mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-02 04:04:19 +00:00
Compare commits
110 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
25a15950f5 | ||
|
|
6f94fb51b1 | ||
|
|
57f3752d5e | ||
|
|
f52f848b95 | ||
|
|
3c3742a54a | ||
|
|
f325cce6fd | ||
|
|
88a85ffbbd | ||
|
|
35cbd23f63 | ||
|
|
210a1ab969 | ||
|
|
90c8ded449 | ||
|
|
8f864aad7b | ||
|
|
dddd0865cb | ||
|
|
0a81eb6463 | ||
|
|
b1740688bf | ||
|
|
86b505e412 | ||
|
|
da67c0a71f | ||
|
|
dadd1a926e | ||
|
|
01c50d57a6 | ||
|
|
e9f1f4d9b7 | ||
|
|
dd05f3249a | ||
|
|
43611fcc0b | ||
|
|
642254bee6 | ||
|
|
22743ca45a | ||
|
|
fb87c0d3c6 | ||
|
|
398ae0cb6b | ||
|
|
aaf5598a03 | ||
|
|
3d2cf554d7 | ||
|
|
55dec4d2f8 | ||
|
|
0f5f7faa9f | ||
|
|
90daabd5b1 | ||
|
|
262e1d7bf9 | ||
|
|
c559eb451e | ||
|
|
6a7ec85e83 | ||
|
|
81ecc98e02 | ||
|
|
9aeeddf5ac | ||
|
|
c7bfe06c54 | ||
|
|
349a391208 | ||
|
|
9d01bfaea3 | ||
|
|
cfbab31fb1 | ||
|
|
cb2481efdc | ||
|
|
d7ac3788e8 | ||
|
|
a0a313b101 | ||
|
|
93c0960c3a | ||
|
|
04d734d6d2 | ||
|
|
8468ea1ab4 | ||
|
|
0920d663d5 | ||
|
|
bbb72f0b73 | ||
|
|
8f8a27d6e5 | ||
|
|
86777bd66b | ||
|
|
8b92122f33 | ||
|
|
e93a5652d0 | ||
|
|
0c80b3a7cc | ||
|
|
f52ddfbd68 | ||
|
|
808b44f87a | ||
|
|
340d1a3447 | ||
|
|
ba20d9bff3 | ||
|
|
370693a200 | ||
|
|
33932ceea4 | ||
|
|
fb03f78fb4 | ||
|
|
523f3833eb | ||
|
|
46497e4f9a | ||
|
|
b627b7c6c6 | ||
|
|
e093f72d00 | ||
|
|
728bb64fed | ||
|
|
a07f0d428d | ||
|
|
b90d4e049d | ||
|
|
b0752e179b | ||
|
|
1fc12e0e5b | ||
|
|
e6fa7b1133 | ||
|
|
28e7dbd3d3 | ||
|
|
adc50051e0 | ||
|
|
2aec880347 | ||
|
|
238a8ebb15 | ||
|
|
86992476da | ||
|
|
751aeabc80 | ||
|
|
b4bb1b103f | ||
|
|
cffd187fc7 | ||
|
|
ccfa317486 | ||
|
|
a5cc2092a6 | ||
|
|
89041a1686 | ||
|
|
7a36419f24 | ||
|
|
281284fa5d | ||
|
|
1a27c7017a | ||
|
|
b8f5f84437 | ||
|
|
f2071e4f80 | ||
|
|
9c25ecdcd1 | ||
|
|
1beed12e59 | ||
|
|
4cd71d67f1 | ||
|
|
d9bc5ec047 | ||
|
|
c04c143cf0 | ||
|
|
c6aae45364 | ||
|
|
7f2a1c90d5 | ||
|
|
f5387387de | ||
|
|
e7e4dc755d | ||
|
|
b8224809ad | ||
|
|
bb22fb5756 | ||
|
|
ff274771ba | ||
|
|
15bf626191 | ||
|
|
ac106e835c | ||
|
|
640b525e83 | ||
|
|
0b379211dc | ||
|
|
bb223da258 | ||
|
|
17c5f89d4f | ||
|
|
695d26183a | ||
|
|
f5120a2aaf | ||
|
|
037314a059 | ||
|
|
ebcfbbadf0 | ||
|
|
6561c7a31f | ||
|
|
a6d98fb067 | ||
|
|
3a2d3a232f |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -48,6 +48,7 @@ tests/monsterdata_java_wire.mon
|
||||
tests/monsterdata_go_wire.mon
|
||||
tests/monsterdata_javascript_wire.mon
|
||||
tests/unicode_test.mon
|
||||
tests/ts/
|
||||
CMakeLists.txt.user
|
||||
CMakeScripts/**
|
||||
CTestTestfile.cmake
|
||||
@@ -66,3 +67,8 @@ build/VS2010/FlatBuffers.opensdf
|
||||
build/VS2010/ipch/**/*.ipch
|
||||
*.so
|
||||
Testing/Temporary
|
||||
.cproject
|
||||
.settings/
|
||||
.project
|
||||
net/**/obj
|
||||
node_modules/
|
||||
|
||||
@@ -24,6 +24,7 @@ endif()
|
||||
|
||||
set(FlatBuffers_Library_SRCS
|
||||
include/flatbuffers/code_generators.h
|
||||
include/flatbuffers/base.h
|
||||
include/flatbuffers/flatbuffers.h
|
||||
include/flatbuffers/hash.h
|
||||
include/flatbuffers/idl.h
|
||||
@@ -31,6 +32,7 @@ set(FlatBuffers_Library_SRCS
|
||||
include/flatbuffers/reflection.h
|
||||
include/flatbuffers/reflection_generated.h
|
||||
include/flatbuffers/flexbuffers.h
|
||||
include/flatbuffers/registry.h
|
||||
src/code_generators.cpp
|
||||
src/idl_parser.cpp
|
||||
src/idl_gen_text.cpp
|
||||
@@ -102,7 +104,7 @@ if(EXISTS "${CMAKE_TOOLCHAIN_FILE}")
|
||||
# is being configured externally
|
||||
elseif(APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
|
||||
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
if(CYGWIN)
|
||||
set(CMAKE_CXX_FLAGS
|
||||
@@ -126,9 +128,14 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
|
||||
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -std=c++0x -stdlib=libc++ -Wall -pedantic -Werror \
|
||||
-Wextra")
|
||||
if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD")
|
||||
"${CMAKE_CXX_FLAGS} -std=c++0x -Wall -pedantic -Werror \
|
||||
-Wextra -Wno-unused-parameter")
|
||||
if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||
endif()
|
||||
if(NOT ("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD" OR
|
||||
"${CMAKE_SYSTEM_NAME}" MATCHES "Linux"))
|
||||
set(CMAKE_EXE_LINKER_FLAGS
|
||||
"${CMAKE_EXE_LINKER_FLAGS} -lc++abi")
|
||||
endif()
|
||||
@@ -138,6 +145,11 @@ elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -fsigned-char")
|
||||
|
||||
elseif(MSVC)
|
||||
# Visual Studio pedantic build settings
|
||||
# warning C4512: assignment operator could not be generated
|
||||
# warning C4316: object allocated on the heap may not be aligned
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /WX /wd4512 /wd4316")
|
||||
endif()
|
||||
|
||||
if(FLATBUFFERS_CODE_COVERAGE)
|
||||
@@ -163,6 +175,10 @@ if(FLATBUFFERS_BUILD_FLATC)
|
||||
if(NOT FLATBUFFERS_FLATC_EXECUTABLE)
|
||||
set(FLATBUFFERS_FLATC_EXECUTABLE $<TARGET_FILE:flatc>)
|
||||
endif()
|
||||
if(MSVC)
|
||||
# Make flatc.exe not depend on runtime dlls for easy distribution.
|
||||
target_compile_options(flatc PUBLIC $<$<CONFIG:Release>:/MT>)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(FLATBUFFERS_BUILD_FLATHASH)
|
||||
@@ -181,6 +197,7 @@ function(compile_flatbuffers_schema_to_cpp SRC_FBS)
|
||||
OUTPUT ${GEN_HEADER}
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable
|
||||
--gen-object-api -o "${SRC_FBS_DIR}"
|
||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
DEPENDS flatc)
|
||||
endfunction()
|
||||
@@ -211,10 +228,10 @@ endif()
|
||||
|
||||
if(FLATBUFFERS_BUILD_GRPCTEST)
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter -Wno-shadow")
|
||||
endif()
|
||||
add_executable(grpctest ${FlatBuffers_GRPCTest_SRCS})
|
||||
target_link_libraries(grpctest grpc++_unsecure grpc pthread dl)
|
||||
target_link_libraries(grpctest grpc++_unsecure pthread dl)
|
||||
endif()
|
||||
|
||||
if(FLATBUFFERS_INSTALL)
|
||||
|
||||
11
appveyor.yml
11
appveyor.yml
@@ -4,6 +4,11 @@ branches:
|
||||
|
||||
os: Visual Studio 2015
|
||||
|
||||
environment:
|
||||
matrix:
|
||||
- CMAKE_VS_VERSION: "10 2010"
|
||||
- CMAKE_VS_VERSION: "14 2015"
|
||||
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
@@ -13,7 +18,7 @@ configuration:
|
||||
- Release
|
||||
|
||||
before_build:
|
||||
- cmake -G"Visual Studio 10 2010"
|
||||
- cmake -G"Visual Studio %CMAKE_VS_VERSION%"
|
||||
# This cuts down on a lot of noise generated by xamarin warnings.
|
||||
- del "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
||||
|
||||
@@ -30,8 +35,8 @@ test_script:
|
||||
- "JavaTest.bat"
|
||||
- rem "---------------- JS -----------------"
|
||||
- "node --version"
|
||||
- "..\\%CONFIGURATION%\\flatc -b monster_test.fbs unicode_test.json"
|
||||
- "node JavaScriptTest"
|
||||
- "..\\%CONFIGURATION%\\flatc -b -I include_test monster_test.fbs unicode_test.json"
|
||||
- "node JavaScriptTest ./monster_test_generated"
|
||||
- rem "---------------- C# -----------------"
|
||||
# Have to compile this here rather than in "build" above because AppVeyor only
|
||||
# supports building one project??
|
||||
|
||||
@@ -1 +1 @@
|
||||
../../CONTRIBUTING
|
||||
../../CONTRIBUTING.md
|
||||
@@ -29,7 +29,7 @@ For any schema input files, one or more generators can be specified:
|
||||
|
||||
- `--python`, `-p`: Generate Python code.
|
||||
|
||||
- `--javascript`, `-s`: Generate JavaScript code.
|
||||
- `--js`, `-s`: Generate JavaScript code.
|
||||
|
||||
- `--php`: Generate PHP code.
|
||||
|
||||
@@ -123,5 +123,7 @@ Additional options:
|
||||
- `--include-prefix PATH` : Prefix this path to any generated include
|
||||
statements.
|
||||
|
||||
- `--keep-prefix` : Keep original prefix of schema include statement.
|
||||
|
||||
NOTE: short-form options for generators are deprecated, use the long form
|
||||
whenever possible.
|
||||
|
||||
@@ -200,6 +200,15 @@ pointer type (`my_ptr<T>`), or by specifying `naked` as the type to get `T *`
|
||||
pointers. Unlike the smart pointers, naked pointers do not manage memory for
|
||||
you, so you'll have to manage their lifecycles manually.
|
||||
|
||||
|
||||
# Using different string type.
|
||||
|
||||
By default the object tree is built out of `std::string`, but you can
|
||||
influence this either globally (using the `--cpp-str-type` argument to
|
||||
`flatc`) or per field using the `cpp_str_type` attribute.
|
||||
|
||||
The type must support T::c_str() and T::length() as member functions.
|
||||
|
||||
## Reflection (& Resizing)
|
||||
|
||||
There is experimental support for reflection in FlatBuffers, allowing you to
|
||||
@@ -402,4 +411,22 @@ manually wrap it in synchronisation primites. There's no automatic way to
|
||||
accomplish this, by design, as we feel multithreaded construction
|
||||
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>
|
||||
|
||||
@@ -125,7 +125,17 @@ map["unknown"].IsNull(); // true
|
||||
# Binary encoding
|
||||
|
||||
A description of how FlexBuffers are encoded is in the
|
||||
[internals](@ref flatbuffers_internals) document.
|
||||
[internals](Internals.md#flexbuffers) document.
|
||||
|
||||
|
||||
# Nesting inside a FlatBuffer
|
||||
|
||||
You can mark a field as containing a FlexBuffer, e.g.
|
||||
|
||||
a:[ubyte] (flexbuffer);
|
||||
|
||||
A special accessor will be generated that allows you to access the root value
|
||||
directly, e.g. `a_flexbuffer_root().AsInt64()`.
|
||||
|
||||
|
||||
# Efficiency tips
|
||||
|
||||
@@ -147,19 +147,20 @@ To use it:
|
||||
array.
|
||||
- Instead of calling standard generated method,
|
||||
e.g.: `Monster.createTestarrayoftablesVector`,
|
||||
call `CreateMySortedVectorOfTables` in C# or
|
||||
call `CreateSortedVectorOfMonster` in C# or
|
||||
`createSortedVectorOfTables` (from the `FlatBufferBuilder` object) in Java,
|
||||
which will first sort all offsets such that the tables they refer to
|
||||
are sorted by the key field, then serialize it.
|
||||
- Now when you're accessing the FlatBuffer, you can use `LookupByKey`
|
||||
to access elements of the vector, e.g.:
|
||||
`Monster.lookupByKey(tablesVectorOffset, "Frodo", dataBuffer)`,
|
||||
- Now when you're accessing the FlatBuffer, you can use
|
||||
the `ByKey` accessor to access elements of the vector, e.g.:
|
||||
`monster.testarrayoftablesByKey("Frodo")` in Java or
|
||||
`monster.TestarrayoftablesByKey("Frodo")` in C#,
|
||||
which returns an object of the corresponding table type,
|
||||
or `null` if not found.
|
||||
`LookupByKey` performs a binary search, so should have a similar speed to
|
||||
`Dictionary`, though may be faster because of better caching. `LookupByKey`
|
||||
only works if the vector has been sorted, it will likely not find elements
|
||||
if it hasn't been sorted.
|
||||
`ByKey` performs a binary search, so should have a similar
|
||||
speed to `Dictionary`, though may be faster because of better caching.
|
||||
`ByKey` only works if the vector has been sorted, it will
|
||||
likely not find elements if it hasn't been sorted.
|
||||
|
||||
## Text parsing
|
||||
|
||||
|
||||
@@ -302,6 +302,9 @@ Current understood attributes:
|
||||
(which must be a vector of ubyte) contains flatbuffer data, for which the
|
||||
root type is given by `table_name`. The generated code will then produce
|
||||
a convenient accessor for the nested FlatBuffer.
|
||||
- `flexbuffer` (on a field): this indicates that the field
|
||||
(which must be a vector of ubyte) contains flexbuffer data. The generated
|
||||
code will then produce a convenient accessor for the FlexBuffer root.
|
||||
- `key` (on a field): this field is meant to be used as a key when sorting
|
||||
a vector of the type of table it sits in. Can be used for in-place
|
||||
binary search.
|
||||
|
||||
@@ -160,6 +160,7 @@ the `schema` that defines the template for our monsters:
|
||||
color:Color = Blue; // Enum.
|
||||
weapons:[Weapon]; // Vector of tables.
|
||||
equipped:Equipment; // Union.
|
||||
path:[Vec3]; // Vector of structs.
|
||||
}
|
||||
|
||||
table Weapon {
|
||||
@@ -799,6 +800,70 @@ elements by calling a lambda. For the common case of `std::vector<std::string>`
|
||||
there's also `CreateVectorOfStrings`.
|
||||
</div>
|
||||
|
||||
Note that vectors of structs are serialized differently from tables, since
|
||||
structs are stored in-line in the vector. For example, to create a vector
|
||||
for the `path` field above:
|
||||
|
||||
<div class="language-cpp">
|
||||
~~~{.cpp}
|
||||
Vec3 points[] = { Vec3(1.0f, 2.0f, 3.0f), Vec3(4.0f, 5.0f, 6.0f) };
|
||||
auto path = fbb.CreateVectorOfStructs(points, 2);
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-java">
|
||||
~~~{.java}
|
||||
Monster.startPathVector(fbb, 2);
|
||||
Vec3.createVec3(builder, 1.0f, 2.0f, 3.0f);
|
||||
Vec3.createVec3(builder, 4.0f, 5.0f, 6.0f);
|
||||
int path = fbb.endVector();
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
Monster.StartPathVector(fbb, 2);
|
||||
Vec3.CreateVec3(builder, 1.0f, 2.0f, 3.0f);
|
||||
Vec3.CreateVec3(builder, 4.0f, 5.0f, 6.0f);
|
||||
var path = fbb.EndVector();
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-go">
|
||||
~~~{.go}
|
||||
sample.MonsterStartPathVector(builder, 2)
|
||||
sample.CreateVec3(builder, 1.0, 2.0, 3.0)
|
||||
sample.CreateVec3(builder, 4.0, 5.0, 6.0)
|
||||
path := builder.EndVector(2)
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-python">
|
||||
~~~{.py}
|
||||
MyGame.Example.Monster.MonsterStartPathVector(builder, 2)
|
||||
MyGame.Sample.Vec3.CreateVec3(builder, 1.0, 2.0, 3.0)
|
||||
MyGame.Sample.Vec3.CreateVec3(builder, 4.0, 5.0, 6.0)
|
||||
path = builder.EndVector(2)
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-javascript">
|
||||
~~~{.js}
|
||||
MyGame.Example.Monster.startPathVector(builder, 2);
|
||||
MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0);
|
||||
MyGame.Sample.Vec3.createVec3(builder, 4.0, 5.0, 6.0);
|
||||
var path = builder.endVector();
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-php">
|
||||
~~~{.php}
|
||||
\MyGame\Example\Monster::StartPathVector($builder, 2);
|
||||
\MyGame\Sample\Vec3::CreateVec3($builder, 1.0, 2.0, 3.0);
|
||||
\MyGame\Sample\Vec3::CreateVec3($builder, 1.0, 2.0, 3.0);
|
||||
$path = $builder->endVector();
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-c">
|
||||
~~~{.c}
|
||||
// TBD
|
||||
~~~
|
||||
</div>
|
||||
|
||||
We have now serialized the non-scalar components of the orc, so we
|
||||
can serialize the monster itself:
|
||||
|
||||
@@ -812,7 +877,7 @@ can serialize the monster itself:
|
||||
// to set all fields.
|
||||
auto orc = CreateMonster(builder, Vec3(1.0f, 2.0f, 3.0f), mana, hp, name,
|
||||
inventory, Color_Red, weapons, Equipment_Weapon,
|
||||
axe.Union());
|
||||
axe.Union(), path);
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-java">
|
||||
@@ -827,6 +892,7 @@ can serialize the monster itself:
|
||||
Monster.addWeapons(builder, weapons);
|
||||
Monster.addEquippedType(builder, Equipment.Weapon);
|
||||
Monster.addEquipped(builder, axe);
|
||||
Monster.addPath(builder, path);
|
||||
int orc = Monster.endMonster(builder);
|
||||
~~~
|
||||
</div>
|
||||
@@ -842,6 +908,7 @@ can serialize the monster itself:
|
||||
Monster.AddWeapons(builder, weapons);
|
||||
Monster.AddEquippedType(builder, Equipment.Weapon);
|
||||
Monster.AddEquipped(builder, axe.Value); // Axe
|
||||
Monster.AddPath(builder, path);
|
||||
var orc = Monster.EndMonster(builder);
|
||||
~~~
|
||||
</div>
|
||||
@@ -857,6 +924,7 @@ can serialize the monster itself:
|
||||
sample.MonsterAddWeapons(builder, weapons)
|
||||
sample.MonsterAddEquippedType(builder, sample.EquipmentWeapon)
|
||||
sample.MonsterAddEquipped(builder, axe)
|
||||
sample.MonsterAddPath(builder, path)
|
||||
orc := sample.MonsterEnd(builder)
|
||||
~~~
|
||||
</div>
|
||||
@@ -875,6 +943,7 @@ can serialize the monster itself:
|
||||
MyGame.Sample.Monster.MonsterAddEquippedType(
|
||||
builder, MyGame.Sample.Equipment.Equipment().Weapon)
|
||||
MyGame.Sample.Monster.MonsterAddEquipped(builder, axe)
|
||||
MyGame.Sample.Monster.MonsterAddPath(builder, path)
|
||||
orc = MyGame.Sample.Monster.MonsterEnd(builder)
|
||||
~~~
|
||||
</div>
|
||||
@@ -891,6 +960,7 @@ can serialize the monster itself:
|
||||
MyGame.Sample.Monster.addWeapons(builder, weapons);
|
||||
MyGame.Sample.Monster.addEquippedType(builder, MyGame.Sample.Equipment.Weapon);
|
||||
MyGame.Sample.Monster.addEquipped(builder, axe);
|
||||
MyGame.Sample.Monster.addPath(builder, path);
|
||||
var orc = MyGame.Sample.Monster.endMonster(builder);
|
||||
~~~
|
||||
</div>
|
||||
@@ -907,6 +977,7 @@ can serialize the monster itself:
|
||||
\MyGame\Sample\Monster::AddWeapons($builder, $weapons);
|
||||
\MyGame\Sample\Monster::AddEquippedType($builder, \MyGame\Sample\Equipment::Weapon);
|
||||
\MyGame\Sample\Monster::AddEquipped($builder, $axe);
|
||||
\MyGame\Sample\Monster::AddPath($builder, $path);
|
||||
$orc = \MyGame\Sample\Monster::EndMonster($builder);
|
||||
~~~
|
||||
</div>
|
||||
@@ -921,7 +992,7 @@ can serialize the monster itself:
|
||||
ns(Equipment_union_ref_t) equipped = ns(Equipment_as_Weapon(axe));
|
||||
ns(Vec3_t) pos = { 1.0f, 2.0f, 3.0f };
|
||||
ns(Monster_create_as_root(B, &pos, mana, hp, name, inventory, ns(Color_Red),
|
||||
weapons, equipped));
|
||||
weapons, equipped, path));
|
||||
~~~
|
||||
</div>
|
||||
|
||||
@@ -929,10 +1000,10 @@ Note how we create `Vec3` struct in-line in the table. Unlike tables, structs
|
||||
are simple combinations of scalars that are always stored inline, just like
|
||||
scalars themselves.
|
||||
|
||||
**Important**: you should not nest tables or any other objects, which is why
|
||||
we created all the strings/vectors/tables that this monster refers to before
|
||||
`start`. If you try to create any of them between `start` and `end`, you
|
||||
will get an assert/exception/panic depending on your language.
|
||||
**Important**: Unlike structs, you should not nest tables or other objects,
|
||||
which is why we created all the strings/vectors/tables that this monster refers
|
||||
to before `start`. If you try to create any of them between `start` and `end`,
|
||||
you will get an assert/exception/panic depending on your language.
|
||||
|
||||
*Note: Since we are passing `150` as the `mana` field, which happens to be the
|
||||
default value, the field will not actually be written to the buffer, since the
|
||||
@@ -1470,10 +1541,10 @@ To access sub-objects, in the case of our `pos`, which is a `Vec3`:
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
var pos = monster.Pos
|
||||
var x = pos.X
|
||||
var y = pos.Y
|
||||
var z = pos.Z
|
||||
var pos = monster.Pos.Value;
|
||||
var x = pos.X;
|
||||
var y = pos.Y;
|
||||
var z = pos.Z;
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-go">
|
||||
@@ -1547,7 +1618,7 @@ FlatBuffers `vector`.
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
int invLength = monster.InventoryLength;
|
||||
var thirdItem = monster.GetInventory(2);
|
||||
var thirdItem = monster.Inventory(2);
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-go">
|
||||
@@ -1604,8 +1675,8 @@ except your need to handle the result as a FlatBuffer `table`:
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
int weaponsLength = monster.WeaponsLength;
|
||||
var secondWeaponName = monster.GetWeapons(1).Name;
|
||||
var secondWeaponDamage = monster.GetWeapons(1).Damage;
|
||||
var secondWeaponName = monster.Weapons(1).Name;
|
||||
var secondWeaponDamage = monster.Weapons(1).Damage;
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-go">
|
||||
@@ -1687,8 +1758,7 @@ We can access the type to dynamically cast the data as needed (since the
|
||||
var unionType = monster.EquippedType;
|
||||
|
||||
if (unionType == Equipment.Weapon) {
|
||||
var weapon = (Weapon)monster.GetEquipped(new Weapon()); // Requires explicit cast
|
||||
// to `Weapon`.
|
||||
var weapon = monster.Equipped<Weapon>().Value;
|
||||
|
||||
var weaponName = weapon.Name; // "Axe"
|
||||
var weaponDamage = weapon.Damage; // 5
|
||||
|
||||
@@ -765,6 +765,7 @@ INPUT = "FlatBuffers.md" \
|
||||
"../../CONTRIBUTING.md" \
|
||||
"Tutorial.md" \
|
||||
"GoApi.md" \
|
||||
"gRPC/CppUsage.md" \
|
||||
"groups" \
|
||||
"../../java/com/google/flatbuffers" \
|
||||
"../../python/flatbuffers/builder.py" \
|
||||
@@ -883,21 +884,21 @@ EXCLUDE_SYMBOLS =
|
||||
# that contain example code fragments that are included (see the \include
|
||||
# command).
|
||||
|
||||
EXAMPLE_PATH = "GoApi_generated.txt"
|
||||
EXAMPLE_PATH = "GoApi_generated.txt" "../../grpc/samples"
|
||||
|
||||
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
|
||||
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
|
||||
# *.h) to filter out the source-files in the directories. If left blank all
|
||||
# files are included.
|
||||
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_PATTERNS = *.cpp *.h *.txt *.fbs
|
||||
|
||||
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
|
||||
# searched for input files to be used with the \include or \dontinclude commands
|
||||
# irrespective of the value of the RECURSIVE tag.
|
||||
# The default value is: NO.
|
||||
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
EXAMPLE_RECURSIVE = YES
|
||||
|
||||
# The IMAGE_PATH tag can be used to specify one or more files or directories
|
||||
# that contain images that are to be included in the documentation (see the
|
||||
|
||||
@@ -39,6 +39,10 @@
|
||||
title="Use in Python"/>
|
||||
<tab type="user" url="@ref flexbuffers"
|
||||
title="Schema-less version"/>
|
||||
<tab type="usergroup" url="" title="gRPC">
|
||||
<tab type="user" url="@ref flatbuffers_grpc_guide_use_cpp"
|
||||
title="Use in C++"/>
|
||||
</tab>
|
||||
</tab>
|
||||
<tab type="user" url="@ref flatbuffers_support"
|
||||
title="Platform / Language / Feature support"/>
|
||||
|
||||
29
docs/source/gRPC/CppUsage.md
Normal file
29
docs/source/gRPC/CppUsage.md
Normal file
@@ -0,0 +1,29 @@
|
||||
Use in C++ {#flatbuffers_grpc_guide_use_cpp}
|
||||
==========
|
||||
|
||||
## Before you get started
|
||||
|
||||
Before diving into the FlatBuffers gRPC usage in C++, you should already be
|
||||
familiar with the following:
|
||||
|
||||
- FlatBuffers as a serialization format
|
||||
- [gRPC](http://www.grpc.io/docs/) usage
|
||||
|
||||
## Using the FlatBuffers gRPC C++ library
|
||||
|
||||
NOTE: The examples below are also in the `grpc/samples/greeter` directory.
|
||||
|
||||
We will illustrate usage with the following schema:
|
||||
|
||||
@include grpc/samples/greeter/greeter.fbs
|
||||
|
||||
When we run `flatc`, we pass in the `--grpc` option and generage an additional
|
||||
`greeter.grpc.fb.h` and `greeter.grpc.fb.cc`.
|
||||
|
||||
Example server code looks like this:
|
||||
|
||||
@include grpc/samples/greeter/server.cpp
|
||||
|
||||
Example client code looks like this:
|
||||
|
||||
@include grpc/samples/greeter/client.cpp
|
||||
14
grpc/samples/greeter/Makefile
Normal file
14
grpc/samples/greeter/Makefile
Normal file
@@ -0,0 +1,14 @@
|
||||
CXXFLAGS ?= -I../../../include
|
||||
LDFLAGS ?=
|
||||
|
||||
.PHONY: all
|
||||
all: server client
|
||||
|
||||
greeter_generated.h: greeter.fbs
|
||||
flatc --grpc --cpp $<
|
||||
|
||||
server: server.cpp greeter.grpc.fb.cc greeter_generated.h greeter.grpc.fb.h
|
||||
g++ -std=c++11 -O2 $(CXXFLAGS) $(LDFLAGS) -lgpr -lgrpc -lgrpc++ server.cpp greeter.grpc.fb.cc -o $@
|
||||
|
||||
client: client.cpp greeter.grpc.fb.cc greeter_generated.h greeter.grpc.fb.h
|
||||
g++ -std=c++11 -O2 $(CXXFLAGS) $(LDFLAGS) -lgpr -lgrpc -lgrpc++ client.cpp greeter.grpc.fb.cc -o $@
|
||||
85
grpc/samples/greeter/client.cpp
Normal file
85
grpc/samples/greeter/client.cpp
Normal file
@@ -0,0 +1,85 @@
|
||||
#include "greeter.grpc.fb.h"
|
||||
#include "greeter_generated.h"
|
||||
|
||||
#include <grpc++/grpc++.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class GreeterClient {
|
||||
public:
|
||||
GreeterClient(std::shared_ptr<grpc::Channel> channel)
|
||||
: stub_(Greeter::NewStub(channel)) {}
|
||||
|
||||
std::string SayHello(const std::string &name) {
|
||||
flatbuffers::grpc::MessageBuilder mb;
|
||||
auto name_offset = mb.CreateString(name);
|
||||
auto request_offset = CreateHelloRequest(mb, name_offset);
|
||||
mb.Finish(request_offset);
|
||||
auto request_msg = mb.ReleaseMessage<HelloRequest>();
|
||||
|
||||
flatbuffers::grpc::Message<HelloReply> response_msg;
|
||||
|
||||
grpc::ClientContext context;
|
||||
|
||||
auto status = stub_->SayHello(&context, request_msg, &response_msg);
|
||||
if (status.ok()) {
|
||||
const HelloReply *response = response_msg.GetRoot();
|
||||
return response->message()->str();
|
||||
} else {
|
||||
std::cerr << status.error_code() << ": " << status.error_message()
|
||||
<< std::endl;
|
||||
return "RPC failed";
|
||||
}
|
||||
}
|
||||
|
||||
void SayManyHellos(const std::string &name, int num_greetings,
|
||||
std::function<void(const std::string &)> callback) {
|
||||
flatbuffers::grpc::MessageBuilder mb;
|
||||
auto name_offset = mb.CreateString(name);
|
||||
auto request_offset =
|
||||
CreateManyHellosRequest(mb, name_offset, num_greetings);
|
||||
mb.Finish(request_offset);
|
||||
auto request_msg = mb.ReleaseMessage<ManyHellosRequest>();
|
||||
|
||||
flatbuffers::grpc::Message<HelloReply> response_msg;
|
||||
|
||||
grpc::ClientContext context;
|
||||
|
||||
auto stream = stub_->SayManyHellos(&context, request_msg);
|
||||
while (stream->Read(&response_msg)) {
|
||||
const HelloReply *response = response_msg.GetRoot();
|
||||
callback(response->message()->str());
|
||||
}
|
||||
auto status = stream->Finish();
|
||||
if (!status.ok()) {
|
||||
std::cerr << status.error_code() << ": " << status.error_message()
|
||||
<< std::endl;
|
||||
callback("RPC failed");
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<Greeter::Stub> stub_;
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
std::string server_address("localhost:50051");
|
||||
|
||||
auto channel =
|
||||
grpc::CreateChannel(server_address, grpc::InsecureChannelCredentials());
|
||||
GreeterClient greeter(channel);
|
||||
|
||||
std::string name("world");
|
||||
|
||||
std::string message = greeter.SayHello(name);
|
||||
std::cerr << "Greeter received: " << message << std::endl;
|
||||
|
||||
int num_greetings = 10;
|
||||
greeter.SayManyHellos(name, num_greetings, [](const std::string &message) {
|
||||
std::cerr << "Greeter received: " << message << std::endl;
|
||||
});
|
||||
|
||||
return 0;
|
||||
}
|
||||
17
grpc/samples/greeter/greeter.fbs
Normal file
17
grpc/samples/greeter/greeter.fbs
Normal file
@@ -0,0 +1,17 @@
|
||||
table HelloReply {
|
||||
message:string;
|
||||
}
|
||||
|
||||
table HelloRequest {
|
||||
name:string;
|
||||
}
|
||||
|
||||
table ManyHellosRequest {
|
||||
name:string;
|
||||
num_greetings:int;
|
||||
}
|
||||
|
||||
rpc_service Greeter {
|
||||
SayHello(HelloRequest):HelloReply;
|
||||
SayManyHellos(ManyHellosRequest):HelloReply (streaming: "server");
|
||||
}
|
||||
80
grpc/samples/greeter/server.cpp
Normal file
80
grpc/samples/greeter/server.cpp
Normal file
@@ -0,0 +1,80 @@
|
||||
#include "greeter.grpc.fb.h"
|
||||
#include "greeter_generated.h"
|
||||
|
||||
#include <grpc++/grpc++.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
class GreeterServiceImpl final : public Greeter::Service {
|
||||
virtual grpc::Status SayHello(
|
||||
grpc::ServerContext *context,
|
||||
const flatbuffers::grpc::Message<HelloRequest> *request_msg,
|
||||
flatbuffers::grpc::Message<HelloReply> *response_msg) override {
|
||||
// flatbuffers::grpc::MessageBuilder mb_;
|
||||
// We call GetRoot to "parse" the message. Verification is already
|
||||
// performed by default. See the notes below for more details.
|
||||
const HelloRequest *request = request_msg->GetRoot();
|
||||
|
||||
// Fields are retrieved as usual with FlatBuffers
|
||||
const std::string &name = request->name()->str();
|
||||
|
||||
// `flatbuffers::grpc::MessageBuilder` is a `FlatBufferBuilder` with a
|
||||
// special allocator for efficient gRPC buffer transfer, but otherwise
|
||||
// usage is the same as usual.
|
||||
auto msg_offset = mb_.CreateString("Hello, " + name);
|
||||
auto hello_offset = CreateHelloReply(mb_, msg_offset);
|
||||
mb_.Finish(hello_offset);
|
||||
|
||||
// The `ReleaseMessage<T>()` function detaches the message from the
|
||||
// builder, so we can transfer the resopnse to gRPC while simultaneously
|
||||
// detaching that memory buffer from the builer.
|
||||
*response_msg = mb_.ReleaseMessage<HelloReply>();
|
||||
assert(response_msg->Verify());
|
||||
|
||||
// Return an OK status.
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
virtual grpc::Status SayManyHellos(
|
||||
grpc::ServerContext *context,
|
||||
const flatbuffers::grpc::Message<ManyHellosRequest> *request_msg,
|
||||
grpc::ServerWriter<flatbuffers::grpc::Message<HelloReply>> *writer)
|
||||
override {
|
||||
// The streaming usage below is simply a combination of standard gRPC
|
||||
// streaming with the FlatBuffers usage shown above.
|
||||
const ManyHellosRequest *request = request_msg->GetRoot();
|
||||
const std::string &name = request->name()->str();
|
||||
int num_greetings = request->num_greetings();
|
||||
|
||||
for (int i = 0; i < num_greetings; i++) {
|
||||
auto msg_offset = mb_.CreateString("Many hellos, " + name);
|
||||
auto hello_offset = CreateHelloReply(mb_, msg_offset);
|
||||
mb_.Finish(hello_offset);
|
||||
writer->Write(mb_.ReleaseMessage<HelloReply>());
|
||||
}
|
||||
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
flatbuffers::grpc::MessageBuilder mb_;
|
||||
};
|
||||
|
||||
void RunServer() {
|
||||
std::string server_address("0.0.0.0:50051");
|
||||
GreeterServiceImpl service;
|
||||
|
||||
grpc::ServerBuilder builder;
|
||||
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
|
||||
builder.RegisterService(&service);
|
||||
std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
|
||||
std::cerr << "Server listening on " << server_address << std::endl;
|
||||
|
||||
server->Wait();
|
||||
}
|
||||
|
||||
int main(int argc, const char *argv[]) {
|
||||
RunServer();
|
||||
return 0;
|
||||
}
|
||||
40
grpc/src/compiler/config.h
Normal file
40
grpc/src/compiler/config.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRC_COMPILER_CONFIG_H
|
||||
#define SRC_COMPILER_CONFIG_H
|
||||
|
||||
// This file is here only because schema_interface.h, which is copied from gRPC,
|
||||
// includes it. There is nothing for Flatbuffers to configure.
|
||||
|
||||
#endif // SRC_COMPILER_CONFIG_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -41,8 +41,20 @@
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "src/compiler/config.h"
|
||||
#include "src/compiler/schema_interface.h"
|
||||
|
||||
#ifndef GRPC_CUSTOM_STRING
|
||||
#include <string>
|
||||
#define GRPC_CUSTOM_STRING std::string
|
||||
#endif
|
||||
|
||||
namespace grpc {
|
||||
|
||||
typedef GRPC_CUSTOM_STRING string;
|
||||
|
||||
} // namespace grpc
|
||||
|
||||
namespace grpc_cpp_generator {
|
||||
|
||||
// Contains all the parameters that are parsed from the command line.
|
||||
@@ -53,31 +65,73 @@ struct Parameters {
|
||||
bool use_system_headers;
|
||||
// Prefix to any grpc include
|
||||
grpc::string grpc_search_path;
|
||||
// Generate GMOCK code to facilitate unit testing.
|
||||
bool generate_mock_code;
|
||||
};
|
||||
|
||||
// Return the prologue of the generated header file.
|
||||
grpc::string GetHeaderPrologue(grpc_generator::File *file, const Parameters ¶ms);
|
||||
grpc::string GetHeaderPrologue(grpc_generator::File *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the includes needed for generated header file.
|
||||
grpc::string GetHeaderIncludes(grpc_generator::File *file, const Parameters ¶ms);
|
||||
grpc::string GetHeaderIncludes(grpc_generator::File *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the includes needed for generated source file.
|
||||
grpc::string GetSourceIncludes(grpc_generator::File *file, const Parameters ¶ms);
|
||||
grpc::string GetSourceIncludes(grpc_generator::File *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the epilogue of the generated header file.
|
||||
grpc::string GetHeaderEpilogue(grpc_generator::File *file, const Parameters ¶ms);
|
||||
grpc::string GetHeaderEpilogue(grpc_generator::File *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the prologue of the generated source file.
|
||||
grpc::string GetSourcePrologue(grpc_generator::File *file, const Parameters ¶ms);
|
||||
grpc::string GetSourcePrologue(grpc_generator::File *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the services for generated header file.
|
||||
grpc::string GetHeaderServices(grpc_generator::File *file, const Parameters ¶ms);
|
||||
grpc::string GetHeaderServices(grpc_generator::File *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the services for generated source file.
|
||||
grpc::string GetSourceServices(grpc_generator::File *file, const Parameters ¶ms);
|
||||
grpc::string GetSourceServices(grpc_generator::File *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the epilogue of the generated source file.
|
||||
grpc::string GetSourceEpilogue(grpc_generator::File *file, const Parameters ¶ms);
|
||||
grpc::string GetSourceEpilogue(grpc_generator::File *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the prologue of the generated mock file.
|
||||
grpc::string GetMockPrologue(grpc_generator::File *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the includes needed for generated mock file.
|
||||
grpc::string GetMockIncludes(grpc_generator::File *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the services for generated mock file.
|
||||
grpc::string GetMockServices(grpc_generator::File *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the epilogue of generated mock file.
|
||||
grpc::string GetMockEpilogue(grpc_generator::File *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the prologue of the generated mock file.
|
||||
grpc::string GetMockPrologue(grpc_generator::File *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the includes needed for generated mock file.
|
||||
grpc::string GetMockIncludes(grpc_generator::File *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the services for generated mock file.
|
||||
grpc::string GetMockServices(grpc_generator::File *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
// Return the epilogue of generated mock file.
|
||||
grpc::string GetMockEpilogue(grpc_generator::File *file,
|
||||
const Parameters ¶ms);
|
||||
|
||||
} // namespace grpc_cpp_generator
|
||||
|
||||
|
||||
@@ -44,6 +44,14 @@ grpc::string as_string(T x) {
|
||||
return out.str();
|
||||
}
|
||||
|
||||
inline bool ClientOnlyStreaming(const grpc_generator::Method *method) {
|
||||
return method->ClientStreaming() && !method->ServerStreaming();
|
||||
}
|
||||
|
||||
inline bool ServerOnlyStreaming(const grpc_generator::Method *method) {
|
||||
return !method->ClientStreaming() && method->ServerStreaming();
|
||||
}
|
||||
|
||||
namespace grpc_go_generator {
|
||||
|
||||
// Returns string with first letter to lowerCase
|
||||
@@ -70,8 +78,8 @@ void GenerateImports(grpc_generator::File *file, grpc_generator::Printer *printe
|
||||
printer->Print("//If you make any local changes, they will be lost\n");
|
||||
printer->Print(vars, "//source: $filename$\n\n");
|
||||
printer->Print(vars, "package $Package$\n\n");
|
||||
if (file->additional_imports() != "") {
|
||||
printer->Print(file->additional_imports().c_str());
|
||||
if (file->additional_headers() != "") {
|
||||
printer->Print(file->additional_headers().c_str());
|
||||
printer->Print("\n\n");
|
||||
}
|
||||
printer->Print("import (\n");
|
||||
@@ -86,11 +94,11 @@ void GenerateImports(grpc_generator::File *file, grpc_generator::Printer *printe
|
||||
void GenerateServerMethodSignature(const grpc_generator::Method *method, grpc_generator::Printer *printer,
|
||||
std::map<grpc::string, grpc::string> vars) {
|
||||
vars["Method"] = exportName(method->name());
|
||||
vars["Request"] = method->input_name();
|
||||
vars["Response"] = (vars["CustomMethodIO"] == "") ? method->output_name() : vars["CustomMethodIO"];
|
||||
vars["Request"] = method->get_input_type_name();
|
||||
vars["Response"] = (vars["CustomMethodIO"] == "") ? method->get_output_type_name() : vars["CustomMethodIO"];
|
||||
if (method->NoStreaming()) {
|
||||
printer->Print(vars, "$Method$($context$.Context, *$Request$) (*$Response$, error)");
|
||||
} else if (method->ServerOnlyStreaming()) {
|
||||
} else if (ServerOnlyStreaming(method)) {
|
||||
printer->Print(vars, "$Method$(*$Request$, $Service$_$Method$Server) error");
|
||||
} else {
|
||||
printer->Print(vars, "$Method$($Service$_$Method$Server) error");
|
||||
@@ -100,8 +108,8 @@ void GenerateServerMethodSignature(const grpc_generator::Method *method, grpc_ge
|
||||
void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::Printer *printer,
|
||||
std::map<grpc::string, grpc::string> vars) {
|
||||
vars["Method"] = exportName(method->name());
|
||||
vars["Request"] = method->input_name();
|
||||
vars["Response"] = (vars["CustomMethodIO"] == "") ? method->output_name() : vars["CustomMethodIO"];
|
||||
vars["Request"] = method->get_input_type_name();
|
||||
vars["Response"] = (vars["CustomMethodIO"] == "") ? method->get_output_type_name() : vars["CustomMethodIO"];
|
||||
vars["FullMethodName"] = "/" + vars["Package"] + "." + vars["Service"] + "/" + vars["Method"];
|
||||
vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
|
||||
if (method->NoStreaming()) {
|
||||
@@ -129,7 +137,7 @@ void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::
|
||||
vars["StreamType"] = vars["ServiceUnexported"] + vars["Method"] + "Server";
|
||||
printer->Print(vars, "func $Handler$(srv interface{}, stream $grpc$.ServerStream) error {\n");
|
||||
printer->Indent();
|
||||
if (method->ServerOnlyStreaming()) {
|
||||
if (ServerOnlyStreaming(method)) {
|
||||
printer->Print(vars, "m := new($Request$)\n");
|
||||
printer->Print(vars, "if err := stream.RecvMsg(m); err != nil { return err }\n");
|
||||
printer->Print(vars, "return srv.($Service$Server).$Method$(m, &$StreamType${stream})\n");
|
||||
@@ -139,9 +147,9 @@ void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::
|
||||
printer->Outdent();
|
||||
printer->Print("}\n\n");
|
||||
|
||||
bool genSend = method->BidiStreaming() || method->ServerOnlyStreaming();
|
||||
bool genRecv = method->BidiStreaming() || method->ClientOnlyStreaming();
|
||||
bool genSendAndClose = method->ClientOnlyStreaming();
|
||||
bool genSend = method->BidiStreaming() || ServerOnlyStreaming(method);
|
||||
bool genRecv = method->BidiStreaming() || ClientOnlyStreaming(method);
|
||||
bool genSendAndClose = ClientOnlyStreaming(method);
|
||||
|
||||
printer->Print(vars, "type $Service$_$Method$Server interface { \n");
|
||||
printer->Indent();
|
||||
@@ -194,12 +202,12 @@ void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::
|
||||
void GenerateClientMethodSignature(const grpc_generator::Method *method, grpc_generator::Printer *printer,
|
||||
std::map<grpc::string, grpc::string> vars) {
|
||||
vars["Method"] = exportName(method->name());
|
||||
vars["Request"] = ", in *" + ((vars["CustomMethodIO"] == "") ? method->input_name() : vars["CustomMethodIO"]);
|
||||
if (method->ClientOnlyStreaming() || method->BidiStreaming()) {
|
||||
vars["Request"] = ", in *" + ((vars["CustomMethodIO"] == "") ? method->get_input_type_name() : vars["CustomMethodIO"]);
|
||||
if (ClientOnlyStreaming(method) || method->BidiStreaming()) {
|
||||
vars["Request"] = "";
|
||||
}
|
||||
vars["Response"] = "* " + method->output_name();
|
||||
if (method->ClientOnlyStreaming() || method->BidiStreaming() || method->ServerOnlyStreaming()) {
|
||||
vars["Response"] = "* " + method->get_output_type_name();
|
||||
if (ClientOnlyStreaming(method) || method->BidiStreaming() || ServerOnlyStreaming(method)) {
|
||||
vars["Response"] = vars["Service"] + "_" + vars["Method"] + "Client" ;
|
||||
}
|
||||
printer->Print(vars, "$Method$(ctx $context$.Context$Request$, \n\topts... $grpc$.CallOption) ($Response$, error)");
|
||||
@@ -213,8 +221,8 @@ void GenerateClientMethod(const grpc_generator::Method *method, grpc_generator::
|
||||
printer->Print(" {\n");
|
||||
printer->Indent();
|
||||
vars["Method"] = exportName(method->name());
|
||||
vars["Request"] = (vars["CustomMethodIO"] == "") ? method->input_name() : vars["CustomMethodIO"];
|
||||
vars["Response"] = method->output_name();
|
||||
vars["Request"] = (vars["CustomMethodIO"] == "") ? method->get_input_type_name() : vars["CustomMethodIO"];
|
||||
vars["Response"] = method->get_output_type_name();
|
||||
vars["FullMethodName"] = "/" + vars["Package"] + "." + vars["Service"] + "/" + vars["Method"];
|
||||
if (method->NoStreaming()) {
|
||||
printer->Print(vars, "out := new($Response$)\n");
|
||||
@@ -230,7 +238,7 @@ void GenerateClientMethod(const grpc_generator::Method *method, grpc_generator::
|
||||
printer->Print("if err != nil { return nil, err }\n");
|
||||
|
||||
printer->Print(vars, "x := &$StreamType${stream}\n");
|
||||
if (method->ServerOnlyStreaming()) {
|
||||
if (ServerOnlyStreaming(method)) {
|
||||
printer->Print("if err := x.ClientStream.SendMsg(in); err != nil { return nil, err }\n");
|
||||
printer->Print("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }\n");
|
||||
}
|
||||
@@ -238,9 +246,9 @@ void GenerateClientMethod(const grpc_generator::Method *method, grpc_generator::
|
||||
printer->Outdent();
|
||||
printer->Print("}\n\n");
|
||||
|
||||
bool genSend = method->BidiStreaming() || method->ClientOnlyStreaming();
|
||||
bool genRecv = method->BidiStreaming() || method->ServerOnlyStreaming();
|
||||
bool genCloseAndRecv = method->ClientOnlyStreaming();
|
||||
bool genSend = method->BidiStreaming() || ClientOnlyStreaming(method);
|
||||
bool genRecv = method->BidiStreaming() || ServerOnlyStreaming(method);
|
||||
bool genCloseAndRecv = ClientOnlyStreaming(method);
|
||||
|
||||
//Stream interface
|
||||
printer->Print(vars, "type $Service$_$Method$Client interface {\n");
|
||||
@@ -396,9 +404,9 @@ void GenerateService(const grpc_generator::Service *service, grpc_generator::Pri
|
||||
printer->Indent();
|
||||
printer->Print(vars, "StreamName: \"$Method$\",\n");
|
||||
printer->Print(vars, "Handler: $Handler$, \n");
|
||||
if (method->ClientOnlyStreaming()) {
|
||||
if (ClientOnlyStreaming(method.get())) {
|
||||
printer->Print("ClientStreams: true,\n");
|
||||
} else if (method->ServerOnlyStreaming()) {
|
||||
} else if (ServerOnlyStreaming(method.get())) {
|
||||
printer->Print("ServerStreams: true,\n");
|
||||
} else {
|
||||
printer->Print("ServerStreams: true,\n");
|
||||
|
||||
@@ -43,12 +43,12 @@
|
||||
namespace grpc_go_generator {
|
||||
|
||||
struct Parameters {
|
||||
//Defines the custom parameter types for methods
|
||||
//eg: flatbuffers uses flatbuffers.Builder as input for the client and output for the server
|
||||
grpc::string custom_method_io_type;
|
||||
//Defines the custom parameter types for methods
|
||||
//eg: flatbuffers uses flatbuffers.Builder as input for the client and output for the server
|
||||
grpc::string custom_method_io_type;
|
||||
|
||||
//Package name for the service
|
||||
grpc::string package_name;
|
||||
//Package name for the service
|
||||
grpc::string package_name;
|
||||
};
|
||||
|
||||
// Return the source of the generated service file.
|
||||
|
||||
@@ -34,79 +34,93 @@
|
||||
#ifndef GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
|
||||
#define GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
|
||||
|
||||
#include <map>
|
||||
#include "src/compiler/config.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#ifndef GRPC_CUSTOM_STRING
|
||||
#include <string>
|
||||
#define GRPC_CUSTOM_STRING std::string
|
||||
#endif
|
||||
#ifndef GRPC_CUSTOM_STRING
|
||||
#include <string>
|
||||
#define GRPC_CUSTOM_STRING std::string
|
||||
#endif
|
||||
|
||||
namespace grpc {
|
||||
|
||||
typedef GRPC_CUSTOM_STRING string;
|
||||
typedef GRPC_CUSTOM_STRING string;
|
||||
|
||||
} // namespace grpc
|
||||
|
||||
namespace grpc_generator {
|
||||
|
||||
// An abstract interface representing a method.
|
||||
struct Method {
|
||||
virtual ~Method() {}
|
||||
// A common interface for objects having comments in the source.
|
||||
// Return formatted comments to be inserted in generated code.
|
||||
struct CommentHolder {
|
||||
virtual ~CommentHolder() {}
|
||||
virtual grpc::string GetLeadingComments(const grpc::string prefix) const = 0;
|
||||
virtual grpc::string GetTrailingComments(const grpc::string prefix) const = 0;
|
||||
virtual std::vector<grpc::string> GetAllComments() const = 0;
|
||||
};
|
||||
|
||||
virtual grpc::string name() const = 0;
|
||||
// An abstract interface representing a method.
|
||||
struct Method : public CommentHolder {
|
||||
virtual ~Method() {}
|
||||
|
||||
virtual grpc::string input_type_name() const = 0;
|
||||
virtual grpc::string output_type_name() const = 0;
|
||||
virtual grpc::string input_name() const = 0;
|
||||
virtual grpc::string output_name() const = 0;
|
||||
virtual grpc::string name() const = 0;
|
||||
|
||||
virtual bool NoStreaming() const = 0;
|
||||
virtual bool ClientOnlyStreaming() const = 0;
|
||||
virtual bool ServerOnlyStreaming() const = 0;
|
||||
virtual bool BidiStreaming() const = 0;
|
||||
};
|
||||
virtual grpc::string input_type_name() const = 0;
|
||||
virtual grpc::string output_type_name() const = 0;
|
||||
|
||||
// An abstract interface representing a service.
|
||||
struct Service {
|
||||
virtual ~Service() {}
|
||||
virtual bool get_module_and_message_path_input(
|
||||
grpc::string *str, grpc::string generator_file_name,
|
||||
bool generate_in_pb2_grpc, grpc::string import_prefix) const = 0;
|
||||
virtual bool get_module_and_message_path_output(
|
||||
grpc::string *str, grpc::string generator_file_name,
|
||||
bool generate_in_pb2_grpc, grpc::string import_prefix) const = 0;
|
||||
|
||||
virtual grpc::string name() const = 0;
|
||||
virtual grpc::string get_input_type_name() const = 0;
|
||||
virtual grpc::string get_output_type_name() const = 0;
|
||||
virtual bool NoStreaming() const = 0;
|
||||
virtual bool ClientStreaming() const = 0;
|
||||
virtual bool ServerStreaming() const = 0;
|
||||
virtual bool BidiStreaming() const = 0;
|
||||
};
|
||||
|
||||
virtual int method_count() const = 0;
|
||||
virtual std::unique_ptr<const Method> method(int i) const = 0;
|
||||
};
|
||||
// An abstract interface representing a service.
|
||||
struct Service : public CommentHolder {
|
||||
virtual ~Service() {}
|
||||
|
||||
struct Printer {
|
||||
virtual ~Printer() {}
|
||||
virtual grpc::string name() const = 0;
|
||||
|
||||
virtual void Print(const std::map<grpc::string, grpc::string> &vars,
|
||||
const char *template_string) = 0;
|
||||
virtual void Print(const char *string) = 0;
|
||||
virtual void Indent() = 0;
|
||||
virtual void Outdent() = 0;
|
||||
};
|
||||
virtual int method_count() const = 0;
|
||||
virtual std::unique_ptr<const Method> method(int i) const = 0;
|
||||
};
|
||||
|
||||
// An interface that allows the source generated to be output using various
|
||||
// libraries/idls/serializers.
|
||||
struct File {
|
||||
virtual ~File() {}
|
||||
struct Printer {
|
||||
virtual ~Printer() {}
|
||||
|
||||
virtual grpc::string filename() const = 0;
|
||||
virtual grpc::string filename_without_ext() const = 0;
|
||||
virtual grpc::string message_header_ext() const = 0;
|
||||
virtual grpc::string service_header_ext() const = 0;
|
||||
virtual grpc::string package() const = 0;
|
||||
virtual std::vector<grpc::string> package_parts() const = 0;
|
||||
virtual grpc::string additional_headers() const = 0;
|
||||
virtual grpc::string additional_imports() const = 0;
|
||||
virtual void Print(const std::map<grpc::string, grpc::string> &vars,
|
||||
const char *template_string) = 0;
|
||||
virtual void Print(const char *string) = 0;
|
||||
virtual void Indent() = 0;
|
||||
virtual void Outdent() = 0;
|
||||
};
|
||||
|
||||
virtual int service_count() const = 0;
|
||||
virtual std::unique_ptr<const Service> service(int i) const = 0;
|
||||
// An interface that allows the source generated to be output using various
|
||||
// libraries/idls/serializers.
|
||||
struct File : public CommentHolder {
|
||||
virtual ~File() {}
|
||||
|
||||
virtual std::unique_ptr<Printer> CreatePrinter(grpc::string *str) const = 0;
|
||||
};
|
||||
} // namespace grpc_generator
|
||||
virtual grpc::string filename() const = 0;
|
||||
virtual grpc::string filename_without_ext() const = 0;
|
||||
virtual grpc::string package() const = 0;
|
||||
virtual std::vector<grpc::string> package_parts() const = 0;
|
||||
virtual grpc::string additional_headers() const = 0;
|
||||
|
||||
virtual int service_count() const = 0;
|
||||
virtual std::unique_ptr<const Service> service(int i) const = 0;
|
||||
|
||||
virtual std::unique_ptr<Printer> CreatePrinter(grpc::string *str) const = 0;
|
||||
};
|
||||
} // namespace grpc_generator
|
||||
|
||||
#endif // GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
|
||||
|
||||
@@ -27,31 +27,41 @@ using namespace MyGame::Example;
|
||||
// code. It implements all rpcs specified in the FlatBuffers schema.
|
||||
class ServiceImpl final : public MyGame::Example::MonsterStorage::Service {
|
||||
virtual ::grpc::Status Store(::grpc::ServerContext* context,
|
||||
const flatbuffers::BufferRef<Monster> *request,
|
||||
flatbuffers::BufferRef<Stat> *response)
|
||||
const flatbuffers::grpc::Message<Monster> *request,
|
||||
flatbuffers::grpc::Message<Stat> *response)
|
||||
override {
|
||||
// Create a response from the incoming request name.
|
||||
fbb_.Clear();
|
||||
auto stat_offset = CreateStat(fbb_, fbb_.CreateString("Hello, " +
|
||||
request->GetRoot()->name()->str()));
|
||||
fbb_.Finish(stat_offset);
|
||||
// Since we keep reusing the same FlatBufferBuilder, the memory it owns
|
||||
// remains valid until the next call (this BufferRef doesn't own the
|
||||
// memory it points to).
|
||||
*response = flatbuffers::BufferRef<Stat>(fbb_.GetBufferPointer(),
|
||||
fbb_.GetSize());
|
||||
// Transfer ownership of the message to gRPC
|
||||
*response = fbb_.ReleaseMessage<Stat>();
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
virtual ::grpc::Status Retrieve(::grpc::ServerContext *context,
|
||||
const flatbuffers::BufferRef<Stat> *request,
|
||||
::grpc::ServerWriter< flatbuffers::BufferRef<Monster>>* writer)
|
||||
override {
|
||||
assert(false); // We're not actually using this RPC.
|
||||
return grpc::Status::CANCELLED;
|
||||
const flatbuffers::grpc::Message<Stat> *request,
|
||||
::grpc::ServerWriter< flatbuffers::grpc::Message<Monster>>* writer)
|
||||
override {
|
||||
|
||||
for (int i=0; i<10; i++) {
|
||||
fbb_.Clear();
|
||||
// Create 10 monsters for resposne.
|
||||
auto monster_offset =
|
||||
CreateMonster(fbb_, 0, 0, 0, fbb_.CreateString(
|
||||
request->GetRoot()->id()->str() + " No." + std::to_string(i)));
|
||||
fbb_.Finish(monster_offset);
|
||||
|
||||
flatbuffers::grpc::Message<Monster> monster = fbb_.ReleaseMessage<Monster>();
|
||||
|
||||
// Send monster to client using streaming.
|
||||
writer->Write(monster);
|
||||
}
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
private:
|
||||
flatbuffers::FlatBufferBuilder fbb_;
|
||||
flatbuffers::grpc::MessageBuilder fbb_;
|
||||
};
|
||||
|
||||
// Track the server instance, so we can terminate it later.
|
||||
@@ -93,25 +103,55 @@ int main(int /*argc*/, const char * /*argv*/[]) {
|
||||
grpc::InsecureChannelCredentials());
|
||||
auto stub = MyGame::Example::MonsterStorage::NewStub(channel);
|
||||
|
||||
grpc::ClientContext context;
|
||||
|
||||
// Build a request with the name set.
|
||||
flatbuffers::FlatBufferBuilder fbb;
|
||||
auto monster_offset = CreateMonster(fbb, 0, 0, 0, fbb.CreateString("Fred"));
|
||||
fbb.Finish(monster_offset);
|
||||
auto request = flatbuffers::BufferRef<Monster>(fbb.GetBufferPointer(),
|
||||
fbb.GetSize());
|
||||
flatbuffers::BufferRef<Stat> response;
|
||||
flatbuffers::grpc::MessageBuilder fbb;
|
||||
{
|
||||
grpc::ClientContext context;
|
||||
// Build a request with the name set.
|
||||
auto monster_offset = CreateMonster(fbb, 0, 0, 0, fbb.CreateString("Fred"));
|
||||
fbb.Finish(monster_offset);
|
||||
auto request = fbb.ReleaseMessage<Monster>();
|
||||
flatbuffers::grpc::Message<Stat> response;
|
||||
|
||||
// The actual RPC.
|
||||
auto status = stub->Store(&context, request, &response);
|
||||
// The actual RPC.
|
||||
auto status = stub->Store(&context, request, &response);
|
||||
|
||||
if (status.ok()) {
|
||||
auto resp = response.GetRoot()->id();
|
||||
std::cout << "RPC response: " << resp->str() << std::endl;
|
||||
} else {
|
||||
std::cout << "RPC failed" << std::endl;
|
||||
if (status.ok()) {
|
||||
auto resp = response.GetRoot()->id();
|
||||
std::cout << "RPC response: " << resp->str() << std::endl;
|
||||
} else {
|
||||
std::cout << "RPC failed" << std::endl;
|
||||
}
|
||||
}
|
||||
{
|
||||
grpc::ClientContext context;
|
||||
fbb.Clear();
|
||||
auto stat_offset = CreateStat(fbb, fbb.CreateString("Fred"));
|
||||
fbb.Finish(stat_offset);
|
||||
auto request = fbb.ReleaseMessage<Stat>();
|
||||
|
||||
flatbuffers::grpc::Message<Monster> response;
|
||||
auto stream = stub->Retrieve(&context, request);
|
||||
while (stream->Read(&response)) {
|
||||
auto resp = response.GetRoot()->name();
|
||||
std::cout << "RPC Streaming response: " << resp->str() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
#if !FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
|
||||
{
|
||||
// Test that an invalid request errors out correctly
|
||||
grpc::ClientContext context;
|
||||
flatbuffers::grpc::Message<Monster> request; // simulate invalid message
|
||||
flatbuffers::grpc::Message<Stat> response;
|
||||
auto status = stub->Store(&context, request, &response);
|
||||
// The rpc status should be INTERNAL to indicate a verification error. This
|
||||
// matches the protobuf gRPC status code for an unparseable message.
|
||||
assert(!status.ok());
|
||||
assert(status.error_code() == ::grpc::StatusCode::INTERNAL);
|
||||
assert(strcmp(status.error_message().c_str(), "Message verification failed") == 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
server_instance->Shutdown();
|
||||
|
||||
@@ -121,4 +161,3 @@ int main(int /*argc*/, const char * /*argv*/[]) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
177
include/flatbuffers/base.h
Normal file
177
include/flatbuffers/base.h
Normal file
@@ -0,0 +1,177 @@
|
||||
#ifndef FLATBUFFERS_BASE_H_
|
||||
#define FLATBUFFERS_BASE_H_
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef ARDUINO
|
||||
#include <cstdint>
|
||||
#endif
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#ifndef ARDUINO
|
||||
#include <utility>
|
||||
#else
|
||||
#include <utility.h>
|
||||
#endif
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
|
||||
#ifdef _STLPORT_VERSION
|
||||
#define FLATBUFFERS_CPP98_STL
|
||||
#endif
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
#include <functional>
|
||||
#endif
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
#if __cplusplus <= 199711L && \
|
||||
(!defined(_MSC_VER) || _MSC_VER < 1600) && \
|
||||
(!defined(__GNUC__) || \
|
||||
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400))
|
||||
#error A C++11 compatible compiler with support for the auto typing is \
|
||||
required for FlatBuffers.
|
||||
#error __cplusplus _MSC_VER __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__
|
||||
#endif
|
||||
|
||||
#if !defined(__clang__) && \
|
||||
defined(__GNUC__) && \
|
||||
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600)
|
||||
// Backwards compatability for g++ 4.4, and 4.5 which don't have the nullptr
|
||||
// and constexpr keywords. Note the __clang__ check is needed, because clang
|
||||
// presents itself as an older GNUC compiler.
|
||||
#ifndef nullptr_t
|
||||
const class nullptr_t {
|
||||
public:
|
||||
template<class T> inline operator T*() const { return 0; }
|
||||
private:
|
||||
void operator&() const;
|
||||
} nullptr = {};
|
||||
#endif
|
||||
#ifndef constexpr
|
||||
#define constexpr const
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// The wire format uses a little endian encoding (since that's efficient for
|
||||
// the common platforms).
|
||||
#if defined(__s390x__)
|
||||
#define FLATBUFFERS_LITTLEENDIAN 0
|
||||
#endif // __s390x__
|
||||
#if !defined(FLATBUFFERS_LITTLEENDIAN)
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#ifdef __BIG_ENDIAN__
|
||||
#define FLATBUFFERS_LITTLEENDIAN 0
|
||||
#else
|
||||
#define FLATBUFFERS_LITTLEENDIAN 1
|
||||
#endif // __BIG_ENDIAN__
|
||||
#elif defined(_MSC_VER)
|
||||
#if defined(_M_PPC)
|
||||
#define FLATBUFFERS_LITTLEENDIAN 0
|
||||
#else
|
||||
#define FLATBUFFERS_LITTLEENDIAN 1
|
||||
#endif
|
||||
#else
|
||||
#error Unable to determine endianness, define FLATBUFFERS_LITTLEENDIAN.
|
||||
#endif
|
||||
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
|
||||
|
||||
#define FLATBUFFERS_VERSION_MAJOR 1
|
||||
#define FLATBUFFERS_VERSION_MINOR 7
|
||||
#define FLATBUFFERS_VERSION_REVISION 0
|
||||
#define FLATBUFFERS_STRING_EXPAND(X) #X
|
||||
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
|
||||
|
||||
#if (!defined(_MSC_VER) || _MSC_VER > 1600) && \
|
||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407))
|
||||
#define FLATBUFFERS_FINAL_CLASS final
|
||||
#define FLATBUFFERS_OVERRIDE override
|
||||
#else
|
||||
#define FLATBUFFERS_FINAL_CLASS
|
||||
#define FLATBUFFERS_OVERRIDE
|
||||
#endif
|
||||
|
||||
#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
|
||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406))
|
||||
#define FLATBUFFERS_CONSTEXPR constexpr
|
||||
#else
|
||||
#define FLATBUFFERS_CONSTEXPR
|
||||
#endif
|
||||
|
||||
#if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46 || \
|
||||
defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026
|
||||
#define FLATBUFFERS_NOEXCEPT noexcept
|
||||
#else
|
||||
#define FLATBUFFERS_NOEXCEPT
|
||||
#endif
|
||||
|
||||
// NOTE: the FLATBUFFERS_DELETE_FUNC macro may change the access mode to
|
||||
// private, so be sure to put it at the end or reset access mode explicitly.
|
||||
#if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \
|
||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404))
|
||||
#define FLATBUFFERS_DELETE_FUNC(func) func = delete;
|
||||
#else
|
||||
#define FLATBUFFERS_DELETE_FUNC(func) private: func;
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4127) // C4127: conditional expression is constant
|
||||
#endif
|
||||
|
||||
/// @endcond
|
||||
|
||||
/// @file
|
||||
namespace flatbuffers {
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
// Our default offset / size type, 32bit on purpose on 64bit systems.
|
||||
// Also, using a consistent offset type maintains compatibility of serialized
|
||||
// offset values between 32bit and 64bit systems.
|
||||
typedef uint32_t uoffset_t;
|
||||
|
||||
// Signed offsets for references that can go in both directions.
|
||||
typedef int32_t soffset_t;
|
||||
|
||||
// Offset/index used in v-tables, can be changed to uint8_t in
|
||||
// format forks to save a bit of space if desired.
|
||||
typedef uint16_t voffset_t;
|
||||
|
||||
typedef uintmax_t largest_scalar_t;
|
||||
|
||||
// In 32bits, this evaluates to 2GB - 1
|
||||
#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(soffset_t) * 8 - 1)) - 1)
|
||||
|
||||
// We support aligning the contents of buffers up to this size.
|
||||
#define FLATBUFFERS_MAX_ALIGNMENT 16
|
||||
|
||||
template<typename T> T EndianScalar(T t) {
|
||||
#if FLATBUFFERS_LITTLEENDIAN
|
||||
return t;
|
||||
#else
|
||||
return EndianSwap(t);
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T> T ReadScalar(const void *p) {
|
||||
return EndianScalar(*reinterpret_cast<const T *>(p));
|
||||
}
|
||||
|
||||
template<typename T> void WriteScalar(void *p, T t) {
|
||||
*reinterpret_cast<T *>(p) = EndianScalar(t);
|
||||
}
|
||||
|
||||
// Computes how many bytes you'd have to pad to be able to write an
|
||||
// "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in
|
||||
// memory).
|
||||
inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
|
||||
return ((~buf_size) + 1) & (scalar_size - 1);
|
||||
}
|
||||
|
||||
}
|
||||
#endif // FLATBUFFERS_BASE_H_
|
||||
@@ -95,8 +95,6 @@ class BaseGenerator {
|
||||
|
||||
static const char *FlatBuffersGeneratedWarning();
|
||||
|
||||
bool IsEverythingGenerated() const;
|
||||
|
||||
static std::string FullNamespace(const char *separator, const Namespace &ns);
|
||||
|
||||
static std::string LastNamespacePart(const Namespace &ns);
|
||||
@@ -114,6 +112,8 @@ class BaseGenerator {
|
||||
|
||||
std::string WrapInNameSpace(const Definition &def) const;
|
||||
|
||||
std::string GetNameSpace(const Definition &def) const;
|
||||
|
||||
const Parser &parser_;
|
||||
const std::string &path_;
|
||||
const std::string &file_name_;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -42,6 +42,7 @@ class FlatCompiler {
|
||||
const char *generator_opt_short;
|
||||
const char *generator_opt_long;
|
||||
const char *lang_name;
|
||||
bool schema_only;
|
||||
GenerateFn generateGRPC;
|
||||
flatbuffers::IDLOptions::Language lang;
|
||||
const char *generator_help;
|
||||
|
||||
@@ -17,14 +17,19 @@
|
||||
#ifndef FLATBUFFERS_FLEXBUFFERS_H_
|
||||
#define FLATBUFFERS_FLEXBUFFERS_H_
|
||||
|
||||
#include <map>
|
||||
// We use the basic binary writing functions from the regular FlatBuffers.
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/util.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4127) // C4127: conditional expression is constant
|
||||
#endif
|
||||
|
||||
namespace flexbuffers {
|
||||
|
||||
class Reference;
|
||||
@@ -85,7 +90,7 @@ inline bool IsFixedTypedVector(Type t) {
|
||||
return t >= TYPE_VECTOR_INT2 && t <= TYPE_VECTOR_FLOAT4;
|
||||
}
|
||||
|
||||
inline Type ToTypedVector(Type t, int fixed_len = 0) {
|
||||
inline Type ToTypedVector(Type t, size_t fixed_len = 0) {
|
||||
assert(IsTypedVectorElementType(t));
|
||||
switch (fixed_len) {
|
||||
case 0: return static_cast<Type>(t - TYPE_INT + TYPE_VECTOR_INT);
|
||||
@@ -104,7 +109,7 @@ inline Type ToTypedVectorElementType(Type t) {
|
||||
inline Type ToFixedTypedVectorElementType(Type t, uint8_t *len) {
|
||||
assert(IsFixedTypedVector(t));
|
||||
auto fixed_type = t - TYPE_VECTOR_INT2;
|
||||
*len = fixed_type / 3 + 2; // 3 types each, starting from length 2.
|
||||
*len = static_cast<uint8_t>(fixed_type / 3 + 2); // 3 types each, starting from length 2.
|
||||
return static_cast<Type>(fixed_type % 3 + TYPE_INT);
|
||||
}
|
||||
|
||||
@@ -155,7 +160,7 @@ inline double ReadDouble(const uint8_t *data, uint8_t byte_width) {
|
||||
byte_width);
|
||||
}
|
||||
|
||||
const uint8_t *Indirect(const uint8_t *offset, uint8_t byte_width) {
|
||||
inline const uint8_t *Indirect(const uint8_t *offset, uint8_t byte_width) {
|
||||
return offset - ReadUInt64(offset, byte_width);
|
||||
}
|
||||
|
||||
@@ -163,7 +168,7 @@ template<typename T> const uint8_t *Indirect(const uint8_t *offset) {
|
||||
return offset - flatbuffers::ReadScalar<T>(offset);
|
||||
}
|
||||
|
||||
static BitWidth WidthU(uint64_t u) {
|
||||
inline BitWidth WidthU(uint64_t u) {
|
||||
#define FLATBUFFERS_GET_FIELD_BIT_WIDTH(value, width) { \
|
||||
if (!((u) & ~((1ULL << (width)) - 1ULL))) return BIT_WIDTH_##width; \
|
||||
}
|
||||
@@ -174,12 +179,12 @@ static BitWidth WidthU(uint64_t u) {
|
||||
return BIT_WIDTH_64;
|
||||
}
|
||||
|
||||
static BitWidth WidthI(int64_t i) {
|
||||
inline BitWidth WidthI(int64_t i) {
|
||||
auto u = static_cast<uint64_t>(i) << 1;
|
||||
return WidthU(i >= 0 ? u : ~u);
|
||||
}
|
||||
|
||||
static BitWidth WidthF(double f) {
|
||||
inline BitWidth WidthF(double f) {
|
||||
return static_cast<double>(static_cast<float>(f)) == f ? BIT_WIDTH_32
|
||||
: BIT_WIDTH_64;
|
||||
}
|
||||
@@ -212,6 +217,7 @@ class String : public Sized {
|
||||
|
||||
size_t length() const { return size(); }
|
||||
const char *c_str() const { return reinterpret_cast<const char *>(data_); }
|
||||
std::string str() const { return std::string(c_str(), length()); }
|
||||
|
||||
static String EmptyString() {
|
||||
static const uint8_t empty_string[] = { 0/*len*/, 0/*terminator*/ };
|
||||
@@ -451,25 +457,61 @@ class Reference {
|
||||
}
|
||||
|
||||
// Unlike AsString(), this will convert any type to a std::string.
|
||||
std::string ToString() const {
|
||||
std::string ToString() {
|
||||
std::string s;
|
||||
ToString(false, false, s);
|
||||
return s;
|
||||
}
|
||||
|
||||
// Convert any type to a JSON-like string. strings_quoted determines if
|
||||
// string values at the top level receive "" quotes (inside other values
|
||||
// they always do). keys_quoted determines if keys are quoted, at any level.
|
||||
// TODO(wvo): add further options to have indentation/newlines.
|
||||
void ToString(bool strings_quoted, bool keys_quoted, std::string &s) const {
|
||||
if (type_ == TYPE_STRING) {
|
||||
return String(Indirect(), byte_width_).c_str();
|
||||
String str(Indirect(), byte_width_);
|
||||
if (strings_quoted) {
|
||||
flatbuffers::EscapeString(str.c_str(), str.length(), &s, true);
|
||||
} else {
|
||||
s.append(str.c_str(), str.length());
|
||||
}
|
||||
} else if (IsKey()) {
|
||||
return AsKey();
|
||||
auto str = AsKey();
|
||||
if (keys_quoted) {
|
||||
flatbuffers::EscapeString(str, strlen(str), &s, true);
|
||||
} else {
|
||||
s += str;
|
||||
}
|
||||
} else if (IsInt()) {
|
||||
return flatbuffers::NumToString(AsInt64());
|
||||
s += flatbuffers::NumToString(AsInt64());
|
||||
} else if (IsUInt()) {
|
||||
return flatbuffers::NumToString(AsUInt64());
|
||||
s += flatbuffers::NumToString(AsUInt64());
|
||||
} else if (IsFloat()) {
|
||||
return flatbuffers::NumToString(AsDouble());
|
||||
s += flatbuffers::NumToString(AsDouble());
|
||||
} else if (IsNull()) {
|
||||
return "null";
|
||||
s += "null";
|
||||
} else if (IsMap()) {
|
||||
return "{..}"; // TODO: show elements.
|
||||
s += "{ ";
|
||||
auto m = AsMap();
|
||||
auto keys = m.Keys();
|
||||
auto vals = m.Values();
|
||||
for (size_t i = 0; i < keys.size(); i++) {
|
||||
keys[i].ToString(true, keys_quoted, s);
|
||||
s += ": ";
|
||||
vals[i].ToString(true, keys_quoted, s);
|
||||
if (i < keys.size() - 1) s += ", ";
|
||||
}
|
||||
s += " }";
|
||||
} else if (IsVector()) {
|
||||
return "[..]"; // TODO: show elements.
|
||||
s += "[ ";
|
||||
auto v = AsVector();
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i].ToString(true, keys_quoted, s);
|
||||
if (i < v.size() - 1) s += ", ";
|
||||
}
|
||||
s += " ]";
|
||||
} else {
|
||||
return "(?)";
|
||||
s += "(?)";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,7 +643,7 @@ class Reference {
|
||||
|
||||
template<typename T> bool Mutate(const uint8_t *dest, T t, size_t byte_width,
|
||||
BitWidth value_width) {
|
||||
auto fits = (1U << value_width) <= byte_width;
|
||||
auto fits = static_cast<size_t>(static_cast<size_t>(1U) << value_width) <= byte_width;
|
||||
if (fits) {
|
||||
t = flatbuffers::EndianScalar(t);
|
||||
memcpy(const_cast<uint8_t *>(dest), &t, byte_width);
|
||||
@@ -740,6 +782,17 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
return buf_;
|
||||
}
|
||||
|
||||
// Reset all state so we can re-use the buffer.
|
||||
void Clear() {
|
||||
buf_.clear();
|
||||
stack_.clear();
|
||||
finished_ = false;
|
||||
// flags_ remains as-is;
|
||||
force_min_bit_width_ = BIT_WIDTH_8;
|
||||
key_pool.clear();
|
||||
string_pool.clear();
|
||||
}
|
||||
|
||||
// All value constructing functions below have two versions: one that
|
||||
// takes a key (for placement inside a map) and one that doesn't (for inside
|
||||
// vectors and elsewhere).
|
||||
@@ -1072,7 +1125,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
auto byte_width = 1U << alignment;
|
||||
buf_.insert(buf_.end(), flatbuffers::PaddingBytes(buf_.size(), byte_width),
|
||||
0);
|
||||
return byte_width;
|
||||
return static_cast<uint8_t>(byte_width);
|
||||
}
|
||||
|
||||
void WriteBytes(const void *val, size_t size) {
|
||||
@@ -1081,8 +1134,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
reinterpret_cast<const uint8_t *>(val) + size);
|
||||
}
|
||||
|
||||
// For values T >= byte_width
|
||||
template<typename T> void Write(T val, uint8_t byte_width) {
|
||||
template<typename T> void Write(T val, size_t byte_width) {
|
||||
assert(sizeof(T) >= byte_width);
|
||||
val = flatbuffers::EndianScalar(val);
|
||||
WriteBytes(&val, byte_width);
|
||||
}
|
||||
@@ -1176,7 +1229,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
auto offset = offset_loc - u_;
|
||||
// Does it fit?
|
||||
auto bit_width = WidthU(offset);
|
||||
if (1U << bit_width == byte_width) return bit_width;
|
||||
if (static_cast<size_t>(static_cast<size_t>(1U) << bit_width) == byte_width)
|
||||
return bit_width;
|
||||
}
|
||||
assert(false); // Must match one of the sizes above.
|
||||
return BIT_WIDTH_64;
|
||||
@@ -1231,7 +1285,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
// TODO: instead of asserting, could write vector with larger elements
|
||||
// instead, though that would be wasteful.
|
||||
assert(WidthU(len) <= bit_width);
|
||||
if (!fixed) Write(len, byte_width);
|
||||
if (!fixed) Write<uint64_t>(len, byte_width);
|
||||
auto vloc = buf_.size();
|
||||
for (size_t i = 0; i < len; i++) Write(elems[i], byte_width);
|
||||
stack_.push_back(Value(static_cast<uint64_t>(vloc),
|
||||
@@ -1273,9 +1327,9 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
// Write vector. First the keys width/offset if available, and size.
|
||||
if (keys) {
|
||||
WriteOffset(keys->u_, byte_width);
|
||||
Write(1U << keys->min_bit_width_, byte_width);
|
||||
Write<uint64_t>(1ULL << keys->min_bit_width_, byte_width);
|
||||
}
|
||||
if (!fixed) Write(vec_len, byte_width);
|
||||
if (!fixed) Write<uint64_t>(vec_len, byte_width);
|
||||
// Then the actual data.
|
||||
auto vloc = buf_.size();
|
||||
for (size_t i = start; i < stack_.size(); i += step) {
|
||||
@@ -1338,4 +1392,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
|
||||
} // namespace flexbuffers
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // FLATBUFFERS_FLEXBUFFERS_H_
|
||||
|
||||
@@ -19,49 +19,234 @@
|
||||
|
||||
// Helper functionality to glue FlatBuffers and GRPC.
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "grpc++/support/byte_buffer.h"
|
||||
#include "grpc/byte_buffer_reader.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
namespace grpc {
|
||||
|
||||
// Message is a typed wrapper around a buffer that manages the underlying
|
||||
// `grpc_slice` and also provides flatbuffers-specific helpers such as `Verify`
|
||||
// and `GetRoot`. Since it is backed by a `grpc_slice`, the underlying buffer
|
||||
// is refcounted and ownership is be managed automatically.
|
||||
template <class T>
|
||||
class Message {
|
||||
public:
|
||||
Message() : slice_(grpc_empty_slice()) {}
|
||||
|
||||
Message(grpc_slice slice, bool add_ref)
|
||||
: slice_(add_ref ? grpc_slice_ref(slice) : slice) {}
|
||||
|
||||
Message &operator=(const Message &other) = delete;
|
||||
|
||||
Message(Message &&other) : slice_(other.slice_) {
|
||||
other.slice_ = grpc_empty_slice();
|
||||
}
|
||||
|
||||
Message(const Message &other) = delete;
|
||||
|
||||
Message &operator=(Message &&other) {
|
||||
grpc_slice_unref(slice_);
|
||||
slice_ = other.slice_;
|
||||
other.slice_ = grpc_empty_slice();
|
||||
return *this;
|
||||
}
|
||||
|
||||
~Message() { grpc_slice_unref(slice_); }
|
||||
|
||||
const uint8_t *mutable_data() const { return GRPC_SLICE_START_PTR(slice_); }
|
||||
|
||||
const uint8_t *data() const { return GRPC_SLICE_START_PTR(slice_); }
|
||||
|
||||
size_t size() const { return GRPC_SLICE_LENGTH(slice_); }
|
||||
|
||||
bool Verify() const {
|
||||
Verifier verifier(data(), size());
|
||||
return verifier.VerifyBuffer<T>(nullptr);
|
||||
}
|
||||
|
||||
T *GetMutableRoot() { return flatbuffers::GetMutableRoot<T>(mutable_data()); }
|
||||
|
||||
const T *GetRoot() const { return flatbuffers::GetRoot<T>(data()); }
|
||||
|
||||
// This is only intended for serializer use, or if you know what you're doing
|
||||
const grpc_slice &BorrowSlice() const { return slice_; }
|
||||
|
||||
private:
|
||||
grpc_slice slice_;
|
||||
};
|
||||
|
||||
class MessageBuilder;
|
||||
|
||||
// SliceAllocator is a gRPC-specific allocator that uses the `grpc_slice`
|
||||
// refcounted slices to manage memory ownership. This makes it easy and
|
||||
// efficient to transfer buffers to gRPC.
|
||||
class SliceAllocator : public Allocator {
|
||||
public:
|
||||
SliceAllocator() : slice_(grpc_empty_slice()) {}
|
||||
|
||||
SliceAllocator(const SliceAllocator &other) = delete;
|
||||
SliceAllocator &operator=(const SliceAllocator &other) = delete;
|
||||
|
||||
virtual ~SliceAllocator() { grpc_slice_unref(slice_); }
|
||||
|
||||
virtual uint8_t *allocate(size_t size) override {
|
||||
assert(GRPC_SLICE_IS_EMPTY(slice_));
|
||||
slice_ = grpc_slice_malloc(size);
|
||||
return GRPC_SLICE_START_PTR(slice_);
|
||||
}
|
||||
|
||||
virtual void deallocate(uint8_t *p, size_t size) override {
|
||||
assert(p == GRPC_SLICE_START_PTR(slice_));
|
||||
assert(size == GRPC_SLICE_LENGTH(slice_));
|
||||
grpc_slice_unref(slice_);
|
||||
slice_ = grpc_empty_slice();
|
||||
}
|
||||
|
||||
virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
|
||||
size_t new_size) override {
|
||||
assert(old_p == GRPC_SLICE_START_PTR(slice_));
|
||||
assert(old_size == GRPC_SLICE_LENGTH(slice_));
|
||||
assert(new_size > old_size);
|
||||
grpc_slice old_slice = slice_;
|
||||
grpc_slice new_slice = grpc_slice_malloc(new_size);
|
||||
uint8_t *new_p = GRPC_SLICE_START_PTR(new_slice);
|
||||
memcpy(new_p + (new_size - old_size), old_p, old_size);
|
||||
slice_ = new_slice;
|
||||
grpc_slice_unref(old_slice);
|
||||
return new_p;
|
||||
}
|
||||
|
||||
private:
|
||||
grpc_slice &get_slice(uint8_t *p, size_t size) {
|
||||
assert(p == GRPC_SLICE_START_PTR(slice_));
|
||||
assert(size == GRPC_SLICE_LENGTH(slice_));
|
||||
return slice_;
|
||||
}
|
||||
|
||||
grpc_slice slice_;
|
||||
|
||||
friend class MessageBuilder;
|
||||
};
|
||||
|
||||
// SliceAllocatorMember is a hack to ensure that the MessageBuilder's
|
||||
// slice_allocator_ member is constructed before the FlatBufferBuilder, since
|
||||
// the allocator is used in the FlatBufferBuilder ctor.
|
||||
namespace detail {
|
||||
struct SliceAllocatorMember {
|
||||
SliceAllocator slice_allocator_;
|
||||
};
|
||||
}
|
||||
|
||||
// MessageBuilder is a gRPC-specific FlatBufferBuilder that uses SliceAllocator
|
||||
// to allocate gRPC buffers.
|
||||
class MessageBuilder : private detail::SliceAllocatorMember,
|
||||
public FlatBufferBuilder {
|
||||
public:
|
||||
explicit MessageBuilder(uoffset_t initial_size = 1024)
|
||||
: FlatBufferBuilder(initial_size, &slice_allocator_, false) {}
|
||||
|
||||
MessageBuilder(const MessageBuilder &other) = delete;
|
||||
MessageBuilder &operator=(const MessageBuilder &other) = delete;
|
||||
|
||||
~MessageBuilder() {}
|
||||
|
||||
// GetMessage extracts the subslice of the buffer corresponding to the
|
||||
// flatbuffers-encoded region and wraps it in a `Message<T>` to handle buffer
|
||||
// ownership.
|
||||
template <class T>
|
||||
Message<T> GetMessage() {
|
||||
auto buf_data = buf_.buf(); // pointer to memory
|
||||
auto buf_size = buf_.capacity(); // size of memory
|
||||
auto msg_data = buf_.data(); // pointer to msg
|
||||
auto msg_size = buf_.size(); // size of msg
|
||||
// Do some sanity checks on data/size
|
||||
assert(msg_data);
|
||||
assert(msg_size);
|
||||
assert(msg_data >= buf_data);
|
||||
assert(msg_data + msg_size <= buf_data + buf_size);
|
||||
// Calculate offsets from the buffer start
|
||||
auto begin = msg_data - buf_data;
|
||||
auto end = begin + msg_size;
|
||||
// Get the slice we are working with (no refcount change)
|
||||
grpc_slice slice = slice_allocator_.get_slice(buf_data, buf_size);
|
||||
// Extract a subslice of the existing slice (increment refcount)
|
||||
grpc_slice subslice = grpc_slice_sub(slice, begin, end);
|
||||
// Wrap the subslice in a `Message<T>`, but don't increment refcount
|
||||
Message<T> msg(subslice, false);
|
||||
return msg;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
Message<T> ReleaseMessage() {
|
||||
Message<T> msg = GetMessage<T>();
|
||||
Reset();
|
||||
return msg;
|
||||
}
|
||||
|
||||
private:
|
||||
// SliceAllocator slice_allocator_; // part of SliceAllocatorMember
|
||||
};
|
||||
|
||||
} // namespace grpc
|
||||
} // namespace flatbuffers
|
||||
|
||||
namespace grpc {
|
||||
|
||||
template <class T>
|
||||
class SerializationTraits<T, typename std::enable_if<std::is_base_of<
|
||||
flatbuffers::BufferRefBase, T>::value>::type> {
|
||||
class SerializationTraits<flatbuffers::grpc::Message<T>> {
|
||||
public:
|
||||
// The type we're passing here is a BufferRef, which is already serialized
|
||||
// FlatBuffer data, which then gets passed to GRPC.
|
||||
static grpc::Status Serialize(const T& msg,
|
||||
grpc_byte_buffer **buffer,
|
||||
bool *own_buffer) {
|
||||
// TODO(wvo): make this work without copying.
|
||||
auto slice = gpr_slice_from_copied_buffer(
|
||||
reinterpret_cast<const char *>(msg.buf), msg.len);
|
||||
*buffer = grpc_raw_byte_buffer_create(&slice, 1);
|
||||
static grpc::Status Serialize(const flatbuffers::grpc::Message<T> &msg,
|
||||
grpc_byte_buffer **buffer, bool *own_buffer) {
|
||||
// We are passed in a `Message<T>`, which is a wrapper around a
|
||||
// `grpc_slice`. We extract it here using `BorrowSlice()`. The const cast
|
||||
// is necesary because the `grpc_raw_byte_buffer_create` func expects
|
||||
// non-const slices in order to increment their refcounts.
|
||||
grpc_slice *slice = const_cast<grpc_slice *>(&msg.BorrowSlice());
|
||||
// Now use `grpc_raw_byte_buffer_create` to package the single slice into a
|
||||
// `grpc_byte_buffer`, incrementing the refcount in the process.
|
||||
*buffer = grpc_raw_byte_buffer_create(slice, 1);
|
||||
*own_buffer = true;
|
||||
return grpc::Status();
|
||||
return grpc::Status::OK;
|
||||
}
|
||||
|
||||
// There is no de-serialization step in FlatBuffers, so we just receive
|
||||
// the data from GRPC.
|
||||
static grpc::Status Deserialize(grpc_byte_buffer *buffer, T *msg) {
|
||||
// TODO(wvo): make this more efficient / zero copy when possible.
|
||||
auto len = grpc_byte_buffer_length(buffer);
|
||||
msg->buf = reinterpret_cast<uint8_t *>(malloc(len));
|
||||
msg->len = static_cast<flatbuffers::uoffset_t>(len);
|
||||
msg->must_free = true;
|
||||
uint8_t *current = msg->buf;
|
||||
grpc_byte_buffer_reader reader;
|
||||
grpc_byte_buffer_reader_init(&reader, buffer);
|
||||
gpr_slice slice;
|
||||
while (grpc_byte_buffer_reader_next(&reader, &slice)) {
|
||||
memcpy(current, GPR_SLICE_START_PTR(slice), GPR_SLICE_LENGTH(slice));
|
||||
current += GPR_SLICE_LENGTH(slice);
|
||||
gpr_slice_unref(slice);
|
||||
// Deserialize by pulling the
|
||||
static grpc::Status Deserialize(grpc_byte_buffer *buffer,
|
||||
flatbuffers::grpc::Message<T> *msg) {
|
||||
if (!buffer) {
|
||||
return ::grpc::Status(::grpc::StatusCode::INTERNAL, "No payload");
|
||||
}
|
||||
// Check if this is a single uncompressed slice.
|
||||
if ((buffer->type == GRPC_BB_RAW) &&
|
||||
(buffer->data.raw.compression == GRPC_COMPRESS_NONE) &&
|
||||
(buffer->data.raw.slice_buffer.count == 1)) {
|
||||
// If it is, then we can reference the `grpc_slice` directly.
|
||||
grpc_slice slice = buffer->data.raw.slice_buffer.slices[0];
|
||||
// We wrap a `Message<T>` around the slice, incrementing the refcount.
|
||||
*msg = flatbuffers::grpc::Message<T>(slice, true);
|
||||
} else {
|
||||
// Otherwise, we need to use `grpc_byte_buffer_reader_readall` to read
|
||||
// `buffer` into a single contiguous `grpc_slice`. The gRPC reader gives
|
||||
// us back a new slice with the refcount already incremented.
|
||||
grpc_byte_buffer_reader reader;
|
||||
grpc_byte_buffer_reader_init(&reader, buffer);
|
||||
grpc_slice slice = grpc_byte_buffer_reader_readall(&reader);
|
||||
grpc_byte_buffer_reader_destroy(&reader);
|
||||
// We wrap a `Message<T>` around the slice, but dont increment refcount
|
||||
*msg = flatbuffers::grpc::Message<T>(slice, false);
|
||||
}
|
||||
GPR_ASSERT(current == msg->buf + msg->len);
|
||||
grpc_byte_buffer_reader_destroy(&reader);
|
||||
grpc_byte_buffer_destroy(buffer);
|
||||
return grpc::Status();
|
||||
#if FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
|
||||
return ::grpc::Status::OK;
|
||||
#else
|
||||
if (msg->Verify()) {
|
||||
return ::grpc::Status::OK;
|
||||
} else {
|
||||
return ::grpc::Status(::grpc::StatusCode::INTERNAL,
|
||||
"Message verification failed");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/hash.h"
|
||||
#include "flatbuffers/reflection.h"
|
||||
#include "flatbuffers/flexbuffers.h"
|
||||
|
||||
// This file defines the data types representing a parsed IDL (Interface
|
||||
// Definition Language) / schema file.
|
||||
@@ -226,18 +227,20 @@ struct Definition {
|
||||
};
|
||||
|
||||
struct FieldDef : public Definition {
|
||||
FieldDef() : deprecated(false), required(false), key(false), padding(0) {}
|
||||
FieldDef() : deprecated(false), required(false), key(false),
|
||||
flexbuffer(false), padding(0) {}
|
||||
|
||||
Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
|
||||
const Parser &parser) const;
|
||||
|
||||
Value value;
|
||||
bool deprecated; // Field is allowed to be present in old data, but can't be
|
||||
bool deprecated; // Field is allowed to be present in old data, but can't be.
|
||||
// written in new data nor accessed in new code.
|
||||
bool required; // Field must always be present.
|
||||
bool key; // Field functions as a key for creating sorted vectors.
|
||||
bool native_inline; // Field will be defined inline (instead of as a pointer)
|
||||
// for native tables if field is a struct.
|
||||
bool flexbuffer; // This field contains FlexBuffer data.
|
||||
size_t padding; // Bytes to always pad after this field.
|
||||
};
|
||||
|
||||
@@ -283,18 +286,18 @@ inline size_t InlineAlignment(const Type &type) {
|
||||
|
||||
struct EnumVal {
|
||||
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;
|
||||
|
||||
std::string name;
|
||||
std::vector<std::string> doc_comment;
|
||||
int64_t value;
|
||||
StructDef *struct_def; // only set if this is a union
|
||||
Type union_type;
|
||||
};
|
||||
|
||||
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) {
|
||||
for (auto it = vals.vec.begin() + static_cast<int>(is_union &&
|
||||
@@ -312,6 +315,7 @@ struct EnumDef : public Definition {
|
||||
|
||||
SymbolTable<EnumVal> vals;
|
||||
bool is_union;
|
||||
bool uses_type_aliases;
|
||||
Type underlying_type;
|
||||
};
|
||||
|
||||
@@ -353,10 +357,16 @@ struct IDLOptions {
|
||||
bool escape_proto_identifiers;
|
||||
bool generate_object_based_api;
|
||||
std::string cpp_object_api_pointer_type;
|
||||
std::string cpp_object_api_string_type;
|
||||
bool union_value_namespacing;
|
||||
bool allow_non_utf8;
|
||||
std::string include_prefix;
|
||||
bool keep_include_path;
|
||||
bool binary_schema_comments;
|
||||
bool skip_flatbuffers_import;
|
||||
std::string go_namespace;
|
||||
bool reexport_ts_modules;
|
||||
bool protobuf_ascii_alike;
|
||||
|
||||
// Possible options for the more general generator below.
|
||||
enum Language {
|
||||
@@ -369,6 +379,7 @@ struct IDLOptions {
|
||||
kPhp = 1 << 6,
|
||||
kJson = 1 << 7,
|
||||
kBinary = 1 << 8,
|
||||
kTs = 1 << 9,
|
||||
kMAX
|
||||
};
|
||||
|
||||
@@ -397,7 +408,11 @@ struct IDLOptions {
|
||||
cpp_object_api_pointer_type("std::unique_ptr"),
|
||||
union_value_namespacing(true),
|
||||
allow_non_utf8(false),
|
||||
keep_include_path(false),
|
||||
binary_schema_comments(false),
|
||||
skip_flatbuffers_import(false),
|
||||
reexport_ts_modules(true),
|
||||
protobuf_ascii_alike(false),
|
||||
lang(IDLOptions::kJava),
|
||||
lang_to_generate(0) {}
|
||||
};
|
||||
@@ -461,6 +476,7 @@ class Parser : public ParserState {
|
||||
explicit Parser(const IDLOptions &options = IDLOptions())
|
||||
: root_struct_def_(nullptr),
|
||||
opts(options),
|
||||
uses_flexbuffers_(false),
|
||||
source_(nullptr),
|
||||
anonymous_counter(0) {
|
||||
// Just in case none are declared:
|
||||
@@ -479,9 +495,11 @@ class Parser : public ParserState {
|
||||
known_attributes_["idempotent"] = true;
|
||||
known_attributes_["cpp_type"] = true;
|
||||
known_attributes_["cpp_ptr_type"] = true;
|
||||
known_attributes_["cpp_str_type"] = true;
|
||||
known_attributes_["native_inline"] = true;
|
||||
known_attributes_["native_type"] = true;
|
||||
known_attributes_["native_default"] = true;
|
||||
known_attributes_["flexbuffer"] = true;
|
||||
}
|
||||
|
||||
~Parser() {
|
||||
@@ -499,6 +517,8 @@ class Parser : public ParserState {
|
||||
// directory.
|
||||
// If the source was loaded from a file and isn't an include file,
|
||||
// supply its name in source_filename.
|
||||
// All paths specified in this call must be in posix format, if you accept
|
||||
// paths from user input, please call PosixPath on them first.
|
||||
bool Parse(const char *_source, const char **include_paths = nullptr,
|
||||
const char *source_filename = nullptr);
|
||||
|
||||
@@ -521,7 +541,12 @@ class Parser : public ParserState {
|
||||
// of the schema provided. Returns non-empty error on any problems.
|
||||
std::string ConformTo(const Parser &base);
|
||||
|
||||
FLATBUFFERS_CHECKED_ERROR CheckBitsFit(int64_t val, size_t bits);
|
||||
// Similar to Parse(), but now only accepts JSON to be parsed into a
|
||||
// FlexBuffer.
|
||||
bool ParseFlexBuffer(const char *source, const char *source_filename,
|
||||
flexbuffers::Builder *builder);
|
||||
|
||||
FLATBUFFERS_CHECKED_ERROR CheckInRange(int64_t val, int64_t min, int64_t max);
|
||||
|
||||
private:
|
||||
FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
|
||||
@@ -540,18 +565,26 @@ private:
|
||||
const std::string &name, const Type &type,
|
||||
FieldDef **dest);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseString(Value &val);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseComma();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
|
||||
size_t parent_fieldn,
|
||||
const StructDef *parent_struct_def);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
|
||||
const StructDef *struct_def,
|
||||
const std::function<CheckedError(const std::string &name)> &body);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
|
||||
std::string *value, uoffset_t *ovalue);
|
||||
void SerializeStruct(const StructDef &struct_def, const Value &val);
|
||||
void AddVector(bool sortbysize, int count);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(size_t &count,
|
||||
const std::function<CheckedError()> &body);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
|
||||
FLATBUFFERS_CHECKED_ERROR TryTypedValue(int dtoken, bool check, Value &e,
|
||||
BaseType req, bool *destmatch);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef* field);
|
||||
FLATBUFFERS_CHECKED_ERROR TokenError();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseSingleValue(Value &e);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(Type &type, int64_t *result);
|
||||
StructDef *LookupCreateStruct(const std::string &name,
|
||||
@@ -571,12 +604,13 @@ private:
|
||||
FLATBUFFERS_CHECKED_ERROR ParseProtoCurliesOrIdent();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseTypeFromProtoType(Type *type);
|
||||
FLATBUFFERS_CHECKED_ERROR SkipAnyJsonValue();
|
||||
FLATBUFFERS_CHECKED_ERROR SkipJsonObject();
|
||||
FLATBUFFERS_CHECKED_ERROR SkipJsonArray();
|
||||
FLATBUFFERS_CHECKED_ERROR SkipJsonString();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder);
|
||||
FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source,
|
||||
const char *source_filename);
|
||||
FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
|
||||
const char **include_paths,
|
||||
const char *source_filename);
|
||||
const char *source_filename,
|
||||
const char *include_filename);
|
||||
FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef*> &fields,
|
||||
StructDef *struct_def,
|
||||
const char *suffix,
|
||||
@@ -595,13 +629,14 @@ private:
|
||||
std::string file_identifier_;
|
||||
std::string file_extension_;
|
||||
|
||||
std::map<std::string, bool> included_files_;
|
||||
std::map<std::string, std::string> included_files_;
|
||||
std::map<std::string, std::set<std::string>> files_included_per_file_;
|
||||
std::vector<std::string> native_included_files_;
|
||||
|
||||
std::map<std::string, bool> known_attributes_;
|
||||
|
||||
IDLOptions opts;
|
||||
bool uses_flexbuffers_;
|
||||
|
||||
private:
|
||||
const char *source_;
|
||||
@@ -647,7 +682,7 @@ extern bool GenerateCPP(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate JavaScript code from the definitions in the Parser object.
|
||||
// Generate JavaScript or TypeScript code from the definitions in the Parser object.
|
||||
// See idl_gen_js.
|
||||
extern std::string GenerateJS(const Parser &parser);
|
||||
extern bool GenerateJS(const Parser &parser,
|
||||
@@ -698,7 +733,7 @@ extern bool GenerateFBS(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated JavaScript code.
|
||||
// Generate a make rule for the generated JavaScript or TypeScript code.
|
||||
// See idl_gen_js.cpp.
|
||||
extern std::string JSMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
@@ -743,4 +778,3 @@ bool GenerateGoGRPC(const Parser &parser,
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_IDL_H_
|
||||
|
||||
|
||||
@@ -30,6 +30,15 @@ namespace flatbuffers {
|
||||
|
||||
// ------------------------- GETTERS -------------------------
|
||||
|
||||
inline bool IsScalar (reflection::BaseType t) { return t >= reflection::UType &&
|
||||
t <= reflection::Double; }
|
||||
inline bool IsInteger(reflection::BaseType t) { return t >= reflection::UType &&
|
||||
t <= reflection::ULong; }
|
||||
inline bool IsFloat (reflection::BaseType t) { return t == reflection::Float ||
|
||||
t == reflection::Double; }
|
||||
inline bool IsLong (reflection::BaseType t) { return t == reflection::Long ||
|
||||
t == reflection::ULong; }
|
||||
|
||||
// Size of a basic type, don't use with structs.
|
||||
inline size_t GetTypeSize(reflection::BaseType base_type) {
|
||||
// This needs to correspond to the BaseType enum.
|
||||
@@ -58,6 +67,18 @@ inline const Table *GetAnyRoot(const uint8_t *flatbuf) {
|
||||
return GetRoot<Table>(flatbuf);
|
||||
}
|
||||
|
||||
// Get a field's default, if you know it's an integer, and its exact type.
|
||||
template<typename T> T GetFieldDefaultI(const reflection::Field &field) {
|
||||
assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
||||
return static_cast<T>(field.default_integer());
|
||||
}
|
||||
|
||||
// Get a field's default, if you know it's floating point and its exact type.
|
||||
template<typename T> T GetFieldDefaultF(const reflection::Field &field) {
|
||||
assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
||||
return static_cast<T>(field.default_real());
|
||||
}
|
||||
|
||||
// Get a field, if you know it's an integer, and its exact type.
|
||||
template<typename T> T GetFieldI(const Table &table,
|
||||
const reflection::Field &field) {
|
||||
@@ -242,8 +263,19 @@ template<typename T> T *GetAnyFieldAddressOf(const Struct &st,
|
||||
// Set any scalar field, if you know its exact type.
|
||||
template<typename T> bool SetField(Table *table, const reflection::Field &field,
|
||||
T val) {
|
||||
assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
||||
return table->SetField(field.offset(), val);
|
||||
reflection::BaseType type = field.type()->base_type();
|
||||
if (!IsScalar(type)) {
|
||||
return false;
|
||||
}
|
||||
assert(sizeof(T) == GetTypeSize(type));
|
||||
T def;
|
||||
if (IsInteger(type)) {
|
||||
def = GetFieldDefaultI<T>(field);
|
||||
} else {
|
||||
assert(IsFloat(type));
|
||||
def = GetFieldDefaultF<T>(field);
|
||||
}
|
||||
return table->SetField(field.offset(), val, def);
|
||||
}
|
||||
|
||||
// Raw helper functions used below: set any value in memory as a 64bit int, a
|
||||
@@ -258,7 +290,7 @@ void SetAnyValueS(reflection::BaseType type, uint8_t *data, const char *val);
|
||||
inline bool SetAnyFieldI(Table *table, const reflection::Field &field,
|
||||
int64_t val) {
|
||||
auto field_ptr = table->GetAddressOf(field.offset());
|
||||
if (!field_ptr) return false;
|
||||
if (!field_ptr) return val == GetFieldDefaultI<int64_t>(field);
|
||||
SetAnyValueI(field.type()->base_type(), field_ptr, val);
|
||||
return true;
|
||||
}
|
||||
@@ -267,7 +299,7 @@ inline bool SetAnyFieldI(Table *table, const reflection::Field &field,
|
||||
inline bool SetAnyFieldF(Table *table, const reflection::Field &field,
|
||||
double val) {
|
||||
auto field_ptr = table->GetAddressOf(field.offset());
|
||||
if (!field_ptr) return false;
|
||||
if (!field_ptr) return val == GetFieldDefaultF<double>(field);
|
||||
SetAnyValueF(field.type()->base_type(), field_ptr, val);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -150,9 +150,9 @@ struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_KEY) &&
|
||||
VerifyOffsetRequired(verifier, VT_KEY) &&
|
||||
verifier.Verify(key()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) &&
|
||||
VerifyOffset(verifier, VT_VALUE) &&
|
||||
verifier.Verify(value()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
@@ -204,7 +204,8 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum {
|
||||
VT_NAME = 4,
|
||||
VT_VALUE = 6,
|
||||
VT_OBJECT = 8
|
||||
VT_OBJECT = 8,
|
||||
VT_UNION_TYPE = 10
|
||||
};
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
@@ -228,13 +229,18 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
const Object *object() const {
|
||||
return GetPointer<const Object *>(VT_OBJECT);
|
||||
}
|
||||
const Type *union_type() const {
|
||||
return GetPointer<const Type *>(VT_UNION_TYPE);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
|
||||
VerifyOffsetRequired(verifier, VT_NAME) &&
|
||||
verifier.Verify(name()) &&
|
||||
VerifyField<int64_t>(verifier, VT_VALUE) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_OBJECT) &&
|
||||
VerifyOffset(verifier, VT_OBJECT) &&
|
||||
verifier.VerifyTable(object()) &&
|
||||
VerifyOffset(verifier, VT_UNION_TYPE) &&
|
||||
verifier.VerifyTable(union_type()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
@@ -251,13 +257,16 @@ struct EnumValBuilder {
|
||||
void add_object(flatbuffers::Offset<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)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
EnumValBuilder &operator=(const EnumValBuilder &);
|
||||
flatbuffers::Offset<EnumVal> Finish() {
|
||||
const auto end = fbb_.EndTable(start_, 3);
|
||||
const auto end = fbb_.EndTable(start_, 4);
|
||||
auto o = flatbuffers::Offset<EnumVal>(end);
|
||||
fbb_.Required(o, EnumVal::VT_NAME);
|
||||
return o;
|
||||
@@ -268,9 +277,11 @@ inline flatbuffers::Offset<EnumVal> CreateEnumVal(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
int64_t value = 0,
|
||||
flatbuffers::Offset<Object> object = 0) {
|
||||
flatbuffers::Offset<Object> object = 0,
|
||||
flatbuffers::Offset<Type> union_type = 0) {
|
||||
EnumValBuilder builder_(_fbb);
|
||||
builder_.add_value(value);
|
||||
builder_.add_union_type(union_type);
|
||||
builder_.add_object(object);
|
||||
builder_.add_name(name);
|
||||
return builder_.Finish();
|
||||
@@ -280,12 +291,14 @@ inline flatbuffers::Offset<EnumVal> CreateEnumValDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
int64_t value = 0,
|
||||
flatbuffers::Offset<Object> object = 0) {
|
||||
flatbuffers::Offset<Object> object = 0,
|
||||
flatbuffers::Offset<Type> union_type = 0) {
|
||||
return reflection::CreateEnumVal(
|
||||
_fbb,
|
||||
name ? _fbb.CreateString(name) : 0,
|
||||
value,
|
||||
object);
|
||||
object,
|
||||
union_type);
|
||||
}
|
||||
|
||||
struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
@@ -323,18 +336,18 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
|
||||
VerifyOffsetRequired(verifier, VT_NAME) &&
|
||||
verifier.Verify(name()) &&
|
||||
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_VALUES) &&
|
||||
VerifyOffsetRequired(verifier, VT_VALUES) &&
|
||||
verifier.Verify(values()) &&
|
||||
verifier.VerifyVectorOfTables(values()) &&
|
||||
VerifyField<uint8_t>(verifier, VT_IS_UNION) &&
|
||||
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_UNDERLYING_TYPE) &&
|
||||
VerifyOffsetRequired(verifier, VT_UNDERLYING_TYPE) &&
|
||||
verifier.VerifyTable(underlying_type()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_ATTRIBUTES) &&
|
||||
VerifyOffset(verifier, VT_ATTRIBUTES) &&
|
||||
verifier.Verify(attributes()) &&
|
||||
verifier.VerifyVectorOfTables(attributes()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_DOCUMENTATION) &&
|
||||
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
||||
verifier.Verify(documentation()) &&
|
||||
verifier.VerifyVectorOfStrings(documentation()) &&
|
||||
verifier.EndTable();
|
||||
@@ -468,9 +481,9 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
|
||||
VerifyOffsetRequired(verifier, VT_NAME) &&
|
||||
verifier.Verify(name()) &&
|
||||
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_TYPE) &&
|
||||
VerifyOffsetRequired(verifier, VT_TYPE) &&
|
||||
verifier.VerifyTable(type()) &&
|
||||
VerifyField<uint16_t>(verifier, VT_ID) &&
|
||||
VerifyField<uint16_t>(verifier, VT_OFFSET) &&
|
||||
@@ -479,10 +492,10 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VerifyField<uint8_t>(verifier, VT_DEPRECATED) &&
|
||||
VerifyField<uint8_t>(verifier, VT_REQUIRED) &&
|
||||
VerifyField<uint8_t>(verifier, VT_KEY) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_ATTRIBUTES) &&
|
||||
VerifyOffset(verifier, VT_ATTRIBUTES) &&
|
||||
verifier.Verify(attributes()) &&
|
||||
verifier.VerifyVectorOfTables(attributes()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_DOCUMENTATION) &&
|
||||
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
||||
verifier.Verify(documentation()) &&
|
||||
verifier.VerifyVectorOfStrings(documentation()) &&
|
||||
verifier.EndTable();
|
||||
@@ -634,18 +647,18 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
|
||||
VerifyOffsetRequired(verifier, VT_NAME) &&
|
||||
verifier.Verify(name()) &&
|
||||
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_FIELDS) &&
|
||||
VerifyOffsetRequired(verifier, VT_FIELDS) &&
|
||||
verifier.Verify(fields()) &&
|
||||
verifier.VerifyVectorOfTables(fields()) &&
|
||||
VerifyField<uint8_t>(verifier, VT_IS_STRUCT) &&
|
||||
VerifyField<int32_t>(verifier, VT_MINALIGN) &&
|
||||
VerifyField<int32_t>(verifier, VT_BYTESIZE) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_ATTRIBUTES) &&
|
||||
VerifyOffset(verifier, VT_ATTRIBUTES) &&
|
||||
verifier.Verify(attributes()) &&
|
||||
verifier.VerifyVectorOfTables(attributes()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_DOCUMENTATION) &&
|
||||
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
||||
verifier.Verify(documentation()) &&
|
||||
verifier.VerifyVectorOfStrings(documentation()) &&
|
||||
verifier.EndTable();
|
||||
@@ -755,17 +768,17 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_OBJECTS) &&
|
||||
VerifyOffsetRequired(verifier, VT_OBJECTS) &&
|
||||
verifier.Verify(objects()) &&
|
||||
verifier.VerifyVectorOfTables(objects()) &&
|
||||
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_ENUMS) &&
|
||||
VerifyOffsetRequired(verifier, VT_ENUMS) &&
|
||||
verifier.Verify(enums()) &&
|
||||
verifier.VerifyVectorOfTables(enums()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_FILE_IDENT) &&
|
||||
VerifyOffset(verifier, VT_FILE_IDENT) &&
|
||||
verifier.Verify(file_ident()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_FILE_EXT) &&
|
||||
VerifyOffset(verifier, VT_FILE_EXT) &&
|
||||
verifier.Verify(file_ext()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_ROOT_TABLE) &&
|
||||
VerifyOffset(verifier, VT_ROOT_TABLE) &&
|
||||
verifier.VerifyTable(root_table()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
|
||||
131
include/flatbuffers/registry.h
Normal file
131
include/flatbuffers/registry.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_REGISTRY_H_
|
||||
#define FLATBUFFERS_REGISTRY_H_
|
||||
|
||||
#include "flatbuffers/idl.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// Convenience class to easily parse or generate text for arbitrary FlatBuffers.
|
||||
// Simply pre-populate it with all schema filenames that may be in use, and
|
||||
// This class will look them up using the file_identifier declared in the
|
||||
// schema.
|
||||
class Registry {
|
||||
public:
|
||||
// Call this for all schemas that may be in use. The identifier has
|
||||
// a function in the generated code, e.g. MonsterIdentifier().
|
||||
void Register(const char *file_identifier, const char *schema_path) {
|
||||
Schema schema;
|
||||
schema.path_ = schema_path;
|
||||
schemas_[file_identifier] = schema;
|
||||
}
|
||||
|
||||
// Generate text from an arbitrary FlatBuffer by looking up its
|
||||
// file_identifier in the registry.
|
||||
bool FlatBufferToText(const uint8_t *flatbuf, size_t len,
|
||||
std::string *dest) {
|
||||
// Get the identifier out of the buffer.
|
||||
// If the buffer is truncated, exit.
|
||||
if (len < sizeof(uoffset_t) +
|
||||
FlatBufferBuilder::kFileIdentifierLength) {
|
||||
lasterror_ = "buffer truncated";
|
||||
return false;
|
||||
}
|
||||
std::string ident(reinterpret_cast<const char *>(flatbuf) +
|
||||
sizeof(uoffset_t),
|
||||
FlatBufferBuilder::kFileIdentifierLength);
|
||||
// Load and parse the schema.
|
||||
Parser parser;
|
||||
if (!LoadSchema(ident, &parser)) return false;
|
||||
// Now we're ready to generate text.
|
||||
if (!GenerateText(parser, flatbuf, dest)) {
|
||||
lasterror_ = "unable to generate text for FlatBuffer binary";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Converts a binary buffer to text using one of the schemas in the registry,
|
||||
// use the file_identifier to indicate which.
|
||||
// If DetachedBuffer::data() is null then parsing failed.
|
||||
DetachedBuffer TextToFlatBuffer(const char *text,
|
||||
const char *file_identifier) {
|
||||
// Load and parse the schema.
|
||||
Parser parser;
|
||||
if (!LoadSchema(file_identifier, &parser)) return DetachedBuffer();
|
||||
// Parse the text.
|
||||
if (!parser.Parse(text)) {
|
||||
lasterror_ = parser.error_;
|
||||
return DetachedBuffer();
|
||||
}
|
||||
// We have a valid FlatBuffer. Detach it from the builder and return.
|
||||
return parser.builder_.ReleaseBufferPointer();
|
||||
}
|
||||
|
||||
// Modify any parsing / output options used by the other functions.
|
||||
void SetOptions(const IDLOptions &opts) { opts_ = opts; }
|
||||
|
||||
// If schemas used contain include statements, call this function for every
|
||||
// directory the parser should search them for.
|
||||
void AddIncludeDirectory(const char *path) {
|
||||
include_paths_.push_back(path);
|
||||
}
|
||||
|
||||
// Returns a human readable error if any of the above functions fail.
|
||||
const std::string &GetLastError() { return lasterror_; }
|
||||
|
||||
private:
|
||||
bool LoadSchema(const std::string &ident, Parser *parser) {
|
||||
// Find the schema, if not, exit.
|
||||
auto it = schemas_.find(ident);
|
||||
if (it == schemas_.end()) {
|
||||
// Don't attach the identifier, since it may not be human readable.
|
||||
lasterror_ = "identifier for this buffer not in the registry";
|
||||
return false;
|
||||
}
|
||||
auto &schema = it->second;
|
||||
// Load the schema from disk. If not, exit.
|
||||
std::string schematext;
|
||||
if (!LoadFile(schema.path_.c_str(), false, &schematext)) {
|
||||
lasterror_ = "could not load schema: " + schema.path_;
|
||||
return false;
|
||||
}
|
||||
// Parse schema.
|
||||
parser->opts = opts_;
|
||||
if (!parser->Parse(schematext.c_str(), include_paths_.data(),
|
||||
schema.path_.c_str())) {
|
||||
lasterror_ = parser->error_;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
struct Schema {
|
||||
std::string path_;
|
||||
// TODO(wvo) optionally cache schema file or parsed schema here.
|
||||
};
|
||||
|
||||
std::string lasterror_;
|
||||
IDLOptions opts_;
|
||||
std::vector<const char *> include_paths_;
|
||||
std::map<std::string, Schema> schemas_;
|
||||
};
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_REGISTRY_H_
|
||||
@@ -40,7 +40,8 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/base.h"
|
||||
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
@@ -71,9 +72,8 @@ template<> inline std::string NumToString<double>(double t) {
|
||||
// Sadly, std::fixed turns "1" into "1.00000", so here we undo that.
|
||||
auto p = s.find_last_not_of('0');
|
||||
if (p != std::string::npos) {
|
||||
s.resize(p + 1); // Strip trailing zeroes.
|
||||
if (s[s.size() - 1] == '.')
|
||||
s.erase(s.size() - 1, 1); // Strip '.' if a whole number.
|
||||
// Strip trailing zeroes. If it is a whole number, keep one zero.
|
||||
s.resize(p + (s[p] == '.' ? 2 : 1));
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -157,16 +157,20 @@ inline bool SaveFile(const char *name, const std::string &buf, bool binary) {
|
||||
return SaveFile(name, buf.c_str(), buf.size(), binary);
|
||||
}
|
||||
|
||||
// Functionality for minimalistic portable path handling:
|
||||
// Functionality for minimalistic portable path handling.
|
||||
|
||||
static const char kPosixPathSeparator = '/';
|
||||
#ifdef _WIN32
|
||||
static const char kPathSeparator = '\\';
|
||||
// The functions below behave correctly regardless of whether posix ('/') or
|
||||
// Windows ('/' or '\\') separators are used.
|
||||
|
||||
// Any new separators inserted are always posix.
|
||||
|
||||
// We internally store paths in posix format ('/'). Paths supplied
|
||||
// by the user should go through PosixPath to ensure correct behavior
|
||||
// on Windows when paths are string-compared.
|
||||
|
||||
static const char kPathSeparator = '/';
|
||||
static const char kPathSeparatorWindows = '\\';
|
||||
static const char *PathSeparatorSet = "\\/"; // Intentionally no ':'
|
||||
#else
|
||||
static const char kPathSeparator = kPosixPathSeparator;
|
||||
static const char *PathSeparatorSet = "/";
|
||||
#endif // _WIN32
|
||||
|
||||
// Returns the path with the extension, if any, removed.
|
||||
inline std::string StripExtension(const std::string &filepath) {
|
||||
@@ -197,13 +201,24 @@ inline std::string StripFileName(const std::string &filepath) {
|
||||
inline std::string ConCatPathFileName(const std::string &path,
|
||||
const std::string &filename) {
|
||||
std::string filepath = path;
|
||||
if (path.length() && path[path.size() - 1] != kPathSeparator &&
|
||||
path[path.size() - 1] != kPosixPathSeparator)
|
||||
filepath += kPathSeparator;
|
||||
if (filepath.length()) {
|
||||
if (filepath.back() == kPathSeparatorWindows) {
|
||||
filepath.back() = kPathSeparator;
|
||||
} else if (filepath.back() != kPathSeparator) {
|
||||
filepath += kPathSeparator;
|
||||
}
|
||||
}
|
||||
filepath += filename;
|
||||
return filepath;
|
||||
}
|
||||
|
||||
// Replaces any '\\' separators with '/'
|
||||
inline std::string PosixPath(const char *path) {
|
||||
std::string p = path;
|
||||
std::replace(p.begin(), p.end(), '\\', '/');
|
||||
return p;
|
||||
}
|
||||
|
||||
// This function ensure a directory exists, by recursively
|
||||
// creating dirs for any parts of the path that don't exist yet.
|
||||
inline void EnsureDirExists(const std::string &filepath) {
|
||||
@@ -345,6 +360,72 @@ inline std::string WordWrap(const std::string in, size_t max_length,
|
||||
return wrapped;
|
||||
}
|
||||
|
||||
inline bool EscapeString(const char *s, size_t length, std::string *_text,
|
||||
bool allow_non_utf8) {
|
||||
std::string &text = *_text;
|
||||
text += "\"";
|
||||
for (uoffset_t i = 0; i < length; i++) {
|
||||
char c = s[i];
|
||||
switch (c) {
|
||||
case '\n': text += "\\n"; break;
|
||||
case '\t': text += "\\t"; break;
|
||||
case '\r': text += "\\r"; break;
|
||||
case '\b': text += "\\b"; break;
|
||||
case '\f': text += "\\f"; break;
|
||||
case '\"': text += "\\\""; break;
|
||||
case '\\': text += "\\\\"; break;
|
||||
default:
|
||||
if (c >= ' ' && c <= '~') {
|
||||
text += c;
|
||||
} else {
|
||||
// Not printable ASCII data. Let's see if it's valid UTF-8 first:
|
||||
const char *utf8 = s + i;
|
||||
int ucc = FromUTF8(&utf8);
|
||||
if (ucc < 0) {
|
||||
if (allow_non_utf8) {
|
||||
text += "\\x";
|
||||
text += IntToStringHex(static_cast<uint8_t>(c), 2);
|
||||
} else {
|
||||
// There are two cases here:
|
||||
//
|
||||
// 1) We reached here by parsing an IDL file. In that case,
|
||||
// we previously checked for non-UTF-8, so we shouldn't reach
|
||||
// here.
|
||||
//
|
||||
// 2) We reached here by someone calling GenerateText()
|
||||
// on a previously-serialized flatbuffer. The data might have
|
||||
// non-UTF-8 Strings, or might be corrupt.
|
||||
//
|
||||
// In both cases, we have to give up and inform the caller
|
||||
// they have no JSON.
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (ucc <= 0xFFFF) {
|
||||
// Parses as Unicode within JSON's \uXXXX range, so use that.
|
||||
text += "\\u";
|
||||
text += IntToStringHex(ucc, 4);
|
||||
} else if (ucc <= 0x10FFFF) {
|
||||
// Encode Unicode SMP values to a surrogate pair using two \u escapes.
|
||||
uint32_t base = ucc - 0x10000;
|
||||
auto high_surrogate = (base >> 10) + 0xD800;
|
||||
auto low_surrogate = (base & 0x03FF) + 0xDC00;
|
||||
text += "\\u";
|
||||
text += IntToStringHex(high_surrogate, 4);
|
||||
text += "\\u";
|
||||
text += IntToStringHex(low_surrogate, 4);
|
||||
}
|
||||
// Skip past characters recognized.
|
||||
i = static_cast<uoffset_t>(utf8 - s - 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
text += "\"";
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_UTIL_H_
|
||||
|
||||
@@ -106,6 +106,22 @@ public class FlatBufferBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the FlatBufferBuilder by purging all data that it holds.
|
||||
*/
|
||||
public void clear(){
|
||||
space = bb.capacity();
|
||||
bb.clear();
|
||||
minalign = 1;
|
||||
while(vtable_in_use > 0) vtable[--vtable_in_use] = 0;
|
||||
vtable_in_use = 0;
|
||||
nested = false;
|
||||
finished = false;
|
||||
object_start = 0;
|
||||
num_vtables = 0;
|
||||
vector_num_elems = 0;
|
||||
}
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
/**
|
||||
* Create a `ByteBuffer` with a given capacity.
|
||||
|
||||
@@ -115,7 +115,7 @@ flatbuffers.Long.create = function(low, high) {
|
||||
* @returns {number}
|
||||
*/
|
||||
flatbuffers.Long.prototype.toFloat64 = function() {
|
||||
return this.low + this.high * 0x100000000;
|
||||
return (this.low >>> 0) + this.high * 0x100000000;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -944,9 +944,17 @@ flatbuffers.ByteBuffer.prototype.readFloat64 = function(offset) {
|
||||
|
||||
/**
|
||||
* @param {number} offset
|
||||
* @param {number} value
|
||||
* @param {number|boolean} value
|
||||
*/
|
||||
flatbuffers.ByteBuffer.prototype.writeInt8 = function(offset, value) {
|
||||
this.bytes_[offset] = /** @type {number} */(value);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} offset
|
||||
* @param {number} value
|
||||
*/
|
||||
flatbuffers.ByteBuffer.prototype.writeUint8 = function(offset, value) {
|
||||
this.bytes_[offset] = value;
|
||||
};
|
||||
|
||||
@@ -959,6 +967,15 @@ flatbuffers.ByteBuffer.prototype.writeInt16 = function(offset, value) {
|
||||
this.bytes_[offset + 1] = value >> 8;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} offset
|
||||
* @param {number} value
|
||||
*/
|
||||
flatbuffers.ByteBuffer.prototype.writeUint16 = function(offset, value) {
|
||||
this.bytes_[offset] = value;
|
||||
this.bytes_[offset + 1] = value >> 8;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} offset
|
||||
* @param {number} value
|
||||
@@ -970,6 +987,17 @@ flatbuffers.ByteBuffer.prototype.writeInt32 = function(offset, value) {
|
||||
this.bytes_[offset + 3] = value >> 24;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} offset
|
||||
* @param {number} value
|
||||
*/
|
||||
flatbuffers.ByteBuffer.prototype.writeUint32 = function(offset, value) {
|
||||
this.bytes_[offset] = value;
|
||||
this.bytes_[offset + 1] = value >> 8;
|
||||
this.bytes_[offset + 2] = value >> 16;
|
||||
this.bytes_[offset + 3] = value >> 24;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} offset
|
||||
* @param {flatbuffers.Long} value
|
||||
@@ -979,6 +1007,15 @@ flatbuffers.ByteBuffer.prototype.writeInt64 = function(offset, value) {
|
||||
this.writeInt32(offset + 4, value.high);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} offset
|
||||
* @param {flatbuffers.Long} value
|
||||
*/
|
||||
flatbuffers.ByteBuffer.prototype.writeUint64 = function(offset, value) {
|
||||
this.writeUint32(offset, value.low);
|
||||
this.writeUint32(offset + 4, value.high);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} offset
|
||||
* @param {number} value
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "flatbuffers",
|
||||
"version": "1.6.0",
|
||||
"version": "1.7.0",
|
||||
"description": "Memory Efficient Serialization Library",
|
||||
"files": ["js/flatbuffers.js"],
|
||||
"main": "js/flatbuffers.js",
|
||||
|
||||
2
pom.xml
2
pom.xml
@@ -5,7 +5,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.google.flatbuffers</groupId>
|
||||
<artifactId>flatbuffers-java</artifactId>
|
||||
<version>1.6.0-SNAPSHOT</version>
|
||||
<version>1.7.0-SNAPSHOT</version>
|
||||
<packaging>bundle</packaging>
|
||||
<name>FlatBuffers Java API</name>
|
||||
<description>
|
||||
|
||||
@@ -54,6 +54,6 @@ you would leave it in.
|
||||
[`flatbuffers` tag]: https://stackoverflow.com/questions/tagged/flatbuffers
|
||||
[FlatBuffers Google Group]: https://groups.google.com/forum/#!forum/flatbuffers
|
||||
[FlatBuffers Issues Tracker]: http://github.com/google/flatbuffers/issues
|
||||
[stackoverflow.com]: http://www.stackoverflow.com
|
||||
[stackoverflow.com]: http://stackoverflow.com/search?q=flatbuffers
|
||||
[landing page]: http://google.github.io/flatbuffers
|
||||
[LICENSE]: https://github.com/google/flatbuffers/blob/master/LICENSE.txt
|
||||
|
||||
@@ -42,7 +42,8 @@ table KeyValue {
|
||||
table EnumVal {
|
||||
name:string (required);
|
||||
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 {
|
||||
|
||||
@@ -81,22 +81,19 @@ class SampleBinary
|
||||
Assert(monster.Color == Color.Red, "monster.Color", Convert.ToString(monster.Color),
|
||||
Convert.ToString(Color.Red));
|
||||
|
||||
// C# also allows you to use performance-enhanced methods to fill an object that has already
|
||||
// been created. These functions are prefixed with "Get". For example: `monster.GetPos()`.
|
||||
var myAlreadyCreatedVector = new Vec3();
|
||||
monster.GetPos(myAlreadyCreatedVector); // Instead of `var myNewVec3 = monster.Pos`.
|
||||
Assert(myAlreadyCreatedVector.X == 1.0f, "myAlreadyCreatedVector.X",
|
||||
Convert.ToString(myAlreadyCreatedVector.X), Convert.ToString(1.0f));
|
||||
Assert(myAlreadyCreatedVector.Y == 2.0f, "myAlreadyCreatedVector.Y",
|
||||
Convert.ToString(myAlreadyCreatedVector.Y), Convert.ToString(2.0f));
|
||||
Assert(myAlreadyCreatedVector.Z == 3.0f, "myAlreadyCreatedVector.Z",
|
||||
Convert.ToString(myAlreadyCreatedVector.Z), Convert.ToString(3.0f));
|
||||
var vec = monster.Pos.Value;
|
||||
Assert(vec.X == 1.0f, "vec.X",
|
||||
Convert.ToString(vec.X), Convert.ToString(1.0f));
|
||||
Assert(vec.Y == 2.0f, "vec.Y",
|
||||
Convert.ToString(vec.Y), Convert.ToString(2.0f));
|
||||
Assert(vec.Z == 3.0f, "vec.Z",
|
||||
Convert.ToString(vec.Z), Convert.ToString(3.0f));
|
||||
|
||||
// Get and test the `Inventory` FlatBuffer `vector`.
|
||||
for (int i = 0; i < monster.InventoryLength; i++)
|
||||
{
|
||||
Assert(monster.GetInventory(i) == i, "monster.GetInventory",
|
||||
Convert.ToString(monster.GetInventory(i)), Convert.ToString(i));
|
||||
Assert(monster.Inventory(i) == i, "monster.Inventory",
|
||||
Convert.ToString(monster.Inventory(i)), Convert.ToString(i));
|
||||
}
|
||||
|
||||
// Get and test the `Weapons` FlatBuffer `vector` of `table`s.
|
||||
@@ -104,17 +101,17 @@ class SampleBinary
|
||||
var expectedWeaponDamages = new short[] {3, 5};
|
||||
for (int i = 0; i < monster.WeaponsLength; i++)
|
||||
{
|
||||
Assert(monster.GetWeapons(i).Name.Equals(expectedWeaponNames[i], StringComparison.Ordinal),
|
||||
"monster.GetWeapons", monster.GetWeapons(i).Name, expectedWeaponNames[i]);
|
||||
Assert(monster.GetWeapons(i).Damage == expectedWeaponDamages[i], "monster.GetWeapons",
|
||||
Convert.ToString(monster.GetWeapons(i).Damage),
|
||||
Assert(monster.Weapons(i).Value.Name.Equals(expectedWeaponNames[i], StringComparison.Ordinal),
|
||||
"monster.Weapons", monster.Weapons(i).Value.Name, expectedWeaponNames[i]);
|
||||
Assert(monster.Weapons(i).Value.Damage == expectedWeaponDamages[i], "monster.GetWeapons",
|
||||
Convert.ToString(monster.Weapons(i).Value.Damage),
|
||||
Convert.ToString(expectedWeaponDamages[i]));
|
||||
}
|
||||
|
||||
// Get and test the `Equipped` FlatBuffer `union`.
|
||||
Assert(monster.EquippedType == Equipment.Weapon, "monster.EquippedType",
|
||||
Convert.ToString(monster.EquippedType), Convert.ToString(Equipment.Weapon));
|
||||
var equipped = (Weapon)monster.GetEquipped(new Weapon());
|
||||
var equipped = monster.Equipped<Weapon>().Value;
|
||||
Assert(equipped.Name.Equals("Axe", StringComparison.Ordinal), "equipped.Name", equipped.Name,
|
||||
"Axe");
|
||||
Assert(equipped.Damage == 5, "equipped.Damage", Convert.ToString(equipped.Damage),
|
||||
|
||||
@@ -25,6 +25,15 @@ enum Color {
|
||||
Color_MAX = Color_Blue
|
||||
};
|
||||
|
||||
inline Color (&EnumValuesColor())[3] {
|
||||
static Color values[] = {
|
||||
Color_Red,
|
||||
Color_Green,
|
||||
Color_Blue
|
||||
};
|
||||
return values;
|
||||
}
|
||||
|
||||
inline const char **EnumNamesColor() {
|
||||
static const char *names[] = {
|
||||
"Red",
|
||||
@@ -47,6 +56,14 @@ enum Equipment {
|
||||
Equipment_MAX = Equipment_Weapon
|
||||
};
|
||||
|
||||
inline Equipment (&EnumValuesEquipment())[2] {
|
||||
static Equipment values[] = {
|
||||
Equipment_NONE,
|
||||
Equipment_Weapon
|
||||
};
|
||||
return values;
|
||||
}
|
||||
|
||||
inline const char **EnumNamesEquipment() {
|
||||
static const char *names[] = {
|
||||
"NONE",
|
||||
@@ -71,32 +88,36 @@ template<> struct EquipmentTraits<Weapon> {
|
||||
|
||||
struct EquipmentUnion {
|
||||
Equipment type;
|
||||
flatbuffers::NativeTable *table;
|
||||
void *value;
|
||||
|
||||
EquipmentUnion() : type(Equipment_NONE), table(nullptr) {}
|
||||
EquipmentUnion(EquipmentUnion&& u):
|
||||
type(std::move(u.type)), table(std::move(u.table)) {}
|
||||
EquipmentUnion(const EquipmentUnion &);
|
||||
EquipmentUnion &operator=(const EquipmentUnion &);
|
||||
EquipmentUnion() : type(Equipment_NONE), value(nullptr) {}
|
||||
EquipmentUnion(EquipmentUnion&& u) FLATBUFFERS_NOEXCEPT :
|
||||
type(Equipment_NONE), value(nullptr)
|
||||
{ std::swap(type, u.type); std::swap(value, u.value); }
|
||||
EquipmentUnion(const EquipmentUnion &) FLATBUFFERS_NOEXCEPT;
|
||||
EquipmentUnion &operator=(const EquipmentUnion &u) FLATBUFFERS_NOEXCEPT
|
||||
{ EquipmentUnion t(u); std::swap(type, t.type); std::swap(value, t.value); return *this; }
|
||||
EquipmentUnion &operator=(EquipmentUnion &&u) FLATBUFFERS_NOEXCEPT
|
||||
{ std::swap(type, u.type); std::swap(value, u.value); return *this; }
|
||||
~EquipmentUnion() { Reset(); }
|
||||
|
||||
void Reset();
|
||||
|
||||
template <typename T>
|
||||
void Set(T&& value) {
|
||||
void Set(T&& val) {
|
||||
Reset();
|
||||
type = EquipmentTraits<typename T::TableType>::enum_value;
|
||||
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;
|
||||
|
||||
WeaponT *AsWeapon() {
|
||||
return type == Equipment_Weapon ?
|
||||
reinterpret_cast<WeaponT *>(table) : nullptr;
|
||||
reinterpret_cast<WeaponT *>(value) : nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -182,13 +203,13 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
return GetField<int16_t>(VT_MANA, 150);
|
||||
}
|
||||
bool mutate_mana(int16_t _mana) {
|
||||
return SetField(VT_MANA, _mana);
|
||||
return SetField<int16_t>(VT_MANA, _mana, 150);
|
||||
}
|
||||
int16_t hp() const {
|
||||
return GetField<int16_t>(VT_HP, 100);
|
||||
}
|
||||
bool mutate_hp(int16_t _hp) {
|
||||
return SetField(VT_HP, _hp);
|
||||
return SetField<int16_t>(VT_HP, _hp, 100);
|
||||
}
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
@@ -206,7 +227,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
return static_cast<Color>(GetField<int8_t>(VT_COLOR, 2));
|
||||
}
|
||||
bool mutate_color(Color _color) {
|
||||
return SetField(VT_COLOR, static_cast<int8_t>(_color));
|
||||
return SetField<int8_t>(VT_COLOR, static_cast<int8_t>(_color), 2);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<Weapon>> *weapons() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Weapon>> *>(VT_WEAPONS);
|
||||
@@ -218,11 +239,15 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
return static_cast<Equipment>(GetField<uint8_t>(VT_EQUIPPED_TYPE, 0));
|
||||
}
|
||||
bool mutate_equipped_type(Equipment _equipped_type) {
|
||||
return SetField(VT_EQUIPPED_TYPE, static_cast<uint8_t>(_equipped_type));
|
||||
return SetField<uint8_t>(VT_EQUIPPED_TYPE, static_cast<uint8_t>(_equipped_type), 0);
|
||||
}
|
||||
const void *equipped() const {
|
||||
return GetPointer<const void *>(VT_EQUIPPED);
|
||||
}
|
||||
template<typename T> const T *equipped_as() const;
|
||||
const Weapon *equipped_as_Weapon() const {
|
||||
return equipped_type() == Equipment_Weapon ? static_cast<const Weapon *>(equipped()) : nullptr;
|
||||
}
|
||||
void *mutable_equipped() {
|
||||
return GetPointer<void *>(VT_EQUIPPED);
|
||||
}
|
||||
@@ -231,16 +256,16 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VerifyField<Vec3>(verifier, VT_POS) &&
|
||||
VerifyField<int16_t>(verifier, VT_MANA) &&
|
||||
VerifyField<int16_t>(verifier, VT_HP) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
|
||||
VerifyOffset(verifier, VT_NAME) &&
|
||||
verifier.Verify(name()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_INVENTORY) &&
|
||||
VerifyOffset(verifier, VT_INVENTORY) &&
|
||||
verifier.Verify(inventory()) &&
|
||||
VerifyField<int8_t>(verifier, VT_COLOR) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_WEAPONS) &&
|
||||
VerifyOffset(verifier, VT_WEAPONS) &&
|
||||
verifier.Verify(weapons()) &&
|
||||
verifier.VerifyVectorOfTables(weapons()) &&
|
||||
VerifyField<uint8_t>(verifier, VT_EQUIPPED_TYPE) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_EQUIPPED) &&
|
||||
VerifyOffset(verifier, VT_EQUIPPED) &&
|
||||
VerifyEquipment(verifier, equipped(), equipped_type()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
@@ -249,6 +274,10 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
static flatbuffers::Offset<Monster> Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||
};
|
||||
|
||||
template<> inline const Weapon *Monster::equipped_as<Weapon>() const {
|
||||
return equipped_as_Weapon();
|
||||
}
|
||||
|
||||
struct MonsterBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
@@ -366,11 +395,11 @@ struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
return GetField<int16_t>(VT_DAMAGE, 0);
|
||||
}
|
||||
bool mutate_damage(int16_t _damage) {
|
||||
return SetField(VT_DAMAGE, _damage);
|
||||
return SetField<int16_t>(VT_DAMAGE, _damage, 0);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
|
||||
VerifyOffset(verifier, VT_NAME) &&
|
||||
verifier.Verify(name()) &&
|
||||
VerifyField<int16_t>(verifier, VT_DAMAGE) &&
|
||||
verifier.EndTable();
|
||||
@@ -436,11 +465,11 @@ inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function
|
||||
{ auto _e = mana(); _o->mana = _e; };
|
||||
{ auto _e = hp(); _o->hp = _e; };
|
||||
{ auto _e = name(); if (_e) _o->name = _e->str(); };
|
||||
{ auto _e = inventory(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inventory.push_back(_e->Get(_i)); } };
|
||||
{ auto _e = 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 = weapons(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->weapons.push_back(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(); 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) {
|
||||
@@ -524,7 +553,7 @@ inline bool VerifyEquipmentVector(flatbuffers::Verifier &verifier, const flatbuf
|
||||
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) {
|
||||
case Equipment_Weapon: {
|
||||
auto ptr = reinterpret_cast<const Weapon *>(obj);
|
||||
@@ -537,23 +566,34 @@ 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 {
|
||||
switch (type) {
|
||||
case Equipment_Weapon: {
|
||||
auto ptr = reinterpret_cast<const WeaponT *>(table);
|
||||
auto ptr = reinterpret_cast<const WeaponT *>(value);
|
||||
return CreateWeapon(_fbb, ptr, _rehasher).Union();
|
||||
}
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline EquipmentUnion::EquipmentUnion(const EquipmentUnion &u) FLATBUFFERS_NOEXCEPT : type(u.type), value(nullptr) {
|
||||
switch (type) {
|
||||
case Equipment_Weapon: {
|
||||
value = new WeaponT(*reinterpret_cast<WeaponT *>(u.value));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void EquipmentUnion::Reset() {
|
||||
switch (type) {
|
||||
case Equipment_Weapon: {
|
||||
auto ptr = reinterpret_cast<WeaponT *>(table);
|
||||
auto ptr = reinterpret_cast<WeaponT *>(value);
|
||||
delete ptr;
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
table = nullptr;
|
||||
value = nullptr;
|
||||
type = Equipment_NONE;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@
|
||||
#include <assert.h>
|
||||
#include "flatbuffers/util.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4127) // C4127: conditional expression is constant
|
||||
#endif
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
void CodeWriter::operator+=(std::string text) {
|
||||
@@ -63,7 +68,7 @@ void CodeWriter::operator+=(std::string text) {
|
||||
|
||||
const char *BaseGenerator::FlatBuffersGeneratedWarning() {
|
||||
return "automatically generated by the FlatBuffers compiler,"
|
||||
" do not modify\n\n";
|
||||
" do not modify";
|
||||
}
|
||||
|
||||
std::string BaseGenerator::NamespaceDir(const Parser &parser,
|
||||
@@ -84,18 +89,6 @@ std::string BaseGenerator::NamespaceDir(const Namespace &ns) const {
|
||||
return BaseGenerator::NamespaceDir(parser_, path_, ns);
|
||||
}
|
||||
|
||||
bool BaseGenerator::IsEverythingGenerated() const {
|
||||
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
|
||||
++it) {
|
||||
if (!(*it)->generated) return false;
|
||||
}
|
||||
for (auto it = parser_.structs_.vec.begin();
|
||||
it != parser_.structs_.vec.end(); ++it) {
|
||||
if (!(*it)->generated) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string BaseGenerator::FullNamespace(const char *separator,
|
||||
const Namespace &ns) {
|
||||
std::string namespace_name;
|
||||
@@ -130,6 +123,20 @@ std::string BaseGenerator::WrapInNameSpace(const Definition &def) const {
|
||||
return WrapInNameSpace(def.defined_namespace, def.name);
|
||||
}
|
||||
|
||||
std::string BaseGenerator::GetNameSpace(const Definition &def) const {
|
||||
const Namespace *ns = def.defined_namespace;
|
||||
if (CurrentNameSpace() == ns) return "";
|
||||
std::string qualified_name = qualifying_start_;
|
||||
for (auto it = ns->components.begin(); it != ns->components.end(); ++it) {
|
||||
qualified_name += *it;
|
||||
if (std::next(it) != ns->components.end()) {
|
||||
qualified_name += qualifying_separator_;
|
||||
}
|
||||
}
|
||||
|
||||
return qualified_name;
|
||||
}
|
||||
|
||||
// Generate a documentation comment, if available.
|
||||
void GenComment(const std::vector<std::string> &dc, std::string *code_ptr,
|
||||
const CommentConfig *config, const char *prefix) {
|
||||
@@ -156,3 +163,8 @@ void GenComment(const std::vector<std::string> &dc, std::string *code_ptr,
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
215
src/flatc.cpp
215
src/flatc.cpp
@@ -16,7 +16,9 @@
|
||||
|
||||
#include "flatbuffers/flatc.h"
|
||||
|
||||
#define FLATC_VERSION "1.6.0 (" __DATE__ ")"
|
||||
#include <list>
|
||||
|
||||
#define FLATC_VERSION "1.7.0 (" __DATE__ ")"
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
@@ -46,7 +48,7 @@ void FlatCompiler::Error(const std::string &err, bool usage,
|
||||
|
||||
std::string FlatCompiler::GetUsageString(const char* program_name) const {
|
||||
std::stringstream ss;
|
||||
ss << "Usageaa: " << program_name << " [OPTION]... FILE... [-- FILE...]\n";
|
||||
ss << "Usage: " << program_name << " [OPTION]... FILE... [-- FILE...]\n";
|
||||
for (size_t i = 0; i < params_.num_generators; ++i) {
|
||||
const Generator& g = params_.generators[i];
|
||||
|
||||
@@ -86,8 +88,11 @@ std::string FlatCompiler::GetUsageString(const char* program_name) const {
|
||||
" --escape-proto-ids Disable appending '_' in namespaces names.\n"
|
||||
" --gen-object-api Generate an additional object-based API.\n"
|
||||
" --cpp-ptr-type T Set object API pointer type (default std::unique_ptr)\n"
|
||||
" --cpp-str-type T Set object API string type (default std::string)\n"
|
||||
" T::c_str() and T::length() must be supported\n"
|
||||
" --no-js-exports Removes Node.js style export lines in JS.\n"
|
||||
" --goog-js-export Uses goog.exports* for closure compiler exporting in JS.\n"
|
||||
" --go-namespace Generate the overrided namespace in Golang.\n"
|
||||
" --raw-binary Allow binaries without file_indentifier to be read.\n"
|
||||
" This may crash flatc given a mismatched schema.\n"
|
||||
" --proto Input is a .proto, translate to .fbs.\n"
|
||||
@@ -100,6 +105,9 @@ std::string FlatCompiler::GetUsageString(const char* program_name) const {
|
||||
" PATH \n"
|
||||
" --include-prefix Prefix this path to any generated include statements.\n"
|
||||
" PATH\n"
|
||||
" --keep-prefix Keep original prefix of schema include statement.\n"
|
||||
" --no-fb-import Don't include flatbuffers import statement for TypeScript.\n"
|
||||
" --no-ts-reexport Don't re-export imported dependencies for TypeScript.\n"
|
||||
"FILEs may be schemas, or JSON files (conforming to preceding schema)\n"
|
||||
"FILEs after the -- must be binary flatbuffer format files.\n"
|
||||
"Output files are named using the base file name of the input,\n"
|
||||
@@ -122,6 +130,7 @@ int FlatCompiler::Compile(int argc, const char** argv) {
|
||||
bool schema_binary = false;
|
||||
bool grpc_enabled = false;
|
||||
std::vector<std::string> filenames;
|
||||
std::list<std::string> include_directories_storage;
|
||||
std::vector<const char *> include_directories;
|
||||
std::vector<const char *> conform_include_directories;
|
||||
std::vector<bool> generator_enabled(params_.num_generators, false);
|
||||
@@ -135,21 +144,29 @@ int FlatCompiler::Compile(int argc, const char** argv) {
|
||||
Error("invalid option location: " + arg, true);
|
||||
if (arg == "-o") {
|
||||
if (++argi >= argc) Error("missing path following: " + arg, true);
|
||||
output_path = flatbuffers::ConCatPathFileName(argv[argi], "");
|
||||
output_path = flatbuffers::ConCatPathFileName(
|
||||
flatbuffers::PosixPath(argv[argi]), "");
|
||||
} else if(arg == "-I") {
|
||||
if (++argi >= argc) Error("missing path following" + arg, true);
|
||||
include_directories.push_back(argv[argi]);
|
||||
include_directories_storage.push_back(
|
||||
flatbuffers::PosixPath(argv[argi]));
|
||||
include_directories.push_back(
|
||||
include_directories_storage.back().c_str());
|
||||
} else if(arg == "--conform") {
|
||||
if (++argi >= argc) Error("missing path following" + arg, true);
|
||||
conform_to_schema = argv[argi];
|
||||
conform_to_schema = flatbuffers::PosixPath(argv[argi]);
|
||||
} else if (arg == "--conform-includes") {
|
||||
if (++argi >= argc) Error("missing path following" + arg, true);
|
||||
conform_include_directories.push_back(argv[argi]);
|
||||
include_directories_storage.push_back(
|
||||
flatbuffers::PosixPath(argv[argi]));
|
||||
conform_include_directories.push_back(
|
||||
include_directories_storage.back().c_str());
|
||||
} else if (arg == "--include-prefix") {
|
||||
if (++argi >= argc) Error("missing path following" + arg, true);
|
||||
opts.include_prefix = argv[argi];
|
||||
if (opts.include_prefix.back() != '/' &&
|
||||
opts.include_prefix.back() != '\\') opts.include_prefix += "/";
|
||||
opts.include_prefix = flatbuffers::ConCatPathFileName(
|
||||
flatbuffers::PosixPath(argv[argi]), "");
|
||||
} else if(arg == "--keep-prefix") {
|
||||
opts.keep_include_path = true;
|
||||
} else if(arg == "--strict-json") {
|
||||
opts.strict_json = true;
|
||||
} else if(arg == "--allow-non-utf8") {
|
||||
@@ -158,6 +175,9 @@ int FlatCompiler::Compile(int argc, const char** argv) {
|
||||
opts.skip_js_exports = true;
|
||||
} else if(arg == "--goog-js-export") {
|
||||
opts.use_goog_js_export_format = true;
|
||||
} else if(arg == "--go-namespace") {
|
||||
if (++argi >= argc) Error("missing golang namespace" + arg, true);
|
||||
opts.go_namespace = argv[argi];
|
||||
} else if(arg == "--defaults-json") {
|
||||
opts.output_default_scalars_in_json = true;
|
||||
} else if (arg == "--unknown-json") {
|
||||
@@ -178,6 +198,9 @@ int FlatCompiler::Compile(int argc, const char** argv) {
|
||||
} else if (arg == "--cpp-ptr-type") {
|
||||
if (++argi >= argc) Error("missing type following" + arg, true);
|
||||
opts.cpp_object_api_pointer_type = argv[argi];
|
||||
} else if (arg == "--cpp-str-type") {
|
||||
if (++argi >= argc) Error("missing type following" + arg, true);
|
||||
opts.cpp_object_api_string_type = argv[argi];
|
||||
} else if(arg == "--gen-all") {
|
||||
opts.generate_all = true;
|
||||
opts.include_dependence_headers = false;
|
||||
@@ -207,6 +230,10 @@ int FlatCompiler::Compile(int argc, const char** argv) {
|
||||
grpc_enabled = true;
|
||||
} else if(arg == "--bfbs-comments") {
|
||||
opts.binary_schema_comments = true;
|
||||
} else if(arg == "--no-fb-import") {
|
||||
opts.skip_flatbuffers_import = true;
|
||||
} else if(arg == "--no-ts-reexport") {
|
||||
opts.reexport_ts_modules = false;
|
||||
} else {
|
||||
for (size_t i = 0; i < params_.num_generators; ++i) {
|
||||
if (arg == params_.generators[i].generator_opt_long ||
|
||||
@@ -222,7 +249,7 @@ int FlatCompiler::Compile(int argc, const char** argv) {
|
||||
found:;
|
||||
}
|
||||
} else {
|
||||
filenames.push_back(argv[argi]);
|
||||
filenames.push_back(flatbuffers::PosixPath(argv[argi]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -249,101 +276,103 @@ int FlatCompiler::Compile(int argc, const char** argv) {
|
||||
for (auto file_it = filenames.begin();
|
||||
file_it != filenames.end();
|
||||
++file_it) {
|
||||
std::string contents;
|
||||
if (!flatbuffers::LoadFile(file_it->c_str(), true, &contents))
|
||||
Error("unable to load file: " + *file_it);
|
||||
auto &filename = *file_it;
|
||||
std::string contents;
|
||||
if (!flatbuffers::LoadFile(filename.c_str(), true, &contents))
|
||||
Error("unable to load file: " + filename);
|
||||
|
||||
bool is_binary = static_cast<size_t>(file_it - filenames.begin()) >=
|
||||
binary_files_from;
|
||||
if (is_binary) {
|
||||
parser->builder_.Clear();
|
||||
parser->builder_.PushFlatBuffer(
|
||||
reinterpret_cast<const uint8_t *>(contents.c_str()),
|
||||
contents.length());
|
||||
if (!raw_binary) {
|
||||
// Generally reading binaries that do not correspond to the schema
|
||||
// will crash, and sadly there's no way around that when the binary
|
||||
// does not contain a file identifier.
|
||||
// We'd expect that typically any binary used as a file would have
|
||||
// such an identifier, so by default we require them to match.
|
||||
if (!parser->file_identifier_.length()) {
|
||||
Error("current schema has no file_identifier: cannot test if \"" +
|
||||
*file_it +
|
||||
"\" matches the schema, use --raw-binary to read this file"
|
||||
" anyway.");
|
||||
} else if (!flatbuffers::BufferHasIdentifier(contents.c_str(),
|
||||
parser->file_identifier_.c_str())) {
|
||||
Error("binary \"" +
|
||||
*file_it +
|
||||
"\" does not have expected file_identifier \"" +
|
||||
parser->file_identifier_ +
|
||||
"\", use --raw-binary to read this file anyway.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Check if file contains 0 bytes.
|
||||
if (contents.length() != strlen(contents.c_str())) {
|
||||
Error("input file appears to be binary: " + *file_it, true);
|
||||
}
|
||||
auto is_schema = flatbuffers::GetExtension(*file_it) == "fbs";
|
||||
if (is_schema) {
|
||||
// If we're processing multiple schemas, make sure to start each
|
||||
// one from scratch. If it depends on previous schemas it must do
|
||||
// so explicitly using an include.
|
||||
parser.reset(new flatbuffers::Parser(opts));
|
||||
}
|
||||
ParseFile(*parser.get(), *file_it, contents, include_directories);
|
||||
if (is_schema && !conform_to_schema.empty()) {
|
||||
auto err = parser->ConformTo(conform_parser);
|
||||
if (!err.empty()) Error("schemas don\'t conform: " + err);
|
||||
}
|
||||
if (schema_binary) {
|
||||
parser->Serialize();
|
||||
parser->file_extension_ = reflection::SchemaExtension();
|
||||
bool is_binary = static_cast<size_t>(file_it - filenames.begin()) >=
|
||||
binary_files_from;
|
||||
auto is_schema = flatbuffers::GetExtension(filename) == "fbs";
|
||||
if (is_binary) {
|
||||
parser->builder_.Clear();
|
||||
parser->builder_.PushFlatBuffer(
|
||||
reinterpret_cast<const uint8_t *>(contents.c_str()),
|
||||
contents.length());
|
||||
if (!raw_binary) {
|
||||
// Generally reading binaries that do not correspond to the schema
|
||||
// will crash, and sadly there's no way around that when the binary
|
||||
// does not contain a file identifier.
|
||||
// We'd expect that typically any binary used as a file would have
|
||||
// such an identifier, so by default we require them to match.
|
||||
if (!parser->file_identifier_.length()) {
|
||||
Error("current schema has no file_identifier: cannot test if \"" +
|
||||
filename +
|
||||
"\" matches the schema, use --raw-binary to read this file"
|
||||
" anyway.");
|
||||
} else if (!flatbuffers::BufferHasIdentifier(contents.c_str(),
|
||||
parser->file_identifier_.c_str())) {
|
||||
Error("binary \"" +
|
||||
filename +
|
||||
"\" does not have expected file_identifier \"" +
|
||||
parser->file_identifier_ +
|
||||
"\", use --raw-binary to read this file anyway.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Check if file contains 0 bytes.
|
||||
if (contents.length() != strlen(contents.c_str())) {
|
||||
Error("input file appears to be binary: " + filename, true);
|
||||
}
|
||||
if (is_schema) {
|
||||
// If we're processing multiple schemas, make sure to start each
|
||||
// one from scratch. If it depends on previous schemas it must do
|
||||
// so explicitly using an include.
|
||||
parser.reset(new flatbuffers::Parser(opts));
|
||||
}
|
||||
ParseFile(*parser.get(), filename, contents, include_directories);
|
||||
if (is_schema && !conform_to_schema.empty()) {
|
||||
auto err = parser->ConformTo(conform_parser);
|
||||
if (!err.empty()) Error("schemas don\'t conform: " + err);
|
||||
}
|
||||
if (schema_binary) {
|
||||
parser->Serialize();
|
||||
parser->file_extension_ = reflection::SchemaExtension();
|
||||
}
|
||||
}
|
||||
|
||||
std::string filebase = flatbuffers::StripPath(
|
||||
flatbuffers::StripExtension(*file_it));
|
||||
std::string filebase = flatbuffers::StripPath(
|
||||
flatbuffers::StripExtension(filename));
|
||||
|
||||
for (size_t i = 0; i < params_.num_generators; ++i) {
|
||||
parser->opts.lang = params_.generators[i].lang;
|
||||
if (generator_enabled[i]) {
|
||||
if (!print_make_rules) {
|
||||
flatbuffers::EnsureDirExists(output_path);
|
||||
if (!params_.generators[i].generate(*parser.get(), output_path, filebase)) {
|
||||
Error(std::string("Unable to generate ") +
|
||||
params_.generators[i].lang_name +
|
||||
" for " +
|
||||
filebase);
|
||||
for (size_t i = 0; i < params_.num_generators; ++i) {
|
||||
parser->opts.lang = params_.generators[i].lang;
|
||||
if (generator_enabled[i]) {
|
||||
if (!print_make_rules) {
|
||||
flatbuffers::EnsureDirExists(output_path);
|
||||
if ((!params_.generators[i].schema_only || is_schema) &&
|
||||
!params_.generators[i].generate(*parser.get(), output_path, filebase)) {
|
||||
Error(std::string("Unable to generate ") +
|
||||
params_.generators[i].lang_name +
|
||||
" for " +
|
||||
filebase);
|
||||
}
|
||||
} else {
|
||||
std::string make_rule = params_.generators[i].make_rule(
|
||||
*parser.get(), output_path, filename);
|
||||
if (!make_rule.empty())
|
||||
printf("%s\n", flatbuffers::WordWrap(
|
||||
make_rule, 80, " ", " \\").c_str());
|
||||
}
|
||||
if (grpc_enabled) {
|
||||
if (params_.generators[i].generateGRPC != nullptr) {
|
||||
if (!params_.generators[i].generateGRPC(*parser.get(), output_path,
|
||||
filebase)) {
|
||||
Error(std::string("Unable to generate GRPC interface for") +
|
||||
params_.generators[i].lang_name);
|
||||
}
|
||||
} else {
|
||||
std::string make_rule = params_.generators[i].make_rule(
|
||||
*parser.get(), output_path, *file_it);
|
||||
if (!make_rule.empty())
|
||||
printf("%s\n", flatbuffers::WordWrap(
|
||||
make_rule, 80, " ", " \\").c_str());
|
||||
}
|
||||
if (grpc_enabled) {
|
||||
if (params_.generators[i].generateGRPC != nullptr) {
|
||||
if (!params_.generators[i].generateGRPC(*parser.get(), output_path,
|
||||
filebase)) {
|
||||
Error(std::string("Unable to generate GRPC interface for") +
|
||||
params_.generators[i].lang_name);
|
||||
}
|
||||
} else {
|
||||
Warn(std::string("GRPC interface generator not implemented for ")
|
||||
+ params_.generators[i].lang_name);
|
||||
}
|
||||
Warn(std::string("GRPC interface generator not implemented for ")
|
||||
+ params_.generators[i].lang_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (opts.proto_mode) GenerateFBS(*parser.get(), output_path, filebase);
|
||||
if (opts.proto_mode) GenerateFBS(*parser.get(), output_path, filebase);
|
||||
|
||||
// We do not want to generate code for the definitions in this file
|
||||
// in any files coming up next.
|
||||
parser->MarkGenerated();
|
||||
// We do not want to generate code for the definitions in this file
|
||||
// in any files coming up next.
|
||||
parser->MarkGenerated();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -46,47 +46,52 @@ int main(int argc, const char *argv[]) {
|
||||
g_program_name = argv[0];
|
||||
|
||||
const flatbuffers::FlatCompiler::Generator generators[] = {
|
||||
{ flatbuffers::GenerateBinary, "-b", "--binary", "binary",
|
||||
{ flatbuffers::GenerateBinary, "-b", "--binary", "binary", false,
|
||||
nullptr,
|
||||
flatbuffers::IDLOptions::kBinary,
|
||||
"Generate wire format binaries for any data definitions",
|
||||
flatbuffers::BinaryMakeRule },
|
||||
{ flatbuffers::GenerateTextFile, "-t", "--json", "text",
|
||||
{ flatbuffers::GenerateTextFile, "-t", "--json", "text", false,
|
||||
nullptr,
|
||||
flatbuffers::IDLOptions::kJson,
|
||||
"Generate text output for any data definitions",
|
||||
flatbuffers::TextMakeRule },
|
||||
{ flatbuffers::GenerateCPP, "-c", "--cpp", "C++",
|
||||
{ flatbuffers::GenerateCPP, "-c", "--cpp", "C++", true,
|
||||
flatbuffers::GenerateCppGRPC,
|
||||
flatbuffers::IDLOptions::kCpp,
|
||||
"Generate C++ headers for tables/structs",
|
||||
flatbuffers::CPPMakeRule },
|
||||
{ flatbuffers::GenerateGo, "-g", "--go", "Go",
|
||||
{ flatbuffers::GenerateGo, "-g", "--go", "Go", true,
|
||||
flatbuffers::GenerateGoGRPC,
|
||||
flatbuffers::IDLOptions::kGo,
|
||||
"Generate Go files for tables/structs",
|
||||
flatbuffers::GeneralMakeRule },
|
||||
{ flatbuffers::GenerateGeneral, "-j", "--java", "Java",
|
||||
{ flatbuffers::GenerateGeneral, "-j", "--java", "Java", true,
|
||||
nullptr,
|
||||
flatbuffers::IDLOptions::kJava,
|
||||
"Generate Java classes for tables/structs",
|
||||
flatbuffers::GeneralMakeRule },
|
||||
{ flatbuffers::GenerateJS, "-s", "--js", "JavaScript",
|
||||
{ flatbuffers::GenerateJS, "-s", "--js", "JavaScript", true,
|
||||
nullptr,
|
||||
flatbuffers::IDLOptions::kJs,
|
||||
"Generate JavaScript code for tables/structs",
|
||||
flatbuffers::JSMakeRule },
|
||||
{ flatbuffers::GenerateGeneral, "-n", "--csharp", "C#",
|
||||
{ flatbuffers::GenerateJS, "-T", "--ts", "TypeScript", true,
|
||||
nullptr,
|
||||
flatbuffers::IDLOptions::kTs,
|
||||
"Generate TypeScript code for tables/structs",
|
||||
flatbuffers::JSMakeRule },
|
||||
{ flatbuffers::GenerateGeneral, "-n", "--csharp", "C#", true,
|
||||
nullptr,
|
||||
flatbuffers::IDLOptions::kCSharp,
|
||||
"Generate C# classes for tables/structs",
|
||||
flatbuffers::GeneralMakeRule },
|
||||
{ flatbuffers::GeneratePython, "-p", "--python", "Python",
|
||||
{ flatbuffers::GeneratePython, "-p", "--python", "Python", true,
|
||||
nullptr,
|
||||
flatbuffers::IDLOptions::kPython,
|
||||
"Generate Python files for tables/structs",
|
||||
flatbuffers::GeneralMakeRule },
|
||||
{ flatbuffers::GeneratePhp, nullptr, "--php", "PHP",
|
||||
{ flatbuffers::GeneratePhp, nullptr, "--php", "PHP", true,
|
||||
nullptr,
|
||||
flatbuffers::IDLOptions::kPhp,
|
||||
"Generate PHP files for tables/structs",
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// Pedantic warning free version of toupper().
|
||||
inline char ToUpper(char c) {
|
||||
return static_cast<char>(::toupper(c));
|
||||
}
|
||||
|
||||
static std::string GeneratedFileName(const std::string &path,
|
||||
const std::string &file_name) {
|
||||
return path + file_name + "_generated.h";
|
||||
@@ -54,7 +59,7 @@ class CppGenerator : public BaseGenerator {
|
||||
guard += *it + "_";
|
||||
}
|
||||
guard += "H_";
|
||||
std::transform(guard.begin(), guard.end(), guard.begin(), ::toupper);
|
||||
std::transform(guard.begin(), guard.end(), guard.begin(), ToUpper);
|
||||
return guard;
|
||||
}
|
||||
|
||||
@@ -67,13 +72,15 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
for (auto it = parser_.included_files_.begin();
|
||||
it != parser_.included_files_.end(); ++it) {
|
||||
const auto basename =
|
||||
flatbuffers::StripPath(flatbuffers::StripExtension(it->first));
|
||||
if (basename != file_name_) {
|
||||
code_ += "#include \"" + parser_.opts.include_prefix + basename +
|
||||
"_generated.h\"";
|
||||
num_includes++;
|
||||
}
|
||||
if (it->second.empty())
|
||||
continue;
|
||||
auto noext = flatbuffers::StripExtension(it->second);
|
||||
auto basename = flatbuffers::StripPath(noext);
|
||||
|
||||
code_ += "#include \"" + parser_.opts.include_prefix +
|
||||
(parser_.opts.keep_include_path ? noext : basename) +
|
||||
"_generated.h\"";
|
||||
num_includes++;
|
||||
}
|
||||
if (num_includes) code_ += "";
|
||||
}
|
||||
@@ -81,10 +88,8 @@ class CppGenerator : public BaseGenerator {
|
||||
// Iterate through all definitions we haven't generate code for (enums,
|
||||
// structs, and tables) and output them to a single file.
|
||||
bool generate() {
|
||||
if (IsEverythingGenerated()) return true;
|
||||
|
||||
code_.Clear();
|
||||
code_ += "// " + std::string(FlatBuffersGeneratedWarning());
|
||||
code_ += "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
|
||||
|
||||
const auto include_guard = GenIncludeGuard();
|
||||
code_ += "#ifndef " + include_guard;
|
||||
@@ -92,6 +97,9 @@ class CppGenerator : public BaseGenerator {
|
||||
code_ += "";
|
||||
|
||||
code_ += "#include \"flatbuffers/flatbuffers.h\"";
|
||||
if (parser_.uses_flexbuffers_) {
|
||||
code_ += "#include \"flatbuffers/flexbuffers.h\"";
|
||||
}
|
||||
code_ += "";
|
||||
|
||||
if (parser_.opts.include_dependence_headers) {
|
||||
@@ -109,7 +117,7 @@ class CppGenerator : public BaseGenerator {
|
||||
SetNameSpace(struct_def.defined_namespace);
|
||||
code_ += "struct " + struct_def.name + ";";
|
||||
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_ += "";
|
||||
}
|
||||
@@ -239,7 +247,7 @@ class CppGenerator : public BaseGenerator {
|
||||
if (parser_.opts.generate_object_based_api) {
|
||||
// A convenient root unpack function.
|
||||
auto native_name =
|
||||
NativeName(WrapInNameSpace(struct_def));
|
||||
NativeName(WrapInNameSpace(struct_def), &struct_def);
|
||||
code_.SetValue("UNPACK_RETURN",
|
||||
GenTypeNativePtr(native_name, nullptr, false));
|
||||
code_.SetValue("UNPACK_TYPE",
|
||||
@@ -255,8 +263,7 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
}
|
||||
|
||||
assert(cur_name_space_);
|
||||
SetNameSpace(nullptr);
|
||||
if (cur_name_space_) SetNameSpace(nullptr);
|
||||
|
||||
// Close the include guard.
|
||||
code_ += "#endif // " + include_guard;
|
||||
@@ -355,13 +362,24 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
|
||||
// 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) {
|
||||
auto attr = field ? field->attributes.Lookup("cpp_ptr_type") : nullptr;
|
||||
return attr ? attr->constant : parser_.opts.cpp_object_api_pointer_type;
|
||||
}
|
||||
|
||||
const std::string NativeString(const FieldDef *field) {
|
||||
auto attr = field ? field->attributes.Lookup("cpp_str_type") : nullptr;
|
||||
auto &ret = attr ? attr->constant : parser_.opts.cpp_object_api_string_type;
|
||||
if (ret.empty()) {
|
||||
return "std::string";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string GenTypeNativePtr(const std::string &type, const FieldDef *field,
|
||||
bool is_constructor) {
|
||||
auto &ptr_type = PtrType(field);
|
||||
@@ -383,7 +401,7 @@ class CppGenerator : public BaseGenerator {
|
||||
const FieldDef &field) {
|
||||
switch (type.base_type) {
|
||||
case BASE_TYPE_STRING: {
|
||||
return "std::string";
|
||||
return NativeString(&field);
|
||||
}
|
||||
case BASE_TYPE_VECTOR: {
|
||||
const auto type_name = GenTypeNative(type.VectorType(), true, field);
|
||||
@@ -402,7 +420,8 @@ class CppGenerator : public BaseGenerator {
|
||||
return GenTypeNativePtr(type_name, &field, false);
|
||||
}
|
||||
} else {
|
||||
return GenTypeNativePtr(NativeName(type_name), &field, false);
|
||||
return GenTypeNativePtr(NativeName(type_name, type.struct_def),
|
||||
&field, false);
|
||||
}
|
||||
}
|
||||
case BASE_TYPE_UNION: {
|
||||
@@ -449,6 +468,27 @@ 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);
|
||||
return ev.name;
|
||||
}
|
||||
}
|
||||
|
||||
static std::string UnionVerifySignature(const EnumDef &enum_def) {
|
||||
return "bool Verify" + enum_def.name +
|
||||
"(flatbuffers::Verifier &verifier, const void *obj, " +
|
||||
@@ -465,7 +505,7 @@ class CppGenerator : public BaseGenerator {
|
||||
static std::string UnionUnPackSignature(const EnumDef &enum_def,
|
||||
bool inclass) {
|
||||
return (inclass ? "static " : "") +
|
||||
std::string("flatbuffers::NativeTable *") +
|
||||
std::string("void *") +
|
||||
(inclass ? "" : enum_def.name + "Union::") +
|
||||
"UnPack(const void *obj, " + enum_def.name +
|
||||
" type, const flatbuffers::resolver_function_t *resolver)";
|
||||
@@ -484,7 +524,7 @@ class CppGenerator : public BaseGenerator {
|
||||
return "flatbuffers::Offset<" + struct_def.name + "> Create" +
|
||||
struct_def.name +
|
||||
"(flatbuffers::FlatBufferBuilder &_fbb, const " +
|
||||
NativeName(struct_def.name) +
|
||||
NativeName(struct_def.name, &struct_def) +
|
||||
" *_o, const flatbuffers::rehasher_function_t *_rehasher" +
|
||||
(predecl ? " = nullptr" : "") + ")";
|
||||
}
|
||||
@@ -495,14 +535,14 @@ class CppGenerator : public BaseGenerator {
|
||||
"flatbuffers::Offset<" + struct_def.name + "> " +
|
||||
(inclass ? "" : struct_def.name + "::") +
|
||||
"Pack(flatbuffers::FlatBufferBuilder &_fbb, " +
|
||||
"const " + NativeName(struct_def.name) + "* _o, " +
|
||||
"const " + NativeName(struct_def.name, &struct_def) + "* _o, " +
|
||||
"const flatbuffers::rehasher_function_t *_rehasher" +
|
||||
(inclass ? " = nullptr" : "") + ")";
|
||||
}
|
||||
|
||||
static std::string TableUnPackSignature(const StructDef &struct_def,
|
||||
bool inclass) {
|
||||
return NativeName(struct_def.name) + " *" +
|
||||
return NativeName(struct_def.name, &struct_def) + " *" +
|
||||
(inclass ? "" : struct_def.name + "::") +
|
||||
"UnPack(const flatbuffers::resolver_function_t *_resolver" +
|
||||
(inclass ? " = nullptr" : "") + ") const";
|
||||
@@ -511,12 +551,14 @@ class CppGenerator : public BaseGenerator {
|
||||
static std::string TableUnPackToSignature(const StructDef &struct_def,
|
||||
bool inclass) {
|
||||
return "void " + (inclass ? "" : struct_def.name + "::") +
|
||||
"UnPackTo(" + NativeName(struct_def.name) + " *" + "_o, " +
|
||||
"const flatbuffers::resolver_function_t *_resolver" +
|
||||
"UnPackTo(" + NativeName(struct_def.name, &struct_def) + " *" +
|
||||
"_o, const flatbuffers::resolver_function_t *_resolver" +
|
||||
(inclass ? " = nullptr" : "") + ") const";
|
||||
}
|
||||
|
||||
// Generate an enum declaration and an enum string lookup table.
|
||||
// Generate an enum declaration,
|
||||
// an enum string lookup table,
|
||||
// and an enum array of values
|
||||
void GenEnum(const EnumDef &enum_def) {
|
||||
code_.SetValue("ENUM_NAME", enum_def.name);
|
||||
code_.SetValue("BASE_TYPE", GenTypeBasic(enum_def.underlying_type, false));
|
||||
@@ -575,6 +617,22 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
code_ += "";
|
||||
|
||||
// Generate an array of all enumeration values
|
||||
auto num_fields = NumToString(enum_def.vals.vec.size());
|
||||
code_ += "inline {{ENUM_NAME}} (&EnumValues{{ENUM_NAME}}())[" + num_fields + "] {";
|
||||
code_ += " static {{ENUM_NAME}} values[] = {";
|
||||
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
|
||||
++it) {
|
||||
const auto &ev = **it;
|
||||
auto value = GetEnumValUse(enum_def, ev);
|
||||
auto suffix = *it != enum_def.vals.vec.back() ? "," : "";
|
||||
code_ += " " + value + suffix;
|
||||
}
|
||||
code_ += " };";
|
||||
code_ += " return values;";
|
||||
code_ += "}";
|
||||
code_ += "";
|
||||
|
||||
// Generate a generate string table for enum values.
|
||||
// Problem is, if values are very sparse that could generate really big
|
||||
// tables. Ideally in that case we generate a map lookup instead, but for
|
||||
@@ -620,7 +678,7 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
|
||||
// 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();
|
||||
++it) {
|
||||
const auto &ev = **it;
|
||||
@@ -629,7 +687,7 @@ class CppGenerator : public BaseGenerator {
|
||||
code_ += "template<typename T> struct {{ENUM_NAME}}Traits {";
|
||||
}
|
||||
else {
|
||||
auto name = WrapInNameSpace(*ev.struct_def);
|
||||
auto name = GetUnionElement(ev, true, true);
|
||||
code_ += "template<> struct {{ENUM_NAME}}Traits<" + name + "> {";
|
||||
}
|
||||
|
||||
@@ -648,26 +706,32 @@ class CppGenerator : public BaseGenerator {
|
||||
|
||||
code_ += "struct {{NAME}}Union {";
|
||||
code_ += " {{NAME}} type;";
|
||||
code_ += " flatbuffers::NativeTable *table;";
|
||||
code_ += " void *value;";
|
||||
code_ += "";
|
||||
code_ += " {{NAME}}Union() : type({{NONE}}), table(nullptr) {}";
|
||||
code_ += " {{NAME}}Union({{NAME}}Union&& u):";
|
||||
code_ += " type(std::move(u.type)), table(std::move(u.table)) {}";
|
||||
code_ += " {{NAME}}Union(const {{NAME}}Union &);";
|
||||
code_ += " {{NAME}}Union &operator=(const {{NAME}}Union &);";
|
||||
code_ += " {{NAME}}Union() : type({{NONE}}), value(nullptr) {}";
|
||||
code_ += " {{NAME}}Union({{NAME}}Union&& u) FLATBUFFERS_NOEXCEPT :";
|
||||
code_ += " type({{NONE}}), value(nullptr)";
|
||||
code_ += " { std::swap(type, u.type); std::swap(value, u.value); }";
|
||||
code_ += " {{NAME}}Union(const {{NAME}}Union &) FLATBUFFERS_NOEXCEPT;";
|
||||
code_ += " {{NAME}}Union &operator=(const {{NAME}}Union &u) FLATBUFFERS_NOEXCEPT";
|
||||
code_ += " { {{NAME}}Union t(u); std::swap(type, t.type); std::swap(value, t.value); return *this; }";
|
||||
code_ += " {{NAME}}Union &operator=({{NAME}}Union &&u) FLATBUFFERS_NOEXCEPT";
|
||||
code_ += " { std::swap(type, u.type); std::swap(value, u.value); return *this; }";
|
||||
code_ += " ~{{NAME}}Union() { Reset(); }";
|
||||
code_ += "";
|
||||
code_ += " void Reset();";
|
||||
code_ += "";
|
||||
code_ += " template <typename T>";
|
||||
code_ += " void Set(T&& value) {";
|
||||
code_ += " Reset();";
|
||||
code_ += " type = {{NAME}}Traits<typename T::TableType>::enum_value;";
|
||||
code_ += " if (type != {{NONE}}) {";
|
||||
code_ += " table = new T(std::forward<T>(value));";
|
||||
code_ += " }";
|
||||
code_ += " }";
|
||||
code_ += "";
|
||||
if (!enum_def.uses_type_aliases) {
|
||||
code_ += " template <typename T>";
|
||||
code_ += " void Set(T&& val) {";
|
||||
code_ += " Reset();";
|
||||
code_ += " type = {{NAME}}Traits<typename T::TableType>::enum_value;";
|
||||
code_ += " if (type != {{NONE}}) {";
|
||||
code_ += " value = new T(std::forward<T>(val));";
|
||||
code_ += " }";
|
||||
code_ += " }";
|
||||
code_ += "";
|
||||
}
|
||||
code_ += " " + UnionUnPackSignature(enum_def, true) + ";";
|
||||
code_ += " " + UnionPackSignature(enum_def, true) + ";";
|
||||
code_ += "";
|
||||
@@ -679,14 +743,16 @@ class CppGenerator : public BaseGenerator {
|
||||
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_NAME", ev.name);
|
||||
code_.SetValue("NATIVE_ID", GetEnumValUse(enum_def, ev));
|
||||
|
||||
code_ += " {{NATIVE_TYPE}} *As{{NATIVE_NAME}}() {";
|
||||
code_ += " return type == {{NATIVE_ID}} ?";
|
||||
code_ += " reinterpret_cast<{{NATIVE_TYPE}} *>(table) : nullptr;";
|
||||
code_ += " reinterpret_cast<{{NATIVE_TYPE}} *>(value) : nullptr;";
|
||||
code_ += " }";
|
||||
}
|
||||
code_ += "};";
|
||||
@@ -716,10 +782,23 @@ class CppGenerator : public BaseGenerator {
|
||||
code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
|
||||
|
||||
if (ev.value) {
|
||||
code_.SetValue("TYPE", WrapInNameSpace(*ev.struct_def));
|
||||
code_.SetValue("TYPE", GetUnionElement(ev, true, true));
|
||||
code_ += " case {{LABEL}}: {";
|
||||
code_ += " auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);";
|
||||
code_ += " return verifier.VerifyTable(ptr);";
|
||||
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);";
|
||||
}
|
||||
} else if (ev.union_type.base_type == BASE_TYPE_STRING) {
|
||||
code_ += getptr;
|
||||
code_ += " return verifier.Verify(ptr);";
|
||||
} else {
|
||||
assert(false);
|
||||
}
|
||||
code_ += " }";
|
||||
} else {
|
||||
code_ += " case {{LABEL}}: {";
|
||||
@@ -756,10 +835,21 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
|
||||
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_ += " auto ptr = reinterpret_cast<const {{TYPE}} *>(obj);";
|
||||
code_ += " return ptr->UnPack(resolver);";
|
||||
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);";
|
||||
}
|
||||
} 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_ += " default: return nullptr;";
|
||||
@@ -777,11 +867,23 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
|
||||
code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
|
||||
code_.SetValue("TYPE", NativeName(WrapInNameSpace(*ev.struct_def)));
|
||||
code_.SetValue("NAME", ev.struct_def->name);
|
||||
code_.SetValue("TYPE", NativeName(GetUnionElement(ev, true, true, true),
|
||||
ev.union_type.struct_def));
|
||||
code_.SetValue("NAME", GetUnionElement(ev, false, true));
|
||||
code_ += " case {{LABEL}}: {";
|
||||
code_ += " auto ptr = reinterpret_cast<const {{TYPE}} *>(table);";
|
||||
code_ += " return Create{{NAME}}(_fbb, ptr, _rehasher).Union();";
|
||||
code_ += " auto ptr = reinterpret_cast<const {{TYPE}} *>(value);";
|
||||
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_ += " default: return 0;";
|
||||
@@ -789,6 +891,49 @@ class CppGenerator : public BaseGenerator {
|
||||
code_ += "}";
|
||||
code_ += "";
|
||||
|
||||
// Union copy constructor
|
||||
code_ += "inline {{ENUM_NAME}}Union::{{ENUM_NAME}}Union(const "
|
||||
"{{ENUM_NAME}}Union &u) FLATBUFFERS_NOEXCEPT : type(u.type), "
|
||||
"value(nullptr) {";
|
||||
code_ += " switch (type) {";
|
||||
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
|
||||
++it) {
|
||||
const auto &ev = **it;
|
||||
if (!ev.value) {
|
||||
continue;
|
||||
}
|
||||
code_.SetValue("LABEL", GetEnumValUse(enum_def, ev));
|
||||
code_.SetValue("TYPE", NativeName(GetUnionElement(ev, true, true, true),
|
||||
ev.union_type.struct_def));
|
||||
code_ += " case {{LABEL}}: {";
|
||||
bool copyable = true;
|
||||
if (ev.union_type.base_type == BASE_TYPE_STRUCT) {
|
||||
// Don't generate code to copy if table is not copyable.
|
||||
// TODO(wvo): make tables copyable instead.
|
||||
for (auto fit = ev.union_type.struct_def->fields.vec.begin();
|
||||
fit != ev.union_type.struct_def->fields.vec.end(); ++fit) {
|
||||
const auto &field = **fit;
|
||||
if (!field.deprecated && field.value.type.struct_def) {
|
||||
copyable = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (copyable) {
|
||||
code_ += " value = new {{TYPE}}(*reinterpret_cast<{{TYPE}} *>"
|
||||
"(u.value));";
|
||||
} else {
|
||||
code_ += " assert(false); // {{TYPE}} not copyable.";
|
||||
}
|
||||
code_ += " break;";
|
||||
code_ += " }";
|
||||
}
|
||||
code_ += " default:";
|
||||
code_ += " break;";
|
||||
code_ += " }";
|
||||
code_ += "}";
|
||||
code_ += "";
|
||||
|
||||
// Union Reset() function.
|
||||
code_.SetValue("NONE",
|
||||
GetEnumValUse(enum_def, *enum_def.vals.Lookup("NONE")));
|
||||
@@ -801,19 +946,18 @@ class CppGenerator : public BaseGenerator {
|
||||
if (!ev.value) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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_ += " auto ptr = reinterpret_cast<{{TYPE}} *>(table);";
|
||||
code_ += " auto ptr = reinterpret_cast<{{TYPE}} *>(value);";
|
||||
code_ += " delete ptr;";
|
||||
code_ += " break;";
|
||||
code_ += " }";
|
||||
}
|
||||
code_ += " default: break;";
|
||||
code_ += " }";
|
||||
code_ += " table = nullptr;";
|
||||
code_ += " value = nullptr;";
|
||||
code_ += " type = {{NONE}};";
|
||||
code_ += "}";
|
||||
code_ += "";
|
||||
@@ -840,7 +984,7 @@ class CppGenerator : public BaseGenerator {
|
||||
|
||||
std::string GenFieldOffsetName(const FieldDef &field) {
|
||||
std::string uname = field.name;
|
||||
std::transform(uname.begin(), uname.end(), uname.begin(), ::toupper);
|
||||
std::transform(uname.begin(), uname.end(), uname.begin(), ToUpper);
|
||||
return "VT_" + uname;
|
||||
}
|
||||
|
||||
@@ -902,7 +1046,9 @@ class CppGenerator : public BaseGenerator {
|
||||
// Generate a member, including a default value for scalars and raw pointers.
|
||||
void GenMember(const FieldDef &field) {
|
||||
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 cpp_type = field.attributes.Lookup("cpp_type");
|
||||
auto full_type = (cpp_type ? cpp_type->constant + " *" : type + " ");
|
||||
@@ -952,7 +1098,7 @@ class CppGenerator : public BaseGenerator {
|
||||
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_ += " {{NATIVE_NAME}}(){{INIT_LIST}} {";
|
||||
@@ -960,7 +1106,7 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
|
||||
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("NATIVE_NAME", native_name);
|
||||
|
||||
@@ -984,7 +1130,12 @@ class CppGenerator : public BaseGenerator {
|
||||
code_.SetValue("REQUIRED", field.required ? "Required" : "");
|
||||
code_.SetValue("SIZE", GenTypeSize(field.value.type));
|
||||
code_.SetValue("OFFSET", GenFieldOffsetName(field));
|
||||
code_ += "{{PRE}}VerifyField{{REQUIRED}}<{{SIZE}}>(verifier, {{OFFSET}})\\";
|
||||
if (IsScalar(field.value.type.base_type) || IsStruct(field.value.type)) {
|
||||
code_ +=
|
||||
"{{PRE}}VerifyField{{REQUIRED}}<{{SIZE}}>(verifier, {{OFFSET}})\\";
|
||||
} else {
|
||||
code_ += "{{PRE}}VerifyOffset{{REQUIRED}}(verifier, {{OFFSET}})\\";
|
||||
}
|
||||
|
||||
switch (field.value.type.base_type) {
|
||||
case BASE_TYPE_UNION: {
|
||||
@@ -1118,16 +1269,50 @@ class CppGenerator : public BaseGenerator {
|
||||
code_ += " return {{FIELD_VALUE}};";
|
||||
code_ += " }";
|
||||
|
||||
if (field.value.type.base_type == BASE_TYPE_UNION) {
|
||||
auto u = field.value.type.enum_def;
|
||||
|
||||
code_ += " template<typename T> "
|
||||
"const T *{{FIELD_NAME}}_as() const;";
|
||||
|
||||
for (auto u_it = u->vals.vec.begin();
|
||||
u_it != u->vals.vec.end(); ++u_it) {
|
||||
auto &ev = **u_it;
|
||||
if (ev.union_type.base_type == BASE_TYPE_NONE) {
|
||||
continue;
|
||||
}
|
||||
auto full_struct_name = GetUnionElement(ev, true, true);
|
||||
|
||||
// @TODO: Mby make this decisions more universal? How?
|
||||
code_.SetValue("U_GET_TYPE", field.name + UnionTypeFieldSuffix());
|
||||
code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace(
|
||||
u->defined_namespace, GetEnumValUse(*u, ev)));
|
||||
code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
|
||||
code_.SetValue("U_FIELD_NAME",
|
||||
field.name + "_as_" + ev.name);
|
||||
|
||||
// `const Type *union_name_asType() const` accessor.
|
||||
code_ += " {{U_FIELD_TYPE}}{{U_FIELD_NAME}}() const {";
|
||||
code_ += " return {{U_GET_TYPE}}() == {{U_ELEMENT_TYPE}} ? "
|
||||
"static_cast<{{U_FIELD_TYPE}}>({{FIELD_NAME}}()) "
|
||||
": nullptr;";
|
||||
code_ += " }";
|
||||
}
|
||||
}
|
||||
|
||||
if (parser_.opts.mutable_buffer) {
|
||||
if (is_scalar) {
|
||||
const auto type = GenTypeWire(field.value.type, "", false);
|
||||
code_.SetValue("SET_FN", "SetField<" + type + ">");
|
||||
code_.SetValue("OFFSET_NAME", offset_str);
|
||||
code_.SetValue("FIELD_TYPE", GenTypeBasic(field.value.type, true));
|
||||
code_.SetValue("FIELD_VALUE",
|
||||
GenUnderlyingCast(field, false, "_" + field.name));
|
||||
code_.SetValue("DEFAULT_VALUE", GenDefaultConstant(field));
|
||||
|
||||
code_ += " bool mutate_{{FIELD_NAME}}({{FIELD_TYPE}} "
|
||||
"_{{FIELD_NAME}}) {";
|
||||
code_ += " return SetField({{OFFSET_NAME}}, {{FIELD_VALUE}});";
|
||||
code_ += " return {{SET_FN}}({{OFFSET_NAME}}, {{FIELD_VALUE}}, {{DEFAULT_VALUE}});";
|
||||
code_ += " }";
|
||||
} else {
|
||||
auto type = GenTypeGet(field.value.type, " ", "", " *", true);
|
||||
@@ -1153,11 +1338,19 @@ class CppGenerator : public BaseGenerator {
|
||||
code_.SetValue("CPP_NAME", TranslateNameSpace(qualified_name));
|
||||
|
||||
code_ += " const {{CPP_NAME}} *{{FIELD_NAME}}_nested_root() const {";
|
||||
code_ += " const uint8_t* data = {{FIELD_NAME}}()->Data();";
|
||||
code_ += " auto data = {{FIELD_NAME}}()->Data();";
|
||||
code_ += " return flatbuffers::GetRoot<{{CPP_NAME}}>(data);";
|
||||
code_ += " }";
|
||||
}
|
||||
|
||||
if (field.flexbuffer) {
|
||||
code_ += " flexbuffers::Reference {{FIELD_NAME}}_flexbuffer_root()"
|
||||
" const {";
|
||||
code_ += " auto v = {{FIELD_NAME}}();";
|
||||
code_ += " return flexbuffers::GetRoot(v->Data(), v->size());";
|
||||
code_ += " }";
|
||||
}
|
||||
|
||||
// Generate a comparison function for this field if it is a key.
|
||||
if (field.key) {
|
||||
const bool is_string = (field.value.type.base_type == BASE_TYPE_STRING);
|
||||
@@ -1222,6 +1415,46 @@ class CppGenerator : public BaseGenerator {
|
||||
code_ += "};"; // End of table.
|
||||
code_ += "";
|
||||
|
||||
// Explicit specializations for union accessors
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
const auto &field = **it;
|
||||
if (field.deprecated ||
|
||||
field.value.type.base_type != BASE_TYPE_UNION) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto u = field.value.type.enum_def;
|
||||
if (u->uses_type_aliases) continue;
|
||||
|
||||
code_.SetValue("FIELD_NAME", field.name);
|
||||
|
||||
for (auto u_it = u->vals.vec.begin();
|
||||
u_it != u->vals.vec.end(); ++u_it) {
|
||||
auto &ev = **u_it;
|
||||
if (ev.union_type.base_type == BASE_TYPE_NONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto full_struct_name = GetUnionElement(ev, true, true);
|
||||
|
||||
code_.SetValue("U_ELEMENT_TYPE", WrapInNameSpace(
|
||||
u->defined_namespace, GetEnumValUse(*u, ev)));
|
||||
code_.SetValue("U_FIELD_TYPE", "const " + full_struct_name + " *");
|
||||
code_.SetValue("U_ELEMENT_NAME", full_struct_name);
|
||||
code_.SetValue("U_FIELD_NAME",
|
||||
field.name + "_as_" + ev.name);
|
||||
|
||||
// `template<> const T *union_name_as<T>() const` accessor.
|
||||
code_ += "template<> "
|
||||
"inline {{U_FIELD_TYPE}}{{STRUCT_NAME}}::{{FIELD_NAME}}_as"
|
||||
"<{{U_ELEMENT_NAME}}>() const {";
|
||||
code_ += " return {{U_FIELD_NAME}}();";
|
||||
code_ += "}";
|
||||
code_ += "";
|
||||
}
|
||||
}
|
||||
|
||||
GenBuilders(struct_def);
|
||||
|
||||
if (parser_.opts.generate_object_based_api) {
|
||||
@@ -1390,6 +1623,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,
|
||||
bool invector, const FieldDef &afield) {
|
||||
switch (type.base_type) {
|
||||
@@ -1409,10 +1650,18 @@ class CppGenerator : public BaseGenerator {
|
||||
return ptype + "(new " + name + "(*" + val + "))";
|
||||
}
|
||||
} 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))";
|
||||
}
|
||||
}
|
||||
case BASE_TYPE_UNION: {
|
||||
return GenUnionUnpackVal(afield,
|
||||
invector ? "->Get(_i)" : "",
|
||||
invector ? ("->GetEnum<" +
|
||||
type.enum_def->name +
|
||||
">(_i)").c_str() : "");
|
||||
}
|
||||
default: {
|
||||
return val;
|
||||
break;
|
||||
@@ -1438,12 +1687,22 @@ class CppGenerator : public BaseGenerator {
|
||||
// for (uoffset_t i = 0; i < _e->size(); ++i) {
|
||||
// _o->field.push_back(_e->Get(_i));
|
||||
// }
|
||||
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 += " _i < _e->size(); _i++) { ";
|
||||
code += "_o->" + field.name + ".push_back(";
|
||||
code += "_o->" + name + "[_i]" + access + " = ";
|
||||
code += GenUnpackVal(field.value.type.VectorType(),
|
||||
indexing, true, field);
|
||||
code += "); }";
|
||||
code += "; } }";
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_UTYPE: {
|
||||
@@ -1454,12 +1713,11 @@ class CppGenerator : public BaseGenerator {
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_UNION: {
|
||||
// Generate code that sets the union table, of the form:
|
||||
// _o->field.table = Union::Unpack(_e, field_type(), resolver);
|
||||
code += "_o->" + field.name + ".table = ";
|
||||
code += field.value.type.enum_def->name + "Union::UnPack(";
|
||||
code += "_e, " + field.name + UnionTypeFieldSuffix() + "(),";
|
||||
code += "_resolver);";
|
||||
// Generate code that sets the union value, of the form:
|
||||
// _o->field.value = Union::Unpack(_e, field_type(), resolver);
|
||||
code += "_o->" + field.name + ".value = ";
|
||||
code += GenUnionUnpackVal(field, "", "");
|
||||
code += ";";
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -1491,8 +1749,7 @@ class CppGenerator : public BaseGenerator {
|
||||
std::string GenCreateParam(const FieldDef &field) {
|
||||
std::string value = "_o->";
|
||||
if (field.value.type.base_type == BASE_TYPE_UTYPE) {
|
||||
value += field.name.substr(0, field.name.size() -
|
||||
strlen(UnionTypeFieldSuffix()));
|
||||
value += StripUnionType(field.name);
|
||||
value += ".type";
|
||||
} else {
|
||||
value += field.name;
|
||||
@@ -1534,7 +1791,15 @@ class CppGenerator : public BaseGenerator {
|
||||
}
|
||||
case BASE_TYPE_STRUCT: {
|
||||
if (IsStruct(vector_type)) {
|
||||
code += "_fbb.CreateVectorOfStructs(" + value + ")";
|
||||
auto native_type =
|
||||
field.value.type.struct_def->attributes.Lookup("native_type");
|
||||
if (native_type) {
|
||||
code += "_fbb.CreateVectorOfNativeStructs<";
|
||||
code += WrapInNameSpace(*vector_type.struct_def) + ">";
|
||||
} else {
|
||||
code += "_fbb.CreateVectorOfStructs";
|
||||
}
|
||||
code += "(" + value + ")";
|
||||
} else {
|
||||
code += "_fbb.CreateVector<flatbuffers::Offset<";
|
||||
code += WrapInNameSpace(*vector_type.struct_def) + ">>";
|
||||
@@ -1549,6 +1814,19 @@ class CppGenerator : public BaseGenerator {
|
||||
code += "_fbb.CreateVector(" + value + ")";
|
||||
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: {
|
||||
if (field.value.type.enum_def) {
|
||||
// For enumerations, we need to get access to the array data for
|
||||
@@ -1607,7 +1885,7 @@ class CppGenerator : public BaseGenerator {
|
||||
// Generate code for tables that needs to come after the regular definition.
|
||||
void GenTablePost(const StructDef &struct_def) {
|
||||
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) {
|
||||
// Generate the X::UnPack() method.
|
||||
@@ -1844,6 +2122,8 @@ class CppGenerator : public BaseGenerator {
|
||||
code_ += " }";
|
||||
|
||||
if (parser_.opts.mutable_buffer) {
|
||||
auto mut_field_type = GenTypeGet(field.value.type, " ", "", " &", true);
|
||||
code_.SetValue("FIELD_TYPE", mut_field_type);
|
||||
if (is_scalar) {
|
||||
code_.SetValue("ARG", GenTypeBasic(field.value.type, true));
|
||||
code_.SetValue("FIELD_VALUE",
|
||||
@@ -1859,6 +2139,24 @@ class CppGenerator : public BaseGenerator {
|
||||
code_ += " }";
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a comparison function for this field if it is a key.
|
||||
if (field.key) {
|
||||
code_ += " bool KeyCompareLessThan(const {{STRUCT_NAME}} *o) const {";
|
||||
code_ += " return {{FIELD_NAME}}() < o->{{FIELD_NAME}}();";
|
||||
code_ += " }";
|
||||
auto type = GenTypeBasic(field.value.type, false);
|
||||
if (parser_.opts.scoped_enums && field.value.type.enum_def &&
|
||||
IsScalar(field.value.type.base_type)) {
|
||||
type = GenTypeGet(field.value.type, " ", "const ", " *", true);
|
||||
}
|
||||
|
||||
code_.SetValue("KEY_TYPE", type);
|
||||
code_ += " int KeyCompareWithValue({{KEY_TYPE}} val) const {";
|
||||
code_ += " const auto key = {{FIELD_NAME}}();";
|
||||
code_ += " return static_cast<int>(key > val) - static_cast<int>(key < val);";
|
||||
code_ += " }";
|
||||
}
|
||||
}
|
||||
code_ += "};";
|
||||
|
||||
|
||||
@@ -72,12 +72,12 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
|
||||
int num_includes = 0;
|
||||
for (auto it = parser.included_files_.begin();
|
||||
it != parser.included_files_.end(); ++it) {
|
||||
if (it->second.empty())
|
||||
continue;
|
||||
auto basename = flatbuffers::StripPath(
|
||||
flatbuffers::StripExtension(it->first));
|
||||
if (basename != file_name) {
|
||||
schema += "include \"" + basename + ".fbs\";\n";
|
||||
num_includes++;
|
||||
}
|
||||
flatbuffers::StripExtension(it->second));
|
||||
schema += "include \"" + basename + ".fbs\";\n";
|
||||
num_includes++;
|
||||
}
|
||||
if (num_includes) schema += "\n";
|
||||
#endif
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "flatbuffers/idl.h"
|
||||
#include "flatbuffers/util.h"
|
||||
#include "flatbuffers/code_generators.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
@@ -128,7 +127,7 @@ const LanguageParameters& GetLangParams(IDLOptions::Language lang) {
|
||||
"__p.",
|
||||
"Table.",
|
||||
"?",
|
||||
"using System;\nusing FlatBuffers;\n\n",
|
||||
"using global::System;\nusing global::FlatBuffers;\n\n",
|
||||
{
|
||||
nullptr,
|
||||
"///",
|
||||
@@ -204,7 +203,14 @@ class GeneralGenerator : public BaseGenerator {
|
||||
if (!classcode.length()) return true;
|
||||
|
||||
std::string code;
|
||||
code = code + "// " + FlatBuffersGeneratedWarning();
|
||||
if (lang_.language == IDLOptions::kCSharp) {
|
||||
code = "// <auto-generated>\n"
|
||||
"// " + std::string(FlatBuffersGeneratedWarning()) + "\n"
|
||||
"// </auto-generated>\n\n";
|
||||
} else {
|
||||
code = "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
|
||||
}
|
||||
|
||||
std::string namespace_name = FullNamespace(".", ns);
|
||||
if (!namespace_name.empty()) {
|
||||
code += lang_.namespace_ident + namespace_name + lang_.namespace_begin;
|
||||
@@ -301,7 +307,7 @@ Type DestinationType(const Type &type, bool vectorelem) {
|
||||
case BASE_TYPE_VECTOR:
|
||||
if (vectorelem)
|
||||
return DestinationType(type.VectorType(), vectorelem);
|
||||
// else fall thru:
|
||||
// else fall thru
|
||||
default: return type;
|
||||
}
|
||||
}
|
||||
@@ -348,7 +354,7 @@ std::string DestinationMask(const Type &type, bool vectorelem) {
|
||||
case BASE_TYPE_VECTOR:
|
||||
if (vectorelem)
|
||||
return DestinationMask(type.VectorType(), vectorelem);
|
||||
// else fall thru:
|
||||
// else fall thru
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
@@ -587,6 +593,22 @@ std::string GenGetter(const Type &type) {
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the function name that is able to read a value of the given type.
|
||||
std::string GenGetterForLookupByKey(flatbuffers::FieldDef *key_field,
|
||||
const std::string &data_buffer,
|
||||
const char *num = nullptr) {
|
||||
auto type = key_field->value.type;
|
||||
auto dest_mask = DestinationMask(type, true);
|
||||
auto dest_cast = DestinationCast(type);
|
||||
auto getter = data_buffer + "." + FunctionStart('G') + "et";
|
||||
if (GenTypeBasic(type, false) != "byte") {
|
||||
getter += MakeCamel(GenTypeBasic(type, false));
|
||||
}
|
||||
getter = dest_cast + getter + "(" + GenOffsetGetter(key_field, num) + ")"
|
||||
+ dest_mask;
|
||||
return getter;
|
||||
}
|
||||
|
||||
// Direct mutation is only allowed for scalar fields.
|
||||
// Hence a setter method will only be generated for such fields.
|
||||
std::string GenSetter(const Type &type) {
|
||||
@@ -699,12 +721,11 @@ std::string GenLookupKeyGetter(flatbuffers::FieldDef *key_field) {
|
||||
key_getter += GenOffsetGetter(key_field);
|
||||
key_getter += ", byteKey, bb);\n";
|
||||
} else {
|
||||
auto get_val = GenGetter(key_field->value.type) +
|
||||
"(" + GenOffsetGetter(key_field) + ")";
|
||||
auto get_val = GenGetterForLookupByKey(key_field, "bb");
|
||||
if (lang_.language == IDLOptions::kCSharp) {
|
||||
key_getter += "int comp = " + get_val + ".CompareTo(key);\n";
|
||||
} else {
|
||||
key_getter += GenTypeGet(key_field->value.type) + " val = ";
|
||||
key_getter += GenTypeNameDest(key_field->value.type) + " val = ";
|
||||
key_getter += get_val + ";\n";
|
||||
key_getter += " int comp = val > key ? 1 : val < key ? -1 : 0;\n";
|
||||
}
|
||||
@@ -728,20 +749,17 @@ std::string GenKeyGetter(flatbuffers::FieldDef *key_field) {
|
||||
key_getter += ";";
|
||||
}
|
||||
else {
|
||||
auto field_getter = data_buffer + GenGetter(key_field->value.type).substr(2) +
|
||||
"(" + GenOffsetGetter(key_field, "o1") + ")";
|
||||
auto field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o1");
|
||||
if (lang_.language == IDLOptions::kCSharp) {
|
||||
key_getter += field_getter;
|
||||
field_getter = data_buffer + GenGetter(key_field->value.type).substr(2) +
|
||||
"(" + GenOffsetGetter(key_field, "o2") + ")";
|
||||
field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o2");
|
||||
key_getter += ".CompareTo(" + field_getter + ")";
|
||||
}
|
||||
else {
|
||||
key_getter += "\n " + GenTypeGet(key_field->value.type) + " val_1 = ";
|
||||
key_getter += field_getter + ";\n " + GenTypeGet(key_field->value.type);
|
||||
key_getter += "\n " + GenTypeNameDest(key_field->value.type) + " val_1 = ";
|
||||
key_getter += field_getter + ";\n " + GenTypeNameDest(key_field->value.type);
|
||||
key_getter += " val_2 = ";
|
||||
field_getter = data_buffer + GenGetter(key_field->value.type).substr(2) +
|
||||
"(" + GenOffsetGetter(key_field, "o2") + ")";
|
||||
field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o2");
|
||||
key_getter += field_getter + ";\n";
|
||||
key_getter += " return val_1 > val_2 ? 1 : val_1 < val_2 ? -1 : 0;\n ";
|
||||
}
|
||||
@@ -993,6 +1011,26 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
|
||||
code += lang_.accessor_prefix + "__vector_len(o) : 0; ";
|
||||
code += lang_.getter_suffix;
|
||||
code += "}\n";
|
||||
// See if we should generate a by-key accessor.
|
||||
if (field.value.type.element == BASE_TYPE_STRUCT &&
|
||||
!field.value.type.struct_def->fixed) {
|
||||
auto &sd = *field.value.type.struct_def;
|
||||
auto &fields = sd.fields.vec;
|
||||
for (auto kit = fields.begin(); kit != fields.end(); ++kit) {
|
||||
auto &key_field = **kit;
|
||||
if (key_field.key) {
|
||||
code += " public " + sd.name + lang_.optional_suffix + " ";
|
||||
code += MakeCamel(field.name, lang_.first_camel_upper) + "ByKey(";
|
||||
code += GenTypeNameDest(key_field.value.type) + " key)";
|
||||
code += offset_prefix;
|
||||
code += sd.name + ".__lookup_by_key(";
|
||||
code += lang_.accessor_prefix + "__vector(o), key, ";
|
||||
code += lang_.accessor_prefix + "bb) : null; ";
|
||||
code += "}\n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Generate a ByteBuffer accessor for strings & vectors of scalars.
|
||||
if ((field.value.type.base_type == BASE_TYPE_VECTOR &&
|
||||
@@ -1279,7 +1317,9 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
|
||||
code += "); }\n";
|
||||
}
|
||||
}
|
||||
if (struct_def.has_key) {
|
||||
// Only generate key compare function for table,
|
||||
// because `key_field` is not set for struct
|
||||
if (struct_def.has_key && !struct_def.fixed) {
|
||||
if (lang_.language == IDLOptions::kJava) {
|
||||
code += "\n @Override\n protected int keysCompare(";
|
||||
code += "Integer o1, Integer o2, ByteBuffer _bb) {";
|
||||
@@ -1288,7 +1328,8 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
|
||||
}
|
||||
else {
|
||||
code += "\n public static VectorOffset ";
|
||||
code += "CreateMySortedVectorOfTables(FlatBufferBuilder builder, ";
|
||||
code += "CreateSortedVectorOf" + struct_def.name;
|
||||
code += "(FlatBufferBuilder builder, ";
|
||||
code += "Offset<" + struct_def.name + ">";
|
||||
code += "[] offsets) {\n";
|
||||
code += " Array.Sort(offsets, (Offset<" + struct_def.name +
|
||||
@@ -1298,8 +1339,8 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
|
||||
}
|
||||
|
||||
code += "\n public static " + struct_def.name + lang_.optional_suffix;
|
||||
code += " " + FunctionStart('L') + "ookupByKey(" + GenVectorOffsetType();
|
||||
code += " vectorOffset, " + GenTypeGet(key_field->value.type);
|
||||
code += " __lookup_by_key(int vectorLocation, ";
|
||||
code += GenTypeNameDest(key_field->value.type);
|
||||
code += " key, ByteBuffer bb) {\n";
|
||||
if (key_field->value.type.base_type == BASE_TYPE_STRING) {
|
||||
code += " byte[] byteKey = ";
|
||||
@@ -1308,13 +1349,9 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
|
||||
else
|
||||
code += "System.Text.Encoding.UTF8.GetBytes(key);\n";
|
||||
}
|
||||
code += " int vectorLocation = " + GenByteBufferLength("bb");
|
||||
code += " - vectorOffset";
|
||||
if (lang_.language == IDLOptions::kCSharp) code += ".Value";
|
||||
code += ";\n int span = ";
|
||||
code += "bb." + FunctionStart('G') + "etInt(vectorLocation);\n";
|
||||
code += " int span = ";
|
||||
code += "bb." + FunctionStart('G') + "etInt(vectorLocation - 4);\n";
|
||||
code += " int start = 0;\n";
|
||||
code += " vectorLocation += 4;\n";
|
||||
code += " while (span != 0) {\n";
|
||||
code += " int middle = span / 2;\n";
|
||||
code += GenLookupKeyGetter(key_field);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
// independent from idl_parser, since this code is not needed for most clients
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/idl.h"
|
||||
@@ -35,6 +36,13 @@
|
||||
namespace flatbuffers {
|
||||
namespace go {
|
||||
|
||||
// see https://golang.org/ref/spec#Keywords
|
||||
static const char *g_golang_keywords[] = {
|
||||
"break", "default", "func", "interface", "select", "case", "defer", "go",
|
||||
"map", "struct", "chan", "else", "goto", "package", "switch", "const",
|
||||
"fallthrough", "if", "range", "type", "continue", "for", "import", "return", "var",
|
||||
};
|
||||
|
||||
static std::string GenGetter(const Type &type);
|
||||
static std::string GenMethod(const FieldDef &field);
|
||||
static void GenStructBuilder(const StructDef &struct_def,
|
||||
@@ -43,6 +51,15 @@ static void GenReceiver(const StructDef &struct_def, std::string *code_ptr);
|
||||
static std::string GenTypeBasic(const Type &type);
|
||||
static std::string GenTypeGet(const Type &type);
|
||||
static std::string TypeName(const FieldDef &field);
|
||||
static std::string GoIdentity(const std::string& name) {
|
||||
for (size_t i=0; i<sizeof(g_golang_keywords)/sizeof(g_golang_keywords[0]); i++) {
|
||||
if (name == g_golang_keywords[i]) {
|
||||
return MakeCamel(name + "_", false);
|
||||
}
|
||||
}
|
||||
|
||||
return MakeCamel(name, false);
|
||||
}
|
||||
|
||||
|
||||
// Most field accessors need to retrieve and test the field offset first,
|
||||
@@ -368,7 +385,7 @@ static void StructBuilderArgs(const StructDef &struct_def,
|
||||
} else {
|
||||
std::string &code = *code_ptr;
|
||||
code += (std::string)", " + nameprefix;
|
||||
code += MakeCamel(field.name, false);
|
||||
code += GoIdentity(field.name);
|
||||
code += " " + GenTypeBasic(field.value.type);
|
||||
}
|
||||
}
|
||||
@@ -400,7 +417,7 @@ static void StructBuilderBody(const StructDef &struct_def,
|
||||
code_ptr);
|
||||
} else {
|
||||
code += "\tbuilder.Prepend" + GenMethod(field) + "(";
|
||||
code += nameprefix + MakeCamel(field.name, false) + ")\n";
|
||||
code += nameprefix + GoIdentity(field.name) + ")\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -430,7 +447,7 @@ static void BuildFieldOfTable(const StructDef &struct_def,
|
||||
std::string &code = *code_ptr;
|
||||
code += "func " + struct_def.name + "Add" + MakeCamel(field.name);
|
||||
code += "(builder *flatbuffers.Builder, ";
|
||||
code += MakeCamel(field.name, false) + " ";
|
||||
code += GoIdentity(field.name) + " ";
|
||||
if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
|
||||
code += "flatbuffers.UOffsetT";
|
||||
} else {
|
||||
@@ -443,9 +460,9 @@ static void BuildFieldOfTable(const StructDef &struct_def,
|
||||
if (!IsScalar(field.value.type.base_type) && (!struct_def.fixed)) {
|
||||
code += "flatbuffers.UOffsetT";
|
||||
code += "(";
|
||||
code += MakeCamel(field.name, false) + ")";
|
||||
code += GoIdentity(field.name) + ")";
|
||||
} else {
|
||||
code += MakeCamel(field.name, false);
|
||||
code += GoIdentity(field.name);
|
||||
}
|
||||
code += ", " + field.value.constant;
|
||||
code += ")\n}\n";
|
||||
@@ -724,9 +741,15 @@ static void GenStructBuilder(const StructDef &struct_def,
|
||||
class GoGenerator : public BaseGenerator {
|
||||
public:
|
||||
GoGenerator(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name)
|
||||
: BaseGenerator(parser, path, file_name, "" /* not used*/,
|
||||
"" /* not used */){};
|
||||
const std::string &file_name, const std::string &go_namespace)
|
||||
: BaseGenerator(parser, path, file_name, "" /* not used*/, "" /* not used */) {
|
||||
std::istringstream iss(go_namespace);
|
||||
std::string component;
|
||||
while (std::getline(iss, component, '.')) {
|
||||
go_namespace_.components.push_back(component);
|
||||
}
|
||||
}
|
||||
|
||||
bool generate() {
|
||||
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
|
||||
++it) {
|
||||
@@ -750,7 +773,7 @@ class GoGenerator : public BaseGenerator {
|
||||
void BeginFile(const std::string name_space_name, const bool needs_imports,
|
||||
std::string *code_ptr) {
|
||||
std::string &code = *code_ptr;
|
||||
code = code + "// " + FlatBuffersGeneratedWarning();
|
||||
code = code + "// " + FlatBuffersGeneratedWarning() + "\n\n";
|
||||
code += "package " + name_space_name + "\n\n";
|
||||
if (needs_imports) {
|
||||
code += "import (\n";
|
||||
@@ -764,19 +787,22 @@ class GoGenerator : public BaseGenerator {
|
||||
bool needs_imports) {
|
||||
if (!classcode.length()) return true;
|
||||
|
||||
Namespace& ns = go_namespace_.components.empty() ? *def.defined_namespace : go_namespace_;
|
||||
std::string code = "";
|
||||
BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code);
|
||||
BeginFile(LastNamespacePart(ns), needs_imports, &code);
|
||||
code += classcode;
|
||||
std::string filename =
|
||||
NamespaceDir(*def.defined_namespace) + def.name + ".go";
|
||||
NamespaceDir(ns) + def.name + ".go";
|
||||
return SaveFile(filename.c_str(), code, false);
|
||||
}
|
||||
|
||||
Namespace go_namespace_;
|
||||
};
|
||||
} // namespace go
|
||||
|
||||
bool GenerateGo(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name) {
|
||||
go::GoGenerator generator(parser, path, file_name);
|
||||
go::GoGenerator generator(parser, path, file_name, parser.opts.go_namespace);
|
||||
return generator.generate();
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,11 @@
|
||||
#include "src/compiler/cpp_generator.h"
|
||||
#include "src/compiler/go_generator.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable: 4512) // C4512: 'class' : assignment operator could not be generated
|
||||
#endif
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
class FlatBufMethod : public grpc_generator::Method {
|
||||
@@ -41,30 +46,52 @@ class FlatBufMethod : public grpc_generator::Method {
|
||||
}
|
||||
}
|
||||
|
||||
grpc::string GetLeadingComments(const grpc::string) const {
|
||||
return "";
|
||||
}
|
||||
grpc::string GetTrailingComments(const grpc::string) const {
|
||||
return "";
|
||||
}
|
||||
std::vector<grpc::string> GetAllComments() const {
|
||||
return std::vector<grpc::string>();
|
||||
}
|
||||
|
||||
std::string name() const { return method_->name; }
|
||||
|
||||
std::string GRPCType(const StructDef &sd) const {
|
||||
return "flatbuffers::BufferRef<" + sd.name + ">";
|
||||
return "flatbuffers::grpc::Message<" + sd.name + ">";
|
||||
}
|
||||
|
||||
std::string get_input_type_name() const {
|
||||
return (*method_->request).name;
|
||||
}
|
||||
std::string get_output_type_name() const {
|
||||
return (*method_->response).name;
|
||||
}
|
||||
|
||||
bool get_module_and_message_path_input(
|
||||
grpc::string * /*str*/, grpc::string /*generator_file_name*/,
|
||||
bool /*generate_in_pb2_grpc*/, grpc::string /*import_prefix*/) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_module_and_message_path_output(
|
||||
grpc::string * /*str*/, grpc::string /*generator_file_name*/,
|
||||
bool /*generate_in_pb2_grpc*/, grpc::string /*import_prefix*/) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string input_type_name() const {
|
||||
return GRPCType(*method_->request);
|
||||
}
|
||||
|
||||
std::string output_type_name() const {
|
||||
return GRPCType(*method_->response);
|
||||
}
|
||||
|
||||
std::string input_name() const {
|
||||
return (*method_->request).name;
|
||||
}
|
||||
|
||||
std::string output_name() const {
|
||||
return (*method_->response).name;
|
||||
}
|
||||
|
||||
bool NoStreaming() const { return streaming_ == kNone; }
|
||||
bool ClientOnlyStreaming() const { return streaming_ == kClient; }
|
||||
bool ServerOnlyStreaming() const { return streaming_ == kServer; }
|
||||
bool ClientStreaming() const { return streaming_ == kClient; }
|
||||
bool ServerStreaming() const { return streaming_ == kServer; }
|
||||
bool BidiStreaming() const { return streaming_ == kBiDi; }
|
||||
|
||||
private:
|
||||
@@ -76,6 +103,16 @@ class FlatBufService : public grpc_generator::Service {
|
||||
public:
|
||||
FlatBufService(const ServiceDef *service) : service_(service) {}
|
||||
|
||||
grpc::string GetLeadingComments(const grpc::string) const {
|
||||
return "";
|
||||
}
|
||||
grpc::string GetTrailingComments(const grpc::string) const {
|
||||
return "";
|
||||
}
|
||||
std::vector<grpc::string> GetAllComments() const {
|
||||
return std::vector<grpc::string>();
|
||||
}
|
||||
|
||||
std::string name() const { return service_->name; }
|
||||
|
||||
int method_count() const {
|
||||
@@ -117,6 +154,9 @@ class FlatBufPrinter : public grpc_generator::Printer {
|
||||
}
|
||||
|
||||
void Print(const char *s) {
|
||||
if (s == nullptr || std::strlen(s) == 0) {
|
||||
return;
|
||||
}
|
||||
// Add this string, but for each part separated by \n, add indentation.
|
||||
for (;;) {
|
||||
// Current indentation.
|
||||
@@ -145,10 +185,26 @@ class FlatBufPrinter : public grpc_generator::Printer {
|
||||
|
||||
class FlatBufFile : public grpc_generator::File {
|
||||
public:
|
||||
FlatBufFile(const Parser &parser, const std::string &file_name)
|
||||
: parser_(parser), file_name_(file_name) {}
|
||||
enum Language {
|
||||
kLanguageGo,
|
||||
kLanguageCpp
|
||||
};
|
||||
|
||||
FlatBufFile(
|
||||
const Parser &parser, const std::string &file_name, Language language)
|
||||
: parser_(parser), file_name_(file_name), language_(language) {}
|
||||
FlatBufFile &operator=(const FlatBufFile &);
|
||||
|
||||
grpc::string GetLeadingComments(const grpc::string) const {
|
||||
return "";
|
||||
}
|
||||
grpc::string GetTrailingComments(const grpc::string) const {
|
||||
return "";
|
||||
}
|
||||
std::vector<grpc::string> GetAllComments() const {
|
||||
return std::vector<grpc::string>();
|
||||
}
|
||||
|
||||
std::string filename() const { return file_name_; }
|
||||
std::string filename_without_ext() const {
|
||||
return StripExtension(file_name_);
|
||||
@@ -166,11 +222,15 @@ class FlatBufFile : public grpc_generator::File {
|
||||
}
|
||||
|
||||
std::string additional_headers() const {
|
||||
return "#include \"flatbuffers/grpc.h\"\n";
|
||||
}
|
||||
|
||||
std::string additional_imports() const {
|
||||
return "import \"github.com/google/flatbuffers/go\"";
|
||||
switch (language_) {
|
||||
case kLanguageCpp: {
|
||||
return "#include \"flatbuffers/grpc.h\"\n";
|
||||
}
|
||||
case kLanguageGo: {
|
||||
return "import \"github.com/google/flatbuffers/go\"";
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
int service_count() const {
|
||||
@@ -190,6 +250,7 @@ class FlatBufFile : public grpc_generator::File {
|
||||
private:
|
||||
const Parser &parser_;
|
||||
const std::string &file_name_;
|
||||
const Language language_;
|
||||
};
|
||||
|
||||
class GoGRPCGenerator : public flatbuffers::BaseGenerator {
|
||||
@@ -200,7 +261,7 @@ class GoGRPCGenerator : public flatbuffers::BaseGenerator {
|
||||
parser_(parser), path_(path), file_name_(file_name) {}
|
||||
|
||||
bool generate() {
|
||||
FlatBufFile file(parser_, file_name_);
|
||||
FlatBufFile file(parser_, file_name_, FlatBufFile::kLanguageGo);
|
||||
grpc_go_generator::Parameters p;
|
||||
p.custom_method_io_type = "flatbuffers.Builder";
|
||||
for (int i = 0; i < file.service_count(); i++) {
|
||||
@@ -233,7 +294,7 @@ bool GenerateGoGRPC(const Parser &parser,
|
||||
}
|
||||
|
||||
bool GenerateCppGRPC(const Parser &parser,
|
||||
const std::string &/*path*/,
|
||||
const std::string &path,
|
||||
const std::string &file_name) {
|
||||
|
||||
int nservices = 0;
|
||||
@@ -247,7 +308,7 @@ bool GenerateCppGRPC(const Parser &parser,
|
||||
// TODO(wvo): make the other parameters in this struct configurable.
|
||||
generator_parameters.use_system_headers = true;
|
||||
|
||||
FlatBufFile fbfile(parser, file_name);
|
||||
FlatBufFile fbfile(parser, file_name, FlatBufFile::kLanguageCpp);
|
||||
|
||||
std::string header_code =
|
||||
grpc_cpp_generator::GetHeaderPrologue(&fbfile, generator_parameters) +
|
||||
@@ -261,11 +322,15 @@ bool GenerateCppGRPC(const Parser &parser,
|
||||
grpc_cpp_generator::GetSourceServices(&fbfile, generator_parameters) +
|
||||
grpc_cpp_generator::GetSourceEpilogue(&fbfile, generator_parameters);
|
||||
|
||||
return flatbuffers::SaveFile((file_name + ".grpc.fb.h").c_str(),
|
||||
return flatbuffers::SaveFile((path + file_name + ".grpc.fb.h").c_str(),
|
||||
header_code, false) &&
|
||||
flatbuffers::SaveFile((file_name + ".grpc.fb.cc").c_str(),
|
||||
flatbuffers::SaveFile((path + file_name + ".grpc.fb.cc").c_str(),
|
||||
source_code, false);
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
*/
|
||||
|
||||
// independent from idl_parser, since this code is not needed for most clients
|
||||
#include <unordered_set>
|
||||
#include <unordered_map>
|
||||
#include <cassert>
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/idl.h"
|
||||
@@ -23,9 +26,43 @@
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
const std::string kGeneratedFileNamePostfix = "_generated";
|
||||
|
||||
struct JsLanguageParameters {
|
||||
IDLOptions::Language language;
|
||||
std::string file_extension;
|
||||
};
|
||||
|
||||
struct ReexportDescription {
|
||||
std::string symbol;
|
||||
std::string source_namespace;
|
||||
std::string target_namespace;
|
||||
};
|
||||
|
||||
const JsLanguageParameters& GetJsLangParams(IDLOptions::Language lang) {
|
||||
static JsLanguageParameters js_language_parameters[] = {
|
||||
{
|
||||
IDLOptions::kJs,
|
||||
".js",
|
||||
},
|
||||
{
|
||||
IDLOptions::kTs,
|
||||
".ts",
|
||||
},
|
||||
};
|
||||
|
||||
if (lang == IDLOptions::kJs) {
|
||||
return js_language_parameters[0];
|
||||
} else {
|
||||
assert(lang == IDLOptions::kTs);
|
||||
return js_language_parameters[1];
|
||||
}
|
||||
}
|
||||
|
||||
static std::string GeneratedFileName(const std::string &path,
|
||||
const std::string &file_name) {
|
||||
return path + file_name + "_generated.js";
|
||||
const std::string &file_name,
|
||||
const JsLanguageParameters &lang) {
|
||||
return path + file_name + kGeneratedFileNamePostfix + lang.file_extension;
|
||||
}
|
||||
|
||||
namespace js {
|
||||
@@ -33,56 +70,127 @@ namespace js {
|
||||
// and tables) and output them to a single file.
|
||||
class JsGenerator : public BaseGenerator {
|
||||
public:
|
||||
typedef std::unordered_set<std::string> imported_fileset;
|
||||
typedef std::unordered_multimap<std::string, ReexportDescription>
|
||||
reexport_map;
|
||||
|
||||
JsGenerator(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name)
|
||||
: BaseGenerator(parser, path, file_name, "", "."){};
|
||||
: BaseGenerator(parser, path, file_name, "", "."),
|
||||
lang_(GetJsLangParams(parser_.opts.lang))
|
||||
{
|
||||
};
|
||||
// Iterate through all definitions we haven't generate code for (enums,
|
||||
// structs, and tables) and output them to a single file.
|
||||
bool generate() {
|
||||
if (IsEverythingGenerated()) return true;
|
||||
imported_fileset imported_files;
|
||||
reexport_map reexports;
|
||||
|
||||
std::string enum_code, struct_code, exports_code, code;
|
||||
generateEnums(&enum_code, &exports_code);
|
||||
generateStructs(&struct_code, &exports_code);
|
||||
std::string enum_code, struct_code, import_code, exports_code, code;
|
||||
generateEnums(&enum_code, &exports_code, reexports);
|
||||
generateStructs(&struct_code, &exports_code, imported_files);
|
||||
generateImportDependencies(&import_code, imported_files);
|
||||
generateReexports(&import_code, reexports, imported_files);
|
||||
|
||||
code = code + "// " + FlatBuffersGeneratedWarning();
|
||||
code = code + "// " + FlatBuffersGeneratedWarning() + "\n\n";
|
||||
|
||||
// Generate code for all the namespace declarations.
|
||||
GenNamespaces(&code, &exports_code);
|
||||
|
||||
// Output the main declaration code from above.
|
||||
code += import_code;
|
||||
|
||||
code += enum_code;
|
||||
code += struct_code;
|
||||
|
||||
if (!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_code;
|
||||
}
|
||||
|
||||
return SaveFile(GeneratedFileName(path_, file_name_).c_str(), code, false);
|
||||
return SaveFile(GeneratedFileName(path_, file_name_, lang_).c_str(), code,
|
||||
false);
|
||||
}
|
||||
|
||||
private:
|
||||
JsLanguageParameters lang_;
|
||||
|
||||
// Generate code for imports
|
||||
void generateImportDependencies(std::string *code_ptr,
|
||||
const imported_fileset &imported_files) {
|
||||
std::string &code = *code_ptr;
|
||||
for (auto it = imported_files.begin(); it != imported_files.end(); ++it) {
|
||||
const auto &file = *it;
|
||||
const auto basename =
|
||||
flatbuffers::StripPath(flatbuffers::StripExtension(file));
|
||||
if (basename != file_name_) {
|
||||
const auto file_name = basename + kGeneratedFileNamePostfix;
|
||||
code += GenPrefixedImport(file, file_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate reexports, which might not have been explicitly imported using the
|
||||
// "export import" trick
|
||||
void generateReexports(std::string *code_ptr,
|
||||
const reexport_map &reexports,
|
||||
imported_fileset imported_files) {
|
||||
if (!parser_.opts.reexport_ts_modules ||
|
||||
lang_.language != IDLOptions::kTs) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string &code = *code_ptr;
|
||||
for (auto it = reexports.begin(); it != reexports.end(); ++it) {
|
||||
const auto &file = *it;
|
||||
const auto basename =
|
||||
flatbuffers::StripPath(flatbuffers::StripExtension(file.first));
|
||||
if (basename != file_name_) {
|
||||
const auto file_name = basename + kGeneratedFileNamePostfix;
|
||||
|
||||
if (imported_files.find(file.first) == imported_files.end()) {
|
||||
code += GenPrefixedImport(file.first, file_name);
|
||||
imported_files.emplace(file.first);
|
||||
}
|
||||
|
||||
code += "export namespace " + file.second.target_namespace + " { \n";
|
||||
code += "export import " + file.second.symbol + " = ";
|
||||
code += GenFileNamespacePrefix(file.first) + "." +
|
||||
file.second.source_namespace + "." + file.second.symbol +
|
||||
"; }\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generate code for all enums.
|
||||
void generateEnums(std::string *enum_code_ptr,
|
||||
std::string *exports_code_ptr) {
|
||||
std::string *exports_code_ptr,
|
||||
reexport_map &reexports) {
|
||||
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
|
||||
++it) {
|
||||
auto &enum_def = **it;
|
||||
GenEnum(enum_def, enum_code_ptr, exports_code_ptr);
|
||||
GenEnum(enum_def, enum_code_ptr, exports_code_ptr, reexports);
|
||||
}
|
||||
}
|
||||
|
||||
// Generate code for all structs.
|
||||
void generateStructs(std::string *decl_code_ptr,
|
||||
std::string *exports_code_ptr) {
|
||||
std::string *exports_code_ptr,
|
||||
imported_fileset &imported_files) {
|
||||
for (auto it = parser_.structs_.vec.begin();
|
||||
it != parser_.structs_.vec.end(); ++it) {
|
||||
auto &struct_def = **it;
|
||||
GenStruct(parser_, struct_def, decl_code_ptr, exports_code_ptr);
|
||||
GenStruct(parser_, struct_def, decl_code_ptr, exports_code_ptr,
|
||||
imported_files);
|
||||
}
|
||||
}
|
||||
void GenNamespaces(std::string *code_ptr, std::string *exports_ptr) {
|
||||
if (lang_.language == IDLOptions::kTs &&
|
||||
parser_.opts.skip_flatbuffers_import) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::set<std::string> namespaces;
|
||||
|
||||
for (auto it = parser_.namespaces_.begin();
|
||||
@@ -110,16 +218,23 @@ class JsGenerator : public BaseGenerator {
|
||||
std::string &exports = *exports_ptr;
|
||||
for (auto it = sorted_namespaces.begin();
|
||||
it != sorted_namespaces.end(); it++) {
|
||||
code += "/**\n * @const\n * @namespace\n */\n";
|
||||
if (it->find('.') == std::string::npos) {
|
||||
code += "var ";
|
||||
if(parser_.opts.use_goog_js_export_format) {
|
||||
exports += "goog.exportSymbol('" + *it + "', " + *it + ");\n";
|
||||
} else {
|
||||
exports += "this." + *it + " = " + *it + ";\n";
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
if (it->find('.') == std::string::npos) {
|
||||
code += "import { flatbuffers } from \"./flatbuffers\"\n";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
code += "/**\n * @const\n * @namespace\n */\n";
|
||||
if (it->find('.') == std::string::npos) {
|
||||
code += "var ";
|
||||
if(parser_.opts.use_goog_js_export_format) {
|
||||
exports += "goog.exportSymbol('" + *it + "', " + *it + ");\n";
|
||||
} else {
|
||||
exports += "this." + *it + " = " + *it + ";\n";
|
||||
}
|
||||
}
|
||||
code += *it + " = " + *it + " || {};\n\n";
|
||||
}
|
||||
code += *it + " = " + *it + " || {};\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,21 +284,26 @@ static void GenDocComment(std::string *code_ptr,
|
||||
|
||||
// Generate an enum declaration and an enum string lookup table.
|
||||
void GenEnum(EnumDef &enum_def, std::string *code_ptr,
|
||||
std::string *exports_ptr) {
|
||||
std::string *exports_ptr, reexport_map &reexports) {
|
||||
if (enum_def.generated) return;
|
||||
std::string &code = *code_ptr;
|
||||
std::string &exports = *exports_ptr;
|
||||
GenDocComment(enum_def.doc_comment, code_ptr, "@enum");
|
||||
if (enum_def.defined_namespace->components.empty()) {
|
||||
code += "var ";
|
||||
if(parser_.opts.use_goog_js_export_format) {
|
||||
exports += "goog.exportSymbol('" + enum_def.name + "', " + enum_def.name +
|
||||
");\n";
|
||||
} else {
|
||||
exports += "this." + enum_def.name + " = " + enum_def.name + ";\n";
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "export namespace " + GetNameSpace(enum_def) + "{\n" +
|
||||
"export enum " + enum_def.name + "{\n";
|
||||
} else {
|
||||
if (enum_def.defined_namespace->components.empty()) {
|
||||
code += "var ";
|
||||
if(parser_.opts.use_goog_js_export_format) {
|
||||
exports += "goog.exportSymbol('" + enum_def.name + "', " +
|
||||
enum_def.name + ");\n";
|
||||
} else {
|
||||
exports += "this." + enum_def.name + " = " + enum_def.name + ";\n";
|
||||
}
|
||||
}
|
||||
code += WrapInNameSpace(enum_def) + " = {\n";
|
||||
}
|
||||
code += WrapInNameSpace(enum_def) + " = {\n";
|
||||
for (auto it = enum_def.vals.vec.begin();
|
||||
it != enum_def.vals.vec.end(); ++it) {
|
||||
auto &ev = **it;
|
||||
@@ -193,10 +313,27 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr,
|
||||
}
|
||||
GenDocComment(ev.doc_comment, code_ptr, "", " ");
|
||||
}
|
||||
code += " " + ev.name + ": " + 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";
|
||||
|
||||
if (ev.union_type.struct_def) {
|
||||
ReexportDescription 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)));
|
||||
}
|
||||
}
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "}};\n\n";
|
||||
} else {
|
||||
code += "};\n\n";
|
||||
}
|
||||
code += "};\n\n";
|
||||
}
|
||||
|
||||
static std::string GenType(const Type &type) {
|
||||
@@ -244,7 +381,12 @@ std::string GenDefaultValue(const Value &value, const std::string &context) {
|
||||
if (value.type.enum_def) {
|
||||
if (auto val = value.type.enum_def->ReverseLookup(
|
||||
atoi(value.constant.c_str()), false)) {
|
||||
return WrapInNameSpace(*value.type.enum_def) + "." + val->name;
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
return GenPrefixedTypeName(WrapInNameSpace(*value.type.enum_def),
|
||||
value.type.enum_def->file) + "." + val->name;
|
||||
} else {
|
||||
return WrapInNameSpace(*value.type.enum_def) + "." + val->name;
|
||||
}
|
||||
} else {
|
||||
return "/** @type {" + WrapInNameSpace(*value.type.enum_def) + "} */ ("
|
||||
+ value.constant + ")";
|
||||
@@ -270,13 +412,16 @@ std::string GenDefaultValue(const Value &value, const std::string &context) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string GenTypeName(const Type &type, bool input) {
|
||||
std::string GenTypeName(const Type &type, bool input, bool allowNull = false) {
|
||||
if (!input) {
|
||||
if (type.base_type == BASE_TYPE_STRING) {
|
||||
return "string|Uint8Array";
|
||||
}
|
||||
if (type.base_type == BASE_TYPE_STRUCT) {
|
||||
return WrapInNameSpace(*type.struct_def);
|
||||
if (type.base_type == BASE_TYPE_STRING || type.base_type == BASE_TYPE_STRUCT) {
|
||||
std::string name;
|
||||
if (type.base_type == BASE_TYPE_STRING) {
|
||||
name = "string|Uint8Array";
|
||||
} else {
|
||||
name = WrapInNameSpace(*type.struct_def);
|
||||
}
|
||||
return (allowNull) ? (name + "|null") : (name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,6 +467,28 @@ static std::string MaybeScale(T value) {
|
||||
return value != 1 ? " * " + NumToString(value) : "";
|
||||
}
|
||||
|
||||
static std::string GenFileNamespacePrefix(const 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,
|
||||
const std::string &base_file_name) {
|
||||
return "import * as "+ GenFileNamespacePrefix(full_file_name) +
|
||||
" from \"./" + base_file_name + "\";\n";
|
||||
}
|
||||
|
||||
// Adds a source-dependent prefix, for of import * statements.
|
||||
std::string GenPrefixedTypeName(const std::string &typeName,
|
||||
const std::string &file) {
|
||||
const auto basename =
|
||||
flatbuffers::StripPath(flatbuffers::StripExtension(file));
|
||||
if (basename == file_name_) {
|
||||
return typeName;
|
||||
}
|
||||
return GenFileNamespacePrefix(file) + "." + typeName;
|
||||
}
|
||||
|
||||
void GenStructArgs(const StructDef &struct_def,
|
||||
std::string *annotations,
|
||||
std::string *arguments,
|
||||
@@ -338,7 +505,13 @@ void GenStructArgs(const StructDef &struct_def,
|
||||
} else {
|
||||
*annotations += "@param {" + GenTypeName(field.value.type, true);
|
||||
*annotations += "} " + nameprefix + field.name + "\n";
|
||||
*arguments += ", " + nameprefix + field.name;
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
*arguments += ", " + nameprefix + field.name + ": " +
|
||||
GenTypeName(field.value.type, true);
|
||||
} else {
|
||||
*arguments += ", " + nameprefix + field.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -373,37 +546,59 @@ static void GenStructBody(const StructDef &struct_def,
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if (struct_def.generated) return;
|
||||
std::string &code = *code_ptr;
|
||||
std::string &exports = *exports_ptr;
|
||||
|
||||
std::string object_name;
|
||||
|
||||
// Emit constructor
|
||||
bool isStatement = struct_def.defined_namespace->components.empty();
|
||||
std::string object_name = WrapInNameSpace(struct_def);
|
||||
GenDocComment(struct_def.doc_comment, code_ptr, "@constructor");
|
||||
if (isStatement) {
|
||||
if(parser_.opts.use_goog_js_export_format) {
|
||||
exports += "goog.exportSymbol('" + struct_def.name + "', " +
|
||||
struct_def.name + ");\n";
|
||||
} else {
|
||||
exports += "this." + struct_def.name + " = " + struct_def.name + ";\n";
|
||||
}
|
||||
code += "function " + object_name;
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
object_name = struct_def.name;
|
||||
std::string object_namespace = GetNameSpace(struct_def);
|
||||
GenDocComment(struct_def.doc_comment, code_ptr, "@constructor");
|
||||
code += "export namespace " + object_namespace + "{\n";
|
||||
code += "export class " + struct_def.name;
|
||||
code += " {\n";
|
||||
code += " /**\n";
|
||||
code += " * @type {flatbuffers.ByteBuffer}\n";
|
||||
code += " */\n";
|
||||
code += " bb: flatbuffers.ByteBuffer;\n";
|
||||
code += "\n";
|
||||
code += " /**\n";
|
||||
code += " * @type {number}\n";
|
||||
code += " */\n";
|
||||
code += " bb_pos:number = 0;\n";
|
||||
} else {
|
||||
code += object_name + " = function";
|
||||
bool isStatement = struct_def.defined_namespace->components.empty();
|
||||
object_name = WrapInNameSpace(struct_def);
|
||||
GenDocComment(struct_def.doc_comment, code_ptr, "@constructor");
|
||||
if (isStatement) {
|
||||
if(parser_.opts.use_goog_js_export_format) {
|
||||
exports += "goog.exportSymbol('" + struct_def.name + "', " +
|
||||
struct_def.name + ");\n";
|
||||
} else {
|
||||
exports += "this." + struct_def.name + " = " + struct_def.name + ";\n";
|
||||
}
|
||||
code += "function " + object_name;
|
||||
} else {
|
||||
code += object_name + " = function";
|
||||
}
|
||||
code += "() {\n";
|
||||
code += " /**\n";
|
||||
code += " * @type {flatbuffers.ByteBuffer}\n";
|
||||
code += " */\n";
|
||||
code += " this.bb = null;\n";
|
||||
code += "\n";
|
||||
code += " /**\n";
|
||||
code += " * @type {number}\n";
|
||||
code += " */\n";
|
||||
code += " this.bb_pos = 0;\n";
|
||||
code += isStatement ? "}\n\n" : "};\n\n";
|
||||
}
|
||||
code += "() {\n";
|
||||
code += " /**\n";
|
||||
code += " * @type {flatbuffers.ByteBuffer}\n";
|
||||
code += " */\n";
|
||||
code += " this.bb = null;\n";
|
||||
code += "\n";
|
||||
code += " /**\n";
|
||||
code += " * @type {number}\n";
|
||||
code += " */\n";
|
||||
code += " this.bb_pos = 0;\n";
|
||||
code += isStatement ? "}\n\n" : "};\n\n";
|
||||
|
||||
// Generate the __init method that sets the field in a pre-existing
|
||||
// accessor object. This is to allow object reuse.
|
||||
@@ -412,7 +607,14 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
code += " * @param {flatbuffers.ByteBuffer} bb\n";
|
||||
code += " * @returns {" + object_name + "}\n";
|
||||
code += " */\n";
|
||||
code += object_name + ".prototype.__init = function(i, bb) {\n";
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "__init(i:number, bb:flatbuffers.ByteBuffer):" + object_name +
|
||||
" {\n";
|
||||
} else {
|
||||
code += object_name + ".prototype.__init = function(i, bb) {\n";
|
||||
}
|
||||
|
||||
code += " this.bb_pos = i;\n";
|
||||
code += " this.bb = bb;\n";
|
||||
code += " return this;\n";
|
||||
@@ -425,8 +627,14 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
"@param {flatbuffers.ByteBuffer} bb\n"
|
||||
"@param {" + object_name + "=} obj\n"
|
||||
"@returns {" + object_name + "}");
|
||||
code += object_name + ".getRootAs" + struct_def.name;
|
||||
code += " = function(bb, obj) {\n";
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "static getRootAs" + struct_def.name;
|
||||
code += "(bb:flatbuffers.ByteBuffer, obj?:" + object_name + "):" +
|
||||
object_name + " {\n";
|
||||
} else {
|
||||
code += object_name + ".getRootAs" + struct_def.name;
|
||||
code += " = function(bb, obj) {\n";
|
||||
}
|
||||
code += " return (obj || new " + object_name;
|
||||
code += ").__init(bb.readInt32(bb.position()) + bb.position(), bb);\n";
|
||||
code += "};\n\n";
|
||||
@@ -437,7 +645,13 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
GenDocComment(code_ptr,
|
||||
"@param {flatbuffers.ByteBuffer} bb\n"
|
||||
"@returns {boolean}");
|
||||
code += object_name + ".bufferHasIdentifier = function(bb) {\n";
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code +=
|
||||
"static bufferHasIdentifier(bb:flatbuffers.ByteBuffer):boolean {\n";
|
||||
} else {
|
||||
code += object_name + ".bufferHasIdentifier = function(bb) {\n";
|
||||
}
|
||||
|
||||
code += " return bb.__has_identifier('" + parser_.file_identifier_;
|
||||
code += "');\n};\n\n";
|
||||
}
|
||||
@@ -457,13 +671,33 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
GenDocComment(field.doc_comment, code_ptr,
|
||||
std::string(field.value.type.base_type == BASE_TYPE_STRING ?
|
||||
"@param {flatbuffers.Encoding=} optionalEncoding\n" : "") +
|
||||
"@returns {" + GenTypeName(field.value.type, false) + "}");
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += " = function(";
|
||||
if (field.value.type.base_type == BASE_TYPE_STRING) {
|
||||
code += "optionalEncoding";
|
||||
"@returns {" + GenTypeName(field.value.type, false, true) + "}");
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
std::string prefix = MakeCamel(field.name, false) + "(";
|
||||
if (field.value.type.base_type == BASE_TYPE_STRING) {
|
||||
code += prefix + "):string|null\n";
|
||||
code += prefix + "optionalEncoding:flatbuffers.Encoding"+"):" +
|
||||
GenTypeName(field.value.type, false, true)+"\n";
|
||||
code += prefix + "optionalEncoding?:any";
|
||||
} else {
|
||||
code += prefix;
|
||||
}
|
||||
if (field.value.type.enum_def) {
|
||||
code += "):" +
|
||||
GenPrefixedTypeName(GenTypeName(field.value.type, false, true),
|
||||
field.value.type.enum_def->file) + " {\n";
|
||||
} else {
|
||||
code += "):" + GenTypeName(field.value.type, false, true) + " {\n";
|
||||
}
|
||||
} else {
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += " = function(";
|
||||
if (field.value.type.base_type == BASE_TYPE_STRING) {
|
||||
code += "optionalEncoding";
|
||||
}
|
||||
code += ") {\n";
|
||||
}
|
||||
code += ") {\n";
|
||||
|
||||
if (struct_def.fixed) {
|
||||
code += " return " + GenGetter(field.value.type, "(this.bb_pos" +
|
||||
MaybeAdd(field.value.offset) + ")") + ";\n";
|
||||
@@ -484,9 +718,16 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
case BASE_TYPE_STRUCT: {
|
||||
auto type = WrapInNameSpace(*field.value.type.struct_def);
|
||||
GenDocComment(field.doc_comment, code_ptr,
|
||||
"@param {" + type + "=} obj\n@returns {" + type + "}");
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += " = function(obj) {\n";
|
||||
"@param {" + type + "=} obj\n@returns {" + type + "|null}");
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
type = GenPrefixedTypeName(type, field.value.type.struct_def->file);
|
||||
code += MakeCamel(field.name, false);
|
||||
code += "(obj?:" + type + "):" + type + "|null {\n";
|
||||
} else {
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += " = function(obj) {\n";
|
||||
}
|
||||
|
||||
if (struct_def.fixed) {
|
||||
code += " return (obj || new " + type;
|
||||
code += ").__init(this.bb_pos";
|
||||
@@ -498,6 +739,11 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
: "this.bb.__indirect(this.bb_pos + offset)";
|
||||
code += ", this.bb) : null;\n";
|
||||
}
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
imported_files.insert(field.value.type.struct_def->file);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -515,14 +761,34 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
}
|
||||
GenDocComment(field.doc_comment, code_ptr, args +
|
||||
"@returns {" + vectortypename + "}");
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += " = function(index";
|
||||
if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
||||
code += ", obj";
|
||||
} else if (vectortype.base_type == BASE_TYPE_STRING) {
|
||||
code += ", optionalEncoding";
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
std::string prefix = MakeCamel(field.name, false);
|
||||
prefix += "(index: number";
|
||||
if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
||||
vectortypename = GenPrefixedTypeName(vectortypename,
|
||||
vectortype.struct_def->file);
|
||||
code += prefix + ", obj?:" + vectortypename;
|
||||
imported_files.insert(vectortype.struct_def->file);
|
||||
} else if (vectortype.base_type == BASE_TYPE_STRING) {
|
||||
code += prefix + "):string\n";
|
||||
code += prefix + ",optionalEncoding:flatbuffers.Encoding" + "):" +
|
||||
vectortypename + "\n";
|
||||
code += prefix + ",optionalEncoding?:any";
|
||||
} else {
|
||||
code += prefix;
|
||||
}
|
||||
code += "):" + vectortypename + "|null {\n";
|
||||
} else {
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += " = function(index";
|
||||
if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
||||
code += ", obj";
|
||||
} else if (vectortype.base_type == BASE_TYPE_STRING) {
|
||||
code += ", optionalEncoding";
|
||||
}
|
||||
code += ") {\n";
|
||||
}
|
||||
code += ") {\n";
|
||||
|
||||
if (vectortype.base_type == BASE_TYPE_STRUCT) {
|
||||
code += offset_prefix + "(obj || new " + vectortypename;
|
||||
code += ").__init(";
|
||||
@@ -561,8 +827,14 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
GenDocComment(field.doc_comment, code_ptr,
|
||||
"@param {flatbuffers.Table} obj\n"
|
||||
"@returns {?flatbuffers.Table}");
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += " = function(obj) {\n";
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += MakeCamel(field.name, false);
|
||||
code += "<T extends flatbuffers.Table>(obj:T):T|null {\n";
|
||||
} else {
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += " = function(obj) {\n";
|
||||
}
|
||||
|
||||
code += offset_prefix + GenGetter(field.value.type,
|
||||
"(obj, this.bb_pos + offset)") + " : null;\n";
|
||||
break;
|
||||
@@ -581,16 +853,41 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
|
||||
// Adds the mutable scalar value to the output
|
||||
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 +
|
||||
"@returns {boolean}");
|
||||
|
||||
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";
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
std::string type;
|
||||
if (field.value.type.enum_def) {
|
||||
type = GenPrefixedTypeName(GenTypeName(field.value.type, true),
|
||||
field.value.type.enum_def->file);
|
||||
} else {
|
||||
type = GenTypeName(field.value.type, true);
|
||||
}
|
||||
|
||||
code += "mutate_" + field.name + "(value:" + type + "):boolean {\n";
|
||||
} else {
|
||||
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 += " if (offset === 0) {\n";
|
||||
code += " return false;\n";
|
||||
code += " }\n\n";
|
||||
code += " this.bb.write" + MakeCamel(GenType(field.value.type)) + "(this.bb_pos + offset, value);\n";
|
||||
|
||||
// special case for bools, which are treated as uint8
|
||||
code += " this.bb.write" + MakeCamel(GenType(field.value.type)) +
|
||||
"(this.bb_pos + offset, ";
|
||||
if (field.value.type.base_type == BASE_TYPE_BOOL &&
|
||||
lang_.language == IDLOptions::kTs) {
|
||||
code += "+";
|
||||
}
|
||||
|
||||
code += "value);\n";
|
||||
code += " return true;\n";
|
||||
code += "};\n\n";
|
||||
|
||||
@@ -605,8 +902,14 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
if (field.value.type.base_type == BASE_TYPE_VECTOR) {
|
||||
// Emit a length helper
|
||||
GenDocComment(code_ptr, "@returns {number}");
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += "Length = function() {\n" + offset_prefix;
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += MakeCamel(field.name, false);
|
||||
code += "Length():number {\n" + offset_prefix;
|
||||
} else {
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += "Length = function() {\n" + offset_prefix;
|
||||
}
|
||||
|
||||
code += "this.bb.__vector_len(this.bb_pos + offset) : 0;\n};\n\n";
|
||||
|
||||
if(parser_.opts.use_goog_js_export_format) {
|
||||
@@ -619,8 +922,16 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
auto vectorType = field.value.type.VectorType();
|
||||
if (IsScalar(vectorType.base_type) && !IsLong(vectorType.base_type)) {
|
||||
GenDocComment(code_ptr, "@returns {" + GenType(vectorType) + "Array}");
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += "Array = function() {\n" + offset_prefix;
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += MakeCamel(field.name, false);
|
||||
code += "Array():" + GenType(vectorType) + "Array|null {\n" +
|
||||
offset_prefix;
|
||||
} else {
|
||||
code += object_name + ".prototype." + MakeCamel(field.name, false);
|
||||
code += "Array = function() {\n" + offset_prefix;
|
||||
}
|
||||
|
||||
code += "new " + GenType(vectorType) + "Array(this.bb.bytes().buffer, "
|
||||
"this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), "
|
||||
"this.bb.__vector_len(this.bb_pos + offset)) : null;\n};\n\n";
|
||||
@@ -641,16 +952,30 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
GenStructArgs(struct_def, &annotations, &arguments, "");
|
||||
GenDocComment(code_ptr, annotations +
|
||||
"@returns {flatbuffers.Offset}");
|
||||
code += object_name + ".create" + struct_def.name + " = function(builder";
|
||||
code += arguments + ") {\n";
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "static create" + struct_def.name + "(builder:flatbuffers.Builder";
|
||||
code += arguments + "):flatbuffers.Offset {\n";
|
||||
} else {
|
||||
code += object_name + ".create" + struct_def.name + " = function(builder";
|
||||
code += arguments + ") {\n";
|
||||
}
|
||||
|
||||
GenStructBody(struct_def, &code, "");
|
||||
code += " return builder.offset();\n};\n\n";
|
||||
} else {
|
||||
// Generate a method to start building a new object
|
||||
GenDocComment(code_ptr,
|
||||
"@param {flatbuffers.Builder} builder");
|
||||
code += object_name + ".start" + struct_def.name;
|
||||
code += " = function(builder) {\n";
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "static start" + struct_def.name;
|
||||
code += "(builder:flatbuffers.Builder) {\n";
|
||||
} else {
|
||||
code += object_name + ".start" + struct_def.name;
|
||||
code += " = function(builder) {\n";
|
||||
}
|
||||
|
||||
code += " builder.startObject(" + NumToString(
|
||||
struct_def.fields.vec.size()) + ");\n";
|
||||
code += "};\n\n";
|
||||
@@ -670,8 +995,24 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
"@param {flatbuffers.Builder} builder\n"
|
||||
"@param {" + GenTypeName(field.value.type, true) + "} " +
|
||||
argname);
|
||||
code += object_name + ".add" + MakeCamel(field.name);
|
||||
code += " = function(builder, " + argname + ") {\n";
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
std::string argType;
|
||||
if (field.value.type.enum_def) {
|
||||
argType = GenPrefixedTypeName(GenTypeName(field.value.type, true),
|
||||
field.value.type.enum_def->file);
|
||||
} else {
|
||||
argType = GenTypeName(field.value.type, true);
|
||||
}
|
||||
|
||||
code += "static add" + MakeCamel(field.name);
|
||||
code += "(builder:flatbuffers.Builder, " + argname + ":" + argType +
|
||||
") {\n";
|
||||
} else {
|
||||
code += object_name + ".add" + MakeCamel(field.name);
|
||||
code += " = function(builder, " + argname + ") {\n";
|
||||
}
|
||||
|
||||
code += " builder.addField" + GenWriteMethod(field.value.type) + "(";
|
||||
code += NumToString(it - struct_def.fields.vec.begin()) + ", ";
|
||||
if (field.value.type.base_type == BASE_TYPE_BOOL) {
|
||||
@@ -700,8 +1041,20 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
"@param {Array.<" + GenTypeName(vector_type, true) +
|
||||
">} data\n"
|
||||
"@returns {flatbuffers.Offset}");
|
||||
code += object_name + ".create" + MakeCamel(field.name);
|
||||
code += "Vector = function(builder, data) {\n";
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "static create" + MakeCamel(field.name);
|
||||
std::string type = GenTypeName(vector_type, true) + "[]";
|
||||
if (type == "number[]") {
|
||||
type += " | Uint8Array";
|
||||
}
|
||||
code += "Vector(builder:flatbuffers.Builder, data:" + type +
|
||||
"):flatbuffers.Offset {\n";
|
||||
} else {
|
||||
code += object_name + ".create" + MakeCamel(field.name);
|
||||
code += "Vector = function(builder, data) {\n";
|
||||
}
|
||||
|
||||
code += " builder.startVector(" + NumToString(elem_size);
|
||||
code += ", data.length, " + NumToString(alignment) + ");\n";
|
||||
code += " for (var i = data.length - 1; i >= 0; i--) {\n";
|
||||
@@ -719,8 +1072,15 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
GenDocComment(code_ptr,
|
||||
"@param {flatbuffers.Builder} builder\n"
|
||||
"@param {number} numElems");
|
||||
code += object_name + ".start" + MakeCamel(field.name);
|
||||
code += "Vector = function(builder, numElems) {\n";
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "static start" + MakeCamel(field.name);
|
||||
code += "Vector(builder:flatbuffers.Builder, numElems:number) {\n";
|
||||
} else {
|
||||
code += object_name + ".start" + MakeCamel(field.name);
|
||||
code += "Vector = function(builder, numElems) {\n";
|
||||
}
|
||||
|
||||
code += " builder.startVector(" + NumToString(elem_size);
|
||||
code += ", numElems, " + NumToString(alignment) + ");\n";
|
||||
code += "};\n\n";
|
||||
@@ -731,8 +1091,15 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
GenDocComment(code_ptr,
|
||||
"@param {flatbuffers.Builder} builder\n"
|
||||
"@returns {flatbuffers.Offset}");
|
||||
code += object_name + ".end" + struct_def.name;
|
||||
code += " = function(builder) {\n";
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "static end" + struct_def.name;
|
||||
code += "(builder:flatbuffers.Builder):flatbuffers.Offset {\n";
|
||||
} else {
|
||||
code += object_name + ".end" + struct_def.name;
|
||||
code += " = function(builder) {\n";
|
||||
}
|
||||
|
||||
code += " var offset = builder.endObject();\n";
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end(); ++it) {
|
||||
@@ -751,8 +1118,15 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
GenDocComment(code_ptr,
|
||||
"@param {flatbuffers.Builder} builder\n"
|
||||
"@param {flatbuffers.Offset} offset");
|
||||
code += object_name + ".finish" + struct_def.name + "Buffer";
|
||||
code += " = function(builder, offset) {\n";
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "static finish" + struct_def.name + "Buffer";
|
||||
code += "(builder:flatbuffers.Builder, offset:flatbuffers.Offset) {\n";
|
||||
} else {
|
||||
code += object_name + ".finish" + struct_def.name + "Buffer";
|
||||
code += " = function(builder, offset) {\n";
|
||||
}
|
||||
|
||||
code += " builder.finish(offset";
|
||||
if (!parser_.file_identifier_.empty()) {
|
||||
code += ", '" + parser_.file_identifier_ + "'";
|
||||
@@ -761,6 +1135,10 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
|
||||
code += "};\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (lang_.language == IDLOptions::kTs) {
|
||||
code += "}\n}\n";
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace js
|
||||
@@ -774,15 +1152,19 @@ bool GenerateJS(const Parser &parser, const std::string &path,
|
||||
std::string JSMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name) {
|
||||
assert(parser.opts.lang <= IDLOptions::kMAX);
|
||||
const auto &lang = GetJsLangParams(parser.opts.lang);
|
||||
|
||||
std::string filebase = flatbuffers::StripPath(
|
||||
flatbuffers::StripExtension(file_name));
|
||||
std::string make_rule = GeneratedFileName(path, filebase) + ": ";
|
||||
std::string make_rule = GeneratedFileName(path, filebase, lang) + ": ";
|
||||
|
||||
auto included_files = parser.GetIncludedFilesRecursive(file_name);
|
||||
for (auto it = included_files.begin();
|
||||
it != included_files.end(); ++it) {
|
||||
make_rule += " " + *it;
|
||||
}
|
||||
return make_rule;
|
||||
return make_rule;
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace php {
|
||||
const bool needs_imports, std::string *code_ptr) {
|
||||
std::string &code = *code_ptr;
|
||||
code += "<?php\n";
|
||||
code = code + "// " + FlatBuffersGeneratedWarning();
|
||||
code = code + "// " + FlatBuffersGeneratedWarning() + "\n\n";
|
||||
code += "namespace " + name_space_name + ";\n\n";
|
||||
|
||||
if (needs_imports) {
|
||||
|
||||
@@ -630,7 +630,7 @@ class PythonGenerator : public BaseGenerator {
|
||||
void BeginFile(const std::string name_space_name, const bool needs_imports,
|
||||
std::string *code_ptr) {
|
||||
std::string &code = *code_ptr;
|
||||
code = code + "# " + FlatBuffersGeneratedWarning();
|
||||
code = code + "# " + FlatBuffersGeneratedWarning() + "\n\n";
|
||||
code += "# namespace: " + name_space_name + "\n\n";
|
||||
if (needs_imports) {
|
||||
code += "import flatbuffers\n\n";
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/idl.h"
|
||||
#include "flatbuffers/util.h"
|
||||
#include "flatbuffers/flexbuffers.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
@@ -49,7 +50,7 @@ void OutputIdentifier(const std::string &name, const IDLOptions &opts,
|
||||
// for a single FlatBuffer value into JSON format.
|
||||
// The general case for scalars:
|
||||
template<typename T> bool Print(T val, Type type, int /*indent*/,
|
||||
StructDef * /*union_sd*/,
|
||||
Type * /*union_type*/,
|
||||
const IDLOptions &opts,
|
||||
std::string *_text) {
|
||||
std::string &text = *_text;
|
||||
@@ -79,7 +80,7 @@ template<typename T> bool PrintVector(const Vector<T> &v, Type type,
|
||||
text += NewLine(opts);
|
||||
for (uoffset_t i = 0; i < v.size(); i++) {
|
||||
if (i) {
|
||||
text += ",";
|
||||
if (!opts.protobuf_ascii_alike) text += ",";
|
||||
text += NewLine(opts);
|
||||
}
|
||||
text.append(indent + Indent(opts), ' ');
|
||||
@@ -101,90 +102,19 @@ template<typename T> bool PrintVector(const Vector<T> &v, Type type,
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool EscapeString(const String &s, std::string *_text, const IDLOptions& opts) {
|
||||
std::string &text = *_text;
|
||||
text += "\"";
|
||||
for (uoffset_t i = 0; i < s.size(); i++) {
|
||||
char c = s[i];
|
||||
switch (c) {
|
||||
case '\n': text += "\\n"; break;
|
||||
case '\t': text += "\\t"; break;
|
||||
case '\r': text += "\\r"; break;
|
||||
case '\b': text += "\\b"; break;
|
||||
case '\f': text += "\\f"; break;
|
||||
case '\"': text += "\\\""; break;
|
||||
case '\\': text += "\\\\"; break;
|
||||
default:
|
||||
if (c >= ' ' && c <= '~') {
|
||||
text += c;
|
||||
} else {
|
||||
// Not printable ASCII data. Let's see if it's valid UTF-8 first:
|
||||
const char *utf8 = s.c_str() + i;
|
||||
int ucc = FromUTF8(&utf8);
|
||||
if (ucc < 0) {
|
||||
if (opts.allow_non_utf8) {
|
||||
text += "\\x";
|
||||
text += IntToStringHex(static_cast<uint8_t>(c), 2);
|
||||
} else {
|
||||
// There are two cases here:
|
||||
//
|
||||
// 1) We reached here by parsing an IDL file. In that case,
|
||||
// we previously checked for non-UTF-8, so we shouldn't reach
|
||||
// here.
|
||||
//
|
||||
// 2) We reached here by someone calling GenerateText()
|
||||
// on a previously-serialized flatbuffer. The data might have
|
||||
// non-UTF-8 Strings, or might be corrupt.
|
||||
//
|
||||
// In both cases, we have to give up and inform the caller
|
||||
// they have no JSON.
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (ucc <= 0xFFFF) {
|
||||
// Parses as Unicode within JSON's \uXXXX range, so use that.
|
||||
text += "\\u";
|
||||
text += IntToStringHex(ucc, 4);
|
||||
} else if (ucc <= 0x10FFFF) {
|
||||
// Encode Unicode SMP values to a surrogate pair using two \u escapes.
|
||||
uint32_t base = ucc - 0x10000;
|
||||
auto high_surrogate = (base >> 10) + 0xD800;
|
||||
auto low_surrogate = (base & 0x03FF) + 0xDC00;
|
||||
text += "\\u";
|
||||
text += IntToStringHex(high_surrogate, 4);
|
||||
text += "\\u";
|
||||
text += IntToStringHex(low_surrogate, 4);
|
||||
}
|
||||
// Skip past characters recognized.
|
||||
i = static_cast<uoffset_t>(utf8 - s.c_str() - 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
text += "\"";
|
||||
return true;
|
||||
}
|
||||
|
||||
// Specialization of Print above for pointer types.
|
||||
template<> bool Print<const void *>(const void *val,
|
||||
Type type, int indent,
|
||||
StructDef *union_sd,
|
||||
Type *union_type,
|
||||
const IDLOptions &opts,
|
||||
std::string *_text) {
|
||||
switch (type.base_type) {
|
||||
case BASE_TYPE_UNION:
|
||||
// If this assert hits, you have an corrupt buffer, a union type field
|
||||
// was not present or was out of range.
|
||||
assert(union_sd);
|
||||
if (!GenStruct(*union_sd,
|
||||
reinterpret_cast<const Table *>(val),
|
||||
indent,
|
||||
opts,
|
||||
_text)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
assert(union_type);
|
||||
return Print<const void *>(val, *union_type, indent, nullptr, opts,
|
||||
_text);
|
||||
case BASE_TYPE_STRUCT:
|
||||
if (!GenStruct(*type.struct_def,
|
||||
reinterpret_cast<const Table *>(val),
|
||||
@@ -195,7 +125,8 @@ template<> bool Print<const void *>(const void *val,
|
||||
}
|
||||
break;
|
||||
case BASE_TYPE_STRING: {
|
||||
if (!EscapeString(*reinterpret_cast<const String *>(val), _text, opts)) {
|
||||
auto s = reinterpret_cast<const String *>(val);
|
||||
if (!EscapeString(s->c_str(), s->Length(), _text, opts.allow_non_utf8)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -236,7 +167,7 @@ template<typename T> static bool GenField(const FieldDef &fd,
|
||||
|
||||
// Generate text for non-scalar field.
|
||||
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 void *val = nullptr;
|
||||
if (fixed) {
|
||||
@@ -244,12 +175,17 @@ static bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
|
||||
assert(IsStruct(fd.value.type));
|
||||
val = reinterpret_cast<const Struct *>(table)->
|
||||
GetStruct<const void *>(fd.value.offset);
|
||||
} else if (fd.flexbuffer) {
|
||||
auto vec = table->GetPointer<const Vector<uint8_t> *>(fd.value.offset);
|
||||
auto root = flexbuffers::GetRoot(vec->data(), vec->size());
|
||||
root.ToString(true, false, *_text);
|
||||
return true;
|
||||
} else {
|
||||
val = IsStruct(fd.value.type)
|
||||
? table->GetStruct<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,
|
||||
@@ -260,7 +196,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
|
||||
std::string &text = *_text;
|
||||
text += "{";
|
||||
int fieldout = 0;
|
||||
StructDef *union_sd = nullptr;
|
||||
Type *union_type = nullptr;
|
||||
for (auto it = struct_def.fields.vec.begin();
|
||||
it != struct_def.fields.vec.end();
|
||||
++it) {
|
||||
@@ -271,12 +207,15 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
|
||||
!fd.deprecated;
|
||||
if (is_present || output_anyway) {
|
||||
if (fieldout++) {
|
||||
text += ",";
|
||||
if (!opts.protobuf_ascii_alike) text += ",";
|
||||
}
|
||||
text += NewLine(opts);
|
||||
text.append(indent + Indent(opts), ' ');
|
||||
OutputIdentifier(fd.name, opts, _text);
|
||||
text += ": ";
|
||||
if (!opts.protobuf_ascii_alike ||
|
||||
(fd.value.type.base_type != BASE_TYPE_STRUCT &&
|
||||
fd.value.type.base_type != BASE_TYPE_VECTOR)) text += ":";
|
||||
text += " ";
|
||||
if (is_present) {
|
||||
switch (fd.value.type.base_type) {
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \
|
||||
@@ -296,7 +235,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
|
||||
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
if (!GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts),
|
||||
union_sd, opts, _text)) {
|
||||
union_type, opts, _text)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -305,7 +244,7 @@ static bool GenStruct(const StructDef &struct_def, const Table *table,
|
||||
auto enum_val = fd.value.type.enum_def->ReverseLookup(
|
||||
table->GetField<uint8_t>(fd.value.offset, 0));
|
||||
assert(enum_val);
|
||||
union_sd = enum_val->struct_def;
|
||||
union_type = &enum_val->union_type;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -86,26 +86,29 @@ CheckedError Parser::Error(const std::string &msg) {
|
||||
|
||||
inline CheckedError NoError() { return CheckedError(false); }
|
||||
|
||||
inline std::string OutOfRangeErrorMsg(int64_t val, const std::string &op,
|
||||
int64_t limit) {
|
||||
const std::string cause = NumToString(val) + op + NumToString(limit);
|
||||
return "constant does not fit (" + cause + ")";
|
||||
}
|
||||
|
||||
// Ensure that integer values we parse fit inside the declared integer type.
|
||||
CheckedError Parser::CheckBitsFit(int64_t val, size_t bits) {
|
||||
// Left-shifting a 64-bit value by 64 bits or more is undefined
|
||||
// behavior (C99 6.5.7), so check *before* we shift.
|
||||
if (bits < 64) {
|
||||
// Bits we allow to be used.
|
||||
auto mask = static_cast<int64_t>((1ull << bits) - 1);
|
||||
if ((val & ~mask) != 0 && // Positive or unsigned.
|
||||
(val | mask) != -1) // Negative.
|
||||
return Error("constant does not fit in a " + NumToString(bits) +
|
||||
"-bit field");
|
||||
}
|
||||
return NoError();
|
||||
CheckedError Parser::CheckInRange(int64_t val, int64_t min, int64_t max) {
|
||||
if (val < min)
|
||||
return Error(OutOfRangeErrorMsg(val, " < ", min));
|
||||
else if (val > max)
|
||||
return Error(OutOfRangeErrorMsg(val, " > ", max));
|
||||
else
|
||||
return NoError();
|
||||
}
|
||||
|
||||
// atot: templated version of atoi/atof: convert a string to an instance of T.
|
||||
template<typename T> inline CheckedError atot(const char *s, Parser &parser,
|
||||
T *val) {
|
||||
int64_t i = StringToInt(s);
|
||||
ECHECK(parser.CheckBitsFit(i, sizeof(T) * 8));
|
||||
const int64_t min = std::numeric_limits<T>::min();
|
||||
const int64_t max = std::numeric_limits<T>::max();
|
||||
ECHECK(parser.CheckInRange(i, min, max));
|
||||
*val = (T)i;
|
||||
return NoError();
|
||||
}
|
||||
@@ -598,6 +601,10 @@ CheckedError Parser::AddField(StructDef &struct_def, const std::string &name,
|
||||
|
||||
CheckedError Parser::ParseField(StructDef &struct_def) {
|
||||
std::string name = attribute_;
|
||||
|
||||
if (name == struct_def.name)
|
||||
return Error("field name can not be the same as table/struct name");
|
||||
|
||||
std::vector<std::string> dc = doc_comment_;
|
||||
EXPECT(kTokenIdentifier);
|
||||
EXPECT(':');
|
||||
@@ -718,6 +725,15 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
|
||||
LookupCreateStruct(nested->constant);
|
||||
}
|
||||
|
||||
if (field->attributes.Lookup("flexbuffer")) {
|
||||
field->flexbuffer = true;
|
||||
uses_flexbuffers_ = true;
|
||||
if (field->value.type.base_type != BASE_TYPE_VECTOR ||
|
||||
field->value.type.element != BASE_TYPE_UCHAR)
|
||||
return Error(
|
||||
"flexbuffer attribute may only apply to a vector of ubyte");
|
||||
}
|
||||
|
||||
if (typefield) {
|
||||
// If this field is a union, and it has a manually assigned id,
|
||||
// the automatically added type field should have an id as well (of N - 1).
|
||||
@@ -735,6 +751,18 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::ParseString(Value &val) {
|
||||
auto s = attribute_;
|
||||
EXPECT(kTokenStringConstant);
|
||||
val.constant = NumToString(builder_.CreateString(s).o);
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::ParseComma() {
|
||||
if (!opts.protobuf_ascii_alike) EXPECT(',');
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
|
||||
size_t parent_fieldn,
|
||||
const StructDef *parent_struct_def) {
|
||||
@@ -763,7 +791,7 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
|
||||
// Remember where we are in the source file, so we can come back here.
|
||||
auto backup = *static_cast<ParserState *>(this);
|
||||
ECHECK(SkipAnyJsonValue()); // The table.
|
||||
EXPECT(',');
|
||||
ECHECK(ParseComma());
|
||||
auto next_name = attribute_;
|
||||
if (Is(kTokenStringConstant)) {
|
||||
NEXT();
|
||||
@@ -784,20 +812,30 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
|
||||
ECHECK(atot(constant.c_str(), *this, &enum_idx));
|
||||
auto enum_val = val.type.enum_def->ReverseLookup(enum_idx);
|
||||
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;
|
||||
}
|
||||
case BASE_TYPE_STRUCT:
|
||||
ECHECK(ParseTable(*val.type.struct_def, &val.constant, nullptr));
|
||||
break;
|
||||
case BASE_TYPE_STRING: {
|
||||
auto s = attribute_;
|
||||
EXPECT(kTokenStringConstant);
|
||||
val.constant = NumToString(builder_.CreateString(s).o);
|
||||
ECHECK(ParseString(val));
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_VECTOR: {
|
||||
EXPECT('[');
|
||||
uoffset_t off;
|
||||
ECHECK(ParseVector(val.type.VectorType(), &off));
|
||||
val.constant = NumToString(off);
|
||||
@@ -830,33 +868,74 @@ void Parser::SerializeStruct(const StructDef &struct_def, const Value &val) {
|
||||
builder_.AddStructOffset(val.offset, builder_.GetSize());
|
||||
}
|
||||
|
||||
CheckedError Parser::ParseTableDelimiters(size_t &fieldn,
|
||||
const StructDef *struct_def,
|
||||
const std::function<CheckedError(const std::string &name)> &body) {
|
||||
// We allow tables both as JSON object{ .. } with field names
|
||||
// or vector[..] with all fields in order
|
||||
char terminator = '}';
|
||||
bool is_nested_vector = struct_def && Is('[');
|
||||
if (is_nested_vector) {
|
||||
NEXT();
|
||||
terminator = ']';
|
||||
} else {
|
||||
EXPECT('{');
|
||||
}
|
||||
for (;;) {
|
||||
if ((!opts.strict_json || !fieldn) && Is(terminator)) break;
|
||||
std::string name;
|
||||
if (is_nested_vector) {
|
||||
if (fieldn > struct_def->fields.vec.size()) {
|
||||
return Error("too many unnamed fields in nested array");
|
||||
}
|
||||
name = struct_def->fields.vec[fieldn]->name;
|
||||
} else {
|
||||
name = attribute_;
|
||||
if (Is(kTokenStringConstant)) {
|
||||
NEXT();
|
||||
} else {
|
||||
EXPECT(opts.strict_json ? kTokenStringConstant : kTokenIdentifier);
|
||||
}
|
||||
if (!opts.protobuf_ascii_alike || !(Is('{') || Is('['))) EXPECT(':');
|
||||
}
|
||||
ECHECK(body(name));
|
||||
if (Is(terminator)) break;
|
||||
ECHECK(ParseComma());
|
||||
}
|
||||
NEXT();
|
||||
if (is_nested_vector && fieldn != struct_def->fields.vec.size()) {
|
||||
return Error("wrong number of unnamed fields in table vector");
|
||||
}
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
|
||||
uoffset_t *ovalue) {
|
||||
EXPECT('{');
|
||||
size_t fieldn = 0;
|
||||
for (;;) {
|
||||
if ((!opts.strict_json || !fieldn) && Is('}')) { NEXT(); break; }
|
||||
std::string name = attribute_;
|
||||
if (Is(kTokenStringConstant)) {
|
||||
NEXT();
|
||||
} else {
|
||||
EXPECT(opts.strict_json ? kTokenStringConstant : kTokenIdentifier);
|
||||
}
|
||||
auto err = ParseTableDelimiters(fieldn, &struct_def,
|
||||
[&](const std::string &name) -> CheckedError {
|
||||
auto field = struct_def.fields.Lookup(name);
|
||||
if (!field) {
|
||||
if (!opts.skip_unexpected_fields_in_json) {
|
||||
return Error("unknown field: " + name);
|
||||
} else {
|
||||
EXPECT(':');
|
||||
ECHECK(SkipAnyJsonValue());
|
||||
}
|
||||
} else {
|
||||
EXPECT(':');
|
||||
if (Is(kTokenNull)) {
|
||||
NEXT(); // Ignore this field.
|
||||
} else {
|
||||
Value val = field->value;
|
||||
ECHECK(ParseAnyValue(val, field, fieldn, &struct_def));
|
||||
if (field->flexbuffer) {
|
||||
flexbuffers::Builder builder(1024,
|
||||
flexbuffers::BUILDER_FLAG_SHARE_ALL);
|
||||
ECHECK(ParseFlexBufferValue(&builder));
|
||||
builder.Finish();
|
||||
auto off = builder_.CreateVector(builder.GetBuffer());
|
||||
val.constant = NumToString(off.o);
|
||||
} else {
|
||||
ECHECK(ParseAnyValue(val, field, fieldn, &struct_def));
|
||||
}
|
||||
// Hardcoded insertion-sort with error-check.
|
||||
// If fields are specified in order, then this loop exits immediately.
|
||||
auto elem = field_stack_.rbegin();
|
||||
@@ -872,8 +951,31 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
|
||||
fieldn++;
|
||||
}
|
||||
}
|
||||
if (Is('}')) { NEXT(); break; }
|
||||
EXPECT(',');
|
||||
return NoError();
|
||||
});
|
||||
ECHECK(err);
|
||||
|
||||
// Check if all required fields are parsed.
|
||||
for (auto field_it = struct_def.fields.vec.begin();
|
||||
field_it != struct_def.fields.vec.end();
|
||||
++field_it) {
|
||||
auto required_field = *field_it;
|
||||
if (!required_field->required) {
|
||||
continue;
|
||||
}
|
||||
bool found = false;
|
||||
for (auto pf_it = field_stack_.end() - fieldn;
|
||||
pf_it != field_stack_.end();
|
||||
++pf_it) {
|
||||
auto parsed_field = pf_it->second;
|
||||
if (parsed_field == required_field) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return Error("required field is missing: " + required_field->name + " in " + struct_def.name);
|
||||
}
|
||||
}
|
||||
|
||||
if (struct_def.fixed && fieldn != struct_def.fields.vec.size())
|
||||
@@ -951,22 +1053,34 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue) {
|
||||
int count = 0;
|
||||
CheckedError Parser::ParseVectorDelimiters(size_t &count,
|
||||
const std::function<CheckedError()> &body) {
|
||||
EXPECT('[');
|
||||
for (;;) {
|
||||
if ((!opts.strict_json || !count) && Is(']')) { NEXT(); break; }
|
||||
if ((!opts.strict_json || !count) && Is(']')) break;
|
||||
ECHECK(body());
|
||||
count++;
|
||||
if (Is(']')) break;
|
||||
ECHECK(ParseComma());
|
||||
}
|
||||
NEXT();
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue) {
|
||||
size_t count = 0;
|
||||
auto err = ParseVectorDelimiters(count, [&]() -> CheckedError {
|
||||
Value val;
|
||||
val.type = type;
|
||||
ECHECK(ParseAnyValue(val, nullptr, 0, nullptr));
|
||||
field_stack_.push_back(std::make_pair(val, nullptr));
|
||||
count++;
|
||||
if (Is(']')) { NEXT(); break; }
|
||||
EXPECT(',');
|
||||
}
|
||||
return NoError();
|
||||
});
|
||||
ECHECK(err);
|
||||
|
||||
builder_.StartVector(count * InlineSize(type) / InlineAlignment(type),
|
||||
InlineAlignment(type));
|
||||
for (int i = 0; i < count; i++) {
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
// start at the back, since we're building the data backwards.
|
||||
auto &val = field_stack_.back().first;
|
||||
switch (val.type.base_type) {
|
||||
@@ -1077,14 +1191,24 @@ CheckedError Parser::ParseHash(Value &e, FieldDef* field) {
|
||||
assert(field);
|
||||
Value *hash_name = field->attributes.Lookup("hash");
|
||||
switch (e.type.base_type) {
|
||||
case BASE_TYPE_INT:
|
||||
case BASE_TYPE_INT: {
|
||||
auto hash = FindHashFunction32(hash_name->constant.c_str());
|
||||
int32_t hashed_value = static_cast<int32_t>(hash(attribute_.c_str()));
|
||||
e.constant = NumToString(hashed_value);
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_UINT: {
|
||||
auto hash = FindHashFunction32(hash_name->constant.c_str());
|
||||
uint32_t hashed_value = hash(attribute_.c_str());
|
||||
e.constant = NumToString(hashed_value);
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_LONG:
|
||||
case BASE_TYPE_LONG: {
|
||||
auto hash = FindHashFunction64(hash_name->constant.c_str());
|
||||
int64_t hashed_value = static_cast<int64_t>(hash(attribute_.c_str()));
|
||||
e.constant = NumToString(hashed_value);
|
||||
break;
|
||||
}
|
||||
case BASE_TYPE_ULONG: {
|
||||
auto hash = FindHashFunction64(hash_name->constant.c_str());
|
||||
uint64_t hashed_value = hash(attribute_.c_str());
|
||||
@@ -1098,6 +1222,11 @@ CheckedError Parser::ParseHash(Value &e, FieldDef* field) {
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::TokenError() {
|
||||
return Error("cannot parse value starting with: " +
|
||||
TokenToStringId(token_));
|
||||
}
|
||||
|
||||
CheckedError Parser::ParseSingleValue(Value &e) {
|
||||
// First see if this could be a conversion function:
|
||||
if (token_ == kTokenIdentifier && *cursor_ == '(') {
|
||||
@@ -1164,9 +1293,7 @@ CheckedError Parser::ParseSingleValue(Value &e) {
|
||||
e,
|
||||
BASE_TYPE_STRING,
|
||||
&match));
|
||||
if (!match)
|
||||
return Error("cannot parse value starting with: " +
|
||||
TokenToStringId(token_));
|
||||
if (!match) return TokenError();
|
||||
}
|
||||
return NoError();
|
||||
}
|
||||
@@ -1290,7 +1417,16 @@ CheckedError Parser::ParseEnum(bool is_union, EnumDef **dest) {
|
||||
return Error("enum value already exists: " + value_name);
|
||||
ev.doc_comment = value_comment;
|
||||
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('=')) {
|
||||
NEXT();
|
||||
@@ -1300,6 +1436,10 @@ CheckedError Parser::ParseEnum(bool is_union, EnumDef **dest) {
|
||||
enum_def.vals.vec[prevsize - 1]->value >= ev.value)
|
||||
return Error("enum values must be specified in ascending order");
|
||||
}
|
||||
if (is_union) {
|
||||
if (ev.value < 0 || ev.value >= 256)
|
||||
return Error("union enum value must fit in a ubyte");
|
||||
}
|
||||
if (opts.proto_mode && Is('[')) {
|
||||
NEXT();
|
||||
// ignore attributes on enums.
|
||||
@@ -1335,7 +1475,7 @@ CheckedError Parser::StartStruct(const std::string &name, StructDef **dest) {
|
||||
struct_def.file = file_being_parsed_;
|
||||
// Move this struct to the back of the vector just in case it was predeclared,
|
||||
// to preserve declaration order.
|
||||
*remove(structs_.vec.begin(), structs_.vec.end(), &struct_def) = &struct_def;
|
||||
*std::remove(structs_.vec.begin(), structs_.vec.end(), &struct_def) = &struct_def;
|
||||
*dest = &struct_def;
|
||||
return NoError();
|
||||
}
|
||||
@@ -1780,14 +1920,21 @@ CheckedError Parser::ParseTypeFromProtoType(Type *type) {
|
||||
|
||||
CheckedError Parser::SkipAnyJsonValue() {
|
||||
switch (token_) {
|
||||
case '{':
|
||||
ECHECK(SkipJsonObject());
|
||||
break;
|
||||
case '{': {
|
||||
size_t fieldn = 0;
|
||||
return ParseTableDelimiters(fieldn, nullptr,
|
||||
[&](const std::string &) -> CheckedError {
|
||||
ECHECK(SkipAnyJsonValue());
|
||||
fieldn++;
|
||||
return NoError();
|
||||
});
|
||||
}
|
||||
case '[': {
|
||||
size_t count = 0;
|
||||
return ParseVectorDelimiters(count, [&]() { return SkipAnyJsonValue(); });
|
||||
}
|
||||
case kTokenStringConstant:
|
||||
ECHECK(SkipJsonString());
|
||||
break;
|
||||
case '[':
|
||||
ECHECK(SkipJsonArray());
|
||||
EXPECT(kTokenStringConstant);
|
||||
break;
|
||||
case kTokenIntegerConstant:
|
||||
EXPECT(kTokenIntegerConstant);
|
||||
@@ -1796,84 +1943,98 @@ CheckedError Parser::SkipAnyJsonValue() {
|
||||
EXPECT(kTokenFloatConstant);
|
||||
break;
|
||||
default:
|
||||
return Error(std::string("Unexpected token:") + std::string(1, static_cast<char>(token_)));
|
||||
return TokenError();
|
||||
}
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::SkipJsonObject() {
|
||||
EXPECT('{');
|
||||
size_t fieldn = 0;
|
||||
|
||||
for (;;) {
|
||||
if ((!opts.strict_json || !fieldn) && Is('}')) break;
|
||||
|
||||
if (!Is(kTokenStringConstant)) {
|
||||
EXPECT(opts.strict_json ? kTokenStringConstant : kTokenIdentifier);
|
||||
CheckedError Parser::ParseFlexBufferValue(flexbuffers::Builder *builder) {
|
||||
switch (token_) {
|
||||
case '{': {
|
||||
auto start = builder->StartMap();
|
||||
size_t fieldn = 0;
|
||||
auto err = ParseTableDelimiters(fieldn, nullptr,
|
||||
[&](const std::string &name) -> CheckedError {
|
||||
builder->Key(name);
|
||||
ECHECK(ParseFlexBufferValue(builder));
|
||||
fieldn++;
|
||||
return NoError();
|
||||
});
|
||||
ECHECK(err);
|
||||
builder->EndMap(start);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
NEXT();
|
||||
case '[':{
|
||||
auto start = builder->StartVector();
|
||||
size_t count = 0;
|
||||
ECHECK(ParseVectorDelimiters(count, [&]() {
|
||||
return ParseFlexBufferValue(builder);
|
||||
}));
|
||||
builder->EndVector(start, false, false);
|
||||
break;
|
||||
}
|
||||
|
||||
EXPECT(':');
|
||||
ECHECK(SkipAnyJsonValue());
|
||||
fieldn++;
|
||||
|
||||
if (Is('}')) break;
|
||||
EXPECT(',');
|
||||
case kTokenStringConstant:
|
||||
builder->String(attribute_);
|
||||
EXPECT(kTokenStringConstant);
|
||||
break;
|
||||
case kTokenIntegerConstant:
|
||||
builder->Int(StringToInt(attribute_.c_str()));
|
||||
EXPECT(kTokenIntegerConstant);
|
||||
break;
|
||||
case kTokenFloatConstant:
|
||||
builder->Double(strtod(attribute_.c_str(), nullptr));
|
||||
EXPECT(kTokenFloatConstant);
|
||||
break;
|
||||
default:
|
||||
return TokenError();
|
||||
}
|
||||
|
||||
NEXT();
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::SkipJsonArray() {
|
||||
EXPECT('[');
|
||||
|
||||
for (;;) {
|
||||
if (Is(']')) break;
|
||||
|
||||
ECHECK(SkipAnyJsonValue());
|
||||
|
||||
if (Is(']')) break;
|
||||
EXPECT(',');
|
||||
}
|
||||
|
||||
NEXT();
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::SkipJsonString() {
|
||||
EXPECT(kTokenStringConstant);
|
||||
return NoError();
|
||||
bool Parser::ParseFlexBuffer(const char *source, const char *source_filename,
|
||||
flexbuffers::Builder *builder) {
|
||||
auto ok = !StartParseFile(source, source_filename).Check() &&
|
||||
!ParseFlexBufferValue(builder).Check();
|
||||
if (ok) builder->Finish();
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool Parser::Parse(const char *source, const char **include_paths,
|
||||
const char *source_filename) {
|
||||
return !DoParse(source, include_paths, source_filename).Check();
|
||||
return !DoParse(source, include_paths, source_filename, nullptr).Check();
|
||||
}
|
||||
|
||||
CheckedError Parser::StartParseFile(const char *source, const char *source_filename) {
|
||||
file_being_parsed_ = source_filename ? source_filename : "";
|
||||
source_ = cursor_ = source;
|
||||
line_ = 1;
|
||||
error_.clear();
|
||||
ECHECK(SkipByteOrderMark());
|
||||
NEXT();
|
||||
if (Is(kTokenEof))
|
||||
return Error("input file is empty");
|
||||
return NoError();
|
||||
}
|
||||
|
||||
CheckedError Parser::DoParse(const char *source, const char **include_paths,
|
||||
const char *source_filename) {
|
||||
file_being_parsed_ = source_filename ? source_filename : "";
|
||||
const char *source_filename,
|
||||
const char *include_filename) {
|
||||
if (source_filename &&
|
||||
included_files_.find(source_filename) == included_files_.end()) {
|
||||
included_files_[source_filename] = true;
|
||||
included_files_[source_filename] = include_filename ? include_filename : "";
|
||||
files_included_per_file_[source_filename] = std::set<std::string>();
|
||||
}
|
||||
if (!include_paths) {
|
||||
static const char *current_directory[] = { "", nullptr };
|
||||
include_paths = current_directory;
|
||||
}
|
||||
source_ = cursor_ = source;
|
||||
line_ = 1;
|
||||
error_.clear();
|
||||
field_stack_.clear();
|
||||
builder_.Clear();
|
||||
// Start with a blank namespace just in case this file doesn't have one.
|
||||
namespaces_.push_back(new Namespace());
|
||||
ECHECK(SkipByteOrderMark());
|
||||
NEXT();
|
||||
|
||||
ECHECK(StartParseFile(source, source_filename));
|
||||
|
||||
// Includes must come before type declarations:
|
||||
for (;;) {
|
||||
// Parse pre-include proto statements if any:
|
||||
@@ -1891,7 +2052,7 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
|
||||
Is(kTokenIdentifier))) {
|
||||
NEXT();
|
||||
if (opts.proto_mode && attribute_ == "public") NEXT();
|
||||
auto name = attribute_;
|
||||
auto name = flatbuffers::PosixPath(attribute_.c_str());
|
||||
EXPECT(kTokenStringConstant);
|
||||
// Look for the file in include_paths.
|
||||
std::string filepath;
|
||||
@@ -1909,7 +2070,8 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
|
||||
std::string contents;
|
||||
if (!LoadFile(filepath.c_str(), true, &contents))
|
||||
return Error("unable to load include file: " + name);
|
||||
ECHECK(DoParse(contents.c_str(), include_paths, filepath.c_str()));
|
||||
ECHECK(DoParse(contents.c_str(), include_paths, filepath.c_str(),
|
||||
name.c_str()));
|
||||
// We generally do not want to output code for any included files:
|
||||
if (!opts.generate_all) MarkGenerated();
|
||||
// This is the easiest way to continue this file after an include:
|
||||
@@ -1919,7 +2081,7 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
|
||||
// entered into included_files_.
|
||||
// This is recursive, but only go as deep as the number of include
|
||||
// statements.
|
||||
return DoParse(source, include_paths, source_filename);
|
||||
return DoParse(source, include_paths, source_filename, include_filename);
|
||||
}
|
||||
EXPECT(';');
|
||||
} else {
|
||||
@@ -1990,6 +2152,8 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
|
||||
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) {
|
||||
auto &enum_def = **it;
|
||||
if (enum_def.is_union) {
|
||||
@@ -1997,8 +2161,11 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
|
||||
val_it != enum_def.vals.vec.end();
|
||||
++val_it) {
|
||||
auto &val = **val_it;
|
||||
if (val.struct_def && val.struct_def->fixed)
|
||||
return Error("only tables can be union elements: " + val.name);
|
||||
if (opts.lang_to_generate != IDLOptions::kCpp &&
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2141,9 +2308,11 @@ Offset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder) const
|
||||
return reflection::CreateEnumVal(*builder,
|
||||
builder->CreateString(name),
|
||||
value,
|
||||
struct_def
|
||||
? struct_def->serialized_location
|
||||
: 0);
|
||||
union_type.struct_def
|
||||
? union_type.struct_def->
|
||||
serialized_location
|
||||
: 0,
|
||||
union_type.Serialize(builder));
|
||||
}
|
||||
|
||||
Offset<reflection::Type> Type::Serialize(FlatBufferBuilder *builder) const {
|
||||
|
||||
@@ -87,8 +87,11 @@ std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data,
|
||||
auto &fielddef = **it;
|
||||
if (!table_field->CheckField(fielddef.offset())) continue;
|
||||
auto val = GetAnyFieldS(*table_field, fielddef, schema);
|
||||
if (fielddef.type()->base_type() == reflection::String)
|
||||
val = "\"" + val + "\""; // Doesn't deal with escape codes etc.
|
||||
if (fielddef.type()->base_type() == reflection::String) {
|
||||
std::string esc;
|
||||
flatbuffers::EscapeString(val.c_str(), val.length(), &esc, true);
|
||||
val = esc;
|
||||
}
|
||||
s += fielddef.name()->str();
|
||||
s += ": ";
|
||||
s += val;
|
||||
@@ -420,8 +423,8 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
|
||||
offset = fbb.CreateVector(elements).o;
|
||||
break;
|
||||
}
|
||||
// FALL-THRU:
|
||||
}
|
||||
// FALL-THRU
|
||||
default: { // Scalars and structs.
|
||||
auto element_size = GetTypeSize(element_base_type);
|
||||
if (elemobjectdef && elemobjectdef->is_struct())
|
||||
@@ -458,8 +461,8 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
|
||||
subobjectdef.bytesize());
|
||||
break;
|
||||
}
|
||||
// else: FALL-THRU:
|
||||
}
|
||||
// ELSE FALL-THRU
|
||||
case reflection::Union:
|
||||
case reflection::String:
|
||||
case reflection::Vector:
|
||||
|
||||
@@ -80,6 +80,9 @@
|
||||
<Compile Include="..\MyGame\Example\Vec3.cs">
|
||||
<Link>MyGame\Example\Vec3.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\MyGame\Example\Ability.cs">
|
||||
<Link>MyGame\Example\Ability.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="..\namespace_test\NamespaceA\NamespaceB\EnumInNestedNS.cs">
|
||||
<Link>NamespaceA\NamespaceB\EnumInNestedNS.cs</Link>
|
||||
</Compile>
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace FlatBuffers.Test
|
||||
Monster.StartMonster(fbb);
|
||||
Monster.AddName(fbb, names[2]);
|
||||
off[2] = Monster.EndMonster(fbb);
|
||||
var sortMons = Monster.CreateMySortedVectorOfTables(fbb, off);
|
||||
var sortMons = Monster.CreateSortedVectorOfMonster(fbb, off);
|
||||
|
||||
// We set up the same values as monsterdata.json:
|
||||
|
||||
@@ -123,9 +123,9 @@ namespace FlatBuffers.Test
|
||||
Assert.AreEqual(monster.Testarrayoftables(2).Value.Name, "Wilma");
|
||||
|
||||
// Example of searching for a table by the key
|
||||
Assert.IsTrue(Monster.LookupByKey(sortMons, "Frodo", fbb.DataBuffer) != null);
|
||||
Assert.IsTrue(Monster.LookupByKey(sortMons, "Barney", fbb.DataBuffer) != null);
|
||||
Assert.IsTrue(Monster.LookupByKey(sortMons, "Wilma", fbb.DataBuffer)!= null);
|
||||
Assert.IsTrue(monster.TestarrayoftablesByKey("Frodo") != null);
|
||||
Assert.IsTrue(monster.TestarrayoftablesByKey("Barney") != null);
|
||||
Assert.IsTrue(monster.TestarrayoftablesByKey("Wilma") != null);
|
||||
|
||||
// testType is an existing field and mutating it should succeed
|
||||
Assert.AreEqual(monster.TestType, Any.Monster);
|
||||
|
||||
9
tests/FlatBuffers.Test/NetTest.sh
Normal file
9
tests/FlatBuffers.Test/NetTest.sh
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Testing C# on Linux using Mono.
|
||||
|
||||
mcs -out:fbnettest.exe ../../net/FlatBuffers/*.cs ../MyGame/Example/*.cs FlatBuffersTestClassAttribute.cs FlatBuffersTestMethodAttribute.cs Assert.cs FlatBuffersExampleTests.cs Program.cs ByteBufferTests.cs FlatBufferBuilderTests.cs FlatBuffersFuzzTests.cs FuzzTestData.cs Lcg.cs TestTable.cs
|
||||
./fbnettest.exe
|
||||
rm fbnettest.exe
|
||||
rm Resources/monsterdata_cstest.mon
|
||||
|
||||
@@ -20,7 +20,7 @@ go_path=${test_dir}/go_gen
|
||||
go_src=${go_path}/src
|
||||
|
||||
# Emit Go code for the example schema in the test dir:
|
||||
../flatc -g monster_test.fbs
|
||||
../flatc -g -I include_test monster_test.fbs
|
||||
|
||||
# Go requires a particular layout of files in order to link multiple packages.
|
||||
# Copy flatbuffer Go files to their own package directories to compile the
|
||||
|
||||
@@ -3,7 +3,7 @@ var assert = require('assert');
|
||||
var fs = require('fs');
|
||||
|
||||
var flatbuffers = require('../js/flatbuffers').flatbuffers;
|
||||
var MyGame = require('./monster_test_generated').MyGame;
|
||||
var MyGame = require(process.argv[2]).MyGame;
|
||||
|
||||
function main() {
|
||||
|
||||
@@ -67,7 +67,7 @@ function main() {
|
||||
// Tests mutation first. This will verify that we did not trample any other
|
||||
// part of the byte buffer.
|
||||
testMutation(fbb.dataBuffer());
|
||||
|
||||
|
||||
testBuffer(fbb.dataBuffer());
|
||||
|
||||
test64bit();
|
||||
@@ -156,7 +156,8 @@ function test64bit() {
|
||||
var mon2 = MyGame.Example.Monster.endMonster(fbb);
|
||||
|
||||
MyGame.Example.Stat.startStat(fbb);
|
||||
MyGame.Example.Stat.addVal(fbb, new flatbuffers.Long(0x12345678, 0x23456789));
|
||||
// 2541551405100253985 = 0x87654321(low part) + 0x23456789 * 0x100000000(high part);
|
||||
MyGame.Example.Stat.addVal(fbb, new flatbuffers.Long(0x87654321, 0x23456789)); // the low part is Uint32
|
||||
var stat = MyGame.Example.Stat.endStat(fbb);
|
||||
|
||||
MyGame.Example.Monster.startMonster(fbb);
|
||||
@@ -177,8 +178,7 @@ function test64bit() {
|
||||
var stat = mon.testempty();
|
||||
assert.strictEqual(stat != null, true);
|
||||
assert.strictEqual(stat.val() != null, true);
|
||||
assert.strictEqual(stat.val().low, 0x12345678);
|
||||
assert.strictEqual(stat.val().high, 0x23456789);
|
||||
assert.strictEqual(stat.val().toFloat64(), 2541551405100253985);
|
||||
|
||||
var mon2 = mon.enemy();
|
||||
assert.strictEqual(mon2 != null, true);
|
||||
|
||||
@@ -15,5 +15,5 @@
|
||||
# limitations under the License.
|
||||
|
||||
pushd "$(dirname $0)" >/dev/null
|
||||
../flatc -b monster_test.fbs unicode_test.json
|
||||
node JavaScriptTest
|
||||
../flatc -b -I include_test monster_test.fbs unicode_test.json
|
||||
node JavaScriptTest ./monster_test_generated
|
||||
|
||||
@@ -63,7 +63,7 @@ class JavaTest {
|
||||
Monster.addName(fbb, names[2]);
|
||||
off[2] = Monster.endMonster(fbb);
|
||||
int sortMons = fbb.createSortedVectorOfTables(new Monster(), off);
|
||||
|
||||
|
||||
// We set up the same values as monsterdata.json:
|
||||
|
||||
int str = fbb.createString("MyMonster");
|
||||
@@ -135,16 +135,16 @@ class JavaTest {
|
||||
// the mana field should retain its default value
|
||||
TestEq(monster.mutateMana((short)10), false);
|
||||
TestEq(monster.mana(), (short)150);
|
||||
|
||||
|
||||
// Accessing a vector of sorted by the key tables
|
||||
TestEq(monster.testarrayoftables(0).name(), "Barney");
|
||||
TestEq(monster.testarrayoftables(1).name(), "Frodo");
|
||||
TestEq(monster.testarrayoftables(2).name(), "Wilma");
|
||||
|
||||
|
||||
// Example of searching for a table by the key
|
||||
TestEq(Monster.lookupByKey(sortMons, "Frodo", fbb.dataBuffer()).name(), "Frodo");
|
||||
TestEq(Monster.lookupByKey(sortMons, "Barney", fbb.dataBuffer()).name(), "Barney");
|
||||
TestEq(Monster.lookupByKey(sortMons, "Wilma", fbb.dataBuffer()).name(), "Wilma");
|
||||
TestEq(monster.testarrayoftablesByKey("Frodo").name(), "Frodo");
|
||||
TestEq(monster.testarrayoftablesByKey("Barney").name(), "Barney");
|
||||
TestEq(monster.testarrayoftablesByKey("Wilma").name(), "Wilma");
|
||||
|
||||
// testType is an existing field and mutating it should succeed
|
||||
TestEq(monster.testType(), (byte)Any.Monster);
|
||||
@@ -201,7 +201,7 @@ class JavaTest {
|
||||
|
||||
static void TestBuffer(ByteBuffer bb) {
|
||||
TestEq(Monster.MonsterBufferHasIdentifier(bb), true);
|
||||
|
||||
|
||||
Monster monster = Monster.getRootAsMonster(bb);
|
||||
|
||||
TestEq(monster.hp(), (short)80);
|
||||
@@ -259,25 +259,25 @@ class JavaTest {
|
||||
|
||||
TestEq(monster.testhashu32Fnv1(), Integer.MAX_VALUE + 1L);
|
||||
}
|
||||
|
||||
|
||||
static void TestNamespaceNesting() {
|
||||
// reference / manipulate these to verify compilation
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(1);
|
||||
|
||||
|
||||
TableInNestedNS.startTableInNestedNS(fbb);
|
||||
TableInNestedNS.addFoo(fbb, 1234);
|
||||
int nestedTableOff = TableInNestedNS.endTableInNestedNS(fbb);
|
||||
|
||||
TableInFirstNS.startTableInFirstNS(fbb);
|
||||
|
||||
TableInFirstNS.startTableInFirstNS(fbb);
|
||||
TableInFirstNS.addFooTable(fbb, nestedTableOff);
|
||||
int off = TableInFirstNS.endTableInFirstNS(fbb);
|
||||
}
|
||||
|
||||
|
||||
static void TestNestedFlatBuffer() {
|
||||
final String nestedMonsterName = "NestedMonsterName";
|
||||
final short nestedMonsterHp = 600;
|
||||
final short nestedMonsterMana = 1024;
|
||||
|
||||
|
||||
FlatBufferBuilder fbb1 = new FlatBufferBuilder(16);
|
||||
int str1 = fbb1.createString(nestedMonsterName);
|
||||
Monster.startMonster(fbb1);
|
||||
@@ -288,8 +288,8 @@ class JavaTest {
|
||||
Monster.finishMonsterBuffer(fbb1, monster1);
|
||||
byte[] fbb1Bytes = fbb1.sizedByteArray();
|
||||
fbb1 = null;
|
||||
|
||||
FlatBufferBuilder fbb2 = new FlatBufferBuilder(16);
|
||||
|
||||
FlatBufferBuilder fbb2 = new FlatBufferBuilder(16);
|
||||
int str2 = fbb2.createString("My Monster");
|
||||
int nestedBuffer = Monster.createTestnestedflatbufferVector(fbb2, fbb1Bytes);
|
||||
Monster.startMonster(fbb2);
|
||||
@@ -299,7 +299,7 @@ class JavaTest {
|
||||
Monster.addTestnestedflatbuffer(fbb2, nestedBuffer);
|
||||
int monster = Monster.endMonster(fbb2);
|
||||
Monster.finishMonsterBuffer(fbb2, monster);
|
||||
|
||||
|
||||
// Now test the data extracted from the nested buffer
|
||||
Monster mons = Monster.getRootAsMonster(fbb2.dataBuffer());
|
||||
Monster nestedMonster = mons.testnestedflatbufferAsMonster();
|
||||
|
||||
@@ -14,31 +14,30 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
set -o errexit
|
||||
|
||||
echo Compile then run the Java test.
|
||||
|
||||
java -version
|
||||
|
||||
testdir=$(readlink -fn `dirname $0`)
|
||||
thisdir=$(readlink -fn `pwd`)
|
||||
testdir="$(readlink -fn "$(dirname "$0")")"
|
||||
|
||||
targetdir=${testdir}/target
|
||||
|
||||
if [[ "$testdir" != "$thisdir" ]]; then
|
||||
echo error: must be run from inside the ${testdir} directory
|
||||
echo you ran it from ${thisdir}
|
||||
exit 1
|
||||
fi
|
||||
|
||||
find .. -type f -name "*.class" -exec rm {} \;
|
||||
targetdir="${testdir}/target"
|
||||
|
||||
if [[ -e "${targetdir}" ]]; then
|
||||
echo "clean target"
|
||||
rm -rf ${targetdir}
|
||||
echo "cleaning target"
|
||||
rm -rf "${targetdir}"
|
||||
fi
|
||||
|
||||
mkdir ${targetdir}
|
||||
mkdir -v "${targetdir}"
|
||||
|
||||
javac -d ${targetdir} -classpath ${testdir}/../java:${testdir}:${testdir}/namespace_test JavaTest.java
|
||||
java -classpath ${targetdir} JavaTest
|
||||
if ! find "${testdir}/../java" -type f -name "*.class" -delete; then
|
||||
echo "failed to clean .class files from java directory" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -rf ${targetdir}
|
||||
javac -d "${targetdir}" -classpath "${testdir}/../java:${testdir}:${testdir}/namespace_test" "${testdir}/JavaTest.java"
|
||||
|
||||
(cd "${testdir}" && java -classpath "${targetdir}" JavaTest )
|
||||
|
||||
rm -rf "${targetdir}"
|
||||
|
||||
32
tests/MyGame/Example/Ability.cs
Normal file
32
tests/MyGame/Example/Ability.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
// <auto-generated>
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// </auto-generated>
|
||||
|
||||
namespace MyGame.Example
|
||||
{
|
||||
|
||||
using global::System;
|
||||
using global::FlatBuffers;
|
||||
|
||||
public struct Ability : IFlatbufferObject
|
||||
{
|
||||
private Struct __p;
|
||||
public ByteBuffer ByteBuffer { get { return __p.bb; } }
|
||||
public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
|
||||
public Ability __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
|
||||
|
||||
public uint Id { get { return __p.bb.GetUint(__p.bb_pos + 0); } }
|
||||
public void MutateId(uint id) { __p.bb.PutUint(__p.bb_pos + 0, id); }
|
||||
public uint Distance { get { return __p.bb.GetUint(__p.bb_pos + 4); } }
|
||||
public void MutateDistance(uint distance) { __p.bb.PutUint(__p.bb_pos + 4, distance); }
|
||||
|
||||
public static Offset<Ability> CreateAbility(FlatBufferBuilder builder, uint Id, uint Distance) {
|
||||
builder.Prep(4, 8);
|
||||
builder.PutUint(Distance);
|
||||
builder.PutUint(Id);
|
||||
return new Offset<Ability>(builder.Offset);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
41
tests/MyGame/Example/Ability.go
Normal file
41
tests/MyGame/Example/Ability.go
Normal file
@@ -0,0 +1,41 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
package Example
|
||||
|
||||
import (
|
||||
flatbuffers "github.com/google/flatbuffers/go"
|
||||
)
|
||||
|
||||
type Ability struct {
|
||||
_tab flatbuffers.Struct
|
||||
}
|
||||
|
||||
func (rcv *Ability) Init(buf []byte, i flatbuffers.UOffsetT) {
|
||||
rcv._tab.Bytes = buf
|
||||
rcv._tab.Pos = i
|
||||
}
|
||||
|
||||
func (rcv *Ability) Table() flatbuffers.Table {
|
||||
return rcv._tab.Table
|
||||
}
|
||||
|
||||
func (rcv *Ability) Id() uint32 {
|
||||
return rcv._tab.GetUint32(rcv._tab.Pos + flatbuffers.UOffsetT(0))
|
||||
}
|
||||
func (rcv *Ability) MutateId(n uint32) bool {
|
||||
return rcv._tab.MutateUint32(rcv._tab.Pos+flatbuffers.UOffsetT(0), n)
|
||||
}
|
||||
|
||||
func (rcv *Ability) Distance() uint32 {
|
||||
return rcv._tab.GetUint32(rcv._tab.Pos + flatbuffers.UOffsetT(4))
|
||||
}
|
||||
func (rcv *Ability) MutateDistance(n uint32) bool {
|
||||
return rcv._tab.MutateUint32(rcv._tab.Pos+flatbuffers.UOffsetT(4), n)
|
||||
}
|
||||
|
||||
func CreateAbility(builder *flatbuffers.Builder, id uint32, distance uint32) flatbuffers.UOffsetT {
|
||||
builder.Prep(4, 8)
|
||||
builder.PrependUint32(distance)
|
||||
builder.PrependUint32(id)
|
||||
return builder.Offset()
|
||||
}
|
||||
27
tests/MyGame/Example/Ability.java
Normal file
27
tests/MyGame/Example/Ability.java
Normal file
@@ -0,0 +1,27 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
package MyGame.Example;
|
||||
|
||||
import java.nio.*;
|
||||
import java.lang.*;
|
||||
import java.util.*;
|
||||
import com.google.flatbuffers.*;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public final class Ability extends Struct {
|
||||
public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
|
||||
public Ability __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
|
||||
|
||||
public long id() { return (long)bb.getInt(bb_pos + 0) & 0xFFFFFFFFL; }
|
||||
public void mutateId(long id) { bb.putInt(bb_pos + 0, (int)id); }
|
||||
public long distance() { return (long)bb.getInt(bb_pos + 4) & 0xFFFFFFFFL; }
|
||||
public void mutateDistance(long distance) { bb.putInt(bb_pos + 4, (int)distance); }
|
||||
|
||||
public static int createAbility(FlatBufferBuilder builder, long id, long distance) {
|
||||
builder.prep(4, 8);
|
||||
builder.putInt((int)distance);
|
||||
builder.putInt((int)id);
|
||||
return builder.offset();
|
||||
}
|
||||
}
|
||||
|
||||
52
tests/MyGame/Example/Ability.php
Normal file
52
tests/MyGame/Example/Ability.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
namespace MyGame\Example;
|
||||
|
||||
use \Google\FlatBuffers\Struct;
|
||||
use \Google\FlatBuffers\Table;
|
||||
use \Google\FlatBuffers\ByteBuffer;
|
||||
use \Google\FlatBuffers\FlatBufferBuilder;
|
||||
|
||||
class Ability extends Struct
|
||||
{
|
||||
/**
|
||||
* @param int $_i offset
|
||||
* @param ByteBuffer $_bb
|
||||
* @return Ability
|
||||
**/
|
||||
public function init($_i, ByteBuffer $_bb)
|
||||
{
|
||||
$this->bb_pos = $_i;
|
||||
$this->bb = $_bb;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return uint
|
||||
*/
|
||||
public function GetId()
|
||||
{
|
||||
return $this->bb->getUint($this->bb_pos + 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return uint
|
||||
*/
|
||||
public function GetDistance()
|
||||
{
|
||||
return $this->bb->getUint($this->bb_pos + 4);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int offset
|
||||
*/
|
||||
public static function createAbility(FlatBufferBuilder $builder, $id, $distance)
|
||||
{
|
||||
$builder->prep(4, 8);
|
||||
$builder->putUint($distance);
|
||||
$builder->putUint($id);
|
||||
return $builder->offset();
|
||||
}
|
||||
}
|
||||
23
tests/MyGame/Example/Ability.py
Normal file
23
tests/MyGame/Example/Ability.py
Normal file
@@ -0,0 +1,23 @@
|
||||
# automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
# namespace: Example
|
||||
|
||||
import flatbuffers
|
||||
|
||||
class Ability(object):
|
||||
__slots__ = ['_tab']
|
||||
|
||||
# Ability
|
||||
def Init(self, buf, pos):
|
||||
self._tab = flatbuffers.table.Table(buf, pos)
|
||||
|
||||
# Ability
|
||||
def Id(self): return self._tab.Get(flatbuffers.number_types.Uint32Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(0))
|
||||
# Ability
|
||||
def Distance(self): return self._tab.Get(flatbuffers.number_types.Uint32Flags, self._tab.Pos + flatbuffers.number_types.UOffsetTFlags.py_type(4))
|
||||
|
||||
def CreateAbility(builder, id, distance):
|
||||
builder.Prep(4, 8)
|
||||
builder.PrependUint32(distance)
|
||||
builder.PrependUint32(id)
|
||||
return builder.Offset()
|
||||
@@ -1,4 +1,6 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// <auto-generated>
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// </auto-generated>
|
||||
|
||||
namespace MyGame.Example
|
||||
{
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// <auto-generated>
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// </auto-generated>
|
||||
|
||||
namespace MyGame.Example
|
||||
{
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// <auto-generated>
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// </auto-generated>
|
||||
|
||||
namespace MyGame.Example
|
||||
{
|
||||
|
||||
using System;
|
||||
using FlatBuffers;
|
||||
using global::System;
|
||||
using global::FlatBuffers;
|
||||
|
||||
/// an example documentation comment: monster object
|
||||
public struct Monster : IFlatbufferObject
|
||||
@@ -41,6 +43,7 @@ public struct Monster : IFlatbufferObject
|
||||
/// multiline too
|
||||
public Monster? Testarrayoftables(int j) { int o = __p.__offset(26); return o != 0 ? (Monster?)(new Monster()).__assign(__p.__indirect(__p.__vector(o) + j * 4), __p.bb) : null; }
|
||||
public int TestarrayoftablesLength { get { int o = __p.__offset(26); return o != 0 ? __p.__vector_len(o) : 0; } }
|
||||
public Monster? TestarrayoftablesByKey(string key) { int o = __p.__offset(26); return o != 0 ? Monster.__lookup_by_key(__p.__vector(o), key, __p.bb) : null; }
|
||||
public Monster? Enemy { get { int o = __p.__offset(28); return o != 0 ? (Monster?)(new Monster()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
|
||||
public byte Testnestedflatbuffer(int j) { int o = __p.__offset(30); return o != 0 ? __p.bb.Get(__p.__vector(o) + j * 1) : (byte)0; }
|
||||
public int TestnestedflatbufferLength { get { int o = __p.__offset(30); return o != 0 ? __p.__vector_len(o) : 0; } }
|
||||
@@ -78,8 +81,14 @@ public struct Monster : IFlatbufferObject
|
||||
public bool MutateTestf3(float testf3) { int o = __p.__offset(58); if (o != 0) { __p.bb.PutFloat(o + __p.bb_pos, testf3); return true; } else { return false; } }
|
||||
public string Testarrayofstring2(int j) { int o = __p.__offset(60); return o != 0 ? __p.__string(__p.__vector(o) + j * 4) : null; }
|
||||
public int Testarrayofstring2Length { get { int o = __p.__offset(60); return o != 0 ? __p.__vector_len(o) : 0; } }
|
||||
public Ability? Testarrayofsortedstruct(int j) { int o = __p.__offset(62); return o != 0 ? (Ability?)(new Ability()).__assign(__p.__vector(o) + j * 8, __p.bb) : null; }
|
||||
public int TestarrayofsortedstructLength { get { int o = __p.__offset(62); return o != 0 ? __p.__vector_len(o) : 0; } }
|
||||
public byte Flex(int j) { int o = __p.__offset(64); return o != 0 ? __p.bb.Get(__p.__vector(o) + j * 1) : (byte)0; }
|
||||
public int FlexLength { get { int o = __p.__offset(64); return o != 0 ? __p.__vector_len(o) : 0; } }
|
||||
public ArraySegment<byte>? GetFlexBytes() { return __p.__vector_as_arraysegment(64); }
|
||||
public bool MutateFlex(int j, byte flex) { int o = __p.__offset(64); if (o != 0) { __p.bb.Put(__p.__vector(o) + j * 1, flex); return true; } else { return false; } }
|
||||
|
||||
public static void StartMonster(FlatBufferBuilder builder) { builder.StartObject(29); }
|
||||
public static void StartMonster(FlatBufferBuilder builder) { builder.StartObject(31); }
|
||||
public static void AddPos(FlatBufferBuilder builder, Offset<Vec3> posOffset) { builder.AddStruct(0, posOffset.Value, 0); }
|
||||
public static void AddMana(FlatBufferBuilder builder, short mana) { builder.AddShort(1, mana, 150); }
|
||||
public static void AddHp(FlatBufferBuilder builder, short hp) { builder.AddShort(2, hp, 100); }
|
||||
@@ -121,6 +130,11 @@ public struct Monster : IFlatbufferObject
|
||||
public static void AddTestarrayofstring2(FlatBufferBuilder builder, VectorOffset testarrayofstring2Offset) { builder.AddOffset(28, testarrayofstring2Offset.Value, 0); }
|
||||
public static VectorOffset CreateTestarrayofstring2Vector(FlatBufferBuilder builder, StringOffset[] data) { builder.StartVector(4, data.Length, 4); for (int i = data.Length - 1; i >= 0; i--) builder.AddOffset(data[i].Value); return builder.EndVector(); }
|
||||
public static void StartTestarrayofstring2Vector(FlatBufferBuilder builder, int numElems) { builder.StartVector(4, numElems, 4); }
|
||||
public static void AddTestarrayofsortedstruct(FlatBufferBuilder builder, VectorOffset testarrayofsortedstructOffset) { builder.AddOffset(29, testarrayofsortedstructOffset.Value, 0); }
|
||||
public static void StartTestarrayofsortedstructVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(8, numElems, 4); }
|
||||
public static void AddFlex(FlatBufferBuilder builder, VectorOffset flexOffset) { builder.AddOffset(30, flexOffset.Value, 0); }
|
||||
public static VectorOffset CreateFlexVector(FlatBufferBuilder builder, byte[] data) { builder.StartVector(1, data.Length, 1); for (int i = data.Length - 1; i >= 0; i--) builder.AddByte(data[i]); return builder.EndVector(); }
|
||||
public static void StartFlexVector(FlatBufferBuilder builder, int numElems) { builder.StartVector(1, numElems, 1); }
|
||||
public static Offset<Monster> EndMonster(FlatBufferBuilder builder) {
|
||||
int o = builder.EndObject();
|
||||
builder.Required(o, 10); // name
|
||||
@@ -128,17 +142,15 @@ public struct Monster : IFlatbufferObject
|
||||
}
|
||||
public static void FinishMonsterBuffer(FlatBufferBuilder builder, Offset<Monster> offset) { builder.Finish(offset.Value, "MONS"); }
|
||||
|
||||
public static VectorOffset CreateMySortedVectorOfTables(FlatBufferBuilder builder, Offset<Monster>[] offsets) {
|
||||
public static VectorOffset CreateSortedVectorOfMonster(FlatBufferBuilder builder, Offset<Monster>[] offsets) {
|
||||
Array.Sort(offsets, (Offset<Monster> o1, Offset<Monster> o2) => Table.CompareStrings(Table.__offset(10, o1.Value, builder.DataBuffer), Table.__offset(10, o2.Value, builder.DataBuffer), builder.DataBuffer));
|
||||
return builder.CreateVectorOfTables(offsets);
|
||||
}
|
||||
|
||||
public static Monster? LookupByKey(VectorOffset vectorOffset, string key, ByteBuffer bb) {
|
||||
public static Monster? __lookup_by_key(int vectorLocation, string key, ByteBuffer bb) {
|
||||
byte[] byteKey = System.Text.Encoding.UTF8.GetBytes(key);
|
||||
int vectorLocation = bb.Length - vectorOffset.Value;
|
||||
int span = bb.GetInt(vectorLocation);
|
||||
int span = bb.GetInt(vectorLocation - 4);
|
||||
int start = 0;
|
||||
vectorLocation += 4;
|
||||
while (span != 0) {
|
||||
int middle = span / 2;
|
||||
int tableOffset = Table.__indirect(vectorLocation + 4 * (start + middle), bb);
|
||||
|
||||
@@ -419,8 +419,52 @@ func (rcv *Monster) Testarrayofstring2Length() int {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *Monster) Testarrayofsortedstruct(obj *Ability, j int) bool {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(62))
|
||||
if o != 0 {
|
||||
x := rcv._tab.Vector(o)
|
||||
x += flatbuffers.UOffsetT(j) * 8
|
||||
obj.Init(rcv._tab.Bytes, x)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (rcv *Monster) TestarrayofsortedstructLength() int {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(62))
|
||||
if o != 0 {
|
||||
return rcv._tab.VectorLen(o)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *Monster) Flex(j int) byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(64))
|
||||
if o != 0 {
|
||||
a := rcv._tab.Vector(o)
|
||||
return rcv._tab.GetByte(a + flatbuffers.UOffsetT(j*1))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *Monster) FlexLength() int {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(64))
|
||||
if o != 0 {
|
||||
return rcv._tab.VectorLen(o)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (rcv *Monster) FlexBytes() []byte {
|
||||
o := flatbuffers.UOffsetT(rcv._tab.Offset(64))
|
||||
if o != 0 {
|
||||
return rcv._tab.ByteVector(o + rcv._tab.Pos)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func MonsterStart(builder *flatbuffers.Builder) {
|
||||
builder.StartObject(29)
|
||||
builder.StartObject(31)
|
||||
}
|
||||
func MonsterAddPos(builder *flatbuffers.Builder, pos flatbuffers.UOffsetT) {
|
||||
builder.PrependStructSlot(0, flatbuffers.UOffsetT(pos), 0)
|
||||
@@ -527,6 +571,18 @@ func MonsterAddTestarrayofstring2(builder *flatbuffers.Builder, testarrayofstrin
|
||||
func MonsterStartTestarrayofstring2Vector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
|
||||
return builder.StartVector(4, numElems, 4)
|
||||
}
|
||||
func MonsterAddTestarrayofsortedstruct(builder *flatbuffers.Builder, testarrayofsortedstruct flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(29, flatbuffers.UOffsetT(testarrayofsortedstruct), 0)
|
||||
}
|
||||
func MonsterStartTestarrayofsortedstructVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
|
||||
return builder.StartVector(8, numElems, 4)
|
||||
}
|
||||
func MonsterAddFlex(builder *flatbuffers.Builder, flex flatbuffers.UOffsetT) {
|
||||
builder.PrependUOffsetTSlot(30, flatbuffers.UOffsetT(flex), 0)
|
||||
}
|
||||
func MonsterStartFlexVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
|
||||
return builder.StartVector(1, numElems, 1)
|
||||
}
|
||||
func MonsterEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
return builder.EndObject()
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ public final class Monster extends Table {
|
||||
public Monster testarrayoftables(int j) { return testarrayoftables(new Monster(), j); }
|
||||
public Monster testarrayoftables(Monster obj, int j) { int o = __offset(26); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; }
|
||||
public int testarrayoftablesLength() { int o = __offset(26); return o != 0 ? __vector_len(o) : 0; }
|
||||
public Monster testarrayoftablesByKey(String key) { int o = __offset(26); return o != 0 ? Monster.__lookup_by_key(__vector(o), key, bb) : null; }
|
||||
public Monster enemy() { return enemy(new Monster()); }
|
||||
public Monster enemy(Monster obj) { int o = __offset(28); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; }
|
||||
public int testnestedflatbuffer(int j) { int o = __offset(30); return o != 0 ? bb.get(__vector(o) + j * 1) & 0xFF : 0; }
|
||||
@@ -87,8 +88,15 @@ public final class Monster extends Table {
|
||||
public boolean mutateTestf3(float testf3) { int o = __offset(58); if (o != 0) { bb.putFloat(o + bb_pos, testf3); return true; } else { return false; } }
|
||||
public String testarrayofstring2(int j) { int o = __offset(60); return o != 0 ? __string(__vector(o) + j * 4) : null; }
|
||||
public int testarrayofstring2Length() { int o = __offset(60); return o != 0 ? __vector_len(o) : 0; }
|
||||
public Ability testarrayofsortedstruct(int j) { return testarrayofsortedstruct(new Ability(), j); }
|
||||
public Ability testarrayofsortedstruct(Ability obj, int j) { int o = __offset(62); return o != 0 ? obj.__assign(__vector(o) + j * 8, bb) : null; }
|
||||
public int testarrayofsortedstructLength() { int o = __offset(62); return o != 0 ? __vector_len(o) : 0; }
|
||||
public int flex(int j) { int o = __offset(64); return o != 0 ? bb.get(__vector(o) + j * 1) & 0xFF : 0; }
|
||||
public int flexLength() { int o = __offset(64); return o != 0 ? __vector_len(o) : 0; }
|
||||
public ByteBuffer flexAsByteBuffer() { return __vector_as_bytebuffer(64, 1); }
|
||||
public boolean mutateFlex(int j, int flex) { int o = __offset(64); if (o != 0) { bb.put(__vector(o) + j * 1, (byte)flex); return true; } else { return false; } }
|
||||
|
||||
public static void startMonster(FlatBufferBuilder builder) { builder.startObject(29); }
|
||||
public static void startMonster(FlatBufferBuilder builder) { builder.startObject(31); }
|
||||
public static void addPos(FlatBufferBuilder builder, int posOffset) { builder.addStruct(0, posOffset, 0); }
|
||||
public static void addMana(FlatBufferBuilder builder, short mana) { builder.addShort(1, mana, 150); }
|
||||
public static void addHp(FlatBufferBuilder builder, short hp) { builder.addShort(2, hp, 100); }
|
||||
@@ -130,6 +138,11 @@ public final class Monster extends Table {
|
||||
public static void addTestarrayofstring2(FlatBufferBuilder builder, int testarrayofstring2Offset) { builder.addOffset(28, testarrayofstring2Offset, 0); }
|
||||
public static int createTestarrayofstring2Vector(FlatBufferBuilder builder, int[] data) { builder.startVector(4, data.length, 4); for (int i = data.length - 1; i >= 0; i--) builder.addOffset(data[i]); return builder.endVector(); }
|
||||
public static void startTestarrayofstring2Vector(FlatBufferBuilder builder, int numElems) { builder.startVector(4, numElems, 4); }
|
||||
public static void addTestarrayofsortedstruct(FlatBufferBuilder builder, int testarrayofsortedstructOffset) { builder.addOffset(29, testarrayofsortedstructOffset, 0); }
|
||||
public static void startTestarrayofsortedstructVector(FlatBufferBuilder builder, int numElems) { builder.startVector(8, numElems, 4); }
|
||||
public static void addFlex(FlatBufferBuilder builder, int flexOffset) { builder.addOffset(30, flexOffset, 0); }
|
||||
public static int createFlexVector(FlatBufferBuilder builder, byte[] data) { builder.startVector(1, data.length, 1); for (int i = data.length - 1; i >= 0; i--) builder.addByte(data[i]); return builder.endVector(); }
|
||||
public static void startFlexVector(FlatBufferBuilder builder, int numElems) { builder.startVector(1, numElems, 1); }
|
||||
public static int endMonster(FlatBufferBuilder builder) {
|
||||
int o = builder.endObject();
|
||||
builder.required(o, 10); // name
|
||||
@@ -140,12 +153,10 @@ public final class Monster extends Table {
|
||||
@Override
|
||||
protected int keysCompare(Integer o1, Integer o2, ByteBuffer _bb) { return compareStrings(__offset(10, o1, _bb), __offset(10, o2, _bb), _bb); }
|
||||
|
||||
public static Monster lookupByKey(int vectorOffset, String key, ByteBuffer bb) {
|
||||
public static Monster __lookup_by_key(int vectorLocation, String key, ByteBuffer bb) {
|
||||
byte[] byteKey = key.getBytes(Table.UTF8_CHARSET.get());
|
||||
int vectorLocation = bb.array().length - vectorOffset;
|
||||
int span = bb.getInt(vectorLocation);
|
||||
int span = bb.getInt(vectorLocation - 4);
|
||||
int start = 0;
|
||||
vectorLocation += 4;
|
||||
while (span != 0) {
|
||||
int middle = span / 2;
|
||||
int tableOffset = __indirect(vectorLocation + 4 * (start + middle), bb);
|
||||
|
||||
@@ -379,22 +379,68 @@ class Monster extends Table
|
||||
return $o != 0 ? $this->__vector_len($o) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returnVectorOffset
|
||||
*/
|
||||
public function getTestarrayofsortedstruct($j)
|
||||
{
|
||||
$o = $this->__offset(62);
|
||||
$obj = new Ability();
|
||||
return $o != 0 ? $obj->init($this->__vector($o) + $j *8, $this->bb) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getTestarrayofsortedstructLength()
|
||||
{
|
||||
$o = $this->__offset(62);
|
||||
return $o != 0 ? $this->__vector_len($o) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int offset
|
||||
* @return byte
|
||||
*/
|
||||
public function getFlex($j)
|
||||
{
|
||||
$o = $this->__offset(64);
|
||||
return $o != 0 ? $this->bb->getByte($this->__vector($o) + $j * 1) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getFlexLength()
|
||||
{
|
||||
$o = $this->__offset(64);
|
||||
return $o != 0 ? $this->__vector_len($o) : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFlexBytes()
|
||||
{
|
||||
return $this->__vector_as_bytes(64);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FlatBufferBuilder $builder
|
||||
* @return void
|
||||
*/
|
||||
public static function startMonster(FlatBufferBuilder $builder)
|
||||
{
|
||||
$builder->StartObject(29);
|
||||
$builder->StartObject(31);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FlatBufferBuilder $builder
|
||||
* @return Monster
|
||||
*/
|
||||
public static function createMonster(FlatBufferBuilder $builder, $pos, $mana, $hp, $name, $inventory, $color, $test_type, $test, $test4, $testarrayofstring, $testarrayoftables, $enemy, $testnestedflatbuffer, $testempty, $testbool, $testhashs32_fnv1, $testhashu32_fnv1, $testhashs64_fnv1, $testhashu64_fnv1, $testhashs32_fnv1a, $testhashu32_fnv1a, $testhashs64_fnv1a, $testhashu64_fnv1a, $testarrayofbools, $testf, $testf2, $testf3, $testarrayofstring2)
|
||||
public static function createMonster(FlatBufferBuilder $builder, $pos, $mana, $hp, $name, $inventory, $color, $test_type, $test, $test4, $testarrayofstring, $testarrayoftables, $enemy, $testnestedflatbuffer, $testempty, $testbool, $testhashs32_fnv1, $testhashu32_fnv1, $testhashs64_fnv1, $testhashu64_fnv1, $testhashs32_fnv1a, $testhashu32_fnv1a, $testhashs64_fnv1a, $testhashu64_fnv1a, $testarrayofbools, $testf, $testf2, $testf3, $testarrayofstring2, $testarrayofsortedstruct, $flex)
|
||||
{
|
||||
$builder->startObject(29);
|
||||
$builder->startObject(31);
|
||||
self::addPos($builder, $pos);
|
||||
self::addMana($builder, $mana);
|
||||
self::addHp($builder, $hp);
|
||||
@@ -423,6 +469,8 @@ class Monster extends Table
|
||||
self::addTestf2($builder, $testf2);
|
||||
self::addTestf3($builder, $testf3);
|
||||
self::addTestarrayofstring2($builder, $testarrayofstring2);
|
||||
self::addTestarrayofsortedstruct($builder, $testarrayofsortedstruct);
|
||||
self::addFlex($builder, $flex);
|
||||
$o = $builder->endObject();
|
||||
$builder->required($o, 10); // name
|
||||
return $o;
|
||||
@@ -871,6 +919,74 @@ class Monster extends Table
|
||||
$builder->startVector(4, $numElems, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FlatBufferBuilder $builder
|
||||
* @param VectorOffset
|
||||
* @return void
|
||||
*/
|
||||
public static function addTestarrayofsortedstruct(FlatBufferBuilder $builder, $testarrayofsortedstruct)
|
||||
{
|
||||
$builder->addOffsetX(29, $testarrayofsortedstruct, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FlatBufferBuilder $builder
|
||||
* @param array offset array
|
||||
* @return int vector offset
|
||||
*/
|
||||
public static function createTestarrayofsortedstructVector(FlatBufferBuilder $builder, array $data)
|
||||
{
|
||||
$builder->startVector(8, count($data), 4);
|
||||
for ($i = count($data) - 1; $i >= 0; $i--) {
|
||||
$builder->addOffset($data[$i]);
|
||||
}
|
||||
return $builder->endVector();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FlatBufferBuilder $builder
|
||||
* @param int $numElems
|
||||
* @return void
|
||||
*/
|
||||
public static function startTestarrayofsortedstructVector(FlatBufferBuilder $builder, $numElems)
|
||||
{
|
||||
$builder->startVector(8, $numElems, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FlatBufferBuilder $builder
|
||||
* @param VectorOffset
|
||||
* @return void
|
||||
*/
|
||||
public static function addFlex(FlatBufferBuilder $builder, $flex)
|
||||
{
|
||||
$builder->addOffsetX(30, $flex, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FlatBufferBuilder $builder
|
||||
* @param array offset array
|
||||
* @return int vector offset
|
||||
*/
|
||||
public static function createFlexVector(FlatBufferBuilder $builder, array $data)
|
||||
{
|
||||
$builder->startVector(1, count($data), 1);
|
||||
for ($i = count($data) - 1; $i >= 0; $i--) {
|
||||
$builder->addByte($data[$i]);
|
||||
}
|
||||
return $builder->endVector();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FlatBufferBuilder $builder
|
||||
* @param int $numElems
|
||||
* @return void
|
||||
*/
|
||||
public static function startFlexVector(FlatBufferBuilder $builder, $numElems)
|
||||
{
|
||||
$builder->startVector(1, $numElems, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param FlatBufferBuilder $builder
|
||||
* @return int table offset
|
||||
|
||||
@@ -297,7 +297,41 @@ class Monster(object):
|
||||
return self._tab.VectorLen(o)
|
||||
return 0
|
||||
|
||||
def MonsterStart(builder): builder.StartObject(29)
|
||||
# Monster
|
||||
def Testarrayofsortedstruct(self, j):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(62))
|
||||
if o != 0:
|
||||
x = self._tab.Vector(o)
|
||||
x += flatbuffers.number_types.UOffsetTFlags.py_type(j) * 8
|
||||
from .Ability import Ability
|
||||
obj = Ability()
|
||||
obj.Init(self._tab.Bytes, x)
|
||||
return obj
|
||||
return None
|
||||
|
||||
# Monster
|
||||
def TestarrayofsortedstructLength(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(62))
|
||||
if o != 0:
|
||||
return self._tab.VectorLen(o)
|
||||
return 0
|
||||
|
||||
# Monster
|
||||
def Flex(self, j):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(64))
|
||||
if o != 0:
|
||||
a = self._tab.Vector(o)
|
||||
return self._tab.Get(flatbuffers.number_types.Uint8Flags, a + flatbuffers.number_types.UOffsetTFlags.py_type(j * 1))
|
||||
return 0
|
||||
|
||||
# Monster
|
||||
def FlexLength(self):
|
||||
o = flatbuffers.number_types.UOffsetTFlags.py_type(self._tab.Offset(64))
|
||||
if o != 0:
|
||||
return self._tab.VectorLen(o)
|
||||
return 0
|
||||
|
||||
def MonsterStart(builder): builder.StartObject(31)
|
||||
def MonsterAddPos(builder, pos): builder.PrependStructSlot(0, flatbuffers.number_types.UOffsetTFlags.py_type(pos), 0)
|
||||
def MonsterAddMana(builder, mana): builder.PrependInt16Slot(1, mana, 150)
|
||||
def MonsterAddHp(builder, hp): builder.PrependInt16Slot(2, hp, 100)
|
||||
@@ -333,4 +367,8 @@ def MonsterAddTestf2(builder, testf2): builder.PrependFloat32Slot(26, testf2, 3.
|
||||
def MonsterAddTestf3(builder, testf3): builder.PrependFloat32Slot(27, testf3, 0.0)
|
||||
def MonsterAddTestarrayofstring2(builder, testarrayofstring2): builder.PrependUOffsetTRelativeSlot(28, flatbuffers.number_types.UOffsetTFlags.py_type(testarrayofstring2), 0)
|
||||
def MonsterStartTestarrayofstring2Vector(builder, numElems): return builder.StartVector(4, numElems, 4)
|
||||
def MonsterAddTestarrayofsortedstruct(builder, testarrayofsortedstruct): builder.PrependUOffsetTRelativeSlot(29, flatbuffers.number_types.UOffsetTFlags.py_type(testarrayofsortedstruct), 0)
|
||||
def MonsterStartTestarrayofsortedstructVector(builder, numElems): return builder.StartVector(8, numElems, 4)
|
||||
def MonsterAddFlex(builder, flex): builder.PrependUOffsetTRelativeSlot(30, flatbuffers.number_types.UOffsetTFlags.py_type(flex), 0)
|
||||
def MonsterStartFlexVector(builder, numElems): return builder.StartVector(1, numElems, 1)
|
||||
def MonsterEnd(builder): return builder.EndObject()
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// <auto-generated>
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// </auto-generated>
|
||||
|
||||
namespace MyGame.Example
|
||||
{
|
||||
|
||||
using System;
|
||||
using FlatBuffers;
|
||||
using global::System;
|
||||
using global::FlatBuffers;
|
||||
|
||||
public struct Stat : IFlatbufferObject
|
||||
{
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// <auto-generated>
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// </auto-generated>
|
||||
|
||||
namespace MyGame.Example
|
||||
{
|
||||
|
||||
using System;
|
||||
using FlatBuffers;
|
||||
using global::System;
|
||||
using global::FlatBuffers;
|
||||
|
||||
public struct Test : IFlatbufferObject
|
||||
{
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// <auto-generated>
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// </auto-generated>
|
||||
|
||||
namespace MyGame.Example
|
||||
{
|
||||
|
||||
using System;
|
||||
using FlatBuffers;
|
||||
using global::System;
|
||||
using global::FlatBuffers;
|
||||
|
||||
public partial struct TestSimpleTableWithEnum : IFlatbufferObject
|
||||
{
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// <auto-generated>
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// </auto-generated>
|
||||
|
||||
namespace MyGame.Example
|
||||
{
|
||||
|
||||
using System;
|
||||
using FlatBuffers;
|
||||
using global::System;
|
||||
using global::FlatBuffers;
|
||||
|
||||
public struct Vec3 : IFlatbufferObject
|
||||
{
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// <auto-generated>
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
// </auto-generated>
|
||||
|
||||
namespace MyGame.Example2
|
||||
{
|
||||
|
||||
using System;
|
||||
using FlatBuffers;
|
||||
using global::System;
|
||||
using global::FlatBuffers;
|
||||
|
||||
public struct Monster : IFlatbufferObject
|
||||
{
|
||||
|
||||
@@ -20,7 +20,7 @@ gen_code_path=${test_dir}
|
||||
runtime_library_dir=${test_dir}/../python
|
||||
|
||||
# Emit Python code for the example schema in the test dir:
|
||||
${test_dir}/../flatc -p -o ${gen_code_path} monster_test.fbs
|
||||
${test_dir}/../flatc -p -o ${gen_code_path} -I include_test monster_test.fbs
|
||||
|
||||
# Syntax: run_tests <interpreter> <benchmark vtable dedupes>
|
||||
# <benchmark read count> <benchmark build count>
|
||||
|
||||
43
tests/TestAll.sh
Normal file
43
tests/TestAll.sh
Normal file
@@ -0,0 +1,43 @@
|
||||
echo "************************ Java:"
|
||||
|
||||
sh JavaTest.sh
|
||||
|
||||
echo "************************ Go:"
|
||||
|
||||
sh GoTest.sh
|
||||
|
||||
echo "************************ Python:"
|
||||
|
||||
sh PythonTest.sh
|
||||
|
||||
echo "************************ JavaScript:"
|
||||
|
||||
sh JavaScriptTest.sh
|
||||
|
||||
echo "************************ TypeScript:"
|
||||
|
||||
sh TypeScriptTest.sh
|
||||
|
||||
echo "************************ C++:"
|
||||
|
||||
cd ..
|
||||
./flattests
|
||||
cd tests
|
||||
|
||||
echo "************************ C#:"
|
||||
|
||||
cd FlatBuffers.Test
|
||||
sh NetTest.sh
|
||||
cd ..
|
||||
|
||||
echo "************************ PHP:"
|
||||
|
||||
php phpTest.php
|
||||
|
||||
echo "************************ C:"
|
||||
|
||||
echo "(in a different repo)"
|
||||
|
||||
echo "************************ Swift:"
|
||||
|
||||
echo "(in a different repo)"
|
||||
23
tests/TypeScriptTest.sh
Executable file
23
tests/TypeScriptTest.sh
Executable file
@@ -0,0 +1,23 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright 2016 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
pushd "$(dirname $0)" >/dev/null
|
||||
../flatc --ts --no-fb-import --gen-mutable -o ts -I include_test monster_test.fbs
|
||||
../flatc -b -I include_test monster_test.fbs unicode_test.json
|
||||
npm install @types/flatbuffers
|
||||
tsc --strict --noUnusedParameters --noUnusedLocals --noImplicitReturns --strictNullChecks ts/monster_test_generated.ts
|
||||
npm uninstall @types/flatbuffers
|
||||
node JavaScriptTest ./ts/monster_test_generated
|
||||
@@ -15,6 +15,6 @@
|
||||
set buildtype=Release
|
||||
if "%1"=="-b" set buildtype=%2
|
||||
|
||||
..\%buildtype%\flatc.exe --cpp --java --csharp --go --binary --python --js --php --grpc --gen-mutable --gen-object-api --no-includes monster_test.fbs monsterdata_test.json
|
||||
..\%buildtype%\flatc.exe --cpp --java --csharp --go --binary --python --js --php --grpc --gen-mutable --gen-object-api --no-includes -I include_test monster_test.fbs monsterdata_test.json
|
||||
..\%buildtype%\flatc.exe --cpp --java --csharp --go --binary --python --js --php --gen-mutable -o namespace_test namespace_test\namespace_test1.fbs namespace_test\namespace_test2.fbs
|
||||
..\%buildtype%\flatc.exe --binary --schema monster_test.fbs
|
||||
..\%buildtype%\flatc.exe --binary --schema -I include_test monster_test.fbs
|
||||
|
||||
@@ -14,11 +14,10 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
../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 --cpp -o union_vector ./union_vector/union_vector.fbs
|
||||
../flatc -b --schema --bfbs-comments monster_test.fbs
|
||||
../flatc --cpp --java --csharp --go --binary --python --js --ts --php --grpc --gen-mutable --gen-object-api --no-includes --no-fb-import -I include_test monster_test.fbs monsterdata_test.json
|
||||
../flatc --cpp --java --csharp --go --binary --python --js --ts --php --gen-mutable --no-fb-import -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs
|
||||
../flatc --cpp --gen-mutable --gen-object-api -o union_vector ./union_vector/union_vector.fbs
|
||||
../flatc -b --schema --bfbs-comments -I include_test monster_test.fbs
|
||||
cd ../samples
|
||||
../flatc --cpp --gen-mutable --gen-object-api monster.fbs
|
||||
cd ../reflection
|
||||
sh generate_code.sh
|
||||
|
||||
5
tests/include_test/include_test1.fbs
Normal file
5
tests/include_test/include_test1.fbs
Normal file
@@ -0,0 +1,5 @@
|
||||
include "sub/include_test2.fbs";
|
||||
include "sub/include_test2.fbs"; // should be skipped
|
||||
include "include_test1.fbs"; // should be skipped
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
include "include_test2.fbs"; // should be skipped
|
||||
include "sub/include_test2.fbs"; // should be skipped
|
||||
|
||||
namespace MyGame.OtherNameSpace;
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
include "include_test2.fbs";
|
||||
include "include_test2.fbs"; // should be skipped
|
||||
include "include_test1.fbs"; // should be skipped
|
||||
|
||||
|
||||
Binary file not shown.
@@ -29,6 +29,11 @@ struct Vec3 (force_align: 16) {
|
||||
test3:Test;
|
||||
}
|
||||
|
||||
struct Ability {
|
||||
id:uint(key);
|
||||
distance:uint;
|
||||
}
|
||||
|
||||
table Stat {
|
||||
id:string;
|
||||
val:long;
|
||||
@@ -50,6 +55,7 @@ table Monster {
|
||||
testarrayofstring:[string] (id: 10);
|
||||
testarrayofstring2:[string] (id: 28);
|
||||
testarrayofbools:[bool] (id: 24);
|
||||
testarrayofsortedstruct:[Ability] (id: 29);
|
||||
enemy:MyGame.Example.Monster (id:12); // Test referring by full namespace.
|
||||
test:Any (id: 8);
|
||||
test4:[Test] (id: 9);
|
||||
@@ -67,6 +73,7 @@ table Monster {
|
||||
testf:float = 3.14159 (id:25);
|
||||
testf2:float = 3 (id:26);
|
||||
testf3:float (id:27);
|
||||
flex:[ubyte] (id:30, flexbuffer);
|
||||
}
|
||||
|
||||
rpc_service MonsterStorage {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Generated by the gRPC protobuf plugin.
|
||||
// Generated by the gRPC C++ plugin.
|
||||
// If you make any local change, they will be lost.
|
||||
// source: monster_test
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
#include <grpc++/impl/codegen/rpc_service_method.h>
|
||||
#include <grpc++/impl/codegen/service_type.h>
|
||||
#include <grpc++/impl/codegen/sync_stream.h>
|
||||
|
||||
namespace MyGame {
|
||||
namespace Example {
|
||||
|
||||
@@ -32,47 +31,46 @@ MonsterStorage::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& cha
|
||||
, rpcmethod_Retrieve_(MonsterStorage_method_names[1], ::grpc::RpcMethod::SERVER_STREAMING, channel)
|
||||
{}
|
||||
|
||||
::grpc::Status MonsterStorage::Stub::Store(::grpc::ClientContext* context, const flatbuffers::BufferRef<Monster>& request, flatbuffers::BufferRef<Stat>* response) {
|
||||
::grpc::Status MonsterStorage::Stub::Store(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, flatbuffers::grpc::Message<Stat>* response) {
|
||||
return ::grpc::BlockingUnaryCall(channel_.get(), rpcmethod_Store_, context, request, response);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncResponseReader< flatbuffers::BufferRef<Stat>>* MonsterStorage::Stub::AsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::BufferRef<Monster>& request, ::grpc::CompletionQueue* cq) {
|
||||
return new ::grpc::ClientAsyncResponseReader< flatbuffers::BufferRef<Stat>>(channel_.get(), cq, rpcmethod_Store_, context, request);
|
||||
::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>* MonsterStorage::Stub::AsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) {
|
||||
return ::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>::Create(channel_.get(), cq, rpcmethod_Store_, context, request);
|
||||
}
|
||||
|
||||
::grpc::ClientReader< flatbuffers::BufferRef<Monster>>* MonsterStorage::Stub::RetrieveRaw(::grpc::ClientContext* context, const flatbuffers::BufferRef<Stat>& request) {
|
||||
return new ::grpc::ClientReader< flatbuffers::BufferRef<Monster>>(channel_.get(), rpcmethod_Retrieve_, context, request);
|
||||
::grpc::ClientReader< flatbuffers::grpc::Message<Monster>>* MonsterStorage::Stub::RetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request) {
|
||||
return new ::grpc::ClientReader< flatbuffers::grpc::Message<Monster>>(channel_.get(), rpcmethod_Retrieve_, context, request);
|
||||
}
|
||||
|
||||
::grpc::ClientAsyncReader< flatbuffers::BufferRef<Monster>>* MonsterStorage::Stub::AsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::BufferRef<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) {
|
||||
return new ::grpc::ClientAsyncReader< flatbuffers::BufferRef<Monster>>(channel_.get(), cq, rpcmethod_Retrieve_, context, request, tag);
|
||||
::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>* MonsterStorage::Stub::AsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) {
|
||||
return ::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>::Create(channel_.get(), cq, rpcmethod_Retrieve_, context, request, tag);
|
||||
}
|
||||
|
||||
MonsterStorage::Service::Service() {
|
||||
(void)MonsterStorage_method_names;
|
||||
AddMethod(new ::grpc::RpcServiceMethod(
|
||||
MonsterStorage_method_names[0],
|
||||
::grpc::RpcMethod::NORMAL_RPC,
|
||||
new ::grpc::RpcMethodHandler< MonsterStorage::Service, flatbuffers::BufferRef<Monster>, flatbuffers::BufferRef<Stat>>(
|
||||
new ::grpc::RpcMethodHandler< MonsterStorage::Service, flatbuffers::grpc::Message<Monster>, flatbuffers::grpc::Message<Stat>>(
|
||||
std::mem_fn(&MonsterStorage::Service::Store), this)));
|
||||
AddMethod(new ::grpc::RpcServiceMethod(
|
||||
MonsterStorage_method_names[1],
|
||||
::grpc::RpcMethod::SERVER_STREAMING,
|
||||
new ::grpc::ServerStreamingHandler< MonsterStorage::Service, flatbuffers::BufferRef<Stat>, flatbuffers::BufferRef<Monster>>(
|
||||
new ::grpc::ServerStreamingHandler< MonsterStorage::Service, flatbuffers::grpc::Message<Stat>, flatbuffers::grpc::Message<Monster>>(
|
||||
std::mem_fn(&MonsterStorage::Service::Retrieve), this)));
|
||||
}
|
||||
|
||||
MonsterStorage::Service::~Service() {
|
||||
}
|
||||
|
||||
::grpc::Status MonsterStorage::Service::Store(::grpc::ServerContext* context, const flatbuffers::BufferRef<Monster>* request, flatbuffers::BufferRef<Stat>* response) {
|
||||
::grpc::Status MonsterStorage::Service::Store(::grpc::ServerContext* context, const flatbuffers::grpc::Message<Monster>* request, flatbuffers::grpc::Message<Stat>* response) {
|
||||
(void) context;
|
||||
(void) request;
|
||||
(void) response;
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
|
||||
::grpc::Status MonsterStorage::Service::Retrieve(::grpc::ServerContext* context, const flatbuffers::BufferRef<Stat>* request, ::grpc::ServerWriter< flatbuffers::BufferRef<Monster>>* writer) {
|
||||
::grpc::Status MonsterStorage::Service::Retrieve(::grpc::ServerContext* context, const flatbuffers::grpc::Message<Stat>* request, ::grpc::ServerWriter< flatbuffers::grpc::Message<Monster>>* writer) {
|
||||
(void) context;
|
||||
(void) request;
|
||||
(void) writer;
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
// Generated by the gRPC protobuf plugin.
|
||||
// Generated by the gRPC C++ plugin.
|
||||
// If you make any local change, they will be lost.
|
||||
// source: monster_test
|
||||
#ifndef GRPC_monster_5ftest__INCLUDED
|
||||
#define GRPC_monster_5ftest__INCLUDED
|
||||
|
||||
#include "monster_test_generated.h"
|
||||
#include "flatbuffers/grpc.h"
|
||||
#include "monster_test_generated.h"
|
||||
|
||||
#include <grpc++/impl/codegen/async_stream.h>
|
||||
#include <grpc++/impl/codegen/async_unary_call.h>
|
||||
#include <grpc++/impl/codegen/method_handler_impl.h>
|
||||
#include <grpc++/impl/codegen/proto_utils.h>
|
||||
#include <grpc++/impl/codegen/rpc_method.h>
|
||||
#include <grpc++/impl/codegen/service_type.h>
|
||||
#include <grpc++/impl/codegen/status.h>
|
||||
@@ -26,45 +28,48 @@ class ServerContext;
|
||||
namespace MyGame {
|
||||
namespace Example {
|
||||
|
||||
class MonsterStorage GRPC_FINAL {
|
||||
class MonsterStorage final {
|
||||
public:
|
||||
static constexpr char const* service_full_name() {
|
||||
return "MyGame.Example.MonsterStorage";
|
||||
}
|
||||
class StubInterface {
|
||||
public:
|
||||
virtual ~StubInterface() {}
|
||||
virtual ::grpc::Status Store(::grpc::ClientContext* context, const flatbuffers::BufferRef<Monster>& request, flatbuffers::BufferRef<Stat>* response) = 0;
|
||||
std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::BufferRef<Stat>>> AsyncStore(::grpc::ClientContext* context, const flatbuffers::BufferRef<Monster>& request, ::grpc::CompletionQueue* cq) {
|
||||
return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::BufferRef<Stat>>>(AsyncStoreRaw(context, request, cq));
|
||||
virtual ::grpc::Status Store(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, flatbuffers::grpc::Message<Stat>* response) = 0;
|
||||
std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::grpc::Message<Stat>>> AsyncStore(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) {
|
||||
return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::grpc::Message<Stat>>>(AsyncStoreRaw(context, request, cq));
|
||||
}
|
||||
std::unique_ptr< ::grpc::ClientReaderInterface< flatbuffers::BufferRef<Monster>>> Retrieve(::grpc::ClientContext* context, const flatbuffers::BufferRef<Stat>& request) {
|
||||
return std::unique_ptr< ::grpc::ClientReaderInterface< flatbuffers::BufferRef<Monster>>>(RetrieveRaw(context, request));
|
||||
std::unique_ptr< ::grpc::ClientReaderInterface< flatbuffers::grpc::Message<Monster>>> Retrieve(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request) {
|
||||
return std::unique_ptr< ::grpc::ClientReaderInterface< flatbuffers::grpc::Message<Monster>>>(RetrieveRaw(context, request));
|
||||
}
|
||||
std::unique_ptr< ::grpc::ClientAsyncReaderInterface< flatbuffers::BufferRef<Monster>>> AsyncRetrieve(::grpc::ClientContext* context, const flatbuffers::BufferRef<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) {
|
||||
return std::unique_ptr< ::grpc::ClientAsyncReaderInterface< flatbuffers::BufferRef<Monster>>>(AsyncRetrieveRaw(context, request, cq, tag));
|
||||
std::unique_ptr< ::grpc::ClientAsyncReaderInterface< flatbuffers::grpc::Message<Monster>>> AsyncRetrieve(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) {
|
||||
return std::unique_ptr< ::grpc::ClientAsyncReaderInterface< flatbuffers::grpc::Message<Monster>>>(AsyncRetrieveRaw(context, request, cq, tag));
|
||||
}
|
||||
private:
|
||||
virtual ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::BufferRef<Stat>>* AsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::BufferRef<Monster>& request, ::grpc::CompletionQueue* cq) = 0;
|
||||
virtual ::grpc::ClientReaderInterface< flatbuffers::BufferRef<Monster>>* RetrieveRaw(::grpc::ClientContext* context, const flatbuffers::BufferRef<Stat>& request) = 0;
|
||||
virtual ::grpc::ClientAsyncReaderInterface< flatbuffers::BufferRef<Monster>>* AsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::BufferRef<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) = 0;
|
||||
virtual ::grpc::ClientAsyncResponseReaderInterface< flatbuffers::grpc::Message<Stat>>* AsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) = 0;
|
||||
virtual ::grpc::ClientReaderInterface< flatbuffers::grpc::Message<Monster>>* RetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request) = 0;
|
||||
virtual ::grpc::ClientAsyncReaderInterface< flatbuffers::grpc::Message<Monster>>* AsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) = 0;
|
||||
};
|
||||
class Stub GRPC_FINAL : public StubInterface {
|
||||
class Stub final : public StubInterface {
|
||||
public:
|
||||
Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel);
|
||||
::grpc::Status Store(::grpc::ClientContext* context, const flatbuffers::BufferRef<Monster>& request, flatbuffers::BufferRef<Stat>* response) GRPC_OVERRIDE;
|
||||
std::unique_ptr< ::grpc::ClientAsyncResponseReader< flatbuffers::BufferRef<Stat>>> AsyncStore(::grpc::ClientContext* context, const flatbuffers::BufferRef<Monster>& request, ::grpc::CompletionQueue* cq) {
|
||||
return std::unique_ptr< ::grpc::ClientAsyncResponseReader< flatbuffers::BufferRef<Stat>>>(AsyncStoreRaw(context, request, cq));
|
||||
::grpc::Status Store(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, flatbuffers::grpc::Message<Stat>* response) override;
|
||||
std::unique_ptr< ::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>> AsyncStore(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) {
|
||||
return std::unique_ptr< ::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>>(AsyncStoreRaw(context, request, cq));
|
||||
}
|
||||
std::unique_ptr< ::grpc::ClientReader< flatbuffers::BufferRef<Monster>>> Retrieve(::grpc::ClientContext* context, const flatbuffers::BufferRef<Stat>& request) {
|
||||
return std::unique_ptr< ::grpc::ClientReader< flatbuffers::BufferRef<Monster>>>(RetrieveRaw(context, request));
|
||||
std::unique_ptr< ::grpc::ClientReader< flatbuffers::grpc::Message<Monster>>> Retrieve(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request) {
|
||||
return std::unique_ptr< ::grpc::ClientReader< flatbuffers::grpc::Message<Monster>>>(RetrieveRaw(context, request));
|
||||
}
|
||||
std::unique_ptr< ::grpc::ClientAsyncReader< flatbuffers::BufferRef<Monster>>> AsyncRetrieve(::grpc::ClientContext* context, const flatbuffers::BufferRef<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) {
|
||||
return std::unique_ptr< ::grpc::ClientAsyncReader< flatbuffers::BufferRef<Monster>>>(AsyncRetrieveRaw(context, request, cq, tag));
|
||||
std::unique_ptr< ::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>> AsyncRetrieve(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) {
|
||||
return std::unique_ptr< ::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>>(AsyncRetrieveRaw(context, request, cq, tag));
|
||||
}
|
||||
|
||||
private:
|
||||
std::shared_ptr< ::grpc::ChannelInterface> channel_;
|
||||
::grpc::ClientAsyncResponseReader< flatbuffers::BufferRef<Stat>>* AsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::BufferRef<Monster>& request, ::grpc::CompletionQueue* cq) GRPC_OVERRIDE;
|
||||
::grpc::ClientReader< flatbuffers::BufferRef<Monster>>* RetrieveRaw(::grpc::ClientContext* context, const flatbuffers::BufferRef<Stat>& request) GRPC_OVERRIDE;
|
||||
::grpc::ClientAsyncReader< flatbuffers::BufferRef<Monster>>* AsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::BufferRef<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) GRPC_OVERRIDE;
|
||||
::grpc::ClientAsyncResponseReader< flatbuffers::grpc::Message<Stat>>* AsyncStoreRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Monster>& request, ::grpc::CompletionQueue* cq) override;
|
||||
::grpc::ClientReader< flatbuffers::grpc::Message<Monster>>* RetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request) override;
|
||||
::grpc::ClientAsyncReader< flatbuffers::grpc::Message<Monster>>* AsyncRetrieveRaw(::grpc::ClientContext* context, const flatbuffers::grpc::Message<Stat>& request, ::grpc::CompletionQueue* cq, void* tag) override;
|
||||
const ::grpc::RpcMethod rpcmethod_Store_;
|
||||
const ::grpc::RpcMethod rpcmethod_Retrieve_;
|
||||
};
|
||||
@@ -74,8 +79,8 @@ class MonsterStorage GRPC_FINAL {
|
||||
public:
|
||||
Service();
|
||||
virtual ~Service();
|
||||
virtual ::grpc::Status Store(::grpc::ServerContext* context, const flatbuffers::BufferRef<Monster>* request, flatbuffers::BufferRef<Stat>* response);
|
||||
virtual ::grpc::Status Retrieve(::grpc::ServerContext* context, const flatbuffers::BufferRef<Stat>* request, ::grpc::ServerWriter< flatbuffers::BufferRef<Monster>>* writer);
|
||||
virtual ::grpc::Status Store(::grpc::ServerContext* context, const flatbuffers::grpc::Message<Monster>* request, flatbuffers::grpc::Message<Stat>* response);
|
||||
virtual ::grpc::Status Retrieve(::grpc::ServerContext* context, const flatbuffers::grpc::Message<Stat>* request, ::grpc::ServerWriter< flatbuffers::grpc::Message<Monster>>* writer);
|
||||
};
|
||||
template <class BaseClass>
|
||||
class WithAsyncMethod_Store : public BaseClass {
|
||||
@@ -85,15 +90,15 @@ class MonsterStorage GRPC_FINAL {
|
||||
WithAsyncMethod_Store() {
|
||||
::grpc::Service::MarkMethodAsync(0);
|
||||
}
|
||||
~WithAsyncMethod_Store() GRPC_OVERRIDE {
|
||||
~WithAsyncMethod_Store() override {
|
||||
BaseClassMustBeDerivedFromService(this);
|
||||
}
|
||||
// disable synchronous version of this method
|
||||
::grpc::Status Store(::grpc::ServerContext* context, const flatbuffers::BufferRef<Monster>* request, flatbuffers::BufferRef<Stat>* response) GRPC_FINAL GRPC_OVERRIDE {
|
||||
::grpc::Status Store(::grpc::ServerContext* context, const flatbuffers::grpc::Message<Monster>* request, flatbuffers::grpc::Message<Stat>* response) final override {
|
||||
abort();
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
void RequestStore(::grpc::ServerContext* context, flatbuffers::BufferRef<Monster>* request, ::grpc::ServerAsyncResponseWriter< flatbuffers::BufferRef<Stat>>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
|
||||
void RequestStore(::grpc::ServerContext* context, flatbuffers::grpc::Message<Monster>* request, ::grpc::ServerAsyncResponseWriter< flatbuffers::grpc::Message<Stat>>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
|
||||
::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag);
|
||||
}
|
||||
};
|
||||
@@ -105,15 +110,15 @@ class MonsterStorage GRPC_FINAL {
|
||||
WithAsyncMethod_Retrieve() {
|
||||
::grpc::Service::MarkMethodAsync(1);
|
||||
}
|
||||
~WithAsyncMethod_Retrieve() GRPC_OVERRIDE {
|
||||
~WithAsyncMethod_Retrieve() override {
|
||||
BaseClassMustBeDerivedFromService(this);
|
||||
}
|
||||
// disable synchronous version of this method
|
||||
::grpc::Status Retrieve(::grpc::ServerContext* context, const flatbuffers::BufferRef<Stat>* request, ::grpc::ServerWriter< flatbuffers::BufferRef<Monster>>* writer) GRPC_FINAL GRPC_OVERRIDE {
|
||||
::grpc::Status Retrieve(::grpc::ServerContext* context, const flatbuffers::grpc::Message<Stat>* request, ::grpc::ServerWriter< flatbuffers::grpc::Message<Monster>>* writer) final override {
|
||||
abort();
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
void RequestRetrieve(::grpc::ServerContext* context, flatbuffers::BufferRef<Stat>* request, ::grpc::ServerAsyncWriter< flatbuffers::BufferRef<Monster>>* writer, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
|
||||
void RequestRetrieve(::grpc::ServerContext* context, flatbuffers::grpc::Message<Stat>* request, ::grpc::ServerAsyncWriter< flatbuffers::grpc::Message<Monster>>* writer, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) {
|
||||
::grpc::Service::RequestAsyncServerStreaming(1, context, request, writer, new_call_cq, notification_cq, tag);
|
||||
}
|
||||
};
|
||||
@@ -126,11 +131,11 @@ class MonsterStorage GRPC_FINAL {
|
||||
WithGenericMethod_Store() {
|
||||
::grpc::Service::MarkMethodGeneric(0);
|
||||
}
|
||||
~WithGenericMethod_Store() GRPC_OVERRIDE {
|
||||
~WithGenericMethod_Store() override {
|
||||
BaseClassMustBeDerivedFromService(this);
|
||||
}
|
||||
// disable synchronous version of this method
|
||||
::grpc::Status Store(::grpc::ServerContext* context, const flatbuffers::BufferRef<Monster>* request, flatbuffers::BufferRef<Stat>* response) GRPC_FINAL GRPC_OVERRIDE {
|
||||
::grpc::Status Store(::grpc::ServerContext* context, const flatbuffers::grpc::Message<Monster>* request, flatbuffers::grpc::Message<Stat>* response) final override {
|
||||
abort();
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
@@ -143,15 +148,58 @@ class MonsterStorage GRPC_FINAL {
|
||||
WithGenericMethod_Retrieve() {
|
||||
::grpc::Service::MarkMethodGeneric(1);
|
||||
}
|
||||
~WithGenericMethod_Retrieve() GRPC_OVERRIDE {
|
||||
~WithGenericMethod_Retrieve() override {
|
||||
BaseClassMustBeDerivedFromService(this);
|
||||
}
|
||||
// disable synchronous version of this method
|
||||
::grpc::Status Retrieve(::grpc::ServerContext* context, const flatbuffers::BufferRef<Stat>* request, ::grpc::ServerWriter< flatbuffers::BufferRef<Monster>>* writer) GRPC_FINAL GRPC_OVERRIDE {
|
||||
::grpc::Status Retrieve(::grpc::ServerContext* context, const flatbuffers::grpc::Message<Stat>* request, ::grpc::ServerWriter< flatbuffers::grpc::Message<Monster>>* writer) final override {
|
||||
abort();
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
};
|
||||
template <class BaseClass>
|
||||
class WithStreamedUnaryMethod_Store : public BaseClass {
|
||||
private:
|
||||
void BaseClassMustBeDerivedFromService(const Service *service) {}
|
||||
public:
|
||||
WithStreamedUnaryMethod_Store() {
|
||||
::grpc::Service::MarkMethodStreamed(0,
|
||||
new ::grpc::StreamedUnaryHandler< flatbuffers::grpc::Message<Monster>, flatbuffers::grpc::Message<Stat>>(std::bind(&WithStreamedUnaryMethod_Store<BaseClass>::StreamedStore, this, std::placeholders::_1, std::placeholders::_2)));
|
||||
}
|
||||
~WithStreamedUnaryMethod_Store() override {
|
||||
BaseClassMustBeDerivedFromService(this);
|
||||
}
|
||||
// disable regular version of this method
|
||||
::grpc::Status Store(::grpc::ServerContext* context, const flatbuffers::grpc::Message<Monster>* request, flatbuffers::grpc::Message<Stat>* response) final override {
|
||||
abort();
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
// replace default version of method with streamed unary
|
||||
virtual ::grpc::Status StreamedStore(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< flatbuffers::grpc::Message<Monster>,flatbuffers::grpc::Message<Stat>>* server_unary_streamer) = 0;
|
||||
};
|
||||
typedef WithStreamedUnaryMethod_Store< Service > StreamedUnaryService;
|
||||
template <class BaseClass>
|
||||
class WithSplitStreamingMethod_Retrieve : public BaseClass {
|
||||
private:
|
||||
void BaseClassMustBeDerivedFromService(const Service *service) {}
|
||||
public:
|
||||
WithSplitStreamingMethod_Retrieve() {
|
||||
::grpc::Service::MarkMethodStreamed(1,
|
||||
new ::grpc::SplitServerStreamingHandler< flatbuffers::grpc::Message<Stat>, flatbuffers::grpc::Message<Monster>>(std::bind(&WithSplitStreamingMethod_Retrieve<BaseClass>::StreamedRetrieve, this, std::placeholders::_1, std::placeholders::_2)));
|
||||
}
|
||||
~WithSplitStreamingMethod_Retrieve() override {
|
||||
BaseClassMustBeDerivedFromService(this);
|
||||
}
|
||||
// disable regular version of this method
|
||||
::grpc::Status Retrieve(::grpc::ServerContext* context, const flatbuffers::grpc::Message<Stat>* request, ::grpc::ServerWriter< flatbuffers::grpc::Message<Monster>>* writer) final override {
|
||||
abort();
|
||||
return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "");
|
||||
}
|
||||
// replace default version of method with split streamed
|
||||
virtual ::grpc::Status StreamedRetrieve(::grpc::ServerContext* context, ::grpc::ServerSplitStreamer< flatbuffers::grpc::Message<Stat>,flatbuffers::grpc::Message<Monster>>* server_split_streamer) = 0;
|
||||
};
|
||||
typedef WithSplitStreamingMethod_Retrieve< Service > SplitStreamedService;
|
||||
typedef WithStreamedUnaryMethod_Store< WithSplitStreamingMethod_Retrieve< Service > > StreamedService;
|
||||
};
|
||||
|
||||
} // namespace Example
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#define FLATBUFFERS_GENERATED_MONSTERTEST_MYGAME_EXAMPLE_H_
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/flexbuffers.h"
|
||||
|
||||
namespace MyGame {
|
||||
namespace Example2 {
|
||||
@@ -23,6 +24,8 @@ struct TestSimpleTableWithEnumT;
|
||||
|
||||
struct Vec3;
|
||||
|
||||
struct Ability;
|
||||
|
||||
struct Stat;
|
||||
struct StatT;
|
||||
|
||||
@@ -37,6 +40,15 @@ enum Color {
|
||||
Color_ANY = 11
|
||||
};
|
||||
|
||||
inline Color (&EnumValuesColor())[3] {
|
||||
static Color values[] = {
|
||||
Color_Red,
|
||||
Color_Green,
|
||||
Color_Blue
|
||||
};
|
||||
return values;
|
||||
}
|
||||
|
||||
inline const char **EnumNamesColor() {
|
||||
static const char *names[] = {
|
||||
"Red",
|
||||
@@ -66,6 +78,16 @@ enum Any {
|
||||
Any_MAX = Any_MyGame_Example2_Monster
|
||||
};
|
||||
|
||||
inline Any (&EnumValuesAny())[4] {
|
||||
static Any values[] = {
|
||||
Any_NONE,
|
||||
Any_Monster,
|
||||
Any_TestSimpleTableWithEnum,
|
||||
Any_MyGame_Example2_Monster
|
||||
};
|
||||
return values;
|
||||
}
|
||||
|
||||
inline const char **EnumNamesAny() {
|
||||
static const char *names[] = {
|
||||
"NONE",
|
||||
@@ -100,40 +122,44 @@ template<> struct AnyTraits<MyGame::Example2::Monster> {
|
||||
|
||||
struct AnyUnion {
|
||||
Any type;
|
||||
flatbuffers::NativeTable *table;
|
||||
void *value;
|
||||
|
||||
AnyUnion() : type(Any_NONE), table(nullptr) {}
|
||||
AnyUnion(AnyUnion&& u):
|
||||
type(std::move(u.type)), table(std::move(u.table)) {}
|
||||
AnyUnion(const AnyUnion &);
|
||||
AnyUnion &operator=(const AnyUnion &);
|
||||
AnyUnion() : type(Any_NONE), value(nullptr) {}
|
||||
AnyUnion(AnyUnion&& u) FLATBUFFERS_NOEXCEPT :
|
||||
type(Any_NONE), value(nullptr)
|
||||
{ std::swap(type, u.type); std::swap(value, u.value); }
|
||||
AnyUnion(const AnyUnion &) FLATBUFFERS_NOEXCEPT;
|
||||
AnyUnion &operator=(const AnyUnion &u) FLATBUFFERS_NOEXCEPT
|
||||
{ AnyUnion t(u); std::swap(type, t.type); std::swap(value, t.value); return *this; }
|
||||
AnyUnion &operator=(AnyUnion &&u) FLATBUFFERS_NOEXCEPT
|
||||
{ std::swap(type, u.type); std::swap(value, u.value); return *this; }
|
||||
~AnyUnion() { Reset(); }
|
||||
|
||||
void Reset();
|
||||
|
||||
template <typename T>
|
||||
void Set(T&& value) {
|
||||
void Set(T&& val) {
|
||||
Reset();
|
||||
type = AnyTraits<typename T::TableType>::enum_value;
|
||||
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;
|
||||
|
||||
MonsterT *AsMonster() {
|
||||
return type == Any_Monster ?
|
||||
reinterpret_cast<MonsterT *>(table) : nullptr;
|
||||
reinterpret_cast<MonsterT *>(value) : nullptr;
|
||||
}
|
||||
TestSimpleTableWithEnumT *AsTestSimpleTableWithEnum() {
|
||||
return type == Any_TestSimpleTableWithEnum ?
|
||||
reinterpret_cast<TestSimpleTableWithEnumT *>(table) : nullptr;
|
||||
reinterpret_cast<TestSimpleTableWithEnumT *>(value) : nullptr;
|
||||
}
|
||||
MyGame::Example2::MonsterT *AsMyGame_Example2_Monster() {
|
||||
return type == Any_MyGame_Example2_Monster ?
|
||||
reinterpret_cast<MyGame::Example2::MonsterT *>(table) : nullptr;
|
||||
reinterpret_cast<MyGame::Example2::MonsterT *>(value) : nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -240,12 +266,50 @@ MANUALLY_ALIGNED_STRUCT(16) Vec3 FLATBUFFERS_FINAL_CLASS {
|
||||
const Test &test3() const {
|
||||
return test3_;
|
||||
}
|
||||
const Test &mutable_test3() {
|
||||
Test &mutable_test3() {
|
||||
return test3_;
|
||||
}
|
||||
};
|
||||
STRUCT_END(Vec3, 32);
|
||||
|
||||
MANUALLY_ALIGNED_STRUCT(4) Ability FLATBUFFERS_FINAL_CLASS {
|
||||
private:
|
||||
uint32_t id_;
|
||||
uint32_t distance_;
|
||||
|
||||
public:
|
||||
Ability() {
|
||||
memset(this, 0, sizeof(Ability));
|
||||
}
|
||||
Ability(const Ability &_o) {
|
||||
memcpy(this, &_o, sizeof(Ability));
|
||||
}
|
||||
Ability(uint32_t _id, uint32_t _distance)
|
||||
: id_(flatbuffers::EndianScalar(_id)),
|
||||
distance_(flatbuffers::EndianScalar(_distance)) {
|
||||
}
|
||||
uint32_t id() const {
|
||||
return flatbuffers::EndianScalar(id_);
|
||||
}
|
||||
void mutate_id(uint32_t _id) {
|
||||
flatbuffers::WriteScalar(&id_, _id);
|
||||
}
|
||||
bool KeyCompareLessThan(const Ability *o) const {
|
||||
return id() < o->id();
|
||||
}
|
||||
int KeyCompareWithValue(uint32_t val) const {
|
||||
const auto key = id();
|
||||
return static_cast<int>(key > val) - static_cast<int>(key < val);
|
||||
}
|
||||
uint32_t distance() const {
|
||||
return flatbuffers::EndianScalar(distance_);
|
||||
}
|
||||
void mutate_distance(uint32_t _distance) {
|
||||
flatbuffers::WriteScalar(&distance_, _distance);
|
||||
}
|
||||
};
|
||||
STRUCT_END(Ability, 8);
|
||||
|
||||
} // namespace Example
|
||||
|
||||
namespace Example2 {
|
||||
@@ -311,7 +375,7 @@ struct TestSimpleTableWithEnum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Ta
|
||||
return static_cast<Color>(GetField<int8_t>(VT_COLOR, 2));
|
||||
}
|
||||
bool mutate_color(Color _color) {
|
||||
return SetField(VT_COLOR, static_cast<int8_t>(_color));
|
||||
return SetField<int8_t>(VT_COLOR, static_cast<int8_t>(_color), 2);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
@@ -379,17 +443,17 @@ struct Stat FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
return GetField<int64_t>(VT_VAL, 0);
|
||||
}
|
||||
bool mutate_val(int64_t _val) {
|
||||
return SetField(VT_VAL, _val);
|
||||
return SetField<int64_t>(VT_VAL, _val, 0);
|
||||
}
|
||||
uint16_t count() const {
|
||||
return GetField<uint16_t>(VT_COUNT, 0);
|
||||
}
|
||||
bool mutate_count(uint16_t _count) {
|
||||
return SetField(VT_COUNT, _count);
|
||||
return SetField<uint16_t>(VT_COUNT, _count, 0);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_ID) &&
|
||||
VerifyOffset(verifier, VT_ID) &&
|
||||
verifier.Verify(id()) &&
|
||||
VerifyField<int64_t>(verifier, VT_VAL) &&
|
||||
VerifyField<uint16_t>(verifier, VT_COUNT) &&
|
||||
@@ -479,6 +543,8 @@ struct MonsterT : public flatbuffers::NativeTable {
|
||||
float testf2;
|
||||
float testf3;
|
||||
std::vector<std::string> testarrayofstring2;
|
||||
std::vector<Ability> testarrayofsortedstruct;
|
||||
std::vector<uint8_t> flex;
|
||||
MonsterT()
|
||||
: mana(150),
|
||||
hp(100),
|
||||
@@ -529,7 +595,9 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VT_TESTF = 54,
|
||||
VT_TESTF2 = 56,
|
||||
VT_TESTF3 = 58,
|
||||
VT_TESTARRAYOFSTRING2 = 60
|
||||
VT_TESTARRAYOFSTRING2 = 60,
|
||||
VT_TESTARRAYOFSORTEDSTRUCT = 62,
|
||||
VT_FLEX = 64
|
||||
};
|
||||
const Vec3 *pos() const {
|
||||
return GetStruct<const Vec3 *>(VT_POS);
|
||||
@@ -541,13 +609,13 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
return GetField<int16_t>(VT_MANA, 150);
|
||||
}
|
||||
bool mutate_mana(int16_t _mana) {
|
||||
return SetField(VT_MANA, _mana);
|
||||
return SetField<int16_t>(VT_MANA, _mana, 150);
|
||||
}
|
||||
int16_t hp() const {
|
||||
return GetField<int16_t>(VT_HP, 100);
|
||||
}
|
||||
bool mutate_hp(int16_t _hp) {
|
||||
return SetField(VT_HP, _hp);
|
||||
return SetField<int16_t>(VT_HP, _hp, 100);
|
||||
}
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
@@ -571,17 +639,27 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
return static_cast<Color>(GetField<int8_t>(VT_COLOR, 8));
|
||||
}
|
||||
bool mutate_color(Color _color) {
|
||||
return SetField(VT_COLOR, static_cast<int8_t>(_color));
|
||||
return SetField<int8_t>(VT_COLOR, static_cast<int8_t>(_color), 8);
|
||||
}
|
||||
Any test_type() const {
|
||||
return static_cast<Any>(GetField<uint8_t>(VT_TEST_TYPE, 0));
|
||||
}
|
||||
bool mutate_test_type(Any _test_type) {
|
||||
return SetField(VT_TEST_TYPE, static_cast<uint8_t>(_test_type));
|
||||
return SetField<uint8_t>(VT_TEST_TYPE, static_cast<uint8_t>(_test_type), 0);
|
||||
}
|
||||
const void *test() const {
|
||||
return GetPointer<const void *>(VT_TEST);
|
||||
}
|
||||
template<typename T> const T *test_as() const;
|
||||
const Monster *test_as_Monster() const {
|
||||
return test_type() == Any_Monster ? static_cast<const Monster *>(test()) : nullptr;
|
||||
}
|
||||
const TestSimpleTableWithEnum *test_as_TestSimpleTableWithEnum() const {
|
||||
return test_type() == Any_TestSimpleTableWithEnum ? static_cast<const TestSimpleTableWithEnum *>(test()) : nullptr;
|
||||
}
|
||||
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;
|
||||
}
|
||||
void *mutable_test() {
|
||||
return GetPointer<void *>(VT_TEST);
|
||||
}
|
||||
@@ -618,7 +696,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
return GetPointer<flatbuffers::Vector<uint8_t> *>(VT_TESTNESTEDFLATBUFFER);
|
||||
}
|
||||
const MyGame::Example::Monster *testnestedflatbuffer_nested_root() const {
|
||||
const uint8_t* data = testnestedflatbuffer()->Data();
|
||||
auto data = testnestedflatbuffer()->Data();
|
||||
return flatbuffers::GetRoot<MyGame::Example::Monster>(data);
|
||||
}
|
||||
const Stat *testempty() const {
|
||||
@@ -631,55 +709,55 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
return GetField<uint8_t>(VT_TESTBOOL, 0) != 0;
|
||||
}
|
||||
bool mutate_testbool(bool _testbool) {
|
||||
return SetField(VT_TESTBOOL, static_cast<uint8_t>(_testbool));
|
||||
return SetField<uint8_t>(VT_TESTBOOL, static_cast<uint8_t>(_testbool), 0);
|
||||
}
|
||||
int32_t testhashs32_fnv1() const {
|
||||
return GetField<int32_t>(VT_TESTHASHS32_FNV1, 0);
|
||||
}
|
||||
bool mutate_testhashs32_fnv1(int32_t _testhashs32_fnv1) {
|
||||
return SetField(VT_TESTHASHS32_FNV1, _testhashs32_fnv1);
|
||||
return SetField<int32_t>(VT_TESTHASHS32_FNV1, _testhashs32_fnv1, 0);
|
||||
}
|
||||
uint32_t testhashu32_fnv1() const {
|
||||
return GetField<uint32_t>(VT_TESTHASHU32_FNV1, 0);
|
||||
}
|
||||
bool mutate_testhashu32_fnv1(uint32_t _testhashu32_fnv1) {
|
||||
return SetField(VT_TESTHASHU32_FNV1, _testhashu32_fnv1);
|
||||
return SetField<uint32_t>(VT_TESTHASHU32_FNV1, _testhashu32_fnv1, 0);
|
||||
}
|
||||
int64_t testhashs64_fnv1() const {
|
||||
return GetField<int64_t>(VT_TESTHASHS64_FNV1, 0);
|
||||
}
|
||||
bool mutate_testhashs64_fnv1(int64_t _testhashs64_fnv1) {
|
||||
return SetField(VT_TESTHASHS64_FNV1, _testhashs64_fnv1);
|
||||
return SetField<int64_t>(VT_TESTHASHS64_FNV1, _testhashs64_fnv1, 0);
|
||||
}
|
||||
uint64_t testhashu64_fnv1() const {
|
||||
return GetField<uint64_t>(VT_TESTHASHU64_FNV1, 0);
|
||||
}
|
||||
bool mutate_testhashu64_fnv1(uint64_t _testhashu64_fnv1) {
|
||||
return SetField(VT_TESTHASHU64_FNV1, _testhashu64_fnv1);
|
||||
return SetField<uint64_t>(VT_TESTHASHU64_FNV1, _testhashu64_fnv1, 0);
|
||||
}
|
||||
int32_t testhashs32_fnv1a() const {
|
||||
return GetField<int32_t>(VT_TESTHASHS32_FNV1A, 0);
|
||||
}
|
||||
bool mutate_testhashs32_fnv1a(int32_t _testhashs32_fnv1a) {
|
||||
return SetField(VT_TESTHASHS32_FNV1A, _testhashs32_fnv1a);
|
||||
return SetField<int32_t>(VT_TESTHASHS32_FNV1A, _testhashs32_fnv1a, 0);
|
||||
}
|
||||
uint32_t testhashu32_fnv1a() const {
|
||||
return GetField<uint32_t>(VT_TESTHASHU32_FNV1A, 0);
|
||||
}
|
||||
bool mutate_testhashu32_fnv1a(uint32_t _testhashu32_fnv1a) {
|
||||
return SetField(VT_TESTHASHU32_FNV1A, _testhashu32_fnv1a);
|
||||
return SetField<uint32_t>(VT_TESTHASHU32_FNV1A, _testhashu32_fnv1a, 0);
|
||||
}
|
||||
int64_t testhashs64_fnv1a() const {
|
||||
return GetField<int64_t>(VT_TESTHASHS64_FNV1A, 0);
|
||||
}
|
||||
bool mutate_testhashs64_fnv1a(int64_t _testhashs64_fnv1a) {
|
||||
return SetField(VT_TESTHASHS64_FNV1A, _testhashs64_fnv1a);
|
||||
return SetField<int64_t>(VT_TESTHASHS64_FNV1A, _testhashs64_fnv1a, 0);
|
||||
}
|
||||
uint64_t testhashu64_fnv1a() const {
|
||||
return GetField<uint64_t>(VT_TESTHASHU64_FNV1A, 0);
|
||||
}
|
||||
bool mutate_testhashu64_fnv1a(uint64_t _testhashu64_fnv1a) {
|
||||
return SetField(VT_TESTHASHU64_FNV1A, _testhashu64_fnv1a);
|
||||
return SetField<uint64_t>(VT_TESTHASHU64_FNV1A, _testhashu64_fnv1a, 0);
|
||||
}
|
||||
const flatbuffers::Vector<uint8_t> *testarrayofbools() const {
|
||||
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_TESTARRAYOFBOOLS);
|
||||
@@ -691,19 +769,19 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
return GetField<float>(VT_TESTF, 3.14159f);
|
||||
}
|
||||
bool mutate_testf(float _testf) {
|
||||
return SetField(VT_TESTF, _testf);
|
||||
return SetField<float>(VT_TESTF, _testf, 3.14159f);
|
||||
}
|
||||
float testf2() const {
|
||||
return GetField<float>(VT_TESTF2, 3.0f);
|
||||
}
|
||||
bool mutate_testf2(float _testf2) {
|
||||
return SetField(VT_TESTF2, _testf2);
|
||||
return SetField<float>(VT_TESTF2, _testf2, 3.0f);
|
||||
}
|
||||
float testf3() const {
|
||||
return GetField<float>(VT_TESTF3, 0.0f);
|
||||
}
|
||||
bool mutate_testf3(float _testf3) {
|
||||
return SetField(VT_TESTF3, _testf3);
|
||||
return SetField<float>(VT_TESTF3, _testf3, 0.0f);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *testarrayofstring2() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_TESTARRAYOFSTRING2);
|
||||
@@ -711,32 +789,48 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *mutable_testarrayofstring2() {
|
||||
return GetPointer<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_TESTARRAYOFSTRING2);
|
||||
}
|
||||
const flatbuffers::Vector<const Ability *> *testarrayofsortedstruct() const {
|
||||
return GetPointer<const flatbuffers::Vector<const Ability *> *>(VT_TESTARRAYOFSORTEDSTRUCT);
|
||||
}
|
||||
flatbuffers::Vector<const Ability *> *mutable_testarrayofsortedstruct() {
|
||||
return GetPointer<flatbuffers::Vector<const Ability *> *>(VT_TESTARRAYOFSORTEDSTRUCT);
|
||||
}
|
||||
const flatbuffers::Vector<uint8_t> *flex() const {
|
||||
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_FLEX);
|
||||
}
|
||||
flatbuffers::Vector<uint8_t> *mutable_flex() {
|
||||
return GetPointer<flatbuffers::Vector<uint8_t> *>(VT_FLEX);
|
||||
}
|
||||
flexbuffers::Reference flex_flexbuffer_root() const {
|
||||
auto v = flex();
|
||||
return flexbuffers::GetRoot(v->Data(), v->size());
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<Vec3>(verifier, VT_POS) &&
|
||||
VerifyField<int16_t>(verifier, VT_MANA) &&
|
||||
VerifyField<int16_t>(verifier, VT_HP) &&
|
||||
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
|
||||
VerifyOffsetRequired(verifier, VT_NAME) &&
|
||||
verifier.Verify(name()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_INVENTORY) &&
|
||||
VerifyOffset(verifier, VT_INVENTORY) &&
|
||||
verifier.Verify(inventory()) &&
|
||||
VerifyField<int8_t>(verifier, VT_COLOR) &&
|
||||
VerifyField<uint8_t>(verifier, VT_TEST_TYPE) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_TEST) &&
|
||||
VerifyOffset(verifier, VT_TEST) &&
|
||||
VerifyAny(verifier, test(), test_type()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_TEST4) &&
|
||||
VerifyOffset(verifier, VT_TEST4) &&
|
||||
verifier.Verify(test4()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_TESTARRAYOFSTRING) &&
|
||||
VerifyOffset(verifier, VT_TESTARRAYOFSTRING) &&
|
||||
verifier.Verify(testarrayofstring()) &&
|
||||
verifier.VerifyVectorOfStrings(testarrayofstring()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_TESTARRAYOFTABLES) &&
|
||||
VerifyOffset(verifier, VT_TESTARRAYOFTABLES) &&
|
||||
verifier.Verify(testarrayoftables()) &&
|
||||
verifier.VerifyVectorOfTables(testarrayoftables()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_ENEMY) &&
|
||||
VerifyOffset(verifier, VT_ENEMY) &&
|
||||
verifier.VerifyTable(enemy()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_TESTNESTEDFLATBUFFER) &&
|
||||
VerifyOffset(verifier, VT_TESTNESTEDFLATBUFFER) &&
|
||||
verifier.Verify(testnestedflatbuffer()) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_TESTEMPTY) &&
|
||||
VerifyOffset(verifier, VT_TESTEMPTY) &&
|
||||
verifier.VerifyTable(testempty()) &&
|
||||
VerifyField<uint8_t>(verifier, VT_TESTBOOL) &&
|
||||
VerifyField<int32_t>(verifier, VT_TESTHASHS32_FNV1) &&
|
||||
@@ -747,14 +841,18 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VerifyField<uint32_t>(verifier, VT_TESTHASHU32_FNV1A) &&
|
||||
VerifyField<int64_t>(verifier, VT_TESTHASHS64_FNV1A) &&
|
||||
VerifyField<uint64_t>(verifier, VT_TESTHASHU64_FNV1A) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_TESTARRAYOFBOOLS) &&
|
||||
VerifyOffset(verifier, VT_TESTARRAYOFBOOLS) &&
|
||||
verifier.Verify(testarrayofbools()) &&
|
||||
VerifyField<float>(verifier, VT_TESTF) &&
|
||||
VerifyField<float>(verifier, VT_TESTF2) &&
|
||||
VerifyField<float>(verifier, VT_TESTF3) &&
|
||||
VerifyField<flatbuffers::uoffset_t>(verifier, VT_TESTARRAYOFSTRING2) &&
|
||||
VerifyOffset(verifier, VT_TESTARRAYOFSTRING2) &&
|
||||
verifier.Verify(testarrayofstring2()) &&
|
||||
verifier.VerifyVectorOfStrings(testarrayofstring2()) &&
|
||||
VerifyOffset(verifier, VT_TESTARRAYOFSORTEDSTRUCT) &&
|
||||
verifier.Verify(testarrayofsortedstruct()) &&
|
||||
VerifyOffset(verifier, VT_FLEX) &&
|
||||
verifier.Verify(flex()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
MonsterT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||
@@ -762,6 +860,18 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
static flatbuffers::Offset<Monster> Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||
};
|
||||
|
||||
template<> inline const Monster *Monster::test_as<Monster>() const {
|
||||
return test_as_Monster();
|
||||
}
|
||||
|
||||
template<> inline const TestSimpleTableWithEnum *Monster::test_as<TestSimpleTableWithEnum>() const {
|
||||
return test_as_TestSimpleTableWithEnum();
|
||||
}
|
||||
|
||||
template<> inline const MyGame::Example2::Monster *Monster::test_as<MyGame::Example2::Monster>() const {
|
||||
return test_as_MyGame_Example2_Monster();
|
||||
}
|
||||
|
||||
struct MonsterBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
@@ -849,13 +959,19 @@ struct MonsterBuilder {
|
||||
void add_testarrayofstring2(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> testarrayofstring2) {
|
||||
fbb_.AddOffset(Monster::VT_TESTARRAYOFSTRING2, testarrayofstring2);
|
||||
}
|
||||
void add_testarrayofsortedstruct(flatbuffers::Offset<flatbuffers::Vector<const Ability *>> testarrayofsortedstruct) {
|
||||
fbb_.AddOffset(Monster::VT_TESTARRAYOFSORTEDSTRUCT, testarrayofsortedstruct);
|
||||
}
|
||||
void add_flex(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> flex) {
|
||||
fbb_.AddOffset(Monster::VT_FLEX, flex);
|
||||
}
|
||||
MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
MonsterBuilder &operator=(const MonsterBuilder &);
|
||||
flatbuffers::Offset<Monster> Finish() {
|
||||
const auto end = fbb_.EndTable(start_, 29);
|
||||
const auto end = fbb_.EndTable(start_, 31);
|
||||
auto o = flatbuffers::Offset<Monster>(end);
|
||||
fbb_.Required(o, Monster::VT_NAME);
|
||||
return o;
|
||||
@@ -891,12 +1007,16 @@ inline flatbuffers::Offset<Monster> CreateMonster(
|
||||
float testf = 3.14159f,
|
||||
float testf2 = 3.0f,
|
||||
float testf3 = 0.0f,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> testarrayofstring2 = 0) {
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> testarrayofstring2 = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<const Ability *>> testarrayofsortedstruct = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> flex = 0) {
|
||||
MonsterBuilder builder_(_fbb);
|
||||
builder_.add_testhashu64_fnv1a(testhashu64_fnv1a);
|
||||
builder_.add_testhashs64_fnv1a(testhashs64_fnv1a);
|
||||
builder_.add_testhashu64_fnv1(testhashu64_fnv1);
|
||||
builder_.add_testhashs64_fnv1(testhashs64_fnv1);
|
||||
builder_.add_flex(flex);
|
||||
builder_.add_testarrayofsortedstruct(testarrayofsortedstruct);
|
||||
builder_.add_testarrayofstring2(testarrayofstring2);
|
||||
builder_.add_testf3(testf3);
|
||||
builder_.add_testf2(testf2);
|
||||
@@ -953,7 +1073,9 @@ inline flatbuffers::Offset<Monster> CreateMonsterDirect(
|
||||
float testf = 3.14159f,
|
||||
float testf2 = 3.0f,
|
||||
float testf3 = 0.0f,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *testarrayofstring2 = nullptr) {
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *testarrayofstring2 = nullptr,
|
||||
const std::vector<const Ability *> *testarrayofsortedstruct = nullptr,
|
||||
const std::vector<uint8_t> *flex = nullptr) {
|
||||
return MyGame::Example::CreateMonster(
|
||||
_fbb,
|
||||
pos,
|
||||
@@ -983,7 +1105,9 @@ inline flatbuffers::Offset<Monster> CreateMonsterDirect(
|
||||
testf,
|
||||
testf2,
|
||||
testf3,
|
||||
testarrayofstring2 ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*testarrayofstring2) : 0);
|
||||
testarrayofstring2 ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*testarrayofstring2) : 0,
|
||||
testarrayofsortedstruct ? _fbb.CreateVector<const Ability *>(*testarrayofsortedstruct) : 0,
|
||||
flex ? _fbb.CreateVector<uint8_t>(*flex) : 0);
|
||||
}
|
||||
|
||||
flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||
@@ -1087,15 +1211,15 @@ inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function
|
||||
{ auto _e = mana(); _o->mana = _e; };
|
||||
{ auto _e = hp(); _o->hp = _e; };
|
||||
{ auto _e = name(); if (_e) _o->name = _e->str(); };
|
||||
{ auto _e = inventory(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inventory.push_back(_e->Get(_i)); } };
|
||||
{ auto _e = 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 = test_type(); _o->test.type = _e; };
|
||||
{ auto _e = test(); if (_e) _o->test.table = AnyUnion::UnPack(_e, test_type(),_resolver); };
|
||||
{ auto _e = test4(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->test4.push_back(*_e->Get(_i)); } };
|
||||
{ auto _e = testarrayofstring(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofstring.push_back(_e->Get(_i)->str()); } };
|
||||
{ auto _e = testarrayoftables(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayoftables.push_back(std::unique_ptr<MonsterT>(_e->Get(_i)->UnPack(_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 = 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 = enemy(); if (_e) _o->enemy = std::unique_ptr<MonsterT>(_e->UnPack(_resolver)); };
|
||||
{ auto _e = testnestedflatbuffer(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testnestedflatbuffer.push_back(_e->Get(_i)); } };
|
||||
{ auto _e = testnestedflatbuffer(); if (_e) { _o->testnestedflatbuffer.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testnestedflatbuffer[_i] = _e->Get(_i); } } };
|
||||
{ auto _e = testempty(); if (_e) _o->testempty = std::unique_ptr<StatT>(_e->UnPack(_resolver)); };
|
||||
{ auto _e = testbool(); _o->testbool = _e; };
|
||||
{ auto _e = testhashs32_fnv1(); _o->testhashs32_fnv1 = _e; };
|
||||
@@ -1106,11 +1230,13 @@ inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function
|
||||
{ auto _e = testhashu32_fnv1a(); if (_resolver) (*_resolver)(reinterpret_cast<void **>(&_o->testhashu32_fnv1a), static_cast<flatbuffers::hash_value_t>(_e)); else _o->testhashu32_fnv1a = nullptr; };
|
||||
{ auto _e = testhashs64_fnv1a(); _o->testhashs64_fnv1a = _e; };
|
||||
{ auto _e = testhashu64_fnv1a(); _o->testhashu64_fnv1a = _e; };
|
||||
{ auto _e = testarrayofbools(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofbools.push_back(_e->Get(_i) != 0); } };
|
||||
{ auto _e = testarrayofbools(); if (_e) { _o->testarrayofbools.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofbools[_i] = _e->Get(_i) != 0; } } };
|
||||
{ auto _e = testf(); _o->testf = _e; };
|
||||
{ auto _e = testf2(); _o->testf2 = _e; };
|
||||
{ auto _e = testf3(); _o->testf3 = _e; };
|
||||
{ auto _e = testarrayofstring2(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofstring2.push_back(_e->Get(_i)->str()); } };
|
||||
{ auto _e = testarrayofstring2(); if (_e) { _o->testarrayofstring2.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofstring2[_i] = _e->Get(_i)->str(); } } };
|
||||
{ auto _e = testarrayofsortedstruct(); if (_e) { _o->testarrayofsortedstruct.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->testarrayofsortedstruct[_i] = *_e->Get(_i); } } };
|
||||
{ auto _e = flex(); if (_e) { _o->flex.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->flex[_i] = _e->Get(_i); } } };
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> Monster::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
|
||||
@@ -1148,6 +1274,8 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder
|
||||
auto _testf2 = _o->testf2;
|
||||
auto _testf3 = _o->testf3;
|
||||
auto _testarrayofstring2 = _o->testarrayofstring2.size() ? _fbb.CreateVectorOfStrings(_o->testarrayofstring2) : 0;
|
||||
auto _testarrayofsortedstruct = _o->testarrayofsortedstruct.size() ? _fbb.CreateVectorOfStructs(_o->testarrayofsortedstruct) : 0;
|
||||
auto _flex = _o->flex.size() ? _fbb.CreateVector(_o->flex) : 0;
|
||||
return MyGame::Example::CreateMonster(
|
||||
_fbb,
|
||||
_pos,
|
||||
@@ -1177,7 +1305,9 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder
|
||||
_testf,
|
||||
_testf2,
|
||||
_testf3,
|
||||
_testarrayofstring2);
|
||||
_testarrayofstring2,
|
||||
_testarrayofsortedstruct,
|
||||
_flex);
|
||||
}
|
||||
|
||||
inline bool VerifyAny(flatbuffers::Verifier &verifier, const void *obj, Any type) {
|
||||
@@ -1212,7 +1342,7 @@ inline bool VerifyAnyVector(flatbuffers::Verifier &verifier, const flatbuffers::
|
||||
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) {
|
||||
case Any_Monster: {
|
||||
auto ptr = reinterpret_cast<const Monster *>(obj);
|
||||
@@ -1233,41 +1363,60 @@ 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 {
|
||||
switch (type) {
|
||||
case Any_Monster: {
|
||||
auto ptr = reinterpret_cast<const MonsterT *>(table);
|
||||
auto ptr = reinterpret_cast<const MonsterT *>(value);
|
||||
return CreateMonster(_fbb, ptr, _rehasher).Union();
|
||||
}
|
||||
case Any_TestSimpleTableWithEnum: {
|
||||
auto ptr = reinterpret_cast<const TestSimpleTableWithEnumT *>(table);
|
||||
auto ptr = reinterpret_cast<const TestSimpleTableWithEnumT *>(value);
|
||||
return CreateTestSimpleTableWithEnum(_fbb, ptr, _rehasher).Union();
|
||||
}
|
||||
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();
|
||||
}
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
inline AnyUnion::AnyUnion(const AnyUnion &u) FLATBUFFERS_NOEXCEPT : type(u.type), value(nullptr) {
|
||||
switch (type) {
|
||||
case Any_Monster: {
|
||||
assert(false); // MonsterT not copyable.
|
||||
break;
|
||||
}
|
||||
case Any_TestSimpleTableWithEnum: {
|
||||
value = new TestSimpleTableWithEnumT(*reinterpret_cast<TestSimpleTableWithEnumT *>(u.value));
|
||||
break;
|
||||
}
|
||||
case Any_MyGame_Example2_Monster: {
|
||||
value = new MyGame::Example2::MonsterT(*reinterpret_cast<MyGame::Example2::MonsterT *>(u.value));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline void AnyUnion::Reset() {
|
||||
switch (type) {
|
||||
case Any_Monster: {
|
||||
auto ptr = reinterpret_cast<MonsterT *>(table);
|
||||
auto ptr = reinterpret_cast<MonsterT *>(value);
|
||||
delete ptr;
|
||||
break;
|
||||
}
|
||||
case Any_TestSimpleTableWithEnum: {
|
||||
auto ptr = reinterpret_cast<TestSimpleTableWithEnumT *>(table);
|
||||
auto ptr = reinterpret_cast<TestSimpleTableWithEnumT *>(value);
|
||||
delete ptr;
|
||||
break;
|
||||
}
|
||||
case Any_MyGame_Example2_Monster: {
|
||||
auto ptr = reinterpret_cast<MyGame::Example2::MonsterT *>(table);
|
||||
auto ptr = reinterpret_cast<MyGame::Example2::MonsterT *>(value);
|
||||
delete ptr;
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
table = nullptr;
|
||||
value = nullptr;
|
||||
type = Any_NONE;
|
||||
}
|
||||
|
||||
|
||||
@@ -398,7 +398,7 @@ MyGame.Example.Vec3.prototype.mutate_test2 = function(value) {
|
||||
|
||||
/**
|
||||
* @param {MyGame.Example.Test=} obj
|
||||
* @returns {MyGame.Example.Test}
|
||||
* @returns {MyGame.Example.Test|null}
|
||||
*/
|
||||
MyGame.Example.Vec3.prototype.test3 = function(obj) {
|
||||
return (obj || new MyGame.Example.Test).__init(this.bb_pos + 26, this.bb);
|
||||
@@ -432,6 +432,89 @@ MyGame.Example.Vec3.createVec3 = function(builder, x, y, z, test1, test2, test3_
|
||||
return builder.offset();
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
MyGame.Example.Ability = function() {
|
||||
/**
|
||||
* @type {flatbuffers.ByteBuffer}
|
||||
*/
|
||||
this.bb = null;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
*/
|
||||
this.bb_pos = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} i
|
||||
* @param {flatbuffers.ByteBuffer} bb
|
||||
* @returns {MyGame.Example.Ability}
|
||||
*/
|
||||
MyGame.Example.Ability.prototype.__init = function(i, bb) {
|
||||
this.bb_pos = i;
|
||||
this.bb = bb;
|
||||
return this;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Ability.prototype.id = function() {
|
||||
return this.bb.readUint32(this.bb_pos);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} value
|
||||
* @returns {boolean}
|
||||
*/
|
||||
MyGame.Example.Ability.prototype.mutate_id = function(value) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 0);
|
||||
|
||||
if (offset === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.bb.writeUint32(this.bb_pos + offset, value);
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Ability.prototype.distance = function() {
|
||||
return this.bb.readUint32(this.bb_pos + 4);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} value
|
||||
* @returns {boolean}
|
||||
*/
|
||||
MyGame.Example.Ability.prototype.mutate_distance = function(value) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 4);
|
||||
|
||||
if (offset === 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.bb.writeUint32(this.bb_pos + offset, value);
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} id
|
||||
* @param {number} distance
|
||||
* @returns {flatbuffers.Offset}
|
||||
*/
|
||||
MyGame.Example.Ability.createAbility = function(builder, id, distance) {
|
||||
builder.prep(4, 8);
|
||||
builder.writeInt32(distance);
|
||||
builder.writeInt32(id);
|
||||
return builder.offset();
|
||||
};
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
@@ -469,7 +552,7 @@ MyGame.Example.Stat.getRootAsStat = function(bb, obj) {
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Encoding=} optionalEncoding
|
||||
* @returns {string|Uint8Array}
|
||||
* @returns {string|Uint8Array|null}
|
||||
*/
|
||||
MyGame.Example.Stat.prototype.id = function(optionalEncoding) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 4);
|
||||
@@ -609,7 +692,7 @@ MyGame.Example.Monster.bufferHasIdentifier = function(bb) {
|
||||
|
||||
/**
|
||||
* @param {MyGame.Example.Vec3=} obj
|
||||
* @returns {MyGame.Example.Vec3}
|
||||
* @returns {MyGame.Example.Vec3|null}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.pos = function(obj) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 4);
|
||||
@@ -664,7 +747,7 @@ MyGame.Example.Monster.prototype.mutate_hp = function(value) {
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Encoding=} optionalEncoding
|
||||
* @returns {string|Uint8Array}
|
||||
* @returns {string|Uint8Array|null}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.name = function(optionalEncoding) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 10);
|
||||
@@ -810,7 +893,7 @@ MyGame.Example.Monster.prototype.testarrayoftablesLength = function() {
|
||||
|
||||
/**
|
||||
* @param {MyGame.Example.Monster=} obj
|
||||
* @returns {MyGame.Example.Monster}
|
||||
* @returns {MyGame.Example.Monster|null}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.enemy = function(obj) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 28);
|
||||
@@ -844,7 +927,7 @@ MyGame.Example.Monster.prototype.testnestedflatbufferArray = function() {
|
||||
|
||||
/**
|
||||
* @param {MyGame.Example.Stat=} obj
|
||||
* @returns {MyGame.Example.Stat}
|
||||
* @returns {MyGame.Example.Stat|null}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testempty = function(obj) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 32);
|
||||
@@ -1170,11 +1253,54 @@ MyGame.Example.Monster.prototype.testarrayofstring2Length = function() {
|
||||
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} index
|
||||
* @param {MyGame.Example.Ability=} obj
|
||||
* @returns {MyGame.Example.Ability}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testarrayofsortedstruct = function(index, obj) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 62);
|
||||
return offset ? (obj || new MyGame.Example.Ability).__init(this.bb.__vector(this.bb_pos + offset) + index * 8, this.bb) : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.testarrayofsortedstructLength = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 62);
|
||||
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} index
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.flex = function(index) {
|
||||
var offset = this.bb.__offset(this.bb_pos, 64);
|
||||
return offset ? this.bb.readUint8(this.bb.__vector(this.bb_pos + offset) + index) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {number}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.flexLength = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 64);
|
||||
return offset ? this.bb.__vector_len(this.bb_pos + offset) : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {Uint8Array}
|
||||
*/
|
||||
MyGame.Example.Monster.prototype.flexArray = function() {
|
||||
var offset = this.bb.__offset(this.bb_pos, 64);
|
||||
return offset ? new Uint8Array(this.bb.bytes().buffer, this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), this.bb.__vector_len(this.bb_pos + offset)) : null;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
*/
|
||||
MyGame.Example.Monster.startMonster = function(builder) {
|
||||
builder.startObject(29);
|
||||
builder.startObject(31);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -1535,6 +1661,51 @@ MyGame.Example.Monster.startTestarrayofstring2Vector = function(builder, numElem
|
||||
builder.startVector(4, numElems, 4);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Offset} testarrayofsortedstructOffset
|
||||
*/
|
||||
MyGame.Example.Monster.addTestarrayofsortedstruct = function(builder, testarrayofsortedstructOffset) {
|
||||
builder.addFieldOffset(29, testarrayofsortedstructOffset, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} numElems
|
||||
*/
|
||||
MyGame.Example.Monster.startTestarrayofsortedstructVector = function(builder, numElems) {
|
||||
builder.startVector(8, numElems, 4);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {flatbuffers.Offset} flexOffset
|
||||
*/
|
||||
MyGame.Example.Monster.addFlex = function(builder, flexOffset) {
|
||||
builder.addFieldOffset(30, flexOffset, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {Array.<number>} data
|
||||
* @returns {flatbuffers.Offset}
|
||||
*/
|
||||
MyGame.Example.Monster.createFlexVector = function(builder, data) {
|
||||
builder.startVector(1, data.length, 1);
|
||||
for (var i = data.length - 1; i >= 0; i--) {
|
||||
builder.addInt8(data[i]);
|
||||
}
|
||||
return builder.endVector();
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @param {number} numElems
|
||||
*/
|
||||
MyGame.Example.Monster.startFlexVector = function(builder, numElems) {
|
||||
builder.startVector(1, numElems, 1);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {flatbuffers.Builder} builder
|
||||
* @returns {flatbuffers.Offset}
|
||||
|
||||
1719
tests/monster_test_generated.ts
Normal file
1719
tests/monster_test_generated.ts
Normal file
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -1,13 +1,13 @@
|
||||
{
|
||||
pos: {
|
||||
x: 1,
|
||||
y: 2,
|
||||
z: 3,
|
||||
test1: 3,
|
||||
x: 1.0,
|
||||
y: 2.0,
|
||||
z: 3.0,
|
||||
test1: 3.0,
|
||||
test2: Green,
|
||||
test3: {
|
||||
a: 5,
|
||||
b: 6
|
||||
a: 10,
|
||||
b: 20
|
||||
}
|
||||
},
|
||||
hp: 80,
|
||||
@@ -17,7 +17,12 @@
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4
|
||||
4,
|
||||
5,
|
||||
6,
|
||||
7,
|
||||
8,
|
||||
9
|
||||
],
|
||||
test_type: Monster,
|
||||
test: {
|
||||
@@ -34,8 +39,22 @@
|
||||
}
|
||||
],
|
||||
testarrayofstring: [
|
||||
"test1",
|
||||
"test2"
|
||||
"bob",
|
||||
"fred",
|
||||
"bob",
|
||||
"fred"
|
||||
],
|
||||
testarrayoftables: [
|
||||
{
|
||||
hp: 1000,
|
||||
name: "Barney"
|
||||
},
|
||||
{
|
||||
name: "Fred"
|
||||
},
|
||||
{
|
||||
name: "Wilma"
|
||||
}
|
||||
],
|
||||
testhashs32_fnv1: -579221183,
|
||||
testhashu32_fnv1: 3715746113,
|
||||
@@ -44,5 +63,6 @@
|
||||
testhashs32_fnv1a: -1904106383,
|
||||
testhashu32_fnv1a: 2390860913,
|
||||
testhashs64_fnv1a: 4898026182817603057,
|
||||
testhashu64_fnv1a: 4898026182817603057
|
||||
testhashu64_fnv1a: 4898026182817603057,
|
||||
flex: 1234
|
||||
}
|
||||
|
||||
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user