From e9d79d2441732264e2b990a5b2dc76d13724db07 Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Wed, 16 Mar 2016 18:07:32 -0700 Subject: Added upb::FileDef, which represents the file defs are declared in. It is entirely optional: MessageDef/EnumDef can still exist on their own. But this can represent a def's file when it is desirable to do so (eg. for code generators). This approach will require that we change the way we handle extensions. But I think it will be a good change overall. Specifically, we previously handled extensions by duplicating the extended message and then adding the extension as a regular field to the duplicated message. This required also duplicating any messages that could reach the extended message. In the new world we will need a way of declaring and looking up extensions separately from the message being extended. This change also involves some notable changes to the generated code: - files are now called foo.upbdefs.h instead of foo.upb.h. This reflects the fact that we might possibly generate several different output files for a .proto file, and this one is just for defs. - we no longer generate selectors in the .h file. - the upbdefs.c no longer vends a SymbolTable. Now it vends the individual messages (and possibly a FileDef later). I think this will compose better once we can generate files where one generated files imports another. We also make the descriptor reader vend a list of FileDefs now. This is the best conceptual match for parsing a FileDescriptorSet. --- tools/dump_cinit.lua | 336 +++++++++++++++++++++++---------------------------- 1 file changed, 150 insertions(+), 186 deletions(-) (limited to 'tools/dump_cinit.lua') diff --git a/tools/dump_cinit.lua b/tools/dump_cinit.lua index 4ec3cbf..ffb48c8 100644 --- a/tools/dump_cinit.lua +++ b/tools/dump_cinit.lua @@ -88,7 +88,9 @@ function sorted_defs(defs) local sorted = {} for def in defs do - sorted[#sorted + 1] = def + if def.type == deftype then + sorted[#sorted + 1] = def + end end table.sort(sorted, @@ -318,7 +320,7 @@ end -- Strips away last path element, ie: -- foo.Bar.Baz -> foo.Bar -local function getpackage(name) +local function remove_name(name) local package_end = 0 for i=1,string.len(name) do if string.byte(name, i) == string.byte(".", 1) then @@ -328,19 +330,6 @@ local function getpackage(name) return string.sub(name, 1, package_end) end --- Returns only the last path element, ie: --- foo.Bar.Baz -> Baz -local function relname(name) - local package = getpackage(name) - return string.sub(name, string.len(package) + 2) -end - -local function strip_prefix(prefix, str) - assert(string.sub(str, 1, string.len(prefix)) == prefix) - return string.sub(str, string.len(prefix) + 1) -end - - local function start_namespace(package, append) local package_components = split(package) for _, component in ipairs(package_components) do @@ -361,9 +350,9 @@ end --]] -local function dump_defs_c(symtab, basename, namespace, append) +local function dump_defs_c(filedef, append) local defs = {} - for def in symtab:defs(upb.DEF_ANY) do + for def in filedef:defs(upb.DEF_ANY) do defs[#defs + 1] = def if (def:def_type() == upb.DEF_MSG) then for field in def:fields() do @@ -412,17 +401,11 @@ local function dump_defs_c(symtab, basename, namespace, append) end end - -- Symbol table entries. - reftable_count = reftable_count + 2 - for _, e in ipairs(upbtable.symtab_symtab(symtab).entries) do - linktab:add("strentries", e.ptr, e) - end - -- Emit forward declarations. emit_file_warning(append) + append('#include \n\n') append('#include "upb/def.h"\n') - append('#include "upb/structdefs.int.h"\n') - append('#include "upb/symtab.h"\n\n') + append('#include "upb/structdefs.int.h"\n\n') append("static const upb_msgdef %s;\n", linktab:cdecl(upb.DEF_MSG)) append("static const upb_fielddef %s;\n", linktab:cdecl(upb.DEF_FIELD)) if not linktab:empty(upb.DEF_ENUM) then @@ -531,19 +514,6 @@ local function dump_defs_c(symtab, basename, namespace, append) end append("};\n\n"); - append("static const upb_symtab symtab = " .. - "UPB_SYMTAB_INIT(%s, &reftables[%d], &reftables[%d]);\n\n", - dumper:strtable(upbtable.symtab_symtab(symtab)), - reftable, - reftable + 1); - - -- TODO: don't hardcode this. - append("const upb_symtab *%s_%s(const void *owner) " .. - "{\n", namespace, to_cident(basename)) - append(" upb_symtab_ref(&symtab, owner);\n") - append(" return &symtab;\n") - append("}\n\n") - append("#ifdef UPB_DEBUG_REFS\n") append("static upb_inttable reftables[%d] = {\n", reftable_count) for i = 1,reftable_count do @@ -552,18 +522,62 @@ local function dump_defs_c(symtab, basename, namespace, append) append("};\n") append("#endif\n\n") + append("static const upb_msgdef *refm(const upb_msgdef *m, const void *owner) {\n") + append(" upb_msgdef_ref(m, owner);\n") + append(" return m;\n") + append("}\n\n") + append("static const upb_enumdef *refe(const upb_enumdef *e, const void *owner) {\n") + append(" upb_enumdef_ref(e, owner);\n") + append(" return e;\n") + append("}\n\n") + + append("/* Public API. */\n") + + for m in linktab:objs(upb.DEF_MSG) do + append("const upb_msgdef *upbdefs_%s_get(const void *owner)" .. + " { return refm(%s, owner); }\n", + to_cident(m:full_name()), linktab:addr(m)) + end + + append("\n") + + for e in linktab:objs(upb.DEF_ENUM) do + append("const upb_enumdef *upbdefs_%s_get(const void *owner)" .. + " { return refe(%s, owner); }\n", + to_cident(e:full_name()), linktab:addr(e)) + end + return linktab end -local function dump_defs_for_type(format, defs, namespace, append) +local function dump_defs_for_type(format, defs, append) local sorted = sorted_defs(defs) for _, def in ipairs(sorted) do - append(format, namespace, to_cident(def:full_name()), def:full_name()) + append(format, to_cident(def:full_name()), def:full_name()) end append("\n") end +local function make_children_map(file) + -- Maps full_name -> children. + local map = {} + for def in file:defs(upb.DEF_ANY) do + local container = remove_name(def:full_name()) + if not map[container] then + map[container] = {} + end + table.insert(map[container], def) + end + + -- Sort all the lists for a consistent ordering. + for name, children in pairs(map) do + table.sort(children, function(a, b) return a:name() < b:name() end) + end + + return map +end + local function dump_enum_vals(enumdef, append) local enum_vals = {} @@ -597,10 +611,10 @@ local function dump_enum_vals(enumdef, append) -- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_TYPE_DOUBLE = 1 -- -- (notice the duplicated "TYPE"). - local cident = to_cident(getpackage(enumdef:full_name())) + local cident = to_cident(remove_name(enumdef:full_name())) for i, pair in ipairs(enum_vals) do k, v = pair[1], pair[2] - append(' %s = %d', to_preproc(cident, k), v) + append(' %s = %d', cident .. "_" .. k, v) if i == #enum_vals then append('\n') else @@ -609,53 +623,63 @@ local function dump_enum_vals(enumdef, append) end end -local function dump_selectors(msgdef, append, base) - local selectors = {} - local types = handler_types(base) - - for f in msgdef:fields() do - for _, handler_type in ipairs(types) do - local sel = f:getsel(base[handler_type]) - if sel then - selectors[#selectors + 1] = { - f:name() .. "_" .. strip_prefix("HANDLER_", handler_type), - sel - } - end - end - end +local print_classes - table.sort(selectors, function(a, b) return a[2] < b[2] end) +local function print_message(def, map, indent, append) + append("\n") + append("%sclass %s : public upb::reffed_ptr {\n", + indent, def:name()) + append("%s public:\n", indent) + append("%s %s(const upb::MessageDef* m, const void *ref_donor = NULL)\n", + indent, def:name()) + append("%s : reffed_ptr(m, ref_donor) {\n", indent) + append("%s assert(upbdefs_%s_is(m));\n", indent, to_cident(def:full_name())) + append("%s }\n", indent) + append("\n") + append("%s static %s get() {\n", indent, def:name()) + append("%s const upb::MessageDef* m = upbdefs_%s_get(&m);\n", indent, to_cident(def:full_name())) + append("%s return %s(m, &m);\n", indent, def:name()) + append("%s }\n", indent) + -- TODO(haberman): add fields + print_classes(def:full_name(), map, indent .. " ", append) + append("%s};\n", indent) +end - -- This is kind of gross, but unless we add something to selectors to - -- distinguish them from enum values, we get conflicts like this: - -- - -- // This can be either the enum value: - -- package google.protobuf; - -- message FieldDescriptorProto { - -- enum Type { - -- TYPE_INT32 = X; - -- } - -- optional Type type = 1; - -- } - -- - -- // Now this can be either the enum value or the selector for the - -- // int32 handler for the "type" field. - -- GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 - -- - -- // So instead we make the latter the very beautiful: - -- SEL_GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 - append("/* %s */\n", msgdef:full_name()) - local cident = to_cident(msgdef:full_name()) - for _, pair in ipairs(selectors) do - k, v = pair[1], pair[2] - append('#define SEL_%s %d\n', to_preproc(cident, k), v) - end +local function print_enum(def, indent, append) append("\n") + append("%sclass %s : public upb::reffed_ptr {\n", + indent, def:name()) + append("%s public:\n", indent) + append("%s %s(const upb::EnumDef* e, const void *ref_donor = NULL)\n", + indent, def:name()) + append("%s : reffed_ptr(e, ref_donor) {\n", indent) + append("%s assert(upbdefs_%s_is(e));\n", indent, to_cident(def:full_name())) + append("%s }\n", indent) + append("%s static %s get() {\n", indent, def:name()) + append("%s const upb::EnumDef* e = upbdefs_%s_get(&e);\n", indent, to_cident(def:full_name())) + append("%s return %s(e, &e);\n", indent, def:name()) + append("%s }\n", indent) + append("%s};\n", indent) +end + +function print_classes(name, map, indent, append) + if not map[name] then + return + end + + for _, def in ipairs(map[name]) do + if def:def_type() == upb.DEF_MSG then + print_message(def, map, indent, append) + elseif def:def_type() == upb.DEF_ENUM then + print_enum(def, indent, append) + else + error("Unknown def type for " .. def:full_name()) + end + end end -local function dump_defs_h(symtab, basename, namespace, append, linktab) - local basename_preproc = to_preproc(basename) +local function dump_defs_h(file, append, linktab) + local basename_preproc = to_preproc(file:name()) append("/* This file contains accessors for a set of compiled-in defs.\n") append(" * Note that unlike Google's protobuf, it does *not* define\n") append(" * generated classes or any other kind of data structure for\n") @@ -665,61 +689,42 @@ local function dump_defs_h(symtab, basename, namespace, append, linktab) emit_file_warning(append) append('#ifndef %s_UPB_H_\n', basename_preproc) append('#define %s_UPB_H_\n\n', basename_preproc) - append('#include "upb/def.h"\n') - append('#include "upb/symtab.h"\n\n') - append('#ifdef __cplusplus\n') - append('UPB_BEGIN_EXTERN_C\n') - append('#endif\n\n') - - local packages = {} - for def in symtab:defs(upb.DEF_ANY) do - if def:def_type() == upb.DEF_MSG then - packages[def:full_name()] = true - else - packages[getpackage(def:full_name())] = true - end - end + append('#include "upb/def.h"\n\n') + append('UPB_BEGIN_EXTERN_C\n\n') -- Dump C enums for proto enums. append("/* Enums */\n\n") - for _, def in ipairs(sorted_defs(symtab:defs(upb.DEF_ENUM))) do + for _, def in ipairs(sorted_defs(file:defs(upb.DEF_ENUM))) do local cident = to_cident(def:full_name()) append('typedef enum {\n') dump_enum_vals(def, append) append('} %s;\n\n', cident) end - -- selectors - append("/* Selectors */\n\n") - for _, def in ipairs(sorted_defs(symtab:defs(upb.DEF_MSG))) do - dump_selectors(def, append, upb) - end - - append("const upb_symtab *%s_%s(const void *owner);" .. - "\n\n", namespace, to_cident(basename)) + append("/* MessageDefs: call these functions to get a ref to a msgdef. */\n") + dump_defs_for_type( + "const upb_msgdef *upbdefs_%s_get(const void *owner);\n", + file:defs(upb.DEF_MSG), append) - append("/* MessageDefs */\n") + append("/* EnumDefs: call these functions to get a ref to an enumdef. */\n") dump_defs_for_type( - "UPB_INLINE const upb_msgdef *%s_%s(const upb_symtab *s) {\n" .. - " const upb_msgdef *m = upb_symtab_lookupmsg(s, \"%s\");\n" .. - " assert(m);\n" .. - " return m;\n" .. - "}\n", - symtab:defs(upb.DEF_MSG), - namespace, append) + "const upb_enumdef *upbdefs_%s_get(const void *owner);\n", + file:defs(upb.DEF_ENUM), append) - append("\n") + append("/* Functions to test whether this message is of a certain type. */\n") + dump_defs_for_type( + "UPB_INLINE bool upbdefs_%s_is(const upb_msgdef *m) {\n" .. + " return strcmp(upb_msgdef_fullname(m), \"%s\") == 0;\n}\n", + file:defs(upb.DEF_MSG), append) - append("/* EnumDefs */\n") + append("/* Functions to test whether this enum is of a certain type. */\n") dump_defs_for_type( - "UPB_INLINE const upb_enumdef *%s_%s(const upb_symtab *s) {\n" .. - " const upb_enumdef *e = upb_symtab_lookupenum(s, \"%s\");\n" .. - " assert(e);\n" .. - " return e;\n" .. - "}\n", - symtab:defs(upb.DEF_ENUM), - namespace, append) + "UPB_INLINE bool upbdefs_%s_is(const upb_enumdef *e) {\n" .. + " return strcmp(upb_enumdef_fullname(e), \"%s\") == 0;\n}\n", + file:defs(upb.DEF_ENUM), append) + + append("\n") -- fields local fields = {} @@ -731,79 +736,38 @@ local function dump_defs_h(symtab, basename, namespace, append, linktab) table.sort(fields, function(a, b) return a[1] < b[1] end) + append("/* Functions to get a fielddef from a msgdef reference. */\n") for _, field in ipairs(fields) do local f = field[2] - append("UPB_INLINE const upb_fielddef *%s_%s(const upb_symtab *s) {" .. - " return upb_msgdef_itof(%s_%s(s), %d); }\n", - namespace, field[1], namespace, - to_cident(f:containing_type():full_name()), f:number()) + local msg_cident = to_cident(f:containing_type():full_name()) + local field_cident = to_cident(f:name()) + append("UPB_INLINE const upb_fielddef *upbdefs_%s_f_%s(const upb_msgdef *m) {" .. + " assert(upbdefs_%s_is(m));" .. + " return upb_msgdef_itof(m, %d); }\n", + msg_cident, field_cident, msg_cident, f:number()) end - append("\n") - append('UPB_END_EXTERN_C\n\n') - append("#ifdef __cplusplus\n\n") + append('\nUPB_END_EXTERN_C\n\n') - append("namespace %s {\n", namespace) + -- C++ wrappers. + local children_map = make_children_map(file) - start_namespace(basename, append) - append("inline upb::reffed_ptr SymbolTable() {\n") - append(" const upb::SymbolTable* s = %s_google_protobuf_descriptor(&s);\n", - namespace) - append(" return upb::reffed_ptr(s, &s);\n") - append("}\n") - end_namespace(basename, append) + append("#ifdef __cplusplus\n\n") + append("namespace upbdefs {\n") + start_namespace(file:package(), append) + print_classes(file:package(), children_map, "", append) append("\n") + end_namespace(file:package(), append) + append("} /* namespace upbdefs */\n\n") + append("#endif /* __cplusplus */\n") - - append([[#define RETURN_REFFED(type, func) \ - const type* obj = func(%s::google::protobuf::descriptor::SymbolTable().get()); \ - return upb::reffed_ptr(obj); - -]], namespace) - - for _, package in ipairs(sortedkeys(packages)) do - start_namespace(package, append) - - local def = symtab:lookup(package) - if def then - assert(def:def_type() == upb.DEF_MSG) - append("inline upb::reffed_ptr MessageDef() " .. - "{ RETURN_REFFED(upb::MessageDef, %s_%s) }\n", - namespace, to_cident(def:full_name())) - end - - for f in linktab:objs(upb.DEF_FIELD) do - if f:containing_type():full_name() == package then - append("inline upb::reffed_ptr %s() " .. - "{ RETURN_REFFED(upb::FieldDef, %s_%s_%s) }\n", - f:name(), namespace, to_cident(f:containing_type():full_name()), - f:name()) - end - end - - for e in linktab:objs(upb.DEF_ENUM) do - if getpackage(e:full_name()) == package then - append("inline upb::reffed_ptr %s() " .. - "{ RETURN_REFFED(upb::EnumDef, %s_%s) }\n", - relname(e:full_name()), namespace, to_cident(e:full_name())) - end - end - - end_namespace(package, append) - append("\n") - end - - append("} /* namespace %s */\n\n\n", namespace) - - append("#undef RETURN_REFFED\n") - append("#endif /* __cplusplus */\n\n") - + append("\n") append('#endif /* %s_UPB_H_ */\n', basename_preproc) end -function export.dump_defs(symtab, basename, append_h, append_c) - local linktab = dump_defs_c(symtab, basename, "upbdefs", append_c) - dump_defs_h(symtab, basename, "upbdefs", append_h, linktab) +function export.dump_defs(filedef, append_h, append_c) + local linktab = dump_defs_c(filedef, append_c) + dump_defs_h(filedef, append_h, linktab) end return export -- cgit v1.2.3 From f8c26358f0b87a9c90be3f038cdea5bdcae185a0 Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Wed, 6 Apr 2016 14:28:45 -0700 Subject: Changes for PR comments. --- tests/pb/test_encoder.cc | 21 +--------- tests/test_def.c | 21 +--------- tests/test_util.h | 99 ++++++++++++++++++++++++++++++------------------ tools/dump_cinit.lua | 2 +- upb/def.c | 41 ++++++++++---------- upb/def.h | 11 +++++- upb/symtab.c | 5 +++ 7 files changed, 100 insertions(+), 100 deletions(-) (limited to 'tools/dump_cinit.lua') diff --git a/tests/pb/test_encoder.cc b/tests/pb/test_encoder.cc index 6dd10ba..6219e08 100644 --- a/tests/pb/test_encoder.cc +++ b/tests/pb/test_encoder.cc @@ -1,4 +1,5 @@ +#include "tests/test_util.h" #include "tests/upb_test.h" #include "upb/bindings/stdc++/string.h" #include "upb/descriptor/descriptor.upbdefs.h" @@ -6,26 +7,6 @@ #include "upb/pb/encoder.h" #include "upb/pb/glue.h" -static char *upb_readfile(const char *filename, size_t *len) { - long size; - char *buf; - FILE *f = fopen(filename, "rb"); - if(!f) return NULL; - if(fseek(f, 0, SEEK_END) != 0) goto error; - size = ftell(f); - if(size < 0) goto error; - if(fseek(f, 0, SEEK_SET) != 0) goto error; - buf = (char*)malloc(size + 1); - if(size && fread(buf, size, 1, f) != 1) goto error; - fclose(f); - if (len) *len = size; - return buf; - -error: - fclose(f); - return NULL; -} - std::string read_string(const char *filename) { size_t len; char *str = upb_readfile(filename, &len); diff --git a/tests/test_def.c b/tests/test_def.c index 6f3fb8f..cc766e0 100644 --- a/tests/test_def.c +++ b/tests/test_def.c @@ -3,6 +3,7 @@ ** (like attempts to link defs that don't have required properties set). */ +#include "tests/test_util.h" #include "upb/def.h" #include "upb/pb/glue.h" #include "upb_test.h" @@ -38,26 +39,6 @@ static void test_noreftracking() { upb_msgdef_unref(md, &md); } -static char *upb_readfile(const char *filename, size_t *len) { - long size; - char *buf; - FILE *f = fopen(filename, "rb"); - if(!f) return NULL; - if(fseek(f, 0, SEEK_END) != 0) goto error; - size = ftell(f); - if(size < 0) goto error; - if(fseek(f, 0, SEEK_SET) != 0) goto error; - buf = malloc(size + 1); - if(size && fread(buf, size, 1, f) != 1) goto error; - fclose(f); - if (len) *len = size; - return buf; - -error: - fclose(f); - return NULL; -} - static upb_symtab *load_test_proto(void *owner) { upb_symtab *s = upb_symtab_new(owner); upb_status status = UPB_STATUS_INIT; diff --git a/tests/test_util.h b/tests/test_util.h index caf9ee8..c6438fc 100644 --- a/tests/test_util.h +++ b/tests/test_util.h @@ -11,23 +11,26 @@ #include "upb/env.h" #include "upb/sink.h" +#ifdef __cplusplus + upb::BufferHandle global_handle; -// A convenience class for parser tests. Provides some useful features: -// -// - can support multiple calls to parse, to test the parser's handling -// of buffer seams. -// -// - can output verbose output about each parse call when requested, for -// ease of debugging. -// -// - can pass NULL for skipped regions of the input if requested. -// -// - allocates and passes a separate buffer for each parsed region, to -// ensure that the parser is not erroneously overreading its buffer. +/* A convenience class for parser tests. Provides some useful features: + * + * - can support multiple calls to parse, to test the parser's handling + * of buffer seams. + * + * - can output verbose output about each parse call when requested, for + * ease of debugging. + * + * - can pass NULL for skipped regions of the input if requested. + * + * - allocates and passes a separate buffer for each parsed region, to + * ensure that the parser is not erroneously overreading its buffer. + */ class VerboseParserEnvironment { public: - // Pass verbose=true to print detailed diagnostics to stderr. + /* Pass verbose=true to print detailed diagnostics to stderr. */ VerboseParserEnvironment(bool verbose) : verbose_(verbose) { env_.SetErrorFunction(&VerboseParserEnvironment::OnError, this); } @@ -60,15 +63,16 @@ class VerboseParserEnvironment { skipped_with_null_ = false; } - // The user should call a series of: - // - // Reset(buf, len, may_skip); - // Start() - // ParseBuffer(X); - // ParseBuffer(Y); - // // Repeat ParseBuffer as desired, but last call should pass -1. - // ParseBuffer(-1); - // End(); + /* The user should call a series of: + * + * Reset(buf, len, may_skip); + * Start() + * ParseBuffer(X); + * ParseBuffer(Y); + * // Repeat ParseBuffer as desired, but last call should pass -1. + * ParseBuffer(-1); + * End(); + */ bool Start() { @@ -111,9 +115,9 @@ class VerboseParserEnvironment { ASSERT((size_t)bytes <= (len_ - ofs_)); - // Copy buffer into a separate, temporary buffer. - // This is necessary to verify that the parser is not erroneously - // reading outside the specified bounds. + /* Copy buffer into a separate, temporary buffer. + * This is necessary to verify that the parser is not erroneously + * reading outside the specified bounds. */ char *buf2 = NULL; if ((int)(ofs_ + bytes) <= skip_until_) { @@ -125,7 +129,7 @@ class VerboseParserEnvironment { } if (buf2 == NULL && bytes == 0) { - // Decoders dont' support buf=NULL, bytes=0. + /* Decoders dont' support buf=NULL, bytes=0. */ return true; } @@ -189,18 +193,41 @@ class VerboseParserEnvironment { bool end_ok_; bool end_ok_set_; - // When our parse call returns a value greater than the number of bytes - // we passed in, the decoder is indicating to us that the next N bytes - // in the stream are not needed and can be skipped. The user is allowed - // to pass a NULL buffer for those N bytes. - // - // skip_until_ is initially set to 0 if we should do this NULL-buffer - // skipping or -1 if we should not. If we are open to doing NULL-buffer - // skipping and we get an opportunity to do it, we set skip_until to the - // stream offset where we can skip until. The user can then test whether - // this happened by testing SkippedWithNull(). + /* When our parse call returns a value greater than the number of bytes + * we passed in, the decoder is indicating to us that the next N bytes + * in the stream are not needed and can be skipped. The user is allowed + * to pass a NULL buffer for those N bytes. + * + * skip_until_ is initially set to 0 if we should do this NULL-buffer + * skipping or -1 if we should not. If we are open to doing NULL-buffer + * skipping and we get an opportunity to do it, we set skip_until to the + * stream offset where we can skip until. The user can then test whether + * this happened by testing SkippedWithNull(). */ int skip_until_; bool skipped_with_null_; }; +#endif /* __cplusplus */ + +UPB_INLINE char *upb_readfile(const char *filename, size_t *len) { + long size; + char *buf; + FILE *f = fopen(filename, "rb"); + if(!f) return NULL; + if(fseek(f, 0, SEEK_END) != 0) goto error; + size = ftell(f); + if(size < 0) goto error; + if(fseek(f, 0, SEEK_SET) != 0) goto error; + buf = (char*)malloc(size + 1); + if(size && fread(buf, size, 1, f) != 1) goto error; + fclose(f); + if (len) *len = size; + buf[size] = '\0'; + return buf; + +error: + fclose(f); + return NULL; +} + #endif diff --git a/tools/dump_cinit.lua b/tools/dump_cinit.lua index ffb48c8..17be8d9 100644 --- a/tools/dump_cinit.lua +++ b/tools/dump_cinit.lua @@ -560,7 +560,7 @@ local function dump_defs_for_type(format, defs, append) end local function make_children_map(file) - -- Maps full_name -> children. + -- Maps file:package() or msg:full_name() -> children. local map = {} for def in file:defs(upb.DEF_ANY) do local container = remove_name(def:full_name()) diff --git a/upb/def.c b/upb/def.c index 4ed61be..2fdbf01 100644 --- a/upb/def.c +++ b/upb/def.c @@ -74,21 +74,17 @@ upb_deftype_t upb_def_type(const upb_def *d) { return d->type; } const char *upb_def_fullname(const upb_def *d) { return d->fullname; } const char *upb_def_name(const upb_def *d) { - /* Return one past the last '.'. */ - const char *ret = d->fullname; - const char *p = ret; + const char *p; - if (ret == NULL) { + if (d->fullname == NULL) { return NULL; + } else if ((p = strrchr(d->fullname, '.')) == NULL) { + /* No '.' in the name, return the full string. */ + return d->fullname; + } else { + /* Return one past the last '.'. */ + return p + 1; } - - for (p = ret; *p; ++p) { - if (*p == '.') { - ret = p + 1; - } - } - - return ret; } bool upb_def_setfullname(upb_def *def, const char *fullname, upb_status *s) { @@ -1527,12 +1523,6 @@ bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor, return true; } -void upb_msgdef_setprimitiveshavepresence(upb_msgdef *m, bool have_presence) { - assert(!upb_msgdef_isfrozen(m)); - assert(!m->base.file); - m->syntax = have_presence ? UPB_SYNTAX_PROTO2 : UPB_SYNTAX_PROTO3; -} - const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) { upb_value val; return upb_inttable_lookup32(&m->itof, i, &val) ? @@ -1898,17 +1888,26 @@ const upb_filedef *upb_filedef_dep(const upb_filedef *f, size_t i) { } bool upb_filedef_setname(upb_filedef *f, const char *name, upb_status *s) { - UPB_UNUSED(s); + name = upb_strdup(name); + if (!name) { + upb_status_seterrmsg(s, "Out of memory"); + return false; + } free((void*)f->name); - f->name = upb_strdup(name); + f->name = name; return true; } bool upb_filedef_setpackage(upb_filedef *f, const char *package, upb_status *s) { if (!upb_isident(package, strlen(package), true, s)) return false; + package = upb_strdup(package); + if (!package) { + upb_status_seterrmsg(s, "Out of memory"); + return false; + } free((void*)f->package); - f->package = upb_strdup(package); + f->package = package; return true; } diff --git a/upb/def.h b/upb/def.h index 487729a..0fc6f41 100644 --- a/upb/def.h +++ b/upb/def.h @@ -921,7 +921,6 @@ bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor, upb_status *s); bool upb_msgdef_addoneof(upb_msgdef *m, upb_oneofdef *o, const void *ref_donor, upb_status *s); -void upb_msgdef_setprimitiveshavepresence(upb_msgdef *m, bool have_presence); /* Field lookup in a couple of different variations: * - itof = int to field @@ -1153,6 +1152,7 @@ class upb::OneofDef { * by name once added to a message def. */ const char* name() const; bool set_name(const char* name, Status* s); + bool set_name(const std::string& name, Status* s); /* Returns the number of fields currently defined in the oneof. */ int field_count() const; @@ -1306,7 +1306,8 @@ class upb::FileDef { /* Get/set name of the file (eg. "foo/bar.proto"). */ const char* name() const; - bool set_name(const char* fullname, Status* s); + bool set_name(const char* name, Status* s); + bool set_name(const std::string& name, Status* s); /* Package name for definitions inside the file (eg. "foo.bar"). */ const char* package() const; @@ -1900,6 +1901,9 @@ inline const char* OneofDef::name() const { inline bool OneofDef::set_name(const char* name, Status* s) { return upb_oneofdef_setname(this, name, s); } +inline bool OneofDef::set_name(const std::string& name, Status* s) { + return upb_oneofdef_setname(this, upb_safecstr(name), s); +} inline int OneofDef::field_count() const { return upb_oneofdef_numfields(this); } @@ -1979,6 +1983,9 @@ inline const char* FileDef::name() const { inline bool FileDef::set_name(const char* name, Status* s) { return upb_filedef_setname(this, name, s); } +inline bool FileDef::set_name(const std::string& name, Status* s) { + return upb_filedef_setname(this, upb_safecstr(name), s); +} inline const char* FileDef::package() const { return upb_filedef_package(this); } diff --git a/upb/symtab.c b/upb/symtab.c index 58913b5..83f549e 100644 --- a/upb/symtab.c +++ b/upb/symtab.c @@ -427,6 +427,11 @@ bool upb_symtab_addfile(upb_symtab *s, upb_filedef *file, upb_status *status) { n = upb_filedef_defcount(file); defs = malloc(sizeof(*defs) * n); + if (defs == NULL) { + upb_status_seterrmsg(status, "Out of memory"); + return false; + } + for (i = 0; i < n; i++) { defs[i] = upb_filedef_mutabledef(file, i); } -- cgit v1.2.3