From 8be8a0a713ebc8a12a792f63057916efc89e5fc6 Mon Sep 17 00:00:00 2001 From: Taiju Tsuiki Date: Sun, 25 Jul 2021 18:20:34 +0900 Subject: [PATCH] [C++] Fix union type handling on object api in C++17 (#6745) --- src/idl_gen_cpp.cpp | 19 +- .../generated_cpp17/monster_test_generated.h | 12 +- .../generated_cpp17/union_vector_generated.h | 844 ++++++++++++++++++ tests/cpp17/test_cpp17.cpp | 3 +- tests/evolution_test/evolution_v1_generated.h | 4 +- tests/evolution_test/evolution_v2_generated.h | 4 +- tests/generate_code.bat | 2 +- tests/generate_code.sh | 3 +- 8 files changed, 872 insertions(+), 19 deletions(-) create mode 100644 tests/cpp17/generated_cpp17/union_vector_generated.h diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index c80ec90f2..457223979 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -929,10 +929,12 @@ class CppGenerator : public BaseGenerator { } std::string UnionVectorVerifySignature(const EnumDef &enum_def) { - return "bool Verify" + Name(enum_def) + "Vector" + + auto name = Name(enum_def); + auto type = opts_.scoped_enums ? name : "uint8_t"; + return "bool Verify" + name + "Vector" + "(flatbuffers::Verifier &verifier, " + "const flatbuffers::Vector> *values, " + - "const flatbuffers::Vector *types)"; + "const flatbuffers::Vector<" + type + "> *types)"; } std::string UnionUnPackSignature(const EnumDef &enum_def, bool inclass) { @@ -2941,10 +2943,15 @@ class CppGenerator : public BaseGenerator { } case BASE_TYPE_UTYPE: { value = StripUnionType(value); - code += "_fbb.CreateVector(" + value + - ".size(), [](size_t i, _VectorArgs *__va) { " - "return static_cast(__va->_" + - value + "[i].type); }, &_va)"; + auto type = opts_.scoped_enums ? Name(*field.value.type.enum_def) + : "uint8_t"; + auto enum_value = "__va->_" + value + "[i].type"; + if (!opts_.scoped_enums) + enum_value = "static_cast(" + enum_value + ")"; + + code += "_fbb.CreateVector<" + type + ">(" + value + + ".size(), [](size_t i, _VectorArgs *__va) { return " + + enum_value + "; }, &_va)"; break; } default: { diff --git a/tests/cpp17/generated_cpp17/monster_test_generated.h b/tests/cpp17/generated_cpp17/monster_test_generated.h index 6f69ae9b6..36a46cf54 100644 --- a/tests/cpp17/generated_cpp17/monster_test_generated.h +++ b/tests/cpp17/generated_cpp17/monster_test_generated.h @@ -271,7 +271,7 @@ struct AnyUnion { }; bool VerifyAny(flatbuffers::Verifier &verifier, const void *obj, Any type); -bool VerifyAnyVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types); +bool VerifyAnyVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types); enum class AnyUniqueAliases : uint8_t { NONE = 0, @@ -384,7 +384,7 @@ struct AnyUniqueAliasesUnion { }; bool VerifyAnyUniqueAliases(flatbuffers::Verifier &verifier, const void *obj, AnyUniqueAliases type); -bool VerifyAnyUniqueAliasesVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types); +bool VerifyAnyUniqueAliasesVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types); enum class AnyAmbiguousAliases : uint8_t { NONE = 0, @@ -469,7 +469,7 @@ struct AnyAmbiguousAliasesUnion { }; bool VerifyAnyAmbiguousAliases(flatbuffers::Verifier &verifier, const void *obj, AnyAmbiguousAliases type); -bool VerifyAnyAmbiguousAliasesVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types); +bool VerifyAnyAmbiguousAliasesVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types); FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(2) Test FLATBUFFERS_FINAL_CLASS { private: @@ -2927,7 +2927,7 @@ inline bool VerifyAny(flatbuffers::Verifier &verifier, const void *obj, Any type } } -inline bool VerifyAnyVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types) { +inline bool VerifyAnyVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types) { if (!values || !types) return !values && !types; if (values->size() != types->size()) return false; for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { @@ -3038,7 +3038,7 @@ inline bool VerifyAnyUniqueAliases(flatbuffers::Verifier &verifier, const void * } } -inline bool VerifyAnyUniqueAliasesVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types) { +inline bool VerifyAnyUniqueAliasesVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types) { if (!values || !types) return !values && !types; if (values->size() != types->size()) return false; for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { @@ -3149,7 +3149,7 @@ inline bool VerifyAnyAmbiguousAliases(flatbuffers::Verifier &verifier, const voi } } -inline bool VerifyAnyAmbiguousAliasesVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types) { +inline bool VerifyAnyAmbiguousAliasesVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types) { if (!values || !types) return !values && !types; if (values->size() != types->size()) return false; for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { diff --git a/tests/cpp17/generated_cpp17/union_vector_generated.h b/tests/cpp17/generated_cpp17/union_vector_generated.h new file mode 100644 index 000000000..70097c7fa --- /dev/null +++ b/tests/cpp17/generated_cpp17/union_vector_generated.h @@ -0,0 +1,844 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_UNIONVECTOR_H_ +#define FLATBUFFERS_GENERATED_UNIONVECTOR_H_ + +#include "flatbuffers/flatbuffers.h" + +struct Attacker; +struct AttackerBuilder; +struct AttackerT; + +struct Rapunzel; + +struct BookReader; + +struct Movie; +struct MovieBuilder; +struct MovieT; + +inline const flatbuffers::TypeTable *AttackerTypeTable(); + +inline const flatbuffers::TypeTable *RapunzelTypeTable(); + +inline const flatbuffers::TypeTable *BookReaderTypeTable(); + +inline const flatbuffers::TypeTable *MovieTypeTable(); + +enum class Character : uint8_t { + NONE = 0, + MuLan = 1, + Rapunzel = 2, + Belle = 3, + BookFan = 4, + Other = 5, + Unused = 6, + MIN = NONE, + MAX = Unused +}; + +inline const Character (&EnumValuesCharacter())[7] { + static const Character values[] = { + Character::NONE, + Character::MuLan, + Character::Rapunzel, + Character::Belle, + Character::BookFan, + Character::Other, + Character::Unused + }; + return values; +} + +inline const char * const *EnumNamesCharacter() { + static const char * const names[8] = { + "NONE", + "MuLan", + "Rapunzel", + "Belle", + "BookFan", + "Other", + "Unused", + nullptr + }; + return names; +} + +inline const char *EnumNameCharacter(Character e) { + if (flatbuffers::IsOutRange(e, Character::NONE, Character::Unused)) return ""; + const size_t index = static_cast(e); + return EnumNamesCharacter()[index]; +} + +struct CharacterUnion { + Character type; + void *value; + + CharacterUnion() : type(Character::NONE), value(nullptr) {} + CharacterUnion(CharacterUnion&& u) FLATBUFFERS_NOEXCEPT : + type(Character::NONE), value(nullptr) + { std::swap(type, u.type); std::swap(value, u.value); } + CharacterUnion(const CharacterUnion &); + CharacterUnion &operator=(const CharacterUnion &u) + { CharacterUnion t(u); std::swap(type, t.type); std::swap(value, t.value); return *this; } + CharacterUnion &operator=(CharacterUnion &&u) FLATBUFFERS_NOEXCEPT + { std::swap(type, u.type); std::swap(value, u.value); return *this; } + ~CharacterUnion() { Reset(); } + + void Reset(); + + static void *UnPack(const void *obj, Character type, const flatbuffers::resolver_function_t *resolver); + flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher = nullptr) const; + + AttackerT *AsMuLan() { + return type == Character::MuLan ? + reinterpret_cast(value) : nullptr; + } + const AttackerT *AsMuLan() const { + return type == Character::MuLan ? + reinterpret_cast(value) : nullptr; + } + Rapunzel *AsRapunzel() { + return type == Character::Rapunzel ? + reinterpret_cast(value) : nullptr; + } + const Rapunzel *AsRapunzel() const { + return type == Character::Rapunzel ? + reinterpret_cast(value) : nullptr; + } + BookReader *AsBelle() { + return type == Character::Belle ? + reinterpret_cast(value) : nullptr; + } + const BookReader *AsBelle() const { + return type == Character::Belle ? + reinterpret_cast(value) : nullptr; + } + BookReader *AsBookFan() { + return type == Character::BookFan ? + reinterpret_cast(value) : nullptr; + } + const BookReader *AsBookFan() const { + return type == Character::BookFan ? + reinterpret_cast(value) : nullptr; + } + std::string *AsOther() { + return type == Character::Other ? + reinterpret_cast(value) : nullptr; + } + const std::string *AsOther() const { + return type == Character::Other ? + reinterpret_cast(value) : nullptr; + } + std::string *AsUnused() { + return type == Character::Unused ? + reinterpret_cast(value) : nullptr; + } + const std::string *AsUnused() const { + return type == Character::Unused ? + reinterpret_cast(value) : nullptr; + } +}; + +bool VerifyCharacter(flatbuffers::Verifier &verifier, const void *obj, Character type); +bool VerifyCharacterVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types); + +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Rapunzel FLATBUFFERS_FINAL_CLASS { + private: + int32_t hair_length_; + + public: + struct Traits; + static const flatbuffers::TypeTable *MiniReflectTypeTable() { + return RapunzelTypeTable(); + } + Rapunzel() + : hair_length_(0) { + } + Rapunzel(int32_t _hair_length) + : hair_length_(flatbuffers::EndianScalar(_hair_length)) { + } + int32_t hair_length() const { + return flatbuffers::EndianScalar(hair_length_); + } + void mutate_hair_length(int32_t _hair_length) { + flatbuffers::WriteScalar(&hair_length_, _hair_length); + } + template + auto get_field() const { + if constexpr (Index == 0) return hair_length(); + else static_assert(Index != Index, "Invalid Field Index"); + } +}; +FLATBUFFERS_STRUCT_END(Rapunzel, 4); + +struct Rapunzel::Traits { + using type = Rapunzel; + static constexpr auto name = "Rapunzel"; + static constexpr auto fully_qualified_name = "Rapunzel"; + static constexpr std::array field_names = { + "hair_length" + }; + template + using FieldType = decltype(std::declval().get_field()); + static constexpr size_t fields_number = 1; +}; + +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) BookReader FLATBUFFERS_FINAL_CLASS { + private: + int32_t books_read_; + + public: + struct Traits; + static const flatbuffers::TypeTable *MiniReflectTypeTable() { + return BookReaderTypeTable(); + } + BookReader() + : books_read_(0) { + } + BookReader(int32_t _books_read) + : books_read_(flatbuffers::EndianScalar(_books_read)) { + } + int32_t books_read() const { + return flatbuffers::EndianScalar(books_read_); + } + void mutate_books_read(int32_t _books_read) { + flatbuffers::WriteScalar(&books_read_, _books_read); + } + template + auto get_field() const { + if constexpr (Index == 0) return books_read(); + else static_assert(Index != Index, "Invalid Field Index"); + } +}; +FLATBUFFERS_STRUCT_END(BookReader, 4); + +struct BookReader::Traits { + using type = BookReader; + static constexpr auto name = "BookReader"; + static constexpr auto fully_qualified_name = "BookReader"; + static constexpr std::array field_names = { + "books_read" + }; + template + using FieldType = decltype(std::declval().get_field()); + static constexpr size_t fields_number = 1; +}; + +struct AttackerT : public flatbuffers::NativeTable { + typedef Attacker TableType; + int32_t sword_attack_damage = 0; +}; + +struct Attacker FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef AttackerT NativeTableType; + typedef AttackerBuilder Builder; + struct Traits; + static const flatbuffers::TypeTable *MiniReflectTypeTable() { + return AttackerTypeTable(); + } + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_SWORD_ATTACK_DAMAGE = 4 + }; + int32_t sword_attack_damage() const { + return GetField(VT_SWORD_ATTACK_DAMAGE, 0); + } + bool mutate_sword_attack_damage(int32_t _sword_attack_damage) { + return SetField(VT_SWORD_ATTACK_DAMAGE, _sword_attack_damage, 0); + } + template + auto get_field() const { + if constexpr (Index == 0) return sword_attack_damage(); + else static_assert(Index != Index, "Invalid Field Index"); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_SWORD_ATTACK_DAMAGE) && + verifier.EndTable(); + } + AttackerT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(AttackerT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const AttackerT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct AttackerBuilder { + typedef Attacker Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_sword_attack_damage(int32_t sword_attack_damage) { + fbb_.AddElement(Attacker::VT_SWORD_ATTACK_DAMAGE, sword_attack_damage, 0); + } + explicit AttackerBuilder(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 CreateAttacker( + flatbuffers::FlatBufferBuilder &_fbb, + int32_t sword_attack_damage = 0) { + AttackerBuilder builder_(_fbb); + builder_.add_sword_attack_damage(sword_attack_damage); + return builder_.Finish(); +} + +struct Attacker::Traits { + using type = Attacker; + static auto constexpr Create = CreateAttacker; + static constexpr auto name = "Attacker"; + static constexpr auto fully_qualified_name = "Attacker"; + static constexpr std::array field_names = { + "sword_attack_damage" + }; + template + using FieldType = decltype(std::declval().get_field()); + static constexpr size_t fields_number = 1; +}; + +flatbuffers::Offset CreateAttacker(flatbuffers::FlatBufferBuilder &_fbb, const AttackerT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +struct MovieT : public flatbuffers::NativeTable { + typedef Movie TableType; + CharacterUnion main_character{}; + std::vector characters{}; +}; + +struct Movie FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { + typedef MovieT NativeTableType; + typedef MovieBuilder Builder; + struct Traits; + static const flatbuffers::TypeTable *MiniReflectTypeTable() { + return MovieTypeTable(); + } + enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { + VT_MAIN_CHARACTER_TYPE = 4, + VT_MAIN_CHARACTER = 6, + VT_CHARACTERS_TYPE = 8, + VT_CHARACTERS = 10 + }; + Character main_character_type() const { + return static_cast(GetField(VT_MAIN_CHARACTER_TYPE, 0)); + } + const void *main_character() const { + return GetPointer(VT_MAIN_CHARACTER); + } + const Attacker *main_character_as_MuLan() const { + return main_character_type() == Character::MuLan ? static_cast(main_character()) : nullptr; + } + const Rapunzel *main_character_as_Rapunzel() const { + return main_character_type() == Character::Rapunzel ? static_cast(main_character()) : nullptr; + } + const BookReader *main_character_as_Belle() const { + return main_character_type() == Character::Belle ? static_cast(main_character()) : nullptr; + } + const BookReader *main_character_as_BookFan() const { + return main_character_type() == Character::BookFan ? static_cast(main_character()) : nullptr; + } + const flatbuffers::String *main_character_as_Other() const { + return main_character_type() == Character::Other ? static_cast(main_character()) : nullptr; + } + const flatbuffers::String *main_character_as_Unused() const { + return main_character_type() == Character::Unused ? static_cast(main_character()) : nullptr; + } + void *mutable_main_character() { + return GetPointer(VT_MAIN_CHARACTER); + } + const flatbuffers::Vector *characters_type() const { + return GetPointer *>(VT_CHARACTERS_TYPE); + } + flatbuffers::Vector *mutable_characters_type() { + return GetPointer *>(VT_CHARACTERS_TYPE); + } + const flatbuffers::Vector> *characters() const { + return GetPointer> *>(VT_CHARACTERS); + } + flatbuffers::Vector> *mutable_characters() { + return GetPointer> *>(VT_CHARACTERS); + } + template + auto get_field() const { + if constexpr (Index == 0) return main_character_type(); + else if constexpr (Index == 1) return main_character(); + else if constexpr (Index == 2) return characters_type(); + else if constexpr (Index == 3) return characters(); + else static_assert(Index != Index, "Invalid Field Index"); + } + bool Verify(flatbuffers::Verifier &verifier) const { + return VerifyTableStart(verifier) && + VerifyField(verifier, VT_MAIN_CHARACTER_TYPE) && + VerifyOffset(verifier, VT_MAIN_CHARACTER) && + VerifyCharacter(verifier, main_character(), main_character_type()) && + VerifyOffset(verifier, VT_CHARACTERS_TYPE) && + verifier.VerifyVector(characters_type()) && + VerifyOffset(verifier, VT_CHARACTERS) && + verifier.VerifyVector(characters()) && + VerifyCharacterVector(verifier, characters(), characters_type()) && + verifier.EndTable(); + } + MovieT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; + void UnPackTo(MovieT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const; + static flatbuffers::Offset Pack(flatbuffers::FlatBufferBuilder &_fbb, const MovieT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); +}; + +struct MovieBuilder { + typedef Movie Table; + flatbuffers::FlatBufferBuilder &fbb_; + flatbuffers::uoffset_t start_; + void add_main_character_type(Character main_character_type) { + fbb_.AddElement(Movie::VT_MAIN_CHARACTER_TYPE, static_cast(main_character_type), 0); + } + void add_main_character(flatbuffers::Offset main_character) { + fbb_.AddOffset(Movie::VT_MAIN_CHARACTER, main_character); + } + void add_characters_type(flatbuffers::Offset> characters_type) { + fbb_.AddOffset(Movie::VT_CHARACTERS_TYPE, characters_type); + } + void add_characters(flatbuffers::Offset>> characters) { + fbb_.AddOffset(Movie::VT_CHARACTERS, characters); + } + explicit MovieBuilder(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 CreateMovie( + flatbuffers::FlatBufferBuilder &_fbb, + Character main_character_type = Character::NONE, + flatbuffers::Offset main_character = 0, + flatbuffers::Offset> characters_type = 0, + flatbuffers::Offset>> characters = 0) { + MovieBuilder builder_(_fbb); + builder_.add_characters(characters); + builder_.add_characters_type(characters_type); + builder_.add_main_character(main_character); + builder_.add_main_character_type(main_character_type); + return builder_.Finish(); +} + +struct Movie::Traits { + using type = Movie; + static auto constexpr Create = CreateMovie; + static constexpr auto name = "Movie"; + static constexpr auto fully_qualified_name = "Movie"; + static constexpr std::array field_names = { + "main_character_type", + "main_character", + "characters_type", + "characters" + }; + template + using FieldType = decltype(std::declval().get_field()); + static constexpr size_t fields_number = 4; +}; + +inline flatbuffers::Offset CreateMovieDirect( + flatbuffers::FlatBufferBuilder &_fbb, + Character main_character_type = Character::NONE, + flatbuffers::Offset main_character = 0, + const std::vector *characters_type = nullptr, + const std::vector> *characters = nullptr) { + auto characters_type__ = characters_type ? _fbb.CreateVector(*characters_type) : 0; + auto characters__ = characters ? _fbb.CreateVector>(*characters) : 0; + return CreateMovie( + _fbb, + main_character_type, + main_character, + characters_type__, + characters__); +} + +flatbuffers::Offset CreateMovie(flatbuffers::FlatBufferBuilder &_fbb, const MovieT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); + +inline AttackerT *Attacker::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::make_unique(); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void Attacker::UnPackTo(AttackerT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = sword_attack_damage(); _o->sword_attack_damage = _e; } +} + +inline flatbuffers::Offset Attacker::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AttackerT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateAttacker(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateAttacker(flatbuffers::FlatBufferBuilder &_fbb, const AttackerT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const AttackerT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _sword_attack_damage = _o->sword_attack_damage; + return CreateAttacker( + _fbb, + _sword_attack_damage); +} + +inline MovieT *Movie::UnPack(const flatbuffers::resolver_function_t *_resolver) const { + auto _o = std::make_unique(); + UnPackTo(_o.get(), _resolver); + return _o.release(); +} + +inline void Movie::UnPackTo(MovieT *_o, const flatbuffers::resolver_function_t *_resolver) const { + (void)_o; + (void)_resolver; + { auto _e = main_character_type(); _o->main_character.type = _e; } + { auto _e = main_character(); if (_e) _o->main_character.value = CharacterUnion::UnPack(_e, main_character_type(), _resolver); } + { auto _e = characters_type(); if (_e) { _o->characters.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->characters[_i].type = static_cast(_e->Get(_i)); } } } + { auto _e = characters(); if (_e) { _o->characters.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->characters[_i].value = CharacterUnion::UnPack(_e->Get(_i), characters_type()->GetEnum(_i), _resolver); } } } +} + +inline flatbuffers::Offset Movie::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MovieT* _o, const flatbuffers::rehasher_function_t *_rehasher) { + return CreateMovie(_fbb, _o, _rehasher); +} + +inline flatbuffers::Offset CreateMovie(flatbuffers::FlatBufferBuilder &_fbb, const MovieT *_o, const flatbuffers::rehasher_function_t *_rehasher) { + (void)_rehasher; + (void)_o; + struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MovieT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; + auto _main_character_type = _o->main_character.type; + auto _main_character = _o->main_character.Pack(_fbb); + auto _characters_type = _o->characters.size() ? _fbb.CreateVector(_o->characters.size(), [](size_t i, _VectorArgs *__va) { return __va->__o->characters[i].type; }, &_va) : 0; + auto _characters = _o->characters.size() ? _fbb.CreateVector>(_o->characters.size(), [](size_t i, _VectorArgs *__va) { return __va->__o->characters[i].Pack(*__va->__fbb, __va->__rehasher); }, &_va) : 0; + return CreateMovie( + _fbb, + _main_character_type, + _main_character, + _characters_type, + _characters); +} + +inline bool VerifyCharacter(flatbuffers::Verifier &verifier, const void *obj, Character type) { + switch (type) { + case Character::NONE: { + return true; + } + case Character::MuLan: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyTable(ptr); + } + case Character::Rapunzel: { + return verifier.Verify(static_cast(obj), 0); + } + case Character::Belle: { + return verifier.Verify(static_cast(obj), 0); + } + case Character::BookFan: { + return verifier.Verify(static_cast(obj), 0); + } + case Character::Other: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyString(ptr); + } + case Character::Unused: { + auto ptr = reinterpret_cast(obj); + return verifier.VerifyString(ptr); + } + default: return true; + } +} + +inline bool VerifyCharacterVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types) { + if (!values || !types) return !values && !types; + if (values->size() != types->size()) return false; + for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { + if (!VerifyCharacter( + verifier, values->Get(i), types->GetEnum(i))) { + return false; + } + } + return true; +} + +inline void *CharacterUnion::UnPack(const void *obj, Character type, const flatbuffers::resolver_function_t *resolver) { + switch (type) { + case Character::MuLan: { + auto ptr = reinterpret_cast(obj); + return ptr->UnPack(resolver); + } + case Character::Rapunzel: { + auto ptr = reinterpret_cast(obj); + return new Rapunzel(*ptr); + } + case Character::Belle: { + auto ptr = reinterpret_cast(obj); + return new BookReader(*ptr); + } + case Character::BookFan: { + auto ptr = reinterpret_cast(obj); + return new BookReader(*ptr); + } + case Character::Other: { + auto ptr = reinterpret_cast(obj); + return new std::string(ptr->c_str(), ptr->size()); + } + case Character::Unused: { + auto ptr = reinterpret_cast(obj); + return new std::string(ptr->c_str(), ptr->size()); + } + default: return nullptr; + } +} + +inline flatbuffers::Offset CharacterUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher) const { + switch (type) { + case Character::MuLan: { + auto ptr = reinterpret_cast(value); + return CreateAttacker(_fbb, ptr, _rehasher).Union(); + } + case Character::Rapunzel: { + auto ptr = reinterpret_cast(value); + return _fbb.CreateStruct(*ptr).Union(); + } + case Character::Belle: { + auto ptr = reinterpret_cast(value); + return _fbb.CreateStruct(*ptr).Union(); + } + case Character::BookFan: { + auto ptr = reinterpret_cast(value); + return _fbb.CreateStruct(*ptr).Union(); + } + case Character::Other: { + auto ptr = reinterpret_cast(value); + return _fbb.CreateString(*ptr).Union(); + } + case Character::Unused: { + auto ptr = reinterpret_cast(value); + return _fbb.CreateString(*ptr).Union(); + } + default: return 0; + } +} + +inline CharacterUnion::CharacterUnion(const CharacterUnion &u) : type(u.type), value(nullptr) { + switch (type) { + case Character::MuLan: { + value = new AttackerT(*reinterpret_cast(u.value)); + break; + } + case Character::Rapunzel: { + value = new Rapunzel(*reinterpret_cast(u.value)); + break; + } + case Character::Belle: { + value = new BookReader(*reinterpret_cast(u.value)); + break; + } + case Character::BookFan: { + value = new BookReader(*reinterpret_cast(u.value)); + break; + } + case Character::Other: { + value = new std::string(*reinterpret_cast(u.value)); + break; + } + case Character::Unused: { + value = new std::string(*reinterpret_cast(u.value)); + break; + } + default: + break; + } +} + +inline void CharacterUnion::Reset() { + switch (type) { + case Character::MuLan: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case Character::Rapunzel: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case Character::Belle: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case Character::BookFan: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case Character::Other: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + case Character::Unused: { + auto ptr = reinterpret_cast(value); + delete ptr; + break; + } + default: break; + } + value = nullptr; + type = Character::NONE; +} + +inline const flatbuffers::TypeTable *CharacterTypeTable() { + static const flatbuffers::TypeCode type_codes[] = { + { flatbuffers::ET_SEQUENCE, 0, -1 }, + { flatbuffers::ET_SEQUENCE, 0, 0 }, + { flatbuffers::ET_SEQUENCE, 0, 1 }, + { flatbuffers::ET_SEQUENCE, 0, 2 }, + { flatbuffers::ET_SEQUENCE, 0, 2 }, + { flatbuffers::ET_STRING, 0, -1 }, + { flatbuffers::ET_STRING, 0, -1 } + }; + static const flatbuffers::TypeFunction type_refs[] = { + AttackerTypeTable, + RapunzelTypeTable, + BookReaderTypeTable + }; + static const char * const names[] = { + "NONE", + "MuLan", + "Rapunzel", + "Belle", + "BookFan", + "Other", + "Unused" + }; + static const flatbuffers::TypeTable tt = { + flatbuffers::ST_UNION, 7, type_codes, type_refs, nullptr, nullptr, names + }; + return &tt; +} + +inline const flatbuffers::TypeTable *AttackerTypeTable() { + static const flatbuffers::TypeCode type_codes[] = { + { flatbuffers::ET_INT, 0, -1 } + }; + static const char * const names[] = { + "sword_attack_damage" + }; + static const flatbuffers::TypeTable tt = { + flatbuffers::ST_TABLE, 1, type_codes, nullptr, nullptr, nullptr, names + }; + return &tt; +} + +inline const flatbuffers::TypeTable *RapunzelTypeTable() { + static const flatbuffers::TypeCode type_codes[] = { + { flatbuffers::ET_INT, 0, -1 } + }; + static const int64_t values[] = { 0, 4 }; + static const char * const names[] = { + "hair_length" + }; + static const flatbuffers::TypeTable tt = { + flatbuffers::ST_STRUCT, 1, type_codes, nullptr, nullptr, values, names + }; + return &tt; +} + +inline const flatbuffers::TypeTable *BookReaderTypeTable() { + static const flatbuffers::TypeCode type_codes[] = { + { flatbuffers::ET_INT, 0, -1 } + }; + static const int64_t values[] = { 0, 4 }; + static const char * const names[] = { + "books_read" + }; + static const flatbuffers::TypeTable tt = { + flatbuffers::ST_STRUCT, 1, type_codes, nullptr, nullptr, values, names + }; + return &tt; +} + +inline const flatbuffers::TypeTable *MovieTypeTable() { + static const flatbuffers::TypeCode type_codes[] = { + { flatbuffers::ET_UTYPE, 0, 0 }, + { flatbuffers::ET_SEQUENCE, 0, 0 }, + { flatbuffers::ET_UTYPE, 1, 0 }, + { flatbuffers::ET_SEQUENCE, 1, 0 } + }; + static const flatbuffers::TypeFunction type_refs[] = { + CharacterTypeTable + }; + static const char * const names[] = { + "main_character_type", + "main_character", + "characters_type", + "characters" + }; + static const flatbuffers::TypeTable tt = { + flatbuffers::ST_TABLE, 4, type_codes, type_refs, nullptr, nullptr, names + }; + return &tt; +} + +inline const Movie *GetMovie(const void *buf) { + return flatbuffers::GetRoot(buf); +} + +inline const Movie *GetSizePrefixedMovie(const void *buf) { + return flatbuffers::GetSizePrefixedRoot(buf); +} + +inline Movie *GetMutableMovie(void *buf) { + return flatbuffers::GetMutableRoot(buf); +} + +inline const char *MovieIdentifier() { + return "MOVI"; +} + +inline bool MovieBufferHasIdentifier(const void *buf) { + return flatbuffers::BufferHasIdentifier( + buf, MovieIdentifier()); +} + +inline bool VerifyMovieBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifyBuffer(MovieIdentifier()); +} + +inline bool VerifySizePrefixedMovieBuffer( + flatbuffers::Verifier &verifier) { + return verifier.VerifySizePrefixedBuffer(MovieIdentifier()); +} + +inline void FinishMovieBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.Finish(root, MovieIdentifier()); +} + +inline void FinishSizePrefixedMovieBuffer( + flatbuffers::FlatBufferBuilder &fbb, + flatbuffers::Offset root) { + fbb.FinishSizePrefixed(root, MovieIdentifier()); +} + +inline std::unique_ptr UnPackMovie( + const void *buf, + const flatbuffers::resolver_function_t *res = nullptr) { + return std::unique_ptr(GetMovie(buf)->UnPack(res)); +} + +inline std::unique_ptr UnPackSizePrefixedMovie( + const void *buf, + const flatbuffers::resolver_function_t *res = nullptr) { + return std::unique_ptr(GetSizePrefixedMovie(buf)->UnPack(res)); +} + +#endif // FLATBUFFERS_GENERATED_UNIONVECTOR_H_ diff --git a/tests/cpp17/test_cpp17.cpp b/tests/cpp17/test_cpp17.cpp index 47083d383..a17205a68 100644 --- a/tests/cpp17/test_cpp17.cpp +++ b/tests/cpp17/test_cpp17.cpp @@ -15,7 +15,7 @@ */ // This is a sandbox for modeling C++17 code generator. -// C++17 code generator: "flatc --cpp_std c++17". +// C++17 code generator: "flatc --cpp-std c++17". // Warning: // This is an experimental feature and could change at any time. @@ -32,6 +32,7 @@ namespace cpp17 { #include "generated_cpp17/monster_test_generated.h" #include "generated_cpp17/optional_scalars_generated.h" +#include "generated_cpp17/union_vector_generated.h" } // namespace cpp17 namespace cpp11 { diff --git a/tests/evolution_test/evolution_v1_generated.h b/tests/evolution_test/evolution_v1_generated.h index a9c2b7f7f..4fd5f50df 100644 --- a/tests/evolution_test/evolution_v1_generated.h +++ b/tests/evolution_test/evolution_v1_generated.h @@ -96,7 +96,7 @@ template<> struct UnionTraits { }; bool VerifyUnion(flatbuffers::Verifier &verifier, const void *obj, Union type); -bool VerifyUnionVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types); +bool VerifyUnionVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types); FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Struct FLATBUFFERS_FINAL_CLASS { private: @@ -465,7 +465,7 @@ inline bool VerifyUnion(flatbuffers::Verifier &verifier, const void *obj, Union } } -inline bool VerifyUnionVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types) { +inline bool VerifyUnionVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types) { if (!values || !types) return !values && !types; if (values->size() != types->size()) return false; for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { diff --git a/tests/evolution_test/evolution_v2_generated.h b/tests/evolution_test/evolution_v2_generated.h index 303d94d6c..940b35e98 100644 --- a/tests/evolution_test/evolution_v2_generated.h +++ b/tests/evolution_test/evolution_v2_generated.h @@ -112,7 +112,7 @@ template<> struct UnionTraits { }; bool VerifyUnion(flatbuffers::Verifier &verifier, const void *obj, Union type); -bool VerifyUnionVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types); +bool VerifyUnionVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types); FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(8) Struct FLATBUFFERS_FINAL_CLASS { private: @@ -552,7 +552,7 @@ inline bool VerifyUnion(flatbuffers::Verifier &verifier, const void *obj, Union } } -inline bool VerifyUnionVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types) { +inline bool VerifyUnionVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector> *values, const flatbuffers::Vector *types) { if (!values || !types) return !values && !types; if (values->size() != types->size()) return false; for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) { diff --git a/tests/generate_code.bat b/tests/generate_code.bat index 49301bf8d..16a285c12 100644 --- a/tests/generate_code.bat +++ b/tests/generate_code.bat @@ -87,7 +87,7 @@ if NOT "%MONSTER_EXTRA%"=="skip" ( @rem..\%buildtype%\flatc.exe %TEST_CPP17_FLAGS% arrays_test.fbs || goto FAIL @rem..\%buildtype%\flatc.exe %TEST_CPP17_FLAGS% native_type_test.fbs || goto FAIL @rem..\%buildtype%\flatc.exe %TEST_CPP17_FLAGS% monster_extra.fbs || goto FAIL - @rem..\%buildtype%\flatc.exe %TEST_CPP17_FLAGS% ./union_vector/union_vector.fbs || goto FAIL + ..\%buildtype%\flatc.exe %TEST_CPP17_FLAGS% ./union_vector/union_vector.fbs || goto FAIL ) cd ../samples diff --git a/tests/generate_code.sh b/tests/generate_code.sh index c7d68d3a1..5e99e7c43 100755 --- a/tests/generate_code.sh +++ b/tests/generate_code.sh @@ -94,9 +94,10 @@ else fi # Flag c++17 requires Clang6, GCC7, MSVC2017 (_MSC_VER >= 1914) or higher. -TEST_CPP17_FLAGS="--cpp --cpp-std c++17 --cpp-static-reflection -o ./cpp17/generated_cpp17 $TEST_NOINCL_FLAGS" +TEST_CPP17_FLAGS="--cpp --cpp-std c++17 --cpp-static-reflection --gen-object-api -o ./cpp17/generated_cpp17 $TEST_NOINCL_FLAGS" ../flatc $TEST_CPP17_FLAGS -I include_test monster_test.fbs ../flatc $TEST_CPP17_FLAGS optional_scalars.fbs +../flatc $TEST_CPP17_FLAGS union_vector/union_vector.fbs cd ../samples ../flatc --cpp --lobster $TEST_BASE_FLAGS $TEST_CPP_FLAGS monster.fbs