Initial support for propagating namespaces from schema files to generated code

Change-Id: Ifc10c54845ea7553586d1896d509314d68e9ab0f
This commit is contained in:
Brett Cooley
2015-05-05 17:10:53 -07:00
parent 1d138fbe07
commit 249f71a12b
6 changed files with 65 additions and 17 deletions

View File

@@ -44,6 +44,18 @@ static std::string WrapInNameSpace(const Parser &parser,
return WrapInNameSpace(parser, def.defined_namespace, def.name);
}
// Translates a qualified name in flatbuffer text format to the same name in
// the equivalent C++ namepsace.
static std::string TranslateNameSpace(const std::string &qualified_name) {
std::string cpp_qualified_name = qualified_name;
size_t start_pos = 0;
while((start_pos = cpp_qualified_name.find(".", start_pos)) !=
std::string::npos) {
cpp_qualified_name.replace(start_pos, 1, "::");
}
return cpp_qualified_name;
}
// Return a C++ type from the table in idl.h
static std::string GenTypeBasic(const Parser &parser, const Type &type,
@@ -258,11 +270,15 @@ static void GenTable(const Parser &parser, StructDef &struct_def,
}
auto nested = field.attributes.Lookup("nested_flatbuffer");
if (nested) {
auto nested_root = parser.structs_.Lookup(nested->constant);
std::string qualified_name = parser.GetFullyQualifiedName(
nested->constant);
auto nested_root = parser.structs_.Lookup(qualified_name);
assert(nested_root); // Guaranteed to exist by parser.
code += " const " + nested_root->name + " *" + field.name;
std::string cpp_qualified_name = TranslateNameSpace(qualified_name);
code += " const " + cpp_qualified_name + " *" + field.name;
code += "_nested_root() const { return flatbuffers::GetRoot<";
code += nested_root->name + ">(" + field.name + "()->Data()); }\n";
code += cpp_qualified_name + ">(" + field.name + "()->Data()); }\n";
}
// Generate a comparison function for this field if it is a key.
if (field.key) {
@@ -685,11 +701,14 @@ std::string GenerateCPP(const Parser &parser,
// Generate convenient global helper functions:
if (parser.root_struct_def) {
auto &name = parser.root_struct_def->name;
std::string qualified_name = parser.GetFullyQualifiedName(name);
std::string cpp_qualified_name = TranslateNameSpace(qualified_name);
// The root datatype accessor:
code += "inline const " + name + " *Get";
code += "inline const " + cpp_qualified_name + " *Get";
code += name;
code += "(const void *buf) { return flatbuffers::GetRoot<";
code += name + ">(buf); }\n\n";
code += cpp_qualified_name + ">(buf); }\n\n";
if (opts.mutable_buffer) {
code += "inline " + name + " *GetMutable";
code += name;
@@ -702,7 +721,7 @@ std::string GenerateCPP(const Parser &parser,
code += name;
code += "Buffer(flatbuffers::Verifier &verifier) { "
"return verifier.VerifyBuffer<";
code += name + ">(); }\n\n";
code += cpp_qualified_name + ">(); }\n\n";
if (parser.file_identifier_.length()) {
// Return the identifier
@@ -727,7 +746,7 @@ std::string GenerateCPP(const Parser &parser,
// Finish a buffer with a given root object:
code += "inline void Finish" + name;
code += "Buffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<";
code += name + "> root) { fbb.Finish(root";
code += cpp_qualified_name + "> root) { fbb.Finish(root";
if (parser.file_identifier_.length())
code += ", " + name + "Identifier()";
code += "); }\n\n";

View File

@@ -773,12 +773,13 @@ void Parser::ParseSingleValue(Value &e) {
}
StructDef *Parser::LookupCreateStruct(const std::string &name) {
auto struct_def = structs_.Lookup(name);
std::string qualified_name = GetFullyQualifiedName(name);
auto struct_def = structs_.Lookup(qualified_name);
if (!struct_def) {
// Rather than failing, we create a "pre declared" StructDef, due to
// circular references, and check for errors at the end of parsing.
struct_def = new StructDef();
structs_.Add(name, struct_def);
structs_.Add(qualified_name, struct_def);
struct_def->name = name;
struct_def->predecl = true;
struct_def->defined_namespace = namespaces_.back();
@@ -951,10 +952,30 @@ void Parser::ParseDecl() {
}
bool Parser::SetRootType(const char *name) {
root_struct_def = structs_.Lookup(name);
root_struct_def = structs_.Lookup(GetFullyQualifiedName(name));
return root_struct_def != nullptr;
}
std::string Parser::GetFullyQualifiedName(const std::string &name) const {
Namespace *ns = namespaces_.back();
// Early exit if we don't have a defined namespace, or if the name is already
// partially qualified
if (ns->components.size() == 0 || name.find(".") != std::string::npos) {
return name;
}
std::stringstream stream;
for (size_t i = 0; i != ns->components.size(); ++i) {
if (i != 0) {
stream << ".";
}
stream << ns->components[i];
}
stream << "." << name;
return stream.str();
}
void Parser::MarkGenerated() {
// Since the Parser object retains definitions across files, we must
// ensure we only output code for definitions once, in the file they are first