External references for the object API thru a resolver function.
This allows hashed string fields to be used for lookup of any C++ objects, a pointer to which are then stored in the object besides the original hash for easy access. Change-Id: I2247a13c349b905f1c54660becde2c818ad23e97 Tested: on Linux. Bug: 30204449
This commit is contained in:
parent
b2e55c556e
commit
dc2fa215b8
|
@ -106,6 +106,25 @@ To use:
|
|||
CreateMonster(fbb, monsterobj.get()); // Serialize into new buffer.
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
# External references.
|
||||
|
||||
An additional feature of the object API is the ability to allow you to load
|
||||
multiple independent FlatBuffers, and have them refer to eachothers objects
|
||||
using hashes which are then represented as typed pointers in the object API.
|
||||
|
||||
To make this work have a field in the objects you want to referred to which is
|
||||
using the string hashing feature (see `hash` attribute in the
|
||||
[schema](@ref flatbuffers_guide_writing_schema) documentation). Then you have
|
||||
a similar hash in the field referring to it, along with a `cpp_type`
|
||||
attribute specifying the C++ type this will refer to (this can be any C++
|
||||
type, and will get a `*` added).
|
||||
|
||||
Then, in JSON or however you create these buffers, make sure they use the
|
||||
same string (or hash).
|
||||
|
||||
When you call `UnPack` (or `Create`), you'll need a function that maps from
|
||||
hash to the object (see `resolver_function_t` for details).
|
||||
|
||||
## Reflection (& Resizing)
|
||||
|
||||
There is experimental support for reflection in FlatBuffers, allowing you to
|
||||
|
|
|
@ -304,6 +304,10 @@ Current understood attributes:
|
|||
- `key` (on a field): this field is meant to be used as a key when sorting
|
||||
a vector of the type of table it sits in. Can be used for in-place
|
||||
binary search.
|
||||
- `hash` (on a field). This is an (un)signed 32/64 bit integer field, whose
|
||||
value during JSON parsing is allowed to be a string, which will then be
|
||||
stored as its hash. The value of attribute is the hashing algorithm to
|
||||
use, one of `fnv1_32` `fnv1_64` `fnv1a_32` `fnv1a_64`.
|
||||
|
||||
## JSON Parsing
|
||||
|
||||
|
|
|
@ -1560,6 +1560,24 @@ class Table {
|
|||
struct NativeTable {
|
||||
};
|
||||
|
||||
/// @brief Function types to be used with resolving hashes into objects and
|
||||
/// back again. The resolver gets a pointer to a field inside an object API
|
||||
/// object that is of the type specified in the schema using the attribute
|
||||
/// `cpp_type` (it is thus important whatever you write to this address
|
||||
/// matches that type). The value of this field is initially null, so you
|
||||
/// may choose to implement a delayed binding lookup using this function
|
||||
/// if you wish. The resolver does the opposite lookup, for when the object
|
||||
/// is being serialized again.
|
||||
typedef uint64_t hash_value_t;
|
||||
#ifdef FLATBUFFERS_CPP98_STL
|
||||
typedef void (*resolver_function_t)(void **pointer_adr, hash_value_t hash);
|
||||
typedef hash_value_t (*rehasher_function_t)(void *pointer);
|
||||
#else
|
||||
typedef std::function<void (void **pointer_adr, hash_value_t hash)>
|
||||
resolver_function_t;
|
||||
typedef std::function<hash_value_t (void *pointer)> rehasher_function_t;
|
||||
#endif
|
||||
|
||||
// Helper function to test if a field is present, using any of the field
|
||||
// enums in the generated code.
|
||||
// `table` must be a generated table type. Since this is a template parameter,
|
||||
|
|
|
@ -450,6 +450,7 @@ class Parser : public ParserState {
|
|||
known_attributes_["csharp_partial"] = true;
|
||||
known_attributes_["streaming"] = true;
|
||||
known_attributes_["idempotent"] = true;
|
||||
known_attributes_["cpp_type"] = true;
|
||||
}
|
||||
|
||||
~Parser() {
|
||||
|
|
|
@ -47,8 +47,8 @@ struct EquipmentUnion {
|
|||
EquipmentUnion &operator=(const EquipmentUnion &);
|
||||
~EquipmentUnion();
|
||||
|
||||
static flatbuffers::NativeTable *UnPack(const void *union_obj, Equipment type);
|
||||
flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb) const;
|
||||
static flatbuffers::NativeTable *UnPack(const void *union_obj, Equipment type, const flatbuffers::resolver_function_t *resolver);
|
||||
flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *rehasher = nullptr) const;
|
||||
|
||||
WeaponT *AsWeapon() { return type == Equipment_Weapon ? reinterpret_cast<WeaponT *>(table) : nullptr; }
|
||||
};
|
||||
|
@ -142,7 +142,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||
VerifyEquipment(verifier, equipped(), equipped_type()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
std::unique_ptr<MonsterT> UnPack() const;
|
||||
std::unique_ptr<MonsterT> UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
|
||||
};
|
||||
|
||||
struct MonsterBuilder {
|
||||
|
@ -201,7 +201,7 @@ inline flatbuffers::Offset<Monster> CreateMonsterDirect(flatbuffers::FlatBufferB
|
|||
return CreateMonster(_fbb, pos, mana, hp, name ? _fbb.CreateString(name) : 0, inventory ? _fbb.CreateVector<uint8_t>(*inventory) : 0, color, weapons ? _fbb.CreateVector<flatbuffers::Offset<Weapon>>(*weapons) : 0, equipped_type, equipped);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o);
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *rehasher = nullptr);
|
||||
|
||||
struct WeaponT : public flatbuffers::NativeTable {
|
||||
std::string name;
|
||||
|
@ -224,7 +224,7 @@ struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||
VerifyField<int16_t>(verifier, VT_DAMAGE) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
std::unique_ptr<WeaponT> UnPack() const;
|
||||
std::unique_ptr<WeaponT> UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
|
||||
};
|
||||
|
||||
struct WeaponBuilder {
|
||||
|
@ -255,9 +255,9 @@ inline flatbuffers::Offset<Weapon> CreateWeaponDirect(flatbuffers::FlatBufferBui
|
|||
return CreateWeapon(_fbb, name ? _fbb.CreateString(name) : 0, damage);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o);
|
||||
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o, const flatbuffers::rehasher_function_t *rehasher = nullptr);
|
||||
|
||||
inline std::unique_ptr<MonsterT> Monster::UnPack() const {
|
||||
inline std::unique_ptr<MonsterT> Monster::UnPack(const flatbuffers::resolver_function_t *resolver) const {
|
||||
auto _o = new MonsterT();
|
||||
{ auto _e = pos(); if (_e) _o->pos = std::unique_ptr<Vec3>(new Vec3(*_e)); };
|
||||
{ auto _e = mana(); _o->mana = _e; };
|
||||
|
@ -265,13 +265,13 @@ inline std::unique_ptr<MonsterT> Monster::UnPack() const {
|
|||
{ auto _e = name(); if (_e) _o->name = _e->str(); };
|
||||
{ auto _e = inventory(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inventory.push_back(_e->Get(_i)); } } };
|
||||
{ auto _e = color(); _o->color = _e; };
|
||||
{ auto _e = weapons(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->weapons.push_back(_e->Get(_i)->UnPack()); } } };
|
||||
{ auto _e = weapons(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->weapons.push_back(_e->Get(_i)->UnPack(resolver)); } } };
|
||||
{ auto _e = equipped_type(); _o->equipped.type = _e; };
|
||||
{ auto _e = equipped(); if (_e) _o->equipped.table = EquipmentUnion::UnPack(_e, equipped_type()); };
|
||||
{ auto _e = equipped(); if (_e) _o->equipped.table = EquipmentUnion::UnPack(_e, equipped_type(), resolver); };
|
||||
return std::unique_ptr<MonsterT>(_o);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o) {
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *rehasher) {
|
||||
return CreateMonster(_fbb,
|
||||
_o->pos ? _o->pos.get() : 0,
|
||||
_o->mana,
|
||||
|
@ -279,19 +279,19 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder
|
|||
_o->name.size() ? _fbb.CreateString(_o->name) : 0,
|
||||
_o->inventory.size() ? _fbb.CreateVector(_o->inventory) : 0,
|
||||
_o->color,
|
||||
_o->weapons.size() ? _fbb.CreateVector<flatbuffers::Offset<Weapon>>(_o->weapons.size(), [&](size_t i) { return CreateWeapon(_fbb, _o->weapons[i].get()); }) : 0,
|
||||
_o->weapons.size() ? _fbb.CreateVector<flatbuffers::Offset<Weapon>>(_o->weapons.size(), [&](size_t i) { return CreateWeapon(_fbb, _o->weapons[i].get(), rehasher); }) : 0,
|
||||
_o->equipped.type,
|
||||
_o->equipped.Pack(_fbb));
|
||||
}
|
||||
|
||||
inline std::unique_ptr<WeaponT> Weapon::UnPack() const {
|
||||
inline std::unique_ptr<WeaponT> Weapon::UnPack(const flatbuffers::resolver_function_t *resolver) const {
|
||||
auto _o = new WeaponT();
|
||||
{ auto _e = name(); if (_e) _o->name = _e->str(); };
|
||||
{ auto _e = damage(); _o->damage = _e; };
|
||||
return std::unique_ptr<WeaponT>(_o);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o) {
|
||||
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o, const flatbuffers::rehasher_function_t *rehasher) {
|
||||
return CreateWeapon(_fbb,
|
||||
_o->name.size() ? _fbb.CreateString(_o->name) : 0,
|
||||
_o->damage);
|
||||
|
@ -305,18 +305,18 @@ inline bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *union_o
|
|||
}
|
||||
}
|
||||
|
||||
inline flatbuffers::NativeTable *EquipmentUnion::UnPack(const void *union_obj, Equipment type) {
|
||||
inline flatbuffers::NativeTable *EquipmentUnion::UnPack(const void *union_obj, Equipment type, const flatbuffers::resolver_function_t *resolver) {
|
||||
switch (type) {
|
||||
case Equipment_NONE: return nullptr;
|
||||
case Equipment_Weapon: return reinterpret_cast<const Weapon *>(union_obj)->UnPack().release();
|
||||
case Equipment_Weapon: return reinterpret_cast<const Weapon *>(union_obj)->UnPack(resolver).release();
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<void> EquipmentUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb) const {
|
||||
inline flatbuffers::Offset<void> EquipmentUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *rehasher) const {
|
||||
switch (type) {
|
||||
case Equipment_NONE: return 0;
|
||||
case Equipment_Weapon: return CreateWeapon(_fbb, reinterpret_cast<const WeaponT *>(table)).Union();
|
||||
case Equipment_Weapon: return CreateWeapon(_fbb, reinterpret_cast<const WeaponT *>(table), rehasher).Union();
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -361,25 +361,32 @@ class CppGenerator : public BaseGenerator {
|
|||
return (inclass ? "static " : "") +
|
||||
std::string("flatbuffers::NativeTable *") +
|
||||
(inclass ? "" : enum_def.name + "Union::") +
|
||||
"UnPack(const void *union_obj, " + enum_def.name + " type)";
|
||||
"UnPack(const void *union_obj, " + enum_def.name +
|
||||
" type, const flatbuffers::resolver_function_t *resolver)";
|
||||
}
|
||||
|
||||
std::string UnionPackSignature(EnumDef &enum_def, bool inclass) {
|
||||
return "flatbuffers::Offset<void> " +
|
||||
(inclass ? "" : enum_def.name + "Union::") +
|
||||
"Pack(flatbuffers::FlatBufferBuilder &_fbb) const";
|
||||
"Pack(flatbuffers::FlatBufferBuilder &_fbb, " +
|
||||
"const flatbuffers::rehasher_function_t *rehasher" +
|
||||
(inclass ? " = nullptr" : "") + ") const";
|
||||
}
|
||||
|
||||
std::string TableCreateSignature(StructDef &struct_def) {
|
||||
std::string TableCreateSignature(StructDef &struct_def, bool predecl) {
|
||||
return "inline flatbuffers::Offset<" + struct_def.name + "> Create" +
|
||||
struct_def.name +
|
||||
"(flatbuffers::FlatBufferBuilder &_fbb, const " +
|
||||
NativeName(struct_def.name) + " *_o)";
|
||||
NativeName(struct_def.name) +
|
||||
" *_o, const flatbuffers::rehasher_function_t *rehasher" +
|
||||
(predecl ? " = nullptr" : "") + ")";
|
||||
}
|
||||
|
||||
std::string TableUnPackSignature(StructDef &struct_def, bool inclass) {
|
||||
return "std::unique_ptr<" + NativeName(struct_def.name) + "> " +
|
||||
(inclass ? "" : struct_def.name + "::") + "UnPack() const";
|
||||
(inclass ? "" : struct_def.name + "::") +
|
||||
"UnPack(const flatbuffers::resolver_function_t *resolver" +
|
||||
(inclass ? " = nullptr" : "") + ") const";
|
||||
}
|
||||
|
||||
// Generate an enum declaration and an enum string lookup table.
|
||||
|
@ -524,7 +531,7 @@ class CppGenerator : public BaseGenerator {
|
|||
} else {
|
||||
code += ": return reinterpret_cast<const ";
|
||||
code += WrapInNameSpace(*ev.struct_def);
|
||||
code += " *>(union_obj)->UnPack().release();\n";
|
||||
code += " *>(union_obj)->UnPack(resolver).release();\n";
|
||||
}
|
||||
}
|
||||
code += " default: return nullptr;\n }\n}\n\n";
|
||||
|
@ -540,7 +547,7 @@ class CppGenerator : public BaseGenerator {
|
|||
code += ": return Create" + ev.struct_def->name;
|
||||
code += "(_fbb, reinterpret_cast<const ";
|
||||
code += NativeName(WrapInNameSpace(*ev.struct_def));
|
||||
code += " *>(table)).Union();\n";
|
||||
code += " *>(table), rehasher).Union();\n";
|
||||
}
|
||||
}
|
||||
code += " default: return 0;\n }\n}\n\n";
|
||||
|
@ -638,8 +645,10 @@ class CppGenerator : public BaseGenerator {
|
|||
auto &field = **it;
|
||||
if (!field.deprecated && // Deprecated fields won't be accessible.
|
||||
field.value.type.base_type != BASE_TYPE_UTYPE) {
|
||||
code += " " + GenTypeNative(field.value.type, false) + " ";
|
||||
code += field.name + ";\n";
|
||||
auto type = GenTypeNative(field.value.type, false);
|
||||
auto cpp_type = field.attributes.Lookup("cpp_type");
|
||||
code += " " + (cpp_type ? cpp_type->constant + " *" : type+ " ") +
|
||||
field.name + ";\n";
|
||||
}
|
||||
}
|
||||
code += "};\n\n";
|
||||
|
@ -945,7 +954,7 @@ class CppGenerator : public BaseGenerator {
|
|||
if (parser_.opts.generate_object_based_api) {
|
||||
// Generate a pre-declaration for a CreateX method that works with an
|
||||
// unpacked C++ object.
|
||||
code += TableCreateSignature(struct_def) + ";\n\n";
|
||||
code += TableCreateSignature(struct_def, true) + ";\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -982,7 +991,7 @@ class CppGenerator : public BaseGenerator {
|
|||
WrapInNameSpace (*type.struct_def) + "(*" + val + "))";
|
||||
}
|
||||
} else {
|
||||
return val + "->UnPack()";
|
||||
return val + "->UnPack(resolver)";
|
||||
}
|
||||
default:
|
||||
return val;
|
||||
|
@ -1009,17 +1018,29 @@ class CppGenerator : public BaseGenerator {
|
|||
code += prefix + deref + union_field.name + ".type = _e;";
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_UNION:
|
||||
case BASE_TYPE_UNION: {
|
||||
code += prefix + dest + ".table = ";
|
||||
code += field.value.type.enum_def->name;
|
||||
code += "Union::UnPack(_e, ";
|
||||
code += field.name + UnionTypeFieldSuffix() + "());";
|
||||
code += field.name + UnionTypeFieldSuffix() + "(), resolver);";
|
||||
break;
|
||||
default:
|
||||
code += assign + gen_unpack_val(field.value.type, "_e", false);
|
||||
}
|
||||
default: {
|
||||
auto cpp_type = field.attributes.Lookup("cpp_type");
|
||||
if (cpp_type) {
|
||||
code += prefix;
|
||||
code += "if (resolver) (*resolver)(reinterpret_cast<void **>(&";
|
||||
code += dest;
|
||||
code += "), static_cast<flatbuffers::hash_value_t>(_e)); else ";
|
||||
code += dest + " = nullptr";
|
||||
} else {
|
||||
code += assign;
|
||||
code += gen_unpack_val(field.value.type, "_e", false);
|
||||
}
|
||||
code += ";";
|
||||
break;
|
||||
}
|
||||
}
|
||||
code += " };\n";
|
||||
}
|
||||
}
|
||||
|
@ -1027,7 +1048,7 @@ class CppGenerator : public BaseGenerator {
|
|||
code += ">(_o);\n}\n\n";
|
||||
|
||||
// Generate a CreateX method that works with an unpacked C++ object.
|
||||
code += TableCreateSignature(struct_def) + " {\n";
|
||||
code += TableCreateSignature(struct_def, false) + " {\n";
|
||||
auto before_return_statement = code.size();
|
||||
code += " return Create";
|
||||
code += struct_def.name + "(_fbb";
|
||||
|
@ -1044,6 +1065,10 @@ class CppGenerator : public BaseGenerator {
|
|||
field_name += ".type";
|
||||
}
|
||||
auto accessor = "_o->" + field_name;
|
||||
if (field.attributes.Lookup("cpp_type"))
|
||||
accessor = "rehasher ? static_cast<" +
|
||||
GenTypeBasic(field.value.type, false) +
|
||||
">((*rehasher)(" + accessor + ")) : 0";
|
||||
auto ptrprefix = accessor + " ? ";
|
||||
auto stlprefix = accessor + ".size() ? ";
|
||||
auto postfix = " : 0";
|
||||
|
@ -1074,7 +1099,7 @@ class CppGenerator : public BaseGenerator {
|
|||
code += vector_type.struct_def->name + ">>(" + accessor;
|
||||
code += ".size(), [&](size_t i) { return Create";
|
||||
code += vector_type.struct_def->name + "(_fbb, " + accessor;
|
||||
code += "[i].get()); })";
|
||||
code += "[i].get(), rehasher); })";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -1093,7 +1118,7 @@ class CppGenerator : public BaseGenerator {
|
|||
} else {
|
||||
code += ptrprefix + "Create";
|
||||
code += field.value.type.struct_def->name;
|
||||
code += "(_fbb, " + accessor + ".get())" + postfix;
|
||||
code += "(_fbb, " + accessor + ".get(), rehasher)" + postfix;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -657,6 +657,11 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
|
|||
"only int, uint, long and ulong data types support hashing.");
|
||||
}
|
||||
}
|
||||
auto cpp_type = field->attributes.Lookup("cpp_type");
|
||||
if (cpp_type) {
|
||||
if (!hash_name)
|
||||
return Error("cpp_type can only be used with a hashed field");
|
||||
}
|
||||
if (field->deprecated && struct_def.fixed)
|
||||
return Error("can't deprecate fields in a struct");
|
||||
field->required = field->attributes.Lookup("required") != nullptr;
|
||||
|
|
|
@ -61,7 +61,7 @@ table Monster {
|
|||
testhashs64_fnv1:long (id:18, hash:"fnv1_64");
|
||||
testhashu64_fnv1:ulong (id:19, hash:"fnv1_64");
|
||||
testhashs32_fnv1a:int (id:20, hash:"fnv1a_32");
|
||||
testhashu32_fnv1a:uint (id:21, hash:"fnv1a_32");
|
||||
testhashu32_fnv1a:uint (id:21, hash:"fnv1a_32", cpp_type:"Stat");
|
||||
testhashs64_fnv1a:long (id:22, hash:"fnv1a_64");
|
||||
testhashu64_fnv1a:ulong (id:23, hash:"fnv1a_64");
|
||||
testf:float = 3.14159 (id:25);
|
||||
|
|
|
@ -61,8 +61,8 @@ struct AnyUnion {
|
|||
AnyUnion &operator=(const AnyUnion &);
|
||||
~AnyUnion();
|
||||
|
||||
static flatbuffers::NativeTable *UnPack(const void *union_obj, Any type);
|
||||
flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb) const;
|
||||
static flatbuffers::NativeTable *UnPack(const void *union_obj, Any type, const flatbuffers::resolver_function_t *resolver);
|
||||
flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *rehasher = nullptr) const;
|
||||
|
||||
MonsterT *AsMonster() { return type == Any_Monster ? reinterpret_cast<MonsterT *>(table) : nullptr; }
|
||||
TestSimpleTableWithEnumT *AsTestSimpleTableWithEnum() { return type == Any_TestSimpleTableWithEnum ? reinterpret_cast<TestSimpleTableWithEnumT *>(table) : nullptr; }
|
||||
|
@ -142,7 +142,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||
return VerifyTableStart(verifier) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
std::unique_ptr<MonsterT> UnPack() const;
|
||||
std::unique_ptr<MonsterT> UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
|
||||
};
|
||||
|
||||
struct MonsterBuilder {
|
||||
|
@ -161,7 +161,7 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder
|
|||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o);
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *rehasher = nullptr);
|
||||
|
||||
} // namespace Example2
|
||||
|
||||
|
@ -182,7 +182,7 @@ struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Ta
|
|||
VerifyField<int8_t>(verifier, VT_COLOR) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
std::unique_ptr<TestSimpleTableWithEnumT> UnPack() const;
|
||||
std::unique_ptr<TestSimpleTableWithEnumT> UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
|
||||
};
|
||||
|
||||
struct TestSimpleTableWithEnumBuilder {
|
||||
|
@ -204,7 +204,7 @@ inline flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnu
|
|||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(flatbuffers::FlatBufferBuilder &_fbb, const TestSimpleTableWithEnumT *_o);
|
||||
inline flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(flatbuffers::FlatBufferBuilder &_fbb, const TestSimpleTableWithEnumT *_o, const flatbuffers::rehasher_function_t *rehasher = nullptr);
|
||||
|
||||
struct StatT : public flatbuffers::NativeTable {
|
||||
std::string id;
|
||||
|
@ -232,7 +232,7 @@ struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||
VerifyField<uint16_t>(verifier, VT_COUNT) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
std::unique_ptr<StatT> UnPack() const;
|
||||
std::unique_ptr<StatT> UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
|
||||
};
|
||||
|
||||
struct StatBuilder {
|
||||
|
@ -267,7 +267,7 @@ inline flatbuffers::Offset<Stat> CreateStatDirect(flatbuffers::FlatBufferBuilder
|
|||
return CreateStat(_fbb, id ? _fbb.CreateString(id) : 0, val, count);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb, const StatT *_o);
|
||||
inline flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb, const StatT *_o, const flatbuffers::rehasher_function_t *rehasher = nullptr);
|
||||
|
||||
struct MonsterT : public flatbuffers::NativeTable {
|
||||
std::unique_ptr<Vec3> pos;
|
||||
|
@ -289,7 +289,7 @@ struct MonsterT : public flatbuffers::NativeTable {
|
|||
int64_t testhashs64_fnv1;
|
||||
uint64_t testhashu64_fnv1;
|
||||
int32_t testhashs32_fnv1a;
|
||||
uint32_t testhashu32_fnv1a;
|
||||
Stat *testhashu32_fnv1a;
|
||||
int64_t testhashs64_fnv1a;
|
||||
uint64_t testhashu64_fnv1a;
|
||||
std::vector<bool> testarrayofbools;
|
||||
|
@ -438,7 +438,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||
verifier.VerifyVectorOfStrings(testarrayofstring2()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
std::unique_ptr<MonsterT> UnPack() const;
|
||||
std::unique_ptr<MonsterT> UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
|
||||
};
|
||||
|
||||
struct MonsterBuilder {
|
||||
|
@ -574,18 +574,18 @@ inline flatbuffers::Offset<Monster> CreateMonsterDirect(flatbuffers::FlatBufferB
|
|||
return CreateMonster(_fbb, pos, mana, hp, name ? _fbb.CreateString(name) : 0, inventory ? _fbb.CreateVector<uint8_t>(*inventory) : 0, color, test_type, test, test4 ? _fbb.CreateVector<const Test *>(*test4) : 0, testarrayofstring ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*testarrayofstring) : 0, testarrayoftables ? _fbb.CreateVector<flatbuffers::Offset<Monster>>(*testarrayoftables) : 0, enemy, testnestedflatbuffer ? _fbb.CreateVector<uint8_t>(*testnestedflatbuffer) : 0, testempty, testbool, testhashs32_fnv1, testhashu32_fnv1, testhashs64_fnv1, testhashu64_fnv1, testhashs32_fnv1a, testhashu32_fnv1a, testhashs64_fnv1a, testhashu64_fnv1a, testarrayofbools ? _fbb.CreateVector<uint8_t>(*testarrayofbools) : 0, testf, testf2, testf3, testarrayofstring2 ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*testarrayofstring2) : 0);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o);
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *rehasher = nullptr);
|
||||
|
||||
} // namespace Example
|
||||
|
||||
namespace Example2 {
|
||||
|
||||
inline std::unique_ptr<MonsterT> Monster::UnPack() const {
|
||||
inline std::unique_ptr<MonsterT> Monster::UnPack(const flatbuffers::resolver_function_t *resolver) const {
|
||||
auto _o = new MonsterT();
|
||||
return std::unique_ptr<MonsterT>(_o);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o) {
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *rehasher) {
|
||||
(void)_o;
|
||||
return CreateMonster(_fbb);
|
||||
}
|
||||
|
@ -594,18 +594,18 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder
|
|||
|
||||
namespace Example {
|
||||
|
||||
inline std::unique_ptr<TestSimpleTableWithEnumT> TestSimpleTableWithEnum::UnPack() const {
|
||||
inline std::unique_ptr<TestSimpleTableWithEnumT> TestSimpleTableWithEnum::UnPack(const flatbuffers::resolver_function_t *resolver) const {
|
||||
auto _o = new TestSimpleTableWithEnumT();
|
||||
{ auto _e = color(); _o->color = _e; };
|
||||
return std::unique_ptr<TestSimpleTableWithEnumT>(_o);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(flatbuffers::FlatBufferBuilder &_fbb, const TestSimpleTableWithEnumT *_o) {
|
||||
inline flatbuffers::Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(flatbuffers::FlatBufferBuilder &_fbb, const TestSimpleTableWithEnumT *_o, const flatbuffers::rehasher_function_t *rehasher) {
|
||||
return CreateTestSimpleTableWithEnum(_fbb,
|
||||
_o->color);
|
||||
}
|
||||
|
||||
inline std::unique_ptr<StatT> Stat::UnPack() const {
|
||||
inline std::unique_ptr<StatT> Stat::UnPack(const flatbuffers::resolver_function_t *resolver) const {
|
||||
auto _o = new StatT();
|
||||
{ auto _e = id(); if (_e) _o->id = _e->str(); };
|
||||
{ auto _e = val(); _o->val = _e; };
|
||||
|
@ -613,14 +613,14 @@ inline std::unique_ptr<StatT> Stat::UnPack() const {
|
|||
return std::unique_ptr<StatT>(_o);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb, const StatT *_o) {
|
||||
inline flatbuffers::Offset<Stat> CreateStat(flatbuffers::FlatBufferBuilder &_fbb, const StatT *_o, const flatbuffers::rehasher_function_t *rehasher) {
|
||||
return CreateStat(_fbb,
|
||||
_o->id.size() ? _fbb.CreateString(_o->id) : 0,
|
||||
_o->val,
|
||||
_o->count);
|
||||
}
|
||||
|
||||
inline std::unique_ptr<MonsterT> Monster::UnPack() const {
|
||||
inline std::unique_ptr<MonsterT> Monster::UnPack(const flatbuffers::resolver_function_t *resolver) const {
|
||||
auto _o = new MonsterT();
|
||||
{ auto _e = pos(); if (_e) _o->pos = std::unique_ptr<Vec3>(new Vec3(*_e)); };
|
||||
{ auto _e = mana(); _o->mana = _e; };
|
||||
|
@ -629,20 +629,20 @@ inline std::unique_ptr<MonsterT> Monster::UnPack() const {
|
|||
{ auto _e = inventory(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inventory.push_back(_e->Get(_i)); } } };
|
||||
{ auto _e = color(); _o->color = _e; };
|
||||
{ auto _e = test_type(); _o->test.type = _e; };
|
||||
{ auto _e = test(); if (_e) _o->test.table = AnyUnion::UnPack(_e, test_type()); };
|
||||
{ auto _e = test(); if (_e) _o->test.table = AnyUnion::UnPack(_e, test_type(), resolver); };
|
||||
{ auto _e = test4(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->test4.push_back(*_e->Get(_i)); } } };
|
||||
{ auto _e = testarrayofstring(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofstring.push_back(_e->Get(_i)->str()); } } };
|
||||
{ auto _e = testarrayoftables(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayoftables.push_back(_e->Get(_i)->UnPack()); } } };
|
||||
{ auto _e = enemy(); if (_e) _o->enemy = _e->UnPack(); };
|
||||
{ auto _e = testarrayoftables(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayoftables.push_back(_e->Get(_i)->UnPack(resolver)); } } };
|
||||
{ auto _e = enemy(); if (_e) _o->enemy = _e->UnPack(resolver); };
|
||||
{ auto _e = testnestedflatbuffer(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testnestedflatbuffer.push_back(_e->Get(_i)); } } };
|
||||
{ auto _e = testempty(); if (_e) _o->testempty = _e->UnPack(); };
|
||||
{ auto _e = testempty(); if (_e) _o->testempty = _e->UnPack(resolver); };
|
||||
{ auto _e = testbool(); _o->testbool = _e; };
|
||||
{ auto _e = testhashs32_fnv1(); _o->testhashs32_fnv1 = _e; };
|
||||
{ auto _e = testhashu32_fnv1(); _o->testhashu32_fnv1 = _e; };
|
||||
{ auto _e = testhashs64_fnv1(); _o->testhashs64_fnv1 = _e; };
|
||||
{ auto _e = testhashu64_fnv1(); _o->testhashu64_fnv1 = _e; };
|
||||
{ auto _e = testhashs32_fnv1a(); _o->testhashs32_fnv1a = _e; };
|
||||
{ auto _e = testhashu32_fnv1a(); _o->testhashu32_fnv1a = _e; };
|
||||
{ auto _e = testhashu32_fnv1a(); if (resolver) (*resolver)(reinterpret_cast<void **>(&_o->testhashu32_fnv1a), static_cast<flatbuffers::hash_value_t>(_e)); else _o->testhashu32_fnv1a = nullptr; };
|
||||
{ auto _e = testhashs64_fnv1a(); _o->testhashs64_fnv1a = _e; };
|
||||
{ auto _e = testhashu64_fnv1a(); _o->testhashu64_fnv1a = _e; };
|
||||
{ auto _e = testarrayofbools(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofbools.push_back(_e->Get(_i)!=0); } } };
|
||||
|
@ -653,7 +653,7 @@ inline std::unique_ptr<MonsterT> Monster::UnPack() const {
|
|||
return std::unique_ptr<MonsterT>(_o);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o) {
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *rehasher) {
|
||||
return CreateMonster(_fbb,
|
||||
_o->pos ? _o->pos.get() : 0,
|
||||
_o->mana,
|
||||
|
@ -665,17 +665,17 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder
|
|||
_o->test.Pack(_fbb),
|
||||
_o->test4.size() ? _fbb.CreateVectorOfStructs(_o->test4) : 0,
|
||||
_o->testarrayofstring.size() ? _fbb.CreateVectorOfStrings(_o->testarrayofstring) : 0,
|
||||
_o->testarrayoftables.size() ? _fbb.CreateVector<flatbuffers::Offset<Monster>>(_o->testarrayoftables.size(), [&](size_t i) { return CreateMonster(_fbb, _o->testarrayoftables[i].get()); }) : 0,
|
||||
_o->enemy ? CreateMonster(_fbb, _o->enemy.get()) : 0,
|
||||
_o->testarrayoftables.size() ? _fbb.CreateVector<flatbuffers::Offset<Monster>>(_o->testarrayoftables.size(), [&](size_t i) { return CreateMonster(_fbb, _o->testarrayoftables[i].get(), rehasher); }) : 0,
|
||||
_o->enemy ? CreateMonster(_fbb, _o->enemy.get(), rehasher) : 0,
|
||||
_o->testnestedflatbuffer.size() ? _fbb.CreateVector(_o->testnestedflatbuffer) : 0,
|
||||
_o->testempty ? CreateStat(_fbb, _o->testempty.get()) : 0,
|
||||
_o->testempty ? CreateStat(_fbb, _o->testempty.get(), rehasher) : 0,
|
||||
_o->testbool,
|
||||
_o->testhashs32_fnv1,
|
||||
_o->testhashu32_fnv1,
|
||||
_o->testhashs64_fnv1,
|
||||
_o->testhashu64_fnv1,
|
||||
_o->testhashs32_fnv1a,
|
||||
_o->testhashu32_fnv1a,
|
||||
rehasher ? static_cast<uint32_t>((*rehasher)(_o->testhashu32_fnv1a)) : 0,
|
||||
_o->testhashs64_fnv1a,
|
||||
_o->testhashu64_fnv1a,
|
||||
_o->testarrayofbools.size() ? _fbb.CreateVector(_o->testarrayofbools) : 0,
|
||||
|
@ -695,22 +695,22 @@ inline bool VerifyAny(flatbuffers::Verifier &verifier, const void *union_obj, An
|
|||
}
|
||||
}
|
||||
|
||||
inline flatbuffers::NativeTable *AnyUnion::UnPack(const void *union_obj, Any type) {
|
||||
inline flatbuffers::NativeTable *AnyUnion::UnPack(const void *union_obj, Any type, const flatbuffers::resolver_function_t *resolver) {
|
||||
switch (type) {
|
||||
case Any_NONE: return nullptr;
|
||||
case Any_Monster: return reinterpret_cast<const Monster *>(union_obj)->UnPack().release();
|
||||
case Any_TestSimpleTableWithEnum: return reinterpret_cast<const TestSimpleTableWithEnum *>(union_obj)->UnPack().release();
|
||||
case Any_MyGame_Example2_Monster: return reinterpret_cast<const MyGame::Example2::Monster *>(union_obj)->UnPack().release();
|
||||
case Any_Monster: return reinterpret_cast<const Monster *>(union_obj)->UnPack(resolver).release();
|
||||
case Any_TestSimpleTableWithEnum: return reinterpret_cast<const TestSimpleTableWithEnum *>(union_obj)->UnPack(resolver).release();
|
||||
case Any_MyGame_Example2_Monster: return reinterpret_cast<const MyGame::Example2::Monster *>(union_obj)->UnPack(resolver).release();
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<void> AnyUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb) const {
|
||||
inline flatbuffers::Offset<void> AnyUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *rehasher) const {
|
||||
switch (type) {
|
||||
case Any_NONE: return 0;
|
||||
case Any_Monster: return CreateMonster(_fbb, reinterpret_cast<const MonsterT *>(table)).Union();
|
||||
case Any_TestSimpleTableWithEnum: return CreateTestSimpleTableWithEnum(_fbb, reinterpret_cast<const TestSimpleTableWithEnumT *>(table)).Union();
|
||||
case Any_MyGame_Example2_Monster: return CreateMonster(_fbb, reinterpret_cast<const MyGame::Example2::MonsterT *>(table)).Union();
|
||||
case Any_Monster: return CreateMonster(_fbb, reinterpret_cast<const MonsterT *>(table), rehasher).Union();
|
||||
case Any_TestSimpleTableWithEnum: return CreateTestSimpleTableWithEnum(_fbb, reinterpret_cast<const TestSimpleTableWithEnumT *>(table), rehasher).Union();
|
||||
case Any_MyGame_Example2_Monster: return CreateMonster(_fbb, reinterpret_cast<const MyGame::Example2::MonsterT *>(table), rehasher).Union();
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -314,17 +314,30 @@ void MutateFlatBuffersTest(uint8_t *flatbuf, std::size_t length) {
|
|||
|
||||
// Unpack a FlatBuffer into objects.
|
||||
void ObjectFlatBuffersTest(uint8_t *flatbuf) {
|
||||
// Optional: we can specify resolver and rehasher functions to turn hashed
|
||||
// strings into object pointers and back, to implement remote references
|
||||
// and such.
|
||||
auto resolver = flatbuffers::resolver_function_t([](void **pointer_adr,
|
||||
flatbuffers::hash_value_t hash) {
|
||||
return nullptr; // Fail the lookup.
|
||||
});
|
||||
auto rehasher = flatbuffers::rehasher_function_t([](void *pointer) {
|
||||
return 0;
|
||||
});
|
||||
|
||||
// Turn a buffer into C++ objects.
|
||||
auto monster1 = GetMonster(flatbuf)->UnPack();
|
||||
auto monster1 = GetMonster(flatbuf)->UnPack(&resolver);
|
||||
|
||||
// Re-serialize the data.
|
||||
flatbuffers::FlatBufferBuilder fbb1;
|
||||
fbb1.Finish(CreateMonster(fbb1, monster1.get()), MonsterIdentifier());
|
||||
fbb1.Finish(CreateMonster(fbb1, monster1.get(), &rehasher),
|
||||
MonsterIdentifier());
|
||||
|
||||
// Unpack again, and re-serialize again.
|
||||
auto monster2 = GetMonster(fbb1.GetBufferPointer())->UnPack();
|
||||
auto monster2 = GetMonster(fbb1.GetBufferPointer())->UnPack(&resolver);
|
||||
flatbuffers::FlatBufferBuilder fbb2;
|
||||
fbb2.Finish(CreateMonster(fbb2, monster2.get()), MonsterIdentifier());
|
||||
fbb2.Finish(CreateMonster(fbb2, monster2.get(), &rehasher),
|
||||
MonsterIdentifier());
|
||||
|
||||
// Now we've gone full round-trip, the two buffers should match.
|
||||
auto len1 = fbb1.GetSize();
|
||||
|
|
Loading…
Reference in New Issue