diff --git a/Makefile b/Makefile index 33cd4f9fd6..73e5b6573b 100644 --- a/Makefile +++ b/Makefile @@ -2,18 +2,19 @@ # Function to expand a wildcard pattern recursively. rwildcard=$(strip $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2)$(filter $(subst *,%,$2),$d))) -.PHONY: all clean test benchmarks benchmark +.PHONY: all clean test benchmarks benchmark descriptorgen CC=gcc CXX=g++ CFLAGS=-std=c99 INCLUDE=-Idescriptor -Isrc -Itests -I. -CPPFLAGS=-O3 -Wall -Wextra -g $(INCLUDE) $(strip $(shell test -f perf-cppflags && cat perf-cppflags)) +CPPFLAGS=-Wall -Wextra -g $(INCLUDE) $(strip $(shell test -f perf-cppflags && cat perf-cppflags)) LIBUPB=src/libupb.a ALL=deps $(OBJ) $(LIBUPB) tests/test_table tests/tests tools/upbc all: $(ALL) clean: rm -f $(call rwildcard,,*.o) $(ALL) benchmark/google_messages.proto.pb benchmark/google_messages.pb.* benchmarks/b.* benchmarks/*.pb* + rm -f descriptor/descriptor.proto.pb # The core library (src/libupb.a) OBJ=src/upb_parse.o src/upb_table.o src/upb_msg.o src/upb_enum.o src/upb_context.o \ @@ -23,6 +24,14 @@ HEADERS=$(call rwildcard,,*.h) $(LIBUPB): $(OBJ) ar rcs $(LIBUPB) $(OBJ) +# Regenerating the auto-generated files in descriptor/. +descriptor/descriptor.proto.pb: descriptor/descriptor.proto + # TODO: replace with upbc + protoc descriptor/descriptor.proto -odescriptor/descriptor.proto.pb + +descriptorgen: descriptor/descriptor.proto.pb tools/upbc + ./tools/upbc -i upb_file_descriptor_set -o descriptor/descriptor descriptor/descriptor.proto.pb + # Tests test: tests/tests ./tests/tests diff --git a/descriptor/descriptor.h b/descriptor/descriptor.h index 39d31175b1..70960239fe 100644 --- a/descriptor/descriptor.h +++ b/descriptor/descriptor.h @@ -131,6 +131,8 @@ typedef struct google_protobuf_MethodOptions /* The message definitions themselves. */ struct google_protobuf_UninterpretedOption_NamePart { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { @@ -144,6 +146,8 @@ struct google_protobuf_UninterpretedOption_NamePart { UPB_DEFINE_MSG_ARRAY(google_protobuf_UninterpretedOption_NamePart) struct google_protobuf_DescriptorProto { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { @@ -167,6 +171,8 @@ struct google_protobuf_DescriptorProto { UPB_DEFINE_MSG_ARRAY(google_protobuf_DescriptorProto) struct google_protobuf_EnumDescriptorProto { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { @@ -182,6 +188,8 @@ struct google_protobuf_EnumDescriptorProto { UPB_DEFINE_MSG_ARRAY(google_protobuf_EnumDescriptorProto) struct google_protobuf_UninterpretedOption { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { @@ -203,6 +211,8 @@ struct google_protobuf_UninterpretedOption { UPB_DEFINE_MSG_ARRAY(google_protobuf_UninterpretedOption) struct google_protobuf_FileDescriptorProto { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { @@ -228,6 +238,8 @@ struct google_protobuf_FileDescriptorProto { UPB_DEFINE_MSG_ARRAY(google_protobuf_FileDescriptorProto) struct google_protobuf_MethodDescriptorProto { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { @@ -245,6 +257,8 @@ struct google_protobuf_MethodDescriptorProto { UPB_DEFINE_MSG_ARRAY(google_protobuf_MethodDescriptorProto) struct google_protobuf_EnumValueOptions { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { @@ -256,6 +270,8 @@ struct google_protobuf_EnumValueOptions { UPB_DEFINE_MSG_ARRAY(google_protobuf_EnumValueOptions) struct google_protobuf_EnumValueDescriptorProto { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { @@ -271,6 +287,8 @@ struct google_protobuf_EnumValueDescriptorProto { UPB_DEFINE_MSG_ARRAY(google_protobuf_EnumValueDescriptorProto) struct google_protobuf_ServiceDescriptorProto { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { @@ -286,6 +304,8 @@ struct google_protobuf_ServiceDescriptorProto { UPB_DEFINE_MSG_ARRAY(google_protobuf_ServiceDescriptorProto) struct google_protobuf_FileDescriptorSet { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { @@ -297,6 +317,8 @@ struct google_protobuf_FileDescriptorSet { UPB_DEFINE_MSG_ARRAY(google_protobuf_FileDescriptorSet) struct google_protobuf_DescriptorProto_ExtensionRange { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { @@ -310,6 +332,8 @@ struct google_protobuf_DescriptorProto_ExtensionRange { UPB_DEFINE_MSG_ARRAY(google_protobuf_DescriptorProto_ExtensionRange) struct google_protobuf_FieldOptions { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { @@ -329,6 +353,8 @@ struct google_protobuf_FieldOptions { UPB_DEFINE_MSG_ARRAY(google_protobuf_FieldOptions) struct google_protobuf_FileOptions { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { @@ -348,6 +374,8 @@ struct google_protobuf_FileOptions { UPB_DEFINE_MSG_ARRAY(google_protobuf_FileOptions) struct google_protobuf_MessageOptions { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { @@ -361,6 +389,8 @@ struct google_protobuf_MessageOptions { UPB_DEFINE_MSG_ARRAY(google_protobuf_MessageOptions) struct google_protobuf_EnumOptions { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { @@ -372,6 +402,8 @@ struct google_protobuf_EnumOptions { UPB_DEFINE_MSG_ARRAY(google_protobuf_EnumOptions) struct google_protobuf_FieldDescriptorProto { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { @@ -397,6 +429,8 @@ struct google_protobuf_FieldDescriptorProto { UPB_DEFINE_MSG_ARRAY(google_protobuf_FieldDescriptorProto) struct google_protobuf_ServiceOptions { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { @@ -408,6 +442,8 @@ struct google_protobuf_ServiceOptions { UPB_DEFINE_MSG_ARRAY(google_protobuf_ServiceOptions) struct google_protobuf_MethodOptions { + struct upb_msgdef *def; + void *gptr; union { uint8_t bytes[1]; struct { diff --git a/perf-tests.sh b/perf-tests.sh index 28873f2267..1d8f4a8d2e 100755 --- a/perf-tests.sh +++ b/perf-tests.sh @@ -11,23 +11,23 @@ fi rm -f perf-tests.out make clean -echo "-DNDEBUG -msse3" > perf-cppflags +echo "-O3 -DNDEBUG -msse3" > perf-cppflags make $MAKETARGET make benchmark | sed -e 's/^/plain./g' | tee -a perf-tests.out make clean -echo "-DNDEBUG -fomit-frame-pointer -msse3" > perf-cppflags +echo "-O3 -DNDEBUG -fomit-frame-pointer -msse3" > perf-cppflags make $MAKETARGET make benchmark | sed -e 's/^/omitfp./g' | tee -a perf-tests.out if [ x`uname -m` == xx86_64 ]; then make clean - echo "-DNDEBUG -msse3 -m32" > perf-cppflags + echo "-O3 -DNDEBUG -msse3 -m32" > perf-cppflags make upb_benchmarks make benchmark | sed -e 's/^/plain32./g' | tee -a perf-tests.out make clean - echo "-DNDEBUG -fomit-frame-pointer -msse3 -m32" > perf-cppflags + echo "-O3 -DNDEBUG -fomit-frame-pointer -msse3 -m32" > perf-cppflags make upb_benchmarks make benchmark | sed -e 's/^/omitfp32./g' | tee -a perf-tests.out fi diff --git a/src/upb.h b/src/upb.h index 83917af2ac..27bf5fc7be 100644 --- a/src/upb.h +++ b/src/upb.h @@ -35,8 +35,6 @@ extern "C" { #define UPB_INDEX(base, i, m) (void*)((char*)(base) + ((i)*(m))) -INLINE uint32_t max(uint32_t a, uint32_t b) { return a > b ? a : b; } - /* Fundamental types and type constants. **************************************/ /* A list of types as they are encoded on-the-wire. */ @@ -104,7 +102,7 @@ union upb_value { bool _bool; struct upb_string *str; struct upb_array *arr; - void *msg; + struct upb_msg *msg; }; /* A pointer to a .proto value. The owner must have an out-of-band way of @@ -119,7 +117,7 @@ union upb_value_ptr { bool *_bool; struct upb_string **str; struct upb_array **arr; - void **msg; + struct upb_msg **msg; void *_void; }; diff --git a/src/upb_array.h b/src/upb_array.h index d48aa17627..65d44bb4d8 100644 --- a/src/upb_array.h +++ b/src/upb_array.h @@ -38,22 +38,32 @@ typedef uint32_t upb_arraylen_t; * the data in the array depends on the type. */ struct upb_array { union upb_value_ptr elements; - void *mem; upb_arraylen_t len; /* Number of elements in "elements". */ - upb_arraylen_t size; /* Memory allocated in "mem" (measured in elements) */ + upb_arraylen_t size; /* Memory we own (0 if by reference). */ + void *gptr; }; INLINE void upb_array_init(struct upb_array *arr) { arr->elements._void = NULL; - arr->mem = NULL; arr->len = 0; arr->size = 0; } -INLINE void upb_array_free(struct upb_array *arr) +INLINE void upb_array_uninit(struct upb_array *arr) { - free(arr->mem); + if(arr->size) free(arr->elements._void); +} + +INLINE struct upb_array *upb_array_new() { + struct upb_array *arr = malloc(sizeof(*arr)); + upb_array_init(arr); + return arr; +} + +INLINE void upb_array_free(struct upb_array *arr) { + upb_array_uninit(arr); + free(arr); } /* Returns a pointer to an array element. Does not perform a bounds check! */ @@ -92,18 +102,18 @@ INLINE bool upb_array_resize(struct upb_array *arr, upb_arraylen_t newlen, { size_t type_size = upb_type_info[type].size; bool dropped = false; - bool ref = arr->elements._void != arr->mem; /* Ref'ing external memory. */ + bool ref = arr->size == 0; /* Ref'ing external memory. */ + void *data = arr->elements._void; if(arr->size < newlen) { /* Need to resize. */ - arr->size = max(4, upb_round_up_to_pow2(newlen)); - arr->mem = realloc(arr->mem, arr->size * type_size); + arr->size = UPB_MAX(4, upb_round_up_to_pow2(newlen)); + arr->elements._void = realloc(ref ? NULL : data, arr->size * type_size); } if(ref) { /* Need to take referenced data and copy it to memory we own. */ - memcpy(arr->mem, arr->elements._void, UPB_MIN(arr->len, newlen) * type_size); + memcpy(arr->elements._void, data, UPB_MIN(arr->len, newlen) * type_size); dropped = true; } - arr->elements._void = arr->mem; arr->len = newlen; return dropped; } @@ -111,8 +121,9 @@ INLINE bool upb_array_resize(struct upb_array *arr, upb_arraylen_t newlen, /* These are all overlays on upb_array, pointers between them can be cast. */ #define UPB_DEFINE_ARRAY_TYPE(name, type) \ struct name ## _array { \ + struct upb_fielddef *f; \ + void *gptr; \ type *elements; \ - type *mem; \ upb_arraylen_t len; \ upb_arraylen_t size; \ }; @@ -132,7 +143,6 @@ UPB_DEFINE_ARRAY_TYPE(upb_msg, void*) #define UPB_DEFINE_MSG_ARRAY(msg_type) \ UPB_MSG_ARRAY(msg_type) { \ msg_type **elements; \ - msg_type **mem; \ upb_arraylen_t len; \ upb_arraylen_t size; \ }; diff --git a/src/upb_context.c b/src/upb_context.c index 5e1833ea3f..252cf17b27 100644 --- a/src/upb_context.c +++ b/src/upb_context.c @@ -60,7 +60,7 @@ void upb_context_free(struct upb_context *c) { free_symtab(&c->symtab); for(size_t i = 0; i < c->fds_len; i++) - upb_msg_free(c->fds[i], c->fds_msg); + upb_msg_free((struct upb_msg*)c->fds[i]); free_symtab(&c->psymtab); free(c->fds); } @@ -280,7 +280,7 @@ bool upb_context_addfds(struct upb_context *c, bool upb_context_parsefds(struct upb_context *c, struct upb_string *fds_str) { google_protobuf_FileDescriptorSet *fds = - upb_msg_parsenew(c->fds_msg, fds_str); + (google_protobuf_FileDescriptorSet*)upb_msg_parsenew(c->fds_msg, fds_str); if(!fds) return false; if(!upb_context_addfds(c, fds)) return false; diff --git a/src/upb_msg.c b/src/upb_msg.c index 16c24c099c..dd627ebe94 100644 --- a/src/upb_msg.c +++ b/src/upb_msg.c @@ -82,7 +82,7 @@ bool upb_msgdef_init(struct upb_msgdef *m, google_protobuf_DescriptorProto *d, f->type = fd->type; f->label = fd->label; m->size = f->byte_offset + type_info->size; - max_align = max(max_align, type_info->align); + max_align = UPB_MAX(max_align, type_info->align); if(fd->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REQUIRED) m->num_required_fields++; @@ -123,59 +123,49 @@ void upb_msgdef_ref(struct upb_msgdef *m, struct upb_msg_fielddef *f, /* Simple, one-shot parsing ***************************************************/ -void *upb_msg_new(struct upb_msgdef *md) +static void *upb_msg_new(struct upb_msgdef *md) { - void *msg = malloc(md->size); - memset(msg, 0, md->size); + size_t size = md->size + (sizeof(void*) * 2); + struct upb_msg *msg = malloc(size); + memset(msg, 0, size); + msg->def = md; return msg; } /* Allocation callbacks. */ -static struct upb_array *getarray_cb(void *msg, struct upb_msgdef *md, - struct upb_array *existingval, - struct upb_msg_fielddef *f, - upb_arraylen_t len) +struct upb_array *getarray_cb( + void *from_gptr, struct upb_array *existingval, struct upb_msg_fielddef *f) { - (void)msg; - (void)md; + (void)from_gptr; (void)existingval; /* Don't care -- always zero. */ - (void)len; - struct upb_array *arr = existingval; - if(!arr) { - arr = malloc(sizeof(*arr)); - upb_array_init(arr); - } - upb_array_resize(arr, len, f->type); - return arr; + (void)f; + return upb_array_new(); } -static struct upb_string *getstring_cb(void *msg, struct upb_msgdef *md, - struct upb_string *existingval, - struct upb_msg_fielddef *f, size_t len) +static struct upb_string *getstring_cb( + void *from_gptr, struct upb_string *existingval, struct upb_msg_fielddef *f, + bool byref) { - (void)msg; - (void)md; + (void)from_gptr; (void)existingval; /* Don't care -- always zero. */ (void)f; - struct upb_string *str = malloc(sizeof(*str)); - str->ptr = malloc(len); - return str; + (void)byref; + return upb_strnew(); } -static void *getmsg_cb(void *msg, struct upb_msgdef *md, - void *existingval, struct upb_msg_fielddef *f) +static struct upb_msg *getmsg_cb( + void *from_gptr, struct upb_msg *existingval, struct upb_msg_fielddef *f) { - (void)msg; - (void)md; + (void)from_gptr; (void)existingval; /* Don't care -- always zero. */ return upb_msg_new(f->ref.msg); } -void *upb_msg_parsenew(struct upb_msgdef *md, struct upb_string *s) +struct upb_msg *upb_msg_parsenew(struct upb_msgdef *md, struct upb_string *s) { struct upb_msg_parser mp; - void *msg = upb_msg_new(md); - upb_msg_parser_reset(&mp, msg, md, false); + struct upb_msg *msg = upb_msg_new(md); + upb_msg_parser_reset(&mp, msg, false); mp.getarray_cb = getarray_cb; mp.getstring_cb = getstring_cb; mp.getmsg_cb = getmsg_cb; @@ -184,7 +174,7 @@ void *upb_msg_parsenew(struct upb_msgdef *md, struct upb_string *s) if(status == UPB_STATUS_OK && read == s->byte_len) { return msg; } else { - upb_msg_free(msg, md); + upb_msg_free(msg); return NULL; } } @@ -197,28 +187,28 @@ static void free_value(union upb_value_ptr p, struct upb_msg_fielddef *f) free((*p.str)->ptr); free(*p.str); } else if(upb_issubmsg(f)) { - upb_msg_free(*p.msg, f->ref.msg); + upb_msg_free(*p.msg); } } -void upb_msg_free(void *data, struct upb_msgdef *m) +void upb_msg_free(struct upb_msg *msg) { - if(!data) return; /* A very free-like thing to do. */ + if(!msg) return; /* A very free-like thing to do. */ + struct upb_msgdef *m = msg->def; for(unsigned int i = 0; i < m->num_fields; i++) { struct upb_msg_fielddef *f = &m->fields[i]; - if(!upb_msg_isset(data, f)) continue; - union upb_value_ptr p = upb_msg_getptr(data, f); + if(!upb_msg_isset(msg, f)) continue; + union upb_value_ptr p = upb_msg_getptr(msg, f); if(upb_isarray(f)) { assert(*p.arr); for(upb_arraylen_t j = 0; j < (*p.arr)->len; j++) free_value(upb_array_getelementptr(*p.arr, j, f->type), f); - free((*p.arr)->elements._void); - free(*p.arr); + upb_array_free(*p.arr); } else { free_value(p, f); } } - free(data); + free(msg); } /* Parsing. ******************************************************************/ @@ -226,14 +216,18 @@ void upb_msg_free(void *data, struct upb_msgdef *m) /* 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(void *data, struct upb_msgdef *m, +static union upb_value_ptr get_value_ptr(struct upb_msg *msg, struct upb_msg_fielddef *f, - upb_msg_getarray_cb_t getarray_cb) + void **gptr, + upb_msg_getandref_array_cb_t getarray_cb) { - union upb_value_ptr p = upb_msg_getptr(data, f); + union upb_value_ptr p = upb_msg_getptr(msg, f); if(upb_isarray(f)) { - size_t len = upb_msg_isset(data, f) ? (*p.arr)->len : 0; - *p.arr = getarray_cb(data, m, *p.arr, f, len + 1); + bool isset = upb_msg_isset(msg, f); + size_t len = isset ? (*p.arr)->len : 0; + if(!isset) *p.arr = getarray_cb(*gptr, *p.arr, f); + upb_array_resize(*p.arr, len+1, f->type); + *gptr = (*p.arr)->gptr; p = upb_array_getelementptr(*p.arr, len, f->type); } return p; @@ -245,7 +239,8 @@ static upb_field_type_t tag_cb(void *udata, struct upb_tag *tag, void **user_field_desc) { struct upb_msg_parser *mp = udata; - struct upb_msg_fielddef *f = upb_msg_fieldbynum(mp->top->m, tag->field_number); + struct upb_msg_fielddef *f = + upb_msg_fieldbynum(mp->top->msg->def, tag->field_number); if(!f || !upb_check_type(tag->wire_type, f->type)) return 0; /* Skip unknown or fields of the wrong type. */ *user_field_desc = f; @@ -257,8 +252,9 @@ static upb_status_t value_cb(void *udata, uint8_t *buf, uint8_t *end, { struct upb_msg_parser *mp = udata; struct upb_msg_fielddef *f = user_field_desc; - void *msg = mp->top->msg; - union upb_value_ptr p = get_value_ptr(msg, mp->top->m, f, mp->getarray_cb); + struct upb_msg *msg = mp->top->msg; + void *gptr = upb_msg_gptr(msg); + union upb_value_ptr p = get_value_ptr(msg, f, &gptr, mp->getarray_cb); upb_msg_set(msg, f); UPB_CHECK(upb_parse_value(buf, end, f->type, p, outbuf)); return UPB_STATUS_OK; @@ -270,16 +266,19 @@ static void str_cb(void *udata, uint8_t *str, { struct upb_msg_parser *mp = udata; struct upb_msg_fielddef *f = udesc; - void *msg = mp->top->msg; - union upb_value_ptr p = get_value_ptr(msg, mp->top->m, f, mp->getarray_cb); + struct upb_msg *msg = mp->top->msg; + void *gptr = upb_msg_gptr(msg); + union upb_value_ptr p = get_value_ptr(msg, f, &gptr, mp->getarray_cb); upb_msg_set(msg, f); if(avail_len != total_len) abort(); /* TODO: support streaming. */ - if(avail_len == total_len && mp->byref) { - *p.str = mp->getstring_cb(msg, mp->top->m, *p.str, f, 0); + bool byref = avail_len == total_len && mp->byref; + *p.str = mp->getstring_cb(gptr, *p.str, f, byref); + if(byref) { + upb_strdrop(*p.str); (*p.str)->ptr = (char*)str; (*p.str)->byte_len = avail_len; } else { - *p.str = mp->getstring_cb(msg, mp->top->m, *p.str, f, total_len); + upb_stralloc(*p.str, total_len); memcpy((*p.str)->ptr, str, avail_len); (*p.str)->byte_len = avail_len; } @@ -289,13 +288,12 @@ static void submsg_start_cb(void *udata, void *user_field_desc) { struct upb_msg_parser *mp = udata; struct upb_msg_fielddef *f = user_field_desc; - struct upb_msgdef *oldmsgdef = mp->top->m; - void *oldmsg = mp->top->msg; - union upb_value_ptr p = get_value_ptr(oldmsg, oldmsgdef, f, mp->getarray_cb); + struct upb_msg *oldmsg = mp->top->msg; + void *gptr = upb_msg_gptr(oldmsg); + union upb_value_ptr p = get_value_ptr(oldmsg, f, &gptr, mp->getarray_cb); upb_msg_set(oldmsg, f); - *p.msg = mp->getmsg_cb(oldmsg, oldmsgdef, *p.msg, f); + *p.msg = mp->getmsg_cb(gptr, *p.msg, f); mp->top++; - mp->top->m = f->ref.msg; mp->top->msg = *p.msg; } @@ -307,13 +305,11 @@ static void submsg_end_cb(void *udata) /* Externally-visible functions for the msg parser. */ -void upb_msg_parser_reset(struct upb_msg_parser *s, void *msg, - struct upb_msgdef *m, bool byref) +void upb_msg_parser_reset(struct upb_msg_parser *s, struct upb_msg *msg, bool byref) { upb_stream_parser_reset(&s->s, s); s->byref = byref; s->top = s->stack; - s->top->m = m; s->top->msg = msg; s->s.tag_cb = tag_cb; s->s.value_cb = value_cb; @@ -551,8 +547,7 @@ bool upb_array_eql(struct upb_array *arr1, struct upb_array *arr2, if(upb_issubmsg(f)) { if(!recursive) return true; for(uint32_t i = 0; i < arr1->len; i++) - if(!upb_msg_eql(arr1->elements.msg[i], arr2->elements.msg[i], - f->ref.msg, recursive)) + if(!upb_msg_eql(arr1->elements.msg[i], arr2->elements.msg[i], recursive)) return false; } else if(upb_isstring(f)) { for(uint32_t i = 0; i < arr1->len; i++) @@ -566,11 +561,13 @@ bool upb_array_eql(struct upb_array *arr1, struct upb_array *arr2, return true; } -bool upb_msg_eql(void *data1, void *data2, struct upb_msgdef *m, bool recursive) +bool upb_msg_eql(struct upb_msg *msg1, struct upb_msg *msg2, bool recursive) { /* Must have the same fields set. TODO: is this wrong? Should we also * consider absent defaults equal to explicitly set defaults? */ - if(memcmp(data1, data2, m->set_flags_bytes) != 0) + if(msg1->def != msg2->def) return false; + struct upb_msgdef *m = msg1->def; + if(memcmp(msg1->data, msg2->data, msg1->def->set_flags_bytes) != 0) return false; /* Possible optimization: create a mask of the bytes in the messages that @@ -579,13 +576,16 @@ bool upb_msg_eql(void *data1, void *data2, struct upb_msgdef *m, bool recursive) for(uint32_t i = 0; i < m->num_fields; i++) { struct upb_msg_fielddef *f = &m->fields[i]; - if(!upb_msg_isset(data1, f)) continue; - union upb_value_ptr p1 = upb_msg_getptr(data1, f); - union upb_value_ptr p2 = upb_msg_getptr(data2, f); + bool msg1set = upb_msg_isset(msg1, f); + bool msg2set = upb_msg_isset(msg2, f); + if(msg1set != msg2set) return false; + if(!msg1set) continue; + union upb_value_ptr p1 = upb_msg_getptr(msg1, f); + union upb_value_ptr p2 = upb_msg_getptr(msg2, f); if(upb_isarray(f)) { if(!upb_array_eql(*p1.arr, *p2.arr, f, recursive)) return false; } else if(upb_issubmsg(f)) { - if(recursive && !upb_msg_eql(p1.msg, p2.msg, f->ref.msg, recursive)) + if(recursive && !upb_msg_eql(*p1.msg, *p2.msg, recursive)) return false; } else if(!upb_value_eql(p1, p2, f->type)) { return false; @@ -600,9 +600,10 @@ static void printval(struct upb_text_printer *printer, union upb_value_ptr p, google_protobuf_FieldDescriptorProto *fd, FILE *stream); -static void printmsg(struct upb_text_printer *printer, void *msg, - struct upb_msgdef *m, FILE *stream) +static void printmsg(struct upb_text_printer *printer, struct upb_msg *msg, + FILE *stream) { + struct upb_msgdef *m = msg->def; for(uint32_t i = 0; i < m->num_fields; i++) { struct upb_msg_fielddef *f = &m->fields[i]; google_protobuf_FieldDescriptorProto *fd = upb_msg_field_descriptor(f, m); @@ -626,18 +627,17 @@ static void printval(struct upb_text_printer *printer, union upb_value_ptr p, FILE *stream) { if(upb_issubmsg(f)) { - upb_text_push(printer, *fd->name, stream); - printmsg(printer, *p.msg, f->ref.msg, stream); + upb_text_push(printer, fd->name, stream); + printmsg(printer, *p.msg, stream); upb_text_pop(printer, stream); } else { - upb_text_printfield(printer, *fd->name, f->type, upb_deref(p, f->type), stream); + upb_text_printfield(printer, fd->name, f->type, upb_deref(p, f->type), stream); } } -void upb_msg_print(void *data, struct upb_msgdef *m, bool single_line, - FILE *stream) +void upb_msg_print(struct upb_msg *msg, bool single_line, FILE *stream) { struct upb_text_printer printer; upb_text_printer_init(&printer, single_line); - printmsg(&printer, data, m, stream); + printmsg(&printer, msg, stream); } diff --git a/src/upb_msg.h b/src/upb_msg.h index 6a0568aaee..e2b69038f0 100644 --- a/src/upb_msg.h +++ b/src/upb_msg.h @@ -108,6 +108,18 @@ INLINE struct google_protobuf_FieldDescriptorProto *upb_msg_field_descriptor( return m->field_descriptors[f->field_index]; } +/* Message structure. *********************************************************/ + +struct upb_msg { + struct upb_msgdef *def; + void *gptr; /* Generic pointer for use by subclasses. */ + uint8_t data[1]; +}; + +INLINE void *upb_msg_gptr(struct upb_msg *msg) { + return msg->gptr; +} + /* Field access. **************************************************************/ /* Note that these only provide access to fields that are directly in the msg @@ -115,14 +127,16 @@ INLINE struct google_protobuf_FieldDescriptorProto *upb_msg_field_descriptor( * necessary to dereference the returned values. */ /* Returns a pointer to a specific field in a message. */ -INLINE union upb_value_ptr upb_msg_getptr(void *msg, struct upb_msg_fielddef *f) { +INLINE union upb_value_ptr upb_msg_getptr(struct upb_msg *msg, + struct upb_msg_fielddef *f) { union upb_value_ptr p; - p._void = ((char*)msg + f->byte_offset); + p._void = &msg->data[f->byte_offset]; return p; } /* Returns a a specific field in a message. */ -INLINE union upb_value upb_msg_get(void *msg, struct upb_msg_fielddef *f) { +INLINE union upb_value upb_msg_get(struct upb_msg *msg, + struct upb_msg_fielddef *f) { return upb_deref(upb_msg_getptr(msg, f), f->type); } @@ -145,40 +159,40 @@ INLINE uint8_t upb_isset_mask(uint32_t field_index) { } /* Returns true if the given field is set, false otherwise. */ -INLINE void upb_msg_set(void *msg, struct upb_msg_fielddef *f) +INLINE void upb_msg_set(struct upb_msg *msg, struct upb_msg_fielddef *f) { - ((char*)msg)[upb_isset_offset(f->field_index)] |= upb_isset_mask(f->field_index); + msg->data[upb_isset_offset(f->field_index)] |= upb_isset_mask(f->field_index); } /* Clears the set bit for this field in the given message. */ -INLINE void upb_msg_unset(void *msg, struct upb_msg_fielddef *f) +INLINE void upb_msg_unset(struct upb_msg *msg, struct upb_msg_fielddef *f) { - ((char*)msg)[upb_isset_offset(f->field_index)] &= ~upb_isset_mask(f->field_index); + msg->data[upb_isset_offset(f->field_index)] &= ~upb_isset_mask(f->field_index); } /* Tests whether the given field is set. */ -INLINE bool upb_msg_isset(void *msg, struct upb_msg_fielddef *f) +INLINE bool upb_msg_isset(struct upb_msg *msg, struct upb_msg_fielddef *f) { - return ((char*)msg)[upb_isset_offset(f->field_index)] & upb_isset_mask(f->field_index); + return msg->data[upb_isset_offset(f->field_index)] & upb_isset_mask(f->field_index); } /* Returns true if *all* required fields are set, false otherwise. */ -INLINE bool upb_msg_all_required_fields_set(void *msg, struct upb_msgdef *m) +INLINE bool upb_msg_all_required_fields_set(struct upb_msg *msg, struct upb_msgdef *m) { int num_fields = m->num_required_fields; int i = 0; while(num_fields > 8) { - if(((uint8_t*)msg)[i++] != 0xFF) return false; + if(msg->data[i++] != 0xFF) return false; num_fields -= 8; } - if(((uint8_t*)msg)[i] != (1 << num_fields) - 1) return false; + if(msg->data[i] != (1 << num_fields) - 1) return false; return true; } /* Clears the set bit for all fields. */ -INLINE void upb_msg_clear(void *msg, struct upb_msgdef *m) +INLINE void upb_msg_clear(struct upb_msg *msg) { - memset(msg, 0, m->set_flags_bytes); + memset(msg->data, 0, msg->def->set_flags_bytes); } /* Number->field and name->field lookup. *************************************/ @@ -230,12 +244,12 @@ INLINE struct upb_msg_fielddef *upb_msg_fieldbyname(struct upb_msgdef *m, * new message data to hold it. If byref is set, strings in the returned * upb_msg will reference s instead of copying from it, but this requires that * s will live for as long as the returned message does. */ -void *upb_msg_parsenew(struct upb_msgdef *m, struct upb_string *s); +struct upb_msg *upb_msg_parsenew(struct upb_msgdef *m, struct upb_string *s); /* This function should be used to free messages that were parsed with * upb_msg_parsenew. It will free the message appropriately (including all * submessages). */ -void upb_msg_free(void *msg, struct upb_msgdef *m); +void upb_msg_free(struct upb_msg *msg); /* Parsing with (re)allocation callbacks. *************************************/ @@ -243,56 +257,52 @@ void upb_msg_free(void *msg, struct upb_msgdef *m); /* This interface parses protocol buffers into upb_msgs, but allows the client * to supply allocation callbacks whenever the parser needs to obtain a string, * array, or submsg (a "dynamic field"). If the parser sees that a dynamic - * field is already present (its "set bit" is set) it will use that, otherwise - * it will call the allocation callback to obtain one. + * field is already present (its "set bit" is set) it will use that, resizing + * it if necessary in the case of an array. Otherwise it will call the + * allocation callback to obtain one. * * This may seem trivial (since nearly all clients will use malloc and free for * memory management), but the allocation callback can be used for more than * just allocation. If we are parsing data into an existing upb_msg, the * allocation callback can examine any existing memory that is allocated for * the dynamic field and determine whether it can reuse it. It can also - * perform memory management like unrefing the existing field or refing the new. + * perform memory management like refing the new field. * * This parser is layered on top of the event-based parser in upb_parse.h. The * parser is upb_mm_msg.h is layered on top of this parser. * * This parser is fully streaming-capable. */ -typedef struct upb_array *(*upb_msg_getarray_cb_t)( - void *msg, struct upb_msgdef *m, - struct upb_array *existingval, struct upb_msg_fielddef *f, - upb_arraylen_t size); +/* Should return an initialized array. */ +typedef struct upb_array *(*upb_msg_getandref_array_cb_t)( + void *from_gptr, struct upb_array *existingval, struct upb_msg_fielddef *f); -/* Callback to allocate a string of size >=len. If len==0 then the client can - * assume that the parser intends to reference the memory instead of copying - * it. */ -typedef struct upb_string *(*upb_msg_getstring_cb_t)( - void *msg, struct upb_msgdef *m, - struct upb_string *existingval, struct upb_msg_fielddef *f, size_t len); +/* Callback to allocate a string. If byref is true, the client should assume + * that the string will be referencing the input data. */ +typedef struct upb_string *(*upb_msg_getandref_string_cb_t)( + void *from_gptr, struct upb_string *existingval, struct upb_msg_fielddef *f, + bool byref); -typedef void *(*upb_msg_getmsg_cb_t)( - void *msg, struct upb_msgdef *m, - void *existingval, struct upb_msg_fielddef *f); +/* Should return a cleared message. */ +typedef struct upb_msg *(*upb_msg_getandref_msg_cb_t)( + void *from_gptr, struct upb_msg *existingval, struct upb_msg_fielddef *f); struct upb_msg_parser_frame { - struct upb_msgdef *m; - void *msg; + struct upb_msg *msg; }; struct upb_msg_parser { struct upb_stream_parser s; bool merge; bool byref; - struct upb_msg *m; struct upb_msg_parser_frame stack[UPB_MAX_NESTING], *top; - upb_msg_getarray_cb_t getarray_cb; - upb_msg_getstring_cb_t getstring_cb; - upb_msg_getmsg_cb_t getmsg_cb; + upb_msg_getandref_array_cb_t getarray_cb; + upb_msg_getandref_string_cb_t getstring_cb; + upb_msg_getandref_msg_cb_t getmsg_cb; }; void upb_msg_parser_reset(struct upb_msg_parser *p, - void *msg, struct upb_msgdef *m, - bool byref); + struct upb_msg *msg, bool byref); /* Parses protocol buffer data out of data which has length of len. The data * need not be a complete protocol buffer. The number of bytes parsed is @@ -347,9 +357,8 @@ upb_status_t upb_msg_serialize(struct upb_msg_serialize_state *s, /* Text dump *****************************************************************/ -bool upb_msg_eql(void *data1, void *data2, struct upb_msgdef *m, bool recursive); -void upb_msg_print(void *data, struct upb_msgdef *m, bool single_line, - FILE *stream); +bool upb_msg_eql(struct upb_msg *msg1, struct upb_msg *msg2, bool recursive); +void upb_msg_print(struct upb_msg *data, bool single_line, FILE *stream); /* Internal functions. ********************************************************/ diff --git a/src/upb_string.c b/src/upb_string.c index bb40a626ff..7754936741 100644 --- a/src/upb_string.c +++ b/src/upb_string.c @@ -14,8 +14,8 @@ bool upb_strreadfile(const char *filename, struct upb_string *data) { long size = ftell(f); if(size < 0) return false; if(fseek(f, 0, SEEK_SET) != 0) return false; - data->ptr = (char*)malloc(size); data->byte_len = size; + upb_stralloc(data, data->byte_len); if(fread(data->ptr, size, 1, f) != 1) { free(data->ptr); return false; diff --git a/src/upb_string.h b/src/upb_string.h index 528c8c8c13..7b63f1c6c5 100644 --- a/src/upb_string.h +++ b/src/upb_string.h @@ -37,6 +37,7 @@ extern "C" { #define INLINE static inline #endif +#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y)) #define UPB_MIN(x, y) ((x) < (y) ? (x) : (y)) struct upb_string { @@ -44,45 +45,80 @@ struct upb_string { * ingrained convention that we follow it. */ char *ptr; uint32_t byte_len; + uint32_t byte_size; /* How many bytes of ptr we own. */ }; +INLINE void upb_strinit(struct upb_string *str) +{ + str->ptr = NULL; + str->byte_len = 0; + str->byte_size = 0; +} + +INLINE void upb_struninit(struct upb_string *str) +{ + if(str->byte_size) free(str->ptr); +} + +INLINE struct upb_string *upb_strnew() +{ + struct upb_string *str = (struct upb_string*)malloc(sizeof(*str)); + upb_strinit(str); + return str; +} + +INLINE void upb_strfree(struct upb_string *str) +{ + upb_struninit(str); + free(str); +} + +INLINE void upb_stralloc(struct upb_string *str, uint32_t size) +{ + if(str->byte_size < size) { + /* Need to resize. */ + str->byte_size = size; + void *oldptr = str->byte_size == 0 ? NULL : str->ptr; + str->ptr = (char*)realloc(oldptr, str->byte_size); + } +} + +INLINE void upb_strdrop(struct upb_string *str) +{ + upb_struninit(str); +} + INLINE bool upb_streql(struct upb_string *s1, struct upb_string *s2) { return s1->byte_len == s2->byte_len && memcmp(s1->ptr, s2->ptr, s1->byte_len) == 0; } -INLINE int upb_strcmp(struct upb_string s1, struct upb_string s2) { - size_t common_length = UPB_MIN(s1.byte_len, s2.byte_len); - int common_diff = memcmp(s1.ptr, s2.ptr, common_length); - if(common_diff == 0) return s1.byte_len - s2.byte_len; - else return common_diff; +INLINE int upb_strcmp(struct upb_string *s1, struct upb_string *s2) { + size_t common_length = UPB_MIN(s1->byte_len, s2->byte_len); + int common_diff = memcmp(s1->ptr, s2->ptr, common_length); + return common_diff == 0 ? (int)s1->byte_len - (int)s2->byte_len : common_diff; } INLINE void upb_strcpy(struct upb_string *dest, struct upb_string *src) { - memcpy(dest->ptr, src->ptr, src->byte_len); dest->byte_len = src->byte_len; + upb_stralloc(dest, dest->byte_len); + memcpy(dest->ptr, src->ptr, src->byte_len); } -INLINE struct upb_string upb_strdup(struct upb_string s) { - struct upb_string copy; - copy.ptr = (char*)malloc(s.byte_len); - copy.byte_len = s.byte_len; - memcpy(copy.ptr, s.ptr, s.byte_len); +INLINE struct upb_string *upb_strdup(struct upb_string *s) { + struct upb_string *copy = upb_strnew(); + upb_strcpy(copy, s); return copy; } -INLINE struct upb_string upb_strdupc(char *s) { - struct upb_string copy; - copy.byte_len = strlen(s); - copy.ptr = (char*)malloc(copy.byte_len); - memcpy(copy.ptr, s, copy.byte_len); +INLINE struct upb_string *upb_strdupc(char *s) { + struct upb_string *copy = upb_strnew(); + copy->byte_len = strlen(s); + upb_stralloc(copy, copy->byte_len); + memcpy(copy->ptr, s, copy->byte_len); return copy; } -INLINE void upb_strfree(struct upb_string s) { - free(s.ptr); -} - /* Reads an entire file into a newly-allocated string. */ bool upb_strreadfile(const char *filename, struct upb_string *data); @@ -95,7 +131,7 @@ bool upb_strreadfile(const char *filename, struct upb_string *data); /* Allows using upb_strings in printf, ie: * struct upb_string str = UPB_STRLIT("Hello, World!\n"); * printf("String is: " UPB_STRFMT, UPB_STRARG(str)); */ -#define UPB_STRARG(str) (str).byte_len, (str).ptr +#define UPB_STRARG(str) (str)->byte_len, (str)->ptr #define UPB_STRFMT "%.*s" #ifdef __cplusplus diff --git a/src/upb_text.c b/src/upb_text.c index 6e1777750e..c9aad7e1b2 100644 --- a/src/upb_text.c +++ b/src/upb_text.c @@ -36,7 +36,7 @@ void upb_text_printval(upb_field_type_t type, union upb_value val, FILE *file) case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_STRING: case GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_BYTES: /* TODO: escaping. */ - fprintf(file, "\"" UPB_STRFMT "\"", UPB_STRARG(*val.str)); break; + fprintf(file, "\"" UPB_STRFMT "\"", UPB_STRARG(val.str)); break; } } @@ -48,7 +48,7 @@ static void print_indent(struct upb_text_printer *p, FILE *stream) } void upb_text_printfield(struct upb_text_printer *p, - struct upb_string name, + struct upb_string *name, upb_field_type_t valtype, union upb_value val, FILE *stream) { @@ -62,7 +62,7 @@ void upb_text_printfield(struct upb_text_printer *p, } void upb_text_push(struct upb_text_printer *p, - struct upb_string submsg_type, + struct upb_string *submsg_type, FILE *stream) { print_indent(p, stream); diff --git a/src/upb_text.h b/src/upb_text.h index f35f8d84d6..32d72784a7 100644 --- a/src/upb_text.h +++ b/src/upb_text.h @@ -23,10 +23,10 @@ INLINE void upb_text_printer_init(struct upb_text_printer *p, bool single_line) p->single_line = single_line; } void upb_text_printval(upb_field_type_t type, union upb_value p, FILE *file); -void upb_text_printfield(struct upb_text_printer *p, struct upb_string name, +void upb_text_printfield(struct upb_text_printer *p, struct upb_string *name, upb_field_type_t valtype, union upb_value val, FILE *stream); -void upb_text_push(struct upb_text_printer *p, struct upb_string submsg_type, +void upb_text_push(struct upb_text_printer *p, struct upb_string *submsg_type, FILE *stream); void upb_text_pop(struct upb_text_printer *p, FILE *stream); diff --git a/tests/test_table.cc b/tests/test_table.cc index f61a85c461..1289fbc30c 100644 --- a/tests/test_table.cc +++ b/tests/test_table.cc @@ -96,7 +96,7 @@ void test_inttable(int32_t *keys, size_t num_entries) upb_inttable_init(&table, num_entries, sizeof(struct inttable_entry)); for(size_t i = 0; i < num_entries; i++) { int32_t key = keys[i]; - largest_key = max(largest_key, key); + largest_key = UPB_MAX((int32_t)largest_key, key); struct inttable_entry e; e.e.key = key; e.value = key*2; diff --git a/tools/upbc.c b/tools/upbc.c index f593ae9c41..f9890c616e 100644 --- a/tools/upbc.c +++ b/tools/upbc.c @@ -5,8 +5,6 @@ * easier to understand, but by its nature it is doing some very "meta" * kinds of things. * - * TODO: compiler currently has memory leaks (trivial to fix with valgrind). - * * Copyright (c) 2009 Joshua Haberman. See LICENSE for details. */ @@ -22,19 +20,19 @@ * the string (and thus never need to re-allocate). */ /* Convert to C identifier: foo.bar.Baz -> foo_bar_Baz. */ -static void to_cident(struct upb_string str) +static void to_cident(struct upb_string *str) { - for(uint32_t i = 0; i < str.byte_len; i++) - if(str.ptr[i] == '.' || str.ptr[i] == '/') - str.ptr[i] = '_'; + for(uint32_t i = 0; i < str->byte_len; i++) + if(str->ptr[i] == '.' || str->ptr[i] == '/') + str->ptr[i] = '_'; } /* Convert to C proprocessor identifier: foo.bar.Baz -> FOO_BAR_BAZ. */ -static void to_preproc(struct upb_string str) +static void to_preproc(struct upb_string *str) { to_cident(str); - for(uint32_t i = 0; i < str.byte_len; i++) - str.ptr[i] = toupper(str.ptr[i]); + for(uint32_t i = 0; i < str->byte_len; i++) + str->ptr[i] = toupper(str->ptr[i]); } static int memrchr(char *data, char c, size_t len) @@ -64,7 +62,7 @@ static void write_h(struct upb_symtab_entry *entries[], int num_entries, char *outfile_name, char *descriptor_cident, FILE *stream) { /* Header file prologue. */ - struct upb_string include_guard_name = upb_strdupc(outfile_name); + struct upb_string *include_guard_name = upb_strdupc(outfile_name); to_preproc(include_guard_name); fputs("/* This file was generated by upbc (the upb compiler). " "Do not edit. */\n\n", stream), @@ -90,21 +88,21 @@ static void write_h(struct upb_symtab_entry *entries[], int num_entries, struct upb_enum *e = entry->ref._enum; google_protobuf_EnumDescriptorProto *ed = e->descriptor; /* We use entry->e.key (the fully qualified name) instead of ed->name. */ - struct upb_string enum_name = upb_strdup(entry->e.key); + struct upb_string *enum_name = upb_strdup(&entry->e.key); to_cident(enum_name); - struct upb_string enum_val_prefix = upb_strdup(entry->e.key); - enum_val_prefix.byte_len = memrchr(enum_val_prefix.ptr, + struct upb_string *enum_val_prefix = upb_strdup(&entry->e.key); + enum_val_prefix->byte_len = memrchr(enum_val_prefix->ptr, UPB_SYMBOL_SEPARATOR, - enum_val_prefix.byte_len); - enum_val_prefix.byte_len++; + enum_val_prefix->byte_len); + enum_val_prefix->byte_len++; to_preproc(enum_val_prefix); fprintf(stream, "typedef enum " UPB_STRFMT " {\n", UPB_STRARG(enum_name)); if(ed->set_flags.has.value) { for(uint32_t j = 0; j < ed->value->len; j++) { /* Foreach enum value. */ google_protobuf_EnumValueDescriptorProto *v = ed->value->elements[j]; - struct upb_string value_name = upb_strdup(*v->name); + struct upb_string *value_name = upb_strdup(v->name); to_preproc(value_name); /* " GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_UINT32 = 13," */ fprintf(stream, " " UPB_STRFMT UPB_STRFMT " = %" PRIu32, @@ -128,7 +126,7 @@ static void write_h(struct upb_symtab_entry *entries[], int num_entries, if(entries[i]->type != UPB_SYM_MESSAGE) continue; struct upb_symtab_entry *entry = entries[i]; /* We use entry->e.key (the fully qualified name). */ - struct upb_string msg_name = upb_strdup(entry->e.key); + struct upb_string *msg_name = upb_strdup(&entry->e.key); to_cident(msg_name); fprintf(stream, "struct " UPB_STRFMT ";\n", UPB_STRARG(msg_name)); fprintf(stream, "typedef struct " UPB_STRFMT "\n " UPB_STRFMT ";\n\n", @@ -143,9 +141,11 @@ static void write_h(struct upb_symtab_entry *entries[], int num_entries, struct upb_symtab_entry *entry = entries[i]; struct upb_msgdef *m = entry->ref.msg; /* We use entry->e.key (the fully qualified name). */ - struct upb_string msg_name = upb_strdup(entry->e.key); + struct upb_string *msg_name = upb_strdup(&entry->e.key); to_cident(msg_name); fprintf(stream, "struct " UPB_STRFMT " {\n", UPB_STRARG(msg_name)); + fputs(" struct upb_msgdef *def;\n", stream); + fputs(" void *gptr;\n", stream); fputs(" union {\n", stream); fprintf(stream, " uint8_t bytes[%" PRIu32 "];\n", m->set_flags_bytes); fputs(" struct {\n", stream); @@ -153,7 +153,7 @@ static void write_h(struct upb_symtab_entry *entries[], int num_entries, static char* labels[] = {"", "optional", "required", "repeated"}; struct google_protobuf_FieldDescriptorProto *fd = m->field_descriptors[j]; fprintf(stream, " bool " UPB_STRFMT ":1; /* = %" PRIu32 ", %s. */\n", - UPB_STRARG(*fd->name), fd->number, labels[fd->label]); + UPB_STRARG(fd->name), fd->number, labels[fd->label]); } fputs(" } has;\n", stream); fputs(" } set_flags;\n", stream); @@ -170,14 +170,14 @@ static void write_h(struct upb_symtab_entry *entries[], int num_entries, type_name_ref.ptr++; type_name_ref.byte_len--; } - struct upb_string type_name = upb_strdup(type_name_ref); + struct upb_string *type_name = upb_strdup(&type_name_ref); to_cident(type_name); if(f->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED) { fprintf(stream, " UPB_MSG_ARRAY(" UPB_STRFMT ")* " UPB_STRFMT ";\n", - UPB_STRARG(type_name), UPB_STRARG(*fd->name)); + UPB_STRARG(type_name), UPB_STRARG(fd->name)); } else { fprintf(stream, " " UPB_STRFMT "* " UPB_STRFMT ";\n", - UPB_STRARG(type_name), UPB_STRARG(*fd->name)); + UPB_STRARG(type_name), UPB_STRARG(fd->name)); } upb_strfree(type_name); } else if(f->label == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_REPEATED) { @@ -193,7 +193,7 @@ static void write_h(struct upb_symtab_entry *entries[], int num_entries, "struct upb_int64_array*" }; fprintf(stream, " %s " UPB_STRFMT ";\n", - c_types[fd->type], UPB_STRARG(*fd->name)); + c_types[fd->type], UPB_STRARG(fd->name)); } else { static char* c_types[] = { "", "double", "float", "int64_t", "uint64_t", "int32_t", "uint64_t", @@ -202,7 +202,7 @@ static void write_h(struct upb_symtab_entry *entries[], int num_entries, "int32_t", "int64_t" }; fprintf(stream, " %s " UPB_STRFMT ";\n", - c_types[fd->type], UPB_STRARG(*fd->name)); + c_types[fd->type], UPB_STRARG(fd->name)); } } fputs("};\n", stream); @@ -230,7 +230,7 @@ struct strtable_entry { struct typetable_entry { struct upb_strtable_entry e; struct upb_msg_fielddef *field; - struct upb_string cident; /* Type name converted with to_cident(). */ + struct upb_string *cident; /* Type name converted with to_cident(). */ /* A list of all values of this type, in an established order. */ union upb_value *values; int values_size, values_len; @@ -251,7 +251,7 @@ struct msgtable_entry { int compare_entries(const void *_e1, const void *_e2) { struct strtable_entry *const*e1 = _e1, *const*e2 = _e2; - return upb_strcmp((*e1)->e.key, (*e2)->e.key); + return upb_strcmp(&(*e1)->e.key, &(*e2)->e.key); } /* Mutually recursive functions to recurse over a set of possibly nested @@ -297,7 +297,6 @@ static void add_strings_from_msg(void *data, struct upb_msgdef *m, * * TODO: make these use a generic msg visitor. */ - struct typetable_entry *get_or_insert_typeentry(struct upb_strtable *t, struct upb_msg_fielddef *f) { @@ -306,7 +305,7 @@ struct typetable_entry *get_or_insert_typeentry(struct upb_strtable *t, struct typetable_entry *type_e = upb_strtable_lookup(t, &type_name); if(type_e == NULL) { struct typetable_entry new_type_e = { - .e = {.key = type_name}, .field = f, .cident = upb_strdup(type_name), + .e = {.key = type_name}, .field = f, .cident = upb_strdup(&type_name), .values = NULL, .values_size = 0, .values_len = 0, .arrays = NULL, .arrays_size = 0, .arrays_len = 0 }; @@ -323,7 +322,7 @@ static void add_value(union upb_value value, struct upb_msg_fielddef *f, { struct typetable_entry *type_e = get_or_insert_typeentry(t, f); if(type_e->values_len == type_e->values_size) { - type_e->values_size = max(type_e->values_size * 2, 4); + type_e->values_size = UPB_MAX(type_e->values_size * 2, 4); type_e->values = realloc(type_e->values, sizeof(*type_e->values) * type_e->values_size); } type_e->values[type_e->values_len++] = value; @@ -343,7 +342,7 @@ static void add_submsgs(void *data, struct upb_msgdef *m, struct upb_strtable *t struct typetable_entry *arr_type_e = get_or_insert_typeentry(t, f); if(arr_type_e->arrays_len == arr_type_e->arrays_size) { - arr_type_e->arrays_size = max(arr_type_e->arrays_size * 2, 4); + arr_type_e->arrays_size = UPB_MAX(arr_type_e->arrays_size * 2, 4); arr_type_e->arrays = realloc(arr_type_e->arrays, sizeof(*arr_type_e->arrays)*arr_type_e->arrays_size); } @@ -492,7 +491,7 @@ static void write_message_c(void *data, struct upb_msgdef *m, for(unsigned int j = 0; j < m->num_fields; j++) { struct upb_msg_fielddef *f = &m->fields[j]; google_protobuf_FieldDescriptorProto *fd = m->field_descriptors[j]; - fprintf(stream, " ." UPB_STRFMT " = ", UPB_STRARG(*fd->name)); + fprintf(stream, " ." UPB_STRFMT " = ", UPB_STRARG(fd->name)); if(upb_msg_isset(msgdata, f)) fprintf(stream, "true"); else @@ -505,7 +504,7 @@ static void write_message_c(void *data, struct upb_msgdef *m, struct upb_msg_fielddef *f = &m->fields[j]; google_protobuf_FieldDescriptorProto *fd = m->field_descriptors[j]; union upb_value val = upb_msg_get(msgdata, f); - fprintf(stream, " ." UPB_STRFMT " = ", UPB_STRARG(*fd->name)); + fprintf(stream, " ." UPB_STRFMT " = ", UPB_STRARG(fd->name)); if(!upb_msg_isset(msgdata, f)) { fputs("0, /* Not set. */", stream); } else if(upb_isstring(f)) { @@ -516,7 +515,7 @@ static void write_message_c(void *data, struct upb_msgdef *m, struct strtable_entry *str_e = upb_strtable_lookup(&strings, val.str); assert(str_e); fprintf(stream, "&strings[%d], /* \"" UPB_STRFMT "\" */", - str_e->num, UPB_STRARG(*val.str)); + str_e->num, UPB_STRARG(val.str)); } } else if(upb_isarray(f)) { /* Find this submessage in the list of msgs for that type. */ @@ -642,15 +641,15 @@ int main(int argc, char *argv[]) if(!outfile_base) outfile_base = input_file; /* Read input file. */ - struct upb_string descriptor; - if(!upb_strreadfile(input_file, &descriptor)) + struct upb_string *descriptor = upb_strnew(); + if(!upb_strreadfile(input_file, descriptor)) error("Couldn't read input file."); /* Parse input file. */ struct upb_context c; upb_context_init(&c); - google_protobuf_FileDescriptorSet *fds = - upb_msg_parsenew(c.fds_msg, &descriptor); + struct upb_msg *fds_msg = upb_msg_parsenew(c.fds_msg, descriptor); + google_protobuf_FileDescriptorSet *fds = (void*)fds_msg; if(!fds) error("Failed to parse input file descriptor."); if(!upb_context_addfds(&c, fds)) @@ -686,7 +685,7 @@ int main(int argc, char *argv[]) write_message_c(fds, c.fds_msg, cident, h_filename, argc, argv, input_file, c_file); fclose(c_file); } - upb_msg_free(fds, c.fds_msg); + upb_msg_free(fds_msg); upb_context_free(&c); upb_strfree(descriptor); fclose(h_file);