mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-02 12:05:50 +00:00
Compare commits
247 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
697147a2e6 | ||
|
|
6df40a2471 | ||
|
|
0dba63909f | ||
|
|
0e3fdd0eea | ||
|
|
45a2b07cbd | ||
|
|
d10c163142 | ||
|
|
35abb7f89b | ||
|
|
9954e09ab7 | ||
|
|
95a21327fc | ||
|
|
89b6183ee9 | ||
|
|
5a98d65e86 | ||
|
|
f73d205bc7 | ||
|
|
7c37abe92d | ||
|
|
4749e77b0e | ||
|
|
6ff1898413 | ||
|
|
c9a30c9ca2 | ||
|
|
8c02d17bea | ||
|
|
34305c4ce4 | ||
|
|
cd88e6b2aa | ||
|
|
3ec7a53c62 | ||
|
|
6d44cede70 | ||
|
|
cc08c0835b | ||
|
|
54f8b787cb | ||
|
|
17557f9131 | ||
|
|
d54af8cd43 | ||
|
|
173e10fdf1 | ||
|
|
8f56990f6c | ||
|
|
6400c9b054 | ||
|
|
7418d85872 | ||
|
|
c580fa284c | ||
|
|
f2a1272303 | ||
|
|
316d7c2089 | ||
|
|
47026ea6ba | ||
|
|
3f677f2414 | ||
|
|
a593a11e59 | ||
|
|
7cdfc8475e | ||
|
|
bab2b0db48 | ||
|
|
89418eb848 | ||
|
|
9cadf05d89 | ||
|
|
6da1cf79d9 | ||
|
|
bee1df96dc | ||
|
|
01189d7edd | ||
|
|
c4b2b0a25d | ||
|
|
a4b2884e4e | ||
|
|
04d80f255d | ||
|
|
55686100aa | ||
|
|
718351831d | ||
|
|
d1b34f0f28 | ||
|
|
21b7061963 | ||
|
|
35daaf83d3 | ||
|
|
3b458f7a17 | ||
|
|
a5d9d0f7d3 | ||
|
|
3cd9b6434a | ||
|
|
355dfd48d1 | ||
|
|
bcd58a159b | ||
|
|
a2c12900aa | ||
|
|
901b89e733 | ||
|
|
31f8799083 | ||
|
|
8023d99e21 | ||
|
|
b4154405d1 | ||
|
|
04c17c7a76 | ||
|
|
62ec7d52ce | ||
|
|
7de668053f | ||
|
|
3a70e0b308 | ||
|
|
9b13201356 | ||
|
|
5e3916050c | ||
|
|
c957550511 | ||
|
|
44bf719883 | ||
|
|
3e8f15df90 | ||
|
|
602721a735 | ||
|
|
13c05f4da3 | ||
|
|
ce3a1c43a2 | ||
|
|
aa75e5734b | ||
|
|
2790fee257 | ||
|
|
eddebec1b6 | ||
|
|
030fee36ab | ||
|
|
f9724d1bde | ||
|
|
b20801ca40 | ||
|
|
a8e800bd7c | ||
|
|
d7530ae961 | ||
|
|
99d11e279f | ||
|
|
4fd8eb214b | ||
|
|
65f8703572 | ||
|
|
75823cc275 | ||
|
|
58e279244c | ||
|
|
3c964e10ab | ||
|
|
c3c32ec942 | ||
|
|
075e8d676b | ||
|
|
bcf1bd5c9e | ||
|
|
136d75fa65 | ||
|
|
091fa1fd1b | ||
|
|
ff3781dc2d | ||
|
|
6beb9f49cb | ||
|
|
80988ea869 | ||
|
|
0f2ff7eaa9 | ||
|
|
dda095023d | ||
|
|
adbcbba5d1 | ||
|
|
cbbd6aca04 | ||
|
|
405c64e07d | ||
|
|
42c08cbca6 | ||
|
|
33d5dd9bdd | ||
|
|
105dd528e9 | ||
|
|
f0f0efe7b8 | ||
|
|
e837d5a296 | ||
|
|
9834ee9787 | ||
|
|
44b2ab087c | ||
|
|
46ae3f80a6 | ||
|
|
7b38aa71e6 | ||
|
|
661bedd837 | ||
|
|
8526e12d73 | ||
|
|
3c7b660d62 | ||
|
|
964365ba69 | ||
|
|
32254b7acd | ||
|
|
521e255ad9 | ||
|
|
1b85292fd3 | ||
|
|
480815447a | ||
|
|
8d5e424c65 | ||
|
|
b4774d2354 | ||
|
|
26f238c248 | ||
|
|
e93c8c46e6 | ||
|
|
e21516b9d7 | ||
|
|
fbc11e8aec | ||
|
|
e9d29c21a7 | ||
|
|
8bfafc76de | ||
|
|
df3e8bf4a7 | ||
|
|
5665cfe492 | ||
|
|
5797540ed0 | ||
|
|
7f1af7cb02 | ||
|
|
32f47ad247 | ||
|
|
842f672baf | ||
|
|
d4cae0a623 | ||
|
|
f1147f65bb | ||
|
|
69d3fec488 | ||
|
|
cfb4ecf6f0 | ||
|
|
a92039687a | ||
|
|
625338d095 | ||
|
|
3f8ce99c50 | ||
|
|
0798b7b698 | ||
|
|
cbdf82e2fb | ||
|
|
e365c502ff | ||
|
|
97f3aa9174 | ||
|
|
2f5bb2eec4 | ||
|
|
917687c7a6 | ||
|
|
f9277e691d | ||
|
|
2706381eef | ||
|
|
b5560fcd52 | ||
|
|
782b865c55 | ||
|
|
3bfc86eaff | ||
|
|
c0282873fb | ||
|
|
4b870aca98 | ||
|
|
d0e3870c0f | ||
|
|
fb25eb87f2 | ||
|
|
cb35d3a0e5 | ||
|
|
8e6cabb31b | ||
|
|
bd31dd2425 | ||
|
|
65b67d2132 | ||
|
|
1fbb711324 | ||
|
|
cd75a36587 | ||
|
|
ec6b0bf297 | ||
|
|
c11b5d7447 | ||
|
|
4525c91be3 | ||
|
|
b97b342f59 | ||
|
|
c1058a903b | ||
|
|
3030449348 | ||
|
|
a2485d4ecc | ||
|
|
a20e71ac96 | ||
|
|
acc9990abd | ||
|
|
2d5315ff0e | ||
|
|
7de1a5e347 | ||
|
|
a4e3ad808e | ||
|
|
c953fa572b | ||
|
|
0c86085a5b | ||
|
|
a1f7ecd148 | ||
|
|
a20c55bea5 | ||
|
|
d7c2b388ef | ||
|
|
9fa8245e81 | ||
|
|
a5ca8bee4d | ||
|
|
09dea79a22 | ||
|
|
b632061eff | ||
|
|
da88be05e1 | ||
|
|
d4fa984f1d | ||
|
|
a0c0131e36 | ||
|
|
de9aa0cdee | ||
|
|
a752d1b88c | ||
|
|
db972be264 | ||
|
|
e304f8c115 | ||
|
|
47c7aa0361 | ||
|
|
7a63792929 | ||
|
|
7d7d796cd0 | ||
|
|
550b386995 | ||
|
|
5479adc80f | ||
|
|
b7012484f3 | ||
|
|
92e9f33036 | ||
|
|
ff1a22a05f | ||
|
|
9fb195cce8 | ||
|
|
7836e65dd4 | ||
|
|
123c7a4890 | ||
|
|
e635141d5b | ||
|
|
0d2cebccfe | ||
|
|
a80db8538c | ||
|
|
a6be1d0d74 | ||
|
|
a7e20b1996 | ||
|
|
4eb3efc221 | ||
|
|
a807fa9567 | ||
|
|
b80ad7e439 | ||
|
|
16aef8ac0d | ||
|
|
b59a1ca2f8 | ||
|
|
4fdfe0d468 | ||
|
|
95004218f7 | ||
|
|
bc7ede8fb3 | ||
|
|
b652fcc3a7 | ||
|
|
c978b9ef1f | ||
|
|
3a88e1031b | ||
|
|
51dd733ba4 | ||
|
|
79f0df3dfc | ||
|
|
9d92fd92e1 | ||
|
|
93f74c0363 | ||
|
|
43dbac5d25 | ||
|
|
53ea1ab1bd | ||
|
|
b10b050ab9 | ||
|
|
563dcd6893 | ||
|
|
30ac512a54 | ||
|
|
b04736f9bd | ||
|
|
bc240b3004 | ||
|
|
0f7e7fd209 | ||
|
|
766ed04422 | ||
|
|
c5e2d37337 | ||
|
|
fe83b68ac6 | ||
|
|
718ddea558 | ||
|
|
8d86b5347f | ||
|
|
39bd667fd0 | ||
|
|
0bb3ce6935 | ||
|
|
b56d60f058 | ||
|
|
bff7ffbc51 | ||
|
|
107c08988a | ||
|
|
f9ebfcb9c4 | ||
|
|
b701c7d56e | ||
|
|
103f61b685 | ||
|
|
e47ca7ab40 | ||
|
|
d79f4e9717 | ||
|
|
5d67693e8f | ||
|
|
af74f87ccd | ||
|
|
b8ef8c1521 | ||
|
|
6cc30b3272 | ||
|
|
e5b6125fa2 | ||
|
|
ac14c8906f | ||
|
|
9936adf473 |
@@ -19,6 +19,7 @@ call generate_code.bat -b %buildtype% || goto FAIL
|
||||
|
||||
:: TODO: Release and Debug builds produce differences here for some reason.
|
||||
git checkout HEAD -- monster_test.bfbs
|
||||
git checkout HEAD -- arrays_test.bfbs
|
||||
|
||||
git -c core.autocrlf=true diff --exit-code --quiet || goto :DIFFFOUND
|
||||
goto SUCCESS
|
||||
|
||||
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,6 +1,8 @@
|
||||
Thank you for submitting a PR!
|
||||
|
||||
Please make sure you include the names of the affected language(s) in your PR title.
|
||||
Please delete this standard text once you've created your own description.
|
||||
|
||||
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
|
||||
@@ -11,6 +13,8 @@ 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.
|
||||
|
||||
For any C++ changes, please make sure to run `sh src/clang-format-git.sh`
|
||||
|
||||
Include other details as appropriate.
|
||||
|
||||
Thanks!
|
||||
|
||||
18
.github/stale.yml
vendored
Normal file
18
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 365
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 14
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
activity for 1 year. It will be automatically closed if no further activity occurs.
|
||||
To keep it open, simply post a new comment. Maintainers will re-open on
|
||||
new activity. Thank you for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -1,6 +1,12 @@
|
||||
*_wire.txt
|
||||
*_wire.bin
|
||||
.DS_Store
|
||||
**/.build
|
||||
**/Packages
|
||||
/*.xcodeproj
|
||||
**/xcuserdata/
|
||||
**/xcshareddata/
|
||||
**/.swiftpm/
|
||||
*.o
|
||||
*.o.d
|
||||
*.class
|
||||
@@ -116,3 +122,6 @@ dart/doc/api/
|
||||
Cargo.lock
|
||||
.corpus**
|
||||
.seed**
|
||||
grpc/google/
|
||||
**/Package.resolved
|
||||
.clangd/**
|
||||
|
||||
47
.travis.yml
47
.travis.yml
@@ -22,6 +22,21 @@ conan-linux: &conan-linux
|
||||
- ./conan/travis/build.sh
|
||||
if: tag IS present
|
||||
|
||||
conan-linux-master: &conan-linux-master
|
||||
os: linux
|
||||
dist: xenial
|
||||
language: python
|
||||
python: "3.7"
|
||||
services:
|
||||
- docker
|
||||
install:
|
||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./conan/travis/install.sh; fi'
|
||||
script:
|
||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./conan/travis/build.sh; fi'
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
conan-osx: &conan-osx
|
||||
os: osx
|
||||
language: generic
|
||||
@@ -78,7 +93,7 @@ matrix:
|
||||
env:
|
||||
matrix:
|
||||
- BUILD_TYPE=Debug
|
||||
- BUILD_TYPE=Release CONAN=true
|
||||
- BUILD_TYPE=Release
|
||||
|
||||
before_install:
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
|
||||
@@ -97,10 +112,9 @@ matrix:
|
||||
-DGRPC_INSTALL_PATH=$TRAVIS_BUILD_DIR/google/grpc/install
|
||||
-DPROTOBUF_DOWNLOAD_PATH=$TRAVIS_BUILD_DIR/google/grpc/third_party/protobuf
|
||||
-DFLATBUFFERS_CODE_SANITIZE=ON
|
||||
- cmake --build . -- -j${JOBS}
|
||||
- cmake --build . --target all --clean-first -- -j${JOBS}
|
||||
- LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/google/grpc/install/lib ctest --extra-verbose --output-on-failure
|
||||
- bash .travis/check-generate-code.sh
|
||||
- if [ "$CONAN" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo pip install conan && conan create . flatbuffers/${TRAVIS_BRANCH}@google/testing -s build_type=$BUILD_TYPE -tf conan/test_package; fi
|
||||
|
||||
- language: cpp
|
||||
os: osx
|
||||
@@ -122,6 +136,8 @@ matrix:
|
||||
- DYLD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/google/grpc/install/lib ctest --extra-verbose --output-on-failure
|
||||
- bash .travis/check-generate-code.sh
|
||||
|
||||
- <<: *conan-linux-master
|
||||
env: CONAN_GCC_VERSIONS=8 CONAN_DOCKER_IMAGE=conanio/gcc8
|
||||
- <<: *conan-linux
|
||||
env: CONAN_GCC_VERSIONS=4.9 CONAN_DOCKER_IMAGE=conanio/gcc49
|
||||
- <<: *conan-linux
|
||||
@@ -132,6 +148,8 @@ matrix:
|
||||
env: CONAN_GCC_VERSIONS=7 CONAN_DOCKER_IMAGE=conanio/gcc7
|
||||
- <<: *conan-linux
|
||||
env: CONAN_GCC_VERSIONS=8 CONAN_DOCKER_IMAGE=conanio/gcc8
|
||||
- <<: *conan-linux
|
||||
env: CONAN_GCC_VERSIONS=9 CONAN_DOCKER_IMAGE=conanio/gcc9
|
||||
- <<: *conan-linux
|
||||
env: CONAN_CLANG_VERSIONS=3.9 CONAN_DOCKER_IMAGE=conanio/clang39
|
||||
- <<: *conan-linux
|
||||
@@ -140,6 +158,10 @@ matrix:
|
||||
env: CONAN_CLANG_VERSIONS=5.0 CONAN_DOCKER_IMAGE=conanio/clang50
|
||||
- <<: *conan-linux
|
||||
env: CONAN_CLANG_VERSIONS=6.0 CONAN_DOCKER_IMAGE=conanio/clang60
|
||||
- <<: *conan-linux
|
||||
env: CONAN_CLANG_VERSIONS=7.0 CONAN_DOCKER_IMAGE=conanio/clang7
|
||||
- <<: *conan-linux
|
||||
env: CONAN_CLANG_VERSIONS=8 CONAN_DOCKER_IMAGE=conanio/clang8
|
||||
- <<: *conan-osx
|
||||
osx_image: xcode7.3
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=7.3
|
||||
@@ -153,11 +175,12 @@ matrix:
|
||||
osx_image: xcode9.4
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=9.1
|
||||
- <<: *conan-osx
|
||||
osx_image: xcode10
|
||||
osx_image: xcode10.2
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=10.0
|
||||
|
||||
- language: android
|
||||
sudo: true
|
||||
dist: trusty
|
||||
android:
|
||||
components:
|
||||
- tools
|
||||
@@ -171,8 +194,20 @@ matrix:
|
||||
before_install:
|
||||
# Output something every 10 minutes or Travis kills the job
|
||||
- while sleep 540; do echo "=====[ $SECONDS seconds still running ]====="; done &
|
||||
- git clone https://github.com/urho3d/android-ndk.git $HOME/android-ndk-root
|
||||
- export ANDROID_NDK_HOME=$HOME/android-ndk-root
|
||||
# Install the r17c version of the NDK that still so that we can continue to test with gnustl
|
||||
# and stlport.
|
||||
- export ANDROID_NDK_HOME=$HOME/android-ndk
|
||||
- NDK_ZIP=$ANDROID_NDK_HOME/ndk.zip
|
||||
- mkdir -p $ANDROID_NDK_HOME
|
||||
- curl -o $NDK_ZIP https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip
|
||||
- unzip -q -d $ANDROID_NDK_HOME $NDK_ZIP
|
||||
- rm $NDK_ZIP
|
||||
- mv $ANDROID_NDK_HOME/android-ndk-*/* $ANDROID_NDK_HOME
|
||||
- rmdir $ANDROID_NDK_HOME/android-ndk-*
|
||||
- export CMAKE=$(which cmake)
|
||||
# libc required for prebuilt llvm toolchain the NDK r17c.
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq libc6; fi
|
||||
# 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
|
||||
|
||||
@@ -15,10 +15,15 @@
|
||||
# limitations under the License.
|
||||
set -e
|
||||
|
||||
# build flatc on debian once to speed up the test loop below
|
||||
docker build -t build_flatc_debian_stretch -f tests/docker/Dockerfile.testing.build_flatc_debian_stretch .
|
||||
BUILD_CONTAINER_ID=$(docker create --read-only build_flatc_debian_stretch)
|
||||
docker cp ${BUILD_CONTAINER_ID}:/code/flatc flatc_debian_stretch
|
||||
docker build -t build_cpp_image -f tests/docker/Dockerfile.testing.cpp.debian_buster .
|
||||
# Run tests with sanitizers (--cap-add SYS_PTRACE), both GCC and Clang.
|
||||
cpp_test_args="--cap-add SYS_PTRACE build_cpp_image sh ./tests/docker/cpp_test.run.sh Debug"
|
||||
docker run --rm $cpp_test_args
|
||||
docker run --rm --env CC=/usr/bin/clang --env CXX=/usr/bin/clang++ $cpp_test_args
|
||||
# Build flatc on debian once to speed up the test loop below.
|
||||
docker run --name flatc_container build_cpp_image sh ./tests/docker/build_flatc.run.sh Debug
|
||||
# All dependent dockers refer to 'flatc_debian_stretch'.
|
||||
docker cp flatc_container:/flatbuffers/flatc flatc_debian_stretch
|
||||
|
||||
for f in $(ls tests/docker/languages | sort)
|
||||
do
|
||||
|
||||
@@ -21,6 +21,8 @@ cd ..
|
||||
|
||||
# TODO: Linux and macos builds produce differences here for some reason.
|
||||
git checkout HEAD -- tests/monster_test.bfbs
|
||||
git checkout HEAD -- tests/arrays_test.bfbs
|
||||
git checkout HEAD -- samples/monster.bfbs
|
||||
|
||||
if ! git diff --quiet; then
|
||||
echo >&2
|
||||
|
||||
148
BUILD
148
BUILD
@@ -1,34 +1,22 @@
|
||||
licenses(["notice"])
|
||||
|
||||
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
|
||||
|
||||
package(
|
||||
default_visibility = ["//visibility:public"],
|
||||
features = [
|
||||
"-layering_check",
|
||||
"-parse_headers",
|
||||
],
|
||||
)
|
||||
|
||||
exports_files([
|
||||
"LICENSE",
|
||||
])
|
||||
|
||||
load(":build_defs.bzl", "flatbuffer_cc_library")
|
||||
|
||||
# Public flatc library to compile flatbuffer files at runtime.
|
||||
cc_library(
|
||||
name = "flatbuffers",
|
||||
srcs = [
|
||||
"src/code_generators.cpp",
|
||||
"src/idl_gen_fbs.cpp",
|
||||
"src/idl_gen_general.cpp",
|
||||
"src/idl_gen_text.cpp",
|
||||
"src/idl_parser.cpp",
|
||||
"src/reflection.cpp",
|
||||
"src/util.cpp",
|
||||
],
|
||||
hdrs = [":public_headers"],
|
||||
includes = ["include/"],
|
||||
hdrs = ["//:public_headers"],
|
||||
linkstatic = 1,
|
||||
strip_include_prefix = "/include",
|
||||
deps = ["//src:flatbuffers"],
|
||||
)
|
||||
|
||||
# Public C++ headers for the Flatbuffers library.
|
||||
@@ -44,6 +32,7 @@ filegroup(
|
||||
"include/flatbuffers/minireflect.h",
|
||||
"include/flatbuffers/reflection.h",
|
||||
"include/flatbuffers/reflection_generated.h",
|
||||
"include/flatbuffers/registry.h",
|
||||
"include/flatbuffers/stl_emulation.h",
|
||||
"include/flatbuffers/util.h",
|
||||
],
|
||||
@@ -52,60 +41,29 @@ filegroup(
|
||||
# Public flatc compiler library.
|
||||
cc_library(
|
||||
name = "flatc_library",
|
||||
srcs = [
|
||||
"src/code_generators.cpp",
|
||||
"src/flatc.cpp",
|
||||
"src/idl_gen_fbs.cpp",
|
||||
"src/idl_parser.cpp",
|
||||
"src/reflection.cpp",
|
||||
"src/util.cpp",
|
||||
],
|
||||
hdrs = [
|
||||
"include/flatbuffers/flatc.h",
|
||||
":public_headers",
|
||||
],
|
||||
includes = [
|
||||
"grpc/",
|
||||
"include/",
|
||||
linkstatic = 1,
|
||||
deps = [
|
||||
"//src:flatc_library",
|
||||
],
|
||||
)
|
||||
|
||||
# Public flatc compiler.
|
||||
cc_binary(
|
||||
name = "flatc",
|
||||
srcs = [
|
||||
"grpc/src/compiler/config.h",
|
||||
"grpc/src/compiler/cpp_generator.cc",
|
||||
"grpc/src/compiler/cpp_generator.h",
|
||||
"grpc/src/compiler/go_generator.cc",
|
||||
"grpc/src/compiler/go_generator.h",
|
||||
"grpc/src/compiler/java_generator.cc",
|
||||
"grpc/src/compiler/java_generator.h",
|
||||
"grpc/src/compiler/schema_interface.h",
|
||||
"src/flatc_main.cpp",
|
||||
"src/idl_gen_cpp.cpp",
|
||||
"src/idl_gen_dart.cpp",
|
||||
"src/idl_gen_general.cpp",
|
||||
"src/idl_gen_go.cpp",
|
||||
"src/idl_gen_grpc.cpp",
|
||||
"src/idl_gen_js_ts.cpp",
|
||||
"src/idl_gen_json_schema.cpp",
|
||||
"src/idl_gen_lobster.cpp",
|
||||
"src/idl_gen_lua.cpp",
|
||||
"src/idl_gen_php.cpp",
|
||||
"src/idl_gen_python.cpp",
|
||||
"src/idl_gen_rust.cpp",
|
||||
"src/idl_gen_text.cpp",
|
||||
],
|
||||
includes = [
|
||||
"grpc/",
|
||||
"include/",
|
||||
],
|
||||
deps = [
|
||||
":flatc_library",
|
||||
"//src:flatc",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "flatc_headers",
|
||||
srcs = [
|
||||
"include/flatbuffers/flatc.h",
|
||||
],
|
||||
visibility = ["//:__subpackages__"],
|
||||
)
|
||||
|
||||
# Library used by flatbuffer_cc_library rules.
|
||||
cc_library(
|
||||
name = "runtime_cc",
|
||||
hdrs = [
|
||||
@@ -115,72 +73,6 @@ cc_library(
|
||||
"include/flatbuffers/stl_emulation.h",
|
||||
"include/flatbuffers/util.h",
|
||||
],
|
||||
includes = ["include/"],
|
||||
linkstatic = 1,
|
||||
)
|
||||
|
||||
# Test binary.
|
||||
cc_test(
|
||||
name = "flatbuffers_test",
|
||||
testonly = 1,
|
||||
srcs = [
|
||||
"include/flatbuffers/minireflect.h",
|
||||
"include/flatbuffers/registry.h",
|
||||
"src/code_generators.cpp",
|
||||
"src/idl_gen_fbs.cpp",
|
||||
"src/idl_gen_general.cpp",
|
||||
"src/idl_gen_text.cpp",
|
||||
"src/idl_parser.cpp",
|
||||
"src/reflection.cpp",
|
||||
"src/util.cpp",
|
||||
"tests/namespace_test/namespace_test1_generated.h",
|
||||
"tests/namespace_test/namespace_test2_generated.h",
|
||||
"tests/test.cpp",
|
||||
"tests/test_assert.cpp",
|
||||
"tests/test_assert.h",
|
||||
"tests/test_builder.cpp",
|
||||
"tests/test_builder.h",
|
||||
"tests/union_vector/union_vector_generated.h",
|
||||
":public_headers",
|
||||
],
|
||||
copts = [
|
||||
"-DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE",
|
||||
"-DBAZEL_TEST_DATA_PATH",
|
||||
],
|
||||
data = [
|
||||
":tests/include_test/include_test1.fbs",
|
||||
":tests/include_test/sub/include_test2.fbs",
|
||||
":tests/monster_test.bfbs",
|
||||
":tests/monster_test.fbs",
|
||||
":tests/monsterdata_test.golden",
|
||||
":tests/prototest/imported.proto",
|
||||
":tests/prototest/test.golden",
|
||||
":tests/prototest/test.proto",
|
||||
":tests/prototest/test_union.golden",
|
||||
":tests/unicode_test.json",
|
||||
":tests/union_vector/union_vector.fbs",
|
||||
":tests/union_vector/union_vector.json",
|
||||
],
|
||||
includes = ["include/"],
|
||||
deps = [
|
||||
":monster_extra_cc_fbs",
|
||||
":monster_test_cc_fbs",
|
||||
],
|
||||
)
|
||||
|
||||
# Test bzl rules
|
||||
|
||||
flatbuffer_cc_library(
|
||||
name = "monster_test_cc_fbs",
|
||||
srcs = ["tests/monster_test.fbs"],
|
||||
include_paths = ["tests/include_test"],
|
||||
includes = [
|
||||
"tests/include_test/include_test1.fbs",
|
||||
"tests/include_test/sub/include_test2.fbs",
|
||||
],
|
||||
)
|
||||
|
||||
flatbuffer_cc_library(
|
||||
name = "monster_extra_cc_fbs",
|
||||
srcs = ["tests/monster_extra.fbs"],
|
||||
strip_include_prefix = "/include",
|
||||
)
|
||||
|
||||
254
CMakeLists.txt
254
CMakeLists.txt
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
# generate compile_commands.json
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
include(CheckCXXSymbolExists)
|
||||
@@ -13,6 +13,8 @@ option(FLATBUFFERS_BUILD_FLATLIB "Enable the build of the flatbuffers library"
|
||||
ON)
|
||||
option(FLATBUFFERS_BUILD_FLATC "Enable the build of the flatbuffers compiler"
|
||||
ON)
|
||||
option(FLATBUFFERS_STATIC_FLATC "Build flatbuffers compiler with -static flag"
|
||||
OFF)
|
||||
option(FLATBUFFERS_BUILD_FLATHASH "Enable the build of flathash" ON)
|
||||
option(FLATBUFFERS_BUILD_GRPCTEST "Enable the build of grpctest" OFF)
|
||||
option(FLATBUFFERS_BUILD_SHAREDLIB
|
||||
@@ -29,6 +31,13 @@ option(FLATBUFFERS_PACKAGE_REDHAT
|
||||
option(FLATBUFFERS_PACKAGE_DEBIAN
|
||||
"Build an deb using the 'package' target."
|
||||
OFF)
|
||||
option(FLATBUFFERS_BUILD_CPP17
|
||||
"Enable the build of c++17 test target. \"
|
||||
Requirements: Clang6, GCC7, MSVC2017 (_MSC_VER >= 1914) or higher."
|
||||
OFF)
|
||||
option(FLATBUFFERS_BUILD_LEGACY
|
||||
"Run C++ code generator with '--cpp-std c++0x' switch."
|
||||
OFF)
|
||||
|
||||
if(NOT FLATBUFFERS_BUILD_FLATC AND FLATBUFFERS_BUILD_TESTS)
|
||||
message(WARNING
|
||||
@@ -42,18 +51,23 @@ if(DEFINED FLATBUFFERS_MAX_PARSING_DEPTH)
|
||||
message(STATUS "FLATBUFFERS_MAX_PARSING_DEPTH: ${FLATBUFFERS_MAX_PARSING_DEPTH}")
|
||||
endif()
|
||||
|
||||
# Auto-detect locale-narrow 'strtod_l' function.
|
||||
# Auto-detect locale-narrow 'strtod_l' and 'strtoull_l' functions.
|
||||
if(NOT DEFINED FLATBUFFERS_LOCALE_INDEPENDENT)
|
||||
set(FLATBUFFERS_LOCALE_INDEPENDENT 0)
|
||||
if(MSVC)
|
||||
check_cxx_symbol_exists(_strtof_l stdlib.h FLATBUFFERS_LOCALE_INDEPENDENT)
|
||||
check_cxx_symbol_exists(_strtof_l stdlib.h FLATBUFFERS_HAS_STRTOF_L)
|
||||
check_cxx_symbol_exists(_strtoui64_l stdlib.h FLATBUFFERS_HAS_STRTOULL_L)
|
||||
else()
|
||||
check_cxx_symbol_exists(strtof_l stdlib.h FLATBUFFERS_LOCALE_INDEPENDENT)
|
||||
check_cxx_symbol_exists(strtof_l stdlib.h FLATBUFFERS_HAS_STRTOF_L)
|
||||
check_cxx_symbol_exists(strtoull_l stdlib.h FLATBUFFERS_HAS_STRTOULL_L)
|
||||
endif()
|
||||
if(FLATBUFFERS_HAS_STRTOF_L AND FLATBUFFERS_HAS_STRTOULL_L)
|
||||
set(FLATBUFFERS_LOCALE_INDEPENDENT 1)
|
||||
endif()
|
||||
endif()
|
||||
add_definitions(-DFLATBUFFERS_LOCALE_INDEPENDENT=$<BOOL:${FLATBUFFERS_LOCALE_INDEPENDENT}>)
|
||||
|
||||
set(FlatBuffers_Library_SRCS
|
||||
include/flatbuffers/code_generators.h
|
||||
include/flatbuffers/base.h
|
||||
include/flatbuffers/flatbuffers.h
|
||||
include/flatbuffers/hash.h
|
||||
@@ -65,7 +79,6 @@ set(FlatBuffers_Library_SRCS
|
||||
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
|
||||
@@ -75,9 +88,11 @@ set(FlatBuffers_Library_SRCS
|
||||
set(FlatBuffers_Compiler_SRCS
|
||||
${FlatBuffers_Library_SRCS}
|
||||
src/idl_gen_cpp.cpp
|
||||
src/idl_gen_csharp.cpp
|
||||
src/idl_gen_dart.cpp
|
||||
src/idl_gen_general.cpp
|
||||
src/idl_gen_kotlin.cpp
|
||||
src/idl_gen_go.cpp
|
||||
src/idl_gen_java.cpp
|
||||
src/idl_gen_js_ts.cpp
|
||||
src/idl_gen_php.cpp
|
||||
src/idl_gen_python.cpp
|
||||
@@ -87,8 +102,11 @@ set(FlatBuffers_Compiler_SRCS
|
||||
src/idl_gen_fbs.cpp
|
||||
src/idl_gen_grpc.cpp
|
||||
src/idl_gen_json_schema.cpp
|
||||
src/idl_gen_swift.cpp
|
||||
src/flatc.cpp
|
||||
src/flatc_main.cpp
|
||||
include/flatbuffers/code_generators.h
|
||||
src/code_generators.cpp
|
||||
grpc/src/compiler/schema_interface.h
|
||||
grpc/src/compiler/cpp_generator.h
|
||||
grpc/src/compiler/cpp_generator.cc
|
||||
@@ -96,6 +114,11 @@ set(FlatBuffers_Compiler_SRCS
|
||||
grpc/src/compiler/go_generator.cc
|
||||
grpc/src/compiler/java_generator.h
|
||||
grpc/src/compiler/java_generator.cc
|
||||
grpc/src/compiler/python_generator.h
|
||||
grpc/src/compiler/python_private_generator.h
|
||||
grpc/src/compiler/python_generator.cc
|
||||
grpc/src/compiler/swift_generator.h
|
||||
grpc/src/compiler/swift_generator.cc
|
||||
)
|
||||
|
||||
set(FlatHash_SRCS
|
||||
@@ -111,8 +134,35 @@ set(FlatBuffers_Tests_SRCS
|
||||
tests/test_assert.cpp
|
||||
tests/test_builder.h
|
||||
tests/test_builder.cpp
|
||||
tests/native_type_test_impl.h
|
||||
tests/native_type_test_impl.cpp
|
||||
include/flatbuffers/code_generators.h
|
||||
src/code_generators.cpp
|
||||
# file generate by running compiler on tests/monster_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h
|
||||
# file generate by running compiler on namespace_test/namespace_test1.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/namespace_test/namespace_test1_generated.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/namespace_test/namespace_test2_generated.h
|
||||
# file generate by running compiler on union_vector/union_vector.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/union_vector/union_vector_generated.h
|
||||
# file generate by running compiler on tests/arrays_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/arrays_test_generated.h
|
||||
# file generate by running compiler on tests/native_type_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/native_type_test_generated.h
|
||||
# file generate by running compiler on tests/monster_extra.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_extra_generated.h
|
||||
# file generate by running compiler on tests/monster_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_bfbs_generated.h
|
||||
)
|
||||
|
||||
set(FlatBuffers_Tests_CPP17_SRCS
|
||||
${FlatBuffers_Library_SRCS}
|
||||
tests/test_assert.h
|
||||
tests/test_assert.cpp
|
||||
tests/cpp17/test_cpp17.cpp
|
||||
# file generate by running compiler on tests/monster_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/cpp17/generated_cpp17/monster_test_generated.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h
|
||||
)
|
||||
|
||||
set(FlatBuffers_Sample_Binary_SRCS
|
||||
@@ -131,7 +181,6 @@ set(FlatBuffers_Sample_Text_SRCS
|
||||
|
||||
set(FlatBuffers_Sample_BFBS_SRCS
|
||||
${FlatBuffers_Library_SRCS}
|
||||
src/idl_gen_general.cpp
|
||||
samples/sample_bfbs.cpp
|
||||
# file generated by running compiler on samples/monster.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
|
||||
@@ -140,6 +189,8 @@ set(FlatBuffers_Sample_BFBS_SRCS
|
||||
set(FlatBuffers_GRPCTest_SRCS
|
||||
include/flatbuffers/flatbuffers.h
|
||||
include/flatbuffers/grpc.h
|
||||
include/flatbuffers/util.h
|
||||
src/util.cpp
|
||||
tests/monster_test.grpc.fb.h
|
||||
tests/test_assert.h
|
||||
tests/test_builder.h
|
||||
@@ -148,8 +199,8 @@ set(FlatBuffers_GRPCTest_SRCS
|
||||
tests/test_builder.cpp
|
||||
grpc/tests/grpctest.cpp
|
||||
grpc/tests/message_builder_test.cpp
|
||||
# file generated by running compiler on samples/monster.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
|
||||
# file generate by running compiler on tests/monster_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h
|
||||
)
|
||||
|
||||
# source_group(Compiler FILES ${FlatBuffers_Compiler_SRCS})
|
||||
@@ -226,23 +277,28 @@ if(FLATBUFFERS_CODE_COVERAGE)
|
||||
endif()
|
||||
|
||||
function(add_fsanitize_to_target _target _sanitizer)
|
||||
# FLATBUFFERS_CODE_SANITIZE: boolean {ON,OFF,YES,NO} or string with list of sanitizer.
|
||||
# List of sanitizer is string starts with '=': "=address,undefined,thread,memory".
|
||||
if((${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") OR
|
||||
((${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9"))
|
||||
)
|
||||
set(_sanitizer_flags "=address,undefined")
|
||||
if(_sanitizer MATCHES "=.*")
|
||||
# override default by user-defined sanitizer list
|
||||
set(_sanitizer_flags ${_sanitizer})
|
||||
if(WIN32)
|
||||
target_compile_definitions(${_target} PRIVATE FLATBUFFERS_MEMORY_LEAK_TRACKING)
|
||||
message(STATUS "Sanitizer MSVC::_CrtDumpMemoryLeaks added to ${_target}")
|
||||
else()
|
||||
# FLATBUFFERS_CODE_SANITIZE: boolean {ON,OFF,YES,NO} or string with list of sanitizer.
|
||||
# List of sanitizer is string starts with '=': "=address,undefined,thread,memory".
|
||||
if((${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") OR
|
||||
((${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9"))
|
||||
)
|
||||
set(_sanitizer_flags "=address,undefined")
|
||||
if(_sanitizer MATCHES "=.*")
|
||||
# override default by user-defined sanitizer list
|
||||
set(_sanitizer_flags ${_sanitizer})
|
||||
endif()
|
||||
target_compile_options(${_target} PRIVATE
|
||||
-g -fsigned-char -fno-omit-frame-pointer
|
||||
"-fsanitize${_sanitizer_flags}")
|
||||
target_link_libraries(${_target} PRIVATE
|
||||
"-fsanitize${_sanitizer_flags}")
|
||||
set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
message(STATUS "Sanitizer ${_sanitizer_flags} added to ${_target}")
|
||||
endif()
|
||||
target_compile_options(${_target} PRIVATE
|
||||
-g -fsigned-char -fno-omit-frame-pointer
|
||||
"-fsanitize${_sanitizer_flags}")
|
||||
target_link_libraries(${_target} PRIVATE
|
||||
"-fsanitize${_sanitizer_flags}")
|
||||
set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
message(STATUS "Sanitizer ${_sanitizer_flags} added to ${_target}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
@@ -256,7 +312,7 @@ include_directories(grpc)
|
||||
|
||||
if(FLATBUFFERS_BUILD_FLATLIB)
|
||||
add_library(flatbuffers STATIC ${FlatBuffers_Library_SRCS})
|
||||
# CMake > 2.8.11: Attach header directory for when build via add_subdirectory().
|
||||
# Attach header directory for when build via add_subdirectory().
|
||||
target_include_directories(flatbuffers INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
|
||||
target_compile_options(flatbuffers PRIVATE "${FLATBUFFERS_PRIVATE_CXX_FLAGS}")
|
||||
@@ -275,6 +331,9 @@ if(FLATBUFFERS_BUILD_FLATC)
|
||||
# Make flatc.exe not depend on runtime dlls for easy distribution.
|
||||
target_compile_options(flatc PUBLIC $<$<CONFIG:Release>:/MT>)
|
||||
endif()
|
||||
if(FLATBUFFERS_STATIC_FLATC AND NOT MSVC)
|
||||
target_link_libraries(flatc PRIVATE -static)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(FLATBUFFERS_BUILD_FLATHASH)
|
||||
@@ -289,57 +348,148 @@ if(FLATBUFFERS_BUILD_SHAREDLIB)
|
||||
# - 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}.11.0")
|
||||
set(FlatBuffers_Library_SONAME_FULL "${FlatBuffers_Library_SONAME_MAJOR}.12.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)
|
||||
# Global list of generated files.
|
||||
# Use the global property to be independent of PARENT_SCOPE.
|
||||
set_property(GLOBAL PROPERTY FBS_GENERATED_OUTPUTS)
|
||||
|
||||
function(get_generated_output generated_files)
|
||||
get_property(tmp GLOBAL PROPERTY FBS_GENERATED_OUTPUTS)
|
||||
set(${generated_files} ${tmp} PARENT_SCOPE)
|
||||
endfunction(get_generated_output)
|
||||
|
||||
function(register_generated_output file_name)
|
||||
get_property(tmp GLOBAL PROPERTY FBS_GENERATED_OUTPUTS)
|
||||
list(APPEND tmp ${file_name})
|
||||
set_property(GLOBAL PROPERTY FBS_GENERATED_OUTPUTS ${tmp})
|
||||
endfunction(register_generated_output)
|
||||
|
||||
function(compile_flatbuffers_schema_to_cpp_opt SRC_FBS OPT)
|
||||
if(FLATBUFFERS_BUILD_LEGACY)
|
||||
set(OPT ${OPT};--cpp-std c++0x)
|
||||
else()
|
||||
# --cpp-std is defined by flatc default settings.
|
||||
endif()
|
||||
message(STATUS "`${SRC_FBS}`: add generation of C++ code with '${OPT}'")
|
||||
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
|
||||
string(REGEX REPLACE "\\.fbs$" "_generated.h" GEN_HEADER ${SRC_FBS})
|
||||
add_custom_command(
|
||||
OUTPUT ${GEN_HEADER}
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable
|
||||
--gen-object-api --gen-compare -o "${SRC_FBS_DIR}"
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}"
|
||||
--cpp --gen-mutable --gen-object-api --reflect-names
|
||||
--cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs
|
||||
--reflect-names
|
||||
${OPT}
|
||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||
-o "${SRC_FBS_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
DEPENDS flatc)
|
||||
DEPENDS flatc
|
||||
COMMENT "Run generation: '${GEN_HEADER}'")
|
||||
register_generated_output(${GEN_HEADER})
|
||||
endfunction()
|
||||
|
||||
function(compile_flatbuffers_schema_to_cpp SRC_FBS)
|
||||
compile_flatbuffers_schema_to_cpp_opt(${SRC_FBS} "--no-includes;--gen-compare")
|
||||
endfunction()
|
||||
|
||||
function(compile_flatbuffers_schema_to_binary SRC_FBS)
|
||||
message(STATUS "`${SRC_FBS}`: add generation of binary (.bfbs) schema")
|
||||
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
|
||||
string(REGEX REPLACE "\\.fbs$" ".bfbs" GEN_BINARY_SCHEMA ${SRC_FBS})
|
||||
# For details about flags see generate_code.bat(sh)
|
||||
add_custom_command(
|
||||
OUTPUT ${GEN_BINARY_SCHEMA}
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -b --schema -o "${SRC_FBS_DIR}"
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}"
|
||||
-b --schema --bfbs-comments --bfbs-builtins
|
||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||
-o "${SRC_FBS_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
DEPENDS flatc)
|
||||
DEPENDS flatc
|
||||
COMMENT "Run generation: '${GEN_BINARY_SCHEMA}'")
|
||||
register_generated_output(${GEN_BINARY_SCHEMA})
|
||||
endfunction()
|
||||
|
||||
function(compile_flatbuffers_schema_to_embedded_binary SRC_FBS OPT)
|
||||
if(FLATBUFFERS_BUILD_LEGACY)
|
||||
set(OPT ${OPT};--cpp-std c++0x)
|
||||
else()
|
||||
# --cpp-std is defined by flatc default settings.
|
||||
endif()
|
||||
message(STATUS "`${SRC_FBS}`: add generation of C++ embedded binary schema code with '${OPT}'")
|
||||
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
|
||||
string(REGEX REPLACE "\\.fbs$" "_bfbs_generated.h" GEN_BFBS_HEADER ${SRC_FBS})
|
||||
# For details about flags see generate_code.bat(sh)
|
||||
add_custom_command(
|
||||
OUTPUT ${GEN_BFBS_HEADER}
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}"
|
||||
--cpp --gen-mutable --gen-object-api --reflect-names
|
||||
--cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs
|
||||
${OPT}
|
||||
--bfbs-comments --bfbs-builtins --bfbs-gen-embed
|
||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||
-o "${SRC_FBS_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
DEPENDS flatc
|
||||
COMMENT "Run generation: '${GEN_BFBS_HEADER}'")
|
||||
register_generated_output(${GEN_BFBS_HEADER})
|
||||
endfunction()
|
||||
|
||||
if(FLATBUFFERS_BUILD_TESTS)
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/samples" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
# TODO Add (monster_test.fbs monsterdata_test.json)->monsterdata_test.mon
|
||||
compile_flatbuffers_schema_to_cpp(tests/monster_test.fbs)
|
||||
compile_flatbuffers_schema_to_binary(tests/monster_test.fbs)
|
||||
compile_flatbuffers_schema_to_cpp(tests/namespace_test/namespace_test1.fbs)
|
||||
compile_flatbuffers_schema_to_cpp(tests/namespace_test/namespace_test2.fbs)
|
||||
compile_flatbuffers_schema_to_cpp(tests/union_vector/union_vector.fbs)
|
||||
compile_flatbuffers_schema_to_cpp_opt(tests/native_type_test.fbs "")
|
||||
compile_flatbuffers_schema_to_cpp_opt(tests/arrays_test.fbs "--scoped-enums;--gen-compare")
|
||||
compile_flatbuffers_schema_to_binary(tests/arrays_test.fbs)
|
||||
compile_flatbuffers_schema_to_embedded_binary(tests/monster_test.fbs "--no-includes;--gen-compare")
|
||||
if(NOT (MSVC AND (MSVC_VERSION LESS 1900)))
|
||||
compile_flatbuffers_schema_to_cpp(tests/monster_extra.fbs) # Test floating-point NAN/INF.
|
||||
endif()
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/tests)
|
||||
add_executable(flattests ${FlatBuffers_Tests_SRCS})
|
||||
add_dependencies(flattests generated_code)
|
||||
set_property(TARGET flattests
|
||||
PROPERTY COMPILE_DEFINITIONS FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
FLATBUFFERS_DEBUG_VERIFICATION_FAILURE=1)
|
||||
if(FLATBUFFERS_CODE_SANITIZE)
|
||||
if(WIN32)
|
||||
target_compile_definitions(flattests PRIVATE FLATBUFFERS_MEMORY_LEAK_TRACKING)
|
||||
message(STATUS "Sanitizer MSVC::_CrtDumpMemoryLeaks added to flattests")
|
||||
else()
|
||||
add_fsanitize_to_target(flattests ${FLATBUFFERS_CODE_SANITIZE})
|
||||
endif()
|
||||
add_fsanitize_to_target(flattests ${FLATBUFFERS_CODE_SANITIZE})
|
||||
endif()
|
||||
|
||||
compile_flatbuffers_schema_to_cpp(samples/monster.fbs)
|
||||
compile_flatbuffers_schema_to_binary(samples/monster.fbs)
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/samples)
|
||||
add_executable(flatsamplebinary ${FlatBuffers_Sample_Binary_SRCS})
|
||||
add_dependencies(flatsamplebinary generated_code)
|
||||
add_executable(flatsampletext ${FlatBuffers_Sample_Text_SRCS})
|
||||
add_dependencies(flatsampletext generated_code)
|
||||
add_executable(flatsamplebfbs ${FlatBuffers_Sample_BFBS_SRCS})
|
||||
add_dependencies(flatsamplebfbs generated_code)
|
||||
|
||||
if(FLATBUFFERS_BUILD_CPP17)
|
||||
# Don't generate header for flattests_cpp17 target.
|
||||
# This target uses "generated_cpp17/monster_test_generated.h"
|
||||
# produced by direct call of generate_code.bat(sh) script.
|
||||
add_executable(flattests_cpp17 ${FlatBuffers_Tests_CPP17_SRCS})
|
||||
add_dependencies(flattests_cpp17 generated_code)
|
||||
target_compile_features(flattests_cpp17 PRIVATE cxx_std_17)
|
||||
target_compile_definitions(flattests_cpp17 PRIVATE
|
||||
FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
FLATBUFFERS_DEBUG_VERIFICATION_FAILURE=1
|
||||
)
|
||||
if(FLATBUFFERS_CODE_SANITIZE)
|
||||
add_fsanitize_to_target(flattests_cpp17 ${FLATBUFFERS_CODE_SANITIZE})
|
||||
endif()
|
||||
endif(FLATBUFFERS_BUILD_CPP17)
|
||||
endif()
|
||||
|
||||
if(FLATBUFFERS_BUILD_GRPCTEST)
|
||||
@@ -356,7 +506,12 @@ if(FLATBUFFERS_BUILD_GRPCTEST)
|
||||
INCLUDE_DIRECTORIES(${PROTOBUF_DOWNLOAD_PATH}/src)
|
||||
LINK_DIRECTORIES(${GRPC_INSTALL_PATH}/lib)
|
||||
add_executable(grpctest ${FlatBuffers_GRPCTest_SRCS})
|
||||
target_link_libraries(grpctest grpc++_unsecure grpc_unsecure gpr pthread dl)
|
||||
add_dependencies(grpctest generated_code)
|
||||
target_link_libraries(grpctest PRIVATE grpc++_unsecure grpc_unsecure gpr pthread dl)
|
||||
if(FLATBUFFERS_CODE_SANITIZE AND NOT WIN32)
|
||||
# GRPC test has problems with alignment and will fail under ASAN/UBSAN.
|
||||
# add_fsanitize_to_target(grpctest ${FLATBUFFERS_CODE_SANITIZE})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(CMake/Version.cmake)
|
||||
@@ -439,14 +594,25 @@ endif()
|
||||
if(FLATBUFFERS_BUILD_TESTS)
|
||||
enable_testing()
|
||||
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests" DESTINATION
|
||||
"${CMAKE_CURRENT_BINARY_DIR}")
|
||||
add_test(NAME flattests COMMAND flattests)
|
||||
if(FLATBUFFERS_BUILD_CPP17)
|
||||
add_test(NAME flattests_cpp17 COMMAND flattests_cpp17)
|
||||
endif()
|
||||
if(FLATBUFFERS_BUILD_GRPCTEST)
|
||||
add_test(NAME grpctest COMMAND grpctest)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# This target is sync-barrier.
|
||||
# Other generate-dependent targets can depend on 'generated_code' only.
|
||||
get_generated_output(fbs_generated)
|
||||
if(fbs_generated)
|
||||
# message(STATUS "Add generated_code target with files:${fbs_generated}")
|
||||
add_custom_target(generated_code
|
||||
DEPENDS ${fbs_generated}
|
||||
COMMENT "All generated files were updated.")
|
||||
endif()
|
||||
|
||||
include(CMake/BuildFlatBuffers.cmake)
|
||||
|
||||
if(UNIX)
|
||||
|
||||
@@ -187,7 +187,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2014 Google Inc.
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
@@ -4,11 +4,14 @@ load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_go",
|
||||
sha256 = "492c3ac68ed9dcf527a07e6a1b2dcbf199c6bf8b35517951467ac32e421c06c1",
|
||||
urls = ["https://github.com/bazelbuild/rules_go/releases/download/0.17.0/rules_go-0.17.0.tar.gz"],
|
||||
urls = [
|
||||
"https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/rules_go/releases/download/v0.20.3/rules_go-v0.20.3.tar.gz",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.20.3/rules_go-v0.20.3.tar.gz",
|
||||
],
|
||||
sha256 = "e88471aea3a3a4f19ec1310a55ba94772d087e9ce46e41ae38ecebe17935de7b",
|
||||
)
|
||||
|
||||
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
|
||||
load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies", "go_register_toolchains")
|
||||
|
||||
go_rules_dependencies()
|
||||
|
||||
|
||||
@@ -36,8 +36,7 @@ LOCAL_MODULE := flatbuffers_extra
|
||||
LOCAL_SRC_FILES := src/idl_parser.cpp \
|
||||
src/idl_gen_text.cpp \
|
||||
src/reflection.cpp \
|
||||
src/util.cpp \
|
||||
src/code_generators.cpp
|
||||
src/util.cpp
|
||||
LOCAL_STATIC_LIBRARIES := flatbuffers
|
||||
LOCAL_ARM_MODE := arm
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
@@ -51,8 +50,10 @@ LOCAL_SRC_FILES := android/jni/main.cpp \
|
||||
tests/test_builder.h \
|
||||
tests/test_assert.cpp \
|
||||
tests/test_builder.cpp \
|
||||
tests/native_type_test_impl.h \
|
||||
tests/native_type_test_impl.cpp \
|
||||
src/idl_gen_fbs.cpp \
|
||||
src/idl_gen_general.cpp
|
||||
src/code_generators.cpp
|
||||
LOCAL_LDLIBS := -llog -landroid -latomic
|
||||
LOCAL_STATIC_LIBRARIES := android_native_app_glue flatbuffers_extra
|
||||
LOCAL_ARM_MODE := arm
|
||||
|
||||
@@ -18,9 +18,6 @@
|
||||
|
||||
extern int main(int argc, char **argv);
|
||||
|
||||
void android_main(android_app *app) {
|
||||
// Make sure glue isn't stripped.
|
||||
app_dummy();
|
||||
|
||||
void android_main(android_app *) {
|
||||
main(0, NULL);
|
||||
}
|
||||
|
||||
36
appveyor.yml
36
appveyor.yml
@@ -2,23 +2,36 @@ branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
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"
|
||||
CMAKE_OPTIONS: ""
|
||||
CPP_TEST_OPTIONS: ""
|
||||
|
||||
matrix:
|
||||
- CMAKE_VS_VERSION: "10 2010"
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_VS_VERSION: "10 2010"
|
||||
CMAKE_OPTIONS: "-DFLATBUFFERS_BUILD_LEGACY=1"
|
||||
CPP_TEST_OPTIONS: "--std-cpp c++0x"
|
||||
MONSTER_EXTRA: "skip"
|
||||
|
||||
- CMAKE_VS_VERSION: "12 2013"
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_VS_VERSION: "12 2013"
|
||||
MONSTER_EXTRA: "skip"
|
||||
|
||||
- CMAKE_VS_VERSION: "14 2015"
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_VS_VERSION: "14 2015"
|
||||
MONSTER_EXTRA: ""
|
||||
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CMAKE_VS_VERSION: "15 2017"
|
||||
MONSTER_EXTRA: ""
|
||||
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
CMAKE_VS_VERSION: "16 2019"
|
||||
MONSTER_EXTRA: ""
|
||||
|
||||
platform:
|
||||
@@ -31,9 +44,11 @@ configuration:
|
||||
|
||||
before_build:
|
||||
- set MONSTER_EXTRA=%MONSTER_EXTRA%
|
||||
- cmake -G"Visual Studio %CMAKE_VS_VERSION%" -DFLATBUFFERS_CODE_SANITIZE=1 .
|
||||
- cmake . -G"Visual Studio %CMAKE_VS_VERSION%" -DFLATBUFFERS_CODE_SANITIZE=1 %CMAKE_OPTIONS%
|
||||
# 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"
|
||||
- if exist "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets" del "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
||||
- if exist "C:\Program Files (x86)\MSBuild\15.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets" del "C:\Program Files (x86)\MSBuild\15.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
||||
- if exist "C:\Program Files (x86)\MSBuild\16.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets" del "C:\Program Files (x86)\MSBuild\16.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
||||
|
||||
build:
|
||||
project: ALL_BUILD.vcxproj
|
||||
@@ -55,7 +70,7 @@ test_script:
|
||||
- call .appveyor\check-generate-code.bat -b %CONFIGURATION%
|
||||
- "cd tests"
|
||||
- rem "Building all code"
|
||||
- generate_code.bat -b %CONFIGURATION%
|
||||
- generate_code.bat -b %CONFIGURATION% %CPP_TEST_OPTIONS%
|
||||
- 7z a GeneratedMyGameCode.zip MyGame\
|
||||
- rem "---------------- C++ -----------------"
|
||||
- "cd .."
|
||||
@@ -90,6 +105,11 @@ test_script:
|
||||
# Have to compile this here rather than in "build" above because AppVeyor only
|
||||
# supports building one project??
|
||||
- "cd FlatBuffers.Test"
|
||||
- "copy ..\\monsterdata_test.mon Resources\\"
|
||||
- "copy ..\\monsterdata_test.json Resources\\"
|
||||
- "dotnet new sln"
|
||||
- "dotnet sln add FlatBuffers.Test.csproj"
|
||||
- "nuget restore"
|
||||
- "msbuild.exe /property:Configuration=Release;OutputPath=tempcs /verbosity:minimal FlatBuffers.Test.csproj"
|
||||
- "tempcs\\FlatBuffers.Test.exe"
|
||||
# Run tests with UNSAFE_BYTEBUFFER
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
Rules for building C++ flatbuffers with Bazel.
|
||||
"""
|
||||
|
||||
load("@rules_cc//cc:defs.bzl", "cc_library")
|
||||
|
||||
flatc_path = "@com_github_google_flatbuffers//:flatc"
|
||||
|
||||
DEFAULT_INCLUDE_PATHS = [
|
||||
@@ -32,7 +34,9 @@ def flatbuffer_library_public(
|
||||
include_paths = DEFAULT_INCLUDE_PATHS,
|
||||
flatc_args = DEFAULT_FLATC_ARGS,
|
||||
reflection_name = "",
|
||||
reflection_visiblity = None,
|
||||
reflection_visibility = None,
|
||||
compatible_with = None,
|
||||
restricted_to = None,
|
||||
output_to_bindir = False):
|
||||
"""Generates code files for reading/writing the given flatbuffers in the requested language using the public compiler.
|
||||
|
||||
@@ -48,7 +52,12 @@ def flatbuffer_library_public(
|
||||
flatc_args: Optional, list of additional arguments to pass to flatc.
|
||||
reflection_name: Optional, if set this will generate the flatbuffer
|
||||
reflection binaries for the schemas.
|
||||
reflection_visiblity: The visibility of the generated reflection Fileset.
|
||||
reflection_visibility: The visibility of the generated reflection Fileset.
|
||||
output_to_bindir: Passed to genrule for output to bin directory.
|
||||
compatible_with: Optional, The list of environments this rule can be
|
||||
built for, in addition to default-supported environments.
|
||||
restricted_to: Optional, The list of environments this rule can be built
|
||||
for, instead of default-supported environments.
|
||||
output_to_bindir: Passed to genrule for output to bin directory.
|
||||
|
||||
|
||||
@@ -82,6 +91,8 @@ def flatbuffer_library_public(
|
||||
output_to_bindir = output_to_bindir,
|
||||
tools = [flatc_path],
|
||||
cmd = genrule_cmd,
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
message = "Generating flatbuffer files for %s:" % (name),
|
||||
)
|
||||
if reflection_name:
|
||||
@@ -107,16 +118,17 @@ def flatbuffer_library_public(
|
||||
outs = reflection_outs,
|
||||
output_to_bindir = output_to_bindir,
|
||||
tools = [flatc_path],
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
cmd = reflection_genrule_cmd,
|
||||
message = "Generating flatbuffer reflection binary for %s:" % (name),
|
||||
)
|
||||
native.Fileset(
|
||||
name = reflection_name,
|
||||
out = "%s_out" % reflection_name,
|
||||
entries = [
|
||||
native.FilesetEntry(files = reflection_outs),
|
||||
],
|
||||
visibility = reflection_visiblity,
|
||||
native.filegroup(
|
||||
name = "%s_out" % reflection_name,
|
||||
srcs = reflection_outs,
|
||||
visibility = reflection_visibility,
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
)
|
||||
|
||||
def flatbuffer_cc_library(
|
||||
@@ -128,6 +140,8 @@ def flatbuffer_cc_library(
|
||||
include_paths = DEFAULT_INCLUDE_PATHS,
|
||||
flatc_args = DEFAULT_FLATC_ARGS,
|
||||
visibility = None,
|
||||
compatible_with = None,
|
||||
restricted_to = None,
|
||||
srcs_filegroup_visibility = None,
|
||||
gen_reflections = False):
|
||||
'''A cc_library with the generated reader/writers for the given flatbuffer definitions.
|
||||
@@ -151,6 +165,10 @@ def flatbuffer_cc_library(
|
||||
By default, use the value of the visibility parameter above.
|
||||
gen_reflections: Optional, if true this will generate the flatbuffer
|
||||
reflection binaries for the schemas.
|
||||
compatible_with: Optional, The list of environments this rule can be built
|
||||
for, in addition to default-supported environments.
|
||||
restricted_to: Optional, The list of environments this rule can be built
|
||||
for, instead of default-supported environments.
|
||||
|
||||
This produces:
|
||||
filegroup([name]_srcs): all generated .h files.
|
||||
@@ -206,10 +224,12 @@ def flatbuffer_cc_library(
|
||||
includes = includes,
|
||||
include_paths = include_paths,
|
||||
flatc_args = flatc_args,
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
reflection_name = reflection_name,
|
||||
reflection_visiblity = visibility,
|
||||
reflection_visibility = visibility,
|
||||
)
|
||||
native.cc_library(
|
||||
cc_library(
|
||||
name = name,
|
||||
hdrs = [
|
||||
":" + srcs_lib,
|
||||
@@ -224,6 +244,8 @@ def flatbuffer_cc_library(
|
||||
"@com_github_google_flatbuffers//:runtime_cc",
|
||||
],
|
||||
includes = [],
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
linkstatic = 1,
|
||||
visibility = visibility,
|
||||
)
|
||||
@@ -233,5 +255,7 @@ def flatbuffer_cc_library(
|
||||
native.filegroup(
|
||||
name = srcs_filegroup_name if srcs_filegroup_name else "%s_includes" % (name),
|
||||
srcs = srcs,
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
visibility = srcs_filegroup_visibility if srcs_filegroup_visibility != None else visibility,
|
||||
)
|
||||
|
||||
@@ -492,7 +492,7 @@ class Builder {
|
||||
/// Write the given list of 64-bit float [values].
|
||||
int writeListFloat64(List<double> values) {
|
||||
_ensureNoVTable();
|
||||
_prepare(4, 1 + (2 * values.length));
|
||||
_prepare(_sizeofFloat64, values.length, additionalBytes: _sizeofUint32);
|
||||
final int result = _tail;
|
||||
int tail = _tail;
|
||||
_setUint32AtTail(_buf, tail, values.length);
|
||||
@@ -522,7 +522,7 @@ class Builder {
|
||||
/// Write the given list of signed 64-bit integer [values].
|
||||
int writeListInt64(List<int> values) {
|
||||
_ensureNoVTable();
|
||||
_prepare(_sizeofUint32, 2 * values.length);
|
||||
_prepare(_sizeofInt64, values.length, additionalBytes: _sizeofUint32);
|
||||
final int result = _tail;
|
||||
int tail = _tail;
|
||||
_setUint32AtTail(_buf, tail, values.length);
|
||||
@@ -537,7 +537,7 @@ class Builder {
|
||||
/// Write the given list of signed 64-bit integer [values].
|
||||
int writeListUint64(List<int> values) {
|
||||
_ensureNoVTable();
|
||||
_prepare(_sizeofUint32, 2 * values.length);
|
||||
_prepare(_sizeofUint64, values.length, additionalBytes: _sizeofUint32);
|
||||
final int result = _tail;
|
||||
int tail = _tail;
|
||||
_setUint32AtTail(_buf, tail, values.length);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: flat_buffers
|
||||
version: 1.11.0
|
||||
version: 1.12.0
|
||||
description: >
|
||||
FlatBuffers reading and writing library for Dart. Use the flatc compiler to
|
||||
generate Dart classes for a FlatBuffers schema, and this library to assist with
|
||||
|
||||
@@ -11,6 +11,7 @@ import 'include_test2_my_game.example_generated.dart';
|
||||
import './monster_test_my_game_generated.dart' as my_game;
|
||||
import './monster_test_my_game.example2_generated.dart' as my_game_example2;
|
||||
|
||||
/// Composite components of Monster color.
|
||||
class Color {
|
||||
final int value;
|
||||
const Color._(this.value);
|
||||
@@ -26,7 +27,12 @@ class Color {
|
||||
static bool containsValue(int value) => values.containsKey(value);
|
||||
|
||||
static const Color Red = const Color._(1);
|
||||
|
||||
/// \brief color Green
|
||||
/// Green is bit_flag with value (1u << 1)
|
||||
static const Color Green = const Color._(2);
|
||||
|
||||
/// \brief color Blue (1u << 3)
|
||||
static const Color Blue = const Color._(8);
|
||||
static get values => {1: Red,2: Green,8: Blue,};
|
||||
|
||||
@@ -46,7 +52,48 @@ class _ColorReader extends fb.Reader<Color> {
|
||||
|
||||
@override
|
||||
Color read(fb.BufferContext bc, int offset) =>
|
||||
new Color.fromValue(const fb.Int8Reader().read(bc, offset));
|
||||
new Color.fromValue(const fb.Uint8Reader().read(bc, offset));
|
||||
}
|
||||
|
||||
class Race {
|
||||
final int value;
|
||||
const Race._(this.value);
|
||||
|
||||
factory Race.fromValue(int value) {
|
||||
if (value == null) value = 0;
|
||||
if (!values.containsKey(value)) {
|
||||
throw new StateError('Invalid value $value for bit flag enum Race');
|
||||
}
|
||||
return values[value];
|
||||
}
|
||||
|
||||
static const int minValue = -1;
|
||||
static const int maxValue = 2;
|
||||
static bool containsValue(int value) => values.containsKey(value);
|
||||
|
||||
static const Race None = const Race._(-1);
|
||||
static const Race Human = const Race._(0);
|
||||
static const Race Dwarf = const Race._(1);
|
||||
static const Race Elf = const Race._(2);
|
||||
static get values => {-1: None,0: Human,1: Dwarf,2: Elf,};
|
||||
|
||||
static const fb.Reader<Race> reader = const _RaceReader();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Race{value: $value}';
|
||||
}
|
||||
}
|
||||
|
||||
class _RaceReader extends fb.Reader<Race> {
|
||||
const _RaceReader();
|
||||
|
||||
@override
|
||||
int get size => 1;
|
||||
|
||||
@override
|
||||
Race read(fb.BufferContext bc, int offset) =>
|
||||
new Race.fromValue(const fb.Int8Reader().read(bc, offset));
|
||||
}
|
||||
|
||||
class AnyTypeId {
|
||||
@@ -108,9 +155,9 @@ class AnyUniqueAliasesTypeId {
|
||||
|
||||
static const AnyUniqueAliasesTypeId NONE = const AnyUniqueAliasesTypeId._(0);
|
||||
static const AnyUniqueAliasesTypeId M = const AnyUniqueAliasesTypeId._(1);
|
||||
static const AnyUniqueAliasesTypeId T = const AnyUniqueAliasesTypeId._(2);
|
||||
static const AnyUniqueAliasesTypeId TS = const AnyUniqueAliasesTypeId._(2);
|
||||
static const AnyUniqueAliasesTypeId M2 = const AnyUniqueAliasesTypeId._(3);
|
||||
static get values => {0: NONE,1: M,2: T,3: M2,};
|
||||
static get values => {0: NONE,1: M,2: TS,3: M2,};
|
||||
|
||||
static const fb.Reader<AnyUniqueAliasesTypeId> reader = const _AnyUniqueAliasesTypeIdReader();
|
||||
|
||||
@@ -259,7 +306,7 @@ class TestSimpleTableWithEnum {
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
Color get color => new Color.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 4, 2));
|
||||
Color get color => new Color.fromValue(const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 4, 2));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
@@ -287,7 +334,7 @@ class TestSimpleTableWithEnumBuilder {
|
||||
}
|
||||
|
||||
int addColor(Color color) {
|
||||
fbBuilder.addInt8(0, color?.value);
|
||||
fbBuilder.addUint8(0, color?.value);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
@@ -311,7 +358,7 @@ class TestSimpleTableWithEnumObjectBuilder extends fb.ObjectBuilder {
|
||||
assert(fbBuilder != null);
|
||||
|
||||
fbBuilder.startTable();
|
||||
fbBuilder.addInt8(0, _color?.value);
|
||||
fbBuilder.addUint8(0, _color?.value);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
@@ -335,7 +382,7 @@ class Vec3 {
|
||||
double get y => const fb.Float32Reader().read(_bc, _bcOffset + 4);
|
||||
double get z => const fb.Float32Reader().read(_bc, _bcOffset + 8);
|
||||
double get test1 => const fb.Float64Reader().read(_bc, _bcOffset + 16);
|
||||
Color get test2 => new Color.fromValue(const fb.Int8Reader().read(_bc, _bcOffset + 24));
|
||||
Color get test2 => new Color.fromValue(const fb.Uint8Reader().read(_bc, _bcOffset + 24));
|
||||
Test get test3 => Test.reader.read(_bc, _bcOffset + 26);
|
||||
|
||||
@override
|
||||
@@ -366,7 +413,7 @@ class Vec3Builder {
|
||||
fbBuilder.pad(2);
|
||||
test3();
|
||||
fbBuilder.pad(1);
|
||||
fbBuilder.putInt8(test2?.value);
|
||||
fbBuilder.putUint8(test2?.value);
|
||||
fbBuilder.putFloat64(test1);
|
||||
fbBuilder.pad(4);
|
||||
fbBuilder.putFloat32(z);
|
||||
@@ -409,7 +456,7 @@ class Vec3ObjectBuilder extends fb.ObjectBuilder {
|
||||
fbBuilder.pad(2);
|
||||
_test3.finish(fbBuilder);
|
||||
fbBuilder.pad(1);
|
||||
fbBuilder.putInt8(_test2?.value);
|
||||
fbBuilder.putUint8(_test2?.value);
|
||||
fbBuilder.putFloat64(_test1);
|
||||
fbBuilder.pad(4);
|
||||
fbBuilder.putFloat32(_z);
|
||||
@@ -690,7 +737,7 @@ class Monster {
|
||||
int get hp => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 8, 100);
|
||||
String get name => const fb.StringReader().vTableGet(_bc, _bcOffset, 10, null);
|
||||
List<int> get inventory => const fb.ListReader<int>(const fb.Uint8Reader()).vTableGet(_bc, _bcOffset, 14, null);
|
||||
Color get color => new Color.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 16, 8));
|
||||
Color get color => new Color.fromValue(const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 16, 8));
|
||||
AnyTypeId get testType => new AnyTypeId.fromValue(const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 18, 0));
|
||||
dynamic get test {
|
||||
switch (testType?.value) {
|
||||
@@ -702,8 +749,8 @@ class Monster {
|
||||
}
|
||||
List<Test> get test4 => const fb.ListReader<Test>(Test.reader).vTableGet(_bc, _bcOffset, 22, null);
|
||||
List<String> get testarrayofstring => const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bc, _bcOffset, 24, null);
|
||||
/// an example documentation comment: this will end up in the generated code
|
||||
/// multiline too
|
||||
/// an example documentation comment: this will end up in the generated code
|
||||
/// multiline too
|
||||
List<Monster> get testarrayoftables => const fb.ListReader<Monster>(Monster.reader).vTableGet(_bc, _bcOffset, 26, null);
|
||||
Monster get enemy => Monster.reader.vTableGet(_bc, _bcOffset, 28, null);
|
||||
List<int> get testnestedflatbuffer => const fb.ListReader<int>(const fb.Uint8Reader()).vTableGet(_bc, _bcOffset, 30, null);
|
||||
@@ -740,7 +787,7 @@ class Monster {
|
||||
dynamic get anyUnique {
|
||||
switch (anyUniqueType?.value) {
|
||||
case 1: return M.reader.vTableGet(_bc, _bcOffset, 92, null);
|
||||
case 2: return T.reader.vTableGet(_bc, _bcOffset, 92, null);
|
||||
case 2: return TS.reader.vTableGet(_bc, _bcOffset, 92, null);
|
||||
case 3: return M2.reader.vTableGet(_bc, _bcOffset, 92, null);
|
||||
default: return null;
|
||||
}
|
||||
@@ -755,10 +802,11 @@ class Monster {
|
||||
}
|
||||
}
|
||||
List<Color> get vectorOfEnums => const fb.ListReader<Color>(Color.reader).vTableGet(_bc, _bcOffset, 98, null);
|
||||
Race get signedEnum => new Race.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 100, -1));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Monster{pos: $pos, mana: $mana, hp: $hp, name: $name, inventory: $inventory, color: $color, testType: $testType, test: $test, test4: $test4, testarrayofstring: $testarrayofstring, testarrayoftables: $testarrayoftables, enemy: $enemy, testnestedflatbuffer: $testnestedflatbuffer, testempty: $testempty, testbool: $testbool, testhashs32Fnv1: $testhashs32Fnv1, testhashu32Fnv1: $testhashu32Fnv1, testhashs64Fnv1: $testhashs64Fnv1, testhashu64Fnv1: $testhashu64Fnv1, testhashs32Fnv1a: $testhashs32Fnv1a, testhashu32Fnv1a: $testhashu32Fnv1a, testhashs64Fnv1a: $testhashs64Fnv1a, testhashu64Fnv1a: $testhashu64Fnv1a, testarrayofbools: $testarrayofbools, testf: $testf, testf2: $testf2, testf3: $testf3, testarrayofstring2: $testarrayofstring2, testarrayofsortedstruct: $testarrayofsortedstruct, flex: $flex, test5: $test5, vectorOfLongs: $vectorOfLongs, vectorOfDoubles: $vectorOfDoubles, parentNamespaceTest: $parentNamespaceTest, vectorOfReferrables: $vectorOfReferrables, singleWeakReference: $singleWeakReference, vectorOfWeakReferences: $vectorOfWeakReferences, vectorOfStrongReferrables: $vectorOfStrongReferrables, coOwningReference: $coOwningReference, vectorOfCoOwningReferences: $vectorOfCoOwningReferences, nonOwningReference: $nonOwningReference, vectorOfNonOwningReferences: $vectorOfNonOwningReferences, anyUniqueType: $anyUniqueType, anyUnique: $anyUnique, anyAmbiguousType: $anyAmbiguousType, anyAmbiguous: $anyAmbiguous, vectorOfEnums: $vectorOfEnums}';
|
||||
return 'Monster{pos: $pos, mana: $mana, hp: $hp, name: $name, inventory: $inventory, color: $color, testType: $testType, test: $test, test4: $test4, testarrayofstring: $testarrayofstring, testarrayoftables: $testarrayoftables, enemy: $enemy, testnestedflatbuffer: $testnestedflatbuffer, testempty: $testempty, testbool: $testbool, testhashs32Fnv1: $testhashs32Fnv1, testhashu32Fnv1: $testhashu32Fnv1, testhashs64Fnv1: $testhashs64Fnv1, testhashu64Fnv1: $testhashu64Fnv1, testhashs32Fnv1a: $testhashs32Fnv1a, testhashu32Fnv1a: $testhashu32Fnv1a, testhashs64Fnv1a: $testhashs64Fnv1a, testhashu64Fnv1a: $testhashu64Fnv1a, testarrayofbools: $testarrayofbools, testf: $testf, testf2: $testf2, testf3: $testf3, testarrayofstring2: $testarrayofstring2, testarrayofsortedstruct: $testarrayofsortedstruct, flex: $flex, test5: $test5, vectorOfLongs: $vectorOfLongs, vectorOfDoubles: $vectorOfDoubles, parentNamespaceTest: $parentNamespaceTest, vectorOfReferrables: $vectorOfReferrables, singleWeakReference: $singleWeakReference, vectorOfWeakReferences: $vectorOfWeakReferences, vectorOfStrongReferrables: $vectorOfStrongReferrables, coOwningReference: $coOwningReference, vectorOfCoOwningReferences: $vectorOfCoOwningReferences, nonOwningReference: $nonOwningReference, vectorOfNonOwningReferences: $vectorOfNonOwningReferences, anyUniqueType: $anyUniqueType, anyUnique: $anyUnique, anyAmbiguousType: $anyAmbiguousType, anyAmbiguous: $anyAmbiguous, vectorOfEnums: $vectorOfEnums, signedEnum: $signedEnum}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -802,7 +850,7 @@ class MonsterBuilder {
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addColor(Color color) {
|
||||
fbBuilder.addInt8(6, color?.value);
|
||||
fbBuilder.addUint8(6, color?.value);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addTestType(AnyTypeId testType) {
|
||||
@@ -969,6 +1017,10 @@ class MonsterBuilder {
|
||||
fbBuilder.addOffset(47, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addSignedEnum(Race signedEnum) {
|
||||
fbBuilder.addInt8(48, signedEnum?.value);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
int finish() {
|
||||
return fbBuilder.endTable();
|
||||
@@ -1023,6 +1075,7 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
final AnyAmbiguousAliasesTypeId _anyAmbiguousType;
|
||||
final dynamic _anyAmbiguous;
|
||||
final List<Color> _vectorOfEnums;
|
||||
final Race _signedEnum;
|
||||
|
||||
MonsterObjectBuilder({
|
||||
Vec3ObjectBuilder pos,
|
||||
@@ -1072,6 +1125,7 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
AnyAmbiguousAliasesTypeId anyAmbiguousType,
|
||||
dynamic anyAmbiguous,
|
||||
List<Color> vectorOfEnums,
|
||||
Race signedEnum,
|
||||
})
|
||||
: _pos = pos,
|
||||
_mana = mana,
|
||||
@@ -1119,7 +1173,8 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
_anyUnique = anyUnique,
|
||||
_anyAmbiguousType = anyAmbiguousType,
|
||||
_anyAmbiguous = anyAmbiguous,
|
||||
_vectorOfEnums = vectorOfEnums;
|
||||
_vectorOfEnums = vectorOfEnums,
|
||||
_signedEnum = signedEnum;
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
@@ -1185,7 +1240,7 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
final int anyUniqueOffset = _anyUnique?.getOrCreateOffset(fbBuilder);
|
||||
final int anyAmbiguousOffset = _anyAmbiguous?.getOrCreateOffset(fbBuilder);
|
||||
final int vectorOfEnumsOffset = _vectorOfEnums?.isNotEmpty == true
|
||||
? fbBuilder.writeListInt8(_vectorOfEnums.map((f) => f.value))
|
||||
? fbBuilder.writeListUint8(_vectorOfEnums.map((f) => f.value))
|
||||
: null;
|
||||
|
||||
fbBuilder.startTable();
|
||||
@@ -1200,7 +1255,7 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
if (inventoryOffset != null) {
|
||||
fbBuilder.addOffset(5, inventoryOffset);
|
||||
}
|
||||
fbBuilder.addInt8(6, _color?.value);
|
||||
fbBuilder.addUint8(6, _color?.value);
|
||||
fbBuilder.addUint8(7, _testType?.value);
|
||||
if (testOffset != null) {
|
||||
fbBuilder.addOffset(8, testOffset);
|
||||
@@ -1288,6 +1343,7 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
if (vectorOfEnumsOffset != null) {
|
||||
fbBuilder.addOffset(47, vectorOfEnumsOffset);
|
||||
}
|
||||
fbBuilder.addInt8(48, _signedEnum?.value);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,19 @@ Building should also produce two sample executables, `flatsamplebinary` and
|
||||
*Note that you MUST be in the root of the FlatBuffers distribution when you
|
||||
run 'flattests' or `flatsampletext`, or it will fail to load its files.*
|
||||
|
||||
## Building with VCPKG
|
||||
|
||||
You can download and install flatbuffers using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:
|
||||
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
./vcpkg install flatbuffers
|
||||
|
||||
The flatbuffers port in vcpkg is kept up to date by Microsoft team members and community contributors.
|
||||
If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||
|
||||
## Building for Android
|
||||
|
||||
There is a `flatbuffers/android` directory that contains all you need to build
|
||||
|
||||
@@ -3,7 +3,7 @@ Using the schema compiler {#flatbuffers_guide_using_schema_compiler}
|
||||
|
||||
Usage:
|
||||
|
||||
flatc [ GENERATOR OPTIONS ] [ -o PATH ] [ -I PATH ] [ -S ] FILES...
|
||||
flatc [ GENERATOR OPTIONS ] [ -o PATH ] [ -I PATH ] FILES...
|
||||
[ -- FILES...]
|
||||
|
||||
The files are read and parsed in order, and can contain either schemas
|
||||
@@ -23,6 +23,8 @@ For any schema input files, one or more generators can be specified:
|
||||
|
||||
- `--java`, `-j` : Generate Java code.
|
||||
|
||||
- `--kotlin`, `-k` : Generate Kotlin code.
|
||||
|
||||
- `--csharp`, `-n` : Generate C# code.
|
||||
|
||||
- `--go`, `-g` : Generate Go code.
|
||||
@@ -45,6 +47,8 @@ For any schema input files, one or more generators can be specified:
|
||||
|
||||
- `--rust`, `-r` : Generate Rust code.
|
||||
|
||||
- `--swift`: Generate Swift code.
|
||||
|
||||
For any data input files:
|
||||
|
||||
- `--binary`, `-b` : If data is contained in this file, generate a
|
||||
@@ -92,7 +96,7 @@ Additional options:
|
||||
statements) use `--no-includes.`
|
||||
|
||||
- `--no-includes` : Don't generate include statements for included schemas the
|
||||
generated file depends on (C++).
|
||||
generated file depends on (C++ / Python).
|
||||
|
||||
- `--gen-mutable` : Generate additional non-const accessors for mutating
|
||||
FlatBuffers in-place.
|
||||
@@ -117,6 +121,8 @@ Additional options:
|
||||
output (by default the case for C++ and JS), all code will end up in
|
||||
this one file.
|
||||
|
||||
- `--cpp-include` : Adds an #include in generated file
|
||||
|
||||
- `--cpp-ptr-type T` : Set object API pointer type (default std::unique_ptr)
|
||||
|
||||
- `--cpp-str-type T` : Set object API string type (default std::string)
|
||||
@@ -128,6 +134,11 @@ Additional options:
|
||||
std::string from Flatbuffers, but (char* + length). This allows efficient
|
||||
construction of custom string types, including zero-copy construction.
|
||||
|
||||
- `--cpp-std CPP_STD` : Generate a C++ code using features of selected C++ standard.
|
||||
Supported `CPP_STD` values:
|
||||
* `c++0x` - generate code compatible with old compilers (VS2010).
|
||||
* `c++11` - use C++11 code generator (default);
|
||||
|
||||
- `--object-prefix` : Customise class prefix for C++ object-based API.
|
||||
|
||||
- `--object-suffix` : Customise class suffix for C++ object-based API.
|
||||
@@ -177,6 +188,13 @@ Additional options:
|
||||
- `--conform-includes PATH` : Include path for the schema given with
|
||||
`--conform PATH`.
|
||||
|
||||
- `--filename-suffix SUFFIX` : The suffix appended to the generated
|
||||
file names. Default is '_generated'.
|
||||
|
||||
- `--filename-ext EXTENSION` : The extension appended to the generated
|
||||
file names. Default is language-specific (e.g. "h" for C++). This
|
||||
should not be used when multiple languages are specified.
|
||||
|
||||
- `--include-prefix PATH` : Prefix this path to any generated include
|
||||
statements.
|
||||
|
||||
@@ -199,5 +217,8 @@ Additional options:
|
||||
- `--force-empty` : When serializing from object API representation, force
|
||||
strings and vectors to empty rather than null.
|
||||
|
||||
- `--force-empty-vectors` : When serializing from object API representation, force
|
||||
vectors to empty rather than null.
|
||||
|
||||
NOTE: short-form options for generators are deprecated, use the long form
|
||||
whenever possible.
|
||||
|
||||
@@ -35,7 +35,7 @@ The test code itself is located in
|
||||
[test.cpp](https://github.com/google/flatbuffers/blob/master/tests/test.cpp).
|
||||
|
||||
This test file is built alongside `flatc`. To review how to build the project,
|
||||
please read the [Building](@ref flatbuffers_guide_building) documenation.
|
||||
please read the [Building](@ref flatbuffers_guide_building) documentation.
|
||||
|
||||
To run the tests, execute `flattests` from the root `flatbuffers/` directory.
|
||||
For example, on [Linux](https://en.wikipedia.org/wiki/Linux), you would simply
|
||||
@@ -114,7 +114,7 @@ To use:
|
||||
MonsterT monsterobj;
|
||||
|
||||
// Deserialize from buffer into object.
|
||||
UnPackTo(&monsterobj, flatbuffer);
|
||||
GetMonster(flatbuffer)->UnPackTo(&monsterobj);
|
||||
|
||||
// Update object directly like a C++ class instance.
|
||||
cout << monsterobj->name; // This is now a std::string!
|
||||
@@ -122,7 +122,7 @@ To use:
|
||||
|
||||
// Serialize into new flatbuffer.
|
||||
FlatBufferBuilder fbb;
|
||||
Pack(fbb, &monsterobj);
|
||||
fbb.Finish(Monster::Pack(fbb, &monsterobj));
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following attributes are specific to the object-based API code generation:
|
||||
@@ -426,6 +426,8 @@ it, this will provide you an easy way to use that data directly.
|
||||
(see the schema documentation for some specifics on the JSON format
|
||||
accepted).
|
||||
|
||||
Schema evolution compatibility for the JSON format follows the same rules as the binary format (JSON formatted data will be forwards/backwards compatible with schemas that evolve in a compatible way).
|
||||
|
||||
There are two ways to use text formats:
|
||||
|
||||
#### Using the compiler as a conversion tool
|
||||
@@ -477,7 +479,7 @@ include paths. If not specified, any include statements try to resolve from
|
||||
the current directory.
|
||||
|
||||
If there were any parsing errors, `Parse` will return `false`, and
|
||||
`Parser::err` contains a human readable error string with a line number
|
||||
`Parser::error_` contains a human readable error string with a line number
|
||||
etc, which you should present to the creator of that file.
|
||||
|
||||
After each JSON file, the `Parser::fbb` member variable is the
|
||||
@@ -546,21 +548,63 @@ locale-independent or locale-narrow functions `strtof_l`, `strtod_l`,
|
||||
These functions use specified locale rather than the global or per-thread
|
||||
locale instead. They are part of POSIX-2008 but not part of the C/C++
|
||||
standard library, therefore, may be missing on some platforms.
|
||||
|
||||
The Flatbuffers library try to detect these functions at configuration and
|
||||
compile time:
|
||||
- `_MSC_VER >= 1900`: check MSVC2012 or higher for MSVC buid
|
||||
- `_XOPEN_SOURCE>=700`: check POSIX-2008 for GCC/Clang build
|
||||
- `check_cxx_symbol_exists(strtof_l stdlib.h)`: CMake check of `strtod_f`
|
||||
- CMake `"CMakeLists.txt"`:
|
||||
- Check existence of `strtol_l` and `strtod_l` in the `<stdlib.h>`.
|
||||
- Compile-time `"/include/base.h"`:
|
||||
- `_MSC_VER >= 1900`: MSVC2012 or higher if build with MSVC.
|
||||
- `_XOPEN_SOURCE>=700`: POSIX-2008 if build with GCC/Clang.
|
||||
|
||||
After detection, the definition `FLATBUFFERS_LOCALE_INDEPENDENT` will be
|
||||
set to `0` or `1`.
|
||||
To override or stop this detection use CMake `-DFLATBUFFERS_LOCALE_INDEPENDENT={0|1}`
|
||||
or predefine `FLATBUFFERS_LOCALE_INDEPENDENT` symbol.
|
||||
|
||||
It is possible to test the compatibility of the Flatbuffers library with
|
||||
a specific locale using the environment variable `FLATBUFFERS_TEST_LOCALE`:
|
||||
To test the compatibility of the Flatbuffers library with
|
||||
a specific locale use the environment variable `FLATBUFFERS_TEST_LOCALE`:
|
||||
```sh
|
||||
>FLATBUFFERS_TEST_LOCALE="" ./flattests
|
||||
>FLATBUFFERS_TEST_LOCALE="ru_RU.CP1251" ./flattests
|
||||
```
|
||||
|
||||
## Support of floating-point numbers
|
||||
The Flatbuffers library assumes that a C++ compiler and a CPU are
|
||||
compatible with the `IEEE-754` floating-point standard.
|
||||
The schema and json parser may fail if `fast-math` or `/fp:fast` mode is active.
|
||||
|
||||
### Support of hexadecimal and special floating-point numbers
|
||||
According to the [grammar](@ref flatbuffers_grammar) `fbs` and `json` files
|
||||
may use hexadecimal and special (`NaN`, `Inf`) floating-point literals.
|
||||
The Flatbuffers uses `strtof` and `strtod` functions to parse floating-point
|
||||
literals. The Flatbuffers library has a code to detect a compiler compatibility
|
||||
with the literals. If necessary conditions are met the preprocessor constant
|
||||
`FLATBUFFERS_HAS_NEW_STRTOD` will be set to `1`.
|
||||
The support of floating-point literals will be limited at compile time
|
||||
if `FLATBUFFERS_HAS_NEW_STRTOD` constant is less than `1`.
|
||||
In this case, schemas with hexadecimal or special literals cannot be used.
|
||||
|
||||
### Comparison of floating-point NaN values
|
||||
The floating-point `NaN` (`not a number`) is special value which
|
||||
representing an undefined or unrepresentable value.
|
||||
`NaN` may be explicitly assigned to variables, typically as a representation
|
||||
for missing values or may be a result of a mathematical operation.
|
||||
The `IEEE-754` defines two kind of `NaNs`:
|
||||
- Quiet NaNs, or `qNaNs`.
|
||||
- Signaling NaNs, or `sNaNs`.
|
||||
|
||||
According to the `IEEE-754`, a comparison with `NaN` always returns
|
||||
an unordered result even when compared with itself. As a result, a whole
|
||||
Flatbuffers object will be not equal to itself if has one or more `NaN`.
|
||||
Flatbuffers scalar fields that have the default value are not actually stored
|
||||
in the serialized data but are generated in code (see [Writing a schema](@ref flatbuffers_guide_writing_schema)).
|
||||
Scalar fields with `NaN` defaults break this behavior.
|
||||
If a schema has a lot of `NaN` defaults the Flatbuffers can override
|
||||
the unordered comparison by the ordered: `(NaN==NaN)->true`.
|
||||
This ordered comparison is enabled when compiling a program with the symbol
|
||||
`FLATBUFFERS_NAN_DEFAULTS` defined.
|
||||
Additional computations added by `FLATBUFFERS_NAN_DEFAULTS` are very cheap
|
||||
if GCC or Clang used. These compilers have a compile-time implementation
|
||||
of `isnan` checking which MSVC does not.
|
||||
|
||||
<br>
|
||||
|
||||
175
docs/source/CsharpUsage.md
Normal file
175
docs/source/CsharpUsage.md
Normal file
@@ -0,0 +1,175 @@
|
||||
Use in C# {#flatbuffers_guide_use_c-sharp}
|
||||
==============
|
||||
|
||||
## Before you get started
|
||||
|
||||
Before diving into the FlatBuffers usage in C#, it should be noted that
|
||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to
|
||||
general FlatBuffers usage in all of the supported languages (including C#).
|
||||
This page is designed to cover the nuances of FlatBuffers usage,
|
||||
specific to C#.
|
||||
|
||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
||||
documentation to build `flatc` and should be familiar with
|
||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
||||
|
||||
## FlatBuffers C-sharp code location
|
||||
|
||||
The code for the FlatBuffers C# library can be found at
|
||||
`flatbuffers/net/FlatBuffers`. You can browse the library on the
|
||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/net/
|
||||
FlatBuffers).
|
||||
|
||||
## Testing the FlatBuffers C-sharp libraries
|
||||
|
||||
The code to test the libraries can be found at `flatbuffers/tests`.
|
||||
|
||||
The test code for C# is located in the [FlatBuffers.Test](https://github.com/
|
||||
google/flatbuffers/tree/master/tests/FlatBuffers.Test) subfolder. To run the
|
||||
tests, open `FlatBuffers.Test.csproj` in [Visual Studio](
|
||||
https://www.visualstudio.com), and compile/run the project.
|
||||
|
||||
Optionally, you can run this using [Mono](http://www.mono-project.com/) instead.
|
||||
Once you have installed `Mono`, you can run the tests from the command line
|
||||
by running the following commands from inside the `FlatBuffers.Test` folder:
|
||||
|
||||
~~~{.sh}
|
||||
mcs *.cs ../MyGame/Example/*.cs ../../net/FlatBuffers/*.cs
|
||||
mono Assert.exe
|
||||
~~~
|
||||
|
||||
## Using the FlatBuffers C# library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers in C#.*
|
||||
|
||||
FlatBuffers supports reading and writing binary FlatBuffers in C#.
|
||||
|
||||
To use FlatBuffers in your own code, first generate C# classes from your
|
||||
schema with the `--csharp` option to `flatc`.
|
||||
Then you can include both FlatBuffers and the generated code to read
|
||||
or write a FlatBuffer.
|
||||
|
||||
For example, here is how you would read a FlatBuffer binary file in C#:
|
||||
First, import the library and generated code. Then, you read a FlatBuffer binary
|
||||
file into a `byte[]`. You then turn the `byte[]` into a `ByteBuffer`, which you
|
||||
pass to the `GetRootAsMyRootType` function:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
using MyGame.Example;
|
||||
using FlatBuffers;
|
||||
|
||||
// This snippet ignores exceptions for brevity.
|
||||
byte[] data = File.ReadAllBytes("monsterdata_test.mon");
|
||||
|
||||
ByteBuffer bb = new ByteBuffer(data);
|
||||
Monster monster = Monster.GetRootAsMonster(bb);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Now you can access the data from the `Monster monster`:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
short hp = monster.Hp;
|
||||
Vec3 pos = monster.Pos;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
C# code naming follows standard C# style with `PascalCasing` identifiers,
|
||||
e.g. `GetRootAsMyRootType`. Also, values (except vectors and unions) are
|
||||
available as properties instead of parameterless accessor methods.
|
||||
The performance-enhancing methods to which you can pass an already created
|
||||
object are prefixed with `Get`, e.g.:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
// property
|
||||
var pos = monster.Pos;
|
||||
|
||||
// method filling a preconstructed object
|
||||
var preconstructedPos = new Vec3();
|
||||
monster.GetPos(preconstructedPos);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
## Storing dictionaries in a FlatBuffer
|
||||
|
||||
FlatBuffers doesn't support dictionaries natively, but there is support to
|
||||
emulate their behavior with vectors and binary search, which means you
|
||||
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 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.
|
||||
- Write out tables of this type as usual, collect their offsets in an
|
||||
array.
|
||||
- Instead of calling standard generated method,
|
||||
e.g.: `Monster.createTestarrayoftablesVector`,
|
||||
call `CreateSortedVectorOfMonster` in C#
|
||||
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
|
||||
the `ByKey` accessor to access elements of the vector, e.g.:
|
||||
`monster.TestarrayoftablesByKey("Frodo")` in C#,
|
||||
which returns an object of the corresponding table type,
|
||||
or `null` if not found.
|
||||
`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
|
||||
|
||||
There currently is no support for parsing text (Schema's and JSON) directly
|
||||
from C#, though you could use the C++ parser through native call
|
||||
interfaces available to each language. Please see the
|
||||
C++ documentation for more on text parsing.
|
||||
|
||||
## 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
|
||||
(requiring pre-order construction of all data, and making mutation harder).
|
||||
|
||||
For times when efficiency is less important a more convenient object based API
|
||||
can be used (through `--gen-object-api`) that is able to unpack & pack a
|
||||
FlatBuffer into objects and standard System.Collections.Generic containers, allowing for convenient
|
||||
construction, access and mutation.
|
||||
|
||||
To use:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
// Deserialize from buffer into object.
|
||||
MonsterT monsterobj = GetMonster(flatbuffer).UnPack();
|
||||
|
||||
// Update object directly like a C# class instance.
|
||||
Console.WriteLine(monsterobj.Name);
|
||||
monsterobj.Name = "Bob"; // Change the name.
|
||||
|
||||
// Serialize into new flatbuffer.
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(1);
|
||||
fbb.Finish(Monster.Pack(fbb, monsterobj).Value);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
### Json Serialization
|
||||
|
||||
An additional feature of the object API is the ability to allow you to
|
||||
serialize & deserialize a JSON text.
|
||||
To use Json Serialization, add `--gen-json-serializer` option to `flatc` and
|
||||
add `Newtonsoft.Json` nuget package to csproj.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
// Deserialize MonsterT from json
|
||||
string jsonText = File.ReadAllText(@"Resources/monsterdata_test.json");
|
||||
MonsterT mon = MonsterT.DeserializeFromJson(jsonText);
|
||||
|
||||
// Serialize MonsterT to json
|
||||
string jsonText2 = mon.SerializeToJson();
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Limitation
|
||||
* `hash` attribute currentry not supported.
|
||||
* NuGet package Dependency
|
||||
* [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json)
|
||||
|
||||
<br>
|
||||
@@ -4,7 +4,7 @@ FlatBuffers {#flatbuffers_index}
|
||||
# Overview {#flatbuffers_overview}
|
||||
|
||||
[FlatBuffers](@ref flatbuffers_overview) is an efficient cross platform
|
||||
serialization library for C++, C#, C, Go, Java, JavaScript, Lobster, Lua, TypeScript, PHP, Python, and Rust.
|
||||
serialization library for C++, C#, C, Go, Java, Kotlin, JavaScript, Lobster, Lua, TypeScript, PHP, Python, Rust and Swift.
|
||||
It was originally created at Google for game development and other
|
||||
performance-critical applications.
|
||||
|
||||
@@ -51,7 +51,7 @@ under the Apache license, v2 (see LICENSE.txt).
|
||||
needed (faster and more memory efficient than other JSON
|
||||
parsers).
|
||||
|
||||
Java and Go code supports object-reuse. C# has efficient struct based
|
||||
Java, Kotlin and Go code supports object-reuse. C# has efficient struct based
|
||||
accessors.
|
||||
|
||||
- **Cross platform code with no dependencies** - C++ code will work
|
||||
@@ -108,7 +108,7 @@ sections provide a more in-depth usage guide.
|
||||
present for every object instance.
|
||||
|
||||
- Use `flatc` (the FlatBuffer compiler) to generate a C++ header (or
|
||||
Java/C#/Go/Python.. classes) with helper classes to access and construct
|
||||
Java/Kotlin/C#/Go/Python.. classes) with helper classes to access and construct
|
||||
serialized data. This header (say `mydata_generated.h`) only depends on
|
||||
`flatbuffers.h`, which defines the core functionality.
|
||||
|
||||
@@ -130,8 +130,12 @@ sections provide a more in-depth usage guide.
|
||||
- How to [write a schema](@ref flatbuffers_guide_writing_schema).
|
||||
- How to [use the generated C++ code](@ref flatbuffers_guide_use_cpp) in your
|
||||
own programs.
|
||||
- How to [use the generated Java/C# code](@ref flatbuffers_guide_use_java_c-sharp)
|
||||
- How to [use the generated Java code](@ref flatbuffers_guide_use_java)
|
||||
in your own programs.
|
||||
- How to [use the generated C# code](@ref flatbuffers_guide_use_c-sharp)
|
||||
in your own programs.
|
||||
- How to [use the generated Kotlin code](@ref flatbuffers_guide_use_kotlin)
|
||||
in your own programs.
|
||||
- How to [use the generated Go code](@ref flatbuffers_guide_use_go) in your
|
||||
own programs.
|
||||
- How to [use the generated Lua code](@ref flatbuffers_guide_use_lua) in your
|
||||
@@ -146,6 +150,8 @@ sections provide a more in-depth usage guide.
|
||||
own programs.
|
||||
- How to [use the generated Rust code](@ref flatbuffers_guide_use_rust) in your
|
||||
own programs.
|
||||
- How to [use the generated Swift code](@ref flatbuffers_guide_use_swift) in your
|
||||
own programs.
|
||||
- [Support matrix](@ref flatbuffers_support) for platforms/languages/features.
|
||||
- Some [benchmarks](@ref flatbuffers_benchmarks) showing the advantage of
|
||||
using FlatBuffers.
|
||||
@@ -161,6 +167,7 @@ sections provide a more in-depth usage guide.
|
||||
- [GitHub repository](http://github.com/google/flatbuffers)
|
||||
- [Landing page](http://google.github.io/flatbuffers)
|
||||
- [FlatBuffers Google Group](https://groups.google.com/forum/#!forum/flatbuffers)
|
||||
- [Discord](https://discord.gg/6qgKs3R) and [Gitter](https://gitter.im/lobster_programming_language/community) chat.
|
||||
- [FlatBuffers Issues Tracker](http://github.com/google/flatbuffers/issues)
|
||||
- Independent implementations & tools:
|
||||
- [FlatCC](https://github.com/dvidelabs/flatcc) Alternative FlatBuffers
|
||||
@@ -176,3 +183,6 @@ sections provide a more in-depth usage guide.
|
||||
- [FlatBuffers in Android](http://frogermcs.github.io/flatbuffers-in-android-introdution/)
|
||||
- [Parsing JSON to FlatBuffers in Java](http://frogermcs.github.io/json-parsing-with-flatbuffers-in-android/)
|
||||
- [FlatBuffers in Unity](http://exiin.com/blog/flatbuffers-for-unity-sample-code/)
|
||||
- [FlexBuffers C#](https://github.com/mzaks/FlexBuffers-CSharp) and
|
||||
[article](https://medium.com/@icex33/flexbuffers-for-unity3d-4d1ab5c53fbe?)
|
||||
on its use.
|
||||
|
||||
@@ -29,9 +29,7 @@ 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.
|
||||
# Usage in C++
|
||||
|
||||
Include the header `flexbuffers.h`, which in turn depends on `flatbuffers.h`
|
||||
and `util.h`.
|
||||
@@ -98,10 +96,10 @@ 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.
|
||||
64 bit ints) that occur more than once can be shared (see ReuseValue).
|
||||
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:
|
||||
|
||||
@@ -122,6 +120,46 @@ map["unknown"].IsNull(); // true
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
# Usage in Java
|
||||
|
||||
Java implementation follows the C++ one, closely.
|
||||
|
||||
For creating the equivalent of the same JSON `{ vec: [ -100, "Fred", 4.0 ], foo: 100 }`,
|
||||
one could use the following code:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
|
||||
FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(512),
|
||||
FlexBuffersBuilder.BUILDER_FLAG_SHARE_KEYS_AND_STRINGS);
|
||||
int smap = builder.startMap();
|
||||
int svec = builder.startVector();
|
||||
builder.putInt(-100);
|
||||
builder.putString("Fred");
|
||||
builder.putFloat(4.0);
|
||||
builder.endVector("vec", svec, false, false);
|
||||
builder.putInt("foo", 100);
|
||||
builder.endMap(null, smap);
|
||||
ByteBuffer bb = builder.finish();
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Similarly, to read the data, just:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
|
||||
FlexBuffers.Map map = FlexBuffers.getRoot(bb).asMap();
|
||||
map.size(); // 2
|
||||
FlexBuffers.Vector vec = map.get("vec").asVector();
|
||||
vec.size(); // 3
|
||||
vec.get(0).asLong(); // -100;
|
||||
vec.get(1).asString(); // "Fred";
|
||||
vec.get(1).asLong(); // 0 (Number parsing failed).
|
||||
vec.get(2).asFloat(); // 4.0
|
||||
vec.get(2).asString().isEmpty(); // true (Wrong Type).
|
||||
vec.get(2).asString(); // "" (This still works though).
|
||||
vec.get(2).toString(); // "4.0" (Or have it converted).
|
||||
map.get("foo").asUInt(); // 100
|
||||
map.get("unknown").isNull(); // true
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
# Binary encoding
|
||||
|
||||
A description of how FlexBuffers are encoded is in the
|
||||
|
||||
@@ -15,6 +15,12 @@ all commonly used CPUs today. FlatBuffers will also work on big-endian
|
||||
machines, but will be slightly slower because of additional
|
||||
byte-swap intrinsics.
|
||||
|
||||
It is assumed that the following conditions are met, to ensure
|
||||
cross-platform interoperability:
|
||||
- The binary `IEEE-754` format is used for floating-point numbers.
|
||||
- The `two's complemented` representation is used for signed integers.
|
||||
- The endianness is the same for floating-point numbers as for integers.
|
||||
|
||||
On purpose, the format leaves a lot of details about where exactly
|
||||
things live in memory undefined, e.g. fields in a table can have any
|
||||
order, and objects to some extent can be stored in many orders. This is
|
||||
|
||||
@@ -1,41 +1,30 @@
|
||||
Use in Java/C# {#flatbuffers_guide_use_java_c-sharp}
|
||||
Use in Java {#flatbuffers_guide_use_java}
|
||||
==============
|
||||
|
||||
## Before you get started
|
||||
|
||||
Before diving into the FlatBuffers usage in Java or C#, it should be noted that
|
||||
Before diving into the FlatBuffers usage in Java, it should be noted that
|
||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to
|
||||
general FlatBuffers usage in all of the supported languages (including both Java
|
||||
and C#). This page is designed to cover the nuances of FlatBuffers usage,
|
||||
specific to Java and C#.
|
||||
general FlatBuffers usage in all of the supported languages (including Java).
|
||||
This page is designed to cover the nuances of FlatBuffers usage,
|
||||
specific to Java.
|
||||
|
||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
||||
documentation to build `flatc` and should be familiar with
|
||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
||||
|
||||
## FlatBuffers Java and C-sharp code location
|
||||
|
||||
#### Java
|
||||
## FlatBuffers Java code location
|
||||
|
||||
The code for the FlatBuffers Java library can be found at
|
||||
`flatbuffers/java/com/google/flatbuffers`. You can browse the library on the
|
||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/
|
||||
java/com/google/flatbuffers).
|
||||
|
||||
#### C-sharp
|
||||
|
||||
The code for the FlatBuffers C# library can be found at
|
||||
`flatbuffers/net/FlatBuffers`. You can browse the library on the
|
||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/net/
|
||||
FlatBuffers).
|
||||
|
||||
## Testing the FlatBuffers Java and C-sharp libraries
|
||||
## Testing the FlatBuffers Java libraries
|
||||
|
||||
The code to test the libraries can be found at `flatbuffers/tests`.
|
||||
|
||||
#### Java
|
||||
|
||||
The test code for Java is located in [JavaTest.java](https://github.com/google
|
||||
/flatbuffers/blob/master/tests/JavaTest.java).
|
||||
|
||||
@@ -47,31 +36,15 @@ system.
|
||||
*Note: These scripts require that [Java](https://www.oracle.com/java/index.html)
|
||||
is installed.*
|
||||
|
||||
#### C-sharp
|
||||
|
||||
The test code for C# is located in the [FlatBuffers.Test](https://github.com/
|
||||
google/flatbuffers/tree/master/tests/FlatBuffers.Test) subfolder. To run the
|
||||
tests, open `FlatBuffers.Test.csproj` in [Visual Studio](
|
||||
https://www.visualstudio.com), and compile/run the project.
|
||||
|
||||
Optionally, you can run this using [Mono](http://www.mono-project.com/) instead.
|
||||
Once you have installed `Mono`, you can run the tests from the command line
|
||||
by running the following commands from inside the `FlatBuffers.Test` folder:
|
||||
|
||||
~~~{.sh}
|
||||
mcs *.cs ../MyGame/Example/*.cs ../../net/FlatBuffers/*.cs
|
||||
mono Assert.exe
|
||||
~~~
|
||||
|
||||
## Using the FlatBuffers Java (and C#) library
|
||||
## Using the FlatBuffers Java library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers in Java or C#.*
|
||||
example of how to use FlatBuffers in Java.*
|
||||
|
||||
FlatBuffers supports reading and writing binary FlatBuffers in Java and C#.
|
||||
FlatBuffers supports reading and writing binary FlatBuffers in Java.
|
||||
|
||||
To use FlatBuffers in your own code, first generate Java classes from your
|
||||
schema with the `--java` option to `flatc`. (Or for C# with `--csharp`).
|
||||
schema with the `--java` option to `flatc`.
|
||||
Then you can include both FlatBuffers and the generated code to read
|
||||
or write a FlatBuffer.
|
||||
|
||||
@@ -80,11 +53,6 @@ First, import the library and generated code. Then, you read a FlatBuffer binary
|
||||
file into a `byte[]`. You then turn the `byte[]` into a `ByteBuffer`, which you
|
||||
pass to the `getRootAsMyRootType` function:
|
||||
|
||||
*Note: The code here is written from the perspective of Java. Code for both
|
||||
languages is both generated and used in nearly the exact same way, with only
|
||||
minor differences. These differences are
|
||||
[explained in a section below](#differences_in_c-sharp).*
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
|
||||
import MyGame.Example.*;
|
||||
import com.google.flatbuffers.FlatBufferBuilder;
|
||||
@@ -107,30 +75,6 @@ Now you can access the data from the `Monster monster`:
|
||||
Vec3 pos = monster.pos();
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
<a name="differences_in_c-sharp">
|
||||
#### Differences in C-sharp
|
||||
</a>
|
||||
|
||||
C# code works almost identically to Java, with only a few minor differences.
|
||||
You can see an example of C# code in
|
||||
`tests/FlatBuffers.Test/FlatBuffersExampleTests.cs` or
|
||||
`samples/SampleBinary.cs`.
|
||||
|
||||
First of all, naming follows standard C# style with `PascalCasing` identifiers,
|
||||
e.g. `GetRootAsMyRootType`. Also, values (except vectors and unions) are
|
||||
available as properties instead of parameterless accessor methods as in Java.
|
||||
The performance-enhancing methods to which you can pass an already created
|
||||
object are prefixed with `Get`, e.g.:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
// property
|
||||
var pos = monster.Pos;
|
||||
|
||||
// method filling a preconstructed object
|
||||
var preconstructedPos = new Vec3();
|
||||
monster.GetPos(preconstructedPos);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
## Storing dictionaries in a FlatBuffer
|
||||
|
||||
FlatBuffers doesn't support dictionaries natively, but there is support to
|
||||
@@ -147,14 +91,12 @@ To use it:
|
||||
array.
|
||||
- Instead of calling standard generated method,
|
||||
e.g.: `Monster.createTestarrayoftablesVector`,
|
||||
call `CreateSortedVectorOfMonster` in C# or
|
||||
`createSortedVectorOfTables` (from the `FlatBufferBuilder` object) in Java,
|
||||
call `createSortedVectorOfTables` (from the `FlatBufferBuilder` object).
|
||||
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
|
||||
the `ByKey` accessor to access elements of the vector, e.g.:
|
||||
`monster.testarrayoftablesByKey("Frodo")` in Java or
|
||||
`monster.TestarrayoftablesByKey("Frodo")` in C#,
|
||||
`monster.testarrayoftablesByKey("Frodo")`.
|
||||
which returns an object of the corresponding table type,
|
||||
or `null` if not found.
|
||||
`ByKey` performs a binary search, so should have a similar
|
||||
@@ -165,7 +107,7 @@ To use it:
|
||||
## Text parsing
|
||||
|
||||
There currently is no support for parsing text (Schema's and JSON) directly
|
||||
from Java or C#, though you could use the C++ parser through native call
|
||||
from Java, though you could use the C++ parser through native call
|
||||
interfaces available to each language. Please see the
|
||||
C++ documentation for more on text parsing.
|
||||
|
||||
84
docs/source/KotlinUsage.md
Normal file
84
docs/source/KotlinUsage.md
Normal file
@@ -0,0 +1,84 @@
|
||||
Use in Kotlin {#flatbuffers_guide_use_kotlin}
|
||||
==============
|
||||
|
||||
## Before you get started
|
||||
|
||||
Before diving into the FlatBuffers usage in Kotlin, it should be noted that
|
||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to
|
||||
general FlatBuffers usage in all of the supported languages (including K).
|
||||
|
||||
This page is designed to cover the nuances of FlatBuffers usage, specific to Kotlin.
|
||||
|
||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
||||
documentation to build `flatc` and should be familiar with
|
||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
||||
|
||||
## Kotlin and FlatBuffers Java code location
|
||||
|
||||
Code generated for Kotlin currently uses the flatbuffers java runtime library. That means that Kotlin generated code can only have Java virtual machine as target architecture (which includes Android). Kotlin Native and Kotlin.js are currently not supported.
|
||||
|
||||
The code for the FlatBuffers Java library can be found at
|
||||
`flatbuffers/java/com/google/flatbuffers`. You can browse the library on the
|
||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/
|
||||
java/com/google/flatbuffers).
|
||||
|
||||
## Testing FlatBuffers Kotlin
|
||||
|
||||
The test code for Java is located in [KotlinTest.java](https://github.com/google
|
||||
/flatbuffers/blob/master/tests/KotlinTest.kt).
|
||||
|
||||
To run the tests, use [KotlinTest.sh](https://github.com/google/
|
||||
flatbuffers/blob/master/tests/KotlinTest.sh) shell script.
|
||||
|
||||
*Note: These scripts require that [Kotlin](https://kotlinlang.org/) is installed.*
|
||||
|
||||
## Using the FlatBuffers Kotlin library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers in Kotlin.*
|
||||
|
||||
FlatBuffers supports reading and writing binary FlatBuffers in Kotlin.
|
||||
|
||||
To use FlatBuffers in your own code, first generate Java classes from your
|
||||
schema with the `--kotlin` option to `flatc`.
|
||||
Then you can include both FlatBuffers and the generated code to read
|
||||
or write a FlatBuffer.
|
||||
|
||||
For example, here is how you would read a FlatBuffer binary file in Kotlin:
|
||||
First, import the library and generated code. Then, you read a FlatBuffer binary
|
||||
file into a `ByteArray`. You then turn the `ByteArray` into a `ByteBuffer`, which you
|
||||
pass to the `getRootAsMyRootType` function:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.kt}
|
||||
import MyGame.Example.*
|
||||
import com.google.flatbuffers.FlatBufferBuilder
|
||||
|
||||
// This snippet ignores exceptions for brevity.
|
||||
val data = RandomAccessFile(File("monsterdata_test.mon"), "r").use {
|
||||
val temp = ByteArray(it.length().toInt())
|
||||
it.readFully(temp)
|
||||
temp
|
||||
}
|
||||
|
||||
val bb = ByteBuffer.wrap(data)
|
||||
val monster = Monster.getRootAsMonster(bb)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Now you can access the data from the `Monster monster`:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.kt}
|
||||
val hp = monster.hp
|
||||
val pos = monster.pos!!;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
|
||||
## Differences between Kotlin and Java code
|
||||
|
||||
Kotlin generated code was designed to be as close as possible to the java counterpart, as for now, we only support kotlin on java virtual machine. So the differences in implementation and usage are basically the ones introduced by the Kotlin language itself. You can find more in-depth information [here](https://kotlinlang.org/docs/reference/comparison-to-java.html).
|
||||
|
||||
The most obvious ones are:
|
||||
|
||||
* Fields as accessed as Kotlin [properties](https://kotlinlang.org/docs/reference/properties.html)
|
||||
* Static methods are accessed in [companion object](https://kotlinlang.org/docs/reference/classes.html#companion-objects)
|
||||
@@ -114,6 +114,27 @@ of same-size data where a `reinterpret_cast` would give you a desirable result,
|
||||
e.g. you could change a `uint` to an `int` if no values in current data use the
|
||||
high bit yet.
|
||||
|
||||
### Arrays
|
||||
|
||||
Arrays are a convenience short-hand for a fixed-length collection of elements.
|
||||
Arrays can be used to replace the following schema:
|
||||
|
||||
struct Vec3 {
|
||||
x:float;
|
||||
y:float;
|
||||
z:float;
|
||||
}
|
||||
|
||||
with the following schema:
|
||||
|
||||
struct Vec3 {
|
||||
v:[float:3];
|
||||
}
|
||||
|
||||
Both representations are binary equivalent.
|
||||
|
||||
Arrays are currently only supported in a `struct`.
|
||||
|
||||
### (Default) Values
|
||||
|
||||
Values are a sequence of digits. Values may be optionally followed by a decimal
|
||||
@@ -324,6 +345,9 @@ Current understood attributes:
|
||||
Note: currently not guaranteed to have an effect when used with
|
||||
`--object-api`, since that may allocate objects at alignments less than
|
||||
what you specify with `force_align`.
|
||||
- `force_align: size` (on a vector): force the alignment of this vector to be
|
||||
something different than what the element size would normally dictate.
|
||||
Note: Now only work for generated C++ code.
|
||||
- `bit_flags` (on an unsigned enum): the values of this field indicate bits,
|
||||
meaning that any unsigned value N specified in the schema will end up
|
||||
representing 1<<N, or if you don't specify values at all, you'll get
|
||||
@@ -418,14 +442,19 @@ numerical literals:
|
||||
For example: `[0x123, +0x45, -0x67]` are equal to `[291, 69, -103]` decimals.
|
||||
- The format of float-point numbers is fully compatible with C/C++ format.
|
||||
If a modern C++ compiler is used the parser accepts hexadecimal and special
|
||||
float-point literals as well:
|
||||
floating-point literals as well:
|
||||
`[-1.0, 2., .3e0, 3.e4, 0x21.34p-5, -inf, nan]`.
|
||||
The exponent suffix of hexadecimal float-point number is mandatory.
|
||||
|
||||
Extended float-point support was tested with:
|
||||
The following conventions for floating-point numbers are used:
|
||||
- The exponent suffix of hexadecimal floating-point number is mandatory.
|
||||
- Parsed `NaN` converted to unsigned IEEE-754 `quiet-NaN` value.
|
||||
|
||||
Extended floating-point support was tested with:
|
||||
- x64 Windows: `MSVC2015` and higher.
|
||||
- x64 Linux: `LLVM 6.0`, `GCC 4.9` and higher.
|
||||
|
||||
For details, see [Use in C++](@ref flatbuffers_guide_use_cpp) section.
|
||||
|
||||
- For compatibility with a JSON lint tool all numeric literals of scalar
|
||||
fields can be wrapped to quoted string:
|
||||
`"1", "2.0", "0x48A", "0x0C.0Ep-1", "-inf", "true"`.
|
||||
@@ -537,7 +566,7 @@ with the new schema now cannot read nor write `a` anymore (any existing code
|
||||
that tries to do so will result in compile errors), but can still read
|
||||
old data (they will ignore the field).
|
||||
|
||||
table { c:int a:int; b:int; }
|
||||
table { c:int; a:int; b:int; }
|
||||
|
||||
This is NOT ok, as this makes the schemas incompatible. Old code reading newer
|
||||
data will interpret `c` as if it was `a`, and new code reading old data
|
||||
|
||||
@@ -18,23 +18,23 @@ In general:
|
||||
|
||||
NOTE: this table is a start, it needs to be extended.
|
||||
|
||||
Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Dart | Lobster | Rust
|
||||
------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ------- | ------- | ----
|
||||
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | Yes | Yes | Yes
|
||||
JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No | Yes | No
|
||||
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No | No
|
||||
Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No | No
|
||||
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No | No
|
||||
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | Yes | Yes | Yes
|
||||
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | No | No | Yes
|
||||
Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ? | Great | Superb
|
||||
Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | Yes | Yes | Yes
|
||||
Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes
|
||||
Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes
|
||||
Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ?
|
||||
Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ?
|
||||
Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ? | No | ?
|
||||
Primary authors (github) | aard* | aard* | ev*/js*| rw | rw | evanw/ev* | kr* | mik* | ch* | dnfield | aard* | rw
|
||||
Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Dart | Lobster | Rust | Swift
|
||||
------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ------- | ------- | ------- | ------
|
||||
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | Yes | Yes | Yes | Yes
|
||||
JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No | Yes | No | No
|
||||
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No | No | No
|
||||
Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No | No | No
|
||||
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No | No | No
|
||||
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | Yes | Yes | Yes | Yes
|
||||
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | No | No | Yes | No
|
||||
Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ? | Great | Superb | ?
|
||||
Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | Yes | Yes | Yes | No
|
||||
Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes | Yes
|
||||
Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes | Yes
|
||||
Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ? | No
|
||||
Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ? | Yes
|
||||
Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ? | No | ? | No
|
||||
Primary authors (github) | aard* | aard* | ev*/js*| rw | rw | evanw/ev* | kr* | mik* | ch* | dnfield | aard* | rw | mi*/mz*
|
||||
|
||||
* aard = aardappel (previously: gwvo)
|
||||
* ev = evolutional
|
||||
@@ -42,5 +42,7 @@ Primary authors (github) | aard* | aard* | ev*/js*| rw | rw | ev
|
||||
* mik = mikkelfj
|
||||
* ch = chobie
|
||||
* kr = krojew
|
||||
* mi = mustiikhalil
|
||||
* mz = mzaks
|
||||
|
||||
<br>
|
||||
|
||||
91
docs/source/SwiftUsage.md
Normal file
91
docs/source/SwiftUsage.md
Normal file
@@ -0,0 +1,91 @@
|
||||
Use in Swift {#flatbuffers_guide_use_swift}
|
||||
=========
|
||||
|
||||
## Before you get started
|
||||
|
||||
Before diving into the FlatBuffers usage in Swift, it should be noted that
|
||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide
|
||||
to general FlatBuffers usage in all of the supported languages (including Swift).
|
||||
This page is designed to cover the nuances of FlatBuffers usage, specific to
|
||||
Swift.
|
||||
|
||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
||||
documentation to build `flatc` and should be familiar with
|
||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
||||
|
||||
## FlatBuffers Swift library code location
|
||||
|
||||
The code for the FlatBuffers Swift library can be found at
|
||||
`flatbuffers/swift`. You can browse the library code on the [FlatBuffers
|
||||
GitHub page](https://github.com/google/flatbuffers/tree/master/swift).
|
||||
|
||||
## Testing the FlatBuffers Swift library
|
||||
|
||||
The code to test the Swift library can be found at `flatbuffers/Flatbuffers.Test.Swift`.
|
||||
The test code itself is located in [Flatbuffers.Test.Swift](https://github.com/google/flatbuffers/blob/master/tests/FlatBuffers.Test.Swift).
|
||||
|
||||
To run the tests, use the [SwiftTest.sh](https://github.com/google/flatbuffers/blob/master/tests/FlatBuffers.Test.Swift/SwiftTest.sh) shell script.
|
||||
|
||||
*Note: The shell script requires [Swift](https://swift.org) to
|
||||
be installed.*
|
||||
|
||||
## Using the FlatBuffers Swift library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers in Swift.*
|
||||
|
||||
FlatBuffers supports reading and writing binary FlatBuffers in Swift.
|
||||
|
||||
To use FlatBuffers in your own code, first generate Swift structs from your
|
||||
schema with the `--swift` option to `flatc`. Then include FlatBuffers using `SPM` in
|
||||
by adding the path to `FlatBuffers/swift` into it. The generated code should also be
|
||||
added to xcode or the path of the package you will be using. Note: sometimes xcode cant
|
||||
and wont see the generated files, so it's better that you copy them to xcode.
|
||||
|
||||
For example, here is how you would read a FlatBuffer binary file in Swift: First,
|
||||
include the library and copy thegenerated code. Then read a FlatBuffer binary file or
|
||||
a data object from the server, which you can pass into the `GetRootAsMonster` function.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift}
|
||||
import FlatBuffers
|
||||
|
||||
typealias Monster1 = MyGame.Sample.Monster
|
||||
typealias Vec3 = MyGame.Sample.Vec3
|
||||
|
||||
let path = FileManager.default.currentDirectoryPath
|
||||
let url = URL(fileURLWithPath: path, isDirectory: true).appendingPathComponent("monsterdata_test").appendingPathExtension("mon")
|
||||
guard let data = try? Data(contentsOf: url) else { return }
|
||||
|
||||
let monster = Monster.getRootAsMonster(bb: ByteBuffer(data: data))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Now you can access values like this:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift}
|
||||
let hp = monster.hp
|
||||
let pos = monster.pos
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
In some cases it's necessary to modify values in an existing FlatBuffer in place (without creating a copy). For this reason, scalar fields of a Flatbuffer table or struct can be mutated.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift}
|
||||
let monster = Monster.getRootAsMonster(bb: ByteBuffer(data: data))
|
||||
|
||||
if !monster.mutate(hp: 10) {
|
||||
fatalError("couldn't mutate")
|
||||
}
|
||||
// mutate a struct field
|
||||
let vec = monster.pos.mutate(z: 4)
|
||||
|
||||
// This mutation will fail because the mana field is not available in
|
||||
// the buffer. It should be set when creating the buffer.
|
||||
if !monster.mutate(mana: 20) {
|
||||
fatalError("couldn't mutate")
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The term `mutate` is used instead of `set` to indicate that this is a special use case. All mutate functions return a boolean value which is false if the field we're trying to mutate is not available in the buffer.
|
||||
|
||||
<br>
|
||||
@@ -23,6 +23,7 @@ Please select your desired language for our quest:
|
||||
<form>
|
||||
<input type="radio" name="language" value="cpp" checked="checked">C++</input>
|
||||
<input type="radio" name="language" value="java">Java</input>
|
||||
<input type="radio" name="language" value="kotlin">Kotlin</input>
|
||||
<input type="radio" name="language" value="csharp">C#</input>
|
||||
<input type="radio" name="language" value="go">Go</input>
|
||||
<input type="radio" name="language" value="python">Python</input>
|
||||
@@ -34,6 +35,7 @@ Please select your desired language for our quest:
|
||||
<input type="radio" name="language" value="lua">Lua</input>
|
||||
<input type="radio" name="language" value="lobster">Lobster</input>
|
||||
<input type="radio" name="language" value="rust">Rust</input>
|
||||
<input type="radio" name="language" value="swift">Swift</input>
|
||||
</form>
|
||||
\endhtmlonly
|
||||
|
||||
@@ -115,6 +117,9 @@ For your chosen language, please cross-reference with:
|
||||
<div class="language-java">
|
||||
[SampleBinary.java](https://github.com/google/flatbuffers/blob/master/samples/SampleBinary.java)
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
[SampleBinary.kt](https://github.com/google/flatbuffers/blob/master/samples/SampleBinary.kt)
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
[SampleBinary.cs](https://github.com/google/flatbuffers/blob/master/samples/SampleBinary.cs)
|
||||
</div>
|
||||
@@ -148,6 +153,9 @@ For your chosen language, please cross-reference with:
|
||||
<div class="language-rust">
|
||||
[sample_binary.rs](https://github.com/google/flatbuffers/blob/master/samples/sample_binary.rs)
|
||||
</div>
|
||||
<div class="language-swift">
|
||||
[sample_binary.swift](https://github.com/google/flatbuffers/blob/master/samples/sample_binary.swift)
|
||||
</div>
|
||||
|
||||
|
||||
## Writing the Monsters' FlatBuffer Schema
|
||||
@@ -284,6 +292,12 @@ Please be aware of the difference between `flatc` and `flatcc` tools.
|
||||
./../flatc --java monster.fbs
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.sh}
|
||||
cd flatbuffers/samples
|
||||
./../flatc --kotlin monster.fbs
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.sh}
|
||||
cd flatbuffers/samples
|
||||
@@ -353,6 +367,12 @@ Please be aware of the difference between `flatc` and `flatcc` tools.
|
||||
./../flatc --rust monster.fbs
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-swift">
|
||||
~~~{.sh}
|
||||
cd flatbuffers/samples
|
||||
./../flatc --swift monster.fbs
|
||||
~~~
|
||||
</div>
|
||||
|
||||
For a more complete guide to using the `flatc` compiler, please read the
|
||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler)
|
||||
@@ -382,6 +402,13 @@ The first step is to import/include the library, generated files, etc.
|
||||
import com.google.flatbuffers.FlatBufferBuilder;
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kotlin}
|
||||
import MyGame.Sample.* //The `flatc` generated files. (Monster, Vec3, etc.)
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
using FlatBuffers;
|
||||
@@ -424,7 +451,7 @@ The first step is to import/include the library, generated files, etc.
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-typescript">
|
||||
// note: import flabuffers with your desired import method
|
||||
// note: import flatbuffers with your desired import method
|
||||
|
||||
import { MyGame } from './monster_generated';
|
||||
</div>
|
||||
@@ -485,8 +512,8 @@ The first step is to import/include the library, generated files, etc.
|
||||
</div>
|
||||
<div class="language-lobster">
|
||||
~~~{.lobster}
|
||||
include from "../lobster/" // Where to find flatbuffers.lobster
|
||||
include "monster_generated.lobster"
|
||||
import from "../lobster/" // Where to find flatbuffers.lobster
|
||||
import monster_generated
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-rust">
|
||||
@@ -506,6 +533,21 @@ The first step is to import/include the library, generated files, etc.
|
||||
~~~
|
||||
</div>
|
||||
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
/**
|
||||
// make sure that monster_generated.swift is included in your project
|
||||
*/
|
||||
import Flatbuffers
|
||||
|
||||
// typealiases for convenience
|
||||
typealias Monster = MyGame1.Sample.Monster
|
||||
typealias Weapon = MyGame1.Sample.Weapon
|
||||
typealias Color = MyGame1.Sample.Color
|
||||
typealias Vec3 = MyGame1.Sample.Vec3
|
||||
~~~
|
||||
</div>
|
||||
|
||||
Now we are ready to start building some buffers. In order to start, we need
|
||||
to create an instance of the `FlatBufferBuilder`, which will contain the buffer
|
||||
as it grows. You can pass an initial size of the buffer (here 1024 bytes),
|
||||
@@ -525,6 +567,13 @@ which will grow automatically if needed:
|
||||
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kt}
|
||||
// Create a `FlatBufferBuilder`, which will be used to create our
|
||||
// monsters' FlatBuffers.
|
||||
val builder = FlatBufferBuilder(1024)
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
// Create a `FlatBufferBuilder`, which will be used to create our
|
||||
@@ -592,7 +641,7 @@ which will grow automatically if needed:
|
||||
</div>
|
||||
<div class="language-lobster">
|
||||
~~~{.lobster}
|
||||
-- get access to the builder
|
||||
// get access to the builder
|
||||
let builder = flatbuffers_builder {}
|
||||
~~~
|
||||
</div>
|
||||
@@ -603,6 +652,12 @@ which will grow automatically if needed:
|
||||
let mut builder = flatbuffers::FlatBufferBuilder::new_with_capacity(1024);
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
// create a `FlatBufferBuilder`, which will be used to serialize objects
|
||||
let builder = FlatBufferBuilder(initialSize: 1024)
|
||||
~~~
|
||||
</div>
|
||||
|
||||
After creating the `builder`, we can start serializing our data. Before we make
|
||||
our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
|
||||
@@ -633,6 +688,19 @@ our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
|
||||
int axe = Weapon.createWeapon(builder, weaponTwoName, weaponTwoDamage);
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kt}
|
||||
val weaponOneName = builder.createString("Sword")
|
||||
val weaponOneDamage: Short = 3;
|
||||
|
||||
val weaponTwoName = builder.createString("Axe")
|
||||
val weaponTwoDamage: Short = 5;
|
||||
|
||||
// Use the `createWeapon()` helper function to create the weapons, since we set every field.
|
||||
val sword = Weapon.createWeapon(builder, weaponOneName, weaponOneDamage)
|
||||
val axe = Weapon.createWeapon(builder, weaponTwoName, weaponTwoDamage)
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
var weaponOneName = builder.CreateString("Sword");
|
||||
@@ -813,12 +881,13 @@ our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
|
||||
let weapon_names = [ "Sword", "Axe" ]
|
||||
let weapon_damages = [ 3, 5 ]
|
||||
|
||||
weapon_offsets := map(weapon_names) name, i:
|
||||
let weapon_offsets = map(weapon_names) name, i:
|
||||
let ns = builder.CreateString(name)
|
||||
builder.MyGame_Sample_WeaponStart()
|
||||
builder.MyGame_Sample_WeaponAddName(ns)
|
||||
builder.MyGame_Sample_WeaponAddDamage(weapon_damages[i])
|
||||
builder.MyGame_Sample_WeaponEnd()
|
||||
MyGame_Sample_WeaponBuilder { b }
|
||||
.start()
|
||||
.add_name(ns)
|
||||
.add_damage(weapon_damages[i])
|
||||
.end()
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-rust">
|
||||
@@ -840,6 +909,25 @@ our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
|
||||
~~~
|
||||
</div>
|
||||
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
let weapon1Name = builder.create(string: "Sword")
|
||||
let weapon2Name = builder.create(string: "Axe")
|
||||
|
||||
// start creating the weapon by calling startWeapon
|
||||
let weapon1Start = Weapon.startWeapon(builder)
|
||||
Weapon.add(name: weapon1Name, builder)
|
||||
Weapon.add(damage: 3, builder)
|
||||
// end the object by passing the start point for the weapon 1
|
||||
let sword = Weapon.endWeapon(builder, start: weapon1Start)
|
||||
|
||||
let weapon2Start = Weapon.startWeapon(builder)
|
||||
Weapon.add(name: weapon2Name, builder)
|
||||
Weapon.add(damage: 5, builder)
|
||||
let axe = Weapon.endWeapon(builder, start: weapon2Start)
|
||||
~~~
|
||||
</div>
|
||||
|
||||
Now let's create our monster, the `orc`. For this `orc`, lets make him
|
||||
`red` with rage, positioned at `(1.0, 2.0, 3.0)`, and give him
|
||||
a large pool of hit points with `300`. We can give him a vector of weapons
|
||||
@@ -874,6 +962,17 @@ traversal. This is generally easy to do on any tree structures.
|
||||
int inv = Monster.createInventoryVector(builder, treasure);
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kt}
|
||||
// Serialize a name for our monster, called "Orc".
|
||||
val name = builder.createString("Orc")
|
||||
|
||||
// Create a `vector` representing the inventory of the Orc. Each number
|
||||
// could correspond to an item that can be claimed after he is slain.
|
||||
val treasure = byteArrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
|
||||
val inv = Monster.createInventoryVector(builder, treasure)
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
// Serialize a name for our monster, called "Orc".
|
||||
@@ -1019,6 +1118,16 @@ traversal. This is generally easy to do on any tree structures.
|
||||
let inventory = builder.create_vector(&[0u8, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
// Name of the Monster.
|
||||
let name = builder.create(string: "Orc")
|
||||
|
||||
// create inventory
|
||||
let inventory: [Byte] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
let inventoryOffset = builder.createVector(inventory)
|
||||
~~~
|
||||
</div>
|
||||
|
||||
We serialized two built-in data types (`string` and `vector`) and captured
|
||||
their return values. These values are offsets into the serialized data,
|
||||
@@ -1059,6 +1168,16 @@ offsets.
|
||||
int weapons = Monster.createWeaponsVector(builder, weaps);
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kt}
|
||||
// Place the two weapons into an array, and pass it to the `createWeaponsVector()` method to
|
||||
// create a FlatBuffer vector.
|
||||
val weaps = intArrayOf(sword, axe)
|
||||
|
||||
// Pass the `weaps` array into the `createWeaponsVector()` method to create a FlatBuffer vector.
|
||||
val weapons = Monster.createWeaponsVector(builder, weaps)
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
var weaps = new Offset<Weapon>[2];
|
||||
@@ -1153,6 +1272,13 @@ offsets.
|
||||
let weapons = builder.create_vector(&[sword, axe]);
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
// Create a FlatBuffer `vector` that contains offsets to the sword and axe
|
||||
// we created above.
|
||||
let weaponsOffset = builder.createVector(ofOffsets: [sword, axe])
|
||||
~~~
|
||||
</div>
|
||||
|
||||
<br>
|
||||
Note there's additional convenience overloads of `CreateVector`, allowing you
|
||||
@@ -1179,6 +1305,14 @@ for the `path` field above:
|
||||
int path = fbb.endVector();
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kt}
|
||||
Monster.startPathVector(fbb, 2)
|
||||
Vec3.createVec3(builder, 1.0f, 2.0f, 3.0f)
|
||||
Vec3.createVec3(builder, 4.0f, 5.0f, 6.0f)
|
||||
val path = fbb.endVector()
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
Monster.StartPathVector(fbb, 2);
|
||||
@@ -1281,6 +1415,15 @@ for the `path` field above:
|
||||
// let path = builder.create_vector(&[&x, &y]);
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
//
|
||||
let points = builder.createVector(structs: [MyGame.Sample.createVec3(x: 1, y: 2, z: 3),
|
||||
MyGame.Sample.createVec3(x: 4, y: 5, z: 6)],
|
||||
type: Vec3.self)
|
||||
~~~
|
||||
</div>
|
||||
|
||||
|
||||
We have now serialized the non-scalar components of the orc, so we
|
||||
can serialize the monster itself:
|
||||
@@ -1317,6 +1460,22 @@ can serialize the monster itself:
|
||||
int orc = Monster.endMonster(builder);
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kt}
|
||||
// Create our monster using `startMonster()` and `endMonster()`.
|
||||
Monster.startMonster(builder)
|
||||
Monster.addPos(builder, Vec3.createVec3(builder, 1.0f, 2.0f, 3.0f))
|
||||
Monster.addName(builder, name)
|
||||
Monster.addColor(builder, Color.Red)
|
||||
Monster.addHp(builder, 300.toShort())
|
||||
Monster.addInventory(builder, inv)
|
||||
Monster.addWeapons(builder, weapons)
|
||||
Monster.addEquippedType(builder, Equipment.Weapon)
|
||||
Monster.addEquipped(builder, axe)
|
||||
Monster.addPath(builder, path)
|
||||
val orc = Monster.endMonster(builder)
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
// Create our monster using `StartMonster()` and `EndMonster()`.
|
||||
@@ -1503,17 +1662,18 @@ can serialize the monster itself:
|
||||
</div>
|
||||
<div class="language-lobster">
|
||||
~~~{.lobster}
|
||||
builder.MyGame_Sample_MonsterStart()
|
||||
builder.MyGame_Sample_MonsterAddPos(builder.MyGame_Sample_CreateVec3(1.0, 2.0, 3.0))
|
||||
builder.MyGame_Sample_MonsterAddHp(300)
|
||||
builder.MyGame_Sample_MonsterAddName(name)
|
||||
builder.MyGame_Sample_MonsterAddInventory(inv)
|
||||
builder.MyGame_Sample_MonsterAddColor(MyGame_Sample_Color_Red)
|
||||
builder.MyGame_Sample_MonsterAddWeapons(weapons)
|
||||
builder.MyGame_Sample_MonsterAddEquippedType(MyGame_Sample_Equipment_Weapon)
|
||||
builder.MyGame_Sample_MonsterAddEquipped(weapon_offsets[1])
|
||||
builder.MyGame_Sample_MonsterAddPath(path)
|
||||
let orc = builder.MyGame_Sample_MonsterEnd()
|
||||
let orc = MyGame_Sample_MonsterBuilder { b }
|
||||
.start()
|
||||
.add_pos(b.MyGame_Sample_CreateVec3(1.0, 2.0, 3.0))
|
||||
.add_hp(300)
|
||||
.add_name(name)
|
||||
.add_inventory(inv)
|
||||
.add_color(MyGame_Sample_Color_Red)
|
||||
.add_weapons(weapons)
|
||||
.add_equipped_type(MyGame_Sample_Equipment_Weapon)
|
||||
.add_equipped(weapon_offsets[1])
|
||||
.add_path(path)
|
||||
.end()
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-rust">
|
||||
@@ -1537,6 +1697,19 @@ can serialize the monster itself:
|
||||
});
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
let orc = Monster.createMonster(builder,
|
||||
offsetOfPos: pos,
|
||||
hp: 300,
|
||||
offsetOfName: name,
|
||||
vectorOfInventory: inventoryOffset,
|
||||
color: .red,
|
||||
vectorOfWeapons: weaponsOffset,
|
||||
equippedType: .weapon,
|
||||
offsetOfEquipped: axe)
|
||||
~~~
|
||||
</div>
|
||||
|
||||
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
|
||||
@@ -1602,6 +1775,21 @@ a bit more flexibility.
|
||||
~~~
|
||||
</div>
|
||||
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
let start = Monster.startMonster(builder)
|
||||
Monster.add(pos: pos, builder)
|
||||
Monster.add(hp: 300, builder)
|
||||
Monster.add(name: name, builder)
|
||||
Monster.addVectorOf(inventory: inventoryOffset, builder)
|
||||
Monster.add(color: .red, builder)
|
||||
Monster.addVectorOf(weapons: weaponsOffset, builder)
|
||||
Monster.add(equippedType: .weapon, builder)
|
||||
Monster.add(equipped: axe, builder)
|
||||
var orc = Monster.endMonster(builder, start: start)
|
||||
~~~
|
||||
</div>
|
||||
|
||||
Before finishing the serialization, let's take a quick look at FlatBuffer
|
||||
`union Equipped`. There are two parts to each FlatBuffer `union`. The first, is
|
||||
a hidden field `_type`, that is generated to hold the type of `table` referred
|
||||
@@ -1625,6 +1813,12 @@ Here is a repetition these lines, to help highlight them more clearly:
|
||||
Monster.addEquipped(axe); // Union data
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kt}
|
||||
Monster.addEquippedType(builder, Equipment.Weapon) // Union type
|
||||
Monster.addEquipped(axe) // Union data
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
Monster.AddEquippedType(builder, Equipment.Weapon); // Union type
|
||||
@@ -1687,8 +1881,8 @@ Here is a repetition these lines, to help highlight them more clearly:
|
||||
</div>
|
||||
<div class="language-lobster">
|
||||
~~~{.lobster}
|
||||
builder.MyGame_Sample_MonsterAddEquippedType(MyGame_Sample_Equipment_Weapon)
|
||||
builder.MyGame_Sample_MonsterAddEquipped(axe)
|
||||
.add_equipped_type(MyGame_Sample_Equipment_Weapon)
|
||||
.add_equipped(axe)
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-rust">
|
||||
@@ -1699,6 +1893,13 @@ Here is a repetition these lines, to help highlight them more clearly:
|
||||
monster_builder.add_equipped(axe.as_union_value()); // Union data
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
Monster.add(equippedType: .weapon, builder) // Type of union
|
||||
Monster.add(equipped: axe, builder) // Union data
|
||||
~~~
|
||||
</div>
|
||||
|
||||
|
||||
After you have created your buffer, you will have the offset to the root of the
|
||||
data in the `orc` variable, so you can finish the buffer by calling the
|
||||
@@ -1720,6 +1921,12 @@ appropriate `finish` method.
|
||||
builder.finish(orc); // You could also call `Monster.finishMonsterBuffer(builder, orc);`.
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kt}
|
||||
// Call `finish()` to instruct the builder that this monster is complete.
|
||||
builder.finish(orc) // You could also call `Monster.finishMonsterBuffer(builder, orc);`.
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
// Call `Finish()` to instruct the builder that this monster is complete.
|
||||
@@ -1788,6 +1995,12 @@ appropriate `finish` method.
|
||||
builder.finish(orc, None);
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
// Call `finish(offset:)` to instruct the builder that this monster is complete.
|
||||
builder.finish(offset: orc)
|
||||
~~~
|
||||
</div>
|
||||
|
||||
The buffer is now ready to be stored somewhere, sent over the network, be
|
||||
compressed, or whatever you'd like to do with it. You can access the buffer
|
||||
@@ -1812,6 +2025,17 @@ like so:
|
||||
byte[] buf = builder.sizedByteArray();
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kt}
|
||||
// This must be called after `finish()`.
|
||||
val buf = builder.dataBuffer()
|
||||
// The data in this ByteBuffer does NOT start at 0, but at buf.position().
|
||||
// The number of bytes is buf.remaining().
|
||||
|
||||
// Alternatively this copies the above data out of the ByteBuffer for you:
|
||||
val buf = builder.sizedByteArray()
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
// This must be called after `Finish()`.
|
||||
@@ -1905,6 +2129,15 @@ like so:
|
||||
~~~
|
||||
</div>
|
||||
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
// This must be called after `finish()`.
|
||||
// `sizedByteArray` returns the finished buf of type [UInt8].
|
||||
let buf = builder.sizedByteArray
|
||||
// or you can use to get an object of type Data
|
||||
let bufData = ByteBuffer(data: builder.data)
|
||||
~~~
|
||||
</div>
|
||||
|
||||
Now you can write the bytes to a file, send them over the network..
|
||||
**Make sure your file mode (or transfer protocol) is set to BINARY, not text.**
|
||||
@@ -1934,6 +2167,13 @@ before:
|
||||
import com.google.flatbuffers.FlatBufferBuilder;
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kt}
|
||||
import MyGame.Sample.* //The `flatc` generated files. (Monster, Vec3, etc.)
|
||||
|
||||
import com.google.flatbuffers.FlatBufferBuilder
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
using FlatBuffers;
|
||||
@@ -2033,8 +2273,8 @@ import './monster_my_game.sample_generated.dart' as myGame;
|
||||
</div>
|
||||
<div class="language-lobster">
|
||||
~~~{.lobster}
|
||||
include from "../lobster/" // Where to find flatbuffers.lobster
|
||||
include "monster_generated.lobster"
|
||||
import from "../lobster/" // Where to find flatbuffers.lobster
|
||||
import monster_generated
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-rust">
|
||||
@@ -2082,6 +2322,15 @@ won't work**
|
||||
Monster monster = Monster.getRootAsMonster(buf);
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kt}
|
||||
val bytes = /* the data you just read */
|
||||
val buf = java.nio.ByteBuffer.wrap(bytes)
|
||||
|
||||
// Get an accessor to the root object inside the buffer.
|
||||
Monster monster = Monster.getRootAsMonster(buf)
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
byte[] bytes = /* the data you just read */
|
||||
@@ -2189,6 +2438,16 @@ myGame.Monster monster = new myGame.Monster(data);
|
||||
~~~
|
||||
</div>
|
||||
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
// create a ByteBuffer(:) from an [UInt8] or Data()
|
||||
let buf = // Get your data
|
||||
|
||||
// Get an accessor to the root object inside the buffer.
|
||||
let monster = Monster.getRootAsMonster(bb: ByteBuffer(bytes: buf))
|
||||
~~~
|
||||
</div>
|
||||
|
||||
If you look in the generated files from the schema compiler, you will see it generated
|
||||
accessors for all non-`deprecated` fields. For example:
|
||||
|
||||
@@ -2206,6 +2465,13 @@ accessors for all non-`deprecated` fields. For example:
|
||||
String name = monster.name();
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kt}
|
||||
val hp = monster.hp
|
||||
val mana = monster.mana
|
||||
val name = monster.name
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
// For C#, unlike most other languages support by FlatBuffers, most values (except for
|
||||
@@ -2289,6 +2555,14 @@ accessors for all non-`deprecated` fields. For example:
|
||||
~~~
|
||||
</div>
|
||||
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
let hp = monster.hp
|
||||
let mana = monster.mana
|
||||
let name = monster.name // returns an optional string
|
||||
~~~
|
||||
</div>
|
||||
|
||||
These should hold `300`, `150`, and `"Orc"` respectively.
|
||||
|
||||
*Note: The default value `150` wasn't stored in `mana`, but we are still able to retrieve it.*
|
||||
@@ -2311,6 +2585,14 @@ To access sub-objects, in the case of our `pos`, which is a `Vec3`:
|
||||
float z = pos.z();
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kt}
|
||||
val pos = monster.pos!!
|
||||
val x = pos.x
|
||||
val y = pos.y
|
||||
val z = pos.z
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
var pos = monster.Pos.Value;
|
||||
@@ -2406,6 +2688,15 @@ To access sub-objects, in the case of our `pos`, which is a `Vec3`:
|
||||
~~~
|
||||
</div>
|
||||
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
let pos = monster.pos
|
||||
let x = pos.x
|
||||
let y = pos.y
|
||||
let z = pos.z
|
||||
~~~
|
||||
</div>
|
||||
|
||||
`x`, `y`, and `z` will contain `1.0`, `2.0`, and `3.0`, respectively.
|
||||
|
||||
*Note: Had we not set `pos` during serialization, it would be a `NULL`-value.*
|
||||
@@ -2417,7 +2708,7 @@ FlatBuffers `vector`.
|
||||
<div class="language-cpp">
|
||||
~~~{.cpp}
|
||||
auto inv = monster->inventory(); // A pointer to a `flatbuffers::Vector<>`.
|
||||
auto inv_len = inv->Length();
|
||||
auto inv_len = inv->size();
|
||||
auto third_item = inv->Get(2);
|
||||
~~~
|
||||
</div>
|
||||
@@ -2427,6 +2718,12 @@ FlatBuffers `vector`.
|
||||
byte thirdItem = monster.inventory(2);
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kotlin}
|
||||
val invLength = monster.inventoryLength
|
||||
val thirdItem = monster.inventory(2)!!
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
int invLength = monster.InventoryLength;
|
||||
@@ -2500,13 +2797,27 @@ FlatBuffers `vector`.
|
||||
~~~
|
||||
</div>
|
||||
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
// Get a the count of objects in the vector
|
||||
let count = monster.inventoryCount
|
||||
|
||||
// get item at index 4
|
||||
let object = monster.inventory(at: 4)
|
||||
|
||||
// or you can fetch the entire array
|
||||
let inv = monster.inventory
|
||||
// inv[4] should equal object
|
||||
~~~
|
||||
</div>
|
||||
|
||||
For `vector`s of `table`s, you can access the elements like any other vector,
|
||||
except your need to handle the result as a FlatBuffer `table`:
|
||||
|
||||
<div class="language-cpp">
|
||||
~~~{.cpp}
|
||||
auto weapons = monster->weapons(); // A pointer to a `flatbuffers::Vector<>`.
|
||||
auto weapon_len = weapons->Length();
|
||||
auto weapon_len = weapons->size();
|
||||
auto second_weapon_name = weapons->Get(1)->name()->str();
|
||||
auto second_weapon_damage = weapons->Get(1)->damage()
|
||||
~~~
|
||||
@@ -2518,6 +2829,13 @@ except your need to handle the result as a FlatBuffer `table`:
|
||||
short secondWeaponDamage = monster.weapons(1).damage();
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kt}
|
||||
val weaponsLength = monster.weaponsLength
|
||||
val secondWeaponName = monster.weapons(1)!!.name
|
||||
val secondWeaponDamage = monster.weapons(1)!!.damage
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
int weaponsLength = monster.WeaponsLength;
|
||||
@@ -2605,6 +2923,16 @@ except your need to handle the result as a FlatBuffer `table`:
|
||||
let second_weapon_damage = wep2.damage();
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
// Get the count of weapon objects
|
||||
let wepsCount = monster.weaponsCount
|
||||
|
||||
let weapon2 = monster.weapons(at: 1)
|
||||
let weaponName = weapon2.name
|
||||
let weaponDmg = weapon2.damage
|
||||
~~~
|
||||
</div>
|
||||
|
||||
Last, we can access our `Equipped` FlatBuffer `union`. Just like when we created
|
||||
the `union`, we need to get both parts of the `union`: the type and the data.
|
||||
@@ -2638,6 +2966,19 @@ We can access the type to dynamically cast the data as needed (since the
|
||||
}
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kt}
|
||||
val unionType = monster.EquippedType
|
||||
|
||||
if (unionType == Equipment.Weapon) {
|
||||
val weapon = monster.equipped(Weapon()) as Weapon // Requires explicit cast
|
||||
// to `Weapon`.
|
||||
|
||||
val weaponName = weapon.name // "Axe"
|
||||
val weaponDamage = weapon.damage // 5
|
||||
}
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
var unionType = monster.EquippedType;
|
||||
@@ -2779,6 +3120,17 @@ We can access the type to dynamically cast the data as needed (since the
|
||||
~~~
|
||||
</div>
|
||||
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
// Get and check if the monster has an equipped item
|
||||
if monster.equippedType == .weapon {
|
||||
let _weapon = monster.equipped(type: Weapon.self)
|
||||
let name = _weapon.name // should return "Axe"
|
||||
let dmg = _weapon.damage // should return 5
|
||||
}
|
||||
~~~
|
||||
</div>
|
||||
|
||||
## Mutating FlatBuffers
|
||||
|
||||
As you saw above, typically once you have created a FlatBuffer, it is read-only
|
||||
@@ -2814,6 +3166,14 @@ mutators like so:
|
||||
monster.mutateInventory(0, 1); // Set vector element.
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
~~~{.kt}
|
||||
val monster = Monster.getRootAsMonster(buf)
|
||||
monster.mutateHp(10) // Set table field.
|
||||
monster.pos!!.mutateZ(4) // Set struct field.
|
||||
monster.mutateInventory(0, 1) // Set vector element.
|
||||
~~~
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
~~~{.cs}
|
||||
var monster = Monster.GetRootAsMonster(buf);
|
||||
@@ -2874,6 +3234,15 @@ mutators like so:
|
||||
~~~
|
||||
</div>
|
||||
|
||||
<div class="language-swift">
|
||||
~~~{.swift}
|
||||
let monster = Monster.getRootAsMonster(bb: ByteBuffer(bytes: buf))
|
||||
monster.mutate(hp: 10) // mutates a value in a table
|
||||
monster.pos.mutate(z: 4) // mutates a value in a struct
|
||||
monster.mutate(inventory: 6, at index: 0) // mutates a value in an Scalar array
|
||||
~~~
|
||||
</div>
|
||||
|
||||
We use the somewhat verbose term `mutate` instead of `set` to indicate that this
|
||||
is a special use case, not to be confused with the default way of constructing
|
||||
FlatBuffer data.
|
||||
@@ -2897,16 +3266,18 @@ If this is not sufficient, other ways of mutating FlatBuffers may be supported
|
||||
in your language through an object based API (`--gen-object-api`) or reflection.
|
||||
See the individual language documents for support.
|
||||
|
||||
## JSON with FlatBuffers
|
||||
## Using `flatc` as a JSON Conversion Tool
|
||||
|
||||
#### Using `flatc` as a Conversion Tool
|
||||
|
||||
This is often the preferred method to use JSON with FlatBuffers, as it doesn't
|
||||
require you to add any new code to your program. It is also efficient, since you
|
||||
can ship with the binary data. The drawback is that it requires an extra step
|
||||
for your users/developers to perform (although it may be able to be automated
|
||||
If you are working with C, C++, or Lobster, you can parse JSON at runtime.
|
||||
If your language does not support JSON at the moment, `flatc` may provide an
|
||||
alternative. Using `flatc` is often the preferred method, as it doesn't require you to
|
||||
add any new code to your program. It is also efficient, since you can ship with
|
||||
the binary data. The drawback is that it requires an extra step for your
|
||||
users/developers to perform (although it may be able to be automated
|
||||
as part of your compilation).
|
||||
|
||||
#### JSON to binary representation
|
||||
|
||||
Lets say you have a JSON file that describes your monster. In this example,
|
||||
we will use the file `flatbuffers/samples/monsterdata.json`.
|
||||
|
||||
@@ -2915,16 +3286,31 @@ Here are the contents of the file:
|
||||
~~~{.json}
|
||||
{
|
||||
pos: {
|
||||
x: 1,
|
||||
y: 2,
|
||||
z: 3
|
||||
x: 1.0,
|
||||
y: 2.0,
|
||||
z: 3.0
|
||||
},
|
||||
hp: 300,
|
||||
name: "Orc"
|
||||
name: "Orc",
|
||||
weapons: [
|
||||
{
|
||||
name: "axe",
|
||||
damage: 100
|
||||
},
|
||||
{
|
||||
name: "bow",
|
||||
damage: 90
|
||||
}
|
||||
],
|
||||
equipped_type: "Weapon",
|
||||
equipped: {
|
||||
name: "bow",
|
||||
damage: 90
|
||||
}
|
||||
}
|
||||
~~~
|
||||
|
||||
You can run this file through the `flatc` compile with the `-b` flag and
|
||||
You can run this file through the `flatc` compiler with the `-b` flag and
|
||||
our `monster.fbs` schema to produce a FlatBuffer binary file.
|
||||
|
||||
~~~{.sh}
|
||||
@@ -2953,6 +3339,30 @@ for `flatcc` to support this.*
|
||||
Guide for more information.*
|
||||
</div>
|
||||
|
||||
#### FlatBuffer binary to JSON
|
||||
|
||||
Converting from a FlatBuffer binary representation to JSON is supported as well:
|
||||
~~~{.sh}
|
||||
./../flatc --json --raw-binary monster.fbs -- monsterdata.bin
|
||||
~~~
|
||||
This will convert `monsterdata.bin` back to its original JSON representation.
|
||||
You need to pass the corresponding FlatBuffers schema so that flatc knows how to
|
||||
interpret the binary buffer. Since `monster.fbs` does not specify an explicit
|
||||
`file_identifier` for binary buffers, `flatc` needs to be forced into reading
|
||||
the `.bin` file using the `--raw-binary` option.
|
||||
|
||||
The FlatBuffer binary representation does not explicitly encode default values,
|
||||
therefore they are not present in the resulting JSON unless you specify
|
||||
`--defaults-json`.
|
||||
|
||||
If you intend to process the JSON with other tools, you may consider switching
|
||||
on `--strict-json` so that identifiers are quoted properly.
|
||||
|
||||
*Note: The resulting JSON file is not necessarily identical with the original JSON.
|
||||
If the binary representation contains floating point numbers, floats and doubles
|
||||
are rounded to 6 and 12 digits, respectively, in order to represent them as
|
||||
decimals in the JSON document. *
|
||||
|
||||
## Advanced Features for Each Language
|
||||
|
||||
Each language has a dedicated `Use in XXX` page in the Programmer's Guide
|
||||
@@ -2964,10 +3374,13 @@ For your chosen language, see:
|
||||
[Use in C++](@ref flatbuffers_guide_use_cpp)
|
||||
</div>
|
||||
<div class="language-java">
|
||||
[Use in Java/C#](@ref flatbuffers_guide_use_java_c-sharp)
|
||||
[Use in Java](@ref flatbuffers_guide_use_java)
|
||||
</div>
|
||||
<div class="language-kotlin">
|
||||
[Use in Kotlin](@ref flatbuffers_guide_use_kotlin)
|
||||
</div>
|
||||
<div class="language-csharp">
|
||||
[Use in Java/C#](@ref flatbuffers_guide_use_java_c-sharp)
|
||||
[Use in C#](@ref flatbuffers_guide_use_c-sharp)
|
||||
</div>
|
||||
<div class="language-go">
|
||||
[Use in Go](@ref flatbuffers_guide_use_go)
|
||||
@@ -2999,5 +3412,7 @@ For your chosen language, see:
|
||||
<div class="language-rust">
|
||||
[Use in Rust](@ref flatbuffers_guide_use_rust)
|
||||
</div>
|
||||
|
||||
<div class="language-swift">
|
||||
[Use in Swift](@ref flatbuffers_guide_use_swift)
|
||||
</div>
|
||||
<br>
|
||||
|
||||
@@ -43,7 +43,7 @@ First, include the library and generated code. Then read the file into an
|
||||
the ByteBuffer to the `getRootAsMonster` function.
|
||||
|
||||
~~~{.ts}
|
||||
// note: import flabuffers with your desired import method
|
||||
// note: import flatbuffers with your desired import method
|
||||
|
||||
import { MyGame } from './monster_generated';
|
||||
|
||||
|
||||
@@ -778,7 +778,7 @@ INPUT = "FlatBuffers.md" \
|
||||
"../../php/FlatbufferBuilder.php" \
|
||||
"../../net/FlatBuffers/FlatBufferBuilder.cs" \
|
||||
"../../include/flatbuffers/flatbuffers.h" \
|
||||
"../../go/builder.go"
|
||||
"../../go/builder.go" \
|
||||
"../../rust/flatbuffers/src/builder.rs"
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
|
||||
@@ -29,8 +29,10 @@
|
||||
title="Use in C"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_go"
|
||||
title="Use in Go"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_java_c-sharp"
|
||||
title="Use in Java/C#"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_java"
|
||||
title="Use in Java"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_c-sharp"
|
||||
title="Use in C#"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_javascript"
|
||||
title="Use in JavaScript"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_typescript"
|
||||
@@ -48,7 +50,7 @@
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_rust"
|
||||
title="Use in Rust"/>
|
||||
<tab type="user" url="@ref flexbuffers"
|
||||
title="Schema-less version"/>
|
||||
title="FlexBuffers (Schema-less version)"/>
|
||||
<tab type="usergroup" url="" title="gRPC">
|
||||
<tab type="user" url="@ref flatbuffers_grpc_guide_use_cpp"
|
||||
title="Use in C++"/>
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
alias(
|
||||
name = "go_default_library",
|
||||
actual = ":go",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go",
|
||||
srcs = [
|
||||
|
||||
@@ -17,6 +17,8 @@ type Builder struct {
|
||||
head UOffsetT
|
||||
nested bool
|
||||
finished bool
|
||||
|
||||
sharedStrings map[string]UOffsetT
|
||||
}
|
||||
|
||||
const fileIdentifierLength = 4
|
||||
@@ -33,7 +35,6 @@ func NewBuilder(initialSize int) *Builder {
|
||||
b.head = UOffsetT(initialSize)
|
||||
b.minalign = 1
|
||||
b.vtables = make([]UOffsetT, 0, 16) // sensible default capacity
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -307,6 +308,20 @@ func (b *Builder) EndVector(vectorNumElems int) UOffsetT {
|
||||
return b.Offset()
|
||||
}
|
||||
|
||||
// CreateSharedString Checks if the string is already written
|
||||
// to the buffer before calling CreateString
|
||||
func (b *Builder) CreateSharedString(s string) UOffsetT {
|
||||
if b.sharedStrings == nil {
|
||||
b.sharedStrings = make(map[string]UOffsetT)
|
||||
}
|
||||
if v, ok := b.sharedStrings[s]; ok {
|
||||
return v
|
||||
}
|
||||
off := b.CreateString(s)
|
||||
b.sharedStrings[s] = off
|
||||
return off
|
||||
}
|
||||
|
||||
// CreateString writes a null-terminated string as a vector.
|
||||
func (b *Builder) CreateString(s string) UOffsetT {
|
||||
b.assertNotNested()
|
||||
|
||||
15
go/grpc.go
15
go/grpc.go
@@ -3,21 +3,36 @@ package flatbuffers
|
||||
// Codec implements gRPC-go Codec which is used to encode and decode messages.
|
||||
var Codec = "flatbuffers"
|
||||
|
||||
// FlatbuffersCodec defines the interface gRPC uses to encode and decode messages. Note
|
||||
// that implementations of this interface must be thread safe; a Codec's
|
||||
// methods can be called from concurrent goroutines.
|
||||
type FlatbuffersCodec struct{}
|
||||
|
||||
// Marshal returns the wire format of v.
|
||||
func (FlatbuffersCodec) Marshal(v interface{}) ([]byte, error) {
|
||||
return v.(*Builder).FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// Unmarshal parses the wire format into v.
|
||||
func (FlatbuffersCodec) Unmarshal(data []byte, v interface{}) error {
|
||||
v.(flatbuffersInit).Init(data, GetUOffsetT(data))
|
||||
return nil
|
||||
}
|
||||
|
||||
// String old gRPC Codec interface func
|
||||
func (FlatbuffersCodec) String() string {
|
||||
return Codec
|
||||
}
|
||||
|
||||
// Name returns the name of the Codec implementation. The returned string
|
||||
// will be used as part of content type in transmission. The result must be
|
||||
// static; the result cannot change between calls.
|
||||
//
|
||||
// add Name() for ForceCodec interface
|
||||
func (FlatbuffersCodec) Name() string {
|
||||
return Codec
|
||||
}
|
||||
|
||||
type flatbuffersInit interface {
|
||||
Init(data []byte, i UOffsetT)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ grpc_1_15_1_githash=1a60e6971f428323245a930031ad267bb3142ba4
|
||||
function build_grpc () {
|
||||
git clone https://github.com/grpc/grpc.git google/grpc
|
||||
cd google/grpc
|
||||
git checkout ${grpc_1_15_1_githash}
|
||||
git checkout ${grpc_1_15_1_githash}
|
||||
git submodule update --init
|
||||
make
|
||||
make install prefix=`pwd`/install
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.google.flatbuffers</groupId>
|
||||
<artifactId>flatbuffers-parent</artifactId>
|
||||
<version>1.11.0</version>
|
||||
<version>1.12.0</version>
|
||||
</parent>
|
||||
<artifactId>flatbuffers-java-grpc</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
@@ -24,7 +24,7 @@
|
||||
</developer>
|
||||
</developers>
|
||||
<properties>
|
||||
<gRPC.version>1.11.0</gRPC.version>
|
||||
<gRPC.version>1.12.0</gRPC.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<groupId>com.google.flatbuffers</groupId>
|
||||
<artifactId>flatbuffers-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>1.11.0</version>
|
||||
<version>1.12.0</version>
|
||||
<name>flatbuffers-parent</name>
|
||||
<description>parent pom for flatbuffers java artifacts</description>
|
||||
<properties>
|
||||
@@ -185,6 +185,12 @@
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<gpgArguments>
|
||||
<arg>--pinentry-mode</arg>
|
||||
<arg>loopback</arg>
|
||||
</gpgArguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
@@ -12,7 +12,8 @@ class GreeterServiceImpl final : public Greeter::Service {
|
||||
grpc::ServerContext *context,
|
||||
const flatbuffers::grpc::Message<HelloRequest> *request_msg,
|
||||
flatbuffers::grpc::Message<HelloReply> *response_msg) override {
|
||||
// flatbuffers::grpc::MessageBuilder mb_;
|
||||
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();
|
||||
|
||||
107
grpc/src/compiler/BUILD
Normal file
107
grpc/src/compiler/BUILD
Normal file
@@ -0,0 +1,107 @@
|
||||
load("@rules_cc//cc:defs.bzl", "cc_library")
|
||||
|
||||
package(
|
||||
default_visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "common_headers",
|
||||
srcs = [
|
||||
"config.h",
|
||||
"schema_interface.h",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "cpp_generator",
|
||||
srcs = [
|
||||
"cpp_generator.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"cpp_generator.h",
|
||||
":common_headers",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
deps = [
|
||||
"//:flatbuffers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "go_generator",
|
||||
srcs = [
|
||||
"go_generator.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"go_generator.h",
|
||||
":common_headers",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
deps = [
|
||||
"//:flatbuffers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "java_generator",
|
||||
srcs = [
|
||||
"java_generator.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"java_generator.h",
|
||||
":common_headers",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
deps = [
|
||||
"//:flatbuffers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "python_generator",
|
||||
hdrs = [
|
||||
"python_generator.h",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
deps = [
|
||||
":python_generator_private",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "python_generator_private",
|
||||
srcs = [
|
||||
"python_generator.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"python_generator.h",
|
||||
"python_private_generator.h",
|
||||
":common_headers",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//:flatbuffers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "swift_generator",
|
||||
srcs = [
|
||||
"swift_generator.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"swift_generator.h",
|
||||
":common_headers",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
deps = [
|
||||
"//:flatbuffers",
|
||||
],
|
||||
)
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "java_generator.h"
|
||||
#include "src/compiler/java_generator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
624
grpc/src/compiler/python_generator.cc
Normal file
624
grpc/src/compiler/python_generator.cc
Normal file
@@ -0,0 +1,624 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2015 gRPC authors.
|
||||
*
|
||||
* 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 <algorithm>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "flatbuffers/util.h"
|
||||
#include "src/compiler/python_generator.h"
|
||||
#include "src/compiler/python_private_generator.h"
|
||||
|
||||
using std::make_pair;
|
||||
using std::map;
|
||||
using std::pair;
|
||||
using std::replace;
|
||||
using std::tuple;
|
||||
using std::vector;
|
||||
using std::set;
|
||||
|
||||
namespace grpc_python_generator {
|
||||
|
||||
grpc::string generator_file_name;
|
||||
|
||||
typedef map<grpc::string, grpc::string> StringMap;
|
||||
typedef vector<grpc::string> StringVector;
|
||||
typedef tuple<grpc::string, grpc::string> StringPair;
|
||||
typedef set<StringPair> StringPairSet;
|
||||
|
||||
// Provides RAII indentation handling. Use as:
|
||||
// {
|
||||
// IndentScope raii_my_indent_var_name_here(my_py_printer);
|
||||
// // constructor indented my_py_printer
|
||||
// ...
|
||||
// // destructor called at end of scope, un-indenting my_py_printer
|
||||
// }
|
||||
class IndentScope {
|
||||
public:
|
||||
explicit IndentScope(grpc_generator::Printer* printer) : printer_(printer) {
|
||||
printer_->Indent();
|
||||
}
|
||||
|
||||
~IndentScope() { printer_->Outdent(); }
|
||||
|
||||
private:
|
||||
grpc_generator::Printer* printer_;
|
||||
};
|
||||
|
||||
inline grpc::string StringReplace(grpc::string str, const grpc::string& from,
|
||||
const grpc::string& to, bool replace_all) {
|
||||
size_t pos = 0;
|
||||
|
||||
do {
|
||||
pos = str.find(from, pos);
|
||||
if (pos == grpc::string::npos) {
|
||||
break;
|
||||
}
|
||||
str.replace(pos, from.length(), to);
|
||||
pos += to.length();
|
||||
} while (replace_all);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
inline grpc::string StringReplace(grpc::string str, const grpc::string& from,
|
||||
const grpc::string& to) {
|
||||
return StringReplace(str, from, to, true);
|
||||
}
|
||||
|
||||
grpc::string ModuleName(const grpc::string& filename,
|
||||
const grpc::string& import_prefix) {
|
||||
grpc::string basename = flatbuffers::StripExtension(filename);
|
||||
basename = StringReplace(basename, "-", "_");
|
||||
basename = StringReplace(basename, "/", ".");
|
||||
return import_prefix + basename + "_fb";
|
||||
}
|
||||
|
||||
grpc::string ModuleAlias(const grpc::string& filename,
|
||||
const grpc::string& import_prefix) {
|
||||
grpc::string module_name = ModuleName(filename, import_prefix);
|
||||
// We can't have dots in the module name, so we replace each with _dot_.
|
||||
// But that could lead to a collision between a.b and a_dot_b, so we also
|
||||
// duplicate each underscore.
|
||||
module_name = StringReplace(module_name, "_", "__");
|
||||
module_name = StringReplace(module_name, ".", "_dot_");
|
||||
return module_name;
|
||||
}
|
||||
|
||||
PrivateGenerator::PrivateGenerator(const GeneratorConfiguration& config_,
|
||||
const grpc_generator::File* file_)
|
||||
: config(config_), file(file_) {}
|
||||
|
||||
void PrivateGenerator::PrintBetaServicer(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out) {
|
||||
StringMap service_dict;
|
||||
service_dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(service_dict, "class Beta$Service$Servicer(object):\n");
|
||||
{
|
||||
IndentScope raii_class_indent(out);
|
||||
out->Print(
|
||||
"\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
|
||||
"\nIt is recommended to use the GA API (classes and functions in this\n"
|
||||
"file not marked beta) for all further purposes. This class was "
|
||||
"generated\n"
|
||||
"only to ease transition from grpcio<0.15.0 to "
|
||||
"grpcio>=0.15.0.\"\"\"\n");
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
grpc::string arg_name =
|
||||
method->ClientStreaming() ? "request_iterator" : "request";
|
||||
StringMap method_dict;
|
||||
method_dict["Method"] = method->name();
|
||||
method_dict["ArgName"] = arg_name;
|
||||
out->Print(method_dict, "def $Method$(self, $ArgName$, context):\n");
|
||||
{
|
||||
IndentScope raii_method_indent(out);
|
||||
out->Print("context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintBetaStub(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out) {
|
||||
StringMap service_dict;
|
||||
service_dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(service_dict, "class Beta$Service$Stub(object):\n");
|
||||
{
|
||||
IndentScope raii_class_indent(out);
|
||||
out->Print(
|
||||
"\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
|
||||
"\nIt is recommended to use the GA API (classes and functions in this\n"
|
||||
"file not marked beta) for all further purposes. This class was "
|
||||
"generated\n"
|
||||
"only to ease transition from grpcio<0.15.0 to "
|
||||
"grpcio>=0.15.0.\"\"\"\n");
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
grpc::string arg_name =
|
||||
method->ClientStreaming() ? "request_iterator" : "request";
|
||||
StringMap method_dict;
|
||||
method_dict["Method"] = method->name();
|
||||
method_dict["ArgName"] = arg_name;
|
||||
out->Print(method_dict,
|
||||
"def $Method$(self, $ArgName$, timeout, metadata=None, "
|
||||
"with_call=False, protocol_options=None):\n");
|
||||
{
|
||||
IndentScope raii_method_indent(out);
|
||||
out->Print("raise NotImplementedError()\n");
|
||||
}
|
||||
if (!method->ServerStreaming()) {
|
||||
out->Print(method_dict, "$Method$.future = None\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintBetaServerFactory(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out) {
|
||||
StringMap service_dict;
|
||||
service_dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(service_dict,
|
||||
"def beta_create_$Service$_server(servicer, pool=None, "
|
||||
"pool_size=None, default_timeout=None, maximum_timeout=None):\n");
|
||||
{
|
||||
IndentScope raii_create_server_indent(out);
|
||||
out->Print(
|
||||
"\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
|
||||
"\nIt is recommended to use the GA API (classes and functions in this\n"
|
||||
"file not marked beta) for all further purposes. This function was\n"
|
||||
"generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
|
||||
"\"\"\"\n");
|
||||
StringMap method_implementation_constructors;
|
||||
StringMap input_message_modules_and_classes;
|
||||
StringMap output_message_modules_and_classes;
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
const grpc::string method_implementation_constructor =
|
||||
grpc::string(method->ClientStreaming() ? "stream_" : "unary_") +
|
||||
grpc::string(method->ServerStreaming() ? "stream_" : "unary_") +
|
||||
"inline";
|
||||
grpc::string input_message_module_and_class = method->get_fb_builder();
|
||||
grpc::string output_message_module_and_class = method->get_fb_builder();
|
||||
method_implementation_constructors.insert(
|
||||
make_pair(method->name(), method_implementation_constructor));
|
||||
input_message_modules_and_classes.insert(
|
||||
make_pair(method->name(), input_message_module_and_class));
|
||||
output_message_modules_and_classes.insert(
|
||||
make_pair(method->name(), output_message_module_and_class));
|
||||
}
|
||||
StringMap method_dict;
|
||||
method_dict["PackageQualifiedServiceName"] = package_qualified_service_name;
|
||||
// out->Print("request_deserializers = {\n");
|
||||
// for (StringMap::iterator name_and_input_module_class_pair =
|
||||
// input_message_modules_and_classes.begin();
|
||||
// name_and_input_module_class_pair !=
|
||||
// input_message_modules_and_classes.end();
|
||||
// name_and_input_module_class_pair++) {
|
||||
// method_dict["MethodName"] = name_and_input_module_class_pair->first;
|
||||
// method_dict["InputTypeModuleAndClass"] =
|
||||
// name_and_input_module_class_pair->second;
|
||||
// IndentScope raii_indent(out);
|
||||
// out->Print(method_dict,
|
||||
// "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
|
||||
// "$InputTypeModuleAndClass$.FromString,\n");
|
||||
// }
|
||||
// out->Print("}\n");
|
||||
// out->Print("response_serializers = {\n");
|
||||
// for (StringMap::iterator name_and_output_module_class_pair =
|
||||
// output_message_modules_and_classes.begin();
|
||||
// name_and_output_module_class_pair !=
|
||||
// output_message_modules_and_classes.end();
|
||||
// name_and_output_module_class_pair++) {
|
||||
// method_dict["MethodName"] = name_and_output_module_class_pair->first;
|
||||
// method_dict["OutputTypeModuleAndClass"] =
|
||||
// name_and_output_module_class_pair->second;
|
||||
// IndentScope raii_indent(out);
|
||||
// out->Print(method_dict,
|
||||
// "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
|
||||
// "$OutputTypeModuleAndClass$.SerializeToString,\n");
|
||||
// }
|
||||
// out->Print("}\n");
|
||||
out->Print("method_implementations = {\n");
|
||||
for (StringMap::iterator name_and_implementation_constructor =
|
||||
method_implementation_constructors.begin();
|
||||
name_and_implementation_constructor !=
|
||||
method_implementation_constructors.end();
|
||||
name_and_implementation_constructor++) {
|
||||
method_dict["Method"] = name_and_implementation_constructor->first;
|
||||
method_dict["Constructor"] = name_and_implementation_constructor->second;
|
||||
IndentScope raii_descriptions_indent(out);
|
||||
const grpc::string method_name =
|
||||
name_and_implementation_constructor->first;
|
||||
out->Print(method_dict,
|
||||
"(\'$PackageQualifiedServiceName$\', \'$Method$\'): "
|
||||
"face_utilities.$Constructor$(servicer.$Method$),\n");
|
||||
}
|
||||
out->Print("}\n");
|
||||
out->Print(
|
||||
"server_options = beta_implementations.server_options("
|
||||
"thread_pool=pool, thread_pool_size=pool_size, "
|
||||
"default_timeout=default_timeout, "
|
||||
"maximum_timeout=maximum_timeout)\n");
|
||||
out->Print(
|
||||
"return beta_implementations.server(method_implementations, "
|
||||
"options=server_options)\n");
|
||||
//"request_deserializers=request_deserializers, "
|
||||
//"response_serializers=response_serializers, "
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintBetaStubFactory(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out) {
|
||||
StringMap dict;
|
||||
dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(dict,
|
||||
"def beta_create_$Service$_stub(channel, host=None,"
|
||||
" metadata_transformer=None, pool=None, pool_size=None):\n");
|
||||
{
|
||||
IndentScope raii_create_server_indent(out);
|
||||
out->Print(
|
||||
"\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
|
||||
"\nIt is recommended to use the GA API (classes and functions in this\n"
|
||||
"file not marked beta) for all further purposes. This function was\n"
|
||||
"generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
|
||||
"\"\"\"\n");
|
||||
StringMap method_cardinalities;
|
||||
StringMap input_message_modules_and_classes;
|
||||
StringMap output_message_modules_and_classes;
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
const grpc::string method_cardinality =
|
||||
grpc::string(method->ClientStreaming() ? "STREAM" : "UNARY") +
|
||||
"_" +
|
||||
grpc::string(method->ServerStreaming() ? "STREAM" : "UNARY");
|
||||
grpc::string input_message_module_and_class = method->get_fb_builder();
|
||||
grpc::string output_message_module_and_class = method->get_fb_builder();
|
||||
method_cardinalities.insert(
|
||||
make_pair(method->name(), method_cardinality));
|
||||
input_message_modules_and_classes.insert(
|
||||
make_pair(method->name(), input_message_module_and_class));
|
||||
output_message_modules_and_classes.insert(
|
||||
make_pair(method->name(), output_message_module_and_class));
|
||||
}
|
||||
StringMap method_dict;
|
||||
method_dict["PackageQualifiedServiceName"] = package_qualified_service_name;
|
||||
// out->Print("request_serializers = {\n");
|
||||
// for (StringMap::iterator name_and_input_module_class_pair =
|
||||
// input_message_modules_and_classes.begin();
|
||||
// name_and_input_module_class_pair !=
|
||||
// input_message_modules_and_classes.end();
|
||||
// name_and_input_module_class_pair++) {
|
||||
// method_dict["MethodName"] = name_and_input_module_class_pair->first;
|
||||
// method_dict["InputTypeModuleAndClass"] =
|
||||
// name_and_input_module_class_pair->second;
|
||||
// IndentScope raii_indent(out);
|
||||
// out->Print(method_dict,
|
||||
// "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
|
||||
// "$InputTypeModuleAndClass$.SerializeToString,\n");
|
||||
// }
|
||||
// out->Print("}\n");
|
||||
// out->Print("response_deserializers = {\n");
|
||||
// for (StringMap::iterator name_and_output_module_class_pair =
|
||||
// output_message_modules_and_classes.begin();
|
||||
// name_and_output_module_class_pair !=
|
||||
// output_message_modules_and_classes.end();
|
||||
// name_and_output_module_class_pair++) {
|
||||
// method_dict["MethodName"] = name_and_output_module_class_pair->first;
|
||||
// method_dict["OutputTypeModuleAndClass"] =
|
||||
// name_and_output_module_class_pair->second;
|
||||
// IndentScope raii_indent(out);
|
||||
// out->Print(method_dict,
|
||||
// "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
|
||||
// "$OutputTypeModuleAndClass$.FromString,\n");
|
||||
// }
|
||||
// out->Print("}\n");
|
||||
out->Print("cardinalities = {\n");
|
||||
for (StringMap::iterator name_and_cardinality =
|
||||
method_cardinalities.begin();
|
||||
name_and_cardinality != method_cardinalities.end();
|
||||
name_and_cardinality++) {
|
||||
method_dict["Method"] = name_and_cardinality->first;
|
||||
method_dict["Cardinality"] = name_and_cardinality->second;
|
||||
IndentScope raii_descriptions_indent(out);
|
||||
out->Print(method_dict,
|
||||
"\'$Method$\': cardinality.Cardinality.$Cardinality$,\n");
|
||||
}
|
||||
out->Print("}\n");
|
||||
out->Print(
|
||||
"stub_options = beta_implementations.stub_options("
|
||||
"host=host, metadata_transformer=metadata_transformer, "
|
||||
"thread_pool=pool, thread_pool_size=pool_size)\n");
|
||||
out->Print(method_dict,
|
||||
"return beta_implementations.dynamic_stub(channel, "
|
||||
"\'$PackageQualifiedServiceName$\', "
|
||||
"cardinalities, options=stub_options)\n");
|
||||
// "request_serializers=request_serializers, "
|
||||
//"response_deserializers=response_deserializers, "
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintStub(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out) {
|
||||
StringMap dict;
|
||||
dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(dict, "class $Service$Stub(object):\n");
|
||||
{
|
||||
IndentScope raii_class_indent(out);
|
||||
out->Print("\n");
|
||||
out->Print("def __init__(self, channel):\n");
|
||||
{
|
||||
IndentScope raii_init_indent(out);
|
||||
out->Print("\"\"\"Constructor.\n");
|
||||
out->Print("\n");
|
||||
out->Print("Args:\n");
|
||||
{
|
||||
IndentScope raii_args_indent(out);
|
||||
out->Print("channel: A grpc.Channel.\n");
|
||||
}
|
||||
out->Print("\"\"\"\n");
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
grpc::string multi_callable_constructor =
|
||||
grpc::string(method->ClientStreaming() ? "stream" : "unary") +
|
||||
"_" +
|
||||
grpc::string(method->ServerStreaming() ? "stream" : "unary");
|
||||
grpc::string request_module_and_class = method->get_fb_builder();
|
||||
grpc::string response_module_and_class = method->get_fb_builder();
|
||||
StringMap method_dict;
|
||||
method_dict["Method"] = method->name();
|
||||
method_dict["MultiCallableConstructor"] = multi_callable_constructor;
|
||||
out->Print(method_dict,
|
||||
"self.$Method$ = channel.$MultiCallableConstructor$(\n");
|
||||
{
|
||||
method_dict["PackageQualifiedService"] =
|
||||
package_qualified_service_name;
|
||||
method_dict["RequestModuleAndClass"] = request_module_and_class;
|
||||
method_dict["ResponseModuleAndClass"] = response_module_and_class;
|
||||
IndentScope raii_first_attribute_indent(out);
|
||||
IndentScope raii_second_attribute_indent(out);
|
||||
out->Print(method_dict, "'/$PackageQualifiedService$/$Method$',\n");
|
||||
out->Print(method_dict,"\n");
|
||||
out->Print(
|
||||
method_dict,"\n");
|
||||
out->Print(")\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintServicer(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out) {
|
||||
StringMap service_dict;
|
||||
service_dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(service_dict, "class $Service$Servicer(object):\n");
|
||||
{
|
||||
IndentScope raii_class_indent(out);
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
grpc::string arg_name =
|
||||
method->ClientStreaming() ? "request_iterator" : "request";
|
||||
StringMap method_dict;
|
||||
method_dict["Method"] = method->name();
|
||||
method_dict["ArgName"] = arg_name;
|
||||
out->Print("\n");
|
||||
out->Print(method_dict, "def $Method$(self, $ArgName$, context):\n");
|
||||
{
|
||||
IndentScope raii_method_indent(out);
|
||||
out->Print("context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n");
|
||||
out->Print("context.set_details('Method not implemented!')\n");
|
||||
out->Print("raise NotImplementedError('Method not implemented!')\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintAddServicerToServer(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out) {
|
||||
StringMap service_dict;
|
||||
service_dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(service_dict,
|
||||
"def add_$Service$Servicer_to_server(servicer, server):\n");
|
||||
{
|
||||
IndentScope raii_class_indent(out);
|
||||
out->Print("rpc_method_handlers = {\n");
|
||||
{
|
||||
IndentScope raii_dict_first_indent(out);
|
||||
IndentScope raii_dict_second_indent(out);
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
grpc::string method_handler_constructor =
|
||||
grpc::string(method->ClientStreaming() ? "stream" : "unary") +
|
||||
"_" +
|
||||
grpc::string(method->ServerStreaming() ? "stream" : "unary") +
|
||||
"_rpc_method_handler";
|
||||
grpc::string request_module_and_class = method->get_fb_builder();
|
||||
grpc::string response_module_and_class = method->get_fb_builder();
|
||||
StringMap method_dict;
|
||||
method_dict["Method"] = method->name();
|
||||
method_dict["MethodHandlerConstructor"] = method_handler_constructor;
|
||||
method_dict["RequestModuleAndClass"] = request_module_and_class;
|
||||
method_dict["ResponseModuleAndClass"] = response_module_and_class;
|
||||
out->Print(method_dict,
|
||||
"'$Method$': grpc.$MethodHandlerConstructor$(\n");
|
||||
{
|
||||
IndentScope raii_call_first_indent(out);
|
||||
IndentScope raii_call_second_indent(out);
|
||||
out->Print(method_dict, "servicer.$Method$,\n");
|
||||
out->Print(
|
||||
method_dict,"\n");
|
||||
out->Print(
|
||||
method_dict,
|
||||
"\n");
|
||||
}
|
||||
out->Print("),\n");
|
||||
}
|
||||
}
|
||||
StringMap method_dict;
|
||||
method_dict["PackageQualifiedServiceName"] = package_qualified_service_name;
|
||||
out->Print("}\n");
|
||||
out->Print("generic_handler = grpc.method_handlers_generic_handler(\n");
|
||||
{
|
||||
IndentScope raii_call_first_indent(out);
|
||||
IndentScope raii_call_second_indent(out);
|
||||
out->Print(method_dict,
|
||||
"'$PackageQualifiedServiceName$', rpc_method_handlers)\n");
|
||||
}
|
||||
out->Print("server.add_generic_rpc_handlers((generic_handler,))\n");
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintBetaPreamble(grpc_generator::Printer* out) {
|
||||
StringMap var;
|
||||
var["Package"] = config.beta_package_root;
|
||||
out->Print(var,
|
||||
"from $Package$ import implementations as beta_implementations\n");
|
||||
out->Print(var, "from $Package$ import interfaces as beta_interfaces\n");
|
||||
out->Print("from grpc.framework.common import cardinality\n");
|
||||
out->Print(
|
||||
"from grpc.framework.interfaces.face import utilities as "
|
||||
"face_utilities\n");
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintPreamble(grpc_generator::Printer* out) {
|
||||
StringMap var;
|
||||
var["Package"] = config.grpc_package_root;
|
||||
out->Print(var, "import $Package$\n");
|
||||
out->Print("\n");
|
||||
StringPairSet imports_set;
|
||||
for (int i = 0; i < file->service_count(); ++i) {
|
||||
auto service = file->service(i);
|
||||
for (int j = 0; j < service->method_count(); ++j) {
|
||||
auto method = service.get()->method(j);
|
||||
|
||||
grpc::string input_type_file_name = method->get_fb_builder();
|
||||
grpc::string input_module_name =
|
||||
ModuleName(input_type_file_name, config.import_prefix);
|
||||
grpc::string input_module_alias =
|
||||
ModuleAlias(input_type_file_name, config.import_prefix);
|
||||
imports_set.insert(
|
||||
std::make_tuple(input_module_name, input_module_alias));
|
||||
|
||||
grpc::string output_type_file_name = method->get_fb_builder();
|
||||
grpc::string output_module_name =
|
||||
ModuleName(output_type_file_name, config.import_prefix);
|
||||
grpc::string output_module_alias =
|
||||
ModuleAlias(output_type_file_name, config.import_prefix);
|
||||
imports_set.insert(
|
||||
std::make_tuple(output_module_name, output_module_alias));
|
||||
}
|
||||
}
|
||||
|
||||
for (StringPairSet::iterator it = imports_set.begin();
|
||||
it != imports_set.end(); ++it) {
|
||||
var["ModuleName"] = std::get<0>(*it);
|
||||
var["ModuleAlias"] = std::get<1>(*it);
|
||||
out->Print(var, "import $ModuleName$ as $ModuleAlias$\n");
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintGAServices(grpc_generator::Printer* out) {
|
||||
grpc::string package = file->package();
|
||||
if (!package.empty()) {
|
||||
package = package.append(".");
|
||||
}
|
||||
|
||||
out->Print(file->additional_headers().c_str());
|
||||
|
||||
for (int i = 0; i < file->service_count(); ++i) {
|
||||
auto service = file->service(i);
|
||||
|
||||
grpc::string package_qualified_service_name = package + service->name();
|
||||
PrintStub(package_qualified_service_name, service.get(), out);
|
||||
PrintServicer(service.get(), out);
|
||||
PrintAddServicerToServer(package_qualified_service_name, service.get(),
|
||||
out);
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintBetaServices(grpc_generator::Printer* out) {
|
||||
grpc::string package = file->package();
|
||||
if (!package.empty()) {
|
||||
package = package.append(".");
|
||||
}
|
||||
for (int i = 0; i < file->service_count(); ++i) {
|
||||
auto service = file->service(i);
|
||||
|
||||
grpc::string package_qualified_service_name = package + service->name();
|
||||
PrintBetaServicer(service.get(), out);
|
||||
PrintBetaStub(service.get(), out);
|
||||
PrintBetaServerFactory(package_qualified_service_name, service.get(), out);
|
||||
PrintBetaStubFactory(package_qualified_service_name, service.get(), out);
|
||||
}
|
||||
}
|
||||
|
||||
grpc::string PrivateGenerator::GetGrpcServices() {
|
||||
grpc::string output;
|
||||
{
|
||||
// Scope the output stream so it closes and finalizes output to the string.
|
||||
auto out = file->CreatePrinter(&output);
|
||||
out->Print(
|
||||
"# Generated by the gRPC Python protocol compiler plugin. "
|
||||
"DO NOT EDIT!\n");
|
||||
StringMap var;
|
||||
var["Package"] = config.grpc_package_root;
|
||||
out->Print(var, "import $Package$\n");
|
||||
PrintGAServices(out.get());
|
||||
out->Print("try:\n");
|
||||
{
|
||||
IndentScope raii_dict_try_indent(out.get());
|
||||
out->Print(
|
||||
"# THESE ELEMENTS WILL BE DEPRECATED.\n"
|
||||
"# Please use the generated *_pb2_grpc.py files instead.\n");
|
||||
out->Print(var, "import $Package$\n");
|
||||
PrintBetaPreamble(out.get());
|
||||
PrintGAServices(out.get());
|
||||
PrintBetaServices(out.get());
|
||||
}
|
||||
out->Print("except ImportError:\n");
|
||||
{
|
||||
IndentScope raii_dict_except_indent(out.get());
|
||||
out->Print("pass");
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
} // namespace grpc_python_generator
|
||||
40
grpc/src/compiler/python_generator.h
Normal file
40
grpc/src/compiler/python_generator.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2015 gRPC authors.
|
||||
*
|
||||
* 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 GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H
|
||||
#define GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "src/compiler/schema_interface.h"
|
||||
|
||||
namespace grpc_python_generator {
|
||||
|
||||
// Data pertaining to configuration of the generator with respect to anything
|
||||
// that may be used internally at Google.
|
||||
struct GeneratorConfiguration {
|
||||
grpc::string grpc_package_root;
|
||||
// TODO(https://github.com/grpc/grpc/issues/8622): Drop this.
|
||||
grpc::string beta_package_root;
|
||||
// TODO(https://github.com/google/protobuf/issues/888): Drop this.
|
||||
grpc::string import_prefix;
|
||||
};
|
||||
|
||||
} // namespace grpc_python_generator
|
||||
|
||||
#endif // GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H
|
||||
72
grpc/src/compiler/python_private_generator.h
Normal file
72
grpc/src/compiler/python_private_generator.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2015 gRPC authors.
|
||||
*
|
||||
* 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 GRPC_INTERNAL_COMPILER_PYTHON_PRIVATE_GENERATOR_H
|
||||
#define GRPC_INTERNAL_COMPILER_PYTHON_PRIVATE_GENERATOR_H
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "src/compiler/python_generator.h"
|
||||
#include "src/compiler/schema_interface.h"
|
||||
|
||||
namespace grpc_python_generator {
|
||||
|
||||
// Tucks all generator state in an anonymous namespace away from
|
||||
// PythonGrpcGenerator and the header file, mostly to encourage future changes
|
||||
// to not require updates to the grpcio-tools C++ code part. Assumes that it is
|
||||
// only ever used from a single thread.
|
||||
struct PrivateGenerator {
|
||||
const GeneratorConfiguration& config;
|
||||
const grpc_generator::File* file;
|
||||
|
||||
PrivateGenerator(const GeneratorConfiguration& config,
|
||||
const grpc_generator::File* file);
|
||||
|
||||
grpc::string GetGrpcServices();
|
||||
|
||||
private:
|
||||
void PrintPreamble(grpc_generator::Printer* out);
|
||||
void PrintBetaPreamble(grpc_generator::Printer* out);
|
||||
void PrintGAServices(grpc_generator::Printer* out);
|
||||
void PrintBetaServices(grpc_generator::Printer* out);
|
||||
|
||||
void PrintAddServicerToServer(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out);
|
||||
void PrintServicer(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out);
|
||||
void PrintStub(const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out);
|
||||
|
||||
void PrintBetaServicer(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out);
|
||||
void PrintBetaServerFactory(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out);
|
||||
void PrintBetaStub(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out);
|
||||
void PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out);
|
||||
};
|
||||
|
||||
} // namespace grpc_python_generator
|
||||
|
||||
#endif // GRPC_INTERNAL_COMPILER_PYTHON_PRIVATE_GENERATOR_H
|
||||
@@ -1,44 +1,29 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
* Copyright 2015 gRPC authors.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* 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
|
||||
*
|
||||
* * 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.
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* 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.
|
||||
* 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 GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
|
||||
#define GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
|
||||
|
||||
#include "src/compiler/config.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "src/compiler/config.h"
|
||||
|
||||
#ifndef GRPC_CUSTOM_STRING
|
||||
# include <string>
|
||||
# define GRPC_CUSTOM_STRING std::string
|
||||
@@ -79,6 +64,9 @@ struct Method : public CommentHolder {
|
||||
|
||||
virtual grpc::string get_input_type_name() const = 0;
|
||||
virtual grpc::string get_output_type_name() const = 0;
|
||||
|
||||
virtual grpc::string get_fb_builder() const = 0;
|
||||
|
||||
virtual bool NoStreaming() const = 0;
|
||||
virtual bool ClientStreaming() const = 0;
|
||||
virtual bool ServerStreaming() const = 0;
|
||||
|
||||
308
grpc/src/compiler/swift_generator.cc
Normal file
308
grpc/src/compiler/swift_generator.cc
Normal file
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE: The following implementation is a translation for the Swift-grpc
|
||||
* generator since flatbuffers doesnt allow plugins for now. if an issue arises
|
||||
* please open an issue in the flatbuffers repository. This file should always
|
||||
* be maintained according to the Swift-grpc repository
|
||||
*/
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
||||
#include "flatbuffers/util.h"
|
||||
#include "src/compiler/schema_interface.h"
|
||||
#include "src/compiler/swift_generator.h"
|
||||
|
||||
namespace grpc_swift_generator {
|
||||
|
||||
grpc::string GenerateMessage(const grpc::string &name) {
|
||||
return "Message<" + name + ">";
|
||||
}
|
||||
|
||||
// MARK: - Client
|
||||
|
||||
grpc::string GenerateClientFuncName(const grpc_generator::Method *method) {
|
||||
if (method->NoStreaming()) {
|
||||
return "$GenAccess$ func $MethodName$(_ request: $Input$"
|
||||
", callOptions: CallOptions?$isNil$) -> UnaryCall<$Input$,$Output$>";
|
||||
}
|
||||
|
||||
if (method->ClientStreaming()) {
|
||||
return "$GenAccess$ func $MethodName$"
|
||||
"(callOptions: CallOptions?$isNil$) -> "
|
||||
"ClientStreamingCall<$Input$,$Output$>";
|
||||
}
|
||||
|
||||
if (method->ServerStreaming()) {
|
||||
return "$GenAccess$ func $MethodName$(_ request: $Input$"
|
||||
", callOptions: CallOptions?$isNil$, handler: @escaping ($Output$"
|
||||
") -> Void) -> ServerStreamingCall<$Input$, $Output$>";
|
||||
}
|
||||
return "$GenAccess$ func $MethodName$"
|
||||
"(callOptions: CallOptions?$isNil$, handler: @escaping ($Output$"
|
||||
") -> Void) -> BidirectionalStreamingCall<$Input$, $Output$>";
|
||||
}
|
||||
|
||||
grpc::string GenerateClientFuncBody(const grpc_generator::Method *method) {
|
||||
if (method->NoStreaming()) {
|
||||
return "return self.makeUnaryCall(path: "
|
||||
"\"/$PATH$$ServiceName$/$MethodName$\", request: request, "
|
||||
"callOptions: callOptions ?? self.defaultCallOptions)";
|
||||
}
|
||||
|
||||
if (method->ClientStreaming()) {
|
||||
return "return self.makeClientStreamingCall(path: "
|
||||
"\"/$PATH$$ServiceName$/$MethodName$\", callOptions: callOptions ?? "
|
||||
"self.defaultCallOptions)";
|
||||
}
|
||||
|
||||
if (method->ServerStreaming()) {
|
||||
return "return self.makeServerStreamingCall(path: "
|
||||
"\"/$PATH$$ServiceName$/$MethodName$\", request: request, "
|
||||
"callOptions: callOptions ?? self.defaultCallOptions, handler: "
|
||||
"handler)";
|
||||
}
|
||||
return "return self.makeBidirectionalStreamingCall(path: "
|
||||
"\"/$PATH$$ServiceName$/$MethodName$\", callOptions: callOptions ?? "
|
||||
"self.defaultCallOptions, handler: handler)";
|
||||
}
|
||||
|
||||
void GenerateClientProtocol(const grpc_generator::Service *service,
|
||||
grpc_generator::Printer *printer,
|
||||
std::map<grpc::string, grpc::string> *dictonary) {
|
||||
auto vars = *dictonary;
|
||||
printer->Print(vars, "$ACCESS$ protocol $ServiceName$Service {\n");
|
||||
vars["GenAccess"] = "";
|
||||
for (auto it = 0; it < service->method_count(); it++) {
|
||||
auto method = service->method(it);
|
||||
vars["Input"] = GenerateMessage(method->get_input_type_name());
|
||||
vars["Output"] = GenerateMessage(method->get_output_type_name());
|
||||
vars["MethodName"] = method->name();
|
||||
vars["isNil"] = "";
|
||||
printer->Print("\t");
|
||||
auto func = GenerateClientFuncName(method.get());
|
||||
printer->Print(vars, func.c_str());
|
||||
printer->Print("\n");
|
||||
}
|
||||
printer->Print("}\n\n");
|
||||
}
|
||||
|
||||
void GenerateClientClass(const grpc_generator::Service *service,
|
||||
grpc_generator::Printer *printer,
|
||||
std::map<grpc::string, grpc::string> *dictonary) {
|
||||
auto vars = *dictonary;
|
||||
printer->Print(vars,
|
||||
"$ACCESS$ final class $ServiceName$ServiceClient: GRPCClient, "
|
||||
"$ServiceName$Service {\n");
|
||||
printer->Print(vars, "\t$ACCESS$ let connection: ClientConnection\n");
|
||||
printer->Print(vars, "\t$ACCESS$ var defaultCallOptions: CallOptions\n");
|
||||
printer->Print("\n");
|
||||
printer->Print(vars,
|
||||
"\t$ACCESS$ init(connection: ClientConnection, "
|
||||
"defaultCallOptions: CallOptions = CallOptions()) {\n");
|
||||
printer->Print("\t\tself.connection = connection\n");
|
||||
printer->Print("\t\tself.defaultCallOptions = defaultCallOptions\n");
|
||||
printer->Print("\t}");
|
||||
printer->Print("\n");
|
||||
vars["GenAccess"] = "public";
|
||||
for (auto it = 0; it < service->method_count(); it++) {
|
||||
auto method = service->method(it);
|
||||
vars["Input"] = GenerateMessage(method->get_input_type_name());
|
||||
vars["Output"] = GenerateMessage(method->get_output_type_name());
|
||||
vars["MethodName"] = method->name();
|
||||
vars["isNil"] = " = nil";
|
||||
printer->Print("\n\t");
|
||||
auto func = GenerateClientFuncName(method.get());
|
||||
printer->Print(vars, func.c_str());
|
||||
printer->Print(" {\n");
|
||||
auto body = GenerateClientFuncBody(method.get());
|
||||
printer->Print("\t\t");
|
||||
printer->Print(vars, body.c_str());
|
||||
printer->Print("\n\t}\n");
|
||||
}
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
// MARK: - Server
|
||||
|
||||
grpc::string GenerateServerFuncName(const grpc_generator::Method *method) {
|
||||
if (method->NoStreaming()) {
|
||||
return "func $MethodName$(_ request: $Input$"
|
||||
", context: StatusOnlyCallContext) -> EventLoopFuture<$Output$>";
|
||||
}
|
||||
|
||||
if (method->ClientStreaming()) {
|
||||
return "func $MethodName$(context: UnaryResponseCallContext<$Output$>) -> "
|
||||
"EventLoopFuture<(StreamEvent<$Input$"
|
||||
">) -> Void>";
|
||||
}
|
||||
|
||||
if (method->ServerStreaming()) {
|
||||
return "func $MethodName$(request: $Input$"
|
||||
", context: StreamingResponseCallContext<$Output$>) -> "
|
||||
"EventLoopFuture<GRPCStatus>";
|
||||
}
|
||||
return "func $MethodName$(context: StreamingResponseCallContext<$Output$>) "
|
||||
"-> EventLoopFuture<(StreamEvent<$Input$>) -> Void>";
|
||||
}
|
||||
|
||||
grpc::string GenerateServerExtensionBody(const grpc_generator::Method *method) {
|
||||
grpc::string start = "\t\tcase \"$MethodName$\":\n\t\t";
|
||||
if (method->NoStreaming()) {
|
||||
return start +
|
||||
"return UnaryCallHandler(callHandlerContext: callHandlerContext) { "
|
||||
"context in"
|
||||
"\n\t\t\t"
|
||||
"return { request in"
|
||||
"\n\t\t\t\t"
|
||||
"self.$MethodName$(request, context: context)"
|
||||
"\n\t\t\t}"
|
||||
"\n\t\t}";
|
||||
}
|
||||
if (method->ClientStreaming()) {
|
||||
return start +
|
||||
"return ClientStreamingCallHandler(callHandlerContext: "
|
||||
"callHandlerContext) { context in"
|
||||
"\n\t\t\t"
|
||||
"return { request in"
|
||||
"\n\t\t\t\t"
|
||||
"self.$MethodName$(request: request, context: context)"
|
||||
"\n\t\t\t}"
|
||||
"\n\t\t}";
|
||||
}
|
||||
if (method->ServerStreaming()) {
|
||||
return start +
|
||||
"return ServerStreamingCallHandler(callHandlerContext: "
|
||||
"callHandlerContext) { context in"
|
||||
"\n\t\t\t"
|
||||
"return { request in"
|
||||
"\n\t\t\t\t"
|
||||
"self.$MethodName$(request: request, context: context)"
|
||||
"\n\t\t\t}"
|
||||
"\n\t\t}";
|
||||
}
|
||||
if (method->BidiStreaming()) {
|
||||
return start +
|
||||
"return BidirectionalStreamingCallHandler(callHandlerContext: "
|
||||
"callHandlerContext) { context in"
|
||||
"\n\t\t\t"
|
||||
"return { request in"
|
||||
"\n\t\t\t\t"
|
||||
"self.$MethodName$(request: request, context: context)"
|
||||
"\n\t\t\t}"
|
||||
"\n\t\t}";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void GenerateServerProtocol(const grpc_generator::Service *service,
|
||||
grpc_generator::Printer *printer,
|
||||
std::map<grpc::string, grpc::string> *dictonary) {
|
||||
auto vars = *dictonary;
|
||||
printer->Print(
|
||||
vars, "$ACCESS$ protocol $ServiceName$Provider: CallHandlerProvider {\n");
|
||||
for (auto it = 0; it < service->method_count(); it++) {
|
||||
auto method = service->method(it);
|
||||
vars["Input"] = GenerateMessage(method->get_input_type_name());
|
||||
vars["Output"] = GenerateMessage(method->get_output_type_name());
|
||||
vars["MethodName"] = method->name();
|
||||
printer->Print("\t");
|
||||
auto func = GenerateServerFuncName(method.get());
|
||||
printer->Print(vars, func.c_str());
|
||||
printer->Print("\n");
|
||||
}
|
||||
printer->Print("}\n\n");
|
||||
|
||||
printer->Print(vars, "$ACCESS$ extension $ServiceName$Provider {\n");
|
||||
printer->Print(vars,
|
||||
"\tvar serviceName: String { return "
|
||||
"\"$PATH$$ServiceName$\" }\n");
|
||||
printer->Print(
|
||||
"\tfunc handleMethod(_ methodName: String, callHandlerContext: "
|
||||
"CallHandlerContext) -> GRPCCallHandler? {\n");
|
||||
printer->Print("\t\tswitch methodName {\n");
|
||||
for (auto it = 0; it < service->method_count(); it++) {
|
||||
auto method = service->method(it);
|
||||
vars["Input"] = GenerateMessage(method->get_input_type_name());
|
||||
vars["Output"] = GenerateMessage(method->get_output_type_name());
|
||||
vars["MethodName"] = method->name();
|
||||
auto body = GenerateServerExtensionBody(method.get());
|
||||
printer->Print(vars, body.c_str());
|
||||
printer->Print("\n");
|
||||
}
|
||||
printer->Print("\t\tdefault: return nil;\n");
|
||||
printer->Print("\t\t}\n");
|
||||
printer->Print("\t}\n\n");
|
||||
printer->Print("}\n\n");
|
||||
}
|
||||
|
||||
grpc::string Generate(grpc_generator::File *file,
|
||||
const grpc_generator::Service *service) {
|
||||
grpc::string output;
|
||||
std::map<grpc::string, grpc::string> vars;
|
||||
vars["PATH"] = file->package();
|
||||
if (!file->package().empty()) { vars["PATH"].append("."); }
|
||||
vars["ServiceName"] = service->name();
|
||||
vars["ACCESS"] = "public";
|
||||
auto printer = file->CreatePrinter(&output);
|
||||
printer->Print(vars,
|
||||
"/// Usage: instantiate $ServiceName$ServiceClient, then call "
|
||||
"methods of this protocol to make API calls.\n");
|
||||
GenerateClientProtocol(service, &*printer, &vars);
|
||||
GenerateClientClass(service, &*printer, &vars);
|
||||
printer->Print("\n");
|
||||
GenerateServerProtocol(service, &*printer, &vars);
|
||||
return output;
|
||||
}
|
||||
|
||||
grpc::string GenerateHeader() {
|
||||
grpc::string code;
|
||||
code +=
|
||||
"/// The following code is generated by the Flatbuffers library which "
|
||||
"might not be in sync with grpc-swift\n";
|
||||
code +=
|
||||
"/// in case of an issue please open github issue, though it would be "
|
||||
"maintained\n";
|
||||
code += "import Foundation\n";
|
||||
code += "import GRPC\n";
|
||||
code += "import NIO\n";
|
||||
code += "import NIOHTTP1\n";
|
||||
code += "import FlatBuffers\n";
|
||||
code += "\n";
|
||||
code +=
|
||||
"public protocol GRPCFlatBufPayload: GRPCPayload, FlatBufferGRPCMessage "
|
||||
"{}\n";
|
||||
|
||||
code += "public extension GRPCFlatBufPayload {\n";
|
||||
code += " init(serializedByteBuffer: inout NIO.ByteBuffer) throws {\n";
|
||||
code +=
|
||||
" self.init(byteBuffer: FlatBuffers.ByteBuffer(contiguousBytes: "
|
||||
"serializedByteBuffer.readableBytesView, count: "
|
||||
"serializedByteBuffer.readableBytes))\n";
|
||||
code += " }\n";
|
||||
|
||||
code += " func serialize(into buffer: inout NIO.ByteBuffer) throws {\n";
|
||||
code +=
|
||||
" let buf = UnsafeRawBufferPointer(start: self.rawPointer, count: "
|
||||
"Int(self.size))\n";
|
||||
code += " buffer.writeBytes(buf)\n";
|
||||
code += " }\n";
|
||||
code += "}\n";
|
||||
code += "extension Message: GRPCFlatBufPayload {}\n";
|
||||
return code;
|
||||
}
|
||||
} // namespace grpc_swift_generator
|
||||
55
grpc/src/compiler/swift_generator.h
Normal file
55
grpc/src/compiler/swift_generator.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#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_swift_generator {
|
||||
grpc::string Generate(grpc_generator::File *file,
|
||||
const grpc_generator::Service *service);
|
||||
grpc::string GenerateHeader();
|
||||
} // namespace grpc_swift_generator
|
||||
@@ -96,7 +96,7 @@ public class JavaGrpcTest {
|
||||
if (monster.hp() > maxHp.get()) {
|
||||
// Found a monster of higher hit points.
|
||||
maxHp.set(monster.hp());
|
||||
maxHpMonsterName.set(monster.name());
|
||||
maxHpMonsterName.set(monster.name());
|
||||
maxHpCount.set(1);
|
||||
}
|
||||
else if (monster.hp() == maxHp.get()) {
|
||||
@@ -141,7 +141,7 @@ public class JavaGrpcTest {
|
||||
channel = ManagedChannelBuilder.forAddress("localhost", port)
|
||||
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
|
||||
// needing certificates.
|
||||
.usePlaintext(true)
|
||||
.usePlaintext()
|
||||
.directExecutor()
|
||||
.build();
|
||||
blockingStub = MonsterStorageGrpc.newBlockingStub(channel);
|
||||
@@ -177,7 +177,7 @@ public class JavaGrpcTest {
|
||||
final CountDownLatch streamAlive = new CountDownLatch(1);
|
||||
|
||||
StreamObserver<Stat> statObserver = new StreamObserver<Stat>() {
|
||||
public void onCompleted() {
|
||||
public void onCompleted() {
|
||||
streamAlive.countDown();
|
||||
}
|
||||
public void onError(Throwable ex) { }
|
||||
|
||||
@@ -14,17 +14,17 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include <grpc++/grpc++.h>
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include "monster_test.grpc.fb.h"
|
||||
#include "monster_test_generated.h"
|
||||
#include "test_assert.h"
|
||||
|
||||
using namespace MyGame::Example;
|
||||
using flatbuffers::grpc::MessageBuilder;
|
||||
using flatbuffers::FlatBufferBuilder;
|
||||
using flatbuffers::grpc::MessageBuilder;
|
||||
|
||||
void message_builder_tests();
|
||||
|
||||
@@ -97,8 +97,7 @@ void RunServer() {
|
||||
server_instance->Wait();
|
||||
}
|
||||
|
||||
template <class Builder>
|
||||
void StoreRPC(MonsterStorage::Stub *stub) {
|
||||
template<class Builder> void StoreRPC(MonsterStorage::Stub *stub) {
|
||||
Builder fbb;
|
||||
grpc::ClientContext context;
|
||||
// Build a request with the name set.
|
||||
@@ -119,8 +118,7 @@ void StoreRPC(MonsterStorage::Stub *stub) {
|
||||
}
|
||||
}
|
||||
|
||||
template <class Builder>
|
||||
void RetrieveRPC(MonsterStorage::Stub *stub) {
|
||||
template<class Builder> void RetrieveRPC(MonsterStorage::Stub *stub) {
|
||||
Builder fbb;
|
||||
grpc::ClientContext context;
|
||||
fbb.Clear();
|
||||
@@ -155,7 +153,6 @@ int grpc_server_test() {
|
||||
RetrieveRPC<MessageBuilder>(stub.get());
|
||||
RetrieveRPC<FlatBufferBuilder>(stub.get());
|
||||
|
||||
|
||||
#if !FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
|
||||
{
|
||||
// Test that an invalid request errors out correctly
|
||||
@@ -181,7 +178,7 @@ int grpc_server_test() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int /*argc*/, const char * /*argv*/ []) {
|
||||
int main(int /*argc*/, const char * /*argv*/[]) {
|
||||
message_builder_tests();
|
||||
grpc_server_test();
|
||||
|
||||
@@ -193,4 +190,3 @@ int main(int /*argc*/, const char * /*argv*/ []) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
174
grpc/tests/grpctest.py
Normal file
174
grpc/tests/grpctest.py
Normal file
@@ -0,0 +1,174 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
import grpc
|
||||
import flatbuffers
|
||||
|
||||
from concurrent import futures
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'tests'))
|
||||
import MyGame.Example.Monster as Monster
|
||||
import MyGame.Example.Stat as Stat
|
||||
import MyGame.Example.Vec3 as Vec3
|
||||
import MyGame.Example.Test as Test
|
||||
import MyGame.Example.monster_test_grpc_fb as monster_grpc_fb
|
||||
|
||||
|
||||
test_stat_id = "test_stat_id"
|
||||
test_stat_val = 8
|
||||
test_stat_count = 1
|
||||
|
||||
test_monster_name1 = "test_monster_name1"
|
||||
test_monster_name2 = "test_monster_name2"
|
||||
test_string = "test_string"
|
||||
test_color = 2
|
||||
test_X = 3.0
|
||||
test_Y = 2.0
|
||||
test_Z = 6.0
|
||||
test_test1 = 4.0
|
||||
test_a = 8
|
||||
test_b = 5
|
||||
test_hp = 67
|
||||
test_inventory = [1, 1, 2, 3, 5, 8]
|
||||
test_testtype = 4
|
||||
|
||||
test_monsters_name_retrieve = ["big_monster", "small_monster"]
|
||||
test_no_of_monsters = 2
|
||||
|
||||
|
||||
class MonsterStorage(monster_grpc_fb.MonsterStorageServicer):
|
||||
|
||||
def Store(self, request, context):
|
||||
|
||||
m = Monster.Monster().GetRootAsMonster(request, 0)
|
||||
|
||||
assert m.Name().decode("utf-8") == test_monster_name1
|
||||
|
||||
assert m.Pos().X() == test_X
|
||||
assert m.Pos().Y() == test_Y
|
||||
assert m.Pos().Z() == test_Z
|
||||
assert m.Pos().Test1() == test_test1
|
||||
assert m.Pos().Test2() == test_color
|
||||
test3 = Test.Test()
|
||||
assert m.Pos().Test3(test3).A() == test_a
|
||||
assert m.Pos().Test3(test3).B() == test_b
|
||||
|
||||
assert m.Hp() == test_hp
|
||||
|
||||
assert m.Color() == test_color
|
||||
|
||||
assert m.InventoryLength() == len(test_inventory)
|
||||
for i in range(0, len(test_inventory)):
|
||||
assert m.Inventory(i) == test_inventory[len(test_inventory)-i -1]
|
||||
|
||||
assert m.TestType() == test_testtype
|
||||
|
||||
assert m.Test() is not None
|
||||
table = m.Test()
|
||||
|
||||
m2 = Monster.Monster()
|
||||
m2.Init(table.Bytes, table.Pos)
|
||||
assert m2.Name().decode("utf-8") == test_monster_name2
|
||||
|
||||
m3 = m.Enemy()
|
||||
assert m3.Name().decode("utf-8") == test_monster_name2
|
||||
|
||||
assert m.Testarrayofstring(0).decode("utf-8") == test_string
|
||||
|
||||
b = flatbuffers.Builder(0)
|
||||
i = b.CreateString(test_stat_id)
|
||||
Stat.StatStart(b)
|
||||
Stat.StatAddId(b, i)
|
||||
Stat.StatAddVal(b, test_stat_val)
|
||||
Stat.StatAddCount(b, test_stat_count)
|
||||
b.Finish(Stat.StatEnd(b))
|
||||
return bytes(b.Output())
|
||||
|
||||
def Retrieve(self, request, context):
|
||||
|
||||
s = Stat.Stat().GetRootAsStat(request, 0)
|
||||
|
||||
no_of_monsters = test_no_of_monsters
|
||||
for i in range(0, no_of_monsters):
|
||||
b = flatbuffers.Builder(0)
|
||||
i = b.CreateString(test_monsters_name_retrieve[i])
|
||||
Monster.MonsterStart(b)
|
||||
Monster.MonsterAddName(b, i)
|
||||
b.Finish(Monster.MonsterEnd(b))
|
||||
yield bytes(b.Output())
|
||||
|
||||
|
||||
def serve():
|
||||
|
||||
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
|
||||
monster_grpc_fb.add_MonsterStorageServicer_to_server(MonsterStorage(), server)
|
||||
server.add_insecure_port('[::]:50051')
|
||||
|
||||
server.start()
|
||||
|
||||
run()
|
||||
|
||||
|
||||
def run():
|
||||
|
||||
channel = grpc.insecure_channel('127.0.0.1:50051')
|
||||
stub = monster_grpc_fb.MonsterStorageStub(channel)
|
||||
|
||||
b = flatbuffers.Builder(0)
|
||||
name2 = b.CreateString(test_monster_name2)
|
||||
name1 = b.CreateString(test_monster_name1)
|
||||
Monster.MonsterStart(b)
|
||||
Monster.MonsterAddName(b, name2)
|
||||
monster2 = Monster.MonsterEnd(b)
|
||||
test1 = b.CreateString(test_string)
|
||||
|
||||
Monster.MonsterStartInventoryVector(b, len(test_inventory))
|
||||
for i in range(0, len(test_inventory)):
|
||||
b.PrependByte(test_inventory[i])
|
||||
inv = b.EndVector(len(test_inventory))
|
||||
|
||||
Monster.MonsterStartTest4Vector(b, 2)
|
||||
Test.CreateTest(b, 10, 20)
|
||||
Test.CreateTest(b, 30, 40)
|
||||
test4 = b.EndVector(2)
|
||||
|
||||
Monster.MonsterStartTestarrayofstringVector(b, 1)
|
||||
b.PrependUOffsetTRelative(test1)
|
||||
test_array_of_string = b.EndVector(1)
|
||||
|
||||
Monster.MonsterStart(b)
|
||||
|
||||
Monster.MonsterAddHp(b, test_hp)
|
||||
Monster.MonsterAddName(b, name1)
|
||||
Monster.MonsterAddColor(b, test_color)
|
||||
pos = Vec3.CreateVec3(b, test_X, test_Y, test_Z, test_test1, test_color, test_a, test_b)
|
||||
Monster.MonsterAddPos(b, pos)
|
||||
Monster.MonsterAddInventory(b, inv)
|
||||
Monster.MonsterAddTestType(b, test_testtype)
|
||||
Monster.MonsterAddTest(b, monster2)
|
||||
Monster.MonsterAddTest4(b, test4)
|
||||
Monster.MonsterAddEnemy(b, monster2)
|
||||
Monster.MonsterAddTestarrayofstring(b, test_array_of_string)
|
||||
monster = Monster.MonsterEnd(b)
|
||||
|
||||
b.Finish(monster)
|
||||
|
||||
stat_response = stub.Store(bytes(b.Output()))
|
||||
|
||||
s = Stat.Stat().GetRootAsStat(stat_response, 0)
|
||||
|
||||
assert s.Id().decode("utf-8") == test_stat_id
|
||||
assert s.Val() == test_stat_val
|
||||
assert s.Count() == test_stat_count
|
||||
|
||||
monster_reponses = stub.Retrieve(stat_response)
|
||||
count = 0
|
||||
for monster_reponse in monster_reponses:
|
||||
m = Monster.Monster().GetRootAsMonster(monster_reponse, 0)
|
||||
assert m.Name().decode("utf-8") == test_monsters_name_retrieve[count]
|
||||
count = count + 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
serve()
|
||||
@@ -3,22 +3,28 @@
|
||||
#include "test_assert.h"
|
||||
#include "test_builder.h"
|
||||
|
||||
using MyGame::Example::Vec3;
|
||||
using MyGame::Example::CreateStat;
|
||||
using MyGame::Example::Any_NONE;
|
||||
using MyGame::Example::CreateStat;
|
||||
using MyGame::Example::Vec3;
|
||||
|
||||
bool verify(flatbuffers::grpc::Message<Monster> &msg, const std::string &expected_name, Color color) {
|
||||
bool verify(flatbuffers::grpc::Message<Monster> &msg,
|
||||
const std::string &expected_name, Color expected_color) {
|
||||
const Monster *monster = msg.GetRoot();
|
||||
return (monster->name()->str() == expected_name) && (monster->color() == color);
|
||||
const auto name = monster->name()->str();
|
||||
const auto color = monster->color();
|
||||
TEST_EQ(name, expected_name);
|
||||
TEST_EQ(color, expected_color);
|
||||
return (name == expected_name) && (color == expected_color);
|
||||
}
|
||||
|
||||
bool release_n_verify(flatbuffers::grpc::MessageBuilder &mbb, const std::string &expected_name, Color color) {
|
||||
bool release_n_verify(flatbuffers::grpc::MessageBuilder &mbb,
|
||||
const std::string &expected_name, Color expected_color) {
|
||||
flatbuffers::grpc::Message<Monster> msg = mbb.ReleaseMessage<Monster>();
|
||||
const Monster *monster = msg.GetRoot();
|
||||
return (monster->name()->str() == expected_name) && (monster->color() == color);
|
||||
return verify(msg, expected_name, expected_color);
|
||||
}
|
||||
|
||||
void builder_move_assign_after_releaseraw_test(flatbuffers::grpc::MessageBuilder dst) {
|
||||
void builder_move_assign_after_releaseraw_test(
|
||||
flatbuffers::grpc::MessageBuilder dst) {
|
||||
auto root_offset1 = populate1(dst);
|
||||
dst.Finish(root_offset1);
|
||||
size_t size, offset;
|
||||
@@ -31,17 +37,16 @@ void builder_move_assign_after_releaseraw_test(flatbuffers::grpc::MessageBuilder
|
||||
// Move into a released builder.
|
||||
dst = std::move(src);
|
||||
TEST_EQ(dst.GetSize(), src_size);
|
||||
TEST_ASSERT(release_n_verify(dst, m2_name, m2_color));
|
||||
TEST_ASSERT(release_n_verify(dst, m2_name(), m2_color()));
|
||||
TEST_EQ(src.GetSize(), 0);
|
||||
grpc_slice_unref(slice);
|
||||
}
|
||||
|
||||
template <class SrcBuilder>
|
||||
template<class SrcBuilder>
|
||||
struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
|
||||
static void builder_reusable_after_release_message_test(TestSelector selector) {
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE)) {
|
||||
return;
|
||||
}
|
||||
static void builder_reusable_after_release_message_test(
|
||||
TestSelector selector) {
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE)) { return; }
|
||||
|
||||
flatbuffers::grpc::MessageBuilder mb;
|
||||
std::vector<flatbuffers::grpc::Message<Monster>> buffers;
|
||||
@@ -49,17 +54,15 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
|
||||
auto root_offset1 = populate1(mb);
|
||||
mb.Finish(root_offset1);
|
||||
buffers.push_back(mb.ReleaseMessage<Monster>());
|
||||
TEST_ASSERT_FUNC(verify(buffers[i], m1_name, m1_color));
|
||||
TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
|
||||
}
|
||||
}
|
||||
|
||||
static void builder_reusable_after_release_test(TestSelector selector) {
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE)) {
|
||||
return;
|
||||
}
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE)) { return; }
|
||||
|
||||
// FIXME: Populate-Release loop fails assert(GRPC_SLICE_IS_EMPTY(slice_)) in SliceAllocator::allocate
|
||||
// in the second iteration.
|
||||
// FIXME: Populate-Release loop fails assert(GRPC_SLICE_IS_EMPTY(slice_)) in
|
||||
// SliceAllocator::allocate in the second iteration.
|
||||
|
||||
flatbuffers::grpc::MessageBuilder mb;
|
||||
std::vector<flatbuffers::DetachedBuffer> buffers;
|
||||
@@ -67,14 +70,12 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
|
||||
auto root_offset1 = populate1(mb);
|
||||
mb.Finish(root_offset1);
|
||||
buffers.push_back(mb.Release());
|
||||
TEST_ASSERT_FUNC(verify(buffers[i], m1_name, m1_color));
|
||||
TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
|
||||
}
|
||||
}
|
||||
|
||||
static void builder_reusable_after_releaseraw_test(TestSelector selector) {
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) {
|
||||
return;
|
||||
}
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) { return; }
|
||||
|
||||
flatbuffers::grpc::MessageBuilder mb;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
@@ -83,18 +84,18 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
|
||||
size_t size, offset;
|
||||
grpc_slice slice;
|
||||
const uint8_t *buf = mb.ReleaseRaw(size, offset, slice);
|
||||
TEST_ASSERT_FUNC(verify(buf, offset, m1_name, m1_color));
|
||||
TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color()));
|
||||
grpc_slice_unref(slice);
|
||||
}
|
||||
}
|
||||
|
||||
static void builder_reusable_after_release_and_move_assign_test(TestSelector selector) {
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN)) {
|
||||
return;
|
||||
}
|
||||
static void builder_reusable_after_release_and_move_assign_test(
|
||||
TestSelector selector) {
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN)) { return; }
|
||||
|
||||
// FIXME: Release-move_assign loop fails assert(p == GRPC_SLICE_START_PTR(slice_))
|
||||
// in DetachedBuffer destructor after all the iterations
|
||||
// FIXME: Release-move_assign loop fails assert(p ==
|
||||
// GRPC_SLICE_START_PTR(slice_)) in DetachedBuffer destructor after all the
|
||||
// iterations
|
||||
|
||||
flatbuffers::grpc::MessageBuilder dst;
|
||||
std::vector<flatbuffers::DetachedBuffer> buffers;
|
||||
@@ -103,7 +104,7 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
|
||||
auto root_offset1 = populate1(dst);
|
||||
dst.Finish(root_offset1);
|
||||
buffers.push_back(dst.Release());
|
||||
TEST_ASSERT_FUNC(verify(buffers[i], m1_name, m1_color));
|
||||
TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
|
||||
|
||||
// bring dst back to life.
|
||||
SrcBuilder src;
|
||||
@@ -113,7 +114,8 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
|
||||
}
|
||||
}
|
||||
|
||||
static void builder_reusable_after_release_message_and_move_assign_test(TestSelector selector) {
|
||||
static void builder_reusable_after_release_message_and_move_assign_test(
|
||||
TestSelector selector) {
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN)) {
|
||||
return;
|
||||
}
|
||||
@@ -125,7 +127,7 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
|
||||
auto root_offset1 = populate1(dst);
|
||||
dst.Finish(root_offset1);
|
||||
buffers.push_back(dst.ReleaseMessage<Monster>());
|
||||
TEST_ASSERT_FUNC(verify(buffers[i], m1_name, m1_color));
|
||||
TEST_ASSERT_FUNC(verify(buffers[i], m1_name(), m1_color()));
|
||||
|
||||
// bring dst back to life.
|
||||
SrcBuilder src;
|
||||
@@ -135,10 +137,9 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
|
||||
}
|
||||
}
|
||||
|
||||
static void builder_reusable_after_releaseraw_and_move_assign_test(TestSelector selector) {
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN)) {
|
||||
return;
|
||||
}
|
||||
static void builder_reusable_after_releaseraw_and_move_assign_test(
|
||||
TestSelector selector) {
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN)) { return; }
|
||||
|
||||
flatbuffers::grpc::MessageBuilder dst;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
@@ -147,7 +148,7 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
|
||||
size_t size, offset;
|
||||
grpc_slice slice = grpc_empty_slice();
|
||||
const uint8_t *buf = dst.ReleaseRaw(size, offset, slice);
|
||||
TEST_ASSERT_FUNC(verify(buf, offset, m1_name, m1_color));
|
||||
TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color()));
|
||||
grpc_slice_unref(slice);
|
||||
|
||||
SrcBuilder src;
|
||||
@@ -175,11 +176,11 @@ void slice_allocator_tests() {
|
||||
uint8_t *buf = sa1.allocate(size);
|
||||
TEST_ASSERT_FUNC(buf != 0);
|
||||
buf[0] = 100;
|
||||
buf[size-1] = 200;
|
||||
buf[size - 1] = 200;
|
||||
flatbuffers::grpc::SliceAllocator sa2(std::move(sa1));
|
||||
// buf should not be deleted after move-construct
|
||||
TEST_EQ_FUNC(buf[0], 100);
|
||||
TEST_EQ_FUNC(buf[size-1], 200);
|
||||
TEST_EQ_FUNC(buf[size - 1], 200);
|
||||
// buf is freed here
|
||||
}
|
||||
|
||||
@@ -194,13 +195,16 @@ void slice_allocator_tests() {
|
||||
}
|
||||
}
|
||||
|
||||
/// This function does not populate exactly the first half of the table. But it could.
|
||||
void populate_first_half(MyGame::Example::MonsterBuilder &wrapper, flatbuffers::Offset<flatbuffers::String> name_offset) {
|
||||
/// This function does not populate exactly the first half of the table. But it
|
||||
/// could.
|
||||
void populate_first_half(MyGame::Example::MonsterBuilder &wrapper,
|
||||
flatbuffers::Offset<flatbuffers::String> name_offset) {
|
||||
wrapper.add_name(name_offset);
|
||||
wrapper.add_color(m1_color);
|
||||
wrapper.add_color(m1_color());
|
||||
}
|
||||
|
||||
/// This function does not populate exactly the second half of the table. But it could.
|
||||
/// This function does not populate exactly the second half of the table. But it
|
||||
/// could.
|
||||
void populate_second_half(MyGame::Example::MonsterBuilder &wrapper) {
|
||||
wrapper.add_hp(77);
|
||||
wrapper.add_mana(88);
|
||||
@@ -208,114 +212,138 @@ void populate_second_half(MyGame::Example::MonsterBuilder &wrapper) {
|
||||
wrapper.add_pos(&vec3);
|
||||
}
|
||||
|
||||
/// This function is a hack to update the FlatBufferBuilder reference (fbb_) in the MonsterBuilder object.
|
||||
/// This function will break if fbb_ is not the first member in MonsterBuilder. In that case, some offset must be added.
|
||||
/// This function is used exclusively for testing correctness of move operations between FlatBufferBuilders.
|
||||
/// If MonsterBuilder had a fbb_ pointer, this hack would be unnecessary. That involves a code-generator change though.
|
||||
void test_only_hack_update_fbb_reference(MyGame::Example::MonsterBuilder &monsterBuilder,
|
||||
flatbuffers::grpc::MessageBuilder &mb) {
|
||||
/// This function is a hack to update the FlatBufferBuilder reference (fbb_) in
|
||||
/// the MonsterBuilder object. This function will break if fbb_ is not the first
|
||||
/// member in MonsterBuilder. In that case, some offset must be added. This
|
||||
/// function is used exclusively for testing correctness of move operations
|
||||
/// between FlatBufferBuilders. If MonsterBuilder had a fbb_ pointer, this hack
|
||||
/// would be unnecessary. That involves a code-generator change though.
|
||||
void test_only_hack_update_fbb_reference(
|
||||
MyGame::Example::MonsterBuilder &monsterBuilder,
|
||||
flatbuffers::grpc::MessageBuilder &mb) {
|
||||
*reinterpret_cast<flatbuffers::FlatBufferBuilder **>(&monsterBuilder) = &mb;
|
||||
}
|
||||
|
||||
/// This test validates correctness of move conversion of FlatBufferBuilder to a MessageBuilder DURING
|
||||
/// a table construction. Half of the table is constructed using FlatBufferBuilder and the other half
|
||||
/// of the table is constructed using a MessageBuilder.
|
||||
/// This test validates correctness of move conversion of FlatBufferBuilder to a
|
||||
/// MessageBuilder DURING a table construction. Half of the table is constructed
|
||||
/// using FlatBufferBuilder and the other half of the table is constructed using
|
||||
/// a MessageBuilder.
|
||||
void builder_move_ctor_conversion_before_finish_half_n_half_table_test() {
|
||||
for (size_t initial_size = 4 ; initial_size <= 2048; initial_size *= 2) {
|
||||
for (size_t initial_size = 4; initial_size <= 2048; initial_size *= 2) {
|
||||
flatbuffers::FlatBufferBuilder fbb(initial_size);
|
||||
auto name_offset = fbb.CreateString(m1_name);
|
||||
MyGame::Example::MonsterBuilder monsterBuilder(fbb); // starts a table in FlatBufferBuilder
|
||||
auto name_offset = fbb.CreateString(m1_name());
|
||||
MyGame::Example::MonsterBuilder monsterBuilder(
|
||||
fbb); // starts a table in FlatBufferBuilder
|
||||
populate_first_half(monsterBuilder, name_offset);
|
||||
flatbuffers::grpc::MessageBuilder mb(std::move(fbb));
|
||||
test_only_hack_update_fbb_reference(monsterBuilder, mb); // hack
|
||||
test_only_hack_update_fbb_reference(monsterBuilder, mb); // hack
|
||||
populate_second_half(monsterBuilder);
|
||||
mb.Finish(monsterBuilder.Finish()); // ends the table in MessageBuilder
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color));
|
||||
mb.Finish(monsterBuilder.Finish()); // ends the table in MessageBuilder
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
|
||||
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// This test populates a COMPLETE inner table before move conversion and later populates more members in the outer table.
|
||||
/// This test populates a COMPLETE inner table before move conversion and later
|
||||
/// populates more members in the outer table.
|
||||
void builder_move_ctor_conversion_before_finish_test() {
|
||||
for (size_t initial_size = 4 ; initial_size <= 2048; initial_size *= 2) {
|
||||
for (size_t initial_size = 1; initial_size <= 2048; initial_size += 1) {
|
||||
flatbuffers::FlatBufferBuilder fbb(initial_size);
|
||||
auto stat_offset = CreateStat(fbb, fbb.CreateString("SomeId"), 0, 0);
|
||||
flatbuffers::grpc::MessageBuilder mb(std::move(fbb));
|
||||
auto monster_offset = CreateMonster(mb, 0, 150, 100, mb.CreateString(m1_name), 0, m1_color, Any_NONE, 0, 0, 0, 0, 0, 0, stat_offset);
|
||||
auto monster_offset =
|
||||
CreateMonster(mb, 0, 150, 100, mb.CreateString(m1_name()), 0,
|
||||
m1_color(), Any_NONE, 0, 0, 0, 0, 0, 0, stat_offset);
|
||||
mb.Finish(monster_offset);
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color));
|
||||
{
|
||||
auto mon = flatbuffers::GetRoot<Monster>(mb.GetBufferPointer());
|
||||
TEST_NOTNULL(mon);
|
||||
TEST_NOTNULL(mon->name());
|
||||
TEST_EQ_STR(mon->name()->c_str(), m1_name().c_str());
|
||||
TEST_EQ(mon->color(), m1_color());
|
||||
}
|
||||
TEST_EQ(1, MyGame::Example::Color_Red);
|
||||
TEST_EQ(1, m1_color());
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
|
||||
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// This test validates correctness of move conversion of FlatBufferBuilder to a MessageBuilder DURING
|
||||
/// a table construction. Half of the table is constructed using FlatBufferBuilder and the other half
|
||||
/// of the table is constructed using a MessageBuilder.
|
||||
/// This test validates correctness of move conversion of FlatBufferBuilder to a
|
||||
/// MessageBuilder DURING a table construction. Half of the table is constructed
|
||||
/// using FlatBufferBuilder and the other half of the table is constructed using
|
||||
/// a MessageBuilder.
|
||||
void builder_move_assign_conversion_before_finish_half_n_half_table_test() {
|
||||
flatbuffers::FlatBufferBuilder fbb;
|
||||
flatbuffers::grpc::MessageBuilder mb;
|
||||
|
||||
for (int i = 0;i < 5; ++i) {
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
flatbuffers::FlatBufferBuilder fbb;
|
||||
auto name_offset = fbb.CreateString(m1_name);
|
||||
MyGame::Example::MonsterBuilder monsterBuilder(fbb); // starts a table in FlatBufferBuilder
|
||||
auto name_offset = fbb.CreateString(m1_name());
|
||||
MyGame::Example::MonsterBuilder monsterBuilder(
|
||||
fbb); // starts a table in FlatBufferBuilder
|
||||
populate_first_half(monsterBuilder, name_offset);
|
||||
mb = std::move(fbb);
|
||||
test_only_hack_update_fbb_reference(monsterBuilder, mb); // hack
|
||||
test_only_hack_update_fbb_reference(monsterBuilder, mb); // hack
|
||||
populate_second_half(monsterBuilder);
|
||||
mb.Finish(monsterBuilder.Finish()); // ends the table in MessageBuilder
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color));
|
||||
mb.Finish(monsterBuilder.Finish()); // ends the table in MessageBuilder
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
|
||||
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// This test populates a COMPLETE inner table before move conversion and later populates more members in the outer table.
|
||||
/// This test populates a COMPLETE inner table before move conversion and later
|
||||
/// populates more members in the outer table.
|
||||
void builder_move_assign_conversion_before_finish_test() {
|
||||
flatbuffers::FlatBufferBuilder fbb;
|
||||
flatbuffers::grpc::MessageBuilder mb;
|
||||
|
||||
for (int i = 0;i < 5; ++i) {
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
auto stat_offset = CreateStat(fbb, fbb.CreateString("SomeId"), 0, 0);
|
||||
mb = std::move(fbb);
|
||||
auto monster_offset = CreateMonster(mb, 0, 150, 100, mb.CreateString(m1_name), 0, m1_color, Any_NONE, 0, 0, 0, 0, 0, 0, stat_offset);
|
||||
auto monster_offset =
|
||||
CreateMonster(mb, 0, 150, 100, mb.CreateString(m1_name()), 0,
|
||||
m1_color(), Any_NONE, 0, 0, 0, 0, 0, 0, stat_offset);
|
||||
mb.Finish(monster_offset);
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color));
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
|
||||
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// This test populates data, finishes the buffer, and does move conversion after.
|
||||
/// This test populates data, finishes the buffer, and does move conversion
|
||||
/// after.
|
||||
void builder_move_ctor_conversion_after_finish_test() {
|
||||
flatbuffers::FlatBufferBuilder fbb;
|
||||
fbb.Finish(populate1(fbb));
|
||||
flatbuffers::grpc::MessageBuilder mb(std::move(fbb));
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color));
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
|
||||
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||
}
|
||||
|
||||
/// This test populates data, finishes the buffer, and does move conversion after.
|
||||
/// This test populates data, finishes the buffer, and does move conversion
|
||||
/// after.
|
||||
void builder_move_assign_conversion_after_finish_test() {
|
||||
flatbuffers::FlatBufferBuilder fbb;
|
||||
flatbuffers::grpc::MessageBuilder mb;
|
||||
|
||||
for (int i = 0;i < 5; ++i) {
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
fbb.Finish(populate1(fbb));
|
||||
mb = std::move(fbb);
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color));
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
|
||||
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
void message_builder_tests() {
|
||||
using flatbuffers::grpc::MessageBuilder;
|
||||
using flatbuffers::FlatBufferBuilder;
|
||||
using flatbuffers::grpc::MessageBuilder;
|
||||
|
||||
slice_allocator_tests();
|
||||
|
||||
#ifndef __APPLE__
|
||||
builder_move_ctor_conversion_before_finish_half_n_half_table_test();
|
||||
builder_move_assign_conversion_before_finish_half_n_half_table_test();
|
||||
#endif // __APPLE__
|
||||
#endif // __APPLE__
|
||||
builder_move_ctor_conversion_before_finish_test();
|
||||
builder_move_assign_conversion_before_finish_test();
|
||||
|
||||
@@ -326,15 +354,18 @@ void message_builder_tests() {
|
||||
BuilderTests<MessageBuilder, FlatBufferBuilder>::all_tests();
|
||||
|
||||
BuilderReuseTestSelector tests[6] = {
|
||||
//REUSABLE_AFTER_RELEASE, // Assertion failed: (GRPC_SLICE_IS_EMPTY(slice_))
|
||||
//REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN, // Assertion failed: (p == GRPC_SLICE_START_PTR(slice_)
|
||||
// REUSABLE_AFTER_RELEASE, // Assertion failed:
|
||||
// (GRPC_SLICE_IS_EMPTY(slice_))
|
||||
// REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN, // Assertion failed: (p ==
|
||||
// GRPC_SLICE_START_PTR(slice_)
|
||||
|
||||
REUSABLE_AFTER_RELEASE_RAW,
|
||||
REUSABLE_AFTER_RELEASE_MESSAGE,
|
||||
REUSABLE_AFTER_RELEASE_RAW, REUSABLE_AFTER_RELEASE_MESSAGE,
|
||||
REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN,
|
||||
REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN
|
||||
};
|
||||
|
||||
BuilderReuseTests<MessageBuilder, MessageBuilder>::run_tests(TestSelector(tests, tests+6));
|
||||
BuilderReuseTests<MessageBuilder, FlatBufferBuilder>::run_tests(TestSelector(tests, tests+6));
|
||||
BuilderReuseTests<MessageBuilder, MessageBuilder>::run_tests(
|
||||
TestSelector(tests, tests + 6));
|
||||
BuilderReuseTests<MessageBuilder, FlatBufferBuilder>::run_tests(
|
||||
TestSelector(tests, tests + 6));
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
<parent>
|
||||
<groupId>com.google.flatbuffers</groupId>
|
||||
<artifactId>flatbuffers-parent</artifactId>
|
||||
<version>1.11.0</version>
|
||||
<version>1.12.0</version>
|
||||
</parent>
|
||||
<artifactId>grpc-test</artifactId>
|
||||
<description>Example/Test project demonstrating usage of flatbuffers with GRPC-Java instead of protobufs
|
||||
</description>
|
||||
<properties>
|
||||
<gRPC.version>1.11.0</gRPC.version>
|
||||
<gRPC.version>1.12.0</gRPC.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@@ -55,6 +55,10 @@
|
||||
|
||||
#include "flatbuffers/stl_emulation.h"
|
||||
|
||||
#if defined(__ICCARM__)
|
||||
#include <intrinsics.h>
|
||||
#endif
|
||||
|
||||
// Note the __clang__ check is needed, because clang presents itself
|
||||
// as an older GNUC compiler (4.2).
|
||||
// Clang 3.3 and later implement all of the ISO C++ 2011 standard.
|
||||
@@ -95,7 +99,7 @@
|
||||
#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
|
||||
// Backwards compatibility 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
|
||||
@@ -117,7 +121,7 @@
|
||||
#define FLATBUFFERS_LITTLEENDIAN 0
|
||||
#endif // __s390x__
|
||||
#if !defined(FLATBUFFERS_LITTLEENDIAN)
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
|
||||
#if (defined(__BIG_ENDIAN__) || \
|
||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||
#define FLATBUFFERS_LITTLEENDIAN 0
|
||||
@@ -136,10 +140,14 @@
|
||||
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
|
||||
|
||||
#define FLATBUFFERS_VERSION_MAJOR 1
|
||||
#define FLATBUFFERS_VERSION_MINOR 11
|
||||
#define FLATBUFFERS_VERSION_MINOR 12
|
||||
#define FLATBUFFERS_VERSION_REVISION 0
|
||||
#define FLATBUFFERS_STRING_EXPAND(X) #X
|
||||
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
|
||||
namespace flatbuffers {
|
||||
// Returns version as string "MAJOR.MINOR.REVISION".
|
||||
const char* FLATBUFFERS_VERSION();
|
||||
}
|
||||
|
||||
#if (!defined(_MSC_VER) || _MSC_VER > 1600) && \
|
||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407)) || \
|
||||
@@ -191,7 +199,7 @@
|
||||
// to detect a header that provides an implementation
|
||||
#if defined(__has_include)
|
||||
// Check for std::string_view (in c++17)
|
||||
#if __has_include(<string_view>) && (__cplusplus >= 201606 || _HAS_CXX17)
|
||||
#if __has_include(<string_view>) && (__cplusplus >= 201606 || (defined(_HAS_CXX17) && _HAS_CXX17))
|
||||
#include <string_view>
|
||||
namespace flatbuffers {
|
||||
typedef std::string_view string_view;
|
||||
@@ -204,6 +212,13 @@
|
||||
typedef std::experimental::string_view string_view;
|
||||
}
|
||||
#define FLATBUFFERS_HAS_STRING_VIEW 1
|
||||
// Check for absl::string_view
|
||||
#elif __has_include("absl/strings/string_view.h")
|
||||
#include "absl/strings/string_view.h"
|
||||
namespace flatbuffers {
|
||||
typedef absl::string_view string_view;
|
||||
}
|
||||
#define FLATBUFFERS_HAS_STRING_VIEW 1
|
||||
#endif
|
||||
#endif // __has_include
|
||||
#endif // !FLATBUFFERS_HAS_STRING_VIEW
|
||||
@@ -234,7 +249,7 @@
|
||||
// Suppress Undefined Behavior Sanitizer (recoverable only). Usage:
|
||||
// - __supress_ubsan__("undefined")
|
||||
// - __supress_ubsan__("signed-integer-overflow")
|
||||
#if defined(__clang__)
|
||||
#if defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7))
|
||||
#define __supress_ubsan__(type) __attribute__((no_sanitize(type)))
|
||||
#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
|
||||
#define __supress_ubsan__(type) __attribute__((no_sanitize_undefined))
|
||||
@@ -288,7 +303,7 @@ 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)
|
||||
#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(::flatbuffers::soffset_t) * 8 - 1)) - 1)
|
||||
|
||||
// We support aligning the contents of buffers up to this size.
|
||||
#define FLATBUFFERS_MAX_ALIGNMENT 16
|
||||
@@ -303,6 +318,11 @@ template<typename T> T EndianSwap(T t) {
|
||||
#define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
|
||||
#define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
|
||||
#define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
|
||||
#elif defined(__ICCARM__)
|
||||
#define FLATBUFFERS_BYTESWAP16 __REV16
|
||||
#define FLATBUFFERS_BYTESWAP32 __REV
|
||||
#define FLATBUFFERS_BYTESWAP64(x) \
|
||||
((__REV(static_cast<uint32_t>(x >> 32U))) | (static_cast<uint64_t>(__REV(static_cast<uint32_t>(x)))) << 32U)
|
||||
#else
|
||||
#if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__)
|
||||
// __builtin_bswap16 was missing prior to GCC 4.8.
|
||||
@@ -317,22 +337,20 @@ template<typename T> T EndianSwap(T t) {
|
||||
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;
|
||||
union { T t; uint16_t i; } u = { 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;
|
||||
union { T t; uint32_t i; } u = { 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;
|
||||
union { T t; uint64_t i; } u = { t };
|
||||
u.i = FLATBUFFERS_BYTESWAP64(u.i);
|
||||
return u.t;
|
||||
} else {
|
||||
FLATBUFFERS_ASSERT(0);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,6 +389,7 @@ template<typename T> __supress_ubsan__("alignment") void WriteScalar(void *p, Of
|
||||
// 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).
|
||||
__supress_ubsan__("unsigned-integer-overflow")
|
||||
inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
|
||||
return ((~buf_size) + 1) & (scalar_size - 1);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
||||
#include "flatbuffers/idl.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
@@ -26,7 +27,7 @@ namespace flatbuffers {
|
||||
// Utility class to assist in generating code through use of text templates.
|
||||
//
|
||||
// Example code:
|
||||
// CodeWriter code;
|
||||
// CodeWriter code("\t");
|
||||
// code.SetValue("NAME", "Foo");
|
||||
// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
|
||||
// code.SetValue("NAME", "Bar");
|
||||
@@ -38,7 +39,8 @@ namespace flatbuffers {
|
||||
// void Bar() { printf("%s", "Bar"); }
|
||||
class CodeWriter {
|
||||
public:
|
||||
CodeWriter() {}
|
||||
CodeWriter(std::string pad = std::string())
|
||||
: pad_(pad), cur_ident_lvl_(0), ignore_ident_(false) {}
|
||||
|
||||
// Clears the current "written" code.
|
||||
void Clear() {
|
||||
@@ -53,6 +55,11 @@ class CodeWriter {
|
||||
value_map_[key] = value;
|
||||
}
|
||||
|
||||
std::string GetValue(const std::string &key) const {
|
||||
const auto it = value_map_.find(key);
|
||||
return it == value_map_.end() ? "" : it->second;
|
||||
}
|
||||
|
||||
// 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
|
||||
@@ -62,9 +69,22 @@ class CodeWriter {
|
||||
// Returns the current contents of the CodeWriter as a std::string.
|
||||
std::string ToString() const { return stream_.str(); }
|
||||
|
||||
// Increase ident level for writing code
|
||||
void IncrementIdentLevel() { cur_ident_lvl_++; }
|
||||
// Decrease ident level for writing code
|
||||
void DecrementIdentLevel() {
|
||||
if (cur_ident_lvl_) cur_ident_lvl_--;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> value_map_;
|
||||
std::stringstream stream_;
|
||||
std::string pad_;
|
||||
int cur_ident_lvl_;
|
||||
bool ignore_ident_;
|
||||
|
||||
// Add ident padding (tab or space) based on ident level
|
||||
void AppendIdent(std::stringstream &stream);
|
||||
};
|
||||
|
||||
class BaseGenerator {
|
||||
@@ -74,16 +94,20 @@ class BaseGenerator {
|
||||
static std::string NamespaceDir(const Parser &parser, const std::string &path,
|
||||
const Namespace &ns);
|
||||
|
||||
std::string GeneratedFileName(const std::string &path,
|
||||
const std::string &file_name,
|
||||
const IDLOptions &options) const;
|
||||
|
||||
protected:
|
||||
BaseGenerator(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name,
|
||||
const std::string qualifying_start,
|
||||
const std::string qualifying_separator)
|
||||
const std::string &file_name, std::string qualifying_start,
|
||||
std::string qualifying_separator, std::string default_extension)
|
||||
: parser_(parser),
|
||||
path_(path),
|
||||
file_name_(file_name),
|
||||
qualifying_start_(qualifying_start),
|
||||
qualifying_separator_(qualifying_separator) {}
|
||||
qualifying_separator_(qualifying_separator),
|
||||
default_extension_(default_extension) {}
|
||||
virtual ~BaseGenerator() {}
|
||||
|
||||
// No copy/assign.
|
||||
@@ -104,8 +128,9 @@ class BaseGenerator {
|
||||
// which works for js and php
|
||||
virtual const Namespace *CurrentNameSpace() const { return nullptr; }
|
||||
|
||||
// Ensure that a type is prefixed with its namespace whenever it is used
|
||||
// outside of its namespace.
|
||||
// Ensure that a type is prefixed with its namespace even within
|
||||
// its own namespace to avoid conflict between generated method
|
||||
// names and similarly named classes or structs
|
||||
std::string WrapInNameSpace(const Namespace *ns,
|
||||
const std::string &name) const;
|
||||
|
||||
@@ -118,6 +143,7 @@ class BaseGenerator {
|
||||
const std::string &file_name_;
|
||||
const std::string qualifying_start_;
|
||||
const std::string qualifying_separator_;
|
||||
const std::string default_extension_;
|
||||
};
|
||||
|
||||
struct CommentConfig {
|
||||
|
||||
@@ -20,24 +20,43 @@
|
||||
#include "flatbuffers/base.h"
|
||||
|
||||
#if defined(FLATBUFFERS_NAN_DEFAULTS)
|
||||
#include <cmath>
|
||||
# include <cmath>
|
||||
#endif
|
||||
|
||||
namespace flatbuffers {
|
||||
// Generic 'operator==' with conditional specialisations.
|
||||
// T e - new value of a scalar field.
|
||||
// T def - default of scalar (is known at compile-time).
|
||||
template<typename T> inline bool IsTheSameAs(T e, T def) { return e == def; }
|
||||
|
||||
#if defined(FLATBUFFERS_NAN_DEFAULTS) && \
|
||||
(!defined(_MSC_VER) || _MSC_VER >= 1800)
|
||||
defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
|
||||
// Like `operator==(e, def)` with weak NaN if T=(float|double).
|
||||
template<typename T> inline bool IsFloatTheSameAs(T e, T def) {
|
||||
return (e == def) || ((def != def) && (e != e));
|
||||
}
|
||||
template<> inline bool IsTheSameAs<float>(float e, float def) {
|
||||
return (e == def) || (std::isnan(def) && std::isnan(e));
|
||||
return IsFloatTheSameAs(e, def);
|
||||
}
|
||||
template<> inline bool IsTheSameAs<double>(double e, double def) {
|
||||
return (e == def) || (std::isnan(def) && std::isnan(e));
|
||||
return IsFloatTheSameAs(e, def);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check 'v' is out of closed range [low; high].
|
||||
// Workaround for GCC warning [-Werror=type-limits]:
|
||||
// comparison is always true due to limited range of data type.
|
||||
template<typename T>
|
||||
inline bool IsOutRange(const T &v, const T &low, const T &high) {
|
||||
return (v < low) || (high < v);
|
||||
}
|
||||
|
||||
// Check 'v' is in closed range [low; high].
|
||||
template<typename T>
|
||||
inline bool IsInRange(const T &v, const T &low, const T &high) {
|
||||
return !IsOutRange(v, low, high);
|
||||
}
|
||||
|
||||
// Wrapper for uoffset_t to allow safe template specialization.
|
||||
// Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
|
||||
template<typename T> struct Offset {
|
||||
@@ -198,17 +217,18 @@ template<typename T, typename IT> struct VectorIterator {
|
||||
const uint8_t *data_;
|
||||
};
|
||||
|
||||
template<typename Iterator> struct VectorReverseIterator :
|
||||
public std::reverse_iterator<Iterator> {
|
||||
template<typename Iterator>
|
||||
struct VectorReverseIterator : public std::reverse_iterator<Iterator> {
|
||||
explicit VectorReverseIterator(Iterator iter)
|
||||
: std::reverse_iterator<Iterator>(iter) {}
|
||||
|
||||
explicit VectorReverseIterator(Iterator iter) : iter_(iter) {}
|
||||
typename Iterator::value_type operator*() const {
|
||||
return *(std::reverse_iterator<Iterator>::current);
|
||||
}
|
||||
|
||||
typename Iterator::value_type operator*() const { return *(iter_ - 1); }
|
||||
|
||||
typename Iterator::value_type operator->() const { return *(iter_ - 1); }
|
||||
|
||||
private:
|
||||
Iterator iter_;
|
||||
typename Iterator::value_type operator->() const {
|
||||
return *(std::reverse_iterator<Iterator>::current);
|
||||
}
|
||||
};
|
||||
|
||||
struct String;
|
||||
@@ -269,11 +289,15 @@ template<typename T> class Vector {
|
||||
iterator end() { return iterator(Data(), size()); }
|
||||
const_iterator end() const { return const_iterator(Data(), size()); }
|
||||
|
||||
reverse_iterator rbegin() { return reverse_iterator(end()); }
|
||||
const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
|
||||
reverse_iterator rbegin() { return reverse_iterator(end() - 1); }
|
||||
const_reverse_iterator rbegin() const {
|
||||
return const_reverse_iterator(end() - 1);
|
||||
}
|
||||
|
||||
reverse_iterator rend() { return reverse_iterator(end()); }
|
||||
const_reverse_iterator rend() const { return const_reverse_iterator(end()); }
|
||||
reverse_iterator rend() { return reverse_iterator(begin() - 1); }
|
||||
const_reverse_iterator rend() const {
|
||||
return const_reverse_iterator(begin() - 1);
|
||||
}
|
||||
|
||||
const_iterator cbegin() const { return begin(); }
|
||||
|
||||
@@ -341,6 +365,7 @@ template<typename T> class Vector {
|
||||
// This class is a pointer. Copying will therefore create an invalid object.
|
||||
// Private and unimplemented copy constructor.
|
||||
Vector(const Vector &);
|
||||
Vector &operator=(const Vector &);
|
||||
|
||||
template<typename K> static int KeyCompare(const void *ap, const void *bp) {
|
||||
const K *key = reinterpret_cast<const K *>(ap);
|
||||
@@ -371,6 +396,7 @@ class VectorOfAny {
|
||||
|
||||
private:
|
||||
VectorOfAny(const VectorOfAny &);
|
||||
VectorOfAny &operator=(const VectorOfAny &);
|
||||
};
|
||||
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
@@ -393,6 +419,131 @@ template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
|
||||
return v ? v->size() : 0;
|
||||
}
|
||||
|
||||
// This is used as a helper type for accessing arrays.
|
||||
template<typename T, uint16_t length> class Array {
|
||||
typedef
|
||||
typename flatbuffers::integral_constant<bool,
|
||||
flatbuffers::is_scalar<T>::value>
|
||||
scalar_tag;
|
||||
typedef
|
||||
typename flatbuffers::conditional<scalar_tag::value, T, const T *>::type
|
||||
IndirectHelperType;
|
||||
|
||||
public:
|
||||
typedef typename IndirectHelper<IndirectHelperType>::return_type return_type;
|
||||
typedef VectorIterator<T, return_type> const_iterator;
|
||||
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
|
||||
|
||||
FLATBUFFERS_CONSTEXPR uint16_t size() const { return length; }
|
||||
|
||||
return_type Get(uoffset_t i) const {
|
||||
FLATBUFFERS_ASSERT(i < size());
|
||||
return IndirectHelper<IndirectHelperType>::Read(Data(), i);
|
||||
}
|
||||
|
||||
return_type operator[](uoffset_t i) const { return Get(i); }
|
||||
|
||||
// If this is a Vector of enums, T will be its storage type, not the enum
|
||||
// type. This function makes it convenient to retrieve value with enum
|
||||
// type E.
|
||||
template<typename E> E GetEnum(uoffset_t i) const {
|
||||
return static_cast<E>(Get(i));
|
||||
}
|
||||
|
||||
const_iterator begin() const { return const_iterator(Data(), 0); }
|
||||
const_iterator end() const { return const_iterator(Data(), size()); }
|
||||
|
||||
const_reverse_iterator rbegin() const {
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
const_reverse_iterator rend() const { return const_reverse_iterator(end()); }
|
||||
|
||||
const_iterator cbegin() const { return begin(); }
|
||||
const_iterator cend() const { return end(); }
|
||||
|
||||
const_reverse_iterator crbegin() const { return rbegin(); }
|
||||
const_reverse_iterator crend() const { return rend(); }
|
||||
|
||||
// Get a mutable pointer to elements inside this array.
|
||||
// This method used to mutate arrays of structs followed by a @p Mutate
|
||||
// operation. For primitive types use @p Mutate directly.
|
||||
// @warning Assignments and reads to/from the dereferenced pointer are not
|
||||
// automatically converted to the correct endianness.
|
||||
typename flatbuffers::conditional<scalar_tag::value, void, T *>::type
|
||||
GetMutablePointer(uoffset_t i) const {
|
||||
FLATBUFFERS_ASSERT(i < size());
|
||||
return const_cast<T *>(&data()[i]);
|
||||
}
|
||||
|
||||
// Change elements if you have a non-const pointer to this object.
|
||||
void Mutate(uoffset_t i, const T &val) { MutateImpl(scalar_tag(), i, val); }
|
||||
|
||||
// The raw data in little endian format. Use with care.
|
||||
const uint8_t *Data() const { return data_; }
|
||||
|
||||
uint8_t *Data() { return data_; }
|
||||
|
||||
// Similarly, but typed, much like std::vector::data
|
||||
const T *data() const { return reinterpret_cast<const T *>(Data()); }
|
||||
T *data() { return reinterpret_cast<T *>(Data()); }
|
||||
|
||||
protected:
|
||||
void MutateImpl(flatbuffers::integral_constant<bool, true>, uoffset_t i,
|
||||
const T &val) {
|
||||
FLATBUFFERS_ASSERT(i < size());
|
||||
WriteScalar(data() + i, val);
|
||||
}
|
||||
|
||||
void MutateImpl(flatbuffers::integral_constant<bool, false>, uoffset_t i,
|
||||
const T &val) {
|
||||
*(GetMutablePointer(i)) = val;
|
||||
}
|
||||
|
||||
// This class is only used to access pre-existing data. Don't ever
|
||||
// try to construct these manually.
|
||||
// 'constexpr' allows us to use 'size()' at compile time.
|
||||
// @note Must not use 'FLATBUFFERS_CONSTEXPR' here, as const is not allowed on
|
||||
// a constructor.
|
||||
#if defined(__cpp_constexpr)
|
||||
constexpr Array();
|
||||
#else
|
||||
Array();
|
||||
#endif
|
||||
|
||||
uint8_t data_[length * sizeof(T)];
|
||||
|
||||
private:
|
||||
// This class is a pointer. Copying will therefore create an invalid object.
|
||||
// Private and unimplemented copy constructor.
|
||||
Array(const Array &);
|
||||
Array &operator=(const Array &);
|
||||
};
|
||||
|
||||
// Specialization for Array[struct] with access using Offset<void> pointer.
|
||||
// This specialization used by idl_gen_text.cpp.
|
||||
template<typename T, uint16_t length> class Array<Offset<T>, length> {
|
||||
static_assert(flatbuffers::is_same<T, void>::value, "unexpected type T");
|
||||
|
||||
public:
|
||||
typedef const void *return_type;
|
||||
|
||||
const uint8_t *Data() const { return data_; }
|
||||
|
||||
// Make idl_gen_text.cpp::PrintContainer happy.
|
||||
return_type operator[](uoffset_t) const {
|
||||
FLATBUFFERS_ASSERT(false);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
// This class is only used to access pre-existing data.
|
||||
Array();
|
||||
Array(const Array &);
|
||||
Array &operator=(const Array &);
|
||||
|
||||
uint8_t data_[1];
|
||||
};
|
||||
|
||||
// Lexicographically compare two strings (possibly containing nulls), and
|
||||
// return true if the first is less than the second.
|
||||
static inline bool StringLessThan(const char *a_data, uoffset_t a_size,
|
||||
@@ -420,13 +571,13 @@ struct String : public Vector<char> {
|
||||
|
||||
// Convenience function to get std::string from a String returning an empty
|
||||
// string on null pointer.
|
||||
static inline std::string GetString(const String * str) {
|
||||
static inline std::string GetString(const String *str) {
|
||||
return str ? str->str() : "";
|
||||
}
|
||||
|
||||
// Convenience function to get char* from a String returning an empty string on
|
||||
// null pointer.
|
||||
static inline const char * GetCstring(const String * str) {
|
||||
static inline const char *GetCstring(const String *str) {
|
||||
return str ? str->c_str() : "";
|
||||
}
|
||||
|
||||
@@ -463,9 +614,9 @@ class Allocator {
|
||||
// to `new_p` of `new_size`. Only memory of size `in_use_front` and
|
||||
// `in_use_back` will be copied from the front and back of the old memory
|
||||
// allocation.
|
||||
void memcpy_downward(uint8_t *old_p, size_t old_size,
|
||||
uint8_t *new_p, size_t new_size,
|
||||
size_t in_use_back, size_t in_use_front) {
|
||||
void memcpy_downward(uint8_t *old_p, size_t old_size, uint8_t *new_p,
|
||||
size_t new_size, size_t in_use_back,
|
||||
size_t in_use_front) {
|
||||
memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back,
|
||||
in_use_back);
|
||||
memcpy(new_p, old_p, in_use_front);
|
||||
@@ -479,13 +630,9 @@ class DefaultAllocator : public Allocator {
|
||||
return new uint8_t[size];
|
||||
}
|
||||
|
||||
void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE {
|
||||
delete[] p;
|
||||
}
|
||||
void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE { delete[] p; }
|
||||
|
||||
static void dealloc(void *p, size_t) {
|
||||
delete[] static_cast<uint8_t *>(p);
|
||||
}
|
||||
static void dealloc(void *p, size_t) { delete[] static_cast<uint8_t *>(p); }
|
||||
};
|
||||
|
||||
// These functions allow for a null allocator to mean use the default allocator,
|
||||
@@ -498,18 +645,19 @@ inline uint8_t *Allocate(Allocator *allocator, size_t size) {
|
||||
}
|
||||
|
||||
inline void Deallocate(Allocator *allocator, uint8_t *p, size_t size) {
|
||||
if (allocator) allocator->deallocate(p, size);
|
||||
else DefaultAllocator().deallocate(p, size);
|
||||
if (allocator)
|
||||
allocator->deallocate(p, size);
|
||||
else
|
||||
DefaultAllocator().deallocate(p, size);
|
||||
}
|
||||
|
||||
inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p,
|
||||
size_t old_size, size_t new_size,
|
||||
size_t in_use_back, size_t in_use_front) {
|
||||
return allocator
|
||||
? allocator->reallocate_downward(old_p, old_size, new_size,
|
||||
in_use_back, in_use_front)
|
||||
: DefaultAllocator().reallocate_downward(old_p, old_size, new_size,
|
||||
in_use_back, in_use_front);
|
||||
return allocator ? allocator->reallocate_downward(old_p, old_size, new_size,
|
||||
in_use_back, in_use_front)
|
||||
: DefaultAllocator().reallocate_downward(
|
||||
old_p, old_size, new_size, in_use_back, in_use_front);
|
||||
}
|
||||
|
||||
// DetachedBuffer is a finished flatbuffer memory region, detached from its
|
||||
@@ -554,6 +702,8 @@ class DetachedBuffer {
|
||||
#if !defined(FLATBUFFERS_CPP98_STL)
|
||||
// clang-format on
|
||||
DetachedBuffer &operator=(DetachedBuffer &&other) {
|
||||
if (this == &other) return *this;
|
||||
|
||||
destroy();
|
||||
|
||||
allocator_ = other.allocator_;
|
||||
@@ -610,7 +760,7 @@ class DetachedBuffer {
|
||||
#endif // !defined(FLATBUFFERS_CPP98_STL)
|
||||
// clang-format on
|
||||
|
||||
protected:
|
||||
protected:
|
||||
Allocator *allocator_;
|
||||
bool own_allocator_;
|
||||
uint8_t *buf_;
|
||||
@@ -642,10 +792,8 @@ protected:
|
||||
// Essentially, this supports 2 std::vectors in a single buffer.
|
||||
class vector_downward {
|
||||
public:
|
||||
explicit vector_downward(size_t initial_size,
|
||||
Allocator *allocator,
|
||||
bool own_allocator,
|
||||
size_t buffer_minalign)
|
||||
explicit vector_downward(size_t initial_size, Allocator *allocator,
|
||||
bool own_allocator, size_t buffer_minalign)
|
||||
: allocator_(allocator),
|
||||
own_allocator_(own_allocator),
|
||||
initial_size_(initial_size),
|
||||
@@ -661,15 +809,15 @@ class vector_downward {
|
||||
#else
|
||||
vector_downward(vector_downward &other)
|
||||
#endif // defined(FLATBUFFERS_CPP98_STL)
|
||||
// clang-format on
|
||||
: allocator_(other.allocator_),
|
||||
own_allocator_(other.own_allocator_),
|
||||
initial_size_(other.initial_size_),
|
||||
buffer_minalign_(other.buffer_minalign_),
|
||||
reserved_(other.reserved_),
|
||||
buf_(other.buf_),
|
||||
cur_(other.cur_),
|
||||
scratch_(other.scratch_) {
|
||||
// clang-format on
|
||||
: allocator_(other.allocator_),
|
||||
own_allocator_(other.own_allocator_),
|
||||
initial_size_(other.initial_size_),
|
||||
buffer_minalign_(other.buffer_minalign_),
|
||||
reserved_(other.reserved_),
|
||||
buf_(other.buf_),
|
||||
cur_(other.cur_),
|
||||
scratch_(other.scratch_) {
|
||||
// No change in other.allocator_
|
||||
// No change in other.initial_size_
|
||||
// No change in other.buffer_minalign_
|
||||
@@ -713,9 +861,7 @@ class vector_downward {
|
||||
clear_scratch();
|
||||
}
|
||||
|
||||
void clear_scratch() {
|
||||
scratch_ = buf_;
|
||||
}
|
||||
void clear_scratch() { scratch_ = buf_; }
|
||||
|
||||
void clear_allocator() {
|
||||
if (own_allocator_ && allocator_) { delete allocator_; }
|
||||
@@ -801,7 +947,7 @@ class vector_downward {
|
||||
uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; }
|
||||
|
||||
void push(const uint8_t *bytes, size_t num) {
|
||||
memcpy(make_space(num), bytes, num);
|
||||
if (num > 0) { memcpy(make_space(num), bytes, num); }
|
||||
}
|
||||
|
||||
// Specialized version of push() that avoids memcpy call for small data.
|
||||
@@ -824,6 +970,7 @@ class vector_downward {
|
||||
}
|
||||
|
||||
// Version for when we know the size is larger.
|
||||
// Precondition: zero_pad_bytes > 0
|
||||
void fill_big(size_t zero_pad_bytes) {
|
||||
memset(make_space(zero_pad_bytes), 0, zero_pad_bytes);
|
||||
}
|
||||
@@ -867,8 +1014,8 @@ class vector_downward {
|
||||
auto old_reserved = reserved_;
|
||||
auto old_size = size();
|
||||
auto old_scratch_size = scratch_size();
|
||||
reserved_ += (std::max)(len,
|
||||
old_reserved ? old_reserved / 2 : initial_size_);
|
||||
reserved_ +=
|
||||
(std::max)(len, old_reserved ? old_reserved / 2 : initial_size_);
|
||||
reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1);
|
||||
if (buf_) {
|
||||
buf_ = ReallocateDownward(allocator_, buf_, old_reserved, reserved_,
|
||||
@@ -890,10 +1037,16 @@ inline voffset_t FieldIndexToOffset(voffset_t field_id) {
|
||||
|
||||
template<typename T, typename Alloc>
|
||||
const T *data(const std::vector<T, Alloc> &v) {
|
||||
return v.empty() ? nullptr : &v.front();
|
||||
// Eventually the returned pointer gets passed down to memcpy, so
|
||||
// we need it to be non-null to avoid undefined behavior.
|
||||
static uint8_t t;
|
||||
return v.empty() ? reinterpret_cast<const T *>(&t) : &v.front();
|
||||
}
|
||||
template<typename T, typename Alloc> T *data(std::vector<T, Alloc> &v) {
|
||||
return v.empty() ? nullptr : &v.front();
|
||||
// Eventually the returned pointer gets passed down to memcpy, so
|
||||
// we need it to be non-null to avoid undefined behavior.
|
||||
static uint8_t t;
|
||||
return v.empty() ? reinterpret_cast<T *>(&t) : &v.front();
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
@@ -920,11 +1073,10 @@ class FlatBufferBuilder {
|
||||
/// minimum alignment upon reallocation. Only needed if you intend to store
|
||||
/// types with custom alignment AND you wish to read the buffer in-place
|
||||
/// directly after creation.
|
||||
explicit FlatBufferBuilder(size_t initial_size = 1024,
|
||||
Allocator *allocator = nullptr,
|
||||
bool own_allocator = false,
|
||||
size_t buffer_minalign =
|
||||
AlignOf<largest_scalar_t>())
|
||||
explicit FlatBufferBuilder(
|
||||
size_t initial_size = 1024, Allocator *allocator = nullptr,
|
||||
bool own_allocator = false,
|
||||
size_t buffer_minalign = AlignOf<largest_scalar_t>())
|
||||
: buf_(initial_size, allocator, own_allocator, buffer_minalign),
|
||||
num_field_loc(0),
|
||||
max_voffset_(0),
|
||||
@@ -1027,8 +1179,8 @@ class FlatBufferBuilder {
|
||||
/// @warning Do NOT attempt to use this FlatBufferBuilder afterwards!
|
||||
/// @return A `FlatBuffer` that owns the buffer and its allocator and
|
||||
/// behaves similar to a `unique_ptr` with a deleter.
|
||||
FLATBUFFERS_ATTRIBUTE(deprecated("use Release() instead")) DetachedBuffer
|
||||
ReleaseBufferPointer() {
|
||||
FLATBUFFERS_ATTRIBUTE(deprecated("use Release() instead"))
|
||||
DetachedBuffer ReleaseBufferPointer() {
|
||||
Finished();
|
||||
return buf_.release();
|
||||
}
|
||||
@@ -1041,13 +1193,14 @@ class FlatBufferBuilder {
|
||||
}
|
||||
|
||||
/// @brief Get the released pointer to the serialized buffer.
|
||||
/// @param The size of the memory block containing
|
||||
/// @param size The size of the memory block containing
|
||||
/// the serialized `FlatBuffer`.
|
||||
/// @param The offset from the released pointer where the finished
|
||||
/// @param offset The offset from the released pointer where the finished
|
||||
/// `FlatBuffer` starts.
|
||||
/// @return A raw pointer to the start of the memory block containing
|
||||
/// the serialized `FlatBuffer`.
|
||||
/// @remark If the allocator is owned, it gets deleted when the destructor is called..
|
||||
/// @remark If the allocator is owned, it gets deleted when the destructor is
|
||||
/// called..
|
||||
uint8_t *ReleaseRaw(size_t &size, size_t &offset) {
|
||||
Finished();
|
||||
return buf_.release_raw(size, offset);
|
||||
@@ -1076,12 +1229,13 @@ class FlatBufferBuilder {
|
||||
|
||||
/// @brief In order to save space, fields that are set to their default value
|
||||
/// don't get serialized into the buffer.
|
||||
/// @param[in] bool fd When set to `true`, always serializes default values that are set.
|
||||
/// Optional fields which are not set explicitly, will still not be serialized.
|
||||
/// @param[in] fd When set to `true`, always serializes default values that
|
||||
/// are set. Optional fields which are not set explicitly, will still not be
|
||||
/// serialized.
|
||||
void ForceDefaults(bool fd) { force_defaults_ = fd; }
|
||||
|
||||
/// @brief By default vtables are deduped in order to save space.
|
||||
/// @param[in] bool dedup When set to `true`, dedup vtables.
|
||||
/// @param[in] dedup When set to `true`, dedup vtables.
|
||||
void DedupVtables(bool dedup) { dedup_vtables_ = dedup; }
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
@@ -1235,7 +1389,7 @@ class FlatBufferBuilder {
|
||||
it += sizeof(uoffset_t)) {
|
||||
auto vt_offset_ptr = reinterpret_cast<uoffset_t *>(it);
|
||||
auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*vt_offset_ptr));
|
||||
auto vt2_size = *vt2;
|
||||
auto vt2_size = ReadScalar<voffset_t>(vt2);
|
||||
if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size)) continue;
|
||||
vt_use = *vt_offset_ptr;
|
||||
buf_.pop(GetSize() - vtableoffsetloc);
|
||||
@@ -1562,17 +1716,16 @@ class FlatBufferBuilder {
|
||||
Offset<Vector<const T *>> CreateVectorOfNativeStructs(const S *v,
|
||||
size_t len) {
|
||||
extern T Pack(const S &);
|
||||
typedef T (*Pack_t)(const S &);
|
||||
std::vector<T> vv(len);
|
||||
std::transform(v, v + len, vv.begin(), static_cast<Pack_t&>(Pack));
|
||||
return CreateVectorOfStructs<T>(vv.data(), vv.size());
|
||||
std::transform(v, v + len, vv.begin(), Pack);
|
||||
return CreateVectorOfStructs<T>(data(vv), vv.size());
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
/// @brief Serialize an array of structs into a FlatBuffer `vector`.
|
||||
/// @tparam T The data type of the struct array elements.
|
||||
/// @param[in] f A function that takes the current iteration 0..vector_size-1
|
||||
/// @param[in] filler A function that takes the current iteration 0..vector_size-1
|
||||
/// and a pointer to the struct that must be filled.
|
||||
/// @return Returns a typed `Offset` into the serialized data indicating
|
||||
/// where the vector is stored.
|
||||
@@ -1612,7 +1765,7 @@ class FlatBufferBuilder {
|
||||
|
||||
/// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`.
|
||||
/// @tparam T The data type of the `std::vector` struct elements.
|
||||
/// @param[in]] v A const reference to the `std::vector` of structs to
|
||||
/// @param[in] v A const reference to the `std::vector` of structs to
|
||||
/// serialize into the buffer as a `vector`.
|
||||
/// @return Returns a typed `Offset` into the serialized data indicating
|
||||
/// where the vector is stored.
|
||||
@@ -1626,7 +1779,7 @@ class FlatBufferBuilder {
|
||||
/// `vector`.
|
||||
/// @tparam T The data type of the `std::vector` struct elements.
|
||||
/// @tparam S The data type of the `std::vector` native struct elements.
|
||||
/// @param[in]] v A const reference to the `std::vector` of structs to
|
||||
/// @param[in] v A const reference to the `std::vector` of structs to
|
||||
/// serialize into the buffer as a `vector`.
|
||||
/// @return Returns a typed `Offset` into the serialized data indicating
|
||||
/// where the vector is stored.
|
||||
@@ -1650,7 +1803,7 @@ class FlatBufferBuilder {
|
||||
/// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`
|
||||
/// in sorted order.
|
||||
/// @tparam T The data type of the `std::vector` struct elements.
|
||||
/// @param[in]] v A const reference to the `std::vector` of structs to
|
||||
/// @param[in] v A const reference to the `std::vector` of structs to
|
||||
/// serialize into the buffer as a `vector`.
|
||||
/// @return Returns a typed `Offset` into the serialized data indicating
|
||||
/// where the vector is stored.
|
||||
@@ -1663,7 +1816,7 @@ class FlatBufferBuilder {
|
||||
/// `vector` in sorted order.
|
||||
/// @tparam T The data type of the `std::vector` struct elements.
|
||||
/// @tparam S The data type of the `std::vector` native struct elements.
|
||||
/// @param[in]] v A const reference to the `std::vector` of structs to
|
||||
/// @param[in] v A const reference to the `std::vector` of structs to
|
||||
/// serialize into the buffer as a `vector`.
|
||||
/// @return Returns a typed `Offset` into the serialized data indicating
|
||||
/// where the vector is stored.
|
||||
@@ -1702,13 +1855,14 @@ class FlatBufferBuilder {
|
||||
extern T Pack(const S &);
|
||||
typedef T (*Pack_t)(const S &);
|
||||
std::vector<T> vv(len);
|
||||
std::transform(v, v + len, vv.begin(), static_cast<Pack_t&>(Pack));
|
||||
std::transform(v, v + len, vv.begin(), static_cast<Pack_t &>(Pack));
|
||||
return CreateVectorOfSortedStructs<T>(vv, len);
|
||||
}
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
template<typename T> struct TableKeyComparator {
|
||||
TableKeyComparator(vector_downward &buf) : buf_(buf) {}
|
||||
TableKeyComparator(const TableKeyComparator &other) : buf_(other.buf_) {}
|
||||
bool operator()(const Offset<T> &a, const Offset<T> &b) const {
|
||||
auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o));
|
||||
auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o));
|
||||
@@ -1717,7 +1871,10 @@ class FlatBufferBuilder {
|
||||
vector_downward &buf_;
|
||||
|
||||
private:
|
||||
TableKeyComparator &operator=(const TableKeyComparator &);
|
||||
TableKeyComparator &operator=(const TableKeyComparator &other) {
|
||||
buf_ = other.buf_;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
@@ -1783,12 +1940,12 @@ class FlatBufferBuilder {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Offset<Vector<const T*>> CreateUninitializedVectorOfStructs(size_t len, T **buf) {
|
||||
Offset<Vector<const T *>> CreateUninitializedVectorOfStructs(size_t len,
|
||||
T **buf) {
|
||||
return CreateUninitializedVector(len, sizeof(T),
|
||||
reinterpret_cast<uint8_t **>(buf));
|
||||
}
|
||||
|
||||
|
||||
// @brief Create a vector of scalar type T given as input a vector of scalar
|
||||
// type U, useful with e.g. pre "enum class" enums, or any existing scalar
|
||||
// data of the wrong type.
|
||||
@@ -1837,8 +1994,7 @@ class FlatBufferBuilder {
|
||||
buf_.swap_allocator(other.buf_);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
protected:
|
||||
// You shouldn't really be copying instances of this class.
|
||||
FlatBufferBuilder(const FlatBufferBuilder &);
|
||||
FlatBufferBuilder &operator=(const FlatBufferBuilder &);
|
||||
@@ -1891,8 +2047,8 @@ protected:
|
||||
bool operator()(const Offset<String> &a, const Offset<String> &b) const {
|
||||
auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o));
|
||||
auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o));
|
||||
return StringLessThan(stra->data(), stra->size(),
|
||||
strb->data(), strb->size());
|
||||
return StringLessThan(stra->data(), stra->size(), strb->data(),
|
||||
strb->size());
|
||||
}
|
||||
const vector_downward *buf_;
|
||||
};
|
||||
@@ -1956,13 +2112,15 @@ const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
|
||||
/// This function is UNDEFINED for FlatBuffers whose schema does not include
|
||||
/// a file_identifier (likely points at padding or the start of a the root
|
||||
/// vtable).
|
||||
inline const char *GetBufferIdentifier(const void *buf, bool size_prefixed = false) {
|
||||
inline const char *GetBufferIdentifier(const void *buf,
|
||||
bool size_prefixed = false) {
|
||||
return reinterpret_cast<const char *>(buf) +
|
||||
((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t));
|
||||
}
|
||||
|
||||
// Helper to see if the identifier in a buffer has the expected value.
|
||||
inline bool BufferHasIdentifier(const void *buf, const char *identifier, bool size_prefixed = false) {
|
||||
inline bool BufferHasIdentifier(const void *buf, const char *identifier,
|
||||
bool size_prefixed = false) {
|
||||
return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier,
|
||||
FlatBufferBuilder::kFileIdentifierLength) == 0;
|
||||
}
|
||||
@@ -1979,8 +2137,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
num_tables_(0),
|
||||
max_tables_(_max_tables),
|
||||
upper_bound_(0),
|
||||
check_alignment_(_check_alignment)
|
||||
{
|
||||
check_alignment_(_check_alignment) {
|
||||
FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
@@ -2011,7 +2168,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
}
|
||||
|
||||
template<typename T> bool VerifyAlignment(size_t elem) const {
|
||||
return (elem & (sizeof(T) - 1)) == 0 || !check_alignment_;
|
||||
return Check((elem & (sizeof(T) - 1)) == 0 || !check_alignment_);
|
||||
}
|
||||
|
||||
// Verify a range indicated by sizeof(T).
|
||||
@@ -2019,13 +2176,18 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
return VerifyAlignment<T>(elem) && Verify(elem, sizeof(T));
|
||||
}
|
||||
|
||||
bool VerifyFromPointer(const uint8_t *p, size_t len) {
|
||||
auto o = static_cast<size_t>(p - buf_);
|
||||
return Verify(o, len);
|
||||
}
|
||||
|
||||
// Verify relative to a known-good base pointer.
|
||||
bool Verify(const uint8_t *base, voffset_t elem_off, size_t elem_len) const {
|
||||
return Verify(static_cast<size_t>(base - buf_) + elem_off, elem_len);
|
||||
}
|
||||
|
||||
template<typename T> bool Verify(const uint8_t *base, voffset_t elem_off)
|
||||
const {
|
||||
template<typename T>
|
||||
bool Verify(const uint8_t *base, voffset_t elem_off) const {
|
||||
return Verify(static_cast<size_t>(base - buf_) + elem_off, sizeof(T));
|
||||
}
|
||||
|
||||
@@ -2048,16 +2210,15 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
// Verify a pointer (may be NULL) to string.
|
||||
bool VerifyString(const String *str) const {
|
||||
size_t end;
|
||||
return !str ||
|
||||
(VerifyVectorOrString(reinterpret_cast<const uint8_t *>(str),
|
||||
1, &end) &&
|
||||
Verify(end, 1) && // Must have terminator
|
||||
Check(buf_[end] == '\0')); // Terminating byte must be 0.
|
||||
return !str || (VerifyVectorOrString(reinterpret_cast<const uint8_t *>(str),
|
||||
1, &end) &&
|
||||
Verify(end, 1) && // Must have terminator
|
||||
Check(buf_[end] == '\0')); // Terminating byte must be 0.
|
||||
}
|
||||
|
||||
// Common code between vectors and strings.
|
||||
bool VerifyVectorOrString(const uint8_t *vec, size_t elem_size,
|
||||
size_t *end = nullptr) const {
|
||||
size_t *end = nullptr) const {
|
||||
auto veco = static_cast<size_t>(vec - buf_);
|
||||
// Check we can read the size field.
|
||||
if (!Verify<uoffset_t>(veco)) return false;
|
||||
@@ -2092,11 +2253,12 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool VerifyTableStart(const uint8_t *table) {
|
||||
__supress_ubsan__("unsigned-integer-overflow") bool VerifyTableStart(
|
||||
const uint8_t *table) {
|
||||
// Check the vtable offset.
|
||||
auto tableo = static_cast<size_t>(table - buf_);
|
||||
if (!Verify<soffset_t>(tableo)) return false;
|
||||
// This offset may be signed, but doing the substraction unsigned always
|
||||
// This offset may be signed, but doing the subtraction unsigned always
|
||||
// gives the result we want.
|
||||
auto vtableo = tableo - static_cast<size_t>(ReadScalar<soffset_t>(table));
|
||||
// Check the vtable size field, then check vtable fits in its entirety.
|
||||
@@ -2107,9 +2269,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
|
||||
|
||||
template<typename T>
|
||||
bool VerifyBufferFromStart(const char *identifier, size_t start) {
|
||||
if (identifier &&
|
||||
(size_ < 2 * sizeof(flatbuffers::uoffset_t) ||
|
||||
!BufferHasIdentifier(buf_ + start, identifier))) {
|
||||
if (identifier && (size_ < 2 * sizeof(flatbuffers::uoffset_t) ||
|
||||
!BufferHasIdentifier(buf_ + start, identifier))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -2241,6 +2402,12 @@ class Struct FLATBUFFERS_FINAL_CLASS {
|
||||
uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; }
|
||||
|
||||
private:
|
||||
// private constructor & copy constructor: you obtain instances of this
|
||||
// class by pointing to existing data only
|
||||
Struct();
|
||||
Struct(const Struct &);
|
||||
Struct &operator=(const Struct &);
|
||||
|
||||
uint8_t data_[1];
|
||||
};
|
||||
|
||||
@@ -2353,12 +2520,13 @@ class Table {
|
||||
// class by pointing to existing data only
|
||||
Table();
|
||||
Table(const Table &other);
|
||||
Table &operator=(const Table &);
|
||||
|
||||
uint8_t data_[1];
|
||||
};
|
||||
|
||||
template<typename T> void FlatBufferBuilder::Required(Offset<T> table,
|
||||
voffset_t field) {
|
||||
template<typename T>
|
||||
void FlatBufferBuilder::Required(Offset<T> table, voffset_t field) {
|
||||
auto table_ptr = reinterpret_cast<const Table *>(buf_.data_at(table.o));
|
||||
bool ok = table_ptr->GetOptionalFieldOffset(field) != 0;
|
||||
// If this fails, the caller will show what field needs to be set.
|
||||
@@ -2405,7 +2573,9 @@ inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
|
||||
}
|
||||
|
||||
/// @brief This return the prefixed size of a FlatBuffer.
|
||||
inline uoffset_t GetPrefixedSize(const uint8_t* buf){ return ReadScalar<uoffset_t>(buf); }
|
||||
inline uoffset_t GetPrefixedSize(const uint8_t *buf) {
|
||||
return ReadScalar<uoffset_t>(buf);
|
||||
}
|
||||
|
||||
// Base class for native objects (FlatBuffer data de-serialized into native
|
||||
// C++ data structures).
|
||||
@@ -2473,7 +2643,7 @@ inline int LookupEnum(const char **names, const char *name) {
|
||||
#define FLATBUFFERS_STRUCT_END(name, size) \
|
||||
__pragma(pack()) \
|
||||
static_assert(sizeof(name) == size, "compiler breaks packing rules")
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#elif defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
|
||||
#define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
|
||||
_Pragma("pack(1)") \
|
||||
struct __attribute__((aligned(alignment)))
|
||||
@@ -2548,10 +2718,10 @@ typedef const TypeTable *(*TypeFunction)();
|
||||
struct TypeTable {
|
||||
SequenceType st;
|
||||
size_t num_elems; // of type_codes, values, names (but not type_refs).
|
||||
const TypeCode *type_codes; // num_elems count
|
||||
const TypeCode *type_codes; // num_elems count
|
||||
const TypeFunction *type_refs; // less than num_elems entries (see TypeCode).
|
||||
const int64_t *values; // Only set for non-consecutive enum/union or structs.
|
||||
const char * const *names; // Only set if compiled with --reflect-names.
|
||||
const char *const *names; // Only set if compiled with --reflect-names.
|
||||
};
|
||||
|
||||
// String which identifies the current version of FlatBuffers.
|
||||
|
||||
@@ -14,18 +14,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_FLATC_H_
|
||||
#define FLATBUFFERS_FLATC_H_
|
||||
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/idl.h"
|
||||
#include "flatbuffers/util.h"
|
||||
|
||||
#ifndef FLATC_H_
|
||||
# define FLATC_H_
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
extern void LogCompilerWarn(const std::string &warn);
|
||||
extern void LogCompilerError(const std::string &err);
|
||||
|
||||
class FlatCompiler {
|
||||
public:
|
||||
// Output generator for the various programming languages and formats we
|
||||
@@ -93,4 +97,4 @@ class FlatCompiler {
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATC_H_
|
||||
#endif // FLATBUFFERS_FLATC_H_
|
||||
|
||||
@@ -65,7 +65,9 @@ enum Type {
|
||||
FBT_VECTOR_UINT = 12,
|
||||
FBT_VECTOR_FLOAT = 13,
|
||||
FBT_VECTOR_KEY = 14,
|
||||
FBT_VECTOR_STRING = 15,
|
||||
// DEPRECATED, use FBT_VECTOR or FBT_VECTOR_KEY instead.
|
||||
// Read test.cpp/FlexBuffersDeprecatedTest() for details on why.
|
||||
FBT_VECTOR_STRING_DEPRECATED = 15,
|
||||
FBT_VECTOR_INT2 = 16, // Typed tuple (no type table, no size field).
|
||||
FBT_VECTOR_UINT2 = 17,
|
||||
FBT_VECTOR_FLOAT2 = 18,
|
||||
@@ -88,7 +90,7 @@ inline bool IsTypedVectorElementType(Type t) {
|
||||
}
|
||||
|
||||
inline bool IsTypedVector(Type t) {
|
||||
return (t >= FBT_VECTOR_INT && t <= FBT_VECTOR_STRING) ||
|
||||
return (t >= FBT_VECTOR_INT && t <= FBT_VECTOR_STRING_DEPRECATED) ||
|
||||
t == FBT_VECTOR_BOOL;
|
||||
}
|
||||
|
||||
@@ -212,26 +214,40 @@ class Object {
|
||||
uint8_t byte_width_;
|
||||
};
|
||||
|
||||
// Stores size in `byte_width_` bytes before data_ pointer.
|
||||
// Object that has a size, obtained either from size prefix, or elsewhere.
|
||||
class Sized : public Object {
|
||||
public:
|
||||
Sized(const uint8_t *data, uint8_t byte_width) : Object(data, byte_width) {}
|
||||
size_t size() const {
|
||||
// Size prefix.
|
||||
Sized(const uint8_t *data, uint8_t byte_width)
|
||||
: Object(data, byte_width), size_(read_size()) {}
|
||||
// Manual size.
|
||||
Sized(const uint8_t *data, uint8_t byte_width, size_t sz)
|
||||
: Object(data, byte_width), size_(sz) {}
|
||||
size_t size() const { return size_; }
|
||||
// Access size stored in `byte_width_` bytes before data_ pointer.
|
||||
size_t read_size() const {
|
||||
return static_cast<size_t>(ReadUInt64(data_ - byte_width_, byte_width_));
|
||||
}
|
||||
|
||||
protected:
|
||||
size_t size_;
|
||||
};
|
||||
|
||||
class String : public Sized {
|
||||
public:
|
||||
// Size prefix.
|
||||
String(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {}
|
||||
// Manual size.
|
||||
String(const uint8_t *data, uint8_t byte_width, size_t sz)
|
||||
: Sized(data, byte_width, sz) {}
|
||||
|
||||
size_t length() const { return size(); }
|
||||
const char *c_str() const { return reinterpret_cast<const char *>(data_); }
|
||||
std::string str() const { return std::string(c_str(), length()); }
|
||||
std::string str() const { return std::string(c_str(), size()); }
|
||||
|
||||
static String EmptyString() {
|
||||
static const uint8_t empty_string[] = { 0 /*len*/, 0 /*terminator*/ };
|
||||
return String(empty_string + 1, 1);
|
||||
static const char *empty_string = "";
|
||||
return String(reinterpret_cast<const uint8_t *>(empty_string), 1, 0);
|
||||
}
|
||||
bool IsTheEmptyString() const { return data_ == EmptyString().data_; }
|
||||
};
|
||||
@@ -279,6 +295,8 @@ class TypedVector : public Sized {
|
||||
|
||||
Type ElementType() { return type_; }
|
||||
|
||||
friend Reference;
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
|
||||
@@ -339,16 +357,22 @@ class Map : public Vector {
|
||||
|
||||
template<typename T>
|
||||
void AppendToString(std::string &s, T &&v, bool keys_quoted) {
|
||||
s += "[ ";
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
if (i) s += ", ";
|
||||
v[i].ToString(true, keys_quoted, s);
|
||||
}
|
||||
s += " ]";
|
||||
s += "[ ";
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
if (i) s += ", ";
|
||||
v[i].ToString(true, keys_quoted, s);
|
||||
}
|
||||
s += " ]";
|
||||
}
|
||||
|
||||
class Reference {
|
||||
public:
|
||||
Reference()
|
||||
: data_(nullptr),
|
||||
parent_width_(0),
|
||||
byte_width_(BIT_WIDTH_8),
|
||||
type_(FBT_NULL) {}
|
||||
|
||||
Reference(const uint8_t *data, uint8_t parent_width, uint8_t byte_width,
|
||||
Type type)
|
||||
: data_(data),
|
||||
@@ -378,15 +402,19 @@ class Reference {
|
||||
bool IsString() const { return type_ == FBT_STRING; }
|
||||
bool IsKey() const { return type_ == FBT_KEY; }
|
||||
bool IsVector() const { return type_ == FBT_VECTOR || type_ == FBT_MAP; }
|
||||
bool IsUntypedVector() const { return type_ == FBT_VECTOR; }
|
||||
bool IsTypedVector() const { return flexbuffers::IsTypedVector(type_); }
|
||||
bool IsFixedTypedVector() const { return flexbuffers::IsFixedTypedVector(type_); }
|
||||
bool IsAnyVector() const { return (IsTypedVector() || IsFixedTypedVector() || IsVector());}
|
||||
bool IsFixedTypedVector() const {
|
||||
return flexbuffers::IsFixedTypedVector(type_);
|
||||
}
|
||||
bool IsAnyVector() const {
|
||||
return (IsTypedVector() || IsFixedTypedVector() || IsVector());
|
||||
}
|
||||
bool IsMap() const { return type_ == FBT_MAP; }
|
||||
bool IsBlob() const { return type_ == FBT_BLOB; }
|
||||
|
||||
bool AsBool() const {
|
||||
return (type_ == FBT_BOOL ? ReadUInt64(data_, parent_width_)
|
||||
: AsUInt64()) != 0;
|
||||
: AsUInt64()) != 0;
|
||||
}
|
||||
|
||||
// Reads any type as a int64_t. Never fails, does most sensible conversion.
|
||||
@@ -464,7 +492,11 @@ class Reference {
|
||||
case FBT_INDIRECT_UINT:
|
||||
return static_cast<double>(ReadUInt64(Indirect(), byte_width_));
|
||||
case FBT_NULL: return 0.0;
|
||||
case FBT_STRING: return strtod(AsString().c_str(), nullptr);
|
||||
case FBT_STRING: {
|
||||
double d;
|
||||
flatbuffers::StringToNumber(AsString().c_str(), &d);
|
||||
return d;
|
||||
}
|
||||
case FBT_VECTOR: return static_cast<double>(AsVector().size());
|
||||
case FBT_BOOL:
|
||||
return static_cast<double>(ReadUInt64(data_, parent_width_));
|
||||
@@ -477,17 +509,22 @@ class Reference {
|
||||
float AsFloat() const { return static_cast<float>(AsDouble()); }
|
||||
|
||||
const char *AsKey() const {
|
||||
if (type_ == FBT_KEY) {
|
||||
if (type_ == FBT_KEY || type_ == FBT_STRING) {
|
||||
return reinterpret_cast<const char *>(Indirect());
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// This function returns the empty string if you try to read a not-string.
|
||||
// This function returns the empty string if you try to read something that
|
||||
// is not a string or key.
|
||||
String AsString() const {
|
||||
if (type_ == FBT_STRING) {
|
||||
return String(Indirect(), byte_width_);
|
||||
} else if (type_ == FBT_KEY) {
|
||||
auto key = Indirect();
|
||||
return String(key, byte_width_,
|
||||
strlen(reinterpret_cast<const char *>(key)));
|
||||
} else {
|
||||
return String::EmptyString();
|
||||
}
|
||||
@@ -549,7 +586,8 @@ class Reference {
|
||||
AppendToString<FixedTypedVector>(s, AsFixedTypedVector(), keys_quoted);
|
||||
} else if (IsBlob()) {
|
||||
auto blob = AsBlob();
|
||||
flatbuffers::EscapeString(reinterpret_cast<const char*>(blob.data()), blob.size(), &s, true, false);
|
||||
flatbuffers::EscapeString(reinterpret_cast<const char *>(blob.data()),
|
||||
blob.size(), &s, true, false);
|
||||
} else {
|
||||
s += "(?)";
|
||||
}
|
||||
@@ -577,8 +615,18 @@ class Reference {
|
||||
|
||||
TypedVector AsTypedVector() const {
|
||||
if (IsTypedVector()) {
|
||||
return TypedVector(Indirect(), byte_width_,
|
||||
ToTypedVectorElementType(type_));
|
||||
auto tv =
|
||||
TypedVector(Indirect(), byte_width_, ToTypedVectorElementType(type_));
|
||||
if (tv.type_ == FBT_STRING) {
|
||||
// These can't be accessed as strings, since we don't know the bit-width
|
||||
// of the size field, see the declaration of
|
||||
// FBT_VECTOR_STRING_DEPRECATED above for details.
|
||||
// We change the type here to be keys, which are a subtype of strings,
|
||||
// and will ignore the size field. This will truncate strings with
|
||||
// embedded nulls.
|
||||
tv.type_ = FBT_KEY;
|
||||
}
|
||||
return tv;
|
||||
} else {
|
||||
return TypedVector::EmptyTypedVector();
|
||||
}
|
||||
@@ -723,9 +771,15 @@ template<> inline int32_t Reference::As<int32_t>() const { return AsInt32(); }
|
||||
template<> inline int64_t Reference::As<int64_t>() const { return AsInt64(); }
|
||||
|
||||
template<> inline uint8_t Reference::As<uint8_t>() const { return AsUInt8(); }
|
||||
template<> inline uint16_t Reference::As<uint16_t>() const { return AsUInt16(); }
|
||||
template<> inline uint32_t Reference::As<uint32_t>() const { return AsUInt32(); }
|
||||
template<> inline uint64_t Reference::As<uint64_t>() const { return AsUInt64(); }
|
||||
template<> inline uint16_t Reference::As<uint16_t>() const {
|
||||
return AsUInt16();
|
||||
}
|
||||
template<> inline uint32_t Reference::As<uint32_t>() const {
|
||||
return AsUInt32();
|
||||
}
|
||||
template<> inline uint64_t Reference::As<uint64_t>() const {
|
||||
return AsUInt64();
|
||||
}
|
||||
|
||||
template<> inline double Reference::As<double>() const { return AsDouble(); }
|
||||
template<> inline float Reference::As<float>() const { return AsFloat(); }
|
||||
@@ -1046,7 +1100,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
for (auto key = start; key < stack_.size(); key += 2) {
|
||||
FLATBUFFERS_ASSERT(stack_[key].type_ == FBT_KEY);
|
||||
}
|
||||
// Now sort values, so later we can do a binary seach lookup.
|
||||
// Now sort values, so later we can do a binary search lookup.
|
||||
// We want to sort 2 array elements at a time.
|
||||
struct TwoValue {
|
||||
Value key;
|
||||
@@ -1194,6 +1248,24 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
EndMap(start);
|
||||
}
|
||||
|
||||
// If you wish to share a value explicitly (a value not shared automatically
|
||||
// through one of the BUILDER_FLAG_SHARE_* flags) you can do so with these
|
||||
// functions. Or if you wish to turn those flags off for performance reasons
|
||||
// and still do some explicit sharing. For example:
|
||||
// builder.IndirectDouble(M_PI);
|
||||
// auto id = builder.LastValue(); // Remember where we stored it.
|
||||
// .. more code goes here ..
|
||||
// builder.ReuseValue(id); // Refers to same double by offset.
|
||||
// LastValue works regardless of wether the value has a key or not.
|
||||
// Works on any data type.
|
||||
struct Value;
|
||||
Value LastValue() { return stack_.back(); }
|
||||
void ReuseValue(Value v) { stack_.push_back(v); }
|
||||
void ReuseValue(const char *key, Value v) {
|
||||
Key(key);
|
||||
ReuseValue(v);
|
||||
}
|
||||
|
||||
// Overloaded Add that tries to call the correct function above.
|
||||
void Add(int8_t i) { Int(i); }
|
||||
void Add(int16_t i) { Int(i); }
|
||||
@@ -1319,6 +1391,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
: FBT_INT);
|
||||
}
|
||||
|
||||
public:
|
||||
// This was really intended to be private, except for LastValue/ReuseValue.
|
||||
struct Value {
|
||||
union {
|
||||
int64_t i_;
|
||||
@@ -1388,6 +1462,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
void WriteAny(const Value &val, uint8_t byte_width) {
|
||||
switch (val.type_) {
|
||||
case FBT_NULL:
|
||||
@@ -1420,6 +1495,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
// TODO: instead of asserting, could write vector with larger elements
|
||||
// instead, though that would be wasteful.
|
||||
FLATBUFFERS_ASSERT(WidthU(len) <= bit_width);
|
||||
Align(bit_width);
|
||||
if (!fixed) Write<uint64_t>(len, byte_width);
|
||||
auto vloc = buf_.size();
|
||||
for (size_t i = 0; i < len; i++) Write(elems[i], byte_width);
|
||||
@@ -1431,7 +1507,9 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
|
||||
Value CreateVector(size_t start, size_t vec_len, size_t step, bool typed,
|
||||
bool fixed, const Value *keys = nullptr) {
|
||||
FLATBUFFERS_ASSERT(!fixed || typed); // typed=false, fixed=true combination is not supported.
|
||||
FLATBUFFERS_ASSERT(
|
||||
!fixed ||
|
||||
typed); // typed=false, fixed=true combination is not supported.
|
||||
// Figure out smallest bit width we can store this vector with.
|
||||
auto bit_width = (std::max)(force_min_bit_width_, WidthU(vec_len));
|
||||
auto prefix_elems = 1;
|
||||
@@ -1511,7 +1589,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
|
||||
typedef std::pair<size_t, size_t> StringOffset;
|
||||
struct StringOffsetCompare {
|
||||
explicit StringOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {}
|
||||
explicit StringOffsetCompare(const std::vector<uint8_t> &buf)
|
||||
: buf_(&buf) {}
|
||||
bool operator()(const StringOffset &a, const StringOffset &b) const {
|
||||
auto stra = reinterpret_cast<const char *>(
|
||||
flatbuffers::vector_data(*buf_) + a.first);
|
||||
@@ -1531,8 +1610,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
|
||||
} // namespace flexbuffers
|
||||
|
||||
# if defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
# endif
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // FLATBUFFERS_FLEXBUFFERS_H_
|
||||
|
||||
@@ -88,8 +88,7 @@ class SliceAllocator : public Allocator {
|
||||
SliceAllocator(const SliceAllocator &other) = delete;
|
||||
SliceAllocator &operator=(const SliceAllocator &other) = delete;
|
||||
|
||||
SliceAllocator(SliceAllocator &&other)
|
||||
: slice_(grpc_empty_slice()) {
|
||||
SliceAllocator(SliceAllocator &&other) : slice_(grpc_empty_slice()) {
|
||||
// default-construct and swap idiom
|
||||
swap(other);
|
||||
}
|
||||
@@ -164,34 +163,36 @@ class MessageBuilder : private detail::SliceAllocatorMember,
|
||||
public FlatBufferBuilder {
|
||||
public:
|
||||
explicit MessageBuilder(uoffset_t initial_size = 1024)
|
||||
: FlatBufferBuilder(initial_size, &slice_allocator_, false) {}
|
||||
: FlatBufferBuilder(initial_size, &slice_allocator_, false) {}
|
||||
|
||||
MessageBuilder(const MessageBuilder &other) = delete;
|
||||
MessageBuilder &operator=(const MessageBuilder &other) = delete;
|
||||
|
||||
MessageBuilder(MessageBuilder &&other)
|
||||
: FlatBufferBuilder(1024, &slice_allocator_, false) {
|
||||
: FlatBufferBuilder(1024, &slice_allocator_, false) {
|
||||
// Default construct and swap idiom.
|
||||
Swap(other);
|
||||
}
|
||||
|
||||
/// Create a MessageBuilder from a FlatBufferBuilder.
|
||||
explicit MessageBuilder(FlatBufferBuilder &&src, void (*dealloc)(void*, size_t) = &DefaultAllocator::dealloc)
|
||||
: FlatBufferBuilder(1024, &slice_allocator_, false) {
|
||||
explicit MessageBuilder(FlatBufferBuilder &&src,
|
||||
void (*dealloc)(void *,
|
||||
size_t) = &DefaultAllocator::dealloc)
|
||||
: FlatBufferBuilder(1024, &slice_allocator_, false) {
|
||||
src.Swap(*this);
|
||||
src.SwapBufAllocator(*this);
|
||||
if (buf_.capacity()) {
|
||||
uint8_t *buf = buf_.scratch_data(); // pointer to memory
|
||||
size_t capacity = buf_.capacity(); // size of memory
|
||||
uint8_t *buf = buf_.scratch_data(); // pointer to memory
|
||||
size_t capacity = buf_.capacity(); // size of memory
|
||||
slice_allocator_.slice_ = grpc_slice_new_with_len(buf, capacity, dealloc);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
slice_allocator_.slice_ = grpc_empty_slice();
|
||||
}
|
||||
}
|
||||
|
||||
/// Move-assign a FlatBufferBuilder to a MessageBuilder.
|
||||
/// Only FlatBufferBuilder with default allocator (basically, nullptr) is supported.
|
||||
/// Only FlatBufferBuilder with default allocator (basically, nullptr) is
|
||||
/// supported.
|
||||
MessageBuilder &operator=(FlatBufferBuilder &&src) {
|
||||
// Move construct a temporary and swap
|
||||
MessageBuilder temp(std::move(src));
|
||||
@@ -209,10 +210,11 @@ class MessageBuilder : private detail::SliceAllocatorMember,
|
||||
void Swap(MessageBuilder &other) {
|
||||
slice_allocator_.swap(other.slice_allocator_);
|
||||
FlatBufferBuilder::Swap(other);
|
||||
// After swapping the FlatBufferBuilder, we swap back the allocator, which restores
|
||||
// the original allocator back in place. This is necessary because MessageBuilder's
|
||||
// allocator is its own member (SliceAllocatorMember). The allocator passed to
|
||||
// FlatBufferBuilder::vector_downward must point to this member.
|
||||
// After swapping the FlatBufferBuilder, we swap back the allocator, which
|
||||
// restores the original allocator back in place. This is necessary because
|
||||
// MessageBuilder's allocator is its own member (SliceAllocatorMember). The
|
||||
// allocator passed to FlatBufferBuilder::vector_downward must point to this
|
||||
// member.
|
||||
buf_.swap_allocator(other.buf_);
|
||||
}
|
||||
|
||||
@@ -232,10 +234,10 @@ class MessageBuilder : private detail::SliceAllocatorMember,
|
||||
// flatbuffers-encoded region and wraps it in a `Message<T>` to handle buffer
|
||||
// ownership.
|
||||
template<class T> Message<T> GetMessage() {
|
||||
auto buf_data = buf_.scratch_data(); // 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
|
||||
auto buf_data = buf_.scratch_data(); // 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
|
||||
FLATBUFFERS_ASSERT(msg_data);
|
||||
FLATBUFFERS_ASSERT(msg_size);
|
||||
@@ -274,7 +276,7 @@ template<class T> class SerializationTraits<flatbuffers::grpc::Message<T>> {
|
||||
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
|
||||
// is necessary 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
|
||||
@@ -306,7 +308,7 @@ template<class T> class SerializationTraits<flatbuffers::grpc::Message<T>> {
|
||||
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
|
||||
// We wrap a `Message<T>` around the slice, but don't increment refcount
|
||||
*msg = flatbuffers::grpc::Message<T>(slice, false);
|
||||
}
|
||||
grpc_byte_buffer_destroy(buffer);
|
||||
|
||||
@@ -57,17 +57,17 @@ template<typename T> T HashFnv1a(const char *input) {
|
||||
return hash;
|
||||
}
|
||||
|
||||
template <> inline uint16_t HashFnv1<uint16_t>(const char *input) {
|
||||
template<> inline uint16_t HashFnv1<uint16_t>(const char *input) {
|
||||
uint32_t hash = HashFnv1<uint32_t>(input);
|
||||
return (hash >> 16) ^ (hash & 0xffff);
|
||||
}
|
||||
|
||||
template <> inline uint16_t HashFnv1a<uint16_t>(const char *input) {
|
||||
template<> inline uint16_t HashFnv1a<uint16_t>(const char *input) {
|
||||
uint32_t hash = HashFnv1a<uint32_t>(input);
|
||||
return (hash >> 16) ^ (hash & 0xffff);
|
||||
}
|
||||
|
||||
template <typename T> struct NamedHashFunction {
|
||||
template<typename T> struct NamedHashFunction {
|
||||
const char *name;
|
||||
|
||||
typedef T (*HashFunction)(const char *);
|
||||
@@ -75,7 +75,7 @@ template <typename T> struct NamedHashFunction {
|
||||
};
|
||||
|
||||
const NamedHashFunction<uint16_t> kHashFunctions16[] = {
|
||||
{ "fnv1_16", HashFnv1<uint16_t> },
|
||||
{ "fnv1_16", HashFnv1<uint16_t> },
|
||||
{ "fnv1a_16", HashFnv1a<uint16_t> },
|
||||
};
|
||||
|
||||
|
||||
@@ -47,25 +47,26 @@ namespace flatbuffers {
|
||||
// of type tokens.
|
||||
// clang-format off
|
||||
#define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
|
||||
TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8) \
|
||||
TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8) /* begin scalar/int */ \
|
||||
TD(BOOL, "bool", uint8_t, boolean,bool, bool, bool, bool) \
|
||||
TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8) \
|
||||
TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8) \
|
||||
TD(SHORT, "short", int16_t, short, int16, short, int16, i16) \
|
||||
TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16, u16) \
|
||||
TD(INT, "int", int32_t, int, int32, int, int32, i32) \
|
||||
TD(UINT, "uint", uint32_t, int, uint32, uint, uint32, u32) \
|
||||
TD(LONG, "long", int64_t, long, int64, long, int64, i64) \
|
||||
TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64, u64) /* end int */ \
|
||||
TD(FLOAT, "float", float, float, float32, float, float32, f32) /* begin float */ \
|
||||
TD(DOUBLE, "double", double, double, float64, double, float64, f64) /* end float/scalar */
|
||||
TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) \
|
||||
TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) /* begin scalar/int */ \
|
||||
TD(BOOL, "bool", uint8_t, boolean,bool, bool, bool, bool, Boolean, Bool) \
|
||||
TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8, Byte, Int8) \
|
||||
TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) \
|
||||
TD(SHORT, "short", int16_t, short, int16, short, int16, i16, Short, Int16) \
|
||||
TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16, u16, UShort, UInt16) \
|
||||
TD(INT, "int", int32_t, int, int32, int, int32, i32, Int, Int32) \
|
||||
TD(UINT, "uint", uint32_t, int, uint32, uint, uint32, u32, UInt, UInt32) \
|
||||
TD(LONG, "long", int64_t, long, int64, long, int64, i64, Long, Int64) \
|
||||
TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64, u64, ULong, UInt64) /* end int */ \
|
||||
TD(FLOAT, "float", float, float, float32, float, float32, f32, Float, Float32) /* begin float */ \
|
||||
TD(DOUBLE, "double", double, double, float64, double, float64, f64, Double, Double) /* end float/scalar */
|
||||
#define FLATBUFFERS_GEN_TYPES_POINTER(TD) \
|
||||
TD(STRING, "string", Offset<void>, int, int, StringOffset, int, unused) \
|
||||
TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused) \
|
||||
TD(STRUCT, "", Offset<void>, int, int, int, int, unused) \
|
||||
TD(UNION, "", Offset<void>, int, int, int, int, unused)
|
||||
|
||||
TD(STRING, "string", Offset<void>, int, int, StringOffset, int, unused, Int, Offset<String>) \
|
||||
TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused, Int, Offset<UOffset>) \
|
||||
TD(STRUCT, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>) \
|
||||
TD(UNION, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>)
|
||||
#define FLATBUFFERS_GEN_TYPE_ARRAY(TD) \
|
||||
TD(ARRAY, "", int, int, int, int, int, unused, Int, Offset<UOffset>)
|
||||
// The fields are:
|
||||
// - enum
|
||||
// - FlatBuffers schema type.
|
||||
@@ -75,13 +76,28 @@ namespace flatbuffers {
|
||||
// - C# / .Net type.
|
||||
// - Python type.
|
||||
// - Rust type.
|
||||
// - Kotlin type.
|
||||
|
||||
// using these macros, we can now write code dealing with types just once, e.g.
|
||||
|
||||
/*
|
||||
switch (type) {
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
|
||||
RTYPE) \
|
||||
RTYPE, KTYPE) \
|
||||
case BASE_TYPE_ ## ENUM: \
|
||||
// do something specific to CTYPE here
|
||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
}
|
||||
*/
|
||||
|
||||
// If not all FLATBUFFERS_GEN_() arguments are necessary for implementation
|
||||
// of FLATBUFFERS_TD, you can use a variadic macro (with __VA_ARGS__ if needed).
|
||||
// In the above example, only CTYPE is used to generate the code, it can be rewritten:
|
||||
|
||||
/*
|
||||
switch (type) {
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
|
||||
case BASE_TYPE_ ## ENUM: \
|
||||
// do something specific to CTYPE here
|
||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||
@@ -91,24 +107,23 @@ switch (type) {
|
||||
|
||||
#define FLATBUFFERS_GEN_TYPES(TD) \
|
||||
FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
|
||||
FLATBUFFERS_GEN_TYPES_POINTER(TD)
|
||||
FLATBUFFERS_GEN_TYPES_POINTER(TD) \
|
||||
FLATBUFFERS_GEN_TYPE_ARRAY(TD)
|
||||
|
||||
// Create an enum for all the types above.
|
||||
#ifdef __GNUC__
|
||||
__extension__ // Stop GCC complaining about trailing comma with -Wpendantic.
|
||||
#endif
|
||||
enum BaseType {
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
|
||||
RTYPE) \
|
||||
BASE_TYPE_ ## ENUM,
|
||||
#define FLATBUFFERS_TD(ENUM, ...) \
|
||||
BASE_TYPE_ ## ENUM,
|
||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
};
|
||||
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
|
||||
RTYPE) \
|
||||
static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \
|
||||
"define largest_scalar_t as " #CTYPE);
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
|
||||
static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \
|
||||
"define largest_scalar_t as " #CTYPE);
|
||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
|
||||
@@ -123,6 +138,13 @@ inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
|
||||
inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; }
|
||||
inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE &&
|
||||
t <= BASE_TYPE_UCHAR; }
|
||||
|
||||
inline bool IsUnsigned(BaseType t) {
|
||||
return (t == BASE_TYPE_UTYPE) || (t == BASE_TYPE_UCHAR) ||
|
||||
(t == BASE_TYPE_USHORT) || (t == BASE_TYPE_UINT) ||
|
||||
(t == BASE_TYPE_ULONG);
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
|
||||
extern const char *const kTypeNames[];
|
||||
@@ -138,18 +160,21 @@ class Parser;
|
||||
// and additional information for vectors/structs_.
|
||||
struct Type {
|
||||
explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr,
|
||||
EnumDef *_ed = nullptr)
|
||||
EnumDef *_ed = nullptr, uint16_t _fixed_length = 0)
|
||||
: base_type(_base_type),
|
||||
element(BASE_TYPE_NONE),
|
||||
struct_def(_sd),
|
||||
enum_def(_ed) {}
|
||||
enum_def(_ed),
|
||||
fixed_length(_fixed_length) {}
|
||||
|
||||
bool operator==(const Type &o) {
|
||||
return base_type == o.base_type && element == o.element &&
|
||||
struct_def == o.struct_def && enum_def == o.enum_def;
|
||||
}
|
||||
|
||||
Type VectorType() const { return Type(element, struct_def, enum_def); }
|
||||
Type VectorType() const {
|
||||
return Type(element, struct_def, enum_def, fixed_length);
|
||||
}
|
||||
|
||||
Offset<reflection::Type> Serialize(FlatBufferBuilder *builder) const;
|
||||
|
||||
@@ -160,6 +185,7 @@ struct Type {
|
||||
StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT
|
||||
EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE,
|
||||
// or for an integral type derived from an enum.
|
||||
uint16_t fixed_length; // only set if t == BASE_TYPE_ARRAY
|
||||
};
|
||||
|
||||
// Represents a parsed scalar value, it's type, and field offset.
|
||||
@@ -224,6 +250,15 @@ struct Namespace {
|
||||
size_t from_table; // Part of the namespace corresponds to a message/table.
|
||||
};
|
||||
|
||||
inline bool operator<(const Namespace &a, const Namespace &b) {
|
||||
size_t min_size = std::min(a.components.size(), b.components.size());
|
||||
for (size_t i = 0; i < min_size; ++i) {
|
||||
if (a.components[i] != b.components[i])
|
||||
return a.components[i] < b.components[i];
|
||||
}
|
||||
return a.components.size() < b.components.size();
|
||||
}
|
||||
|
||||
// Base class for all definition types (fields, structs_, enums_).
|
||||
struct Definition {
|
||||
Definition()
|
||||
@@ -315,64 +350,138 @@ struct StructDef : public Definition {
|
||||
flatbuffers::unique_ptr<std::string> original_location;
|
||||
};
|
||||
|
||||
inline bool IsStruct(const Type &type) {
|
||||
return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
|
||||
}
|
||||
|
||||
inline size_t InlineSize(const Type &type) {
|
||||
return IsStruct(type) ? type.struct_def->bytesize : SizeOf(type.base_type);
|
||||
}
|
||||
|
||||
inline size_t InlineAlignment(const Type &type) {
|
||||
return IsStruct(type) ? type.struct_def->minalign : SizeOf(type.base_type);
|
||||
}
|
||||
struct EnumDef;
|
||||
struct EnumValBuilder;
|
||||
|
||||
struct EnumVal {
|
||||
EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
|
||||
EnumVal() : value(0) {}
|
||||
|
||||
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder,
|
||||
const Parser &parser) const;
|
||||
|
||||
bool Deserialize(const Parser &parser, const reflection::EnumVal *val);
|
||||
|
||||
uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); }
|
||||
int64_t GetAsInt64() const { return value; }
|
||||
bool IsZero() const { return 0 == value; }
|
||||
bool IsNonZero() const { return !IsZero(); }
|
||||
|
||||
std::string name;
|
||||
std::vector<std::string> doc_comment;
|
||||
int64_t value;
|
||||
Type union_type;
|
||||
|
||||
private:
|
||||
friend EnumDef;
|
||||
friend EnumValBuilder;
|
||||
friend bool operator==(const EnumVal &lhs, const EnumVal &rhs);
|
||||
|
||||
EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
|
||||
EnumVal() : value(0) {}
|
||||
|
||||
int64_t value;
|
||||
};
|
||||
|
||||
struct EnumDef : public Definition {
|
||||
EnumDef() : is_union(false), uses_multiple_type_instances(false) {}
|
||||
|
||||
EnumVal *ReverseLookup(int64_t enum_idx, bool skip_union_default = true) {
|
||||
for (auto it = Vals().begin() +
|
||||
static_cast<int>(is_union && skip_union_default);
|
||||
it != Vals().end(); ++it) {
|
||||
if ((*it)->value == enum_idx) { return *it; }
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||
Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder,
|
||||
const Parser &parser) const;
|
||||
|
||||
bool Deserialize(Parser &parser, const reflection::Enum *values);
|
||||
|
||||
template<typename T> void ChangeEnumValue(EnumVal *ev, T new_val);
|
||||
void SortByValue();
|
||||
void RemoveDuplicates();
|
||||
|
||||
std::string AllFlags() const;
|
||||
const EnumVal *MinValue() const;
|
||||
const EnumVal *MaxValue() const;
|
||||
// Returns the number of integer steps from v1 to v2.
|
||||
uint64_t Distance(const EnumVal *v1, const EnumVal *v2) const;
|
||||
// Returns the number of integer steps from Min to Max.
|
||||
uint64_t Distance() const { return Distance(MinValue(), MaxValue()); }
|
||||
|
||||
EnumVal *ReverseLookup(int64_t enum_idx,
|
||||
bool skip_union_default = false) const;
|
||||
EnumVal *FindByValue(const std::string &constant) const;
|
||||
|
||||
std::string ToString(const EnumVal &ev) const {
|
||||
return IsUInt64() ? NumToString(ev.GetAsUInt64())
|
||||
: NumToString(ev.GetAsInt64());
|
||||
}
|
||||
|
||||
size_t size() const { return vals.vec.size(); }
|
||||
|
||||
const std::vector<EnumVal *> &Vals() const {
|
||||
return vals.vec;
|
||||
}
|
||||
|
||||
SymbolTable<EnumVal> vals;
|
||||
const EnumVal *Lookup(const std::string &enum_name) const {
|
||||
return vals.Lookup(enum_name);
|
||||
}
|
||||
|
||||
bool is_union;
|
||||
// Type is a union which uses type aliases where at least one type is
|
||||
// available under two different names.
|
||||
bool uses_multiple_type_instances;
|
||||
Type underlying_type;
|
||||
|
||||
private:
|
||||
bool IsUInt64() const {
|
||||
return (BASE_TYPE_ULONG == underlying_type.base_type);
|
||||
}
|
||||
|
||||
friend EnumValBuilder;
|
||||
SymbolTable<EnumVal> vals;
|
||||
};
|
||||
|
||||
inline bool IsStruct(const Type &type) {
|
||||
return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
|
||||
}
|
||||
|
||||
inline bool IsUnion(const Type &type) {
|
||||
return type.enum_def != nullptr && type.enum_def->is_union;
|
||||
}
|
||||
|
||||
inline bool IsVector(const Type &type) {
|
||||
return type.base_type == BASE_TYPE_VECTOR;
|
||||
}
|
||||
|
||||
inline bool IsArray(const Type &type) {
|
||||
return type.base_type == BASE_TYPE_ARRAY;
|
||||
}
|
||||
|
||||
inline bool IsSeries(const Type &type) {
|
||||
return IsVector(type) || IsArray(type);
|
||||
}
|
||||
|
||||
inline bool IsEnum(const Type &type) {
|
||||
return type.enum_def != nullptr && IsInteger(type.base_type);
|
||||
}
|
||||
|
||||
inline size_t InlineSize(const Type &type) {
|
||||
return IsStruct(type)
|
||||
? type.struct_def->bytesize
|
||||
: (IsArray(type)
|
||||
? InlineSize(type.VectorType()) * type.fixed_length
|
||||
: SizeOf(type.base_type));
|
||||
}
|
||||
|
||||
inline size_t InlineAlignment(const Type &type) {
|
||||
if (IsStruct(type)) {
|
||||
return type.struct_def->minalign;
|
||||
} else if (IsArray(type)) {
|
||||
return IsStruct(type.VectorType()) ? type.struct_def->minalign
|
||||
: SizeOf(type.element);
|
||||
} else {
|
||||
return SizeOf(type.base_type);
|
||||
}
|
||||
}
|
||||
inline bool operator==(const EnumVal &lhs, const EnumVal &rhs) {
|
||||
return lhs.value == rhs.value;
|
||||
}
|
||||
inline bool operator!=(const EnumVal &lhs, const EnumVal &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool EqualByName(const Type &a, const Type &b) {
|
||||
return a.base_type == b.base_type && a.element == b.element &&
|
||||
(a.struct_def == b.struct_def ||
|
||||
@@ -381,7 +490,8 @@ inline bool EqualByName(const Type &a, const Type &b) {
|
||||
}
|
||||
|
||||
struct RPCCall : public Definition {
|
||||
Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||
Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder,
|
||||
const Parser &parser) const;
|
||||
|
||||
bool Deserialize(Parser &parser, const reflection::RPCCall *call);
|
||||
|
||||
@@ -389,7 +499,8 @@ struct RPCCall : public Definition {
|
||||
};
|
||||
|
||||
struct ServiceDef : public Definition {
|
||||
Offset<reflection::Service> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||
Offset<reflection::Service> Serialize(FlatBufferBuilder *builder,
|
||||
const Parser &parser) const;
|
||||
bool Deserialize(Parser &parser, const reflection::Service *service);
|
||||
|
||||
SymbolTable<RPCCall> calls;
|
||||
@@ -397,6 +508,8 @@ struct ServiceDef : public Definition {
|
||||
|
||||
// Container of options that may apply to any of the source/text generators.
|
||||
struct IDLOptions {
|
||||
// Use flexbuffers instead for binary and text generation
|
||||
bool use_flexbuffers;
|
||||
bool strict_json;
|
||||
bool skip_js_exports;
|
||||
bool use_goog_js_export_format;
|
||||
@@ -420,6 +533,7 @@ struct IDLOptions {
|
||||
std::string cpp_object_api_string_type;
|
||||
bool cpp_object_api_string_flexible_constructor;
|
||||
bool gen_nullable;
|
||||
bool java_checkerframework;
|
||||
bool gen_generated;
|
||||
std::string object_prefix;
|
||||
std::string object_suffix;
|
||||
@@ -430,6 +544,7 @@ struct IDLOptions {
|
||||
bool keep_include_path;
|
||||
bool binary_schema_comments;
|
||||
bool binary_schema_builtins;
|
||||
bool binary_schema_gen_embed;
|
||||
bool skip_flatbuffers_import;
|
||||
std::string go_import;
|
||||
std::string go_namespace;
|
||||
@@ -439,6 +554,13 @@ struct IDLOptions {
|
||||
bool size_prefixed;
|
||||
std::string root_type;
|
||||
bool force_defaults;
|
||||
bool java_primitive_has_method;
|
||||
bool cs_gen_json_serializer;
|
||||
std::vector<std::string> cpp_includes;
|
||||
std::string cpp_std;
|
||||
std::string proto_namespace_suffix;
|
||||
std::string filename_suffix;
|
||||
std::string filename_extension;
|
||||
|
||||
// Possible options for the more general generator below.
|
||||
enum Language {
|
||||
@@ -457,6 +579,8 @@ struct IDLOptions {
|
||||
kLua = 1 << 12,
|
||||
kLobster = 1 << 13,
|
||||
kRust = 1 << 14,
|
||||
kKotlin = 1 << 15,
|
||||
kSwift = 1 << 16,
|
||||
kMAX
|
||||
};
|
||||
|
||||
@@ -470,12 +594,17 @@ struct IDLOptions {
|
||||
// for code generation.
|
||||
unsigned long lang_to_generate;
|
||||
|
||||
// If set (default behavior), empty string and vector fields will be set to
|
||||
// nullptr to make the flatbuffer more compact.
|
||||
bool set_empty_to_null;
|
||||
// If set (default behavior), empty string fields will be set to nullptr to
|
||||
// make the flatbuffer more compact.
|
||||
bool set_empty_strings_to_null;
|
||||
|
||||
// If set (default behavior), empty vector fields will be set to nullptr to
|
||||
// make the flatbuffer more compact.
|
||||
bool set_empty_vectors_to_null;
|
||||
|
||||
IDLOptions()
|
||||
: strict_json(false),
|
||||
: use_flexbuffers(false),
|
||||
strict_json(false),
|
||||
skip_js_exports(false),
|
||||
use_goog_js_export_format(false),
|
||||
use_ES6_js_export_format(false),
|
||||
@@ -497,6 +626,7 @@ struct IDLOptions {
|
||||
cpp_object_api_pointer_type("std::unique_ptr"),
|
||||
cpp_object_api_string_flexible_constructor(false),
|
||||
gen_nullable(false),
|
||||
java_checkerframework(false),
|
||||
gen_generated(false),
|
||||
object_suffix("T"),
|
||||
union_value_namespacing(true),
|
||||
@@ -505,16 +635,22 @@ struct IDLOptions {
|
||||
keep_include_path(false),
|
||||
binary_schema_comments(false),
|
||||
binary_schema_builtins(false),
|
||||
binary_schema_gen_embed(false),
|
||||
skip_flatbuffers_import(false),
|
||||
reexport_ts_modules(true),
|
||||
js_ts_short_names(false),
|
||||
protobuf_ascii_alike(false),
|
||||
size_prefixed(false),
|
||||
force_defaults(false),
|
||||
java_primitive_has_method(false),
|
||||
cs_gen_json_serializer(false),
|
||||
filename_suffix("_generated"),
|
||||
filename_extension(),
|
||||
lang(IDLOptions::kJava),
|
||||
mini_reflect(IDLOptions::kNone),
|
||||
lang_to_generate(0),
|
||||
set_empty_to_null(true) {}
|
||||
set_empty_strings_to_null(true),
|
||||
set_empty_vectors_to_null(true) {}
|
||||
};
|
||||
|
||||
// This encapsulates where the parser is in the current source file.
|
||||
@@ -607,15 +743,14 @@ class Parser : public ParserState {
|
||||
explicit Parser(const IDLOptions &options = IDLOptions())
|
||||
: current_namespace_(nullptr),
|
||||
empty_namespace_(nullptr),
|
||||
flex_builder_(256, flexbuffers::BUILDER_FLAG_SHARE_ALL),
|
||||
root_struct_def_(nullptr),
|
||||
opts(options),
|
||||
uses_flexbuffers_(false),
|
||||
source_(nullptr),
|
||||
anonymous_counter(0),
|
||||
recurse_protection_counter(0) {
|
||||
if (opts.force_defaults) {
|
||||
builder_.ForceDefaults(true);
|
||||
}
|
||||
if (opts.force_defaults) { builder_.ForceDefaults(true); }
|
||||
// Start out with the empty namespace being current.
|
||||
empty_namespace_ = new Namespace();
|
||||
namespaces_.push_back(empty_namespace_);
|
||||
@@ -686,9 +821,9 @@ class Parser : public ParserState {
|
||||
|
||||
// Fills internal structure as if the schema passed had been loaded by parsing
|
||||
// with Parse except that included filenames will not be populated.
|
||||
bool Deserialize(const reflection::Schema* schema);
|
||||
bool Deserialize(const reflection::Schema *schema);
|
||||
|
||||
Type* DeserializeType(const reflection::Type* type);
|
||||
Type *DeserializeType(const reflection::Type *type);
|
||||
|
||||
// Checks that the schema represented by this parser is a safe evolution
|
||||
// of the schema provided. Returns non-empty error on any problems.
|
||||
@@ -701,7 +836,7 @@ class Parser : public ParserState {
|
||||
|
||||
StructDef *LookupStruct(const std::string &id) const;
|
||||
|
||||
std::string UnqualifiedName(std::string fullQualifiedName);
|
||||
std::string UnqualifiedName(const std::string &fullQualifiedName);
|
||||
|
||||
FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
|
||||
|
||||
@@ -738,20 +873,26 @@ class Parser : public ParserState {
|
||||
FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
|
||||
std::string *value, uoffset_t *ovalue);
|
||||
void SerializeStruct(const StructDef &struct_def, const Value &val);
|
||||
void SerializeStruct(FlatBufferBuilder &builder, const StructDef &struct_def,
|
||||
const Value &val);
|
||||
template<typename F>
|
||||
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
|
||||
FieldDef *field, size_t fieldn);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field,
|
||||
size_t fieldn,
|
||||
const StructDef *parent_struct_def);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array);
|
||||
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(const std::string *name, int dtoken, bool check, Value &e,
|
||||
BaseType req, bool *destmatch);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef* field);
|
||||
FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, 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(const std::string *name, Value &e, bool check_now);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type, std::string *result);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e,
|
||||
bool check_now);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type,
|
||||
std::string *result);
|
||||
StructDef *LookupCreateStruct(const std::string &name,
|
||||
bool create_if_new = true,
|
||||
bool definition = false);
|
||||
@@ -759,8 +900,7 @@ class Parser : public ParserState {
|
||||
FLATBUFFERS_CHECKED_ERROR ParseNamespace();
|
||||
FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
|
||||
StructDef **dest);
|
||||
FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name,
|
||||
bool is_union,
|
||||
FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name, bool is_union,
|
||||
EnumDef **dest);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseDecl();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseService();
|
||||
@@ -776,18 +916,18 @@ class Parser : public ParserState {
|
||||
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);
|
||||
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,
|
||||
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);
|
||||
const char *suffix, BaseType baseType);
|
||||
|
||||
bool SupportsAdvancedUnionFeatures() const;
|
||||
bool SupportsAdvancedArrayFeatures() const;
|
||||
Namespace *UniqueNamespace(Namespace *ns);
|
||||
|
||||
FLATBUFFERS_CHECKED_ERROR RecurseError();
|
||||
@@ -801,9 +941,11 @@ class Parser : public ParserState {
|
||||
std::vector<Namespace *> namespaces_;
|
||||
Namespace *current_namespace_;
|
||||
Namespace *empty_namespace_;
|
||||
std::string error_; // User readable error_ if Parse() == false
|
||||
std::string error_; // User readable error_ if Parse() == false
|
||||
|
||||
FlatBufferBuilder builder_; // any data contained in the file
|
||||
flexbuffers::Builder flex_builder_;
|
||||
flexbuffers::Reference flex_root_;
|
||||
StructDef *root_struct_def_;
|
||||
std::string file_identifier_;
|
||||
std::string file_extension_;
|
||||
@@ -832,6 +974,8 @@ class Parser : public ParserState {
|
||||
|
||||
extern std::string MakeCamel(const std::string &in, bool first = true);
|
||||
|
||||
extern std::string MakeScreamingCamel(const std::string &in);
|
||||
|
||||
// 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,
|
||||
@@ -840,156 +984,154 @@ extern std::string MakeCamel(const std::string &in, bool first = true);
|
||||
// strict_json adds "quotes" around field names if true.
|
||||
// If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8
|
||||
// byte arrays in String values), returns false.
|
||||
extern bool GenerateTextFromTable(const Parser &parser,
|
||||
const void *table,
|
||||
extern bool GenerateTextFromTable(const Parser &parser, const void *table,
|
||||
const std::string &tablename,
|
||||
std::string *text);
|
||||
extern bool GenerateText(const Parser &parser,
|
||||
const void *flatbuffer,
|
||||
extern bool GenerateText(const Parser &parser, const void *flatbuffer,
|
||||
std::string *text);
|
||||
extern bool GenerateTextFile(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern bool GenerateTextFile(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate binary files from a given FlatBuffer, and a given Parser
|
||||
// object that has been populated with the corresponding schema.
|
||||
// See idl_gen_general.cpp.
|
||||
extern bool GenerateBinary(const Parser &parser,
|
||||
const std::string &path,
|
||||
// See code_generators.cpp.
|
||||
extern bool GenerateBinary(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a C++ header from the definitions in the Parser object.
|
||||
// See idl_gen_cpp.
|
||||
extern bool GenerateCPP(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern bool GenerateCPP(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
extern bool GenerateDart(const Parser &parser,
|
||||
const std::string &path,
|
||||
// Generate C# files from the definitions in the Parser object.
|
||||
// See idl_gen_csharp.cpp.
|
||||
extern bool GenerateCSharp(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
extern bool GenerateDart(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate JavaScript or TypeScript code from the definitions in the Parser object.
|
||||
// See idl_gen_js.
|
||||
extern bool GenerateJSTS(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
// Generate Java files from the definitions in the Parser object.
|
||||
// See idl_gen_java.cpp.
|
||||
extern bool GenerateJava(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate JavaScript or TypeScript code from the definitions in the Parser
|
||||
// object. See idl_gen_js.
|
||||
extern bool GenerateJSTS(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Go files from the definitions in the Parser object.
|
||||
// See idl_gen_go.cpp.
|
||||
extern bool GenerateGo(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern bool GenerateGo(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Php code from the definitions in the Parser object.
|
||||
// See idl_gen_php.
|
||||
extern bool GeneratePhp(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern bool GeneratePhp(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Python files from the definitions in the Parser object.
|
||||
// See idl_gen_python.cpp.
|
||||
extern bool GeneratePython(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern bool GeneratePython(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Lobster files from the definitions in the Parser object.
|
||||
// See idl_gen_lobster.cpp.
|
||||
extern bool GenerateLobster(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern bool GenerateLobster(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Lua files from the definitions in the Parser object.
|
||||
// See idl_gen_lua.cpp.
|
||||
extern bool GenerateLua(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
extern bool GenerateLua(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Rust files from the definitions in the Parser object.
|
||||
// See idl_gen_rust.cpp.
|
||||
extern bool GenerateRust(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern bool GenerateRust(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,
|
||||
extern bool GenerateJsonSchema(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
extern bool GenerateKotlin(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Java/C#/.. files from the definitions in the Parser object.
|
||||
// See idl_gen_general.cpp.
|
||||
extern bool GenerateGeneral(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
// Generate Swift classes.
|
||||
// See idl_gen_swift.cpp
|
||||
extern bool GenerateSwift(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a schema file from the internal representation, useful after
|
||||
// parsing a .proto schema.
|
||||
extern std::string GenerateFBS(const Parser &parser,
|
||||
const std::string &file_name);
|
||||
extern bool GenerateFBS(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern bool GenerateFBS(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated JavaScript or TypeScript code.
|
||||
// See idl_gen_js.cpp.
|
||||
extern std::string JSTSMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
extern std::string JSTSMakeRule(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated C++ header.
|
||||
// See idl_gen_cpp.cpp.
|
||||
extern std::string CPPMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern std::string CPPMakeRule(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated Dart code
|
||||
// see idl_gen_dart.cpp
|
||||
extern std::string DartMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern std::string DartMakeRule(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated Rust code.
|
||||
// See idl_gen_rust.cpp.
|
||||
extern std::string RustMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern std::string RustMakeRule(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated Java/C#/... files.
|
||||
// See idl_gen_general.cpp.
|
||||
extern std::string GeneralMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
// Generate a make rule for generated Java or C# files.
|
||||
// See code_generators.cpp.
|
||||
extern std::string JavaCSharpMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated text (JSON) files.
|
||||
// See idl_gen_text.cpp.
|
||||
extern std::string TextMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern std::string TextMakeRule(const Parser &parser, const std::string &path,
|
||||
const std::string &file_names);
|
||||
|
||||
// Generate a make rule for the generated binary files.
|
||||
// See idl_gen_general.cpp.
|
||||
extern std::string BinaryMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
// See code_generators.cpp.
|
||||
extern std::string BinaryMakeRule(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate GRPC Cpp interfaces.
|
||||
// See idl_gen_grpc.cpp.
|
||||
bool GenerateCppGRPC(const Parser &parser,
|
||||
const std::string &path,
|
||||
bool GenerateCppGRPC(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate GRPC Go interfaces.
|
||||
// See idl_gen_grpc.cpp.
|
||||
bool GenerateGoGRPC(const Parser &parser,
|
||||
const std::string &path,
|
||||
bool GenerateGoGRPC(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate GRPC Java classes.
|
||||
// See idl_gen_grpc.cpp
|
||||
bool GenerateJavaGRPC(const Parser &parser,
|
||||
const std::string &path,
|
||||
bool GenerateJavaGRPC(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate GRPC Python interfaces.
|
||||
// See idl_gen_grpc.cpp.
|
||||
bool GeneratePythonGRPC(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate GRPC Swift interfaces.
|
||||
// See idl_gen_grpc.cpp.
|
||||
extern bool GenerateSwiftGRPC(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_IDL_H_
|
||||
|
||||
@@ -88,7 +88,8 @@ inline size_t InlineSize(ElementaryType type, const TypeTable *type_table) {
|
||||
switch (type_table->st) {
|
||||
case ST_TABLE:
|
||||
case ST_UNION: return 4;
|
||||
case ST_STRUCT: return static_cast<size_t>(type_table->values[type_table->num_elems]);
|
||||
case ST_STRUCT:
|
||||
return static_cast<size_t>(type_table->values[type_table->num_elems]);
|
||||
default: FLATBUFFERS_ASSERT(false); return 1;
|
||||
}
|
||||
default: FLATBUFFERS_ASSERT(false); return 1;
|
||||
|
||||
@@ -228,7 +228,7 @@ inline std::string GetAnyVectorElemS(const VectorOfAny *vec,
|
||||
template<typename T>
|
||||
T *GetAnyVectorElemPointer(const VectorOfAny *vec, size_t i) {
|
||||
auto elem_ptr = vec->Data() + sizeof(uoffset_t) * i;
|
||||
return reinterpret_cast<T*>(elem_ptr + ReadScalar<uoffset_t>(elem_ptr));
|
||||
return reinterpret_cast<T *>(elem_ptr + ReadScalar<uoffset_t>(elem_ptr));
|
||||
}
|
||||
|
||||
// Get the inline-address of a vector element. Useful for Structs (pass Struct
|
||||
|
||||
@@ -9,22 +9,31 @@
|
||||
namespace reflection {
|
||||
|
||||
struct Type;
|
||||
struct TypeBuilder;
|
||||
|
||||
struct KeyValue;
|
||||
struct KeyValueBuilder;
|
||||
|
||||
struct EnumVal;
|
||||
struct EnumValBuilder;
|
||||
|
||||
struct Enum;
|
||||
struct EnumBuilder;
|
||||
|
||||
struct Field;
|
||||
struct FieldBuilder;
|
||||
|
||||
struct Object;
|
||||
struct ObjectBuilder;
|
||||
|
||||
struct RPCCall;
|
||||
struct RPCCallBuilder;
|
||||
|
||||
struct Service;
|
||||
struct ServiceBuilder;
|
||||
|
||||
struct Schema;
|
||||
struct SchemaBuilder;
|
||||
|
||||
enum BaseType {
|
||||
None = 0,
|
||||
@@ -43,10 +52,11 @@ enum BaseType {
|
||||
String = 13,
|
||||
Vector = 14,
|
||||
Obj = 15,
|
||||
Union = 16
|
||||
Union = 16,
|
||||
Array = 17
|
||||
};
|
||||
|
||||
inline const BaseType (&EnumValuesBaseType())[17] {
|
||||
inline const BaseType (&EnumValuesBaseType())[18] {
|
||||
static const BaseType values[] = {
|
||||
None,
|
||||
UType,
|
||||
@@ -64,13 +74,14 @@ inline const BaseType (&EnumValuesBaseType())[17] {
|
||||
String,
|
||||
Vector,
|
||||
Obj,
|
||||
Union
|
||||
Union,
|
||||
Array
|
||||
};
|
||||
return values;
|
||||
}
|
||||
|
||||
inline const char * const *EnumNamesBaseType() {
|
||||
static const char * const names[] = {
|
||||
static const char * const names[19] = {
|
||||
"None",
|
||||
"UType",
|
||||
"Bool",
|
||||
@@ -88,53 +99,64 @@ inline const char * const *EnumNamesBaseType() {
|
||||
"Vector",
|
||||
"Obj",
|
||||
"Union",
|
||||
"Array",
|
||||
nullptr
|
||||
};
|
||||
return names;
|
||||
}
|
||||
|
||||
inline const char *EnumNameBaseType(BaseType e) {
|
||||
if (e < None || e > Union) return "";
|
||||
if (flatbuffers::IsOutRange(e, None, Array)) return "";
|
||||
const size_t index = static_cast<size_t>(e);
|
||||
return EnumNamesBaseType()[index];
|
||||
}
|
||||
|
||||
struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef TypeBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_BASE_TYPE = 4,
|
||||
VT_ELEMENT = 6,
|
||||
VT_INDEX = 8
|
||||
VT_INDEX = 8,
|
||||
VT_FIXED_LENGTH = 10
|
||||
};
|
||||
BaseType base_type() const {
|
||||
return static_cast<BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0));
|
||||
reflection::BaseType base_type() const {
|
||||
return static_cast<reflection::BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0));
|
||||
}
|
||||
BaseType element() const {
|
||||
return static_cast<BaseType>(GetField<int8_t>(VT_ELEMENT, 0));
|
||||
reflection::BaseType element() const {
|
||||
return static_cast<reflection::BaseType>(GetField<int8_t>(VT_ELEMENT, 0));
|
||||
}
|
||||
int32_t index() const {
|
||||
return GetField<int32_t>(VT_INDEX, -1);
|
||||
}
|
||||
uint16_t fixed_length() const {
|
||||
return GetField<uint16_t>(VT_FIXED_LENGTH, 0);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<int8_t>(verifier, VT_BASE_TYPE) &&
|
||||
VerifyField<int8_t>(verifier, VT_ELEMENT) &&
|
||||
VerifyField<int32_t>(verifier, VT_INDEX) &&
|
||||
VerifyField<uint16_t>(verifier, VT_FIXED_LENGTH) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct TypeBuilder {
|
||||
typedef Type Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_base_type(BaseType base_type) {
|
||||
void add_base_type(reflection::BaseType base_type) {
|
||||
fbb_.AddElement<int8_t>(Type::VT_BASE_TYPE, static_cast<int8_t>(base_type), 0);
|
||||
}
|
||||
void add_element(BaseType element) {
|
||||
void add_element(reflection::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);
|
||||
}
|
||||
void add_fixed_length(uint16_t fixed_length) {
|
||||
fbb_.AddElement<uint16_t>(Type::VT_FIXED_LENGTH, fixed_length, 0);
|
||||
}
|
||||
explicit TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
@@ -149,17 +171,20 @@ struct TypeBuilder {
|
||||
|
||||
inline flatbuffers::Offset<Type> CreateType(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
BaseType base_type = None,
|
||||
BaseType element = None,
|
||||
int32_t index = -1) {
|
||||
reflection::BaseType base_type = reflection::None,
|
||||
reflection::BaseType element = reflection::None,
|
||||
int32_t index = -1,
|
||||
uint16_t fixed_length = 0) {
|
||||
TypeBuilder builder_(_fbb);
|
||||
builder_.add_index(index);
|
||||
builder_.add_fixed_length(fixed_length);
|
||||
builder_.add_element(element);
|
||||
builder_.add_base_type(base_type);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef KeyValueBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_KEY = 4,
|
||||
VT_VALUE = 6
|
||||
@@ -187,6 +212,7 @@ struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
};
|
||||
|
||||
struct KeyValueBuilder {
|
||||
typedef KeyValue Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_key(flatbuffers::Offset<flatbuffers::String> key) {
|
||||
@@ -231,6 +257,7 @@ inline flatbuffers::Offset<KeyValue> CreateKeyValueDirect(
|
||||
}
|
||||
|
||||
struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef EnumValBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_NAME = 4,
|
||||
VT_VALUE = 6,
|
||||
@@ -250,11 +277,11 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
int KeyCompareWithValue(int64_t val) const {
|
||||
return static_cast<int>(value() > val) - static_cast<int>(value() < val);
|
||||
}
|
||||
const Object *object() const {
|
||||
return GetPointer<const Object *>(VT_OBJECT);
|
||||
const reflection::Object *object() const {
|
||||
return GetPointer<const reflection::Object *>(VT_OBJECT);
|
||||
}
|
||||
const Type *union_type() const {
|
||||
return GetPointer<const Type *>(VT_UNION_TYPE);
|
||||
const reflection::Type *union_type() const {
|
||||
return GetPointer<const reflection::Type *>(VT_UNION_TYPE);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||
@@ -276,6 +303,7 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
};
|
||||
|
||||
struct EnumValBuilder {
|
||||
typedef EnumVal Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
@@ -284,10 +312,10 @@ struct EnumValBuilder {
|
||||
void add_value(int64_t value) {
|
||||
fbb_.AddElement<int64_t>(EnumVal::VT_VALUE, value, 0);
|
||||
}
|
||||
void add_object(flatbuffers::Offset<Object> object) {
|
||||
void add_object(flatbuffers::Offset<reflection::Object> object) {
|
||||
fbb_.AddOffset(EnumVal::VT_OBJECT, object);
|
||||
}
|
||||
void add_union_type(flatbuffers::Offset<Type> union_type) {
|
||||
void add_union_type(flatbuffers::Offset<reflection::Type> union_type) {
|
||||
fbb_.AddOffset(EnumVal::VT_UNION_TYPE, union_type);
|
||||
}
|
||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||
@@ -310,8 +338,8 @@ 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<Type> union_type = 0,
|
||||
flatbuffers::Offset<reflection::Object> object = 0,
|
||||
flatbuffers::Offset<reflection::Type> union_type = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||
EnumValBuilder builder_(_fbb);
|
||||
builder_.add_value(value);
|
||||
@@ -326,8 +354,8 @@ inline flatbuffers::Offset<EnumVal> CreateEnumValDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
int64_t value = 0,
|
||||
flatbuffers::Offset<Object> object = 0,
|
||||
flatbuffers::Offset<Type> union_type = 0,
|
||||
flatbuffers::Offset<reflection::Object> object = 0,
|
||||
flatbuffers::Offset<reflection::Type> union_type = 0,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||
@@ -341,6 +369,7 @@ inline flatbuffers::Offset<EnumVal> CreateEnumValDirect(
|
||||
}
|
||||
|
||||
struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef EnumBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_NAME = 4,
|
||||
VT_VALUES = 6,
|
||||
@@ -358,17 +387,17 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
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);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>> *values() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::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 reflection::Type *underlying_type() const {
|
||||
return GetPointer<const reflection::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<reflection::KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||
@@ -394,21 +423,22 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
};
|
||||
|
||||
struct EnumBuilder {
|
||||
typedef Enum Table;
|
||||
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) {
|
||||
void add_values(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::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) {
|
||||
void add_underlying_type(flatbuffers::Offset<reflection::Type> underlying_type) {
|
||||
fbb_.AddOffset(Enum::VT_UNDERLYING_TYPE, underlying_type);
|
||||
}
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) {
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
|
||||
fbb_.AddOffset(Enum::VT_ATTRIBUTES, attributes);
|
||||
}
|
||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||
@@ -432,10 +462,10 @@ struct EnumBuilder {
|
||||
inline flatbuffers::Offset<Enum> CreateEnum(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<EnumVal>>> values = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>>> values = 0,
|
||||
bool is_union = false,
|
||||
flatbuffers::Offset<Type> underlying_type = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<reflection::Type> underlying_type = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||
EnumBuilder builder_(_fbb);
|
||||
builder_.add_documentation(documentation);
|
||||
@@ -450,14 +480,14 @@ inline flatbuffers::Offset<Enum> CreateEnum(
|
||||
inline flatbuffers::Offset<Enum> CreateEnumDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
const std::vector<flatbuffers::Offset<EnumVal>> *values = nullptr,
|
||||
std::vector<flatbuffers::Offset<reflection::EnumVal>> *values = nullptr,
|
||||
bool is_union = false,
|
||||
flatbuffers::Offset<Type> underlying_type = 0,
|
||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||
flatbuffers::Offset<reflection::Type> underlying_type = 0,
|
||||
std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||
auto values__ = values ? _fbb.CreateVector<flatbuffers::Offset<EnumVal>>(*values) : 0;
|
||||
auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0;
|
||||
auto values__ = values ? _fbb.CreateVectorOfSortedTables<reflection::EnumVal>(values) : 0;
|
||||
auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
|
||||
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||
return reflection::CreateEnum(
|
||||
_fbb,
|
||||
@@ -470,6 +500,7 @@ inline flatbuffers::Offset<Enum> CreateEnumDirect(
|
||||
}
|
||||
|
||||
struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef FieldBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_NAME = 4,
|
||||
VT_TYPE = 6,
|
||||
@@ -492,8 +523,8 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
int KeyCompareWithValue(const char *val) const {
|
||||
return strcmp(name()->c_str(), val);
|
||||
}
|
||||
const Type *type() const {
|
||||
return GetPointer<const Type *>(VT_TYPE);
|
||||
const reflection::Type *type() const {
|
||||
return GetPointer<const reflection::Type *>(VT_TYPE);
|
||||
}
|
||||
uint16_t id() const {
|
||||
return GetField<uint16_t>(VT_ID, 0);
|
||||
@@ -516,8 +547,8 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
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<reflection::KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||
@@ -546,12 +577,13 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
};
|
||||
|
||||
struct FieldBuilder {
|
||||
typedef Field Table;
|
||||
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) {
|
||||
void add_type(flatbuffers::Offset<reflection::Type> type) {
|
||||
fbb_.AddOffset(Field::VT_TYPE, type);
|
||||
}
|
||||
void add_id(uint16_t id) {
|
||||
@@ -575,7 +607,7 @@ struct FieldBuilder {
|
||||
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) {
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
|
||||
fbb_.AddOffset(Field::VT_ATTRIBUTES, attributes);
|
||||
}
|
||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||
@@ -598,7 +630,7 @@ struct FieldBuilder {
|
||||
inline flatbuffers::Offset<Field> CreateField(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<Type> type = 0,
|
||||
flatbuffers::Offset<reflection::Type> type = 0,
|
||||
uint16_t id = 0,
|
||||
uint16_t offset = 0,
|
||||
int64_t default_integer = 0,
|
||||
@@ -606,7 +638,7 @@ inline flatbuffers::Offset<Field> CreateField(
|
||||
bool deprecated = false,
|
||||
bool required = false,
|
||||
bool key = false,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||
FieldBuilder builder_(_fbb);
|
||||
builder_.add_default_real(default_real);
|
||||
@@ -626,7 +658,7 @@ inline flatbuffers::Offset<Field> CreateField(
|
||||
inline flatbuffers::Offset<Field> CreateFieldDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
flatbuffers::Offset<Type> type = 0,
|
||||
flatbuffers::Offset<reflection::Type> type = 0,
|
||||
uint16_t id = 0,
|
||||
uint16_t offset = 0,
|
||||
int64_t default_integer = 0,
|
||||
@@ -634,10 +666,10 @@ inline flatbuffers::Offset<Field> CreateFieldDirect(
|
||||
bool deprecated = false,
|
||||
bool required = false,
|
||||
bool key = false,
|
||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||
std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||
auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0;
|
||||
auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
|
||||
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||
return reflection::CreateField(
|
||||
_fbb,
|
||||
@@ -655,6 +687,7 @@ inline flatbuffers::Offset<Field> CreateFieldDirect(
|
||||
}
|
||||
|
||||
struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef ObjectBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_NAME = 4,
|
||||
VT_FIELDS = 6,
|
||||
@@ -673,8 +706,8 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
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);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::Field>> *fields() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Field>> *>(VT_FIELDS);
|
||||
}
|
||||
bool is_struct() const {
|
||||
return GetField<uint8_t>(VT_IS_STRUCT, 0) != 0;
|
||||
@@ -685,8 +718,8 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
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<reflection::KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||
@@ -712,12 +745,13 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
};
|
||||
|
||||
struct ObjectBuilder {
|
||||
typedef Object Table;
|
||||
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) {
|
||||
void add_fields(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Field>>> fields) {
|
||||
fbb_.AddOffset(Object::VT_FIELDS, fields);
|
||||
}
|
||||
void add_is_struct(bool is_struct) {
|
||||
@@ -729,7 +763,7 @@ struct ObjectBuilder {
|
||||
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) {
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
|
||||
fbb_.AddOffset(Object::VT_ATTRIBUTES, attributes);
|
||||
}
|
||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||
@@ -752,11 +786,11 @@ struct ObjectBuilder {
|
||||
inline flatbuffers::Offset<Object> CreateObject(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> fields = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::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<reflection::KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||
ObjectBuilder builder_(_fbb);
|
||||
builder_.add_documentation(documentation);
|
||||
@@ -772,15 +806,15 @@ inline flatbuffers::Offset<Object> CreateObject(
|
||||
inline flatbuffers::Offset<Object> CreateObjectDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
const std::vector<flatbuffers::Offset<Field>> *fields = nullptr,
|
||||
std::vector<flatbuffers::Offset<reflection::Field>> *fields = nullptr,
|
||||
bool is_struct = false,
|
||||
int32_t minalign = 0,
|
||||
int32_t bytesize = 0,
|
||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||
std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||
auto fields__ = fields ? _fbb.CreateVector<flatbuffers::Offset<Field>>(*fields) : 0;
|
||||
auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0;
|
||||
auto fields__ = fields ? _fbb.CreateVectorOfSortedTables<reflection::Field>(fields) : 0;
|
||||
auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
|
||||
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||
return reflection::CreateObject(
|
||||
_fbb,
|
||||
@@ -794,6 +828,7 @@ inline flatbuffers::Offset<Object> CreateObjectDirect(
|
||||
}
|
||||
|
||||
struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef RPCCallBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_NAME = 4,
|
||||
VT_REQUEST = 6,
|
||||
@@ -810,14 +845,14 @@ struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
int KeyCompareWithValue(const char *val) const {
|
||||
return strcmp(name()->c_str(), val);
|
||||
}
|
||||
const Object *request() const {
|
||||
return GetPointer<const Object *>(VT_REQUEST);
|
||||
const reflection::Object *request() const {
|
||||
return GetPointer<const reflection::Object *>(VT_REQUEST);
|
||||
}
|
||||
const Object *response() const {
|
||||
return GetPointer<const Object *>(VT_RESPONSE);
|
||||
const reflection::Object *response() const {
|
||||
return GetPointer<const reflection::Object *>(VT_RESPONSE);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||
@@ -841,18 +876,19 @@ struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
};
|
||||
|
||||
struct RPCCallBuilder {
|
||||
typedef RPCCall Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(RPCCall::VT_NAME, name);
|
||||
}
|
||||
void add_request(flatbuffers::Offset<Object> request) {
|
||||
void add_request(flatbuffers::Offset<reflection::Object> request) {
|
||||
fbb_.AddOffset(RPCCall::VT_REQUEST, request);
|
||||
}
|
||||
void add_response(flatbuffers::Offset<Object> response) {
|
||||
void add_response(flatbuffers::Offset<reflection::Object> response) {
|
||||
fbb_.AddOffset(RPCCall::VT_RESPONSE, response);
|
||||
}
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) {
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
|
||||
fbb_.AddOffset(RPCCall::VT_ATTRIBUTES, attributes);
|
||||
}
|
||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||
@@ -876,9 +912,9 @@ struct RPCCallBuilder {
|
||||
inline flatbuffers::Offset<RPCCall> CreateRPCCall(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<Object> request = 0,
|
||||
flatbuffers::Offset<Object> response = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<reflection::Object> request = 0,
|
||||
flatbuffers::Offset<reflection::Object> response = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||
RPCCallBuilder builder_(_fbb);
|
||||
builder_.add_documentation(documentation);
|
||||
@@ -892,12 +928,12 @@ inline flatbuffers::Offset<RPCCall> CreateRPCCall(
|
||||
inline flatbuffers::Offset<RPCCall> CreateRPCCallDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
flatbuffers::Offset<Object> request = 0,
|
||||
flatbuffers::Offset<Object> response = 0,
|
||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||
flatbuffers::Offset<reflection::Object> request = 0,
|
||||
flatbuffers::Offset<reflection::Object> response = 0,
|
||||
std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||
auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0;
|
||||
auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
|
||||
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||
return reflection::CreateRPCCall(
|
||||
_fbb,
|
||||
@@ -909,6 +945,7 @@ inline flatbuffers::Offset<RPCCall> CreateRPCCallDirect(
|
||||
}
|
||||
|
||||
struct Service FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef ServiceBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_NAME = 4,
|
||||
VT_CALLS = 6,
|
||||
@@ -924,11 +961,11 @@ struct Service FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
int KeyCompareWithValue(const char *val) const {
|
||||
return strcmp(name()->c_str(), val);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<RPCCall>> *calls() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<RPCCall>> *>(VT_CALLS);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>> *calls() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>> *>(VT_CALLS);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||
@@ -951,15 +988,16 @@ struct Service FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
};
|
||||
|
||||
struct ServiceBuilder {
|
||||
typedef Service Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(Service::VT_NAME, name);
|
||||
}
|
||||
void add_calls(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<RPCCall>>> calls) {
|
||||
void add_calls(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>>> calls) {
|
||||
fbb_.AddOffset(Service::VT_CALLS, calls);
|
||||
}
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) {
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
|
||||
fbb_.AddOffset(Service::VT_ATTRIBUTES, attributes);
|
||||
}
|
||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||
@@ -981,8 +1019,8 @@ struct ServiceBuilder {
|
||||
inline flatbuffers::Offset<Service> CreateService(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<RPCCall>>> calls = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>>> calls = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||
ServiceBuilder builder_(_fbb);
|
||||
builder_.add_documentation(documentation);
|
||||
@@ -995,12 +1033,12 @@ inline flatbuffers::Offset<Service> CreateService(
|
||||
inline flatbuffers::Offset<Service> CreateServiceDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
const std::vector<flatbuffers::Offset<RPCCall>> *calls = nullptr,
|
||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||
std::vector<flatbuffers::Offset<reflection::RPCCall>> *calls = nullptr,
|
||||
std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||
auto calls__ = calls ? _fbb.CreateVector<flatbuffers::Offset<RPCCall>>(*calls) : 0;
|
||||
auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0;
|
||||
auto calls__ = calls ? _fbb.CreateVectorOfSortedTables<reflection::RPCCall>(calls) : 0;
|
||||
auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
|
||||
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||
return reflection::CreateService(
|
||||
_fbb,
|
||||
@@ -1011,6 +1049,7 @@ inline flatbuffers::Offset<Service> CreateServiceDirect(
|
||||
}
|
||||
|
||||
struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
typedef SchemaBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_OBJECTS = 4,
|
||||
VT_ENUMS = 6,
|
||||
@@ -1019,11 +1058,11 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VT_ROOT_TABLE = 12,
|
||||
VT_SERVICES = 14
|
||||
};
|
||||
const flatbuffers::Vector<flatbuffers::Offset<Object>> *objects() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Object>> *>(VT_OBJECTS);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *objects() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *>(VT_OBJECTS);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<Enum>> *enums() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Enum>> *>(VT_ENUMS);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>> *enums() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>> *>(VT_ENUMS);
|
||||
}
|
||||
const flatbuffers::String *file_ident() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_FILE_IDENT);
|
||||
@@ -1031,11 +1070,11 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
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 reflection::Object *root_table() const {
|
||||
return GetPointer<const reflection::Object *>(VT_ROOT_TABLE);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<Service>> *services() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Service>> *>(VT_SERVICES);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::Service>> *services() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Service>> *>(VT_SERVICES);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
@@ -1059,12 +1098,13 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
};
|
||||
|
||||
struct SchemaBuilder {
|
||||
typedef Schema Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_objects(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Object>>> objects) {
|
||||
void add_objects(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Object>>> objects) {
|
||||
fbb_.AddOffset(Schema::VT_OBJECTS, objects);
|
||||
}
|
||||
void add_enums(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Enum>>> enums) {
|
||||
void add_enums(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>>> enums) {
|
||||
fbb_.AddOffset(Schema::VT_ENUMS, enums);
|
||||
}
|
||||
void add_file_ident(flatbuffers::Offset<flatbuffers::String> file_ident) {
|
||||
@@ -1073,10 +1113,10 @@ struct SchemaBuilder {
|
||||
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) {
|
||||
void add_root_table(flatbuffers::Offset<reflection::Object> root_table) {
|
||||
fbb_.AddOffset(Schema::VT_ROOT_TABLE, root_table);
|
||||
}
|
||||
void add_services(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Service>>> services) {
|
||||
void add_services(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Service>>> services) {
|
||||
fbb_.AddOffset(Schema::VT_SERVICES, services);
|
||||
}
|
||||
explicit SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
@@ -1095,12 +1135,12 @@ struct SchemaBuilder {
|
||||
|
||||
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::Vector<flatbuffers::Offset<reflection::Object>>> objects = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>>> enums = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> file_ident = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> file_ext = 0,
|
||||
flatbuffers::Offset<Object> root_table = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Service>>> services = 0) {
|
||||
flatbuffers::Offset<reflection::Object> root_table = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Service>>> services = 0) {
|
||||
SchemaBuilder builder_(_fbb);
|
||||
builder_.add_services(services);
|
||||
builder_.add_root_table(root_table);
|
||||
@@ -1113,17 +1153,17 @@ inline flatbuffers::Offset<Schema> CreateSchema(
|
||||
|
||||
inline flatbuffers::Offset<Schema> CreateSchemaDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const std::vector<flatbuffers::Offset<Object>> *objects = nullptr,
|
||||
const std::vector<flatbuffers::Offset<Enum>> *enums = nullptr,
|
||||
std::vector<flatbuffers::Offset<reflection::Object>> *objects = nullptr,
|
||||
std::vector<flatbuffers::Offset<reflection::Enum>> *enums = nullptr,
|
||||
const char *file_ident = nullptr,
|
||||
const char *file_ext = nullptr,
|
||||
flatbuffers::Offset<Object> root_table = 0,
|
||||
const std::vector<flatbuffers::Offset<Service>> *services = nullptr) {
|
||||
auto objects__ = objects ? _fbb.CreateVector<flatbuffers::Offset<Object>>(*objects) : 0;
|
||||
auto enums__ = enums ? _fbb.CreateVector<flatbuffers::Offset<Enum>>(*enums) : 0;
|
||||
flatbuffers::Offset<reflection::Object> root_table = 0,
|
||||
std::vector<flatbuffers::Offset<reflection::Service>> *services = nullptr) {
|
||||
auto objects__ = objects ? _fbb.CreateVectorOfSortedTables<reflection::Object>(objects) : 0;
|
||||
auto enums__ = enums ? _fbb.CreateVectorOfSortedTables<reflection::Enum>(enums) : 0;
|
||||
auto file_ident__ = file_ident ? _fbb.CreateString(file_ident) : 0;
|
||||
auto file_ext__ = file_ext ? _fbb.CreateString(file_ext) : 0;
|
||||
auto services__ = services ? _fbb.CreateVector<flatbuffers::Offset<Service>>(*services) : 0;
|
||||
auto services__ = services ? _fbb.CreateVectorOfSortedTables<reflection::Service>(services) : 0;
|
||||
return reflection::CreateSchema(
|
||||
_fbb,
|
||||
objects__,
|
||||
|
||||
@@ -96,13 +96,13 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
||||
}
|
||||
};
|
||||
|
||||
template <> class numeric_limits<float> :
|
||||
template <> class numeric_limits<float> :
|
||||
public std::numeric_limits<float> {
|
||||
public:
|
||||
static float lowest() { return -FLT_MAX; }
|
||||
};
|
||||
|
||||
template <> class numeric_limits<double> :
|
||||
template <> class numeric_limits<double> :
|
||||
public std::numeric_limits<double> {
|
||||
public:
|
||||
static double lowest() { return -DBL_MAX; }
|
||||
@@ -138,7 +138,12 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
||||
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>;
|
||||
template <typename T> using is_enum = std::is_enum<T>;
|
||||
template <typename T> using make_unsigned = std::make_unsigned<T>;
|
||||
template<bool B, class T, class F>
|
||||
using conditional = std::conditional<B, T, F>;
|
||||
template<class T, T v>
|
||||
using integral_constant = std::integral_constant<T, v>;
|
||||
#else
|
||||
// Map C++ TR1 templates defined by stlport.
|
||||
template <typename T> using is_scalar = std::tr1::is_scalar<T>;
|
||||
@@ -146,6 +151,7 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
||||
template <typename T> using is_floating_point =
|
||||
std::tr1::is_floating_point<T>;
|
||||
template <typename T> using is_unsigned = std::tr1::is_unsigned<T>;
|
||||
template <typename T> using is_enum = std::tr1::is_enum<T>;
|
||||
// Android NDK doesn't have std::make_unsigned or std::tr1::make_unsigned.
|
||||
template<typename T> struct make_unsigned {
|
||||
static_assert(is_unsigned<T>::value, "Specialization not implemented!");
|
||||
@@ -157,6 +163,10 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
||||
template<> struct make_unsigned<long> { using type = unsigned long; };
|
||||
template<>
|
||||
struct make_unsigned<long long> { using type = unsigned long long; };
|
||||
template<bool B, class T, class F>
|
||||
using conditional = std::tr1::conditional<B, T, F>;
|
||||
template<class T, T v>
|
||||
using integral_constant = std::tr1::integral_constant<T, v>;
|
||||
#endif // !FLATBUFFERS_CPP98_STL
|
||||
#else
|
||||
// MSVC 2010 doesn't support C++11 aliases.
|
||||
@@ -165,7 +175,12 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
||||
template <typename T> struct is_floating_point :
|
||||
public std::is_floating_point<T> {};
|
||||
template <typename T> struct is_unsigned : public std::is_unsigned<T> {};
|
||||
template <typename T> struct is_enum : public std::is_enum<T> {};
|
||||
template <typename T> struct make_unsigned : public std::make_unsigned<T> {};
|
||||
template<bool B, class T, class F>
|
||||
struct conditional : public std::conditional<B, T, F> {};
|
||||
template<class T, T v>
|
||||
struct integral_constant : public std::integral_constant<T, v> {};
|
||||
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
@@ -268,6 +283,23 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
||||
template <class T> bool operator==(const unique_ptr<T>& x, intptr_t y) {
|
||||
return reinterpret_cast<intptr_t>(x.get()) == y;
|
||||
}
|
||||
|
||||
template <class T> bool operator!=(const unique_ptr<T>& x, decltype(nullptr)) {
|
||||
return !!x;
|
||||
}
|
||||
|
||||
template <class T> bool operator!=(decltype(nullptr), const unique_ptr<T>& x) {
|
||||
return !!x;
|
||||
}
|
||||
|
||||
template <class T> bool operator==(const unique_ptr<T>& x, decltype(nullptr)) {
|
||||
return !x;
|
||||
}
|
||||
|
||||
template <class T> bool operator==(decltype(nullptr), const unique_ptr<T>& x) {
|
||||
return !x;
|
||||
}
|
||||
|
||||
#endif // !FLATBUFFERS_CPP98_STL
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
@@ -17,10 +17,10 @@
|
||||
#ifndef FLATBUFFERS_UTIL_H_
|
||||
#define FLATBUFFERS_UTIL_H_
|
||||
|
||||
#include "flatbuffers/base.h"
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "flatbuffers/base.h"
|
||||
|
||||
#ifndef FLATBUFFERS_PREFER_PRINTF
|
||||
# include <sstream>
|
||||
#else // FLATBUFFERS_PREFER_PRINTF
|
||||
@@ -102,7 +102,7 @@ std::string NumToStringImplWrapper(T t, const char *fmt, int precision = 0) {
|
||||
size_t string_width = NumToStringWidth(t, precision);
|
||||
std::string s(string_width, 0x00);
|
||||
// Allow snprintf to use std::string trailing null to detect buffer overflow
|
||||
snprintf(const_cast<char *>(s.data()), (s.size() + 1), fmt, precision, t);
|
||||
snprintf(const_cast<char *>(s.data()), (s.size() + 1), fmt, string_width, t);
|
||||
return s;
|
||||
}
|
||||
#endif // FLATBUFFERS_PREFER_PRINTF
|
||||
@@ -327,7 +327,7 @@ template<typename T> inline bool StringToNumber(const char *s, T *val) {
|
||||
int64_t i64;
|
||||
// The errno check isn't needed, will return MAX/MIN on overflow.
|
||||
if (StringToIntegerImpl(&i64, s, 0, false)) {
|
||||
const int64_t max = flatbuffers::numeric_limits<T>::max();
|
||||
const int64_t max = (flatbuffers::numeric_limits<T>::max)();
|
||||
const int64_t min = flatbuffers::numeric_limits<T>::lowest();
|
||||
if (i64 > max) {
|
||||
*val = static_cast<T>(max);
|
||||
@@ -365,7 +365,7 @@ inline bool StringToNumber<uint64_t>(const char *str, uint64_t *val) {
|
||||
if (*s == '-') {
|
||||
// For unsigned types return the max to distinguish from
|
||||
// "no conversion can be performed".
|
||||
*val = flatbuffers::numeric_limits<uint64_t>::max();
|
||||
*val = (flatbuffers::numeric_limits<uint64_t>::max)();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -636,6 +636,32 @@ inline bool EscapeString(const char *s, size_t length, std::string *_text,
|
||||
return true;
|
||||
}
|
||||
|
||||
inline std::string BufferToHexText(const void *buffer, size_t buffer_size,
|
||||
size_t max_length,
|
||||
const std::string &wrapped_line_prefix,
|
||||
const std::string &wrapped_line_suffix) {
|
||||
std::string text = wrapped_line_prefix;
|
||||
size_t start_offset = 0;
|
||||
const char *s = reinterpret_cast<const char *>(buffer);
|
||||
for (size_t i = 0; s && i < buffer_size; i++) {
|
||||
// Last iteration or do we have more?
|
||||
bool have_more = i + 1 < buffer_size;
|
||||
text += "0x";
|
||||
text += IntToStringHex(static_cast<uint8_t>(s[i]), 2);
|
||||
if (have_more) { text += ','; }
|
||||
// If we have more to process and we reached max_length
|
||||
if (have_more &&
|
||||
text.size() + wrapped_line_suffix.size() >= start_offset + max_length) {
|
||||
text += wrapped_line_suffix;
|
||||
text += '\n';
|
||||
start_offset = text.size();
|
||||
text += wrapped_line_prefix;
|
||||
}
|
||||
}
|
||||
text += wrapped_line_suffix;
|
||||
return text;
|
||||
}
|
||||
|
||||
// Remove paired quotes in a string: "text"|'text' -> text.
|
||||
std::string RemoveStringQuotes(const std::string &s);
|
||||
|
||||
@@ -649,6 +675,9 @@ bool SetGlobalTestLocale(const char *locale_name,
|
||||
bool ReadEnvironmentVariable(const char *var_name,
|
||||
std::string *_value = nullptr);
|
||||
|
||||
// MSVC specific: Send all assert reports to STDOUT to prevent CI hangs.
|
||||
void SetupDefaultCRTReportMode();
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_UTIL_H_
|
||||
|
||||
241
java/com/google/flatbuffers/ArrayReadWriteBuf.java
Normal file
241
java/com/google/flatbuffers/ArrayReadWriteBuf.java
Normal file
@@ -0,0 +1,241 @@
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Implements {@code ReadBuf} using an array of bytes
|
||||
* as a backing storage. Using array of bytes are
|
||||
* usually faster than {@code ByteBuffer}.
|
||||
*
|
||||
* This class is not thread-safe, meaning that
|
||||
* it must operate on a single thread. Operating from
|
||||
* multiple thread leads into a undefined behavior
|
||||
*/
|
||||
public class ArrayReadWriteBuf implements ReadWriteBuf {
|
||||
|
||||
private byte[] buffer;
|
||||
private int writePos;
|
||||
|
||||
public ArrayReadWriteBuf() {
|
||||
this(10);
|
||||
}
|
||||
|
||||
public ArrayReadWriteBuf(int initialCapacity) {
|
||||
this(new byte[initialCapacity]);
|
||||
}
|
||||
|
||||
public ArrayReadWriteBuf(byte[] buffer) {
|
||||
this.buffer = buffer;
|
||||
this.writePos = 0;
|
||||
}
|
||||
|
||||
public ArrayReadWriteBuf(byte[] buffer, int startPos) {
|
||||
this.buffer = buffer;
|
||||
this.writePos = startPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(int index) {
|
||||
return buffer[index] != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte get(int index) {
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort(int index) {
|
||||
return (short) ((buffer[index+ 1] << 8) | (buffer[index] & 0xff));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(int index) {
|
||||
return (((buffer[index + 3]) << 24) |
|
||||
((buffer[index + 2] & 0xff) << 16) |
|
||||
((buffer[index + 1] & 0xff) << 8) |
|
||||
((buffer[index] & 0xff)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(int index) {
|
||||
return ((((long) buffer[index++] & 0xff)) |
|
||||
(((long) buffer[index++] & 0xff) << 8) |
|
||||
(((long) buffer[index++] & 0xff) << 16) |
|
||||
(((long) buffer[index++] & 0xff) << 24) |
|
||||
(((long) buffer[index++] & 0xff) << 32) |
|
||||
(((long) buffer[index++] & 0xff) << 40) |
|
||||
(((long) buffer[index++] & 0xff) << 48) |
|
||||
(((long) buffer[index]) << 56));
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(int index) {
|
||||
return Float.intBitsToFloat(getInt(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble(int index) {
|
||||
return Double.longBitsToDouble(getLong(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(int start, int size) {
|
||||
return Utf8Safe.decodeUtf8Array(buffer, start, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] data() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void putBoolean(boolean value) {
|
||||
setBoolean(writePos, value);
|
||||
writePos++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(byte[] value, int start, int length) {
|
||||
set(writePos, value, start, length);
|
||||
writePos+=length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(byte value) {
|
||||
set(writePos, value);
|
||||
writePos++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putShort(short value) {
|
||||
setShort(writePos, value);
|
||||
writePos +=2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putInt(int value) {
|
||||
setInt(writePos, value);
|
||||
writePos +=4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putLong(long value) {
|
||||
setLong(writePos, value);
|
||||
writePos +=8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putFloat(float value) {
|
||||
setFloat(writePos, value);
|
||||
writePos +=4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putDouble(double value) {
|
||||
setDouble(writePos, value);
|
||||
writePos +=8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBoolean(int index, boolean value) {
|
||||
set(index, value ? (byte)1 : (byte)0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, byte value) {
|
||||
requestCapacity(index + 1);
|
||||
buffer[index] = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, byte[] toCopy, int start, int length) {
|
||||
requestCapacity(index + (length - start));
|
||||
System.arraycopy(toCopy, start, buffer, index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setShort(int index, short value) {
|
||||
requestCapacity(index + 2);
|
||||
|
||||
buffer[index++] = (byte) ((value) & 0xff);
|
||||
buffer[index ] = (byte) ((value >> 8) & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInt(int index, int value) {
|
||||
requestCapacity(index + 4);
|
||||
|
||||
buffer[index++] = (byte) ((value) & 0xff);
|
||||
buffer[index++] = (byte) ((value >> 8) & 0xff);
|
||||
buffer[index++] = (byte) ((value >> 16) & 0xff);
|
||||
buffer[index ] = (byte) ((value >> 24) & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLong(int index, long value) {
|
||||
requestCapacity(index + 8);
|
||||
|
||||
int i = (int) value;
|
||||
buffer[index++] = (byte) ((i) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 8) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 16) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 24) & 0xff);
|
||||
i = (int) (value >> 32);
|
||||
buffer[index++] = (byte) ((i) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 8) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 16) & 0xff);
|
||||
buffer[index ] = (byte) ((i >> 24) & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFloat(int index, float value) {
|
||||
requestCapacity(index + 4);
|
||||
|
||||
int iValue = Float.floatToRawIntBits(value);
|
||||
buffer[index++] = (byte) ((iValue) & 0xff);
|
||||
buffer[index++] = (byte) ((iValue >> 8) & 0xff);
|
||||
buffer[index++] = (byte) ((iValue >> 16) & 0xff);
|
||||
buffer[index ] = (byte) ((iValue >> 24) & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDouble(int index, double value) {
|
||||
requestCapacity(index + 8);
|
||||
|
||||
long lValue = Double.doubleToRawLongBits(value);
|
||||
int i = (int) lValue;
|
||||
buffer[index++] = (byte) ((i) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 8) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 16) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 24) & 0xff);
|
||||
i = (int) (lValue >> 32);
|
||||
buffer[index++] = (byte) ((i) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 8) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 16) & 0xff);
|
||||
buffer[index ] = (byte) ((i >> 24) & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int limit() {
|
||||
return writePos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int writePosition() {
|
||||
return writePos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requestCapacity(int capacity) {
|
||||
if (buffer.length > capacity) {
|
||||
return true;
|
||||
}
|
||||
// implemented in the same growing fashion as ArrayList
|
||||
int oldCapacity = buffer.length;
|
||||
int newCapacity = oldCapacity + (oldCapacity >> 1);
|
||||
buffer = Arrays.copyOf(buffer, newCapacity);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
96
java/com/google/flatbuffers/BaseVector.java
Normal file
96
java/com/google/flatbuffers/BaseVector.java
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
|
||||
/**
|
||||
* All vector access objects derive from this class, and add their own accessors.
|
||||
*/
|
||||
public class BaseVector {
|
||||
/** Used to hold the vector data position. */
|
||||
private int vector;
|
||||
/** Used to hold the vector size. */
|
||||
private int length;
|
||||
/** Used to hold the vector element size in table. */
|
||||
private int element_size;
|
||||
/** The underlying ByteBuffer to hold the data of the vector. */
|
||||
protected ByteBuffer bb;
|
||||
|
||||
/**
|
||||
* Get the start data of a vector.
|
||||
*
|
||||
* @return Returns the start of the vector data.
|
||||
*/
|
||||
protected int __vector() {
|
||||
return vector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the element position in vector's ByteBuffer.
|
||||
*
|
||||
* @param j An `int` index of element into a vector.
|
||||
* @return Returns the position of the vector element in a ByteBuffer.
|
||||
*/
|
||||
protected int __element(int j) {
|
||||
return vector + j * element_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-init the internal state with an external buffer {@code ByteBuffer}, an offset within and
|
||||
* element size.
|
||||
*
|
||||
* This method exists primarily to allow recycling vector instances without risking memory leaks
|
||||
* due to {@code ByteBuffer} references.
|
||||
*/
|
||||
protected void __reset(int _vector, int _element_size, ByteBuffer _bb) {
|
||||
bb = _bb;
|
||||
if (bb != null) {
|
||||
vector = _vector;
|
||||
length = bb.getInt(_vector - Constants.SIZEOF_INT);
|
||||
element_size = _element_size;
|
||||
} else {
|
||||
vector = 0;
|
||||
length = 0;
|
||||
element_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the internal state with a null {@code ByteBuffer} and a zero position.
|
||||
*
|
||||
* This method exists primarily to allow recycling vector instances without risking memory leaks
|
||||
* due to {@code ByteBuffer} references. The instance will be unusable until it is assigned
|
||||
* again to a {@code ByteBuffer}.
|
||||
*/
|
||||
public void reset() {
|
||||
__reset(0, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the length of a vector.
|
||||
*
|
||||
* @return Returns the length of the vector.
|
||||
*/
|
||||
public int length() {
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
49
java/com/google/flatbuffers/BooleanVector.java
Normal file
49
java/com/google/flatbuffers/BooleanVector.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import static com.google.flatbuffers.Constants.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Helper type for accessing vector of booleans.
|
||||
*/
|
||||
public final class BooleanVector extends BaseVector {
|
||||
/**
|
||||
* Assigns vector access object to vector data.
|
||||
*
|
||||
* @param _vector Start data of a vector.
|
||||
* @param _bb Table's ByteBuffer.
|
||||
* @return Returns current vector access object assigned to vector data whose offset is stored at
|
||||
* `vector`.
|
||||
*/
|
||||
public BooleanVector __assign(int _vector, ByteBuffer _bb) {
|
||||
__reset(_vector, Constants.SIZEOF_BYTE, _bb); return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the boolean at the given index.
|
||||
*
|
||||
* @param j The index from which the boolean will be read.
|
||||
* @return the boolean value at the given index.
|
||||
*/
|
||||
public boolean get(int j) {
|
||||
return 0 != bb.get(__element(j));
|
||||
}
|
||||
}
|
||||
165
java/com/google/flatbuffers/ByteBufferReadWriteBuf.java
Normal file
165
java/com/google/flatbuffers/ByteBufferReadWriteBuf.java
Normal file
@@ -0,0 +1,165 @@
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
public class ByteBufferReadWriteBuf implements ReadWriteBuf {
|
||||
|
||||
private final ByteBuffer buffer;
|
||||
|
||||
public ByteBufferReadWriteBuf(ByteBuffer bb) {
|
||||
this.buffer = bb;
|
||||
this.buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(int index) {
|
||||
return get(index) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte get(int index) {
|
||||
return buffer.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort(int index) {
|
||||
return buffer.getShort(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(int index) {
|
||||
return buffer.getInt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(int index) {
|
||||
return buffer.getLong(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(int index) {
|
||||
return buffer.getFloat(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble(int index) {
|
||||
return buffer.getDouble(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(int start, int size) {
|
||||
return Utf8Safe.decodeUtf8Buffer(buffer, start, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] data() {
|
||||
return buffer.array();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putBoolean(boolean value) {
|
||||
buffer.put(value ? (byte)1 : (byte)0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(byte[] value, int start, int length) {
|
||||
buffer.put(value, start, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(byte value) {
|
||||
buffer.put(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putShort(short value) {
|
||||
buffer.putShort(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putInt(int value) {
|
||||
buffer.putInt(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putLong(long value) {
|
||||
buffer.putLong(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putFloat(float value) {
|
||||
buffer.putFloat(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putDouble(double value) {
|
||||
buffer.putDouble(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBoolean(int index, boolean value) {
|
||||
set(index, value ? (byte)1 : (byte)0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, byte value) {
|
||||
requestCapacity(index + 1);
|
||||
buffer.put(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, byte[] value, int start, int length) {
|
||||
requestCapacity(index + (length - start));
|
||||
int curPos = buffer.position();
|
||||
buffer.position(index);
|
||||
buffer.put(value, start, length);
|
||||
buffer.position(curPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setShort(int index, short value) {
|
||||
requestCapacity(index + 2);
|
||||
buffer.putShort(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInt(int index, int value) {
|
||||
requestCapacity(index + 4);
|
||||
buffer.putInt(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLong(int index, long value) {
|
||||
requestCapacity(index + 8);
|
||||
buffer.putLong(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFloat(int index, float value) {
|
||||
requestCapacity(index + 4);
|
||||
buffer.putFloat(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDouble(int index, double value) {
|
||||
requestCapacity(index + 8);
|
||||
buffer.putDouble(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int writePosition() {
|
||||
return buffer.position();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int limit() {
|
||||
return buffer.limit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requestCapacity(int capacity) {
|
||||
return capacity <= buffer.limit();
|
||||
}
|
||||
|
||||
}
|
||||
60
java/com/google/flatbuffers/ByteVector.java
Normal file
60
java/com/google/flatbuffers/ByteVector.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import static com.google.flatbuffers.Constants.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Helper type for accessing vector of signed or unsigned 8-bit values.
|
||||
*/
|
||||
public final class ByteVector extends BaseVector {
|
||||
/**
|
||||
* Assigns vector access object to vector data.
|
||||
*
|
||||
* @param vector Start data of a vector.
|
||||
* @param bb Table's ByteBuffer.
|
||||
* @return Returns current vector access object assigned to vector data whose offset is stored at
|
||||
* `vector`.
|
||||
*/
|
||||
public ByteVector __assign(int vector, ByteBuffer bb) {
|
||||
__reset(vector, Constants.SIZEOF_BYTE, bb); return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the byte at the given index.
|
||||
*
|
||||
* @param j The index from which the byte will be read.
|
||||
* @return the 8-bit value at the given index.
|
||||
*/
|
||||
public byte get(int j) {
|
||||
return bb.get(__element(j));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the byte at the given index, zero-extends it to type int, and returns the result,
|
||||
* which is therefore in the range 0 through 255.
|
||||
*
|
||||
* @param j The index from which the byte will be read.
|
||||
* @return the unsigned 8-bit at the given index.
|
||||
*/
|
||||
public int getAsUnsigned(int j) {
|
||||
return (int) get(j) & 0xFF;
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,14 @@ public class Constants {
|
||||
static final int FILE_IDENTIFIER_LENGTH = 4;
|
||||
/** The number of bytes in a size prefix. */
|
||||
public static final int SIZE_PREFIX_LENGTH = 4;
|
||||
/** A version identifier to force a compile error if someone
|
||||
accidentally tries to build generated code with a runtime of
|
||||
two mismatched version. Versions need to always match, as
|
||||
the runtime and generated code are modified in sync.
|
||||
Changes to the Java implementation need to be sure to change
|
||||
the version here and in the code generator on every possible
|
||||
incompatible change */
|
||||
public static void FLATBUFFERS_1_12_0() {}
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
|
||||
49
java/com/google/flatbuffers/DoubleVector.java
Normal file
49
java/com/google/flatbuffers/DoubleVector.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import static com.google.flatbuffers.Constants.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Helper type for accessing vector of double values.
|
||||
*/
|
||||
public final class DoubleVector extends BaseVector {
|
||||
/**
|
||||
* Assigns vector access object to vector data.
|
||||
*
|
||||
* @param _vector Start data of a vector.
|
||||
* @param _bb Table's ByteBuffer.
|
||||
* @return Returns current vector access object assigned to vector data whose offset is stored at
|
||||
* `vector`.
|
||||
*/
|
||||
public DoubleVector __assign(int _vector, ByteBuffer _bb) {
|
||||
__reset(_vector, Constants.SIZEOF_DOUBLE, _bb); return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the double value at the given index.
|
||||
*
|
||||
* @param j The index from which the double value will be read.
|
||||
* @return the double value at the given index.
|
||||
*/
|
||||
public double get(int j) {
|
||||
return bb.getDouble(__element(j));
|
||||
}
|
||||
}
|
||||
@@ -72,7 +72,6 @@ public class FlatBufferBuilder {
|
||||
if (initial_size <= 0) {
|
||||
initial_size = 1;
|
||||
}
|
||||
space = initial_size;
|
||||
this.bb_factory = bb_factory;
|
||||
if (existing_bb != null) {
|
||||
bb = existing_bb;
|
||||
@@ -82,6 +81,7 @@ public class FlatBufferBuilder {
|
||||
bb = bb_factory.newByteBuffer(initial_size);
|
||||
}
|
||||
this.utf8 = utf8;
|
||||
space = bb.capacity();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,6 +199,17 @@ public class FlatBufferBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to test if a field is present in the table
|
||||
*
|
||||
* @param table Flatbuffer table
|
||||
* @param offset virtual table offset
|
||||
* @return true if the filed is present
|
||||
*/
|
||||
public static boolean isFieldPresent(Table table, int offset) {
|
||||
return table.__offset(offset) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the FlatBufferBuilder by purging all data that it holds.
|
||||
*/
|
||||
@@ -231,6 +242,7 @@ public class FlatBufferBuilder {
|
||||
int new_buf_size = old_buf_size == 0 ? 1 : old_buf_size << 1;
|
||||
bb.position(0);
|
||||
ByteBuffer nbb = bb_factory.newByteBuffer(new_buf_size);
|
||||
new_buf_size = nbb.clear().capacity(); // Ensure the returned buffer is treated as empty
|
||||
nbb.position(new_buf_size - old_buf_size);
|
||||
nbb.put(bb);
|
||||
return nbb;
|
||||
@@ -560,6 +572,38 @@ public class FlatBufferBuilder {
|
||||
return endVector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a byte array in the buffer.
|
||||
*
|
||||
* @param arr a source array with data.
|
||||
* @param offset the offset in the source array to start copying from.
|
||||
* @param length the number of bytes to copy from the source array.
|
||||
* @return The offset in the buffer where the encoded array starts.
|
||||
*/
|
||||
public int createByteVector(byte[] arr, int offset, int length) {
|
||||
startVector(1, length, 1);
|
||||
bb.position(space -= length);
|
||||
bb.put(arr, offset, length);
|
||||
return endVector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a byte array in the buffer.
|
||||
*
|
||||
* The source {@link ByteBuffer} position is advanced by {@link ByteBuffer#remaining()} places
|
||||
* after this call.
|
||||
*
|
||||
* @param byteBuffer A source {@link ByteBuffer} with data.
|
||||
* @return The offset in the buffer where the encoded array starts.
|
||||
*/
|
||||
public int createByteVector(ByteBuffer byteBuffer) {
|
||||
int length = byteBuffer.remaining();
|
||||
startVector(1, length, 1);
|
||||
bb.position(space -= length);
|
||||
bb.put(byteBuffer);
|
||||
return endVector();
|
||||
}
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
/**
|
||||
* Should not be accessing the final buffer before it is finished.
|
||||
@@ -632,7 +676,7 @@ public class FlatBufferBuilder {
|
||||
*
|
||||
* @param numfields The number of fields found in this object.
|
||||
*/
|
||||
public void startObject(int numfields) {
|
||||
public void startTable(int numfields) {
|
||||
notNested();
|
||||
if (vtable == null || vtable.length < numfields) vtable = new int[numfields];
|
||||
vtable_in_use = numfields;
|
||||
@@ -757,11 +801,11 @@ public class FlatBufferBuilder {
|
||||
* Finish off writing the object that is under construction.
|
||||
*
|
||||
* @return The offset to the object inside {@link #dataBuffer()}.
|
||||
* @see #startObject(int)
|
||||
* @see #startTable(int)
|
||||
*/
|
||||
public int endObject() {
|
||||
public int endTable() {
|
||||
if (vtable == null || !nested)
|
||||
throw new AssertionError("FlatBuffers: endObject called without startObject");
|
||||
throw new AssertionError("FlatBuffers: endTable called without startTable");
|
||||
addInt(0);
|
||||
int vtableloc = offset();
|
||||
// Write out the current vtable.
|
||||
|
||||
1102
java/com/google/flatbuffers/FlexBuffers.java
Normal file
1102
java/com/google/flatbuffers/FlexBuffers.java
Normal file
File diff suppressed because it is too large
Load Diff
770
java/com/google/flatbuffers/FlexBuffersBuilder.java
Normal file
770
java/com/google/flatbuffers/FlexBuffersBuilder.java
Normal file
@@ -0,0 +1,770 @@
|
||||
/*
|
||||
* Copyright 2014 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.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
|
||||
import static com.google.flatbuffers.FlexBuffers.*;
|
||||
import static com.google.flatbuffers.FlexBuffers.Unsigned.byteToUnsignedInt;
|
||||
import static com.google.flatbuffers.FlexBuffers.Unsigned.intToUnsignedLong;
|
||||
import static com.google.flatbuffers.FlexBuffers.Unsigned.shortToUnsignedInt;
|
||||
|
||||
/// @file
|
||||
/// @addtogroup flatbuffers_java_api
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* Helper class that builds FlexBuffers
|
||||
* <p> This class presents all necessary APIs to create FlexBuffers. A `ByteBuffer` will be used to store the
|
||||
* data. It can be created internally, or passed down in the constructor.</p>
|
||||
*
|
||||
* <p>There are some limitations when compared to original implementation in C++. Most notably:
|
||||
* <ul>
|
||||
* <li><p> No support for mutations (might change in the future).</p></li>
|
||||
* <li><p> Buffer size limited to {@link Integer#MAX_VALUE}</p></li>
|
||||
* <li><p> Since Java does not support unsigned type, all unsigned operations accepts an immediate higher representation
|
||||
* of similar type.</p></li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
public class FlexBuffersBuilder {
|
||||
|
||||
/**
|
||||
* No keys or strings will be shared
|
||||
*/
|
||||
public static final int BUILDER_FLAG_NONE = 0;
|
||||
/**
|
||||
* Keys will be shared between elements. Identical keys will only be serialized once, thus possibly saving space.
|
||||
* But serialization performance might be slower and consumes more memory.
|
||||
*/
|
||||
public static final int BUILDER_FLAG_SHARE_KEYS = 1;
|
||||
/**
|
||||
* Strings will be shared between elements. Identical strings will only be serialized once, thus possibly saving space.
|
||||
* But serialization performance might be slower and consumes more memory. This is ideal if you expect many repeated
|
||||
* strings on the message.
|
||||
*/
|
||||
public static final int BUILDER_FLAG_SHARE_STRINGS = 2;
|
||||
/**
|
||||
* Strings and keys will be shared between elements.
|
||||
*/
|
||||
public static final int BUILDER_FLAG_SHARE_KEYS_AND_STRINGS = 3;
|
||||
/**
|
||||
* Reserved for the future.
|
||||
*/
|
||||
public static final int BUILDER_FLAG_SHARE_KEY_VECTORS = 4;
|
||||
/**
|
||||
* Reserved for the future.
|
||||
*/
|
||||
public static final int BUILDER_FLAG_SHARE_ALL = 7;
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
private static final int WIDTH_8 = 0;
|
||||
private static final int WIDTH_16 = 1;
|
||||
private static final int WIDTH_32 = 2;
|
||||
private static final int WIDTH_64 = 3;
|
||||
private final ReadWriteBuf bb;
|
||||
private final ArrayList<Value> stack = new ArrayList<>();
|
||||
private final HashMap<String, Integer> keyPool = new HashMap<>();
|
||||
private final HashMap<String, Integer> stringPool = new HashMap<>();
|
||||
private final int flags;
|
||||
private boolean finished = false;
|
||||
|
||||
// A lambda to sort map keys
|
||||
private Comparator<Value> keyComparator = new Comparator<Value>() {
|
||||
@Override
|
||||
public int compare(Value o1, Value o2) {
|
||||
int ia = o1.key;
|
||||
int io = o2.key;
|
||||
byte c1, c2;
|
||||
do {
|
||||
c1 = bb.get(ia);
|
||||
c2 = bb.get(io);
|
||||
if (c1 == 0)
|
||||
return c1 - c2;
|
||||
ia++;
|
||||
io++;
|
||||
}
|
||||
while (c1 == c2);
|
||||
return c1 - c2;
|
||||
}
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
/**
|
||||
* Constructs a newly allocated {@code FlexBuffersBuilder} with {@link #BUILDER_FLAG_SHARE_KEYS} set.
|
||||
* @param bufSize size of buffer in bytes.
|
||||
*/
|
||||
public FlexBuffersBuilder(int bufSize) {
|
||||
this(new ArrayReadWriteBuf(bufSize), BUILDER_FLAG_SHARE_KEYS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a newly allocated {@code FlexBuffersBuilder} with {@link #BUILDER_FLAG_SHARE_KEYS} set.
|
||||
*/
|
||||
public FlexBuffersBuilder() {
|
||||
this(256);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a newly allocated {@code FlexBuffersBuilder}.
|
||||
*
|
||||
* @param bb `ByteBuffer` that will hold the message
|
||||
* @param flags Share flags
|
||||
*/
|
||||
@Deprecated
|
||||
public FlexBuffersBuilder(ByteBuffer bb, int flags) {
|
||||
this(new ArrayReadWriteBuf(bb.array()), flags);
|
||||
}
|
||||
|
||||
public FlexBuffersBuilder(ReadWriteBuf bb, int flags) {
|
||||
this.bb = bb;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a newly allocated {@code FlexBuffersBuilder}.
|
||||
* By default same keys will be serialized only once
|
||||
* @param bb `ByteBuffer` that will hold the message
|
||||
*/
|
||||
public FlexBuffersBuilder(ByteBuffer bb) {
|
||||
this(bb, BUILDER_FLAG_SHARE_KEYS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `ByteBuffer` containing FlexBuffer message. {@code #finish()} must be called before calling this
|
||||
* function otherwise an assert will trigger.
|
||||
*
|
||||
* @return `ByteBuffer` with finished message
|
||||
*/
|
||||
public ReadWriteBuf getBuffer() {
|
||||
assert (finished);
|
||||
return bb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a single boolean into the buffer
|
||||
* @param val true or false
|
||||
*/
|
||||
public void putBoolean(boolean val) {
|
||||
putBoolean(null, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a single boolean into the buffer
|
||||
* @param key key used to store element in map
|
||||
* @param val true or false
|
||||
*/
|
||||
public void putBoolean(String key, boolean val) {
|
||||
stack.add(Value.bool(putKey(key), val));
|
||||
}
|
||||
|
||||
private int putKey(String key) {
|
||||
if (key == null) {
|
||||
return -1;
|
||||
}
|
||||
int pos = bb.writePosition();
|
||||
if ((flags & BUILDER_FLAG_SHARE_KEYS) != 0) {
|
||||
Integer keyFromPool = keyPool.get(key);
|
||||
if (keyFromPool == null) {
|
||||
byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
|
||||
bb.put(keyBytes, 0, keyBytes.length);
|
||||
bb.put((byte) 0);
|
||||
keyPool.put(key, pos);
|
||||
} else {
|
||||
pos = keyFromPool;
|
||||
}
|
||||
} else {
|
||||
byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
|
||||
bb.put(keyBytes, 0, keyBytes.length);
|
||||
bb.put((byte) 0);
|
||||
keyPool.put(key, pos);
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a integer into the buff
|
||||
* @param val integer
|
||||
*/
|
||||
public void putInt(int val) {
|
||||
putInt(null, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a integer into the buff
|
||||
* @param key key used to store element in map
|
||||
* @param val integer
|
||||
*/
|
||||
public void putInt(String key, int val) {
|
||||
putInt(key, (long) val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a integer into the buff
|
||||
* @param key key used to store element in map
|
||||
* @param val 64-bit integer
|
||||
*/
|
||||
public void putInt(String key, long val) {
|
||||
int iKey = putKey(key);
|
||||
if (Byte.MIN_VALUE <= val && val <= Byte.MAX_VALUE) {
|
||||
stack.add(Value.int8(iKey, (int) val));
|
||||
} else if (Short.MIN_VALUE <= val && val <= Short.MAX_VALUE) {
|
||||
stack.add(Value.int16(iKey, (int) val));
|
||||
} else if (Integer.MIN_VALUE <= val && val <= Integer.MAX_VALUE) {
|
||||
stack.add(Value.int32(iKey, (int) val));
|
||||
} else {
|
||||
stack.add(Value.int64(iKey, val));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a 64-bit integer into the buff
|
||||
* @param value integer
|
||||
*/
|
||||
public void putInt(long value) {
|
||||
putInt(null, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a unsigned integer into the buff.
|
||||
* @param value integer representing unsigned value
|
||||
*/
|
||||
public void putUInt(int value) {
|
||||
putUInt(null, (long) value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a unsigned integer (stored in a signed 64-bit integer) into the buff.
|
||||
* @param value integer representing unsigned value
|
||||
*/
|
||||
public void putUInt(long value) {
|
||||
putUInt(null, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a 64-bit unsigned integer (stored as {@link BigInteger}) into the buff.
|
||||
* Warning: This operation might be very slow.
|
||||
* @param value integer representing unsigned value
|
||||
*/
|
||||
public void putUInt64(BigInteger value) {
|
||||
putUInt64(null, value.longValue());
|
||||
}
|
||||
|
||||
private void putUInt64(String key, long value) {
|
||||
stack.add(Value.uInt64(putKey(key), value));
|
||||
}
|
||||
|
||||
private void putUInt(String key, long value) {
|
||||
int iKey = putKey(key);
|
||||
Value vVal;
|
||||
|
||||
int width = widthUInBits(value);
|
||||
|
||||
if (width == WIDTH_8) {
|
||||
vVal = Value.uInt8(iKey, (int)value);
|
||||
} else if (width == WIDTH_16) {
|
||||
vVal = Value.uInt16(iKey, (int)value);
|
||||
} else if (width == WIDTH_32) {
|
||||
vVal = Value.uInt32(iKey, (int)value);
|
||||
} else {
|
||||
vVal = Value.uInt64(iKey, value);
|
||||
}
|
||||
stack.add(vVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a 32-bit float into the buff.
|
||||
* @param value float representing value
|
||||
*/
|
||||
public void putFloat(float value) {
|
||||
putFloat(null, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a 32-bit float into the buff.
|
||||
* @param key key used to store element in map
|
||||
* @param value float representing value
|
||||
*/
|
||||
public void putFloat(String key, float val) {
|
||||
stack.add(Value.float32(putKey(key), val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a 64-bit float into the buff.
|
||||
* @param value float representing value
|
||||
*/
|
||||
public void putFloat(double value) {
|
||||
putFloat(null, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a 64-bit float into the buff.
|
||||
* @param key key used to store element in map
|
||||
* @param value float representing value
|
||||
*/
|
||||
public void putFloat(String key, double val) {
|
||||
stack.add(Value.float64(putKey(key), val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a String into the buffer
|
||||
* @param value string
|
||||
* @return start position of string in the buffer
|
||||
*/
|
||||
public int putString(String value) {
|
||||
return putString(null, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a String into the buffer
|
||||
* @param key key used to store element in map
|
||||
* @param value string
|
||||
* @return start position of string in the buffer
|
||||
*/
|
||||
public int putString(String key, String val) {
|
||||
int iKey = putKey(key);
|
||||
if ((flags & FlexBuffersBuilder.BUILDER_FLAG_SHARE_STRINGS) != 0) {
|
||||
Integer i = stringPool.get(val);
|
||||
if (i == null) {
|
||||
Value value = writeString(iKey, val);
|
||||
stringPool.put(val, (int) value.iValue);
|
||||
stack.add(value);
|
||||
return (int) value.iValue;
|
||||
} else {
|
||||
int bitWidth = widthUInBits(val.length());
|
||||
stack.add(Value.blob(iKey, i, FBT_STRING, bitWidth));
|
||||
return i;
|
||||
}
|
||||
} else {
|
||||
Value value = writeString(iKey, val);
|
||||
stack.add(value);
|
||||
return (int) value.iValue;
|
||||
}
|
||||
}
|
||||
|
||||
private Value writeString(int key, String s) {
|
||||
return writeBlob(key, s.getBytes(StandardCharsets.UTF_8), FBT_STRING, true);
|
||||
}
|
||||
|
||||
// in bits to fit a unsigned int
|
||||
static int widthUInBits(long len) {
|
||||
if (len <= byteToUnsignedInt((byte)0xff)) return WIDTH_8;
|
||||
if (len <= shortToUnsignedInt((short)0xffff)) return WIDTH_16;
|
||||
if (len <= intToUnsignedLong(0xffff_ffff)) return WIDTH_32;
|
||||
return WIDTH_64;
|
||||
}
|
||||
|
||||
private Value writeBlob(int key, byte[] blob, int type, boolean trailing) {
|
||||
int bitWidth = widthUInBits(blob.length);
|
||||
int byteWidth = align(bitWidth);
|
||||
writeInt(blob.length, byteWidth);
|
||||
int sloc = bb.writePosition();
|
||||
bb.put(blob, 0, blob.length);
|
||||
if (trailing) {
|
||||
bb.put((byte) 0);
|
||||
}
|
||||
return Value.blob(key, sloc, type, bitWidth);
|
||||
}
|
||||
|
||||
// Align to prepare for writing a scalar with a certain size.
|
||||
private int align(int alignment) {
|
||||
int byteWidth = 1 << alignment;
|
||||
int padBytes = Value.paddingBytes(bb.writePosition(), byteWidth);
|
||||
while (padBytes-- != 0) {
|
||||
bb.put((byte) 0);
|
||||
}
|
||||
return byteWidth;
|
||||
}
|
||||
|
||||
private void writeInt(long value, int byteWidth) {
|
||||
switch (byteWidth) {
|
||||
case 1: bb.put((byte) value); break;
|
||||
case 2: bb.putShort((short) value); break;
|
||||
case 4: bb.putInt((int) value); break;
|
||||
case 8: bb.putLong(value); break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a byte array into the message
|
||||
* @param value byte array
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
public int putBlob(byte[] value) {
|
||||
return putBlob(null, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a byte array into the message
|
||||
* @param key key used to store element in map
|
||||
* @param value byte array
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
public int putBlob(String key, byte[] val) {
|
||||
int iKey = putKey(key);
|
||||
Value value = writeBlob(iKey, val, FBT_BLOB, false);
|
||||
stack.add(value);
|
||||
return (int) value.iValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new vector in the buffer.
|
||||
* @return a reference indicating position of the vector in buffer. This
|
||||
* reference must be passed along when the vector is finished using endVector()
|
||||
*/
|
||||
public int startVector() {
|
||||
return stack.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes a vector, but writing the information in the buffer
|
||||
* @param key key used to store element in map
|
||||
* @param start reference for begining of the vector. Returned by {@link startVector()}
|
||||
* @param typed boolean indicating wether vector is typed
|
||||
* @param fixed boolean indicating wether vector is fixed
|
||||
* @return Reference to the vector
|
||||
*/
|
||||
public int endVector(String key, int start, boolean typed, boolean fixed) {
|
||||
int iKey = putKey(key);
|
||||
Value vec = createVector(iKey, start, stack.size() - start, typed, fixed, null);
|
||||
// Remove temp elements and return vector.
|
||||
while (stack.size() > start) {
|
||||
stack.remove(stack.size() - 1);
|
||||
}
|
||||
stack.add(vec);
|
||||
return (int) vec.iValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish writing the message into the buffer. After that no other element must
|
||||
* be inserted into the buffer. Also, you must call this function before start using the
|
||||
* FlexBuffer message
|
||||
* @return `ByteBuffer` containing the FlexBuffer message
|
||||
*/
|
||||
public ByteBuffer finish() {
|
||||
// If you hit this assert, you likely have objects that were never included
|
||||
// in a parent. You need to have exactly one root to finish a buffer.
|
||||
// Check your Start/End calls are matched, and all objects are inside
|
||||
// some other object.
|
||||
assert (stack.size() == 1);
|
||||
// Write root value.
|
||||
int byteWidth = align(stack.get(0).elemWidth(bb.writePosition(), 0));
|
||||
writeAny(stack.get(0), byteWidth);
|
||||
// Write root type.
|
||||
bb.put(stack.get(0).storedPackedType());
|
||||
// Write root size. Normally determined by parent, but root has no parent :)
|
||||
bb.put((byte) byteWidth);
|
||||
this.finished = true;
|
||||
return ByteBuffer.wrap(bb.data(), 0, bb.writePosition());
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a vector based on the elements stored in the stack
|
||||
*
|
||||
* @param key reference to its key
|
||||
* @param start element in the stack
|
||||
* @param length size of the vector
|
||||
* @param typed whether is TypedVector or not
|
||||
* @param fixed whether is Fixed vector or not
|
||||
* @param keys Value representing key vector
|
||||
* @return Value representing the created vector
|
||||
*/
|
||||
private Value createVector(int key, int start, int length, boolean typed, boolean fixed, Value keys) {
|
||||
assert (!fixed || typed); // typed=false, fixed=true combination is not supported.
|
||||
// Figure out smallest bit width we can store this vector with.
|
||||
int bitWidth = Math.max(WIDTH_8, widthUInBits(length));
|
||||
int prefixElems = 1;
|
||||
if (keys != null) {
|
||||
// If this vector is part of a map, we will pre-fix an offset to the keys
|
||||
// to this vector.
|
||||
bitWidth = Math.max(bitWidth, keys.elemWidth(bb.writePosition(), 0));
|
||||
prefixElems += 2;
|
||||
}
|
||||
int vectorType = FBT_KEY;
|
||||
// Check bit widths and types for all elements.
|
||||
for (int i = start; i < stack.size(); i++) {
|
||||
int elemWidth = stack.get(i).elemWidth(bb.writePosition(), i + prefixElems);
|
||||
bitWidth = Math.max(bitWidth, elemWidth);
|
||||
if (typed) {
|
||||
if (i == start) {
|
||||
vectorType = stack.get(i).type;
|
||||
if (!FlexBuffers.isTypedVectorElementType(vectorType)) {
|
||||
throw new FlexBufferException("TypedVector does not support this element type");
|
||||
}
|
||||
} else {
|
||||
// If you get this assert, you are writing a typed vector with
|
||||
// elements that are not all the same type.
|
||||
assert (vectorType == stack.get(i).type);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If you get this assert, your fixed types are not one of:
|
||||
// Int / UInt / Float / Key.
|
||||
assert (!fixed || FlexBuffers.isTypedVectorElementType(vectorType));
|
||||
|
||||
int byteWidth = align(bitWidth);
|
||||
// Write vector. First the keys width/offset if available, and size.
|
||||
if (keys != null) {
|
||||
writeOffset(keys.iValue, byteWidth);
|
||||
writeInt(1L << keys.minBitWidth, byteWidth);
|
||||
}
|
||||
if (!fixed) {
|
||||
writeInt(length, byteWidth);
|
||||
}
|
||||
// Then the actual data.
|
||||
int vloc = bb.writePosition();
|
||||
for (int i = start; i < stack.size(); i++) {
|
||||
writeAny(stack.get(i), byteWidth);
|
||||
}
|
||||
// Then the types.
|
||||
if (!typed) {
|
||||
for (int i = start; i < stack.size(); i++) {
|
||||
bb.put(stack.get(i).storedPackedType(bitWidth));
|
||||
}
|
||||
}
|
||||
return new Value(key, keys != null ? FBT_MAP
|
||||
: (typed ? FlexBuffers.toTypedVector(vectorType, fixed ? length : 0)
|
||||
: FBT_VECTOR), bitWidth, vloc);
|
||||
}
|
||||
|
||||
private void writeOffset(long val, int byteWidth) {
|
||||
int reloff = (int) (bb.writePosition() - val);
|
||||
assert (byteWidth == 8 || reloff < 1L << (byteWidth * 8));
|
||||
writeInt(reloff, byteWidth);
|
||||
}
|
||||
|
||||
private void writeAny(final Value val, int byteWidth) {
|
||||
switch (val.type) {
|
||||
case FBT_NULL:
|
||||
case FBT_BOOL:
|
||||
case FBT_INT:
|
||||
case FBT_UINT:
|
||||
writeInt(val.iValue, byteWidth);
|
||||
break;
|
||||
case FBT_FLOAT:
|
||||
writeDouble(val.dValue, byteWidth);
|
||||
break;
|
||||
default:
|
||||
writeOffset(val.iValue, byteWidth);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDouble(double val, int byteWidth) {
|
||||
if (byteWidth == 4) {
|
||||
bb.putFloat((float) val);
|
||||
} else if (byteWidth == 8) {
|
||||
bb.putDouble(val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new map in the buffer.
|
||||
* @return a reference indicating position of the map in buffer. This
|
||||
* reference must be passed along when the map is finished using endMap()
|
||||
*/
|
||||
public int startMap() {
|
||||
return stack.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes a map, but writing the information in the buffer
|
||||
* @param key key used to store element in map
|
||||
* @param start reference for begining of the map. Returned by {@link startMap()}
|
||||
* @return Reference to the map
|
||||
*/
|
||||
public int endMap(String key, int start) {
|
||||
int iKey = putKey(key);
|
||||
|
||||
Collections.sort(stack.subList(start, stack.size()), keyComparator);
|
||||
|
||||
Value keys = createKeyVector(start, stack.size() - start);
|
||||
Value vec = createVector(iKey, start, stack.size() - start, false, false, keys);
|
||||
// Remove temp elements and return map.
|
||||
while (stack.size() > start) {
|
||||
stack.remove(stack.size() - 1);
|
||||
}
|
||||
stack.add(vec);
|
||||
return (int) vec.iValue;
|
||||
}
|
||||
|
||||
private Value createKeyVector(int start, int length) {
|
||||
// Figure out smallest bit width we can store this vector with.
|
||||
int bitWidth = Math.max(WIDTH_8, widthUInBits(length));
|
||||
int prefixElems = 1;
|
||||
// Check bit widths and types for all elements.
|
||||
for (int i = start; i < stack.size(); i++) {
|
||||
int elemWidth = Value.elemWidth(FBT_KEY, WIDTH_8, stack.get(i).key, bb.writePosition(), i + prefixElems);
|
||||
bitWidth = Math.max(bitWidth, elemWidth);
|
||||
}
|
||||
|
||||
int byteWidth = align(bitWidth);
|
||||
// Write vector. First the keys width/offset if available, and size.
|
||||
writeInt(length, byteWidth);
|
||||
// Then the actual data.
|
||||
int vloc = bb.writePosition();
|
||||
for (int i = start; i < stack.size(); i++) {
|
||||
int pos = stack.get(i).key;
|
||||
assert(pos != -1);
|
||||
writeOffset(stack.get(i).key, byteWidth);
|
||||
}
|
||||
// Then the types.
|
||||
return new Value(-1, FlexBuffers.toTypedVector(FBT_KEY,0), bitWidth, vloc);
|
||||
}
|
||||
|
||||
private static class Value {
|
||||
final int type;
|
||||
// for scalars, represents scalar size in bytes
|
||||
// for vectors, represents the size
|
||||
// for string, length
|
||||
final int minBitWidth;
|
||||
// float value
|
||||
final double dValue;
|
||||
// integer value
|
||||
long iValue;
|
||||
// position of the key associated with this value in buffer
|
||||
int key;
|
||||
|
||||
Value(int key, int type, int bitWidth, long iValue) {
|
||||
this.key = key;
|
||||
this.type = type;
|
||||
this.minBitWidth = bitWidth;
|
||||
this.iValue = iValue;
|
||||
this.dValue = Double.MIN_VALUE;
|
||||
}
|
||||
|
||||
Value(int key, int type, int bitWidth, double dValue) {
|
||||
this.key = key;
|
||||
this.type = type;
|
||||
this.minBitWidth = bitWidth;
|
||||
this.dValue = dValue;
|
||||
this.iValue = Long.MIN_VALUE;
|
||||
}
|
||||
|
||||
static Value bool(int key, boolean b) {
|
||||
return new Value(key, FBT_BOOL, WIDTH_8, b ? 1 : 0);
|
||||
}
|
||||
|
||||
static Value blob(int key, int position, int type, int bitWidth) {
|
||||
return new Value(key, type, bitWidth, position);
|
||||
}
|
||||
|
||||
static Value int8(int key, int value) {
|
||||
return new Value(key, FBT_INT, WIDTH_8, value);
|
||||
}
|
||||
|
||||
static Value int16(int key, int value) {
|
||||
return new Value(key, FBT_INT, WIDTH_16, value);
|
||||
}
|
||||
|
||||
static Value int32(int key, int value) {
|
||||
return new Value(key, FBT_INT, WIDTH_32, value);
|
||||
}
|
||||
|
||||
static Value int64(int key, long value) {
|
||||
return new Value(key, FBT_INT, WIDTH_64, value);
|
||||
}
|
||||
|
||||
static Value uInt8(int key, int value) {
|
||||
return new Value(key, FBT_UINT, WIDTH_8, value);
|
||||
}
|
||||
|
||||
static Value uInt16(int key, int value) {
|
||||
return new Value(key, FBT_UINT, WIDTH_16, value);
|
||||
}
|
||||
|
||||
static Value uInt32(int key, int value) {
|
||||
return new Value(key, FBT_UINT, WIDTH_32, value);
|
||||
}
|
||||
|
||||
static Value uInt64(int key, long value) {
|
||||
return new Value(key, FBT_UINT, WIDTH_64, value);
|
||||
}
|
||||
|
||||
static Value float32(int key, float value) {
|
||||
return new Value(key, FBT_FLOAT, WIDTH_32, value);
|
||||
}
|
||||
|
||||
static Value float64(int key, double value) {
|
||||
return new Value(key, FBT_FLOAT, WIDTH_64, value);
|
||||
}
|
||||
|
||||
private byte storedPackedType() {
|
||||
return storedPackedType(WIDTH_8);
|
||||
}
|
||||
|
||||
private byte storedPackedType(int parentBitWidth) {
|
||||
return packedType(storedWidth(parentBitWidth), type);
|
||||
}
|
||||
|
||||
private static byte packedType(int bitWidth, int type) {
|
||||
return (byte) (bitWidth | (type << 2));
|
||||
}
|
||||
|
||||
private int storedWidth(int parentBitWidth) {
|
||||
if (FlexBuffers.isTypeInline(type)) {
|
||||
return Math.max(minBitWidth, parentBitWidth);
|
||||
} else {
|
||||
return minBitWidth;
|
||||
}
|
||||
}
|
||||
|
||||
private int elemWidth(int bufSize, int elemIndex) {
|
||||
return elemWidth(type, minBitWidth, iValue, bufSize, elemIndex);
|
||||
}
|
||||
|
||||
private static int elemWidth(int type, int minBitWidth, long iValue, int bufSize, int elemIndex) {
|
||||
if (FlexBuffers.isTypeInline(type)) {
|
||||
return minBitWidth;
|
||||
} else {
|
||||
// We have an absolute offset, but want to store a relative offset
|
||||
// elem_index elements beyond the current buffer end. Since whether
|
||||
// the relative offset fits in a certain byte_width depends on
|
||||
// the size of the elements before it (and their alignment), we have
|
||||
// to test for each size in turn.
|
||||
|
||||
// Original implementation checks for largest scalar
|
||||
// which is long unsigned int
|
||||
for (int byteWidth = 1; byteWidth <= 32; byteWidth *= 2) {
|
||||
// Where are we going to write this offset?
|
||||
int offsetLoc = bufSize + paddingBytes(bufSize, byteWidth) + (elemIndex * byteWidth);
|
||||
// Compute relative offset.
|
||||
long offset = offsetLoc - iValue;
|
||||
// Does it fit?
|
||||
int bitWidth = widthUInBits((int) offset);
|
||||
if (((1L) << bitWidth) == byteWidth)
|
||||
return bitWidth;
|
||||
}
|
||||
assert (false); // Must match one of the sizes above.
|
||||
return WIDTH_64;
|
||||
}
|
||||
}
|
||||
|
||||
private static int paddingBytes(int bufSize, int scalarSize) {
|
||||
return ((~bufSize) + 1) & (scalarSize - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @}
|
||||
49
java/com/google/flatbuffers/FloatVector.java
Normal file
49
java/com/google/flatbuffers/FloatVector.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import static com.google.flatbuffers.Constants.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Helper type for accessing vector of float values.
|
||||
*/
|
||||
public final class FloatVector extends BaseVector {
|
||||
/**
|
||||
* Assigns vector access object to vector data.
|
||||
*
|
||||
* @param _vector Start data of a vector.
|
||||
* @param _bb Table's ByteBuffer.
|
||||
* @return Returns current vector access object assigned to vector data whose offset is stored at
|
||||
* `vector`.
|
||||
*/
|
||||
public FloatVector __assign(int _vector, ByteBuffer _bb) {
|
||||
__reset(_vector, Constants.SIZEOF_FLOAT, _bb); return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the float value at the given index.
|
||||
*
|
||||
* @param j The index from which the float value will be read.
|
||||
* @return the float value at the given index.
|
||||
*/
|
||||
public float get(int j) {
|
||||
return bb.getFloat(__element(j));
|
||||
}
|
||||
}
|
||||
60
java/com/google/flatbuffers/IntVector.java
Normal file
60
java/com/google/flatbuffers/IntVector.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import static com.google.flatbuffers.Constants.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Helper type for accessing vector of signed or unsigned 32-bit values.
|
||||
*/
|
||||
public final class IntVector extends BaseVector {
|
||||
/**
|
||||
* Assigns vector access object to vector data.
|
||||
*
|
||||
* @param _vector Start data of a vector.
|
||||
* @param _bb Table's ByteBuffer.
|
||||
* @return Returns current vector access object assigned to vector data whose offset is stored at
|
||||
* `vector`.
|
||||
*/
|
||||
public IntVector __assign(int _vector, ByteBuffer _bb) {
|
||||
__reset(_vector, Constants.SIZEOF_INT, _bb); return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the integer at the given index.
|
||||
*
|
||||
* @param j The index from which the integer will be read.
|
||||
* @return the 32-bit value at the given index.
|
||||
*/
|
||||
public int get(int j) {
|
||||
return bb.getInt(__element(j));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the integer at the given index, zero-extends it to type long, and returns the result,
|
||||
* which is therefore in the range 0 through 4294967295.
|
||||
*
|
||||
* @param j The index from which the integer will be read.
|
||||
* @return the unsigned 32-bit at the given index.
|
||||
*/
|
||||
public long getAsUnsigned(int j) {
|
||||
return (long) get(j) & 0xFFFFFFFFL;
|
||||
}
|
||||
}
|
||||
49
java/com/google/flatbuffers/LongVector.java
Normal file
49
java/com/google/flatbuffers/LongVector.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import static com.google.flatbuffers.Constants.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Helper type for accessing vector of long values.
|
||||
*/
|
||||
public final class LongVector extends BaseVector {
|
||||
/**
|
||||
* Assigns vector access object to vector data.
|
||||
*
|
||||
* @param _vector Start data of a vector.
|
||||
* @param _bb Table's ByteBuffer.
|
||||
* @return Returns current vector access object assigned to vector data whose offset is stored at
|
||||
* `vector`.
|
||||
*/
|
||||
public LongVector __assign(int _vector, ByteBuffer _bb) {
|
||||
__reset(_vector, Constants.SIZEOF_LONG, _bb); return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the long value at the given index.
|
||||
*
|
||||
* @param j The index from which the long value will be read.
|
||||
* @return the signed 64-bit value at the given index.
|
||||
*/
|
||||
public long get(int j) {
|
||||
return bb.getLong(__element(j));
|
||||
}
|
||||
}
|
||||
81
java/com/google/flatbuffers/ReadBuf.java
Normal file
81
java/com/google/flatbuffers/ReadBuf.java
Normal file
@@ -0,0 +1,81 @@
|
||||
package com.google.flatbuffers;
|
||||
|
||||
/**
|
||||
* Represent a chunk of data, where FlexBuffers will read from.
|
||||
*/
|
||||
interface ReadBuf {
|
||||
|
||||
/**
|
||||
* Read boolean from data. Booleans as stored as single byte
|
||||
* @param index position of the element in ReadBuf
|
||||
* @return boolean element
|
||||
*/
|
||||
boolean getBoolean(int index);
|
||||
|
||||
/**
|
||||
* Read a byte from data.
|
||||
* @param index position of the element in ReadBuf
|
||||
* @return a byte
|
||||
*/
|
||||
byte get(int index);
|
||||
|
||||
/**
|
||||
* Read a short from data.
|
||||
* @param index position of the element in ReadBuf
|
||||
* @return a short
|
||||
*/
|
||||
short getShort(int index);
|
||||
|
||||
/**
|
||||
* Read a 32-bit int from data.
|
||||
* @param index position of the element in ReadBuf
|
||||
* @return an int
|
||||
*/
|
||||
int getInt(int index);
|
||||
|
||||
/**
|
||||
* Read a 64-bit long from data.
|
||||
* @param index position of the element in ReadBuf
|
||||
* @return a long
|
||||
*/
|
||||
long getLong(int index);
|
||||
|
||||
/**
|
||||
* Read a 32-bit float from data.
|
||||
* @param index position of the element in ReadBuf
|
||||
* @return a float
|
||||
*/
|
||||
float getFloat(int index);
|
||||
|
||||
/**
|
||||
* Read a 64-bit float from data.
|
||||
* @param index position of the element in ReadBuf
|
||||
* @return a double
|
||||
*/
|
||||
double getDouble(int index);
|
||||
|
||||
/**
|
||||
* Read an UTF-8 string from data.
|
||||
* @param start initial element of the string
|
||||
* @param size size of the string in bytes.
|
||||
* @return a {@code String}
|
||||
*/
|
||||
String getString(int start, int size);
|
||||
|
||||
/**
|
||||
* Expose ReadBuf as an array of bytes.
|
||||
* This method is meant to be as efficient as possible, so for a array-backed ReadBuf, it should
|
||||
* return its own internal data. In case access to internal data is not possible,
|
||||
* a copy of the data into an array of bytes might occur.
|
||||
* @return ReadBuf as an array of bytes
|
||||
*/
|
||||
byte[] data();
|
||||
|
||||
/**
|
||||
* Defines the size of the message in the buffer. It also determines last position that buffer
|
||||
* can be read. Last byte to be accessed is in position {@code limit() -1}.
|
||||
* @return indicate last position
|
||||
*/
|
||||
int limit();
|
||||
|
||||
}
|
||||
135
java/com/google/flatbuffers/ReadWriteBuf.java
Normal file
135
java/com/google/flatbuffers/ReadWriteBuf.java
Normal file
@@ -0,0 +1,135 @@
|
||||
package com.google.flatbuffers;
|
||||
|
||||
/**
|
||||
* Interface to represent a read-write buffer. This interface will be used to access and write
|
||||
* FlexBuffers message.
|
||||
*/
|
||||
interface ReadWriteBuf extends ReadBuf {
|
||||
/**
|
||||
* Put a boolean into the buffer at {@code writePosition()} . Booleans as stored as single
|
||||
* byte. Write position will be incremented.
|
||||
* @return boolean element
|
||||
*/
|
||||
void putBoolean(boolean value);
|
||||
|
||||
/**
|
||||
* Put an array of bytes into the buffer at {@code writePosition()}. Write position will be
|
||||
* incremented.
|
||||
* @param value the data to be copied
|
||||
* @param start initial position on value to be copied
|
||||
* @param length amount of bytes to be copied
|
||||
*/
|
||||
void put (byte[] value, int start, int length);
|
||||
|
||||
/**
|
||||
* Write a byte into the buffer at {@code writePosition()}. Write position will be
|
||||
* incremented.
|
||||
*/
|
||||
void put(byte value);
|
||||
|
||||
/**
|
||||
* Write a 16-bit into in the buffer at {@code writePosition()}. Write position will be
|
||||
* incremented.
|
||||
*/
|
||||
void putShort(short value);
|
||||
|
||||
/**
|
||||
* Write a 32-bit into in the buffer at {@code writePosition()}. Write position will be
|
||||
* incremented.
|
||||
*/
|
||||
void putInt(int value);
|
||||
|
||||
/**
|
||||
* Write a 64-bit into in the buffer at {@code writePosition()}. Write position will be
|
||||
* incremented.
|
||||
*/
|
||||
void putLong(long value);
|
||||
|
||||
/**
|
||||
* Write a 32-bit float into the buffer at {@code writePosition()}. Write position will be
|
||||
* incremented.
|
||||
*/
|
||||
void putFloat(float value);
|
||||
|
||||
/**
|
||||
* Write a 64-bit float into the buffer at {@code writePosition()}. Write position will be
|
||||
* incremented.
|
||||
*/
|
||||
void putDouble(double value);
|
||||
|
||||
/**
|
||||
* Write boolean into a given position on the buffer. Booleans as stored as single byte.
|
||||
* @param index position of the element in buffer
|
||||
*/
|
||||
void setBoolean(int index, boolean value);
|
||||
|
||||
/**
|
||||
* Read a byte from data.
|
||||
* @param index position of the element in the buffer
|
||||
* @return a byte
|
||||
*/
|
||||
void set(int index, byte value);
|
||||
|
||||
/**
|
||||
* Write an array of bytes into the buffer.
|
||||
* @param index initial position of the buffer to be written
|
||||
* @param value the data to be copied
|
||||
* @param start initial position on value to be copied
|
||||
* @param length amount of bytes to be copied
|
||||
*/
|
||||
void set(int index, byte[] value, int start, int length);
|
||||
|
||||
/**
|
||||
* Read a short from data.
|
||||
* @param index position of the element in ReadBuf
|
||||
* @return a short
|
||||
*/
|
||||
void setShort(int index, short value);
|
||||
|
||||
/**
|
||||
* Read a 32-bit int from data.
|
||||
* @param index position of the element in ReadBuf
|
||||
* @return an int
|
||||
*/
|
||||
void setInt(int index, int value);
|
||||
|
||||
/**
|
||||
* Read a 64-bit long from data.
|
||||
* @param index position of the element in ReadBuf
|
||||
* @return a long
|
||||
*/
|
||||
void setLong(int index, long value);
|
||||
|
||||
/**
|
||||
* Read a 32-bit float from data.
|
||||
* @param index position of the element in ReadBuf
|
||||
* @return a float
|
||||
*/
|
||||
void setFloat(int index, float value);
|
||||
|
||||
/**
|
||||
* Read a 64-bit float from data.
|
||||
* @param index position of the element in ReadBuf
|
||||
* @return a double
|
||||
*/
|
||||
void setDouble(int index, double value);
|
||||
|
||||
|
||||
int writePosition();
|
||||
/**
|
||||
* Defines the size of the message in the buffer. It also determines last position that buffer
|
||||
* can be read or write. Last byte to be accessed is in position {@code limit() -1}.
|
||||
* @return indicate last position
|
||||
*/
|
||||
int limit();
|
||||
|
||||
/**
|
||||
* Request capacity of the buffer. In case buffer is already larger
|
||||
* than the requested, this method will just return true. Otherwise
|
||||
* It might try to resize the buffer.
|
||||
*
|
||||
* @return true if buffer is able to offer
|
||||
* the requested capacity
|
||||
*/
|
||||
boolean requestCapacity(int capacity);
|
||||
}
|
||||
60
java/com/google/flatbuffers/ShortVector.java
Normal file
60
java/com/google/flatbuffers/ShortVector.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import static com.google.flatbuffers.Constants.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Helper type for accessing vector of signed or unsigned 16-bit values.
|
||||
*/
|
||||
public final class ShortVector extends BaseVector {
|
||||
/**
|
||||
* Assigns vector access object to vector data.
|
||||
*
|
||||
* @param _vector Start data of a vector.
|
||||
* @param _bb Table's ByteBuffer.
|
||||
* @return Returns current vector access object assigned to vector data whose offset is stored at
|
||||
* `vector`.
|
||||
*/
|
||||
public ShortVector __assign(int _vector, ByteBuffer _bb) {
|
||||
__reset(_vector, Constants.SIZEOF_SHORT, _bb); return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the short value at the given index.
|
||||
*
|
||||
* @param j The index from which the short value will be read.
|
||||
* @return the 16-bit value at the given index.
|
||||
*/
|
||||
public short get(int j) {
|
||||
return bb.getShort(__element(j));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the short at the given index, zero-extends it to type int, and returns the result,
|
||||
* which is therefore in the range 0 through 65535.
|
||||
*
|
||||
* @param j The index from which the short value will be read.
|
||||
* @return the unsigned 16-bit at the given index.
|
||||
*/
|
||||
public int getAsUnsigned(int j) {
|
||||
return (int) get(j) & 0xFFFF;
|
||||
}
|
||||
}
|
||||
52
java/com/google/flatbuffers/StringVector.java
Normal file
52
java/com/google/flatbuffers/StringVector.java
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import static com.google.flatbuffers.Constants.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Helper type for accessing vector of String.
|
||||
*/
|
||||
public final class StringVector extends BaseVector {
|
||||
private Utf8 utf8 = Utf8.getDefault();
|
||||
|
||||
/**
|
||||
* Assigns vector access object to vector data.
|
||||
*
|
||||
* @param _vector Start data of a vector.
|
||||
* @param _element_size Size of a vector element.
|
||||
* @param _bb Table's ByteBuffer.
|
||||
* @return Returns current vector access object assigned to vector data whose offset is stored at
|
||||
* `vector`.
|
||||
*/
|
||||
public StringVector __assign(int _vector, int _element_size, ByteBuffer _bb) {
|
||||
__reset(_vector, _element_size, _bb); return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the String at the given index.
|
||||
*
|
||||
* @param j The index from which the String value will be read.
|
||||
* @return the String at the given index.
|
||||
*/
|
||||
public String get(int j) {
|
||||
return Table.__string(__element(j), bb, utf8);
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,21 @@ public class Struct {
|
||||
/** The underlying ByteBuffer to hold the data of the Struct. */
|
||||
protected ByteBuffer bb;
|
||||
|
||||
/**
|
||||
* Re-init the internal state with an external buffer {@code ByteBuffer} and an offset within.
|
||||
*
|
||||
* This method exists primarily to allow recycling Table instances without risking memory leaks
|
||||
* due to {@code ByteBuffer} references.
|
||||
*/
|
||||
protected void __reset(int _i, ByteBuffer _bb) {
|
||||
bb = _bb;
|
||||
if (bb != null) {
|
||||
bb_pos = _i;
|
||||
} else {
|
||||
bb_pos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets internal state with a null {@code ByteBuffer} and a zero position.
|
||||
*
|
||||
@@ -39,8 +54,7 @@ public class Struct {
|
||||
* @param struct the instance to reset to initial state
|
||||
*/
|
||||
public void __reset() {
|
||||
bb = null;
|
||||
bb_pos = 0;
|
||||
__reset(0, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ package com.google.flatbuffers;
|
||||
import static com.google.flatbuffers.Constants.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
|
||||
@@ -27,20 +26,14 @@ import java.nio.charset.Charset;
|
||||
* All tables in the generated code derive from this class, and add their own accessors.
|
||||
*/
|
||||
public class Table {
|
||||
public final static ThreadLocal<Charset> UTF8_CHARSET = new ThreadLocal<Charset>() {
|
||||
@Override
|
||||
protected Charset initialValue() {
|
||||
return Charset.forName("UTF-8");
|
||||
}
|
||||
};
|
||||
/** Used to hold the position of the `bb` buffer. */
|
||||
protected int bb_pos;
|
||||
/** The underlying ByteBuffer to hold the data of the Table. */
|
||||
protected ByteBuffer bb;
|
||||
/** Used to hold the vtable position. */
|
||||
protected int vtable_start;
|
||||
private int vtable_start;
|
||||
/** Used to hold the vtable size. */
|
||||
protected int vtable_size;
|
||||
private int vtable_size;
|
||||
Utf8 utf8 = Utf8.getDefault();
|
||||
|
||||
/**
|
||||
@@ -75,6 +68,13 @@ public class Table {
|
||||
return offset + bb.getInt(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve a relative offset.
|
||||
*
|
||||
* @param offset An `int` index into a ByteBuffer containing the relative offset.
|
||||
* @param bb from which the relative offset will be retrieved.
|
||||
* @return Returns the relative offset stored at `offset`.
|
||||
*/
|
||||
protected static int __indirect(int offset, ByteBuffer bb) {
|
||||
return offset + bb.getInt(offset);
|
||||
}
|
||||
@@ -91,6 +91,23 @@ public class Table {
|
||||
* @return Returns a `String` from the data stored inside the FlatBuffer at `offset`.
|
||||
*/
|
||||
protected String __string(int offset) {
|
||||
return __string(offset, bb, utf8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Java `String` from UTF-8 data stored inside the FlatBuffer.
|
||||
*
|
||||
* This allocates a new string and converts to wide chars upon each access,
|
||||
* which is not very efficient. Instead, each FlatBuffer string also comes with an
|
||||
* accessor based on __vector_as_bytebuffer below, which is much more efficient,
|
||||
* assuming your Java program can handle UTF-8 data directly.
|
||||
*
|
||||
* @param offset An `int` index into the Table's ByteBuffer.
|
||||
* @param bb Table ByteBuffer used to read a string at given offset.
|
||||
* @param utf8 decoder that creates a Java `String` from UTF-8 characters.
|
||||
* @return Returns a `String` from the data stored inside the FlatBuffer at `offset`.
|
||||
*/
|
||||
protected static String __string(int offset, ByteBuffer bb, Utf8 utf8) {
|
||||
offset += bb.getInt(offset);
|
||||
int length = bb.getInt(offset);
|
||||
return utf8.decodeUtf8(bb, offset + SIZEOF_INT, length);
|
||||
@@ -169,11 +186,19 @@ public class Table {
|
||||
* @return Returns the Table that points to the union at `offset`.
|
||||
*/
|
||||
protected Table __union(Table t, int offset) {
|
||||
offset += bb_pos;
|
||||
t.bb_pos = offset + bb.getInt(offset);
|
||||
t.bb = bb;
|
||||
t.vtable_start = t.bb_pos - bb.getInt(t.bb_pos);
|
||||
t.vtable_size = bb.getShort(t.vtable_start);
|
||||
return __union(t, offset, bb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize any Table-derived type to point to the union at the given `offset`.
|
||||
*
|
||||
* @param t A `Table`-derived type that should point to the union at `offset`.
|
||||
* @param offset An `int` index into the Table's ByteBuffer.
|
||||
* @param bb Table ByteBuffer used to initialize the object Table-derived type.
|
||||
* @return Returns the Table that points to the union at `offset`.
|
||||
*/
|
||||
protected static Table __union(Table t, int offset, ByteBuffer bb) {
|
||||
t.__reset(__indirect(offset, bb), bb);
|
||||
return t;
|
||||
}
|
||||
|
||||
@@ -263,6 +288,25 @@ public class Table {
|
||||
return len_1 - len_2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-init the internal state with an external buffer {@code ByteBuffer} and an offset within.
|
||||
*
|
||||
* This method exists primarily to allow recycling Table instances without risking memory leaks
|
||||
* due to {@code ByteBuffer} references.
|
||||
*/
|
||||
protected void __reset(int _i, ByteBuffer _bb) {
|
||||
bb = _bb;
|
||||
if (bb != null) {
|
||||
bb_pos = _i;
|
||||
vtable_start = bb_pos - bb.getInt(bb_pos);
|
||||
vtable_size = bb.getShort(vtable_start);
|
||||
} else {
|
||||
bb_pos = 0;
|
||||
vtable_start = 0;
|
||||
vtable_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the internal state with a null {@code ByteBuffer} and a zero position.
|
||||
*
|
||||
@@ -271,10 +315,7 @@ public class Table {
|
||||
* again to a {@code ByteBuffer}.
|
||||
*/
|
||||
public void __reset() {
|
||||
bb = null;
|
||||
bb_pos = 0;
|
||||
vtable_start = 0;
|
||||
vtable_size = 0;
|
||||
__reset(0, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
52
java/com/google/flatbuffers/UnionVector.java
Normal file
52
java/com/google/flatbuffers/UnionVector.java
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2019 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.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import static com.google.flatbuffers.Constants.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Helper type for accessing vector of unions.
|
||||
*/
|
||||
public final class UnionVector extends BaseVector {
|
||||
/**
|
||||
* Assigns vector access object to vector data.
|
||||
*
|
||||
* @param _vector Start data of a vector.
|
||||
* @param _element_size Size of a vector element.
|
||||
* @param _bb Table's ByteBuffer.
|
||||
* @return Returns current vector access object assigned to vector data whose offset is stored at
|
||||
* `vector`.
|
||||
*/
|
||||
public UnionVector __assign(int _vector, int _element_size, ByteBuffer _bb) {
|
||||
__reset(_vector, _element_size, _bb); return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize any Table-derived type to point to the union at the given `index`.
|
||||
*
|
||||
* @param obj A `Table`-derived type that should point to the union at `index`.
|
||||
* @param j An `int` index into the union vector.
|
||||
* @return Returns the Table that points to the union at `index`.
|
||||
*/
|
||||
public Table get(Table obj, int j) {
|
||||
return Table.__union(obj, __element(j), bb);
|
||||
}
|
||||
}
|
||||
@@ -110,9 +110,11 @@ public abstract class Utf8 {
|
||||
throws IllegalArgumentException {
|
||||
// Simultaneously checks for illegal trailing-byte in leading position (<= '11000000') and
|
||||
// overlong 2-byte, '11000001'.
|
||||
if (byte1 < (byte) 0xC2
|
||||
|| isNotTrailingByte(byte2)) {
|
||||
throw new IllegalArgumentException("Invalid UTF-8");
|
||||
if (byte1 < (byte) 0xC2) {
|
||||
throw new IllegalArgumentException("Invalid UTF-8: Illegal leading byte in 2 bytes utf");
|
||||
}
|
||||
if (isNotTrailingByte(byte2)) {
|
||||
throw new IllegalArgumentException("Invalid UTF-8: Illegal trailing byte in 2 bytes utf");
|
||||
}
|
||||
resultArr[resultPos] = (char) (((byte1 & 0x1F) << 6) | trailingByteValue(byte2));
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ public class Utf8Old extends Utf8 {
|
||||
throw new IllegalArgumentException("bad character encoding", e);
|
||||
}
|
||||
}
|
||||
cache.lastOutput.flip();
|
||||
return cache.lastOutput.remaining();
|
||||
}
|
||||
|
||||
@@ -90,7 +91,6 @@ public class Utf8Old extends Utf8 {
|
||||
buffer.limit(offset + length);
|
||||
try {
|
||||
CharBuffer result = decoder.decode(buffer);
|
||||
result.flip();
|
||||
return result.toString();
|
||||
} catch (CharacterCodingException e) {
|
||||
throw new IllegalArgumentException("Bad encoding", e);
|
||||
|
||||
@@ -123,7 +123,7 @@ final public class Utf8Safe extends Utf8 {
|
||||
return utf8Length;
|
||||
}
|
||||
|
||||
private static String decodeUtf8Array(byte[] bytes, int index, int size) {
|
||||
public static String decodeUtf8Array(byte[] bytes, int index, int size) {
|
||||
// Bitwise OR combines the sign bits so any negative value fails the check.
|
||||
if ((index | size | bytes.length - index - size) < 0) {
|
||||
throw new ArrayIndexOutOfBoundsException(
|
||||
@@ -197,7 +197,7 @@ final public class Utf8Safe extends Utf8 {
|
||||
return new String(resultArr, 0, resultPos);
|
||||
}
|
||||
|
||||
private static String decodeUtf8Buffer(ByteBuffer buffer, int offset,
|
||||
public static String decodeUtf8Buffer(ByteBuffer buffer, int offset,
|
||||
int length) {
|
||||
// Bitwise OR combines the sign bits so any negative value fails the check.
|
||||
if ((offset | length | buffer.limit() - offset - length) < 0) {
|
||||
|
||||
@@ -48,6 +48,12 @@ flatbuffers.SIZEOF_INT = 4;
|
||||
*/
|
||||
flatbuffers.FILE_IDENTIFIER_LENGTH = 4;
|
||||
|
||||
/**
|
||||
* @type {number}
|
||||
* @const
|
||||
*/
|
||||
flatbuffers.SIZE_PREFIX_LENGTH = 4;
|
||||
|
||||
/**
|
||||
* @enum {number}
|
||||
*/
|
||||
@@ -104,7 +110,7 @@ flatbuffers.Long = function(low, high) {
|
||||
/**
|
||||
* @param {number} low
|
||||
* @param {number} high
|
||||
* @returns {flatbuffers.Long}
|
||||
* @returns {!flatbuffers.Long}
|
||||
*/
|
||||
flatbuffers.Long.create = function(low, high) {
|
||||
// Special-case zero to avoid GC overhead for default values
|
||||
@@ -127,7 +133,7 @@ flatbuffers.Long.prototype.equals = function(other) {
|
||||
};
|
||||
|
||||
/**
|
||||
* @type {flatbuffers.Long}
|
||||
* @type {!flatbuffers.Long}
|
||||
* @const
|
||||
*/
|
||||
flatbuffers.Long.ZERO = new flatbuffers.Long(0, 0);
|
||||
@@ -265,7 +271,7 @@ flatbuffers.Builder.prototype.dataBuffer = function() {
|
||||
* Get the bytes representing the FlatBuffer. Only call this after you've
|
||||
* called finish().
|
||||
*
|
||||
* @returns {Uint8Array}
|
||||
* @returns {!Uint8Array}
|
||||
*/
|
||||
flatbuffers.Builder.prototype.asUint8Array = function() {
|
||||
return this.bb.bytes().subarray(this.bb.position(), this.bb.position() + this.offset());
|
||||
@@ -550,7 +556,7 @@ flatbuffers.Builder.prototype.offset = function() {
|
||||
* the end of the new buffer (since we build the buffer backwards).
|
||||
*
|
||||
* @param {flatbuffers.ByteBuffer} bb The current buffer with the existing data
|
||||
* @returns {flatbuffers.ByteBuffer} A new byte buffer with the old data copied
|
||||
* @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
|
||||
@@ -676,12 +682,14 @@ outer_loop:
|
||||
*
|
||||
* @param {flatbuffers.Offset} root_table
|
||||
* @param {string=} opt_file_identifier
|
||||
* @param {boolean=} opt_size_prefix
|
||||
*/
|
||||
flatbuffers.Builder.prototype.finish = function(root_table, opt_file_identifier) {
|
||||
flatbuffers.Builder.prototype.finish = function(root_table, opt_file_identifier, opt_size_prefix) {
|
||||
var size_prefix = opt_size_prefix ? flatbuffers.SIZE_PREFIX_LENGTH : 0;
|
||||
if (opt_file_identifier) {
|
||||
var file_identifier = opt_file_identifier;
|
||||
this.prep(this.minalign, flatbuffers.SIZEOF_INT +
|
||||
flatbuffers.FILE_IDENTIFIER_LENGTH);
|
||||
flatbuffers.FILE_IDENTIFIER_LENGTH + size_prefix);
|
||||
if (file_identifier.length != flatbuffers.FILE_IDENTIFIER_LENGTH) {
|
||||
throw new Error('FlatBuffers: file identifier must be length ' +
|
||||
flatbuffers.FILE_IDENTIFIER_LENGTH);
|
||||
@@ -690,11 +698,24 @@ flatbuffers.Builder.prototype.finish = function(root_table, opt_file_identifier)
|
||||
this.writeInt8(file_identifier.charCodeAt(i));
|
||||
}
|
||||
}
|
||||
this.prep(this.minalign, flatbuffers.SIZEOF_INT);
|
||||
this.prep(this.minalign, flatbuffers.SIZEOF_INT + size_prefix);
|
||||
this.addOffset(root_table);
|
||||
if (size_prefix) {
|
||||
this.addInt32(this.bb.capacity() - this.space);
|
||||
}
|
||||
this.bb.setPosition(this.space);
|
||||
};
|
||||
|
||||
/**
|
||||
* Finalize a size prefixed buffer, pointing to the given `root_table`.
|
||||
*
|
||||
* @param {flatbuffers.Offset} root_table
|
||||
* @param {string=} opt_file_identifier
|
||||
*/
|
||||
flatbuffers.Builder.prototype.finishSizePrefixed = function (root_table, opt_file_identifier) {
|
||||
this.finish(root_table, opt_file_identifier, true);
|
||||
};
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
/**
|
||||
* This checks a required field has been set in a given table that has
|
||||
@@ -804,7 +825,7 @@ flatbuffers.Builder.prototype.createString = function(s) {
|
||||
*
|
||||
* @param {number} low
|
||||
* @param {number} high
|
||||
* @returns {flatbuffers.Long}
|
||||
* @returns {!flatbuffers.Long}
|
||||
*/
|
||||
flatbuffers.Builder.prototype.createLong = function(low, high) {
|
||||
return flatbuffers.Long.create(low, high);
|
||||
@@ -835,7 +856,7 @@ flatbuffers.ByteBuffer = function(bytes) {
|
||||
* Create and allocate a new ByteBuffer with a given size.
|
||||
*
|
||||
* @param {number} byte_size
|
||||
* @returns {flatbuffers.ByteBuffer}
|
||||
* @returns {!flatbuffers.ByteBuffer}
|
||||
*/
|
||||
flatbuffers.ByteBuffer.allocate = function(byte_size) {
|
||||
return new flatbuffers.ByteBuffer(new Uint8Array(byte_size));
|
||||
@@ -931,7 +952,7 @@ flatbuffers.ByteBuffer.prototype.readUint32 = function(offset) {
|
||||
|
||||
/**
|
||||
* @param {number} offset
|
||||
* @returns {flatbuffers.Long}
|
||||
* @returns {!flatbuffers.Long}
|
||||
*/
|
||||
flatbuffers.ByteBuffer.prototype.readInt64 = function(offset) {
|
||||
return new flatbuffers.Long(this.readInt32(offset), this.readInt32(offset + 4));
|
||||
@@ -939,7 +960,7 @@ flatbuffers.ByteBuffer.prototype.readInt64 = function(offset) {
|
||||
|
||||
/**
|
||||
* @param {number} offset
|
||||
* @returns {flatbuffers.Long}
|
||||
* @returns {!flatbuffers.Long}
|
||||
*/
|
||||
flatbuffers.ByteBuffer.prototype.readUint64 = function(offset) {
|
||||
return new flatbuffers.Long(this.readUint32(offset), this.readUint32(offset + 4));
|
||||
@@ -1114,7 +1135,7 @@ flatbuffers.ByteBuffer.prototype.__union = function(t, offset) {
|
||||
*
|
||||
* @param {number} offset
|
||||
* @param {flatbuffers.Encoding=} opt_encoding Defaults to UTF16_STRING
|
||||
* @returns {string|Uint8Array}
|
||||
* @returns {string|!Uint8Array}
|
||||
*/
|
||||
flatbuffers.ByteBuffer.prototype.__string = function(offset, opt_encoding) {
|
||||
offset += this.readInt32(offset);
|
||||
@@ -1225,7 +1246,7 @@ flatbuffers.ByteBuffer.prototype.__has_identifier = function(ident) {
|
||||
*
|
||||
* @param {number} low
|
||||
* @param {number} high
|
||||
* @returns {flatbuffers.Long}
|
||||
* @returns {!flatbuffers.Long}
|
||||
*/
|
||||
flatbuffers.ByteBuffer.prototype.createLong = function(low, high) {
|
||||
return flatbuffers.Long.create(low, high);
|
||||
|
||||
@@ -12,32 +12,37 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
include "std.lobster"
|
||||
import std
|
||||
|
||||
namespace flatbuffers
|
||||
|
||||
struct handle:
|
||||
class handle:
|
||||
buf_:string
|
||||
pos_:int
|
||||
|
||||
enum + sz_8 = 1,
|
||||
sz_16 = 2,
|
||||
sz_32 = 4,
|
||||
sz_64 = 8,
|
||||
sz_voffset = 2,
|
||||
sz_uoffset = 4,
|
||||
sz_soffset = 4,
|
||||
sz_metadata_fields = 2
|
||||
// More strongly typed than a naked int, at no cost.
|
||||
struct offset:
|
||||
o:int
|
||||
|
||||
struct builder:
|
||||
buf:string = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
enum sizeof:
|
||||
sz_8 = 1
|
||||
sz_16 = 2
|
||||
sz_32 = 4
|
||||
sz_64 = 8
|
||||
sz_voffset = 2
|
||||
sz_uoffset = 4
|
||||
sz_soffset = 4
|
||||
sz_metadata_fields = 2
|
||||
|
||||
class builder:
|
||||
buf = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
current_vtable:[int] = []
|
||||
head:int = 0
|
||||
minalign:int = 1
|
||||
object_end:int = 0
|
||||
head = 0
|
||||
minalign = 1
|
||||
object_end = 0
|
||||
vtables:[int] = []
|
||||
nested:int = false
|
||||
finished:int = false
|
||||
nested = false
|
||||
finished = false
|
||||
|
||||
// Optionally call this right after creating the builder for a larger initial buffer.
|
||||
def Initial(initial_size:int):
|
||||
@@ -49,7 +54,7 @@ struct builder:
|
||||
|
||||
def Offset():
|
||||
// Offset relative to the end of the buffer.
|
||||
return head
|
||||
return offset { head }
|
||||
|
||||
// Returns a copy of the part of the buffer containing only the finished FlatBuffer
|
||||
def SizedCopy():
|
||||
@@ -75,11 +80,11 @@ struct builder:
|
||||
// Prepend a zero scalar to the object. Later in this function we'll
|
||||
// write an offset here that points to the object's vtable:
|
||||
PrependInt32(0)
|
||||
object_offset := head
|
||||
let object_offset = head
|
||||
// Write out new vtable speculatively.
|
||||
vtable_size := (current_vtable.length + sz_metadata_fields) * sz_voffset
|
||||
let vtable_size = (current_vtable.length + sz_metadata_fields) * sz_voffset
|
||||
while current_vtable.length:
|
||||
o := current_vtable.pop()
|
||||
let o = current_vtable.pop()
|
||||
PrependVOffsetT(if o: object_offset - o else: 0)
|
||||
// The two metadata fields are written last.
|
||||
// First, store the object bytesize:
|
||||
@@ -91,17 +96,18 @@ struct builder:
|
||||
// BenchmarkVtableDeduplication for a case in which this heuristic
|
||||
// saves about 30% of the time used in writing objects with duplicate
|
||||
// tables.
|
||||
existing_vtable := do():
|
||||
def find_existing_table():
|
||||
reverse(vtables) vt2_offset:
|
||||
// Find the other vtable:
|
||||
vt2_start := buf.length - vt2_offset
|
||||
vt2_len := buf.read_int16_le(vt2_start)
|
||||
let vt2_start = buf.length - vt2_offset
|
||||
let vt2_len = buf.read_int16_le(vt2_start)
|
||||
// Compare the other vtable to the one under consideration.
|
||||
// If they are equal, return the offset:
|
||||
if vtable_size == vt2_len and
|
||||
not compare_substring(buf, Start(), buf, vt2_start, vtable_size):
|
||||
return vt2_offset from do
|
||||
0
|
||||
return vt2_offset
|
||||
return 0
|
||||
let existing_vtable = find_existing_table()
|
||||
if existing_vtable:
|
||||
// Found a duplicate vtable, remove the one we wrote.
|
||||
head = object_offset
|
||||
@@ -116,10 +122,11 @@ struct builder:
|
||||
// Finally, store this vtable in memory for future
|
||||
// deduplication:
|
||||
vtables.push(head)
|
||||
return object_offset
|
||||
return offset { object_offset }
|
||||
|
||||
def Pad(n):
|
||||
for(n): buf, head = buf.write_int8_le_back(head, 0)
|
||||
for(n):
|
||||
buf, head = buf.write_int8_le_back(head, 0)
|
||||
|
||||
def Prep(size, additional_bytes):
|
||||
// Track the biggest thing we've ever aligned to.
|
||||
@@ -127,27 +134,27 @@ struct builder:
|
||||
minalign = size
|
||||
// Find the amount of alignment needed such that `size` is properly
|
||||
// aligned after `additionalBytes`:
|
||||
align_size := ((~(head + additional_bytes)) + 1) & (size - 1)
|
||||
let align_size = ((~(head + additional_bytes)) + 1) & (size - 1)
|
||||
Pad(align_size)
|
||||
|
||||
def PrependUOffsetTRelative(off):
|
||||
def PrependUOffsetTRelative(off:offset):
|
||||
// Prepends an unsigned offset into vector data, relative to where it will be written.
|
||||
Prep(sz_uoffset, 0)
|
||||
assert off <= head
|
||||
PlaceUOffsetT(head - off + sz_uoffset)
|
||||
assert off.o <= head
|
||||
PlaceUOffsetT(head - off.o + sz_uoffset)
|
||||
|
||||
def StartVector(elem_size, num_elems, alignment):
|
||||
// Initializes bookkeeping for writing a new vector.
|
||||
StartNesting()
|
||||
Prep(sz_32, elem_size * num_elems)
|
||||
Prep(alignment, elem_size * num_elems) // In case alignment > int.
|
||||
return head
|
||||
return Offset()
|
||||
|
||||
def EndVector(vector_num_elems):
|
||||
EndNesting()
|
||||
// we already made space for this, so write without PrependUint32
|
||||
PlaceUOffsetT(vector_num_elems)
|
||||
return head
|
||||
return Offset()
|
||||
|
||||
def CreateString(s:string):
|
||||
// writes a null-terminated byte string.
|
||||
@@ -168,11 +175,11 @@ struct builder:
|
||||
while current_vtable.length <= slotnum: current_vtable.push(0)
|
||||
current_vtable[slotnum] = head
|
||||
|
||||
def __Finish(root_table:int, size_prefix:int):
|
||||
def __Finish(root_table:offset, size_prefix:int):
|
||||
// Finish finalizes a buffer, pointing to the given root_table
|
||||
assert not finished
|
||||
assert not nested
|
||||
prep_size := sz_32
|
||||
var prep_size = sz_32
|
||||
if size_prefix:
|
||||
prep_size += sz_32
|
||||
Prep(minalign, prep_size)
|
||||
@@ -182,10 +189,10 @@ struct builder:
|
||||
finished = true
|
||||
return Start()
|
||||
|
||||
def Finish(root_table:int):
|
||||
def Finish(root_table:offset):
|
||||
return __Finish(root_table, false)
|
||||
|
||||
def FinishSizePrefixed(root_table:int):
|
||||
def FinishSizePrefixed(root_table:offset):
|
||||
return __Finish(root_table, true)
|
||||
|
||||
def PrependBool(x):
|
||||
@@ -263,16 +270,15 @@ struct builder:
|
||||
def PrependFloat32Slot(o, x, d): PrependSlot(o, x, d): PrependFloat32(_)
|
||||
def PrependFloat64Slot(o, x, d): PrependSlot(o, x, d): PrependFloat64(_)
|
||||
|
||||
def PrependUOffsetTRelativeSlot(o, x, d):
|
||||
if x != d:
|
||||
def PrependUOffsetTRelativeSlot(o:int, x:offset):
|
||||
if x.o:
|
||||
PrependUOffsetTRelative(x)
|
||||
Slot(o)
|
||||
|
||||
def PrependStructSlot(v, x, d):
|
||||
if x != d:
|
||||
def PrependStructSlot(v:int, x:offset):
|
||||
if x.o:
|
||||
// Structs are always stored inline, so need to be created right
|
||||
// where they are used. You'll get this error if you created it
|
||||
//elsewhere.
|
||||
assert x == head
|
||||
// elsewhere.
|
||||
assert x.o == head
|
||||
Slot(v)
|
||||
|
||||
|
||||
@@ -29,12 +29,12 @@ local getAlignSize = compat.GetAlignSize
|
||||
|
||||
local function vtableEqual(a, objectStart, b)
|
||||
UOffsetT:EnforceNumber(objectStart)
|
||||
if (#a * VOffsetT.bytewidth) ~= #b then
|
||||
if (#a * 2) ~= #b then
|
||||
return false
|
||||
end
|
||||
|
||||
for i, elem in ipairs(a) do
|
||||
local x = string.unpack(VOffsetT.packFmt, b, 1 + (i - 1) * VOffsetT.bytewidth)
|
||||
local x = string.unpack(VOffsetT.packFmt, b, 1 + (i - 1) * 2)
|
||||
if x ~= 0 or elem ~= 0 then
|
||||
local y = objectStart - elem
|
||||
if x ~= y then
|
||||
@@ -60,6 +60,23 @@ function m.New(initialSize)
|
||||
return o
|
||||
end
|
||||
|
||||
-- Clears the builder and resets the state. It does not actually clear the backing binary array, it just reuses it as
|
||||
-- needed. This is a performant way to use the builder for multiple constructions without the overhead of multiple
|
||||
-- builder allocations.
|
||||
function mt:Clear()
|
||||
self.finished = false
|
||||
self.nested = false
|
||||
self.minalign = 1
|
||||
self.currentVTable = nil
|
||||
self.objectEnd = nil
|
||||
self.head = #self.bytes -- place the head at the end of the binary array
|
||||
|
||||
-- clear vtables instead of making a new table
|
||||
local vtable = self.vtables
|
||||
local vtableCount = #vtable
|
||||
for i=1,vtableCount do vtable[i] = nil end
|
||||
end
|
||||
|
||||
function mt:Output(full)
|
||||
assert(self.finished, "Builder Not Finished")
|
||||
if full then
|
||||
@@ -104,7 +121,7 @@ function mt:WriteVtable()
|
||||
local vt2lenstr = self.bytes:Slice(vt2Start, vt2Start+1)
|
||||
local vt2Len = string.unpack(VOffsetT.packFmt, vt2lenstr, 1)
|
||||
|
||||
local metadata = VtableMetadataFields * VOffsetT.bytewidth
|
||||
local metadata = VtableMetadataFields * 2
|
||||
local vt2End = vt2Start + vt2Len
|
||||
local vt2 = self.bytes:Slice(vt2Start+metadata,vt2End)
|
||||
|
||||
@@ -133,7 +150,7 @@ function mt:WriteVtable()
|
||||
self:PrependVOffsetT(objectSize)
|
||||
|
||||
local vBytes = #self.currentVTable + VtableMetadataFields
|
||||
vBytes = vBytes * VOffsetT.bytewidth
|
||||
vBytes = vBytes * 2
|
||||
self:PrependVOffsetT(vBytes)
|
||||
|
||||
local objectStart = #self.bytes - objectOffset
|
||||
@@ -208,17 +225,17 @@ function mt:Prep(size, additionalBytes)
|
||||
end
|
||||
|
||||
function mt:PrependSOffsetTRelative(off)
|
||||
self:Prep(SOffsetT.bytewidth, 0)
|
||||
self:Prep(4, 0)
|
||||
assert(off <= self:Offset(), "Offset arithmetic error")
|
||||
local off2 = self:Offset() - off + SOffsetT.bytewidth
|
||||
local off2 = self:Offset() - off + 4
|
||||
self:Place(off2, SOffsetT)
|
||||
end
|
||||
|
||||
function mt:PrependUOffsetTRelative(off)
|
||||
self:Prep(UOffsetT.bytewidth, 0)
|
||||
self:Prep(4, 0)
|
||||
local soffset = self:Offset()
|
||||
if off <= soffset then
|
||||
local off2 = soffset - off + UOffsetT.bytewidth
|
||||
local off2 = soffset - off + 4
|
||||
self:Place(off2, UOffsetT)
|
||||
else
|
||||
error("Offset arithmetic error")
|
||||
@@ -228,8 +245,9 @@ end
|
||||
function mt:StartVector(elemSize, numElements, alignment)
|
||||
assert(not self.nested)
|
||||
self.nested = true
|
||||
self:Prep(Uint32.bytewidth, elemSize * numElements)
|
||||
self:Prep(alignment, elemSize * numElements)
|
||||
local elementSize = elemSize * numElements
|
||||
self:Prep(4, elementSize) -- Uint32 length
|
||||
self:Prep(alignment, elementSize)
|
||||
return self:Offset()
|
||||
end
|
||||
|
||||
@@ -246,7 +264,7 @@ function mt:CreateString(s)
|
||||
|
||||
assert(type(s) == "string")
|
||||
|
||||
self:Prep(UOffsetT.bytewidth, (#s + 1)*Uint8.bytewidth)
|
||||
self:Prep(4, #s + 1)
|
||||
self:Place(0, Uint8)
|
||||
|
||||
local l = #s
|
||||
@@ -254,20 +272,21 @@ function mt:CreateString(s)
|
||||
|
||||
self.bytes:Set(s, self.head, self.head + l)
|
||||
|
||||
return self:EndVector(#s)
|
||||
return self:EndVector(l)
|
||||
end
|
||||
|
||||
function mt:CreateByteVector(x)
|
||||
assert(not self.nested)
|
||||
self.nested = true
|
||||
self:Prep(UOffsetT.bytewidth, #x*Uint8.bytewidth)
|
||||
|
||||
local l = #x
|
||||
self:Prep(4, l)
|
||||
|
||||
self.head = self.head - l
|
||||
|
||||
self.bytes:Set(x, self.head, self.head + l)
|
||||
|
||||
return self:EndVector(#x)
|
||||
return self:EndVector(l)
|
||||
end
|
||||
|
||||
function mt:Slot(slotnum)
|
||||
@@ -278,12 +297,7 @@ end
|
||||
|
||||
local function finish(self, rootTable, sizePrefix)
|
||||
UOffsetT:EnforceNumber(rootTable)
|
||||
local prepSize = UOffsetT.bytewidth
|
||||
if sizePrefix then
|
||||
prepSize = prepSize + Int32.bytewidth
|
||||
end
|
||||
|
||||
self:Prep(self.minalign, prepSize)
|
||||
self:Prep(self.minalign, sizePrefix and 8 or 4)
|
||||
self:PrependUOffsetTRelative(rootTable)
|
||||
if sizePrefix then
|
||||
local size = #self.bytes - self.head
|
||||
@@ -308,8 +322,9 @@ function mt:Prepend(flags, off)
|
||||
end
|
||||
|
||||
function mt:PrependSlot(flags, o, x, d)
|
||||
flags:EnforceNumber(x)
|
||||
flags:EnforceNumber(d)
|
||||
flags:EnforceNumbers(x,d)
|
||||
-- flags:EnforceNumber(x)
|
||||
-- flags:EnforceNumber(d)
|
||||
if x ~= d then
|
||||
self:Prepend(flags, x)
|
||||
self:Slot(o)
|
||||
|
||||
@@ -34,6 +34,20 @@ function type_mt:EnforceNumber(n)
|
||||
error("Number is not in the valid range")
|
||||
end
|
||||
|
||||
function type_mt:EnforceNumbers(a,b)
|
||||
-- duplicate code since the overhead of function calls
|
||||
-- for such a popular method is time consuming
|
||||
if not self.min_value and not self.max_value then
|
||||
return
|
||||
end
|
||||
|
||||
if self.min_value <= a and a <= self.max_value and self.min_value <= b and b <= self.max_value then
|
||||
return
|
||||
end
|
||||
|
||||
error("Number is not in the valid range")
|
||||
end
|
||||
|
||||
function type_mt:EnforceNumberAndPack(n)
|
||||
return bpack(self.packFmt, n)
|
||||
end
|
||||
@@ -53,7 +67,13 @@ local bool_mt =
|
||||
max_value = true,
|
||||
lua_type = type(true),
|
||||
name = "bool",
|
||||
packFmt = "<b"
|
||||
packFmt = "<I1",
|
||||
Pack = function(self, value) return value and "1" or "0" end,
|
||||
Unpack = function(self, buf, pos) return buf[pos] == "1" end,
|
||||
ValidNumber = function(self, n) return true end, -- anything is a valid boolean in Lua
|
||||
EnforceNumber = function(self, n) end, -- anything is a valid boolean in Lua
|
||||
EnforceNumbers = function(self, a, b) end, -- anything is a valid boolean in Lua
|
||||
EnforceNumberAndPack = function(self, n) return self:Pack(value) end,
|
||||
}
|
||||
|
||||
local uint8_mt =
|
||||
@@ -170,7 +190,6 @@ setmetatable(float32_mt, {__index = type_mt})
|
||||
setmetatable(float64_mt, {__index = type_mt})
|
||||
|
||||
|
||||
m.Bool = bool_mt
|
||||
m.Uint8 = uint8_mt
|
||||
m.Uint16 = uint16_mt
|
||||
m.Uint32 = uint32_mt
|
||||
@@ -186,7 +205,7 @@ m.UOffsetT = uint32_mt
|
||||
m.VOffsetT = uint16_mt
|
||||
m.SOffsetT = int32_mt
|
||||
|
||||
function GenerateTypes(listOfTypes)
|
||||
local GenerateTypes = function(listOfTypes)
|
||||
for _,t in pairs(listOfTypes) do
|
||||
t.Pack = function(self, value) return bpack(self.packFmt, value) end
|
||||
t.Unpack = function(self, buf, pos) return bunpack(self.packFmt, buf, pos) end
|
||||
@@ -195,4 +214,6 @@ end
|
||||
|
||||
GenerateTypes(m)
|
||||
|
||||
-- explicitly execute after GenerateTypes call, as we don't want to define a Pack/Unpack function for it.
|
||||
m.Bool = bool_mt
|
||||
return m
|
||||
|
||||
@@ -6,69 +6,83 @@ local mt_name = "flatbuffers.view.mt"
|
||||
local N = require("flatbuffers.numTypes")
|
||||
local binaryarray = require("flatbuffers.binaryarray")
|
||||
|
||||
local function enforceOffset(off)
|
||||
if off < 0 or off > 42949672951 then
|
||||
error("Offset is not valid")
|
||||
end
|
||||
end
|
||||
|
||||
local unpack = string.unpack
|
||||
local function unPackUoffset(bytes, off)
|
||||
return unpack("<I4", bytes.str, off + 1)
|
||||
end
|
||||
|
||||
local function unPackVoffset(bytes, off)
|
||||
return unpack("<I2", bytes.str, off + 1)
|
||||
end
|
||||
|
||||
function m.New(buf, pos)
|
||||
N.UOffsetT:EnforceNumber(pos)
|
||||
|
||||
enforceOffset(pos)
|
||||
-- need to convert from a string buffer into
|
||||
-- a binary array
|
||||
|
||||
local o = {
|
||||
bytes = type(buf) == "string" and binaryarray.New(buf) or buf,
|
||||
pos = pos
|
||||
pos = pos,
|
||||
}
|
||||
setmetatable(o, {__index = mt, __metatable = mt_name})
|
||||
return o
|
||||
end
|
||||
|
||||
function mt:Offset(vtableOffset)
|
||||
local vtable = self.pos - self:Get(N.SOffsetT, self.pos)
|
||||
local vtableEnd = self:Get(N.VOffsetT, vtable)
|
||||
if vtableOffset < vtableEnd then
|
||||
return self:Get(N.VOffsetT, vtable + vtableOffset)
|
||||
local vtable = self.vtable
|
||||
if not vtable then
|
||||
vtable = self.pos - self:Get(N.SOffsetT, self.pos)
|
||||
self.vtable = vtable
|
||||
self.vtableEnd = self:Get(N.VOffsetT, vtable)
|
||||
end
|
||||
if vtableOffset < self.vtableEnd then
|
||||
return unPackVoffset(self.bytes, vtable + vtableOffset)
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function mt:Indirect(off)
|
||||
N.UOffsetT:EnforceNumber(off)
|
||||
return off + N.UOffsetT:Unpack(self.bytes, off)
|
||||
enforceOffset(off)
|
||||
return off + unPackUoffset(self.bytes, off)
|
||||
end
|
||||
|
||||
function mt:String(off)
|
||||
N.UOffsetT:EnforceNumber(off)
|
||||
off = off + N.UOffsetT:Unpack(self.bytes, off)
|
||||
local start = off + N.UOffsetT.bytewidth
|
||||
local length = N.UOffsetT:Unpack(self.bytes, off)
|
||||
enforceOffset(off)
|
||||
off = off + unPackUoffset(self.bytes, off)
|
||||
local start = off + 4
|
||||
local length = unPackUoffset(self.bytes, off)
|
||||
return self.bytes:Slice(start, start+length)
|
||||
end
|
||||
|
||||
function mt:VectorLen(off)
|
||||
N.UOffsetT:EnforceNumber(off)
|
||||
enforceOffset(off)
|
||||
off = off + self.pos
|
||||
off = off + N.UOffsetT:Unpack(self.bytes, off)
|
||||
return N.UOffsetT:Unpack(self.bytes, off)
|
||||
off = off + unPackUoffset(self.bytes, off)
|
||||
return unPackUoffset(self.bytes, off)
|
||||
end
|
||||
|
||||
function mt:Vector(off)
|
||||
N.UOffsetT:EnforceNumber(off)
|
||||
|
||||
enforceOffset(off)
|
||||
off = off + self.pos
|
||||
local x = off + self:Get(N.UOffsetT, off)
|
||||
x = x + N.UOffsetT.bytewidth
|
||||
return x
|
||||
return off + self:Get(N.UOffsetT, off) + 4
|
||||
end
|
||||
|
||||
function mt:Union(t2, off)
|
||||
assert(getmetatable(t2) == mt_name)
|
||||
N.UOffsetT:EnforceNumber(off)
|
||||
|
||||
enforceOffset(off)
|
||||
off = off + self.pos
|
||||
t2.pos = off + self:Get(N.UOffsetT, off)
|
||||
t2.bytes = self.bytes
|
||||
end
|
||||
|
||||
function mt:Get(flags, off)
|
||||
N.UOffsetT:EnforceNumber(off)
|
||||
enforceOffset(off)
|
||||
return flags:Unpack(self.bytes, off)
|
||||
end
|
||||
|
||||
@@ -85,8 +99,7 @@ function mt:GetSlot(slot, d, validatorFlags)
|
||||
end
|
||||
|
||||
function mt:GetVOffsetTSlot(slot, d)
|
||||
N.VOffsetT:EnforceNumber(slot)
|
||||
N.VOffsetT:EnforceNumber(d)
|
||||
N.VOffsetT:EnforceNumbers(slot, d)
|
||||
local off = self:Offset(slot)
|
||||
if off == 0 then
|
||||
return d
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
/// @file
|
||||
@@ -47,6 +48,9 @@ namespace FlatBuffers
|
||||
// For the current vector being built.
|
||||
private int _vectorNumElems = 0;
|
||||
|
||||
// For CreateSharedString
|
||||
private Dictionary<string, StringOffset> _sharedStringMap = null;
|
||||
|
||||
/// <summary>
|
||||
/// Create a FlatBufferBuilder with a given initial size.
|
||||
/// </summary>
|
||||
@@ -191,7 +195,7 @@ namespace FlatBuffers
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Puts an array of type T into this builder at the
|
||||
/// Puts an array of type T into this builder at the
|
||||
/// current offset
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the input data </typeparam>
|
||||
@@ -204,7 +208,7 @@ namespace FlatBuffers
|
||||
|
||||
#if ENABLE_SPAN_T
|
||||
/// <summary>
|
||||
/// Puts a span of type T into this builder at the
|
||||
/// Puts a span of type T into this builder at the
|
||||
/// current offset
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the input data </typeparam>
|
||||
@@ -407,7 +411,7 @@ namespace FlatBuffers
|
||||
"FlatBuffers: object serialization must not be nested.");
|
||||
}
|
||||
|
||||
public void StartObject(int numfields)
|
||||
public void StartTable(int numfields)
|
||||
{
|
||||
if (numfields < 0)
|
||||
throw new ArgumentOutOfRangeException("Flatbuffers: invalid numfields");
|
||||
@@ -536,9 +540,9 @@ namespace FlatBuffers
|
||||
/// </summary>
|
||||
/// <param name="o">The index into the vtable</param>
|
||||
/// <param name="x">The value to put into the buffer. If the value is equal to the default
|
||||
/// and <see cref="ForceDefaults"/> is false, the value will be skipped.</param>
|
||||
/// the value will be skipped.</param>
|
||||
/// <param name="d">The default value to compare the value against</param>
|
||||
public void AddOffset(int o, int x, int d) { if (ForceDefaults || x != d) { AddOffset(x); Slot(o); } }
|
||||
public void AddOffset(int o, int x, int d) { if (x != d) { AddOffset(x); Slot(o); } }
|
||||
/// @endcond
|
||||
|
||||
/// <summary>
|
||||
@@ -579,6 +583,32 @@ namespace FlatBuffers
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Store a string in the buffer, which can contain any binary data.
|
||||
/// If a string with this exact contents has already been serialized before,
|
||||
/// instead simply returns the offset of the existing string.
|
||||
/// </summary>
|
||||
/// <param name="s">The string to encode.</param>
|
||||
/// <returns>
|
||||
/// The offset in the buffer where the encoded string starts.
|
||||
/// </returns>
|
||||
public StringOffset CreateSharedString(string s)
|
||||
{
|
||||
if (_sharedStringMap == null)
|
||||
{
|
||||
_sharedStringMap = new Dictionary<string, StringOffset>();
|
||||
}
|
||||
|
||||
if (_sharedStringMap.ContainsKey(s))
|
||||
{
|
||||
return _sharedStringMap[s];
|
||||
}
|
||||
|
||||
var stringOffset = CreateString(s);
|
||||
_sharedStringMap.Add(s, stringOffset);
|
||||
return stringOffset;
|
||||
}
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
// Structs are stored inline, so nothing additional is being added.
|
||||
// `d` is always 0.
|
||||
@@ -591,11 +621,11 @@ namespace FlatBuffers
|
||||
}
|
||||
}
|
||||
|
||||
public int EndObject()
|
||||
public int EndTable()
|
||||
{
|
||||
if (_vtableSize < 0)
|
||||
throw new InvalidOperationException(
|
||||
"Flatbuffers: calling endObject without a startObject");
|
||||
"Flatbuffers: calling EndTable without a StartTable");
|
||||
|
||||
AddInt((int)0);
|
||||
var vtableloc = Offset;
|
||||
|
||||
@@ -25,5 +25,13 @@ namespace FlatBuffers
|
||||
{
|
||||
public const int FileIdentifierLength = 4;
|
||||
public const int SizePrefixLength = 4;
|
||||
/** A version identifier to force a compile error if someone
|
||||
accidentally tries to build generated code with a runtime of
|
||||
two mismatched version. Versions need to always match, as
|
||||
the runtime and generated code are modified in sync.
|
||||
Changes to the C# implementation need to be sure to change
|
||||
the version here and in the code generator on every possible
|
||||
incompatible change */
|
||||
public static void FLATBUFFERS_1_12_0() {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,14 @@ namespace FlatBuffers
|
||||
/// </summary>
|
||||
public struct Struct
|
||||
{
|
||||
public int bb_pos;
|
||||
public ByteBuffer bb;
|
||||
public int bb_pos { get; private set; }
|
||||
public ByteBuffer bb { get; private set; }
|
||||
|
||||
// Re-init the internal state with an external buffer {@code ByteBuffer} and an offset within.
|
||||
public Struct(int _i, ByteBuffer _bb) : this()
|
||||
{
|
||||
bb = _bb;
|
||||
bb_pos = _i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace FlatBuffers
|
||||
{
|
||||
@@ -24,11 +25,18 @@ namespace FlatBuffers
|
||||
/// </summary>
|
||||
public struct Table
|
||||
{
|
||||
public int bb_pos;
|
||||
public ByteBuffer bb;
|
||||
public int bb_pos { get; private set; }
|
||||
public ByteBuffer bb { get; private set; }
|
||||
|
||||
public ByteBuffer ByteBuffer { get { return bb; } }
|
||||
|
||||
// Re-init the internal state with an external buffer {@code ByteBuffer} and an offset within.
|
||||
public Table(int _i, ByteBuffer _bb) : this()
|
||||
{
|
||||
bb = _bb;
|
||||
bb_pos = _i;
|
||||
}
|
||||
|
||||
// Look up a field in the vtable, return an offset into the object, or 0 if the field is not
|
||||
// present.
|
||||
public int __offset(int vtableOffset)
|
||||
@@ -82,17 +90,23 @@ namespace FlatBuffers
|
||||
// Get the data of a vector whoses offset is stored at "offset" in this object as an
|
||||
// Spant<byte>. If the vector is not present in the ByteBuffer,
|
||||
// then an empty span will be returned.
|
||||
public Span<byte> __vector_as_span(int offset)
|
||||
public Span<T> __vector_as_span<T>(int offset, int elementSize) where T : struct
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
{
|
||||
throw new NotSupportedException("Getting typed span on a Big Endian " +
|
||||
"system is not support");
|
||||
}
|
||||
|
||||
var o = this.__offset(offset);
|
||||
if (0 == o)
|
||||
{
|
||||
return new Span<byte>();
|
||||
return new Span<T>();
|
||||
}
|
||||
|
||||
var pos = this.__vector(o);
|
||||
var len = this.__vector_len(o);
|
||||
return bb.ToSpan(pos, len);
|
||||
return MemoryMarshal.Cast<byte, T>(bb.ToSpan(pos, len * elementSize));
|
||||
}
|
||||
#else
|
||||
// Get the data of a vector whoses offset is stored at "offset" in this object as an
|
||||
@@ -138,9 +152,8 @@ namespace FlatBuffers
|
||||
// Initialize any Table-derived type to point to the union at the given offset.
|
||||
public T __union<T>(int offset) where T : struct, IFlatbufferObject
|
||||
{
|
||||
offset += bb_pos;
|
||||
T t = new T();
|
||||
t.__init(offset + bb.GetInt(offset), bb);
|
||||
t.__init(__indirect(offset), bb);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "flatbuffers",
|
||||
"version": "1.11.0",
|
||||
"version": "1.12.0",
|
||||
"description": "Memory Efficient Serialization Library",
|
||||
"files": [
|
||||
"js/flatbuffers.js",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user