Added support for structs and strings in unions.

(C++ only for now).
Also fixed vector of union support in the object API.

Bug: 36902939
Change-Id: I935f4cc2c303a4728e26c7916a8ec0adcd6f84cb
Tested: on Linux.
parent 1fc12e0e
...@@ -411,4 +411,22 @@ manually wrap it in synchronisation primites. There's no automatic way to ...@@ -411,4 +411,22 @@ manually wrap it in synchronisation primites. There's no automatic way to
accomplish this, by design, as we feel multithreaded construction accomplish this, by design, as we feel multithreaded construction
of a single buffer will be rare, and synchronisation overhead would be costly. of a single buffer will be rare, and synchronisation overhead would be costly.
## Advanced union features
The C++ implementation currently supports vectors of unions (i.e. you can
declare a field as `[T]` where `T` is a union type instead of a table type). It
also supports structs and strings in unions, besides tables.
For an example of these features, see `tests/union_vector`, and
`UnionVectorTest` in `test.cpp`.
Since these features haven't been ported to other languages yet, if you
choose to use them, you won't be able to use these buffers in other languages
(`flatc` will refuse to compile a schema that uses these features).
These features reduce the amount of "table wrapping" that was previously
needed to use unions.
To use scalars, simply wrap them in a struct.
<br> <br>
...@@ -360,6 +360,8 @@ private: ...@@ -360,6 +360,8 @@ private:
const uint8_t *data_; const uint8_t *data_;
}; };
struct String;
// This is used as a helper type for accessing vectors. // This is used as a helper type for accessing vectors.
// Vector::data() assumes the vector elements start after the length field. // Vector::data() assumes the vector elements start after the length field.
template<typename T> class Vector { template<typename T> class Vector {
...@@ -391,6 +393,18 @@ public: ...@@ -391,6 +393,18 @@ public:
return static_cast<E>(Get(i)); return static_cast<E>(Get(i));
} }
// If this a vector of unions, this does the cast for you. There's no check
// to make sure this is the right type!
template<typename U> const U *GetAs(uoffset_t i) const {
return reinterpret_cast<const U *>(Get(i));
}
// If this a vector of unions, this does the cast for you. There's no check
// to make sure this is actually a string!
const String *GetAsString(uoffset_t i) const {
return reinterpret_cast<const String *>(Get(i));
}
const void *GetStructFromOffset(size_t o) const { const void *GetStructFromOffset(size_t o) const {
return reinterpret_cast<const void *>(Data() + o); return reinterpret_cast<const void *>(Data() + o);
} }
...@@ -1327,6 +1341,13 @@ FLATBUFFERS_FINAL_CLASS ...@@ -1327,6 +1341,13 @@ FLATBUFFERS_FINAL_CLASS
reinterpret_cast<uint8_t **>(buf)); reinterpret_cast<uint8_t **>(buf));
} }
/// @brief Write a struct by itself, typically to be part of a union.
template<typename T> Offset<const T *> CreateStruct(const T &structobj) {
Align(AlignOf<T>());
buf_.push_small(structobj);
return Offset<const T *>(GetSize());
}
/// @brief The length of a FlatBuffer file header. /// @brief The length of a FlatBuffer file header.
static const size_t kFileIdentifierLength = 4; static const size_t kFileIdentifierLength = 4;
......
...@@ -283,18 +283,18 @@ inline size_t InlineAlignment(const Type &type) { ...@@ -283,18 +283,18 @@ inline size_t InlineAlignment(const Type &type) {
struct EnumVal { struct EnumVal {
EnumVal(const std::string &_name, int64_t _val) EnumVal(const std::string &_name, int64_t _val)
: name(_name), value(_val), struct_def(nullptr) {} : name(_name), value(_val) {}
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder) const; Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder) const;
std::string name; std::string name;
std::vector<std::string> doc_comment; std::vector<std::string> doc_comment;
int64_t value; int64_t value;
StructDef *struct_def; // only set if this is a union Type union_type;
}; };
struct EnumDef : public Definition { struct EnumDef : public Definition {
EnumDef() : is_union(false) {} EnumDef() : is_union(false), uses_type_aliases(false) {}
EnumVal *ReverseLookup(int enum_idx, bool skip_union_default = true) { EnumVal *ReverseLookup(int enum_idx, bool skip_union_default = true) {
for (auto it = vals.vec.begin() + static_cast<int>(is_union && for (auto it = vals.vec.begin() + static_cast<int>(is_union &&
...@@ -312,6 +312,7 @@ struct EnumDef : public Definition { ...@@ -312,6 +312,7 @@ struct EnumDef : public Definition {
SymbolTable<EnumVal> vals; SymbolTable<EnumVal> vals;
bool is_union; bool is_union;
bool uses_type_aliases;
Type underlying_type; Type underlying_type;
}; };
...@@ -548,6 +549,7 @@ private: ...@@ -548,6 +549,7 @@ private:
const std::string &name, const Type &type, const std::string &name, const Type &type,
FieldDef **dest); FieldDef **dest);
FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def); FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def);
FLATBUFFERS_CHECKED_ERROR ParseString(Value &val);
FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field, FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
size_t parent_fieldn, size_t parent_fieldn,
const StructDef *parent_struct_def); const StructDef *parent_struct_def);
......
...@@ -204,7 +204,8 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { ...@@ -204,7 +204,8 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
enum { enum {
VT_NAME = 4, VT_NAME = 4,
VT_VALUE = 6, VT_VALUE = 6,
VT_OBJECT = 8 VT_OBJECT = 8,
VT_UNION_TYPE = 10
}; };
const flatbuffers::String *name() const { const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(VT_NAME); return GetPointer<const flatbuffers::String *>(VT_NAME);
...@@ -228,6 +229,9 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { ...@@ -228,6 +229,9 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const Object *object() const { const Object *object() const {
return GetPointer<const Object *>(VT_OBJECT); return GetPointer<const Object *>(VT_OBJECT);
} }
const Type *union_type() const {
return GetPointer<const Type *>(VT_UNION_TYPE);
}
bool Verify(flatbuffers::Verifier &verifier) const { bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) && return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) && VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
...@@ -235,6 +239,8 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { ...@@ -235,6 +239,8 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyField<int64_t>(verifier, VT_VALUE) && VerifyField<int64_t>(verifier, VT_VALUE) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_OBJECT) && VerifyField<flatbuffers::uoffset_t>(verifier, VT_OBJECT) &&
verifier.VerifyTable(object()) && verifier.VerifyTable(object()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_UNION_TYPE) &&
verifier.VerifyTable(union_type()) &&
verifier.EndTable(); verifier.EndTable();
} }
}; };
...@@ -251,13 +257,16 @@ struct EnumValBuilder { ...@@ -251,13 +257,16 @@ struct EnumValBuilder {
void add_object(flatbuffers::Offset<Object> object) { void add_object(flatbuffers::Offset<Object> object) {
fbb_.AddOffset(EnumVal::VT_OBJECT, object); fbb_.AddOffset(EnumVal::VT_OBJECT, object);
} }
void add_union_type(flatbuffers::Offset<Type> union_type) {
fbb_.AddOffset(EnumVal::VT_UNION_TYPE, union_type);
}
EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb) EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) { : fbb_(_fbb) {
start_ = fbb_.StartTable(); start_ = fbb_.StartTable();
} }
EnumValBuilder &operator=(const EnumValBuilder &); EnumValBuilder &operator=(const EnumValBuilder &);
flatbuffers::Offset<EnumVal> Finish() { flatbuffers::Offset<EnumVal> Finish() {
const auto end = fbb_.EndTable(start_, 3); const auto end = fbb_.EndTable(start_, 4);
auto o = flatbuffers::Offset<EnumVal>(end); auto o = flatbuffers::Offset<EnumVal>(end);
fbb_.Required(o, EnumVal::VT_NAME); fbb_.Required(o, EnumVal::VT_NAME);
return o; return o;
...@@ -268,9 +277,11 @@ inline flatbuffers::Offset<EnumVal> CreateEnumVal( ...@@ -268,9 +277,11 @@ inline flatbuffers::Offset<EnumVal> CreateEnumVal(
flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::String> name = 0, flatbuffers::Offset<flatbuffers::String> name = 0,
int64_t value = 0, int64_t value = 0,
flatbuffers::Offset<Object> object = 0) { flatbuffers::Offset<Object> object = 0,
flatbuffers::Offset<Type> union_type = 0) {
EnumValBuilder builder_(_fbb); EnumValBuilder builder_(_fbb);
builder_.add_value(value); builder_.add_value(value);
builder_.add_union_type(union_type);
builder_.add_object(object); builder_.add_object(object);
builder_.add_name(name); builder_.add_name(name);
return builder_.Finish(); return builder_.Finish();
...@@ -280,12 +291,14 @@ inline flatbuffers::Offset<EnumVal> CreateEnumValDirect( ...@@ -280,12 +291,14 @@ inline flatbuffers::Offset<EnumVal> CreateEnumValDirect(
flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::FlatBufferBuilder &_fbb,
const char *name = nullptr, const char *name = nullptr,
int64_t value = 0, int64_t value = 0,
flatbuffers::Offset<Object> object = 0) { flatbuffers::Offset<Object> object = 0,
flatbuffers::Offset<Type> union_type = 0) {
return reflection::CreateEnumVal( return reflection::CreateEnumVal(
_fbb, _fbb,
name ? _fbb.CreateString(name) : 0, name ? _fbb.CreateString(name) : 0,
value, value,
object); object,
union_type);
} }
struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
......
...@@ -42,7 +42,8 @@ table KeyValue { ...@@ -42,7 +42,8 @@ table KeyValue {
table EnumVal { table EnumVal {
name:string (required); name:string (required);
value:long (key); value:long (key);
object:Object; // Only if part of a union. object:Object; // Will be deprecated in favor of union_type in the future.
union_type:Type;
} }
table Enum { table Enum {
......
...@@ -71,35 +71,35 @@ template<> struct EquipmentTraits<Weapon> { ...@@ -71,35 +71,35 @@ template<> struct EquipmentTraits<Weapon> {
struct EquipmentUnion { struct EquipmentUnion {
Equipment type; Equipment type;
flatbuffers::NativeTable *table; void *value;
EquipmentUnion() : type(Equipment_NONE), table(nullptr) {} EquipmentUnion() : type(Equipment_NONE), value(nullptr) {}
EquipmentUnion(EquipmentUnion&& u) FLATBUFFERS_NOEXCEPT : EquipmentUnion(EquipmentUnion&& u) FLATBUFFERS_NOEXCEPT :
type(Equipment_NONE), table(nullptr) type(Equipment_NONE), value(nullptr)
{ std::swap(type, u.type); std::swap(table, u.table); } { std::swap(type, u.type); std::swap(value, u.value); }
EquipmentUnion(const EquipmentUnion &); EquipmentUnion(const EquipmentUnion &);
EquipmentUnion &operator=(const EquipmentUnion &); EquipmentUnion &operator=(const EquipmentUnion &);
EquipmentUnion &operator=(EquipmentUnion &&u) FLATBUFFERS_NOEXCEPT EquipmentUnion &operator=(EquipmentUnion &&u) FLATBUFFERS_NOEXCEPT
{ std::swap(type, u.type); std::swap(table, u.table); return *this; } { std::swap(type, u.type); std::swap(value, u.value); return *this; }
~EquipmentUnion() { Reset(); } ~EquipmentUnion() { Reset(); }
void Reset(); void Reset();
template <typename T> template <typename T>
void Set(T&& value) { void Set(T&& val) {
Reset(); Reset();
type = EquipmentTraits<typename T::TableType>::enum_value; type = EquipmentTraits<typename T::TableType>::enum_value;
if (type != Equipment_NONE) { if (type != Equipment_NONE) {
table = new T(std::forward<T>(value)); value = new T(std::forward<T>(val));
} }
} }
static flatbuffers::NativeTable *UnPack(const void *obj, Equipment type, const flatbuffers::resolver_function_t *resolver); static void *UnPack(const void *obj, Equipment type, const flatbuffers::resolver_function_t *resolver);
flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher = nullptr) const; flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher = nullptr) const;
WeaponT *AsWeapon() { WeaponT *AsWeapon() {
return type == Equipment_Weapon ? return type == Equipment_Weapon ?
reinterpret_cast<WeaponT *>(table) : nullptr; reinterpret_cast<WeaponT *>(value) : nullptr;
} }
}; };
...@@ -228,7 +228,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { ...@@ -228,7 +228,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
} }
template<typename T> const T *equipped_as() const; template<typename T> const T *equipped_as() const;
const Weapon *equipped_as_Weapon() const { const Weapon *equipped_as_Weapon() const {
return (equipped_type() == Equipment_Weapon)? static_cast<const Weapon *>(equipped()) : nullptr; return equipped_type() == Equipment_Weapon ? static_cast<const Weapon *>(equipped()) : nullptr;
} }
void *mutable_equipped() { void *mutable_equipped() {
return GetPointer<void *>(VT_EQUIPPED); return GetPointer<void *>(VT_EQUIPPED);
...@@ -451,7 +451,7 @@ inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function ...@@ -451,7 +451,7 @@ inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function
{ auto _e = color(); _o->color = _e; }; { auto _e = color(); _o->color = _e; };
{ auto _e = weapons(); if (_e) { _o->weapons.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->weapons[_i] = std::unique_ptr<WeaponT>(_e->Get(_i)->UnPack(_resolver)); } } }; { auto _e = weapons(); if (_e) { _o->weapons.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->weapons[_i] = std::unique_ptr<WeaponT>(_e->Get(_i)->UnPack(_resolver)); } } };
{ auto _e = equipped_type(); _o->equipped.type = _e; }; { auto _e = equipped_type(); _o->equipped.type = _e; };
{ auto _e = equipped(); if (_e) _o->equipped.table = EquipmentUnion::UnPack(_e, equipped_type(),_resolver); }; { auto _e = equipped(); if (_e) _o->equipped.value = EquipmentUnion::UnPack(_e, equipped_type(), _resolver); };
} }
inline flatbuffers::Offset<Monster> Monster::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT* _o, const flatbuffers::rehasher_function_t *_rehasher) { inline flatbuffers::Offset<Monster> Monster::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
...@@ -535,7 +535,7 @@ inline bool VerifyEquipmentVector(flatbuffers::Verifier &verifier, const flatbuf ...@@ -535,7 +535,7 @@ inline bool VerifyEquipmentVector(flatbuffers::Verifier &verifier, const flatbuf
return true; return true;
} }
inline flatbuffers::NativeTable *EquipmentUnion::UnPack(const void *obj, Equipment type, const flatbuffers::resolver_function_t *resolver) { inline void *EquipmentUnion::UnPack(const void *obj, Equipment type, const flatbuffers::resolver_function_t *resolver) {
switch (type) { switch (type) {
case Equipment_Weapon: { case Equipment_Weapon: {
auto ptr = reinterpret_cast<const Weapon *>(obj); auto ptr = reinterpret_cast<const Weapon *>(obj);
...@@ -548,7 +548,7 @@ inline flatbuffers::NativeTable *EquipmentUnion::UnPack(const void *obj, Equipme ...@@ -548,7 +548,7 @@ inline flatbuffers::NativeTable *EquipmentUnion::UnPack(const void *obj, Equipme
inline flatbuffers::Offset<void> EquipmentUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher) const { inline flatbuffers::Offset<void> EquipmentUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher) const {
switch (type) { switch (type) {
case Equipment_Weapon: { case Equipment_Weapon: {
auto ptr = reinterpret_cast<const WeaponT *>(table); auto ptr = reinterpret_cast<const WeaponT *>(value);
return CreateWeapon(_fbb, ptr, _rehasher).Union(); return CreateWeapon(_fbb, ptr, _rehasher).Union();
} }
default: return 0; default: return 0;
...@@ -558,13 +558,13 @@ inline flatbuffers::Offset<void> EquipmentUnion::Pack(flatbuffers::FlatBufferBui ...@@ -558,13 +558,13 @@ inline flatbuffers::Offset<void> EquipmentUnion::Pack(flatbuffers::FlatBufferBui
inline void EquipmentUnion::Reset() { inline void EquipmentUnion::Reset() {
switch (type) { switch (type) {
case Equipment_Weapon: { case Equipment_Weapon: {
auto ptr = reinterpret_cast<WeaponT *>(table); auto ptr = reinterpret_cast<WeaponT *>(value);
delete ptr; delete ptr;
break; break;
} }
default: break; default: break;
} }
table = nullptr; value = nullptr;
type = Equipment_NONE; type = Equipment_NONE;
} }
......
...@@ -109,7 +109,7 @@ class CppGenerator : public BaseGenerator { ...@@ -109,7 +109,7 @@ class CppGenerator : public BaseGenerator {
SetNameSpace(struct_def.defined_namespace); SetNameSpace(struct_def.defined_namespace);
code_ += "struct " + struct_def.name + ";"; code_ += "struct " + struct_def.name + ";";
if (parser_.opts.generate_object_based_api && !struct_def.fixed) { if (parser_.opts.generate_object_based_api && !struct_def.fixed) {
code_ += "struct " + NativeName(struct_def.name) + ";"; code_ += "struct " + NativeName(struct_def.name, &struct_def) + ";";
} }
code_ += ""; code_ += "";
} }
...@@ -239,7 +239,7 @@ class CppGenerator : public BaseGenerator { ...@@ -239,7 +239,7 @@ class CppGenerator : public BaseGenerator {
if (parser_.opts.generate_object_based_api) { if (parser_.opts.generate_object_based_api) {
// A convenient root unpack function. // A convenient root unpack function.
auto native_name = auto native_name =
NativeName(WrapInNameSpace(struct_def)); NativeName(WrapInNameSpace(struct_def), &struct_def);
code_.SetValue("UNPACK_RETURN", code_.SetValue("UNPACK_RETURN",
GenTypeNativePtr(native_name, nullptr, false)); GenTypeNativePtr(native_name, nullptr, false));
code_.SetValue("UNPACK_TYPE", code_.SetValue("UNPACK_TYPE",
...@@ -355,7 +355,9 @@ class CppGenerator : public BaseGenerator { ...@@ -355,7 +355,9 @@ class CppGenerator : public BaseGenerator {
} }
// TODO(wvo): make this configurable. // TODO(wvo): make this configurable.
static std::string NativeName(const std::string &name) { return name + "T"; } static std::string NativeName(const std::string &name, const StructDef *sd) {
return sd && !sd->fixed ? name + "T" : name;
}
const std::string &PtrType(const FieldDef *field) { const std::string &PtrType(const FieldDef *field) {
auto attr = field ? field->attributes.Lookup("cpp_ptr_type") : nullptr; auto attr = field ? field->attributes.Lookup("cpp_ptr_type") : nullptr;
...@@ -411,7 +413,8 @@ class CppGenerator : public BaseGenerator { ...@@ -411,7 +413,8 @@ class CppGenerator : public BaseGenerator {
return GenTypeNativePtr(type_name, &field, false); return GenTypeNativePtr(type_name, &field, false);
} }
} else { } else {
return GenTypeNativePtr(NativeName(type_name), &field, false); return GenTypeNativePtr(NativeName(type_name, type.struct_def),
&field, false);
} }
} }
case BASE_TYPE_UNION: { case BASE_TYPE_UNION: {
...@@ -458,6 +461,26 @@ class CppGenerator : public BaseGenerator { ...@@ -458,6 +461,26 @@ class CppGenerator : public BaseGenerator {
} }
} }
std::string StripUnionType(const std::string &name) {
return name.substr(0, name.size() - strlen(UnionTypeFieldSuffix()));
}
std::string GetUnionElement(const EnumVal &ev, bool wrap, bool actual_type,
bool native_type = false) {
if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
auto name = actual_type ? ev.union_type.struct_def->name : ev.name;
return wrap
? WrapInNameSpace(ev.union_type.struct_def->defined_namespace, name)
: name;
} else if (ev.union_type.base_type == BASE_TYPE_STRING) {
return actual_type
? (native_type ? "std::string" : "flatbuffers::String")
: ev.name;
} else {
assert(false);
}
}
static std::string UnionVerifySignature(const EnumDef &enum_def) { static std::string UnionVerifySignature(const EnumDef &enum_def) {
return "bool Verify" + enum_def.name + return "bool Verify" + enum_def.name +
"(flatbuffers::Verifier &verifier, const void *obj, " + "(flatbuffers::Verifier &verifier, const void *obj, " +
...@@ -474,7 +497,7 @@ class CppGenerator : public BaseGenerator { ...@@ -474,7 +497,7 @@ class CppGenerator : public BaseGenerator {
static std::string UnionUnPackSignature(const EnumDef &enum_def, static std::string UnionUnPackSignature(const EnumDef &enum_def,
bool inclass) { bool inclass) {
return (inclass ? "static " : "") + return (inclass ? "static " : "") +
std::string("flatbuffers::NativeTable *") + std::string("void *") +
(inclass ? "" : enum_def.name + "Union::") + (inclass ? "" : enum_def.name + "Union::") +
"UnPack(const void *obj, " + enum_def.name + "UnPack(const void *obj, " + enum_def.name +
" type, const flatbuffers::resolver_function_t *resolver)"; " type, const flatbuffers::resolver_function_t *resolver)";
...@@ -493,7 +516,7 @@ class CppGenerator : public BaseGenerator { ...@@ -493,7 +516,7 @@ class CppGenerator : public BaseGenerator {
return "flatbuffers::Offset<" + struct_def.name + "> Create" + return "flatbuffers::Offset<" + struct_def.name + "> Create" +
struct_def.name + struct_def.name +
"(flatbuffers::FlatBufferBuilder &_fbb, const " + "(flatbuffers::FlatBufferBuilder &_fbb, const " +
NativeName(struct_def.name) + NativeName(struct_def.name, &struct_def) +
" *_o, const flatbuffers::rehasher_function_t *_rehasher" + " *_o, const flatbuffers::rehasher_function_t *_rehasher" +
(predecl ? " = nullptr" : "") + ")"; (predecl ? " = nullptr" : "") + ")";
} }
...@@ -504,14 +527,14 @@ class CppGenerator : public BaseGenerator { ...@@ -504,14 +527,14 @@ class CppGenerator : public BaseGenerator {
"flatbuffers::Offset<" + struct_def.name + "> " + "flatbuffers::Offset<" + struct_def.name + "> " +
(inclass ? "" : struct_def.name + "::") + (inclass ? "" : struct_def.name + "::") +
"Pack(flatbuffers::FlatBufferBuilder &_fbb, " + "Pack(flatbuffers::FlatBufferBuilder &_fbb, " +
"const " + NativeName(struct_def.name) + "* _o, " + "const " + NativeName(struct_def.name, &struct_def) + "* _o, " +
"const flatbuffers::rehasher_function_t *_rehasher" + "const flatbuffers::rehasher_function_t *_rehasher" +
(inclass ? " = nullptr" : "") + ")"; (inclass ? " = nullptr" : "") + ")";
} }
static std::string TableUnPackSignature(const StructDef &struct_def, static std::string TableUnPackSignature(const StructDef &struct_def,
bool inclass) { bool inclass) {
return NativeName(struct_def.name) + " *" + return NativeName(struct_def.name, &struct_def) + " *" +
(inclass ? "" : struct_def.name + "::") + (inclass ? "" : struct_def.name + "::") +
"UnPack(const flatbuffers::resolver_function_t *_resolver" + "UnPack(const flatbuffers::resolver_function_t *_resolver" +
(inclass ? " = nullptr" : "") + ") const"; (inclass ? " = nullptr" : "") + ") const";
...@@ -520,8 +543,8 @@ class CppGenerator : public BaseGenerator { ...@@ -520,8 +543,8 @@ class CppGenerator : public BaseGenerator {
static std::string TableUnPackToSignature(const StructDef &struct_def, static std::string TableUnPackToSignature(const StructDef &struct_def,
bool inclass) { bool inclass) {
return "void " + (inclass ? "" : struct_def.name + "::") + return "void " + (inclass ? "" : struct_def.name + "::") +
"UnPackTo(" + NativeName(struct_def.name) + " *" + "_o, " + "UnPackTo(" + NativeName(struct_def.name, &struct_def) + " *" +
"const flatbuffers::resolver_function_t *_resolver" + "_o, const flatbuffers::resolver_function_t *_resolver" +
(inclass ? " = nullptr" : "") + ") const"; (inclass ? " = nullptr" : "") + ") const";
} }
...@@ -629,7 +652,7 @@ class CppGenerator : public BaseGenerator { ...@@ -629,7 +652,7 @@ class CppGenerator : public BaseGenerator {
} }
// Generate type traits for unions to map from a type to union enum value. // Generate type traits for unions to map from a type to union enum value.
if (enum_def.is_union) { if (enum_def.is_union && !enum_def.uses_type_aliases) {
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end(); for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
++it) { ++it) {
const auto &ev = **it; const auto &ev = **it;
...@@ -638,7 +661,7 @@ class CppGenerator : public BaseGenerator { ...@@ -638,7 +661,7 @@ class CppGenerator : public BaseGenerator {
code_ += "template<typename T> struct {{ENUM_NAME}}Traits {"; code_ += "template<typename T> struct {{ENUM_NAME}}Traits {";
} }
else { else {
auto name = WrapInNameSpace(*ev.struct_def); auto name = GetUnionElement(ev, true, true);
code_ += "template<> struct {{ENUM_NAME}}Traits<" + name + "> {"; code_ += "template<> struct {{ENUM_NAME}}Traits<" + name + "> {";
} }
...@@ -657,29 +680,31 @@ class CppGenerator : public BaseGenerator { ...@@ -657,29 +680,31 @@ class CppGenerator : public BaseGenerator {
code_ += "struct {{NAME}}Union {"; code_ += "struct {{NAME}}Union {";
code_ += " {{NAME}} type;"; code_ += " {{NAME}} type;";
code_ += " flatbuffers::NativeTable *table;"; code_ += " void *value;";
code_ += ""; code_ += "";
code_ += " {{NAME}}Union() : type({{NONE}}), table(nullptr) {}"; code_ += " {{NAME}}Union() : type({{NONE}}), value(nullptr) {}";
code_ += " {{NAME}}Union({{NAME}}Union&& u) FLATBUFFERS_NOEXCEPT :"; code_ += " {{NAME}}Union({{NAME}}Union&& u) FLATBUFFERS_NOEXCEPT :";
code_ += " type({{NONE}}), table(nullptr)"; code_ += " type({{NONE}}), value(nullptr)";
code_ += " { std::swap(type, u.type); std::swap(table, u.table); }"; code_ += " { std::swap(type, u.type); std::swap(value, u.value); }";
code_ += " {{NAME}}Union(const {{NAME}}Union &);"; code_ += " {{NAME}}Union(const {{NAME}}Union &);";
code_ += " {{NAME}}Union &operator=(const {{NAME}}Union &);"; code_ += " {{NAME}}Union &operator=(const {{NAME}}Union &);";
code_ += " {{NAME}}Union &operator=({{NAME}}Union &&u) FLATBUFFERS_NOEXCEPT"; code_ += " {{NAME}}Union &operator=({{NAME}}Union &&u) FLATBUFFERS_NOEXCEPT";
code_ += " { std::swap(type, u.type); std::swap(table, u.table); return *this; }"; code_ += " { std::swap(type, u.type); std::swap(value, u.value); return *this; }";
code_ += " ~{{NAME}}Union() { Reset(); }"; code_ += " ~{{NAME}}Union() { Reset(); }";
code_ += ""; code_ += "";
code_ += " void Reset();"; code_ += " void Reset();";
code_ += ""; code_ += "";
if (!enum_def.uses_type_aliases) {
code_ += " template <typename T>"; code_ += " template <typename T>";
code_ += " void Set(T&& value) {"; code_ += " void Set(T&& val) {";
code_ += " Reset();"; code_ += " Reset();";
code_ += " type = {{NAME}}Traits<typename T::TableType>::enum_value;"; code_ += " type = {{NAME}}Traits<typename T::TableType>::enum_value;";
code_ += " if (type != {{NONE}}) {"; code_ += " if (type != {{NONE}}) {";
code_ += " table = new T(std::forward<T>(value));"; code_ += " value = new T(std::forward<T>(val));";
code_ += " }"; code_ += " }";
code_ += " }"; code_ += " }";
code_ += ""; code_ += "";
}
code_ += " " + UnionUnPackSignature(enum_def, true) + ";"; code_ += " " + UnionUnPackSignature(enum_def, true) + ";";
code_ += " " + UnionPackSignature(enum_def, true) + ";"; code_ += " " + UnionPackSignature(enum_def, true) + ";";
code_ += ""; code_ += "";
...@@ -691,14 +716,16 @@ class CppGenerator : public BaseGenerator { ...@@ -691,14 +716,16 @@ class CppGenerator : public BaseGenerator {
continue; continue;
} }
const auto native_type = NativeName(WrapInNameSpace(*ev.struct_def)); const auto native_type =
NativeName(GetUnionElement(ev, true, true, true),
ev.union_type.struct_def);
code_.SetValue("NATIVE_TYPE", native_type); code_.SetValue("NATIVE_TYPE", native_type);
code_.SetValue("NATIVE_NAME", ev.name); code_.SetValue("NATIVE_NAME", ev.name);
code_.SetValue("NATIVE_ID", GetEnumValUse(enum_def, ev)); code_.SetValue("NATIVE_ID", GetEnumValUse(enum_def, ev));
code_ += " {{NATIVE_TYPE}} *As{{NATIVE_NAME}}() {"; code_ += " {{NATIVE_TYPE}} *As{{NATIVE_NAME}}() {";
code_ += " return type == {{NATIVE_ID}} ?"; code_ += " return type == {{NATIVE_ID}} ?";
code_ += " reinterpret_cast<{{NATIVE_TYPE}} *>(table) : nullptr;"; code_ += " reinterpret_cast<{{NATIVE_TYPE}} *>(value) : nullptr;";
code_ += " }"; code_ += " }";
} }
code_ += "};"; code_ += "};";
...@@ -728,10 +755,23 @@ class CppGenerator : public BaseGenerator { ...@@ -728,10 +755,23 @@ class CppGenerator : public BaseGenerator {
code_.SetValue("LABEL", GetEnumValUse(enum_def, ev)); code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
if (ev.value) { if (ev.value) {
code_.SetValue("TYPE", WrapInNameSpace(*ev.struct_def)); code_.SetValue("TYPE", GetUnionElement(ev, true, true));
code_ += " case {{LABEL}}: {"; code_ += " case {{LABEL}}: {";
code_ += " auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);"; auto getptr =
" auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);";
if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
if (ev.union_type.struct_def->fixed) {
code_ += " return true;";
} else {
code_ += getptr;
code_ += " return verifier.VerifyTable(ptr);"; code_ += " return verifier.VerifyTable(ptr);";
}
} else if (ev.union_type.base_type == BASE_TYPE_STRING) {
code_ += getptr;
code_ += " return verifier.Verify(ptr);";
} else {
assert(false);
}
code_ += " }"; code_ += " }";
} else { } else {
code_ += " case {{LABEL}}: {"; code_ += " case {{LABEL}}: {";
...@@ -768,10 +808,21 @@ class CppGenerator : public BaseGenerator { ...@@ -768,10 +808,21 @@ class CppGenerator : public BaseGenerator {
} }
code_.SetValue("LABEL", GetEnumValUse(enum_def, ev)); code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
code_.SetValue("TYPE", WrapInNameSpace(*ev.struct_def)); code_.SetValue("TYPE", GetUnionElement(ev, true, true));
code_ += " case {{LABEL}}: {"; code_ += " case {{LABEL}}: {";
code_ += " auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);"; code_ += " auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);";
if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
if (ev.union_type.struct_def->fixed) {
code_ += " return new " +
WrapInNameSpace(*ev.union_type.struct_def) + "(*ptr);";
} else {
code_ += " return ptr->UnPack(resolver);"; code_ += " return ptr->UnPack(resolver);";
}
} else if (ev.union_type.base_type == BASE_TYPE_STRING) {
code_ += " return new std::string(ptr->c_str(), ptr->size());";
} else {
assert(false);
}
code_ += " }"; code_ += " }";
} }
code_ += " default: return nullptr;"; code_ += " default: return nullptr;";
...@@ -789,11 +840,23 @@ class CppGenerator : public BaseGenerator { ...@@ -789,11 +840,23 @@ class CppGenerator : public BaseGenerator {
} }
code_.SetValue("LABEL", GetEnumValUse(enum_def, ev)); code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
code_.SetValue("TYPE", NativeName(WrapInNameSpace(*ev.struct_def))); code_.SetValue("TYPE", NativeName(GetUnionElement(ev, true, true, true),
code_.SetValue("NAME", ev.struct_def->name); ev.union_type.struct_def));
code_.SetValue("NAME", GetUnionElement(ev, false, true));
code_ += " case {{LABEL}}: {"; code_ += " case {{LABEL}}: {";
code_ += " auto ptr = reinterpret_cast<const {{TYPE}} *>(table);"; code_ += " auto ptr = reinterpret_cast<const {{TYPE}} *>(value);";
code_ += " return Create{{NAME}}(_fbb, ptr, _rehasher).Union();"; if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
if (ev.union_type.struct_def->fixed) {
code_ += " return _fbb.CreateStruct(*ptr).Union();";
} else {
code_ +=
" return Create{{NAME}}(_fbb, ptr, _rehasher).Union();";
}
} else if (ev.union_type.base_type == BASE_TYPE_STRING) {
code_ += " return _fbb.CreateString(*ptr).Union();";
} else {
assert(false);
}
code_ += " }"; code_ += " }";
} }
code_ += " default: return 0;"; code_ += " default: return 0;";
...@@ -815,17 +878,18 @@ class CppGenerator : public BaseGenerator { ...@@ -815,17 +878,18 @@ class CppGenerator : public BaseGenerator {
} }
code_.SetValue("LABEL", GetEnumValUse(enum_def, ev)); code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
code_.SetValue("TYPE", NativeName(WrapInNameSpace(*ev.struct_def))); code_.SetValue("TYPE", NativeName(GetUnionElement(ev, true, true, true),
ev.union_type.struct_def));
code_ += " case {{LABEL}}: {"; code_ += " case {{LABEL}}: {";
code_ += " auto ptr = reinterpret_cast<{{TYPE}} *>(table);"; code_ += " auto ptr = reinterpret_cast<{{TYPE}} *>(value);";
code_ += " delete ptr;"; code_ += " delete ptr;";
code_ += " break;"; code_ += " break;";
code_ += " }"; code_ += " }";
} }
code_ += " default: break;"; code_ += " default: break;";
code_ += " }"; code_ += " }";
code_ += " table = nullptr;"; code_ += " value = nullptr;";
code_ += " type = {{NONE}};"; code_ += " type = {{NONE}};";
code_ += "}"; code_ += "}";
code_ += ""; code_ += "";
...@@ -914,7 +978,9 @@ class CppGenerator : public BaseGenerator { ...@@ -914,7 +978,9 @@ class CppGenerator : public BaseGenerator {
// Generate a member, including a default value for scalars and raw pointers. // Generate a member, including a default value for scalars and raw pointers.
void GenMember(const FieldDef &field) { void GenMember(const FieldDef &field) {
if (!field.deprecated && // Deprecated fields won't be accessible. if (!field.deprecated && // Deprecated fields won't be accessible.
field.value.type.base_type != BASE_TYPE_UTYPE) { field.value.type.base_type != BASE_TYPE_UTYPE &&
(field.value.type.base_type != BASE_TYPE_VECTOR ||
field.value.type.element != BASE_TYPE_UTYPE)) {
auto type = GenTypeNative(field.value.type, false, field); auto type = GenTypeNative(field.value.type, false, field);
auto cpp_type = field.attributes.Lookup("cpp_type"); auto cpp_type = field.attributes.Lookup("cpp_type");
auto full_type = (cpp_type ? cpp_type->constant + " *" : type + " "); auto full_type = (cpp_type ? cpp_type->constant + " *" : type + " ");
...@@ -964,7 +1030,7 @@ class CppGenerator : public BaseGenerator { ...@@ -964,7 +1030,7 @@ class CppGenerator : public BaseGenerator {
initializer_list = "\n : " + initializer_list; initializer_list = "\n : " + initializer_list;
} }
code_.SetValue("NATIVE_NAME", NativeName(struct_def.name)); code_.SetValue("NATIVE_NAME", NativeName(struct_def.name, &struct_def));
code_.SetValue("INIT_LIST", initializer_list); code_.SetValue("INIT_LIST", initializer_list);
code_ += " {{NATIVE_NAME}}(){{INIT_LIST}} {"; code_ += " {{NATIVE_NAME}}(){{INIT_LIST}} {";
...@@ -972,7 +1038,7 @@ class CppGenerator : public BaseGenerator { ...@@ -972,7 +1038,7 @@ class CppGenerator : public BaseGenerator {
} }
void GenNativeTable(const StructDef &struct_def) { void GenNativeTable(const StructDef &struct_def) {
const auto native_name = NativeName(struct_def.name); const auto native_name = NativeName(struct_def.name, &struct_def);
code_.SetValue("STRUCT_NAME", struct_def.name); code_.SetValue("STRUCT_NAME", struct_def.name);
code_.SetValue("NATIVE_NAME", native_name); code_.SetValue("NATIVE_NAME", native_name);
...@@ -1138,24 +1204,23 @@ class CppGenerator : public BaseGenerator { ...@@ -1138,24 +1204,23 @@ class CppGenerator : public BaseGenerator {
for (auto u_it = u->vals.vec.begin(); for (auto u_it = u->vals.vec.begin();
u_it != u->vals.vec.end(); ++u_it) { u_it != u->vals.vec.end(); ++u_it) {
if (!(*u_it)->struct_def) { auto &ev = **u_it;
if (ev.union_type.base_type == BASE_TYPE_NONE) {
continue; continue;
} }
auto arg_struct_def = (*u_it)->struct_def; auto full_struct_name = GetUnionElement(ev, true, true);
auto full_struct_name = WrapInNameSpace(*arg_struct_def);
// @TODO: Mby make this decisions more universal? How? // @TODO: Mby make this decisions more universal? How?
code_.SetValue("U_GET_TYPE", field.name + UnionTypeFieldSuffix()); code_.SetValue("U_GET_TYPE", field.name + UnionTypeFieldSuffix());
code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace( code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace(
u->defined_namespace, GetEnumValUse(*u, **u_it))); u->defined_namespace, GetEnumValUse(*u, ev)));
code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *"); code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
code_.SetValue("U_ELEMENT_NAME", full_struct_name);
code_.SetValue("U_FIELD_NAME", code_.SetValue("U_FIELD_NAME",
field.name + "_as_" + (*u_it)->name); field.name + "_as_" + ev.name);
// `const Type *union_name_asType() const` accessor. // `const Type *union_name_asType() const` accessor.
code_ += " {{U_FIELD_TYPE}}{{U_FIELD_NAME}}() const {"; code_ += " {{U_FIELD_TYPE}}{{U_FIELD_NAME}}() const {";
code_ += " return ({{U_GET_TYPE}}() == {{U_ELEMENT_TYPE}})? " code_ += " return {{U_GET_TYPE}}() == {{U_ELEMENT_TYPE}} ? "
"static_cast<{{U_FIELD_TYPE}}>({{FIELD_NAME}}()) " "static_cast<{{U_FIELD_TYPE}}>({{FIELD_NAME}}()) "
": nullptr;"; ": nullptr;";
code_ += " }"; code_ += " }";
...@@ -1279,23 +1344,25 @@ class CppGenerator : public BaseGenerator { ...@@ -1279,23 +1344,25 @@ class CppGenerator : public BaseGenerator {
} }
auto u = field.value.type.enum_def; auto u = field.value.type.enum_def;
if (u->uses_type_aliases) continue;
code_.SetValue("FIELD_NAME", field.name); code_.SetValue("FIELD_NAME", field.name);
for (auto u_it = u->vals.vec.begin(); for (auto u_it = u->vals.vec.begin();
u_it != u->vals.vec.end(); ++u_it) { u_it != u->vals.vec.end(); ++u_it) {
if (!(*u_it)->struct_def) { auto &ev = **u_it;
if (ev.union_type.base_type == BASE_TYPE_NONE) {
continue; continue;
} }
auto arg_struct_def = (*u_it)->struct_def; auto full_struct_name = GetUnionElement(ev, true, true);
auto full_struct_name = WrapInNameSpace(*arg_struct_def);
code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace( code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace(
u->defined_namespace, GetEnumValUse(*u, **u_it))); u->defined_namespace, GetEnumValUse(*u, ev)));
code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *"); code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
code_.SetValue("U_ELEMENT_NAME", full_struct_name); code_.SetValue("U_ELEMENT_NAME", full_struct_name);
code_.SetValue("U_FIELD_NAME", code_.SetValue("U_FIELD_NAME",
field.name + "_as_" + (*u_it)->name); field.name + "_as_" + ev.name);
// `template<> const T *union_name_as<T>() const` accessor. // `template<> const T *union_name_as<T>() const` accessor.
code_ += "template<> " code_ += "template<> "
...@@ -1475,6 +1542,14 @@ class CppGenerator : public BaseGenerator { ...@@ -1475,6 +1542,14 @@ class CppGenerator : public BaseGenerator {
} }
} }
std::string GenUnionUnpackVal(const FieldDef &afield,
const char *vec_elem_access,
const char *vec_type_access) {
return afield.value.type.enum_def->name + "Union::UnPack(" + "_e" +
vec_elem_access + ", " + afield.name + UnionTypeFieldSuffix() +
"()" + vec_type_access + ", _resolver)";
}
std::string GenUnpackVal(const Type &type, const std::string &val, std::string GenUnpackVal(const Type &type, const std::string &val,
bool invector, const FieldDef &afield) { bool invector, const FieldDef &afield) {
switch (type.base_type) { switch (type.base_type) {
...@@ -1494,10 +1569,18 @@ class CppGenerator : public BaseGenerator { ...@@ -1494,10 +1569,18 @@ class CppGenerator : public BaseGenerator {
return ptype + "(new " + name + "(*" + val + "))"; return ptype + "(new " + name + "(*" + val + "))";
} }
} else { } else {
const auto ptype = GenTypeNativePtr(NativeName(name), &afield, true); const auto ptype = GenTypeNativePtr(NativeName(name, type.struct_def),
&afield, true);
return ptype + "(" + val + "->UnPack(_resolver))"; return ptype + "(" + val + "->UnPack(_resolver))";
} }
} }
case BASE_TYPE_UNION: {
return GenUnionUnpackVal(afield,
invector ? "->Get(_i)" : "",
invector ? ("->GetEnum<" +
type.enum_def->name +
">(_i)").c_str() : "");
}
default: { default: {
return val; return val;
break; break;
...@@ -1523,10 +1606,19 @@ class CppGenerator : public BaseGenerator { ...@@ -1523,10 +1606,19 @@ class CppGenerator : public BaseGenerator {
// for (uoffset_t i = 0; i < _e->size(); ++i) { // for (uoffset_t i = 0; i < _e->size(); ++i) {
// _o->field.push_back(_e->Get(_i)); // _o->field.push_back(_e->Get(_i));
// } // }
code += "{ _o->" + field.name + ".resize(_e->size()); "; auto name = field.name;
if (field.value.type.element == BASE_TYPE_UTYPE) {
name = StripUnionType(field.name);
}
auto access = field.value.type.element == BASE_TYPE_UTYPE
? ".type"
: (field.value.type.element == BASE_TYPE_UNION
? ".value"
: "");
code += "{ _o->" + name + ".resize(_e->size()); ";
code += "for (flatbuffers::uoffset_t _i = 0;"; code += "for (flatbuffers::uoffset_t _i = 0;";
code += " _i < _e->size(); _i++) { "; code += " _i < _e->size(); _i++) { ";
code += "_o->" + field.name + "[_i] = "; code += "_o->" + name + "[_i]" + access + " = ";
code += GenUnpackVal(field.value.type.VectorType(), code += GenUnpackVal(field.value.type.VectorType(),
indexing, true, field); indexing, true, field);
code += "; } }"; code += "; } }";
...@@ -1540,12 +1632,11 @@ class CppGenerator : public BaseGenerator { ...@@ -1540,12 +1632,11 @@ class CppGenerator : public BaseGenerator {
break; break;
} }
case BASE_TYPE_UNION: { case BASE_TYPE_UNION: {
// Generate code that sets the union table, of the form: // Generate code that sets the union value, of the form:
// _o->field.table = Union::Unpack(_e, field_type(), resolver); // _o->field.value = Union::Unpack(_e, field_type(), resolver);
code += "_o->" + field.name + ".table = "; code += "_o->" + field.name + ".value = ";
code += field.value.type.enum_def->name + "Union::UnPack("; code += GenUnionUnpackVal(field, "", "");
code += "_e, " + field.name + UnionTypeFieldSuffix() + "(),"; code += ";";
code += "_resolver);";
break; break;
} }
default: { default: {
...@@ -1577,8 +1668,7 @@ class CppGenerator : public BaseGenerator { ...@@ -1577,8 +1668,7 @@ class CppGenerator : public BaseGenerator {
std::string GenCreateParam(const FieldDef &field) { std::string GenCreateParam(const FieldDef &field) {
std::string value = "_o->"; std::string value = "_o->";
if (field.value.type.base_type == BASE_TYPE_UTYPE) { if (field.value.type.base_type == BASE_TYPE_UTYPE) {
value += field.name.substr(0, field.name.size() - value += StripUnionType(field.name);
strlen(UnionTypeFieldSuffix()));
value += ".type"; value += ".type";
} else { } else {
value += field.name; value += field.name;
...@@ -1635,6 +1725,19 @@ class CppGenerator : public BaseGenerator { ...@@ -1635,6 +1725,19 @@ class CppGenerator : public BaseGenerator {
code += "_fbb.CreateVector(" + value + ")"; code += "_fbb.CreateVector(" + value + ")";
break; break;
} }
case BASE_TYPE_UNION: {
code += "_fbb.CreateVector<flatbuffers::Offset<void>>(" + value +
".size(), [&](size_t i) { return " + value +
"[i].Pack(_fbb, _rehasher); })";
break;
}
case BASE_TYPE_UTYPE: {
value = StripUnionType(value);
code += "_fbb.CreateVector<uint8_t>(" + value +
".size(), [&](size_t i) { return static_cast<uint8_t>(" + value +
"[i].type); })";
break;
}
default: { default: {
if (field.value.type.enum_def) { if (field.value.type.enum_def) {
// For enumerations, we need to get access to the array data for // For enumerations, we need to get access to the array data for
...@@ -1693,7 +1796,7 @@ class CppGenerator : public BaseGenerator { ...@@ -1693,7 +1796,7 @@ class CppGenerator : public BaseGenerator {
// Generate code for tables that needs to come after the regular definition. // Generate code for tables that needs to come after the regular definition.
void GenTablePost(const StructDef &struct_def) { void GenTablePost(const StructDef &struct_def) {
code_.SetValue("STRUCT_NAME", struct_def.name); code_.SetValue("STRUCT_NAME", struct_def.name);
code_.SetValue("NATIVE_NAME", NativeName(struct_def.name)); code_.SetValue("NATIVE_NAME", NativeName(struct_def.name, &struct_def));
if (parser_.opts.generate_object_based_api) { if (parser_.opts.generate_object_based_api) {
// Generate the X::UnPack() method. // Generate the X::UnPack() method.
......
...@@ -71,7 +71,8 @@ namespace js { ...@@ -71,7 +71,8 @@ namespace js {
class JsGenerator : public BaseGenerator { class JsGenerator : public BaseGenerator {
public: public:
typedef std::unordered_set<std::string> imported_fileset; typedef std::unordered_set<std::string> imported_fileset;
typedef std::unordered_multimap<std::string, ReexportDescription> reexport_map; typedef std::unordered_multimap<std::string, ReexportDescription>
reexport_map;
JsGenerator(const Parser &parser, const std::string &path, JsGenerator(const Parser &parser, const std::string &path,
const std::string &file_name) const std::string &file_name)
...@@ -104,19 +105,22 @@ class JsGenerator : public BaseGenerator { ...@@ -104,19 +105,22 @@ class JsGenerator : public BaseGenerator {
code += enum_code; code += enum_code;
code += struct_code; code += struct_code;
if (lang_.language == IDLOptions::kJs && !exports_code.empty() && !parser_.opts.skip_js_exports) { if (lang_.language == IDLOptions::kJs && !exports_code.empty() &&
!parser_.opts.skip_js_exports) {
code += "// Exports for Node.js and RequireJS\n"; code += "// Exports for Node.js and RequireJS\n";
code += exports_code; code += exports_code;
} }
return SaveFile(GeneratedFileName(path_, file_name_, lang_).c_str(), code, false); return SaveFile(GeneratedFileName(path_, file_name_, lang_).c_str(), code,
false);
} }
private: private:
JsLanguageParameters lang_; JsLanguageParameters lang_;
// Generate code for imports // Generate code for imports
void generateImportDependencies(std::string *code_ptr, const imported_fileset &imported_files) { void generateImportDependencies(std::string *code_ptr,
const imported_fileset &imported_files) {
std::string &code = *code_ptr; std::string &code = *code_ptr;
for (auto it = imported_files.begin(); it != imported_files.end(); ++it) { for (auto it = imported_files.begin(); it != imported_files.end(); ++it) {
const auto &file = *it; const auto &file = *it;
...@@ -129,11 +133,13 @@ class JsGenerator : public BaseGenerator { ...@@ -129,11 +133,13 @@ class JsGenerator : public BaseGenerator {
} }
} }
// Generate reexports, which might not have been explicitly imported using the "export import" trick // Generate reexports, which might not have been explicitly imported using the
// "export import" trick
void generateReexports(std::string *code_ptr, void generateReexports(std::string *code_ptr,
const reexport_map &reexports, const reexport_map &reexports,
imported_fileset imported_files) { imported_fileset imported_files) {
if (!parser_.opts.reexport_ts_modules || lang_.language != IDLOptions::kTs) { if (!parser_.opts.reexport_ts_modules ||
lang_.language != IDLOptions::kTs) {
return; return;
} }
...@@ -152,7 +158,9 @@ class JsGenerator : public BaseGenerator { ...@@ -152,7 +158,9 @@ class JsGenerator : public BaseGenerator {
code += "export namespace " + file.second.target_namespace + " { \n"; code += "export namespace " + file.second.target_namespace + " { \n";
code += "export import " + file.second.symbol + " = "; code += "export import " + file.second.symbol + " = ";
code += GenFileNamespacePrefix(file.first) + "." + file.second.source_namespace + "." + file.second.symbol + "; }\n"; code += GenFileNamespacePrefix(file.first) + "." +
file.second.source_namespace + "." + file.second.symbol +
"; }\n";
} }
} }
} }
...@@ -175,11 +183,13 @@ class JsGenerator : public BaseGenerator { ...@@ -175,11 +183,13 @@ class JsGenerator : public BaseGenerator {
for (auto it = parser_.structs_.vec.begin(); for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) { it != parser_.structs_.vec.end(); ++it) {
auto &struct_def = **it; auto &struct_def = **it;
GenStruct(parser_, struct_def, decl_code_ptr, exports_code_ptr, imported_files); GenStruct(parser_, struct_def, decl_code_ptr, exports_code_ptr,
imported_files);
} }
} }
void GenNamespaces(std::string *code_ptr, std::string *exports_ptr) { void GenNamespaces(std::string *code_ptr, std::string *exports_ptr) {
if (lang_.language == IDLOptions::kTs && parser_.opts.skip_flatbuffers_import) { if (lang_.language == IDLOptions::kTs &&
parser_.opts.skip_flatbuffers_import) {
return; return;
} }
...@@ -282,13 +292,14 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr, ...@@ -282,13 +292,14 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr,
std::string &exports = *exports_ptr; std::string &exports = *exports_ptr;
GenDocComment(enum_def.doc_comment, code_ptr, "@enum"); GenDocComment(enum_def.doc_comment, code_ptr, "@enum");
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
code += "export namespace " + GetNameSpace(enum_def) + "{\n" + "export enum " + enum_def.name + "{\n"; code += "export namespace " + GetNameSpace(enum_def) + "{\n" +
"export enum " + enum_def.name + "{\n";
} else { } else {
if (enum_def.defined_namespace->components.empty()) { if (enum_def.defined_namespace->components.empty()) {
code += "var "; code += "var ";
if(parser_.opts.use_goog_js_export_format) { if(parser_.opts.use_goog_js_export_format) {
exports += "goog.exportSymbol('" + enum_def.name + "', " + enum_def.name + exports += "goog.exportSymbol('" + enum_def.name + "', " +
");\n"; enum_def.name + ");\n";
} else { } else {
exports += "this." + enum_def.name + " = " + enum_def.name + ";\n"; exports += "this." + enum_def.name + " = " + enum_def.name + ";\n";
} }
...@@ -304,12 +315,19 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr, ...@@ -304,12 +315,19 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr,
} }
GenDocComment(ev.doc_comment, code_ptr, "", " "); GenDocComment(ev.doc_comment, code_ptr, "", " ");
} }
code += " " + ev.name + ((lang_.language == IDLOptions::kTs) ? ("= ") : (": ")) + NumToString(ev.value); code += " " + ev.name;
code += lang_.language == IDLOptions::kTs ? "= " : ": ";
code += NumToString(ev.value);
code += (it + 1) != enum_def.vals.vec.end() ? ",\n" : "\n"; code += (it + 1) != enum_def.vals.vec.end() ? ",\n" : "\n";
if (ev.struct_def) { if (ev.union_type.struct_def) {
ReexportDescription desc = { ev.name, GetNameSpace(*ev.struct_def), GetNameSpace(enum_def) }; ReexportDescription desc = {
reexports.insert(std::make_pair(ev.struct_def->file, std::move(desc))); ev.name,
GetNameSpace(*ev.union_type.struct_def),
GetNameSpace(enum_def)
};
reexports.insert(std::make_pair(ev.union_type.struct_def->file,
std::move(desc)));
} }
} }
...@@ -366,7 +384,8 @@ std::string GenDefaultValue(const Value &value, const std::string &context) { ...@@ -366,7 +384,8 @@ std::string GenDefaultValue(const Value &value, const std::string &context) {
if (auto val = value.type.enum_def->ReverseLookup( if (auto val = value.type.enum_def->ReverseLookup(
atoi(value.constant.c_str()), false)) { atoi(value.constant.c_str()), false)) {
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
return GenPrefixedTypeName(WrapInNameSpace(*value.type.enum_def), value.type.enum_def->file) + "." + val->name; return GenPrefixedTypeName(WrapInNameSpace(*value.type.enum_def),
value.type.enum_def->file) + "." + val->name;
} else { } else {
return WrapInNameSpace(*value.type.enum_def) + "." + val->name; return WrapInNameSpace(*value.type.enum_def) + "." + val->name;
} }
...@@ -448,17 +467,21 @@ static std::string MaybeScale(T value) { ...@@ -448,17 +467,21 @@ static std::string MaybeScale(T value) {
} }
static std::string GenFileNamespacePrefix(const std::string &file) { static std::string GenFileNamespacePrefix(const std::string &file) {
return "NS" + std::to_string(static_cast<unsigned long long>(std::hash<std::string>()(file))); return "NS" + std::to_string(
static_cast<unsigned long long>(std::hash<std::string>()(file)));
} }
static std::string GenPrefixedImport(const std::string &full_file_name, static std::string GenPrefixedImport(const std::string &full_file_name,
const std::string &base_file_name) { const std::string &base_file_name) {
return "import * as "+ GenFileNamespacePrefix(full_file_name) + " from \"./" + base_file_name + "\";\n"; return "import * as "+ GenFileNamespacePrefix(full_file_name) +
" from \"./" + base_file_name + "\";\n";
} }
// Adds a source-dependent prefix, for of import * statements. // Adds a source-dependent prefix, for of import * statements.
std::string GenPrefixedTypeName(const std::string &typeName, const std::string &file) { std::string GenPrefixedTypeName(const std::string &typeName,
const auto basename = flatbuffers::StripPath(flatbuffers::StripExtension(file)); const std::string &file) {
const auto basename =
flatbuffers::StripPath(flatbuffers::StripExtension(file));
if (basename == file_name_) { if (basename == file_name_) {
return typeName; return typeName;
} }
...@@ -483,7 +506,8 @@ void GenStructArgs(const StructDef &struct_def, ...@@ -483,7 +506,8 @@ void GenStructArgs(const StructDef &struct_def,
*annotations += "} " + nameprefix + field.name + "\n"; *annotations += "} " + nameprefix + field.name + "\n";
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
*arguments += ", " + nameprefix + field.name + ": " + GenTypeName(field.value.type, true); *arguments += ", " + nameprefix + field.name + ": " +
GenTypeName(field.value.type, true);
} else { } else {
*arguments += ", " + nameprefix + field.name; *arguments += ", " + nameprefix + field.name;
} }
...@@ -521,7 +545,8 @@ static void GenStructBody(const StructDef &struct_def, ...@@ -521,7 +545,8 @@ static void GenStructBody(const StructDef &struct_def,
} }
// Generate an accessor struct with constructor for a flatbuffers struct. // Generate an accessor struct with constructor for a flatbuffers struct.
void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_ptr, std::string *exports_ptr, void GenStruct(const Parser &parser, StructDef &struct_def,
std::string *code_ptr, std::string *exports_ptr,
imported_fileset &imported_files) { imported_fileset &imported_files) {
if (struct_def.generated) return; if (struct_def.generated) return;
std::string &code = *code_ptr; std::string &code = *code_ptr;
...@@ -583,7 +608,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt ...@@ -583,7 +608,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
code += " */\n"; code += " */\n";
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
code += "__init(i:number, bb:flatbuffers.ByteBuffer):" + object_name + " {\n"; code += "__init(i:number, bb:flatbuffers.ByteBuffer):" + object_name +
" {\n";
} else { } else {
code += object_name + ".prototype.__init = function(i, bb) {\n"; code += object_name + ".prototype.__init = function(i, bb) {\n";
} }
...@@ -602,7 +628,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt ...@@ -602,7 +628,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
"@returns {" + object_name + "}"); "@returns {" + object_name + "}");
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
code += "static getRootAs" + struct_def.name; code += "static getRootAs" + struct_def.name;
code += "(bb:flatbuffers.ByteBuffer, obj?:" + object_name + "):" + object_name + " {\n"; code += "(bb:flatbuffers.ByteBuffer, obj?:" + object_name + "):" +
object_name + " {\n";
} else { } else {
code += object_name + ".getRootAs" + struct_def.name; code += object_name + ".getRootAs" + struct_def.name;
code += " = function(bb, obj) {\n"; code += " = function(bb, obj) {\n";
...@@ -618,7 +645,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt ...@@ -618,7 +645,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
"@param {flatbuffers.ByteBuffer} bb\n" "@param {flatbuffers.ByteBuffer} bb\n"
"@returns {boolean}"); "@returns {boolean}");
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
code += "static bufferHasIdentifier(bb:flatbuffers.ByteBuffer):boolean {\n"; code +=
"static bufferHasIdentifier(bb:flatbuffers.ByteBuffer):boolean {\n";
} else { } else {
code += object_name + ".bufferHasIdentifier = function(bb) {\n"; code += object_name + ".bufferHasIdentifier = function(bb) {\n";
} }
...@@ -647,13 +675,16 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt ...@@ -647,13 +675,16 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
std::string prefix = MakeCamel(field.name, false) + "("; std::string prefix = MakeCamel(field.name, false) + "(";
if (field.value.type.base_type == BASE_TYPE_STRING) { if (field.value.type.base_type == BASE_TYPE_STRING) {
code += prefix + "):string\n"; code += prefix + "):string\n";
code += prefix + "optionalEncoding:flatbuffers.Encoding"+"):" + GenTypeName(field.value.type, false)+"\n"; code += prefix + "optionalEncoding:flatbuffers.Encoding"+"):" +
GenTypeName(field.value.type, false)+"\n";
code += prefix + "optionalEncoding?:any"; code += prefix + "optionalEncoding?:any";
} else { } else {
code += prefix; code += prefix;
} }
if (field.value.type.enum_def) { if (field.value.type.enum_def) {
code += "):" + GenPrefixedTypeName(GenTypeName(field.value.type, false), field.value.type.enum_def->file) + " {\n"; code += "):" +
GenPrefixedTypeName(GenTypeName(field.value.type, false),
field.value.type.enum_def->file) + " {\n";
} else { } else {
code += "):" + GenTypeName(field.value.type, false) + " {\n"; code += "):" + GenTypeName(field.value.type, false) + " {\n";
} }
...@@ -733,12 +764,14 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt ...@@ -733,12 +764,14 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
std::string prefix = MakeCamel(field.name, false); std::string prefix = MakeCamel(field.name, false);
prefix += "(index: number"; prefix += "(index: number";
if (vectortype.base_type == BASE_TYPE_STRUCT) { if (vectortype.base_type == BASE_TYPE_STRUCT) {
vectortypename = GenPrefixedTypeName(vectortypename, vectortype.struct_def->file); vectortypename = GenPrefixedTypeName(vectortypename,
vectortype.struct_def->file);
code += prefix + ", obj?:" + vectortypename; code += prefix + ", obj?:" + vectortypename;
imported_files.insert(vectortype.struct_def->file); imported_files.insert(vectortype.struct_def->file);
} else if (vectortype.base_type == BASE_TYPE_STRING) { } else if (vectortype.base_type == BASE_TYPE_STRING) {
code += prefix + "):string\n"; code += prefix + "):string\n";
code += prefix + ",optionalEncoding:flatbuffers.Encoding" + "):" + vectortypename + "\n"; code += prefix + ",optionalEncoding:flatbuffers.Encoding" + "):" +
vectortypename + "\n";
code += prefix + ",optionalEncoding?:any"; code += prefix + ",optionalEncoding?:any";
} else { } else {
code += prefix; code += prefix;
...@@ -819,31 +852,37 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt ...@@ -819,31 +852,37 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
// Adds the mutable scalar value to the output // Adds the mutable scalar value to the output
if (IsScalar(field.value.type.base_type) && parser.opts.mutable_buffer) { if (IsScalar(field.value.type.base_type) && parser.opts.mutable_buffer) {
std::string annotations = "@param {" + GenTypeName(field.value.type, true) + "} value\n"; std::string annotations =
"@param {" + GenTypeName(field.value.type, true) + "} value\n";
GenDocComment(code_ptr, annotations + GenDocComment(code_ptr, annotations +
"@returns {boolean}"); "@returns {boolean}");
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
std::string type; std::string type;
if (field.value.type.enum_def) { if (field.value.type.enum_def) {
type = GenPrefixedTypeName(GenTypeName(field.value.type, true), field.value.type.enum_def->file); type = GenPrefixedTypeName(GenTypeName(field.value.type, true),
field.value.type.enum_def->file);
} else { } else {
type = GenTypeName(field.value.type, true); type = GenTypeName(field.value.type, true);
} }
code += "mutate_" + field.name + "(value:" + type + "):boolean {\n"; code += "mutate_" + field.name + "(value:" + type + "):boolean {\n";
} else { } else {
code += object_name + ".prototype.mutate_" + field.name + " = function(value) {\n"; code += object_name + ".prototype.mutate_" + field.name +
" = function(value) {\n";
} }
code += " var offset = this.bb.__offset(this.bb_pos, " + NumToString(field.value.offset) + ");\n\n"; code += " var offset = this.bb.__offset(this.bb_pos, " +
NumToString(field.value.offset) + ");\n\n";
code += " if (offset === 0) {\n"; code += " if (offset === 0) {\n";
code += " return false;\n"; code += " return false;\n";
code += " }\n\n"; code += " }\n\n";
// special case for bools, which are treated as uint8 // special case for bools, which are treated as uint8
code += " this.bb.write" + MakeCamel(GenType(field.value.type)) + "(this.bb_pos + offset, "; code += " this.bb.write" + MakeCamel(GenType(field.value.type)) +
if (field.value.type.base_type == BASE_TYPE_BOOL && lang_.language == IDLOptions::kTs) { "(this.bb_pos + offset, ";
if (field.value.type.base_type == BASE_TYPE_BOOL &&
lang_.language == IDLOptions::kTs) {
code += "+"; code += "+";
} }
...@@ -885,7 +924,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt ...@@ -885,7 +924,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
code += MakeCamel(field.name, false); code += MakeCamel(field.name, false);
code += "Array():" + GenType(vectorType) + "Array {\n" + offset_prefix; code += "Array():" + GenType(vectorType) + "Array {\n" +
offset_prefix;
} else { } else {
code += object_name + ".prototype." + MakeCamel(field.name, false); code += object_name + ".prototype." + MakeCamel(field.name, false);
code += "Array = function() {\n" + offset_prefix; code += "Array = function() {\n" + offset_prefix;
...@@ -958,13 +998,15 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt ...@@ -958,13 +998,15 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
if (lang_.language == IDLOptions::kTs) { if (lang_.language == IDLOptions::kTs) {
std::string argType; std::string argType;
if (field.value.type.enum_def) { if (field.value.type.enum_def) {
argType = GenPrefixedTypeName(GenTypeName(field.value.type, true), field.value.type.enum_def->file); argType = GenPrefixedTypeName(GenTypeName(field.value.type, true),
field.value.type.enum_def->file);
} else { } else {
argType = GenTypeName(field.value.type, true); argType = GenTypeName(field.value.type, true);
} }
code += "static add" + MakeCamel(field.name); code += "static add" + MakeCamel(field.name);
code += "(builder:flatbuffers.Builder, " + argname + ":" + argType + ") {\n"; code += "(builder:flatbuffers.Builder, " + argname + ":" + argType +
") {\n";
} else { } else {
code += object_name + ".add" + MakeCamel(field.name); code += object_name + ".add" + MakeCamel(field.name);
code += " = function(builder, " + argname + ") {\n"; code += " = function(builder, " + argname + ") {\n";
...@@ -1005,7 +1047,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt ...@@ -1005,7 +1047,8 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
if (type == "number[]") { if (type == "number[]") {
type += " | Uint8Array"; type += " | Uint8Array";
} }
code += "Vector(builder:flatbuffers.Builder, data:" + type+"):flatbuffers.Offset {\n"; code += "Vector(builder:flatbuffers.Builder, data:" + type +
"):flatbuffers.Offset {\n";
code += "if(!data){\n return null\n}\n"; code += "if(!data){\n return null\n}\n";
} else { } else {
code += object_name + ".create" + MakeCamel(field.name); code += object_name + ".create" + MakeCamel(field.name);
......
...@@ -49,7 +49,7 @@ void OutputIdentifier(const std::string &name, const IDLOptions &opts, ...@@ -49,7 +49,7 @@ void OutputIdentifier(const std::string &name, const IDLOptions &opts,
// for a single FlatBuffer value into JSON format. // for a single FlatBuffer value into JSON format.
// The general case for scalars: // The general case for scalars:
template<typename T> bool Print(T val, Type type, int /*indent*/, template<typename T> bool Print(T val, Type type, int /*indent*/,
StructDef * /*union_sd*/, Type */*union_type*/,
const IDLOptions &opts, const IDLOptions &opts,
std::string *_text) { std::string *_text) {
std::string &text = *_text; std::string &text = *_text;
...@@ -169,22 +169,16 @@ static bool EscapeString(const String &s, std::string *_text, const IDLOptions& ...@@ -169,22 +169,16 @@ static bool EscapeString(const String &s, std::string *_text, const IDLOptions&
// Specialization of Print above for pointer types. // Specialization of Print above for pointer types.
template<> bool Print<const void *>(const void *val, template<> bool Print<const void *>(const void *val,
Type type, int indent, Type type, int indent,
StructDef *union_sd, Type *union_type,
const IDLOptions &opts, const IDLOptions &opts,
std::string *_text) { std::string *_text) {
switch (type.base_type) { switch (type.base_type) {
case BASE_TYPE_UNION: case BASE_TYPE_UNION:
// If this assert hits, you have an corrupt buffer, a union type field // If this assert hits, you have an corrupt buffer, a union type field
// was not present or was out of range. // was not present or was out of range.
assert(union_sd); assert(union_type);
if (!GenStruct(*union_sd, return Print<const void *>(val, *union_type, indent, nullptr, opts,
reinterpret_cast<const Table *>(val), _text);
indent,
opts,
_text)) {
return false;
}
break;
case BASE_TYPE_STRUCT: case BASE_TYPE_STRUCT:
if (!GenStruct(*type.struct_def, if (!GenStruct(*type.struct_def,
reinterpret_cast<const Table *>(val), reinterpret_cast<const Table *>(val),
...@@ -236,7 +230,7 @@ template<typename T> static bool GenField(const FieldDef &fd, ...@@ -236,7 +230,7 @@ template<typename T> static bool GenField(const FieldDef &fd,
// Generate text for non-scalar field. // Generate text for non-scalar field.
static bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed, static bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
int indent, StructDef *union_sd, int indent, Type *union_type,
const IDLOptions &opts, std::string *_text) { const IDLOptions &opts, std::string *_text) {
const void *val = nullptr; const void *val = nullptr;
if (fixed) { if (fixed) {
...@@ -249,7 +243,7 @@ static bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed, ...@@ -249,7 +243,7 @@ static bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
? table->GetStruct<const void *>(fd.value.offset) ? table->GetStruct<const void *>(fd.value.offset)
: table->GetPointer<const void *>(fd.value.offset); : table->GetPointer<const void *>(fd.value.offset);
} }
return Print(val, fd.value.type, indent, union_sd, opts, _text); return Print(val, fd.value.type, indent, union_type, opts, _text);
} }
// Generate text for a struct or table, values separated by commas, indented, // Generate text for a struct or table, values separated by commas, indented,
...@@ -260,7 +254,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table, ...@@ -260,7 +254,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
std::string &text = *_text; std::string &text = *_text;
text += "{"; text += "{";
int fieldout = 0; int fieldout = 0;
StructDef *union_sd = nullptr; Type *union_type = nullptr;
for (auto it = struct_def.fields.vec.begin(); for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); it != struct_def.fields.vec.end();
++it) { ++it) {
...@@ -296,7 +290,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table, ...@@ -296,7 +290,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD) FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD #undef FLATBUFFERS_TD
if (!GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts), if (!GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts),
union_sd, opts, _text)) { union_type, opts, _text)) {
return false; return false;
} }
break; break;
...@@ -305,7 +299,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table, ...@@ -305,7 +299,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
auto enum_val = fd.value.type.enum_def->ReverseLookup( auto enum_val = fd.value.type.enum_def->ReverseLookup(
table->GetField<uint8_t>(fd.value.offset, 0)); table->GetField<uint8_t>(fd.value.offset, 0));
assert(enum_val); assert(enum_val);
union_sd = enum_val->struct_def; union_type = &enum_val->union_type;
} }
} }
else else
......
...@@ -735,6 +735,13 @@ CheckedError Parser::ParseField(StructDef &struct_def) { ...@@ -735,6 +735,13 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
return NoError(); return NoError();
} }
CheckedError Parser::ParseString(Value &val) {
auto s = attribute_;
EXPECT(kTokenStringConstant);
val.constant = NumToString(builder_.CreateString(s).o);
return NoError();
}
CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field, CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
size_t parent_fieldn, size_t parent_fieldn,
const StructDef *parent_struct_def) { const StructDef *parent_struct_def) {
...@@ -784,16 +791,27 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field, ...@@ -784,16 +791,27 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
ECHECK(atot(constant.c_str(), *this, &enum_idx)); ECHECK(atot(constant.c_str(), *this, &enum_idx));
auto enum_val = val.type.enum_def->ReverseLookup(enum_idx); auto enum_val = val.type.enum_def->ReverseLookup(enum_idx);
if (!enum_val) return Error("illegal type id for: " + field->name); if (!enum_val) return Error("illegal type id for: " + field->name);
ECHECK(ParseTable(*enum_val->struct_def, &val.constant, nullptr)); if (enum_val->union_type.base_type == BASE_TYPE_STRUCT) {
ECHECK(ParseTable(*enum_val->union_type.struct_def, &val.constant,
nullptr));
if (enum_val->union_type.struct_def->fixed) {
// All BASE_TYPE_UNION values are offsets, so turn this into one.
SerializeStruct(*enum_val->union_type.struct_def, val);
builder_.ClearOffsets();
val.constant = NumToString(builder_.GetSize());
}
} else if (enum_val->union_type.base_type == BASE_TYPE_STRING) {
ECHECK(ParseString(val));
} else {
assert(false);
}
break; break;
} }
case BASE_TYPE_STRUCT: case BASE_TYPE_STRUCT:
ECHECK(ParseTable(*val.type.struct_def, &val.constant, nullptr)); ECHECK(ParseTable(*val.type.struct_def, &val.constant, nullptr));
break; break;
case BASE_TYPE_STRING: { case BASE_TYPE_STRING: {
auto s = attribute_; ECHECK(ParseString(val));
EXPECT(kTokenStringConstant);
val.constant = NumToString(builder_.CreateString(s).o);
break; break;
} }
case BASE_TYPE_VECTOR: { case BASE_TYPE_VECTOR: {
...@@ -1290,7 +1308,16 @@ CheckedError Parser::ParseEnum(bool is_union, EnumDef **dest) { ...@@ -1290,7 +1308,16 @@ CheckedError Parser::ParseEnum(bool is_union, EnumDef **dest) {
return Error("enum value already exists: " + value_name); return Error("enum value already exists: " + value_name);
ev.doc_comment = value_comment; ev.doc_comment = value_comment;
if (is_union) { if (is_union) {
ev.struct_def = LookupCreateStruct(full_name); if (Is(':')) {
NEXT();
ECHECK(ParseType(ev.union_type));
if (ev.union_type.base_type != BASE_TYPE_STRUCT &&
ev.union_type.base_type != BASE_TYPE_STRING)
return Error("union value type may only be table/struct/string");
enum_def.uses_type_aliases = true;
} else {
ev.union_type = Type(BASE_TYPE_STRUCT, LookupCreateStruct(full_name));
}
} }
if (Is('=')) { if (Is('=')) {
NEXT(); NEXT();
...@@ -1994,6 +2021,8 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths, ...@@ -1994,6 +2021,8 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
return Error("type referenced but not defined: " + (*it)->name); return Error("type referenced but not defined: " + (*it)->name);
} }
} }
// This check has to happen here and not earlier, because only now do we
// know for sure what the type of these are.
for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) { for (auto it = enums_.vec.begin(); it != enums_.vec.end(); ++it) {
auto &enum_def = **it; auto &enum_def = **it;
if (enum_def.is_union) { if (enum_def.is_union) {
...@@ -2001,8 +2030,11 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths, ...@@ -2001,8 +2030,11 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
val_it != enum_def.vals.vec.end(); val_it != enum_def.vals.vec.end();
++val_it) { ++val_it) {
auto &val = **val_it; auto &val = **val_it;
if (val.struct_def && val.struct_def->fixed) if (opts.lang_to_generate != IDLOptions::kCpp &&
return Error("only tables can be union elements: " + val.name); val.union_type.struct_def && val.union_type.struct_def->fixed)
return Error(
"only tables can be union elements in the generated language: "
+ val.name);
} }
} }
} }
...@@ -2145,9 +2177,11 @@ Offset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder) const ...@@ -2145,9 +2177,11 @@ Offset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder) const
return reflection::CreateEnumVal(*builder, return reflection::CreateEnumVal(*builder,
builder->CreateString(name), builder->CreateString(name),
value, value,
struct_def union_type.struct_def
? struct_def->serialized_location ? union_type.struct_def->
: 0); serialized_location
: 0,
union_type.Serialize(builder));
} }
Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const { Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const {
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
../flatc --cpp --java --csharp --go --binary --python --js --ts --php --grpc --gen-mutable --gen-object-api --no-includes monster_test.fbs monsterdata_test.json ../flatc --cpp --java --csharp --go --binary --python --js --ts --php --grpc --gen-mutable --gen-object-api --no-includes monster_test.fbs monsterdata_test.json
../flatc --cpp --java --csharp --go --binary --python --js --ts --php --gen-mutable -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs ../flatc --cpp --java --csharp --go --binary --python --js --ts --php --gen-mutable -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs
../flatc --cpp -o union_vector ./union_vector/union_vector.fbs ../flatc --cpp --gen-mutable --gen-object-api -o union_vector ./union_vector/union_vector.fbs
../flatc -b --schema --bfbs-comments monster_test.fbs ../flatc -b --schema --bfbs-comments monster_test.fbs
cd ../samples cd ../samples
../flatc --cpp --gen-mutable --gen-object-api monster.fbs ../flatc --cpp --gen-mutable --gen-object-api monster.fbs
......
No preview for this file type
...@@ -102,43 +102,43 @@ template<> struct AnyTraits<MyGame::Example2::Monster> { ...@@ -102,43 +102,43 @@ template<> struct AnyTraits<MyGame::Example2::Monster> {
struct AnyUnion { struct AnyUnion {
Any type; Any type;
flatbuffers::NativeTable *table; void *value;
AnyUnion() : type(Any_NONE), table(nullptr) {} AnyUnion() : type(Any_NONE), value(nullptr) {}
AnyUnion(AnyUnion&& u) FLATBUFFERS_NOEXCEPT : AnyUnion(AnyUnion&& u) FLATBUFFERS_NOEXCEPT :
type(Any_NONE), table(nullptr) type(Any_NONE), value(nullptr)
{ std::swap(type, u.type); std::swap(table, u.table); } { std::swap(type, u.type); std::swap(value, u.value); }
AnyUnion(const AnyUnion &); AnyUnion(const AnyUnion &);
AnyUnion &operator=(const AnyUnion &); AnyUnion &operator=(const AnyUnion &);
AnyUnion &operator=(AnyUnion &&u) FLATBUFFERS_NOEXCEPT AnyUnion &operator=(AnyUnion &&u) FLATBUFFERS_NOEXCEPT
{ std::swap(type, u.type); std::swap(table, u.table); return *this; } { std::swap(type, u.type); std::swap(value, u.value); return *this; }
~AnyUnion() { Reset(); } ~AnyUnion() { Reset(); }
void Reset(); void Reset();
template <typename T> template <typename T>
void Set(T&& value) { void Set(T&& val) {
Reset(); Reset();
type = AnyTraits<typename T::TableType>::enum_value; type = AnyTraits<typename T::TableType>::enum_value;
if (type != Any_NONE) { if (type != Any_NONE) {
table = new T(std::forward<T>(value)); value = new T(std::forward<T>(val));
} }
} }
static flatbuffers::NativeTable *UnPack(const void *obj, Any type, const flatbuffers::resolver_function_t *resolver); static void *UnPack(const void *obj, Any type, const flatbuffers::resolver_function_t *resolver);
flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher = nullptr) const; flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher = nullptr) const;
MonsterT *AsMonster() { MonsterT *AsMonster() {
return type == Any_Monster ? return type == Any_Monster ?
reinterpret_cast<MonsterT *>(table) : nullptr; reinterpret_cast<MonsterT *>(value) : nullptr;
} }
TestSimpleTableWithEnumT *AsTestSimpleTableWithEnum() { TestSimpleTableWithEnumT *AsTestSimpleTableWithEnum() {
return type == Any_TestSimpleTableWithEnum ? return type == Any_TestSimpleTableWithEnum ?
reinterpret_cast<TestSimpleTableWithEnumT *>(table) : nullptr; reinterpret_cast<TestSimpleTableWithEnumT *>(value) : nullptr;
} }
MyGame::Example2::MonsterT *AsMyGame_Example2_Monster() { MyGame::Example2::MonsterT *AsMyGame_Example2_Monster() {
return type == Any_MyGame_Example2_Monster ? return type == Any_MyGame_Example2_Monster ?
reinterpret_cast<MyGame::Example2::MonsterT *>(table) : nullptr; reinterpret_cast<MyGame::Example2::MonsterT *>(value) : nullptr;
} }
}; };
...@@ -629,13 +629,13 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { ...@@ -629,13 +629,13 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
} }
template<typename T> const T *test_as() const; template<typename T> const T *test_as() const;
const Monster *test_as_Monster() const { const Monster *test_as_Monster() const {
return (test_type() == Any_Monster)? static_cast<const Monster *>(test()) : nullptr; return test_type() == Any_Monster ? static_cast<const Monster *>(test()) : nullptr;
} }
const TestSimpleTableWithEnum *test_as_TestSimpleTableWithEnum() const { const TestSimpleTableWithEnum *test_as_TestSimpleTableWithEnum() const {
return (test_type() == Any_TestSimpleTableWithEnum)? static_cast<const TestSimpleTableWithEnum *>(test()) : nullptr; return test_type() == Any_TestSimpleTableWithEnum ? static_cast<const TestSimpleTableWithEnum *>(test()) : nullptr;
} }
const MyGame::Example2::Monster *test_as_MyGame_Example2_Monster() const { const MyGame::Example2::Monster *test_as_MyGame_Example2_Monster() const {
return (test_type() == Any_MyGame_Example2_Monster)? static_cast<const MyGame::Example2::Monster *>(test()) : nullptr; return test_type() == Any_MyGame_Example2_Monster ? static_cast<const MyGame::Example2::Monster *>(test()) : nullptr;
} }
void *mutable_test() { void *mutable_test() {
return GetPointer<void *>(VT_TEST); return GetPointer<void *>(VT_TEST);
...@@ -1172,7 +1172,7 @@ inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function ...@@ -1172,7 +1172,7 @@ inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function
{ auto _e = inventory(); if (_e) { _o->inventory.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inventory[_i] = _e->Get(_i); } } }; { auto _e = inventory(); if (_e) { _o->inventory.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inventory[_i] = _e->Get(_i); } } };
{ auto _e = color(); _o->color = _e; }; { auto _e = color(); _o->color = _e; };
{ auto _e = test_type(); _o->test.type = _e; }; { auto _e = test_type(); _o->test.type = _e; };
{ auto _e = test(); if (_e) _o->test.table = AnyUnion::UnPack(_e, test_type(),_resolver); }; { auto _e = test(); if (_e) _o->test.value = AnyUnion::UnPack(_e, test_type(), _resolver); };
{ auto _e = test4(); if (_e) { _o->test4.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->test4[_i] = *_e->Get(_i); } } }; { auto _e = test4(); if (_e) { _o->test4.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->test4[_i] = *_e->Get(_i); } } };
{ auto _e = testarrayofstring(); if (_e) { _o->testarrayofstring.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofstring[_i] = _e->Get(_i)->str(); } } }; { auto _e = testarrayofstring(); if (_e) { _o->testarrayofstring.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofstring[_i] = _e->Get(_i)->str(); } } };
{ auto _e = testarrayoftables(); if (_e) { _o->testarrayoftables.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayoftables[_i] = std::unique_ptr<MonsterT>(_e->Get(_i)->UnPack(_resolver)); } } }; { auto _e = testarrayoftables(); if (_e) { _o->testarrayoftables.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayoftables[_i] = std::unique_ptr<MonsterT>(_e->Get(_i)->UnPack(_resolver)); } } };
...@@ -1297,7 +1297,7 @@ inline bool VerifyAnyVector(flatbuffers::Verifier &verifier, const flatbuffers:: ...@@ -1297,7 +1297,7 @@ inline bool VerifyAnyVector(flatbuffers::Verifier &verifier, const flatbuffers::
return true; return true;
} }
inline flatbuffers::NativeTable *AnyUnion::UnPack(const void *obj, Any type, const flatbuffers::resolver_function_t *resolver) { inline void *AnyUnion::UnPack(const void *obj, Any type, const flatbuffers::resolver_function_t *resolver) {
switch (type) { switch (type) {
case Any_Monster: { case Any_Monster: {
auto ptr = reinterpret_cast<const Monster *>(obj); auto ptr = reinterpret_cast<const Monster *>(obj);
...@@ -1318,15 +1318,15 @@ inline flatbuffers::NativeTable *AnyUnion::UnPack(const void *obj, Any type, con ...@@ -1318,15 +1318,15 @@ inline flatbuffers::NativeTable *AnyUnion::UnPack(const void *obj, Any type, con
inline flatbuffers::Offset<void> AnyUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher) const { inline flatbuffers::Offset<void> AnyUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher) const {
switch (type) { switch (type) {
case Any_Monster: { case Any_Monster: {
auto ptr = reinterpret_cast<const MonsterT *>(table); auto ptr = reinterpret_cast<const MonsterT *>(value);
return CreateMonster(_fbb, ptr, _rehasher).Union(); return CreateMonster(_fbb, ptr, _rehasher).Union();
} }
case Any_TestSimpleTableWithEnum: { case Any_TestSimpleTableWithEnum: {
auto ptr = reinterpret_cast<const TestSimpleTableWithEnumT *>(table); auto ptr = reinterpret_cast<const TestSimpleTableWithEnumT *>(value);
return CreateTestSimpleTableWithEnum(_fbb, ptr, _rehasher).Union(); return CreateTestSimpleTableWithEnum(_fbb, ptr, _rehasher).Union();
} }
case Any_MyGame_Example2_Monster: { case Any_MyGame_Example2_Monster: {
auto ptr = reinterpret_cast<const MyGame::Example2::MonsterT *>(table); auto ptr = reinterpret_cast<const MyGame::Example2::MonsterT *>(value);
return CreateMonster(_fbb, ptr, _rehasher).Union(); return CreateMonster(_fbb, ptr, _rehasher).Union();
} }
default: return 0; default: return 0;
...@@ -1336,23 +1336,23 @@ inline flatbuffers::Offset<void> AnyUnion::Pack(flatbuffers::FlatBufferBuilder & ...@@ -1336,23 +1336,23 @@ inline flatbuffers::Offset<void> AnyUnion::Pack(flatbuffers::FlatBufferBuilder &
inline void AnyUnion::Reset() { inline void AnyUnion::Reset() {
switch (type) { switch (type) {
case Any_Monster: { case Any_Monster: {
auto ptr = reinterpret_cast<MonsterT *>(table); auto ptr = reinterpret_cast<MonsterT *>(value);
delete ptr; delete ptr;
break; break;
} }
case Any_TestSimpleTableWithEnum: { case Any_TestSimpleTableWithEnum: {
auto ptr = reinterpret_cast<TestSimpleTableWithEnumT *>(table); auto ptr = reinterpret_cast<TestSimpleTableWithEnumT *>(value);
delete ptr; delete ptr;
break; break;
} }
case Any_MyGame_Example2_Monster: { case Any_MyGame_Example2_Monster: {
auto ptr = reinterpret_cast<MyGame::Example2::MonsterT *>(table); auto ptr = reinterpret_cast<MyGame::Example2::MonsterT *>(value);
delete ptr; delete ptr;
break; break;
} }
default: break; default: break;
} }
table = nullptr; value = nullptr;
type = Any_NONE; type = Any_NONE;
} }
......
...@@ -1334,46 +1334,78 @@ void UnionVectorTest() { ...@@ -1334,46 +1334,78 @@ void UnionVectorTest() {
// union types. // union types.
std::vector<uint8_t> types; std::vector<uint8_t> types;
types.push_back(static_cast<uint8_t>(Character_Belle)); types.push_back(static_cast<uint8_t>(Character_Belle));
types.push_back(static_cast<uint8_t>(Character_Rapunzel));
types.push_back(static_cast<uint8_t>(Character_MuLan)); types.push_back(static_cast<uint8_t>(Character_MuLan));
types.push_back(static_cast<uint8_t>(Character_BookFan));
types.push_back(static_cast<uint8_t>(Character_Other));
types.push_back(static_cast<uint8_t>(Character_Unused));
// union values. // union values.
std::vector<flatbuffers::Offset<void>> characters; std::vector<flatbuffers::Offset<void>> characters;
characters.push_back(CreateBelle(fbb, /*books_read=*/7).Union()); characters.push_back(fbb.CreateStruct(BookReader(/*books_read=*/7)).Union());
characters.push_back(CreateRapunzel(fbb, /*hair_length=*/6).Union()); characters.push_back(CreateAttacker(fbb, /*sword_attack_damage=*/5).Union());
characters.push_back(CreateMuLan(fbb, /*sword_attack_damage=*/5).Union()); characters.push_back(fbb.CreateStruct(BookReader(/*books_read=*/2)).Union());
characters.push_back(fbb.CreateString("Other").Union());
characters.push_back(fbb.CreateString("Unused").Union());
// create Movie. // create Movie.
const auto movie_offset = const auto movie_offset =
CreateMovie(fbb, fbb.CreateVector(types), fbb.CreateVector(characters)); CreateMovie(fbb,
Character_Rapunzel,
fbb.CreateStruct(Rapunzel(/*hair_length=*/6)).Union(),
fbb.CreateVector(types),
fbb.CreateVector(characters));
FinishMovieBuffer(fbb, movie_offset); FinishMovieBuffer(fbb, movie_offset);
uint8_t *buf = fbb.GetBufferPointer(); auto buf = fbb.GetBufferPointer();
flatbuffers::Verifier verifier(buf, fbb.GetSize()); flatbuffers::Verifier verifier(buf, fbb.GetSize());
TEST_EQ(VerifyMovieBuffer(verifier), true); TEST_EQ(VerifyMovieBuffer(verifier), true);
const Movie *movie = GetMovie(buf); auto flat_movie = GetMovie(buf);
TEST_EQ(movie->characters_type()->size(), 3);
TEST_EQ(
movie->characters_type()->GetEnum<Character>(0) == Character_Belle,
true);
TEST_EQ(
movie->characters_type()->GetEnum<Character>(1) == Character_Rapunzel,
true);
TEST_EQ(
movie->characters_type()->GetEnum<Character>(2) == Character_MuLan,
true);
TEST_EQ(movie->characters()->size(), 3); auto TestMovie = [](const Movie *movie) {
const Belle *belle = TEST_EQ(movie->main_character_type() == Character_Rapunzel, true);
reinterpret_cast<const Belle*>(movie->characters()->Get(0));
TEST_EQ(belle->books_read(), 7); auto cts = movie->characters_type();
const Rapunzel *rapunzel = TEST_EQ(movie->characters_type()->size(), 5);
reinterpret_cast<const Rapunzel*>(movie->characters()->Get(1)); TEST_EQ(cts->GetEnum<Character>(0) == Character_Belle, true);
TEST_EQ(cts->GetEnum<Character>(1) == Character_MuLan, true);
TEST_EQ(cts->GetEnum<Character>(2) == Character_BookFan, true);
TEST_EQ(cts->GetEnum<Character>(3) == Character_Other, true);
TEST_EQ(cts->GetEnum<Character>(4) == Character_Unused, true);
auto rapunzel = movie->main_character_as_Rapunzel();
TEST_EQ(rapunzel->hair_length(), 6); TEST_EQ(rapunzel->hair_length(), 6);
const MuLan *mu_lan =
reinterpret_cast<const MuLan*>(movie->characters()->Get(2)); auto cs = movie->characters();
TEST_EQ(cs->size(), 5);
auto belle = cs->GetAs<BookReader>(0);
TEST_EQ(belle->books_read(), 7);
auto mu_lan = cs->GetAs<Attacker>(1);
TEST_EQ(mu_lan->sword_attack_damage(), 5); TEST_EQ(mu_lan->sword_attack_damage(), 5);
auto book_fan = cs->GetAs<BookReader>(2);
TEST_EQ(book_fan->books_read(), 2);
auto other = cs->GetAsString(3);
TEST_EQ_STR(other->c_str(), "Other");
auto unused = cs->GetAsString(4);
TEST_EQ_STR(unused->c_str(), "Unused");
};
TestMovie(flat_movie);
auto movie_object = flat_movie->UnPack();
TEST_EQ(movie_object->main_character.AsRapunzel()->hair_length(), 6);
TEST_EQ(movie_object->characters[0].AsBelle()->books_read(), 7);
TEST_EQ(movie_object->characters[1].AsMuLan()->sword_attack_damage, 5);
TEST_EQ(movie_object->characters[2].AsBookFan()->books_read(), 2);
TEST_EQ_STR(movie_object->characters[3].AsOther()->c_str(), "Other");
TEST_EQ_STR(movie_object->characters[4].AsUnused()->c_str(), "Unused");
fbb.Clear();
fbb.Finish(Movie::Pack(fbb, movie_object));
auto repacked_movie = GetMovie(fbb.GetBufferPointer());
TestMovie(repacked_movie);
} }
void ConformTest() { void ConformTest() {
......
table MuLan { // Demonstrates the ability to have vectors of unions, and also to
// store structs and strings in unions.
table Attacker {
sword_attack_damage: int; sword_attack_damage: int;
} }
table Rapunzel { struct Rapunzel {
hair_length: int; hair_length: int;
} }
table Belle { struct BookReader {
books_read: int; books_read: int;
} }
union Character { union Character {
MuLan, MuLan: Attacker, // Can have name be different from type.
Rapunzel, Rapunzel, // Or just both the same, as before.
Belle, Belle: BookReader,
BookFan: BookReader,
Other: string,
Unused: string
} }
table Movie { table Movie {
main_character: Character;
characters: [Character]; characters: [Character];
} }
......
...@@ -6,21 +6,26 @@ ...@@ -6,21 +6,26 @@
#include "flatbuffers/flatbuffers.h" #include "flatbuffers/flatbuffers.h"
struct MuLan; struct Attacker;
struct AttackerT;
struct Rapunzel; struct Rapunzel;
struct Belle; struct BookReader;
struct Movie; struct Movie;
struct MovieT;
enum Character { enum Character {
Character_NONE = 0, Character_NONE = 0,
Character_MuLan = 1, Character_MuLan = 1,
Character_Rapunzel = 2, Character_Rapunzel = 2,
Character_Belle = 3, Character_Belle = 3,
Character_BookFan = 4,
Character_Other = 5,
Character_Unused = 6,
Character_MIN = Character_NONE, Character_MIN = Character_NONE,
Character_MAX = Character_Belle Character_MAX = Character_Unused
}; };
inline const char **EnumNamesCharacter() { inline const char **EnumNamesCharacter() {
...@@ -29,6 +34,9 @@ inline const char **EnumNamesCharacter() { ...@@ -29,6 +34,9 @@ inline const char **EnumNamesCharacter() {
"MuLan", "MuLan",
"Rapunzel", "Rapunzel",
"Belle", "Belle",
"BookFan",
"Other",
"Unused",
nullptr nullptr
}; };
return names; return names;
...@@ -39,158 +47,221 @@ inline const char *EnumNameCharacter(Character e) { ...@@ -39,158 +47,221 @@ inline const char *EnumNameCharacter(Character e) {
return EnumNamesCharacter()[index]; return EnumNamesCharacter()[index];
} }
template<typename T> struct CharacterTraits { struct CharacterUnion {
static const Character enum_value = Character_NONE; Character type;
}; void *value;
template<> struct CharacterTraits<MuLan> { CharacterUnion() : type(Character_NONE), value(nullptr) {}
static const Character enum_value = Character_MuLan; CharacterUnion(CharacterUnion&& u) FLATBUFFERS_NOEXCEPT :
}; type(Character_NONE), value(nullptr)
{ std::swap(type, u.type); std::swap(value, u.value); }
CharacterUnion(const CharacterUnion &);
CharacterUnion &operator=(const CharacterUnion &);
CharacterUnion &operator=(CharacterUnion &&u) FLATBUFFERS_NOEXCEPT
{ std::swap(type, u.type); std::swap(value, u.value); return *this; }
~CharacterUnion() { Reset(); }
template<> struct CharacterTraits<Rapunzel> { void Reset();
static const Character enum_value = Character_Rapunzel;
};
template<> struct CharacterTraits<Belle> { static void *UnPack(const void *obj, Character type, const flatbuffers::resolver_function_t *resolver);
static const Character enum_value = Character_Belle; flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher = nullptr) const;
AttackerT *AsMuLan() {
return type == Character_MuLan ?
reinterpret_cast<AttackerT *>(value) : nullptr;
}
Rapunzel *AsRapunzel() {
return type == Character_Rapunzel ?
reinterpret_cast<Rapunzel *>(value) : nullptr;
}
BookReader *AsBelle() {
return type == Character_Belle ?
reinterpret_cast<BookReader *>(value) : nullptr;
}
BookReader *AsBookFan() {
return type == Character_BookFan ?
reinterpret_cast<BookReader *>(value) : nullptr;
}
std::string *AsOther() {
return type == Character_Other ?
reinterpret_cast<std::string *>(value) : nullptr;
}
std::string *AsUnused() {
return type == Character_Unused ?
reinterpret_cast<std::string *>(value) : nullptr;
}
}; };
bool VerifyCharacter(flatbuffers::Verifier &verifier, const void *obj, Character type); bool VerifyCharacter(flatbuffers::Verifier &verifier, const void *obj, Character type);
bool VerifyCharacterVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types); bool VerifyCharacterVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
struct MuLan FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { MANUALLY_ALIGNED_STRUCT(4) Rapunzel FLATBUFFERS_FINAL_CLASS {
enum { private:
VT_SWORD_ATTACK_DAMAGE = 4 int32_t hair_length_;
};
int32_t sword_attack_damage() const { public:
return GetField<int32_t>(VT_SWORD_ATTACK_DAMAGE, 0); Rapunzel() {
memset(this, 0, sizeof(Rapunzel));
} }
bool Verify(flatbuffers::Verifier &verifier) const { Rapunzel(const Rapunzel &_o) {
return VerifyTableStart(verifier) && memcpy(this, &_o, sizeof(Rapunzel));
VerifyField<int32_t>(verifier, VT_SWORD_ATTACK_DAMAGE) &&
verifier.EndTable();
} }
}; Rapunzel(int32_t _hair_length)
: hair_length_(flatbuffers::EndianScalar(_hair_length)) {
struct MuLanBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_sword_attack_damage(int32_t sword_attack_damage) {
fbb_.AddElement<int32_t>(MuLan::VT_SWORD_ATTACK_DAMAGE, sword_attack_damage, 0);
} }
MuLanBuilder(flatbuffers::FlatBufferBuilder &_fbb) int32_t hair_length() const {
: fbb_(_fbb) { return flatbuffers::EndianScalar(hair_length_);
start_ = fbb_.StartTable();
} }
MuLanBuilder &operator=(const MuLanBuilder &); void mutate_hair_length(int32_t _hair_length) {
flatbuffers::Offset<MuLan> Finish() { flatbuffers::WriteScalar(&hair_length_, _hair_length);
const auto end = fbb_.EndTable(start_, 1);
auto o = flatbuffers::Offset<MuLan>(end);
return o;
} }
}; };
STRUCT_END(Rapunzel, 4);
inline flatbuffers::Offset<MuLan> CreateMuLan( MANUALLY_ALIGNED_STRUCT(4) BookReader FLATBUFFERS_FINAL_CLASS {
flatbuffers::FlatBufferBuilder &_fbb, private:
int32_t sword_attack_damage = 0) { int32_t books_read_;
MuLanBuilder builder_(_fbb);
builder_.add_sword_attack_damage(sword_attack_damage);
return builder_.Finish();
}
struct Rapunzel FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { public:
enum { BookReader() {
VT_HAIR_LENGTH = 4 memset(this, 0, sizeof(BookReader));
};
int32_t hair_length() const {
return GetField<int32_t>(VT_HAIR_LENGTH, 0);
} }
bool Verify(flatbuffers::Verifier &verifier) const { BookReader(const BookReader &_o) {
return VerifyTableStart(verifier) && memcpy(this, &_o, sizeof(BookReader));
VerifyField<int32_t>(verifier, VT_HAIR_LENGTH) &&
verifier.EndTable();
} }
}; BookReader(int32_t _books_read)
: books_read_(flatbuffers::EndianScalar(_books_read)) {
struct RapunzelBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_hair_length(int32_t hair_length) {
fbb_.AddElement<int32_t>(Rapunzel::VT_HAIR_LENGTH, hair_length, 0);
} }
RapunzelBuilder(flatbuffers::FlatBufferBuilder &_fbb) int32_t books_read() const {
: fbb_(_fbb) { return flatbuffers::EndianScalar(books_read_);
start_ = fbb_.StartTable();
} }
RapunzelBuilder &operator=(const RapunzelBuilder &); void mutate_books_read(int32_t _books_read) {
flatbuffers::Offset<Rapunzel> Finish() { flatbuffers::WriteScalar(&books_read_, _books_read);
const auto end = fbb_.EndTable(start_, 1);
auto o = flatbuffers::Offset<Rapunzel>(end);
return o;
} }
}; };
STRUCT_END(BookReader, 4);
inline flatbuffers::Offset<Rapunzel> CreateRapunzel( struct AttackerT : public flatbuffers::NativeTable {
flatbuffers::FlatBufferBuilder &_fbb, typedef Attacker TableType;
int32_t hair_length = 0) { int32_t sword_attack_damage;
RapunzelBuilder builder_(_fbb); AttackerT()
builder_.add_hair_length(hair_length); : sword_attack_damage(0) {
return builder_.Finish(); }
} };
struct Belle FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Attacker FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef AttackerT NativeTableType;
enum { enum {
VT_BOOKS_READ = 4 VT_SWORD_ATTACK_DAMAGE = 4
}; };
int32_t books_read() const { int32_t sword_attack_damage() const {
return GetField<int32_t>(VT_BOOKS_READ, 0); return GetField<int32_t>(VT_SWORD_ATTACK_DAMAGE, 0);
}
bool mutate_sword_attack_damage(int32_t _sword_attack_damage) {
return SetField<int32_t>(VT_SWORD_ATTACK_DAMAGE, _sword_attack_damage, 0);
} }
bool Verify(flatbuffers::Verifier &verifier) const { bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) && return VerifyTableStart(verifier) &&
VerifyField<int32_t>(verifier, VT_BOOKS_READ) && VerifyField<int32_t>(verifier, VT_SWORD_ATTACK_DAMAGE) &&
verifier.EndTable(); verifier.EndTable();
} }
AttackerT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
void UnPackTo(AttackerT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
static flatbuffers::Offset<Attacker> Pack(flatbuffers::FlatBufferBuilder &_fbb, const AttackerT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
}; };
struct BelleBuilder { struct AttackerBuilder {
flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_; flatbuffers::uoffset_t start_;
void add_books_read(int32_t books_read) { void add_sword_attack_damage(int32_t sword_attack_damage) {
fbb_.AddElement<int32_t>(Belle::VT_BOOKS_READ, books_read, 0); fbb_.AddElement<int32_t>(Attacker::VT_SWORD_ATTACK_DAMAGE, sword_attack_damage, 0);
} }
BelleBuilder(flatbuffers::FlatBufferBuilder &_fbb) AttackerBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) { : fbb_(_fbb) {
start_ = fbb_.StartTable(); start_ = fbb_.StartTable();
} }
BelleBuilder &operator=(const BelleBuilder &); AttackerBuilder &operator=(const AttackerBuilder &);
flatbuffers::Offset<Belle> Finish() { flatbuffers::Offset<Attacker> Finish() {
const auto end = fbb_.EndTable(start_, 1); const auto end = fbb_.EndTable(start_, 1);
auto o = flatbuffers::Offset<Belle>(end); auto o = flatbuffers::Offset<Attacker>(end);
return o; return o;
} }
}; };
inline flatbuffers::Offset<Belle> CreateBelle( inline flatbuffers::Offset<Attacker> CreateAttacker(
flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::FlatBufferBuilder &_fbb,
int32_t books_read = 0) { int32_t sword_attack_damage = 0) {
BelleBuilder builder_(_fbb); AttackerBuilder builder_(_fbb);
builder_.add_books_read(books_read); builder_.add_sword_attack_damage(sword_attack_damage);
return builder_.Finish(); return builder_.Finish();
} }
flatbuffers::Offset<Attacker> CreateAttacker(flatbuffers::FlatBufferBuilder &_fbb, const AttackerT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
struct MovieT : public flatbuffers::NativeTable {
typedef Movie TableType;
CharacterUnion main_character;
std::vector<CharacterUnion> characters;
MovieT() {
}
};
struct Movie FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { struct Movie FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef MovieT NativeTableType;
enum { enum {
VT_CHARACTERS_TYPE = 4, VT_MAIN_CHARACTER_TYPE = 4,
VT_CHARACTERS = 6 VT_MAIN_CHARACTER = 6,
VT_CHARACTERS_TYPE = 8,
VT_CHARACTERS = 10
}; };
Character main_character_type() const {
return static_cast<Character>(GetField<uint8_t>(VT_MAIN_CHARACTER_TYPE, 0));
}
bool mutate_main_character_type(Character _main_character_type) {
return SetField<uint8_t>(VT_MAIN_CHARACTER_TYPE, static_cast<uint8_t>(_main_character_type), 0);
}
const void *main_character() const {
return GetPointer<const void *>(VT_MAIN_CHARACTER);
}
template<typename T> const T *main_character_as() const;
const Attacker *main_character_as_MuLan() const {
return main_character_type() == Character_MuLan ? static_cast<const Attacker *>(main_character()) : nullptr;
}
const Rapunzel *main_character_as_Rapunzel() const {
return main_character_type() == Character_Rapunzel ? static_cast<const Rapunzel *>(main_character()) : nullptr;
}
const BookReader *main_character_as_Belle() const {
return main_character_type() == Character_Belle ? static_cast<const BookReader *>(main_character()) : nullptr;
}
const BookReader *main_character_as_BookFan() const {
return main_character_type() == Character_BookFan ? static_cast<const BookReader *>(main_character()) : nullptr;
}
const flatbuffers::String *main_character_as_Other() const {
return main_character_type() == Character_Other ? static_cast<const flatbuffers::String *>(main_character()) : nullptr;
}
const flatbuffers::String *main_character_as_Unused() const {
return main_character_type() == Character_Unused ? static_cast<const flatbuffers::String *>(main_character()) : nullptr;
}
void *mutable_main_character() {
return GetPointer<void *>(VT_MAIN_CHARACTER);
}
const flatbuffers::Vector<uint8_t> *characters_type() const { const flatbuffers::Vector<uint8_t> *characters_type() const {
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_CHARACTERS_TYPE); return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_CHARACTERS_TYPE);
} }
flatbuffers::Vector<uint8_t> *mutable_characters_type() {
return GetPointer<flatbuffers::Vector<uint8_t> *>(VT_CHARACTERS_TYPE);
}
const flatbuffers::Vector<flatbuffers::Offset<void>> *characters() const { const flatbuffers::Vector<flatbuffers::Offset<void>> *characters() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<void>> *>(VT_CHARACTERS); return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<void>> *>(VT_CHARACTERS);
} }
flatbuffers::Vector<flatbuffers::Offset<void>> *mutable_characters() {
return GetPointer<flatbuffers::Vector<flatbuffers::Offset<void>> *>(VT_CHARACTERS);
}
bool Verify(flatbuffers::Verifier &verifier) const { bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) && return VerifyTableStart(verifier) &&
VerifyField<uint8_t>(verifier, VT_MAIN_CHARACTER_TYPE) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_MAIN_CHARACTER) &&
VerifyCharacter(verifier, main_character(), main_character_type()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_CHARACTERS_TYPE) && VerifyField<flatbuffers::uoffset_t>(verifier, VT_CHARACTERS_TYPE) &&
verifier.Verify(characters_type()) && verifier.Verify(characters_type()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_CHARACTERS) && VerifyField<flatbuffers::uoffset_t>(verifier, VT_CHARACTERS) &&
...@@ -198,11 +269,20 @@ struct Movie FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { ...@@ -198,11 +269,20 @@ struct Movie FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyCharacterVector(verifier, characters(), characters_type()) && VerifyCharacterVector(verifier, characters(), characters_type()) &&
verifier.EndTable(); verifier.EndTable();
} }
MovieT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
void UnPackTo(MovieT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
static flatbuffers::Offset<Movie> Pack(flatbuffers::FlatBufferBuilder &_fbb, const MovieT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
}; };
struct MovieBuilder { struct MovieBuilder {
flatbuffers::FlatBufferBuilder &fbb_; flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_; flatbuffers::uoffset_t start_;
void add_main_character_type(Character main_character_type) {
fbb_.AddElement<uint8_t>(Movie::VT_MAIN_CHARACTER_TYPE, static_cast<uint8_t>(main_character_type), 0);
}
void add_main_character(flatbuffers::Offset<void> main_character) {
fbb_.AddOffset(Movie::VT_MAIN_CHARACTER, main_character);
}
void add_characters_type(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> characters_type) { void add_characters_type(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> characters_type) {
fbb_.AddOffset(Movie::VT_CHARACTERS_TYPE, characters_type); fbb_.AddOffset(Movie::VT_CHARACTERS_TYPE, characters_type);
} }
...@@ -215,7 +295,7 @@ struct MovieBuilder { ...@@ -215,7 +295,7 @@ struct MovieBuilder {
} }
MovieBuilder &operator=(const MovieBuilder &); MovieBuilder &operator=(const MovieBuilder &);
flatbuffers::Offset<Movie> Finish() { flatbuffers::Offset<Movie> Finish() {
const auto end = fbb_.EndTable(start_, 2); const auto end = fbb_.EndTable(start_, 4);
auto o = flatbuffers::Offset<Movie>(end); auto o = flatbuffers::Offset<Movie>(end);
return o; return o;
} }
...@@ -223,40 +303,118 @@ struct MovieBuilder { ...@@ -223,40 +303,118 @@ struct MovieBuilder {
inline flatbuffers::Offset<Movie> CreateMovie( inline flatbuffers::Offset<Movie> CreateMovie(
flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::FlatBufferBuilder &_fbb,
Character main_character_type = Character_NONE,
flatbuffers::Offset<void> main_character = 0,
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> characters_type = 0, flatbuffers::Offset<flatbuffers::Vector<uint8_t>> characters_type = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<void>>> characters = 0) { flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<void>>> characters = 0) {
MovieBuilder builder_(_fbb); MovieBuilder builder_(_fbb);
builder_.add_characters(characters); builder_.add_characters(characters);
builder_.add_characters_type(characters_type); builder_.add_characters_type(characters_type);
builder_.add_main_character(main_character);
builder_.add_main_character_type(main_character_type);
return builder_.Finish(); return builder_.Finish();
} }
inline flatbuffers::Offset<Movie> CreateMovieDirect( inline flatbuffers::Offset<Movie> CreateMovieDirect(
flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::FlatBufferBuilder &_fbb,
Character main_character_type = Character_NONE,
flatbuffers::Offset<void> main_character = 0,
const std::vector<uint8_t> *characters_type = nullptr, const std::vector<uint8_t> *characters_type = nullptr,
const std::vector<flatbuffers::Offset<void>> *characters = nullptr) { const std::vector<flatbuffers::Offset<void>> *characters = nullptr) {
return CreateMovie( return CreateMovie(
_fbb, _fbb,
main_character_type,
main_character,
characters_type ? _fbb.CreateVector<uint8_t>(*characters_type) : 0, characters_type ? _fbb.CreateVector<uint8_t>(*characters_type) : 0,
characters ? _fbb.CreateVector<flatbuffers::Offset<void>>(*characters) : 0); characters ? _fbb.CreateVector<flatbuffers::Offset<void>>(*characters) : 0);
} }
flatbuffers::Offset<Movie> CreateMovie(flatbuffers::FlatBufferBuilder &_fbb, const MovieT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
inline AttackerT *Attacker::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
auto _o = new AttackerT();
UnPackTo(_o, _resolver);
return _o;
}
inline void Attacker::UnPackTo(AttackerT *_o, const flatbuffers::resolver_function_t *_resolver) const {
(void)_o;
(void)_resolver;
{ auto _e = sword_attack_damage(); _o->sword_attack_damage = _e; };
}
inline flatbuffers::Offset<Attacker> Attacker::Pack(flatbuffers::FlatBufferBuilder &_fbb, const AttackerT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
return CreateAttacker(_fbb, _o, _rehasher);
}
inline flatbuffers::Offset<Attacker> CreateAttacker(flatbuffers::FlatBufferBuilder &_fbb, const AttackerT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
(void)_rehasher;
(void)_o;
auto _sword_attack_damage = _o->sword_attack_damage;
return CreateAttacker(
_fbb,
_sword_attack_damage);
}
inline MovieT *Movie::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
auto _o = new MovieT();
UnPackTo(_o, _resolver);
return _o;
}
inline void Movie::UnPackTo(MovieT *_o, const flatbuffers::resolver_function_t *_resolver) const {
(void)_o;
(void)_resolver;
{ auto _e = main_character_type(); _o->main_character.type = _e; };
{ auto _e = main_character(); if (_e) _o->main_character.value = CharacterUnion::UnPack(_e, main_character_type(), _resolver); };
{ auto _e = characters_type(); if (_e) { _o->characters.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->characters[_i].type = (Character)_e->Get(_i); } } };
{ auto _e = characters(); if (_e) { _o->characters.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->characters[_i].value = CharacterUnion::UnPack(_e->Get(_i), characters_type()->GetEnum<Character>(_i), _resolver); } } };
}
inline flatbuffers::Offset<Movie> Movie::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MovieT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
return CreateMovie(_fbb, _o, _rehasher);
}
inline flatbuffers::Offset<Movie> CreateMovie(flatbuffers::FlatBufferBuilder &_fbb, const MovieT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
(void)_rehasher;
(void)_o;
auto _main_character_type = _o->main_character.type;
auto _main_character = _o->main_character.Pack(_fbb);
auto _characters_type = _o->characters.size() ? _fbb.CreateVector<uint8_t>(_o->characters.size(), [&](size_t i) { return static_cast<uint8_t>(_o->characters[i].type); }) : 0;
auto _characters = _o->characters.size() ? _fbb.CreateVector<flatbuffers::Offset<void>>(_o->characters.size(), [&](size_t i) { return _o->characters[i].Pack(_fbb, _rehasher); }) : 0;
return CreateMovie(
_fbb,
_main_character_type,
_main_character,
_characters_type,
_characters);
}
inline bool VerifyCharacter(flatbuffers::Verifier &verifier, const void *obj, Character type) { inline bool VerifyCharacter(flatbuffers::Verifier &verifier, const void *obj, Character type) {
switch (type) { switch (type) {
case Character_NONE: { case Character_NONE: {
return true; return true;
} }
case Character_MuLan: { case Character_MuLan: {
auto ptr = reinterpret_cast<const MuLan *>(obj); auto ptr = reinterpret_cast<const Attacker *>(obj);
return verifier.VerifyTable(ptr); return verifier.VerifyTable(ptr);
} }
case Character_Rapunzel: { case Character_Rapunzel: {
auto ptr = reinterpret_cast<const Rapunzel *>(obj); return true;
return verifier.VerifyTable(ptr);
} }
case Character_Belle: { case Character_Belle: {
auto ptr = reinterpret_cast<const Belle *>(obj); return true;
return verifier.VerifyTable(ptr); }
case Character_BookFan: {
return true;
}
case Character_Other: {
auto ptr = reinterpret_cast<const flatbuffers::String *>(obj);
return verifier.Verify(ptr);
}
case Character_Unused: {
auto ptr = reinterpret_cast<const flatbuffers::String *>(obj);
return verifier.Verify(ptr);
} }
default: return false; default: return false;
} }
...@@ -273,10 +431,112 @@ inline bool VerifyCharacterVector(flatbuffers::Verifier &verifier, const flatbuf ...@@ -273,10 +431,112 @@ inline bool VerifyCharacterVector(flatbuffers::Verifier &verifier, const flatbuf
return true; return true;
} }
inline void *CharacterUnion::UnPack(const void *obj, Character type, const flatbuffers::resolver_function_t *resolver) {
switch (type) {
case Character_MuLan: {
auto ptr = reinterpret_cast<const Attacker *>(obj);
return ptr->UnPack(resolver);
}
case Character_Rapunzel: {
auto ptr = reinterpret_cast<const Rapunzel *>(obj);
return new Rapunzel(*ptr);
}
case Character_Belle: {
auto ptr = reinterpret_cast<const BookReader *>(obj);
return new BookReader(*ptr);
}
case Character_BookFan: {
auto ptr = reinterpret_cast<const BookReader *>(obj);
return new BookReader(*ptr);
}
case Character_Other: {
auto ptr = reinterpret_cast<const flatbuffers::String *>(obj);
return new std::string(ptr->c_str(), ptr->size());
}
case Character_Unused: {
auto ptr = reinterpret_cast<const flatbuffers::String *>(obj);
return new std::string(ptr->c_str(), ptr->size());
}
default: return nullptr;
}
}
inline flatbuffers::Offset<void> CharacterUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher) const {
switch (type) {
case Character_MuLan: {
auto ptr = reinterpret_cast<const AttackerT *>(value);
return CreateAttacker(_fbb, ptr, _rehasher).Union();
}
case Character_Rapunzel: {
auto ptr = reinterpret_cast<const Rapunzel *>(value);
return _fbb.CreateStruct(*ptr).Union();
}
case Character_Belle: {
auto ptr = reinterpret_cast<const BookReader *>(value);
return _fbb.CreateStruct(*ptr).Union();
}
case Character_BookFan: {
auto ptr = reinterpret_cast<const BookReader *>(value);
return _fbb.CreateStruct(*ptr).Union();
}
case Character_Other: {
auto ptr = reinterpret_cast<const std::string *>(value);
return _fbb.CreateString(*ptr).Union();
}
case Character_Unused: {
auto ptr = reinterpret_cast<const std::string *>(value);
return _fbb.CreateString(*ptr).Union();
}
default: return 0;
}
}
inline void CharacterUnion::Reset() {
switch (type) {
case Character_MuLan: {
auto ptr = reinterpret_cast<AttackerT *>(value);
delete ptr;
break;
}
case Character_Rapunzel: {
auto ptr = reinterpret_cast<Rapunzel *>(value);
delete ptr;
break;
}
case Character_Belle: {
auto ptr = reinterpret_cast<BookReader *>(value);
delete ptr;
break;
}
case Character_BookFan: {
auto ptr = reinterpret_cast<BookReader *>(value);
delete ptr;
break;
}
case Character_Other: {
auto ptr = reinterpret_cast<std::string *>(value);
delete ptr;
break;
}
case Character_Unused: {
auto ptr = reinterpret_cast<std::string *>(value);
delete ptr;
break;
}
default: break;
}
value = nullptr;
type = Character_NONE;
}
inline const Movie *GetMovie(const void *buf) { inline const Movie *GetMovie(const void *buf) {
return flatbuffers::GetRoot<Movie>(buf); return flatbuffers::GetRoot<Movie>(buf);
} }
inline Movie *GetMutableMovie(void *buf) {
return flatbuffers::GetMutableRoot<Movie>(buf);
}
inline const char *MovieIdentifier() { inline const char *MovieIdentifier() {
return "MOVI"; return "MOVI";
} }
...@@ -297,4 +557,10 @@ inline void FinishMovieBuffer( ...@@ -297,4 +557,10 @@ inline void FinishMovieBuffer(
fbb.Finish(root, MovieIdentifier()); fbb.Finish(root, MovieIdentifier());
} }
inline std::unique_ptr<MovieT> UnPackMovie(
const void *buf,
const flatbuffers::resolver_function_t *res = nullptr) {
return std::unique_ptr<MovieT>(GetMovie(buf)->UnPack(res));
}
#endif // FLATBUFFERS_GENERATED_UNIONVECTOR_H_ #endif // FLATBUFFERS_GENERATED_UNIONVECTOR_H_
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment