forked from BigfootDev/flatbuffers
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5b7f602ea8 | |||
| a06c41f2c7 | |||
| 4f6ad45b0e | |||
| 81e5f093f9 |
@@ -238,8 +238,13 @@ set(FlatBuffers_Tests_SRCS
|
|||||||
tests/util_test.cpp
|
tests/util_test.cpp
|
||||||
tests/vector_table_naked_ptr_test.h
|
tests/vector_table_naked_ptr_test.h
|
||||||
tests/vector_table_naked_ptr_test.cpp
|
tests/vector_table_naked_ptr_test.cpp
|
||||||
|
tests/test_vector_type.h
|
||||||
|
tests/cpp_vector_type_test.h
|
||||||
|
tests/cpp_vector_type_test.cpp
|
||||||
tests/native_type_test_impl.h
|
tests/native_type_test_impl.h
|
||||||
tests/native_type_test_impl.cpp
|
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.h
|
||||||
tests/alignment_test.cpp
|
tests/alignment_test.cpp
|
||||||
tests/64bit/offset64_test.h
|
tests/64bit/offset64_test.h
|
||||||
@@ -548,17 +553,20 @@ if(FLATBUFFERS_BUILD_TESTS)
|
|||||||
# The flattest target needs some generated files
|
# The flattest target needs some generated files
|
||||||
SET(FLATC_OPT_COMP --cpp --gen-compare --gen-mutable --gen-object-api --reflect-names)
|
SET(FLATC_OPT_COMP --cpp --gen-compare --gen-mutable --gen-object-api --reflect-names)
|
||||||
SET(FLATC_OPT_SCOPED_ENUMS ${FLATC_OPT_COMP};--scoped-enums)
|
SET(FLATC_OPT_SCOPED_ENUMS ${FLATC_OPT_COMP};--scoped-enums)
|
||||||
|
SET(FLATC_OPT_CPP_VECTOR_TYPE ${FLATC_OPT_COMP};--cpp-include;test_vector_type.h;--cpp-vector-type;::flatbuffers::tests::CustomVector)
|
||||||
|
|
||||||
compile_schema_for_test(tests/alignment_test.fbs "${FLATC_OPT_COMP}")
|
compile_schema_for_test(tests/alignment_test.fbs "${FLATC_OPT_COMP}")
|
||||||
compile_schema_for_test_fbsh(tests/default_vectors_strings_test.fbs "${FLATC_OPT_COMP}")
|
compile_schema_for_test_fbsh(tests/default_vectors_strings_test.fbs "${FLATC_OPT_COMP}")
|
||||||
compile_schema_for_test(tests/arrays_test.fbs "${FLATC_OPT_SCOPED_ENUMS}")
|
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_inline_table_test.fbs "${FLATC_OPT_COMP}")
|
||||||
compile_schema_for_test(tests/native_type_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/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/test_64bit.fbs "${FLATC_OPT_COMP};--bfbs-gen-embed")
|
||||||
compile_schema_for_test(tests/64bit/evolution/v1.fbs "${FLATC_OPT_COMP}")
|
compile_schema_for_test(tests/64bit/evolution/v1.fbs "${FLATC_OPT_COMP}")
|
||||||
compile_schema_for_test(tests/64bit/evolution/v2.fbs "${FLATC_OPT_COMP}")
|
compile_schema_for_test(tests/64bit/evolution/v2.fbs "${FLATC_OPT_COMP}")
|
||||||
compile_schema_for_test(tests/union_underlying_type_test.fbs "${FLATC_OPT_SCOPED_ENUMS}")
|
compile_schema_for_test(tests/union_underlying_type_test.fbs "${FLATC_OPT_SCOPED_ENUMS}")
|
||||||
|
compile_schema_for_test(tests/cpp_vector_type.fbs "${FLATC_OPT_CPP_VECTOR_TYPE}")
|
||||||
|
|
||||||
if(FLATBUFFERS_CODE_SANITIZE)
|
if(FLATBUFFERS_CODE_SANITIZE)
|
||||||
add_fsanitize_to_target(flattests ${FLATBUFFERS_CODE_SANITIZE})
|
add_fsanitize_to_target(flattests ${FLATBUFFERS_CODE_SANITIZE})
|
||||||
|
|||||||
@@ -168,6 +168,12 @@ list of `FILES...`.
|
|||||||
std::string from Flatbuffers, but (char* + length). This allows efficient
|
std::string from Flatbuffers, but (char* + length). This allows efficient
|
||||||
construction of custom string types, including zero-copy construction.
|
construction of custom string types, including zero-copy construction.
|
||||||
|
|
||||||
|
- `--cpp-vector-type T` : Set object API vector type (default std::vector).
|
||||||
|
T must be a template taking a single element type argument and support
|
||||||
|
resize(), reserve(), size(), data(), operator[], emplace_back() and
|
||||||
|
begin()/end(), matching the subset of std::vector's interface generated
|
||||||
|
code relies on.
|
||||||
|
|
||||||
- `--no-cpp-direct-copy` : Don't generate direct copy methods for C++
|
- `--no-cpp-direct-copy` : Don't generate direct copy methods for C++
|
||||||
object-based API.
|
object-based API.
|
||||||
|
|
||||||
|
|||||||
@@ -242,6 +242,42 @@ provide the following functions to aide in the serialization process:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- `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<Name>`/`UnPack<Name>` definitions for it (so no
|
||||||
|
hand-written implementation is required anywhere).
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
struct HardReference (bigfoot_ref_wrapper: "::Bigfoot::HardReference") {
|
||||||
|
uuid: UUID;
|
||||||
|
}
|
||||||
|
|
||||||
|
table AssetB {
|
||||||
|
ref_a: HardReference (bigfoot_ref: "::Bigfoot::AssetA");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
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_type("type")` (on a table): Tables can also be represented with
|
||||||
native types. For example, the following schema:
|
native types. For example, the following schema:
|
||||||
|
|
||||||
@@ -337,6 +373,27 @@ constructor in the following format: `custom_str_class(const char *, size_t)`.
|
|||||||
Please note that the character array is not guaranteed to be NULL terminated,
|
Please note that the character array is not guaranteed to be NULL terminated,
|
||||||
you should always use the provided size to determine end of string.
|
you should always use the provided size to determine end of string.
|
||||||
|
|
||||||
|
## Using different vector type
|
||||||
|
|
||||||
|
By default the object tree's vector fields are built out of `std::vector`,
|
||||||
|
but you can influence this either globally (using the `--cpp-vector-type`
|
||||||
|
argument to `flatc`) or per field using the `cpp_vector_type` attribute, to
|
||||||
|
use any other vector-like template type (e.g. `eastl::vector`).
|
||||||
|
|
||||||
|
The type must be a template taking a single element type argument
|
||||||
|
(`my_vector<T>`), and must support the following member functions:
|
||||||
|
`resize()`, `reserve()`, `size()`, `data()`, `operator[]`, `emplace_back()`,
|
||||||
|
and `begin()`/`end()`. This matches the subset of `std::vector`'s interface
|
||||||
|
that generated code relies on.
|
||||||
|
|
||||||
|
Note that unlike `std::vector<bool>`, the custom vector type must not use a
|
||||||
|
bit-packed specialization for `bool` elements, since generated code accesses
|
||||||
|
`data()` as a contiguous `bool` array.
|
||||||
|
|
||||||
|
As with custom string types, the header defining the custom vector type is
|
||||||
|
not automatically included; use `--cpp-include` to add the necessary
|
||||||
|
`#include`.
|
||||||
|
|
||||||
## Reflection (& Resizing)
|
## Reflection (& Resizing)
|
||||||
|
|
||||||
There is experimental support for reflection in FlatBuffers, allowing you to
|
There is experimental support for reflection in FlatBuffers, allowing you to
|
||||||
|
|||||||
@@ -142,6 +142,19 @@
|
|||||||
#define FLATBUFFERS_VERSION_MAJOR 25
|
#define FLATBUFFERS_VERSION_MAJOR 25
|
||||||
#define FLATBUFFERS_VERSION_MINOR 12
|
#define FLATBUFFERS_VERSION_MINOR 12
|
||||||
#define FLATBUFFERS_VERSION_REVISION 19
|
#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_EXPAND(X) #X
|
||||||
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
|
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
|
||||||
namespace flatbuffers {
|
namespace flatbuffers {
|
||||||
|
|||||||
@@ -677,6 +677,7 @@ struct IDLOptions {
|
|||||||
std::string cpp_object_api_pointer_type;
|
std::string cpp_object_api_pointer_type;
|
||||||
std::string cpp_object_api_string_type;
|
std::string cpp_object_api_string_type;
|
||||||
bool cpp_object_api_string_flexible_constructor;
|
bool cpp_object_api_string_flexible_constructor;
|
||||||
|
std::string cpp_object_api_vector_type;
|
||||||
CaseStyle cpp_object_api_field_case_style;
|
CaseStyle cpp_object_api_field_case_style;
|
||||||
bool cpp_direct_copy;
|
bool cpp_direct_copy;
|
||||||
bool gen_nullable;
|
bool gen_nullable;
|
||||||
@@ -1012,10 +1013,13 @@ class Parser : public ParserState {
|
|||||||
known_attributes_["cpp_ptr_type_get"] = true;
|
known_attributes_["cpp_ptr_type_get"] = true;
|
||||||
known_attributes_["cpp_str_type"] = true;
|
known_attributes_["cpp_str_type"] = true;
|
||||||
known_attributes_["cpp_str_flex_ctor"] = true;
|
known_attributes_["cpp_str_flex_ctor"] = true;
|
||||||
|
known_attributes_["cpp_vector_type"] = true;
|
||||||
known_attributes_["native_inline"] = true;
|
known_attributes_["native_inline"] = true;
|
||||||
known_attributes_["native_custom_alloc"] = true;
|
known_attributes_["native_custom_alloc"] = true;
|
||||||
known_attributes_["native_type"] = true;
|
known_attributes_["native_type"] = true;
|
||||||
known_attributes_["native_type_pack_name"] = true;
|
known_attributes_["native_type_pack_name"] = true;
|
||||||
|
known_attributes_["bigfoot_ref_wrapper"] = true;
|
||||||
|
known_attributes_["bigfoot_ref"] = true;
|
||||||
known_attributes_["native_default"] = true;
|
known_attributes_["native_default"] = true;
|
||||||
known_attributes_["flexbuffer"] = true;
|
known_attributes_["flexbuffer"] = true;
|
||||||
known_attributes_["private"] = true;
|
known_attributes_["private"] = true;
|
||||||
|
|||||||
@@ -251,6 +251,21 @@ flatc(
|
|||||||
schema="vector_table_naked_ptr.fbs",
|
schema="vector_table_naked_ptr.fbs",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
flatc(
|
||||||
|
[
|
||||||
|
"--cpp",
|
||||||
|
"--gen-compare",
|
||||||
|
"--gen-mutable",
|
||||||
|
"--gen-object-api",
|
||||||
|
"--reflect-names",
|
||||||
|
"--cpp-include",
|
||||||
|
"test_vector_type.h",
|
||||||
|
"--cpp-vector-type",
|
||||||
|
"::flatbuffers::tests::CustomVector",
|
||||||
|
],
|
||||||
|
schema="cpp_vector_type.fbs",
|
||||||
|
)
|
||||||
|
|
||||||
flatc(
|
flatc(
|
||||||
BASE_OPTS + CPP_OPTS + CS_OPTS + JAVA_OPTS + KOTLIN_OPTS + PHP_OPTS,
|
BASE_OPTS + CPP_OPTS + CS_OPTS + JAVA_OPTS + KOTLIN_OPTS + PHP_OPTS,
|
||||||
prefix="union_vector",
|
prefix="union_vector",
|
||||||
|
|||||||
@@ -145,6 +145,12 @@ const static FlatCOption flatc_options[] = {
|
|||||||
{"", "cpp-str-flex-ctor", "",
|
{"", "cpp-str-flex-ctor", "",
|
||||||
"Don't construct custom string types by passing std::string from "
|
"Don't construct custom string types by passing std::string from "
|
||||||
"Flatbuffers, but (char* + length)."},
|
"Flatbuffers, but (char* + length)."},
|
||||||
|
{"", "cpp-vector-type", "T",
|
||||||
|
"Set object API vector type (default std::vector). T must be a "
|
||||||
|
"template taking a single element type argument and support "
|
||||||
|
"resize(), reserve(), size(), data(), operator[], emplace_back(), and "
|
||||||
|
"begin()/end(). The custom type also needs its own header to be "
|
||||||
|
"included via --cpp-include."},
|
||||||
{"", "cpp-field-case-style", "STYLE",
|
{"", "cpp-field-case-style", "STYLE",
|
||||||
"Generate C++ fields using selected case style. Supported STYLE values: * "
|
"Generate C++ fields using selected case style. Supported STYLE values: * "
|
||||||
"'unchanged' - leave unchanged (default) * 'upper' - schema snake_case "
|
"'unchanged' - leave unchanged (default) * 'upper' - schema snake_case "
|
||||||
@@ -545,6 +551,9 @@ FlatCOptions FlatCompiler::ParseFromCommandLineArguments(int argc,
|
|||||||
opts.cpp_object_api_string_type = argv[argi];
|
opts.cpp_object_api_string_type = argv[argi];
|
||||||
} else if (arg == "--cpp-str-flex-ctor") {
|
} else if (arg == "--cpp-str-flex-ctor") {
|
||||||
opts.cpp_object_api_string_flexible_constructor = true;
|
opts.cpp_object_api_string_flexible_constructor = true;
|
||||||
|
} else if (arg == "--cpp-vector-type") {
|
||||||
|
if (++argi >= argc) Error("missing type following: " + arg, true);
|
||||||
|
opts.cpp_object_api_vector_type = argv[argi];
|
||||||
} else if (arg == "--no-cpp-direct-copy") {
|
} else if (arg == "--no-cpp-direct-copy") {
|
||||||
opts.cpp_direct_copy = false;
|
opts.cpp_direct_copy = false;
|
||||||
} else if (arg == "--cpp-field-case-style") {
|
} else if (arg == "--cpp-field-case-style") {
|
||||||
|
|||||||
+275
-25
@@ -257,6 +257,19 @@ class CppGenerator : public BaseGenerator {
|
|||||||
code_ += " FLATBUFFERS_VERSION_REVISION == " +
|
code_ += " FLATBUFFERS_VERSION_REVISION == " +
|
||||||
std::to_string(FLATBUFFERS_VERSION_REVISION) + ",";
|
std::to_string(FLATBUFFERS_VERSION_REVISION) + ",";
|
||||||
code_ += " \"Non-compatible flatbuffers version included\");";
|
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() {
|
void GenIncludeDependencies() {
|
||||||
@@ -529,6 +542,8 @@ class CppGenerator : public BaseGenerator {
|
|||||||
code_ += "";
|
code_ += "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GenerateBigfootRefForwardDecls();
|
||||||
|
|
||||||
// Generate preablmle code for mini reflection.
|
// Generate preablmle code for mini reflection.
|
||||||
if (opts_.mini_reflect != IDLOptions::kNone) {
|
if (opts_.mini_reflect != IDLOptions::kNone) {
|
||||||
// To break cyclic dependencies, first pre-declare all tables/structs.
|
// To break cyclic dependencies, first pre-declare all tables/structs.
|
||||||
@@ -758,6 +773,8 @@ class CppGenerator : public BaseGenerator {
|
|||||||
|
|
||||||
if (cur_name_space_) SetNameSpace(nullptr);
|
if (cur_name_space_) SetNameSpace(nullptr);
|
||||||
|
|
||||||
|
GenerateBigfootRefImpls();
|
||||||
|
|
||||||
// Close the include guard.
|
// Close the include guard.
|
||||||
code_ += "#endif // " + include_guard;
|
code_ += "#endif // " + include_guard;
|
||||||
|
|
||||||
@@ -892,6 +909,24 @@ class CppGenerator : public BaseGenerator {
|
|||||||
return opts_.gen_nullable ? " _Nullable " : "";
|
return opts_.gen_nullable ? " _Nullable " : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A field's `native_type`/`native_type_pack_name` normally come from the
|
||||||
|
// referenced struct's own declaration. A field can override both (see
|
||||||
|
// `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;
|
||||||
|
return struct_def.attributes.Lookup("native_type");
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Value* EffectiveNativeTypePackName(const FieldDef& field,
|
||||||
|
const StructDef& struct_def) {
|
||||||
|
if (const auto v = field.attributes.Lookup("native_type_pack_name"))
|
||||||
|
return v;
|
||||||
|
return struct_def.attributes.Lookup("native_type_pack_name");
|
||||||
|
}
|
||||||
|
|
||||||
static std::string NativeName(const std::string& name, const StructDef* sd,
|
static std::string NativeName(const std::string& name, const StructDef* sd,
|
||||||
const IDLOptions& opts) {
|
const IDLOptions& opts) {
|
||||||
// If the table is a native_type, return the native_type name.
|
// If the table is a native_type, return the native_type name.
|
||||||
@@ -937,6 +972,23 @@ class CppGenerator : public BaseGenerator {
|
|||||||
"std::string"; // Only for custom string types.
|
"std::string"; // Only for custom string types.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::string NativeVectorType(const FieldDef* field) {
|
||||||
|
auto attr = field ? field->attributes.Lookup("cpp_vector_type") : nullptr;
|
||||||
|
auto& ret = attr ? attr->constant : opts_.cpp_object_api_vector_type;
|
||||||
|
if (ret.empty()) {
|
||||||
|
return "std::vector";
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// True if this field's native vector uses a custom (non-std::vector)
|
||||||
|
// container, meaning generated Pack() code can't rely on the std::vector
|
||||||
|
// specific CreateVector*() overloads and must fall back to data()/size()
|
||||||
|
// or per-element construction instead.
|
||||||
|
bool UsesCustomVectorType(const FieldDef* field) {
|
||||||
|
return NativeVectorType(field) != "std::vector";
|
||||||
|
}
|
||||||
|
|
||||||
std::string GenTypeNativePtr(const std::string& type, const FieldDef* field,
|
std::string GenTypeNativePtr(const std::string& type, const FieldDef* field,
|
||||||
bool is_constructor) {
|
bool is_constructor) {
|
||||||
auto& ptr_type = PtrType(field);
|
auto& ptr_type = PtrType(field);
|
||||||
@@ -974,20 +1026,21 @@ class CppGenerator : public BaseGenerator {
|
|||||||
case BASE_TYPE_VECTOR64:
|
case BASE_TYPE_VECTOR64:
|
||||||
case BASE_TYPE_VECTOR: {
|
case BASE_TYPE_VECTOR: {
|
||||||
const auto type_name = GenTypeNative(type.VectorType(), true, field);
|
const auto type_name = GenTypeNative(type.VectorType(), true, field);
|
||||||
if (type.struct_def &&
|
const auto vector_type = NativeVectorType(&field);
|
||||||
|
if (vector_type == "std::vector" && type.struct_def &&
|
||||||
type.struct_def->attributes.Lookup("native_custom_alloc")) {
|
type.struct_def->attributes.Lookup("native_custom_alloc")) {
|
||||||
auto native_custom_alloc =
|
auto native_custom_alloc =
|
||||||
type.struct_def->attributes.Lookup("native_custom_alloc");
|
type.struct_def->attributes.Lookup("native_custom_alloc");
|
||||||
return "std::vector<" + type_name + "," +
|
return "std::vector<" + type_name + "," +
|
||||||
native_custom_alloc->constant + "<" + type_name + ">>";
|
native_custom_alloc->constant + "<" + type_name + ">>";
|
||||||
} else {
|
} else {
|
||||||
return "std::vector<" + type_name + ">";
|
return vector_type + "<" + type_name + ">";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case BASE_TYPE_STRUCT: {
|
case BASE_TYPE_STRUCT: {
|
||||||
auto type_name = WrapInNameSpace(*type.struct_def);
|
auto type_name = WrapInNameSpace(*type.struct_def);
|
||||||
if (IsStruct(type)) {
|
if (IsStruct(type)) {
|
||||||
auto native_type = type.struct_def->attributes.Lookup("native_type");
|
auto native_type = EffectiveNativeType(field, *type.struct_def);
|
||||||
if (native_type) {
|
if (native_type) {
|
||||||
type_name = native_type->constant;
|
type_name = native_type->constant;
|
||||||
}
|
}
|
||||||
@@ -1979,7 +2032,7 @@ class CppGenerator : public BaseGenerator {
|
|||||||
const std::string& full_type =
|
const std::string& full_type =
|
||||||
(cpp_type
|
(cpp_type
|
||||||
? (IsVector(field.value.type)
|
? (IsVector(field.value.type)
|
||||||
? "std::vector<" +
|
? NativeVectorType(&field) + "<" +
|
||||||
GenTypeNativePtr(cpp_type->constant, &field,
|
GenTypeNativePtr(cpp_type->constant, &field,
|
||||||
false) +
|
false) +
|
||||||
"> "
|
"> "
|
||||||
@@ -3515,11 +3568,11 @@ class CppGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
case BASE_TYPE_STRUCT: {
|
case BASE_TYPE_STRUCT: {
|
||||||
if (IsStruct(type)) {
|
if (IsStruct(type)) {
|
||||||
const auto& struct_attrs = type.struct_def->attributes;
|
const auto native_type = EffectiveNativeType(afield, *type.struct_def);
|
||||||
const auto native_type = struct_attrs.Lookup("native_type");
|
|
||||||
if (native_type) {
|
if (native_type) {
|
||||||
std::string unpack_call = "::flatbuffers::UnPack";
|
std::string unpack_call = "::flatbuffers::UnPack";
|
||||||
const auto pack_name = struct_attrs.Lookup("native_type_pack_name");
|
const auto pack_name =
|
||||||
|
EffectiveNativeTypePackName(afield, *type.struct_def);
|
||||||
if (pack_name) {
|
if (pack_name) {
|
||||||
unpack_call += pack_name->constant;
|
unpack_call += pack_name->constant;
|
||||||
}
|
}
|
||||||
@@ -3772,13 +3825,22 @@ class CppGenerator : public BaseGenerator {
|
|||||||
case BASE_TYPE_VECTOR64:
|
case BASE_TYPE_VECTOR64:
|
||||||
case BASE_TYPE_VECTOR: {
|
case BASE_TYPE_VECTOR: {
|
||||||
auto vector_type = field.value.type.VectorType();
|
auto vector_type = field.value.type.VectorType();
|
||||||
|
// If the field's native container isn't std::vector, the
|
||||||
|
// std::vector-specific CreateVector*() overloads in
|
||||||
|
// flatbuffer_builder.h can't be used directly. Fall back to
|
||||||
|
// data()/size()-based overloads (which only require the container to
|
||||||
|
// support those, like std::vector does) or, where no such overload
|
||||||
|
// exists, to the same per-element lambda serialization already used
|
||||||
|
// above for custom string/table/union element types.
|
||||||
|
const bool custom_vector = UsesCustomVectorType(&field);
|
||||||
switch (vector_type.base_type) {
|
switch (vector_type.base_type) {
|
||||||
case BASE_TYPE_STRING: {
|
case BASE_TYPE_STRING: {
|
||||||
if (NativeString(&field) == "std::string") {
|
if (!custom_vector && NativeString(&field) == "std::string") {
|
||||||
code += "_fbb.CreateVectorOfStrings(" + value + ")";
|
code += "_fbb.CreateVectorOfStrings(" + value + ")";
|
||||||
} else {
|
} else {
|
||||||
// Use by-function serialization to emulate
|
// Use by-function serialization to emulate
|
||||||
// CreateVectorOfStrings(); this works also with non-std strings.
|
// CreateVectorOfStrings(); this works also with non-std strings
|
||||||
|
// and non-std::vector vector types.
|
||||||
code +=
|
code +=
|
||||||
"_fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::"
|
"_fbb.CreateVector<::flatbuffers::Offset<::flatbuffers::"
|
||||||
"String>>"
|
"String>>"
|
||||||
@@ -3793,20 +3855,37 @@ class CppGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
case BASE_TYPE_STRUCT: {
|
case BASE_TYPE_STRUCT: {
|
||||||
if (IsStruct(vector_type)) {
|
if (IsStruct(vector_type)) {
|
||||||
const auto& struct_attrs =
|
const auto native_type =
|
||||||
field.value.type.struct_def->attributes;
|
EffectiveNativeType(field, *field.value.type.struct_def);
|
||||||
const auto native_type = struct_attrs.Lookup("native_type");
|
|
||||||
if (native_type) {
|
if (native_type) {
|
||||||
code += "_fbb.CreateVectorOfNativeStructs<";
|
code += "_fbb.CreateVectorOfNativeStructs<";
|
||||||
code += WrapInNameSpace(*vector_type.struct_def) + ", " +
|
code += WrapInNameSpace(*vector_type.struct_def) + ", " +
|
||||||
native_type->constant + ">";
|
native_type->constant + ">";
|
||||||
code += "(" + value;
|
if (custom_vector) {
|
||||||
const auto pack_name =
|
code += "(" + value + ".data(), " + value + ".size()";
|
||||||
struct_attrs.Lookup("native_type_pack_name");
|
} else {
|
||||||
|
code += "(" + value;
|
||||||
|
}
|
||||||
|
const auto pack_name = EffectiveNativeTypePackName(
|
||||||
|
field, *field.value.type.struct_def);
|
||||||
if (pack_name) {
|
if (pack_name) {
|
||||||
code += ", ::flatbuffers::Pack" + pack_name->constant;
|
code += ", ::flatbuffers::Pack" + pack_name->constant;
|
||||||
}
|
}
|
||||||
code += ")";
|
code += ")";
|
||||||
|
} else if (custom_vector &&
|
||||||
|
(field.value.type.base_type == BASE_TYPE_VECTOR64 ||
|
||||||
|
field.offset64)) {
|
||||||
|
// CreateVectorOfStructs64() (and CreateVectorOfStructs64<V>()
|
||||||
|
// for offset64) only accept a std::vector; use the
|
||||||
|
// equivalent explicit-template raw pointer overload instead.
|
||||||
|
const auto struct_type = WrapInNameSpace(*vector_type.struct_def);
|
||||||
|
const auto vector_t = field.value.type.base_type ==
|
||||||
|
BASE_TYPE_VECTOR64
|
||||||
|
? "::flatbuffers::Vector64"
|
||||||
|
: "::flatbuffers::Vector";
|
||||||
|
code += "_fbb.CreateVectorOfStructs<" + struct_type +
|
||||||
|
", ::flatbuffers::Offset64, " + vector_t + ">(" +
|
||||||
|
value + ".data(), " + value + ".size())";
|
||||||
} else {
|
} else {
|
||||||
// If the field uses 64-bit addressing, create a 64-bit vector.
|
// If the field uses 64-bit addressing, create a 64-bit vector.
|
||||||
if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
|
if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
|
||||||
@@ -3818,7 +3897,11 @@ class CppGenerator : public BaseGenerator {
|
|||||||
code += "64<::flatbuffers::Vector>";
|
code += "64<::flatbuffers::Vector>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
code += "(" + value + ")";
|
if (custom_vector) {
|
||||||
|
code += "(" + value + ".data(), " + value + ".size())";
|
||||||
|
} else {
|
||||||
|
code += "(" + value + ")";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
code += "_fbb.CreateVector<::flatbuffers::Offset<";
|
code += "_fbb.CreateVector<::flatbuffers::Offset<";
|
||||||
@@ -3837,7 +3920,17 @@ class CppGenerator : public BaseGenerator {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BASE_TYPE_BOOL: {
|
case BASE_TYPE_BOOL: {
|
||||||
code += "_fbb.CreateVector(" + value + ")";
|
if (custom_vector) {
|
||||||
|
// Vectors of bool are always stored on the wire as uint8_t
|
||||||
|
// (there is no Vector<bool>); CreateVectorScalarCast() does
|
||||||
|
// the per-element bool->uint8_t cast from a raw data()/size()
|
||||||
|
// pointer pair, avoiding any dependency on std::vector<bool>'s
|
||||||
|
// bit-packed specialization.
|
||||||
|
code += "_fbb.CreateVectorScalarCast<uint8_t>(" + value +
|
||||||
|
".data(), " + value + ".size())";
|
||||||
|
} else {
|
||||||
|
code += "_fbb.CreateVector(" + value + ")";
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case BASE_TYPE_UNION: {
|
case BASE_TYPE_UNION: {
|
||||||
@@ -3873,9 +3966,11 @@ class CppGenerator : public BaseGenerator {
|
|||||||
// the underlying storage type (eg. uint8_t).
|
// the underlying storage type (eg. uint8_t).
|
||||||
const auto basetype = GenTypeBasic(
|
const auto basetype = GenTypeBasic(
|
||||||
field.value.type.enum_def->underlying_type, false);
|
field.value.type.enum_def->underlying_type, false);
|
||||||
code += "_fbb.CreateVectorScalarCast<" + basetype +
|
const std::string data_ptr =
|
||||||
">(::flatbuffers::data(" + value + "), " + value +
|
custom_vector ? value + ".data()"
|
||||||
".size())";
|
: "::flatbuffers::data(" + value + ")";
|
||||||
|
code += "_fbb.CreateVectorScalarCast<" + basetype + ">(" +
|
||||||
|
data_ptr + ", " + value + ".size())";
|
||||||
} else if (field.attributes.Lookup("cpp_type")) {
|
} else if (field.attributes.Lookup("cpp_type")) {
|
||||||
auto type = GenTypeBasic(vector_type, false);
|
auto type = GenTypeBasic(vector_type, false);
|
||||||
code += "_fbb.CreateVector<" + type + ">(" + value + ".size(), ";
|
code += "_fbb.CreateVector<" + type + ">(" + value + ".size(), ";
|
||||||
@@ -3884,6 +3979,27 @@ class CppGenerator : public BaseGenerator {
|
|||||||
code += "static_cast<" + type + ">((*__va->__rehasher)";
|
code += "static_cast<" + type + ">((*__va->__rehasher)";
|
||||||
code += "(__va->_" + value + "[i]" + GenPtrGet(field) + ")) : 0";
|
code += "(__va->_" + value + "[i]" + GenPtrGet(field) + ")) : 0";
|
||||||
code += "; }, &_va )";
|
code += "; }, &_va )";
|
||||||
|
} else if (custom_vector) {
|
||||||
|
// Explicitly specify the element type so it can be deduced
|
||||||
|
// from a raw data()/size() pointer pair instead of relying on
|
||||||
|
// the std::vector<T, Alloc>-specific CreateVector overloads.
|
||||||
|
// Use the user-facing type (matches what GenTypeNative()
|
||||||
|
// stores in the native vector, e.g. the enum type itself for
|
||||||
|
// scoped-enum fields) so it matches data()'s pointee type.
|
||||||
|
auto type = GenTypeBasic(vector_type, true);
|
||||||
|
if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
|
||||||
|
code += "_fbb.CreateVector<" + type +
|
||||||
|
", ::flatbuffers::Offset64, ::flatbuffers::Vector64>(" +
|
||||||
|
value + ".data(), " + value + ".size())";
|
||||||
|
} else if (field.offset64) {
|
||||||
|
// This is normal 32-bit vector, with 64-bit addressing.
|
||||||
|
code += "_fbb.CreateVector<" + type +
|
||||||
|
", ::flatbuffers::Offset64, ::flatbuffers::Vector>(" +
|
||||||
|
value + ".data(), " + value + ".size())";
|
||||||
|
} else {
|
||||||
|
code += "_fbb.CreateVector(" + value + ".data(), " + value +
|
||||||
|
".size())";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// If the field uses 64-bit addressing, create a 64-bit vector.
|
// If the field uses 64-bit addressing, create a 64-bit vector.
|
||||||
if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
|
if (field.value.type.base_type == BASE_TYPE_VECTOR64) {
|
||||||
@@ -3917,12 +4033,12 @@ class CppGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
case BASE_TYPE_STRUCT: {
|
case BASE_TYPE_STRUCT: {
|
||||||
if (IsStruct(field.value.type)) {
|
if (IsStruct(field.value.type)) {
|
||||||
const auto& struct_attribs = field.value.type.struct_def->attributes;
|
const auto native_type =
|
||||||
const auto native_type = struct_attribs.Lookup("native_type");
|
EffectiveNativeType(field, *field.value.type.struct_def);
|
||||||
if (native_type && field.native_inline) {
|
if (native_type && field.native_inline) {
|
||||||
code += "::flatbuffers::Pack";
|
code += "::flatbuffers::Pack";
|
||||||
const auto pack_name =
|
const auto pack_name =
|
||||||
struct_attribs.Lookup("native_type_pack_name");
|
EffectiveNativeTypePackName(field, *field.value.type.struct_def);
|
||||||
if (pack_name) {
|
if (pack_name) {
|
||||||
code += pack_name->constant;
|
code += pack_name->constant;
|
||||||
}
|
}
|
||||||
@@ -4087,8 +4203,7 @@ class CppGenerator : public BaseGenerator {
|
|||||||
if (field->value.type.base_type == BASE_TYPE_STRUCT) {
|
if (field->value.type.base_type == BASE_TYPE_STRUCT) {
|
||||||
if (IsStruct(field->value.type)) {
|
if (IsStruct(field->value.type)) {
|
||||||
auto native_type =
|
auto native_type =
|
||||||
field->value.type.struct_def->attributes.Lookup(
|
EffectiveNativeType(*field, *field->value.type.struct_def);
|
||||||
"native_type");
|
|
||||||
auto native_inline = field->attributes.Lookup("native_inline");
|
auto native_inline = field->attributes.Lookup("native_inline");
|
||||||
if (native_type) {
|
if (native_type) {
|
||||||
pass_by_address = true;
|
pass_by_address = true;
|
||||||
@@ -4443,6 +4558,141 @@ class CppGenerator : public BaseGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Split a "::"-qualified C++ name into namespace components + final name.
|
||||||
|
static std::vector<std::string> SplitQualifiedName(const std::string& qualified) {
|
||||||
|
std::vector<std::string> 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<std::string> 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<std::string> 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<std::string> 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
|
// Set up the correct namespace. Only open a namespace if the existing one is
|
||||||
// different (closing/opening only what is necessary).
|
// different (closing/opening only what is necessary).
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1286,6 +1286,55 @@ CheckedError Parser::ParseField(StructDef& struct_def) {
|
|||||||
"'native_inline' can only be defined on structs, vector of structs or "
|
"'native_inline' can only be defined on structs, vector of structs or "
|
||||||
"vector of tables");
|
"vector of tables");
|
||||||
|
|
||||||
|
// `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 `<wrapper><::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(
|
||||||
|
"'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* wrapper = target_struct->attributes.Lookup("bigfoot_ref_wrapper");
|
||||||
|
if (!wrapper)
|
||||||
|
return Error(
|
||||||
|
"'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(
|
||||||
|
"'bigfoot_ref' cannot be combined with an explicit 'native_type' "
|
||||||
|
"on the same field");
|
||||||
|
|
||||||
|
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 = 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")) {
|
||||||
|
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 = bigfoot_ref->type;
|
||||||
|
pack_name_val->constant = target_struct->name + asset_short_name;
|
||||||
|
field->attributes.Add("native_type_pack_name", pack_name_val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto nested = field->attributes.Lookup("nested_flatbuffer");
|
auto nested = field->attributes.Lookup("nested_flatbuffer");
|
||||||
if (nested) {
|
if (nested) {
|
||||||
if (nested->type.base_type != BASE_TYPE_STRING)
|
if (nested->type.base_type != BASE_TYPE_STRING)
|
||||||
|
|||||||
@@ -78,6 +78,9 @@ cc_test(
|
|||||||
"vector_table_naked_ptr/vector_table_naked_ptr_generated.h",
|
"vector_table_naked_ptr/vector_table_naked_ptr_generated.h",
|
||||||
"vector_table_naked_ptr_test.h",
|
"vector_table_naked_ptr_test.h",
|
||||||
"vector_table_naked_ptr_test.cpp",
|
"vector_table_naked_ptr_test.cpp",
|
||||||
|
"test_vector_type.h",
|
||||||
|
"cpp_vector_type_test.h",
|
||||||
|
"cpp_vector_type_test.cpp",
|
||||||
],
|
],
|
||||||
copts = [
|
copts = [
|
||||||
"-DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE",
|
"-DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE",
|
||||||
@@ -136,6 +139,7 @@ cc_test(
|
|||||||
deps = [
|
deps = [
|
||||||
":alignment_test_cc_fbs",
|
":alignment_test_cc_fbs",
|
||||||
":arrays_test_cc_fbs",
|
":arrays_test_cc_fbs",
|
||||||
|
":cpp_vector_type_cc_fbs",
|
||||||
":default_vectors_strings_test_cc_fbs",
|
":default_vectors_strings_test_cc_fbs",
|
||||||
":monster_extra_cc_fbs",
|
":monster_extra_cc_fbs",
|
||||||
":monster_test_cc_fbs",
|
":monster_test_cc_fbs",
|
||||||
@@ -271,6 +275,19 @@ flatbuffer_cc_library(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
flatbuffer_cc_library(
|
||||||
|
name = "cpp_vector_type_cc_fbs",
|
||||||
|
srcs = ["cpp_vector_type.fbs"],
|
||||||
|
flatc_args = [
|
||||||
|
"--gen-compare",
|
||||||
|
"--gen-mutable",
|
||||||
|
"--gen-object-api",
|
||||||
|
"--reflect-names",
|
||||||
|
"--cpp-include test_vector_type.h",
|
||||||
|
"--cpp-vector-type ::flatbuffers::tests::CustomVector",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
flatbuffer_cc_library(
|
flatbuffer_cc_library(
|
||||||
name = "alignment_test_cc_fbs",
|
name = "alignment_test_cc_fbs",
|
||||||
srcs = ["alignment_test.fbs"],
|
srcs = ["alignment_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;
|
||||||
@@ -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::Thing>(Native::RefId(1));
|
||||||
|
src.ref_a_again.push_back(Native::Ref<Native::Thing>(Native::RefId(2)));
|
||||||
|
src.ref_a_again.push_back(Native::Ref<Native::Thing>(Native::RefId(3)));
|
||||||
|
src.ref_b = Native::Ref<Native::OtherThing>(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
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
#ifndef BIGFOOT_REF_TEST_IMPL_H
|
||||||
|
#define BIGFOOT_REF_TEST_IMPL_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
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<T> must compile and round-trip
|
||||||
|
// without T ever being a complete type, exactly like Bigfoot's
|
||||||
|
// HardReference<T>/SoftReference<T>. 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 <typename T>
|
||||||
|
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
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
// Schema used to test the --cpp-vector-type flatc option, which lets the
|
||||||
|
// generated Object API use a custom vector-like container (e.g.
|
||||||
|
// eastl::vector) instead of std::vector. See tests/test_vector_type.h for
|
||||||
|
// the stand-in container used by the test, and
|
||||||
|
// tests/cpp_vector_type_test.cpp for the test itself.
|
||||||
|
|
||||||
|
namespace CppVectorTypeNS;
|
||||||
|
|
||||||
|
enum CppVectorTypeColor : byte { Red = 0, Green, Blue }
|
||||||
|
|
||||||
|
struct CppVectorTypeVec2 {
|
||||||
|
x: float;
|
||||||
|
y: float;
|
||||||
|
}
|
||||||
|
|
||||||
|
table CppVectorTypeMonster {
|
||||||
|
id: int32;
|
||||||
|
}
|
||||||
|
|
||||||
|
table CppVectorTypeTest {
|
||||||
|
ints: [int32];
|
||||||
|
flags: [bool];
|
||||||
|
colors: [CppVectorTypeColor];
|
||||||
|
strings: [string];
|
||||||
|
positions: [CppVectorTypeVec2];
|
||||||
|
monsters: [CppVectorTypeMonster];
|
||||||
|
}
|
||||||
|
|
||||||
|
root_type CppVectorTypeTest;
|
||||||
@@ -0,0 +1,143 @@
|
|||||||
|
#include "cpp_vector_type_test.h"
|
||||||
|
|
||||||
|
#include "cpp_vector_type_generated.h"
|
||||||
|
#include "test_assert.h"
|
||||||
|
|
||||||
|
namespace flatbuffers {
|
||||||
|
namespace tests {
|
||||||
|
|
||||||
|
// Exercises the --cpp-vector-type flatc option (see
|
||||||
|
// tests/cpp_vector_type.fbs and tests/test_vector_type.h), which replaces
|
||||||
|
// std::vector with a custom vector-like container in the generated Object
|
||||||
|
// API. This covers every CreateVector*-family code path in Pack(): plain
|
||||||
|
// scalars, bool, enum-cast, vector-of-string, vector-of-struct and
|
||||||
|
// vector-of-table, then round-trips everything back through UnPackTo().
|
||||||
|
void CppVectorTypeTest() {
|
||||||
|
using CppVectorTypeNS::CppVectorTypeColor_Blue;
|
||||||
|
using CppVectorTypeNS::CppVectorTypeColor_Green;
|
||||||
|
using CppVectorTypeNS::CppVectorTypeColor_Red;
|
||||||
|
using CppVectorTypeNS::CppVectorTypeMonsterT;
|
||||||
|
using CppVectorTypeNS::CppVectorTypeTest;
|
||||||
|
using CppVectorTypeNS::CppVectorTypeTestT;
|
||||||
|
using CppVectorTypeNS::CppVectorTypeVec2;
|
||||||
|
|
||||||
|
// ---------------------------------------
|
||||||
|
// 1) Build a native object using the custom vector container for every
|
||||||
|
// vector field (scalars, bools, enums, strings, structs and tables).
|
||||||
|
// ---------------------------------------
|
||||||
|
CppVectorTypeTestT src;
|
||||||
|
src.ints.push_back(1);
|
||||||
|
src.ints.push_back(2);
|
||||||
|
src.ints.push_back(3);
|
||||||
|
|
||||||
|
src.flags.push_back(true);
|
||||||
|
src.flags.push_back(false);
|
||||||
|
src.flags.push_back(true);
|
||||||
|
|
||||||
|
src.colors.push_back(CppVectorTypeColor_Red);
|
||||||
|
src.colors.push_back(CppVectorTypeColor_Green);
|
||||||
|
src.colors.push_back(CppVectorTypeColor_Blue);
|
||||||
|
|
||||||
|
src.strings.push_back("hello");
|
||||||
|
src.strings.push_back("world");
|
||||||
|
|
||||||
|
src.positions.push_back(CppVectorTypeVec2(1.0f, 2.0f));
|
||||||
|
src.positions.push_back(CppVectorTypeVec2(3.0f, 4.0f));
|
||||||
|
|
||||||
|
src.monsters.emplace_back(new CppVectorTypeMonsterT());
|
||||||
|
src.monsters[0]->id = 111;
|
||||||
|
src.monsters.emplace_back(new CppVectorTypeMonsterT());
|
||||||
|
src.monsters[1]->id = 222;
|
||||||
|
|
||||||
|
// ---------------------------------------
|
||||||
|
// 2) Exercise the copy constructor / copy assignment operator generated
|
||||||
|
// for object-API types (--gen-compare requires these too), which rely
|
||||||
|
// on the custom vector's own copy ctor plus reserve()/emplace_back()
|
||||||
|
// for the vector-of-pointer (table) field.
|
||||||
|
// ---------------------------------------
|
||||||
|
CppVectorTypeTestT copy_of_src(src);
|
||||||
|
TEST_EQ(copy_of_src == src, true);
|
||||||
|
TEST_ASSERT(copy_of_src.monsters[0].get() != src.monsters[0].get());
|
||||||
|
TEST_EQ(copy_of_src.monsters[0]->id, 111);
|
||||||
|
|
||||||
|
// ---------------------------------------
|
||||||
|
// 3) Pack into a FlatBuffer and verify the wire-format contents.
|
||||||
|
// ---------------------------------------
|
||||||
|
flatbuffers::FlatBufferBuilder fbb;
|
||||||
|
fbb.Finish(CppVectorTypeTest::Pack(fbb, &src));
|
||||||
|
|
||||||
|
const auto* fb =
|
||||||
|
flatbuffers::GetRoot<CppVectorTypeTest>(fbb.GetBufferPointer());
|
||||||
|
|
||||||
|
TEST_EQ(fb->ints()->size(), 3u);
|
||||||
|
TEST_EQ(fb->ints()->Get(0), 1);
|
||||||
|
TEST_EQ(fb->ints()->Get(1), 2);
|
||||||
|
TEST_EQ(fb->ints()->Get(2), 3);
|
||||||
|
|
||||||
|
TEST_EQ(fb->flags()->size(), 3u);
|
||||||
|
TEST_EQ(fb->flags()->Get(0) != 0, true);
|
||||||
|
TEST_EQ(fb->flags()->Get(1) != 0, false);
|
||||||
|
TEST_EQ(fb->flags()->Get(2) != 0, true);
|
||||||
|
|
||||||
|
TEST_EQ(fb->colors()->size(), 3u);
|
||||||
|
TEST_EQ(fb->colors()->Get(0), CppVectorTypeColor_Red);
|
||||||
|
TEST_EQ(fb->colors()->Get(1), CppVectorTypeColor_Green);
|
||||||
|
TEST_EQ(fb->colors()->Get(2), CppVectorTypeColor_Blue);
|
||||||
|
|
||||||
|
TEST_EQ(fb->strings()->size(), 2u);
|
||||||
|
TEST_EQ_STR(fb->strings()->Get(0)->c_str(), "hello");
|
||||||
|
TEST_EQ_STR(fb->strings()->Get(1)->c_str(), "world");
|
||||||
|
|
||||||
|
TEST_EQ(fb->positions()->size(), 2u);
|
||||||
|
TEST_EQ(fb->positions()->Get(0)->x(), 1.0f);
|
||||||
|
TEST_EQ(fb->positions()->Get(0)->y(), 2.0f);
|
||||||
|
TEST_EQ(fb->positions()->Get(1)->x(), 3.0f);
|
||||||
|
TEST_EQ(fb->positions()->Get(1)->y(), 4.0f);
|
||||||
|
|
||||||
|
TEST_EQ(fb->monsters()->size(), 2u);
|
||||||
|
TEST_EQ(fb->monsters()->Get(0)->id(), 111);
|
||||||
|
TEST_EQ(fb->monsters()->Get(1)->id(), 222);
|
||||||
|
|
||||||
|
// ---------------------------------------
|
||||||
|
// 4) Unpack back into a fresh native object and verify a full round-trip
|
||||||
|
// through the custom vector container.
|
||||||
|
// ---------------------------------------
|
||||||
|
CppVectorTypeTestT dst;
|
||||||
|
fb->UnPackTo(&dst);
|
||||||
|
|
||||||
|
TEST_EQ(dst == src, true);
|
||||||
|
|
||||||
|
TEST_EQ(dst.ints.size(), 3u);
|
||||||
|
TEST_EQ(dst.ints[0], 1);
|
||||||
|
TEST_EQ(dst.ints[1], 2);
|
||||||
|
TEST_EQ(dst.ints[2], 3);
|
||||||
|
|
||||||
|
TEST_EQ(dst.flags.size(), 3u);
|
||||||
|
TEST_EQ(dst.flags[0], true);
|
||||||
|
TEST_EQ(dst.flags[1], false);
|
||||||
|
TEST_EQ(dst.flags[2], true);
|
||||||
|
|
||||||
|
TEST_EQ(dst.colors.size(), 3u);
|
||||||
|
TEST_EQ(dst.colors[0], CppVectorTypeColor_Red);
|
||||||
|
TEST_EQ(dst.colors[1], CppVectorTypeColor_Green);
|
||||||
|
TEST_EQ(dst.colors[2], CppVectorTypeColor_Blue);
|
||||||
|
|
||||||
|
TEST_EQ(dst.strings.size(), 2u);
|
||||||
|
TEST_EQ_STR(dst.strings[0].c_str(), "hello");
|
||||||
|
TEST_EQ_STR(dst.strings[1].c_str(), "world");
|
||||||
|
|
||||||
|
TEST_EQ(dst.positions.size(), 2u);
|
||||||
|
TEST_EQ(dst.positions[0].x(), 1.0f);
|
||||||
|
TEST_EQ(dst.positions[0].y(), 2.0f);
|
||||||
|
TEST_EQ(dst.positions[1].x(), 3.0f);
|
||||||
|
TEST_EQ(dst.positions[1].y(), 4.0f);
|
||||||
|
|
||||||
|
TEST_EQ(dst.monsters.size(), 2u);
|
||||||
|
TEST_ASSERT(dst.monsters[0] != nullptr);
|
||||||
|
TEST_ASSERT(dst.monsters[1] != nullptr);
|
||||||
|
TEST_EQ(dst.monsters[0]->id, 111);
|
||||||
|
TEST_EQ(dst.monsters[1]->id, 222);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace tests
|
||||||
|
} // namespace flatbuffers
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef TESTS_CPP_VECTOR_TYPE_TEST_H
|
||||||
|
#define TESTS_CPP_VECTOR_TYPE_TEST_H
|
||||||
|
|
||||||
|
namespace flatbuffers {
|
||||||
|
namespace tests {
|
||||||
|
|
||||||
|
void CppVectorTypeTest();
|
||||||
|
|
||||||
|
} // namespace tests
|
||||||
|
} // namespace flatbuffers
|
||||||
|
|
||||||
|
#endif // TESTS_CPP_VECTOR_TYPE_TEST_H
|
||||||
@@ -31,14 +31,6 @@ struct ApplicationDataT;
|
|||||||
bool operator==(const ApplicationDataT &lhs, const ApplicationDataT &rhs);
|
bool operator==(const ApplicationDataT &lhs, const ApplicationDataT &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 *ApplicationDataTypeTable();
|
|
||||||
|
|
||||||
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3D FLATBUFFERS_FINAL_CLASS {
|
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3D FLATBUFFERS_FINAL_CLASS {
|
||||||
private:
|
private:
|
||||||
float x_;
|
float x_;
|
||||||
@@ -46,9 +38,7 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3D FLATBUFFERS_FINAL_CLASS {
|
|||||||
float z_;
|
float z_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
|
struct Traits;
|
||||||
return Vector3DTypeTable();
|
|
||||||
}
|
|
||||||
Vector3D()
|
Vector3D()
|
||||||
: x_(0),
|
: x_(0),
|
||||||
y_(0),
|
y_(0),
|
||||||
@@ -62,24 +52,19 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3D FLATBUFFERS_FINAL_CLASS {
|
|||||||
float x() const {
|
float x() const {
|
||||||
return ::flatbuffers::EndianScalar(x_);
|
return ::flatbuffers::EndianScalar(x_);
|
||||||
}
|
}
|
||||||
void mutate_x(float _x) {
|
|
||||||
::flatbuffers::WriteScalar(&x_, _x);
|
|
||||||
}
|
|
||||||
float y() const {
|
float y() const {
|
||||||
return ::flatbuffers::EndianScalar(y_);
|
return ::flatbuffers::EndianScalar(y_);
|
||||||
}
|
}
|
||||||
void mutate_y(float _y) {
|
|
||||||
::flatbuffers::WriteScalar(&y_, _y);
|
|
||||||
}
|
|
||||||
float z() const {
|
float z() const {
|
||||||
return ::flatbuffers::EndianScalar(z_);
|
return ::flatbuffers::EndianScalar(z_);
|
||||||
}
|
}
|
||||||
void mutate_z(float _z) {
|
|
||||||
::flatbuffers::WriteScalar(&z_, _z);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
FLATBUFFERS_STRUCT_END(Vector3D, 12);
|
FLATBUFFERS_STRUCT_END(Vector3D, 12);
|
||||||
|
|
||||||
|
struct Vector3D::Traits {
|
||||||
|
using type = Vector3D;
|
||||||
|
};
|
||||||
|
|
||||||
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3DAlt FLATBUFFERS_FINAL_CLASS {
|
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3DAlt FLATBUFFERS_FINAL_CLASS {
|
||||||
private:
|
private:
|
||||||
float a_;
|
float a_;
|
||||||
@@ -87,9 +72,7 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3DAlt FLATBUFFERS_FINAL_CLASS {
|
|||||||
float c_;
|
float c_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
|
struct Traits;
|
||||||
return Vector3DAltTypeTable();
|
|
||||||
}
|
|
||||||
Vector3DAlt()
|
Vector3DAlt()
|
||||||
: a_(0),
|
: a_(0),
|
||||||
b_(0),
|
b_(0),
|
||||||
@@ -103,30 +86,23 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3DAlt FLATBUFFERS_FINAL_CLASS {
|
|||||||
float a() const {
|
float a() const {
|
||||||
return ::flatbuffers::EndianScalar(a_);
|
return ::flatbuffers::EndianScalar(a_);
|
||||||
}
|
}
|
||||||
void mutate_a(float _a) {
|
|
||||||
::flatbuffers::WriteScalar(&a_, _a);
|
|
||||||
}
|
|
||||||
float b() const {
|
float b() const {
|
||||||
return ::flatbuffers::EndianScalar(b_);
|
return ::flatbuffers::EndianScalar(b_);
|
||||||
}
|
}
|
||||||
void mutate_b(float _b) {
|
|
||||||
::flatbuffers::WriteScalar(&b_, _b);
|
|
||||||
}
|
|
||||||
float c() const {
|
float c() const {
|
||||||
return ::flatbuffers::EndianScalar(c_);
|
return ::flatbuffers::EndianScalar(c_);
|
||||||
}
|
}
|
||||||
void mutate_c(float _c) {
|
|
||||||
::flatbuffers::WriteScalar(&c_, _c);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
FLATBUFFERS_STRUCT_END(Vector3DAlt, 12);
|
FLATBUFFERS_STRUCT_END(Vector3DAlt, 12);
|
||||||
|
|
||||||
|
struct Vector3DAlt::Traits {
|
||||||
|
using type = Vector3DAlt;
|
||||||
|
};
|
||||||
|
|
||||||
struct Matrix FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
struct Matrix FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||||
typedef Native::Matrix NativeTableType;
|
typedef Native::Matrix NativeTableType;
|
||||||
typedef MatrixBuilder Builder;
|
typedef MatrixBuilder Builder;
|
||||||
static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
|
struct Traits;
|
||||||
return MatrixTypeTable();
|
|
||||||
}
|
|
||||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
VT_ROWS = 4,
|
VT_ROWS = 4,
|
||||||
VT_COLUMNS = 6,
|
VT_COLUMNS = 6,
|
||||||
@@ -135,21 +111,12 @@ struct Matrix FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
|||||||
int32_t rows() const {
|
int32_t rows() const {
|
||||||
return GetField<int32_t>(VT_ROWS, 0);
|
return GetField<int32_t>(VT_ROWS, 0);
|
||||||
}
|
}
|
||||||
bool mutate_rows(int32_t _rows = 0) {
|
|
||||||
return SetField<int32_t>(VT_ROWS, _rows, 0);
|
|
||||||
}
|
|
||||||
int32_t columns() const {
|
int32_t columns() const {
|
||||||
return GetField<int32_t>(VT_COLUMNS, 0);
|
return GetField<int32_t>(VT_COLUMNS, 0);
|
||||||
}
|
}
|
||||||
bool mutate_columns(int32_t _columns = 0) {
|
|
||||||
return SetField<int32_t>(VT_COLUMNS, _columns, 0);
|
|
||||||
}
|
|
||||||
const ::flatbuffers::Vector<float> *values() const {
|
const ::flatbuffers::Vector<float> *values() const {
|
||||||
return GetPointer<const ::flatbuffers::Vector<float> *>(VT_VALUES);
|
return GetPointer<const ::flatbuffers::Vector<float> *>(VT_VALUES);
|
||||||
}
|
}
|
||||||
::flatbuffers::Vector<float> *mutable_values() {
|
|
||||||
return GetPointer<::flatbuffers::Vector<float> *>(VT_VALUES);
|
|
||||||
}
|
|
||||||
template <bool B = false>
|
template <bool B = false>
|
||||||
bool Verify(::flatbuffers::VerifierTemplate<B> &verifier) const {
|
bool Verify(::flatbuffers::VerifierTemplate<B> &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
@@ -200,6 +167,11 @@ inline ::flatbuffers::Offset<Matrix> CreateMatrix(
|
|||||||
return builder_.Finish();
|
return builder_.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Matrix::Traits {
|
||||||
|
using type = Matrix;
|
||||||
|
static auto constexpr Create = CreateMatrix;
|
||||||
|
};
|
||||||
|
|
||||||
inline ::flatbuffers::Offset<Matrix> CreateMatrixDirect(
|
inline ::flatbuffers::Offset<Matrix> CreateMatrixDirect(
|
||||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
int32_t rows = 0,
|
int32_t rows = 0,
|
||||||
@@ -232,9 +204,7 @@ struct ApplicationDataT : public ::flatbuffers::NativeTable {
|
|||||||
struct ApplicationData FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
struct ApplicationData FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
||||||
typedef ApplicationDataT NativeTableType;
|
typedef ApplicationDataT NativeTableType;
|
||||||
typedef ApplicationDataBuilder Builder;
|
typedef ApplicationDataBuilder Builder;
|
||||||
static const ::flatbuffers::TypeTable *MiniReflectTypeTable() {
|
struct Traits;
|
||||||
return ApplicationDataTypeTable();
|
|
||||||
}
|
|
||||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
VT_VECTORS = 4,
|
VT_VECTORS = 4,
|
||||||
VT_VECTORS_ALT = 6,
|
VT_VECTORS_ALT = 6,
|
||||||
@@ -246,39 +216,21 @@ struct ApplicationData FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table {
|
|||||||
const ::flatbuffers::Vector<const Geometry::Vector3D *> *vectors() const {
|
const ::flatbuffers::Vector<const Geometry::Vector3D *> *vectors() const {
|
||||||
return GetPointer<const ::flatbuffers::Vector<const Geometry::Vector3D *> *>(VT_VECTORS);
|
return GetPointer<const ::flatbuffers::Vector<const Geometry::Vector3D *> *>(VT_VECTORS);
|
||||||
}
|
}
|
||||||
::flatbuffers::Vector<const Geometry::Vector3D *> *mutable_vectors() {
|
|
||||||
return GetPointer<::flatbuffers::Vector<const Geometry::Vector3D *> *>(VT_VECTORS);
|
|
||||||
}
|
|
||||||
const ::flatbuffers::Vector<const Geometry::Vector3DAlt *> *vectors_alt() const {
|
const ::flatbuffers::Vector<const Geometry::Vector3DAlt *> *vectors_alt() const {
|
||||||
return GetPointer<const ::flatbuffers::Vector<const Geometry::Vector3DAlt *> *>(VT_VECTORS_ALT);
|
return GetPointer<const ::flatbuffers::Vector<const Geometry::Vector3DAlt *> *>(VT_VECTORS_ALT);
|
||||||
}
|
}
|
||||||
::flatbuffers::Vector<const Geometry::Vector3DAlt *> *mutable_vectors_alt() {
|
|
||||||
return GetPointer<::flatbuffers::Vector<const Geometry::Vector3DAlt *> *>(VT_VECTORS_ALT);
|
|
||||||
}
|
|
||||||
const Geometry::Vector3D *position() const {
|
const Geometry::Vector3D *position() const {
|
||||||
return GetStruct<const Geometry::Vector3D *>(VT_POSITION);
|
return GetStruct<const Geometry::Vector3D *>(VT_POSITION);
|
||||||
}
|
}
|
||||||
Geometry::Vector3D *mutable_position() {
|
|
||||||
return GetStruct<Geometry::Vector3D *>(VT_POSITION);
|
|
||||||
}
|
|
||||||
const Geometry::Vector3D *position_inline() const {
|
const Geometry::Vector3D *position_inline() const {
|
||||||
return GetStruct<const Geometry::Vector3D *>(VT_POSITION_INLINE);
|
return GetStruct<const Geometry::Vector3D *>(VT_POSITION_INLINE);
|
||||||
}
|
}
|
||||||
Geometry::Vector3D *mutable_position_inline() {
|
|
||||||
return GetStruct<Geometry::Vector3D *>(VT_POSITION_INLINE);
|
|
||||||
}
|
|
||||||
const Geometry::Matrix *matrix() const {
|
const Geometry::Matrix *matrix() const {
|
||||||
return GetPointer<const Geometry::Matrix *>(VT_MATRIX);
|
return GetPointer<const Geometry::Matrix *>(VT_MATRIX);
|
||||||
}
|
}
|
||||||
Geometry::Matrix *mutable_matrix() {
|
|
||||||
return GetPointer<Geometry::Matrix *>(VT_MATRIX);
|
|
||||||
}
|
|
||||||
const ::flatbuffers::Vector<::flatbuffers::Offset<Geometry::Matrix>> *matrices() const {
|
const ::flatbuffers::Vector<::flatbuffers::Offset<Geometry::Matrix>> *matrices() const {
|
||||||
return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<Geometry::Matrix>> *>(VT_MATRICES);
|
return GetPointer<const ::flatbuffers::Vector<::flatbuffers::Offset<Geometry::Matrix>> *>(VT_MATRICES);
|
||||||
}
|
}
|
||||||
::flatbuffers::Vector<::flatbuffers::Offset<Geometry::Matrix>> *mutable_matrices() {
|
|
||||||
return GetPointer<::flatbuffers::Vector<::flatbuffers::Offset<Geometry::Matrix>> *>(VT_MATRICES);
|
|
||||||
}
|
|
||||||
template <bool B = false>
|
template <bool B = false>
|
||||||
bool Verify(::flatbuffers::VerifierTemplate<B> &verifier) const {
|
bool Verify(::flatbuffers::VerifierTemplate<B> &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
@@ -351,6 +303,11 @@ inline ::flatbuffers::Offset<ApplicationData> CreateApplicationData(
|
|||||||
return builder_.Finish();
|
return builder_.Finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ApplicationData::Traits {
|
||||||
|
using type = ApplicationData;
|
||||||
|
static auto constexpr Create = CreateApplicationData;
|
||||||
|
};
|
||||||
|
|
||||||
inline ::flatbuffers::Offset<ApplicationData> CreateApplicationDataDirect(
|
inline ::flatbuffers::Offset<ApplicationData> CreateApplicationDataDirect(
|
||||||
::flatbuffers::FlatBufferBuilder &_fbb,
|
::flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
const std::vector<Geometry::Vector3D> *vectors = nullptr,
|
const std::vector<Geometry::Vector3D> *vectors = nullptr,
|
||||||
@@ -375,7 +332,7 @@ inline ::flatbuffers::Offset<ApplicationData> CreateApplicationDataDirect(
|
|||||||
::flatbuffers::Offset<ApplicationData> CreateApplicationData(::flatbuffers::FlatBufferBuilder &_fbb, const ApplicationDataT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
::flatbuffers::Offset<ApplicationData> 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 {
|
inline Native::Matrix *Matrix::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const {
|
||||||
auto _o = std::unique_ptr<Native::Matrix>(new Native::Matrix());
|
auto _o = std::make_unique<Native::Matrix>();
|
||||||
UnPackTo(_o.get(), _resolver);
|
UnPackTo(_o.get(), _resolver);
|
||||||
return _o.release();
|
return _o.release();
|
||||||
}
|
}
|
||||||
@@ -421,7 +378,7 @@ inline ApplicationDataT &ApplicationDataT::operator=(ApplicationDataT o) FLATBUF
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline ApplicationDataT *ApplicationData::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const {
|
inline ApplicationDataT *ApplicationData::UnPack(const ::flatbuffers::resolver_function_t *_resolver) const {
|
||||||
auto _o = std::unique_ptr<ApplicationDataT>(new ApplicationDataT());
|
auto _o = std::make_unique<ApplicationDataT>();
|
||||||
UnPackTo(_o.get(), _resolver);
|
UnPackTo(_o.get(), _resolver);
|
||||||
return _o.release();
|
return _o.release();
|
||||||
}
|
}
|
||||||
@@ -461,87 +418,6 @@ inline ::flatbuffers::Offset<ApplicationData> ApplicationData::Pack(::flatbuffer
|
|||||||
_matrices);
|
_matrices);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 *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 }
|
|
||||||
};
|
|
||||||
static const ::flatbuffers::TypeFunction type_refs[] = {
|
|
||||||
Geometry::Vector3DTypeTable,
|
|
||||||
Geometry::Vector3DAltTypeTable,
|
|
||||||
Geometry::MatrixTypeTable
|
|
||||||
};
|
|
||||||
static const char * const names[] = {
|
|
||||||
"vectors",
|
|
||||||
"vectors_alt",
|
|
||||||
"position",
|
|
||||||
"position_inline",
|
|
||||||
"matrix",
|
|
||||||
"matrices"
|
|
||||||
};
|
|
||||||
static const ::flatbuffers::TypeTable tt = {
|
|
||||||
::flatbuffers::ST_TABLE, 6, type_codes, type_refs, nullptr, nullptr, names
|
|
||||||
};
|
|
||||||
return &tt;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const Geometry::ApplicationData *GetApplicationData(const void *buf) {
|
inline const Geometry::ApplicationData *GetApplicationData(const void *buf) {
|
||||||
return ::flatbuffers::GetRoot<Geometry::ApplicationData>(buf);
|
return ::flatbuffers::GetRoot<Geometry::ApplicationData>(buf);
|
||||||
}
|
}
|
||||||
@@ -550,14 +426,6 @@ inline const Geometry::ApplicationData *GetSizePrefixedApplicationData(const voi
|
|||||||
return ::flatbuffers::GetSizePrefixedRoot<Geometry::ApplicationData>(buf);
|
return ::flatbuffers::GetSizePrefixedRoot<Geometry::ApplicationData>(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ApplicationData *GetMutableApplicationData(void *buf) {
|
|
||||||
return ::flatbuffers::GetMutableRoot<ApplicationData>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline Geometry::ApplicationData *GetMutableSizePrefixedApplicationData(void *buf) {
|
|
||||||
return ::flatbuffers::GetMutableSizePrefixedRoot<Geometry::ApplicationData>(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <bool B = false>
|
template <bool B = false>
|
||||||
inline bool VerifyApplicationDataBuffer(
|
inline bool VerifyApplicationDataBuffer(
|
||||||
::flatbuffers::VerifierTemplate<B> &verifier) {
|
::flatbuffers::VerifierTemplate<B> &verifier) {
|
||||||
@@ -570,6 +438,10 @@ inline bool VerifySizePrefixedApplicationDataBuffer(
|
|||||||
return verifier.template VerifySizePrefixedBuffer<Geometry::ApplicationData>(nullptr);
|
return verifier.template VerifySizePrefixedBuffer<Geometry::ApplicationData>(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const char *ApplicationDataExtension() {
|
||||||
|
return "bfbs";
|
||||||
|
}
|
||||||
|
|
||||||
inline void FinishApplicationDataBuffer(
|
inline void FinishApplicationDataBuffer(
|
||||||
::flatbuffers::FlatBufferBuilder &fbb,
|
::flatbuffers::FlatBufferBuilder &fbb,
|
||||||
::flatbuffers::Offset<Geometry::ApplicationData> root) {
|
::flatbuffers::Offset<Geometry::ApplicationData> root) {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ struct Matrix {
|
|||||||
(values == other.values);
|
(values == other.values);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Native
|
} // namespace Native
|
||||||
|
|
||||||
namespace Geometry {
|
namespace Geometry {
|
||||||
|
|||||||
@@ -97,6 +97,17 @@ void ErrorTest() {
|
|||||||
"datatype already");
|
"datatype already");
|
||||||
TestError("struct X (force_align: 7) { Y:int; }", "force_align");
|
TestError("struct X (force_align: 7) { Y:int; }", "force_align");
|
||||||
TestError("struct X {}", "size 0");
|
TestError("struct X {}", "size 0");
|
||||||
|
TestError(
|
||||||
|
"struct X { Y:int; } table T { y:X (bigfoot_ref:\"::Foo::Bar\"); "
|
||||||
|
"}",
|
||||||
|
"'bigfoot_ref_wrapper' attribute");
|
||||||
|
TestError(
|
||||||
|
"table T { y:int (bigfoot_ref:\"::Foo::Bar\"); }",
|
||||||
|
"struct-typed fields");
|
||||||
|
TestError(
|
||||||
|
"struct X (bigfoot_ref_wrapper: \"Foo\") { Y:int; } "
|
||||||
|
"table T { y:X (bigfoot_ref:\"\"); }",
|
||||||
|
"cannot be empty");
|
||||||
TestError("{}", "no root");
|
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 } { Y:1 }", "end of file");
|
||||||
TestError("table X { Y:byte; } root_type X; { Y:1 } table Y{ Z:int }",
|
TestError("table X { Y:byte; } root_type X; { Y:1 } table Y{ Z:int }",
|
||||||
|
|||||||
+5
-1
@@ -66,6 +66,8 @@
|
|||||||
#include "native_type_test_generated.h"
|
#include "native_type_test_generated.h"
|
||||||
#include "test_assert.h"
|
#include "test_assert.h"
|
||||||
#include "util_test.h"
|
#include "util_test.h"
|
||||||
|
#include "cpp_vector_type_test.h"
|
||||||
|
#include "bigfoot_ref_test_impl.h"
|
||||||
#include "vector_table_naked_ptr_test.h"
|
#include "vector_table_naked_ptr_test.h"
|
||||||
|
|
||||||
void FlatBufferBuilderTest();
|
void FlatBufferBuilderTest();
|
||||||
@@ -950,7 +952,6 @@ void NativeTypeTest() {
|
|||||||
TEST_EQ(dstDataT->position_inline.x, 4.0f);
|
TEST_EQ(dstDataT->position_inline.x, 4.0f);
|
||||||
TEST_EQ(dstDataT->position_inline.y, 5.0f);
|
TEST_EQ(dstDataT->position_inline.y, 5.0f);
|
||||||
TEST_EQ(dstDataT->position_inline.z, 6.0f);
|
TEST_EQ(dstDataT->position_inline.z, 6.0f);
|
||||||
|
|
||||||
for (int i = 0; i < N; ++i) {
|
for (int i = 0; i < N; ++i) {
|
||||||
const Native::Vector3D& v = dstDataT->vectors[i];
|
const Native::Vector3D& v = dstDataT->vectors[i];
|
||||||
TEST_EQ(v.x, 10 * i + 0.1f);
|
TEST_EQ(v.x, 10 * i + 0.1f);
|
||||||
@@ -1744,6 +1745,8 @@ int FlatBufferTests(const std::string& tests_data_path) {
|
|||||||
|
|
||||||
AlignmentTest();
|
AlignmentTest();
|
||||||
|
|
||||||
|
CppVectorTypeTest();
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_NO_FILE_TESTS
|
#ifndef FLATBUFFERS_NO_FILE_TESTS
|
||||||
ParseAndGenerateTextTest(tests_data_path, false);
|
ParseAndGenerateTextTest(tests_data_path, false);
|
||||||
ParseAndGenerateTextTest(tests_data_path, true);
|
ParseAndGenerateTextTest(tests_data_path, true);
|
||||||
@@ -1813,6 +1816,7 @@ int FlatBufferTests(const std::string& tests_data_path) {
|
|||||||
InvalidFloatTest();
|
InvalidFloatTest();
|
||||||
FixedLengthArrayTest();
|
FixedLengthArrayTest();
|
||||||
NativeTypeTest();
|
NativeTypeTest();
|
||||||
|
flatbuffers::tests::BigfootRefTest();
|
||||||
OptionalScalarsTest();
|
OptionalScalarsTest();
|
||||||
ParseFlexbuffersFromJsonWithNullTest();
|
ParseFlexbuffersFromJsonWithNullTest();
|
||||||
FlatbuffersSpanTest();
|
FlatbuffersSpanTest();
|
||||||
|
|||||||
@@ -0,0 +1,152 @@
|
|||||||
|
#ifndef TESTS_TEST_VECTOR_TYPE_H_
|
||||||
|
#define TESTS_TEST_VECTOR_TYPE_H_
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <new>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace flatbuffers {
|
||||||
|
namespace tests {
|
||||||
|
|
||||||
|
// A minimal stand-in for a custom vector-like container (e.g.
|
||||||
|
// eastl::vector), used to exercise the --cpp-vector-type flatc option.
|
||||||
|
//
|
||||||
|
// This is deliberately its own contiguous container rather than a wrapper
|
||||||
|
// around std::vector, so that:
|
||||||
|
// - generated code can't silently keep depending on any of the
|
||||||
|
// std::vector-specific overloads in flatbuffer_builder.h (e.g.
|
||||||
|
// CreateVector(const std::vector<T,Alloc>&)), and
|
||||||
|
// - CustomVector<bool> stores plain contiguous bools accessible via
|
||||||
|
// data(), unlike std::vector<bool>'s bit-packed specialization, matching
|
||||||
|
// how real alternative containers such as eastl::vector behave.
|
||||||
|
template<typename T>
|
||||||
|
class CustomVector {
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
using iterator = T*;
|
||||||
|
using const_iterator = const T*;
|
||||||
|
|
||||||
|
CustomVector() = default;
|
||||||
|
CustomVector(const CustomVector& o) { assign_copy(o); }
|
||||||
|
CustomVector(CustomVector&& o) noexcept { steal(o); }
|
||||||
|
|
||||||
|
CustomVector& operator=(const CustomVector& o) {
|
||||||
|
if (this != &o) {
|
||||||
|
destroy_all();
|
||||||
|
deallocate();
|
||||||
|
assign_copy(o);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
CustomVector& operator=(CustomVector&& o) noexcept {
|
||||||
|
if (this != &o) {
|
||||||
|
destroy_all();
|
||||||
|
deallocate();
|
||||||
|
steal(o);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
~CustomVector() {
|
||||||
|
destroy_all();
|
||||||
|
deallocate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve(size_t n) {
|
||||||
|
if (n > capacity_) grow_to(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(size_t n) {
|
||||||
|
if (n > capacity_) grow_to(n);
|
||||||
|
for (size_t i = n; i < size_; ++i) data_[i].~T();
|
||||||
|
for (size_t i = size_; i < n; ++i) new (&data_[i]) T();
|
||||||
|
size_ = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const { return size_; }
|
||||||
|
bool empty() const { return size_ == 0; }
|
||||||
|
|
||||||
|
T* data() { return data_; }
|
||||||
|
const T* data() const { return data_; }
|
||||||
|
|
||||||
|
T& operator[](size_t i) { return data_[i]; }
|
||||||
|
const T& operator[](size_t i) const { return data_[i]; }
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
|
void emplace_back(Args&&... args) {
|
||||||
|
if (size_ == capacity_) grow_to(capacity_ == 0 ? 1 : capacity_ * 2);
|
||||||
|
new (&data_[size_]) T(std::forward<Args>(args)...);
|
||||||
|
++size_;
|
||||||
|
}
|
||||||
|
void push_back(const T& v) { emplace_back(v); }
|
||||||
|
|
||||||
|
iterator begin() { return data_; }
|
||||||
|
iterator end() { return data_ + size_; }
|
||||||
|
const_iterator begin() const { return data_; }
|
||||||
|
const_iterator end() const { return data_ + size_; }
|
||||||
|
const_iterator cbegin() const { return data_; }
|
||||||
|
const_iterator cend() const { return data_ + size_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void grow_to(size_t n) {
|
||||||
|
T* new_data = static_cast<T*>(::operator new(n * sizeof(T)));
|
||||||
|
for (size_t i = 0; i < size_; ++i) {
|
||||||
|
new (&new_data[i]) T(std::move(data_[i]));
|
||||||
|
data_[i].~T();
|
||||||
|
}
|
||||||
|
::operator delete(data_);
|
||||||
|
data_ = new_data;
|
||||||
|
capacity_ = n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void assign_copy(const CustomVector& o) {
|
||||||
|
data_ = o.size_ ? static_cast<T*>(::operator new(o.size_ * sizeof(T)))
|
||||||
|
: nullptr;
|
||||||
|
capacity_ = o.size_;
|
||||||
|
for (size_t i = 0; i < o.size_; ++i) new (&data_[i]) T(o.data_[i]);
|
||||||
|
size_ = o.size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void steal(CustomVector& o) {
|
||||||
|
data_ = o.data_;
|
||||||
|
size_ = o.size_;
|
||||||
|
capacity_ = o.capacity_;
|
||||||
|
o.data_ = nullptr;
|
||||||
|
o.size_ = o.capacity_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroy_all() {
|
||||||
|
for (size_t i = 0; i < size_; ++i) data_[i].~T();
|
||||||
|
size_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate() {
|
||||||
|
::operator delete(data_);
|
||||||
|
data_ = nullptr;
|
||||||
|
capacity_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
T* data_ = nullptr;
|
||||||
|
size_t size_ = 0;
|
||||||
|
size_t capacity_ = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool operator==(const CustomVector<T>& lhs, const CustomVector<T>& rhs) {
|
||||||
|
if (lhs.size() != rhs.size()) return false;
|
||||||
|
for (size_t i = 0; i < lhs.size(); ++i) {
|
||||||
|
if (!(lhs[i] == rhs[i])) return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool operator!=(const CustomVector<T>& lhs, const CustomVector<T>& rhs) {
|
||||||
|
return !(lhs == rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace tests
|
||||||
|
} // namespace flatbuffers
|
||||||
|
|
||||||
|
#endif // TESTS_TEST_VECTOR_TYPE_H_
|
||||||
Reference in New Issue
Block a user