diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 02de41604..b836bfbcd 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -3812,14 +3812,25 @@ class CppGenerator : public BaseGenerator { if (IsStruct(vector_type)) { const auto& struct_attrs = field.value.type.struct_def->attributes; - const auto native_type = struct_attrs.Lookup("native_type"); + // Field-level native_type takes priority over struct-level + // native_type + auto field_native_type = field.attributes.Lookup("native_type"); + const auto native_type = field_native_type + ? field_native_type + : struct_attrs.Lookup("native_type"); if (native_type) { code += "_fbb.CreateVectorOfNativeStructs<"; code += WrapInNameSpace(*vector_type.struct_def) + ", " + native_type->constant + ">"; code += "(" + value; + // Field-level native_type_pack_name takes priority over + // struct-level + auto field_pack_name = + field.attributes.Lookup("native_type_pack_name"); const auto pack_name = - struct_attrs.Lookup("native_type_pack_name"); + field_pack_name + ? field_pack_name + : struct_attrs.Lookup("native_type_pack_name"); if (pack_name) { code += ", ::flatbuffers::Pack" + pack_name->constant; } @@ -4114,9 +4125,15 @@ class CppGenerator : public BaseGenerator { bool check_ptr = false; if (field->value.type.base_type == BASE_TYPE_STRUCT) { if (IsStruct(field->value.type)) { + // Field-level native_type takes priority over struct-level + // native_type + auto field_native_type = + field->attributes.Lookup("native_type"); auto native_type = - field->value.type.struct_def->attributes.Lookup( - "native_type"); + field_native_type + ? field_native_type + : field->value.type.struct_def->attributes.Lookup( + "native_type"); auto native_inline = field->attributes.Lookup("native_inline"); if (native_type) { pass_by_address = true; diff --git a/tests/native_type_test.fbs b/tests/native_type_test.fbs index 1e73d3330..af4c7473d 100644 --- a/tests/native_type_test.fbs +++ b/tests/native_type_test.fbs @@ -14,6 +14,12 @@ struct Vector3DAlt (native_type:"Native::Vector3D", native_type_pack_name:"Vecto c:float; } +struct Vector3DSimple { + x:float; + y:float; + z:float; +} + table Matrix (native_type:"Native::Matrix") { rows:int32; columns:int32; @@ -27,6 +33,8 @@ table ApplicationData { position_inline:Vector3D (native_inline); matrix:Matrix; matrices:[Matrix]; + simple_position:Vector3DSimple (native_type: "Native::Vector3D", native_inline, native_type_pack_name: "Vector3DSimple"); + simple_vectors:[Vector3DSimple] (native_type: "Native::Vector3D", native_type_pack_name: "Vector3DSimple"); } root_type ApplicationData; diff --git a/tests/native_type_test_generated.h b/tests/native_type_test_generated.h index a401e7264..1f5b32cea 100644 --- a/tests/native_type_test_generated.h +++ b/tests/native_type_test_generated.h @@ -21,6 +21,8 @@ struct Vector3D; struct Vector3DAlt; +struct Vector3DSimple; + struct Matrix; struct MatrixBuilder; @@ -28,6 +30,8 @@ struct ApplicationData; struct ApplicationDataBuilder; struct ApplicationDataT; +bool operator==(const Vector3DSimple &lhs, const Vector3DSimple &rhs); +bool operator!=(const Vector3DSimple &lhs, const Vector3DSimple &rhs); bool operator==(const ApplicationDataT &lhs, const ApplicationDataT &rhs); bool operator!=(const ApplicationDataT &lhs, const ApplicationDataT &rhs); @@ -35,6 +39,8 @@ inline const ::flatbuffers::TypeTable *Vector3DTypeTable(); inline const ::flatbuffers::TypeTable *Vector3DAltTypeTable(); +inline const ::flatbuffers::TypeTable *Vector3DSimpleTypeTable(); + inline const ::flatbuffers::TypeTable *MatrixTypeTable(); inline const ::flatbuffers::TypeTable *ApplicationDataTypeTable(); @@ -121,6 +127,59 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3DAlt FLATBUFFERS_FINAL_CLASS { }; FLATBUFFERS_STRUCT_END(Vector3DAlt, 12); +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3DSimple FLATBUFFERS_FINAL_CLASS { + private: + float x_; + float y_; + float z_; + + public: + static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { + return Vector3DSimpleTypeTable(); + } + Vector3DSimple() + : x_(0), + y_(0), + z_(0) { + } + Vector3DSimple(float _x, float _y, float _z) + : x_(::flatbuffers::EndianScalar(_x)), + y_(::flatbuffers::EndianScalar(_y)), + z_(::flatbuffers::EndianScalar(_z)) { + } + 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(Vector3DSimple, 12); + +inline bool operator==(const Vector3DSimple &lhs, const Vector3DSimple &rhs) { + return + (lhs.x() == rhs.x()) && + (lhs.y() == rhs.y()) && + (lhs.z() == rhs.z()); +} + +inline bool operator!=(const Vector3DSimple &lhs, const Vector3DSimple &rhs) { + return !(lhs == rhs); +} + + struct Matrix FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { typedef Native::Matrix NativeTableType; typedef MatrixBuilder Builder; @@ -223,6 +282,8 @@ struct ApplicationDataT : public ::flatbuffers::NativeTable { Native::Vector3D position_inline{}; std::unique_ptr matrix{}; std::vector> matrices{}; + Native::Vector3D simple_position{}; + std::vector simple_vectors{}; ApplicationDataT() = default; ApplicationDataT(const ApplicationDataT &o); ApplicationDataT(ApplicationDataT&&) FLATBUFFERS_NOEXCEPT = default; @@ -241,7 +302,9 @@ struct ApplicationData FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { VT_POSITION = 8, VT_POSITION_INLINE = 10, VT_MATRIX = 12, - VT_MATRICES = 14 + VT_MATRICES = 14, + VT_SIMPLE_POSITION = 16, + VT_SIMPLE_VECTORS = 18 }; const ::flatbuffers::Vector *vectors() const { return GetPointer *>(VT_VECTORS); @@ -279,6 +342,18 @@ struct ApplicationData FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { ::flatbuffers::Vector<::flatbuffers::Offset> *mutable_matrices() { return GetPointer<::flatbuffers::Vector<::flatbuffers::Offset> *>(VT_MATRICES); } + const Geometry::Vector3DSimple *simple_position() const { + return GetStruct(VT_SIMPLE_POSITION); + } + Geometry::Vector3DSimple *mutable_simple_position() { + return GetStruct(VT_SIMPLE_POSITION); + } + const ::flatbuffers::Vector *simple_vectors() const { + return GetPointer *>(VT_SIMPLE_VECTORS); + } + ::flatbuffers::Vector *mutable_simple_vectors() { + return GetPointer<::flatbuffers::Vector *>(VT_SIMPLE_VECTORS); + } template bool Verify(::flatbuffers::VerifierTemplate &verifier) const { return VerifyTableStart(verifier) && @@ -293,6 +368,9 @@ struct ApplicationData FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { VerifyOffset(verifier, VT_MATRICES) && verifier.VerifyVector(matrices()) && verifier.VerifyVectorOfTables(matrices()) && + VerifyField(verifier, VT_SIMPLE_POSITION, 4) && + VerifyOffset(verifier, VT_SIMPLE_VECTORS) && + verifier.VerifyVector(simple_vectors()) && verifier.EndTable(); } ApplicationDataT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; @@ -322,6 +400,12 @@ struct ApplicationDataBuilder { void add_matrices(::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> matrices) { fbb_.AddOffset(ApplicationData::VT_MATRICES, matrices); } + void add_simple_position(const Geometry::Vector3DSimple *simple_position) { + fbb_.AddStruct(ApplicationData::VT_SIMPLE_POSITION, simple_position); + } + void add_simple_vectors(::flatbuffers::Offset<::flatbuffers::Vector> simple_vectors) { + fbb_.AddOffset(ApplicationData::VT_SIMPLE_VECTORS, simple_vectors); + } explicit ApplicationDataBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); @@ -340,8 +424,12 @@ 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) { + ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> matrices = 0, + const Geometry::Vector3DSimple *simple_position = nullptr, + ::flatbuffers::Offset<::flatbuffers::Vector> simple_vectors = 0) { ApplicationDataBuilder builder_(_fbb); + builder_.add_simple_vectors(simple_vectors); + builder_.add_simple_position(simple_position); builder_.add_matrices(matrices); builder_.add_matrix(matrix); builder_.add_position_inline(position_inline); @@ -358,10 +446,13 @@ 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 std::vector<::flatbuffers::Offset> *matrices = nullptr, + const Geometry::Vector3DSimple *simple_position = nullptr, + const std::vector *simple_vectors = 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; + auto simple_vectors__ = simple_vectors ? _fbb.CreateVectorOfStructs(*simple_vectors) : 0; return Geometry::CreateApplicationData( _fbb, vectors__, @@ -369,7 +460,9 @@ inline ::flatbuffers::Offset CreateApplicationDataDirect( position, position_inline, matrix, - matrices__); + matrices__, + simple_position, + simple_vectors__); } ::flatbuffers::Offset CreateApplicationData(::flatbuffers::FlatBufferBuilder &_fbb, const ApplicationDataT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); @@ -392,7 +485,9 @@ 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.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.simple_position == rhs.simple_position) && + (lhs.simple_vectors == rhs.simple_vectors); } inline bool operator!=(const ApplicationDataT &lhs, const ApplicationDataT &rhs) { @@ -405,7 +500,9 @@ 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) { + matrix((o.matrix) ? new Native::Matrix(*o.matrix) : nullptr), + simple_position(o.simple_position), + simple_vectors(o.simple_vectors) { matrices.reserve(o.matrices.size()); for (const auto &matrices_ : o.matrices) { matrices.emplace_back((matrices_) ? new Native::Matrix(*matrices_) : nullptr); } } @@ -417,6 +514,8 @@ 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(simple_position, o.simple_position); + std::swap(simple_vectors, o.simple_vectors); return *this; } @@ -435,6 +534,8 @@ 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 = simple_position(); if (_e) _o->simple_position = ::flatbuffers::UnPackVector3DSimple(*_e); } + { auto _e = simple_vectors(); if (_e) { _o->simple_vectors.resize(_e->size()); for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->simple_vectors[_i] = ::flatbuffers::UnPackVector3DSimple(*_e->Get(_i)); } } else { _o->simple_vectors.resize(0); } } } inline ::flatbuffers::Offset CreateApplicationData(::flatbuffers::FlatBufferBuilder &_fbb, const ApplicationDataT *_o, const ::flatbuffers::rehasher_function_t *_rehasher) { @@ -451,6 +552,8 @@ 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 _simple_position = ::flatbuffers::PackVector3DSimple(_o->simple_position); + auto _simple_vectors = _o->simple_vectors.size() ? _fbb.CreateVectorOfNativeStructs(_o->simple_vectors, ::flatbuffers::PackVector3DSimple) : 0; return Geometry::CreateApplicationData( _fbb, _vectors, @@ -458,7 +561,9 @@ inline ::flatbuffers::Offset ApplicationData::Pack(::flatbuffer _o->position ? &_position : nullptr, &_position_inline, _matrix, - _matrices); + _matrices, + &_simple_position, + _simple_vectors); } inline const ::flatbuffers::TypeTable *Vector3DTypeTable() { @@ -497,6 +602,24 @@ inline const ::flatbuffers::TypeTable *Vector3DAltTypeTable() { return &tt; } +inline const ::flatbuffers::TypeTable *Vector3DSimpleTypeTable() { + 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 *MatrixTypeTable() { static const ::flatbuffers::TypeCode type_codes[] = { { ::flatbuffers::ET_INT, 0, -1 }, @@ -521,12 +644,15 @@ inline const ::flatbuffers::TypeTable *ApplicationDataTypeTable() { { ::flatbuffers::ET_SEQUENCE, 0, 0 }, { ::flatbuffers::ET_SEQUENCE, 0, 0 }, { ::flatbuffers::ET_SEQUENCE, 0, 2 }, - { ::flatbuffers::ET_SEQUENCE, 1, 2 } + { ::flatbuffers::ET_SEQUENCE, 1, 2 }, + { ::flatbuffers::ET_SEQUENCE, 0, 3 }, + { ::flatbuffers::ET_SEQUENCE, 1, 3 } }; static const ::flatbuffers::TypeFunction type_refs[] = { Geometry::Vector3DTypeTable, Geometry::Vector3DAltTypeTable, - Geometry::MatrixTypeTable + Geometry::MatrixTypeTable, + Geometry::Vector3DSimpleTypeTable }; static const char * const names[] = { "vectors", @@ -534,10 +660,12 @@ inline const ::flatbuffers::TypeTable *ApplicationDataTypeTable() { "position", "position_inline", "matrix", - "matrices" + "matrices", + "simple_position", + "simple_vectors" }; static const ::flatbuffers::TypeTable tt = { - ::flatbuffers::ST_TABLE, 6, type_codes, type_refs, nullptr, nullptr, names + ::flatbuffers::ST_TABLE, 8, type_codes, type_refs, nullptr, nullptr, names }; return &tt; } diff --git a/tests/native_type_test_impl.cpp b/tests/native_type_test_impl.cpp index 8719c140f..d08bf76a4 100644 --- a/tests/native_type_test_impl.cpp +++ b/tests/native_type_test_impl.cpp @@ -18,6 +18,15 @@ 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::Vector3DSimple PackVector3DSimple(const Native::Vector3D& obj) { + return Geometry::Vector3DSimple(obj.x, obj.y, obj.z); +} + +const Native::Vector3D UnPackVector3DSimple( + const Geometry::Vector3DSimple& obj) { + return Native::Vector3D(obj.x(), obj.y(), obj.z()); +} } // namespace flatbuffers namespace Geometry { diff --git a/tests/native_type_test_impl.h b/tests/native_type_test_impl.h index 88781f9fe..25017217a 100644 --- a/tests/native_type_test_impl.h +++ b/tests/native_type_test_impl.h @@ -48,6 +48,7 @@ struct Matrix { namespace Geometry { struct Vector3D; struct Vector3DAlt; +struct Vector3DSimple; } // namespace Geometry namespace flatbuffers { @@ -55,6 +56,8 @@ 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::Vector3DSimple PackVector3DSimple(const Native::Vector3D& obj); +const Native::Vector3D UnPackVector3DSimple(const Geometry::Vector3DSimple& obj); } // namespace flatbuffers #endif // VECTOR3D_PACK_H diff --git a/tests/test.cpp b/tests/test.cpp index c94d21592..88aea9e10 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -929,6 +929,12 @@ void NativeTypeTest() { Native::Vector3D(20 * i + 0.1f, 20 * i + 0.2f, 20 * i + 0.3f)); } + src_data.simple_position = Native::Vector3D(7.0f, 8.0f, 9.0f); + for (int i = 0; i < N; ++i) { + src_data.simple_vectors.push_back( + Native::Vector3D(30 * i + 0.1f, 30 * i + 0.2f, 30 * i + 0.3f)); + } + src_data.matrix = std::unique_ptr(new Native::Matrix(1, 2)); src_data.matrix->values = {3, 4}; @@ -963,6 +969,17 @@ void NativeTypeTest() { TEST_EQ(v2.z, 20 * i + 0.3f); } + TEST_EQ(dstDataT->simple_position.x, 7.0f); + TEST_EQ(dstDataT->simple_position.y, 8.0f); + TEST_EQ(dstDataT->simple_position.z, 9.0f); + + for (int i = 0; i < N; ++i) { + const Native::Vector3D& sv = dstDataT->simple_vectors[i]; + TEST_EQ(sv.x, 30 * i + 0.1f); + TEST_EQ(sv.y, 30 * i + 0.2f); + TEST_EQ(sv.z, 30 * i + 0.3f); + } + TEST_EQ(dstDataT->matrix->rows, 1); TEST_EQ(dstDataT->matrix->columns, 2); TEST_EQ(dstDataT->matrix->values[0], 3);