diff --git a/CMakeLists.txt b/CMakeLists.txt index bee932219b734da512fbf1db4e5b16a30194609c..1ef337295ada3d52f565c79694ab9266948e29ed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,7 +99,10 @@ set(FlatBuffers_GRPCTest_SRCS # source_group(Compiler FILES ${FlatBuffers_Compiler_SRCS}) # source_group(Tests FILES ${FlatBuffers_Tests_SRCS}) -if(APPLE) +if(EXISTS "${CMAKE_TOOLCHAIN_FILE}") + # do not apply any global settings if the toolchain + # is being configured externally +elseif(APPLE) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra") elseif(CMAKE_COMPILER_IS_GNUCXX) diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index 39942e271cd47c67ff95cce986e3b2f32b4bc80d..030f6cad936bd91502c3854329878eaa47390db5 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -255,7 +255,7 @@ struct VectorIterator public: VectorIterator(const uint8_t *data, uoffset_t i) : - data_(data + IndirectHelper<T>::element_stride * i) {}; + data_(data + IndirectHelper<T>::element_stride * i) {} VectorIterator(const VectorIterator &other) : data_(other.data_) {} #ifndef FLATBUFFERS_CPP98_STL VectorIterator(VectorIterator &&other) : data_(std::move(other.data_)) {} diff --git a/net/FlatBuffers/FlatBuffers.csproj b/net/FlatBuffers/FlatBuffers.csproj index 3ae938a156edaf512a1c5eb65f6906ecdac6f252..2a0cf99de9038a86d43df53db276c5930bfa4b91 100644 --- a/net/FlatBuffers/FlatBuffers.csproj +++ b/net/FlatBuffers/FlatBuffers.csproj @@ -37,6 +37,7 @@ <Compile Include="ByteBuffer.cs" /> <Compile Include="FlatBufferBuilder.cs" /> <Compile Include="FlatBufferConstants.cs" /> + <Compile Include="IFlatbufferObject.cs" /> <Compile Include="Offset.cs" /> <Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Struct.cs" /> diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 23bcab7cf1093dbf49035b5655578ea7461cd6e2..ff32c16ef491b57be2dab794bf2a1ad07afbdfe8 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -490,7 +490,24 @@ class CppGenerator : public BaseGenerator { } code += "]; }\n\n"; } - + + // Generate type traits for unions to map from a type to union enum value. + if (enum_def.is_union) { + for (auto it = enum_def.vals.vec.begin(); + it != enum_def.vals.vec.end(); + ++it) { + auto &ev = **it; + if (it == enum_def.vals.vec.begin()) { + code += "template<typename T> struct " + enum_def.name + "Traits {\n"; + } + else { + code += "template<> struct " + enum_def.name + "Traits<" + WrapInNameSpace(*ev.struct_def) + "> {\n"; + } + code += " static const " + enum_def.name + " enum_value = " + GenEnumValDecl(enum_def, ev.name, parser_.opts) + ";\n"; + code += "};\n\n"; + } + } + if (enum_def.is_union) { code += UnionVerifySignature(enum_def) + ";\n\n"; } diff --git a/src/idl_gen_general.cpp b/src/idl_gen_general.cpp index 30899d4d45546726dbcc2e50fdbf5631754899c2..3f72e92fbc91aede8412bad09ab9afe592b0c61d 100644 --- a/src/idl_gen_general.cpp +++ b/src/idl_gen_general.cpp @@ -210,17 +210,21 @@ class GeneralGenerator : public BaseGenerator { GeneralGenerator(const Parser &parser, const std::string &path, const std::string &file_name) : BaseGenerator(parser, path, file_name, "", "."), - lang_(language_parameters[parser_.opts.lang]) { + lang_(language_parameters[parser_.opts.lang]), + cur_name_space_( nullptr ) { assert(parser_.opts.lang <= IDLOptions::kMAX); }; GeneralGenerator &operator=(const GeneralGenerator &); bool generate() { std::string one_file_code; + cur_name_space_ = parser_.namespaces_.back(); for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end(); ++it) { std::string enumcode; auto &enum_def = **it; + if (!parser_.opts.one_file) + cur_name_space_ = enum_def.defined_namespace; GenEnum(enum_def, &enumcode); if (parser_.opts.one_file) { one_file_code += enumcode; @@ -234,6 +238,8 @@ class GeneralGenerator : public BaseGenerator { it != parser_.structs_.vec.end(); ++it) { std::string declcode; auto &struct_def = **it; + if (!parser_.opts.one_file) + cur_name_space_ = struct_def.defined_namespace; GenStruct(struct_def, &declcode); if (parser_.opts.one_file) { one_file_code += declcode; @@ -270,7 +276,7 @@ class GeneralGenerator : public BaseGenerator { return SaveFile(filename.c_str(), code, false); } - const Namespace *CurrentNameSpace() { return parser_.namespaces_.back(); } + const Namespace *CurrentNameSpace() { return cur_name_space_; } std::string FunctionStart(char upper) { return std::string() + (lang_.language == IDLOptions::kJava @@ -1363,6 +1369,8 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) { code += "\n\n"; } const LanguageParameters & lang_; + // This tracks the current namespace used to determine if a type need to be prefixed by its namespace + const Namespace *cur_name_space_; }; } // namespace general diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index c9fa1b0dc987527ab066f6ccf5bca2ea19247e20..4529f6698d7ee5df5bfc890c5012a8496de0d56f 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -1988,7 +1988,8 @@ std::set<std::string> Parser::GetIncludedFilesRecursive( // Schema serialization functionality: template<typename T> bool compareName(const T* a, const T* b) { - return a->name < b->name; + return a->defined_namespace->GetFullyQualifiedName(a->name) + < b->defined_namespace->GetFullyQualifiedName(b->name); } template<typename T> void AssignIndices(const std::vector<T *> &defvec) { @@ -2034,8 +2035,9 @@ Offset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder, (*it)->Serialize(builder, static_cast<uint16_t>(it - fields.vec.begin()), parser)); } + auto qualified_name = defined_namespace->GetFullyQualifiedName(name); return reflection::CreateObject(*builder, - builder->CreateString(name), + builder->CreateString(qualified_name), builder->CreateVectorOfSortedTables( &field_offsets), fixed, @@ -2072,8 +2074,9 @@ Offset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder, for (auto it = vals.vec.begin(); it != vals.vec.end(); ++it) { enumval_offsets.push_back((*it)->Serialize(builder)); } + auto qualified_name = defined_namespace->GetFullyQualifiedName(name); return reflection::CreateEnum(*builder, - builder->CreateString(name), + builder->CreateString(qualified_name), builder->CreateVector(enumval_offsets), is_union, underlying_type.Serialize(builder), diff --git a/tests/MyGame/Example2/Monster.cs b/tests/MyGame/Example2/Monster.cs index 6b1602edb9cc0d4d4711095238f8077a340ae76b..2a0b6de4c16b810b1fb7d6530e650378daeb62f7 100644 --- a/tests/MyGame/Example2/Monster.cs +++ b/tests/MyGame/Example2/Monster.cs @@ -17,9 +17,9 @@ public struct Monster : IFlatbufferObject public static void StartMonster(FlatBufferBuilder builder) { builder.StartObject(0); } - public static Offset<MyGame.Example2.Monster> EndMonster(FlatBufferBuilder builder) { + public static Offset<Monster> EndMonster(FlatBufferBuilder builder) { int o = builder.EndObject(); - return new Offset<MyGame.Example2.Monster>(o); + return new Offset<Monster>(o); } }; diff --git a/tests/monster_test.bfbs b/tests/monster_test.bfbs index e131ac8c2ee97914bfc1c02ce683ac4f5ecb43d6..66d3ee8f215a67b4978d70df9bdb2e6d344e89b8 100644 Binary files a/tests/monster_test.bfbs and b/tests/monster_test.bfbs differ diff --git a/tests/monster_test_generated.h b/tests/monster_test_generated.h index eda76bd0e9e4ad53432ed83d0d47bfcd3f543967..e4ea3f6b22a1b47f67febd79d1addbcc797e49b3 100644 --- a/tests/monster_test_generated.h +++ b/tests/monster_test_generated.h @@ -76,6 +76,22 @@ inline const char **EnumNamesAny() { inline const char *EnumNameAny(Any e) { return EnumNamesAny()[static_cast<int>(e)]; } +template<typename T> struct AnyTraits { + static const Any enum_value = Any_NONE; +}; + +template<> struct AnyTraits<Monster> { + static const Any enum_value = Any_Monster; +}; + +template<> struct AnyTraits<TestSimpleTableWithEnum> { + static const Any enum_value = Any_TestSimpleTableWithEnum; +}; + +template<> struct AnyTraits<MyGame::Example2::Monster> { + static const Any enum_value = Any_MyGame_Example2_Monster; +}; + inline bool VerifyAny(flatbuffers::Verifier &verifier, const void *union_obj, Any type); MANUALLY_ALIGNED_STRUCT(2) Test FLATBUFFERS_FINAL_CLASS { diff --git a/tests/namespace_test/NamespaceA/TableInFirstNS.cs b/tests/namespace_test/NamespaceA/TableInFirstNS.cs index f1c7e96b27fa44295df7b41492ed21f20ddcd4e1..3b5659af4ff99a7eb0c03a829a5e84fc8d4099fb 100644 --- a/tests/namespace_test/NamespaceA/TableInFirstNS.cs +++ b/tests/namespace_test/NamespaceA/TableInFirstNS.cs @@ -24,9 +24,9 @@ public struct TableInFirstNS : IFlatbufferObject public static void AddFooTable(FlatBufferBuilder builder, Offset<NamespaceA.NamespaceB.TableInNestedNS> 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<NamespaceA.NamespaceB.StructInNestedNS> fooStructOffset) { builder.AddStruct(2, fooStructOffset.Value, 0); } - public static Offset<NamespaceA.TableInFirstNS> EndTableInFirstNS(FlatBufferBuilder builder) { + public static Offset<TableInFirstNS> EndTableInFirstNS(FlatBufferBuilder builder) { int o = builder.EndObject(); - return new Offset<NamespaceA.TableInFirstNS>(o); + return new Offset<TableInFirstNS>(o); } }; diff --git a/tests/namespace_test/NamespaceC/TableInC.cs b/tests/namespace_test/NamespaceC/TableInC.cs index 6dddcd4db300638ecdc07ff4218aac694876b640..fa53ec5244a53d0459a97e5ead9518821a5b4ea9 100644 --- a/tests/namespace_test/NamespaceC/TableInC.cs +++ b/tests/namespace_test/NamespaceC/TableInC.cs @@ -16,11 +16,11 @@ public struct TableInC : IFlatbufferObject public TableInC __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; } public NamespaceA.TableInFirstNS? ReferToA1 { get { int o = __p.__offset(4); return o != 0 ? (NamespaceA.TableInFirstNS?)(new NamespaceA.TableInFirstNS()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } - public SecondTableInA? ReferToA2 { get { int o = __p.__offset(6); return o != 0 ? (SecondTableInA?)(new SecondTableInA()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } + public NamespaceA.SecondTableInA? ReferToA2 { get { int o = __p.__offset(6); return o != 0 ? (NamespaceA.SecondTableInA?)(new NamespaceA.SecondTableInA()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } } - public static Offset<NamespaceC.TableInC> CreateTableInC(FlatBufferBuilder builder, + public static Offset<TableInC> CreateTableInC(FlatBufferBuilder builder, Offset<NamespaceA.TableInFirstNS> refer_to_a1Offset = default(Offset<NamespaceA.TableInFirstNS>), - Offset<SecondTableInA> refer_to_a2Offset = default(Offset<SecondTableInA>)) { + Offset<NamespaceA.SecondTableInA> refer_to_a2Offset = default(Offset<NamespaceA.SecondTableInA>)) { builder.StartObject(2); TableInC.AddReferToA2(builder, refer_to_a2Offset); TableInC.AddReferToA1(builder, refer_to_a1Offset); @@ -29,10 +29,10 @@ public struct TableInC : IFlatbufferObject public static void StartTableInC(FlatBufferBuilder builder) { builder.StartObject(2); } public static void AddReferToA1(FlatBufferBuilder builder, Offset<NamespaceA.TableInFirstNS> referToA1Offset) { builder.AddOffset(0, referToA1Offset.Value, 0); } - public static void AddReferToA2(FlatBufferBuilder builder, Offset<SecondTableInA> referToA2Offset) { builder.AddOffset(1, referToA2Offset.Value, 0); } - public static Offset<NamespaceC.TableInC> EndTableInC(FlatBufferBuilder builder) { + public static void AddReferToA2(FlatBufferBuilder builder, Offset<NamespaceA.SecondTableInA> referToA2Offset) { builder.AddOffset(1, referToA2Offset.Value, 0); } + public static Offset<TableInC> EndTableInC(FlatBufferBuilder builder) { int o = builder.EndObject(); - return new Offset<NamespaceC.TableInC>(o); + return new Offset<TableInC>(o); } }; diff --git a/tests/namespace_test/NamespaceC/TableInC.java b/tests/namespace_test/NamespaceC/TableInC.java index 12658ed6dd8934fbbd77aeeffbe876427a40d900..56d495450d3deec7e40e636f0239f04805645a6a 100644 --- a/tests/namespace_test/NamespaceC/TableInC.java +++ b/tests/namespace_test/NamespaceC/TableInC.java @@ -16,8 +16,8 @@ public final class TableInC extends Table { public NamespaceA.TableInFirstNS referToA1() { return referToA1(new NamespaceA.TableInFirstNS()); } public NamespaceA.TableInFirstNS referToA1(NamespaceA.TableInFirstNS obj) { int o = __offset(4); return o != 0 ? obj.__assign(__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.__assign(__indirect(o + bb_pos), bb) : null; } + public NamespaceA.SecondTableInA referToA2() { return referToA2(new NamespaceA.SecondTableInA()); } + public NamespaceA.SecondTableInA referToA2(NamespaceA.SecondTableInA obj) { int o = __offset(6); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; } public static int createTableInC(FlatBufferBuilder builder, int refer_to_a1Offset, diff --git a/tests/test.cpp b/tests/test.cpp index d704fb6254bc0f498d1f8178167dc8ef4ec819f9..d4332afbba21308689d861eb099358a0e550ad9d 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -465,7 +465,7 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) { // Make sure the schema is what we expect it to be. auto &schema = *reflection::GetSchema(bfbsfile.c_str()); auto root_table = schema.root_table(); - TEST_EQ_STR(root_table->name()->c_str(), "Monster"); + TEST_EQ_STR(root_table->name()->c_str(), "MyGame.Example.Monster"); auto fields = root_table->fields(); auto hp_field_ptr = fields->LookupByKey("hp"); TEST_NOTNULL(hp_field_ptr); @@ -478,6 +478,14 @@ void ReflectionTest(uint8_t *flatbuf, size_t length) { TEST_NOTNULL(friendly_field_ptr->attributes()); TEST_NOTNULL(friendly_field_ptr->attributes()->LookupByKey("priority")); + // Make sure the table index is what we expect it to be. + auto pos_field_ptr = fields->LookupByKey("pos"); + TEST_NOTNULL(pos_field_ptr); + TEST_EQ(pos_field_ptr->type()->base_type(), reflection::Obj); + auto pos_table_ptr = schema.objects()->Get(pos_field_ptr->type()->index()); + TEST_NOTNULL(pos_table_ptr); + TEST_EQ_STR(pos_table_ptr->name()->c_str(), "MyGame.Example.Vec3"); + // Now use it to dynamically access a buffer. auto &root = *flatbuffers::GetAnyRoot(flatbuf); auto hp = flatbuffers::GetFieldI<uint16_t>(root, hp_field);