From 87a18f37743efde6f66f77209c98400cdec67cbe Mon Sep 17 00:00:00 2001 From: Chris Fallin Date: Wed, 14 Jan 2015 11:18:20 -0800 Subject: [PATCH] Support oneof defs in upb. This change adds support for a OneofDef (upb_oneofdef), which represents a 'oneof' as introduced by Protocol Buffers. This is semantically a union type that contains fields and in turn may be added to a MessageDef. This change does not alter parsing or the handler abstraction in any way, because a oneof has impact only at a higher semantic level (i.e., any sort of storage of the fields in a message object), which is user-specific with respect to upb. --- tests/bindings/googlepb/test_vs_proto2.cc | 4 +- tests/test_cpp.cc | 102 +++- tests/test_def.c | 57 +- upb/bindings/googlepb/bridge.cc | 3 +- upb/bindings/lua/upb.c | 29 +- upb/bindings/python/upb.c | 41 +- upb/bindings/ruby/upb.c | 39 +- upb/def.c | 409 ++++++++++++-- upb/def.h | 632 ++++++++++++++++++++-- upb/handlers.c | 18 +- upb/json/printer.c | 6 +- upb/pb/compile_decoder.c | 14 +- upb/pb/encoder.c | 6 +- upb/pb/textprinter.c | 6 +- upb/symtab.c | 12 +- upb/table.int.h | 3 + 16 files changed, 1230 insertions(+), 151 deletions(-) diff --git a/tests/bindings/googlepb/test_vs_proto2.cc b/tests/bindings/googlepb/test_vs_proto2.cc index c89339ae6b..49dfe49c05 100644 --- a/tests/bindings/googlepb/test_vs_proto2.cc +++ b/tests/bindings/googlepb/test_vs_proto2.cc @@ -40,8 +40,8 @@ const unsigned char message2_data[] = { void compare_metadata(const google::protobuf::Descriptor* d, const upb::MessageDef *upb_md) { ASSERT(d->field_count() == upb_md->field_count()); - for (upb::MessageDef::const_iterator i = upb_md->begin(); i != upb_md->end(); - ++i) { + for (upb::MessageDef::const_field_iterator i = upb_md->field_begin(); + i != upb_md->field_end(); ++i) { const upb::FieldDef* upb_f = *i; const google::protobuf::FieldDescriptor *proto2_f = d->FindFieldByNumber(upb_f->number()); diff --git a/tests/test_cpp.cc b/tests/test_cpp.cc index 55bb4b390b..71f354ceaa 100644 --- a/tests/test_cpp.cc +++ b/tests/test_cpp.cc @@ -12,6 +12,7 @@ #include #include +#include #include "upb/def.h" #include "upb/descriptor/reader.h" @@ -164,7 +165,7 @@ static void TestSymbolTable(const char *descriptor_file) { #ifdef UPB_CXX11 // Test range-based for. std::set fielddefs; - for (const upb::FieldDef* f : *md.get()) { + for (const upb::FieldDef* f : md.get()->fields()) { AssertInsert(&fielddefs, f); ASSERT(f->containing_type() == md.get()); } @@ -1117,6 +1118,103 @@ void TestHandlerDataDestruction() { ASSERT(x == 0); } +void TestOneofs() { + upb::Status status; + upb::reffed_ptr md(upb::MessageDef::New()); + upb::reffed_ptr o(upb::OneofDef::New()); + + o->set_name("test_oneof", &status); + ASSERT(status.ok()); + + for (int i = 0; i < 5; i++) { + std::ostringstream fieldname; + fieldname << "field_" << i; + upb::reffed_ptr f(upb::FieldDef::New()); + f->set_name(fieldname.str(), &status); + ASSERT(status.ok()); + f->set_type(UPB_TYPE_INT32); + f->set_number(i + 1, &status); + ASSERT(status.ok()); + f->set_label(UPB_LABEL_OPTIONAL); + + o->AddField(f.get(), &status); + ASSERT(status.ok()); + } + + md->AddOneof(o.get(), &status); + ASSERT(status.ok()); + + int field_count = 0; + for (upb::OneofDef::iterator it = o->begin(); it != o->end(); ++it) { + upb::FieldDef* f = *it; + ASSERT(f->type() == UPB_TYPE_INT32); + field_count++; + } + ASSERT(field_count == 5); + + upb::MessageDef::oneof_iterator msg_it = md->oneof_begin(); + ASSERT(msg_it != md->oneof_end()); + ASSERT((*msg_it) == o.get()); + +#ifdef UPB_CXX11 + // Test range-based for on both fields and oneofs (with the iterator adaptor). + field_count = 0; + for (auto* field : md->fields()) { + UPB_UNUSED(field); + field_count++; + } + ASSERT(field_count == 5); + + int oneof_count = 0; + for (auto* oneof : md->oneofs()) { + UPB_UNUSED(oneof); + oneof_count++; + } + ASSERT(oneof_count == 1); +#endif // UPB_CXX11 + + // Test that we can add a new field to the oneof and that it becomes a member + // of the msgdef as well. + upb::reffed_ptr newf(upb::FieldDef::New()); + newf->set_name("new_field_10", &status); + ASSERT(status.ok()); + newf->set_number(10, &status); + ASSERT(status.ok()); + newf->set_label(UPB_LABEL_OPTIONAL); + newf->set_type(UPB_TYPE_INT32); + o->AddField(newf.get(), &status); + ASSERT(status.ok()); + ASSERT(newf->containing_type() == md.get()); + + // Test that we can add a new field to the msgdef first and then to the oneof. + upb::reffed_ptr newf2(upb::FieldDef::New()); + newf2->set_name("new_field_11", &status); + ASSERT(status.ok()); + newf2->set_number(11, &status); + ASSERT(status.ok()); + newf2->set_label(UPB_LABEL_OPTIONAL); + newf2->set_type(UPB_TYPE_INT32); + md->AddField(newf2.get(), &status); + ASSERT(status.ok()); + o->AddField(newf2.get(), &status); + ASSERT(status.ok()); + ASSERT(newf2->containing_oneof() == o.get()); + + // Test that we cannot add REQUIRED or REPEATED fields to the oneof. + upb::reffed_ptr newf3(upb::FieldDef::New()); + newf3->set_name("new_field_12", &status); + ASSERT(status.ok()); + newf3->set_number(12, &status); + ASSERT(status.ok()); + newf3->set_label(UPB_LABEL_REQUIRED); + newf3->set_type(UPB_TYPE_INT32); + o->AddField(newf3.get(), &status); + ASSERT(!status.ok()); + newf->set_label(UPB_LABEL_REPEATED); + o->AddField(newf3.get(), &status); + ASSERT(!status.ok()); +} + extern "C" { int run_tests(int argc, char *argv[]) { @@ -1173,6 +1271,8 @@ int run_tests(int argc, char *argv[]) { TestHandlerDataDestruction(); + TestOneofs(); + return 0; } diff --git a/tests/test_def.c b/tests/test_def.c index dcf80c05ec..b85b0317d6 100644 --- a/tests/test_def.c +++ b/tests/test_def.c @@ -189,7 +189,9 @@ static upb_fielddef *newfield( ASSERT(upb_fielddef_setnumber(f, num, NULL)); upb_fielddef_settype(f, type); upb_fielddef_setlabel(f, label); - ASSERT(upb_fielddef_setsubdefname(f, type_name, NULL)); + if (type_name) { + ASSERT(upb_fielddef_setsubdefname(f, type_name, NULL)); + } return f; } @@ -342,6 +344,58 @@ static void test_descriptor_flags() { upb_msgdef_unref(m2, &m2); } +static void test_oneofs() { + upb_status s = UPB_STATUS_INIT; + bool ok = true; + + upb_symtab *symtab = upb_symtab_new(&symtab); + ASSERT(symtab != NULL); + + // Create a test message for fields to refer to. + upb_msgdef *subm = upb_msgdef_newnamed("SubMessage", &symtab); + upb_msgdef_addfield(subm, newfield("field1", 1, UPB_TYPE_INT32, + UPB_LABEL_OPTIONAL, NULL, &symtab), + &symtab, NULL); + upb_def *subm_defs[] = {UPB_UPCAST(subm)}; + ASSERT_STATUS(upb_symtab_add(symtab, subm_defs, 1, &symtab, &s), &s); + + upb_msgdef *m = upb_msgdef_newnamed("TestMessage", &symtab); + ASSERT(upb_msgdef_numoneofs(m) == 0); + + upb_oneofdef *o = upb_oneofdef_new(&o); + ASSERT(upb_oneofdef_numfields(o) == 0); + ASSERT(upb_oneofdef_name(o) == NULL); + + ok = upb_oneofdef_setname(o, "test_oneof", &s); + ASSERT_STATUS(ok, &s); + + ok = upb_oneofdef_addfield(o, newfield("field1", 1, UPB_TYPE_INT32, + UPB_LABEL_OPTIONAL, NULL, &symtab), + &symtab, NULL); + ASSERT_STATUS(ok, &s); + ok = upb_oneofdef_addfield(o, newfield("field2", 2, UPB_TYPE_MESSAGE, + UPB_LABEL_OPTIONAL, ".SubMessage", + &symtab), + &symtab, NULL); + ASSERT_STATUS(ok, &s); + + ok = upb_msgdef_addoneof(m, o, NULL, &s); + ASSERT_STATUS(ok, &s); + + upb_def *defs[] = {UPB_UPCAST(m)}; + ASSERT_STATUS(upb_symtab_add(symtab, defs, 1, &symtab, &s), &s); + + ASSERT(upb_msgdef_numoneofs(m) == 1); + const upb_oneofdef *lookup_o = upb_msgdef_ntooz(m, "test_oneof"); + ASSERT(lookup_o == o); + + const upb_fielddef *lookup_field = upb_oneofdef_ntofz(o, "field1"); + ASSERT(lookup_field != NULL && upb_fielddef_number(lookup_field) == 1); + + upb_symtab_unref(symtab, &symtab); + upb_oneofdef_unref(o, &o); +} + int run_tests(int argc, char *argv[]) { if (argc < 2) { fprintf(stderr, "Usage: test_def \n"); @@ -358,5 +412,6 @@ int run_tests(int argc, char *argv[]) { test_partial_freeze(); test_noreftracking(); test_descriptor_flags(); + test_oneofs(); return 0; } diff --git a/upb/bindings/googlepb/bridge.cc b/upb/bindings/googlepb/bridge.cc index 6ae8868e4f..2a2bbbfc4d 100644 --- a/upb/bindings/googlepb/bridge.cc +++ b/upb/bindings/googlepb/bridge.cc @@ -246,7 +246,8 @@ const Handlers* CodeCache::GetMaybeUnfrozenWriteHandlers( to_freeze_.push_back(h); const goog::Descriptor* d = m.GetDescriptor(); - for (upb::MessageDef::const_iterator i = md->begin(); i != md->end(); ++i) { + for (upb::MessageDef::const_field_iterator i = md->field_begin(); + i != md->field_end(); ++i) { const FieldDef* upb_f = *i; const goog::FieldDescriptor* proto2_f = diff --git a/upb/bindings/lua/upb.c b/upb/bindings/lua/upb.c index 17fc0a865c..5ad0235cec 100644 --- a/upb/bindings/lua/upb.c +++ b/upb/bindings/lua/upb.c @@ -139,7 +139,8 @@ bool lupb_openlib(lua_State *L, void *ptr, const char *name, // Pushes a new userdata with the given metatable and ensures that it has a // uservalue. -static void *newudata_with_userval(lua_State *L, size_t size, const char *type) { +static void *newudata_with_userval(lua_State *L, size_t size, + const char *type) { void *ret = lua_newuserdata(L, size); // Set metatable. @@ -952,17 +953,17 @@ static int lupb_msgdef_field(lua_State *L) { } static int lupb_msgiter_next(lua_State *L) { - upb_msg_iter *i = lua_touserdata(L, lua_upvalueindex(1)); - if (upb_msg_done(i)) return 0; + upb_msg_field_iter *i = lua_touserdata(L, lua_upvalueindex(1)); + if (upb_msg_field_done(i)) return 0; lupb_def_pushwrapper(L, UPB_UPCAST(upb_msg_iter_field(i)), NULL); - upb_msg_next(i); + upb_msg_field_next(i); return 1; } static int lupb_msgdef_fields(lua_State *L) { const upb_msgdef *m = lupb_msgdef_check(L, 1); - upb_msg_iter *i = lua_newuserdata(L, sizeof(upb_msg_iter)); - upb_msg_begin(i, m); + upb_msg_field_iter *i = lua_newuserdata(L, sizeof(upb_msg_field_iter)); + upb_msg_field_begin(i, m); // Need to guarantee that the msgdef outlives the iter. lua_pushvalue(L, 1); lua_pushcclosure(L, &lupb_msgiter_next, 2); @@ -1416,8 +1417,10 @@ static lupb_msgdef *lupb_msg_assignoffsets(lua_State *L, int narg) { size_t userval_idx = 1; // Assign offsets. - upb_msg_iter i; - for (upb_msg_begin(&i, lmd->md); !upb_msg_done(&i); upb_msg_next(&i)) { + upb_msg_field_iter i; + for (upb_msg_field_begin(&i, lmd->md); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); if (in_userval(f)) { offsets[upb_fielddef_index(f)] = userval_idx++; @@ -1442,7 +1445,9 @@ static lupb_msgdef *lupb_msg_assignoffsets(lua_State *L, int narg) { lua_newtable(L); // This will be our userval. int idx = 1; - for (upb_msg_begin(&i, lmd->md); !upb_msg_done(&i); upb_msg_next(&i)) { + for (upb_msg_field_begin(&i, lmd->md); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE) { bool created = lupb_def_pushwrapper(L, upb_fielddef_subdef(f), NULL); @@ -1660,9 +1665,9 @@ void callback(const void *closure, upb_handlers *h) { lua_State *L = (lua_State*)closure; lupb_def_pushwrapper(L, UPB_UPCAST(upb_handlers_msgdef(h)), NULL); lupb_msgdef *lmd = lupb_msg_assignoffsets(L, -1); - upb_msg_iter i; - upb_msg_begin(&i, upb_handlers_msgdef(h)); - for (; !upb_msg_done(&i); upb_msg_next(&i)) { + upb_msg_field_iter i; + upb_msg_field_begin(&i, upb_handlers_msgdef(h)); + for (; !upb_msg_field_done(&i); upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); int hasbit = upb_fielddef_index(f); uint16_t ofs = lmd->field_offsets[upb_fielddef_index(f)]; diff --git a/upb/bindings/python/upb.c b/upb/bindings/python/upb.c index 497074b5c9..6cfc8e9a0d 100644 --- a/upb/bindings/python/upb.c +++ b/upb/bindings/python/upb.c @@ -298,7 +298,8 @@ static PyObject *PyUpb_MessageDef_new(PyTypeObject *subtype, static PyObject *PyUpb_MessageDef_add_fields(PyObject *o, PyObject *args); -static int PyUpb_MessageDef_init(PyObject *self, PyObject *args, PyObject *kwds) { +static int PyUpb_MessageDef_init( + PyObject *self, PyObject *args, PyObject *kwds) { if (!kwds) return 0; PyObject *key, *value; Py_ssize_t pos = 0; @@ -323,7 +324,8 @@ static PyObject *PyUpb_MessageDef_getattro(PyObject *obj, PyObject *attr_name) { return PyObject_GenericGetAttr(obj, attr_name); } -static int PyUpb_MessageDef_setattro(PyObject *o, PyObject *key, PyObject *val) { +static int PyUpb_MessageDef_setattro( + PyObject *o, PyObject *key, PyObject *val) { upb_msgdef *m = Check_MessageDef(o, -1); if (!upb_def_ismutable(UPB_UPCAST(m))) { PyErr_SetString(PyExc_TypeError, "MessageDef is not mutable."); @@ -343,9 +345,11 @@ static int PyUpb_MessageDef_setattro(PyObject *o, PyObject *key, PyObject *val) static PyObject *PyUpb_MessageDef_fields(PyObject *obj, PyObject *args) { upb_msgdef *m = Check_MessageDef(obj, NULL); PyObject *ret = PyList_New(0); - upb_msg_iter i; - for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) { - upb_fielddef *f = upb_msg_iter_field(i); + upb_msg_field_iter i; + for(upb_msg_field_begin(&i, m); + !upb_msg_field_done(&i); + upb_msg_field_next(&ii)) { + upb_fielddef *f = upb_msg_iter_field(&i); PyList_Append(ret, PyUpb_FieldDef_GetOrCreate(f)); } return ret; @@ -374,9 +378,12 @@ static PyObject *PyUpb_MessageDef_add_field(PyObject *o, PyObject *field) { } static PyMethodDef PyUpb_MessageDef_methods[] = { - {"add_field", &PyUpb_MessageDef_add_field, METH_O, "Adds a list of fields."}, - {"add_fields", &PyUpb_MessageDef_add_fields, METH_O, "Adds a list of fields."}, - {"fields", &PyUpb_MessageDef_fields, METH_NOARGS, "Returns list of fields."}, + {"add_field", &PyUpb_MessageDef_add_field, METH_O, + "Adds a list of fields."}, + {"add_fields", &PyUpb_MessageDef_add_fields, METH_O, + "Adds a list of fields."}, + {"fields", &PyUpb_MessageDef_fields, METH_NOARGS, + "Returns list of fields."}, {NULL, NULL} }; @@ -448,7 +455,8 @@ static PyObject *PyUpb_SymbolTable_new(PyTypeObject *subtype, return PyUpb_ObjCacheGet(upb_symtab_new(), subtype); } -static int PyUpb_SymbolTable_init(PyObject *self, PyObject *args, PyObject *kwds) { +static int PyUpb_SymbolTable_init( + PyObject *self, PyObject *args, PyObject *kwds) { return 0; } @@ -475,8 +483,10 @@ static PyObject *PyUpb_SymbolTable_add_defs(PyObject *o, PyObject *defs) { cdefs[i++] = def; upb_msgdef *md = upb_dyncast_msgdef(def); if (!md) continue; - upb_msg_iter j; - for(j = upb_msg_begin(md); !upb_msg_done(j); j = upb_msg_next(md, j)) { + upb_msg_field_iter j; + for(upb_msg_field_begin(&j, md); + !upb_msg_field_done(&j); + upb_msg_field_next(&j)) { upb_fielddef *f = upb_msg_iter_field(j); upb_fielddef_setaccessor(f, PyUpb_AccessorForField(f)); } @@ -601,7 +611,8 @@ static upb_sflow_t PyUpb_Message_StartSubmessage(void *m, upb_value fval) { return UPB_CONTINUE_WITH(*submsg); } -static upb_sflow_t PyUpb_Message_StartRepeatedSubmessage(void *a, upb_value fval) { +static upb_sflow_t PyUpb_Message_StartRepeatedSubmessage( + void *a, upb_value fval) { (void)fval; PyObject **elem = upb_stdarray_append(a, sizeof(void*)); PyTypeObject *type = ((PyUpb_MessageType*)Py_TYPE(a))->alt_type; @@ -609,7 +620,8 @@ static upb_sflow_t PyUpb_Message_StartRepeatedSubmessage(void *a, upb_value fval return UPB_CONTINUE_WITH(*elem); } -static upb_flow_t PyUpb_Message_StringValue(void *m, upb_value fval, upb_value val) { +static upb_flow_t PyUpb_Message_StringValue( + void *m, upb_value fval, upb_value val) { PyObject **str = PyUpb_Accessor_GetPtr(m, fval); if (*str) { Py_DECREF(*str); } *str = PyString_FromStringAndSize(NULL, upb_value_getstrref(val)->len); @@ -618,7 +630,8 @@ static upb_flow_t PyUpb_Message_StringValue(void *m, upb_value fval, upb_value v return UPB_CONTINUE; } -static upb_flow_t PyUpb_Message_AppendStringValue(void *a, upb_value fval, upb_value val) { +static upb_flow_t PyUpb_Message_AppendStringValue( + void *a, upb_value fval, upb_value val) { (void)fval; PyObject **elem = upb_stdarray_append(a, sizeof(void*)); *elem = PyString_FromStringAndSize(NULL, upb_value_getstrref(val)->len); diff --git a/upb/bindings/ruby/upb.c b/upb/bindings/ruby/upb.c index 2817a158f7..961836692d 100644 --- a/upb/bindings/ruby/upb.c +++ b/upb/bindings/ruby/upb.c @@ -273,9 +273,11 @@ static size_t rupb_sizeof(const upb_fielddef *f) { static void assign_offsets(rb_msglayout *layout, const upb_msgdef *md) { layout->field_offsets = ALLOC_N(uint32_t, upb_msgdef_numfields(md)); size_t ofs = 0; - upb_msg_iter i; + upb_msg_field_iter i; - for (upb_msg_begin(&i, md); !upb_msg_done(&i); upb_msg_next(&i)) { + for (upb_msg_field_begin(&i, md); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { const upb_fielddef *f = upb_msg_iter_field(&i); size_t field_size = rupb_sizeof(f); @@ -301,8 +303,10 @@ static void make_prototype(rb_msglayout *layout, const upb_msgdef *md) { // more specific initialization. memset(prototype, 0, layout->size); - upb_msg_iter i; - for (upb_msg_begin(&i, md); !upb_msg_done(&i); upb_msg_next(&i)) { + upb_msg_field_iter i; + for (upb_msg_field_begin(&i, md); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { const upb_fielddef *f = upb_msg_iter_field(&i); if (is_ruby_value(f)) { size_t ofs = layout->field_offsets[upb_fielddef_index(f)]; @@ -373,8 +377,10 @@ static void msgdef_mark(void *_rmd) { rb_gc_mark(rmd->klass); // Mark all submessage types. - upb_msg_iter i; - for (upb_msg_begin(&i, rmd->md); !upb_msg_done(&i); upb_msg_next(&i)) { + upb_msg_field_iter i; + for (upb_msg_field_begin(&i, rmd->md); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); if (upb_fielddef_issubmsg(f)) { // If we were trying to be more aggressively lazy, the submessage might @@ -495,8 +501,10 @@ static void msg_mark(void *p) { // We need to mark all references to other Ruby values: strings, arrays, and // submessages that we point to. - upb_msg_iter i; - for (upb_msg_begin(&i, rmd->md); !upb_msg_done(&i); upb_msg_next(&i)) { + upb_msg_field_iter i; + for (upb_msg_field_begin(&i, rmd->md); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); if (is_ruby_value(f)) { size_t ofs = rmd->layout.field_offsets[upb_fielddef_index(f)]; @@ -903,7 +911,8 @@ static void *submsg_handler(void *closure, const void *hd) { const submsg_handlerdata_t *submsgdata = hd; if (DEREF(msg, submsgdata->ofs, VALUE) == Qnil) { - DEREF(msg, submsgdata->ofs, VALUE) = msg_new(msgdef_getwrapper(submsgdata->md)); + DEREF(msg, submsgdata->ofs, VALUE) = + msg_new(msgdef_getwrapper(submsgdata->md)); } VALUE submsg = DEREF(msg, submsgdata->ofs, VALUE); @@ -912,9 +921,11 @@ static void *submsg_handler(void *closure, const void *hd) { static void add_handlers_for_message(const void *closure, upb_handlers *h) { const rupb_MessageDef *rmd = get_rbmsgdef(upb_handlers_msgdef(h)); - upb_msg_iter i; + upb_msg_field_iter i; - for (upb_msg_begin(&i, rmd->md); !upb_msg_done(&i); upb_msg_next(&i)) { + for (upb_msg_field_begin(&i, rmd->md); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { const upb_fielddef *f = upb_msg_iter_field(&i); size_t ofs = rmd->layout.field_offsets[upb_fielddef_index(f)]; @@ -1085,8 +1096,10 @@ static void putmsg(rupb_Message *msg, const rupb_MessageDef *rmd, upb_sink *sink) { upb_sink_startmsg(sink); - upb_msg_iter i; - for (upb_msg_begin(&i, rmd->md); !upb_msg_done(&i); upb_msg_next(&i)) { + upb_msg_field_iter i; + for (upb_msg_field_begin(&i, rmd->md); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); uint32_t ofs = rmd->layout.field_offsets[upb_fielddef_index(f)]; diff --git a/upb/def.c b/upb/def.c index 349dfd5b3f..3dba2215dc 100644 --- a/upb/def.c +++ b/upb/def.c @@ -248,10 +248,12 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { upb_fielddef **fields = malloc(n * sizeof(*fields)); if (!fields) return false; - upb_msg_iter j; + upb_msg_field_iter j; int i; m->submsg_field_count = 0; - for(i = 0, upb_msg_begin(&j, m); !upb_msg_done(&j); upb_msg_next(&j), i++) { + for(i = 0, upb_msg_field_begin(&j, m); + !upb_msg_field_done(&j); + upb_msg_field_next(&j), i++) { upb_fielddef *f = upb_msg_iter_field(&j); assert(f->msg.def == m); if (!upb_validate_field(f, s)) { @@ -287,7 +289,9 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { upb_selector_t sel; upb_inttable_insert(&t, UPB_STARTMSG_SELECTOR, v); upb_inttable_insert(&t, UPB_ENDMSG_SELECTOR, v); - for(upb_msg_begin(&j, m); !upb_msg_done(&j); upb_msg_next(&j)) { + for(upb_msg_field_begin(&j, m); + !upb_msg_field_done(&j); + upb_msg_field_next(&j)) { upb_fielddef *f = upb_msg_iter_field(&j); // These calls will assert-fail in upb_table if the value already exists. TRY(UPB_HANDLER_INT32); @@ -545,6 +549,9 @@ static void visitfield(const upb_refcounted *r, upb_refcounted_visit *visit, if (upb_fielddef_containingtype(f)) { visit(r, UPB_UPCAST2(upb_fielddef_containingtype(f)), closure); } + if (upb_fielddef_containingoneof(f)) { + visit(r, UPB_UPCAST2(upb_fielddef_containingoneof(f)), closure); + } if (upb_fielddef_subdef(f)) { visit(r, UPB_UPCAST(upb_fielddef_subdef(f)), closure); } @@ -620,6 +627,7 @@ upb_fielddef *upb_fielddef_new(const void *owner) { } f->msg.def = NULL; f->sub.def = NULL; + f->oneof = NULL; f->subdef_is_symbolic = false; f->msg_is_symbolic = false; f->label_ = UPB_LABEL_OPTIONAL; @@ -749,6 +757,10 @@ const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) { return f->msg_is_symbolic ? NULL : f->msg.def; } +const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f) { + return f->oneof; +} + upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f) { return (upb_msgdef*)upb_fielddef_containingtype(f); } @@ -777,6 +789,10 @@ bool upb_fielddef_setcontainingtypename(upb_fielddef *f, const char *name, } bool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s) { + if (upb_fielddef_containingtype(f) || upb_fielddef_containingoneof(f)) { + upb_status_seterrmsg(s, "Already added to message or oneof"); + return false; + } return upb_def_setfullname(UPB_UPCAST(f), name, s); } @@ -1248,15 +1264,25 @@ bool upb_fielddef_checkdescriptortype(int32_t type) { static void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit, void *closure) { const upb_msgdef *m = (const upb_msgdef*)r; - upb_msg_iter i; - for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) { + upb_msg_field_iter i; + for(upb_msg_field_begin(&i, m); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); visit(r, UPB_UPCAST2(f), closure); } + upb_msg_oneof_iter o; + for(upb_msg_oneof_begin(&o, m); + !upb_msg_oneof_done(&o); + upb_msg_oneof_next(&o)) { + upb_oneofdef *f = upb_msg_iter_oneof(&o); + visit(r, UPB_UPCAST2(f), closure); + } } static void freemsg(upb_refcounted *r) { upb_msgdef *m = (upb_msgdef*)r; + upb_strtable_uninit(&m->ntoo); upb_strtable_uninit(&m->ntof); upb_inttable_uninit(&m->itof); upb_def_uninit(UPB_UPCAST(m)); @@ -1268,14 +1294,17 @@ upb_msgdef *upb_msgdef_new(const void *owner) { upb_msgdef *m = malloc(sizeof(*m)); if (!m) return NULL; if (!upb_def_init(UPB_UPCAST(m), UPB_DEF_MSG, &vtbl, owner)) goto err2; - if (!upb_inttable_init(&m->itof, UPB_CTYPE_PTR)) goto err2; - if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err1; + if (!upb_inttable_init(&m->itof, UPB_CTYPE_PTR)) goto err3; + if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err2; + if (!upb_strtable_init(&m->ntoo, UPB_CTYPE_PTR)) goto err1; m->map_entry = false; return m; err1: - upb_inttable_uninit(&m->itof); + upb_strtable_uninit(&m->ntof); err2: + upb_inttable_uninit(&m->itof); +err3: free(m); return NULL; } @@ -1287,14 +1316,28 @@ upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner) { upb_def_fullname(UPB_UPCAST(m)), NULL); newm->map_entry = m->map_entry; UPB_ASSERT_VAR(ok, ok); - upb_msg_iter i; - for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) { + upb_msg_field_iter i; + for(upb_msg_field_begin(&i, m); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { upb_fielddef *f = upb_fielddef_dup(upb_msg_iter_field(&i), &f); + // Fields in oneofs are dup'd below. + if (upb_fielddef_containingoneof(f)) continue; if (!f || !upb_msgdef_addfield(newm, f, &f, NULL)) { upb_msgdef_unref(newm, owner); return NULL; } } + upb_msg_oneof_iter o; + for(upb_msg_oneof_begin(&o, m); + !upb_msg_oneof_done(&o); + upb_msg_oneof_next(&o)) { + upb_oneofdef *f = upb_oneofdef_dup(upb_msg_iter_oneof(&o), &f); + if (!f || !upb_msgdef_addoneof(newm, f, &f, NULL)) { + upb_msgdef_unref(newm, owner); + return NULL; + } + } return newm; } @@ -1333,6 +1376,35 @@ bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, return upb_def_setfullname(UPB_UPCAST(m), fullname, s); } +// Helper: check that the field |f| is safe to add to msgdef |m|. Set an error +// on status |s| and return false if not. +static bool check_field_add(const upb_msgdef *m, const upb_fielddef *f, + upb_status *s) { + if (upb_fielddef_containingtype(f) != NULL) { + upb_status_seterrmsg(s, "fielddef already belongs to a message"); + return false; + } else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) { + upb_status_seterrmsg(s, "field name or number were not set"); + return false; + } else if (upb_msgdef_ntofz(m, upb_fielddef_name(f)) || + upb_msgdef_itof(m, upb_fielddef_number(f))) { + upb_status_seterrmsg(s, "duplicate field name or number for field"); + return false; + } + return true; +} + +static void add_field(upb_msgdef *m, upb_fielddef *f, const void *ref_donor) { + release_containingtype(f); + f->msg.def = m; + f->msg_is_symbolic = false; + upb_inttable_insert(&m->itof, upb_fielddef_number(f), upb_value_ptr(f)); + upb_strtable_insert(&m->ntof, upb_fielddef_name(f), upb_value_ptr(f)); + upb_ref2(f, m); + upb_ref2(m, f); + if (ref_donor) upb_fielddef_unref(f, ref_donor); +} + bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor, upb_status *s) { // TODO: extensions need to have a separate namespace, because proto2 allows a @@ -1346,28 +1418,65 @@ bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor, // We also need to validate that the field number is in an extension range iff // it is an extension. + // This method is idempotent. Check if |f| is already part of this msgdef and + // return immediately if so. + if (upb_fielddef_containingtype(f) == m) { + return true; + } + // Check constraints for all fields before performing any action. - if (upb_fielddef_containingtype(f) != NULL) { - upb_status_seterrmsg(s, "fielddef already belongs to a message"); + if (!check_field_add(m, f, s)) { return false; - } else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) { - upb_status_seterrmsg(s, "field name or number were not set"); - return false; - } else if(upb_msgdef_itof(m, upb_fielddef_number(f)) || - upb_msgdef_ntofz(m, upb_fielddef_name(f))) { - upb_status_seterrmsg(s, "duplicate field name or number"); + } else if (upb_fielddef_containingoneof(f) != NULL) { + // Fields in a oneof can only be added by adding the oneof to the msgdef. + upb_status_seterrmsg(s, "fielddef is part of a oneof"); return false; } // Constraint checks ok, perform the action. - release_containingtype(f); - f->msg.def = m; - f->msg_is_symbolic = false; - upb_inttable_insert(&m->itof, upb_fielddef_number(f), upb_value_ptr(f)); - upb_strtable_insert(&m->ntof, upb_fielddef_name(f), upb_value_ptr(f)); - upb_ref2(f, m); - upb_ref2(m, f); - if (ref_donor) upb_fielddef_unref(f, ref_donor); + add_field(m, f, ref_donor); + return true; +} + +bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor, + upb_status *s) { + // Check various conditions that would prevent this oneof from being added. + if (upb_oneofdef_containingtype(o)) { + upb_status_seterrmsg(s, "oneofdef already belongs to a message"); + return false; + } else if (upb_oneofdef_name(o) == NULL) { + upb_status_seterrmsg(s, "oneofdef name was not set"); + return false; + } else if (upb_msgdef_ntooz(m, upb_oneofdef_name(o))) { + upb_status_seterrmsg(s, "duplicate oneof name"); + return false; + } + + // Check that all of the oneof's fields do not conflict with names or numbers + // of fields already in the message. + upb_oneof_iter it; + for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) { + const upb_fielddef *f = upb_oneof_iter_field(&it); + if (!check_field_add(m, f, s)) { + return false; + } + } + + // Everything checks out -- commit now. + + // Add oneof itself first. + o->parent = m; + upb_strtable_insert(&m->ntoo, upb_oneofdef_name(o), upb_value_ptr(o)); + upb_ref2(o, m); + upb_ref2(m, o); + + // Add each field of the oneof directly to the msgdef. + for (upb_oneof_begin(&it, o); !upb_oneof_done(&it); upb_oneof_next(&it)) { + upb_fielddef *f = upb_oneof_iter_field(&it); + add_field(m, f, NULL); + } + + if (ref_donor) upb_oneofdef_unref(o, ref_donor); return true; } @@ -1385,10 +1494,21 @@ const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name, upb_value_getptr(val) : NULL; } +const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name, + size_t len) { + upb_value val; + return upb_strtable_lookup2(&m->ntoo, name, len, &val) ? + upb_value_getptr(val) : NULL; +} + int upb_msgdef_numfields(const upb_msgdef *m) { return upb_strtable_count(&m->ntof); } +int upb_msgdef_numoneofs(const upb_msgdef *m) { + return upb_strtable_count(&m->ntoo); +} + void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry) { assert(!upb_msgdef_isfrozen(m)); m->map_entry = map_entry; @@ -1398,18 +1518,245 @@ bool upb_msgdef_mapentry(const upb_msgdef *m) { return m->map_entry; } -void upb_msg_begin(upb_msg_iter *iter, const upb_msgdef *m) { +void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m) { upb_inttable_begin(iter, &m->itof); } -void upb_msg_next(upb_msg_iter *iter) { upb_inttable_next(iter); } +void upb_msg_field_next(upb_msg_field_iter *iter) { upb_inttable_next(iter); } + +bool upb_msg_field_done(const upb_msg_field_iter *iter) { + return upb_inttable_done(iter); +} + +upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter) { + return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter)); +} + +void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) { + upb_inttable_iter_setdone(iter); +} + +void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) { + upb_strtable_begin(iter, &m->ntoo); +} + +void upb_msg_oneof_next(upb_msg_oneof_iter *iter) { upb_strtable_next(iter); } + +bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) { + return upb_strtable_done(iter); +} + +upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter) { + return (upb_oneofdef*)upb_value_getptr(upb_strtable_iter_value(iter)); +} + +void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter) { + upb_strtable_iter_setdone(iter); +} + +/* upb_oneofdef ***************************************************************/ + +static void visitoneof(const upb_refcounted *r, upb_refcounted_visit *visit, + void *closure) { + const upb_oneofdef *o = (const upb_oneofdef*)r; + upb_oneof_iter i; + for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) { + const upb_fielddef *f = upb_oneof_iter_field(&i); + visit(r, UPB_UPCAST2(f), closure); + } + if (o->parent) { + visit(r, UPB_UPCAST2(o->parent), closure); + } +} + +static void freeoneof(upb_refcounted *r) { + upb_oneofdef *o = (upb_oneofdef*)r; + upb_strtable_uninit(&o->ntof); + upb_inttable_uninit(&o->itof); + upb_def_uninit(UPB_UPCAST(o)); + free(o); +} + +upb_oneofdef *upb_oneofdef_new(const void *owner) { + static const struct upb_refcounted_vtbl vtbl = {visitoneof, freeoneof}; + upb_oneofdef *o = malloc(sizeof(*o)); + o->parent = NULL; + if (!o) return NULL; + if (!upb_def_init(UPB_UPCAST(o), UPB_DEF_ONEOF, &vtbl, owner)) goto err2; + if (!upb_inttable_init(&o->itof, UPB_CTYPE_PTR)) goto err2; + if (!upb_strtable_init(&o->ntof, UPB_CTYPE_PTR)) goto err1; + return o; + +err1: + upb_inttable_uninit(&o->itof); +err2: + free(o); + return NULL; +} + +upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner) { + upb_oneofdef *newo = upb_oneofdef_new(owner); + if (!newo) return NULL; + bool ok = upb_def_setfullname(UPB_UPCAST(newo), + upb_def_fullname(UPB_UPCAST(o)), NULL); + UPB_ASSERT_VAR(ok, ok); + upb_oneof_iter i; + for (upb_oneof_begin(&i, o); !upb_oneof_done(&i); upb_oneof_next(&i)) { + upb_fielddef *f = upb_fielddef_dup(upb_oneof_iter_field(&i), &f); + if (!f || !upb_oneofdef_addfield(newo, f, &f, NULL)) { + upb_oneofdef_unref(newo, owner); + return NULL; + } + } + return newo; +} + +bool upb_oneofdef_isfrozen(const upb_oneofdef *o) { + return upb_def_isfrozen(UPB_UPCAST(o)); +} + +void upb_oneofdef_ref(const upb_oneofdef *o, const void *owner) { + upb_def_ref(UPB_UPCAST(o), owner); +} + +void upb_oneofdef_unref(const upb_oneofdef *o, const void *owner) { + upb_def_unref(UPB_UPCAST(o), owner); +} + +void upb_oneofdef_donateref(const upb_oneofdef *o, const void *from, + const void *to) { + upb_def_donateref(UPB_UPCAST(o), from, to); +} + +void upb_oneofdef_checkref(const upb_oneofdef *o, const void *owner) { + upb_def_checkref(UPB_UPCAST(o), owner); +} + +const char *upb_oneofdef_name(const upb_oneofdef *o) { + return upb_def_fullname(UPB_UPCAST(o)); +} + +bool upb_oneofdef_setname(upb_oneofdef *o, const char *fullname, + upb_status *s) { + if (upb_oneofdef_containingtype(o)) { + upb_status_seterrmsg(s, "oneof already added to a message"); + return false; + } + return upb_def_setfullname(UPB_UPCAST(o), fullname, s); +} + +const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o) { + return o->parent; +} + +int upb_oneofdef_numfields(const upb_oneofdef *o) { + return upb_strtable_count(&o->ntof); +} + +bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f, + const void *ref_donor, + upb_status *s) { + assert(!upb_oneofdef_isfrozen(o)); + assert(!o->parent || !upb_msgdef_isfrozen(o->parent)); -bool upb_msg_done(const upb_msg_iter *iter) { return upb_inttable_done(iter); } + // This method is idempotent. Check if |f| is already part of this oneofdef + // and return immediately if so. + if (upb_fielddef_containingoneof(f) == o) { + return true; + } + + // The field must have an OPTIONAL label. + if (upb_fielddef_label(f) != UPB_LABEL_OPTIONAL) { + upb_status_seterrmsg(s, "fields in oneof must have OPTIONAL label"); + return false; + } + + // Check that no field with this name or number exists already in the oneof. + // Also check that the field is not already part of a oneof. + if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) { + upb_status_seterrmsg(s, "field name or number were not set"); + return false; + } else if (upb_oneofdef_itof(o, upb_fielddef_number(f)) || + upb_oneofdef_ntofz(o, upb_fielddef_name(f))) { + upb_status_seterrmsg(s, "duplicate field name or number"); + return false; + } else if (upb_fielddef_containingoneof(f) != NULL) { + upb_status_seterrmsg(s, "fielddef already belongs to a oneof"); + return false; + } + + // We allow adding a field to the oneof either if the field is not part of a + // msgdef, or if it is and we are also part of the same msgdef. + if (o->parent == NULL) { + // If we're not in a msgdef, the field cannot be either. Otherwise we would + // need to magically add this oneof to a msgdef to remain consistent, which + // is surprising behavior. + if (upb_fielddef_containingtype(f) != NULL) { + upb_status_seterrmsg(s, "fielddef already belongs to a message, but " + "oneof does not"); + return false; + } + } else { + // If we're in a msgdef, the user can add fields that either aren't in any + // msgdef (in which case they're added to our msgdef) or already a part of + // our msgdef. + if (upb_fielddef_containingtype(f) != NULL && + upb_fielddef_containingtype(f) != o->parent) { + upb_status_seterrmsg(s, "fielddef belongs to a different message " + "than oneof"); + return false; + } + } + + // Commit phase. First add the field to our parent msgdef, if any, because + // that may fail; then add the field to our own tables. + + if (o->parent != NULL && upb_fielddef_containingtype(f) == NULL) { + if (!upb_msgdef_addfield((upb_msgdef*)o->parent, f, NULL, s)) { + return false; + } + } + + release_containingtype(f); + f->oneof = o; + upb_inttable_insert(&o->itof, upb_fielddef_number(f), upb_value_ptr(f)); + upb_strtable_insert(&o->ntof, upb_fielddef_name(f), upb_value_ptr(f)); + upb_ref2(f, o); + upb_ref2(o, f); + if (ref_donor) upb_fielddef_unref(f, ref_donor); + + return true; +} + +const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o, + const char *name, size_t length) { + upb_value val; + return upb_strtable_lookup2(&o->ntof, name, length, &val) ? + upb_value_getptr(val) : NULL; +} + +const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) { + upb_value val; + return upb_inttable_lookup32(&o->itof, num, &val) ? + upb_value_getptr(val) : NULL; +} + +void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) { + upb_inttable_begin(iter, &o->itof); +} + +void upb_oneof_next(upb_oneof_iter *iter) { + upb_inttable_next(iter); +} + +bool upb_oneof_done(upb_oneof_iter *iter) { + return upb_inttable_done(iter); +} -upb_fielddef *upb_msg_iter_field(const upb_msg_iter *iter) { +upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter) { return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter)); } -void upb_msg_iter_setdone(upb_msg_iter *iter) { +void upb_oneof_iter_setdone(upb_oneof_iter *iter) { upb_inttable_iter_setdone(iter); } diff --git a/upb/def.h b/upb/def.h index ee138a05ec..fc342f3e28 100644 --- a/upb/def.h +++ b/upb/def.h @@ -34,6 +34,7 @@ class Def; class EnumDef; class FieldDef; class MessageDef; +class OneofDef; } #endif @@ -41,6 +42,7 @@ UPB_DECLARE_TYPE(upb::Def, upb_def); UPB_DECLARE_TYPE(upb::EnumDef, upb_enumdef); UPB_DECLARE_TYPE(upb::FieldDef, upb_fielddef); UPB_DECLARE_TYPE(upb::MessageDef, upb_msgdef); +UPB_DECLARE_TYPE(upb::OneofDef, upb_oneofdef); // Maximum field number allowed for FieldDefs. This is an inherent limit of the // protobuf wire format. @@ -64,6 +66,7 @@ typedef enum { UPB_DEF_MSG, UPB_DEF_FIELD, UPB_DEF_ENUM, + UPB_DEF_ONEOF, UPB_DEF_SERVICE, // Not yet implemented. UPB_DEF_ANY = -1, // Wildcard for upb_symtab_get*() } upb_deftype_t; @@ -348,6 +351,10 @@ UPB_DEFINE_DEF(upb::FieldDef, fielddef, FIELD, const MessageDef* containing_type() const; const char* containing_type_name(); + // The OneofDef to which this field belongs, or NULL if this field is not part + // of a oneof. + const OneofDef* containing_oneof() const; + // The field's type according to the enum in descriptor.proto. This is not // the same as UPB_TYPE_*, because it distinguishes between (for example) // INT32 and SINT32, whereas our "type" enum does not. This return of @@ -521,6 +528,7 @@ UPB_DEFINE_STRUCT(upb_fielddef, upb_def, } sub; // The msgdef or enumdef for this field, if upb_hassubdef(f). bool subdef_is_symbolic; bool msg_is_symbolic; + const upb_oneofdef *oneof; bool default_is_string; bool type_is_set_; // False until type is explicitly set. bool is_extension_; @@ -536,11 +544,11 @@ UPB_DEFINE_STRUCT(upb_fielddef, upb_def, )); #define UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, is_extension, lazy, \ - packed, name, num, msgdef, subdef, selector_base, \ + packed, name, num, msgdef, subdef, selector_base, \ index, defaultval, refs, ref2s) \ { \ UPB_DEF_INIT(name, UPB_DEF_FIELD, refs, ref2s), defaultval, {msgdef}, \ - {subdef}, false, false, \ + {subdef}, NULL, false, false, \ type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES, true, is_extension, \ lazy, packed, intfmt, tagdelim, type, label, num, selector_base, index \ } @@ -574,6 +582,7 @@ bool upb_fielddef_isextension(const upb_fielddef *f); bool upb_fielddef_lazy(const upb_fielddef *f); bool upb_fielddef_packed(const upb_fielddef *f); const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f); +const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f); upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f); const char *upb_fielddef_containingtypename(upb_fielddef *f); upb_intfmt_t upb_fielddef_intfmt(const upb_fielddef *f); @@ -641,7 +650,8 @@ UPB_END_EXTERN_C // } /* upb::MessageDef ************************************************************/ -typedef upb_inttable_iter upb_msg_iter; +typedef upb_inttable_iter upb_msg_field_iter; +typedef upb_strtable_iter upb_msg_oneof_iter; // Structure that describes a single .proto message type. // @@ -671,14 +681,37 @@ UPB_DEFINE_DEF(upb::MessageDef, msgdef, MSG, UPB_QUOTE( // The number of fields that belong to the MessageDef. int field_count() const; + // The number of oneofs that belong to the MessageDef. + int oneof_count() const; + // Adds a field (upb_fielddef object) to a msgdef. Requires that the msgdef // and the fielddefs are mutable. The fielddef's name and number must be // set, and the message may not already contain any field with this name or // number, and this fielddef may not be part of another message. In error // cases false is returned and the msgdef is unchanged. + // + // If the given field is part of a oneof, this call succeeds if and only if + // that oneof is already part of this msgdef. (Note that adding a oneof to a + // msgdef automatically adds all of its fields to the msgdef at the time that + // the oneof is added, so it is usually more idiomatic to add the oneof's + // fields first then add the oneof to the msgdef. This case is supported for + // convenience.) + // + // If |f| is already part of this MessageDef, this method performs no action + // and returns true (success). Thus, this method is idempotent. bool AddField(FieldDef* f, Status* s); bool AddField(const reffed_ptr& f, Status* s); + // Adds a oneof (upb_oneofdef object) to a msgdef. Requires that the msgdef, + // oneof, and any fielddefs are mutable, that the fielddefs contained in the + // oneof do not have any name or number conflicts with existing fields in the + // msgdef, and that the oneof's name is unique among all oneofs in the msgdef. + // If the oneof is added successfully, all of its fields will be added + // directly to the msgdef as well. In error cases, false is returned and the + // msgdef is unchanged. + bool AddOneof(OneofDef* o, Status* s); + bool AddOneof(const reffed_ptr& o, Status* s); + // These return NULL if the field is not found. FieldDef* FindFieldByNumber(uint32_t number); FieldDef* FindFieldByName(const char *name, size_t len); @@ -702,6 +735,25 @@ UPB_DEFINE_DEF(upb::MessageDef, msgdef, MSG, UPB_QUOTE( return FindFieldByName(str.c_str(), str.size()); } + OneofDef* FindOneofByName(const char* name, size_t len); + const OneofDef* FindOneofByName(const char* name, size_t len) const; + + OneofDef* FindOneofByName(const char* name) { + return FindOneofByName(name, strlen(name)); + } + const OneofDef* FindOneofByName(const char* name) const { + return FindOneofByName(name, strlen(name)); + } + + template + OneofDef* FindOneofByName(const T& str) { + return FindOneofByName(str.c_str(), str.size()); + } + template + const OneofDef* FindOneofByName(const T& str) const { + return FindOneofByName(str.c_str(), str.size()); + } + // Returns a new msgdef that is a copy of the given msgdef (and a copy of all // the fields) but with any references to submessages broken and replaced // with just the name of the submessage. Returns NULL if memory allocation @@ -717,39 +769,117 @@ UPB_DEFINE_DEF(upb::MessageDef, msgdef, MSG, UPB_QUOTE( bool mapentry() const; // Iteration over fields. The order is undefined. - class iterator : public std::iterator { + class field_iterator + : public std::iterator { public: - explicit iterator(MessageDef* md); - static iterator end(MessageDef* md); + explicit field_iterator(MessageDef* md); + static field_iterator end(MessageDef* md); void operator++(); FieldDef* operator*() const; - bool operator!=(const iterator& other) const; - bool operator==(const iterator& other) const; + bool operator!=(const field_iterator& other) const; + bool operator==(const field_iterator& other) const; private: - upb_msg_iter iter_; + upb_msg_field_iter iter_; }; - class const_iterator + class const_field_iterator : public std::iterator { public: - explicit const_iterator(const MessageDef* md); - static const_iterator end(const MessageDef* md); + explicit const_field_iterator(const MessageDef* md); + static const_field_iterator end(const MessageDef* md); void operator++(); const FieldDef* operator*() const; - bool operator!=(const const_iterator& other) const; - bool operator==(const const_iterator& other) const; + bool operator!=(const const_field_iterator& other) const; + bool operator==(const const_field_iterator& other) const; private: - upb_msg_iter iter_; + upb_msg_field_iter iter_; }; - iterator begin(); - iterator end(); - const_iterator begin() const; - const_iterator end() const; + // Iteration over oneofs. The order is undefined. + class oneof_iterator + : public std::iterator { + public: + explicit oneof_iterator(MessageDef* md); + static oneof_iterator end(MessageDef* md); + + void operator++(); + OneofDef* operator*() const; + bool operator!=(const oneof_iterator& other) const; + bool operator==(const oneof_iterator& other) const; + + private: + upb_msg_oneof_iter iter_; + }; + + class const_oneof_iterator + : public std::iterator { + public: + explicit const_oneof_iterator(const MessageDef* md); + static const_oneof_iterator end(const MessageDef* md); + + void operator++(); + const OneofDef* operator*() const; + bool operator!=(const const_oneof_iterator& other) const; + bool operator==(const const_oneof_iterator& other) const; + + private: + upb_msg_oneof_iter iter_; + }; + + class FieldAccessor { + public: + explicit FieldAccessor(MessageDef* msg) : msg_(msg) {} + field_iterator begin() { return msg_->field_begin(); } + field_iterator end() { return msg_->field_end(); } + private: + MessageDef* msg_; + }; + + class ConstFieldAccessor { + public: + explicit ConstFieldAccessor(const MessageDef* msg) : msg_(msg) {} + const_field_iterator begin() { return msg_->field_begin(); } + const_field_iterator end() { return msg_->field_end(); } + private: + const MessageDef* msg_; + }; + + class OneofAccessor { + public: + explicit OneofAccessor(MessageDef* msg) : msg_(msg) {} + oneof_iterator begin() { return msg_->oneof_begin(); } + oneof_iterator end() { return msg_->oneof_end(); } + private: + MessageDef* msg_; + }; + + class ConstOneofAccessor { + public: + explicit ConstOneofAccessor(const MessageDef* msg) : msg_(msg) {} + const_oneof_iterator begin() { return msg_->oneof_begin(); } + const_oneof_iterator end() { return msg_->oneof_end(); } + private: + const MessageDef* msg_; + }; + + field_iterator field_begin(); + field_iterator field_end(); + const_field_iterator field_begin() const; + const_field_iterator field_end() const; + + oneof_iterator oneof_begin(); + oneof_iterator oneof_end(); + const_oneof_iterator oneof_begin() const; + const_oneof_iterator oneof_end() const; + + FieldAccessor fields() { return FieldAccessor(this); } + ConstFieldAccessor fields() const { return ConstFieldAccessor(this); } + OneofAccessor oneofs() { return OneofAccessor(this); } + ConstOneofAccessor oneofs() const { return ConstOneofAccessor(this); } private: UPB_DISALLOW_POD_OPS(MessageDef, upb::MessageDef); @@ -762,6 +892,9 @@ UPB_DEFINE_STRUCT(upb_msgdef, upb_def, upb_inttable itof; // int to field upb_strtable ntof; // name to field + // Tables for looking up oneofs by name. + upb_strtable ntoo; // name to oneof + // Is this a map-entry message? // TODO: set this flag properly for static descriptors; regenerate // descriptor.upb.c. @@ -770,11 +903,14 @@ UPB_DEFINE_STRUCT(upb_msgdef, upb_def, // TODO(haberman): proper extension ranges (there can be multiple). )); +// TODO: also support static initialization of the oneofs table. This will be +// needed if we compile in descriptors that contain oneofs. #define UPB_MSGDEF_INIT(name, selector_count, submsg_field_count, itof, ntof, \ refs, ref2s) \ { \ UPB_DEF_INIT(name, UPB_DEF_MSG, refs, ref2s), selector_count, \ - submsg_field_count, itof, ntof, false \ + submsg_field_count, itof, ntof, \ + UPB_EMPTY_STRTABLE_INIT(UPB_CTYPE_PTR), false \ } UPB_BEGIN_EXTERN_C // { @@ -798,6 +934,8 @@ bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, upb_status *s); upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner); bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor, upb_status *s); +bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor, + upb_status *s); // Field lookup in a couple of different variations: // - itof = int to field @@ -822,11 +960,34 @@ UPB_INLINE upb_fielddef *upb_msgdef_ntof_mutable(upb_msgdef *m, return (upb_fielddef *)upb_msgdef_ntof(m, name, len); } +// Oneof lookup: +// - ntoo = name to oneof +// - ntooz = name to oneof, null-terminated string. +const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name, + size_t len); +int upb_msgdef_numoneofs(const upb_msgdef *m); + +UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m, + const char *name) { + return upb_msgdef_ntoo(m, name, strlen(name)); +} + +UPB_INLINE upb_oneofdef *upb_msgdef_ntoo_mutable(upb_msgdef *m, + const char *name, size_t len) { + return (upb_oneofdef *)upb_msgdef_ntoo(m, name, len); +} + void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry); bool upb_msgdef_mapentry(const upb_msgdef *m); -// upb_msg_iter i; -// for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) { +const upb_oneofdef *upb_msgdef_findoneof(const upb_msgdef *m, + const char *name); +int upb_msgdef_numoneofs(const upb_msgdef *m); + +// upb_msg_field_iter i; +// for(upb_msg_field_begin(&i, m); +// !upb_msg_field_done(&i); +// upb_msg_field_next(&i)) { // upb_fielddef *f = upb_msg_iter_field(&i); // // ... // } @@ -834,11 +995,18 @@ bool upb_msgdef_mapentry(const upb_msgdef *m); // For C we don't have separate iterators for const and non-const. // It is the caller's responsibility to cast the upb_fielddef* to // const if the upb_msgdef* is const. -void upb_msg_begin(upb_msg_iter *iter, const upb_msgdef *m); -void upb_msg_next(upb_msg_iter *iter); -bool upb_msg_done(const upb_msg_iter *iter); -upb_fielddef *upb_msg_iter_field(const upb_msg_iter *iter); -void upb_msg_iter_setdone(upb_msg_iter *iter); +void upb_msg_field_begin(upb_msg_field_iter *iter, const upb_msgdef *m); +void upb_msg_field_next(upb_msg_field_iter *iter); +bool upb_msg_field_done(const upb_msg_field_iter *iter); +upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter); +void upb_msg_field_iter_setdone(upb_msg_field_iter *iter); + +// Similar to above, we also support iterating through the oneofs in a msgdef. +void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m); +void upb_msg_oneof_next(upb_msg_oneof_iter *iter); +bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter); +upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter); +void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter); UPB_END_EXTERN_C // } @@ -980,6 +1148,172 @@ int32_t upb_enum_iter_number(upb_enum_iter *iter); UPB_END_EXTERN_C // } +/* upb::OneofDef **************************************************************/ + +typedef upb_inttable_iter upb_oneof_iter; + +// Class that represents a oneof. Its base class is upb::Def (convert with +// upb::upcast()). +UPB_DEFINE_DEF(upb::OneofDef, oneofdef, ONEOF, UPB_QUOTE( + public: + // Returns NULL if memory allocation failed. + static reffed_ptr New(); + + // Functionality from upb::RefCounted. + bool IsFrozen() const; + void Ref(const void* owner) const; + void Unref(const void* owner) const; + void DonateRef(const void* from, const void* to) const; + void CheckRef(const void* owner) const; + + // Functionality from upb::Def. + const char* full_name() const; + + // Returns the MessageDef that owns this OneofDef. + const MessageDef* containing_type() const; + + // Returns the name of this oneof. This is the name used to look up the oneof + // by name once added to a message def. + const char* name() const; + bool set_name(const char* name, Status* s); + + // Returns the number of fields currently defined in the oneof. + int field_count() const; + + // Adds a field to the oneof. The field must not have been added to any other + // oneof or msgdef. If the oneof is not yet part of a msgdef, then when the + // oneof is eventually added to a msgdef, all fields added to the oneof will + // also be added to the msgdef at that time. If the oneof is already part of a + // msgdef, the field must either be a part of that msgdef already, or must not + // be a part of any msgdef; in the latter case, the field is added to the + // msgdef as a part of this operation. + // + // The field may only have an OPTIONAL label, never REQUIRED or REPEATED. + // + // If |f| is already part of this MessageDef, this method performs no action + // and returns true (success). Thus, this method is idempotent. + bool AddField(FieldDef* field, Status* s); + bool AddField(const reffed_ptr& field, Status* s); + + // Looks up by name. + const FieldDef* FindFieldByName(const char* name, size_t len) const; + FieldDef* FindFieldByName(const char* name, size_t len); + const FieldDef* FindFieldByName(const char* name) const { + return FindFieldByName(name, strlen(name)); + } + FieldDef* FindFieldByName(const char* name) { + return FindFieldByName(name, strlen(name)); + } + + template + FieldDef* FindFieldByName(const T& str) { + return FindFieldByName(str.c_str(), str.size()); + } + template + const FieldDef* FindFieldByName(const T& str) const { + return FindFieldByName(str.c_str(), str.size()); + } + + // Looks up by tag number. + const FieldDef* FindFieldByNumber(uint32_t num) const; + + // Returns a new OneofDef with all the same fields. The OneofDef will be owned + // by the given owner. + OneofDef* Dup(const void* owner) const; + + // Iteration over fields. The order is undefined. + class iterator : public std::iterator { + public: + explicit iterator(OneofDef* md); + static iterator end(OneofDef* md); + + void operator++(); + FieldDef* operator*() const; + bool operator!=(const iterator& other) const; + bool operator==(const iterator& other) const; + + private: + upb_oneof_iter iter_; + }; + + class const_iterator + : public std::iterator { + public: + explicit const_iterator(const OneofDef* md); + static const_iterator end(const OneofDef* md); + + void operator++(); + const FieldDef* operator*() const; + bool operator!=(const const_iterator& other) const; + bool operator==(const const_iterator& other) const; + + private: + upb_oneof_iter iter_; + }; + + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + + private: + UPB_DISALLOW_POD_OPS(OneofDef, upb::OneofDef); +), +UPB_DEFINE_STRUCT(upb_oneofdef, upb_def, + upb_strtable ntof; + upb_inttable itof; + const upb_msgdef *parent; +)); + +#define UPB_ONEOFDEF_INIT(name, ntof, itof, refs, ref2s) \ + { UPB_DEF_INIT(name, UPB_DEF_ENUM, refs, ref2s), ntof, itof } + +UPB_BEGIN_EXTERN_C // { + +// Native C API. +upb_oneofdef *upb_oneofdef_new(const void *owner); +upb_oneofdef *upb_oneofdef_dup(const upb_oneofdef *o, const void *owner); + +// From upb_refcounted. +void upb_oneofdef_unref(const upb_oneofdef *o, const void *owner); +bool upb_oneofdef_isfrozen(const upb_oneofdef *e); +void upb_oneofdef_ref(const upb_oneofdef *o, const void *owner); +void upb_oneofdef_donateref(const upb_oneofdef *m, const void *from, + const void *to); +void upb_oneofdef_checkref(const upb_oneofdef *o, const void *owner); + +const char *upb_oneofdef_name(const upb_oneofdef *o); +bool upb_oneofdef_setname(upb_oneofdef *o, const char *name, upb_status *s); + +const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o); +int upb_oneofdef_numfields(const upb_oneofdef *o); +bool upb_oneofdef_addfield(upb_oneofdef *o, upb_fielddef *f, + const void *ref_donor, + upb_status *s); + +// Oneof lookups: +// - ntof: look up a field by name. +// - ntofz: look up a field by name (as a null-terminated string). +// - itof: look up a field by number. +const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o, + const char *name, size_t length); +UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o, + const char *name) { + return upb_oneofdef_ntof(o, name, strlen(name)); +} +const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num); + +// upb_oneof_iter i; +// for(upb_oneof_begin(&i, e); !upb_oneof_done(&i); upb_oneof_next(&i)) { +// // ... +// } +void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o); +void upb_oneof_next(upb_oneof_iter *iter); +bool upb_oneof_done(upb_oneof_iter *iter); +upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter); +void upb_oneof_iter_setdone(upb_oneof_iter *iter); + +UPB_END_EXTERN_C // } #ifdef __cplusplus @@ -1106,6 +1440,9 @@ inline void FieldDef::set_packed(bool packed) { inline const MessageDef* FieldDef::containing_type() const { return upb_fielddef_containingtype(this); } +inline const OneofDef* FieldDef::containing_oneof() const { + return upb_fielddef_containingoneof(this); +} inline const char* FieldDef::containing_type_name() { return upb_fielddef_containingtypename(this); } @@ -1256,12 +1593,21 @@ inline bool MessageDef::Freeze(Status* status) { inline int MessageDef::field_count() const { return upb_msgdef_numfields(this); } +inline int MessageDef::oneof_count() const { + return upb_msgdef_numoneofs(this); +} inline bool MessageDef::AddField(upb_fielddef* f, Status* s) { return upb_msgdef_addfield(this, f, NULL, s); } inline bool MessageDef::AddField(const reffed_ptr& f, Status* s) { return upb_msgdef_addfield(this, f.get(), NULL, s); } +inline bool MessageDef::AddOneof(upb_oneofdef* o, Status* s) { + return upb_msgdef_addoneof(this, o, NULL, s); +} +inline bool MessageDef::AddOneof(const reffed_ptr& o, Status* s) { + return upb_msgdef_addoneof(this, o.get(), NULL, s); +} inline FieldDef* MessageDef::FindFieldByNumber(uint32_t number) { return upb_msgdef_itof_mutable(this, number); } @@ -1275,6 +1621,13 @@ inline const FieldDef *MessageDef::FindFieldByName(const char *name, size_t len) const { return upb_msgdef_ntof(this, name, len); } +inline OneofDef* MessageDef::FindOneofByName(const char* name, size_t len) { + return upb_msgdef_ntoo_mutable(this, name, len); +} +inline const OneofDef* MessageDef::FindOneofByName(const char* name, + size_t len) const { + return upb_msgdef_ntoo(this, name, len); +} inline MessageDef* MessageDef::Dup(const void *owner) const { return upb_msgdef_dup(this, owner); } @@ -1284,55 +1637,127 @@ inline void MessageDef::setmapentry(bool map_entry) { inline bool MessageDef::mapentry() const { return upb_msgdef_mapentry(this); } -inline MessageDef::iterator MessageDef::begin() { return iterator(this); } -inline MessageDef::iterator MessageDef::end() { return iterator::end(this); } -inline MessageDef::const_iterator MessageDef::begin() const { - return const_iterator(this); +inline MessageDef::field_iterator MessageDef::field_begin() { + return field_iterator(this); } -inline MessageDef::const_iterator MessageDef::end() const { - return const_iterator::end(this); +inline MessageDef::field_iterator MessageDef::field_end() { + return field_iterator::end(this); +} +inline MessageDef::const_field_iterator MessageDef::field_begin() const { + return const_field_iterator(this); +} +inline MessageDef::const_field_iterator MessageDef::field_end() const { + return const_field_iterator::end(this); } -inline MessageDef::iterator::iterator(MessageDef* md) { - upb_msg_begin(&iter_, md); +inline MessageDef::oneof_iterator MessageDef::oneof_begin() { + return oneof_iterator(this); +} +inline MessageDef::oneof_iterator MessageDef::oneof_end() { + return oneof_iterator::end(this); +} +inline MessageDef::const_oneof_iterator MessageDef::oneof_begin() const { + return const_oneof_iterator(this); +} +inline MessageDef::const_oneof_iterator MessageDef::oneof_end() const { + return const_oneof_iterator::end(this); } -inline MessageDef::iterator MessageDef::iterator::end(MessageDef* md) { - MessageDef::iterator iter(md); - upb_msg_iter_setdone(&iter.iter_); + +inline MessageDef::field_iterator::field_iterator(MessageDef* md) { + upb_msg_field_begin(&iter_, md); +} +inline MessageDef::field_iterator MessageDef::field_iterator::end( + MessageDef* md) { + MessageDef::field_iterator iter(md); + upb_msg_field_iter_setdone(&iter.iter_); return iter; } -inline FieldDef* MessageDef::iterator::operator*() const { +inline FieldDef* MessageDef::field_iterator::operator*() const { return upb_msg_iter_field(&iter_); } -inline void MessageDef::iterator::operator++() { return upb_msg_next(&iter_); } -inline bool MessageDef::iterator::operator==(const iterator &other) const { +inline void MessageDef::field_iterator::operator++() { + return upb_msg_field_next(&iter_); +} +inline bool MessageDef::field_iterator::operator==( + const field_iterator &other) const { return upb_inttable_iter_isequal(&iter_, &other.iter_); } -inline bool MessageDef::iterator::operator!=(const iterator &other) const { +inline bool MessageDef::field_iterator::operator!=( + const field_iterator &other) const { return !(*this == other); } -inline MessageDef::const_iterator::const_iterator(const MessageDef* md) { - upb_msg_begin(&iter_, md); +inline MessageDef::const_field_iterator::const_field_iterator( + const MessageDef* md) { + upb_msg_field_begin(&iter_, md); } -inline MessageDef::const_iterator MessageDef::const_iterator::end( +inline MessageDef::const_field_iterator MessageDef::const_field_iterator::end( const MessageDef *md) { - MessageDef::const_iterator iter(md); - upb_msg_iter_setdone(&iter.iter_); + MessageDef::const_field_iterator iter(md); + upb_msg_field_iter_setdone(&iter.iter_); return iter; } -inline const FieldDef* MessageDef::const_iterator::operator*() const { +inline const FieldDef* MessageDef::const_field_iterator::operator*() const { return upb_msg_iter_field(&iter_); } -inline void MessageDef::const_iterator::operator++() { - return upb_msg_next(&iter_); +inline void MessageDef::const_field_iterator::operator++() { + return upb_msg_field_next(&iter_); } -inline bool MessageDef::const_iterator::operator==( - const const_iterator &other) const { +inline bool MessageDef::const_field_iterator::operator==( + const const_field_iterator &other) const { return upb_inttable_iter_isequal(&iter_, &other.iter_); } -inline bool MessageDef::const_iterator::operator!=( - const const_iterator &other) const { +inline bool MessageDef::const_field_iterator::operator!=( + const const_field_iterator &other) const { + return !(*this == other); +} + +inline MessageDef::oneof_iterator::oneof_iterator(MessageDef* md) { + upb_msg_oneof_begin(&iter_, md); +} +inline MessageDef::oneof_iterator MessageDef::oneof_iterator::end( + MessageDef* md) { + MessageDef::oneof_iterator iter(md); + upb_msg_oneof_iter_setdone(&iter.iter_); + return iter; +} +inline OneofDef* MessageDef::oneof_iterator::operator*() const { + return upb_msg_iter_oneof(&iter_); +} +inline void MessageDef::oneof_iterator::operator++() { + return upb_msg_oneof_next(&iter_); +} +inline bool MessageDef::oneof_iterator::operator==( + const oneof_iterator &other) const { + return upb_strtable_iter_isequal(&iter_, &other.iter_); +} +inline bool MessageDef::oneof_iterator::operator!=( + const oneof_iterator &other) const { + return !(*this == other); +} + +inline MessageDef::const_oneof_iterator::const_oneof_iterator( + const MessageDef* md) { + upb_msg_oneof_begin(&iter_, md); +} +inline MessageDef::const_oneof_iterator MessageDef::const_oneof_iterator::end( + const MessageDef *md) { + MessageDef::const_oneof_iterator iter(md); + upb_msg_oneof_iter_setdone(&iter.iter_); + return iter; +} +inline const OneofDef* MessageDef::const_oneof_iterator::operator*() const { + return upb_msg_iter_oneof(&iter_); +} +inline void MessageDef::const_oneof_iterator::operator++() { + return upb_msg_oneof_next(&iter_); +} +inline bool MessageDef::const_oneof_iterator::operator==( + const const_oneof_iterator &other) const { + return upb_strtable_iter_isequal(&iter_, &other.iter_); +} +inline bool MessageDef::const_oneof_iterator::operator!=( + const const_oneof_iterator &other) const { return !(*this == other); } @@ -1400,6 +1825,105 @@ inline const char* EnumDef::Iterator::name() { } inline bool EnumDef::Iterator::Done() { return upb_enum_done(&iter_); } inline void EnumDef::Iterator::Next() { return upb_enum_next(&iter_); } + +inline reffed_ptr OneofDef::New() { + upb_oneofdef *o = upb_oneofdef_new(&o); + return reffed_ptr(o, &o); +} +inline bool OneofDef::IsFrozen() const { return upb_oneofdef_isfrozen(this); } +inline void OneofDef::Ref(const void* owner) const { + return upb_oneofdef_ref(this, owner); +} +inline void OneofDef::Unref(const void* owner) const { + return upb_oneofdef_unref(this, owner); +} +inline void OneofDef::DonateRef(const void* from, const void* to) const { + return upb_oneofdef_donateref(this, from, to); +} +inline void OneofDef::CheckRef(const void* owner) const { + return upb_oneofdef_checkref(this, owner); +} +inline const char* OneofDef::full_name() const { + return upb_oneofdef_name(this); +} + +inline const MessageDef* OneofDef::containing_type() const { + return upb_oneofdef_containingtype(this); +} +inline const char* OneofDef::name() const { + return upb_oneofdef_name(this); +} +inline bool OneofDef::set_name(const char* name, Status* s) { + return upb_oneofdef_setname(this, name, s); +} +inline int OneofDef::field_count() const { + return upb_oneofdef_numfields(this); +} +inline bool OneofDef::AddField(FieldDef* field, Status* s) { + return upb_oneofdef_addfield(this, field, NULL, s); +} +inline bool OneofDef::AddField(const reffed_ptr& field, Status* s) { + return upb_oneofdef_addfield(this, field.get(), NULL, s); +} +inline const FieldDef* OneofDef::FindFieldByName(const char* name, + size_t len) const { + return upb_oneofdef_ntof(this, name, len); +} +inline const FieldDef* OneofDef::FindFieldByNumber(uint32_t num) const { + return upb_oneofdef_itof(this, num); +} +inline OneofDef::iterator OneofDef::begin() { return iterator(this); } +inline OneofDef::iterator OneofDef::end() { return iterator::end(this); } +inline OneofDef::const_iterator OneofDef::begin() const { + return const_iterator(this); +} +inline OneofDef::const_iterator OneofDef::end() const { + return const_iterator::end(this); +} + +inline OneofDef::iterator::iterator(OneofDef* o) { + upb_oneof_begin(&iter_, o); +} +inline OneofDef::iterator OneofDef::iterator::end(OneofDef* o) { + OneofDef::iterator iter(o); + upb_oneof_iter_setdone(&iter.iter_); + return iter; +} +inline FieldDef* OneofDef::iterator::operator*() const { + return upb_oneof_iter_field(&iter_); +} +inline void OneofDef::iterator::operator++() { return upb_oneof_next(&iter_); } +inline bool OneofDef::iterator::operator==(const iterator &other) const { + return upb_inttable_iter_isequal(&iter_, &other.iter_); +} +inline bool OneofDef::iterator::operator!=(const iterator &other) const { + return !(*this == other); +} + +inline OneofDef::const_iterator::const_iterator(const OneofDef* md) { + upb_oneof_begin(&iter_, md); +} +inline OneofDef::const_iterator OneofDef::const_iterator::end( + const OneofDef *md) { + OneofDef::const_iterator iter(md); + upb_oneof_iter_setdone(&iter.iter_); + return iter; +} +inline const FieldDef* OneofDef::const_iterator::operator*() const { + return upb_msg_iter_field(&iter_); +} +inline void OneofDef::const_iterator::operator++() { + return upb_oneof_next(&iter_); +} +inline bool OneofDef::const_iterator::operator==( + const const_iterator &other) const { + return upb_inttable_iter_isequal(&iter_, &other.iter_); +} +inline bool OneofDef::const_iterator::operator!=( + const const_iterator &other) const { + return !(*this == other); +} + } // namespace upb #endif diff --git a/upb/handlers.c b/upb/handlers.c index c0fd271a6f..fd19633c33 100644 --- a/upb/handlers.c +++ b/upb/handlers.c @@ -40,8 +40,10 @@ static void freehandlers(upb_refcounted *r) { static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit, void *closure) { const upb_handlers *h = (const upb_handlers*)r; - upb_msg_iter i; - for(upb_msg_begin(&i, h->msg); !upb_msg_done(&i); upb_msg_next(&i)) { + upb_msg_field_iter i; + for(upb_msg_field_begin(&i, h->msg); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); if (!upb_fielddef_issubmsg(f)) continue; const upb_handlers *sub = upb_handlers_getsubhandlers(h, f); @@ -70,8 +72,10 @@ static upb_handlers *newformsg(const upb_msgdef *m, const void *owner, // For each submessage field, get or create a handlers object and set it as // the subhandlers. - upb_msg_iter i; - for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) { + upb_msg_field_iter i; + for(upb_msg_field_begin(&i, m); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); if (!upb_fielddef_issubmsg(f)) continue; @@ -428,8 +432,10 @@ bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) { // Check that there are no closure mismatches due to missing Start* handlers // or subhandlers with different type-level types. - upb_msg_iter j; - for(upb_msg_begin(&j, h->msg); !upb_msg_done(&j); upb_msg_next(&j)) { + upb_msg_field_iter j; + for(upb_msg_field_begin(&j, h->msg); + !upb_msg_field_done(&j); + upb_msg_field_next(&j)) { const upb_fielddef *f = upb_msg_iter_field(&j); if (upb_fielddef_isseq(f)) { diff --git a/upb/json/printer.c b/upb/json/printer.c index b996ccfae9..3dd3c20f0f 100644 --- a/upb/json/printer.c +++ b/upb/json/printer.c @@ -437,9 +437,9 @@ void printer_sethandlers(const void *closure, upb_handlers *h) { } \ break; - upb_msg_iter i; - upb_msg_begin(&i, upb_handlers_msgdef(h)); - for(; !upb_msg_done(&i); upb_msg_next(&i)) { + upb_msg_field_iter i; + upb_msg_field_begin(&i, upb_handlers_msgdef(h)); + for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) { const upb_fielddef *f = upb_msg_iter_field(&i); upb_handlerattr name_attr = UPB_HANDLERATTR_INITIALIZER; diff --git a/upb/pb/compile_decoder.c b/upb/pb/compile_decoder.c index 11aa4e9447..377cbb497a 100644 --- a/upb/pb/compile_decoder.c +++ b/upb/pb/compile_decoder.c @@ -762,8 +762,10 @@ static void compile_method(compiler *c, upb_pbdecodermethod *method) { putsel(c, OP_STARTMSG, UPB_STARTMSG_SELECTOR, h); label(c, LABEL_FIELD); uint32_t* start_pc = c->pc; - upb_msg_iter i; - for(upb_msg_begin(&i, md); !upb_msg_done(&i); upb_msg_next(&i)) { + upb_msg_field_iter i; + for(upb_msg_field_begin(&i, md); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { const upb_fielddef *f = upb_msg_iter_field(&i); upb_fieldtype_t type = upb_fielddef_type(f); @@ -813,9 +815,11 @@ static void find_methods(compiler *c, const upb_handlers *h) { newmethod(h, c->group); // Find submethods. - upb_msg_iter i; + upb_msg_field_iter i; const upb_msgdef *md = upb_handlers_msgdef(h); - for(upb_msg_begin(&i, md); !upb_msg_done(&i); upb_msg_next(&i)) { + for(upb_msg_field_begin(&i, md); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { const upb_fielddef *f = upb_msg_iter_field(&i); const upb_handlers *sub_h; if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE && @@ -857,7 +861,7 @@ static void set_bytecode_handlers(mgroup *g) { } -/* JIT setup. ******************************************************************/ +/* JIT setup. *****************************************************************/ #ifdef UPB_USE_JIT_X64 diff --git a/upb/pb/encoder.c b/upb/pb/encoder.c index d2c22e99f0..d5685dc0ff 100644 --- a/upb/pb/encoder.c +++ b/upb/pb/encoder.c @@ -378,8 +378,10 @@ static void newhandlers_callback(const void *closure, upb_handlers *h) { upb_handlers_setendmsg(h, endmsg, NULL); const upb_msgdef *m = upb_handlers_msgdef(h); - upb_msg_iter i; - for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) { + upb_msg_field_iter i; + for(upb_msg_field_begin(&i, m); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { const upb_fielddef *f = upb_msg_iter_field(&i); bool packed = upb_fielddef_isseq(f) && upb_fielddef_isprimitive(f) && upb_fielddef_packed(f); diff --git a/upb/pb/textprinter.c b/upb/pb/textprinter.c index 8ceed68628..45c5e434c3 100644 --- a/upb/pb/textprinter.c +++ b/upb/pb/textprinter.c @@ -261,8 +261,10 @@ static void onmreg(const void *c, upb_handlers *h) { upb_handlers_setstartmsg(h, textprinter_startmsg, NULL); upb_handlers_setendmsg(h, textprinter_endmsg, NULL); - upb_msg_iter i; - for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) { + upb_msg_field_iter i; + for(upb_msg_field_begin(&i, m); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; upb_handlerattr_sethandlerdata(&attr, f); diff --git a/upb/symtab.c b/upb/symtab.c index f172aaa500..817a581bed 100644 --- a/upb/symtab.c +++ b/upb/symtab.c @@ -139,8 +139,10 @@ static bool upb_resolve_dfs(const upb_def *def, upb_strtable *addtab, // For messages, continue the recursion by visiting all subdefs. const upb_msgdef *m = upb_dyncast_msgdef(def); if (m) { - upb_msg_iter i; - for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) { + upb_msg_field_iter i; + for(upb_msg_field_begin(&i, m); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); if (!upb_fielddef_hassubdef(f)) continue; // |= to avoid short-circuit; we need its side-effects. @@ -293,8 +295,10 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, // Type names are resolved relative to the message in which they appear. const char *base = upb_msgdef_fullname(m); - upb_msg_iter j; - for(upb_msg_begin(&j, m); !upb_msg_done(&j); upb_msg_next(&j)) { + upb_msg_field_iter j; + for(upb_msg_field_begin(&j, m); + !upb_msg_field_done(&j); + upb_msg_field_next(&j)) { upb_fielddef *f = upb_msg_iter_field(&j); const char *name = upb_fielddef_subdefname(f); if (name && !upb_fielddef_subdef(f)) { diff --git a/upb/table.int.h b/upb/table.int.h index e851e903c3..e27fb01a05 100644 --- a/upb/table.int.h +++ b/upb/table.int.h @@ -207,6 +207,9 @@ typedef struct { #define UPB_STRTABLE_INIT(count, mask, ctype, size_lg2, entries) \ {{count, mask, ctype, size_lg2, entries}} +#define UPB_EMPTY_STRTABLE_INIT(ctype) \ + UPB_STRTABLE_INIT(0, 0, ctype, 0, NULL) + typedef struct { upb_table t; // For entries that don't fit in the array part. const _upb_value *array; // Array part of the table. See const note above.