summaryrefslogtreecommitdiff
path: root/src/upb_msg.c
diff options
context:
space:
mode:
authorJoshua Haberman <jhaberman@gmail.com>2011-06-17 10:34:29 -0700
committerJoshua Haberman <jhaberman@gmail.com>2011-06-17 10:34:29 -0700
commit559e23c796f973a65d05c76e211835b126ee8ac8 (patch)
treeec359628f3b93b88718cc34e5ec86ca6e6c6c1e2 /src/upb_msg.c
parenta503b8859c37906ab5012db163daca43bfe393bb (diff)
Major refactoring: abandon upb_msg, add upb_accessors.
Next on the chopping block is upb_string.
Diffstat (limited to 'src/upb_msg.c')
-rw-r--r--src/upb_msg.c611
1 files changed, 238 insertions, 373 deletions
diff --git a/src/upb_msg.c b/src/upb_msg.c
index 91f1454..b88df32 100644
--- a/src/upb_msg.c
+++ b/src/upb_msg.c
@@ -9,201 +9,23 @@
#include "upb_msg.h"
-static uint32_t upb_round_up_pow2(uint32_t v) {
- // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
- v--;
- v |= v >> 1;
- v |= v >> 2;
- v |= v >> 4;
- v |= v >> 8;
- v |= v >> 16;
- v++;
- return v;
-}
-
-static void upb_elem_free(upb_value v, upb_fielddef *f) {
- switch(f->type) {
- case UPB_TYPE(MESSAGE):
- case UPB_TYPE(GROUP):
- _upb_msg_free(upb_value_getmsg(v), upb_downcast_msgdef(f->def));
- break;
- case UPB_TYPE(STRING):
- case UPB_TYPE(BYTES):
- _upb_string_free(upb_value_getstr(v));
- break;
- default:
- abort();
- }
-}
-
-static void upb_elem_unref(upb_value v, upb_fielddef *f) {
- assert(upb_elem_ismm(f));
- upb_atomic_t *refcount = upb_value_getrefcount(v);
- if (refcount && upb_atomic_unref(refcount))
- upb_elem_free(v, f);
-}
-
-static void upb_field_free(upb_value v, upb_fielddef *f) {
- if (upb_isarray(f)) {
- _upb_array_free(upb_value_getarr(v), f);
- } else {
- upb_elem_free(v, f);
- }
-}
-
-static void upb_field_unref(upb_value v, upb_fielddef *f) {
- assert(upb_field_ismm(f));
- upb_atomic_t *refcount = upb_value_getrefcount(v);
- if (refcount && upb_atomic_unref(refcount))
- upb_field_free(v, f);
-}
-
-
-/* upb_array ******************************************************************/
-
-upb_array *upb_array_new(void) {
- upb_array *arr = malloc(sizeof(*arr));
- upb_atomic_init(&arr->refcount, 1);
- arr->size = 0;
- arr->len = 0;
- arr->ptr = NULL;
- return arr;
-}
-
-void __attribute__((noinline)) upb_array_dorecycle(upb_array **_arr) {
- upb_array *arr = *_arr;
- if(arr && upb_atomic_only(&arr->refcount)) {
- arr->len = 0;
- } else {
- if (arr) {
- bool was_lastref = upb_atomic_unref(&arr->refcount);
- (void)was_lastref;
- assert(!was_lastref); // If it was, we would have just recycled.
- }
- *_arr = upb_array_new();
- }
-}
-
-void upb_array_recycle(upb_array **_arr) {
- upb_array *arr = *_arr;
- if(arr && upb_atomic_only(&arr->refcount)) {
- arr->len = 0;
- } else {
- upb_array_dorecycle(_arr);
- }
-}
-
-void _upb_array_free(upb_array *arr, upb_fielddef *f) {
- if (upb_elem_ismm(f)) {
- // Need to release refs on sub-objects.
- upb_valuetype_t type = upb_elem_valuetype(f);
- for (int32_t i = 0; i < arr->size; i++) {
- upb_valueptr p = _upb_array_getptr(arr, f, i);
- upb_elem_unref(upb_value_read(p, type), f);
- }
- }
- free(arr->ptr);
- free(arr);
-}
-
-void __attribute__((noinline)) upb_array_doresize(
- upb_array *arr, size_t type_size, upb_arraylen_t len) {
- upb_arraylen_t old_size = arr->size;
- size_t new_size = upb_round_up_pow2(len);
- arr->ptr = realloc(arr->ptr, new_size * type_size);
- arr->size = new_size;
- memset(arr->ptr + (old_size * type_size), 0,
- (new_size - old_size) * type_size);
-}
-
-void upb_array_resizefortypesize(upb_array *arr, size_t type_size,
- int32_t len) {
- assert(len >= 0);
- if (arr->size < len) upb_array_doresize(arr, type_size, len);
- arr->len = len;
-}
-
-void upb_array_resize(upb_array *arr, upb_fielddef *f, upb_arraylen_t len) {
- upb_array_resizefortypesize(arr, upb_types[f->type].size, len);
-}
-
-
-/* upb_msg ********************************************************************/
-
-upb_msg *upb_msg_new(upb_msgdef *md) {
- upb_msg *msg = malloc(md->size);
- // Clear all set bits and cached pointers.
- memset(msg, 0, md->size);
- upb_atomic_init(&msg->refcount, 1);
- return msg;
-}
-
-void _upb_msg_free(upb_msg *msg, upb_msgdef *md) {
- // Need to release refs on all sub-objects.
- upb_msg_iter i;
- for(i = upb_msg_begin(md); !upb_msg_done(i); i = upb_msg_next(md, i)) {
- upb_fielddef *f = upb_msg_iter_field(i);
- upb_valueptr p = _upb_msg_getptr(msg, f);
- upb_valuetype_t type = upb_field_valuetype(f);
- if (upb_field_ismm(f)) upb_field_unref(upb_value_read(p, type), f);
- }
- free(msg);
-}
-
-void upb_msg_recycle(upb_msg **_msg, upb_msgdef *msgdef) {
- upb_msg *msg = *_msg;
- if(msg && upb_atomic_only(&msg->refcount)) {
- upb_msg_clear(msg, msgdef);
- } else {
- upb_msg_unref(msg, msgdef);
- if (msg) {
- bool was_lastref = upb_atomic_unref(&msg->refcount);
- (void)was_lastref;
- assert(!was_lastref);
- }
- *_msg = upb_msg_new(msgdef);
- }
-}
-
-INLINE void upb_msg_sethas(upb_msg *msg, upb_fielddef *f) {
- msg->data[f->set_bit_offset] |= f->set_bit_mask;
-}
-
-void upb_msg_set(upb_msg *msg, upb_fielddef *f, upb_value val) {
- assert(val.type == upb_types[upb_field_valuetype(f)].inmemory_type);
- upb_valueptr ptr = _upb_msg_getptr(msg, f);
- if (upb_field_ismm(f)) {
- // Unref any previous value we may have had there.
- upb_value oldval = upb_value_read(ptr, upb_field_valuetype(f));
- upb_field_unref(oldval, f);
-
- // Ref the new value.
- upb_atomic_t *refcount = upb_value_getrefcount(val);
- if (refcount) upb_atomic_ref(refcount);
- }
- upb_msg_sethas(msg, f);
- return upb_value_write(ptr, val, upb_field_valuetype(f));
-}
-
-upb_value upb_msg_get(upb_msg *msg, upb_fielddef *f) {
- if (!upb_msg_has(msg, f)) {
- upb_value val = f->default_value;
- if (upb_issubmsg(f)) {
- // TODO: handle arrays also, which must be treated similarly.
- upb_msgdef *md = upb_downcast_msgdef(f->def);
- upb_msg *m = upb_msg_new(md);
- // Copy all set bits and values, except the refcount.
- memcpy(m , upb_value_getmsg(val), md->size);
- upb_atomic_init(&m->refcount, 0); // The msg will take a ref.
- upb_value_setmsg(&val, m);
- }
- upb_msg_set(msg, f, val);
- return val;
- } else {
- return upb_value_read(_upb_msg_getptr(msg, f), upb_field_valuetype(f));
+void upb_msg_clear(void *msg, upb_msgdef *md) {
+ memset(msg, 0, md->hasbit_bytes);
+ // TODO: set primitive fields to defaults?
+}
+
+void *upb_stdarray_append(upb_stdarray *a, size_t type_size) {
+ assert(a->len <= a->size);
+ if (a->len == a->size) {
+ size_t old_size = a->size;
+ a->size = old_size == 0 ? 8 : (old_size * 2);
+ a->ptr = realloc(a->ptr, a->size * type_size);
+ memset(&a->ptr[old_size * type_size], 0, (a->size - old_size) * type_size);
}
+ return &a->ptr[a->len++ * type_size];
}
+#if 0
static upb_flow_t upb_msg_dispatch(upb_msg *msg, upb_msgdef *md,
upb_dispatcher *d);
@@ -253,110 +75,64 @@ void upb_msg_runhandlers(upb_msg *msg, upb_msgdef *md, upb_handlers *h,
upb_dispatcher_uninit(&d);
}
+#endif
-static upb_valueptr upb_msg_getappendptr(upb_msg *msg, upb_fielddef *f) {
- upb_valueptr p = _upb_msg_getptr(msg, f);
- if (upb_isarray(f)) {
- // Create/recycle/resize the array if necessary, and find a pointer to
- // a newly-appended element.
- if (!upb_msg_has(msg, f)) {
- upb_array_recycle(p.arr);
- upb_msg_sethas(msg, f);
- }
- assert(*p.arr != NULL);
- upb_arraylen_t oldlen = upb_array_len(*p.arr);
- upb_array_resize(*p.arr, f, oldlen + 1);
- p = _upb_array_getptr(*p.arr, f, oldlen);
- }
- return p;
-}
-
-upb_msg *upb_msg_appendmsg(upb_msg *msg, upb_fielddef *f, upb_msgdef *msgdef) {
- upb_valueptr p = upb_msg_getappendptr(msg, f);
- if (upb_isarray(f) || !upb_msg_has(msg, f)) {
- upb_msg_recycle(p.msg, msgdef);
- upb_msg_sethas(msg, f);
- }
- return *p.msg;
-}
-
-
-/* upb_msg handlers ***********************************************************/
+/* Standard writers. **********************************************************/
-#if UPB_MAX_FIELDS > 2048
-#error "We're using an 8-bit integer to store a has_offset."
-#endif
-typedef struct {
- uint8_t has_offset;
- uint8_t has_mask;
- uint16_t val_offset;
- uint16_t msg_size;
- uint8_t set_flags_bytes;
- uint8_t padding;
-} upb_msgsink_fval;
-
-static upb_msgsink_fval upb_msgsink_unpackfval(upb_value fval) {
- assert(sizeof(upb_msgsink_fval) == 8);
- upb_msgsink_fval ret;
- uint64_t fval_u64 = upb_value_getuint64(fval);
- memcpy(&ret, &fval_u64, 8);
- return ret;
+void upb_stdmsg_sethas(void *_m, upb_value fval) {
+ char *m = _m;
+ upb_fielddef *f = upb_value_getfielddef(fval);
+ if (f->hasbit >= 0) m[f->hasbit / 8] |= (1 << (f->hasbit % 8));
}
-static uint64_t upb_msgsink_packfval(uint8_t has_offset, uint8_t has_mask,
- uint16_t val_offset, uint16_t msg_size,
- uint8_t set_flags_bytes) {
- upb_msgsink_fval fval = {
- has_offset, has_mask, val_offset, msg_size, set_flags_bytes, 0};
- uint64_t ret = 0;
- memcpy(&ret, &fval, sizeof(fval));
- return ret;
+bool upb_stdmsg_has(void *_m, upb_value fval) {
+ char *m = _m;
+ upb_fielddef *f = upb_value_getfielddef(fval);
+ return f->hasbit < 0 || (m[f->hasbit / 8] & (1 << (f->hasbit % 8)));
}
-#define SCALAR_VALUE_CB_PAIR(type, ctype) \
- upb_flow_t upb_msgsink_ ## type ## value(void *_m, upb_value _fval, \
- upb_value val) { \
- upb_msg *m = _m; \
- upb_msgsink_fval fval = upb_msgsink_unpackfval(_fval); \
- m->data[fval.has_offset] |= fval.has_mask; \
- *(ctype*)&m->data[fval.val_offset] = upb_value_get ## type(val); \
+#define UPB_ACCESSORS(type, ctype) \
+ upb_flow_t upb_stdmsg_set ## type (void *_m, upb_value fval, \
+ upb_value val) { \
+ upb_fielddef *f = upb_value_getfielddef(fval); \
+ uint8_t *m = _m; \
+ upb_stdmsg_sethas(_m, fval); \
+ *(ctype*)&m[f->offset] = upb_value_get ## type(val); \
return UPB_CONTINUE; \
} \
\
- upb_flow_t upb_msgsink_ ## type ## value_r(void *_a, upb_value _fval, \
- upb_value val) { \
+ upb_flow_t upb_stdmsg_set ## type ## _r(void *a, upb_value _fval, \
+ upb_value val) { \
(void)_fval; \
- upb_array *arr = _a; \
- upb_array_resizefortypesize(arr, sizeof(ctype), arr->len+1); \
- upb_valueptr p = _upb_array_getptrforsize(arr, sizeof(ctype), \
- arr->len-1); \
- *(ctype*)p._void = upb_value_get ## type(val); \
+ ctype *p = upb_stdarray_append((upb_stdarray*)a, sizeof(ctype)); \
+ *p = upb_value_get ## type(val); \
return UPB_CONTINUE; \
} \
-
-SCALAR_VALUE_CB_PAIR(double, double)
-SCALAR_VALUE_CB_PAIR(float, float)
-SCALAR_VALUE_CB_PAIR(int32, int32_t)
-SCALAR_VALUE_CB_PAIR(int64, int64_t)
-SCALAR_VALUE_CB_PAIR(uint32, uint32_t)
-SCALAR_VALUE_CB_PAIR(uint64, uint64_t)
-SCALAR_VALUE_CB_PAIR(bool, bool)
-
-upb_sflow_t upb_msgsink_startseq(void *_m, upb_value _fval) {
- upb_msg *m = _m;
- upb_msgsink_fval fval = upb_msgsink_unpackfval(_fval);
- upb_array **arr = (upb_array**)&m->data[fval.val_offset];
- if (!(m->data[fval.has_offset] & fval.has_mask)) {
- upb_array_recycle(arr);
- m->data[fval.has_offset] |= fval.has_mask;
+ \
+ upb_value upb_stdmsg_get ## type(void *_m, upb_value fval) { \
+ uint8_t *m = _m; \
+ upb_fielddef *f = upb_value_getfielddef(fval); \
+ upb_value ret; \
+ upb_value_set ## type(&ret, *(ctype*)&m[f->offset]); \
+ return ret; \
+ } \
+ upb_value upb_stdmsg_seqget ## type(void *i) { \
+ upb_value val; \
+ upb_value_set ## type(&val, *(ctype*)i); \
+ return val; \
}
- return UPB_CONTINUE_WITH(*arr);
-}
-upb_flow_t upb_msgsink_strvalue(void *_m, upb_value _fval, upb_value val) {
- upb_msg *m = _m;
- upb_msgsink_fval fval = upb_msgsink_unpackfval(_fval);
- m->data[fval.has_offset] |= fval.has_mask;
+UPB_ACCESSORS(double, double)
+UPB_ACCESSORS(float, float)
+UPB_ACCESSORS(int32, int32_t)
+UPB_ACCESSORS(int64, int64_t)
+UPB_ACCESSORS(uint32, uint32_t)
+UPB_ACCESSORS(uint64, uint64_t)
+UPB_ACCESSORS(bool, bool)
+UPB_ACCESSORS(ptr, void*)
+#undef UPB_ACCESSORS
+
+static void _upb_stdmsg_setstr(void *_dst, upb_value _src) {
// We do:
// - upb_string_recycle(), upb_string_substr() instead of
// - upb_string_unref(), upb_string_getref()
@@ -369,115 +145,204 @@ upb_flow_t upb_msgsink_strvalue(void *_m, upb_value _fval, upb_value val) {
// allocate string objects whereas a upb_string_getref could have avoided
// those allocations completely; if this is an issue, we could make it an
// option of the upb_msgsink which behavior is desired.
- upb_string *src = upb_value_getstr(val);
- upb_string **dst = (void*)&m->data[fval.val_offset];
+ upb_string **dst = _dst;
+ upb_string *src = upb_value_getstr(_src);
upb_string_recycle(dst);
upb_string_substr(*dst, src, 0, upb_string_len(src));
+}
+
+upb_flow_t upb_stdmsg_setstr(void *_m, upb_value fval, upb_value val) {
+ char *m = _m;
+ upb_fielddef *f = upb_value_getfielddef(fval);
+ upb_stdmsg_sethas(_m, fval);
+ _upb_stdmsg_setstr(&m[f->offset], val);
return UPB_CONTINUE;
}
-upb_flow_t upb_msgsink_strvalue_r(void *_a, upb_value _fval,
- upb_value val) {
- upb_array *arr = _a;
- (void)_fval;
- upb_array_resizefortypesize(arr, sizeof(void*), arr->len+1);
- upb_valueptr p = _upb_array_getptrforsize(arr, sizeof(void*),
- upb_array_len(arr)-1);
- upb_string *src = upb_value_getstr(val);
- upb_string_recycle(p.str);
- upb_string_substr(*p.str, src, 0, upb_string_len(src));
+upb_flow_t upb_stdmsg_setstr_r(void *a, upb_value fval, upb_value val) {
+ (void)fval;
+ _upb_stdmsg_setstr(upb_stdarray_append((upb_stdarray*)a, sizeof(void*)), val);
return UPB_CONTINUE;
}
+upb_value upb_stdmsg_getstr(void *m, upb_value fval) {
+ upb_value val = upb_stdmsg_getptr(m, fval);
+ upb_value_setstr(&val, upb_value_getptr(val));
+ return val;
+}
+
+upb_value upb_stdmsg_seqgetstr(void *i) {
+ upb_value val = upb_stdmsg_seqgetptr(i);
+ upb_value_setstr(&val, upb_value_getptr(val));
+ return val;
+}
+
+void *upb_stdmsg_new(upb_msgdef *md) {
+ void *m = malloc(md->size);
+ memset(m, 0, md->size);
+ upb_msg_clear(m, md);
+ return m;
+}
-upb_sflow_t upb_msgsink_startsubmsg(void *_m, upb_value _fval) {
- upb_msg *msg = _m;
- upb_msgsink_fval fval = upb_msgsink_unpackfval(_fval);
-
- upb_msgdef md;
- md.size = fval.msg_size;
- md.set_flags_bytes = fval.set_flags_bytes;
- upb_fielddef f;
- f.set_bit_mask = fval.has_mask;
- f.set_bit_offset = fval.has_offset;
- f.label = UPB_LABEL(OPTIONAL); // Just not repeated.
- f.type = UPB_TYPE(MESSAGE);
- f.byte_offset = fval.val_offset;
-
- upb_msg **subm = _upb_msg_getptr(msg, &f).msg;
- if (!upb_msg_has(msg, &f)) {
- upb_msg_recycle(subm, &md);
- upb_msg_sethas(msg, &f);
+void upb_stdseq_free(void *s, upb_fielddef *f) {
+ upb_stdarray *a = s;
+ if (upb_issubmsg(f) || upb_isstring(f)) {
+ void **p = (void**)a->ptr;
+ for (int i = 0; i < a->size; i++) {
+ if (upb_issubmsg(f)) {
+ upb_stdmsg_free(p[i], upb_downcast_msgdef(f->def));
+ } else {
+ upb_string_unref(p[i]);
+ }
+ }
+ }
+ free(a->ptr);
+ free(a);
+}
+
+void upb_stdmsg_free(void *m, upb_msgdef *md) {
+ if (m == NULL) return;
+ upb_msg_iter i;
+ for(i = upb_msg_begin(md); !upb_msg_done(i); i = upb_msg_next(md, i)) {
+ upb_fielddef *f = upb_msg_iter_field(i);
+ if (!upb_isseq(f) && !upb_issubmsg(f) && !upb_isstring(f)) continue;
+ void *subp = upb_value_getptr(upb_stdmsg_getptr(m, f->fval));
+ if (subp == NULL) continue;
+ if (upb_isseq(f)) {
+ upb_stdseq_free(subp, f);
+ } else if (upb_issubmsg(f)) {
+ upb_stdmsg_free(subp, upb_downcast_msgdef(f->def));
+ } else {
+ upb_string_unref(subp);
+ }
+ }
+ free(m);
+}
+
+upb_sflow_t upb_stdmsg_startseq(void *_m, upb_value fval) {
+ char *m = _m;
+ upb_fielddef *f = upb_value_getfielddef(fval);
+ upb_stdarray **arr = (void*)&m[f->offset];
+ if (!upb_stdmsg_has(_m, fval)) {
+ if (!*arr) {
+ *arr = malloc(sizeof(**arr));
+ (*arr)->size = 0;
+ (*arr)->ptr = NULL;
+ }
+ (*arr)->len = 0;
+ upb_stdmsg_sethas(m, fval);
+ }
+ return UPB_CONTINUE_WITH(*arr);
+}
+
+void upb_stdmsg_recycle(void **m, upb_msgdef *md) {
+ if (*m)
+ upb_msg_clear(*m, md);
+ else
+ *m = upb_stdmsg_new(md);
+}
+
+upb_sflow_t upb_stdmsg_startsubmsg(void *_m, upb_value fval) {
+ char *m = _m;
+ upb_fielddef *f = upb_value_getfielddef(fval);
+ void **subm = (void*)&m[f->offset];
+ if (!upb_stdmsg_has(m, fval)) {
+ upb_stdmsg_recycle(subm, upb_downcast_msgdef(f->def));
+ upb_stdmsg_sethas(m, fval);
}
return UPB_CONTINUE_WITH(*subm);
}
-upb_sflow_t upb_msgsink_startsubmsg_r(void *_a, upb_value _fval) {
- upb_array *a = _a;
+upb_sflow_t upb_stdmsg_startsubmsg_r(void *a, upb_value fval) {
assert(a != NULL);
- upb_msgsink_fval fval = upb_msgsink_unpackfval(_fval);
-
- upb_msgdef md;
- md.size = fval.msg_size;
- md.set_flags_bytes = fval.set_flags_bytes;
- upb_fielddef f;
- f.set_bit_mask = fval.has_mask;
- f.set_bit_offset = fval.has_offset;
- f.label = UPB_LABEL(REPEATED);
- f.type = UPB_TYPE(MESSAGE);
- f.byte_offset = fval.val_offset;
-
- upb_arraylen_t oldlen = upb_array_len(a);
- upb_array_resize(a, &f, oldlen + 1);
- upb_valueptr p = _upb_array_getptr(a, &f, oldlen);
- upb_msg_recycle(p.msg, &md);
- return UPB_CONTINUE_WITH(*p.msg);
+ upb_fielddef *f = upb_value_getfielddef(fval);
+ void **subm = upb_stdarray_append((upb_stdarray*)a, sizeof(void*));
+ upb_stdmsg_recycle(subm, upb_downcast_msgdef(f->def));
+ return UPB_CONTINUE_WITH(*subm);
}
-INLINE void upb_msg_onfreg(void *c, upb_fhandlers *fh, upb_fielddef *f) {
- (void)c;
- uint16_t msg_size = 0;
- uint8_t set_flags_bytes = 0;
- if (upb_issubmsg(f)) {
- upb_msgdef *md = upb_downcast_msgdef(f->def);
- msg_size = md->size;
- set_flags_bytes = md->set_flags_bytes;
+void *upb_stdmsg_seqbegin(void *_a) {
+ upb_stdarray *a = _a;
+ return a->len > 0 ? a->ptr : NULL;
+}
+
+#define NEXTFUNC(size) \
+ void *upb_stdmsg_ ## size ## byte_seqnext(void *_a, void *iter) { \
+ upb_stdarray *a = _a; \
+ void *next = (char*)iter + size; \
+ return (char*)next < (char*)a->ptr + (a->len * size) ? next : NULL; \
}
- upb_value_setuint64(&fh->fval,
- upb_msgsink_packfval(f->set_bit_offset, f->set_bit_mask,
- f->byte_offset, msg_size, set_flags_bytes));
- if (fh->repeated) upb_fhandlers_setstartseq(fh, upb_msgsink_startseq);
-#define CASE(upb_type, type) \
-case UPB_TYPE(upb_type): \
- upb_fhandlers_setvalue(fh, upb_isarray(f) ? \
- upb_msgsink_ ## type ## value_r : upb_msgsink_ ## type ## value); \
- break;
- switch (f->type) {
- CASE(DOUBLE, double)
- CASE(FLOAT, float)
- CASE(INT32, int32)
- CASE(INT64, int64)
- CASE(UINT32, uint32)
- CASE(UINT64, uint64)
- CASE(SINT32, int32)
- CASE(SINT64, int64)
- CASE(FIXED32, uint32)
- CASE(FIXED64, uint64)
- CASE(SFIXED32, int32)
- CASE(SFIXED64, int64)
- CASE(BOOL, bool)
- CASE(ENUM, int32)
- CASE(STRING, str)
- CASE(BYTES, str)
-#undef CASE
- case UPB_TYPE(MESSAGE):
- case UPB_TYPE(GROUP):
- upb_fhandlers_setstartsubmsg(fh,
- upb_isarray(f) ? upb_msgsink_startsubmsg_r : upb_msgsink_startsubmsg);
- break;
+
+NEXTFUNC(8)
+NEXTFUNC(4)
+NEXTFUNC(1)
+
+#define STDMSG(type) { static upb_accessor_vtbl vtbl = {NULL, &upb_stdmsg_startsubmsg, \
+ &upb_stdmsg_set ## type, &upb_stdmsg_has, &upb_stdmsg_get ## type, \
+ NULL, NULL, NULL}; return &vtbl; }
+#define STDMSG_R(type, size) { static upb_accessor_vtbl vtbl = { \
+ &upb_stdmsg_startseq, &upb_stdmsg_startsubmsg_r, &upb_stdmsg_set ## type ## _r, \
+ &upb_stdmsg_has, &upb_stdmsg_getptr, &upb_stdmsg_seqbegin, \
+ &upb_stdmsg_ ## size ## byte_seqnext, &upb_stdmsg_seqget ## type}; \
+ return &vtbl; }
+
+upb_accessor_vtbl *upb_stdmsg_accessor(upb_fielddef *f) {
+ if (upb_isseq(f)) {
+ switch (f->type) {
+ case UPB_TYPE(DOUBLE): STDMSG_R(double, 8)
+ case UPB_TYPE(FLOAT): STDMSG_R(float, 4)
+ case UPB_TYPE(UINT64):
+ case UPB_TYPE(FIXED64): STDMSG_R(uint64, 8)
+ case UPB_TYPE(INT64):
+ case UPB_TYPE(SFIXED64):
+ case UPB_TYPE(SINT64): STDMSG_R(int64, 8)
+ case UPB_TYPE(INT32):
+ case UPB_TYPE(SINT32):
+ case UPB_TYPE(ENUM):
+ case UPB_TYPE(SFIXED32): STDMSG_R(int32, 4)
+ case UPB_TYPE(UINT32):
+ case UPB_TYPE(FIXED32): STDMSG_R(uint32, 4)
+ case UPB_TYPE(BOOL): STDMSG_R(bool, 1)
+ case UPB_TYPE(STRING):
+ case UPB_TYPE(BYTES):
+ case UPB_TYPE(GROUP):
+ case UPB_TYPE(MESSAGE): STDMSG_R(str, 8) // TODO: 32-bit
+ }
+ } else {
+ switch (f->type) {
+ case UPB_TYPE(DOUBLE): STDMSG(double)
+ case UPB_TYPE(FLOAT): STDMSG(float)
+ case UPB_TYPE(UINT64):
+ case UPB_TYPE(FIXED64): STDMSG(uint64)
+ case UPB_TYPE(INT64):
+ case UPB_TYPE(SFIXED64):
+ case UPB_TYPE(SINT64): STDMSG(int64)
+ case UPB_TYPE(INT32):
+ case UPB_TYPE(SINT32):
+ case UPB_TYPE(ENUM):
+ case UPB_TYPE(SFIXED32): STDMSG(int32)
+ case UPB_TYPE(UINT32):
+ case UPB_TYPE(FIXED32): STDMSG(uint32)
+ case UPB_TYPE(BOOL): STDMSG(bool)
+ case UPB_TYPE(STRING):
+ case UPB_TYPE(BYTES):
+ case UPB_TYPE(GROUP):
+ case UPB_TYPE(MESSAGE): STDMSG(str)
+ }
+ }
+ return NULL;
+}
+
+static void upb_accessors_onfreg(void *c, upb_fhandlers *fh, upb_fielddef *f) {
+ (void)c;
+ if (f->accessor) {
+ upb_fhandlers_setstartseq(fh, f->accessor->appendseq);
+ upb_fhandlers_setvalue(fh, f->accessor->set);
+ upb_fhandlers_setstartsubmsg(fh, f->accessor->appendsubmsg);
+ upb_fhandlers_setfval(fh, f->fval);
}
}
-upb_mhandlers *upb_msg_reghandlers(upb_handlers *h, upb_msgdef *m) {
- return upb_handlers_regmsgdef(h, m, NULL, &upb_msg_onfreg, NULL);
+upb_mhandlers *upb_accessors_reghandlers(upb_handlers *h, upb_msgdef *m) {
+ return upb_handlers_regmsgdef(h, m, NULL, &upb_accessors_onfreg, NULL);
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback