From 4b5a7c1eedcc60e18abf1b9ad5fc244ee81c2727 Mon Sep 17 00:00:00 2001 From: Cedric Athanasiades Date: Sun, 10 Nov 2024 10:25:05 +0100 Subject: [PATCH 1/2] feat: add constant primitives support array length, default values, and constant primitive initialization fixup! feat: add constant primitives fixup! feat: add constant primitives --- include/flatbuffers/idl.h | 16 ++++++-- src/idl_gen_cpp.cpp | 13 ++++++ src/idl_parser.cpp | 84 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 104 insertions(+), 9 deletions(-) diff --git a/include/flatbuffers/idl.h b/include/flatbuffers/idl.h index c84999a5485..5029975976f 100644 --- a/include/flatbuffers/idl.h +++ b/include/flatbuffers/idl.h @@ -186,6 +186,7 @@ inline const char* StringOf(const BaseType t) { // clang-format on struct StructDef; +struct ConstPrimDef; struct EnumDef; class Parser; @@ -346,7 +347,7 @@ struct FieldDef : public Definition { return IsScalar() && IsOptional(); } bool IsScalar() const { - return ::flatbuffers::IsScalar(value.type.base_type); + return ::flatbuffers::IsScalar(value.type.base_type); } bool IsOptional() const { return presence == kOptional; } bool IsRequired() const { return presence == kRequired; } @@ -425,6 +426,10 @@ struct StructDef : public Definition { std::vector reserved_ids; }; +struct ConstPrimDef : public Definition { + Value value; +}; + struct EnumDef; struct EnumValBuilder; @@ -1103,6 +1108,9 @@ class Parser : public ParserState { FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id, std::string *last); FLATBUFFERS_CHECKED_ERROR ParseTypeIdent(Type &type); + FLATBUFFERS_CHECKED_ERROR ConstantPrimLookUp( + const std::string const_prim_name, Value *val); + bool IsConstantPrimLookUp(const std::string const_prim_name); FLATBUFFERS_CHECKED_ERROR ParseType(Type &type); FLATBUFFERS_CHECKED_ERROR AddField(StructDef &struct_def, const std::string &name, const Type &type, @@ -1154,6 +1162,7 @@ class Parser : public ParserState { FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name, bool is_union, EnumDef **dest); FLATBUFFERS_CHECKED_ERROR ParseDecl(const char *filename); + FLATBUFFERS_CHECKED_ERROR ParseConstPrim(); FLATBUFFERS_CHECKED_ERROR ParseService(const char *filename); FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def, bool isextend, bool inside_oneof); @@ -1202,6 +1211,7 @@ class Parser : public ParserState { public: SymbolTable types_; SymbolTable structs_; + SymbolTable const_prims_; SymbolTable enums_; SymbolTable services_; std::vector namespaces_; @@ -1256,8 +1266,8 @@ class Parser : public ParserState { // it contains non-UTF-8 byte arrays in String values). extern bool GenerateTextFromTable(const Parser &parser, const void *table, - const std::string &tablename, - std::string *text); + const std::string &tablename, + std::string *text); extern const char *GenerateText(const Parser &parser, const void *flatbuffer, std::string *text); extern const char *GenerateTextFile(const Parser &parser, diff --git a/src/idl_gen_cpp.cpp b/src/idl_gen_cpp.cpp index 06571693286..97ded1442cc 100644 --- a/src/idl_gen_cpp.cpp +++ b/src/idl_gen_cpp.cpp @@ -456,6 +456,19 @@ class CppGenerator : public BaseGenerator { FLATBUFFERS_ASSERT(!cur_name_space_); + // Generate definition for all constant primitives + for (const auto &const_prim_def : parser_.const_prims_.vec) { + if (!const_prim_def->generated) { + SetNameSpace(const_prim_def->defined_namespace); + code_ += "constexpr " + GenTypeBasic(const_prim_def->value.type, true) + + " " + Name(*const_prim_def) + " = " + + NumToStringCpp(const_prim_def->value.constant, + const_prim_def->value.type.base_type) + + ";"; + } + } + if (parser_.const_prims_.vec.size() > 0) { code_ += ""; } + // Generate forward declarations for all structs/tables, since they may // have circular references. for (const auto &struct_def : parser_.structs_.vec) { diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp index d01e18ef761..450984fe862 100644 --- a/src/idl_parser.cpp +++ b/src/idl_parser.cpp @@ -793,6 +793,24 @@ CheckedError Parser::ParseTypeIdent(Type &type) { return NoError(); } +bool Parser::IsConstantPrimLookUp(const std::string const_prim_name) { + for (const auto const_prim_def : const_prims_.vec) { + if (const_prim_def->name.compare(const_prim_name) == 0) { return true; } + } + return false; +} + +CheckedError Parser::ConstantPrimLookUp(const std::string const_prim_name, + Value *val) { + for (const auto const_prim_def : const_prims_.vec) { + if (const_prim_def->name.compare(const_prim_name) == 0) { + *val = const_prim_def->value; + return NoError(); + } + } + return Error("Constant primitive doesn't exist: " + const_prim_name); +} + // Parse any IDL type. CheckedError Parser::ParseType(Type &type) { if (token_ == kTokenIdentifier) { @@ -848,11 +866,19 @@ CheckedError Parser::ParseType(Type &type) { } if (token_ == ':') { NEXT(); - if (token_ != kTokenIntegerConstant) { - return Error("length of fixed-length array must be an integer value"); - } uint16_t fixed_length = 0; - bool check = StringToNumber(attribute_.c_str(), &fixed_length); + bool check = true; + if (token_ == kTokenIdentifier) { + Value value; + ECHECK(ConstantPrimLookUp(attribute_, &value)); + check = StringToNumber(value.constant.c_str(), &fixed_length); + } else if (token_ != kTokenIntegerConstant) { + return Error( + "length of fixed-length array must be an integer value (or a " + "constant primitive)"); + } else { + check = StringToNumber(attribute_.c_str(), &fixed_length); + } if (!check || fixed_length < 1) { return Error( "length of fixed-length array must be positive and fit to " @@ -952,7 +978,7 @@ CheckedError Parser::ParseField(StructDef &struct_def) { Type union_type(type.enum_def->underlying_type); union_type.base_type = BASE_TYPE_UTYPE; ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(),union_type, &typefield)); - + } else if (IsVector(type) && type.element == BASE_TYPE_UNION) { advanced_features_ |= reflection::AdvancedUnionFeatures; // Only cpp, js and ts supports the union vector feature so far. @@ -982,7 +1008,15 @@ CheckedError Parser::ParseField(StructDef &struct_def) { if (token_ == '=') { NEXT(); - ECHECK(ParseSingleValue(&field->name, field->value, true)); + if (token_ == kTokenIdentifier && IsConstantPrimLookUp(attribute_)) { + Value value; + ECHECK(ConstantPrimLookUp(attribute_, &value)); + NEXT(); + field->value.type = value.type; + field->value.constant = value.constant; + } else { + ECHECK(ParseSingleValue(&field->name, field->value, true)); + } if (IsStruct(type) || (struct_def.fixed && field->value.constant != "0")) return Error( "default values are not supported for struct fields, table fields, " @@ -2844,6 +2878,39 @@ CheckedError Parser::ParseDecl(const char *filename) { return NoError(); } +CheckedError Parser::ParseConstPrim() { + auto &const_prim_def = *new ConstPrimDef(); + const_prim_def.defined_namespace = current_namespace_; + NEXT(); + auto name = attribute_; + const_prim_def.name = name; + EXPECT(kTokenIdentifier); + EXPECT(':'); + ECHECK(ParseType(const_prim_def.value.type)); + if (!(IsScalar(const_prim_def.value.type + .base_type) /*|| IsString(const_prim_def.value.type)*/)) { + return Error("constant primitive can only be scalar" /*+ "or string"*/); + } + EXPECT('='); + Value value; + if (token_ == kTokenIdentifier && IsConstantPrimLookUp(attribute_)) { + ECHECK(ConstantPrimLookUp(attribute_, &value)) + NEXT(); + } else { + value.type = const_prim_def.value.type; + ECHECK(ParseSingleValue(&const_prim_def.name, value, true)); + } + const_prim_def.value.type = value.type; + const_prim_def.value.constant = value.constant; + EXPECT(';'); + + const auto qualified_name = + current_namespace_->GetFullyQualifiedName(const_prim_def.name); + if (const_prims_.Add(qualified_name, &const_prim_def)) + return Error("constant primitive already exists: " + qualified_name); + return NoError(); +} + CheckedError Parser::ParseService(const char *filename) { std::vector service_comment = doc_comment_; NEXT(); @@ -2902,6 +2969,9 @@ void Parser::MarkGenerated() { // This function marks all existing definitions as having already // been generated, which signals no code for included files should be // generated. + for (auto it = const_prims_.vec.begin(); it != const_prims_.vec.end(); ++it) { + (*it)->generated = true; + } for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { (*it)->generated = true; } @@ -3795,6 +3865,8 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths, known_attributes_[name] = false; } else if (IsIdent("rpc_service")) { ECHECK(ParseService(source_filename)); + } else if (IsIdent("const")) { + ECHECK(ParseConstPrim()); } else { ECHECK(ParseDecl(source_filename)); } From 50c87907e5043c5d7281d4393b518fdc08abe017 Mon Sep 17 00:00:00 2001 From: Cedric Athanasiades Date: Sun, 10 Nov 2024 13:53:07 +0100 Subject: [PATCH 2/2] docs: update doc, tuto, and sample to include constant primitives --- docs/source/Schemas.md | 13 ++- docs/source/Tutorial.md | 13 ++- samples/monster.fbs | 17 ++- samples/monster_generated.h | 226 +++++++++++++++++++++++++++++++----- 4 files changed, 233 insertions(+), 36 deletions(-) diff --git a/docs/source/Schemas.md b/docs/source/Schemas.md index f049cf40b9d..a6c85f94c50 100644 --- a/docs/source/Schemas.md +++ b/docs/source/Schemas.md @@ -12,6 +12,8 @@ first: attribute "priority"; + const MAX_MANA:short = 150; + enum Color : byte { Red = 1, Green, Blue } union Any { Monster, Weapon, Pickup } @@ -24,7 +26,7 @@ first: table Monster { pos:Vec3; - mana:short = 150; + mana:short = MAX_MANA; hp:short = 100; name:string; friendly:bool = false (deprecated, priority: 1); @@ -217,6 +219,15 @@ Monster table. There is also experimental support for other types besides tables in unions, in particular structs and strings. There's no direct support for scalars in unions, but they can be wrapped in a struct at no space cost. +### Constant primitives + +Defines a (scalar) constant that can be used within the schema itself. It is declared using the +keyword `const` followed by the `NAME`, the (mandatory) `:type`, and the `= value`. +Recomendation is to use `UPPER_CASE` with underscores. + +They can be used to set fields default values, fixed-size arrays, or other constants. +(Generating constants in code is supported only for C++ so far.) + ### Namespaces These will generate the corresponding namespace in C++ for all helper diff --git a/docs/source/Tutorial.md b/docs/source/Tutorial.md index 70196fd29c9..1a343d77edb 100644 --- a/docs/source/Tutorial.md +++ b/docs/source/Tutorial.md @@ -169,6 +169,8 @@ the `schema` that defines the template for our monsters: namespace MyGame.Sample; + const MAX_MANA:short = 150; + enum Color:byte { Red = 0, Green, Blue = 2 } union Equipment { Weapon } // Optionally add more tables. @@ -181,7 +183,7 @@ the `schema` that defines the template for our monsters: table Monster { pos:Vec3; // Struct. - mana:short = 150; + mana:short = MAX_MANA; hp:short = 100; name:string; friendly:bool = false (deprecated); @@ -209,6 +211,11 @@ The `schema` starts with a `namespace` declaration. This determines the corresponding package/namespace for the generated code. In our example, we have the `Sample` namespace inside of the `MyGame` namespace. +After we have a `const` definition. The type of the constant primitive `MAX_MANA` +is `short` and the value associated is `150`; +Fields that use constants will be replaced by the value they represent during +the parsing step. They also generate scoped definition in code (only C++ so far). + Next, we have an `enum` definition. In this example, we have an `enum` of type `byte`, named `Color`. We have three values in this `enum`: `Red`, `Green`, and `Blue`. We specify `Red = 0` and `Blue = 2`, but we do not specify an explicit @@ -227,7 +234,9 @@ less memory and have faster lookup. The `Monster` table is the main object in our FlatBuffer. This will be used as the template to store our `orc` monster. We specify some default values for -fields, such as `mana:short = 150`. If unspecified, scalar fields (like `int`, +fields, such as `mana:short = MAX_MANA;` using the `const` defined above and +`hp:short = 100;`. +If unspecified, scalar fields (like `int`, `uint`, or `float`) will be given a default of `0` while strings and tables will be given a default of `null`. Another thing to note is the line `friendly:bool = false (deprecated);`. Since you cannot delete fields from a `table` (to support diff --git a/samples/monster.fbs b/samples/monster.fbs index af224512ee7..f7b697a4c05 100644 --- a/samples/monster.fbs +++ b/samples/monster.fbs @@ -2,6 +2,11 @@ namespace MyGame.Sample; +const DEFAULT_MANA:int32 = 150; +const NUM_EYES:short = 3; +const MAX_PERCENT:float = 100.0; +const MAX_LIFE:float = MAX_PERCENT; + enum Color:byte { Red = 0, Green, Blue = 2 } union Equipment { Weapon } // Optionally add more tables. @@ -12,9 +17,17 @@ struct Vec3 { z:float; } +struct Eye { + blind:bool; +} + +struct Eyes { + eyes:[Eye:NUM_EYES]; +} + table Monster { pos:Vec3; - mana:short = 150; + mana:int32 = DEFAULT_MANA; hp:short = 100; name:string; friendly:bool = false (deprecated); @@ -23,11 +36,13 @@ table Monster { weapons:[Weapon]; equipped:Equipment; path:[Vec3]; + eyes:Eyes; } table Weapon { name:string; damage:short; + life:float = MAX_LIFE; } root_type Monster; diff --git a/samples/monster_generated.h b/samples/monster_generated.h index 96795af5282..23f0f7c3289 100644 --- a/samples/monster_generated.h +++ b/samples/monster_generated.h @@ -16,8 +16,17 @@ static_assert(FLATBUFFERS_VERSION_MAJOR == 24 && namespace MyGame { namespace Sample { +constexpr int32_t DEFAULT_MANA = 150; +constexpr int16_t NUM_EYES = 3; +constexpr float MAX_PERCENT = 100.0; +constexpr float MAX_LIFE = 100.0; + struct Vec3; +struct Eye; + +struct Eyes; + struct Monster; struct MonsterBuilder; struct MonsterT; @@ -28,6 +37,10 @@ struct WeaponT; bool operator==(const Vec3 &lhs, const Vec3 &rhs); bool operator!=(const Vec3 &lhs, const Vec3 &rhs); +bool operator==(const Eye &lhs, const Eye &rhs); +bool operator!=(const Eye &lhs, const Eye &rhs); +bool operator==(const Eyes &lhs, const Eyes &rhs); +bool operator!=(const Eyes &lhs, const Eyes &rhs); bool operator==(const MonsterT &lhs, const MonsterT &rhs); bool operator!=(const MonsterT &lhs, const MonsterT &rhs); bool operator==(const WeaponT &lhs, const WeaponT &rhs); @@ -35,6 +48,10 @@ bool operator!=(const WeaponT &lhs, const WeaponT &rhs); inline const ::flatbuffers::TypeTable *Vec3TypeTable(); +inline const ::flatbuffers::TypeTable *EyeTypeTable(); + +inline const ::flatbuffers::TypeTable *EyesTypeTable(); + inline const ::flatbuffers::TypeTable *MonsterTypeTable(); inline const ::flatbuffers::TypeTable *WeaponTypeTable(); @@ -235,10 +252,76 @@ inline bool operator!=(const Vec3 &lhs, const Vec3 &rhs) { } +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(1) Eye FLATBUFFERS_FINAL_CLASS { + private: + uint8_t blind_; + + public: + static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { + return EyeTypeTable(); + } + Eye() + : blind_(0) { + } + Eye(bool _blind) + : blind_(::flatbuffers::EndianScalar(static_cast(_blind))) { + } + bool blind() const { + return ::flatbuffers::EndianScalar(blind_) != 0; + } + void mutate_blind(bool _blind) { + ::flatbuffers::WriteScalar(&blind_, static_cast(_blind)); + } +}; +FLATBUFFERS_STRUCT_END(Eye, 1); + +inline bool operator==(const Eye &lhs, const Eye &rhs) { + return + (lhs.blind() == rhs.blind()); +} + +inline bool operator!=(const Eye &lhs, const Eye &rhs) { + return !(lhs == rhs); +} + + +FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(1) Eyes FLATBUFFERS_FINAL_CLASS { + private: + MyGame::Sample::Eye eyes_[3]; + + public: + static const ::flatbuffers::TypeTable *MiniReflectTypeTable() { + return EyesTypeTable(); + } + Eyes() + : eyes_() { + } + Eyes(::flatbuffers::span _eyes) { + ::flatbuffers::CastToArray(eyes_).CopyFromSpan(_eyes); + } + const ::flatbuffers::Array *eyes() const { + return &::flatbuffers::CastToArray(eyes_); + } + ::flatbuffers::Array *mutable_eyes() { + return &::flatbuffers::CastToArray(eyes_); + } +}; +FLATBUFFERS_STRUCT_END(Eyes, 3); + +inline bool operator==(const Eyes &lhs, const Eyes &rhs) { + return + (*lhs.eyes() == *rhs.eyes()); +} + +inline bool operator!=(const Eyes &lhs, const Eyes &rhs) { + return !(lhs == rhs); +} + + struct MonsterT : public ::flatbuffers::NativeTable { typedef Monster TableType; std::unique_ptr pos{}; - int16_t mana = 150; + int32_t mana = 150; int16_t hp = 100; std::string name{}; std::vector inventory{}; @@ -246,6 +329,7 @@ struct MonsterT : public ::flatbuffers::NativeTable { std::vector> weapons{}; MyGame::Sample::EquipmentUnion equipped{}; std::vector path{}; + std::unique_ptr eyes{}; MonsterT() = default; MonsterT(const MonsterT &o); MonsterT(MonsterT&&) FLATBUFFERS_NOEXCEPT = default; @@ -268,7 +352,8 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { VT_WEAPONS = 18, VT_EQUIPPED_TYPE = 20, VT_EQUIPPED = 22, - VT_PATH = 24 + VT_PATH = 24, + VT_EYES = 26 }; const MyGame::Sample::Vec3 *pos() const { return GetStruct(VT_POS); @@ -276,11 +361,11 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { MyGame::Sample::Vec3 *mutable_pos() { return GetStruct(VT_POS); } - int16_t mana() const { - return GetField(VT_MANA, 150); + int32_t mana() const { + return GetField(VT_MANA, 150); } - bool mutate_mana(int16_t _mana = 150) { - return SetField(VT_MANA, _mana, 150); + bool mutate_mana(int32_t _mana = 150) { + return SetField(VT_MANA, _mana, 150); } int16_t hp() const { return GetField(VT_HP, 100); @@ -331,10 +416,16 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { ::flatbuffers::Vector *mutable_path() { return GetPointer<::flatbuffers::Vector *>(VT_PATH); } + const MyGame::Sample::Eyes *eyes() const { + return GetStruct(VT_EYES); + } + MyGame::Sample::Eyes *mutable_eyes() { + return GetStruct(VT_EYES); + } bool Verify(::flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField(verifier, VT_POS, 4) && - VerifyField(verifier, VT_MANA, 2) && + VerifyField(verifier, VT_MANA, 4) && VerifyField(verifier, VT_HP, 2) && VerifyOffset(verifier, VT_NAME) && verifier.VerifyString(name()) && @@ -349,6 +440,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { VerifyEquipment(verifier, equipped(), equipped_type()) && VerifyOffset(verifier, VT_PATH) && verifier.VerifyVector(path()) && + VerifyField(verifier, VT_EYES, 1) && verifier.EndTable(); } MonsterT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; @@ -367,8 +459,8 @@ struct MonsterBuilder { void add_pos(const MyGame::Sample::Vec3 *pos) { fbb_.AddStruct(Monster::VT_POS, pos); } - void add_mana(int16_t mana) { - fbb_.AddElement(Monster::VT_MANA, mana, 150); + void add_mana(int32_t mana) { + fbb_.AddElement(Monster::VT_MANA, mana, 150); } void add_hp(int16_t hp) { fbb_.AddElement(Monster::VT_HP, hp, 100); @@ -394,6 +486,9 @@ struct MonsterBuilder { void add_path(::flatbuffers::Offset<::flatbuffers::Vector> path) { fbb_.AddOffset(Monster::VT_PATH, path); } + void add_eyes(const MyGame::Sample::Eyes *eyes) { + fbb_.AddStruct(Monster::VT_EYES, eyes); + } explicit MonsterBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); @@ -408,7 +503,7 @@ struct MonsterBuilder { inline ::flatbuffers::Offset CreateMonster( ::flatbuffers::FlatBufferBuilder &_fbb, const MyGame::Sample::Vec3 *pos = nullptr, - int16_t mana = 150, + int32_t mana = 150, int16_t hp = 100, ::flatbuffers::Offset<::flatbuffers::String> name = 0, ::flatbuffers::Offset<::flatbuffers::Vector> inventory = 0, @@ -416,16 +511,18 @@ inline ::flatbuffers::Offset CreateMonster( ::flatbuffers::Offset<::flatbuffers::Vector<::flatbuffers::Offset>> weapons = 0, MyGame::Sample::Equipment equipped_type = MyGame::Sample::Equipment_NONE, ::flatbuffers::Offset equipped = 0, - ::flatbuffers::Offset<::flatbuffers::Vector> path = 0) { + ::flatbuffers::Offset<::flatbuffers::Vector> path = 0, + const MyGame::Sample::Eyes *eyes = nullptr) { MonsterBuilder builder_(_fbb); + builder_.add_eyes(eyes); builder_.add_path(path); builder_.add_equipped(equipped); builder_.add_weapons(weapons); builder_.add_inventory(inventory); builder_.add_name(name); + builder_.add_mana(mana); builder_.add_pos(pos); builder_.add_hp(hp); - builder_.add_mana(mana); builder_.add_equipped_type(equipped_type); builder_.add_color(color); return builder_.Finish(); @@ -434,7 +531,7 @@ inline ::flatbuffers::Offset CreateMonster( inline ::flatbuffers::Offset CreateMonsterDirect( ::flatbuffers::FlatBufferBuilder &_fbb, const MyGame::Sample::Vec3 *pos = nullptr, - int16_t mana = 150, + int32_t mana = 150, int16_t hp = 100, const char *name = nullptr, const std::vector *inventory = nullptr, @@ -442,7 +539,8 @@ inline ::flatbuffers::Offset CreateMonsterDirect( const std::vector<::flatbuffers::Offset> *weapons = nullptr, MyGame::Sample::Equipment equipped_type = MyGame::Sample::Equipment_NONE, ::flatbuffers::Offset equipped = 0, - const std::vector *path = nullptr) { + const std::vector *path = nullptr, + const MyGame::Sample::Eyes *eyes = nullptr) { auto name__ = name ? _fbb.CreateString(name) : 0; auto inventory__ = inventory ? _fbb.CreateVector(*inventory) : 0; auto weapons__ = weapons ? _fbb.CreateVector<::flatbuffers::Offset>(*weapons) : 0; @@ -458,7 +556,8 @@ inline ::flatbuffers::Offset CreateMonsterDirect( weapons__, equipped_type, equipped, - path__); + path__, + eyes); } ::flatbuffers::Offset CreateMonster(::flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); @@ -467,6 +566,7 @@ struct WeaponT : public ::flatbuffers::NativeTable { typedef Weapon TableType; std::string name{}; int16_t damage = 0; + float life = 100.0f; }; struct Weapon FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { @@ -477,7 +577,8 @@ struct Weapon FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { } enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_NAME = 4, - VT_DAMAGE = 6 + VT_DAMAGE = 6, + VT_LIFE = 8 }; const ::flatbuffers::String *name() const { return GetPointer(VT_NAME); @@ -491,11 +592,18 @@ struct Weapon FLATBUFFERS_FINAL_CLASS : private ::flatbuffers::Table { bool mutate_damage(int16_t _damage = 0) { return SetField(VT_DAMAGE, _damage, 0); } + float life() const { + return GetField(VT_LIFE, 100.0f); + } + bool mutate_life(float _life = 100.0f) { + return SetField(VT_LIFE, _life, 100.0f); + } bool Verify(::flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_NAME) && verifier.VerifyString(name()) && VerifyField(verifier, VT_DAMAGE, 2) && + VerifyField(verifier, VT_LIFE, 4) && verifier.EndTable(); } WeaponT *UnPack(const ::flatbuffers::resolver_function_t *_resolver = nullptr) const; @@ -513,6 +621,9 @@ struct WeaponBuilder { void add_damage(int16_t damage) { fbb_.AddElement(Weapon::VT_DAMAGE, damage, 0); } + void add_life(float life) { + fbb_.AddElement(Weapon::VT_LIFE, life, 100.0f); + } explicit WeaponBuilder(::flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); @@ -527,8 +638,10 @@ struct WeaponBuilder { inline ::flatbuffers::Offset CreateWeapon( ::flatbuffers::FlatBufferBuilder &_fbb, ::flatbuffers::Offset<::flatbuffers::String> name = 0, - int16_t damage = 0) { + int16_t damage = 0, + float life = 100.0f) { WeaponBuilder builder_(_fbb); + builder_.add_life(life); builder_.add_name(name); builder_.add_damage(damage); return builder_.Finish(); @@ -537,12 +650,14 @@ inline ::flatbuffers::Offset CreateWeapon( inline ::flatbuffers::Offset CreateWeaponDirect( ::flatbuffers::FlatBufferBuilder &_fbb, const char *name = nullptr, - int16_t damage = 0) { + int16_t damage = 0, + float life = 100.0f) { auto name__ = name ? _fbb.CreateString(name) : 0; return MyGame::Sample::CreateWeapon( _fbb, name__, - damage); + damage, + life); } ::flatbuffers::Offset CreateWeapon(::flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o, const ::flatbuffers::rehasher_function_t *_rehasher = nullptr); @@ -558,7 +673,8 @@ inline bool operator==(const MonsterT &lhs, const MonsterT &rhs) { (lhs.color == rhs.color) && (lhs.weapons.size() == rhs.weapons.size() && std::equal(lhs.weapons.cbegin(), lhs.weapons.cend(), rhs.weapons.cbegin(), [](std::unique_ptr const &a, std::unique_ptr const &b) { return (a == b) || (a && b && *a == *b); })) && (lhs.equipped == rhs.equipped) && - (lhs.path == rhs.path); + (lhs.path == rhs.path) && + ((lhs.eyes == rhs.eyes) || (lhs.eyes && rhs.eyes && *lhs.eyes == *rhs.eyes)); } inline bool operator!=(const MonsterT &lhs, const MonsterT &rhs) { @@ -574,7 +690,8 @@ inline MonsterT::MonsterT(const MonsterT &o) inventory(o.inventory), color(o.color), equipped(o.equipped), - path(o.path) { + path(o.path), + eyes((o.eyes) ? new MyGame::Sample::Eyes(*o.eyes) : nullptr) { weapons.reserve(o.weapons.size()); for (const auto &weapons_ : o.weapons) { weapons.emplace_back((weapons_) ? new MyGame::Sample::WeaponT(*weapons_) : nullptr); } } @@ -589,6 +706,7 @@ inline MonsterT &MonsterT::operator=(MonsterT o) FLATBUFFERS_NOEXCEPT { std::swap(weapons, o.weapons); std::swap(equipped, o.equipped); std::swap(path, o.path); + std::swap(eyes, o.eyes); return *this; } @@ -611,6 +729,7 @@ inline void Monster::UnPackTo(MonsterT *_o, const ::flatbuffers::resolver_functi { auto _e = equipped_type(); _o->equipped.type = _e; } { auto _e = equipped(); if (_e) _o->equipped.value = MyGame::Sample::EquipmentUnion::UnPack(_e, equipped_type(), _resolver); } { auto _e = path(); if (_e) { _o->path.resize(_e->size()); for (::flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->path[_i] = *_e->Get(_i); } } else { _o->path.resize(0); } } + { auto _e = eyes(); if (_e) _o->eyes = std::unique_ptr(new MyGame::Sample::Eyes(*_e)); } } inline ::flatbuffers::Offset Monster::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const MonsterT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { @@ -631,6 +750,7 @@ inline ::flatbuffers::Offset CreateMonster(::flatbuffers::FlatBufferBui auto _equipped_type = _o->equipped.type; auto _equipped = _o->equipped.Pack(_fbb); auto _path = _o->path.size() ? _fbb.CreateVectorOfStructs(_o->path) : 0; + auto _eyes = _o->eyes ? _o->eyes.get() : nullptr; return MyGame::Sample::CreateMonster( _fbb, _pos, @@ -642,14 +762,16 @@ inline ::flatbuffers::Offset CreateMonster(::flatbuffers::FlatBufferBui _weapons, _equipped_type, _equipped, - _path); + _path, + _eyes); } inline bool operator==(const WeaponT &lhs, const WeaponT &rhs) { return (lhs.name == rhs.name) && - (lhs.damage == rhs.damage); + (lhs.damage == rhs.damage) && + (lhs.life == rhs.life); } inline bool operator!=(const WeaponT &lhs, const WeaponT &rhs) { @@ -668,6 +790,7 @@ inline void Weapon::UnPackTo(WeaponT *_o, const ::flatbuffers::resolver_function (void)_resolver; { auto _e = name(); if (_e) _o->name = _e->str(); } { auto _e = damage(); _o->damage = _e; } + { auto _e = life(); _o->life = _e; } } inline ::flatbuffers::Offset Weapon::Pack(::flatbuffers::FlatBufferBuilder &_fbb, const WeaponT* _o, const ::flatbuffers::rehasher_function_t *_rehasher) { @@ -680,10 +803,12 @@ inline ::flatbuffers::Offset CreateWeapon(::flatbuffers::FlatBufferBuild struct _VectorArgs { ::flatbuffers::FlatBufferBuilder *__fbb; const WeaponT* __o; const ::flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; auto _name = _o->name.empty() ? 0 : _fbb.CreateString(_o->name); auto _damage = _o->damage; + auto _life = _o->life; return MyGame::Sample::CreateWeapon( _fbb, _name, - _damage); + _damage, + _life); } inline bool VerifyEquipment(::flatbuffers::Verifier &verifier, const void *obj, Equipment type) { @@ -813,10 +938,42 @@ inline const ::flatbuffers::TypeTable *Vec3TypeTable() { return &tt; } +inline const ::flatbuffers::TypeTable *EyeTypeTable() { + static const ::flatbuffers::TypeCode type_codes[] = { + { ::flatbuffers::ET_BOOL, 0, -1 } + }; + static const int64_t values[] = { 0, 1 }; + static const char * const names[] = { + "blind" + }; + static const ::flatbuffers::TypeTable tt = { + ::flatbuffers::ST_STRUCT, 1, type_codes, nullptr, nullptr, values, names + }; + return &tt; +} + +inline const ::flatbuffers::TypeTable *EyesTypeTable() { + static const ::flatbuffers::TypeCode type_codes[] = { + { ::flatbuffers::ET_SEQUENCE, 1, 0 } + }; + static const ::flatbuffers::TypeFunction type_refs[] = { + MyGame::Sample::EyeTypeTable + }; + static const int16_t array_sizes[] = { 3, }; + static const int64_t values[] = { 0, 3 }; + static const char * const names[] = { + "eyes" + }; + static const ::flatbuffers::TypeTable tt = { + ::flatbuffers::ST_STRUCT, 1, type_codes, type_refs, array_sizes, values, names + }; + return &tt; +} + inline const ::flatbuffers::TypeTable *MonsterTypeTable() { static const ::flatbuffers::TypeCode type_codes[] = { { ::flatbuffers::ET_SEQUENCE, 0, 0 }, - { ::flatbuffers::ET_SHORT, 0, -1 }, + { ::flatbuffers::ET_INT, 0, -1 }, { ::flatbuffers::ET_SHORT, 0, -1 }, { ::flatbuffers::ET_STRING, 0, -1 }, { ::flatbuffers::ET_BOOL, 0, -1 }, @@ -825,13 +982,15 @@ inline const ::flatbuffers::TypeTable *MonsterTypeTable() { { ::flatbuffers::ET_SEQUENCE, 1, 2 }, { ::flatbuffers::ET_UTYPE, 0, 3 }, { ::flatbuffers::ET_SEQUENCE, 0, 3 }, - { ::flatbuffers::ET_SEQUENCE, 1, 0 } + { ::flatbuffers::ET_SEQUENCE, 1, 0 }, + { ::flatbuffers::ET_SEQUENCE, 0, 4 } }; static const ::flatbuffers::TypeFunction type_refs[] = { MyGame::Sample::Vec3TypeTable, MyGame::Sample::ColorTypeTable, MyGame::Sample::WeaponTypeTable, - MyGame::Sample::EquipmentTypeTable + MyGame::Sample::EquipmentTypeTable, + MyGame::Sample::EyesTypeTable }; static const char * const names[] = { "pos", @@ -844,10 +1003,11 @@ inline const ::flatbuffers::TypeTable *MonsterTypeTable() { "weapons", "equipped_type", "equipped", - "path" + "path", + "eyes" }; static const ::flatbuffers::TypeTable tt = { - ::flatbuffers::ST_TABLE, 11, type_codes, type_refs, nullptr, nullptr, names + ::flatbuffers::ST_TABLE, 12, type_codes, type_refs, nullptr, nullptr, names }; return &tt; } @@ -855,14 +1015,16 @@ inline const ::flatbuffers::TypeTable *MonsterTypeTable() { inline const ::flatbuffers::TypeTable *WeaponTypeTable() { static const ::flatbuffers::TypeCode type_codes[] = { { ::flatbuffers::ET_STRING, 0, -1 }, - { ::flatbuffers::ET_SHORT, 0, -1 } + { ::flatbuffers::ET_SHORT, 0, -1 }, + { ::flatbuffers::ET_FLOAT, 0, -1 } }; static const char * const names[] = { "name", - "damage" + "damage", + "life" }; static const ::flatbuffers::TypeTable tt = { - ::flatbuffers::ST_TABLE, 2, type_codes, nullptr, nullptr, nullptr, names + ::flatbuffers::ST_TABLE, 3, type_codes, nullptr, nullptr, nullptr, names }; return &tt; }