mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-04 04:33:23 +00:00
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
This commit is contained in:
committed by
Wouter van Oortmerssen
parent
873a60b0d8
commit
33791dc7b0
@@ -223,7 +223,7 @@ function(compile_flatbuffers_schema_to_cpp SRC_FBS)
|
||||
add_custom_command(
|
||||
OUTPUT ${GEN_HEADER}
|
||||
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
|
||||
--reflect-names
|
||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||
|
||||
@@ -96,6 +96,8 @@ Additional options:
|
||||
at the cost of efficiency (object allocation). Recommended only to be used
|
||||
if other options are insufficient.
|
||||
|
||||
- `--gen-compare` : Generate operator== for object-based API types.
|
||||
|
||||
- `--gen-onefile` : Generate single output file (useful for C#)
|
||||
|
||||
- `--gen-all`: Generate not just code for the current schema files, but
|
||||
|
||||
@@ -379,6 +379,7 @@ struct IDLOptions {
|
||||
bool skip_unexpected_fields_in_json;
|
||||
bool generate_name_strings;
|
||||
bool generate_object_based_api;
|
||||
bool gen_compare;
|
||||
std::string cpp_object_api_pointer_type;
|
||||
std::string cpp_object_api_string_type;
|
||||
bool gen_nullable;
|
||||
@@ -453,6 +454,7 @@ struct IDLOptions {
|
||||
skip_unexpected_fields_in_json(false),
|
||||
generate_name_strings(false),
|
||||
generate_object_based_api(false),
|
||||
gen_compare(false),
|
||||
cpp_object_api_pointer_type("std::unique_ptr"),
|
||||
gen_nullable(false),
|
||||
object_suffix("T"),
|
||||
|
||||
@@ -17,6 +17,10 @@ struct MonsterT;
|
||||
struct Weapon;
|
||||
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 *MonsterTypeTable();
|
||||
@@ -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 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 {
|
||||
};
|
||||
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 {
|
||||
typedef Monster TableType;
|
||||
flatbuffers::unique_ptr<Vec3> pos;
|
||||
@@ -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 {
|
||||
typedef MonsterT NativeTableType;
|
||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
@@ -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 {
|
||||
typedef WeaponT NativeTableType;
|
||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
|
||||
@@ -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-name-strings Generate type name functions for C++.\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-str-type T Set object API string type (default std::string)\n"
|
||||
" T::c_str() and T::length() must be supported\n"
|
||||
@@ -222,6 +223,8 @@ int FlatCompiler::Compile(int argc, const char **argv) {
|
||||
opts.generate_name_strings = true;
|
||||
} else if (arg == "--gen-object-api") {
|
||||
opts.generate_object_based_api = true;
|
||||
} else if (arg == "--gen-compare") {
|
||||
opts.gen_compare = true;
|
||||
} else if (arg == "--cpp-ptr-type") {
|
||||
if (++argi >= argc) Error("missing type following" + arg, true);
|
||||
opts.cpp_object_api_pointer_type = argv[argi];
|
||||
|
||||
@@ -226,14 +226,30 @@ class CppGenerator : public BaseGenerator {
|
||||
if (!struct_def.generated) {
|
||||
SetNameSpace(struct_def.defined_namespace);
|
||||
code_ += "struct " + Name(struct_def) + ";";
|
||||
if (parser_.opts.generate_object_based_api && !struct_def.fixed) {
|
||||
code_ += "struct " +
|
||||
NativeName(Name(struct_def), &struct_def, parser_.opts) +
|
||||
";";
|
||||
if (parser_.opts.generate_object_based_api) {
|
||||
auto nativeName = NativeName(Name(struct_def), &struct_def, parser_.opts);
|
||||
if (!struct_def.fixed) {
|
||||
code_ += "struct " + nativeName + ";";
|
||||
}
|
||||
}
|
||||
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.
|
||||
if (parser_.opts.mini_reflect != IDLOptions::kNone) {
|
||||
// To break cyclic dependencies, first pre-declare all tables/structs.
|
||||
@@ -1096,6 +1112,38 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
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) {
|
||||
@@ -1456,6 +1504,44 @@ class CppGenerator : public BaseGenerator {
|
||||
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) {
|
||||
if (auto native_custom_alloc =
|
||||
struct_def.attributes.Lookup("native_custom_alloc")) {
|
||||
@@ -1488,6 +1574,7 @@ class CppGenerator : public BaseGenerator {
|
||||
GenOperatorNewDelete(struct_def);
|
||||
GenDefaultConstructor(struct_def);
|
||||
code_ += "};";
|
||||
if (parser_.opts.gen_compare) GenCompareOperator(struct_def);
|
||||
code_ += "";
|
||||
}
|
||||
|
||||
@@ -2600,6 +2687,7 @@ class CppGenerator : public BaseGenerator {
|
||||
|
||||
code_.SetValue("STRUCT_BYTE_SIZE", NumToString(struct_def.bytesize));
|
||||
code_ += "FLATBUFFERS_STRUCT_END({{STRUCT_NAME}}, {{STRUCT_BYTE_SIZE}});";
|
||||
if (parser_.opts.gen_compare) GenCompareOperator(struct_def, "()");
|
||||
code_ += "";
|
||||
}
|
||||
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
set buildtype=Release
|
||||
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 --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 --jsonschema --schema -I include_test monster_test.fbs
|
||||
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 ../tests
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# 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 --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 --jsonschema --schema -I include_test monster_test.fbs
|
||||
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
|
||||
|
||||
@@ -44,6 +44,25 @@ struct TypeAliasesT;
|
||||
|
||||
} // 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();
|
||||
|
||||
namespace Example2 {
|
||||
@@ -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 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 {
|
||||
};
|
||||
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 {
|
||||
private:
|
||||
float x_;
|
||||
@@ -318,6 +367,16 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(16) Vec3 FLATBUFFERS_FINAL_CLASS {
|
||||
};
|
||||
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 {
|
||||
private:
|
||||
uint32_t id_;
|
||||
@@ -352,6 +411,12 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Ability FLATBUFFERS_FINAL_CLASS {
|
||||
};
|
||||
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
|
||||
|
||||
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 {
|
||||
typedef InParentNamespaceT NativeTableType;
|
||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
@@ -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 {
|
||||
typedef MonsterT NativeTableType;
|
||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
@@ -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 {
|
||||
typedef TestSimpleTableWithEnumT NativeTableType;
|
||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
@@ -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 {
|
||||
typedef StatT NativeTableType;
|
||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
@@ -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 {
|
||||
typedef ReferrableT NativeTableType;
|
||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
@@ -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
|
||||
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef MonsterT NativeTableType;
|
||||
@@ -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 {
|
||||
typedef TypeAliasesT NativeTableType;
|
||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
|
||||
@@ -1978,6 +1978,25 @@ void UninitializedVectorTest() {
|
||||
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.
|
||||
void LoadVerifyBinaryTest() {
|
||||
std::string binary;
|
||||
@@ -2062,6 +2081,7 @@ int main(int /*argc*/, const char * /*argv*/ []) {
|
||||
|
||||
FlexBuffersTest();
|
||||
UninitializedVectorTest();
|
||||
EqualOperatorTest();
|
||||
|
||||
if (!testing_fails) {
|
||||
TEST_OUTPUT_LINE("ALL TESTS PASSED");
|
||||
|
||||
@@ -16,6 +16,11 @@ struct BookReader;
|
||||
struct Movie;
|
||||
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 *RapunzelTypeTable();
|
||||
@@ -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 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 {
|
||||
};
|
||||
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 {
|
||||
private:
|
||||
int32_t books_read_;
|
||||
@@ -181,6 +227,11 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) BookReader FLATBUFFERS_FINAL_CLASS {
|
||||
};
|
||||
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 {
|
||||
typedef Attacker TableType;
|
||||
int32_t sword_attack_damage;
|
||||
@@ -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 {
|
||||
typedef AttackerT NativeTableType;
|
||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
@@ -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 {
|
||||
typedef MovieT NativeTableType;
|
||||
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
|
||||
|
||||
Reference in New Issue
Block a user