From 074a050bb10d9f132c6612260c086e2eb07061b9 Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Thu, 8 Sep 2016 19:07:23 -0700 Subject: Added support for loading oneofs from descriptors. --- upb/descriptor/reader.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 1 deletion(-) (limited to 'upb/descriptor/reader.c') diff --git a/upb/descriptor/reader.c b/upb/descriptor/reader.c index 82fd574..be3eed8 100644 --- a/upb/descriptor/reader.c +++ b/upb/descriptor/reader.c @@ -29,6 +29,8 @@ typedef struct { /* Index of the first def that is under this scope. For msgdefs, the * msgdef itself is at start-1. */ int start; + uint32_t oneof_start; + uint32_t oneof_index; } upb_descreader_frame; /* The maximum number of nested declarations that are allowed, ie. @@ -49,6 +51,7 @@ struct upb_descreader { upb_filedef *file; /* The last file in files. */ upb_descreader_frame stack[UPB_MAX_MESSAGE_NESTING]; int stack_len; + upb_inttable oneofs; uint32_t number; char *name; @@ -126,16 +129,27 @@ static upb_def *upb_descreader_last(upb_descreader *r) { void upb_descreader_startcontainer(upb_descreader *r) { upb_descreader_frame *f = &r->stack[r->stack_len++]; f->start = upb_filedef_defcount(r->file); + f->oneof_start = upb_inttable_count(&r->oneofs); + f->oneof_index = 0; f->name = NULL; } bool upb_descreader_endcontainer(upb_descreader *r) { - upb_descreader_frame *f = &r->stack[--r->stack_len]; + upb_descreader_frame *f = &r->stack[r->stack_len - 1]; + + while (upb_inttable_count(&r->oneofs) > f->oneof_start) { + upb_oneofdef *o = upb_value_getptr(upb_inttable_pop(&r->oneofs)); + bool ok = upb_msgdef_addoneof(upb_descreader_top(r), o, &r->oneofs, NULL); + UPB_ASSERT(ok); + } + if (!upb_descreader_qualify(r->file, f->name, f->start)) { return false; } upb_gfree(f->name); f->name = NULL; + + r->stack_len--; return true; } @@ -145,6 +159,23 @@ void upb_descreader_setscopename(upb_descreader *r, char *str) { f->name = str; } +static upb_oneofdef *upb_descreader_getoneof(upb_descreader *r, + uint32_t index) { + bool found; + upb_value val; + upb_descreader_frame *f = &r->stack[r->stack_len-1]; + + index += f->oneof_start; + + while (upb_inttable_count(&r->oneofs) <= index) { + upb_inttable_push(&r->oneofs, upb_value_ptr(upb_oneofdef_new(&r->oneofs))); + } + + found = upb_inttable_lookup(&r->oneofs, index, &val); + UPB_ASSERT(found); + return upb_value_getptr(val); +} + /** Handlers for google.protobuf.FileDescriptorSet. ***************************/ static void *fileset_startfile(void *closure, const void *hd) { @@ -536,6 +567,35 @@ static size_t field_ondefaultval(void *closure, const void *hd, const char *buf, return n; } +static bool field_ononeofindex(void *closure, const void *hd, int32_t index) { + upb_descreader *r = closure; + upb_oneofdef *o = upb_descreader_getoneof(r, index); + bool ok; + UPB_UNUSED(hd); + + ok = upb_oneofdef_addfield(o, r->f, NULL, NULL); + UPB_ASSERT(ok); + return true; +} + +/** Handlers for google.protobuf.OneofDescriptorProto. ************************/ + +static size_t oneof_name(void *closure, const void *hd, const char *buf, + size_t n, const upb_bufhandle *handle) { + upb_descreader *r = closure; + upb_descreader_frame *f = &r->stack[r->stack_len-1]; + upb_oneofdef *o = upb_descreader_getoneof(r, f->oneof_index++); + bool ok; + char *name_null_terminated = upb_strndup(buf, n); + UPB_UNUSED(hd); + UPB_UNUSED(handle); + + ok = upb_oneofdef_setname(o, name_null_terminated, NULL); + UPB_ASSERT(ok); + free(name_null_terminated); + return n; +} + /** Handlers for google.protobuf.DescriptorProto ******************************/ static bool msg_start(void *closure, const void *hd) { @@ -687,6 +747,10 @@ static void reghandlers(const void *closure, upb_handlers *h) { &field_onextendee, NULL); upb_handlers_setstring(h, F(FieldDescriptorProto, default_value), &field_ondefaultval, NULL); + upb_handlers_setint32(h, F(FieldDescriptorProto, oneof_index), + &field_ononeofindex, NULL); + } else if (upbdefs_google_protobuf_OneofDescriptorProto_is(m)) { + upb_handlers_setstring(h, F(OneofDescriptorProto, name), &oneof_name, NULL); } else if (upbdefs_google_protobuf_FieldOptions_is(m)) { upb_handlers_setbool(h, F(FieldOptions, lazy), &field_onlazy, NULL); upb_handlers_setbool(h, F(FieldOptions, packed), &field_onpacked, NULL); @@ -709,6 +773,7 @@ void descreader_cleanup(void *_r) { upb_gfree(r->name); upb_inttable_uninit(&r->files); + upb_inttable_uninit(&r->oneofs); upb_gfree(r->default_string); while (r->stack_len > 0) { upb_descreader_frame *f = &r->stack[--r->stack_len]; @@ -726,6 +791,7 @@ upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h) { } upb_inttable_init(&r->files, UPB_CTYPE_PTR); + upb_inttable_init(&r->oneofs, UPB_CTYPE_PTR); upb_sink_reset(upb_descreader_input(r), h, r); r->stack_len = 0; r->name = NULL; -- cgit v1.2.3 From bb872be0c0e40a25b7529bce98643688a85b612e Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Fri, 9 Sep 2016 14:23:16 -0700 Subject: Addressed CR comments: simplify slightly. --- upb/descriptor/reader.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'upb/descriptor/reader.c') diff --git a/upb/descriptor/reader.c b/upb/descriptor/reader.c index be3eed8..4164bc7 100644 --- a/upb/descriptor/reader.c +++ b/upb/descriptor/reader.c @@ -570,10 +570,9 @@ static size_t field_ondefaultval(void *closure, const void *hd, const char *buf, static bool field_ononeofindex(void *closure, const void *hd, int32_t index) { upb_descreader *r = closure; upb_oneofdef *o = upb_descreader_getoneof(r, index); - bool ok; + bool ok = upb_oneofdef_addfield(o, r->f, NULL, NULL); UPB_UNUSED(hd); - ok = upb_oneofdef_addfield(o, r->f, NULL, NULL); UPB_ASSERT(ok); return true; } @@ -585,12 +584,11 @@ static size_t oneof_name(void *closure, const void *hd, const char *buf, upb_descreader *r = closure; upb_descreader_frame *f = &r->stack[r->stack_len-1]; upb_oneofdef *o = upb_descreader_getoneof(r, f->oneof_index++); - bool ok; char *name_null_terminated = upb_strndup(buf, n); + bool ok = upb_oneofdef_setname(o, name_null_terminated, NULL); UPB_UNUSED(hd); UPB_UNUSED(handle); - ok = upb_oneofdef_setname(o, name_null_terminated, NULL); UPB_ASSERT(ok); free(name_null_terminated); return n; -- cgit v1.2.3 From c387d372ee42d338ca03d91112370c532c6bc574 Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Fri, 9 Sep 2016 14:54:15 -0700 Subject: Added descriptive comment about descriptor nesting. --- upb/descriptor/reader.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'upb/descriptor/reader.c') diff --git a/upb/descriptor/reader.c b/upb/descriptor/reader.c index 4164bc7..b515840 100644 --- a/upb/descriptor/reader.c +++ b/upb/descriptor/reader.c @@ -165,6 +165,9 @@ static upb_oneofdef *upb_descreader_getoneof(upb_descreader *r, upb_value val; upb_descreader_frame *f = &r->stack[r->stack_len-1]; + /* DescriptorProto messages can be nested, so we will see the nested messages + * between when we see the FieldDescriptorProto and the OneofDescriptorProto. + * We need to preserve the oneofs in between these two things. */ index += f->oneof_start; while (upb_inttable_count(&r->oneofs) <= index) { -- cgit v1.2.3