Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
F
flatbuffers
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
flatbuffers
Commits
4f4495a6
Commit
4f4495a6
authored
Jan 24, 2017
by
jsanmiya
Committed by
GitHub
Jan 24, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #4148 from gbeili/vector_unions
C++ Union Vector
parents
bbef92c1
68bbe983
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
567 additions
and
121 deletions
+567
-121
Schemas.md
docs/source/Schemas.md
+4
-0
idl.h
include/flatbuffers/idl.h
+18
-2
monster_generated.h
samples/monster_generated.h
+12
-0
flatc.cpp
src/flatc.cpp
+7
-6
idl_gen_cpp.cpp
src/idl_gen_cpp.cpp
+24
-0
idl_gen_general.cpp
src/idl_gen_general.cpp
+89
-105
idl_parser.cpp
src/idl_parser.cpp
+13
-6
generate_code.sh
tests/generate_code.sh
+1
-1
monster_test_generated.h
tests/monster_test_generated.h
+12
-0
test.cpp
tests/test.cpp
+63
-1
union_vector.fbs
tests/union_vector/union_vector.fbs
+24
-0
union_vector_generated.h
tests/union_vector/union_vector_generated.h
+300
-0
No files found.
docs/source/Schemas.md
View file @
4f4495a6
...
...
@@ -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
...
...
include/flatbuffers/idl.h
View file @
4f4495a6
...
...
@@ -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.
...
...
samples/monster_generated.h
View file @
4f4495a6
...
...
@@ -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
:
{
...
...
src/flatc.cpp
View file @
4f4495a6
...
...
@@ -47,17 +47,17 @@ struct Generator {
const
Generator
generators
[]
=
{
{
flatbuffers
::
GenerateBinary
,
"-b"
,
"--binary"
,
"binary"
,
nullptr
,
flatbuffers
::
IDLOptions
::
k
MAX
,
flatbuffers
::
IDLOptions
::
k
Binary
,
"Generate wire format binaries for any data definitions"
,
flatbuffers
::
BinaryMakeRule
},
{
flatbuffers
::
GenerateTextFile
,
"-t"
,
"--json"
,
"text"
,
nullptr
,
flatbuffers
::
IDLOptions
::
k
MAX
,
flatbuffers
::
IDLOptions
::
k
Json
,
"Generate text output for any data definitions"
,
flatbuffers
::
TextMakeRule
},
{
flatbuffers
::
GenerateCPP
,
"-c"
,
"--cpp"
,
"C++"
,
flatbuffers
::
GenerateCppGRPC
,
flatbuffers
::
IDLOptions
::
k
MAX
,
flatbuffers
::
IDLOptions
::
k
Cpp
,
"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
::
k
MAX
,
flatbuffers
::
IDLOptions
::
k
Js
,
"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
::
k
MAX
,
flatbuffers
::
IDLOptions
::
k
Python
,
"Generate Python files for tables/structs"
,
flatbuffers
::
GeneralMakeRule
},
{
flatbuffers
::
GeneratePhp
,
nullptr
,
"--php"
,
"PHP"
,
nullptr
,
flatbuffers
::
IDLOptions
::
k
MAX
,
flatbuffers
::
IDLOptions
::
k
Php
,
"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
;
}
}
...
...
src/idl_gen_cpp.cpp
View file @
4f4495a6
...
...
@@ -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
;
}
...
...
src/idl_gen_general.cpp
View file @
4f4495a6
...
...
@@ -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.*;
\n
import java.lang.*;
\n
import 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.*;
\n
import java.lang.*;
\n
import 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;
\n
using 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;
\n
using 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\t
flatbuffers
\"
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
*
g
typename
[]
=
{
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
;
...
...
src/idl_parser.cpp
View file @
4f4495a6
...
...
@@ -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
;
...
...
tests/generate_code.sh
View file @
4f4495a6
...
...
@@ -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
...
...
tests/monster_test_generated.h
View file @
4f4495a6
...
...
@@ -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
:
{
...
...
tests/test.cpp
View file @
4f4495a6
...
...
@@ -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
)
{
...
...
tests/union_vector/union_vector.fbs
0 → 100644
View file @
4f4495a6
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";
tests/union_vector/union_vector_generated.h
0 → 100644
View file @
4f4495a6
// 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_
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment