mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-02 12:05:50 +00:00
Compare commits
247 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
34aea4361f | ||
|
|
be1ad33910 | ||
|
|
0cf04ad9d5 | ||
|
|
fe483fa380 | ||
|
|
8a8dc4e111 | ||
|
|
7e803c410c | ||
|
|
1336d26252 | ||
|
|
853f7033e0 | ||
|
|
e2c7196ea8 | ||
|
|
61fe2a4fac | ||
|
|
d233b38008 | ||
|
|
ca52bfefc0 | ||
|
|
2edb1dcdda | ||
|
|
6eb031de9a | ||
|
|
5f2af34e02 | ||
|
|
f3f113b24a | ||
|
|
6bb0a728d3 | ||
|
|
97face1527 | ||
|
|
f2627e16ac | ||
|
|
01bac38c84 | ||
|
|
a1b5f565d9 | ||
|
|
0780a7db24 | ||
|
|
9234ddcf11 | ||
|
|
6d9a226f75 | ||
|
|
b0fd1a8c66 | ||
|
|
a0e5d78353 | ||
|
|
bc8a1608a8 | ||
|
|
30e7d16104 | ||
|
|
9c3920d0ab | ||
|
|
5b4acf809e | ||
|
|
86fb05d320 | ||
|
|
5e4739184f | ||
|
|
971a68110e | ||
|
|
7a6b2bf521 | ||
|
|
03e2899985 | ||
|
|
72a99abfb7 | ||
|
|
21a8121982 | ||
|
|
28920aff8f | ||
|
|
77b22aed5a | ||
|
|
cc25516d3e | ||
|
|
1d444f63d3 | ||
|
|
5fa00630af | ||
|
|
97af3d798b | ||
|
|
bb736091f3 | ||
|
|
d5b4db0692 | ||
|
|
5808f7fb03 | ||
|
|
42611f9a83 | ||
|
|
1f0bd12851 | ||
|
|
321a1c9dc0 | ||
|
|
ac1015e3c4 | ||
|
|
513958ea72 | ||
|
|
2f2e4cced4 | ||
|
|
f779962e3e | ||
|
|
69776b9e7e | ||
|
|
00d726fc4c | ||
|
|
ad0f48d7e7 | ||
|
|
801e1b7699 | ||
|
|
432e7582c6 | ||
|
|
d76113100a | ||
|
|
dca33ddb75 | ||
|
|
76744a4345 | ||
|
|
b4e91091ec | ||
|
|
d5f5d382eb | ||
|
|
ffddbdc7ab | ||
|
|
46bb05d952 | ||
|
|
7cc72e4b11 | ||
|
|
a6a3f59253 | ||
|
|
8a58aafda1 | ||
|
|
8dc1641c8a | ||
|
|
4b27c92910 | ||
|
|
7fe281295f | ||
|
|
917ff81b46 | ||
|
|
8a2cc7cc4e | ||
|
|
a64d968473 | ||
|
|
a2b1bfc107 | ||
|
|
f2b3705c2c | ||
|
|
3282a84e30 | ||
|
|
89a68942ac | ||
|
|
360c34467c | ||
|
|
265e43faf0 | ||
|
|
f064a6cc60 | ||
|
|
7fead0f140 | ||
|
|
d6f14b704f | ||
|
|
a892322203 | ||
|
|
2e2063cbeb | ||
|
|
625c989875 | ||
|
|
f20204180d | ||
|
|
0e85eeef2c | ||
|
|
b0fa5e0f42 | ||
|
|
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 | ||
|
|
cebdad4d23 | ||
|
|
d798100be9 | ||
|
|
1fb6b9ee6f | ||
|
|
2d6e8f096b | ||
|
|
ec8038cc3d | ||
|
|
2df3d1c965 | ||
|
|
2272229983 | ||
|
|
b7bfecb4ee | ||
|
|
c7c4bbfce2 | ||
|
|
d7ba17dfe5 | ||
|
|
60b11435e6 | ||
|
|
ed2110d7b3 | ||
|
|
a9514de978 | ||
|
|
c57ab92e60 | ||
|
|
f878024d0b | ||
|
|
aac6be1153 | ||
|
|
dabe030890 | ||
|
|
29574282a2 | ||
|
|
2dd6ba57d1 | ||
|
|
6cc2307c71 | ||
|
|
74c8c7137a | ||
|
|
f9055ff9a7 | ||
|
|
9b3d8b318a | ||
|
|
87e29b25de | ||
|
|
f7bc9bd51b | ||
|
|
3dee617c86 | ||
|
|
2fb25e2bb3 | ||
|
|
b395359b6e | ||
|
|
fd61d70205 | ||
|
|
4f4495a693 | ||
|
|
68bbe983e9 | ||
|
|
bbef92c17d | ||
|
|
25c884158f | ||
|
|
3f936c5655 | ||
|
|
42a265b419 | ||
|
|
4bc4979acc | ||
|
|
b095367d17 | ||
|
|
eac2905568 | ||
|
|
12fd0c6838 | ||
|
|
19101826a8 | ||
|
|
7b94eab2b1 | ||
|
|
1a21b54560 | ||
|
|
b55f18649a | ||
|
|
e2373668d9 | ||
|
|
8c1a723ba5 | ||
|
|
ab7949dc16 | ||
|
|
2c4dce5ba7 | ||
|
|
cc84240098 |
0
.gitattributes
vendored
Executable file → Normal file
0
.gitattributes
vendored
Executable file → Normal file
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
16
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
Thank you for submitting a PR!
|
||||
|
||||
Please make sure you include the names of the affected language(s) in your PR title.
|
||||
This helps us get the correct maintainers to look at your issue.
|
||||
|
||||
If you make changes to any of the code generators, be sure to run
|
||||
`cd tests && sh generate_code.sh` (or equivalent .bat) and include the generated
|
||||
code changes in the PR. This allows us to better see the effect of the PR.
|
||||
|
||||
If your PR includes C++ code, please adhere to the Google C++ Style Guide,
|
||||
and don't forget we try to support older compilers (e.g. VS2010, GCC 4.6.3),
|
||||
so only some C++11 support is available.
|
||||
|
||||
Include other details as appropriate.
|
||||
|
||||
Thanks!
|
||||
15
.gitignore
vendored
Executable file → Normal file
15
.gitignore
vendored
Executable file → Normal file
@@ -5,6 +5,7 @@
|
||||
*.o.d
|
||||
*.class
|
||||
*.a
|
||||
*.swp
|
||||
*~
|
||||
*.vcxproj
|
||||
*.vcxproj.filters
|
||||
@@ -43,11 +44,14 @@ flatsampletext.exe
|
||||
grpctest
|
||||
grpctest.exe
|
||||
snapshot.sh
|
||||
tags
|
||||
tests/go_gen
|
||||
tests/monsterdata_java_wire.mon
|
||||
tests/monsterdata_go_wire.mon
|
||||
tests/monsterdata_javascript_wire.mon
|
||||
tests/unicode_test.mon
|
||||
tests/ts/
|
||||
tests/php/
|
||||
CMakeLists.txt.user
|
||||
CMakeScripts/**
|
||||
CTestTestfile.cmake
|
||||
@@ -66,3 +70,14 @@ build/VS2010/FlatBuffers.opensdf
|
||||
build/VS2010/ipch/**/*.ipch
|
||||
*.so
|
||||
Testing/Temporary
|
||||
.cproject
|
||||
.settings/
|
||||
.project
|
||||
net/**/obj
|
||||
node_modules/
|
||||
android/.externalNativeBuild/
|
||||
android/.gradle/
|
||||
android/build/
|
||||
samples/android/.externalNativeBuild/
|
||||
samples/android/.gradle/
|
||||
samples/android/build/
|
||||
|
||||
81
.travis.yml
81
.travis.yml
@@ -1,31 +1,58 @@
|
||||
language: cpp
|
||||
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
#- clang
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- BUILD_TYPE=Debug BIICODE=false
|
||||
- BUILD_TYPE=Release BIICODE=false
|
||||
# biicode .deb files no longer available.
|
||||
# - BUILD_TYPE=Release BIICODE=true
|
||||
# - BUILD_TYPE=Debug BIICODE=true
|
||||
global:
|
||||
# Set at the root level as this is ignored when set under matrix.env.
|
||||
- GCC_VERSION="4.9"
|
||||
matrix:
|
||||
include:
|
||||
- language: cpp
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
#- clang
|
||||
|
||||
env:
|
||||
matrix:
|
||||
- BUILD_TYPE=Debug BIICODE=false
|
||||
- BUILD_TYPE=Release BIICODE=false
|
||||
# biicode .deb files no longer available.
|
||||
# - BUILD_TYPE=Release BIICODE=true
|
||||
# - BUILD_TYPE=Debug BIICODE=true
|
||||
|
||||
before_install:
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq g++-$GCC_VERSION; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq gcc-$GCC_VERSION; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which g++-$GCC_VERSION) /usr/bin/g++; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
|
||||
|
||||
script:
|
||||
- if [ "$BIICODE" == "false" ]; then cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE . && make && make test; fi
|
||||
- if [ "$BIICODE" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then ./biicode/support/bii-travis.sh $BUILD_TYPE; fi
|
||||
|
||||
before_install:
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq g++-$GCC_VERSION; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq gcc-$GCC_VERSION; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which g++-$GCC_VERSION) /usr/bin/g++; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
|
||||
|
||||
script:
|
||||
- if [ "$BIICODE" == "false" ]; then cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE . && make && make test; fi
|
||||
- if [ "$BIICODE" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then ./biicode/support/bii-travis.sh $BUILD_TYPE; fi
|
||||
- language: android
|
||||
sudo: true
|
||||
android:
|
||||
components:
|
||||
- tools
|
||||
- platform-tools
|
||||
- build-tools-25.0.2
|
||||
- android-25
|
||||
- extra-android-m2repository
|
||||
compiler:
|
||||
- gcc
|
||||
before_install:
|
||||
- git clone https://github.com/urho3d/android-ndk.git $HOME/android-ndk-root
|
||||
- export ANDROID_NDK_HOME=$HOME/android-ndk-root
|
||||
# Setup environment for Linux build which is required to build the sample.
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq g++-$GCC_VERSION; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq gcc-$GCC_VERSION; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which g++-$GCC_VERSION) /usr/bin/g++; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
|
||||
script:
|
||||
- failed=0; for build_gradle in $(git ls-files | grep build.gradle); do ( cd "$(dirname "${build_gradle}")" && ./gradlew build ) || failed=1; done; exit $((failed))
|
||||
|
||||
4
CMake/FlatbuffersConfig.cmake
Normal file
4
CMake/FlatbuffersConfig.cmake
Normal file
@@ -0,0 +1,4 @@
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/FlatbuffersTargets.cmake" OPTIONAL)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/FlatcTargets.cmake" OPTIONAL)
|
||||
include("${CMAKE_CURRENT_LIST_DIR}/FlatbuffersSharedTargets.cmake" OPTIONAL)
|
||||
|
||||
109
CMakeLists.txt
109
CMakeLists.txt
@@ -24,12 +24,18 @@ 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
|
||||
include/flatbuffers/util.h
|
||||
include/flatbuffers/reflection.h
|
||||
include/flatbuffers/reflection_generated.h
|
||||
include/flatbuffers/stl_emulation.h
|
||||
include/flatbuffers/flexbuffers.h
|
||||
include/flatbuffers/registry.h
|
||||
include/flatbuffers/minireflect.h
|
||||
src/code_generators.cpp
|
||||
src/idl_parser.cpp
|
||||
src/idl_gen_text.cpp
|
||||
src/reflection.cpp
|
||||
@@ -46,7 +52,9 @@ set(FlatBuffers_Compiler_SRCS
|
||||
src/idl_gen_python.cpp
|
||||
src/idl_gen_fbs.cpp
|
||||
src/idl_gen_grpc.cpp
|
||||
src/idl_gen_json_schema.cpp
|
||||
src/flatc.cpp
|
||||
src/flatc_main.cpp
|
||||
grpc/src/compiler/schema_interface.h
|
||||
grpc/src/compiler/cpp_generator.h
|
||||
grpc/src/compiler/cpp_generator.cc
|
||||
@@ -62,7 +70,6 @@ set(FlatHash_SRCS
|
||||
set(FlatBuffers_Tests_SRCS
|
||||
${FlatBuffers_Library_SRCS}
|
||||
src/idl_gen_fbs.cpp
|
||||
src/idl_gen_general.cpp
|
||||
tests/test.cpp
|
||||
# file generate by running compiler on tests/monster_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h
|
||||
@@ -76,13 +83,7 @@ set(FlatBuffers_Sample_Binary_SRCS
|
||||
)
|
||||
|
||||
set(FlatBuffers_Sample_Text_SRCS
|
||||
include/flatbuffers/flatbuffers.h
|
||||
include/flatbuffers/hash.h
|
||||
include/flatbuffers/idl.h
|
||||
include/flatbuffers/util.h
|
||||
src/idl_parser.cpp
|
||||
src/idl_gen_text.cpp
|
||||
src/util.cpp
|
||||
${FlatBuffers_Library_SRCS}
|
||||
samples/sample_text.cpp
|
||||
# file generated by running compiler on samples/monster.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
|
||||
@@ -106,7 +107,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
|
||||
@@ -130,9 +131,13 @@ 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()
|
||||
@@ -142,6 +147,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)
|
||||
@@ -167,6 +177,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)
|
||||
@@ -175,7 +189,16 @@ endif()
|
||||
|
||||
if(FLATBUFFERS_BUILD_SHAREDLIB)
|
||||
add_library(flatbuffers_shared SHARED ${FlatBuffers_Library_SRCS})
|
||||
set_target_properties(flatbuffers_shared PROPERTIES OUTPUT_NAME flatbuffers)
|
||||
|
||||
# Shared object version: "major.minor.micro"
|
||||
# - micro updated every release when there is no API/ABI changes
|
||||
# - minor updated when there are additions in API/ABI
|
||||
# - major (ABI number) updated when there are changes in ABI (or removals)
|
||||
set(FlatBuffers_Library_SONAME_MAJOR "1")
|
||||
set(FlatBuffers_Library_SONAME_FULL "${FlatBuffers_Library_SONAME_MAJOR}.8.0")
|
||||
set_target_properties(flatbuffers_shared PROPERTIES OUTPUT_NAME flatbuffers
|
||||
SOVERSION "${FlatBuffers_Library_SONAME_MAJOR}"
|
||||
VERSION "${FlatBuffers_Library_SONAME_FULL}")
|
||||
endif()
|
||||
|
||||
function(compile_flatbuffers_schema_to_cpp SRC_FBS)
|
||||
@@ -185,6 +208,9 @@ 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}"
|
||||
--cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs
|
||||
--reflect-names
|
||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
DEPENDS flatc)
|
||||
endfunction()
|
||||
@@ -215,22 +241,67 @@ 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 grpc_unsecure pthread dl)
|
||||
endif()
|
||||
|
||||
if(FLATBUFFERS_INSTALL)
|
||||
install(DIRECTORY include/flatbuffers DESTINATION include)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
install(DIRECTORY include/flatbuffers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
|
||||
set(FB_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/flatbuffers")
|
||||
|
||||
install(
|
||||
FILES "CMake/FlatbuffersConfig.cmake"
|
||||
DESTINATION ${FB_CMAKE_DIR}
|
||||
)
|
||||
|
||||
if(FLATBUFFERS_BUILD_FLATLIB)
|
||||
install(TARGETS flatbuffers DESTINATION lib)
|
||||
install(
|
||||
TARGETS flatbuffers EXPORT FlatbuffersTargets
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
||||
install(EXPORT FlatbuffersTargets
|
||||
FILE FlatbuffersTargets.cmake
|
||||
NAMESPACE flatbuffers::
|
||||
DESTINATION ${FB_CMAKE_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(FLATBUFFERS_BUILD_FLATC)
|
||||
install(TARGETS flatc DESTINATION bin)
|
||||
install(
|
||||
TARGETS flatc EXPORT FlatcTargets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
CONFIGURATIONS Release
|
||||
)
|
||||
|
||||
install(
|
||||
EXPORT FlatcTargets
|
||||
FILE FlatcTargets.cmake
|
||||
NAMESPACE flatbuffers::
|
||||
DESTINATION ${FB_CMAKE_DIR}
|
||||
CONFIGURATIONS Release
|
||||
)
|
||||
endif()
|
||||
|
||||
if(FLATBUFFERS_BUILD_SHAREDLIB)
|
||||
install(TARGETS flatbuffers_shared DESTINATION lib)
|
||||
install(
|
||||
TARGETS flatbuffers_shared EXPORT FlatbuffersSharedTargets
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
||||
install(
|
||||
EXPORT FlatbuffersSharedTargets
|
||||
FILE FlatbuffersSharedTargets.cmake
|
||||
NAMESPACE flatbuffers::
|
||||
DESTINATION ${FB_CMAKE_DIR}
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ use Github pull requests for this purpose.
|
||||
|
||||
Some tips for good pull requests:
|
||||
* Use our code
|
||||
[style guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.html).
|
||||
[style guide](https://google.github.io/styleguide/cppguide.html).
|
||||
When in doubt, try to stay true to the existing code of the project.
|
||||
* Write a descriptive commit message. What problem are you solving and what
|
||||
are the consequences? Where and what did you test? Some good tips:
|
||||
|
||||
0
android/.project
Executable file → Normal file
0
android/.project
Executable file → Normal file
11
android/AndroidManifest.xml
Executable file → Normal file
11
android/AndroidManifest.xml
Executable file → Normal file
@@ -17,17 +17,14 @@
|
||||
-->
|
||||
<!-- BEGIN_INCLUDE(manifest) -->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.example.FlatBufferTest"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
package="com.example.FlatBufferTest">
|
||||
|
||||
<uses-feature android:glEsVersion="0x00020000"></uses-feature>
|
||||
<!-- This is the platform API where NativeActivity was introduced. -->
|
||||
<uses-sdk android:minSdkVersion="9" />
|
||||
|
||||
<!-- This .apk has no Java code itself, so set hasCode to false. -->
|
||||
<application android:label="@string/app_name" android:hasCode="false">
|
||||
|
||||
<application android:label="@string/app_name"
|
||||
android:hasCode="false"
|
||||
android:allowBackup="false">
|
||||
<!-- Our activity is the built-in NativeActivity framework class.
|
||||
This will take care of integrating with our NDK code. -->
|
||||
<activity android:name="android.app.NativeActivity"
|
||||
|
||||
108
android/build.gradle
Normal file
108
android/build.gradle
Normal file
@@ -0,0 +1,108 @@
|
||||
// Copyright (c) 2017 Google, Inc.
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.3.0'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion '25.0.2'
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile 'AndroidManifest.xml'
|
||||
res.srcDirs = ['res']
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
path "jni/Android.mk"
|
||||
}
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId 'com.example.FlatBufferTest'
|
||||
// This is the platform API where NativeActivity was introduced.
|
||||
minSdkVersion 9
|
||||
targetSdkVersion 25
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
targets "FlatBufferTest"
|
||||
arguments "-j" + Runtime.getRuntime().availableProcessors()
|
||||
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
// Build with each STL variant.
|
||||
productFlavors {
|
||||
stlport {
|
||||
applicationIdSuffix ".stlport"
|
||||
versionNameSuffix "-stlport"
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
arguments "APP_STL=stlport_static"
|
||||
}
|
||||
}
|
||||
}
|
||||
gnustl {
|
||||
applicationIdSuffix ".gnustl"
|
||||
versionNameSuffix "-gnustl"
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
arguments "APP_STL=gnustl_static"
|
||||
}
|
||||
}
|
||||
}
|
||||
libcpp {
|
||||
applicationIdSuffix ".libcpp"
|
||||
versionNameSuffix "-libcpp"
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
arguments "APP_STL=c++_static"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,511 +0,0 @@
|
||||
#!/bin/bash -eu
|
||||
#
|
||||
# Copyright (c) 2013 Google, Inc.
|
||||
#
|
||||
# This software is provided 'as-is', without any express or implied
|
||||
# warranty. In no event will the authors be held liable for any damages
|
||||
# arising from the use of this software.
|
||||
# Permission is granted to anyone to use this software for any purpose,
|
||||
# including commercial applications, and to alter it and redistribute it
|
||||
# freely, subject to the following restrictions:
|
||||
# 1. The origin of this software must not be misrepresented; you must not
|
||||
# claim that you wrote the original software. If you use this software
|
||||
# in a product, an acknowledgment in the product documentation would be
|
||||
# appreciated but is not required.
|
||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||
# misrepresented as being the original software.
|
||||
# 3. This notice may not be removed or altered from any source distribution.
|
||||
#
|
||||
# Build, deploy, debug / execute a native Android package based upon
|
||||
# NativeActivity.
|
||||
|
||||
declare -r script_directory=$(dirname $0)
|
||||
declare -r android_root=${script_directory}/../../../../../../
|
||||
declare -r script_name=$(basename $0)
|
||||
declare -r android_manifest=AndroidManifest.xml
|
||||
declare -r os_name=$(uname -s)
|
||||
|
||||
# Minimum Android target version supported by this project.
|
||||
: ${BUILDAPK_ANDROID_TARGET_MINVERSION:=10}
|
||||
# Directory containing the Android SDK
|
||||
# (http://developer.android.com/sdk/index.html).
|
||||
: ${ANDROID_SDK_HOME:=}
|
||||
# Directory containing the Android NDK
|
||||
# (http://developer.android.com/tools/sdk/ndk/index.html).
|
||||
: ${NDK_HOME:=}
|
||||
|
||||
# Display script help and exit.
|
||||
usage() {
|
||||
echo "
|
||||
Build the Android package in the current directory and deploy it to a
|
||||
connected device.
|
||||
|
||||
Usage: ${script_name} \\
|
||||
[ADB_DEVICE=serial_number] [BUILD=0] [DEPLOY=0] [RUN_DEBUGGER=1] \
|
||||
[LAUNCH=0] [SWIG_BIN=swig_binary_directory] [SWIG_LIB=swig_include_directory] [ndk-build arguments ...]
|
||||
|
||||
ADB_DEVICE=serial_number:
|
||||
serial_number specifies the device to deploy the built apk to if multiple
|
||||
Android devices are connected to the host.
|
||||
BUILD=0:
|
||||
Disables the build of the package.
|
||||
DEPLOY=0:
|
||||
Disables the deployment of the built apk to the Android device.
|
||||
RUN_DEBUGGER=1:
|
||||
Launches the application in gdb after it has been deployed. To debug in
|
||||
gdb, NDK_DEBUG=1 must also be specified on the command line to build a
|
||||
debug apk.
|
||||
LAUNCH=0:
|
||||
Disable the launch of the apk on the Android device.
|
||||
SWIG_BIN=swig_binary_directory:
|
||||
The directory where the SWIG binary lives. No need to set this if SWIG is
|
||||
installed and point to from your PATH variable.
|
||||
SWIG_LIB=swig_include_directory:
|
||||
The directory where SWIG shared include files are, usually obtainable from
|
||||
commandline with \"swig -swiglib\". No need to set this if SWIG is installed
|
||||
and point to from your PATH variable.
|
||||
ndk-build arguments...:
|
||||
Additional arguments for ndk-build. See ndk-build -h for more information.
|
||||
" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Get the number of CPU cores present on the host.
|
||||
get_number_of_cores() {
|
||||
case ${os_name} in
|
||||
Darwin)
|
||||
sysctl hw.ncpu | awk '{ print $2 }'
|
||||
;;
|
||||
CYGWIN*|Linux)
|
||||
awk '/^processor/ { n=$3 } END { print n + 1 }' /proc/cpuinfo
|
||||
;;
|
||||
*)
|
||||
echo 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Get the package name from an AndroidManifest.xml file.
|
||||
get_package_name_from_manifest() {
|
||||
xmllint --xpath 'string(/manifest/@package)' "${1}"
|
||||
}
|
||||
|
||||
# Get the library name from an AndroidManifest.xml file.
|
||||
get_library_name_from_manifest() {
|
||||
echo "\
|
||||
setns android=http://schemas.android.com/apk/res/android
|
||||
xpath string(/manifest/application/activity\
|
||||
[@android:name=\"android.app.NativeActivity\"]/meta-data\
|
||||
[@android:name=\"android.app.lib_name\"]/@android:value)" |
|
||||
xmllint --shell "${1}" | awk '/Object is a string/ { print $NF }'
|
||||
}
|
||||
|
||||
# Get the number of Android devices connected to the system.
|
||||
get_number_of_devices_connected() {
|
||||
adb devices -l | \
|
||||
awk '/^..*$/ { if (p) { print $0 } }
|
||||
/List of devices attached/ { p = 1 }' | \
|
||||
wc -l
|
||||
return ${PIPESTATUS[0]}
|
||||
}
|
||||
|
||||
# Kill a process and its' children. This is provided for cygwin which
|
||||
# doesn't ship with pkill.
|
||||
kill_process_group() {
|
||||
local parent_pid="${1}"
|
||||
local child_pid=
|
||||
for child_pid in $(ps -f | \
|
||||
awk '{ if ($3 == '"${parent_pid}"') { print $2 } }'); do
|
||||
kill_process_group "${child_pid}"
|
||||
done
|
||||
kill "${parent_pid}" 2>/dev/null
|
||||
}
|
||||
|
||||
# Find and run "adb".
|
||||
adb() {
|
||||
local adb_path=
|
||||
for path in "$(which adb 2>/dev/null)" \
|
||||
"${ANDROID_SDK_HOME}/sdk/platform-tools/adb" \
|
||||
"${android_root}/prebuilts/sdk/platform-tools/adb"; do
|
||||
if [[ -e "${path}" ]]; then
|
||||
adb_path="${path}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "${adb_path}" == "" ]]; then
|
||||
echo -e "Unable to find adb." \
|
||||
"\nAdd the Android ADT sdk/platform-tools directory to the" \
|
||||
"PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
"${adb_path}" "$@"
|
||||
}
|
||||
|
||||
# Find and run "android".
|
||||
android() {
|
||||
local android_executable=android
|
||||
if echo "${os_name}" | grep -q CYGWIN; then
|
||||
android_executable=android.bat
|
||||
fi
|
||||
local android_path=
|
||||
for path in "$(which ${android_executable})" \
|
||||
"${ANDROID_SDK_HOME}/sdk/tools/${android_executable}" \
|
||||
"${android_root}/prebuilts/sdk/tools/${android_executable}"; do
|
||||
if [[ -e "${path}" ]]; then
|
||||
android_path="${path}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "${android_path}" == "" ]]; then
|
||||
echo -e "Unable to find android tool." \
|
||||
"\nAdd the Android ADT sdk/tools directory to the PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
# Make sure ant is installed.
|
||||
if [[ "$(which ant)" == "" ]]; then
|
||||
echo -e "Unable to find ant." \
|
||||
"\nPlease install ant and add to the PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"${android_path}" "$@"
|
||||
}
|
||||
|
||||
# Find and run "ndk-build"
|
||||
ndkbuild() {
|
||||
local ndkbuild_path=
|
||||
for path in "$(which ndk-build 2>/dev/null)" \
|
||||
"${NDK_HOME}/ndk-build" \
|
||||
"${android_root}/prebuilts/ndk/current/ndk-build"; do
|
||||
if [[ -e "${path}" ]]; then
|
||||
ndkbuild_path="${path}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "${ndkbuild_path}" == "" ]]; then
|
||||
echo -e "Unable to find ndk-build." \
|
||||
"\nAdd the Android NDK directory to the PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
"${ndkbuild_path}" "$@"
|
||||
}
|
||||
|
||||
# Get file modification time of $1 in seconds since the epoch.
|
||||
stat_mtime() {
|
||||
local filename="${1}"
|
||||
case ${os_name} in
|
||||
Darwin) stat -f%m "${filename}" 2>/dev/null || echo 0 ;;
|
||||
*) stat -c%Y "${filename}" 2>/dev/null || echo 0 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Build the native (C/C++) build targets in the current directory.
|
||||
build_native_targets() {
|
||||
# Save the list of output modules in the install directory so that it's
|
||||
# possible to restore their timestamps after the build is complete. This
|
||||
# works around a bug in ndk/build/core/setup-app.mk which results in the
|
||||
# unconditional execution of the clean-installed-binaries rule.
|
||||
restore_libraries="$(find libs -type f 2>/dev/null | \
|
||||
sed -E 's@^libs/(.*)@\1@')"
|
||||
|
||||
# Build native code.
|
||||
ndkbuild -j$(get_number_of_cores) "$@"
|
||||
|
||||
# Restore installed libraries.
|
||||
# Obviously this is a nasty hack (along with ${restore_libraries} above) as
|
||||
# it assumes it knows where the NDK will be placing output files.
|
||||
(
|
||||
IFS=$'\n'
|
||||
for libpath in ${restore_libraries}; do
|
||||
source_library="obj/local/${libpath}"
|
||||
target_library="libs/${libpath}"
|
||||
if [[ -e "${source_library}" ]]; then
|
||||
cp -a "${source_library}" "${target_library}"
|
||||
fi
|
||||
done
|
||||
)
|
||||
}
|
||||
|
||||
# Select the oldest installed android build target that is at least as new as
|
||||
# BUILDAPK_ANDROID_TARGET_MINVERSION. If a suitable build target isn't found,
|
||||
# this function prints an error message and exits with an error.
|
||||
select_android_build_target() {
|
||||
local -r android_targets_installed=$( \
|
||||
android list targets | \
|
||||
awk -F'"' '/^id:.*android/ { print $2 }')
|
||||
local android_build_target=
|
||||
for android_target in $(echo "${android_targets_installed}" | \
|
||||
awk -F- '{ print $2 }' | sort -n); do
|
||||
local isNumber='^[0-9]+$'
|
||||
# skip preview API releases e.g. 'android-L'
|
||||
if [[ $android_target =~ $isNumber ]]; then
|
||||
if [[ $((android_target)) -ge \
|
||||
$((BUILDAPK_ANDROID_TARGET_MINVERSION)) ]]; then
|
||||
android_build_target="android-${android_target}"
|
||||
break
|
||||
fi
|
||||
# else
|
||||
# The API version is a letter, so skip it.
|
||||
fi
|
||||
done
|
||||
if [[ "${android_build_target}" == "" ]]; then
|
||||
echo -e \
|
||||
"Found installed Android targets:" \
|
||||
"$(echo ${android_targets_installed} | sed 's/ /\n /g;s/^/\n /;')" \
|
||||
"\nAndroid SDK platform" \
|
||||
"android-$((BUILDAPK_ANDROID_TARGET_MINVERSION))" \
|
||||
"must be installed to build this project." \
|
||||
"\nUse the \"android\" application to install API" \
|
||||
"$((BUILDAPK_ANDROID_TARGET_MINVERSION)) or newer." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "${android_build_target}"
|
||||
}
|
||||
|
||||
# Sign unsigned apk $1 and write the result to $2 with key store file $3 and
|
||||
# password $4.
|
||||
# If a key store file $3 and password $4 aren't specified, a temporary
|
||||
# (60 day) key is generated and used to sign the package.
|
||||
sign_apk() {
|
||||
local unsigned_apk="${1}"
|
||||
local signed_apk="${2}"
|
||||
if [[ $(stat_mtime "${unsigned_apk}") -gt \
|
||||
$(stat_mtime "${signed_apk}") ]]; then
|
||||
local -r key_alias=$(basename ${signed_apk} .apk)
|
||||
local keystore="${3}"
|
||||
local key_password="${4}"
|
||||
[[ "${keystore}" == "" ]] && keystore="${unsigned_apk}.keystore"
|
||||
[[ "${key_password}" == "" ]] && \
|
||||
key_password="${key_alias}123456"
|
||||
if [[ ! -e ${keystore} ]]; then
|
||||
keytool -genkey -v -dname "cn=, ou=${key_alias}, o=fpl" \
|
||||
-storepass ${key_password} \
|
||||
-keypass ${key_password} -keystore ${keystore} \
|
||||
-alias ${key_alias} -keyalg RSA -keysize 2048 -validity 60
|
||||
fi
|
||||
cp "${unsigned_apk}" "${signed_apk}"
|
||||
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 \
|
||||
-keystore ${keystore} -storepass ${key_password} \
|
||||
-keypass ${key_password} "${signed_apk}" ${key_alias}
|
||||
fi
|
||||
}
|
||||
|
||||
# Build the apk $1 for package filename $2 in the current directory using the
|
||||
# ant build target $3.
|
||||
build_apk() {
|
||||
local -r output_apk="${1}"
|
||||
local -r package_filename="${2}"
|
||||
local -r ant_target="${3}"
|
||||
# Get the list of installed android targets and select the oldest target
|
||||
# that is at least as new as BUILDAPK_ANDROID_TARGET_MINVERSION.
|
||||
local -r android_build_target=$(select_android_build_target)
|
||||
[[ "${android_build_target}" == "" ]] && exit 1
|
||||
echo "Building ${output_apk} for target ${android_build_target}" >&2
|
||||
|
||||
# Create / update build.xml and local.properties files.
|
||||
if [[ $(stat_mtime "${android_manifest}") -gt \
|
||||
$(stat_mtime build.xml) ]]; then
|
||||
android update project --target "${android_build_target}" \
|
||||
-n ${package_filename} --path .
|
||||
fi
|
||||
|
||||
# Use ant to build the apk.
|
||||
ant -quiet ${ant_target}
|
||||
|
||||
# Sign release apks with a temporary key as these packages will not be
|
||||
# redistributed.
|
||||
local unsigned_apk="bin/${package_filename}-${ant_target}-unsigned.apk"
|
||||
if [[ "${ant_target}" == "release" ]]; then
|
||||
sign_apk "${unsigned_apk}" "${output_apk}" "" ""
|
||||
fi
|
||||
}
|
||||
|
||||
# Uninstall package $1 and install apk $2 on device $3 where $3 is "-s device"
|
||||
# or an empty string. If $3 is an empty string adb will fail when multiple
|
||||
# devices are connected to the host system.
|
||||
install_apk() {
|
||||
local -r uninstall_package_name="${1}"
|
||||
local -r install_apk="${2}"
|
||||
local -r adb_device="${3}"
|
||||
# Uninstall the package if it's already installed.
|
||||
adb ${adb_device} uninstall "${uninstall_package_name}" 1>&2 > /dev/null || \
|
||||
true # no error check
|
||||
|
||||
# Install the apk.
|
||||
# NOTE: The following works around adb not returning an error code when
|
||||
# it fails to install an apk.
|
||||
echo "Install ${install_apk}" >&2
|
||||
local -r adb_install_result=$(adb ${adb_device} install "${install_apk}")
|
||||
echo "${adb_install_result}"
|
||||
if echo "${adb_install_result}" | grep -qF 'Failure ['; then
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Launch previously installed package $1 on device $2.
|
||||
# If $2 is an empty string adb will fail when multiple devices are connected
|
||||
# to the host system.
|
||||
launch_package() {
|
||||
(
|
||||
# Determine the SDK version of Android on the device.
|
||||
local -r android_sdk_version=$(
|
||||
adb ${adb_device} shell cat system/build.prop | \
|
||||
awk -F= '/ro.build.version.sdk/ {
|
||||
v=$2; sub(/[ \r\n]/, "", v); print v
|
||||
}')
|
||||
|
||||
# Clear logs from previous runs.
|
||||
# Note that logcat does not just 'tail' the logs, it dumps the entire log
|
||||
# history.
|
||||
adb ${adb_device} logcat -c
|
||||
|
||||
local finished_msg='Displayed '"${package_name}"
|
||||
local timeout_msg='Activity destroy timeout.*'"${package_name}"
|
||||
# Maximum time to wait before stopping log monitoring. 0 = infinity.
|
||||
local launch_timeout=0
|
||||
# If this is a Gingerbread device, kill log monitoring after 10 seconds.
|
||||
if [[ $((android_sdk_version)) -le 10 ]]; then
|
||||
launch_timeout=10
|
||||
fi
|
||||
# Display logcat in the background.
|
||||
# Stop displaying the log when the app launch / execution completes or the
|
||||
# logcat
|
||||
(
|
||||
adb ${adb_device} logcat | \
|
||||
awk "
|
||||
{
|
||||
print \$0
|
||||
}
|
||||
|
||||
/ActivityManager.*: ${finished_msg}/ {
|
||||
exit 0
|
||||
}
|
||||
|
||||
/ActivityManager.*: ${timeout_msg}/ {
|
||||
exit 0
|
||||
}" &
|
||||
adb_logcat_pid=$!;
|
||||
if [[ $((launch_timeout)) -gt 0 ]]; then
|
||||
sleep $((launch_timeout));
|
||||
kill ${adb_logcat_pid};
|
||||
else
|
||||
wait ${adb_logcat_pid};
|
||||
fi
|
||||
) &
|
||||
logcat_pid=$!
|
||||
# Kill adb logcat if this shell exits.
|
||||
trap "kill_process_group ${logcat_pid}" SIGINT SIGTERM EXIT
|
||||
|
||||
# If the SDK is newer than 10, "am" supports stopping an activity.
|
||||
adb_stop_activity=
|
||||
if [[ $((android_sdk_version)) -gt 10 ]]; then
|
||||
adb_stop_activity=-S
|
||||
fi
|
||||
|
||||
# Launch the activity and wait for it to complete.
|
||||
adb ${adb_device} shell am start ${adb_stop_activity} -n \
|
||||
${package_name}/android.app.NativeActivity
|
||||
|
||||
wait "${logcat_pid}"
|
||||
)
|
||||
}
|
||||
|
||||
# See usage().
|
||||
main() {
|
||||
# Parse arguments for this script.
|
||||
local adb_device=
|
||||
local ant_target=release
|
||||
local disable_deploy=0
|
||||
local disable_build=0
|
||||
local run_debugger=0
|
||||
local launch=1
|
||||
local build_package=1
|
||||
for opt; do
|
||||
case ${opt} in
|
||||
# NDK_DEBUG=0 tells ndk-build to build this as debuggable but to not
|
||||
# modify the underlying code whereas NDK_DEBUG=1 also builds as debuggable
|
||||
# but does modify the code
|
||||
NDK_DEBUG=1) ant_target=debug ;;
|
||||
NDK_DEBUG=0) ant_target=debug ;;
|
||||
ADB_DEVICE*) adb_device="$(\
|
||||
echo "${opt}" | sed -E 's/^ADB_DEVICE=([^ ]+)$/-s \1/;t;s/.*//')" ;;
|
||||
BUILD=0) disable_build=1 ;;
|
||||
DEPLOY=0) disable_deploy=1 ;;
|
||||
RUN_DEBUGGER=1) run_debugger=1 ;;
|
||||
LAUNCH=0) launch=0 ;;
|
||||
clean) build_package=0 disable_deploy=1 launch=0 ;;
|
||||
-h|--help|help) usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# If a target device hasn't been specified and multiple devices are connected
|
||||
# to the host machine, display an error.
|
||||
local -r devices_connected=$(get_number_of_devices_connected)
|
||||
if [[ "${adb_device}" == "" && $((devices_connected)) -gt 1 && \
|
||||
($((disable_deploy)) -eq 0 || $((launch)) -ne 0 || \
|
||||
$((run_debugger)) -ne 0) ]]; then
|
||||
if [[ $((disable_deploy)) -ne 0 ]]; then
|
||||
echo "Deployment enabled, disable using DEPLOY=0" >&2
|
||||
fi
|
||||
if [[ $((launch)) -ne 0 ]]; then
|
||||
echo "Launch enabled." >&2
|
||||
fi
|
||||
if [[ $((disable_deploy)) -eq 0 ]]; then
|
||||
echo "Deployment enabled." >&2
|
||||
fi
|
||||
if [[ $((run_debugger)) -ne 0 ]]; then
|
||||
echo "Debugger launch enabled." >&2
|
||||
fi
|
||||
echo "
|
||||
Multiple Android devices are connected to this host. Either disable deployment
|
||||
and execution of the built .apk using:
|
||||
\"${script_name} DEPLOY=0 LAUNCH=0\"
|
||||
|
||||
or specify a device to deploy to using:
|
||||
\"${script_name} ADB_DEVICE=\${device_serial}\".
|
||||
|
||||
The Android devices connected to this machine are:
|
||||
$(adb devices -l)
|
||||
" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $((disable_build)) -eq 0 ]]; then
|
||||
# Build the native target.
|
||||
build_native_targets "$@"
|
||||
fi
|
||||
|
||||
# Get the package name from the manifest.
|
||||
local -r package_name=$(get_package_name_from_manifest "${android_manifest}")
|
||||
if [[ "${package_name}" == "" ]]; then
|
||||
echo -e "No package name specified in ${android_manifest},"\
|
||||
"skipping apk build, deploy"
|
||||
"\nand launch steps." >&2
|
||||
exit 0
|
||||
fi
|
||||
local -r package_basename=${package_name/*./}
|
||||
local package_filename=$(get_library_name_from_manifest ${android_manifest})
|
||||
[[ "${package_filename}" == "" ]] && package_filename="${package_basename}"
|
||||
|
||||
# Output apk name.
|
||||
local -r output_apk="bin/${package_filename}-${ant_target}.apk"
|
||||
|
||||
if [[ $((disable_build)) -eq 0 && $((build_package)) -eq 1 ]]; then
|
||||
# Build the apk.
|
||||
build_apk "${output_apk}" "${package_filename}" "${ant_target}"
|
||||
fi
|
||||
|
||||
# Deploy to the device.
|
||||
if [[ $((disable_deploy)) -eq 0 ]]; then
|
||||
install_apk "${package_name}" "${output_apk}" "${adb_device}"
|
||||
fi
|
||||
|
||||
if [[ "${ant_target}" == "debug" && $((run_debugger)) -eq 1 ]]; then
|
||||
# Start debugging.
|
||||
ndk-gdb ${adb_device} --start
|
||||
elif [[ $((launch)) -eq 1 ]]; then
|
||||
launch_package "${package_name}" "${adb_device}"
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
BIN
android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
6
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#Mon Jun 19 11:54:59 PDT 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-all.zip
|
||||
172
android/gradlew
vendored
Executable file
172
android/gradlew
vendored
Executable file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
84
android/gradlew.bat
vendored
Normal file
84
android/gradlew.bat
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
10
android/jni/Android.mk
Executable file → Normal file
10
android/jni/Android.mk
Executable file → Normal file
@@ -24,7 +24,9 @@ LOCAL_PATH := $(call realpath-portable,$(LOCAL_PATH))
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_MODULE := flatbuffers
|
||||
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
|
||||
LOCAL_EXPORT_CPPFLAGS := -std=c++11 -fexceptions -Wall -Wno-literal-suffix
|
||||
LOCAL_EXPORT_CPPFLAGS := -std=c++11 -fexceptions -Wall \
|
||||
-DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
# static library that additionally includes text parsing/generation/reflection
|
||||
@@ -34,8 +36,10 @@ LOCAL_MODULE := flatbuffers_extra
|
||||
LOCAL_SRC_FILES := src/idl_parser.cpp \
|
||||
src/idl_gen_text.cpp \
|
||||
src/reflection.cpp \
|
||||
src/util.cpp
|
||||
src/util.cpp \
|
||||
src/code_generators.cpp
|
||||
LOCAL_STATIC_LIBRARIES := flatbuffers
|
||||
LOCAL_ARM_MODE := arm
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
|
||||
# FlatBuffers test
|
||||
@@ -45,7 +49,7 @@ LOCAL_SRC_FILES := android/jni/main.cpp \
|
||||
tests/test.cpp \
|
||||
src/idl_gen_fbs.cpp \
|
||||
src/idl_gen_general.cpp
|
||||
LOCAL_LDLIBS := -llog -landroid
|
||||
LOCAL_LDLIBS := -llog -landroid -latomic
|
||||
LOCAL_STATIC_LIBRARIES := android_native_app_glue flatbuffers_extra
|
||||
LOCAL_ARM_MODE := arm
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
|
||||
6
android/jni/Application.mk
Executable file → Normal file
6
android/jni/Application.mk
Executable file → Normal file
@@ -13,10 +13,8 @@
|
||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||
# misrepresented as being the original software.
|
||||
# 3. This notice may not be removed or altered from any source distribution.
|
||||
APP_PLATFORM := android-10
|
||||
APP_PLATFORM := android-9
|
||||
APP_PROJECT_PATH := $(call my-dir)/..
|
||||
APP_STL := gnustl_static
|
||||
|
||||
APP_STL ?= stlport_static
|
||||
APP_ABI := armeabi-v7a
|
||||
|
||||
APP_CPPFLAGS += -std=c++11
|
||||
|
||||
0
android/jni/build_flatc.bat
Executable file → Normal file
0
android/jni/build_flatc.bat
Executable file → Normal file
0
android/res/values/strings.xml
Executable file → Normal file
0
android/res/values/strings.xml
Executable file → Normal file
51
appveyor.yml
51
appveyor.yml
@@ -4,6 +4,17 @@ branches:
|
||||
|
||||
os: Visual Studio 2015
|
||||
|
||||
environment:
|
||||
|
||||
global:
|
||||
# Workaround for https://github.com/conda/conda-build/issues/636
|
||||
PYTHONIOENCODING: UTF-8
|
||||
CONDA_INSTALL_LOCN: "C:\\Miniconda35-x64"
|
||||
|
||||
matrix:
|
||||
- CMAKE_VS_VERSION: "10 2010"
|
||||
- CMAKE_VS_VERSION: "14 2015"
|
||||
|
||||
platform:
|
||||
- x86
|
||||
- x64
|
||||
@@ -13,7 +24,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"
|
||||
|
||||
@@ -21,17 +32,41 @@ build:
|
||||
project: ALL_BUILD.vcxproj
|
||||
verbosity: minimal
|
||||
|
||||
install:
|
||||
- set PATH=%CONDA_INSTALL_LOCN%;%CONDA_INSTALL_LOCN%\scripts;%PATH%;
|
||||
|
||||
test_script:
|
||||
- rem "---------------- C++ -----------------"
|
||||
- "%CONFIGURATION%\\flattests.exe"
|
||||
- rem "---------------- Java -----------------"
|
||||
- "cd tests"
|
||||
- rem "Building all code"
|
||||
- generate_code.bat -b %CONFIGURATION%
|
||||
- 7z a GeneratedMyGameCode.zip MyGame\
|
||||
- rem "---------------- C++ -----------------"
|
||||
- "cd .."
|
||||
- "%CONFIGURATION%\\flattests.exe"
|
||||
- "cd tests"
|
||||
- rem "---------------- Java -----------------"
|
||||
- "java -version"
|
||||
- "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 "-------------- Python ---------------"
|
||||
- where python
|
||||
- python --version
|
||||
- where pip
|
||||
- pip --version
|
||||
- where conda
|
||||
- conda --version
|
||||
- rem "installing flatbuffers python library"
|
||||
- pip install ../python
|
||||
- rem "testing without installing Numpy"
|
||||
- python py_test.py 0 0 0
|
||||
- rem "testing after installing Numpy - disabled"
|
||||
# FIXME: This has a LOT of unnecessary dependencies and makes the tests fail
|
||||
# with timeouts.
|
||||
# - conda install --yes numpy
|
||||
# - python py_test.py 0 0 0
|
||||
- rem "---------------- C# -----------------"
|
||||
# Have to compile this here rather than in "build" above because AppVeyor only
|
||||
# supports building one project??
|
||||
@@ -42,5 +77,7 @@ test_script:
|
||||
- "cd ..\\.."
|
||||
|
||||
artifacts:
|
||||
- path: $(CONFIGURATION)\\flatc.exe
|
||||
- path: $(CONFIGURATION)\flatc.exe
|
||||
name: flatc.exe
|
||||
- path: tests\GeneratedMyGameCode.zip
|
||||
name: GeneratedMyGameCode.zip
|
||||
|
||||
0
docs/footer.html
Executable file → Normal file
0
docs/footer.html
Executable file → Normal file
2
docs/source/Benchmarks.md
Executable file → Normal file
2
docs/source/Benchmarks.md
Executable file → Normal file
@@ -1,4 +1,4 @@
|
||||
Benchmarks {#flatbuffers_benchmarks}
|
||||
C++ Benchmarks {#flatbuffers_benchmarks}
|
||||
==========
|
||||
|
||||
Comparing against other serialization solutions, running on Windows 7
|
||||
|
||||
0
docs/source/Building.md
Executable file → Normal file
0
docs/source/Building.md
Executable file → Normal file
@@ -1 +1 @@
|
||||
../../CONTRIBUTING
|
||||
../../CONTRIBUTING.md
|
||||
18
docs/source/Compiler.md
Executable file → Normal file
18
docs/source/Compiler.md
Executable file → Normal file
@@ -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.
|
||||
|
||||
@@ -93,6 +93,12 @@ Additional options:
|
||||
output (by default the case for C++ and JS), all code will end up in
|
||||
this one file.
|
||||
|
||||
- `--no-js-exports` : Removes Node.js style export lines (useful for JS)
|
||||
|
||||
- `--goog-js-export` : Uses goog.exportsSymbol and goog.exportsProperty
|
||||
instead of Node.js style exporting. Needed for compatibility with the
|
||||
Google closure compiler (useful for JS).
|
||||
|
||||
- `--raw-binary` : Allow binaries without a file_indentifier to be read.
|
||||
This may crash flatc given a mismatched schema.
|
||||
|
||||
@@ -108,9 +114,19 @@ Additional options:
|
||||
to the reflection/reflection.fbs schema. Loading this binary file is the
|
||||
basis for reflection functionality.
|
||||
|
||||
- `--bfbs-comments`: Add doc comments to the binary schema files.
|
||||
|
||||
- `--conform FILE` : Specify a schema the following schemas should be
|
||||
an evolution of. Gives errors if not. Useful to check if schema
|
||||
modifications don't break schema evolution rules.
|
||||
|
||||
- `--include-prefix PATH` : Prefix this path to any generated include
|
||||
statements.
|
||||
|
||||
- `--keep-prefix` : Keep original prefix of schema include statement.
|
||||
|
||||
- `--reflect-types` : Add minimal type reflection to code generation.
|
||||
- `--reflect-names` : Add minimal type/name reflection.
|
||||
|
||||
NOTE: short-form options for generators are deprecated, use the long form
|
||||
whenever possible.
|
||||
|
||||
123
docs/source/CppUsage.md
Executable file → Normal file
123
docs/source/CppUsage.md
Executable file → Normal file
@@ -85,7 +85,7 @@ convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
|
||||
|
||||
*Note: That we never stored a `mana` value, so it will return the default.*
|
||||
|
||||
## Object based API.
|
||||
## Object based API. {#flatbuffers_cpp_object_based_api}
|
||||
|
||||
FlatBuffers is all about memory efficiency, which is why its base API is written
|
||||
around using as little as possible of it. This does make the API clumsier
|
||||
@@ -99,13 +99,79 @@ construction, access and mutation.
|
||||
To use:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
auto monsterobj = UnpackMonster(buffer);
|
||||
// Autogenerated class from table Monster.
|
||||
MonsterT monsterobj;
|
||||
|
||||
// Deserialize from buffer into object.
|
||||
UnPackTo(&monsterobj, flatbuffer);
|
||||
|
||||
// Update object directly like a C++ class instance.
|
||||
cout << monsterobj->name; // This is now a std::string!
|
||||
monsterobj->name = "Bob"; // Change the name.
|
||||
|
||||
// Serialize into new flatbuffer.
|
||||
FlatBufferBuilder fbb;
|
||||
CreateMonster(fbb, monsterobj.get()); // Serialize into new buffer.
|
||||
Pack(fbb, &monsterobj);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following attributes are specific to the object-based API code generation:
|
||||
|
||||
- `native_inline` (on a field): Because FlatBuffer tables and structs are
|
||||
optionally present in a given buffer, they are best represented as pointers
|
||||
(specifically std::unique_ptrs) in the native class since they can be null.
|
||||
This attribute changes the member declaration to use the type directly
|
||||
rather than wrapped in a unique_ptr.
|
||||
|
||||
- `native_default`: "value" (on a field): For members that are declared
|
||||
"native_inline", the value specified with this attribute will be included
|
||||
verbatim in the class constructor initializer list for this member.
|
||||
|
||||
- `native_type`' "type" (on a struct): In some cases, a more optimal C++ data
|
||||
type exists for a given struct. For example, the following schema:
|
||||
|
||||
struct Vec2 {
|
||||
x: float;
|
||||
y: float;
|
||||
}
|
||||
|
||||
generates the following Object-Based API class:
|
||||
|
||||
struct Vec2T : flatbuffers::NativeTable {
|
||||
float x;
|
||||
float y;
|
||||
};
|
||||
|
||||
However, it can be useful to instead use a user-defined C++ type since it
|
||||
can provide more functionality, eg.
|
||||
|
||||
struct vector2 {
|
||||
float x = 0, y = 0;
|
||||
vector2 operator+(vector2 rhs) const { ... }
|
||||
vector2 operator-(vector2 rhs) const { ... }
|
||||
float length() const { ... }
|
||||
// etc.
|
||||
};
|
||||
|
||||
The `native_type` attribute will replace the usage of the generated class
|
||||
with the given type. So, continuing with the example, the generated
|
||||
code would use |vector2| in place of |Vec2T| for all generated code.
|
||||
|
||||
However, becuase the native_type is unknown to flatbuffers, the user must
|
||||
provide the following functions to aide in the serialization process:
|
||||
|
||||
namespace flatbuffers {
|
||||
FlatbufferStruct Pack(const native_type& obj);
|
||||
native_type UnPack(const FlatbufferStruct& obj);
|
||||
}
|
||||
|
||||
Finally, the following top-level attribute
|
||||
|
||||
- native_include: "path" (at file level): Because the `native_type` attribute
|
||||
can be used to introduce types that are unknown to flatbuffers, it may be
|
||||
necessary to include "external" header files in the generated code. This
|
||||
attribute can be used to directly add an #include directive to the top of
|
||||
the generated code that includes the specified path directly.
|
||||
|
||||
# External references.
|
||||
|
||||
An additional feature of the object API is the ability to allow you to load
|
||||
@@ -134,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
|
||||
@@ -156,6 +231,30 @@ schema, as well as a lot of helper functions.
|
||||
And example of usage, for the time being, can be found in
|
||||
`test.cpp/ReflectionTest()`.
|
||||
|
||||
## Mini Reflection
|
||||
|
||||
A more limited form of reflection is available for direct inclusion in
|
||||
generated code, which doesn't any (binary) schema access at all. It was designed
|
||||
to keep the overhead of reflection as low as possible (on the order of 2-6
|
||||
bytes per field added to your executable), but doesn't contain all the
|
||||
information the (binary) schema contains.
|
||||
|
||||
You add this information to your generated code by specifying `--reflect-types`
|
||||
(or instead `--reflect-names` if you also want field / enum names).
|
||||
|
||||
You can now use this information, for example to print a FlatBuffer to text:
|
||||
|
||||
auto s = flatbuffers::FlatBufferToString(flatbuf, MonsterTypeTable());
|
||||
|
||||
`MonsterTypeTable()` is declared in the generated code for each type. The
|
||||
string produced is very similar to the JSON produced by the `Parser` based
|
||||
text generator.
|
||||
|
||||
You'll need `flatbuffers/minireflect.h` for this functionality. In there is also
|
||||
a convenient visitor/iterator so you can write your own output / functionality
|
||||
based on the mini reflection tables without having to know the FlatBuffers or
|
||||
reflection encoding.
|
||||
|
||||
## Storing maps / dictionaries in a FlatBuffer
|
||||
|
||||
FlatBuffers doesn't support maps natively, but there is support to
|
||||
@@ -336,4 +435,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>
|
||||
|
||||
@@ -78,6 +78,9 @@ inefficiency, but also forces you to write *more* code to access data
|
||||
In this context, it is only a better choice for systems that have very
|
||||
little to no information ahead of time about what data needs to be stored.
|
||||
|
||||
If you do need to store data that doesn't fit a schema, FlatBuffers also
|
||||
offers a schema-less (self-describing) version!
|
||||
|
||||
Read more about the "why" of FlatBuffers in the
|
||||
[white paper](@ref flatbuffers_white_paper).
|
||||
|
||||
@@ -138,6 +141,8 @@ sections provide a more in-depth usage guide.
|
||||
using FlatBuffers.
|
||||
- A [white paper](@ref flatbuffers_white_paper) explaining the "why" of
|
||||
FlatBuffers.
|
||||
- How to use the [schema-less](@ref flexbuffers) version of
|
||||
FlatBuffers.
|
||||
- A description of the [internals](@ref flatbuffers_internals) of FlatBuffers.
|
||||
- A formal [grammar](@ref flatbuffers_grammar) of the schema language.
|
||||
|
||||
|
||||
166
docs/source/FlexBuffers.md
Normal file
166
docs/source/FlexBuffers.md
Normal file
@@ -0,0 +1,166 @@
|
||||
FlexBuffers {#flexbuffers}
|
||||
==========
|
||||
|
||||
FlatBuffers was designed around schemas, because when you want maximum
|
||||
performance and data consistency, strong typing is helpful.
|
||||
|
||||
There are however times when you want to store data that doesn't fit a
|
||||
schema, because you can't know ahead of time what all needs to be stored.
|
||||
|
||||
For this, FlatBuffers has a dedicated format, called FlexBuffers.
|
||||
This is a binary format that can be used in conjunction
|
||||
with FlatBuffers (by storing a part of a buffer in FlexBuffers
|
||||
format), or also as its own independent serialization format.
|
||||
|
||||
While it loses the strong typing, you retain the most unique advantage
|
||||
FlatBuffers has over other serialization formats (schema-based or not):
|
||||
FlexBuffers can also be accessed without parsing / copying / object allocation.
|
||||
This is a huge win in efficiency / memory friendly-ness, and allows unique
|
||||
use cases such as mmap-ing large amounts of free-form data.
|
||||
|
||||
FlexBuffers' design and implementation allows for a very compact encoding,
|
||||
combining automatic pooling of strings with automatic sizing of containers to
|
||||
their smallest possible representation (8/16/32/64 bits). Many values and
|
||||
offsets can be encoded in just 8 bits. While a schema-less representation is
|
||||
usually more bulky because of the need to be self-descriptive, FlexBuffers
|
||||
generates smaller binaries for many cases than regular FlatBuffers.
|
||||
|
||||
FlexBuffers is still slower than regular FlatBuffers though, so we recommend to
|
||||
only use it if you need it.
|
||||
|
||||
|
||||
# Usage
|
||||
|
||||
This is for C++, other languages may follow.
|
||||
|
||||
Include the header `flexbuffers.h`, which in turn depends on `flatbuffers.h`
|
||||
and `util.h`.
|
||||
|
||||
To create a buffer:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
flexbuffers::Builder fbb;
|
||||
fbb.Int(13);
|
||||
fbb.Finish();
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
You create any value, followed by `Finish`. Unlike FlatBuffers which requires
|
||||
the root value to be a table, here any value can be the root, including a lonely
|
||||
int value.
|
||||
|
||||
You can now access the `std::vector<uint8_t>` that contains the encoded value
|
||||
as `fbb.GetBuffer()`. Write it, send it, or store it in a parent FlatBuffer. In
|
||||
this case, the buffer is just 3 bytes in size.
|
||||
|
||||
To read this value back, you could just say:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
auto root = flexbuffers::GetRoot(my_buffer);
|
||||
int64_t i = root.AsInt64();
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
FlexBuffers stores ints only as big as needed, so it doesn't differentiate
|
||||
between different sizes of ints. You can ask for the 64 bit version,
|
||||
regardless of what you put in. In fact, since you demand to read the root
|
||||
as an int, if you supply a buffer that actually contains a float, or a
|
||||
string with numbers in it, it will convert it for you on the fly as well,
|
||||
or return 0 if it can't. If instead you actually want to know what is inside
|
||||
the buffer before you access it, you can call `root.GetType()` or `root.IsInt()`
|
||||
etc.
|
||||
|
||||
Here's a slightly more complex value you could write instead of `fbb.Int` above:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
fbb.Map([&]() {
|
||||
fbb.Vector("vec", [&]() {
|
||||
fbb.Int(-100);
|
||||
fbb.String("Fred");
|
||||
fbb.IndirectFloat(4.0f);
|
||||
});
|
||||
fbb.UInt("foo", 100);
|
||||
});
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This stores the equivalent of the JSON value
|
||||
`{ vec: [ -100, "Fred", 4.0 ], foo: 100 }`. The root is a dictionary that has
|
||||
just two key-value pairs, with keys `vec` and `foo`. Unlike FlatBuffers, it
|
||||
actually has to store these keys in the buffer (which it does only once if
|
||||
you store multiple such objects, by pooling key values), but also unlike
|
||||
FlatBuffers it has no restriction on the keys (fields) that you use.
|
||||
|
||||
The map constructor uses a C++11 Lambda to group its children, but you can
|
||||
also use more conventional start/end calls if you prefer.
|
||||
|
||||
The first value in the map is a vector. You'll notice that unlike FlatBuffers,
|
||||
you can use mixed types. There is also a `TypedVector` variant that only
|
||||
allows a single type, and uses a bit less memory.
|
||||
|
||||
`IndirectFloat` is an interesting feature that allows you to store values
|
||||
by offset rather than inline. Though that doesn't make any visible change
|
||||
to the user, the consequence is that large values (especially doubles or
|
||||
64 bit ints) that occur more than once can be shared. Another use case is
|
||||
inside of vectors, where the largest element makes up the size of all elements
|
||||
(e.g. a single double forces all elements to 64bit), so storing a lot of small
|
||||
integers together with a double is more efficient if the double is indirect.
|
||||
|
||||
Accessing it:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||
auto map = flexbuffers::GetRoot(my_buffer).AsMap();
|
||||
map.size(); // 2
|
||||
auto vec = map["vec"].AsVector();
|
||||
vec.size(); // 3
|
||||
vec[0].AsInt64(); // -100;
|
||||
vec[1].AsString().c_str(); // "Fred";
|
||||
vec[1].AsInt64(); // 0 (Number parsing failed).
|
||||
vec[2].AsDouble(); // 4.0
|
||||
vec[2].AsString().IsTheEmptyString(); // true (Wrong Type).
|
||||
vec[2].AsString().c_str(); // "" (This still works though).
|
||||
vec[2].ToString().c_str(); // "4" (Or have it converted).
|
||||
map["foo"].AsUInt8(); // 100
|
||||
map["unknown"].IsNull(); // true
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
# Binary encoding
|
||||
|
||||
A description of how FlexBuffers are encoded is in the
|
||||
[internals](@ref flatbuffers_internals) 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
|
||||
|
||||
* Vectors generally are a lot more efficient than maps, so prefer them over maps
|
||||
when possible for small objects. Instead of a map with keys `x`, `y` and `z`,
|
||||
use a vector. Better yet, use a typed vector. Or even better, use a fixed
|
||||
size typed vector.
|
||||
* Maps are backwards compatible with vectors, and can be iterated as such.
|
||||
You can iterate either just the values (`map.Values()`), or in parallel with
|
||||
the keys vector (`map.Keys()`). If you intend
|
||||
to access most or all elements, this is faster than looking up each element
|
||||
by key, since that involves a binary search of the key vector.
|
||||
* When possible, don't mix values that require a big bit width (such as double)
|
||||
in a large vector of smaller values, since all elements will take on this
|
||||
width. Use `IndirectDouble` when this is a possibility. Note that
|
||||
integers automatically use the smallest width possible, i.e. if you ask
|
||||
to serialize an int64_t whose value is actually small, you will use less
|
||||
bits. Doubles are represented as floats whenever possible losslessly, but
|
||||
this is only possible for few values.
|
||||
Since nested vectors/maps are stored over offsets, they typically don't
|
||||
affect the vector width.
|
||||
* To store large arrays of byte data, use a blob. If you'd use a typed
|
||||
vector, the bit width of the size field may make it use more space than
|
||||
expected, and may not be compatible with `memcpy`.
|
||||
Similarly, large arrays of (u)int16_t may be better off stored as a
|
||||
binary blob if their size could exceed 64k elements.
|
||||
Construction and use are otherwise similar to strings.
|
||||
25
docs/source/Grammar.md
Executable file → Normal file
25
docs/source/Grammar.md
Executable file → Normal file
@@ -4,7 +4,7 @@ Grammar of the schema language {#flatbuffers_grammar}
|
||||
schema = include*
|
||||
( namespace\_decl | type\_decl | enum\_decl | root\_decl |
|
||||
file_extension_decl | file_identifier_decl |
|
||||
attribute\_decl | object )*
|
||||
attribute\_decl | rpc\_decl | object )*
|
||||
|
||||
include = `include` string\_constant `;`
|
||||
|
||||
@@ -14,16 +14,22 @@ attribute\_decl = `attribute` string\_constant `;`
|
||||
|
||||
type\_decl = ( `table` | `struct` ) ident metadata `{` field\_decl+ `}`
|
||||
|
||||
enum\_decl = ( `enum` | `union` ) ident [ `:` type ] metadata `{` commasep(
|
||||
enumval\_decl ) `}`
|
||||
enum\_decl = ( `enum` ident [ `:` type ] | `union` ident ) metadata `{`
|
||||
commasep( enumval\_decl ) `}`
|
||||
|
||||
root\_decl = `root_type` ident `;`
|
||||
|
||||
field\_decl = ident `:` type [ `=` scalar ] metadata `;`
|
||||
|
||||
rpc\_decl = `rpc_service` ident `{` rpc\_method+ `}`
|
||||
|
||||
rpc\_method = ident `(` ident `)` `:` ident metadata `;`
|
||||
|
||||
type = `bool` | `byte` | `ubyte` | `short` | `ushort` | `int` | `uint` |
|
||||
`float` | `long` | `ulong` | `double`
|
||||
| `string` | `[` type `]` | ident
|
||||
`float` | `long` | `ulong` | `double` |
|
||||
`int8` | `uint8` | `int16` | `uint16` | `int32` | `uint32`| `int64` | `uint64` |
|
||||
`float32` | `float64` |
|
||||
`string` | `[` type `]` | ident
|
||||
|
||||
enumval\_decl = ident [ `=` integer\_constant ]
|
||||
|
||||
@@ -43,6 +49,11 @@ file_extension_decl = `file_extension` string\_constant `;`
|
||||
|
||||
file_identifier_decl = `file_identifier` string\_constant `;`
|
||||
|
||||
integer\_constant = -?[0-9]+ | `true` | `false`
|
||||
integer\_constant = `-?[0-9]+` | `true` | `false`
|
||||
|
||||
float\_constant = `-?[0-9]+.[0-9]+((e|E)(+|-)?[0-9]+)?`
|
||||
|
||||
string\_constant = `\".*?\"`
|
||||
|
||||
ident = `[a-zA-Z_][a-zA-Z0-9_]*`
|
||||
|
||||
float\_constant = -?[0-9]+.[0-9]+((e|E)(+|-)?[0-9]+)?
|
||||
|
||||
154
docs/source/Internals.md
Executable file → Normal file
154
docs/source/Internals.md
Executable file → Normal file
@@ -292,4 +292,158 @@ flexibility in which of the children of root object to write first (though in
|
||||
this case there's only one string), and what order to write the fields in.
|
||||
Different orders may also cause different alignments to happen.
|
||||
|
||||
### Additional reading.
|
||||
|
||||
The author of the C language implementation has made a similar
|
||||
[document](https://github.com/dvidelabs/flatcc/blob/master/doc/binary-format.md#flatbuffers-binary-format)
|
||||
that may further help clarify the format.
|
||||
|
||||
# FlexBuffers
|
||||
|
||||
The [schema-less](@ref flexbuffers) version of FlatBuffers have their
|
||||
own encoding, detailed here.
|
||||
|
||||
It shares many properties mentioned above, in that all data is accessed
|
||||
over offsets, all scalars are aligned to their own size, and
|
||||
all data is always stored in little endian format.
|
||||
|
||||
One difference is that FlexBuffers are built front to back, so children are
|
||||
stored before parents, and the root of the data starts at the last byte.
|
||||
|
||||
Another difference is that scalar data is stored with a variable number of bits
|
||||
(8/16/32/64). The current width is always determined by the *parent*, i.e. if
|
||||
the scalar sits in a vector, the vector determines the bit width for all
|
||||
elements at once. Selecting the minimum bit width for a particular vector is
|
||||
something the encoder does automatically and thus is typically of no concern
|
||||
to the user, though being aware of this feature (and not sticking a double in
|
||||
the same vector as a bunch of byte sized elements) is helpful for efficiency.
|
||||
|
||||
Unlike FlatBuffers there is only one kind of offset, and that is an unsigned
|
||||
integer indicating the number of bytes in a negative direction from the address
|
||||
of itself (where the offset is stored).
|
||||
|
||||
### Vectors
|
||||
|
||||
The representation of the vector is at the core of how FlexBuffers works (since
|
||||
maps are really just a combination of 2 vectors), so it is worth starting there.
|
||||
|
||||
As mentioned, a vector is governed by a single bit width (supplied by its
|
||||
parent). This includes the size field. For example, a vector that stores the
|
||||
integer values `1, 2, 3` is encoded as follows:
|
||||
|
||||
uint8_t 3, 1, 2, 3, 4, 4, 4
|
||||
|
||||
The first `3` is the size field, and is placed before the vector (an offset
|
||||
from the parent to this vector points to the first element, not the size
|
||||
field, so the size field is effectively at index -1).
|
||||
Since this is an untyped vector `SL_VECTOR`, it is followed by 3 type
|
||||
bytes (one per element of the vector), which are always following the vector,
|
||||
and are always a uint8_t even if the vector is made up of bigger scalars.
|
||||
|
||||
### Types
|
||||
|
||||
A type byte is made up of 2 components (see flexbuffers.h for exact values):
|
||||
|
||||
* 2 lower bits representing the bit-width of the child (8, 16, 32, 64).
|
||||
This is only used if the child is accessed over an offset, such as a child
|
||||
vector. It is ignored for inline types.
|
||||
* 6 bits representing the actual type (see flexbuffers.h).
|
||||
|
||||
Thus, in this example `4` means 8 bit child (value 0, unused, since the value is
|
||||
in-line), type `SL_INT` (value 1).
|
||||
|
||||
### Typed Vectors
|
||||
|
||||
These are like the Vectors above, but omit the type bytes. The type is instead
|
||||
determined by the vector type supplied by the parent. Typed vectors are only
|
||||
available for a subset of types for which these savings can be significant,
|
||||
namely inline signed/unsigned integers (`TYPE_VECTOR_INT` / `TYPE_VECTOR_UINT`),
|
||||
floats (`TYPE_VECTOR_FLOAT`), and keys (`TYPE_VECTOR_KEY`, see below).
|
||||
|
||||
Additionally, for scalars, there are fixed length vectors of sizes 2 / 3 / 4
|
||||
that don't store the size (`TYPE_VECTOR_INT2` etc.), for an additional savings
|
||||
in space when storing common vector or color data.
|
||||
|
||||
### Scalars
|
||||
|
||||
FlexBuffers supports integers (`TYPE_INT` and `TYPE_UINT`) and floats
|
||||
(`TYPE_FLOAT`), available in the bit-widths mentioned above. They can be stored
|
||||
both inline and over an offset (`TYPE_INDIRECT_*`).
|
||||
|
||||
The offset version is useful to encode costly 64bit (or even 32bit) quantities
|
||||
into vectors / maps of smaller sizes, and to share / repeat a value multiple
|
||||
times.
|
||||
|
||||
### Booleans and Nulls
|
||||
|
||||
Booleans (`TYPE_BOOL`) and nulls (`TYPE_NULL`) are encoded as inlined unsigned integers.
|
||||
|
||||
### Blobs, Strings and Keys.
|
||||
|
||||
A blob (`TYPE_BLOB`) is encoded similar to a vector, with one difference: the
|
||||
elements are always `uint8_t`. The parent bit width only determines the width of
|
||||
the size field, allowing blobs to be large without the elements being large.
|
||||
|
||||
Strings (`TYPE_STRING`) are similar to blobs, except they have an additional 0
|
||||
termination byte for convenience, and they MUST be UTF-8 encoded (since an
|
||||
accessor in a language that does not support pointers to UTF-8 data may have to
|
||||
convert them to a native string type).
|
||||
|
||||
A "Key" (`TYPE_KEY`) is similar to a string, but doesn't store the size
|
||||
field. They're so named because they are used with maps, which don't care
|
||||
for the size, and can thus be even more compact. Unlike strings, keys cannot
|
||||
contain bytes of value 0 as part of their data (size can only be determined by
|
||||
`strlen`), so while you can use them outside the context of maps if you so
|
||||
desire, you're usually better off with strings.
|
||||
|
||||
### Maps
|
||||
|
||||
A map (`TYPE_MAP`) is like an (untyped) vector, but with 2 prefixes before the
|
||||
size field:
|
||||
|
||||
| index | field |
|
||||
| ----: | :----------------------------------------------------------- |
|
||||
| -3 | An offset to the keys vector (may be shared between tables). |
|
||||
| -2 | Byte width of the keys vector. |
|
||||
| -1 | Size (from here on it is compatible with `TYPE_VECTOR`) |
|
||||
| 0 | Elements. |
|
||||
| Size | Types. |
|
||||
|
||||
Since a map is otherwise the same as a vector, it can be iterated like
|
||||
a vector (which is probably faster than lookup by key).
|
||||
|
||||
The keys vector is a typed vector of keys. Both the keys and corresponding
|
||||
values *have* to be stored in sorted order (as determined by `strcmp`), such
|
||||
that lookups can be made using binary search.
|
||||
|
||||
The reason the key vector is a seperate structure from the value vector is
|
||||
such that it can be shared between multiple value vectors, and also to
|
||||
allow it to be treated as its own individual vector in code.
|
||||
|
||||
An example map { foo: 13, bar: 14 } would be encoded as:
|
||||
|
||||
0 : uint8_t 'b', 'a', 'r', 0
|
||||
4 : uint8_t 'f', 'o', 'o', 0
|
||||
8 : uint8_t 2 // key vector of size 2
|
||||
// key vector offset points here
|
||||
9 : uint8_t 9, 6 // offsets to bar_key and foo_key
|
||||
11: uint8_t 2, 1 // offset to key vector, and its byte width
|
||||
13: uint8_t 2 // value vector of size
|
||||
// value vector offset points here
|
||||
14: uint8_t 14, 13 // values
|
||||
16: uint8_t 4, 4 // types
|
||||
|
||||
### The root
|
||||
|
||||
As mentioned, the root starts at the end of the buffer.
|
||||
The last uint8_t is the width in bytes of the root (normally the parent
|
||||
determines the width, but the root has no parent). The uint8_t before this is
|
||||
the type of the root, and the bytes before that are the root value (of the
|
||||
number of bytes specified by the last byte).
|
||||
|
||||
So for example, the integer value `13` as root would be:
|
||||
|
||||
uint8_t 13, 4, 1 // Value, type, root byte width.
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
19
docs/source/JavaCsharpUsage.md
Executable file → Normal file
19
docs/source/JavaCsharpUsage.md
Executable file → Normal file
@@ -139,7 +139,7 @@ can have fast lookups directly from a FlatBuffer without having to unpack
|
||||
your data into a `Dictionary` or similar.
|
||||
|
||||
To use it:
|
||||
- Designate one of the fields in a table as they "key" field. You do this
|
||||
- Designate one of the fields in a table as the "key" field. You do this
|
||||
by setting the `key` attribute on this field, e.g.
|
||||
`name:string (key)`.
|
||||
You may only have one key field, and it must be of string or scalar type.
|
||||
@@ -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
|
||||
|
||||
|
||||
0
docs/source/JavaScriptUsage.md
Executable file → Normal file
0
docs/source/JavaScriptUsage.md
Executable file → Normal file
27
docs/source/PythonUsage.md
Executable file → Normal file
27
docs/source/PythonUsage.md
Executable file → Normal file
@@ -64,6 +64,33 @@ Now you can access values like this:
|
||||
pos = monster.Pos()
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
## Support for Numpy arrays
|
||||
|
||||
The Flatbuffers python library also has support for accessing scalar
|
||||
vectors as numpy arrays. This can be orders of magnitude faster than
|
||||
iterating over the vector one element at a time, and is particularly
|
||||
useful when unpacking large nested flatbuffers. The generated code for
|
||||
a scalar vector will have a method `<vector name>AsNumpy()`. In the
|
||||
case of the Monster example, you could access the inventory vector
|
||||
like this:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py}
|
||||
inventory = monster.InventoryAsNumpy()
|
||||
# inventory is a numpy array of type np.dtype('uint8')
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
instead of
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py}
|
||||
inventory = []
|
||||
for i in range(monster.InventoryLength()):
|
||||
inventory.append(int(monster.Inventory(i)))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Numpy is not a requirement. If numpy is not installed on your system,
|
||||
then attempting to access one of the `*asNumpy()` methods will result
|
||||
in a `NumpyRequiredForThisFeature` exception.
|
||||
|
||||
## Text Parsing
|
||||
|
||||
There currently is no support for parsing text (Schema's and JSON) directly
|
||||
|
||||
35
docs/source/Schemas.md
Executable file → Normal file
35
docs/source/Schemas.md
Executable file → Normal file
@@ -84,15 +84,19 @@ parent object, and use no virtual table).
|
||||
|
||||
### Types
|
||||
|
||||
Built-in scalar types are:
|
||||
Built-in scalar types are
|
||||
|
||||
- 8 bit: `byte`, `ubyte`, `bool`
|
||||
- 8 bit: `byte` (`int8`), `ubyte` (`uint8`), `bool`
|
||||
|
||||
- 16 bit: `short`, `ushort`
|
||||
- 16 bit: `short` (`int16`), `ushort` (`uint16`)
|
||||
|
||||
- 32 bit: `int`, `uint`, `float`
|
||||
- 32 bit: `int` (`int32`), `uint` (`uint32`), `float` (`float32`)
|
||||
|
||||
- 64 bit: `long`, `ulong`, `double`
|
||||
- 64 bit: `long` (`int64`), `ulong` (`uint64`), `double` (`float64`)
|
||||
|
||||
The type names in parentheses are alias names such that for example
|
||||
`uint8` can be used in place of `ubyte`, and `int32` can be used in
|
||||
place of `int` without affecting code generation.
|
||||
|
||||
Built-in non-scalar types:
|
||||
|
||||
@@ -158,6 +162,10 @@ If you have a need to distinguish between different FlatBuffers in a more
|
||||
open-ended way, for example for use as files, see the file identification
|
||||
feature below.
|
||||
|
||||
There is an experimental support only in C++ for a vector of unions
|
||||
(and types). In the example IDL file above, use [Any] to add a
|
||||
vector of Any to Monster table.
|
||||
|
||||
### Namespaces
|
||||
|
||||
These will generate the corresponding namespace in C++ for all helper
|
||||
@@ -274,7 +282,10 @@ Current understood attributes:
|
||||
IDs allow the fields to be placed in any order in the schema.
|
||||
When a new field is added to the schema it must use the next available ID.
|
||||
- `deprecated` (on a field): do not generate accessors for this field
|
||||
anymore, code should stop using this data.
|
||||
anymore, code should stop using this data. Old data may still contain this
|
||||
field, but it won't be accessible anymore by newer code. Note that if you
|
||||
deprecate a field that was previous required, old code may fail to validate
|
||||
new data (when using the optional verifier).
|
||||
- `required` (on a non-scalar table field): this field must always be set.
|
||||
By default, all fields are optional, i.e. may be left out. This is
|
||||
desirable, as it helps with forwards/backwards compatibility, and
|
||||
@@ -284,7 +295,10 @@ Current understood attributes:
|
||||
constructs FlatBuffers to ensure this field is initialized, so the reading
|
||||
code may access it directly, without checking for NULL. If the constructing
|
||||
code does not initialize this field, they will get an assert, and also
|
||||
the verifier will fail on buffers that have missing required fields.
|
||||
the verifier will fail on buffers that have missing required fields. Note
|
||||
that if you add this attribute to an existing field, this will only be
|
||||
valid if existing data always contains this field / existing code always
|
||||
writes this field.
|
||||
- `force_align: size` (on a struct): force the alignment of this struct
|
||||
to be something higher than what it is naturally aligned to. Causes
|
||||
these structs to be aligned to that amount inside a buffer, IF that
|
||||
@@ -298,6 +312,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.
|
||||
@@ -309,6 +326,10 @@ Current understood attributes:
|
||||
to be stored in any particular order, they are often optimized for
|
||||
space by sorting them to size. This attribute stops that from happening.
|
||||
There should generally not be any reason to use this flag.
|
||||
- 'native_*'. Several attributes have been added to support the [C++ object
|
||||
Based API](@ref flatbuffers_cpp_object_based_api). All such attributes
|
||||
are prefixed with the term "native_".
|
||||
|
||||
|
||||
## JSON Parsing
|
||||
|
||||
|
||||
0
docs/source/Support.md
Executable file → Normal file
0
docs/source/Support.md
Executable file → Normal file
@@ -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 {
|
||||
@@ -209,12 +210,21 @@ The `Weapon` table is a sub-table used within our FlatBuffer. It is
|
||||
used twice: once within the `Monster` table and once within the `Equipment`
|
||||
enum. For our `Monster`, it is used to populate a `vector of tables` via the
|
||||
`weapons` field within our `Monster`. It is also the only table referenced by
|
||||
the `Equipment` enum.
|
||||
the `Equipment` union.
|
||||
|
||||
The last part of the `schema` is the `root_type`. The root type declares what
|
||||
will be the root table for the serialized data. In our case, the root type is
|
||||
our `Monster` table.
|
||||
|
||||
The scalar types can also use alias type names such as `int16` instead
|
||||
of `short` and `float32` instead of `float`. Thus we could also write
|
||||
the `Weapon` table as:
|
||||
|
||||
table Weapon {
|
||||
name:string;
|
||||
damage:int16;
|
||||
}
|
||||
|
||||
#### More Information About Schemas
|
||||
|
||||
You can find a complete guide to writing `schema` files in the
|
||||
@@ -603,7 +613,7 @@ traversal. This is generally easy to do on any tree structures.
|
||||
|
||||
// Create a `vector` representing the inventory of the Orc. Each number
|
||||
// could correspond to an item that can be claimed after he is slain.
|
||||
unsigned char treasure = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
unsigned char treasure[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
auto inventory = builder.CreateVector(treasure, 10);
|
||||
~~~
|
||||
</div>
|
||||
@@ -709,6 +719,10 @@ adding fields to our monster.
|
||||
other `vector`s), collect their offsets into a temporary data structure, and
|
||||
then create an additional `vector` containing their offsets.*
|
||||
|
||||
If instead of creating a vector from an existing array you serialize elements
|
||||
individually one by one, take care to note that this happens in reverse order,
|
||||
as buffers are built back to front.
|
||||
|
||||
For example, take a look at the two `Weapon`s that we created earlier (`Sword`
|
||||
and `Axe`). These are both FlatBuffer `table`s, whose offsets we now store in
|
||||
memory. Therefore we can create a FlatBuffer `vector` to contain these
|
||||
@@ -799,6 +813,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 = builder.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.Sample.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.Sample.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 +890,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 +905,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 +921,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 +937,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 +956,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 +973,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 +990,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 +1005,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 +1013,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
|
||||
@@ -953,13 +1037,14 @@ a bit more flexibility.
|
||||
// manually.
|
||||
MonsterBuilder monster_builder(builder);
|
||||
monster_builder.add_pos(&pos);
|
||||
auto pos = Vec3(1.0f, 2.0f, 3.0f);
|
||||
monster_builder.add_hp(hp);
|
||||
monster_builder.add_name(name);
|
||||
monster_builder.add_inventory(inventory);
|
||||
monster_builder.add_color(Color_Red);
|
||||
monster_builder.add_weapons(weapons);
|
||||
monster_builder.add_equipped_type(Equipment_Weapon);
|
||||
monster_builder.add_equpped(axe);
|
||||
monster_builder.add_equpped(axe.Union());
|
||||
auto orc = monster_builder.Finish();
|
||||
~~~
|
||||
</div>
|
||||
@@ -1091,7 +1176,7 @@ appropriate `finish` method.
|
||||
<div class="language-javascript">
|
||||
~~~{.js}
|
||||
// Call `finish()` to instruct the builder that this monster is complete.
|
||||
builder.finish(orc); // You could also call `MyGame.Example.Monster.finishMonsterBuffer(builder,
|
||||
builder.finish(orc); // You could also call `MyGame.Sample.Monster.finishMonsterBuffer(builder,
|
||||
// orc);`.
|
||||
~~~
|
||||
</div>
|
||||
@@ -1309,6 +1394,8 @@ won't work**
|
||||
|
||||
// `monster` is of type `Monster *`.
|
||||
// Note: root object pointers are NOT the same as `buffer_pointer`.
|
||||
// `GetMonster` is a convenience function that calls `GetRoot<Monster>`,
|
||||
// the latter is also available for non-root types.
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-java">
|
||||
@@ -1470,10 +1557,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 +1634,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 +1691,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 +1774,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
|
||||
|
||||
0
docs/source/WhitePaper.md
Executable file → Normal file
0
docs/source/WhitePaper.md
Executable file → Normal file
8
docs/source/doxyfile
Executable file → Normal file
8
docs/source/doxyfile
Executable file → Normal file
@@ -759,11 +759,13 @@ INPUT = "FlatBuffers.md" \
|
||||
"Support.md" \
|
||||
"Benchmarks.md" \
|
||||
"WhitePaper.md" \
|
||||
"FlexBuffers.md" \
|
||||
"Internals.md" \
|
||||
"Grammar.md" \
|
||||
"../../CONTRIBUTING.md" \
|
||||
"Tutorial.md" \
|
||||
"GoApi.md" \
|
||||
"gRPC/CppUsage.md" \
|
||||
"groups" \
|
||||
"../../java/com/google/flatbuffers" \
|
||||
"../../python/flatbuffers/builder.py" \
|
||||
@@ -882,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
|
||||
|
||||
@@ -37,6 +37,12 @@
|
||||
title="Use in PHP"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_python"
|
||||
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
|
||||
@@ -110,6 +110,11 @@ func (b *Builder) WriteVtable() (n UOffsetT) {
|
||||
objectOffset := b.Offset()
|
||||
existingVtable := UOffsetT(0)
|
||||
|
||||
// Trim vtable of trailing zeroes.
|
||||
i := len(b.vtable) - 1;
|
||||
for ; i >= 0 && b.vtable[i] == 0; i-- {}
|
||||
b.vtable = b.vtable[:i + 1];
|
||||
|
||||
// Search backwards through existing vtables, because similar vtables
|
||||
// are likely to have been recently appended. See
|
||||
// BenchmarkVtableDeduplication for a case in which this heuristic
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package flatbuffers
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -10,7 +10,7 @@ type Table struct {
|
||||
|
||||
// Offset provides access into the Table's vtable.
|
||||
//
|
||||
// Deprecated fields are ignored by checking against the vtable's length.
|
||||
// Fields which are deprecated are ignored by checking against the vtable's length.
|
||||
func (t *Table) Offset(vtableOffset VOffsetT) VOffsetT {
|
||||
vtable := UOffsetT(SOffsetT(t.Pos) - t.GetSOffsetT(t.Pos))
|
||||
if vtableOffset < t.GetVOffsetT(vtable) {
|
||||
|
||||
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,13 +44,21 @@ 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
|
||||
grpc::string unexportName(grpc::string s) {
|
||||
if (s.empty())
|
||||
return s;
|
||||
s[0] = std::tolower(s[0]);
|
||||
s[0] = static_cast<char>(std::tolower(s[0]));
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -58,7 +66,7 @@ grpc::string unexportName(grpc::string s) {
|
||||
grpc::string exportName(grpc::string s) {
|
||||
if (s.empty())
|
||||
return s;
|
||||
s[0] = std::toupper(s[0]);
|
||||
s[0] = static_cast<char>(std::toupper(s[0]));
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
233
include/flatbuffers/base.h
Normal file
233
include/flatbuffers/base.h
Normal file
@@ -0,0 +1,233 @@
|
||||
#ifndef FLATBUFFERS_BASE_H_
|
||||
#define FLATBUFFERS_BASE_H_
|
||||
|
||||
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
|
||||
defined(_MSC_VER) && defined(_DEBUG)
|
||||
#define _CRTDBG_MAP_ALLOC
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifndef ARDUINO
|
||||
#include <cstdint>
|
||||
#endif
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
|
||||
defined(_MSC_VER) && defined(_DEBUG)
|
||||
#include <crtdbg.h>
|
||||
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
|
||||
#define new DEBUG_NEW
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H)
|
||||
#include <utility.h>
|
||||
#else
|
||||
#include <utility>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#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
|
||||
|
||||
#include "flatbuffers/stl_emulation.h"
|
||||
|
||||
/// @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 8
|
||||
#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 EndianSwap(T t) {
|
||||
#if defined(_MSC_VER)
|
||||
#define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
|
||||
#define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
|
||||
#define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
|
||||
#else
|
||||
#if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__)
|
||||
// __builtin_bswap16 was missing prior to GCC 4.8.
|
||||
#define FLATBUFFERS_BYTESWAP16(x) \
|
||||
static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16))
|
||||
#else
|
||||
#define FLATBUFFERS_BYTESWAP16 __builtin_bswap16
|
||||
#endif
|
||||
#define FLATBUFFERS_BYTESWAP32 __builtin_bswap32
|
||||
#define FLATBUFFERS_BYTESWAP64 __builtin_bswap64
|
||||
#endif
|
||||
if (sizeof(T) == 1) { // Compile-time if-then's.
|
||||
return t;
|
||||
} else if (sizeof(T) == 2) {
|
||||
union { T t; uint16_t i; } u;
|
||||
u.t = t;
|
||||
u.i = FLATBUFFERS_BYTESWAP16(u.i);
|
||||
return u.t;
|
||||
} else if (sizeof(T) == 4) {
|
||||
union { T t; uint32_t i; } u;
|
||||
u.t = t;
|
||||
u.i = FLATBUFFERS_BYTESWAP32(u.i);
|
||||
return u.t;
|
||||
} else if (sizeof(T) == 8) {
|
||||
union { T t; uint64_t i; } u;
|
||||
u.t = t;
|
||||
u.i = FLATBUFFERS_BYTESWAP64(u.i);
|
||||
return u.t;
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
||||
#endif // FLATBUFFERS_BASE_H_
|
||||
@@ -17,25 +17,63 @@
|
||||
#ifndef FLATBUFFERS_CODE_GENERATORS_H_
|
||||
#define FLATBUFFERS_CODE_GENERATORS_H_
|
||||
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include "flatbuffers/idl.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// Utility class to assist in generating code through use of text templates.
|
||||
//
|
||||
// Example code:
|
||||
// CodeWriter code;
|
||||
// code.SetValue("NAME", "Foo");
|
||||
// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
|
||||
// code.SetValue("NAME", "Bar");
|
||||
// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
|
||||
// std::cout << code.ToString() << std::endl;
|
||||
//
|
||||
// Output:
|
||||
// void Foo() { printf("%s", "Foo"); }
|
||||
// void Bar() { printf("%s", "Bar"); }
|
||||
class CodeWriter {
|
||||
public:
|
||||
CodeWriter() {}
|
||||
|
||||
// Clears the current "written" code.
|
||||
void Clear() {
|
||||
stream_.str("");
|
||||
stream_.clear();
|
||||
}
|
||||
|
||||
// Associates a key with a value. All subsequent calls to operator+=, where
|
||||
// the specified key is contained in {{ and }} delimiters will be replaced by
|
||||
// the given value.
|
||||
void SetValue(const std::string& key, const std::string& value) {
|
||||
value_map_[key] = value;
|
||||
}
|
||||
|
||||
// Appends the given text to the generated code as well as a newline
|
||||
// character. Any text within {{ and }} delimeters is replaced by values
|
||||
// previously stored in the CodeWriter by calling SetValue above. The newline
|
||||
// will be suppressed if the text ends with the \\ character.
|
||||
void operator+=(std::string text);
|
||||
|
||||
// Returns the current contents of the CodeWriter as a std::string.
|
||||
std::string ToString() const { return stream_.str(); }
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> value_map_;
|
||||
std::stringstream stream_;
|
||||
};
|
||||
|
||||
class BaseGenerator {
|
||||
public:
|
||||
virtual bool generate() = 0;
|
||||
|
||||
static const std::string NamespaceDir(const Parser &parser,
|
||||
const std::string &path,
|
||||
const Namespace &ns) {
|
||||
EnsureDirExists(path.c_str());
|
||||
if (parser.opts.one_file) return path;
|
||||
std::string namespace_dir = path; // Either empty or ends in separator.
|
||||
auto &namespaces = ns.components;
|
||||
for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
|
||||
namespace_dir += *it + kPathSeparator;
|
||||
EnsureDirExists(namespace_dir.c_str());
|
||||
}
|
||||
return namespace_dir;
|
||||
}
|
||||
static std::string NamespaceDir(const Parser &parser,
|
||||
const std::string &path,
|
||||
const Namespace &ns);
|
||||
|
||||
protected:
|
||||
BaseGenerator(const Parser &parser, const std::string &path,
|
||||
@@ -46,71 +84,35 @@ class BaseGenerator {
|
||||
path_(path),
|
||||
file_name_(file_name),
|
||||
qualifying_start_(qualifying_start),
|
||||
qualifying_separator_(qualifying_separator){};
|
||||
virtual ~BaseGenerator(){};
|
||||
qualifying_separator_(qualifying_separator) {}
|
||||
virtual ~BaseGenerator() {}
|
||||
|
||||
// No copy/assign.
|
||||
BaseGenerator &operator=(const BaseGenerator &);
|
||||
BaseGenerator(const BaseGenerator &);
|
||||
|
||||
const std::string NamespaceDir(const Namespace &ns) {
|
||||
return BaseGenerator::NamespaceDir(parser_, path_, ns);
|
||||
}
|
||||
std::string NamespaceDir(const Namespace &ns) const;
|
||||
|
||||
const char *FlatBuffersGeneratedWarning() {
|
||||
return "automatically generated by the FlatBuffers compiler,"
|
||||
" do not modify\n\n";
|
||||
}
|
||||
static const char *FlatBuffersGeneratedWarning();
|
||||
|
||||
bool IsEverythingGenerated() {
|
||||
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;
|
||||
}
|
||||
static std::string FullNamespace(const char *separator, const Namespace &ns);
|
||||
|
||||
std::string FullNamespace(const char *separator, const Namespace &ns) {
|
||||
std::string namespace_name;
|
||||
auto &namespaces = ns.components;
|
||||
for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
|
||||
if (namespace_name.length()) namespace_name += separator;
|
||||
namespace_name += *it;
|
||||
}
|
||||
return namespace_name;
|
||||
}
|
||||
|
||||
const std::string LastNamespacePart(const Namespace &ns) {
|
||||
auto &namespaces = ns.components;
|
||||
if (namespaces.size())
|
||||
return *(namespaces.end() - 1);
|
||||
else
|
||||
return std::string("");
|
||||
}
|
||||
static std::string LastNamespacePart(const Namespace &ns);
|
||||
|
||||
// tracks the current namespace for early exit in WrapInNameSpace
|
||||
// c++, java and csharp returns a different namespace from
|
||||
// the following default (no early exit, always fully qualify),
|
||||
// which works for js and php
|
||||
virtual const Namespace *CurrentNameSpace() { return nullptr; }
|
||||
virtual const Namespace *CurrentNameSpace() const { return nullptr; }
|
||||
|
||||
// Ensure that a type is prefixed with its namespace whenever it is used
|
||||
// outside of its namespace.
|
||||
std::string WrapInNameSpace(const Namespace *ns, const std::string &name) {
|
||||
if (CurrentNameSpace() == ns) return name;
|
||||
std::string qualified_name = qualifying_start_;
|
||||
for (auto it = ns->components.begin(); it != ns->components.end(); ++it)
|
||||
qualified_name += *it + qualifying_separator_;
|
||||
return qualified_name + name;
|
||||
}
|
||||
std::string WrapInNameSpace(const Namespace *ns,
|
||||
const std::string &name) const;
|
||||
|
||||
std::string WrapInNameSpace(const Definition &def) {
|
||||
return WrapInNameSpace(def.defined_namespace, def.name);
|
||||
}
|
||||
std::string WrapInNameSpace(const Definition &def) const;
|
||||
|
||||
std::string GetNameSpace(const Definition &def) const;
|
||||
|
||||
const Parser &parser_;
|
||||
const std::string &path_;
|
||||
@@ -119,6 +121,17 @@ class BaseGenerator {
|
||||
const std::string qualifying_separator_;
|
||||
};
|
||||
|
||||
struct CommentConfig {
|
||||
const char *first_line;
|
||||
const char *content_line_prefix;
|
||||
const char *last_line;
|
||||
};
|
||||
|
||||
extern void GenComment(const std::vector<std::string> &dc,
|
||||
std::string *code_ptr,
|
||||
const CommentConfig *config,
|
||||
const char *prefix = "");
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_CODE_GENERATORS_H_
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
97
include/flatbuffers/flatc.h
Normal file
97
include/flatbuffers/flatc.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/idl.h"
|
||||
#include "flatbuffers/util.h"
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#ifndef FLATC_H_
|
||||
#define FLATC_H_
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
class FlatCompiler {
|
||||
public:
|
||||
// Output generator for the various programming languages and formats we
|
||||
// support.
|
||||
struct Generator {
|
||||
typedef bool (*GenerateFn)(const flatbuffers::Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
typedef std::string (*MakeRuleFn)(const flatbuffers::Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
GenerateFn generate;
|
||||
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;
|
||||
MakeRuleFn make_rule;
|
||||
};
|
||||
|
||||
typedef void (*WarnFn)(const FlatCompiler *flatc,
|
||||
const std::string &warn,
|
||||
bool show_exe_name);
|
||||
|
||||
typedef void (*ErrorFn)(const FlatCompiler *flatc,
|
||||
const std::string &err,
|
||||
bool usage, bool show_exe_name);
|
||||
|
||||
// Parameters required to initialize the FlatCompiler.
|
||||
struct InitParams {
|
||||
InitParams()
|
||||
: generators(nullptr),
|
||||
num_generators(0),
|
||||
warn_fn(nullptr),
|
||||
error_fn(nullptr) {}
|
||||
|
||||
const Generator* generators;
|
||||
size_t num_generators;
|
||||
WarnFn warn_fn;
|
||||
ErrorFn error_fn;
|
||||
};
|
||||
|
||||
explicit FlatCompiler(const InitParams& params) : params_(params) {}
|
||||
|
||||
int Compile(int argc, const char** argv);
|
||||
|
||||
std::string GetUsageString(const char* program_name) const;
|
||||
|
||||
private:
|
||||
void ParseFile(flatbuffers::Parser &parser,
|
||||
const std::string &filename,
|
||||
const std::string &contents,
|
||||
std::vector<const char *> &include_directories) const;
|
||||
|
||||
void Warn(const std::string &warn, bool show_exe_name = true) const;
|
||||
|
||||
void Error(const std::string &err, bool usage = true,
|
||||
bool show_exe_name = true) const;
|
||||
|
||||
InitParams params_;
|
||||
};
|
||||
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATC_H_
|
||||
1498
include/flatbuffers/flexbuffers.h
Normal file
1498
include/flatbuffers/flexbuffers.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -19,51 +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.
|
||||
// Deserialize by pulling the
|
||||
static grpc::Status Deserialize(grpc_byte_buffer *buffer,
|
||||
T *msg,
|
||||
int max_message_size) {
|
||||
// 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);
|
||||
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
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -20,11 +20,16 @@
|
||||
#include <map>
|
||||
#include <stack>
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
#include "flatbuffers/base.h"
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/hash.h"
|
||||
#include "flatbuffers/reflection.h"
|
||||
#include "flatbuffers/flexbuffers.h"
|
||||
|
||||
#if !defined(FLATBUFFERS_CPP98_STL)
|
||||
#include <functional>
|
||||
#endif // !defined(FLATBUFFERS_CPP98_STL)
|
||||
|
||||
// This file defines the data types representing a parsed IDL (Interface
|
||||
// Definition Language) / schema file.
|
||||
@@ -104,6 +109,7 @@ inline bool IsFloat (BaseType t) { return t == BASE_TYPE_FLOAT ||
|
||||
t == BASE_TYPE_DOUBLE; }
|
||||
inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
|
||||
t == BASE_TYPE_ULONG; }
|
||||
inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; }
|
||||
|
||||
extern const char *const kTypeNames[];
|
||||
extern const char kTypeSizes[];
|
||||
@@ -163,7 +169,7 @@ template<typename T> class SymbolTable {
|
||||
}
|
||||
|
||||
bool Add(const std::string &name, T *e) {
|
||||
vec.emplace_back(e);
|
||||
vector_emplace_back(&vec, e);
|
||||
auto it = dict.find(name);
|
||||
if (it != dict.end()) return true;
|
||||
dict[name] = e;
|
||||
@@ -193,7 +199,8 @@ template<typename T> class SymbolTable {
|
||||
|
||||
// A name space, as set in the schema.
|
||||
struct Namespace {
|
||||
std::vector<std::string> components;
|
||||
Namespace() : from_table(0) {}
|
||||
|
||||
|
||||
// Given a (potentally unqualified) name, return the "fully qualified" name
|
||||
// which has a full namespaced descriptor.
|
||||
@@ -201,12 +208,15 @@ struct Namespace {
|
||||
// the current namespace has.
|
||||
std::string GetFullyQualifiedName(const std::string &name,
|
||||
size_t max_components = 1000) const;
|
||||
|
||||
std::vector<std::string> components;
|
||||
size_t from_table; // Part of the namespace corresponds to a message/table.
|
||||
};
|
||||
|
||||
// Base class for all definition types (fields, structs_, enums_).
|
||||
struct Definition {
|
||||
Definition() : generated(false), defined_namespace(nullptr),
|
||||
serialized_location(0), index(-1) {}
|
||||
serialized_location(0), index(-1), refcount(1) {}
|
||||
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<
|
||||
reflection::KeyValue>>>
|
||||
@@ -223,21 +233,26 @@ struct Definition {
|
||||
// For use with Serialize()
|
||||
uoffset_t serialized_location;
|
||||
int index; // Inside the vector it is stored.
|
||||
int refcount;
|
||||
};
|
||||
|
||||
struct FieldDef : public Definition {
|
||||
FieldDef() : deprecated(false), required(false), key(false), padding(0) {}
|
||||
FieldDef() : deprecated(false), required(false), key(false),
|
||||
native_inline(false), flexbuffer(false), nested_flatbuffer(NULL),
|
||||
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.
|
||||
StructDef *nested_flatbuffer; // This field contains nested FlatBuffer data.
|
||||
size_t padding; // Bytes to always pad after this field.
|
||||
};
|
||||
|
||||
@@ -261,12 +276,15 @@ struct StructDef : public Definition {
|
||||
const Parser &parser) const;
|
||||
|
||||
SymbolTable<FieldDef> fields;
|
||||
|
||||
bool fixed; // If it's struct, not a table.
|
||||
bool predecl; // If it's used before it was defined.
|
||||
bool sortbysize; // Whether fields come in the declaration or size order.
|
||||
bool has_key; // It has a key field.
|
||||
size_t minalign; // What the whole object needs to be aligned to.
|
||||
size_t bytesize; // Size if fixed.
|
||||
|
||||
flatbuffers::unique_ptr<std::string> original_location;
|
||||
};
|
||||
|
||||
inline bool IsStruct(const Type &type) {
|
||||
@@ -283,18 +301,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 +330,7 @@ struct EnumDef : public Definition {
|
||||
|
||||
SymbolTable<EnumVal> vals;
|
||||
bool is_union;
|
||||
bool uses_type_aliases;
|
||||
Type underlying_type;
|
||||
};
|
||||
|
||||
@@ -337,6 +356,7 @@ struct ServiceDef : public Definition {
|
||||
struct IDLOptions {
|
||||
bool strict_json;
|
||||
bool skip_js_exports;
|
||||
bool use_goog_js_export_format;
|
||||
bool output_default_scalars_in_json;
|
||||
int indent_step;
|
||||
bool output_enum_identifiers;
|
||||
@@ -349,20 +369,53 @@ struct IDLOptions {
|
||||
bool generate_all;
|
||||
bool skip_unexpected_fields_in_json;
|
||||
bool generate_name_strings;
|
||||
bool escape_proto_identifiers;
|
||||
bool generate_object_based_api;
|
||||
std::string cpp_object_api_pointer_type;
|
||||
std::string cpp_object_api_string_type;
|
||||
bool gen_nullable;
|
||||
std::string object_prefix;
|
||||
std::string object_suffix;
|
||||
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_import;
|
||||
std::string go_namespace;
|
||||
bool reexport_ts_modules;
|
||||
bool protobuf_ascii_alike;
|
||||
|
||||
// Possible options for the more general generator below.
|
||||
enum Language { kJava, kCSharp, kGo, kMAX };
|
||||
enum Language {
|
||||
kJava = 1 << 0,
|
||||
kCSharp = 1 << 1,
|
||||
kGo = 1 << 2,
|
||||
kCpp = 1 << 3,
|
||||
kJs = 1 << 4,
|
||||
kPython = 1 << 5,
|
||||
kPhp = 1 << 6,
|
||||
kJson = 1 << 7,
|
||||
kBinary = 1 << 8,
|
||||
kTs = 1 << 9,
|
||||
kJsonSchema = 1 << 10,
|
||||
kMAX
|
||||
};
|
||||
|
||||
Language lang;
|
||||
|
||||
enum MiniReflect { kNone, kTypes, kTypesAndNames };
|
||||
|
||||
MiniReflect mini_reflect;
|
||||
|
||||
// The corresponding language bit will be set if a language is included
|
||||
// for code generation.
|
||||
unsigned long lang_to_generate;
|
||||
|
||||
IDLOptions()
|
||||
: strict_json(false),
|
||||
skip_js_exports(false),
|
||||
use_goog_js_export_format(false),
|
||||
output_default_scalars_in_json(false),
|
||||
indent_step(2),
|
||||
output_enum_identifiers(true), prefixed_enums(true), scoped_enums(false),
|
||||
@@ -373,12 +426,20 @@ struct IDLOptions {
|
||||
generate_all(false),
|
||||
skip_unexpected_fields_in_json(false),
|
||||
generate_name_strings(false),
|
||||
escape_proto_identifiers(false),
|
||||
generate_object_based_api(false),
|
||||
cpp_object_api_pointer_type("std::unique_ptr"),
|
||||
gen_nullable(false),
|
||||
object_suffix("T"),
|
||||
union_value_namespacing(true),
|
||||
allow_non_utf8(false),
|
||||
lang(IDLOptions::kJava) {}
|
||||
keep_include_path(false),
|
||||
binary_schema_comments(false),
|
||||
skip_flatbuffers_import(false),
|
||||
reexport_ts_modules(true),
|
||||
protobuf_ascii_alike(false),
|
||||
lang(IDLOptions::kJava),
|
||||
mini_reflect(IDLOptions::kNone),
|
||||
lang_to_generate(0) {}
|
||||
};
|
||||
|
||||
// This encapsulates where the parser is in the current source file.
|
||||
@@ -438,12 +499,17 @@ class CheckedError {
|
||||
class Parser : public ParserState {
|
||||
public:
|
||||
explicit Parser(const IDLOptions &options = IDLOptions())
|
||||
: root_struct_def_(nullptr),
|
||||
: current_namespace_(nullptr),
|
||||
empty_namespace_(nullptr),
|
||||
root_struct_def_(nullptr),
|
||||
opts(options),
|
||||
uses_flexbuffers_(false),
|
||||
source_(nullptr),
|
||||
anonymous_counter(0) {
|
||||
// Just in case none are declared:
|
||||
namespaces_.push_back(new Namespace());
|
||||
// Start out with the empty namespace being current.
|
||||
empty_namespace_ = new Namespace();
|
||||
namespaces_.push_back(empty_namespace_);
|
||||
current_namespace_ = empty_namespace_;
|
||||
known_attributes_["deprecated"] = true;
|
||||
known_attributes_["required"] = true;
|
||||
known_attributes_["key"] = true;
|
||||
@@ -458,7 +524,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() {
|
||||
@@ -476,6 +546,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);
|
||||
|
||||
@@ -498,14 +570,24 @@ 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);
|
||||
|
||||
StructDef *LookupStruct(const std::string &id) const;
|
||||
|
||||
private:
|
||||
void Message(const std::string &msg);
|
||||
void Warning(const std::string &msg);
|
||||
FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, int64_t *val);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
|
||||
FLATBUFFERS_CHECKED_ERROR Next();
|
||||
FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
|
||||
bool Is(int t);
|
||||
bool IsIdent(const char *id);
|
||||
FLATBUFFERS_CHECKED_ERROR Expect(int t);
|
||||
std::string TokenToStringId(int t);
|
||||
EnumDef *LookupEnum(const std::string &id);
|
||||
@@ -517,18 +599,46 @@ 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);
|
||||
#if defined(FLATBUFFERS_CPP98_STL)
|
||||
typedef CheckedError (*ParseTableDelimitersBody)(
|
||||
const std::string &name, size_t &fieldn, const StructDef *struct_def,
|
||||
void *state);
|
||||
#else
|
||||
typedef std::function<CheckedError(const std::string&, size_t&,
|
||||
const StructDef*, void*)>
|
||||
ParseTableDelimitersBody;
|
||||
#endif // defined(FLATBUFFERS_CPP98_STL)
|
||||
FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
|
||||
const StructDef *struct_def,
|
||||
ParseTableDelimitersBody body,
|
||||
void *state);
|
||||
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);
|
||||
#if defined(FLATBUFFERS_CPP98_STL)
|
||||
typedef CheckedError (*ParseVectorDelimitersBody)(size_t &count,
|
||||
void *state);
|
||||
#else
|
||||
typedef std::function<CheckedError(size_t&, void*)>
|
||||
ParseVectorDelimitersBody;
|
||||
#endif // defined(FLATBUFFERS_CPP98_STL)
|
||||
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(
|
||||
size_t &count, ParseVectorDelimitersBody body, void *state);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field,
|
||||
size_t fieldn,
|
||||
const StructDef *parent_struct_def);
|
||||
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,
|
||||
@@ -548,22 +658,32 @@ 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 DoParse(const char *_source,
|
||||
FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder);
|
||||
FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source,
|
||||
const char *source_filename);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source,
|
||||
const char **include_paths,
|
||||
const char *source_filename);
|
||||
FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
|
||||
const char **include_paths,
|
||||
const char *source_filename,
|
||||
const char *include_filename);
|
||||
FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef*> &fields,
|
||||
StructDef *struct_def,
|
||||
const char *suffix,
|
||||
BaseType baseType);
|
||||
|
||||
bool SupportsVectorOfUnions() const;
|
||||
Namespace *UniqueNamespace(Namespace *ns);
|
||||
|
||||
public:
|
||||
SymbolTable<Type> types_;
|
||||
SymbolTable<StructDef> structs_;
|
||||
SymbolTable<EnumDef> enums_;
|
||||
SymbolTable<ServiceDef> services_;
|
||||
std::vector<Namespace *> namespaces_;
|
||||
Namespace *current_namespace_;
|
||||
Namespace *empty_namespace_;
|
||||
std::string error_; // User readable error_ if Parse() == false
|
||||
|
||||
FlatBufferBuilder builder_; // any data contained in the file
|
||||
@@ -571,12 +691,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_;
|
||||
@@ -592,13 +714,6 @@ private:
|
||||
|
||||
extern std::string MakeCamel(const std::string &in, bool first = true);
|
||||
|
||||
struct CommentConfig;
|
||||
|
||||
extern void GenComment(const std::vector<std::string> &dc,
|
||||
std::string *code_ptr,
|
||||
const CommentConfig *config,
|
||||
const char *prefix = "");
|
||||
|
||||
// Generate text (JSON) from a given FlatBuffer, and a given Parser
|
||||
// object that has been populated with the corresponding schema.
|
||||
// If ident_step is 0, no indentation will be generated. Additionally,
|
||||
@@ -629,7 +744,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,
|
||||
@@ -660,6 +775,12 @@ extern bool GeneratePython(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Json schema file
|
||||
// See idl_gen_json_schema.cpp.
|
||||
extern bool GenerateJsonSchema(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate C# files from the definitions in the Parser object.
|
||||
// See idl_gen_csharp.cpp.
|
||||
extern bool GenerateCSharp(const Parser &parser,
|
||||
@@ -680,7 +801,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,
|
||||
@@ -725,4 +846,3 @@ bool GenerateGoGRPC(const Parser &parser,
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_IDL_H_
|
||||
|
||||
|
||||
352
include/flatbuffers/minireflect.h
Normal file
352
include/flatbuffers/minireflect.h
Normal file
@@ -0,0 +1,352 @@
|
||||
/*
|
||||
* 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_MINIREFLECT_H_
|
||||
#define FLATBUFFERS_MINIREFLECT_H_
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/util.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
// Utilities that can be used with the "mini reflection" tables present
|
||||
// in generated code with --reflect-types (only types) or --reflect-names
|
||||
// (also names).
|
||||
// This allows basic reflection functionality such as pretty-printing
|
||||
// that does not require the use of the schema parser or loading of binary
|
||||
// schema files at runtime (reflection.h).
|
||||
|
||||
// For any of the functions below that take `const TypeTable *`, you pass
|
||||
// `FooTypeTable()` if the type of the root is `Foo`.
|
||||
|
||||
// First, a generic iterator that can be used by multiple algorithms.
|
||||
|
||||
struct IterationVisitor {
|
||||
// These mark the scope of a table or struct.
|
||||
virtual void StartSequence() {}
|
||||
virtual void EndSequence() {}
|
||||
// Called for each field regardless of wether it is present or not.
|
||||
// If not present, val == nullptr. set_idx is the index of all set fields.
|
||||
virtual void Field(size_t /*field_idx*/, size_t /*set_idx*/,
|
||||
ElementaryType /*type*/, bool /*is_vector*/,
|
||||
const TypeTable * /*type_table*/, const char * /*name*/,
|
||||
const uint8_t * /*val*/) {}
|
||||
// Called for a value that is actually present, after a field, or as part
|
||||
// of a vector.
|
||||
virtual void UType(uint8_t, const char *) {}
|
||||
virtual void Bool(bool) {}
|
||||
virtual void Char(int8_t, const char *) {}
|
||||
virtual void UChar(uint8_t, const char *) {}
|
||||
virtual void Short(int16_t, const char *) {}
|
||||
virtual void UShort(uint16_t, const char *) {}
|
||||
virtual void Int(int32_t, const char *) {}
|
||||
virtual void UInt(uint32_t, const char *) {}
|
||||
virtual void Long(int64_t) {}
|
||||
virtual void ULong(uint64_t) {}
|
||||
virtual void Float(float) {}
|
||||
virtual void Double(double) {}
|
||||
virtual void String(const String *) {}
|
||||
virtual void Unknown(const uint8_t *) {} // From a future version.
|
||||
// These mark the scope of a vector.
|
||||
virtual void StartVector() {}
|
||||
virtual void EndVector() {}
|
||||
virtual void Element(size_t /*i*/, ElementaryType /*type*/,
|
||||
const TypeTable * /*type_table*/,
|
||||
const uint8_t * /*val*/)
|
||||
{}
|
||||
virtual ~IterationVisitor() {}
|
||||
};
|
||||
|
||||
inline size_t InlineSize(ElementaryType type, const TypeTable *type_table) {
|
||||
switch (type) {
|
||||
case ET_UTYPE:
|
||||
case ET_BOOL:
|
||||
case ET_CHAR:
|
||||
case ET_UCHAR:
|
||||
return 1;
|
||||
case ET_SHORT:
|
||||
case ET_USHORT:
|
||||
return 2;
|
||||
case ET_INT:
|
||||
case ET_UINT:
|
||||
case ET_FLOAT:
|
||||
case ET_STRING:
|
||||
return 4;
|
||||
case ET_LONG:
|
||||
case ET_ULONG:
|
||||
case ET_DOUBLE:
|
||||
return 8;
|
||||
case ET_SEQUENCE:
|
||||
switch (type_table->st) {
|
||||
case ST_TABLE:
|
||||
case ST_UNION:
|
||||
return 4;
|
||||
case ST_STRUCT:
|
||||
return type_table->values[type_table->num_elems];
|
||||
default:
|
||||
assert(false);
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
assert(false);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
inline int32_t LookupEnum(int32_t enum_val, const int32_t *values,
|
||||
size_t num_values) {
|
||||
if (!values) return enum_val;
|
||||
for (size_t i = 0; i < num_values; i++) {
|
||||
if (enum_val == values[i]) return static_cast<int32_t>(i);
|
||||
}
|
||||
return -1; // Unknown enum value.
|
||||
}
|
||||
|
||||
template<typename T> const char *EnumName(T tval, const TypeTable *type_table) {
|
||||
if (!type_table || !type_table->names) return nullptr;
|
||||
auto i = LookupEnum(static_cast<int32_t>(tval), type_table->values,
|
||||
type_table->num_elems);
|
||||
if (i >= 0 && i < static_cast<int32_t>(type_table->num_elems)) {
|
||||
return type_table->names[i];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void IterateObject(const uint8_t *obj, const TypeTable *type_table,
|
||||
IterationVisitor *visitor);
|
||||
|
||||
inline void IterateValue(ElementaryType type, const uint8_t *val,
|
||||
const TypeTable *type_table,
|
||||
const uint8_t *prev_val,
|
||||
soffset_t vector_index,
|
||||
IterationVisitor *visitor) {
|
||||
switch (type) {
|
||||
case ET_UTYPE: {
|
||||
auto tval = *reinterpret_cast<const uint8_t *>(val);
|
||||
visitor->UType(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_BOOL: {
|
||||
visitor->Bool(*reinterpret_cast<const uint8_t *>(val) != 0);
|
||||
break;
|
||||
}
|
||||
case ET_CHAR: {
|
||||
auto tval = *reinterpret_cast<const int8_t *>(val);
|
||||
visitor->Char(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_UCHAR: {
|
||||
auto tval = *reinterpret_cast<const uint8_t *>(val);
|
||||
visitor->UChar(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_SHORT: {
|
||||
auto tval = *reinterpret_cast<const int16_t *>(val);
|
||||
visitor->Short(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_USHORT: {
|
||||
auto tval = *reinterpret_cast<const uint16_t *>(val);
|
||||
visitor->UShort(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_INT: {
|
||||
auto tval = *reinterpret_cast<const int32_t *>(val);
|
||||
visitor->Int(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_UINT: {
|
||||
auto tval = *reinterpret_cast<const uint32_t *>(val);
|
||||
visitor->UInt(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_LONG: {
|
||||
visitor->Long(*reinterpret_cast<const int64_t *>(val));
|
||||
break;
|
||||
}
|
||||
case ET_ULONG: {
|
||||
visitor->ULong(*reinterpret_cast<const uint64_t *>(val));
|
||||
break;
|
||||
}
|
||||
case ET_FLOAT: {
|
||||
visitor->Float(*reinterpret_cast<const float *>(val));
|
||||
break;
|
||||
}
|
||||
case ET_DOUBLE: {
|
||||
visitor->Double(*reinterpret_cast<const double *>(val));
|
||||
break;
|
||||
}
|
||||
case ET_STRING: {
|
||||
val += ReadScalar<uoffset_t>(val);
|
||||
visitor->String(reinterpret_cast<const String *>(val));
|
||||
break;
|
||||
}
|
||||
case ET_SEQUENCE: {
|
||||
switch (type_table->st) {
|
||||
case ST_TABLE:
|
||||
val += ReadScalar<uoffset_t>(val);
|
||||
IterateObject(val, type_table, visitor);
|
||||
break;
|
||||
case ST_STRUCT:
|
||||
IterateObject(val, type_table, visitor);
|
||||
break;
|
||||
case ST_UNION: {
|
||||
val += ReadScalar<uoffset_t>(val);
|
||||
assert(prev_val);
|
||||
auto union_type = *prev_val; // Always a uint8_t.
|
||||
if (vector_index >= 0) {
|
||||
auto type_vec = reinterpret_cast<const Vector<uint8_t> *>(prev_val);
|
||||
union_type = type_vec->Get(static_cast<uoffset_t>(vector_index));
|
||||
}
|
||||
auto type_code_idx = LookupEnum(union_type, type_table->values,
|
||||
type_table->num_elems);
|
||||
if (type_code_idx >= 0 && type_code_idx <
|
||||
static_cast<int32_t>(type_table->num_elems)) {
|
||||
auto type_code = type_table->type_codes[type_code_idx];
|
||||
switch (type_code.base_type) {
|
||||
case ET_SEQUENCE: {
|
||||
auto ref = type_table->type_refs[type_code.sequence_ref]();
|
||||
IterateObject(val, ref, visitor);
|
||||
break;
|
||||
}
|
||||
case ET_STRING:
|
||||
visitor->String(reinterpret_cast<const String *>(val));
|
||||
break;
|
||||
default:
|
||||
visitor->Unknown(val);
|
||||
}
|
||||
} else {
|
||||
visitor->Unknown(val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ST_ENUM:
|
||||
assert(false);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
visitor->Unknown(val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void IterateObject(const uint8_t *obj, const TypeTable *type_table,
|
||||
IterationVisitor *visitor) {
|
||||
visitor->StartSequence();
|
||||
const uint8_t *prev_val = nullptr;
|
||||
size_t set_idx = 0;
|
||||
for (size_t i = 0; i < type_table->num_elems; i++) {
|
||||
auto type_code = type_table->type_codes[i];
|
||||
auto type = static_cast<ElementaryType>(type_code.base_type);
|
||||
auto is_vector = type_code.is_vector != 0;
|
||||
auto ref_idx = type_code.sequence_ref;
|
||||
const TypeTable *ref = nullptr;
|
||||
if (ref_idx >= 0) {
|
||||
ref = type_table->type_refs[ref_idx]();
|
||||
}
|
||||
auto name = type_table->names ? type_table->names[i] : nullptr;
|
||||
const uint8_t *val = nullptr;
|
||||
if (type_table->st == ST_TABLE) {
|
||||
val = reinterpret_cast<const Table *>(obj)->GetAddressOf(
|
||||
FieldIndexToOffset(static_cast<voffset_t>(i)));
|
||||
} else {
|
||||
val = obj + type_table->values[i];
|
||||
}
|
||||
visitor->Field(i, set_idx, type, is_vector, ref, name, val);
|
||||
if (val) {
|
||||
set_idx++;
|
||||
if (is_vector) {
|
||||
val += ReadScalar<uoffset_t>(val);
|
||||
auto vec = reinterpret_cast<const Vector<uint8_t> *>(val);
|
||||
visitor->StartVector();
|
||||
auto elem_ptr = vec->Data();
|
||||
for (size_t j = 0; j < vec->size(); j++) {
|
||||
visitor->Element(j, type, ref, elem_ptr);
|
||||
IterateValue(type, elem_ptr, ref, prev_val, static_cast<soffset_t>(j),
|
||||
visitor);
|
||||
elem_ptr += InlineSize(type, ref);
|
||||
}
|
||||
visitor->EndVector();
|
||||
} else {
|
||||
IterateValue(type, val, ref, prev_val, -1, visitor);
|
||||
}
|
||||
}
|
||||
prev_val = val;
|
||||
}
|
||||
visitor->EndSequence();
|
||||
}
|
||||
|
||||
inline void IterateFlatBuffer(const uint8_t *buffer,
|
||||
const TypeTable *type_table,
|
||||
IterationVisitor *callback) {
|
||||
IterateObject(GetRoot<uint8_t>(buffer), type_table, callback);
|
||||
}
|
||||
|
||||
// Outputting a Flatbuffer to a string. Tries to conform as close to JSON /
|
||||
// the output generated by idl_gen_text.cpp.
|
||||
|
||||
struct ToStringVisitor : public IterationVisitor {
|
||||
std::string s;
|
||||
void StartSequence() { s += "{ "; }
|
||||
void EndSequence() { s += " }"; }
|
||||
void Field(size_t /*field_idx*/, size_t set_idx, ElementaryType /*type*/,
|
||||
bool /*is_vector*/, const TypeTable * /*type_table*/,
|
||||
const char *name, const uint8_t *val) {
|
||||
if (!val) return;
|
||||
if (set_idx) s += ", ";
|
||||
if (name) { s += name; s += ": "; }
|
||||
}
|
||||
template<typename T> void Named(T x, const char *name) {
|
||||
if (name) s+= name;
|
||||
else s+= NumToString(x);
|
||||
}
|
||||
void UType(uint8_t x, const char *name) { Named(x, name); }
|
||||
void Bool(bool x) { s+= x ? "true" : "false"; }
|
||||
void Char(int8_t x, const char *name) { Named(x, name); }
|
||||
void UChar(uint8_t x, const char *name) { Named(x, name); }
|
||||
void Short(int16_t x, const char *name) { Named(x, name); }
|
||||
void UShort(uint16_t x, const char *name) { Named(x, name); }
|
||||
void Int(int32_t x, const char *name) { Named(x, name); }
|
||||
void UInt(uint32_t x, const char *name) { Named(x, name); }
|
||||
void Long(int64_t x) { s+= NumToString(x); }
|
||||
void ULong(uint64_t x) { s+= NumToString(x); }
|
||||
void Float(float x) { s+= NumToString(x); }
|
||||
void Double(double x) { s+= NumToString(x); }
|
||||
void String(const struct String *str) {
|
||||
EscapeString(str->c_str(), str->size(), &s, true);
|
||||
}
|
||||
void Unknown(const uint8_t *) { s += "(?)"; }
|
||||
void StartVector() { s += "[ "; }
|
||||
void EndVector() { s += " ]"; }
|
||||
void Element(size_t i, ElementaryType /*type*/,
|
||||
const TypeTable * /*type_table*/, const uint8_t * /*val*/) {
|
||||
if (i) s += ", ";
|
||||
}
|
||||
};
|
||||
|
||||
inline std::string FlatBufferToString(const uint8_t *buffer,
|
||||
const TypeTable *type_table) {
|
||||
ToStringVisitor tostring_visitor;
|
||||
IterateFlatBuffer(buffer, type_table, &tostring_visitor);
|
||||
return tostring_visitor.s;
|
||||
}
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_MINIREFLECT_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;
|
||||
}
|
||||
@@ -329,12 +361,13 @@ template<typename T, typename U> class pointer_inside_vector {
|
||||
public:
|
||||
pointer_inside_vector(T *ptr, std::vector<U> &vec)
|
||||
: offset_(reinterpret_cast<uint8_t *>(ptr) -
|
||||
reinterpret_cast<uint8_t *>(vec.data())),
|
||||
reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec))),
|
||||
vec_(vec) {}
|
||||
|
||||
T *operator*() const {
|
||||
return reinterpret_cast<T *>(
|
||||
reinterpret_cast<uint8_t *>(vec_.data()) + offset_);
|
||||
reinterpret_cast<uint8_t *>(
|
||||
flatbuffers::vector_data(vec_)) + offset_);
|
||||
}
|
||||
T *operator->() const {
|
||||
return operator*();
|
||||
@@ -386,7 +419,6 @@ uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize,
|
||||
uoffset_t elem_size, std::vector<uint8_t> *flatbuf,
|
||||
const reflection::Object *root_table = nullptr);
|
||||
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
template <typename T>
|
||||
void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
|
||||
const Vector<T> *vec, std::vector<uint8_t> *flatbuf,
|
||||
@@ -400,7 +432,7 @@ void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
|
||||
// Set new elements to "val".
|
||||
for (int i = 0; i < delta_elem; i++) {
|
||||
auto loc = newelems + i * sizeof(T);
|
||||
auto is_scalar = std::is_scalar<T>::value;
|
||||
auto is_scalar = flatbuffers::is_scalar<T>::value;
|
||||
if (is_scalar) {
|
||||
WriteScalar(loc, val);
|
||||
} else { // struct
|
||||
@@ -408,7 +440,6 @@ void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Adds any new data (in the form of a new FlatBuffer) to an existing
|
||||
// FlatBuffer. This can be used when any of the above methods are not
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
|
||||
#ifndef FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_
|
||||
#define FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_
|
||||
|
||||
@@ -41,12 +42,57 @@ enum BaseType {
|
||||
Union = 16
|
||||
};
|
||||
|
||||
inline BaseType (&EnumValuesBaseType())[17] {
|
||||
static BaseType values[] = {
|
||||
None,
|
||||
UType,
|
||||
Bool,
|
||||
Byte,
|
||||
UByte,
|
||||
Short,
|
||||
UShort,
|
||||
Int,
|
||||
UInt,
|
||||
Long,
|
||||
ULong,
|
||||
Float,
|
||||
Double,
|
||||
String,
|
||||
Vector,
|
||||
Obj,
|
||||
Union
|
||||
};
|
||||
return values;
|
||||
}
|
||||
|
||||
inline const char **EnumNamesBaseType() {
|
||||
static const char *names[] = { "None", "UType", "Bool", "Byte", "UByte", "Short", "UShort", "Int", "UInt", "Long", "ULong", "Float", "Double", "String", "Vector", "Obj", "Union", nullptr };
|
||||
static const char *names[] = {
|
||||
"None",
|
||||
"UType",
|
||||
"Bool",
|
||||
"Byte",
|
||||
"UByte",
|
||||
"Short",
|
||||
"UShort",
|
||||
"Int",
|
||||
"UInt",
|
||||
"Long",
|
||||
"ULong",
|
||||
"Float",
|
||||
"Double",
|
||||
"String",
|
||||
"Vector",
|
||||
"Obj",
|
||||
"Union",
|
||||
nullptr
|
||||
};
|
||||
return names;
|
||||
}
|
||||
|
||||
inline const char *EnumNameBaseType(BaseType e) { return EnumNamesBaseType()[static_cast<int>(e)]; }
|
||||
inline const char *EnumNameBaseType(BaseType e) {
|
||||
const size_t index = static_cast<int>(e);
|
||||
return EnumNamesBaseType()[index];
|
||||
}
|
||||
|
||||
struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum {
|
||||
@@ -54,9 +100,15 @@ struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VT_ELEMENT = 6,
|
||||
VT_INDEX = 8
|
||||
};
|
||||
BaseType base_type() const { return static_cast<BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0)); }
|
||||
BaseType element() const { return static_cast<BaseType>(GetField<int8_t>(VT_ELEMENT, 0)); }
|
||||
int32_t index() const { return GetField<int32_t>(VT_INDEX, -1); }
|
||||
BaseType base_type() const {
|
||||
return static_cast<BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0));
|
||||
}
|
||||
BaseType element() const {
|
||||
return static_cast<BaseType>(GetField<int8_t>(VT_ELEMENT, 0));
|
||||
}
|
||||
int32_t index() const {
|
||||
return GetField<int32_t>(VT_INDEX, -1);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<int8_t>(verifier, VT_BASE_TYPE) &&
|
||||
@@ -69,18 +121,29 @@ struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
struct TypeBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_base_type(BaseType base_type) { fbb_.AddElement<int8_t>(Type::VT_BASE_TYPE, static_cast<int8_t>(base_type), 0); }
|
||||
void add_element(BaseType element) { fbb_.AddElement<int8_t>(Type::VT_ELEMENT, static_cast<int8_t>(element), 0); }
|
||||
void add_index(int32_t index) { fbb_.AddElement<int32_t>(Type::VT_INDEX, index, -1); }
|
||||
TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
|
||||
void add_base_type(BaseType base_type) {
|
||||
fbb_.AddElement<int8_t>(Type::VT_BASE_TYPE, static_cast<int8_t>(base_type), 0);
|
||||
}
|
||||
void add_element(BaseType element) {
|
||||
fbb_.AddElement<int8_t>(Type::VT_ELEMENT, static_cast<int8_t>(element), 0);
|
||||
}
|
||||
void add_index(int32_t index) {
|
||||
fbb_.AddElement<int32_t>(Type::VT_INDEX, index, -1);
|
||||
}
|
||||
TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
TypeBuilder &operator=(const TypeBuilder &);
|
||||
flatbuffers::Offset<Type> Finish() {
|
||||
auto o = flatbuffers::Offset<Type>(fbb_.EndTable(start_, 3));
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<Type>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<Type> CreateType(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
inline flatbuffers::Offset<Type> CreateType(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
BaseType base_type = None,
|
||||
BaseType element = None,
|
||||
int32_t index = -1) {
|
||||
@@ -96,15 +159,23 @@ struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VT_KEY = 4,
|
||||
VT_VALUE = 6
|
||||
};
|
||||
const flatbuffers::String *key() const { return GetPointer<const flatbuffers::String *>(VT_KEY); }
|
||||
bool KeyCompareLessThan(const KeyValue *o) const { return *key() < *o->key(); }
|
||||
int KeyCompareWithValue(const char *val) const { return strcmp(key()->c_str(), val); }
|
||||
const flatbuffers::String *value() const { return GetPointer<const flatbuffers::String *>(VT_VALUE); }
|
||||
const flatbuffers::String *key() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_KEY);
|
||||
}
|
||||
bool KeyCompareLessThan(const KeyValue *o) const {
|
||||
return *key() < *o->key();
|
||||
}
|
||||
int KeyCompareWithValue(const char *val) const {
|
||||
return strcmp(key()->c_str(), val);
|
||||
}
|
||||
const flatbuffers::String *value() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_VALUE);
|
||||
}
|
||||
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();
|
||||
}
|
||||
@@ -113,18 +184,27 @@ struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
struct KeyValueBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_key(flatbuffers::Offset<flatbuffers::String> key) { fbb_.AddOffset(KeyValue::VT_KEY, key); }
|
||||
void add_value(flatbuffers::Offset<flatbuffers::String> value) { fbb_.AddOffset(KeyValue::VT_VALUE, value); }
|
||||
KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
|
||||
void add_key(flatbuffers::Offset<flatbuffers::String> key) {
|
||||
fbb_.AddOffset(KeyValue::VT_KEY, key);
|
||||
}
|
||||
void add_value(flatbuffers::Offset<flatbuffers::String> value) {
|
||||
fbb_.AddOffset(KeyValue::VT_VALUE, value);
|
||||
}
|
||||
KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
KeyValueBuilder &operator=(const KeyValueBuilder &);
|
||||
flatbuffers::Offset<KeyValue> Finish() {
|
||||
auto o = flatbuffers::Offset<KeyValue>(fbb_.EndTable(start_, 2));
|
||||
fbb_.Required(o, KeyValue::VT_KEY); // key
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<KeyValue>(end);
|
||||
fbb_.Required(o, KeyValue::VT_KEY);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<KeyValue> CreateKeyValue(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
inline flatbuffers::Offset<KeyValue> CreateKeyValue(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> key = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> value = 0) {
|
||||
KeyValueBuilder builder_(_fbb);
|
||||
@@ -133,30 +213,57 @@ inline flatbuffers::Offset<KeyValue> CreateKeyValue(flatbuffers::FlatBufferBuild
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<KeyValue> CreateKeyValueDirect(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
inline flatbuffers::Offset<KeyValue> CreateKeyValueDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *key = nullptr,
|
||||
const char *value = nullptr) {
|
||||
return CreateKeyValue(_fbb, key ? _fbb.CreateString(key) : 0, value ? _fbb.CreateString(value) : 0);
|
||||
return reflection::CreateKeyValue(
|
||||
_fbb,
|
||||
key ? _fbb.CreateString(key) : 0,
|
||||
value ? _fbb.CreateString(value) : 0);
|
||||
}
|
||||
|
||||
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); }
|
||||
int64_t value() const { return GetField<int64_t>(VT_VALUE, 0); }
|
||||
bool KeyCompareLessThan(const EnumVal *o) const { return value() < o->value(); }
|
||||
int KeyCompareWithValue(int64_t val) const { return value() < val ? -1 : value() > val; }
|
||||
const Object *object() const { return GetPointer<const Object *>(VT_OBJECT); }
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
int64_t value() const {
|
||||
return GetField<int64_t>(VT_VALUE, 0);
|
||||
}
|
||||
bool KeyCompareLessThan(const EnumVal *o) const {
|
||||
return value() < o->value();
|
||||
}
|
||||
int KeyCompareWithValue(int64_t val) const {
|
||||
const auto key = value();
|
||||
if (key < val) {
|
||||
return -1;
|
||||
} else if (key > val) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
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();
|
||||
}
|
||||
};
|
||||
@@ -164,34 +271,57 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
struct EnumValBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(EnumVal::VT_NAME, name); }
|
||||
void add_value(int64_t value) { fbb_.AddElement<int64_t>(EnumVal::VT_VALUE, value, 0); }
|
||||
void add_object(flatbuffers::Offset<Object> object) { fbb_.AddOffset(EnumVal::VT_OBJECT, object); }
|
||||
EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(EnumVal::VT_NAME, name);
|
||||
}
|
||||
void add_value(int64_t value) {
|
||||
fbb_.AddElement<int64_t>(EnumVal::VT_VALUE, value, 0);
|
||||
}
|
||||
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() {
|
||||
auto o = flatbuffers::Offset<EnumVal>(fbb_.EndTable(start_, 3));
|
||||
fbb_.Required(o, EnumVal::VT_NAME); // name
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<EnumVal>(end);
|
||||
fbb_.Required(o, EnumVal::VT_NAME);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<EnumVal> CreateEnumVal(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
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();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<EnumVal> CreateEnumValDirect(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
inline flatbuffers::Offset<EnumVal> CreateEnumValDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
int64_t value = 0,
|
||||
flatbuffers::Offset<Object> object = 0) {
|
||||
return CreateEnumVal(_fbb, name ? _fbb.CreateString(name) : 0, value, object);
|
||||
flatbuffers::Offset<Object> object = 0,
|
||||
flatbuffers::Offset<Type> union_type = 0) {
|
||||
return reflection::CreateEnumVal(
|
||||
_fbb,
|
||||
name ? _fbb.CreateString(name) : 0,
|
||||
value,
|
||||
object,
|
||||
union_type);
|
||||
}
|
||||
|
||||
struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
@@ -200,28 +330,49 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VT_VALUES = 6,
|
||||
VT_IS_UNION = 8,
|
||||
VT_UNDERLYING_TYPE = 10,
|
||||
VT_ATTRIBUTES = 12
|
||||
VT_ATTRIBUTES = 12,
|
||||
VT_DOCUMENTATION = 14
|
||||
};
|
||||
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(VT_NAME); }
|
||||
bool KeyCompareLessThan(const Enum *o) const { return *name() < *o->name(); }
|
||||
int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); }
|
||||
const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *values() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *>(VT_VALUES); }
|
||||
bool is_union() const { return GetField<uint8_t>(VT_IS_UNION, 0) != 0; }
|
||||
const Type *underlying_type() const { return GetPointer<const Type *>(VT_UNDERLYING_TYPE); }
|
||||
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES); }
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
bool KeyCompareLessThan(const Enum *o) const {
|
||||
return *name() < *o->name();
|
||||
}
|
||||
int KeyCompareWithValue(const char *val) const {
|
||||
return strcmp(name()->c_str(), val);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *values() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *>(VT_VALUES);
|
||||
}
|
||||
bool is_union() const {
|
||||
return GetField<uint8_t>(VT_IS_UNION, 0) != 0;
|
||||
}
|
||||
const Type *underlying_type() const {
|
||||
return GetPointer<const Type *>(VT_UNDERLYING_TYPE);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||
}
|
||||
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()) &&
|
||||
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
||||
verifier.Verify(documentation()) &&
|
||||
verifier.VerifyVectorOfStrings(documentation()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
@@ -229,29 +380,49 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
struct EnumBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(Enum::VT_NAME, name); }
|
||||
void add_values(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<EnumVal>>> values) { fbb_.AddOffset(Enum::VT_VALUES, values); }
|
||||
void add_is_union(bool is_union) { fbb_.AddElement<uint8_t>(Enum::VT_IS_UNION, static_cast<uint8_t>(is_union), 0); }
|
||||
void add_underlying_type(flatbuffers::Offset<Type> underlying_type) { fbb_.AddOffset(Enum::VT_UNDERLYING_TYPE, underlying_type); }
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) { fbb_.AddOffset(Enum::VT_ATTRIBUTES, attributes); }
|
||||
EnumBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(Enum::VT_NAME, name);
|
||||
}
|
||||
void add_values(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<EnumVal>>> values) {
|
||||
fbb_.AddOffset(Enum::VT_VALUES, values);
|
||||
}
|
||||
void add_is_union(bool is_union) {
|
||||
fbb_.AddElement<uint8_t>(Enum::VT_IS_UNION, static_cast<uint8_t>(is_union), 0);
|
||||
}
|
||||
void add_underlying_type(flatbuffers::Offset<Type> underlying_type) {
|
||||
fbb_.AddOffset(Enum::VT_UNDERLYING_TYPE, underlying_type);
|
||||
}
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) {
|
||||
fbb_.AddOffset(Enum::VT_ATTRIBUTES, attributes);
|
||||
}
|
||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||
fbb_.AddOffset(Enum::VT_DOCUMENTATION, documentation);
|
||||
}
|
||||
EnumBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
EnumBuilder &operator=(const EnumBuilder &);
|
||||
flatbuffers::Offset<Enum> Finish() {
|
||||
auto o = flatbuffers::Offset<Enum>(fbb_.EndTable(start_, 5));
|
||||
fbb_.Required(o, Enum::VT_NAME); // name
|
||||
fbb_.Required(o, Enum::VT_VALUES); // values
|
||||
fbb_.Required(o, Enum::VT_UNDERLYING_TYPE); // underlying_type
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<Enum>(end);
|
||||
fbb_.Required(o, Enum::VT_NAME);
|
||||
fbb_.Required(o, Enum::VT_VALUES);
|
||||
fbb_.Required(o, Enum::VT_UNDERLYING_TYPE);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<Enum> CreateEnum(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
inline flatbuffers::Offset<Enum> CreateEnum(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<EnumVal>>> values = 0,
|
||||
bool is_union = false,
|
||||
flatbuffers::Offset<Type> underlying_type = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0) {
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||
EnumBuilder builder_(_fbb);
|
||||
builder_.add_documentation(documentation);
|
||||
builder_.add_attributes(attributes);
|
||||
builder_.add_underlying_type(underlying_type);
|
||||
builder_.add_values(values);
|
||||
@@ -260,13 +431,22 @@ inline flatbuffers::Offset<Enum> CreateEnum(flatbuffers::FlatBufferBuilder &_fbb
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Enum> CreateEnumDirect(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
inline flatbuffers::Offset<Enum> CreateEnumDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
const std::vector<flatbuffers::Offset<EnumVal>> *values = nullptr,
|
||||
bool is_union = false,
|
||||
flatbuffers::Offset<Type> underlying_type = 0,
|
||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr) {
|
||||
return CreateEnum(_fbb, name ? _fbb.CreateString(name) : 0, values ? _fbb.CreateVector<flatbuffers::Offset<EnumVal>>(*values) : 0, is_union, underlying_type, attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0);
|
||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||
return reflection::CreateEnum(
|
||||
_fbb,
|
||||
name ? _fbb.CreateString(name) : 0,
|
||||
values ? _fbb.CreateVector<flatbuffers::Offset<EnumVal>>(*values) : 0,
|
||||
is_union,
|
||||
underlying_type,
|
||||
attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0,
|
||||
documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0);
|
||||
}
|
||||
|
||||
struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
@@ -280,25 +460,53 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VT_DEPRECATED = 16,
|
||||
VT_REQUIRED = 18,
|
||||
VT_KEY = 20,
|
||||
VT_ATTRIBUTES = 22
|
||||
VT_ATTRIBUTES = 22,
|
||||
VT_DOCUMENTATION = 24
|
||||
};
|
||||
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(VT_NAME); }
|
||||
bool KeyCompareLessThan(const Field *o) const { return *name() < *o->name(); }
|
||||
int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); }
|
||||
const Type *type() const { return GetPointer<const Type *>(VT_TYPE); }
|
||||
uint16_t id() const { return GetField<uint16_t>(VT_ID, 0); }
|
||||
uint16_t offset() const { return GetField<uint16_t>(VT_OFFSET, 0); }
|
||||
int64_t default_integer() const { return GetField<int64_t>(VT_DEFAULT_INTEGER, 0); }
|
||||
double default_real() const { return GetField<double>(VT_DEFAULT_REAL, 0.0); }
|
||||
bool deprecated() const { return GetField<uint8_t>(VT_DEPRECATED, 0) != 0; }
|
||||
bool required() const { return GetField<uint8_t>(VT_REQUIRED, 0) != 0; }
|
||||
bool key() const { return GetField<uint8_t>(VT_KEY, 0) != 0; }
|
||||
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES); }
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
bool KeyCompareLessThan(const Field *o) const {
|
||||
return *name() < *o->name();
|
||||
}
|
||||
int KeyCompareWithValue(const char *val) const {
|
||||
return strcmp(name()->c_str(), val);
|
||||
}
|
||||
const Type *type() const {
|
||||
return GetPointer<const Type *>(VT_TYPE);
|
||||
}
|
||||
uint16_t id() const {
|
||||
return GetField<uint16_t>(VT_ID, 0);
|
||||
}
|
||||
uint16_t offset() const {
|
||||
return GetField<uint16_t>(VT_OFFSET, 0);
|
||||
}
|
||||
int64_t default_integer() const {
|
||||
return GetField<int64_t>(VT_DEFAULT_INTEGER, 0);
|
||||
}
|
||||
double default_real() const {
|
||||
return GetField<double>(VT_DEFAULT_REAL, 0.0);
|
||||
}
|
||||
bool deprecated() const {
|
||||
return GetField<uint8_t>(VT_DEPRECATED, 0) != 0;
|
||||
}
|
||||
bool required() const {
|
||||
return GetField<uint8_t>(VT_REQUIRED, 0) != 0;
|
||||
}
|
||||
bool key() const {
|
||||
return GetField<uint8_t>(VT_KEY, 0) != 0;
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||
}
|
||||
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) &&
|
||||
@@ -307,9 +515,12 @@ 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()) &&
|
||||
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
||||
verifier.Verify(documentation()) &&
|
||||
verifier.VerifyVectorOfStrings(documentation()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
@@ -317,27 +528,55 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
struct FieldBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(Field::VT_NAME, name); }
|
||||
void add_type(flatbuffers::Offset<Type> type) { fbb_.AddOffset(Field::VT_TYPE, type); }
|
||||
void add_id(uint16_t id) { fbb_.AddElement<uint16_t>(Field::VT_ID, id, 0); }
|
||||
void add_offset(uint16_t offset) { fbb_.AddElement<uint16_t>(Field::VT_OFFSET, offset, 0); }
|
||||
void add_default_integer(int64_t default_integer) { fbb_.AddElement<int64_t>(Field::VT_DEFAULT_INTEGER, default_integer, 0); }
|
||||
void add_default_real(double default_real) { fbb_.AddElement<double>(Field::VT_DEFAULT_REAL, default_real, 0.0); }
|
||||
void add_deprecated(bool deprecated) { fbb_.AddElement<uint8_t>(Field::VT_DEPRECATED, static_cast<uint8_t>(deprecated), 0); }
|
||||
void add_required(bool required) { fbb_.AddElement<uint8_t>(Field::VT_REQUIRED, static_cast<uint8_t>(required), 0); }
|
||||
void add_key(bool key) { fbb_.AddElement<uint8_t>(Field::VT_KEY, static_cast<uint8_t>(key), 0); }
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) { fbb_.AddOffset(Field::VT_ATTRIBUTES, attributes); }
|
||||
FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(Field::VT_NAME, name);
|
||||
}
|
||||
void add_type(flatbuffers::Offset<Type> type) {
|
||||
fbb_.AddOffset(Field::VT_TYPE, type);
|
||||
}
|
||||
void add_id(uint16_t id) {
|
||||
fbb_.AddElement<uint16_t>(Field::VT_ID, id, 0);
|
||||
}
|
||||
void add_offset(uint16_t offset) {
|
||||
fbb_.AddElement<uint16_t>(Field::VT_OFFSET, offset, 0);
|
||||
}
|
||||
void add_default_integer(int64_t default_integer) {
|
||||
fbb_.AddElement<int64_t>(Field::VT_DEFAULT_INTEGER, default_integer, 0);
|
||||
}
|
||||
void add_default_real(double default_real) {
|
||||
fbb_.AddElement<double>(Field::VT_DEFAULT_REAL, default_real, 0.0);
|
||||
}
|
||||
void add_deprecated(bool deprecated) {
|
||||
fbb_.AddElement<uint8_t>(Field::VT_DEPRECATED, static_cast<uint8_t>(deprecated), 0);
|
||||
}
|
||||
void add_required(bool required) {
|
||||
fbb_.AddElement<uint8_t>(Field::VT_REQUIRED, static_cast<uint8_t>(required), 0);
|
||||
}
|
||||
void add_key(bool key) {
|
||||
fbb_.AddElement<uint8_t>(Field::VT_KEY, static_cast<uint8_t>(key), 0);
|
||||
}
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) {
|
||||
fbb_.AddOffset(Field::VT_ATTRIBUTES, attributes);
|
||||
}
|
||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||
fbb_.AddOffset(Field::VT_DOCUMENTATION, documentation);
|
||||
}
|
||||
FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
FieldBuilder &operator=(const FieldBuilder &);
|
||||
flatbuffers::Offset<Field> Finish() {
|
||||
auto o = flatbuffers::Offset<Field>(fbb_.EndTable(start_, 10));
|
||||
fbb_.Required(o, Field::VT_NAME); // name
|
||||
fbb_.Required(o, Field::VT_TYPE); // type
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<Field>(end);
|
||||
fbb_.Required(o, Field::VT_NAME);
|
||||
fbb_.Required(o, Field::VT_TYPE);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<Field> CreateField(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
inline flatbuffers::Offset<Field> CreateField(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<Type> type = 0,
|
||||
uint16_t id = 0,
|
||||
@@ -347,10 +586,12 @@ inline flatbuffers::Offset<Field> CreateField(flatbuffers::FlatBufferBuilder &_f
|
||||
bool deprecated = false,
|
||||
bool required = false,
|
||||
bool key = false,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0) {
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||
FieldBuilder builder_(_fbb);
|
||||
builder_.add_default_real(default_real);
|
||||
builder_.add_default_integer(default_integer);
|
||||
builder_.add_documentation(documentation);
|
||||
builder_.add_attributes(attributes);
|
||||
builder_.add_type(type);
|
||||
builder_.add_name(name);
|
||||
@@ -362,7 +603,8 @@ inline flatbuffers::Offset<Field> CreateField(flatbuffers::FlatBufferBuilder &_f
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Field> CreateFieldDirect(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
inline flatbuffers::Offset<Field> CreateFieldDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
flatbuffers::Offset<Type> type = 0,
|
||||
uint16_t id = 0,
|
||||
@@ -372,8 +614,21 @@ inline flatbuffers::Offset<Field> CreateFieldDirect(flatbuffers::FlatBufferBuild
|
||||
bool deprecated = false,
|
||||
bool required = false,
|
||||
bool key = false,
|
||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr) {
|
||||
return CreateField(_fbb, name ? _fbb.CreateString(name) : 0, type, id, offset, default_integer, default_real, deprecated, required, key, attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0);
|
||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||
return reflection::CreateField(
|
||||
_fbb,
|
||||
name ? _fbb.CreateString(name) : 0,
|
||||
type,
|
||||
id,
|
||||
offset,
|
||||
default_integer,
|
||||
default_real,
|
||||
deprecated,
|
||||
required,
|
||||
key,
|
||||
attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0,
|
||||
documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0);
|
||||
}
|
||||
|
||||
struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
@@ -383,29 +638,52 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VT_IS_STRUCT = 8,
|
||||
VT_MINALIGN = 10,
|
||||
VT_BYTESIZE = 12,
|
||||
VT_ATTRIBUTES = 14
|
||||
VT_ATTRIBUTES = 14,
|
||||
VT_DOCUMENTATION = 16
|
||||
};
|
||||
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(VT_NAME); }
|
||||
bool KeyCompareLessThan(const Object *o) const { return *name() < *o->name(); }
|
||||
int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); }
|
||||
const flatbuffers::Vector<flatbuffers::Offset<Field>> *fields() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Field>> *>(VT_FIELDS); }
|
||||
bool is_struct() const { return GetField<uint8_t>(VT_IS_STRUCT, 0) != 0; }
|
||||
int32_t minalign() const { return GetField<int32_t>(VT_MINALIGN, 0); }
|
||||
int32_t bytesize() const { return GetField<int32_t>(VT_BYTESIZE, 0); }
|
||||
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES); }
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
bool KeyCompareLessThan(const Object *o) const {
|
||||
return *name() < *o->name();
|
||||
}
|
||||
int KeyCompareWithValue(const char *val) const {
|
||||
return strcmp(name()->c_str(), val);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<Field>> *fields() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Field>> *>(VT_FIELDS);
|
||||
}
|
||||
bool is_struct() const {
|
||||
return GetField<uint8_t>(VT_IS_STRUCT, 0) != 0;
|
||||
}
|
||||
int32_t minalign() const {
|
||||
return GetField<int32_t>(VT_MINALIGN, 0);
|
||||
}
|
||||
int32_t bytesize() const {
|
||||
return GetField<int32_t>(VT_BYTESIZE, 0);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||
}
|
||||
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()) &&
|
||||
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
||||
verifier.Verify(documentation()) &&
|
||||
verifier.VerifyVectorOfStrings(documentation()) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
@@ -413,30 +691,52 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
struct ObjectBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(Object::VT_NAME, name); }
|
||||
void add_fields(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> fields) { fbb_.AddOffset(Object::VT_FIELDS, fields); }
|
||||
void add_is_struct(bool is_struct) { fbb_.AddElement<uint8_t>(Object::VT_IS_STRUCT, static_cast<uint8_t>(is_struct), 0); }
|
||||
void add_minalign(int32_t minalign) { fbb_.AddElement<int32_t>(Object::VT_MINALIGN, minalign, 0); }
|
||||
void add_bytesize(int32_t bytesize) { fbb_.AddElement<int32_t>(Object::VT_BYTESIZE, bytesize, 0); }
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) { fbb_.AddOffset(Object::VT_ATTRIBUTES, attributes); }
|
||||
ObjectBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(Object::VT_NAME, name);
|
||||
}
|
||||
void add_fields(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> fields) {
|
||||
fbb_.AddOffset(Object::VT_FIELDS, fields);
|
||||
}
|
||||
void add_is_struct(bool is_struct) {
|
||||
fbb_.AddElement<uint8_t>(Object::VT_IS_STRUCT, static_cast<uint8_t>(is_struct), 0);
|
||||
}
|
||||
void add_minalign(int32_t minalign) {
|
||||
fbb_.AddElement<int32_t>(Object::VT_MINALIGN, minalign, 0);
|
||||
}
|
||||
void add_bytesize(int32_t bytesize) {
|
||||
fbb_.AddElement<int32_t>(Object::VT_BYTESIZE, bytesize, 0);
|
||||
}
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) {
|
||||
fbb_.AddOffset(Object::VT_ATTRIBUTES, attributes);
|
||||
}
|
||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||
fbb_.AddOffset(Object::VT_DOCUMENTATION, documentation);
|
||||
}
|
||||
ObjectBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
ObjectBuilder &operator=(const ObjectBuilder &);
|
||||
flatbuffers::Offset<Object> Finish() {
|
||||
auto o = flatbuffers::Offset<Object>(fbb_.EndTable(start_, 6));
|
||||
fbb_.Required(o, Object::VT_NAME); // name
|
||||
fbb_.Required(o, Object::VT_FIELDS); // fields
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<Object>(end);
|
||||
fbb_.Required(o, Object::VT_NAME);
|
||||
fbb_.Required(o, Object::VT_FIELDS);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<Object> CreateObject(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
inline flatbuffers::Offset<Object> CreateObject(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> fields = 0,
|
||||
bool is_struct = false,
|
||||
int32_t minalign = 0,
|
||||
int32_t bytesize = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0) {
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||
ObjectBuilder builder_(_fbb);
|
||||
builder_.add_documentation(documentation);
|
||||
builder_.add_attributes(attributes);
|
||||
builder_.add_bytesize(bytesize);
|
||||
builder_.add_minalign(minalign);
|
||||
@@ -446,14 +746,24 @@ inline flatbuffers::Offset<Object> CreateObject(flatbuffers::FlatBufferBuilder &
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Object> CreateObjectDirect(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
inline flatbuffers::Offset<Object> CreateObjectDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
const std::vector<flatbuffers::Offset<Field>> *fields = nullptr,
|
||||
bool is_struct = false,
|
||||
int32_t minalign = 0,
|
||||
int32_t bytesize = 0,
|
||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr) {
|
||||
return CreateObject(_fbb, name ? _fbb.CreateString(name) : 0, fields ? _fbb.CreateVector<flatbuffers::Offset<Field>>(*fields) : 0, is_struct, minalign, bytesize, attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0);
|
||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||
return reflection::CreateObject(
|
||||
_fbb,
|
||||
name ? _fbb.CreateString(name) : 0,
|
||||
fields ? _fbb.CreateVector<flatbuffers::Offset<Field>>(*fields) : 0,
|
||||
is_struct,
|
||||
minalign,
|
||||
bytesize,
|
||||
attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0,
|
||||
documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0);
|
||||
}
|
||||
|
||||
struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
@@ -464,24 +774,34 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VT_FILE_EXT = 10,
|
||||
VT_ROOT_TABLE = 12
|
||||
};
|
||||
const flatbuffers::Vector<flatbuffers::Offset<Object>> *objects() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Object>> *>(VT_OBJECTS); }
|
||||
const flatbuffers::Vector<flatbuffers::Offset<Enum>> *enums() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Enum>> *>(VT_ENUMS); }
|
||||
const flatbuffers::String *file_ident() const { return GetPointer<const flatbuffers::String *>(VT_FILE_IDENT); }
|
||||
const flatbuffers::String *file_ext() const { return GetPointer<const flatbuffers::String *>(VT_FILE_EXT); }
|
||||
const Object *root_table() const { return GetPointer<const Object *>(VT_ROOT_TABLE); }
|
||||
const flatbuffers::Vector<flatbuffers::Offset<Object>> *objects() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Object>> *>(VT_OBJECTS);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<Enum>> *enums() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Enum>> *>(VT_ENUMS);
|
||||
}
|
||||
const flatbuffers::String *file_ident() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_FILE_IDENT);
|
||||
}
|
||||
const flatbuffers::String *file_ext() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_FILE_EXT);
|
||||
}
|
||||
const Object *root_table() const {
|
||||
return GetPointer<const Object *>(VT_ROOT_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();
|
||||
}
|
||||
@@ -490,22 +810,37 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
struct SchemaBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_objects(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Object>>> objects) { fbb_.AddOffset(Schema::VT_OBJECTS, objects); }
|
||||
void add_enums(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Enum>>> enums) { fbb_.AddOffset(Schema::VT_ENUMS, enums); }
|
||||
void add_file_ident(flatbuffers::Offset<flatbuffers::String> file_ident) { fbb_.AddOffset(Schema::VT_FILE_IDENT, file_ident); }
|
||||
void add_file_ext(flatbuffers::Offset<flatbuffers::String> file_ext) { fbb_.AddOffset(Schema::VT_FILE_EXT, file_ext); }
|
||||
void add_root_table(flatbuffers::Offset<Object> root_table) { fbb_.AddOffset(Schema::VT_ROOT_TABLE, root_table); }
|
||||
SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
|
||||
void add_objects(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Object>>> objects) {
|
||||
fbb_.AddOffset(Schema::VT_OBJECTS, objects);
|
||||
}
|
||||
void add_enums(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Enum>>> enums) {
|
||||
fbb_.AddOffset(Schema::VT_ENUMS, enums);
|
||||
}
|
||||
void add_file_ident(flatbuffers::Offset<flatbuffers::String> file_ident) {
|
||||
fbb_.AddOffset(Schema::VT_FILE_IDENT, file_ident);
|
||||
}
|
||||
void add_file_ext(flatbuffers::Offset<flatbuffers::String> file_ext) {
|
||||
fbb_.AddOffset(Schema::VT_FILE_EXT, file_ext);
|
||||
}
|
||||
void add_root_table(flatbuffers::Offset<Object> root_table) {
|
||||
fbb_.AddOffset(Schema::VT_ROOT_TABLE, root_table);
|
||||
}
|
||||
SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
SchemaBuilder &operator=(const SchemaBuilder &);
|
||||
flatbuffers::Offset<Schema> Finish() {
|
||||
auto o = flatbuffers::Offset<Schema>(fbb_.EndTable(start_, 5));
|
||||
fbb_.Required(o, Schema::VT_OBJECTS); // objects
|
||||
fbb_.Required(o, Schema::VT_ENUMS); // enums
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<Schema>(end);
|
||||
fbb_.Required(o, Schema::VT_OBJECTS);
|
||||
fbb_.Required(o, Schema::VT_ENUMS);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<Schema> CreateSchema(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
inline flatbuffers::Offset<Schema> CreateSchema(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Object>>> objects = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Enum>>> enums = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> file_ident = 0,
|
||||
@@ -520,13 +855,20 @@ inline flatbuffers::Offset<Schema> CreateSchema(flatbuffers::FlatBufferBuilder &
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Schema> CreateSchemaDirect(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
inline flatbuffers::Offset<Schema> CreateSchemaDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const std::vector<flatbuffers::Offset<Object>> *objects = nullptr,
|
||||
const std::vector<flatbuffers::Offset<Enum>> *enums = nullptr,
|
||||
const char *file_ident = nullptr,
|
||||
const char *file_ext = nullptr,
|
||||
flatbuffers::Offset<Object> root_table = 0) {
|
||||
return CreateSchema(_fbb, objects ? _fbb.CreateVector<flatbuffers::Offset<Object>>(*objects) : 0, enums ? _fbb.CreateVector<flatbuffers::Offset<Enum>>(*enums) : 0, file_ident ? _fbb.CreateString(file_ident) : 0, file_ext ? _fbb.CreateString(file_ext) : 0, root_table);
|
||||
return reflection::CreateSchema(
|
||||
_fbb,
|
||||
objects ? _fbb.CreateVector<flatbuffers::Offset<Object>>(*objects) : 0,
|
||||
enums ? _fbb.CreateVector<flatbuffers::Offset<Enum>>(*enums) : 0,
|
||||
file_ident ? _fbb.CreateString(file_ident) : 0,
|
||||
file_ext ? _fbb.CreateString(file_ext) : 0,
|
||||
root_table);
|
||||
}
|
||||
|
||||
inline const reflection::Schema *GetSchema(const void *buf) {
|
||||
@@ -538,16 +880,22 @@ inline const char *SchemaIdentifier() {
|
||||
}
|
||||
|
||||
inline bool SchemaBufferHasIdentifier(const void *buf) {
|
||||
return flatbuffers::BufferHasIdentifier(buf, SchemaIdentifier());
|
||||
return flatbuffers::BufferHasIdentifier(
|
||||
buf, SchemaIdentifier());
|
||||
}
|
||||
|
||||
inline bool VerifySchemaBuffer(flatbuffers::Verifier &verifier) {
|
||||
inline bool VerifySchemaBuffer(
|
||||
flatbuffers::Verifier &verifier) {
|
||||
return verifier.VerifyBuffer<reflection::Schema>(SchemaIdentifier());
|
||||
}
|
||||
|
||||
inline const char *SchemaExtension() { return "bfbs"; }
|
||||
inline const char *SchemaExtension() {
|
||||
return "bfbs";
|
||||
}
|
||||
|
||||
inline void FinishSchemaBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<reflection::Schema> root) {
|
||||
inline void FinishSchemaBuffer(
|
||||
flatbuffers::FlatBufferBuilder &fbb,
|
||||
flatbuffers::Offset<reflection::Schema> root) {
|
||||
fbb.Finish(root, SchemaIdentifier());
|
||||
}
|
||||
|
||||
|
||||
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(), vector_data(include_paths_),
|
||||
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_
|
||||
222
include/flatbuffers/stl_emulation.h
Normal file
222
include/flatbuffers/stl_emulation.h
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* 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_STL_EMULATION_H_
|
||||
#define FLATBUFFERS_STL_EMULATION_H_
|
||||
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <limits>
|
||||
|
||||
#if defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
|
||||
#define FLATBUFFERS_CPP98_STL
|
||||
#endif // defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
|
||||
|
||||
#if defined(FLATBUFFERS_CPP98_STL)
|
||||
#include <cctype>
|
||||
#endif // defined(FLATBUFFERS_CPP98_STL)
|
||||
|
||||
// This header provides backwards compatibility for C++98 STLs like stlport.
|
||||
namespace flatbuffers {
|
||||
|
||||
// Retrieve ::back() from a string in a way that is compatible with pre C++11
|
||||
// STLs (e.g stlport).
|
||||
inline char string_back(const std::string &value) {
|
||||
return value[value.length() - 1];
|
||||
}
|
||||
|
||||
// Helper method that retrieves ::data() from a vector in a way that is
|
||||
// compatible with pre C++11 STLs (e.g stlport).
|
||||
template <typename T> inline T *vector_data(std::vector<T> &vector) {
|
||||
// In some debug environments, operator[] does bounds checking, so &vector[0]
|
||||
// can't be used.
|
||||
return &(*vector.begin());
|
||||
}
|
||||
|
||||
template <typename T> inline const T *vector_data(
|
||||
const std::vector<T> &vector) {
|
||||
return &(*vector.begin());
|
||||
}
|
||||
|
||||
template <typename T, typename V>
|
||||
inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
||||
#if defined(FLATBUFFERS_CPP98_STL)
|
||||
vector->push_back(data);
|
||||
#else
|
||||
vector->emplace_back(std::forward<V>(data));
|
||||
#endif // defined(FLATBUFFERS_CPP98_STL)
|
||||
}
|
||||
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
#if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
||||
template <typename T>
|
||||
using numeric_limits = std::numeric_limits<T>;
|
||||
#else
|
||||
template <typename T> class numeric_limits :
|
||||
public std::numeric_limits<T> {};
|
||||
#endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
||||
#else
|
||||
template <typename T> class numeric_limits :
|
||||
public std::numeric_limits<T> {};
|
||||
|
||||
template <> class numeric_limits<unsigned long long> {
|
||||
public:
|
||||
static unsigned long long min() { return 0ULL; }
|
||||
static unsigned long long max() { return ~0ULL; }
|
||||
};
|
||||
|
||||
template <> class numeric_limits<long long> {
|
||||
public:
|
||||
static long long min() {
|
||||
return static_cast<long long>(1ULL << ((sizeof(long long) << 3) - 1));
|
||||
}
|
||||
static long long max() {
|
||||
return static_cast<long long>(
|
||||
(1ULL << ((sizeof(long long) << 3) - 1)) - 1);
|
||||
}
|
||||
};
|
||||
#endif // FLATBUFFERS_CPP98_STL
|
||||
|
||||
#if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
template <typename T> using is_scalar = std::is_scalar<T>;
|
||||
template <typename T, typename U> using is_same = std::is_same<T,U>;
|
||||
template <typename T> using is_floating_point = std::is_floating_point<T>;
|
||||
template <typename T> using is_unsigned = std::is_unsigned<T>;
|
||||
#else
|
||||
// Map C++ TR1 templates defined by stlport.
|
||||
template <typename T> using is_scalar = std::tr1::is_scalar<T>;
|
||||
template <typename T, typename U> using is_same = std::tr1::is_same<T,U>;
|
||||
template <typename T> using is_floating_point =
|
||||
std::tr1::is_floating_point<T>;
|
||||
template <typename T> using is_unsigned = std::tr1::is_unsigned<T>;
|
||||
#endif // !FLATBUFFERS_CPP98_STL
|
||||
#else
|
||||
// MSVC 2010 doesn't support C++11 aliases.
|
||||
template <typename T> struct is_scalar : public std::is_scalar<T> {};
|
||||
template <typename T, typename U> struct is_same : public std::is_same<T,U> {};
|
||||
template <typename T> struct is_floating_point :
|
||||
public std::is_floating_point<T> {};
|
||||
template <typename T> struct is_unsigned : public std::is_unsigned<T> {};
|
||||
#endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
||||
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
#if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
||||
template <class T> using unique_ptr = std::unique_ptr<T>;
|
||||
#else
|
||||
// MSVC 2010 doesn't support C++11 aliases.
|
||||
// We're manually "aliasing" the class here as we want to bring unique_ptr
|
||||
// into the flatbuffers namespace. We have unique_ptr in the flatbuffers
|
||||
// namespace we have a completely independent implemenation (see below)
|
||||
// for C++98 STL implementations.
|
||||
template <class T> class unique_ptr : public std::unique_ptr<T> {
|
||||
public:
|
||||
unique_ptr() {}
|
||||
explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {}
|
||||
unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); }
|
||||
unique_ptr(unique_ptr&& u) { *this = std::move(u); }
|
||||
unique_ptr& operator=(std::unique_ptr<T>&& u) {
|
||||
std::unique_ptr<T>::reset(u.release());
|
||||
return *this;
|
||||
}
|
||||
unique_ptr& operator=(unique_ptr&& u) {
|
||||
std::unique_ptr<T>::reset(u.release());
|
||||
return *this;
|
||||
}
|
||||
unique_ptr& operator=(T* p) {
|
||||
return std::unique_ptr<T>::operator=(p);
|
||||
}
|
||||
};
|
||||
#endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
||||
#else
|
||||
// Very limited implementation of unique_ptr.
|
||||
// This is provided simply to allow the C++ code generated from the default
|
||||
// settings to function in C++98 environments with no modifications.
|
||||
template <class T> class unique_ptr {
|
||||
public:
|
||||
typedef T element_type;
|
||||
|
||||
unique_ptr() : ptr_(nullptr) {}
|
||||
explicit unique_ptr(T* p) : ptr_(p) {}
|
||||
unique_ptr(unique_ptr&& u) : ptr_(nullptr) { reset(u.release()); }
|
||||
unique_ptr(const unique_ptr& u) : ptr_(nullptr) {
|
||||
reset(const_cast<unique_ptr*>(&u)->release());
|
||||
}
|
||||
~unique_ptr() { reset(); }
|
||||
|
||||
unique_ptr& operator=(const unique_ptr& u) {
|
||||
reset(const_cast<unique_ptr*>(&u)->release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
unique_ptr& operator=(unique_ptr&& u) {
|
||||
reset(u.release());
|
||||
return *this;
|
||||
}
|
||||
|
||||
unique_ptr& operator=(T* p) {
|
||||
reset(p);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const T& operator*() const { return *ptr_; }
|
||||
T* operator->() const { return ptr_; }
|
||||
T* get() const noexcept { return ptr_; }
|
||||
explicit operator bool() const { return ptr_ != nullptr; }
|
||||
|
||||
// modifiers
|
||||
T* release() {
|
||||
T* value = ptr_;
|
||||
ptr_ = nullptr;
|
||||
return value;
|
||||
}
|
||||
|
||||
void reset(T* p = nullptr) {
|
||||
T* value = ptr_;
|
||||
ptr_ = p;
|
||||
if (value) delete value;
|
||||
}
|
||||
|
||||
void swap(unique_ptr& u) {
|
||||
T* temp_ptr = ptr_;
|
||||
ptr_ = u.ptr_;
|
||||
u.ptr_ = temp_ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
T* ptr_;
|
||||
};
|
||||
|
||||
template <class T> bool operator==(const unique_ptr<T>& x,
|
||||
const unique_ptr<T>& y) {
|
||||
return x.get() == y.get();
|
||||
}
|
||||
|
||||
template <class T, class D> bool operator==(const unique_ptr<T>& x,
|
||||
const D* y) {
|
||||
return static_cast<D*>(x.get()) == y;
|
||||
}
|
||||
|
||||
template <class T> bool operator==(const unique_ptr<T>& x, intptr_t y) {
|
||||
return reinterpret_cast<intptr_t>(x.get()) == y;
|
||||
}
|
||||
#endif // !FLATBUFFERS_CPP98_STL
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_STL_EMULATION_H_
|
||||
@@ -40,7 +40,8 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/base.h"
|
||||
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
@@ -59,6 +60,20 @@ template<> inline std::string NumToString<signed char>(signed char t) {
|
||||
template<> inline std::string NumToString<unsigned char>(unsigned char t) {
|
||||
return NumToString(static_cast<int>(t));
|
||||
}
|
||||
#if defined(FLATBUFFERS_CPP98_STL)
|
||||
template <> inline std::string NumToString<long long>(long long t) {
|
||||
char buf[21]; // (log((1 << 63) - 1) / log(10)) + 2
|
||||
snprintf(buf, sizeof(buf), "%lld", t);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
template <> inline std::string NumToString<unsigned long long>(
|
||||
unsigned long long t) {
|
||||
char buf[22]; // (log((1 << 63) - 1) / log(10)) + 1
|
||||
snprintf(buf, sizeof(buf), "%llu", t);
|
||||
return std::string(buf);
|
||||
}
|
||||
#endif // defined(FLATBUFFERS_CPP98_STL)
|
||||
|
||||
// Special versions for floats/doubles.
|
||||
template<> inline std::string NumToString<double>(double t) {
|
||||
@@ -71,9 +86,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;
|
||||
}
|
||||
@@ -95,7 +109,8 @@ inline std::string IntToStringHex(int i, int xdigits) {
|
||||
}
|
||||
|
||||
// Portable implementation of strtoll().
|
||||
inline int64_t StringToInt(const char *str, char **endptr = nullptr, int base = 10) {
|
||||
inline int64_t StringToInt(const char *str, char **endptr = nullptr,
|
||||
int base = 10) {
|
||||
#ifdef _MSC_VER
|
||||
return _strtoi64(str, endptr, base);
|
||||
#else
|
||||
@@ -104,7 +119,8 @@ inline int64_t StringToInt(const char *str, char **endptr = nullptr, int base =
|
||||
}
|
||||
|
||||
// Portable implementation of strtoull().
|
||||
inline int64_t StringToUInt(const char *str, char **endptr = nullptr, int base = 10) {
|
||||
inline uint64_t StringToUInt(const char *str, char **endptr = nullptr,
|
||||
int base = 10) {
|
||||
#ifdef _MSC_VER
|
||||
return _strtoui64(str, endptr, base);
|
||||
#else
|
||||
@@ -155,16 +171,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) {
|
||||
@@ -195,13 +215,25 @@ 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()) {
|
||||
char filepath_last_character = string_back(filepath);
|
||||
if (filepath_last_character == kPathSeparatorWindows) {
|
||||
filepath_last_character = kPathSeparator;
|
||||
} else if (filepath_last_character != 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) {
|
||||
@@ -343,6 +375,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_
|
||||
|
||||
@@ -18,13 +18,13 @@ package com.google.flatbuffers;
|
||||
|
||||
import static com.google.flatbuffers.Constants.*;
|
||||
|
||||
import java.nio.CharBuffer;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.*;
|
||||
import java.nio.charset.CharacterCodingException;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.nio.charset.CoderResult;
|
||||
import java.util.Arrays;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/// @file
|
||||
@@ -52,26 +52,51 @@ public class FlatBufferBuilder {
|
||||
boolean force_defaults = false; // False omits default values from the serialized data.
|
||||
CharsetEncoder encoder = utf8charset.newEncoder();
|
||||
ByteBuffer dst;
|
||||
ByteBufferFactory bb_factory; // Factory for allocating the internal buffer
|
||||
/// @endcond
|
||||
|
||||
/**
|
||||
* Start with a buffer of size `initial_size`, then grow as required.
|
||||
*
|
||||
* @param initial_size The initial size of the internal buffer to use.
|
||||
* @param bb_factory The factory to be used for allocating the internal buffer
|
||||
*/
|
||||
public FlatBufferBuilder(int initial_size, ByteBufferFactory bb_factory) {
|
||||
if (initial_size <= 0) initial_size = 1;
|
||||
space = initial_size;
|
||||
this.bb_factory = bb_factory;
|
||||
bb = bb_factory.newByteBuffer(initial_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start with a buffer of size `initial_size`, then grow as required.
|
||||
*
|
||||
* @param initial_size The initial size of the internal buffer to use.
|
||||
*/
|
||||
public FlatBufferBuilder(int initial_size) {
|
||||
if (initial_size <= 0) initial_size = 1;
|
||||
space = initial_size;
|
||||
bb = newByteBuffer(initial_size);
|
||||
this(initial_size, new HeapByteBufferFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
* Start with a buffer of 1KiB, then grow as required.
|
||||
*/
|
||||
/**
|
||||
* Start with a buffer of 1KiB, then grow as required.
|
||||
*/
|
||||
public FlatBufferBuilder() {
|
||||
this(1024);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternative constructor allowing reuse of {@link ByteBuffer}s. The builder
|
||||
* can still grow the buffer as necessary. User classes should make sure
|
||||
* to call {@link #dataBuffer()} to obtain the resulting encoded message.
|
||||
*
|
||||
* @param existing_bb The byte buffer to reuse.
|
||||
* @param bb_factory The factory to be used for allocating a new internal buffer if
|
||||
* the existing buffer needs to grow
|
||||
*/
|
||||
public FlatBufferBuilder(ByteBuffer existing_bb, ByteBufferFactory bb_factory) {
|
||||
init(existing_bb, bb_factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternative constructor allowing reuse of {@link ByteBuffer}s. The builder
|
||||
* can still grow the buffer as necessary. User classes should make sure
|
||||
@@ -80,7 +105,7 @@ public class FlatBufferBuilder {
|
||||
* @param existing_bb The byte buffer to reuse.
|
||||
*/
|
||||
public FlatBufferBuilder(ByteBuffer existing_bb) {
|
||||
init(existing_bb);
|
||||
init(existing_bb, new HeapByteBufferFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,9 +114,12 @@ public class FlatBufferBuilder {
|
||||
* objects that have been allocated for temporary storage.
|
||||
*
|
||||
* @param existing_bb The byte buffer to reuse.
|
||||
* @param bb_factory The factory to be used for allocating a new internal buffer if
|
||||
* the existing buffer needs to grow
|
||||
* @return Returns `this`.
|
||||
*/
|
||||
public FlatBufferBuilder init(ByteBuffer existing_bb){
|
||||
public FlatBufferBuilder init(ByteBuffer existing_bb, ByteBufferFactory bb_factory){
|
||||
this.bb_factory = bb_factory;
|
||||
bb = existing_bb;
|
||||
bb.clear();
|
||||
bb.order(ByteOrder.LITTLE_ENDIAN);
|
||||
@@ -106,17 +134,53 @@ public class FlatBufferBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
/**
|
||||
* Create a `ByteBuffer` with a given capacity.
|
||||
* An interface that provides a user of the FlatBufferBuilder class the ability to specify
|
||||
* the method in which the internal buffer gets allocated. This allows for alternatives
|
||||
* to the default behavior, which is to allocate memory for a new byte-array
|
||||
* backed `ByteBuffer` array inside the JVM.
|
||||
*
|
||||
* @param capacity The size of the `ByteBuffer` to allocate.
|
||||
* @return Returns the new `ByteBuffer` that was allocated.
|
||||
* The FlatBufferBuilder class contains the HeapByteBufferFactory class to
|
||||
* preserve the default behavior in the event that the user does not provide
|
||||
* their own implementation of this interface.
|
||||
*/
|
||||
static ByteBuffer newByteBuffer(int capacity) {
|
||||
ByteBuffer newbb = ByteBuffer.allocate(capacity);
|
||||
newbb.order(ByteOrder.LITTLE_ENDIAN);
|
||||
return newbb;
|
||||
public interface ByteBufferFactory {
|
||||
/**
|
||||
* Create a `ByteBuffer` with a given capacity.
|
||||
*
|
||||
* @param capacity The size of the `ByteBuffer` to allocate.
|
||||
* @return Returns the new `ByteBuffer` that was allocated.
|
||||
*/
|
||||
ByteBuffer newByteBuffer(int capacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* An implementation of the ByteBufferFactory interface that is used when
|
||||
* one is not provided by the user.
|
||||
*
|
||||
* Allocate memory for a new byte-array backed `ByteBuffer` array inside the JVM.
|
||||
*/
|
||||
public static final class HeapByteBufferFactory implements ByteBufferFactory {
|
||||
@Override
|
||||
public ByteBuffer newByteBuffer(int capacity) {
|
||||
return ByteBuffer.allocate(capacity).order(ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,16 +188,17 @@ public class FlatBufferBuilder {
|
||||
* end of the new buffer (since we build the buffer backwards).
|
||||
*
|
||||
* @param bb The current buffer with the existing data.
|
||||
* @param bb_factory The factory to be used for allocating the new internal buffer
|
||||
* @return A new byte buffer with the old data copied copied to it. The data is
|
||||
* located at the end of the buffer.
|
||||
*/
|
||||
static ByteBuffer growByteBuffer(ByteBuffer bb) {
|
||||
static ByteBuffer growByteBuffer(ByteBuffer bb, ByteBufferFactory bb_factory) {
|
||||
int old_buf_size = bb.capacity();
|
||||
if ((old_buf_size & 0xC0000000) != 0) // Ensure we don't grow beyond what fits in an int.
|
||||
throw new AssertionError("FlatBuffers: cannot grow buffer beyond 2 gigabytes.");
|
||||
int new_buf_size = old_buf_size << 1;
|
||||
bb.position(0);
|
||||
ByteBuffer nbb = newByteBuffer(new_buf_size);
|
||||
ByteBuffer nbb = bb_factory.newByteBuffer(new_buf_size);
|
||||
nbb.position(new_buf_size - old_buf_size);
|
||||
nbb.put(bb);
|
||||
return nbb;
|
||||
@@ -176,7 +241,7 @@ public class FlatBufferBuilder {
|
||||
// Reallocate the buffer if needed.
|
||||
while (space < align_size + size + additional_bytes) {
|
||||
int old_buf_size = bb.capacity();
|
||||
bb = growByteBuffer(bb);
|
||||
bb = growByteBuffer(bb, bb_factory);
|
||||
space += bb.capacity() - old_buf_size;
|
||||
}
|
||||
pad(align_size);
|
||||
@@ -413,7 +478,7 @@ public class FlatBufferBuilder {
|
||||
obj.sortTables(offsets, bb);
|
||||
return createVectorOfTables(offsets);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encode the string `s` in the buffer using UTF-8. If {@code s} is
|
||||
* already a {@link CharBuffer}, this method is allocation free.
|
||||
@@ -679,7 +744,11 @@ public class FlatBufferBuilder {
|
||||
addInt(0);
|
||||
int vtableloc = offset();
|
||||
// Write out the current vtable.
|
||||
for (int i = vtable_in_use - 1; i >= 0 ; i--) {
|
||||
int i = vtable_in_use - 1;
|
||||
// Trim trailing zeroes.
|
||||
for (; i >= 0 && vtable[i] == 0; i--) {}
|
||||
int trimmed_size = i + 1;
|
||||
for (; i >= 0 ; i--) {
|
||||
// Offset relative to the start of the table.
|
||||
short off = (short)(vtable[i] != 0 ? vtableloc - vtable[i] : 0);
|
||||
addShort(off);
|
||||
@@ -687,12 +756,12 @@ public class FlatBufferBuilder {
|
||||
|
||||
final int standard_fields = 2; // The fields below:
|
||||
addShort((short)(vtableloc - object_start));
|
||||
addShort((short)((vtable_in_use + standard_fields) * SIZEOF_SHORT));
|
||||
addShort((short)((trimmed_size + standard_fields) * SIZEOF_SHORT));
|
||||
|
||||
// Search for an existing vtable that matches the current one.
|
||||
int existing_vtable = 0;
|
||||
outer_loop:
|
||||
for (int i = 0; i < num_vtables; i++) {
|
||||
for (i = 0; i < num_vtables; i++) {
|
||||
int vt1 = bb.capacity() - vtables[i];
|
||||
int vt2 = space;
|
||||
short len = bb.getShort(vt1);
|
||||
@@ -837,6 +906,41 @@ public class FlatBufferBuilder {
|
||||
public byte[] sizedByteArray() {
|
||||
return sizedByteArray(space, bb.capacity() - space);
|
||||
}
|
||||
|
||||
/**
|
||||
* A utility function to return an InputStream to the ByteBuffer data
|
||||
*
|
||||
* @return An InputStream that starts at the beginning of the ByteBuffer data
|
||||
* and can read to the end of it.
|
||||
*/
|
||||
public InputStream sizedInputStream() {
|
||||
finished();
|
||||
ByteBuffer duplicate = bb.duplicate();
|
||||
duplicate.position(space);
|
||||
duplicate.limit(bb.capacity());
|
||||
return new ByteBufferBackedInputStream(duplicate);
|
||||
}
|
||||
|
||||
/**
|
||||
* A class that allows a user to create an InputStream from a ByteBuffer.
|
||||
*/
|
||||
static class ByteBufferBackedInputStream extends InputStream {
|
||||
|
||||
ByteBuffer buf;
|
||||
|
||||
public ByteBufferBackedInputStream(ByteBuffer buf) {
|
||||
this.buf = buf;
|
||||
}
|
||||
|
||||
public int read() throws IOException {
|
||||
try {
|
||||
return buf.get() & 0xFF;
|
||||
} catch(BufferUnderflowException e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class Table {
|
||||
}
|
||||
|
||||
protected static int __offset(int vtable_offset, int offset, ByteBuffer bb) {
|
||||
int vtable = bb.array().length - offset;
|
||||
int vtable = bb.capacity() - offset;
|
||||
return bb.getShort(vtable + vtable_offset - bb.getInt(vtable)) + vtable;
|
||||
}
|
||||
|
||||
@@ -245,10 +245,9 @@ public class Table {
|
||||
int startPos_1 = offset_1 + SIZEOF_INT;
|
||||
int startPos_2 = offset_2 + SIZEOF_INT;
|
||||
int len = Math.min(len_1, len_2);
|
||||
byte[] bbArray = bb.array();
|
||||
for(int i = 0; i < len; i++) {
|
||||
if (bbArray[i + startPos_1] != bbArray[i + startPos_2])
|
||||
return bbArray[i + startPos_1] - bbArray[i + startPos_2];
|
||||
if (bb.get(i + startPos_1) != bb.get(i + startPos_2))
|
||||
return bb.get(i + startPos_1) - bb.get(i + startPos_2);
|
||||
}
|
||||
return len_1 - len_2;
|
||||
}
|
||||
@@ -266,10 +265,9 @@ public class Table {
|
||||
int len_2 = key.length;
|
||||
int startPos_1 = offset_1 + Constants.SIZEOF_INT;
|
||||
int len = Math.min(len_1, len_2);
|
||||
byte[] bbArray = bb.array();
|
||||
for (int i = 0; i < len; i++) {
|
||||
if (bbArray[i + startPos_1] != key[i])
|
||||
return bbArray[i + startPos_1] - key[i];
|
||||
if (bb.get(i + startPos_1) != key[i])
|
||||
return bb.get(i + startPos_1) - key[i];
|
||||
}
|
||||
return len_1 - len_2;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,15 @@
|
||||
/// @addtogroup flatbuffers_javascript_api
|
||||
/// @{
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
|
||||
/**
|
||||
* @fileoverview
|
||||
*
|
||||
* Need to suppress 'global this' error so the Node.js export line doesn't cause
|
||||
* closure compile to error out.
|
||||
* @suppress {globalThis}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @namespace
|
||||
@@ -106,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;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -530,6 +539,10 @@ flatbuffers.Builder.prototype.offset = function() {
|
||||
* @param {flatbuffers.ByteBuffer} bb The current buffer with the existing data
|
||||
* @returns {flatbuffers.ByteBuffer} A new byte buffer with the old data copied
|
||||
* to it. The data is located at the end of the buffer.
|
||||
*
|
||||
* uint8Array.set() formally takes {Array<number>|ArrayBufferView}, so to pass
|
||||
* it a uint8Array we need to suppress the type check:
|
||||
* @suppress {checkTypes}
|
||||
*/
|
||||
flatbuffers.Builder.growByteBuffer = function(bb) {
|
||||
var old_buf_size = bb.capacity();
|
||||
@@ -591,23 +604,28 @@ flatbuffers.Builder.prototype.endObject = function() {
|
||||
this.addInt32(0);
|
||||
var vtableloc = this.offset();
|
||||
|
||||
// Trim trailing zeroes.
|
||||
var i = this.vtable_in_use - 1;
|
||||
for (; i >= 0 && this.vtable[i] == 0; i--) {}
|
||||
var trimmed_size = i + 1;
|
||||
|
||||
// Write out the current vtable.
|
||||
for (var i = this.vtable_in_use - 1; i >= 0; i--) {
|
||||
for (; i >= 0; i--) {
|
||||
// Offset relative to the start of the table.
|
||||
this.addInt16(this.vtable[i] != 0 ? vtableloc - this.vtable[i] : 0);
|
||||
}
|
||||
|
||||
var standard_fields = 2; // The fields below:
|
||||
this.addInt16(vtableloc - this.object_start);
|
||||
this.addInt16((this.vtable_in_use + standard_fields) * flatbuffers.SIZEOF_SHORT);
|
||||
var len = (trimmed_size + standard_fields) * flatbuffers.SIZEOF_SHORT;
|
||||
this.addInt16(len);
|
||||
|
||||
// Search for an existing vtable that matches the current one.
|
||||
var existing_vtable = 0;
|
||||
var vt1 = this.space;
|
||||
outer_loop:
|
||||
for (var i = 0; i < this.vtables.length; i++) {
|
||||
var vt1 = this.bb.capacity() - this.vtables[i];
|
||||
var vt2 = this.space;
|
||||
var len = this.bb.readInt16(vt1);
|
||||
for (i = 0; i < this.vtables.length; i++) {
|
||||
var vt2 = this.bb.capacity() - this.vtables[i];
|
||||
if (len == this.bb.readInt16(vt2)) {
|
||||
for (var j = flatbuffers.SIZEOF_SHORT; j < len; j += flatbuffers.SIZEOF_SHORT) {
|
||||
if (this.bb.readInt16(vt1 + j) != this.bb.readInt16(vt2 + j)) {
|
||||
@@ -931,9 +949,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;
|
||||
};
|
||||
|
||||
@@ -946,6 +972,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
|
||||
@@ -957,6 +992,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
|
||||
@@ -966,6 +1012,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
|
||||
|
||||
0
net/FlatBuffers/ByteBuffer.cs
Executable file → Normal file
0
net/FlatBuffers/ByteBuffer.cs
Executable file → Normal file
@@ -500,7 +500,11 @@ namespace FlatBuffers
|
||||
AddInt((int)0);
|
||||
var vtableloc = Offset;
|
||||
// Write out the current vtable.
|
||||
for (int i = _vtableSize - 1; i >= 0 ; i--) {
|
||||
int i = _vtableSize - 1;
|
||||
// Trim trailing zeroes.
|
||||
for (; i >= 0 && _vtable[i] == 0; i--) {}
|
||||
int trimmedSize = i + 1;
|
||||
for (; i >= 0 ; i--) {
|
||||
// Offset relative to the start of the table.
|
||||
short off = (short)(_vtable[i] != 0
|
||||
? vtableloc - _vtable[i]
|
||||
@@ -513,12 +517,12 @@ namespace FlatBuffers
|
||||
|
||||
const int standardFields = 2; // The fields below:
|
||||
AddShort((short)(vtableloc - _objectStart));
|
||||
AddShort((short)((_vtableSize + standardFields) *
|
||||
AddShort((short)((trimmedSize + standardFields) *
|
||||
sizeof(short)));
|
||||
|
||||
// Search for an existing vtable that matches the current one.
|
||||
int existingVtable = 0;
|
||||
for (int i = 0; i < _numVtables; i++) {
|
||||
for (i = 0; i < _numVtables; i++) {
|
||||
int vt1 = _bb.Length - _vtables[i];
|
||||
int vt2 = _space;
|
||||
short len = _bb.GetShort(vt1);
|
||||
|
||||
27
package.json
Normal file
27
package.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "flatbuffers",
|
||||
"version": "1.8.0",
|
||||
"description": "Memory Efficient Serialization Library",
|
||||
"files": ["js/flatbuffers.js"],
|
||||
"main": "js/flatbuffers.js",
|
||||
"directories": {
|
||||
"doc": "docs",
|
||||
"test": "tests"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "tests/JavaScriptTest.sh"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/google/flatbuffers.git"
|
||||
},
|
||||
"keywords": [
|
||||
"flatbuffers"
|
||||
],
|
||||
"author": "The FlatBuffers project",
|
||||
"license": "SEE LICENSE IN LICENSE.txt",
|
||||
"bugs": {
|
||||
"url": "https://github.com/google/flatbuffers/issues"
|
||||
},
|
||||
"homepage": "https://google.github.io/flatbuffers/"
|
||||
}
|
||||
@@ -596,7 +596,7 @@ class FlatbufferBuilder
|
||||
if (function_exists('mb_detect_encoding')) {
|
||||
return (bool) mb_detect_encoding($bytes, 'UTF-8', true);
|
||||
}
|
||||
|
||||
|
||||
$len = strlen($bytes);
|
||||
if ($len < 1) {
|
||||
/* NOTE: always return 1 when passed string is null */
|
||||
@@ -812,14 +812,18 @@ class FlatbufferBuilder
|
||||
$this->addInt(0);
|
||||
$vtableloc = $this->offset();
|
||||
|
||||
for ($i = $this->vtable_in_use -1; $i >= 0; $i--) {
|
||||
$i = $this->vtable_in_use -1;
|
||||
// Trim trailing zeroes.
|
||||
for (; $i >= 0 && $this->vtable[$i] == 0; $i--) {}
|
||||
$trimmed_size = $i + 1;
|
||||
for (; $i >= 0; $i--) {
|
||||
$off = ($this->vtable[$i] != 0) ? $vtableloc - $this->vtable[$i] : 0;
|
||||
$this->addShort($off);
|
||||
}
|
||||
|
||||
$standard_fields = 2; // the fields below
|
||||
$this->addShort($vtableloc - $this->object_start);
|
||||
$this->addShort(($this->vtable_in_use + $standard_fields) * Constants::SIZEOF_SHORT);
|
||||
$this->addShort(($trimmed_size + $standard_fields) * Constants::SIZEOF_SHORT);
|
||||
|
||||
// search for an existing vtable that matches the current one.
|
||||
$existing_vtable = 0;
|
||||
|
||||
@@ -28,4 +28,14 @@ abstract class Struct
|
||||
* @var ByteBuffer $bb
|
||||
*/
|
||||
protected $bb;
|
||||
|
||||
public function setByteBufferPos($pos)
|
||||
{
|
||||
$this->bb_pos = $pos;
|
||||
}
|
||||
|
||||
public function setByteBuffer($bb)
|
||||
{
|
||||
$this->bb = $bb;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,16 @@ abstract class Table
|
||||
{
|
||||
}
|
||||
|
||||
public function setByteBufferPos($pos)
|
||||
{
|
||||
$this->bb_pos = $pos;
|
||||
}
|
||||
|
||||
public function setByteBuffer($bb)
|
||||
{
|
||||
$this->bb = $bb;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns actual vtable offset
|
||||
*
|
||||
@@ -107,8 +117,8 @@ abstract class Table
|
||||
protected function __union($table, $offset)
|
||||
{
|
||||
$offset += $this->bb_pos;
|
||||
$table->bb_pos = $offset + $this->bb->getInt($offset);
|
||||
$table->bb = $this->bb;
|
||||
$table->setByteBufferPos($offset + $this->bb->getInt($offset));
|
||||
$table->setByteBuffer($this->bb);
|
||||
return $table;
|
||||
}
|
||||
|
||||
|
||||
51
pom.xml
51
pom.xml
@@ -5,17 +5,20 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.google.flatbuffers</groupId>
|
||||
<artifactId>flatbuffers-java</artifactId>
|
||||
<version>1.5.0-SNAPSHOT</version>
|
||||
<version>1.8.0</version>
|
||||
<packaging>bundle</packaging>
|
||||
<name>FlatBuffers Java API</name>
|
||||
<description>
|
||||
Memory Efficient Serialization Library
|
||||
</description>
|
||||
|
||||
<developers>
|
||||
<developer>
|
||||
<name>Wouter van Oortmerssen</name>
|
||||
</developer>
|
||||
</developers>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<url>https://github.com/google/flatbuffers</url>
|
||||
<licenses>
|
||||
<license>
|
||||
@@ -32,6 +35,12 @@
|
||||
</scm>
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
<distributionManagement>
|
||||
<snapshotRepository>
|
||||
<id>ossrh</id>
|
||||
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
<build>
|
||||
<sourceDirectory>java</sourceDirectory>
|
||||
<plugins>
|
||||
@@ -84,6 +93,42 @@
|
||||
<version>3.0.1</version>
|
||||
<extensions>true</extensions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.sonatype.plugins</groupId>
|
||||
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||
<version>1.6.7</version>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<serverId>ossrh</serverId>
|
||||
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
|
||||
<autoReleaseAfterClose>true</autoReleaseAfterClose>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-gpg-plugin</artifactId>
|
||||
<version>1.5</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>sign-artifacts</id>
|
||||
<phase>verify</phase>
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-release-plugin</artifactId>
|
||||
<version>2.5.3</version>
|
||||
<configuration>
|
||||
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||
<useReleaseProfile>false</useReleaseProfile>
|
||||
<releaseProfiles>release</releaseProfiles>
|
||||
<goals>deploy</goals>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
@@ -193,6 +193,10 @@ class Builder(object):
|
||||
objectOffset = self.Offset()
|
||||
existingVtable = None
|
||||
|
||||
# Trim trailing 0 offsets.
|
||||
while self.current_vtable and self.current_vtable[-1] == 0:
|
||||
self.current_vtable.pop()
|
||||
|
||||
# Search backwards through existing vtables, because similar vtables
|
||||
# are likely to have been recently appended. See
|
||||
# BenchmarkVtableDeduplication for a case in which this heuristic
|
||||
@@ -417,6 +421,27 @@ class Builder(object):
|
||||
|
||||
return self.EndVector(len(x))
|
||||
|
||||
def CreateByteVector(self, x):
|
||||
"""CreateString writes a byte vector."""
|
||||
|
||||
self.assertNotNested()
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
self.nested = True
|
||||
## @endcond
|
||||
|
||||
if not isinstance(x, compat.binary_types):
|
||||
raise TypeError("non-byte vector passed to CreateByteVector")
|
||||
|
||||
self.Prep(N.UOffsetTFlags.bytewidth, len(x)*N.Uint8Flags.bytewidth)
|
||||
|
||||
l = UOffsetTFlags.py_type(len(x))
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
self.head = UOffsetTFlags.py_type(self.Head() - l)
|
||||
## @endcond
|
||||
self.Bytes[self.Head():self.Head()+l] = x
|
||||
|
||||
return self.EndVector(len(x))
|
||||
|
||||
## @cond FLATBUFFERS_INTERNAL
|
||||
def assertNested(self):
|
||||
"""
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
""" A tiny version of `six` to help with backwards compability. """
|
||||
""" A tiny version of `six` to help with backwards compability. Also includes
|
||||
compatibility helpers for numpy. """
|
||||
|
||||
import sys
|
||||
import imp
|
||||
|
||||
PY2 = sys.version_info[0] == 2
|
||||
PY26 = sys.version_info[0:2] == (2, 6)
|
||||
@@ -43,4 +45,37 @@ else:
|
||||
memoryview_type = memoryview
|
||||
struct_bool_decl = "?"
|
||||
|
||||
# Helper functions to facilitate making numpy optional instead of required
|
||||
|
||||
def import_numpy():
|
||||
"""
|
||||
Returns the numpy module if it exists on the system,
|
||||
otherwise returns None.
|
||||
"""
|
||||
try:
|
||||
imp.find_module('numpy')
|
||||
numpy_exists = True
|
||||
except ImportError:
|
||||
numpy_exists = False
|
||||
|
||||
if numpy_exists:
|
||||
# We do this outside of try/except block in case numpy exists
|
||||
# but is not installed correctly. We do not want to catch an
|
||||
# incorrect installation which would manifest as an
|
||||
# ImportError.
|
||||
import numpy as np
|
||||
else:
|
||||
np = None
|
||||
|
||||
return np
|
||||
|
||||
|
||||
class NumpyRequiredForThisFeature(RuntimeError):
|
||||
"""
|
||||
Error raised when user tries to use a feature that
|
||||
requires numpy without having numpy installed.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
# NOTE: Future Jython support may require code here (look at `six`).
|
||||
|
||||
@@ -15,13 +15,26 @@
|
||||
from . import number_types as N
|
||||
from . import packer
|
||||
from .compat import memoryview_type
|
||||
from .compat import import_numpy, NumpyRequiredForThisFeature
|
||||
|
||||
np = import_numpy()
|
||||
|
||||
def Get(packer_type, buf, head):
|
||||
""" Get decodes a value at buf[head:] using `packer_type`. """
|
||||
""" Get decodes a value at buf[head] using `packer_type`. """
|
||||
return packer_type.unpack_from(memoryview_type(buf), head)[0]
|
||||
|
||||
|
||||
def GetVectorAsNumpy(numpy_type, buf, count, offset):
|
||||
""" GetVecAsNumpy decodes values starting at buf[head] as
|
||||
`numpy_type`, where `numpy_type` is a numpy dtype. """
|
||||
if np is not None:
|
||||
# TODO: could set .flags.writeable = False to make users jump through
|
||||
# hoops before modifying...
|
||||
return np.frombuffer(buf, dtype=numpy_type, count=count, offset=offset)
|
||||
else:
|
||||
raise NumpyRequiredForThisFeature('Numpy was not found.')
|
||||
|
||||
|
||||
def Write(packer_type, buf, head, n):
|
||||
""" Write encodes `n` at buf[head:] using `packer_type`. """
|
||||
""" Write encodes `n` at buf[head] using `packer_type`. """
|
||||
packer_type.pack_into(buf, head, n)
|
||||
|
||||
@@ -16,7 +16,9 @@ import collections
|
||||
import struct
|
||||
|
||||
from . import packer
|
||||
from .compat import import_numpy, NumpyRequiredForThisFeature
|
||||
|
||||
np = import_numpy()
|
||||
|
||||
# For reference, see:
|
||||
# https://docs.python.org/2/library/ctypes.html#ctypes-fundamental-data-types-2
|
||||
@@ -170,3 +172,10 @@ def uint64_to_float64(n):
|
||||
packed = struct.pack("<1Q", n)
|
||||
(unpacked,) = struct.unpack("<1d", packed)
|
||||
return unpacked
|
||||
|
||||
|
||||
def to_numpy_type(number_type):
|
||||
if np is not None:
|
||||
return np.dtype(number_type.name).newbyteorder('<')
|
||||
else:
|
||||
raise NumpyRequiredForThisFeature('Numpy was not found.')
|
||||
|
||||
@@ -101,6 +101,18 @@ class Table(object):
|
||||
return d
|
||||
return self.Get(validator_flags, self.Pos + off)
|
||||
|
||||
def GetVectorAsNumpy(self, flags, off):
|
||||
"""
|
||||
GetVectorAsNumpy returns the vector that starts at `Vector(off)`
|
||||
as a numpy array with the type specified by `flags`. The array is
|
||||
a `view` into Bytes, so modifying the returned array will
|
||||
modify Bytes in place.
|
||||
"""
|
||||
offset = self.Vector(off)
|
||||
length = self.VectorLen(off) # TODO: length accounts for bytewidth, right?
|
||||
numpy_dtype = N.to_numpy_type(flags)
|
||||
return encode.GetVectorAsNumpy(numpy_dtype, self.Bytes, length, offset)
|
||||
|
||||
def GetVOffsetTSlot(self, slot, d):
|
||||
"""
|
||||
GetVOffsetTSlot retrieves the VOffsetT that the given vtable location
|
||||
|
||||
2
readme.md
Executable file → Normal file
2
readme.md
Executable file → Normal file
@@ -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 {
|
||||
@@ -51,6 +52,7 @@ table Enum {
|
||||
is_union:bool = false;
|
||||
underlying_type:Type (required);
|
||||
attributes:[KeyValue];
|
||||
documentation:[string];
|
||||
}
|
||||
|
||||
table Field {
|
||||
@@ -64,6 +66,7 @@ table Field {
|
||||
required:bool = false;
|
||||
key:bool = false;
|
||||
attributes:[KeyValue];
|
||||
documentation:[string];
|
||||
}
|
||||
|
||||
table Object { // Used for both tables and structs.
|
||||
@@ -73,6 +76,7 @@ table Object { // Used for both tables and structs.
|
||||
minalign:int;
|
||||
bytesize:int; // For structs.
|
||||
attributes:[KeyValue];
|
||||
documentation:[string];
|
||||
}
|
||||
|
||||
table Schema {
|
||||
|
||||
@@ -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),
|
||||
|
||||
11
samples/android/AndroidManifest.xml
Executable file → Normal file
11
samples/android/AndroidManifest.xml
Executable file → Normal file
@@ -17,17 +17,14 @@
|
||||
-->
|
||||
<!-- BEGIN_INCLUDE(manifest) -->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.samples.FlatBufferSample"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
package="com.samples.FlatBufferSample">
|
||||
|
||||
<uses-feature android:glEsVersion="0x00020000"></uses-feature>
|
||||
<!-- This is the platform API where NativeActivity was introduced. -->
|
||||
<uses-sdk android:minSdkVersion="9" />
|
||||
|
||||
<!-- This .apk has no Java code itself, so set hasCode to false. -->
|
||||
<application android:label="@string/app_name" android:hasCode="false">
|
||||
|
||||
<application android:label="@string/app_name"
|
||||
android:hasCode="false"
|
||||
android:allowBackup="false">
|
||||
<!-- Our activity is the built-in NativeActivity framework class.
|
||||
This will take care of integrating with our NDK code. -->
|
||||
<activity android:name="android.app.NativeActivity"
|
||||
|
||||
108
samples/android/build.gradle
Normal file
108
samples/android/build.gradle
Normal file
@@ -0,0 +1,108 @@
|
||||
// Copyright (c) 2017 Google, Inc.
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.3.0'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion '25.0.2'
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
manifest.srcFile 'AndroidManifest.xml'
|
||||
res.srcDirs = ['res']
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
path "jni/Android.mk"
|
||||
}
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId 'com.samples.FlatBufferSample'
|
||||
// This is the platform API where NativeActivity was introduced.
|
||||
minSdkVersion 9
|
||||
targetSdkVersion 25
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
}
|
||||
}
|
||||
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
targets "FlatBufferSample"
|
||||
arguments "-j" + Runtime.getRuntime().availableProcessors()
|
||||
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
// Build with each STL variant.
|
||||
productFlavors {
|
||||
stlport {
|
||||
applicationIdSuffix ".stlport"
|
||||
versionNameSuffix "-stlport"
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
arguments "APP_STL=stlport_static"
|
||||
}
|
||||
}
|
||||
}
|
||||
gnustl {
|
||||
applicationIdSuffix ".gnustl"
|
||||
versionNameSuffix "-gnustl"
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
arguments "APP_STL=gnustl_static"
|
||||
}
|
||||
}
|
||||
}
|
||||
libcpp {
|
||||
applicationIdSuffix ".libcpp"
|
||||
versionNameSuffix "-libcpp"
|
||||
externalNativeBuild {
|
||||
ndkBuild {
|
||||
arguments "APP_STL=c++_static"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,511 +0,0 @@
|
||||
#!/bin/bash -eu
|
||||
#
|
||||
# Copyright (c) 2013 Google, Inc.
|
||||
#
|
||||
# This software is provided 'as-is', without any express or implied
|
||||
# warranty. In no event will the authors be held liable for any damages
|
||||
# arising from the use of this software.
|
||||
# Permission is granted to anyone to use this software for any purpose,
|
||||
# including commercial applications, and to alter it and redistribute it
|
||||
# freely, subject to the following restrictions:
|
||||
# 1. The origin of this software must not be misrepresented; you must not
|
||||
# claim that you wrote the original software. If you use this software
|
||||
# in a product, an acknowledgment in the product documentation would be
|
||||
# appreciated but is not required.
|
||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||
# misrepresented as being the original software.
|
||||
# 3. This notice may not be removed or altered from any source distribution.
|
||||
#
|
||||
# Build, deploy, debug / execute a native Android package based upon
|
||||
# NativeActivity.
|
||||
|
||||
declare -r script_directory=$(dirname $0)
|
||||
declare -r android_root=${script_directory}/../../../../../../
|
||||
declare -r script_name=$(basename $0)
|
||||
declare -r android_manifest=AndroidManifest.xml
|
||||
declare -r os_name=$(uname -s)
|
||||
|
||||
# Minimum Android target version supported by this project.
|
||||
: ${BUILDAPK_ANDROID_TARGET_MINVERSION:=10}
|
||||
# Directory containing the Android SDK
|
||||
# (http://developer.android.com/sdk/index.html).
|
||||
: ${ANDROID_SDK_HOME:=}
|
||||
# Directory containing the Android NDK
|
||||
# (http://developer.android.com/tools/sdk/ndk/index.html).
|
||||
: ${NDK_HOME:=}
|
||||
|
||||
# Display script help and exit.
|
||||
usage() {
|
||||
echo "
|
||||
Build the Android package in the current directory and deploy it to a
|
||||
connected device.
|
||||
|
||||
Usage: ${script_name} \\
|
||||
[ADB_DEVICE=serial_number] [BUILD=0] [DEPLOY=0] [RUN_DEBUGGER=1] \
|
||||
[LAUNCH=0] [SWIG_BIN=swig_binary_directory] [SWIG_LIB=swig_include_directory] [ndk-build arguments ...]
|
||||
|
||||
ADB_DEVICE=serial_number:
|
||||
serial_number specifies the device to deploy the built apk to if multiple
|
||||
Android devices are connected to the host.
|
||||
BUILD=0:
|
||||
Disables the build of the package.
|
||||
DEPLOY=0:
|
||||
Disables the deployment of the built apk to the Android device.
|
||||
RUN_DEBUGGER=1:
|
||||
Launches the application in gdb after it has been deployed. To debug in
|
||||
gdb, NDK_DEBUG=1 must also be specified on the command line to build a
|
||||
debug apk.
|
||||
LAUNCH=0:
|
||||
Disable the launch of the apk on the Android device.
|
||||
SWIG_BIN=swig_binary_directory:
|
||||
The directory where the SWIG binary lives. No need to set this if SWIG is
|
||||
installed and point to from your PATH variable.
|
||||
SWIG_LIB=swig_include_directory:
|
||||
The directory where SWIG shared include files are, usually obtainable from
|
||||
commandline with \"swig -swiglib\". No need to set this if SWIG is installed
|
||||
and point to from your PATH variable.
|
||||
ndk-build arguments...:
|
||||
Additional arguments for ndk-build. See ndk-build -h for more information.
|
||||
" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Get the number of CPU cores present on the host.
|
||||
get_number_of_cores() {
|
||||
case ${os_name} in
|
||||
Darwin)
|
||||
sysctl hw.ncpu | awk '{ print $2 }'
|
||||
;;
|
||||
CYGWIN*|Linux)
|
||||
awk '/^processor/ { n=$3 } END { print n + 1 }' /proc/cpuinfo
|
||||
;;
|
||||
*)
|
||||
echo 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Get the package name from an AndroidManifest.xml file.
|
||||
get_package_name_from_manifest() {
|
||||
xmllint --xpath 'string(/manifest/@package)' "${1}"
|
||||
}
|
||||
|
||||
# Get the library name from an AndroidManifest.xml file.
|
||||
get_library_name_from_manifest() {
|
||||
echo "\
|
||||
setns android=http://schemas.android.com/apk/res/android
|
||||
xpath string(/manifest/application/activity\
|
||||
[@android:name=\"android.app.NativeActivity\"]/meta-data\
|
||||
[@android:name=\"android.app.lib_name\"]/@android:value)" |
|
||||
xmllint --shell "${1}" | awk '/Object is a string/ { print $NF }'
|
||||
}
|
||||
|
||||
# Get the number of Android devices connected to the system.
|
||||
get_number_of_devices_connected() {
|
||||
adb devices -l | \
|
||||
awk '/^..*$/ { if (p) { print $0 } }
|
||||
/List of devices attached/ { p = 1 }' | \
|
||||
wc -l
|
||||
return ${PIPESTATUS[0]}
|
||||
}
|
||||
|
||||
# Kill a process and its' children. This is provided for cygwin which
|
||||
# doesn't ship with pkill.
|
||||
kill_process_group() {
|
||||
local parent_pid="${1}"
|
||||
local child_pid=
|
||||
for child_pid in $(ps -f | \
|
||||
awk '{ if ($3 == '"${parent_pid}"') { print $2 } }'); do
|
||||
kill_process_group "${child_pid}"
|
||||
done
|
||||
kill "${parent_pid}" 2>/dev/null
|
||||
}
|
||||
|
||||
# Find and run "adb".
|
||||
adb() {
|
||||
local adb_path=
|
||||
for path in "$(which adb 2>/dev/null)" \
|
||||
"${ANDROID_SDK_HOME}/sdk/platform-tools/adb" \
|
||||
"${android_root}/prebuilts/sdk/platform-tools/adb"; do
|
||||
if [[ -e "${path}" ]]; then
|
||||
adb_path="${path}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "${adb_path}" == "" ]]; then
|
||||
echo -e "Unable to find adb." \
|
||||
"\nAdd the Android ADT sdk/platform-tools directory to the" \
|
||||
"PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
"${adb_path}" "$@"
|
||||
}
|
||||
|
||||
# Find and run "android".
|
||||
android() {
|
||||
local android_executable=android
|
||||
if echo "${os_name}" | grep -q CYGWIN; then
|
||||
android_executable=android.bat
|
||||
fi
|
||||
local android_path=
|
||||
for path in "$(which ${android_executable})" \
|
||||
"${ANDROID_SDK_HOME}/sdk/tools/${android_executable}" \
|
||||
"${android_root}/prebuilts/sdk/tools/${android_executable}"; do
|
||||
if [[ -e "${path}" ]]; then
|
||||
android_path="${path}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "${android_path}" == "" ]]; then
|
||||
echo -e "Unable to find android tool." \
|
||||
"\nAdd the Android ADT sdk/tools directory to the PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
# Make sure ant is installed.
|
||||
if [[ "$(which ant)" == "" ]]; then
|
||||
echo -e "Unable to find ant." \
|
||||
"\nPlease install ant and add to the PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"${android_path}" "$@"
|
||||
}
|
||||
|
||||
# Find and run "ndk-build"
|
||||
ndkbuild() {
|
||||
local ndkbuild_path=
|
||||
for path in "$(which ndk-build 2>/dev/null)" \
|
||||
"${NDK_HOME}/ndk-build" \
|
||||
"${android_root}/prebuilts/ndk/current/ndk-build"; do
|
||||
if [[ -e "${path}" ]]; then
|
||||
ndkbuild_path="${path}"
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [[ "${ndkbuild_path}" == "" ]]; then
|
||||
echo -e "Unable to find ndk-build." \
|
||||
"\nAdd the Android NDK directory to the PATH." >&2
|
||||
exit 1
|
||||
fi
|
||||
"${ndkbuild_path}" "$@"
|
||||
}
|
||||
|
||||
# Get file modification time of $1 in seconds since the epoch.
|
||||
stat_mtime() {
|
||||
local filename="${1}"
|
||||
case ${os_name} in
|
||||
Darwin) stat -f%m "${filename}" 2>/dev/null || echo 0 ;;
|
||||
*) stat -c%Y "${filename}" 2>/dev/null || echo 0 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Build the native (C/C++) build targets in the current directory.
|
||||
build_native_targets() {
|
||||
# Save the list of output modules in the install directory so that it's
|
||||
# possible to restore their timestamps after the build is complete. This
|
||||
# works around a bug in ndk/build/core/setup-app.mk which results in the
|
||||
# unconditional execution of the clean-installed-binaries rule.
|
||||
restore_libraries="$(find libs -type f 2>/dev/null | \
|
||||
sed -E 's@^libs/(.*)@\1@')"
|
||||
|
||||
# Build native code.
|
||||
ndkbuild -j$(get_number_of_cores) "$@"
|
||||
|
||||
# Restore installed libraries.
|
||||
# Obviously this is a nasty hack (along with ${restore_libraries} above) as
|
||||
# it assumes it knows where the NDK will be placing output files.
|
||||
(
|
||||
IFS=$'\n'
|
||||
for libpath in ${restore_libraries}; do
|
||||
source_library="obj/local/${libpath}"
|
||||
target_library="libs/${libpath}"
|
||||
if [[ -e "${source_library}" ]]; then
|
||||
cp -a "${source_library}" "${target_library}"
|
||||
fi
|
||||
done
|
||||
)
|
||||
}
|
||||
|
||||
# Select the oldest installed android build target that is at least as new as
|
||||
# BUILDAPK_ANDROID_TARGET_MINVERSION. If a suitable build target isn't found,
|
||||
# this function prints an error message and exits with an error.
|
||||
select_android_build_target() {
|
||||
local -r android_targets_installed=$( \
|
||||
android list targets | \
|
||||
awk -F'"' '/^id:.*android/ { print $2 }')
|
||||
local android_build_target=
|
||||
for android_target in $(echo "${android_targets_installed}" | \
|
||||
awk -F- '{ print $2 }' | sort -n); do
|
||||
local isNumber='^[0-9]+$'
|
||||
# skip preview API releases e.g. 'android-L'
|
||||
if [[ $android_target =~ $isNumber ]]; then
|
||||
if [[ $((android_target)) -ge \
|
||||
$((BUILDAPK_ANDROID_TARGET_MINVERSION)) ]]; then
|
||||
android_build_target="android-${android_target}"
|
||||
break
|
||||
fi
|
||||
# else
|
||||
# The API version is a letter, so skip it.
|
||||
fi
|
||||
done
|
||||
if [[ "${android_build_target}" == "" ]]; then
|
||||
echo -e \
|
||||
"Found installed Android targets:" \
|
||||
"$(echo ${android_targets_installed} | sed 's/ /\n /g;s/^/\n /;')" \
|
||||
"\nAndroid SDK platform" \
|
||||
"android-$((BUILDAPK_ANDROID_TARGET_MINVERSION))" \
|
||||
"must be installed to build this project." \
|
||||
"\nUse the \"android\" application to install API" \
|
||||
"$((BUILDAPK_ANDROID_TARGET_MINVERSION)) or newer." >&2
|
||||
exit 1
|
||||
fi
|
||||
echo "${android_build_target}"
|
||||
}
|
||||
|
||||
# Sign unsigned apk $1 and write the result to $2 with key store file $3 and
|
||||
# password $4.
|
||||
# If a key store file $3 and password $4 aren't specified, a temporary
|
||||
# (60 day) key is generated and used to sign the package.
|
||||
sign_apk() {
|
||||
local unsigned_apk="${1}"
|
||||
local signed_apk="${2}"
|
||||
if [[ $(stat_mtime "${unsigned_apk}") -gt \
|
||||
$(stat_mtime "${signed_apk}") ]]; then
|
||||
local -r key_alias=$(basename ${signed_apk} .apk)
|
||||
local keystore="${3}"
|
||||
local key_password="${4}"
|
||||
[[ "${keystore}" == "" ]] && keystore="${unsigned_apk}.keystore"
|
||||
[[ "${key_password}" == "" ]] && \
|
||||
key_password="${key_alias}123456"
|
||||
if [[ ! -e ${keystore} ]]; then
|
||||
keytool -genkey -v -dname "cn=, ou=${key_alias}, o=fpl" \
|
||||
-storepass ${key_password} \
|
||||
-keypass ${key_password} -keystore ${keystore} \
|
||||
-alias ${key_alias} -keyalg RSA -keysize 2048 -validity 60
|
||||
fi
|
||||
cp "${unsigned_apk}" "${signed_apk}"
|
||||
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 \
|
||||
-keystore ${keystore} -storepass ${key_password} \
|
||||
-keypass ${key_password} "${signed_apk}" ${key_alias}
|
||||
fi
|
||||
}
|
||||
|
||||
# Build the apk $1 for package filename $2 in the current directory using the
|
||||
# ant build target $3.
|
||||
build_apk() {
|
||||
local -r output_apk="${1}"
|
||||
local -r package_filename="${2}"
|
||||
local -r ant_target="${3}"
|
||||
# Get the list of installed android targets and select the oldest target
|
||||
# that is at least as new as BUILDAPK_ANDROID_TARGET_MINVERSION.
|
||||
local -r android_build_target=$(select_android_build_target)
|
||||
[[ "${android_build_target}" == "" ]] && exit 1
|
||||
echo "Building ${output_apk} for target ${android_build_target}" >&2
|
||||
|
||||
# Create / update build.xml and local.properties files.
|
||||
if [[ $(stat_mtime "${android_manifest}") -gt \
|
||||
$(stat_mtime build.xml) ]]; then
|
||||
android update project --target "${android_build_target}" \
|
||||
-n ${package_filename} --path .
|
||||
fi
|
||||
|
||||
# Use ant to build the apk.
|
||||
ant -quiet ${ant_target}
|
||||
|
||||
# Sign release apks with a temporary key as these packages will not be
|
||||
# redistributed.
|
||||
local unsigned_apk="bin/${package_filename}-${ant_target}-unsigned.apk"
|
||||
if [[ "${ant_target}" == "release" ]]; then
|
||||
sign_apk "${unsigned_apk}" "${output_apk}" "" ""
|
||||
fi
|
||||
}
|
||||
|
||||
# Uninstall package $1 and install apk $2 on device $3 where $3 is "-s device"
|
||||
# or an empty string. If $3 is an empty string adb will fail when multiple
|
||||
# devices are connected to the host system.
|
||||
install_apk() {
|
||||
local -r uninstall_package_name="${1}"
|
||||
local -r install_apk="${2}"
|
||||
local -r adb_device="${3}"
|
||||
# Uninstall the package if it's already installed.
|
||||
adb ${adb_device} uninstall "${uninstall_package_name}" 1>&2 > /dev/null || \
|
||||
true # no error check
|
||||
|
||||
# Install the apk.
|
||||
# NOTE: The following works around adb not returning an error code when
|
||||
# it fails to install an apk.
|
||||
echo "Install ${install_apk}" >&2
|
||||
local -r adb_install_result=$(adb ${adb_device} install "${install_apk}")
|
||||
echo "${adb_install_result}"
|
||||
if echo "${adb_install_result}" | grep -qF 'Failure ['; then
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Launch previously installed package $1 on device $2.
|
||||
# If $2 is an empty string adb will fail when multiple devices are connected
|
||||
# to the host system.
|
||||
launch_package() {
|
||||
(
|
||||
# Determine the SDK version of Android on the device.
|
||||
local -r android_sdk_version=$(
|
||||
adb ${adb_device} shell cat system/build.prop | \
|
||||
awk -F= '/ro.build.version.sdk/ {
|
||||
v=$2; sub(/[ \r\n]/, "", v); print v
|
||||
}')
|
||||
|
||||
# Clear logs from previous runs.
|
||||
# Note that logcat does not just 'tail' the logs, it dumps the entire log
|
||||
# history.
|
||||
adb ${adb_device} logcat -c
|
||||
|
||||
local finished_msg='Displayed '"${package_name}"
|
||||
local timeout_msg='Activity destroy timeout.*'"${package_name}"
|
||||
# Maximum time to wait before stopping log monitoring. 0 = infinity.
|
||||
local launch_timeout=0
|
||||
# If this is a Gingerbread device, kill log monitoring after 10 seconds.
|
||||
if [[ $((android_sdk_version)) -le 10 ]]; then
|
||||
launch_timeout=10
|
||||
fi
|
||||
# Display logcat in the background.
|
||||
# Stop displaying the log when the app launch / execution completes or the
|
||||
# logcat
|
||||
(
|
||||
adb ${adb_device} logcat | \
|
||||
awk "
|
||||
{
|
||||
print \$0
|
||||
}
|
||||
|
||||
/ActivityManager.*: ${finished_msg}/ {
|
||||
exit 0
|
||||
}
|
||||
|
||||
/ActivityManager.*: ${timeout_msg}/ {
|
||||
exit 0
|
||||
}" &
|
||||
adb_logcat_pid=$!;
|
||||
if [[ $((launch_timeout)) -gt 0 ]]; then
|
||||
sleep $((launch_timeout));
|
||||
kill ${adb_logcat_pid};
|
||||
else
|
||||
wait ${adb_logcat_pid};
|
||||
fi
|
||||
) &
|
||||
logcat_pid=$!
|
||||
# Kill adb logcat if this shell exits.
|
||||
trap "kill_process_group ${logcat_pid}" SIGINT SIGTERM EXIT
|
||||
|
||||
# If the SDK is newer than 10, "am" supports stopping an activity.
|
||||
adb_stop_activity=
|
||||
if [[ $((android_sdk_version)) -gt 10 ]]; then
|
||||
adb_stop_activity=-S
|
||||
fi
|
||||
|
||||
# Launch the activity and wait for it to complete.
|
||||
adb ${adb_device} shell am start ${adb_stop_activity} -n \
|
||||
${package_name}/android.app.NativeActivity
|
||||
|
||||
wait "${logcat_pid}"
|
||||
)
|
||||
}
|
||||
|
||||
# See usage().
|
||||
main() {
|
||||
# Parse arguments for this script.
|
||||
local adb_device=
|
||||
local ant_target=release
|
||||
local disable_deploy=0
|
||||
local disable_build=0
|
||||
local run_debugger=0
|
||||
local launch=1
|
||||
local build_package=1
|
||||
for opt; do
|
||||
case ${opt} in
|
||||
# NDK_DEBUG=0 tells ndk-build to build this as debuggable but to not
|
||||
# modify the underlying code whereas NDK_DEBUG=1 also builds as debuggable
|
||||
# but does modify the code
|
||||
NDK_DEBUG=1) ant_target=debug ;;
|
||||
NDK_DEBUG=0) ant_target=debug ;;
|
||||
ADB_DEVICE*) adb_device="$(\
|
||||
echo "${opt}" | sed -E 's/^ADB_DEVICE=([^ ]+)$/-s \1/;t;s/.*//')" ;;
|
||||
BUILD=0) disable_build=1 ;;
|
||||
DEPLOY=0) disable_deploy=1 ;;
|
||||
RUN_DEBUGGER=1) run_debugger=1 ;;
|
||||
LAUNCH=0) launch=0 ;;
|
||||
clean) build_package=0 disable_deploy=1 launch=0 ;;
|
||||
-h|--help|help) usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# If a target device hasn't been specified and multiple devices are connected
|
||||
# to the host machine, display an error.
|
||||
local -r devices_connected=$(get_number_of_devices_connected)
|
||||
if [[ "${adb_device}" == "" && $((devices_connected)) -gt 1 && \
|
||||
($((disable_deploy)) -eq 0 || $((launch)) -ne 0 || \
|
||||
$((run_debugger)) -ne 0) ]]; then
|
||||
if [[ $((disable_deploy)) -ne 0 ]]; then
|
||||
echo "Deployment enabled, disable using DEPLOY=0" >&2
|
||||
fi
|
||||
if [[ $((launch)) -ne 0 ]]; then
|
||||
echo "Launch enabled." >&2
|
||||
fi
|
||||
if [[ $((disable_deploy)) -eq 0 ]]; then
|
||||
echo "Deployment enabled." >&2
|
||||
fi
|
||||
if [[ $((run_debugger)) -ne 0 ]]; then
|
||||
echo "Debugger launch enabled." >&2
|
||||
fi
|
||||
echo "
|
||||
Multiple Android devices are connected to this host. Either disable deployment
|
||||
and execution of the built .apk using:
|
||||
\"${script_name} DEPLOY=0 LAUNCH=0\"
|
||||
|
||||
or specify a device to deploy to using:
|
||||
\"${script_name} ADB_DEVICE=\${device_serial}\".
|
||||
|
||||
The Android devices connected to this machine are:
|
||||
$(adb devices -l)
|
||||
" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ $((disable_build)) -eq 0 ]]; then
|
||||
# Build the native target.
|
||||
build_native_targets "$@"
|
||||
fi
|
||||
|
||||
# Get the package name from the manifest.
|
||||
local -r package_name=$(get_package_name_from_manifest "${android_manifest}")
|
||||
if [[ "${package_name}" == "" ]]; then
|
||||
echo -e "No package name specified in ${android_manifest},"\
|
||||
"skipping apk build, deploy"
|
||||
"\nand launch steps." >&2
|
||||
exit 0
|
||||
fi
|
||||
local -r package_basename=${package_name/*./}
|
||||
local package_filename=$(get_library_name_from_manifest ${android_manifest})
|
||||
[[ "${package_filename}" == "" ]] && package_filename="${package_basename}"
|
||||
|
||||
# Output apk name.
|
||||
local -r output_apk="bin/${package_filename}-${ant_target}.apk"
|
||||
|
||||
if [[ $((disable_build)) -eq 0 && $((build_package)) -eq 1 ]]; then
|
||||
# Build the apk.
|
||||
build_apk "${output_apk}" "${package_filename}" "${ant_target}"
|
||||
fi
|
||||
|
||||
# Deploy to the device.
|
||||
if [[ $((disable_deploy)) -eq 0 ]]; then
|
||||
install_apk "${package_name}" "${output_apk}" "${adb_device}"
|
||||
fi
|
||||
|
||||
if [[ "${ant_target}" == "debug" && $((run_debugger)) -eq 1 ]]; then
|
||||
# Start debugging.
|
||||
ndk-gdb ${adb_device} --start
|
||||
elif [[ $((launch)) -eq 1 ]]; then
|
||||
launch_package "${package_name}" "${adb_device}"
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@"
|
||||
BIN
samples/android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
samples/android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
6
samples/android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
samples/android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#Mon Jun 19 11:54:59 PDT 2017
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-all.zip
|
||||
172
samples/android/gradlew
vendored
Executable file
172
samples/android/gradlew
vendored
Executable file
@@ -0,0 +1,172 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
84
samples/android/gradlew.bat
vendored
Normal file
84
samples/android/gradlew.bat
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
2
samples/android/jni/Android.mk
Executable file → Normal file
2
samples/android/jni/Android.mk
Executable file → Normal file
@@ -38,7 +38,7 @@ $(info $(LOCAL_C_INCLUDES))
|
||||
LOCAL_SRC_FILES := main.cpp
|
||||
|
||||
LOCAL_CPPFLAGS := -std=c++11 -fexceptions -Wall -Wno-literal-suffix
|
||||
LOCAL_LDLIBS := -llog -landroid
|
||||
LOCAL_LDLIBS := -llog -landroid -latomic
|
||||
LOCAL_ARM_MODE := arm
|
||||
LOCAL_STATIC_LIBRARIES := android_native_app_glue flatbuffers
|
||||
|
||||
|
||||
6
samples/android/jni/Application.mk
Executable file → Normal file
6
samples/android/jni/Application.mk
Executable file → Normal file
@@ -13,10 +13,8 @@
|
||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||
# misrepresented as being the original software.
|
||||
# 3. This notice may not be removed or altered from any source distribution.
|
||||
APP_PLATFORM := android-10
|
||||
APP_PLATFORM := android-9
|
||||
APP_PROJECT_PATH := $(call my-dir)/..
|
||||
APP_STL := gnustl_static
|
||||
|
||||
APP_STL ?= stlport_static
|
||||
APP_ABI := armeabi-v7a
|
||||
|
||||
APP_CPPFLAGS += -std=c++11
|
||||
|
||||
0
samples/android/res/values/strings.xml
Executable file → Normal file
0
samples/android/res/values/strings.xml
Executable file → Normal file
@@ -29,8 +29,7 @@ fi
|
||||
|
||||
# Execute `build_apk.sh` to build and run the android app.
|
||||
cd android
|
||||
./build_apk.sh
|
||||
./gradlew build
|
||||
|
||||
|
||||
|
||||
# Cleanup the temporary files.
|
||||
rm build.xml local.properties proguard-project.txt project.properties
|
||||
rm -rf bin libs obj
|
||||
|
||||
0
samples/monster.fbs
Executable file → Normal file
0
samples/monster.fbs
Executable file → Normal file
@@ -1,5 +1,6 @@
|
||||
// automatically generated by the FlatBuffers compiler, do not modify
|
||||
|
||||
|
||||
#ifndef FLATBUFFERS_GENERATED_MONSTER_MYGAME_SAMPLE_H_
|
||||
#define FLATBUFFERS_GENERATED_MONSTER_MYGAME_SAMPLE_H_
|
||||
|
||||
@@ -24,12 +25,29 @@ 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", "Green", "Blue", nullptr };
|
||||
static const char *names[] = {
|
||||
"Red",
|
||||
"Green",
|
||||
"Blue",
|
||||
nullptr
|
||||
};
|
||||
return names;
|
||||
}
|
||||
|
||||
inline const char *EnumNameColor(Color e) { return EnumNamesColor()[static_cast<int>(e)]; }
|
||||
inline const char *EnumNameColor(Color e) {
|
||||
const size_t index = static_cast<int>(e);
|
||||
return EnumNamesColor()[index];
|
||||
}
|
||||
|
||||
enum Equipment {
|
||||
Equipment_NONE = 0,
|
||||
@@ -38,12 +56,27 @@ 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", "Weapon", nullptr };
|
||||
static const char *names[] = {
|
||||
"NONE",
|
||||
"Weapon",
|
||||
nullptr
|
||||
};
|
||||
return names;
|
||||
}
|
||||
|
||||
inline const char *EnumNameEquipment(Equipment e) { return EnumNamesEquipment()[static_cast<int>(e)]; }
|
||||
inline const char *EnumNameEquipment(Equipment e) {
|
||||
const size_t index = static_cast<int>(e);
|
||||
return EnumNamesEquipment()[index];
|
||||
}
|
||||
|
||||
template<typename T> struct EquipmentTraits {
|
||||
static const Equipment enum_value = Equipment_NONE;
|
||||
@@ -55,30 +88,47 @@ template<> struct EquipmentTraits<Weapon> {
|
||||
|
||||
struct EquipmentUnion {
|
||||
Equipment type;
|
||||
void *value;
|
||||
|
||||
flatbuffers::NativeTable *table;
|
||||
EquipmentUnion() : type(Equipment_NONE), table(nullptr) {}
|
||||
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();
|
||||
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
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));
|
||||
}
|
||||
}
|
||||
#endif // FLATBUFFERS_CPP98_STL
|
||||
|
||||
static flatbuffers::NativeTable *UnPack(const void *union_obj, Equipment type, const flatbuffers::resolver_function_t *resolver);
|
||||
flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *rehasher = nullptr) const;
|
||||
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; }
|
||||
WeaponT *AsWeapon() {
|
||||
return type == Equipment_Weapon ?
|
||||
reinterpret_cast<WeaponT *>(value) : nullptr;
|
||||
}
|
||||
const WeaponT *AsWeapon() const {
|
||||
return type == Equipment_Weapon ?
|
||||
reinterpret_cast<const WeaponT *>(value) : nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
inline bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *union_obj, Equipment type);
|
||||
bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *obj, Equipment type);
|
||||
bool VerifyEquipmentVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
|
||||
|
||||
MANUALLY_ALIGNED_STRUCT(4) Vec3 FLATBUFFERS_FINAL_CLASS {
|
||||
private:
|
||||
@@ -87,34 +137,50 @@ MANUALLY_ALIGNED_STRUCT(4) Vec3 FLATBUFFERS_FINAL_CLASS {
|
||||
float z_;
|
||||
|
||||
public:
|
||||
Vec3() { memset(this, 0, sizeof(Vec3)); }
|
||||
Vec3(const Vec3 &_o) { memcpy(this, &_o, sizeof(Vec3)); }
|
||||
Vec3() {
|
||||
memset(this, 0, sizeof(Vec3));
|
||||
}
|
||||
Vec3(float _x, float _y, float _z)
|
||||
: x_(flatbuffers::EndianScalar(_x)), y_(flatbuffers::EndianScalar(_y)), z_(flatbuffers::EndianScalar(_z)) { }
|
||||
|
||||
float x() const { return flatbuffers::EndianScalar(x_); }
|
||||
void mutate_x(float _x) { flatbuffers::WriteScalar(&x_, _x); }
|
||||
float y() const { return flatbuffers::EndianScalar(y_); }
|
||||
void mutate_y(float _y) { flatbuffers::WriteScalar(&y_, _y); }
|
||||
float z() const { return flatbuffers::EndianScalar(z_); }
|
||||
void mutate_z(float _z) { flatbuffers::WriteScalar(&z_, _z); }
|
||||
: x_(flatbuffers::EndianScalar(_x)),
|
||||
y_(flatbuffers::EndianScalar(_y)),
|
||||
z_(flatbuffers::EndianScalar(_z)) {
|
||||
}
|
||||
float x() const {
|
||||
return flatbuffers::EndianScalar(x_);
|
||||
}
|
||||
void mutate_x(float _x) {
|
||||
flatbuffers::WriteScalar(&x_, _x);
|
||||
}
|
||||
float y() const {
|
||||
return flatbuffers::EndianScalar(y_);
|
||||
}
|
||||
void mutate_y(float _y) {
|
||||
flatbuffers::WriteScalar(&y_, _y);
|
||||
}
|
||||
float z() const {
|
||||
return flatbuffers::EndianScalar(z_);
|
||||
}
|
||||
void mutate_z(float _z) {
|
||||
flatbuffers::WriteScalar(&z_, _z);
|
||||
}
|
||||
};
|
||||
STRUCT_END(Vec3, 12);
|
||||
|
||||
struct MonsterT : public flatbuffers::NativeTable {
|
||||
typedef Monster TableType;
|
||||
std::unique_ptr<Vec3> pos;
|
||||
flatbuffers::unique_ptr<Vec3> pos;
|
||||
int16_t mana;
|
||||
int16_t hp;
|
||||
std::string name;
|
||||
std::vector<uint8_t> inventory;
|
||||
Color color;
|
||||
std::vector<std::unique_ptr<WeaponT>> weapons;
|
||||
std::vector<flatbuffers::unique_ptr<WeaponT>> weapons;
|
||||
EquipmentUnion equipped;
|
||||
MonsterT()
|
||||
: mana(150),
|
||||
hp(100),
|
||||
color(Color_Blue) {}
|
||||
: mana(150),
|
||||
hp(100),
|
||||
color(Color_Blue) {
|
||||
}
|
||||
};
|
||||
|
||||
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
@@ -130,67 +196,135 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VT_EQUIPPED_TYPE = 20,
|
||||
VT_EQUIPPED = 22
|
||||
};
|
||||
const Vec3 *pos() const { return GetStruct<const Vec3 *>(VT_POS); }
|
||||
Vec3 *mutable_pos() { return GetStruct<Vec3 *>(VT_POS); }
|
||||
int16_t mana() const { return GetField<int16_t>(VT_MANA, 150); }
|
||||
bool mutate_mana(int16_t _mana) { return SetField(VT_MANA, _mana); }
|
||||
int16_t hp() const { return GetField<int16_t>(VT_HP, 100); }
|
||||
bool mutate_hp(int16_t _hp) { return SetField(VT_HP, _hp); }
|
||||
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(VT_NAME); }
|
||||
flatbuffers::String *mutable_name() { return GetPointer<flatbuffers::String *>(VT_NAME); }
|
||||
const flatbuffers::Vector<uint8_t> *inventory() const { return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_INVENTORY); }
|
||||
flatbuffers::Vector<uint8_t> *mutable_inventory() { return GetPointer<flatbuffers::Vector<uint8_t> *>(VT_INVENTORY); }
|
||||
Color color() const { return static_cast<Color>(GetField<int8_t>(VT_COLOR, 2)); }
|
||||
bool mutate_color(Color _color) { return SetField(VT_COLOR, static_cast<int8_t>(_color)); }
|
||||
const flatbuffers::Vector<flatbuffers::Offset<Weapon>> *weapons() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Weapon>> *>(VT_WEAPONS); }
|
||||
flatbuffers::Vector<flatbuffers::Offset<Weapon>> *mutable_weapons() { return GetPointer<flatbuffers::Vector<flatbuffers::Offset<Weapon>> *>(VT_WEAPONS); }
|
||||
Equipment equipped_type() const { 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)); }
|
||||
const void *equipped() const { return GetPointer<const void *>(VT_EQUIPPED); }
|
||||
void *mutable_equipped() { return GetPointer<void *>(VT_EQUIPPED); }
|
||||
const Vec3 *pos() const {
|
||||
return GetStruct<const Vec3 *>(VT_POS);
|
||||
}
|
||||
Vec3 *mutable_pos() {
|
||||
return GetStruct<Vec3 *>(VT_POS);
|
||||
}
|
||||
int16_t mana() const {
|
||||
return GetField<int16_t>(VT_MANA, 150);
|
||||
}
|
||||
bool mutate_mana(int16_t _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<int16_t>(VT_HP, _hp, 100);
|
||||
}
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
flatbuffers::String *mutable_name() {
|
||||
return GetPointer<flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
const flatbuffers::Vector<uint8_t> *inventory() const {
|
||||
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_INVENTORY);
|
||||
}
|
||||
flatbuffers::Vector<uint8_t> *mutable_inventory() {
|
||||
return GetPointer<flatbuffers::Vector<uint8_t> *>(VT_INVENTORY);
|
||||
}
|
||||
Color color() const {
|
||||
return static_cast<Color>(GetField<int8_t>(VT_COLOR, 2));
|
||||
}
|
||||
bool mutate_color(Color _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);
|
||||
}
|
||||
flatbuffers::Vector<flatbuffers::Offset<Weapon>> *mutable_weapons() {
|
||||
return GetPointer<flatbuffers::Vector<flatbuffers::Offset<Weapon>> *>(VT_WEAPONS);
|
||||
}
|
||||
Equipment equipped_type() const {
|
||||
return static_cast<Equipment>(GetField<uint8_t>(VT_EQUIPPED_TYPE, 0));
|
||||
}
|
||||
bool mutate_equipped_type(Equipment _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);
|
||||
}
|
||||
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) &&
|
||||
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();
|
||||
}
|
||||
MonsterT *UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
|
||||
MonsterT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||
void UnPackTo(MonsterT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||
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_;
|
||||
void add_pos(const Vec3 *pos) { fbb_.AddStruct(Monster::VT_POS, pos); }
|
||||
void add_mana(int16_t mana) { fbb_.AddElement<int16_t>(Monster::VT_MANA, mana, 150); }
|
||||
void add_hp(int16_t hp) { fbb_.AddElement<int16_t>(Monster::VT_HP, hp, 100); }
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(Monster::VT_NAME, name); }
|
||||
void add_inventory(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory) { fbb_.AddOffset(Monster::VT_INVENTORY, inventory); }
|
||||
void add_color(Color color) { fbb_.AddElement<int8_t>(Monster::VT_COLOR, static_cast<int8_t>(color), 2); }
|
||||
void add_weapons(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Weapon>>> weapons) { fbb_.AddOffset(Monster::VT_WEAPONS, weapons); }
|
||||
void add_equipped_type(Equipment equipped_type) { fbb_.AddElement<uint8_t>(Monster::VT_EQUIPPED_TYPE, static_cast<uint8_t>(equipped_type), 0); }
|
||||
void add_equipped(flatbuffers::Offset<void> equipped) { fbb_.AddOffset(Monster::VT_EQUIPPED, equipped); }
|
||||
MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
|
||||
void add_pos(const Vec3 *pos) {
|
||||
fbb_.AddStruct(Monster::VT_POS, pos);
|
||||
}
|
||||
void add_mana(int16_t mana) {
|
||||
fbb_.AddElement<int16_t>(Monster::VT_MANA, mana, 150);
|
||||
}
|
||||
void add_hp(int16_t hp) {
|
||||
fbb_.AddElement<int16_t>(Monster::VT_HP, hp, 100);
|
||||
}
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(Monster::VT_NAME, name);
|
||||
}
|
||||
void add_inventory(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory) {
|
||||
fbb_.AddOffset(Monster::VT_INVENTORY, inventory);
|
||||
}
|
||||
void add_color(Color color) {
|
||||
fbb_.AddElement<int8_t>(Monster::VT_COLOR, static_cast<int8_t>(color), 2);
|
||||
}
|
||||
void add_weapons(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Weapon>>> weapons) {
|
||||
fbb_.AddOffset(Monster::VT_WEAPONS, weapons);
|
||||
}
|
||||
void add_equipped_type(Equipment equipped_type) {
|
||||
fbb_.AddElement<uint8_t>(Monster::VT_EQUIPPED_TYPE, static_cast<uint8_t>(equipped_type), 0);
|
||||
}
|
||||
void add_equipped(flatbuffers::Offset<void> equipped) {
|
||||
fbb_.AddOffset(Monster::VT_EQUIPPED, equipped);
|
||||
}
|
||||
explicit MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
MonsterBuilder &operator=(const MonsterBuilder &);
|
||||
flatbuffers::Offset<Monster> Finish() {
|
||||
auto o = flatbuffers::Offset<Monster>(fbb_.EndTable(start_, 10));
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<Monster>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const Vec3 *pos = 0,
|
||||
int16_t mana = 150,
|
||||
int16_t hp = 100,
|
||||
@@ -213,7 +347,8 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonsterDirect(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
inline flatbuffers::Offset<Monster> CreateMonsterDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const Vec3 *pos = 0,
|
||||
int16_t mana = 150,
|
||||
int16_t hp = 100,
|
||||
@@ -223,17 +358,28 @@ inline flatbuffers::Offset<Monster> CreateMonsterDirect(flatbuffers::FlatBufferB
|
||||
const std::vector<flatbuffers::Offset<Weapon>> *weapons = nullptr,
|
||||
Equipment equipped_type = Equipment_NONE,
|
||||
flatbuffers::Offset<void> equipped = 0) {
|
||||
return CreateMonster(_fbb, pos, mana, hp, name ? _fbb.CreateString(name) : 0, inventory ? _fbb.CreateVector<uint8_t>(*inventory) : 0, color, weapons ? _fbb.CreateVector<flatbuffers::Offset<Weapon>>(*weapons) : 0, equipped_type, equipped);
|
||||
return MyGame::Sample::CreateMonster(
|
||||
_fbb,
|
||||
pos,
|
||||
mana,
|
||||
hp,
|
||||
name ? _fbb.CreateString(name) : 0,
|
||||
inventory ? _fbb.CreateVector<uint8_t>(*inventory) : 0,
|
||||
color,
|
||||
weapons ? _fbb.CreateVector<flatbuffers::Offset<Weapon>>(*weapons) : 0,
|
||||
equipped_type,
|
||||
equipped);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *rehasher = nullptr);
|
||||
flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||
|
||||
struct WeaponT : public flatbuffers::NativeTable {
|
||||
typedef Weapon TableType;
|
||||
std::string name;
|
||||
int16_t damage;
|
||||
WeaponT()
|
||||
: damage(0) {}
|
||||
: damage(0) {
|
||||
}
|
||||
};
|
||||
|
||||
struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
@@ -242,35 +388,53 @@ struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VT_NAME = 4,
|
||||
VT_DAMAGE = 6
|
||||
};
|
||||
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(VT_NAME); }
|
||||
flatbuffers::String *mutable_name() { return GetPointer<flatbuffers::String *>(VT_NAME); }
|
||||
int16_t damage() const { return GetField<int16_t>(VT_DAMAGE, 0); }
|
||||
bool mutate_damage(int16_t _damage) { return SetField(VT_DAMAGE, _damage); }
|
||||
const flatbuffers::String *name() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
flatbuffers::String *mutable_name() {
|
||||
return GetPointer<flatbuffers::String *>(VT_NAME);
|
||||
}
|
||||
int16_t damage() const {
|
||||
return GetField<int16_t>(VT_DAMAGE, 0);
|
||||
}
|
||||
bool mutate_damage(int16_t _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();
|
||||
}
|
||||
WeaponT *UnPack(const flatbuffers::resolver_function_t *resolver = nullptr) const;
|
||||
WeaponT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||
void UnPackTo(WeaponT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
|
||||
static flatbuffers::Offset<Weapon> Pack(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||
};
|
||||
|
||||
struct WeaponBuilder {
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(Weapon::VT_NAME, name); }
|
||||
void add_damage(int16_t damage) { fbb_.AddElement<int16_t>(Weapon::VT_DAMAGE, damage, 0); }
|
||||
WeaponBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(Weapon::VT_NAME, name);
|
||||
}
|
||||
void add_damage(int16_t damage) {
|
||||
fbb_.AddElement<int16_t>(Weapon::VT_DAMAGE, damage, 0);
|
||||
}
|
||||
explicit WeaponBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
}
|
||||
WeaponBuilder &operator=(const WeaponBuilder &);
|
||||
flatbuffers::Offset<Weapon> Finish() {
|
||||
auto o = flatbuffers::Offset<Weapon>(fbb_.EndTable(start_, 2));
|
||||
const auto end = fbb_.EndTable(start_);
|
||||
auto o = flatbuffers::Offset<Weapon>(end);
|
||||
return o;
|
||||
}
|
||||
};
|
||||
|
||||
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
inline flatbuffers::Offset<Weapon> CreateWeapon(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
int16_t damage = 0) {
|
||||
WeaponBuilder builder_(_fbb);
|
||||
@@ -279,99 +443,279 @@ inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Weapon> CreateWeaponDirect(flatbuffers::FlatBufferBuilder &_fbb,
|
||||
inline flatbuffers::Offset<Weapon> CreateWeaponDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
int16_t damage = 0) {
|
||||
return CreateWeapon(_fbb, name ? _fbb.CreateString(name) : 0, damage);
|
||||
return MyGame::Sample::CreateWeapon(
|
||||
_fbb,
|
||||
name ? _fbb.CreateString(name) : 0,
|
||||
damage);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o, const flatbuffers::rehasher_function_t *rehasher = nullptr);
|
||||
flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
|
||||
|
||||
inline MonsterT *Monster::UnPack(const flatbuffers::resolver_function_t *resolver) const {
|
||||
(void)resolver;
|
||||
inline MonsterT *Monster::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
|
||||
auto _o = new MonsterT();
|
||||
{ auto _e = pos(); if (_e) _o->pos = std::unique_ptr<Vec3>(new Vec3(*_e)); };
|
||||
UnPackTo(_o, _resolver);
|
||||
return _o;
|
||||
}
|
||||
|
||||
inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function_t *_resolver) const {
|
||||
(void)_o;
|
||||
(void)_resolver;
|
||||
{ auto _e = pos(); if (_e) _o->pos = flatbuffers::unique_ptr<Vec3>(new Vec3(*_e)); };
|
||||
{ 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] = flatbuffers::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); };
|
||||
return _o;
|
||||
{ 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) {
|
||||
return CreateMonster(_fbb, _o, _rehasher);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *rehasher) {
|
||||
(void)rehasher;
|
||||
return CreateMonster(_fbb,
|
||||
_o->pos ? _o->pos.get() : 0,
|
||||
_o->mana,
|
||||
_o->hp,
|
||||
_o->name.size() ? _fbb.CreateString(_o->name) : 0,
|
||||
_o->inventory.size() ? _fbb.CreateVector(_o->inventory) : 0,
|
||||
_o->color,
|
||||
_o->weapons.size() ? _fbb.CreateVector<flatbuffers::Offset<Weapon>>(_o->weapons.size(), [&](size_t i) { return CreateWeapon(_fbb, _o->weapons[i].get(), rehasher); }) : 0,
|
||||
_o->equipped.type,
|
||||
_o->equipped.Pack(_fbb));
|
||||
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
|
||||
(void)_rehasher;
|
||||
(void)_o;
|
||||
struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MonsterT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
|
||||
auto _pos = _o->pos ? _o->pos.get() : 0;
|
||||
auto _mana = _o->mana;
|
||||
auto _hp = _o->hp;
|
||||
auto _name = _o->name.empty() ? 0 : _fbb.CreateString(_o->name);
|
||||
auto _inventory = _o->inventory.size() ? _fbb.CreateVector(_o->inventory) : 0;
|
||||
auto _color = _o->color;
|
||||
auto _weapons = _o->weapons.size() ? _fbb.CreateVector<flatbuffers::Offset<Weapon>> (_o->weapons.size(), [](size_t i, _VectorArgs *__va) { return CreateWeapon(*__va->__fbb, __va->__o->weapons[i].get(), __va->__rehasher); }, &_va ) : 0;
|
||||
auto _equipped_type = _o->equipped.type;
|
||||
auto _equipped = _o->equipped.Pack(_fbb);
|
||||
return MyGame::Sample::CreateMonster(
|
||||
_fbb,
|
||||
_pos,
|
||||
_mana,
|
||||
_hp,
|
||||
_name,
|
||||
_inventory,
|
||||
_color,
|
||||
_weapons,
|
||||
_equipped_type,
|
||||
_equipped);
|
||||
}
|
||||
|
||||
inline WeaponT *Weapon::UnPack(const flatbuffers::resolver_function_t *resolver) const {
|
||||
(void)resolver;
|
||||
inline WeaponT *Weapon::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
|
||||
auto _o = new WeaponT();
|
||||
UnPackTo(_o, _resolver);
|
||||
return _o;
|
||||
}
|
||||
|
||||
inline void Weapon::UnPackTo(WeaponT *_o, const flatbuffers::resolver_function_t *_resolver) const {
|
||||
(void)_o;
|
||||
(void)_resolver;
|
||||
{ auto _e = name(); if (_e) _o->name = _e->str(); };
|
||||
{ auto _e = damage(); _o->damage = _e; };
|
||||
return _o;
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Weapon> Weapon::Pack(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
|
||||
return CreateWeapon(_fbb, _o, _rehasher);
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o, const flatbuffers::rehasher_function_t *rehasher) {
|
||||
(void)rehasher;
|
||||
return CreateWeapon(_fbb,
|
||||
_o->name.size() ? _fbb.CreateString(_o->name) : 0,
|
||||
_o->damage);
|
||||
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
|
||||
(void)_rehasher;
|
||||
(void)_o;
|
||||
struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const WeaponT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
|
||||
auto _name = _o->name.empty() ? 0 : _fbb.CreateString(_o->name);
|
||||
auto _damage = _o->damage;
|
||||
return MyGame::Sample::CreateWeapon(
|
||||
_fbb,
|
||||
_name,
|
||||
_damage);
|
||||
}
|
||||
|
||||
inline bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *union_obj, Equipment type) {
|
||||
inline bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *obj, Equipment type) {
|
||||
switch (type) {
|
||||
case Equipment_NONE: return true;
|
||||
case Equipment_Weapon: return verifier.VerifyTable(reinterpret_cast<const Weapon *>(union_obj));
|
||||
case Equipment_NONE: {
|
||||
return true;
|
||||
}
|
||||
case Equipment_Weapon: {
|
||||
auto ptr = reinterpret_cast<const Weapon *>(obj);
|
||||
return verifier.VerifyTable(ptr);
|
||||
}
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline flatbuffers::NativeTable *EquipmentUnion::UnPack(const void *union_obj, Equipment type, const flatbuffers::resolver_function_t *resolver) {
|
||||
inline bool VerifyEquipmentVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types) {
|
||||
if (values->size() != types->size()) return false;
|
||||
for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {
|
||||
if (!VerifyEquipment(
|
||||
verifier, values->Get(i), types->GetEnum<Equipment>(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void *EquipmentUnion::UnPack(const void *obj, Equipment type, const flatbuffers::resolver_function_t *resolver) {
|
||||
switch (type) {
|
||||
case Equipment_NONE: return nullptr;
|
||||
case Equipment_Weapon: return reinterpret_cast<const Weapon *>(union_obj)->UnPack(resolver);
|
||||
case Equipment_Weapon: {
|
||||
auto ptr = reinterpret_cast<const Weapon *>(obj);
|
||||
return ptr->UnPack(resolver);
|
||||
}
|
||||
default: return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
inline flatbuffers::Offset<void> EquipmentUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *rehasher) const {
|
||||
inline flatbuffers::Offset<void> EquipmentUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher) const {
|
||||
switch (type) {
|
||||
case Equipment_NONE: return 0;
|
||||
case Equipment_Weapon: return CreateWeapon(_fbb, reinterpret_cast<const WeaponT *>(table), rehasher).Union();
|
||||
case Equipment_Weapon: {
|
||||
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: delete reinterpret_cast<WeaponT *>(table); break;
|
||||
case Equipment_Weapon: {
|
||||
auto ptr = reinterpret_cast<WeaponT *>(value);
|
||||
delete ptr;
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
table = nullptr;
|
||||
value = nullptr;
|
||||
type = Equipment_NONE;
|
||||
}
|
||||
|
||||
inline flatbuffers::TypeTable *Vec3TypeTable();
|
||||
|
||||
inline flatbuffers::TypeTable *MonsterTypeTable();
|
||||
|
||||
inline flatbuffers::TypeTable *WeaponTypeTable();
|
||||
|
||||
inline flatbuffers::TypeTable *ColorTypeTable() {
|
||||
static flatbuffers::TypeCode type_codes[] = {
|
||||
{ flatbuffers::ET_CHAR, 0, 0 },
|
||||
{ flatbuffers::ET_CHAR, 0, 0 },
|
||||
{ flatbuffers::ET_CHAR, 0, 0 }
|
||||
};
|
||||
static flatbuffers::TypeFunction type_refs[] = {
|
||||
ColorTypeTable
|
||||
};
|
||||
static const char *names[] = {
|
||||
"Red",
|
||||
"Green",
|
||||
"Blue"
|
||||
};
|
||||
static flatbuffers::TypeTable tt = {
|
||||
flatbuffers::ST_ENUM, 3, type_codes, type_refs, nullptr, names
|
||||
};
|
||||
return &tt;
|
||||
}
|
||||
|
||||
inline flatbuffers::TypeTable *EquipmentTypeTable() {
|
||||
static flatbuffers::TypeCode type_codes[] = {
|
||||
{ flatbuffers::ET_SEQUENCE, 0, -1 },
|
||||
{ flatbuffers::ET_SEQUENCE, 0, 0 }
|
||||
};
|
||||
static flatbuffers::TypeFunction type_refs[] = {
|
||||
WeaponTypeTable
|
||||
};
|
||||
static const char *names[] = {
|
||||
"NONE",
|
||||
"Weapon"
|
||||
};
|
||||
static flatbuffers::TypeTable tt = {
|
||||
flatbuffers::ST_UNION, 2, type_codes, type_refs, nullptr, names
|
||||
};
|
||||
return &tt;
|
||||
}
|
||||
|
||||
inline flatbuffers::TypeTable *Vec3TypeTable() {
|
||||
static flatbuffers::TypeCode type_codes[] = {
|
||||
{ flatbuffers::ET_FLOAT, 0, -1 },
|
||||
{ flatbuffers::ET_FLOAT, 0, -1 },
|
||||
{ flatbuffers::ET_FLOAT, 0, -1 }
|
||||
};
|
||||
static const int32_t values[] = { 0, 4, 8, 12 };
|
||||
static const char *names[] = {
|
||||
"x",
|
||||
"y",
|
||||
"z"
|
||||
};
|
||||
static flatbuffers::TypeTable tt = {
|
||||
flatbuffers::ST_STRUCT, 3, type_codes, nullptr, values, names
|
||||
};
|
||||
return &tt;
|
||||
}
|
||||
|
||||
inline flatbuffers::TypeTable *MonsterTypeTable() {
|
||||
static flatbuffers::TypeCode type_codes[] = {
|
||||
{ flatbuffers::ET_SEQUENCE, 0, 0 },
|
||||
{ flatbuffers::ET_SHORT, 0, -1 },
|
||||
{ flatbuffers::ET_SHORT, 0, -1 },
|
||||
{ flatbuffers::ET_STRING, 0, -1 },
|
||||
{ flatbuffers::ET_BOOL, 0, -1 },
|
||||
{ flatbuffers::ET_UCHAR, 1, -1 },
|
||||
{ flatbuffers::ET_CHAR, 0, 1 },
|
||||
{ flatbuffers::ET_SEQUENCE, 1, 2 },
|
||||
{ flatbuffers::ET_UTYPE, 0, 3 },
|
||||
{ flatbuffers::ET_SEQUENCE, 0, 3 }
|
||||
};
|
||||
static flatbuffers::TypeFunction type_refs[] = {
|
||||
Vec3TypeTable,
|
||||
ColorTypeTable,
|
||||
WeaponTypeTable,
|
||||
EquipmentTypeTable
|
||||
};
|
||||
static const char *names[] = {
|
||||
"pos",
|
||||
"mana",
|
||||
"hp",
|
||||
"name",
|
||||
"friendly",
|
||||
"inventory",
|
||||
"color",
|
||||
"weapons",
|
||||
"equipped_type",
|
||||
"equipped"
|
||||
};
|
||||
static flatbuffers::TypeTable tt = {
|
||||
flatbuffers::ST_TABLE, 10, type_codes, type_refs, nullptr, names
|
||||
};
|
||||
return &tt;
|
||||
}
|
||||
|
||||
inline flatbuffers::TypeTable *WeaponTypeTable() {
|
||||
static flatbuffers::TypeCode type_codes[] = {
|
||||
{ flatbuffers::ET_STRING, 0, -1 },
|
||||
{ flatbuffers::ET_SHORT, 0, -1 }
|
||||
};
|
||||
static const char *names[] = {
|
||||
"name",
|
||||
"damage"
|
||||
};
|
||||
static flatbuffers::TypeTable tt = {
|
||||
flatbuffers::ST_TABLE, 2, type_codes, nullptr, nullptr, names
|
||||
};
|
||||
return &tt;
|
||||
}
|
||||
|
||||
inline const MyGame::Sample::Monster *GetMonster(const void *buf) {
|
||||
return flatbuffers::GetRoot<MyGame::Sample::Monster>(buf);
|
||||
}
|
||||
@@ -380,16 +724,21 @@ inline Monster *GetMutableMonster(void *buf) {
|
||||
return flatbuffers::GetMutableRoot<Monster>(buf);
|
||||
}
|
||||
|
||||
inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) {
|
||||
inline bool VerifyMonsterBuffer(
|
||||
flatbuffers::Verifier &verifier) {
|
||||
return verifier.VerifyBuffer<MyGame::Sample::Monster>(nullptr);
|
||||
}
|
||||
|
||||
inline void FinishMonsterBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<MyGame::Sample::Monster> root) {
|
||||
inline void FinishMonsterBuffer(
|
||||
flatbuffers::FlatBufferBuilder &fbb,
|
||||
flatbuffers::Offset<MyGame::Sample::Monster> root) {
|
||||
fbb.Finish(root);
|
||||
}
|
||||
|
||||
inline std::unique_ptr<MonsterT> UnPackMonster(const void *buf, const flatbuffers::resolver_function_t *resolver = nullptr) {
|
||||
return std::unique_ptr<MonsterT>(GetMonster(buf)->UnPack(resolver));
|
||||
inline flatbuffers::unique_ptr<MonsterT> UnPackMonster(
|
||||
const void *buf,
|
||||
const flatbuffers::resolver_function_t *res = nullptr) {
|
||||
return flatbuffers::unique_ptr<MonsterT>(GetMonster(buf)->UnPack(res));
|
||||
}
|
||||
|
||||
} // namespace Sample
|
||||
|
||||
0
samples/monsterdata.json
Executable file → Normal file
0
samples/monsterdata.json
Executable file → Normal file
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user