summaryrefslogtreecommitdiff
path: root/src/upb_msg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/upb_msg.c')
-rw-r--r--src/upb_msg.c110
1 files changed, 49 insertions, 61 deletions
diff --git a/src/upb_msg.c b/src/upb_msg.c
index dd00610..9f1f00d 100644
--- a/src/upb_msg.c
+++ b/src/upb_msg.c
@@ -97,7 +97,7 @@ 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 (upb_arraylen_t i = 0; i < arr->size; i++) {
+ 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);
}
@@ -117,7 +117,8 @@ void __attribute__((noinline)) upb_array_doresize(
}
void upb_array_resizefortypesize(upb_array *arr, size_t type_size,
- upb_arraylen_t len) {
+ int32_t len) {
+ assert(len >= 0);
if (arr->size < len) upb_array_doresize(arr, type_size, len);
arr->len = len;
}
@@ -312,18 +313,6 @@ static uint64_t upb_msgsink_packfval(uint8_t has_offset, uint8_t has_mask,
return ret;
}
-upb_valueptr __attribute__((noinline)) upb_array_recycleorresize(
- upb_msg *m, upb_msgsink_fval fval, size_t type_size) {
- upb_array **arr = (void*)&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_arraylen_t len = upb_array_len(*arr);
- upb_array_resizefortypesize(*arr, type_size, len+1);
- return _upb_array_getptrforsize(*arr, type_size, len);
-}
-
#define SCALAR_VALUE_CB_PAIR(type, ctype) \
upb_flow_t upb_msgsink_ ## type ## value(void *_m, upb_value _fval, \
upb_value val) { \
@@ -334,25 +323,13 @@ upb_valueptr __attribute__((noinline)) upb_array_recycleorresize(
return UPB_CONTINUE; \
} \
\
- upb_flow_t upb_msgsink_ ## type ## value_r(void *_m, upb_value _fval, \
- upb_value val) { \
- 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)) { \
- if(arr && upb_atomic_only(&arr->refcount)) { \
- m->data[fval.has_offset] |= fval.has_mask; \
- arr->len = 0; \
- } else { \
- goto slow; \
- } \
- } else if (arr->len == arr->size) goto slow; \
+ upb_flow_t upb_msgsink_ ## type ## value_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++); \
- *(ctype*)p._void = upb_value_get ## type(val); \
- return UPB_CONTINUE; \
- slow: \
- p = upb_array_recycleorresize(m, fval, sizeof(ctype)); \
+ arr->len-1); \
*(ctype*)p._void = upb_value_get ## type(val); \
return UPB_CONTINUE; \
} \
@@ -365,6 +342,17 @@ 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;
+ }
+ 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);
@@ -388,38 +376,24 @@ upb_flow_t upb_msgsink_strvalue(void *_m, upb_value _fval, upb_value val) {
return UPB_CONTINUE;
}
-upb_flow_t upb_msgsink_strvalue_r(void *_m, upb_value _fval,
+upb_flow_t upb_msgsink_strvalue_r(void *_a, upb_value _fval,
upb_value val) {
- 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)) {
- if(arr && upb_atomic_only(&arr->refcount)) {
- m->data[fval.has_offset] |= fval.has_mask;
- arr->len = 0;
- } else {
- goto slow;
- }
- } else if (arr->len == arr->size) goto slow;
- ++arr->len;
+ 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));
+ 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));
return UPB_CONTINUE;
-slow:
- p = upb_array_recycleorresize(m, fval, sizeof(void*));
- src = upb_value_getstr(val);
- upb_string_recycle(p.str);
- upb_string_substr(*p.str, src, 0, upb_string_len(src));
- return UPB_CONTINUE;
}
upb_sflow_t upb_msgsink_startsubmsg(void *_m, upb_value _fval) {
- upb_msg *m = _m;
+ 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;
@@ -429,12 +403,20 @@ upb_sflow_t upb_msgsink_startsubmsg(void *_m, upb_value _fval) {
f.label = UPB_LABEL(OPTIONAL); // Just not repeated.
f.type = UPB_TYPE(MESSAGE);
f.byte_offset = fval.val_offset;
- return UPB_CONTINUE_WITH(upb_msg_appendmsg(m, &f, &md));
+
+ 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);
+ }
+ return UPB_CONTINUE_WITH(*subm);
}
-upb_sflow_t upb_msgsink_startsubmsg_r(void *_m, upb_value _fval) {
- upb_msg *m = _m;
+upb_sflow_t upb_msgsink_startsubmsg_r(void *_a, upb_value _fval) {
+ upb_array *a = _a;
+ 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;
@@ -444,7 +426,12 @@ upb_sflow_t upb_msgsink_startsubmsg_r(void *_m, upb_value _fval) {
f.label = UPB_LABEL(REPEATED);
f.type = UPB_TYPE(MESSAGE);
f.byte_offset = fval.val_offset;
- return UPB_CONTINUE_WITH(upb_msg_appendmsg(m, &f, &md));
+
+ 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);
}
INLINE void upb_msg_onfreg(void *c, upb_fhandlers *fh, upb_fielddef *f) {
@@ -459,10 +446,11 @@ INLINE void upb_msg_onfreg(void *c, upb_fhandlers *fh, upb_fielddef *f) {
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): \
- fh->value = upb_isarray(f) ? \
- upb_msgsink_ ## type ## value_r : upb_msgsink_ ## type ## value; \
+ upb_fhandlers_setvalue(fh, upb_isarray(f) ? \
+ upb_msgsink_ ## type ## value_r : upb_msgsink_ ## type ## value); \
break;
switch (f->type) {
CASE(DOUBLE, double)
@@ -484,8 +472,8 @@ case UPB_TYPE(upb_type): \
#undef CASE
case UPB_TYPE(MESSAGE):
case UPB_TYPE(GROUP):
- fh->startsubmsg =
- upb_isarray(f) ? upb_msgsink_startsubmsg_r : upb_msgsink_startsubmsg;
+ upb_fhandlers_setstartsubmsg(fh,
+ upb_isarray(f) ? upb_msgsink_startsubmsg_r : upb_msgsink_startsubmsg);
break;
}
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback