Improved .proto conversion.

- Allowed enums to be declared before use.
- Generalized parsing of `required`.
- Reworked escaping of namespaces.
- Escaping field names that are C++ keywords.
- Many smaller fixes.

Change-Id: Ie580de7b70dc208f676f4f71bb0d061808648b8d
Tested: on Linux.
This commit is contained in:
Wouter van Oortmerssen
2017-10-02 15:41:34 -07:00
parent 5b4acf809e
commit 9c3920d0ab
6 changed files with 268 additions and 149 deletions

View File

@@ -199,7 +199,8 @@ template<typename T> class SymbolTable {
// A name space, as set in the schema. // A name space, as set in the schema.
struct Namespace { struct Namespace {
std::vector<std::string> components; Namespace() : from_table(0) {}
// Given a (potentally unqualified) name, return the "fully qualified" name // Given a (potentally unqualified) name, return the "fully qualified" name
// which has a full namespaced descriptor. // which has a full namespaced descriptor.
@@ -207,12 +208,15 @@ struct Namespace {
// the current namespace has. // the current namespace has.
std::string GetFullyQualifiedName(const std::string &name, std::string GetFullyQualifiedName(const std::string &name,
size_t max_components = 1000) const; size_t max_components = 1000) const;
std::vector<std::string> components;
size_t from_table; // Part of the namespace corresponds to a message/table.
}; };
// Base class for all definition types (fields, structs_, enums_). // Base class for all definition types (fields, structs_, enums_).
struct Definition { struct Definition {
Definition() : generated(false), defined_namespace(nullptr), Definition() : generated(false), defined_namespace(nullptr),
serialized_location(0), index(-1) {} serialized_location(0), index(-1), refcount(1) {}
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset< flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<
reflection::KeyValue>>> reflection::KeyValue>>>
@@ -229,6 +233,7 @@ struct Definition {
// For use with Serialize() // For use with Serialize()
uoffset_t serialized_location; uoffset_t serialized_location;
int index; // Inside the vector it is stored. int index; // Inside the vector it is stored.
int refcount;
}; };
struct FieldDef : public Definition { struct FieldDef : public Definition {
@@ -271,12 +276,15 @@ struct StructDef : public Definition {
const Parser &parser) const; const Parser &parser) const;
SymbolTable<FieldDef> fields; SymbolTable<FieldDef> fields;
bool fixed; // If it's struct, not a table. bool fixed; // If it's struct, not a table.
bool predecl; // If it's used before it was defined. bool predecl; // If it's used before it was defined.
bool sortbysize; // Whether fields come in the declaration or size order. bool sortbysize; // Whether fields come in the declaration or size order.
bool has_key; // It has a key field. bool has_key; // It has a key field.
size_t minalign; // What the whole object needs to be aligned to. size_t minalign; // What the whole object needs to be aligned to.
size_t bytesize; // Size if fixed. size_t bytesize; // Size if fixed.
std::unique_ptr<std::string> original_location;
}; };
inline bool IsStruct(const Type &type) { inline bool IsStruct(const Type &type) {
@@ -361,7 +369,6 @@ struct IDLOptions {
bool generate_all; bool generate_all;
bool skip_unexpected_fields_in_json; bool skip_unexpected_fields_in_json;
bool generate_name_strings; bool generate_name_strings;
bool escape_proto_identifiers;
bool generate_object_based_api; bool generate_object_based_api;
std::string cpp_object_api_pointer_type; std::string cpp_object_api_pointer_type;
std::string cpp_object_api_string_type; std::string cpp_object_api_string_type;
@@ -417,7 +424,6 @@ struct IDLOptions {
generate_all(false), generate_all(false),
skip_unexpected_fields_in_json(false), skip_unexpected_fields_in_json(false),
generate_name_strings(false), generate_name_strings(false),
escape_proto_identifiers(false),
generate_object_based_api(false), generate_object_based_api(false),
cpp_object_api_pointer_type("std::unique_ptr"), cpp_object_api_pointer_type("std::unique_ptr"),
object_suffix("T"), object_suffix("T"),
@@ -568,7 +574,11 @@ class Parser : public ParserState {
FLATBUFFERS_CHECKED_ERROR CheckInRange(int64_t val, int64_t min, int64_t max); FLATBUFFERS_CHECKED_ERROR CheckInRange(int64_t val, int64_t min, int64_t max);
StructDef *LookupStruct(const std::string &id) const;
private: private:
void Message(const std::string &msg);
void Warning(const std::string &msg);
FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg); FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val); FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
FLATBUFFERS_CHECKED_ERROR Next(); FLATBUFFERS_CHECKED_ERROR Next();

View File

@@ -85,7 +85,6 @@ std::string FlatCompiler::GetUsageString(const char* program_name) const {
" --gen-mutable Generate accessors that can mutate buffers in-place.\n" " --gen-mutable Generate accessors that can mutate buffers in-place.\n"
" --gen-onefile Generate single output file for C#.\n" " --gen-onefile Generate single output file for C#.\n"
" --gen-name-strings Generate type name functions for C++.\n" " --gen-name-strings Generate type name functions for C++.\n"
" --escape-proto-ids Disable appending '_' in namespaces names.\n"
" --gen-object-api Generate an additional object-based API.\n" " --gen-object-api Generate an additional object-based API.\n"
" --cpp-ptr-type T Set object API pointer type (default std::unique_ptr)\n" " --cpp-ptr-type T Set object API pointer type (default std::unique_ptr)\n"
" --cpp-str-type T Set object API string type (default std::string)\n" " --cpp-str-type T Set object API string type (default std::string)\n"
@@ -228,8 +227,6 @@ int FlatCompiler::Compile(int argc, const char** argv) {
binary_files_from = filenames.size(); binary_files_from = filenames.size();
} else if(arg == "--proto") { } else if(arg == "--proto") {
opts.proto_mode = true; opts.proto_mode = true;
} else if(arg == "--escape-proto-ids") {
opts.escape_proto_identifiers = true;
} else if(arg == "--schema") { } else if(arg == "--schema") {
schema_binary = true; schema_binary = true;
} else if(arg == "-M") { } else if(arg == "-M") {

View File

@@ -39,7 +39,26 @@ class CppGenerator : public BaseGenerator {
CppGenerator(const Parser &parser, const std::string &path, CppGenerator(const Parser &parser, const std::string &path,
const std::string &file_name) const std::string &file_name)
: BaseGenerator(parser, path, file_name, "", "::"), : BaseGenerator(parser, path, file_name, "", "::"),
cur_name_space_(nullptr) {} cur_name_space_(nullptr) {
const char *keywords[] = {
"alignas", "alignof", "and", "and_eq", "asm", "atomic_cancel",
"atomic_commit", "atomic_noexcept", "auto", "bitand", "bitor", "bool",
"break", "case", "catch", "char", "char16_t", "char32_t", "class",
"compl", "concept", "const", "constexpr", "const_cast", "continue",
"co_await", "co_return", "co_yield", "decltype", "default", "delete",
"do", "double", "dynamic_cast", "else", "enum", "explicit", "export",
"extern", "false", "float", "for", "friend", "goto", "if", "import",
"inline", "int", "long", "module", "mutable", "namespace", "new",
"noexcept", "not", "not_eq", "nullptr", "operator", "or", "or_eq",
"private", "protected", "public", "register", "reinterpret_cast",
"requires", "return", "short", "signed", "sizeof", "static",
"static_assert", "static_cast", "struct", "switch", "synchronized",
"template", "this", "thread_local", "throw", "true", "try", "typedef",
"typeid", "typename", "union", "unsigned", "using", "virtual", "void",
"volatile", "wchar_t", "while", "xor", "xor_eq", nullptr
};
for (auto kw = keywords; *kw; kw++) keywords_.insert(*kw);
}
std::string GenIncludeGuard() const { std::string GenIncludeGuard() const {
// Generate include guard. // Generate include guard.
@@ -85,6 +104,18 @@ class CppGenerator : public BaseGenerator {
if (num_includes) code_ += ""; if (num_includes) code_ += "";
} }
std::string EscapeKeyword(const std::string &name) const {
return keywords_.find(name) == keywords_.end() ? name : name + "_";
}
std::string Name(const Definition &def) const {
return EscapeKeyword(def.name);
}
std::string Name(const EnumVal &ev) const {
return EscapeKeyword(ev.name);
}
// Iterate through all definitions we haven't generate code for (enums, // Iterate through all definitions we haven't generate code for (enums,
// structs, and tables) and output them to a single file. // structs, and tables) and output them to a single file.
bool generate() { bool generate() {
@@ -115,9 +146,11 @@ class CppGenerator : public BaseGenerator {
const auto &struct_def = **it; const auto &struct_def = **it;
if (!struct_def.generated) { if (!struct_def.generated) {
SetNameSpace(struct_def.defined_namespace); SetNameSpace(struct_def.defined_namespace);
code_ += "struct " + struct_def.name + ";"; code_ += "struct " + Name(struct_def) + ";";
if (parser_.opts.generate_object_based_api && !struct_def.fixed) { if (parser_.opts.generate_object_based_api && !struct_def.fixed) {
code_ += "struct " + NativeName(struct_def.name, &struct_def, parser_.opts) + ";"; code_ += "struct " +
NativeName(Name(struct_def), &struct_def, parser_.opts) +
";";
} }
code_ += ""; code_ += "";
} }
@@ -204,10 +237,10 @@ class CppGenerator : public BaseGenerator {
if (parser_.root_struct_def_) { if (parser_.root_struct_def_) {
auto &struct_def = *parser_.root_struct_def_; auto &struct_def = *parser_.root_struct_def_;
SetNameSpace(struct_def.defined_namespace); SetNameSpace(struct_def.defined_namespace);
const auto &name = struct_def.name; auto name = Name(struct_def);
const auto qualified_name = auto qualified_name =
cur_name_space_->GetFullyQualifiedName(name); cur_name_space_->GetFullyQualifiedName(name);
const auto cpp_name = TranslateNameSpace(qualified_name); auto cpp_name = TranslateNameSpace(qualified_name);
code_.SetValue("STRUCT_NAME", name); code_.SetValue("STRUCT_NAME", name);
code_.SetValue("CPP_NAME", cpp_name); code_.SetValue("CPP_NAME", cpp_name);
@@ -307,6 +340,8 @@ class CppGenerator : public BaseGenerator {
private: private:
CodeWriter code_; CodeWriter code_;
std::set<std::string> keywords_;
// This tracks the current namespace so we can insert namespace declarations. // This tracks the current namespace so we can insert namespace declarations.
const Namespace *cur_name_space_; const Namespace *cur_name_space_;
@@ -477,24 +512,24 @@ class CppGenerator : public BaseGenerator {
std::string GenEnumDecl(const EnumDef &enum_def) const { std::string GenEnumDecl(const EnumDef &enum_def) const {
const IDLOptions &opts = parser_.opts; const IDLOptions &opts = parser_.opts;
return (opts.scoped_enums ? "enum class " : "enum ") + enum_def.name; return (opts.scoped_enums ? "enum class " : "enum ") + Name(enum_def);
} }
std::string GenEnumValDecl(const EnumDef &enum_def, std::string GenEnumValDecl(const EnumDef &enum_def,
const std::string &enum_val) const { const std::string &enum_val) const {
const IDLOptions &opts = parser_.opts; const IDLOptions &opts = parser_.opts;
return opts.prefixed_enums ? enum_def.name + "_" + enum_val : enum_val; return opts.prefixed_enums ? Name(enum_def) + "_" + enum_val : enum_val;
} }
std::string GetEnumValUse(const EnumDef &enum_def, std::string GetEnumValUse(const EnumDef &enum_def,
const EnumVal &enum_val) const { const EnumVal &enum_val) const {
const IDLOptions &opts = parser_.opts; const IDLOptions &opts = parser_.opts;
if (opts.scoped_enums) { if (opts.scoped_enums) {
return enum_def.name + "::" + enum_val.name; return Name(enum_def) + "::" + Name(enum_val);
} else if (opts.prefixed_enums) { } else if (opts.prefixed_enums) {
return enum_def.name + "_" + enum_val.name; return Name(enum_def) + "_" + Name(enum_val);
} else { } else {
return enum_val.name; return Name(enum_val);
} }
} }
@@ -505,87 +540,87 @@ class CppGenerator : public BaseGenerator {
std::string GetUnionElement(const EnumVal &ev, bool wrap, bool actual_type, std::string GetUnionElement(const EnumVal &ev, bool wrap, bool actual_type,
bool native_type = false) { bool native_type = false) {
if (ev.union_type.base_type == BASE_TYPE_STRUCT) { if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
auto name = actual_type ? ev.union_type.struct_def->name : ev.name; auto name = actual_type ? ev.union_type.struct_def->name : Name(ev);
return wrap return wrap
? WrapInNameSpace(ev.union_type.struct_def->defined_namespace, name) ? WrapInNameSpace(ev.union_type.struct_def->defined_namespace, name)
: name; : name;
} else if (ev.union_type.base_type == BASE_TYPE_STRING) { } else if (ev.union_type.base_type == BASE_TYPE_STRING) {
return actual_type return actual_type
? (native_type ? "std::string" : "flatbuffers::String") ? (native_type ? "std::string" : "flatbuffers::String")
: ev.name; : Name(ev);
} else { } else {
assert(false); assert(false);
return ev.name; return Name(ev);
} }
} }
static std::string UnionVerifySignature(const EnumDef &enum_def) { std::string UnionVerifySignature(const EnumDef &enum_def) {
return "bool Verify" + enum_def.name + return "bool Verify" + Name(enum_def) +
"(flatbuffers::Verifier &verifier, const void *obj, " + "(flatbuffers::Verifier &verifier, const void *obj, " +
enum_def.name + " type)"; Name(enum_def) + " type)";
} }
static std::string UnionVectorVerifySignature(const EnumDef &enum_def) { std::string UnionVectorVerifySignature(const EnumDef &enum_def) {
return "bool Verify" + enum_def.name + "Vector" + return "bool Verify" + Name(enum_def) + "Vector" +
"(flatbuffers::Verifier &verifier, " + "(flatbuffers::Verifier &verifier, " +
"const flatbuffers::Vector<flatbuffers::Offset<void>> *values, " + "const flatbuffers::Vector<flatbuffers::Offset<void>> *values, " +
"const flatbuffers::Vector<uint8_t> *types)"; "const flatbuffers::Vector<uint8_t> *types)";
} }
static std::string UnionUnPackSignature(const EnumDef &enum_def, std::string UnionUnPackSignature(const EnumDef &enum_def,
bool inclass) { bool inclass) {
return (inclass ? "static " : "") + return (inclass ? "static " : "") +
std::string("void *") + std::string("void *") +
(inclass ? "" : enum_def.name + "Union::") + (inclass ? "" : Name(enum_def) + "Union::") +
"UnPack(const void *obj, " + enum_def.name + "UnPack(const void *obj, " + Name(enum_def) +
" type, const flatbuffers::resolver_function_t *resolver)"; " type, const flatbuffers::resolver_function_t *resolver)";
} }
static std::string UnionPackSignature(const EnumDef &enum_def, bool inclass) { std::string UnionPackSignature(const EnumDef &enum_def, bool inclass) {
return "flatbuffers::Offset<void> " + return "flatbuffers::Offset<void> " +
(inclass ? "" : enum_def.name + "Union::") + (inclass ? "" : Name(enum_def) + "Union::") +
"Pack(flatbuffers::FlatBufferBuilder &_fbb, " + "Pack(flatbuffers::FlatBufferBuilder &_fbb, " +
"const flatbuffers::rehasher_function_t *_rehasher" + "const flatbuffers::rehasher_function_t *_rehasher" +
(inclass ? " = nullptr" : "") + ") const"; (inclass ? " = nullptr" : "") + ") const";
} }
static std::string TableCreateSignature(const StructDef &struct_def, std::string TableCreateSignature(const StructDef &struct_def,
bool predecl, bool predecl,
const IDLOptions & opts) { const IDLOptions & opts) {
return "flatbuffers::Offset<" + struct_def.name + "> Create" + return "flatbuffers::Offset<" + Name(struct_def) + "> Create" +
struct_def.name + Name(struct_def) +
"(flatbuffers::FlatBufferBuilder &_fbb, const " + "(flatbuffers::FlatBufferBuilder &_fbb, const " +
NativeName(struct_def.name, &struct_def, opts) + NativeName(Name(struct_def), &struct_def, opts) +
" *_o, const flatbuffers::rehasher_function_t *_rehasher" + " *_o, const flatbuffers::rehasher_function_t *_rehasher" +
(predecl ? " = nullptr" : "") + ")"; (predecl ? " = nullptr" : "") + ")";
} }
static std::string TablePackSignature(const StructDef &struct_def, std::string TablePackSignature(const StructDef &struct_def,
bool inclass, bool inclass,
const IDLOptions & opts) { const IDLOptions & opts) {
return std::string(inclass ? "static " : "") + return std::string(inclass ? "static " : "") +
"flatbuffers::Offset<" + struct_def.name + "> " + "flatbuffers::Offset<" + Name(struct_def) + "> " +
(inclass ? "" : struct_def.name + "::") + (inclass ? "" : Name(struct_def) + "::") +
"Pack(flatbuffers::FlatBufferBuilder &_fbb, " + "Pack(flatbuffers::FlatBufferBuilder &_fbb, " +
"const " + NativeName(struct_def.name, &struct_def, opts) + "* _o, " + "const " + NativeName(Name(struct_def), &struct_def, opts) + "* _o, " +
"const flatbuffers::rehasher_function_t *_rehasher" + "const flatbuffers::rehasher_function_t *_rehasher" +
(inclass ? " = nullptr" : "") + ")"; (inclass ? " = nullptr" : "") + ")";
} }
static std::string TableUnPackSignature(const StructDef &struct_def, std::string TableUnPackSignature(const StructDef &struct_def,
bool inclass, bool inclass,
const IDLOptions & opts) { const IDLOptions & opts) {
return NativeName(struct_def.name, &struct_def, opts) + " *" + return NativeName(Name(struct_def), &struct_def, opts) + " *" +
(inclass ? "" : struct_def.name + "::") + (inclass ? "" : Name(struct_def) + "::") +
"UnPack(const flatbuffers::resolver_function_t *_resolver" + "UnPack(const flatbuffers::resolver_function_t *_resolver" +
(inclass ? " = nullptr" : "") + ") const"; (inclass ? " = nullptr" : "") + ") const";
} }
static std::string TableUnPackToSignature(const StructDef &struct_def, std::string TableUnPackToSignature(const StructDef &struct_def,
bool inclass, bool inclass,
const IDLOptions & opts) { const IDLOptions & opts) {
return "void " + (inclass ? "" : struct_def.name + "::") + return "void " + (inclass ? "" : Name(struct_def) + "::") +
"UnPackTo(" + NativeName(struct_def.name, &struct_def, opts) + " *" + "UnPackTo(" + NativeName(Name(struct_def), &struct_def, opts) + " *" +
"_o, const flatbuffers::resolver_function_t *_resolver" + "_o, const flatbuffers::resolver_function_t *_resolver" +
(inclass ? " = nullptr" : "") + ") const"; (inclass ? " = nullptr" : "") + ") const";
} }
@@ -613,14 +648,14 @@ class CppGenerator : public BaseGenerator {
for (auto it = struct_def->fields.vec.begin(); for (auto it = struct_def->fields.vec.begin();
it != struct_def->fields.vec.end(); ++it) { it != struct_def->fields.vec.end(); ++it) {
const auto &field = **it; const auto &field = **it;
names.push_back(field.name); names.push_back(Name(field));
types.push_back(field.value.type); types.push_back(field.value.type);
} }
} else { } else {
for (auto it = enum_def->vals.vec.begin(); it != enum_def->vals.vec.end(); for (auto it = enum_def->vals.vec.begin(); it != enum_def->vals.vec.end();
++it) { ++it) {
const auto &ev = **it; const auto &ev = **it;
names.push_back(ev.name); names.push_back(Name(ev));
types.push_back(enum_def->is_union ? ev.union_type types.push_back(enum_def->is_union ? ev.union_type
: Type(enum_def->underlying_type)); : Type(enum_def->underlying_type));
if (static_cast<int64_t>(it - enum_def->vals.vec.begin()) != ev.value) { if (static_cast<int64_t>(it - enum_def->vals.vec.begin()) != ev.value) {
@@ -728,7 +763,7 @@ class CppGenerator : public BaseGenerator {
// an enum string lookup table, // an enum string lookup table,
// and an enum array of values // and an enum array of values
void GenEnum(const EnumDef &enum_def) { void GenEnum(const EnumDef &enum_def) {
code_.SetValue("ENUM_NAME", enum_def.name); code_.SetValue("ENUM_NAME", Name(enum_def));
code_.SetValue("BASE_TYPE", GenTypeBasic(enum_def.underlying_type, false)); code_.SetValue("BASE_TYPE", GenTypeBasic(enum_def.underlying_type, false));
code_.SetValue("SEP", ""); code_.SetValue("SEP", "");
@@ -745,7 +780,7 @@ class CppGenerator : public BaseGenerator {
const auto &ev = **it; const auto &ev = **it;
GenComment(ev.doc_comment, " "); GenComment(ev.doc_comment, " ");
code_.SetValue("KEY", GenEnumValDecl(enum_def, ev.name)); code_.SetValue("KEY", GenEnumValDecl(enum_def, Name(ev)));
code_.SetValue("VALUE", NumToString(ev.value)); code_.SetValue("VALUE", NumToString(ev.value));
code_ += "{{SEP}} {{KEY}} = {{VALUE}}\\"; code_ += "{{SEP}} {{KEY}} = {{VALUE}}\\";
code_.SetValue("SEP", ",\n"); code_.SetValue("SEP", ",\n");
@@ -822,7 +857,7 @@ class CppGenerator : public BaseGenerator {
while (val++ != ev.value) { while (val++ != ev.value) {
code_ += " \"\","; code_ += " \"\",";
} }
code_ += " \"" + ev.name + "\","; code_ += " \"" + Name(ev) + "\",";
} }
code_ += " nullptr"; code_ += " nullptr";
code_ += " };"; code_ += " };";
@@ -868,7 +903,7 @@ class CppGenerator : public BaseGenerator {
if (parser_.opts.generate_object_based_api && enum_def.is_union) { if (parser_.opts.generate_object_based_api && enum_def.is_union) {
// Generate a union type // Generate a union type
code_.SetValue("NAME", enum_def.name); code_.SetValue("NAME", Name(enum_def));
code_.SetValue("NONE", code_.SetValue("NONE",
GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE"))); GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE")));
@@ -917,7 +952,7 @@ class CppGenerator : public BaseGenerator {
NativeName(GetUnionElement(ev, true, true, true), NativeName(GetUnionElement(ev, true, true, true),
ev.union_type.struct_def, parser_.opts); ev.union_type.struct_def, parser_.opts);
code_.SetValue("NATIVE_TYPE", native_type); code_.SetValue("NATIVE_TYPE", native_type);
code_.SetValue("NATIVE_NAME", ev.name); code_.SetValue("NATIVE_NAME", Name(ev));
code_.SetValue("NATIVE_ID", GetEnumValUse(enum_def, ev)); code_.SetValue("NATIVE_ID", GetEnumValUse(enum_def, ev));
code_ += " {{NATIVE_TYPE}} *As{{NATIVE_NAME}}() {"; code_ += " {{NATIVE_TYPE}} *As{{NATIVE_NAME}}() {";
@@ -947,7 +982,7 @@ class CppGenerator : public BaseGenerator {
// verifier function to call, this should be safe even if the union type // verifier function to call, this should be safe even if the union type
// has been corrupted, since the verifiers will simply fail when called // has been corrupted, since the verifiers will simply fail when called
// on the wrong type. // on the wrong type.
code_.SetValue("ENUM_NAME", enum_def.name); code_.SetValue("ENUM_NAME", Name(enum_def));
code_ += "inline " + UnionVerifySignature(enum_def) + " {"; code_ += "inline " + UnionVerifySignature(enum_def) + " {";
code_ += " switch (type) {"; code_ += " switch (type) {";
@@ -989,8 +1024,8 @@ class CppGenerator : public BaseGenerator {
code_ += "inline " + UnionVectorVerifySignature(enum_def) + " {"; code_ += "inline " + UnionVectorVerifySignature(enum_def) + " {";
code_ += " if (values->size() != types->size()) return false;"; code_ += " if (values->size() != types->size()) return false;";
code_ += " for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {"; code_ += " for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {";
code_ += " if (!Verify" + enum_def.name + "("; code_ += " if (!Verify" + Name(enum_def) + "(";
code_ += " verifier, values->Get(i), types->GetEnum<" + enum_def.name + ">(i))) {"; code_ += " verifier, values->Get(i), types->GetEnum<" + Name(enum_def) + ">(i))) {";
code_ += " return false;"; code_ += " return false;";
code_ += " }"; code_ += " }";
code_ += " }"; code_ += " }";
@@ -1158,7 +1193,7 @@ class CppGenerator : public BaseGenerator {
} }
std::string GenFieldOffsetName(const FieldDef &field) { std::string GenFieldOffsetName(const FieldDef &field) {
std::string uname = field.name; std::string uname = Name(field);
std::transform(uname.begin(), uname.end(), uname.begin(), ToUpper); std::transform(uname.begin(), uname.end(), uname.begin(), ToUpper);
return "VT_" + uname; return "VT_" + uname;
} }
@@ -1202,7 +1237,7 @@ class CppGenerator : public BaseGenerator {
void GenParam(const FieldDef &field, bool direct, const char *prefix) { void GenParam(const FieldDef &field, bool direct, const char *prefix) {
code_.SetValue("PRE", prefix); code_.SetValue("PRE", prefix);
code_.SetValue("PARAM_NAME", field.name); code_.SetValue("PARAM_NAME", Name(field));
if (direct && field.value.type.base_type == BASE_TYPE_STRING) { if (direct && field.value.type.base_type == BASE_TYPE_STRING) {
code_.SetValue("PARAM_TYPE", "const char *"); code_.SetValue("PARAM_TYPE", "const char *");
code_.SetValue("PARAM_VALUE", "nullptr"); code_.SetValue("PARAM_VALUE", "nullptr");
@@ -1227,7 +1262,7 @@ class CppGenerator : public BaseGenerator {
auto cpp_type = field.attributes.Lookup("cpp_type"); auto cpp_type = field.attributes.Lookup("cpp_type");
auto full_type = (cpp_type ? cpp_type->constant + " *" : type + " "); auto full_type = (cpp_type ? cpp_type->constant + " *" : type + " ");
code_.SetValue("FIELD_TYPE", full_type); code_.SetValue("FIELD_TYPE", full_type);
code_.SetValue("FIELD_NAME", field.name); code_.SetValue("FIELD_NAME", Name(field));
code_ += " {{FIELD_TYPE}}{{FIELD_NAME}};"; code_ += " {{FIELD_TYPE}}{{FIELD_NAME}};";
} }
} }
@@ -1247,7 +1282,7 @@ class CppGenerator : public BaseGenerator {
if (!initializer_list.empty()) { if (!initializer_list.empty()) {
initializer_list += ",\n "; initializer_list += ",\n ";
} }
initializer_list += field.name; initializer_list += Name(field);
initializer_list += "(" + GetDefaultScalarValue(field) + ")"; initializer_list += "(" + GetDefaultScalarValue(field) + ")";
} else if (field.value.type.base_type == BASE_TYPE_STRUCT) { } else if (field.value.type.base_type == BASE_TYPE_STRUCT) {
if (IsStruct(field.value.type)) { if (IsStruct(field.value.type)) {
@@ -1257,14 +1292,14 @@ class CppGenerator : public BaseGenerator {
initializer_list += ",\n "; initializer_list += ",\n ";
} }
initializer_list += initializer_list +=
field.name + "(" + native_default->constant + ")"; Name(field) + "(" + native_default->constant + ")";
} }
} }
} else if (cpp_type) { } else if (cpp_type) {
if (!initializer_list.empty()) { if (!initializer_list.empty()) {
initializer_list += ",\n "; initializer_list += ",\n ";
} }
initializer_list += field.name + "(0)"; initializer_list += Name(field) + "(0)";
} }
} }
} }
@@ -1272,7 +1307,7 @@ class CppGenerator : public BaseGenerator {
initializer_list = "\n : " + initializer_list; initializer_list = "\n : " + initializer_list;
} }
code_.SetValue("NATIVE_NAME", NativeName(struct_def.name, &struct_def, parser_.opts)); code_.SetValue("NATIVE_NAME", NativeName(Name(struct_def), &struct_def, parser_.opts));
code_.SetValue("INIT_LIST", initializer_list); code_.SetValue("INIT_LIST", initializer_list);
code_ += " {{NATIVE_NAME}}(){{INIT_LIST}} {"; code_ += " {{NATIVE_NAME}}(){{INIT_LIST}} {";
@@ -1280,8 +1315,8 @@ class CppGenerator : public BaseGenerator {
} }
void GenNativeTable(const StructDef &struct_def) { void GenNativeTable(const StructDef &struct_def) {
const auto native_name = NativeName(struct_def.name, &struct_def, parser_.opts); const auto native_name = NativeName(Name(struct_def), &struct_def, parser_.opts);
code_.SetValue("STRUCT_NAME", struct_def.name); code_.SetValue("STRUCT_NAME", Name(struct_def));
code_.SetValue("NATIVE_NAME", native_name); code_.SetValue("NATIVE_NAME", native_name);
// Generate a C++ object that can hold an unpacked version of this table. // Generate a C++ object that can hold an unpacked version of this table.
@@ -1300,7 +1335,7 @@ class CppGenerator : public BaseGenerator {
// Generate the code to call the appropriate Verify function(s) for a field. // Generate the code to call the appropriate Verify function(s) for a field.
void GenVerifyCall(const FieldDef &field, const char* prefix) { void GenVerifyCall(const FieldDef &field, const char* prefix) {
code_.SetValue("PRE", prefix); code_.SetValue("PRE", prefix);
code_.SetValue("NAME", field.name); code_.SetValue("NAME", Name(field));
code_.SetValue("REQUIRED", field.required ? "Required" : ""); code_.SetValue("REQUIRED", field.required ? "Required" : "");
code_.SetValue("SIZE", GenTypeSize(field.value.type)); code_.SetValue("SIZE", GenTypeSize(field.value.type));
code_.SetValue("OFFSET", GenFieldOffsetName(field)); code_.SetValue("OFFSET", GenFieldOffsetName(field));
@@ -1369,14 +1404,14 @@ class CppGenerator : public BaseGenerator {
// type name() const { return GetField<type>(offset, defaultval); } // type name() const { return GetField<type>(offset, defaultval); }
GenComment(struct_def.doc_comment); GenComment(struct_def.doc_comment);
code_.SetValue("STRUCT_NAME", struct_def.name); code_.SetValue("STRUCT_NAME", Name(struct_def));
code_ += "struct {{STRUCT_NAME}} FLATBUFFERS_FINAL_CLASS" code_ += "struct {{STRUCT_NAME}} FLATBUFFERS_FINAL_CLASS"
" : private flatbuffers::Table {"; " : private flatbuffers::Table {";
if (parser_.opts.generate_object_based_api) { if (parser_.opts.generate_object_based_api) {
code_ += " typedef {{NATIVE_NAME}} NativeTableType;"; code_ += " typedef {{NATIVE_NAME}} NativeTableType;";
} }
GenFullyQualifiedNameGetter(struct_def, struct_def.name); GenFullyQualifiedNameGetter(struct_def, Name(struct_def));
// Generate field id constants. // Generate field id constants.
if (struct_def.fields.vec.size() > 0) { if (struct_def.fields.vec.size() > 0) {
@@ -1412,7 +1447,7 @@ class CppGenerator : public BaseGenerator {
const bool is_struct = IsStruct(field.value.type); const bool is_struct = IsStruct(field.value.type);
const bool is_scalar = IsScalar(field.value.type.base_type); const bool is_scalar = IsScalar(field.value.type.base_type);
code_.SetValue("FIELD_NAME", field.name); code_.SetValue("FIELD_NAME", Name(field));
// Call a different accessor for pointers, that indirects. // Call a different accessor for pointers, that indirects.
std::string accessor = ""; std::string accessor = "";
@@ -1458,12 +1493,12 @@ class CppGenerator : public BaseGenerator {
auto full_struct_name = GetUnionElement(ev, true, true); auto full_struct_name = GetUnionElement(ev, true, true);
// @TODO: Mby make this decisions more universal? How? // @TODO: Mby make this decisions more universal? How?
code_.SetValue("U_GET_TYPE", field.name + UnionTypeFieldSuffix()); code_.SetValue("U_GET_TYPE", Name(field) + UnionTypeFieldSuffix());
code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace( code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace(
u->defined_namespace, GetEnumValUse(*u, ev))); u->defined_namespace, GetEnumValUse(*u, ev)));
code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *"); code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
code_.SetValue("U_FIELD_NAME", code_.SetValue("U_FIELD_NAME",
field.name + "_as_" + ev.name); Name(field) + "_as_" + Name(ev));
// `const Type *union_name_asType() const` accessor. // `const Type *union_name_asType() const` accessor.
code_ += " {{U_FIELD_TYPE}}{{U_FIELD_NAME}}() const {"; code_ += " {{U_FIELD_TYPE}}{{U_FIELD_NAME}}() const {";
@@ -1481,7 +1516,7 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("OFFSET_NAME", offset_str); code_.SetValue("OFFSET_NAME", offset_str);
code_.SetValue("FIELD_TYPE", GenTypeBasic(field.value.type, true)); code_.SetValue("FIELD_TYPE", GenTypeBasic(field.value.type, true));
code_.SetValue("FIELD_VALUE", code_.SetValue("FIELD_VALUE",
GenUnderlyingCast(field, false, "_" + field.name)); GenUnderlyingCast(field, false, "_" + Name(field)));
code_.SetValue("DEFAULT_VALUE", GenDefaultConstant(field)); code_.SetValue("DEFAULT_VALUE", GenDefaultConstant(field));
code_ += " bool mutate_{{FIELD_NAME}}({{FIELD_TYPE}} " code_ += " bool mutate_{{FIELD_NAME}}({{FIELD_TYPE}} "
@@ -1506,7 +1541,7 @@ class CppGenerator : public BaseGenerator {
std::string qualified_name = std::string qualified_name =
parser_.current_namespace_->GetFullyQualifiedName( parser_.current_namespace_->GetFullyQualifiedName(
nested->constant); nested->constant);
auto nested_root = parser_.structs_.Lookup(qualified_name); auto nested_root = parser_.LookupStruct(qualified_name);
assert(nested_root); // Guaranteed to exist by parser. assert(nested_root); // Guaranteed to exist by parser.
(void)nested_root; (void)nested_root;
code_.SetValue("CPP_NAME", TranslateNameSpace(qualified_name)); code_.SetValue("CPP_NAME", TranslateNameSpace(qualified_name));
@@ -1601,7 +1636,7 @@ class CppGenerator : public BaseGenerator {
auto u = field.value.type.enum_def; auto u = field.value.type.enum_def;
if (u->uses_type_aliases) continue; if (u->uses_type_aliases) continue;
code_.SetValue("FIELD_NAME", field.name); code_.SetValue("FIELD_NAME", Name(field));
for (auto u_it = u->vals.vec.begin(); for (auto u_it = u->vals.vec.begin();
u_it != u->vals.vec.end(); ++u_it) { u_it != u->vals.vec.end(); ++u_it) {
@@ -1617,7 +1652,7 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *"); code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
code_.SetValue("U_ELEMENT_NAME", full_struct_name); code_.SetValue("U_ELEMENT_NAME", full_struct_name);
code_.SetValue("U_FIELD_NAME", code_.SetValue("U_FIELD_NAME",
field.name + "_as_" + ev.name); Name(field) + "_as_" + Name(ev));
// `template<> const T *union_name_as<T>() const` accessor. // `template<> const T *union_name_as<T>() const` accessor.
code_ += "template<> " code_ += "template<> "
@@ -1640,7 +1675,7 @@ class CppGenerator : public BaseGenerator {
} }
void GenBuilders(const StructDef &struct_def) { void GenBuilders(const StructDef &struct_def) {
code_.SetValue("STRUCT_NAME", struct_def.name); code_.SetValue("STRUCT_NAME", Name(struct_def));
// Generate a builder struct: // Generate a builder struct:
code_ += "struct {{STRUCT_NAME}}Builder {"; code_ += "struct {{STRUCT_NAME}}Builder {";
@@ -1660,16 +1695,16 @@ class CppGenerator : public BaseGenerator {
} }
std::string offset = GenFieldOffsetName(field); std::string offset = GenFieldOffsetName(field);
std::string name = GenUnderlyingCast(field, false, field.name); std::string name = GenUnderlyingCast(field, false, Name(field));
std::string value = is_scalar ? GenDefaultConstant(field) : ""; std::string value = is_scalar ? GenDefaultConstant(field) : "";
// Generate accessor functions of the form: // Generate accessor functions of the form:
// void add_name(type name) { // void add_name(type name) {
// fbb_.AddElement<type>(offset, name, default); // fbb_.AddElement<type>(offset, name, default);
// } // }
code_.SetValue("FIELD_NAME", field.name); code_.SetValue("FIELD_NAME", Name(field));
code_.SetValue("FIELD_TYPE", GenTypeWire(field.value.type, " ", true)); code_.SetValue("FIELD_TYPE", GenTypeWire(field.value.type, " ", true));
code_.SetValue("ADD_OFFSET", struct_def.name + "::" + offset); code_.SetValue("ADD_OFFSET", Name(struct_def) + "::" + offset);
code_.SetValue("ADD_NAME", name); code_.SetValue("ADD_NAME", name);
code_.SetValue("ADD_VALUE", value); code_.SetValue("ADD_VALUE", value);
if (is_scalar) { if (is_scalar) {
@@ -1711,7 +1746,7 @@ class CppGenerator : public BaseGenerator {
it != struct_def.fields.vec.end(); ++it) { it != struct_def.fields.vec.end(); ++it) {
const auto &field = **it; const auto &field = **it;
if (!field.deprecated && field.required) { if (!field.deprecated && field.required) {
code_.SetValue("FIELD_NAME", field.name); code_.SetValue("FIELD_NAME", Name(field));
code_.SetValue("OFFSET_NAME", GenFieldOffsetName(field)); code_.SetValue("OFFSET_NAME", GenFieldOffsetName(field));
code_ += " fbb_.Required(o, {{STRUCT_NAME}}::{{OFFSET_NAME}});"; code_ += " fbb_.Required(o, {{STRUCT_NAME}}::{{OFFSET_NAME}});";
} }
@@ -1743,7 +1778,7 @@ class CppGenerator : public BaseGenerator {
const auto &field = **it; const auto &field = **it;
if (!field.deprecated && (!struct_def.sortbysize || if (!field.deprecated && (!struct_def.sortbysize ||
size == SizeOf(field.value.type.base_type))) { size == SizeOf(field.value.type.base_type))) {
code_.SetValue("FIELD_NAME", field.name); code_.SetValue("FIELD_NAME", Name(field));
code_ += " builder_.add_{{FIELD_NAME}}({{FIELD_NAME}});"; code_ += " builder_.add_{{FIELD_NAME}}({{FIELD_NAME}});";
} }
} }
@@ -1776,7 +1811,7 @@ class CppGenerator : public BaseGenerator {
it != struct_def.fields.vec.end(); ++it) { it != struct_def.fields.vec.end(); ++it) {
const auto &field = **it; const auto &field = **it;
if (!field.deprecated) { if (!field.deprecated) {
code_.SetValue("FIELD_NAME", field.name); code_.SetValue("FIELD_NAME", Name(field));
if (field.value.type.base_type == BASE_TYPE_STRING) { if (field.value.type.base_type == BASE_TYPE_STRING) {
code_ += ",\n {{FIELD_NAME}} ? " code_ += ",\n {{FIELD_NAME}} ? "
@@ -1800,7 +1835,7 @@ class CppGenerator : public BaseGenerator {
const char *vec_elem_access, const char *vec_elem_access,
const char *vec_type_access) { const char *vec_type_access) {
return afield.value.type.enum_def->name + "Union::UnPack(" + "_e" + return afield.value.type.enum_def->name + "Union::UnPack(" + "_e" +
vec_elem_access + ", " + afield.name + UnionTypeFieldSuffix() + vec_elem_access + ", " + Name(afield) + UnionTypeFieldSuffix() +
"()" + vec_type_access + ", _resolver)"; "()" + vec_type_access + ", _resolver)";
} }
@@ -1860,9 +1895,9 @@ class CppGenerator : public BaseGenerator {
// for (uoffset_t i = 0; i < _e->size(); ++i) { // for (uoffset_t i = 0; i < _e->size(); ++i) {
// _o->field.push_back(_e->Get(_i)); // _o->field.push_back(_e->Get(_i));
// } // }
auto name = field.name; auto name = Name(field);
if (field.value.type.element == BASE_TYPE_UTYPE) { if (field.value.type.element == BASE_TYPE_UTYPE) {
name = StripUnionType(field.name); name = StripUnionType(Name(field));
} }
auto access = field.value.type.element == BASE_TYPE_UTYPE auto access = field.value.type.element == BASE_TYPE_UTYPE
? ".type" ? ".type"
@@ -1888,7 +1923,7 @@ class CppGenerator : public BaseGenerator {
case BASE_TYPE_UNION: { case BASE_TYPE_UNION: {
// Generate code that sets the union value, of the form: // Generate code that sets the union value, of the form:
// _o->field.value = Union::Unpack(_e, field_type(), resolver); // _o->field.value = Union::Unpack(_e, field_type(), resolver);
code += "_o->" + field.name + ".value = "; code += "_o->" + Name(field) + ".value = ";
code += GenUnionUnpackVal(field, "", ""); code += GenUnionUnpackVal(field, "", "");
code += ";"; code += ";";
break; break;
@@ -1903,14 +1938,14 @@ class CppGenerator : public BaseGenerator {
// _o->field = nullptr; // _o->field = nullptr;
code += "if (_resolver) "; code += "if (_resolver) ";
code += "(*_resolver)"; code += "(*_resolver)";
code += "(reinterpret_cast<void **>(&_o->" + field.name + "), "; code += "(reinterpret_cast<void **>(&_o->" + Name(field) + "), ";
code += "static_cast<flatbuffers::hash_value_t>(_e));"; code += "static_cast<flatbuffers::hash_value_t>(_e));";
code += " else "; code += " else ";
code += "_o->" + field.name + " = nullptr;"; code += "_o->" + Name(field) + " = nullptr;";
} else { } else {
// Generate code for assigning the value, of the form: // Generate code for assigning the value, of the form:
// _o->field = value; // _o->field = value;
code += "_o->" + field.name + " = "; code += "_o->" + Name(field) + " = ";
code += GenUnpackVal(field.value.type, "_e", false, field) + ";"; code += GenUnpackVal(field.value.type, "_e", false, field) + ";";
} }
break; break;
@@ -1922,10 +1957,10 @@ class CppGenerator : public BaseGenerator {
std::string GenCreateParam(const FieldDef &field) { std::string GenCreateParam(const FieldDef &field) {
std::string value = "_o->"; std::string value = "_o->";
if (field.value.type.base_type == BASE_TYPE_UTYPE) { if (field.value.type.base_type == BASE_TYPE_UTYPE) {
value += StripUnionType(field.name); value += StripUnionType(Name(field));
value += ".type"; value += ".type";
} else { } else {
value += field.name; value += Name(field);
} }
if (field.attributes.Lookup("cpp_type")) { if (field.attributes.Lookup("cpp_type")) {
auto type = GenTypeBasic(field.value.type, false); auto type = GenTypeBasic(field.value.type, false);
@@ -2062,8 +2097,8 @@ class CppGenerator : public BaseGenerator {
// Generate code for tables that needs to come after the regular definition. // Generate code for tables that needs to come after the regular definition.
void GenTablePost(const StructDef &struct_def) { void GenTablePost(const StructDef &struct_def) {
code_.SetValue("STRUCT_NAME", struct_def.name); code_.SetValue("STRUCT_NAME", Name(struct_def));
code_.SetValue("NATIVE_NAME", NativeName(struct_def.name, &struct_def, parser_.opts)); code_.SetValue("NATIVE_NAME", NativeName(Name(struct_def), &struct_def, parser_.opts));
if (parser_.opts.generate_object_based_api) { if (parser_.opts.generate_object_based_api) {
// Generate the X::UnPack() method. // Generate the X::UnPack() method.
@@ -2092,7 +2127,7 @@ class CppGenerator : public BaseGenerator {
const auto statement = const auto statement =
GenUnpackFieldStatement(field, is_union ? *(it + 1) : nullptr); GenUnpackFieldStatement(field, is_union ? *(it + 1) : nullptr);
code_.SetValue("FIELD_NAME", field.name); code_.SetValue("FIELD_NAME", Name(field));
auto prefix = " { auto _e = {{FIELD_NAME}}(); "; auto prefix = " { auto _e = {{FIELD_NAME}}(); ";
auto check = IsScalar(field.value.type.base_type) ? "" : "if (_e) "; auto check = IsScalar(field.value.type.base_type) ? "" : "if (_e) ";
auto postfix = " };"; auto postfix = " };";
@@ -2117,7 +2152,7 @@ class CppGenerator : public BaseGenerator {
" struct _VectorArgs " " struct _VectorArgs "
"{ flatbuffers::FlatBufferBuilder *__fbb; " "{ flatbuffers::FlatBufferBuilder *__fbb; "
"const " + "const " +
NativeName(struct_def.name, &struct_def, parser_.opts) + NativeName(Name(struct_def), &struct_def, parser_.opts) +
"* __o; " "* __o; "
"const flatbuffers::rehasher_function_t *__rehasher; } _va = { " "const flatbuffers::rehasher_function_t *__rehasher; } _va = { "
"&_fbb, _o, _rehasher}; (void)_va;"; "&_fbb, _o, _rehasher}; (void)_va;";
@@ -2128,7 +2163,7 @@ class CppGenerator : public BaseGenerator {
if (field.deprecated) { if (field.deprecated) {
continue; continue;
} }
code_ += " auto _" + field.name + " = " + GenCreateParam(field) + ";"; code_ += " auto _" + Name(field) + " = " + GenCreateParam(field) + ";";
} }
// Need to call "Create" with the struct namespace. // Need to call "Create" with the struct namespace.
const auto qualified_create_name = struct_def.defined_namespace->GetFullyQualifiedName("Create"); const auto qualified_create_name = struct_def.defined_namespace->GetFullyQualifiedName("Create");
@@ -2156,9 +2191,9 @@ class CppGenerator : public BaseGenerator {
// Call the CreateX function using values from |_o|. // Call the CreateX function using values from |_o|.
if (pass_by_address) { if (pass_by_address) {
code_ += ",\n &_" + field.name + "\\"; code_ += ",\n &_" + Name(field) + "\\";
} else { } else {
code_ += ",\n _" + field.name + "\\"; code_ += ",\n _" + Name(field) + "\\";
} }
} }
code_ += ");"; code_ += ");";
@@ -2204,7 +2239,7 @@ class CppGenerator : public BaseGenerator {
// platforms. // platforms.
GenComment(struct_def.doc_comment); GenComment(struct_def.doc_comment);
code_.SetValue("ALIGN", NumToString(struct_def.minalign)); code_.SetValue("ALIGN", NumToString(struct_def.minalign));
code_.SetValue("STRUCT_NAME", struct_def.name); code_.SetValue("STRUCT_NAME", Name(struct_def));
code_ += "MANUALLY_ALIGNED_STRUCT({{ALIGN}}) " code_ += "MANUALLY_ALIGNED_STRUCT({{ALIGN}}) "
"{{STRUCT_NAME}} FLATBUFFERS_FINAL_CLASS {"; "{{STRUCT_NAME}} FLATBUFFERS_FINAL_CLASS {";
@@ -2216,7 +2251,7 @@ class CppGenerator : public BaseGenerator {
const auto &field = **it; const auto &field = **it;
code_.SetValue("FIELD_TYPE", code_.SetValue("FIELD_TYPE",
GenTypeGet(field.value.type, " ", "", " ", false)); GenTypeGet(field.value.type, " ", "", " ", false));
code_.SetValue("FIELD_NAME", field.name); code_.SetValue("FIELD_NAME", Name(field));
code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}_;"; code_ += " {{FIELD_TYPE}}{{FIELD_NAME}}_;";
if (field.padding) { if (field.padding) {
@@ -2229,7 +2264,7 @@ class CppGenerator : public BaseGenerator {
// Generate GetFullyQualifiedName // Generate GetFullyQualifiedName
code_ += ""; code_ += "";
code_ += " public:"; code_ += " public:";
GenFullyQualifiedNameGetter(struct_def, struct_def.name); GenFullyQualifiedNameGetter(struct_def, Name(struct_def));
// Generate a default constructor. // Generate a default constructor.
code_ += " {{STRUCT_NAME}}() {"; code_ += " {{STRUCT_NAME}}() {";
@@ -2248,8 +2283,8 @@ class CppGenerator : public BaseGenerator {
for (auto it = struct_def.fields.vec.begin(); for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) { it != struct_def.fields.vec.end(); ++it) {
const auto &field = **it; const auto &field = **it;
const auto member_name = field.name + "_"; const auto member_name = Name(field) + "_";
const auto arg_name = "_" + field.name; const auto arg_name = "_" + Name(field);
const auto arg_type = const auto arg_type =
GenTypeGet(field.value.type, " ", "const ", " &", true); GenTypeGet(field.value.type, " ", "const ", " &", true);
@@ -2295,11 +2330,11 @@ class CppGenerator : public BaseGenerator {
auto field_type = GenTypeGet(field.value.type, " ", "const ", " &", true); auto field_type = GenTypeGet(field.value.type, " ", "const ", " &", true);
auto is_scalar = IsScalar(field.value.type.base_type); auto is_scalar = IsScalar(field.value.type.base_type);
auto member = field.name + "_"; auto member = Name(field) + "_";
auto value = is_scalar ? "flatbuffers::EndianScalar(" + member + ")" auto value = is_scalar ? "flatbuffers::EndianScalar(" + member + ")"
: member; : member;
code_.SetValue("FIELD_NAME", field.name); code_.SetValue("FIELD_NAME", Name(field));
code_.SetValue("FIELD_TYPE", field_type); code_.SetValue("FIELD_TYPE", field_type);
code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, value)); code_.SetValue("FIELD_VALUE", GenUnderlyingCast(field, true, value));
@@ -2314,7 +2349,7 @@ class CppGenerator : public BaseGenerator {
if (is_scalar) { if (is_scalar) {
code_.SetValue("ARG", GenTypeBasic(field.value.type, true)); code_.SetValue("ARG", GenTypeBasic(field.value.type, true));
code_.SetValue("FIELD_VALUE", code_.SetValue("FIELD_VALUE",
GenUnderlyingCast(field, false, "_" + field.name)); GenUnderlyingCast(field, false, "_" + Name(field)));
code_ += " void mutate_{{FIELD_NAME}}({{ARG}} _{{FIELD_NAME}}) {"; code_ += " void mutate_{{FIELD_NAME}}({{ARG}} _{{FIELD_NAME}}) {";
code_ += " flatbuffers::WriteScalar(&{{FIELD_NAME}}_, " code_ += " flatbuffers::WriteScalar(&{{FIELD_NAME}}_, "

View File

@@ -23,18 +23,20 @@
namespace flatbuffers { namespace flatbuffers {
static std::string GenType(const Type &type) { static std::string GenType(const Type &type, bool underlying = false) {
switch (type.base_type) { switch (type.base_type) {
case BASE_TYPE_STRUCT: case BASE_TYPE_STRUCT:
return type.struct_def->defined_namespace->GetFullyQualifiedName( return type.struct_def->defined_namespace->GetFullyQualifiedName(
type.struct_def->name); type.struct_def->name);
case BASE_TYPE_UNION:
return type.enum_def->defined_namespace->GetFullyQualifiedName(
type.enum_def->name);
case BASE_TYPE_VECTOR: case BASE_TYPE_VECTOR:
return "[" + GenType(type.VectorType()) + "]"; return "[" + GenType(type.VectorType()) + "]";
default: default:
return kTypeNames[type.base_type]; if (type.enum_def && !underlying) {
return type.enum_def->defined_namespace->GetFullyQualifiedName(
type.enum_def->name);
} else {
return kTypeNames[type.base_type];
}
} }
} }
@@ -54,14 +56,13 @@ static void GenNameSpace(const Namespace &name_space, std::string *_schema,
// Generate a flatbuffer schema from the Parser's internal representation. // Generate a flatbuffer schema from the Parser's internal representation.
std::string GenerateFBS(const Parser &parser, const std::string &file_name) { std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
// Proto namespaces may clash with table names, so we have to prefix all: // Proto namespaces may clash with table names, escape the ones that were
if (!parser.opts.escape_proto_identifiers) { // generated from a table:
for (auto it = parser.namespaces_.begin(); it != parser.namespaces_.end(); for (auto it = parser.namespaces_.begin(); it != parser.namespaces_.end();
++it) { ++it) {
for (auto comp = (*it)->components.begin(); comp != (*it)->components.end(); auto &ns = **it;
++comp) { for (size_t i = 0; i < ns.from_table; i++) {
(*comp) = "_" + (*comp); ns.components[ns.components.size() - 1 - i] += "_";
}
} }
} }
@@ -90,7 +91,7 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
GenNameSpace(*enum_def.defined_namespace, &schema, &last_namespace); GenNameSpace(*enum_def.defined_namespace, &schema, &last_namespace);
GenComment(enum_def.doc_comment, &schema, nullptr); GenComment(enum_def.doc_comment, &schema, nullptr);
schema += "enum " + enum_def.name + " : "; schema += "enum " + enum_def.name + " : ";
schema += GenType(enum_def.underlying_type) + " {\n"; schema += GenType(enum_def.underlying_type, true) + " {\n";
for (auto it = enum_def.vals.vec.begin(); for (auto it = enum_def.vals.vec.begin();
it != enum_def.vals.vec.end(); ++it) { it != enum_def.vals.vec.end(); ++it) {
auto &ev = **it; auto &ev = **it;
@@ -109,11 +110,13 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
for (auto field_it = struct_def.fields.vec.begin(); for (auto field_it = struct_def.fields.vec.begin();
field_it != struct_def.fields.vec.end(); ++field_it) { field_it != struct_def.fields.vec.end(); ++field_it) {
auto &field = **field_it; auto &field = **field_it;
GenComment(field.doc_comment, &schema, nullptr, " "); if (field.value.type.base_type != BASE_TYPE_UTYPE) {
schema += " " + field.name + ":" + GenType(field.value.type); GenComment(field.doc_comment, &schema, nullptr, " ");
if (field.value.constant != "0") schema += " = " + field.value.constant; schema += " " + field.name + ":" + GenType(field.value.type);
if (field.required) schema += " (required)"; if (field.value.constant != "0") schema += " = " + field.value.constant;
schema += ";\n"; if (field.required) schema += " (required)";
schema += ";\n";
}
} }
schema += "}\n\n"; schema += "}\n\n";
} }

View File

@@ -75,7 +75,7 @@ static bool ValidateUTF8(const std::string &str) {
return true; return true;
} }
CheckedError Parser::Error(const std::string &msg) { void Parser::Message(const std::string &msg) {
error_ = file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : ""; error_ = file_being_parsed_.length() ? AbsolutePath(file_being_parsed_) : "";
#ifdef _WIN32 #ifdef _WIN32
error_ += "(" + NumToString(line_) + ")"; // MSVC alike error_ += "(" + NumToString(line_) + ")"; // MSVC alike
@@ -83,7 +83,15 @@ CheckedError Parser::Error(const std::string &msg) {
if (file_being_parsed_.length()) error_ += ":"; if (file_being_parsed_.length()) error_ += ":";
error_ += NumToString(line_) + ":0"; // gcc alike error_ += NumToString(line_) + ":0"; // gcc alike
#endif #endif
error_ += ": error: " + msg; error_ += ": " + msg;
}
void Parser::Warning(const std::string &msg) {
Message("warning: " + msg);
}
CheckedError Parser::Error(const std::string &msg) {
Message("error: " + msg);
return CheckedError(true); return CheckedError(true);
} }
@@ -454,6 +462,12 @@ EnumDef *Parser::LookupEnum(const std::string &id) {
return nullptr; return nullptr;
} }
StructDef *Parser::LookupStruct(const std::string &id) const {
auto sd = structs_.Lookup(id);
if (sd) sd->refcount++;
return sd;
}
CheckedError Parser::ParseTypeIdent(Type &type) { CheckedError Parser::ParseTypeIdent(Type &type) {
std::string id = attribute_; std::string id = attribute_;
EXPECT(kTokenIdentifier); EXPECT(kTokenIdentifier);
@@ -557,7 +571,7 @@ CheckedError Parser::AddField(StructDef &struct_def, const std::string &name,
CheckedError Parser::ParseField(StructDef &struct_def) { CheckedError Parser::ParseField(StructDef &struct_def) {
std::string name = attribute_; std::string name = attribute_;
if (structs_.Lookup(name)) if (LookupStruct(name))
return Error("field name can not be the same as table/struct name"); return Error("field name can not be the same as table/struct name");
std::vector<std::string> dc = doc_comment_; std::vector<std::string> dc = doc_comment_;
@@ -610,7 +624,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
!type.enum_def->attributes.Lookup("bit_flags") && !type.enum_def->attributes.Lookup("bit_flags") &&
!type.enum_def->ReverseLookup(static_cast<int>( !type.enum_def->ReverseLookup(static_cast<int>(
StringToInt(field->value.constant.c_str())))) StringToInt(field->value.constant.c_str()))))
return Error("enum " + type.enum_def->name + Warning("enum " + type.enum_def->name +
" does not have a declaration for this field\'s default of " + " does not have a declaration for this field\'s default of " +
field->value.constant); field->value.constant);
@@ -682,7 +696,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
// Keep a pointer to StructDef in FieldDef to simplify re-use later // Keep a pointer to StructDef in FieldDef to simplify re-use later
auto nested_qualified_name = auto nested_qualified_name =
current_namespace_->GetFullyQualifiedName(nested->constant); current_namespace_->GetFullyQualifiedName(nested->constant);
field->nested_flatbuffer = structs_.Lookup(nested_qualified_name); field->nested_flatbuffer = LookupStruct(nested_qualified_name);
} }
if (field->attributes.Lookup("flexbuffer")) { if (field->attributes.Lookup("flexbuffer")) {
@@ -1326,7 +1340,7 @@ StructDef *Parser::LookupCreateStruct(const std::string &name,
bool create_if_new, bool definition) { bool create_if_new, bool definition) {
std::string qualified_name = current_namespace_->GetFullyQualifiedName(name); std::string qualified_name = current_namespace_->GetFullyQualifiedName(name);
// See if it exists pre-declared by an unqualified use. // See if it exists pre-declared by an unqualified use.
auto struct_def = structs_.Lookup(name); auto struct_def = LookupStruct(name);
if (struct_def && struct_def->predecl) { if (struct_def && struct_def->predecl) {
if (definition) { if (definition) {
// Make sure it has the current namespace, and is registered under its // Make sure it has the current namespace, and is registered under its
@@ -1337,7 +1351,7 @@ StructDef *Parser::LookupCreateStruct(const std::string &name,
return struct_def; return struct_def;
} }
// See if it exists pre-declared by an qualified use. // See if it exists pre-declared by an qualified use.
struct_def = structs_.Lookup(qualified_name); struct_def = LookupStruct(qualified_name);
if (struct_def && struct_def->predecl) { if (struct_def && struct_def->predecl) {
if (definition) { if (definition) {
// Make sure it has the current namespace. // Make sure it has the current namespace.
@@ -1349,7 +1363,7 @@ StructDef *Parser::LookupCreateStruct(const std::string &name,
// Search thru parent namespaces. // Search thru parent namespaces.
for (size_t components = current_namespace_->components.size(); for (size_t components = current_namespace_->components.size();
components && !struct_def; components--) { components && !struct_def; components--) {
struct_def = structs_.Lookup( struct_def = LookupStruct(
current_namespace_->GetFullyQualifiedName(name, components - 1)); current_namespace_->GetFullyQualifiedName(name, components - 1));
} }
} }
@@ -1363,12 +1377,13 @@ StructDef *Parser::LookupCreateStruct(const std::string &name,
// Not a definition. // Not a definition.
// Rather than failing, we create a "pre declared" StructDef, due to // Rather than failing, we create a "pre declared" StructDef, due to
// circular references, and check for errors at the end of parsing. // circular references, and check for errors at the end of parsing.
// It is defined in the root namespace, since we don't know what the // It is defined in the current namespace, as the best guess what the
// final namespace will be. // final namespace will be.
// TODO: maybe safer to use special namespace?
structs_.Add(name, struct_def); structs_.Add(name, struct_def);
struct_def->name = name; struct_def->name = name;
struct_def->defined_namespace = empty_namespace_; struct_def->defined_namespace = current_namespace_;
struct_def->original_location.reset(new std::string(file_being_parsed_ +
":" + NumToString(line_)));
} }
} }
return struct_def; return struct_def;
@@ -1655,9 +1670,9 @@ CheckedError Parser::ParseService() {
} }
bool Parser::SetRootType(const char *name) { bool Parser::SetRootType(const char *name) {
root_struct_def_ = structs_.Lookup(name); root_struct_def_ = LookupStruct(name);
if (!root_struct_def_) if (!root_struct_def_)
root_struct_def_ = structs_.Lookup( root_struct_def_ = LookupStruct(
current_namespace_->GetFullyQualifiedName(name)); current_namespace_->GetFullyQualifiedName(name));
return root_struct_def_ != nullptr; return root_struct_def_ != nullptr;
} }
@@ -1735,6 +1750,7 @@ CheckedError Parser::ParseProtoDecl() {
*ns = *current_namespace_; *ns = *current_namespace_;
// But with current message name. // But with current message name.
ns->components.push_back(name); ns->components.push_back(name);
ns->from_table++;
parent_namespace = current_namespace_; parent_namespace = current_namespace_;
current_namespace_ = UniqueNamespace(ns); current_namespace_ = UniqueNamespace(ns);
} }
@@ -1797,9 +1813,8 @@ CheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend,
EXPECT(';'); EXPECT(';');
} else if (IsIdent("reserved")) { // Skip these. } else if (IsIdent("reserved")) { // Skip these.
NEXT(); NEXT();
EXPECT(kTokenIntegerConstant); while (!Is(';')) { NEXT(); } // A variety of formats, just skip.
while (Is(',')) { NEXT(); EXPECT(kTokenIntegerConstant); } NEXT();
EXPECT(';');
} else { } else {
std::vector<std::string> field_comment = doc_comment_; std::vector<std::string> field_comment = doc_comment_;
// Parse the qualifier. // Parse the qualifier.
@@ -1837,6 +1852,13 @@ CheckedError Parser::ParseProtoFields(StructDef *struct_def, bool isextend,
if (repeated) { if (repeated) {
type.element = type.base_type; type.element = type.base_type;
type.base_type = BASE_TYPE_VECTOR; type.base_type = BASE_TYPE_VECTOR;
if (type.element == BASE_TYPE_VECTOR) {
// We have a vector or vectors, which FlatBuffers doesn't support.
// For now make it a vector of string (since the source is likely
// "repeated bytes").
// TODO(wvo): A better solution would be to wrap this in a table.
type.element = BASE_TYPE_STRING;
}
} }
std::string name = attribute_; std::string name = attribute_;
EXPECT(kTokenIdentifier); EXPECT(kTokenIdentifier);
@@ -2088,11 +2110,63 @@ CheckedError Parser::ParseRoot(const char *source, const char **include_paths,
ECHECK(DoParse(source, include_paths, source_filename, nullptr)); ECHECK(DoParse(source, include_paths, source_filename, nullptr));
// Check that all types were defined. // Check that all types were defined.
for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ++it) { for (auto it = structs_.vec.begin(); it != structs_.vec.end(); ) {
if ((*it)->predecl) { auto &struct_def = **it;
return Error("type referenced but not defined (check namespace): " + if (struct_def.predecl) {
(*it)->name); if (opts.proto_mode) {
// Protos allow enums to be used before declaration, so check if that
// is the case here.
EnumDef *enum_def = nullptr;
for (size_t components = struct_def.defined_namespace->
components.size() + 1;
components && !enum_def; components--) {
auto qualified_name = struct_def.defined_namespace->
GetFullyQualifiedName(struct_def.name,
components - 1);
enum_def = LookupEnum(qualified_name);
}
if (enum_def) {
// This is pretty slow, but a simple solution for now.
auto initial_count = struct_def.refcount;
for (auto struct_it = structs_.vec.begin();
struct_it != structs_.vec.end();
++struct_it) {
auto &sd = **struct_it;
for (auto field_it = sd.fields.vec.begin();
field_it != sd.fields.vec.end();
++field_it) {
auto &field = **field_it;
if (field.value.type.struct_def == &struct_def) {
field.value.type.struct_def = nullptr;
field.value.type.enum_def = enum_def;
auto &bt = field.value.type.base_type == BASE_TYPE_VECTOR
? field.value.type.element
: field.value.type.base_type;
assert(bt == BASE_TYPE_STRUCT);
bt = enum_def->underlying_type.base_type;
struct_def.refcount--;
enum_def->refcount++;
}
}
}
if (struct_def.refcount)
return Error("internal: " + NumToString(struct_def.refcount) + "/" +
NumToString(initial_count) +
" use(s) of pre-declaration enum not accounted for: "
+ enum_def->name);
structs_.dict.erase(structs_.dict.find(struct_def.name));
it = structs_.vec.erase(it);
delete &struct_def;
continue; // Skip error.
}
}
auto err = "type referenced but not defined (check namespace): " +
struct_def.name;
if (struct_def.original_location)
err += ", originally at: " + *struct_def.original_location;
return Error(err);
} }
++it;
} }
// This check has to happen here and not earlier, because only now do we // This check has to happen here and not earlier, because only now do we
@@ -2433,7 +2507,7 @@ std::string Parser::ConformTo(const Parser &base) {
auto &struct_def = **sit; auto &struct_def = **sit;
auto qualified_name = auto qualified_name =
struct_def.defined_namespace->GetFullyQualifiedName(struct_def.name); struct_def.defined_namespace->GetFullyQualifiedName(struct_def.name);
auto struct_def_base = base.structs_.Lookup(qualified_name); auto struct_def_base = base.LookupStruct(qualified_name);
if (!struct_def_base) continue; if (!struct_def_base) continue;
for (auto fit = struct_def.fields.vec.begin(); for (auto fit = struct_def.fields.vec.begin();
fit != struct_def.fields.vec.end(); ++fit) { fit != struct_def.fields.vec.end(); ++fit) {

View File

@@ -1,6 +1,6 @@
// Generated from test.proto // Generated from test.proto
namespace _proto._test; namespace proto.test;
/// Enum doc comment. /// Enum doc comment.
enum ProtoEnum : int { enum ProtoEnum : int {
@@ -33,12 +33,12 @@ table ProtoMessage {
/// lines /// lines
l:string (required); l:string (required);
m:[ubyte]; m:[ubyte];
n:_proto._test._ProtoMessage.OtherMessage; n:proto.test.ProtoMessage_.OtherMessage;
o:[string]; o:[string];
z:_proto._test.ImportedMessage; z:proto.test.ImportedMessage;
} }
namespace _proto._test._ProtoMessage; namespace proto.test.ProtoMessage_;
table OtherMessage { table OtherMessage {
a:double; a:double;