From 2d5315ff0eebfa4b9c967e708c24be0b21d921b6 Mon Sep 17 00:00:00 2001 From: Alexey Geraskin Date: Fri, 2 Aug 2019 00:31:48 +0300 Subject: [PATCH] [C++] remove static_cast expression (#5440) * [C++] remove static_cast expression * [C++] Add unit test for native_type usage * [C++] Add flatc compilation for native_type_test.fbs * [C++] update CMakeLists to compile native_type_test.fbs properly * Update BUILD file for bazel * [C++] Add generated native_type_test_generated.h and fix arguments for flatc according to CMakeList * [C++] remove "= default" from constructor to support old compilers * Update BUILD file for bazel, attempt 2 * [C++] Workaround for MSVC 2010 for the issue with std::vector and explicitly aligned custom data types * Update BUILD file for bazel, attempt 3 * Update BUILD file for bazel, attempt 4 * Update BUILD file for bazel, attempt 5 * Update BUILD file for bazel, attempt 6 * [C++] Workaround for MSVC 2010 for the issue with std::vector and explicitly aligned custom data types Part 2 * [C++] Keep only one optional parameter to compile_flatbuffers_schema_to_cpp_opt * native_type_test.fbs style corrected * [C++] Code style modifications * [C++] Fix flatc arguments in CMakeLists * [C++] Remove --gen-compare from default parameters for flatc in CMakeLists * [C++] Change Vector3D fields from double to float, to have alignment eq. 4 (to support MSVC 2010), plus minor review fix * [C++] Remove one more #if !defined * [C++] Restore version with correct static_cast, add the same fix for SortedStructs * Revert "[C++] Restore version with correct static_cast, add the same fix for SortedStructs" This reverts commit d61f4d6628cfce530c8b9a4c9e7af368d599f99f. * [C++] Fix Android.mk --- BUILD | 19 ++- CMakeLists.txt | 11 +- android/jni/Android.mk | 2 + include/flatbuffers/flatbuffers.h | 3 +- tests/generate_code.bat | 1 + tests/native_type_test.fbs | 15 ++ tests/native_type_test_generated.h | 238 +++++++++++++++++++++++++++++ tests/native_type_test_impl.cpp | 13 ++ tests/native_type_test_impl.h | 24 +++ tests/test.cpp | 29 +++- 10 files changed, 348 insertions(+), 7 deletions(-) create mode 100644 tests/native_type_test.fbs create mode 100644 tests/native_type_test_generated.h create mode 100644 tests/native_type_test_impl.cpp create mode 100644 tests/native_type_test_impl.h diff --git a/BUILD b/BUILD index 6c69195fb..520f98af8 100644 --- a/BUILD +++ b/BUILD @@ -137,6 +137,8 @@ cc_test( "src/util.cpp", "tests/namespace_test/namespace_test1_generated.h", "tests/namespace_test/namespace_test2_generated.h", + "tests/native_type_test_impl.h", + "tests/native_type_test_impl.cpp", "tests/test.cpp", "tests/test_assert.cpp", "tests/test_assert.h", @@ -168,12 +170,17 @@ cc_test( ":tests/arrays_test.bfbs", ":tests/arrays_test.fbs", ":tests/arrays_test.golden", + ":tests/native_type_test.fbs", + ], + includes = [ + "include/", + "tests/", ], - includes = ["include/"], deps = [ ":monster_extra_cc_fbs", ":monster_test_cc_fbs", ":arrays_test_cc_fbs", + ":native_type_test_cc_fbs", ], ) @@ -206,3 +213,13 @@ flatbuffer_cc_library( "--cpp-ptr-type flatbuffers::unique_ptr", "--scoped-enums" ], ) + +flatbuffer_cc_library( + name = "native_type_test_cc_fbs", + srcs = ["tests/native_type_test.fbs"], + flatc_args = [ + "--gen-object-api", + "--gen-mutable", + "--cpp-ptr-type flatbuffers::unique_ptr" ], +) + diff --git a/CMakeLists.txt b/CMakeLists.txt index 029ccb5d2..7da75f41a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,10 +118,14 @@ set(FlatBuffers_Tests_SRCS tests/test_assert.cpp tests/test_builder.h tests/test_builder.cpp + tests/native_type_test_impl.h + tests/native_type_test_impl.cpp # file generate by running compiler on tests/monster_test.fbs ${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h # file generate by running compiler on tests/arrays_test.fbs ${CMAKE_CURRENT_BINARY_DIR}/tests/arrays_test_generated.h + # file generate by running compiler on tests/native_type_test.fbs + ${CMAKE_CURRENT_BINARY_DIR}/tests/native_type_test_generated.h ) set(FlatBuffers_Sample_Binary_SRCS @@ -311,8 +315,8 @@ function(compile_flatbuffers_schema_to_cpp_opt SRC_FBS OPT) string(REGEX REPLACE "\\.fbs$" "_generated.h" GEN_HEADER ${SRC_FBS}) add_custom_command( OUTPUT ${GEN_HEADER} - COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable - --gen-object-api --gen-compare -o "${SRC_FBS_DIR}" + COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --gen-mutable + --gen-object-api -o "${SRC_FBS_DIR}" --cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs --reflect-names ${OPT} -I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test" @@ -321,7 +325,7 @@ function(compile_flatbuffers_schema_to_cpp_opt SRC_FBS OPT) endfunction() function(compile_flatbuffers_schema_to_cpp SRC_FBS) - compile_flatbuffers_schema_to_cpp_opt(${SRC_FBS} "") + compile_flatbuffers_schema_to_cpp_opt(${SRC_FBS} "--no-includes;--gen-compare") endfunction() function(compile_flatbuffers_schema_to_binary SRC_FBS) @@ -336,6 +340,7 @@ endfunction() if(FLATBUFFERS_BUILD_TESTS) compile_flatbuffers_schema_to_cpp(tests/monster_test.fbs) + compile_flatbuffers_schema_to_cpp_opt(tests/native_type_test.fbs "") compile_flatbuffers_schema_to_cpp_opt(tests/arrays_test.fbs --scoped-enums) include_directories(${CMAKE_CURRENT_BINARY_DIR}/tests) add_executable(flattests ${FlatBuffers_Tests_SRCS}) diff --git a/android/jni/Android.mk b/android/jni/Android.mk index b22033269..e29c87289 100644 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -51,6 +51,8 @@ LOCAL_SRC_FILES := android/jni/main.cpp \ tests/test_builder.h \ tests/test_assert.cpp \ tests/test_builder.cpp \ + tests/native_type_test_impl.h \ + tests/native_type_test_impl.cpp \ src/idl_gen_fbs.cpp \ src/idl_gen_general.cpp LOCAL_LDLIBS := -llog -landroid -latomic diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h index f2218f333..1a250cd73 100644 --- a/include/flatbuffers/flatbuffers.h +++ b/include/flatbuffers/flatbuffers.h @@ -1653,9 +1653,8 @@ class FlatBufferBuilder { Offset> CreateVectorOfNativeStructs(const S *v, size_t len) { extern T Pack(const S &); - typedef T (*Pack_t)(const S &); std::vector vv(len); - std::transform(v, v + len, vv.begin(), static_cast(&Pack)); + std::transform(v, v + len, vv.begin(), Pack); return CreateVectorOfStructs(vv.data(), vv.size()); } diff --git a/tests/generate_code.bat b/tests/generate_code.bat index 3164dff4a..59033b8ea 100644 --- a/tests/generate_code.bat +++ b/tests/generate_code.bat @@ -22,6 +22,7 @@ if "%1"=="-b" set buildtype=%2 ..\%buildtype%\flatc.exe -b --schema --bfbs-comments --bfbs-builtins -I include_test arrays_test.fbs || goto FAIL ..\%buildtype%\flatc.exe --jsonschema --schema -I include_test monster_test.fbs || goto FAIL ..\%buildtype%\flatc.exe --cpp --java --csharp --python --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes --scoped-enums --jsonschema --cpp-ptr-type flatbuffers::unique_ptr arrays_test.fbs || goto FAIL +..\%buildtype%\flatc.exe --cpp --gen-mutable --gen-object-api --reflect-names --cpp-ptr-type flatbuffers::unique_ptr native_type_test.fbs || goto FAIL IF NOT "%MONSTER_EXTRA%"=="skip" ( @echo Generate MosterExtra diff --git a/tests/native_type_test.fbs b/tests/native_type_test.fbs new file mode 100644 index 000000000..de80bdf96 --- /dev/null +++ b/tests/native_type_test.fbs @@ -0,0 +1,15 @@ +native_include "native_type_test_impl.h"; + +namespace Geometry; + +struct Vector3D (native_type:"Native::Vector3D") { + x:float; + y:float; + z:float; +} + +table ApplicationData { + vectors:[Vector3D]; +} + +root_type ApplicationData; diff --git a/tests/native_type_test_generated.h b/tests/native_type_test_generated.h new file mode 100644 index 000000000..9ba7c61f7 --- /dev/null +++ b/tests/native_type_test_generated.h @@ -0,0 +1,238 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_NATIVETYPETEST_GEOMETRY_H_ +#define FLATBUFFERS_GENERATED_NATIVETYPETEST_GEOMETRY_H_ + +#include "flatbuffers/flatbuffers.h" + +#include "native_type_test_impl.h" + +namespace Geometry { + +struct Vector3D; + +struct ApplicationData; +struct ApplicationDataT; + +inline const flatbuffers::TypeTable *Vector3DTypeTable(); + +inline const flatbuffers::TypeTable *ApplicationDataTypeTable(); + +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vector3D FLATBUFFERS_FINAL_CLASS { + private: + float x_; + float y_; + float z_; + + public: + static const flatbuffers::TypeTable *MiniReflectTypeTable() { + return Vector3DTypeTable(); + } + Vector3D() { + memset(static_cast(this), 0, sizeof(Vector3D)); + } + Vector3D(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(Vector3D, 12); + +struct ApplicationDataT : public flatbuffers::NativeTable { + typedef ApplicationData TableType; + std::vector vectors; + ApplicationDataT() { + } +}; + +struct ApplicationData FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef ApplicationDataT NativeTableType; + static const flatbuffers::TypeTable *MiniReflectTypeTable() { + return ApplicationDataTypeTable(); + } + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_VECTORS = 4 + }; + const flatbuffers::Vector *vectors() const { + return GetPointer *>(VT_VECTORS); + } + flatbuffers::Vector *mutable_vectors() { + return GetPointer *>(VT_VECTORS); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyOffset(verifier, VT_VECTORS) && + verifier.VerifyVector(vectors()) && + verifier.EndTable(); + } + ApplicationDataT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(ApplicationDataT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const ApplicationDataT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct ApplicationDataBuilder { + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_vectors(flatbuffers::Offset> vectors) { + fbb_.AddOffset(ApplicationData::VT_VECTORS, vectors); + } + explicit ApplicationDataBuilder(flatbuffers::FlatBufferBuilder &_fbb) + : fbb_(_fbb) { + start_ = fbb_.StartTable(); + } + ApplicationDataBuilder &operator=(const ApplicationDataBuilder &); + flatbuffers::Offset Finish() { + const auto end = fbb_.EndTable(start_); + auto o = flatbuffers::Offset(end); + return o; + } +}; + +inline flatbuffers::Offset CreateApplicationData( + flatbuffers::FlatBufferBuilder &_fbb, + flatbuffers::Offset> vectors = 0) { + ApplicationDataBuilder builder_(_fbb); + builder_.add_vectors(vectors); + return builder_.Finish(); +} + +inline flatbuffers::Offset CreateApplicationDataDirect( + flatbuffers::FlatBufferBuilder &_fbb, + const std::vector *vectors = nullptr) { + auto vectors__ = vectors ? _fbb.CreateVectorOfStructs(*vectors) : 0; + return Geometry::CreateApplicationData( + _fbb, + vectors__); +} + +flatbuffers::Offset CreateApplicationData(flatbuffers::FlatBufferBuilder &_fbb, const ApplicationDataT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +inline ApplicationDataT *ApplicationData::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = new ApplicationDataT(); + UnPackTo(_o, _resolver); + return _o; +} + +inline void ApplicationData::UnPackTo(ApplicationDataT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = vectors(); if (_e) { _o->vectors.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->vectors[_i] = flatbuffers::UnPack(*_e->Get(_i)); } } }; +} + +inline flatbuffers::Offset ApplicationData::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ApplicationDataT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateApplicationData(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateApplicationData(flatbuffers::FlatBufferBuilder &_fbb, const ApplicationDataT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ApplicationDataT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _vectors = _o->vectors.size() ? _fbb.CreateVectorOfNativeStructs(_o->vectors) : 0; + return Geometry::CreateApplicationData( + _fbb, + _vectors); +} + +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, values, names + }; + return &tt; +} + +inline const flatbuffers::TypeTable *ApplicationDataTypeTable() { + static const flatbuffers::TypeCode type_codes[] = { + { flatbuffers::ET_SEQUENCE, 1, 0 } + }; + static const flatbuffers::TypeFunction type_refs[] = { + Geometry::Vector3DTypeTable + }; + static const char * const names[] = { + "vectors" + }; + static const flatbuffers::TypeTable tt = { + flatbuffers::ST_TABLE, 1, type_codes, type_refs, nullptr, names + }; + return &tt; +} + +inline const Geometry::ApplicationData *GetApplicationData(const void *buf) { + return flatbuffers::GetRoot(buf); +} + +inline const Geometry::ApplicationData *GetSizePrefixedApplicationData(const void *buf) { + return flatbuffers::GetSizePrefixedRoot(buf); +} + +inline ApplicationData *GetMutableApplicationData(void *buf) { + return flatbuffers::GetMutableRoot(buf); +} + +inline bool VerifyApplicationDataBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifyBuffer(nullptr); +} + +inline bool VerifySizePrefixedApplicationDataBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifySizePrefixedBuffer(nullptr); +} + +inline void FinishApplicationDataBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.Finish(root); +} + +inline void FinishSizePrefixedApplicationDataBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.FinishSizePrefixed(root); +} + +inline flatbuffers::unique_ptr UnPackApplicationData( + const void *buf, + const flatbuffers::resolver_function_t *res = nullptr) { + return flatbuffers::unique_ptr(GetApplicationData(buf)->UnPack(res)); +} + +inline flatbuffers::unique_ptr UnPackSizePrefixedApplicationData( + const void *buf, + const flatbuffers::resolver_function_t *res = nullptr) { + return flatbuffers::unique_ptr(GetSizePrefixedApplicationData(buf)->UnPack(res)); +} + +} // namespace Geometry + +#endif // FLATBUFFERS_GENERATED_NATIVETYPETEST_GEOMETRY_H_ diff --git a/tests/native_type_test_impl.cpp b/tests/native_type_test_impl.cpp new file mode 100644 index 000000000..04ddb9632 --- /dev/null +++ b/tests/native_type_test_impl.cpp @@ -0,0 +1,13 @@ +#include "native_type_test_impl.h" +#include "native_type_test_generated.h" + +namespace flatbuffers { + Geometry::Vector3D Pack(const Native::Vector3D &obj) { + return Geometry::Vector3D(obj.x, obj.y, obj.z); + } + + const Native::Vector3D UnPack(const Geometry::Vector3D &obj) { + return Native::Vector3D(obj.x(), obj.y(), obj.z()); + } +} + diff --git a/tests/native_type_test_impl.h b/tests/native_type_test_impl.h new file mode 100644 index 000000000..c6efff49d --- /dev/null +++ b/tests/native_type_test_impl.h @@ -0,0 +1,24 @@ +#ifndef NATIVE_TYPE_TEST_IMPL_H +#define NATIVE_TYPE_TEST_IMPL_H + +namespace Native { + struct Vector3D { + float x; + float y; + float z; + + Vector3D() { x = 0; y = 0; z = 0; }; + Vector3D(float x, float y, float z) { this->x = x; this->y = y; this->z = z; } + }; +} + +namespace Geometry { + struct Vector3D; +} + +namespace flatbuffers { + Geometry::Vector3D Pack(const Native::Vector3D &obj); + const Native::Vector3D UnPack(const Geometry::Vector3D &obj); +} + +#endif // VECTOR3D_PACK_H diff --git a/tests/test.cpp b/tests/test.cpp index 444455d01..461840c00 100644 --- a/tests/test.cpp +++ b/tests/test.cpp @@ -35,12 +35,15 @@ #include "union_vector/union_vector_generated.h" #include "monster_extra_generated.h" #if !defined(_MSC_VER) || _MSC_VER >= 1700 -# include "arrays_test_generated.h" +#include "arrays_test_generated.h" #endif + +#include "native_type_test_generated.h" #include "test_assert.h" #include "flatbuffers/flexbuffers.h" + // clang-format off // Check that char* and uint8_t* are interoperable types. // The reinterpret_cast<> between the pointers are used to simplify data loading. @@ -2867,6 +2870,29 @@ void FixedLengthArrayTest() { #endif } +void NativeTypeTest() { + const int N = 3; + + Geometry::ApplicationDataT src_data; + src_data.vectors.reserve(N); + + for (int i = 0; i < N; ++i) { + src_data.vectors.push_back (Native::Vector3D(10 * i + 0.1f, 10 * i + 0.2f, 10 * i + 0.3f)); + } + + flatbuffers::FlatBufferBuilder fbb; + fbb.Finish(Geometry::ApplicationData::Pack(fbb, &src_data)); + + auto dstDataT = Geometry::UnPackApplicationData(fbb.GetBufferPointer()); + + for (int i = 0; i < N; ++i) { + Native::Vector3D& v = dstDataT->vectors[i]; + TEST_EQ(v.x, 10 * i + 0.1f); + TEST_EQ(v.y, 10 * i + 0.2f); + TEST_EQ(v.z, 10 * i + 0.3f); + } +} + void FixedLengthArrayJsonTest(bool binary) { // VS10 does not support typed enums, exclude from tests #if !defined(_MSC_VER) || _MSC_VER >= 1700 @@ -3011,6 +3037,7 @@ int FlatBufferTests() { InvalidFloatTest(); TestMonsterExtraFloats(); FixedLengthArrayTest(); + NativeTypeTest(); return 0; }