Merge from Google-internal development:

- rewritten decoder; interpreted decoder is bytecode-based,
  JIT decoder no longer falls back to the interpreter.
- C++ improvements: C++11-compatible iterators, upb::reffed_ptr
  for RAII refcounting, better upcast/downcast support.
- removed the gross upb_value abstraction from public upb.h.
pull/13171/head
Josh Haberman 11 years ago
parent 61109fca1f
commit 26d98ca94f
  1. 7
      benchmarks/google_messages.proto
  2. 29
      bindings/lua/table.c
  3. 134
      bindings/lua/upb.c
  4. 48
      tests/test_cpp.cc
  5. 213
      tests/test_decoder.cc
  6. 30
      tests/test_def.c
  7. 22
      tests/test_table.cc
  8. 4
      tests/test_varint.c
  9. 22
      tests/test_vs_proto2.cc
  10. 82
      tools/dump_cinit.lua
  11. 6
      tools/test_cinit.lua
  12. 22
      upb/bytestream.upb.c
  13. 2
      upb/bytestream.upb.h
  14. 253
      upb/def.c
  15. 608
      upb/def.h
  16. 656
      upb/descriptor/descriptor.upb.c
  17. 336
      upb/descriptor/descriptor.upb.h
  18. 133
      upb/descriptor/reader.c
  19. 12
      upb/descriptor/reader.h
  20. 37
      upb/google/bridge.cc
  21. 107
      upb/handlers-inl.h
  22. 29
      upb/handlers.c
  23. 9
      upb/handlers.h
  24. 855
      upb/pb/compile_decoder.c
  25. 368
      upb/pb/compile_decoder_x64.c
  26. 1087
      upb/pb/compile_decoder_x64.dasc
  27. 1198
      upb/pb/decoder.c
  28. 7
      upb/pb/decoder.h
  29. 242
      upb/pb/decoder.int.h
  30. 1086
      upb/pb/decoder_x64.dasc
  31. 6
      upb/pb/glue.c
  32. 2
      upb/pb/varint.c
  33. 5
      upb/pb/varint.int.h
  34. 200
      upb/refcounted.c
  35. 22
      upb/refcounted.h
  36. 28
      upb/shim/shim.c
  37. 16
      upb/shim/shim.h
  38. 14
      upb/sink.c
  39. 13
      upb/sink.h
  40. 16
      upb/symtab.c
  41. 4
      upb/symtab.h
  42. 146
      upb/table.c
  43. 182
      upb/table.int.h
  44. 59
      upb/upb.c
  45. 366
      upb/upb.h

@ -8,6 +8,13 @@ enum Foo {
FOO_VALUE2 = 2;
}
message Simple {
message M2 {
optional int32 f1 = 1234567;
}
optional M2 m2 = 1;
}
message SpeedMessage1 {
required string field1 = 1;
optional string field9 = 9;

@ -31,8 +31,8 @@ static void lupbtable_setnum(lua_State *L, int tab, const char *key,
lua_setfield(L, tab - 1, key);
}
static void lupbtable_pushval(lua_State *L, _upb_value val, upb_ctype_t type) {
switch (type) {
static void lupbtable_pushval(lua_State *L, _upb_value val, upb_ctype_t ctype) {
switch (ctype) {
case UPB_CTYPE_INT32:
lua_pushnumber(L, val.int32);
break;
@ -43,15 +43,15 @@ static void lupbtable_pushval(lua_State *L, _upb_value val, upb_ctype_t type) {
lua_pushstring(L, val.cstr);
break;
default:
luaL_error(L, "Unexpected type: %d", type);
luaL_error(L, "Unexpected type: %d", ctype);
}
}
// Sets a few fields common to both hash table entries and arrays.
static void lupbtable_setmetafields(lua_State *L, int type, const void *ptr) {
static void lupbtable_setmetafields(lua_State *L, int ctype, const void *ptr) {
// We tack this onto every entry so we know it even if the entries
// don't stay with the table.
lua_pushnumber(L, type);
lua_pushnumber(L, ctype);
lua_setfield(L, -2, "valtype");
// Set this to facilitate linking.
@ -60,7 +60,7 @@ static void lupbtable_setmetafields(lua_State *L, int type, const void *ptr) {
}
static void lupbtable_pushent(lua_State *L, const upb_tabent *e,
bool inttab, int type) {
bool inttab, int ctype) {
lua_newtable(L);
if (!upb_tabent_isempty(e)) {
if (inttab) {
@ -69,12 +69,12 @@ static void lupbtable_pushent(lua_State *L, const upb_tabent *e,
lua_pushstring(L, e->key.str);
}
lua_setfield(L, -2, "key");
lupbtable_pushval(L, e->val, type);
lupbtable_pushval(L, e->val, ctype);
lua_setfield(L, -2, "value");
}
lua_pushlightuserdata(L, (void*)e->next);
lua_setfield(L, -2, "next");
lupbtable_setmetafields(L, type, e);
lupbtable_setmetafields(L, ctype, e);
}
// Dumps the shared part of upb_table into a Lua table.
@ -82,12 +82,12 @@ static void lupbtable_pushtable(lua_State *L, const upb_table *t, bool inttab) {
lua_newtable(L);
lupbtable_setnum(L, -1, "count", t->count);
lupbtable_setnum(L, -1, "mask", t->mask);
lupbtable_setnum(L, -1, "type", t->type);
lupbtable_setnum(L, -1, "ctype", t->ctype);
lupbtable_setnum(L, -1, "size_lg2", t->size_lg2);
lua_newtable(L);
for (int i = 0; i < upb_table_size(t); i++) {
lupbtable_pushent(L, &t->entries[i], inttab, t->type);
lupbtable_pushent(L, &t->entries[i], inttab, t->ctype);
lua_rawseti(L, -2, i + 1);
}
lua_setfield(L, -2, "entries");
@ -103,10 +103,10 @@ static void lupbtable_pushinttable(lua_State *L, const upb_inttable *t) {
for (int i = 0; i < t->array_size; i++) {
lua_newtable(L);
if (upb_arrhas(t->array[i])) {
lupbtable_pushval(L, t->array[i], t->t.type);
lupbtable_pushval(L, t->array[i], t->t.ctype);
lua_setfield(L, -2, "val");
}
lupbtable_setmetafields(L, t->t.type, &t->array[i]);
lupbtable_setmetafields(L, t->t.ctype, &t->array[i]);
lua_rawseti(L, -2, i + 1);
}
lua_setfield(L, -2, "array");
@ -156,8 +156,9 @@ static const struct luaL_Reg lupbtable_toplevel_m[] = {
int luaopen_upbtable(lua_State *L) {
lupb_newlib(L, "upb.table", lupbtable_toplevel_m);
// We define these here because they are not public (at least at the moment).
lupbtable_setfieldi(L, "CTYPE_PTR", UPB_CTYPE_PTR);
// We define these here because they are not public.
lupbtable_setfieldi(L, "CTYPE_PTR", UPB_CTYPE_PTR);
lupbtable_setfieldi(L, "CTYPE_CSTR", UPB_CTYPE_CSTR);
lupbtable_setfieldi(L, "CTYPE_INT32", UPB_CTYPE_INT32);
lua_pushlightuserdata(L, NULL);

@ -72,76 +72,52 @@ static uint32_t chkint32(lua_State *L, int narg, const char *name) {
return n;
}
// Converts a number or bool from Lua -> upb_value.
static upb_value lupb_getvalue(lua_State *L, int narg, upb_fieldtype_t type) {
upb_value val;
if (type == UPB_TYPE_BOOL) {
// Sets a fielddef default from the given Lua value.
static void lupb_setdefault(lua_State *L, int narg, upb_fielddef *f) {
if (upb_fielddef_type(f) == UPB_TYPE_BOOL) {
if (!lua_isboolean(L, narg))
luaL_error(L, "Must explicitly pass true or false for boolean fields");
upb_value_setbool(&val, lua_toboolean(L, narg));
upb_fielddef_setdefaultbool(f, lua_toboolean(L, narg));
} else {
// Numeric type.
lua_Number num = luaL_checknumber(L, narg);
switch (type) {
switch (upb_fielddef_type(f)) {
case UPB_TYPE_INT32:
case UPB_TYPE_ENUM:
if (num > INT32_MAX || num < INT32_MIN || num != rint(num))
luaL_error(L, "Cannot convert %f to 32-bit integer", num);
upb_value_setint32(&val, num);
upb_fielddef_setdefaultint32(f, num);
break;
case UPB_TYPE_INT64:
if (num > INT64_MAX || num < INT64_MIN || num != rint(num))
luaL_error(L, "Cannot convert %f to 64-bit integer", num);
upb_value_setint64(&val, num);
upb_fielddef_setdefaultint64(f, num);
break;
case UPB_TYPE_UINT32:
if (num > UINT32_MAX || num < 0 || num != rint(num))
luaL_error(L, "Cannot convert %f to unsigned 32-bit integer", num);
upb_value_setuint32(&val, num);
upb_fielddef_setdefaultuint32(f, num);
break;
case UPB_TYPE_UINT64:
if (num > UINT64_MAX || num < 0 || num != rint(num))
luaL_error(L, "Cannot convert %f to unsigned 64-bit integer", num);
upb_value_setuint64(&val, num);
upb_fielddef_setdefaultuint64(f, num);
break;
case UPB_TYPE_DOUBLE:
if (num > DBL_MAX || num < -DBL_MAX) {
// This could happen if lua_Number was long double.
luaL_error(L, "Cannot convert %f to double", num);
}
upb_value_setdouble(&val, num);
upb_fielddef_setdefaultdouble(f, num);
break;
case UPB_TYPE_FLOAT:
if (num > FLT_MAX || num < -FLT_MAX)
luaL_error(L, "Cannot convert %f to float", num);
upb_value_setfloat(&val, num);
upb_fielddef_setdefaultfloat(f, num);
break;
default: luaL_error(L, "invalid type");
}
}
return val;
}
// Converts a upb_value -> Lua value.
static void lupb_pushvalue(lua_State *L, upb_value val, upb_fieldtype_t type) {
switch (type) {
case UPB_TYPE_INT32:
case UPB_TYPE_ENUM:
lua_pushnumber(L, upb_value_getint32(val)); break;
case UPB_TYPE_INT64:
lua_pushnumber(L, upb_value_getint64(val)); break;
case UPB_TYPE_UINT32:
lua_pushnumber(L, upb_value_getuint32(val)); break;
case UPB_TYPE_UINT64:
lua_pushnumber(L, upb_value_getuint64(val)); break;
case UPB_TYPE_DOUBLE:
lua_pushnumber(L, upb_value_getdouble(val)); break;
case UPB_TYPE_FLOAT:
lua_pushnumber(L, upb_value_getfloat(val)); break;
case UPB_TYPE_BOOL:
lua_pushboolean(L, upb_value_getbool(val)); break;
default: luaL_error(L, "internal error");
}
}
void lupb_checkstatus(lua_State *L, upb_status *s) {
@ -263,7 +239,7 @@ bool lupb_def_pushwrapper(lua_State *L, const upb_def *def, const void *owner) {
case UPB_DEF_FIELD: type = LUPB_FIELDDEF; break;
default: luaL_error(L, "unknown deftype %d", def->type);
}
return lupb_refcounted_pushwrapper(L, upb_upcast(def), type, owner);
return lupb_refcounted_pushwrapper(L, UPB_UPCAST(def), type, owner);
}
void lupb_def_pushnewrapper(lua_State *L, const upb_def *def,
@ -332,7 +308,7 @@ static void lupb_fielddef_dosetdefault(lua_State *L, upb_fielddef *f,
const char *str = lua_tolstring(L, narg, &len);
CHK(upb_fielddef_setdefaultstr(f, str, len, &status));
} else {
upb_fielddef_setdefault(f, lupb_getvalue(L, narg, upbtype));
lupb_setdefault(L, narg, f);
}
}
@ -451,7 +427,7 @@ static int lupb_fielddef_new(lua_State *L) {
upb_fielddef *f = upb_fielddef_new(&f);
int narg = lua_gettop(L);
lupb_def_pushnewrapper(L, upb_upcast(f), &f);
lupb_def_pushnewrapper(L, UPB_UPCAST(f), &f);
if (narg == 0) return 1;
@ -488,10 +464,36 @@ static int lupb_fielddef_new(lua_State *L) {
static int lupb_fielddef_default(lua_State *L) {
const upb_fielddef *f = lupb_fielddef_check(L, 1);
upb_fieldtype_t type = upb_fielddef_type(f);
if (upb_fielddef_default_is_symbolic(f))
type = UPB_TYPE_STRING;
lupb_pushvalue(L, upb_fielddef_default(f), type);
switch (upb_fielddef_type(f)) {
case UPB_TYPE_INT32:
int32:
lua_pushnumber(L, upb_fielddef_defaultint32(f)); break;
case UPB_TYPE_INT64:
lua_pushnumber(L, upb_fielddef_defaultint64(f)); break;
case UPB_TYPE_UINT32:
lua_pushnumber(L, upb_fielddef_defaultuint32(f)); break;
case UPB_TYPE_UINT64:
lua_pushnumber(L, upb_fielddef_defaultuint64(f)); break;
case UPB_TYPE_DOUBLE:
lua_pushnumber(L, upb_fielddef_defaultdouble(f)); break;
case UPB_TYPE_FLOAT:
lua_pushnumber(L, upb_fielddef_defaultfloat(f)); break;
case UPB_TYPE_BOOL:
lua_pushboolean(L, upb_fielddef_defaultbool(f)); break;
case UPB_TYPE_ENUM:
if (!upb_fielddef_default_is_symbolic(f))
goto int32;
// Fallthrough.
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES: {
size_t len;
const char *data = upb_fielddef_defaultstr(f, &len);
lua_pushlstring(L, data, len);
break;
}
case UPB_TYPE_MESSAGE:
return luaL_error(L, "Message fields do not have explicit defaults.");
}
return 1;
}
@ -542,9 +544,9 @@ static int lupb_fielddef_hassubdef(lua_State *L) {
return 1;
}
static int lupb_fielddef_msgdef(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_upcast(upb_fielddef_msgdef(f)), NULL);
lupb_def_pushwrapper(L, UPB_UPCAST(upb_fielddef_containingtype(f)), NULL);
return 1;
}
@ -596,13 +598,13 @@ static int lupb_fielddef_gc(lua_State *L) {
static const struct luaL_Reg lupb_fielddef_m[] = {
LUPB_COMMON_DEF_METHODS
{"containing_type", lupb_fielddef_containingtype},
{"default", lupb_fielddef_default},
{"getsel", lupb_fielddef_getsel},
{"has_subdef", lupb_fielddef_hassubdef},
{"intfmt", lupb_fielddef_intfmt},
{"istagdelim", lupb_fielddef_istagdelim},
{"label", lupb_fielddef_label},
{"msgdef", lupb_fielddef_msgdef},
{"name", lupb_fielddef_name},
{"number", lupb_fielddef_number},
{"subdef", lupb_fielddef_subdef},
@ -657,7 +659,7 @@ static int lupb_msgdef_gc(lua_State *L) {
static int lupb_msgdef_new(lua_State *L) {
int narg = lua_gettop(L);
upb_msgdef *md = upb_msgdef_new(&md);
lupb_def_pushnewrapper(L, upb_upcast(md), &md);
lupb_def_pushnewrapper(L, UPB_UPCAST(md), &md);
if (narg == 0) return 1;
@ -669,7 +671,7 @@ static int lupb_msgdef_new(lua_State *L) {
const char *key = lua_tostring(L, -2);
if (streql(key, "full_name")) { // full_name="MyMessage"
CHK(upb_def_setfullname(upb_upcast(md), chkname(L, -1), &status));
CHK(upb_def_setfullname(UPB_UPCAST(md), chkname(L, -1), &status));
} else if (streql(key, "fields")) { // fields={...}
// Iterate over the list of fields.
luaL_checktype(L, -1, LUA_TTABLE);
@ -730,14 +732,14 @@ static int lupb_msgdef_field(lua_State *L) {
return luaL_argerror(L, 2, msg);
}
lupb_def_pushwrapper(L, upb_upcast(f), NULL);
lupb_def_pushwrapper(L, UPB_UPCAST(f), NULL);
return 1;
}
static int lupb_msgiter_next(lua_State *L) {
upb_msg_iter *i = lua_touserdata(L, lua_upvalueindex(1));
if (upb_msg_done(i)) return 0;
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);
return 1;
}
@ -795,7 +797,7 @@ static int lupb_enumdef_gc(lua_State *L) {
static int lupb_enumdef_new(lua_State *L) {
int narg = lua_gettop(L);
upb_enumdef *e = upb_enumdef_new(&e);
lupb_def_pushnewrapper(L, upb_upcast(e), &e);
lupb_def_pushnewrapper(L, UPB_UPCAST(e), &e);
if (narg == 0) return 1;
@ -820,7 +822,7 @@ static int lupb_enumdef_new(lua_State *L) {
lua_pop(L, 2); // The key/val we got from lua_rawgeti()
}
} else if (streql(key, "full_name")) {
CHK(upb_def_setfullname(upb_upcast(e), chkname(L, -1), &status));
CHK(upb_def_setfullname(UPB_UPCAST(e), chkname(L, -1), &status));
} else {
luaL_error(L, "Unknown initializer key '%s'", key);
}
@ -933,7 +935,7 @@ void lupb_symtab_doadd(lua_State *L, upb_symtab *s, int narg) {
static int lupb_symtab_new(lua_State *L) {
int narg = lua_gettop(L);
upb_symtab *s = upb_symtab_new(&s);
lupb_refcounted_pushnewrapper(L, upb_upcast(s), LUPB_SYMTAB, &s);
lupb_refcounted_pushnewrapper(L, UPB_UPCAST(s), LUPB_SYMTAB, &s);
if (narg > 0) lupb_symtab_doadd(L, s, 1);
return 1;
}
@ -1127,20 +1129,20 @@ int luaopen_upb(lua_State *L) {
lupb_setfieldi(L, "DEF_SERVICE", UPB_DEF_SERVICE);
lupb_setfieldi(L, "DEF_ANY", UPB_DEF_ANY);
lupb_setfieldi(L, "UPB_HANDLER_INT32", UPB_HANDLER_INT32);
lupb_setfieldi(L, "UPB_HANDLER_INT64", UPB_HANDLER_INT64);
lupb_setfieldi(L, "UPB_HANDLER_UINT32", UPB_HANDLER_UINT32);
lupb_setfieldi(L, "UPB_HANDLER_UINT64", UPB_HANDLER_UINT64);
lupb_setfieldi(L, "UPB_HANDLER_FLOAT", UPB_HANDLER_FLOAT);
lupb_setfieldi(L, "UPB_HANDLER_DOUBLE", UPB_HANDLER_DOUBLE);
lupb_setfieldi(L, "UPB_HANDLER_BOOL", UPB_HANDLER_BOOL);
lupb_setfieldi(L, "UPB_HANDLER_STARTSTR", UPB_HANDLER_STARTSTR);
lupb_setfieldi(L, "UPB_HANDLER_STRING", UPB_HANDLER_STRING);
lupb_setfieldi(L, "UPB_HANDLER_ENDSTR", UPB_HANDLER_ENDSTR);
lupb_setfieldi(L, "UPB_HANDLER_STARTSUBMSG", UPB_HANDLER_STARTSUBMSG);
lupb_setfieldi(L, "UPB_HANDLER_ENDSUBMSG", UPB_HANDLER_ENDSUBMSG);
lupb_setfieldi(L, "UPB_HANDLER_STARTSEQ", UPB_HANDLER_STARTSEQ);
lupb_setfieldi(L, "UPB_HANDLER_ENDSEQ", UPB_HANDLER_ENDSEQ);
lupb_setfieldi(L, "HANDLER_INT32", UPB_HANDLER_INT32);
lupb_setfieldi(L, "HANDLER_INT64", UPB_HANDLER_INT64);
lupb_setfieldi(L, "HANDLER_UINT32", UPB_HANDLER_UINT32);
lupb_setfieldi(L, "HANDLER_UINT64", UPB_HANDLER_UINT64);
lupb_setfieldi(L, "HANDLER_FLOAT", UPB_HANDLER_FLOAT);
lupb_setfieldi(L, "HANDLER_DOUBLE", UPB_HANDLER_DOUBLE);
lupb_setfieldi(L, "HANDLER_BOOL", UPB_HANDLER_BOOL);
lupb_setfieldi(L, "HANDLER_STARTSTR", UPB_HANDLER_STARTSTR);
lupb_setfieldi(L, "HANDLER_STRING", UPB_HANDLER_STRING);
lupb_setfieldi(L, "HANDLER_ENDSTR", UPB_HANDLER_ENDSTR);
lupb_setfieldi(L, "HANDLER_STARTSUBMSG", UPB_HANDLER_STARTSUBMSG);
lupb_setfieldi(L, "HANDLER_ENDSUBMSG", UPB_HANDLER_ENDSUBMSG);
lupb_setfieldi(L, "HANDLER_STARTSEQ", UPB_HANDLER_STARTSEQ);
lupb_setfieldi(L, "HANDLER_ENDSEQ", UPB_HANDLER_ENDSEQ);
return 1; // Return package table.
}

@ -10,6 +10,7 @@
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <set>
#include "upb/def.h"
#include "upb/descriptor/reader.h"
#include "upb/handlers.h"
@ -18,6 +19,36 @@
#include "upb_test.h"
#include "upb/upb.h"
template <class T>
void AssertInsert(T* const container, const typename T::value_type& val) {
bool inserted = container->insert(val).second;
ASSERT(inserted);
}
static void TestCasts1() {
const upb::MessageDef* md = upb::MessageDef::New(&md);
const upb::Def* def = md->Upcast();
const upb::MessageDef* md2 = upb::down_cast<const upb::MessageDef*>(def);
const upb::MessageDef* md3 = upb::dyn_cast<const upb::MessageDef*>(def);
ASSERT(md == md2);
ASSERT(md == md3);
const upb::EnumDef* ed = upb::dyn_cast<const upb::EnumDef*>(def);
ASSERT(!ed);
md->Unref(&md);
}
static void TestCasts2() {
// Test non-const -> const cast.
upb::MessageDef* md = upb::MessageDef::New(&md);
upb::Def* def = md->Upcast();
const upb::MessageDef* const_md = upb::down_cast<const upb::MessageDef*>(def);
ASSERT(const_md == md);
md->Unref(&md);
}
static void TestSymbolTable(const char *descriptor_file) {
upb::SymbolTable *s = upb::SymbolTable::New(&s);
upb::Status status;
@ -25,9 +56,22 @@ static void TestSymbolTable(const char *descriptor_file) {
std::cerr << "Couldn't load descriptor: " << status.GetString();
exit(1);
}
const upb::MessageDef *md = s->LookupMessage("A", &md);
const upb::MessageDef* md = s->LookupMessage("C", &md);
ASSERT(md);
// We want a def that satisfies this to test iteration.
ASSERT(md->field_count() > 1);
#ifdef UPB_CXX11
// Test range-based for.
std::set<const upb::FieldDef*> fielddefs;
for (const upb::FieldDef* f : *md) {
AssertInsert(&fielddefs, f);
ASSERT(f->containing_type() == md);
}
ASSERT(fielddefs.size() == md->field_count());
#endif
s->Unref(&s);
md->Unref(&md);
}
@ -40,6 +84,8 @@ int run_tests(int argc, char *argv[]) {
return 1;
}
TestSymbolTable(argv[1]);
TestCasts1();
TestCasts2();
return 0;
}

@ -20,6 +20,10 @@
* pointers overflow (this might be difficult).
* - a few "kitchen sink" examples (one proto that uses all types, lots
* of submsg/sequences, etc.
* - test different handlers at every level and whether handlers fire at
* the correct field path.
* - test skips that extend past the end of current buffer (where decoder
* returns value greater than the size param).
*/
#ifndef __STDC_FORMAT_MACROS
@ -34,12 +38,28 @@
#include "upb/bytestream.h"
#include "upb/handlers.h"
#include "upb/pb/decoder.h"
#include "upb/pb/varint.h"
#include "upb/pb/varint.int.h"
#include "upb_test.h"
#include "upb/upb.h"
#include "third_party/upb/tests/test_decoder_schema.upb.h"
#undef PRINT_FAILURE
#define PRINT_FAILURE(expr) \
fprintf(stderr, "Assertion failed: %s:%d\n", __FILE__, __LINE__); \
fprintf(stderr, "expr: %s\n", #expr); \
if (testhash) { \
fprintf(stderr, "assertion failed running test %x. " \
"Run with the arg %x to run only this test.\n", \
testhash, testhash); \
fprintf(stderr, "Failed at %02.2f%% through tests.\n", \
(float)completed * 100 / total); \
}
uint32_t filter_hash = 0;
double completed;
double total;
double *count;
bool count_only;
// Copied from decoder.c, since this is not a public interface.
typedef struct {
@ -134,13 +154,15 @@ const buffer empty;
buffer cat(const buffer& a, const buffer& b,
const buffer& c = empty,
const buffer& d = empty,
const buffer& e = empty) {
const buffer& e = empty,
const buffer& f = empty) {
buffer ret;
ret.append(a);
ret.append(b);
ret.append(c);
ret.append(d);
ret.append(e);
ret.append(f);
return ret;
}
@ -179,7 +201,7 @@ buffer submsg(uint32_t fn, const buffer& buf) {
// using the closure depth to test that the stack of closures is properly
// handled.
int closures[UPB_MAX_NESTING];
int closures[UPB_DECODER_MAX_NESTING];
buffer output;
void indentbuf(buffer *buf, int depth) {
@ -363,12 +385,13 @@ void reghandlers(upb_handlers *h) {
const upb::Handlers *handlers;
const upb::Handlers *plan;
uint32_t Hash(const buffer& proto, const buffer* expected_output) {
uint32_t Hash(const buffer& proto, const buffer* expected_output, size_t seam1,
size_t seam2) {
uint32_t hash = MurmurHash2(proto.buf(), proto.len(), 0);
if (expected_output)
hash = MurmurHash2(expected_output->buf(), expected_output->len(), hash);
bool hasjit = upb::pb::HasJitCode(plan);
hash = MurmurHash2(&hasjit, 1, hash);
hash = MurmurHash2(&seam1, sizeof(seam1), hash);
hash = MurmurHash2(&seam2, sizeof(seam2), hash);
return hash;
}
@ -380,6 +403,8 @@ bool parse(
size_t parsed =
s->PutStringBuffer(UPB_BYTESTREAM_BYTES_STRING, buf + start, len);
if (s->pipeline()->status().ok() != (parsed >= len)) {
fprintf(stderr, "Status: %s, parsed=%zu, len=%zu\n",
s->pipeline()->status().GetString(), parsed, len);
ASSERT(false);
}
if (!s->pipeline()->status().ok())
@ -391,8 +416,6 @@ bool parse(
#define LINE(x) x "\n"
void run_decoder(const buffer& proto, const buffer* expected_output) {
testhash = Hash(proto, expected_output);
if (filter_hash && testhash != filter_hash) return;
upb::Pipeline pipeline(NULL, 0, upb_realloc, NULL);
upb::Sink* sink = pipeline.NewSink(handlers);
upb::Sink* decoder_sink = pipeline.NewSink(plan);
@ -400,37 +423,42 @@ void run_decoder(const buffer& proto, const buffer* expected_output) {
upb::pb::ResetDecoderSink(d, sink);
for (size_t i = 0; i < proto.len(); i++) {
for (size_t j = i; j < UPB_MIN(proto.len(), i + 5); j++) {
pipeline.Reset();
output.clear();
sink->Reset(&closures[0]);
size_t ofs = 0;
bool ok =
decoder_sink->StartMessage() &&
decoder_sink->StartString(
UPB_BYTESTREAM_BYTES_STARTSTR, proto.len()) &&
parse(decoder_sink, proto.buf(), 0, i, &ofs) &&
parse(decoder_sink, proto.buf(), i, j, &ofs) &&
parse(decoder_sink, proto.buf(), j, proto.len(), &ofs) &&
ofs == proto.len() &&
decoder_sink->EndString(UPB_BYTESTREAM_BYTES_ENDSTR);
if (ok) decoder_sink->EndMessage();
if (expected_output) {
if (!output.eql(*expected_output)) {
fprintf(stderr, "Text mismatch: '%s' vs '%s'\n",
output.buf(), expected_output->buf());
}
if (!ok) {
fprintf(stderr, "Failed: %s\n", pipeline.status().GetString());
}
ASSERT(ok);
ASSERT(output.eql(*expected_output));
} else {
if (ok) {
fprintf(stderr, "Didn't expect ok result, but got output: '%s'\n",
output.buf());
testhash = Hash(proto, expected_output, i, j);
if (filter_hash && testhash != filter_hash) continue;
if (!count_only) {
pipeline.Reset();
output.clear();
sink->Reset(&closures[0]);
size_t ofs = 0;
bool ok =
decoder_sink->StartMessage() &&
decoder_sink->StartString(
UPB_BYTESTREAM_BYTES_STARTSTR, proto.len()) &&
parse(decoder_sink, proto.buf(), 0, i, &ofs) &&
parse(decoder_sink, proto.buf(), i, j, &ofs) &&
parse(decoder_sink, proto.buf(), j, proto.len(), &ofs) &&
ofs == proto.len() &&
decoder_sink->EndString(UPB_BYTESTREAM_BYTES_ENDSTR);
if (ok) decoder_sink->EndMessage();
if (expected_output) {
if (!output.eql(*expected_output)) {
fprintf(stderr, "Text mismatch: '%s' vs '%s'\n",
output.buf(), expected_output->buf());
}
if (!ok) {
fprintf(stderr, "Failed: %s\n", pipeline.status().GetString());
}
ASSERT(ok);
ASSERT(output.eql(*expected_output));
} else {
if (ok) {
fprintf(stderr, "Didn't expect ok result, but got output: '%s'\n",
output.buf());
}
ASSERT(!ok);
}
ASSERT(!ok);
}
(*count)++;
}
}
testhash = 0;
@ -446,7 +474,7 @@ void assert_successful_parse(const buffer& proto,
va_start(args, expected_fmt);
expected_text.vappendf(expected_fmt, args);
va_end(args);
// The JIT is only used for data >=20 bytes from end-of-buffer, so
// To test both middle-of-buffer and end-of-buffer code paths,
// repeat once with no-op padding data at the end of buffer.
run_decoder(proto, &expected_text);
run_decoder(cat( proto, thirty_byte_nop ), &expected_text);
@ -457,8 +485,7 @@ void assert_does_not_parse_at_eof(const buffer& proto) {
}
void assert_does_not_parse(const buffer& proto) {
// The JIT is only used for data >=20 bytes from end-of-buffer, so
// repeat once with no-op padding data at the end of buffer.
// Test that the error is caught both at end-of-buffer and middle-of-buffer.
assert_does_not_parse_at_eof(proto);
assert_does_not_parse_at_eof(cat( proto, thirty_byte_nop ));
}
@ -641,10 +668,12 @@ void test_invalid() {
assert_does_not_parse_at_eof( buffer("\x80") );
// EOF inside a known group.
assert_does_not_parse_at_eof( tag(4, UPB_WIRE_TYPE_START_GROUP) );
// TODO(haberman): add group to decoder test schema.
//assert_does_not_parse_at_eof( tag(4, UPB_WIRE_TYPE_START_GROUP) );
// EOF inside an unknown group.
assert_does_not_parse_at_eof( tag(UNKNOWN_FIELD, UPB_WIRE_TYPE_START_GROUP) );
// TODO(haberman): unknown groups not supported yet.
//assert_does_not_parse_at_eof( tag(UNKNOWN_FIELD, UPB_WIRE_TYPE_START_GROUP) );
// End group that we are not currently in.
assert_does_not_parse( tag(4, UPB_WIRE_TYPE_END_GROUP) );
@ -658,15 +687,24 @@ void test_invalid() {
cat( tag(UPB_MAX_FIELDNUMBER + 1, UPB_WIRE_TYPE_DELIMITED),
varint(0) ));
// Known group inside a submessage has ENDGROUP tag AFTER submessage end.
assert_does_not_parse(
cat ( submsg(UPB_DESCRIPTOR_TYPE_MESSAGE,
tag(UPB_DESCRIPTOR_TYPE_GROUP, UPB_WIRE_TYPE_START_GROUP)),
tag(UPB_DESCRIPTOR_TYPE_GROUP, UPB_WIRE_TYPE_END_GROUP)));
// Test exceeding the resource limit of stack depth.
buffer buf;
for (int i = 0; i <= UPB_MAX_NESTING; i++) {
for (int i = 0; i <= UPB_DECODER_MAX_NESTING; i++) {
buf.assign(submsg(UPB_DESCRIPTOR_TYPE_MESSAGE, buf));
}
assert_does_not_parse(buf);
}
void test_valid() {
// Empty protobuf.
assert_successful_parse(buffer(""), "<\n>\n");
test_valid_data_for_signed_type(UPB_DESCRIPTOR_TYPE_DOUBLE,
dbl(33),
dbl(-66));
@ -698,6 +736,49 @@ void test_valid() {
test_valid_data_for_type(UPB_DESCRIPTOR_TYPE_FIXED64, uint64(33), uint64(66));
test_valid_data_for_type(UPB_DESCRIPTOR_TYPE_FIXED32, uint32(33), uint32(66));
// Unknown fields.
int int32_type = UPB_DESCRIPTOR_TYPE_INT32;
int msg_type = UPB_DESCRIPTOR_TYPE_MESSAGE;
assert_successful_parse(
cat( tag(12345, UPB_WIRE_TYPE_VARINT), varint(2345678) ),
"<\n>\n");
assert_successful_parse(
cat( tag(12345, UPB_WIRE_TYPE_32BIT), uint32(2345678) ),
"<\n>\n");
assert_successful_parse(
cat( tag(12345, UPB_WIRE_TYPE_64BIT), uint64(2345678) ),
"<\n>\n");
assert_successful_parse(
submsg(12345, buffer(" ")),
"<\n>\n");
assert_successful_parse(
cat(
submsg(UPB_DESCRIPTOR_TYPE_MESSAGE,
submsg(UPB_DESCRIPTOR_TYPE_MESSAGE,
cat( tag(int32_type, UPB_WIRE_TYPE_VARINT), varint(2345678),
tag(12345, UPB_WIRE_TYPE_VARINT), varint(2345678) ))),
tag(int32_type, UPB_WIRE_TYPE_VARINT), varint(22222)),
LINE("<")
LINE("%u:{")
LINE(" <")
LINE(" %u:{")
LINE(" <")
LINE(" %u:2345678")
LINE(" >")
LINE(" }")
LINE(" >")
LINE("}")
LINE("%u:22222")
LINE(">"), msg_type, msg_type, int32_type, int32_type);
assert_successful_parse(
cat( tag(UPB_DESCRIPTOR_TYPE_INT32, UPB_WIRE_TYPE_VARINT), varint(1),
tag(12345, UPB_WIRE_TYPE_VARINT), varint(2345678) ),
LINE("<")
LINE("%u:1")
LINE(">"), UPB_DESCRIPTOR_TYPE_INT32);
// Test implicit startseq/endseq.
uint32_t repfl_fn = rep_fn(UPB_DESCRIPTOR_TYPE_FLOAT);
uint32_t repdb_fn = rep_fn(UPB_DESCRIPTOR_TYPE_DOUBLE);
@ -753,7 +834,7 @@ void test_valid() {
// Staying within the stack limit should work properly.
buffer buf;
buffer textbuf;
int total = UPB_MAX_NESTING - 1;
int total = UPB_DECODER_MAX_NESTING - 1;
for (int i = 0; i < total; i++) {
buf.assign(submsg(UPB_DESCRIPTOR_TYPE_MESSAGE, buf));
indentbuf(&textbuf, i);
@ -779,42 +860,62 @@ void run_tests() {
test_valid();
}
void test_emptyhandlers(bool allowjit) {
// Create an empty handlers to make sure that the decoder can handle empty
// messages.
upb::Handlers* h = upb_handlers_new(UPB_TEST_DECODER_EMPTYMESSAGE, NULL, &h);
bool ok = upb::Handlers::Freeze(&h, 1, NULL);
ASSERT(ok);
const upb::Handlers* plan = upb::pb::GetDecoderHandlers(h, allowjit, &plan);
h->Unref(&h);
plan->Unref(&plan);
}
extern "C" {
int run_tests(int argc, char *argv[]) {
if (argc > 1)
filter_hash = strtol(argv[1], NULL, 16);
for (int i = 0; i < UPB_MAX_NESTING; i++) {
for (int i = 0; i < UPB_DECODER_MAX_NESTING; i++) {
closures[i] = i;
}
// Create an empty handlers to make sure that the decoder can handle empty
// messages.
upb::Handlers *h = upb_handlers_new(UPB_TEST_DECODER_EMPTYMESSAGE, NULL, &h);
bool ok = upb::Handlers::Freeze(&h, 1, NULL);
ASSERT(ok);
plan = upb::pb::GetDecoderHandlers(h, true, &plan);
h->Unref(&h);
plan->Unref(&plan);
// Construct decoder plan.
h = upb::Handlers::New(UPB_TEST_DECODER_DECODERTEST, NULL, &handlers);
upb::Handlers* h =
upb::Handlers::New(UPB_TEST_DECODER_DECODERTEST, NULL, &handlers);
reghandlers(h);
ok = upb::Handlers::Freeze(&h, 1, NULL);
bool ok = upb::Handlers::Freeze(&h, 1, NULL);
ASSERT(ok);
handlers = h;
// Count tests.
plan = upb::pb::GetDecoderHandlers(handlers, false, &plan);
count_only = true;
count = &total;
total = 0;
run_tests();
count_only = false;
count = &completed;
plan->Unref(&plan);
// Test without JIT.
plan = upb::pb::GetDecoderHandlers(handlers, false, &plan);
ASSERT(!upb::pb::HasJitCode(plan));
completed = 0;
run_tests();
plan->Unref(&plan);
test_emptyhandlers(false);
#ifdef UPB_USE_JIT_X64
// Test JIT.
plan = upb::pb::GetDecoderHandlers(handlers, true, &plan);
ASSERT(upb::pb::HasJitCode(plan));
completed = 0;
run_tests();
plan->Unref(&plan);
test_emptyhandlers(true);
#endif
plan = NULL;

@ -75,7 +75,7 @@ static void test_fielddef_unref() {
upb_symtab_unref(s, &s);
upb_msgdef_unref(md, &md);
// Check that md is still alive.
ASSERT(strcmp(upb_def_fullname(upb_upcast(md)), "A") == 0);
ASSERT(strcmp(upb_msgdef_fullname(md), "A") == 0);
// Check that unref of fielddef frees the whole remaining graph.
upb_fielddef_unref(f, &f);
@ -123,13 +123,13 @@ static upb_fielddef *newfield(
static upb_msgdef *upb_msgdef_newnamed(const char *name, void *owner) {
upb_msgdef *m = upb_msgdef_new(owner);
upb_def_setfullname(upb_upcast(m), name, NULL);
upb_msgdef_setfullname(m, name, NULL);
return m;
}
static upb_enumdef *upb_enumdef_newnamed(const char *name, void *owner) {
upb_enumdef *e = upb_enumdef_new(owner);
upb_def_setfullname(upb_upcast(e), name, NULL);
upb_enumdef_setfullname(e, name, NULL);
return e;
}
@ -143,15 +143,15 @@ static void test_replacement() {
upb_msgdef *m2 = upb_msgdef_newnamed("MyMessage2", &s);
upb_enumdef *e = upb_enumdef_newnamed("MyEnum", &s);
upb_def *newdefs[] = {upb_upcast(m), upb_upcast(m2), upb_upcast(e)};
upb_def *newdefs[] = {UPB_UPCAST(m), UPB_UPCAST(m2), UPB_UPCAST(e)};
upb_status status = UPB_STATUS_INIT;
ASSERT_STATUS(upb_symtab_add(s, newdefs, 3, &s, &status), &status);
// Try adding a new definition of MyEnum, MyMessage should get replaced with
// a new version.
upb_enumdef *e2 = upb_enumdef_new(&s);
upb_def_setfullname(upb_upcast(e2), "MyEnum", NULL);
upb_def *newdefs2[] = {upb_upcast(e2)};
upb_enumdef_setfullname(e2, "MyEnum", NULL);
upb_def *newdefs2[] = {UPB_UPCAST(e2)};
ASSERT_STATUS(upb_symtab_add(s, newdefs2, 1, &s, &status), &status);
const upb_msgdef *m3 = upb_symtab_lookupmsg(s, "MyMessage", &m3);
@ -184,7 +184,7 @@ static void test_freeze_free() {
upb_fielddef_settype(f, UPB_TYPE_MESSAGE);
ASSERT(upb_fielddef_setnumber(f, 1, NULL));
ASSERT(upb_fielddef_setname(f, "foo", NULL));
ASSERT(upb_fielddef_setsubdef(f, upb_upcast(m4), NULL));
ASSERT(upb_fielddef_setmsgsubdef(f, m4, NULL));
ASSERT(upb_msgdef_addfield(m1, f, &f, NULL));
@ -197,9 +197,9 @@ static void test_freeze_free() {
ASSERT(upb_fielddef_setnumber(f, 1, NULL));
ASSERT(upb_fielddef_setname(f, "foo", NULL));
ASSERT(upb_fielddef_setsubdef(f, upb_upcast(m1), NULL));
ASSERT(upb_fielddef_setsubdef(f, upb_upcast(m2), NULL));
ASSERT(upb_fielddef_setsubdef(f, upb_upcast(m3), NULL));
ASSERT(upb_fielddef_setmsgsubdef(f, m1, NULL));
ASSERT(upb_fielddef_setmsgsubdef(f, m2, NULL));
ASSERT(upb_fielddef_setmsgsubdef(f, m3, NULL));
// Make M3 cyclic with itself.
ASSERT(upb_msgdef_addfield(m3, f, &f, NULL));
@ -211,8 +211,8 @@ static void test_freeze_free() {
upb_msgdef_unref(m2, &m2);
// Test that they are still alive (NOT allowed by the API).
ASSERT(strcmp("M1", upb_def_fullname(upb_upcast(m1))) == 0);
ASSERT(strcmp("M2", upb_def_fullname(upb_upcast(m2))) == 0);
ASSERT(strcmp("M1", upb_msgdef_fullname(m1)) == 0);
ASSERT(strcmp("M2", upb_msgdef_fullname(m2)) == 0);
// Freeze M3. If the test leaked no memory, then freeing m1 and m2 was
// successful.
@ -232,20 +232,20 @@ static void test_partial_freeze() {
upb_fielddef_settype(f1, UPB_TYPE_MESSAGE);
ASSERT(upb_fielddef_setnumber(f1, 1, NULL));
ASSERT(upb_fielddef_setname(f1, "f1", NULL));
ASSERT(upb_fielddef_setsubdef(f1, upb_upcast(m1), NULL));
ASSERT(upb_fielddef_setmsgsubdef(f1, m1, NULL));
upb_fielddef *f2 = upb_fielddef_new(&f2);
upb_fielddef_settype(f2, UPB_TYPE_MESSAGE);
ASSERT(upb_fielddef_setnumber(f2, 2, NULL));
ASSERT(upb_fielddef_setname(f2, "f2", NULL));
ASSERT(upb_fielddef_setsubdef(f2, upb_upcast(m2), NULL));
ASSERT(upb_fielddef_setmsgsubdef(f2, m2, NULL));
ASSERT(upb_msgdef_addfield(m3, f1, &f1, NULL));
ASSERT(upb_msgdef_addfield(m3, f2, &f2, NULL));
// Freeze M1 and M2, which should cause the group to be split
// and m3 (left mutable) to take references on m1 and m2.
upb_def *defs[] = {upb_upcast(m1), upb_upcast(m2)};
upb_def *defs[] = {UPB_UPCAST(m1), UPB_UPCAST(m2)};
ASSERT(upb_def_freeze(defs, 2, NULL));
ASSERT(upb_msgdef_isfrozen(m1));

@ -6,6 +6,7 @@
* Tests for upb_table.
*/
#include <limits.h>
#include <string.h>
#include <sys/resource.h>
#include <ext/hash_map>
@ -16,7 +17,7 @@
#include <vector>
#include "tests/test_util.h"
#include "tests/upb_test.h"
#include "upb/table.h"
#include "upb/table.int.h"
bool benchmark = false;
#define CPU_TIME_PER_TEST 0.5
@ -126,6 +127,19 @@ void test_inttable(int32_t *keys, uint16_t num_entries, const char *desc) {
}
}
// Test replace.
for(uint32_t i = 0; i <= largest_key; i++) {
upb_value v = upb_value_uint32(i*3);
bool replaced = upb_inttable_replace(&table, i, v);
if(m.find(i) != m.end()) { /* Assume map implementation is correct. */
ASSERT(replaced);
m[i] = i * 3;
hm[i] = i * 3;
} else {
ASSERT(!replaced);
}
}
// Compact and test correctness again.
upb_inttable_compact(&table);
for(uint32_t i = 0; i <= largest_key; i++) {
@ -133,9 +147,9 @@ void test_inttable(int32_t *keys, uint16_t num_entries, const char *desc) {
bool found = upb_inttable_lookup(&table, i, &v);
if(m.find(i) != m.end()) { /* Assume map implementation is correct. */
ASSERT(found);
ASSERT(upb_value_getuint32(v) == i*2);
ASSERT(m[i] == i*2);
ASSERT(hm[i] == i*2);
ASSERT(upb_value_getuint32(v) == i*3);
ASSERT(m[i] == i*3);
ASSERT(hm[i] == i*3);
} else {
ASSERT(!found);
}

@ -5,7 +5,7 @@
*/
#include <stdio.h>
#include "upb/pb/varint.h"
#include "upb/pb/varint.int.h"
#include "upb_test.h"
// Test that we can round-trip from int->varint->int.
@ -66,7 +66,7 @@ static void test_varint_decoder(upb_decoderet (*decoder)(const char*)) {
ASSERT(r.p == NULL);
for (uint64_t num = 5; num * 1.5 > num; num *= 1.5) {
for (uint64_t num = 5; num * 1.5 < UINT64_MAX; num *= 1.5) {
test_varint_for_num(decoder, num);
}
test_varint_for_num(decoder, 0);

@ -12,6 +12,7 @@
#include <google/protobuf/descriptor.h>
#include <google/protobuf/dynamic_message.h>
#include <google/protobuf/message.h>
#include <google/protobuf/text_format.h>
#include <google/protobuf/wire_format_lite.h>
#include <inttypes.h>
#include <stdint.h>
@ -24,14 +25,15 @@
#include "upb/handlers.h"
#include "upb/pb/decoder.h"
#include "upb/pb/glue.h"
#include "upb/pb/varint.h"
#include "upb/pb/varint.int.h"
#include "upb_test.h"
void compare_metadata(const google::protobuf::Descriptor* d,
const upb::MessageDef *upb_md) {
ASSERT(d->field_count() == upb_md->field_count());
for (upb::MessageDef::ConstIterator i(upb_md); !i.Done(); i.Next()) {
const upb::FieldDef* upb_f = i.field();
for (upb::MessageDef::const_iterator i = upb_md->begin(); i != upb_md->end();
++i) {
const upb::FieldDef* upb_f = *i;
const google::protobuf::FieldDescriptor *proto2_f =
d->FindFieldByNumber(upb_f->number());
ASSERT(upb_f);
@ -65,6 +67,9 @@ void parse_and_compare(google::protobuf::Message *msg1,
msg2->Clear();
bool ok = upb::PutStringToBytestream(decoder_sink, str, len);
if (!ok) {
fprintf(stderr, "error parsing: %s\n", pipeline.status().GetString());
}
ASSERT(ok);
ASSERT(pipeline.status().ok());
@ -76,12 +81,21 @@ void parse_and_compare(google::protobuf::Message *msg1,
std::string str2;
msg1->SerializeToString(&str1);
msg2->SerializeToString(&str2);
std::string text_str1;
std::string text_str2;
google::protobuf::TextFormat::PrintToString(*msg1, &text_str1);
google::protobuf::TextFormat::PrintToString(*msg2, &text_str2);
if (str1 != str2) {
fprintf(stderr, "str1: %s, str2: %s\n",
text_str1.c_str(), text_str2.c_str());
}
ASSERT(str1 == str2);
ASSERT(std::string(str, len) == str2);
}
void test_zig_zag() {
for (uint64_t num = 5; num * 1.5 > num; num *= 1.5) {
for (uint64_t num = 5; num * 1.5 < UINT64_MAX; num *= 1.5) {
ASSERT(upb_zzenc_64(num) ==
google::protobuf::internal::WireFormatLite::ZigZagEncode64(num));
if (num < UINT32_MAX) {

@ -38,9 +38,16 @@ function export.file_appender(file)
end
-- const(f, label) -> UPB_LABEL_REPEATED, where f:label() == upb.LABEL_REPEATED
function const(obj, name)
local val = obj[name](obj)
for k, v in pairs(upb) do
function const(obj, name, base)
local val = obj[name]
base = base or upb
-- Support both f:label() and f.label.
if type(val) == "function" then
val = val(obj)
end
for k, v in pairs(base) do
if v == val and string.find(k, "^" .. string.upper(name)) then
return "UPB_" .. k
end
@ -52,7 +59,7 @@ end
function constlist(pattern)
local ret = {}
for k, v in pairs(upb) do
if string.find(k, "^UPB_" .. pattern) then
if string.find(k, "^" .. pattern) then
ret[k] = v
end
end
@ -205,8 +212,9 @@ end
function Dumper:strtable(t)
-- UPB_STRTABLE_INIT(count, mask, type, size_lg2, entries)
return string.format(
"UPB_STRTABLE_INIT(%d, %d, %d, %d, %s)",
t.count, t.mask, t.type, t.size_lg2, self.linktab:addr(t.entries[1].ptr))
"UPB_STRTABLE_INIT(%d, %d, %s, %d, %s)",
t.count, t.mask, const(t, "ctype", upbtable) , t.size_lg2,
self.linktab:addr(t.entries[1].ptr))
end
function Dumper:inttable(t)
@ -217,8 +225,8 @@ function Dumper:inttable(t)
entries = lt:addr(t.entries[1].ptr)
end
return string.format(
"UPB_INTTABLE_INIT(%d, %d, %d, %d, %s, %s, %d, %d)",
t.count, t.mask, t.type, t.size_lg2, entries,
"UPB_INTTABLE_INIT(%d, %d, %s, %d, %s, %s, %d, %d)",
t.count, t.mask, const(t, "ctype", upbtable), t.size_lg2, entries,
lt:addr(t.array[1].ptr), t.array_size, t.array_count)
end
@ -279,9 +287,12 @@ local function dump_defs_c(symtab, basename, append)
strentries = "strentries",
arrays = "arrays",
})
local reftable_count = 0
for _, def in ipairs(defs) do
assert(def:is_frozen(), "can only dump frozen defs.")
linktab:add(def:def_type(), def)
reftable_count = reftable_count + 2
local tables = gettables(def)
if tables then
for _, e in ipairs(tables.str.entries) do
@ -306,19 +317,28 @@ local function dump_defs_c(symtab, basename, append)
append("const upb_tabent %s;\n", linktab:cdecl("intentries"))
append("const _upb_value %s;\n", linktab:cdecl("arrays"))
append("\n")
append("#ifdef UPB_DEBUG_REFS\n")
append("static upb_inttable reftables[%d];\n", reftable_count)
append("#endif\n")
append("\n")
-- Emit defs.
local dumper = Dumper:new(linktab)
local reftable = 0
append("const upb_msgdef %s = {\n", linktab:cdecl(upb.DEF_MSG))
for m in linktab:objs(upb.DEF_MSG) do
local tables = gettables(m)
-- UPB_MSGDEF_INIT(name, itof, ntof)
append(' UPB_MSGDEF_INIT("%s", %s, %s, %s),\n',
append(' UPB_MSGDEF_INIT("%s", %s, %s, %s, ' ..
'&reftables[%d], &reftables[%d]),\n',
m:full_name(),
dumper:inttable(tables.int),
dumper:strtable(tables.str),
m:_selector_count())
m:_selector_count(),
reftable, reftable + 1)
reftable = reftable + 2
end
append("};\n\n")
@ -326,7 +346,7 @@ local function dump_defs_c(symtab, basename, append)
for f in linktab:objs(upb.DEF_FIELD) do
local subdef = "NULL"
if f:has_subdef() then
subdef = string.format("upb_upcast(%s)", linktab:addr(f:subdef()))
subdef = string.format("UPB_UPCAST(%s)", linktab:addr(f:subdef()))
end
local intfmt
if f:type() == upb.TYPE_UINT32 or
@ -340,12 +360,15 @@ local function dump_defs_c(symtab, basename, append)
-- UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, name, num, msgdef,
-- subdef, selector_base, default_value)
append(' UPB_FIELDDEF_INIT(%s, %s, %s, %s, "%s", %d, %s, %s, %d, ' ..
'UPB_VALUE_INIT_NONE),\n', -- TODO: support default value
'{0},' .. -- TODO: support default value
'&reftables[%d], &reftables[%d]),\n',
const(f, "label"), const(f, "type"), intfmt,
boolstr(f:istagdelim()), f:name(),
f:number(), linktab:addr(f:msgdef()), subdef,
f:_selector_base()
f:number(), linktab:addr(f:containing_type()), subdef,
f:_selector_base(),
reftable, reftable + 1
)
reftable = reftable + 2
end
append("};\n\n")
@ -353,12 +376,15 @@ local function dump_defs_c(symtab, basename, append)
for e in linktab:objs(upb.DEF_ENUM) do
local tables = gettables(e)
-- UPB_ENUMDEF_INIT(name, ntoi, iton, defaultval)
append(' UPB_ENUMDEF_INIT("%s", %s, %s, %d),\n',
append(' UPB_ENUMDEF_INIT("%s", %s, %s, %d, ' ..
'&reftables[%d], &reftables[%d]),\n',
e:full_name(),
dumper:strtable(tables.str),
dumper:inttable(tables.int),
--e:default())
0)
0,
reftable, reftable + 1)
reftable = reftable + 2
end
append("};\n\n")
@ -380,6 +406,14 @@ local function dump_defs_c(symtab, basename, append)
end
append("};\n\n");
append("#ifdef UPB_DEBUG_REFS\n")
append("static upb_inttable reftables[%d] = {\n", reftable_count)
for i = 1,reftable_count do
append(" UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),\n")
end
append("};\n")
append("#endif\n\n")
return linktab
end
@ -431,19 +465,27 @@ local function dump_defs_h(symtab, basename, append, linktab)
end
append("\n")
append("// Selector definitions.\n")
local selector_types = constlist("HANDLER_")
local selectors = {}
for f in linktab:objs(upb.DEF_FIELD) do
for sel_type_name, sel_type_value in pairs(selector_types) do
sel_type_name = sel_type_name:gsub("UPB_HANDLER_", "")
sel_type_name = sel_type_name:gsub("HANDLER_", "")
local sel = f:getsel(sel_type_value)
if sel then
local symname = f:msgdef():full_name() .. "." .. f:name() ..
local symname = f:containing_type():full_name() .. "." .. f:name() ..
"." .. sel_type_name
append("#define %s %d\n", to_preproc(symname), sel)
selectors[#selectors + 1] = {to_preproc(symname), sel}
end
end
end
table.sort(selectors, function(a, b) return a[1] < b[1] end)
append("// Selector definitions.\n")
for _, selector in ipairs(selectors) do
append("#define %s %d\n", selector[1], selector[2])
end
append("\n")
append('#ifdef __cplusplus\n')

@ -48,11 +48,11 @@ if arg[1] == "generate" then
f:write([[int luaopen_staticdefs(lua_State *L) {
lua_newtable(L);
for (int i = 0; i < ELEMENTS(test_msgs); i++) {
lupb_def_pushnewrapper(L, upb_upcast(&test_msgs[i]), NULL);
lupb_def_pushnewrapper(L, UPB_UPCAST(&test_msgs[i]), NULL);
lua_rawseti(L, -2, i + 1);
}
for (int i = 0; i < ELEMENTS(test_enums); i++) {
lupb_def_pushnewrapper(L, upb_upcast(&test_enums[i]), NULL);
lupb_def_pushnewrapper(L, UPB_UPCAST(&test_enums[i]), NULL);
lua_rawseti(L, -2, ELEMENTS(test_msgs) + i + 1);
}
return 1;
@ -71,7 +71,7 @@ elseif arg[1] == "test" then
assert(enum:full_name() == "MyEnum")
assert(enum:value("FOO") == 1)
assert(f2:name() == "field2")
assert(f2:msgdef() == msg)
assert(f2:containing_type() == msg)
assert(f2:subdef() == enum)
else
error("Unknown operation " .. arg[1])

@ -9,14 +9,18 @@ const upb_fielddef upb_bytestream_fields[1];
const upb_enumdef upb_bytestream_enums[0];
const upb_tabent upb_bytestream_strentries[4];
const upb_tabent upb_bytestream_intentries[0];
const _upb_value upb_bytestream_arrays[3];
const _upb_value upb_bytestream_arrays[2];
#ifdef UPB_DEBUG_REFS
static upb_inttable reftables[4];
#endif
const upb_msgdef upb_bytestream_msgs[1] = {
UPB_MSGDEF_INIT("upb.ByteStream", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &upb_bytestream_arrays[0], 3, 1), UPB_STRTABLE_INIT(1, 3, 9, 2, &upb_bytestream_strentries[0]), 5),
UPB_MSGDEF_INIT("upb.ByteStream", UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &upb_bytestream_arrays[0], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &upb_bytestream_strentries[0]), 5, &reftables[0], &reftables[1]),
};
const upb_fielddef upb_bytestream_fields[1] = {
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, "bytes", 1, &upb_bytestream_msgs[0], NULL, 2, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, "bytes", 1, &upb_bytestream_msgs[0], NULL, 2, {0},&reftables[2], &reftables[3]),
};
const upb_enumdef upb_bytestream_enums[0] = {
@ -32,9 +36,17 @@ const upb_tabent upb_bytestream_strentries[4] = {
const upb_tabent upb_bytestream_intentries[0] = {
};
const _upb_value upb_bytestream_arrays[3] = {
const _upb_value upb_bytestream_arrays[2] = {
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&upb_bytestream_fields[0]),
UPB_ARRAY_EMPTYENT,
};
#ifdef UPB_DEBUG_REFS
static upb_inttable reftables[4] = {
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
};
#endif

@ -27,8 +27,8 @@ extern const upb_enumdef upb_bytestream_enums[0];
// Selector definitions.
#define UPB_BYTESTREAM_BYTES_ENDSTR 4
#define UPB_BYTESTREAM_BYTES_STRING 2
#define UPB_BYTESTREAM_BYTES_STARTSTR 3
#define UPB_BYTESTREAM_BYTES_STRING 2
#ifdef __cplusplus
}; // extern "C"

@ -88,39 +88,39 @@ bool upb_def_setfullname(upb_def *def, const char *fullname, upb_status *s) {
upb_def *upb_def_dup(const upb_def *def, const void *o) {
switch (def->type) {
case UPB_DEF_MSG:
return upb_upcast(upb_msgdef_dup(upb_downcast_msgdef(def), o));
return UPB_UPCAST(upb_msgdef_dup(upb_downcast_msgdef(def), o));
case UPB_DEF_FIELD:
return upb_upcast(upb_fielddef_dup(upb_downcast_fielddef(def), o));
return UPB_UPCAST(upb_fielddef_dup(upb_downcast_fielddef(def), o));
case UPB_DEF_ENUM:
return upb_upcast(upb_enumdef_dup(upb_downcast_enumdef(def), o));
return UPB_UPCAST(upb_enumdef_dup(upb_downcast_enumdef(def), o));
default: assert(false); return NULL;
}
}
bool upb_def_isfrozen(const upb_def *def) {
return upb_refcounted_isfrozen(upb_upcast(def));
return upb_refcounted_isfrozen(UPB_UPCAST(def));
}
void upb_def_ref(const upb_def *def, const void *owner) {
upb_refcounted_ref(upb_upcast(def), owner);
upb_refcounted_ref(UPB_UPCAST(def), owner);
}
void upb_def_unref(const upb_def *def, const void *owner) {
upb_refcounted_unref(upb_upcast(def), owner);
upb_refcounted_unref(UPB_UPCAST(def), owner);
}
void upb_def_donateref(const upb_def *def, const void *from, const void *to) {
upb_refcounted_donateref(upb_upcast(def), from, to);
upb_refcounted_donateref(UPB_UPCAST(def), from, to);
}
void upb_def_checkref(const upb_def *def, const void *owner) {
upb_refcounted_checkref(upb_upcast(def), owner);
upb_refcounted_checkref(UPB_UPCAST(def), owner);
}
static bool upb_def_init(upb_def *def, upb_deftype_t type,
const struct upb_refcounted_vtbl *vtbl,
const void *owner) {
if (!upb_refcounted_init(upb_upcast(def), vtbl, owner)) return false;
if (!upb_refcounted_init(UPB_UPCAST(def), vtbl, owner)) return false;
def->type = type;
def->fullname = NULL;
def->came_from_user = false;
@ -132,7 +132,7 @@ static void upb_def_uninit(upb_def *def) {
}
static const char *msgdef_name(const upb_msgdef *m) {
const char *name = upb_def_fullname(upb_upcast(m));
const char *name = upb_def_fullname(UPB_UPCAST(m));
return name ? name : "(anonymous)";
}
@ -191,6 +191,7 @@ bool upb_def_freeze(upb_def *const* defs, int n, upb_status *s) {
}
}
// Second pass of validation. Also assign selectors, compact tables.
for (int i = 0; i < n; i++) {
upb_msgdef *m = upb_dyncast_msgdef_mutable(defs[i]);
upb_enumdef *e = upb_dyncast_enumdef_mutable(defs[i]);
@ -211,8 +212,11 @@ bool upb_def_freeze(upb_def *const* defs, int n, upb_status *s) {
}
}
// Def graph contains FieldDefs between each MessageDef, so double the limit.
int maxdepth = UPB_MAX_MESSAGE_DEPTH * 2;
// Validation all passed; freeze the defs.
return upb_refcounted_freeze((upb_refcounted*const*)defs, n, s);
return upb_refcounted_freeze((upb_refcounted * const *)defs, n, s, maxdepth);
err:
for (int i = 0; i < n; i++) {
@ -235,7 +239,7 @@ static void upb_enumdef_free(upb_refcounted *r) {
}
upb_strtable_uninit(&e->ntoi);
upb_inttable_uninit(&e->iton);
upb_def_uninit(upb_upcast(e));
upb_def_uninit(UPB_UPCAST(e));
free(e);
}
@ -243,7 +247,7 @@ upb_enumdef *upb_enumdef_new(const void *owner) {
static const struct upb_refcounted_vtbl vtbl = {NULL, &upb_enumdef_free};
upb_enumdef *e = malloc(sizeof(*e));
if (!e) return NULL;
if (!upb_def_init(upb_upcast(e), UPB_DEF_ENUM, &vtbl, owner)) goto err2;
if (!upb_def_init(UPB_UPCAST(e), UPB_DEF_ENUM, &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;
@ -271,33 +275,33 @@ upb_enumdef *upb_enumdef_dup(const upb_enumdef *e, const void *owner) {
}
bool upb_enumdef_isfrozen(const upb_enumdef *e) {
return upb_def_isfrozen(upb_upcast(e));
return upb_def_isfrozen(UPB_UPCAST(e));
}
void upb_enumdef_ref(const upb_enumdef *e, const void *owner) {
upb_def_ref(upb_upcast(e), owner);
upb_def_ref(UPB_UPCAST(e), owner);
}
void upb_enumdef_unref(const upb_enumdef *e, const void *owner) {
upb_def_unref(upb_upcast(e), owner);
upb_def_unref(UPB_UPCAST(e), owner);
}
void upb_enumdef_donateref(
const upb_enumdef *e, const void *from, const void *to) {
upb_def_donateref(upb_upcast(e), from, to);
upb_def_donateref(UPB_UPCAST(e), from, to);
}
void upb_enumdef_checkref(const upb_enumdef *e, const void *owner) {
upb_def_checkref(upb_upcast(e), owner);
upb_def_checkref(UPB_UPCAST(e), owner);
}
const char *upb_enumdef_fullname(const upb_enumdef *e) {
return upb_def_fullname(upb_upcast(e));
return upb_def_fullname(UPB_UPCAST(e));
}
bool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname,
upb_status *s) {
return upb_def_setfullname(upb_upcast(e), fullname, s);
return upb_def_setfullname(UPB_UPCAST(e), fullname, s);
}
bool upb_enumdef_addval(upb_enumdef *e, const char *name, int32_t num,
@ -371,17 +375,17 @@ static void upb_fielddef_init_default(upb_fielddef *f);
static void upb_fielddef_uninit_default(upb_fielddef *f) {
if (f->type_is_set_ && f->default_is_string)
freestr(upb_value_getptr(f->defaultval));
freestr(f->defaultval.bytes);
}
static void visitfield(const upb_refcounted *r, upb_refcounted_visit *visit,
void *closure) {
const upb_fielddef *f = (const upb_fielddef*)r;
if (f->msgdef) {
visit(r, upb_upcast2(f->msgdef), closure);
visit(r, UPB_UPCAST2(f->msgdef), closure);
}
if (!f->subdef_is_symbolic && f->sub.def) {
visit(r, upb_upcast(f->sub.def), closure);
visit(r, UPB_UPCAST(f->sub.def), closure);
}
}
@ -390,7 +394,7 @@ static void freefield(upb_refcounted *r) {
upb_fielddef_uninit_default(f);
if (f->subdef_is_symbolic)
free(f->sub.name);
upb_def_uninit(upb_upcast(f));
upb_def_uninit(UPB_UPCAST(f));
free(f);
}
@ -398,7 +402,7 @@ upb_fielddef *upb_fielddef_new(const void *owner) {
static const struct upb_refcounted_vtbl vtbl = {visitfield, freefield};
upb_fielddef *f = malloc(sizeof(*f));
if (!f) return NULL;
if (!upb_def_init(upb_upcast(f), UPB_DEF_FIELD, &vtbl, owner)) {
if (!upb_def_init(UPB_UPCAST(f), UPB_DEF_FIELD, &vtbl, owner)) {
free(f);
return NULL;
}
@ -431,10 +435,10 @@ upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner) {
upb_fielddef_setnumber(newf, upb_fielddef_number(f), NULL);
upb_fielddef_setname(newf, upb_fielddef_name(f), NULL);
if (f->default_is_string) {
str_t *s = upb_value_getptr(upb_fielddef_default(f));
str_t *s = f->defaultval.bytes;
upb_fielddef_setdefaultstr(newf, s->str, s->len, NULL);
} else {
upb_fielddef_setdefault(newf, upb_fielddef_default(f));
newf->defaultval = f->defaultval;
}
const char *srcname;
@ -459,24 +463,24 @@ upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner) {
}
bool upb_fielddef_isfrozen(const upb_fielddef *f) {
return upb_def_isfrozen(upb_upcast(f));
return upb_def_isfrozen(UPB_UPCAST(f));
}
void upb_fielddef_ref(const upb_fielddef *f, const void *owner) {
upb_def_ref(upb_upcast(f), owner);
upb_def_ref(UPB_UPCAST(f), owner);
}
void upb_fielddef_unref(const upb_fielddef *f, const void *owner) {
upb_def_unref(upb_upcast(f), owner);
upb_def_unref(UPB_UPCAST(f), owner);
}
void upb_fielddef_donateref(
const upb_fielddef *f, const void *from, const void *to) {
upb_def_donateref(upb_upcast(f), from, to);
upb_def_donateref(UPB_UPCAST(f), from, to);
}
void upb_fielddef_checkref(const upb_fielddef *f, const void *owner) {
upb_def_checkref(upb_upcast(f), owner);
upb_def_checkref(UPB_UPCAST(f), owner);
}
bool upb_fielddef_typeisset(const upb_fielddef *f) {
@ -505,30 +509,69 @@ uint32_t upb_fielddef_number(const upb_fielddef *f) {
}
const char *upb_fielddef_name(const upb_fielddef *f) {
return upb_def_fullname(upb_upcast(f));
return upb_def_fullname(UPB_UPCAST(f));
}
const upb_msgdef *upb_fielddef_msgdef(const upb_fielddef *f) {
const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f) {
return f->msgdef;
}
upb_msgdef *upb_fielddef_msgdef_mutable(upb_fielddef *f) {
upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f) {
return (upb_msgdef*)f->msgdef;
}
bool upb_fielddef_setname(upb_fielddef *f, const char *name, upb_status *s) {
return upb_def_setfullname(upb_upcast(f), name, s);
return upb_def_setfullname(UPB_UPCAST(f), name, s);
}
upb_value upb_fielddef_default(const upb_fielddef *f) {
assert(f->type_is_set_);
return f->defaultval;
static void chkdefaulttype(const upb_fielddef *f, upb_fieldtype_t type) {
UPB_UNUSED(f);
UPB_UNUSED(type);
assert(f->type_is_set_ && upb_fielddef_type(f) == type);
}
int64_t upb_fielddef_defaultint64(const upb_fielddef *f) {
chkdefaulttype(f, UPB_TYPE_INT64);
return f->defaultval.sint;
}
int32_t upb_fielddef_defaultint32(const upb_fielddef *f) {
chkdefaulttype(f, UPB_TYPE_INT32);
return f->defaultval.sint;
}
uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) {
chkdefaulttype(f, UPB_TYPE_UINT64);
return f->defaultval.uint;
}
uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f) {
chkdefaulttype(f, UPB_TYPE_UINT32);
return f->defaultval.uint;
}
bool upb_fielddef_defaultbool(const upb_fielddef *f) {
chkdefaulttype(f, UPB_TYPE_BOOL);
return f->defaultval.uint;
}
float upb_fielddef_defaultfloat(const upb_fielddef *f) {
chkdefaulttype(f, UPB_TYPE_FLOAT);
return f->defaultval.flt;
}
double upb_fielddef_defaultdouble(const upb_fielddef *f) {
chkdefaulttype(f, UPB_TYPE_DOUBLE);
return f->defaultval.dbl;
}
const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) {
assert(f->type_is_set_);
assert(upb_fielddef_type(f) == UPB_TYPE_STRING ||
upb_fielddef_type(f) == UPB_TYPE_BYTES ||
upb_fielddef_type(f) == UPB_TYPE_ENUM);
if (f->default_is_string) {
str_t *str = upb_value_getptr(f->defaultval);
str_t *str = f->defaultval.bytes;
if (len) *len = str->len;
return str->str;
}
@ -538,20 +581,20 @@ const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) {
static void upb_fielddef_init_default(upb_fielddef *f) {
f->default_is_string = false;
switch (upb_fielddef_type(f)) {
case UPB_TYPE_DOUBLE: upb_value_setdouble(&f->defaultval, 0); break;
case UPB_TYPE_FLOAT: upb_value_setfloat(&f->defaultval, 0); break;
case UPB_TYPE_UINT64: upb_value_setuint64(&f->defaultval, 0); break;
case UPB_TYPE_INT64: upb_value_setint64(&f->defaultval, 0); break;
case UPB_TYPE_ENUM:
case UPB_TYPE_INT32: upb_value_setint32(&f->defaultval, 0); break;
case UPB_TYPE_UINT32: upb_value_setuint32(&f->defaultval, 0); break;
case UPB_TYPE_BOOL: upb_value_setbool(&f->defaultval, false); break;
case UPB_TYPE_DOUBLE: f->defaultval.dbl = 0; break;
case UPB_TYPE_FLOAT: f->defaultval.flt = 0; break;
case UPB_TYPE_INT32:
case UPB_TYPE_INT64:
case UPB_TYPE_ENUM: f->defaultval.sint = 0; break;
case UPB_TYPE_UINT64:
case UPB_TYPE_UINT32:
case UPB_TYPE_BOOL: f->defaultval.uint = 0; break;
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
upb_value_setptr(&f->defaultval, newstr("", 0));
f->defaultval.bytes = newstr("", 0);
f->default_is_string = true;
break;
case UPB_TYPE_MESSAGE: upb_value_setptr(&f->defaultval, NULL); break;
case UPB_TYPE_MESSAGE: break;
}
}
@ -564,6 +607,16 @@ const upb_def *upb_fielddef_subdef(const upb_fielddef *f) {
}
}
const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) {
const upb_def *def = upb_fielddef_subdef(f);
return def ? upb_dyncast_msgdef(def) : NULL;
}
const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) {
const upb_def *def = upb_fielddef_subdef(f);
return def ? upb_dyncast_enumdef(def) : NULL;
}
upb_def *upb_fielddef_subdef_mutable(upb_fielddef *f) {
return (upb_def*)upb_fielddef_subdef(f);
}
@ -715,17 +768,57 @@ bool upb_fielddef_settagdelim(upb_fielddef *f, bool tag_delim) {
return true;
}
void upb_fielddef_setdefault(upb_fielddef *f, upb_value value) {
assert(f->type_is_set_);
assert(!upb_fielddef_isfrozen(f));
assert(!upb_fielddef_isstring(f) && !upb_fielddef_issubmsg(f));
static bool checksetdefault(upb_fielddef *f, upb_fieldtype_t type) {
if (!f->type_is_set_ || upb_fielddef_isfrozen(f) ||
upb_fielddef_type(f) != type) {
assert(false);
return false;
}
if (f->default_is_string) {
str_t *s = upb_value_getptr(f->defaultval);
str_t *s = f->defaultval.bytes;
assert(s);
freestr(s);
}
f->defaultval = value;
f->default_is_string = false;
return true;
}
void upb_fielddef_setdefaultint64(upb_fielddef *f, int64_t value) {
if (checksetdefault(f, UPB_TYPE_INT64))
f->defaultval.sint = value;
}
void upb_fielddef_setdefaultint32(upb_fielddef *f, int32_t value) {
if ((upb_fielddef_type(f) == UPB_TYPE_ENUM &&
checksetdefault(f, UPB_TYPE_ENUM)) ||
checksetdefault(f, UPB_TYPE_INT32)) {
f->defaultval.sint = value;
}
}
void upb_fielddef_setdefaultuint64(upb_fielddef *f, uint64_t value) {
if (checksetdefault(f, UPB_TYPE_UINT64))
f->defaultval.uint = value;
}
void upb_fielddef_setdefaultuint32(upb_fielddef *f, uint32_t value) {
if (checksetdefault(f, UPB_TYPE_UINT32))
f->defaultval.uint = value;
}
void upb_fielddef_setdefaultbool(upb_fielddef *f, bool value) {
if (checksetdefault(f, UPB_TYPE_BOOL))
f->defaultval.uint = value;
}
void upb_fielddef_setdefaultfloat(upb_fielddef *f, float value) {
if (checksetdefault(f, UPB_TYPE_FLOAT))
f->defaultval.flt = value;
}
void upb_fielddef_setdefaultdouble(upb_fielddef *f, double value) {
if (checksetdefault(f, UPB_TYPE_DOUBLE))
f->defaultval.dbl = value;
}
bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len,
@ -735,7 +828,7 @@ bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len,
return false;
if (f->default_is_string) {
str_t *s = upb_value_getptr(f->defaultval);
str_t *s = f->defaultval.bytes;
assert(s);
freestr(s);
} else {
@ -743,7 +836,7 @@ bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len,
}
str_t *str2 = newstr(str, len);
upb_value_setptr(&f->defaultval, str2);
f->defaultval.bytes = str2;
f->default_is_string = true;
return true;
}
@ -763,20 +856,20 @@ bool upb_fielddef_default_is_symbolic(const upb_fielddef *f) {
bool upb_fielddef_resolveenumdefault(upb_fielddef *f, upb_status *s) {
if (!upb_fielddef_default_is_symbolic(f)) return true;
str_t *str = upb_value_getptr(f->defaultval);
str_t *str = f->defaultval.bytes;
const upb_enumdef *e = upb_downcast_enumdef(upb_fielddef_subdef(f));
assert(str); // Points to either a real default or the empty string.
assert(e);
if (str->len == 0) {
// The "default default" for an enum is the first defined value.
upb_value_setint32(&f->defaultval, e->defaultval);
f->defaultval.sint = e->defaultval;
} else {
int32_t val = 0;
if (!upb_enumdef_ntoi(e, str->str, &val)) {
upb_status_seterrf(s, "enum default not found in enum (%s)", str->str);
return false;
}
upb_value_setint32(&f->defaultval, val);
f->defaultval.sint = val;
}
f->default_is_string = false;
freestr(str);
@ -821,6 +914,16 @@ bool upb_fielddef_setsubdef(upb_fielddef *f, const upb_def *subdef,
return true;
}
bool upb_fielddef_setmsgsubdef(upb_fielddef *f, const upb_msgdef *subdef,
upb_status *s) {
return upb_fielddef_setsubdef(f, UPB_UPCAST(subdef), s);
}
bool upb_fielddef_setenumsubdef(upb_fielddef *f, const upb_enumdef *subdef,
upb_status *s) {
return upb_fielddef_setsubdef(f, UPB_UPCAST(subdef), s);
}
bool upb_fielddef_setsubdefname(upb_fielddef *f, const char *name,
upb_status *s) {
assert(!upb_fielddef_isfrozen(f));
@ -875,7 +978,7 @@ static void visitmsg(const upb_refcounted *r, upb_refcounted_visit *visit,
upb_msg_iter i;
for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) {
upb_fielddef *f = upb_msg_iter_field(&i);
visit(r, upb_upcast2(f), closure);
visit(r, UPB_UPCAST2(f), closure);
}
}
@ -883,7 +986,7 @@ static void freemsg(upb_refcounted *r) {
upb_msgdef *m = (upb_msgdef*)r;
upb_strtable_uninit(&m->ntof);
upb_inttable_uninit(&m->itof);
upb_def_uninit(upb_upcast(m));
upb_def_uninit(UPB_UPCAST(m));
free(m);
}
@ -891,7 +994,7 @@ upb_msgdef *upb_msgdef_new(const void *owner) {
static const struct upb_refcounted_vtbl vtbl = {visitmsg, freemsg};
upb_msgdef *m = malloc(sizeof(*m));
if (!m) return NULL;
if (!upb_def_init(upb_upcast(m), UPB_DEF_MSG, &vtbl, owner)) goto err2;
if (!upb_def_init(UPB_UPCAST(m), UPB_DEF_MSG, &vtbl, owner)) goto err2;
if (!upb_inttable_init(&m->itof, UPB_CTYPE_PTR)) goto err2;
if (!upb_strtable_init(&m->ntof, UPB_CTYPE_PTR)) goto err1;
return m;
@ -906,8 +1009,8 @@ err2:
upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner) {
upb_msgdef *newm = upb_msgdef_new(owner);
if (!newm) return NULL;
bool ok = upb_def_setfullname(upb_upcast(newm),
upb_def_fullname(upb_upcast(m)), NULL);
bool ok = upb_def_setfullname(UPB_UPCAST(newm),
upb_def_fullname(UPB_UPCAST(m)), NULL);
UPB_ASSERT_VAR(ok, ok);
upb_msg_iter i;
for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) {
@ -921,33 +1024,33 @@ upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner) {
}
bool upb_msgdef_isfrozen(const upb_msgdef *m) {
return upb_def_isfrozen(upb_upcast(m));
return upb_def_isfrozen(UPB_UPCAST(m));
}
void upb_msgdef_ref(const upb_msgdef *m, const void *owner) {
upb_def_ref(upb_upcast(m), owner);
upb_def_ref(UPB_UPCAST(m), owner);
}
void upb_msgdef_unref(const upb_msgdef *m, const void *owner) {
upb_def_unref(upb_upcast(m), owner);
upb_def_unref(UPB_UPCAST(m), owner);
}
void upb_msgdef_donateref(
const upb_msgdef *m, const void *from, const void *to) {
upb_def_donateref(upb_upcast(m), from, to);
upb_def_donateref(UPB_UPCAST(m), from, to);
}
void upb_msgdef_checkref(const upb_msgdef *m, const void *owner) {
upb_def_checkref(upb_upcast(m), owner);
upb_def_checkref(UPB_UPCAST(m), owner);
}
const char *upb_msgdef_fullname(const upb_msgdef *m) {
return upb_def_fullname(upb_upcast(m));
return upb_def_fullname(UPB_UPCAST(m));
}
bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname,
upb_status *s) {
return upb_def_setfullname(upb_upcast(m), fullname, s);
return upb_def_setfullname(UPB_UPCAST(m), fullname, s);
}
bool upb_msgdef_addfields(upb_msgdef *m, upb_fielddef *const *fields, int n,
@ -1018,8 +1121,8 @@ void upb_msg_begin(upb_msg_iter *iter, const upb_msgdef *m) {
void upb_msg_next(upb_msg_iter *iter) { upb_inttable_next(iter); }
bool upb_msg_done(upb_msg_iter *iter) { return upb_inttable_done(iter); }
bool upb_msg_done(const upb_msg_iter *iter) { return upb_inttable_done(iter); }
upb_fielddef *upb_msg_iter_field(upb_msg_iter *iter) {
upb_fielddef *upb_msg_iter_field(const upb_msg_iter *iter) {
return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter));
}

File diff suppressed because it is too large Load Diff

@ -8,120 +8,124 @@ const upb_msgdef google_protobuf_msgs[20];
const upb_fielddef google_protobuf_fields[73];
const upb_enumdef google_protobuf_enums[4];
const upb_tabent google_protobuf_strentries[192];
const upb_tabent google_protobuf_intentries[66];
const _upb_value google_protobuf_arrays[97];
const upb_tabent google_protobuf_intentries[14];
const _upb_value google_protobuf_arrays[224];
#ifdef UPB_DEBUG_REFS
static upb_inttable reftables[194];
#endif
const upb_msgdef google_protobuf_msgs[20] = {
UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", UPB_INTTABLE_INIT(2, 3, 9, 2, &google_protobuf_intentries[0], &google_protobuf_arrays[0], 6, 5), UPB_STRTABLE_INIT(7, 15, 9, 4, &google_protobuf_strentries[0]), 33),
UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ExtensionRange", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[6], 4, 2), UPB_STRTABLE_INIT(2, 3, 9, 2, &google_protobuf_strentries[16]), 4),
UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[10], 4, 3), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[20]), 13),
UPB_MSGDEF_INIT("google.protobuf.EnumOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[4], &google_protobuf_arrays[14], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[24]), 7),
UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[15], 4, 3), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[28]), 9),
UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[6], &google_protobuf_arrays[19], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[32]), 7),
UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", UPB_INTTABLE_INIT(3, 3, 9, 2, &google_protobuf_intentries[8], &google_protobuf_arrays[20], 6, 5), UPB_STRTABLE_INIT(8, 15, 9, 4, &google_protobuf_strentries[36]), 20),
UPB_MSGDEF_INIT("google.protobuf.FieldOptions", UPB_INTTABLE_INIT(2, 3, 9, 2, &google_protobuf_intentries[12], &google_protobuf_arrays[26], 5, 3), UPB_STRTABLE_INIT(5, 7, 9, 3, &google_protobuf_strentries[52]), 13),
UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", UPB_INTTABLE_INIT(4, 7, 9, 3, &google_protobuf_intentries[16], &google_protobuf_arrays[31], 6, 5), UPB_STRTABLE_INIT(9, 15, 9, 4, &google_protobuf_strentries[60]), 39),
UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[37], 3, 1), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[76]), 7),
UPB_MSGDEF_INIT("google.protobuf.FileOptions", UPB_INTTABLE_INIT(8, 15, 9, 4, &google_protobuf_intentries[24], &google_protobuf_arrays[40], 6, 1), UPB_STRTABLE_INIT(9, 15, 9, 4, &google_protobuf_strentries[80]), 19),
UPB_MSGDEF_INIT("google.protobuf.MessageOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[40], &google_protobuf_arrays[46], 4, 2), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[96]), 9),
UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[50], 5, 4), UPB_STRTABLE_INIT(4, 7, 9, 3, &google_protobuf_strentries[100]), 14),
UPB_MSGDEF_INIT("google.protobuf.MethodOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[42], &google_protobuf_arrays[55], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[108]), 7),
UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[56], 4, 3), UPB_STRTABLE_INIT(3, 3, 9, 2, &google_protobuf_strentries[112]), 13),
UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", UPB_INTTABLE_INIT(1, 1, 9, 1, &google_protobuf_intentries[44], &google_protobuf_arrays[60], 1, 0), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[116]), 7),
UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[61], 3, 1), UPB_STRTABLE_INIT(1, 3, 9, 2, &google_protobuf_strentries[120]), 7),
UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[64], 4, 2), UPB_STRTABLE_INIT(2, 3, 9, 2, &google_protobuf_strentries[124]), 8),
UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", UPB_INTTABLE_INIT(3, 3, 9, 2, &google_protobuf_intentries[46], &google_protobuf_arrays[68], 6, 4), UPB_STRTABLE_INIT(7, 15, 9, 4, &google_protobuf_strentries[128]), 19),
UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", UPB_INTTABLE_INIT(0, 0, 9, 0, NULL, &google_protobuf_arrays[74], 4, 2), UPB_STRTABLE_INIT(2, 3, 9, 2, &google_protobuf_strentries[144]), 6),
UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[0], 8, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &google_protobuf_strentries[0]), 33, &reftables[0], &reftables[1]),
UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ExtensionRange", UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[8], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[16]), 4, &reftables[2], &reftables[3]),
UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[11], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[20]), 13, &reftables[4], &reftables[5]),
UPB_MSGDEF_INIT("google.protobuf.EnumOptions", UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &google_protobuf_intentries[0], &google_protobuf_arrays[15], 4, 0), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[24]), 7, &reftables[6], &reftables[7]),
UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[19], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[28]), 9, &reftables[8], &reftables[9]),
UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &google_protobuf_intentries[2], &google_protobuf_arrays[23], 4, 0), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[32]), 7, &reftables[10], &reftables[11]),
UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[27], 9, 8), UPB_STRTABLE_INIT(8, 15, UPB_CTYPE_PTR, 4, &google_protobuf_strentries[36]), 20, &reftables[12], &reftables[13]),
UPB_MSGDEF_INIT("google.protobuf.FieldOptions", UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &google_protobuf_intentries[4], &google_protobuf_arrays[36], 32, 4), UPB_STRTABLE_INIT(5, 7, UPB_CTYPE_PTR, 3, &google_protobuf_strentries[52]), 13, &reftables[14], &reftables[15]),
UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[68], 10, 9), UPB_STRTABLE_INIT(9, 15, UPB_CTYPE_PTR, 4, &google_protobuf_strentries[60]), 39, &reftables[16], &reftables[17]),
UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[78], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[76]), 7, &reftables[18], &reftables[19]),
UPB_MSGDEF_INIT("google.protobuf.FileOptions", UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &google_protobuf_intentries[6], &google_protobuf_arrays[80], 64, 8), UPB_STRTABLE_INIT(9, 15, UPB_CTYPE_PTR, 4, &google_protobuf_strentries[80]), 19, &reftables[20], &reftables[21]),
UPB_MSGDEF_INIT("google.protobuf.MessageOptions", UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &google_protobuf_intentries[8], &google_protobuf_arrays[144], 16, 2), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[96]), 9, &reftables[22], &reftables[23]),
UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[160], 5, 4), UPB_STRTABLE_INIT(4, 7, UPB_CTYPE_PTR, 3, &google_protobuf_strentries[100]), 14, &reftables[24], &reftables[25]),
UPB_MSGDEF_INIT("google.protobuf.MethodOptions", UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &google_protobuf_intentries[10], &google_protobuf_arrays[165], 4, 0), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[108]), 7, &reftables[26], &reftables[27]),
UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[169], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[112]), 13, &reftables[28], &reftables[29]),
UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &google_protobuf_intentries[12], &google_protobuf_arrays[173], 4, 0), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[116]), 7, &reftables[30], &reftables[31]),
UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[177], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[120]), 7, &reftables[32], &reftables[33]),
UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[179], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[124]), 8, &reftables[34], &reftables[35]),
UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[182], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &google_protobuf_strentries[128]), 19, &reftables[36], &reftables[37]),
UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[191], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[144]), 6, &reftables[38], &reftables[39]),
};
const upb_fielddef google_protobuf_fields[73] = {
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "aggregate_value", 8, &google_protobuf_msgs[18], NULL, 12, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "cc_generic_services", 16, &google_protobuf_msgs[10], NULL, 5, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "ctype", 1, &google_protobuf_msgs[7], upb_upcast(&google_protobuf_enums[2]), 2, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "default_value", 7, &google_protobuf_msgs[6], NULL, 17, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, "dependency", 3, &google_protobuf_msgs[8], NULL, 10, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "deprecated", 3, &google_protobuf_msgs[7], NULL, 4, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, "double_value", 6, &google_protobuf_msgs[18], NULL, 15, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "end", 2, &google_protobuf_msgs[1], NULL, 3, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "enum_type", 4, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[2]), 17, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "enum_type", 5, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[2]), 20, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "experimental_map_key", 9, &google_protobuf_msgs[7], NULL, 5, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "extendee", 2, &google_protobuf_msgs[6], NULL, 5, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension", 7, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[6]), 36, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension", 6, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[6]), 27, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension_range", 5, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[1]), 22, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "field", 2, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[6]), 7, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "file", 1, &google_protobuf_msgs[9], upb_upcast(&google_protobuf_msgs[8]), 4, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "identifier_value", 3, &google_protobuf_msgs[18], NULL, 7, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "input_type", 2, &google_protobuf_msgs[12], NULL, 5, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_BOOL, 0, false, "is_extension", 2, &google_protobuf_msgs[19], NULL, 5, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "java_generate_equals_and_hash", 20, &google_protobuf_msgs[10], NULL, 8, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "java_generic_services", 17, &google_protobuf_msgs[10], NULL, 6, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "java_multiple_files", 10, &google_protobuf_msgs[10], NULL, 18, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "java_outer_classname", 8, &google_protobuf_msgs[10], NULL, 14, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "java_package", 1, &google_protobuf_msgs[10], NULL, 2, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "label", 4, &google_protobuf_msgs[6], upb_upcast(&google_protobuf_enums[0]), 9, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "location", 1, &google_protobuf_msgs[16], upb_upcast(&google_protobuf_msgs[17]), 4, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "message_set_wire_format", 1, &google_protobuf_msgs[11], NULL, 2, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "message_type", 4, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[0]), 15, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "method", 2, &google_protobuf_msgs[14], upb_upcast(&google_protobuf_msgs[12]), 7, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[12], NULL, 2, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[4], NULL, 2, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[14], NULL, 2, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[2], NULL, 2, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[6], NULL, 2, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "name", 2, &google_protobuf_msgs[18], upb_upcast(&google_protobuf_msgs[19]), 4, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[0], NULL, 2, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[8], NULL, 2, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, "name_part", 1, &google_protobuf_msgs[19], NULL, 2, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, "negative_int_value", 5, &google_protobuf_msgs[18], NULL, 11, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "nested_type", 3, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[0]), 12, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "no_standard_descriptor_accessor", 2, &google_protobuf_msgs[11], NULL, 3, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "number", 2, &google_protobuf_msgs[4], NULL, 5, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "number", 3, &google_protobuf_msgs[6], NULL, 8, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "optimize_for", 9, &google_protobuf_msgs[10], upb_upcast(&google_protobuf_enums[3]), 17, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 4, &google_protobuf_msgs[12], upb_upcast(&google_protobuf_msgs[13]), 11, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[14], upb_upcast(&google_protobuf_msgs[15]), 10, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 8, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[10]), 23, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[2], upb_upcast(&google_protobuf_msgs[3]), 10, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 7, &google_protobuf_msgs[0], upb_upcast(&google_protobuf_msgs[11]), 30, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 8, &google_protobuf_msgs[6], upb_upcast(&google_protobuf_msgs[7]), 11, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[4], upb_upcast(&google_protobuf_msgs[5]), 6, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "output_type", 3, &google_protobuf_msgs[12], NULL, 8, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "package", 2, &google_protobuf_msgs[8], NULL, 5, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "packed", 2, &google_protobuf_msgs[7], NULL, 3, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "path", 1, &google_protobuf_msgs[17], NULL, 4, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, "positive_int_value", 4, &google_protobuf_msgs[18], NULL, 10, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "py_generic_services", 18, &google_protobuf_msgs[10], NULL, 7, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "service", 6, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[14]), 31, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "source_code_info", 9, &google_protobuf_msgs[8], upb_upcast(&google_protobuf_msgs[16]), 26, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "span", 2, &google_protobuf_msgs[17], NULL, 7, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "start", 1, &google_protobuf_msgs[1], NULL, 2, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, "string_value", 7, &google_protobuf_msgs[18], NULL, 16, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "type", 5, &google_protobuf_msgs[6], upb_upcast(&google_protobuf_enums[1]), 10, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "type_name", 6, &google_protobuf_msgs[6], NULL, 14, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[15], upb_upcast(&google_protobuf_msgs[18]), 4, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[11], upb_upcast(&google_protobuf_msgs[18]), 6, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[13], upb_upcast(&google_protobuf_msgs[18]), 4, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[10], upb_upcast(&google_protobuf_msgs[18]), 11, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[7], upb_upcast(&google_protobuf_msgs[18]), 10, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[3], upb_upcast(&google_protobuf_msgs[18]), 4, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[5], upb_upcast(&google_protobuf_msgs[18]), 4, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "value", 2, &google_protobuf_msgs[2], upb_upcast(&google_protobuf_msgs[4]), 7, UPB_VALUE_INIT_NONE),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "aggregate_value", 8, &google_protobuf_msgs[18], NULL, 16, {0},&reftables[40], &reftables[41]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "cc_generic_services", 16, &google_protobuf_msgs[10], NULL, 10, {0},&reftables[42], &reftables[43]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "ctype", 1, &google_protobuf_msgs[7], UPB_UPCAST(&google_protobuf_enums[2]), 2, {0},&reftables[44], &reftables[45]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "default_value", 7, &google_protobuf_msgs[6], NULL, 14, {0},&reftables[46], &reftables[47]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, "dependency", 3, &google_protobuf_msgs[8], NULL, 10, {0},&reftables[48], &reftables[49]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "deprecated", 3, &google_protobuf_msgs[7], NULL, 4, {0},&reftables[50], &reftables[51]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, "double_value", 6, &google_protobuf_msgs[18], NULL, 12, {0},&reftables[52], &reftables[53]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "end", 2, &google_protobuf_msgs[1], NULL, 3, {0},&reftables[54], &reftables[55]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "enum_type", 4, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[2]), 17, {0},&reftables[56], &reftables[57]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "enum_type", 5, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[2]), 20, {0},&reftables[58], &reftables[59]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "experimental_map_key", 9, &google_protobuf_msgs[7], NULL, 5, {0},&reftables[60], &reftables[61]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "extendee", 2, &google_protobuf_msgs[6], NULL, 5, {0},&reftables[62], &reftables[63]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension", 7, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[6]), 30, {0},&reftables[64], &reftables[65]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension", 6, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[6]), 27, {0},&reftables[66], &reftables[67]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "extension_range", 5, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[1]), 22, {0},&reftables[68], &reftables[69]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "field", 2, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[6]), 7, {0},&reftables[70], &reftables[71]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "file", 1, &google_protobuf_msgs[9], UPB_UPCAST(&google_protobuf_msgs[8]), 4, {0},&reftables[72], &reftables[73]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "identifier_value", 3, &google_protobuf_msgs[18], NULL, 7, {0},&reftables[74], &reftables[75]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "input_type", 2, &google_protobuf_msgs[12], NULL, 5, {0},&reftables[76], &reftables[77]),
UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_BOOL, 0, false, "is_extension", 2, &google_protobuf_msgs[19], NULL, 5, {0},&reftables[78], &reftables[79]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "java_generate_equals_and_hash", 20, &google_protobuf_msgs[10], NULL, 13, {0},&reftables[80], &reftables[81]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "java_generic_services", 17, &google_protobuf_msgs[10], NULL, 11, {0},&reftables[82], &reftables[83]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "java_multiple_files", 10, &google_protobuf_msgs[10], NULL, 9, {0},&reftables[84], &reftables[85]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "java_outer_classname", 8, &google_protobuf_msgs[10], NULL, 5, {0},&reftables[86], &reftables[87]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "java_package", 1, &google_protobuf_msgs[10], NULL, 2, {0},&reftables[88], &reftables[89]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "label", 4, &google_protobuf_msgs[6], UPB_UPCAST(&google_protobuf_enums[0]), 9, {0},&reftables[90], &reftables[91]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "location", 1, &google_protobuf_msgs[16], UPB_UPCAST(&google_protobuf_msgs[17]), 4, {0},&reftables[92], &reftables[93]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "message_set_wire_format", 1, &google_protobuf_msgs[11], NULL, 2, {0},&reftables[94], &reftables[95]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "message_type", 4, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[0]), 15, {0},&reftables[96], &reftables[97]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "method", 2, &google_protobuf_msgs[14], UPB_UPCAST(&google_protobuf_msgs[12]), 7, {0},&reftables[98], &reftables[99]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "name", 2, &google_protobuf_msgs[18], UPB_UPCAST(&google_protobuf_msgs[19]), 4, {0},&reftables[100], &reftables[101]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[8], NULL, 2, {0},&reftables[102], &reftables[103]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[14], NULL, 2, {0},&reftables[104], &reftables[105]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[12], NULL, 2, {0},&reftables[106], &reftables[107]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[6], NULL, 2, {0},&reftables[108], &reftables[109]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[4], NULL, 2, {0},&reftables[110], &reftables[111]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[2], NULL, 2, {0},&reftables[112], &reftables[113]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "name", 1, &google_protobuf_msgs[0], NULL, 2, {0},&reftables[114], &reftables[115]),
UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, "name_part", 1, &google_protobuf_msgs[19], NULL, 2, {0},&reftables[116], &reftables[117]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, "negative_int_value", 5, &google_protobuf_msgs[18], NULL, 11, {0},&reftables[118], &reftables[119]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "nested_type", 3, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[0]), 12, {0},&reftables[120], &reftables[121]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "no_standard_descriptor_accessor", 2, &google_protobuf_msgs[11], NULL, 3, {0},&reftables[122], &reftables[123]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "number", 2, &google_protobuf_msgs[4], NULL, 5, {0},&reftables[124], &reftables[125]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "number", 3, &google_protobuf_msgs[6], NULL, 8, {0},&reftables[126], &reftables[127]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "optimize_for", 9, &google_protobuf_msgs[10], UPB_UPCAST(&google_protobuf_enums[3]), 8, {0},&reftables[128], &reftables[129]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[2], UPB_UPCAST(&google_protobuf_msgs[3]), 10, {0},&reftables[130], &reftables[131]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 8, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[10]), 33, {0},&reftables[132], &reftables[133]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[14], UPB_UPCAST(&google_protobuf_msgs[15]), 10, {0},&reftables[134], &reftables[135]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 7, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[11]), 30, {0},&reftables[136], &reftables[137]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 4, &google_protobuf_msgs[12], UPB_UPCAST(&google_protobuf_msgs[13]), 11, {0},&reftables[138], &reftables[139]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 3, &google_protobuf_msgs[4], UPB_UPCAST(&google_protobuf_msgs[5]), 6, {0},&reftables[140], &reftables[141]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "options", 8, &google_protobuf_msgs[6], UPB_UPCAST(&google_protobuf_msgs[7]), 17, {0},&reftables[142], &reftables[143]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "output_type", 3, &google_protobuf_msgs[12], NULL, 8, {0},&reftables[144], &reftables[145]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "package", 2, &google_protobuf_msgs[8], NULL, 5, {0},&reftables[146], &reftables[147]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "packed", 2, &google_protobuf_msgs[7], NULL, 3, {0},&reftables[148], &reftables[149]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "path", 1, &google_protobuf_msgs[17], NULL, 4, {0},&reftables[150], &reftables[151]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, "positive_int_value", 4, &google_protobuf_msgs[18], NULL, 10, {0},&reftables[152], &reftables[153]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, "py_generic_services", 18, &google_protobuf_msgs[10], NULL, 12, {0},&reftables[154], &reftables[155]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "service", 6, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[14]), 25, {0},&reftables[156], &reftables[157]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, "source_code_info", 9, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[16]), 36, {0},&reftables[158], &reftables[159]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "span", 2, &google_protobuf_msgs[17], NULL, 7, {0},&reftables[160], &reftables[161]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, "start", 1, &google_protobuf_msgs[1], NULL, 2, {0},&reftables[162], &reftables[163]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, "string_value", 7, &google_protobuf_msgs[18], NULL, 13, {0},&reftables[164], &reftables[165]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, "type", 5, &google_protobuf_msgs[6], UPB_UPCAST(&google_protobuf_enums[1]), 10, {0},&reftables[166], &reftables[167]),
UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, "type_name", 6, &google_protobuf_msgs[6], NULL, 11, {0},&reftables[168], &reftables[169]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[3], UPB_UPCAST(&google_protobuf_msgs[18]), 4, {0},&reftables[170], &reftables[171]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[15], UPB_UPCAST(&google_protobuf_msgs[18]), 4, {0},&reftables[172], &reftables[173]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[11], UPB_UPCAST(&google_protobuf_msgs[18]), 6, {0},&reftables[174], &reftables[175]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[10], UPB_UPCAST(&google_protobuf_msgs[18]), 16, {0},&reftables[176], &reftables[177]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[7], UPB_UPCAST(&google_protobuf_msgs[18]), 10, {0},&reftables[178], &reftables[179]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[13], UPB_UPCAST(&google_protobuf_msgs[18]), 4, {0},&reftables[180], &reftables[181]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "uninterpreted_option", 999, &google_protobuf_msgs[5], UPB_UPCAST(&google_protobuf_msgs[18]), 4, {0},&reftables[182], &reftables[183]),
UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, "value", 2, &google_protobuf_msgs[2], UPB_UPCAST(&google_protobuf_msgs[4]), 7, {0},&reftables[184], &reftables[185]),
};
const upb_enumdef google_protobuf_enums[4] = {
UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Label", UPB_STRTABLE_INIT(3, 3, 1, 2, &google_protobuf_strentries[148]), UPB_INTTABLE_INIT(0, 0, 8, 0, NULL, &google_protobuf_arrays[78], 4, 3), 0),
UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Type", UPB_STRTABLE_INIT(18, 31, 1, 5, &google_protobuf_strentries[152]), UPB_INTTABLE_INIT(12, 15, 8, 4, &google_protobuf_intentries[50], &google_protobuf_arrays[82], 7, 6), 0),
UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.CType", UPB_STRTABLE_INIT(3, 3, 1, 2, &google_protobuf_strentries[184]), UPB_INTTABLE_INIT(0, 0, 8, 0, NULL, &google_protobuf_arrays[89], 4, 3), 0),
UPB_ENUMDEF_INIT("google.protobuf.FileOptions.OptimizeMode", UPB_STRTABLE_INIT(3, 3, 1, 2, &google_protobuf_strentries[188]), UPB_INTTABLE_INIT(0, 0, 8, 0, NULL, &google_protobuf_arrays[93], 4, 3), 0),
UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Label", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &google_protobuf_strentries[148]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &google_protobuf_arrays[194], 4, 3), 0, &reftables[186], &reftables[187]),
UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Type", UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_INT32, 5, &google_protobuf_strentries[152]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &google_protobuf_arrays[198], 19, 18), 0, &reftables[188], &reftables[189]),
UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.CType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &google_protobuf_strentries[184]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &google_protobuf_arrays[217], 3, 3), 0, &reftables[190], &reftables[191]),
UPB_ENUMDEF_INIT("google.protobuf.FileOptions.OptimizeMode", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &google_protobuf_strentries[188]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &google_protobuf_arrays[220], 4, 3), 0, &reftables[192], &reftables[193]),
};
const upb_tabent google_protobuf_strentries[192] = {
{UPB_TABKEY_STR("extension"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[13]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[36]), NULL},
{UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[37]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
@ -132,7 +136,7 @@ const upb_tabent google_protobuf_strentries[192] = {
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[49]), NULL},
{UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[48]), NULL},
{UPB_TABKEY_STR("enum_type"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[8]), &google_protobuf_strentries[14]},
{UPB_TABKEY_STR("start"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[61]), NULL},
{UPB_TABKEY_STR("end"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[7]), NULL},
@ -140,16 +144,16 @@ const upb_tabent google_protobuf_strentries[192] = {
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_STR("value"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[72]), NULL},
{UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[48]), NULL},
{UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[33]), &google_protobuf_strentries[22]},
{UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[70]), NULL},
{UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[45]), NULL},
{UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[36]), &google_protobuf_strentries[22]},
{UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[65]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_STR("number"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[42]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[51]), NULL},
{UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[31]), &google_protobuf_strentries[30]},
{UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[50]), NULL},
{UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[35]), &google_protobuf_strentries[30]},
{UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[71]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
@ -169,7 +173,7 @@ const upb_tabent google_protobuf_strentries[192] = {
{UPB_TABKEY_STR("extendee"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[11]), NULL},
{UPB_TABKEY_STR("type"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[63]), &google_protobuf_strentries[48]},
{UPB_TABKEY_STR("default_value"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[3]), NULL},
{UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[50]), NULL},
{UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[51]), NULL},
{UPB_TABKEY_STR("experimental_map_key"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[10]), &google_protobuf_strentries[58]},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_STR("ctype"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[2]), NULL},
@ -181,7 +185,7 @@ const upb_tabent google_protobuf_strentries[192] = {
{UPB_TABKEY_STR("extension"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[12]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[37]), NULL},
{UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[31]), NULL},
{UPB_TABKEY_STR("service"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[58]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_STR("source_code_info"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[59]), NULL},
@ -192,7 +196,7 @@ const upb_tabent google_protobuf_strentries[192] = {
{UPB_TABKEY_STR("message_type"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[28]), NULL},
{UPB_TABKEY_STR("package"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[53]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[47]), NULL},
{UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[46]), NULL},
{UPB_TABKEY_STR("enum_type"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[9]), &google_protobuf_strentries[74]},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_STR("file"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[16]), NULL},
@ -216,25 +220,25 @@ const upb_tabent google_protobuf_strentries[192] = {
{UPB_TABKEY_STR("java_outer_classname"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[23]), NULL},
{UPB_TABKEY_STR("message_set_wire_format"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[27]), &google_protobuf_strentries[98]},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[66]), NULL},
{UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[67]), NULL},
{UPB_TABKEY_STR("no_standard_descriptor_accessor"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[41]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[30]), NULL},
{UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[33]), NULL},
{UPB_TABKEY_STR("input_type"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[18]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_STR("output_type"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[52]), NULL},
{UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[45]), NULL},
{UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[67]), NULL},
{UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[49]), NULL},
{UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[70]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[46]), &google_protobuf_strentries[114]},
{UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[47]), &google_protobuf_strentries[114]},
{UPB_TABKEY_STR("method"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[29]), NULL},
{UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[32]), &google_protobuf_strentries[113]},
{UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[65]), NULL},
{UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[66]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
@ -249,7 +253,7 @@ const upb_tabent google_protobuf_strentries[192] = {
{UPB_TABKEY_STR("double_value"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[6]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[35]), NULL},
{UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[30]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
@ -312,95 +316,50 @@ const upb_tabent google_protobuf_strentries[192] = {
{UPB_TABKEY_STR("LITE_RUNTIME"), UPB_VALUE_INIT_INT32(3), NULL},
};
const upb_tabent google_protobuf_intentries[66] = {
const upb_tabent google_protobuf_intentries[14] = {
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NUM(6), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[13]), NULL},
{UPB_TABKEY_NUM(7), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[49]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[70]), NULL},
{UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[65]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[71]), NULL},
{UPB_TABKEY_NUM(8), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[50]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NUM(6), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[64]), NULL},
{UPB_TABKEY_NUM(7), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[3]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NUM(9), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[10]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[69]), NULL},
{UPB_TABKEY_NUM(8), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[47]), NULL},
{UPB_TABKEY_NUM(9), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[59]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NUM(6), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[58]), NULL},
{UPB_TABKEY_NUM(7), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[12]), NULL},
{UPB_TABKEY_NUM(16), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[1]), NULL},
{UPB_TABKEY_NUM(17), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[21]), NULL},
{UPB_TABKEY_NUM(18), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[57]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NUM(20), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[20]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[68]), NULL},
{UPB_TABKEY_NUM(8), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[23]), NULL},
{UPB_TABKEY_NUM(9), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[44]), NULL},
{UPB_TABKEY_NUM(10), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[22]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[66]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[67]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[65]), NULL},
{UPB_TABKEY_NUM(8), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[0]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NUM(6), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[6]), NULL},
{UPB_TABKEY_NUM(7), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[62]), NULL},
{UPB_TABKEY_NUM(16), UPB_VALUE_INIT_CONSTPTR("TYPE_SFIXED64"), NULL},
{UPB_TABKEY_NUM(17), UPB_VALUE_INIT_CONSTPTR("TYPE_SINT32"), NULL},
{UPB_TABKEY_NUM(18), UPB_VALUE_INIT_CONSTPTR("TYPE_SINT64"), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[70]), NULL},
{UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL},
{UPB_TABKEY_NUM(7), UPB_VALUE_INIT_CONSTPTR("TYPE_FIXED32"), NULL},
{UPB_TABKEY_NUM(8), UPB_VALUE_INIT_CONSTPTR("TYPE_BOOL"), NULL},
{UPB_TABKEY_NUM(9), UPB_VALUE_INIT_CONSTPTR("TYPE_STRING"), NULL},
{UPB_TABKEY_NUM(10), UPB_VALUE_INIT_CONSTPTR("TYPE_GROUP"), NULL},
{UPB_TABKEY_NUM(11), UPB_VALUE_INIT_CONSTPTR("TYPE_MESSAGE"), NULL},
{UPB_TABKEY_NUM(12), UPB_VALUE_INIT_CONSTPTR("TYPE_BYTES"), NULL},
{UPB_TABKEY_NUM(13), UPB_VALUE_INIT_CONSTPTR("TYPE_UINT32"), NULL},
{UPB_TABKEY_NUM(14), UPB_VALUE_INIT_CONSTPTR("TYPE_ENUM"), NULL},
{UPB_TABKEY_NUM(15), UPB_VALUE_INIT_CONSTPTR("TYPE_SFIXED32"), NULL},
{UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[66]), NULL},
};
const _upb_value google_protobuf_arrays[97] = {
const _upb_value google_protobuf_arrays[224] = {
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[36]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[37]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[15]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[40]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[8]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[14]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[13]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[48]),
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[61]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[7]),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[33]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[36]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[72]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[48]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[45]),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[31]),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[35]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[42]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[51]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[50]),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[34]),
@ -408,59 +367,168 @@ const _upb_value google_protobuf_arrays[97] = {
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[43]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[25]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[63]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[64]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[3]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[51]),
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[2]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[54]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[5]),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[37]),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[10]),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[31]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[53]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[4]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[28]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[9]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[58]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[12]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[46]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[59]),
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[16]),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[24]),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[23]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[44]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[22]),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[1]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[21]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[57]),
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[20]),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[27]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[41]),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[30]),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[33]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[18]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[52]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[45]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[49]),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[32]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[29]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[46]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[47]),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[26]),
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[26]),
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[55]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[60]),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[35]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[30]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[17]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[56]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[39]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[6]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[62]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[0]),
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[38]),
UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[19]),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR("LABEL_OPTIONAL"),
UPB_VALUE_INIT_CONSTPTR("LABEL_REQUIRED"),
UPB_VALUE_INIT_CONSTPTR("LABEL_REPEATED"),
@ -471,13 +539,223 @@ const _upb_value google_protobuf_arrays[97] = {
UPB_VALUE_INIT_CONSTPTR("TYPE_UINT64"),
UPB_VALUE_INIT_CONSTPTR("TYPE_INT32"),
UPB_VALUE_INIT_CONSTPTR("TYPE_FIXED64"),
UPB_VALUE_INIT_CONSTPTR("TYPE_FIXED32"),
UPB_VALUE_INIT_CONSTPTR("TYPE_BOOL"),
UPB_VALUE_INIT_CONSTPTR("TYPE_STRING"),
UPB_VALUE_INIT_CONSTPTR("TYPE_GROUP"),
UPB_VALUE_INIT_CONSTPTR("TYPE_MESSAGE"),
UPB_VALUE_INIT_CONSTPTR("TYPE_BYTES"),
UPB_VALUE_INIT_CONSTPTR("TYPE_UINT32"),
UPB_VALUE_INIT_CONSTPTR("TYPE_ENUM"),
UPB_VALUE_INIT_CONSTPTR("TYPE_SFIXED32"),
UPB_VALUE_INIT_CONSTPTR("TYPE_SFIXED64"),
UPB_VALUE_INIT_CONSTPTR("TYPE_SINT32"),
UPB_VALUE_INIT_CONSTPTR("TYPE_SINT64"),
UPB_VALUE_INIT_CONSTPTR("STRING"),
UPB_VALUE_INIT_CONSTPTR("CORD"),
UPB_VALUE_INIT_CONSTPTR("STRING_PIECE"),
UPB_ARRAY_EMPTYENT,
UPB_ARRAY_EMPTYENT,
UPB_VALUE_INIT_CONSTPTR("SPEED"),
UPB_VALUE_INIT_CONSTPTR("CODE_SIZE"),
UPB_VALUE_INIT_CONSTPTR("LITE_RUNTIME"),
};
#ifdef UPB_DEBUG_REFS
static upb_inttable reftables[194] = {
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR),
};
#endif

@ -84,198 +84,198 @@ extern const upb_enumdef google_protobuf_enums[4];
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART &google_protobuf_msgs[19]
// Selector definitions.
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_ENDSTR 14
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STRING 12
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STARTSTR 13
#define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES_BOOL 5
#define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE_INT32 2
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_ENDSTR 19
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STRING 17
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STARTSTR 18
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSTR 12
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSEQ 9
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STRING 10
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSTR 11
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSEQ 8
#define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED_BOOL 4
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE_DOUBLE 15
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END_INT32 3
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 17
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 16
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 15
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 18
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 20
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 19
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 18
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 21
#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_ENDSTR 7
#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STRING 5
#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STARTSTR 6
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_ENDSTR 7
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STRING 5
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STARTSTR 6
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSUBMSG 36
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSEQ 35
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSEQ 34
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSUBMSG 37
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSUBMSG 27
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 15
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 17
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END_INT32 3
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START_INT32 2
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSEQ 26
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSEQ 25
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSUBMSG 28
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSUBMSG 22
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSEQ 21
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSEQ 20
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSUBMSG 23
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSUBMSG 7
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSEQ 20
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSUBMSG 22
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSEQ 25
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSUBMSG 27
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_ENDSEQ 6
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSEQ 5
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_ENDSUBMSG 8
#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSUBMSG 4
#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSEQ 3
#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSEQ 2
#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSUBMSG 5
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_ENDSTR 9
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STRING 7
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STARTSTR 8
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_ENDSTR 7
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STRING 5
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STARTSTR 6
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION_BOOL 5
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH_BOOL 8
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES_BOOL 6
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES_BOOL 18
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_ENDSTR 16
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STRING 14
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STARTSTR 15
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_ENDSTR 4
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STRING 2
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STARTSTR 3
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_INT32 9
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STARTSUBMSG 4
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_ENDSEQ 3
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STARTSEQ 2
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_ENDSUBMSG 5
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT_BOOL 2
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STARTSUBMSG 15
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_ENDSEQ 14
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STARTSEQ 13
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_ENDSUBMSG 16
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STARTSUBMSG 7
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_ENDSEQ 6
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STARTSEQ 5
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_ENDSUBMSG 8
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_ENDSTR 4
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_STRING 2
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_STARTSTR 3
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_ENDSTR 4
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_STRING 2
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_STARTSTR 3
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_ENDSTR 4
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_STRING 2
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_STARTSTR 3
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSEQ 5
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSUBMSG 7
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_ENDSTR 4
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_STARTSTR 3
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_STRING 2
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSEQ 11
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSUBMSG 13
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSEQ 10
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSUBMSG 12
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_ENDSUBMSG 31
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_STARTSUBMSG 30
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_ENDSTR 4
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_STRING 2
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_STARTSTR 3
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_STRING 2
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 11
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 10
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_ENDSEQ 6
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_ENDSUBMSG 8
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STARTSEQ 5
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STARTSUBMSG 7
#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 3
#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 2
#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 4
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_ENDSTR 4
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_STARTSTR 3
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_STRING 2
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER_INT32 5
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 7
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 6
#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 3
#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 2
#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 4
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_ENDSTR 16
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STARTSTR 15
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STRING 14
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_ENDSTR 7
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STARTSTR 6
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STRING 5
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_INT32 9
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_ENDSTR 4
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_STRING 2
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_STARTSTR 3
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STARTSUBMSG 4
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_ENDSEQ 3
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STARTSEQ 2
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_ENDSUBMSG 5
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_ENDSTR 4
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_STRING 2
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_STARTSTR 3
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_STRING 2
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER_INT32 8
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 18
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 17
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 10
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_ENDSTR 13
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STARTSTR 12
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STRING 11
#define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE_INT32 2
#define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED_BOOL 4
#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_ENDSTR 7
#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STARTSTR 6
#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STRING 5
#define GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED_BOOL 3
#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 9
#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 11
#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 8
#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 10
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSEQ 9
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSTR 12
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSEQ 8
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSTR 11
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STRING 10
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 19
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 21
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 18
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 20
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSEQ 29
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSUBMSG 31
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSEQ 28
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSUBMSG 30
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_ENDSEQ 14
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_ENDSUBMSG 16
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STARTSEQ 13
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STARTSUBMSG 15
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_ENDSTR 4
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_STRING 2
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_STARTSTR 3
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_ENDSTR 4
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STRING 2
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STARTSTR 3
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE_INT64 11
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSUBMSG 12
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSEQ 11
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSEQ 10
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSUBMSG 13
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_STRING 2
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 34
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 33
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_ENDSTR 7
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_STARTSTR 6
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_STRING 5
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSEQ 24
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSUBMSG 26
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSEQ 23
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSUBMSG 25
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_ENDSUBMSG 37
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_STARTSUBMSG 36
#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSEQ 3
#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSUBMSG 5
#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSEQ 2
#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSUBMSG 4
#define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES_BOOL 10
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH_BOOL 13
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES_BOOL 11
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES_BOOL 9
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_ENDSTR 7
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STARTSTR 6
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STRING 5
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_ENDSTR 4
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STARTSTR 3
#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STRING 2
#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR_INT32 8
#define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES_BOOL 12
#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 15
#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 17
#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 14
#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 16
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT_BOOL 2
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR_BOOL 3
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER_INT32 5
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER_INT32 8
#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR_INT32 17
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 11
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 5
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 7
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 4
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 6
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_ENDSTR 7
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STARTSTR 6
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STRING 5
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_ENDSTR 4
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_STARTSTR 3
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_STRING 2
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 12
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 10
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 11
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 23
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 24
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 10
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 11
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_STARTSUBMSG 30
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_ENDSUBMSG 31
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 11
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 12
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 6
#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 7
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 11
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_ENDSTR 10
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_STRING 8
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_STARTSTR 9
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_ENDSTR 7
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_STRING 5
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_STARTSTR 6
#define GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED_BOOL 3
#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_STRING 8
#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 3
#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 2
#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 4
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_ENDSEQ 6
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_ENDSUBMSG 8
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STARTSEQ 5
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STARTSUBMSG 7
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_ENDSTR 4
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_STARTSTR 3
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_STRING 2
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 11
#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 10
#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 3
#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 2
#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 4
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_ENDSEQ 3
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_ENDSUBMSG 5
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_ENDSEQ 3
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_INT32 4
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_STARTSEQ 2
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE_UINT64 10
#define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES_BOOL 7
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSUBMSG 31
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSEQ 30
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSEQ 29
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSUBMSG 32
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_STARTSUBMSG 26
#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_ENDSUBMSG 27
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_ENDSEQ 6
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_INT32 7
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_STARTSEQ 5
#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START_INT32 2
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_ENDSTR 18
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STRING 16
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STARTSTR 17
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 10
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_ENDSTR 16
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STRING 14
#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STARTSTR 15
#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 4
#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 3
#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 2
#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 6
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 5
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 4
#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 7
#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 4
#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 3
#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 2
#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 11
#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 10
#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 9
#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 12
#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 10
#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 9
#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 8
#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 11
#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 4
#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 3
#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 2
#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 4
#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 3
#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 2
#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STARTSUBMSG 7
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_ENDSEQ 6
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STARTSEQ 5
#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_ENDSUBMSG 8
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STARTSEQ 2
#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STARTSUBMSG 4
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_ENDSTR 18
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STARTSTR 17
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STRING 16
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE_DOUBLE 12
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_ENDSTR 9
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STARTSTR 8
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STRING 7
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION_BOOL 5
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_ENDSTR 4
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STARTSTR 3
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STRING 2
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_ENDSEQ 3
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_ENDSUBMSG 5
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STARTSEQ 2
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STARTSUBMSG 4
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE_INT64 11
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE_UINT64 10
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_ENDSTR 15
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STARTSTR 14
#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STRING 13
#ifdef __cplusplus
}; // extern "C"

@ -100,7 +100,7 @@ static upb_def *upb_deflist_last(upb_deflist *l) {
// Qualify the defname for all defs starting with offset "start" with "str".
static void upb_deflist_qualify(upb_deflist *l, char *str, int32_t start) {
for(uint32_t i = start; i < l->len; i++) {
for (uint32_t i = start; i < l->len; i++) {
upb_def *def = l->defs[i];
char *name = upb_join(str, upb_def_fullname(def));
upb_def_setfullname(def, name, NULL);
@ -124,7 +124,7 @@ typedef struct {
struct upb_descreader {
upb_deflist defs;
upb_descreader_frame stack[UPB_MAX_TYPE_DEPTH];
upb_descreader_frame stack[UPB_MAX_MESSAGE_NESTING];
int stack_len;
uint32_t number;
@ -184,7 +184,7 @@ upb_def **upb_descreader_getdefs(upb_descreader *r, void *owner, int *n) {
}
static upb_msgdef *upb_descreader_top(upb_descreader *r) {
if (r->stack_len <= 1) return NULL;
assert(r->stack_len > 1);
int index = r->stack[r->stack_len-1].start - 1;
assert(index >= 0);
return upb_downcast_msgdef_mutable(r->defs.defs[index]);
@ -291,7 +291,7 @@ static bool enumval_endmsg(void *closure, const void *hd, upb_status *status) {
static bool enum_startmsg(void *closure, const void *hd) {
UPB_UNUSED(hd);
upb_descreader *r = closure;
upb_deflist_push(&r->defs, upb_upcast(upb_enumdef_new(&r->defs)));
upb_deflist_push(&r->defs, UPB_UPCAST(upb_enumdef_new(&r->defs)));
return true;
}
@ -333,64 +333,68 @@ static bool field_startmsg(void *closure, const void *hd) {
// Converts the default value in string "str" into "d". Passes a ref on str.
// Returns true on success.
static bool parse_default(char *str, upb_value *d, int type) {
static bool parse_default(char *str, upb_fielddef *f) {
bool success = true;
if (str) {
switch(type) {
case UPB_TYPE_INT32: upb_value_setint32(d, 0); break;
case UPB_TYPE_INT64: upb_value_setint64(d, 0); break;
case UPB_TYPE_UINT32: upb_value_setuint32(d, 0);
case UPB_TYPE_UINT64: upb_value_setuint64(d, 0); break;
case UPB_TYPE_FLOAT: upb_value_setfloat(d, 0); break;
case UPB_TYPE_DOUBLE: upb_value_setdouble(d, 0); break;
case UPB_TYPE_BOOL: upb_value_setbool(d, false); break;
default: abort();
char *end;
switch (upb_fielddef_type(f)) {
case UPB_TYPE_INT32: {
long val = strtol(str, &end, 0);
if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end)
success = false;
else
upb_fielddef_setdefaultint32(f, val);
break;
}
} else {
char *end;
switch (type) {
case UPB_TYPE_INT32: {
long val = strtol(str, &end, 0);
if (val > INT32_MAX || val < INT32_MIN || errno == ERANGE || *end)
success = false;
else
upb_value_setint32(d, val);
break;
}
case UPB_TYPE_INT64:
upb_value_setint64(d, strtoll(str, &end, 0));
if (errno == ERANGE || *end) success = false;
break;
case UPB_TYPE_UINT32: {
unsigned long val = strtoul(str, &end, 0);
if (val > UINT32_MAX || errno == ERANGE || *end)
success = false;
else
upb_value_setuint32(d, val);
break;
}
case UPB_TYPE_UINT64:
upb_value_setuint64(d, strtoull(str, &end, 0));
if (errno == ERANGE || *end) success = false;
break;
case UPB_TYPE_DOUBLE:
upb_value_setdouble(d, strtod(str, &end));
if (errno == ERANGE || *end) success = false;
break;
case UPB_TYPE_FLOAT:
upb_value_setfloat(d, strtof(str, &end));
if (errno == ERANGE || *end) success = false;
break;
case UPB_TYPE_BOOL: {
if (strcmp(str, "false") == 0)
upb_value_setbool(d, false);
else if (strcmp(str, "true") == 0)
upb_value_setbool(d, true);
else
success = false;
}
default: abort();
case UPB_TYPE_INT64: {
long long val = strtoll(str, &end, 0);
if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || *end)
success = false;
else
upb_fielddef_setdefaultint64(f, val);
break;
}
case UPB_TYPE_UINT32: {
long val = strtoul(str, &end, 0);
if (val > UINT32_MAX || errno == ERANGE || *end)
success = false;
else
upb_fielddef_setdefaultuint32(f, val);
break;
}
case UPB_TYPE_UINT64: {
unsigned long long val = strtoull(str, &end, 0);
if (val > UINT64_MAX || errno == ERANGE || *end)
success = false;
else
upb_fielddef_setdefaultuint64(f, val);
break;
}
case UPB_TYPE_DOUBLE: {
double val = strtod(str, &end);
if (errno == ERANGE || *end)
success = false;
else
upb_fielddef_setdefaultdouble(f, val);
break;
}
case UPB_TYPE_FLOAT: {
float val = strtof(str, &end);
if (errno == ERANGE || *end)
success = false;
else
upb_fielddef_setdefaultfloat(f, val);
break;
}
case UPB_TYPE_BOOL: {
if (strcmp(str, "false") == 0)
upb_fielddef_setdefaultbool(f, false);
else if (strcmp(str, "true") == 0)
upb_fielddef_setdefaultbool(f, true);
else
success = false;
break;
}
default: abort();
}
return success;
}
@ -411,15 +415,12 @@ static bool field_endmsg(void *closure, const void *hd, upb_status *status) {
if (upb_fielddef_isstring(f) || upb_fielddef_type(f) == UPB_TYPE_ENUM) {
upb_fielddef_setdefaultcstr(f, r->default_string, NULL);
} else {
upb_value val;
upb_value_setptr(&val, NULL); // Silence inaccurate compiler warnings.
if (!parse_default(r->default_string, &val, upb_fielddef_type(f))) {
if (r->default_string && !parse_default(r->default_string, f)) {
// We don't worry too much about giving a great error message since the
// compiler should have ensured this was correct.
upb_status_seterrliteral(status, "Error converting default value.");
return false;
}
upb_fielddef_setdefault(f, val);
}
}
return true;
@ -484,7 +485,7 @@ static size_t field_ondefaultval(void *closure, const void *hd,
static bool msg_startmsg(void *closure, const void *hd) {
UPB_UNUSED(hd);
upb_descreader *r = closure;
upb_deflist_push(&r->defs, upb_upcast(upb_msgdef_new(&r->defs)));
upb_deflist_push(&r->defs, UPB_UPCAST(upb_msgdef_new(&r->defs)));
upb_descreader_startcontainer(r);
return true;
}
@ -493,7 +494,7 @@ static bool msg_endmsg(void *closure, const void *hd, upb_status *status) {
UPB_UNUSED(hd);
upb_descreader *r = closure;
upb_msgdef *m = upb_descreader_top(r);
if(!upb_def_fullname(upb_upcast(m))) {
if(!upb_def_fullname(UPB_UPCAST(m))) {
upb_status_seterrliteral(status, "Encountered message with no name.");
return false;
}
@ -508,7 +509,7 @@ static size_t msg_onname(void *closure, const void *hd, const char *buf,
upb_msgdef *m = upb_descreader_top(r);
// XXX: see comment at the top of the file.
char *name = upb_strndup(buf, n);
upb_def_setfullname(upb_upcast(m), name, NULL);
upb_def_setfullname(UPB_UPCAST(m), name, NULL);
upb_descreader_setscopename(r, name); // Passes ownership of name.
return n;
}

@ -13,6 +13,18 @@
#include "upb/handlers.h"
// The maximum number of nested declarations that are allowed, ie.
// message Foo {
// message Bar {
// message Baz {
// }
// }
// }
//
// This is a resource limit that affects how big our runtime stack can grow.
// TODO: make this a runtime-settable property of the Reader instance.
#define UPB_MAX_MESSAGE_NESTING 64
#ifdef __cplusplus
namespace upb {
namespace descriptor {

@ -19,6 +19,14 @@
#include "upb/google/proto2.h"
#include "upb/handlers.h"
#define ASSERT_STATUS(status) do { \
if (!upb_ok(status)) { \
fprintf(stderr, "upb status failure: %s\n", upb_status_getstr(status)); \
assert(upb_ok(status)); \
} \
} while (0)
namespace upb {
namespace proto2_bridge_google3 { class Defs; }
namespace proto2_bridge_opensource { class Defs; }
@ -44,8 +52,8 @@ class me::Defs {
const upb::MessageDef* md = h->message_def();
const goog::Message& m = *message_map_[md];
const goog::Descriptor* d = m.GetDescriptor();
for (upb::MessageDef::ConstIterator i(md); !i.Done(); i.Next()) {
const upb::FieldDef* upb_f = i.field();
for (upb::MessageDef::const_iterator i = md->begin(); i != md->end(); ++i) {
const upb::FieldDef* upb_f = *i;
const goog::FieldDescriptor* proto2_f =
d->FindFieldByNumber(upb_f->number());
if (!proto2_f) {
@ -137,27 +145,25 @@ FieldDef* AddFieldDef(const goog::Message& m, const goog::FieldDescriptor* f,
} else {
switch (upb_f->type()) {
case UPB_TYPE_INT32:
upb_f->set_default_value(MakeValue(f->default_value_int32()));
upb_f->set_default_int32(f->default_value_int32());
break;
case UPB_TYPE_INT64:
upb_f->set_default_value(
MakeValue(static_cast<int64_t>(f->default_value_int64())));
upb_f->set_default_int64(f->default_value_int64());
break;
case UPB_TYPE_UINT32:
upb_f->set_default_value(MakeValue(f->default_value_uint32()));
upb_f->set_default_uint32(f->default_value_uint32());
break;
case UPB_TYPE_UINT64:
upb_f->set_default_value(
MakeValue(static_cast<uint64_t>(f->default_value_uint64())));
upb_f->set_default_uint64(f->default_value_uint64());
break;
case UPB_TYPE_DOUBLE:
upb_f->set_default_value(MakeValue(f->default_value_double()));
upb_f->set_default_double(f->default_value_double());
break;
case UPB_TYPE_FLOAT:
upb_f->set_default_value(MakeValue(f->default_value_float()));
upb_f->set_default_float(f->default_value_float());
break;
case UPB_TYPE_BOOL:
upb_f->set_default_value(MakeValue(f->default_value_bool()));
upb_f->set_default_bool(f->default_value_bool());
break;
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
@ -168,15 +174,14 @@ FieldDef* AddFieldDef(const goog::Message& m, const goog::FieldDescriptor* f,
break;
case UPB_TYPE_ENUM:
// We set the enum default numerically.
upb_f->set_default_value(
MakeValue(static_cast<int32_t>(f->default_value_enum()->number())));
upb_f->set_default_int32(f->default_value_enum()->number());
upb_f->set_subdef_name(f->enum_type()->full_name(), &status);
break;
}
}
md->AddField(upb_f, &upb_f, &status);
UPB_ASSERT_STATUS(&status);
ASSERT_STATUS(&status);
if (weak_prototype) {
*subm = weak_prototype;
@ -200,7 +205,7 @@ upb::EnumDef* NewEnumDef(const goog::EnumDescriptor* desc, const void* owner) {
bool success = e->AddValue(val->name(), val->number(), &status);
UPB_ASSERT_VAR(success, success);
}
UPB_ASSERT_STATUS(&status);
ASSERT_STATUS(&status);
return e;
}
@ -245,7 +250,7 @@ static upb::MessageDef* NewMessageDef(const goog::Message& m, const void* owner,
}
f->set_subdef(subdef, &status);
}
UPB_ASSERT_STATUS(&status);
ASSERT_STATUS(&status);
return md;
}

@ -11,6 +11,86 @@
#ifndef UPB_HANDLERS_INL_H_
#define UPB_HANDLERS_INL_H_
#include <limits.h>
// Type detection and typedefs for integer types.
// For platforms where there are multiple 32-bit or 64-bit types, we need to be
// able to enumerate them so we can properly create overloads for all variants.
//
// If any platform existed where there were three integer types with the same
// size, this would have to become more complicated. For example, short, int,
// and long could all be 32-bits. Even more diabolically, short, int, long,
// and long long could all be 64 bits and still be standard-compliant.
// However, few platforms are this strange, and it's unlikely that upb will be
// used on the strangest ones.
// Can't count on stdint.h limits like INT32_MAX, because in C++ these are
// only defined when __STDC_LIMIT_MACROS are defined before the *first* include
// of stdint.h. We can't guarantee that someone else didn't include these first
// without defining __STDC_LIMIT_MACROS.
#define UPB_INT32_MAX 0x7fffffffLL
#define UPB_INT32_MIN (-UPB_INT32_MAX - 1)
#define UPB_INT64_MAX 0x7fffffffffffffffLL
#define UPB_INT64_MIN (-UPB_INT64_MAX - 1)
#if INT_MAX == UPB_INT32_MAX && INT_MIN == UPB_INT32_MIN
#define UPB_INT_IS_32BITS 1
#endif
#if LONG_MAX == UPB_INT32_MAX && LONG_MIN == UPB_INT32_MIN
#define UPB_LONG_IS_32BITS 1
#endif
#if LONG_MAX == UPB_INT64_MAX && LONG_MIN == UPB_INT64_MIN
#define UPB_LONG_IS_64BITS 1
#endif
#if LLONG_MAX == UPB_INT64_MAX && LLONG_MIN == UPB_INT64_MIN
#define UPB_LLONG_IS_64BITS 1
#endif
// We use macros instead of typedefs so we can undefine them later and avoid
// leaking them outside this header file.
#if UPB_INT_IS_32BITS
#define UPB_INT32_T int
#define UPB_UINT32_T unsigned int
#if UPB_LONG_IS_32BITS
#define UPB_TWO_32BIT_TYPES 1
#define UPB_INT32ALT_T long
#define UPB_UINT32ALT_T unsigned long
#endif // UPB_LONG_IS_32BITS
#elif UPB_LONG_IS_32BITS // && !UPB_INT_IS_32BITS
#define UPB_INT32_T long
#define UPB_UINT32_T unsigned long
#endif // UPB_INT_IS_32BITS
#if UPB_LONG_IS_64BITS
#define UPB_INT64_T long
#define UPB_UINT64_T unsigned long
#if UPB_LLONG_IS_64BITS
#define UPB_TWO_64BIT_TYPES 1
#define UPB_INT64ALT_T long long
#define UPB_UINT64ALT_T unsigned long long
#endif // UPB_LLONG_IS_64BITS
#elif UPB_LLONG_IS_64BITS // && !UPB_LONG_IS_64BITS
#define UPB_INT64_T long long
#define UPB_UINT64_T unsigned long long
#endif // UPB_LONG_IS_64BITS
#undef UPB_INT32_MAX
#undef UPB_INT32_MIN
#undef UPB_INT64_MAX
#undef UPB_INT64_MIN
#undef UPB_INT_IS_32BITS
#undef UPB_LONG_IS_32BITS
#undef UPB_LONG_IS_64BITS
#undef UPB_LLONG_IS_64BITS
#ifdef __cplusplus
namespace upb {
@ -312,20 +392,20 @@ inline Handlers::StringHandler BindHandler(
TYPE_METHODS(Double, double, double, double);
TYPE_METHODS(Float, float, float, float);
TYPE_METHODS(UInt64, uint64, uint64_t, upb_uint64_t);
TYPE_METHODS(UInt32, uint32, uint32_t, upb_uint32_t);
TYPE_METHODS(Int64, int64, int64_t, upb_int64_t);
TYPE_METHODS(Int32, int32, int32_t, upb_int32_t);
TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64_T);
TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32_T);
TYPE_METHODS(Int64, int64, int64_t, UPB_INT64_T);
TYPE_METHODS(Int32, int32, int32_t, UPB_INT32_T);
TYPE_METHODS(Bool, bool, bool, bool);
#ifdef UPB_TWO_32BIT_TYPES
TYPE_METHODS(Int32, int32, int32_t, upb_int32alt_t);
TYPE_METHODS(Uint32, uint32, uint32_t, upb_uint32alt_t);
TYPE_METHODS(Int32, int32, int32_t, UPB_INT32ALT_T);
TYPE_METHODS(UInt32, uint32, uint32_t, UPB_UINT32ALT_T);
#endif
#ifdef UPB_TWO_64BIT_TYPES
TYPE_METHODS(Int64, int64, int64_t, upb_int64alt_t);
TYPE_METHODS(UInt64, uint64, uint64_t, upb_uint64alt_t);
TYPE_METHODS(Int64, int64, int64_t, UPB_INT64ALT_T);
TYPE_METHODS(UInt64, uint64, uint64_t, UPB_UINT64ALT_T);
#endif
#undef TYPE_METHODS
@ -483,4 +563,15 @@ inline const void *Handlers::GetHandlerData(Handlers::Selector selector) {
#endif // __cplusplus
#undef UPB_TWO_32BIT_TYPES
#undef UPB_TWO_64BIT_TYPES
#undef UPB_INT32_T
#undef UPB_UINT32_T
#undef UPB_INT32ALT_T
#undef UPB_UINT32ALT_T
#undef UPB_INT64_T
#undef UPB_UINT64_T
#undef UPB_INT64ALT_T
#undef UPB_UINT64ALT_T
#endif // UPB_HANDLERS_INL_H_

@ -46,7 +46,7 @@ static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit,
upb_fielddef *f = upb_msg_iter_field(&i);
if (!upb_fielddef_issubmsg(f)) continue;
const upb_handlers *sub = upb_handlers_getsubhandlers(h, f);
if (sub) visit(r, upb_upcast(sub), closure);
if (sub) visit(r, UPB_UPCAST(sub), closure);
}
}
@ -101,7 +101,7 @@ static int32_t getsel(upb_handlers *h, const upb_fielddef *f,
upb_handlertype_t type) {
upb_selector_t sel;
assert(!upb_handlers_isfrozen(h));
if (upb_handlers_msgdef(h) != upb_fielddef_msgdef(f)) {
if (upb_handlers_msgdef(h) != upb_fielddef_containingtype(f)) {
upb_status_seterrf(
h->status_, "type mismatch: field %s does not belong to message %s",
upb_fielddef_name(f), upb_msgdef_fullname(upb_handlers_msgdef(h)));
@ -153,24 +153,24 @@ static bool doset(upb_handlers *h, upb_selector_t sel, upb_func *func,
/* Public interface ***********************************************************/
bool upb_handlers_isfrozen(const upb_handlers *h) {
return upb_refcounted_isfrozen(upb_upcast(h));
return upb_refcounted_isfrozen(UPB_UPCAST(h));
}
void upb_handlers_ref(const upb_handlers *h, const void *owner) {
upb_refcounted_ref(upb_upcast(h), owner);
upb_refcounted_ref(UPB_UPCAST(h), owner);
}
void upb_handlers_unref(const upb_handlers *h, const void *owner) {
upb_refcounted_unref(upb_upcast(h), owner);
upb_refcounted_unref(UPB_UPCAST(h), owner);
}
void upb_handlers_donateref(
const upb_handlers *h, const void *from, const void *to) {
upb_refcounted_donateref(upb_upcast(h), from, to);
upb_refcounted_donateref(UPB_UPCAST(h), from, to);
}
void upb_handlers_checkref(const upb_handlers *h, const void *owner) {
upb_refcounted_checkref(upb_upcast(h), owner);
upb_refcounted_checkref(UPB_UPCAST(h), owner);
}
@ -192,13 +192,13 @@ upb_handlers *upb_handlers_new(const upb_msgdef *md, const upb_frametype *ft,
h->cleanup_size = 0;
h->cleanup_len = 0;
upb_msgdef_ref(h->msg, h);
if (!upb_refcounted_init(upb_upcast(h), &vtbl, owner)) goto oom;
if (!upb_refcounted_init(UPB_UPCAST(h), &vtbl, owner)) goto oom;
// calloc() above initialized all handlers to NULL.
return h;
oom:
freehandlers(upb_upcast(h));
freehandlers(UPB_UPCAST(h));
return NULL;
}
@ -217,8 +217,8 @@ const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m,
upb_inttable_uninit(&state.tab);
if (!ret) return NULL;
upb_refcounted *r = upb_upcast(ret);
bool ok = upb_refcounted_freeze(&r, 1, NULL);
upb_refcounted *r = UPB_UPCAST(ret);
bool ok = upb_refcounted_freeze(&r, 1, NULL, UPB_MAX_HANDLER_DEPTH);
UPB_ASSERT_VAR(ok, ok);
return ret;
@ -276,7 +276,7 @@ bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f,
assert(!upb_handlers_isfrozen(h));
assert(upb_fielddef_issubmsg(f));
if (SUBH(h, f->selector_base)) return false; // Can't reset.
if (upb_upcast(upb_handlers_msgdef(sub)) != upb_fielddef_subdef(f)) {
if (UPB_UPCAST(upb_handlers_msgdef(sub)) != upb_fielddef_subdef(f)) {
return false;
}
SUBH(h, f->selector_base) = sub;
@ -324,7 +324,8 @@ bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) {
}
}
if (!upb_refcounted_freeze((upb_refcounted*const*)handlers, n, s)) {
if (!upb_refcounted_freeze((upb_refcounted*const*)handlers, n, s,
UPB_MAX_HANDLER_DEPTH)) {
return false;
}
@ -395,7 +396,7 @@ bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type,
break;
// Subhandler slot is selector_base + 2.
}
assert(*s < upb_fielddef_msgdef(f)->selector_count);
assert(*s < upb_fielddef_containingtype(f)->selector_count);
return true;
}

@ -45,6 +45,15 @@ typedef struct upb_handlers upb_handlers;
typedef struct upb_sinkframe upb_sinkframe;
#endif
// The maximum depth that the handler graph can have. This is a resource limit
// for the C stack since we sometimes need to recursively traverse the graph.
// Cycles are ok; the traversal will stop when it detects a cycle, but we must
// hit the cycle before the maximum depth is reached.
//
// If having a single static limit is too inflexible, we can add another variant
// of Handlers::Freeze that allows specifying this as a parameter.
#define UPB_MAX_HANDLER_DEPTH 64
typedef struct {
void (*func)();
const void *data;

@ -0,0 +1,855 @@
/*
* upb - a minimalist implementation of protocol buffers.
*
* Copyright (c) 2013 Google Inc. See LICENSE for details.
* Author: Josh Haberman <jhaberman@gmail.com>
*
* Code to compile a upb::MessageDef into bytecode for decoding that message.
* Bytecode definition is in decoder.int.h.
*/
#include <stdarg.h>
#include "upb/pb/decoder.int.h"
#include "upb/pb/varint.int.h"
#include "upb/bytestream.h"
#ifdef UPB_DUMP_BYTECODE
#include <stdio.h>
#endif
#define MAXLABEL 5
#define EMPTYLABEL -1
/* upb_pbdecodermethod ********************************************************/
static upb_pbdecodermethod *newmethod(const upb_msgdef *msg,
const upb_handlers *dest_handlers) {
upb_pbdecodermethod *ret = malloc(sizeof(upb_pbdecodermethod));
ret->msg = msg;
ret->dest_handlers = dest_handlers;
ret->native_code = false; // If we JIT, it will update this later.
upb_inttable_init(&ret->dispatch, UPB_CTYPE_UINT64);
if (ret->dest_handlers) {
upb_handlers_ref(ret->dest_handlers, ret);
}
return ret;
}
static void freemethod(upb_pbdecodermethod *method) {
if (method->dest_handlers) {
upb_handlers_unref(method->dest_handlers, method);
}
upb_inttable_uninit(&method->dispatch);
free(method);
}
/* upb_pbdecoderplan **********************************************************/
upb_pbdecoderplan *newplan() {
upb_pbdecoderplan *p = malloc(sizeof(*p));
upb_inttable_init(&p->methods, UPB_CTYPE_PTR);
p->code = NULL;
p->code_end = NULL;
return p;
}
void freeplan(void *_p) {
upb_pbdecoderplan *p = _p;
upb_inttable_iter i;
upb_inttable_begin(&i, &p->methods);
for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i));
freemethod(method);
}
upb_inttable_uninit(&p->methods);
free(p->code);
#ifdef UPB_USE_JIT_X64
upb_pbdecoder_freejit(p);
#endif
free(p);
}
void set_bytecode_handlers(upb_pbdecoderplan *p, upb_handlers *h) {
upb_handlers_setstartstr(h, UPB_BYTESTREAM_BYTES, upb_pbdecoder_start, p,
NULL);
upb_handlers_setstring(h, UPB_BYTESTREAM_BYTES, upb_pbdecoder_decode, p,
freeplan);
upb_handlers_setendstr(h, UPB_BYTESTREAM_BYTES, upb_pbdecoder_end, p, NULL);
}
static const upb_pbdecoderplan *getdecoderplan(const upb_handlers *h) {
if (upb_handlers_frametype(h) != &upb_pbdecoder_frametype)
return NULL;
upb_selector_t sel;
if (!upb_handlers_getselector(UPB_BYTESTREAM_BYTES, UPB_HANDLER_STARTSTR,
&sel)) {
return NULL;
}
return upb_handlers_gethandlerdata(h, sel);
}
/* compiler *******************************************************************/
// Data used only at compilation time.
typedef struct {
upb_pbdecoderplan *plan;
uint32_t *pc;
int fwd_labels[MAXLABEL];
int back_labels[MAXLABEL];
} compiler;
static compiler *newcompiler(upb_pbdecoderplan *plan) {
compiler *ret = malloc(sizeof(compiler));
ret->plan = plan;
for (int i = 0; i < MAXLABEL; i++) {
ret->fwd_labels[i] = EMPTYLABEL;
ret->back_labels[i] = EMPTYLABEL;
}
return ret;
}
static void freecompiler(compiler *c) {
free(c);
}
const size_t ptr_words = sizeof(void*) / sizeof(uint32_t);
// How many words an instruction is.
static int instruction_len(uint32_t instr) {
switch (getop(instr)) {
case OP_SETDISPATCH: return 1 + ptr_words;
case OP_TAGN: return 3;
case OP_SETBIGGROUPNUM: return 2;
default: return 1;
}
}
bool op_has_longofs(int32_t instruction) {
switch (getop(instruction)) {
case OP_CALL:
case OP_BRANCH:
case OP_CHECKDELIM:
return true;
// The "tag" instructions only have 8 bytes available for the jump target,
// but that is ok because these opcodes only require short jumps.
case OP_TAG1:
case OP_TAG2:
case OP_TAGN:
return false;
default:
assert(false);
return false;
}
}
static int32_t getofs(uint32_t instruction) {
if (op_has_longofs(instruction)) {
return (int32_t)instruction >> 8;
} else {
return (int8_t)(instruction >> 8);
}
}
static void setofs(uint32_t *instruction, int32_t ofs) {
if (op_has_longofs(*instruction)) {
*instruction = getop(*instruction) | ofs << 8;
} else {
*instruction = (*instruction & ~0xff00) | ((ofs & 0xff) << 8);
}
assert(getofs(*instruction) == ofs); // Would fail in cases of overflow.
}
static uint32_t pcofs(compiler *c) { return c->pc - c->plan->code; }
// Defines a local label at the current PC location. All previous forward
// references are updated to point to this location. The location is noted
// for any future backward references.
static void label(compiler *c, unsigned int label) {
assert(label < MAXLABEL);
int val = c->fwd_labels[label];
uint32_t *codep = (val == EMPTYLABEL) ? NULL : c->plan->code + val;
while (codep) {
int ofs = getofs(*codep);
setofs(codep, c->pc - codep - instruction_len(*codep));
codep = ofs ? codep + ofs : NULL;
}
c->fwd_labels[label] = EMPTYLABEL;
c->back_labels[label] = pcofs(c);
}
// Creates a reference to a numbered label; either a forward reference
// (positive arg) or backward reference (negative arg). For forward references
// the value returned now is actually a "next" pointer into a linked list of all
// instructions that use this label and will be patched later when the label is
// defined with label().
//
// The returned value is the offset that should be written into the instruction.
static int32_t labelref(compiler *c, int label) {
assert(label < MAXLABEL);
if (label == LABEL_DISPATCH) {
// No resolving required.
return 0;
} else if (label < 0) {
// Backward local label. Relative to the next instruction.
uint32_t from = (c->pc + 1) - c->plan->code;
return c->back_labels[-label] - from;
} else {
// Forward local label: prepend to (possibly-empty) linked list.
int *lptr = &c->fwd_labels[label];
int32_t ret = (*lptr == EMPTYLABEL) ? 0 : *lptr - pcofs(c);
*lptr = pcofs(c);
return ret;
}
}
static void put32(compiler *c, uint32_t v) {
if (c->pc == c->plan->code_end) {
int ofs = pcofs(c);
size_t oldsize = c->plan->code_end - c->plan->code;
size_t newsize = UPB_MAX(oldsize * 2, 64);
// TODO(haberman): handle OOM.
c->plan->code = realloc(c->plan->code, newsize * sizeof(uint32_t));
c->plan->code_end = c->plan->code + newsize;
c->pc = c->plan->code + ofs;
}
*c->pc++ = v;
}
static void putop(compiler *c, opcode op, ...) {
va_list ap;
va_start(ap, op);
switch (op) {
case OP_SETDISPATCH: {
uintptr_t ptr = (uintptr_t)va_arg(ap, void*);
put32(c, OP_SETDISPATCH);
put32(c, ptr);
if (sizeof(uintptr_t) > sizeof(uint32_t))
put32(c, (uint64_t)ptr >> 32);
break;
}
case OP_STARTMSG:
case OP_ENDMSG:
case OP_PUSHTAGDELIM:
case OP_PUSHLENDELIM:
case OP_POP:
case OP_SETDELIM:
case OP_HALT:
put32(c, op);
break;
case OP_PARSE_DOUBLE:
case OP_PARSE_FLOAT:
case OP_PARSE_INT64:
case OP_PARSE_UINT64:
case OP_PARSE_INT32:
case OP_PARSE_FIXED64:
case OP_PARSE_FIXED32:
case OP_PARSE_BOOL:
case OP_PARSE_UINT32:
case OP_PARSE_SFIXED32:
case OP_PARSE_SFIXED64:
case OP_PARSE_SINT32:
case OP_PARSE_SINT64:
case OP_STARTSEQ:
case OP_SETGROUPNUM:
case OP_ENDSEQ:
case OP_STARTSUBMSG:
case OP_ENDSUBMSG:
case OP_STARTSTR:
case OP_STRING:
case OP_ENDSTR:
put32(c, op | va_arg(ap, upb_selector_t) << 8);
break;
case OP_SETBIGGROUPNUM:
put32(c, op);
put32(c, va_arg(ap, int));
break;
case OP_CALL: {
const upb_pbdecodermethod *method = va_arg(ap, upb_pbdecodermethod *);
put32(c, op | (method->base.ofs - (pcofs(c) + 1)) << 8);
break;
}
case OP_CHECKDELIM:
case OP_BRANCH: {
uint32_t instruction = op;
int label = va_arg(ap, int);
setofs(&instruction, labelref(c, label));
put32(c, instruction);
break;
}
case OP_TAG1:
case OP_TAG2: {
int label = va_arg(ap, int);
uint64_t tag = va_arg(ap, uint64_t);
uint32_t instruction = op | (tag << 16);
assert(tag <= 0xffff);
setofs(&instruction, labelref(c, label));
put32(c, instruction);
break;
}
case OP_TAGN: {
int label = va_arg(ap, int);
uint64_t tag = va_arg(ap, uint64_t);
uint32_t instruction = op | (upb_value_size(tag) << 16);
setofs(&instruction, labelref(c, label));
put32(c, instruction);
put32(c, tag);
put32(c, tag >> 32);
break;
}
}
va_end(ap);
}
#if defined(UPB_USE_JIT_X64) || defined(UPB_DUMP_BYTECODE)
const char *upb_pbdecoder_getopname(unsigned int op) {
#define OP(op) [OP_ ## op] = "OP_" #op
#define T(op) OP(PARSE_##op)
static const char *names[] = {
"<no opcode>",
T(DOUBLE), T(FLOAT), T(INT64), T(UINT64), T(INT32), T(FIXED64), T(FIXED32),
T(BOOL), T(UINT32), T(SFIXED32), T(SFIXED64), T(SINT32), T(SINT64),
OP(STARTMSG), OP(ENDMSG), OP(STARTSEQ), OP(ENDSEQ), OP(STARTSUBMSG),
OP(ENDSUBMSG), OP(STARTSTR), OP(STRING), OP(ENDSTR), OP(CALL),
OP(PUSHLENDELIM), OP(PUSHTAGDELIM), OP(SETDELIM), OP(CHECKDELIM),
OP(BRANCH), OP(TAG1), OP(TAG2), OP(TAGN), OP(SETDISPATCH), OP(POP),
OP(SETGROUPNUM), OP(SETBIGGROUPNUM), OP(HALT),
};
return op > OP_HALT ? names[0] : names[op];
#undef OP
#undef T
}
#endif
#ifdef UPB_DUMP_BYTECODE
static void dumpbc(uint32_t *p, uint32_t *end, FILE *f) {
uint32_t *begin = p;
while (p < end) {
fprintf(f, "%p %8tx", p, p - begin);
uint32_t instr = *p++;
uint8_t op = getop(instr);
fprintf(f, " %s", upb_pbdecoder_getopname(op));
switch ((opcode)op) {
case OP_SETDISPATCH: {
const upb_inttable *dispatch;
memcpy(&dispatch, p, sizeof(void*));
p += ptr_words;
const upb_pbdecodermethod *method =
(void *)((char *)dispatch -
offsetof(upb_pbdecodermethod, dispatch));
fprintf(f, " %s", upb_msgdef_fullname(method->msg));
break;
}
case OP_STARTMSG:
case OP_ENDMSG:
case OP_PUSHLENDELIM:
case OP_PUSHTAGDELIM:
case OP_POP:
case OP_SETDELIM:
case OP_HALT:
break;
case OP_PARSE_DOUBLE:
case OP_PARSE_FLOAT:
case OP_PARSE_INT64:
case OP_PARSE_UINT64:
case OP_PARSE_INT32:
case OP_PARSE_FIXED64:
case OP_PARSE_FIXED32:
case OP_PARSE_BOOL:
case OP_PARSE_UINT32:
case OP_PARSE_SFIXED32:
case OP_PARSE_SFIXED64:
case OP_PARSE_SINT32:
case OP_PARSE_SINT64:
case OP_STARTSEQ:
case OP_ENDSEQ:
case OP_STARTSUBMSG:
case OP_ENDSUBMSG:
case OP_STARTSTR:
case OP_STRING:
case OP_ENDSTR:
case OP_SETGROUPNUM:
fprintf(f, " %d", instr >> 8);
break;
case OP_SETBIGGROUPNUM:
fprintf(f, " %d", *p++);
break;
case OP_CHECKDELIM:
case OP_CALL:
case OP_BRANCH:
fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
break;
case OP_TAG1:
case OP_TAG2: {
fprintf(f, " tag:0x%x", instr >> 16);
if (getofs(instr)) {
fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
}
break;
}
case OP_TAGN: {
uint64_t tag = *p++;
tag |= (uint64_t)*p++ << 32;
fprintf(f, " tag:0x%llx", (long long)tag);
fprintf(f, " n:%d", instr >> 16);
if (getofs(instr)) {
fprintf(f, " =>0x%tx", p + getofs(instr) - begin);
}
break;
}
}
fputs("\n", f);
}
}
#endif
static uint64_t get_encoded_tag(const upb_fielddef *f, int wire_type) {
uint32_t tag = (upb_fielddef_number(f) << 3) | wire_type;
uint64_t encoded_tag = upb_vencode32(tag);
// No tag should be greater than 5 bytes.
assert(encoded_tag <= 0xffffffffff);
return encoded_tag;
}
static void putchecktag(compiler *c, const upb_fielddef *f,
int wire_type, int dest) {
uint64_t tag = get_encoded_tag(f, wire_type);
switch (upb_value_size(tag)) {
case 1:
putop(c, OP_TAG1, dest, tag);
break;
case 2:
putop(c, OP_TAG2, dest, tag);
break;
default:
putop(c, OP_TAGN, dest, tag);
break;
}
}
static upb_selector_t getsel(const upb_fielddef *f, upb_handlertype_t type) {
upb_selector_t selector;
bool ok = upb_handlers_getselector(f, type, &selector);
UPB_ASSERT_VAR(ok, ok);
return selector;
}
// Marks the current bytecode position as the dispatch target for this message,
// field, and wire type.
//
static void dispatchtarget(compiler *c, upb_pbdecodermethod *method,
const upb_fielddef *f, int wire_type) {
// Offset is relative to msg base.
uint64_t ofs = pcofs(c) - method->base.ofs;
uint32_t fn = upb_fielddef_number(f);
upb_inttable *d = &method->dispatch;
upb_value v;
if (upb_inttable_remove(d, fn, &v)) {
// TODO: prioritize based on packed setting in .proto file.
uint64_t oldval = upb_value_getuint64(v);
assert(((oldval >> 8) & 0xff) == 0); // wt2 should not be set yet.
upb_inttable_insert(d, fn, upb_value_uint64(oldval | (wire_type << 8)));
upb_inttable_insert(d, fn + UPB_MAX_FIELDNUMBER, upb_value_uint64(ofs));
} else {
upb_inttable_insert(d, fn, upb_value_uint64((ofs << 16) | wire_type));
}
}
static void putpush(compiler *c, const upb_fielddef *f) {
if (upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE) {
putop(c, OP_PUSHLENDELIM);
} else {
uint32_t fn = upb_fielddef_number(f);
putop(c, OP_PUSHTAGDELIM);
if (fn >= 1 << 24) {
putop(c, OP_SETBIGGROUPNUM, fn);
} else {
putop(c, OP_SETGROUPNUM, fn);
}
}
}
static upb_pbdecodermethod *find_submethod(const compiler *c,
const upb_pbdecodermethod *method,
const upb_fielddef *f) {
const void *key = method->dest_handlers ?
(const void*)upb_handlers_getsubhandlers(method->dest_handlers, f) :
(const void*)upb_downcast_msgdef(upb_fielddef_subdef(f));
upb_value v;
bool ok = upb_inttable_lookupptr(&c->plan->methods, key, &v);
UPB_ASSERT_VAR(ok, ok);
return upb_value_getptr(v);
}
// Adds bytecode for parsing the given message to the given decoderplan,
// while adding all dispatch targets to this message's dispatch table.
static void compile_method(compiler *c, upb_pbdecodermethod *method) {
assert(method);
// Symbolic names for our local labels.
const int LABEL_LOOPSTART = 1; // Top of a repeated field loop.
const int LABEL_LOOPBREAK = 2; // To jump out of a repeated loop
const int LABEL_FIELD = 3; // Jump backward to find the most recent field.
const int LABEL_ENDMSG = 4; // To reach the OP_ENDMSG instr for this msg.
// Index is descriptor type.
static const uint8_t native_wire_types[] = {
UPB_WIRE_TYPE_END_GROUP, // ENDGROUP
UPB_WIRE_TYPE_64BIT, // DOUBLE
UPB_WIRE_TYPE_32BIT, // FLOAT
UPB_WIRE_TYPE_VARINT, // INT64
UPB_WIRE_TYPE_VARINT, // UINT64
UPB_WIRE_TYPE_VARINT, // INT32
UPB_WIRE_TYPE_64BIT, // FIXED64
UPB_WIRE_TYPE_32BIT, // FIXED32
UPB_WIRE_TYPE_VARINT, // BOOL
UPB_WIRE_TYPE_DELIMITED, // STRING
UPB_WIRE_TYPE_START_GROUP, // GROUP
UPB_WIRE_TYPE_DELIMITED, // MESSAGE
UPB_WIRE_TYPE_DELIMITED, // BYTES
UPB_WIRE_TYPE_VARINT, // UINT32
UPB_WIRE_TYPE_VARINT, // ENUM
UPB_WIRE_TYPE_32BIT, // SFIXED32
UPB_WIRE_TYPE_64BIT, // SFIXED64
UPB_WIRE_TYPE_VARINT, // SINT32
UPB_WIRE_TYPE_VARINT, // SINT64
};
// Clear all entries in the dispatch table.
upb_inttable_uninit(&method->dispatch);
upb_inttable_init(&method->dispatch, UPB_CTYPE_UINT64);
method->base.ofs = pcofs(c);
putop(c, OP_SETDISPATCH, &method->dispatch);
putop(c, OP_STARTMSG);
label(c, LABEL_FIELD);
upb_msg_iter i;
for(upb_msg_begin(&i, method->msg); !upb_msg_done(&i); upb_msg_next(&i)) {
const upb_fielddef *f = upb_msg_iter_field(&i);
upb_descriptortype_t type = upb_fielddef_descriptortype(f);
// From a decoding perspective, ENUM is the same as INT32.
if (type == UPB_DESCRIPTOR_TYPE_ENUM)
type = UPB_DESCRIPTOR_TYPE_INT32;
label(c, LABEL_FIELD);
switch (upb_fielddef_type(f)) {
case UPB_TYPE_MESSAGE: {
const upb_pbdecodermethod *sub_m = find_submethod(c, method, f);
int wire_type = (type == UPB_DESCRIPTOR_TYPE_MESSAGE) ?
UPB_WIRE_TYPE_DELIMITED : UPB_WIRE_TYPE_START_GROUP;
if (upb_fielddef_isseq(f)) {
putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
putchecktag(c, f, wire_type, LABEL_DISPATCH);
dispatchtarget(c, method, f, wire_type);
putop(c, OP_PUSHTAGDELIM);
putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
label(c, LABEL_LOOPSTART);
putpush(c, f);
putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
putop(c, OP_CALL, sub_m);
putop(c, OP_POP);
putop(c, OP_ENDSUBMSG, getsel(f, UPB_HANDLER_ENDSUBMSG));
if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
putop(c, OP_SETDELIM);
}
putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
putop(c, OP_BRANCH, -LABEL_LOOPSTART);
label(c, LABEL_LOOPBREAK);
putop(c, OP_POP);
putop(c, OP_ENDSEQ, getsel(f, UPB_HANDLER_ENDSEQ));
} else {
putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
putchecktag(c, f, wire_type, LABEL_DISPATCH);
dispatchtarget(c, method, f, wire_type);
putpush(c, f);
putop(c, OP_STARTSUBMSG, getsel(f, UPB_HANDLER_STARTSUBMSG));
putop(c, OP_CALL, sub_m);
putop(c, OP_POP);
putop(c, OP_ENDSUBMSG, getsel(f, UPB_HANDLER_ENDSUBMSG));
if (wire_type == UPB_WIRE_TYPE_DELIMITED) {
putop(c, OP_SETDELIM);
}
}
break;
}
case UPB_TYPE_STRING:
case UPB_TYPE_BYTES:
if (upb_fielddef_isseq(f)) {
putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
putop(c, OP_PUSHTAGDELIM);
putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ));
label(c, LABEL_LOOPSTART);
putop(c, OP_PUSHLENDELIM);
putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
putop(c, OP_POP);
putop(c, OP_ENDSTR, getsel(f, UPB_HANDLER_ENDSTR));
putop(c, OP_SETDELIM);
putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_LOOPBREAK);
putop(c, OP_BRANCH, -LABEL_LOOPSTART);
label(c, LABEL_LOOPBREAK);
putop(c, OP_POP);
putop(c, OP_ENDSEQ, getsel(f, UPB_HANDLER_ENDSEQ));
} else {
putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
putop(c, OP_PUSHLENDELIM);
putop(c, OP_STARTSTR, getsel(f, UPB_HANDLER_STARTSTR));
putop(c, OP_STRING, getsel(f, UPB_HANDLER_STRING));
putop(c, OP_POP);
putop(c, OP_ENDSTR, getsel(f, UPB_HANDLER_ENDSTR));
putop(c, OP_SETDELIM);
}
break;
default: {
opcode parse_type = (opcode)type;
assert(parse_type >= 0 && parse_type <= OP_MAX);
upb_selector_t sel = getsel(f, upb_handlers_getprimitivehandlertype(f));
int wire_type = native_wire_types[upb_fielddef_descriptortype(f)];
if (upb_fielddef_isseq(f)) {
putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
putchecktag(c, f, UPB_WIRE_TYPE_DELIMITED, LABEL_DISPATCH);
dispatchtarget(c, method, f, UPB_WIRE_TYPE_DELIMITED);
putop(c, OP_PUSHLENDELIM);
putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); // Packed
label(c, LABEL_LOOPSTART);
putop(c, parse_type, sel);
putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
putop(c, OP_BRANCH, -LABEL_LOOPSTART);
dispatchtarget(c, method, f, wire_type);
putop(c, OP_PUSHTAGDELIM);
putop(c, OP_STARTSEQ, getsel(f, UPB_HANDLER_STARTSEQ)); // Non-packed
label(c, LABEL_LOOPSTART);
putop(c, parse_type, sel);
putop(c, OP_CHECKDELIM, LABEL_LOOPBREAK);
putchecktag(c, f, wire_type, LABEL_LOOPBREAK);
putop(c, OP_BRANCH, -LABEL_LOOPSTART);
label(c, LABEL_LOOPBREAK);
putop(c, OP_POP); // Packed and non-packed join.
putop(c, OP_ENDSEQ, getsel(f, UPB_HANDLER_ENDSEQ));
putop(c, OP_SETDELIM); // Could remove for non-packed by dup ENDSEQ.
} else {
putop(c, OP_CHECKDELIM, LABEL_ENDMSG);
putchecktag(c, f, wire_type, LABEL_DISPATCH);
dispatchtarget(c, method, f, wire_type);
putop(c, parse_type, sel);
}
}
}
}
// For now we just loop back to the last field of the message (or if none,
// the DISPATCH opcode for the message.
putop(c, OP_BRANCH, -LABEL_FIELD);
label(c, LABEL_ENDMSG);
putop(c, OP_ENDMSG);
upb_inttable_compact(&method->dispatch);
}
// Populate "methods" with new upb_pbdecodermethod objects reachable from "md".
// "h" can be NULL, in which case the methods will not be statically bound to
// destination handlers.
//
// Returns the method for this msgdef/handlers.
//
// Note that there is a deep difference between keying the method table on
// upb_msgdef and keying it on upb_handlers. Since upb_msgdef : upb_handlers
// can be 1:many, binding a handlers statically can result in *more* methods
// being generated than if the methods are dynamically-bound.
//
// On the other hand, if/when the optimization mentioned below is implemented,
// binding to a upb_handlers can result in *fewer* methods being generated if
// many of the submessages have no handlers bound to them.
static upb_pbdecodermethod *find_methods(compiler *c,
const upb_msgdef *md,
const upb_handlers *h) {
const void *key = h ? (const void*)h : (const void*)md;
upb_value v;
if (upb_inttable_lookupptr(&c->plan->methods, key, &v))
return upb_value_getptr(v);
upb_pbdecodermethod *method = newmethod(md, h);
// Takes ownership of method.
upb_inttable_insertptr(&c->plan->methods, key, upb_value_ptr(method));
upb_msg_iter i;
for(upb_msg_begin(&i, md); !upb_msg_done(&i); upb_msg_next(&i)) {
const upb_fielddef *f = upb_msg_iter_field(&i);
if (upb_fielddef_type(f) != UPB_TYPE_MESSAGE)
continue;
const upb_handlers *sub_h = h ? upb_handlers_getsubhandlers(h, f) : NULL;
if (h && !sub_h &&
upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_MESSAGE) {
// OPT: We could optimize away the sub-method, but would have to make sure
// this field is compiled as a string instead of a submessage.
}
find_methods(c, upb_downcast_msgdef(upb_fielddef_subdef(f)), sub_h);
}
return method;
}
// (Re-)compile bytecode for all messages in "msgs", ensuring that the code
// for "md" is emitted first. Overwrites any existing bytecode in "c".
static void compile_methods(compiler *c) {
// Start over at the beginning of the bytecode.
c->pc = c->plan->code;
compile_method(c, c->plan->topmethod);
upb_inttable_iter i;
upb_inttable_begin(&i, &c->plan->methods);
for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i));
if (method != c->plan->topmethod) {
compile_method(c, method);
}
}
}
/* JIT setup. ******************************************************************/
#ifdef UPB_USE_JIT_X64
static void sethandlers(upb_pbdecoderplan *p, upb_handlers *h, bool allowjit) {
p->jit_code = NULL;
if (allowjit) {
upb_pbdecoder_jit(p); // Compile byte-code into machine code.
upb_handlers_setstartstr(h, UPB_BYTESTREAM_BYTES, upb_pbdecoder_start, p,
freeplan);
upb_handlers_setstring(h, UPB_BYTESTREAM_BYTES, p->jit_code, NULL, NULL);
upb_handlers_setendstr(h, UPB_BYTESTREAM_BYTES, upb_pbdecoder_end, p, NULL);
} else {
set_bytecode_handlers(p, h);
}
}
static bool bind_dynamic(bool allowjit) {
// For the moment, JIT handlers always bind statically, but bytecode handlers
// never do.
return !allowjit;
}
#else // UPB_USE_JIT_X64
static void sethandlers(upb_pbdecoderplan *p, upb_handlers *h, bool allowjit) {
// No JIT compiled in; use bytecode handlers unconditionally.
UPB_UNUSED(allowjit);
set_bytecode_handlers(p, h);
}
static bool bind_dynamic(bool allowjit) {
// Bytecode handlers never bind statically.
return true;
}
#endif // UPB_USE_JIT_X64
/* Public interface ***********************************************************/
bool upb_pbdecoder_isdecoder(const upb_handlers *h) {
return getdecoderplan(h) != NULL;
}
bool upb_pbdecoderplan_hasjitcode(const upb_pbdecoderplan *p) {
#ifdef UPB_USE_JIT_X64
return p->jit_code != NULL;
#else
UPB_UNUSED(p);
return false;
#endif
}
bool upb_pbdecoder_hasjitcode(const upb_handlers *h) {
const upb_pbdecoderplan *p = getdecoderplan(h);
if (!p) return false;
return upb_pbdecoderplan_hasjitcode(p);
}
uint32_t *upb_pbdecoderplan_codebase(const upb_pbdecoderplan *p) {
return p->code;
}
upb_string_handler *upb_pbdecoderplan_jitcode(const upb_pbdecoderplan *p) {
#ifdef UPB_USE_JIT_X64
return p->jit_code;
#else
assert(false);
return NULL;
#endif
}
const upb_handlers *upb_pbdecoder_getdesthandlers(const upb_handlers *h) {
const upb_pbdecoderplan *p = getdecoderplan(h);
if (!p) return NULL;
return p->topmethod->dest_handlers;
}
const upb_handlers *upb_pbdecoder_gethandlers(const upb_handlers *dest,
bool allowjit,
const void *owner) {
UPB_UNUSED(allowjit);
assert(upb_handlers_isfrozen(dest));
const upb_msgdef *md = upb_handlers_msgdef(dest);
upb_pbdecoderplan *p = newplan();
compiler *c = newcompiler(p);
if (bind_dynamic(allowjit)) {
// If binding dynamically, remove the reference against destination
// handlers.
dest = NULL;
}
p->topmethod = find_methods(c, md, dest);
// We compile in two passes:
// 1. all messages are assigned relative offsets from the beginning of the
// bytecode (saved in method->base).
// 2. forwards OP_CALL instructions can be correctly linked since message
// offsets have been previously assigned.
//
// Could avoid the second pass by linking OP_CALL instructions somehow.
compile_methods(c);
compile_methods(c);
p->code_end = c->pc;
#ifdef UPB_DUMP_BYTECODE
FILE *f = fopen("/tmp/upb-bytecode", "wb");
assert(f);
dumpbc(p->code, p->code_end, stderr);
dumpbc(p->code, p->code_end, f);
fclose(f);
#endif
upb_handlers *h = upb_handlers_new(
UPB_BYTESTREAM, &upb_pbdecoder_frametype, owner);
sethandlers(p, h, allowjit);
freecompiler(c);
return h;
}

@ -0,0 +1,368 @@
/*
* upb - a minimalist implementation of protocol buffers.
*
* Copyright (c) 2013 Google Inc. See LICENSE for details.
* Author: Josh Haberman <jhaberman@gmail.com>
*
* Driver code for the x64 JIT compiler.
*/
#include <dlfcn.h>
#include <stdio.h>
#include <sys/mman.h>
#include "upb/pb/decoder.h"
#include "upb/pb/decoder.int.h"
#include "upb/pb/varint.int.h"
#include "upb/shim/shim.h"
// These defines are necessary for DynASM codegen.
// See dynasm/dasm_proto.h for more info.
#define Dst_DECL jitcompiler *jc
#define Dst_REF (jc->dynasm)
#define Dst (jc)
// In debug mode, make DynASM do internal checks (must be defined before any
// dasm header is included.
#ifndef NDEBUG
#define DASM_CHECKS
#endif
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
#define DECODE_EOF -3
typedef struct {
upb_pbdecoderplan *plan;
uint32_t *pc;
// This pointer is allocated by dasm_init() and freed by dasm_free().
struct dasm_State *dynasm;
// Maps bytecode pc location -> pclabel.
upb_inttable pclabels;
upb_inttable pcdefined;
// For marking labels that should go into the generated code.
// Maps pclabel -> char* label (string is owned by the table).
upb_inttable asmlabels;
// For checking that two asmlabels aren't defined for the same byte.
int lastlabelofs;
// The total number of pclabels currently defined.
uint32_t pclabel_count;
// Used by DynASM to store globals.
void **globals;
bool usefp;
bool chkret;
} jitcompiler;
// Functions called by codegen.
static int pclabel(jitcompiler *jc, const void *here);
static int define_pclabel(jitcompiler *jc, const void *here);
static void asmlabel(jitcompiler *jc, const char *fmt, ...);
#include "dynasm/dasm_proto.h"
#include "dynasm/dasm_x86.h"
#include "upb/pb/compile_decoder_x64.h"
static jitcompiler *newjitcompiler(upb_pbdecoderplan *plan) {
jitcompiler *jc = malloc(sizeof(jitcompiler));
jc->usefp = false;
jc->chkret = false;
jc->plan = plan;
jc->pclabel_count = 0;
jc->lastlabelofs = -1;
upb_inttable_init(&jc->pclabels, UPB_CTYPE_UINT32);
upb_inttable_init(&jc->pcdefined, UPB_CTYPE_BOOL);
upb_inttable_init(&jc->asmlabels, UPB_CTYPE_PTR);
jc->globals = malloc(UPB_JIT_GLOBAL__MAX * sizeof(*jc->globals));
dasm_init(jc, 1);
dasm_setupglobal(jc, jc->globals, UPB_JIT_GLOBAL__MAX);
dasm_setup(jc, upb_jit_actionlist);
return jc;
}
static void freejitcompiler(jitcompiler *jc) {
upb_inttable_iter i;
upb_inttable_begin(&i, &jc->asmlabels);
for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
free(upb_value_getptr(upb_inttable_iter_value(&i)));
}
upb_inttable_uninit(&jc->asmlabels);
upb_inttable_uninit(&jc->pclabels);
upb_inttable_uninit(&jc->pcdefined);
dasm_free(jc);
free(jc->globals);
free(jc);
}
// Returns a pclabel associated with the given arbitrary pointer.
static int pclabel(jitcompiler *jc, const void *here) {
upb_value v;
bool found = upb_inttable_lookupptr(&jc->pclabels, here, &v);
if (!found) {
upb_value_setuint32(&v, jc->pclabel_count++);
dasm_growpc(jc, jc->pclabel_count);
upb_inttable_insertptr(&jc->pclabels, here, v);
}
return upb_value_getuint32(v);
}
// Defines a pclabel associated with the given arbitrary pointer.
// May only be called once (to avoid redefining the pclabel).
static int define_pclabel(jitcompiler *jc, const void *here) {
// Will assert-fail if it already exists.
upb_inttable_insertptr(&jc->pcdefined, here, upb_value_bool(true));
return pclabel(jc, here);
}
static void upb_reg_jit_gdb(jitcompiler *jc);
// Given a pcofs relative to method, returns the machine code offset for it
// (relative to the beginning of the machine code).
int nativeofs(jitcompiler *jc, const upb_pbdecodermethod *method, int pcofs) {
void *target = jc->plan->code + method->base.ofs + pcofs;
return dasm_getpclabel(jc, pclabel(jc, target));
}
// Given a pcofs relative to this method's base, returns a machine code offset
// relative to pclabel(dispatch->array) (which is used in jitdispatch as the
// machine code base for dispatch table lookups).
uint32_t dispatchofs(jitcompiler *jc, const upb_pbdecodermethod *method,
int pcofs) {
int ofs1 = dasm_getpclabel(jc, pclabel(jc, method->dispatch.array));
int ofs2 = nativeofs(jc, method, pcofs);
assert(ofs1 > 0);
assert(ofs2 > 0);
int ret = ofs2 - ofs1;
assert(ret > 0);
return ret;
}
// Rewrites the dispatch tables into machine code offsets.
static void patchdispatch(jitcompiler *jc) {
upb_inttable_iter i;
upb_inttable_begin(&i, &jc->plan->methods);
for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i));
upb_inttable *dispatch = &method->dispatch;
upb_inttable_iter i2;
upb_inttable_begin(&i2, dispatch);
for (; !upb_inttable_done(&i2); upb_inttable_next(&i2)) {
uintptr_t key = upb_inttable_iter_key(&i2);
if (key == 0) continue;
uint64_t val = upb_value_getuint64(upb_inttable_iter_value(&i2));
uint64_t newval;
if (key <= UPB_MAX_FIELDNUMBER) {
// Primary slot.
uint64_t oldofs = val >> 16;
uint64_t newofs = dispatchofs(jc, method, oldofs);
newval = (val & 0xffff) | (newofs << 16);
assert((int64_t)newval > 0);
} else {
// Secondary slot. Since we have 64 bits for the value, we use an
// absolute offset.
newval = (uint64_t)(jc->plan->jit_code + nativeofs(jc, method, val));
}
bool ok = upb_inttable_replace(dispatch, key, upb_value_uint64(newval));
UPB_ASSERT_VAR(ok, ok);
}
}
}
// Define for JIT debugging.
#ifdef UPB_JIT_LOAD_SO
static void load_so(jitcompiler *jc) {
// Dump to a .so file in /tmp and load that, so all the tooling works right
// (for example, debuggers and profilers will see symbol names for the JIT-ted
// code). This is the same goal of the GDB JIT code below, but the GDB JIT
// interface is only used/understood by GDB. Hopefully a standard will
// develop for registering JIT-ted code that all tools will recognize,
// rendering this obsolete.
//
// Requires that gcc is available from the command-line.
// Convert all asm labels from pclabel offsets to machine code offsets.
upb_inttable_iter i;
upb_inttable mclabels;
upb_inttable_init(&mclabels, UPB_CTYPE_PTR);
upb_inttable_begin(&i, &jc->asmlabels);
for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
upb_inttable_insert(&mclabels,
dasm_getpclabel(jc, upb_inttable_iter_key(&i)),
upb_inttable_iter_value(&i));
}
FILE *f = fopen("/tmp/upb-jit-code.s", "w");
if (f) {
fputs(" .text\n\n", f);
size_t linelen = 0;
for (size_t i = 0; i < jc->plan->jit_size; i++) {
upb_value v;
if (upb_inttable_lookup(&mclabels, i, &v)) {
const char *label = upb_value_getptr(v);
// "X." makes our JIT syms recognizable as such, which we build into
// other tooling.
fprintf(f, "\n\nX.%s:\n", label);
fprintf(f, " .globl X.%s", label);
linelen = 1000;
}
if (linelen >= 77) {
linelen = fprintf(f, "\n .byte %u", jit_code[i]);
} else {
linelen += fprintf(f, ",%u", jit_code[i]);
}
}
fputs("\n", f);
fclose(f);
} else {
fprintf(stderr, "Couldn't open /tmp/upb-jit-code.s for writing/\n");
}
// TODO: racy
if (system("gcc -shared -o /tmp/upb-jit-code.so /tmp/upb-jit-code.s") != 0) {
abort();
}
jc->dl = dlopen("/tmp/upb-jit-code.so", RTLD_LAZY);
if (!jc->dl) {
fprintf(stderr, "Couldn't dlopen(): %s\n", dlerror());
abort();
}
munmap(jit_code, jc->plan->jit_size);
jit_code = dlsym(jc->dl, "X.enterjit");
if (!jit_code) {
fprintf(stderr, "Couldn't find enterjit sym\n");
abort();
}
upb_inttable_uninit(&mclabels);
}
#endif
void upb_pbdecoder_jit(upb_pbdecoderplan *plan) {
plan->debug_info = NULL;
plan->dl = NULL;
jitcompiler *jc = newjitcompiler(plan);
emit_static_asm(jc);
jitbytecode(jc);
int dasm_status = dasm_link(jc, &jc->plan->jit_size);
if (dasm_status != DASM_S_OK) {
fprintf(stderr, "DynASM error; returned status: 0x%08x\n", dasm_status);
abort();
}
char *jit_code = mmap(NULL, jc->plan->jit_size, PROT_READ | PROT_WRITE,
MAP_32BIT | MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
dasm_encode(jc, jit_code);
mprotect(jit_code, jc->plan->jit_size, PROT_EXEC | PROT_READ);
upb_reg_jit_gdb(jc);
#ifdef UPB_JIT_LOAD_SO
load_so(jc);
#endif
jc->plan->jit_code = (upb_string_handler *)jit_code;
patchdispatch(jc);
freejitcompiler(jc);
}
void upb_pbdecoder_freejit(upb_pbdecoderplan *plan) {
if (!plan->jit_code) return;
if (plan->dl) {
dlclose(plan->dl);
} else {
munmap(plan->jit_code, plan->jit_size);
}
free(plan->debug_info);
// TODO: unregister GDB JIT interface.
}
// To debug JIT-ted code with GDB we need to tell GDB about the JIT-ted code
// at runtime. GDB 7.x+ has defined an interface for doing this, and these
// structure/function defintions are copied out of gdb/jit.h
//
// We need to give GDB an ELF file at runtime describing the symbols we have
// generated. To avoid implementing the ELF format, we generate an ELF file
// at compile-time and compile it in as a character string. We can replace
// a few key constants (address of JIT-ted function and its size) by looking
// for a few magic numbers and doing a dumb string replacement.
//
// Unfortunately this approach is showing its limits; we can only define one
// symbol, and this approach only works with GDB. The .so approach above is
// more reliable.
#ifndef __APPLE__
const unsigned char upb_jit_debug_elf_file[] = {
#include "upb/pb/jit_debug_elf_file.h"
};
typedef enum {
GDB_JIT_NOACTION = 0,
GDB_JIT_REGISTER,
GDB_JIT_UNREGISTER
} jit_actions_t;
typedef struct gdb_jit_entry {
struct gdb_jit_entry *next_entry;
struct gdb_jit_entry *prev_entry;
const char *symfile_addr;
uint64_t symfile_size;
} gdb_jit_entry;
typedef struct {
uint32_t version;
uint32_t action_flag;
gdb_jit_entry *relevant_entry;
gdb_jit_entry *first_entry;
} gdb_jit_descriptor;
gdb_jit_descriptor __jit_debug_descriptor = {1, GDB_JIT_NOACTION, NULL, NULL};
void __attribute__((noinline)) __jit_debug_register_code() {
__asm__ __volatile__("");
}
static void upb_reg_jit_gdb(jitcompiler *jc) {
// Create debug info.
size_t elf_len = sizeof(upb_jit_debug_elf_file);
jc->plan->debug_info = malloc(elf_len);
memcpy(jc->plan->debug_info, upb_jit_debug_elf_file, elf_len);
uint64_t *p = (void *)jc->plan->debug_info;
for (; (void *)(p + 1) <= (void *)jc->plan->debug_info + elf_len; ++p) {
if (*p == 0x12345678) {
*p = (uintptr_t)jc->plan->jit_code;
}
if (*p == 0x321) {
*p = jc->plan->jit_size;
}
}
// Register the JIT-ted code with GDB.
gdb_jit_entry *e = malloc(sizeof(gdb_jit_entry));
e->next_entry = __jit_debug_descriptor.first_entry;
e->prev_entry = NULL;
if (e->next_entry) e->next_entry->prev_entry = e;
e->symfile_addr = jc->plan->debug_info;
e->symfile_size = elf_len;
__jit_debug_descriptor.first_entry = e;
__jit_debug_descriptor.relevant_entry = e;
__jit_debug_descriptor.action_flag = GDB_JIT_REGISTER;
__jit_debug_register_code();
}
#else
static void upb_reg_jit_gdb(jitcompiler *jc) { (void)jc; }
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -14,6 +14,13 @@
#include "upb/sink.h"
// The maximum that any submessages can be nested. Matches proto2's limit.
// At the moment this specifies the size of several statically-sized arrays
// and therefore setting it high will cause more memory to be used. Will
// be replaced by a runtime-configurable limit and dynamically-resizing arrays.
// TODO: make this a runtime-settable property of Decoder.
#define UPB_DECODER_MAX_NESTING 64
#ifdef __cplusplus
namespace upb {
namespace pb {

@ -0,0 +1,242 @@
#ifndef UPB_DECODER_INT_H_
#define UPB_DECODER_INT_H_
#include <stdlib.h>
#include "upb/def.h"
#include "upb/handlers.h"
#include "upb/sink.h"
#include "upb/pb/decoder.h"
// Opcode definitions. The canonical meaning of each opcode is its
// implementation in the interpreter (the JIT is written to match this).
//
// All instructions have the opcode in the low byte.
// Instruction format for most instructions is:
//
// +-------------------+--------+
// | arg (24) | op (8) |
// +-------------------+--------+
//
// Exceptions are indicated below. A few opcodes are multi-word.
typedef enum {
// Opcodes 1-8, 13, 15-18 parse their respective descriptor types.
// Arg for all of these is the upb selector for this field.
#define T(type) OP_PARSE_ ## type = UPB_DESCRIPTOR_TYPE_ ## type
T(DOUBLE), T(FLOAT), T(INT64), T(UINT64), T(INT32), T(FIXED64), T(FIXED32),
T(BOOL), T(UINT32), T(SFIXED32), T(SFIXED64), T(SINT32), T(SINT64),
#undef T
OP_STARTMSG = 9, // No arg.
OP_ENDMSG = 10, // No arg.
OP_STARTSEQ = 11,
OP_ENDSEQ = 12,
OP_STARTSUBMSG = 14,
OP_ENDSUBMSG = 19,
OP_STARTSTR = 20,
OP_STRING = 21,
OP_ENDSTR = 22,
OP_PUSHTAGDELIM = 23, // No arg.
OP_PUSHLENDELIM = 24, // No arg.
OP_POP = 25, // No arg.
OP_SETDELIM = 26, // No arg.
OP_SETGROUPNUM = 27,
OP_SETBIGGROUPNUM = 28, // two words: | unused (24) | opc || groupnum (32) |
// The arg for these opcodes is a local label reference.
OP_CHECKDELIM = 29,
OP_CALL = 30,
OP_BRANCH = 31,
// Different opcodes depending on how many bytes expected.
OP_TAG1 = 32, // | expected tag (16) | jump target (8) | opc (8) |
OP_TAG2 = 33, // | expected tag (16) | jump target (8) | opc (8) |
OP_TAGN = 34, // three words:
// | unused (16) | jump target(8) | opc (8) |
// | expected tag 1 (32) |
// | expected tag 2 (32) |
OP_SETDISPATCH = 35, // N words:
// | unused (24) | opc |
// | upb_inttable* (32 or 64) |
OP_HALT = 36, // No arg.
} opcode;
#define OP_MAX OP_HALT
UPB_INLINE opcode getop(uint32_t instr) { return instr & 0xff; }
const upb_frametype upb_pbdecoder_frametype;
// Decoder entry points; used as handlers.
void *upb_pbdecoder_start(void *closure, const void *handler_data,
size_t size_hint);
size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf,
size_t size);
bool upb_pbdecoder_end(void *closure, const void *handler_data);
// Decoder-internal functions that the JIT calls to handle fallback paths.
void *upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf,
size_t size);
size_t upb_pbdecoder_suspend(upb_pbdecoder *d);
int32_t upb_pbdecoder_skipunknown(upb_pbdecoder *d, uint32_t fieldnum,
uint8_t wire_type);
int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d, uint64_t expected);
int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d, uint64_t *u64);
int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32);
int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64);
void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg);
// Error messages that are shared between the bytecode and JIT decoders.
extern const char *kPbDecoderStackOverflow;
typedef struct _upb_pbdecoderplan upb_pbdecoderplan;
// Access to decoderplan members needed by the decoder.
bool upb_pbdecoderplan_hasjitcode(const upb_pbdecoderplan *p);
uint32_t *upb_pbdecoderplan_codebase(const upb_pbdecoderplan *p);
const char *upb_pbdecoder_getopname(unsigned int op);
upb_string_handler *upb_pbdecoderplan_jitcode(const upb_pbdecoderplan *p);
// JIT entry point.
void upb_pbdecoder_jit(upb_pbdecoderplan *plan);
void upb_pbdecoder_freejit(upb_pbdecoderplan *plan);
// A special label that means "do field dispatch for this message and branch to
// wherever that takes you."
#define LABEL_DISPATCH 0
#define DECODE_OK -1
#define DECODE_MISMATCH -2 // Used only from checktag_slow().
#define DECODE_ENDGROUP -2 // Used only from checkunknown().
typedef struct {
// The absolute stream offset of the end-of-frame delimiter.
// Non-delimited frames (groups and non-packed repeated fields) reuse the
// delimiter of their parent, even though the frame may not end there.
//
// NOTE: the JIT stores a slightly different value here for non-top frames.
// It stores the value relative to the end of the enclosed message. But the
// innermost frame is still stored the same way, which is important for
// ensuring that calls from the JIT into C work correctly.
uint64_t end_ofs;
uint32_t *base;
uint32_t groupnum;
union {
upb_inttable *dispatch; // Not used by the JIT.
void *closure; // Only used by the JIT.
} u;
} upb_pbdecoder_frame;
struct upb_pbdecoder {
// Where we push parsed data (not owned).
upb_sink *sink;
size_t call_len;
uint32_t *pc, *last;
// Current input buffer and its stream offset.
const char *buf, *ptr, *end, *checkpoint;
// End of the delimited region, relative to ptr, or NULL if not in this buf.
const char *delim_end;
// End of the delimited region, relative to ptr, or end if not in this buf.
const char *data_end;
// Overall stream offset of "buf."
uint64_t bufstart_ofs;
// How many bytes past the end of the user buffer we want to skip.
size_t skip;
// Buffer for residual bytes not parsed from the previous buffer.
// The maximum number of residual bytes we require is 12; a five-byte
// unknown tag plus an eight-byte value, less one because the value
// is only a partial value.
char residual[12];
char *residual_end;
// Stores the user buffer passed to our decode function.
const char *buf_param;
size_t size_param;
#ifdef UPB_USE_JIT_X64
// Used momentarily by the generated code to store a value while a user
// function is called.
uint32_t tmp_len;
const void *saved_rsp;
#endif
upb_status *status;
// Our internal stack.
upb_pbdecoder_frame *top, *limit;
upb_pbdecoder_frame stack[UPB_DECODER_MAX_NESTING];
uint32_t *callstack[UPB_DECODER_MAX_NESTING * 2];
};
// Data pertaining to a single decoding method/function.
// Each method contains code to parse a single message type.
// If may or may not be bound to a destination handlers object.
typedef struct {
// While compiling, the base is relative in "ofs", after compiling it is
// absolute in "ptr".
union {
uint32_t ofs; // PC offset of method.
const void *ptr; // Pointer to bytecode or machine code for this method.
} base;
// Whether this method is native code or bytecode.
bool native_code;
// The message type that this method is parsing.
const upb_msgdef *msg;
// The destination handlers this method is bound to, or NULL if this method
// can be bound to a destination handlers instance at runtime.
//
// If non-NULL, we own a ref.
const upb_handlers *dest_handlers;
// The dispatch table layout is:
// [field number] -> [ 48-bit offset ][ 8-bit wt2 ][ 8-bit wt1 ]
//
// If wt1 matches, jump to the 48-bit offset. If wt2 matches, lookup
// (UPB_MAX_FIELDNUMBER + fieldnum) and jump there.
//
// We need two wire types because of packed/non-packed compatibility. A
// primitive repeated field can use either wire type and be valid. While we
// could key the table on fieldnum+wiretype, the table would be 8x sparser.
//
// Storing two wire types in the primary value allows us to quickly rule out
// the second wire type without needing to do a separate lookup (this case is
// less common than an unknown field).
upb_inttable dispatch;
} upb_pbdecodermethod;
struct _upb_pbdecoderplan {
// Pointer to bytecode.
uint32_t *code, *code_end;
// Maps upb_msgdef*/upb_handlers* -> upb_pbdecodermethod
upb_inttable methods;
// The method that starts parsing when we first call into the plan.
// Ideally we will remove the idea that any of the methods in the plan
// are special like this, so that any method can be the top-level one.
upb_pbdecodermethod *topmethod;
#ifdef UPB_USE_JIT_X64
// JIT-generated machine code (else NULL).
upb_string_handler *jit_code;
size_t jit_size;
char *debug_info;
void *dl;
#endif
};
#endif // UPB_DECODER_INT_H_

File diff suppressed because it is too large Load Diff

@ -19,7 +19,7 @@ upb_def **upb_load_defs_from_descriptor(const char *str, size_t len, int *n,
// Create handlers.
const upb_handlers *reader_h = upb_descreader_gethandlers(&reader_h);
const upb_handlers *decoder_h =
upb_pbdecoder_gethandlers(reader_h, false, &decoder_h);
upb_pbdecoder_gethandlers(reader_h, true, &decoder_h);
// Create pipeline.
upb_pipeline pipeline;
@ -68,8 +68,8 @@ char *upb_readfile(const char *filename, size_t *len) {
long size = ftell(f);
if(size < 0) goto error;
if(fseek(f, 0, SEEK_SET) != 0) goto error;
char *buf = malloc(size);
if(fread(buf, size, 1, f) != 1) goto error;
char *buf = malloc(size + 1);
if(size && fread(buf, size, 1, f) != 1) goto error;
fclose(f);
if (len) *len = size;
return buf;

@ -5,7 +5,7 @@
* Author: Josh Haberman <jhaberman@gmail.com>
*/
#include "upb/pb/varint.h"
#include "upb/pb/varint.int.h"
// A basic branch-based decoder, uses 32-bit values to get good performance
// on 32-bit architectures (but performs well on 64-bits also).

@ -11,6 +11,7 @@
#ifndef UPB_VARINT_DECODER_H_
#define UPB_VARINT_DECODER_H_
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include "upb/upb.h"
@ -29,6 +30,8 @@ typedef enum {
UPB_WIRE_TYPE_32BIT = 5,
} upb_wiretype_t;
#define UPB_MAX_WIRE_TYPE 5
// The maximum number of bytes that it takes to encode a 64-bit varint.
// Note that with a better encoding this could be 9 (TODO: write up a
// wiki document about this).
@ -87,7 +90,7 @@ UPB_VARINT_DECODER_CHECK2(massimino, upb_vdecode_max8_massimino);
// favored best-performing implementations.
UPB_INLINE upb_decoderet upb_vdecode_fast(const char *p) {
if (sizeof(long) == 8)
return upb_vdecode_check2_massimino(p);
return upb_vdecode_check2_branch64(p);
else
return upb_vdecode_check2_branch32(p);
}

@ -24,6 +24,7 @@
#include <stdlib.h>
uint32_t static_refcount = 1;
static void freeobj(upb_refcounted *o);
/* arch-specific atomic primitives *******************************************/
@ -74,90 +75,26 @@ void upb_unlock();
// code-paths that can normally never fail, like upb_refcounted_ref(). Since
// we have no way to propagage out-of-memory errors back to the user, and since
// these errors can only occur in UPB_DEBUG_REFS mode, we immediately fail.
#define CHECK_OOM(predicate) assert(predicate)
#define CHECK_OOM(predicate) if (!(predicate)) { assert(predicate); exit(1); }
typedef struct {
const upb_refcounted *obj; // Object we are taking a ref on.
int count; // How many refs there are (duplicates only allowed for ref2).
bool is_ref2;
} trackedref;
trackedref *trackedref_new(const upb_refcounted *obj, bool is_ref2) {
trackedref *trackedref_new(bool is_ref2) {
trackedref *ret = malloc(sizeof(*ret));
CHECK_OOM(ret);
ret->obj = obj;
ret->count = 1;
ret->is_ref2 = is_ref2;
return ret;
}
// A reversible function for obfuscating a uintptr_t.
// This depends on sizeof(uintptr_t) <= sizeof(uint64_t), so would fail
// on 128-bit machines.
static uintptr_t obfuscate(const void *x) { return ~(uintptr_t)x; }
static upb_value obfuscate_v(const void *x) {
return upb_value_uint64(obfuscate(x));
}
static const void *unobfuscate_v(upb_value x) {
return (void*)~upb_value_getuint64(x);
}
//
// Stores tracked references according to the following scheme:
// (upb_inttable)reftracks = {
// (void*)owner -> (upb_inttable*) = {
// obfuscate((upb_refcounted*)obj) -> obfuscate((trackedref*)is_ref2)
// }
// }
//
// obfuscate() is a function that hides the link from the heap checker, so
// that it is not followed for the purposes of deciding what has "indirectly
// leaked." Even though we have a pointer to the trackedref*, we want it to
// appear leaked if it is not freed.
//
// This scheme gives us the following desirable properties:
//
// 1. We can easily determine whether an (owner->obj) ref already exists
// and error out if a duplicate ref is taken.
//
// 2. Because the trackedref is allocated with malloc() at the point that
// the ref is taken, that memory will be leaked if the ref is not released.
// Because the malloc'd memory points to the refcounted object, the object
// itself will only be considered "indirectly leaked" by smart memory
// checkers like Valgrind. This will correctly blame the ref leaker
// instead of the innocent code that allocated the object to begin with.
//
// 3. We can easily enumerate all of the ref2 refs for a given owner, which
// allows us to double-check that the object's visit() function is
// correctly implemented.
//
static upb_inttable reftracks = UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR);
static upb_inttable *trygettab(const void *p) {
upb_value v;
return upb_inttable_lookupptr(&reftracks, p, &v) ? upb_value_getptr(v) : NULL;
}
// Gets or creates the tracking table for the given owner.
static upb_inttable *gettab(const void *p) {
upb_inttable *tab = trygettab(p);
if (tab == NULL) {
tab = malloc(sizeof(*tab));
CHECK_OOM(tab);
upb_inttable_init(tab, UPB_CTYPE_UINT64);
upb_inttable_insertptr(&reftracks, p, upb_value_ptr(tab));
}
return tab;
}
static void track(const upb_refcounted *r, const void *owner, bool ref2) {
upb_lock();
upb_inttable *refs = gettab(owner);
upb_value v;
if (upb_inttable_lookup(refs, obfuscate(r), &v)) {
trackedref *ref = (trackedref*)unobfuscate_v(v);
if (upb_inttable_lookupptr(r->refs, owner, &v)) {
trackedref *ref = upb_value_getptr(v);
// Since we allow multiple ref2's for the same to/from pair without
// allocating separate memory for each one, we lose the fine-grained
// tracking behavior we get with regular refs. Since ref2s only happen
@ -167,29 +104,38 @@ static void track(const upb_refcounted *r, const void *owner, bool ref2) {
assert(ref->is_ref2);
ref->count++;
} else {
trackedref *ref = trackedref_new(r, ref2);
bool ok = upb_inttable_insert(refs, obfuscate(r), obfuscate_v(ref));
trackedref *ref = trackedref_new(ref2);
bool ok = upb_inttable_insertptr(r->refs, owner, upb_value_ptr(ref));
CHECK_OOM(ok);
if (ref2) {
// We know this cast is safe when it is a ref2, because it's coming from
// another refcounted object.
const upb_refcounted *from = owner;
assert(!upb_inttable_lookupptr(from->ref2s, r, NULL));
ok = upb_inttable_insertptr(from->ref2s, r, upb_value_ptr(NULL));
CHECK_OOM(ok);
}
}
upb_unlock();
}
static void untrack(const upb_refcounted *r, const void *owner, bool ref2) {
upb_lock();
upb_inttable *refs = gettab(owner);
upb_value v;
bool found = upb_inttable_lookup(refs, obfuscate(r), &v);
bool found = upb_inttable_lookupptr(r->refs, owner, &v);
// This assert will fail if an owner attempts to release a ref it didn't have.
UPB_ASSERT_VAR(found, found);
trackedref *ref = (trackedref*)unobfuscate_v(v);
trackedref *ref = upb_value_getptr(v);
assert(ref->is_ref2 == ref2);
if (--ref->count == 0) {
free(ref);
upb_inttable_remove(refs, obfuscate(r), NULL);
if (upb_inttable_count(refs) == 0) {
upb_inttable_uninit(refs);
free(refs);
upb_inttable_removeptr(&reftracks, owner, NULL);
upb_inttable_removeptr(r->refs, owner, NULL);
if (ref2) {
// We know this cast is safe when it is a ref2, because it's coming from
// another refcounted object.
const upb_refcounted *from = owner;
bool removed = upb_inttable_removeptr(from->ref2s, r, NULL);
assert(removed);
}
}
upb_unlock();
@ -197,12 +143,10 @@ static void untrack(const upb_refcounted *r, const void *owner, bool ref2) {
static void checkref(const upb_refcounted *r, const void *owner, bool ref2) {
upb_lock();
upb_inttable *refs = gettab(owner);
upb_value v;
bool found = upb_inttable_lookup(refs, obfuscate(r), &v);
bool found = upb_inttable_lookupptr(r->refs, owner, &v);
UPB_ASSERT_VAR(found, found);
trackedref *ref = (trackedref*)unobfuscate_v(v);
assert(ref->obj == r);
trackedref *ref = upb_value_getptr(v);
assert(ref->is_ref2 == ref2);
upb_unlock();
}
@ -211,18 +155,20 @@ static void checkref(const upb_refcounted *r, const void *owner, bool ref2) {
// originate from the given owner.
static void getref2s(const upb_refcounted *owner, upb_inttable *tab) {
upb_lock();
upb_inttable *refs = trygettab(owner);
if (refs) {
upb_inttable_iter i;
upb_inttable_begin(&i, refs);
for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
trackedref *ref = (trackedref*)unobfuscate_v(upb_inttable_iter_value(&i));
if (ref->is_ref2) {
upb_value count = upb_value_int32(ref->count);
bool ok = upb_inttable_insertptr(tab, ref->obj, count);
CHECK_OOM(ok);
}
}
upb_inttable_iter i;
upb_inttable_begin(&i, owner->ref2s);
for(; !upb_inttable_done(&i); upb_inttable_next(&i)) {
upb_refcounted *to = (upb_refcounted*)upb_inttable_iter_key(&i);
// To get the count we need to look in the target's table.
upb_value v;
bool found = upb_inttable_lookupptr(to->refs, owner, &v);
assert(found);
trackedref *ref = upb_value_getptr(v);
upb_value count = upb_value_int32(ref->count);
bool ok = upb_inttable_insertptr(tab, to, count);
CHECK_OOM(ok);
}
upb_unlock();
}
@ -269,6 +215,30 @@ static void visit(const upb_refcounted *r, upb_refcounted_visit *v,
if (r->vtbl->visit) r->vtbl->visit(r, v, closure);
}
static bool trackinit(upb_refcounted *r) {
r->refs = malloc(sizeof(*r->refs));
r->ref2s = malloc(sizeof(*r->ref2s));
if (!r->refs || !r->ref2s) goto err1;
if (!upb_inttable_init(r->refs, UPB_CTYPE_PTR)) goto err1;
if (!upb_inttable_init(r->ref2s, UPB_CTYPE_PTR)) goto err2;
return true;
err2:
upb_inttable_uninit(r->refs);
err1:
free(r->refs);
free(r->ref2s);
return false;
}
static void trackfree(const upb_refcounted *r) {
upb_inttable_uninit(r->refs);
upb_inttable_uninit(r->ref2s);
free(r->refs);
free(r->ref2s);
}
#else
static void track(const upb_refcounted *r, const void *owner, bool ref2) {
@ -289,6 +259,15 @@ static void checkref(const upb_refcounted *r, const void *owner, bool ref2) {
UPB_UNUSED(ref2);
}
static bool trackinit(upb_refcounted *r) {
UPB_UNUSED(r);
return true;
}
static void trackfree(const upb_refcounted *r) {
UPB_UNUSED(r);
}
static void visit(const upb_refcounted *r, upb_refcounted_visit *v,
void *closure) {
if (r->vtbl->visit) r->vtbl->visit(r, v, closure);
@ -505,7 +484,8 @@ static void crossref(const upb_refcounted *r, const upb_refcounted *subobj,
}
}
static bool freeze(upb_refcounted *const*roots, int n, upb_status *s) {
static bool freeze(upb_refcounted *const*roots, int n, upb_status *s,
int maxdepth) {
volatile bool ret = false;
// We run in two passes so that we can allocate all memory before performing
@ -514,7 +494,7 @@ static bool freeze(upb_refcounted *const*roots, int n, upb_status *s) {
tarjan t;
t.index = 0;
t.depth = 0;
t.maxdepth = UPB_MAX_TYPE_DEPTH * 2; // May want to make this a parameter.
t.maxdepth = maxdepth;
t.status = s;
if (!upb_inttable_init(&t.objattr, UPB_CTYPE_UINT64)) goto err1;
if (!upb_inttable_init(&t.stack, UPB_CTYPE_PTR)) goto err2;
@ -628,7 +608,7 @@ static bool freeze(upb_refcounted *const*roots, int n, upb_status *s) {
o = obj;
do { o->group = NULL; } while ((o = o->next) != obj);
}
obj->vtbl->free(obj);
freeobj(obj);
}
}
@ -680,11 +660,11 @@ static void release_ref2(const upb_refcounted *obj,
const upb_refcounted *subobj,
void *closure) {
UPB_UNUSED(closure);
untrack(subobj, obj, true);
if (!merged(obj, subobj)) {
assert(subobj->is_frozen);
unref(subobj);
}
untrack(subobj, obj, true);
}
static void unref(const upb_refcounted *r) {
@ -700,12 +680,17 @@ static void unref(const upb_refcounted *r) {
do {
const upb_refcounted *next = o->next;
assert(o->is_frozen || o->individual_count == 0);
o->vtbl->free((upb_refcounted*)o);
freeobj((upb_refcounted*)o);
o = next;
} while(o != r);
}
}
static void freeobj(upb_refcounted *o) {
trackfree(o);
o->vtbl->free((upb_refcounted*)o);
}
/* Public interface ***********************************************************/
@ -719,6 +704,10 @@ bool upb_refcounted_init(upb_refcounted *r,
r->group = malloc(sizeof(*r->group));
if (!r->group) return false;
*r->group = 0;
if (!trackinit(r)) {
free(r->group);
return false;
}
upb_refcounted_ref(r, owner);
return true;
}
@ -728,37 +717,37 @@ bool upb_refcounted_isfrozen(const upb_refcounted *r) {
}
void upb_refcounted_ref(const upb_refcounted *r, const void *owner) {
track(r, owner, false);
if (!r->is_frozen)
((upb_refcounted*)r)->individual_count++;
atomic_inc(r->group);
track(r, owner, false);
}
void upb_refcounted_unref(const upb_refcounted *r, const void *owner) {
untrack(r, owner, false);
if (!r->is_frozen)
((upb_refcounted*)r)->individual_count--;
unref(r);
untrack(r, owner, false);
}
void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from) {
assert(!from->is_frozen); // Non-const pointer implies this.
track(r, from, true);
if (r->is_frozen) {
atomic_inc(r->group);
} else {
merge((upb_refcounted*)r, from);
}
track(r, from, true);
}
void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from) {
assert(!from->is_frozen); // Non-const pointer implies this.
untrack(r, from, true);
if (r->is_frozen) {
unref(r);
} else {
assert(merged(r, from));
}
untrack(r, from, true);
}
void upb_refcounted_donateref(
@ -774,9 +763,10 @@ void upb_refcounted_checkref(const upb_refcounted *r, const void *owner) {
checkref(r, owner, false);
}
bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s) {
bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s,
int maxdepth) {
for (int i = 0; i < n; i++) {
assert(!roots[i]->is_frozen);
}
return freeze(roots, n, s);
return freeze(roots, n, s, maxdepth);
}

@ -19,7 +19,7 @@
#ifndef UPB_REFCOUNTED_H_
#define UPB_REFCOUNTED_H_
#include "upb/table.h"
#include "upb/table.int.h"
// Reference tracking is designed to be used with a tool like Valgrind; when
// enabled, it will cause reference leaks to show up as actual memory leaks
@ -86,6 +86,11 @@ struct upb_refcounted {
uint32_t individual_count;
bool is_frozen;
#ifdef UPB_DEBUG_REFS
upb_inttable *refs; // Maps owner -> trackedref for incoming refs.
upb_inttable *ref2s; // Set of targets for outgoing ref2s.
#endif
};
// Native C API.
@ -137,8 +142,9 @@ void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from);
// Freezes all mutable object reachable by ref2() refs from the given roots.
// This will split refcounting groups into precise SCC groups, so that
// refcounting of frozen objects can be more aggressive. If memory allocation
// fails or if more than 2**31 mutable objects are reachable from "roots",
// false is returned and the objects are unchanged.
// fails, or if more than 2**31 mutable objects are reachable from "roots", or
// if the maximum depth of the graph exceeds "maxdepth", false is returned and
// the objects are unchanged.
//
// After this operation succeeds, the objects are frozen/const, and may not be
// used through non-const pointers. In particular, they may not be passed as
@ -147,12 +153,18 @@ void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from);
// at the precise moment that they become unreachable.
//
// Caller must own refs on each object in the "roots" list.
bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s);
bool upb_refcounted_freeze(upb_refcounted *const*roots, int n, upb_status *s,
int maxdepth);
// Shared by all compiled-in refcounted objects.
extern uint32_t static_refcount;
#define UPB_REFCOUNT_INIT {&static_refcount, NULL, NULL, 0, true}
#ifdef UPB_DEBUG_REFS
#define UPB_REFCOUNT_INIT(refs, ref2s) \
{&static_refcount, NULL, NULL, 0, true, refs, ref2s}
#else
#define UPB_REFCOUNT_INIT(refs, ref2s) {&static_refcount, NULL, NULL, 0, true}
#endif
#ifdef __cplusplus
} /* extern "C" */

@ -53,17 +53,27 @@ bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset,
#undef TYPE
}
const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s) {
const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s,
upb_fieldtype_t *type) {
upb_func *f = upb_handlers_gethandler(h, s);
if ((upb_int64_handler*)f == upb_shim_setint64 ||
(upb_int32_handler*)f == upb_shim_setint32 ||
(upb_uint64_handler*)f == upb_shim_setuint64 ||
(upb_uint32_handler*)f == upb_shim_setuint32 ||
(upb_double_handler*)f == upb_shim_setdouble ||
(upb_float_handler*)f == upb_shim_setfloat ||
(upb_bool_handler*)f == upb_shim_setbool) {
return (const upb_shim_data*)upb_handlers_gethandlerdata(h, s);
if ((upb_int64_handler*)f == upb_shim_setint64) {
*type = UPB_TYPE_INT64;
} else if ((upb_int32_handler*)f == upb_shim_setint32) {
*type = UPB_TYPE_INT32;
} else if ((upb_uint64_handler*)f == upb_shim_setuint64) {
*type = UPB_TYPE_UINT64;
} else if ((upb_uint32_handler*)f == upb_shim_setuint32) {
*type = UPB_TYPE_UINT32;
} else if ((upb_double_handler*)f == upb_shim_setdouble) {
*type = UPB_TYPE_DOUBLE;
} else if ((upb_float_handler*)f == upb_shim_setfloat) {
*type = UPB_TYPE_FLOAT;
} else if ((upb_bool_handler*)f == upb_shim_setbool) {
*type = UPB_TYPE_BOOL;
} else {
return NULL;
}
return (const upb_shim_data*)upb_handlers_gethandlerdata(h, s);
}

@ -37,9 +37,10 @@ struct Shim {
// true if the handler was set successfully.
static bool Set(Handlers *h, const FieldDef *f, size_t ofs, int32_t hasbit);
// If this handler is a shim, returns the corresponding upb::Shim::Data.
// Otherwise returns NULL.
static const Data* GetData(const Handlers* h, Handlers::Selector s);
// If this handler is a shim, returns the corresponding upb::Shim::Data and
// stores the type in "type". Otherwise returns NULL.
static const Data* GetData(const Handlers* h, Handlers::Selector s,
FieldDef::Type* type);
};
} // namespace upb
@ -50,7 +51,8 @@ extern "C" {
// C API.
bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset,
int32_t hasbit);
const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s);
const upb_shim_data *upb_shim_getdata(const upb_handlers *h, upb_selector_t s,
upb_fieldtype_t *type);
#ifdef __cplusplus
} // extern "C"
@ -62,9 +64,9 @@ inline bool Shim::Set(Handlers* h, const FieldDef* f, size_t ofs,
int32_t hasbit) {
return upb_shim_set(h, f, ofs, hasbit);
}
inline const Shim::Data* Shim::GetData(const Handlers* h,
Handlers::Selector s) {
return upb_shim_getdata(h, s);
inline const Shim::Data* Shim::GetData(const Handlers* h, Handlers::Selector s,
FieldDef::Type* type) {
return upb_shim_getdata(h, s, type);
}
} // namespace

@ -201,9 +201,9 @@ static void upb_sink_resetobj(void *obj) {
static void upb_sink_init(upb_sink *s, const upb_handlers *h, upb_pipeline *p) {
s->pipeline_ = p;
s->stack = upb_pipeline_alloc(p, sizeof(*s->stack) * UPB_MAX_NESTING);
s->stack = upb_pipeline_alloc(p, sizeof(*s->stack) * UPB_SINK_MAX_NESTING);
s->top = s->stack;
s->limit = s->stack + UPB_MAX_NESTING;
s->limit = s->stack + UPB_SINK_MAX_NESTING;
s->top->h = h;
if (h->ft) {
s->top->closure = upb_pipeline_allocobj(p, h->ft);
@ -231,7 +231,6 @@ bool upb_sink_startmsg(upb_sink *s) {
}
bool upb_sink_endmsg(upb_sink *s) {
assert(s->top == s->stack);
const upb_handlers *h = s->top->h;
upb_endmsg_handler *endmsg =
(upb_endmsg_handler *)upb_handlers_gethandler(h, UPB_ENDMSG_SELECTOR);
@ -386,19 +385,10 @@ bool upb_sink_startsubmsg(upb_sink *s, upb_selector_t sel) {
// TODO: should add support for submessages without any handlers
assert(s->top->h);
s->top->closure = subc;
upb_sink_startmsg(s);
return true;
}
bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel) {
upb_endmsg_handler *endmsg = (upb_endmsg_handler *)upb_handlers_gethandler(
s->top->h, UPB_ENDMSG_SELECTOR);
if (endmsg) {
// TODO(haberman): check return value.
const void *hd =
upb_handlers_gethandlerdata(s->top->h, UPB_ENDMSG_SELECTOR);
endmsg(s->top->closure, hd, &s->pipeline_->status_);
}
--s->top;
assert(sel == s->top->selector);

@ -38,6 +38,10 @@ typedef struct upb_sink upb_sink;
#endif
struct upb_sinkframe;
// The maximum nesting depth that upb::Sink will allow. Matches proto2's limit.
// TODO: make this a runtime-settable property of Sink.
#define UPB_SINK_MAX_NESTING 64
#ifdef __cplusplus
// A upb::Pipeline is a set of sinks that can send data to each other. The
@ -168,7 +172,14 @@ class upb::Sink {
// These may not be called from within one of the same sink's handlers (in
// other words, handlers are not re-entrant).
// Should be called at the start and end of processing.
// Should be called at the start and end of every message; both the top-level
// message and submessages. This means that submessages should use the
// following sequence:
// sink->StartSubMessage(startsubmsg_selector);
// sink->StartMessage();
// // ...
// sink->EndMessage();
// sink->EndSubMessage(endsubmsg_selector);
bool StartMessage();
bool EndMessage();

@ -11,24 +11,24 @@
#include <string.h>
bool upb_symtab_isfrozen(const upb_symtab *s) {
return upb_refcounted_isfrozen(upb_upcast(s));
return upb_refcounted_isfrozen(UPB_UPCAST(s));
}
void upb_symtab_ref(const upb_symtab *s, const void *owner) {
upb_refcounted_ref(upb_upcast(s), owner);
upb_refcounted_ref(UPB_UPCAST(s), owner);
}
void upb_symtab_unref(const upb_symtab *s, const void *owner) {
upb_refcounted_unref(upb_upcast(s), owner);
upb_refcounted_unref(UPB_UPCAST(s), owner);
}
void upb_symtab_donateref(
const upb_symtab *s, const void *from, const void *to) {
upb_refcounted_donateref(upb_upcast(s), from, to);
upb_refcounted_donateref(UPB_UPCAST(s), from, to);
}
void upb_symtab_checkref(const upb_symtab *s, const void *owner) {
upb_refcounted_checkref(upb_upcast(s), owner);
upb_refcounted_checkref(UPB_UPCAST(s), owner);
}
static void upb_symtab_free(upb_refcounted *r) {
@ -47,7 +47,7 @@ static const struct upb_refcounted_vtbl vtbl = {NULL, &upb_symtab_free};
upb_symtab *upb_symtab_new(const void *owner) {
upb_symtab *s = malloc(sizeof(*s));
upb_refcounted_init(upb_upcast(s), &vtbl, owner);
upb_refcounted_init(UPB_UPCAST(s), &vtbl, owner);
upb_strtable_init(&s->symtab, UPB_CTYPE_PTR);
return s;
}
@ -100,7 +100,7 @@ const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym,
static upb_def *upb_resolvename(const upb_strtable *t,
const char *base, const char *sym) {
if(strlen(sym) == 0) return NULL;
if(sym[0] == UPB_SYMBOL_SEPARATOR) {
if(sym[0] == '.') {
// Symbols starting with '.' are absolute, so we do a single lookup.
// Slice to omit the leading '.'
upb_value v;
@ -243,7 +243,7 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor,
upb_msgdef *m = upb_dyncast_msgdef_mutable(def);
if (!m) continue;
// Type names are resolved relative to the message in which they appear.
const char *base = upb_def_fullname(upb_upcast(m));
const char *base = upb_msgdef_fullname(m);
upb_msg_iter j;
for(upb_msg_begin(&j, m); !upb_msg_done(&j); upb_msg_next(&j)) {

@ -154,9 +154,9 @@ inline SymbolTable* SymbolTable::New(const void* owner) {
return upb_symtab_new(owner);
}
inline RefCounted* SymbolTable::Upcast() { return upb_upcast(this); }
inline RefCounted* SymbolTable::Upcast() { return UPB_UPCAST(this); }
inline const RefCounted* SymbolTable::Upcast() const {
return upb_upcast(this);
return UPB_UPCAST(this);
}
inline bool SymbolTable::IsFrozen() const {
return upb_symtab_isfrozen(this);

@ -7,23 +7,31 @@
* Implementation is heavily inspired by Lua's ltable.c.
*/
#include "upb/table.h"
#include "upb/table.int.h"
#include <stdlib.h>
#include <string.h>
#define UPB_MAXARRSIZE 16 // 64k.
// From Chromium.
#define ARRAY_SIZE(x) \
((sizeof(x)/sizeof(0[x])) / ((size_t)(!(sizeof(x) % sizeof(0[x])))))
static const double MAX_LOAD = 0.85;
// The minimum percentage of an array part that we will allow. This is a
// speed/memory-usage tradeoff (though it's not straightforward because of
// The minimum utilization of the array part of a mixed hash/array table. This
// is a speed/memory-usage tradeoff (though it's not straightforward because of
// cache effects). The lower this is, the more memory we'll use.
static const double MIN_DENSITY = 0.1;
int upb_log2(uint64_t v) {
bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; }
int log2ceil(uint64_t v) {
int ret = 0;
bool pow2 = is_pow2(v);
while (v >>= 1) ret++;
ret = pow2 ? ret : ret + 1; // Ceiling.
return UPB_MIN(UPB_MAXARRSIZE, ret);
}
@ -49,9 +57,9 @@ static bool isfull(upb_table *t) {
return (double)(t->count + 1) / upb_table_size(t) > MAX_LOAD;
}
static bool init(upb_table *t, upb_ctype_t type, uint8_t size_lg2) {
static bool init(upb_table *t, upb_ctype_t ctype, uint8_t size_lg2) {
t->count = 0;
t->type = type;
t->ctype = ctype;
t->size_lg2 = size_lg2;
t->mask = upb_table_size(t) ? upb_table_size(t) - 1 : 0;
size_t bytes = upb_table_size(t) * sizeof(upb_tabent);
@ -88,7 +96,7 @@ static bool lookup(const upb_table *t, upb_tabkey key, upb_value *v,
const upb_tabent *e = findentry(t, key, hash, eql);
if (e) {
if (v) {
_upb_value_setval(v, e->val, t->type);
_upb_value_setval(v, e->val, t->ctype);
}
return true;
} else {
@ -100,7 +108,7 @@ static bool lookup(const upb_table *t, upb_tabkey key, upb_value *v,
static void insert(upb_table *t, upb_tabkey key, upb_value val,
hashfunc_t *hash, eqlfunc_t *eql) {
assert(findentry(t, key, hash, eql) == NULL);
assert(val.type == t->type);
assert(val.ctype == t->ctype);
t->count++;
upb_tabent *mainpos_e = (upb_tabent*)hash(t, key);
upb_tabent *our_e = mainpos_e;
@ -145,7 +153,7 @@ static bool rm(upb_table *t, upb_tabkey key, upb_value *val,
// Element to remove is at the head of its chain.
t->count--;
if (val) {
_upb_value_setval(val, chain->val, t->type);
_upb_value_setval(val, chain->val, t->ctype);
}
if (chain->next) {
upb_tabent *move = (upb_tabent*)chain->next;
@ -164,7 +172,7 @@ static bool rm(upb_table *t, upb_tabkey key, upb_value *val,
if (chain->next) {
// Found element to remove.
if (val) {
_upb_value_setval(val, chain->next->val, t->type);
_upb_value_setval(val, chain->next->val, t->ctype);
}
upb_tabent *rm = (upb_tabent*)chain->next;
if (removed) *removed = rm->key;
@ -204,8 +212,8 @@ static bool streql(upb_tabkey k1, upb_tabkey k2) {
return strcmp(k1.str, k2.str) == 0;
}
bool upb_strtable_init(upb_strtable *t, upb_ctype_t type) {
return init(&t->t, type, 2);
bool upb_strtable_init(upb_strtable *t, upb_ctype_t ctype) {
return init(&t->t, ctype, 2);
}
void upb_strtable_uninit(upb_strtable *t) {
@ -218,7 +226,7 @@ bool upb_strtable_insert(upb_strtable *t, const char *k, upb_value v) {
if (isfull(&t->t)) {
// Need to resize. New table of double the size, add old elements to it.
upb_strtable new_table;
if (!init(&new_table.t, t->t.type, t->t.size_lg2 + 1))
if (!init(&new_table.t, t->t.ctype, t->t.size_lg2 + 1))
return false;
upb_strtable_iter i;
upb_strtable_begin(&i, t);
@ -267,6 +275,21 @@ static bool inteql(upb_tabkey k1, upb_tabkey k2) {
return k1.num == k2.num;
}
static _upb_value *inttable_val(upb_inttable *t, uintptr_t key) {
if (key < t->array_size) {
return upb_arrhas(t->array[key]) ? (_upb_value*)&t->array[key] : NULL;
} else {
upb_tabent *e =
(upb_tabent*)findentry(&t->t, upb_intkey(key), &upb_inthash, &inteql);
return e ? &e->val : NULL;
}
}
static const _upb_value *inttable_val_const(const upb_inttable *t,
uintptr_t key) {
return inttable_val((upb_inttable*)t, key);
}
size_t upb_inttable_count(const upb_inttable *t) {
return t->t.count + t->array_count;
}
@ -285,9 +308,9 @@ static void check(upb_inttable *t) {
#endif
}
bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t type,
bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t ctype,
size_t asize, int hsize_lg2) {
if (!init(&t->t, type, hsize_lg2)) return false;
if (!init(&t->t, ctype, hsize_lg2)) return false;
// Always make the array part at least 1 long, so that we know key 0
// won't be in the hash part, which simplifies things.
t->array_size = UPB_MAX(1, asize);
@ -303,8 +326,8 @@ bool upb_inttable_sizedinit(upb_inttable *t, upb_ctype_t type,
return true;
}
bool upb_inttable_init(upb_inttable *t, upb_ctype_t type) {
return upb_inttable_sizedinit(t, type, 0, 4);
bool upb_inttable_init(upb_inttable *t, upb_ctype_t ctype) {
return upb_inttable_sizedinit(t, ctype, 0, 4);
}
void upb_inttable_uninit(upb_inttable *t) {
@ -322,12 +345,12 @@ bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val) {
if (isfull(&t->t)) {
// Need to resize the hash part, but we re-use the array part.
upb_table new_table;
if (!init(&new_table, t->t.type, t->t.size_lg2 + 1))
if (!init(&new_table, t->t.ctype, t->t.size_lg2 + 1))
return false;
const upb_tabent *e;
for (e = begin(&t->t); e; e = next(&t->t, e)) {
upb_value v;
_upb_value_setval(&v, e->val, t->t.type);
_upb_value_setval(&v, e->val, t->t.ctype);
insert(&new_table, e->key, v, &upb_inthash, &inteql);
}
@ -343,15 +366,17 @@ bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val) {
}
bool upb_inttable_lookup(const upb_inttable *t, uintptr_t key, upb_value *v) {
if (key < t->array_size) {
bool ret = upb_arrhas(t->array[key]);
if (ret && v) {
_upb_value_setval(v, t->array[key], t->t.type);
}
return ret;
} else {
return lookup(&t->t, upb_intkey(key), v, &upb_inthash, &inteql);
}
const _upb_value *table_v = inttable_val_const(t, key);
if (!table_v) return false;
if (v) _upb_value_setval(v, *table_v, t->t.ctype);
return true;
}
bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val) {
_upb_value *table_v = inttable_val(t, key);
if (!table_v) return false;
*table_v = val.val;
return true;
}
bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) {
@ -360,7 +385,7 @@ bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) {
if (upb_arrhas(t->array[key])) {
t->array_count--;
if (val) {
_upb_value_setval(val, t->array[key], t->t.type);
_upb_value_setval(val, t->array[key], t->t.ctype);
}
((upb_value*)t->array)[key] = upb_value_uint64(-1);
success = true;
@ -400,31 +425,58 @@ bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val) {
}
void upb_inttable_compact(upb_inttable *t) {
// Find the largest power of two that satisfies the MIN_DENSITY definition.
// Create a power-of-two histogram of the table keys.
int counts[UPB_MAXARRSIZE + 1] = {0};
uintptr_t max_key = 0;
upb_inttable_iter i;
for (upb_inttable_begin(&i, t); !upb_inttable_done(&i); upb_inttable_next(&i))
counts[upb_log2(upb_inttable_iter_key(&i))]++;
// Int part must always be at least 1 entry large to catch lookups of key 0.
// Key 0 must always be in the array part because "0" in the hash part
// denotes an empty entry.
int count = UPB_MAX(upb_inttable_count(t), 1);
int size;
for (size = UPB_MAXARRSIZE; size > 1; size--) {
count -= counts[size];
if (count >= (1 << size) * MIN_DENSITY) break;
upb_inttable_begin(&i, t);
for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
uintptr_t key = upb_inttable_iter_key(&i);
if (key > max_key) {
max_key = key;
}
counts[log2ceil(key)]++;
}
int arr_size;
int arr_count = upb_inttable_count(t);
if (upb_inttable_count(t) >= max_key * MIN_DENSITY) {
// We can put 100% of the entries in the array part.
arr_size = max_key + 1;
} else {
// Find the largest power of two that satisfies the MIN_DENSITY definition.
for (int size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 1; size_lg2--) {
arr_size = 1 << size_lg2;
arr_count -= counts[size_lg2];
if (arr_count >= arr_size * MIN_DENSITY) {
break;
}
}
}
// Array part must always be at least 1 entry large to catch lookups of key
// 0. Key 0 must always be in the array part because "0" in the hash part
// denotes an empty entry.
arr_size = UPB_MAX(arr_size, 1);
// Insert all elements into new, perfectly-sized table.
upb_inttable new_table;
int hashsize = (upb_inttable_count(t) - count + 1) / MAX_LOAD;
int hash_count = upb_inttable_count(t) - arr_count;
int hash_size = hash_count ? (hash_count / MAX_LOAD) + 1 : 0;
int hashsize_lg2 = log2ceil(hash_size);
assert(hash_count >= 0);
upb_inttable_sizedinit(&new_table, t->t.type, size, upb_log2(hashsize));
for (upb_inttable_begin(&i, t); !upb_inttable_done(&i); upb_inttable_next(&i))
upb_inttable_insert(
&new_table, upb_inttable_iter_key(&i), upb_inttable_iter_value(&i));
upb_inttable new_t;
upb_inttable_sizedinit(&new_t, t->t.ctype, arr_size, hashsize_lg2);
upb_inttable_begin(&i, t);
for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
uintptr_t k = upb_inttable_iter_key(&i);
upb_inttable_insert(&new_t, k, upb_inttable_iter_value(&i));
}
assert(new_t.array_size == arr_size);
assert(new_t.t.size_lg2 == hashsize_lg2);
upb_inttable_uninit(t);
*t = new_table;
*t = new_t;
}
void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) {

@ -4,6 +4,7 @@
* Copyright (c) 2009 Google Inc. See LICENSE for details.
* Author: Josh Haberman <jhaberman@gmail.com>
*
* This header is INTERNAL-ONLY! Its interfaces are not public or stable!
* This file defines very fast int->upb_value (inttable) and string->upb_value
* (strtable) hash tables.
*
@ -15,24 +16,132 @@
* store pointers or integers of at least 32 bits (upb isn't really useful on
* systems where sizeof(void*) < 4).
*
* This header is internal to upb; its interface should not be considered
* public or stable.
*
* The table must be homogenous (all values of the same type). We currently
* enforce this on insert but store the full upb_value (with type) anyway.
* This is required with the current interface because lookups vend a pointer
* to the table's internal storage.
* The table must be homogenous (all values of the same type). In debug
* mode, we check this on insert and lookup.
*/
#ifndef UPB_TABLE_H_
#define UPB_TABLE_H_
#include <assert.h>
#include <stdint.h>
#include "upb.h"
#ifdef __cplusplus
extern "C" {
#endif
/* upb_value ******************************************************************/
// A tagged union (stored untagged inside the table) so that we can check that
// clients calling table accessors are correctly typed without having to have
// an explosion of accessors.
typedef enum {
UPB_CTYPE_INT32 = 1,
UPB_CTYPE_INT64 = 2,
UPB_CTYPE_UINT32 = 3,
UPB_CTYPE_UINT64 = 4,
UPB_CTYPE_BOOL = 5,
UPB_CTYPE_CSTR = 6,
UPB_CTYPE_PTR = 7,
} upb_ctype_t;
typedef union {
int32_t int32;
int64_t int64;
uint64_t uint64;
uint32_t uint32;
bool _bool;
char *cstr;
void *ptr;
const void *constptr;
} _upb_value;
typedef struct {
_upb_value val;
#ifndef NDEBUG
// In debug mode we carry the value type around also so we can check accesses
// to be sure the right member is being read.
upb_ctype_t ctype;
#endif
} upb_value;
#ifdef UPB_C99
#define UPB_VALUE_INIT(v, member) {.member = v}
#endif
#define UPB__VALUE_INIT_NONE UPB_VALUE_INIT(NULL, ptr)
#ifdef NDEBUG
#define SET_TYPE(dest, val) UPB_UNUSED(val)
#define UPB_VALUE_INIT_NONE {UPB__VALUE_INIT_NONE}
#else
#define SET_TYPE(dest, val) dest = val
// Non-existent type, all reads will fail.
#define UPB_VALUE_INIT_NONE {UPB__VALUE_INIT_NONE, -1}
#endif
#define UPB_VALUE_INIT_INT32(v) UPB_VALUE_INIT(v, int32)
#define UPB_VALUE_INIT_INT64(v) UPB_VALUE_INIT(v, int64)
#define UPB_VALUE_INIT_UINT32(v) UPB_VALUE_INIT(v, uint32)
#define UPB_VALUE_INIT_UINT64(v) UPB_VALUE_INIT(v, uint64)
#define UPB_VALUE_INIT_BOOL(v) UPB_VALUE_INIT(v, _bool)
#define UPB_VALUE_INIT_CSTR(v) UPB_VALUE_INIT(v, cstr)
#define UPB_VALUE_INIT_PTR(v) UPB_VALUE_INIT(v, ptr)
#define UPB_VALUE_INIT_CONSTPTR(v) UPB_VALUE_INIT(v, constptr)
// Like strdup(), which isn't always available since it's not ANSI C.
char *upb_strdup(const char *s);
UPB_INLINE void _upb_value_setval(upb_value *v, _upb_value val,
upb_ctype_t ctype) {
v->val = val;
SET_TYPE(v->ctype, ctype);
}
UPB_INLINE upb_value _upb_value_val(_upb_value val, upb_ctype_t ctype) {
upb_value ret;
_upb_value_setval(&ret, val, ctype);
return ret;
}
// For each value ctype, define the following set of functions:
//
// // Get/set an int32 from a upb_value.
// int32_t upb_value_getint32(upb_value val);
// void upb_value_setint32(upb_value *val, int32_t cval);
//
// // Construct a new upb_value from an int32.
// upb_value upb_value_int32(int32_t val);
#define FUNCS(name, membername, type_t, proto_type) \
UPB_INLINE void upb_value_set ## name(upb_value *val, type_t cval) { \
val->val.uint64 = 0; \
SET_TYPE(val->ctype, proto_type); \
val->val.membername = cval; \
} \
UPB_INLINE upb_value upb_value_ ## name(type_t val) { \
upb_value ret; \
upb_value_set ## name(&ret, val); \
return ret; \
} \
UPB_INLINE type_t upb_value_get ## name(upb_value val) { \
assert(val.ctype == proto_type); \
return val.val.membername; \
}
FUNCS(int32, int32, int32_t, UPB_CTYPE_INT32);
FUNCS(int64, int64, int64_t, UPB_CTYPE_INT64);
FUNCS(uint32, uint32, uint32_t, UPB_CTYPE_UINT32);
FUNCS(uint64, uint64, uint64_t, UPB_CTYPE_UINT64);
FUNCS(bool, _bool, bool, UPB_CTYPE_BOOL);
FUNCS(cstr, cstr, char*, UPB_CTYPE_CSTR);
FUNCS(ptr, ptr, void*, UPB_CTYPE_PTR);
#undef FUNCS
/* upb_table ******************************************************************/
typedef union {
uintptr_t num;
const char *str; // We own, nullz.
@ -58,7 +167,7 @@ typedef struct _upb_tabent {
typedef struct {
size_t count; // Number of entries in the hash part.
size_t mask; // Mask to turn hash value -> bucket.
upb_ctype_t type; // Type of all values.
upb_ctype_t ctype; // Type of all values.
uint8_t size_lg2; // Size of the hash table part is 2^size_lg2 entries.
const upb_tabent *entries; // Hash table.
} upb_table;
@ -67,8 +176,8 @@ typedef struct {
upb_table t;
} upb_strtable;
#define UPB_STRTABLE_INIT(count, mask, type, size_lg2, entries) \
{{count, mask, type, size_lg2, entries}}
#define UPB_STRTABLE_INIT(count, mask, ctype, size_lg2, entries) \
{{count, mask, ctype, size_lg2, entries}}
typedef struct {
upb_table t; // For entries that don't fit in the array part.
@ -77,11 +186,11 @@ typedef struct {
size_t array_count; // Array part number of elements.
} upb_inttable;
#define UPB_INTTABLE_INIT(count, mask, type, size_lg2, ent, a, asize, acount) \
{{count, mask, type, size_lg2, ent}, a, asize, acount}
#define UPB_INTTABLE_INIT(count, mask, ctype, size_lg2, ent, a, asize, acount) \
{{count, mask, ctype, size_lg2, ent}, a, asize, acount}
#define UPB_EMPTY_INTTABLE_INIT(type) \
UPB_INTTABLE_INIT(0, 0, type, 0, NULL, NULL, 0, 0)
#define UPB_EMPTY_INTTABLE_INIT(ctype) \
UPB_INTTABLE_INIT(0, 0, ctype, 0, NULL, NULL, 0, 0)
#define UPB_ARRAY_EMPTYENT UPB_VALUE_INIT_INT64(-1)
@ -113,8 +222,8 @@ uint32_t MurmurHash2(const void *key, size_t len, uint32_t seed);
// Initialize and uninitialize a table, respectively. If memory allocation
// failed, false is returned that the table is uninitialized.
bool upb_inttable_init(upb_inttable *table, upb_ctype_t type);
bool upb_strtable_init(upb_strtable *table, upb_ctype_t type);
bool upb_inttable_init(upb_inttable *table, upb_ctype_t ctype);
bool upb_strtable_init(upb_strtable *table, upb_ctype_t ctype);
void upb_inttable_uninit(upb_inttable *table);
void upb_strtable_uninit(upb_strtable *table);
@ -145,6 +254,11 @@ bool upb_strtable_lookup(const upb_strtable *t, const char *key, upb_value *v);
bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val);
bool upb_strtable_remove(upb_strtable *t, const char *key, upb_value *val);
// Updates an existing entry in an inttable. If the entry does not exist,
// returns false and does nothing. Unlike insert/remove, this does not
// invalidate iterators.
bool upb_inttable_replace(upb_inttable *t, uintptr_t key, upb_value val);
// Handy routines for treating an inttable like a stack. May not be mixed with
// other insert/remove calls.
bool upb_inttable_push(upb_inttable *t, upb_value val);
@ -168,7 +282,7 @@ UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key,
if (key < t->array_size) {
_upb_value arrval = t->array[key];
if (upb_arrhas(arrval)) {
_upb_value_setval(v, arrval, t->t.type);
_upb_value_setval(v, arrval, t->t.ctype);
return true;
} else {
return false;
@ -178,7 +292,7 @@ UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key,
if (t->t.entries == NULL) return NULL;
for (e = upb_inthash(&t->t, upb_intkey(key)); true; e = e->next) {
if ((uint32_t)e->key.num == key) {
_upb_value_setval(v, e->val, t->t.type);
_upb_value_setval(v, e->val, t->t.ctype);
return true;
}
if (e->next == NULL) return false;
@ -209,7 +323,18 @@ UPB_INLINE const char *upb_strtable_iter_key(upb_strtable_iter *i) {
return i->e->key.str;
}
UPB_INLINE upb_value upb_strtable_iter_value(upb_strtable_iter *i) {
return _upb_value_val(i->e->val, i->t->t.type);
return _upb_value_val(i->e->val, i->t->t.ctype);
}
UPB_INLINE void upb_strtable_iter_copy(upb_strtable_iter *to,
const upb_strtable_iter *from) {
*to = *from;
}
UPB_INLINE void upb_strtable_iter_setdone(upb_strtable_iter *i) {
i->e = NULL;
}
UPB_INLINE bool upb_strtable_iter_isequal(const upb_strtable_iter *i1,
const upb_strtable_iter *i2) {
return i1->e == i2->e;
}
@ -235,15 +360,26 @@ typedef struct {
void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t);
void upb_inttable_next(upb_inttable_iter *i);
UPB_INLINE bool upb_inttable_done(upb_inttable_iter *i) {
UPB_INLINE bool upb_inttable_done(const upb_inttable_iter *i) {
return i->ptr.ent == NULL;
}
UPB_INLINE uintptr_t upb_inttable_iter_key(upb_inttable_iter *i) {
UPB_INLINE uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) {
return i->array_part ? i->arrkey : i->ptr.ent->key.num;
}
UPB_INLINE upb_value upb_inttable_iter_value(upb_inttable_iter *i) {
UPB_INLINE upb_value upb_inttable_iter_value(const upb_inttable_iter *i) {
return _upb_value_val(
i->array_part ? *i->ptr.val : i->ptr.ent->val, i->t->t.type);
i->array_part ? *i->ptr.val : i->ptr.ent->val, i->t->t.ctype);
}
UPB_INLINE void upb_inttable_iter_copy(upb_inttable_iter *to,
const upb_inttable_iter *from) {
*to = *from;
}
UPB_INLINE void upb_inttable_iter_setdone(upb_inttable_iter *i) {
i->ptr.ent = NULL;
}
UPB_INLINE bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
const upb_inttable_iter *i2) {
return i1->ptr.ent == i2->ptr.ent;
}
#ifdef __cplusplus

@ -8,16 +8,41 @@
#include <errno.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "upb/upb.h"
#ifdef NDEBUG
upb_value UPB_NO_VALUE = {{0}};
#else
upb_value UPB_NO_VALUE = {{0}, -1};
#endif
// Like vasprintf (which allocates a string large enough for the result), but
// uses *buf (which can be NULL) as a starting point and reallocates it only if
// the new value will not fit. "size" is updated to reflect the allocated size
// of the buffer. Starts writing at the given offset into the string; bytes
// preceding this offset are unaffected. Returns the new length of the string,
// or -1 on memory allocation failure.
static int upb_vrprintf(char **buf, size_t *size, size_t ofs,
const char *fmt, va_list args) {
// Try once without reallocating. We have to va_copy because we might have
// to call vsnprintf again.
uint32_t len = *size - ofs;
va_list args_copy;
va_copy(args_copy, args);
uint32_t true_len = vsnprintf(*buf + ofs, len, fmt, args_copy);
va_end(args_copy);
// Resize to be the correct size.
if (true_len >= len) {
// Need to print again, because some characters were truncated. vsnprintf
// will not write the entire string unless you give it space to store the
// NULL terminator also.
*size = (ofs + true_len + 1);
char *newbuf = realloc(*buf, *size);
if (!newbuf) return -1;
vsnprintf(newbuf + ofs, true_len + 1, fmt, args);
*buf = newbuf;
}
return true_len;
}
void upb_status_init(upb_status *status) {
status->buf = NULL;
@ -104,27 +129,3 @@ void upb_status_seteof(upb_status *status) {
if (!status) return;
status->eof_ = true;
}
int upb_vrprintf(char **buf, size_t *size, size_t ofs,
const char *fmt, va_list args) {
// Try once without reallocating. We have to va_copy because we might have
// to call vsnprintf again.
uint32_t len = *size - ofs;
va_list args_copy;
va_copy(args_copy, args);
uint32_t true_len = vsnprintf(*buf + ofs, len, fmt, args_copy);
va_end(args_copy);
// Resize to be the correct size.
if (true_len >= len) {
// Need to print again, because some characters were truncated. vsnprintf
// will not write the entire string unless you give it space to store the
// NULL terminator also.
*size = (ofs + true_len + 1);
char *newbuf = realloc(*buf, *size);
if (!newbuf) return -1;
vsnprintf(newbuf + ofs, true_len + 1, fmt, args);
*buf = newbuf;
}
return true_len;
}

@ -13,16 +13,8 @@
#ifndef UPB_H_
#define UPB_H_
#include <assert.h>
#include <limits.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
// inline if possible, emit standalone code if required.
#ifdef __cplusplus
@ -54,108 +46,15 @@ extern "C" {
void operator=(const class_name&);
#endif
#if defined(__clang__) && defined(LANG_CXX11) && defined(__has_warning)
#if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough")
#define UPB_FALLTHROUGH_INTENDED [[clang::fallthrough]]
#endif
#endif
#ifndef UPB_FALLTHROUGH_INTENDED
#define UPB_FALLTHROUGH_INTENDED do { } while (0)
#endif
#ifdef __GNUC__
#define UPB_NORETURN __attribute__((__noreturn__))
#else
#define UPB_NORETURN
#endif
// Type detection and typedefs for integer types.
// For platforms where there are multiple 32-bit or 64-bit types, we need to be
// able to enumerate them so we can properly create overloads for all variants.
//
// If any platform existed where there were three integer types with the same
// size, this would have to become more complicated. For example, short, int,
// and long could all be 32-bits. Even more diabolically, short, int, long,
// and long long could all be 64 bits and still be standard-compliant.
// However, few platforms are this strange, and it's unlikely that upb will be
// used on the strangest ones.
// Can't count on stdint.h limits like INT32_MAX, because in C++ these are
// only defined when __STDC_LIMIT_MACROS are defined before the *first* include
// of stdint.h. We can't guarantee that someone else didn't include these first
// without defining __STDC_LIMIT_MACROS.
#define UPB_INT32_MAX 0x7fffffffLL
#define UPB_INT32_MIN (-UPB_INT32_MAX - 1)
#define UPB_INT64_MAX 0x7fffffffffffffffLL
#define UPB_INT64_MIN (-UPB_INT64_MAX - 1)
#if INT_MAX == UPB_INT32_MAX && INT_MIN == UPB_INT32_MIN
#define UPB_INT_IS_32BITS 1
#endif
#if LONG_MAX == UPB_INT32_MAX && LONG_MIN == UPB_INT32_MIN
#define UPB_LONG_IS_32BITS 1
#endif
#if LONG_MAX == UPB_INT64_MAX && LONG_MIN == UPB_INT64_MIN
#define UPB_LONG_IS_64BITS 1
#endif
#if LLONG_MAX == UPB_INT64_MAX && LLONG_MIN == UPB_INT64_MIN
#define UPB_LLONG_IS_64BITS 1
#endif
#if UPB_INT_IS_32BITS
typedef int upb_int32_t;
typedef unsigned int upb_uint32_t;
#define UPB_INT32_CTYPE i
#if UPB_LONG_IS_32BITS
#define UPB_TWO_32BIT_TYPES 1
typedef long upb_int32alt_t;
typedef unsigned long upb_uint32alt_t;
#define UPB_INT32_CTYPE2 l
#endif // UPB_LONG_IS_32BITS
#elif UPB_LONG_IS_32BITS // && !UPB_INT_IS_32BITS
typedef long upb_int32_t;
typedef unsigned long upb_uint32_t;
#define UPB_INT32_CTYPE l
#endif // UPB_INT_IS_32BITS
#if UPB_LONG_IS_64BITS
typedef long upb_int64_t;
typedef unsigned long upb_uint64_t;
#define UPB_INT64_CTYPE l
#if UPB_LLONG_IS_64BITS
#define UPB_TWO_64BIT_TYPES 1
typedef long long upb_int64alt_t;
typedef unsigned long long upb_uint64alt_t;
#define UPB_INT64_CTYPE2 ll
#endif // UPB_LLONG_IS_64BITS
#elif UPB_LLONG_IS_64BITS // && !UPB_LONG_IS_64BITS
typedef long long upb_int64_t;
typedef unsigned long long upb_uint64_t;
#define UPB_INT64_CTYPE ll
#endif // UPB_LONG_IS_64BITS
#define UPB_MAX(x, y) ((x) > (y) ? (x) : (y))
#define UPB_MIN(x, y) ((x) < (y) ? (x) : (y))
// For our C-based inheritance, sometimes it's necessary to upcast an object to
// its base class. We try to minimize the need for this by replicating base
// class functions in the derived class -- the derived class functions simply
// forward to the base class implementations. This strategy simplifies the C++
// API since we can't use real C++ inheritance.
#define upb_upcast(obj) (&(obj)->base)
#define upb_upcast2(obj) upb_upcast(upb_upcast(obj))
char *upb_strdup(const char *s);
#define UPB_UNUSED(var) (void)var
// For asserting something about a variable when the variable is not used for
@ -163,42 +62,39 @@ char *upb_strdup(const char *s);
// debug mode.
#define UPB_ASSERT_VAR(var, predicate) UPB_UNUSED(var); assert(predicate)
#define UPB_ASSERT_STATUS(status) do { \
if (!upb_ok(status)) { \
fprintf(stderr, "upb status failure: %s\n", upb_status_getstr(status)); \
assert(upb_ok(status)); \
} \
} while (0)
// The maximum that any submessages can be nested. Matches proto2's limit.
// At the moment this specifies the size of several statically-sized arrays
// and therefore setting it high will cause more memory to be used. Will
// be replaced by a runtime-configurable limit and dynamically-resizing arrays.
// TODO: make this a runtime-settable property of upb_handlers.
#define UPB_MAX_NESTING 64
// Inherent limit of protobuf wire format and schema definition.
#define UPB_MAX_FIELDNUMBER ((1 << 29) - 1)
// Nested type names are separated by periods.
#define UPB_SYMBOL_SEPARATOR '.'
// The longest chain that mutually-recursive types are allowed to form. For
// example, this is a type cycle of length 2:
// message A {
// B b = 1;
// }
// message B {
// A a = 1;
// }
#define UPB_MAX_TYPE_CYCLE_LEN 16
// The maximum depth that the type graph can have. Note that this setting does
// not automatically constrain UPB_MAX_NESTING, because type cycles allow for
// unlimited nesting if we do not limit it. Many algorithms in upb call
// recursive functions that traverse the type graph, so we must limit this to
// avoid blowing the C stack.
#define UPB_MAX_TYPE_DEPTH 64
/* Casts **********************************************************************/
// Upcasts for C. For downcasts see the definitions of the subtypes.
#define UPB_UPCAST(obj) (&(obj)->base)
#define UPB_UPCAST2(obj) UPB_UPCAST(UPB_UPCAST(obj))
#ifdef __cplusplus
// Downcasts for C++. We can't use C++ inheritance directly and maintain
// compatibility with C. So our inheritance is undeclared in C++.
// Specializations of these casting functions are defined for appropriate type
// pairs, and perform the necessary checks.
//
// Example:
// upb::Def* def = <...>;
// upb::MessageDef* = upb::dyn_cast<upb::MessageDef*>(def);
//
// For upcasts, see the Upcast() method in the types themselves.
namespace upb {
// Casts to a direct subclass. The caller must know that cast is correct; an
// incorrect cast will throw an assertion failure.
template<class To, class From> To down_cast(From* f);
// Casts to a direct subclass. If the class does not actually match the given
// subtype, returns NULL.
template<class To, class From> To dyn_cast(From* f);
}
#endif
/* upb::Status ****************************************************************/
@ -260,6 +156,10 @@ struct upb_status {
#define UPB_STATUS_INIT {UPB_OK, false, 0, NULL, NULL, NULL, 0}
#ifdef __cplusplus
extern "C" {
#endif
void upb_status_init(upb_status *status);
void upb_status_uninit(upb_status *status);
@ -278,203 +178,11 @@ void upb_status_seteof(upb_status *status);
const char *upb_status_getstr(const upb_status *status);
void upb_status_copy(upb_status *to, const upb_status *from);
// Like vasprintf (which allocates a string large enough for the result), but
// uses *buf (which can be NULL) as a starting point and reallocates it only if
// the new value will not fit. "size" is updated to reflect the allocated size
// of the buffer. Starts writing at the given offset into the string; bytes
// preceding this offset are unaffected. Returns the new length of the string,
// or -1 on memory allocation failure.
int upb_vrprintf(char **buf, size_t *size, size_t ofs,
const char *fmt, va_list args);
/* upb::Value *****************************************************************/
// TODO(haberman): upb::Value is gross and should be retired from the public
// interface (we *may* still want to keep it for internal use). upb::Handlers
// and upb::Def should replace their use of Value with one function for each C
// type.
// Clients should not need to access these enum values; they are used internally
// to do typechecks of upb_value accesses.
typedef enum {
UPB_CTYPE_INT32 = 1,
UPB_CTYPE_INT64 = 2,
UPB_CTYPE_UINT32 = 3,
UPB_CTYPE_UINT64 = 4,
UPB_CTYPE_DOUBLE = 5,
UPB_CTYPE_FLOAT = 6,
UPB_CTYPE_BOOL = 7,
UPB_CTYPE_CSTR = 8,
UPB_CTYPE_PTR = 9,
UPB_CTYPE_BYTEREGION = 10,
UPB_CTYPE_FIELDDEF = 11,
} upb_ctype_t;
typedef union {
uint64_t uint64;
int32_t int32;
int64_t int64;
uint32_t uint32;
double _double;
float _float;
bool _bool;
char *cstr;
void *ptr;
const void *constptr;
} _upb_value;
// A single .proto value. The owner must have an out-of-band way of knowing
// the type, so that it knows which union member to use.
typedef struct {
_upb_value val;
#ifndef NDEBUG
// In debug mode we carry the value type around also so we can check accesses
// to be sure the right member is being read.
upb_ctype_t type;
#endif
} upb_value;
#ifdef UPB_C99
#define UPB_VALUE_INIT(v, member) {.member = v}
#endif
// TODO(haberman): C++
//
//
#define UPB__VALUE_INIT_NONE UPB_VALUE_INIT(NULL, ptr)
#ifdef NDEBUG
#define SET_TYPE(dest, val) UPB_UNUSED(val)
#define UPB_VALUE_INIT_NONE {UPB__VALUE_INIT_NONE}
#else
#define SET_TYPE(dest, val) dest = val
// Non-existent type, all reads will fail.
#define UPB_VALUE_INIT_NONE {UPB__VALUE_INIT_NONE, -1}
#endif
#define UPB_VALUE_INIT_INT32(v) UPB_VALUE_INIT(v, int32)
#define UPB_VALUE_INIT_INT64(v) UPB_VALUE_INIT(v, int64)
#define UPB_VALUE_INIT_UINT32(v) UPB_VALUE_INIT(v, uint32)
#define UPB_VALUE_INIT_UINT64(v) UPB_VALUE_INIT(v, uint64)
#define UPB_VALUE_INIT_DOUBLE(v) UPB_VALUE_INIT(v, _double)
#define UPB_VALUE_INIT_FLOAT(v) UPB_VALUE_INIT(v, _float)
#define UPB_VALUE_INIT_BOOL(v) UPB_VALUE_INIT(v, _bool)
#define UPB_VALUE_INIT_CSTR(v) UPB_VALUE_INIT(v, cstr)
#define UPB_VALUE_INIT_PTR(v) UPB_VALUE_INIT(v, ptr)
#define UPB_VALUE_INIT_CONSTPTR(v) UPB_VALUE_INIT(v, constptr)
UPB_INLINE void _upb_value_setval(upb_value *v, _upb_value val,
upb_ctype_t type) {
v->val = val;
SET_TYPE(v->type, type);
}
UPB_INLINE upb_value _upb_value_val(_upb_value val, upb_ctype_t type) {
upb_value ret;
_upb_value_setval(&ret, val, type);
return ret;
}
// For each value type, define the following set of functions:
//
// // Get/set an int32 from a upb_value.
// int32_t upb_value_getint32(upb_value val);
// void upb_value_setint32(upb_value *val, int32_t cval);
//
// // Construct a new upb_value from an int32.
// upb_value upb_value_int32(int32_t val);
#define WRITERS(name, membername, ctype, proto_type) \
UPB_INLINE void upb_value_set ## name(upb_value *val, ctype cval) { \
val->val.uint64 = 0; \
SET_TYPE(val->type, proto_type); \
val->val.membername = cval; \
} \
UPB_INLINE upb_value upb_value_ ## name(ctype val) { \
upb_value ret; \
upb_value_set ## name(&ret, val); \
return ret; \
}
#define ALL(name, membername, ctype, proto_type) \
/* Can't reuse WRITERS() here unfortunately because "bool" is a macro \
* that expands to _Bool, so it ends up defining eg. upb_value_set_Bool */ \
UPB_INLINE void upb_value_set ## name(upb_value *val, ctype cval) { \
val->val.uint64 = 0; \
SET_TYPE(val->type, proto_type); \
val->val.membername = cval; \
} \
UPB_INLINE upb_value upb_value_ ## name(ctype val) { \
upb_value ret; \
upb_value_set ## name(&ret, val); \
return ret; \
} \
UPB_INLINE ctype upb_value_get ## name(upb_value val) { \
assert(val.type == proto_type); \
return val.val.membername; \
}
ALL(int32, int32, int32_t, UPB_CTYPE_INT32);
ALL(int64, int64, int64_t, UPB_CTYPE_INT64);
ALL(uint32, uint32, uint32_t, UPB_CTYPE_UINT32);
ALL(uint64, uint64, uint64_t, UPB_CTYPE_UINT64);
ALL(bool, _bool, bool, UPB_CTYPE_BOOL);
ALL(cstr, cstr, char*, UPB_CTYPE_CSTR);
ALL(ptr, ptr, void*, UPB_CTYPE_PTR);
#ifdef __KERNEL__
// Linux kernel modules are compiled without SSE and therefore are incapable
// of compiling functions that return floating-point values, so we define as
// macros instead and lose the type check.
WRITERS(double, _double, double, UPB_CTYPE_DOUBLE);
WRITERS(float, _float, float, UPB_CTYPE_FLOAT);
#define upb_value_getdouble(v) (v.val._double)
#define upb_value_getfloat(v) (v.val._float)
#else
ALL(double, _double, double, UPB_CTYPE_DOUBLE);
ALL(float, _float, float, UPB_CTYPE_FLOAT);
#endif /* __KERNEL__ */
#undef WRITERS
#undef ALL
extern upb_value UPB_NO_VALUE;
#ifdef __cplusplus
} // extern "C"
namespace upb {
typedef upb_value Value;
template <typename T> T GetValue(Value v);
template <typename T> Value MakeValue(T v);
#define UPB_VALUE_ACCESSORS(type, ctype) \
template <> inline ctype GetValue<ctype>(Value v) { \
return upb_value_get ## type(v); \
} \
template <> inline Value MakeValue<ctype>(ctype v) { \
return upb_value_ ## type(v); \
}
UPB_VALUE_ACCESSORS(double, double);
UPB_VALUE_ACCESSORS(float, float);
UPB_VALUE_ACCESSORS(int32, int32_t);
UPB_VALUE_ACCESSORS(int64, int64_t);
UPB_VALUE_ACCESSORS(uint32, uint32_t);
UPB_VALUE_ACCESSORS(uint64, uint64_t);
UPB_VALUE_ACCESSORS(bool, bool);
#undef UPB_VALUE_ACCESSORS
template <typename T> inline T* GetPtrValue(Value v) {
return static_cast<T*>(upb_value_getptr(v));
}
template <typename T> inline Value MakePtrValue(T* v) {
return upb_value_ptr(static_cast<void*>(v));
}
// C++ Wrappers
inline Status::Status() { upb_status_init(this); }
inline Status::~Status() { upb_status_uninit(this); }

Loading…
Cancel
Save