summaryrefslogtreecommitdiff
path: root/src/upb_parse.c
diff options
context:
space:
mode:
authorJoshua Haberman <joshua@reverberate.org>2010-01-08 18:42:24 -0800
committerJoshua Haberman <joshua@reverberate.org>2010-01-08 18:42:24 -0800
commit527c0945000315ed8589436d2807bd5f8ad7a543 (patch)
tree1b1b214f99b294b8d47248a542e41694fbc8a671 /src/upb_parse.c
parent5864888c6e7424af70d84802b55879f406d2d7b2 (diff)
Reduced the complexity of the cbparser interface.
Diffstat (limited to 'src/upb_parse.c')
-rw-r--r--src/upb_parse.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/src/upb_parse.c b/src/upb_parse.c
index c4790c6..101792a 100644
--- a/src/upb_parse.c
+++ b/src/upb_parse.c
@@ -432,17 +432,19 @@ size_t upb_cbparser_parse(struct upb_cbparser *p, upb_strptr str,
bool keep_going = true;
// Make local copies so optimizer knows they won't change.
- upb_str_cb str_cb = p->str_cb;
- upb_value_cb value_cb = p->value_cb;
- void *udata = p->udata;
+ const upb_str_cb str_cb = p->str_cb;
+ const upb_value_cb value_cb = p->value_cb;
+ void *const udata = p->udata;
// We need to check the status of operations that can fail, but we do so as
// late as possible to avoid introducing branches that have to wait on
- // (status->code) which must be loaded from memory.
+ // (status->code) which must be loaded from memory. We must always check
+ // before calling a user callback.
#define CHECK_STATUS() do { if(!upb_ok(status)) goto err; } while(0)
- // Main loop: parse a tag, find the appropriate fielddef.
+ // Main loop: executed once per tag/field pair.
while(keep_going && buf < end) {
+ // Parse/handle tag.
struct upb_tag tag;
buf = parse_tag(buf, end, &tag, status);
if(tag.wire_type == UPB_WIRE_TYPE_END_GROUP) {
@@ -459,20 +461,23 @@ size_t upb_cbparser_parse(struct upb_cbparser *p, upb_strptr str,
continue;
}
+ // Look up field by tag number.
struct upb_fielddef *f = upb_msg_itof(msgdef, tag.field_number);
+
+ // Parse/handle field.
if(tag.wire_type == UPB_WIRE_TYPE_DELIMITED) {
int32_t delim_len;
buf = upb_get_INT32(buf, end, &delim_len, status);
- CHECK_STATUS();
+ CHECK_STATUS(); // Checking parse_tag() and upb_get_INT32().
const uint8_t *delim_end = buf + delim_len;
if(f && f->type == UPB_TYPE(MESSAGE)) {
submsg_end = push(p, start, delim_end - start, f, status);
msgdef = p->top->msgdef;
} else {
if(f && upb_isstringtype(f->type)) {
- size_t avail_len = UPB_MIN(delim_end, end) - buf;
+ int32_t str_start = buf - start;
keep_going =
- str_cb(udata, msgdef, f, buf, avail_len, delim_end - buf);
+ str_cb(udata, f, str, str_start, str_start + delim_len);
} // else { TODO: packed arrays }
// If field was not found, it is skipped silently.
buf = delim_end; // Could be >end.
@@ -487,7 +492,8 @@ size_t upb_cbparser_parse(struct upb_cbparser *p, upb_strptr str,
union upb_value val;
buf = upb_parse_value(buf, end, f->type, upb_value_addrof(&val),
status);
- keep_going = value_cb(udata, msgdef, f, val);
+ CHECK_STATUS(); // Checking upb_parse_value().
+ keep_going = value_cb(udata, f, val);
}
}
CHECK_STATUS();
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback