From 5b7f602ea85e1a5ee9f99e4bb00af25803a81b68 Mon Sep 17 00:00:00 2001 From: Romain BOULLARD Date: Fri, 31 Jul 2026 02:43:43 +0200 Subject: [PATCH] bigfoot_ref --- CMakeLists.txt | 3 + docs/source/languages/cpp.md | 70 +++--- include/flatbuffers/base.h | 13 + include/flatbuffers/idl.h | 4 +- src/idl_gen_cpp.cpp | 158 +++++++++++- src/idl_parser.cpp | 96 +++----- tests/bigfoot_ref_test.fbs | 31 +++ tests/bigfoot_ref_test_impl.cpp | 47 ++++ tests/bigfoot_ref_test_impl.h | 55 +++++ tests/native_type_test.fbs | 16 -- tests/native_type_test_generated.h | 374 +++-------------------------- tests/native_type_test_impl.cpp | 28 --- tests/native_type_test_impl.h | 40 --- tests/parser_test.cpp | 12 +- tests/test.cpp | 10 +- 15 files changed, 407 insertions(+), 550 deletions(-) create mode 100644 tests/bigfoot_ref_test.fbs create mode 100644 tests/bigfoot_ref_test_impl.cpp create mode 100644 tests/bigfoot_ref_test_impl.h diff --git a/CMakeLists.txt b/CMakeLists.txt index b0990af60..91e0bdd31 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -243,6 +243,8 @@ set(FlatBuffers_Tests_SRCS tests/cpp_vector_type_test.cpp tests/native_type_test_impl.h tests/native_type_test_impl.cpp + tests/bigfoot_ref_test_impl.h + tests/bigfoot_ref_test_impl.cpp tests/alignment_test.h tests/alignment_test.cpp tests/64bit/offset64_test.h @@ -558,6 +560,7 @@ if(FLATBUFFERS_BUILD_TESTS) compile_schema_for_test(tests/arrays_test.fbs "${FLATC_OPT_SCOPED_ENUMS}") compile_schema_for_test(tests/native_inline_table_test.fbs "${FLATC_OPT_COMP}") compile_schema_for_test(tests/native_type_test.fbs "${FLATC_OPT_COMP}") + compile_schema_for_test(tests/bigfoot_ref_test.fbs "${FLATC_OPT_COMP}") compile_schema_for_test(tests/key_field/key_field_sample.fbs "${FLATC_OPT_COMP}") compile_schema_for_test(tests/64bit/test_64bit.fbs "${FLATC_OPT_COMP};--bfbs-gen-embed") compile_schema_for_test(tests/64bit/evolution/v1.fbs "${FLATC_OPT_COMP}") diff --git a/docs/source/languages/cpp.md b/docs/source/languages/cpp.md index 1a3d9071b..c7ed96a66 100644 --- a/docs/source/languages/cpp.md +++ b/docs/source/languages/cpp.md @@ -242,55 +242,41 @@ provide the following functions to aide in the serialization process: } ``` -- `native_type_template("type")` (on a struct) together with - `native_type_template_arg("type")` (on a field of that struct type): - lets a single struct declaration back a native type that is a C++ - template, instantiated differently per field, instead of requiring one - struct declaration (and `native_type`) per instantiation. - `native_type_template_arg` is angle-bracket-appended to - `native_type_template` to form the field's native type, so - `native_type_template: "Native::Box"` with - `native_type_template_arg: "Native::TypeA"` produces - `Native::Box`. For example: +- `bigfoot_ref_wrapper("type")` (on a struct) together with `bigfoot_ref("type")` + (on a field of that struct type): Bigfoot-specific sugar for a + UUID-addressed reference to another native type. `bigfoot_ref_wrapper` + marks a struct as a reference-wrapper template (e.g. Bigfoot's + `HardReference`/`SoftReference`); `bigfoot_ref` on a field of that type + names the referenced native type, e.g. `bigfoot_ref: "::Bigfoot::AssetA"` + on a `HardReference`-typed field with `bigfoot_ref_wrapper: + "::Bigfoot::HardReference"` produces the field's native type + `::Bigfoot::HardReference<::Bigfoot::AssetA>` (auto-deriving a + `native_type_pack_name` of `HardReferenceAssetA`, same short-name + convention as `native_type_pack_name`). Unlike a hand-written + `native_type`, `bigfoot_ref` also emits, directly into the generated + header: + - a forward declaration of the referenced type (so the referencing + schema's generated header never needs that type's real definition - + only the wrapper template's constructor and a `GetUUID()` accessor + are used, and those don't require the referenced type to be + complete), and + - `inline` `Pack`/`UnPack` definitions for it (so no + hand-written implementation is required anywhere). ```cpp - struct Box (native_type_template: "Native::Box") { - value: int32; + struct HardReference (bigfoot_ref_wrapper: "::Bigfoot::HardReference") { + uuid: UUID; } - table Example { - a: Box (native_inline, native_type_template_arg: "Native::TypeA"); - b: Box (native_inline, native_type_template_arg: "Native::TypeB"); + table AssetB { + ref_a: HardReference (bigfoot_ref: "::Bigfoot::AssetA"); } ``` -is equivalent to writing, on each field itself: - -```cpp - a: Box (native_inline, native_type: "Native::Box", native_type_pack_name: "BoxTypeA"); - b: Box (native_inline, native_type: "Native::Box", native_type_pack_name: "BoxTypeB"); -``` - -`native_type_template_arg` also auto-derives a `native_type_pack_name` of -`` (here, `BoxTypeA`/`BoxTypeB`) so the Pack/UnPack -functions stay unique across instantiations without spelling it out -yourself; an explicit `native_type_pack_name` on the field still overrides -this. More than one template parameter is supported by separating them with -commas: - -```cpp - struct Pair (native_type_template: "Native::Pair") { - value: int32; - } - - table Example2 { - p: Pair (native_inline, native_type_template_arg: "Native::Key, Native::Value"); - } -``` - -which produces `Native::Pair`. -`native_type_template_arg` is only valid on fields whose type is a struct -(or vector of structs) that declares `native_type_template`. + is enough on its own - no forward declaration of `::Bigfoot::AssetA` and + no `flatbuffers::Pack/UnPackHardReferenceAssetA` implementation need to + be written by hand. `bigfoot_ref` is only valid on fields whose type is a + struct (or vector of structs) that declares `bigfoot_ref_wrapper`. - `native_type("type")` (on a table): Tables can also be represented with native types. For example, the following schema: diff --git a/include/flatbuffers/base.h b/include/flatbuffers/base.h index 1d2ab5858..30e164eb5 100644 --- a/include/flatbuffers/base.h +++ b/include/flatbuffers/base.h @@ -142,6 +142,19 @@ #define FLATBUFFERS_VERSION_MAJOR 25 #define FLATBUFFERS_VERSION_MINOR 12 #define FLATBUFFERS_VERSION_REVISION 19 + +// Identifies this header as Bigfoot's fork of flatbuffers, and versions the +// fork's own generated-code-affecting changes independently of the upstream +// FLATBUFFERS_VERSION_* triplet above (which just tracks the upstream +// version this fork is based on, and would still match an unforked, stock +// flatbuffers install of the same version). Generated headers assert on +// this - see GenFlatbuffersVersionCheck() in idl_gen_cpp.cpp - so building +// Bigfoot-generated code against stock flatbuffers, or a differently +// versioned Bigfoot fork, fails to compile immediately instead of silently +// miscompiling. Bump this whenever a change here affects what generated +// code assumes about this header (e.g. adding bigfoot_ref/bigfoot_ref_wrapper). +#define FLATBUFFERS_BIGFOOT_VERSION 1 + #define FLATBUFFERS_STRING_EXPAND(X) #X #define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X) namespace flatbuffers { diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index 181813766..1c30f2741 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -1018,8 +1018,8 @@ class Parser : public ParserState { known_attributes_["native_custom_alloc"] = true; known_attributes_["native_type"] = true; known_attributes_["native_type_pack_name"] = true; - known_attributes_["native_type_template"] = true; - known_attributes_["native_type_template_arg"] = true; + known_attributes_["bigfoot_ref_wrapper"] = true; + known_attributes_["bigfoot_ref"] = true; known_attributes_["native_default"] = true; known_attributes_["flexbuffer"] = true; known_attributes_["private"] = true; diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 8d1b26be8..767f48073 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -257,6 +257,19 @@ class CppGenerator : public BaseGenerator { code_ += " FLATBUFFERS_VERSION_REVISION == " + std::to_string(FLATBUFFERS_VERSION_REVISION) + ","; code_ += " \"Non-compatible flatbuffers version included\");"; + + code_ += "// Ensure the included flatbuffers.h is Bigfoot's fork - stock"; + code_ += "// flatbuffers (or a differently versioned Bigfoot fork) is not compatible."; + code_ += "#ifndef FLATBUFFERS_BIGFOOT_VERSION"; + code_ += + "#error \"This file requires Bigfoot's flatbuffers fork - stock " + "flatbuffers is not compatible\""; + code_ += "#endif"; + code_ += "static_assert(FLATBUFFERS_BIGFOOT_VERSION == " + + std::to_string(FLATBUFFERS_BIGFOOT_VERSION) + ","; + code_ += + " \"Non-compatible Bigfoot flatbuffers fork version " + "included\");"; } void GenIncludeDependencies() { @@ -529,6 +542,8 @@ class CppGenerator : public BaseGenerator { code_ += ""; } + GenerateBigfootRefForwardDecls(); + // Generate preablmle code for mini reflection. if (opts_.mini_reflect != IDLOptions::kNone) { // To break cyclic dependencies, first pre-declare all tables/structs. @@ -758,6 +773,8 @@ class CppGenerator : public BaseGenerator { if (cur_name_space_) SetNameSpace(nullptr); + GenerateBigfootRefImpls(); + // Close the include guard. code_ += "#endif // " + include_guard; @@ -894,9 +911,9 @@ class CppGenerator : public BaseGenerator { // A field's `native_type`/`native_type_pack_name` normally come from the // referenced struct's own declaration. A field can override both (see - // `native_type_template_arg` in idl_parser.cpp, which synthesizes these - // two attributes directly on the field) to instantiate a templated - // native type differently per field. + // `bigfoot_ref` in idl_parser.cpp, which synthesizes these two attributes + // directly on the field) to instantiate a templated native type + // differently per field. static const Value* EffectiveNativeType(const FieldDef& field, const StructDef& struct_def) { if (const auto v = field.attributes.Lookup("native_type")) return v; @@ -4541,6 +4558,141 @@ class CppGenerator : public BaseGenerator { } } + // Split a "::"-qualified C++ name into namespace components + final name. + static std::vector SplitQualifiedName(const std::string& qualified) { + std::vector parts; + size_t start = qualified.compare(0, 2, "::") == 0 ? 2 : 0; + for (;;) { + const auto pos = qualified.find("::", start); + if (pos == std::string::npos) { + parts.push_back(qualified.substr(start)); + break; + } + parts.push_back(qualified.substr(start, pos - start)); + start = pos + 2; + } + return parts; + } + + // Bigfoot: for every field annotated `bigfoot_ref: "::Ns::AssetX"` (see + // idl_parser.cpp), forward-declare AssetX plus prototype the Pack/UnPack + // functions for its reference wrapper. Called early (alongside the + // regular struct/table forward declarations), since these prototypes - + // unlike their definitions in GenerateBigfootRefImpls() - only need + // AssetX and the wrapper struct forward-declared, not complete. + void GenerateBigfootRefForwardDecls() { + std::unordered_set declared_assets; + for (const auto& struct_def : parser_.structs_.vec) { + if (struct_def->generated) continue; + for (const auto& field : struct_def->fields.vec) { + const auto* bigfoot_ref = field->attributes.Lookup("bigfoot_ref"); + if (!bigfoot_ref) continue; + if (!declared_assets.insert(bigfoot_ref->constant).second) continue; + + auto parts = SplitQualifiedName(bigfoot_ref->constant); + const std::string class_name = parts.back(); + parts.pop_back(); + + SetNameSpace(nullptr); + for (const auto& ns_part : parts) code_ += "namespace " + ns_part + " {"; + code_ += "class " + class_name + ";"; + for (auto it = parts.rbegin(); it != parts.rend(); ++it) + code_ += "} // namespace " + *it; + code_ += ""; + } + } + + std::unordered_set declared_pairs; + bool opened_flatbuffers_ns = false; + for (const auto& struct_def : parser_.structs_.vec) { + if (struct_def->generated) continue; + for (const auto& field : struct_def->fields.vec) { + const auto* bigfoot_ref = field->attributes.Lookup("bigfoot_ref"); + if (!bigfoot_ref) continue; + + const auto* pack_name = field->attributes.Lookup("native_type_pack_name"); + if (!declared_pairs.insert(pack_name->constant).second) continue; + + if (!opened_flatbuffers_ns) { + SetNameSpace(nullptr); + code_ += "namespace flatbuffers {"; + opened_flatbuffers_ns = true; + } + + const auto* native_type = field->attributes.Lookup("native_type"); + const std::string flat_wrapper = + WrapInNameSpace(*field->value.type.struct_def); + + code_ += flat_wrapper + " Pack" + pack_name->constant + + "(const " + native_type->constant + "& p_asset);"; + code_ += native_type->constant + " UnPack" + pack_name->constant + + "(const " + flat_wrapper + "& p_asset);"; + } + } + + if (opened_flatbuffers_ns) { + code_ += "} // namespace flatbuffers"; + code_ += ""; + } + } + + // Bigfoot: defines the Pack/UnPack functions prototyped by + // GenerateBigfootRefForwardDecls(). Called late (after every struct/table + // in this file has been fully defined), since a wrapper struct (e.g. + // HardReference/SoftReference) may be defined in this same generated file + // rather than one it includes, and these definitions construct it by + // value - they need it complete, unlike the earlier prototypes. + void GenerateBigfootRefImpls() { + std::unordered_set declared_pairs; + bool opened_flatbuffers_ns = false; + for (const auto& struct_def : parser_.structs_.vec) { + if (struct_def->generated) continue; + for (const auto& field : struct_def->fields.vec) { + const auto* bigfoot_ref = field->attributes.Lookup("bigfoot_ref"); + if (!bigfoot_ref) continue; + + const auto* pack_name = field->attributes.Lookup("native_type_pack_name"); + if (!declared_pairs.insert(pack_name->constant).second) continue; + + if (!opened_flatbuffers_ns) { + SetNameSpace(nullptr); + code_ += "namespace flatbuffers {"; + opened_flatbuffers_ns = true; + } + + const auto* native_type = field->attributes.Lookup("native_type"); + const std::string flat_wrapper = + WrapInNameSpace(*field->value.type.struct_def); + + // A single translation unit can end up including two different + // generated headers that both reference the same asset type (e.g. + // AssetB references AssetA, and some other TU includes both + // AssetA_generated.hpp and AssetB_generated.hpp directly) - each + // would otherwise emit an identical, independent definition of these + // functions. `inline` only allows identical definitions to repeat + // across *different* translation units, not twice within the same + // one, so guard against that with a plain macro guard. + std::string guard_name = pack_name->constant; + std::transform(guard_name.begin(), guard_name.end(), guard_name.begin(), CharToUpper); + const std::string guard = "FLATBUFFERS_BIGFOOT_REF_" + guard_name; + code_ += "#ifndef " + guard; + code_ += "#define " + guard; + code_ += "inline " + flat_wrapper + " Pack" + pack_name->constant + + "(const " + native_type->constant + + "& p_asset) { return {Pack(p_asset.GetUUID())}; }"; + code_ += "inline " + native_type->constant + " UnPack" + + pack_name->constant + "(const " + flat_wrapper + + "& p_asset) { return {UnPack(p_asset.uuid())}; }"; + code_ += "#endif // " + guard; + } + } + + if (opened_flatbuffers_ns) { + code_ += "} // namespace flatbuffers"; + code_ += ""; + } + } + // Set up the correct namespace. Only open a namespace if the existing one is // different (closing/opening only what is necessary). // diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index e5014773e..d60ab586f 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -1286,83 +1286,51 @@ CheckedError Parser::ParseField(StructDef& struct_def) { "'native_inline' can only be defined on structs, vector of structs or " "vector of tables"); - auto native_type_template_arg = - field->attributes.Lookup("native_type_template_arg"); - if (native_type_template_arg) { + // `bigfoot_ref` is Bigfoot's single-purpose replacement for the old, + // general-purpose `native_type_template`/`native_type_template_arg` pair: + // a field typed as a `bigfoot_ref_wrapper`-tagged struct (HardReference or + // SoftReference) and annotated `bigfoot_ref: "::Bigfoot::AssetX"` gets its + // native type instantiated as `<::Bigfoot::AssetX>`, plus (unlike + // the old mechanism) a forward declaration of AssetX and inline Pack/UnPack + // definitions are emitted directly into the generated header - see + // GenerateBigfootRefDecls in idl_gen_cpp.cpp. + auto bigfoot_ref = field->attributes.Lookup("bigfoot_ref"); + if (bigfoot_ref) { if (!IsStruct(field->value.type) && !IsVectorOfStruct(field->value.type)) return Error( - "'native_type_template_arg' can only be defined on struct-typed " - "fields or vectors of structs"); + "'bigfoot_ref' can only be defined on struct-typed fields or " + "vectors of structs"); const auto* target_struct = field->value.type.struct_def; - const auto* native_type_template = - target_struct->attributes.Lookup("native_type_template"); - if (!native_type_template) + const auto* wrapper = target_struct->attributes.Lookup("bigfoot_ref_wrapper"); + if (!wrapper) return Error( - "'native_type_template_arg' requires the field's type ('" + - target_struct->name + - "') to declare a 'native_type_template' attribute"); + "'bigfoot_ref' requires the field's type ('" + target_struct->name + + "') to declare a 'bigfoot_ref_wrapper' attribute"); if (field->attributes.Lookup("native_type")) return Error( - "'native_type_template_arg' cannot be combined with an explicit " - "'native_type' on the same field"); + "'bigfoot_ref' cannot be combined with an explicit 'native_type' " + "on the same field"); - // Split on top-level commas, so multiple template arguments can be - // given (e.g. "::Foo::Key, ::Foo::Value"). Commas nested inside a - // template argument that is itself templated (e.g. - // "std::pair") are not treated as separators. - std::vector args; - { - const auto& s = native_type_template_arg->constant; - int depth = 0; - size_t start = 0; - for (size_t i = 0; i < s.size(); ++i) { - if (s[i] == '<') { - ++depth; - } else if (s[i] == '>') { - --depth; - } else if (s[i] == ',' && depth == 0) { - args.push_back(s.substr(start, i - start)); - start = i + 1; - } - } - args.push_back(s.substr(start)); - for (auto& arg : args) { - const auto b = arg.find_first_not_of(" \t"); - const auto e = arg.find_last_not_of(" \t"); - arg = b == std::string::npos ? "" : arg.substr(b, e - b + 1); - if (arg.empty()) - return Error( - "'native_type_template_arg' contains an empty template " - "argument"); - } - } - - // The native type is `native_type_template`, the bare template name, - // with the arguments appended as a trailing, angle-bracketed template - // argument list, e.g. "Native::Box" + ["Native::TypeA"] -> - // "Native::Box". - std::string native_type_str = native_type_template->constant + "<"; - for (size_t i = 0; i < args.size(); ++i) { - if (i) native_type_str += ", "; - native_type_str += args[i]; - } - native_type_str += ">"; + const auto b = bigfoot_ref->constant.find_first_not_of(" \t"); + const auto e = bigfoot_ref->constant.find_last_not_of(" \t"); + const std::string asset_type = + b == std::string::npos ? "" : bigfoot_ref->constant.substr(b, e - b + 1); + if (asset_type.empty()) + return Error("'bigfoot_ref' cannot be empty"); auto native_type_val = new Value(); - native_type_val->type = native_type_template_arg->type; - native_type_val->constant = native_type_str; + native_type_val->type = bigfoot_ref->type; + native_type_val->constant = wrapper->constant + "<" + asset_type + ">"; field->attributes.Add("native_type", native_type_val); if (!field->attributes.Lookup("native_type_pack_name")) { - std::string pack_name = target_struct->name; - for (const auto& arg : args) { - const auto last_colon = arg.find_last_of(':'); - pack_name += - last_colon == std::string::npos ? arg : arg.substr(last_colon + 1); - } + const auto last_colon = asset_type.find_last_of(':'); + const std::string asset_short_name = + last_colon == std::string::npos ? asset_type + : asset_type.substr(last_colon + 1); auto pack_name_val = new Value(); - pack_name_val->type = native_type_template_arg->type; - pack_name_val->constant = pack_name; + pack_name_val->type = bigfoot_ref->type; + pack_name_val->constant = target_struct->name + asset_short_name; field->attributes.Add("native_type_pack_name", pack_name_val); } } diff --git a/tests/bigfoot_ref_test.fbs b/tests/bigfoot_ref_test.fbs new file mode 100644 index 000000000..0b51b0b11 --- /dev/null +++ b/tests/bigfoot_ref_test.fbs @@ -0,0 +1,31 @@ +native_include "bigfoot_ref_test_impl.h"; + +namespace BigfootRefTestNS; + +// Stands in for Bigfoot's real UUID - a `native_type` struct so RefId has a +// distinct native/flat representation, matching the shape `bigfoot_ref` +// requires of a wrapper's payload field. +struct RefId (native_type: "Native::RefId") { + value: uint64; +} + +// The reference-wrapper template itself. `bigfoot_ref_wrapper` marks Ref as +// instantiable per referenced type via `bigfoot_ref` below. +struct Ref (bigfoot_ref_wrapper: "Native::Ref") { + uuid: RefId; +} + +// RefHolder references two distinct C++ types (Thing, OtherThing) that are +// *never defined anywhere in this test* - only ever forward-declared, by +// flatc itself, directly into the generated header. This is the property +// `bigfoot_ref` exists to provide: a reference field never requires the +// referenced type to be complete. It also references `Thing` twice (once as +// a plain field, once in a vector), exercising the include-guard dedup for +// two fields that resolve to the identical Pack/UnPack pair. +table RefHolder { + ref_a: Ref (native_inline, bigfoot_ref: "Native::Thing"); + ref_a_again: [Ref] (native_inline, bigfoot_ref: "Native::Thing"); + ref_b: Ref (native_inline, bigfoot_ref: "Native::OtherThing"); +} + +root_type RefHolder; diff --git a/tests/bigfoot_ref_test_impl.cpp b/tests/bigfoot_ref_test_impl.cpp new file mode 100644 index 000000000..bcb386bcb --- /dev/null +++ b/tests/bigfoot_ref_test_impl.cpp @@ -0,0 +1,47 @@ +#include "bigfoot_ref_test_impl.h" + +#include "bigfoot_ref_test_generated.h" +#include "test_assert.h" + +namespace flatbuffers { +BigfootRefTestNS::RefId Pack(const Native::RefId& obj) { + return BigfootRefTestNS::RefId(obj.value); +} + +const Native::RefId UnPack(const BigfootRefTestNS::RefId& obj) { + return Native::RefId(obj.value()); +} +} // namespace flatbuffers + +namespace flatbuffers { +namespace tests { + +// Exercises the --bigfoot_ref/--bigfoot_ref_wrapper flatc attributes (see +// tests/bigfoot_ref_test.fbs): a reference field never requires the +// referenced native type to be complete, and the generated header supplies +// its own forward declaration plus inline Pack/UnPack definitions, with no +// hand-written boilerplate anywhere in this file for `Thing`/`OtherThing`. +void BigfootRefTest() { + using BigfootRefTestNS::RefHolder; + using BigfootRefTestNS::RefHolderT; + + RefHolderT src; + src.ref_a = Native::Ref(Native::RefId(1)); + src.ref_a_again.push_back(Native::Ref(Native::RefId(2))); + src.ref_a_again.push_back(Native::Ref(Native::RefId(3))); + src.ref_b = Native::Ref(Native::RefId(4)); + + flatbuffers::FlatBufferBuilder fbb; + fbb.Finish(RefHolder::Pack(fbb, &src)); + + auto dst = BigfootRefTestNS::UnPackRefHolder(fbb.GetBufferPointer()); + + TEST_EQ(dst->ref_a.uuid.value, 1u); + TEST_EQ(dst->ref_a_again.size(), 2u); + TEST_EQ(dst->ref_a_again[0].uuid.value, 2u); + TEST_EQ(dst->ref_a_again[1].uuid.value, 3u); + TEST_EQ(dst->ref_b.uuid.value, 4u); +} + +} // namespace tests +} // namespace flatbuffers diff --git a/tests/bigfoot_ref_test_impl.h b/tests/bigfoot_ref_test_impl.h new file mode 100644 index 000000000..10d458745 --- /dev/null +++ b/tests/bigfoot_ref_test_impl.h @@ -0,0 +1,55 @@ +#ifndef BIGFOOT_REF_TEST_IMPL_H +#define BIGFOOT_REF_TEST_IMPL_H + +#include + +namespace Native { +// Stands in for Bigfoot's real UUID. +struct RefId { + uint64_t value; + + RefId() : value(0) {} + explicit RefId(uint64_t _value) : value(_value) {} + + bool operator==(const RefId& other) const { return value == other.value; } +}; + +// `Thing`/`OtherThing` are intentionally *never* defined anywhere in this +// test (see bigfoot_ref_test.fbs) - Ref must compile and round-trip +// without T ever being a complete type, exactly like Bigfoot's +// HardReference/SoftReference. Their forward declarations are emitted +// automatically by flatc (GenerateBigfootRefForwardDecls in +// idl_gen_cpp.cpp) directly into bigfoot_ref_test_generated.h - no manual +// forward declaration belongs here. + +// The reference-wrapper template `bigfoot_ref_wrapper`/`bigfoot_ref` (see +// idl_parser.cpp/idl_gen_cpp.cpp) instantiate per referenced type. Only +// needs a `GetUUID()` accessor and a constructor from RefId - never needs T +// complete. +template +struct Ref { + RefId uuid; + + Ref() : uuid() {} + Ref(const RefId& _uuid) : uuid(_uuid) {} + + const RefId& GetUUID() const { return uuid; } + + bool operator==(const Ref& other) const { return uuid == other.uuid; } +}; +} // namespace Native + +namespace BigfootRefTestNS { +struct RefId; +} // namespace BigfootRefTestNS + +namespace flatbuffers { +BigfootRefTestNS::RefId Pack(const Native::RefId& obj); +const Native::RefId UnPack(const BigfootRefTestNS::RefId& obj); + +namespace tests { +void BigfootRefTest(); +} // namespace tests +} // namespace flatbuffers + +#endif // BIGFOOT_REF_TEST_IMPL_H diff --git a/tests/native_type_test.fbs b/tests/native_type_test.fbs index 5699240c1..1e73d3330 100644 --- a/tests/native_type_test.fbs +++ b/tests/native_type_test.fbs @@ -20,19 +20,6 @@ table Matrix (native_type:"Native::Matrix") { values:[float]; } -// A struct whose native type is a template, instantiated differently per -// field via `native_type_template_arg` instead of needing one flatbuffers -// struct declaration per specialization (compare to Vector3D/Vector3DAlt -// above). -struct Tagged (native_type_template: "Native::Tagged") { - value:int32; -} - -// A native type template that takes more than one argument. -struct Pair (native_type_template: "Native::Pair") { - value:int32; -} - table ApplicationData { vectors:[Vector3D]; vectors_alt:[Vector3DAlt]; @@ -40,9 +27,6 @@ table ApplicationData { position_inline:Vector3D (native_inline); matrix:Matrix; matrices:[Matrix]; - tagged_a:Tagged (native_inline, native_type_template_arg: "Native::TagA"); - tagged_b:Tagged (native_inline, native_type_template_arg: "Native::TagB"); - pair_ab:Pair (native_inline, native_type_template_arg: "Native::TagA, Native::TagB"); } root_type ApplicationData; diff --git a/tests/native_type_test_generated.h b/tests/native_type_test_generated.h index cfdccb89f..c610af251 100644 --- a/tests/native_type_test_generated.h +++ b/tests/native_type_test_generated.h @@ -24,33 +24,13 @@ struct Vector3DAlt; struct Matrix; struct MatrixBuilder; -struct Tagged; - -struct Pair; - struct ApplicationData; struct ApplicationDataBuilder; struct ApplicationDataT; -bool operator==(const Tagged &lhs, const Tagged &rhs); -bool operator!=(const Tagged &lhs, const Tagged &rhs); -bool operator==(const Pair &lhs, const Pair &rhs); -bool operator!=(const Pair &lhs, const Pair &rhs); bool operator==(const ApplicationDataT &lhs, const ApplicationDataT &rhs); bool operator!=(const ApplicationDataT &lhs, const ApplicationDataT &rhs); -inline const ::flatbuffers::TypeTable *Vector3DTypeTable(); - -inline const ::flatbuffers::TypeTable *Vector3DAltTypeTable(); - -inline const ::flatbuffers::TypeTable *MatrixTypeTable(); - -inline const ::flatbuffers::TypeTable *TaggedTypeTable(); - -inline const ::flatbuffers::TypeTable *PairTypeTable(); - -inline const ::flatbuffers::TypeTable *ApplicationDataTypeTable(); - FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3D FLATBUFFERS_FINAL_CLASS { private: float x_; @@ -58,9 +38,7 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3D FLATBUFFERS_FINAL_CLASS { float z_; public: - static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { - return Vector3DTypeTable(); - } + struct Traits; Vector3D() : x_(0), y_(0), @@ -74,24 +52,19 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3D FLATBUFFERS_FINAL_CLASS { float x() const { return ::flatbuffers::EndianScalar(x_); } - void mutate_x(float _x) { - ::flatbuffers::WriteScalar(&x_, _x); - } float y() const { return ::flatbuffers::EndianScalar(y_); } - void mutate_y(float _y) { - ::flatbuffers::WriteScalar(&y_, _y); - } float z() const { return ::flatbuffers::EndianScalar(z_); } - void mutate_z(float _z) { - ::flatbuffers::WriteScalar(&z_, _z); - } }; FLATBUFFERS_STRUCT_END(Vector3D, 12); +struct Vector3D::Traits { + using type = Vector3D; +}; + FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3DAlt FLATBUFFERS_FINAL_CLASS { private: float a_; @@ -99,9 +72,7 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3DAlt FLATBUFFERS_FINAL_CLASS { float c_; public: - static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { - return Vector3DAltTypeTable(); - } + struct Traits; Vector3DAlt() : a_(0), b_(0), @@ -115,96 +86,23 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3DAlt FLATBUFFERS_FINAL_CLASS { float a() const { return ::flatbuffers::EndianScalar(a_); } - void mutate_a(float _a) { - ::flatbuffers::WriteScalar(&a_, _a); - } float b() const { return ::flatbuffers::EndianScalar(b_); } - void mutate_b(float _b) { - ::flatbuffers::WriteScalar(&b_, _b); - } float c() const { return ::flatbuffers::EndianScalar(c_); } - void mutate_c(float _c) { - ::flatbuffers::WriteScalar(&c_, _c); - } }; FLATBUFFERS_STRUCT_END(Vector3DAlt, 12); -FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Tagged FLATBUFFERS_FINAL_CLASS { - private: - int32_t value_; - - public: - static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { - return TaggedTypeTable(); - } - Tagged() - : value_(0) { - } - Tagged(int32_t _value) - : value_(::flatbuffers::EndianScalar(_value)) { - } - int32_t value() const { - return ::flatbuffers::EndianScalar(value_); - } - void mutate_value(int32_t _value) { - ::flatbuffers::WriteScalar(&value_, _value); - } +struct Vector3DAlt::Traits { + using type = Vector3DAlt; }; -FLATBUFFERS_STRUCT_END(Tagged, 4); - -inline bool operator==(const Tagged &lhs, const Tagged &rhs) { - return - (lhs.value() == rhs.value()); -} - -inline bool operator!=(const Tagged &lhs, const Tagged &rhs) { - return !(lhs == rhs); -} - - -FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Pair FLATBUFFERS_FINAL_CLASS { - private: - int32_t value_; - - public: - static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { - return PairTypeTable(); - } - Pair() - : value_(0) { - } - Pair(int32_t _value) - : value_(::flatbuffers::EndianScalar(_value)) { - } - int32_t value() const { - return ::flatbuffers::EndianScalar(value_); - } - void mutate_value(int32_t _value) { - ::flatbuffers::WriteScalar(&value_, _value); - } -}; -FLATBUFFERS_STRUCT_END(Pair, 4); - -inline bool operator==(const Pair &lhs, const Pair &rhs) { - return - (lhs.value() == rhs.value()); -} - -inline bool operator!=(const Pair &lhs, const Pair &rhs) { - return !(lhs == rhs); -} - struct Matrix FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { typedef Native::Matrix NativeTableType; typedef MatrixBuilder Builder; - static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { - return MatrixTypeTable(); - } + struct Traits; enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_ROWS = 4, VT_COLUMNS = 6, @@ -213,21 +111,12 @@ struct Matrix FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { int32_t rows() const { return GetField(VT_ROWS, 0); } - bool mutate_rows(int32_t _rows = 0) { - return SetField(VT_ROWS, _rows, 0); - } int32_t columns() const { return GetField(VT_COLUMNS, 0); } - bool mutate_columns(int32_t _columns = 0) { - return SetField(VT_COLUMNS, _columns, 0); - } const ::flatbuffers::Vector *values() const { return GetPointer *>(VT_VALUES); } - ::flatbuffers::Vector *mutable_values() { - return GetPointer<::flatbuffers::Vector *>(VT_VALUES); - } template bool Verify(::flatbuffers::VerifierTemplate &verifier) const { return VerifyTableStart(verifier) && @@ -278,6 +167,11 @@ inline ::flatbuffers::Offset CreateMatrix( return builder_.Finish(); } +struct Matrix::Traits { + using type = Matrix; + static auto constexpr Create = CreateMatrix; +}; + inline ::flatbuffers::Offset CreateMatrixDirect( ::flatbuffers::FlatBufferBuilder &_fbb, int32_t rows = 0, @@ -301,9 +195,6 @@ struct ApplicationDataT : public ::flatbuffers::NativeTable { Native::Vector3D position_inline{}; std::unique_ptr matrix{}; std::vector> matrices{}; - Native::Tagged tagged_a{}; - Native::Tagged tagged_b{}; - Native::Pair pair_ab{}; ApplicationDataT() = default; ApplicationDataT(const ApplicationDataT &o); ApplicationDataT(ApplicationDataT&&) FLATBUFFERS_NOEXCEPT = default; @@ -313,74 +204,33 @@ struct ApplicationDataT : public ::flatbuffers::NativeTable { struct ApplicationData FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { typedef ApplicationDataT NativeTableType; typedef ApplicationDataBuilder Builder; - static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { - return ApplicationDataTypeTable(); - } + struct Traits; enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_VECTORS = 4, VT_VECTORS_ALT = 6, VT_POSITION = 8, VT_POSITION_INLINE = 10, VT_MATRIX = 12, - VT_MATRICES = 14, - VT_TAGGED_A = 16, - VT_TAGGED_B = 18, - VT_PAIR_AB = 20 + VT_MATRICES = 14 }; const ::flatbuffers::Vector *vectors() const { return GetPointer *>(VT_VECTORS); } - ::flatbuffers::Vector *mutable_vectors() { - return GetPointer<::flatbuffers::Vector *>(VT_VECTORS); - } const ::flatbuffers::Vector *vectors_alt() const { return GetPointer *>(VT_VECTORS_ALT); } - ::flatbuffers::Vector *mutable_vectors_alt() { - return GetPointer<::flatbuffers::Vector *>(VT_VECTORS_ALT); - } const Geometry::Vector3D *position() const { return GetStruct(VT_POSITION); } - Geometry::Vector3D *mutable_position() { - return GetStruct(VT_POSITION); - } const Geometry::Vector3D *position_inline() const { return GetStruct(VT_POSITION_INLINE); } - Geometry::Vector3D *mutable_position_inline() { - return GetStruct(VT_POSITION_INLINE); - } const Geometry::Matrix *matrix() const { return GetPointer(VT_MATRIX); } - Geometry::Matrix *mutable_matrix() { - return GetPointer(VT_MATRIX); - } const ::flatbuffers::Vector<::flatbuffers::Offset> *matrices() const { return GetPointer> *>(VT_MATRICES); } - ::flatbuffers::Vector<::flatbuffers::Offset> *mutable_matrices() { - return GetPointer<::flatbuffers::Vector<::flatbuffers::Offset> *>(VT_MATRICES); - } - const Geometry::Tagged *tagged_a() const { - return GetStruct(VT_TAGGED_A); - } - Geometry::Tagged *mutable_tagged_a() { - return GetStruct(VT_TAGGED_A); - } - const Geometry::Tagged *tagged_b() const { - return GetStruct(VT_TAGGED_B); - } - Geometry::Tagged *mutable_tagged_b() { - return GetStruct(VT_TAGGED_B); - } - const Geometry::Pair *pair_ab() const { - return GetStruct(VT_PAIR_AB); - } - Geometry::Pair *mutable_pair_ab() { - return GetStruct(VT_PAIR_AB); - } template bool Verify(::flatbuffers::VerifierTemplate &verifier) const { return VerifyTableStart(verifier) && @@ -395,9 +245,6 @@ struct ApplicationData FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { VerifyOffset(verifier, VT_MATRICES) && verifier.VerifyVector(matrices()) && verifier.VerifyVectorOfTables(matrices()) && - VerifyField(verifier, VT_TAGGED_A, 4) && - VerifyField(verifier, VT_TAGGED_B, 4) && - VerifyField(verifier, VT_PAIR_AB, 4) && verifier.EndTable(); } ApplicationDataT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; @@ -427,15 +274,6 @@ struct ApplicationDataBuilder { void add_matrices(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> matrices) { fbb_.AddOffset(ApplicationData::VT_MATRICES, matrices); } - void add_tagged_a(const Geometry::Tagged *tagged_a) { - fbb_.AddStruct(ApplicationData::VT_TAGGED_A, tagged_a); - } - void add_tagged_b(const Geometry::Tagged *tagged_b) { - fbb_.AddStruct(ApplicationData::VT_TAGGED_B, tagged_b); - } - void add_pair_ab(const Geometry::Pair *pair_ab) { - fbb_.AddStruct(ApplicationData::VT_PAIR_AB, pair_ab); - } explicit ApplicationDataBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); @@ -454,14 +292,8 @@ inline ::flatbuffers::Offset CreateApplicationData( const Geometry::Vector3D *position = nullptr, const Geometry::Vector3D *position_inline = nullptr, ::flatbuffers::Offset matrix = 0, - ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> matrices = 0, - const Geometry::Tagged *tagged_a = nullptr, - const Geometry::Tagged *tagged_b = nullptr, - const Geometry::Pair *pair_ab = nullptr) { + ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> matrices = 0) { ApplicationDataBuilder builder_(_fbb); - builder_.add_pair_ab(pair_ab); - builder_.add_tagged_b(tagged_b); - builder_.add_tagged_a(tagged_a); builder_.add_matrices(matrices); builder_.add_matrix(matrix); builder_.add_position_inline(position_inline); @@ -471,6 +303,11 @@ inline ::flatbuffers::Offset CreateApplicationData( return builder_.Finish(); } +struct ApplicationData::Traits { + using type = ApplicationData; + static auto constexpr Create = CreateApplicationData; +}; + inline ::flatbuffers::Offset CreateApplicationDataDirect( ::flatbuffers::FlatBufferBuilder &_fbb, const std::vector *vectors = nullptr, @@ -478,10 +315,7 @@ inline ::flatbuffers::Offset CreateApplicationDataDirect( const Geometry::Vector3D *position = nullptr, const Geometry::Vector3D *position_inline = nullptr, ::flatbuffers::Offset matrix = 0, - const std::vector<::flatbuffers::Offset> *matrices = nullptr, - const Geometry::Tagged *tagged_a = nullptr, - const Geometry::Tagged *tagged_b = nullptr, - const Geometry::Pair *pair_ab = nullptr) { + const std::vector<::flatbuffers::Offset> *matrices = nullptr) { auto vectors__ = vectors ? _fbb.CreateVectorOfStructs(*vectors) : 0; auto vectors_alt__ = vectors_alt ? _fbb.CreateVectorOfStructs(*vectors_alt) : 0; auto matrices__ = matrices ? _fbb.CreateVector<::flatbuffers::Offset>(*matrices) : 0; @@ -492,16 +326,13 @@ inline ::flatbuffers::Offset CreateApplicationDataDirect( position, position_inline, matrix, - matrices__, - tagged_a, - tagged_b, - pair_ab); + matrices__); } ::flatbuffers::Offset CreateApplicationData(::flatbuffers::FlatBufferBuilder &_fbb, const ApplicationDataT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); inline Native::Matrix *Matrix::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { - auto _o = std::unique_ptr(new Native::Matrix()); + auto _o = std::make_unique(); UnPackTo(_o.get(), _resolver); return _o.release(); } @@ -518,10 +349,7 @@ inline bool operator==(const ApplicationDataT &lhs, const ApplicationDataT &rhs) ((lhs.position == rhs.position) || (lhs.position && rhs.position && *lhs.position == *rhs.position)) && (lhs.position_inline == rhs.position_inline) && ((lhs.matrix == rhs.matrix) || (lhs.matrix && rhs.matrix && *lhs.matrix == *rhs.matrix)) && - (lhs.matrices.size() == rhs.matrices.size() && std::equal(lhs.matrices.cbegin(), lhs.matrices.cend(), rhs.matrices.cbegin(), [](std::unique_ptr const &a, std::unique_ptr const &b) { return (a == b) || (a && b && *a == *b); })) && - (lhs.tagged_a == rhs.tagged_a) && - (lhs.tagged_b == rhs.tagged_b) && - (lhs.pair_ab == rhs.pair_ab); + (lhs.matrices.size() == rhs.matrices.size() && std::equal(lhs.matrices.cbegin(), lhs.matrices.cend(), rhs.matrices.cbegin(), [](std::unique_ptr const &a, std::unique_ptr const &b) { return (a == b) || (a && b && *a == *b); })); } inline bool operator!=(const ApplicationDataT &lhs, const ApplicationDataT &rhs) { @@ -534,10 +362,7 @@ inline ApplicationDataT::ApplicationDataT(const ApplicationDataT &o) vectors_alt(o.vectors_alt), position((o.position) ? new Native::Vector3D(*o.position) : nullptr), position_inline(o.position_inline), - matrix((o.matrix) ? new Native::Matrix(*o.matrix) : nullptr), - tagged_a(o.tagged_a), - tagged_b(o.tagged_b), - pair_ab(o.pair_ab) { + matrix((o.matrix) ? new Native::Matrix(*o.matrix) : nullptr) { matrices.reserve(o.matrices.size()); for (const auto &matrices_ : o.matrices) { matrices.emplace_back((matrices_) ? new Native::Matrix(*matrices_) : nullptr); } } @@ -549,14 +374,11 @@ inline ApplicationDataT &ApplicationDataT::operator=(ApplicationDataT o) FLATBUF std::swap(position_inline, o.position_inline); std::swap(matrix, o.matrix); std::swap(matrices, o.matrices); - std::swap(tagged_a, o.tagged_a); - std::swap(tagged_b, o.tagged_b); - std::swap(pair_ab, o.pair_ab); return *this; } inline ApplicationDataT *ApplicationData::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const { - auto _o = std::unique_ptr(new ApplicationDataT()); + auto _o = std::make_unique(); UnPackTo(_o.get(), _resolver); return _o.release(); } @@ -570,9 +392,6 @@ inline void ApplicationData::UnPackTo(ApplicationDataT *_o, const ::flatbuffers: { auto _e = position_inline(); if (_e) _o->position_inline = ::flatbuffers::UnPack(*_e); } { auto _e = matrix(); if (_e) { if(_o->matrix) { _e->UnPackTo(_o->matrix.get(), _resolver); } else { _o->matrix = std::unique_ptr(_e->UnPack(_resolver)); } } else if (_o->matrix) { _o->matrix.reset(); } } { auto _e = matrices(); if (_e) { _o->matrices.resize(_e->size()); for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { if(_o->matrices[_i]) { _e->Get(_i)->UnPackTo(_o->matrices[_i].get(), _resolver); } else { _o->matrices[_i] = std::unique_ptr(_e->Get(_i)->UnPack(_resolver)); } } } else { _o->matrices.resize(0); } } - { auto _e = tagged_a(); if (_e) _o->tagged_a = ::flatbuffers::UnPackTaggedTagA(*_e); } - { auto _e = tagged_b(); if (_e) _o->tagged_b = ::flatbuffers::UnPackTaggedTagB(*_e); } - { auto _e = pair_ab(); if (_e) _o->pair_ab = ::flatbuffers::UnPackPairTagATagB(*_e); } } inline ::flatbuffers::Offset CreateApplicationData(::flatbuffers::FlatBufferBuilder &_fbb, const ApplicationDataT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { @@ -589,9 +408,6 @@ inline ::flatbuffers::Offset ApplicationData::Pack(::flatbuffer auto _position_inline = ::flatbuffers::Pack(_o->position_inline); auto _matrix = _o->matrix ? CreateMatrix(_fbb, _o->matrix.get(), _rehasher) : 0; auto _matrices = _o->matrices.size() ? _fbb.CreateVector<::flatbuffers::Offset> (_o->matrices.size(), [](size_t i, _VectorArgs *__va) { return CreateMatrix(*__va->__fbb, __va->__o->matrices[i].get(), __va->__rehasher); }, &_va ) : 0; - auto _tagged_a = ::flatbuffers::PackTaggedTagA(_o->tagged_a); - auto _tagged_b = ::flatbuffers::PackTaggedTagB(_o->tagged_b); - auto _pair_ab = ::flatbuffers::PackPairTagATagB(_o->pair_ab); return Geometry::CreateApplicationData( _fbb, _vectors, @@ -599,127 +415,7 @@ inline ::flatbuffers::Offset ApplicationData::Pack(::flatbuffer _o->position ? &_position : nullptr, &_position_inline, _matrix, - _matrices, - &_tagged_a, - &_tagged_b, - &_pair_ab); -} - -inline const ::flatbuffers::TypeTable *Vector3DTypeTable() { - static const ::flatbuffers::TypeCode type_codes[] = { - { ::flatbuffers::ET_FLOAT, 0, -1 }, - { ::flatbuffers::ET_FLOAT, 0, -1 }, - { ::flatbuffers::ET_FLOAT, 0, -1 } - }; - static const int64_t values[] = { 0, 4, 8, 12 }; - static const char * const names[] = { - "x", - "y", - "z" - }; - static const ::flatbuffers::TypeTable tt = { - ::flatbuffers::ST_STRUCT, 3, type_codes, nullptr, nullptr, values, names - }; - return &tt; -} - -inline const ::flatbuffers::TypeTable *Vector3DAltTypeTable() { - static const ::flatbuffers::TypeCode type_codes[] = { - { ::flatbuffers::ET_FLOAT, 0, -1 }, - { ::flatbuffers::ET_FLOAT, 0, -1 }, - { ::flatbuffers::ET_FLOAT, 0, -1 } - }; - static const int64_t values[] = { 0, 4, 8, 12 }; - static const char * const names[] = { - "a", - "b", - "c" - }; - static const ::flatbuffers::TypeTable tt = { - ::flatbuffers::ST_STRUCT, 3, type_codes, nullptr, nullptr, values, names - }; - return &tt; -} - -inline const ::flatbuffers::TypeTable *MatrixTypeTable() { - static const ::flatbuffers::TypeCode type_codes[] = { - { ::flatbuffers::ET_INT, 0, -1 }, - { ::flatbuffers::ET_INT, 0, -1 }, - { ::flatbuffers::ET_FLOAT, 1, -1 } - }; - static const char * const names[] = { - "rows", - "columns", - "values" - }; - static const ::flatbuffers::TypeTable tt = { - ::flatbuffers::ST_TABLE, 3, type_codes, nullptr, nullptr, nullptr, names - }; - return &tt; -} - -inline const ::flatbuffers::TypeTable *TaggedTypeTable() { - static const ::flatbuffers::TypeCode type_codes[] = { - { ::flatbuffers::ET_INT, 0, -1 } - }; - static const int64_t values[] = { 0, 4 }; - static const char * const names[] = { - "value" - }; - static const ::flatbuffers::TypeTable tt = { - ::flatbuffers::ST_STRUCT, 1, type_codes, nullptr, nullptr, values, names - }; - return &tt; -} - -inline const ::flatbuffers::TypeTable *PairTypeTable() { - static const ::flatbuffers::TypeCode type_codes[] = { - { ::flatbuffers::ET_INT, 0, -1 } - }; - static const int64_t values[] = { 0, 4 }; - static const char * const names[] = { - "value" - }; - static const ::flatbuffers::TypeTable tt = { - ::flatbuffers::ST_STRUCT, 1, type_codes, nullptr, nullptr, values, names - }; - return &tt; -} - -inline const ::flatbuffers::TypeTable *ApplicationDataTypeTable() { - static const ::flatbuffers::TypeCode type_codes[] = { - { ::flatbuffers::ET_SEQUENCE, 1, 0 }, - { ::flatbuffers::ET_SEQUENCE, 1, 1 }, - { ::flatbuffers::ET_SEQUENCE, 0, 0 }, - { ::flatbuffers::ET_SEQUENCE, 0, 0 }, - { ::flatbuffers::ET_SEQUENCE, 0, 2 }, - { ::flatbuffers::ET_SEQUENCE, 1, 2 }, - { ::flatbuffers::ET_SEQUENCE, 0, 3 }, - { ::flatbuffers::ET_SEQUENCE, 0, 3 }, - { ::flatbuffers::ET_SEQUENCE, 0, 4 } - }; - static const ::flatbuffers::TypeFunction type_refs[] = { - Geometry::Vector3DTypeTable, - Geometry::Vector3DAltTypeTable, - Geometry::MatrixTypeTable, - Geometry::TaggedTypeTable, - Geometry::PairTypeTable - }; - static const char * const names[] = { - "vectors", - "vectors_alt", - "position", - "position_inline", - "matrix", - "matrices", - "tagged_a", - "tagged_b", - "pair_ab" - }; - static const ::flatbuffers::TypeTable tt = { - ::flatbuffers::ST_TABLE, 9, type_codes, type_refs, nullptr, nullptr, names - }; - return &tt; + _matrices); } inline const Geometry::ApplicationData *GetApplicationData(const void *buf) { @@ -730,14 +426,6 @@ inline const Geometry::ApplicationData *GetSizePrefixedApplicationData(const voi return ::flatbuffers::GetSizePrefixedRoot(buf); } -inline ApplicationData *GetMutableApplicationData(void *buf) { - return ::flatbuffers::GetMutableRoot(buf); -} - -inline Geometry::ApplicationData *GetMutableSizePrefixedApplicationData(void *buf) { - return ::flatbuffers::GetMutableSizePrefixedRoot(buf); -} - template inline bool VerifyApplicationDataBuffer( ::flatbuffers::VerifierTemplate &verifier) { @@ -750,6 +438,10 @@ inline bool VerifySizePrefixedApplicationDataBuffer( return verifier.template VerifySizePrefixedBuffer(nullptr); } +inline const char *ApplicationDataExtension() { + return "bfbs"; +} + inline void FinishApplicationDataBuffer( ::flatbuffers::FlatBufferBuilder &fbb, ::flatbuffers::Offset root) { diff --git a/tests/native_type_test_impl.cpp b/tests/native_type_test_impl.cpp index c2bb31942..8719c140f 100644 --- a/tests/native_type_test_impl.cpp +++ b/tests/native_type_test_impl.cpp @@ -18,34 +18,6 @@ Geometry::Vector3DAlt PackVector3DAlt(const Native::Vector3D& obj) { const Native::Vector3D UnPackVector3DAlt(const Geometry::Vector3DAlt& obj) { return Native::Vector3D(obj.a(), obj.b(), obj.c()); } - -Geometry::Tagged PackTaggedTagA(const Native::Tagged& obj) { - return Geometry::Tagged(obj.value); -} - -const Native::Tagged UnPackTaggedTagA( - const Geometry::Tagged& obj) { - return Native::Tagged(obj.value()); -} - -Geometry::Tagged PackTaggedTagB(const Native::Tagged& obj) { - return Geometry::Tagged(obj.value); -} - -const Native::Tagged UnPackTaggedTagB( - const Geometry::Tagged& obj) { - return Native::Tagged(obj.value()); -} - -Geometry::Pair PackPairTagATagB( - const Native::Pair& obj) { - return Geometry::Pair(obj.value); -} - -const Native::Pair UnPackPairTagATagB( - const Geometry::Pair& obj) { - return Native::Pair(obj.value()); -} } // namespace flatbuffers namespace Geometry { diff --git a/tests/native_type_test_impl.h b/tests/native_type_test_impl.h index 94c799cec..6a5a7b339 100644 --- a/tests/native_type_test_impl.h +++ b/tests/native_type_test_impl.h @@ -44,41 +44,11 @@ struct Matrix { } }; -// Phantom tag types used purely to select a template specialization; they -// carry no data of their own. -struct TagA {}; -struct TagB {}; - -// A native type template, instantiated per-field in the schema via -// `native_type_template_arg` rather than needing one flatbuffers struct -// declaration per specialization. -template -struct Tagged { - int32_t value; - - Tagged() : value(0) {} - explicit Tagged(int32_t _value) : value(_value) {} - - bool operator==(const Tagged& other) const { return value == other.value; } -}; - -// A native type template taking more than one argument. -template -struct Pair { - int32_t value; - - Pair() : value(0) {} - explicit Pair(int32_t _value) : value(_value) {} - - bool operator==(const Pair& other) const { return value == other.value; } -}; } // namespace Native namespace Geometry { struct Vector3D; struct Vector3DAlt; -struct Tagged; -struct Pair; } // namespace Geometry namespace flatbuffers { @@ -86,16 +56,6 @@ Geometry::Vector3D Pack(const Native::Vector3D& obj); const Native::Vector3D UnPack(const Geometry::Vector3D& obj); Geometry::Vector3DAlt PackVector3DAlt(const Native::Vector3D& obj); const Native::Vector3D UnPackVector3DAlt(const Geometry::Vector3DAlt& obj); - -Geometry::Tagged PackTaggedTagA(const Native::Tagged& obj); -const Native::Tagged UnPackTaggedTagA(const Geometry::Tagged& obj); -Geometry::Tagged PackTaggedTagB(const Native::Tagged& obj); -const Native::Tagged UnPackTaggedTagB(const Geometry::Tagged& obj); - -Geometry::Pair PackPairTagATagB( - const Native::Pair& obj); -const Native::Pair UnPackPairTagATagB( - const Geometry::Pair& obj); } // namespace flatbuffers #endif // VECTOR3D_PACK_H diff --git a/tests/parser_test.cpp b/tests/parser_test.cpp index 905996b41..2ca1873fd 100644 --- a/tests/parser_test.cpp +++ b/tests/parser_test.cpp @@ -98,16 +98,16 @@ void ErrorTest() { TestError("struct X (force_align: 7) { Y:int; }", "force_align"); TestError("struct X {}", "size 0"); TestError( - "struct X { Y:int; } table T { y:X (native_type_template_arg:\"int\"); " + "struct X { Y:int; } table T { y:X (bigfoot_ref:\"::Foo::Bar\"); " "}", - "'native_type_template' attribute"); + "'bigfoot_ref_wrapper' attribute"); TestError( - "table T { y:int (native_type_template_arg:\"int\"); }", + "table T { y:int (bigfoot_ref:\"::Foo::Bar\"); }", "struct-typed fields"); TestError( - "struct X (native_type_template: \"Foo\") { Y:int; } " - "table T { y:X (native_type_template_arg:\"\"); }", - "empty template argument"); + "struct X (bigfoot_ref_wrapper: \"Foo\") { Y:int; } " + "table T { y:X (bigfoot_ref:\"\"); }", + "cannot be empty"); TestError("{}", "no root"); TestError("table X { Y:byte; } root_type X; { Y:1 } { Y:1 }", "end of file"); TestError("table X { Y:byte; } root_type X; { Y:1 } table Y{ Z:int }", diff --git a/tests/test.cpp b/tests/test.cpp index c7fe57d4f..a068c2b2a 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -67,6 +67,7 @@ #include "test_assert.h" #include "util_test.h" #include "cpp_vector_type_test.h" +#include "bigfoot_ref_test_impl.h" #include "vector_table_naked_ptr_test.h" void FlatBufferBuilderTest(); @@ -930,10 +931,6 @@ void NativeTypeTest() { Native::Vector3D(20 * i + 0.1f, 20 * i + 0.2f, 20 * i + 0.3f)); } - src_data.tagged_a = Native::Tagged(7); - src_data.tagged_b = Native::Tagged(8); - src_data.pair_ab = Native::Pair(9); - src_data.matrix = std::unique_ptr(new Native::Matrix(1, 2)); src_data.matrix->values = {3, 4}; @@ -955,10 +952,6 @@ void NativeTypeTest() { TEST_EQ(dstDataT->position_inline.x, 4.0f); TEST_EQ(dstDataT->position_inline.y, 5.0f); TEST_EQ(dstDataT->position_inline.z, 6.0f); - TEST_EQ(dstDataT->tagged_a.value, 7); - TEST_EQ(dstDataT->tagged_b.value, 8); - TEST_EQ(dstDataT->pair_ab.value, 9); - for (int i = 0; i < N; ++i) { const Native::Vector3D& v = dstDataT->vectors[i]; TEST_EQ(v.x, 10 * i + 0.1f); @@ -1823,6 +1816,7 @@ int FlatBufferTests(const std::string& tests_data_path) { InvalidFloatTest(); FixedLengthArrayTest(); NativeTypeTest(); + flatbuffers::tests::BigfootRefTest(); OptionalScalarsTest(); ParseFlexbuffersFromJsonWithNullTest(); FlatbuffersSpanTest();