diff options
-rw-r--r-- | tests/test.proto | 19 | ||||
-rw-r--r-- | tests/test.proto.pb | bin | 353 -> 652 bytes | |||
-rw-r--r-- | upb/descriptor/reader.c | 68 |
3 files changed, 86 insertions, 1 deletions
diff --git a/tests/test.proto b/tests/test.proto index 40e185b..e790cbf 100644 --- a/tests/test.proto +++ b/tests/test.proto @@ -6,6 +6,8 @@ // ^ |`---|--------^ // +----------+----+ F +syntax = "proto2"; + message A { optional B b = 1; } @@ -46,4 +48,21 @@ message SimplePrimitives { optional sint32 i32 = 7; optional bool b = 8; optional string str = 9; + + oneof foo { + int32 oneof_int32 = 10; + string oneof_string = 11; + } + + oneof bar { + int64 oneof_int64 = 13; + bytes oneof_bytes = 14; + } + + message Nested { + oneof foo { + int32 oneof_int32 = 10; + string b = 11; + } + } } diff --git a/tests/test.proto.pb b/tests/test.proto.pb Binary files differindex 9fc835a..a587fb1 100644 --- a/tests/test.proto.pb +++ b/tests/test.proto.pb 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; |