From a38b191e8dd18d838d60da6060fcc2ba23657138 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Tue, 24 Feb 2009 08:32:07 -0800 Subject: Move submessage begin code to handler as well. --- pbstream.c | 84 ++++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 57 insertions(+), 27 deletions(-) (limited to 'pbstream.c') diff --git a/pbstream.c b/pbstream.c index dd91bb8..10f149c 100644 --- a/pbstream.c +++ b/pbstream.c @@ -91,6 +91,9 @@ static pbstream_status_t get_f_uint64_t(char **buf, char *end, uint64_t *val) static int32_t zz_decode_32(uint32_t n) { return (n >> 1) ^ -(int32_t)(n & 1); } static int64_t zz_decode_64(uint64_t n) { return (n >> 1) ^ -(int64_t)(n & 1); } +/* Functions for reading wire values and converting them to values. These + * are generated with macros because they follow a higly consistent pattern. */ + #define CHECK(func) do { \ pbstream_wire_type_t status = func; \ if(status != PBSTREAM_STATUS_OK) return status; \ @@ -106,11 +109,14 @@ static int64_t zz_decode_64(uint64_t n) { return (n >> 1) ^ -(int64_t)(n & 1); } * pbstream_status_t get_TYPE(char **buf, char *end, size_t offset, * pbstream_value *dst) */ #define GET(type, v_or_f, wire_t, val_t, member_name) \ - static pbstream_status_t get_ ## type(char **buf, char *end, size_t offset, \ + static pbstream_status_t get_ ## type(struct pbstream_parse_state *s, \ + char *buf, char *end, \ struct pbstream_value *d) { \ wire_t tmp; \ - CHECK(get_ ## v_or_f ## _ ## wire_t(buf, end, &tmp)); \ - wvtov_ ## type(tmp, &d->v.member_name, offset); \ + char *b = buf; \ + CHECK(get_ ## v_or_f ## _ ## wire_t(&b, end, &tmp)); \ + wvtov_ ## type(tmp, &d->v.member_name, s->offset); \ + s->offset += (b-buf); \ return PBSTREAM_STATUS_OK; \ } @@ -134,22 +140,61 @@ T(SFIXED64, f, uint64_t, int64_t, int64) { *d = (int64_t)s; } T(BOOL, v, uint32_t, bool, _bool) { *d = (bool)s; } T(ENUM, v, uint32_t, int32_t, _enum) { *d = (int32_t)s; } -#define T_DELIMITED(type) \ - T(type, v, uint32_t, struct pbstream_delimited, delimited) { \ +#define WVTOV_DELIMITED(type) \ + WVTOV(type, uint32_t, struct pbstream_delimited) { \ d->offset = offset; \ d->len = s; \ } -T_DELIMITED(STRING); /* We leave UTF-8 validation to the client. */ -T_DELIMITED(BYTES); -T_DELIMITED(MESSAGE); +WVTOV_DELIMITED(STRING); +WVTOV_DELIMITED(BYTES); +WVTOV_DELIMITED(MESSAGE); #undef WVTOV #undef GET #undef T #undef T_DELIMITED +static pbstream_status_t get_STRING(struct pbstream_parse_state *s, + char *buf, char *end, + struct pbstream_value *d) { + uint32_t tmp; + CHECK(get_v_uint32_t(&buf, end, &tmp)); + wvtov_STRING(tmp, &d->v.delimited, s->offset); + s->offset = d->v.delimited.offset + d->v.delimited.len; /* skip string */ + /* we leave UTF-8 validation to the client. */ + return PBSTREAM_STATUS_OK; +} + +static pbstream_status_t get_BYTES(struct pbstream_parse_state *s, + char *buf, char *end, + struct pbstream_value *d) { + uint32_t tmp; + CHECK(get_v_uint32_t(&buf, end, &tmp)); + wvtov_BYTES(tmp, &d->v.delimited, s->offset); + s->offset = d->v.delimited.offset + d->v.delimited.len; /* skip bytes */ + return PBSTREAM_STATUS_OK; +} + +static pbstream_status_t get_MESSAGE(struct pbstream_parse_state *s, + char *buf, char *end, + struct pbstream_value *d) { + /* We're entering a sub-message. */ + uint32_t tmp; + CHECK(get_v_uint32_t(&buf, end, &tmp)); + wvtov_MESSAGE(tmp, &d->v.delimited, s->offset); + s->offset = d->v.delimited.offset; /* skip past only the tag. */ + RESIZE_DYNARRAY(s->stack, s->stack_len+1); + struct pbstream_parse_stack_frame *frame = DYNARRAY_GET_TOP(s->stack); + frame->message_descriptor = d->field_descriptor->d.message; + frame->end_offset = d->v.delimited.offset + d->v.delimited.len; + int num_seen_fields = frame->message_descriptor->num_seen_fields; + INIT_DYNARRAY(frame->seen_fields, num_seen_fields, num_seen_fields); + return PBSTREAM_STATUS_OK; +} + struct pbstream_type_info { pbstream_wire_type_t expected_wire_type; - pbstream_status_t (*get)(char **buf, char *end, size_t offset, + pbstream_status_t (*get)(struct pbstream_parse_state *s, + char *buf, char *end, struct pbstream_value *d); }; static struct pbstream_type_info type_info[] = { @@ -228,7 +273,6 @@ static struct pbstream_field_descriptor *find_field_descriptor( return NULL; } -/* Process actions associated with the end of a [sub-]message. */ pbstream_status_t process_message_end(struct pbstream_parse_state *s) { struct pbstream_parse_stack_frame *frame = DYNARRAY_GET_TOP(s->stack); @@ -283,23 +327,9 @@ pbstream_status_t parse_field(struct pbstream_parse_state *s, frame->seen_fields[fd->seen_field_num] = true; } - if(unlikely(fd->type == PBSTREAM_TYPE_MESSAGE)) { - /* We're entering a sub-message. */ - CHECK(info->get(&b, end, val_offset, val)); - RESIZE_DYNARRAY(s->stack, s->stack_len+1); - struct pbstream_parse_stack_frame *frame = DYNARRAY_GET_TOP(s->stack); - frame->message_descriptor = fd->d.message; - frame->end_offset = val->v.delimited.offset + val->v.delimited.len; - s->offset = wv->v.delimited.offset; /* skip past only the tag. */ - int num_seen_fields = frame->message_descriptor->num_seen_fields; - INIT_DYNARRAY(frame->seen_fields, num_seen_fields, num_seen_fields); - } else { - /* This is a scalar value. */ - *fieldnum = tag.field_number; - val->type = fd->type; - CHECK(info->get(&b, end, val_offset, val)); - s->offset += (b-buf); - } + *fieldnum = tag.field_number; + val->field_descriptor = fd; + CHECK(info->get(s, b, end, val)); return PBSTREAM_STATUS_OK; unknown_value: -- cgit v1.2.3