Commit 4f4495a6 authored by jsanmiya's avatar jsanmiya Committed by GitHub

Merge pull request #4148 from gbeili/vector_unions

C++ Union Vector
parents bbef92c1 68bbe983
......@@ -158,6 +158,10 @@ If you have a need to distinguish between different FlatBuffers in a more
open-ended way, for example for use as files, see the file identification
feature below.
There is an experimental support only in C++ for a vector of unions
(and types). In the example IDL file above, use [Any] to add a
vector of Any to Monster table.
### Namespaces
These will generate the corresponding namespace in C++ for all helper
......
......@@ -356,10 +356,25 @@ struct IDLOptions {
bool allow_non_utf8;
// Possible options for the more general generator below.
enum Language { kJava, kCSharp, kGo, kMAX };
enum Language {
kJava = 1 << 0,
kCSharp = 1 << 1,
kGo = 1 << 2,
kCpp = 1 << 3,
kJs = 1 << 4,
kPython = 1 << 5,
kPhp = 1 << 6,
kJson = 1 << 7,
kBinary = 1 << 8,
kMAX
};
Language lang;
// The corresponding language bit will be set if a language is included
// for code generation.
unsigned long lang_to_generate;
IDLOptions()
: strict_json(false),
skip_js_exports(false),
......@@ -378,7 +393,8 @@ struct IDLOptions {
cpp_object_api_pointer_type("std::unique_ptr"),
union_value_namespacing(true),
allow_non_utf8(false),
lang(IDLOptions::kJava) {}
lang(IDLOptions::kJava),
lang_to_generate(0) {}
};
// This encapsulates where the parser is in the current source file.
......
......@@ -99,6 +99,7 @@ struct EquipmentUnion {
};
bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *obj, Equipment type);
bool VerifyEquipmentVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
MANUALLY_ALIGNED_STRUCT(4) Vec3 FLATBUFFERS_FINAL_CLASS {
private:
......@@ -510,6 +511,17 @@ inline bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *obj, Eq
}
}
inline bool VerifyEquipmentVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types) {
if (values->size() != types->size()) return false;
for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {
if (!VerifyEquipment(
verifier, values->Get(i), types->GetEnum<Equipment>(i))) {
return false;
}
}
return true;
}
inline flatbuffers::NativeTable *EquipmentUnion::UnPack(const void *obj, Equipment type, const flatbuffers::resolver_function_t *resolver) {
switch (type) {
case Equipment_Weapon: {
......
......@@ -47,17 +47,17 @@ struct Generator {
const Generator generators[] = {
{ flatbuffers::GenerateBinary, "-b", "--binary", "binary",
nullptr,
flatbuffers::IDLOptions::kMAX,
flatbuffers::IDLOptions::kBinary,
"Generate wire format binaries for any data definitions",
flatbuffers::BinaryMakeRule },
{ flatbuffers::GenerateTextFile, "-t", "--json", "text",
nullptr,
flatbuffers::IDLOptions::kMAX,
flatbuffers::IDLOptions::kJson,
"Generate text output for any data definitions",
flatbuffers::TextMakeRule },
{ flatbuffers::GenerateCPP, "-c", "--cpp", "C++",
flatbuffers::GenerateCppGRPC,
flatbuffers::IDLOptions::kMAX,
flatbuffers::IDLOptions::kCpp,
"Generate C++ headers for tables/structs",
flatbuffers::CPPMakeRule },
{ flatbuffers::GenerateGo, "-g", "--go", "Go",
......@@ -72,7 +72,7 @@ const Generator generators[] = {
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateJS, "-s", "--js", "JavaScript",
nullptr,
flatbuffers::IDLOptions::kMAX,
flatbuffers::IDLOptions::kJs,
"Generate JavaScript code for tables/structs",
flatbuffers::JSMakeRule },
{ flatbuffers::GenerateGeneral, "-n", "--csharp", "C#",
......@@ -82,12 +82,12 @@ const Generator generators[] = {
flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePython, "-p", "--python", "Python",
nullptr,
flatbuffers::IDLOptions::kMAX,
flatbuffers::IDLOptions::kPython,
"Generate Python files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePhp, nullptr, "--php", "PHP",
nullptr,
flatbuffers::IDLOptions::kMAX,
flatbuffers::IDLOptions::kPhp,
"Generate PHP files for tables/structs",
flatbuffers::GeneralMakeRule },
};
......@@ -267,6 +267,7 @@ int main(int argc, const char *argv[]) {
arg == generators[i].generator_opt_short)) {
generator_enabled[i] = true;
any_generator = true;
opts.lang_to_generate |= generators[i].lang;
goto found;
}
}
......
......@@ -454,6 +454,13 @@ class CppGenerator : public BaseGenerator {
enum_def.name + " type)";
}
static std::string UnionVectorVerifySignature(const EnumDef &enum_def) {
return "bool Verify" + enum_def.name + "Vector" +
"(flatbuffers::Verifier &verifier, " +
"const flatbuffers::Vector<flatbuffers::Offset<void>> *values, " +
"const flatbuffers::Vector<uint8_t> *types)";
}
static std::string UnionUnPackSignature(const EnumDef &enum_def,
bool inclass) {
return (inclass ? "static " : "") +
......@@ -685,6 +692,7 @@ class CppGenerator : public BaseGenerator {
if (enum_def.is_union) {
code_ += UnionVerifySignature(enum_def) + ";";
code_ += UnionVectorVerifySignature(enum_def) + ";";
code_ += "";
}
}
......@@ -721,6 +729,18 @@ class CppGenerator : public BaseGenerator {
code_ += "}";
code_ += "";
code_ += "inline " + UnionVectorVerifySignature(enum_def) + " {";
code_ += " if (values->size() != types->size()) return false;";
code_ += " for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {";
code_ += " if (!Verify" + enum_def.name + "(";
code_ += " verifier, values->Get(i), types->GetEnum<" + enum_def.name + ">(i))) { ";
code_ += " return false; ";
code_ += " }";
code_ += " }";
code_ += " return true;";
code_ += "}";
code_ += "";
if (parser_.opts.generate_object_based_api) {
// Generate union Unpack() and Pack() functions.
code_ += "inline " + UnionUnPackSignature(enum_def, false) + " {";
......@@ -995,6 +1015,10 @@ class CppGenerator : public BaseGenerator {
}
break;
}
case BASE_TYPE_UNION: {
code_ += "{{PRE}}Verify{{ENUM_NAME}}Vector(verifier, {{NAME}}(), {{NAME}}_type())\\";
break;
}
default:
break;
}
......
......@@ -70,108 +70,80 @@ struct LanguageParameters {
CommentConfig comment_config;
};
LanguageParameters language_parameters[] = {
{
IDLOptions::kJava,
false,
".java",
"String",
"boolean ",
" {\n",
"class ",
" final ",
"final ",
"final class ",
";\n",
"()",
"",
" extends ",
"package ",
";",
"",
"_bb.order(ByteOrder.LITTLE_ENDIAN); ",
"position()",
"offset()",
"",
"",
"",
"import java.nio.*;\nimport java.lang.*;\nimport java.util.*;\n"
"import com.google.flatbuffers.*;\n\n@SuppressWarnings(\"unused\")\n",
const LanguageParameters& GetLangParams(IDLOptions::Language lang) {
static LanguageParameters language_parameters[] = {
{
"/**",
" *",
" */",
IDLOptions::kJava,
false,
".java",
"String",
"boolean ",
" {\n",
"class ",
" final ",
"final ",
"final class ",
";\n",
"()",
"",
" extends ",
"package ",
";",
"",
"_bb.order(ByteOrder.LITTLE_ENDIAN); ",
"position()",
"offset()",
"",
"",
"",
"import java.nio.*;\nimport java.lang.*;\nimport java.util.*;\n"
"import com.google.flatbuffers.*;\n\n@SuppressWarnings(\"unused\")\n",
{
"/**",
" *",
" */",
},
},
},
{
IDLOptions::kCSharp,
true,
".cs",
"string",
"bool ",
"\n{\n",
"struct ",
" readonly ",
"",
"enum ",
",\n",
" { get",
"} ",
" : ",
"namespace ",
"\n{",
"\n}\n",
"",
"Position",
"Offset",
"__p.",
"Table.",
"?",
"using System;\nusing FlatBuffers;\n\n",
{
nullptr,
"///",
nullptr,
IDLOptions::kCSharp,
true,
".cs",
"string",
"bool ",
"\n{\n",
"struct ",
" readonly ",
"",
"enum ",
",\n",
" { get",
"} ",
" : ",
"namespace ",
"\n{",
"\n}\n",
"",
"Position",
"Offset",
"__p.",
"Table.",
"?",
"using System;\nusing FlatBuffers;\n\n",
{
nullptr,
"///",
nullptr,
},
},
},
// TODO: add Go support to the general generator.
// WARNING: this is currently only used for generating make rules for Go.
{
IDLOptions::kGo,
true,
".go",
"string",
"bool ",
"\n{\n",
"class ",
"const ",
" ",
"class ",
";\n",
"()",
"",
"",
"package ",
"",
"",
"",
"position()",
"offset()",
"",
"",
"",
"import (\n\tflatbuffers \"github.com/google/flatbuffers/go\"\n)",
{
nullptr,
"///",
nullptr,
},
}
};
};
static_assert(sizeof(language_parameters) / sizeof(LanguageParameters) ==
IDLOptions::kMAX,
"Please add extra elements to the arrays above.");
if (lang == IDLOptions::kJava) {
return language_parameters[0];
} else {
assert(lang == IDLOptions::kCSharp);
return language_parameters[1];
}
}
namespace general {
class GeneralGenerator : public BaseGenerator {
......@@ -179,10 +151,10 @@ class GeneralGenerator : public BaseGenerator {
GeneralGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
: BaseGenerator(parser, path, file_name, "", "."),
lang_(language_parameters[parser_.opts.lang]),
lang_(GetLangParams(parser_.opts.lang)),
cur_name_space_( nullptr ) {
assert(parser_.opts.lang <= IDLOptions::kMAX);
};
}
GeneralGenerator &operator=(const GeneralGenerator &);
bool generate() {
std::string one_file_code;
......@@ -258,9 +230,16 @@ static bool IsEnum(const Type& type) {
}
std::string GenTypeBasic(const Type &type, bool enableLangOverrides) {
static const char *gtypename[] = {
static const char *java_typename[] = {
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
#JTYPE, #NTYPE, #GTYPE,
#JTYPE,
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
};
static const char *csharp_typename[] = {
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
#NTYPE,
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
};
......@@ -274,7 +253,12 @@ std::string GenTypeBasic(const Type &type, bool enableLangOverrides) {
}
}
return gtypename[type.base_type * IDLOptions::kMAX + lang_.language];
if (lang_.language == IDLOptions::kJava) {
return java_typename[type.base_type];
} else {
assert(lang_.language == IDLOptions::kCSharp);
return csharp_typename[type.base_type];
}
}
std::string GenTypeBasic(const Type &type) {
......@@ -1352,7 +1336,7 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
code += (lang_.language != IDLOptions::kJava) ? ";" : "";
code += "\n\n";
}
const LanguageParameters & lang_;
const LanguageParameters& lang_;
// This tracks the current namespace used to determine if a type need to be prefixed by its namespace
const Namespace *cur_name_space_;
};
......@@ -1367,7 +1351,7 @@ bool GenerateGeneral(const Parser &parser, const std::string &path,
std::string GeneralMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
assert(parser.opts.lang <= IDLOptions::kMAX);
auto lang = language_parameters[parser.opts.lang];
const auto &lang = GetLangParams(parser.opts.lang);
std::string make_rule;
......
......@@ -554,12 +554,6 @@ CheckedError Parser::ParseType(Type &type) {
return Error(
"nested vector types not supported (wrap in table first).");
}
if (subtype.base_type == BASE_TYPE_UNION) {
// We could support this if we stored a struct of 2 elements per
// union element.
return Error(
"vector of union types not supported (wrap in table first).");
}
type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def);
type.element = subtype.base_type;
EXPECT(']');
......@@ -611,6 +605,19 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
// with a special suffix.
ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(),
type.enum_def->underlying_type, &typefield));
} else if (type.base_type == BASE_TYPE_VECTOR &&
type.element == BASE_TYPE_UNION) {
// Only cpp supports the union vector feature so far.
if (opts.lang_to_generate != IDLOptions::kCpp) {
return Error("Vectors of unions are not yet supported in all "
"the specified programming languages.");
}
// For vector of union fields, add a second auto-generated vector field to
// hold the types, with a special suffix.
Type union_vector(BASE_TYPE_VECTOR, nullptr, type.enum_def);
union_vector.element = BASE_TYPE_UTYPE;
ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(),
union_vector, &typefield));
}
FieldDef *field;
......
......@@ -16,7 +16,7 @@
../flatc --cpp --java --csharp --go --binary --python --js --php --grpc --gen-mutable --gen-object-api --no-includes monster_test.fbs monsterdata_test.json
../flatc --cpp --java --csharp --go --binary --python --js --php --gen-mutable -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs
../flatc --binary --schema monster_test.fbs
../flatc --cpp -o union_vector ./union_vector/union_vector.fbs
cd ../samples
../flatc --cpp --gen-mutable --gen-object-api monster.fbs
cd ../reflection
......
......@@ -136,6 +136,7 @@ struct AnyUnion {
};
bool VerifyAny(flatbuffers::Verifier &verifier, const void *obj, Any type);
bool VerifyAnyVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
MANUALLY_ALIGNED_STRUCT(2) Test FLATBUFFERS_FINAL_CLASS {
private:
......@@ -1198,6 +1199,17 @@ inline bool VerifyAny(flatbuffers::Verifier &verifier, const void *obj, Any type
}
}
inline bool VerifyAnyVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types) {
if (values->size() != types->size()) return false;
for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {
if (!VerifyAny(
verifier, values->Get(i), types->GetEnum<Any>(i))) {
return false;
}
}
return true;
}
inline flatbuffers::NativeTable *AnyUnion::UnPack(const void *obj, Any type, const flatbuffers::resolver_function_t *resolver) {
switch (type) {
case Any_Monster: {
......
......@@ -21,6 +21,7 @@
#include "monster_test_generated.h"
#include "namespace_test/namespace_test1_generated.h"
#include "namespace_test/namespace_test2_generated.h"
#include "union_vector/union_vector_generated.h"
#ifndef FLATBUFFERS_CPP98_STL
#include <random>
......@@ -954,7 +955,6 @@ void ErrorTest() {
TestError("@", "illegal");
TestError("table 1", "expecting");
TestError("table X { Y:[[int]]; }", "nested vector");
TestError("union Z { X } table X { Y:[Z]; }", "vector of union");
TestError("table X { Y:1; }", "illegal type");
TestError("table X { Y:int; Y:int; }", "field already");
TestError("struct X { Y:string; }", "only scalar");
......@@ -1276,6 +1276,67 @@ void ParseUnionTest() {
"{ e_type: N_A, e: {} }"), true);
}
void UnionVectorTest() {
// load FlatBuffer fbs schema.
// TODO: load a JSON file with such a vector when JSON support is ready.
std::string schemafile;
TEST_EQ(flatbuffers::LoadFile(
"tests/union_vector/union_vector.fbs", false, &schemafile), true);
// parse schema.
flatbuffers::IDLOptions idl_opts;
idl_opts.lang_to_generate |= flatbuffers::IDLOptions::kCpp;
flatbuffers::Parser parser(idl_opts);
const char *include_directories[] = { "tests/union_vector", nullptr };
TEST_EQ(parser.Parse(schemafile.c_str(), include_directories), true);
flatbuffers::FlatBufferBuilder fbb;
// union types.
std::vector<uint8_t> types;
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));
// union values.
std::vector<flatbuffers::Offset<void>> characters;
characters.push_back(CreateBelle(fbb, /*books_read=*/7).Union());
characters.push_back(CreateRapunzel(fbb, /*hair_length=*/6).Union());
characters.push_back(CreateMuLan(fbb, /*sward_attack_damage=*/5).Union());
// create Movie.
const auto movie_offset =
CreateMovie(fbb, fbb.CreateVector(types), fbb.CreateVector(characters));
FinishMovieBuffer(fbb, movie_offset);
uint8_t *buf = fbb.GetBufferPointer();
flatbuffers::Verifier verifier(buf, fbb.GetSize());
TEST_EQ(VerifyMovieBuffer(verifier), true);
const Movie *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);
const Belle *belle =
reinterpret_cast<const Belle*>(movie->characters()->Get(0));
TEST_EQ(belle->books_read(), 7);
const Rapunzel *rapunzel =
reinterpret_cast<const Rapunzel*>(movie->characters()->Get(1));
TEST_EQ(rapunzel->hair_length(), 6);
const MuLan *mu_lan =
reinterpret_cast<const MuLan*>(movie->characters()->Get(2));
TEST_EQ(mu_lan->sword_attack_damage(), 5);
}
void ConformTest() {
flatbuffers::Parser parser;
TEST_EQ(parser.Parse("table T { A:int; } enum E:byte { A }"), true);
......@@ -1330,6 +1391,7 @@ int main(int /*argc*/, const char * /*argv*/[]) {
InvalidUTF8Test();
UnknownFieldsTest();
ParseUnionTest();
UnionVectorTest();
ConformTest();
if (!testing_fails) {
......
table MuLan {
sword_attack_damage: int;
}
table Rapunzel {
hair_length: int;
}
table Belle {
books_read: int;
}
union Character {
MuLan,
Rapunzel,
Belle,
}
table Movie {
characters: [Character];
}
root_type Movie;
file_identifier "MOVI";
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_UNIONVECTOR_H_
#define FLATBUFFERS_GENERATED_UNIONVECTOR_H_
#include "flatbuffers/flatbuffers.h"
struct MuLan;
struct Rapunzel;
struct Belle;
struct Movie;
enum Character {
Character_NONE = 0,
Character_MuLan = 1,
Character_Rapunzel = 2,
Character_Belle = 3,
Character_MIN = Character_NONE,
Character_MAX = Character_Belle
};
inline const char **EnumNamesCharacter() {
static const char *names[] = {
"NONE",
"MuLan",
"Rapunzel",
"Belle",
nullptr
};
return names;
}
inline const char *EnumNameCharacter(Character e) {
const size_t index = static_cast<int>(e);
return EnumNamesCharacter()[index];
}
template<typename T> struct CharacterTraits {
static const Character enum_value = Character_NONE;
};
template<> struct CharacterTraits<MuLan> {
static const Character enum_value = Character_MuLan;
};
template<> struct CharacterTraits<Rapunzel> {
static const Character enum_value = Character_Rapunzel;
};
template<> struct CharacterTraits<Belle> {
static const Character enum_value = Character_Belle;
};
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);
struct MuLan FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
enum {
VT_SWORD_ATTACK_DAMAGE = 4
};
int32_t sword_attack_damage() const {
return GetField<int32_t>(VT_SWORD_ATTACK_DAMAGE, 0);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<int32_t>(verifier, VT_SWORD_ATTACK_DAMAGE) &&
verifier.EndTable();
}
};
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)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
MuLanBuilder &operator=(const MuLanBuilder &);
flatbuffers::Offset<MuLan> Finish() {
const auto end = fbb_.EndTable(start_, 1);
auto o = flatbuffers::Offset<MuLan>(end);
return o;
}
};
inline flatbuffers::Offset<MuLan> CreateMuLan(
flatbuffers::FlatBufferBuilder &_fbb,
int32_t sword_attack_damage = 0) {
MuLanBuilder builder_(_fbb);
builder_.add_sword_attack_damage(sword_attack_damage);
return builder_.Finish();
}
struct Rapunzel FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
enum {
VT_HAIR_LENGTH = 4
};
int32_t hair_length() const {
return GetField<int32_t>(VT_HAIR_LENGTH, 0);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<int32_t>(verifier, VT_HAIR_LENGTH) &&
verifier.EndTable();
}
};
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)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
RapunzelBuilder &operator=(const RapunzelBuilder &);
flatbuffers::Offset<Rapunzel> Finish() {
const auto end = fbb_.EndTable(start_, 1);
auto o = flatbuffers::Offset<Rapunzel>(end);
return o;
}
};
inline flatbuffers::Offset<Rapunzel> CreateRapunzel(
flatbuffers::FlatBufferBuilder &_fbb,
int32_t hair_length = 0) {
RapunzelBuilder builder_(_fbb);
builder_.add_hair_length(hair_length);
return builder_.Finish();
}
struct Belle FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
enum {
VT_BOOKS_READ = 4
};
int32_t books_read() const {
return GetField<int32_t>(VT_BOOKS_READ, 0);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<int32_t>(verifier, VT_BOOKS_READ) &&
verifier.EndTable();
}
};
struct BelleBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_books_read(int32_t books_read) {
fbb_.AddElement<int32_t>(Belle::VT_BOOKS_READ, books_read, 0);
}
BelleBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
BelleBuilder &operator=(const BelleBuilder &);
flatbuffers::Offset<Belle> Finish() {
const auto end = fbb_.EndTable(start_, 1);
auto o = flatbuffers::Offset<Belle>(end);
return o;
}
};
inline flatbuffers::Offset<Belle> CreateBelle(
flatbuffers::FlatBufferBuilder &_fbb,
int32_t books_read = 0) {
BelleBuilder builder_(_fbb);
builder_.add_books_read(books_read);
return builder_.Finish();
}
struct Movie FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
enum {
VT_CHARACTERS_TYPE = 4,
VT_CHARACTERS = 6
};
const flatbuffers::Vector<uint8_t> *characters_type() const {
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_CHARACTERS_TYPE);
}
const flatbuffers::Vector<flatbuffers::Offset<void>> *characters() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<void>> *>(VT_CHARACTERS);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_CHARACTERS_TYPE) &&
verifier.Verify(characters_type()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_CHARACTERS) &&
verifier.Verify(characters()) &&
VerifyCharacterVector(verifier, characters(), characters_type()) &&
verifier.EndTable();
}
};
struct MovieBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_characters_type(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> characters_type) {
fbb_.AddOffset(Movie::VT_CHARACTERS_TYPE, characters_type);
}
void add_characters(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<void>>> characters) {
fbb_.AddOffset(Movie::VT_CHARACTERS, characters);
}
MovieBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
MovieBuilder &operator=(const MovieBuilder &);
flatbuffers::Offset<Movie> Finish() {
const auto end = fbb_.EndTable(start_, 2);
auto o = flatbuffers::Offset<Movie>(end);
return o;
}
};
inline flatbuffers::Offset<Movie> CreateMovie(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> characters_type = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<void>>> characters = 0) {
MovieBuilder builder_(_fbb);
builder_.add_characters(characters);
builder_.add_characters_type(characters_type);
return builder_.Finish();
}
inline flatbuffers::Offset<Movie> CreateMovieDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const std::vector<uint8_t> *characters_type = nullptr,
const std::vector<flatbuffers::Offset<void>> *characters = nullptr) {
return CreateMovie(
_fbb,
characters_type ? _fbb.CreateVector<uint8_t>(*characters_type) : 0,
characters ? _fbb.CreateVector<flatbuffers::Offset<void>>(*characters) : 0);
}
inline bool VerifyCharacter(flatbuffers::Verifier &verifier, const void *obj, Character type) {
switch (type) {
case Character_NONE: {
return true;
}
case Character_MuLan: {
auto ptr = reinterpret_cast<const MuLan *>(obj);
return verifier.VerifyTable(ptr);
}
case Character_Rapunzel: {
auto ptr = reinterpret_cast<const Rapunzel *>(obj);
return verifier.VerifyTable(ptr);
}
case Character_Belle: {
auto ptr = reinterpret_cast<const Belle *>(obj);
return verifier.VerifyTable(ptr);
}
default: return false;
}
}
inline bool VerifyCharacterVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types) {
if (values->size() != types->size()) return false;
for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {
if (!VerifyCharacter(
verifier, values->Get(i), types->GetEnum<Character>(i))) {
return false;
}
}
return true;
}
inline const Movie *GetMovie(const void *buf) {
return flatbuffers::GetRoot<Movie>(buf);
}
inline const char *MovieIdentifier() {
return "MOVI";
}
inline bool MovieBufferHasIdentifier(const void *buf) {
return flatbuffers::BufferHasIdentifier(
buf, MovieIdentifier());
}
inline bool VerifyMovieBuffer(
flatbuffers::Verifier &verifier) {
return verifier.VerifyBuffer<Movie>(MovieIdentifier());
}
inline void FinishMovieBuffer(
flatbuffers::FlatBufferBuilder &fbb,
flatbuffers::Offset<Movie> root) {
fbb.Finish(root, MovieIdentifier());
}
#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