diff --git a/CMakeLists.txt b/CMakeLists.txt index f5ae5ac81c7..7c740fb2433 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -230,6 +230,8 @@ set(FlatBuffers_Tests_SRCS tests/util_test.cpp tests/native_type_test_impl.h tests/native_type_test_impl.cpp + tests/alignment_test.h + tests/alignment_test.cpp include/flatbuffers/code_generators.h src/code_generators.cpp # file generate by running compiler on tests/monster_test.fbs @@ -251,6 +253,8 @@ set(FlatBuffers_Tests_SRCS ${CMAKE_CURRENT_BINARY_DIR}/tests/optional_scalars_generated.h # file generate by running compiler on tests/native_inline_table_test.fbs ${CMAKE_CURRENT_BINARY_DIR}/tests/native_inline_table_test_generated.h + # file generate by running compiler on tests/alignment_test.fbs + ${CMAKE_CURRENT_BINARY_DIR}/tests/alignment_test_generated.h ) set(FlatBuffers_Tests_CPP17_SRCS @@ -623,6 +627,7 @@ if(FLATBUFFERS_BUILD_TESTS) compile_flatbuffers_schema_to_binary(tests/arrays_test.fbs) compile_flatbuffers_schema_to_embedded_binary(tests/monster_test.fbs "--no-includes;--gen-compare") compile_flatbuffers_schema_to_cpp(tests/native_inline_table_test.fbs "--gen-compare") + compile_flatbuffers_schema_to_cpp(tests/alignment_test.fbs "--gen-compare") if(NOT (MSVC AND (MSVC_VERSION LESS 1900))) compile_flatbuffers_schema_to_cpp(tests/monster_extra.fbs) # Test floating-point NAN/INF. endif() diff --git a/include/flatbuffers/flatbuffer_builder.h b/include/flatbuffers/flatbuffer_builder.h index f9432338f07..66c33ffccdf 100644 --- a/include/flatbuffers/flatbuffer_builder.h +++ b/include/flatbuffers/flatbuffer_builder.h @@ -449,7 +449,7 @@ class FlatBufferBuilder { } template void PreAlign(size_t len) { AssertScalarT(); - PreAlign(len, sizeof(T)); + PreAlign(len, AlignOf()); } /// @endcond @@ -589,11 +589,15 @@ class FlatBufferBuilder { return PushElement(static_cast(len)); } - void StartVector(size_t len, size_t elemsize) { + void StartVector(size_t len, size_t elemsize, size_t alignment) { NotNested(); nested = true; PreAlign(len * elemsize); - PreAlign(len * elemsize, elemsize); // Just in case elemsize > uoffset_t. + PreAlign(len * elemsize, alignment); // Just in case elemsize > uoffset_t. + } + + template void StartVector(size_t len) { + return StartVector(len, sizeof(T), AlignOf()); } // Call this right before StartVector/CreateVector if you want to force the @@ -627,7 +631,7 @@ class FlatBufferBuilder { // If this assert hits, you're specifying a template argument that is // causing the wrong overload to be selected, remove it. AssertScalarT(); - StartVector(len, sizeof(T)); + StartVector(len); if (len == 0) { return Offset>(EndVector(len)); } // clang-format off #if FLATBUFFERS_LITTLEENDIAN @@ -668,7 +672,7 @@ class FlatBufferBuilder { template Offset>> CreateVector(const Offset *v, size_t len) { - StartVector(len, sizeof(Offset)); + StartVector>(len); for (auto i = len; i > 0;) { PushElement(v[--i]); } return Offset>>(EndVector(len)); } @@ -688,7 +692,7 @@ class FlatBufferBuilder { // an array. Instead, read elements manually. // Background: https://isocpp.org/blog/2012/11/on-vectorbool Offset> CreateVector(const std::vector &v) { - StartVector(v.size(), sizeof(uint8_t)); + StartVector(v.size()); for (auto i = v.size(); i > 0;) { PushElement(static_cast(v[--i])); } @@ -762,7 +766,7 @@ class FlatBufferBuilder { for (auto it = begin; it != end; ++it) { buf_.scratch_push_small(CreateString(*it)); } - StartVector(size, sizeof(Offset)); + StartVector>(size); for (auto i = 1; i <= size; i++) { // Note we re-evaluate the buf location each iteration to account for any // underlying buffer resizing that may occur. @@ -782,7 +786,7 @@ class FlatBufferBuilder { /// where the vector is stored. template Offset> CreateVectorOfStructs(const T *v, size_t len) { - StartVector(len * sizeof(T) / AlignOf(), AlignOf()); + StartVector(len * sizeof(T) / AlignOf(), sizeof(T), AlignOf()); if (len > 0) { PushBytes(reinterpret_cast(v), sizeof(T) * len); } @@ -1025,9 +1029,9 @@ class FlatBufferBuilder { /// written to at a later time to serialize the data into a `vector` /// in the buffer. uoffset_t CreateUninitializedVector(size_t len, size_t elemsize, - uint8_t **buf) { + size_t alignment, uint8_t **buf) { NotNested(); - StartVector(len, elemsize); + StartVector(len, elemsize, alignment); buf_.make_space(len * elemsize); auto vec_start = GetSize(); auto vec_end = EndVector(len); @@ -1035,6 +1039,12 @@ class FlatBufferBuilder { return vec_end; } + FLATBUFFERS_ATTRIBUTE([[deprecated("call the version above instead")]]) + uoffset_t CreateUninitializedVector(size_t len, size_t elemsize, + uint8_t **buf) { + return CreateUninitializedVector(len, elemsize, elemsize, buf); + } + /// @brief Specialized version of `CreateVector` for non-copying use cases. /// Write the data any time later to the returned buffer pointer `buf`. /// @tparam T The data type of the data that will be stored in the buffer @@ -1046,14 +1056,14 @@ class FlatBufferBuilder { template Offset> CreateUninitializedVector(size_t len, T **buf) { AssertScalarT(); - return CreateUninitializedVector(len, sizeof(T), + return CreateUninitializedVector(len, sizeof(T), AlignOf(), reinterpret_cast(buf)); } template Offset> CreateUninitializedVectorOfStructs(size_t len, T **buf) { - return CreateUninitializedVector(len, sizeof(T), + return CreateUninitializedVector(len, sizeof(T), AlignOf(), reinterpret_cast(buf)); } @@ -1064,7 +1074,7 @@ class FlatBufferBuilder { Offset> CreateVectorScalarCast(const U *v, size_t len) { AssertScalarT(); AssertScalarT(); - StartVector(len, sizeof(T)); + StartVector(len); for (auto i = len; i > 0;) { PushElement(static_cast(v[--i])); } return Offset>(EndVector(len)); } @@ -1173,7 +1183,7 @@ class FlatBufferBuilder { // Allocates space for a vector of structures. // Must be completed with EndVectorOfStructs(). template T *StartVectorOfStructs(size_t vector_size) { - StartVector(vector_size * sizeof(T) / AlignOf(), AlignOf()); + StartVector(vector_size * sizeof(T) / AlignOf(), sizeof(T), AlignOf()); return reinterpret_cast(buf_.make_space(vector_size * sizeof(T))); } diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index cadcb6a09fc..d8015cb6e58 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -1614,6 +1614,7 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue, }); ECHECK(err); + const size_t alignment = InlineAlignment(type); const size_t len = count * InlineSize(type) / InlineAlignment(type); const size_t elemsize = InlineAlignment(type); const auto force_align = field->attributes.Lookup("force_align"); @@ -1623,7 +1624,8 @@ CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue, if (align > 1) { builder_.ForceVectorAlignment(len, elemsize, align); } } - builder_.StartVector(len, elemsize); + // TODO Fix using element alignment as size (`elemsize`)! + builder_.StartVector(len, elemsize, alignment); for (uoffset_t i = 0; i < count; i++) { // start at the back, since we're building the data backwards. auto &val = field_stack_.back().first; diff --git a/src/reflection.cpp b/src/reflection.cpp index 9abfd9fac4c..6ea2d20b121 100644 --- a/src/reflection.cpp +++ b/src/reflection.cpp @@ -689,9 +689,10 @@ Offset CopyTable(FlatBufferBuilder &fbb, FLATBUFFERS_FALLTHROUGH(); // fall thru default: { // Scalars and structs. auto element_size = GetTypeSize(element_base_type); + auto element_alignment = element_size; // For primitive elements if (elemobjectdef && elemobjectdef->is_struct()) element_size = elemobjectdef->bytesize(); - fbb.StartVector(vec->size(), element_size); + fbb.StartVector(vec->size(), element_size, element_alignment); fbb.PushBytes(vec->Data(), element_size * vec->size()); offset = fbb.EndVector(vec->size()); break; diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel index 3330bfc530a..d9048ea291c 100644 --- a/tests/BUILD.bazel +++ b/tests/BUILD.bazel @@ -8,6 +8,9 @@ cc_test( name = "flatbuffers_test", testonly = 1, srcs = [ + "alignment_test.cpp", + "alignment_test.h", + "alignment_test_generated.h", "evolution_test.cpp", "evolution_test.h", "evolution_test/evolution_v1_generated.h", @@ -50,6 +53,7 @@ cc_test( "-DBAZEL_TEST_DATA_PATH", ], data = [ + ":alignment_test.fbs", ":arrays_test.bfbs", ":arrays_test.fbs", ":arrays_test.golden", @@ -90,6 +94,7 @@ cc_test( "include/", ], deps = [ + ":alignment_test_cc_fbs", ":arrays_test_cc_fbs", ":monster_extra_cc_fbs", ":monster_test_cc_fbs", @@ -214,3 +219,8 @@ flatbuffer_cc_library( "--cpp-ptr-type flatbuffers::unique_ptr", ], ) + +flatbuffer_cc_library( + name = "alignment_test_cc_fbs", + srcs = ["alignment_test.fbs"], +) diff --git a/tests/alignment_test.cpp b/tests/alignment_test.cpp new file mode 100644 index 00000000000..1026fc3397c --- /dev/null +++ b/tests/alignment_test.cpp @@ -0,0 +1,31 @@ +#include "alignment_test.h" + +#include "flatbuffers/flatbuffer_builder.h" +#include "alignment_test_generated.h" +#include "test_assert.h" + +namespace flatbuffers { +namespace tests { + +void AlignmentTest() { + FlatBufferBuilder builder; + + BadAlignmentLarge large; + Offset outer_large = CreateOuterLarge(builder, &large); + + BadAlignmentSmall *small; + Offset> small_offset = + builder.CreateUninitializedVectorOfStructs(9, &small); + (void)small; // We do not have to write data to trigger the test failure + + Offset root = + CreateBadAlignmentRoot(builder, outer_large, small_offset); + + builder.Finish(root); + + Verifier verifier(builder.GetBufferPointer(), builder.GetSize()); + TEST_ASSERT(VerifyBadAlignmentRootBuffer(verifier)); +} + +} // namespace tests +} // namespace flatbuffers diff --git a/tests/alignment_test.fbs b/tests/alignment_test.fbs new file mode 100644 index 00000000000..3fc08bd7ff5 --- /dev/null +++ b/tests/alignment_test.fbs @@ -0,0 +1,24 @@ +// sizeof(BadAlignmentSmall) == 12 +// alignof(BadAlignmentSmall) == 4 +struct BadAlignmentSmall { + var_0: uint; + var_1: uint; + var_2: uint; +} + +// sizeof(BadAlignmentLarge) == 8 +// alignof(BadAlignmentLarge) == 8 +struct BadAlignmentLarge { + var_0: ulong; +} + +table OuterLarge { + large: BadAlignmentLarge; +} + +table BadAlignmentRoot { + large: OuterLarge; + small: [BadAlignmentSmall]; +} + +root_type BadAlignmentRoot; diff --git a/tests/alignment_test.h b/tests/alignment_test.h new file mode 100644 index 00000000000..68cdf0bd82e --- /dev/null +++ b/tests/alignment_test.h @@ -0,0 +1,12 @@ +#ifndef TESTS_ALIGNMENT_TEST_H +#define TESTS_ALIGNMENT_TEST_H + +namespace flatbuffers { +namespace tests { + +void AlignmentTest(); + +} // namespace tests +} // namespace flatbuffers + +#endif diff --git a/tests/alignment_test_generated.h b/tests/alignment_test_generated.h new file mode 100644 index 00000000000..416152b76cc --- /dev/null +++ b/tests/alignment_test_generated.h @@ -0,0 +1,497 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_ALIGNMENTTEST_H_ +#define FLATBUFFERS_GENERATED_ALIGNMENTTEST_H_ + +#include "flatbuffers/flatbuffers.h" + +// Ensure the included flatbuffers.h is the same version as when this file was +// generated, otherwise it may not be compatible. +static_assert(FLATBUFFERS_VERSION_MAJOR == 2 && + FLATBUFFERS_VERSION_MINOR == 0 && + FLATBUFFERS_VERSION_REVISION == 8, + "Non-compatible flatbuffers version included"); + +struct BadAlignmentSmall; + +struct BadAlignmentLarge; + +struct OuterLarge; +struct OuterLargeBuilder; +struct OuterLargeT; + +struct BadAlignmentRoot; +struct BadAlignmentRootBuilder; +struct BadAlignmentRootT; + +bool operator==(const BadAlignmentSmall &lhs, const BadAlignmentSmall &rhs); +bool operator!=(const BadAlignmentSmall &lhs, const BadAlignmentSmall &rhs); +bool operator==(const BadAlignmentLarge &lhs, const BadAlignmentLarge &rhs); +bool operator!=(const BadAlignmentLarge &lhs, const BadAlignmentLarge &rhs); +bool operator==(const OuterLargeT &lhs, const OuterLargeT &rhs); +bool operator!=(const OuterLargeT &lhs, const OuterLargeT &rhs); +bool operator==(const BadAlignmentRootT &lhs, const BadAlignmentRootT &rhs); +bool operator!=(const BadAlignmentRootT &lhs, const BadAlignmentRootT &rhs); + +inline const flatbuffers::TypeTable *BadAlignmentSmallTypeTable(); + +inline const flatbuffers::TypeTable *BadAlignmentLargeTypeTable(); + +inline const flatbuffers::TypeTable *OuterLargeTypeTable(); + +inline const flatbuffers::TypeTable *BadAlignmentRootTypeTable(); + +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) BadAlignmentSmall FLATBUFFERS_FINAL_CLASS { + private: + uint32_t var_0_; + uint32_t var_1_; + uint32_t var_2_; + + public: + static const flatbuffers::TypeTable *MiniReflectTypeTable() { + return BadAlignmentSmallTypeTable(); + } + BadAlignmentSmall() + : var_0_(0), + var_1_(0), + var_2_(0) { + } + BadAlignmentSmall(uint32_t _var_0, uint32_t _var_1, uint32_t _var_2) + : var_0_(flatbuffers::EndianScalar(_var_0)), + var_1_(flatbuffers::EndianScalar(_var_1)), + var_2_(flatbuffers::EndianScalar(_var_2)) { + } + uint32_t var_0() const { + return flatbuffers::EndianScalar(var_0_); + } + void mutate_var_0(uint32_t _var_0) { + flatbuffers::WriteScalar(&var_0_, _var_0); + } + uint32_t var_1() const { + return flatbuffers::EndianScalar(var_1_); + } + void mutate_var_1(uint32_t _var_1) { + flatbuffers::WriteScalar(&var_1_, _var_1); + } + uint32_t var_2() const { + return flatbuffers::EndianScalar(var_2_); + } + void mutate_var_2(uint32_t _var_2) { + flatbuffers::WriteScalar(&var_2_, _var_2); + } +}; +FLATBUFFERS_STRUCT_END(BadAlignmentSmall, 12); + +inline bool operator==(const BadAlignmentSmall &lhs, const BadAlignmentSmall &rhs) { + return + (lhs.var_0() == rhs.var_0()) && + (lhs.var_1() == rhs.var_1()) && + (lhs.var_2() == rhs.var_2()); +} + +inline bool operator!=(const BadAlignmentSmall &lhs, const BadAlignmentSmall &rhs) { + return !(lhs == rhs); +} + + +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) BadAlignmentLarge FLATBUFFERS_FINAL_CLASS { + private: + uint64_t var_0_; + + public: + static const flatbuffers::TypeTable *MiniReflectTypeTable() { + return BadAlignmentLargeTypeTable(); + } + BadAlignmentLarge() + : var_0_(0) { + } + BadAlignmentLarge(uint64_t _var_0) + : var_0_(flatbuffers::EndianScalar(_var_0)) { + } + uint64_t var_0() const { + return flatbuffers::EndianScalar(var_0_); + } + void mutate_var_0(uint64_t _var_0) { + flatbuffers::WriteScalar(&var_0_, _var_0); + } +}; +FLATBUFFERS_STRUCT_END(BadAlignmentLarge, 8); + +inline bool operator==(const BadAlignmentLarge &lhs, const BadAlignmentLarge &rhs) { + return + (lhs.var_0() == rhs.var_0()); +} + +inline bool operator!=(const BadAlignmentLarge &lhs, const BadAlignmentLarge &rhs) { + return !(lhs == rhs); +} + + +struct OuterLargeT : public flatbuffers::NativeTable { + typedef OuterLarge TableType; + flatbuffers::unique_ptr large{}; + OuterLargeT() = default; + OuterLargeT(const OuterLargeT &o); + OuterLargeT(OuterLargeT&&) FLATBUFFERS_NOEXCEPT = default; + OuterLargeT &operator=(OuterLargeT o) FLATBUFFERS_NOEXCEPT; +}; + +struct OuterLarge FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef OuterLargeT NativeTableType; + typedef OuterLargeBuilder Builder; + static const flatbuffers::TypeTable *MiniReflectTypeTable() { + return OuterLargeTypeTable(); + } + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_LARGE = 4 + }; + const BadAlignmentLarge *large() const { + return GetStruct(VT_LARGE); + } + BadAlignmentLarge *mutable_large() { + return GetStruct(VT_LARGE); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_LARGE, 8) && + verifier.EndTable(); + } + OuterLargeT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(OuterLargeT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const OuterLargeT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct OuterLargeBuilder { + typedef OuterLarge Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_large(const BadAlignmentLarge *large) { + fbb_.AddStruct(OuterLarge::VT_LARGE, large); + } + explicit OuterLargeBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateOuterLarge( + flatbuffers::FlatBufferBuilder &_fbb, + const BadAlignmentLarge *large = nullptr) { + OuterLargeBuilder builder_(_fbb); + builder_.add_large(large); + return builder_.Finish(); +} + +flatbuffers::Offset CreateOuterLarge(flatbuffers::FlatBufferBuilder &_fbb, const OuterLargeT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct BadAlignmentRootT : public flatbuffers::NativeTable { + typedef BadAlignmentRoot TableType; + flatbuffers::unique_ptr large{}; + std::vector small{}; + BadAlignmentRootT() = default; + BadAlignmentRootT(const BadAlignmentRootT &o); + BadAlignmentRootT(BadAlignmentRootT&&) FLATBUFFERS_NOEXCEPT = default; + BadAlignmentRootT &operator=(BadAlignmentRootT o) FLATBUFFERS_NOEXCEPT; +}; + +struct BadAlignmentRoot FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef BadAlignmentRootT NativeTableType; + typedef BadAlignmentRootBuilder Builder; + static const flatbuffers::TypeTable *MiniReflectTypeTable() { + return BadAlignmentRootTypeTable(); + } + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_LARGE = 4, + VT_SMALL = 6 + }; + const OuterLarge *large() const { + return GetPointer(VT_LARGE); + } + OuterLarge *mutable_large() { + return GetPointer(VT_LARGE); + } + const flatbuffers::Vector *small() const { + return GetPointer *>(VT_SMALL); + } + flatbuffers::Vector *mutable_small() { + return GetPointer *>(VT_SMALL); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_LARGE) && + verifier.VerifyTable(large()) && + VerifyOffset(verifier, VT_SMALL) && + verifier.VerifyVector(small()) && + verifier.EndTable(); + } + BadAlignmentRootT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(BadAlignmentRootT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const BadAlignmentRootT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct BadAlignmentRootBuilder { + typedef BadAlignmentRoot Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_large(flatbuffers::Offset large) { + fbb_.AddOffset(BadAlignmentRoot::VT_LARGE, large); + } + void add_small(flatbuffers::Offset> small) { + fbb_.AddOffset(BadAlignmentRoot::VT_SMALL, small); + } + explicit BadAlignmentRootBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateBadAlignmentRoot( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset large = 0, + flatbuffers::Offset> small = 0) { + BadAlignmentRootBuilder builder_(_fbb); + builder_.add_small(small); + builder_.add_large(large); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateBadAlignmentRootDirect( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset large = 0, + const std::vector *small = nullptr) { + auto small__ = small ? _fbb.CreateVectorOfStructs(*small) : 0; + return CreateBadAlignmentRoot( + _fbb, + large, + small__); +} + +flatbuffers::Offset CreateBadAlignmentRoot(flatbuffers::FlatBufferBuilder &_fbb, const BadAlignmentRootT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + + +inline bool operator==(const OuterLargeT &lhs, const OuterLargeT &rhs) { + return + ((lhs.large == rhs.large) || (lhs.large && rhs.large && *lhs.large == *rhs.large)); +} + +inline bool operator!=(const OuterLargeT &lhs, const OuterLargeT &rhs) { + return !(lhs == rhs); +} + + +inline OuterLargeT::OuterLargeT(const OuterLargeT &o) + : large((o.large) ? new BadAlignmentLarge(*o.large) : nullptr) { +} + +inline OuterLargeT &OuterLargeT::operator=(OuterLargeT o) FLATBUFFERS_NOEXCEPT { + std::swap(large, o.large); + return *this; +} + +inline OuterLargeT *OuterLarge::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new OuterLargeT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void OuterLarge::UnPackTo(OuterLargeT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = large(); if (_e) _o->large = flatbuffers::unique_ptr(new BadAlignmentLarge(*_e)); } +} + +inline flatbuffers::Offset OuterLarge::Pack(flatbuffers::FlatBufferBuilder &_fbb, const OuterLargeT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateOuterLarge(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateOuterLarge(flatbuffers::FlatBufferBuilder &_fbb, const OuterLargeT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const OuterLargeT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _large = _o->large ? _o->large.get() : nullptr; + return CreateOuterLarge( + _fbb, + _large); +} + + +inline bool operator==(const BadAlignmentRootT &lhs, const BadAlignmentRootT &rhs) { + return + ((lhs.large == rhs.large) || (lhs.large && rhs.large && *lhs.large == *rhs.large)) && + (lhs.small == rhs.small); +} + +inline bool operator!=(const BadAlignmentRootT &lhs, const BadAlignmentRootT &rhs) { + return !(lhs == rhs); +} + + +inline BadAlignmentRootT::BadAlignmentRootT(const BadAlignmentRootT &o) + : large((o.large) ? new OuterLargeT(*o.large) : nullptr), + small(o.small) { +} + +inline BadAlignmentRootT &BadAlignmentRootT::operator=(BadAlignmentRootT o) FLATBUFFERS_NOEXCEPT { + std::swap(large, o.large); + std::swap(small, o.small); + return *this; +} + +inline BadAlignmentRootT *BadAlignmentRoot::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::unique_ptr(new BadAlignmentRootT()); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void BadAlignmentRoot::UnPackTo(BadAlignmentRootT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = large(); if (_e) { if(_o->large) { _e->UnPackTo(_o->large.get(), _resolver); } else { _o->large = flatbuffers::unique_ptr(_e->UnPack(_resolver)); } } else if (_o->large) { _o->large.reset(); } } + { auto _e = small(); if (_e) { _o->small.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->small[_i] = *_e->Get(_i); } } else { _o->small.resize(0); } } +} + +inline flatbuffers::Offset BadAlignmentRoot::Pack(flatbuffers::FlatBufferBuilder &_fbb, const BadAlignmentRootT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateBadAlignmentRoot(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateBadAlignmentRoot(flatbuffers::FlatBufferBuilder &_fbb, const BadAlignmentRootT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const BadAlignmentRootT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _large = _o->large ? CreateOuterLarge(_fbb, _o->large.get(), _rehasher) : 0; + auto _small = _o->small.size() ? _fbb.CreateVectorOfStructs(_o->small) : 0; + return CreateBadAlignmentRoot( + _fbb, + _large, + _small); +} + +inline const flatbuffers::TypeTable *BadAlignmentSmallTypeTable() { + static const flatbuffers::TypeCode type_codes[] = { + { flatbuffers::ET_UINT, 0, -1 }, + { flatbuffers::ET_UINT, 0, -1 }, + { flatbuffers::ET_UINT, 0, -1 } + }; + static const int64_t values[] = { 0, 4, 8, 12 }; + static const char * const names[] = { + "var_0", + "var_1", + "var_2" + }; + static const flatbuffers::TypeTable tt = { + flatbuffers::ST_STRUCT, 3, type_codes, nullptr, nullptr, values, names + }; + return &tt; +} + +inline const flatbuffers::TypeTable *BadAlignmentLargeTypeTable() { + static const flatbuffers::TypeCode type_codes[] = { + { flatbuffers::ET_ULONG, 0, -1 } + }; + static const int64_t values[] = { 0, 8 }; + static const char * const names[] = { + "var_0" + }; + static const flatbuffers::TypeTable tt = { + flatbuffers::ST_STRUCT, 1, type_codes, nullptr, nullptr, values, names + }; + return &tt; +} + +inline const flatbuffers::TypeTable *OuterLargeTypeTable() { + static const flatbuffers::TypeCode type_codes[] = { + { flatbuffers::ET_SEQUENCE, 0, 0 } + }; + static const flatbuffers::TypeFunction type_refs[] = { + BadAlignmentLargeTypeTable + }; + static const char * const names[] = { + "large" + }; + static const flatbuffers::TypeTable tt = { + flatbuffers::ST_TABLE, 1, type_codes, type_refs, nullptr, nullptr, names + }; + return &tt; +} + +inline const flatbuffers::TypeTable *BadAlignmentRootTypeTable() { + static const flatbuffers::TypeCode type_codes[] = { + { flatbuffers::ET_SEQUENCE, 0, 0 }, + { flatbuffers::ET_SEQUENCE, 1, 1 } + }; + static const flatbuffers::TypeFunction type_refs[] = { + OuterLargeTypeTable, + BadAlignmentSmallTypeTable + }; + static const char * const names[] = { + "large", + "small" + }; + static const flatbuffers::TypeTable tt = { + flatbuffers::ST_TABLE, 2, type_codes, type_refs, nullptr, nullptr, names + }; + return &tt; +} + +inline const BadAlignmentRoot *GetBadAlignmentRoot(const void *buf) { + return flatbuffers::GetRoot(buf); +} + +inline const BadAlignmentRoot *GetSizePrefixedBadAlignmentRoot(const void *buf) { + return flatbuffers::GetSizePrefixedRoot(buf); +} + +inline BadAlignmentRoot *GetMutableBadAlignmentRoot(void *buf) { + return flatbuffers::GetMutableRoot(buf); +} + +inline BadAlignmentRoot *GetMutableSizePrefixedBadAlignmentRoot(void *buf) { + return flatbuffers::GetMutableSizePrefixedRoot(buf); +} + +inline bool VerifyBadAlignmentRootBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifyBuffer(nullptr); +} + +inline bool VerifySizePrefixedBadAlignmentRootBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifySizePrefixedBuffer(nullptr); +} + +inline void FinishBadAlignmentRootBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.Finish(root); +} + +inline void FinishSizePrefixedBadAlignmentRootBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.FinishSizePrefixed(root); +} + +inline flatbuffers::unique_ptr UnPackBadAlignmentRoot( + const void *buf, + const flatbuffers::resolver_function_t *res = nullptr) { + return flatbuffers::unique_ptr(GetBadAlignmentRoot(buf)->UnPack(res)); +} + +inline flatbuffers::unique_ptr UnPackSizePrefixedBadAlignmentRoot( + const void *buf, + const flatbuffers::resolver_function_t *res = nullptr) { + return flatbuffers::unique_ptr(GetSizePrefixedBadAlignmentRoot(buf)->UnPack(res)); +} + +#endif // FLATBUFFERS_GENERATED_ALIGNMENTTEST_H_ diff --git a/tests/test.cpp b/tests/test.cpp index 7e05c08ff22..60c9f5d99eb 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -20,6 +20,7 @@ #include #include "evolution_test.h" +#include "alignment_test.h" #include "flatbuffers/flatbuffers.h" #include "flatbuffers/idl.h" #include "flatbuffers/minireflect.h" @@ -1416,6 +1417,8 @@ int FlatBufferTests(const std::string &tests_data_path) { SizePrefixedTest(); + AlignmentTest(); + #ifndef FLATBUFFERS_NO_FILE_TESTS ParseAndGenerateTextTest(tests_data_path, false); ParseAndGenerateTextTest(tests_data_path, true);