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:
Wouter van Oortmerssen 2016-10-05 16:59:15 -07:00
parent b2e55c556e
commit dc2fa215b8
10 changed files with 161 additions and 76 deletions

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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() {

View File

@ -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;
}
}

View File

@ -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:

View File

@ -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;

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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();