diff options
Diffstat (limited to 'upb')
-rw-r--r-- | upb/decode.c | 30 | ||||
-rw-r--r-- | upb/msg.c | 15 | ||||
-rw-r--r-- | upb/msg.h | 6 |
3 files changed, 25 insertions, 26 deletions
diff --git a/upb/decode.c b/upb/decode.c index 275f26c..8d3b398 100644 --- a/upb/decode.c +++ b/upb/decode.c @@ -30,19 +30,26 @@ const uint8_t upb_desctype_to_fieldtype[] = { /* Data pertaining to the parse. */ typedef struct { - /* Current decoding pointer. Points to the beginning of a field until we - * have finished decoding the whole field. */ - const char *ptr; + /* Parsing limit: either end of delimited region or end of buffer. */ + const char *limit; + + /* Signals how the parse ended: + * - when 0: parse ended at delimited limit. + * - when 1: parse ended due to end-of-stream. + * - otherwise: parse ended due to a terminating tag (either 0 or END_GROUP). + * + * In the last case, tag-1 is stored, to avoid conflicting with case 0. */ + uint32_t parse_status; + + upb_arena *arena; } upb_decstate; -/* Data pertaining to a single message frame. */ +/* Data passed by value to each parsing function. */ typedef struct { - const char *limit; - int32_t group_number; /* 0 if we are not parsing a group. */ - - /* These members are unset for an unknown group frame. */ + const char *ptr, char *msg; const upb_msglayout *m; + upb_decstate *state; } upb_decframe; #define CHK(x) if (!(x)) { return false; } @@ -132,7 +139,7 @@ static void upb_set32(void *msg, size_t ofs, uint32_t val) { static bool upb_append_unknown(upb_decstate *d, upb_decframe *frame, const char *start) { - upb_msg_addunknown(frame->msg, start, d->ptr - start); + upb_msg_addunknown(frame->msg, start, d->ptr - start, d->arena); return true; } @@ -559,10 +566,11 @@ static bool upb_decode_message(upb_decstate *d, const char *limit, return true; } -bool upb_decode(const char *buf, size_t size, void *msg, - const upb_msglayout *l) { +bool upb_decode(const char *buf, size_t size, void *msg, const upb_msglayout *l, + upb_arena *arena) { upb_decstate state; state.ptr = buf; + state.arena = arena; return upb_decode_message(&state, buf + size, 0, msg, l); } @@ -13,9 +13,6 @@ /* Used when a message is not extendable. */ typedef struct { - /* TODO(haberman): use pointer tagging so we we are slim when known unknown - * fields are not present. */ - upb_arena *arena; char *unknown; size_t unknown_len; size_t unknown_size; @@ -49,10 +46,6 @@ static upb_msg_internal_withext *upb_msg_getinternalwithext( return VOIDPTR_AT(msg, -sizeof(upb_msg_internal_withext)); } -upb_arena *upb_msg_arena(const upb_msg *msg) { - return upb_msg_getinternal_const(msg)->arena; -} - upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a) { upb_alloc *alloc = upb_arena_alloc(a); void *mem = upb_malloc(alloc, upb_msg_sizeof(l)); @@ -70,7 +63,6 @@ upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a) { /* Initialize internal members. */ in = upb_msg_getinternal(msg); - in->arena = a; in->unknown = NULL; in->unknown_len = 0; in->unknown_size = 0; @@ -99,10 +91,11 @@ upb_array *upb_array_new(upb_fieldtype_t type, upb_arena *a) { return ret; } -void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len) { - upb_msg_internal* in = upb_msg_getinternal(msg); +void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, + upb_arena *arena) { + upb_msg_internal *in = upb_msg_getinternal(msg); if (len > in->unknown_size - in->unknown_len) { - upb_alloc *alloc = upb_arena_alloc(in->arena); + upb_alloc *alloc = upb_arena_alloc(arena); size_t need = in->unknown_size + len; size_t newsize = UPB_MAX(in->unknown_size * 2, need); in->unknown = upb_realloc(alloc, in->unknown, in->unknown_size, newsize); @@ -58,10 +58,8 @@ typedef struct { upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a); upb_msg *upb_msg_new(const upb_msglayout *l, upb_arena *a); -/* Returns the arena for the given message. */ -upb_arena *upb_msg_arena(const upb_msg *msg); - -void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len); +void upb_msg_addunknown(upb_msg *msg, const char *data, size_t len, + upb_arena *arena); const char *upb_msg_getunknown(const upb_msg *msg, size_t *len); upb_array *upb_array_new(upb_fieldtype_t type, upb_arena *a); |