diff options
author | Joshua Haberman <joshua@reverberate.org> | 2009-07-21 01:44:13 -0700 |
---|---|---|
committer | Joshua Haberman <joshua@reverberate.org> | 2009-07-21 01:44:13 -0700 |
commit | babefc3c66552db4a0b0302324f1280b0faacd82 (patch) | |
tree | b0864240621ef3ea3e59949fc73ecc0f7cd34a31 | |
parent | b2a39e50d829a288243dc590997910a1a87f626e (diff) |
Bugfixes to parser.
-rw-r--r-- | src/upb_msg.c | 21 | ||||
-rw-r--r-- | src/upb_msg.h | 13 | ||||
-rw-r--r-- | src/upb_parse.c | 32 | ||||
-rw-r--r-- | src/upb_parse.h | 19 |
4 files changed, 46 insertions, 39 deletions
diff --git a/src/upb_msg.c b/src/upb_msg.c index deefb27..a923bb8 100644 --- a/src/upb_msg.c +++ b/src/upb_msg.c @@ -1,6 +1,7 @@ /* * upb - a minimalist implementation of protocol buffers. * + * Copyright (c) 2009 Joshua Haberman. See LICENSE for details. */ #include <inttypes.h> @@ -281,10 +282,13 @@ static void *value_cb(void *udata, void *buf, void *end, struct upb_msg_parse_state *s = udata; struct upb_msg_field *f = user_field_desc; union upb_value_ptr p = get_value_ptr(s->top->data, f); - return upb_parse_value(buf, end, f->type, p, errjmp); + void *ret = upb_parse_value(buf, end, f->type, p, errjmp); + google_protobuf_FieldDescriptorProto *fd = upb_msg_field_descriptor(f, s->top->m); + //upb_text_printfield(&s->p, *fd->name, f->type, p, stdout); + return ret; } -static upb_status_t str_cb(void *udata, struct upb_string *str, +static void str_cb(void *udata, struct upb_string *str, void *user_field_desc) { struct upb_msg_parse_state *s = udata; @@ -297,7 +301,8 @@ static upb_status_t str_cb(void *udata, struct upb_string *str, upb_msg_reuse_str(p.str, str->byte_len); upb_strcpy(*p.str, str); } - return UPB_STATUS_OK; + google_protobuf_FieldDescriptorProto *fd = upb_msg_field_descriptor(f, s->top->m); + //upb_text_printfield(&s->p, *fd->name, f->type, p, stdout); } static void submsg_start_cb(void *udata, void *user_field_desc) @@ -311,12 +316,21 @@ static void submsg_start_cb(void *udata, void *user_field_desc) s->top->m = f->ref.msg; s->top->data = *p.msg; if(!s->merge) upb_msg_clear(s->top->data, s->top->m); + //upb_text_push(&s->p, *s->top->m->descriptor->name, stdout); +} + +static void submsg_end_cb(void *udata) +{ + struct upb_msg_parse_state *s = udata; + s->top--; + //upb_text_pop(&s->p, stdout); } void upb_msg_parse_reset(struct upb_msg_parse_state *s, void *msg, struct upb_msg *m, bool merge, bool byref) { upb_parse_reset(&s->s, s); + //upb_text_printer_init(&s->p, false); s->merge = merge; s->byref = byref; if(!merge && msg == NULL) msg = upb_msgdata_new(m); @@ -328,6 +342,7 @@ void upb_msg_parse_reset(struct upb_msg_parse_state *s, void *msg, s->s.value_cb = value_cb; s->s.str_cb = str_cb; s->s.submsg_start_cb = submsg_start_cb; + s->s.submsg_end_cb = submsg_end_cb; } void upb_msg_parse_init(struct upb_msg_parse_state *s, void *msg, diff --git a/src/upb_msg.h b/src/upb_msg.h index 0cb3cd5..9eaf6c2 100644 --- a/src/upb_msg.h +++ b/src/upb_msg.h @@ -101,7 +101,6 @@ #include "upb.h" #include "upb_table.h" #include "upb_parse.h" -#include "descriptor.h" #ifdef __cplusplus extern "C" { @@ -195,16 +194,6 @@ INLINE struct upb_msg_field *upb_msg_fieldbyname(struct upb_msg *m, return e ? &e->f : NULL; } -INLINE bool upb_issubmsgtype(upb_field_type_t type) { - return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP || - type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE; -} - -INLINE bool upb_isstringtype(upb_field_type_t type) { - return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING || - type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES; -} - INLINE bool upb_issubmsg(struct upb_msg_field *f) { return upb_issubmsgtype(f->type); } @@ -311,12 +300,14 @@ struct upb_msg_parse_frame { void *data; }; +//#include "upb_text.h" struct upb_msg_parse_state { struct upb_parse_state s; bool merge; bool byref; struct upb_msg *m; struct upb_msg_parse_frame stack[UPB_MAX_NESTING], *top; + //struct upb_text_printer p; }; /* Initializes/frees a message parser. The parser will write the data to the diff --git a/src/upb_parse.c b/src/upb_parse.c index fa37a56..3bbbf4a 100644 --- a/src/upb_parse.c +++ b/src/upb_parse.c @@ -10,7 +10,6 @@ #include <stdlib.h> /* May want to move this to upb.c if enough other things warrant it. */ -#include "descriptor.h" #define alignof(t) offsetof(struct { char c; t x; }, x) struct upb_type_info upb_type_info[] = { [GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_DOUBLE] = {alignof(double), sizeof(double), UPB_WIRE_TYPE_64BIT}, @@ -258,6 +257,7 @@ void upb_parse_reset(struct upb_parse_state *state, void *udata) /* The top-level message is not delimited (we can keep receiving data for * it indefinitely), so we treat it like a group. */ *state->top = 0; + state->completed_offset = 0; state->udata = udata; } @@ -272,34 +272,23 @@ void upb_parse_free(struct upb_parse_state *state) free(state->stack); } -static void *pop_stack_frame(struct upb_parse_state *s, - uint8_t *buf, uint8_t *submsg_end) +static void *pop_stack_frame(struct upb_parse_state *s, uint8_t *buf) { if(s->submsg_end_cb) s->submsg_end_cb(s->udata); - uint32_t final_submsg_len = *s->top - (buf - submsg_end); s->top--; - *s->top -= final_submsg_len; - return (char*)buf + (*s->top > 0 ? *s->top : 0); + return (char*)buf + (*s->top > 0 ? (*s->top - s->completed_offset) : 0); } /* Returns the next end offset. */ static void *push_stack_frame(struct upb_parse_state *s, - uint8_t *buf, uint8_t *submsg_end, uint32_t len, + uint8_t *buf, uint32_t len, void *user_field_desc, jmp_buf errjmp) { - *s->top -= len; - if(*s->top < 0) *s->top -= (buf - submsg_end); s->top++; if(s->top > s->limit) longjmp(errjmp, UPB_ERROR_STACK_OVERFLOW); - *s->top = len; + *s->top = s->completed_offset + len; if(s->submsg_start_cb) s->submsg_start_cb(s->udata, user_field_desc); - return (char*)buf + *s->top; -} - -upb_status_t upb_isstringtype(upb_field_type_t type) -{ - return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING || - type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES; + return (char*)buf + (*s->top > 0 ? (*s->top - s->completed_offset) : 0); } upb_status_t upb_parse(struct upb_parse_state *s, void *_buf, size_t len, @@ -320,7 +309,7 @@ upb_status_t upb_parse(struct upb_parse_state *s, void *_buf, size_t len, struct upb_tag tag; buf = parse_tag(buf, end, &tag, errjmp); if(tag.wire_type == UPB_WIRE_TYPE_END_GROUP) { - submsg_end = pop_stack_frame(s, buf, submsg_end); + submsg_end = pop_stack_frame(s, start); completed = buf; continue; } @@ -344,7 +333,7 @@ upb_status_t upb_parse(struct upb_parse_state *s, void *_buf, size_t len, } if(ft == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE) { - submsg_end = push_stack_frame(s, buf, submsg_end, delim_len, user_field_desc, errjmp); + submsg_end = push_stack_frame(s, start, delim_end - start, user_field_desc, errjmp); } else { /* Delimited data for which we require (and have) all data. */ if(ft == 0) { /* Do nothing -- client has elected to skip. */ @@ -361,16 +350,17 @@ upb_status_t upb_parse(struct upb_parse_state *s, void *_buf, size_t len, if(ft == 0) /* Client elected to skip. */ buf = skip_wire_value(buf, end, tag.wire_type, errjmp); else if(ft == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP) - submsg_end = push_stack_frame(s, buf, submsg_end, 0, user_field_desc, errjmp); + submsg_end = push_stack_frame(s, start, 0, user_field_desc, errjmp); else buf = s->value_cb(s->udata, buf, end, user_field_desc, errjmp); } - while(buf == submsg_end) submsg_end = pop_stack_frame(s, buf, submsg_end); + while(buf == submsg_end) submsg_end = pop_stack_frame(s, start); completed = buf; } done: *read = (char*)completed - (char*)start; + s->completed_offset += *read; return status; } diff --git a/src/upb_parse.h b/src/upb_parse.h index 4a432d8..8975052 100644 --- a/src/upb_parse.h +++ b/src/upb_parse.h @@ -16,6 +16,7 @@ #include <stdbool.h> #include <stdint.h> #include "upb.h" +#include "descriptor.h" #ifdef __cplusplus extern "C" { @@ -48,6 +49,16 @@ struct upb_tag { upb_wire_type_t wire_type; }; +INLINE bool upb_issubmsgtype(upb_field_type_t type) { + return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_GROUP || + type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_MESSAGE; +} + +INLINE bool upb_isstringtype(upb_field_type_t type) { + return type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING || + type == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES; +} + /* High-level parsing interface. **********************************************/ /* The general scheme is that the client registers callbacks that will be @@ -90,9 +101,8 @@ typedef void *(*upb_value_cb)(void *udata, void *buf, void *end, void *user_field_desc, jmp_buf errjmp); /* The callback that is called when a string is parsed. */ -typedef upb_status_t (*upb_str_cb)(void *udata, - struct upb_string *str, - void *user_field_desc); +typedef void (*upb_str_cb)(void *udata, struct upb_string *str, + void *user_field_desc); /* Callbacks that are called when a submessage begins and ends, respectively. * Both are called with the submessage's stack frame at the top of the stack. */ @@ -103,7 +113,8 @@ typedef void (*upb_submsg_end_cb)(void *udata); struct upb_parse_state { /* For delimited submsgs, counts from the submsg len down to zero. * For group submsgs, counts from zero down to the negative len. */ - int32_t stack[UPB_MAX_NESTING], *top, *limit; + uint32_t stack[UPB_MAX_NESTING], *top, *limit; + size_t completed_offset; void *udata; upb_tag_cb tag_cb; upb_value_cb value_cb; |