From b79fd65a83e6563393807efbc44be3e2bdb16537 Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Tue, 11 Sep 2018 10:59:08 -0700 Subject: WIP. --- upb/bindings/lua/def.c | 64 ++++--------- upb/bindings/lua/upb/table.c | 211 ----------------------------------------- upb/bindings/lua/upb/table.lua | 3 - 3 files changed, 16 insertions(+), 262 deletions(-) delete mode 100644 upb/bindings/lua/upb/table.c delete mode 100644 upb/bindings/lua/upb/table.lua (limited to 'upb/bindings') diff --git a/upb/bindings/lua/def.c b/upb/bindings/lua/def.c index 194acc3..7b3f612 100644 --- a/upb/bindings/lua/def.c +++ b/upb/bindings/lua/def.c @@ -6,7 +6,6 @@ #include "lauxlib.h" #include "upb/bindings/lua/upb.h" #include "upb/def.h" -#include "upb/pb/glue.h" #define LUPB_ENUMDEF "lupb.enumdef" #define LUPB_FIELDDEF "lupb.fielddef" @@ -1196,37 +1195,27 @@ static int lupb_symtab_gc(lua_State *L) { } static int lupb_symtab_add(lua_State *L) { + size_t len; upb_symtab *s = lupb_symtab_check(L, 1); - int n; - upb_def **defs; - - luaL_checktype(L, 2, LUA_TTABLE); - /* Iterate over table twice. First iteration to count entries and - * check constraints. */ - n = 0; - for (lua_pushnil(L); lua_next(L, 2); lua_pop(L, 1)) { - lupb_def_checkmutable(L, -1); - ++n; - } + const char *str = luaL_checklstring(L, 2, &len); + google_protobuf_FileDescriptorSet *set = + google_protobuf_FileDescriptorSet_parsenew(upb_stringview_make(str, len), + upb_symtab_arena(s)); + size_t i; + upb_array *file_arr; - /* Second iteration to build deflist. - * Allocate list with lua_newuserdata() so it is anchored as a GC root in - * case any Lua functions longjmp(). */ - defs = lua_newuserdata(L, n * sizeof(*defs)); - n = 0; - for (lua_pushnil(L); lua_next(L, 2); lua_pop(L, 1)) { - upb_def *def = lupb_def_checkmutable(L, -1); - defs[n++] = def; + if (!set) { + luaL_argerror(L, 2, "failed to parse descriptor"); } - CHK(upb_symtab_add(s, defs, n, NULL, &status)); - return 0; -} + file_arr = (upb_array*)google_protobuf_FileDescriptorSet_file(set); + for (i = 0; i < upb_array_size(file_arr); i++) { + upb_msgval entry = upb_array_get(file_arr, i); + google_protobuf_FileDescriptorProto *file = + (void *)upb_msgval_getmsg(entry); + CHK(upb_symtab_addfile(s, file, &status)); + } -static int lupb_symtab_addfile(lua_State *L) { - upb_symtab *s = lupb_symtab_check(L, 1); - upb_filedef *f = lupb_filedef_checkmutable(L, 2); - CHK(upb_symtab_addfile(s, f, &status)); return 0; } @@ -1262,7 +1251,6 @@ static int lupb_symtab_defs(lua_State *L) { static const struct luaL_Reg lupb_symtab_m[] = { {"add", lupb_symtab_add}, - {"add_file", lupb_symtab_addfile}, {"defs", lupb_symtab_defs}, {"lookup", lupb_symtab_lookup}, {NULL, NULL} @@ -1290,25 +1278,6 @@ static int lupb_freeze(lua_State *L) { return 0; } -/* This is a *temporary* API that will be removed once pending refactorings are - * complete (it does not belong here in core because it depends on both - * the descriptor.proto schema and the protobuf binary format. */ -static int lupb_loaddescriptor(lua_State *L) { - size_t len; - const char *str = luaL_checklstring(L, 1, &len); - size_t i; - upb_filedef **files = NULL; - CHK(files = upb_loaddescriptor(str, len, &files, &status)); - - lua_newtable(L); - for (i = 1; *files; i++, files++) { - lupb_filedef_pushnewrapper(L, *files, &files); - lua_rawseti(L, -2, i); - } - - return 1; -} - static void lupb_setfieldi(lua_State *L, const char *field, int i) { lua_pushinteger(L, i); lua_setfield(L, -2, field); @@ -1322,7 +1291,6 @@ static const struct luaL_Reg lupbdef_toplevel_m[] = { {"OneofDef", lupb_oneofdef_new}, {"SymbolTable", lupb_symtab_new}, {"freeze", lupb_freeze}, - {"load_descriptor", lupb_loaddescriptor}, {NULL, NULL} }; diff --git a/upb/bindings/lua/upb/table.c b/upb/bindings/lua/upb/table.c deleted file mode 100644 index 79120c7..0000000 --- a/upb/bindings/lua/upb/table.c +++ /dev/null @@ -1,211 +0,0 @@ -/* -** require("upb.table") -- a Lua extension for accessing upb_table -** -** This is an internal-only interface and exists for the sole purpose of -** writing a C code generator in Lua that can dump a upb_table as static C -** initializers. This lets us use Lua for convenient string manipulation while -** saving us from re-implementing the upb_table hash function and hash table -** layout / collision strategy in Lua. -** -** Since this is used only as part of the toolchain (and not part of the -** runtime) we do not hold this module to the same stringent requirements as -** the main Lua modules (for example that misbehaving Lua programs cannot -** crash the interpreter). -*/ - -#include -#include -#include -#include - -#include "lauxlib.h" -#include "upb/bindings/lua/upb.h" -#include "upb/def.h" -#include "upb/structdefs.int.h" -#include "upb/table.int.h" - -static void lupbtable_setnum(lua_State *L, int tab, const char *key, - lua_Number val) { - lua_pushnumber(L, val); - lua_setfield(L, tab - 1, key); -} - -static void lupbtable_pushval(lua_State *L, upb_tabval val, upb_ctype_t ctype) { - switch (ctype) { - case UPB_CTYPE_INT32: - lua_pushnumber(L, val.val); - break; - case UPB_CTYPE_PTR: - lupb_def_pushwrapper(L, (void*)val.val, NULL); - break; - case UPB_CTYPE_CSTR: - lua_pushstring(L, (const char*)val.val); - break; - default: - 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 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, ctype); - lua_setfield(L, -2, "valtype"); - - /* Set this to facilitate linking. */ - lua_pushlightuserdata(L, (void*)ptr); - lua_setfield(L, -2, "ptr"); -} - -static void lupbtable_pushent(lua_State *L, const upb_tabent *e, - bool inttab, int ctype) { - lua_newtable(L); - if (!upb_tabent_isempty(e)) { - if (inttab) { - lua_pushnumber(L, e->key); - } else { - uint32_t len; - const char *str = upb_tabstr(e->key, &len); - lua_pushlstring(L, str, len); - } - lua_setfield(L, -2, "key"); - 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, ctype, e); -} - -/* Dumps the shared part of upb_table into a Lua table. */ -static void lupbtable_pushtable(lua_State *L, const upb_table *t, bool inttab) { - size_t i; - - lua_newtable(L); - lupbtable_setnum(L, -1, "count", t->count); - lupbtable_setnum(L, -1, "mask", t->mask); - lupbtable_setnum(L, -1, "ctype", t->ctype); - lupbtable_setnum(L, -1, "size_lg2", t->size_lg2); - - lua_newtable(L); - for (i = 0; i < upb_table_size(t); i++) { - lupbtable_pushent(L, &t->entries[i], inttab, t->ctype); - lua_rawseti(L, -2, i + 1); - } - lua_setfield(L, -2, "entries"); -} - -/* Dumps a upb_inttable to a Lua table. */ -static void lupbtable_pushinttable(lua_State *L, const upb_inttable *t) { - size_t i; - - lupbtable_pushtable(L, &t->t, true); - lupbtable_setnum(L, -1, "array_size", t->array_size); - lupbtable_setnum(L, -1, "array_count", t->array_count); - - lua_newtable(L); - for (i = 0; i < t->array_size; i++) { - lua_newtable(L); - if (upb_arrhas(t->array[i])) { - lupbtable_pushval(L, t->array[i], t->t.ctype); - lua_setfield(L, -2, "val"); - } - lupbtable_setmetafields(L, t->t.ctype, &t->array[i]); - lua_rawseti(L, -2, i + 1); - } - lua_setfield(L, -2, "array"); -} - -static void lupbtable_pushstrtable(lua_State *L, const upb_strtable *t) { - lupbtable_pushtable(L, &t->t, false); -} - -static int lupbtable_msgdef_itof(lua_State *L) { - const upb_msgdef *m = lupb_msgdef_check(L, 1); - lupbtable_pushinttable(L, &m->itof); - return 1; -} - -static int lupbtable_msgdef_ntof(lua_State *L) { - const upb_msgdef *m = lupb_msgdef_check(L, 1); - lupbtable_pushstrtable(L, &m->ntof); - return 1; -} - -static int lupbtable_enumdef_iton(lua_State *L) { - const upb_enumdef *e = lupb_enumdef_check(L, 1); - lupbtable_pushinttable(L, &e->iton); - return 1; -} - -static int lupbtable_enumdef_ntoi(lua_State *L) { - const upb_enumdef *e = lupb_enumdef_check(L, 1); - lupbtable_pushstrtable(L, &e->ntoi); - return 1; -} - -static int lupbtable_symtab_symtab(lua_State *L) { - const upb_symtab *s = lupb_symtab_check(L, 1); - lupbtable_pushstrtable(L, &s->symtab); - return 1; -} - -static void lupbtable_setfieldi(lua_State *L, const char *field, int i) { - lua_pushnumber(L, i); - lua_setfield(L, -2, field); -} - -/* These aren't from the table, but they access other internal-only - * definitions. */ -static int lupb_fielddef_selectorbase(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - if (!upb_fielddef_isfrozen(f)) - luaL_error(L, "_selectorbase is only defined for frozen fielddefs"); - lua_pushinteger(L, f->selector_base); - return 1; -} - -static int lupb_msgdef_selectorcount(lua_State *L) { - const upb_msgdef *m = lupb_msgdef_check(L, 1); - lua_pushinteger(L, m->selector_count); - return 1; -} - -static int lupb_msgdef_submsgfieldcount(lua_State *L) { - const upb_msgdef *m = lupb_msgdef_check(L, 1); - lua_pushinteger(L, m->submsg_field_count); - return 1; -} - -static const struct luaL_Reg lupbtable_toplevel_m[] = { - {"msgdef_itof", lupbtable_msgdef_itof}, - {"msgdef_ntof", lupbtable_msgdef_ntof}, - {"enumdef_iton", lupbtable_enumdef_iton}, - {"enumdef_ntoi", lupbtable_enumdef_ntoi}, - {"symtab_symtab", lupbtable_symtab_symtab}, - - {"msgdef_selector_count", lupb_msgdef_selectorcount}, - {"msgdef_submsg_field_count", lupb_msgdef_submsgfieldcount}, - - {"fielddef_selector_base", lupb_fielddef_selectorbase}, - - {NULL, NULL} -}; - -int luaopen_upb_table_c(lua_State *L) { - static char module_key; - if (lupb_openlib(L, &module_key, "upb.table", lupbtable_toplevel_m)) { - return 1; - } - - /* 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); - lua_setfield(L, -2, "NULL"); - - return 1; /* Return a single Lua value, the package table created above. */ -} diff --git a/upb/bindings/lua/upb/table.lua b/upb/bindings/lua/upb/table.lua deleted file mode 100644 index ad8b066..0000000 --- a/upb/bindings/lua/upb/table.lua +++ /dev/null @@ -1,3 +0,0 @@ - -require "upb" -return require "upb.table_c" -- cgit v1.2.3 From 336402b4d7251d37239d2f7ff8259174525baa38 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Mon, 10 Dec 2018 10:18:48 -0800 Subject: WIP, core library compiles now. --- BUILD | 33 +-- CMakeLists.txt | 216 +------------- upb/bindings/lua/def.c | 780 ++++++------------------------------------------- upb/def.c | 722 ++++++++++++++++++++++++++------------------- upb/def.h | 13 +- upb/handlers.c | 4 +- upb/json/parser.c | 126 ++++---- upb/json/parser.h | 3 +- upb/json/parser.rl | 20 +- upb/json/printer.c | 2 +- upb/msg.h | 9 + upb/pb/textprinter.c | 4 +- upb/structdefs.int.h | 196 ------------- 13 files changed, 602 insertions(+), 1526 deletions(-) delete mode 100644 upb/structdefs.int.h (limited to 'upb/bindings') diff --git a/BUILD b/BUILD index 96418f1..df05e06 100644 --- a/BUILD +++ b/BUILD @@ -27,7 +27,6 @@ cc_library( "upb/port_undef.inc", "upb/refcounted.c", "upb/sink.c", - "upb/structdefs.int.h", "upb/structs.int.h", "upb/table.c", "upb/table.int.h", @@ -429,13 +428,6 @@ proto_library( ], ) -genrule( - name = "copy_google_descriptor_pb", - srcs = [":google_descriptor_proto"], - outs = ["generated/google/protobuf/descriptor.pb"], - cmd = "cp $< $@", -) - genrule( name = "generate_descriptor_c", srcs = ["google/protobuf/descriptor.proto"], @@ -462,16 +454,16 @@ genrule( cmd = "cp $< $@", ) -genrule( - name = "generated_json_test_proto_upbdefs", - srcs = ["generated/tests/json/test.proto.pb"], - outs = [ - "generated/tests/json/test.upbdefs.h", - "generated/tests/json/test.upbdefs.c", - ], - cmd = "UPBC=$$PWD/$(location :lua_upbc); INFILE=$$PWD/$<; cd $(GENDIR)/generated && $$UPBC --generate-upbdefs $$INFILE", - tools = [":lua_upbc"], -) +#genrule( +# name = "generated_json_test_proto_upbdefs", +# srcs = ["generated/tests/json/test.proto.pb"], +# outs = [ +# "generated/tests/json/test.upbdefs.h", +# "generated/tests/json/test.upbdefs.c", +# ], +# cmd = "UPBC=$$PWD/$(location :lua_upbc); INFILE=$$PWD/$<; cd $(GENDIR)/generated && $$UPBC --generate-upbdefs $$INFILE", +# tools = [":lua_upbc"], +#) genrule( name = "generate_json_ragel", @@ -488,11 +480,6 @@ generated_file_staleness_test( "google/protobuf/descriptor.upb.c", "google/protobuf/descriptor.upb.h", "tests/json/test.proto.pb", - "tests/json/test.upbdefs.c", - "tests/json/test.upbdefs.h", - "upb/descriptor/descriptor.pb", - "upb/descriptor/descriptor.upbdefs.c", - "upb/descriptor/descriptor.upbdefs.h", "upb/json/parser.c", "upb/pb/compile_decoder_x64.h", ], diff --git a/CMakeLists.txt b/CMakeLists.txt index 4fb3b53..26ac066 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,209 +57,6 @@ elseif(UNIX) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--build-id") endif() -<<<<<<< HEAD -FIND_PACKAGE(Lua) -if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/third_party/protobuf/Makefile.am") - set(PROTOBUF_FOUND TRUE) -endif() -find_program(RAGEL NAMES ragel) - -if(LUA_FOUND) - include_directories(${LUA_INCLUDE_DIR}) - - add_library(upb_c SHARED - upb/bindings/lua/upb.c - upb/bindings/lua/def.c - upb/bindings/lua/msg.c - ) - target_link_libraries(upb_c LINK_PRIVATE - upbpb_pic - upbdef_pic - upbhandlers_pic upb_pic ) - - add_library(pb_c SHARED - upb/bindings/lua/upb/pb.c - ) - target_link_libraries(pb_c LINK_PRIVATE upb_c upbpb_pic) - - set_target_properties(upb_c - PROPERTIES - LIBRARY_OUTPUT_DIRECTORY "upb/bindings/lua" - PREFIX "" - SUFFIX ".so") - set_target_properties(pb_c - PROPERTIES - LIBRARY_OUTPUT_DIRECTORY "upb/bindings/lua/upb" - PREFIX "" - SUFFIX ".so") - - add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/tools/upbc - DEPENDS ${CMAKE_SOURCE_DIR}/tools/upbc - ${CMAKE_SOURCE_DIR}/tools/upbc.lua - ${CMAKE_SOURCE_DIR}/tools/make_c_api.lua - ${CMAKE_SOURCE_DIR}/upb/bindings/lua/upb.lua - ${CMAKE_SOURCE_DIR}/upb/bindings/lua/upb/pb.lua - upb_c - pb_c - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_SOURCE_DIR}/tools/upbc - ${CMAKE_SOURCE_DIR}/tools/upbc.lua - ${CMAKE_SOURCE_DIR}/tools/make_c_api.lua - ${CMAKE_CURRENT_BINARY_DIR}/tools) - add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lua/upb.lua - DEPENDS ${CMAKE_SOURCE_DIR}/upb/bindings/lua/upb.lua - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_SOURCE_DIR}/upb/bindings/lua/upb.lua - ${CMAKE_CURRENT_BINARY_DIR}/upb/bindings/lua) - add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/lua/upb/pb.lua - DEPENDS ${CMAKE_SOURCE_DIR}/upb/bindings/lua/upb/pb.lua - COMMAND ${CMAKE_COMMAND} -E copy - ${CMAKE_SOURCE_DIR}/upb/bindings/lua/upb/pb.lua - ${CMAKE_CURRENT_BINARY_DIR}/upb/bindings/lua/upb) - - add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/upb/pb/compile_decoder_x64.h - DEPENDS upb/pb/compile_decoder_x64.dasc - COMMAND - cd ${CMAKE_CURRENT_SOURCE_DIR} && - lua third_party/dynasm/dynasm.lua - -c upb/pb/compile_decoder_x64.dasc - > ${CMAKE_CURRENT_BINARY_DIR}/upb/pb/compile_decoder_x64.h - ) - - add_custom_target( - genfiles2 ALL - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/upb/pb/compile_decoder_x64.h - ) - - add_test( - NAME testlua - COMMAND lua ${CMAKE_SOURCE_DIR}/tests/bindings/lua/test_upb.lua - ${CMAKE_SOURCE_DIR}/tests/bindings/lua/test_upb.pb.lua - ) - set_property(TEST testlua PROPERTY ENVIRONMENT - LUA_PATH=${CMAKE_SOURCE_DIR}/third_party/lunit/?.lua$${CMAKE_SOURCE_DIR}/upb/bindings/lua/?.lua - LUA_CPATH=${CMAKE_BINARY_DIR}/upb/bindings/lua/?.so - ) - set_tests_properties(testlua - PROPERTIES - DEPENDS "upb_c;pb_c" - ) - enable_testing() -endif() - -if(LUA_FOUND AND PROTOBUF_FOUND) - set(protobuf_BUILD_TESTS OFF CACHE BOOL "enable tests for proto2" FORCE) - set(protobuf_BUILD_SHARED_LIBS OFF CACHE BOOL "enable shared libs for proto2" FORCE) - set(protobuf_BUILD_CONFORMANCE ON CACHE BOOL "Build conformance tests" FORCE) - add_subdirectory(third_party/protobuf/cmake) - - add_custom_target( - upbc ALL - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/tools/make_c_api.lua - ${CMAKE_CURRENT_SOURCE_DIR}/tools/upbc.lua - ${CMAKE_CURRENT_BINARY_DIR}/tools/upbc - ${CMAKE_CURRENT_BINARY_DIR}/lua/upb.lua - ${CMAKE_CURRENT_BINARY_DIR}/lua/upb/pb.lua - ) - - add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/conformance.upb.h - ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/test_messages_proto3.upb.h - ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/test_messages_proto3.upb.c - ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/any.upb.c - ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/duration.upb.c - ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/field_mask.upb.c - ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/struct.upb.c - ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/timestamp.upb.c - ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/wrappers.upb.c - ${CMAKE_CURRENT_BINARY_DIR}/conformance.upb.c - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/tools/upbc - ${CMAKE_CURRENT_SOURCE_DIR}/third_party/protobuf/conformance/conformance.proto - COMMAND protoc --include_imports - ${CMAKE_CURRENT_SOURCE_DIR}/third_party/protobuf/conformance/conformance.proto - ${CMAKE_CURRENT_SOURCE_DIR}/third_party/protobuf/src/google/protobuf/test_messages_proto3.proto - -I${CMAKE_CURRENT_SOURCE_DIR}/third_party/protobuf/conformance - -I${CMAKE_CURRENT_SOURCE_DIR}/third_party/protobuf/src - -o${CMAKE_CURRENT_BINARY_DIR}/conformance.pb && - tools/upbc ${CMAKE_CURRENT_BINARY_DIR}/conformance.pb - ) - - add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/descriptor.upb.h - ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/descriptor.upb.c - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/tools/upbc - ${CMAKE_CURRENT_SOURCE_DIR}/google/protobuf/descriptor.proto - COMMAND protoc - ${CMAKE_CURRENT_SOURCE_DIR}/google/protobuf/descriptor.proto - -I${CMAKE_CURRENT_SOURCE_DIR} - -o${CMAKE_CURRENT_BINARY_DIR}/descriptor.pb && - tools/upbc ${CMAKE_CURRENT_BINARY_DIR}/descriptor.pb - ) - - add_custom_target( - genfiles ALL - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/conformance.upb.h - ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/descriptor.upb.h - ) - - add_executable(conformance_upb - tests/conformance_upb.c - ${CMAKE_CURRENT_BINARY_DIR}/conformance.upb.c - ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/test_messages_proto3.upb.c - ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/any.upb.c - ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/duration.upb.c - ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/field_mask.upb.c - ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/struct.upb.c - ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/timestamp.upb.c - ${CMAKE_CURRENT_BINARY_DIR}/google/protobuf/wrappers.upb.c - ) - target_link_libraries(conformance_upb LINK_PRIVATE - upb - ) - - add_custom_target( - conformance - DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/conformance_upb - ${CMAKE_CURRENT_BINARY_DIR}/third_party/protobuf/cmake/conformance_test_runner - COMMAND ${CMAKE_CURRENT_BINARY_DIR}/third_party/protobuf/cmake/conformance_test_runner ${CMAKE_CURRENT_BINARY_DIR}/conformance_upb - ) - -endif() - -if (RAGEL) - add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/upb/json/parser.c - DEPENDS upb/json/parser.rl - COMMAND cd ${CMAKE_CURRENT_SOURCE_DIR} && RAGEL -C -o ${CMAKE_CURRENT_BINARY_DIR}/upb/json/parser.c upb/json/parser.rl - ) -endif() - -configure_file(tools/copy_genfiles.sh.in tools/copy_genfiles.sh) - -set(UPB_SRCS - upb/decode.c - upb/encode.c - upb/msg.c - upb/table.c - upb/upb.c -) - -set (UPBDEF_SRCS - upb/def.c - upb/msgfactory.c -) - -set(UPBHANDLERS_SRCS - upb/sink.c - upb/handlers.c -) - -set(UPBPB_SRCS -======= enable_testing() add_library(upb @@ -290,15 +87,7 @@ add_library(upb upb/refcounted.h upb/sink.h upb/upb.h) -add_library(upb_descriptor - upb/descriptor/descriptor.upbdefs.c - upb/descriptor/reader.c - upb/descriptor/descriptor.upbdefs.h - upb/descriptor/reader.h) -target_link_libraries(upb_descriptor - upb) add_library(upb_pb ->>>>>>> cmake-mac-fixes upb/pb/compile_decoder.c upb/pb/decoder.c upb/pb/decoder.int.h @@ -308,11 +97,9 @@ add_library(upb_pb upb/pb/varint.int.h upb/pb/decoder.h upb/pb/encoder.h - upb/pb/glue.h upb/pb/textprinter.h) target_link_libraries(upb_pb - upb - upb_descriptor) + upb) add_library(upb_json upb/json/parser.c upb/json/printer.c @@ -369,7 +156,6 @@ add_executable(test_cpp add_test(NAME test_cpp COMMAND test_cpp) target_link_libraries(test_cpp upb - upb_descriptor upb_pb upb_test) add_executable(test_table diff --git a/upb/bindings/lua/def.c b/upb/bindings/lua/def.c index 7b3f612..1fde212 100644 --- a/upb/bindings/lua/def.c +++ b/upb/bindings/lua/def.c @@ -22,22 +22,6 @@ } while (0) -const char *lupb_checkname(lua_State *L, int narg) { - size_t len; - const char *name = luaL_checklstring(L, narg, &len); - if (strlen(name) != len) - luaL_error(L, "names cannot have embedded NULLs"); - return name; -} - -upb_fieldtype_t lupb_checkfieldtype(lua_State *L, int narg) { - int type = luaL_checkint(L, narg); - if (!upb_fielddef_checktype(type)) - luaL_argerror(L, narg, "invalid field type"); - return type; -} - - /* lupb_refcounted ************************************************************/ /* All upb objects that use upb_refcounted have a userdata that begins with a @@ -49,12 +33,12 @@ upb_fieldtype_t lupb_checkfieldtype(lua_State *L, int narg) { * long as it begins with a pointer. */ /* Checks type; if it matches, pulls the pointer out of the wrapper. */ -void *lupb_refcounted_check(lua_State *L, int narg, const char *type) { +void *lupb_checkwrapper(lua_State *L, int narg, const char *type) { void *ud = lua_touserdata(L, narg); void *ret; if (!ud) { - luaL_typerror(L, narg, "refcounted"); + luaL_typerror(L, narg, "upb wrapper"); } memcpy(&ret, ud, sizeof(ret)); @@ -66,15 +50,12 @@ void *lupb_refcounted_check(lua_State *L, int narg, const char *type) { return ret; } -bool lupb_refcounted_pushwrapper(lua_State *L, const upb_refcounted *obj, - const char *type, const void *ref_donor, - size_t size) { - bool create; +void lupb_pushwrapper(lua_State *L, const void *obj, const char *type) { void *ud; if (obj == NULL) { lua_pushnil(L); - return false; + return; } /* Lookup our cache in the registry (we don't put our objects in the registry @@ -85,34 +66,11 @@ bool lupb_refcounted_pushwrapper(lua_State *L, const upb_refcounted *obj, lua_rawget(L, -2); /* Stack is now: objcache, cached value. */ - create = false; - if (lua_isnil(L, -1)) { - create = true; - } else { - void *ud = lua_touserdata(L, -1); - void *ud_obj; - lupb_assert(L, ud); - memcpy(&ud_obj, ud, sizeof(void*)); - - /* A corner case: it is possible for the value to be GC'd - * already, in which case we should evict this entry and create - * a new one. */ - if (ud_obj == NULL) { - create = true; - } - } - - ud = NULL; - - if (create) { /* Remove bad cached value and push new value. */ lua_pop(L, 1); - - /* All of our userdata begin with a pointer to the obj. */ - ud = lua_newuserdata(L, size); - memcpy(ud, &obj, sizeof(void*)); - upb_refcounted_donateref(obj, ref_donor, ud); + ud = lua_newuserdata(L, sizeof(*ud)); + memcpy(ud, &obj, sizeof(*ud)); luaL_getmetatable(L, type); /* Should have been created by luaopen_upb. */ @@ -123,207 +81,36 @@ bool lupb_refcounted_pushwrapper(lua_State *L, const upb_refcounted *obj, lua_pushlightuserdata(L, (void*)obj); lua_pushvalue(L, -2); lua_rawset(L, -4); - } else { - /* Existing wrapper obj already has a ref. */ - ud = lua_touserdata(L, -1); - upb_refcounted_checkref(obj, ud); - if (ref_donor) - upb_refcounted_unref(obj, ref_donor); } lua_insert(L, -2); lua_pop(L, 1); - return create; -} - -void lupb_refcounted_pushnewrapper(lua_State *L, const upb_refcounted *obj, - const char *type, const void *ref_donor) { - bool created = - lupb_refcounted_pushwrapper(L, obj, type, ref_donor, sizeof(void *)); - UPB_ASSERT(created == true); -} - -int lupb_refcounted_gc(lua_State *L) { - void *ud = lua_touserdata(L, 1); - void *nullp; - upb_refcounted *obj; - memcpy(&obj, ud, sizeof(obj)); - upb_refcounted_unref(obj, ud); - - /* Zero out pointer so we can detect a call into a GC'd object. */ - nullp = NULL; - memcpy(ud, &nullp, sizeof(nullp)); - - return 0; -} - - -/* lupb_def *******************************************************************/ - -static const upb_def *lupb_def_check(lua_State *L, int narg) { - upb_def *ret; - void *ud, *ud2; - - ud = lua_touserdata(L, narg); - if (!ud) { - luaL_typerror(L, narg, "upb def"); - } - - memcpy(&ret, ud, sizeof(ret)); - if (!ret) { - luaL_error(L, "called into dead object"); - } - - ud2 = luaL_testudata(L, narg, LUPB_MSGDEF); - if (!ud2) ud2 = luaL_testudata(L, narg, LUPB_ENUMDEF); - if (!ud2) ud2 = luaL_testudata(L, narg, LUPB_FIELDDEF); - if (!ud2) luaL_typerror(L, narg, "upb def"); - - return ret; -} - -static upb_def *lupb_def_checkmutable(lua_State *L, int narg) { - const upb_def *def = lupb_def_check(L, narg); - if (upb_def_isfrozen(def)) - luaL_error(L, "not allowed on frozen value"); - return (upb_def*)def; -} - -bool lupb_def_pushwrapper(lua_State *L, const upb_def *def, - const void *ref_donor) { - const char *type = NULL; - bool created; - - if (def == NULL) { - lua_pushnil(L); - return false; - } - - switch (upb_def_type(def)) { - case UPB_DEF_MSG: - type = LUPB_MSGDEF; - break; - case UPB_DEF_FIELD: - type = LUPB_FIELDDEF; - break; - case UPB_DEF_ENUM: - type = LUPB_ENUMDEF; - break; - default: - printf("Def type: %d\n", (int)upb_def_type(def)); - UPB_UNREACHABLE(); - } - - created = lupb_refcounted_pushwrapper(L, upb_def_upcast(def), type, ref_donor, - sizeof(void *)); - return created; -} - -void lupb_def_pushnewrapper(lua_State *L, const upb_def *def, - const void *ref_donor) { - bool created = lupb_def_pushwrapper(L, def, ref_donor); - UPB_ASSERT(created == true); -} - -static int lupb_def_type(lua_State *L) { - const upb_def *def = lupb_def_check(L, 1); - lua_pushinteger(L, upb_def_type(def)); - return 1; -} - -void lupb_filedef_pushwrapper(lua_State *L, const upb_filedef *f, - const void *ref_donor); - -static int lupb_def_file(lua_State *L) { - const upb_def *def = lupb_def_check(L, 1); - lupb_filedef_pushwrapper(L, upb_def_file(def), NULL); - return 1; -} - -static int lupb_def_freeze(lua_State *L) { - upb_def *def = lupb_def_checkmutable(L, 1); - CHK(upb_def_freeze(&def, 1, &status)); - return 0; -} - -static int lupb_def_isfrozen(lua_State *L) { - const upb_def *def = lupb_def_check(L, 1); - lua_pushboolean(L, upb_def_isfrozen(def)); - return 1; -} - -static int lupb_def_fullname(lua_State *L) { - const upb_def *def = lupb_def_check(L, 1); - lua_pushstring(L, upb_def_fullname(def)); - return 1; } -static int lupb_def_name(lua_State *L) { - const upb_def *def = lupb_def_check(L, 1); - lua_pushstring(L, upb_def_name(def)); - return 1; -} - -static int lupb_def_setfullname(lua_State *L) { - const char *name = lupb_checkname(L, 2); - CHK(upb_def_setfullname(lupb_def_checkmutable(L, 1), name, &status)); - return 0; -} - -#define LUPB_COMMON_DEF_METHODS \ - {"def_type", lupb_def_type}, \ - {"file", lupb_def_file}, \ - {"full_name", lupb_def_fullname}, \ - {"freeze", lupb_def_freeze}, \ - {"is_frozen", lupb_def_isfrozen}, \ - {"name", lupb_def_name}, \ - {"set_full_name", lupb_def_setfullname}, \ +void lupb_msgdef_pushwrapper(lua_State *L, const upb_msgdef *m); +void lupb_oneofdef_pushwrapper(lua_State *L, const upb_oneofdef *o); +static void lupb_enumdef_pushwrapper(lua_State *L, const upb_enumdef *e); /* lupb_fielddef **************************************************************/ -void lupb_fielddef_pushwrapper(lua_State *L, const upb_fielddef *f, - const void *ref_donor) { - lupb_def_pushwrapper(L, upb_fielddef_upcast(f), ref_donor); +void lupb_fielddef_pushwrapper(lua_State *L, const upb_fielddef *f) { + lupb_pushwrapper(L, f, LUPB_FIELDDEF); } const upb_fielddef *lupb_fielddef_check(lua_State *L, int narg) { - return lupb_refcounted_check(L, narg, LUPB_FIELDDEF); + return lupb_checkwrapper(L, narg, LUPB_FIELDDEF); } -static upb_fielddef *lupb_fielddef_checkmutable(lua_State *L, int narg) { - const upb_fielddef *f = lupb_fielddef_check(L, narg); - if (upb_fielddef_isfrozen(f)) - luaL_error(L, "not allowed on frozen value"); - return (upb_fielddef*)f; -} - -static int lupb_fielddef_new(lua_State *L) { - upb_fielddef *f = upb_fielddef_new(&f); - lupb_def_pushnewrapper(L, upb_fielddef_upcast(f), &f); - return 1; -} - -/* Getters */ - -void lupb_oneofdef_pushwrapper(lua_State *L, const upb_oneofdef *o, - const void *ref_donor); - static int lupb_fielddef_containingoneof(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); - lupb_oneofdef_pushwrapper(L, upb_fielddef_containingoneof(f), NULL); + lupb_oneofdef_pushwrapper(L, upb_fielddef_containingoneof(f)); return 1; } static int lupb_fielddef_containingtype(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); - lupb_msgdef_pushwrapper(L, upb_fielddef_containingtype(f), NULL); - return 1; -} - -static int lupb_fielddef_containingtypename(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lua_pushstring(L, upb_fielddef_containingtypename(f)); + lupb_msgdef_pushwrapper(L, upb_fielddef_containingtype(f)); return 1; } @@ -331,7 +118,7 @@ static int lupb_fielddef_default(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); switch (upb_fielddef_type(f)) { case UPB_TYPE_INT32: - int32: + case UPB_TYPE_ENUM: lupb_pushint32(L, upb_fielddef_defaultint32(f)); break; case UPB_TYPE_INT64: lupb_pushint64(L, upb_fielddef_defaultint64(f)); break; @@ -345,18 +132,8 @@ static int lupb_fielddef_default(lua_State *L) { 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_enumhasdefaultstr(f)) { - goto str; - } else if (upb_fielddef_enumhasdefaultint32(f)) { - goto int32; - } else { - lua_pushnil(L); - } - break; case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: - str: { + case UPB_TYPE_BYTES: { size_t len; const char *data = upb_fielddef_defaultstr(f, &len); lua_pushlstring(L, data, len); @@ -397,24 +174,12 @@ static int lupb_fielddef_index(lua_State *L) { return 1; } -static int lupb_fielddef_intfmt(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - lua_pushinteger(L, upb_fielddef_intfmt(f)); - return 1; -} - static int lupb_fielddef_isextension(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); lua_pushboolean(L, upb_fielddef_isextension(f)); return 1; } -static int lupb_fielddef_istagdelim(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - lua_pushboolean(L, upb_fielddef_istagdelim(f)); - return 1; -} - static int lupb_fielddef_label(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); lua_pushinteger(L, upb_fielddef_label(f)); @@ -449,22 +214,15 @@ static int lupb_fielddef_packed(lua_State *L) { return 1; } -static int lupb_fielddef_subdef(lua_State *L) { +static int lupb_fielddef_msgsubdef(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); - const upb_def *def; - - if (!upb_fielddef_hassubdef(f)) - luaL_error(L, "Tried to get subdef of non-message field"); - def = upb_fielddef_subdef(f); - lupb_def_pushwrapper(L, def, NULL); + lupb_msgdef_pushwrapper(L, upb_fielddef_msgsubdef(f)); return 1; } -static int lupb_fielddef_subdefname(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - if (!upb_fielddef_hassubdef(f)) - luaL_error(L, "Tried to get subdef name of non-message field"); - lua_pushstring(L, upb_fielddef_subdefname(f)); +static int lupb_fielddef_enumsubdef(lua_State *L) { + const upb_fielddef *f = lupb_fielddef_check(L, 1); + lupb_enumdef_pushwrapper(L, upb_fielddef_enumsubdef(f)); return 1; } @@ -477,216 +235,40 @@ static int lupb_fielddef_type(lua_State *L) { return 1; } -/* Setters */ - -static int lupb_fielddef_setcontainingtypename(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - const char *name = NULL; - if (!lua_isnil(L, 2)) - name = lupb_checkname(L, 2); - CHK(upb_fielddef_setcontainingtypename(f, name, &status)); - return 0; -} - -static int lupb_fielddef_setdefault(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - - switch (upb_fielddef_type(f)) { - case UPB_TYPE_INT32: - upb_fielddef_setdefaultint32(f, lupb_checkint32(L, 2)); - break; - case UPB_TYPE_INT64: - upb_fielddef_setdefaultint64(f, lupb_checkint64(L, 2)); - break; - case UPB_TYPE_UINT32: - upb_fielddef_setdefaultuint32(f, lupb_checkuint32(L, 2)); - break; - case UPB_TYPE_UINT64: - upb_fielddef_setdefaultuint64(f, lupb_checkuint64(L, 2)); - break; - case UPB_TYPE_DOUBLE: - upb_fielddef_setdefaultdouble(f, lupb_checkdouble(L, 2)); - break; - case UPB_TYPE_FLOAT: - upb_fielddef_setdefaultfloat(f, lupb_checkfloat(L, 2)); - break; - case UPB_TYPE_BOOL: - upb_fielddef_setdefaultbool(f, lupb_checkbool(L, 2)); - break; - case UPB_TYPE_MESSAGE: - return luaL_error(L, "Message types cannot have defaults."); - case UPB_TYPE_ENUM: - if (lua_type(L, 2) != LUA_TSTRING) { - upb_fielddef_setdefaultint32(f, lupb_checkint32(L, 2)); - break; - } - /* Else fall through and set string default. */ - case UPB_TYPE_BYTES: - case UPB_TYPE_STRING: { - size_t len; - const char *str = lua_tolstring(L, 2, &len); - CHK(upb_fielddef_setdefaultstr(f, str, len, &status)); - } - } - return 0; -} - -static int lupb_fielddef_setisextension(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - CHK(upb_fielddef_setisextension(f, lupb_checkbool(L, 2))); - return 0; -} - -static int lupb_fielddef_setlabel(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - int label = luaL_checkint(L, 2); - if (!upb_fielddef_checklabel(label)) - luaL_argerror(L, 2, "invalid field label"); - upb_fielddef_setlabel(f, label); - return 0; -} - -static int lupb_fielddef_setlazy(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - upb_fielddef_setlazy(f, lupb_checkbool(L, 2)); - return 0; -} - -static int lupb_fielddef_setname(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - CHK(upb_fielddef_setname(f, lupb_checkname(L, 2), &status)); - return 0; -} - -static int lupb_fielddef_setnumber(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - CHK(upb_fielddef_setnumber(f, luaL_checkint(L, 2), &status)); - return 0; -} - -static int lupb_fielddef_setpacked(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - upb_fielddef_setpacked(f, lupb_checkbool(L, 2)); - return 0; -} - -static int lupb_fielddef_setsubdef(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - const upb_def *def = NULL; - if (!lua_isnil(L, 2)) - def = lupb_def_check(L, 2); - CHK(upb_fielddef_setsubdef(f, def, &status)); - return 0; -} - -static int lupb_fielddef_setsubdefname(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - const char *name = NULL; - if (!lua_isnil(L, 2)) - name = lupb_checkname(L, 2); - CHK(upb_fielddef_setsubdefname(f, name, &status)); - return 0; -} - -static int lupb_fielddef_settype(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - upb_fielddef_settype(f, lupb_checkfieldtype(L, 2)); - return 0; -} - -static int lupb_fielddef_setintfmt(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - int32_t intfmt = luaL_checknumber(L, 2); - if (!upb_fielddef_checkintfmt(intfmt)) - luaL_argerror(L, 2, "invalid intfmt"); - upb_fielddef_setintfmt(f, intfmt); - return 0; -} - -static int lupb_fielddef_settagdelim(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - bool is_tag_delim = lupb_checkbool(L, 2); - CHK(upb_fielddef_settagdelim(f, is_tag_delim)); - return 0; -} - -static const struct luaL_Reg lupb_fielddef_mm[] = { - {"__gc", lupb_refcounted_gc}, - {NULL, NULL} -}; - static const struct luaL_Reg lupb_fielddef_m[] = { - LUPB_COMMON_DEF_METHODS - {"containing_oneof", lupb_fielddef_containingoneof}, {"containing_type", lupb_fielddef_containingtype}, - {"containing_type_name", lupb_fielddef_containingtypename}, {"default", lupb_fielddef_default}, {"descriptor_type", lupb_fielddef_descriptortype}, {"getsel", lupb_fielddef_getsel}, {"has_subdef", lupb_fielddef_hassubdef}, {"index", lupb_fielddef_index}, - {"intfmt", lupb_fielddef_intfmt}, {"is_extension", lupb_fielddef_isextension}, - {"istagdelim", lupb_fielddef_istagdelim}, {"label", lupb_fielddef_label}, {"lazy", lupb_fielddef_lazy}, {"name", lupb_fielddef_name}, {"number", lupb_fielddef_number}, {"packed", lupb_fielddef_packed}, - {"subdef", lupb_fielddef_subdef}, - {"subdef_name", lupb_fielddef_subdefname}, + {"msgsubdef", lupb_fielddef_msgsubdef}, + {"enumsubdef", lupb_fielddef_enumsubdef}, {"type", lupb_fielddef_type}, - - {"set_containing_type_name", lupb_fielddef_setcontainingtypename}, - {"set_default", lupb_fielddef_setdefault}, - {"set_is_extension", lupb_fielddef_setisextension}, - {"set_label", lupb_fielddef_setlabel}, - {"set_lazy", lupb_fielddef_setlazy}, - {"set_name", lupb_fielddef_setname}, - {"set_number", lupb_fielddef_setnumber}, - {"set_packed", lupb_fielddef_setpacked}, - {"set_subdef", lupb_fielddef_setsubdef}, - {"set_subdef_name", lupb_fielddef_setsubdefname}, - {"set_type", lupb_fielddef_settype}, - {"set_intfmt", lupb_fielddef_setintfmt}, - {"set_tagdelim", lupb_fielddef_settagdelim}, - {NULL, NULL} }; /* lupb_oneofdef **************************************************************/ -void lupb_oneofdef_pushwrapper(lua_State *L, const upb_oneofdef *o, - const void *ref_donor) { - lupb_refcounted_pushwrapper(L, upb_oneofdef_upcast(o), LUPB_ONEOFDEF, - ref_donor, sizeof(void *)); +void lupb_oneofdef_pushwrapper(lua_State *L, const upb_oneofdef *o) { + lupb_pushwrapper(L, o, LUPB_ONEOFDEF); } const upb_oneofdef *lupb_oneofdef_check(lua_State *L, int narg) { return lupb_refcounted_check(L, narg, LUPB_ONEOFDEF); } -static upb_oneofdef *lupb_oneofdef_checkmutable(lua_State *L, int narg) { - const upb_oneofdef *o = lupb_oneofdef_check(L, narg); - if (upb_oneofdef_isfrozen(o)) - luaL_error(L, "not allowed on frozen value"); - return (upb_oneofdef*)o; -} - -static int lupb_oneofdef_new(lua_State *L) { - upb_oneofdef *o = upb_oneofdef_new(&o); - lupb_refcounted_pushnewrapper(L, upb_oneofdef_upcast(o), LUPB_ONEOFDEF, &o); - return 1; -} - -/* Getters */ - static int lupb_oneofdef_containingtype(lua_State *L) { const upb_oneofdef *o = lupb_oneofdef_check(L, 1); - lupb_def_pushwrapper(L, upb_msgdef_upcast(upb_oneofdef_containingtype(o)), - NULL); + lupb_msgdef_pushwrapper(L, upb_oneofdef_containingtype(o)); return 1; } @@ -704,14 +286,14 @@ static int lupb_oneofdef_field(lua_State *L) { return luaL_argerror(L, 2, msg); } - lupb_def_pushwrapper(L, upb_fielddef_upcast(f), NULL); + lupb_fielddef_pushwrapper(L, f); return 1; } static int lupb_oneofiter_next(lua_State *L) { upb_oneof_iter *i = lua_touserdata(L, lua_upvalueindex(1)); if (upb_oneof_done(i)) return 0; - lupb_fielddef_pushwrapper(L, upb_oneof_iter_field(i), NULL); + lupb_fielddef_pushwrapper(L, upb_oneof_iter_field(i)); upb_oneof_next(i); return 1; } @@ -738,35 +320,15 @@ static int lupb_oneofdef_name(lua_State *L) { return 1; } -/* Setters */ - -static int lupb_oneofdef_add(lua_State *L) { - upb_oneofdef *o = lupb_oneofdef_checkmutable(L, 1); - upb_fielddef *f = lupb_fielddef_checkmutable(L, 2); - CHK(upb_oneofdef_addfield(o, f, NULL, &status)); - return 0; -} - -static int lupb_oneofdef_setname(lua_State *L) { - upb_oneofdef *o = lupb_oneofdef_checkmutable(L, 1); - CHK(upb_oneofdef_setname(o, lupb_checkname(L, 2), &status)); - return 0; -} - static const struct luaL_Reg lupb_oneofdef_m[] = { {"containing_type", lupb_oneofdef_containingtype}, {"field", lupb_oneofdef_field}, {"fields", lupb_oneofdef_fields}, {"name", lupb_oneofdef_name}, - - {"add", lupb_oneofdef_add}, - {"set_name", lupb_oneofdef_setname}, - {NULL, NULL} }; static const struct luaL_Reg lupb_oneofdef_mm[] = { - {"__gc", lupb_refcounted_gc}, {"__len", lupb_oneofdef_len}, {NULL, NULL} }; @@ -778,42 +340,14 @@ typedef struct { const upb_msgdef *md; } lupb_msgdef; -void lupb_msgdef_pushwrapper(lua_State *L, const upb_msgdef *m, - const void *ref_donor) { - lupb_def_pushwrapper(L, upb_msgdef_upcast(m), ref_donor); +void lupb_msgdef_pushwrapper(lua_State *L, const upb_msgdef *m) { + lupb_pushwrapper(L, m, LUPB_MSGDEF); } const upb_msgdef *lupb_msgdef_check(lua_State *L, int narg) { return lupb_refcounted_check(L, narg, LUPB_MSGDEF); } -static upb_msgdef *lupb_msgdef_checkmutable(lua_State *L, int narg) { - const upb_msgdef *m = lupb_msgdef_check(L, narg); - if (upb_msgdef_isfrozen(m)) - luaL_error(L, "not allowed on frozen value"); - return (upb_msgdef*)m; -} - -static int lupb_msgdef_new(lua_State *L) { - upb_msgdef *md = upb_msgdef_new(&md); - lupb_def_pushnewrapper(L, upb_msgdef_upcast(md), &md); - return 1; -} - -static int lupb_msgdef_add(lua_State *L) { - upb_msgdef *m = lupb_msgdef_checkmutable(L, 1); - - /* Both oneofs and fields can be added. */ - if (luaL_testudata(L, 2, LUPB_FIELDDEF)) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 2); - CHK(upb_msgdef_addfield(m, f, NULL, &status)); - } else if (luaL_testudata(L, 2, LUPB_ONEOFDEF)) { - upb_oneofdef *o = lupb_oneofdef_checkmutable(L, 2); - CHK(upb_msgdef_addoneof(m, o, NULL, &status)); - } - return 0; -} - static int lupb_msgdef_len(lua_State *L) { const upb_msgdef *m = lupb_msgdef_check(L, 1); lua_pushinteger(L, upb_msgdef_numfields(m)); @@ -834,7 +368,7 @@ static int lupb_msgdef_field(lua_State *L) { return luaL_argerror(L, 2, msg); } - lupb_def_pushwrapper(L, upb_fielddef_upcast(f), NULL); + lupb_fielddef_pushwrapper(L, f); return 1; } @@ -845,9 +379,9 @@ static int lupb_msgdef_lookupname(lua_State *L) { if (!upb_msgdef_lookupnamez(m, lua_tostring(L, 2), &f, &o)) { lua_pushnil(L); } else if (o) { - lupb_oneofdef_pushwrapper(L, o, NULL); + lupb_oneofdef_pushwrapper(L, o); } else { - lupb_fielddef_pushwrapper(L, f, NULL); + lupb_fielddef_pushwrapper(L, f); } return 1; } @@ -855,7 +389,7 @@ static int lupb_msgdef_lookupname(lua_State *L) { static int lupb_msgfielditer_next(lua_State *L) { upb_msg_field_iter *i = lua_touserdata(L, lua_upvalueindex(1)); if (upb_msg_field_done(i)) return 0; - lupb_def_pushwrapper(L, upb_fielddef_upcast(upb_msg_iter_field(i)), NULL); + lupb_fielddef_pushwrapper(L, upb_msg_iter_field(i)); upb_msg_field_next(i); return 1; } @@ -873,7 +407,7 @@ static int lupb_msgdef_fields(lua_State *L) { static int lupb_msgoneofiter_next(lua_State *L) { upb_msg_oneof_iter *i = lua_touserdata(L, lua_upvalueindex(1)); if (upb_msg_oneof_done(i)) return 0; - lupb_oneofdef_pushwrapper(L, upb_msg_iter_oneof(i), NULL); + lupb_oneofdef_pushwrapper(L, upb_msg_iter_oneof(i)); upb_msg_oneof_next(i); return 1; } @@ -902,20 +436,16 @@ static int lupb_msgdef_syntax(lua_State *L) { static const struct luaL_Reg lupb_msgdef_mm[] = { {"__len", lupb_msgdef_len}, - {"__gc", lupb_refcounted_gc}, {NULL, NULL} }; static const struct luaL_Reg lupb_msgdef_m[] = { - LUPB_COMMON_DEF_METHODS - {"add", lupb_msgdef_add}, {"field", lupb_msgdef_field}, {"fields", lupb_msgdef_fields}, {"lookup_name", lupb_msgdef_lookupname}, {"oneofs", lupb_msgdef_oneofs}, {"syntax", lupb_msgdef_syntax}, {"_map_entry", lupb_msgdef_mapentry}, - {NULL, NULL} }; @@ -926,25 +456,8 @@ const upb_enumdef *lupb_enumdef_check(lua_State *L, int narg) { return lupb_refcounted_check(L, narg, LUPB_ENUMDEF); } -static upb_enumdef *lupb_enumdef_checkmutable(lua_State *L, int narg) { - const upb_enumdef *f = lupb_enumdef_check(L, narg); - if (upb_enumdef_isfrozen(f)) - luaL_error(L, "not allowed on frozen value"); - return (upb_enumdef*)f; -} - -static int lupb_enumdef_new(lua_State *L) { - upb_enumdef *e = upb_enumdef_new(&e); - lupb_def_pushnewrapper(L, upb_enumdef_upcast(e), &e); - return 1; -} - -static int lupb_enumdef_add(lua_State *L) { - upb_enumdef *e = lupb_enumdef_checkmutable(L, 1); - const char *name = lupb_checkname(L, 2); - int32_t val = lupb_checkint32(L, 3); - CHK(upb_enumdef_addval(e, name, val, &status)); - return 0; +static void lupb_enumdef_pushwrapper(lua_State *L, const upb_enumdef *e) { + lupb_pushwrapper(L, e, LUPB_ENUMDEF); } static int lupb_enumdef_len(lua_State *L) { @@ -996,14 +509,11 @@ static int lupb_enumdef_values(lua_State *L) { } static const struct luaL_Reg lupb_enumdef_mm[] = { - {"__gc", lupb_refcounted_gc}, {"__len", lupb_enumdef_len}, {NULL, NULL} }; static const struct luaL_Reg lupb_enumdef_m[] = { - LUPB_COMMON_DEF_METHODS - {"add", lupb_enumdef_add}, {"value", lupb_enumdef_value}, {"values", lupb_enumdef_values}, {NULL, NULL} @@ -1012,68 +522,50 @@ static const struct luaL_Reg lupb_enumdef_m[] = { /* lupb_filedef ***************************************************************/ -void lupb_filedef_pushwrapper(lua_State *L, const upb_filedef *f, - const void *ref_donor) { - lupb_refcounted_pushwrapper(L, upb_filedef_upcast(f), LUPB_FILEDEF, ref_donor, - sizeof(void *)); -} - -void lupb_filedef_pushnewrapper(lua_State *L, const upb_filedef *f, - const void *ref_donor) { - lupb_refcounted_pushnewrapper(L, upb_filedef_upcast(f), LUPB_FILEDEF, - ref_donor); +void lupb_filedef_pushwrapper(lua_State *L, const upb_filedef *f) { + lupb_pushwrapper(L, f, LUPB_FILEDEF); } const upb_filedef *lupb_filedef_check(lua_State *L, int narg) { return lupb_refcounted_check(L, narg, LUPB_FILEDEF); } -static upb_filedef *lupb_filedef_checkmutable(lua_State *L, int narg) { - const upb_filedef *f = lupb_filedef_check(L, narg); - if (upb_filedef_isfrozen(f)) - luaL_error(L, "not allowed on frozen value"); - return (upb_filedef*)f; +static int lupb_filedef_dep(lua_State *L) { + const upb_filedef *f = lupb_filedef_check(L, 1); + int index = luaL_checkint(L, 2); + lupb_filedef_pushwrapper(L, upb_filedef_dep(f, index)); + return 1; } -static int lupb_filedef_new(lua_State *L) { - upb_filedef *f = upb_filedef_new(&f); - lupb_filedef_pushnewrapper(L, f, &f); +static int lupb_filedef_depcount(lua_State *L) { + const upb_filedef *f = lupb_filedef_check(L, 1); + lua_pushnumber(L, upb_filedef_depcount(f)); return 1; } -static int lupb_filedef_def(lua_State *L) { +static int lupb_filedef_enum(lua_State *L) { const upb_filedef *f = lupb_filedef_check(L, 1); int index = luaL_checkint(L, 2); - const upb_def *def = upb_filedef_def(f, index); - - if (!def) { - return luaL_error(L, "index out of range"); - } - - lupb_def_pushwrapper(L, def, NULL); + lupb_enumdef_pushwrapper(L, upb_filedef_enum(f, index)); return 1; } -static int lupb_filedefdepiter_next(lua_State *L) { - const upb_filedef *f = lupb_filedef_check(L, lua_upvalueindex(1)); - size_t i = lua_tointeger(L, lua_upvalueindex(2)); - - if (i >= upb_filedef_depcount(f)) { - return 0; - } - - lupb_filedef_pushwrapper(L, upb_filedef_dep(f, i), NULL); - lua_pushinteger(L, i + 1); - lua_replace(L, lua_upvalueindex(2)); +static int lupb_filedef_enumcount(lua_State *L) { + const upb_filedef *f = lupb_filedef_check(L, 1); + lua_pushnumber(L, upb_filedef_enumcount(f)); return 1; } +static int lupb_filedef_msg(lua_State *L) { + const upb_filedef *f = lupb_filedef_check(L, 1); + int index = luaL_checkint(L, 2); + lupb_msgdef_pushwrapper(L, upb_filedef_msg(f, index)); + return 1; +} -static int lupb_filedef_dependencies(lua_State *L) { - lupb_filedef_check(L, 1); - lua_pushvalue(L, 1); - lua_pushnumber(L, 0); /* Index, starts at zero. */ - lua_pushcclosure(L, &lupb_filedefdepiter_next, 2); +static int lupb_filedef_msgcount(lua_State *L) { + const upb_filedef *f = lupb_filedef_check(L, 1); + lua_pushnumber(L, upb_filedef_msgcount(f)); return 1; } @@ -1095,72 +587,16 @@ static int lupb_filedef_syntax(lua_State *L) { return 1; } -static int lupb_filedef_len(lua_State *L) { - const upb_filedef *f = lupb_filedef_check(L, 1); - lua_pushinteger(L, upb_filedef_defcount(f)); - return 1; -} - -static int lupb_filedef_setname(lua_State *L) { - upb_filedef *f = lupb_filedef_checkmutable(L, 1); - CHK(upb_filedef_setname(f, lupb_checkname(L, 2), &status)); - return 0; -} - -static int lupb_filedef_setpackage(lua_State *L) { - upb_filedef *f = lupb_filedef_checkmutable(L, 1); - CHK(upb_filedef_setpackage(f, lupb_checkname(L, 2), &status)); - return 0; -} - -static int lupb_filedefiter_next(lua_State *L) { - const upb_filedef *f = lupb_filedef_check(L, lua_upvalueindex(1)); - int type = lua_tointeger(L, lua_upvalueindex(2)); - size_t i = lua_tointeger(L, lua_upvalueindex(3)); - size_t n = upb_filedef_defcount(f); - - for (; i < n; i++) { - const upb_def *def; - - def = upb_filedef_def(f, i); - UPB_ASSERT(def); - - if (type == UPB_DEF_ANY || upb_def_type(def) == type) { - lua_pushinteger(L, i + 1); - lua_replace(L, lua_upvalueindex(3)); - lupb_def_pushwrapper(L, def, NULL); - return 1; - } - } - - return 0; -} - -static int lupb_filedef_defs(lua_State *L) { - lupb_filedef_check(L, 1); - luaL_checkinteger(L, 2); /* Def type. Could make this optional. */ - lua_pushnumber(L, 0); /* Index, starts at zero. */ - lua_pushcclosure(L, &lupb_filedefiter_next, 3); - return 1; -} - -static const struct luaL_Reg lupb_filedef_mm[] = { - {"__gc", lupb_refcounted_gc}, - {"__len", lupb_filedef_len}, - {NULL, NULL} -}; - static const struct luaL_Reg lupb_filedef_m[] = { - {"def", lupb_filedef_def}, - {"defs", lupb_filedef_defs}, - {"dependencies", lupb_filedef_dependencies}, + {"dep", lupb_filedef_dep}, + {"depcount", lupb_filedef_depcount}, + {"enum", lupb_filedef_enum}, + {"enumcount", lupb_filedef_enumcount}, + {"msg", lupb_filedef_msg}, + {"msgcount", lupb_filedef_msgcount}, {"name", lupb_filedef_name}, {"package", lupb_filedef_package}, {"syntax", lupb_filedef_syntax}, - - {"set_name", lupb_filedef_setname}, - {"set_package", lupb_filedef_setpackage}, - {NULL, NULL} }; @@ -1194,15 +630,23 @@ static int lupb_symtab_gc(lua_State *L) { return 0; } +/* TODO(haberman): perhaps this should take a message object instead of a + * serialized string once we have a good story for vending compiled-in + * messages. */ static int lupb_symtab_add(lua_State *L) { size_t len; - upb_symtab *s = lupb_symtab_check(L, 1); - const char *str = luaL_checklstring(L, 2, &len); - google_protobuf_FileDescriptorSet *set = - google_protobuf_FileDescriptorSet_parsenew(upb_stringview_make(str, len), - upb_symtab_arena(s)); + upb_arena *arena; size_t i; upb_array *file_arr; + google_protobuf_FileDescriptorSet *set; + upb_symtab *s = lupb_symtab_check(L, 1); + const char *str = luaL_checklstring(L, 2, &len); + + lupb_arena_new(L); + arena = lupb_arena_check(L, -1); + + set = google_protobuf_FileDescriptorSet_parsenew( + upb_stringview_make(str, len), arena); if (!set) { luaL_argerror(L, 2, "failed to parse descriptor"); @@ -1219,40 +663,24 @@ static int lupb_symtab_add(lua_State *L) { return 0; } -static int lupb_symtab_lookup(lua_State *L) { +static int lupb_symtab_lookupmsg(lua_State *L) { const upb_symtab *s = lupb_symtab_check(L, 1); - int i; - for (i = 2; i <= lua_gettop(L); i++) { - const upb_def *def = upb_symtab_lookup(s, luaL_checkstring(L, i)); - lupb_def_pushwrapper(L, def, NULL); - lua_replace(L, i); - } - return lua_gettop(L) - 1; -} - -static int lupb_symtabiter_next(lua_State *L) { - upb_symtab_iter *i = lua_touserdata(L, lua_upvalueindex(1)); - if (upb_symtab_done(i)) return 0; - lupb_def_pushwrapper(L, upb_symtab_iter_def(i), NULL); - upb_symtab_next(i); + const upb_msgdef *m = upb_symtab_lookupmsg(s, luaL_checkstring(L, 2)); + lupb_msgdef_pushwrapper(L, m); return 1; } -static int lupb_symtab_defs(lua_State *L) { +static int lupb_symtab_lookupenum(lua_State *L) { const upb_symtab *s = lupb_symtab_check(L, 1); - upb_deftype_t type = lua_gettop(L) > 1 ? luaL_checkint(L, 2) : UPB_DEF_ANY; - upb_symtab_iter *i = lua_newuserdata(L, sizeof(upb_symtab_iter)); - upb_symtab_begin(i, s, type); - /* Need to guarantee that the symtab outlives the iter. */ - lua_pushvalue(L, 1); - lua_pushcclosure(L, &lupb_symtabiter_next, 2); + const upb_enumdef *e = upb_symtab_lookupenum(s, luaL_checkstring(L, 2)); + lupb_enumdef_pushwrapper(L, e); return 1; } static const struct luaL_Reg lupb_symtab_m[] = { {"add", lupb_symtab_add}, - {"defs", lupb_symtab_defs}, - {"lookup", lupb_symtab_lookup}, + {"lookup_msg", lupb_symtab_lookupmsg}, + {"lookup_enum", lupb_symtab_lookupenum}, {NULL, NULL} }; @@ -1263,35 +691,13 @@ static const struct luaL_Reg lupb_symtab_mm[] = { /* lupb toplevel **************************************************************/ -static int lupb_freeze(lua_State *L) { - int n = lua_gettop(L); - int i; - /* Scratch memory; lua_newuserdata() anchors it as a GC root in case any Lua - * functions fail. */ - upb_def **defs = lua_newuserdata(L, n * sizeof(upb_def*)); - - for (i = 0; i < n; i++) { - /* Could allow an array of defs here also. */ - defs[i] = lupb_def_checkmutable(L, i + 1); - } - CHK(upb_def_freeze(defs, n, &status)); - return 0; -} - static void lupb_setfieldi(lua_State *L, const char *field, int i) { lua_pushinteger(L, i); lua_setfield(L, -2, field); } static const struct luaL_Reg lupbdef_toplevel_m[] = { - {"EnumDef", lupb_enumdef_new}, - {"FieldDef", lupb_fielddef_new}, - {"FileDef", lupb_filedef_new}, - {"MessageDef", lupb_msgdef_new}, - {"OneofDef", lupb_oneofdef_new}, {"SymbolTable", lupb_symtab_new}, - {"freeze", lupb_freeze}, - {NULL, NULL} }; @@ -1300,8 +706,8 @@ void lupb_def_registertypes(lua_State *L) { /* Refcounted types. */ lupb_register_type(L, LUPB_ENUMDEF, lupb_enumdef_m, lupb_enumdef_mm); - lupb_register_type(L, LUPB_FIELDDEF, lupb_fielddef_m, lupb_fielddef_mm); - lupb_register_type(L, LUPB_FILEDEF, lupb_filedef_m, lupb_filedef_mm); + lupb_register_type(L, LUPB_FIELDDEF, lupb_fielddef_m, NULL); + lupb_register_type(L, LUPB_FILEDEF, lupb_filedef_m, NULL); lupb_register_type(L, LUPB_MSGDEF, lupb_msgdef_m, lupb_msgdef_mm); lupb_register_type(L, LUPB_ONEOFDEF, lupb_oneofdef_m, lupb_oneofdef_mm); lupb_register_type(L, LUPB_SYMTAB, lupb_symtab_m, lupb_symtab_mm); @@ -1354,12 +760,6 @@ void lupb_def_registertypes(lua_State *L) { lupb_setfieldi(L, "DESCRIPTOR_TYPE_SINT32", UPB_DESCRIPTOR_TYPE_SINT32); lupb_setfieldi(L, "DESCRIPTOR_TYPE_SINT64", UPB_DESCRIPTOR_TYPE_SINT64); - lupb_setfieldi(L, "DEF_MSG", UPB_DEF_MSG); - lupb_setfieldi(L, "DEF_FIELD", UPB_DEF_FIELD); - lupb_setfieldi(L, "DEF_ENUM", UPB_DEF_ENUM); - lupb_setfieldi(L, "DEF_SERVICE", UPB_DEF_SERVICE); - lupb_setfieldi(L, "DEF_ANY", UPB_DEF_ANY); - lupb_setfieldi(L, "HANDLER_INT32", UPB_HANDLER_INT32); lupb_setfieldi(L, "HANDLER_INT64", UPB_HANDLER_INT64); lupb_setfieldi(L, "HANDLER_UINT32", UPB_HANDLER_UINT32); diff --git a/upb/def.c b/upb/def.c index c800319..3167222 100644 --- a/upb/def.c +++ b/upb/def.c @@ -2,8 +2,10 @@ #include "upb/def.h" #include +#include #include #include +#include "google/protobuf/descriptor.upb.h" #include "upb/handlers.h" typedef struct { @@ -29,6 +31,7 @@ struct upb_fielddef { uint64_t uint; double dbl; float flt; + bool boolean; str_t *str; } defaultval; const upb_msgdef *msgdef; @@ -48,14 +51,11 @@ struct upb_fielddef { }; struct upb_msgdef { - upb_filedef *file; + const upb_filedef *file; const char *full_name; uint32_t selector_count; uint32_t submsg_field_count; - upb_fielddef **fields; - upb_oneofdef **oneofs; - /* Tables for looking up fields by number and name. */ upb_inttable itof; upb_strtable ntof; @@ -82,11 +82,6 @@ struct upb_oneofdef { upb_inttable itof; }; -struct upb_symtab { - upb_arena arena; - upb_strtable symtab; -}; - struct upb_filedef { const char *name; const char *package; @@ -94,8 +89,37 @@ struct upb_filedef { const char *phpnamespace; upb_syntax_t syntax; - upb_inttable defs; - upb_inttable deps; + const upb_msgdef **msgs; + const upb_enumdef **enums; + const upb_filedef **deps; + + int msgcount; + int enumcount; + int depcount; +}; + +/* Inside a symtab we store tagged pointers to specific def types. */ +typedef enum { + UPB_DEFTYPE_MSG = 0, + UPB_DEFTYPE_ENUM = 1, + UPB_DEFTYPE_FIELD = 2, + UPB_DEFTYPE_ONEOF = 3 +} upb_deftype_t; + +static const void *unpack_def(upb_value v, upb_deftype_t type) { + uintptr_t num = (uintptr_t)upb_value_getconstptr(v); + return (num & 3) == type ? (const void*)(num & ~3) : NULL; +} + +static upb_value pack_def(const void *ptr, upb_deftype_t type) { + uintptr_t num = (uintptr_t)ptr | type; + return upb_value_constptr((const void*)num); +} + +struct upb_symtab { + upb_arena arena; + upb_strtable syms; /* full_name -> packed def ptr */ + upb_strtable files; /* file_name -> upb_filedef* */ }; /* isalpha() etc. from are locale-dependent, which we don't want. */ @@ -111,7 +135,9 @@ static bool upb_isalphanum(char c) { return upb_isletter(c) || upb_isbetween(c, '0', '9'); } -static bool upb_isident(const char *str, size_t len, bool full, upb_status *s) { +static bool upb_isident(upb_stringview name, bool full, upb_status *s) { + const char *str = name.data; + size_t len = name.size; bool start = true; size_t i; for (i = 0; i < len; i++) { @@ -141,7 +167,7 @@ static bool upb_isident(const char *str, size_t len, bool full, upb_status *s) { return !start; } -static const char *shortname(const char *fullname) { +static const char *shortdefname(const char *fullname) { const char *p; if (fullname == NULL) { @@ -388,22 +414,12 @@ err: /* upb_enumdef ****************************************************************/ -#if 0 -bool upb_enumdef_init(upb_enumdef *e) { - upb_def_init(&e->base, UPB_DEF_ENUM); - - if (!upb_strtable_init(&e->ntoi, UPB_CTYPE_INT32)) goto err2; - if (!upb_inttable_init(&e->iton, UPB_CTYPE_CSTR)) goto err1; - return true; -} -#endif - const char *upb_enumdef_fullname(const upb_enumdef *e) { return e->full_name; } const char *upb_enumdef_name(const upb_enumdef *e) { - return shortname(e->full_name); + return shortdefname(e->full_name); } #if 0 @@ -499,43 +515,10 @@ int32_t upb_enum_iter_number(upb_enum_iter *iter) { /* upb_fielddef ***************************************************************/ -static void upb_fielddef_init_default(upb_fielddef *f); - const char *upb_fielddef_fullname(const upb_fielddef *f) { return f->full_name; } -#if 0 -upb_fielddef *upb_fielddef_new(const void *o) { - upb_fielddef *f = upb_gmalloc(sizeof(*f)); - if (!f) return NULL; - upb_def_init(&f->base, UPB_DEF_FIELD); - f->msg.def = NULL; - f->sub.def = NULL; - f->oneof = NULL; - f->subdef_is_symbolic = false; - f->label_ = UPB_LABEL_OPTIONAL; - f->type_ = UPB_TYPE_INT32; - f->number_ = 0; - f->type_is_set_ = false; - f->tagdelim = false; - f->is_extension_ = false; - f->lazy_ = false; - f->packed_ = true; - - /* For the moment we default this to UPB_INTFMT_VARIABLE, since it will work - * with all integer types and is in some since more "default" since the most - * normal-looking proto2 types int32/int64/uint32/uint64 use variable. - * - * Other options to consider: - * - there is no default; users must set this manually (like type). - * - default signed integers to UPB_INTFMT_ZIGZAG, since it's more likely to - * be an optimal default for signed integers. */ - f->intfmt = UPB_INTFMT_VARIABLE; - return f; -} -#endif - upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f) { switch (f->type_) { case UPB_DESCRIPTOR_TYPE_DOUBLE: @@ -699,32 +682,6 @@ const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) { return str->str; } -#if 0 -static void upb_fielddef_init_default(upb_fielddef *f) { - f->default_is_string = false; - switch (upb_fielddef_type(f)) { - 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: 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: - f->defaultval.bytes = newstr("", 0); - f->default_is_string = true; - break; - case UPB_TYPE_MESSAGE: break; - case UPB_TYPE_ENUM: - /* This is our special sentinel that indicates "not set" for an enum. */ - f->default_is_string = true; - f->defaultval.bytes = NULL; - break; - } -} -#endif - const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f) { UPB_ASSERT(upb_fielddef_type(f) == UPB_TYPE_MESSAGE); return f->sub.msgdef; @@ -735,38 +692,6 @@ const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f) { return f->sub.enumdef; } -#if 0 -bool upb_fielddef_setnumber(upb_fielddef *f, uint32_t number, upb_status *s) { - if (upb_fielddef_containingtype(f)) { - upb_status_seterrmsg( - s, "cannot change field number after adding to a message"); - return false; - } - if (number == 0 || number > UPB_MAX_FIELDNUMBER) { - upb_status_seterrf(s, "invalid field number (%u)", number); - return false; - } - f->number_ = number; - return true; -} - -static bool upb_subdef_typecheck(upb_fielddef *f, const upb_def *subdef, - upb_status *s) { - if (f->type_ == UPB_TYPE_MESSAGE) { - if (upb_dyncast_msgdef(subdef)) return true; - upb_status_seterrmsg(s, "invalid subdef type for this submessage field"); - return false; - } else if (f->type_ == UPB_TYPE_ENUM) { - if (upb_dyncast_enumdef(subdef)) return true; - upb_status_seterrmsg(s, "invalid subdef type for this enum field"); - return false; - } else { - upb_status_seterrmsg(s, "only message and enum fields can have a subdef"); - return false; - } -} -#endif - bool upb_fielddef_issubmsg(const upb_fielddef *f) { return upb_fielddef_type(f) == UPB_TYPE_MESSAGE; } @@ -812,7 +737,7 @@ const char *upb_msgdef_fullname(const upb_msgdef *m) { } const char *upb_msgdef_name(const upb_msgdef *m) { - return shortname(m->full_name); + return shortdefname(m->full_name); } upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m) { @@ -827,16 +752,6 @@ static bool check_field_add(const upb_msgdef *m, const upb_fielddef *f, if (upb_fielddef_containingtype(f) != NULL) { upb_status_seterrmsg(s, "fielddef already belongs to a message"); return false; - } else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) { - upb_status_seterrmsg(s, "field name or number were not set"); - return false; - } else if (upb_msgdef_itof(m, upb_fielddef_number(f))) { - upb_status_seterrmsg(s, "duplicate field number"); - return false; - } else if (upb_strtable_lookup(&m->ntof, upb_fielddef_name(f), NULL)) { - upb_status_seterrmsg(s, "name conflicts with existing field or oneof"); - return false; - } return true; } @@ -1156,38 +1071,6 @@ void upb_oneof_iter_setdone(upb_oneof_iter *iter) { /* upb_filedef ****************************************************************/ -upb_filedef *upb_filedef_new(const void *owner) { - upb_filedef *f = upb_gmalloc(sizeof(*f)); - - if (!f) { - return NULL; - } - - f->package = NULL; - f->name = NULL; - f->phpprefix = NULL; - f->phpnamespace = NULL; - f->syntax = UPB_SYNTAX_PROTO2; - - if (!upb_inttable_init(&f->defs, UPB_CTYPE_CONSTPTR)) { - goto err; - } - - if (!upb_inttable_init(&f->deps, UPB_CTYPE_CONSTPTR)) { - goto err2; - } - - return f; - - -err2: - upb_inttable_uninit(&f->defs); - -err: - upb_gfree(f); - return NULL; -} - const char *upb_filedef_name(const upb_filedef *f) { return f->name; } @@ -1208,32 +1091,28 @@ upb_syntax_t upb_filedef_syntax(const upb_filedef *f) { return f->syntax; } -size_t upb_filedef_defcount(const upb_filedef *f) { - return upb_inttable_count(&f->defs); +int upb_filedef_msgcount(const upb_filedef *f) { + return f->msgcount; } -size_t upb_filedef_depcount(const upb_filedef *f) { - return upb_inttable_count(&f->deps); +int upb_filedef_depcount(const upb_filedef *f) { + return f->depcount; } -const upb_def *upb_filedef_def(const upb_filedef *f, size_t i) { - upb_value v; +int upb_filedef_enumcount(const upb_filedef *f) { + return f->enumcount; +} - if (upb_inttable_lookup32(&f->defs, i, &v)) { - return upb_value_getconstptr(v); - } else { - return NULL; - } +const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i) { + return i < 0 || i >= f->depcount ? NULL : f->deps[i]; } -const upb_filedef *upb_filedef_dep(const upb_filedef *f, size_t i) { - upb_value v; +const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i) { + return i < 0 || i >= f->msgcount ? NULL : f->msgs[i]; +} - if (upb_inttable_lookup32(&f->deps, i, &v)) { - return upb_value_getconstptr(v); - } else { - return NULL; - } +const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i) { + return i < 0 || i >= f->enumcount ? NULL : f->enums[i]; } void upb_symtab_free(upb_symtab *s) { @@ -1243,53 +1122,44 @@ void upb_symtab_free(upb_symtab *s) { upb_symtab *upb_symtab_new() { upb_symtab *s = upb_gmalloc(sizeof(*s)); + upb_alloc *alloc; + if (!s) { return NULL; } - if (!upb_arena_init(&s->arena)) goto err2; - if (!upb_strtable_init2(&s->symtab, UPB_CTYPE_PTR, - upb_arena_alloc(&s->arena))) { - goto err1; - } - return s; + upb_arena_init(&s->arena); + alloc = upb_arena_alloc(&s->arena); -err1: - upb_arena_uninit(&s->arena); -err2: - upb_gfree(s); + if (!upb_strtable_init2(&s->syms, UPB_CTYPE_CONSTPTR, alloc) || + !upb_strtable_init2(&s->files, UPB_CTYPE_CONSTPTR, alloc)) { + upb_arena_uninit(&s->arena); + upb_gfree(s); + s = NULL; + } return s; } -const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym) { - upb_value v; - upb_def *ret = upb_strtable_lookup(&s->symtab, sym, &v) ? - upb_value_getptr(v) : NULL; - return ret; -} - const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) { upb_value v; - upb_def *def = upb_strtable_lookup(&s->symtab, sym, &v) ? - upb_value_getptr(v) : NULL; - return def ? upb_dyncast_msgdef(def) : NULL; + return upb_strtable_lookup(&s->syms, sym, &v) ? + unpack_def(v, UPB_DEFTYPE_MSG) : NULL; } const upb_msgdef *upb_symtab_lookupmsg2(const upb_symtab *s, const char *sym, size_t len) { upb_value v; - upb_def *def = upb_strtable_lookup2(&s->symtab, sym, len, &v) ? - upb_value_getptr(v) : NULL; - return def ? upb_dyncast_msgdef(def) : NULL; + return upb_strtable_lookup2(&s->syms, sym, len, &v) ? + unpack_def(v, UPB_DEFTYPE_MSG) : NULL; } const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) { upb_value v; - upb_def *def = upb_strtable_lookup(&s->symtab, sym, &v) ? - upb_value_getptr(v) : NULL; - return def ? upb_dyncast_enumdef(def) : NULL; + return upb_strtable_lookup(&s->syms, sym, &v) ? + unpack_def(v, UPB_DEFTYPE_ENUM) : NULL; } +#if 0 /* Given a symbol and the base symbol inside which it is defined, find the * symbol's definition in t. */ static upb_def *upb_resolvename(const upb_strtable *t, @@ -1311,11 +1181,10 @@ static upb_def *upb_resolvename(const upb_strtable *t, const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base, const char *sym) { - upb_def *ret = upb_resolvename(&s->symtab, base, sym); + upb_def *ret = upb_resolvename(&s->syms, base, sym); return ret; } -#if 0 /* Now using the table, resolve symbolic references for subdefs. */ upb_strtable_begin(&iter, &addtab); for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { @@ -1338,7 +1207,7 @@ const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base, * there, try existing defs. */ upb_def *subdef = upb_resolvename(&addtab, base, name); if (subdef == NULL) { - subdef = upb_resolvename(&s->symtab, base, name); + subdef = upb_resolvename(&s->syms, base, name); } if (subdef == NULL) { upb_status_seterrf( @@ -1352,76 +1221,258 @@ const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base, } #endif + +/* Code to build defs from descriptor protos. *********************************/ + +/* There is a question of how much validation to do here. It will be difficult + * to perfectly match the amount of validation performed by proto2. But since + * this code is used to directly build defs from Ruby (for example) we do need + * to validate important constraints like uniqueness of names and numbers. */ + +#define CHK(x) if (!(x)) return false +#define CHK_OOM(x) if (!(x)) { upb_upberr_setoom(ctx->status); return false; } + +typedef struct { + const upb_symtab *symtab; + const upb_filedef *file; /* File we are building. */ + upb_alloc *alloc; /* Allocate defs here. */ + upb_alloc *tmp; /* Alloc for addtab and any other tmp data. */ + upb_strtable *addtab; /* full_name -> packed def ptr for new defs. */ + upb_status *status; /* Record errors here. */ +} symtab_addctx; + +static const char *makefullname(const char *prefix, upb_stringview name) { + return NULL; +} + +static bool symtab_add(const symtab_addctx *ctx, const char *name, + upb_value v) { + upb_value tmp; + if (upb_strtable_lookup(ctx->addtab, name, &tmp) || + upb_strtable_lookup(&ctx->symtab->syms, name, &tmp)) { + upb_status_seterrf(ctx->status, "Duplicate symbol '%s'", name); + return false; + } + + CHK_OOM(upb_strtable_insert3(ctx->addtab, name, strlen(name), v, ctx->tmp)); + return true; +} + static bool create_oneofdef( - upb_symtab *s, const google_protobuf_OneofDescriptorProto *oneof_proto, - upb_msgdef *m, upb_status *s) { - upb_alloc *alloc = upb_arena_alloc(&s->arena); - upb_oneofdef *o = upb_malloc(alloc, sizeof(upb_oneofdef)); + const symtab_addctx *ctx, upb_msgdef *m, + const google_protobuf_OneofDescriptorProto *oneof_proto) { + upb_oneofdef *o = upb_malloc(ctx->alloc, sizeof(*o)); upb_stringview name = google_protobuf_OneofDescriptorProto_name(oneof_proto); upb_value o_ptr = upb_value_ptr(o); - CHK(o); - CHK(upb_inttable_init2(&o->itof, UPB_CTYPE_PTR, alloc)); - CHK(upb_strtable_init2(&o->ntof, UPB_CTYPE_PTR, alloc)); + CHK_OOM(o); + CHK_OOM(upb_inttable_init2(&o->itof, UPB_CTYPE_PTR, ctx->alloc)); + CHK_OOM(upb_strtable_init2(&o->ntof, UPB_CTYPE_PTR, ctx->alloc)); o->index = upb_strtable_count(&m->ntof); - o->name = upb_strdup2(name.data, name.size, alloc); + o->name = upb_strdup2(name.data, name.size, ctx->alloc); o->parent = m; - CHK(upb_strtable_insert3(&m->ntof, name.data, name.size, o_ptr, alloc)); + CHK_OOM(upb_strtable_insert3(&m->ntof, name.data, name.size, o_ptr, + ctx->alloc)); return true; } -static bool create_field( - upb_symtab *s, const google_protobuf_FieldDescriptorProto *field_proto, - upb_msgdef *m, upb_status *s) { - upb_alloc *alloc = upb_arena_alloc(&s->arena); - upb_fielddef *f = upb_malloc(alloc, sizeof(upb_fielddef)); - const google_protobuf_MessageOptions *options; +static bool parse_default(const char *str, size_t len, upb_fielddef *f) { + char *end; + switch (upb_fielddef_type(f)) { + case UPB_TYPE_INT32: { + long val = strtol(str, &end, 0); + CHK(val <= INT32_MAX && val >= INT32_MIN && errno != ERANGE && !*end); + f->defaultval.sint = val; + break; + } + case UPB_TYPE_ENUM: + case UPB_TYPE_INT64: { + /* XXX: Need to write our own strtoll, since it's not available in c89. */ + long long val = strtol(str, &end, 0); + CHK(val <= INT64_MAX && val >= INT64_MIN && errno != ERANGE && !*end); + f->defaultval.sint = val; + break; + } + case UPB_TYPE_UINT32: { + unsigned long val = strtoul(str, &end, 0); + CHK(val <= UINT32_MAX && errno != ERANGE && !*end); + f->defaultval.uint = val; + break; + } + case UPB_TYPE_UINT64: { + /* XXX: Need to write our own strtoull, since it's not available in c89. */ + unsigned long long val = strtoul(str, &end, 0); + CHK(val <= UINT64_MAX && errno != ERANGE && !*end); + f->defaultval.uint = val; + break; + } + case UPB_TYPE_DOUBLE: { + double val = strtod(str, &end); + CHK(errno != ERANGE && !*end); + f->defaultval.dbl = val; + break; + } + case UPB_TYPE_FLOAT: { + /* XXX: Need to write our own strtof, since it's not available in c89. */ + float val = strtod(str, &end); + CHK(errno != ERANGE && !*end); + f->defaultval.dbl = val; + break; + } + case UPB_TYPE_BOOL: { + if (strcmp(str, "false") == 0) { + f->defaultval.boolean = false; + } else if (strcmp(str, "true") == 0) { + f->defaultval.boolean = true; + } else { + return false; + } + } + case UPB_TYPE_STRING: + f->defaultval.str = newstr(str, len); + break; + case UPB_TYPE_BYTES: + /* XXX: need to interpret the C-escaped value. */ + f->defaultval.str = newstr(str, len); + case UPB_TYPE_MESSAGE: + /* Should not have a default value. */ + return false; + } + return true; +} + +static bool create_fielddef( + const symtab_addctx *ctx, const char *prefix, upb_msgdef *m, + const google_protobuf_FieldDescriptorProto *field_proto) { + upb_alloc *alloc = ctx->alloc; + upb_fielddef *f = upb_malloc(ctx->alloc, sizeof(*f)); + const google_protobuf_FieldOptions *options; + upb_stringview defaultval, name; + upb_value packed_v = pack_def(f, UPB_DEFTYPE_FIELD); + upb_value v = upb_value_constptr(f); + const char *shortname; + + CHK_OOM(f); + memset(f, 0, sizeof(*f)); + + name = google_protobuf_FieldDescriptorProto_name(field_proto); + + /* TODO(haberman): use hazzers. */ + if (name.size == 0 || f->number_ == 0) { + upb_status_seterrmsg(ctx->status, "field name or number were not set"); + return false; + } + + CHK(upb_isident(name, false, ctx->status)); + + f->full_name = makefullname(prefix, name); + f->type_ = (int)google_protobuf_FieldDescriptorProto_type(field_proto); + f->label_ = (int)google_protobuf_FieldDescriptorProto_label(field_proto); + f->number_ = google_protobuf_FieldDescriptorProto_number(field_proto); + shortname = shortdefname(f->full_name); + + if (f->number_ == 0 || f->number_ > UPB_MAX_FIELDNUMBER) { + upb_status_seterrf(ctx->status, "invalid field number (%u)", f->number_); + return false; + } +#if 0 + //f->oneof + //f->sub +#endif + + defaultval = google_protobuf_FieldDescriptorProto_default_value(field_proto); + + if (defaultval.data) { + CHK(parse_default(defaultval.data, defaultval.size, f)); + } + + options = google_protobuf_FieldDescriptorProto_options(field_proto); + + if (options) { + f->lazy_ = google_protobuf_FieldOptions_lazy(options); + f->packed_ = google_protobuf_FieldOptions_packed(options); + } + + if (m) { + /* direct message field. */ + if (!upb_strtable_insert3(&m->ntof, name.data, name.size, packed_v, alloc)) { + upb_status_seterrf(ctx->status, "duplicate name (%s)", shortname); + return false; + } + + if (!upb_inttable_insert2(&m->itof, f->number_, v, alloc)) { + upb_status_seterrf(ctx->status, "duplicate field number (%u)", f->number_); + return false; + } + + f->msgdef = m; + f->is_extension_ = false; + } else { + /* extension field. */ + f->is_extension_ = true; + } + + return true; +} + +static bool create_enumdef( + const symtab_addctx *ctx, const char *prefix, + const google_protobuf_EnumDescriptorProto *enum_proto) { + upb_enumdef *e = upb_malloc(ctx->alloc, sizeof(*e)); const upb_array *arr; + upb_stringview name; + size_t i; - CHK(f); + name = google_protobuf_EnumDescriptorProto_name(enum_proto); + CHK(upb_isident(name, false, ctx->status)); - f->msgdef = m; + e->full_name = makefullname(prefix, name); + e->defaultval = 0; - union { - int64_t sint; - uint64_t uint; - double dbl; - float flt; - void *bytes; - } defaultval; - const upb_msgdef *msgdef; - union { - const upb_msgdef *msgdef; - const upb_msgdef *enumdef; - } sub; - const upb_oneofdef *oneof; - bool is_extension_; - bool lazy_; - bool packed_; - upb_intfmt_t intfmt; - bool tagdelim; - upb_fieldtype_t type_; - upb_label_t label_; - uint32_t number_; - uint32_t selector_base; /* Used to index into a upb::Handlers table. */ - uint32_t index_; + CHK_OOM(e); + CHK_OOM(upb_strtable_init2(&e->ntoi, UPB_CTYPE_INT32, ctx->alloc)); + CHK_OOM(upb_inttable_init2(&e->iton, UPB_CTYPE_CSTR, ctx->alloc)); + + arr = google_protobuf_EnumDescriptorProto_value(enum_proto); + + for (i = 0; i < upb_array_size(arr); i++) { + const google_protobuf_EnumValueDescriptorProto *value = + upb_msgval_getptr(upb_array_get(arr, i)); + upb_stringview name = google_protobuf_EnumValueDescriptorProto_name(value); + char *name2 = upb_strdup2(name.data, name.size, ctx->alloc); + int32_t num = google_protobuf_EnumValueDescriptorProto_number(value); + upb_value v = upb_value_int32(num); + + CHK_OOM(name2 && upb_strtable_insert(&e->ntoi, name2, v)); + + if (!upb_inttable_lookup(&e->iton, num, NULL)) { + CHK_OOM(upb_inttable_insert(&e->iton, num, upb_value_cstr(name2))); + } + } + + return true; } -static bool create_msgdef(upb_symtab *s, - const google_protobuf_DescriptorProto *msg_proto, - upb_symtab *addtab, upb_status *status) { - upb_alloc *alloc = upb_arena_alloc(&s->arena); - upb_msgdef *m = upb_malloc(alloc, sizeof(upb_msgdef)); +static bool create_msgdef(const symtab_addctx *ctx, const char *prefix, + const google_protobuf_DescriptorProto *msg_proto) { + upb_msgdef *m = upb_malloc(ctx->alloc, sizeof(upb_msgdef)); const google_protobuf_MessageOptions *options; const upb_array *arr; + size_t i; + upb_stringview name; - CHK(m); - CHK(upb_inttable_init2(&m->itof, UPB_CTYPE_PTR, alloc)); - CHK(upb_strtable_init2(&m->ntof, UPB_CTYPE_PTR, alloc)); + CHK_OOM(m); + CHK_OOM(upb_inttable_init2(&m->itof, UPB_CTYPE_PTR, ctx->alloc)); + CHK_OOM(upb_strtable_init2(&m->ntof, UPB_CTYPE_PTR, ctx->alloc)); + name = google_protobuf_DescriptorProto_name(msg_proto); + CHK(upb_isident(name, false, ctx->status)); + + m->file = ctx->file; + m->full_name = makefullname(prefix, name); m->map_entry = false; options = google_protobuf_DescriptorProto_options(msg_proto); @@ -1434,118 +1485,181 @@ static bool create_msgdef(upb_symtab *s, for (i = 0; i < upb_array_size(arr); i++) { const google_protobuf_OneofDescriptorProto *oneof_proto = - (const void *)upb_array_get(arr, i); - CHK(create_oneofdef(s, oneof_proto, m, status)); + upb_msgval_getptr(upb_array_get(arr, i)); + CHK(create_oneofdef(ctx, m, oneof_proto)); } arr = google_protobuf_DescriptorProto_field(msg_proto); for (i = 0; i < upb_array_size(arr); i++) { const google_protobuf_FieldDescriptorProto *field_proto = - (const void *)upb_array_get(arr, i); - CHK(create_fielddef(s, field_proto, m, status)); + upb_msgval_getptr(upb_array_get(arr, i)); + CHK(create_fielddef(ctx, m->full_name, m, field_proto)); } + CHK(assign_msg_indices(m, ctx->status)); + assign_msg_wellknowntype(m); + symtab_add(ctx, m->full_name, pack_def(m, UPB_DEFTYPE_MSG)); + + /* This message is built. Now build nested messages and enums. */ + arr = google_protobuf_DescriptorProto_enum_type(msg_proto); for (i = 0; i < upb_array_size(arr); i++) { const google_protobuf_EnumDescriptorProto *enum_proto = - (const void *)upb_array_get(arr, i); - CHK(create_enumdef(s, enum_proto, addtab, status)); + upb_msgval_getptr(upb_array_get(arr, i)); + CHK(create_enumdef(ctx, m->full_name, enum_proto)); } arr = google_protobuf_DescriptorProto_nested_type(msg_proto); for (i = 0; i < upb_array_size(arr); i++) { const google_protobuf_DescriptorProto *msg_proto2 = - (const void *)upb_array_get(arr, i); - CHK(create_msgdef(s, msg_proto2, addtab, status)); + upb_msgval_getptr(upb_array_get(arr, i)); + CHK(create_msgdef(ctx, m->full_name, msg_proto2)); } return true; } -static char* strviewdup(upb_symtab *symtab, upb_stringview view) { +static char* strviewdup(const symtab_addctx *ctx, upb_stringview view) { if (view.size == 0) { return NULL; } - return upb_strdup2(view.data, view.size, upb_arena_alloc(&symtab->arena)); + return upb_strdup2(view.data, view.size, ctx->alloc); } -bool upb_symtab_addfile(upb_symtab *s, const char *buf, size_t len, - upb_status *status) { - upb_arena tmparena; - upb_strtable addtab; - upb_alloc *alloc = upb_arena_alloc(&s->arena); - upb_stringview serialized = upb_stringview_make(buf, len); - const google_protobuf_FileDescriptorProto *file_proto; +static bool build_filedef( + const symtab_addctx *ctx, upb_filedef *file, + const google_protobuf_FileDescriptorProto *file_proto) { const google_protobuf_FileOptions *file_options_proto; - upb_filedef *file = upb_malloc(alloc, sizeof(*file)); - const upb_array *arr; upb_strtable_iter iter; - size_t i; - - upb_arena_init(&tmparena); - upb_strtable_init2(&addtab, UPB_CTYPE_PTR, upb_arena_alloc(&tmparena)); - file_proto = - google_protobuf_FileDescriptorProto_parsenew(serialized, &tmparena); - + const upb_array *arr; + size_t i, n; + upb_stringview syntax, package; - if (!file_proto || !file) goto err; + package = google_protobuf_FileDescriptorProto_package(file_proto); + CHK(upb_isident(package, true, ctx->status)); file->name = - strviewdup(s, google_protobuf_FileDescriptorProto_name(file_proto)); - file->package = - strviewdup(s, google_protobuf_FileDescriptorProto_package(file_proto)); + strviewdup(ctx, google_protobuf_FileDescriptorProto_name(file_proto)); + file->package = strviewdup(ctx, package); file->phpprefix = NULL; file->phpnamespace = NULL; + syntax = google_protobuf_FileDescriptorProto_syntax(file_proto); + + if (upb_stringview_eql(syntax, upb_stringview_makez("proto2"))) { + file->syntax = UPB_SYNTAX_PROTO2; + } else if (upb_stringview_eql(syntax, upb_stringview_makez("proto3"))) { + file->syntax = UPB_SYNTAX_PROTO3; + } else { + upb_status_seterrf(ctx->status, "Invalid syntax '%s'", syntax); + return false; + } + + /* Read options. */ + file_options_proto = google_protobuf_FileDescriptorProto_options(file_proto); + if (file_options_proto) { - file->phpprefix = - strviewdup(s, google_protobuf_FileOptions_php_class_prefix(file_proto)); - file->phpnamespace = - strviewdup(s, google_protobuf_FileOptions_php_namespace(file_proto)); + file->phpprefix = strviewdup( + ctx, google_protobuf_FileOptions_php_class_prefix(file_options_proto)); + file->phpnamespace = strviewdup( + ctx, google_protobuf_FileOptions_php_namespace(file_options_proto)); } - arr = google_protobuf_FileDescriptorProto_message_type(file_proto); + /* Resolve dependencies. */ + + arr = google_protobuf_FileDescriptorProto_dependency(file_proto); + n = upb_array_size(arr); + file->deps = upb_malloc(ctx->alloc, sizeof(*file->deps) * n) ; + CHK_OOM(file->deps); + for (i = 0; i < n; i++) { + upb_stringview dep_name = upb_msgval_getstr(upb_array_get(arr, i)); + upb_value v; + if (!upb_strtable_lookup2(&ctx->symtab->files, dep_name.data, + dep_name.size, &v)) { + upb_status_seterrf(ctx->status, + "Depends on file '%s', but it has not been loaded", + dep_name.data); + return false; + } + file->deps[i] = upb_value_getconstptr(v); + } + /* Create messages. */ + + arr = google_protobuf_FileDescriptorProto_message_type(file_proto); for (i = 0; i < upb_array_size(arr); i++) { const google_protobuf_DescriptorProto *msg_proto = - (const void *)upb_array_get(arr, i); - if (!create_msgdef(s, msg_proto, &addtab, status)) goto err; + upb_msgval_getptr(upb_array_get(arr, i)); + CHK(create_msgdef(ctx, file->package, msg_proto)); } - arr = google_protobuf_FileDescriptorProto_enum_type(file_proto); + /* Create enums. */ + arr = google_protobuf_FileDescriptorProto_enum_type(file_proto); for (i = 0; i < upb_array_size(arr); i++) { const google_protobuf_EnumDescriptorProto *enum_proto = - (const void *)upb_array_get(arr, i); - if (!create_enumdef(s, enum_proto, &addtab, status)) goto err; + upb_msgval_getptr(upb_array_get(arr, i)); + CHK(create_enumdef(ctx, file->package, enum_proto)); } /* Now that all names are in the table, resolve references. */ - upb_strtable_begin(&iter, &addtab); + upb_strtable_begin(&iter, ctx->addtab); for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { } - /* Success; add addtab to symtab. */ - upb_strtable_begin(&iter, &addtab); + return true; +} + +static bool upb_symtab_addtotabs(upb_symtab *s, symtab_addctx *ctx, + upb_status *status) { + const upb_filedef *file = ctx->file; + upb_alloc *alloc = upb_arena_alloc(&s->arena); + upb_strtable_iter iter; + + CHK_OOM(upb_strtable_insert3(&s->files, file->name, strlen(file->name), + upb_value_constptr(file), alloc)); + + upb_strtable_begin(&iter, ctx->addtab); for (; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { const char *key = upb_strtable_iter_key(&iter); - size_t keylen = upb_strtable_iter_keylen(&iter); + size_t keylen = upb_strtable_iter_keylength(&iter); upb_value value = upb_strtable_iter_value(&iter); - upb_strtable_insert3(&s->symtab, key, keylen, value, alloc); + CHK_OOM(upb_strtable_insert3(&s->syms, key, keylen, value, alloc)); } return true; +} + +bool upb_symtab_addfile(upb_symtab *s, + const google_protobuf_FileDescriptorProto *file_proto, + upb_status *status) { + upb_arena tmparena; + upb_strtable addtab; + symtab_addctx ctx; + upb_alloc *alloc = upb_arena_alloc(&s->arena); + upb_filedef *file = upb_malloc(alloc, sizeof(*file)); + bool ok; + + ctx.file = file; + ctx.alloc = alloc; + ctx.tmp = upb_arena_alloc(&tmparena); + ctx.addtab = &addtab; + ctx.status = status; + + upb_arena_init(&tmparena); + + ok = file && + upb_strtable_init2(&addtab, UPB_CTYPE_PTR, ctx.tmp) && + build_filedef(&ctx, file, file_proto) && + upb_symtab_addtotabs(s, &ctx, status); -err: upb_arena_uninit(&tmparena); - return false; + return ok; } -bool upb_symtab_addset(upb_symtab *s, const char *buf, size_t len, - upb_status *status) { - return true; -} +#undef CHK +#undef CHK_OOM diff --git a/upb/def.h b/upb/def.h index 2551c86..4a7342e 100644 --- a/upb/def.h +++ b/upb/def.h @@ -19,6 +19,7 @@ #include "upb/upb.h" #include "upb/table.int.h" +#include "google/protobuf/descriptor.upb.h" #ifdef __cplusplus #include @@ -665,6 +666,13 @@ const char *upb_filedef_package(const upb_filedef *f); const char *upb_filedef_phpprefix(const upb_filedef *f); const char *upb_filedef_phpnamespace(const upb_filedef *f); upb_syntax_t upb_filedef_syntax(const upb_filedef *f); +int upb_filedef_depcount(const upb_filedef *f); +int upb_filedef_msgcount(const upb_filedef *f); +int upb_filedef_enumcount(const upb_filedef *f); +const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i); +const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i); +const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i); + UPB_END_EXTERN_C @@ -708,10 +716,9 @@ const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym); const upb_msgdef *upb_symtab_lookupmsg2( const upb_symtab *s, const char *sym, size_t len); const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym); -bool upb_symtab_addfile(upb_symtab *s, const char *buf, size_t len, +bool upb_symtab_addfile(upb_symtab *s, + const google_protobuf_FileDescriptorProto* file, upb_status *status); -bool upb_symtab_addset(upb_symtab *s, const char *buf, size_t len, - upb_status *status); UPB_END_EXTERN_C diff --git a/upb/handlers.c b/upb/handlers.c index 7382e0c..fa75a48 100644 --- a/upb/handlers.c +++ b/upb/handlers.c @@ -84,7 +84,7 @@ static upb_handlers *newformsg(const upb_msgdef *m, const void *owner, if (!upb_fielddef_issubmsg(f)) continue; - subdef = upb_downcast_msgdef(upb_fielddef_subdef(f)); + subdef = upb_fielddef_msgsubdef(f); if (upb_inttable_lookupptr(&s->tab, subdef, &subm_ent)) { upb_handlers_setsubhandlers(h, f, upb_value_getptr(subm_ent)); } else { @@ -392,7 +392,7 @@ bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f, UPB_ASSERT(!upb_handlers_isfrozen(h)); UPB_ASSERT(upb_fielddef_issubmsg(f)); if (SUBH_F(h, f)) return false; /* Can't reset. */ - if (upb_msgdef_upcast(upb_handlers_msgdef(sub)) != upb_fielddef_subdef(f)) { + if (upb_handlers_msgdef(sub) != upb_fielddef_msgsubdef(f)) { return false; } SUBH_F(h, f) = sub; diff --git a/upb/json/parser.c b/upb/json/parser.c index 83590a1..85919e7 100644 --- a/upb/json/parser.c +++ b/upb/json/parser.c @@ -264,10 +264,6 @@ struct upb_json_parsermethod { upb_byteshandler input_handler_; - /* Mainly for the purposes of refcounting, so all the fielddefs we point - * to stay alive. */ - const upb_msgdef *msg; - /* Keys are upb_msgdef*, values are upb_strtable (json_name -> fielddef) */ upb_inttable name_tables; }; @@ -1327,8 +1323,7 @@ static bool end_stringval_nontop(upb_json_parser *p) { case UPB_TYPE_ENUM: { /* Resolve enum symbolic name to integer value. */ - const upb_enumdef *enumdef = - (const upb_enumdef*)upb_fielddef_subdef(p->top->f); + const upb_enumdef *enumdef = upb_fielddef_enumsubdef(p->top->f); size_t len; const char *buf = accumulate_getptr(p, &len); @@ -2414,11 +2409,11 @@ static bool is_string_wrapper_object(upb_json_parser *p) { * final state once, when the closing '"' is seen. */ -#line 2576 "upb/json/parser.rl" +#line 2571 "upb/json/parser.rl" -#line 2422 "upb/json/parser.c" +#line 2417 "upb/json/parser.c" static const char _json_actions[] = { 0, 1, 0, 1, 1, 1, 3, 1, 4, 1, 6, 1, 7, 1, 8, 1, @@ -2665,7 +2660,7 @@ static const int json_en_value_machine = 75; static const int json_en_main = 1; -#line 2579 "upb/json/parser.rl" +#line 2574 "upb/json/parser.rl" size_t parse(void *closure, const void *hd, const char *buf, size_t size, const upb_bufhandle *handle) { @@ -2688,7 +2683,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size, capture_resume(parser, buf); -#line 2692 "upb/json/parser.c" +#line 2687 "upb/json/parser.c" { int _klen; unsigned int _trans; @@ -2763,83 +2758,83 @@ _match: switch ( *_acts++ ) { case 1: -#line 2427 "upb/json/parser.rl" +#line 2422 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 2: -#line 2429 "upb/json/parser.rl" +#line 2424 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 23;goto _again;} } break; case 3: -#line 2433 "upb/json/parser.rl" +#line 2428 "upb/json/parser.rl" { start_text(parser, p); } break; case 4: -#line 2434 "upb/json/parser.rl" +#line 2429 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_text(parser, p)); } break; case 5: -#line 2440 "upb/json/parser.rl" +#line 2435 "upb/json/parser.rl" { start_hex(parser); } break; case 6: -#line 2441 "upb/json/parser.rl" +#line 2436 "upb/json/parser.rl" { hexdigit(parser, p); } break; case 7: -#line 2442 "upb/json/parser.rl" +#line 2437 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_hex(parser)); } break; case 8: -#line 2448 "upb/json/parser.rl" +#line 2443 "upb/json/parser.rl" { CHECK_RETURN_TOP(escape(parser, p)); } break; case 9: -#line 2454 "upb/json/parser.rl" +#line 2449 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 10: -#line 2466 "upb/json/parser.rl" +#line 2461 "upb/json/parser.rl" { start_duration_base(parser, p); } break; case 11: -#line 2467 "upb/json/parser.rl" +#line 2462 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_duration_base(parser, p)); } break; case 12: -#line 2469 "upb/json/parser.rl" +#line 2464 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 13: -#line 2474 "upb/json/parser.rl" +#line 2469 "upb/json/parser.rl" { start_timestamp_base(parser, p); } break; case 14: -#line 2475 "upb/json/parser.rl" +#line 2470 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_base(parser, p)); } break; case 15: -#line 2477 "upb/json/parser.rl" +#line 2472 "upb/json/parser.rl" { start_timestamp_fraction(parser, p); } break; case 16: -#line 2478 "upb/json/parser.rl" +#line 2473 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); } break; case 17: -#line 2480 "upb/json/parser.rl" +#line 2475 "upb/json/parser.rl" { start_timestamp_zone(parser, p); } break; case 18: -#line 2481 "upb/json/parser.rl" +#line 2476 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); } break; case 19: -#line 2483 "upb/json/parser.rl" +#line 2478 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 20: -#line 2488 "upb/json/parser.rl" +#line 2483 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) { {stack[top++] = cs; cs = 47;goto _again;} @@ -2851,11 +2846,11 @@ _match: } break; case 21: -#line 2499 "upb/json/parser.rl" +#line 2494 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 75;goto _again;} } break; case 22: -#line 2504 "upb/json/parser.rl" +#line 2499 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { start_any_member(parser, p); @@ -2865,11 +2860,11 @@ _match: } break; case 23: -#line 2511 "upb/json/parser.rl" +#line 2506 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_membername(parser)); } break; case 24: -#line 2514 "upb/json/parser.rl" +#line 2509 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { end_any_member(parser, p); @@ -2879,7 +2874,7 @@ _match: } break; case 25: -#line 2525 "upb/json/parser.rl" +#line 2520 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { start_any_object(parser, p); @@ -2889,7 +2884,7 @@ _match: } break; case 26: -#line 2534 "upb/json/parser.rl" +#line 2529 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { CHECK_RETURN_TOP(end_any_object(parser, p)); @@ -2899,54 +2894,54 @@ _match: } break; case 27: -#line 2546 "upb/json/parser.rl" +#line 2541 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_array(parser)); } break; case 28: -#line 2550 "upb/json/parser.rl" +#line 2545 "upb/json/parser.rl" { end_array(parser); } break; case 29: -#line 2555 "upb/json/parser.rl" +#line 2550 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_number(parser, p)); } break; case 30: -#line 2556 "upb/json/parser.rl" +#line 2551 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 31: -#line 2558 "upb/json/parser.rl" +#line 2553 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_stringval(parser)); } break; case 32: -#line 2559 "upb/json/parser.rl" +#line 2554 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_stringval(parser)); } break; case 33: -#line 2561 "upb/json/parser.rl" +#line 2556 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, true)); } break; case 34: -#line 2563 "upb/json/parser.rl" +#line 2558 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, false)); } break; case 35: -#line 2565 "upb/json/parser.rl" +#line 2560 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_null(parser)); } break; case 36: -#line 2567 "upb/json/parser.rl" +#line 2562 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_subobject_full(parser)); } break; case 37: -#line 2568 "upb/json/parser.rl" +#line 2563 "upb/json/parser.rl" { end_subobject_full(parser); } break; case 38: -#line 2573 "upb/json/parser.rl" +#line 2568 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; -#line 2950 "upb/json/parser.c" +#line 2945 "upb/json/parser.c" } } @@ -2963,32 +2958,32 @@ _again: while ( __nacts-- > 0 ) { switch ( *__acts++ ) { case 0: -#line 2425 "upb/json/parser.rl" +#line 2420 "upb/json/parser.rl" { p--; {cs = stack[--top]; if ( p == pe ) goto _test_eof; goto _again;} } break; case 30: -#line 2556 "upb/json/parser.rl" +#line 2551 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 33: -#line 2561 "upb/json/parser.rl" +#line 2556 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, true)); } break; case 34: -#line 2563 "upb/json/parser.rl" +#line 2558 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, false)); } break; case 35: -#line 2565 "upb/json/parser.rl" +#line 2560 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_null(parser)); } break; case 37: -#line 2568 "upb/json/parser.rl" +#line 2563 "upb/json/parser.rl" { end_subobject_full(parser); } break; -#line 2992 "upb/json/parser.c" +#line 2987 "upb/json/parser.c" } } } @@ -2996,7 +2991,7 @@ goto _again;} } _out: {} } -#line 2601 "upb/json/parser.rl" +#line 2596 "upb/json/parser.rl" if (p != pe) { upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p); @@ -3044,13 +3039,13 @@ static void json_parser_reset(upb_json_parser *p) { /* Emit Ragel initialization of the parser. */ -#line 3048 "upb/json/parser.c" +#line 3043 "upb/json/parser.c" { cs = json_start; top = 0; } -#line 2648 "upb/json/parser.rl" +#line 2643 "upb/json/parser.rl" p->current_state = cs; p->parser_top = top; accumulate_clear(p); @@ -3060,13 +3055,6 @@ static void json_parser_reset(upb_json_parser *p) { upb_status_clear(&p->status); } -static void visit_json_parsermethod(const upb_refcounted *r, - upb_refcounted_visit *visit, - void *closure) { - const upb_json_parsermethod *method = (upb_json_parsermethod*)r; - visit(r, upb_msgdef_upcast2(method->msg), closure); -} - static void free_json_parsermethod(upb_refcounted *r) { upb_json_parsermethod *method = (upb_json_parsermethod*)r; @@ -3183,14 +3171,10 @@ upb_bytessink *upb_json_parser_input(upb_json_parser *p) { upb_json_parsermethod *upb_json_parsermethod_new(const upb_msgdef* md, const void* owner) { - static const struct upb_refcounted_vtbl vtbl = {visit_json_parsermethod, - free_json_parsermethod}; + static const struct upb_refcounted_vtbl vtbl = {NULL, free_json_parsermethod}; upb_json_parsermethod *ret = upb_gmalloc(sizeof(*ret)); upb_refcounted_init(upb_json_parsermethod_upcast_mutable(ret), &vtbl, owner); - ret->msg = md; - upb_ref2(md, ret); - upb_byteshandler_init(&ret->input_handler_); upb_byteshandler_setstring(&ret->input_handler_, parse, ret); upb_byteshandler_setendstr(&ret->input_handler_, end, ret); diff --git a/upb/json/parser.h b/upb/json/parser.h index fb5fd2f..91b08d8 100644 --- a/upb/json/parser.h +++ b/upb/json/parser.h @@ -52,7 +52,8 @@ class upb::json::ParserMethod { /* Include base methods from upb::ReferenceCounted. */ UPB_REFCOUNTED_CPPMETHODS - /* Returns handlers for parsing according to the specified schema. */ + /* Returns handlers for parsing according to the specified schema. + * The MessageDef must outlive the ParserMethod. */ static reffed_ptr New(const upb::MessageDef* md); /* The destination handlers that are statically bound to this method. diff --git a/upb/json/parser.rl b/upb/json/parser.rl index a7bdb3f..9ceb816 100644 --- a/upb/json/parser.rl +++ b/upb/json/parser.rl @@ -262,10 +262,6 @@ struct upb_json_parsermethod { upb_byteshandler input_handler_; - /* Mainly for the purposes of refcounting, so all the fielddefs we point - * to stay alive. */ - const upb_msgdef *msg; - /* Keys are upb_msgdef*, values are upb_strtable (json_name -> fielddef) */ upb_inttable name_tables; }; @@ -1325,8 +1321,7 @@ static bool end_stringval_nontop(upb_json_parser *p) { case UPB_TYPE_ENUM: { /* Resolve enum symbolic name to integer value. */ - const upb_enumdef *enumdef = - (const upb_enumdef*)upb_fielddef_subdef(p->top->f); + const upb_enumdef *enumdef = upb_fielddef_enumsubdef(p->top->f); size_t len; const char *buf = accumulate_getptr(p, &len); @@ -2654,13 +2649,6 @@ static void json_parser_reset(upb_json_parser *p) { upb_status_clear(&p->status); } -static void visit_json_parsermethod(const upb_refcounted *r, - upb_refcounted_visit *visit, - void *closure) { - const upb_json_parsermethod *method = (upb_json_parsermethod*)r; - visit(r, upb_msgdef_upcast2(method->msg), closure); -} - static void free_json_parsermethod(upb_refcounted *r) { upb_json_parsermethod *method = (upb_json_parsermethod*)r; @@ -2777,14 +2765,10 @@ upb_bytessink *upb_json_parser_input(upb_json_parser *p) { upb_json_parsermethod *upb_json_parsermethod_new(const upb_msgdef* md, const void* owner) { - static const struct upb_refcounted_vtbl vtbl = {visit_json_parsermethod, - free_json_parsermethod}; + static const struct upb_refcounted_vtbl vtbl = {NULL, free_json_parsermethod}; upb_json_parsermethod *ret = upb_gmalloc(sizeof(*ret)); upb_refcounted_init(upb_json_parsermethod_upcast_mutable(ret), &vtbl, owner); - ret->msg = md; - upb_ref2(md, ret); - upb_byteshandler_init(&ret->input_handler_); upb_byteshandler_setstring(&ret->input_handler_, parse, ret); upb_byteshandler_setendstr(&ret->input_handler_, end, ret); diff --git a/upb/json/printer.c b/upb/json/printer.c index fe306d4..00438aa 100644 --- a/upb/json/printer.c +++ b/upb/json/printer.c @@ -585,7 +585,7 @@ static void set_enum_hd(upb_handlers *h, bool preserve_fieldnames, upb_handlerattr *attr) { EnumHandlerData *hd = upb_gmalloc(sizeof(EnumHandlerData)); - hd->enumdef = (const upb_enumdef *)upb_fielddef_subdef(f); + hd->enumdef = upb_fielddef_enumsubdef(f); hd->keyname = newstrpc(h, f, preserve_fieldnames); upb_handlers_addcleanup(h, hd, upb_gfree); upb_handlerattr_sethandlerdata(attr, hd); diff --git a/upb/msg.h b/upb/msg.h index 3f0aa0b..f707795 100644 --- a/upb/msg.h +++ b/upb/msg.h @@ -22,6 +22,7 @@ #define UPB_MSG_H_ #include +#include #include "upb/upb.h" #ifdef __cplusplus @@ -86,6 +87,14 @@ UPB_INLINE upb_stringview upb_stringview_make(const char *data, size_t size) { return ret; } +UPB_INLINE upb_stringview upb_stringview_makez(const char *data) { + return upb_stringview_make(data, strlen(data)); +} + +UPB_INLINE bool upb_stringview_eql(upb_stringview a, upb_stringview b) { + return a.size == b.size && memcmp(a.data, b.data, a.size) == 0; +} + #define UPB_STRINGVIEW_INIT(ptr, len) {ptr, len} diff --git a/upb/pb/textprinter.c b/upb/pb/textprinter.c index abfc2eb..e8033f8 100644 --- a/upb/pb/textprinter.c +++ b/upb/pb/textprinter.c @@ -183,7 +183,7 @@ static bool textprinter_putenum(void *closure, const void *handler_data, int32_t val) { upb_textprinter *p = closure; const upb_fielddef *f = handler_data; - const upb_enumdef *enum_def = upb_downcast_enumdef(upb_fielddef_subdef(f)); + const upb_enumdef *enum_def = upb_fielddef_enumsubdef(f); const char *label = upb_enumdef_iton(enum_def, val); if (label) { indent(p); @@ -292,7 +292,7 @@ static void onmreg(const void *c, upb_handlers *h) { break; case UPB_TYPE_MESSAGE: { const char *name = - upb_fielddef_istagdelim(f) + upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_GROUP ? shortname(upb_msgdef_fullname(upb_fielddef_msgsubdef(f))) : upb_fielddef_name(f); upb_handlerattr_sethandlerdata(&attr, name); diff --git a/upb/structdefs.int.h b/upb/structdefs.int.h deleted file mode 100644 index cf8bd1d..0000000 --- a/upb/structdefs.int.h +++ /dev/null @@ -1,196 +0,0 @@ -/* -** This file contains definitions of structs that should be considered private -** and NOT stable across versions of upb. -** -** The only reason they are declared here and not in .c files is to allow upb -** and the application (if desired) to embed statically-initialized instances -** of structures like defs. -** -** If you include this file, all guarantees of ABI compatibility go out the -** window! Any code that includes this file needs to recompile against the -** exact same version of upb that they are linking against. -** -** You also need to recompile if you change the value of the UPB_DEBUG_REFS -** flag. -*/ - -#include "upb/def.h" - -#ifndef UPB_STATICINIT_H_ -#define UPB_STATICINIT_H_ - -#ifdef __cplusplus -/* Because of how we do our typedefs, this header can't be included from C++. */ -#error This file cannot be included from C++ -#endif - -/* upb_refcounted *************************************************************/ - - -/* upb_def ********************************************************************/ - -struct upb_def { - upb_refcounted base; - - const char *fullname; - const upb_filedef* file; - char type; /* A upb_deftype_t (char to save space) */ - - /* Used as a flag during the def's mutable stage. Must be false unless - * it is currently being used by a function on the stack. This allows - * us to easily determine which defs were passed into the function's - * current invocation. */ - bool came_from_user; -}; - -#define UPB_DEF_INIT(name, type, vtbl, refs, ref2s) \ - { UPB_REFCOUNT_INIT(vtbl, refs, ref2s), name, NULL, type, false } - - -/* upb_fielddef ***************************************************************/ - -struct upb_fielddef { - upb_def base; - - union { - int64_t sint; - uint64_t uint; - double dbl; - float flt; - void *bytes; - } defaultval; - union { - const upb_msgdef *def; /* If !msg_is_symbolic. */ - char *name; /* If msg_is_symbolic. */ - } msg; - union { - const upb_def *def; /* If !subdef_is_symbolic. */ - char *name; /* If subdef_is_symbolic. */ - } sub; /* The msgdef or enumdef for this field, if upb_hassubdef(f). */ - bool subdef_is_symbolic; - bool msg_is_symbolic; - const upb_oneofdef *oneof; - bool default_is_string; - bool type_is_set_; /* False until type is explicitly set. */ - bool is_extension_; - bool lazy_; - bool packed_; - upb_intfmt_t intfmt; - bool tagdelim; - upb_fieldtype_t type_; - upb_label_t label_; - uint32_t number_; - uint32_t selector_base; /* Used to index into a upb::Handlers table. */ - uint32_t index_; -}; - -extern const struct upb_refcounted_vtbl upb_fielddef_vtbl; - -#define UPB_FIELDDEF_INIT(label, type, intfmt, tagdelim, is_extension, lazy, \ - packed, name, num, msgdef, subdef, selector_base, \ - index, defaultval, refs, ref2s) \ - { \ - UPB_DEF_INIT(name, UPB_DEF_FIELD, &upb_fielddef_vtbl, refs, ref2s), \ - defaultval, {msgdef}, {subdef}, NULL, false, false, \ - type == UPB_TYPE_STRING || type == UPB_TYPE_BYTES, true, is_extension, \ - lazy, packed, intfmt, tagdelim, type, label, num, selector_base, index \ - } - - -/* upb_msgdef *****************************************************************/ - -struct upb_msgdef { - upb_def base; - - size_t selector_count; - uint32_t submsg_field_count; - - /* Tables for looking up fields by number and name. */ - upb_inttable itof; /* int to field */ - upb_strtable ntof; /* name to field/oneof */ - - /* Is this a map-entry message? */ - bool map_entry; - - /* Whether this message has proto2 or proto3 semantics. */ - upb_syntax_t syntax; - - /* Type of well known type message. UPB_WELLKNOWN_UNSPECIFIED for - * non-well-known message. */ - upb_wellknowntype_t well_known_type; - - /* TODO(haberman): proper extension ranges (there can be multiple). */ -}; - -extern const struct upb_refcounted_vtbl upb_msgdef_vtbl; - -/* TODO: also support static initialization of the oneofs table. This will be - * needed if we compile in descriptors that contain oneofs. */ -#define UPB_MSGDEF_INIT(name, selector_count, submsg_field_count, itof, ntof, \ - map_entry, syntax, well_known_type, refs, ref2s) \ - { \ - UPB_DEF_INIT(name, UPB_DEF_MSG, &upb_fielddef_vtbl, refs, ref2s), \ - selector_count, submsg_field_count, itof, ntof, map_entry, syntax, \ - well_known_type \ - } - - -/* upb_enumdef ****************************************************************/ - -struct upb_enumdef { - upb_def base; - - upb_strtable ntoi; - upb_inttable iton; - int32_t defaultval; -}; - -extern const struct upb_refcounted_vtbl upb_enumdef_vtbl; - -#define UPB_ENUMDEF_INIT(name, ntoi, iton, defaultval, refs, ref2s) \ - { UPB_DEF_INIT(name, UPB_DEF_ENUM, &upb_enumdef_vtbl, refs, ref2s), ntoi, \ - iton, defaultval } - - -/* upb_oneofdef ***************************************************************/ - -struct upb_oneofdef { - upb_refcounted base; - - uint32_t index; /* Index within oneofs. */ - const char *name; - upb_strtable ntof; - upb_inttable itof; - const upb_msgdef *parent; -}; - -extern const struct upb_refcounted_vtbl upb_oneofdef_vtbl; - -#define UPB_ONEOFDEF_INIT(name, ntof, itof, refs, ref2s) \ - { UPB_REFCOUNT_INIT(&upb_oneofdef_vtbl, refs, ref2s), 0, name, ntof, itof } - - -/* upb_symtab *****************************************************************/ - -struct upb_symtab { - upb_refcounted base; - - upb_strtable symtab; -}; - -struct upb_filedef { - upb_refcounted base; - - const char *name; - const char *package; - const char *phpprefix; - const char *phpnamespace; - upb_syntax_t syntax; - - upb_inttable defs; - upb_inttable deps; -}; - -extern const struct upb_refcounted_vtbl upb_filedef_vtbl; - -#endif /* UPB_STATICINIT_H_ */ -- cgit v1.2.3 From cf0a89ed69561d73210056566272b27844a95782 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Thu, 13 Dec 2018 07:41:56 -0800 Subject: Updated to use the new array accessors. --- upb/bindings/lua/def.c | 14 ++---- upb/def.c | 133 +++++++++++++++++++++---------------------------- 2 files changed, 63 insertions(+), 84 deletions(-) (limited to 'upb/bindings') diff --git a/upb/bindings/lua/def.c b/upb/bindings/lua/def.c index 1fde212..00b75c9 100644 --- a/upb/bindings/lua/def.c +++ b/upb/bindings/lua/def.c @@ -634,10 +634,9 @@ static int lupb_symtab_gc(lua_State *L) { * serialized string once we have a good story for vending compiled-in * messages. */ static int lupb_symtab_add(lua_State *L) { - size_t len; upb_arena *arena; - size_t i; - upb_array *file_arr; + size_t i, n, len; + const google_protobuf_FileDescriptorProto *const *files; google_protobuf_FileDescriptorSet *set; upb_symtab *s = lupb_symtab_check(L, 1); const char *str = luaL_checklstring(L, 2, &len); @@ -652,12 +651,9 @@ static int lupb_symtab_add(lua_State *L) { luaL_argerror(L, 2, "failed to parse descriptor"); } - file_arr = (upb_array*)google_protobuf_FileDescriptorSet_file(set); - for (i = 0; i < upb_array_size(file_arr); i++) { - upb_msgval entry = upb_array_get(file_arr, i); - google_protobuf_FileDescriptorProto *file = - (void *)upb_msgval_getmsg(entry); - CHK(upb_symtab_addfile(s, file, &status)); + files = google_protobuf_FileDescriptorSet_file(set, &n); + for (i = 0; i < n; i++) { + CHK(upb_symtab_addfile(s, files[i], &status)); } return 0; diff --git a/upb/def.c b/upb/def.c index 9a4d766..8029c92 100644 --- a/upb/def.c +++ b/upb/def.c @@ -1232,9 +1232,9 @@ static bool create_enumdef( const symtab_addctx *ctx, const char *prefix, const google_protobuf_EnumDescriptorProto *enum_proto) { upb_enumdef *e; - const upb_array *arr; + const google_protobuf_EnumValueDescriptorProto *const *values; upb_stringview name; - size_t i; + size_t i, n; name = google_protobuf_EnumDescriptorProto_name(enum_proto); CHK(upb_isident(name, false, ctx->status)); @@ -1248,11 +1248,10 @@ static bool create_enumdef( e->defaultval = 0; - arr = google_protobuf_EnumDescriptorProto_value(enum_proto); + values = google_protobuf_EnumDescriptorProto_value(enum_proto, &n); - for (i = 0; i < upb_array_size(arr); i++) { - const google_protobuf_EnumValueDescriptorProto *value = - upb_msgval_getptr(upb_array_get(arr, i)); + for (i = 0; i < n; i++) { + const google_protobuf_EnumValueDescriptorProto *value = values[i]; upb_stringview name = google_protobuf_EnumValueDescriptorProto_name(value); char *name2 = upb_strdup2(name.data, name.size, ctx->alloc); int32_t num = google_protobuf_EnumValueDescriptorProto_number(value); @@ -1277,7 +1276,10 @@ static bool create_msgdef(const symtab_addctx *ctx, const char *prefix, const google_protobuf_DescriptorProto *msg_proto) { upb_msgdef *m; const google_protobuf_MessageOptions *options; - const upb_array *arr; + const google_protobuf_OneofDescriptorProto *const *oneofs; + const google_protobuf_FieldDescriptorProto *const *fields; + const google_protobuf_EnumDescriptorProto *const *enums; + const google_protobuf_DescriptorProto *const *msgs; size_t i, n; upb_stringview name; @@ -1300,21 +1302,16 @@ static bool create_msgdef(const symtab_addctx *ctx, const char *prefix, m->map_entry = google_protobuf_MessageOptions_map_entry(options); } - arr = google_protobuf_DescriptorProto_oneof_decl(msg_proto); + oneofs = google_protobuf_DescriptorProto_oneof_decl(msg_proto, &n); m->oneof_count = 0; - n = upb_array_size(arr); m->oneofs = upb_malloc(ctx->alloc, sizeof(*m->oneofs) * n); for (i = 0; i < n; i++) { - const google_protobuf_OneofDescriptorProto *oneof_proto = - upb_msgval_getptr(upb_array_get(arr, i)); - CHK(create_oneofdef(ctx, m, oneof_proto)); + CHK(create_oneofdef(ctx, m, oneofs[i])); } - arr = google_protobuf_DescriptorProto_field(msg_proto); - for (i = 0; i < upb_array_size(arr); i++) { - const google_protobuf_FieldDescriptorProto *field_proto = - upb_msgval_getptr(upb_array_get(arr, i)); - CHK(create_fielddef(ctx, m->full_name, m, field_proto)); + fields = google_protobuf_DescriptorProto_field(msg_proto, &n); + for (i = 0; i < n; i++) { + CHK(create_fielddef(ctx, m->full_name, m, fields[i])); } CHK(assign_msg_indices(m, ctx->status)); @@ -1322,18 +1319,14 @@ static bool create_msgdef(const symtab_addctx *ctx, const char *prefix, /* This message is built. Now build nested messages and enums. */ - arr = google_protobuf_DescriptorProto_enum_type(msg_proto); - for (i = 0; i < upb_array_size(arr); i++) { - const google_protobuf_EnumDescriptorProto *enum_proto = - upb_msgval_getptr(upb_array_get(arr, i)); - CHK(create_enumdef(ctx, m->full_name, enum_proto)); + enums = google_protobuf_DescriptorProto_enum_type(msg_proto, &n); + for (i = 0; i < n; i++) { + CHK(create_enumdef(ctx, m->full_name, enums[i])); } - arr = google_protobuf_DescriptorProto_nested_type(msg_proto); - for (i = 0; i < upb_array_size(arr); i++) { - const google_protobuf_DescriptorProto *msg_proto2 = - upb_msgval_getptr(upb_array_get(arr, i)); - CHK(create_msgdef(ctx, m->full_name, msg_proto2)); + msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n); + for (i = 0; i < n; i++) { + CHK(create_msgdef(ctx, m->full_name, msgs[i])); } return true; @@ -1352,45 +1345,39 @@ typedef struct { int ext_count; } decl_counts; -static void count_types_in_msg( - const google_protobuf_DescriptorProto *msg_proto, - decl_counts *counts) { - const upb_array *arr; - size_t i; +static void count_types_in_msg(const google_protobuf_DescriptorProto *msg_proto, + decl_counts *counts) { + const google_protobuf_DescriptorProto *const *msgs; + size_t i, n; - arr = google_protobuf_DescriptorProto_nested_type(msg_proto); - if (arr) { - for (i = 0; i < upb_array_size(arr); i++) { - count_types_in_msg(upb_msgval_getptr(upb_array_get(arr, i)), counts); - } + msgs = google_protobuf_DescriptorProto_nested_type(msg_proto, &n); + for (i = 0; i < n; i++) { + count_types_in_msg(msgs[i], counts); } - arr = google_protobuf_DescriptorProto_enum_type(msg_proto); - if (arr) { - counts->enum_count += upb_array_size(arr); - } + google_protobuf_DescriptorProto_enum_type(msg_proto, &n); + counts->enum_count += n; - arr = google_protobuf_DescriptorProto_extension(msg_proto); - if (arr) { - counts->ext_count += upb_array_size(arr); - } + google_protobuf_DescriptorProto_extension(msg_proto, &n); + counts->ext_count += n; } static void count_types_in_file( const google_protobuf_FileDescriptorProto *file_proto, decl_counts *counts) { - const upb_array *arr; - size_t i; + const google_protobuf_DescriptorProto *const *msgs; + size_t i, n; - arr = google_protobuf_FileDescriptorProto_message_type(file_proto); - for (i = 0; i < upb_array_size(arr); i++) { - count_types_in_msg(upb_msgval_getptr(upb_array_get(arr, i)), counts); + msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n); + for (i = 0; i < n; i++) { + count_types_in_msg(msgs[i], counts); } - arr = google_protobuf_FileDescriptorProto_enum_type(file_proto); - counts->enum_count += upb_array_size(arr); - arr = google_protobuf_FileDescriptorProto_extension(file_proto); - counts->ext_count += upb_array_size(arr); + google_protobuf_FileDescriptorProto_enum_type(file_proto, &n); + counts->enum_count += n; + + google_protobuf_FileDescriptorProto_extension(file_proto, &n); + counts->ext_count += n; } static bool resolve_fielddef(const symtab_addctx *ctx, const char *prefix, @@ -1424,11 +1411,13 @@ static bool resolve_fielddef(const symtab_addctx *ctx, const char *prefix, static bool build_filedef( const symtab_addctx *ctx, upb_filedef *file, const google_protobuf_FileDescriptorProto *file_proto) { - const google_protobuf_FileOptions *file_options_proto; upb_alloc *alloc = ctx->alloc; - const upb_array *arr; + const google_protobuf_FileOptions *file_options_proto; + const google_protobuf_DescriptorProto *const *msgs; + const google_protobuf_EnumDescriptorProto *const *enums; + const google_protobuf_FieldDescriptorProto *const *exts; + const upb_stringview* strs; size_t i, n; - int j; decl_counts counts; upb_stringview syntax, package; @@ -1473,12 +1462,12 @@ static bool build_filedef( } /* Verify dependencies. */ - arr = google_protobuf_FileDescriptorProto_dependency(file_proto); - n = upb_array_size(arr); + strs = google_protobuf_FileDescriptorProto_dependency(file_proto, &n); file->deps = upb_malloc(alloc, sizeof(*file->deps) * n) ; CHK_OOM(file->deps); + for (i = 0; i < n; i++) { - upb_stringview dep_name = upb_msgval_getstr(upb_array_get(arr, i)); + upb_stringview dep_name = strs[i]; upb_value v; if (!upb_strtable_lookup2(&ctx->symtab->files, dep_name.data, dep_name.size, &v)) { @@ -1491,30 +1480,23 @@ static bool build_filedef( } /* Create messages. */ - arr = google_protobuf_FileDescriptorProto_message_type(file_proto); - for (i = 0; i < upb_array_size(arr); i++) { - const google_protobuf_DescriptorProto *msg_proto = - upb_msgval_getptr(upb_array_get(arr, i)); - CHK(create_msgdef(ctx, file->package, msg_proto)); + msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n); + for (i = 0; i < n; i++) { + CHK(create_msgdef(ctx, file->package, msgs[i])); } /* Create enums. */ - arr = google_protobuf_FileDescriptorProto_enum_type(file_proto); - for (i = 0; i < upb_array_size(arr); i++) { - const google_protobuf_EnumDescriptorProto *enum_proto = - upb_msgval_getptr(upb_array_get(arr, i)); - CHK(create_enumdef(ctx, file->package, enum_proto)); + enums = google_protobuf_FileDescriptorProto_enum_type(file_proto, &n); + for (i = 0; i < n; i++) { + CHK(create_enumdef(ctx, file->package, enums[i])); } /* Create extensions. */ - arr = google_protobuf_FileDescriptorProto_extension(file_proto); - n = upb_array_size(arr); + exts = google_protobuf_FileDescriptorProto_extension(file_proto, &n); file->exts = upb_malloc(alloc, sizeof(*file->exts) * n); CHK_OOM(file->exts); for (i = 0; i < n; i++) { - const google_protobuf_FieldDescriptorProto *field_proto = - upb_msgval_getptr(upb_array_get(arr, i)); - CHK(create_fielddef(ctx, file->package, NULL, field_proto)); + CHK(create_fielddef(ctx, file->package, NULL, exts[i])); } /* Now that all names are in the table, resolve references. */ @@ -1524,6 +1506,7 @@ static bool build_filedef( for (i = 0; i < file->msg_count; i++) { const upb_msgdef *m = &file->msgs[i]; + int j; for (j = 0; i < m->field_count; i++) { CHK(resolve_fielddef(ctx, m->full_name, (upb_fielddef*)&m->fields[j])); } -- cgit v1.2.3 From 0553eff64a87eceff0de3b6260b4f2d45b61703a Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Wed, 9 Jan 2019 22:40:50 -0800 Subject: upb_refcounted is gone! Some tests still to fix. --- BUILD | 49 +-- tests/json/test_json.cc | 23 +- tests/pb/test_encoder.cc | 22 +- upb/bindings/lua/def.c | 18 +- upb/bindings/lua/upb.h | 7 +- upb/handlers-inl.h | 34 +- upb/handlers.c | 366 ++++++-------------- upb/handlers.h | 84 ++--- upb/json/parser.c | 320 +++++++++--------- upb/json/parser.h | 50 ++- upb/json/parser.rl | 214 ++++++------ upb/json/printer.c | 17 +- upb/json/printer.h | 17 +- upb/msgfactory.c | 9 - upb/pb/compile_decoder.c | 176 ++++------ upb/pb/decoder.h | 128 ++----- upb/pb/decoder.int.h | 63 ++-- upb/pb/encoder.c | 5 +- upb/pb/encoder.h | 12 +- upb/pb/textprinter.c | 5 +- upb/pb/textprinter.h | 11 +- upb/refcounted.c | 851 ----------------------------------------------- upb/refcounted.h | 348 ------------------- 23 files changed, 666 insertions(+), 2163 deletions(-) delete mode 100644 upb/refcounted.c delete mode 100644 upb/refcounted.h (limited to 'upb/bindings') diff --git a/BUILD b/BUILD index bf988f9..ffb5bbd 100644 --- a/BUILD +++ b/BUILD @@ -1,16 +1,19 @@ load( ":build_defs.bzl", + "generated_file_staleness_test", + "lua_binary", "lua_cclibrary", "lua_library", - "lua_binary", "lua_test", - "generated_file_staleness_test", "make_shell_script", "upb_amalgamation", "upb_proto_library", "upb_proto_reflection_library", ) +# Remove once our C++ wrappers are more sane. +CXX_COPTS = ["-Wno-unused-private-field"] + # C/C++ rules ################################################################## cc_library( @@ -26,7 +29,6 @@ cc_library( "upb/msgfactory.c", "upb/port_def.inc", "upb/port_undef.inc", - "upb/refcounted.c", "upb/sink.c", "upb/structs.int.h", "upb/table.c", @@ -42,7 +44,6 @@ cc_library( "upb/handlers.h", "upb/msg.h", "upb/msgfactory.h", - "upb/refcounted.h", "upb/sink.h", "upb/upb.h", ], @@ -161,8 +162,8 @@ cc_test( upb_proto_reflection_library( name = "descriptor_upbproto", - deps = ["descriptor_proto"], upbc = ":protoc-gen-upb", + deps = ["descriptor_proto"], ) cc_test( @@ -178,14 +179,14 @@ cc_test( proto_library( name = "test_decoder_proto", srcs = [ - "tests/pb/test_decoder.proto" - ] + "tests/pb/test_decoder.proto", + ], ) upb_proto_reflection_library( name = "test_decoder_upbproto", - deps = ["test_decoder_proto"], upbc = ":protoc-gen-upb", + deps = ["test_decoder_proto"], ) cc_test( @@ -201,6 +202,7 @@ cc_test( cc_test( name = "test_encoder", srcs = ["tests/pb/test_encoder.cc"], + copts = CXX_COPTS, data = ["google/protobuf/descriptor.pb"], deps = [ ":upb_cc_bindings", @@ -212,19 +214,20 @@ cc_test( proto_library( name = "test_cpp_proto", srcs = [ - "tests/test_cpp.proto" - ] + "tests/test_cpp.proto", + ], ) upb_proto_reflection_library( name = "test_cpp_upbproto", - deps = ["test_cpp_proto"], upbc = ":protoc-gen-upb", + deps = ["test_cpp_proto"], ) cc_test( name = "test_cpp", srcs = ["tests/test_cpp.cc"], + copts = CXX_COPTS, deps = [ ":test_cpp_upbproto", ":upb", @@ -249,8 +252,8 @@ proto_library( upb_proto_reflection_library( name = "test_json_upbproto", - deps = ["test_json_proto"], upbc = ":protoc-gen-upb", + deps = ["test_json_proto"], ) cc_test( @@ -258,6 +261,7 @@ cc_test( srcs = [ "tests/json/test_json.cc", ], + copts = CXX_COPTS, deps = [ ":test_json_upbproto", ":upb_json", @@ -279,11 +283,11 @@ cc_binary( srcs = [ "tests/conformance_upb.c", ], + copts = ["-Ibazel-out/k8-fastbuild/bin"], deps = [ ":conformance_proto_upb", ":upb", ], - copts = ["-Ibazel-out/k8-fastbuild/bin"], ) make_shell_script( @@ -363,12 +367,16 @@ lua_test( cc_library( name = "upbc_generator", + srcs = [ + "upbc/generator.cc", + "upbc/message_layout.cc", + "upbc/message_layout.h", + ], hdrs = ["upbc/generator.h"], - srcs = ["upbc/generator.cc", "upbc/message_layout.h", "upbc/message_layout.cc"], deps = [ + "@absl//absl/strings", "@com_google_protobuf//:protobuf", "@com_google_protobuf//:protoc_lib", - "@absl//absl/strings", ], ) @@ -386,7 +394,7 @@ cc_binary( make_shell_script( name = "gen_run_cmake_build", out = "run_cmake_build.sh", - contents = "mkdir build && cd build && cmake .. && make -j8 && make test" + contents = "mkdir build && cd build && cmake .. && make -j8 && make test", ) sh_test( @@ -447,10 +455,13 @@ genrule( genrule( name = "gen_cmakelists", + srcs = [ + "BUILD", + "WORKSPACE", + ], outs = ["generated/CMakeLists.txt"], - srcs = ["BUILD", "WORKSPACE"], + cmd = "$(location :make_cmakelists) $@", tools = [":make_cmakelists"], - cmd = "$(location :make_cmakelists) $@" ) proto_library( @@ -469,8 +480,8 @@ genrule( ], cmd = "$(location @com_google_protobuf//:protoc) $< --upb_out=$(GENDIR)/generated --plugin=protoc-gen-upb=$(location :protoc-gen-upb)", tools = [ + ":protoc-gen-upb", "@com_google_protobuf//:protoc", - ":protoc-gen-upb" ], ) diff --git a/tests/json/test_json.cc b/tests/json/test_json.cc index 98bf59e..b9b50cd 100644 --- a/tests/json/test_json.cc +++ b/tests/json/test_json.cc @@ -204,12 +204,15 @@ void test_json_roundtrip_message(const char* json_src, // and compares the result. void test_json_roundtrip() { upb::SymbolTable* symtab = upb::SymbolTable::New(); + upb::HandlerCache* serialize_handlercache = upb::json::Printer::NewCache(false); + upb::json::CodeCache* parse_codecache = upb::json::CodeCache::New(); + const upb::MessageDef* md = upb_test_json_TestMessage_getmsgdef(symtab); ASSERT(md); - upb::reffed_ptr serialize_handlers( - upb::json::Printer::NewHandlers(md, false)); - upb::reffed_ptr parser_method( - upb::json::ParserMethod::New(md)); + const upb::Handlers* serialize_handlers = serialize_handlercache->Get(md); + const upb::json::ParserMethod* parser_method = parse_codecache->Get(md); + ASSERT(serialize_handlers); + ASSERT(parser_method); for (const TestCase* test_case = kTestRoundtripMessages; test_case->input != NULL; test_case++) { @@ -220,12 +223,13 @@ void test_json_roundtrip() { for (size_t i = 0; i < strlen(test_case->input); i++) { test_json_roundtrip_message(test_case->input, expected, - serialize_handlers.get(), parser_method.get(), - i); + serialize_handlers, parser_method, i); } } - serialize_handlers = upb::json::Printer::NewHandlers(md, true); + upb::HandlerCache::Free(serialize_handlercache); + serialize_handlercache = upb::json::Printer::NewCache(true); + serialize_handlers = serialize_handlercache->Get(md); for (const TestCase* test_case = kTestRoundtripMessagesPreserve; test_case->input != NULL; test_case++) { @@ -236,11 +240,12 @@ void test_json_roundtrip() { for (size_t i = 0; i < strlen(test_case->input); i++) { test_json_roundtrip_message(test_case->input, expected, - serialize_handlers.get(), parser_method.get(), - i); + serialize_handlers, parser_method, i); } } + upb::HandlerCache::Free(serialize_handlercache); + upb::json::CodeCache::Free(parse_codecache); upb::SymbolTable::Free(symtab); } diff --git a/tests/pb/test_encoder.cc b/tests/pb/test_encoder.cc index a0f8453..fac0dae 100644 --- a/tests/pb/test_encoder.cc +++ b/tests/pb/test_encoder.cc @@ -19,6 +19,11 @@ std::string read_string(const char *filename) { void test_pb_roundtrip() { std::string input = read_string("google/protobuf/descriptor.pb"); upb::SymbolTable* symtab = upb::SymbolTable::New(); + upb::HandlerCache* encoder_cache = upb::pb::Encoder::NewCache(); + upb::pb::CodeCache* decoder_cache = upb::pb::CodeCache::New(encoder_cache); + ASSERT(symtab); + ASSERT(encoder_cache); + ASSERT(decoder_cache); upb::Arena arena; google_protobuf_FileDescriptorSet *set = google_protobuf_FileDescriptorSet_parsenew( @@ -37,24 +42,23 @@ void test_pb_roundtrip() { const upb::MessageDef *md = symtab->LookupMessage("google.protobuf.FileDescriptorSet"); ASSERT(md); - printf("name: %s\n", md->full_name()); - upb::reffed_ptr encoder_handlers( - upb::pb::Encoder::NewHandlers(md)); - upb::reffed_ptr method( - upb::pb::DecoderMethod::New( - upb::pb::DecoderMethodOptions(encoder_handlers.get()))); + const upb::Handlers* encoder_handlers = encoder_cache->Get(md); + ASSERT(encoder_handlers); + const upb::pb::DecoderMethod* method = decoder_cache->Get(md); + ASSERT(method); upb::InlinedEnvironment<512> env; std::string output; upb::StringSink string_sink(&output); upb::pb::Encoder* encoder = - upb::pb::Encoder::Create(&env, encoder_handlers.get(), - string_sink.input()); + upb::pb::Encoder::Create(&env, encoder_handlers, string_sink.input()); upb::pb::Decoder* decoder = - upb::pb::Decoder::Create(&env, method.get(), encoder->input()); + upb::pb::Decoder::Create(&env, method, encoder->input()); ok = upb::BufferSource::PutBuffer(input, decoder->input()); ASSERT(ok); ASSERT(input == output); + upb::pb::CodeCache::Free(decoder_cache); + upb::HandlerCache::Free(encoder_cache); upb::SymbolTable::Free(symtab); } diff --git a/upb/bindings/lua/def.c b/upb/bindings/lua/def.c index 00b75c9..76510be 100644 --- a/upb/bindings/lua/def.c +++ b/upb/bindings/lua/def.c @@ -22,15 +22,9 @@ } while (0) -/* lupb_refcounted ************************************************************/ +/* lupb_wrapper ***************************************************************/ -/* All upb objects that use upb_refcounted have a userdata that begins with a - * pointer to that object. Each type has its own metatable. Objects are cached - * in a weak table indexed by the C pointer of the object they are caching. - * - * Note that we consistently use memcpy() to read to/from the object. This - * allows the userdata to use its own struct without violating aliasing, as - * long as it begins with a pointer. */ +/* Wrappers around upb objects. */ /* Checks type; if it matches, pulls the pointer out of the wrapper. */ void *lupb_checkwrapper(lua_State *L, int narg, const char *type) { @@ -263,7 +257,7 @@ void lupb_oneofdef_pushwrapper(lua_State *L, const upb_oneofdef *o) { } const upb_oneofdef *lupb_oneofdef_check(lua_State *L, int narg) { - return lupb_refcounted_check(L, narg, LUPB_ONEOFDEF); + return lupb_checkwrapper(L, narg, LUPB_ONEOFDEF); } static int lupb_oneofdef_containingtype(lua_State *L) { @@ -345,7 +339,7 @@ void lupb_msgdef_pushwrapper(lua_State *L, const upb_msgdef *m) { } const upb_msgdef *lupb_msgdef_check(lua_State *L, int narg) { - return lupb_refcounted_check(L, narg, LUPB_MSGDEF); + return lupb_checkwrapper(L, narg, LUPB_MSGDEF); } static int lupb_msgdef_len(lua_State *L) { @@ -453,7 +447,7 @@ static const struct luaL_Reg lupb_msgdef_m[] = { /* lupb_enumdef ***************************************************************/ const upb_enumdef *lupb_enumdef_check(lua_State *L, int narg) { - return lupb_refcounted_check(L, narg, LUPB_ENUMDEF); + return lupb_checkwrapper(L, narg, LUPB_ENUMDEF); } static void lupb_enumdef_pushwrapper(lua_State *L, const upb_enumdef *e) { @@ -527,7 +521,7 @@ void lupb_filedef_pushwrapper(lua_State *L, const upb_filedef *f) { } const upb_filedef *lupb_filedef_check(lua_State *L, int narg) { - return lupb_refcounted_check(L, narg, LUPB_FILEDEF); + return lupb_checkwrapper(L, narg, LUPB_FILEDEF); } static int lupb_filedef_dep(lua_State *L) { diff --git a/upb/bindings/lua/upb.h b/upb/bindings/lua/upb.h index 9e58f03..6861286 100644 --- a/upb/bindings/lua/upb.h +++ b/upb/bindings/lua/upb.h @@ -84,9 +84,7 @@ void lupb_pushuint32(lua_State *L, uint32_t val); void lupb_pushdouble(lua_State *L, double val); void lupb_pushfloat(lua_State *L, float val); -/* Registers a type with the given name, methods, and metamethods. - * If "refcount_gc" is true, adds a __gc metamethod that does an unref. - * Refcounted types must be allocated with lupb_refcounted_push[new]wrapper. */ +/* Registers a type with the given name, methods, and metamethods. */ void lupb_register_type(lua_State *L, const char *name, const luaL_Reg *m, const luaL_Reg *mm); @@ -98,7 +96,6 @@ void lupb_checkstatus(lua_State *L, upb_status *s); upb_fieldtype_t lupb_checkfieldtype(lua_State *L, int narg); -void *lupb_refcounted_check(lua_State *L, int narg, const char *type); const upb_msgdef *lupb_msgdef_check(lua_State *L, int narg); const upb_enumdef *lupb_enumdef_check(lua_State *L, int narg); const upb_fielddef *lupb_fielddef_check(lua_State *L, int narg); @@ -106,8 +103,6 @@ upb_symtab *lupb_symtab_check(lua_State *L, int narg); void lupb_def_registertypes(lua_State *L); -int lupb_refcounted_gc(lua_State *L); - /** From msg.c. ***************************************************************/ diff --git a/upb/handlers-inl.h b/upb/handlers-inl.h index afc1382..eb9a0fa 100644 --- a/upb/handlers-inl.h +++ b/upb/handlers-inl.h @@ -997,32 +997,12 @@ const T* BufferHandle::GetAttachedObject() const { : NULL; } -inline reffed_ptr Handlers::New(const MessageDef *m) { - upb_handlers *h = upb_handlers_new(m, &h); - return reffed_ptr(h, &h); -} -inline reffed_ptr Handlers::NewFrozen( - const MessageDef *m, upb_handlers_callback *callback, - const void *closure) { - const upb_handlers *h = upb_handlers_newfrozen(m, &h, callback, closure); - return reffed_ptr(h, &h); -} inline const Status* Handlers::status() { return upb_handlers_status(this); } inline void Handlers::ClearError() { return upb_handlers_clearerr(this); } -inline bool Handlers::Freeze(Status *s) { - upb::Handlers* h = this; - return upb_handlers_freeze(&h, 1, s); -} -inline bool Handlers::Freeze(Handlers *const *handlers, int n, Status *s) { - return upb_handlers_freeze(handlers, n, s); -} -inline bool Handlers::Freeze(const std::vector& h, Status* status) { - return upb_handlers_freeze((Handlers* const*)&h[0], h.size(), status); -} inline const MessageDef *Handlers::message_def() const { return upb_handlers_msgdef(this); } @@ -1092,9 +1072,6 @@ inline bool Handlers::SetEndSequenceHandler(const FieldDef *f, handler.AddCleanup(this); return upb_handlers_setendseq(this, f, handler.handler_, &handler.attr_); } -inline bool Handlers::SetSubHandlers(const FieldDef *f, const Handlers *sub) { - return upb_handlers_setsubhandlers(this, f, sub); -} inline const Handlers *Handlers::GetSubHandlers(const FieldDef *f) const { return upb_handlers_getsubhandlers(this, f); } @@ -1116,6 +1093,17 @@ inline const void *Handlers::GetHandlerData(Handlers::Selector selector) { return upb_handlers_gethandlerdata(this, selector); } +inline HandlerCache *HandlerCache::New(upb_handlers_callback *callback, + const void *closure) { + return upb_handlercache_new(callback, closure); +} +inline void HandlerCache::Free(HandlerCache* cache) { + return upb_handlercache_free(cache); +} +const Handlers* HandlerCache::Get(const MessageDef* md) { + return upb_handlercache_get(this, md); +} + inline BytesHandler::BytesHandler() { upb_byteshandler_init(this); } diff --git a/upb/handlers.c b/upb/handlers.c index fa75a48..90fb7b8 100644 --- a/upb/handlers.c +++ b/upb/handlers.c @@ -9,8 +9,8 @@ #include "upb/sink.h" -static void *upb_calloc(size_t size) { - void *mem = upb_gmalloc(size); +static void *upb_calloc(upb_arena *arena, size_t size) { + void *mem = upb_malloc(upb_arena_alloc(arena), size); if (mem) { memset(mem, 0, size); } @@ -21,86 +21,6 @@ static void *upb_calloc(size_t size) { * UPB_NO_CLOSURE. */ char _upb_noclosure; -static void freehandlers(upb_refcounted *r) { - upb_handlers *h = (upb_handlers*)r; - - upb_inttable_iter i; - upb_inttable_begin(&i, &h->cleanup_); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - void *val = (void*)upb_inttable_iter_key(&i); - upb_value func_val = upb_inttable_iter_value(&i); - upb_handlerfree *func = upb_value_getfptr(func_val); - func(val); - } - - upb_inttable_uninit(&h->cleanup_); - upb_gfree(h->sub); - upb_gfree(h); -} - -static void visithandlers(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const upb_handlers *h = (const upb_handlers*)r; - upb_msg_field_iter i; - for(upb_msg_field_begin(&i, h->msg); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - upb_fielddef *f = upb_msg_iter_field(&i); - const upb_handlers *sub; - if (!upb_fielddef_issubmsg(f)) continue; - sub = upb_handlers_getsubhandlers(h, f); - if (sub) visit(r, upb_handlers_upcast(sub), closure); - } -} - -static const struct upb_refcounted_vtbl vtbl = {visithandlers, freehandlers}; - -typedef struct { - upb_inttable tab; /* maps upb_msgdef* -> upb_handlers*. */ - upb_handlers_callback *callback; - const void *closure; -} dfs_state; - -/* TODO(haberman): discard upb_handlers* objects that do not actually have any - * handlers set and cannot reach any upb_handlers* object that does. This is - * slightly tricky to do correctly. */ -static upb_handlers *newformsg(const upb_msgdef *m, const void *owner, - dfs_state *s) { - upb_msg_field_iter i; - upb_handlers *h = upb_handlers_new(m, owner); - if (!h) return NULL; - if (!upb_inttable_insertptr(&s->tab, m, upb_value_ptr(h))) goto oom; - - s->callback(s->closure, h); - - /* For each submessage field, get or create a handlers object and set it as - * the subhandlers. */ - for(upb_msg_field_begin(&i, m); - !upb_msg_field_done(&i); - upb_msg_field_next(&i)) { - upb_fielddef *f = upb_msg_iter_field(&i); - const upb_msgdef *subdef; - upb_value subm_ent; - - if (!upb_fielddef_issubmsg(f)) continue; - - subdef = upb_fielddef_msgsubdef(f); - if (upb_inttable_lookupptr(&s->tab, subdef, &subm_ent)) { - upb_handlers_setsubhandlers(h, f, upb_value_getptr(subm_ent)); - } else { - upb_handlers *sub_mh = newformsg(subdef, &sub_mh, s); - if (!sub_mh) goto oom; - upb_handlers_setsubhandlers(h, f, sub_mh); - upb_handlers_unref(sub_mh, &sub_mh); - } - } - return h; - -oom: - upb_handlers_unref(h, owner); - return NULL; -} - /* Given a selector for a STARTSUBMSG handler, resolves to a pointer to the * subhandlers for this submessage field. */ #define SUBH(h, selector) (h->sub[selector]) @@ -111,20 +31,13 @@ oom: static int32_t trygetsel(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type) { upb_selector_t sel; - UPB_ASSERT(!upb_handlers_isfrozen(h)); - 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))); - return -1; - } - if (!upb_handlers_getselector(f, type, &sel)) { - upb_status_seterrf( - &h->status_, - "type mismatch: cannot register handler type %d for field %s", - type, upb_fielddef_name(f)); - return -1; - } + bool ok; + + ok = upb_handlers_getselector(f, type, &sel); + + UPB_ASSERT(upb_handlers_msgdef(h) == upb_fielddef_containingtype(f)); + UPB_ASSERT(ok); + return sel; } @@ -147,19 +60,7 @@ static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f, const void *closure_type; const void **context_closure_type; - UPB_ASSERT(!upb_handlers_isfrozen(h)); - - if (sel < 0) { - upb_status_seterrmsg(&h->status_, - "incorrect handler type for this field."); - return false; - } - - if (h->table[sel].func) { - upb_status_seterrmsg(&h->status_, - "cannot change handler once it has been set."); - return false; - } + UPB_ASSERT(!h->table[sel].func); if (attr) { set_attr = *attr; @@ -181,16 +82,7 @@ static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f, if (closure_type && *context_closure_type && closure_type != *context_closure_type) { - /* TODO(haberman): better message for debugging. */ - if (f) { - upb_status_seterrf(&h->status_, - "closure type does not match for field %s", - upb_fielddef_name(f)); - } else { - upb_status_seterrmsg( - &h->status_, "closure type does not match for message-level handler"); - } - return false; + UPB_ASSERT(false); } if (closure_type) @@ -203,8 +95,7 @@ static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f, const void *table_return_type = upb_handlerattr_returnclosuretype(&h->table[sel].attr); if (return_type && table_return_type && return_type != table_return_type) { - upb_status_seterrmsg(&h->status_, "closure return type does not match"); - return false; + UPB_ASSERT(false); } if (table_return_type && !return_type) @@ -268,80 +159,36 @@ bool checkstart(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type, return_closure_type = upb_handlerattr_returnclosuretype(attr); if (closure_type && return_closure_type && closure_type != return_closure_type) { - upb_status_seterrf(status, - "expected start handler to return sub type for field %f", - upb_fielddef_name(f)); - return false; + UPB_ASSERT(false); } return true; } -/* Public interface ***********************************************************/ - -upb_handlers *upb_handlers_new(const upb_msgdef *md, const void *owner) { +static upb_handlers *upb_handlers_new(const upb_msgdef *md, upb_handlercache *cache) { int extra; upb_handlers *h; extra = sizeof(upb_handlers_tabent) * (upb_msgdef_selectorcount(md) - 1); - h = upb_calloc(sizeof(*h) + extra); + h = upb_calloc(&cache->arena, sizeof(*h) + extra); if (!h) return NULL; + h->cache = cache; h->msg = md; - upb_status_clear(&h->status_); if (upb_msgdef_submsgfieldcount(md) > 0) { - h->sub = upb_calloc(upb_msgdef_submsgfieldcount(md) * sizeof(*h->sub)); - if (!h->sub) goto oom; + size_t bytes = upb_msgdef_submsgfieldcount(md) * sizeof(*h->sub); + h->sub = upb_calloc(&cache->arena, bytes); + if (!h->sub) return NULL; } else { h->sub = 0; } - if (!upb_refcounted_init(upb_handlers_upcast_mutable(h), &vtbl, owner)) - goto oom; - if (!upb_inttable_init(&h->cleanup_, UPB_CTYPE_FPTR)) goto oom; - /* calloc() above initialized all handlers to NULL. */ return h; - -oom: - freehandlers(upb_handlers_upcast_mutable(h)); - return NULL; } -const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m, - const void *owner, - upb_handlers_callback *callback, - const void *closure) { - dfs_state state; - upb_handlers *ret; - bool ok; - upb_refcounted *r; - - state.callback = callback; - state.closure = closure; - if (!upb_inttable_init(&state.tab, UPB_CTYPE_PTR)) return NULL; - - ret = newformsg(m, owner, &state); - - upb_inttable_uninit(&state.tab); - if (!ret) return NULL; - - r = upb_handlers_upcast_mutable(ret); - ok = upb_refcounted_freeze(&r, 1, NULL, UPB_MAX_HANDLER_DEPTH); - UPB_ASSERT(ok); - return ret; -} - -const upb_status *upb_handlers_status(upb_handlers *h) { - UPB_ASSERT(!upb_handlers_isfrozen(h)); - return &h->status_; -} - -void upb_handlers_clearerr(upb_handlers *h) { - UPB_ASSERT(!upb_handlers_isfrozen(h)); - upb_status_clear(&h->status_); -} +/* Public interface ***********************************************************/ #define SETTER(name, handlerctype, handlertype) \ bool upb_handlers_set ## name(upb_handlers *h, const upb_fielddef *f, \ @@ -381,7 +228,6 @@ bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func, bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func, upb_handlerattr *attr) { - UPB_ASSERT(!upb_handlers_isfrozen(h)); return doset(h, UPB_ENDMSG_SELECTOR, NULL, UPB_HANDLER_INT32, (upb_func *)func, attr); } @@ -389,14 +235,12 @@ bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func, bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f, const upb_handlers *sub) { UPB_ASSERT(sub); - UPB_ASSERT(!upb_handlers_isfrozen(h)); UPB_ASSERT(upb_fielddef_issubmsg(f)); if (SUBH_F(h, f)) return false; /* Can't reset. */ if (upb_handlers_msgdef(sub) != upb_fielddef_msgsubdef(f)) { return false; } SUBH_F(h, f) = sub; - upb_ref2(sub, h); return true; } @@ -424,101 +268,14 @@ const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; } bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) { bool ok; - if (upb_inttable_lookupptr(&h->cleanup_, p, NULL)) { + if (upb_inttable_lookupptr(&h->cache->cleanup_, p, NULL)) { return false; } - ok = upb_inttable_insertptr(&h->cleanup_, p, upb_value_fptr(func)); + ok = upb_inttable_insertptr(&h->cache->cleanup_, p, upb_value_fptr(func)); UPB_ASSERT(ok); return true; } - -/* "Static" methods ***********************************************************/ - -bool upb_handlers_freeze(upb_handlers *const*handlers, int n, upb_status *s) { - /* TODO: verify we have a transitive closure. */ - int i; - for (i = 0; i < n; i++) { - upb_msg_field_iter j; - upb_handlers *h = handlers[i]; - - if (!upb_ok(&h->status_)) { - upb_status_seterrf(s, "handlers for message %s had error status: %s", - upb_msgdef_fullname(upb_handlers_msgdef(h)), - upb_status_errmsg(&h->status_)); - return false; - } - - /* Check that there are no closure mismatches due to missing Start* handlers - * or subhandlers with different type-level types. */ - for(upb_msg_field_begin(&j, h->msg); - !upb_msg_field_done(&j); - upb_msg_field_next(&j)) { - - const upb_fielddef *f = upb_msg_iter_field(&j); - if (upb_fielddef_isseq(f)) { - if (!checkstart(h, f, UPB_HANDLER_STARTSEQ, s)) - return false; - } - - if (upb_fielddef_isstring(f)) { - if (!checkstart(h, f, UPB_HANDLER_STARTSTR, s)) - return false; - } - - if (upb_fielddef_issubmsg(f)) { - bool hashandler = false; - if (upb_handlers_gethandler( - h, handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)) || - upb_handlers_gethandler( - h, handlers_getsel(h, f, UPB_HANDLER_ENDSUBMSG))) { - hashandler = true; - } - - if (upb_fielddef_isseq(f) && - (upb_handlers_gethandler( - h, handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)) || - upb_handlers_gethandler( - h, handlers_getsel(h, f, UPB_HANDLER_ENDSEQ)))) { - hashandler = true; - } - - if (hashandler && !upb_handlers_getsubhandlers(h, f)) { - /* For now we add an empty subhandlers in this case. It makes the - * decoder code generator simpler, because it only has to handle two - * cases (submessage has handlers or not) as opposed to three - * (submessage has handlers in enclosing message but no subhandlers). - * - * This makes parsing less efficient in the case that we want to - * notice a submessage but skip its contents (like if we're testing - * for submessage presence or counting the number of repeated - * submessages). In this case we will end up parsing the submessage - * field by field and throwing away the results for each, instead of - * skipping the whole delimited thing at once. If this is an issue we - * can revisit it, but do remember that this only arises when you have - * handlers (startseq/startsubmsg/endsubmsg/endseq) set for the - * submessage but no subhandlers. The uses cases for this are - * limited. */ - upb_handlers *sub = upb_handlers_new(upb_fielddef_msgsubdef(f), &sub); - upb_handlers_setsubhandlers(h, f, sub); - upb_handlers_unref(sub, &sub); - } - - /* TODO(haberman): check type of submessage. - * This is slightly tricky; also consider whether we should check that - * they match at setsubhandlers time. */ - } - } - } - - if (!upb_refcounted_freeze((upb_refcounted*const*)handlers, n, s, - UPB_MAX_HANDLER_DEPTH)) { - return false; - } - - return true; -} - upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) { switch (upb_fielddef_type(f)) { case UPB_TYPE_INT32: @@ -616,6 +373,85 @@ uint32_t upb_handlers_selectorcount(const upb_fielddef *f) { return ret; } +/* upb_handlercache ***********************************************************/ + +const upb_handlers *upb_handlercache_get(upb_handlercache *c, + const upb_msgdef *md) { + upb_msg_field_iter i; + upb_value v; + upb_handlers *h; + + if (upb_inttable_lookupptr(&c->tab, md, &v)) { + return upb_value_getptr(v); + } + + h = upb_handlers_new(md, c); + v = upb_value_ptr(h); + + if (!h) return NULL; + if (!upb_inttable_insertptr(&c->tab, md, v)) return NULL; + + c->callback(c->closure, h); + + /* For each submessage field, get or create a handlers object and set it as + * the subhandlers. */ + for(upb_msg_field_begin(&i, md); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { + upb_fielddef *f = upb_msg_iter_field(&i); + + if (upb_fielddef_issubmsg(f)) { + const upb_msgdef *subdef = upb_fielddef_msgsubdef(f); + const upb_handlers *sub_mh = upb_handlercache_get(c, subdef); + + if (!sub_mh) return NULL; + + upb_handlers_setsubhandlers(h, f, sub_mh); + } + } + + return h; +} + + +upb_handlercache *upb_handlercache_new(upb_handlers_callback *callback, + const void *closure) { + upb_handlercache *cache = upb_gmalloc(sizeof(*cache)); + + if (!cache) return NULL; + + upb_arena_init(&cache->arena); + + cache->callback = callback; + cache->closure = closure; + + if (!upb_inttable_init(&cache->tab, UPB_CTYPE_PTR)) goto oom; + if (!upb_inttable_init(&cache->cleanup_, UPB_CTYPE_FPTR)) goto oom; + + return cache; + +oom: + upb_gfree(cache); + return NULL; +} + +void upb_handlercache_free(upb_handlercache *cache) { + upb_inttable_iter i; + + upb_inttable_begin(&i, &cache->cleanup_); + for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { + void *val = (void*)upb_inttable_iter_key(&i); + upb_value func_val = upb_inttable_iter_value(&i); + upb_handlerfree *func = upb_value_getfptr(func_val); + func(val); + } + + upb_inttable_uninit(&cache->tab); + upb_inttable_uninit(&cache->cleanup_); + upb_arena_uninit(&cache->arena); + upb_gfree(cache); +} + /* upb_handlerattr ************************************************************/ diff --git a/upb/handlers.h b/upb/handlers.h index 15d06a0..741bd48 100644 --- a/upb/handlers.h +++ b/upb/handlers.h @@ -21,7 +21,6 @@ #include "upb/def.h" #include "upb/table.int.h" -#include "upb/refcounted.h" #ifdef __cplusplus namespace upb { @@ -29,6 +28,7 @@ class BufferHandle; class BytesHandler; class HandlerAttributes; class Handlers; +class HandlerCache; template class Handler; template struct CanonicalType; } /* namespace upb */ @@ -37,8 +37,8 @@ template struct CanonicalType; UPB_DECLARE_TYPE(upb::BufferHandle, upb_bufhandle) UPB_DECLARE_TYPE(upb::BytesHandler, upb_byteshandler) UPB_DECLARE_TYPE(upb::HandlerAttributes, upb_handlerattr) -UPB_DECLARE_DERIVED_TYPE(upb::Handlers, upb::RefCounted, - upb_handlers, upb_refcounted) +UPB_DECLARE_TYPE(upb::Handlers, upb_handlers) +UPB_DECLARE_TYPE(upb::HandlerCache, upb_handlercache) /* 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. @@ -275,22 +275,6 @@ class upb::Handlers { typedef void HandlersCallback(const void *closure, upb_handlers *h); - /* Returns a new handlers object for the given frozen msgdef. - * Returns NULL if memory allocation failed. */ - static reffed_ptr New(const MessageDef *m); - - /* Convenience function for registering a graph of handlers that mirrors the - * graph of msgdefs for some message. For "m" and all its children a new set - * of handlers will be created and the given callback will be invoked, - * allowing the client to register handlers for this message. Note that any - * subhandlers set by the callback will be overwritten. */ - static reffed_ptr NewFrozen(const MessageDef *m, - HandlersCallback *callback, - const void *closure); - - /* Functionality from upb::RefCounted. */ - UPB_REFCOUNTED_CPPMETHODS - /* All handler registration functions return bool to indicate success or * failure; details about failures are stored in this status object. If a * failure does occur, it must be cleared before the Handlers are frozen, @@ -299,16 +283,6 @@ class upb::Handlers { const Status* status(); void ClearError(); - /* Call to freeze these Handlers. Requires that any SubHandlers are already - * frozen. For cycles, you must use the static version below and freeze the - * whole graph at once. */ - bool Freeze(Status* s); - - /* Freezes the given set of handlers. You may not freeze a handler without - * also freezing any handlers they point to. */ - static bool Freeze(Handlers*const* handlers, int n, Status* s); - static bool Freeze(const std::vector& handlers, Status* s); - /* Returns the msgdef associated with this handlers object. */ const MessageDef* message_def() const; @@ -473,9 +447,8 @@ class upb::Handlers { */ bool SetEndSequenceHandler(const FieldDef* f, const EndFieldHandler& h); - /* Sets or gets the object that specifies handlers for the given field, which + /* Gets the object that specifies handlers for the given field, which * must be a submessage or group. Returns NULL if no handlers are set. */ - bool SetSubHandlers(const FieldDef* f, const Handlers* sub); const Handlers* GetSubHandlers(const FieldDef* f) const; /* Equivalent to GetSubHandlers, but takes the STARTSUBMSG selector for the @@ -519,13 +492,10 @@ class upb::Handlers { #else struct upb_handlers { #endif - upb_refcounted base; - + upb_handlercache *cache; const upb_msgdef *msg; const upb_handlers **sub; const void *top_closure_type; - upb_inttable cleanup_; - upb_status status_; /* Used only when mutable. */ upb_handlers_tabent table[1]; /* Dynamically-sized field handler array. */ }; @@ -675,17 +645,6 @@ UPB_INLINE const void *upb_handlerattr_handlerdata( } /* upb_handlers */ -typedef void upb_handlers_callback(const void *closure, upb_handlers *h); -upb_handlers *upb_handlers_new(const upb_msgdef *m, - const void *owner); -const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m, - const void *owner, - upb_handlers_callback *callback, - const void *closure); - -/* Include refcounted methods like upb_handlers_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_handlers, upb_handlers_upcast) - const upb_status *upb_handlers_status(upb_handlers *h); void upb_handlers_clearerr(upb_handlers *h); const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h); @@ -737,8 +696,6 @@ bool upb_handlers_setendseq(upb_handlers *h, const upb_fielddef *f, upb_endfield_handlerfunc *func, upb_handlerattr *attr); -bool upb_handlers_setsubhandlers(upb_handlers *h, const upb_fielddef *f, - const upb_handlers *sub); const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h, const upb_fielddef *f); const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h, @@ -757,6 +714,36 @@ UPB_INLINE const void *upb_handlers_gethandlerdata(const upb_handlers *h, return upb_handlerattr_handlerdata(&h->table[s].attr); } +typedef void upb_handlers_callback(const void *closure, upb_handlers *h); + +#ifdef __cplusplus + +class upb::HandlerCache { + public: + static HandlerCache *New(upb_handlers_callback *callback, + const void *closure); + static void Free(HandlerCache* cache); + + const Handlers* Get(const MessageDef* md); + + private: + UPB_DISALLOW_POD_OPS(HandlerCache, upb::pb::HandlerCache) +#else +struct upb_handlercache { +#endif + upb_arena arena; + upb_inttable tab; /* maps upb_msgdef* -> upb_handlers*. */ + upb_inttable cleanup_; + upb_handlers_callback *callback; + const void *closure; +}; + +upb_handlercache *upb_handlercache_new(upb_handlers_callback *callback, + const void *closure); +void upb_handlercache_free(upb_handlercache *cache); +const upb_handlers *upb_handlercache_get(upb_handlercache *cache, + const upb_msgdef *md); + #ifdef __cplusplus /* Handler types for single fields. @@ -788,7 +775,6 @@ bool upb_byteshandler_setendstr(upb_byteshandler *h, upb_endfield_handlerfunc *func, void *d); /* "Static" methods */ -bool upb_handlers_freeze(upb_handlers *const *handlers, int n, upb_status *s); upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f); bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type, upb_selector_t *s); diff --git a/upb/json/parser.c b/upb/json/parser.c index 90a401d..4bc9163 100644 --- a/upb/json/parser.c +++ b/upb/json/parser.c @@ -154,14 +154,13 @@ void upb_stringsink_uninit(upb_stringsink *sink) { free(sink->ptr); } typedef struct { /* For encoding Any value field in binary format. */ - const upb_handlers *encoder_handlers; - upb_pb_encoder *encoder; + upb_handlercache *encoder_handlercache; upb_stringsink stringsink; /* For decoding Any value field in json format. */ - upb_json_parsermethod *parser_method; - upb_json_parser* parser; + upb_json_codecache *parser_codecache; upb_sink sink; + upb_json_parser *parser; /* Mark the range of uninterpreted values in json input before type url. */ const char *before_type_url_start; @@ -180,7 +179,7 @@ typedef struct { const upb_fielddef *f; /* The table mapping json name to fielddef for this message. */ - upb_strtable *name_table; + const upb_strtable *name_table; /* We are in a repeated-field context, ready to emit mapentries as * submessages. This flag alters the start-of-object (open-brace) behavior to @@ -259,60 +258,67 @@ struct upb_json_parser { struct tm tm; }; -struct upb_json_parsermethod { - upb_refcounted base; +struct upb_json_codecache { + upb_arena arena; + upb_inttable methods; /* upb_msgdef* -> upb_json_parsermethod* */ +}; +struct upb_json_parsermethod { + const upb_json_codecache *cache; upb_byteshandler input_handler_; - /* Keys are upb_msgdef*, values are upb_strtable (json_name -> fielddef) */ - upb_inttable name_tables; + /* Maps json_name -> fielddef */ + upb_strtable name_table; }; #define PARSER_CHECK_RETURN(x) if (!(x)) return false -static void json_parser_any_frame_reset(upb_jsonparser_any_frame *frame) { - frame->encoder_handlers = NULL; - frame->encoder = NULL; - frame->parser_method = NULL; +static upb_jsonparser_any_frame *json_parser_any_frame_new( + upb_json_parser *p) { + upb_jsonparser_any_frame *frame; + + frame = upb_env_malloc(p->env, sizeof(upb_jsonparser_any_frame)); + + frame->encoder_handlercache = upb_pb_encoder_newcache(); + frame->parser_codecache = upb_json_codecache_new(); frame->parser = NULL; frame->before_type_url_start = NULL; frame->before_type_url_end = NULL; frame->after_type_url_start = NULL; + + upb_stringsink_init(&frame->stringsink); + + return frame; } static void json_parser_any_frame_set_payload_type( upb_json_parser *p, upb_jsonparser_any_frame *frame, const upb_msgdef *payload_type) { + const upb_handlers *h; + const upb_json_parsermethod *parser_method; + upb_pb_encoder *encoder; + /* Initialize encoder. */ - frame->encoder_handlers = - upb_pb_encoder_newhandlers(payload_type, &frame->encoder_handlers); - upb_stringsink_init(&frame->stringsink); - frame->encoder = - upb_pb_encoder_create( - p->env, frame->encoder_handlers, - &frame->stringsink.sink); + h = upb_handlercache_get(frame->encoder_handlercache, payload_type); + encoder = upb_pb_encoder_create(p->env, h, &frame->stringsink.sink); /* Initialize parser. */ - frame->parser_method = - upb_json_parsermethod_new(payload_type, &frame->parser_method); - upb_sink_reset(&frame->sink, frame->encoder_handlers, frame->encoder); - frame->parser = - upb_json_parser_create(p->env, frame->parser_method, p->symtab, - &frame->sink, p->ignore_json_unknown); + parser_method = upb_json_codecache_get(frame->parser_codecache, payload_type); + upb_sink_reset(&frame->sink, h, encoder); + frame->parser = upb_json_parser_create(p->env, parser_method, p->symtab, + &frame->sink, p->ignore_json_unknown); } static void json_parser_any_frame_free(upb_jsonparser_any_frame *frame) { - upb_handlers_unref(frame->encoder_handlers, - &frame->encoder_handlers); - upb_json_parsermethod_unref(frame->parser_method, - &frame->parser_method); + upb_handlercache_free(frame->encoder_handlercache); + upb_json_codecache_free(frame->parser_codecache); upb_stringsink_uninit(&frame->stringsink); } static bool json_parser_any_frame_has_type_url( upb_jsonparser_any_frame *frame) { - return frame->encoder != NULL; + return frame->parser != NULL; } static bool json_parser_any_frame_has_value_before_type_url( @@ -334,7 +340,7 @@ static bool json_parser_any_frame_has_value( static void json_parser_any_frame_set_before_type_url_end( upb_jsonparser_any_frame *frame, const char *ptr) { - if (frame->encoder == NULL) { + if (frame->parser == NULL) { frame->before_type_url_end = ptr; } } @@ -376,9 +382,12 @@ static bool check_stack(upb_json_parser *p) { static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) { upb_value v; - bool ok = upb_inttable_lookupptr(&p->method->name_tables, frame->m, &v); + const upb_json_codecache *cache = p->method->cache; + bool ok = upb_inttable_lookupptr(&cache->methods, frame->m, &v); + const upb_json_parsermethod *method = upb_value_getptr(v); UPB_ASSERT(ok); - frame->name_table = upb_value_getptr(v); + + frame->name_table = &method->name_table; } /* There are GCC/Clang built-ins for overflow checking which we could start @@ -1929,9 +1938,7 @@ static bool start_subobject(upb_json_parser *p) { if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) { p->top->is_any = true; - p->top->any_frame = - upb_env_malloc(p->env, sizeof(upb_jsonparser_any_frame)); - json_parser_any_frame_reset(p->top->any_frame); + p->top->any_frame = json_parser_any_frame_new(p); } else { p->top->is_any = false; p->top->any_frame = NULL; @@ -2409,11 +2416,11 @@ static bool is_string_wrapper_object(upb_json_parser *p) { * final state once, when the closing '"' is seen. */ -#line 2571 "upb/json/parser.rl" +#line 2578 "upb/json/parser.rl" -#line 2417 "upb/json/parser.c" +#line 2424 "upb/json/parser.c" static const char _json_actions[] = { 0, 1, 0, 1, 1, 1, 3, 1, 4, 1, 6, 1, 7, 1, 8, 1, @@ -2660,7 +2667,7 @@ static const int json_en_value_machine = 75; static const int json_en_main = 1; -#line 2574 "upb/json/parser.rl" +#line 2581 "upb/json/parser.rl" size_t parse(void *closure, const void *hd, const char *buf, size_t size, const upb_bufhandle *handle) { @@ -2683,7 +2690,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size, capture_resume(parser, buf); -#line 2687 "upb/json/parser.c" +#line 2694 "upb/json/parser.c" { int _klen; unsigned int _trans; @@ -2758,83 +2765,83 @@ _match: switch ( *_acts++ ) { case 1: -#line 2422 "upb/json/parser.rl" +#line 2429 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 2: -#line 2424 "upb/json/parser.rl" +#line 2431 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 23;goto _again;} } break; case 3: -#line 2428 "upb/json/parser.rl" +#line 2435 "upb/json/parser.rl" { start_text(parser, p); } break; case 4: -#line 2429 "upb/json/parser.rl" +#line 2436 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_text(parser, p)); } break; case 5: -#line 2435 "upb/json/parser.rl" +#line 2442 "upb/json/parser.rl" { start_hex(parser); } break; case 6: -#line 2436 "upb/json/parser.rl" +#line 2443 "upb/json/parser.rl" { hexdigit(parser, p); } break; case 7: -#line 2437 "upb/json/parser.rl" +#line 2444 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_hex(parser)); } break; case 8: -#line 2443 "upb/json/parser.rl" +#line 2450 "upb/json/parser.rl" { CHECK_RETURN_TOP(escape(parser, p)); } break; case 9: -#line 2449 "upb/json/parser.rl" +#line 2456 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 10: -#line 2461 "upb/json/parser.rl" +#line 2468 "upb/json/parser.rl" { start_duration_base(parser, p); } break; case 11: -#line 2462 "upb/json/parser.rl" +#line 2469 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_duration_base(parser, p)); } break; case 12: -#line 2464 "upb/json/parser.rl" +#line 2471 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 13: -#line 2469 "upb/json/parser.rl" +#line 2476 "upb/json/parser.rl" { start_timestamp_base(parser, p); } break; case 14: -#line 2470 "upb/json/parser.rl" +#line 2477 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_base(parser, p)); } break; case 15: -#line 2472 "upb/json/parser.rl" +#line 2479 "upb/json/parser.rl" { start_timestamp_fraction(parser, p); } break; case 16: -#line 2473 "upb/json/parser.rl" +#line 2480 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); } break; case 17: -#line 2475 "upb/json/parser.rl" +#line 2482 "upb/json/parser.rl" { start_timestamp_zone(parser, p); } break; case 18: -#line 2476 "upb/json/parser.rl" +#line 2483 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); } break; case 19: -#line 2478 "upb/json/parser.rl" +#line 2485 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 20: -#line 2483 "upb/json/parser.rl" +#line 2490 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) { {stack[top++] = cs; cs = 47;goto _again;} @@ -2846,11 +2853,11 @@ _match: } break; case 21: -#line 2494 "upb/json/parser.rl" +#line 2501 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 75;goto _again;} } break; case 22: -#line 2499 "upb/json/parser.rl" +#line 2506 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { start_any_member(parser, p); @@ -2860,11 +2867,11 @@ _match: } break; case 23: -#line 2506 "upb/json/parser.rl" +#line 2513 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_membername(parser)); } break; case 24: -#line 2509 "upb/json/parser.rl" +#line 2516 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { end_any_member(parser, p); @@ -2874,7 +2881,7 @@ _match: } break; case 25: -#line 2520 "upb/json/parser.rl" +#line 2527 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { start_any_object(parser, p); @@ -2884,7 +2891,7 @@ _match: } break; case 26: -#line 2529 "upb/json/parser.rl" +#line 2536 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { CHECK_RETURN_TOP(end_any_object(parser, p)); @@ -2894,54 +2901,54 @@ _match: } break; case 27: -#line 2541 "upb/json/parser.rl" +#line 2548 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_array(parser)); } break; case 28: -#line 2545 "upb/json/parser.rl" +#line 2552 "upb/json/parser.rl" { end_array(parser); } break; case 29: -#line 2550 "upb/json/parser.rl" +#line 2557 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_number(parser, p)); } break; case 30: -#line 2551 "upb/json/parser.rl" +#line 2558 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 31: -#line 2553 "upb/json/parser.rl" +#line 2560 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_stringval(parser)); } break; case 32: -#line 2554 "upb/json/parser.rl" +#line 2561 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_stringval(parser)); } break; case 33: -#line 2556 "upb/json/parser.rl" +#line 2563 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, true)); } break; case 34: -#line 2558 "upb/json/parser.rl" +#line 2565 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, false)); } break; case 35: -#line 2560 "upb/json/parser.rl" +#line 2567 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_null(parser)); } break; case 36: -#line 2562 "upb/json/parser.rl" +#line 2569 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_subobject_full(parser)); } break; case 37: -#line 2563 "upb/json/parser.rl" +#line 2570 "upb/json/parser.rl" { end_subobject_full(parser); } break; case 38: -#line 2568 "upb/json/parser.rl" +#line 2575 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; -#line 2945 "upb/json/parser.c" +#line 2952 "upb/json/parser.c" } } @@ -2958,32 +2965,32 @@ _again: while ( __nacts-- > 0 ) { switch ( *__acts++ ) { case 0: -#line 2420 "upb/json/parser.rl" +#line 2427 "upb/json/parser.rl" { p--; {cs = stack[--top]; if ( p == pe ) goto _test_eof; goto _again;} } break; case 30: -#line 2551 "upb/json/parser.rl" +#line 2558 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 33: -#line 2556 "upb/json/parser.rl" +#line 2563 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, true)); } break; case 34: -#line 2558 "upb/json/parser.rl" +#line 2565 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, false)); } break; case 35: -#line 2560 "upb/json/parser.rl" +#line 2567 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_null(parser)); } break; case 37: -#line 2563 "upb/json/parser.rl" +#line 2570 "upb/json/parser.rl" { end_subobject_full(parser); } break; -#line 2987 "upb/json/parser.c" +#line 2994 "upb/json/parser.c" } } } @@ -2991,7 +2998,7 @@ goto _again;} } _out: {} } -#line 2596 "upb/json/parser.rl" +#line 2603 "upb/json/parser.rl" if (p != pe) { upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p); @@ -3039,13 +3046,13 @@ static void json_parser_reset(upb_json_parser *p) { /* Emit Ragel initialization of the parser. */ -#line 3043 "upb/json/parser.c" +#line 3050 "upb/json/parser.c" { cs = json_start; top = 0; } -#line 2643 "upb/json/parser.rl" +#line 2650 "upb/json/parser.rl" p->current_state = cs; p->parser_top = top; accumulate_clear(p); @@ -3055,70 +3062,46 @@ static void json_parser_reset(upb_json_parser *p) { upb_status_clear(&p->status); } -static void free_json_parsermethod(upb_refcounted *r) { - upb_json_parsermethod *method = (upb_json_parsermethod*)r; - - upb_inttable_iter i; - upb_inttable_begin(&i, &method->name_tables); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_value val = upb_inttable_iter_value(&i); - upb_strtable *t = upb_value_getptr(val); - upb_strtable_uninit(t); - upb_gfree(t); - } - - upb_inttable_uninit(&method->name_tables); +static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c, + const upb_msgdef *md) { + upb_msg_field_iter i; + upb_alloc *alloc = upb_arena_alloc(&c->arena); - upb_gfree(r); -} + upb_json_parsermethod *m = upb_gmalloc(sizeof(*m)); -static void add_jsonname_table(upb_json_parsermethod *m, const upb_msgdef* md) { - upb_msg_field_iter i; - upb_strtable *t; + m->cache = c; - /* It would be nice to stack-allocate this, but protobufs do not limit the - * length of fields to any reasonable limit. */ - char *buf = NULL; - size_t len = 0; + upb_byteshandler_init(&m->input_handler_); + upb_byteshandler_setstring(&m->input_handler_, parse, m); + upb_byteshandler_setendstr(&m->input_handler_, end, m); - if (upb_inttable_lookupptr(&m->name_tables, md, NULL)) { - return; - } + upb_strtable_init2(&m->name_table, UPB_CTYPE_CONSTPTR, alloc); - /* TODO(haberman): handle malloc failure. */ - t = upb_gmalloc(sizeof(*t)); - upb_strtable_init(t, UPB_CTYPE_CONSTPTR); - upb_inttable_insertptr(&m->name_tables, md, upb_value_ptr(t)); + /* Build name_table */ for(upb_msg_field_begin(&i, md); !upb_msg_field_done(&i); upb_msg_field_next(&i)) { const upb_fielddef *f = upb_msg_iter_field(&i); + upb_value v = upb_value_constptr(f); + char *buf; /* Add an entry for the JSON name. */ - size_t field_len = upb_fielddef_getjsonname(f, buf, len); - if (field_len > len) { - size_t len2; - buf = upb_grealloc(buf, 0, field_len); - len = field_len; - len2 = upb_fielddef_getjsonname(f, buf, len); - UPB_ASSERT(len == len2); - } - upb_strtable_insert(t, buf, upb_value_constptr(f)); + size_t len = upb_fielddef_getjsonname(f, NULL, 0); + buf = upb_malloc(alloc, len); + upb_fielddef_getjsonname(f, buf, len); + upb_strtable_insert3(&m->name_table, buf, len, v, alloc); if (strcmp(buf, upb_fielddef_name(f)) != 0) { /* Since the JSON name is different from the regular field name, add an * entry for the raw name (compliant proto3 JSON parsers must accept * both). */ - upb_strtable_insert(t, upb_fielddef_name(f), upb_value_constptr(f)); - } - - if (upb_fielddef_issubmsg(f)) { - add_jsonname_table(m, upb_fielddef_msgsubdef(f)); + const char *name = upb_fielddef_name(f); + upb_strtable_insert3(&m->name_table, name, strlen(name), v, alloc); } } - upb_gfree(buf); + return m; } /* Public API *****************************************************************/ @@ -3146,9 +3129,7 @@ upb_json_parser *upb_json_parser_create(upb_env *env, p->top->m = upb_handlers_msgdef(output->handlers); if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) { p->top->is_any = true; - p->top->any_frame = - upb_env_malloc(p->env, sizeof(upb_jsonparser_any_frame)); - json_parser_any_frame_reset(p->top->any_frame); + p->top->any_frame = json_parser_any_frame_new(p); } else { p->top->is_any = false; p->top->any_frame = NULL; @@ -3169,24 +3150,61 @@ upb_bytessink *upb_json_parser_input(upb_json_parser *p) { return &p->input_; } -upb_json_parsermethod *upb_json_parsermethod_new(const upb_msgdef* md, - const void* owner) { - static const struct upb_refcounted_vtbl vtbl = {NULL, free_json_parsermethod}; - upb_json_parsermethod *ret = upb_gmalloc(sizeof(*ret)); - upb_refcounted_init(upb_json_parsermethod_upcast_mutable(ret), &vtbl, owner); +const upb_byteshandler *upb_json_parsermethod_inputhandler( + const upb_json_parsermethod *m) { + return &m->input_handler_; +} + +upb_json_codecache *upb_json_codecache_new() { + upb_alloc *alloc; + upb_json_codecache *c; - upb_byteshandler_init(&ret->input_handler_); - upb_byteshandler_setstring(&ret->input_handler_, parse, ret); - upb_byteshandler_setendstr(&ret->input_handler_, end, ret); + c = upb_gmalloc(sizeof(*c)); - upb_inttable_init(&ret->name_tables, UPB_CTYPE_PTR); + upb_arena_init(&c->arena); + alloc = upb_arena_alloc(&c->arena); - add_jsonname_table(ret, md); + upb_inttable_init2(&c->methods, UPB_CTYPE_CONSTPTR, alloc); - return ret; + return c; } -const upb_byteshandler *upb_json_parsermethod_inputhandler( - const upb_json_parsermethod *m) { - return &m->input_handler_; +void upb_json_codecache_free(upb_json_codecache *c) { + upb_arena_uninit(&c->arena); + upb_gfree(c); +} + +upb_json_parsermethod *upb_json_codecache_get(upb_json_codecache *c, + const upb_msgdef *md) { + upb_json_parsermethod *m; + upb_value v; + upb_msg_field_iter i; + + if (upb_inttable_lookupptr(&c->methods, md, &v)) { + return upb_value_getptr(v); + } + + m = parsermethod_new(c, md); + v = upb_value_ptr(m); + + if (!m) return NULL; + if (!upb_inttable_insertptr(&c->methods, m, v)) return NULL; + + /* Populate parser methods for all submessages, so the name tables will + * be available during parsing. */ + for(upb_msg_field_begin(&i, md); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { + upb_fielddef *f = upb_msg_iter_field(&i); + + if (upb_fielddef_issubmsg(f)) { + const upb_msgdef *subdef = upb_fielddef_msgsubdef(f); + const upb_json_parsermethod *sub_method = + upb_json_codecache_get(c, subdef); + + if (!sub_method) return NULL; + } + } + + return m; } diff --git a/upb/json/parser.h b/upb/json/parser.h index 91b08d8..d5ec396 100644 --- a/upb/json/parser.h +++ b/upb/json/parser.h @@ -13,6 +13,7 @@ #ifdef __cplusplus namespace upb { namespace json { +class CodeCache; class Parser; class ParserMethod; } /* namespace json */ @@ -20,8 +21,8 @@ class ParserMethod; #endif UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser) -UPB_DECLARE_DERIVED_TYPE(upb::json::ParserMethod, upb::RefCounted, - upb_json_parsermethod, upb_refcounted) +UPB_DECLARE_TYPE(upb::json::ParserMethod, upb_json_parsermethod) +UPB_DECLARE_TYPE(upb::json::CodeCache, upb_json_codecache) /* upb::json::Parser **********************************************************/ @@ -49,18 +50,6 @@ class upb::json::Parser { class upb::json::ParserMethod { public: - /* Include base methods from upb::ReferenceCounted. */ - UPB_REFCOUNTED_CPPMETHODS - - /* Returns handlers for parsing according to the specified schema. - * The MessageDef must outlive the ParserMethod. */ - static reffed_ptr New(const upb::MessageDef* md); - - /* The destination handlers that are statically bound to this method. - * This method is only capable of outputting to a sink that uses these - * handlers. */ - const Handlers* dest_handlers() const; - /* The input handlers for this decoder method. */ const BytesHandler* input_handler() const; @@ -68,6 +57,19 @@ class upb::json::ParserMethod { UPB_DISALLOW_POD_OPS(ParserMethod, upb::json::ParserMethod) }; +class upb::json::CodeCache { + public: + static CodeCache* New(); + static void Free(CodeCache* cache); + + /* Returns a DecoderMethod that can push data to the given handlers. + * If a suitable method already exists, it will be returned from the cache. */ + const ParserMethod *Get(const MessageDef* md); + + private: + UPB_DISALLOW_POD_OPS(CodeCache, upb::json::CodeCache) +}; + #endif UPB_BEGIN_EXTERN_C @@ -79,15 +81,13 @@ upb_json_parser* upb_json_parser_create(upb_env* e, bool ignore_json_unknown); upb_bytessink *upb_json_parser_input(upb_json_parser *p); -upb_json_parsermethod* upb_json_parsermethod_new(const upb_msgdef* md, - const void* owner); -const upb_handlers *upb_json_parsermethod_desthandlers( - const upb_json_parsermethod *m); const upb_byteshandler *upb_json_parsermethod_inputhandler( const upb_json_parsermethod *m); -/* Include refcounted methods like upb_json_parsermethod_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_json_parsermethod, upb_json_parsermethod_upcast) +upb_json_codecache *upb_json_codecache_new(); +void upb_json_codecache_free(upb_json_codecache *cache); +upb_json_parsermethod* upb_json_codecache_get(upb_json_codecache* cache, + const upb_msgdef* md); UPB_END_EXTERN_C @@ -105,17 +105,12 @@ inline BytesSink* Parser::input() { return upb_json_parser_input(this); } -inline const Handlers* ParserMethod::dest_handlers() const { - return upb_json_parsermethod_desthandlers(this); -} inline const BytesHandler* ParserMethod::input_handler() const { return upb_json_parsermethod_inputhandler(this); } /* static */ -inline reffed_ptr ParserMethod::New( - const MessageDef* md) { - const upb_json_parsermethod *m = upb_json_parsermethod_new(md, &m); - return reffed_ptr(m, &m); +inline const ParserMethod* CodeCache::Get(const MessageDef* md) { + return upb_json_codecache_get(this, md); } } /* namespace json */ @@ -123,5 +118,4 @@ inline reffed_ptr ParserMethod::New( #endif - #endif /* UPB_JSON_PARSER_H_ */ diff --git a/upb/json/parser.rl b/upb/json/parser.rl index 3a32fd9..c2866c9 100644 --- a/upb/json/parser.rl +++ b/upb/json/parser.rl @@ -152,14 +152,13 @@ void upb_stringsink_uninit(upb_stringsink *sink) { free(sink->ptr); } typedef struct { /* For encoding Any value field in binary format. */ - const upb_handlers *encoder_handlers; - upb_pb_encoder *encoder; + upb_handlercache *encoder_handlercache; upb_stringsink stringsink; /* For decoding Any value field in json format. */ - upb_json_parsermethod *parser_method; - upb_json_parser* parser; + upb_json_codecache *parser_codecache; upb_sink sink; + upb_json_parser *parser; /* Mark the range of uninterpreted values in json input before type url. */ const char *before_type_url_start; @@ -178,7 +177,7 @@ typedef struct { const upb_fielddef *f; /* The table mapping json name to fielddef for this message. */ - upb_strtable *name_table; + const upb_strtable *name_table; /* We are in a repeated-field context, ready to emit mapentries as * submessages. This flag alters the start-of-object (open-brace) behavior to @@ -257,60 +256,67 @@ struct upb_json_parser { struct tm tm; }; -struct upb_json_parsermethod { - upb_refcounted base; +struct upb_json_codecache { + upb_arena arena; + upb_inttable methods; /* upb_msgdef* -> upb_json_parsermethod* */ +}; +struct upb_json_parsermethod { + const upb_json_codecache *cache; upb_byteshandler input_handler_; - /* Keys are upb_msgdef*, values are upb_strtable (json_name -> fielddef) */ - upb_inttable name_tables; + /* Maps json_name -> fielddef */ + upb_strtable name_table; }; #define PARSER_CHECK_RETURN(x) if (!(x)) return false -static void json_parser_any_frame_reset(upb_jsonparser_any_frame *frame) { - frame->encoder_handlers = NULL; - frame->encoder = NULL; - frame->parser_method = NULL; +static upb_jsonparser_any_frame *json_parser_any_frame_new( + upb_json_parser *p) { + upb_jsonparser_any_frame *frame; + + frame = upb_env_malloc(p->env, sizeof(upb_jsonparser_any_frame)); + + frame->encoder_handlercache = upb_pb_encoder_newcache(); + frame->parser_codecache = upb_json_codecache_new(); frame->parser = NULL; frame->before_type_url_start = NULL; frame->before_type_url_end = NULL; frame->after_type_url_start = NULL; + + upb_stringsink_init(&frame->stringsink); + + return frame; } static void json_parser_any_frame_set_payload_type( upb_json_parser *p, upb_jsonparser_any_frame *frame, const upb_msgdef *payload_type) { + const upb_handlers *h; + const upb_json_parsermethod *parser_method; + upb_pb_encoder *encoder; + /* Initialize encoder. */ - frame->encoder_handlers = - upb_pb_encoder_newhandlers(payload_type, &frame->encoder_handlers); - upb_stringsink_init(&frame->stringsink); - frame->encoder = - upb_pb_encoder_create( - p->env, frame->encoder_handlers, - &frame->stringsink.sink); + h = upb_handlercache_get(frame->encoder_handlercache, payload_type); + encoder = upb_pb_encoder_create(p->env, h, &frame->stringsink.sink); /* Initialize parser. */ - frame->parser_method = - upb_json_parsermethod_new(payload_type, &frame->parser_method); - upb_sink_reset(&frame->sink, frame->encoder_handlers, frame->encoder); - frame->parser = - upb_json_parser_create(p->env, frame->parser_method, p->symtab, - &frame->sink, p->ignore_json_unknown); + parser_method = upb_json_codecache_get(frame->parser_codecache, payload_type); + upb_sink_reset(&frame->sink, h, encoder); + frame->parser = upb_json_parser_create(p->env, parser_method, p->symtab, + &frame->sink, p->ignore_json_unknown); } static void json_parser_any_frame_free(upb_jsonparser_any_frame *frame) { - upb_handlers_unref(frame->encoder_handlers, - &frame->encoder_handlers); - upb_json_parsermethod_unref(frame->parser_method, - &frame->parser_method); + upb_handlercache_free(frame->encoder_handlercache); + upb_json_codecache_free(frame->parser_codecache); upb_stringsink_uninit(&frame->stringsink); } static bool json_parser_any_frame_has_type_url( upb_jsonparser_any_frame *frame) { - return frame->encoder != NULL; + return frame->parser != NULL; } static bool json_parser_any_frame_has_value_before_type_url( @@ -332,7 +338,7 @@ static bool json_parser_any_frame_has_value( static void json_parser_any_frame_set_before_type_url_end( upb_jsonparser_any_frame *frame, const char *ptr) { - if (frame->encoder == NULL) { + if (frame->parser == NULL) { frame->before_type_url_end = ptr; } } @@ -374,9 +380,12 @@ static bool check_stack(upb_json_parser *p) { static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) { upb_value v; - bool ok = upb_inttable_lookupptr(&p->method->name_tables, frame->m, &v); + const upb_json_codecache *cache = p->method->cache; + bool ok = upb_inttable_lookupptr(&cache->methods, frame->m, &v); + const upb_json_parsermethod *method = upb_value_getptr(v); UPB_ASSERT(ok); - frame->name_table = upb_value_getptr(v); + + frame->name_table = &method->name_table; } /* There are GCC/Clang built-ins for overflow checking which we could start @@ -1927,9 +1936,7 @@ static bool start_subobject(upb_json_parser *p) { if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) { p->top->is_any = true; - p->top->any_frame = - upb_env_malloc(p->env, sizeof(upb_jsonparser_any_frame)); - json_parser_any_frame_reset(p->top->any_frame); + p->top->any_frame = json_parser_any_frame_new(p); } else { p->top->is_any = false; p->top->any_frame = NULL; @@ -2649,70 +2656,46 @@ static void json_parser_reset(upb_json_parser *p) { upb_status_clear(&p->status); } -static void free_json_parsermethod(upb_refcounted *r) { - upb_json_parsermethod *method = (upb_json_parsermethod*)r; +static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c, + const upb_msgdef *md) { + upb_msg_field_iter i; + upb_alloc *alloc = upb_arena_alloc(&c->arena); - upb_inttable_iter i; - upb_inttable_begin(&i, &method->name_tables); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_value val = upb_inttable_iter_value(&i); - upb_strtable *t = upb_value_getptr(val); - upb_strtable_uninit(t); - upb_gfree(t); - } + upb_json_parsermethod *m = upb_gmalloc(sizeof(*m)); - upb_inttable_uninit(&method->name_tables); + m->cache = c; - upb_gfree(r); -} + upb_byteshandler_init(&m->input_handler_); + upb_byteshandler_setstring(&m->input_handler_, parse, m); + upb_byteshandler_setendstr(&m->input_handler_, end, m); -static void add_jsonname_table(upb_json_parsermethod *m, const upb_msgdef* md) { - upb_msg_field_iter i; - upb_strtable *t; + upb_strtable_init2(&m->name_table, UPB_CTYPE_CONSTPTR, alloc); - /* It would be nice to stack-allocate this, but protobufs do not limit the - * length of fields to any reasonable limit. */ - char *buf = NULL; - size_t len = 0; - - if (upb_inttable_lookupptr(&m->name_tables, md, NULL)) { - return; - } - - /* TODO(haberman): handle malloc failure. */ - t = upb_gmalloc(sizeof(*t)); - upb_strtable_init(t, UPB_CTYPE_CONSTPTR); - upb_inttable_insertptr(&m->name_tables, md, upb_value_ptr(t)); + /* Build name_table */ for(upb_msg_field_begin(&i, md); !upb_msg_field_done(&i); upb_msg_field_next(&i)) { const upb_fielddef *f = upb_msg_iter_field(&i); + upb_value v = upb_value_constptr(f); + char *buf; /* Add an entry for the JSON name. */ - size_t field_len = upb_fielddef_getjsonname(f, buf, len); - if (field_len > len) { - size_t len2; - buf = upb_grealloc(buf, 0, field_len); - len = field_len; - len2 = upb_fielddef_getjsonname(f, buf, len); - UPB_ASSERT(len == len2); - } - upb_strtable_insert(t, buf, upb_value_constptr(f)); + size_t len = upb_fielddef_getjsonname(f, NULL, 0); + buf = upb_malloc(alloc, len); + upb_fielddef_getjsonname(f, buf, len); + upb_strtable_insert3(&m->name_table, buf, len, v, alloc); if (strcmp(buf, upb_fielddef_name(f)) != 0) { /* Since the JSON name is different from the regular field name, add an * entry for the raw name (compliant proto3 JSON parsers must accept * both). */ - upb_strtable_insert(t, upb_fielddef_name(f), upb_value_constptr(f)); - } - - if (upb_fielddef_issubmsg(f)) { - add_jsonname_table(m, upb_fielddef_msgsubdef(f)); + const char *name = upb_fielddef_name(f); + upb_strtable_insert3(&m->name_table, name, strlen(name), v, alloc); } } - upb_gfree(buf); + return m; } /* Public API *****************************************************************/ @@ -2740,9 +2723,7 @@ upb_json_parser *upb_json_parser_create(upb_env *env, p->top->m = upb_handlers_msgdef(output->handlers); if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) { p->top->is_any = true; - p->top->any_frame = - upb_env_malloc(p->env, sizeof(upb_jsonparser_any_frame)); - json_parser_any_frame_reset(p->top->any_frame); + p->top->any_frame = json_parser_any_frame_new(p); } else { p->top->is_any = false; p->top->any_frame = NULL; @@ -2763,24 +2744,61 @@ upb_bytessink *upb_json_parser_input(upb_json_parser *p) { return &p->input_; } -upb_json_parsermethod *upb_json_parsermethod_new(const upb_msgdef* md, - const void* owner) { - static const struct upb_refcounted_vtbl vtbl = {NULL, free_json_parsermethod}; - upb_json_parsermethod *ret = upb_gmalloc(sizeof(*ret)); - upb_refcounted_init(upb_json_parsermethod_upcast_mutable(ret), &vtbl, owner); +const upb_byteshandler *upb_json_parsermethod_inputhandler( + const upb_json_parsermethod *m) { + return &m->input_handler_; +} + +upb_json_codecache *upb_json_codecache_new() { + upb_alloc *alloc; + upb_json_codecache *c; - upb_byteshandler_init(&ret->input_handler_); - upb_byteshandler_setstring(&ret->input_handler_, parse, ret); - upb_byteshandler_setendstr(&ret->input_handler_, end, ret); + c = upb_gmalloc(sizeof(*c)); - upb_inttable_init(&ret->name_tables, UPB_CTYPE_PTR); + upb_arena_init(&c->arena); + alloc = upb_arena_alloc(&c->arena); - add_jsonname_table(ret, md); + upb_inttable_init2(&c->methods, UPB_CTYPE_CONSTPTR, alloc); - return ret; + return c; } -const upb_byteshandler *upb_json_parsermethod_inputhandler( - const upb_json_parsermethod *m) { - return &m->input_handler_; +void upb_json_codecache_free(upb_json_codecache *c) { + upb_arena_uninit(&c->arena); + upb_gfree(c); +} + +upb_json_parsermethod *upb_json_codecache_get(upb_json_codecache *c, + const upb_msgdef *md) { + upb_json_parsermethod *m; + upb_value v; + upb_msg_field_iter i; + + if (upb_inttable_lookupptr(&c->methods, md, &v)) { + return upb_value_getptr(v); + } + + m = parsermethod_new(c, md); + v = upb_value_ptr(m); + + if (!m) return NULL; + if (!upb_inttable_insertptr(&c->methods, m, v)) return NULL; + + /* Populate parser methods for all submessages, so the name tables will + * be available during parsing. */ + for(upb_msg_field_begin(&i, md); + !upb_msg_field_done(&i); + upb_msg_field_next(&i)) { + upb_fielddef *f = upb_msg_iter_field(&i); + + if (upb_fielddef_issubmsg(f)) { + const upb_msgdef *subdef = upb_fielddef_msgsubdef(f); + const upb_json_parsermethod *sub_method = + upb_json_codecache_get(c, subdef); + + if (!sub_method) return NULL; + } + } + + return m; } diff --git a/upb/json/printer.c b/upb/json/printer.c index 95a4ad5..444916f 100644 --- a/upb/json/printer.c +++ b/upb/json/printer.c @@ -48,6 +48,10 @@ void freestrpc(void *ptr) { upb_gfree(pc); } +typedef struct { + bool preserve_fieldnames; +} upb_json_printercache; + /* Convert fielddef name to JSON name and return as a string piece. */ strpc *newstrpc(upb_handlers *h, const upb_fielddef *f, bool preserve_fieldnames) { @@ -1112,8 +1116,8 @@ void printer_sethandlers(const void *closure, upb_handlers *h) { bool is_mapentry = upb_msgdef_mapentry(md); upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; upb_msg_field_iter i; - const bool *preserve_fieldnames_ptr = closure; - const bool preserve_fieldnames = *preserve_fieldnames_ptr; + const upb_json_printercache *cache = closure; + const bool preserve_fieldnames = cache->preserve_fieldnames; if (is_mapentry) { /* mapentry messages are sufficiently different that we handle them @@ -1281,9 +1285,8 @@ upb_sink *upb_json_printer_input(upb_json_printer *p) { return &p->input_; } -const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md, - bool preserve_fieldnames, - const void *owner) { - return upb_handlers_newfrozen( - md, owner, printer_sethandlers, &preserve_fieldnames); +upb_handlercache *upb_json_printer_newcache(bool preserve_proto_fieldnames) { + upb_json_printercache *cache = upb_gmalloc(sizeof(*cache)); + cache->preserve_fieldnames = preserve_proto_fieldnames; + return upb_handlercache_new(printer_sethandlers, cache); } diff --git a/upb/json/printer.h b/upb/json/printer.h index 80644f1..fe9c8f1 100644 --- a/upb/json/printer.h +++ b/upb/json/printer.h @@ -35,14 +35,8 @@ class upb::json::Printer { /* The input to the printer. */ Sink* input(); - /* Returns handlers for printing according to the specified schema. - * If preserve_proto_fieldnames is true, the output JSON will use the - * original .proto field names (ie. {"my_field":3}) instead of using - * camelCased names, which is the default: (eg. {"myField":3}). */ - static reffed_ptr NewHandlers(const upb::MessageDef* md, - bool preserve_proto_fieldnames); - static const size_t kSize = UPB_JSON_PRINTER_SIZE; + static upb_handlercache* NewCache(bool preserve_proto_fieldnames); private: UPB_DISALLOW_POD_OPS(Printer, upb::json::Printer) @@ -60,6 +54,8 @@ const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md, bool preserve_fieldnames, const void *owner); +upb_handlercache *upb_json_printer_newcache(bool preserve_proto_fieldnames); + UPB_END_EXTERN_C #ifdef __cplusplus @@ -71,11 +67,8 @@ inline Printer* Printer::Create(Environment* env, const upb::Handlers* handlers, return upb_json_printer_create(env, handlers, output); } inline Sink* Printer::input() { return upb_json_printer_input(this); } -inline reffed_ptr Printer::NewHandlers( - const upb::MessageDef *md, bool preserve_proto_fieldnames) { - const Handlers* h = upb_json_printer_newhandlers( - md, preserve_proto_fieldnames, &h); - return reffed_ptr(h, &h); +inline upb_handlercache* Printer::NewCache(bool preserve_proto_fieldnames) { + return upb_json_printer_newcache(preserve_proto_fieldnames); } } /* namespace json */ } /* namespace upb */ diff --git a/upb/msgfactory.c b/upb/msgfactory.c index 63df49e..23dd79a 100644 --- a/upb/msgfactory.c +++ b/upb/msgfactory.c @@ -197,7 +197,6 @@ static bool upb_msglayout_init(const upb_msgdef *m, struct upb_msgfactory { const upb_symtab *symtab; /* We own a ref. */ upb_inttable layouts; - upb_inttable mergehandlers; }; upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab) { @@ -205,7 +204,6 @@ upb_msgfactory *upb_msgfactory_new(const upb_symtab *symtab) { ret->symtab = symtab; upb_inttable_init(&ret->layouts, UPB_CTYPE_PTR); - upb_inttable_init(&ret->mergehandlers, UPB_CTYPE_CONSTPTR); return ret; } @@ -218,14 +216,7 @@ void upb_msgfactory_free(upb_msgfactory *f) { upb_msglayout_free(l); } - upb_inttable_begin(&i, &f->mergehandlers); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - const upb_handlers *h = upb_value_getconstptr(upb_inttable_iter_value(&i)); - upb_handlers_unref(h, f); - } - upb_inttable_uninit(&f->layouts); - upb_inttable_uninit(&f->mergehandlers); upb_gfree(f); } diff --git a/upb/pb/compile_decoder.c b/upb/pb/compile_decoder.c index d147edf..02f5179 100644 --- a/upb/pb/compile_decoder.c +++ b/upb/pb/compile_decoder.c @@ -23,80 +23,23 @@ #define MAXLABEL 5 #define EMPTYLABEL -1 -/* mgroup *********************************************************************/ - -static void freegroup(upb_refcounted *r) { - mgroup *g = (mgroup*)r; - upb_inttable_uninit(&g->methods); -#ifdef UPB_USE_JIT_X64 - upb_pbdecoder_freejit(g); -#endif - upb_gfree(g->bytecode); - upb_gfree(g); -} - -static void visitgroup(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const mgroup *g = (const mgroup*)r; - upb_inttable_iter i; - upb_inttable_begin(&i, &g->methods); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_pbdecodermethod *method = upb_value_getptr(upb_inttable_iter_value(&i)); - visit(r, upb_pbdecodermethod_upcast(method), closure); - } -} - -mgroup *newgroup(const void *owner) { - mgroup *g = upb_gmalloc(sizeof(*g)); - static const struct upb_refcounted_vtbl vtbl = {visitgroup, freegroup}; - upb_refcounted_init(mgroup_upcast_mutable(g), &vtbl, owner); - upb_inttable_init(&g->methods, UPB_CTYPE_PTR); - g->bytecode = NULL; - g->bytecode_end = NULL; - return g; -} - - /* upb_pbdecodermethod ********************************************************/ -static void freemethod(upb_refcounted *r) { - upb_pbdecodermethod *method = (upb_pbdecodermethod*)r; - - if (method->dest_handlers_) { - upb_handlers_unref(method->dest_handlers_, method); - } - +static void freemethod(upb_pbdecodermethod *method) { upb_inttable_uninit(&method->dispatch); upb_gfree(method); } -static void visitmethod(const upb_refcounted *r, upb_refcounted_visit *visit, - void *closure) { - const upb_pbdecodermethod *m = (const upb_pbdecodermethod*)r; - visit(r, m->group, closure); -} - static upb_pbdecodermethod *newmethod(const upb_handlers *dest_handlers, mgroup *group) { - static const struct upb_refcounted_vtbl vtbl = {visitmethod, freemethod}; upb_pbdecodermethod *ret = upb_gmalloc(sizeof(*ret)); - upb_refcounted_init(upb_pbdecodermethod_upcast_mutable(ret), &vtbl, &ret); upb_byteshandler_init(&ret->input_handler_); - /* The method references the group and vice-versa, in a circular reference. */ - upb_ref2(ret, group); - upb_ref2(group, ret); - upb_inttable_insertptr(&group->methods, dest_handlers, upb_value_ptr(ret)); - upb_pbdecodermethod_unref(ret, &ret); - - ret->group = mgroup_upcast_mutable(group); + ret->group = group; ret->dest_handlers_ = dest_handlers; ret->is_native_ = 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; } @@ -114,16 +57,31 @@ bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m) { return m->is_native_; } -const upb_pbdecodermethod *upb_pbdecodermethod_new( - const upb_pbdecodermethodopts *opts, const void *owner) { - const upb_pbdecodermethod *ret; - upb_pbcodecache cache; - upb_pbcodecache_init(&cache); - ret = upb_pbcodecache_getdecodermethod(&cache, opts); - upb_pbdecodermethod_ref(ret, owner); - upb_pbcodecache_uninit(&cache); - return ret; +/* mgroup *********************************************************************/ + +static void freegroup(mgroup *g) { + upb_inttable_iter i; + + upb_inttable_begin(&i, &g->methods); + for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { + freemethod(upb_value_getptr(upb_inttable_iter_value(&i))); + } + + upb_inttable_uninit(&g->methods); +#ifdef UPB_USE_JIT_X64 + upb_pbdecoder_freejit(g); +#endif + upb_gfree(g->bytecode); + upb_gfree(g); +} + +mgroup *newgroup() { + mgroup *g = upb_gmalloc(sizeof(*g)); + upb_inttable_init(&g->methods, UPB_CTYPE_PTR); + g->bytecode = NULL; + g->bytecode_end = NULL; + return g; } @@ -814,10 +772,13 @@ static void find_methods(compiler *c, const upb_handlers *h) { upb_value v; upb_msg_field_iter i; const upb_msgdef *md; + upb_pbdecodermethod *method; if (upb_inttable_lookupptr(&c->group->methods, h, &v)) return; - newmethod(h, c->group); + + method = newmethod(h, c->group); + upb_inttable_insertptr(&c->group->methods, h, upb_value_ptr(method)); /* Find submethods. */ md = upb_handlers_msgdef(h); @@ -893,15 +854,13 @@ static void sethandlers(mgroup *g, bool allowjit) { /* TODO(haberman): allow this to be constructed for an arbitrary set of dest * handlers and other mgroups (but verify we have a transitive closure). */ -const mgroup *mgroup_new(const upb_handlers *dest, bool allowjit, bool lazy, - const void *owner) { +const mgroup *mgroup_new(const upb_handlers *dest, bool allowjit, bool lazy) { mgroup *g; compiler *c; UPB_UNUSED(allowjit); - UPB_ASSERT(upb_handlers_isfrozen(dest)); - g = newgroup(owner); + g = newgroup(); c = newcompiler(g, lazy); find_methods(c, dest); @@ -939,56 +898,63 @@ const mgroup *mgroup_new(const upb_handlers *dest, bool allowjit, bool lazy, /* upb_pbcodecache ************************************************************/ -void upb_pbcodecache_init(upb_pbcodecache *c) { - upb_inttable_init(&c->groups, UPB_CTYPE_CONSTPTR); - c->allow_jit_ = true; +upb_pbcodecache *upb_pbcodecache_new(upb_handlercache *dest) { + upb_pbcodecache *c = upb_gmalloc(sizeof(*c)); + + if (!c) return NULL; + + c->dest = dest; + c->allow_jit = true; + c->lazy = false; + + upb_arena_init(&c->arena); + if (!upb_inttable_init(&c->groups, UPB_CTYPE_CONSTPTR)) return NULL; + + return c; } -void upb_pbcodecache_uninit(upb_pbcodecache *c) { - upb_inttable_iter i; - upb_inttable_begin(&i, &c->groups); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - const mgroup *group = upb_value_getconstptr(upb_inttable_iter_value(&i)); - mgroup_unref(group, c); +void upb_pbcodecache_free(upb_pbcodecache *c) { + size_t i; + + for (i = 0; i < upb_inttable_count(&c->groups); i++) { + upb_value v; + bool ok = upb_inttable_lookup(&c->groups, i, &v); + UPB_ASSERT(ok); + freegroup((void*)upb_value_getconstptr(v)); } + upb_inttable_uninit(&c->groups); + upb_gfree(c); } bool upb_pbcodecache_allowjit(const upb_pbcodecache *c) { - return c->allow_jit_; + return c->allow_jit; } -bool upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow) { - if (upb_inttable_count(&c->groups) > 0) - return false; - c->allow_jit_ = allow; - return true; +void upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow) { + UPB_ASSERT(upb_inttable_count(&c->groups) == 0); + c->allow_jit = allow; } -const upb_pbdecodermethod *upb_pbcodecache_getdecodermethod( - upb_pbcodecache *c, const upb_pbdecodermethodopts *opts) { +void upb_pbdecodermethodopts_setlazy(upb_pbcodecache *c, bool lazy) { + UPB_ASSERT(upb_inttable_count(&c->groups) == 0); + c->lazy = lazy; +} + +const upb_pbdecodermethod *upb_pbcodecache_get(upb_pbcodecache *c, + const upb_msgdef *md) { upb_value v; bool ok; + const upb_handlers *h; + const mgroup *g; /* Right now we build a new DecoderMethod every time. * TODO(haberman): properly cache methods by their true key. */ - const mgroup *g = mgroup_new(opts->handlers, c->allow_jit_, opts->lazy, c); + h = upb_handlercache_get(c->dest, md); + g = mgroup_new(h, c->allow_jit, c->lazy); upb_inttable_push(&c->groups, upb_value_constptr(g)); - ok = upb_inttable_lookupptr(&g->methods, opts->handlers, &v); + ok = upb_inttable_lookupptr(&g->methods, h, &v); UPB_ASSERT(ok); return upb_value_getptr(v); } - - -/* upb_pbdecodermethodopts ****************************************************/ - -void upb_pbdecodermethodopts_init(upb_pbdecodermethodopts *opts, - const upb_handlers *h) { - opts->handlers = h; - opts->lazy = false; -} - -void upb_pbdecodermethodopts_setlazy(upb_pbdecodermethodopts *opts, bool lazy) { - opts->lazy = lazy; -} diff --git a/upb/pb/decoder.h b/upb/pb/decoder.h index 7c1877a..1a00801 100644 --- a/upb/pb/decoder.h +++ b/upb/pb/decoder.h @@ -30,10 +30,7 @@ class DecoderMethodOptions; UPB_DECLARE_TYPE(upb::pb::CodeCache, upb_pbcodecache) UPB_DECLARE_TYPE(upb::pb::Decoder, upb_pbdecoder) -UPB_DECLARE_TYPE(upb::pb::DecoderMethodOptions, upb_pbdecodermethodopts) - -UPB_DECLARE_DERIVED_TYPE(upb::pb::DecoderMethod, upb::RefCounted, - upb_pbdecodermethod, upb_refcounted) +UPB_DECLARE_TYPE(upb::pb::DecoderMethod, upb_pbdecodermethod) /* The maximum number of bytes we are required to buffer internally between * calls to the decoder. The value is 14: a 5 byte unknown tag plus ten-byte @@ -44,35 +41,10 @@ UPB_DECLARE_DERIVED_TYPE(upb::pb::DecoderMethod, upb::RefCounted, #ifdef __cplusplus -/* The parameters one uses to construct a DecoderMethod. - * TODO(haberman): move allowjit here? Seems more convenient for users. - * TODO(haberman): move this to be heap allocated for ABI stability. */ -class upb::pb::DecoderMethodOptions { - public: - /* Parameter represents the destination handlers that this method will push - * to. */ - explicit DecoderMethodOptions(const Handlers* dest_handlers); - - /* Should the decoder push submessages to lazy handlers for fields that have - * them? The caller should set this iff the lazy handlers expect data that is - * in protobuf binary format and the caller wishes to lazy parse it. */ - void set_lazy(bool lazy); -#else -struct upb_pbdecodermethodopts { -#endif - const upb_handlers *handlers; - bool lazy; -}; - -#ifdef __cplusplus - /* Represents the code to parse a protobuf according to a destination * Handlers. */ class upb::pb::DecoderMethod { public: - /* Include base methods from upb::ReferenceCounted. */ - UPB_REFCOUNTED_CPPMETHODS - /* The destination handlers that are statically bound to this method. * This method is only capable of outputting to a sink that uses these * handlers. */ @@ -84,10 +56,6 @@ class upb::pb::DecoderMethod { /* Whether this method is native. */ bool is_native() const; - /* Convenience method for generating a DecoderMethod without explicitly - * creating a CodeCache. */ - static reffed_ptr New(const DecoderMethodOptions& opts); - private: UPB_DISALLOW_POD_OPS(DecoderMethod, upb::pb::DecoderMethod) }; @@ -147,20 +115,14 @@ class upb::pb::Decoder { UPB_DISALLOW_POD_OPS(Decoder, upb::pb::Decoder) }; -#endif /* __cplusplus */ - -#ifdef __cplusplus - /* A class for caching protobuf processing code, whether bytecode for the * interpreted decoder or machine code for the JIT. * - * This class is not thread-safe. - * - * TODO(haberman): move this to be heap allocated for ABI stability. */ + * This class is not thread-safe. */ class upb::pb::CodeCache { public: - CodeCache(); - ~CodeCache(); + static CodeCache* New(HandlerCache* dest); + static void Free(CodeCache* cache); /* Whether the cache is allowed to generate machine code. Defaults to true. * There is no real reason to turn it off except for testing or if you are @@ -172,33 +134,24 @@ class upb::pb::CodeCache { bool allow_jit() const; /* This may only be called when the object is first constructed, and prior to - * any code generation, otherwise returns false and does nothing. */ - bool set_allow_jit(bool allow); + * any code generation. */ + void set_allow_jit(bool allow); - /* Returns a DecoderMethod that can push data to the given handlers. - * If a suitable method already exists, it will be returned from the cache. - * - * Specifying the destination handlers here allows the DecoderMethod to be - * statically bound to the destination handlers if possible, which can allow - * more efficient decoding. However the returned method may or may not - * actually be statically bound. But in all cases, the returned method can - * push data to the given handlers. */ - const DecoderMethod *GetDecoderMethod(const DecoderMethodOptions& opts); + /* Should the decoder push submessages to lazy handlers for fields that have + * them? The caller should set this iff the lazy handlers expect data that is + * in protobuf binary format and the caller wishes to lazy parse it. */ + void set_lazy(bool lazy); - /* If/when someone needs to explicitly create a dynamically-bound - * DecoderMethod*, we can add a method to get it here. */ + /* Returns a DecoderMethod that can push data to the given handlers. + * If a suitable method already exists, it will be returned from the cache. */ + const DecoderMethod *Get(const MessageDef* md); private: - UPB_DISALLOW_COPY_AND_ASSIGN(CodeCache) -#else -struct upb_pbcodecache { -#endif - bool allow_jit_; - - /* Array of mgroups. */ - upb_inttable groups; + UPB_DISALLOW_POD_OPS(CodeCache, upb::pb::CodeCache) }; +#endif + UPB_BEGIN_EXTERN_C upb_pbdecoder *upb_pbdecoder_create(upb_env *e, @@ -211,28 +164,21 @@ size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d); bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max); void upb_pbdecoder_reset(upb_pbdecoder *d); -void upb_pbdecodermethodopts_init(upb_pbdecodermethodopts *opts, - const upb_handlers *h); -void upb_pbdecodermethodopts_setlazy(upb_pbdecodermethodopts *opts, bool lazy); -/* Include refcounted methods like upb_pbdecodermethod_ref(). */ -UPB_REFCOUNTED_CMETHODS(upb_pbdecodermethod, upb_pbdecodermethod_upcast) - const upb_handlers *upb_pbdecodermethod_desthandlers( const upb_pbdecodermethod *m); const upb_byteshandler *upb_pbdecodermethod_inputhandler( const upb_pbdecodermethod *m); bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m); -const upb_pbdecodermethod *upb_pbdecodermethod_new( - const upb_pbdecodermethodopts *opts, const void *owner); -void upb_pbcodecache_init(upb_pbcodecache *c); -void upb_pbcodecache_uninit(upb_pbcodecache *c); +upb_pbcodecache *upb_pbcodecache_new(upb_handlercache *dest); +void upb_pbcodecache_free(upb_pbcodecache *c); bool upb_pbcodecache_allowjit(const upb_pbcodecache *c); -bool upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow); -const upb_pbdecodermethod *upb_pbcodecache_getdecodermethod( - upb_pbcodecache *c, const upb_pbdecodermethodopts *opts); +void upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow); +void upb_pbcodecache_setlazy(upb_pbcodecache *c, bool lazy); +const upb_pbdecodermethod *upb_pbcodecache_get(upb_pbcodecache *c, + const upb_msgdef *md); UPB_END_EXTERN_C @@ -264,13 +210,6 @@ inline bool Decoder::set_max_nesting(size_t max) { } inline void Decoder::Reset() { upb_pbdecoder_reset(this); } -inline DecoderMethodOptions::DecoderMethodOptions(const Handlers* h) { - upb_pbdecodermethodopts_init(this, h); -} -inline void DecoderMethodOptions::set_lazy(bool lazy) { - upb_pbdecodermethodopts_setlazy(this, lazy); -} - inline const Handlers* DecoderMethod::dest_handlers() const { return upb_pbdecodermethod_desthandlers(this); } @@ -280,28 +219,21 @@ inline const BytesHandler* DecoderMethod::input_handler() const { inline bool DecoderMethod::is_native() const { return upb_pbdecodermethod_isnative(this); } -/* static */ -inline reffed_ptr DecoderMethod::New( - const DecoderMethodOptions &opts) { - const upb_pbdecodermethod *m = upb_pbdecodermethod_new(&opts, &m); - return reffed_ptr(m, &m); -} -inline CodeCache::CodeCache() { - upb_pbcodecache_init(this); +inline CodeCache* CodeCache::New(HandlerCache* dest) { + return upb_pbcodecache_new(dest); } -inline CodeCache::~CodeCache() { - upb_pbcodecache_uninit(this); +inline void CodeCache::Free(CodeCache* cache) { + upb_pbcodecache_free(cache); } inline bool CodeCache::allow_jit() const { return upb_pbcodecache_allowjit(this); } -inline bool CodeCache::set_allow_jit(bool allow) { - return upb_pbcodecache_setallowjit(this, allow); +inline void CodeCache::set_allow_jit(bool allow) { + upb_pbcodecache_setallowjit(this, allow); } -inline const DecoderMethod *CodeCache::GetDecoderMethod( - const DecoderMethodOptions& opts) { - return upb_pbcodecache_getdecodermethod(this, &opts); +inline const DecoderMethod *CodeCache::Get(const MessageDef *md) { + return upb_pbcodecache_get(this, md); } } /* namespace pb */ diff --git a/upb/pb/decoder.int.h b/upb/pb/decoder.int.h index f02bdd5..8d464fa 100644 --- a/upb/pb/decoder.int.h +++ b/upb/pb/decoder.int.h @@ -11,17 +11,6 @@ #include "upb/sink.h" #include "upb/table.int.h" -/* C++ names are not actually used since this type isn't exposed to users. */ -#ifdef __cplusplus -namespace upb { -namespace pb { -class MessageGroup; -} /* namespace pb */ -} /* namespace upb */ -#endif -UPB_DECLARE_DERIVED_TYPE(upb::pb::MessageGroup, upb::RefCounted, - mgroup, upb_refcounted) - /* Opcode definitions. The canonical meaning of each opcode is its * implementation in the interpreter (the JIT is written to match this). * @@ -83,30 +72,25 @@ typedef enum { UPB_INLINE opcode getop(uint32_t instr) { return instr & 0xff; } +struct upb_pbcodecache { + upb_arena arena; + upb_handlercache *dest; + bool allow_jit; + bool lazy; + + /* Array of mgroups. */ + upb_inttable groups; +}; + /* Method group; represents a set of decoder methods that had their code - * emitted together, and must therefore be freed together. Immutable once - * created. It is possible we may want to expose this to users at some point. - * - * Overall ownership of Decoder objects looks like this: - * - * +----------+ - * | | <---> DecoderMethod - * | method | - * CodeCache ---> | group | <---> DecoderMethod - * | | - * | (mgroup) | <---> DecoderMethod - * +----------+ - */ -struct mgroup { - upb_refcounted base; - - /* Maps upb_msgdef/upb_handlers -> upb_pbdecodermethod. We own refs on the - * methods. */ + * emitted together. Immutable once created. */ +typedef struct { + /* Maps upb_msgdef/upb_handlers -> upb_pbdecodermethod. Owned by us. + * + * Ideally this would be on pbcodecache (if we were actually caching code). + * Right now we don't actually cache anything, which is wasteful. */ upb_inttable methods; - /* When we add the ability to link to previously existing mgroups, we'll - * need an array of mgroups we reference here, and own refs on them. */ - /* The bytecode for our methods, if any exists. Owned by us. */ uint32_t *bytecode; uint32_t *bytecode_end; @@ -119,7 +103,7 @@ struct mgroup { char *debug_info; void *dl; #endif -}; +} mgroup; /* The maximum that any submessages can be nested. Matches proto2's limit. * This specifies the size of the decoder's statically-sized array and therefore @@ -159,8 +143,6 @@ typedef struct { } upb_pbdecoder_frame; struct upb_pbdecodermethod { - upb_refcounted base; - /* While compiling, the base is relative in "ofs", after compiling it is * absolute in "ptr". */ union { @@ -168,14 +150,8 @@ struct upb_pbdecodermethod { void *ptr; /* Pointer to bytecode or machine code for this method. */ } code_base; - /* The decoder method group to which this method belongs. We own a ref. - * Owning a ref on the entire group is more coarse-grained than is strictly - * necessary; all we truly require is that methods we directly reference - * outlive us, while the group could contain many other messages we don't - * require. But the group represents the messages that were - * allocated+compiled together, so it makes the most sense to free them - * together also. */ - const upb_refcounted *group; + /* The decoder method group to which this method belongs. */ + const mgroup *group; /* Whether this method is native code or bytecode. */ bool is_native_; @@ -276,7 +252,6 @@ const char *upb_pbdecoder_getopname(unsigned int op); /* JIT codegen entry point. */ void upb_pbdecoder_jit(mgroup *group); void upb_pbdecoder_freejit(mgroup *group); -UPB_REFCOUNTED_CMETHODS(mgroup, mgroup_upcast) /* A special label that means "do field dispatch for this message and branch to * wherever that takes you." */ diff --git a/upb/pb/encoder.c b/upb/pb/encoder.c index 839ede0..ca3ca5c 100644 --- a/upb/pb/encoder.c +++ b/upb/pb/encoder.c @@ -526,9 +526,8 @@ void upb_pb_encoder_reset(upb_pb_encoder *e) { /* public API *****************************************************************/ -const upb_handlers *upb_pb_encoder_newhandlers(const upb_msgdef *m, - const void *owner) { - return upb_handlers_newfrozen(m, owner, newhandlers_callback, NULL); +upb_handlercache *upb_pb_encoder_newcache() { + return upb_handlercache_new(newhandlers_callback, NULL); } upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h, diff --git a/upb/pb/encoder.h b/upb/pb/encoder.h index 41b7e7b..eefa385 100644 --- a/upb/pb/encoder.h +++ b/upb/pb/encoder.h @@ -47,7 +47,7 @@ class upb::pb::Encoder { Sink* input(); /* Creates a new set of handlers for this MessageDef. */ - static reffed_ptr NewHandlers(const MessageDef* msg); + static upb_handlercache* NewCache(); static const size_t kSize = UPB_PB_ENCODER_SIZE; @@ -59,12 +59,12 @@ class upb::pb::Encoder { UPB_BEGIN_EXTERN_C -const upb_handlers *upb_pb_encoder_newhandlers(const upb_msgdef *m, - const void *owner); upb_sink *upb_pb_encoder_input(upb_pb_encoder *p); upb_pb_encoder* upb_pb_encoder_create(upb_env* e, const upb_handlers* h, upb_bytessink* output); +upb_handlercache *upb_pb_encoder_newcache(); + UPB_END_EXTERN_C #ifdef __cplusplus @@ -78,10 +78,8 @@ inline Encoder* Encoder::Create(Environment* env, const Handlers* handlers, inline Sink* Encoder::input() { return upb_pb_encoder_input(this); } -inline reffed_ptr Encoder::NewHandlers( - const upb::MessageDef *md) { - const Handlers* h = upb_pb_encoder_newhandlers(md, &h); - return reffed_ptr(h, &h); +inline upb_handlercache* Encoder::NewCache() { + return upb_pb_encoder_newcache(); } } /* namespace pb */ } /* namespace upb */ diff --git a/upb/pb/textprinter.c b/upb/pb/textprinter.c index e8033f8..b6f8024 100644 --- a/upb/pb/textprinter.c +++ b/upb/pb/textprinter.c @@ -327,9 +327,8 @@ upb_textprinter *upb_textprinter_create(upb_env *env, const upb_handlers *h, return p; } -const upb_handlers *upb_textprinter_newhandlers(const upb_msgdef *m, - const void *owner) { - return upb_handlers_newfrozen(m, owner, &onmreg, NULL); +upb_handlercache *upb_textprinter_newcache() { + return upb_handlercache_new(&onmreg, NULL); } upb_sink *upb_textprinter_input(upb_textprinter *p) { return &p->input_; } diff --git a/upb/pb/textprinter.h b/upb/pb/textprinter.h index 2f40ed8..06ff7d5 100644 --- a/upb/pb/textprinter.h +++ b/upb/pb/textprinter.h @@ -34,7 +34,7 @@ class upb::pb::TextPrinter { /* If handler caching becomes a requirement we can add a code cache as in * decoder.h */ - static reffed_ptr NewHandlers(const MessageDef* md); + static HandlerCache* NewCache(); }; #endif @@ -47,8 +47,7 @@ upb_textprinter *upb_textprinter_create(upb_env *env, const upb_handlers *h, void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line); upb_sink *upb_textprinter_input(upb_textprinter *p); -const upb_handlers *upb_textprinter_newhandlers(const upb_msgdef *m, - const void *owner); +upb_handlercache *upb_textprinter_newcache(); UPB_END_EXTERN_C @@ -67,10 +66,8 @@ inline void TextPrinter::SetSingleLineMode(bool single_line) { inline Sink* TextPrinter::input() { return upb_textprinter_input(this); } -inline reffed_ptr TextPrinter::NewHandlers( - const MessageDef *md) { - const Handlers* h = upb_textprinter_newhandlers(md, &h); - return reffed_ptr(h, &h); +inline HandlerCache* TextPrinter::NewCache() { + return upb_textprinter_newcache(); } } /* namespace pb */ } /* namespace upb */ diff --git a/upb/refcounted.c b/upb/refcounted.c deleted file mode 100644 index f00dbb7..0000000 --- a/upb/refcounted.c +++ /dev/null @@ -1,851 +0,0 @@ -/* -** upb::RefCounted Implementation -** -** Our key invariants are: -** 1. reference cycles never span groups -** 2. for ref2(to, from), we increment to's count iff group(from) != group(to) -** -** The previous two are how we avoid leaking cycles. Other important -** invariants are: -** 3. for mutable objects "from" and "to", if there exists a ref2(to, from) -** this implies group(from) == group(to). (In practice, what we implement -** is even stronger; "from" and "to" will share a group if there has *ever* -** been a ref2(to, from), but all that is necessary for correctness is the -** weaker one). -** 4. mutable and immutable objects are never in the same group. -*/ - -#include "upb/refcounted.h" - -#include - -static void freeobj(upb_refcounted *o); - -const char untracked_val; -const void *UPB_UNTRACKED_REF = &untracked_val; - -/* arch-specific atomic primitives *******************************************/ - -#ifdef UPB_THREAD_UNSAFE /*---------------------------------------------------*/ - -static void atomic_inc(uint32_t *a) { (*a)++; } -static bool atomic_dec(uint32_t *a) { return --(*a) == 0; } - -#elif defined(__GNUC__) || defined(__clang__) /*------------------------------*/ - -static void atomic_inc(uint32_t *a) { __sync_fetch_and_add(a, 1); } -static bool atomic_dec(uint32_t *a) { return __sync_sub_and_fetch(a, 1) == 0; } - -#elif defined(WIN32) /*-------------------------------------------------------*/ - -#include - -static void atomic_inc(upb_atomic_t *a) { InterlockedIncrement(&a->val); } -static bool atomic_dec(upb_atomic_t *a) { - return InterlockedDecrement(&a->val) == 0; -} - -#else -#error Atomic primitives not defined for your platform/CPU. \ - Implement them or compile with UPB_THREAD_UNSAFE. -#endif - -/* All static objects point to this refcount. - * It is special-cased in ref/unref below. */ -uint32_t static_refcount = -1; - -/* We can avoid atomic ops for statically-declared objects. - * This is a minor optimization but nice since we can avoid degrading under - * contention in this case. */ - -static void refgroup(uint32_t *group) { - if (group != &static_refcount) - atomic_inc(group); -} - -static bool unrefgroup(uint32_t *group) { - if (group == &static_refcount) { - return false; - } else { - return atomic_dec(group); - } -} - - -/* Reference tracking (debug only) ********************************************/ - -#ifdef UPB_DEBUG_REFS - -#ifdef UPB_THREAD_UNSAFE - -static void upb_lock() {} -static void upb_unlock() {} - -#else - -/* User must define functions that lock/unlock a global mutex and link this - * file against them. */ -void upb_lock(); -void upb_unlock(); - -#endif - -/* UPB_DEBUG_REFS mode counts on being able to malloc() memory in some - * 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 use an allocator that - * immediately aborts on failure (avoiding the global allocator, which might - * inject failures). */ - -#include - -static void *upb_debugrefs_allocfunc(upb_alloc *alloc, void *ptr, - size_t oldsize, size_t size) { - UPB_UNUSED(alloc); - UPB_UNUSED(oldsize); - if (size == 0) { - free(ptr); - return NULL; - } else { - void *ret = realloc(ptr, size); - - if (!ret) { - abort(); - } - - return ret; - } -} - -upb_alloc upb_alloc_debugrefs = {&upb_debugrefs_allocfunc}; - -typedef struct { - int count; /* How many refs there are (duplicates only allowed for ref2). */ - bool is_ref2; -} trackedref; - -static trackedref *trackedref_new(bool is_ref2) { - trackedref *ret = upb_malloc(&upb_alloc_debugrefs, sizeof(*ret)); - ret->count = 1; - ret->is_ref2 = is_ref2; - return ret; -} - -static void track(const upb_refcounted *r, const void *owner, bool ref2) { - upb_value v; - - UPB_ASSERT(owner); - if (owner == UPB_UNTRACKED_REF) return; - - upb_lock(); - 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 - * inside upb, we'll accept this limitation until/unless there is a really - * difficult upb-internal bug that can't be figured out without it. */ - UPB_ASSERT(ref2); - UPB_ASSERT(ref->is_ref2); - ref->count++; - } else { - trackedref *ref = trackedref_new(ref2); - upb_inttable_insertptr2(r->refs, owner, upb_value_ptr(ref), - &upb_alloc_debugrefs); - 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; - UPB_ASSERT(!upb_inttable_lookupptr(from->ref2s, r, NULL)); - upb_inttable_insertptr2(from->ref2s, r, upb_value_ptr(NULL), - &upb_alloc_debugrefs); - } - } - upb_unlock(); -} - -static void untrack(const upb_refcounted *r, const void *owner, bool ref2) { - upb_value v; - bool found; - trackedref *ref; - - UPB_ASSERT(owner); - if (owner == UPB_UNTRACKED_REF) return; - - upb_lock(); - 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(found); - ref = upb_value_getptr(v); - UPB_ASSERT(ref->is_ref2 == ref2); - if (--ref->count == 0) { - free(ref); - 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); - UPB_ASSERT(removed); - } - } - upb_unlock(); -} - -static void checkref(const upb_refcounted *r, const void *owner, bool ref2) { - upb_value v; - bool found; - trackedref *ref; - - upb_lock(); - found = upb_inttable_lookupptr(r->refs, owner, &v); - UPB_ASSERT(found); - ref = upb_value_getptr(v); - UPB_ASSERT(ref->is_ref2 == ref2); - upb_unlock(); -} - -/* Populates the given UPB_CTYPE_INT32 inttable with counts of ref2's that - * originate from the given owner. */ -static void getref2s(const upb_refcounted *owner, upb_inttable *tab) { - upb_inttable_iter i; - - upb_lock(); - upb_inttable_begin(&i, owner->ref2s); - for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { - upb_value v; - upb_value count; - trackedref *ref; - bool found; - - upb_refcounted *to = (upb_refcounted*)upb_inttable_iter_key(&i); - - /* To get the count we need to look in the target's table. */ - found = upb_inttable_lookupptr(to->refs, owner, &v); - UPB_ASSERT(found); - ref = upb_value_getptr(v); - count = upb_value_int32(ref->count); - - upb_inttable_insertptr2(tab, to, count, &upb_alloc_debugrefs); - } - upb_unlock(); -} - -typedef struct { - upb_inttable ref2; - const upb_refcounted *obj; -} check_state; - -static void visit_check(const upb_refcounted *obj, const upb_refcounted *subobj, - void *closure) { - check_state *s = closure; - upb_inttable *ref2 = &s->ref2; - upb_value v; - bool removed; - int32_t newcount; - - UPB_ASSERT(obj == s->obj); - UPB_ASSERT(subobj); - removed = upb_inttable_removeptr(ref2, subobj, &v); - /* The following assertion will fail if the visit() function visits a subobj - * that it did not have a ref2 on, or visits the same subobj too many times. */ - UPB_ASSERT(removed); - newcount = upb_value_getint32(v) - 1; - if (newcount > 0) { - upb_inttable_insert2(ref2, (uintptr_t)subobj, upb_value_int32(newcount), - &upb_alloc_debugrefs); - } -} - -static void visit(const upb_refcounted *r, upb_refcounted_visit *v, - void *closure) { - /* In DEBUG_REFS mode we know what existing ref2 refs there are, so we know - * exactly the set of nodes that visit() should visit. So we verify visit()'s - * correctness here. */ - check_state state; - state.obj = r; - upb_inttable_init2(&state.ref2, UPB_CTYPE_INT32, &upb_alloc_debugrefs); - getref2s(r, &state.ref2); - - /* This should visit any children in the ref2 table. */ - if (r->vtbl->visit) r->vtbl->visit(r, visit_check, &state); - - /* This assertion will fail if the visit() function missed any children. */ - UPB_ASSERT(upb_inttable_count(&state.ref2) == 0); - upb_inttable_uninit2(&state.ref2, &upb_alloc_debugrefs); - if (r->vtbl->visit) r->vtbl->visit(r, v, closure); -} - -static void trackinit(upb_refcounted *r) { - r->refs = upb_malloc(&upb_alloc_debugrefs, sizeof(*r->refs)); - r->ref2s = upb_malloc(&upb_alloc_debugrefs, sizeof(*r->ref2s)); - upb_inttable_init2(r->refs, UPB_CTYPE_PTR, &upb_alloc_debugrefs); - upb_inttable_init2(r->ref2s, UPB_CTYPE_PTR, &upb_alloc_debugrefs); -} - -static void trackfree(const upb_refcounted *r) { - upb_inttable_uninit2(r->refs, &upb_alloc_debugrefs); - upb_inttable_uninit2(r->ref2s, &upb_alloc_debugrefs); - upb_free(&upb_alloc_debugrefs, r->refs); - upb_free(&upb_alloc_debugrefs, r->ref2s); -} - -#else - -static void track(const upb_refcounted *r, const void *owner, bool ref2) { - UPB_UNUSED(r); - UPB_UNUSED(owner); - UPB_UNUSED(ref2); -} - -static void untrack(const upb_refcounted *r, const void *owner, bool ref2) { - UPB_UNUSED(r); - UPB_UNUSED(owner); - UPB_UNUSED(ref2); -} - -static void checkref(const upb_refcounted *r, const void *owner, bool ref2) { - UPB_UNUSED(r); - UPB_UNUSED(owner); - UPB_UNUSED(ref2); -} - -static void trackinit(upb_refcounted *r) { - UPB_UNUSED(r); -} - -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); -} - -#endif /* UPB_DEBUG_REFS */ - - -/* freeze() *******************************************************************/ - -/* The freeze() operation is by far the most complicated part of this scheme. - * We compute strongly-connected components and then mutate the graph such that - * we preserve the invariants documented at the top of this file. And we must - * handle out-of-memory errors gracefully (without leaving the graph - * inconsistent), which adds to the fun. */ - -/* The state used by the freeze operation (shared across many functions). */ -typedef struct { - int depth; - int maxdepth; - uint64_t index; - /* Maps upb_refcounted* -> attributes (color, etc). attr layout varies by - * color. */ - upb_inttable objattr; - upb_inttable stack; /* stack of upb_refcounted* for Tarjan's algorithm. */ - upb_inttable groups; /* array of uint32_t*, malloc'd refcounts for new groups */ - upb_status *status; - jmp_buf err; -} tarjan; - -static void release_ref2(const upb_refcounted *obj, - const upb_refcounted *subobj, - void *closure); - -/* Node attributes -----------------------------------------------------------*/ - -/* After our analysis phase all nodes will be either GRAY or WHITE. */ - -typedef enum { - BLACK = 0, /* Object has not been seen. */ - GRAY, /* Object has been found via a refgroup but may not be reachable. */ - GREEN, /* Object is reachable and is currently on the Tarjan stack. */ - WHITE /* Object is reachable and has been assigned a group (SCC). */ -} color_t; - -UPB_NORETURN static void err(tarjan *t) { longjmp(t->err, 1); } -UPB_NORETURN static void oom(tarjan *t) { - upb_status_seterrmsg(t->status, "out of memory"); - err(t); -} - -static uint64_t trygetattr(const tarjan *t, const upb_refcounted *r) { - upb_value v; - return upb_inttable_lookupptr(&t->objattr, r, &v) ? - upb_value_getuint64(v) : 0; -} - -static uint64_t getattr(const tarjan *t, const upb_refcounted *r) { - upb_value v; - bool found = upb_inttable_lookupptr(&t->objattr, r, &v); - UPB_ASSERT(found); - return upb_value_getuint64(v); -} - -static void setattr(tarjan *t, const upb_refcounted *r, uint64_t attr) { - upb_inttable_removeptr(&t->objattr, r, NULL); - upb_inttable_insertptr(&t->objattr, r, upb_value_uint64(attr)); -} - -static color_t color(tarjan *t, const upb_refcounted *r) { - return trygetattr(t, r) & 0x3; /* Color is always stored in the low 2 bits. */ -} - -static void set_gray(tarjan *t, const upb_refcounted *r) { - UPB_ASSERT(color(t, r) == BLACK); - setattr(t, r, GRAY); -} - -/* Pushes an obj onto the Tarjan stack and sets it to GREEN. */ -static void push(tarjan *t, const upb_refcounted *r) { - UPB_ASSERT(color(t, r) == BLACK || color(t, r) == GRAY); - /* This defines the attr layout for the GREEN state. "index" and "lowlink" - * get 31 bits, which is plenty (limit of 2B objects frozen at a time). */ - setattr(t, r, GREEN | (t->index << 2) | (t->index << 33)); - if (++t->index == 0x80000000) { - upb_status_seterrmsg(t->status, "too many objects to freeze"); - err(t); - } - upb_inttable_push(&t->stack, upb_value_ptr((void*)r)); -} - -/* Pops an obj from the Tarjan stack and sets it to WHITE, with a ptr to its - * SCC group. */ -static upb_refcounted *pop(tarjan *t) { - upb_refcounted *r = upb_value_getptr(upb_inttable_pop(&t->stack)); - UPB_ASSERT(color(t, r) == GREEN); - /* This defines the attr layout for nodes in the WHITE state. - * Top of group stack is [group, NULL]; we point at group. */ - setattr(t, r, WHITE | (upb_inttable_count(&t->groups) - 2) << 8); - return r; -} - -static void tarjan_newgroup(tarjan *t) { - uint32_t *group = upb_gmalloc(sizeof(*group)); - if (!group) oom(t); - /* Push group and empty group leader (we'll fill in leader later). */ - if (!upb_inttable_push(&t->groups, upb_value_ptr(group)) || - !upb_inttable_push(&t->groups, upb_value_ptr(NULL))) { - upb_gfree(group); - oom(t); - } - *group = 0; -} - -static uint32_t idx(tarjan *t, const upb_refcounted *r) { - UPB_ASSERT(color(t, r) == GREEN); - return (getattr(t, r) >> 2) & 0x7FFFFFFF; -} - -static uint32_t lowlink(tarjan *t, const upb_refcounted *r) { - if (color(t, r) == GREEN) { - return getattr(t, r) >> 33; - } else { - return UINT32_MAX; - } -} - -static void set_lowlink(tarjan *t, const upb_refcounted *r, uint32_t lowlink) { - UPB_ASSERT(color(t, r) == GREEN); - setattr(t, r, ((uint64_t)lowlink << 33) | (getattr(t, r) & 0x1FFFFFFFF)); -} - -static uint32_t *group(tarjan *t, upb_refcounted *r) { - uint64_t groupnum; - upb_value v; - bool found; - - UPB_ASSERT(color(t, r) == WHITE); - groupnum = getattr(t, r) >> 8; - found = upb_inttable_lookup(&t->groups, groupnum, &v); - UPB_ASSERT(found); - return upb_value_getptr(v); -} - -/* If the group leader for this object's group has not previously been set, - * the given object is assigned to be its leader. */ -static upb_refcounted *groupleader(tarjan *t, upb_refcounted *r) { - uint64_t leader_slot; - upb_value v; - bool found; - - UPB_ASSERT(color(t, r) == WHITE); - leader_slot = (getattr(t, r) >> 8) + 1; - found = upb_inttable_lookup(&t->groups, leader_slot, &v); - UPB_ASSERT(found); - if (upb_value_getptr(v)) { - return upb_value_getptr(v); - } else { - upb_inttable_remove(&t->groups, leader_slot, NULL); - upb_inttable_insert(&t->groups, leader_slot, upb_value_ptr(r)); - return r; - } -} - - -/* Tarjan's algorithm --------------------------------------------------------*/ - -/* See: - * http://en.wikipedia.org/wiki/Tarjan%27s_strongly_connected_components_algorithm */ -static void do_tarjan(const upb_refcounted *obj, tarjan *t); - -static void tarjan_visit(const upb_refcounted *obj, - const upb_refcounted *subobj, - void *closure) { - tarjan *t = closure; - if (++t->depth > t->maxdepth) { - upb_status_seterrf(t->status, "graph too deep to freeze (%d)", t->maxdepth); - err(t); - } else if (subobj->is_frozen || color(t, subobj) == WHITE) { - /* Do nothing: we don't want to visit or color already-frozen nodes, - * and WHITE nodes have already been assigned a SCC. */ - } else if (color(t, subobj) < GREEN) { - /* Subdef has not yet been visited; recurse on it. */ - do_tarjan(subobj, t); - set_lowlink(t, obj, UPB_MIN(lowlink(t, obj), lowlink(t, subobj))); - } else if (color(t, subobj) == GREEN) { - /* Subdef is in the stack and hence in the current SCC. */ - set_lowlink(t, obj, UPB_MIN(lowlink(t, obj), idx(t, subobj))); - } - --t->depth; -} - -static void do_tarjan(const upb_refcounted *obj, tarjan *t) { - if (color(t, obj) == BLACK) { - /* We haven't seen this object's group; mark the whole group GRAY. */ - const upb_refcounted *o = obj; - do { set_gray(t, o); } while ((o = o->next) != obj); - } - - push(t, obj); - visit(obj, tarjan_visit, t); - if (lowlink(t, obj) == idx(t, obj)) { - tarjan_newgroup(t); - while (pop(t) != obj) - ; - } -} - - -/* freeze() ------------------------------------------------------------------*/ - -static void crossref(const upb_refcounted *r, const upb_refcounted *subobj, - void *_t) { - tarjan *t = _t; - UPB_ASSERT(color(t, r) > BLACK); - if (color(t, subobj) > BLACK && r->group != subobj->group) { - /* Previously this ref was not reflected in subobj->group because they - * were in the same group; now that they are split a ref must be taken. */ - refgroup(subobj->group); - } -} - -static bool freeze(upb_refcounted *const*roots, int n, upb_status *s, - int maxdepth) { - volatile bool ret = false; - int i; - upb_inttable_iter iter; - - /* We run in two passes so that we can allocate all memory before performing - * any mutation of the input -- this allows us to leave the input unchanged - * in the case of memory allocation failure. */ - tarjan t; - t.index = 0; - t.depth = 0; - 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; - if (!upb_inttable_init(&t.groups, UPB_CTYPE_PTR)) goto err3; - if (setjmp(t.err) != 0) goto err4; - - - for (i = 0; i < n; i++) { - if (color(&t, roots[i]) < GREEN) { - do_tarjan(roots[i], &t); - } - } - - /* If we've made it this far, no further errors are possible so it's safe to - * mutate the objects without risk of leaving them in an inconsistent state. */ - ret = true; - - /* The transformation that follows requires care. The preconditions are: - * - all objects in attr map are WHITE or GRAY, and are in mutable groups - * (groups of all mutable objs) - * - no ref2(to, from) refs have incremented count(to) if both "to" and - * "from" are in our attr map (this follows from invariants (2) and (3)) */ - - /* Pass 1: we remove WHITE objects from their mutable groups, and add them to - * new groups according to the SCC's we computed. These new groups will - * consist of only frozen objects. None will be immediately collectible, - * because WHITE objects are by definition reachable from one of "roots", - * which the caller must own refs on. */ - upb_inttable_begin(&iter, &t.objattr); - for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) { - upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter); - /* Since removal from a singly-linked list requires access to the object's - * predecessor, we consider obj->next instead of obj for moving. With the - * while() loop we guarantee that we will visit every node's predecessor. - * Proof: - * 1. every node's predecessor is in our attr map. - * 2. though the loop body may change a node's predecessor, it will only - * change it to be the node we are currently operating on, so with a - * while() loop we guarantee ourselves the chance to remove each node. */ - while (color(&t, obj->next) == WHITE && - group(&t, obj->next) != obj->next->group) { - upb_refcounted *leader; - - /* Remove from old group. */ - upb_refcounted *move = obj->next; - if (obj == move) { - /* Removing the last object from a group. */ - UPB_ASSERT(*obj->group == obj->individual_count); - upb_gfree(obj->group); - } else { - obj->next = move->next; - /* This may decrease to zero; we'll collect GRAY objects (if any) that - * remain in the group in the third pass. */ - UPB_ASSERT(*move->group >= move->individual_count); - *move->group -= move->individual_count; - } - - /* Add to new group. */ - leader = groupleader(&t, move); - if (move == leader) { - /* First object added to new group is its leader. */ - move->group = group(&t, move); - move->next = move; - *move->group = move->individual_count; - } else { - /* Group already has at least one object in it. */ - UPB_ASSERT(leader->group == group(&t, move)); - move->group = group(&t, move); - move->next = leader->next; - leader->next = move; - *move->group += move->individual_count; - } - - move->is_frozen = true; - } - } - - /* Pass 2: GRAY and WHITE objects "obj" with ref2(to, obj) references must - * increment count(to) if group(obj) != group(to) (which could now be the - * case if "to" was just frozen). */ - upb_inttable_begin(&iter, &t.objattr); - for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) { - upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter); - visit(obj, crossref, &t); - } - - /* Pass 3: GRAY objects are collected if their group's refcount dropped to - * zero when we removed its white nodes. This can happen if they had only - * been kept alive by virtue of sharing a group with an object that was just - * frozen. - * - * It is important that we do this last, since the GRAY object's free() - * function could call unref2() on just-frozen objects, which will decrement - * refs that were added in pass 2. */ - upb_inttable_begin(&iter, &t.objattr); - for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) { - upb_refcounted *obj = (upb_refcounted*)upb_inttable_iter_key(&iter); - if (obj->group == NULL || *obj->group == 0) { - if (obj->group) { - upb_refcounted *o; - - /* We eagerly free() the group's count (since we can't easily determine - * the group's remaining size it's the easiest way to ensure it gets - * done). */ - upb_gfree(obj->group); - - /* Visit to release ref2's (done in a separate pass since release_ref2 - * depends on o->group being unmodified so it can test merged()). */ - o = obj; - do { visit(o, release_ref2, NULL); } while ((o = o->next) != obj); - - /* Mark "group" fields as NULL so we know to free the objects later in - * this loop, but also don't try to delete the group twice. */ - o = obj; - do { o->group = NULL; } while ((o = o->next) != obj); - } - freeobj(obj); - } - } - -err4: - if (!ret) { - upb_inttable_begin(&iter, &t.groups); - for(; !upb_inttable_done(&iter); upb_inttable_next(&iter)) - upb_gfree(upb_value_getptr(upb_inttable_iter_value(&iter))); - } - upb_inttable_uninit(&t.groups); -err3: - upb_inttable_uninit(&t.stack); -err2: - upb_inttable_uninit(&t.objattr); -err1: - return ret; -} - - -/* Misc internal functions ***************************************************/ - -static bool merged(const upb_refcounted *r, const upb_refcounted *r2) { - return r->group == r2->group; -} - -static void merge(upb_refcounted *r, upb_refcounted *from) { - upb_refcounted *base; - upb_refcounted *tmp; - - if (merged(r, from)) return; - *r->group += *from->group; - upb_gfree(from->group); - base = from; - - /* Set all refcount pointers in the "from" chain to the merged refcount. - * - * TODO(haberman): this linear algorithm can result in an overall O(n^2) bound - * if the user continuously extends a group by one object. Prevent this by - * using one of the techniques in this paper: - * http://bioinfo.ict.ac.cn/~dbu/AlgorithmCourses/Lectures/Union-Find-Tarjan.pdf */ - do { from->group = r->group; } while ((from = from->next) != base); - - /* Merge the two circularly linked lists by swapping their next pointers. */ - tmp = r->next; - r->next = base->next; - base->next = tmp; -} - -static void unref(const upb_refcounted *r); - -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)) { - UPB_ASSERT(subobj->is_frozen); - unref(subobj); - } -} - -static void unref(const upb_refcounted *r) { - if (unrefgroup(r->group)) { - const upb_refcounted *o; - - upb_gfree(r->group); - - /* In two passes, since release_ref2 needs a guarantee that any subobjs - * are alive. */ - o = r; - do { visit(o, release_ref2, NULL); } while((o = o->next) != r); - - o = r; - do { - const upb_refcounted *next = o->next; - UPB_ASSERT(o->is_frozen || o->individual_count == 0); - 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 ***********************************************************/ - -bool upb_refcounted_init(upb_refcounted *r, - const struct upb_refcounted_vtbl *vtbl, - const void *owner) { -#ifndef NDEBUG - /* Endianness check. This is unrelated to upb_refcounted, it's just a - * convenient place to put the check that we can be assured will run for - * basically every program using upb. */ - const int x = 1; -#ifdef UPB_BIG_ENDIAN - UPB_ASSERT(*(char*)&x != 1); -#else - UPB_ASSERT(*(char*)&x == 1); -#endif -#endif - - r->next = r; - r->vtbl = vtbl; - r->individual_count = 0; - r->is_frozen = false; - r->group = upb_gmalloc(sizeof(*r->group)); - if (!r->group) return false; - *r->group = 0; - trackinit(r); - upb_refcounted_ref(r, owner); - return true; -} - -bool upb_refcounted_isfrozen(const upb_refcounted *r) { - return r->is_frozen; -} - -void upb_refcounted_ref(const upb_refcounted *r, const void *owner) { - track(r, owner, false); - if (!r->is_frozen) - ((upb_refcounted*)r)->individual_count++; - refgroup(r->group); -} - -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); -} - -void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from) { - UPB_ASSERT(!from->is_frozen); /* Non-const pointer implies this. */ - track(r, from, true); - if (r->is_frozen) { - refgroup(r->group); - } else { - merge((upb_refcounted*)r, from); - } -} - -void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from) { - UPB_ASSERT(!from->is_frozen); /* Non-const pointer implies this. */ - untrack(r, from, true); - if (r->is_frozen) { - unref(r); - } else { - UPB_ASSERT(merged(r, from)); - } -} - -void upb_refcounted_donateref( - const upb_refcounted *r, const void *from, const void *to) { - UPB_ASSERT(from != to); - if (to != NULL) - upb_refcounted_ref(r, to); - if (from != NULL) - upb_refcounted_unref(r, from); -} - -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, - int maxdepth) { - int i; - bool ret; - for (i = 0; i < n; i++) { - UPB_ASSERT(!roots[i]->is_frozen); - } - ret = freeze(roots, n, s, maxdepth); - UPB_ASSERT(!s || ret == upb_ok(s)); - return ret; -} diff --git a/upb/refcounted.h b/upb/refcounted.h deleted file mode 100644 index 6698d38..0000000 --- a/upb/refcounted.h +++ /dev/null @@ -1,348 +0,0 @@ -/* -** upb::RefCounted (upb_refcounted) -** -** A refcounting scheme that supports circular refs. It accomplishes this by -** partitioning the set of objects into groups such that no cycle spans groups; -** we can then reference-count the group as a whole and ignore refs within the -** group. When objects are mutable, these groups are computed very -** conservatively; we group any objects that have ever had a link between them. -** When objects are frozen, we compute strongly-connected components which -** allows us to be precise and only group objects that are actually cyclic. -** -** This is a mixed C/C++ interface that offers a full API to both languages. -** See the top-level README for more information. -*/ - -#ifndef UPB_REFCOUNTED_H_ -#define UPB_REFCOUNTED_H_ - -#include "upb/table.int.h" - -/* Reference tracking will check ref()/unref() operations to make sure the - * ref ownership is correct. Where possible it will also make tools like - * Valgrind attribute ref leaks to the code that took the leaked ref, not - * the code that originally created the object. - * - * Enabling this requires the application to define upb_lock()/upb_unlock() - * functions that acquire/release a global mutex (or #define UPB_THREAD_UNSAFE). - * For this reason we don't enable it by default, even in debug builds. - */ - -/* #define UPB_DEBUG_REFS */ - -#ifdef __cplusplus -namespace upb { -class RefCounted; -template class reffed_ptr; -} -#endif - -UPB_DECLARE_TYPE(upb::RefCounted, upb_refcounted) - -struct upb_refcounted_vtbl; - -#ifdef __cplusplus - -class upb::RefCounted { - public: - /* Returns true if the given object is frozen. */ - bool IsFrozen() const; - - /* Increases the ref count, the new ref is owned by "owner" which must not - * already own a ref (and should not itself be a refcounted object if the ref - * could possibly be circular; see below). - * Thread-safe iff "this" is frozen. */ - void Ref(const void *owner) const; - - /* Release a ref that was acquired from upb_refcounted_ref() and collects any - * objects it can. */ - void Unref(const void *owner) const; - - /* Moves an existing ref from "from" to "to", without changing the overall - * ref count. DonateRef(foo, NULL, owner) is the same as Ref(foo, owner), - * but "to" may not be NULL. */ - void DonateRef(const void *from, const void *to) const; - - /* Verifies that a ref to the given object is currently held by the given - * owner. Only effective in UPB_DEBUG_REFS builds. */ - void CheckRef(const void *owner) const; - - private: - UPB_DISALLOW_POD_OPS(RefCounted, upb::RefCounted) -#else -struct upb_refcounted { -#endif - /* TODO(haberman): move the actual structure definition to structdefs.int.h. - * The only reason they are here is because inline functions need to see the - * definition of upb_handlers, which needs to see this definition. But we - * can change the upb_handlers inline functions to deal in raw offsets - * instead. - */ - - /* A single reference count shared by all objects in the group. */ - uint32_t *group; - - /* A singly-linked list of all objects in the group. */ - upb_refcounted *next; - - /* Table of function pointers for this type. */ - const struct upb_refcounted_vtbl *vtbl; - - /* Maintained only when mutable, this tracks the number of refs (but not - * ref2's) to this object. *group should be the sum of all individual_count - * in the group. */ - 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 -}; - -#ifdef UPB_DEBUG_REFS -extern upb_alloc upb_alloc_debugrefs; -#define UPB_REFCOUNT_INIT(vtbl, refs, ref2s) \ - {&static_refcount, NULL, vtbl, 0, true, refs, ref2s} -#else -#define UPB_REFCOUNT_INIT(vtbl, refs, ref2s) \ - {&static_refcount, NULL, vtbl, 0, true} -#endif - -UPB_BEGIN_EXTERN_C - -/* It is better to use tracked refs when possible, for the extra debugging - * capability. But if this is not possible (because you don't have easy access - * to a stable pointer value that is associated with the ref), you can pass - * UPB_UNTRACKED_REF instead. */ -extern const void *UPB_UNTRACKED_REF; - -/* Native C API. */ -bool upb_refcounted_isfrozen(const upb_refcounted *r); -void upb_refcounted_ref(const upb_refcounted *r, const void *owner); -void upb_refcounted_unref(const upb_refcounted *r, const void *owner); -void upb_refcounted_donateref( - const upb_refcounted *r, const void *from, const void *to); -void upb_refcounted_checkref(const upb_refcounted *r, const void *owner); - -#define UPB_REFCOUNTED_CMETHODS(type, upcastfunc) \ - UPB_INLINE bool type ## _isfrozen(const type *v) { \ - return upb_refcounted_isfrozen(upcastfunc(v)); \ - } \ - UPB_INLINE void type ## _ref(const type *v, const void *owner) { \ - upb_refcounted_ref(upcastfunc(v), owner); \ - } \ - UPB_INLINE void type ## _unref(const type *v, const void *owner) { \ - upb_refcounted_unref(upcastfunc(v), owner); \ - } \ - UPB_INLINE void type ## _donateref(const type *v, const void *from, const void *to) { \ - upb_refcounted_donateref(upcastfunc(v), from, to); \ - } \ - UPB_INLINE void type ## _checkref(const type *v, const void *owner) { \ - upb_refcounted_checkref(upcastfunc(v), owner); \ - } - -#define UPB_REFCOUNTED_CPPMETHODS \ - bool IsFrozen() const { \ - return upb::upcast_to(this)->IsFrozen(); \ - } \ - void Ref(const void *owner) const { \ - return upb::upcast_to(this)->Ref(owner); \ - } \ - void Unref(const void *owner) const { \ - return upb::upcast_to(this)->Unref(owner); \ - } \ - void DonateRef(const void *from, const void *to) const { \ - return upb::upcast_to(this)->DonateRef(from, to); \ - } \ - void CheckRef(const void *owner) const { \ - return upb::upcast_to(this)->CheckRef(owner); \ - } - -/* Internal-to-upb Interface **************************************************/ - -typedef void upb_refcounted_visit(const upb_refcounted *r, - const upb_refcounted *subobj, - void *closure); - -struct upb_refcounted_vtbl { - /* Must visit all subobjects that are currently ref'd via upb_refcounted_ref2. - * Must be longjmp()-safe. */ - void (*visit)(const upb_refcounted *r, upb_refcounted_visit *visit, void *c); - - /* Must free the object and release all references to other objects. */ - void (*free)(upb_refcounted *r); -}; - -/* Initializes the refcounted with a single ref for the given owner. Returns - * false if memory could not be allocated. */ -bool upb_refcounted_init(upb_refcounted *r, - const struct upb_refcounted_vtbl *vtbl, - const void *owner); - -/* Adds a ref from one refcounted object to another ("from" must not already - * own a ref). These refs may be circular; cycles will be collected correctly - * (if conservatively). These refs do not need to be freed in from's free() - * function. */ -void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from); - -/* Removes a ref that was acquired from upb_refcounted_ref2(), and collects any - * object it can. This is only necessary when "from" no longer points to "r", - * and not from from's "free" function. */ -void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from); - -#define upb_ref2(r, from) \ - upb_refcounted_ref2((const upb_refcounted*)r, (upb_refcounted*)from) -#define upb_unref2(r, from) \ - 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", 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 - * the second parameter of upb_refcounted_{ref,unref}2(). On the upside, all - * operations on frozen refcounteds are threadsafe, and objects will be freed - * 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, - int maxdepth); - -/* Shared by all compiled-in refcounted objects. */ -extern uint32_t static_refcount; - -UPB_END_EXTERN_C - -#ifdef __cplusplus -/* C++ Wrappers. */ -namespace upb { -inline bool RefCounted::IsFrozen() const { - return upb_refcounted_isfrozen(this); -} -inline void RefCounted::Ref(const void *owner) const { - upb_refcounted_ref(this, owner); -} -inline void RefCounted::Unref(const void *owner) const { - upb_refcounted_unref(this, owner); -} -inline void RefCounted::DonateRef(const void *from, const void *to) const { - upb_refcounted_donateref(this, from, to); -} -inline void RefCounted::CheckRef(const void *owner) const { - upb_refcounted_checkref(this, owner); -} -} /* namespace upb */ -#endif - - -/* upb::reffed_ptr ************************************************************/ - -#ifdef __cplusplus - -#include /* For std::swap(). */ - -/* Provides RAII semantics for upb refcounted objects. Each reffed_ptr owns a - * ref on whatever object it points to (if any). */ -template class upb::reffed_ptr { - public: - reffed_ptr() : ptr_(NULL) {} - - /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */ - template - reffed_ptr(U* val, const void* ref_donor = NULL) - : ptr_(upb::upcast(val)) { - if (ref_donor) { - UPB_ASSERT(ptr_); - ptr_->DonateRef(ref_donor, this); - } else if (ptr_) { - ptr_->Ref(this); - } - } - - template - reffed_ptr(const reffed_ptr& other) - : ptr_(upb::upcast(other.get())) { - if (ptr_) ptr_->Ref(this); - } - - reffed_ptr(const reffed_ptr& other) - : ptr_(upb::upcast(other.get())) { - if (ptr_) ptr_->Ref(this); - } - - ~reffed_ptr() { if (ptr_) ptr_->Unref(this); } - - template - reffed_ptr& operator=(const reffed_ptr& other) { - reset(other.get()); - return *this; - } - - reffed_ptr& operator=(const reffed_ptr& other) { - reset(other.get()); - return *this; - } - - /* TODO(haberman): add C++11 move construction/assignment for greater - * efficiency. */ - - void swap(reffed_ptr& other) { - if (ptr_ == other.ptr_) { - return; - } - - if (ptr_) ptr_->DonateRef(this, &other); - if (other.ptr_) other.ptr_->DonateRef(&other, this); - std::swap(ptr_, other.ptr_); - } - - T& operator*() const { - UPB_ASSERT(ptr_); - return *ptr_; - } - - T* operator->() const { - UPB_ASSERT(ptr_); - return ptr_; - } - - T* get() const { return ptr_; } - - /* If ref_donor is NULL, takes a new ref, otherwise adopts from ref_donor. */ - template - void reset(U* ptr = NULL, const void* ref_donor = NULL) { - reffed_ptr(ptr, ref_donor).swap(*this); - } - - template - reffed_ptr down_cast() { - return reffed_ptr(upb::down_cast(get())); - } - - template - reffed_ptr dyn_cast() { - return reffed_ptr(upb::dyn_cast(get())); - } - - /* Plain release() is unsafe; if we were the only owner, it would leak the - * object. Instead we provide this: */ - T* ReleaseTo(const void* new_owner) { - T* ret = NULL; - ptr_->DonateRef(this, new_owner); - std::swap(ret, ptr_); - return ret; - } - - private: - T* ptr_; -}; - -#endif /* __cplusplus */ - -#endif /* UPB_REFCOUNT_H_ */ -- cgit v1.2.3 From d2f9bec5c6f3c34362cf13e35e11d3dbc7888a32 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Sat, 12 Jan 2019 16:15:46 -0800 Subject: Removed old-style C++ handlers that relied on UB in favor of more normal ones. --- CMakeLists.txt | 2 - tests/pb/test_encoder.cc | 33 +- tests/test_util.h | 2 +- upb/bindings/stdc++/string.h | 6 +- upb/def.h | 1159 ++++++++++++++++++------------------------ upb/handlers-inl.h | 292 ++--------- upb/handlers.c | 175 +++---- upb/handlers.h | 816 +++++++++++++---------------- upb/json/printer.c | 44 +- upb/pb/compile_decoder.c | 8 +- upb/pb/decoder.h | 221 ++++---- upb/pb/encoder.c | 10 +- upb/pb/encoder.h | 70 ++- upb/pb/textprinter.c | 6 +- upb/sink.c | 6 +- upb/sink.h | 603 ++++++++++------------ upb/upb.h | 69 --- 17 files changed, 1408 insertions(+), 2114 deletions(-) (limited to 'upb/bindings') diff --git a/CMakeLists.txt b/CMakeLists.txt index 699653f..58d6571 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -70,7 +70,6 @@ add_library(upb upb/msgfactory.c upb/port_def.inc upb/port_undef.inc - upb/refcounted.c upb/sink.c upb/structs.int.h upb/table.c @@ -84,7 +83,6 @@ add_library(upb upb/handlers.h upb/msg.h upb/msgfactory.h - upb/refcounted.h upb/sink.h upb/upb.h) add_library(upb_pb diff --git a/tests/pb/test_encoder.cc b/tests/pb/test_encoder.cc index fac0dae..35c0e1e 100644 --- a/tests/pb/test_encoder.cc +++ b/tests/pb/test_encoder.cc @@ -18,12 +18,9 @@ std::string read_string(const char *filename) { void test_pb_roundtrip() { std::string input = read_string("google/protobuf/descriptor.pb"); - upb::SymbolTable* symtab = upb::SymbolTable::New(); - upb::HandlerCache* encoder_cache = upb::pb::Encoder::NewCache(); - upb::pb::CodeCache* decoder_cache = upb::pb::CodeCache::New(encoder_cache); - ASSERT(symtab); - ASSERT(encoder_cache); - ASSERT(decoder_cache); + upb::SymbolTable symtab; + upb::HandlerCache encoder_cache(upb::pb::EncoderPtr::NewCache()); + upb::pb::CodeCache decoder_cache(&encoder_cache); upb::Arena arena; google_protobuf_FileDescriptorSet *set = google_protobuf_FileDescriptorSet_parsenew( @@ -34,32 +31,28 @@ void test_pb_roundtrip() { google_protobuf_FileDescriptorSet_file(set, &n); ASSERT(n == 1); upb::Status status; - bool ok = symtab->AddFile(files[0], &status); + bool ok = symtab.AddFile(files[0], &status); if (!ok) { fprintf(stderr, "Error building def: %s\n", upb_status_errmsg(&status)); ASSERT(false); } - const upb::MessageDef *md = - symtab->LookupMessage("google.protobuf.FileDescriptorSet"); + upb::MessageDefPtr md = + symtab.LookupMessage("google.protobuf.FileDescriptorSet"); ASSERT(md); - const upb::Handlers* encoder_handlers = encoder_cache->Get(md); + const upb::Handlers *encoder_handlers = encoder_cache.Get(md); ASSERT(encoder_handlers); - const upb::pb::DecoderMethod* method = decoder_cache->Get(md); - ASSERT(method); + const upb::pb::DecoderMethodPtr method = decoder_cache.Get(md); upb::InlinedEnvironment<512> env; std::string output; upb::StringSink string_sink(&output); - upb::pb::Encoder* encoder = - upb::pb::Encoder::Create(&env, encoder_handlers, string_sink.input()); - upb::pb::Decoder* decoder = - upb::pb::Decoder::Create(&env, method, encoder->input()); - ok = upb::BufferSource::PutBuffer(input, decoder->input()); + upb::pb::EncoderPtr encoder = + upb::pb::EncoderPtr::Create(&env, encoder_handlers, string_sink.input()); + upb::pb::DecoderPtr decoder = + upb::pb::DecoderPtr::Create(&env, method, encoder.input()); + ok = upb::PutBuffer(input, decoder.input()); ASSERT(ok); ASSERT(input == output); - upb::pb::CodeCache::Free(decoder_cache); - upb::HandlerCache::Free(encoder_cache); - upb::SymbolTable::Free(symtab); } extern "C" { diff --git a/tests/test_util.h b/tests/test_util.h index f616c36..1b1ff01 100644 --- a/tests/test_util.h +++ b/tests/test_util.h @@ -12,7 +12,7 @@ #ifdef __cplusplus -upb::BufferHandle global_handle; +upb_bufhandle global_handle; /* A convenience class for parser tests. Provides some useful features: * diff --git a/upb/bindings/stdc++/string.h b/upb/bindings/stdc++/string.h index 99efd4f..4d7a719 100644 --- a/upb/bindings/stdc++/string.h +++ b/upb/bindings/stdc++/string.h @@ -9,7 +9,7 @@ namespace upb { template class FillStringHandler { public: - static void SetHandler(BytesHandler* handler) { + static void SetHandler(upb_byteshandler* handler) { upb_byteshandler_setstartstr(handler, &FillStringHandler::StartString, NULL); upb_byteshandler_setstring(handler, &FillStringHandler::StringBuf, NULL); @@ -28,7 +28,7 @@ class FillStringHandler { } static size_t StringBuf(void* c, const void* hd, const char* buf, size_t n, - const BufferHandle* h) { + const upb_bufhandle* h) { UPB_UNUSED(hd); UPB_UNUSED(h); @@ -55,7 +55,7 @@ class StringSink { BytesSink* input() { return &input_; } private: - BytesHandler handler_; + upb_byteshandler handler_; BytesSink input_; }; diff --git a/upb/def.h b/upb/def.h index 81b5659..fb8a71d 100644 --- a/upb/def.h +++ b/upb/def.h @@ -2,11 +2,11 @@ ** Defs are upb's internal representation of the constructs that can appear ** in a .proto file: ** -** - upb::MessageDef (upb_msgdef): describes a "message" construct. -** - upb::FieldDef (upb_fielddef): describes a message field. -** - upb::FileDef (upb_filedef): describes a .proto file and its defs. -** - upb::EnumDef (upb_enumdef): describes an enum. -** - upb::OneofDef (upb_oneofdef): describes a oneof. +** - upb::MessageDefPtr (upb_msgdef): describes a "message" construct. +** - upb::FieldDefPtr (upb_fielddef): describes a message field. +** - upb::FileDefPtr (upb_filedef): describes a .proto file and its defs. +** - upb::EnumDefPtr (upb_enumdef): describes an enum. +** - upb::OneofDefPtr (upb_oneofdef): describes a oneof. ** ** TODO: definitions of services. ** @@ -23,51 +23,101 @@ #ifdef __cplusplus #include +#include #include #include namespace upb { -class EnumDef; -class FieldDef; -class FileDef; -class MessageDef; -class OneofDef; +class EnumDefPtr; +class FieldDefPtr; +class FileDefPtr; +class MessageDefPtr; +class OneofDefPtr; class SymbolTable; } #endif -UPB_DECLARE_TYPE(upb::EnumDef, upb_enumdef) -UPB_DECLARE_TYPE(upb::FieldDef, upb_fielddef) -UPB_DECLARE_TYPE(upb::FileDef, upb_filedef) -UPB_DECLARE_TYPE(upb::MessageDef, upb_msgdef) -UPB_DECLARE_TYPE(upb::OneofDef, upb_oneofdef) -UPB_DECLARE_TYPE(upb::SymbolTable, upb_symtab) - - -/* upb::FieldDef **************************************************************/ +struct upb_enumdef; +typedef struct upb_enumdef upb_enumdef; +struct upb_fielddef; +typedef struct upb_fielddef upb_fielddef; +struct upb_filedef; +typedef struct upb_filedef upb_filedef; +struct upb_msgdef; +typedef struct upb_msgdef upb_msgdef; +struct upb_oneofdef; +typedef struct upb_oneofdef upb_oneofdef; +struct upb_symtab; +typedef struct upb_symtab upb_symtab; + +/* upb_fielddef ***************************************************************/ /* Maximum field number allowed for FieldDefs. This is an inherent limit of the * protobuf wire format. */ #define UPB_MAX_FIELDNUMBER ((1 << 29) - 1) +UPB_BEGIN_EXTERN_C + +const char *upb_fielddef_fullname(const upb_fielddef *f); +upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f); +upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f); +upb_label_t upb_fielddef_label(const upb_fielddef *f); +uint32_t upb_fielddef_number(const upb_fielddef *f); +const char *upb_fielddef_name(const upb_fielddef *f); +bool upb_fielddef_isextension(const upb_fielddef *f); +bool upb_fielddef_lazy(const upb_fielddef *f); +bool upb_fielddef_packed(const upb_fielddef *f); +size_t upb_fielddef_getjsonname(const upb_fielddef *f, char *buf, size_t len); +const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f); +const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f); +upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f); +uint32_t upb_fielddef_index(const upb_fielddef *f); +bool upb_fielddef_issubmsg(const upb_fielddef *f); +bool upb_fielddef_isstring(const upb_fielddef *f); +bool upb_fielddef_isseq(const upb_fielddef *f); +bool upb_fielddef_isprimitive(const upb_fielddef *f); +bool upb_fielddef_ismap(const upb_fielddef *f); +int64_t upb_fielddef_defaultint64(const upb_fielddef *f); +int32_t upb_fielddef_defaultint32(const upb_fielddef *f); +uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f); +uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f); +bool upb_fielddef_defaultbool(const upb_fielddef *f); +float upb_fielddef_defaultfloat(const upb_fielddef *f); +double upb_fielddef_defaultdouble(const upb_fielddef *f); +const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len); +bool upb_fielddef_hassubdef(const upb_fielddef *f); +bool upb_fielddef_haspresence(const upb_fielddef *f); +const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f); +const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f); + +/* Internal only. */ +uint32_t upb_fielddef_selectorbase(const upb_fielddef *f); + +UPB_END_EXTERN_C + #ifdef __cplusplus /* A upb_fielddef describes a single field in a message. It is most often * found as a part of a upb_msgdef, but can also stand alone to represent * an extension. */ -class upb::FieldDef { +class upb::FieldDefPtr { public: + explicit FieldDefPtr(const upb_fielddef *ptr) : ptr_(ptr) {} + + const upb_fielddef* ptr() const { return ptr_; } + explicit operator bool() const { return ptr_ != nullptr; } + typedef upb_fieldtype_t Type; typedef upb_label_t Label; typedef upb_descriptortype_t DescriptorType; - const char* full_name() const; + const char* full_name() const { return upb_fielddef_fullname(ptr_); } - Type type() const; - Label label() const; - const char* name() const; - uint32_t number() const; - bool is_extension() const; + Type type() const { return upb_fielddef_type(ptr_); } + Label label() const { return upb_fielddef_label(ptr_); } + const char* name() const { return upb_fielddef_name(ptr_); } + uint32_t number() const { return upb_fielddef_number(ptr_); } + bool is_extension() const { return upb_fielddef_isextension(ptr_); } /* Copies the JSON name for this field into the given buffer. Returns the * actual size of the JSON name, including the NULL terminator. If the @@ -79,7 +129,9 @@ class upb::FieldDef { * name. However if the regular name is unset, the JSON name will be unset * also. */ - size_t GetJsonName(char* buf, size_t len) const; + size_t GetJsonName(char *buf, size_t len) const { + return upb_fielddef_getjsonname(ptr_, buf, len); + } /* Convenience version of the above function which copies the JSON name * into the given string, returning false if the name is not set. */ @@ -97,20 +149,20 @@ class upb::FieldDef { * TODO(haberman): I think we want to move this into a FieldOptions container * when we add support for custom options (the FieldOptions struct will * contain both regular FieldOptions like "lazy" *and* custom options). */ - bool lazy() const; + bool lazy() const { return upb_fielddef_lazy(ptr_); } /* For non-string, non-submessage fields, this indicates whether binary * protobufs are encoded in packed or non-packed format. * * TODO(haberman): see note above about putting options like this into a * FieldOptions container. */ - bool packed() const; + bool packed() const { return upb_fielddef_packed(ptr_); } /* An integer that can be used as an index into an array of fields for * whatever message this field belongs to. Guaranteed to be less than * f->containing_type()->field_count(). May only be accessed once the def has * been finalized. */ - uint32_t index() const; + uint32_t index() const { return upb_fielddef_index(ptr_); } /* The MessageDef to which this field belongs. * @@ -120,25 +172,27 @@ class upb::FieldDef { * If the field has not yet been added to a MessageDef, you can set the name * of the containing type symbolically instead. This is mostly useful for * extensions, where the extension is declared separately from the message. */ - const MessageDef* containing_type() const; + MessageDefPtr containing_type() const; /* The OneofDef to which this field belongs, or NULL if this field is not part * of a oneof. */ - const OneofDef* containing_oneof() const; + OneofDefPtr containing_oneof() const; /* The field's type according to the enum in descriptor.proto. This is not * the same as UPB_TYPE_*, because it distinguishes between (for example) * INT32 and SINT32, whereas our "type" enum does not. This return of * descriptor_type() is a function of type(), integer_format(), and * is_tag_delimited(). */ - DescriptorType descriptor_type() const; + DescriptorType descriptor_type() const { + return upb_fielddef_descriptortype(ptr_); + } /* Convenient field type tests. */ - bool IsSubMessage() const; - bool IsString() const; - bool IsSequence() const; - bool IsPrimitive() const; - bool IsMap() const; + bool IsSubMessage() const { return upb_fielddef_issubmsg(ptr_); } + bool IsString() const { return upb_fielddef_isstring(ptr_); } + bool IsSequence() const { return upb_fielddef_isseq(ptr_); } + bool IsPrimitive() const { return upb_fielddef_isprimitive(ptr_); } + bool IsMap() const { return upb_fielddef_ismap(ptr_); } /* Returns the non-string default value for this fielddef, which may either * be something the client set explicitly or the "default default" (0 for @@ -146,210 +200,170 @@ class upb::FieldDef { * returned value, except for enum fields that are still mutable. * * Requires that the given function matches the field's current type. */ - int64_t default_int64() const; - int32_t default_int32() const; - uint64_t default_uint64() const; - uint32_t default_uint32() const; - bool default_bool() const; - float default_float() const; - double default_double() const; + int64_t default_int64() const { return upb_fielddef_defaultint64(ptr_); } + int32_t default_int32() const { return upb_fielddef_defaultint32(ptr_); } + uint64_t default_uint64() const { return upb_fielddef_defaultuint64(ptr_); } + uint32_t default_uint32() const { return upb_fielddef_defaultuint32(ptr_); } + bool default_bool() const { return upb_fielddef_defaultbool(ptr_); } + float default_float() const { return upb_fielddef_defaultfloat(ptr_); } + double default_double() const { return upb_fielddef_defaultdouble(ptr_); } /* The resulting string is always NULL-terminated. If non-NULL, the length * will be stored in *len. */ - const char *default_string(size_t* len) const; + const char *default_string(size_t * len) const { + return upb_fielddef_defaultstr(ptr_, len); + } /* Returns the enum or submessage def for this field, if any. The field's * type must match (ie. you may only call enum_subdef() for fields where * type() == UPB_TYPE_ENUM). */ - const EnumDef* enum_subdef() const; - const MessageDef* message_subdef() const; + EnumDefPtr enum_subdef() const; + MessageDefPtr message_subdef() const; private: - UPB_DISALLOW_POD_OPS(FieldDef, upb::FieldDef) + const upb_fielddef *ptr_; }; -# endif /* defined(__cplusplus) */ - -UPB_BEGIN_EXTERN_C - -/* Native C API. */ -const char *upb_fielddef_fullname(const upb_fielddef *f); -bool upb_fielddef_typeisset(const upb_fielddef *f); -upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f); -upb_descriptortype_t upb_fielddef_descriptortype(const upb_fielddef *f); -upb_label_t upb_fielddef_label(const upb_fielddef *f); -uint32_t upb_fielddef_number(const upb_fielddef *f); -const char *upb_fielddef_name(const upb_fielddef *f); -bool upb_fielddef_isextension(const upb_fielddef *f); -bool upb_fielddef_lazy(const upb_fielddef *f); -bool upb_fielddef_packed(const upb_fielddef *f); -size_t upb_fielddef_getjsonname(const upb_fielddef *f, char *buf, size_t len); -const upb_msgdef *upb_fielddef_containingtype(const upb_fielddef *f); -const upb_oneofdef *upb_fielddef_containingoneof(const upb_fielddef *f); -upb_msgdef *upb_fielddef_containingtype_mutable(upb_fielddef *f); -uint32_t upb_fielddef_index(const upb_fielddef *f); -bool upb_fielddef_issubmsg(const upb_fielddef *f); -bool upb_fielddef_isstring(const upb_fielddef *f); -bool upb_fielddef_isseq(const upb_fielddef *f); -bool upb_fielddef_isprimitive(const upb_fielddef *f); -bool upb_fielddef_ismap(const upb_fielddef *f); -int64_t upb_fielddef_defaultint64(const upb_fielddef *f); -int32_t upb_fielddef_defaultint32(const upb_fielddef *f); -uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f); -uint32_t upb_fielddef_defaultuint32(const upb_fielddef *f); -bool upb_fielddef_defaultbool(const upb_fielddef *f); -float upb_fielddef_defaultfloat(const upb_fielddef *f); -double upb_fielddef_defaultdouble(const upb_fielddef *f); -const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len); -bool upb_fielddef_hassubdef(const upb_fielddef *f); -bool upb_fielddef_haspresence(const upb_fielddef *f); -const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f); -const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f); - -/* Internal only. */ -uint32_t upb_fielddef_selectorbase(const upb_fielddef *f); - -UPB_END_EXTERN_C +#endif /* __cplusplus */ +/* upb_oneofdef ***************************************************************/ -/* upb::MessageDef ************************************************************/ +UPB_BEGIN_EXTERN_C -typedef upb_inttable_iter upb_msg_field_iter; -typedef upb_strtable_iter upb_msg_oneof_iter; +typedef upb_inttable_iter upb_oneof_iter; -/* Well-known field tag numbers for map-entry messages. */ -#define UPB_MAPENTRY_KEY 1 -#define UPB_MAPENTRY_VALUE 2 +const char *upb_oneofdef_name(const upb_oneofdef *o); +const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o); +int upb_oneofdef_numfields(const upb_oneofdef *o); +uint32_t upb_oneofdef_index(const upb_oneofdef *o); -/* Well-known field tag numbers for Any messages. */ -#define UPB_ANY_TYPE 1 -#define UPB_ANY_VALUE 2 +/* Oneof lookups: + * - ntof: look up a field by name. + * - ntofz: look up a field by name (as a null-terminated string). + * - itof: look up a field by number. */ +const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o, + const char *name, size_t length); +UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o, + const char *name) { + return upb_oneofdef_ntof(o, name, strlen(name)); +} +const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num); -/* Well-known field tag numbers for timestamp messages. */ -#define UPB_DURATION_SECONDS 1 -#define UPB_DURATION_NANOS 2 +/* upb_oneof_iter i; + * for(upb_oneof_begin(&i, e); !upb_oneof_done(&i); upb_oneof_next(&i)) { + * // ... + * } + */ +void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o); +void upb_oneof_next(upb_oneof_iter *iter); +bool upb_oneof_done(upb_oneof_iter *iter); +upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter); +void upb_oneof_iter_setdone(upb_oneof_iter *iter); +bool upb_oneof_iter_isequal(const upb_oneof_iter *iter1, + const upb_oneof_iter *iter2); -/* Well-known field tag numbers for duration messages. */ -#define UPB_TIMESTAMP_SECONDS 1 -#define UPB_TIMESTAMP_NANOS 2 +UPB_END_EXTERN_C #ifdef __cplusplus -/* Structure that describes a single .proto message type. */ -class upb::MessageDef { +/* Class that represents a oneof. */ +class upb::OneofDefPtr { public: - const char* full_name() const; - const char* name() const; - - /* The number of fields that belong to the MessageDef. */ - int field_count() const; + explicit OneofDefPtr(const upb_oneofdef *ptr) : ptr_(ptr) {} - /* The number of oneofs that belong to the MessageDef. */ - int oneof_count() const; + const upb_oneofdef* ptr() const { return ptr_; } + explicit operator bool() { return ptr_ != nullptr; } - upb_syntax_t syntax() const; + /* Returns the MessageDef that owns this OneofDef. */ + MessageDefPtr containing_type() const; - /* These return NULL if the field is not found. */ - const FieldDef* FindFieldByNumber(uint32_t number) const; - const FieldDef* FindFieldByName(const char* name, size_t len) const; + /* Returns the name of this oneof. This is the name used to look up the oneof + * by name once added to a message def. */ + const char* name() const { return upb_oneofdef_name(ptr_); } + /* Returns the number of fields currently defined in the oneof. */ + int field_count() const { return upb_oneofdef_numfields(ptr_); } - const FieldDef* FindFieldByName(const char *name) const { - return FindFieldByName(name, strlen(name)); + /* Looks up by name. */ + FieldDefPtr FindFieldByName(const char *name, size_t len) const { + return FieldDefPtr(upb_oneofdef_ntof(ptr_, name, len)); + } + FieldDefPtr FindFieldByName(const char* name) const { + return FieldDefPtr(upb_oneofdef_ntofz(ptr_, name)); } template - const FieldDef* FindFieldByName(const T& str) const { + FieldDefPtr FindFieldByName(const T& str) const { return FindFieldByName(str.c_str(), str.size()); } - OneofDef* FindOneofByName(const char* name, size_t len); - const OneofDef* FindOneofByName(const char* name, size_t len) const; - - const OneofDef* FindOneofByName(const char* name) const { - return FindOneofByName(name, strlen(name)); - } - - template - const OneofDef* FindOneofByName(const T& str) const { - return FindOneofByName(str.c_str(), str.size()); + /* Looks up by tag number. */ + FieldDefPtr FindFieldByNumber(uint32_t num) const { + return FieldDefPtr(upb_oneofdef_itof(ptr_, num)); } - /* Is this message a map entry? */ - void setmapentry(bool map_entry); - bool mapentry() const; - - /* Return the type of well known type message. UPB_WELLKNOWN_UNSPECIFIED for - * non-well-known message. */ - upb_wellknowntype_t wellknowntype() const; + class const_iterator + : public std::iterator { + public: + void operator++() { upb_oneof_next(&iter_); } - /* Whether is a number wrapper. */ - bool isnumberwrapper() const; + FieldDefPtr operator*() const { + return FieldDefPtr(upb_oneof_iter_field(&iter_)); + } - /* Iteration over fields. The order is undefined. */ - class const_field_iterator - : public std::iterator { - public: - explicit const_field_iterator(const MessageDef* md); - static const_field_iterator end(const MessageDef* md); + bool operator!=(const const_iterator& other) const { + return !upb_oneof_iter_isequal(&iter_, &other.iter_); + } - void operator++(); - const FieldDef* operator*() const; - bool operator!=(const const_field_iterator& other) const; - bool operator==(const const_field_iterator& other) const; + bool operator==(const const_iterator& other) const { + return upb_oneof_iter_isequal(&iter_, &other.iter_); + } private: - upb_msg_field_iter iter_; - }; + friend class OneofDefPtr; + + const_iterator() {} + explicit const_iterator(OneofDefPtr o) { + upb_oneof_begin(&iter_, o.ptr()); + } + static const_iterator end() { + const_iterator iter; + upb_oneof_iter_setdone(&iter.iter_); + return iter; + } - /* Iteration over oneofs. The order is undefined. */ - class const_oneof_iterator - : public std::iterator { - public: - explicit const_oneof_iterator(const MessageDef* md); - static const_oneof_iterator end(const MessageDef* md); + upb_oneof_iter iter_; + }; - void operator++(); - const OneofDef* operator*() const; - bool operator!=(const const_oneof_iterator& other) const; - bool operator==(const const_oneof_iterator& other) const; + const_iterator begin() const { return const_iterator(*this); } + const_iterator end() const { return const_iterator::end(); } - private: - upb_msg_oneof_iter iter_; - }; + private: + const upb_oneofdef *ptr_; +}; - class ConstFieldAccessor { - public: - explicit ConstFieldAccessor(const MessageDef* msg) : msg_(msg) {} - const_field_iterator begin() { return msg_->field_begin(); } - const_field_iterator end() { return msg_->field_end(); } - private: - const MessageDef* msg_; - }; +#endif /* __cplusplus */ - class ConstOneofAccessor { - public: - explicit ConstOneofAccessor(const MessageDef* msg) : msg_(msg) {} - const_oneof_iterator begin() { return msg_->oneof_begin(); } - const_oneof_iterator end() { return msg_->oneof_end(); } - private: - const MessageDef* msg_; - }; +/* upb_msgdef *****************************************************************/ - const_field_iterator field_begin() const; - const_field_iterator field_end() const; +typedef upb_inttable_iter upb_msg_field_iter; +typedef upb_strtable_iter upb_msg_oneof_iter; - const_oneof_iterator oneof_begin() const; - const_oneof_iterator oneof_end() const; +/* Well-known field tag numbers for map-entry messages. */ +#define UPB_MAPENTRY_KEY 1 +#define UPB_MAPENTRY_VALUE 2 - ConstFieldAccessor fields() const { return ConstFieldAccessor(this); } - ConstOneofAccessor oneofs() const { return ConstOneofAccessor(this); } +/* Well-known field tag numbers for Any messages. */ +#define UPB_ANY_TYPE 1 +#define UPB_ANY_VALUE 2 - private: - UPB_DISALLOW_POD_OPS(MessageDef, upb::MessageDef) -}; +/* Well-known field tag numbers for timestamp messages. */ +#define UPB_DURATION_SECONDS 1 +#define UPB_DURATION_NANOS 2 -#endif /* __cplusplus */ +/* Well-known field tag numbers for duration messages. */ +#define UPB_TIMESTAMP_SECONDS 1 +#define UPB_TIMESTAMP_NANOS 2 UPB_BEGIN_EXTERN_C @@ -362,30 +376,12 @@ bool upb_msgdef_mapentry(const upb_msgdef *m); upb_wellknowntype_t upb_msgdef_wellknowntype(const upb_msgdef *m); bool upb_msgdef_isnumberwrapper(const upb_msgdef *m); bool upb_msgdef_setsyntax(upb_msgdef *m, upb_syntax_t syntax); - -/* Internal-only. */ -size_t upb_msgdef_selectorcount(const upb_msgdef *m); -uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m); - -/* Field lookup in a couple of different variations: - * - itof = int to field - * - ntof = name to field - * - ntofz = name to field, null-terminated string. */ const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i); const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name, size_t len); -int upb_msgdef_numfields(const upb_msgdef *m); - -UPB_INLINE const upb_fielddef *upb_msgdef_ntofz(const upb_msgdef *m, - const char *name) { - return upb_msgdef_ntof(m, name, strlen(name)); -} - -/* Oneof lookup: - * - ntoo = name to oneof - * - ntooz = name to oneof, null-terminated string. */ const upb_oneofdef *upb_msgdef_ntoo(const upb_msgdef *m, const char *name, size_t len); +int upb_msgdef_numfields(const upb_msgdef *m); int upb_msgdef_numoneofs(const upb_msgdef *m); UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m, @@ -393,6 +389,15 @@ UPB_INLINE const upb_oneofdef *upb_msgdef_ntooz(const upb_msgdef *m, return upb_msgdef_ntoo(m, name, strlen(name)); } +UPB_INLINE const upb_fielddef *upb_msgdef_ntofz(const upb_msgdef *m, + const char *name) { + return upb_msgdef_ntof(m, name, strlen(name)); +} + +/* Internal-only. */ +size_t upb_msgdef_selectorcount(const upb_msgdef *m); +uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m); + /* Lookup of either field or oneof by name. Returns whether either was found. * If the return is true, then the found def will be set, and the non-found * one set to NULL. */ @@ -423,75 +428,202 @@ void upb_msg_field_next(upb_msg_field_iter *iter); bool upb_msg_field_done(const upb_msg_field_iter *iter); upb_fielddef *upb_msg_iter_field(const upb_msg_field_iter *iter); void upb_msg_field_iter_setdone(upb_msg_field_iter *iter); +bool upb_msg_field_iter_isequal(const upb_msg_field_iter * iter1, + const upb_msg_field_iter * iter2); /* Similar to above, we also support iterating through the oneofs in a * msgdef. */ -void upb_msg_oneof_begin(upb_msg_oneof_iter *iter, const upb_msgdef *m); -void upb_msg_oneof_next(upb_msg_oneof_iter *iter); +void upb_msg_oneof_begin(upb_msg_oneof_iter * iter, const upb_msgdef *m); +void upb_msg_oneof_next(upb_msg_oneof_iter * iter); bool upb_msg_oneof_done(const upb_msg_oneof_iter *iter); const upb_oneofdef *upb_msg_iter_oneof(const upb_msg_oneof_iter *iter); -void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter *iter); +void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter * iter); +bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1, + const upb_msg_oneof_iter *iter2); UPB_END_EXTERN_C - -/* upb::EnumDef ***************************************************************/ - -typedef upb_strtable_iter upb_enum_iter; - #ifdef __cplusplus -class upb::EnumDef { +/* Structure that describes a single .proto message type. */ +class upb::MessageDefPtr { public: - const char* full_name() const; - const char* name() const; - /* The value that is used as the default when no field default is specified. - * If not set explicitly, the first value that was added will be used. - * The default value must be a member of the enum. - * Requires that value_count() > 0. */ - int32_t default_value() const; + MessageDefPtr(const upb_msgdef *ptr) : ptr_(ptr) {} - /* Returns the number of values currently defined in the enum. Note that - * multiple names can refer to the same number, so this may be greater than - * the total number of unique numbers. */ - int value_count() const; + const upb_msgdef *ptr() const { return ptr_; } + explicit operator bool() const { return ptr_ != nullptr; } - /* Lookups from name to integer, returning true if found. */ - bool FindValueByName(const char* name, int32_t* num) const; + const char* full_name() const { return upb_msgdef_fullname(ptr_); } + const char* name() const { return upb_msgdef_name(ptr_); } - /* Finds the name corresponding to the given number, or NULL if none was - * found. If more than one name corresponds to this number, returns the - * first one that was added. */ - const char* FindValueByNumber(int32_t num) const; + /* The number of fields that belong to the MessageDef. */ + int field_count() const { return upb_msgdef_numfields(ptr_); } - /* Iteration over name/value pairs. The order is undefined. - * Adding an enum val invalidates any iterators. - * - * TODO: make compatible with range-for, with elements as pairs? */ - class Iterator { - public: - explicit Iterator(const EnumDef*); + /* The number of oneofs that belong to the MessageDef. */ + int oneof_count() const { return upb_msgdef_numoneofs(ptr_); } - int32_t number(); - const char *name(); - bool Done(); - void Next(); + upb_syntax_t syntax() const { return upb_msgdef_syntax(ptr_); } - private: - upb_enum_iter iter_; - }; + /* These return null pointers if the field is not found. */ + FieldDefPtr FindFieldByNumber(uint32_t number) const { + return FieldDefPtr(upb_msgdef_itof(ptr_, number)); + } + FieldDefPtr FindFieldByName(const char* name, size_t len) const { + return FieldDefPtr(upb_msgdef_ntof(ptr_, name, len)); + } + FieldDefPtr FindFieldByName(const char *name) const { + return FieldDefPtr(upb_msgdef_ntofz(ptr_, name)); + } - private: - UPB_DISALLOW_POD_OPS(EnumDef, upb::EnumDef) -}; + template + FieldDefPtr FindFieldByName(const T& str) const { + return FindFieldByName(str.c_str(), str.size()); + } -#endif /* __cplusplus */ + OneofDefPtr FindOneofByName(const char* name, size_t len) const { + return OneofDefPtr(upb_msgdef_ntoo(ptr_, name, len)); + } -UPB_BEGIN_EXTERN_C + OneofDefPtr FindOneofByName(const char *name) const { + return OneofDefPtr(upb_msgdef_ntooz(ptr_, name)); + } -const char *upb_enumdef_fullname(const upb_enumdef *e); -const char *upb_enumdef_name(const upb_enumdef *e); -const upb_filedef *upb_enumdef_file(const upb_enumdef *e); + template + OneofDefPtr FindOneofByName(const T &str) const { + return FindOneofByName(str.c_str(), str.size()); + } + + /* Is this message a map entry? */ + bool mapentry() const { return upb_msgdef_mapentry(ptr_); } + + /* Return the type of well known type message. UPB_WELLKNOWN_UNSPECIFIED for + * non-well-known message. */ + upb_wellknowntype_t wellknowntype() const { + return upb_msgdef_wellknowntype(ptr_); + } + + /* Whether is a number wrapper. */ + bool isnumberwrapper() const { return upb_msgdef_isnumberwrapper(ptr_); } + + /* Iteration over fields. The order is undefined. */ + class const_field_iterator + : public std::iterator { + public: + void operator++() { upb_msg_field_next(&iter_); } + + FieldDefPtr operator*() const { + return FieldDefPtr(upb_msg_iter_field(&iter_)); + } + + bool operator!=(const const_field_iterator &other) const { + return !upb_msg_field_iter_isequal(&iter_, &other.iter_); + } + + bool operator==(const const_field_iterator &other) const { + return upb_msg_field_iter_isequal(&iter_, &other.iter_); + } + + private: + friend class MessageDefPtr; + + explicit const_field_iterator() {} + + explicit const_field_iterator(MessageDefPtr msg) { + upb_msg_field_begin(&iter_, msg.ptr()); + } + + static const_field_iterator end() { + const_field_iterator iter; + upb_msg_field_iter_setdone(&iter.iter_); + return iter; + } + + upb_msg_field_iter iter_; + }; + + /* Iteration over oneofs. The order is undefined. */ + class const_oneof_iterator + : public std::iterator { + public: + + void operator++() { upb_msg_oneof_next(&iter_); } + + OneofDefPtr operator*() const { + return OneofDefPtr(upb_msg_iter_oneof(&iter_)); + } + + bool operator!=(const const_oneof_iterator& other) const { + return !upb_msg_oneof_iter_isequal(&iter_, &other.iter_); + } + + bool operator==(const const_oneof_iterator &other) const { + return upb_msg_oneof_iter_isequal(&iter_, &other.iter_); + } + + private: + friend class MessageDefPtr; + + const_oneof_iterator() {} + + explicit const_oneof_iterator(MessageDefPtr msg) { + upb_msg_oneof_begin(&iter_, msg.ptr()); + } + + static const_oneof_iterator end() { + const_oneof_iterator iter; + upb_msg_oneof_iter_setdone(&iter.iter_); + return iter; + } + + upb_msg_oneof_iter iter_; + }; + + class ConstFieldAccessor { + public: + explicit ConstFieldAccessor(const upb_msgdef* md) : md_(md) {} + const_field_iterator begin() { return MessageDefPtr(md_).field_begin(); } + const_field_iterator end() { return MessageDefPtr(md_).field_end(); } + private: + const upb_msgdef* md_; + }; + + class ConstOneofAccessor { + public: + explicit ConstOneofAccessor(const upb_msgdef* md) : md_(md) {} + const_oneof_iterator begin() { return MessageDefPtr(md_).oneof_begin(); } + const_oneof_iterator end() { return MessageDefPtr(md_).oneof_end(); } + private: + const upb_msgdef* md_; + }; + + const_field_iterator field_begin() const { + return const_field_iterator(*this); + } + + const_field_iterator field_end() const { return const_field_iterator::end(); } + + const_oneof_iterator oneof_begin() const { + return const_oneof_iterator(*this); + } + + const_oneof_iterator oneof_end() const { return const_oneof_iterator::end(); } + + ConstFieldAccessor fields() const { return ConstFieldAccessor(ptr()); } + ConstOneofAccessor oneofs() const { return ConstOneofAccessor(ptr()); } + + private: + const upb_msgdef* ptr_; +}; + +#endif /* __cplusplus */ + +/* upb_enumdef ****************************************************************/ + +typedef upb_strtable_iter upb_enum_iter; + +const char *upb_enumdef_fullname(const upb_enumdef *e); +const char *upb_enumdef_name(const upb_enumdef *e); +const upb_filedef *upb_enumdef_file(const upb_enumdef *e); int32_t upb_enumdef_default(const upb_enumdef *e); int upb_enumdef_numvals(const upb_enumdef *e); @@ -519,188 +651,129 @@ bool upb_enum_done(upb_enum_iter *iter); const char *upb_enum_iter_name(upb_enum_iter *iter); int32_t upb_enum_iter_number(upb_enum_iter *iter); -UPB_END_EXTERN_C - - -/* upb::OneofDef **************************************************************/ - -typedef upb_inttable_iter upb_oneof_iter; - #ifdef __cplusplus -/* Class that represents a oneof. */ -class upb::OneofDef { +class upb::EnumDefPtr { public: - /* Returns the MessageDef that owns this OneofDef. */ - const MessageDef* containing_type() const; + explicit EnumDefPtr(const upb_enumdef* ptr) : ptr_(ptr) {} - /* Returns the name of this oneof. This is the name used to look up the oneof - * by name once added to a message def. */ - const char* name() const; + const upb_enumdef* ptr() const { return ptr_; } + explicit operator bool() const { return ptr_ != nullptr; } - /* Returns the number of fields currently defined in the oneof. */ - int field_count() const; + const char* full_name() const { return upb_enumdef_fullname(ptr_); } + const char* name() const { return upb_enumdef_name(ptr_); } - /* Looks up by name. */ - const FieldDef* FindFieldByName(const char* name, size_t len) const; - FieldDef* FindFieldByName(const char* name, size_t len); - const FieldDef* FindFieldByName(const char* name) const { - return FindFieldByName(name, strlen(name)); - } + /* The value that is used as the default when no field default is specified. + * If not set explicitly, the first value that was added will be used. + * The default value must be a member of the enum. + * Requires that value_count() > 0. */ + int32_t default_value() const { return upb_enumdef_default(ptr_); } - template - const FieldDef* FindFieldByName(const T& str) const { - return FindFieldByName(str.c_str(), str.size()); + /* Returns the number of values currently defined in the enum. Note that + * multiple names can refer to the same number, so this may be greater than + * the total number of unique numbers. */ + int value_count() const { return upb_enumdef_numvals(ptr_); } + + /* Lookups from name to integer, returning true if found. */ + bool FindValueByName(const char *name, int32_t *num) const { + return upb_enumdef_ntoiz(ptr_, name, num); } - /* Looks up by tag number. */ - const FieldDef* FindFieldByNumber(uint32_t num) const; + /* Finds the name corresponding to the given number, or NULL if none was + * found. If more than one name corresponds to this number, returns the + * first one that was added. */ + const char *FindValueByNumber(int32_t num) const { + return upb_enumdef_iton(ptr_, num); + } - class const_iterator - : public std::iterator { + /* Iteration over name/value pairs. The order is undefined. + * Adding an enum val invalidates any iterators. + * + * TODO: make compatible with range-for, with elements as pairs? */ + class Iterator { public: - explicit const_iterator(const OneofDef* md); - static const_iterator end(const OneofDef* md); + explicit Iterator(EnumDefPtr e) { upb_enum_begin(&iter_, e.ptr()); } - void operator++(); - const FieldDef* operator*() const; - bool operator!=(const const_iterator& other) const; - bool operator==(const const_iterator& other) const; + int32_t number() { return upb_enum_iter_number(&iter_); } + const char *name() { return upb_enum_iter_name(&iter_); } + bool Done() { return upb_enum_done(&iter_); } + void Next() { return upb_enum_next(&iter_); } private: - upb_oneof_iter iter_; + upb_enum_iter iter_; }; - const_iterator begin() const; - const_iterator end() const; - private: - UPB_DISALLOW_POD_OPS(OneofDef, upb::OneofDef) + const upb_enumdef *ptr_; }; #endif /* __cplusplus */ -UPB_BEGIN_EXTERN_C +/* upb_filedef ****************************************************************/ -const char *upb_oneofdef_name(const upb_oneofdef *o); -const upb_msgdef *upb_oneofdef_containingtype(const upb_oneofdef *o); -int upb_oneofdef_numfields(const upb_oneofdef *o); -uint32_t upb_oneofdef_index(const upb_oneofdef *o); - -/* Oneof lookups: - * - ntof: look up a field by name. - * - ntofz: look up a field by name (as a null-terminated string). - * - itof: look up a field by number. */ -const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o, - const char *name, size_t length); -UPB_INLINE const upb_fielddef *upb_oneofdef_ntofz(const upb_oneofdef *o, - const char *name) { - return upb_oneofdef_ntof(o, name, strlen(name)); -} -const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num); +UPB_BEGIN_EXTERN_C -/* upb_oneof_iter i; - * for(upb_oneof_begin(&i, e); !upb_oneof_done(&i); upb_oneof_next(&i)) { - * // ... - * } - */ -void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o); -void upb_oneof_next(upb_oneof_iter *iter); -bool upb_oneof_done(upb_oneof_iter *iter); -upb_fielddef *upb_oneof_iter_field(const upb_oneof_iter *iter); -void upb_oneof_iter_setdone(upb_oneof_iter *iter); +const char *upb_filedef_name(const upb_filedef *f); +const char *upb_filedef_package(const upb_filedef *f); +const char *upb_filedef_phpprefix(const upb_filedef *f); +const char *upb_filedef_phpnamespace(const upb_filedef *f); +upb_syntax_t upb_filedef_syntax(const upb_filedef *f); +int upb_filedef_depcount(const upb_filedef *f); +int upb_filedef_msgcount(const upb_filedef *f); +int upb_filedef_enumcount(const upb_filedef *f); +const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i); +const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i); +const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i); UPB_END_EXTERN_C - -/* upb::FileDef ***************************************************************/ - #ifdef __cplusplus /* Class that represents a .proto file with some things defined in it. * * Many users won't care about FileDefs, but they are necessary if you want to * read the values of file-level options. */ -class upb::FileDef { +class upb::FileDefPtr { public: + explicit FileDefPtr(const upb_filedef *ptr) : ptr_(ptr) {} + + const upb_filedef* ptr() const { return ptr_; } + explicit operator bool() const { return ptr_ != nullptr; } + /* Get/set name of the file (eg. "foo/bar.proto"). */ - const char* name() const; + const char* name() const { return upb_filedef_name(ptr_); } /* Package name for definitions inside the file (eg. "foo.bar"). */ - const char* package() const; + const char* package() const { return upb_filedef_package(ptr_); } /* Sets the php class prefix which is prepended to all php generated classes * from this .proto. Default is empty. */ - const char* phpprefix() const; + const char* phpprefix() const { return upb_filedef_phpprefix(ptr_); } /* Use this option to change the namespace of php generated classes. Default * is empty. When this option is empty, the package name will be used for * determining the namespace. */ - const char* phpnamespace() const; + const char* phpnamespace() const { return upb_filedef_phpnamespace(ptr_); } /* Syntax for the file. Defaults to proto2. */ - upb_syntax_t syntax() const; + upb_syntax_t syntax() const { return upb_filedef_syntax(ptr_); } /* Get the list of dependencies from the file. These are returned in the - * order that they were added to the FileDef. */ - int dependency_count() const; - const FileDef* dependency(int index) const; - - private: - UPB_DISALLOW_POD_OPS(FileDef, upb::FileDef) -}; - -#endif - -UPB_BEGIN_EXTERN_C - -const char *upb_filedef_name(const upb_filedef *f); -const char *upb_filedef_package(const upb_filedef *f); -const char *upb_filedef_phpprefix(const upb_filedef *f); -const char *upb_filedef_phpnamespace(const upb_filedef *f); -upb_syntax_t upb_filedef_syntax(const upb_filedef *f); -int upb_filedef_depcount(const upb_filedef *f); -int upb_filedef_msgcount(const upb_filedef *f); -int upb_filedef_enumcount(const upb_filedef *f); -const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i); -const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i); -const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -/* Non-const methods in upb::SymbolTable are NOT thread-safe. */ -class upb::SymbolTable { - public: - /* Returns a new symbol table with a single ref owned by "owner." - * Returns NULL if memory allocation failed. */ - static SymbolTable* New(); - static void Free(upb::SymbolTable* table); - - /* Finds an entry in the symbol table with this exact name. If not found, - * returns NULL. */ - const MessageDef* LookupMessage(const char *sym) const; - const EnumDef* LookupEnum(const char *sym) const; - - /* TODO: iteration? */ - - /* Adds the given serialized FileDescriptorProto to the pool. */ - bool AddFile(const google_protobuf_FileDescriptorProto *file_proto, - Status *status); - - /* Adds the given serialized FileDescriptorSet to the pool. */ - bool AddSet(const char *set, size_t len, Status *status); + * order that they were added to the FileDefPtr. */ + int dependency_count() const { return upb_filedef_depcount(ptr_); } + const FileDefPtr dependency(int index) const { + return FileDefPtr(upb_filedef_dep(ptr_, index)); + } private: - UPB_DISALLOW_POD_OPS(SymbolTable, upb::SymbolTable) + const upb_filedef* ptr_; }; #endif /* __cplusplus */ -UPB_BEGIN_EXTERN_C +/* upb_symtab *****************************************************************/ -/* Native C API. */ +UPB_BEGIN_EXTERN_C upb_symtab *upb_symtab_new(); void upb_symtab_free(upb_symtab* s); @@ -725,299 +798,43 @@ bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init); UPB_END_EXTERN_C #ifdef __cplusplus -/* C++ inline wrappers. */ -namespace upb { -inline SymbolTable* SymbolTable::New() { - return upb_symtab_new(); -} -inline void SymbolTable::Free(SymbolTable* s) { - upb_symtab_free(s); -} -inline const MessageDef *SymbolTable::LookupMessage(const char *sym) const { - return upb_symtab_lookupmsg(this, sym); -} -inline bool SymbolTable::AddFile( - const google_protobuf_FileDescriptorProto *file_proto, Status *status) { - return upb_symtab_addfile(this, file_proto, status); -} -} /* namespace upb */ -#endif - -#ifdef __cplusplus - -UPB_INLINE const char* upb_safecstr(const std::string& str) { - UPB_ASSERT(str.size() == std::strlen(str.c_str())); - return str.c_str(); -} - -/* Inline C++ wrappers. */ -namespace upb { - -inline const char* FieldDef::full_name() const { - return upb_fielddef_fullname(this); -} -inline FieldDef::Type FieldDef::type() const { return upb_fielddef_type(this); } -inline FieldDef::DescriptorType FieldDef::descriptor_type() const { - return upb_fielddef_descriptortype(this); -} -inline FieldDef::Label FieldDef::label() const { - return upb_fielddef_label(this); -} -inline uint32_t FieldDef::number() const { return upb_fielddef_number(this); } -inline const char* FieldDef::name() const { return upb_fielddef_name(this); } -inline bool FieldDef::is_extension() const { - return upb_fielddef_isextension(this); -} -inline size_t FieldDef::GetJsonName(char* buf, size_t len) const { - return upb_fielddef_getjsonname(this, buf, len); -} -inline bool FieldDef::lazy() const { - return upb_fielddef_lazy(this); -} -inline bool FieldDef::packed() const { - return upb_fielddef_packed(this); -} -inline uint32_t FieldDef::index() const { - return upb_fielddef_index(this); -} -inline const MessageDef* FieldDef::containing_type() const { - return upb_fielddef_containingtype(this); -} -inline const OneofDef* FieldDef::containing_oneof() const { - return upb_fielddef_containingoneof(this); -} -inline bool FieldDef::IsSubMessage() const { - return upb_fielddef_issubmsg(this); -} -inline bool FieldDef::IsString() const { return upb_fielddef_isstring(this); } -inline bool FieldDef::IsSequence() const { return upb_fielddef_isseq(this); } -inline bool FieldDef::IsMap() const { return upb_fielddef_ismap(this); } -inline int64_t FieldDef::default_int64() const { - return upb_fielddef_defaultint64(this); -} -inline int32_t FieldDef::default_int32() const { - return upb_fielddef_defaultint32(this); -} -inline uint64_t FieldDef::default_uint64() const { - return upb_fielddef_defaultuint64(this); -} -inline uint32_t FieldDef::default_uint32() const { - return upb_fielddef_defaultuint32(this); -} -inline bool FieldDef::default_bool() const { - return upb_fielddef_defaultbool(this); -} -inline float FieldDef::default_float() const { - return upb_fielddef_defaultfloat(this); -} -inline double FieldDef::default_double() const { - return upb_fielddef_defaultdouble(this); -} -inline const char* FieldDef::default_string(size_t* len) const { - return upb_fielddef_defaultstr(this, len); -} -inline const MessageDef *FieldDef::message_subdef() const { - return upb_fielddef_msgsubdef(this); -} -inline const EnumDef *FieldDef::enum_subdef() const { - return upb_fielddef_enumsubdef(this); -} -inline const char *MessageDef::full_name() const { - return upb_msgdef_fullname(this); -} -inline const char *MessageDef::name() const { - return upb_msgdef_name(this); -} -inline upb_syntax_t MessageDef::syntax() const { - return upb_msgdef_syntax(this); -} -inline int MessageDef::field_count() const { - return upb_msgdef_numfields(this); -} -inline int MessageDef::oneof_count() const { - return upb_msgdef_numoneofs(this); -} -inline const FieldDef* MessageDef::FindFieldByNumber(uint32_t number) const { - return upb_msgdef_itof(this, number); -} -inline const FieldDef *MessageDef::FindFieldByName(const char *name, - size_t len) const { - return upb_msgdef_ntof(this, name, len); -} -inline const OneofDef* MessageDef::FindOneofByName(const char* name, - size_t len) const { - return upb_msgdef_ntoo(this, name, len); -} -inline bool MessageDef::mapentry() const { - return upb_msgdef_mapentry(this); -} -inline upb_wellknowntype_t MessageDef::wellknowntype() const { - return upb_msgdef_wellknowntype(this); -} -inline bool MessageDef::isnumberwrapper() const { - return upb_msgdef_isnumberwrapper(this); -} -inline MessageDef::const_field_iterator MessageDef::field_begin() const { - return const_field_iterator(this); -} -inline MessageDef::const_field_iterator MessageDef::field_end() const { - return const_field_iterator::end(this); -} - -inline MessageDef::const_oneof_iterator MessageDef::oneof_begin() const { - return const_oneof_iterator(this); -} -inline MessageDef::const_oneof_iterator MessageDef::oneof_end() const { - return const_oneof_iterator::end(this); -} +/* Non-const methods in upb::SymbolTable are NOT thread-safe. */ +class upb::SymbolTable { + public: + SymbolTable() : ptr_(upb_symtab_new(), upb_symtab_free) {} + explicit SymbolTable(upb_symtab* s) : ptr_(s, upb_symtab_free) {} -inline MessageDef::const_field_iterator::const_field_iterator( - const MessageDef* md) { - upb_msg_field_begin(&iter_, md); -} -inline MessageDef::const_field_iterator MessageDef::const_field_iterator::end( - const MessageDef *md) { - MessageDef::const_field_iterator iter(md); - upb_msg_field_iter_setdone(&iter.iter_); - return iter; -} -inline const FieldDef* MessageDef::const_field_iterator::operator*() const { - return upb_msg_iter_field(&iter_); -} -inline void MessageDef::const_field_iterator::operator++() { - return upb_msg_field_next(&iter_); -} -inline bool MessageDef::const_field_iterator::operator==( - const const_field_iterator &other) const { - return upb_inttable_iter_isequal(&iter_, &other.iter_); -} -inline bool MessageDef::const_field_iterator::operator!=( - const const_field_iterator &other) const { - return !(*this == other); -} + const upb_symtab* ptr() const { return ptr_.get(); } + upb_symtab* ptr() { return ptr_.get(); } -inline MessageDef::const_oneof_iterator::const_oneof_iterator( - const MessageDef* md) { - upb_msg_oneof_begin(&iter_, md); -} -inline MessageDef::const_oneof_iterator MessageDef::const_oneof_iterator::end( - const MessageDef *md) { - MessageDef::const_oneof_iterator iter(md); - upb_msg_oneof_iter_setdone(&iter.iter_); - return iter; -} -inline const OneofDef* MessageDef::const_oneof_iterator::operator*() const { - return upb_msg_iter_oneof(&iter_); -} -inline void MessageDef::const_oneof_iterator::operator++() { - return upb_msg_oneof_next(&iter_); -} -inline bool MessageDef::const_oneof_iterator::operator==( - const const_oneof_iterator &other) const { - return upb_strtable_iter_isequal(&iter_, &other.iter_); -} -inline bool MessageDef::const_oneof_iterator::operator!=( - const const_oneof_iterator &other) const { - return !(*this == other); -} + /* Finds an entry in the symbol table with this exact name. If not found, + * returns NULL. */ + MessageDefPtr LookupMessage(const char *sym) const { + return MessageDefPtr(upb_symtab_lookupmsg(ptr_.get(), sym)); + } -inline const char* EnumDef::full_name() const { - return upb_enumdef_fullname(this); -} -inline const char* EnumDef::name() const { - return upb_enumdef_name(this); -} -inline int32_t EnumDef::default_value() const { - return upb_enumdef_default(this); -} -inline int EnumDef::value_count() const { return upb_enumdef_numvals(this); } -inline bool EnumDef::FindValueByName(const char* name, int32_t *num) const { - return upb_enumdef_ntoiz(this, name, num); -} -inline const char* EnumDef::FindValueByNumber(int32_t num) const { - return upb_enumdef_iton(this, num); -} + const EnumDefPtr LookupEnum(const char *sym) const { + return EnumDefPtr(upb_symtab_lookupenum(ptr_.get(), sym)); + } -inline EnumDef::Iterator::Iterator(const EnumDef* e) { - upb_enum_begin(&iter_, e); -} -inline int32_t EnumDef::Iterator::number() { - return upb_enum_iter_number(&iter_); -} -inline const char* EnumDef::Iterator::name() { - return upb_enum_iter_name(&iter_); -} -inline bool EnumDef::Iterator::Done() { return upb_enum_done(&iter_); } -inline void EnumDef::Iterator::Next() { return upb_enum_next(&iter_); } + /* TODO: iteration? */ -inline const MessageDef* OneofDef::containing_type() const { - return upb_oneofdef_containingtype(this); -} -inline const char* OneofDef::name() const { - return upb_oneofdef_name(this); -} -inline int OneofDef::field_count() const { - return upb_oneofdef_numfields(this); -} -inline const FieldDef* OneofDef::FindFieldByName(const char* name, - size_t len) const { - return upb_oneofdef_ntof(this, name, len); -} -inline const FieldDef* OneofDef::FindFieldByNumber(uint32_t num) const { - return upb_oneofdef_itof(this, num); -} -inline OneofDef::const_iterator OneofDef::begin() const { - return const_iterator(this); -} -inline OneofDef::const_iterator OneofDef::end() const { - return const_iterator::end(this); -} + /* Adds the given serialized FileDescriptorProto to the pool. */ + bool AddFile(const google_protobuf_FileDescriptorProto *file_proto, + Status *status) { + return upb_symtab_addfile(ptr_.get(), file_proto, status); + } -inline OneofDef::const_iterator::const_iterator(const OneofDef* md) { - upb_oneof_begin(&iter_, md); -} -inline OneofDef::const_iterator OneofDef::const_iterator::end( - const OneofDef *md) { - OneofDef::const_iterator iter(md); - upb_oneof_iter_setdone(&iter.iter_); - return iter; -} -inline const FieldDef* OneofDef::const_iterator::operator*() const { - return upb_msg_iter_field(&iter_); -} -inline void OneofDef::const_iterator::operator++() { - return upb_oneof_next(&iter_); -} -inline bool OneofDef::const_iterator::operator==( - const const_iterator &other) const { - return upb_inttable_iter_isequal(&iter_, &other.iter_); -} -inline bool OneofDef::const_iterator::operator!=( - const const_iterator &other) const { - return !(*this == other); -} + private: + std::unique_ptr ptr_; +}; -inline const char* FileDef::name() const { - return upb_filedef_name(this); -} -inline const char* FileDef::package() const { - return upb_filedef_package(this); -} -inline const char* FileDef::phpprefix() const { - return upb_filedef_phpprefix(this); -} -inline const char* FileDef::phpnamespace() const { - return upb_filedef_phpnamespace(this); -} -inline int FileDef::dependency_count() const { - return upb_filedef_depcount(this); -} -inline const FileDef* FileDef::dependency(int index) const { - return upb_filedef_dep(this, index); +UPB_INLINE const char* upb_safecstr(const std::string& str) { + UPB_ASSERT(str.size() == std::strlen(str.c_str())); + return str.c_str(); } -} /* namespace upb */ -#endif +#endif /* __cplusplus */ #endif /* UPB_DEF_H_ */ diff --git a/upb/handlers-inl.h b/upb/handlers-inl.h index eb9a0fa..b038e30 100644 --- a/upb/handlers-inl.h +++ b/upb/handlers-inl.h @@ -8,39 +8,6 @@ #include -/* C inline methods. */ - -/* upb_bufhandle */ -UPB_INLINE void upb_bufhandle_init(upb_bufhandle *h) { - h->obj_ = NULL; - h->objtype_ = NULL; - h->buf_ = NULL; - h->objofs_ = 0; -} -UPB_INLINE void upb_bufhandle_uninit(upb_bufhandle *h) { - UPB_UNUSED(h); -} -UPB_INLINE void upb_bufhandle_setobj(upb_bufhandle *h, const void *obj, - const void *type) { - h->obj_ = obj; - h->objtype_ = type; -} -UPB_INLINE void upb_bufhandle_setbuf(upb_bufhandle *h, const char *buf, - size_t ofs) { - h->buf_ = buf; - h->objofs_ = ofs; -} -UPB_INLINE const void *upb_bufhandle_obj(const upb_bufhandle *h) { - return h->obj_; -} -UPB_INLINE const void *upb_bufhandle_objtype(const upb_bufhandle *h) { - return h->objtype_; -} -UPB_INLINE const char *upb_bufhandle_buf(const upb_bufhandle *h) { - return h->buf_; -} - - #ifdef __cplusplus /* Type detection and typedefs for integer types. @@ -604,9 +571,9 @@ void *ReturnClosureOrBreak3(P1 p1, P2 p2, P3 p3) { /* For the string callback, which takes five params, returns the size param. */ template + void F(P1, P2, const char *, size_t, const upb_bufhandle *)> size_t ReturnStringLen(P1 p1, P2 p2, const char *p3, size_t p4, - const BufferHandle *p5) { + const upb_bufhandle *p5) { F(p1, p2, p3, p4, p5); return p4; } @@ -614,9 +581,9 @@ size_t ReturnStringLen(P1 p1, P2 p2, const char *p3, size_t p4, /* For the string callback, which takes five params, returns the size param or * zero. */ template + bool F(P1, P2, const char *, size_t, const upb_bufhandle *)> size_t ReturnNOr0(P1 p1, P2 p2, const char *p3, size_t p4, - const BufferHandle *p5) { + const upb_bufhandle *p5) { return F(p1, p2, p3, p4, p5) ? p4 : 0; } @@ -675,22 +642,22 @@ struct MaybeWrapReturn, void *> { /* If our function returns void but we want one returning size_t, wrap it in a * function that returns the size argument. */ template + void F(P1, P2, const char *, size_t, const upb_bufhandle *), class I> struct MaybeWrapReturn< - Func5, + Func5, size_t> { - typedef Func5, I> Func; }; /* If our function returns bool but we want one returning size_t, wrap it in a * function that returns either 0 or the buf size. */ template + bool F(P1, P2, const char *, size_t, const upb_bufhandle *), class I> struct MaybeWrapReturn< - Func5, + Func5, size_t> { - typedef Func5, I> Func; }; @@ -731,7 +698,7 @@ R IgnoreHandlerData5(void *p1, const void *hd, P2 p2, P3 p3, P4 p4) { template R IgnoreHandlerDataIgnoreHandle(void *p1, const void *hd, const char *p2, - size_t p3, const BufferHandle *handle) { + size_t p3, const upb_bufhandle *handle) { UPB_UNUSED(hd); UPB_UNUSED(handle); return F(static_cast(p1), p2, p3); @@ -757,7 +724,7 @@ R CastHandlerData5(void *c, const void *hd, P3 p3, P4 p4, P5 p5) { template R CastHandlerDataIgnoreHandle(void *c, const void *hd, const char *p3, - size_t p4, const BufferHandle *handle) { + size_t p4, const upb_bufhandle *handle) { UPB_UNUSED(handle); return F(static_cast(c), static_cast(hd), p3, p4); } @@ -777,11 +744,11 @@ struct ConvertParams, }; /* For StringBuffer only; this ignores both the handler data and the - * BufferHandle. */ + * upb_bufhandle. */ template struct ConvertParams, T> { typedef Func5, + const upb_bufhandle *, IgnoreHandlerDataIgnoreHandle, I> Func; }; @@ -807,13 +774,14 @@ struct ConvertParams, CastHandlerData3, I> Func; }; -/* For StringBuffer only; this ignores the BufferHandle. */ +/* For StringBuffer only; this ignores the upb_bufhandle. */ template struct ConvertParams, T> { typedef Func5, - I> Func; + const upb_bufhandle *, + CastHandlerDataIgnoreHandle, I> + Func; }; template , T> { /* utype/ltype are upper/lower-case, ctype is canonical C type, vtype is * variant C type. */ -#define TYPE_METHODS(utype, ltype, ctype, vtype) \ - template <> struct CanonicalType { \ - typedef ctype Type; \ - }; \ - template <> \ - inline bool Handlers::SetValueHandler( \ - const FieldDef *f, \ - const Handlers::utype ## Handler& handler) { \ - UPB_ASSERT(!handler.registered_); \ - handler.AddCleanup(this); \ - handler.registered_ = true; \ - return upb_handlers_set##ltype(this, f, handler.handler_, &handler.attr_); \ - } \ +#define TYPE_METHODS(utype, ltype, ctype, vtype) \ + template <> \ + struct CanonicalType { \ + typedef ctype Type; \ + }; \ + template <> \ + inline bool HandlersPtr::SetValueHandler( \ + FieldDefPtr f, const HandlersPtr::utype##Handler &handler) { \ + handler.AddCleanup(ptr()); \ + return upb_handlers_set##ltype(ptr(), f.ptr(), handler.handler(), \ + &handler.attr()); \ + } TYPE_METHODS(Double, double, double, double) TYPE_METHODS(Float, float, float, float) @@ -862,24 +829,6 @@ template <> struct CanonicalType { typedef Status* Type; }; -/* Type methods that are only one-per-canonical-type and not - * one-per-cvariant. */ - -#define TYPE_METHODS(utype, ctype) \ - inline bool Handlers::Set##utype##Handler(const FieldDef *f, \ - const utype##Handler &h) { \ - return SetValueHandler(f, h); \ - } \ - -TYPE_METHODS(Double, double) -TYPE_METHODS(Float, float) -TYPE_METHODS(UInt64, uint64_t) -TYPE_METHODS(UInt32, uint32_t) -TYPE_METHODS(Int64, int64_t) -TYPE_METHODS(Int32, int32_t) -TYPE_METHODS(Bool, bool) -#undef TYPE_METHODS - template struct ReturnOf; template @@ -902,10 +851,6 @@ struct ReturnOf { typedef R Return; }; -template const void *UniquePtrForType() { - static const char ch = 0; - return &ch; -} template template @@ -926,10 +871,10 @@ inline Handler::Handler(F func) /* If the original function returns void, then we know that we wrapped it to * always return ok. */ bool always_ok = is_same::value; - attr_.SetAlwaysOk(always_ok); + attr_.alwaysok = always_ok; /* Closure parameter and return type. */ - attr_.SetClosureType(UniquePtrForType()); + attr_.closure_type = UniquePtrForType(); /* We use the closure type (from the first parameter) if the return type is * void or bool, since these are the two cases we wrap to return the closure's @@ -940,176 +885,19 @@ inline Handler::Handler(F func) typedef typename FirstUnlessVoidOrBool::value EffectiveReturn; - attr_.SetReturnClosureType(UniquePtrForType()); + attr_.return_closure_type = UniquePtrForType(); } template -inline Handler::~Handler() { - UPB_ASSERT(registered_); -} - -inline HandlerAttributes::HandlerAttributes() { upb_handlerattr_init(this); } -inline HandlerAttributes::~HandlerAttributes() { upb_handlerattr_uninit(this); } -inline bool HandlerAttributes::SetHandlerData(const void *hd) { - return upb_handlerattr_sethandlerdata(this, hd); -} -inline const void* HandlerAttributes::handler_data() const { - return upb_handlerattr_handlerdata(this); -} -inline bool HandlerAttributes::SetClosureType(const void *type) { - return upb_handlerattr_setclosuretype(this, type); -} -inline const void* HandlerAttributes::closure_type() const { - return upb_handlerattr_closuretype(this); -} -inline bool HandlerAttributes::SetReturnClosureType(const void *type) { - return upb_handlerattr_setreturnclosuretype(this, type); -} -inline const void* HandlerAttributes::return_closure_type() const { - return upb_handlerattr_returnclosuretype(this); -} -inline bool HandlerAttributes::SetAlwaysOk(bool always_ok) { - return upb_handlerattr_setalwaysok(this, always_ok); -} -inline bool HandlerAttributes::always_ok() const { - return upb_handlerattr_alwaysok(this); -} - -inline BufferHandle::BufferHandle() { upb_bufhandle_init(this); } -inline BufferHandle::~BufferHandle() { upb_bufhandle_uninit(this); } -inline const char* BufferHandle::buffer() const { - return upb_bufhandle_buf(this); -} -inline size_t BufferHandle::object_offset() const { - return upb_bufhandle_objofs(this); -} -inline void BufferHandle::SetBuffer(const char* buf, size_t ofs) { - upb_bufhandle_setbuf(this, buf, ofs); -} -template -void BufferHandle::SetAttachedObject(const T* obj) { - upb_bufhandle_setobj(this, obj, UniquePtrForType()); -} -template -const T* BufferHandle::GetAttachedObject() const { - return upb_bufhandle_objtype(this) == UniquePtrForType() - ? static_cast(upb_bufhandle_obj(this)) - : NULL; -} - -inline const Status* Handlers::status() { - return upb_handlers_status(this); -} -inline void Handlers::ClearError() { - return upb_handlers_clearerr(this); -} -inline const MessageDef *Handlers::message_def() const { - return upb_handlers_msgdef(this); -} -inline bool Handlers::AddCleanup(void *p, upb_handlerfree *func) { - return upb_handlers_addcleanup(this, p, func); -} -inline bool Handlers::SetStartMessageHandler( - const Handlers::StartMessageHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setstartmsg(this, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetEndMessageHandler( - const Handlers::EndMessageHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setendmsg(this, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetStartStringHandler(const FieldDef *f, - const StartStringHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setstartstr(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetEndStringHandler(const FieldDef *f, - const EndFieldHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setendstr(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetStringHandler(const FieldDef *f, - const StringHandler& handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setstring(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetStartSequenceHandler( - const FieldDef *f, const StartFieldHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setstartseq(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetStartSubMessageHandler( - const FieldDef *f, const StartFieldHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setstartsubmsg(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetEndSubMessageHandler(const FieldDef *f, - const EndFieldHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setendsubmsg(this, f, handler.handler_, &handler.attr_); -} -inline bool Handlers::SetEndSequenceHandler(const FieldDef *f, - const EndFieldHandler &handler) { - UPB_ASSERT(!handler.registered_); - handler.registered_ = true; - handler.AddCleanup(this); - return upb_handlers_setendseq(this, f, handler.handler_, &handler.attr_); -} -inline const Handlers *Handlers::GetSubHandlers(const FieldDef *f) const { - return upb_handlers_getsubhandlers(this, f); -} -inline const Handlers *Handlers::GetSubHandlers(Handlers::Selector sel) const { - return upb_handlers_getsubhandlers_sel(this, sel); -} -inline bool Handlers::GetSelector(const FieldDef *f, Handlers::Type type, - Handlers::Selector *s) { - return upb_handlers_getselector(f, type, s); -} -inline Handlers::Selector Handlers::GetEndSelector(Handlers::Selector start) { - return upb_handlers_getendselector(start); -} -inline Handlers::GenericFunction *Handlers::GetHandler( - Handlers::Selector selector) { - return upb_handlers_gethandler(this, selector); -} -inline const void *Handlers::GetHandlerData(Handlers::Selector selector) { - return upb_handlers_gethandlerdata(this, selector); -} - -inline HandlerCache *HandlerCache::New(upb_handlers_callback *callback, - const void *closure) { - return upb_handlercache_new(callback, closure); -} -inline void HandlerCache::Free(HandlerCache* cache) { - return upb_handlercache_free(cache); -} -const Handlers* HandlerCache::Get(const MessageDef* md) { - return upb_handlercache_get(this, md); -} - -inline BytesHandler::BytesHandler() { - upb_byteshandler_init(this); +inline void Handler::AddCleanup(upb_handlers* h) const { + UPB_ASSERT(!registered_); + registered_ = true; + if (cleanup_func_) { + bool ok = upb_handlers_addcleanup(h, cleanup_data_, cleanup_func_); + UPB_ASSERT(ok); + } } -inline BytesHandler::~BytesHandler() {} - } /* namespace upb */ #endif /* __cplusplus */ diff --git a/upb/handlers.c b/upb/handlers.c index 90fb7b8..fd81b03 100644 --- a/upb/handlers.c +++ b/upb/handlers.c @@ -9,6 +9,15 @@ #include "upb/sink.h" + +struct upb_handlers { + upb_handlercache *cache; + const upb_msgdef *msg; + const upb_handlers **sub; + const void *top_closure_type; + upb_handlers_tabent table[1]; /* Dynamically-sized field handler array. */ +}; + static void *upb_calloc(upb_arena *arena, size_t size) { void *mem = upb_malloc(upb_arena_alloc(arena), size); if (mem) { @@ -50,13 +59,13 @@ static upb_selector_t handlers_getsel(upb_handlers *h, const upb_fielddef *f, static const void **returntype(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type) { - return &h->table[handlers_getsel(h, f, type)].attr.return_closure_type_; + return &h->table[handlers_getsel(h, f, type)].attr.return_closure_type; } static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f, upb_handlertype_t type, upb_func *func, - upb_handlerattr *attr) { - upb_handlerattr set_attr = UPB_HANDLERATTR_INITIALIZER; + const upb_handlerattr *attr) { + upb_handlerattr set_attr = UPB_HANDLERATTR_INIT; const void *closure_type; const void **context_closure_type; @@ -68,7 +77,7 @@ static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f, /* Check that the given closure type matches the closure type that has been * established for this context (if any). */ - closure_type = upb_handlerattr_closuretype(&set_attr); + closure_type = set_attr.closure_type; if (type == UPB_HANDLER_STRING) { context_closure_type = returntype(h, f, UPB_HANDLER_STARTSTR); @@ -91,15 +100,15 @@ static bool doset(upb_handlers *h, int32_t sel, const upb_fielddef *f, /* If this is a STARTSEQ or STARTSTR handler, check that the returned pointer * matches any pre-existing expectations about what type is expected. */ if (type == UPB_HANDLER_STARTSEQ || type == UPB_HANDLER_STARTSTR) { - const void *return_type = upb_handlerattr_returnclosuretype(&set_attr); - const void *table_return_type = - upb_handlerattr_returnclosuretype(&h->table[sel].attr); + const void *return_type = set_attr.return_closure_type; + const void *table_return_type = h->table[sel].attr.return_closure_type; if (return_type && table_return_type && return_type != table_return_type) { UPB_ASSERT(false); } - if (table_return_type && !return_type) - upb_handlerattr_setreturnclosuretype(&set_attr, table_return_type); + if (table_return_type && !return_type) { + set_attr.return_closure_type = table_return_type; + } } h->table[sel].func = (upb_func*)func; @@ -125,18 +134,18 @@ const void *effective_closure_type(upb_handlers *h, const upb_fielddef *f, type != UPB_HANDLER_STARTSEQ && type != UPB_HANDLER_ENDSEQ && h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSEQ)].func) { - ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr); + ret = h->table[sel].attr.return_closure_type; } if (type == UPB_HANDLER_STRING && h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSTR)].func) { - ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr); + ret = h->table[sel].attr.return_closure_type; } /* The effective type of the submessage; not used yet. * if (type == SUBMESSAGE && * h->table[sel = handlers_getsel(h, f, UPB_HANDLER_STARTSUBMSG)].func) { - * ret = upb_handlerattr_returnclosuretype(&h->table[sel].attr); + * ret = h->table[sel].attr.return_closure_type; * } */ return ret; @@ -156,7 +165,7 @@ bool checkstart(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type, if (h->table[sel].func) return true; closure_type = effective_closure_type(h, f, type); attr = &h->table[sel].attr; - return_closure_type = upb_handlerattr_returnclosuretype(attr); + return_closure_type = attr->return_closure_type; if (closure_type && return_closure_type && closure_type != return_closure_type) { UPB_ASSERT(false); @@ -164,12 +173,14 @@ bool checkstart(upb_handlers *h, const upb_fielddef *f, upb_handlertype_t type, return true; } -static upb_handlers *upb_handlers_new(const upb_msgdef *md, upb_handlercache *cache) { +static upb_handlers *upb_handlers_new(const upb_msgdef *md, + upb_handlercache *cache, + upb_arena *arena) { int extra; upb_handlers *h; extra = sizeof(upb_handlers_tabent) * (upb_msgdef_selectorcount(md) - 1); - h = upb_calloc(&cache->arena, sizeof(*h) + extra); + h = upb_calloc(arena, sizeof(*h) + extra); if (!h) return NULL; h->cache = cache; @@ -177,7 +188,7 @@ static upb_handlers *upb_handlers_new(const upb_msgdef *md, upb_handlercache *ca if (upb_msgdef_submsgfieldcount(md) > 0) { size_t bytes = upb_msgdef_submsgfieldcount(md) * sizeof(*h->sub); - h->sub = upb_calloc(&cache->arena, bytes); + h->sub = upb_calloc(arena, bytes); if (!h->sub) return NULL; } else { h->sub = 0; @@ -187,14 +198,14 @@ static upb_handlers *upb_handlers_new(const upb_msgdef *md, upb_handlercache *ca return h; } - /* Public interface ***********************************************************/ -#define SETTER(name, handlerctype, handlertype) \ - bool upb_handlers_set ## name(upb_handlers *h, const upb_fielddef *f, \ - handlerctype func, upb_handlerattr *attr) { \ - int32_t sel = trygetsel(h, f, handlertype); \ - return doset(h, sel, f, handlertype, (upb_func*)func, attr); \ +#define SETTER(name, handlerctype, handlertype) \ + bool upb_handlers_set##name(upb_handlers *h, const upb_fielddef *f, \ + handlerctype func, \ + const upb_handlerattr *attr) { \ + int32_t sel = trygetsel(h, f, handlertype); \ + return doset(h, sel, f, handlertype, (upb_func *)func, attr); \ } SETTER(int32, upb_int32_handlerfunc*, UPB_HANDLER_INT32) @@ -215,19 +226,19 @@ SETTER(endseq, upb_endfield_handlerfunc*, UPB_HANDLER_ENDSEQ) #undef SETTER bool upb_handlers_setunknown(upb_handlers *h, upb_unknown_handlerfunc *func, - upb_handlerattr *attr) { + const upb_handlerattr *attr) { return doset(h, UPB_UNKNOWN_SELECTOR, NULL, UPB_HANDLER_INT32, (upb_func *)func, attr); } bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func, - upb_handlerattr *attr) { + const upb_handlerattr *attr) { return doset(h, UPB_STARTMSG_SELECTOR, NULL, UPB_HANDLER_INT32, (upb_func *)func, attr); } bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func, - upb_handlerattr *attr) { + const upb_handlerattr *attr) { return doset(h, UPB_ENDMSG_SELECTOR, NULL, UPB_HANDLER_INT32, (upb_func *)func, attr); } @@ -250,9 +261,18 @@ const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h, return SUBH_F(h, f); } +upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s, + const void **handler_data) { + upb_func *ret = (upb_func *)h->table[s].func; + if (ret && handler_data) { + *handler_data = h->table[s].attr.handler_data; + } + return ret; +} + bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t sel, upb_handlerattr *attr) { - if (!upb_handlers_gethandler(h, sel)) + if (!upb_handlers_gethandler(h, sel, NULL)) return false; *attr = h->table[sel].attr; return true; @@ -266,16 +286,6 @@ const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h, const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; } -bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) { - bool ok; - if (upb_inttable_lookupptr(&h->cache->cleanup_, p, NULL)) { - return false; - } - ok = upb_inttable_insertptr(&h->cache->cleanup_, p, upb_value_fptr(func)); - UPB_ASSERT(ok); - return true; -} - upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) { switch (upb_fielddef_type(f)) { case UPB_TYPE_INT32: @@ -375,6 +385,14 @@ uint32_t upb_handlers_selectorcount(const upb_fielddef *f) { /* upb_handlercache ***********************************************************/ +struct upb_handlercache { + upb_arena arena; + upb_inttable tab; /* maps upb_msgdef* -> upb_handlers*. */ + upb_inttable cleanup_; + upb_handlers_callback *callback; + const void *closure; +}; + const upb_handlers *upb_handlercache_get(upb_handlercache *c, const upb_msgdef *md) { upb_msg_field_iter i; @@ -385,7 +403,7 @@ const upb_handlers *upb_handlercache_get(upb_handlercache *c, return upb_value_getptr(v); } - h = upb_handlers_new(md, c); + h = upb_handlers_new(md, c, &c->arena); v = upb_value_ptr(h); if (!h) return NULL; @@ -452,90 +470,39 @@ void upb_handlercache_free(upb_handlercache *cache) { upb_gfree(cache); } - -/* upb_handlerattr ************************************************************/ - -void upb_handlerattr_init(upb_handlerattr *attr) { - upb_handlerattr from = UPB_HANDLERATTR_INITIALIZER; - memcpy(attr, &from, sizeof(*attr)); -} - -void upb_handlerattr_uninit(upb_handlerattr *attr) { - UPB_UNUSED(attr); -} - -bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, const void *hd) { - attr->handler_data_ = hd; - return true; -} - -bool upb_handlerattr_setclosuretype(upb_handlerattr *attr, const void *type) { - attr->closure_type_ = type; - return true; -} - -const void *upb_handlerattr_closuretype(const upb_handlerattr *attr) { - return attr->closure_type_; -} - -bool upb_handlerattr_setreturnclosuretype(upb_handlerattr *attr, - const void *type) { - attr->return_closure_type_ = type; - return true; -} - -const void *upb_handlerattr_returnclosuretype(const upb_handlerattr *attr) { - return attr->return_closure_type_; -} - -bool upb_handlerattr_setalwaysok(upb_handlerattr *attr, bool alwaysok) { - attr->alwaysok_ = alwaysok; +bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) { + bool ok; + if (upb_inttable_lookupptr(&h->cache->cleanup_, p, NULL)) { + return false; + } + ok = upb_inttable_insertptr(&h->cache->cleanup_, p, upb_value_fptr(func)); + UPB_ASSERT(ok); return true; } -bool upb_handlerattr_alwaysok(const upb_handlerattr *attr) { - return attr->alwaysok_; -} - -/* upb_bufhandle **************************************************************/ - -size_t upb_bufhandle_objofs(const upb_bufhandle *h) { - return h->objofs_; -} - /* upb_byteshandler ***********************************************************/ -void upb_byteshandler_init(upb_byteshandler* h) { - memset(h, 0, sizeof(*h)); -} - -/* For when we support handlerfree callbacks. */ -void upb_byteshandler_uninit(upb_byteshandler* h) { - UPB_UNUSED(h); -} - bool upb_byteshandler_setstartstr(upb_byteshandler *h, upb_startstr_handlerfunc *func, void *d) { h->table[UPB_STARTSTR_SELECTOR].func = (upb_func*)func; - h->table[UPB_STARTSTR_SELECTOR].attr.handler_data_ = d; + h->table[UPB_STARTSTR_SELECTOR].attr.handler_data = d; return true; } bool upb_byteshandler_setstring(upb_byteshandler *h, upb_string_handlerfunc *func, void *d) { h->table[UPB_STRING_SELECTOR].func = (upb_func*)func; - h->table[UPB_STRING_SELECTOR].attr.handler_data_ = d; + h->table[UPB_STRING_SELECTOR].attr.handler_data = d; return true; } bool upb_byteshandler_setendstr(upb_byteshandler *h, upb_endfield_handlerfunc *func, void *d) { h->table[UPB_ENDSTR_SELECTOR].func = (upb_func*)func; - h->table[UPB_ENDSTR_SELECTOR].attr.handler_data_ = d; + h->table[UPB_ENDSTR_SELECTOR].attr.handler_data = d; return true; } - /** Handlers for upb_msg ******************************************************/ typedef struct { @@ -564,7 +531,7 @@ MSG_WRITER(bool, bool) bool upb_msg_setscalarhandler(upb_handlers *h, const upb_fielddef *f, size_t offset, int32_t hasbit) { - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlerattr attr = UPB_HANDLERATTR_INIT; bool ok; upb_msg_handlerdata *d = upb_gmalloc(sizeof(*d)); @@ -572,8 +539,8 @@ bool upb_msg_setscalarhandler(upb_handlers *h, const upb_fielddef *f, d->offset = offset; d->hasbit = hasbit; - upb_handlerattr_sethandlerdata(&attr, d); - upb_handlerattr_setalwaysok(&attr, true); + attr.handler_data = d; + attr.alwaysok = true; upb_handlers_addcleanup(h, d, upb_gfree); #define TYPE(u, l) \ @@ -595,7 +562,6 @@ bool upb_msg_setscalarhandler(upb_handlers *h, const upb_fielddef *f, } #undef TYPE - upb_handlerattr_uninit(&attr); return ok; } @@ -605,7 +571,8 @@ bool upb_msg_getscalarhandlerdata(const upb_handlers *h, size_t *offset, int32_t *hasbit) { const upb_msg_handlerdata *d; - upb_func *f = upb_handlers_gethandler(h, s); + const void *p; + upb_func *f = upb_handlers_gethandler(h, s, &p); if ((upb_int64_handlerfunc*)f == upb_msg_setint64) { *type = UPB_TYPE_INT64; @@ -625,7 +592,7 @@ bool upb_msg_getscalarhandlerdata(const upb_handlers *h, return false; } - d = upb_handlers_gethandlerdata(h, s); + d = p; *offset = d->offset; *hasbit = d->hasbit; return true; diff --git a/upb/handlers.h b/upb/handlers.h index 741bd48..4558786 100644 --- a/upb/handlers.h +++ b/upb/handlers.h @@ -24,21 +24,13 @@ #ifdef __cplusplus namespace upb { -class BufferHandle; -class BytesHandler; -class HandlerAttributes; -class Handlers; +class HandlersPtr; class HandlerCache; template class Handler; template struct CanonicalType; } /* namespace upb */ #endif -UPB_DECLARE_TYPE(upb::BufferHandle, upb_bufhandle) -UPB_DECLARE_TYPE(upb::BytesHandler, upb_byteshandler) -UPB_DECLARE_TYPE(upb::HandlerAttributes, upb_handlerattr) -UPB_DECLARE_TYPE(upb::Handlers, upb_handlers) -UPB_DECLARE_TYPE(upb::HandlerCache, upb_handlercache) /* 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. @@ -80,28 +72,6 @@ extern char _upb_noclosure; * (for example: the STARTSUBMSG handler for field "field15"). */ typedef int32_t upb_selector_t; -UPB_BEGIN_EXTERN_C - -/* Forward-declares for C inline accessors. We need to declare these here - * so we can "friend" them in the class declarations in C++. */ -UPB_INLINE upb_func *upb_handlers_gethandler(const upb_handlers *h, - upb_selector_t s); -UPB_INLINE const void *upb_handlerattr_handlerdata(const upb_handlerattr *attr); -UPB_INLINE const void *upb_handlers_gethandlerdata(const upb_handlers *h, - upb_selector_t s); - -UPB_INLINE void upb_bufhandle_init(upb_bufhandle *h); -UPB_INLINE void upb_bufhandle_setobj(upb_bufhandle *h, const void *obj, - const void *type); -UPB_INLINE void upb_bufhandle_setbuf(upb_bufhandle *h, const char *buf, - size_t ofs); -UPB_INLINE const void *upb_bufhandle_obj(const upb_bufhandle *h); -UPB_INLINE const void *upb_bufhandle_objtype(const upb_bufhandle *h); -UPB_INLINE const char *upb_bufhandle_buf(const upb_bufhandle *h); - -UPB_END_EXTERN_C - - /* Static selectors for upb::Handlers. */ #define UPB_STARTMSG_SELECTOR 0 #define UPB_ENDMSG_SELECTOR 1 @@ -113,126 +83,234 @@ UPB_END_EXTERN_C #define UPB_STRING_SELECTOR 1 #define UPB_ENDSTR_SELECTOR 2 -typedef void upb_handlerfree(void *d); - #ifdef __cplusplus - -/* A set of attributes that accompanies a handler's function pointer. */ -class upb::HandlerAttributes { - public: - HandlerAttributes(); - ~HandlerAttributes(); - - /* Sets the handler data that will be passed as the second parameter of the - * handler. To free this pointer when the handlers are freed, call - * Handlers::AddCleanup(). */ - bool SetHandlerData(const void *handler_data); - const void* handler_data() const; - - /* Use this to specify the type of the closure. This will be checked against - * all other closure types for handler that use the same closure. - * Registration will fail if this does not match all other non-NULL closure - * types. */ - bool SetClosureType(const void *closure_type); - const void* closure_type() const; - - /* Use this to specify the type of the returned closure. Only used for - * Start*{String,SubMessage,Sequence} handlers. This must match the closure - * type of any handlers that use it (for example, the StringBuf handler must - * match the closure returned from StartString). */ - bool SetReturnClosureType(const void *return_closure_type); - const void* return_closure_type() const; - - /* Set to indicate that the handler always returns "ok" (either "true" or a - * non-NULL closure). This is a hint that can allow code generators to - * generate more efficient code. */ - bool SetAlwaysOk(bool always_ok); - bool always_ok() const; - - private: - friend UPB_INLINE const void * ::upb_handlerattr_handlerdata( - const upb_handlerattr *attr); -#else -struct upb_handlerattr { +template const void *UniquePtrForType() { + static const char ch = 0; + return &ch; +} #endif - const void *handler_data_; - const void *closure_type_; - const void *return_closure_type_; - bool alwaysok_; -}; -#define UPB_HANDLERATTR_INITIALIZER {NULL, NULL, NULL, false} +/* upb_handlers ************************************************************/ +/* Handler attributes, to be registered with the handler itself. */ typedef struct { - upb_func *func; + const void *handler_data; + const void *closure_type; + const void *return_closure_type; + bool alwaysok; +} upb_handlerattr; - /* It is wasteful to include the entire attributes here: - * - * * Some of the information is redundant (like storing the closure type - * separately for each handler that must match). - * * Some of the info is only needed prior to freeze() (like closure types). - * * alignment padding wastes a lot of space for alwaysok_. - * - * If/when the size and locality of handlers is an issue, we can optimize this - * not to store the entire attr like this. We do not expose the table's - * layout to allow this optimization in the future. */ - upb_handlerattr attr; -} upb_handlers_tabent; - -#ifdef __cplusplus - -/* Extra information about a buffer that is passed to a StringBuf handler. - * TODO(haberman): allow the handle to be pinned so that it will outlive - * the handler invocation. */ -class upb::BufferHandle { - public: - BufferHandle(); - ~BufferHandle(); +#define UPB_HANDLERATTR_INIT {NULL, NULL, NULL, false} +/* Bufhandle, data passed along with a buffer to indicate its provenance. */ +typedef struct { /* The beginning of the buffer. This may be different than the pointer * passed to a StringBuf handler because the handler may receive data * that is from the middle or end of a larger buffer. */ - const char* buffer() const; + const char *buf; /* The offset within the attached object where this buffer begins. Only * meaningful if there is an attached object. */ - size_t object_offset() const; + size_t objofs; - /* Note that object_offset is the offset of "buf" within the attached - * object. */ - void SetBuffer(const char* buf, size_t object_offset); + /* The attached object (if any) and a pointer representing its type. */ + const void *obj; + const void *objtype; - /* The BufferHandle can have an "attached object", which can be used to - * tunnel through a pointer to the buffer's underlying representation. */ +#ifdef __cplusplus template - void SetAttachedObject(const T* obj); + void SetAttachedObject(const T* _obj) { + obj = _obj; + objtype = UniquePtrForType(); + } - /* Returns NULL if the attached object is not of this type. */ template - const T* GetAttachedObject() const; - - private: - friend UPB_INLINE void ::upb_bufhandle_init(upb_bufhandle *h); - friend UPB_INLINE void ::upb_bufhandle_setobj(upb_bufhandle *h, - const void *obj, - const void *type); - friend UPB_INLINE void ::upb_bufhandle_setbuf(upb_bufhandle *h, - const char *buf, size_t ofs); - friend UPB_INLINE const void* ::upb_bufhandle_obj(const upb_bufhandle *h); - friend UPB_INLINE const void* ::upb_bufhandle_objtype( - const upb_bufhandle *h); - friend UPB_INLINE const char* ::upb_bufhandle_buf(const upb_bufhandle *h); -#else -struct upb_bufhandle { + const T *GetAttachedObject() const { + return objtype == UniquePtrForType() ? static_cast(obj) + : NULL; + } #endif - const char *buf_; - const void *obj_; - const void *objtype_; - size_t objofs_; -}; +} upb_bufhandle; + +#define UPB_BUFHANDLE_INIT {NULL, 0, NULL, NULL} + +/* Handler function typedefs. */ +typedef void upb_handlerfree(void *d); +typedef bool upb_unknown_handlerfunc(void *c, const void *hd, const char *buf, + size_t n); +typedef bool upb_startmsg_handlerfunc(void *c, const void*); +typedef bool upb_endmsg_handlerfunc(void *c, const void *, upb_status *status); +typedef void* upb_startfield_handlerfunc(void *c, const void *hd); +typedef bool upb_endfield_handlerfunc(void *c, const void *hd); +typedef bool upb_int32_handlerfunc(void *c, const void *hd, int32_t val); +typedef bool upb_int64_handlerfunc(void *c, const void *hd, int64_t val); +typedef bool upb_uint32_handlerfunc(void *c, const void *hd, uint32_t val); +typedef bool upb_uint64_handlerfunc(void *c, const void *hd, uint64_t val); +typedef bool upb_float_handlerfunc(void *c, const void *hd, float val); +typedef bool upb_double_handlerfunc(void *c, const void *hd, double val); +typedef bool upb_bool_handlerfunc(void *c, const void *hd, bool val); +typedef void *upb_startstr_handlerfunc(void *c, const void *hd, + size_t size_hint); +typedef size_t upb_string_handlerfunc(void *c, const void *hd, const char *buf, + size_t n, const upb_bufhandle* handle); + +struct upb_handlers; +typedef struct upb_handlers upb_handlers; + +UPB_BEGIN_EXTERN_C + +/* Mutating accessors. */ +const upb_status *upb_handlers_status(upb_handlers *h); +void upb_handlers_clearerr(upb_handlers *h); +const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h); +bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *hfree); +bool upb_handlers_setunknown(upb_handlers *h, upb_unknown_handlerfunc *func, + const upb_handlerattr *attr); +bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func, + const upb_handlerattr *attr); +bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func, + const upb_handlerattr *attr); +bool upb_handlers_setint32(upb_handlers *h, const upb_fielddef *f, + upb_int32_handlerfunc *func, + const upb_handlerattr *attr); +bool upb_handlers_setint64(upb_handlers *h, const upb_fielddef *f, + upb_int64_handlerfunc *func, + const upb_handlerattr *attr); +bool upb_handlers_setuint32(upb_handlers *h, const upb_fielddef *f, + upb_uint32_handlerfunc *func, + const upb_handlerattr *attr); +bool upb_handlers_setuint64(upb_handlers *h, const upb_fielddef *f, + upb_uint64_handlerfunc *func, + const upb_handlerattr *attr); +bool upb_handlers_setfloat(upb_handlers *h, const upb_fielddef *f, + upb_float_handlerfunc *func, + const upb_handlerattr *attr); +bool upb_handlers_setdouble(upb_handlers *h, const upb_fielddef *f, + upb_double_handlerfunc *func, + const upb_handlerattr *attr); +bool upb_handlers_setbool(upb_handlers *h, const upb_fielddef *f, + upb_bool_handlerfunc *func, + const upb_handlerattr *attr); +bool upb_handlers_setstartstr(upb_handlers *h, const upb_fielddef *f, + upb_startstr_handlerfunc *func, + const upb_handlerattr *attr); +bool upb_handlers_setstring(upb_handlers *h, const upb_fielddef *f, + upb_string_handlerfunc *func, + const upb_handlerattr *attr); +bool upb_handlers_setendstr(upb_handlers *h, const upb_fielddef *f, + upb_endfield_handlerfunc *func, + const upb_handlerattr *attr); +bool upb_handlers_setstartseq(upb_handlers *h, const upb_fielddef *f, + upb_startfield_handlerfunc *func, + const upb_handlerattr *attr); +bool upb_handlers_setstartsubmsg(upb_handlers *h, const upb_fielddef *f, + upb_startfield_handlerfunc *func, + const upb_handlerattr *attr); +bool upb_handlers_setendsubmsg(upb_handlers *h, const upb_fielddef *f, + upb_endfield_handlerfunc *func, + const upb_handlerattr *attr); +bool upb_handlers_setendseq(upb_handlers *h, const upb_fielddef *f, + upb_endfield_handlerfunc *func, + const upb_handlerattr *attr); + +/* Read-only accessors. */ +const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h, + const upb_fielddef *f); +const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h, + upb_selector_t sel); +upb_func *upb_handlers_gethandler(const upb_handlers *h, upb_selector_t s, + const void **handler_data); +bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t s, + upb_handlerattr *attr); + +/* "Static" methods */ +upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f); +bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type, + upb_selector_t *s); +UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) { + return start + 1; +} + +/* Internal-only. */ +uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f); +uint32_t upb_handlers_selectorcount(const upb_fielddef *f); + +UPB_END_EXTERN_C #ifdef __cplusplus +namespace upb { +typedef upb_handlers Handlers; +} + +/* Convenience macros for creating a Handler object that is wrapped with a + * type-safe wrapper function that converts the "void*" parameters/returns + * of the underlying C API into nice C++ function. + * + * Sample usage: + * void OnValue1(MyClosure* c, const MyHandlerData* d, int32_t val) { + * // do stuff ... + * } + * + * // Handler that doesn't need any data bound to it. + * void OnValue2(MyClosure* c, int32_t val) { + * // do stuff ... + * } + * + * // Handler that returns bool so it can return failure if necessary. + * bool OnValue3(MyClosure* c, int32_t val) { + * // do stuff ... + * return ok; + * } + * + * // Member function handler. + * class MyClosure { + * public: + * void OnValue(int32_t val) { + * // do stuff ... + * } + * }; + * + * // Takes ownership of the MyHandlerData. + * handlers->SetInt32Handler(f1, UpbBind(OnValue1, new MyHandlerData(...))); + * handlers->SetInt32Handler(f2, UpbMakeHandler(OnValue2)); + * handlers->SetInt32Handler(f1, UpbMakeHandler(OnValue3)); + * handlers->SetInt32Handler(f2, UpbMakeHandler(&MyClosure::OnValue)); + */ + +/* In C++11, the "template" disambiguator can appear even outside templates, + * so all calls can safely use this pair of macros. */ + +#define UpbMakeHandler(f) upb::MatchFunc(f).template GetFunc() + +/* We have to be careful to only evaluate "d" once. */ +#define UpbBind(f, d) upb::MatchFunc(f).template GetFunc((d)) + +/* Handler: a struct that contains the (handler, data, deleter) tuple that is + * used to register all handlers. Users can Make() these directly but it's + * more convenient to use the UpbMakeHandler/UpbBind macros above. */ +template class upb::Handler { + public: + /* The underlying, handler function signature that upb uses internally. */ + typedef T FuncPtr; + + /* Intentionally implicit. */ + template Handler(F func); + ~Handler() { UPB_ASSERT(registered_); } + + void AddCleanup(upb_handlers* h) const; + FuncPtr handler() const { return handler_; } + const upb_handlerattr& attr() const { return attr_; } + + private: + UPB_DISALLOW_COPY_AND_ASSIGN(Handler) + FuncPtr handler_; + mutable upb_handlerattr attr_; + mutable bool registered_; + void *cleanup_data_; + upb_handlerfree *cleanup_func_; +}; + /* A upb::Handlers object represents the set of handlers associated with a * message in the graph of messages. You can think of it as a big virtual * table with functions corresponding to all the events that can fire while @@ -244,18 +322,23 @@ struct upb_bufhandle { * * The easiest way to create the *Handler objects needed by the Set* methods is * with the UpbBind() and UpbMakeHandler() macros; see below. */ -class upb::Handlers { +class upb::HandlersPtr { public: + HandlersPtr(upb_handlers* ptr) : ptr_(ptr) {} + + upb_handlers* ptr() const { return ptr_; } + typedef upb_selector_t Selector; typedef upb_handlertype_t Type; typedef Handler StartFieldHandler; typedef Handler EndFieldHandler; typedef Handler StartMessageHandler; - typedef Handler EndMessageHandler; + typedef Handler EndMessageHandler; typedef Handler StartStringHandler; typedef Handler StringHandler; + const upb_bufhandle *)> + StringHandler; template struct ValueHandler { typedef Handler H; @@ -275,21 +358,17 @@ class upb::Handlers { typedef void HandlersCallback(const void *closure, upb_handlers *h); - /* All handler registration functions return bool to indicate success or - * failure; details about failures are stored in this status object. If a - * failure does occur, it must be cleared before the Handlers are frozen, - * otherwise the freeze() operation will fail. The functions may *only* be - * used while the Handlers are mutable. */ - const Status* status(); - void ClearError(); - /* Returns the msgdef associated with this handlers object. */ - const MessageDef* message_def() const; + MessageDefPtr message_def() const { + return MessageDefPtr(upb_handlers_msgdef(ptr())); + } /* Adds the given pointer and function to the list of cleanup functions that * will be run when these handlers are freed. If this pointer has previously * been registered, the function returns false and does nothing. */ - bool AddCleanup(void *ptr, upb_handlerfree *cleanup); + bool AddCleanup(void *ptr, upb_handlerfree *cleanup) { + return upb_handlers_addcleanup(ptr_, ptr, cleanup); + } /* Sets the startmsg handler for the message, which is defined as follows: * @@ -299,7 +378,10 @@ class upb::Handlers { * return true; * } */ - bool SetStartMessageHandler(const StartMessageHandler& handler); + bool SetStartMessageHandler(const StartMessageHandler &h) { + h.AddCleanup(ptr()); + return upb_handlers_setstartmsg(ptr(), h.handler(), &h.attr()); + } /* Sets the endmsg handler for the message, which is defined as follows: * @@ -309,7 +391,10 @@ class upb::Handlers { * // can also be modified in-place to update the final status. * } */ - bool SetEndMessageHandler(const EndMessageHandler& handler); + bool SetEndMessageHandler(const EndMessageHandler& h) { + h.AddCleanup(ptr()); + return upb_handlers_setendmsg(ptr(), h.handler(), &h.attr()); + } /* Sets the value handler for the given field, which is defined as follows * (this is for an int32 field; other field types will pass their native @@ -331,13 +416,40 @@ class upb::Handlers { * Returns false if the handler failed to register; in this case the cleanup * handler (if any) will be called immediately. */ - bool SetInt32Handler (const FieldDef* f, const Int32Handler& h); - bool SetInt64Handler (const FieldDef* f, const Int64Handler& h); - bool SetUInt32Handler(const FieldDef* f, const UInt32Handler& h); - bool SetUInt64Handler(const FieldDef* f, const UInt64Handler& h); - bool SetFloatHandler (const FieldDef* f, const FloatHandler& h); - bool SetDoubleHandler(const FieldDef* f, const DoubleHandler& h); - bool SetBoolHandler (const FieldDef* f, const BoolHandler& h); + bool SetInt32Handler(FieldDefPtr f, const Int32Handler &h) { + h.AddCleanup(ptr()); + return upb_handlers_setint32(ptr(), f.ptr(), h.handler(), &h.attr()); + } + + bool SetInt64Handler (FieldDefPtr f, const Int64Handler& h) { + h.AddCleanup(ptr()); + return upb_handlers_setint64(ptr(), f.ptr(), h.handler(), &h.attr()); + } + + bool SetUInt32Handler(FieldDefPtr f, const UInt32Handler& h) { + h.AddCleanup(ptr()); + return upb_handlers_setuint32(ptr(), f.ptr(), h.handler(), &h.attr()); + } + + bool SetUInt64Handler(FieldDefPtr f, const UInt64Handler& h) { + h.AddCleanup(ptr()); + return upb_handlers_setuint64(ptr(), f.ptr(), h.handler(), &h.attr()); + } + + bool SetFloatHandler (FieldDefPtr f, const FloatHandler& h) { + h.AddCleanup(ptr()); + return upb_handlers_setfloat(ptr(), f.ptr(), h.handler(), &h.attr()); + } + + bool SetDoubleHandler(FieldDefPtr f, const DoubleHandler& h) { + h.AddCleanup(ptr()); + return upb_handlers_setdouble(ptr(), f.ptr(), h.handler(), &h.attr()); + } + + bool SetBoolHandler(FieldDefPtr f, const BoolHandler &h) { + h.AddCleanup(ptr()); + return upb_handlers_setbool(ptr(), f.ptr(), h.handler(), &h.attr()); + } /* Like the previous, but templated on the type on the value (ie. int32). * This is mostly useful to call from other templates. To call this you must @@ -345,8 +457,8 @@ class upb::Handlers { * h->SetValueHandler(f, UpbBind(MyHandler, MyData)); */ template bool SetValueHandler( - const FieldDef *f, - const typename ValueHandler::Type>::H& handler); + FieldDefPtr f, + const typename ValueHandler::Type>::H &handler); /* Sets handlers for a string field, which are defined as follows: * @@ -384,9 +496,20 @@ class upb::Handlers { * return true; * } */ - bool SetStartStringHandler(const FieldDef* f, const StartStringHandler& h); - bool SetStringHandler(const FieldDef* f, const StringHandler& h); - bool SetEndStringHandler(const FieldDef* f, const EndFieldHandler& h); + bool SetStartStringHandler(FieldDefPtr f, const StartStringHandler &h) { + h.AddCleanup(ptr()); + return upb_handlers_setstartstr(ptr(), f.ptr(), h.handler(), &h.attr()); + } + + bool SetStringHandler(FieldDefPtr f, const StringHandler& h) { + h.AddCleanup(ptr()); + return upb_handlers_setstring(ptr(), f.ptr(), h.handler(), &h.attr()); + } + + bool SetEndStringHandler(FieldDefPtr f, const EndFieldHandler& h) { + h.AddCleanup(ptr()); + return upb_handlers_setendstr(ptr(), f.ptr(), h.handler(), &h.attr()); + } /* Sets the startseq handler, which is defined as follows: * @@ -402,7 +525,10 @@ class upb::Handlers { * Returns "false" if "f" does not belong to this message or is not a * repeated field. */ - bool SetStartSequenceHandler(const FieldDef* f, const StartFieldHandler& h); + bool SetStartSequenceHandler(FieldDefPtr f, const StartFieldHandler &h) { + h.AddCleanup(ptr()); + return upb_handlers_setstartseq(ptr(), f.ptr(), h.handler(), &h.attr()); + } /* Sets the startsubmsg handler for the given field, which is defined as * follows: @@ -419,7 +545,10 @@ class upb::Handlers { * Returns "false" if "f" does not belong to this message or is not a * submessage/group field. */ - bool SetStartSubMessageHandler(const FieldDef* f, const StartFieldHandler& h); + bool SetStartSubMessageHandler(FieldDefPtr f, const StartFieldHandler& h) { + h.AddCleanup(ptr()); + return upb_handlers_setstartsubmsg(ptr(), f.ptr(), h.handler(), &h.attr()); + } /* Sets the endsubmsg handler for the given field, which is defined as * follows: @@ -432,7 +561,10 @@ class upb::Handlers { * Returns "false" if "f" does not belong to this message or is not a * submessage/group field. */ - bool SetEndSubMessageHandler(const FieldDef *f, const EndFieldHandler &h); + bool SetEndSubMessageHandler(FieldDefPtr f, const EndFieldHandler &h) { + h.AddCleanup(ptr()); + return upb_handlers_setendsubmsg(ptr(), f.ptr(), h.handler(), &h.attr()); + } /* Starts the endsubseq handler for the given field, which is defined as * follows: @@ -445,328 +577,93 @@ class upb::Handlers { * Returns "false" if "f" does not belong to this message or is not a * repeated field. */ - bool SetEndSequenceHandler(const FieldDef* f, const EndFieldHandler& h); - - /* Gets the object that specifies handlers for the given field, which - * must be a submessage or group. Returns NULL if no handlers are set. */ - const Handlers* GetSubHandlers(const FieldDef* f) const; - - /* Equivalent to GetSubHandlers, but takes the STARTSUBMSG selector for the - * field. */ - const Handlers* GetSubHandlers(Selector startsubmsg) const; - - /* A selector refers to a specific field handler in the Handlers object - * (for example: the STARTSUBMSG handler for field "field15"). - * On success, returns true and stores the selector in "s". - * If the FieldDef or Type are invalid, returns false. - * The returned selector is ONLY valid for Handlers whose MessageDef - * contains this FieldDef. */ - static bool GetSelector(const FieldDef* f, Type type, Selector* s); - - /* Given a START selector of any kind, returns the corresponding END selector. */ - static Selector GetEndSelector(Selector start_selector); - - /* Returns the function pointer for this handler. It is the client's - * responsibility to cast to the correct function type before calling it. */ - GenericFunction* GetHandler(Selector selector); - - /* Sets the given attributes to the attributes for this selector. */ - bool GetAttributes(Selector selector, HandlerAttributes* attr); - - /* Returns the handler data that was registered with this handler. */ - const void* GetHandlerData(Selector selector); - - /* Could add any of the following functions as-needed, with some minor - * implementation changes: - * - * const FieldDef* GetFieldDef(Selector selector); - * static bool IsSequence(Selector selector); */ + bool SetEndSequenceHandler(FieldDefPtr f, const EndFieldHandler &h) { + h.AddCleanup(ptr()); + return upb_handlers_setendseq(ptr(), f.ptr(), h.handler(), &h.attr()); + } private: - UPB_DISALLOW_POD_OPS(Handlers, upb::Handlers) - - friend UPB_INLINE GenericFunction *::upb_handlers_gethandler( - const upb_handlers *h, upb_selector_t s); - friend UPB_INLINE const void *::upb_handlers_gethandlerdata( - const upb_handlers *h, upb_selector_t s); -#else -struct upb_handlers { -#endif - upb_handlercache *cache; - const upb_msgdef *msg; - const upb_handlers **sub; - const void *top_closure_type; - upb_handlers_tabent table[1]; /* Dynamically-sized field handler array. */ + upb_handlers* ptr_; }; -#ifdef __cplusplus - -namespace upb { - -/* Convenience macros for creating a Handler object that is wrapped with a - * type-safe wrapper function that converts the "void*" parameters/returns - * of the underlying C API into nice C++ function. - * - * Sample usage: - * void OnValue1(MyClosure* c, const MyHandlerData* d, int32_t val) { - * // do stuff ... - * } - * - * // Handler that doesn't need any data bound to it. - * void OnValue2(MyClosure* c, int32_t val) { - * // do stuff ... - * } - * - * // Handler that returns bool so it can return failure if necessary. - * bool OnValue3(MyClosure* c, int32_t val) { - * // do stuff ... - * return ok; - * } - * - * // Member function handler. - * class MyClosure { - * public: - * void OnValue(int32_t val) { - * // do stuff ... - * } - * }; - * - * // Takes ownership of the MyHandlerData. - * handlers->SetInt32Handler(f1, UpbBind(OnValue1, new MyHandlerData(...))); - * handlers->SetInt32Handler(f2, UpbMakeHandler(OnValue2)); - * handlers->SetInt32Handler(f1, UpbMakeHandler(OnValue3)); - * handlers->SetInt32Handler(f2, UpbMakeHandler(&MyClosure::OnValue)); - */ - -#ifdef UPB_CXX11 - -/* In C++11, the "template" disambiguator can appear even outside templates, - * so all calls can safely use this pair of macros. */ - -#define UpbMakeHandler(f) upb::MatchFunc(f).template GetFunc() - -/* We have to be careful to only evaluate "d" once. */ -#define UpbBind(f, d) upb::MatchFunc(f).template GetFunc((d)) +#endif /* __cplusplus */ -#else +/* upb_handlercache ***********************************************************/ -/* Prior to C++11, the "template" disambiguator may only appear inside a - * template, so the regular macro must not use "template" */ +UPB_BEGIN_EXTERN_C -#define UpbMakeHandler(f) upb::MatchFunc(f).GetFunc() +struct upb_handlercache; +typedef struct upb_handlercache upb_handlercache; -#define UpbBind(f, d) upb::MatchFunc(f).GetFunc((d)) +typedef void upb_handlers_callback(const void *closure, upb_handlers *h); -#endif /* UPB_CXX11 */ +upb_handlercache *upb_handlercache_new(upb_handlers_callback *callback, + const void *closure); +void upb_handlercache_free(upb_handlercache *cache); +const upb_handlers *upb_handlercache_get(upb_handlercache *cache, + const upb_msgdef *md); -/* This macro must be used in C++98 for calls from inside a template. But we - * define this variant in all cases; code that wants to be compatible with both - * C++98 and C++11 should always use this macro when calling from a template. */ -#define UpbMakeHandlerT(f) upb::MatchFunc(f).template GetFunc() +UPB_END_EXTERN_C -/* We have to be careful to only evaluate "d" once. */ -#define UpbBindT(f, d) upb::MatchFunc(f).template GetFunc((d)) +#ifdef __cplusplus -/* Handler: a struct that contains the (handler, data, deleter) tuple that is - * used to register all handlers. Users can Make() these directly but it's - * more convenient to use the UpbMakeHandler/UpbBind macros above. */ -template class Handler { +class upb::HandlerCache { public: - /* The underlying, handler function signature that upb uses internally. */ - typedef T FuncPtr; + HandlerCache(upb_handlers_callback *callback, const void *closure) + : ptr_(upb_handlercache_new(callback, closure), upb_handlercache_free) {} + HandlerCache(HandlerCache&&) = default; + HandlerCache& operator=(HandlerCache&&) = default; + HandlerCache(upb_handlercache* c) : ptr_(c, upb_handlercache_free) {} - /* Intentionally implicit. */ - template Handler(F func); - ~Handler(); + upb_handlercache* ptr() { return ptr_.get(); } - private: - void AddCleanup(Handlers* h) const { - if (cleanup_func_) { - bool ok = h->AddCleanup(cleanup_data_, cleanup_func_); - UPB_ASSERT(ok); - } + const upb_handlers *Get(MessageDefPtr md) { + return upb_handlercache_get(ptr_.get(), md.ptr()); } - UPB_DISALLOW_COPY_AND_ASSIGN(Handler) - friend class Handlers; - FuncPtr handler_; - mutable HandlerAttributes attr_; - mutable bool registered_; - void *cleanup_data_; - upb_handlerfree *cleanup_func_; + private: + std::unique_ptr ptr_; }; -} /* namespace upb */ - #endif /* __cplusplus */ -UPB_BEGIN_EXTERN_C - -/* Native C API. */ +/* upb_byteshandler ***********************************************************/ -/* Handler function typedefs. */ -typedef bool upb_unknown_handlerfunc(void *c, const void *hd, const char *buf, - size_t n); -typedef bool upb_startmsg_handlerfunc(void *c, const void*); -typedef bool upb_endmsg_handlerfunc(void *c, const void *, upb_status *status); -typedef void* upb_startfield_handlerfunc(void *c, const void *hd); -typedef bool upb_endfield_handlerfunc(void *c, const void *hd); -typedef bool upb_int32_handlerfunc(void *c, const void *hd, int32_t val); -typedef bool upb_int64_handlerfunc(void *c, const void *hd, int64_t val); -typedef bool upb_uint32_handlerfunc(void *c, const void *hd, uint32_t val); -typedef bool upb_uint64_handlerfunc(void *c, const void *hd, uint64_t val); -typedef bool upb_float_handlerfunc(void *c, const void *hd, float val); -typedef bool upb_double_handlerfunc(void *c, const void *hd, double val); -typedef bool upb_bool_handlerfunc(void *c, const void *hd, bool val); -typedef void *upb_startstr_handlerfunc(void *c, const void *hd, - size_t size_hint); -typedef size_t upb_string_handlerfunc(void *c, const void *hd, const char *buf, - size_t n, const upb_bufhandle* handle); - -/* upb_bufhandle */ -size_t upb_bufhandle_objofs(const upb_bufhandle *h); - -/* upb_handlerattr */ -void upb_handlerattr_init(upb_handlerattr *attr); -void upb_handlerattr_uninit(upb_handlerattr *attr); - -bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, const void *hd); -bool upb_handlerattr_setclosuretype(upb_handlerattr *attr, const void *type); -const void *upb_handlerattr_closuretype(const upb_handlerattr *attr); -bool upb_handlerattr_setreturnclosuretype(upb_handlerattr *attr, - const void *type); -const void *upb_handlerattr_returnclosuretype(const upb_handlerattr *attr); -bool upb_handlerattr_setalwaysok(upb_handlerattr *attr, bool alwaysok); -bool upb_handlerattr_alwaysok(const upb_handlerattr *attr); - -UPB_INLINE const void *upb_handlerattr_handlerdata( - const upb_handlerattr *attr) { - return attr->handler_data_; -} +UPB_BEGIN_EXTERN_C -/* upb_handlers */ -const upb_status *upb_handlers_status(upb_handlers *h); -void upb_handlers_clearerr(upb_handlers *h); -const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h); -bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *hfree); -bool upb_handlers_setunknown(upb_handlers *h, upb_unknown_handlerfunc *func, - upb_handlerattr *attr); +typedef struct { + upb_func *func; -bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setendmsg(upb_handlers *h, upb_endmsg_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setint32(upb_handlers *h, const upb_fielddef *f, - upb_int32_handlerfunc *func, upb_handlerattr *attr); -bool upb_handlers_setint64(upb_handlers *h, const upb_fielddef *f, - upb_int64_handlerfunc *func, upb_handlerattr *attr); -bool upb_handlers_setuint32(upb_handlers *h, const upb_fielddef *f, - upb_uint32_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setuint64(upb_handlers *h, const upb_fielddef *f, - upb_uint64_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setfloat(upb_handlers *h, const upb_fielddef *f, - upb_float_handlerfunc *func, upb_handlerattr *attr); -bool upb_handlers_setdouble(upb_handlers *h, const upb_fielddef *f, - upb_double_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setbool(upb_handlers *h, const upb_fielddef *f, - upb_bool_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setstartstr(upb_handlers *h, const upb_fielddef *f, - upb_startstr_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setstring(upb_handlers *h, const upb_fielddef *f, - upb_string_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setendstr(upb_handlers *h, const upb_fielddef *f, - upb_endfield_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setstartseq(upb_handlers *h, const upb_fielddef *f, - upb_startfield_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setstartsubmsg(upb_handlers *h, const upb_fielddef *f, - upb_startfield_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setendsubmsg(upb_handlers *h, const upb_fielddef *f, - upb_endfield_handlerfunc *func, - upb_handlerattr *attr); -bool upb_handlers_setendseq(upb_handlers *h, const upb_fielddef *f, - upb_endfield_handlerfunc *func, - upb_handlerattr *attr); + /* It is wasteful to include the entire attributes here: + * + * * Some of the information is redundant (like storing the closure type + * separately for each handler that must match). + * * Some of the info is only needed prior to freeze() (like closure types). + * * alignment padding wastes a lot of space for alwaysok_. + * + * If/when the size and locality of handlers is an issue, we can optimize this + * not to store the entire attr like this. We do not expose the table's + * layout to allow this optimization in the future. */ + upb_handlerattr attr; +} upb_handlers_tabent; -const upb_handlers *upb_handlers_getsubhandlers(const upb_handlers *h, - const upb_fielddef *f); -const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h, - upb_selector_t sel); +#define UPB_TABENT_INIT {NULL, UPB_HANDLERATTR_INIT} -UPB_INLINE upb_func *upb_handlers_gethandler(const upb_handlers *h, - upb_selector_t s) { - return (upb_func *)h->table[s].func; -} +typedef struct { + upb_handlers_tabent table[3]; +} upb_byteshandler; -bool upb_handlers_getattr(const upb_handlers *h, upb_selector_t s, - upb_handlerattr *attr); +#define UPB_BYTESHANDLER_INIT \ + { \ + { UPB_TABENT_INIT, UPB_TABENT_INIT, UPB_TABENT_INIT } \ + } -UPB_INLINE const void *upb_handlers_gethandlerdata(const upb_handlers *h, - upb_selector_t s) { - return upb_handlerattr_handlerdata(&h->table[s].attr); +UPB_INLINE void upb_byteshandler_init(upb_byteshandler *handler) { + upb_byteshandler init = UPB_BYTESHANDLER_INIT; + *handler = init; } -typedef void upb_handlers_callback(const void *closure, upb_handlers *h); - -#ifdef __cplusplus - -class upb::HandlerCache { - public: - static HandlerCache *New(upb_handlers_callback *callback, - const void *closure); - static void Free(HandlerCache* cache); - - const Handlers* Get(const MessageDef* md); - - private: - UPB_DISALLOW_POD_OPS(HandlerCache, upb::pb::HandlerCache) -#else -struct upb_handlercache { -#endif - upb_arena arena; - upb_inttable tab; /* maps upb_msgdef* -> upb_handlers*. */ - upb_inttable cleanup_; - upb_handlers_callback *callback; - const void *closure; -}; - -upb_handlercache *upb_handlercache_new(upb_handlers_callback *callback, - const void *closure); -void upb_handlercache_free(upb_handlercache *cache); -const upb_handlers *upb_handlercache_get(upb_handlercache *cache, - const upb_msgdef *md); - -#ifdef __cplusplus - -/* Handler types for single fields. - * Right now we only have one for TYPE_BYTES but ones for other types - * should follow. - * - * These follow the same handlers protocol for fields of a message. */ -class upb::BytesHandler { - public: - BytesHandler(); - ~BytesHandler(); -#else -struct upb_byteshandler { -#endif - upb_handlers_tabent table[3]; -}; - -void upb_byteshandler_init(upb_byteshandler *h); - -/* Caller must ensure that "d" outlives the handlers. - * TODO(haberman): should this have a "freeze" operation? It's not necessary - * for memory management, but could be useful to force immutability and provide - * a convenient moment to verify that all registration succeeded. */ +/* Caller must ensure that "d" outlives the handlers. */ bool upb_byteshandler_setstartstr(upb_byteshandler *h, upb_startstr_handlerfunc *func, void *d); bool upb_byteshandler_setstring(upb_byteshandler *h, @@ -774,21 +671,18 @@ bool upb_byteshandler_setstring(upb_byteshandler *h, bool upb_byteshandler_setendstr(upb_byteshandler *h, upb_endfield_handlerfunc *func, void *d); -/* "Static" methods */ -upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f); -bool upb_handlers_getselector(const upb_fielddef *f, upb_handlertype_t type, - upb_selector_t *s); -UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) { - return start + 1; +#ifdef __cplusplus +namespace upb { +typedef upb_byteshandler BytesHandler; } +#endif -/* Internal-only. */ -uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f); -uint32_t upb_handlers_selectorcount(const upb_fielddef *f); - +UPB_END_EXTERN_C /** Message handlers ******************************************************************/ +UPB_BEGIN_EXTERN_C + /* These are the handlers used internally by upb_msgfactory_getmergehandlers(). * They write scalar data to a known offset from the message pointer. * diff --git a/upb/json/printer.c b/upb/json/printer.c index 444916f..b2c9ebd 100644 --- a/upb/json/printer.c +++ b/upb/json/printer.c @@ -601,7 +601,7 @@ static void set_enum_hd(upb_handlers *h, hd->enumdef = upb_fielddef_enumsubdef(f); hd->keyname = newstrpc(h, f, preserve_fieldnames); upb_handlers_addcleanup(h, hd, upb_gfree); - upb_handlerattr_sethandlerdata(attr, hd); + attr->handler_data = hd; } /* Set up handlers for a mapentry submessage (i.e., an individual key/value pair @@ -626,7 +626,7 @@ void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames, const upb_fielddef* key_field = upb_msgdef_itof(md, UPB_MAPENTRY_KEY); const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_MAPENTRY_VALUE); - upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT; UPB_UNUSED(closure); @@ -690,10 +690,9 @@ void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames, upb_handlers_setstring(h, value_field, putbytes, &empty_attr); break; case UPB_TYPE_ENUM: { - upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlerattr enum_attr = UPB_HANDLERATTR_INIT; set_enum_hd(h, value_field, preserve_fieldnames, &enum_attr); upb_handlers_setint32(h, value_field, mapvalue_enum, &enum_attr); - upb_handlerattr_uninit(&enum_attr); break; } case UPB_TYPE_MESSAGE: @@ -701,8 +700,6 @@ void printer_sethandlers_mapentry(const void *closure, bool preserve_fieldnames, * as appropriate. */ break; } - - upb_handlerattr_uninit(&empty_attr); } static bool putseconds(void *closure, const void *handler_data, @@ -948,16 +945,16 @@ void printer_sethandlers_any(const void *closure, upb_handlers *h) { const upb_fielddef* type_field = upb_msgdef_itof(md, UPB_ANY_TYPE); const upb_fielddef* value_field = upb_msgdef_itof(md, UPB_ANY_VALUE); - upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT; /* type_url's json name is "@type" */ - upb_handlerattr type_name_attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr value_name_attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlerattr type_name_attr = UPB_HANDLERATTR_INIT; + upb_handlerattr value_name_attr = UPB_HANDLERATTR_INIT; strpc *type_url_json_name = newstrpc_str(h, "@type"); strpc *value_json_name = newstrpc_str(h, "value"); - upb_handlerattr_sethandlerdata(&type_name_attr, type_url_json_name); - upb_handlerattr_sethandlerdata(&value_name_attr, value_json_name); + type_name_attr.handler_data = type_url_json_name; + value_name_attr.handler_data = value_json_name; /* Set up handlers. */ upb_handlers_setstartmsg(h, printer_startmsg, &empty_attr); @@ -985,7 +982,7 @@ void printer_sethandlers_duration(const void *closure, upb_handlers *h) { const upb_fielddef* nanos_field = upb_msgdef_itof(md, UPB_DURATION_NANOS); - upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT; upb_handlers_setstartmsg(h, printer_startdurationmsg, &empty_attr); upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr); @@ -1005,7 +1002,7 @@ void printer_sethandlers_timestamp(const void *closure, upb_handlers *h) { const upb_fielddef* nanos_field = upb_msgdef_itof(md, UPB_TIMESTAMP_NANOS); - upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT; upb_handlers_setstartmsg(h, printer_starttimestampmsg, &empty_attr); upb_handlers_setint64(h, seconds_field, putseconds, &empty_attr); @@ -1019,7 +1016,7 @@ void printer_sethandlers_value(const void *closure, upb_handlers *h) { const upb_msgdef *md = upb_handlers_msgdef(h); upb_msg_field_iter i; - upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT; upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr); upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr); @@ -1058,7 +1055,7 @@ void printer_sethandlers_value(const void *closure, upb_handlers *h) { void printer_sethandlers_##wrapper(const void *closure, upb_handlers *h) { \ const upb_msgdef *md = upb_handlers_msgdef(h); \ const upb_fielddef* f = upb_msgdef_itof(md, 1); \ - upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; \ + upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT; \ upb_handlers_setstartmsg(h, printer_startmsg_noframe, &empty_attr); \ upb_handlers_setendmsg(h, printer_endmsg_noframe, &empty_attr); \ upb_handlers_set##type(h, f, putmethod, &empty_attr); \ @@ -1081,7 +1078,7 @@ void printer_sethandlers_listvalue(const void *closure, upb_handlers *h) { const upb_msgdef *md = upb_handlers_msgdef(h); const upb_fielddef* f = upb_msgdef_itof(md, 1); - upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT; upb_handlers_setstartseq(h, f, startseq_nokey, &empty_attr); upb_handlers_setendseq(h, f, endseq, &empty_attr); @@ -1098,7 +1095,7 @@ void printer_sethandlers_structvalue(const void *closure, upb_handlers *h) { const upb_msgdef *md = upb_handlers_msgdef(h); const upb_fielddef* f = upb_msgdef_itof(md, 1); - upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT; upb_handlers_setstartseq(h, f, startmap_nokey, &empty_attr); upb_handlers_setendseq(h, f, endmap, &empty_attr); @@ -1114,7 +1111,7 @@ void printer_sethandlers_structvalue(const void *closure, upb_handlers *h) { void printer_sethandlers(const void *closure, upb_handlers *h) { const upb_msgdef *md = upb_handlers_msgdef(h); bool is_mapentry = upb_msgdef_mapentry(md); - upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT; upb_msg_field_iter i; const upb_json_printercache *cache = closure; const bool preserve_fieldnames = cache->preserve_fieldnames; @@ -1181,9 +1178,8 @@ void printer_sethandlers(const void *closure, upb_handlers *h) { for(; !upb_msg_field_done(&i); upb_msg_field_next(&i)) { const upb_fielddef *f = upb_msg_iter_field(&i); - upb_handlerattr name_attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&name_attr, - newstrpc(h, f, preserve_fieldnames)); + upb_handlerattr name_attr = UPB_HANDLERATTR_INIT; + name_attr.handler_data = newstrpc(h, f, preserve_fieldnames); if (upb_fielddef_ismap(f)) { upb_handlers_setstartseq(h, f, startmap, &name_attr); @@ -1205,7 +1201,7 @@ void printer_sethandlers(const void *closure, upb_handlers *h) { /* For now, we always emit symbolic names for enums. We may want an * option later to control this behavior, but we will wait for a real * need first. */ - upb_handlerattr enum_attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlerattr enum_attr = UPB_HANDLERATTR_INIT; set_enum_hd(h, f, preserve_fieldnames, &enum_attr); if (upb_fielddef_isseq(f)) { @@ -1214,7 +1210,6 @@ void printer_sethandlers(const void *closure, upb_handlers *h) { upb_handlers_setint32(h, f, scalar_enum, &enum_attr); } - upb_handlerattr_uninit(&enum_attr); break; } case UPB_TYPE_STRING: @@ -1245,11 +1240,8 @@ void printer_sethandlers(const void *closure, upb_handlers *h) { } break; } - - upb_handlerattr_uninit(&name_attr); } - upb_handlerattr_uninit(&empty_attr); #undef TYPE } diff --git a/upb/pb/compile_decoder.c b/upb/pb/compile_decoder.c index 02f5179..e17ca03 100644 --- a/upb/pb/compile_decoder.c +++ b/upb/pb/compile_decoder.c @@ -516,7 +516,7 @@ static upb_pbdecodermethod *find_submethod(const compiler *c, static void putsel(compiler *c, opcode op, upb_selector_t sel, const upb_handlers *h) { - if (upb_handlers_gethandler(h, sel)) { + if (upb_handlers_gethandler(h, sel, NULL)) { putop(c, op, sel); } } @@ -532,9 +532,9 @@ static bool haslazyhandlers(const upb_handlers *h, const upb_fielddef *f) { if (!upb_fielddef_lazy(f)) return false; - return upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STARTSTR)) || - upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STRING)) || - upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_ENDSTR)); + return upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STARTSTR), NULL) || + upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_STRING), NULL) || + upb_handlers_gethandler(h, getsel(f, UPB_HANDLER_ENDSTR), NULL); } diff --git a/upb/pb/decoder.h b/upb/pb/decoder.h index 1a00801..1ffcb7d 100644 --- a/upb/pb/decoder.h +++ b/upb/pb/decoder.h @@ -21,17 +21,13 @@ namespace upb { namespace pb { class CodeCache; -class Decoder; -class DecoderMethod; +class DecoderPtr; +class DecoderMethodPtr; class DecoderMethodOptions; } /* namespace pb */ } /* namespace upb */ #endif -UPB_DECLARE_TYPE(upb::pb::CodeCache, upb_pbcodecache) -UPB_DECLARE_TYPE(upb::pb::Decoder, upb_pbdecoder) -UPB_DECLARE_TYPE(upb::pb::DecoderMethod, upb_pbdecodermethod) - /* The maximum number of bytes we are required to buffer internally between * calls to the decoder. The value is 14: a 5 byte unknown tag plus ten-byte * varint, less one because we are buffering an incomplete value. @@ -39,54 +35,106 @@ UPB_DECLARE_TYPE(upb::pb::DecoderMethod, upb_pbdecodermethod) * Should only be used by unit tests. */ #define UPB_DECODER_MAX_RESIDUAL_BYTES 14 +/* upb_pbdecodermethod ********************************************************/ + +struct upb_pbdecodermethod; +typedef struct upb_pbdecodermethod upb_pbdecodermethod; + +UPB_BEGIN_EXTERN_C + +const upb_handlers *upb_pbdecodermethod_desthandlers( + const upb_pbdecodermethod *m); +const upb_byteshandler *upb_pbdecodermethod_inputhandler( + const upb_pbdecodermethod *m); +bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m); + +UPB_END_EXTERN_C + #ifdef __cplusplus /* Represents the code to parse a protobuf according to a destination * Handlers. */ -class upb::pb::DecoderMethod { +class upb::pb::DecoderMethodPtr { public: + DecoderMethodPtr(const upb_pbdecodermethod* ptr) : ptr_(ptr) {} + + const upb_pbdecodermethod* ptr() { return ptr_; } + /* The destination handlers that are statically bound to this method. * This method is only capable of outputting to a sink that uses these * handlers. */ - const Handlers* dest_handlers() const; + const Handlers *dest_handlers() const { + return upb_pbdecodermethod_desthandlers(ptr_); + } /* The input handlers for this decoder method. */ - const BytesHandler* input_handler() const; + const BytesHandler* input_handler() const { + return upb_pbdecodermethod_inputhandler(ptr_); + } /* Whether this method is native. */ - bool is_native() const; + bool is_native() const { + return upb_pbdecodermethod_isnative(ptr_); + } private: - UPB_DISALLOW_POD_OPS(DecoderMethod, upb::pb::DecoderMethod) + const upb_pbdecodermethod* ptr_; }; #endif +/* upb_pbdecoder **************************************************************/ + /* Preallocation hint: decoder won't allocate more bytes than this when first * constructed. This hint may be an overestimate for some build configurations. * But if the decoder library is upgraded without recompiling the application, * it may be an underestimate. */ #define UPB_PB_DECODER_SIZE 4416 +struct upb_pbdecoder; +typedef struct upb_pbdecoder upb_pbdecoder; + +UPB_BEGIN_EXTERN_C + +upb_pbdecoder *upb_pbdecoder_create(upb_env *e, + const upb_pbdecodermethod *method, + upb_sink *output); +const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d); +upb_bytessink *upb_pbdecoder_input(upb_pbdecoder *d); +uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d); +size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d); +bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max); +void upb_pbdecoder_reset(upb_pbdecoder *d); + +UPB_END_EXTERN_C + #ifdef __cplusplus /* A Decoder receives binary protobuf data on its input sink and pushes the * decoded data to its output sink. */ -class upb::pb::Decoder { +class upb::pb::DecoderPtr { public: + DecoderPtr(upb_pbdecoder* ptr) : ptr_(ptr) {} + + upb_pbdecoder* ptr() { return ptr_; } + /* Constructs a decoder instance for the given method, which must outlive this * decoder. Any errors during parsing will be set on the given status, which * must also outlive this decoder. * * The sink must match the given method. */ - static Decoder* Create(Environment* env, const DecoderMethod* method, - Sink* output); + static DecoderPtr Create(Environment *env, DecoderMethodPtr method, + upb_sink *output) { + return DecoderPtr(upb_pbdecoder_create(env, method.ptr(), output)); + } /* Returns the DecoderMethod this decoder is parsing from. */ - const DecoderMethod* method() const; + const DecoderMethodPtr method() const { + return DecoderMethodPtr(upb_pbdecoder_method(ptr_)); + } /* The sink on which this decoder receives input. */ - BytesSink* input(); + upb_bytessink* input() { return upb_pbdecoder_input(ptr()); } /* Returns number of bytes successfully parsed. * @@ -95,7 +143,7 @@ class upb::pb::Decoder { * * This value may not be up-to-date when called from inside a parsing * callback. */ - uint64_t BytesParsed() const; + uint64_t BytesParsed() { return upb_pbdecoder_bytesparsed(ptr()); } /* Gets/sets the parsing nexting limit. If the total number of nested * submessages and repeated fields hits this limit, parsing will fail. This @@ -104,25 +152,51 @@ class upb::pb::Decoder { * * Setting the limit will fail if the parser is currently suspended at a depth * greater than this, or if memory allocation of the stack fails. */ - size_t max_nesting() const; - bool set_max_nesting(size_t max); + size_t max_nesting() { return upb_pbdecoder_maxnesting(ptr()); } + bool set_max_nesting(size_t max) { return upb_pbdecoder_maxnesting(ptr()); } - void Reset(); + void Reset() { upb_pbdecoder_reset(ptr()); } static const size_t kSize = UPB_PB_DECODER_SIZE; private: - UPB_DISALLOW_POD_OPS(Decoder, upb::pb::Decoder) + upb_pbdecoder *ptr_; }; +#endif /* __cplusplus */ + +/* upb_pbcodecache ************************************************************/ + +struct upb_pbcodecache; +typedef struct upb_pbcodecache upb_pbcodecache; + +UPB_BEGIN_EXTERN_C + +upb_pbcodecache *upb_pbcodecache_new(upb_handlercache *dest); +void upb_pbcodecache_free(upb_pbcodecache *c); +bool upb_pbcodecache_allowjit(const upb_pbcodecache *c); +void upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow); +void upb_pbcodecache_setlazy(upb_pbcodecache *c, bool lazy); +const upb_pbdecodermethod *upb_pbcodecache_get(upb_pbcodecache *c, + const upb_msgdef *md); + +UPB_END_EXTERN_C + +#ifdef __cplusplus + /* A class for caching protobuf processing code, whether bytecode for the * interpreted decoder or machine code for the JIT. * * This class is not thread-safe. */ class upb::pb::CodeCache { public: - static CodeCache* New(HandlerCache* dest); - static void Free(CodeCache* cache); + CodeCache(upb::HandlerCache *dest) + : ptr_(upb_pbcodecache_new(dest->ptr()), upb_pbcodecache_free) {} + CodeCache(CodeCache&&) = default; + CodeCache& operator=(CodeCache&&) = default; + + upb_pbcodecache* ptr() { return ptr_.get(); } + const upb_pbcodecache* ptr() const { return ptr_.get(); } /* Whether the cache is allowed to generate machine code. Defaults to true. * There is no real reason to turn it off except for testing or if you are @@ -131,114 +205,27 @@ class upb::pb::CodeCache { * Note that allow_jit = true does not *guarantee* that the code will be JIT * compiled. If this platform is not supported or the JIT was not compiled * in, the code may still be interpreted. */ - bool allow_jit() const; + bool allow_jit() const { return upb_pbcodecache_allowjit(ptr()); } /* This may only be called when the object is first constructed, and prior to * any code generation. */ - void set_allow_jit(bool allow); + void set_allow_jit(bool allow) { upb_pbcodecache_setallowjit(ptr(), allow); } /* Should the decoder push submessages to lazy handlers for fields that have * them? The caller should set this iff the lazy handlers expect data that is * in protobuf binary format and the caller wishes to lazy parse it. */ - void set_lazy(bool lazy); + void set_lazy(bool lazy) { upb_pbcodecache_setlazy(ptr(), lazy); } /* Returns a DecoderMethod that can push data to the given handlers. * If a suitable method already exists, it will be returned from the cache. */ - const DecoderMethod *Get(const MessageDef* md); + const DecoderMethodPtr Get(MessageDefPtr md) { + return DecoderMethodPtr(upb_pbcodecache_get(ptr(), md.ptr())); + } private: - UPB_DISALLOW_POD_OPS(CodeCache, upb::pb::CodeCache) + std::unique_ptr ptr_; }; -#endif - -UPB_BEGIN_EXTERN_C - -upb_pbdecoder *upb_pbdecoder_create(upb_env *e, - const upb_pbdecodermethod *method, - upb_sink *output); -const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d); -upb_bytessink *upb_pbdecoder_input(upb_pbdecoder *d); -uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d); -size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d); -bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max); -void upb_pbdecoder_reset(upb_pbdecoder *d); - - - -const upb_handlers *upb_pbdecodermethod_desthandlers( - const upb_pbdecodermethod *m); -const upb_byteshandler *upb_pbdecodermethod_inputhandler( - const upb_pbdecodermethod *m); -bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m); - -upb_pbcodecache *upb_pbcodecache_new(upb_handlercache *dest); -void upb_pbcodecache_free(upb_pbcodecache *c); -bool upb_pbcodecache_allowjit(const upb_pbcodecache *c); -void upb_pbcodecache_setallowjit(upb_pbcodecache *c, bool allow); -void upb_pbcodecache_setlazy(upb_pbcodecache *c, bool lazy); -const upb_pbdecodermethod *upb_pbcodecache_get(upb_pbcodecache *c, - const upb_msgdef *md); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upb { - -namespace pb { - -/* static */ -inline Decoder* Decoder::Create(Environment* env, const DecoderMethod* m, - Sink* sink) { - return upb_pbdecoder_create(env, m, sink); -} -inline const DecoderMethod* Decoder::method() const { - return upb_pbdecoder_method(this); -} -inline BytesSink* Decoder::input() { - return upb_pbdecoder_input(this); -} -inline uint64_t Decoder::BytesParsed() const { - return upb_pbdecoder_bytesparsed(this); -} -inline size_t Decoder::max_nesting() const { - return upb_pbdecoder_maxnesting(this); -} -inline bool Decoder::set_max_nesting(size_t max) { - return upb_pbdecoder_setmaxnesting(this, max); -} -inline void Decoder::Reset() { upb_pbdecoder_reset(this); } - -inline const Handlers* DecoderMethod::dest_handlers() const { - return upb_pbdecodermethod_desthandlers(this); -} -inline const BytesHandler* DecoderMethod::input_handler() const { - return upb_pbdecodermethod_inputhandler(this); -} -inline bool DecoderMethod::is_native() const { - return upb_pbdecodermethod_isnative(this); -} - -inline CodeCache* CodeCache::New(HandlerCache* dest) { - return upb_pbcodecache_new(dest); -} -inline void CodeCache::Free(CodeCache* cache) { - upb_pbcodecache_free(cache); -} -inline bool CodeCache::allow_jit() const { - return upb_pbcodecache_allowjit(this); -} -inline void CodeCache::set_allow_jit(bool allow) { - upb_pbcodecache_setallowjit(this, allow); -} -inline const DecoderMethod *CodeCache::Get(const MessageDef *md) { - return upb_pbcodecache_get(this, md); -} - -} /* namespace pb */ -} /* namespace upb */ - #endif /* __cplusplus */ #endif /* UPB_DECODER_H_ */ diff --git a/upb/pb/encoder.c b/upb/pb/encoder.c index ca3ca5c..3497007 100644 --- a/upb/pb/encoder.c +++ b/upb/pb/encoder.c @@ -304,8 +304,7 @@ static void new_tag(upb_handlers *h, const upb_fielddef *f, upb_wiretype_t wt, tag_t *tag = upb_gmalloc(sizeof(tag_t)); tag->bytes = upb_vencode64((n << 3) | wt, tag->tag); - upb_handlerattr_init(attr); - upb_handlerattr_sethandlerdata(attr, tag); + attr->handler_data = tag; upb_handlers_addcleanup(h, tag, upb_gfree); } @@ -451,7 +450,7 @@ static void newhandlers_callback(const void *closure, upb_handlers *h) { const upb_fielddef *f = upb_msg_iter_field(&i); bool packed = upb_fielddef_isseq(f) && upb_fielddef_isprimitive(f) && upb_fielddef_packed(f); - upb_handlerattr attr; + upb_handlerattr attr = UPB_HANDLERATTR_INIT; upb_wiretype_t wt = packed ? UPB_WIRE_TYPE_DELIMITED : upb_pb_native_wire_types[upb_fielddef_descriptortype(f)]; @@ -500,20 +499,17 @@ static void newhandlers_callback(const void *closure, upb_handlers *h) { break; case UPB_DESCRIPTOR_TYPE_GROUP: { /* Endgroup takes a different tag (wire_type = END_GROUP). */ - upb_handlerattr attr2; + upb_handlerattr attr2 = UPB_HANDLERATTR_INIT; new_tag(h, f, UPB_WIRE_TYPE_END_GROUP, &attr2); upb_handlers_setstartsubmsg(h, f, encode_startgroup, &attr); upb_handlers_setendsubmsg(h, f, encode_endgroup, &attr2); - upb_handlerattr_uninit(&attr2); break; } } #undef T - - upb_handlerattr_uninit(&attr); } } diff --git a/upb/pb/encoder.h b/upb/pb/encoder.h index eefa385..20ce606 100644 --- a/upb/pb/encoder.h +++ b/upb/pb/encoder.h @@ -17,16 +17,14 @@ #ifdef __cplusplus namespace upb { namespace pb { -class Encoder; +class EncoderPtr; } /* namespace pb */ } /* namespace upb */ #endif -UPB_DECLARE_TYPE(upb::pb::Encoder, upb_pb_encoder) - #define UPB_PBENCODER_MAX_NESTING 100 -/* upb::pb::Encoder ***********************************************************/ +/* upb_pb_encoder *************************************************************/ /* Preallocation hint: decoder won't allocate more bytes than this when first * constructed. This hint may be an overestimate for some build configurations. @@ -34,56 +32,48 @@ UPB_DECLARE_TYPE(upb::pb::Encoder, upb_pb_encoder) * it may be an underestimate. */ #define UPB_PB_ENCODER_SIZE 768 +struct upb_pb_encoder; +typedef struct upb_pb_encoder upb_pb_encoder; + +UPB_BEGIN_EXTERN_C + +upb_sink *upb_pb_encoder_input(upb_pb_encoder *p); +upb_pb_encoder* upb_pb_encoder_create(upb_env* e, const upb_handlers* h, + upb_bytessink* output); + +upb_handlercache *upb_pb_encoder_newcache(); + +UPB_END_EXTERN_C + #ifdef __cplusplus -class upb::pb::Encoder { +class upb::pb::EncoderPtr { public: + EncoderPtr(upb_pb_encoder* ptr) : ptr_(ptr) {} + + upb_pb_encoder* ptr() { return ptr_; } + /* Creates a new encoder in the given environment. The Handlers must have * come from NewHandlers() below. */ - static Encoder* Create(Environment* env, const Handlers* handlers, - BytesSink* output); + static EncoderPtr Create(Environment* env, const Handlers* handlers, + BytesSink* output) { + return EncoderPtr(upb_pb_encoder_create(env, handlers, output->ptr())); + } /* The input to the encoder. */ - Sink* input(); + upb_sink* input() { return upb_pb_encoder_input(ptr()); } /* Creates a new set of handlers for this MessageDef. */ - static upb_handlercache* NewCache(); + static HandlerCache NewCache() { + return HandlerCache(upb_pb_encoder_newcache()); + } static const size_t kSize = UPB_PB_ENCODER_SIZE; private: - UPB_DISALLOW_POD_OPS(Encoder, upb::pb::Encoder) + upb_pb_encoder* ptr_; }; -#endif - -UPB_BEGIN_EXTERN_C - -upb_sink *upb_pb_encoder_input(upb_pb_encoder *p); -upb_pb_encoder* upb_pb_encoder_create(upb_env* e, const upb_handlers* h, - upb_bytessink* output); - -upb_handlercache *upb_pb_encoder_newcache(); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upb { -namespace pb { -inline Encoder* Encoder::Create(Environment* env, const Handlers* handlers, - BytesSink* output) { - return upb_pb_encoder_create(env, handlers, output); -} -inline Sink* Encoder::input() { - return upb_pb_encoder_input(this); -} -inline upb_handlercache* Encoder::NewCache() { - return upb_pb_encoder_newcache(); -} -} /* namespace pb */ -} /* namespace upb */ - -#endif +#endif /* __cplusplus */ #endif /* UPB_ENCODER_H_ */ diff --git a/upb/pb/textprinter.c b/upb/pb/textprinter.c index b6f8024..d1d539d 100644 --- a/upb/pb/textprinter.c +++ b/upb/pb/textprinter.c @@ -260,8 +260,8 @@ static void onmreg(const void *c, upb_handlers *h) { !upb_msg_field_done(&i); upb_msg_field_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); - upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&attr, f); + upb_handlerattr attr = UPB_HANDLERATTR_INIT; + attr.handler_data = f; switch (upb_fielddef_type(f)) { case UPB_TYPE_INT32: upb_handlers_setint32(h, f, textprinter_putint32, &attr); @@ -295,7 +295,7 @@ static void onmreg(const void *c, upb_handlers *h) { upb_fielddef_descriptortype(f) == UPB_DESCRIPTOR_TYPE_GROUP ? shortname(upb_msgdef_fullname(upb_fielddef_msgsubdef(f))) : upb_fielddef_name(f); - upb_handlerattr_sethandlerdata(&attr, name); + attr.handler_data = name; upb_handlers_setstartsubmsg(h, f, textprinter_startsubmsg, &attr); upb_handlers_setendsubmsg(h, f, textprinter_endsubmsg, &attr); break; diff --git a/upb/sink.c b/upb/sink.c index e6ede49..d0197a6 100644 --- a/upb/sink.c +++ b/upb/sink.c @@ -4,9 +4,8 @@ bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink *sink) { void *subc; bool ret; - upb_bufhandle handle; - upb_bufhandle_init(&handle); - upb_bufhandle_setbuf(&handle, buf, 0); + upb_bufhandle handle = UPB_BUFHANDLE_INIT; + handle.buf = buf; ret = upb_bytessink_start(sink, len, &subc); if (ret && len != 0) { ret = (upb_bytessink_putbuf(sink, subc, buf, len, &handle) >= len); @@ -14,7 +13,6 @@ bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink *sink) { if (ret) { ret = upb_bytessink_end(sink); } - upb_bufhandle_uninit(&handle); return ret; } diff --git a/upb/sink.h b/upb/sink.h index 0b98f07..8cab45d 100644 --- a/upb/sink.h +++ b/upb/sink.h @@ -22,17 +22,177 @@ #ifdef __cplusplus namespace upb { -class BufferSink; -class BufferSource; class BytesSink; class Sink; } #endif -UPB_DECLARE_TYPE(upb::BufferSink, upb_bufsink) -UPB_DECLARE_TYPE(upb::BufferSource, upb_bufsrc) -UPB_DECLARE_TYPE(upb::BytesSink, upb_bytessink) -UPB_DECLARE_TYPE(upb::Sink, upb_sink) +/* upb_sink *******************************************************************/ + +UPB_BEGIN_EXTERN_C + +typedef struct { + const upb_handlers *handlers; + void *closure; +} upb_sink; + +#define PUTVAL(type, ctype) \ + UPB_INLINE bool upb_sink_put##type(upb_sink *s, upb_selector_t sel, \ + ctype val) { \ + typedef upb_##type##_handlerfunc functype; \ + functype *func; \ + const void *hd; \ + if (!s->handlers) return true; \ + func = (functype *)upb_handlers_gethandler(s->handlers, sel, &hd); \ + if (!func) return true; \ + return func(s->closure, hd, val); \ + } + +PUTVAL(int32, int32_t) +PUTVAL(int64, int64_t) +PUTVAL(uint32, uint32_t) +PUTVAL(uint64, uint64_t) +PUTVAL(float, float) +PUTVAL(double, double) +PUTVAL(bool, bool) +#undef PUTVAL + +UPB_INLINE void upb_sink_reset(upb_sink *s, const upb_handlers *h, void *c) { + s->handlers = h; + s->closure = c; +} + +UPB_INLINE size_t upb_sink_putstring(upb_sink *s, upb_selector_t sel, + const char *buf, size_t n, + const upb_bufhandle *handle) { + typedef upb_string_handlerfunc func; + func *handler; + const void *hd; + if (!s->handlers) return n; + handler = (func *)upb_handlers_gethandler(s->handlers, sel, &hd); + + if (!handler) return n; + return handler(s->closure, hd, buf, n, handle); +} + +UPB_INLINE bool upb_sink_putunknown(upb_sink *s, const char *buf, size_t n) { + typedef upb_unknown_handlerfunc func; + func *handler; + const void *hd; + if (!s->handlers) return true; + handler = + (func *)upb_handlers_gethandler(s->handlers, UPB_UNKNOWN_SELECTOR, &hd); + + if (!handler) return n; + return handler(s->closure, hd, buf, n); +} + +UPB_INLINE bool upb_sink_startmsg(upb_sink *s) { + typedef upb_startmsg_handlerfunc func; + func *startmsg; + const void *hd; + if (!s->handlers) return true; + startmsg = + (func *)upb_handlers_gethandler(s->handlers, UPB_STARTMSG_SELECTOR, &hd); + + if (!startmsg) return true; + return startmsg(s->closure, hd); +} + +UPB_INLINE bool upb_sink_endmsg(upb_sink *s, upb_status *status) { + typedef upb_endmsg_handlerfunc func; + func *endmsg; + const void *hd; + if (!s->handlers) return true; + endmsg = + (func *)upb_handlers_gethandler(s->handlers, UPB_ENDMSG_SELECTOR, &hd); + + if (!endmsg) return true; + return endmsg(s->closure, hd, status); +} + +UPB_INLINE bool upb_sink_startseq(upb_sink *s, upb_selector_t sel, + upb_sink *sub) { + typedef upb_startfield_handlerfunc func; + func *startseq; + const void *hd; + sub->closure = s->closure; + sub->handlers = s->handlers; + if (!s->handlers) return true; + startseq = (func*)upb_handlers_gethandler(s->handlers, sel, &hd); + + if (!startseq) return true; + sub->closure = startseq(s->closure, hd); + return sub->closure ? true : false; +} + +UPB_INLINE bool upb_sink_endseq(upb_sink *s, upb_selector_t sel) { + typedef upb_endfield_handlerfunc func; + func *endseq; + const void *hd; + if (!s->handlers) return true; + endseq = (func*)upb_handlers_gethandler(s->handlers, sel, &hd); + + if (!endseq) return true; + return endseq(s->closure, hd); +} + +UPB_INLINE bool upb_sink_startstr(upb_sink *s, upb_selector_t sel, + size_t size_hint, upb_sink *sub) { + typedef upb_startstr_handlerfunc func; + func *startstr; + const void *hd; + sub->closure = s->closure; + sub->handlers = s->handlers; + if (!s->handlers) return true; + startstr = (func*)upb_handlers_gethandler(s->handlers, sel, &hd); + + if (!startstr) return true; + sub->closure = startstr(s->closure, hd, size_hint); + return sub->closure ? true : false; +} + +UPB_INLINE bool upb_sink_endstr(upb_sink *s, upb_selector_t sel) { + typedef upb_endfield_handlerfunc func; + func *endstr; + const void *hd; + if (!s->handlers) return true; + endstr = (func*)upb_handlers_gethandler(s->handlers, sel, &hd); + + if (!endstr) return true; + return endstr(s->closure, hd); +} + +UPB_INLINE bool upb_sink_startsubmsg(upb_sink *s, upb_selector_t sel, + upb_sink *sub) { + typedef upb_startfield_handlerfunc func; + func *startsubmsg; + const void *hd; + sub->closure = s->closure; + if (!s->handlers) { + sub->handlers = NULL; + return true; + } + sub->handlers = upb_handlers_getsubhandlers_sel(s->handlers, sel); + startsubmsg = (func*)upb_handlers_gethandler(s->handlers, sel, &hd); + + if (!startsubmsg) return true; + sub->closure = startsubmsg(s->closure, hd); + return sub->closure ? true : false; +} + +UPB_INLINE bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel) { + typedef upb_endfield_handlerfunc func; + func *endsubmsg; + const void *hd; + if (!s->handlers) return true; + endsubmsg = (func*)upb_handlers_gethandler(s->handlers, sel, &hd); + + if (!endsubmsg) return s->closure; + return endsubmsg(s->closure, hd); +} + +UPB_END_EXTERN_C #ifdef __cplusplus @@ -81,16 +241,24 @@ class upb::Sink { * * TODO: once the Handlers know the expected closure type, verify that T * matches it. */ - template Sink(const Handlers* handlers, T* closure); + template Sink(const upb_handlers* handlers, T* closure) { + Reset(handlers, closure); + } + + upb_sink* ptr() { return &sink_; } /* Resets the value of the sink. */ - template void Reset(const Handlers* handlers, T* closure); + template void Reset(const upb_handlers* handlers, T* closure) { + upb_sink_reset(&sink_, handlers, closure); + } /* Returns the top-level object that is bound to this sink. * * TODO: once the Handlers know the expected closure type, verify that T * matches it. */ - template T* GetObject() const; + template T* GetObject() const { + return static_cast(sink_.closure); + } /* Functions for pushing data into the sink. * @@ -108,37 +276,57 @@ class upb::Sink { * // ... * sink->EndMessage(&status); * sink->EndSubMessage(endsubmsg_selector); */ - bool StartMessage(); - bool EndMessage(Status* status); + bool StartMessage() { return upb_sink_startmsg(&sink_); } + bool EndMessage(Status* status) { return upb_sink_endmsg(&sink_, status); } /* Putting of individual values. These work for both repeated and * non-repeated fields, but for repeated fields you must wrap them in * calls to StartSequence()/EndSequence(). */ - bool PutInt32(Handlers::Selector s, int32_t val); - bool PutInt64(Handlers::Selector s, int64_t val); - bool PutUInt32(Handlers::Selector s, uint32_t val); - bool PutUInt64(Handlers::Selector s, uint64_t val); - bool PutFloat(Handlers::Selector s, float val); - bool PutDouble(Handlers::Selector s, double val); - bool PutBool(Handlers::Selector s, bool val); + bool PutInt32(HandlersPtr::Selector s, int32_t val) { + return upb_sink_putint32(&sink_, s, val); + } + + bool PutInt64(HandlersPtr::Selector s, int64_t val) { + return upb_sink_putint64(&sink_, s, val); + } + + bool PutUInt32(HandlersPtr::Selector s, uint32_t val) { + return upb_sink_putuint32(&sink_, s, val); + } + + bool PutUInt64(HandlersPtr::Selector s, uint64_t val) { + return upb_sink_putuint64(&sink_, s, val); + } + + bool PutFloat(HandlersPtr::Selector s, float val) { + return upb_sink_putfloat(&sink_, s, val); + } + + bool PutDouble(HandlersPtr::Selector s, double val) { + return upb_sink_putdouble(&sink_, s, val); + } + + bool PutBool(HandlersPtr::Selector s, bool val) { + return upb_sink_putbool(&sink_, s, val); + } /* Putting of string/bytes values. Each string can consist of zero or more * non-contiguous buffers of data. * * For StartString(), the function will write a sink for the string to "sub." * The sub-sink must be used for any/all PutStringBuffer() calls. */ - bool StartString(Handlers::Selector s, size_t size_hint, Sink* sub); - size_t PutStringBuffer(Handlers::Selector s, const char *buf, size_t len, - const BufferHandle *handle); - bool EndString(Handlers::Selector s); + bool StartString(HandlersPtr::Selector s, size_t size_hint, Sink* sub); + size_t PutStringBuffer(HandlersPtr::Selector s, const char *buf, size_t len, + const upb_bufhandle *handle); + bool EndString(HandlersPtr::Selector s); /* For submessage fields. * * For StartSubMessage(), the function will write a sink for the string to * "sub." The sub-sink must be used for any/all handlers called within the * submessage. */ - bool StartSubMessage(Handlers::Selector s, Sink* sub); - bool EndSubMessage(Handlers::Selector s); + bool StartSubMessage(HandlersPtr::Selector s, Sink* sub); + bool EndSubMessage(HandlersPtr::Selector s); /* For repeated fields of any type, the sequence of values must be wrapped in * these calls. @@ -146,84 +334,26 @@ class upb::Sink { * For StartSequence(), the function will write a sink for the string to * "sub." The sub-sink must be used for any/all handlers called within the * sequence. */ - bool StartSequence(Handlers::Selector s, Sink* sub); - bool EndSequence(Handlers::Selector s); + bool StartSequence(HandlersPtr::Selector s, Sink* sub); + bool EndSequence(HandlersPtr::Selector s); /* Copy and assign specifically allowed. * We don't even bother making these members private because so many * functions need them and this is mainly just a dumb data container anyway. */ -#else -struct upb_sink { -#endif - const upb_handlers *handlers; - void *closure; -}; -#ifdef __cplusplus -class upb::BytesSink { - public: - BytesSink() {} + private: + upb_sink sink_; +}; - /* Constructs a new sink for the given frozen handlers and closure. - * - * TODO(haberman): once the Handlers know the expected closure type, verify - * that T matches it. */ - template BytesSink(const BytesHandler* handler, T* closure); +#endif /* __cplusplus */ - /* Resets the value of the sink. */ - template void Reset(const BytesHandler* handler, T* closure); +/* upb_bytessink **************************************************************/ - bool Start(size_t size_hint, void **subc); - size_t PutBuffer(void *subc, const char *buf, size_t len, - const BufferHandle *handle); - bool End(); -#else -struct upb_bytessink { -#endif +typedef struct { const upb_byteshandler *handler; void *closure; -}; - -#ifdef __cplusplus - -/* A class for pushing a flat buffer of data to a BytesSink. - * You can construct an instance of this to get a resumable source, - * or just call the static PutBuffer() to do a non-resumable push all in one - * go. */ -class upb::BufferSource { - public: - BufferSource(); - BufferSource(const char* buf, size_t len, BytesSink* sink); - - /* Returns true if the entire buffer was pushed successfully. Otherwise the - * next call to PutNext() will resume where the previous one left off. - * TODO(haberman): implement this. */ - bool PutNext(); - - /* A static version; with this version is it not possible to resume in the - * case of failure or a partially-consumed buffer. */ - static bool PutBuffer(const char* buf, size_t len, BytesSink* sink); - - template static bool PutBuffer(const T& str, BytesSink* sink) { - return PutBuffer(str.c_str(), str.size(), sink); - } -#else -struct upb_bufsrc { - char dummy; -#endif -}; - -UPB_BEGIN_EXTERN_C - -/* A class for accumulating output string data in a flat buffer. */ - -upb_bufsink *upb_bufsink_new(upb_env *env); -void upb_bufsink_free(upb_bufsink *sink); -upb_bytessink *upb_bufsink_sink(upb_bufsink *sink); -const char *upb_bufsink_getdata(const upb_bufsink *sink, size_t *len); - -/* Inline definitions. */ +} upb_bytessink ; UPB_INLINE void upb_bytessink_reset(upb_bytessink *s, const upb_byteshandler *h, void *closure) { @@ -240,8 +370,8 @@ UPB_INLINE bool upb_bytessink_start(upb_bytessink *s, size_t size_hint, start = (func *)s->handler->table[UPB_STARTSTR_SELECTOR].func; if (!start) return true; - *subc = start(s->closure, upb_handlerattr_handlerdata( - &s->handler->table[UPB_STARTSTR_SELECTOR].attr), + *subc = start(s->closure, + s->handler->table[UPB_STARTSTR_SELECTOR].attr.handler_data, size_hint); return *subc != NULL; } @@ -255,8 +385,7 @@ UPB_INLINE size_t upb_bytessink_putbuf(upb_bytessink *s, void *subc, putbuf = (func *)s->handler->table[UPB_STRING_SELECTOR].func; if (!putbuf) return true; - return putbuf(subc, upb_handlerattr_handlerdata( - &s->handler->table[UPB_STRING_SELECTOR].attr), + return putbuf(subc, s->handler->table[UPB_STRING_SELECTOR].attr.handler_data, buf, size, handle); } @@ -268,266 +397,80 @@ UPB_INLINE bool upb_bytessink_end(upb_bytessink *s) { if (!end) return true; return end(s->closure, - upb_handlerattr_handlerdata( - &s->handler->table[UPB_ENDSTR_SELECTOR].attr)); -} - -bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink *sink); - -#define PUTVAL(type, ctype) \ - UPB_INLINE bool upb_sink_put##type(upb_sink *s, upb_selector_t sel, \ - ctype val) { \ - typedef upb_##type##_handlerfunc functype; \ - functype *func; \ - const void *hd; \ - if (!s->handlers) return true; \ - func = (functype *)upb_handlers_gethandler(s->handlers, sel); \ - if (!func) return true; \ - hd = upb_handlers_gethandlerdata(s->handlers, sel); \ - return func(s->closure, hd, val); \ - } - -PUTVAL(int32, int32_t) -PUTVAL(int64, int64_t) -PUTVAL(uint32, uint32_t) -PUTVAL(uint64, uint64_t) -PUTVAL(float, float) -PUTVAL(double, double) -PUTVAL(bool, bool) -#undef PUTVAL - -UPB_INLINE void upb_sink_reset(upb_sink *s, const upb_handlers *h, void *c) { - s->handlers = h; - s->closure = c; + s->handler->table[UPB_ENDSTR_SELECTOR].attr.handler_data); } -UPB_INLINE size_t upb_sink_putstring(upb_sink *s, upb_selector_t sel, - const char *buf, size_t n, - const upb_bufhandle *handle) { - typedef upb_string_handlerfunc func; - func *handler; - const void *hd; - if (!s->handlers) return n; - handler = (func *)upb_handlers_gethandler(s->handlers, sel); - - if (!handler) return n; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - return handler(s->closure, hd, buf, n, handle); -} - -UPB_INLINE bool upb_sink_putunknown(upb_sink *s, const char *buf, size_t n) { - typedef upb_unknown_handlerfunc func; - func *handler; - const void *hd; - if (!s->handlers) return true; - handler = (func *)upb_handlers_gethandler(s->handlers, UPB_UNKNOWN_SELECTOR); - - if (!handler) return n; - hd = upb_handlers_gethandlerdata(s->handlers, UPB_UNKNOWN_SELECTOR); - return handler(s->closure, hd, buf, n); -} - -UPB_INLINE bool upb_sink_startmsg(upb_sink *s) { - typedef upb_startmsg_handlerfunc func; - func *startmsg; - const void *hd; - if (!s->handlers) return true; - startmsg = (func*)upb_handlers_gethandler(s->handlers, UPB_STARTMSG_SELECTOR); - - if (!startmsg) return true; - hd = upb_handlers_gethandlerdata(s->handlers, UPB_STARTMSG_SELECTOR); - return startmsg(s->closure, hd); -} - -UPB_INLINE bool upb_sink_endmsg(upb_sink *s, upb_status *status) { - typedef upb_endmsg_handlerfunc func; - func *endmsg; - const void *hd; - if (!s->handlers) return true; - endmsg = (func *)upb_handlers_gethandler(s->handlers, UPB_ENDMSG_SELECTOR); - - if (!endmsg) return true; - hd = upb_handlers_gethandlerdata(s->handlers, UPB_ENDMSG_SELECTOR); - return endmsg(s->closure, hd, status); -} +#ifdef __cplusplus -UPB_INLINE bool upb_sink_startseq(upb_sink *s, upb_selector_t sel, - upb_sink *sub) { - typedef upb_startfield_handlerfunc func; - func *startseq; - const void *hd; - sub->closure = s->closure; - sub->handlers = s->handlers; - if (!s->handlers) return true; - startseq = (func*)upb_handlers_gethandler(s->handlers, sel); +class upb::BytesSink { + public: + BytesSink() {} - if (!startseq) return true; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - sub->closure = startseq(s->closure, hd); - return sub->closure ? true : false; -} + upb_bytessink* ptr() { return &sink_; } -UPB_INLINE bool upb_sink_endseq(upb_sink *s, upb_selector_t sel) { - typedef upb_endfield_handlerfunc func; - func *endseq; - const void *hd; - if (!s->handlers) return true; - endseq = (func*)upb_handlers_gethandler(s->handlers, sel); + /* Constructs a new sink for the given frozen handlers and closure. + * + * TODO(haberman): once the Handlers know the expected closure type, verify + * that T matches it. */ + template BytesSink(const upb_byteshandler* handler, T* closure) { + upb_bytessink_reset(&sink_, handler, closure); + } - if (!endseq) return true; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - return endseq(s->closure, hd); -} + /* Resets the value of the sink. */ + template void Reset(const upb_byteshandler* handler, T* closure) { + upb_bytessink_reset(&sink_, handler, closure); + } -UPB_INLINE bool upb_sink_startstr(upb_sink *s, upb_selector_t sel, - size_t size_hint, upb_sink *sub) { - typedef upb_startstr_handlerfunc func; - func *startstr; - const void *hd; - sub->closure = s->closure; - sub->handlers = s->handlers; - if (!s->handlers) return true; - startstr = (func*)upb_handlers_gethandler(s->handlers, sel); + bool Start(size_t size_hint, void **subc) { + return upb_bytessink_start(&sink_, size_hint, subc); + } - if (!startstr) return true; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - sub->closure = startstr(s->closure, hd, size_hint); - return sub->closure ? true : false; -} + size_t PutBuffer(void *subc, const char *buf, size_t len, + const upb_bufhandle *handle) { + return upb_bytessink_putbuf(&sink_, subc, buf, len, handle); + } -UPB_INLINE bool upb_sink_endstr(upb_sink *s, upb_selector_t sel) { - typedef upb_endfield_handlerfunc func; - func *endstr; - const void *hd; - if (!s->handlers) return true; - endstr = (func*)upb_handlers_gethandler(s->handlers, sel); + bool End() { + return upb_bytessink_end(&sink_); + } - if (!endstr) return true; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - return endstr(s->closure, hd); -} + private: + upb_bytessink sink_; +}; -UPB_INLINE bool upb_sink_startsubmsg(upb_sink *s, upb_selector_t sel, - upb_sink *sub) { - typedef upb_startfield_handlerfunc func; - func *startsubmsg; - const void *hd; - sub->closure = s->closure; - if (!s->handlers) { - sub->handlers = NULL; - return true; - } - sub->handlers = upb_handlers_getsubhandlers_sel(s->handlers, sel); - startsubmsg = (func*)upb_handlers_gethandler(s->handlers, sel); +#endif /* __cplusplus */ - if (!startsubmsg) return true; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - sub->closure = startsubmsg(s->closure, hd); - return sub->closure ? true : false; -} +/* upb_bufsrc *****************************************************************/ -UPB_INLINE bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel) { - typedef upb_endfield_handlerfunc func; - func *endsubmsg; - const void *hd; - if (!s->handlers) return true; - endsubmsg = (func*)upb_handlers_gethandler(s->handlers, sel); +UPB_BEGIN_EXTERN_C - if (!endsubmsg) return s->closure; - hd = upb_handlers_gethandlerdata(s->handlers, sel); - return endsubmsg(s->closure, hd); -} +bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink *sink); UPB_END_EXTERN_C #ifdef __cplusplus namespace upb { - -template Sink::Sink(const Handlers* handlers, T* closure) { - upb_sink_reset(this, handlers, closure); -} -template -inline void Sink::Reset(const Handlers* handlers, T* closure) { - upb_sink_reset(this, handlers, closure); -} -inline bool Sink::StartMessage() { - return upb_sink_startmsg(this); -} -inline bool Sink::EndMessage(Status* status) { - return upb_sink_endmsg(this, status); -} -inline bool Sink::PutInt32(Handlers::Selector sel, int32_t val) { - return upb_sink_putint32(this, sel, val); -} -inline bool Sink::PutInt64(Handlers::Selector sel, int64_t val) { - return upb_sink_putint64(this, sel, val); -} -inline bool Sink::PutUInt32(Handlers::Selector sel, uint32_t val) { - return upb_sink_putuint32(this, sel, val); -} -inline bool Sink::PutUInt64(Handlers::Selector sel, uint64_t val) { - return upb_sink_putuint64(this, sel, val); -} -inline bool Sink::PutFloat(Handlers::Selector sel, float val) { - return upb_sink_putfloat(this, sel, val); -} -inline bool Sink::PutDouble(Handlers::Selector sel, double val) { - return upb_sink_putdouble(this, sel, val); +template bool PutBuffer(const T& str, upb_bytessink* sink) { + return upb_bufsrc_putbuf(str.c_str(), str.size(), sink); } -inline bool Sink::PutBool(Handlers::Selector sel, bool val) { - return upb_sink_putbool(this, sel, val); -} -inline bool Sink::StartString(Handlers::Selector sel, size_t size_hint, - Sink *sub) { - return upb_sink_startstr(this, sel, size_hint, sub); -} -inline size_t Sink::PutStringBuffer(Handlers::Selector sel, const char *buf, - size_t len, const BufferHandle* handle) { - return upb_sink_putstring(this, sel, buf, len, handle); -} -inline bool Sink::EndString(Handlers::Selector sel) { - return upb_sink_endstr(this, sel); -} -inline bool Sink::StartSubMessage(Handlers::Selector sel, Sink* sub) { - return upb_sink_startsubmsg(this, sel, sub); -} -inline bool Sink::EndSubMessage(Handlers::Selector sel) { - return upb_sink_endsubmsg(this, sel); -} -inline bool Sink::StartSequence(Handlers::Selector sel, Sink* sub) { - return upb_sink_startseq(this, sel, sub); -} -inline bool Sink::EndSequence(Handlers::Selector sel) { - return upb_sink_endseq(this, sel); } -template -BytesSink::BytesSink(const BytesHandler* handler, T* closure) { - Reset(handler, closure); -} +#endif /* __cplusplus */ -template -void BytesSink::Reset(const BytesHandler *handler, T *closure) { - upb_bytessink_reset(this, handler, closure); -} -inline bool BytesSink::Start(size_t size_hint, void **subc) { - return upb_bytessink_start(this, size_hint, subc); -} -inline size_t BytesSink::PutBuffer(void *subc, const char *buf, size_t len, - const BufferHandle *handle) { - return upb_bytessink_putbuf(this, subc, buf, len, handle); -} -inline bool BytesSink::End() { - return upb_bytessink_end(this); -} +/* upb_bufsink ****************************************************************/ -inline bool BufferSource::PutBuffer(const char *buf, size_t len, - BytesSink *sink) { - return upb_bufsrc_putbuf(buf, len, sink); -} +/* A class for accumulating output string data in a flat buffer. */ +struct upb_bufsink; +typedef struct upb_bufsink upb_bufsink; -} /* namespace upb */ -#endif +UPB_BEGIN_EXTERN_C + +upb_bufsink *upb_bufsink_init(upb_env *env); +void upb_bufsink_free(upb_bufsink *sink); +upb_bytessink *upb_bufsink_sink(upb_bufsink *sink); +const char *upb_bufsink_getdata(const upb_bufsink *sink, size_t *len); + +UPB_END_EXTERN_C #endif diff --git a/upb/upb.h b/upb/upb.h index 2fb7a88..a75e311 100644 --- a/upb/upb.h +++ b/upb/upb.h @@ -74,7 +74,6 @@ template class InlinedEnvironment; #error Need implementations of [v]snprintf and va_copy #endif - #if ((defined(__cplusplus) && __cplusplus >= 201103L) || \ defined(__GXX_EXPERIMENTAL_CXX0X__)) && !defined(UPB_NO_CXX11) #define UPB_CXX11 @@ -110,28 +109,6 @@ template class InlinedEnvironment; #define UPB_FINAL #endif -/* UPB_DECLARE_TYPE() - * UPB_DECLARE_DERIVED_TYPE() - * UPB_DECLARE_DERIVED_TYPE2() - * - * Macros for declaring C and C++ types both, including inheritance. - * The inheritance doesn't use real C++ inheritance, to stay compatible with C. - * - * These macros also provide upcasts: - * - in C: types-specific functions (ie. upb_foo_upcast(foo)) - * - in C++: upb::upcast(foo) along with implicit conversions - * - * Downcasts are not provided, but upb/def.h defines downcasts for upb::Def. */ - -#define UPB_C_UPCASTS(ty, base) \ - UPB_INLINE base *ty ## _upcast_mutable(ty *p) { return (base*)p; } \ - UPB_INLINE const base *ty ## _upcast(const ty *p) { return (const base*)p; } - -#define UPB_C_UPCASTS2(ty, base, base2) \ - UPB_C_UPCASTS(ty, base) \ - UPB_INLINE base2 *ty ## _upcast2_mutable(ty *p) { return (base2*)p; } \ - UPB_INLINE const base2 *ty ## _upcast2(const ty *p) { return (const base2*)p; } - #ifdef __cplusplus #define UPB_BEGIN_EXTERN_C extern "C" { @@ -139,45 +116,6 @@ template class InlinedEnvironment; #define UPB_PRIVATE_FOR_CPP private: #define UPB_DECLARE_TYPE(cppname, cname) typedef cppname cname; -#define UPB_DECLARE_DERIVED_TYPE(cppname, cppbase, cname, cbase) \ - UPB_DECLARE_TYPE(cppname, cname) \ - UPB_C_UPCASTS(cname, cbase) \ - namespace upb { \ - template <> \ - class Pointer : public PointerBase { \ - public: \ - explicit Pointer(cppname* ptr) \ - : PointerBase(ptr) {} \ - }; \ - template <> \ - class Pointer \ - : public PointerBase { \ - public: \ - explicit Pointer(const cppname* ptr) \ - : PointerBase(ptr) {} \ - }; \ - } - -#define UPB_DECLARE_DERIVED_TYPE2(cppname, cppbase, cppbase2, cname, cbase, \ - cbase2) \ - UPB_DECLARE_TYPE(cppname, cname) \ - UPB_C_UPCASTS2(cname, cbase, cbase2) \ - namespace upb { \ - template <> \ - class Pointer : public PointerBase2 { \ - public: \ - explicit Pointer(cppname* ptr) \ - : PointerBase2(ptr) {} \ - }; \ - template <> \ - class Pointer \ - : public PointerBase2 { \ - public: \ - explicit Pointer(const cppname* ptr) \ - : PointerBase2(ptr) {} \ - }; \ - } - #else /* !defined(__cplusplus) */ #define UPB_BEGIN_EXTERN_C @@ -186,13 +124,6 @@ template class InlinedEnvironment; #define UPB_DECLARE_TYPE(cppname, cname) \ struct cname; \ typedef struct cname cname; -#define UPB_DECLARE_DERIVED_TYPE(cppname, cppbase, cname, cbase) \ - UPB_DECLARE_TYPE(cppname, cname) \ - UPB_C_UPCASTS(cname, cbase) -#define UPB_DECLARE_DERIVED_TYPE2(cppname, cppbase, cppbase2, \ - cname, cbase, cbase2) \ - UPB_DECLARE_TYPE(cppname, cname) \ - UPB_C_UPCASTS2(cname, cbase, cbase2) #endif /* defined(__cplusplus) */ -- cgit v1.2.3 From 48863ea0be94ea3d3d61206ad7ce9ead206770fa Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Sat, 12 Jan 2019 19:12:57 -0800 Subject: A lot more tests are working now. --- BUILD | 10 --- tests/json/test_json.cc | 36 +++++----- tests/pb/test_decoder.cc | 157 ++++++++++++++++++++----------------------- tests/test_handlers.c | 42 ------------ tests/test_util.h | 10 +-- upb/bindings/stdc++/string.h | 3 +- upb/handlers-inl.h | 2 +- upb/handlers.c | 11 ++- upb/handlers.h | 2 + upb/json/parser.c | 144 ++++++++++++++++++++------------------- upb/json/parser.h | 140 ++++++++++++++++++++------------------ upb/json/parser.rl | 38 ++++++----- upb/json/printer.c | 32 +++++---- upb/json/printer.h | 68 ++++++++----------- upb/pb/decoder.c | 11 ++- upb/pb/decoder.h | 11 +-- upb/pb/encoder.c | 14 ++-- upb/pb/encoder.h | 12 ++-- upb/sink.c | 8 +-- upb/sink.h | 28 ++++++-- 20 files changed, 375 insertions(+), 404 deletions(-) delete mode 100644 tests/test_handlers.c (limited to 'upb/bindings') diff --git a/BUILD b/BUILD index ffb5bbd..c6c401c 100644 --- a/BUILD +++ b/BUILD @@ -166,16 +166,6 @@ upb_proto_reflection_library( deps = ["descriptor_proto"], ) -cc_test( - name = "test_handlers", - srcs = ["tests/test_handlers.c"], - deps = [ - ":descriptor_upbproto", - ":upb_pb", - ":upb_test", - ], -) - proto_library( name = "test_decoder_proto", srcs = [ diff --git a/tests/json/test_json.cc b/tests/json/test_json.cc index b9b50cd..b0fd3e3 100644 --- a/tests/json/test_json.cc +++ b/tests/json/test_json.cc @@ -144,7 +144,7 @@ class StringSink { } ~StringSink() { } - upb_bytessink* Sink() { return &bytessink_; } + upb_bytessink Sink() { return bytessink_; } const std::string& Data() { return s_; } @@ -169,16 +169,15 @@ class StringSink { void test_json_roundtrip_message(const char* json_src, const char* json_expected, const upb::Handlers* serialize_handlers, - const upb::json::ParserMethod* parser_method, + const upb::json::ParserMethodPtr parser_method, int seam) { VerboseParserEnvironment env(verbose); StringSink data_sink; - upb::json::Printer* printer = upb::json::Printer::Create( + upb::json::PrinterPtr printer = upb::json::PrinterPtr::Create( env.env(), serialize_handlers, data_sink.Sink()); - upb::json::Parser* parser = - upb::json::Parser::Create( - env.env(), parser_method, NULL, printer->input(), false); - env.ResetBytesSink(parser->input()); + upb::json::ParserPtr parser = upb::json::ParserPtr::Create( + env.env(), parser_method, NULL, printer.input(), false); + env.ResetBytesSink(parser.input()); env.Reset(json_src, strlen(json_src), false, false); bool ok = env.Start() && @@ -203,16 +202,16 @@ void test_json_roundtrip_message(const char* json_src, // Starts with a message in JSON format, parses and directly serializes again, // and compares the result. void test_json_roundtrip() { - upb::SymbolTable* symtab = upb::SymbolTable::New(); - upb::HandlerCache* serialize_handlercache = upb::json::Printer::NewCache(false); - upb::json::CodeCache* parse_codecache = upb::json::CodeCache::New(); + upb::SymbolTable symtab; + upb::HandlerCache serialize_handlercache( + upb::json::PrinterPtr::NewCache(false)); + upb::json::CodeCache parse_codecache; - const upb::MessageDef* md = upb_test_json_TestMessage_getmsgdef(symtab); + upb::MessageDefPtr md(upb_test_json_TestMessage_getmsgdef(symtab.ptr())); ASSERT(md); - const upb::Handlers* serialize_handlers = serialize_handlercache->Get(md); - const upb::json::ParserMethod* parser_method = parse_codecache->Get(md); + const upb::Handlers* serialize_handlers = serialize_handlercache.Get(md); + const upb::json::ParserMethodPtr parser_method = parse_codecache.Get(md); ASSERT(serialize_handlers); - ASSERT(parser_method); for (const TestCase* test_case = kTestRoundtripMessages; test_case->input != NULL; test_case++) { @@ -227,9 +226,8 @@ void test_json_roundtrip() { } } - upb::HandlerCache::Free(serialize_handlercache); - serialize_handlercache = upb::json::Printer::NewCache(true); - serialize_handlers = serialize_handlercache->Get(md); + serialize_handlercache = upb::json::PrinterPtr::NewCache(true); + serialize_handlers = serialize_handlercache.Get(md); for (const TestCase* test_case = kTestRoundtripMessagesPreserve; test_case->input != NULL; test_case++) { @@ -243,10 +241,6 @@ void test_json_roundtrip() { serialize_handlers, parser_method, i); } } - - upb::HandlerCache::Free(serialize_handlercache); - upb::json::CodeCache::Free(parse_codecache); - upb::SymbolTable::Free(symtab); } extern "C" { diff --git a/tests/pb/test_decoder.cc b/tests/pb/test_decoder.cc index d0e3fa3..ec7a788 100644 --- a/tests/pb/test_decoder.cc +++ b/tests/pb/test_decoder.cc @@ -279,7 +279,7 @@ int* startstr(int* depth, const uint32_t* num, size_t size_hint) { } size_t value_string(int* depth, const uint32_t* num, const char* buf, - size_t n, const upb::BufferHandle* handle) { + size_t n, const upb_bufhandle* handle) { UPB_UNUSED(num); UPB_UNUSED(depth); check_stack_alignment(); @@ -348,13 +348,13 @@ void free_uint32(void *val) { } template -void doreg(upb_handlers *h, uint32_t num) { - const upb_fielddef *f = upb_msgdef_itof(upb_handlers_msgdef(h), num); +void doreg(upb::HandlersPtr h, uint32_t num) { + upb::FieldDefPtr f = h.message_def().FindFieldByNumber(num); ASSERT(f); - ASSERT(h->SetValueHandler(f, UpbBindT(F, new uint32_t(num)))); - if (f->IsSequence()) { - ASSERT(h->SetStartSequenceHandler(f, UpbBind(startseq, new uint32_t(num)))); - ASSERT(h->SetEndSequenceHandler(f, UpbBind(endseq, new uint32_t(num)))); + ASSERT(h.SetValueHandler(f, UpbBind(F, new uint32_t(num)))); + if (f.IsSequence()) { + ASSERT(h.SetStartSequenceHandler(f, UpbBind(startseq, new uint32_t(num)))); + ASSERT(h.SetEndSequenceHandler(f, UpbBind(endseq, new uint32_t(num)))); } } @@ -368,7 +368,7 @@ uint32_t rep_fn(uint32_t fn) { #define UNKNOWN_FIELD 666 template -void reg(upb_handlers *h, upb_descriptortype_t type) { +void reg(upb::HandlersPtr h, upb_descriptortype_t type) { // We register both a repeated and a non-repeated field for every type. // For the non-repeated field we make the field number the same as the // type. For the repeated field we make it a function of the type. @@ -376,39 +376,40 @@ void reg(upb_handlers *h, upb_descriptortype_t type) { doreg(h, rep_fn(type)); } -void regseq(upb::Handlers* h, const upb::FieldDef* f, uint32_t num) { - ASSERT(h->SetStartSequenceHandler(f, UpbBind(startseq, new uint32_t(num)))); - ASSERT(h->SetEndSequenceHandler(f, UpbBind(endseq, new uint32_t(num)))); +void regseq(upb::HandlersPtr h, upb::FieldDefPtr f, uint32_t num) { + ASSERT(h.SetStartSequenceHandler(f, UpbBind(startseq, new uint32_t(num)))); + ASSERT(h.SetEndSequenceHandler(f, UpbBind(endseq, new uint32_t(num)))); } -void reg_subm(upb_handlers *h, uint32_t num) { - const upb_fielddef *f = upb_msgdef_itof(upb_handlers_msgdef(h), num); +void reg_subm(upb::HandlersPtr h, uint32_t num) { + upb::FieldDefPtr f = h.message_def().FindFieldByNumber(num); ASSERT(f); - if (f->IsSequence()) regseq(h, f, num); + if (f.IsSequence()) regseq(h, f, num); ASSERT( - h->SetStartSubMessageHandler(f, UpbBind(startsubmsg, new uint32_t(num)))); - ASSERT(h->SetEndSubMessageHandler(f, UpbBind(endsubmsg, new uint32_t(num)))); + h.SetStartSubMessageHandler(f, UpbBind(startsubmsg, new uint32_t(num)))); + ASSERT(h.SetEndSubMessageHandler(f, UpbBind(endsubmsg, new uint32_t(num)))); } -void reg_str(upb_handlers *h, uint32_t num) { - const upb_fielddef *f = upb_msgdef_itof(upb_handlers_msgdef(h), num); +void reg_str(upb::HandlersPtr h, uint32_t num) { + upb::FieldDefPtr f = h.message_def().FindFieldByNumber(num); ASSERT(f); - if (f->IsSequence()) regseq(h, f, num); - ASSERT(h->SetStartStringHandler(f, UpbBind(startstr, new uint32_t(num)))); - ASSERT(h->SetEndStringHandler(f, UpbBind(endstr, new uint32_t(num)))); - ASSERT(h->SetStringHandler(f, UpbBind(value_string, new uint32_t(num)))); + if (f.IsSequence()) regseq(h, f, num); + ASSERT(h.SetStartStringHandler(f, UpbBind(startstr, new uint32_t(num)))); + ASSERT(h.SetEndStringHandler(f, UpbBind(endstr, new uint32_t(num)))); + ASSERT(h.SetStringHandler(f, UpbBind(value_string, new uint32_t(num)))); } struct HandlerRegisterData { TestMode mode; }; -void callback(const void *closure, upb_handlers *h) { +void callback(const void *closure, upb::Handlers* h_ptr) { + upb::HandlersPtr h(h_ptr); const HandlerRegisterData* data = static_cast(closure); if (data->mode == ALL_HANDLERS) { - h->SetStartMessageHandler(UpbMakeHandler(startmsg)); - h->SetEndMessageHandler(UpbMakeHandler(endmsg)); + h.SetStartMessageHandler(UpbMakeHandler(startmsg)); + h.SetEndMessageHandler(UpbMakeHandler(endmsg)); // Register handlers for each type. reg(h, UPB_DESCRIPTOR_TYPE_DOUBLE); @@ -436,7 +437,7 @@ void callback(const void *closure, upb_handlers *h) { reg_subm(h, UPB_DESCRIPTOR_TYPE_MESSAGE); reg_subm(h, rep_fn(UPB_DESCRIPTOR_TYPE_MESSAGE)); - if (h->message_def()->full_name() == std::string("DecoderTest")) { + if (h.message_def().full_name() == std::string("DecoderTest")) { reg_subm(h, UPB_DESCRIPTOR_TYPE_GROUP); reg_subm(h, rep_fn(UPB_DESCRIPTOR_TYPE_GROUP)); } @@ -446,25 +447,16 @@ void callback(const void *closure, upb_handlers *h) { } } -upb::reffed_ptr NewHandlers(upb::SymbolTable* symtab, - TestMode mode) { - HandlerRegisterData handlerdata; - handlerdata.mode = mode; - return upb::Handlers::NewFrozen(DecoderTest_getmsgdef(symtab), callback, - &handlerdata); -} - /* Running of test cases ******************************************************/ const upb::Handlers *global_handlers; -const upb::pb::DecoderMethod *global_method; - -upb::pb::Decoder* CreateDecoder(upb::Environment* env, - const upb::pb::DecoderMethod* method, - upb::Sink* sink) { - upb::pb::Decoder *ret = upb::pb::Decoder::Create(env, method, sink); - ASSERT(ret != NULL); - ret->set_max_nesting(MAX_NESTING); +upb::pb::DecoderMethodPtr global_method; + +upb::pb::DecoderPtr CreateDecoder(upb::Environment* env, + upb::pb::DecoderMethodPtr method, + upb::Sink sink) { + upb::pb::DecoderPtr ret = upb::pb::DecoderPtr::Create(env, method, sink); + ret.set_max_nesting(MAX_NESTING); return ret; } @@ -479,7 +471,7 @@ uint32_t Hash(const string& proto, const string* expected_output, size_t seam1, return hash; } -void CheckBytesParsed(const upb::pb::Decoder& decoder, size_t ofs) { +void CheckBytesParsed(upb::pb::DecoderPtr decoder, size_t ofs) { // We can't have parsed more data than the decoder callback is telling us it // parsed. ASSERT(decoder.BytesParsed() <= ofs); @@ -491,7 +483,7 @@ void CheckBytesParsed(const upb::pb::Decoder& decoder, size_t ofs) { } static bool parse(VerboseParserEnvironment* env, - const upb::pb::Decoder& decoder, int bytes) { + upb::pb::DecoderPtr decoder, int bytes) { CheckBytesParsed(decoder, env->ofs()); bool ret = env->ParseBuffer(bytes); if (ret) { @@ -501,11 +493,11 @@ static bool parse(VerboseParserEnvironment* env, return ret; } -void do_run_decoder(VerboseParserEnvironment* env, upb::pb::Decoder* decoder, +void do_run_decoder(VerboseParserEnvironment* env, upb::pb::DecoderPtr decoder, const string& proto, const string* expected_output, size_t i, size_t j, bool may_skip) { env->Reset(proto.c_str(), proto.size(), may_skip, expected_output == NULL); - decoder->Reset(); + decoder.Reset(); testhash = Hash(proto, expected_output, i, j, may_skip); if (filter_hash && testhash != filter_hash) return; @@ -515,7 +507,7 @@ void do_run_decoder(VerboseParserEnvironment* env, upb::pb::Decoder* decoder, if (filter_hash) { fprintf(stderr, "RUNNING TEST CASE, hash=%x\n", testhash); fprintf(stderr, "JIT on: %s\n", - global_method->is_native() ? "true" : "false"); + global_method.is_native() ? "true" : "false"); fprintf(stderr, "Input (len=%u): ", (unsigned)proto.size()); PrintBinary(proto); fprintf(stderr, "\n"); @@ -534,9 +526,9 @@ void do_run_decoder(VerboseParserEnvironment* env, upb::pb::Decoder* decoder, } bool ok = env->Start() && - parse(env, *decoder, i) && - parse(env, *decoder, j - i) && - parse(env, *decoder, -1) && + parse(env, decoder, i) && + parse(env, decoder, j - i) && + parse(env, decoder, -1) && env->End(); ASSERT(env->CheckConsistency()); @@ -564,8 +556,8 @@ void do_run_decoder(VerboseParserEnvironment* env, upb::pb::Decoder* decoder, void run_decoder(const string& proto, const string* expected_output) { VerboseParserEnvironment env(filter_hash != 0); upb::Sink sink(global_handlers, &closures[0]); - upb::pb::Decoder *decoder = CreateDecoder(env.env(), global_method, &sink); - env.ResetBytesSink(decoder->input()); + upb::pb::DecoderPtr decoder = CreateDecoder(env.env(), global_method, sink); + env.ResetBytesSink(decoder.input()); for (size_t i = 0; i < proto.size(); i++) { for (size_t j = i; j < UPB_MIN(proto.size(), i + 5); j++) { do_run_decoder(&env, decoder, proto, expected_output, i, j, true); @@ -883,9 +875,9 @@ void test_valid() { upb::Environment env; env.ReportErrorsTo(&status); upb::Sink sink(global_handlers, &closures[0]); - upb::pb::Decoder* decoder = CreateDecoder(&env, global_method, &sink); + upb::pb::DecoderPtr decoder = CreateDecoder(&env, global_method, sink); output.clear(); - bool ok = upb::BufferSource::PutBuffer("", 0, decoder->input()); + bool ok = upb::PutBuffer(std::string(), decoder.input()); ASSERT(ok); ASSERT(status.ok()); if (test_mode == ALL_HANDLERS) { @@ -1133,23 +1125,22 @@ void test_valid() { run_decoder(buf, &textbuf); } -upb::reffed_ptr NewMethod( - const upb::Handlers* dest_handlers, bool allow_jit) { - upb::pb::CodeCache cache; - cache.set_allow_jit(allow_jit); - return cache.GetDecoderMethod(upb::pb::DecoderMethodOptions(dest_handlers)); -} +void empty_callback(const void *closure, upb::Handlers* h_ptr) {} void test_emptyhandlers(upb::SymbolTable* symtab, bool allowjit) { // Create an empty handlers to make sure that the decoder can handle empty // messages. - const upb::MessageDef* md = Empty_getmsgdef(symtab); - upb::reffed_ptr h(upb::Handlers::New(md)); - bool ok = h->Freeze(NULL); - ASSERT(ok); -upb::reffed_ptr method = - NewMethod(h.get(), allowjit); - ASSERT(method.get()); + HandlerRegisterData handlerdata; + handlerdata.mode = test_mode; + + upb::HandlerCache handler_cache(empty_callback, &handlerdata); + upb::pb::CodeCache pb_code_cache(&handler_cache); + + pb_code_cache.set_allow_jit(allowjit); + + upb::MessageDefPtr md = upb::MessageDefPtr(Empty_getmsgdef(symtab->ptr())); + global_handlers = handler_cache.Get(md); + global_method = pb_code_cache.Get(md); // TODO: also test the case where a message has fields, but the fields are // submessage fields and have no handlers. This also results in a decoder @@ -1169,9 +1160,9 @@ upb::reffed_ptr method = }; for (int i = 0; testdata[i].data; i++) { VerboseParserEnvironment env(filter_hash != 0); - upb::Sink sink(method->dest_handlers(), &closures[0]); - upb::pb::Decoder* decoder = CreateDecoder(env.env(), method.get(), &sink); - env.ResetBytesSink(decoder->input()); + upb::Sink sink(global_method.dest_handlers(), &closures[0]); + upb::pb::DecoderPtr decoder = CreateDecoder(env.env(), global_method, sink); + env.ResetBytesSink(decoder.input()); env.Reset(testdata[i].data, testdata[i].length, true, false); ASSERT(env.Start()); ASSERT(env.ParseBuffer(-1)); @@ -1181,24 +1172,25 @@ upb::reffed_ptr method = } void run_tests(bool use_jit) { - upb::reffed_ptr method; - upb::reffed_ptr handlers; - upb::SymbolTable* symtab = upb::SymbolTable::New(); + HandlerRegisterData handlerdata; + handlerdata.mode = test_mode; - handlers = NewHandlers(symtab, test_mode); - global_handlers = handlers.get(); + upb::SymbolTable symtab; + upb::HandlerCache handler_cache(callback, &handlerdata); + upb::pb::CodeCache pb_code_cache(&handler_cache); - method = NewMethod(handlers.get(), use_jit); - global_method = method.get(); - ASSERT(use_jit == global_method->is_native()); + pb_code_cache.set_allow_jit(use_jit); + + upb::MessageDefPtr md(DecoderTest_getmsgdef(symtab.ptr())); + global_handlers = handler_cache.Get(md); + global_method = pb_code_cache.Get(md); + ASSERT(use_jit == global_method.is_native()); completed = 0; test_invalid(); test_valid(); - test_emptyhandlers(symtab, use_jit); - - upb::SymbolTable::Free(symtab); + test_emptyhandlers(&symtab, use_jit); } void run_test_suite() { @@ -1218,9 +1210,6 @@ int run_tests(int argc, char *argv[]) { closures[i] = i; } - upb::reffed_ptr method; - upb::reffed_ptr handlers; - // Count tests. count = &total; total = 0; diff --git a/tests/test_handlers.c b/tests/test_handlers.c deleted file mode 100644 index 2b19cab..0000000 --- a/tests/test_handlers.c +++ /dev/null @@ -1,42 +0,0 @@ - -#include -#include -#include "google/protobuf/descriptor.upbdefs.h" -#include "upb/handlers.h" -#include "upb_test.h" - -static bool startmsg(void *c, const void *hd) { - UPB_UNUSED(c); - UPB_UNUSED(hd); - return true; -} - -static void test_error() { - /* Test creating handlers of a static msgdef. */ - upb_symtab *s = upb_symtab_new(); - const upb_msgdef *m = google_protobuf_DescriptorProto_getmsgdef(s); - upb_handlers *h = upb_handlers_new(m, &h); - - /* Attempt to set the same handler twice causes error. */ - ASSERT(upb_ok(upb_handlers_status(h))); - upb_handlers_setstartmsg(h, &startmsg, NULL); - ASSERT(upb_ok(upb_handlers_status(h))); - upb_handlers_setstartmsg(h, &startmsg, NULL); - ASSERT(!upb_ok(upb_handlers_status(h))); - ASSERT(!upb_handlers_freeze(&h, 1, NULL)); - - /* Clearing the error will let us proceed. */ - upb_handlers_clearerr(h); - ASSERT(upb_handlers_freeze(&h, 1, NULL)); - ASSERT(upb_handlers_isfrozen(h)); - - upb_handlers_unref(h, &h); - upb_symtab_free(s); -} - -int run_tests(int argc, char *argv[]) { - UPB_UNUSED(argc); - UPB_UNUSED(argv); - test_error(); - return 0; -} diff --git a/tests/test_util.h b/tests/test_util.h index 1b1ff01..0b5ddd4 100644 --- a/tests/test_util.h +++ b/tests/test_util.h @@ -78,14 +78,14 @@ class VerboseParserEnvironment { if (verbose_) { fprintf(stderr, "Calling start()\n"); } - return sink_->Start(len_, &subc_); + return sink_.Start(len_, &subc_); } bool End() { if (verbose_) { fprintf(stderr, "Calling end()\n"); } - end_ok_ = sink_->End(); + end_ok_ = sink_.End(); end_ok_set_ = true; return end_ok_; @@ -137,7 +137,7 @@ class VerboseParserEnvironment { (unsigned)bytes, (unsigned)ofs_, (unsigned)(ofs_ + bytes)); } - int parsed = sink_->PutBuffer(subc_, buf2, bytes, &global_handle); + int parsed = sink_.PutBuffer(subc_, buf2, bytes, &global_handle); free(buf2); if (verbose_) { @@ -170,7 +170,7 @@ class VerboseParserEnvironment { return true; } - void ResetBytesSink(upb::BytesSink* sink) { + void ResetBytesSink(upb::BytesSink sink) { sink_ = sink; } @@ -181,7 +181,7 @@ class VerboseParserEnvironment { private: upb::Environment env_; - upb::BytesSink* sink_; + upb::BytesSink sink_; const char* buf_; size_t len_; bool verbose_; diff --git a/upb/bindings/stdc++/string.h b/upb/bindings/stdc++/string.h index 4d7a719..55b44cf 100644 --- a/upb/bindings/stdc++/string.h +++ b/upb/bindings/stdc++/string.h @@ -48,11 +48,12 @@ class StringSink { explicit StringSink(T* target) { // TODO(haberman): we need to avoid rebuilding a new handler every time, // but with class globals disallowed for google3 C++ this is tricky. + upb_byteshandler_init(&handler_); FillStringHandler::SetHandler(&handler_); input_.Reset(&handler_, target); } - BytesSink* input() { return &input_; } + BytesSink input() { return input_; } private: upb_byteshandler handler_; diff --git a/upb/handlers-inl.h b/upb/handlers-inl.h index b038e30..5677a4a 100644 --- a/upb/handlers-inl.h +++ b/upb/handlers-inl.h @@ -858,7 +858,7 @@ inline Handler::Handler(F func) : registered_(false), cleanup_data_(func.GetData()), cleanup_func_(func.GetCleanup()) { - upb_handlerattr_sethandlerdata(&attr_, func.GetData()); + attr_.handler_data = func.GetData(); typedef typename ReturnOf::Return Return; typedef typename ConvertParams::Func ConvertedParamsFunc; typedef typename MaybeWrapReturn::Func diff --git a/upb/handlers.c b/upb/handlers.c index fd81b03..ba27b98 100644 --- a/upb/handlers.c +++ b/upb/handlers.c @@ -286,6 +286,10 @@ const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h, const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; } +bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) { + return upb_handlercache_addcleanup(h->cache, p, func); +} + upb_handlertype_t upb_handlers_getprimitivehandlertype(const upb_fielddef *f) { switch (upb_fielddef_type(f)) { case UPB_TYPE_INT32: @@ -470,12 +474,13 @@ void upb_handlercache_free(upb_handlercache *cache) { upb_gfree(cache); } -bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) { +bool upb_handlercache_addcleanup(upb_handlercache *c, void *p, + upb_handlerfree *func) { bool ok; - if (upb_inttable_lookupptr(&h->cache->cleanup_, p, NULL)) { + if (upb_inttable_lookupptr(&c->cleanup_, p, NULL)) { return false; } - ok = upb_inttable_insertptr(&h->cache->cleanup_, p, upb_value_fptr(func)); + ok = upb_inttable_insertptr(&c->cleanup_, p, upb_value_fptr(func)); UPB_ASSERT(ok); return true; } diff --git a/upb/handlers.h b/upb/handlers.h index 4558786..44cad18 100644 --- a/upb/handlers.h +++ b/upb/handlers.h @@ -602,6 +602,8 @@ upb_handlercache *upb_handlercache_new(upb_handlers_callback *callback, void upb_handlercache_free(upb_handlercache *cache); const upb_handlers *upb_handlercache_get(upb_handlercache *cache, const upb_msgdef *md); +bool upb_handlercache_addcleanup(upb_handlercache *h, void *p, + upb_handlerfree *hfree); UPB_END_EXTERN_C diff --git a/upb/json/parser.c b/upb/json/parser.c index 4bc9163..1dac800 100644 --- a/upb/json/parser.c +++ b/upb/json/parser.c @@ -301,13 +301,13 @@ static void json_parser_any_frame_set_payload_type( /* Initialize encoder. */ h = upb_handlercache_get(frame->encoder_handlercache, payload_type); - encoder = upb_pb_encoder_create(p->env, h, &frame->stringsink.sink); + encoder = upb_pb_encoder_create(p->env, h, frame->stringsink.sink); /* Initialize parser. */ parser_method = upb_json_codecache_get(frame->parser_codecache, payload_type); upb_sink_reset(&frame->sink, h, encoder); frame->parser = upb_json_parser_create(p->env, parser_method, p->symtab, - &frame->sink, p->ignore_json_unknown); + frame->sink, p->ignore_json_unknown); } static void json_parser_any_frame_free(upb_jsonparser_any_frame *frame) { @@ -383,9 +383,12 @@ static bool check_stack(upb_json_parser *p) { static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) { upb_value v; const upb_json_codecache *cache = p->method->cache; - bool ok = upb_inttable_lookupptr(&cache->methods, frame->m, &v); - const upb_json_parsermethod *method = upb_value_getptr(v); + bool ok; + const upb_json_parsermethod *method; + + ok = upb_inttable_lookupptr(&cache->methods, frame->m, &v); UPB_ASSERT(ok); + method = upb_value_getconstptr(v); frame->name_table = &method->name_table; } @@ -1287,7 +1290,7 @@ static bool end_any_stringval(upb_json_parser *p) { } json_parser_any_frame_set_payload_type(p, p->top->any_frame, payload_type); - + return true; } else { upb_status_seterrf( @@ -2416,11 +2419,11 @@ static bool is_string_wrapper_object(upb_json_parser *p) { * final state once, when the closing '"' is seen. */ -#line 2578 "upb/json/parser.rl" +#line 2581 "upb/json/parser.rl" -#line 2424 "upb/json/parser.c" +#line 2427 "upb/json/parser.c" static const char _json_actions[] = { 0, 1, 0, 1, 1, 1, 3, 1, 4, 1, 6, 1, 7, 1, 8, 1, @@ -2667,7 +2670,7 @@ static const int json_en_value_machine = 75; static const int json_en_main = 1; -#line 2581 "upb/json/parser.rl" +#line 2584 "upb/json/parser.rl" size_t parse(void *closure, const void *hd, const char *buf, size_t size, const upb_bufhandle *handle) { @@ -2690,7 +2693,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size, capture_resume(parser, buf); -#line 2694 "upb/json/parser.c" +#line 2697 "upb/json/parser.c" { int _klen; unsigned int _trans; @@ -2765,83 +2768,83 @@ _match: switch ( *_acts++ ) { case 1: -#line 2429 "upb/json/parser.rl" +#line 2432 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 2: -#line 2431 "upb/json/parser.rl" +#line 2434 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 23;goto _again;} } break; case 3: -#line 2435 "upb/json/parser.rl" +#line 2438 "upb/json/parser.rl" { start_text(parser, p); } break; case 4: -#line 2436 "upb/json/parser.rl" +#line 2439 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_text(parser, p)); } break; case 5: -#line 2442 "upb/json/parser.rl" +#line 2445 "upb/json/parser.rl" { start_hex(parser); } break; case 6: -#line 2443 "upb/json/parser.rl" +#line 2446 "upb/json/parser.rl" { hexdigit(parser, p); } break; case 7: -#line 2444 "upb/json/parser.rl" +#line 2447 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_hex(parser)); } break; case 8: -#line 2450 "upb/json/parser.rl" +#line 2453 "upb/json/parser.rl" { CHECK_RETURN_TOP(escape(parser, p)); } break; case 9: -#line 2456 "upb/json/parser.rl" +#line 2459 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 10: -#line 2468 "upb/json/parser.rl" +#line 2471 "upb/json/parser.rl" { start_duration_base(parser, p); } break; case 11: -#line 2469 "upb/json/parser.rl" +#line 2472 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_duration_base(parser, p)); } break; case 12: -#line 2471 "upb/json/parser.rl" +#line 2474 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 13: -#line 2476 "upb/json/parser.rl" +#line 2479 "upb/json/parser.rl" { start_timestamp_base(parser, p); } break; case 14: -#line 2477 "upb/json/parser.rl" +#line 2480 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_base(parser, p)); } break; case 15: -#line 2479 "upb/json/parser.rl" +#line 2482 "upb/json/parser.rl" { start_timestamp_fraction(parser, p); } break; case 16: -#line 2480 "upb/json/parser.rl" +#line 2483 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); } break; case 17: -#line 2482 "upb/json/parser.rl" +#line 2485 "upb/json/parser.rl" { start_timestamp_zone(parser, p); } break; case 18: -#line 2483 "upb/json/parser.rl" +#line 2486 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); } break; case 19: -#line 2485 "upb/json/parser.rl" +#line 2488 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 20: -#line 2490 "upb/json/parser.rl" +#line 2493 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) { {stack[top++] = cs; cs = 47;goto _again;} @@ -2853,11 +2856,11 @@ _match: } break; case 21: -#line 2501 "upb/json/parser.rl" +#line 2504 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 75;goto _again;} } break; case 22: -#line 2506 "upb/json/parser.rl" +#line 2509 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { start_any_member(parser, p); @@ -2867,11 +2870,11 @@ _match: } break; case 23: -#line 2513 "upb/json/parser.rl" +#line 2516 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_membername(parser)); } break; case 24: -#line 2516 "upb/json/parser.rl" +#line 2519 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { end_any_member(parser, p); @@ -2881,7 +2884,7 @@ _match: } break; case 25: -#line 2527 "upb/json/parser.rl" +#line 2530 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { start_any_object(parser, p); @@ -2891,7 +2894,7 @@ _match: } break; case 26: -#line 2536 "upb/json/parser.rl" +#line 2539 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { CHECK_RETURN_TOP(end_any_object(parser, p)); @@ -2901,54 +2904,54 @@ _match: } break; case 27: -#line 2548 "upb/json/parser.rl" +#line 2551 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_array(parser)); } break; case 28: -#line 2552 "upb/json/parser.rl" +#line 2555 "upb/json/parser.rl" { end_array(parser); } break; case 29: -#line 2557 "upb/json/parser.rl" +#line 2560 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_number(parser, p)); } break; case 30: -#line 2558 "upb/json/parser.rl" +#line 2561 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 31: -#line 2560 "upb/json/parser.rl" +#line 2563 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_stringval(parser)); } break; case 32: -#line 2561 "upb/json/parser.rl" +#line 2564 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_stringval(parser)); } break; case 33: -#line 2563 "upb/json/parser.rl" +#line 2566 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, true)); } break; case 34: -#line 2565 "upb/json/parser.rl" +#line 2568 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, false)); } break; case 35: -#line 2567 "upb/json/parser.rl" +#line 2570 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_null(parser)); } break; case 36: -#line 2569 "upb/json/parser.rl" +#line 2572 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_subobject_full(parser)); } break; case 37: -#line 2570 "upb/json/parser.rl" +#line 2573 "upb/json/parser.rl" { end_subobject_full(parser); } break; case 38: -#line 2575 "upb/json/parser.rl" +#line 2578 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; -#line 2952 "upb/json/parser.c" +#line 2955 "upb/json/parser.c" } } @@ -2965,32 +2968,32 @@ _again: while ( __nacts-- > 0 ) { switch ( *__acts++ ) { case 0: -#line 2427 "upb/json/parser.rl" +#line 2430 "upb/json/parser.rl" { p--; {cs = stack[--top]; if ( p == pe ) goto _test_eof; goto _again;} } break; case 30: -#line 2558 "upb/json/parser.rl" +#line 2561 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 33: -#line 2563 "upb/json/parser.rl" +#line 2566 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, true)); } break; case 34: -#line 2565 "upb/json/parser.rl" +#line 2568 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, false)); } break; case 35: -#line 2567 "upb/json/parser.rl" +#line 2570 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_null(parser)); } break; case 37: -#line 2570 "upb/json/parser.rl" +#line 2573 "upb/json/parser.rl" { end_subobject_full(parser); } break; -#line 2994 "upb/json/parser.c" +#line 2997 "upb/json/parser.c" } } } @@ -2998,7 +3001,7 @@ goto _again;} } _out: {} } -#line 2603 "upb/json/parser.rl" +#line 2606 "upb/json/parser.rl" if (p != pe) { upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p); @@ -3046,13 +3049,13 @@ static void json_parser_reset(upb_json_parser *p) { /* Emit Ragel initialization of the parser. */ -#line 3050 "upb/json/parser.c" +#line 3053 "upb/json/parser.c" { cs = json_start; top = 0; } -#line 2650 "upb/json/parser.rl" +#line 2653 "upb/json/parser.rl" p->current_state = cs; p->parser_top = top; accumulate_clear(p); @@ -3067,7 +3070,7 @@ static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c, upb_msg_field_iter i; upb_alloc *alloc = upb_arena_alloc(&c->arena); - upb_json_parsermethod *m = upb_gmalloc(sizeof(*m)); + upb_json_parsermethod *m = upb_malloc(alloc, sizeof(*m)); m->cache = c; @@ -3090,7 +3093,7 @@ static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c, size_t len = upb_fielddef_getjsonname(f, NULL, 0); buf = upb_malloc(alloc, len); upb_fielddef_getjsonname(f, buf, len); - upb_strtable_insert3(&m->name_table, buf, len, v, alloc); + upb_strtable_insert3(&m->name_table, buf, strlen(buf), v, alloc); if (strcmp(buf, upb_fielddef_name(f)) != 0) { /* Since the JSON name is different from the regular field name, add an @@ -3109,7 +3112,7 @@ static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c, upb_json_parser *upb_json_parser_create(upb_env *env, const upb_json_parsermethod *method, const upb_symtab* symtab, - upb_sink *output, + upb_sink output, bool ignore_json_unknown) { #ifndef NDEBUG const size_t size_before = upb_env_bytesallocated(env); @@ -3125,8 +3128,8 @@ upb_json_parser *upb_json_parser_create(upb_env *env, upb_bytessink_reset(&p->input_, &method->input_handler_, p); json_parser_reset(p); - upb_sink_reset(&p->top->sink, output->handlers, output->closure); - p->top->m = upb_handlers_msgdef(output->handlers); + p->top->sink = output; + p->top->m = upb_handlers_msgdef(output.handlers); if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) { p->top->is_any = true; p->top->any_frame = json_parser_any_frame_new(p); @@ -3146,8 +3149,8 @@ upb_json_parser *upb_json_parser_create(upb_env *env, return p; } -upb_bytessink *upb_json_parser_input(upb_json_parser *p) { - return &p->input_; +upb_bytessink upb_json_parser_input(upb_json_parser *p) { + return p->input_; } const upb_byteshandler *upb_json_parsermethod_inputhandler( @@ -3174,21 +3177,22 @@ void upb_json_codecache_free(upb_json_codecache *c) { upb_gfree(c); } -upb_json_parsermethod *upb_json_codecache_get(upb_json_codecache *c, - const upb_msgdef *md) { +const upb_json_parsermethod *upb_json_codecache_get(upb_json_codecache *c, + const upb_msgdef *md) { upb_json_parsermethod *m; upb_value v; upb_msg_field_iter i; + upb_alloc *alloc = upb_arena_alloc(&c->arena); if (upb_inttable_lookupptr(&c->methods, md, &v)) { - return upb_value_getptr(v); + return upb_value_getconstptr(v); } m = parsermethod_new(c, md); - v = upb_value_ptr(m); + v = upb_value_constptr(m); if (!m) return NULL; - if (!upb_inttable_insertptr(&c->methods, m, v)) return NULL; + if (!upb_inttable_insertptr2(&c->methods, md, v, alloc)) return NULL; /* Populate parser methods for all submessages, so the name tables will * be available during parsing. */ diff --git a/upb/json/parser.h b/upb/json/parser.h index d5ec396..d1a1471 100644 --- a/upb/json/parser.h +++ b/upb/json/parser.h @@ -14,17 +14,44 @@ namespace upb { namespace json { class CodeCache; -class Parser; -class ParserMethod; +class ParserPtr; +class ParserMethodPtr; } /* namespace json */ } /* namespace upb */ #endif -UPB_DECLARE_TYPE(upb::json::Parser, upb_json_parser) -UPB_DECLARE_TYPE(upb::json::ParserMethod, upb_json_parsermethod) -UPB_DECLARE_TYPE(upb::json::CodeCache, upb_json_codecache) +/* upb_json_parsermethod ******************************************************/ -/* upb::json::Parser **********************************************************/ +struct upb_json_parsermethod; +typedef struct upb_json_parsermethod upb_json_parsermethod; + +UPB_BEGIN_EXTERN_C + +const upb_byteshandler* upb_json_parsermethod_inputhandler( + const upb_json_parsermethod* m); + +UPB_END_EXTERN_C + +#ifdef __cplusplus + +class upb::json::ParserMethodPtr { + public: + ParserMethodPtr() : ptr_(nullptr) {} + ParserMethodPtr(const upb_json_parsermethod* ptr) : ptr_(ptr) {} + + const upb_json_parsermethod* ptr() const { return ptr_; } + + const BytesHandler* input_handler() const { + return upb_json_parsermethod_inputhandler(ptr()); + } + + private: + const upb_json_parsermethod* ptr_; +}; + +#endif /* __cplusplus */ + +/* upb_json_parser ************************************************************/ /* Preallocation hint: parser won't allocate more bytes than this when first * constructed. This hint may be an overestimate for some build configurations. @@ -32,89 +59,72 @@ UPB_DECLARE_TYPE(upb::json::CodeCache, upb_json_codecache) * it may be an underestimate. */ #define UPB_JSON_PARSER_SIZE 5712 +struct upb_json_parser; +typedef struct upb_json_parser upb_json_parser; + +UPB_BEGIN_EXTERN_C + +upb_json_parser* +upb_json_parser_create(upb_env* e, const upb_json_parsermethod* m, + const upb_symtab* symtab, upb_sink output, + bool ignore_json_unknown); +upb_bytessink upb_json_parser_input(upb_json_parser* p); + +UPB_END_EXTERN_C + #ifdef __cplusplus /* Parses an incoming BytesStream, pushing the results to the destination * sink. */ -class upb::json::Parser { +class upb::json::ParserPtr { public: - static Parser* Create(Environment* env, const ParserMethod* method, - const SymbolTable* symtab, - Sink* output, bool ignore_json_unknown); + ParserPtr(upb_json_parser* ptr) : ptr_(ptr) {} - BytesSink* input(); + static ParserPtr Create(Environment* env, ParserMethodPtr method, + SymbolTable* symtab, Sink output, + bool ignore_json_unknown) { + upb_symtab* symtab_ptr = symtab ? symtab->ptr() : nullptr; + return ParserPtr(upb_json_parser_create( + env, method.ptr(), symtab_ptr, output.sink(), ignore_json_unknown)); + } - private: - UPB_DISALLOW_POD_OPS(Parser, upb::json::Parser) -}; - -class upb::json::ParserMethod { - public: - /* The input handlers for this decoder method. */ - const BytesHandler* input_handler() const; + BytesSink input() { return upb_json_parser_input(ptr_); } private: - UPB_DISALLOW_POD_OPS(ParserMethod, upb::json::ParserMethod) + upb_json_parser* ptr_; }; -class upb::json::CodeCache { - public: - static CodeCache* New(); - static void Free(CodeCache* cache); - - /* Returns a DecoderMethod that can push data to the given handlers. - * If a suitable method already exists, it will be returned from the cache. */ - const ParserMethod *Get(const MessageDef* md); +#endif /* __cplusplus */ - private: - UPB_DISALLOW_POD_OPS(CodeCache, upb::json::CodeCache) -}; +/* upb_json_codecache *********************************************************/ -#endif +struct upb_json_codecache; +typedef struct upb_json_codecache upb_json_codecache; UPB_BEGIN_EXTERN_C -upb_json_parser* upb_json_parser_create(upb_env* e, - const upb_json_parsermethod* m, - const upb_symtab* symtab, - upb_sink* output, - bool ignore_json_unknown); -upb_bytessink *upb_json_parser_input(upb_json_parser *p); - -const upb_byteshandler *upb_json_parsermethod_inputhandler( - const upb_json_parsermethod *m); - upb_json_codecache *upb_json_codecache_new(); void upb_json_codecache_free(upb_json_codecache *cache); -upb_json_parsermethod* upb_json_codecache_get(upb_json_codecache* cache, - const upb_msgdef* md); +const upb_json_parsermethod* upb_json_codecache_get(upb_json_codecache* cache, + const upb_msgdef* md); UPB_END_EXTERN_C #ifdef __cplusplus -namespace upb { -namespace json { -inline Parser* Parser::Create(Environment* env, const ParserMethod* method, - const SymbolTable* symtab, - Sink* output, bool ignore_json_unknown) { - return upb_json_parser_create( - env, method, symtab, output, ignore_json_unknown); -} -inline BytesSink* Parser::input() { - return upb_json_parser_input(this); -} - -inline const BytesHandler* ParserMethod::input_handler() const { - return upb_json_parsermethod_inputhandler(this); -} -/* static */ -inline const ParserMethod* CodeCache::Get(const MessageDef* md) { - return upb_json_codecache_get(this, md); -} +class upb::json::CodeCache { + public: + CodeCache() : ptr_(upb_json_codecache_new(), upb_json_codecache_free) {} -} /* namespace json */ -} /* namespace upb */ + /* Returns a DecoderMethod that can push data to the given handlers. + * If a suitable method already exists, it will be returned from the cache. */ + ParserMethodPtr Get(MessageDefPtr md) { + return upb_json_codecache_get(ptr_.get(), md.ptr()); + } + + private: + std::unique_ptr ptr_; +}; #endif diff --git a/upb/json/parser.rl b/upb/json/parser.rl index c2866c9..05a9505 100644 --- a/upb/json/parser.rl +++ b/upb/json/parser.rl @@ -299,13 +299,13 @@ static void json_parser_any_frame_set_payload_type( /* Initialize encoder. */ h = upb_handlercache_get(frame->encoder_handlercache, payload_type); - encoder = upb_pb_encoder_create(p->env, h, &frame->stringsink.sink); + encoder = upb_pb_encoder_create(p->env, h, frame->stringsink.sink); /* Initialize parser. */ parser_method = upb_json_codecache_get(frame->parser_codecache, payload_type); upb_sink_reset(&frame->sink, h, encoder); frame->parser = upb_json_parser_create(p->env, parser_method, p->symtab, - &frame->sink, p->ignore_json_unknown); + frame->sink, p->ignore_json_unknown); } static void json_parser_any_frame_free(upb_jsonparser_any_frame *frame) { @@ -381,9 +381,12 @@ static bool check_stack(upb_json_parser *p) { static void set_name_table(upb_json_parser *p, upb_jsonparser_frame *frame) { upb_value v; const upb_json_codecache *cache = p->method->cache; - bool ok = upb_inttable_lookupptr(&cache->methods, frame->m, &v); - const upb_json_parsermethod *method = upb_value_getptr(v); + bool ok; + const upb_json_parsermethod *method; + + ok = upb_inttable_lookupptr(&cache->methods, frame->m, &v); UPB_ASSERT(ok); + method = upb_value_getconstptr(v); frame->name_table = &method->name_table; } @@ -1285,7 +1288,7 @@ static bool end_any_stringval(upb_json_parser *p) { } json_parser_any_frame_set_payload_type(p, p->top->any_frame, payload_type); - + return true; } else { upb_status_seterrf( @@ -2661,7 +2664,7 @@ static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c, upb_msg_field_iter i; upb_alloc *alloc = upb_arena_alloc(&c->arena); - upb_json_parsermethod *m = upb_gmalloc(sizeof(*m)); + upb_json_parsermethod *m = upb_malloc(alloc, sizeof(*m)); m->cache = c; @@ -2684,7 +2687,7 @@ static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c, size_t len = upb_fielddef_getjsonname(f, NULL, 0); buf = upb_malloc(alloc, len); upb_fielddef_getjsonname(f, buf, len); - upb_strtable_insert3(&m->name_table, buf, len, v, alloc); + upb_strtable_insert3(&m->name_table, buf, strlen(buf), v, alloc); if (strcmp(buf, upb_fielddef_name(f)) != 0) { /* Since the JSON name is different from the regular field name, add an @@ -2703,7 +2706,7 @@ static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c, upb_json_parser *upb_json_parser_create(upb_env *env, const upb_json_parsermethod *method, const upb_symtab* symtab, - upb_sink *output, + upb_sink output, bool ignore_json_unknown) { #ifndef NDEBUG const size_t size_before = upb_env_bytesallocated(env); @@ -2719,8 +2722,8 @@ upb_json_parser *upb_json_parser_create(upb_env *env, upb_bytessink_reset(&p->input_, &method->input_handler_, p); json_parser_reset(p); - upb_sink_reset(&p->top->sink, output->handlers, output->closure); - p->top->m = upb_handlers_msgdef(output->handlers); + p->top->sink = output; + p->top->m = upb_handlers_msgdef(output.handlers); if (is_wellknown_msg(p, UPB_WELLKNOWN_ANY)) { p->top->is_any = true; p->top->any_frame = json_parser_any_frame_new(p); @@ -2740,8 +2743,8 @@ upb_json_parser *upb_json_parser_create(upb_env *env, return p; } -upb_bytessink *upb_json_parser_input(upb_json_parser *p) { - return &p->input_; +upb_bytessink upb_json_parser_input(upb_json_parser *p) { + return p->input_; } const upb_byteshandler *upb_json_parsermethod_inputhandler( @@ -2768,21 +2771,22 @@ void upb_json_codecache_free(upb_json_codecache *c) { upb_gfree(c); } -upb_json_parsermethod *upb_json_codecache_get(upb_json_codecache *c, - const upb_msgdef *md) { +const upb_json_parsermethod *upb_json_codecache_get(upb_json_codecache *c, + const upb_msgdef *md) { upb_json_parsermethod *m; upb_value v; upb_msg_field_iter i; + upb_alloc *alloc = upb_arena_alloc(&c->arena); if (upb_inttable_lookupptr(&c->methods, md, &v)) { - return upb_value_getptr(v); + return upb_value_getconstptr(v); } m = parsermethod_new(c, md); - v = upb_value_ptr(m); + v = upb_value_constptr(m); if (!m) return NULL; - if (!upb_inttable_insertptr(&c->methods, m, v)) return NULL; + if (!upb_inttable_insertptr2(&c->methods, md, v, alloc)) return NULL; /* Populate parser methods for all submessages, so the name tables will * be available during parsing. */ diff --git a/upb/json/printer.c b/upb/json/printer.c index b2c9ebd..83f1a58 100644 --- a/upb/json/printer.c +++ b/upb/json/printer.c @@ -13,7 +13,7 @@ struct upb_json_printer { upb_sink input_; /* BytesSink closure. */ void *subc_; - upb_bytessink *output_; + upb_bytessink output_; /* We track the depth so that we know when to emit startstr/endstr on the * output. */ @@ -87,7 +87,7 @@ strpc *newstrpc_str(upb_handlers *h, const char * str) { static void print_data( upb_json_printer *p, const char *buf, unsigned int len) { /* TODO: Will need to change if we support pushback from the sink. */ - size_t n = upb_bytessink_putbuf(p->output_, p->subc_, buf, len, NULL); + size_t n = upb_bytessink_putbuf(&p->output_, p->subc_, buf, len, NULL); UPB_ASSERT(n == len); } @@ -369,7 +369,7 @@ static bool printer_startmsg(void *closure, const void *handler_data) { upb_json_printer *p = closure; UPB_UNUSED(handler_data); if (p->depth_ == 0) { - upb_bytessink_start(p->output_, 0, &p->subc_); + upb_bytessink_start(&p->output_, 0, &p->subc_); } start_frame(p); return true; @@ -381,7 +381,7 @@ static bool printer_endmsg(void *closure, const void *handler_data, upb_status * UPB_UNUSED(s); end_frame(p); if (p->depth_ == 0) { - upb_bytessink_end(p->output_); + upb_bytessink_end(&p->output_); } return true; } @@ -770,7 +770,7 @@ static bool printer_startdurationmsg(void *closure, const void *handler_data) { upb_json_printer *p = closure; UPB_UNUSED(handler_data); if (p->depth_ == 0) { - upb_bytessink_start(p->output_, 0, &p->subc_); + upb_bytessink_start(&p->output_, 0, &p->subc_); } return true; } @@ -828,7 +828,7 @@ static bool printer_enddurationmsg(void *closure, const void *handler_data, print_data(p, "\"", 1); if (p->depth_ == 0) { - upb_bytessink_end(p->output_); + upb_bytessink_end(&p->output_); } UPB_UNUSED(handler_data); @@ -839,7 +839,7 @@ static bool printer_starttimestampmsg(void *closure, const void *handler_data) { upb_json_printer *p = closure; UPB_UNUSED(handler_data); if (p->depth_ == 0) { - upb_bytessink_start(p->output_, 0, &p->subc_); + upb_bytessink_start(&p->output_, 0, &p->subc_); } return true; } @@ -902,7 +902,7 @@ static bool printer_endtimestampmsg(void *closure, const void *handler_data, print_data(p, "\"", 1); if (p->depth_ == 0) { - upb_bytessink_end(p->output_); + upb_bytessink_end(&p->output_); } UPB_UNUSED(handler_data); @@ -914,7 +914,7 @@ static bool printer_startmsg_noframe(void *closure, const void *handler_data) { upb_json_printer *p = closure; UPB_UNUSED(handler_data); if (p->depth_ == 0) { - upb_bytessink_start(p->output_, 0, &p->subc_); + upb_bytessink_start(&p->output_, 0, &p->subc_); } return true; } @@ -925,7 +925,7 @@ static bool printer_endmsg_noframe( UPB_UNUSED(handler_data); UPB_UNUSED(s); if (p->depth_ == 0) { - upb_bytessink_end(p->output_); + upb_bytessink_end(&p->output_); } return true; } @@ -1253,7 +1253,7 @@ static void json_printer_reset(upb_json_printer *p) { /* Public API *****************************************************************/ upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h, - upb_bytessink *output) { + upb_bytessink output) { #ifndef NDEBUG size_t size_before = upb_env_bytesallocated(e); #endif @@ -1273,12 +1273,16 @@ upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h, return p; } -upb_sink *upb_json_printer_input(upb_json_printer *p) { - return &p->input_; +upb_sink upb_json_printer_input(upb_json_printer *p) { + return p->input_; } upb_handlercache *upb_json_printer_newcache(bool preserve_proto_fieldnames) { upb_json_printercache *cache = upb_gmalloc(sizeof(*cache)); + upb_handlercache *ret = upb_handlercache_new(printer_sethandlers, cache); + cache->preserve_fieldnames = preserve_proto_fieldnames; - return upb_handlercache_new(printer_sethandlers, cache); + upb_handlercache_addcleanup(ret, cache, upb_gfree); + + return ret; } diff --git a/upb/json/printer.h b/upb/json/printer.h index fe9c8f1..a7a37bb 100644 --- a/upb/json/printer.h +++ b/upb/json/printer.h @@ -12,44 +12,24 @@ #ifdef __cplusplus namespace upb { namespace json { -class Printer; +class PrinterPtr; } /* namespace json */ } /* namespace upb */ #endif -UPB_DECLARE_TYPE(upb::json::Printer, upb_json_printer) - - -/* upb::json::Printer *********************************************************/ +/* upb_json_printer ***********************************************************/ #define UPB_JSON_PRINTER_SIZE 192 -#ifdef __cplusplus - -/* Prints an incoming stream of data to a BytesSink in JSON format. */ -class upb::json::Printer { - public: - static Printer* Create(Environment* env, const upb::Handlers* handlers, - BytesSink* output); - - /* The input to the printer. */ - Sink* input(); - - static const size_t kSize = UPB_JSON_PRINTER_SIZE; - static upb_handlercache* NewCache(bool preserve_proto_fieldnames); - - private: - UPB_DISALLOW_POD_OPS(Printer, upb::json::Printer) -}; - -#endif +struct upb_json_printer; +typedef struct upb_json_printer upb_json_printer; UPB_BEGIN_EXTERN_C /* Native C API. */ upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h, - upb_bytessink *output); -upb_sink *upb_json_printer_input(upb_json_printer *p); + upb_bytessink output); +upb_sink upb_json_printer_input(upb_json_printer *p); const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md, bool preserve_fieldnames, const void *owner); @@ -60,19 +40,29 @@ UPB_END_EXTERN_C #ifdef __cplusplus -namespace upb { -namespace json { -inline Printer* Printer::Create(Environment* env, const upb::Handlers* handlers, - BytesSink* output) { - return upb_json_printer_create(env, handlers, output); -} -inline Sink* Printer::input() { return upb_json_printer_input(this); } -inline upb_handlercache* Printer::NewCache(bool preserve_proto_fieldnames) { - return upb_json_printer_newcache(preserve_proto_fieldnames); -} -} /* namespace json */ -} /* namespace upb */ +/* Prints an incoming stream of data to a BytesSink in JSON format. */ +class upb::json::PrinterPtr { + public: + PrinterPtr(upb_json_printer* ptr) : ptr_(ptr) {} -#endif + static PrinterPtr Create(Environment *env, const upb::Handlers *handlers, + BytesSink output) { + return PrinterPtr(upb_json_printer_create(env, handlers, output.sink())); + } + + /* The input to the printer. */ + Sink input() { return upb_json_printer_input(ptr_); } + + static const size_t kSize = UPB_JSON_PRINTER_SIZE; + + static HandlerCache NewCache(bool preserve_proto_fieldnames) { + return upb_json_printer_newcache(preserve_proto_fieldnames); + } + + private: + upb_json_printer* ptr_; +}; + +#endif /* __cplusplus */ #endif /* UPB_JSON_TYPED_PRINTER_H_ */ diff --git a/upb/pb/decoder.c b/upb/pb/decoder.c index 0cae05b..cd64f72 100644 --- a/upb/pb/decoder.c +++ b/upb/pb/decoder.c @@ -993,7 +993,7 @@ void upb_pbdecoder_reset(upb_pbdecoder *d) { } upb_pbdecoder *upb_pbdecoder_create(upb_env *e, const upb_pbdecodermethod *m, - upb_sink *sink) { + upb_sink sink) { const size_t default_max_nesting = 64; #ifndef NDEBUG size_t size_before = upb_env_bytesallocated(e); @@ -1017,12 +1017,11 @@ upb_pbdecoder *upb_pbdecoder_create(upb_env *e, const upb_pbdecodermethod *m, upb_pbdecoder_reset(d); upb_bytessink_reset(&d->input_, &m->input_handler_, d); - UPB_ASSERT(sink); if (d->method_->dest_handlers_) { - if (sink->handlers != d->method_->dest_handlers_) + if (sink.handlers != d->method_->dest_handlers_) return NULL; } - upb_sink_reset(&d->top->sink, sink->handlers, sink->closure); + d->top->sink = sink; /* If this fails, increase the value in decoder.h. */ UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(e) - size_before <= @@ -1038,8 +1037,8 @@ const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d) { return d->method_; } -upb_bytessink *upb_pbdecoder_input(upb_pbdecoder *d) { - return &d->input_; +upb_bytessink upb_pbdecoder_input(upb_pbdecoder *d) { + return d->input_; } size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d) { diff --git a/upb/pb/decoder.h b/upb/pb/decoder.h index 1ffcb7d..ba381f3 100644 --- a/upb/pb/decoder.h +++ b/upb/pb/decoder.h @@ -56,6 +56,7 @@ UPB_END_EXTERN_C * Handlers. */ class upb::pb::DecoderMethodPtr { public: + DecoderMethodPtr() : ptr_(nullptr) {} DecoderMethodPtr(const upb_pbdecodermethod* ptr) : ptr_(ptr) {} const upb_pbdecodermethod* ptr() { return ptr_; } @@ -98,9 +99,9 @@ UPB_BEGIN_EXTERN_C upb_pbdecoder *upb_pbdecoder_create(upb_env *e, const upb_pbdecodermethod *method, - upb_sink *output); + upb_sink output); const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d); -upb_bytessink *upb_pbdecoder_input(upb_pbdecoder *d); +upb_bytessink upb_pbdecoder_input(upb_pbdecoder *d); uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d); size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d); bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max); @@ -124,8 +125,8 @@ class upb::pb::DecoderPtr { * * The sink must match the given method. */ static DecoderPtr Create(Environment *env, DecoderMethodPtr method, - upb_sink *output) { - return DecoderPtr(upb_pbdecoder_create(env, method.ptr(), output)); + upb::Sink output) { + return DecoderPtr(upb_pbdecoder_create(env, method.ptr(), output.sink())); } /* Returns the DecoderMethod this decoder is parsing from. */ @@ -134,7 +135,7 @@ class upb::pb::DecoderPtr { } /* The sink on which this decoder receives input. */ - upb_bytessink* input() { return upb_pbdecoder_input(ptr()); } + BytesSink input() { return BytesSink(upb_pbdecoder_input(ptr())); } /* Returns number of bytes successfully parsed. * diff --git a/upb/pb/encoder.c b/upb/pb/encoder.c index 3497007..1496eba 100644 --- a/upb/pb/encoder.c +++ b/upb/pb/encoder.c @@ -95,7 +95,7 @@ struct upb_pb_encoder { /* Our input and output. */ upb_sink input_; - upb_bytessink *output_; + upb_bytessink output_; /* The "subclosure" -- used as the inner closure as part of the bytessink * protocol. */ @@ -127,7 +127,7 @@ struct upb_pb_encoder { /* TODO(haberman): handle pushback */ static void putbuf(upb_pb_encoder *e, const char *buf, size_t len) { - size_t n = upb_bytessink_putbuf(e->output_, e->subc, buf, len, NULL); + size_t n = upb_bytessink_putbuf(&e->output_, e->subc, buf, len, NULL); UPB_ASSERT(n == len); } @@ -353,7 +353,7 @@ static bool startmsg(void *c, const void *hd) { upb_pb_encoder *e = c; UPB_UNUSED(hd); if (e->depth++ == 0) { - upb_bytessink_start(e->output_, 0, &e->subc); + upb_bytessink_start(&e->output_, 0, &e->subc); } return true; } @@ -363,7 +363,7 @@ static bool endmsg(void *c, const void *hd, upb_status *status) { UPB_UNUSED(hd); UPB_UNUSED(status); if (--e->depth == 0) { - upb_bytessink_end(e->output_); + upb_bytessink_end(&e->output_); } return true; } @@ -527,7 +527,7 @@ upb_handlercache *upb_pb_encoder_newcache() { } upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h, - upb_bytessink *output) { + upb_bytessink output) { const size_t initial_bufsize = 256; const size_t initial_segbufsize = 16; /* TODO(haberman): make this configurable. */ @@ -556,7 +556,7 @@ upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h, e->env = env; e->output_ = output; - e->subc = output->closure; + e->subc = output.closure; e->ptr = e->buf; /* If this fails, increase the value in encoder.h. */ @@ -565,4 +565,4 @@ upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h, return e; } -upb_sink *upb_pb_encoder_input(upb_pb_encoder *e) { return &e->input_; } +upb_sink upb_pb_encoder_input(upb_pb_encoder *e) { return e->input_; } diff --git a/upb/pb/encoder.h b/upb/pb/encoder.h index 20ce606..7aa2870 100644 --- a/upb/pb/encoder.h +++ b/upb/pb/encoder.h @@ -30,16 +30,16 @@ class EncoderPtr; * constructed. This hint may be an overestimate for some build configurations. * But if the decoder library is upgraded without recompiling the application, * it may be an underestimate. */ -#define UPB_PB_ENCODER_SIZE 768 +#define UPB_PB_ENCODER_SIZE 784 struct upb_pb_encoder; typedef struct upb_pb_encoder upb_pb_encoder; UPB_BEGIN_EXTERN_C -upb_sink *upb_pb_encoder_input(upb_pb_encoder *p); +upb_sink upb_pb_encoder_input(upb_pb_encoder *p); upb_pb_encoder* upb_pb_encoder_create(upb_env* e, const upb_handlers* h, - upb_bytessink* output); + upb_bytessink output); upb_handlercache *upb_pb_encoder_newcache(); @@ -56,12 +56,12 @@ class upb::pb::EncoderPtr { /* Creates a new encoder in the given environment. The Handlers must have * come from NewHandlers() below. */ static EncoderPtr Create(Environment* env, const Handlers* handlers, - BytesSink* output) { - return EncoderPtr(upb_pb_encoder_create(env, handlers, output->ptr())); + BytesSink output) { + return EncoderPtr(upb_pb_encoder_create(env, handlers, output.sink())); } /* The input to the encoder. */ - upb_sink* input() { return upb_pb_encoder_input(ptr()); } + upb::Sink input() { return upb_pb_encoder_input(ptr()); } /* Creates a new set of handlers for this MessageDef. */ static HandlerCache NewCache() { diff --git a/upb/sink.c b/upb/sink.c index d0197a6..6ef5718 100644 --- a/upb/sink.c +++ b/upb/sink.c @@ -1,17 +1,17 @@ #include "upb/sink.h" -bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink *sink) { +bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink sink) { void *subc; bool ret; upb_bufhandle handle = UPB_BUFHANDLE_INIT; handle.buf = buf; - ret = upb_bytessink_start(sink, len, &subc); + ret = upb_bytessink_start(&sink, len, &subc); if (ret && len != 0) { - ret = (upb_bytessink_putbuf(sink, subc, buf, len, &handle) >= len); + ret = (upb_bytessink_putbuf(&sink, subc, buf, len, &handle) >= len); } if (ret) { - ret = upb_bytessink_end(sink); + ret = upb_bytessink_end(&sink); } return ret; } diff --git a/upb/sink.h b/upb/sink.h index 8cab45d..1359c5e 100644 --- a/upb/sink.h +++ b/upb/sink.h @@ -237,6 +237,17 @@ class upb::Sink { /* Constructor with no initialization; must be Reset() before use. */ Sink() {} + Sink(const Sink&) = default; + Sink& operator=(const Sink&) = default; + + Sink(const upb_sink& sink) : sink_(sink) {} + Sink &operator=(const upb_sink &sink) { + sink_ = sink; + return *this; + } + + upb_sink sink() { return sink_; } + /* Constructs a new sink for the given frozen handlers and closure. * * TODO: once the Handlers know the expected closure type, verify that T @@ -406,7 +417,16 @@ class upb::BytesSink { public: BytesSink() {} - upb_bytessink* ptr() { return &sink_; } + BytesSink(const BytesSink&) = default; + BytesSink& operator=(const BytesSink&) = default; + + BytesSink(const upb_bytessink& sink) : sink_(sink) {} + BytesSink &operator=(const upb_bytessink &sink) { + sink_ = sink; + return *this; + } + + upb_bytessink sink() { return sink_; } /* Constructs a new sink for the given frozen handlers and closure. * @@ -444,15 +464,15 @@ class upb::BytesSink { UPB_BEGIN_EXTERN_C -bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink *sink); +bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink sink); UPB_END_EXTERN_C #ifdef __cplusplus namespace upb { -template bool PutBuffer(const T& str, upb_bytessink* sink) { - return upb_bufsrc_putbuf(str.c_str(), str.size(), sink); +template bool PutBuffer(const T& str, BytesSink sink) { + return upb_bufsrc_putbuf(str.c_str(), str.size(), sink.sink()); } } -- cgit v1.2.3 From cb26d883d1290ed258e5594454c2ffe0526b13f9 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Mon, 14 Jan 2019 10:56:58 -0800 Subject: WIP. --- google/protobuf/descriptor.upb.h | 8 +- tests/conformance_upb.c | 16 +-- tests/json/test_json.cc | 4 +- tests/pb/test_decoder.cc | 14 +-- tests/pb/test_encoder.cc | 9 +- tests/test_cpp.cc | 2 +- tests/test_util.h | 21 ++-- upb/bindings/lua/def.c | 9 +- upb/bindings/lua/msg.c | 13 +- upb/bindings/lua/upb/pb.c | 8 +- upb/decode.h | 8 +- upb/def.c | 41 ++++--- upb/def.h | 37 +++--- upb/encode.h | 8 +- upb/generated_util.h | 3 +- upb/handlers.c | 8 +- upb/handlers.h | 39 +++--- upb/json/parser.c | 259 ++++++++++++++++----------------------- upb/json/parser.h | 37 +++--- upb/json/parser.rl | 153 +++++++++-------------- upb/json/printer.c | 8 +- upb/json/printer.h | 14 ++- upb/msg.h | 28 ++--- upb/msgfactory.h | 12 +- upb/pb/compile_decoder.c | 2 +- upb/pb/decoder.c | 22 ++-- upb/pb/decoder.h | 28 +++-- upb/pb/decoder.int.h | 4 +- upb/pb/encoder.c | 22 ++-- upb/pb/encoder.h | 14 ++- upb/pb/textprinter.c | 26 ++-- upb/pb/textprinter.h | 75 +++++------- upb/sink.c | 70 ----------- upb/sink.h | 33 ++--- upb/table.int.h | 15 --- upb/upb.c | 75 +++++------- upb/upb.h | 161 +++++++++--------------- upbc/generator.cc | 8 +- 38 files changed, 555 insertions(+), 759 deletions(-) (limited to 'upb/bindings') diff --git a/google/protobuf/descriptor.upb.h b/google/protobuf/descriptor.upb.h index 32bccc7..7e62be5 100644 --- a/google/protobuf/descriptor.upb.h +++ b/google/protobuf/descriptor.upb.h @@ -16,7 +16,9 @@ #include "upb/decode.h" #include "upb/encode.h" #include "upb/port_def.inc" -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif struct google_protobuf_FileDescriptorSet; struct google_protobuf_FileDescriptorProto; @@ -1668,7 +1670,9 @@ UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_prot } -UPB_END_EXTERN_C +#ifdef __cplusplus +} /* extern "C" */ +#endif #include "upb/port_undef.inc" diff --git a/tests/conformance_upb.c b/tests/conformance_upb.c index e0a7d8c..cefac4c 100644 --- a/tests/conformance_upb.c +++ b/tests/conformance_upb.c @@ -130,7 +130,7 @@ void DoTest( } bool DoTestIo() { - upb_arena arena; + upb_arena *arena; upb_alloc *alloc; upb_status status; char *serialized_input; @@ -145,8 +145,8 @@ bool DoTestIo() { return false; } - upb_arena_init(&arena); - alloc = upb_arena_alloc(&arena); + arena = upb_arena_new(); + alloc = upb_arena_alloc(arena); serialized_input = upb_malloc(alloc, input_size); if (!CheckedRead(STDIN_FILENO, serialized_input, input_size)) { @@ -155,24 +155,26 @@ bool DoTestIo() { } request = conformance_ConformanceRequest_parsenew( - upb_stringview_make(serialized_input, input_size), &arena); - response = conformance_ConformanceResponse_new(&arena); + upb_stringview_make(serialized_input, input_size), arena); + response = conformance_ConformanceResponse_new(arena); if (request) { - DoTest(request, response, &arena); + DoTest(request, response, arena); } else { fprintf(stderr, "conformance_upb: parse of ConformanceRequest failed: %s\n", upb_status_errmsg(&status)); } serialized_output = conformance_ConformanceResponse_serialize( - response, &arena, &output_size); + response, arena, &output_size); CheckedWrite(STDOUT_FILENO, &output_size, sizeof(uint32_t)); CheckedWrite(STDOUT_FILENO, serialized_output, output_size); test_count++; + upb_arena_free(arena); + return true; } diff --git a/tests/json/test_json.cc b/tests/json/test_json.cc index b0fd3e3..1f7d364 100644 --- a/tests/json/test_json.cc +++ b/tests/json/test_json.cc @@ -174,9 +174,9 @@ void test_json_roundtrip_message(const char* json_src, VerboseParserEnvironment env(verbose); StringSink data_sink; upb::json::PrinterPtr printer = upb::json::PrinterPtr::Create( - env.env(), serialize_handlers, data_sink.Sink()); + env.arena(), serialize_handlers, data_sink.Sink()); upb::json::ParserPtr parser = upb::json::ParserPtr::Create( - env.env(), parser_method, NULL, printer.input(), false); + env.arena(), parser_method, NULL, printer.input(), false); env.ResetBytesSink(parser.input()); env.Reset(json_src, strlen(json_src), false, false); diff --git a/tests/pb/test_decoder.cc b/tests/pb/test_decoder.cc index ec7a788..b2dd812 100644 --- a/tests/pb/test_decoder.cc +++ b/tests/pb/test_decoder.cc @@ -452,10 +452,10 @@ void callback(const void *closure, upb::Handlers* h_ptr) { const upb::Handlers *global_handlers; upb::pb::DecoderMethodPtr global_method; -upb::pb::DecoderPtr CreateDecoder(upb::Environment* env, +upb::pb::DecoderPtr CreateDecoder(upb::Arena* arena, upb::pb::DecoderMethodPtr method, upb::Sink sink) { - upb::pb::DecoderPtr ret = upb::pb::DecoderPtr::Create(env, method, sink); + upb::pb::DecoderPtr ret = upb::pb::DecoderPtr::Create(arena, method, sink); ret.set_max_nesting(MAX_NESTING); return ret; } @@ -556,7 +556,7 @@ void do_run_decoder(VerboseParserEnvironment* env, upb::pb::DecoderPtr decoder, void run_decoder(const string& proto, const string* expected_output) { VerboseParserEnvironment env(filter_hash != 0); upb::Sink sink(global_handlers, &closures[0]); - upb::pb::DecoderPtr decoder = CreateDecoder(env.env(), global_method, sink); + upb::pb::DecoderPtr decoder = CreateDecoder(env.arena(), global_method, sink); env.ResetBytesSink(decoder.input()); for (size_t i = 0; i < proto.size(); i++) { for (size_t j = i; j < UPB_MIN(proto.size(), i + 5); j++) { @@ -872,10 +872,9 @@ void test_valid() { if (!filter_hash || filter_hash == testhash) { testhash = emptyhash; upb::Status status; - upb::Environment env; - env.ReportErrorsTo(&status); + upb::Arena arena; upb::Sink sink(global_handlers, &closures[0]); - upb::pb::DecoderPtr decoder = CreateDecoder(&env, global_method, sink); + upb::pb::DecoderPtr decoder = CreateDecoder(&arena, global_method, sink); output.clear(); bool ok = upb::PutBuffer(std::string(), decoder.input()); ASSERT(ok); @@ -1161,7 +1160,8 @@ void test_emptyhandlers(upb::SymbolTable* symtab, bool allowjit) { for (int i = 0; testdata[i].data; i++) { VerboseParserEnvironment env(filter_hash != 0); upb::Sink sink(global_method.dest_handlers(), &closures[0]); - upb::pb::DecoderPtr decoder = CreateDecoder(env.env(), global_method, sink); + upb::pb::DecoderPtr decoder = + CreateDecoder(env.arena(), global_method, sink); env.ResetBytesSink(decoder.input()); env.Reset(testdata[i].data, testdata[i].length, true, false); ASSERT(env.Start()); diff --git a/tests/pb/test_encoder.cc b/tests/pb/test_encoder.cc index 35c0e1e..7145097 100644 --- a/tests/pb/test_encoder.cc +++ b/tests/pb/test_encoder.cc @@ -24,7 +24,7 @@ void test_pb_roundtrip() { upb::Arena arena; google_protobuf_FileDescriptorSet *set = google_protobuf_FileDescriptorSet_parsenew( - upb_stringview_make(input.c_str(), input.size()), &arena); + upb_stringview_make(input.c_str(), input.size()), arena.ptr()); ASSERT(set); size_t n; const google_protobuf_FileDescriptorProto *const *files = @@ -33,7 +33,7 @@ void test_pb_roundtrip() { upb::Status status; bool ok = symtab.AddFile(files[0], &status); if (!ok) { - fprintf(stderr, "Error building def: %s\n", upb_status_errmsg(&status)); + fprintf(stderr, "Error building def: %s\n", status.error_message()); ASSERT(false); } upb::MessageDefPtr md = @@ -43,13 +43,12 @@ void test_pb_roundtrip() { ASSERT(encoder_handlers); const upb::pb::DecoderMethodPtr method = decoder_cache.Get(md); - upb::InlinedEnvironment<512> env; std::string output; upb::StringSink string_sink(&output); upb::pb::EncoderPtr encoder = - upb::pb::EncoderPtr::Create(&env, encoder_handlers, string_sink.input()); + upb::pb::EncoderPtr::Create(&arena, encoder_handlers, string_sink.input()); upb::pb::DecoderPtr decoder = - upb::pb::DecoderPtr::Create(&env, method, encoder.input()); + upb::pb::DecoderPtr::Create(&arena, method, encoder.input()); ok = upb::PutBuffer(input, decoder.input()); ASSERT(ok); ASSERT(input == output); diff --git a/tests/test_cpp.cc b/tests/test_cpp.cc index a5bfbc7..5e9a8dd 100644 --- a/tests/test_cpp.cc +++ b/tests/test_cpp.cc @@ -672,7 +672,7 @@ void DoNothingStringBufHandler(C* closure, const char *buf, size_t len) { } template -void DoNothingEndMessageHandler(C* closure, upb::Status *status) { +void DoNothingEndMessageHandler(C* closure, upb_status *status) { UPB_UNUSED(closure); UPB_UNUSED(status); } diff --git a/tests/test_util.h b/tests/test_util.h index 0b5ddd4..04ca3fb 100644 --- a/tests/test_util.h +++ b/tests/test_util.h @@ -30,15 +30,11 @@ upb_bufhandle global_handle; class VerboseParserEnvironment { public: /* Pass verbose=true to print detailed diagnostics to stderr. */ - VerboseParserEnvironment(bool verbose) : verbose_(verbose) { - env_.SetErrorFunction(&VerboseParserEnvironment::OnError, this); - } + VerboseParserEnvironment(bool verbose) : verbose_(verbose) {} static bool OnError(void *ud, const upb::Status* status) { VerboseParserEnvironment* env = static_cast(ud); - env->saw_error_ = true; - if (env->expect_error_ && env->verbose_) { fprintf(stderr, "Encountered error, as expected: "); } else if (!env->expect_error_) { @@ -56,7 +52,6 @@ class VerboseParserEnvironment { len_ = len; ofs_ = 0; expect_error_ = expect_error; - saw_error_ = false; end_ok_set_ = false; skip_until_ = may_skip ? 0 : -1; skipped_with_null_ = false; @@ -94,12 +89,12 @@ class VerboseParserEnvironment { bool CheckConsistency() { /* If we called end (which we should only do when previous bytes are fully * accepted), then end() should return true iff there were no errors. */ - if (end_ok_set_ && end_ok_ != !saw_error_) { + if (end_ok_set_ && end_ok_ != status_.ok()) { fprintf(stderr, "End() status and saw_error didn't match.\n"); return false; } - if (expect_error_ && !saw_error_) { + if (expect_error_ && status_.ok()) { fprintf(stderr, "Expected error but saw none.\n"); return false; } @@ -158,8 +153,9 @@ class VerboseParserEnvironment { } } - if (saw_error_) + if (!status_.ok()) { return false; + } if (parsed > bytes && skip_until_ >= 0) { skip_until_ = ofs_ + parsed; @@ -175,12 +171,14 @@ class VerboseParserEnvironment { } size_t ofs() { return ofs_; } - upb::Environment* env() { return &env_; } bool SkippedWithNull() { return skipped_with_null_; } + upb::Arena* arena() { return &arena_; } + private: - upb::Environment env_; + upb::Arena arena_; + upb::Status status_; upb::BytesSink sink_; const char* buf_; size_t len_; @@ -188,7 +186,6 @@ class VerboseParserEnvironment { size_t ofs_; void *subc_; bool expect_error_; - bool saw_error_; bool end_ok_; bool end_ok_set_; diff --git a/upb/bindings/lua/def.c b/upb/bindings/lua/def.c index 76510be..c38b6d1 100644 --- a/upb/bindings/lua/def.c +++ b/upb/bindings/lua/def.c @@ -15,13 +15,14 @@ #define LUPB_SYMTAB "lupb.symtab" #define LUPB_OBJCACHE "lupb.objcache" -#define CHK(pred) do { \ - upb_status status = UPB_STATUS_INIT; \ - pred; \ +#define CHK(pred) \ + do { \ + upb_status status; \ + upb_status_clear(&status); \ + pred; \ lupb_checkstatus(L, &status); \ } while (0) - /* lupb_wrapper ***************************************************************/ /* Wrappers around upb objects. */ diff --git a/upb/bindings/lua/msg.c b/upb/bindings/lua/msg.c index e983f46..df5a143 100644 --- a/upb/bindings/lua/msg.c +++ b/upb/bindings/lua/msg.c @@ -100,16 +100,21 @@ static void *lupb_newuserdata(lua_State *L, size_t size, const char *type) { * it is an internal memory management detail. Other objects refer to this * object from their userdata to keep the arena-owned data alive. */ +typedef struct { + upb_arena *arena; +} lupb_arena; + upb_arena *lupb_arena_check(lua_State *L, int narg) { - return luaL_checkudata(L, narg, LUPB_ARENA); + lupb_arena *a = luaL_checkudata(L, narg, LUPB_ARENA); + return a ? a->arena : NULL; } int lupb_arena_new(lua_State *L) { - upb_arena *a = lupb_newuserdata(L, sizeof(upb_arena), LUPB_ARENA); + lupb_arena *a = lupb_newuserdata(L, sizeof(lupb_arena), LUPB_ARENA); /* TODO(haberman): use Lua alloc func as block allocator? Would need to * verify that all cases of upb_malloc in msg/table are longjmp-safe. */ - upb_arena_init(a); + a->arena = upb_arena_new(); return 1; } @@ -140,7 +145,7 @@ static void lupb_arena_initsingleton(lua_State *L) { static int lupb_arena_gc(lua_State *L) { upb_arena *a = lupb_arena_check(L, 1); - upb_arena_uninit(a); + upb_arena_free(a); return 0; } diff --git a/upb/bindings/lua/upb/pb.c b/upb/bindings/lua/upb/pb.c index bca2ee8..2edefe0 100644 --- a/upb/bindings/lua/upb/pb.c +++ b/upb/bindings/lua/upb/pb.c @@ -27,17 +27,15 @@ static int lupb_pb_decode(lua_State *L) { static int lupb_pb_encode(lua_State *L) { const upb_msglayout *layout; const upb_msg *msg = lupb_msg_checkmsg2(L, 1, &layout); - upb_arena arena; + upb_arena *arena = upb_arena_new(); size_t size; char *result; - upb_arena_init(&arena); - - result = upb_encode(msg, (const void*)layout, &arena, &size); + result = upb_encode(msg, (const void*)layout, arena, &size); /* Free resources before we potentially bail on error. */ lua_pushlstring(L, result, size); - upb_arena_uninit(&arena); + upb_arena_free(arena); /* TODO(haberman): check for error. */ return 1; diff --git a/upb/decode.h b/upb/decode.h index 79774ed..790d7ef 100644 --- a/upb/decode.h +++ b/upb/decode.h @@ -7,10 +7,14 @@ #include "upb/msg.h" -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif bool upb_decode(upb_stringview buf, upb_msg *msg, const upb_msglayout *l); -UPB_END_EXTERN_C +#ifdef __cplusplus +} /* extern "C" */ +#endif #endif /* UPB_DECODE_H_ */ diff --git a/upb/def.c b/upb/def.c index 27de875..c744138 100644 --- a/upb/def.c +++ b/upb/def.c @@ -125,7 +125,7 @@ static upb_value pack_def(const void *ptr, upb_deftype_t type) { } struct upb_symtab { - upb_arena arena; + upb_arena *arena; upb_strtable syms; /* full_name -> packed def ptr */ upb_strtable files; /* file_name -> upb_filedef* */ }; @@ -224,7 +224,7 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { fields = upb_gmalloc(n * sizeof(*fields)); if (!fields) { - upb_upberr_setoom(s); + upb_status_setoom(s); return false; } @@ -870,7 +870,7 @@ const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i) { } void upb_symtab_free(upb_symtab *s) { - upb_arena_uninit(&s->arena); + upb_arena_free(s->arena); upb_gfree(s); } @@ -882,12 +882,12 @@ upb_symtab *upb_symtab_new() { return NULL; } - upb_arena_init(&s->arena); - alloc = upb_arena_alloc(&s->arena); + s->arena = upb_arena_new(); + alloc = upb_arena_alloc(s->arena); if (!upb_strtable_init2(&s->syms, UPB_CTYPE_CONSTPTR, alloc) || !upb_strtable_init2(&s->files, UPB_CTYPE_CONSTPTR, alloc)) { - upb_arena_uninit(&s->arena); + upb_arena_free(s->arena); upb_gfree(s); s = NULL; } @@ -922,7 +922,7 @@ const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) { * to validate important constraints like uniqueness of names and numbers. */ #define CHK(x) if (!(x)) { return false; } -#define CHK_OOM(x) if (!(x)) { upb_upberr_setoom(ctx->status); return false; } +#define CHK_OOM(x) if (!(x)) { upb_status_setoom(ctx->status); return false; } typedef struct { const upb_symtab *symtab; @@ -1632,7 +1632,7 @@ static bool build_filedef( static bool upb_symtab_addtotabs(upb_symtab *s, symtab_addctx *ctx, upb_status *status) { const upb_filedef *file = ctx->file; - upb_alloc *alloc = upb_arena_alloc(&s->arena); + upb_alloc *alloc = upb_arena_alloc(s->arena); upb_strtable_iter iter; CHK_OOM(upb_strtable_insert3(&s->files, file->name, strlen(file->name), @@ -1652,9 +1652,9 @@ static bool upb_symtab_addtotabs(upb_symtab *s, symtab_addctx *ctx, bool upb_symtab_addfile(upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto, upb_status *status) { - upb_arena tmparena; + upb_arena *tmparena = upb_arena_new(); upb_strtable addtab; - upb_alloc *alloc = upb_arena_alloc(&s->arena); + upb_alloc *alloc = upb_arena_alloc(s->arena); upb_filedef *file = upb_malloc(alloc, sizeof(*file)); bool ok; symtab_addctx ctx; @@ -1662,18 +1662,16 @@ bool upb_symtab_addfile(upb_symtab *s, ctx.file = file; ctx.symtab = s; ctx.alloc = alloc; - ctx.tmp = upb_arena_alloc(&tmparena); + ctx.tmp = upb_arena_alloc(tmparena); ctx.addtab = &addtab; ctx.status = status; - upb_arena_init(&tmparena); - ok = file && upb_strtable_init2(&addtab, UPB_CTYPE_CONSTPTR, ctx.tmp) && build_filedef(&ctx, file, file_proto) && upb_symtab_addtotabs(s, &ctx, status); - upb_arena_uninit(&tmparena); + upb_arena_free(tmparena); return ok; } @@ -1685,19 +1683,22 @@ bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) { * print errors to stderr instead of returning error status to the user. */ upb_def_init **deps = init->deps; google_protobuf_FileDescriptorProto *file; - upb_arena arena; - upb_status status = UPB_STATUS_INIT; + upb_arena *arena; + upb_status status; + + upb_status_clear(&status); if (upb_strtable_lookup(&s->files, init->filename, NULL)) { return true; } + arena = upb_arena_new(); + for (; *deps; deps++) { if (!_upb_symtab_loaddefinit(s, *deps)) goto err; } - upb_arena_init(&arena); - file = google_protobuf_FileDescriptorProto_parsenew(init->descriptor, &arena); + file = google_protobuf_FileDescriptorProto_parsenew(init->descriptor, arena); if (!file) { upb_status_seterrf( @@ -1710,13 +1711,13 @@ bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) { if (!upb_symtab_addfile(s, file, &status)) goto err; - upb_arena_uninit(&arena); + upb_arena_free(arena); return true; err: fprintf(stderr, "Error loading compiled-in descriptor: %s\n", upb_status_errmsg(&status)); - upb_arena_uninit(&arena); + upb_arena_free(arena); return false; } diff --git a/upb/def.h b/upb/def.h index fb8a71d..b1cf275 100644 --- a/upb/def.h +++ b/upb/def.h @@ -56,7 +56,9 @@ typedef struct upb_symtab upb_symtab; * protobuf wire format. */ #define UPB_MAX_FIELDNUMBER ((1 << 29) - 1) -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif const char *upb_fielddef_fullname(const upb_fielddef *f); upb_fieldtype_t upb_fielddef_type(const upb_fielddef *f); @@ -93,9 +95,8 @@ const upb_enumdef *upb_fielddef_enumsubdef(const upb_fielddef *f); /* Internal only. */ uint32_t upb_fielddef_selectorbase(const upb_fielddef *f); -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" */ /* A upb_fielddef describes a single field in a message. It is most often * found as a part of a upb_msgdef, but can also stand alone to represent @@ -228,7 +229,9 @@ class upb::FieldDefPtr { /* upb_oneofdef ***************************************************************/ -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif typedef upb_inttable_iter upb_oneof_iter; @@ -262,9 +265,8 @@ void upb_oneof_iter_setdone(upb_oneof_iter *iter); bool upb_oneof_iter_isequal(const upb_oneof_iter *iter1, const upb_oneof_iter *iter2); -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" */ /* Class that represents a oneof. */ class upb::OneofDefPtr { @@ -365,7 +367,9 @@ typedef upb_strtable_iter upb_msg_oneof_iter; #define UPB_TIMESTAMP_SECONDS 1 #define UPB_TIMESTAMP_NANOS 2 -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif const char *upb_msgdef_fullname(const upb_msgdef *m); const upb_filedef *upb_msgdef_file(const upb_msgdef *m); @@ -441,9 +445,8 @@ void upb_msg_oneof_iter_setdone(upb_msg_oneof_iter * iter); bool upb_msg_oneof_iter_isequal(const upb_msg_oneof_iter *iter1, const upb_msg_oneof_iter *iter2); -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" */ /* Structure that describes a single .proto message type. */ class upb::MessageDefPtr { @@ -711,7 +714,9 @@ class upb::EnumDefPtr { /* upb_filedef ****************************************************************/ -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif const char *upb_filedef_name(const upb_filedef *f); const char *upb_filedef_package(const upb_filedef *f); @@ -725,9 +730,8 @@ const upb_filedef *upb_filedef_dep(const upb_filedef *f, int i); const upb_msgdef *upb_filedef_msg(const upb_filedef *f, int i); const upb_enumdef *upb_filedef_enum(const upb_filedef *f, int i); -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" */ /* Class that represents a .proto file with some things defined in it. * @@ -773,7 +777,9 @@ class upb::FileDefPtr { /* upb_symtab *****************************************************************/ -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif upb_symtab *upb_symtab_new(); void upb_symtab_free(upb_symtab* s); @@ -795,9 +801,8 @@ typedef struct upb_def_init { bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init); -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" */ /* Non-const methods in upb::SymbolTable are NOT thread-safe. */ class upb::SymbolTable { @@ -823,7 +828,7 @@ class upb::SymbolTable { /* Adds the given serialized FileDescriptorProto to the pool. */ bool AddFile(const google_protobuf_FileDescriptorProto *file_proto, Status *status) { - return upb_symtab_addfile(ptr_.get(), file_proto, status); + return upb_symtab_addfile(ptr_.get(), file_proto, status->ptr()); } private: diff --git a/upb/encode.h b/upb/encode.h index 1a451b0..6842777 100644 --- a/upb/encode.h +++ b/upb/encode.h @@ -7,11 +7,15 @@ #include "upb/msg.h" -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif char *upb_encode(const void *msg, const upb_msglayout *l, upb_arena *arena, size_t *size); -UPB_END_EXTERN_C +#ifdef __cplusplus +} /* extern "C" */ +#endif #endif /* UPB_ENCODE_H_ */ diff --git a/upb/generated_util.h b/upb/generated_util.h index 3989f1e..657280f 100644 --- a/upb/generated_util.h +++ b/upb/generated_util.h @@ -54,10 +54,9 @@ UPB_INLINE void *_upb_array_resize_accessor(void *msg, size_t ofs, size_t size, size_t new_size = UPB_MAX(arr->size, 4); size_t old_bytes = arr->size * elem_size; size_t new_bytes; - upb_alloc *alloc = upb_arena_alloc(arr->arena); while (new_size < size) new_size *= 2; new_bytes = new_size * elem_size; - arr->data = upb_realloc(alloc, arr->data, old_bytes, new_bytes); + arr->data = upb_arena_realloc(arena, arr->data, old_bytes, new_bytes); if (!arr->data) { return NULL; } diff --git a/upb/handlers.c b/upb/handlers.c index ca978bf..aa23b46 100644 --- a/upb/handlers.c +++ b/upb/handlers.c @@ -390,7 +390,7 @@ uint32_t upb_handlers_selectorcount(const upb_fielddef *f) { /* upb_handlercache ***********************************************************/ struct upb_handlercache { - upb_arena arena; + upb_arena *arena; upb_inttable tab; /* maps upb_msgdef* -> upb_handlers*. */ upb_inttable cleanup_; upb_handlers_callback *callback; @@ -407,7 +407,7 @@ const upb_handlers *upb_handlercache_get(upb_handlercache *c, return upb_value_getptr(v); } - h = upb_handlers_new(md, c, &c->arena); + h = upb_handlers_new(md, c, c->arena); v = upb_value_ptr(h); if (!h) return NULL; @@ -442,7 +442,7 @@ upb_handlercache *upb_handlercache_new(upb_handlers_callback *callback, if (!cache) return NULL; - upb_arena_init(&cache->arena); + cache->arena = upb_arena_new(); cache->callback = callback; cache->closure = closure; @@ -470,7 +470,7 @@ void upb_handlercache_free(upb_handlercache *cache) { upb_inttable_uninit(&cache->tab); upb_inttable_uninit(&cache->cleanup_); - upb_arena_uninit(&cache->arena); + upb_arena_free(cache->arena); upb_gfree(cache); } diff --git a/upb/handlers.h b/upb/handlers.h index 44cad18..764e83e 100644 --- a/upb/handlers.h +++ b/upb/handlers.h @@ -157,7 +157,9 @@ typedef size_t upb_string_handlerfunc(void *c, const void *hd, const char *buf, struct upb_handlers; typedef struct upb_handlers upb_handlers; -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif /* Mutating accessors. */ const upb_status *upb_handlers_status(upb_handlers *h); @@ -235,9 +237,8 @@ UPB_INLINE upb_selector_t upb_handlers_getendselector(upb_selector_t start) { uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f); uint32_t upb_handlers_selectorcount(const upb_fielddef *f); -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" */ namespace upb { typedef upb_handlers Handlers; @@ -303,7 +304,9 @@ template class upb::Handler { const upb_handlerattr& attr() const { return attr_; } private: - UPB_DISALLOW_COPY_AND_ASSIGN(Handler) + Handler(const Handler&) = delete; + Handler& operator=(const Handler&) = delete; + FuncPtr handler_; mutable upb_handlerattr attr_; mutable bool registered_; @@ -334,7 +337,8 @@ class upb::HandlersPtr { typedef Handler StartFieldHandler; typedef Handler EndFieldHandler; typedef Handler StartMessageHandler; - typedef Handler EndMessageHandler; + typedef Handler + EndMessageHandler; typedef Handler StartStringHandler; typedef Handler @@ -590,7 +594,9 @@ class upb::HandlersPtr { /* upb_handlercache ***********************************************************/ -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif struct upb_handlercache; typedef struct upb_handlercache upb_handlercache; @@ -605,9 +611,8 @@ const upb_handlers *upb_handlercache_get(upb_handlercache *cache, bool upb_handlercache_addcleanup(upb_handlercache *h, void *p, upb_handlerfree *hfree); -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" */ class upb::HandlerCache { public: @@ -631,8 +636,6 @@ class upb::HandlerCache { /* upb_byteshandler ***********************************************************/ -UPB_BEGIN_EXTERN_C - typedef struct { upb_func *func; @@ -665,6 +668,10 @@ UPB_INLINE void upb_byteshandler_init(upb_byteshandler *handler) { *handler = init; } +#ifdef __cplusplus +extern "C" { +#endif + /* Caller must ensure that "d" outlives the handlers. */ bool upb_byteshandler_setstartstr(upb_byteshandler *h, upb_startstr_handlerfunc *func, void *d); @@ -674,16 +681,18 @@ bool upb_byteshandler_setendstr(upb_byteshandler *h, upb_endfield_handlerfunc *func, void *d); #ifdef __cplusplus +} /* extern "C" */ + namespace upb { typedef upb_byteshandler BytesHandler; } #endif -UPB_END_EXTERN_C - /** Message handlers ******************************************************************/ -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif /* These are the handlers used internally by upb_msgfactory_getmergehandlers(). * They write scalar data to a known offset from the message pointer. @@ -710,7 +719,9 @@ bool upb_msg_getscalarhandlerdata(const upb_handlers *h, -UPB_END_EXTERN_C +#ifdef __cplusplus +} /* extern "C" */ +#endif #include "upb/handlers-inl.h" diff --git a/upb/json/parser.c b/upb/json/parser.c index 1dac800..a594bfd 100644 --- a/upb/json/parser.c +++ b/upb/json/parser.c @@ -212,7 +212,7 @@ typedef struct { } upb_jsonparser_frame; struct upb_json_parser { - upb_env *env; + upb_arena *arena; const upb_json_parsermethod *method; upb_bytessink input_; @@ -221,7 +221,7 @@ struct upb_json_parser { upb_jsonparser_frame *top; upb_jsonparser_frame *limit; - upb_status status; + upb_status *status; /* Ragel's internal parsing stack for the parsing state machine. */ int current_state; @@ -259,7 +259,7 @@ struct upb_json_parser { }; struct upb_json_codecache { - upb_arena arena; + upb_arena *arena; upb_inttable methods; /* upb_msgdef* -> upb_json_parsermethod* */ }; @@ -277,7 +277,7 @@ static upb_jsonparser_any_frame *json_parser_any_frame_new( upb_json_parser *p) { upb_jsonparser_any_frame *frame; - frame = upb_env_malloc(p->env, sizeof(upb_jsonparser_any_frame)); + frame = upb_arena_malloc(p->arena, sizeof(upb_jsonparser_any_frame)); frame->encoder_handlercache = upb_pb_encoder_newcache(); frame->parser_codecache = upb_json_codecache_new(); @@ -301,12 +301,12 @@ static void json_parser_any_frame_set_payload_type( /* Initialize encoder. */ h = upb_handlercache_get(frame->encoder_handlercache, payload_type); - encoder = upb_pb_encoder_create(p->env, h, frame->stringsink.sink); + encoder = upb_pb_encoder_create(p->arena, h, frame->stringsink.sink); /* Initialize parser. */ parser_method = upb_json_codecache_get(frame->parser_codecache, payload_type); upb_sink_reset(&frame->sink, h, encoder); - frame->parser = upb_json_parser_create(p->env, parser_method, p->symtab, + frame->parser = upb_json_parser_create(p->arena, parser_method, p->symtab, frame->sink, p->ignore_json_unknown); } @@ -372,8 +372,7 @@ static upb_selector_t parser_getsel(upb_json_parser *p) { static bool check_stack(upb_json_parser *p) { if ((p->top + 1) == p->limit) { - upb_status_seterrmsg(&p->status, "Nesting too deep"); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "Nesting too deep"); return false; } @@ -468,10 +467,9 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr, char output[3]; if (limit - ptr < 4) { - upb_status_seterrf(&p->status, + upb_status_seterrf(p->status, "Base64 input for bytes field not a multiple of 4: %s", upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); return false; } @@ -495,10 +493,9 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr, otherchar: if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) || nonbase64(ptr[3]) ) { - upb_status_seterrf(&p->status, + upb_status_seterrf(p->status, "Non-base64 characters in bytes field: %s", upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); return false; } if (ptr[2] == '=') { uint32_t val; @@ -536,11 +533,10 @@ otherchar: } badpadding: - upb_status_seterrf(&p->status, + upb_status_seterrf(p->status, "Incorrect base64 padding for field: %s (%.*s)", upb_fielddef_name(p->top->f), 4, ptr); - upb_env_reporterror(p->env, &p->status); return false; } @@ -584,10 +580,9 @@ static bool accumulate_realloc(upb_json_parser *p, size_t need) { new_size = saturating_multiply(new_size, 2); } - mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size); + mem = upb_arena_realloc(p->arena, p->accumulate_buf, old_size, new_size); if (!mem) { - upb_status_seterrmsg(&p->status, "Out of memory allocating buffer."); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "Out of memory allocating buffer."); return false; } @@ -610,8 +605,7 @@ static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len, } if (!checked_add(p->accumulated_len, len, &need)) { - upb_status_seterrmsg(&p->status, "Integer overflow."); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "Integer overflow."); return false; } @@ -689,8 +683,7 @@ static bool multipart_text(upb_json_parser *p, const char *buf, size_t len, switch (p->multipart_state) { case MULTIPART_INACTIVE: upb_status_seterrmsg( - &p->status, "Internal error: unexpected state MULTIPART_INACTIVE"); - upb_env_reporterror(p->env, &p->status); + p->status, "Internal error: unexpected state MULTIPART_INACTIVE"); return false; case MULTIPART_ACCUMULATE: @@ -1055,8 +1048,7 @@ static bool parse_number(upb_json_parser *p, bool is_quoted) { multipart_end(p); return true; } else { - upb_status_seterrf(&p->status, "error parsing number: %s", buf); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrf(p->status, "error parsing number: %s", buf); multipart_end(p); return false; } @@ -1070,10 +1062,9 @@ static bool parser_putbool(upb_json_parser *p, bool val) { } if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) { - upb_status_seterrf(&p->status, + upb_status_seterrf(p->status, "Boolean value specified for non-bool field: %s", upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); return false; } @@ -1248,10 +1239,9 @@ static bool start_stringval(upb_json_parser *p) { multipart_startaccum(p); return true; } else { - upb_status_seterrf(&p->status, + upb_status_seterrf(p->status, "String specified for bool or submessage field: %s", upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); return false; } } @@ -1284,8 +1274,7 @@ static bool end_any_stringval(upb_json_parser *p) { payload_type = upb_symtab_lookupmsg2(p->symtab, buf, len); if (payload_type == NULL) { upb_status_seterrf( - &p->status, "Cannot find packed type: %.*s\n", (int)len, buf); - upb_env_reporterror(p->env, &p->status); + p->status, "Cannot find packed type: %.*s\n", (int)len, buf); return false; } @@ -1294,8 +1283,7 @@ static bool end_any_stringval(upb_json_parser *p) { return true; } else { upb_status_seterrf( - &p->status, "Invalid type url: %.*s\n", (int)len, buf); - upb_env_reporterror(p->env, &p->status); + p->status, "Invalid type url: %.*s\n", (int)len, buf); return false; } } @@ -1347,8 +1335,7 @@ static bool end_stringval_nontop(upb_json_parser *p) { upb_selector_t sel = parser_getsel(p); upb_sink_putint32(&p->top->sink, sel, int_val); } else { - upb_status_seterrf(&p->status, "Enum value unknown: '%.*s'", len, buf); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrf(p->status, "Enum value unknown: '%.*s'", len, buf); } break; @@ -1365,8 +1352,7 @@ static bool end_stringval_nontop(upb_json_parser *p) { default: UPB_ASSERT(false); - upb_status_seterrmsg(&p->status, "Internal error in JSON decoder"); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "Internal error in JSON decoder"); ok = false; break; } @@ -1445,25 +1431,22 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) { memcpy(seconds_buf, buf, fraction_start); seconds = strtol(seconds_buf, &end, 10); if (errno == ERANGE || end != seconds_buf + fraction_start) { - upb_status_seterrf(&p->status, "error parsing duration: %s", + upb_status_seterrf(p->status, "error parsing duration: %s", seconds_buf); - upb_env_reporterror(p->env, &p->status); return false; } if (seconds > 315576000000) { - upb_status_seterrf(&p->status, "error parsing duration: " + upb_status_seterrf(p->status, "error parsing duration: " "maximum acceptable value is " "315576000000"); - upb_env_reporterror(p->env, &p->status); return false; } if (seconds < -315576000000) { - upb_status_seterrf(&p->status, "error parsing duration: " + upb_status_seterrf(p->status, "error parsing duration: " "minimum acceptable value is " "-315576000000"); - upb_env_reporterror(p->env, &p->status); return false; } @@ -1472,9 +1455,8 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) { memcpy(nanos_buf + 1, buf + fraction_start, len - fraction_start); val = strtod(nanos_buf, &end); if (errno == ERANGE || end != nanos_buf + len - fraction_start + 1) { - upb_status_seterrf(&p->status, "error parsing duration: %s", + upb_status_seterrf(p->status, "error parsing duration: %s", nanos_buf); - upb_env_reporterror(p->env, &p->status); return false; } @@ -1500,7 +1482,7 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) { upb_sink_putint32(&p->top->sink, parser_getsel(p), nanos); end_member(p); - /* Continue previous environment */ + /* Continue previous arena */ multipart_startaccum(p); return true; @@ -1530,8 +1512,7 @@ static bool end_timestamp_base(upb_json_parser *p, const char *ptr) { /* Parse seconds */ if (strptime(timestamp_buf, "%FT%H:%M:%S%Z", &p->tm) == NULL) { - upb_status_seterrf(&p->status, "error parsing timestamp: %s", buf); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrf(p->status, "error parsing timestamp: %s", buf); return false; } @@ -1564,9 +1545,8 @@ static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) { buf = accumulate_getptr(p, &len); if (len > 10) { - upb_status_seterrf(&p->status, + upb_status_seterrf(p->status, "error parsing timestamp: at most 9-digit fraction."); - upb_env_reporterror(p->env, &p->status); return false; } @@ -1576,9 +1556,8 @@ static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) { val = strtod(nanos_buf, &end); if (errno == ERANGE || end != nanos_buf + len + 1) { - upb_status_seterrf(&p->status, "error parsing timestamp nanos: %s", + upb_status_seterrf(p->status, "error parsing timestamp nanos: %s", nanos_buf); - upb_env_reporterror(p->env, &p->status); return false; } @@ -1620,8 +1599,7 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) { if (buf[0] != 'Z') { if (sscanf(buf + 1, "%2d:00", &hours) != 1) { - upb_status_seterrf(&p->status, "error parsing timestamp offset"); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrf(p->status, "error parsing timestamp offset"); return false; } @@ -1637,10 +1615,9 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) { /* Check timestamp boundary */ if (seconds < -62135596800) { - upb_status_seterrf(&p->status, "error parsing timestamp: " + upb_status_seterrf(p->status, "error parsing timestamp: " "minimum acceptable value is " "0001-01-01T00:00:00Z"); - upb_env_reporterror(p->env, &p->status); return false; } @@ -1681,8 +1658,7 @@ static bool parse_mapentry_key(upb_json_parser *p) { p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY); if (p->top->f == NULL) { - upb_status_seterrmsg(&p->status, "mapentry message has no key"); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "mapentry message has no key"); return false; } switch (upb_fielddef_type(p->top->f)) { @@ -1705,9 +1681,8 @@ static bool parse_mapentry_key(upb_json_parser *p) { return false; } } else { - upb_status_seterrmsg(&p->status, + upb_status_seterrmsg(p->status, "Map bool key not 'true' or 'false'"); - upb_env_reporterror(p->env, &p->status); return false; } multipart_end(p); @@ -1725,8 +1700,7 @@ static bool parse_mapentry_key(upb_json_parser *p) { break; } default: - upb_status_seterrmsg(&p->status, "Invalid field type for map key"); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "Invalid field type for map key"); return false; } @@ -1785,8 +1759,7 @@ static bool handle_mapentry(upb_json_parser *p) { p->top->is_mapentry = true; /* set up to pop frame after value is parsed. */ p->top->mapfield = mapfield; if (p->top->f == NULL) { - upb_status_seterrmsg(&p->status, "mapentry message has no value"); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "mapentry message has no value"); return false; } @@ -1821,8 +1794,7 @@ static bool end_membername(upb_json_parser *p) { multipart_end(p); return true; } else { - upb_status_seterrf(&p->status, "No such field: %.*s\n", (int)len, buf); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrf(p->status, "No such field: %.*s\n", (int)len, buf); return false; } } @@ -1848,14 +1820,13 @@ static bool end_any_membername(upb_json_parser *p) { static void end_member(upb_json_parser *p) { /* If we just parsed a map-entry value, end that frame too. */ if (p->top->is_mapentry) { - upb_status s = UPB_STATUS_INIT; upb_selector_t sel; bool ok; const upb_fielddef *mapfield; UPB_ASSERT(p->top > p->stack); /* send ENDMSG on submsg. */ - upb_sink_endmsg(&p->top->sink, &s); + upb_sink_endmsg(&p->top->sink, p->status); mapfield = p->top->mapfield; /* send ENDSUBMSG in repeated-field-of-mapentries frame. */ @@ -1949,10 +1920,9 @@ static bool start_subobject(upb_json_parser *p) { return true; } else { - upb_status_seterrf(&p->status, + upb_status_seterrf(p->status, "Object specified for non-message/group field: %s", upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); return false; } } @@ -2060,10 +2030,9 @@ static bool start_array(upb_json_parser *p) { } if (!upb_fielddef_isseq(p->top->f)) { - upb_status_seterrf(&p->status, + upb_status_seterrf(p->status, "Array specified for non-repeated field: %s", upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); return false; } @@ -2122,12 +2091,7 @@ static void start_object(upb_json_parser *p) { static void end_object(upb_json_parser *p) { if (!p->top->is_map && p->top->m != NULL) { - upb_status status; - upb_status_clear(&status); - upb_sink_endmsg(&p->top->sink, &status); - if (!upb_ok(&status)) { - upb_env_reporterror(p->env, &status); - } + upb_sink_endmsg(&p->top->sink, p->status); } } @@ -2146,8 +2110,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) { if (json_parser_any_frame_has_value(p->top->any_frame) && !json_parser_any_frame_has_type_url(p->top->any_frame)) { - upb_status_seterrmsg(&p->status, "No valid type url"); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "No valid type url"); return false; } @@ -2162,8 +2125,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) { p->top->any_frame->before_type_url_end - p->top->any_frame->before_type_url_start); if (p->top->any_frame->before_type_url_start == NULL) { - upb_status_seterrmsg(&p->status, "invalid data for well known type."); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "invalid data for well known type."); return false; } p->top->any_frame->before_type_url_start++; @@ -2175,8 +2137,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) { (ptr + 1) - p->top->any_frame->after_type_url_start); if (p->top->any_frame->after_type_url_start == NULL) { - upb_status_seterrmsg(&p->status, "Invalid data for well known type."); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "Invalid data for well known type."); return false; } p->top->any_frame->after_type_url_start++; @@ -2249,7 +2210,6 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) { /* Deallocate any parse frame. */ json_parser_any_frame_free(p->top->any_frame); - upb_env_free(p->env, p->top->any_frame); return true; } @@ -2419,11 +2379,11 @@ static bool is_string_wrapper_object(upb_json_parser *p) { * final state once, when the closing '"' is seen. */ -#line 2581 "upb/json/parser.rl" +#line 2541 "upb/json/parser.rl" -#line 2427 "upb/json/parser.c" +#line 2387 "upb/json/parser.c" static const char _json_actions[] = { 0, 1, 0, 1, 1, 1, 3, 1, 4, 1, 6, 1, 7, 1, 8, 1, @@ -2670,7 +2630,7 @@ static const int json_en_value_machine = 75; static const int json_en_main = 1; -#line 2584 "upb/json/parser.rl" +#line 2544 "upb/json/parser.rl" size_t parse(void *closure, const void *hd, const char *buf, size_t size, const upb_bufhandle *handle) { @@ -2693,7 +2653,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size, capture_resume(parser, buf); -#line 2697 "upb/json/parser.c" +#line 2657 "upb/json/parser.c" { int _klen; unsigned int _trans; @@ -2768,83 +2728,83 @@ _match: switch ( *_acts++ ) { case 1: -#line 2432 "upb/json/parser.rl" +#line 2392 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 2: -#line 2434 "upb/json/parser.rl" +#line 2394 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 23;goto _again;} } break; case 3: -#line 2438 "upb/json/parser.rl" +#line 2398 "upb/json/parser.rl" { start_text(parser, p); } break; case 4: -#line 2439 "upb/json/parser.rl" +#line 2399 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_text(parser, p)); } break; case 5: -#line 2445 "upb/json/parser.rl" +#line 2405 "upb/json/parser.rl" { start_hex(parser); } break; case 6: -#line 2446 "upb/json/parser.rl" +#line 2406 "upb/json/parser.rl" { hexdigit(parser, p); } break; case 7: -#line 2447 "upb/json/parser.rl" +#line 2407 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_hex(parser)); } break; case 8: -#line 2453 "upb/json/parser.rl" +#line 2413 "upb/json/parser.rl" { CHECK_RETURN_TOP(escape(parser, p)); } break; case 9: -#line 2459 "upb/json/parser.rl" +#line 2419 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 10: -#line 2471 "upb/json/parser.rl" +#line 2431 "upb/json/parser.rl" { start_duration_base(parser, p); } break; case 11: -#line 2472 "upb/json/parser.rl" +#line 2432 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_duration_base(parser, p)); } break; case 12: -#line 2474 "upb/json/parser.rl" +#line 2434 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 13: -#line 2479 "upb/json/parser.rl" +#line 2439 "upb/json/parser.rl" { start_timestamp_base(parser, p); } break; case 14: -#line 2480 "upb/json/parser.rl" +#line 2440 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_base(parser, p)); } break; case 15: -#line 2482 "upb/json/parser.rl" +#line 2442 "upb/json/parser.rl" { start_timestamp_fraction(parser, p); } break; case 16: -#line 2483 "upb/json/parser.rl" +#line 2443 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); } break; case 17: -#line 2485 "upb/json/parser.rl" +#line 2445 "upb/json/parser.rl" { start_timestamp_zone(parser, p); } break; case 18: -#line 2486 "upb/json/parser.rl" +#line 2446 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); } break; case 19: -#line 2488 "upb/json/parser.rl" +#line 2448 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 20: -#line 2493 "upb/json/parser.rl" +#line 2453 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) { {stack[top++] = cs; cs = 47;goto _again;} @@ -2856,11 +2816,11 @@ _match: } break; case 21: -#line 2504 "upb/json/parser.rl" +#line 2464 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 75;goto _again;} } break; case 22: -#line 2509 "upb/json/parser.rl" +#line 2469 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { start_any_member(parser, p); @@ -2870,11 +2830,11 @@ _match: } break; case 23: -#line 2516 "upb/json/parser.rl" +#line 2476 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_membername(parser)); } break; case 24: -#line 2519 "upb/json/parser.rl" +#line 2479 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { end_any_member(parser, p); @@ -2884,7 +2844,7 @@ _match: } break; case 25: -#line 2530 "upb/json/parser.rl" +#line 2490 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { start_any_object(parser, p); @@ -2894,7 +2854,7 @@ _match: } break; case 26: -#line 2539 "upb/json/parser.rl" +#line 2499 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { CHECK_RETURN_TOP(end_any_object(parser, p)); @@ -2904,54 +2864,54 @@ _match: } break; case 27: -#line 2551 "upb/json/parser.rl" +#line 2511 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_array(parser)); } break; case 28: -#line 2555 "upb/json/parser.rl" +#line 2515 "upb/json/parser.rl" { end_array(parser); } break; case 29: -#line 2560 "upb/json/parser.rl" +#line 2520 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_number(parser, p)); } break; case 30: -#line 2561 "upb/json/parser.rl" +#line 2521 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 31: -#line 2563 "upb/json/parser.rl" +#line 2523 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_stringval(parser)); } break; case 32: -#line 2564 "upb/json/parser.rl" +#line 2524 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_stringval(parser)); } break; case 33: -#line 2566 "upb/json/parser.rl" +#line 2526 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, true)); } break; case 34: -#line 2568 "upb/json/parser.rl" +#line 2528 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, false)); } break; case 35: -#line 2570 "upb/json/parser.rl" +#line 2530 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_null(parser)); } break; case 36: -#line 2572 "upb/json/parser.rl" +#line 2532 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_subobject_full(parser)); } break; case 37: -#line 2573 "upb/json/parser.rl" +#line 2533 "upb/json/parser.rl" { end_subobject_full(parser); } break; case 38: -#line 2578 "upb/json/parser.rl" +#line 2538 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; -#line 2955 "upb/json/parser.c" +#line 2915 "upb/json/parser.c" } } @@ -2968,32 +2928,32 @@ _again: while ( __nacts-- > 0 ) { switch ( *__acts++ ) { case 0: -#line 2430 "upb/json/parser.rl" +#line 2390 "upb/json/parser.rl" { p--; {cs = stack[--top]; if ( p == pe ) goto _test_eof; goto _again;} } break; case 30: -#line 2561 "upb/json/parser.rl" +#line 2521 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 33: -#line 2566 "upb/json/parser.rl" +#line 2526 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, true)); } break; case 34: -#line 2568 "upb/json/parser.rl" +#line 2528 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, false)); } break; case 35: -#line 2570 "upb/json/parser.rl" +#line 2530 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_null(parser)); } break; case 37: -#line 2573 "upb/json/parser.rl" +#line 2533 "upb/json/parser.rl" { end_subobject_full(parser); } break; -#line 2997 "upb/json/parser.c" +#line 2957 "upb/json/parser.c" } } } @@ -3001,11 +2961,10 @@ goto _again;} } _out: {} } -#line 2606 "upb/json/parser.rl" +#line 2566 "upb/json/parser.rl" if (p != pe) { - upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p); - upb_env_reporterror(parser->env, &parser->status); + upb_status_seterrf(parser->status, "Parse error at '%.*s'\n", pe - p, p); } else { capture_suspend(parser, &p); } @@ -3049,26 +3008,25 @@ static void json_parser_reset(upb_json_parser *p) { /* Emit Ragel initialization of the parser. */ -#line 3053 "upb/json/parser.c" +#line 3012 "upb/json/parser.c" { cs = json_start; top = 0; } -#line 2653 "upb/json/parser.rl" +#line 2612 "upb/json/parser.rl" p->current_state = cs; p->parser_top = top; accumulate_clear(p); p->multipart_state = MULTIPART_INACTIVE; p->capture = NULL; p->accumulated = NULL; - upb_status_clear(&p->status); } static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c, const upb_msgdef *md) { upb_msg_field_iter i; - upb_alloc *alloc = upb_arena_alloc(&c->arena); + upb_alloc *alloc = upb_arena_alloc(c->arena); upb_json_parsermethod *m = upb_malloc(alloc, sizeof(*m)); @@ -3109,19 +3067,20 @@ static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c, /* Public API *****************************************************************/ -upb_json_parser *upb_json_parser_create(upb_env *env, +upb_json_parser *upb_json_parser_create(upb_arena *arena, const upb_json_parsermethod *method, const upb_symtab* symtab, upb_sink output, bool ignore_json_unknown) { #ifndef NDEBUG - const size_t size_before = upb_env_bytesallocated(env); + const size_t size_before = upb_arena_bytesallocated(arena); #endif - upb_json_parser *p = upb_env_malloc(env, sizeof(upb_json_parser)); + upb_json_parser *p = upb_arena_malloc(arena, sizeof(upb_json_parser)); if (!p) return false; - p->env = env; + p->arena = arena; p->method = method; + p->status = NULL; p->limit = p->stack + UPB_JSON_MAX_DEPTH; p->accumulate_buf = NULL; p->accumulate_buf_size = 0; @@ -3143,8 +3102,8 @@ upb_json_parser *upb_json_parser_create(upb_env *env, p->ignore_json_unknown = ignore_json_unknown; /* If this fails, uncomment and increase the value in parser.h. */ - /* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */ - UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(env) - size_before <= + /* fprintf(stderr, "%zd\n", upb_arena_bytesallocated(arena) - size_before); */ + UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(arena) - size_before <= UPB_JSON_PARSER_SIZE); return p; } @@ -3164,8 +3123,8 @@ upb_json_codecache *upb_json_codecache_new() { c = upb_gmalloc(sizeof(*c)); - upb_arena_init(&c->arena); - alloc = upb_arena_alloc(&c->arena); + c->arena = upb_arena_new(); + alloc = upb_arena_alloc(c->arena); upb_inttable_init2(&c->methods, UPB_CTYPE_CONSTPTR, alloc); @@ -3173,7 +3132,7 @@ upb_json_codecache *upb_json_codecache_new() { } void upb_json_codecache_free(upb_json_codecache *c) { - upb_arena_uninit(&c->arena); + upb_arena_free(c->arena); upb_gfree(c); } @@ -3182,7 +3141,7 @@ const upb_json_parsermethod *upb_json_codecache_get(upb_json_codecache *c, upb_json_parsermethod *m; upb_value v; upb_msg_field_iter i; - upb_alloc *alloc = upb_arena_alloc(&c->arena); + upb_alloc *alloc = upb_arena_alloc(c->arena); if (upb_inttable_lookupptr(&c->methods, md, &v)) { return upb_value_getconstptr(v); diff --git a/upb/json/parser.h b/upb/json/parser.h index d1a1471..2a06fcf 100644 --- a/upb/json/parser.h +++ b/upb/json/parser.h @@ -25,14 +25,15 @@ class ParserMethodPtr; struct upb_json_parsermethod; typedef struct upb_json_parsermethod upb_json_parsermethod; -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif const upb_byteshandler* upb_json_parsermethod_inputhandler( const upb_json_parsermethod* m); -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" */ class upb::json::ParserMethodPtr { public: @@ -62,17 +63,19 @@ class upb::json::ParserMethodPtr { struct upb_json_parser; typedef struct upb_json_parser upb_json_parser; -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif -upb_json_parser* -upb_json_parser_create(upb_env* e, const upb_json_parsermethod* m, - const upb_symtab* symtab, upb_sink output, - bool ignore_json_unknown); +upb_json_parser* upb_json_parser_create(upb_arena* a, + const upb_json_parsermethod* m, + const upb_symtab* symtab, + upb_sink output, + bool ignore_json_unknown); upb_bytessink upb_json_parser_input(upb_json_parser* p); -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" */ /* Parses an incoming BytesStream, pushing the results to the destination * sink. */ @@ -80,12 +83,13 @@ class upb::json::ParserPtr { public: ParserPtr(upb_json_parser* ptr) : ptr_(ptr) {} - static ParserPtr Create(Environment* env, ParserMethodPtr method, + static ParserPtr Create(Arena* arena, ParserMethodPtr method, SymbolTable* symtab, Sink output, bool ignore_json_unknown) { upb_symtab* symtab_ptr = symtab ? symtab->ptr() : nullptr; - return ParserPtr(upb_json_parser_create( - env, method.ptr(), symtab_ptr, output.sink(), ignore_json_unknown)); + return ParserPtr(upb_json_parser_create(arena->ptr(), method.ptr(), + symtab_ptr, output.sink(), + ignore_json_unknown)); } BytesSink input() { return upb_json_parser_input(ptr_); } @@ -101,16 +105,17 @@ class upb::json::ParserPtr { struct upb_json_codecache; typedef struct upb_json_codecache upb_json_codecache; -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif upb_json_codecache *upb_json_codecache_new(); void upb_json_codecache_free(upb_json_codecache *cache); const upb_json_parsermethod* upb_json_codecache_get(upb_json_codecache* cache, const upb_msgdef* md); -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" */ class upb::json::CodeCache { public: diff --git a/upb/json/parser.rl b/upb/json/parser.rl index 05a9505..a117d0c 100644 --- a/upb/json/parser.rl +++ b/upb/json/parser.rl @@ -210,7 +210,7 @@ typedef struct { } upb_jsonparser_frame; struct upb_json_parser { - upb_env *env; + upb_arena *arena; const upb_json_parsermethod *method; upb_bytessink input_; @@ -219,7 +219,7 @@ struct upb_json_parser { upb_jsonparser_frame *top; upb_jsonparser_frame *limit; - upb_status status; + upb_status *status; /* Ragel's internal parsing stack for the parsing state machine. */ int current_state; @@ -257,7 +257,7 @@ struct upb_json_parser { }; struct upb_json_codecache { - upb_arena arena; + upb_arena *arena; upb_inttable methods; /* upb_msgdef* -> upb_json_parsermethod* */ }; @@ -275,7 +275,7 @@ static upb_jsonparser_any_frame *json_parser_any_frame_new( upb_json_parser *p) { upb_jsonparser_any_frame *frame; - frame = upb_env_malloc(p->env, sizeof(upb_jsonparser_any_frame)); + frame = upb_arena_malloc(p->arena, sizeof(upb_jsonparser_any_frame)); frame->encoder_handlercache = upb_pb_encoder_newcache(); frame->parser_codecache = upb_json_codecache_new(); @@ -299,12 +299,12 @@ static void json_parser_any_frame_set_payload_type( /* Initialize encoder. */ h = upb_handlercache_get(frame->encoder_handlercache, payload_type); - encoder = upb_pb_encoder_create(p->env, h, frame->stringsink.sink); + encoder = upb_pb_encoder_create(p->arena, h, frame->stringsink.sink); /* Initialize parser. */ parser_method = upb_json_codecache_get(frame->parser_codecache, payload_type); upb_sink_reset(&frame->sink, h, encoder); - frame->parser = upb_json_parser_create(p->env, parser_method, p->symtab, + frame->parser = upb_json_parser_create(p->arena, parser_method, p->symtab, frame->sink, p->ignore_json_unknown); } @@ -370,8 +370,7 @@ static upb_selector_t parser_getsel(upb_json_parser *p) { static bool check_stack(upb_json_parser *p) { if ((p->top + 1) == p->limit) { - upb_status_seterrmsg(&p->status, "Nesting too deep"); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "Nesting too deep"); return false; } @@ -466,10 +465,9 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr, char output[3]; if (limit - ptr < 4) { - upb_status_seterrf(&p->status, + upb_status_seterrf(p->status, "Base64 input for bytes field not a multiple of 4: %s", upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); return false; } @@ -493,10 +491,9 @@ static bool base64_push(upb_json_parser *p, upb_selector_t sel, const char *ptr, otherchar: if (nonbase64(ptr[0]) || nonbase64(ptr[1]) || nonbase64(ptr[2]) || nonbase64(ptr[3]) ) { - upb_status_seterrf(&p->status, + upb_status_seterrf(p->status, "Non-base64 characters in bytes field: %s", upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); return false; } if (ptr[2] == '=') { uint32_t val; @@ -534,11 +531,10 @@ otherchar: } badpadding: - upb_status_seterrf(&p->status, + upb_status_seterrf(p->status, "Incorrect base64 padding for field: %s (%.*s)", upb_fielddef_name(p->top->f), 4, ptr); - upb_env_reporterror(p->env, &p->status); return false; } @@ -582,10 +578,9 @@ static bool accumulate_realloc(upb_json_parser *p, size_t need) { new_size = saturating_multiply(new_size, 2); } - mem = upb_env_realloc(p->env, p->accumulate_buf, old_size, new_size); + mem = upb_arena_realloc(p->arena, p->accumulate_buf, old_size, new_size); if (!mem) { - upb_status_seterrmsg(&p->status, "Out of memory allocating buffer."); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "Out of memory allocating buffer."); return false; } @@ -608,8 +603,7 @@ static bool accumulate_append(upb_json_parser *p, const char *buf, size_t len, } if (!checked_add(p->accumulated_len, len, &need)) { - upb_status_seterrmsg(&p->status, "Integer overflow."); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "Integer overflow."); return false; } @@ -687,8 +681,7 @@ static bool multipart_text(upb_json_parser *p, const char *buf, size_t len, switch (p->multipart_state) { case MULTIPART_INACTIVE: upb_status_seterrmsg( - &p->status, "Internal error: unexpected state MULTIPART_INACTIVE"); - upb_env_reporterror(p->env, &p->status); + p->status, "Internal error: unexpected state MULTIPART_INACTIVE"); return false; case MULTIPART_ACCUMULATE: @@ -1053,8 +1046,7 @@ static bool parse_number(upb_json_parser *p, bool is_quoted) { multipart_end(p); return true; } else { - upb_status_seterrf(&p->status, "error parsing number: %s", buf); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrf(p->status, "error parsing number: %s", buf); multipart_end(p); return false; } @@ -1068,10 +1060,9 @@ static bool parser_putbool(upb_json_parser *p, bool val) { } if (upb_fielddef_type(p->top->f) != UPB_TYPE_BOOL) { - upb_status_seterrf(&p->status, + upb_status_seterrf(p->status, "Boolean value specified for non-bool field: %s", upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); return false; } @@ -1246,10 +1237,9 @@ static bool start_stringval(upb_json_parser *p) { multipart_startaccum(p); return true; } else { - upb_status_seterrf(&p->status, + upb_status_seterrf(p->status, "String specified for bool or submessage field: %s", upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); return false; } } @@ -1282,8 +1272,7 @@ static bool end_any_stringval(upb_json_parser *p) { payload_type = upb_symtab_lookupmsg2(p->symtab, buf, len); if (payload_type == NULL) { upb_status_seterrf( - &p->status, "Cannot find packed type: %.*s\n", (int)len, buf); - upb_env_reporterror(p->env, &p->status); + p->status, "Cannot find packed type: %.*s\n", (int)len, buf); return false; } @@ -1292,8 +1281,7 @@ static bool end_any_stringval(upb_json_parser *p) { return true; } else { upb_status_seterrf( - &p->status, "Invalid type url: %.*s\n", (int)len, buf); - upb_env_reporterror(p->env, &p->status); + p->status, "Invalid type url: %.*s\n", (int)len, buf); return false; } } @@ -1345,8 +1333,7 @@ static bool end_stringval_nontop(upb_json_parser *p) { upb_selector_t sel = parser_getsel(p); upb_sink_putint32(&p->top->sink, sel, int_val); } else { - upb_status_seterrf(&p->status, "Enum value unknown: '%.*s'", len, buf); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrf(p->status, "Enum value unknown: '%.*s'", len, buf); } break; @@ -1363,8 +1350,7 @@ static bool end_stringval_nontop(upb_json_parser *p) { default: UPB_ASSERT(false); - upb_status_seterrmsg(&p->status, "Internal error in JSON decoder"); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "Internal error in JSON decoder"); ok = false; break; } @@ -1443,25 +1429,22 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) { memcpy(seconds_buf, buf, fraction_start); seconds = strtol(seconds_buf, &end, 10); if (errno == ERANGE || end != seconds_buf + fraction_start) { - upb_status_seterrf(&p->status, "error parsing duration: %s", + upb_status_seterrf(p->status, "error parsing duration: %s", seconds_buf); - upb_env_reporterror(p->env, &p->status); return false; } if (seconds > 315576000000) { - upb_status_seterrf(&p->status, "error parsing duration: " + upb_status_seterrf(p->status, "error parsing duration: " "maximum acceptable value is " "315576000000"); - upb_env_reporterror(p->env, &p->status); return false; } if (seconds < -315576000000) { - upb_status_seterrf(&p->status, "error parsing duration: " + upb_status_seterrf(p->status, "error parsing duration: " "minimum acceptable value is " "-315576000000"); - upb_env_reporterror(p->env, &p->status); return false; } @@ -1470,9 +1453,8 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) { memcpy(nanos_buf + 1, buf + fraction_start, len - fraction_start); val = strtod(nanos_buf, &end); if (errno == ERANGE || end != nanos_buf + len - fraction_start + 1) { - upb_status_seterrf(&p->status, "error parsing duration: %s", + upb_status_seterrf(p->status, "error parsing duration: %s", nanos_buf); - upb_env_reporterror(p->env, &p->status); return false; } @@ -1498,7 +1480,7 @@ static bool end_duration_base(upb_json_parser *p, const char *ptr) { upb_sink_putint32(&p->top->sink, parser_getsel(p), nanos); end_member(p); - /* Continue previous environment */ + /* Continue previous arena */ multipart_startaccum(p); return true; @@ -1528,8 +1510,7 @@ static bool end_timestamp_base(upb_json_parser *p, const char *ptr) { /* Parse seconds */ if (strptime(timestamp_buf, "%FT%H:%M:%S%Z", &p->tm) == NULL) { - upb_status_seterrf(&p->status, "error parsing timestamp: %s", buf); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrf(p->status, "error parsing timestamp: %s", buf); return false; } @@ -1562,9 +1543,8 @@ static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) { buf = accumulate_getptr(p, &len); if (len > 10) { - upb_status_seterrf(&p->status, + upb_status_seterrf(p->status, "error parsing timestamp: at most 9-digit fraction."); - upb_env_reporterror(p->env, &p->status); return false; } @@ -1574,9 +1554,8 @@ static bool end_timestamp_fraction(upb_json_parser *p, const char *ptr) { val = strtod(nanos_buf, &end); if (errno == ERANGE || end != nanos_buf + len + 1) { - upb_status_seterrf(&p->status, "error parsing timestamp nanos: %s", + upb_status_seterrf(p->status, "error parsing timestamp nanos: %s", nanos_buf); - upb_env_reporterror(p->env, &p->status); return false; } @@ -1618,8 +1597,7 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) { if (buf[0] != 'Z') { if (sscanf(buf + 1, "%2d:00", &hours) != 1) { - upb_status_seterrf(&p->status, "error parsing timestamp offset"); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrf(p->status, "error parsing timestamp offset"); return false; } @@ -1635,10 +1613,9 @@ static bool end_timestamp_zone(upb_json_parser *p, const char *ptr) { /* Check timestamp boundary */ if (seconds < -62135596800) { - upb_status_seterrf(&p->status, "error parsing timestamp: " + upb_status_seterrf(p->status, "error parsing timestamp: " "minimum acceptable value is " "0001-01-01T00:00:00Z"); - upb_env_reporterror(p->env, &p->status); return false; } @@ -1679,8 +1656,7 @@ static bool parse_mapentry_key(upb_json_parser *p) { p->top->f = upb_msgdef_itof(p->top->m, UPB_MAPENTRY_KEY); if (p->top->f == NULL) { - upb_status_seterrmsg(&p->status, "mapentry message has no key"); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "mapentry message has no key"); return false; } switch (upb_fielddef_type(p->top->f)) { @@ -1703,9 +1679,8 @@ static bool parse_mapentry_key(upb_json_parser *p) { return false; } } else { - upb_status_seterrmsg(&p->status, + upb_status_seterrmsg(p->status, "Map bool key not 'true' or 'false'"); - upb_env_reporterror(p->env, &p->status); return false; } multipart_end(p); @@ -1723,8 +1698,7 @@ static bool parse_mapentry_key(upb_json_parser *p) { break; } default: - upb_status_seterrmsg(&p->status, "Invalid field type for map key"); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "Invalid field type for map key"); return false; } @@ -1783,8 +1757,7 @@ static bool handle_mapentry(upb_json_parser *p) { p->top->is_mapentry = true; /* set up to pop frame after value is parsed. */ p->top->mapfield = mapfield; if (p->top->f == NULL) { - upb_status_seterrmsg(&p->status, "mapentry message has no value"); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "mapentry message has no value"); return false; } @@ -1819,8 +1792,7 @@ static bool end_membername(upb_json_parser *p) { multipart_end(p); return true; } else { - upb_status_seterrf(&p->status, "No such field: %.*s\n", (int)len, buf); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrf(p->status, "No such field: %.*s\n", (int)len, buf); return false; } } @@ -1846,14 +1818,13 @@ static bool end_any_membername(upb_json_parser *p) { static void end_member(upb_json_parser *p) { /* If we just parsed a map-entry value, end that frame too. */ if (p->top->is_mapentry) { - upb_status s = UPB_STATUS_INIT; upb_selector_t sel; bool ok; const upb_fielddef *mapfield; UPB_ASSERT(p->top > p->stack); /* send ENDMSG on submsg. */ - upb_sink_endmsg(&p->top->sink, &s); + upb_sink_endmsg(&p->top->sink, p->status); mapfield = p->top->mapfield; /* send ENDSUBMSG in repeated-field-of-mapentries frame. */ @@ -1947,10 +1918,9 @@ static bool start_subobject(upb_json_parser *p) { return true; } else { - upb_status_seterrf(&p->status, + upb_status_seterrf(p->status, "Object specified for non-message/group field: %s", upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); return false; } } @@ -2058,10 +2028,9 @@ static bool start_array(upb_json_parser *p) { } if (!upb_fielddef_isseq(p->top->f)) { - upb_status_seterrf(&p->status, + upb_status_seterrf(p->status, "Array specified for non-repeated field: %s", upb_fielddef_name(p->top->f)); - upb_env_reporterror(p->env, &p->status); return false; } @@ -2120,12 +2089,7 @@ static void start_object(upb_json_parser *p) { static void end_object(upb_json_parser *p) { if (!p->top->is_map && p->top->m != NULL) { - upb_status status; - upb_status_clear(&status); - upb_sink_endmsg(&p->top->sink, &status); - if (!upb_ok(&status)) { - upb_env_reporterror(p->env, &status); - } + upb_sink_endmsg(&p->top->sink, p->status); } } @@ -2144,8 +2108,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) { if (json_parser_any_frame_has_value(p->top->any_frame) && !json_parser_any_frame_has_type_url(p->top->any_frame)) { - upb_status_seterrmsg(&p->status, "No valid type url"); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "No valid type url"); return false; } @@ -2160,8 +2123,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) { p->top->any_frame->before_type_url_end - p->top->any_frame->before_type_url_start); if (p->top->any_frame->before_type_url_start == NULL) { - upb_status_seterrmsg(&p->status, "invalid data for well known type."); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "invalid data for well known type."); return false; } p->top->any_frame->before_type_url_start++; @@ -2173,8 +2135,7 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) { (ptr + 1) - p->top->any_frame->after_type_url_start); if (p->top->any_frame->after_type_url_start == NULL) { - upb_status_seterrmsg(&p->status, "Invalid data for well known type."); - upb_env_reporterror(p->env, &p->status); + upb_status_seterrmsg(p->status, "Invalid data for well known type."); return false; } p->top->any_frame->after_type_url_start++; @@ -2247,7 +2208,6 @@ static bool end_any_object(upb_json_parser *p, const char *ptr) { /* Deallocate any parse frame. */ json_parser_any_frame_free(p->top->any_frame); - upb_env_free(p->env, p->top->any_frame); return true; } @@ -2605,8 +2565,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size, %% write exec; if (p != pe) { - upb_status_seterrf(&parser->status, "Parse error at '%.*s'\n", pe - p, p); - upb_env_reporterror(parser->env, &parser->status); + upb_status_seterrf(parser->status, "Parse error at '%.*s'\n", pe - p, p); } else { capture_suspend(parser, &p); } @@ -2656,13 +2615,12 @@ static void json_parser_reset(upb_json_parser *p) { p->multipart_state = MULTIPART_INACTIVE; p->capture = NULL; p->accumulated = NULL; - upb_status_clear(&p->status); } static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c, const upb_msgdef *md) { upb_msg_field_iter i; - upb_alloc *alloc = upb_arena_alloc(&c->arena); + upb_alloc *alloc = upb_arena_alloc(c->arena); upb_json_parsermethod *m = upb_malloc(alloc, sizeof(*m)); @@ -2703,19 +2661,20 @@ static upb_json_parsermethod *parsermethod_new(upb_json_codecache *c, /* Public API *****************************************************************/ -upb_json_parser *upb_json_parser_create(upb_env *env, +upb_json_parser *upb_json_parser_create(upb_arena *arena, const upb_json_parsermethod *method, const upb_symtab* symtab, upb_sink output, bool ignore_json_unknown) { #ifndef NDEBUG - const size_t size_before = upb_env_bytesallocated(env); + const size_t size_before = upb_arena_bytesallocated(arena); #endif - upb_json_parser *p = upb_env_malloc(env, sizeof(upb_json_parser)); + upb_json_parser *p = upb_arena_malloc(arena, sizeof(upb_json_parser)); if (!p) return false; - p->env = env; + p->arena = arena; p->method = method; + p->status = NULL; p->limit = p->stack + UPB_JSON_MAX_DEPTH; p->accumulate_buf = NULL; p->accumulate_buf_size = 0; @@ -2737,8 +2696,8 @@ upb_json_parser *upb_json_parser_create(upb_env *env, p->ignore_json_unknown = ignore_json_unknown; /* If this fails, uncomment and increase the value in parser.h. */ - /* fprintf(stderr, "%zd\n", upb_env_bytesallocated(env) - size_before); */ - UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(env) - size_before <= + /* fprintf(stderr, "%zd\n", upb_arena_bytesallocated(arena) - size_before); */ + UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(arena) - size_before <= UPB_JSON_PARSER_SIZE); return p; } @@ -2758,8 +2717,8 @@ upb_json_codecache *upb_json_codecache_new() { c = upb_gmalloc(sizeof(*c)); - upb_arena_init(&c->arena); - alloc = upb_arena_alloc(&c->arena); + c->arena = upb_arena_new(); + alloc = upb_arena_alloc(c->arena); upb_inttable_init2(&c->methods, UPB_CTYPE_CONSTPTR, alloc); @@ -2767,7 +2726,7 @@ upb_json_codecache *upb_json_codecache_new() { } void upb_json_codecache_free(upb_json_codecache *c) { - upb_arena_uninit(&c->arena); + upb_arena_free(c->arena); upb_gfree(c); } @@ -2776,7 +2735,7 @@ const upb_json_parsermethod *upb_json_codecache_get(upb_json_codecache *c, upb_json_parsermethod *m; upb_value v; upb_msg_field_iter i; - upb_alloc *alloc = upb_arena_alloc(&c->arena); + upb_alloc *alloc = upb_arena_alloc(c->arena); if (upb_inttable_lookupptr(&c->methods, md, &v)) { return upb_value_getconstptr(v); diff --git a/upb/json/printer.c b/upb/json/printer.c index 83f1a58..bc18055 100644 --- a/upb/json/printer.c +++ b/upb/json/printer.c @@ -1252,13 +1252,13 @@ static void json_printer_reset(upb_json_printer *p) { /* Public API *****************************************************************/ -upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h, +upb_json_printer *upb_json_printer_create(upb_arena *a, const upb_handlers *h, upb_bytessink output) { #ifndef NDEBUG - size_t size_before = upb_env_bytesallocated(e); + size_t size_before = upb_arena_bytesallocated(a); #endif - upb_json_printer *p = upb_env_malloc(e, sizeof(upb_json_printer)); + upb_json_printer *p = upb_arena_malloc(a, sizeof(upb_json_printer)); if (!p) return NULL; p->output_ = output; @@ -1268,7 +1268,7 @@ upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h, p->nanos = 0; /* If this fails, increase the value in printer.h. */ - UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(e) - size_before <= + UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(a) - size_before <= UPB_JSON_PRINTER_SIZE); return p; } diff --git a/upb/json/printer.h b/upb/json/printer.h index a7a37bb..857ae47 100644 --- a/upb/json/printer.h +++ b/upb/json/printer.h @@ -24,10 +24,12 @@ class PrinterPtr; struct upb_json_printer; typedef struct upb_json_printer upb_json_printer; -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif /* Native C API. */ -upb_json_printer *upb_json_printer_create(upb_env *e, const upb_handlers *h, +upb_json_printer *upb_json_printer_create(upb_arena *a, const upb_handlers *h, upb_bytessink output); upb_sink upb_json_printer_input(upb_json_printer *p); const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md, @@ -36,18 +38,18 @@ const upb_handlers *upb_json_printer_newhandlers(const upb_msgdef *md, upb_handlercache *upb_json_printer_newcache(bool preserve_proto_fieldnames); -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" */ /* Prints an incoming stream of data to a BytesSink in JSON format. */ class upb::json::PrinterPtr { public: PrinterPtr(upb_json_printer* ptr) : ptr_(ptr) {} - static PrinterPtr Create(Environment *env, const upb::Handlers *handlers, + static PrinterPtr Create(Arena *arena, const upb::Handlers *handlers, BytesSink output) { - return PrinterPtr(upb_json_printer_create(env, handlers, output.sink())); + return PrinterPtr( + upb_json_printer_create(arena->ptr(), handlers, output.sink())); } /* The input to the printer. */ diff --git a/upb/msg.h b/upb/msg.h index 4529478..149b7ab 100644 --- a/upb/msg.h +++ b/upb/msg.h @@ -37,18 +37,22 @@ class MessageLayout; #endif -UPB_DECLARE_TYPE(upb::Map, upb_map) -UPB_DECLARE_TYPE(upb::MapIterator, upb_mapiter) - -struct upb_array; -typedef struct upb_array upb_array; - /* TODO(haberman): C++ accessors */ -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif typedef void upb_msg; +struct upb_array; +typedef struct upb_array upb_array; + +struct upb_map; +typedef struct upb_map upb_map; + +struct upb_mapiter; +typedef struct upb_mapiter upb_mapiter; /** upb_msglayout *************************************************************/ @@ -75,7 +79,6 @@ typedef struct upb_msglayout { bool extendable; } upb_msglayout; - /** upb_stringview ************************************************************/ typedef struct { @@ -103,7 +106,6 @@ UPB_INLINE bool upb_stringview_eql(upb_stringview a, upb_stringview b) { #define UPB_STRINGVIEW_INIT(ptr, len) {ptr, len} - /** upb_msgval ****************************************************************/ /* A union representing all possible protobuf values. Used for generic get/set @@ -156,7 +158,6 @@ UPB_INLINE upb_msgval upb_msgval_makestr(const char *data, size_t size) { return upb_msgval_str(upb_stringview_make(data, size)); } - /** upb_msg *******************************************************************/ /* A upb_msg represents a protobuf message. It always corresponds to a specific @@ -216,7 +217,6 @@ bool upb_msg_clearfield(upb_msg *msg, /* TODO(haberman): copyfrom()/mergefrom()? */ - /** upb_array *****************************************************************/ /* A upb_array stores data for a repeated field. The memory management @@ -236,7 +236,6 @@ upb_msgval upb_array_get(const upb_array *arr, size_t i); bool upb_array_set(upb_array *arr, size_t i, upb_msgval val); - /** upb_map *******************************************************************/ /* A upb_map stores data for a map field. The memory management semantics are @@ -268,7 +267,6 @@ bool upb_map_set(upb_map *map, /* Deletes an entry in the map. Returns true if the key was present. */ bool upb_map_del(upb_map *map, upb_msgval key); - /** upb_mapiter ***************************************************************/ /* For iterating over a map. Map iterators are invalidated by mutations to the @@ -290,6 +288,8 @@ upb_msgval upb_mapiter_value(const upb_mapiter *i); void upb_mapiter_setdone(upb_mapiter *i); bool upb_mapiter_isequal(const upb_mapiter *i1, const upb_mapiter *i2); -UPB_END_EXTERN_C +#ifdef __cplusplus +} /* extern "C" */ +#endif #endif /* UPB_MSG_H_ */ diff --git a/upb/msgfactory.h b/upb/msgfactory.h index 73a26ba..9b3b599 100644 --- a/upb/msgfactory.h +++ b/upb/msgfactory.h @@ -5,10 +5,15 @@ #ifndef UPB_MSGFACTORY_H_ #define UPB_MSGFACTORY_H_ -UPB_DECLARE_TYPE(upb::MessageFactory, upb_msgfactory) - /** upb_msgfactory ************************************************************/ +struct upb_msgfactory; +typedef struct upb_msgfactory upb_msgfactory; + +#ifdef __cplusplus +extern "C" { +#endif + /* A upb_msgfactory contains a cache of upb_msglayout, upb_handlers, and * upb_visitorplan objects. These are the objects necessary to represent, * populate, and and visit upb_msg objects. @@ -36,5 +41,8 @@ const upb_symtab *upb_msgfactory_symtab(const upb_msgfactory *f); const upb_msglayout *upb_msgfactory_getlayout(upb_msgfactory *f, const upb_msgdef *m); +#ifdef __cplusplus +} /* extern "C" */ +#endif #endif /* UPB_MSGFACTORY_H_ */ diff --git a/upb/pb/compile_decoder.c b/upb/pb/compile_decoder.c index e17ca03..ca497ed 100644 --- a/upb/pb/compile_decoder.c +++ b/upb/pb/compile_decoder.c @@ -907,7 +907,7 @@ upb_pbcodecache *upb_pbcodecache_new(upb_handlercache *dest) { c->allow_jit = true; c->lazy = false; - upb_arena_init(&c->arena); + c->arena = upb_arena_new(); if (!upb_inttable_init(&c->groups, UPB_CTYPE_CONSTPTR)) return NULL; return c; diff --git a/upb/pb/decoder.c b/upb/pb/decoder.c index cd64f72..5068225 100644 --- a/upb/pb/decoder.c +++ b/upb/pb/decoder.c @@ -99,9 +99,7 @@ static bool in_residual_buf(const upb_pbdecoder *d, const char *p); * benchmarks. */ static void seterr(upb_pbdecoder *d, const char *msg) { - upb_status status = UPB_STATUS_INIT; - upb_status_seterrmsg(&status, msg); - upb_env_reporterror(d->env, &status); + upb_status_seterrmsg(d->status, msg); } void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg) { @@ -992,24 +990,24 @@ void upb_pbdecoder_reset(upb_pbdecoder *d) { d->residual_end = d->residual; } -upb_pbdecoder *upb_pbdecoder_create(upb_env *e, const upb_pbdecodermethod *m, +upb_pbdecoder *upb_pbdecoder_create(upb_arena *a, const upb_pbdecodermethod *m, upb_sink sink) { const size_t default_max_nesting = 64; #ifndef NDEBUG - size_t size_before = upb_env_bytesallocated(e); + size_t size_before = upb_arena_bytesallocated(a); #endif - upb_pbdecoder *d = upb_env_malloc(e, sizeof(upb_pbdecoder)); + upb_pbdecoder *d = upb_arena_malloc(a, sizeof(upb_pbdecoder)); if (!d) return NULL; d->method_ = m; - d->callstack = upb_env_malloc(e, callstacksize(d, default_max_nesting)); - d->stack = upb_env_malloc(e, stacksize(d, default_max_nesting)); + d->callstack = upb_arena_malloc(a, callstacksize(d, default_max_nesting)); + d->stack = upb_arena_malloc(a, stacksize(d, default_max_nesting)); if (!d->stack || !d->callstack) { return NULL; } - d->env = e; + d->arena = a; d->limit = d->stack + default_max_nesting - 1; d->stack_size = default_max_nesting; d->status = NULL; @@ -1024,7 +1022,7 @@ upb_pbdecoder *upb_pbdecoder_create(upb_env *e, const upb_pbdecodermethod *m, d->top->sink = sink; /* If this fails, increase the value in decoder.h. */ - UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(e) - size_before <= + UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(a) - size_before <= UPB_PB_DECODER_SIZE); return d; } @@ -1057,7 +1055,7 @@ bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) { /* Need to reallocate stack and callstack to accommodate. */ size_t old_size = stacksize(d, d->stack_size); size_t new_size = stacksize(d, max); - void *p = upb_env_realloc(d->env, d->stack, old_size, new_size); + void *p = upb_arena_realloc(d->arena, d->stack, old_size, new_size); if (!p) { return false; } @@ -1065,7 +1063,7 @@ bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max) { old_size = callstacksize(d, d->stack_size); new_size = callstacksize(d, max); - p = upb_env_realloc(d->env, d->callstack, old_size, new_size); + p = upb_arena_realloc(d->arena, d->callstack, old_size, new_size); if (!p) { return false; } diff --git a/upb/pb/decoder.h b/upb/pb/decoder.h index ba381f3..6fcef03 100644 --- a/upb/pb/decoder.h +++ b/upb/pb/decoder.h @@ -40,7 +40,9 @@ class DecoderMethodOptions; struct upb_pbdecodermethod; typedef struct upb_pbdecodermethod upb_pbdecodermethod; -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif const upb_handlers *upb_pbdecodermethod_desthandlers( const upb_pbdecodermethod *m); @@ -48,9 +50,8 @@ const upb_byteshandler *upb_pbdecodermethod_inputhandler( const upb_pbdecodermethod *m); bool upb_pbdecodermethod_isnative(const upb_pbdecodermethod *m); -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" */ /* Represents the code to parse a protobuf according to a destination * Handlers. */ @@ -95,9 +96,11 @@ class upb::pb::DecoderMethodPtr { struct upb_pbdecoder; typedef struct upb_pbdecoder upb_pbdecoder; -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif -upb_pbdecoder *upb_pbdecoder_create(upb_env *e, +upb_pbdecoder *upb_pbdecoder_create(upb_arena *arena, const upb_pbdecodermethod *method, upb_sink output); const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d); @@ -107,9 +110,8 @@ size_t upb_pbdecoder_maxnesting(const upb_pbdecoder *d); bool upb_pbdecoder_setmaxnesting(upb_pbdecoder *d, size_t max); void upb_pbdecoder_reset(upb_pbdecoder *d); -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" */ /* A Decoder receives binary protobuf data on its input sink and pushes the * decoded data to its output sink. */ @@ -124,9 +126,10 @@ class upb::pb::DecoderPtr { * must also outlive this decoder. * * The sink must match the given method. */ - static DecoderPtr Create(Environment *env, DecoderMethodPtr method, + static DecoderPtr Create(Arena *arena, DecoderMethodPtr method, upb::Sink output) { - return DecoderPtr(upb_pbdecoder_create(env, method.ptr(), output.sink())); + return DecoderPtr( + upb_pbdecoder_create(arena->ptr(), method.ptr(), output.sink())); } /* Returns the DecoderMethod this decoder is parsing from. */ @@ -171,7 +174,9 @@ class upb::pb::DecoderPtr { struct upb_pbcodecache; typedef struct upb_pbcodecache upb_pbcodecache; -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif upb_pbcodecache *upb_pbcodecache_new(upb_handlercache *dest); void upb_pbcodecache_free(upb_pbcodecache *c); @@ -181,9 +186,8 @@ void upb_pbcodecache_setlazy(upb_pbcodecache *c, bool lazy); const upb_pbdecodermethod *upb_pbcodecache_get(upb_pbcodecache *c, const upb_msgdef *md); -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" */ /* A class for caching protobuf processing code, whether bytecode for the * interpreted decoder or machine code for the JIT. diff --git a/upb/pb/decoder.int.h b/upb/pb/decoder.int.h index 8d464fa..47eb3ed 100644 --- a/upb/pb/decoder.int.h +++ b/upb/pb/decoder.int.h @@ -73,7 +73,7 @@ typedef enum { UPB_INLINE opcode getop(uint32_t instr) { return instr & 0xff; } struct upb_pbcodecache { - upb_arena arena; + upb_arena *arena; upb_handlercache *dest; bool allow_jit; bool lazy; @@ -169,7 +169,7 @@ struct upb_pbdecodermethod { }; struct upb_pbdecoder { - upb_env *env; + upb_arena *arena; /* Our input sink. */ upb_bytessink input_; diff --git a/upb/pb/encoder.c b/upb/pb/encoder.c index 1496eba..722cc5b 100644 --- a/upb/pb/encoder.c +++ b/upb/pb/encoder.c @@ -91,7 +91,7 @@ typedef struct { } upb_pb_encoder_segment; struct upb_pb_encoder { - upb_env *env; + upb_arena *arena; /* Our input and output. */ upb_sink input_; @@ -150,7 +150,7 @@ static bool reserve(upb_pb_encoder *e, size_t bytes) { new_size *= 2; } - new_buf = upb_env_realloc(e->env, e->buf, old_size, new_size); + new_buf = upb_arena_realloc(e->arena, e->buf, old_size, new_size); if (new_buf == NULL) { return false; @@ -230,7 +230,7 @@ static bool start_delim(upb_pb_encoder *e) { (e->seglimit - e->segbuf) * sizeof(upb_pb_encoder_segment); size_t new_size = old_size * 2; upb_pb_encoder_segment *new_buf = - upb_env_realloc(e->env, e->segbuf, old_size, new_size); + upb_arena_realloc(e->arena, e->segbuf, old_size, new_size); if (new_buf == NULL) { return false; @@ -526,22 +526,22 @@ upb_handlercache *upb_pb_encoder_newcache() { return upb_handlercache_new(newhandlers_callback, NULL); } -upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h, +upb_pb_encoder *upb_pb_encoder_create(upb_arena *arena, const upb_handlers *h, upb_bytessink output) { const size_t initial_bufsize = 256; const size_t initial_segbufsize = 16; /* TODO(haberman): make this configurable. */ const size_t stack_size = 64; #ifndef NDEBUG - const size_t size_before = upb_env_bytesallocated(env); + const size_t size_before = upb_arena_bytesallocated(arena); #endif - upb_pb_encoder *e = upb_env_malloc(env, sizeof(upb_pb_encoder)); + upb_pb_encoder *e = upb_arena_malloc(arena, sizeof(upb_pb_encoder)); if (!e) return NULL; - e->buf = upb_env_malloc(env, initial_bufsize); - e->segbuf = upb_env_malloc(env, initial_segbufsize * sizeof(*e->segbuf)); - e->stack = upb_env_malloc(env, stack_size * sizeof(*e->stack)); + e->buf = upb_arena_malloc(arena, initial_bufsize); + e->segbuf = upb_arena_malloc(arena, initial_segbufsize * sizeof(*e->segbuf)); + e->stack = upb_arena_malloc(arena, stack_size * sizeof(*e->stack)); if (!e->buf || !e->segbuf || !e->stack) { return NULL; @@ -554,13 +554,13 @@ upb_pb_encoder *upb_pb_encoder_create(upb_env *env, const upb_handlers *h, upb_pb_encoder_reset(e); upb_sink_reset(&e->input_, h, e); - e->env = env; + e->arena = arena; e->output_ = output; e->subc = output.closure; e->ptr = e->buf; /* If this fails, increase the value in encoder.h. */ - UPB_ASSERT_DEBUGVAR(upb_env_bytesallocated(env) - size_before <= + UPB_ASSERT_DEBUGVAR(upb_arena_bytesallocated(arena) - size_before <= UPB_PB_ENCODER_SIZE); return e; } diff --git a/upb/pb/encoder.h b/upb/pb/encoder.h index 7aa2870..780f60f 100644 --- a/upb/pb/encoder.h +++ b/upb/pb/encoder.h @@ -35,17 +35,18 @@ class EncoderPtr; struct upb_pb_encoder; typedef struct upb_pb_encoder upb_pb_encoder; -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif upb_sink upb_pb_encoder_input(upb_pb_encoder *p); -upb_pb_encoder* upb_pb_encoder_create(upb_env* e, const upb_handlers* h, +upb_pb_encoder* upb_pb_encoder_create(upb_arena* a, const upb_handlers* h, upb_bytessink output); upb_handlercache *upb_pb_encoder_newcache(); -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" { */ class upb::pb::EncoderPtr { public: @@ -55,9 +56,10 @@ class upb::pb::EncoderPtr { /* Creates a new encoder in the given environment. The Handlers must have * come from NewHandlers() below. */ - static EncoderPtr Create(Environment* env, const Handlers* handlers, + static EncoderPtr Create(Arena* arena, const Handlers* handlers, BytesSink output) { - return EncoderPtr(upb_pb_encoder_create(env, handlers, output.sink())); + return EncoderPtr( + upb_pb_encoder_create(arena->ptr(), handlers, output.sink())); } /* The input to the encoder. */ diff --git a/upb/pb/textprinter.c b/upb/pb/textprinter.c index d1d539d..91d0d55 100644 --- a/upb/pb/textprinter.c +++ b/upb/pb/textprinter.c @@ -18,7 +18,7 @@ struct upb_textprinter { upb_sink input_; - upb_bytessink *output_; + upb_bytessink output_; int indent_depth_; bool single_line_; void *subc; @@ -35,13 +35,13 @@ static int indent(upb_textprinter *p) { int i; if (!p->single_line_) for (i = 0; i < p->indent_depth_; i++) - upb_bytessink_putbuf(p->output_, p->subc, " ", 2, NULL); + upb_bytessink_putbuf(&p->output_, p->subc, " ", 2, NULL); return 0; } static int endfield(upb_textprinter *p) { const char ch = (p->single_line_ ? ' ' : '\n'); - upb_bytessink_putbuf(p->output_, p->subc, &ch, 1, NULL); + upb_bytessink_putbuf(&p->output_, p->subc, &ch, 1, NULL); return 0; } @@ -60,7 +60,7 @@ static int putescaped(upb_textprinter *p, const char *buf, size_t len, bool is_hex_escape; if (dstend - dst < 4) { - upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL); + upb_bytessink_putbuf(&p->output_, p->subc, dstbuf, dst - dstbuf, NULL); dst = dstbuf; } @@ -88,7 +88,7 @@ static int putescaped(upb_textprinter *p, const char *buf, size_t len, last_hex_escape = is_hex_escape; } /* Flush remaining data. */ - upb_bytessink_putbuf(p->output_, p->subc, dstbuf, dst - dstbuf, NULL); + upb_bytessink_putbuf(&p->output_, p->subc, dstbuf, dst - dstbuf, NULL); return 0; } @@ -114,7 +114,7 @@ bool putf(upb_textprinter *p, const char *fmt, ...) { va_end(args); UPB_ASSERT(written == len); - ok = upb_bytessink_putbuf(p->output_, p->subc, str, len, NULL); + ok = upb_bytessink_putbuf(&p->output_, p->subc, str, len, NULL); upb_gfree(str); return ok; } @@ -126,7 +126,7 @@ static bool textprinter_startmsg(void *c, const void *hd) { upb_textprinter *p = c; UPB_UNUSED(hd); if (p->indent_depth_ == 0) { - upb_bytessink_start(p->output_, 0, &p->subc); + upb_bytessink_start(&p->output_, 0, &p->subc); } return true; } @@ -136,7 +136,7 @@ static bool textprinter_endmsg(void *c, const void *hd, upb_status *s) { UPB_UNUSED(hd); UPB_UNUSED(s); if (p->indent_depth_ == 0) { - upb_bytessink_end(p->output_); + upb_bytessink_end(&p->output_); } return true; } @@ -241,7 +241,7 @@ static bool textprinter_endsubmsg(void *closure, const void *handler_data) { UPB_UNUSED(handler_data); p->indent_depth_--; CHECK(indent(p)); - upb_bytessink_putbuf(p->output_, p->subc, "}", 1, NULL); + upb_bytessink_putbuf(&p->output_, p->subc, "}", 1, NULL); CHECK(endfield(p)); return true; err: @@ -315,9 +315,9 @@ static void textprinter_reset(upb_textprinter *p, bool single_line) { /* Public API *****************************************************************/ -upb_textprinter *upb_textprinter_create(upb_env *env, const upb_handlers *h, - upb_bytessink *output) { - upb_textprinter *p = upb_env_malloc(env, sizeof(upb_textprinter)); +upb_textprinter *upb_textprinter_create(upb_arena *arena, const upb_handlers *h, + upb_bytessink output) { + upb_textprinter *p = upb_arena_malloc(arena, sizeof(upb_textprinter)); if (!p) return NULL; p->output_ = output; @@ -331,7 +331,7 @@ upb_handlercache *upb_textprinter_newcache() { return upb_handlercache_new(&onmreg, NULL); } -upb_sink *upb_textprinter_input(upb_textprinter *p) { return &p->input_; } +upb_sink upb_textprinter_input(upb_textprinter *p) { return p->input_; } void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line) { p->single_line_ = single_line; diff --git a/upb/pb/textprinter.h b/upb/pb/textprinter.h index 06ff7d5..e59e11d 100644 --- a/upb/pb/textprinter.h +++ b/upb/pb/textprinter.h @@ -17,60 +17,51 @@ class TextPrinter; } /* namespace upb */ #endif -UPB_DECLARE_TYPE(upb::pb::TextPrinter, upb_textprinter) +/* upb_textprinter ************************************************************/ + +struct upb_textprinter; +typedef struct upb_textprinter upb_textprinter; #ifdef __cplusplus +extern "C" { +#endif -class upb::pb::TextPrinter { +/* C API. */ +upb_textprinter *upb_textprinter_create(upb_arena *arena, const upb_handlers *h, + upb_bytessink output); +void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line); +upb_sink upb_textprinter_input(upb_textprinter *p); +upb_handlercache *upb_textprinter_newcache(); + +#ifdef __cplusplus +} /* extern "C" */ + +class upb::pb::TextPrinterPtr { public: + TextPrinterPtr(upb_textprinter* ptr) : ptr_(ptr) {} + /* The given handlers must have come from NewHandlers(). It must outlive the * TextPrinter. */ - static TextPrinter *Create(Environment *env, const upb::Handlers *handlers, - BytesSink *output); + static TextPrinterPtr *Create(Arena *arena, const upb::Handlers *handlers, + BytesSink output) { + return TextPrinterPtr(upb_textprinter_create(arena, handlers, output)); + } - void SetSingleLineMode(bool single_line); + void SetSingleLineMode(bool single_line) { + upb_textprinter_setsingleline(ptr_, single_line); + } - Sink* input(); + Sink input() { return upb_textprinter_input(ptr_); } /* If handler caching becomes a requirement we can add a code cache as in * decoder.h */ - static HandlerCache* NewCache(); -}; - -#endif - -UPB_BEGIN_EXTERN_C + static HandlerCache NewCache() { + return HandlerCache(upb_textprinter_newcache()); + } -/* C API. */ -upb_textprinter *upb_textprinter_create(upb_env *env, const upb_handlers *h, - upb_bytessink *output); -void upb_textprinter_setsingleline(upb_textprinter *p, bool single_line); -upb_sink *upb_textprinter_input(upb_textprinter *p); - -upb_handlercache *upb_textprinter_newcache(); - -UPB_END_EXTERN_C - -#ifdef __cplusplus - -namespace upb { -namespace pb { -inline TextPrinter *TextPrinter::Create(Environment *env, - const upb::Handlers *handlers, - BytesSink *output) { - return upb_textprinter_create(env, handlers, output); -} -inline void TextPrinter::SetSingleLineMode(bool single_line) { - upb_textprinter_setsingleline(this, single_line); -} -inline Sink* TextPrinter::input() { - return upb_textprinter_input(this); -} -inline HandlerCache* TextPrinter::NewCache() { - return upb_textprinter_newcache(); -} -} /* namespace pb */ -} /* namespace upb */ + private: + upb_textprinter* ptr_; +}; #endif diff --git a/upb/sink.c b/upb/sink.c index 6ef5718..7a7eeb4 100644 --- a/upb/sink.c +++ b/upb/sink.c @@ -15,73 +15,3 @@ bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink sink) { } return ret; } - -struct upb_bufsink { - upb_byteshandler handler; - upb_bytessink sink; - upb_env *env; - char *ptr; - size_t len, size; -}; - -static void *upb_bufsink_start(void *_sink, const void *hd, size_t size_hint) { - upb_bufsink *sink = _sink; - UPB_UNUSED(hd); - UPB_UNUSED(size_hint); - sink->len = 0; - return sink; -} - -static size_t upb_bufsink_string(void *_sink, const void *hd, const char *ptr, - size_t len, const upb_bufhandle *handle) { - upb_bufsink *sink = _sink; - size_t new_size = sink->size; - - UPB_ASSERT(new_size > 0); - UPB_UNUSED(hd); - UPB_UNUSED(handle); - - while (sink->len + len > new_size) { - new_size *= 2; - } - - if (new_size != sink->size) { - sink->ptr = upb_env_realloc(sink->env, sink->ptr, sink->size, new_size); - sink->size = new_size; - } - - memcpy(sink->ptr + sink->len, ptr, len); - sink->len += len; - - return len; -} - -upb_bufsink *upb_bufsink_new(upb_env *env) { - upb_bufsink *sink = upb_env_malloc(env, sizeof(upb_bufsink)); - upb_byteshandler_init(&sink->handler); - upb_byteshandler_setstartstr(&sink->handler, upb_bufsink_start, NULL); - upb_byteshandler_setstring(&sink->handler, upb_bufsink_string, NULL); - - upb_bytessink_reset(&sink->sink, &sink->handler, sink); - - sink->env = env; - sink->size = 32; - sink->ptr = upb_env_malloc(env, sink->size); - sink->len = 0; - - return sink; -} - -void upb_bufsink_free(upb_bufsink *sink) { - upb_env_free(sink->env, sink->ptr); - upb_env_free(sink->env, sink); -} - -upb_bytessink *upb_bufsink_sink(upb_bufsink *sink) { - return &sink->sink; -} - -const char *upb_bufsink_getdata(const upb_bufsink *sink, size_t *len) { - *len = sink->len; - return sink->ptr; -} diff --git a/upb/sink.h b/upb/sink.h index 1855542..d93d966 100644 --- a/upb/sink.h +++ b/upb/sink.h @@ -29,7 +29,9 @@ class Sink; /* upb_sink *******************************************************************/ -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif typedef struct { const upb_handlers *handlers; @@ -192,9 +194,8 @@ UPB_INLINE bool upb_sink_endsubmsg(upb_sink *s, upb_selector_t sel) { return endsubmsg(s->closure, hd); } -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" */ /* A upb::Sink is an object that binds a upb::Handlers object to some runtime * state. It represents an endpoint to which data can be sent. @@ -288,7 +289,9 @@ class upb::Sink { * sink->EndMessage(&status); * sink->EndSubMessage(endsubmsg_selector); */ bool StartMessage() { return upb_sink_startmsg(&sink_); } - bool EndMessage(Status* status) { return upb_sink_endmsg(&sink_, status); } + bool EndMessage(upb_status *status) { + return upb_sink_endmsg(&sink_, status); + } /* Putting of individual values. These work for both repeated and * non-repeated fields, but for repeated fields you must wrap them in @@ -489,13 +492,14 @@ class upb::BytesSink { /* upb_bufsrc *****************************************************************/ -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif bool upb_bufsrc_putbuf(const char *buf, size_t len, upb_bytessink sink); -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" */ namespace upb { template bool PutBuffer(const T& str, BytesSink sink) { @@ -505,19 +509,4 @@ template bool PutBuffer(const T& str, BytesSink sink) { #endif /* __cplusplus */ -/* upb_bufsink ****************************************************************/ - -/* A class for accumulating output string data in a flat buffer. */ -struct upb_bufsink; -typedef struct upb_bufsink upb_bufsink; - -UPB_BEGIN_EXTERN_C - -upb_bufsink *upb_bufsink_init(upb_env *env); -void upb_bufsink_free(upb_bufsink *sink); -upb_bytessink *upb_bufsink_sink(upb_bufsink *sink); -const char *upb_bufsink_getdata(const upb_bufsink *sink, size_t *len); - -UPB_END_EXTERN_C - #endif diff --git a/upb/table.int.h b/upb/table.int.h index 63dce59..2b86390 100644 --- a/upb/table.int.h +++ b/upb/table.int.h @@ -156,21 +156,6 @@ UPB_INLINE upb_value upb_value_double(double cval) { * initializing a non-first union member. */ typedef uintptr_t upb_tabkey; -#define UPB_TABKEY_NUM(n) n -#define UPB_TABKEY_NONE 0 -/* The preprocessor isn't quite powerful enough to turn the compile-time string - * length into a byte-wise string representation, so code generation needs to - * help it along. - * - * "len1" is the low byte and len4 is the high byte. */ -#ifdef UPB_BIG_ENDIAN -#define UPB_TABKEY_STR(len1, len2, len3, len4, strval) \ - (uintptr_t)(len4 len3 len2 len1 strval) -#else -#define UPB_TABKEY_STR(len1, len2, len3, len4, strval) \ - (uintptr_t)(len1 len2 len3 len4 strval) -#endif - UPB_INLINE char *upb_tabstr(upb_tabkey key, uint32_t *len) { char* mem = (char*)key; if (len) memcpy(len, mem, sizeof(*len)); diff --git a/upb/upb.c b/upb/upb.c index 68e26b0..f56f6c4 100644 --- a/upb/upb.c +++ b/upb/upb.c @@ -8,12 +8,6 @@ #include #include "upb/upb.h" -bool upb_dumptostderr(void *closure, const upb_status* status) { - UPB_UNUSED(closure); - fprintf(stderr, "%s\n", upb_status_errmsg(status)); - return false; -} - /* Guarantee null-termination and provide ellipsis truncation. * It may be tempting to "optimize" this by initializing these final * four bytes up-front and then being careful never to overwrite them, @@ -29,24 +23,17 @@ static void nullz(upb_status *status) { void upb_status_clear(upb_status *status) { if (!status) return; - status->ok_ = true; - status->code_ = 0; + status->ok = true; status->msg[0] = '\0'; } -bool upb_ok(const upb_status *status) { return status->ok_; } - -upb_errorspace *upb_status_errspace(const upb_status *status) { - return status->error_space_; -} - -int upb_status_errcode(const upb_status *status) { return status->code_; } +bool upb_ok(const upb_status *status) { return status->ok; } const char *upb_status_errmsg(const upb_status *status) { return status->msg; } void upb_status_seterrmsg(upb_status *status, const char *msg) { if (!status) return; - status->ok_ = false; + status->ok = false; strncpy(status->msg, msg, sizeof(status->msg)); nullz(status); } @@ -60,17 +47,11 @@ void upb_status_seterrf(upb_status *status, const char *fmt, ...) { void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args) { if (!status) return; - status->ok_ = false; + status->ok = false; _upb_vsnprintf(status->msg, sizeof(status->msg), fmt, args); nullz(status); } -void upb_status_copy(upb_status *to, const upb_status *from) { - if (!to) return; - *to = *from; -} - - /* upb_alloc ******************************************************************/ static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize, @@ -87,7 +68,6 @@ static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize, upb_alloc upb_alloc_global = {&upb_global_allocfunc}; - /* upb_arena ******************************************************************/ /* Be conservative and choose 16 in case anyone is using SSE. */ @@ -115,11 +95,7 @@ struct upb_arena { /* Cleanup entries. Pointer to a cleanup_ent, defined in env.c */ void *cleanup_head; - - /* For future expansion, since the size of this struct is exposed to users. */ - void *future1; - void *future2; -} upb_arena; +}; typedef struct mem_block { struct mem_block *next; @@ -149,7 +125,6 @@ static void upb_arena_addblock(upb_arena *a, void *ptr, size_t size, /* TODO(haberman): ASAN poison. */ } - static mem_block *upb_arena_allocblock(upb_arena *a, size_t size) { size_t block_size = UPB_MAX(size, a->next_block_size) + sizeof(mem_block); mem_block *block = upb_malloc(a->block_alloc, block_size); @@ -202,7 +177,25 @@ static void *upb_arena_doalloc(upb_alloc *alloc, void *ptr, size_t oldsize, /* Public Arena API ***********************************************************/ -void upb_arena_init(upb_arena *a) { +upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc) { + const size_t first_block_overhead = sizeof(upb_arena) + sizeof(mem_block); + upb_arena *a; + bool owned = false; + + if (n < first_block_overhead) { + /* We need to malloc the initial block. */ + n = first_block_overhead + 256; + owned = true; + if (!alloc || !(mem = upb_malloc(alloc, n))) { + return NULL; + } + } + + a = mem; + mem = (char*)mem + sizeof(*a); + n -= sizeof(*a); + upb_arena_addblock(a, mem, n, owned); + a->alloc.func = &upb_arena_doalloc; a->block_alloc = &upb_alloc_global; a->bytes_allocated = 0; @@ -210,21 +203,12 @@ void upb_arena_init(upb_arena *a) { a->max_block_size = 16384; a->cleanup_head = NULL; a->block_head = NULL; -} - -void upb_arena_init2(upb_arena *a, void *mem, size_t size, upb_alloc *alloc) { - upb_arena_init(a); + a->block_alloc = alloc; - if (size > sizeof(mem_block)) { - upb_arena_addblock(a, mem, size, false); - } - - if (alloc) { - a->block_alloc = alloc; - } + return a; } -void upb_arena_uninit(upb_arena *a) { +void upb_arena_free(upb_arena *a) { cleanup_ent *ent = a->cleanup_head; mem_block *block = a->block_head; @@ -236,6 +220,7 @@ void upb_arena_uninit(upb_arena *a) { /* Must do this after running cleanup functions, because this will delete * the memory we store our cleanup entries in! */ while (block) { + /* Load first since we are deleting block. */ mem_block *next = block->next; if (block->owned) { @@ -244,10 +229,6 @@ void upb_arena_uninit(upb_arena *a) { block = next; } - - /* Protect against multiple-uninit. */ - a->cleanup_head = NULL; - a->block_head = NULL; } bool upb_arena_addcleanup(upb_arena *a, upb_cleanup_func *func, void *ud) { diff --git a/upb/upb.h b/upb/upb.h index 4384812..07b0455 100644 --- a/upb/upb.h +++ b/upb/upb.h @@ -15,14 +15,11 @@ #include #ifdef __cplusplus +#include namespace upb { -class Allocator; class Arena; -class Environment; -class ErrorSpace; class Status; template class InlinedArena; -template class InlinedEnvironment; } #endif @@ -74,46 +71,14 @@ template class InlinedEnvironment; #error Need implementations of [v]snprintf and va_copy #endif -#if (defined(__cplusplus) && __cplusplus >= 201103L) || \ - defined(__GXX_EXPERIMENTAL_CXX0X__) || \ +#ifdef __cplusplus +#if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__) || \ (defined(_MSC_VER) && _MSC_VER >= 1900) // C++11 is present #else #error upb requires C++11 for C++ support #endif - -/* UPB_DISALLOW_COPY_AND_ASSIGN() - * UPB_DISALLOW_POD_OPS() - * - * Declare these in the "private" section of a C++ class to forbid copy/assign - * or all POD ops (construct, destruct, copy, assign) on that class. */ -#include -#define UPB_DISALLOW_COPY_AND_ASSIGN(class_name) \ - class_name(const class_name&) = delete; \ - void operator=(const class_name&) = delete; -#define UPB_DISALLOW_POD_OPS(class_name, full_class_name) \ - class_name() = delete; \ - ~class_name() = delete; \ - UPB_DISALLOW_COPY_AND_ASSIGN(class_name) -#define UPB_ASSERT_STDLAYOUT(type) \ - static_assert(std::is_standard_layout::value, \ - #type " must be standard layout"); - -#ifdef __cplusplus - -#define UPB_BEGIN_EXTERN_C extern "C" { -#define UPB_END_EXTERN_C } -#define UPB_DECLARE_TYPE(cppname, cname) typedef cppname cname; - -#else /* !defined(__cplusplus) */ - -#define UPB_BEGIN_EXTERN_C -#define UPB_END_EXTERN_C -#define UPB_DECLARE_TYPE(cppname, cname) \ - struct cname; \ - typedef struct cname cname; - -#endif /* defined(__cplusplus) */ +#endif #define UPB_MAX(x, y) ((x) > (y) ? (x) : (y)) #define UPB_MIN(x, y) ((x) < (y) ? (x) : (y)) @@ -138,21 +103,26 @@ template class InlinedEnvironment; #define UPB_UNREACHABLE() do { assert(0); } while(0) #endif -/* upb::Status ****************************************************************/ +/* upb_status *****************************************************************/ -/* upb::Status represents a success or failure status and error message. +/* upb_status represents a success or failure status and error message. * It owns no resources and allocates no memory, so it should work * even in OOM situations. */ -UPB_DECLARE_TYPE(upb::Status, upb_status) /* The maximum length of an error message before it will get truncated. */ -#define UPB_STATUS_MAX_MESSAGE 128 +#define UPB_STATUS_MAX_MESSAGE 127 -UPB_BEGIN_EXTERN_C +typedef struct { + bool ok; + char msg[UPB_STATUS_MAX_MESSAGE]; /* Error message; NULL-terminated. */ +} upb_status; + +#ifdef __cplusplus +extern "C" { +#endif const char *upb_status_errmsg(const upb_status *status); bool upb_ok(const upb_status *status); -int upb_status_errcode(const upb_status *status); /* Any of the functions that write to a status object allow status to be NULL, * to support use cases where the function's caller does not care about the @@ -161,60 +131,44 @@ void upb_status_clear(upb_status *status); void upb_status_seterrmsg(upb_status *status, const char *msg); void upb_status_seterrf(upb_status *status, const char *fmt, ...); void upb_status_vseterrf(upb_status *status, const char *fmt, va_list args); -void upb_status_copy(upb_status *to, const upb_status *from); -UPB_END_EXTERN_C +UPB_INLINE void upb_status_setoom(upb_status *status) { + upb_status_seterrmsg(status, "out of memory"); +} #ifdef __cplusplus +} /* extern "C" */ class upb::Status { public: - Status() { upb_status_clear(this); } + Status() { upb_status_clear(&status_); } - /* Returns true if there is no error. */ - bool ok() const { return upb_ok(this); } + upb_status* ptr() { return &status_; } - /* Optional error space and code, useful if the caller wants to - * programmatically check the specific kind of error. */ - ErrorSpace* error_space() { return upb_status_errspace(this); } - int error_code() const { return upb_status_errcode(this); } + /* Returns true if there is no error. */ + bool ok() const { return upb_ok(&status_); } - /* The returned string is invalidated by any other call into the status. */ - const char *error_message() const { return upb_status_errmsg(this); } + /* Guaranteed to be NULL-terminated. */ + const char *error_message() const { return upb_status_errmsg(&status_); } /* The error message will be truncated if it is longer than * UPB_STATUS_MAX_MESSAGE-4. */ - void SetErrorMessage(const char* msg) { upb_status_seterrmsg(this, msg); } - void SetFormattedErrorMessage(const char* fmt, ...) { + void SetErrorMessage(const char *msg) { upb_status_seterrmsg(&status_, msg); } + void SetFormattedErrorMessage(const char *fmt, ...) { va_list args; va_start(args, fmt); - upb_status_vseterrf(this, fmt, args); + upb_status_vseterrf(&status_, fmt, args); va_end(args); } /* Resets the status to a successful state with no message. */ - void Clear() { upb_status_clear(this); } - - void CopyFrom(const Status& other) { upb_status_copy(this, &other); } + void Clear() { upb_status_clear(&status_); } private: - UPB_DISALLOW_COPY_AND_ASSIGN(Status) -#else -struct upb_status { -#endif - bool ok_; - - /* Specific status code defined by some error space (optional). */ - int code_; - upb_errorspace *error_space_; - - /* TODO(haberman): add file/line of error? */ - - /* Error message; NULL-terminated. */ - char msg[UPB_STATUS_MAX_MESSAGE]; + upb_status status_; }; -#define UPB_STATUS_INIT {true, 0, NULL, {0}} +#endif /* __cplusplus */ /** upb_alloc *****************************************************************/ @@ -291,17 +245,23 @@ UPB_INLINE void upb_gfree(void *ptr) { typedef void upb_cleanup_func(void *ud); struct upb_arena; -typedef upb_arena upb_arena; +typedef struct upb_arena upb_arena; -UPB_BEGIN_EXTERN_C +#ifdef __cplusplus +extern "C" { +#endif -upb_arena *upb_arena_new2(void *mem, size_t n, upb_alloc *alloc); +/* Creates an arena from the given initial block (if any -- n may be 0). + * Additional blocks will be allocated from |alloc|. If |alloc| is NULL, this + * is a fixed-size arena and cannot grow. */ +upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc); void upb_arena_free(upb_arena *a); bool upb_arena_addcleanup(upb_arena *a, upb_cleanup_func *func, void *ud); size_t upb_arena_bytesallocated(const upb_arena *a); UPB_INLINE upb_alloc *upb_arena_alloc(upb_arena *a) { return (upb_alloc*)a; } +/* Convenience wrappers around upb_alloc functions. */ UPB_INLINE void *upb_arena_malloc(upb_arena *a, size_t size) { return upb_malloc(upb_arena_alloc(a), size); } @@ -312,52 +272,38 @@ UPB_INLINE void *upb_arena_realloc(upb_arena *a, void *ptr, size_t oldsize, } UPB_INLINE upb_arena *upb_arena_new() { - return upb_arena_new2(NULL, 0, &upb_alloc_global); + return upb_arena_init(NULL, 0, &upb_alloc_global); } -UPB_END_EXTERN_C - #ifdef __cplusplus +} /* extern "C" */ class upb::Arena { public: /* A simple arena with no initial memory block and the default allocator. */ - Arena() { upb_arena_init(&arena_); } + Arena() : ptr_(upb_arena_new(), upb_arena_free) {} - upb_arena* ptr() { return &arena_; } - - /* Constructs an arena with the given initial block which allocates blocks - * with the given allocator. The given allocator must outlive the Arena. - * - * If you pass NULL for the allocator it will default to the global allocator - * upb_alloc_global, and NULL/0 for the initial block will cause there to be - * no initial block. */ - Arena(void *mem, size_t len, upb_alloc *a) { - upb_arena_init2(&arena_, mem, len, a); - } - - ~Arena() { upb_arena_uninit(&arena_); } + upb_arena* ptr() { return ptr_.get(); } /* Allows this arena to be used as a generic allocator. * * The arena does not need free() calls so when using Arena as an allocator * it is safe to skip them. However they are no-ops so there is no harm in * calling free() either. */ - upb_alloc *allocator() { return upb_arena_alloc(&arena_); } + upb_alloc *allocator() { return upb_arena_alloc(ptr_.get()); } /* Add a cleanup function to run when the arena is destroyed. * Returns false on out-of-memory. */ bool AddCleanup(upb_cleanup_func *func, void *ud) { - return upb_arena_addcleanup(&arena_, func, ud); + return upb_arena_addcleanup(ptr_.get(), func, ud); } /* Total number of bytes that have been allocated. It is undefined what * Realloc() does to &arena_ counter. */ - size_t BytesAllocated() const { return upb_arena_bytesallocated(&arena_); } + size_t BytesAllocated() const { return upb_arena_bytesallocated(ptr_.get()); } private: - UPB_DISALLOW_COPY_AND_ASSIGN(Arena) - upb_arena arena_; + std::unique_ptr ptr_; }; #endif @@ -373,13 +319,16 @@ class upb::Arena { template class upb::InlinedArena : public upb::Arena { public: - InlinedArena() : Arena(initial_block_, N, NULL) {} - explicit InlinedArena(Allocator* a) : Arena(initial_block_, N, a) {} + InlinedArena() : ptr_(upb_arena_new(&initial_block_, N, &upb_alloc_global)) {} + + upb_arena* ptr() { return ptr_.get(); } private: - UPB_DISALLOW_COPY_AND_ASSIGN(InlinedArena) + InlinedArena(const InlinedArena*) = delete; + InlinedArena& operator=(const InlinedArena*) = delete; - char initial_block_[N + UPB_ARENA_BLOCK_OVERHEAD]; + std::unique_ptr ptr_; + char initial_block_[N]; }; #endif /* __cplusplus */ diff --git a/upbc/generator.cc b/upbc/generator.cc index ddfaa7b..de40eee 100644 --- a/upbc/generator.cc +++ b/upbc/generator.cc @@ -502,7 +502,9 @@ void WriteHeader(const protobuf::FileDescriptor* file, Output& output) { "#include \"upb/decode.h\"\n" "#include \"upb/encode.h\"\n" "#include \"upb/port_def.inc\"\n" - "UPB_BEGIN_EXTERN_C\n\n", + "#ifdef __cplusplus\n" + "extern \"C\" {\n" + "#endif\n\n", ToPreproc(file->name())); // Forward-declare types defined in this file. @@ -548,7 +550,9 @@ void WriteHeader(const protobuf::FileDescriptor* file, Output& output) { } output( - "UPB_END_EXTERN_C\n" + "#ifdef __cplusplus\n" + "} /* extern \"C\" */\n" + "#endif\n" "\n" "#include \"upb/port_undef.inc\"\n" "\n" -- cgit v1.2.3 From 8cd3b9dfa99764685727e065e43fb405ca5aa29f Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Thu, 17 Jan 2019 12:38:04 -0800 Subject: Moved some definitions to def.h --- upb/bindings/lua/def.c | 4 - upb/def.h | 31 +++++ upb/json/parser.c | 361 +++++++++---------------------------------------- upb/json/parser.rl | 20 +-- upb/json/printer.c | 5 +- upb/upb.h | 39 ------ 6 files changed, 106 insertions(+), 354 deletions(-) (limited to 'upb/bindings') diff --git a/upb/bindings/lua/def.c b/upb/bindings/lua/def.c index e16d426..3868179 100644 --- a/upb/bindings/lua/def.c +++ b/upb/bindings/lua/def.c @@ -728,10 +728,6 @@ void lupb_def_registertypes(lua_State *L) { lupb_setfieldi(L, "TYPE_UINT32", UPB_TYPE_UINT32); lupb_setfieldi(L, "TYPE_ENUM", UPB_TYPE_ENUM); - lupb_setfieldi(L, "INTFMT_VARIABLE", UPB_INTFMT_VARIABLE); - lupb_setfieldi(L, "INTFMT_FIXED", UPB_INTFMT_FIXED); - lupb_setfieldi(L, "INTFMT_ZIGZAG", UPB_INTFMT_ZIGZAG); - lupb_setfieldi(L, "DESCRIPTOR_TYPE_DOUBLE", UPB_DESCRIPTOR_TYPE_DOUBLE); lupb_setfieldi(L, "DESCRIPTOR_TYPE_FLOAT", UPB_DESCRIPTOR_TYPE_FLOAT); lupb_setfieldi(L, "DESCRIPTOR_TYPE_INT64", UPB_DESCRIPTOR_TYPE_INT64); diff --git a/upb/def.h b/upb/def.h index 7675138..2c336c5 100644 --- a/upb/def.h +++ b/upb/def.h @@ -50,6 +50,37 @@ typedef struct upb_oneofdef upb_oneofdef; struct upb_symtab; typedef struct upb_symtab upb_symtab; +typedef enum { + UPB_SYNTAX_PROTO2 = 2, + UPB_SYNTAX_PROTO3 = 3 +} upb_syntax_t; + +/* All the different kind of well known type messages. For simplicity of check, + * number wrappers and string wrappers are grouped together. Make sure the + * order and merber of these groups are not changed. + */ +typedef enum { + UPB_WELLKNOWN_UNSPECIFIED, + UPB_WELLKNOWN_ANY, + UPB_WELLKNOWN_FIELDMASK, + UPB_WELLKNOWN_DURATION, + UPB_WELLKNOWN_TIMESTAMP, + /* number wrappers */ + UPB_WELLKNOWN_DOUBLEVALUE, + UPB_WELLKNOWN_FLOATVALUE, + UPB_WELLKNOWN_INT64VALUE, + UPB_WELLKNOWN_UINT64VALUE, + UPB_WELLKNOWN_INT32VALUE, + UPB_WELLKNOWN_UINT32VALUE, + /* string wrappers */ + UPB_WELLKNOWN_STRINGVALUE, + UPB_WELLKNOWN_BYTESVALUE, + UPB_WELLKNOWN_BOOLVALUE, + UPB_WELLKNOWN_VALUE, + UPB_WELLKNOWN_LISTVALUE, + UPB_WELLKNOWN_STRUCT +} upb_wellknowntype_t; + /* upb_fielddef ***************************************************************/ /* Maximum field number allowed for FieldDefs. This is an inherent limit of the diff --git a/upb/json/parser.c b/upb/json/parser.c index 38a0535..0b9eb92 100644 --- a/upb/json/parser.c +++ b/upb/json/parser.c @@ -21,6 +21,7 @@ ** - handling of keys/escape-sequences/etc that span input buffers. */ +#include #include #include #include @@ -63,7 +64,6 @@ static bool is_string_wrapper_object(upb_json_parser *p); static bool does_string_wrapper_start(upb_json_parser *p); static bool does_string_wrapper_end(upb_json_parser *p); -static bool is_fieldmask_object(upb_json_parser *p); static bool does_fieldmask_start(upb_json_parser *p); static bool does_fieldmask_end(upb_json_parser *p); static void start_fieldmask_object(upb_json_parser *p); @@ -1332,13 +1332,8 @@ static bool end_stringval_nontop(upb_json_parser *p) { case UPB_TYPE_STRING: { upb_selector_t sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR); -<<<<<<< HEAD - p->top--; upb_sink_endstr(p->top->sink, sel); -======= - upb_sink_endstr(&p->top->sink, sel); p->top--; ->>>>>>> arrayapi break; } @@ -1675,9 +1670,7 @@ static void start_fieldmask_path_text(upb_json_parser *p, const char *ptr) { } static bool end_fieldmask_path_text(upb_json_parser *p, const char *ptr) { - if (!capture_end(p, ptr)) { - return false; - } + return capture_end(p, ptr); } static bool start_fieldmask_path(upb_json_parser *p) { @@ -1690,7 +1683,7 @@ static bool start_fieldmask_path(upb_json_parser *p) { * handler frames, and string events occur in a sub-frame. */ inner = p->top + 1; sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR); - upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink); + upb_sink_startstr(p->top->sink, sel, 0, &inner->sink); inner->m = p->top->m; inner->f = p->top->f; inner->name_table = NULL; @@ -1712,10 +1705,10 @@ static bool lower_camel_push( for (;ptr < limit; ptr++) { if (*ptr >= 'A' && *ptr <= 'Z' && !first) { char lower = tolower(*ptr); - upb_sink_putstring(&p->top->sink, sel, "_", 1, NULL); - upb_sink_putstring(&p->top->sink, sel, &lower, 1, NULL); + upb_sink_putstring(p->top->sink, sel, "_", 1, NULL); + upb_sink_putstring(p->top->sink, sel, &lower, 1, NULL); } else { - upb_sink_putstring(&p->top->sink, sel, ptr, 1, NULL); + upb_sink_putstring(p->top->sink, sel, ptr, 1, NULL); } first = false; } @@ -1732,7 +1725,7 @@ static bool end_fieldmask_path(upb_json_parser *p) { } sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR); - upb_sink_endstr(&p->top->sink, sel); + upb_sink_endstr(p->top->sink, sel); p->top--; multipart_end(p); @@ -1796,11 +1789,7 @@ static bool parse_mapentry_key(upb_json_parser *p) { sel = getsel_for_handlertype(p, UPB_HANDLER_STRING); upb_sink_putstring(subsink, sel, buf, len, NULL); sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR); -<<<<<<< HEAD - upb_sink_endstr(p->top->sink, sel); -======= - upb_sink_endstr(&subsink, sel); ->>>>>>> arrayapi + upb_sink_endstr(subsink, sel); multipart_end(p); break; } @@ -2498,10 +2487,6 @@ static bool does_fieldmask_end(upb_json_parser *p) { return p->top->m != NULL && is_fieldmask(p->top->m); } -static bool is_fieldmask_object(upb_json_parser *p) { - return p->top->m != NULL && is_fieldmask(p->top->m); -} - #define CHECK_RETURN_TOP(x) if (!(x)) goto error @@ -2523,19 +2508,11 @@ static bool is_fieldmask_object(upb_json_parser *p) { * final state once, when the closing '"' is seen. */ -<<<<<<< HEAD -#line 2542 "upb/json/parser.rl" +#line 2690 "upb/json/parser.rl" -#line 2388 "upb/json/parser.c" -======= -#line 2730 "upb/json/parser.rl" - - - -#line 2556 "upb/json/parser.c" ->>>>>>> arrayapi +#line 2516 "upb/json/parser.c" static const char _json_actions[] = { 0, 1, 0, 1, 1, 1, 3, 1, 4, 1, 6, 1, 7, 1, 8, 1, @@ -2787,11 +2764,7 @@ static const int json_en_value_machine = 78; static const int json_en_main = 1; -<<<<<<< HEAD -#line 2545 "upb/json/parser.rl" -======= -#line 2733 "upb/json/parser.rl" ->>>>>>> arrayapi +#line 2693 "upb/json/parser.rl" size_t parse(void *closure, const void *hd, const char *buf, size_t size, const upb_bufhandle *handle) { @@ -2814,11 +2787,7 @@ size_t parse(void *closure, const void *hd, const char *buf, size_t size, capture_resume(parser, buf); -<<<<<<< HEAD -#line 2658 "upb/json/parser.c" -======= -#line 2831 "upb/json/parser.c" ->>>>>>> arrayapi +#line 2791 "upb/json/parser.c" { int _klen; unsigned int _trans; @@ -2893,183 +2862,103 @@ _match: switch ( *_acts++ ) { case 1: -<<<<<<< HEAD -#line 2393 "upb/json/parser.rl" +#line 2521 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 2: -#line 2395 "upb/json/parser.rl" +#line 2523 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 23;goto _again;} } break; case 3: -#line 2399 "upb/json/parser.rl" +#line 2527 "upb/json/parser.rl" { start_text(parser, p); } break; case 4: -#line 2400 "upb/json/parser.rl" +#line 2528 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_text(parser, p)); } break; case 5: -#line 2406 "upb/json/parser.rl" +#line 2534 "upb/json/parser.rl" { start_hex(parser); } break; case 6: -#line 2407 "upb/json/parser.rl" +#line 2535 "upb/json/parser.rl" { hexdigit(parser, p); } break; case 7: -#line 2408 "upb/json/parser.rl" +#line 2536 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_hex(parser)); } break; case 8: -#line 2414 "upb/json/parser.rl" +#line 2542 "upb/json/parser.rl" { CHECK_RETURN_TOP(escape(parser, p)); } break; case 9: -#line 2420 "upb/json/parser.rl" +#line 2548 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 10: -#line 2432 "upb/json/parser.rl" +#line 2560 "upb/json/parser.rl" { start_duration_base(parser, p); } break; case 11: -#line 2433 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_duration_base(parser, p)); } - break; - case 12: -#line 2435 "upb/json/parser.rl" - { p--; {cs = stack[--top]; goto _again;} } - break; - case 13: -#line 2440 "upb/json/parser.rl" - { start_timestamp_base(parser, p); } - break; - case 14: -#line 2441 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_timestamp_base(parser, p)); } - break; - case 15: -#line 2443 "upb/json/parser.rl" - { start_timestamp_fraction(parser, p); } - break; - case 16: -#line 2444 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); } - break; - case 17: -#line 2446 "upb/json/parser.rl" - { start_timestamp_zone(parser, p); } - break; - case 18: -#line 2447 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); } - break; - case 19: -#line 2449 "upb/json/parser.rl" - { p--; {cs = stack[--top]; goto _again;} } - break; - case 20: -#line 2454 "upb/json/parser.rl" -======= #line 2561 "upb/json/parser.rl" - { p--; {cs = stack[--top]; goto _again;} } - break; - case 2: -#line 2563 "upb/json/parser.rl" - { p--; {stack[top++] = cs; cs = 23;goto _again;} } - break; - case 3: -#line 2567 "upb/json/parser.rl" - { start_text(parser, p); } - break; - case 4: -#line 2568 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_text(parser, p)); } - break; - case 5: -#line 2574 "upb/json/parser.rl" - { start_hex(parser); } - break; - case 6: -#line 2575 "upb/json/parser.rl" - { hexdigit(parser, p); } - break; - case 7: -#line 2576 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_hex(parser)); } - break; - case 8: -#line 2582 "upb/json/parser.rl" - { CHECK_RETURN_TOP(escape(parser, p)); } - break; - case 9: -#line 2588 "upb/json/parser.rl" - { p--; {cs = stack[--top]; goto _again;} } - break; - case 10: -#line 2600 "upb/json/parser.rl" - { start_duration_base(parser, p); } - break; - case 11: -#line 2601 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_duration_base(parser, p)); } break; case 12: -#line 2603 "upb/json/parser.rl" +#line 2563 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 13: -#line 2608 "upb/json/parser.rl" +#line 2568 "upb/json/parser.rl" { start_timestamp_base(parser, p); } break; case 14: -#line 2609 "upb/json/parser.rl" +#line 2569 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_base(parser, p)); } break; case 15: -#line 2611 "upb/json/parser.rl" +#line 2571 "upb/json/parser.rl" { start_timestamp_fraction(parser, p); } break; case 16: -#line 2612 "upb/json/parser.rl" +#line 2572 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_fraction(parser, p)); } break; case 17: -#line 2614 "upb/json/parser.rl" +#line 2574 "upb/json/parser.rl" { start_timestamp_zone(parser, p); } break; case 18: -#line 2615 "upb/json/parser.rl" +#line 2575 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_timestamp_zone(parser, p)); } break; case 19: -#line 2617 "upb/json/parser.rl" +#line 2577 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 20: -#line 2622 "upb/json/parser.rl" +#line 2582 "upb/json/parser.rl" { start_fieldmask_path_text(parser, p); } break; case 21: -#line 2623 "upb/json/parser.rl" +#line 2583 "upb/json/parser.rl" { end_fieldmask_path_text(parser, p); } break; case 22: -#line 2628 "upb/json/parser.rl" +#line 2588 "upb/json/parser.rl" { start_fieldmask_path(parser); } break; case 23: -#line 2629 "upb/json/parser.rl" +#line 2589 "upb/json/parser.rl" { end_fieldmask_path(parser); } break; case 24: -#line 2635 "upb/json/parser.rl" +#line 2595 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; case 25: -#line 2640 "upb/json/parser.rl" ->>>>>>> arrayapi +#line 2600 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_TIMESTAMP)) { {stack[top++] = cs; cs = 47;goto _again;} @@ -3082,21 +2971,12 @@ _match: } } break; -<<<<<<< HEAD - case 21: -#line 2465 "upb/json/parser.rl" - { p--; {stack[top++] = cs; cs = 75;goto _again;} } - break; - case 22: -#line 2470 "upb/json/parser.rl" -======= case 26: -#line 2653 "upb/json/parser.rl" +#line 2613 "upb/json/parser.rl" { p--; {stack[top++] = cs; cs = 78;goto _again;} } break; case 27: -#line 2658 "upb/json/parser.rl" ->>>>>>> arrayapi +#line 2618 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { start_any_member(parser, p); @@ -3105,21 +2985,12 @@ _match: } } break; -<<<<<<< HEAD - case 23: -#line 2477 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_membername(parser)); } - break; - case 24: -#line 2480 "upb/json/parser.rl" -======= case 28: -#line 2665 "upb/json/parser.rl" +#line 2625 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_membername(parser)); } break; case 29: -#line 2668 "upb/json/parser.rl" ->>>>>>> arrayapi +#line 2628 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { end_any_member(parser, p); @@ -3128,13 +2999,8 @@ _match: } } break; -<<<<<<< HEAD - case 25: -#line 2491 "upb/json/parser.rl" -======= case 30: -#line 2679 "upb/json/parser.rl" ->>>>>>> arrayapi +#line 2639 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { start_any_object(parser, p); @@ -3143,13 +3009,8 @@ _match: } } break; -<<<<<<< HEAD - case 26: -#line 2500 "upb/json/parser.rl" -======= case 31: -#line 2688 "upb/json/parser.rl" ->>>>>>> arrayapi +#line 2648 "upb/json/parser.rl" { if (is_wellknown_msg(parser, UPB_WELLKNOWN_ANY)) { CHECK_RETURN_TOP(end_any_object(parser, p)); @@ -3158,107 +3019,55 @@ _match: } } break; -<<<<<<< HEAD - case 27: -#line 2512 "upb/json/parser.rl" - { CHECK_RETURN_TOP(start_array(parser)); } - break; - case 28: -#line 2516 "upb/json/parser.rl" - { end_array(parser); } - break; - case 29: -#line 2521 "upb/json/parser.rl" - { CHECK_RETURN_TOP(start_number(parser, p)); } - break; - case 30: -#line 2522 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_number(parser, p)); } - break; - case 31: -#line 2524 "upb/json/parser.rl" - { CHECK_RETURN_TOP(start_stringval(parser)); } - break; - case 32: -#line 2525 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_stringval(parser)); } - break; - case 33: -#line 2527 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_bool(parser, true)); } - break; - case 34: -#line 2529 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_bool(parser, false)); } - break; - case 35: -#line 2531 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_null(parser)); } - break; - case 36: -#line 2533 "upb/json/parser.rl" - { CHECK_RETURN_TOP(start_subobject_full(parser)); } - break; - case 37: -#line 2534 "upb/json/parser.rl" - { end_subobject_full(parser); } - break; - case 38: -#line 2539 "upb/json/parser.rl" - { p--; {cs = stack[--top]; goto _again;} } - break; -#line 2916 "upb/json/parser.c" -======= case 32: -#line 2700 "upb/json/parser.rl" +#line 2660 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_array(parser)); } break; case 33: -#line 2704 "upb/json/parser.rl" +#line 2664 "upb/json/parser.rl" { end_array(parser); } break; case 34: -#line 2709 "upb/json/parser.rl" +#line 2669 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_number(parser, p)); } break; case 35: -#line 2710 "upb/json/parser.rl" +#line 2670 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 36: -#line 2712 "upb/json/parser.rl" +#line 2672 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_stringval(parser)); } break; case 37: -#line 2713 "upb/json/parser.rl" +#line 2673 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_stringval(parser)); } break; case 38: -#line 2715 "upb/json/parser.rl" +#line 2675 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, true)); } break; case 39: -#line 2717 "upb/json/parser.rl" +#line 2677 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, false)); } break; case 40: -#line 2719 "upb/json/parser.rl" +#line 2679 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_null(parser)); } break; case 41: -#line 2721 "upb/json/parser.rl" +#line 2681 "upb/json/parser.rl" { CHECK_RETURN_TOP(start_subobject_full(parser)); } break; case 42: -#line 2722 "upb/json/parser.rl" +#line 2682 "upb/json/parser.rl" { end_subobject_full(parser); } break; case 43: -#line 2727 "upb/json/parser.rl" +#line 2687 "upb/json/parser.rl" { p--; {cs = stack[--top]; goto _again;} } break; -#line 3111 "upb/json/parser.c" ->>>>>>> arrayapi +#line 3071 "upb/json/parser.c" } } @@ -3275,60 +3084,32 @@ _again: while ( __nacts-- > 0 ) { switch ( *__acts++ ) { case 0: -<<<<<<< HEAD -#line 2391 "upb/json/parser.rl" -======= -#line 2559 "upb/json/parser.rl" ->>>>>>> arrayapi +#line 2519 "upb/json/parser.rl" { p--; {cs = stack[--top]; if ( p == pe ) goto _test_eof; goto _again;} } break; -<<<<<<< HEAD - case 30: -#line 2522 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_number(parser, p)); } - break; - case 33: -#line 2527 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_bool(parser, true)); } - break; - case 34: -#line 2529 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_bool(parser, false)); } - break; - case 35: -#line 2531 "upb/json/parser.rl" - { CHECK_RETURN_TOP(end_null(parser)); } - break; - case 37: -#line 2534 "upb/json/parser.rl" - { end_subobject_full(parser); } - break; -#line 2958 "upb/json/parser.c" -======= case 35: -#line 2710 "upb/json/parser.rl" +#line 2670 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_number(parser, p)); } break; case 38: -#line 2715 "upb/json/parser.rl" +#line 2675 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, true)); } break; case 39: -#line 2717 "upb/json/parser.rl" +#line 2677 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_bool(parser, false)); } break; case 40: -#line 2719 "upb/json/parser.rl" +#line 2679 "upb/json/parser.rl" { CHECK_RETURN_TOP(end_null(parser)); } break; case 42: -#line 2722 "upb/json/parser.rl" +#line 2682 "upb/json/parser.rl" { end_subobject_full(parser); } break; -#line 3153 "upb/json/parser.c" ->>>>>>> arrayapi +#line 3113 "upb/json/parser.c" } } } @@ -3336,11 +3117,7 @@ goto _again;} } _out: {} } -<<<<<<< HEAD -#line 2567 "upb/json/parser.rl" -======= -#line 2755 "upb/json/parser.rl" ->>>>>>> arrayapi +#line 2715 "upb/json/parser.rl" if (p != pe) { upb_status_seterrf(parser->status, "Parse error at '%.*s'\n", pe - p, p); @@ -3388,21 +3165,13 @@ static void json_parser_reset(upb_json_parser *p) { /* Emit Ragel initialization of the parser. */ -<<<<<<< HEAD -#line 3013 "upb/json/parser.c" -======= -#line 3210 "upb/json/parser.c" ->>>>>>> arrayapi +#line 3169 "upb/json/parser.c" { cs = json_start; top = 0; } -<<<<<<< HEAD -#line 2613 "upb/json/parser.rl" -======= -#line 2803 "upb/json/parser.rl" ->>>>>>> arrayapi +#line 2762 "upb/json/parser.rl" p->current_state = cs; p->parser_top = top; accumulate_clear(p); diff --git a/upb/json/parser.rl b/upb/json/parser.rl index f722d28..1ae896a 100644 --- a/upb/json/parser.rl +++ b/upb/json/parser.rl @@ -19,6 +19,7 @@ ** - handling of keys/escape-sequences/etc that span input buffers. */ +#include #include #include #include @@ -61,7 +62,6 @@ static bool is_string_wrapper_object(upb_json_parser *p); static bool does_string_wrapper_start(upb_json_parser *p); static bool does_string_wrapper_end(upb_json_parser *p); -static bool is_fieldmask_object(upb_json_parser *p); static bool does_fieldmask_start(upb_json_parser *p); static bool does_fieldmask_end(upb_json_parser *p); static void start_fieldmask_object(upb_json_parser *p); @@ -1668,9 +1668,7 @@ static void start_fieldmask_path_text(upb_json_parser *p, const char *ptr) { } static bool end_fieldmask_path_text(upb_json_parser *p, const char *ptr) { - if (!capture_end(p, ptr)) { - return false; - } + return capture_end(p, ptr); } static bool start_fieldmask_path(upb_json_parser *p) { @@ -1683,7 +1681,7 @@ static bool start_fieldmask_path(upb_json_parser *p) { * handler frames, and string events occur in a sub-frame. */ inner = p->top + 1; sel = getsel_for_handlertype(p, UPB_HANDLER_STARTSTR); - upb_sink_startstr(&p->top->sink, sel, 0, &inner->sink); + upb_sink_startstr(p->top->sink, sel, 0, &inner->sink); inner->m = p->top->m; inner->f = p->top->f; inner->name_table = NULL; @@ -1705,10 +1703,10 @@ static bool lower_camel_push( for (;ptr < limit; ptr++) { if (*ptr >= 'A' && *ptr <= 'Z' && !first) { char lower = tolower(*ptr); - upb_sink_putstring(&p->top->sink, sel, "_", 1, NULL); - upb_sink_putstring(&p->top->sink, sel, &lower, 1, NULL); + upb_sink_putstring(p->top->sink, sel, "_", 1, NULL); + upb_sink_putstring(p->top->sink, sel, &lower, 1, NULL); } else { - upb_sink_putstring(&p->top->sink, sel, ptr, 1, NULL); + upb_sink_putstring(p->top->sink, sel, ptr, 1, NULL); } first = false; } @@ -1725,7 +1723,7 @@ static bool end_fieldmask_path(upb_json_parser *p) { } sel = getsel_for_handlertype(p, UPB_HANDLER_ENDSTR); - upb_sink_endstr(&p->top->sink, sel); + upb_sink_endstr(p->top->sink, sel); p->top--; multipart_end(p); @@ -2487,10 +2485,6 @@ static bool does_fieldmask_end(upb_json_parser *p) { return p->top->m != NULL && is_fieldmask(p->top->m); } -static bool is_fieldmask_object(upb_json_parser *p) { - return p->top->m != NULL && is_fieldmask(p->top->m); -} - #define CHECK_RETURN_TOP(x) if (!(x)) goto error diff --git a/upb/json/printer.c b/upb/json/printer.c index 5b16861..2d566cb 100644 --- a/upb/json/printer.c +++ b/upb/json/printer.c @@ -5,8 +5,9 @@ #include "upb/json/printer.h" -#include +#include #include +#include #include struct upb_json_printer { @@ -1029,7 +1030,7 @@ void printer_sethandlers_fieldmask(const void *closure, upb_handlers *h) { const upb_msgdef *md = upb_handlers_msgdef(h); const upb_fielddef* f = upb_msgdef_itof(md, 1); - upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlerattr empty_attr = UPB_HANDLERATTR_INIT; upb_handlers_setstartseq(h, f, startseq_fieldmask, &empty_attr); upb_handlers_setendseq(h, f, endseq_fieldmask, &empty_attr); diff --git a/upb/upb.h b/upb/upb.h index 3848229..92db893 100644 --- a/upb/upb.h +++ b/upb/upb.h @@ -377,14 +377,6 @@ typedef enum { UPB_LABEL_REPEATED = 3 } upb_label_t; -/* How integers should be encoded in serializations that offer multiple - * integer encoding methods. */ -typedef enum { - UPB_INTFMT_VARIABLE = 1, - UPB_INTFMT_FIXED = 2, - UPB_INTFMT_ZIGZAG = 3 /* Only for signed types (INT32/INT64). */ -} upb_intfmt_t; - /* Descriptor types, as defined in descriptor.proto. */ typedef enum { UPB_DESCRIPTOR_TYPE_DOUBLE = 1, @@ -407,37 +399,6 @@ typedef enum { UPB_DESCRIPTOR_TYPE_SINT64 = 18 } upb_descriptortype_t; -typedef enum { - UPB_SYNTAX_PROTO2 = 2, - UPB_SYNTAX_PROTO3 = 3 -} upb_syntax_t; - -/* All the different kind of well known type messages. For simplicity of check, - * number wrappers and string wrappers are grouped together. Make sure the - * order and merber of these groups are not changed. - */ -typedef enum { - UPB_WELLKNOWN_UNSPECIFIED, - UPB_WELLKNOWN_ANY, - UPB_WELLKNOWN_FIELDMASK, - UPB_WELLKNOWN_DURATION, - UPB_WELLKNOWN_TIMESTAMP, - /* number wrappers */ - UPB_WELLKNOWN_DOUBLEVALUE, - UPB_WELLKNOWN_FLOATVALUE, - UPB_WELLKNOWN_INT64VALUE, - UPB_WELLKNOWN_UINT64VALUE, - UPB_WELLKNOWN_INT32VALUE, - UPB_WELLKNOWN_UINT32VALUE, - /* string wrappers */ - UPB_WELLKNOWN_STRINGVALUE, - UPB_WELLKNOWN_BYTESVALUE, - UPB_WELLKNOWN_BOOLVALUE, - UPB_WELLKNOWN_VALUE, - UPB_WELLKNOWN_LISTVALUE, - UPB_WELLKNOWN_STRUCT -} upb_wellknowntype_t; - extern const uint8_t upb_desctype_to_fieldtype[]; #endif /* UPB_H_ */ -- cgit v1.2.3