Commit 33791dc7 authored by Thomas's avatar Thomas Committed by Wouter van Oortmerssen

Add compare operator to code generated for c++ (#4940)

* Add operator== for c++ genated code

New "--gen-compare" option for flatc to generate compare operators. The operators are defined based on object based api types.

Inspired by issue #263.

* Improve compare operator for c++.
Thanks for the code review.

- Improve robustness against future schema extensions
- Code style
- Fix --rust generation in generate_code.sh
parent 873a60b0
...@@ -223,7 +223,7 @@ function(compile_flatbuffers_schema_to_cpp SRC_FBS) ...@@ -223,7 +223,7 @@ function(compile_flatbuffers_schema_to_cpp SRC_FBS)
add_custom_command( add_custom_command(
OUTPUT ${GEN_HEADER} OUTPUT ${GEN_HEADER}
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable
--gen-object-api -o "${SRC_FBS_DIR}" --gen-object-api --gen-compare -o "${SRC_FBS_DIR}"
--cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs --cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs
--reflect-names --reflect-names
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test" -I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
......
...@@ -96,6 +96,8 @@ Additional options: ...@@ -96,6 +96,8 @@ Additional options:
at the cost of efficiency (object allocation). Recommended only to be used at the cost of efficiency (object allocation). Recommended only to be used
if other options are insufficient. if other options are insufficient.
- `--gen-compare` : Generate operator== for object-based API types.
- `--gen-onefile` : Generate single output file (useful for C#) - `--gen-onefile` : Generate single output file (useful for C#)
- `--gen-all`: Generate not just code for the current schema files, but - `--gen-all`: Generate not just code for the current schema files, but
......
...@@ -379,6 +379,7 @@ struct IDLOptions { ...@@ -379,6 +379,7 @@ struct IDLOptions {
bool skip_unexpected_fields_in_json; bool skip_unexpected_fields_in_json;
bool generate_name_strings; bool generate_name_strings;
bool generate_object_based_api; bool generate_object_based_api;
bool gen_compare;
std::string cpp_object_api_pointer_type; std::string cpp_object_api_pointer_type;
std::string cpp_object_api_string_type; std::string cpp_object_api_string_type;
bool gen_nullable; bool gen_nullable;
...@@ -453,6 +454,7 @@ struct IDLOptions { ...@@ -453,6 +454,7 @@ struct IDLOptions {
skip_unexpected_fields_in_json(false), skip_unexpected_fields_in_json(false),
generate_name_strings(false), generate_name_strings(false),
generate_object_based_api(false), generate_object_based_api(false),
gen_compare(false),
cpp_object_api_pointer_type("std::unique_ptr"), cpp_object_api_pointer_type("std::unique_ptr"),
gen_nullable(false), gen_nullable(false),
object_suffix("T"), object_suffix("T"),
......
...@@ -17,6 +17,10 @@ struct MonsterT; ...@@ -17,6 +17,10 @@ struct MonsterT;
struct Weapon; struct Weapon;
struct WeaponT; struct WeaponT;
bool operator==(const Vec3 &lhs, const Vec3 &rhs);
bool operator==(const MonsterT &lhs, const MonsterT &rhs);
bool operator==(const WeaponT &lhs, const WeaponT &rhs);
inline const flatbuffers::TypeTable *Vec3TypeTable(); inline const flatbuffers::TypeTable *Vec3TypeTable();
inline const flatbuffers::TypeTable *MonsterTypeTable(); inline const flatbuffers::TypeTable *MonsterTypeTable();
...@@ -133,6 +137,22 @@ struct EquipmentUnion { ...@@ -133,6 +137,22 @@ struct EquipmentUnion {
} }
}; };
inline bool operator==(const EquipmentUnion &lhs, const EquipmentUnion &rhs) {
if (lhs.type != rhs.type) return false;
switch (lhs.type) {
case Equipment_NONE: {
return true;
}
case Equipment_Weapon: {
return *(reinterpret_cast<const WeaponT *>(lhs.value)) ==
*(reinterpret_cast<const WeaponT *>(rhs.value));
}
default: {
return false;
}
}
}
bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *obj, Equipment type); bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *obj, Equipment type);
bool VerifyEquipmentVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types); bool VerifyEquipmentVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
...@@ -172,6 +192,13 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vec3 FLATBUFFERS_FINAL_CLASS { ...@@ -172,6 +192,13 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vec3 FLATBUFFERS_FINAL_CLASS {
}; };
FLATBUFFERS_STRUCT_END(Vec3, 12); FLATBUFFERS_STRUCT_END(Vec3, 12);
inline bool operator==(const Vec3 &lhs, const Vec3 &rhs) {
return
(lhs.x() == rhs.x()) &&
(lhs.y() == rhs.y()) &&
(lhs.z() == rhs.z());
}
struct MonsterT : public flatbuffers::NativeTable { struct MonsterT : public flatbuffers::NativeTable {
typedef Monster TableType; typedef Monster TableType;
flatbuffers::unique_ptr<Vec3> pos; flatbuffers::unique_ptr<Vec3> pos;
...@@ -189,6 +216,18 @@ struct MonsterT : public flatbuffers::NativeTable { ...@@ -189,6 +216,18 @@ struct MonsterT : public flatbuffers::NativeTable {
} }
}; };
inline bool operator==(const MonsterT &lhs, const MonsterT &rhs) {
return
(lhs.pos == rhs.pos) &&
(lhs.mana == rhs.mana) &&
(lhs.hp == rhs.hp) &&
(lhs.name == rhs.name) &&
(lhs.inventory == rhs.inventory) &&
(lhs.color == rhs.color) &&
(lhs.weapons == rhs.weapons) &&
(lhs.equipped == rhs.equipped);
}
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef MonsterT NativeTableType; typedef MonsterT NativeTableType;
static const flatbuffers::TypeTable *MiniReflectTypeTable() { static const flatbuffers::TypeTable *MiniReflectTypeTable() {
...@@ -391,6 +430,12 @@ struct WeaponT : public flatbuffers::NativeTable { ...@@ -391,6 +430,12 @@ struct WeaponT : public flatbuffers::NativeTable {
} }
}; };
inline bool operator==(const WeaponT &lhs, const WeaponT &rhs) {
return
(lhs.name == rhs.name) &&
(lhs.damage == rhs.damage);
}
struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef WeaponT NativeTableType; typedef WeaponT NativeTableType;
static const flatbuffers::TypeTable *MiniReflectTypeTable() { static const flatbuffers::TypeTable *MiniReflectTypeTable() {
......
...@@ -88,6 +88,7 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const { ...@@ -88,6 +88,7 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const {
" --gen-onefile Generate single output file for C# and Go.\n" " --gen-onefile Generate single output file for C# and Go.\n"
" --gen-name-strings Generate type name functions for C++.\n" " --gen-name-strings Generate type name functions for C++.\n"
" --gen-object-api Generate an additional object-based API.\n" " --gen-object-api Generate an additional object-based API.\n"
" --gen-compare Generate operator== for object-based API types.\n"
" --cpp-ptr-type T Set object API pointer type (default std::unique_ptr)\n" " --cpp-ptr-type T Set object API pointer type (default std::unique_ptr)\n"
" --cpp-str-type T Set object API string type (default std::string)\n" " --cpp-str-type T Set object API string type (default std::string)\n"
" T::c_str() and T::length() must be supported\n" " T::c_str() and T::length() must be supported\n"
...@@ -222,6 +223,8 @@ int FlatCompiler::Compile(int argc, const char **argv) { ...@@ -222,6 +223,8 @@ int FlatCompiler::Compile(int argc, const char **argv) {
opts.generate_name_strings = true; opts.generate_name_strings = true;
} else if (arg == "--gen-object-api") { } else if (arg == "--gen-object-api") {
opts.generate_object_based_api = true; opts.generate_object_based_api = true;
} else if (arg == "--gen-compare") {
opts.gen_compare = true;
} else if (arg == "--cpp-ptr-type") { } else if (arg == "--cpp-ptr-type") {
if (++argi >= argc) Error("missing type following" + arg, true); if (++argi >= argc) Error("missing type following" + arg, true);
opts.cpp_object_api_pointer_type = argv[argi]; opts.cpp_object_api_pointer_type = argv[argi];
......
...@@ -226,14 +226,30 @@ class CppGenerator : public BaseGenerator { ...@@ -226,14 +226,30 @@ class CppGenerator : public BaseGenerator {
if (!struct_def.generated) { if (!struct_def.generated) {
SetNameSpace(struct_def.defined_namespace); SetNameSpace(struct_def.defined_namespace);
code_ += "struct " + Name(struct_def) + ";"; code_ += "struct " + Name(struct_def) + ";";
if (parser_.opts.generate_object_based_api && !struct_def.fixed) { if (parser_.opts.generate_object_based_api) {
code_ += "struct " + auto nativeName = NativeName(Name(struct_def), &struct_def, parser_.opts);
NativeName(Name(struct_def), &struct_def, parser_.opts) + if (!struct_def.fixed) {
";"; code_ += "struct " + nativeName + ";";
}
} }
code_ += ""; code_ += "";
} }
} }
// Generate forward declarations for all equal operators
if (parser_.opts.generate_object_based_api && parser_.opts.gen_compare) {
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
const auto &struct_def = **it;
if (!struct_def.generated) {
SetNameSpace(struct_def.defined_namespace);
auto nativeName = NativeName(Name(struct_def), &struct_def, parser_.opts);
code_ += "bool operator==(const " + nativeName + " &lhs, const " + nativeName + " &rhs);";
}
}
code_ += "";
}
// Generate preablmle code for mini reflection. // Generate preablmle code for mini reflection.
if (parser_.opts.mini_reflect != IDLOptions::kNone) { if (parser_.opts.mini_reflect != IDLOptions::kNone) {
// To break cyclic dependencies, first pre-declare all tables/structs. // To break cyclic dependencies, first pre-declare all tables/structs.
...@@ -1096,6 +1112,38 @@ class CppGenerator : public BaseGenerator { ...@@ -1096,6 +1112,38 @@ class CppGenerator : public BaseGenerator {
} }
code_ += "};"; code_ += "};";
code_ += ""; code_ += "";
if (parser_.opts.gen_compare) {
code_ += "";
code_ += "inline bool operator==(const {{NAME}}Union &lhs, const {{NAME}}Union &rhs) {";
code_ += " if (lhs.type != rhs.type) return false;";
code_ += " switch (lhs.type) {";
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
++it) {
const auto &ev = **it;
code_.SetValue("NATIVE_ID", GetEnumValUse(enum_def, ev));
if (ev.value) {
const auto native_type =
NativeName(GetUnionElement(ev, true, true, true),
ev.union_type.struct_def, parser_.opts);
code_.SetValue("NATIVE_TYPE", native_type);
code_ += " case {{NATIVE_ID}}: {";
code_ += " return *(reinterpret_cast<const {{NATIVE_TYPE}} *>(lhs.value)) ==";
code_ += " *(reinterpret_cast<const {{NATIVE_TYPE}} *>(rhs.value));";
code_ += " }";
} else {
code_ += " case {{NATIVE_ID}}: {";
code_ += " return true;"; // "NONE" enum value.
code_ += " }";
}
}
code_ += " default: {";
code_ += " return false;";
code_ += " }";
code_ += " }";
code_ += "}";
}
} }
if (enum_def.is_union) { if (enum_def.is_union) {
...@@ -1456,6 +1504,44 @@ class CppGenerator : public BaseGenerator { ...@@ -1456,6 +1504,44 @@ class CppGenerator : public BaseGenerator {
code_ += " }"; code_ += " }";
} }
void GenCompareOperator(const StructDef &struct_def, std::string accessSuffix = "") {
std::string compare_op;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
const auto &field = **it;
if (!field.deprecated && // Deprecated fields won't be accessible.
field.value.type.base_type != BASE_TYPE_UTYPE &&
(field.value.type.base_type != BASE_TYPE_VECTOR ||
field.value.type.element != BASE_TYPE_UTYPE)) {
if (!compare_op.empty()) {
compare_op += " &&\n ";
}
auto accessor = Name(field) + accessSuffix;
compare_op += "(lhs." + accessor + " == rhs." + accessor + ")";
}
}
std::string cmp_lhs;
std::string cmp_rhs;
if (compare_op.empty()) {
cmp_lhs = "";
cmp_rhs = "";
compare_op = " return true;";
} else {
cmp_lhs = "lhs";
cmp_rhs = "rhs";
compare_op = " return\n " + compare_op + ";";
}
code_.SetValue("CMP_OP", compare_op);
code_.SetValue("CMP_LHS", cmp_lhs);
code_.SetValue("CMP_RHS", cmp_rhs);
code_ += "";
code_ += "inline bool operator==(const {{NATIVE_NAME}} &{{CMP_LHS}}, const {{NATIVE_NAME}} &{{CMP_RHS}}) {";
code_ += "{{CMP_OP}}";
code_ += "}";
}
void GenOperatorNewDelete(const StructDef &struct_def) { void GenOperatorNewDelete(const StructDef &struct_def) {
if (auto native_custom_alloc = if (auto native_custom_alloc =
struct_def.attributes.Lookup("native_custom_alloc")) { struct_def.attributes.Lookup("native_custom_alloc")) {
...@@ -1488,6 +1574,7 @@ class CppGenerator : public BaseGenerator { ...@@ -1488,6 +1574,7 @@ class CppGenerator : public BaseGenerator {
GenOperatorNewDelete(struct_def); GenOperatorNewDelete(struct_def);
GenDefaultConstructor(struct_def); GenDefaultConstructor(struct_def);
code_ += "};"; code_ += "};";
if (parser_.opts.gen_compare) GenCompareOperator(struct_def);
code_ += ""; code_ += "";
} }
...@@ -2600,6 +2687,7 @@ class CppGenerator : public BaseGenerator { ...@@ -2600,6 +2687,7 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("STRUCT_BYTE_SIZE", NumToString(struct_def.bytesize)); code_.SetValue("STRUCT_BYTE_SIZE", NumToString(struct_def.bytesize));
code_ += "FLATBUFFERS_STRUCT_END({{STRUCT_NAME}}, {{STRUCT_BYTE_SIZE}});"; code_ += "FLATBUFFERS_STRUCT_END({{STRUCT_NAME}}, {{STRUCT_BYTE_SIZE}});";
if (parser_.opts.gen_compare) GenCompareOperator(struct_def, "()");
code_ += ""; code_ += "";
} }
......
...@@ -15,13 +15,13 @@ ...@@ -15,13 +15,13 @@
set buildtype=Release set buildtype=Release
if "%1"=="-b" set buildtype=%2 if "%1"=="-b" set buildtype=%2
..\%buildtype%\flatc.exe --cpp --java --csharp --go --binary --python --lobster --lua --js --rust --ts --php --grpc --gen-mutable --reflect-names --gen-object-api --no-includes --cpp-ptr-type flatbuffers::unique_ptr --no-fb-import -I include_test monster_test.fbs monsterdata_test.json ..\%buildtype%\flatc.exe --cpp --java --csharp --go --binary --python --lobster --lua --js --rust --ts --php --grpc --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes --cpp-ptr-type flatbuffers::unique_ptr --no-fb-import -I include_test monster_test.fbs monsterdata_test.json
..\%buildtype%\flatc.exe --cpp --java --csharp --go --binary --python --lobster --lua --js --rust --ts --php --gen-mutable --reflect-names --no-fb-import --cpp-ptr-type flatbuffers::unique_ptr -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs ..\%buildtype%\flatc.exe --cpp --java --csharp --go --binary --python --lobster --lua --js --rust --ts --php --gen-mutable --reflect-names --no-fb-import --cpp-ptr-type flatbuffers::unique_ptr -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs
..\%buildtype%\flatc.exe --cpp --js --ts --php --gen-mutable --reflect-names --gen-object-api --cpp-ptr-type flatbuffers::unique_ptr -o union_vector ./union_vector/union_vector.fbs ..\%buildtype%\flatc.exe --cpp --js --ts --php --gen-mutable --reflect-names --gen-object-api --gen-compare --cpp-ptr-type flatbuffers::unique_ptr -o union_vector ./union_vector/union_vector.fbs
..\%buildtype%\flatc.exe -b --schema --bfbs-comments -I include_test monster_test.fbs ..\%buildtype%\flatc.exe -b --schema --bfbs-comments -I include_test monster_test.fbs
..\%buildtype%\flatc.exe --jsonschema --schema -I include_test monster_test.fbs ..\%buildtype%\flatc.exe --jsonschema --schema -I include_test monster_test.fbs
cd ../samples cd ../samples
..\%buildtype%\flatc.exe --cpp --lobster --gen-mutable --reflect-names --gen-object-api --cpp-ptr-type flatbuffers::unique_ptr monster.fbs ..\%buildtype%\flatc.exe --cpp --lobster --gen-mutable --reflect-names --gen-object-api --gen-compare --cpp-ptr-type flatbuffers::unique_ptr monster.fbs
cd ../reflection cd ../reflection
cd ../tests cd ../tests
...@@ -14,11 +14,11 @@ ...@@ -14,11 +14,11 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
../flatc --cpp --java --csharp --dart --go --binary --lobster --lua --python --js --ts --php --rust --grpc --gen-mutable --reflect-names --gen-object-api --no-includes --cpp-ptr-type flatbuffers::unique_ptr --no-fb-import -I include_test monster_test.fbs monsterdata_test.json ../flatc --cpp --java --csharp --dart --go --binary --lobster --lua --python --js --ts --php --rust --grpc --gen-mutable --reflect-names --gen-object-api --gen-compare --no-includes --cpp-ptr-type flatbuffers::unique_ptr --no-fb-import -I include_test monster_test.fbs monsterdata_test.json
../flatc --cpp --java --csharp --dart --go --binary --lobster --lua --python --js --ts --php --rust --gen-mutable --reflect-names --no-fb-import --cpp-ptr-type flatbuffers::unique_ptr -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs ../flatc --cpp --java --csharp --dart --go --binary --lobster --lua --python --js --ts --php --rust --gen-mutable --reflect-names --no-fb-import --cpp-ptr-type flatbuffers::unique_ptr -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs
../flatc --cpp --js --ts --php --gen-mutable --reflect-names --gen-object-api --cpp-ptr-type flatbuffers::unique_ptr -o union_vector ./union_vector/union_vector.fbs ../flatc --cpp --js --ts --php --gen-mutable --reflect-names --gen-object-api --gen-compare --cpp-ptr-type flatbuffers::unique_ptr -o union_vector ./union_vector/union_vector.fbs
../flatc -b --schema --bfbs-comments -I include_test monster_test.fbs ../flatc -b --schema --bfbs-comments -I include_test monster_test.fbs
../flatc --jsonschema --schema -I include_test monster_test.fbs ../flatc --jsonschema --schema -I include_test monster_test.fbs
cd ../samples cd ../samples
../flatc --cpp --lobster --gen-mutable --reflect-names --gen-object-api --cpp-ptr-type flatbuffers::unique_ptr monster.fbs ../flatc --cpp --lobster --gen-mutable --reflect-names --gen-object-api --gen-compare --cpp-ptr-type flatbuffers::unique_ptr monster.fbs
cd ../reflection cd ../reflection
...@@ -44,6 +44,25 @@ struct TypeAliasesT; ...@@ -44,6 +44,25 @@ struct TypeAliasesT;
} // namespace Example } // namespace Example
bool operator==(const InParentNamespaceT &lhs, const InParentNamespaceT &rhs);
namespace Example2 {
bool operator==(const MonsterT &lhs, const MonsterT &rhs);
} // namespace Example2
namespace Example {
bool operator==(const Test &lhs, const Test &rhs);
bool operator==(const TestSimpleTableWithEnumT &lhs, const TestSimpleTableWithEnumT &rhs);
bool operator==(const Vec3 &lhs, const Vec3 &rhs);
bool operator==(const Ability &lhs, const Ability &rhs);
bool operator==(const StatT &lhs, const StatT &rhs);
bool operator==(const ReferrableT &lhs, const ReferrableT &rhs);
bool operator==(const MonsterT &lhs, const MonsterT &rhs);
bool operator==(const TypeAliasesT &lhs, const TypeAliasesT &rhs);
} // namespace Example
inline const flatbuffers::TypeTable *InParentNamespaceTypeTable(); inline const flatbuffers::TypeTable *InParentNamespaceTypeTable();
namespace Example2 { namespace Example2 {
...@@ -215,6 +234,30 @@ struct AnyUnion { ...@@ -215,6 +234,30 @@ struct AnyUnion {
} }
}; };
inline bool operator==(const AnyUnion &lhs, const AnyUnion &rhs) {
if (lhs.type != rhs.type) return false;
switch (lhs.type) {
case Any_NONE: {
return true;
}
case Any_Monster: {
return *(reinterpret_cast<const MonsterT *>(lhs.value)) ==
*(reinterpret_cast<const MonsterT *>(rhs.value));
}
case Any_TestSimpleTableWithEnum: {
return *(reinterpret_cast<const TestSimpleTableWithEnumT *>(lhs.value)) ==
*(reinterpret_cast<const TestSimpleTableWithEnumT *>(rhs.value));
}
case Any_MyGame_Example2_Monster: {
return *(reinterpret_cast<const MyGame::Example2::MonsterT *>(lhs.value)) ==
*(reinterpret_cast<const MyGame::Example2::MonsterT *>(rhs.value));
}
default: {
return false;
}
}
}
bool VerifyAny(flatbuffers::Verifier &verifier, const void *obj, Any type); bool VerifyAny(flatbuffers::Verifier &verifier, const void *obj, Any type);
bool VerifyAnyVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types); bool VerifyAnyVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
...@@ -249,6 +292,12 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(2) Test FLATBUFFERS_FINAL_CLASS { ...@@ -249,6 +292,12 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(2) Test FLATBUFFERS_FINAL_CLASS {
}; };
FLATBUFFERS_STRUCT_END(Test, 4); FLATBUFFERS_STRUCT_END(Test, 4);
inline bool operator==(const Test &lhs, const Test &rhs) {
return
(lhs.a() == rhs.a()) &&
(lhs.b() == rhs.b());
}
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(16) Vec3 FLATBUFFERS_FINAL_CLASS { FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(16) Vec3 FLATBUFFERS_FINAL_CLASS {
private: private:
float x_; float x_;
...@@ -318,6 +367,16 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(16) Vec3 FLATBUFFERS_FINAL_CLASS { ...@@ -318,6 +367,16 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(16) Vec3 FLATBUFFERS_FINAL_CLASS {
}; };
FLATBUFFERS_STRUCT_END(Vec3, 32); FLATBUFFERS_STRUCT_END(Vec3, 32);
inline bool operator==(const Vec3 &lhs, const Vec3 &rhs) {
return
(lhs.x() == rhs.x()) &&
(lhs.y() == rhs.y()) &&
(lhs.z() == rhs.z()) &&
(lhs.test1() == rhs.test1()) &&
(lhs.test2() == rhs.test2()) &&
(lhs.test3() == rhs.test3());
}
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Ability FLATBUFFERS_FINAL_CLASS { FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Ability FLATBUFFERS_FINAL_CLASS {
private: private:
uint32_t id_; uint32_t id_;
...@@ -352,6 +411,12 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Ability FLATBUFFERS_FINAL_CLASS { ...@@ -352,6 +411,12 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Ability FLATBUFFERS_FINAL_CLASS {
}; };
FLATBUFFERS_STRUCT_END(Ability, 8); FLATBUFFERS_STRUCT_END(Ability, 8);
inline bool operator==(const Ability &lhs, const Ability &rhs) {
return
(lhs.id() == rhs.id()) &&
(lhs.distance() == rhs.distance());
}
} // namespace Example } // namespace Example
struct InParentNamespaceT : public flatbuffers::NativeTable { struct InParentNamespaceT : public flatbuffers::NativeTable {
...@@ -360,6 +425,10 @@ struct InParentNamespaceT : public flatbuffers::NativeTable { ...@@ -360,6 +425,10 @@ struct InParentNamespaceT : public flatbuffers::NativeTable {
} }
}; };
inline bool operator==(const InParentNamespaceT &, const InParentNamespaceT &) {
return true;
}
struct InParentNamespace FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct InParentNamespace FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef InParentNamespaceT NativeTableType; typedef InParentNamespaceT NativeTableType;
static const flatbuffers::TypeTable *MiniReflectTypeTable() { static const flatbuffers::TypeTable *MiniReflectTypeTable() {
...@@ -405,6 +474,10 @@ struct MonsterT : public flatbuffers::NativeTable { ...@@ -405,6 +474,10 @@ struct MonsterT : public flatbuffers::NativeTable {
} }
}; };
inline bool operator==(const MonsterT &, const MonsterT &) {
return true;
}
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef MonsterT NativeTableType; typedef MonsterT NativeTableType;
static const flatbuffers::TypeTable *MiniReflectTypeTable() { static const flatbuffers::TypeTable *MiniReflectTypeTable() {
...@@ -454,6 +527,11 @@ struct TestSimpleTableWithEnumT : public flatbuffers::NativeTable { ...@@ -454,6 +527,11 @@ struct TestSimpleTableWithEnumT : public flatbuffers::NativeTable {
} }
}; };
inline bool operator==(const TestSimpleTableWithEnumT &lhs, const TestSimpleTableWithEnumT &rhs) {
return
(lhs.color == rhs.color);
}
struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef TestSimpleTableWithEnumT NativeTableType; typedef TestSimpleTableWithEnumT NativeTableType;
static const flatbuffers::TypeTable *MiniReflectTypeTable() { static const flatbuffers::TypeTable *MiniReflectTypeTable() {
...@@ -517,6 +595,13 @@ struct StatT : public flatbuffers::NativeTable { ...@@ -517,6 +595,13 @@ struct StatT : public flatbuffers::NativeTable {
} }
}; };
inline bool operator==(const StatT &lhs, const StatT &rhs) {
return
(lhs.id == rhs.id) &&
(lhs.val == rhs.val) &&
(lhs.count == rhs.count);
}
struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef StatT NativeTableType; typedef StatT NativeTableType;
static const flatbuffers::TypeTable *MiniReflectTypeTable() { static const flatbuffers::TypeTable *MiniReflectTypeTable() {
...@@ -616,6 +701,11 @@ struct ReferrableT : public flatbuffers::NativeTable { ...@@ -616,6 +701,11 @@ struct ReferrableT : public flatbuffers::NativeTable {
} }
}; };
inline bool operator==(const ReferrableT &lhs, const ReferrableT &rhs) {
return
(lhs.id == rhs.id);
}
struct Referrable FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Referrable FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef ReferrableT NativeTableType; typedef ReferrableT NativeTableType;
static const flatbuffers::TypeTable *MiniReflectTypeTable() { static const flatbuffers::TypeTable *MiniReflectTypeTable() {
...@@ -739,6 +829,51 @@ struct MonsterT : public flatbuffers::NativeTable { ...@@ -739,6 +829,51 @@ struct MonsterT : public flatbuffers::NativeTable {
} }
}; };
inline bool operator==(const MonsterT &lhs, const MonsterT &rhs) {
return
(lhs.pos == rhs.pos) &&
(lhs.mana == rhs.mana) &&
(lhs.hp == rhs.hp) &&
(lhs.name == rhs.name) &&
(lhs.inventory == rhs.inventory) &&
(lhs.color == rhs.color) &&
(lhs.test == rhs.test) &&
(lhs.test4 == rhs.test4) &&
(lhs.testarrayofstring == rhs.testarrayofstring) &&
(lhs.testarrayoftables == rhs.testarrayoftables) &&
(lhs.enemy == rhs.enemy) &&
(lhs.testnestedflatbuffer == rhs.testnestedflatbuffer) &&
(lhs.testempty == rhs.testempty) &&
(lhs.testbool == rhs.testbool) &&
(lhs.testhashs32_fnv1 == rhs.testhashs32_fnv1) &&
(lhs.testhashu32_fnv1 == rhs.testhashu32_fnv1) &&
(lhs.testhashs64_fnv1 == rhs.testhashs64_fnv1) &&
(lhs.testhashu64_fnv1 == rhs.testhashu64_fnv1) &&
(lhs.testhashs32_fnv1a == rhs.testhashs32_fnv1a) &&
(lhs.testhashu32_fnv1a == rhs.testhashu32_fnv1a) &&
(lhs.testhashs64_fnv1a == rhs.testhashs64_fnv1a) &&
(lhs.testhashu64_fnv1a == rhs.testhashu64_fnv1a) &&
(lhs.testarrayofbools == rhs.testarrayofbools) &&
(lhs.testf == rhs.testf) &&
(lhs.testf2 == rhs.testf2) &&
(lhs.testf3 == rhs.testf3) &&
(lhs.testarrayofstring2 == rhs.testarrayofstring2) &&
(lhs.testarrayofsortedstruct == rhs.testarrayofsortedstruct) &&
(lhs.flex == rhs.flex) &&
(lhs.test5 == rhs.test5) &&
(lhs.vector_of_longs == rhs.vector_of_longs) &&
(lhs.vector_of_doubles == rhs.vector_of_doubles) &&
(lhs.parent_namespace_test == rhs.parent_namespace_test) &&
(lhs.vector_of_referrables == rhs.vector_of_referrables) &&
(lhs.single_weak_reference == rhs.single_weak_reference) &&
(lhs.vector_of_weak_references == rhs.vector_of_weak_references) &&
(lhs.vector_of_strong_referrables == rhs.vector_of_strong_referrables) &&
(lhs.co_owning_reference == rhs.co_owning_reference) &&
(lhs.vector_of_co_owning_references == rhs.vector_of_co_owning_references) &&
(lhs.non_owning_reference == rhs.non_owning_reference) &&
(lhs.vector_of_non_owning_references == rhs.vector_of_non_owning_references);
}
/// an example documentation comment: monster object /// an example documentation comment: monster object
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef MonsterT NativeTableType; typedef MonsterT NativeTableType;
...@@ -1507,6 +1642,22 @@ struct TypeAliasesT : public flatbuffers::NativeTable { ...@@ -1507,6 +1642,22 @@ struct TypeAliasesT : public flatbuffers::NativeTable {
} }
}; };
inline bool operator==(const TypeAliasesT &lhs, const TypeAliasesT &rhs) {
return
(lhs.i8 == rhs.i8) &&
(lhs.u8 == rhs.u8) &&
(lhs.i16 == rhs.i16) &&
(lhs.u16 == rhs.u16) &&
(lhs.i32 == rhs.i32) &&
(lhs.u32 == rhs.u32) &&
(lhs.i64 == rhs.i64) &&
(lhs.u64 == rhs.u64) &&
(lhs.f32 == rhs.f32) &&
(lhs.f64 == rhs.f64) &&
(lhs.v8 == rhs.v8) &&
(lhs.vf64 == rhs.vf64);
}
struct TypeAliases FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct TypeAliases FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef TypeAliasesT NativeTableType; typedef TypeAliasesT NativeTableType;
static const flatbuffers::TypeTable *MiniReflectTypeTable() { static const flatbuffers::TypeTable *MiniReflectTypeTable() {
......
...@@ -1978,6 +1978,25 @@ void UninitializedVectorTest() { ...@@ -1978,6 +1978,25 @@ void UninitializedVectorTest() {
TEST_EQ(test_1->b(), 40); TEST_EQ(test_1->b(), 40);
} }
void EqualOperatorTest() {
MonsterT a;
MonsterT b;
TEST_EQ(b == a, true);
b.mana = 33;
TEST_EQ(b == a, false);
b.mana = 150;
TEST_EQ(b == a, true);
b.inventory.push_back(3);
TEST_EQ(b == a, false);
b.inventory.clear();
TEST_EQ(b == a, true);
b.test.type = Any_Monster;
TEST_EQ(b == a, false);
}
// For testing any binaries, e.g. from fuzzing. // For testing any binaries, e.g. from fuzzing.
void LoadVerifyBinaryTest() { void LoadVerifyBinaryTest() {
std::string binary; std::string binary;
...@@ -2062,6 +2081,7 @@ int main(int /*argc*/, const char * /*argv*/ []) { ...@@ -2062,6 +2081,7 @@ int main(int /*argc*/, const char * /*argv*/ []) {
FlexBuffersTest(); FlexBuffersTest();
UninitializedVectorTest(); UninitializedVectorTest();
EqualOperatorTest();
if (!testing_fails) { if (!testing_fails) {
TEST_OUTPUT_LINE("ALL TESTS PASSED"); TEST_OUTPUT_LINE("ALL TESTS PASSED");
......
...@@ -16,6 +16,11 @@ struct BookReader; ...@@ -16,6 +16,11 @@ struct BookReader;
struct Movie; struct Movie;
struct MovieT; struct MovieT;
bool operator==(const AttackerT &lhs, const AttackerT &rhs);
bool operator==(const Rapunzel &lhs, const Rapunzel &rhs);
bool operator==(const BookReader &lhs, const BookReader &rhs);
bool operator==(const MovieT &lhs, const MovieT &rhs);
inline const flatbuffers::TypeTable *AttackerTypeTable(); inline const flatbuffers::TypeTable *AttackerTypeTable();
inline const flatbuffers::TypeTable *RapunzelTypeTable(); inline const flatbuffers::TypeTable *RapunzelTypeTable();
...@@ -138,6 +143,42 @@ struct CharacterUnion { ...@@ -138,6 +143,42 @@ struct CharacterUnion {
} }
}; };
inline bool operator==(const CharacterUnion &lhs, const CharacterUnion &rhs) {
if (lhs.type != rhs.type) return false;
switch (lhs.type) {
case Character_NONE: {
return true;
}
case Character_MuLan: {
return *(reinterpret_cast<const AttackerT *>(lhs.value)) ==
*(reinterpret_cast<const AttackerT *>(rhs.value));
}
case Character_Rapunzel: {
return *(reinterpret_cast<const Rapunzel *>(lhs.value)) ==
*(reinterpret_cast<const Rapunzel *>(rhs.value));
}
case Character_Belle: {
return *(reinterpret_cast<const BookReader *>(lhs.value)) ==
*(reinterpret_cast<const BookReader *>(rhs.value));
}
case Character_BookFan: {
return *(reinterpret_cast<const BookReader *>(lhs.value)) ==
*(reinterpret_cast<const BookReader *>(rhs.value));
}
case Character_Other: {
return *(reinterpret_cast<const std::string *>(lhs.value)) ==
*(reinterpret_cast<const std::string *>(rhs.value));
}
case Character_Unused: {
return *(reinterpret_cast<const std::string *>(lhs.value)) ==
*(reinterpret_cast<const std::string *>(rhs.value));
}
default: {
return false;
}
}
}
bool VerifyCharacter(flatbuffers::Verifier &verifier, const void *obj, Character type); bool VerifyCharacter(flatbuffers::Verifier &verifier, const void *obj, Character type);
bool VerifyCharacterVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types); bool VerifyCharacterVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
...@@ -161,6 +202,11 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Rapunzel FLATBUFFERS_FINAL_CLASS { ...@@ -161,6 +202,11 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Rapunzel FLATBUFFERS_FINAL_CLASS {
}; };
FLATBUFFERS_STRUCT_END(Rapunzel, 4); FLATBUFFERS_STRUCT_END(Rapunzel, 4);
inline bool operator==(const Rapunzel &lhs, const Rapunzel &rhs) {
return
(lhs.hair_length() == rhs.hair_length());
}
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) BookReader FLATBUFFERS_FINAL_CLASS { FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) BookReader FLATBUFFERS_FINAL_CLASS {
private: private:
int32_t books_read_; int32_t books_read_;
...@@ -181,6 +227,11 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) BookReader FLATBUFFERS_FINAL_CLASS { ...@@ -181,6 +227,11 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) BookReader FLATBUFFERS_FINAL_CLASS {
}; };
FLATBUFFERS_STRUCT_END(BookReader, 4); FLATBUFFERS_STRUCT_END(BookReader, 4);
inline bool operator==(const BookReader &lhs, const BookReader &rhs) {
return
(lhs.books_read() == rhs.books_read());
}
struct AttackerT : public flatbuffers::NativeTable { struct AttackerT : public flatbuffers::NativeTable {
typedef Attacker TableType; typedef Attacker TableType;
int32_t sword_attack_damage; int32_t sword_attack_damage;
...@@ -189,6 +240,11 @@ struct AttackerT : public flatbuffers::NativeTable { ...@@ -189,6 +240,11 @@ struct AttackerT : public flatbuffers::NativeTable {
} }
}; };
inline bool operator==(const AttackerT &lhs, const AttackerT &rhs) {
return
(lhs.sword_attack_damage == rhs.sword_attack_damage);
}
struct Attacker FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Attacker FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef AttackerT NativeTableType; typedef AttackerT NativeTableType;
static const flatbuffers::TypeTable *MiniReflectTypeTable() { static const flatbuffers::TypeTable *MiniReflectTypeTable() {
...@@ -249,6 +305,12 @@ struct MovieT : public flatbuffers::NativeTable { ...@@ -249,6 +305,12 @@ struct MovieT : public flatbuffers::NativeTable {
} }
}; };
inline bool operator==(const MovieT &lhs, const MovieT &rhs) {
return
(lhs.main_character == rhs.main_character) &&
(lhs.characters == rhs.characters);
}
struct Movie FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Movie FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef MovieT NativeTableType; typedef MovieT NativeTableType;
static const flatbuffers::TypeTable *MiniReflectTypeTable() { static const flatbuffers::TypeTable *MiniReflectTypeTable() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment