summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--tests/bindings/lua/test_upb.lua24
-rw-r--r--upb/bindings/lua/upb.c168
-rw-r--r--upb/bindings/lua/upb.h2
-rw-r--r--upb/bindings/lua/upb.lua21
-rw-r--r--upb/def.c139
-rw-r--r--upb/def.h36
-rw-r--r--upb/refcounted.h7
-rw-r--r--upb/structdefs.int.h36
-rw-r--r--upb/table.int.h13
10 files changed, 371 insertions, 80 deletions
diff --git a/Makefile b/Makefile
index 966168b..142a5cc 100644
--- a/Makefile
+++ b/Makefile
@@ -109,6 +109,7 @@ dep:
clean_leave_profile:
@rm -rf obj lib
@rm -f tests/google_message?.h
+ @rm -f tests/json/test.upbdefs.o
@rm -f $(TESTS) tests/testmain.o tests/t.*
@rm -rf tools/upbc deps
@rm -rf upb/bindings/python/build
@@ -455,8 +456,8 @@ LUATESTS = \
.PHONY: clean_lua testlua lua
testlua: lua
- @set -e # Abort on error.
- @for test in $(LUATESTS) ; do \
+ @set -e; \
+ for test in $(LUATESTS) ; do \
echo LUA $$test; \
LUA_PATH="third_party/lunit/?.lua;upb/bindings/lua/?.lua" \
LUA_CPATH=upb/bindings/lua/?.so \
diff --git a/tests/bindings/lua/test_upb.lua b/tests/bindings/lua/test_upb.lua
index f32a690..7c14b58 100644
--- a/tests/bindings/lua/test_upb.lua
+++ b/tests/bindings/lua/test_upb.lua
@@ -16,6 +16,18 @@ function iter_to_array(iter)
return arr
end
+function test_msgdef()
+ local f2 = upb.FieldDef{name = "field2", number = 1, type = upb.TYPE_INT32}
+ local o = upb.OneofDef{name = "field1", fields = {f2}}
+ local f = upb.FieldDef{name = "field3", number = 2, type = upb.TYPE_INT32}
+
+ local m = upb.MessageDef{fields = {o, f}}
+
+ assert_equal(f, m:lookup_name("field3"))
+ assert_equal(o, m:lookup_name("field1"))
+ assert_equal(f2, m:lookup_name("field2"))
+end
+
function test_fielddef()
local f = upb.FieldDef()
assert_false(f:is_frozen())
@@ -314,6 +326,18 @@ function test_msgdef_errors()
}
end)
+ assert_error(function()
+ -- Duplicate field name.
+ upb.MessageDef{
+ fields = {
+ upb.OneofDef{name = "field1", fields = {
+ upb.FieldDef{name = "field2", number = 1, type = upb.TYPE_INT32},
+ }},
+ upb.FieldDef{name = "field2", number = 2, type = upb.TYPE_INT32}
+ }
+ }
+ end)
+
-- attempt to set a name with embedded NULLs.
assert_error_match("names cannot have embedded NULLs", function()
md:set_full_name("abc\0def")
diff --git a/upb/bindings/lua/upb.c b/upb/bindings/lua/upb.c
index 7a66180..4768212 100644
--- a/upb/bindings/lua/upb.c
+++ b/upb/bindings/lua/upb.c
@@ -31,14 +31,16 @@
#include "upb/shim/shim.h"
/* Lua metatable types. */
-#define LUPB_MSG "lupb.msg"
-#define LUPB_ARRAY "lupb.array"
-#define LUPB_MSGDEF "lupb.msgdef"
#define LUPB_ENUMDEF "lupb.enumdef"
#define LUPB_FIELDDEF "lupb.fielddef"
#define LUPB_FILEDEF "lupb.filedef"
+#define LUPB_MSGDEF "lupb.msgdef"
+#define LUPB_ONEOFDEF "lupb.oneof"
#define LUPB_SYMTAB "lupb.symtab"
+#define LUPB_ARRAY "lupb.array"
+#define LUPB_MSG "lupb.msg"
+
/* Other table constants. */
#define LUPB_OBJCACHE "lupb.objcache"
@@ -509,6 +511,11 @@ static int lupb_def_setfullname(lua_State *L) {
/* lupb_fielddef **************************************************************/
+void lupb_fielddef_pushwrapper(lua_State *L, const upb_fielddef *f,
+ const void *ref_donor) {
+ lupb_def_pushwrapper(L, upb_fielddef_upcast(f), ref_donor);
+}
+
const upb_fielddef *lupb_fielddef_check(lua_State *L, int narg) {
return lupb_refcounted_check(L, narg, LUPB_FIELDDEF);
}
@@ -530,8 +537,7 @@ static int lupb_fielddef_new(lua_State *L) {
static int lupb_fielddef_containingtype(lua_State *L) {
const upb_fielddef *f = lupb_fielddef_check(L, 1);
- lupb_def_pushwrapper(L, upb_msgdef_upcast(upb_fielddef_containingtype(f)),
- NULL);
+ lupb_msgdef_pushwrapper(L, upb_fielddef_containingtype(f), NULL);
return 1;
}
@@ -857,6 +863,102 @@ static const struct luaL_Reg lupb_fielddef_m[] = {
};
+/* lupb_oneofdef **************************************************************/
+
+void lupb_oneofdef_pushwrapper(lua_State *L, const upb_oneofdef *o,
+ const void *ref_donor) {
+ lupb_refcounted_pushwrapper(L, upb_oneofdef_upcast(o), LUPB_ONEOFDEF,
+ ref_donor, sizeof(void *));
+}
+
+const upb_oneofdef *lupb_oneofdef_check(lua_State *L, int narg) {
+ return lupb_refcounted_check(L, narg, LUPB_ONEOFDEF);
+}
+
+static upb_oneofdef *lupb_oneofdef_checkmutable(lua_State *L, int narg) {
+ const upb_oneofdef *o = lupb_oneofdef_check(L, narg);
+ if (upb_oneofdef_isfrozen(o))
+ luaL_error(L, "not allowed on frozen value");
+ return (upb_oneofdef*)o;
+}
+
+static int lupb_oneofdef_new(lua_State *L) {
+ upb_oneofdef *o = upb_oneofdef_new(&o);
+ lupb_refcounted_pushnewrapper(L, upb_oneofdef_upcast(o), LUPB_ONEOFDEF, &o);
+ return 1;
+}
+
+/* Getters */
+
+static int lupb_oneofdef_containingtype(lua_State *L) {
+ const upb_oneofdef *o = lupb_oneofdef_check(L, 1);
+ lupb_def_pushwrapper(L, upb_msgdef_upcast(upb_oneofdef_containingtype(o)),
+ NULL);
+ return 1;
+}
+
+static int lupb_oneofdef_field(lua_State *L) {
+ const upb_oneofdef *o = lupb_oneofdef_check(L, 1);
+ int type = lua_type(L, 2);
+ const upb_fielddef *f;
+ if (type == LUA_TNUMBER) {
+ f = upb_oneofdef_itof(o, lua_tointeger(L, 2));
+ } else if (type == LUA_TSTRING) {
+ f = upb_oneofdef_ntofz(o, lua_tostring(L, 2));
+ } else {
+ const char *msg = lua_pushfstring(L, "number or string expected, got %s",
+ luaL_typename(L, 2));
+ return luaL_argerror(L, 2, msg);
+ }
+
+ lupb_def_pushwrapper(L, upb_fielddef_upcast(f), NULL);
+ return 1;
+}
+
+static int lupb_oneofdef_len(lua_State *L) {
+ const upb_oneofdef *o = lupb_oneofdef_check(L, 1);
+ lua_pushinteger(L, upb_oneofdef_numfields(o));
+ return 1;
+}
+
+static int lupb_oneofdef_name(lua_State *L) {
+ const upb_oneofdef *o = lupb_oneofdef_check(L, 1);
+ lua_pushstring(L, upb_oneofdef_name(o));
+ return 1;
+}
+
+/* Setters */
+
+static int lupb_oneofdef_add(lua_State *L) {
+ upb_oneofdef *o = lupb_oneofdef_checkmutable(L, 1);
+ upb_fielddef *f = lupb_fielddef_checkmutable(L, 2);
+ CHK(upb_oneofdef_addfield(o, f, NULL, &status));
+ return 0;
+}
+
+static int lupb_oneofdef_setname(lua_State *L) {
+ upb_oneofdef *o = lupb_oneofdef_checkmutable(L, 1);
+ CHK(upb_oneofdef_setname(o, lupb_checkname(L, 2), &status));
+ return 0;
+}
+
+static const struct luaL_Reg lupb_oneofdef_m[] = {
+ {"containing_type", lupb_oneofdef_containingtype},
+ {"field", lupb_oneofdef_field},
+ {"name", lupb_oneofdef_name},
+
+ {"add", lupb_oneofdef_add},
+ {"set_name", lupb_oneofdef_setname},
+
+ {NULL, NULL}
+};
+
+static const struct luaL_Reg lupb_oneofdef_mm[] = {
+ {"__len", lupb_oneofdef_len},
+ {NULL, NULL}
+};
+
+
/* lupb_msgdef ****************************************************************/
typedef struct {
@@ -874,6 +976,11 @@ static size_t lupb_msgdef_sizeof() {
return sizeof(lupb_msgdef);
}
+void lupb_msgdef_pushwrapper(lua_State *L, const upb_msgdef *m,
+ const void *ref_donor) {
+ lupb_def_pushwrapper(L, upb_msgdef_upcast(m), ref_donor);
+}
+
const upb_msgdef *lupb_msgdef_check(lua_State *L, int narg) {
return lupb_refcounted_check(L, narg, LUPB_MSGDEF);
}
@@ -912,8 +1019,15 @@ static void lupb_msgdef_init(lua_State *L) {
static int lupb_msgdef_add(lua_State *L) {
upb_msgdef *m = lupb_msgdef_checkmutable(L, 1);
- upb_fielddef *f = lupb_fielddef_checkmutable(L, 2);
- CHK(upb_msgdef_addfield(m, f, NULL, &status));
+
+ /* Both oneofs and fields can be added. */
+ if (luaL_testudata(L, 2, LUPB_FIELDDEF)) {
+ upb_fielddef *f = lupb_fielddef_checkmutable(L, 2);
+ CHK(upb_msgdef_addfield(m, f, NULL, &status));
+ } else if (luaL_testudata(L, 2, LUPB_ONEOFDEF)) {
+ upb_oneofdef *o = lupb_oneofdef_checkmutable(L, 2);
+ CHK(upb_msgdef_addoneof(m, o, NULL, &status));
+ }
return 0;
}
@@ -941,7 +1055,21 @@ static int lupb_msgdef_field(lua_State *L) {
return 1;
}
-static int lupb_msgiter_next(lua_State *L) {
+static int lupb_msgdef_lookupname(lua_State *L) {
+ const upb_msgdef *m = lupb_msgdef_check(L, 1);
+ const upb_fielddef *f;
+ const upb_oneofdef *o;
+ if (!upb_msgdef_lookupnamez(m, lua_tostring(L, 2), &f, &o)) {
+ lua_pushnil(L);
+ } else if (o) {
+ lupb_oneofdef_pushwrapper(L, o, NULL);
+ } else {
+ lupb_fielddef_pushwrapper(L, f, NULL);
+ }
+ return 1;
+}
+
+static int lupb_msgfielditer_next(lua_State *L) {
upb_msg_field_iter *i = lua_touserdata(L, lua_upvalueindex(1));
if (upb_msg_field_done(i)) return 0;
lupb_def_pushwrapper(L, upb_fielddef_upcast(upb_msg_iter_field(i)), NULL);
@@ -955,7 +1083,25 @@ static int lupb_msgdef_fields(lua_State *L) {
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);
+ lua_pushcclosure(L, &lupb_msgfielditer_next, 2);
+ return 1;
+}
+
+static int lupb_msgoneofiter_next(lua_State *L) {
+ upb_msg_oneof_iter *i = lua_touserdata(L, lua_upvalueindex(1));
+ if (upb_msg_oneof_done(i)) return 0;
+ lupb_oneofdef_pushwrapper(L, upb_msg_iter_oneof(i), NULL);
+ upb_msg_oneof_next(i);
+ return 1;
+}
+
+static int lupb_msgdef_oneofs(lua_State *L) {
+ const upb_msgdef *m = lupb_msgdef_check(L, 1);
+ upb_msg_oneof_iter *i = lua_newuserdata(L, sizeof(upb_msg_oneof_iter));
+ upb_msg_oneof_begin(i, m);
+ /* Need to guarantee that the msgdef outlives the iter. */
+ lua_pushvalue(L, 1);
+ lua_pushcclosure(L, &lupb_msgoneofiter_next, 2);
return 1;
}
@@ -982,6 +1128,8 @@ static const struct luaL_Reg lupb_msgdef_m[] = {
{"add", lupb_msgdef_add},
{"field", lupb_msgdef_field},
{"fields", lupb_msgdef_fields},
+ {"lookup_name", lupb_msgdef_lookupname},
+ {"oneofs", lupb_msgdef_oneofs},
{"syntax", lupb_msgdef_syntax},
{"_map_entry", lupb_msgdef_mapentry},
@@ -1900,6 +2048,7 @@ static const struct luaL_Reg lupb_toplevel_m[] = {
{"FileDef", lupb_filedef_new},
{"Message", lupb_msg_new},
{"MessageDef", lupb_msgdef_new},
+ {"OneofDef", lupb_oneofdef_new},
{"SymbolTable", lupb_symtab_new},
{"freeze", lupb_freeze},
{"load_descriptor", lupb_loaddescriptor},
@@ -1953,6 +2102,7 @@ int luaopen_upb_c(lua_State *L) {
lupb_register_type(L, LUPB_ENUMDEF, lupb_enumdef_m, lupb_enumdef_mm, true);
lupb_register_type(L, LUPB_FIELDDEF, lupb_fielddef_m, NULL, true);
lupb_register_type(L, LUPB_FILEDEF, lupb_filedef_m, lupb_filedef_mm, true);
+ lupb_register_type(L, LUPB_ONEOFDEF, lupb_oneofdef_m, lupb_oneofdef_mm, true);
lupb_register_type(L, LUPB_SYMTAB, lupb_symtab_m, NULL, true);
/* Refcounted but with custom __gc. */
diff --git a/upb/bindings/lua/upb.h b/upb/bindings/lua/upb.h
index 6957ec2..f37ed9a 100644
--- a/upb/bindings/lua/upb.h
+++ b/upb/bindings/lua/upb.h
@@ -94,6 +94,8 @@ bool lupb_def_pushwrapper(lua_State *L, const upb_def *def,
const void *ref_donor);
void lupb_def_pushnewrapper(lua_State *L, const upb_def *def,
const void *ref_donor);
+void lupb_msgdef_pushwrapper(lua_State *L, const upb_msgdef *m,
+ const void *ref_donor);
void lupb_symtab_pushwrapper(lua_State *L, const upb_symtab *s,
const void *ref_donor);
void lupb_symtab_pushnewrapper(lua_State *L, const upb_symtab *s,
diff --git a/upb/bindings/lua/upb.lua b/upb/bindings/lua/upb.lua
index ee0ad4e..728852e 100644
--- a/upb/bindings/lua/upb.lua
+++ b/upb/bindings/lua/upb.lua
@@ -66,6 +66,7 @@ end
local RealFieldDef = upb.FieldDef
local RealEnumDef = upb.EnumDef
local RealMessageDef = upb.MessageDef
+local RealOneofDef = upb.OneofDef
local RealSymbolTable = upb.SymbolTable
-- FieldDef constructor; a wrapper around the real constructor that can
@@ -136,6 +137,26 @@ upb.EnumDef = function(init)
return e
end
+-- OneofDef constructor; a wrapper around the real constructor that can
+-- set initial properties.
+--
+-- User can specify initialization values like so:
+-- upb.OneofDef{name="foo", fields={...}}
+upb.OneofDef = function(init)
+ local o = RealOneofDef()
+
+ if init then
+ for _, val in pairs(init.fields or {}) do
+ o:add(val)
+ end
+ init.fields = nil
+
+ set_named(o, init)
+ end
+
+ return o
+end
+
-- SymbolTable constructor; a wrapper around the real constructor that can
-- add an initial set of defs.
upb.SymbolTable = function(defs)
diff --git a/upb/def.c b/upb/def.c
index 0febf47..621eefc 100644
--- a/upb/def.c
+++ b/upb/def.c
@@ -66,6 +66,22 @@ static bool upb_isident(const char *str, size_t len, bool full, upb_status *s) {
return !start;
}
+static bool upb_isoneof(const upb_refcounted *def) {
+ return def->vtbl == &upb_oneofdef_vtbl;
+}
+
+static bool upb_isfield(const upb_refcounted *def) {
+ return def->vtbl == &upb_fielddef_vtbl;
+}
+
+static const upb_oneofdef *upb_trygetoneof(const upb_refcounted *def) {
+ return upb_isoneof(def) ? (const upb_oneofdef*)def : NULL;
+}
+
+static const upb_fielddef *upb_trygetfield(const upb_refcounted *def) {
+ return upb_isfield(def) ? (const upb_fielddef*)def : NULL;
+}
+
/* upb_def ********************************************************************/
@@ -437,12 +453,17 @@ static void upb_enumdef_free(upb_refcounted *r) {
upb_gfree(e);
}
+const struct upb_refcounted_vtbl upb_enumdef_vtbl = {NULL, &upb_enumdef_free};
+
upb_enumdef *upb_enumdef_new(const void *owner) {
- static const struct upb_refcounted_vtbl vtbl = {NULL, &upb_enumdef_free};
upb_enumdef *e = upb_gmalloc(sizeof(*e));
if (!e) return NULL;
- if (!upb_def_init(upb_enumdef_upcast_mutable(e), UPB_DEF_ENUM, &vtbl, owner))
+
+ if (!upb_def_init(upb_enumdef_upcast_mutable(e), UPB_DEF_ENUM,
+ &upb_enumdef_vtbl, owner)) {
goto err2;
+ }
+
if (!upb_strtable_init(&e->ntoi, UPB_CTYPE_INT32)) goto err2;
if (!upb_inttable_init(&e->iton, UPB_CTYPE_CSTR)) goto err1;
return e;
@@ -663,11 +684,13 @@ static bool enumdefaultint32(const upb_fielddef *f, int32_t *val) {
return false;
}
+const struct upb_refcounted_vtbl upb_fielddef_vtbl = {visitfield, freefield};
+
upb_fielddef *upb_fielddef_new(const void *o) {
- static const struct upb_refcounted_vtbl vtbl = {visitfield, freefield};
upb_fielddef *f = upb_gmalloc(sizeof(*f));
if (!f) return NULL;
- if (!upb_def_init(upb_fielddef_upcast_mutable(f), UPB_DEF_FIELD, &vtbl, o)) {
+ if (!upb_def_init(upb_fielddef_upcast_mutable(f), UPB_DEF_FIELD,
+ &upb_fielddef_vtbl, o)) {
upb_gfree(f);
return NULL;
}
@@ -1378,31 +1401,32 @@ static void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit,
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_msgdef_upcast_mutable(m));
upb_gfree(m);
}
+const struct upb_refcounted_vtbl upb_msgdef_vtbl = {visitmsg, freemsg};
+
upb_msgdef *upb_msgdef_new(const void *owner) {
- static const struct upb_refcounted_vtbl vtbl = {visitmsg, freemsg};
upb_msgdef *m = upb_gmalloc(sizeof(*m));
if (!m) return NULL;
- if (!upb_def_init(upb_msgdef_upcast_mutable(m), UPB_DEF_MSG, &vtbl, owner))
+
+ if (!upb_def_init(upb_msgdef_upcast_mutable(m), UPB_DEF_MSG, &upb_msgdef_vtbl,
+ owner)) {
goto err2;
- 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;
+ }
+
+ if (!upb_inttable_init(&m->itof, UPB_CTYPE_PTR)) goto err2;
+ if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err1;
m->map_entry = false;
m->syntax = UPB_SYNTAX_PROTO2;
return m;
err1:
- upb_strtable_uninit(&m->ntof);
-err2:
upb_inttable_uninit(&m->itof);
-err3:
+err2:
upb_gfree(m);
return NULL;
}
@@ -1484,9 +1508,11 @@ static bool check_field_add(const upb_msgdef *m, const upb_fielddef *f,
} 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");
+ } else if (upb_msgdef_itof(m, upb_fielddef_number(f))) {
+ upb_status_seterrmsg(s, "duplicate field number");
+ return false;
+ } else if (upb_strtable_lookup(&m->ntof, upb_fielddef_name(f), NULL)) {
+ upb_status_seterrmsg(s, "name conflicts with existing field or oneof");
return false;
}
return true;
@@ -1547,8 +1573,8 @@ bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor,
} 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");
+ } else if (upb_strtable_lookup(&m->ntof, upb_oneofdef_name(o), NULL)) {
+ upb_status_seterrmsg(s, "name conflicts with existing field or oneof");
return false;
}
@@ -1565,7 +1591,7 @@ bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor,
/* Add oneof itself first. */
o->parent = m;
- upb_strtable_insert(&m->ntoo, upb_oneofdef_name(o), upb_value_ptr(o));
+ upb_strtable_insert(&m->ntof, upb_oneofdef_name(o), upb_value_ptr(o));
upb_ref2(o, m);
upb_ref2(m, o);
@@ -1589,23 +1615,47 @@ const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) {
const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
size_t len) {
upb_value val;
- return upb_strtable_lookup2(&m->ntof, name, len, &val) ?
- upb_value_getptr(val) : NULL;
+
+ if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+ return NULL;
+ }
+
+ return upb_trygetfield(upb_value_getptr(val));
}
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;
+
+ if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+ return NULL;
+ }
+
+ return upb_trygetoneof(upb_value_getptr(val));
+}
+
+bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
+ const upb_fielddef **f, const upb_oneofdef **o) {
+ upb_value val;
+
+ if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+ return false;
+ }
+
+ *o = upb_trygetoneof(upb_value_getptr(val));
+ *f = upb_trygetfield(upb_value_getptr(val));
+ assert((*o != NULL) ^ (*f != NULL)); /* Exactly one of the two should be set. */
+ return true;
}
int upb_msgdef_numfields(const upb_msgdef *m) {
- return upb_strtable_count(&m->ntof);
+ /* The number table contains only fields. */
+ return upb_inttable_count(&m->itof);
}
int upb_msgdef_numoneofs(const upb_msgdef *m) {
- return upb_strtable_count(&m->ntoo);
+ /* The name table includes oneofs, and the number table does not. */
+ return upb_strtable_count(&m->ntof) - upb_inttable_count(&m->itof);
}
void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry) {
@@ -1636,10 +1686,21 @@ void upb_msg_field_iter_setdone(upb_msg_field_iter *iter) {
}
void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m) {
- upb_strtable_begin(iter, &m->ntoo);
+ upb_strtable_begin(iter, &m->ntof);
+ /* We need to skip past any initial fields. */
+ while (!upb_strtable_done(iter) &&
+ !upb_isoneof(upb_value_getptr(upb_strtable_iter_value(iter)))) {
+ upb_strtable_next(iter);
+ }
}
-void upb_msg_oneof_next(upb_msg_oneof_iter *iter) { upb_strtable_next(iter); }
+void upb_msg_oneof_next(upb_msg_oneof_iter *iter) {
+ /* We need to skip past fields to return only oneofs. */
+ do {
+ upb_strtable_next(iter);
+ } while (!upb_strtable_done(iter) &&
+ !upb_isoneof(upb_value_getptr(upb_strtable_iter_value(iter))));
+}
bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter) {
return upb_strtable_done(iter);
@@ -1676,16 +1737,26 @@ static void freeoneof(upb_refcounted *r) {
upb_gfree(o);
}
+const struct upb_refcounted_vtbl upb_oneofdef_vtbl = {visitoneof, freeoneof};
+
upb_oneofdef *upb_oneofdef_new(const void *owner) {
- static const struct upb_refcounted_vtbl vtbl = {visitoneof, freeoneof};
upb_oneofdef *o = upb_gmalloc(sizeof(*o));
+
+ if (!o) {
+ return NULL;
+ }
+
o->parent = NULL;
- if (!o) return NULL;
- if (!upb_refcounted_init(upb_oneofdef_upcast_mutable(o), &vtbl, owner))
- goto err2;
o->name = NULL;
+
+ if (!upb_refcounted_init(upb_oneofdef_upcast_mutable(o), &upb_oneofdef_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:
@@ -1879,8 +1950,9 @@ static void freefiledef(upb_refcounted *r) {
upb_gfree(f);
}
+const struct upb_refcounted_vtbl upb_filedef_vtbl = {visitfiledef, freefiledef};
+
upb_filedef *upb_filedef_new(const void *owner) {
- static const struct upb_refcounted_vtbl vtbl = {visitfiledef, freefiledef};
upb_filedef *f = upb_gmalloc(sizeof(*f));
if (!f) {
@@ -1891,7 +1963,8 @@ upb_filedef *upb_filedef_new(const void *owner) {
f->name = NULL;
f->syntax = UPB_SYNTAX_PROTO2;
- if (!upb_refcounted_init(upb_filedef_upcast_mutable(f), &vtbl, owner)) {
+ if (!upb_refcounted_init(upb_filedef_upcast_mutable(f), &upb_filedef_vtbl,
+ owner)) {
goto err;
}
diff --git a/upb/def.h b/upb/def.h
index 87e1766..2cfaebc 100644
--- a/upb/def.h
+++ b/upb/def.h
@@ -668,6 +668,10 @@ UPB_END_EXTERN_C
typedef upb_inttable_iter upb_msg_field_iter;
typedef upb_strtable_iter upb_msg_oneof_iter;
+/* Well-known field tag numbers for map-entry messages. */
+#define UPB_MAPENTRY_KEY 1
+#define UPB_MAPENTRY_VALUE 2
+
#ifdef __cplusplus
/* Structure that describes a single .proto message type.
@@ -921,16 +925,20 @@ UPB_REFCOUNTED_CMETHODS(upb_msgdef, upb_msgdef_upcast2)
bool upb_msgdef_freeze(upb_msgdef *m, upb_status *status);
+upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner);
const char *upb_msgdef_fullname(const upb_msgdef *m);
const char *upb_msgdef_name(const upb_msgdef *m);
+int upb_msgdef_numoneofs(const upb_msgdef *m);
upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m);
-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);
+bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, upb_status *s);
+void upb_msgdef_setmapentry(upb_msgdef *m, bool map_entry);
+bool upb_msgdef_mapentry(const upb_msgdef *m);
+bool upb_msgdef_setsyntax(upb_msgdef *m, upb_syntax_t syntax);
/* Field lookup in a couple of different variations:
* - itof = int to field
@@ -972,19 +980,21 @@ UPB_INLINE upb_oneofdef *upb_msgdef_ntoo_mutable(upb_msgdef *m,
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);
-bool upb_msgdef_setsyntax(upb_msgdef *m, upb_syntax_t syntax);
+/* Lookup of either field or oneof by name. Returns whether either was found.
+ * If the return is true, then the found def will be set, and the non-found
+ * one set to NULL. */
+bool upb_msgdef_lookupname(const upb_msgdef *m, const char *name, size_t len,
+ const upb_fielddef **f, const upb_oneofdef **o);
-/* Well-known field tag numbers for map-entry messages. */
-#define UPB_MAPENTRY_KEY 1
-#define UPB_MAPENTRY_VALUE 2
-
-const upb_oneofdef *upb_msgdef_findoneof(const upb_msgdef *m,
- const char *name);
-int upb_msgdef_numoneofs(const upb_msgdef *m);
+UPB_INLINE bool upb_msgdef_lookupnamez(const upb_msgdef *m, const char *name,
+ const upb_fielddef **f,
+ const upb_oneofdef **o) {
+ return upb_msgdef_lookupname(m, name, strlen(name), f, o);
+}
-/* upb_msg_field_iter i;
+/* Iteration over fields and oneofs. For example:
+ *
+ * upb_msg_field_iter i;
* for(upb_msg_field_begin(&i, m);
* !upb_msg_field_done(&i);
* upb_msg_field_next(&i)) {
diff --git a/upb/refcounted.h b/upb/refcounted.h
index 54c1127..115fc43 100644
--- a/upb/refcounted.h
+++ b/upb/refcounted.h
@@ -103,10 +103,11 @@ struct upb_refcounted {
#ifdef UPB_DEBUG_REFS
extern upb_alloc upb_alloc_debugrefs;
-#define UPB_REFCOUNT_INIT(refs, ref2s) \
- {&static_refcount, NULL, NULL, 0, true, refs, ref2s}
+#define UPB_REFCOUNT_INIT(vtbl, refs, ref2s) \
+ {&static_refcount, NULL, vtbl, 0, true, refs, ref2s}
#else
-#define UPB_REFCOUNT_INIT(refs, ref2s) {&static_refcount, NULL, NULL, 0, true}
+#define UPB_REFCOUNT_INIT(vtbl, refs, ref2s) \
+ {&static_refcount, NULL, vtbl, 0, true}
#endif
UPB_BEGIN_EXTERN_C
diff --git a/upb/structdefs.int.h b/upb/structdefs.int.h
index da9a2ec..6b19537 100644
--- a/upb/structdefs.int.h
+++ b/upb/structdefs.int.h
@@ -43,8 +43,8 @@ struct upb_def {
bool came_from_user;
};
-#define UPB_DEF_INIT(name, type, refs, ref2s) \
- { UPB_REFCOUNT_INIT(refs, ref2s), name, NULL, type, false }
+#define UPB_DEF_INIT(name, type, vtbl, refs, ref2s) \
+ { UPB_REFCOUNT_INIT(vtbl, refs, ref2s), name, NULL, type, false }
/* upb_fielddef ***************************************************************/
@@ -84,12 +84,14 @@ struct upb_fielddef {
uint32_t index_;
};
+extern const struct upb_refcounted_vtbl upb_fielddef_vtbl;
+
#define UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, is_extension, lazy, \
packed, name, num, msgdef, subdef, selector_base, \
index, defaultval, refs, ref2s) \
{ \
- UPB_DEF_INIT(name, UPB_DEF_FIELD, refs, ref2s), defaultval, {msgdef}, \
- {subdef}, NULL, false, false, \
+ UPB_DEF_INIT(name, UPB_DEF_FIELD, &upb_fielddef_vtbl, refs, ref2s), \
+ defaultval, {msgdef}, {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 \
}
@@ -105,10 +107,7 @@ struct upb_msgdef {
/* Tables for looking up fields by number and name. */
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 */
+ upb_strtable ntof; /* name to field/oneof */
/* Is this a map-entry message? */
bool map_entry;
@@ -119,14 +118,15 @@ struct upb_msgdef {
/* TODO(haberman): proper extension ranges (there can be multiple). */
};
+extern const struct upb_refcounted_vtbl upb_msgdef_vtbl;
+
/* 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, \
map_entry, syntax, refs, ref2s) \
{ \
- UPB_DEF_INIT(name, UPB_DEF_MSG, refs, ref2s), selector_count, \
- submsg_field_count, itof, ntof, \
- UPB_EMPTY_STRTABLE_INIT(UPB_CTYPE_PTR), map_entry, syntax \
+ UPB_DEF_INIT(name, UPB_DEF_MSG, &upb_fielddef_vtbl, refs, ref2s), \
+ selector_count, submsg_field_count, itof, ntof, map_entry, syntax \
}
@@ -140,8 +140,11 @@ struct upb_enumdef {
int32_t defaultval;
};
+extern const struct upb_refcounted_vtbl upb_enumdef_vtbl;
+
#define UPB_ENUMDEF_INIT(name, ntoi, iton, defaultval, refs, ref2s) \
- { UPB_DEF_INIT(name, UPB_DEF_ENUM, refs, ref2s), ntoi, iton, defaultval }
+ { UPB_DEF_INIT(name, UPB_DEF_ENUM, &upb_enumdef_vtbl, refs, ref2s), ntoi, \
+ iton, defaultval }
/* upb_oneofdef ***************************************************************/
@@ -155,8 +158,10 @@ struct upb_oneofdef {
const upb_msgdef *parent;
};
+extern const struct upb_refcounted_vtbl upb_oneofdef_vtbl;
+
#define UPB_ONEOFDEF_INIT(name, ntof, itof, refs, ref2s) \
- { UPB_REFCOUNT_INIT(refs, ref2s), name, ntof, itof }
+ { UPB_REFCOUNT_INIT(&upb_oneofdef_vtbl, refs, ref2s), name, ntof, itof }
/* upb_symtab *****************************************************************/
@@ -167,9 +172,6 @@ struct upb_symtab {
upb_strtable symtab;
};
-#define UPB_SYMTAB_INIT(symtab, refs, ref2s) \
- { UPB_REFCOUNT_INIT(refs, ref2s), symtab }
-
struct upb_filedef {
upb_refcounted base;
@@ -181,4 +183,6 @@ struct upb_filedef {
upb_inttable deps;
};
+extern const struct upb_refcounted_vtbl upb_filedef_vtbl;
+
#endif /* UPB_STATICINIT_H_ */
diff --git a/upb/table.int.h b/upb/table.int.h
index d908196..131a74f 100644
--- a/upb/table.int.h
+++ b/upb/table.int.h
@@ -261,13 +261,18 @@ typedef struct {
} upb_table;
#ifdef NDEBUG
-#define UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries) \
- {count, mask, ctype, size_lg2, entries}
+# define UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries) \
+ {count, mask, ctype, size_lg2, entries}
#else
+# ifdef UPB_DEBUG_REFS
/* At the moment the only mutable tables we statically initialize are debug
* ref tables. */
-#define UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries) \
- {count, mask, ctype, size_lg2, entries, &upb_alloc_debugrefs}
+# define UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries) \
+ {count, mask, ctype, size_lg2, entries, &upb_alloc_debugrefs}
+# else
+# define UPB_TABLE_INIT(count, mask, ctype, size_lg2, entries) \
+ {count, mask, ctype, size_lg2, entries, NULL}
+# endif
#endif
typedef struct {
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback