From c33d51581abab1e2770080535cbcc2bf936cc5f2 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Thu, 31 Dec 2009 18:19:05 -0800 Subject: upbc compiles and links! But probably doesn't work yet. --- src/upb.h | 28 +++++++----- src/upb_data.c | 138 ++++++++++++++++++++++++++++++++++++-------------------- src/upb_data.h | 34 +++++++++++--- src/upb_parse.c | 117 +++++++++++++++++++++++++---------------------- src/upb_parse.h | 10 ++-- 5 files changed, 201 insertions(+), 126 deletions(-) diff --git a/src/upb.h b/src/upb.h index 158d631..e130dd8 100644 --- a/src/upb.h +++ b/src/upb.h @@ -13,6 +13,7 @@ #include #include // only for size_t. #include "descriptor_const.h" +#include "upb_atomic.h" #ifdef __cplusplus extern "C" { @@ -124,13 +125,14 @@ struct upb_tag { // INTERNAL-ONLY: never refer to these types with a tag ("union", "struct"). // Always use the typedefs. -union upb_string; -union upb_array; -struct upb_msg; +union _upb_string; +union _upb_array; +struct _upb_msg; -typedef union upb_string upb_string; -typedef union upb_array upb_array; -typedef struct upb_msg upb_msg; +typedef union _upb_string upb_string; +typedef union _upb_array upb_array; +typedef struct _upb_msg upb_msg; +typedef upb_atomic_refcount_t upb_data; // A single .proto value. The owner must have an out-of-band way of knowing // the type, so that it knows which union member to use. @@ -142,9 +144,10 @@ union upb_value { uint32_t uint32; uint64_t uint64; bool _bool; - union upb_string *str; - union upb_array *arr; - struct upb_msg *msg; + upb_string *str; + upb_array *arr; + upb_msg *msg; + upb_data *data; }; // A pointer to a .proto value. The owner must have an out-of-band way of @@ -158,9 +161,10 @@ union upb_value_ptr { uint32_t *uint32; uint64_t *uint64; bool *_bool; - union upb_string **str; - union upb_array **arr; - struct upb_msg **msg; + upb_string **str; + upb_array **arr; + upb_msg **msg; + upb_data **data; void *_void; }; diff --git a/src/upb_data.c b/src/upb_data.c index 595015f..084a03c 100644 --- a/src/upb_data.c +++ b/src/upb_data.c @@ -7,6 +7,7 @@ #include #include "upb_data.h" #include "upb_def.h" +#include "upb_parse.h" static uint32_t round_up_to_pow2(uint32_t v) { @@ -51,6 +52,18 @@ static void check_not_frozen(upb_data *d) { if(upb_data_hasflag(d, UPB_DATA_FROZEN)) abort(); } + +/* upb_string *******************************************************************/ + +upb_string *upb_string_new() { + upb_string *s = malloc(sizeof(upb_refcounted_string)); + data_init(&s->common.base, UPB_DATA_HEAPALLOCATED | UPB_DATA_REFCOUNTED); + s->refcounted.byte_size = 0; + s->common.byte_len = 0; + s->common.ptr = NULL; + return s; +} + static upb_strlen_t string_get_bytesize(upb_string *s) { if(upb_data_hasflag(&s->common.base, UPB_DATA_REFCOUNTED)) { return s->refcounted.byte_size; @@ -68,18 +81,6 @@ static void string_set_bytesize(upb_string *s, upb_strlen_t newsize) { } } - -/* upb_string *******************************************************************/ - -upb_string *upb_string_new() { - upb_string *s = malloc(sizeof(upb_refcounted_string)); - data_init(&s->common.base, UPB_DATA_HEAPALLOCATED | UPB_DATA_REFCOUNTED); - s->refcounted.byte_size = 0; - s->common.byte_len = 0; - s->common.ptr = NULL; - return s; -} - void _upb_string_free(upb_string *s) { if(string_get_bytesize(s) != 0) free(s->common.ptr); @@ -136,11 +137,6 @@ void upb_strcat(upb_string *s, upb_string *append) { upb_string_getrobuf(append), append_len); } -void upb_strcpy(upb_string *dest, upb_string *src) { - upb_strlen_t src_len = upb_strlen(src); - memcpy(upb_string_getrwbuf(dest, src_len), upb_string_getrobuf(src), src_len); -} - upb_string *upb_strslice(upb_string *s, int offset, int len) { upb_string *slice = upb_string_new(); len = UPB_MIN((upb_strlen_t)len, upb_strlen(s) - (upb_strlen_t)offset); @@ -165,6 +161,15 @@ int upb_strcmp(upb_string *s1, upb_string *s2) { /* upb_array ******************************************************************/ +upb_array *upb_array_new() { + upb_array *a = malloc(sizeof(upb_refcounted_array)); + data_init(&a->common.base, UPB_DATA_HEAPALLOCATED | UPB_DATA_REFCOUNTED); + a->refcounted.size = 0; + a->common.len = 0; + a->common.elements._void = NULL; + return a; +} + // ONLY handles refcounted arrays for the moment. void _upb_array_free(upb_array *a, struct upb_fielddef *f) { @@ -178,9 +183,42 @@ void _upb_array_free(upb_array *a, struct upb_fielddef *f) free(a); } +static upb_arraylen_t array_get_size(upb_array *a) { + if(upb_data_hasflag(&a->common.base, UPB_DATA_REFCOUNTED)) { + return a->refcounted.size; + } else { + return (a->norefcount.size_and_flags & 0xFFFFFFF8) >> 3; + } +} + +static void array_set_size(upb_array *a, upb_arraylen_t newsize) { + if(upb_data_hasflag(&a->common.base, UPB_DATA_REFCOUNTED)) { + a->refcounted.size = newsize; + } else { + a->norefcount.size_and_flags &= 0x7; + a->norefcount.size_and_flags |= (newsize << 3); + } +} + +void upb_array_resize(upb_array *a, upb_strlen_t len) { + check_not_frozen(&a->common.base); + if(array_get_size(a) < len) { + // Need to resize. + size_t new_size = round_up_to_pow2(len); + a->common.elements._void = realloc(a->common.elements._void, new_size); + array_set_size(a, new_size); + } + a->common.len = len; +} + + /* upb_msg ********************************************************************/ +static void upb_msg_sethas(upb_msg *msg, struct upb_fielddef *f) { + msg->data[f->field_index/8] |= (1 << (f->field_index % 8)); +} + upb_msg *upb_msg_new(struct upb_msgdef *md) { upb_msg *msg = malloc(md->size); memset(msg, 0, md->size); @@ -219,74 +257,75 @@ struct upb_msgparser { /* Helper function that returns a pointer to where the next value for field "f" * should be stored, taking into account whether f is an array that may need to * be allocated or resized. */ -static union upb_value_ptr get_value_ptr(struct upb_msg *msg, - struct upb_fielddef *f) +static union upb_value_ptr get_value_ptr(upb_msg *msg, struct upb_fielddef *f) { - union upb_value_ptr p = upb_msg_getptr(msg, f); + union upb_value_ptr p = _upb_msg_getptr(msg, f); if(upb_isarray(f)) { - if(!upb_msg_isset(msg, f)) { - if(!*p.arr || !upb_mmhead_only(&((*p.arr)->mmhead))) { + if(!upb_msg_has(msg, f)) { + if(!*p.arr || !upb_data_only(*p.data)) { if(*p.arr) - upb_array_unref(*p.arr); - *p.arr = upb_array_new(f); + upb_array_unref(*p.arr, f); + *p.arr = upb_array_new(); } upb_array_truncate(*p.arr); - upb_msg_set(msg, f); + upb_msg_sethas(msg, f); } - p = upb_array_append(*p.arr); + upb_arraylen_t oldlen = upb_array_len(*p.arr); + upb_array_resize(*p.arr, oldlen + 1); + p = _upb_array_getptr(*p.arr, f, oldlen); } return p; } -/* Callbacks for the stream parser. */ +// Callbacks for the stream parser. +// TODO: implement these in terms of public interfaces. static bool value_cb(void *udata, struct upb_msgdef *msgdef, struct upb_fielddef *f, union upb_value val) { (void)msgdef; struct upb_msgparser *mp = udata; - struct upb_msg *msg = mp->top->msg; + upb_msg *msg = mp->top->msg; union upb_value_ptr p = get_value_ptr(msg, f); - upb_msg_set(msg, f); + upb_msg_sethas(msg, f); upb_value_write(p, val, f->type); return true; } static bool str_cb(void *udata, struct upb_msgdef *msgdef, - struct upb_fielddef *f, uint8_t *str, size_t avail_len, + struct upb_fielddef *f, const uint8_t *str, size_t avail_len, size_t total_len) { (void)msgdef; struct upb_msgparser *mp = udata; - struct upb_msg *msg = mp->top->msg; + upb_msg *msg = mp->top->msg; union upb_value_ptr p = get_value_ptr(msg, f); - upb_msg_set(msg, f); + upb_msg_sethas(msg, f); if(avail_len != total_len) abort(); /* TODO: support streaming. */ - if(!*p.str || !upb_mmhead_only(&((*p.str)->mmhead))) { + if(!*p.str || !upb_data_only(*p.data)) { if(*p.str) upb_string_unref(*p.str); *p.str = upb_string_new(); } - upb_string_resize(*p.str, total_len); - memcpy((*p.str)->ptr, str, avail_len); - (*p.str)->byte_len = avail_len; + upb_strcpylen(*p.str, str, avail_len); return true; } static void start_cb(void *udata, struct upb_fielddef *f) { struct upb_msgparser *mp = udata; - struct upb_msg *oldmsg = mp->top->msg; + upb_msg *oldmsg = mp->top->msg; union upb_value_ptr p = get_value_ptr(oldmsg, f); - if(upb_isarray(f) || !upb_msg_isset(oldmsg, f)) { - if(!*p.msg || !upb_mmhead_only(&((*p.msg)->mmhead))) { + if(upb_isarray(f) || !upb_msg_has(oldmsg, f)) { + struct upb_msgdef *md = upb_downcast_msgdef(f->def); + if(!*p.msg || !upb_data_only(*p.data)) { if(*p.msg) - upb_msg_unref(*p.msg); - *p.msg = upb_msg_new(upb_downcast_msgdef(f->def)); + upb_msg_unref(*p.msg, md); + *p.msg = upb_msg_new(md); } - upb_msg_clear(*p.msg); - upb_msg_set(oldmsg, f); + upb_msg_clear(*p.msg, md); + upb_msg_sethas(oldmsg, f); } mp->top++; @@ -308,10 +347,9 @@ struct upb_msgparser *upb_msgparser_new(struct upb_msgdef *def) return mp; } -void upb_msgparser_reset(struct upb_msgparser *s, struct upb_msg *msg, bool byref) +void upb_msgparser_reset(struct upb_msgparser *s, upb_msg *msg) { upb_cbparser_reset(s->s, s); - s->byref = byref; s->top = s->stack; s->top->msg = msg; } @@ -322,13 +360,13 @@ void upb_msgparser_free(struct upb_msgparser *s) free(s); } -void upb_msg_parsestr(struct upb_msg *msg, void *buf, size_t len, +void upb_msg_parsestr(upb_msg *msg, struct upb_msgdef *md, upb_string *str, struct upb_status *status) { - struct upb_msgparser *mp = upb_msgparser_new(msg->def); - upb_msgparser_reset(mp, msg, false); - upb_msg_clear(msg); - upb_msgparser_parse(mp, buf, len, status); + struct upb_msgparser *mp = upb_msgparser_new(md); + upb_msgparser_reset(mp, msg); + upb_msg_clear(msg, md); + upb_msgparser_parse(mp, str, status); upb_msgparser_free(mp); } diff --git a/src/upb_data.h b/src/upb_data.h index b3bbb3c..872f237 100644 --- a/src/upb_data.h +++ b/src/upb_data.h @@ -35,7 +35,8 @@ struct upb_fielddef; // The "base class" of strings, arrays, and messages. Contains a few flags and // possibly a reference count. None of the functions for upb_data are public, // but some of the constants are. -typedef upb_atomic_refcount_t upb_data; + +// typedef upb_atomic_refcount_t upb_data; // The flags in upb_data. typedef enum { @@ -196,7 +197,7 @@ typedef struct { uint32_t byte_size; } upb_refcounted_string; -union upb_string { +union _upb_string { upb_norefcount_string norefcount; upb_string_common common; upb_refcounted_string refcounted; @@ -265,8 +266,22 @@ INLINE bool upb_streql(upb_string *s1, upb_string *s2) { // Like strcmp(). int upb_strcmp(upb_string *s1, upb_string *s2); +// Like upb_strcpy, but copies from a buffer and length. +INLINE void upb_strcpylen(upb_string *dest, const void *src, upb_strlen_t len) { + memcpy(upb_string_getrwbuf(dest, len), src, len); +} + // Replaces the contents of "dest" with the contents of "src". -void upb_strcpy(upb_string *dest, upb_string *src); +INLINE void upb_strcpy(upb_string *dest, upb_string *src) { + upb_strcpylen(dest, upb_string_getrobuf(src), upb_strlen(src)); +} + +// Like upb_strcpy, but copies from a NULL-terminated string. +INLINE void upb_strcpyc(upb_string *dest, const char *src) { + // This does two passes over src, but that is necessary unless we want to + // repeatedly re-allocate dst, which seems worse. + upb_strcpylen(dest, src, strlen(src)); +} // Returns a new string whose contents are a copy of s. upb_string *upb_strdup(upb_string *s); @@ -323,7 +338,7 @@ typedef struct { upb_arraylen_t size; } upb_refcounted_array; -union upb_array { +union _upb_array { upb_norefcount_array norefcount; upb_array_common common; upb_refcounted_array refcounted; @@ -395,12 +410,17 @@ INLINE size_t upb_array_len(upb_array *a) { return a->common.len; } +INLINE void upb_array_truncate(upb_array *a) { + a->common.len = 0; +} + + /* upb_msg ********************************************************************/ // Note that some inline functions for upb_msg are defined in upb_def.h since // they rely on the defs. -struct upb_msg { +struct _upb_msg { upb_data base; uint8_t data[4]; // We allocate the appropriate amount per message. }; @@ -444,7 +464,9 @@ INLINE union upb_value upb_msg_get(upb_msg *msg, struct upb_fielddef *f) { // and will drop a ref on whatever was there before. void upb_msg_set(upb_msg *msg, struct upb_fielddef *f, union upb_value val); -void upb_msg_clear(upb_msg *msg, struct upb_msgdef *md); +INLINE void upb_msg_clear(upb_msg *msg, struct upb_msgdef *md) { + memset(msg->data, 0, md->set_flags_bytes); +} /* Parsing ********************************************************************/ diff --git a/src/upb_parse.c b/src/upb_parse.c index b9cad5a..32332d9 100644 --- a/src/upb_parse.c +++ b/src/upb_parse.c @@ -18,12 +18,14 @@ // generation, because the generated code would want to inline these functions. // The same applies to the functions to read .proto values below. -uint8_t *upb_get_v_uint64_t_full(uint8_t *buf, uint8_t *end, uint64_t *val, - struct upb_status *status); +const uint8_t *upb_get_v_uint64_t_full(const uint8_t *buf, const uint8_t *end, + uint64_t *val, + struct upb_status *status); // Gets a varint (wire type: UPB_WIRE_TYPE_VARINT). -INLINE uint8_t *upb_get_v_uint64_t(uint8_t *buf, uint8_t *end, uint64_t *val, - struct upb_status *status) +INLINE const uint8_t *upb_get_v_uint64_t(const uint8_t *buf, const uint8_t *end, + uint64_t *val, + struct upb_status *status) { // We inline this common case (1-byte varints), if that fails we dispatch to // the full (non-inlined) version. @@ -36,20 +38,21 @@ INLINE uint8_t *upb_get_v_uint64_t(uint8_t *buf, uint8_t *end, uint64_t *val, } // Gets a varint -- called when we only need 32 bits of it. -INLINE uint8_t *upb_get_v_uint32_t(uint8_t *buf, uint8_t *end, - uint32_t *val, struct upb_status *status) +INLINE const uint8_t *upb_get_v_uint32_t(const uint8_t *buf, const uint8_t *end, + uint32_t *val, + struct upb_status *status) { uint64_t val64; - uint8_t *ret = upb_get_v_uint64_t(buf, end, &val64, status); + const uint8_t *ret = upb_get_v_uint64_t(buf, end, &val64, status); *val = (uint32_t)val64; // Discard the high bits. return ret; } // Gets a fixed-length 32-bit integer (wire type: UPB_WIRE_TYPE_32BIT). -INLINE uint8_t *upb_get_f_uint32_t(uint8_t *buf, uint8_t *end, - uint32_t *val, struct upb_status *status) +INLINE const uint8_t *upb_get_f_uint32_t(const uint8_t *buf, const uint8_t *end, + uint32_t *val, struct upb_status *status) { - uint8_t *uint32_end = buf + sizeof(uint32_t); + const uint8_t *uint32_end = buf + sizeof(uint32_t); if(uint32_end > end) { status->code = UPB_STATUS_NEED_MORE_DATA; return end; @@ -65,10 +68,11 @@ INLINE uint8_t *upb_get_f_uint32_t(uint8_t *buf, uint8_t *end, } // Gets a fixed-length 64-bit integer (wire type: UPB_WIRE_TYPE_64BIT). -INLINE uint8_t *upb_get_f_uint64_t(uint8_t *buf, uint8_t *end, - uint64_t *val, struct upb_status *status) +INLINE const uint8_t *upb_get_f_uint64_t(const uint8_t *buf, const uint8_t *end, + uint64_t *val, + struct upb_status *status) { - uint8_t *uint64_end = buf + sizeof(uint64_t); + const uint8_t *uint64_end = buf + sizeof(uint64_t); if(uint64_end > end) { status->code = UPB_STATUS_NEED_MORE_DATA; return end; @@ -84,10 +88,11 @@ INLINE uint8_t *upb_get_f_uint64_t(uint8_t *buf, uint8_t *end, return uint64_end; } -INLINE uint8_t *upb_skip_v_uint64_t(uint8_t *buf, uint8_t *end, - struct upb_status *status) +INLINE const uint8_t *upb_skip_v_uint64_t(const uint8_t *buf, + const uint8_t *end, + struct upb_status *status) { - uint8_t *const maxend = buf + 10; + const uint8_t *const maxend = buf + 10; uint8_t last = 0x80; for(; buf < (uint8_t*)end && (last & 0x80); buf++) last = *buf; @@ -102,10 +107,11 @@ INLINE uint8_t *upb_skip_v_uint64_t(uint8_t *buf, uint8_t *end, return buf; } -INLINE uint8_t *upb_skip_f_uint32_t(uint8_t *buf, uint8_t *end, - struct upb_status *status) +INLINE const uint8_t *upb_skip_f_uint32_t(const uint8_t *buf, + const uint8_t *end, + struct upb_status *status) { - uint8_t *uint32_end = buf + sizeof(uint32_t); + const uint8_t *uint32_end = buf + sizeof(uint32_t); if(uint32_end > end) { status->code = UPB_STATUS_NEED_MORE_DATA; return end; @@ -113,10 +119,11 @@ INLINE uint8_t *upb_skip_f_uint32_t(uint8_t *buf, uint8_t *end, return uint32_end; } -INLINE uint8_t *upb_skip_f_uint64_t(uint8_t *buf, uint8_t *end, - struct upb_status *status) +INLINE const uint8_t *upb_skip_f_uint64_t(const uint8_t *buf, + const uint8_t *end, + struct upb_status *status) { - uint8_t *uint64_end = buf + sizeof(uint64_t); + const uint8_t *uint64_end = buf + sizeof(uint64_t); if(uint64_end > end) { status->code = UPB_STATUS_NEED_MORE_DATA; return end; @@ -137,8 +144,8 @@ INLINE int64_t upb_zzdec_64(uint64_t n) { return (n >> 1) ^ -(int64_t)(n & 1); } // // not contain the entire value UPB_STATUS_NEED_MORE_DATA is returned). // // On success, a pointer will be returned to the first byte that was // // not consumed. -// uint8_t *upb_get_INT32(uint8_t *buf, uint8_t *end, int32_t *d, -// struct upb_status *status); +// const uint8_t *upb_get_INT32(const uint8_t *buf, const uint8_t *end, +// int32_t *d, struct upb_status *status); // // // Given an already read wire value s (source), convert it to a .proto // // value and return it. @@ -151,10 +158,10 @@ INLINE int64_t upb_zzdec_64(uint64_t n) { return (n >> 1) ^ -(int64_t)(n & 1); } INLINE val_t upb_wvtov_ ## type(wire_t s) #define GET(type, v_or_f, wire_t, val_t, member_name) \ - INLINE uint8_t *upb_get_ ## type(uint8_t *buf, uint8_t *end, val_t *d, \ - struct upb_status *status) { \ + INLINE const uint8_t *upb_get_ ## type(const uint8_t *buf, const uint8_t *end, \ + val_t *d, struct upb_status *status) { \ wire_t tmp = 0; \ - uint8_t *ret = upb_get_ ## v_or_f ## _ ## wire_t(buf, end, &tmp, status); \ + const uint8_t *ret = upb_get_ ## v_or_f ## _ ## wire_t(buf, end, &tmp, status); \ *d = upb_wvtov_ ## type(tmp); \ return ret; \ } @@ -192,11 +199,11 @@ T(FLOAT, f, uint32_t, float, _float) { #undef T // Parses a tag, places the result in *tag. -INLINE uint8_t *parse_tag(uint8_t *buf, uint8_t *end, struct upb_tag *tag, - struct upb_status *status) +INLINE const uint8_t *parse_tag(const uint8_t *buf, const uint8_t *end, + struct upb_tag *tag, struct upb_status *status) { uint32_t tag_int; - uint8_t *ret = upb_get_v_uint32_t(buf, end, &tag_int, status); + const uint8_t *ret = upb_get_v_uint32_t(buf, end, &tag_int, status); tag->wire_type = (upb_wire_type_t)(tag_int & 0x07); tag->field_number = tag_int >> 3; return ret; @@ -207,10 +214,10 @@ INLINE uint8_t *parse_tag(uint8_t *buf, uint8_t *end, struct upb_tag *tag, * Parses a 64-bit varint that is known to be >= 2 bytes (the inline version * handles 1 and 2 byte varints). */ -uint8_t *upb_get_v_uint64_t_full(uint8_t *buf, uint8_t *end, uint64_t *val, - struct upb_status *status) +const uint8_t *upb_get_v_uint64_t_full(const uint8_t *buf, const uint8_t *end, + uint64_t *val, struct upb_status *status) { - uint8_t *const maxend = buf + 10; + const uint8_t *const maxend = buf + 10; uint8_t last = 0x80; *val = 0; int bitpos; @@ -231,9 +238,10 @@ uint8_t *upb_get_v_uint64_t_full(uint8_t *buf, uint8_t *end, uint64_t *val, return buf; } -uint8_t *upb_parse_wire_value(uint8_t *buf, uint8_t *end, upb_wire_type_t wt, - union upb_wire_value *wv, - struct upb_status *status) +const uint8_t *upb_parse_wire_value(uint8_t *buf, uint8_t *end, + upb_wire_type_t wt, + union upb_wire_value *wv, + struct upb_status *status) { switch(wt) { case UPB_WIRE_TYPE_VARINT: @@ -252,8 +260,9 @@ uint8_t *upb_parse_wire_value(uint8_t *buf, uint8_t *end, upb_wire_type_t wt, * Advances buf past the current wire value (of type wt), saving the result in * outbuf. */ -static uint8_t *skip_wire_value(uint8_t *buf, uint8_t *end, upb_wire_type_t wt, - struct upb_status *status) +static const uint8_t *skip_wire_value(const uint8_t *buf, const uint8_t *end, + upb_wire_type_t wt, + struct upb_status *status) { switch(wt) { case UPB_WIRE_TYPE_VARINT: @@ -272,8 +281,10 @@ static uint8_t *skip_wire_value(uint8_t *buf, uint8_t *end, upb_wire_type_t wt, } } -static uint8_t *upb_parse_value(uint8_t *buf, uint8_t *end, upb_field_type_t ft, - union upb_value_ptr v, struct upb_status *status) +static const uint8_t *upb_parse_value(const uint8_t *buf, const uint8_t *end, + upb_field_type_t ft, + union upb_value_ptr v, + struct upb_status *status) { #define CASE(t, member_name) \ case UPB_TYPE(t): return upb_get_ ## t(buf, end, v.member_name, status); @@ -349,7 +360,7 @@ void upb_cbparser_reset(struct upb_cbparser *p, void *udata) p->top->end_offset = 0; } -static void *get_msgend(struct upb_cbparser *p, uint8_t *start) +static const void *get_msgend(struct upb_cbparser *p, const uint8_t *start) { if(p->top->end_offset > 0) return start + (p->top->end_offset - p->completed_offset); @@ -357,7 +368,7 @@ static void *get_msgend(struct upb_cbparser *p, uint8_t *start) return (void*)UINTPTR_MAX; // group. } -static bool isgroup(void *submsg_end) +static bool isgroup(const void *submsg_end) { return submsg_end == (void*)UINTPTR_MAX; } @@ -374,9 +385,9 @@ INLINE bool upb_check_type(upb_wire_type_t wt, upb_field_type_t ft) { * Pushes a new stack frame for a submessage with the given len (which will * be zero if the submessage is a group). */ -static uint8_t *push(struct upb_cbparser *p, uint8_t *start, - uint32_t submsg_len, struct upb_fielddef *f, - struct upb_status *status) +static const uint8_t *push(struct upb_cbparser *p, const uint8_t *start, + uint32_t submsg_len, struct upb_fielddef *f, + struct upb_status *status) { p->top++; if(p->top >= p->limit) { @@ -397,7 +408,7 @@ static uint8_t *push(struct upb_cbparser *p, uint8_t *start, * Pops a stack frame, returning a pointer for where the next submsg should * end (or a pointer that is out of range for a group). */ -static void *pop(struct upb_cbparser *p, uint8_t *start) +static const void *pop(struct upb_cbparser *p, const uint8_t *start) { if(p->end_cb) p->end_cb(p->udata); p->top--; @@ -405,18 +416,18 @@ static void *pop(struct upb_cbparser *p, uint8_t *start) } -size_t upb_cbparser_parse(struct upb_cbparser *p, void *_buf, size_t len, +size_t upb_cbparser_parse(struct upb_cbparser *p, upb_string *str, struct upb_status *status) { // buf is our current offset, moves from start to end. - uint8_t *buf = _buf; - uint8_t *const start = buf; // ptr equivalent of p->completed_offset - uint8_t *end = buf + len; + const uint8_t *buf = (uint8_t*)upb_string_getrobuf(str); + const uint8_t *const start = buf; // ptr equivalent of p->completed_offset + const uint8_t *const end = buf + upb_strlen(str); // When we have fully parsed a tag/value pair, we advance this. - uint8_t *completed = buf; + const uint8_t *completed = buf; - uint8_t *submsg_end = get_msgend(p, start); + const uint8_t *submsg_end = get_msgend(p, start); struct upb_msgdef *msgdef = p->top->msgdef; bool keep_going = true; @@ -453,7 +464,7 @@ size_t upb_cbparser_parse(struct upb_cbparser *p, void *_buf, size_t len, int32_t delim_len; buf = upb_get_INT32(buf, end, &delim_len, status); CHECK_STATUS(); - uint8_t *delim_end = buf + delim_len; + 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; diff --git a/src/upb_parse.h b/src/upb_parse.h index 12e04e1..7086204 100644 --- a/src/upb_parse.h +++ b/src/upb_parse.h @@ -40,7 +40,7 @@ typedef bool (*upb_value_cb)(void *udata, struct upb_msgdef *msgdef, // available at str. If the client is streaming and the current buffer ends in // the middle of the string, this number could be less than total_len. typedef bool (*upb_str_cb)(void *udata, struct upb_msgdef *msgdef, - struct upb_fielddef *f, uint8_t *str, + struct upb_fielddef *f, const uint8_t *str, size_t avail_len, size_t total_len); // The start and end callbacks are called when a submessage begins and ends, @@ -80,7 +80,7 @@ void upb_cbparser_reset(struct upb_cbparser *p, void *udata); // // TODO: see if we can provide the following guarantee efficiently: // retval will always be >= len. */ -size_t upb_cbparser_parse(struct upb_cbparser *p, void *buf, size_t len, +size_t upb_cbparser_parse(struct upb_cbparser *p, upb_string *str, struct upb_status *status); /* Pick parser interface. ************************************************/ @@ -117,10 +117,10 @@ struct upb_pickparser *upb_pickparser_new(struct upb_msgdef *msgdef, char *fields[], upb_pp_value_cb value_cb, upb_pp_str_cb str_cb); -void upb_pickparser_free(struct upb_cbparser *p); +void upb_pickparser_free(struct upb_pickparser *p); void upb_pickparser_reset(struct upb_pickparser *p, void *udata); -size_t upb_cbparser_parse(struct upb_cbparser *p, void *buf, size_t len, - struct upb_status *status); +size_t upb_pickparser_parse(struct upb_pickparser *p, upb_string *str, + struct upb_status *status); #ifdef __cplusplus } /* extern "C" */ -- cgit v1.2.3