Merge pull request #11 from cfallin/oneofs

Support oneof defs in upb.
pull/13171/head
Joshua Haberman 10 years ago
commit 1988a660f4
  1. 4
      tests/bindings/googlepb/test_vs_proto2.cc
  2. 102
      tests/test_cpp.cc
  3. 57
      tests/test_def.c
  4. 3
      upb/bindings/googlepb/bridge.cc
  5. 29
      upb/bindings/lua/upb.c
  6. 41
      upb/bindings/python/upb.c
  7. 39
      upb/bindings/ruby/upb.c
  8. 409
      upb/def.c
  9. 632
      upb/def.h
  10. 18
      upb/handlers.c
  11. 6
      upb/json/printer.c
  12. 14
      upb/pb/compile_decoder.c
  13. 6
      upb/pb/encoder.c
  14. 6
      upb/pb/textprinter.c
  15. 12
      upb/symtab.c
  16. 3
      upb/table.int.h

@ -40,8 +40,8 @@ const unsigned char message2_data[] = {
void compare_metadata(const google::protobuf::Descriptor* d, void compare_metadata(const google::protobuf::Descriptor* d,
const upb::MessageDef *upb_md) { const upb::MessageDef *upb_md) {
ASSERT(d->field_count() == upb_md->field_count()); ASSERT(d->field_count() == upb_md->field_count());
for (upb::MessageDef::const_iterator i = upb_md->begin(); i != upb_md->end(); for (upb::MessageDef::const_field_iterator i = upb_md->field_begin();
++i) { i != upb_md->field_end(); ++i) {
const upb::FieldDef* upb_f = *i; const upb::FieldDef* upb_f = *i;
const google::protobuf::FieldDescriptor *proto2_f = const google::protobuf::FieldDescriptor *proto2_f =
d->FindFieldByNumber(upb_f->number()); d->FindFieldByNumber(upb_f->number());

@ -12,6 +12,7 @@
#include <iostream> #include <iostream>
#include <set> #include <set>
#include <sstream>
#include "upb/def.h" #include "upb/def.h"
#include "upb/descriptor/reader.h" #include "upb/descriptor/reader.h"
@ -164,7 +165,7 @@ static void TestSymbolTable(const char *descriptor_file) {
#ifdef UPB_CXX11 #ifdef UPB_CXX11
// Test range-based for. // Test range-based for.
std::set<const upb::FieldDef*> fielddefs; std::set<const upb::FieldDef*> fielddefs;
for (const upb::FieldDef* f : *md.get()) { for (const upb::FieldDef* f : md.get()->fields()) {
AssertInsert(&fielddefs, f); AssertInsert(&fielddefs, f);
ASSERT(f->containing_type() == md.get()); ASSERT(f->containing_type() == md.get());
} }
@ -1117,6 +1118,103 @@ void TestHandlerDataDestruction() {
ASSERT(x == 0); ASSERT(x == 0);
} }
void TestOneofs() {
upb::Status status;
upb::reffed_ptr<upb::MessageDef> md(upb::MessageDef::New());
upb::reffed_ptr<upb::OneofDef> 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<upb::FieldDef> 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<upb::FieldDef> 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<upb::FieldDef> 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<upb::FieldDef> 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" { extern "C" {
int run_tests(int argc, char *argv[]) { int run_tests(int argc, char *argv[]) {
@ -1173,6 +1271,8 @@ int run_tests(int argc, char *argv[]) {
TestHandlerDataDestruction(); TestHandlerDataDestruction();
TestOneofs();
return 0; return 0;
} }

@ -189,7 +189,9 @@ static upb_fielddef *newfield(
ASSERT(upb_fielddef_setnumber(f, num, NULL)); ASSERT(upb_fielddef_setnumber(f, num, NULL));
upb_fielddef_settype(f, type); upb_fielddef_settype(f, type);
upb_fielddef_setlabel(f, label); 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; return f;
} }
@ -342,6 +344,58 @@ static void test_descriptor_flags() {
upb_msgdef_unref(m2, &m2); 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[]) { int run_tests(int argc, char *argv[]) {
if (argc < 2) { if (argc < 2) {
fprintf(stderr, "Usage: test_def <test.proto.pb>\n"); fprintf(stderr, "Usage: test_def <test.proto.pb>\n");
@ -358,5 +412,6 @@ int run_tests(int argc, char *argv[]) {
test_partial_freeze(); test_partial_freeze();
test_noreftracking(); test_noreftracking();
test_descriptor_flags(); test_descriptor_flags();
test_oneofs();
return 0; return 0;
} }

@ -246,7 +246,8 @@ const Handlers* CodeCache::GetMaybeUnfrozenWriteHandlers(
to_freeze_.push_back(h); to_freeze_.push_back(h);
const goog::Descriptor* d = m.GetDescriptor(); 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 FieldDef* upb_f = *i;
const goog::FieldDescriptor* proto2_f = const goog::FieldDescriptor* proto2_f =

@ -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 // Pushes a new userdata with the given metatable and ensures that it has a
// uservalue. // 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); void *ret = lua_newuserdata(L, size);
// Set metatable. // Set metatable.
@ -952,17 +953,17 @@ static int lupb_msgdef_field(lua_State *L) {
} }
static int lupb_msgiter_next(lua_State *L) { static int lupb_msgiter_next(lua_State *L) {
upb_msg_iter *i = lua_touserdata(L, lua_upvalueindex(1)); upb_msg_field_iter *i = lua_touserdata(L, lua_upvalueindex(1));
if (upb_msg_done(i)) return 0; if (upb_msg_field_done(i)) return 0;
lupb_def_pushwrapper(L, UPB_UPCAST(upb_msg_iter_field(i)), NULL); lupb_def_pushwrapper(L, UPB_UPCAST(upb_msg_iter_field(i)), NULL);
upb_msg_next(i); upb_msg_field_next(i);
return 1; return 1;
} }
static int lupb_msgdef_fields(lua_State *L) { static int lupb_msgdef_fields(lua_State *L) {
const upb_msgdef *m = lupb_msgdef_check(L, 1); const upb_msgdef *m = lupb_msgdef_check(L, 1);
upb_msg_iter *i = lua_newuserdata(L, sizeof(upb_msg_iter)); upb_msg_field_iter *i = lua_newuserdata(L, sizeof(upb_msg_field_iter));
upb_msg_begin(i, m); upb_msg_field_begin(i, m);
// Need to guarantee that the msgdef outlives the iter. // Need to guarantee that the msgdef outlives the iter.
lua_pushvalue(L, 1); lua_pushvalue(L, 1);
lua_pushcclosure(L, &lupb_msgiter_next, 2); 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; size_t userval_idx = 1;
// Assign offsets. // Assign offsets.
upb_msg_iter i; upb_msg_field_iter i;
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); upb_fielddef *f = upb_msg_iter_field(&i);
if (in_userval(f)) { if (in_userval(f)) {
offsets[upb_fielddef_index(f)] = userval_idx++; 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. lua_newtable(L); // This will be our userval.
int idx = 1; 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); upb_fielddef *f = upb_msg_iter_field(&i);
if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE) { if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE) {
bool created = lupb_def_pushwrapper(L, upb_fielddef_subdef(f), NULL); 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; lua_State *L = (lua_State*)closure;
lupb_def_pushwrapper(L, UPB_UPCAST(upb_handlers_msgdef(h)), NULL); lupb_def_pushwrapper(L, UPB_UPCAST(upb_handlers_msgdef(h)), NULL);
lupb_msgdef *lmd = lupb_msg_assignoffsets(L, -1); lupb_msgdef *lmd = lupb_msg_assignoffsets(L, -1);
upb_msg_iter i; upb_msg_field_iter i;
upb_msg_begin(&i, upb_handlers_msgdef(h)); upb_msg_field_begin(&i, upb_handlers_msgdef(h));
for (; !upb_msg_done(&i); upb_msg_next(&i)) { for (; !upb_msg_field_done(&i); upb_msg_field_next(&i)) {
upb_fielddef *f = upb_msg_iter_field(&i); upb_fielddef *f = upb_msg_iter_field(&i);
int hasbit = upb_fielddef_index(f); int hasbit = upb_fielddef_index(f);
uint16_t ofs = lmd->field_offsets[upb_fielddef_index(f)]; uint16_t ofs = lmd->field_offsets[upb_fielddef_index(f)];

@ -298,7 +298,8 @@ static PyObject *PyUpb_MessageDef_new(PyTypeObject *subtype,
static PyObject *PyUpb_MessageDef_add_fields(PyObject *o, PyObject *args); 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; if (!kwds) return 0;
PyObject *key, *value; PyObject *key, *value;
Py_ssize_t pos = 0; 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); 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); upb_msgdef *m = Check_MessageDef(o, -1);
if (!upb_def_ismutable(UPB_UPCAST(m))) { if (!upb_def_ismutable(UPB_UPCAST(m))) {
PyErr_SetString(PyExc_TypeError, "MessageDef is not mutable."); 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) { static PyObject *PyUpb_MessageDef_fields(PyObject *obj, PyObject *args) {
upb_msgdef *m = Check_MessageDef(obj, NULL); upb_msgdef *m = Check_MessageDef(obj, NULL);
PyObject *ret = PyList_New(0); PyObject *ret = PyList_New(0);
upb_msg_iter i; upb_msg_field_iter i;
for(i = upb_msg_begin(m); !upb_msg_done(i); i = upb_msg_next(m, i)) { for(upb_msg_field_begin(&i, m);
upb_fielddef *f = upb_msg_iter_field(i); !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)); PyList_Append(ret, PyUpb_FieldDef_GetOrCreate(f));
} }
return ret; return ret;
@ -374,9 +378,12 @@ static PyObject *PyUpb_MessageDef_add_field(PyObject *o, PyObject *field) {
} }
static PyMethodDef PyUpb_MessageDef_methods[] = { static PyMethodDef PyUpb_MessageDef_methods[] = {
{"add_field", &PyUpb_MessageDef_add_field, METH_O, "Adds a list of fields."}, {"add_field", &PyUpb_MessageDef_add_field, METH_O,
{"add_fields", &PyUpb_MessageDef_add_fields, METH_O, "Adds a list of fields."}, "Adds a list of fields."},
{"fields", &PyUpb_MessageDef_fields, METH_NOARGS, "Returns 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} {NULL, NULL}
}; };
@ -448,7 +455,8 @@ static PyObject *PyUpb_SymbolTable_new(PyTypeObject *subtype,
return PyUpb_ObjCacheGet(upb_symtab_new(), 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; return 0;
} }
@ -475,8 +483,10 @@ static PyObject *PyUpb_SymbolTable_add_defs(PyObject *o, PyObject *defs) {
cdefs[i++] = def; cdefs[i++] = def;
upb_msgdef *md = upb_dyncast_msgdef(def); upb_msgdef *md = upb_dyncast_msgdef(def);
if (!md) continue; if (!md) continue;
upb_msg_iter j; upb_msg_field_iter j;
for(j = upb_msg_begin(md); !upb_msg_done(j); j = upb_msg_next(md, 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 *f = upb_msg_iter_field(j);
upb_fielddef_setaccessor(f, PyUpb_AccessorForField(f)); 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); 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; (void)fval;
PyObject **elem = upb_stdarray_append(a, sizeof(void*)); PyObject **elem = upb_stdarray_append(a, sizeof(void*));
PyTypeObject *type = ((PyUpb_MessageType*)Py_TYPE(a))->alt_type; 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); 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); PyObject **str = PyUpb_Accessor_GetPtr(m, fval);
if (*str) { Py_DECREF(*str); } if (*str) { Py_DECREF(*str); }
*str = PyString_FromStringAndSize(NULL, upb_value_getstrref(val)->len); *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; 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; (void)fval;
PyObject **elem = upb_stdarray_append(a, sizeof(void*)); PyObject **elem = upb_stdarray_append(a, sizeof(void*));
*elem = PyString_FromStringAndSize(NULL, upb_value_getstrref(val)->len); *elem = PyString_FromStringAndSize(NULL, upb_value_getstrref(val)->len);

@ -273,9 +273,11 @@ static size_t rupb_sizeof(const upb_fielddef *f) {
static void assign_offsets(rb_msglayout *layout, const upb_msgdef *md) { static void assign_offsets(rb_msglayout *layout, const upb_msgdef *md) {
layout->field_offsets = ALLOC_N(uint32_t, upb_msgdef_numfields(md)); layout->field_offsets = ALLOC_N(uint32_t, upb_msgdef_numfields(md));
size_t ofs = 0; 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); const upb_fielddef *f = upb_msg_iter_field(&i);
size_t field_size = rupb_sizeof(f); 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. // more specific initialization.
memset(prototype, 0, layout->size); memset(prototype, 0, layout->size);
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); const upb_fielddef *f = upb_msg_iter_field(&i);
if (is_ruby_value(f)) { if (is_ruby_value(f)) {
size_t ofs = layout->field_offsets[upb_fielddef_index(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); rb_gc_mark(rmd->klass);
// Mark all submessage types. // Mark all submessage types.
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)) {
upb_fielddef *f = upb_msg_iter_field(&i); upb_fielddef *f = upb_msg_iter_field(&i);
if (upb_fielddef_issubmsg(f)) { if (upb_fielddef_issubmsg(f)) {
// If we were trying to be more aggressively lazy, the submessage might // 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 // We need to mark all references to other Ruby values: strings, arrays, and
// submessages that we point to. // submessages that we point to.
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)) {
upb_fielddef *f = upb_msg_iter_field(&i); upb_fielddef *f = upb_msg_iter_field(&i);
if (is_ruby_value(f)) { if (is_ruby_value(f)) {
size_t ofs = rmd->layout.field_offsets[upb_fielddef_index(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; const submsg_handlerdata_t *submsgdata = hd;
if (DEREF(msg, submsgdata->ofs, VALUE) == Qnil) { 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); 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) { static void add_handlers_for_message(const void *closure, upb_handlers *h) {
const rupb_MessageDef *rmd = get_rbmsgdef(upb_handlers_msgdef(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); const upb_fielddef *f = upb_msg_iter_field(&i);
size_t ofs = rmd->layout.field_offsets[upb_fielddef_index(f)]; 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 *sink) {
upb_sink_startmsg(sink); upb_sink_startmsg(sink);
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)) {
upb_fielddef *f = upb_msg_iter_field(&i); upb_fielddef *f = upb_msg_iter_field(&i);
uint32_t ofs = rmd->layout.field_offsets[upb_fielddef_index(f)]; uint32_t ofs = rmd->layout.field_offsets[upb_fielddef_index(f)];

@ -248,10 +248,12 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) {
upb_fielddef **fields = malloc(n * sizeof(*fields)); upb_fielddef **fields = malloc(n * sizeof(*fields));
if (!fields) return false; if (!fields) return false;
upb_msg_iter j; upb_msg_field_iter j;
int i; int i;
m->submsg_field_count = 0; 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); upb_fielddef *f = upb_msg_iter_field(&j);
assert(f->msg.def == m); assert(f->msg.def == m);
if (!upb_validate_field(f, s)) { 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_selector_t sel;
upb_inttable_insert(&t, UPB_STARTMSG_SELECTOR, v); upb_inttable_insert(&t, UPB_STARTMSG_SELECTOR, v);
upb_inttable_insert(&t, UPB_ENDMSG_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); upb_fielddef *f = upb_msg_iter_field(&j);
// These calls will assert-fail in upb_table if the value already exists. // These calls will assert-fail in upb_table if the value already exists.
TRY(UPB_HANDLER_INT32); TRY(UPB_HANDLER_INT32);
@ -545,6 +549,9 @@ static void visitfield(const upb_refcounted *r, upb_refcounted_visit *visit,
if (upb_fielddef_containingtype(f)) { if (upb_fielddef_containingtype(f)) {
visit(r, UPB_UPCAST2(upb_fielddef_containingtype(f)), closure); 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)) { if (upb_fielddef_subdef(f)) {
visit(r, UPB_UPCAST(upb_fielddef_subdef(f)), closure); 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->msg.def = NULL;
f->sub.def = NULL; f->sub.def = NULL;
f->oneof = NULL;
f->subdef_is_symbolic = false; f->subdef_is_symbolic = false;
f->msg_is_symbolic = false; f->msg_is_symbolic = false;
f->label_ = UPB_LABEL_OPTIONAL; 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; 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) { upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f) {
return (upb_msgdef*)upb_fielddef_containingtype(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) { 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); 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, static void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit,
void *closure) { void *closure) {
const upb_msgdef *m = (const upb_msgdef*)r; const upb_msgdef *m = (const upb_msgdef*)r;
upb_msg_iter i; upb_msg_field_iter i;
for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&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_fielddef *f = upb_msg_iter_field(&i);
visit(r, UPB_UPCAST2(f), closure); 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) { static void freemsg(upb_refcounted *r) {
upb_msgdef *m = (upb_msgdef*)r; upb_msgdef *m = (upb_msgdef*)r;
upb_strtable_uninit(&m->ntoo);
upb_strtable_uninit(&m->ntof); upb_strtable_uninit(&m->ntof);
upb_inttable_uninit(&m->itof); upb_inttable_uninit(&m->itof);
upb_def_uninit(UPB_UPCAST(m)); upb_def_uninit(UPB_UPCAST(m));
@ -1268,14 +1294,17 @@ upb_msgdef *upb_msgdef_new(const void *owner) {
upb_msgdef *m = malloc(sizeof(*m)); upb_msgdef *m = malloc(sizeof(*m));
if (!m) return NULL; if (!m) return NULL;
if (!upb_def_init(UPB_UPCAST(m), UPB_DEF_MSG, &vtbl, owner)) goto err2; 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_inttable_init(&m->itof, UPB_CTYPE_PTR)) goto err3;
if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err1; 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; m->map_entry = false;
return m; return m;
err1: err1:
upb_inttable_uninit(&m->itof); upb_strtable_uninit(&m->ntof);
err2: err2:
upb_inttable_uninit(&m->itof);
err3:
free(m); free(m);
return NULL; 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); upb_def_fullname(UPB_UPCAST(m)), NULL);
newm->map_entry = m->map_entry; newm->map_entry = m->map_entry;
UPB_ASSERT_VAR(ok, ok); UPB_ASSERT_VAR(ok, ok);
upb_msg_iter i; upb_msg_field_iter i;
for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&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); 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)) { if (!f || !upb_msgdef_addfield(newm, f, &f, NULL)) {
upb_msgdef_unref(newm, owner); upb_msgdef_unref(newm, owner);
return NULL; 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; 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); 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, bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor,
upb_status *s) { upb_status *s) {
// TODO: extensions need to have a separate namespace, because proto2 allows a // 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 // We also need to validate that the field number is in an extension range iff
// it is an extension. // 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. // Check constraints for all fields before performing any action.
if (upb_fielddef_containingtype(f) != NULL) { if (!check_field_add(m, f, s)) {
upb_status_seterrmsg(s, "fielddef already belongs to a message");
return false; return false;
} else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) { } else if (upb_fielddef_containingoneof(f) != NULL) {
upb_status_seterrmsg(s, "field name or number were not set"); // Fields in a oneof can only be added by adding the oneof to the msgdef.
return false; upb_status_seterrmsg(s, "fielddef is part of a oneof");
} 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");
return false; return false;
} }
// Constraint checks ok, perform the action. // Constraint checks ok, perform the action.
release_containingtype(f); add_field(m, f, ref_donor);
f->msg.def = m; return true;
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)); bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor,
upb_ref2(f, m); upb_status *s) {
upb_ref2(m, f); // Check various conditions that would prevent this oneof from being added.
if (ref_donor) upb_fielddef_unref(f, ref_donor); 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; return true;
} }
@ -1385,10 +1494,21 @@ const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
upb_value_getptr(val) : NULL; 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) { int upb_msgdef_numfields(const upb_msgdef *m) {
return upb_strtable_count(&m->ntof); 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) { void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry) {
assert(!upb_msgdef_isfrozen(m)); assert(!upb_msgdef_isfrozen(m));
m->map_entry = map_entry; m->map_entry = map_entry;
@ -1398,18 +1518,245 @@ bool upb_msgdef_mapentry(const upb_msgdef *m) {
return m->map_entry; 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); 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)); 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); upb_inttable_iter_setdone(iter);
} }

@ -34,6 +34,7 @@ class Def;
class EnumDef; class EnumDef;
class FieldDef; class FieldDef;
class MessageDef; class MessageDef;
class OneofDef;
} }
#endif #endif
@ -41,6 +42,7 @@ UPB_DECLARE_TYPE(upb::Def, upb_def);
UPB_DECLARE_TYPE(upb::EnumDef, upb_enumdef); UPB_DECLARE_TYPE(upb::EnumDef, upb_enumdef);
UPB_DECLARE_TYPE(upb::FieldDef, upb_fielddef); UPB_DECLARE_TYPE(upb::FieldDef, upb_fielddef);
UPB_DECLARE_TYPE(upb::MessageDef, upb_msgdef); 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 // Maximum field number allowed for FieldDefs. This is an inherent limit of the
// protobuf wire format. // protobuf wire format.
@ -64,6 +66,7 @@ typedef enum {
UPB_DEF_MSG, UPB_DEF_MSG,
UPB_DEF_FIELD, UPB_DEF_FIELD,
UPB_DEF_ENUM, UPB_DEF_ENUM,
UPB_DEF_ONEOF,
UPB_DEF_SERVICE, // Not yet implemented. UPB_DEF_SERVICE, // Not yet implemented.
UPB_DEF_ANY = -1, // Wildcard for upb_symtab_get*() UPB_DEF_ANY = -1, // Wildcard for upb_symtab_get*()
} upb_deftype_t; } upb_deftype_t;
@ -348,6 +351,10 @@ UPB_DEFINE_DEF(upb::FieldDef, fielddef, FIELD,
const MessageDef* containing_type() const; const MessageDef* containing_type() const;
const char* containing_type_name(); 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 field's type according to the enum in descriptor.proto. This is not
// the same as UPB_TYPE_*, because it distinguishes between (for example) // the same as UPB_TYPE_*, because it distinguishes between (for example)
// INT32 and SINT32, whereas our "type" enum does not. This return of // 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). } sub; // The msgdef or enumdef for this field, if upb_hassubdef(f).
bool subdef_is_symbolic; bool subdef_is_symbolic;
bool msg_is_symbolic; bool msg_is_symbolic;
const upb_oneofdef *oneof;
bool default_is_string; bool default_is_string;
bool type_is_set_; // False until type is explicitly set. bool type_is_set_; // False until type is explicitly set.
bool is_extension_; 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, \ #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) \ index, defaultval, refs, ref2s) \
{ \ { \
UPB_DEF_INIT(name, UPB_DEF_FIELD, refs, ref2s), defaultval, {msgdef}, \ 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, \ type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES, true, is_extension, \
lazy, packed, intfmt, tagdelim, type, label, num, selector_base, index \ 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_lazy(const upb_fielddef *f);
bool upb_fielddef_packed(const upb_fielddef *f); bool upb_fielddef_packed(const upb_fielddef *f);
const upb_msgdef *upb_fielddef_containingtype(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); upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f);
const char *upb_fielddef_containingtypename(upb_fielddef *f); const char *upb_fielddef_containingtypename(upb_fielddef *f);
upb_intfmt_t upb_fielddef_intfmt(const upb_fielddef *f); upb_intfmt_t upb_fielddef_intfmt(const upb_fielddef *f);
@ -641,7 +650,8 @@ UPB_END_EXTERN_C // }
/* upb::MessageDef ************************************************************/ /* 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. // 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. // The number of fields that belong to the MessageDef.
int field_count() const; 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 // 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 // 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 // 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 // number, and this fielddef may not be part of another message. In error
// cases false is returned and the msgdef is unchanged. // 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(FieldDef* f, Status* s);
bool AddField(const reffed_ptr<FieldDef>& f, Status* s); bool AddField(const reffed_ptr<FieldDef>& 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<OneofDef>& o, Status* s);
// These return NULL if the field is not found. // These return NULL if the field is not found.
FieldDef* FindFieldByNumber(uint32_t number); FieldDef* FindFieldByNumber(uint32_t number);
FieldDef* FindFieldByName(const char *name, size_t len); 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()); 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<class T>
OneofDef* FindOneofByName(const T& str) {
return FindOneofByName(str.c_str(), str.size());
}
template<class T>
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 // 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 // the fields) but with any references to submessages broken and replaced
// with just the name of the submessage. Returns NULL if memory allocation // 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; bool mapentry() const;
// Iteration over fields. The order is undefined. // Iteration over fields. The order is undefined.
class iterator : public std::iterator<std::forward_iterator_tag, FieldDef*> { class field_iterator
: public std::iterator<std::forward_iterator_tag, FieldDef*> {
public: public:
explicit iterator(MessageDef* md); explicit field_iterator(MessageDef* md);
static iterator end(MessageDef* md); static field_iterator end(MessageDef* md);
void operator++(); void operator++();
FieldDef* operator*() const; FieldDef* operator*() const;
bool operator!=(const iterator& other) const; bool operator!=(const field_iterator& other) const;
bool operator==(const iterator& other) const; bool operator==(const field_iterator& other) const;
private: private:
upb_msg_iter iter_; upb_msg_field_iter iter_;
}; };
class const_iterator class const_field_iterator
: public std::iterator<std::forward_iterator_tag, const FieldDef*> { : public std::iterator<std::forward_iterator_tag, const FieldDef*> {
public: public:
explicit const_iterator(const MessageDef* md); explicit const_field_iterator(const MessageDef* md);
static const_iterator end(const MessageDef* md); static const_field_iterator end(const MessageDef* md);
void operator++(); void operator++();
const FieldDef* operator*() const; const FieldDef* operator*() const;
bool operator!=(const const_iterator& other) const; bool operator!=(const const_field_iterator& other) const;
bool operator==(const const_iterator& other) const; bool operator==(const const_field_iterator& other) const;
private: private:
upb_msg_iter iter_; upb_msg_field_iter iter_;
}; };
iterator begin(); // Iteration over oneofs. The order is undefined.
iterator end(); class oneof_iterator
const_iterator begin() const; : public std::iterator<std::forward_iterator_tag, FieldDef*> {
const_iterator end() const; 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<std::forward_iterator_tag, const FieldDef*> {
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: private:
UPB_DISALLOW_POD_OPS(MessageDef, upb::MessageDef); 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_inttable itof; // int to field
upb_strtable ntof; // name 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? // Is this a map-entry message?
// TODO: set this flag properly for static descriptors; regenerate // TODO: set this flag properly for static descriptors; regenerate
// descriptor.upb.c. // descriptor.upb.c.
@ -770,11 +903,14 @@ UPB_DEFINE_STRUCT(upb_msgdef, upb_def,
// TODO(haberman): proper extension ranges (there can be multiple). // 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, \ #define UPB_MSGDEF_INIT(name, selector_count, submsg_field_count, itof, ntof, \
refs, ref2s) \ refs, ref2s) \
{ \ { \
UPB_DEF_INIT(name, UPB_DEF_MSG, refs, ref2s), selector_count, \ 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 // { 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); 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, bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor,
upb_status *s); 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: // Field lookup in a couple of different variations:
// - itof = int to field // - 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); 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); void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry);
bool upb_msgdef_mapentry(const upb_msgdef *m); bool upb_msgdef_mapentry(const upb_msgdef *m);
// upb_msg_iter i; const upb_oneofdef *upb_msgdef_findoneof(const upb_msgdef *m,
// for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) { 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); // 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. // 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 // It is the caller's responsibility to cast the upb_fielddef* to
// const if the upb_msgdef* is const. // const if the upb_msgdef* is const.
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);
void upb_msg_next(upb_msg_iter *iter); void upb_msg_field_next(upb_msg_field_iter *iter);
bool upb_msg_done(const upb_msg_iter *iter); bool upb_msg_field_done(const upb_msg_field_iter *iter);
upb_fielddef *upb_msg_iter_field(const upb_msg_iter *iter); upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter);
void upb_msg_iter_setdone(upb_msg_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 // } UPB_END_EXTERN_C // }
@ -980,6 +1148,172 @@ int32_t upb_enum_iter_number(upb_enum_iter *iter);
UPB_END_EXTERN_C // } 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<OneofDef> 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<FieldDef>& 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 <class T>
FieldDef* FindFieldByName(const T& str) {
return FindFieldByName(str.c_str(), str.size());
}
template <class T>
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<std::forward_iterator_tag, FieldDef*> {
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<std::forward_iterator_tag, const FieldDef*> {
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 #ifdef __cplusplus
@ -1106,6 +1440,9 @@ inline void FieldDef::set_packed(bool packed) {
inline const MessageDef* FieldDef::containing_type() const { inline const MessageDef* FieldDef::containing_type() const {
return upb_fielddef_containingtype(this); return upb_fielddef_containingtype(this);
} }
inline const OneofDef* FieldDef::containing_oneof() const {
return upb_fielddef_containingoneof(this);
}
inline const char* FieldDef::containing_type_name() { inline const char* FieldDef::containing_type_name() {
return upb_fielddef_containingtypename(this); return upb_fielddef_containingtypename(this);
} }
@ -1256,12 +1593,21 @@ inline bool MessageDef::Freeze(Status* status) {
inline int MessageDef::field_count() const { inline int MessageDef::field_count() const {
return upb_msgdef_numfields(this); 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) { inline bool MessageDef::AddField(upb_fielddef* f, Status* s) {
return upb_msgdef_addfield(this, f, NULL, s); return upb_msgdef_addfield(this, f, NULL, s);
} }
inline bool MessageDef::AddField(const reffed_ptr<FieldDef>& f, Status* s) { inline bool MessageDef::AddField(const reffed_ptr<FieldDef>& f, Status* s) {
return upb_msgdef_addfield(this, f.get(), NULL, 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<OneofDef>& o, Status* s) {
return upb_msgdef_addoneof(this, o.get(), NULL, s);
}
inline FieldDef* MessageDef::FindFieldByNumber(uint32_t number) { inline FieldDef* MessageDef::FindFieldByNumber(uint32_t number) {
return upb_msgdef_itof_mutable(this, number); return upb_msgdef_itof_mutable(this, number);
} }
@ -1275,6 +1621,13 @@ inline const FieldDef *MessageDef::FindFieldByName(const char *name,
size_t len) const { size_t len) const {
return upb_msgdef_ntof(this, name, len); 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 { inline MessageDef* MessageDef::Dup(const void *owner) const {
return upb_msgdef_dup(this, owner); return upb_msgdef_dup(this, owner);
} }
@ -1284,55 +1637,127 @@ inline void MessageDef::setmapentry(bool map_entry) {
inline bool MessageDef::mapentry() const { inline bool MessageDef::mapentry() const {
return upb_msgdef_mapentry(this); return upb_msgdef_mapentry(this);
} }
inline MessageDef::iterator MessageDef::begin() { return iterator(this); } inline MessageDef::field_iterator MessageDef::field_begin() {
inline MessageDef::iterator MessageDef::end() { return iterator::end(this); } return field_iterator(this);
inline MessageDef::const_iterator MessageDef::begin() const {
return const_iterator(this);
} }
inline MessageDef::const_iterator MessageDef::end() const { inline MessageDef::field_iterator MessageDef::field_end() {
return const_iterator::end(this); 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) { inline MessageDef::oneof_iterator MessageDef::oneof_begin() {
upb_msg_begin(&iter_, md); 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); inline MessageDef::field_iterator::field_iterator(MessageDef* md) {
upb_msg_iter_setdone(&iter.iter_); 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; return iter;
} }
inline FieldDef* MessageDef::iterator::operator*() const { inline FieldDef* MessageDef::field_iterator::operator*() const {
return upb_msg_iter_field(&iter_); return upb_msg_iter_field(&iter_);
} }
inline void MessageDef::iterator::operator++() { return upb_msg_next(&iter_); } inline void MessageDef::field_iterator::operator++() {
inline bool MessageDef::iterator::operator==(const iterator &other) const { 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_); 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); return !(*this == other);
} }
inline MessageDef::const_iterator::const_iterator(const MessageDef* md) { inline MessageDef::const_field_iterator::const_field_iterator(
upb_msg_begin(&iter_, md); 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) { const MessageDef *md) {
MessageDef::const_iterator iter(md); MessageDef::const_field_iterator iter(md);
upb_msg_iter_setdone(&iter.iter_); upb_msg_field_iter_setdone(&iter.iter_);
return 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_); return upb_msg_iter_field(&iter_);
} }
inline void MessageDef::const_iterator::operator++() { inline void MessageDef::const_field_iterator::operator++() {
return upb_msg_next(&iter_); return upb_msg_field_next(&iter_);
} }
inline bool MessageDef::const_iterator::operator==( inline bool MessageDef::const_field_iterator::operator==(
const const_iterator &other) const { const const_field_iterator &other) const {
return upb_inttable_iter_isequal(&iter_, &other.iter_); return upb_inttable_iter_isequal(&iter_, &other.iter_);
} }
inline bool MessageDef::const_iterator::operator!=( inline bool MessageDef::const_field_iterator::operator!=(
const const_iterator &other) const { 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); return !(*this == other);
} }
@ -1400,6 +1825,105 @@ inline const char* EnumDef::Iterator::name() {
} }
inline bool EnumDef::Iterator::Done() { return upb_enum_done(&iter_); } inline bool EnumDef::Iterator::Done() { return upb_enum_done(&iter_); }
inline void EnumDef::Iterator::Next() { return upb_enum_next(&iter_); } inline void EnumDef::Iterator::Next() { return upb_enum_next(&iter_); }
inline reffed_ptr<OneofDef> OneofDef::New() {
upb_oneofdef *o = upb_oneofdef_new(&o);
return reffed_ptr<OneofDef>(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<FieldDef>& 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 } // namespace upb
#endif #endif

@ -40,8 +40,10 @@ static void freehandlers(upb_refcounted *r) {
static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit, static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit,
void *closure) { void *closure) {
const upb_handlers *h = (const upb_handlers*)r; const upb_handlers *h = (const upb_handlers*)r;
upb_msg_iter i; upb_msg_field_iter i;
for(upb_msg_begin(&i, h->msg); !upb_msg_done(&i); upb_msg_next(&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); upb_fielddef *f = upb_msg_iter_field(&i);
if (!upb_fielddef_issubmsg(f)) continue; if (!upb_fielddef_issubmsg(f)) continue;
const upb_handlers *sub = upb_handlers_getsubhandlers(h, f); 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 // For each submessage field, get or create a handlers object and set it as
// the subhandlers. // the subhandlers.
upb_msg_iter i; upb_msg_field_iter i;
for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&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_fielddef *f = upb_msg_iter_field(&i);
if (!upb_fielddef_issubmsg(f)) continue; 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 // Check that there are no closure mismatches due to missing Start* handlers
// or subhandlers with different type-level types. // or subhandlers with different type-level types.
upb_msg_iter j; upb_msg_field_iter j;
for(upb_msg_begin(&j, h->msg); !upb_msg_done(&j); upb_msg_next(&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); const upb_fielddef *f = upb_msg_iter_field(&j);
if (upb_fielddef_isseq(f)) { if (upb_fielddef_isseq(f)) {

@ -437,9 +437,9 @@ void printer_sethandlers(const void *closure, upb_handlers *h) {
} \ } \
break; break;
upb_msg_iter i; upb_msg_field_iter i;
upb_msg_begin(&i, upb_handlers_msgdef(h)); upb_msg_field_begin(&i, upb_handlers_msgdef(h));
for(; !upb_msg_done(&i); upb_msg_next(&i)) { for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) {
const upb_fielddef *f = upb_msg_iter_field(&i); const upb_fielddef *f = upb_msg_iter_field(&i);
upb_handlerattr name_attr = UPB_HANDLERATTR_INITIALIZER; upb_handlerattr name_attr = UPB_HANDLERATTR_INITIALIZER;

@ -762,8 +762,10 @@ static void compile_method(compiler *c, upb_pbdecodermethod *method) {
putsel(c, OP_STARTMSG, UPB_STARTMSG_SELECTOR, h); putsel(c, OP_STARTMSG, UPB_STARTMSG_SELECTOR, h);
label(c, LABEL_FIELD); label(c, LABEL_FIELD);
uint32_t* start_pc = c->pc; uint32_t* start_pc = c->pc;
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); const upb_fielddef *f = upb_msg_iter_field(&i);
upb_fieldtype_t type = upb_fielddef_type(f); 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); newmethod(h, c->group);
// Find submethods. // Find submethods.
upb_msg_iter i; upb_msg_field_iter i;
const upb_msgdef *md = upb_handlers_msgdef(h); 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_fielddef *f = upb_msg_iter_field(&i);
const upb_handlers *sub_h; const upb_handlers *sub_h;
if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE && 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 #ifdef UPB_USE_JIT_X64

@ -378,8 +378,10 @@ static void newhandlers_callback(const void *closure, upb_handlers *h) {
upb_handlers_setendmsg(h, endmsg, NULL); upb_handlers_setendmsg(h, endmsg, NULL);
const upb_msgdef *m = upb_handlers_msgdef(h); const upb_msgdef *m = upb_handlers_msgdef(h);
upb_msg_iter i; upb_msg_field_iter i;
for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&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); const upb_fielddef *f = upb_msg_iter_field(&i);
bool packed = upb_fielddef_isseq(f) && upb_fielddef_isprimitive(f) && bool packed = upb_fielddef_isseq(f) && upb_fielddef_isprimitive(f) &&
upb_fielddef_packed(f); upb_fielddef_packed(f);

@ -261,8 +261,10 @@ static void onmreg(const void *c, upb_handlers *h) {
upb_handlers_setstartmsg(h, textprinter_startmsg, NULL); upb_handlers_setstartmsg(h, textprinter_startmsg, NULL);
upb_handlers_setendmsg(h, textprinter_endmsg, NULL); upb_handlers_setendmsg(h, textprinter_endmsg, NULL);
upb_msg_iter i; upb_msg_field_iter i;
for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&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_fielddef *f = upb_msg_iter_field(&i);
upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER;
upb_handlerattr_sethandlerdata(&attr, f); upb_handlerattr_sethandlerdata(&attr, f);

@ -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. // For messages, continue the recursion by visiting all subdefs.
const upb_msgdef *m = upb_dyncast_msgdef(def); const upb_msgdef *m = upb_dyncast_msgdef(def);
if (m) { if (m) {
upb_msg_iter i; upb_msg_field_iter i;
for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&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_fielddef *f = upb_msg_iter_field(&i);
if (!upb_fielddef_hassubdef(f)) continue; if (!upb_fielddef_hassubdef(f)) continue;
// |= to avoid short-circuit; we need its side-effects. // |= 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. // Type names are resolved relative to the message in which they appear.
const char *base = upb_msgdef_fullname(m); const char *base = upb_msgdef_fullname(m);
upb_msg_iter j; upb_msg_field_iter j;
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); upb_fielddef *f = upb_msg_iter_field(&j);
const char *name = upb_fielddef_subdefname(f); const char *name = upb_fielddef_subdefname(f);
if (name && !upb_fielddef_subdef(f)) { if (name && !upb_fielddef_subdef(f)) {

@ -207,6 +207,9 @@ typedef struct {
#define UPB_STRTABLE_INIT(count, mask, ctype, size_lg2, entries) \ #define UPB_STRTABLE_INIT(count, mask, ctype, size_lg2, entries) \
{{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 { typedef struct {
upb_table t; // For entries that don't fit in the array part. 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. const _upb_value *array; // Array part of the table. See const note above.

Loading…
Cancel
Save