diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index d5dfb57e4..eb5093461 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -23,11 +23,15 @@ namespace flatbuffers { namespace cpp { +// This tracks the current namespace so we can insert namespace declarations. +// TODO(wvo): this needs to be moved into a code generator context object. +static const Namespace *code_generator_cur_name_space = nullptr; + // Ensure that a type is prefixed with its namespace whenever it is used // outside of its namespace. -static std::string WrapInNameSpace(const Parser &parser, const Namespace *ns, +static std::string WrapInNameSpace(const Namespace *ns, const std::string &name) { - if (parser.namespaces_.back() != ns) { + if (code_generator_cur_name_space != ns) { std::string qualified_name; for (auto it = ns->components.begin(); it != ns->components.end(); ++it) { @@ -39,9 +43,8 @@ static std::string WrapInNameSpace(const Parser &parser, const Namespace *ns, } } -static std::string WrapInNameSpace(const Parser &parser, - const Definition &def) { - return WrapInNameSpace(parser, def.defined_namespace, def.name); +static std::string WrapInNameSpace(const Definition &def) { + return WrapInNameSpace(def.defined_namespace, def.name); } // Translates a qualified name in flatbuffer text format to the same name in @@ -58,8 +61,7 @@ static std::string TranslateNameSpace(const std::string &qualified_name) { // Return a C++ type from the table in idl.h -static std::string GenTypeBasic(const Parser &parser, const Type &type, - bool user_facing_type) { +static std::string GenTypeBasic(const Type &type, bool user_facing_type) { static const char *ctypename[] = { #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \ #CTYPE, @@ -67,7 +69,7 @@ static std::string GenTypeBasic(const Parser &parser, const Type &type, #undef FLATBUFFERS_TD }; if (user_facing_type) { - if (type.enum_def) return WrapInNameSpace(parser, *type.enum_def); + if (type.enum_def) return WrapInNameSpace(*type.enum_def); if (type.base_type == BASE_TYPE_BOOL) return "bool"; } return ctypename[type.base_type]; @@ -86,7 +88,7 @@ static std::string GenTypePointer(const Parser &parser, const Type &type) { return "flatbuffers::Vector<" + GenTypeWire(parser, type.VectorType(), "", false) + ">"; case BASE_TYPE_STRUCT: { - return WrapInNameSpace(parser, *type.struct_def); + return WrapInNameSpace(*type.struct_def); } case BASE_TYPE_UNION: // fall through @@ -100,7 +102,7 @@ static std::string GenTypePointer(const Parser &parser, const Type &type) { static std::string GenTypeWire(const Parser &parser, const Type &type, const char *postfix, bool user_facing_type) { return IsScalar(type.base_type) - ? GenTypeBasic(parser, type, user_facing_type) + postfix + ? GenTypeBasic(type, user_facing_type) + postfix : IsStruct(type) ? "const " + GenTypePointer(parser, type) + " *" : "flatbuffers::Offset<" + GenTypePointer(parser, type) + ">" + postfix; @@ -110,7 +112,7 @@ static std::string GenTypeWire(const Parser &parser, const Type &type, // serialized size. static std::string GenTypeSize(const Parser &parser, const Type &type) { return IsScalar(type.base_type) - ? GenTypeBasic(parser, type, false) + ? GenTypeBasic(type, false) : IsStruct(type) ? GenTypePointer(parser, type) : "flatbuffers::uoffset_t"; @@ -122,7 +124,7 @@ static std::string GenTypeGet(const Parser &parser, const Type &type, const char *afterbasic, const char *beforeptr, const char *afterptr, bool user_facing_type) { return IsScalar(type.base_type) - ? GenTypeBasic(parser, type, user_facing_type) + afterbasic + ? GenTypeBasic(type, user_facing_type) + afterbasic : beforeptr + GenTypePointer(parser, type) + afterptr; } @@ -148,16 +150,20 @@ static std::string GetEnumVal(const EnumDef &enum_def, const EnumVal &enum_val, } } +std::string EnumSignature(EnumDef &enum_def) { + return "inline bool Verify" + enum_def.name + + "(flatbuffers::Verifier &verifier, " + + "const void *union_obj, " + enum_def.name + " type)"; +} + // Generate an enum declaration and an enum string lookup table. static void GenEnum(const Parser &parser, EnumDef &enum_def, - std::string *code_ptr, std::string *code_ptr_post) { - if (enum_def.generated) return; + std::string *code_ptr) { std::string &code = *code_ptr; - std::string &code_post = *code_ptr_post; GenComment(enum_def.doc_comment, code_ptr, nullptr); code += GenEnumDecl(enum_def, parser.opts); if (parser.opts.scoped_enums) - code += " : " + GenTypeBasic(parser, enum_def.underlying_type, false); + code += " : " + GenTypeBasic(enum_def.underlying_type, false); code += " {\n"; EnumVal *minv = nullptr, *maxv = nullptr; for (auto it = enum_def.vals.vec.begin(); @@ -208,45 +214,47 @@ static void GenEnum(const Parser &parser, EnumDef &enum_def, } if (enum_def.is_union) { - // Generate a verifier function for this union that can be called by the - // table verifier functions. It uses a switch case to select a specific - // verifier function to call, this should be safe even if the union type - // has been corrupted, since the verifiers will simply fail when called - // on the wrong type. - auto signature = "inline bool Verify" + enum_def.name + - "(flatbuffers::Verifier &verifier, " + - "const void *union_obj, " + enum_def.name + " type)"; - code += signature + ";\n\n"; - code_post += signature + " {\n switch (type) {\n"; - for (auto it = enum_def.vals.vec.begin(); - it != enum_def.vals.vec.end(); - ++it) { - auto &ev = **it; - code_post += " case " + GetEnumVal(enum_def, ev, parser.opts); - if (!ev.value) { - code_post += ": return true;\n"; // "NONE" enum value. - } else { - code_post += ": return verifier.VerifyTable(reinterpret_cast(" + val + ")"; } else { return val; @@ -262,9 +270,7 @@ std::string GenFieldOffsetName(const FieldDef &field) { // Generate an accessor struct, builder structs & function for a table. static void GenTable(const Parser &parser, StructDef &struct_def, std::string *code_ptr) { - if (struct_def.generated) return; std::string &code = *code_ptr; - // Generate an accessor struct, with methods of the form: // type name() const { return GetField(offset, defaultval); } GenComment(struct_def.doc_comment, code_ptr, nullptr); @@ -281,7 +287,7 @@ static void GenTable(const Parser &parser, StructDef &struct_def, auto &field = **it; if (!field.deprecated) { // Deprecated fields won't be accessible. if (!is_first_field) { - // Add trailing comma and newline to previous element. Don't add trailing comma to + // Add trailing comma and newline to previous element. Don't add trailing comma to // last element since older versions of gcc complain about this. code += ",\n"; } else { @@ -317,19 +323,19 @@ static void GenTable(const Parser &parser, StructDef &struct_def, if (IsScalar(field.value.type.base_type)) call += ", " + field.value.constant; call += ")"; - code += GenUnderlyingCast(parser, field, true, call); + code += GenUnderlyingCast(field, true, call); code += "; }\n"; if (parser.opts.mutable_buffer) { if (is_scalar) { code += " bool mutate_" + field.name + "("; - code += GenTypeBasic(parser, field.value.type, true); + code += GenTypeBasic(field.value.type, true); code += " _" + field.name + ") { return SetField(" + offsetstr + ", "; - code += GenUnderlyingCast(parser, field, false, "_" + field.name); + code += GenUnderlyingCast(field, false, "_" + field.name); code += "); }\n"; } else { auto type = GenTypeGet(parser, field.value.type, " ", "", " *", true); code += " " + type + "mutable_" + field.name + "() { return "; - code += GenUnderlyingCast(parser, field, true, + code += GenUnderlyingCast(field, true, accessor + type + ">(" + offsetstr + ")"); code += "; }\n"; } @@ -366,7 +372,7 @@ static void GenTable(const Parser &parser, StructDef &struct_def, code += GenTypeGet(parser, field.value.type, " ", "const ", " *", true); } else { - code += GenTypeBasic(parser, field.value.type, false); + code += GenTypeBasic(field.value.type, false); } code += " val) const { return " + field.name + "() < val ? -1 : "; code += field.name + "() > val; }\n"; @@ -452,7 +458,7 @@ static void GenTable(const Parser &parser, StructDef &struct_def, code += "Offset"; } code += "(" + struct_def.name + "::" + GenFieldOffsetName(field) + ", "; - code += GenUnderlyingCast(parser, field, false, field.name); + code += GenUnderlyingCast(field, false, field.name); if (IsScalar(field.value.type.base_type)) code += ", " + field.value.constant; code += "); }\n"; @@ -495,12 +501,11 @@ static void GenTable(const Parser &parser, StructDef &struct_def, auto ev = field.value.type.enum_def->ReverseLookup( static_cast(StringToInt(field.value.constant.c_str())), false); if (ev) { - code += WrapInNameSpace(parser, - field.value.type.enum_def->defined_namespace, + code += WrapInNameSpace(field.value.type.enum_def->defined_namespace, GetEnumVal(*field.value.type.enum_def, *ev, parser.opts)); } else { - code += GenUnderlyingCast(parser, field, true, field.value.constant); + code += GenUnderlyingCast(field, true, field.value.constant); } } else if (field.value.type.base_type == BASE_TYPE_BOOL) { code += field.value.constant == "0" ? "false" : "true"; @@ -527,10 +532,10 @@ static void GenTable(const Parser &parser, StructDef &struct_def, code += " return builder_.Finish();\n}\n\n"; } -static void GenPadding(const FieldDef &field, - std::string &code, - int &padding_id, - const std::function &f) { +static void GenPadding(const FieldDef &field, std::string &code, + int &padding_id, + const std::function &f) { if (field.padding) { for (int i = 0; i < 4; i++) if (static_cast(field.padding) & (1 << i)) @@ -598,7 +603,7 @@ static void GenStruct(const Parser &parser, StructDef &struct_def, code += field.name + "_("; if (IsScalar(field.value.type.base_type)) { code += "flatbuffers::EndianScalar("; - code += GenUnderlyingCast(parser, field, false, "_" + field.name); + code += GenUnderlyingCast(field, false, "_" + field.name); code += "))"; } else { code += "_" + field.name + ")"; @@ -627,7 +632,7 @@ static void GenStruct(const Parser &parser, StructDef &struct_def, code += " " + GenTypeGet(parser, field.value.type, " ", "const ", " &", true); code += field.name + "() const { return "; - code += GenUnderlyingCast(parser, field, true, + code += GenUnderlyingCast(field, true, is_scalar ? "flatbuffers::EndianScalar(" + field.name + "_)" : field.name + "_"); @@ -635,10 +640,10 @@ static void GenStruct(const Parser &parser, StructDef &struct_def, if (parser.opts.mutable_buffer) { if (is_scalar) { code += " void mutate_" + field.name + "("; - code += GenTypeBasic(parser, field.value.type, true); + code += GenTypeBasic(field.value.type, true); code += " _" + field.name + ") { flatbuffers::WriteScalar(&"; code += field.name + "_, "; - code += GenUnderlyingCast(parser, field, false, "_" + field.name); + code += GenUnderlyingCast(field, false, "_" + field.name); code += "); }\n"; } else { code += " "; @@ -652,18 +657,35 @@ static void GenStruct(const Parser &parser, StructDef &struct_def, code += NumToString(struct_def.bytesize) + ");\n\n"; } -void GenerateNestedNameSpaces(Namespace *ns, std::string *code_ptr) { +void GenerateNestedNameSpaces(const Namespace *ns, std::string *code_ptr) { for (auto it = ns->components.begin(); it != ns->components.end(); ++it) { *code_ptr += "namespace " + *it + " {\n"; } } -void CloseNestedNameSpaces(Namespace *ns, std::string *code_ptr) { +void CloseNestedNameSpaces(const Namespace *ns, std::string *code_ptr) { for (auto it = ns->components.rbegin(); it != ns->components.rend(); ++it) { *code_ptr += "} // namespace " + *it + "\n"; } } +void CheckNameSpace(const Definition &def, std::string *code_ptr) { + // Set up the correct namespace. Only open a namespace if + // the existing one is different. + // TODO: this could be done more intelligently, by sorting to + // namespace path and only opening/closing what is necessary, but that's + // quite a bit more complexity. + if (code_generator_cur_name_space != def.defined_namespace) { + if (code_generator_cur_name_space) { + CloseNestedNameSpaces(code_generator_cur_name_space, code_ptr); + if (code_generator_cur_name_space->components.size()) *code_ptr += "\n"; + } + GenerateNestedNameSpaces(def.defined_namespace, code_ptr); + code_generator_cur_name_space = def.defined_namespace; + if (code_generator_cur_name_space->components.size()) *code_ptr += "\n"; + } +} + } // namespace cpp struct IsAlnum { @@ -676,182 +698,178 @@ struct IsAlnum { // and tables) and output them to a single file. std::string GenerateCPP(const Parser &parser, const std::string &file_name) { + // Check if we have any code to generate at all, to avoid an empty header. + for (auto it = parser.enums_.vec.begin(); it != parser.enums_.vec.end(); + ++it) { + if (!(*it)->generated) goto generate_code; + } + for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end(); + ++it) { + if (!(*it)->generated) goto generate_code; + } + // No code to generate, exit: + return std::string(); + + generate_code: + using namespace cpp; - // Generate code for all the enum declarations. - std::string enum_code, enum_code_post; - for (auto it = parser.enums_.vec.begin(); - it != parser.enums_.vec.end(); ++it) { - GenEnum(parser, **it, &enum_code, &enum_code_post); + std::string code; + code = "// automatically generated by the FlatBuffers compiler," + " do not modify\n\n"; + + // Generate include guard. + std::string include_guard_ident = file_name; + // Remove any non-alpha-numeric characters that may appear in a filename. + include_guard_ident.erase( + std::remove_if(include_guard_ident.begin(), + include_guard_ident.end(), + IsAlnum()), + include_guard_ident.end()); + std::string include_guard = "FLATBUFFERS_GENERATED_" + include_guard_ident; + include_guard += "_"; + // For further uniqueness, also add the namespace. + auto name_space = parser.namespaces_.back(); + for (auto it = name_space->components.begin(); + it != name_space->components.end(); ++it) { + include_guard += *it + "_"; } + include_guard += "H_"; + std::transform(include_guard.begin(), include_guard.end(), + include_guard.begin(), ::toupper); + code += "#ifndef " + include_guard + "\n"; + code += "#define " + include_guard + "\n\n"; + + code += "#include \"flatbuffers/flatbuffers.h\"\n\n"; + + if (parser.opts.include_dependence_headers) { + int num_includes = 0; + for (auto it = parser.included_files_.begin(); + it != parser.included_files_.end(); ++it) { + auto basename = flatbuffers::StripPath( + flatbuffers::StripExtension(it->first)); + if (basename != file_name) { + code += "#include \"" + basename + "_generated.h\"\n"; + num_includes++; + } + } + if (num_includes) code += "\n"; + } + + assert(!code_generator_cur_name_space); // Generate forward declarations for all structs/tables, since they may // have circular references. - std::string forward_decl_code_same_namespace; - std::string forward_decl_code_other_namespace; - Namespace *cur_name_space = nullptr; for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end(); ++it) { auto &struct_def = **it; - auto decl = "struct " + struct_def.name + ";\n"; - if (struct_def.defined_namespace == parser.namespaces_.back()) { - forward_decl_code_same_namespace += decl; - } else { - // Wrap this decl in the correct namespace. Only open a namespace if - // the adjacent one is different. - // TODO: this could be done more intelligently, by sorting to - // namespace path and only opening/closing what is necessary, but that's - // quite a bit more complexity. - if (cur_name_space != struct_def.defined_namespace) { - if (cur_name_space) { - CloseNestedNameSpaces(cur_name_space, - &forward_decl_code_other_namespace); - } - GenerateNestedNameSpaces(struct_def.defined_namespace, - &forward_decl_code_other_namespace); - cur_name_space = struct_def.defined_namespace; - } - forward_decl_code_other_namespace += decl; - } + CheckNameSpace(struct_def, &code); + code += "struct " + struct_def.name + ";\n\n"; } - if (cur_name_space) { - CloseNestedNameSpaces(cur_name_space, - &forward_decl_code_other_namespace); + + // Generate code for all the enum declarations. + for (auto it = parser.enums_.vec.begin(); + it != parser.enums_.vec.end(); ++it) { + auto &enum_def = **it; + if (!enum_def.generated) { + CheckNameSpace(**it, &code); + GenEnum(parser, **it, &code); + } } // Generate code for all structs, then all tables. - std::string decl_code; for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end(); ++it) { - if ((**it).fixed) GenStruct(parser, **it, &decl_code); + auto &struct_def = **it; + if (struct_def.fixed && !struct_def.generated) { + CheckNameSpace(struct_def, &code); + GenStruct(parser, struct_def, &code); + } } for (auto it = parser.structs_.vec.begin(); it != parser.structs_.vec.end(); ++it) { - if (!(**it).fixed) GenTable(parser, **it, &decl_code); + auto &struct_def = **it; + if (!struct_def.fixed && !struct_def.generated) { + CheckNameSpace(struct_def, &code); + GenTable(parser, struct_def, &code); + } } - // Only output file-level code if there were any declarations. - if (enum_code.length() || decl_code.length()) { - std::string code; - code = "// automatically generated by the FlatBuffers compiler," - " do not modify\n\n"; - - // Generate include guard. - std::string include_guard_ident = file_name; - // Remove any non-alpha-numeric characters that may appear in a filename. - include_guard_ident.erase( - std::remove_if(include_guard_ident.begin(), - include_guard_ident.end(), - IsAlnum()), - include_guard_ident.end()); - std::string include_guard = "FLATBUFFERS_GENERATED_" + include_guard_ident; - include_guard += "_"; - // For further uniqueness, also add the namespace. - auto name_space = parser.namespaces_.back(); - for (auto it = name_space->components.begin(); - it != name_space->components.end(); ++it) { - include_guard += *it + "_"; + // Generate code for union verifiers. + for (auto it = parser.enums_.vec.begin(); + it != parser.enums_.vec.end(); ++it) { + auto &enum_def = **it; + if (enum_def.is_union && !enum_def.generated) { + CheckNameSpace(enum_def, &code); + GenEnumPost(parser, enum_def, &code); } - include_guard += "H_"; - std::transform(include_guard.begin(), include_guard.end(), - include_guard.begin(), ::toupper); - code += "#ifndef " + include_guard + "\n"; - code += "#define " + include_guard + "\n\n"; - - code += "#include \"flatbuffers/flatbuffers.h\"\n\n"; - - if (parser.opts.include_dependence_headers) { - int num_includes = 0; - for (auto it = parser.included_files_.begin(); - it != parser.included_files_.end(); ++it) { - auto basename = flatbuffers::StripPath( - flatbuffers::StripExtension(it->first)); - if (basename != file_name) { - code += "#include \"" + basename + "_generated.h\"\n"; - num_includes++; - } - } - if (num_includes) code += "\n"; - } - - code += forward_decl_code_other_namespace; - code += "\n"; - - GenerateNestedNameSpaces(name_space, &code); - code += "\n"; - - code += forward_decl_code_same_namespace; - code += "\n"; - - // Output the main declaration code from above. - code += enum_code; - code += decl_code; - code += enum_code_post; - - // Generate convenient global helper functions: - if (parser.root_struct_def_) { - auto &name = parser.root_struct_def_->name; - std::string qualified_name = - parser.namespaces_.back()->GetFullyQualifiedName(name); - std::string cpp_qualified_name = TranslateNameSpace(qualified_name); - - // The root datatype accessor: - code += "inline const " + cpp_qualified_name + " *Get"; - code += name; - code += "(const void *buf) { return flatbuffers::GetRoot<"; - code += cpp_qualified_name + ">(buf); }\n\n"; - if (parser.opts.mutable_buffer) { - code += "inline " + name + " *GetMutable"; - code += name; - code += "(void *buf) { return flatbuffers::GetMutableRoot<"; - code += name + ">(buf); }\n\n"; - } - - // The root verifier: - code += "inline bool Verify"; - code += name; - code += "Buffer(flatbuffers::Verifier &verifier) { " - "return verifier.VerifyBuffer<"; - code += cpp_qualified_name + ">(); }\n\n"; - - if (parser.file_identifier_.length()) { - // Return the identifier - code += "inline const char *" + name; - code += "Identifier() { return \"" + parser.file_identifier_; - code += "\"; }\n\n"; - - // Check if a buffer has the identifier. - code += "inline bool " + name; - code += "BufferHasIdentifier(const void *buf) { return flatbuffers::"; - code += "BufferHasIdentifier(buf, "; - code += name + "Identifier()); }\n\n"; - } - - if (parser.file_extension_.length()) { - // Return the extension - code += "inline const char *" + name; - code += "Extension() { return \"" + parser.file_extension_; - code += "\"; }\n\n"; - } - - // Finish a buffer with a given root object: - code += "inline void Finish" + name; - code += "Buffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<"; - code += cpp_qualified_name + "> root) { fbb.Finish(root"; - if (parser.file_identifier_.length()) - code += ", " + name + "Identifier()"; - code += "); }\n\n"; - } - - CloseNestedNameSpaces(name_space, &code); - - // Close the include guard. - code += "\n#endif // " + include_guard + "\n"; - - return code; } - return std::string(); + // Generate convenient global helper functions: + if (parser.root_struct_def_) { + CheckNameSpace(*parser.root_struct_def_, &code); + auto &name = parser.root_struct_def_->name; + std::string qualified_name = + parser.namespaces_.back()->GetFullyQualifiedName(name); + std::string cpp_qualified_name = TranslateNameSpace(qualified_name); + + // The root datatype accessor: + code += "inline const " + cpp_qualified_name + " *Get"; + code += name; + code += "(const void *buf) { return flatbuffers::GetRoot<"; + code += cpp_qualified_name + ">(buf); }\n\n"; + if (parser.opts.mutable_buffer) { + code += "inline " + name + " *GetMutable"; + code += name; + code += "(void *buf) { return flatbuffers::GetMutableRoot<"; + code += name + ">(buf); }\n\n"; + } + + // The root verifier: + code += "inline bool Verify"; + code += name; + code += "Buffer(flatbuffers::Verifier &verifier) { " + "return verifier.VerifyBuffer<"; + code += cpp_qualified_name + ">(); }\n\n"; + + if (parser.file_identifier_.length()) { + // Return the identifier + code += "inline const char *" + name; + code += "Identifier() { return \"" + parser.file_identifier_; + code += "\"; }\n\n"; + + // Check if a buffer has the identifier. + code += "inline bool " + name; + code += "BufferHasIdentifier(const void *buf) { return flatbuffers::"; + code += "BufferHasIdentifier(buf, "; + code += name + "Identifier()); }\n\n"; + } + + if (parser.file_extension_.length()) { + // Return the extension + code += "inline const char *" + name; + code += "Extension() { return \"" + parser.file_extension_; + code += "\"; }\n\n"; + } + + // Finish a buffer with a given root object: + code += "inline void Finish" + name; + code += "Buffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<"; + code += cpp_qualified_name + "> root) { fbb.Finish(root"; + if (parser.file_identifier_.length()) + code += ", " + name + "Identifier()"; + code += "); }\n\n"; + } + + assert(code_generator_cur_name_space); + CloseNestedNameSpaces(code_generator_cur_name_space, &code); + + code_generator_cur_name_space = nullptr; + + // Close the include guard. + code += "\n#endif // " + include_guard + "\n"; + + return code; } static std::string GeneratedFileName(const std::string &path, diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index 622a1f61b..adbd79edc 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -981,15 +981,26 @@ CheckedError Parser::ParseSingleValue(Value &e) { StructDef *Parser::LookupCreateStruct(const std::string &name, bool create_if_new, bool definition) { std::string qualified_name = namespaces_.back()->GetFullyQualifiedName(name); + // See if it exists pre-declared by an unqualified use. auto struct_def = structs_.Lookup(name); if (struct_def && struct_def->predecl) { if (definition) { + // Make sure it has the current namespace, and is registered under its + // qualified name. struct_def->defined_namespace = namespaces_.back(); structs_.Move(name, qualified_name); } return struct_def; } + // See if it exists pre-declared by an qualified use. struct_def = structs_.Lookup(qualified_name); + if (struct_def && struct_def->predecl) { + if (definition) { + // Make sure it has the current namespace. + struct_def->defined_namespace = namespaces_.back(); + } + return struct_def; + } if (!definition) { // Search thru parent namespaces. for (size_t components = namespaces_.back()->components.size(); diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index a42fa4be5..a7f02ffe7 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -7,7 +7,9 @@ namespace MyGame { namespace OtherNameSpace { + struct Unused; + } // namespace OtherNameSpace } // namespace MyGame @@ -15,9 +17,13 @@ namespace MyGame { namespace Example { struct Test; + struct TestSimpleTableWithEnum; + struct Vec3; + struct Stat; + struct Monster; enum Color { diff --git a/tests/namespace_test/NamespaceA/SecondTableInA.cs b/tests/namespace_test/NamespaceA/SecondTableInA.cs new file mode 100644 index 000000000..11bf90fd7 --- /dev/null +++ b/tests/namespace_test/NamespaceA/SecondTableInA.cs @@ -0,0 +1,33 @@ +// automatically generated, do not modify + +namespace NamespaceA +{ + +using System; +using FlatBuffers; + +public sealed class SecondTableInA : Table { + public static SecondTableInA GetRootAsSecondTableInA(ByteBuffer _bb) { return GetRootAsSecondTableInA(_bb, new SecondTableInA()); } + public static SecondTableInA GetRootAsSecondTableInA(ByteBuffer _bb, SecondTableInA obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public SecondTableInA __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + public NamespaceC.TableInC ReferToC { get { return GetReferToC(new NamespaceC.TableInC()); } } + public NamespaceC.TableInC GetReferToC(NamespaceC.TableInC obj) { int o = __offset(4); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; } + + public static Offset CreateSecondTableInA(FlatBufferBuilder builder, + Offset refer_to_cOffset = default(Offset)) { + builder.StartObject(1); + SecondTableInA.AddReferToC(builder, refer_to_cOffset); + return SecondTableInA.EndSecondTableInA(builder); + } + + public static void StartSecondTableInA(FlatBufferBuilder builder) { builder.StartObject(1); } + public static void AddReferToC(FlatBufferBuilder builder, Offset referToCOffset) { builder.AddOffset(0, referToCOffset.Value, 0); } + public static Offset EndSecondTableInA(FlatBufferBuilder builder) { + int o = builder.EndObject(); + return new Offset(o); + } +}; + + +} diff --git a/tests/namespace_test/NamespaceA/SecondTableInA.go b/tests/namespace_test/NamespaceA/SecondTableInA.go new file mode 100644 index 000000000..78514388a --- /dev/null +++ b/tests/namespace_test/NamespaceA/SecondTableInA.go @@ -0,0 +1,32 @@ +// automatically generated, do not modify + +package NamespaceA + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) +type SecondTableInA struct { + _tab flatbuffers.Table +} + +func (rcv *SecondTableInA) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *SecondTableInA) ReferToC(obj *TableInC) *TableInC { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(TableInC) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +func SecondTableInAStart(builder *flatbuffers.Builder) { builder.StartObject(1) } +func SecondTableInAAddReferToC(builder *flatbuffers.Builder, referToC flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(referToC), 0) } +func SecondTableInAEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { return builder.EndObject() } diff --git a/tests/namespace_test/NamespaceA/SecondTableInA.java b/tests/namespace_test/NamespaceA/SecondTableInA.java new file mode 100644 index 000000000..b1fa7a7e0 --- /dev/null +++ b/tests/namespace_test/NamespaceA/SecondTableInA.java @@ -0,0 +1,33 @@ +// automatically generated, do not modify + +package NamespaceA; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +public final class SecondTableInA extends Table { + public static SecondTableInA getRootAsSecondTableInA(ByteBuffer _bb) { return getRootAsSecondTableInA(_bb, new SecondTableInA()); } + public static SecondTableInA getRootAsSecondTableInA(ByteBuffer _bb, SecondTableInA obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public SecondTableInA __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + public NamespaceC.TableInC referToC() { return referToC(new NamespaceC.TableInC()); } + public NamespaceC.TableInC referToC(NamespaceC.TableInC obj) { int o = __offset(4); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; } + + public static int createSecondTableInA(FlatBufferBuilder builder, + int refer_to_cOffset) { + builder.startObject(1); + SecondTableInA.addReferToC(builder, refer_to_cOffset); + return SecondTableInA.endSecondTableInA(builder); + } + + public static void startSecondTableInA(FlatBufferBuilder builder) { builder.startObject(1); } + public static void addReferToC(FlatBufferBuilder builder, int referToCOffset) { builder.addOffset(0, referToCOffset, 0); } + public static int endSecondTableInA(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +}; + diff --git a/tests/namespace_test/NamespaceA/SecondTableInA.php b/tests/namespace_test/NamespaceA/SecondTableInA.php new file mode 100644 index 000000000..78dc27f53 --- /dev/null +++ b/tests/namespace_test/NamespaceA/SecondTableInA.php @@ -0,0 +1,82 @@ +init($bb->getInt($bb->getPosition()) + $bb->getPosition(), $bb)); + } + + /** + * @param int $_i offset + * @param ByteBuffer $_bb + * @return SecondTableInA + **/ + public function init($_i, ByteBuffer $_bb) + { + $this->bb_pos = $_i; + $this->bb = $_bb; + return $this; + } + + public function getReferToC() + { + $obj = new TableInC(); + $o = $this->__offset(4); + return $o != 0 ? $obj->init($this->__indirect($o + $this->bb_pos), $this->bb) : 0; + } + + /** + * @param FlatBufferBuilder $builder + * @return void + */ + public static function startSecondTableInA(FlatBufferBuilder $builder) + { + $builder->StartObject(1); + } + + /** + * @param FlatBufferBuilder $builder + * @return SecondTableInA + */ + public static function createSecondTableInA(FlatBufferBuilder $builder, $refer_to_c) + { + $builder->startObject(1); + self::addReferToC($builder, $refer_to_c); + $o = $builder->endObject(); + return $o; + } + + /** + * @param FlatBufferBuilder $builder + * @param int + * @return void + */ + public static function addReferToC(FlatBufferBuilder $builder, $referToC) + { + $builder->addOffsetX(0, $referToC, 0); + } + + /** + * @param FlatBufferBuilder $builder + * @return int table offset + */ + public static function endSecondTableInA(FlatBufferBuilder $builder) + { + $o = $builder->endObject(); + return $o; + } +} diff --git a/tests/namespace_test/NamespaceA/SecondTableInA.py b/tests/namespace_test/NamespaceA/SecondTableInA.py new file mode 100644 index 000000000..f70153947 --- /dev/null +++ b/tests/namespace_test/NamespaceA/SecondTableInA.py @@ -0,0 +1,27 @@ +# automatically generated, do not modify + +# namespace: NamespaceA + +import flatbuffers + +class SecondTableInA(object): + __slots__ = ['_tab'] + + # SecondTableInA + def Init(self, buf, pos): + self._tab = flatbuffers.table.Table(buf, pos) + + # SecondTableInA + def ReferToC(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4)) + if o != 0: + x = self._tab.Indirect(o + self._tab.Pos) + from .TableInC import TableInC + obj = TableInC() + obj.Init(self._tab.Bytes, x) + return obj + return None + +def SecondTableInAStart(builder): builder.StartObject(1) +def SecondTableInAAddReferToC(builder, referToC): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(referToC), 0) +def SecondTableInAEnd(builder): return builder.EndObject() diff --git a/tests/namespace_test/NamespaceA/TableInC.cs b/tests/namespace_test/NamespaceA/TableInC.cs new file mode 100644 index 000000000..19576df11 --- /dev/null +++ b/tests/namespace_test/NamespaceA/TableInC.cs @@ -0,0 +1,38 @@ +// automatically generated, do not modify + +namespace NamespaceA +{ + +using System; +using FlatBuffers; + +public sealed class TableInC : Table { + public static TableInC GetRootAsTableInC(ByteBuffer _bb) { return GetRootAsTableInC(_bb, new TableInC()); } + public static TableInC GetRootAsTableInC(ByteBuffer _bb, TableInC obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); } + public TableInC __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + public NamespaceA.TableInFirstNS ReferToA1 { get { return GetReferToA1(new NamespaceA.TableInFirstNS()); } } + public NamespaceA.TableInFirstNS GetReferToA1(NamespaceA.TableInFirstNS obj) { int o = __offset(4); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; } + public SecondTableInA ReferToA2 { get { return GetReferToA2(new SecondTableInA()); } } + public SecondTableInA GetReferToA2(SecondTableInA obj) { int o = __offset(6); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; } + + public static Offset CreateTableInC(FlatBufferBuilder builder, + Offset refer_to_a1Offset = default(Offset), + Offset refer_to_a2Offset = default(Offset)) { + builder.StartObject(2); + TableInC.AddReferToA2(builder, refer_to_a2Offset); + TableInC.AddReferToA1(builder, refer_to_a1Offset); + return TableInC.EndTableInC(builder); + } + + public static void StartTableInC(FlatBufferBuilder builder) { builder.StartObject(2); } + public static void AddReferToA1(FlatBufferBuilder builder, Offset referToA1Offset) { builder.AddOffset(0, referToA1Offset.Value, 0); } + public static void AddReferToA2(FlatBufferBuilder builder, Offset referToA2Offset) { builder.AddOffset(1, referToA2Offset.Value, 0); } + public static Offset EndTableInC(FlatBufferBuilder builder) { + int o = builder.EndObject(); + return new Offset(o); + } +}; + + +} diff --git a/tests/namespace_test/NamespaceA/TableInC.go b/tests/namespace_test/NamespaceA/TableInC.go new file mode 100644 index 000000000..535493f64 --- /dev/null +++ b/tests/namespace_test/NamespaceA/TableInC.go @@ -0,0 +1,46 @@ +// automatically generated, do not modify + +package NamespaceA + +import ( + flatbuffers "github.com/google/flatbuffers/go" +) +type TableInC struct { + _tab flatbuffers.Table +} + +func (rcv *TableInC) Init(buf []byte, i flatbuffers.UOffsetT) { + rcv._tab.Bytes = buf + rcv._tab.Pos = i +} + +func (rcv *TableInC) ReferToA1(obj *TableInFirstNS) *TableInFirstNS { + o := flatbuffers.UOffsetT(rcv._tab.Offset(4)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(TableInFirstNS) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +func (rcv *TableInC) ReferToA2(obj *SecondTableInA) *SecondTableInA { + o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) + if o != 0 { + x := rcv._tab.Indirect(o + rcv._tab.Pos) + if obj == nil { + obj = new(SecondTableInA) + } + obj.Init(rcv._tab.Bytes, x) + return obj + } + return nil +} + +func TableInCStart(builder *flatbuffers.Builder) { builder.StartObject(2) } +func TableInCAddReferToA1(builder *flatbuffers.Builder, referToA1 flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(referToA1), 0) } +func TableInCAddReferToA2(builder *flatbuffers.Builder, referToA2 flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(referToA2), 0) } +func TableInCEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { return builder.EndObject() } diff --git a/tests/namespace_test/NamespaceA/TableInC.java b/tests/namespace_test/NamespaceA/TableInC.java new file mode 100644 index 000000000..36e3cf192 --- /dev/null +++ b/tests/namespace_test/NamespaceA/TableInC.java @@ -0,0 +1,38 @@ +// automatically generated, do not modify + +package NamespaceA; + +import java.nio.*; +import java.lang.*; +import java.util.*; +import com.google.flatbuffers.*; + +@SuppressWarnings("unused") +public final class TableInC extends Table { + public static TableInC getRootAsTableInC(ByteBuffer _bb) { return getRootAsTableInC(_bb, new TableInC()); } + public static TableInC getRootAsTableInC(ByteBuffer _bb, TableInC obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); } + public TableInC __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; } + + public NamespaceA.TableInFirstNS referToA1() { return referToA1(new NamespaceA.TableInFirstNS()); } + public NamespaceA.TableInFirstNS referToA1(NamespaceA.TableInFirstNS obj) { int o = __offset(4); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; } + public SecondTableInA referToA2() { return referToA2(new SecondTableInA()); } + public SecondTableInA referToA2(SecondTableInA obj) { int o = __offset(6); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; } + + public static int createTableInC(FlatBufferBuilder builder, + int refer_to_a1Offset, + int refer_to_a2Offset) { + builder.startObject(2); + TableInC.addReferToA2(builder, refer_to_a2Offset); + TableInC.addReferToA1(builder, refer_to_a1Offset); + return TableInC.endTableInC(builder); + } + + public static void startTableInC(FlatBufferBuilder builder) { builder.startObject(2); } + public static void addReferToA1(FlatBufferBuilder builder, int referToA1Offset) { builder.addOffset(0, referToA1Offset, 0); } + public static void addReferToA2(FlatBufferBuilder builder, int referToA2Offset) { builder.addOffset(1, referToA2Offset, 0); } + public static int endTableInC(FlatBufferBuilder builder) { + int o = builder.endObject(); + return o; + } +}; + diff --git a/tests/namespace_test/NamespaceA/TableInC.php b/tests/namespace_test/NamespaceA/TableInC.php new file mode 100644 index 000000000..e02226235 --- /dev/null +++ b/tests/namespace_test/NamespaceA/TableInC.php @@ -0,0 +1,100 @@ +init($bb->getInt($bb->getPosition()) + $bb->getPosition(), $bb)); + } + + /** + * @param int $_i offset + * @param ByteBuffer $_bb + * @return TableInC + **/ + public function init($_i, ByteBuffer $_bb) + { + $this->bb_pos = $_i; + $this->bb = $_bb; + return $this; + } + + public function getReferToA1() + { + $obj = new TableInFirstNS(); + $o = $this->__offset(4); + return $o != 0 ? $obj->init($this->__indirect($o + $this->bb_pos), $this->bb) : 0; + } + + public function getReferToA2() + { + $obj = new SecondTableInA(); + $o = $this->__offset(6); + return $o != 0 ? $obj->init($this->__indirect($o + $this->bb_pos), $this->bb) : 0; + } + + /** + * @param FlatBufferBuilder $builder + * @return void + */ + public static function startTableInC(FlatBufferBuilder $builder) + { + $builder->StartObject(2); + } + + /** + * @param FlatBufferBuilder $builder + * @return TableInC + */ + public static function createTableInC(FlatBufferBuilder $builder, $refer_to_a1, $refer_to_a2) + { + $builder->startObject(2); + self::addReferToA1($builder, $refer_to_a1); + self::addReferToA2($builder, $refer_to_a2); + $o = $builder->endObject(); + return $o; + } + + /** + * @param FlatBufferBuilder $builder + * @param int + * @return void + */ + public static function addReferToA1(FlatBufferBuilder $builder, $referToA1) + { + $builder->addOffsetX(0, $referToA1, 0); + } + + /** + * @param FlatBufferBuilder $builder + * @param int + * @return void + */ + public static function addReferToA2(FlatBufferBuilder $builder, $referToA2) + { + $builder->addOffsetX(1, $referToA2, 0); + } + + /** + * @param FlatBufferBuilder $builder + * @return int table offset + */ + public static function endTableInC(FlatBufferBuilder $builder) + { + $o = $builder->endObject(); + return $o; + } +} diff --git a/tests/namespace_test/NamespaceA/TableInC.py b/tests/namespace_test/NamespaceA/TableInC.py new file mode 100644 index 000000000..bc101a7e3 --- /dev/null +++ b/tests/namespace_test/NamespaceA/TableInC.py @@ -0,0 +1,39 @@ +# automatically generated, do not modify + +# namespace: NamespaceA + +import flatbuffers + +class TableInC(object): + __slots__ = ['_tab'] + + # TableInC + def Init(self, buf, pos): + self._tab = flatbuffers.table.Table(buf, pos) + + # TableInC + def ReferToA1(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(4)) + if o != 0: + x = self._tab.Indirect(o + self._tab.Pos) + from .TableInFirstNS import TableInFirstNS + obj = TableInFirstNS() + obj.Init(self._tab.Bytes, x) + return obj + return None + + # TableInC + def ReferToA2(self): + o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(6)) + if o != 0: + x = self._tab.Indirect(o + self._tab.Pos) + from .SecondTableInA import SecondTableInA + obj = SecondTableInA() + obj.Init(self._tab.Bytes, x) + return obj + return None + +def TableInCStart(builder): builder.StartObject(2) +def TableInCAddReferToA1(builder, referToA1): builder.PrependUOffsetTRelativeSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(referToA1), 0) +def TableInCAddReferToA2(builder, referToA2): builder.PrependUOffsetTRelativeSlot(1, flatbuffers.number_types.UOffsetTFlags.py_type(referToA2), 0) +def TableInCEnd(builder): return builder.EndObject() diff --git a/tests/namespace_test/NamespaceA/TableInFirstNS.cs b/tests/namespace_test/NamespaceA/TableInFirstNS.cs index 21a12cf59..a5f6ee27c 100644 --- a/tests/namespace_test/NamespaceA/TableInFirstNS.cs +++ b/tests/namespace_test/NamespaceA/TableInFirstNS.cs @@ -22,9 +22,9 @@ public sealed class TableInFirstNS : Table { public static void AddFooTable(FlatBufferBuilder builder, Offset fooTableOffset) { builder.AddOffset(0, fooTableOffset.Value, 0); } public static void AddFooEnum(FlatBufferBuilder builder, NamespaceA.NamespaceB.EnumInNestedNS fooEnum) { builder.AddSbyte(1, (sbyte)fooEnum, 0); } public static void AddFooStruct(FlatBufferBuilder builder, Offset fooStructOffset) { builder.AddStruct(2, fooStructOffset.Value, 0); } - public static Offset EndTableInFirstNS(FlatBufferBuilder builder) { + public static Offset EndTableInFirstNS(FlatBufferBuilder builder) { int o = builder.EndObject(); - return new Offset(o); + return new Offset(o); } }; diff --git a/tests/namespace_test/namespace_test1_generated.h b/tests/namespace_test/namespace_test1_generated.h index 241c2cfe6..9e10eb4c1 100644 --- a/tests/namespace_test/namespace_test1_generated.h +++ b/tests/namespace_test/namespace_test1_generated.h @@ -5,19 +5,19 @@ #include "flatbuffers/flatbuffers.h" - namespace NamespaceA { namespace NamespaceB { struct TableInNestedNS; + struct StructInNestedNS; enum EnumInNestedNS { EnumInNestedNS_A = 0, EnumInNestedNS_B = 1, EnumInNestedNS_C = 2, - EnumInNestedNS_MIN_VAL = EnumInNestedNS_A, - EnumInNestedNS_MAX_VAL = EnumInNestedNS_C + EnumInNestedNS_MIN = EnumInNestedNS_A, + EnumInNestedNS_MAX = EnumInNestedNS_C }; inline const char **EnumNamesEnumInNestedNS() { diff --git a/tests/namespace_test/namespace_test2.fbs b/tests/namespace_test/namespace_test2.fbs index 59b9bb2a1..11d7deadc 100644 --- a/tests/namespace_test/namespace_test2.fbs +++ b/tests/namespace_test/namespace_test2.fbs @@ -8,3 +8,17 @@ table TableInFirstNS foo_enum:NamespaceB.EnumInNestedNS; foo_struct:NamespaceB.StructInNestedNS; } + +// Test switching namespaces inside a file. +namespace NamespaceC; + +table TableInC { + refer_to_a1:NamespaceA.TableInFirstNS; + refer_to_a2:NamespaceA.SecondTableInA; +} + +namespace NamespaceA; + +table SecondTableInA { + refer_to_c:NamespaceC.TableInC; +} diff --git a/tests/namespace_test/namespace_test2_generated.h b/tests/namespace_test/namespace_test2_generated.h index 5075894e1..1831454c2 100644 --- a/tests/namespace_test/namespace_test2_generated.h +++ b/tests/namespace_test/namespace_test2_generated.h @@ -9,8 +9,11 @@ namespace NamespaceA { namespace NamespaceB { + struct TableInNestedNS; + struct StructInNestedNS; + } // namespace NamespaceB } // namespace NamespaceA @@ -18,6 +21,22 @@ namespace NamespaceA { struct TableInFirstNS; +} // namespace NamespaceA + +namespace NamespaceC { + +struct TableInC; + +} // namespace NamespaceC + +namespace NamespaceA { + +struct SecondTableInA; + +} // namespace NamespaceA + +namespace NamespaceA { + struct TableInFirstNS FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { enum { VT_FOO_TABLE = 4, @@ -67,4 +86,86 @@ inline flatbuffers::Offset CreateTableInFirstNS(flatbuffers::Fla } // namespace NamespaceA +namespace NamespaceC { + +struct TableInC FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_REFER_TO_A1 = 4, + VT_REFER_TO_A2 = 6 + }; + const NamespaceA::TableInFirstNS *refer_to_a1() const { return GetPointer(VT_REFER_TO_A1); } + NamespaceA::TableInFirstNS *mutable_refer_to_a1() { return GetPointer(VT_REFER_TO_A1); } + const NamespaceA::SecondTableInA *refer_to_a2() const { return GetPointer(VT_REFER_TO_A2); } + NamespaceA::SecondTableInA *mutable_refer_to_a2() { return GetPointer(VT_REFER_TO_A2); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_REFER_TO_A1) && + verifier.VerifyTable(refer_to_a1()) && + VerifyField(verifier, VT_REFER_TO_A2) && + verifier.VerifyTable(refer_to_a2()) && + verifier.EndTable(); + } +}; + +struct TableInCBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_refer_to_a1(flatbuffers::Offset refer_to_a1) { fbb_.AddOffset(TableInC::VT_REFER_TO_A1, refer_to_a1); } + void add_refer_to_a2(flatbuffers::Offset refer_to_a2) { fbb_.AddOffset(TableInC::VT_REFER_TO_A2, refer_to_a2); } + TableInCBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + TableInCBuilder &operator=(const TableInCBuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 2)); + return o; + } +}; + +inline flatbuffers::Offset CreateTableInC(flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset refer_to_a1 = 0, + flatbuffers::Offset refer_to_a2 = 0) { + TableInCBuilder builder_(_fbb); + builder_.add_refer_to_a2(refer_to_a2); + builder_.add_refer_to_a1(refer_to_a1); + return builder_.Finish(); +} + +} // namespace NamespaceC + +namespace NamespaceA { + +struct SecondTableInA FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + enum { + VT_REFER_TO_C = 4 + }; + const NamespaceC::TableInC *refer_to_c() const { return GetPointer(VT_REFER_TO_C); } + NamespaceC::TableInC *mutable_refer_to_c() { return GetPointer(VT_REFER_TO_C); } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_REFER_TO_C) && + verifier.VerifyTable(refer_to_c()) && + verifier.EndTable(); + } +}; + +struct SecondTableInABuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_refer_to_c(flatbuffers::Offset refer_to_c) { fbb_.AddOffset(SecondTableInA::VT_REFER_TO_C, refer_to_c); } + SecondTableInABuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); } + SecondTableInABuilder &operator=(const SecondTableInABuilder &); + flatbuffers::Offset Finish() { + auto o = flatbuffers::Offset(fbb_.EndTable(start_, 1)); + return o; + } +}; + +inline flatbuffers::Offset CreateSecondTableInA(flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset refer_to_c = 0) { + SecondTableInABuilder builder_(_fbb); + builder_.add_refer_to_c(refer_to_c); + return builder_.Finish(); +} + +} // namespace NamespaceA + #endif // FLATBUFFERS_GENERATED_NAMESPACETEST2_NAMESPACEA_H_ diff --git a/tests/namespace_test/namespace_test2_generated.js b/tests/namespace_test/namespace_test2_generated.js index e99d77573..c1953705e 100644 --- a/tests/namespace_test/namespace_test2_generated.js +++ b/tests/namespace_test/namespace_test2_generated.js @@ -10,6 +10,11 @@ var NamespaceA = NamespaceA || {}; */ NamespaceA.NamespaceB = NamespaceA.NamespaceB || {}; +/** + * @const +*/ +var NamespaceC = NamespaceC || {}; + /** * @constructor */ @@ -111,5 +116,159 @@ NamespaceA.TableInFirstNS.endTableInFirstNS = function(builder) { return offset; }; +/** + * @constructor + */ +NamespaceC.TableInC = function() { + /** + * @type {flatbuffers.ByteBuffer} + */ + this.bb = null; + + /** + * @type {number} + */ + this.bb_pos = 0; +}; + +/** + * @param {number} i + * @param {flatbuffers.ByteBuffer} bb + * @returns {NamespaceC.TableInC} + */ +NamespaceC.TableInC.prototype.__init = function(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; +}; + +/** + * @param {flatbuffers.ByteBuffer} bb + * @param {NamespaceC.TableInC=} obj + * @returns {NamespaceC.TableInC} + */ +NamespaceC.TableInC.getRootAsTableInC = function(bb, obj) { + return (obj || new NamespaceC.TableInC).__init(bb.readInt32(bb.position()) + bb.position(), bb); +}; + +/** + * @param {NamespaceA.TableInFirstNS=} obj + * @returns {NamespaceA.TableInFirstNS} + */ +NamespaceC.TableInC.prototype.referToA1 = function(obj) { + var offset = this.bb.__offset(this.bb_pos, 4); + return offset ? (obj || new NamespaceA.TableInFirstNS).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null; +}; + +/** + * @param {NamespaceA.SecondTableInA=} obj + * @returns {NamespaceA.SecondTableInA} + */ +NamespaceC.TableInC.prototype.referToA2 = function(obj) { + var offset = this.bb.__offset(this.bb_pos, 6); + return offset ? (obj || new NamespaceA.SecondTableInA).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null; +}; + +/** + * @param {flatbuffers.Builder} builder + */ +NamespaceC.TableInC.startTableInC = function(builder) { + builder.startObject(2); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {flatbuffers.Offset} referToA1Offset + */ +NamespaceC.TableInC.addReferToA1 = function(builder, referToA1Offset) { + builder.addFieldOffset(0, referToA1Offset, 0); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {flatbuffers.Offset} referToA2Offset + */ +NamespaceC.TableInC.addReferToA2 = function(builder, referToA2Offset) { + builder.addFieldOffset(1, referToA2Offset, 0); +}; + +/** + * @param {flatbuffers.Builder} builder + * @returns {flatbuffers.Offset} + */ +NamespaceC.TableInC.endTableInC = function(builder) { + var offset = builder.endObject(); + return offset; +}; + +/** + * @constructor + */ +NamespaceA.SecondTableInA = function() { + /** + * @type {flatbuffers.ByteBuffer} + */ + this.bb = null; + + /** + * @type {number} + */ + this.bb_pos = 0; +}; + +/** + * @param {number} i + * @param {flatbuffers.ByteBuffer} bb + * @returns {NamespaceA.SecondTableInA} + */ +NamespaceA.SecondTableInA.prototype.__init = function(i, bb) { + this.bb_pos = i; + this.bb = bb; + return this; +}; + +/** + * @param {flatbuffers.ByteBuffer} bb + * @param {NamespaceA.SecondTableInA=} obj + * @returns {NamespaceA.SecondTableInA} + */ +NamespaceA.SecondTableInA.getRootAsSecondTableInA = function(bb, obj) { + return (obj || new NamespaceA.SecondTableInA).__init(bb.readInt32(bb.position()) + bb.position(), bb); +}; + +/** + * @param {NamespaceC.TableInC=} obj + * @returns {NamespaceC.TableInC} + */ +NamespaceA.SecondTableInA.prototype.referToC = function(obj) { + var offset = this.bb.__offset(this.bb_pos, 4); + return offset ? (obj || new NamespaceC.TableInC).__init(this.bb.__indirect(this.bb_pos + offset), this.bb) : null; +}; + +/** + * @param {flatbuffers.Builder} builder + */ +NamespaceA.SecondTableInA.startSecondTableInA = function(builder) { + builder.startObject(1); +}; + +/** + * @param {flatbuffers.Builder} builder + * @param {flatbuffers.Offset} referToCOffset + */ +NamespaceA.SecondTableInA.addReferToC = function(builder, referToCOffset) { + builder.addFieldOffset(0, referToCOffset, 0); +}; + +/** + * @param {flatbuffers.Builder} builder + * @returns {flatbuffers.Offset} + */ +NamespaceA.SecondTableInA.endSecondTableInA = function(builder) { + var offset = builder.endObject(); + return offset; +}; + // Exports for Node.js and RequireJS this.NamespaceA = NamespaceA; +this.NamespaceC = NamespaceC;