mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-15 08:48:52 +00:00
Compare commits
169 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20a400e940 | ||
|
|
676f0248aa | ||
|
|
34b8b80f15 | ||
|
|
0998861e0f | ||
|
|
2e3d3cbcb5 | ||
|
|
d3a00f7730 | ||
|
|
cc54963830 | ||
|
|
79f62ee353 | ||
|
|
c0a6e5120d | ||
|
|
08cf50c54a | ||
|
|
6b3f057bdc | ||
|
|
60de374486 | ||
|
|
e78825e7a0 | ||
|
|
cc158e7009 | ||
|
|
5377957b14 | ||
|
|
4bc6de9a88 | ||
|
|
3a62813f0e | ||
|
|
fb94af8899 | ||
|
|
77b458bee5 | ||
|
|
9ce98dd77d | ||
|
|
4ea1be53d4 | ||
|
|
0068b25132 | ||
|
|
ec74f58b94 | ||
|
|
48d8232584 | ||
|
|
55ddb84eb2 | ||
|
|
6e2e909b5c | ||
|
|
b24c0b07a3 | ||
|
|
59e26017cb | ||
|
|
132e6a8220 | ||
|
|
19c81b11b3 | ||
|
|
36f8564846 | ||
|
|
daf0a420be | ||
|
|
474ba68bba | ||
|
|
9de0861104 | ||
|
|
b513db86c7 | ||
|
|
6a1acdc23b | ||
|
|
c696422558 | ||
|
|
e93d2bda07 | ||
|
|
bbf4dac6a3 | ||
|
|
8df2d9a3ef | ||
|
|
462ce03ebe | ||
|
|
020012e69c | ||
|
|
f431a96523 | ||
|
|
3694ae0817 | ||
|
|
2265129e14 | ||
|
|
4bddc6cc0c | ||
|
|
e162366b3f | ||
|
|
fee9afd80b | ||
|
|
98f681deb0 | ||
|
|
5cee340ad3 | ||
|
|
f0769b60ab | ||
|
|
79b80f84df | ||
|
|
dfe68566e4 | ||
|
|
0aa36101f4 | ||
|
|
70f345012d | ||
|
|
a056402f56 | ||
|
|
d7b1d418ee | ||
|
|
9dae3eac60 | ||
|
|
99a8a68a80 | ||
|
|
0c86929e39 | ||
|
|
b24f2016a1 | ||
|
|
1d73b3b9fc | ||
|
|
a4dbe13486 | ||
|
|
89711c9c47 | ||
|
|
5d9930aa0d | ||
|
|
8518b3fb4e | ||
|
|
61f4a46c43 | ||
|
|
dd73b53e28 | ||
|
|
c1901f2c01 | ||
|
|
4071b6f68b | ||
|
|
142401f50a | ||
|
|
7799642270 | ||
|
|
67b29d4e43 | ||
|
|
85b131a719 | ||
|
|
0e8a21854c | ||
|
|
53a897731e | ||
|
|
ba08b0ec02 | ||
|
|
da0bda6be3 | ||
|
|
617bbc9b0c | ||
|
|
0c8b4c7614 | ||
|
|
34aea4361f | ||
|
|
be1ad33910 | ||
|
|
0cf04ad9d5 | ||
|
|
fe483fa380 | ||
|
|
8a8dc4e111 | ||
|
|
7e803c410c | ||
|
|
1336d26252 | ||
|
|
853f7033e0 | ||
|
|
e2c7196ea8 | ||
|
|
61fe2a4fac | ||
|
|
d233b38008 | ||
|
|
ca52bfefc0 | ||
|
|
2edb1dcdda | ||
|
|
6eb031de9a | ||
|
|
5f2af34e02 | ||
|
|
f3f113b24a | ||
|
|
6bb0a728d3 | ||
|
|
97face1527 | ||
|
|
f2627e16ac | ||
|
|
01bac38c84 | ||
|
|
a1b5f565d9 | ||
|
|
0780a7db24 | ||
|
|
9234ddcf11 | ||
|
|
6d9a226f75 | ||
|
|
b0fd1a8c66 | ||
|
|
a0e5d78353 | ||
|
|
bc8a1608a8 | ||
|
|
30e7d16104 | ||
|
|
9c3920d0ab | ||
|
|
5b4acf809e | ||
|
|
86fb05d320 | ||
|
|
5e4739184f | ||
|
|
971a68110e | ||
|
|
7a6b2bf521 | ||
|
|
03e2899985 | ||
|
|
72a99abfb7 | ||
|
|
21a8121982 | ||
|
|
28920aff8f | ||
|
|
77b22aed5a | ||
|
|
cc25516d3e | ||
|
|
1d444f63d3 | ||
|
|
5fa00630af | ||
|
|
97af3d798b | ||
|
|
bb736091f3 | ||
|
|
d5b4db0692 | ||
|
|
5808f7fb03 | ||
|
|
42611f9a83 | ||
|
|
1f0bd12851 | ||
|
|
321a1c9dc0 | ||
|
|
ac1015e3c4 | ||
|
|
513958ea72 | ||
|
|
2f2e4cced4 | ||
|
|
f779962e3e | ||
|
|
69776b9e7e | ||
|
|
00d726fc4c | ||
|
|
ad0f48d7e7 | ||
|
|
801e1b7699 | ||
|
|
432e7582c6 | ||
|
|
d76113100a | ||
|
|
dca33ddb75 | ||
|
|
76744a4345 | ||
|
|
b4e91091ec | ||
|
|
d5f5d382eb | ||
|
|
ffddbdc7ab | ||
|
|
46bb05d952 | ||
|
|
7cc72e4b11 | ||
|
|
a6a3f59253 | ||
|
|
8a58aafda1 | ||
|
|
8dc1641c8a | ||
|
|
4b27c92910 | ||
|
|
7fe281295f | ||
|
|
917ff81b46 | ||
|
|
8a2cc7cc4e | ||
|
|
a64d968473 | ||
|
|
a2b1bfc107 | ||
|
|
f2b3705c2c | ||
|
|
3282a84e30 | ||
|
|
89a68942ac | ||
|
|
360c34467c | ||
|
|
265e43faf0 | ||
|
|
f064a6cc60 | ||
|
|
7fead0f140 | ||
|
|
d6f14b704f | ||
|
|
a892322203 | ||
|
|
2e2063cbeb | ||
|
|
625c989875 | ||
|
|
f20204180d | ||
|
|
0e85eeef2c | ||
|
|
b0fa5e0f42 |
13
.clang-format
Normal file
13
.clang-format
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
BasedOnStyle: Google
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
PointerAlignment: Right
|
||||||
|
IndentPPDirectives: AfterHash
|
||||||
|
Cpp11BracedListStyle: false
|
||||||
|
AlwaysBreakTemplateDeclarations: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: true
|
||||||
|
SpaceAfterTemplateKeyword: false
|
||||||
|
AllowShortBlocksOnASingleLine: true
|
||||||
|
...
|
||||||
|
|
||||||
7
.editorconfig
Normal file
7
.editorconfig
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
root = true
|
||||||
|
[*.{cpp,cc,h}]
|
||||||
|
end_of_line = LF
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
0
.gitattributes
vendored
Executable file → Normal file
0
.gitattributes
vendored
Executable file → Normal file
21
.gitignore
vendored
Executable file → Normal file
21
.gitignore
vendored
Executable file → Normal file
@@ -5,6 +5,7 @@
|
|||||||
*.o.d
|
*.o.d
|
||||||
*.class
|
*.class
|
||||||
*.a
|
*.a
|
||||||
|
*.swp
|
||||||
*~
|
*~
|
||||||
*.vcxproj
|
*.vcxproj
|
||||||
*.vcxproj.filters
|
*.vcxproj.filters
|
||||||
@@ -43,15 +44,19 @@ flatsampletext.exe
|
|||||||
grpctest
|
grpctest
|
||||||
grpctest.exe
|
grpctest.exe
|
||||||
snapshot.sh
|
snapshot.sh
|
||||||
|
tags
|
||||||
tests/go_gen
|
tests/go_gen
|
||||||
tests/monsterdata_java_wire.mon
|
tests/monsterdata_java_wire.mon
|
||||||
|
tests/monsterdata_java_wire_sp.mon
|
||||||
tests/monsterdata_go_wire.mon
|
tests/monsterdata_go_wire.mon
|
||||||
tests/monsterdata_javascript_wire.mon
|
tests/monsterdata_javascript_wire.mon
|
||||||
tests/unicode_test.mon
|
tests/unicode_test.mon
|
||||||
tests/ts/
|
tests/ts/
|
||||||
|
tests/php/
|
||||||
CMakeLists.txt.user
|
CMakeLists.txt.user
|
||||||
CMakeScripts/**
|
CMakeScripts/**
|
||||||
CTestTestfile.cmake
|
CTestTestfile.cmake
|
||||||
|
FlatbuffersConfigVersion.cmake
|
||||||
FlatBuffers.cbp
|
FlatBuffers.cbp
|
||||||
build/Xcode/FlatBuffers.xcodeproj/project.xcworkspace/**
|
build/Xcode/FlatBuffers.xcodeproj/project.xcworkspace/**
|
||||||
build/Xcode/FlatBuffers.xcodeproj/xcuserdata/**
|
build/Xcode/FlatBuffers.xcodeproj/xcuserdata/**
|
||||||
@@ -72,3 +77,19 @@ Testing/Temporary
|
|||||||
.project
|
.project
|
||||||
net/**/obj
|
net/**/obj
|
||||||
node_modules/
|
node_modules/
|
||||||
|
android/.externalNativeBuild/
|
||||||
|
android/.gradle/
|
||||||
|
android/build/
|
||||||
|
samples/android/.externalNativeBuild/
|
||||||
|
samples/android/.gradle/
|
||||||
|
samples/android/build/
|
||||||
|
js/flatbuffers.mjs
|
||||||
|
/bazel-bin
|
||||||
|
/bazel-flatbuffers
|
||||||
|
/bazel-genfiles
|
||||||
|
/bazel-out
|
||||||
|
/bazel-testlogs
|
||||||
|
.ninja_deps
|
||||||
|
.ninja_log
|
||||||
|
build.ninja
|
||||||
|
rules.ninja
|
||||||
|
|||||||
104
.travis.yml
104
.travis.yml
@@ -1,31 +1,83 @@
|
|||||||
language: cpp
|
|
||||||
|
|
||||||
os:
|
|
||||||
- linux
|
|
||||||
- osx
|
|
||||||
|
|
||||||
compiler:
|
|
||||||
- gcc
|
|
||||||
#- clang
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
matrix:
|
|
||||||
- BUILD_TYPE=Debug BIICODE=false
|
|
||||||
- BUILD_TYPE=Release BIICODE=false
|
|
||||||
# biicode .deb files no longer available.
|
|
||||||
# - BUILD_TYPE=Release BIICODE=true
|
|
||||||
# - BUILD_TYPE=Debug BIICODE=true
|
|
||||||
global:
|
global:
|
||||||
|
# Set at the root level as this is ignored when set under matrix.env.
|
||||||
- GCC_VERSION="4.9"
|
- GCC_VERSION="4.9"
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
#- language: python
|
||||||
|
# python: "2.7"
|
||||||
|
# install:
|
||||||
|
# - "pip install wheel twine"
|
||||||
|
# script:
|
||||||
|
# - "cd python/"
|
||||||
|
# - 'VERSION="$TRAVIS_TAG" python setup.py sdist bdist_wheel'
|
||||||
|
# - "cd ../"
|
||||||
|
# deploy:
|
||||||
|
# # Checkpointed release builds.
|
||||||
|
# - provider: script
|
||||||
|
# script: .travis/deploy-python.sh
|
||||||
|
# skip_cleanup: true
|
||||||
|
# on:
|
||||||
|
# tags: true
|
||||||
|
# # all_branches must be set with tags: true. See below post:
|
||||||
|
# # https://stackoverflow.com/a/27775257/1076585
|
||||||
|
# all_branches: true
|
||||||
|
# # Produce a new build for the cutting edge when master changes.
|
||||||
|
# - provider: script
|
||||||
|
# script: .travis/deploy-python.sh
|
||||||
|
# skip_cleanup: true
|
||||||
|
# on:
|
||||||
|
# branch: master
|
||||||
|
- language: cpp
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
- osx
|
||||||
|
|
||||||
before_install:
|
compiler:
|
||||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
|
- gcc
|
||||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi
|
#- clang
|
||||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq g++-$GCC_VERSION; fi
|
|
||||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq gcc-$GCC_VERSION; fi
|
|
||||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which g++-$GCC_VERSION) /usr/bin/g++; fi
|
|
||||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
|
|
||||||
|
|
||||||
script:
|
env:
|
||||||
- if [ "$BIICODE" == "false" ]; then cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE . && make && make test; fi
|
matrix:
|
||||||
- if [ "$BIICODE" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then ./biicode/support/bii-travis.sh $BUILD_TYPE; fi
|
- BUILD_TYPE=Debug BIICODE=false
|
||||||
|
- BUILD_TYPE=Release BIICODE=false CONAN=true
|
||||||
|
# biicode .deb files no longer available.
|
||||||
|
# - BUILD_TYPE=Release BIICODE=true
|
||||||
|
# - BUILD_TYPE=Debug BIICODE=true
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
|
||||||
|
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi
|
||||||
|
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq g++-$GCC_VERSION; fi
|
||||||
|
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq gcc-$GCC_VERSION; fi
|
||||||
|
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which g++-$GCC_VERSION) /usr/bin/g++; fi
|
||||||
|
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
|
||||||
|
|
||||||
|
script:
|
||||||
|
- if [ "$BIICODE" == "false" ]; then cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE . && make && make test; fi
|
||||||
|
- if [ "$BIICODE" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then ./biicode/support/bii-travis.sh $BUILD_TYPE; fi
|
||||||
|
- if [ "$CONAN" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo pip install conan && conan create . flatbuffers/testing -s build_type=$BUILD_TYPE; fi
|
||||||
|
|
||||||
|
- language: android
|
||||||
|
sudo: true
|
||||||
|
android:
|
||||||
|
components:
|
||||||
|
- tools
|
||||||
|
- platform-tools
|
||||||
|
- build-tools-25.0.2
|
||||||
|
- android-25
|
||||||
|
- extra-android-m2repository
|
||||||
|
compiler:
|
||||||
|
- gcc
|
||||||
|
before_install:
|
||||||
|
- git clone https://github.com/urho3d/android-ndk.git $HOME/android-ndk-root
|
||||||
|
- export ANDROID_NDK_HOME=$HOME/android-ndk-root
|
||||||
|
# Setup environment for Linux build which is required to build the sample.
|
||||||
|
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
|
||||||
|
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi
|
||||||
|
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq g++-$GCC_VERSION; fi
|
||||||
|
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq gcc-$GCC_VERSION; fi
|
||||||
|
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which g++-$GCC_VERSION) /usr/bin/g++; fi
|
||||||
|
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
|
||||||
|
script:
|
||||||
|
- failed=0; for build_gradle in $(git ls-files | grep build.gradle); do ( cd "$(dirname "${build_gradle}")" && ./gradlew build ) || failed=1; done; exit $((failed))
|
||||||
|
|||||||
12
.travis/deploy-python.sh
Executable file
12
.travis/deploy-python.sh
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
PROD_REPOSITORY="https://upload.pypi.org/legacy/"
|
||||||
|
TEST_REPOSITORY="https://test.pypi.org/legacy/"
|
||||||
|
|
||||||
|
twine upload \
|
||||||
|
--username "$PYPI_USERNAME" \
|
||||||
|
--password "$PYPI_PASSWORD" \
|
||||||
|
--repository-url "$PROD_REPOSITORY" \
|
||||||
|
"$DIR/../python/dist/"*
|
||||||
|
|
||||||
145
BUILD
Normal file
145
BUILD
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
package(
|
||||||
|
default_visibility = ["//visibility:public"],
|
||||||
|
features = [
|
||||||
|
"-layering_check",
|
||||||
|
"-parse_headers",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
exports_files([
|
||||||
|
"LICENSE",
|
||||||
|
])
|
||||||
|
|
||||||
|
FLATBUFFERS_COPTS = [
|
||||||
|
"-Wno-implicit-fallthrough",
|
||||||
|
"-linclude",
|
||||||
|
]
|
||||||
|
|
||||||
|
# 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"],
|
||||||
|
copts = FLATBUFFERS_COPTS,
|
||||||
|
includes = ["include/"],
|
||||||
|
linkstatic = 1,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Public C++ headers for the Flatbuffers library.
|
||||||
|
filegroup(
|
||||||
|
name = "public_headers",
|
||||||
|
srcs = [
|
||||||
|
"include/flatbuffers/base.h",
|
||||||
|
"include/flatbuffers/code_generators.h",
|
||||||
|
"include/flatbuffers/flatbuffers.h",
|
||||||
|
"include/flatbuffers/flexbuffers.h",
|
||||||
|
"include/flatbuffers/hash.h",
|
||||||
|
"include/flatbuffers/idl.h",
|
||||||
|
"include/flatbuffers/reflection.h",
|
||||||
|
"include/flatbuffers/reflection_generated.h",
|
||||||
|
"include/flatbuffers/stl_emulation.h",
|
||||||
|
"include/flatbuffers/util.h",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
# 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",
|
||||||
|
],
|
||||||
|
copts = FLATBUFFERS_COPTS,
|
||||||
|
includes = [
|
||||||
|
"grpc/",
|
||||||
|
"include/",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
# 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_general.cpp",
|
||||||
|
"src/idl_gen_go.cpp",
|
||||||
|
"src/idl_gen_grpc.cpp",
|
||||||
|
"src/idl_gen_js.cpp",
|
||||||
|
"src/idl_gen_json_schema.cpp",
|
||||||
|
"src/idl_gen_php.cpp",
|
||||||
|
"src/idl_gen_python.cpp",
|
||||||
|
"src/idl_gen_text.cpp",
|
||||||
|
],
|
||||||
|
copts = FLATBUFFERS_COPTS,
|
||||||
|
includes = [
|
||||||
|
"grpc/",
|
||||||
|
"include/",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
":flatc_library",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
# 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/monster_test_generated.h",
|
||||||
|
"tests/namespace_test/namespace_test1_generated.h",
|
||||||
|
"tests/namespace_test/namespace_test2_generated.h",
|
||||||
|
"tests/test.cpp",
|
||||||
|
"tests/union_vector/union_vector_generated.h",
|
||||||
|
":public_headers",
|
||||||
|
],
|
||||||
|
copts = FLATBUFFERS_COPTS + [
|
||||||
|
"-DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE",
|
||||||
|
],
|
||||||
|
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/union_vector/union_vector.fbs",
|
||||||
|
],
|
||||||
|
includes = ["include/"],
|
||||||
|
)
|
||||||
4
CMake/FlatbuffersConfig.cmake
Normal file
4
CMake/FlatbuffersConfig.cmake
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/FlatbuffersTargets.cmake" OPTIONAL)
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/FlatcTargets.cmake" OPTIONAL)
|
||||||
|
include("${CMAKE_CURRENT_LIST_DIR}/FlatbuffersSharedTargets.cmake" OPTIONAL)
|
||||||
|
|
||||||
11
CMake/FlatbuffersConfigVersion.cmake.in
Normal file
11
CMake/FlatbuffersConfigVersion.cmake.in
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
set(PACKAGE_VERSION "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@")
|
||||||
|
|
||||||
|
# Check whether the requested PACKAGE_FIND_VERSION is compatible
|
||||||
|
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
|
||||||
|
set(PACKAGE_VERSION_COMPATIBLE FALSE)
|
||||||
|
else()
|
||||||
|
set(PACKAGE_VERSION_COMPATIBLE TRUE)
|
||||||
|
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
|
||||||
|
set(PACKAGE_VERSION_EXACT TRUE)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
@@ -11,22 +11,6 @@ if (UNIX)
|
|||||||
SET(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/google/flatbuffers")
|
SET(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/google/flatbuffers")
|
||||||
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Vitaly Isaev <vitalyisaev2@gmail.com>")
|
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Vitaly Isaev <vitalyisaev2@gmail.com>")
|
||||||
|
|
||||||
# Derive package version from git
|
|
||||||
EXECUTE_PROCESS(
|
|
||||||
COMMAND date +%Y%m%d
|
|
||||||
OUTPUT_VARIABLE DATE
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
||||||
)
|
|
||||||
EXECUTE_PROCESS(
|
|
||||||
COMMAND git describe
|
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
|
||||||
OUTPUT_VARIABLE GIT_DESCRIBE_DIRTY
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
||||||
)
|
|
||||||
string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GIT_DESCRIBE_DIRTY}")
|
|
||||||
string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${GIT_DESCRIBE_DIRTY}")
|
|
||||||
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${GIT_DESCRIBE_DIRTY}")
|
|
||||||
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+\\-([0-9]+).*" "\\1" VERSION_COMMIT "${GIT_DESCRIBE_DIRTY}")
|
|
||||||
SET(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
|
SET(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
|
||||||
SET(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
|
SET(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
|
||||||
SET(CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH})
|
SET(CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH})
|
||||||
|
|||||||
11
CMake/Version.cmake
Normal file
11
CMake/Version.cmake
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
find_program(GIT git)
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${GIT} describe
|
||||||
|
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||||
|
OUTPUT_VARIABLE GIT_DESCRIBE_DIRTY
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GIT_DESCRIBE_DIRTY}")
|
||||||
|
string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${GIT_DESCRIBE_DIRTY}")
|
||||||
|
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${GIT_DESCRIBE_DIRTY}")
|
||||||
|
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+\\-([0-9]+).*" "\\1" VERSION_COMMIT "${GIT_DESCRIBE_DIRTY}")
|
||||||
106
CMakeLists.txt
106
CMakeLists.txt
@@ -31,8 +31,10 @@ set(FlatBuffers_Library_SRCS
|
|||||||
include/flatbuffers/util.h
|
include/flatbuffers/util.h
|
||||||
include/flatbuffers/reflection.h
|
include/flatbuffers/reflection.h
|
||||||
include/flatbuffers/reflection_generated.h
|
include/flatbuffers/reflection_generated.h
|
||||||
|
include/flatbuffers/stl_emulation.h
|
||||||
include/flatbuffers/flexbuffers.h
|
include/flatbuffers/flexbuffers.h
|
||||||
include/flatbuffers/registry.h
|
include/flatbuffers/registry.h
|
||||||
|
include/flatbuffers/minireflect.h
|
||||||
src/code_generators.cpp
|
src/code_generators.cpp
|
||||||
src/idl_parser.cpp
|
src/idl_parser.cpp
|
||||||
src/idl_gen_text.cpp
|
src/idl_gen_text.cpp
|
||||||
@@ -50,6 +52,7 @@ set(FlatBuffers_Compiler_SRCS
|
|||||||
src/idl_gen_python.cpp
|
src/idl_gen_python.cpp
|
||||||
src/idl_gen_fbs.cpp
|
src/idl_gen_fbs.cpp
|
||||||
src/idl_gen_grpc.cpp
|
src/idl_gen_grpc.cpp
|
||||||
|
src/idl_gen_json_schema.cpp
|
||||||
src/flatc.cpp
|
src/flatc.cpp
|
||||||
src/flatc_main.cpp
|
src/flatc_main.cpp
|
||||||
grpc/src/compiler/schema_interface.h
|
grpc/src/compiler/schema_interface.h
|
||||||
@@ -57,6 +60,8 @@ set(FlatBuffers_Compiler_SRCS
|
|||||||
grpc/src/compiler/cpp_generator.cc
|
grpc/src/compiler/cpp_generator.cc
|
||||||
grpc/src/compiler/go_generator.h
|
grpc/src/compiler/go_generator.h
|
||||||
grpc/src/compiler/go_generator.cc
|
grpc/src/compiler/go_generator.cc
|
||||||
|
grpc/src/compiler/java_generator.h
|
||||||
|
grpc/src/compiler/java_generator.cc
|
||||||
)
|
)
|
||||||
|
|
||||||
set(FlatHash_SRCS
|
set(FlatHash_SRCS
|
||||||
@@ -115,10 +120,13 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
|
|||||||
endif(CYGWIN)
|
endif(CYGWIN)
|
||||||
set(CMAKE_CXX_FLAGS
|
set(CMAKE_CXX_FLAGS
|
||||||
"${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra -Werror=shadow")
|
"${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra -Werror=shadow")
|
||||||
if (GCC_VERSION VERSION_GREATER 4.4)
|
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.4)
|
||||||
|
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0)
|
||||||
|
set(CMAKE_CXX_FLAGS
|
||||||
|
"${CMAKE_CXX_FLAGS} -faligned-new")
|
||||||
|
endif()
|
||||||
set(CMAKE_CXX_FLAGS
|
set(CMAKE_CXX_FLAGS
|
||||||
"${CMAKE_CXX_FLAGS} -Wunused-result -Werror=unused-result \
|
"${CMAKE_CXX_FLAGS} -Wunused-result -Werror=unused-result -Wunused-parameter -Werror=unused-parameter")
|
||||||
-Wunused-parameter -Werror=unused-parameter")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Certain platforms such as ARM do not use signed chars by default
|
# Certain platforms such as ARM do not use signed chars by default
|
||||||
@@ -128,8 +136,7 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
|
|||||||
|
|
||||||
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
|
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
|
||||||
set(CMAKE_CXX_FLAGS
|
set(CMAKE_CXX_FLAGS
|
||||||
"${CMAKE_CXX_FLAGS} -std=c++0x -Wall -pedantic -Werror \
|
"${CMAKE_CXX_FLAGS} -std=c++0x -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
|
||||||
-Wextra -Wno-unused-parameter")
|
|
||||||
if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
|
if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
|
||||||
set(CMAKE_CXX_FLAGS
|
set(CMAKE_CXX_FLAGS
|
||||||
"${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
"${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||||
@@ -187,7 +194,16 @@ endif()
|
|||||||
|
|
||||||
if(FLATBUFFERS_BUILD_SHAREDLIB)
|
if(FLATBUFFERS_BUILD_SHAREDLIB)
|
||||||
add_library(flatbuffers_shared SHARED ${FlatBuffers_Library_SRCS})
|
add_library(flatbuffers_shared SHARED ${FlatBuffers_Library_SRCS})
|
||||||
set_target_properties(flatbuffers_shared PROPERTIES OUTPUT_NAME flatbuffers)
|
|
||||||
|
# Shared object version: "major.minor.micro"
|
||||||
|
# - micro updated every release when there is no API/ABI changes
|
||||||
|
# - minor updated when there are additions in API/ABI
|
||||||
|
# - major (ABI number) updated when there are changes in ABI (or removals)
|
||||||
|
set(FlatBuffers_Library_SONAME_MAJOR "1")
|
||||||
|
set(FlatBuffers_Library_SONAME_FULL "${FlatBuffers_Library_SONAME_MAJOR}.9.0")
|
||||||
|
set_target_properties(flatbuffers_shared PROPERTIES OUTPUT_NAME flatbuffers
|
||||||
|
SOVERSION "${FlatBuffers_Library_SONAME_MAJOR}"
|
||||||
|
VERSION "${FlatBuffers_Library_SONAME_FULL}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
function(compile_flatbuffers_schema_to_cpp SRC_FBS)
|
function(compile_flatbuffers_schema_to_cpp SRC_FBS)
|
||||||
@@ -197,6 +213,8 @@ function(compile_flatbuffers_schema_to_cpp SRC_FBS)
|
|||||||
OUTPUT ${GEN_HEADER}
|
OUTPUT ${GEN_HEADER}
|
||||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable
|
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable
|
||||||
--gen-object-api -o "${SRC_FBS_DIR}"
|
--gen-object-api -o "${SRC_FBS_DIR}"
|
||||||
|
--cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs
|
||||||
|
--reflect-names
|
||||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||||
DEPENDS flatc)
|
DEPENDS flatc)
|
||||||
@@ -231,19 +249,85 @@ if(FLATBUFFERS_BUILD_GRPCTEST)
|
|||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter -Wno-shadow")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter -Wno-shadow")
|
||||||
endif()
|
endif()
|
||||||
add_executable(grpctest ${FlatBuffers_GRPCTest_SRCS})
|
add_executable(grpctest ${FlatBuffers_GRPCTest_SRCS})
|
||||||
target_link_libraries(grpctest grpc++_unsecure pthread dl)
|
target_link_libraries(grpctest grpc++_unsecure grpc_unsecure gpr pthread dl)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
include(CMake/Version.cmake)
|
||||||
|
|
||||||
if(FLATBUFFERS_INSTALL)
|
if(FLATBUFFERS_INSTALL)
|
||||||
install(DIRECTORY include/flatbuffers DESTINATION include)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
install(DIRECTORY include/flatbuffers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||||
|
|
||||||
|
set(FB_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/flatbuffers")
|
||||||
|
|
||||||
|
configure_file(CMake/FlatbuffersConfigVersion.cmake.in FlatbuffersConfigVersion.cmake @ONLY)
|
||||||
|
install(
|
||||||
|
FILES "CMake/FlatbuffersConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/FlatbuffersConfigVersion.cmake"
|
||||||
|
DESTINATION ${FB_CMAKE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
if(FLATBUFFERS_BUILD_FLATLIB)
|
if(FLATBUFFERS_BUILD_FLATLIB)
|
||||||
install(TARGETS flatbuffers DESTINATION lib)
|
if(CMAKE_VERSION VERSION_LESS 3.0)
|
||||||
|
install(
|
||||||
|
TARGETS flatbuffers EXPORT FlatbuffersTargets
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
install(
|
||||||
|
TARGETS flatbuffers EXPORT FlatbuffersTargets
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(EXPORT FlatbuffersTargets
|
||||||
|
FILE FlatbuffersTargets.cmake
|
||||||
|
NAMESPACE flatbuffers::
|
||||||
|
DESTINATION ${FB_CMAKE_DIR}
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(FLATBUFFERS_BUILD_FLATC)
|
if(FLATBUFFERS_BUILD_FLATC)
|
||||||
install(TARGETS flatc DESTINATION bin)
|
install(
|
||||||
|
TARGETS flatc EXPORT FlatcTargets
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
CONFIGURATIONS Release
|
||||||
|
)
|
||||||
|
|
||||||
|
install(
|
||||||
|
EXPORT FlatcTargets
|
||||||
|
FILE FlatcTargets.cmake
|
||||||
|
NAMESPACE flatbuffers::
|
||||||
|
DESTINATION ${FB_CMAKE_DIR}
|
||||||
|
CONFIGURATIONS Release
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(FLATBUFFERS_BUILD_SHAREDLIB)
|
if(FLATBUFFERS_BUILD_SHAREDLIB)
|
||||||
install(TARGETS flatbuffers_shared DESTINATION lib)
|
if(CMAKE_VERSION VERSION_LESS 3.0)
|
||||||
|
install(
|
||||||
|
TARGETS flatbuffers_shared EXPORT FlatbuffersSharedTargets
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
install(
|
||||||
|
TARGETS flatbuffers_shared EXPORT FlatbuffersSharedTargets
|
||||||
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(
|
||||||
|
EXPORT FlatbuffersSharedTargets
|
||||||
|
FILE FlatbuffersSharedTargets.cmake
|
||||||
|
NAMESPACE flatbuffers::
|
||||||
|
DESTINATION ${FB_CMAKE_DIR}
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
0
android/.project
Executable file → Normal file
0
android/.project
Executable file → Normal file
11
android/AndroidManifest.xml
Executable file → Normal file
11
android/AndroidManifest.xml
Executable file → Normal file
@@ -17,17 +17,14 @@
|
|||||||
-->
|
-->
|
||||||
<!-- BEGIN_INCLUDE(manifest) -->
|
<!-- BEGIN_INCLUDE(manifest) -->
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.example.FlatBufferTest"
|
package="com.example.FlatBufferTest">
|
||||||
android:versionCode="1"
|
|
||||||
android:versionName="1.0">
|
|
||||||
|
|
||||||
<uses-feature android:glEsVersion="0x00020000"></uses-feature>
|
<uses-feature android:glEsVersion="0x00020000"></uses-feature>
|
||||||
<!-- This is the platform API where NativeActivity was introduced. -->
|
|
||||||
<uses-sdk android:minSdkVersion="9" />
|
|
||||||
|
|
||||||
<!-- This .apk has no Java code itself, so set hasCode to false. -->
|
<!-- This .apk has no Java code itself, so set hasCode to false. -->
|
||||||
<application android:label="@string/app_name" android:hasCode="false">
|
<application android:label="@string/app_name"
|
||||||
|
android:hasCode="false"
|
||||||
|
android:allowBackup="false">
|
||||||
<!-- Our activity is the built-in NativeActivity framework class.
|
<!-- Our activity is the built-in NativeActivity framework class.
|
||||||
This will take care of integrating with our NDK code. -->
|
This will take care of integrating with our NDK code. -->
|
||||||
<activity android:name="android.app.NativeActivity"
|
<activity android:name="android.app.NativeActivity"
|
||||||
|
|||||||
108
android/build.gradle
Normal file
108
android/build.gradle
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
// Copyright (c) 2017 Google, Inc.
|
||||||
|
//
|
||||||
|
// This software is provided 'as-is', without any express or implied
|
||||||
|
// warranty. In no event will the authors be held liable for any damages
|
||||||
|
// arising from the use of this software.
|
||||||
|
// Permission is granted to anyone to use this software for any purpose,
|
||||||
|
// including commercial applications, and to alter it and redistribute it
|
||||||
|
// freely, subject to the following restrictions:
|
||||||
|
// 1. The origin of this software must not be misrepresented; you must not
|
||||||
|
// claim that you wrote the original software. If you use this software
|
||||||
|
// in a product, an acknowledgment in the product documentation would be
|
||||||
|
// appreciated but is not required.
|
||||||
|
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
|
// misrepresented as being the original software.
|
||||||
|
// 3. This notice may not be removed or altered from any source distribution.
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.android.tools.build:gradle:2.3.0'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
allprojects {
|
||||||
|
repositories {
|
||||||
|
jcenter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'com.android.application'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 25
|
||||||
|
buildToolsVersion '25.0.2'
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
manifest.srcFile 'AndroidManifest.xml'
|
||||||
|
res.srcDirs = ['res']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
externalNativeBuild {
|
||||||
|
ndkBuild {
|
||||||
|
path "jni/Android.mk"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
applicationId 'com.example.FlatBufferTest'
|
||||||
|
// This is the platform API where NativeActivity was introduced.
|
||||||
|
minSdkVersion 9
|
||||||
|
targetSdkVersion 25
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
externalNativeBuild {
|
||||||
|
ndkBuild {
|
||||||
|
targets "FlatBufferTest"
|
||||||
|
arguments "-j" + Runtime.getRuntime().availableProcessors()
|
||||||
|
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lintOptions {
|
||||||
|
abortOnError false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build with each STL variant.
|
||||||
|
productFlavors {
|
||||||
|
stlport {
|
||||||
|
applicationIdSuffix ".stlport"
|
||||||
|
versionNameSuffix "-stlport"
|
||||||
|
externalNativeBuild {
|
||||||
|
ndkBuild {
|
||||||
|
arguments "APP_STL=stlport_static"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gnustl {
|
||||||
|
applicationIdSuffix ".gnustl"
|
||||||
|
versionNameSuffix "-gnustl"
|
||||||
|
externalNativeBuild {
|
||||||
|
ndkBuild {
|
||||||
|
arguments "APP_STL=gnustl_static"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
libcpp {
|
||||||
|
applicationIdSuffix ".libcpp"
|
||||||
|
versionNameSuffix "-libcpp"
|
||||||
|
externalNativeBuild {
|
||||||
|
ndkBuild {
|
||||||
|
arguments "APP_STL=c++_static"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,511 +0,0 @@
|
|||||||
#!/bin/bash -eu
|
|
||||||
#
|
|
||||||
# Copyright (c) 2013 Google, Inc.
|
|
||||||
#
|
|
||||||
# This software is provided 'as-is', without any express or implied
|
|
||||||
# warranty. In no event will the authors be held liable for any damages
|
|
||||||
# arising from the use of this software.
|
|
||||||
# Permission is granted to anyone to use this software for any purpose,
|
|
||||||
# including commercial applications, and to alter it and redistribute it
|
|
||||||
# freely, subject to the following restrictions:
|
|
||||||
# 1. The origin of this software must not be misrepresented; you must not
|
|
||||||
# claim that you wrote the original software. If you use this software
|
|
||||||
# in a product, an acknowledgment in the product documentation would be
|
|
||||||
# appreciated but is not required.
|
|
||||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
|
||||||
# misrepresented as being the original software.
|
|
||||||
# 3. This notice may not be removed or altered from any source distribution.
|
|
||||||
#
|
|
||||||
# Build, deploy, debug / execute a native Android package based upon
|
|
||||||
# NativeActivity.
|
|
||||||
|
|
||||||
declare -r script_directory=$(dirname $0)
|
|
||||||
declare -r android_root=${script_directory}/../../../../../../
|
|
||||||
declare -r script_name=$(basename $0)
|
|
||||||
declare -r android_manifest=AndroidManifest.xml
|
|
||||||
declare -r os_name=$(uname -s)
|
|
||||||
|
|
||||||
# Minimum Android target version supported by this project.
|
|
||||||
: ${BUILDAPK_ANDROID_TARGET_MINVERSION:=10}
|
|
||||||
# Directory containing the Android SDK
|
|
||||||
# (http://developer.android.com/sdk/index.html).
|
|
||||||
: ${ANDROID_SDK_HOME:=}
|
|
||||||
# Directory containing the Android NDK
|
|
||||||
# (http://developer.android.com/tools/sdk/ndk/index.html).
|
|
||||||
: ${NDK_HOME:=}
|
|
||||||
|
|
||||||
# Display script help and exit.
|
|
||||||
usage() {
|
|
||||||
echo "
|
|
||||||
Build the Android package in the current directory and deploy it to a
|
|
||||||
connected device.
|
|
||||||
|
|
||||||
Usage: ${script_name} \\
|
|
||||||
[ADB_DEVICE=serial_number] [BUILD=0] [DEPLOY=0] [RUN_DEBUGGER=1] \
|
|
||||||
[LAUNCH=0] [SWIG_BIN=swig_binary_directory] [SWIG_LIB=swig_include_directory] [ndk-build arguments ...]
|
|
||||||
|
|
||||||
ADB_DEVICE=serial_number:
|
|
||||||
serial_number specifies the device to deploy the built apk to if multiple
|
|
||||||
Android devices are connected to the host.
|
|
||||||
BUILD=0:
|
|
||||||
Disables the build of the package.
|
|
||||||
DEPLOY=0:
|
|
||||||
Disables the deployment of the built apk to the Android device.
|
|
||||||
RUN_DEBUGGER=1:
|
|
||||||
Launches the application in gdb after it has been deployed. To debug in
|
|
||||||
gdb, NDK_DEBUG=1 must also be specified on the command line to build a
|
|
||||||
debug apk.
|
|
||||||
LAUNCH=0:
|
|
||||||
Disable the launch of the apk on the Android device.
|
|
||||||
SWIG_BIN=swig_binary_directory:
|
|
||||||
The directory where the SWIG binary lives. No need to set this if SWIG is
|
|
||||||
installed and point to from your PATH variable.
|
|
||||||
SWIG_LIB=swig_include_directory:
|
|
||||||
The directory where SWIG shared include files are, usually obtainable from
|
|
||||||
commandline with \"swig -swiglib\". No need to set this if SWIG is installed
|
|
||||||
and point to from your PATH variable.
|
|
||||||
ndk-build arguments...:
|
|
||||||
Additional arguments for ndk-build. See ndk-build -h for more information.
|
|
||||||
" >&2
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get the number of CPU cores present on the host.
|
|
||||||
get_number_of_cores() {
|
|
||||||
case ${os_name} in
|
|
||||||
Darwin)
|
|
||||||
sysctl hw.ncpu | awk '{ print $2 }'
|
|
||||||
;;
|
|
||||||
CYGWIN*|Linux)
|
|
||||||
awk '/^processor/ { n=$3 } END { print n + 1 }' /proc/cpuinfo
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
echo 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get the package name from an AndroidManifest.xml file.
|
|
||||||
get_package_name_from_manifest() {
|
|
||||||
xmllint --xpath 'string(/manifest/@package)' "${1}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get the library name from an AndroidManifest.xml file.
|
|
||||||
get_library_name_from_manifest() {
|
|
||||||
echo "\
|
|
||||||
setns android=http://schemas.android.com/apk/res/android
|
|
||||||
xpath string(/manifest/application/activity\
|
|
||||||
[@android:name=\"android.app.NativeActivity\"]/meta-data\
|
|
||||||
[@android:name=\"android.app.lib_name\"]/@android:value)" |
|
|
||||||
xmllint --shell "${1}" | awk '/Object is a string/ { print $NF }'
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get the number of Android devices connected to the system.
|
|
||||||
get_number_of_devices_connected() {
|
|
||||||
adb devices -l | \
|
|
||||||
awk '/^..*$/ { if (p) { print $0 } }
|
|
||||||
/List of devices attached/ { p = 1 }' | \
|
|
||||||
wc -l
|
|
||||||
return ${PIPESTATUS[0]}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Kill a process and its' children. This is provided for cygwin which
|
|
||||||
# doesn't ship with pkill.
|
|
||||||
kill_process_group() {
|
|
||||||
local parent_pid="${1}"
|
|
||||||
local child_pid=
|
|
||||||
for child_pid in $(ps -f | \
|
|
||||||
awk '{ if ($3 == '"${parent_pid}"') { print $2 } }'); do
|
|
||||||
kill_process_group "${child_pid}"
|
|
||||||
done
|
|
||||||
kill "${parent_pid}" 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
# Find and run "adb".
|
|
||||||
adb() {
|
|
||||||
local adb_path=
|
|
||||||
for path in "$(which adb 2>/dev/null)" \
|
|
||||||
"${ANDROID_SDK_HOME}/sdk/platform-tools/adb" \
|
|
||||||
"${android_root}/prebuilts/sdk/platform-tools/adb"; do
|
|
||||||
if [[ -e "${path}" ]]; then
|
|
||||||
adb_path="${path}"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if [[ "${adb_path}" == "" ]]; then
|
|
||||||
echo -e "Unable to find adb." \
|
|
||||||
"\nAdd the Android ADT sdk/platform-tools directory to the" \
|
|
||||||
"PATH." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
"${adb_path}" "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Find and run "android".
|
|
||||||
android() {
|
|
||||||
local android_executable=android
|
|
||||||
if echo "${os_name}" | grep -q CYGWIN; then
|
|
||||||
android_executable=android.bat
|
|
||||||
fi
|
|
||||||
local android_path=
|
|
||||||
for path in "$(which ${android_executable})" \
|
|
||||||
"${ANDROID_SDK_HOME}/sdk/tools/${android_executable}" \
|
|
||||||
"${android_root}/prebuilts/sdk/tools/${android_executable}"; do
|
|
||||||
if [[ -e "${path}" ]]; then
|
|
||||||
android_path="${path}"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if [[ "${android_path}" == "" ]]; then
|
|
||||||
echo -e "Unable to find android tool." \
|
|
||||||
"\nAdd the Android ADT sdk/tools directory to the PATH." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
# Make sure ant is installed.
|
|
||||||
if [[ "$(which ant)" == "" ]]; then
|
|
||||||
echo -e "Unable to find ant." \
|
|
||||||
"\nPlease install ant and add to the PATH." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
"${android_path}" "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Find and run "ndk-build"
|
|
||||||
ndkbuild() {
|
|
||||||
local ndkbuild_path=
|
|
||||||
for path in "$(which ndk-build 2>/dev/null)" \
|
|
||||||
"${NDK_HOME}/ndk-build" \
|
|
||||||
"${android_root}/prebuilts/ndk/current/ndk-build"; do
|
|
||||||
if [[ -e "${path}" ]]; then
|
|
||||||
ndkbuild_path="${path}"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if [[ "${ndkbuild_path}" == "" ]]; then
|
|
||||||
echo -e "Unable to find ndk-build." \
|
|
||||||
"\nAdd the Android NDK directory to the PATH." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
"${ndkbuild_path}" "$@"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get file modification time of $1 in seconds since the epoch.
|
|
||||||
stat_mtime() {
|
|
||||||
local filename="${1}"
|
|
||||||
case ${os_name} in
|
|
||||||
Darwin) stat -f%m "${filename}" 2>/dev/null || echo 0 ;;
|
|
||||||
*) stat -c%Y "${filename}" 2>/dev/null || echo 0 ;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
|
|
||||||
# Build the native (C/C++) build targets in the current directory.
|
|
||||||
build_native_targets() {
|
|
||||||
# Save the list of output modules in the install directory so that it's
|
|
||||||
# possible to restore their timestamps after the build is complete. This
|
|
||||||
# works around a bug in ndk/build/core/setup-app.mk which results in the
|
|
||||||
# unconditional execution of the clean-installed-binaries rule.
|
|
||||||
restore_libraries="$(find libs -type f 2>/dev/null | \
|
|
||||||
sed -E 's@^libs/(.*)@\1@')"
|
|
||||||
|
|
||||||
# Build native code.
|
|
||||||
ndkbuild -j$(get_number_of_cores) "$@"
|
|
||||||
|
|
||||||
# Restore installed libraries.
|
|
||||||
# Obviously this is a nasty hack (along with ${restore_libraries} above) as
|
|
||||||
# it assumes it knows where the NDK will be placing output files.
|
|
||||||
(
|
|
||||||
IFS=$'\n'
|
|
||||||
for libpath in ${restore_libraries}; do
|
|
||||||
source_library="obj/local/${libpath}"
|
|
||||||
target_library="libs/${libpath}"
|
|
||||||
if [[ -e "${source_library}" ]]; then
|
|
||||||
cp -a "${source_library}" "${target_library}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
# Select the oldest installed android build target that is at least as new as
|
|
||||||
# BUILDAPK_ANDROID_TARGET_MINVERSION. If a suitable build target isn't found,
|
|
||||||
# this function prints an error message and exits with an error.
|
|
||||||
select_android_build_target() {
|
|
||||||
local -r android_targets_installed=$( \
|
|
||||||
android list targets | \
|
|
||||||
awk -F'"' '/^id:.*android/ { print $2 }')
|
|
||||||
local android_build_target=
|
|
||||||
for android_target in $(echo "${android_targets_installed}" | \
|
|
||||||
awk -F- '{ print $2 }' | sort -n); do
|
|
||||||
local isNumber='^[0-9]+$'
|
|
||||||
# skip preview API releases e.g. 'android-L'
|
|
||||||
if [[ $android_target =~ $isNumber ]]; then
|
|
||||||
if [[ $((android_target)) -ge \
|
|
||||||
$((BUILDAPK_ANDROID_TARGET_MINVERSION)) ]]; then
|
|
||||||
android_build_target="android-${android_target}"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
# else
|
|
||||||
# The API version is a letter, so skip it.
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
if [[ "${android_build_target}" == "" ]]; then
|
|
||||||
echo -e \
|
|
||||||
"Found installed Android targets:" \
|
|
||||||
"$(echo ${android_targets_installed} | sed 's/ /\n /g;s/^/\n /;')" \
|
|
||||||
"\nAndroid SDK platform" \
|
|
||||||
"android-$((BUILDAPK_ANDROID_TARGET_MINVERSION))" \
|
|
||||||
"must be installed to build this project." \
|
|
||||||
"\nUse the \"android\" application to install API" \
|
|
||||||
"$((BUILDAPK_ANDROID_TARGET_MINVERSION)) or newer." >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "${android_build_target}"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Sign unsigned apk $1 and write the result to $2 with key store file $3 and
|
|
||||||
# password $4.
|
|
||||||
# If a key store file $3 and password $4 aren't specified, a temporary
|
|
||||||
# (60 day) key is generated and used to sign the package.
|
|
||||||
sign_apk() {
|
|
||||||
local unsigned_apk="${1}"
|
|
||||||
local signed_apk="${2}"
|
|
||||||
if [[ $(stat_mtime "${unsigned_apk}") -gt \
|
|
||||||
$(stat_mtime "${signed_apk}") ]]; then
|
|
||||||
local -r key_alias=$(basename ${signed_apk} .apk)
|
|
||||||
local keystore="${3}"
|
|
||||||
local key_password="${4}"
|
|
||||||
[[ "${keystore}" == "" ]] && keystore="${unsigned_apk}.keystore"
|
|
||||||
[[ "${key_password}" == "" ]] && \
|
|
||||||
key_password="${key_alias}123456"
|
|
||||||
if [[ ! -e ${keystore} ]]; then
|
|
||||||
keytool -genkey -v -dname "cn=, ou=${key_alias}, o=fpl" \
|
|
||||||
-storepass ${key_password} \
|
|
||||||
-keypass ${key_password} -keystore ${keystore} \
|
|
||||||
-alias ${key_alias} -keyalg RSA -keysize 2048 -validity 60
|
|
||||||
fi
|
|
||||||
cp "${unsigned_apk}" "${signed_apk}"
|
|
||||||
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 \
|
|
||||||
-keystore ${keystore} -storepass ${key_password} \
|
|
||||||
-keypass ${key_password} "${signed_apk}" ${key_alias}
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Build the apk $1 for package filename $2 in the current directory using the
|
|
||||||
# ant build target $3.
|
|
||||||
build_apk() {
|
|
||||||
local -r output_apk="${1}"
|
|
||||||
local -r package_filename="${2}"
|
|
||||||
local -r ant_target="${3}"
|
|
||||||
# Get the list of installed android targets and select the oldest target
|
|
||||||
# that is at least as new as BUILDAPK_ANDROID_TARGET_MINVERSION.
|
|
||||||
local -r android_build_target=$(select_android_build_target)
|
|
||||||
[[ "${android_build_target}" == "" ]] && exit 1
|
|
||||||
echo "Building ${output_apk} for target ${android_build_target}" >&2
|
|
||||||
|
|
||||||
# Create / update build.xml and local.properties files.
|
|
||||||
if [[ $(stat_mtime "${android_manifest}") -gt \
|
|
||||||
$(stat_mtime build.xml) ]]; then
|
|
||||||
android update project --target "${android_build_target}" \
|
|
||||||
-n ${package_filename} --path .
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Use ant to build the apk.
|
|
||||||
ant -quiet ${ant_target}
|
|
||||||
|
|
||||||
# Sign release apks with a temporary key as these packages will not be
|
|
||||||
# redistributed.
|
|
||||||
local unsigned_apk="bin/${package_filename}-${ant_target}-unsigned.apk"
|
|
||||||
if [[ "${ant_target}" == "release" ]]; then
|
|
||||||
sign_apk "${unsigned_apk}" "${output_apk}" "" ""
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Uninstall package $1 and install apk $2 on device $3 where $3 is "-s device"
|
|
||||||
# or an empty string. If $3 is an empty string adb will fail when multiple
|
|
||||||
# devices are connected to the host system.
|
|
||||||
install_apk() {
|
|
||||||
local -r uninstall_package_name="${1}"
|
|
||||||
local -r install_apk="${2}"
|
|
||||||
local -r adb_device="${3}"
|
|
||||||
# Uninstall the package if it's already installed.
|
|
||||||
adb ${adb_device} uninstall "${uninstall_package_name}" 1>&2 > /dev/null || \
|
|
||||||
true # no error check
|
|
||||||
|
|
||||||
# Install the apk.
|
|
||||||
# NOTE: The following works around adb not returning an error code when
|
|
||||||
# it fails to install an apk.
|
|
||||||
echo "Install ${install_apk}" >&2
|
|
||||||
local -r adb_install_result=$(adb ${adb_device} install "${install_apk}")
|
|
||||||
echo "${adb_install_result}"
|
|
||||||
if echo "${adb_install_result}" | grep -qF 'Failure ['; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Launch previously installed package $1 on device $2.
|
|
||||||
# If $2 is an empty string adb will fail when multiple devices are connected
|
|
||||||
# to the host system.
|
|
||||||
launch_package() {
|
|
||||||
(
|
|
||||||
# Determine the SDK version of Android on the device.
|
|
||||||
local -r android_sdk_version=$(
|
|
||||||
adb ${adb_device} shell cat system/build.prop | \
|
|
||||||
awk -F= '/ro.build.version.sdk/ {
|
|
||||||
v=$2; sub(/[ \r\n]/, "", v); print v
|
|
||||||
}')
|
|
||||||
|
|
||||||
# Clear logs from previous runs.
|
|
||||||
# Note that logcat does not just 'tail' the logs, it dumps the entire log
|
|
||||||
# history.
|
|
||||||
adb ${adb_device} logcat -c
|
|
||||||
|
|
||||||
local finished_msg='Displayed '"${package_name}"
|
|
||||||
local timeout_msg='Activity destroy timeout.*'"${package_name}"
|
|
||||||
# Maximum time to wait before stopping log monitoring. 0 = infinity.
|
|
||||||
local launch_timeout=0
|
|
||||||
# If this is a Gingerbread device, kill log monitoring after 10 seconds.
|
|
||||||
if [[ $((android_sdk_version)) -le 10 ]]; then
|
|
||||||
launch_timeout=10
|
|
||||||
fi
|
|
||||||
# Display logcat in the background.
|
|
||||||
# Stop displaying the log when the app launch / execution completes or the
|
|
||||||
# logcat
|
|
||||||
(
|
|
||||||
adb ${adb_device} logcat | \
|
|
||||||
awk "
|
|
||||||
{
|
|
||||||
print \$0
|
|
||||||
}
|
|
||||||
|
|
||||||
/ActivityManager.*: ${finished_msg}/ {
|
|
||||||
exit 0
|
|
||||||
}
|
|
||||||
|
|
||||||
/ActivityManager.*: ${timeout_msg}/ {
|
|
||||||
exit 0
|
|
||||||
}" &
|
|
||||||
adb_logcat_pid=$!;
|
|
||||||
if [[ $((launch_timeout)) -gt 0 ]]; then
|
|
||||||
sleep $((launch_timeout));
|
|
||||||
kill ${adb_logcat_pid};
|
|
||||||
else
|
|
||||||
wait ${adb_logcat_pid};
|
|
||||||
fi
|
|
||||||
) &
|
|
||||||
logcat_pid=$!
|
|
||||||
# Kill adb logcat if this shell exits.
|
|
||||||
trap "kill_process_group ${logcat_pid}" SIGINT SIGTERM EXIT
|
|
||||||
|
|
||||||
# If the SDK is newer than 10, "am" supports stopping an activity.
|
|
||||||
adb_stop_activity=
|
|
||||||
if [[ $((android_sdk_version)) -gt 10 ]]; then
|
|
||||||
adb_stop_activity=-S
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Launch the activity and wait for it to complete.
|
|
||||||
adb ${adb_device} shell am start ${adb_stop_activity} -n \
|
|
||||||
${package_name}/android.app.NativeActivity
|
|
||||||
|
|
||||||
wait "${logcat_pid}"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
# See usage().
|
|
||||||
main() {
|
|
||||||
# Parse arguments for this script.
|
|
||||||
local adb_device=
|
|
||||||
local ant_target=release
|
|
||||||
local disable_deploy=0
|
|
||||||
local disable_build=0
|
|
||||||
local run_debugger=0
|
|
||||||
local launch=1
|
|
||||||
local build_package=1
|
|
||||||
for opt; do
|
|
||||||
case ${opt} in
|
|
||||||
# NDK_DEBUG=0 tells ndk-build to build this as debuggable but to not
|
|
||||||
# modify the underlying code whereas NDK_DEBUG=1 also builds as debuggable
|
|
||||||
# but does modify the code
|
|
||||||
NDK_DEBUG=1) ant_target=debug ;;
|
|
||||||
NDK_DEBUG=0) ant_target=debug ;;
|
|
||||||
ADB_DEVICE*) adb_device="$(\
|
|
||||||
echo "${opt}" | sed -E 's/^ADB_DEVICE=([^ ]+)$/-s \1/;t;s/.*//')" ;;
|
|
||||||
BUILD=0) disable_build=1 ;;
|
|
||||||
DEPLOY=0) disable_deploy=1 ;;
|
|
||||||
RUN_DEBUGGER=1) run_debugger=1 ;;
|
|
||||||
LAUNCH=0) launch=0 ;;
|
|
||||||
clean) build_package=0 disable_deploy=1 launch=0 ;;
|
|
||||||
-h|--help|help) usage ;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
# If a target device hasn't been specified and multiple devices are connected
|
|
||||||
# to the host machine, display an error.
|
|
||||||
local -r devices_connected=$(get_number_of_devices_connected)
|
|
||||||
if [[ "${adb_device}" == "" && $((devices_connected)) -gt 1 && \
|
|
||||||
($((disable_deploy)) -eq 0 || $((launch)) -ne 0 || \
|
|
||||||
$((run_debugger)) -ne 0) ]]; then
|
|
||||||
if [[ $((disable_deploy)) -ne 0 ]]; then
|
|
||||||
echo "Deployment enabled, disable using DEPLOY=0" >&2
|
|
||||||
fi
|
|
||||||
if [[ $((launch)) -ne 0 ]]; then
|
|
||||||
echo "Launch enabled." >&2
|
|
||||||
fi
|
|
||||||
if [[ $((disable_deploy)) -eq 0 ]]; then
|
|
||||||
echo "Deployment enabled." >&2
|
|
||||||
fi
|
|
||||||
if [[ $((run_debugger)) -ne 0 ]]; then
|
|
||||||
echo "Debugger launch enabled." >&2
|
|
||||||
fi
|
|
||||||
echo "
|
|
||||||
Multiple Android devices are connected to this host. Either disable deployment
|
|
||||||
and execution of the built .apk using:
|
|
||||||
\"${script_name} DEPLOY=0 LAUNCH=0\"
|
|
||||||
|
|
||||||
or specify a device to deploy to using:
|
|
||||||
\"${script_name} ADB_DEVICE=\${device_serial}\".
|
|
||||||
|
|
||||||
The Android devices connected to this machine are:
|
|
||||||
$(adb devices -l)
|
|
||||||
" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $((disable_build)) -eq 0 ]]; then
|
|
||||||
# Build the native target.
|
|
||||||
build_native_targets "$@"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Get the package name from the manifest.
|
|
||||||
local -r package_name=$(get_package_name_from_manifest "${android_manifest}")
|
|
||||||
if [[ "${package_name}" == "" ]]; then
|
|
||||||
echo -e "No package name specified in ${android_manifest},"\
|
|
||||||
"skipping apk build, deploy"
|
|
||||||
"\nand launch steps." >&2
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
local -r package_basename=${package_name/*./}
|
|
||||||
local package_filename=$(get_library_name_from_manifest ${android_manifest})
|
|
||||||
[[ "${package_filename}" == "" ]] && package_filename="${package_basename}"
|
|
||||||
|
|
||||||
# Output apk name.
|
|
||||||
local -r output_apk="bin/${package_filename}-${ant_target}.apk"
|
|
||||||
|
|
||||||
if [[ $((disable_build)) -eq 0 && $((build_package)) -eq 1 ]]; then
|
|
||||||
# Build the apk.
|
|
||||||
build_apk "${output_apk}" "${package_filename}" "${ant_target}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Deploy to the device.
|
|
||||||
if [[ $((disable_deploy)) -eq 0 ]]; then
|
|
||||||
install_apk "${package_name}" "${output_apk}" "${adb_device}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ "${ant_target}" == "debug" && $((run_debugger)) -eq 1 ]]; then
|
|
||||||
# Start debugging.
|
|
||||||
ndk-gdb ${adb_device} --start
|
|
||||||
elif [[ $((launch)) -eq 1 ]]; then
|
|
||||||
launch_package "${package_name}" "${adb_device}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
BIN
android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
android/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
6
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
6
android/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#Mon Jun 19 11:54:59 PDT 2017
|
||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-all.zip
|
||||||
172
android/gradlew
vendored
Executable file
172
android/gradlew
vendored
Executable file
@@ -0,0 +1,172 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
##
|
||||||
|
## Gradle start up script for UN*X
|
||||||
|
##
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
PRG="$0"
|
||||||
|
# Need this for relative symlinks.
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG=`dirname "$PRG"`"/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
SAVED="`pwd`"
|
||||||
|
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
|
APP_HOME="`pwd -P`"
|
||||||
|
cd "$SAVED" >/dev/null
|
||||||
|
|
||||||
|
APP_NAME="Gradle"
|
||||||
|
APP_BASE_NAME=`basename "$0"`
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS=""
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD="maximum"
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="java"
|
||||||
|
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||||
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
|
if [ $? -eq 0 ] ; then
|
||||||
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
MAX_FD="$MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
ulimit -n $MAX_FD
|
||||||
|
if [ $? -ne 0 ] ; then
|
||||||
|
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Darwin, add options to specify how the application appears in the dock
|
||||||
|
if $darwin; then
|
||||||
|
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin ; then
|
||||||
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||||
|
SEP=""
|
||||||
|
for dir in $ROOTDIRSRAW ; do
|
||||||
|
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||||
|
SEP="|"
|
||||||
|
done
|
||||||
|
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||||
|
# Add a user-defined pattern to the cygpath arguments
|
||||||
|
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||||
|
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||||
|
fi
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
i=0
|
||||||
|
for arg in "$@" ; do
|
||||||
|
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||||
|
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||||
|
|
||||||
|
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||||
|
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||||
|
else
|
||||||
|
eval `echo args$i`="\"$arg\""
|
||||||
|
fi
|
||||||
|
i=$((i+1))
|
||||||
|
done
|
||||||
|
case $i in
|
||||||
|
(0) set -- ;;
|
||||||
|
(1) set -- "$args0" ;;
|
||||||
|
(2) set -- "$args0" "$args1" ;;
|
||||||
|
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||||
|
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||||
|
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||||
|
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||||
|
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||||
|
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||||
|
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Escape application args
|
||||||
|
save () {
|
||||||
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
|
}
|
||||||
|
APP_ARGS=$(save "$@")
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||||
|
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||||
|
|
||||||
|
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||||
|
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
84
android/gradlew.bat
vendored
Normal file
84
android/gradlew.bat
vendored
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
@if "%DEBUG%" == "" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS=
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if "%ERRORLEVEL%" == "0" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
|
echo.
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
echo location of your Java installation.
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:init
|
||||||
|
@rem Get command-line arguments, handling Windows variants
|
||||||
|
|
||||||
|
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
|
|
||||||
|
:win9xME_args
|
||||||
|
@rem Slurp the command line arguments.
|
||||||
|
set CMD_LINE_ARGS=
|
||||||
|
set _SKIP=2
|
||||||
|
|
||||||
|
:win9xME_args_slurp
|
||||||
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
|
set CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
||||||
3
android/jni/Android.mk
Executable file → Normal file
3
android/jni/Android.mk
Executable file → Normal file
@@ -39,6 +39,7 @@ LOCAL_SRC_FILES := src/idl_parser.cpp \
|
|||||||
src/util.cpp \
|
src/util.cpp \
|
||||||
src/code_generators.cpp
|
src/code_generators.cpp
|
||||||
LOCAL_STATIC_LIBRARIES := flatbuffers
|
LOCAL_STATIC_LIBRARIES := flatbuffers
|
||||||
|
LOCAL_ARM_MODE := arm
|
||||||
include $(BUILD_STATIC_LIBRARY)
|
include $(BUILD_STATIC_LIBRARY)
|
||||||
|
|
||||||
# FlatBuffers test
|
# FlatBuffers test
|
||||||
@@ -48,7 +49,7 @@ LOCAL_SRC_FILES := android/jni/main.cpp \
|
|||||||
tests/test.cpp \
|
tests/test.cpp \
|
||||||
src/idl_gen_fbs.cpp \
|
src/idl_gen_fbs.cpp \
|
||||||
src/idl_gen_general.cpp
|
src/idl_gen_general.cpp
|
||||||
LOCAL_LDLIBS := -llog -landroid
|
LOCAL_LDLIBS := -llog -landroid -latomic
|
||||||
LOCAL_STATIC_LIBRARIES := android_native_app_glue flatbuffers_extra
|
LOCAL_STATIC_LIBRARIES := android_native_app_glue flatbuffers_extra
|
||||||
LOCAL_ARM_MODE := arm
|
LOCAL_ARM_MODE := arm
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|||||||
6
android/jni/Application.mk
Executable file → Normal file
6
android/jni/Application.mk
Executable file → Normal file
@@ -13,10 +13,8 @@
|
|||||||
# 2. Altered source versions must be plainly marked as such, and must not be
|
# 2. Altered source versions must be plainly marked as such, and must not be
|
||||||
# misrepresented as being the original software.
|
# misrepresented as being the original software.
|
||||||
# 3. This notice may not be removed or altered from any source distribution.
|
# 3. This notice may not be removed or altered from any source distribution.
|
||||||
APP_PLATFORM := android-10
|
APP_PLATFORM := android-9
|
||||||
APP_PROJECT_PATH := $(call my-dir)/..
|
APP_PROJECT_PATH := $(call my-dir)/..
|
||||||
APP_STL := gnustl_static
|
APP_STL ?= stlport_static
|
||||||
|
|
||||||
APP_ABI := armeabi-v7a
|
APP_ABI := armeabi-v7a
|
||||||
|
|
||||||
APP_CPPFLAGS += -std=c++11
|
APP_CPPFLAGS += -std=c++11
|
||||||
|
|||||||
0
android/jni/build_flatc.bat
Executable file → Normal file
0
android/jni/build_flatc.bat
Executable file → Normal file
0
android/res/values/strings.xml
Executable file → Normal file
0
android/res/values/strings.xml
Executable file → Normal file
40
appveyor.yml
40
appveyor.yml
@@ -5,6 +5,12 @@ branches:
|
|||||||
os: Visual Studio 2015
|
os: Visual Studio 2015
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
|
||||||
|
global:
|
||||||
|
# Workaround for https://github.com/conda/conda-build/issues/636
|
||||||
|
PYTHONIOENCODING: UTF-8
|
||||||
|
CONDA_INSTALL_LOCN: "C:\\Miniconda35-x64"
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
- CMAKE_VS_VERSION: "10 2010"
|
- CMAKE_VS_VERSION: "10 2010"
|
||||||
- CMAKE_VS_VERSION: "14 2015"
|
- CMAKE_VS_VERSION: "14 2015"
|
||||||
@@ -26,17 +32,41 @@ build:
|
|||||||
project: ALL_BUILD.vcxproj
|
project: ALL_BUILD.vcxproj
|
||||||
verbosity: minimal
|
verbosity: minimal
|
||||||
|
|
||||||
|
install:
|
||||||
|
- set PATH=%CONDA_INSTALL_LOCN%;%CONDA_INSTALL_LOCN%\scripts;%PATH%;
|
||||||
|
|
||||||
test_script:
|
test_script:
|
||||||
- rem "---------------- C++ -----------------"
|
|
||||||
- "%CONFIGURATION%\\flattests.exe"
|
|
||||||
- rem "---------------- Java -----------------"
|
|
||||||
- "cd tests"
|
- "cd tests"
|
||||||
|
- rem "Building all code"
|
||||||
|
- generate_code.bat -b %CONFIGURATION%
|
||||||
|
- 7z a GeneratedMyGameCode.zip MyGame\
|
||||||
|
- rem "---------------- C++ -----------------"
|
||||||
|
- "cd .."
|
||||||
|
- "%CONFIGURATION%\\flattests.exe"
|
||||||
|
- "cd tests"
|
||||||
|
- rem "---------------- Java -----------------"
|
||||||
- "java -version"
|
- "java -version"
|
||||||
- "JavaTest.bat"
|
- "JavaTest.bat"
|
||||||
- rem "---------------- JS -----------------"
|
- rem "---------------- JS -----------------"
|
||||||
- "node --version"
|
- "node --version"
|
||||||
- "..\\%CONFIGURATION%\\flatc -b -I include_test monster_test.fbs unicode_test.json"
|
- "..\\%CONFIGURATION%\\flatc -b -I include_test monster_test.fbs unicode_test.json"
|
||||||
- "node JavaScriptTest ./monster_test_generated"
|
- "node JavaScriptTest ./monster_test_generated"
|
||||||
|
- rem "-------------- Python ---------------"
|
||||||
|
- where python
|
||||||
|
- python --version
|
||||||
|
- where pip
|
||||||
|
- pip --version
|
||||||
|
- where conda
|
||||||
|
- conda --version
|
||||||
|
- rem "installing flatbuffers python library"
|
||||||
|
- pip install ../python
|
||||||
|
- rem "testing without installing Numpy"
|
||||||
|
- python py_test.py 0 0 0
|
||||||
|
- rem "testing after installing Numpy - disabled"
|
||||||
|
# FIXME: This has a LOT of unnecessary dependencies and makes the tests fail
|
||||||
|
# with timeouts.
|
||||||
|
# - conda install --yes numpy
|
||||||
|
# - python py_test.py 0 0 0
|
||||||
- rem "---------------- C# -----------------"
|
- rem "---------------- C# -----------------"
|
||||||
# Have to compile this here rather than in "build" above because AppVeyor only
|
# Have to compile this here rather than in "build" above because AppVeyor only
|
||||||
# supports building one project??
|
# supports building one project??
|
||||||
@@ -47,5 +77,7 @@ test_script:
|
|||||||
- "cd ..\\.."
|
- "cd ..\\.."
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
- path: $(CONFIGURATION)\\flatc.exe
|
- path: $(CONFIGURATION)\flatc.exe
|
||||||
name: flatc.exe
|
name: flatc.exe
|
||||||
|
- path: tests\GeneratedMyGameCode.zip
|
||||||
|
name: GeneratedMyGameCode.zip
|
||||||
|
|||||||
53
conanfile.py
Normal file
53
conanfile.py
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""Conan recipe package for Google FlatBuffers
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
from conans import ConanFile, CMake, tools
|
||||||
|
|
||||||
|
|
||||||
|
class FlatbuffersConan(ConanFile):
|
||||||
|
name = "flatbuffers"
|
||||||
|
version = "1.9.0"
|
||||||
|
license = "https://github.com/google/flatbuffers/blob/master/LICENSE.txt"
|
||||||
|
url = "https://github.com/google/flatbuffers"
|
||||||
|
description = "Memory Efficient Serialization Library"
|
||||||
|
settings = "os", "compiler", "build_type", "arch", "os_build", "arch_build"
|
||||||
|
options = {"shared": [True, False]}
|
||||||
|
default_options = "shared=False"
|
||||||
|
generators = "cmake"
|
||||||
|
exports = "LICENSE.txt"
|
||||||
|
exports_sources = ["CMake/*", "include/*", "src/*", "grpc/*", "CMakeLists.txt"]
|
||||||
|
|
||||||
|
def _inject_magic_lines(self):
|
||||||
|
"""Inject Conan setup in cmake file to solve exteral dependencies.
|
||||||
|
"""
|
||||||
|
conan_magic_lines = '''project(FlatBuffers)
|
||||||
|
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||||
|
conan_basic_setup()
|
||||||
|
'''
|
||||||
|
tools.replace_in_file("CMakeLists.txt", "project(FlatBuffers)", conan_magic_lines)
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
"""Configure, build and install FlatBuffers using CMake.
|
||||||
|
"""
|
||||||
|
self._inject_magic_lines()
|
||||||
|
cmake = CMake(self)
|
||||||
|
cmake.definitions["FLATBUFFERS_BUILD_TESTS"] = False
|
||||||
|
cmake.definitions["FLATBUFFERS_BUILD_SHAREDLIB"] = self.options.shared
|
||||||
|
cmake.configure()
|
||||||
|
cmake.build()
|
||||||
|
cmake.install()
|
||||||
|
|
||||||
|
def package(self):
|
||||||
|
"""Copy Flatbuffers' artifacts to package folder
|
||||||
|
"""
|
||||||
|
self.copy(pattern="LICENSE.txt", dst="licenses")
|
||||||
|
self.copy(pattern="flathash*", dst="bin", src="bin")
|
||||||
|
|
||||||
|
def package_info(self):
|
||||||
|
"""Collect built libraries names and solve flatc path.
|
||||||
|
"""
|
||||||
|
self.cpp_info.libs = tools.collect_libs(self)
|
||||||
|
self.env_info.PATH.append(os.path.join(self.package_folder, "bin"))
|
||||||
0
docs/footer.html
Executable file → Normal file
0
docs/footer.html
Executable file → Normal file
2
docs/source/Benchmarks.md
Executable file → Normal file
2
docs/source/Benchmarks.md
Executable file → Normal file
@@ -1,4 +1,4 @@
|
|||||||
Benchmarks {#flatbuffers_benchmarks}
|
C++ Benchmarks {#flatbuffers_benchmarks}
|
||||||
==========
|
==========
|
||||||
|
|
||||||
Comparing against other serialization solutions, running on Windows 7
|
Comparing against other serialization solutions, running on Windows 7
|
||||||
|
|||||||
2
docs/source/Building.md
Executable file → Normal file
2
docs/source/Building.md
Executable file → Normal file
@@ -5,7 +5,7 @@ Building {#flatbuffers_guide_building}
|
|||||||
|
|
||||||
The distribution comes with a `cmake` file that should allow
|
The distribution comes with a `cmake` file that should allow
|
||||||
you to build project/make files for any platform. For details on `cmake`, see
|
you to build project/make files for any platform. For details on `cmake`, see
|
||||||
<http://www.cmake.org>. In brief, depending on your platform, use one of
|
<https://www.cmake.org>. In brief, depending on your platform, use one of
|
||||||
e.g.:
|
e.g.:
|
||||||
|
|
||||||
cmake -G "Unix Makefiles"
|
cmake -G "Unix Makefiles"
|
||||||
|
|||||||
3
docs/source/Compiler.md
Executable file → Normal file
3
docs/source/Compiler.md
Executable file → Normal file
@@ -125,5 +125,8 @@ Additional options:
|
|||||||
|
|
||||||
- `--keep-prefix` : Keep original prefix of schema include statement.
|
- `--keep-prefix` : Keep original prefix of schema include statement.
|
||||||
|
|
||||||
|
- `--reflect-types` : Add minimal type reflection to code generation.
|
||||||
|
- `--reflect-names` : Add minimal type/name reflection.
|
||||||
|
|
||||||
NOTE: short-form options for generators are deprecated, use the long form
|
NOTE: short-form options for generators are deprecated, use the long form
|
||||||
whenever possible.
|
whenever possible.
|
||||||
|
|||||||
65
docs/source/CppUsage.md
Executable file → Normal file
65
docs/source/CppUsage.md
Executable file → Normal file
@@ -126,6 +126,45 @@ The following attributes are specific to the object-based API code generation:
|
|||||||
"native_inline", the value specified with this attribute will be included
|
"native_inline", the value specified with this attribute will be included
|
||||||
verbatim in the class constructor initializer list for this member.
|
verbatim in the class constructor initializer list for this member.
|
||||||
|
|
||||||
|
- `native_custom_alloc`:"custom_allocator" (on a table or struct): When using the
|
||||||
|
object-based API all generated NativeTables that are allocated when unpacking
|
||||||
|
your flatbuffer will use "custom allocator". The allocator is also used by
|
||||||
|
any std::vector that appears in a table defined with `native_custom_alloc`.
|
||||||
|
This can be used to provide allocation from a pool for example, for faster
|
||||||
|
unpacking when using the object-based API.
|
||||||
|
|
||||||
|
Minimal Example:
|
||||||
|
|
||||||
|
schema:
|
||||||
|
|
||||||
|
table mytable(native_custom_alloc:"custom_allocator") {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
with custom_allocator defined before flatbuffers.h is included, as:
|
||||||
|
|
||||||
|
template <typename T> struct custom_allocator : public std::allocator<T> {
|
||||||
|
|
||||||
|
typedef T *pointer;
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
struct rebind {
|
||||||
|
typedef custom_allocator<U> other;
|
||||||
|
};
|
||||||
|
|
||||||
|
pointer allocate(const std::size_t n) {
|
||||||
|
return std::allocator<T>::allocate(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
void deallocate(T* ptr, std::size_t n) {
|
||||||
|
return std::allocator<T>::deallocate(ptr,n);
|
||||||
|
}
|
||||||
|
|
||||||
|
custom_allocator() throw() {}
|
||||||
|
template <class U>
|
||||||
|
custom_allocator(const custom_allocator<U>&) throw() {}
|
||||||
|
};
|
||||||
|
|
||||||
- `native_type`' "type" (on a struct): In some cases, a more optimal C++ data
|
- `native_type`' "type" (on a struct): In some cases, a more optimal C++ data
|
||||||
type exists for a given struct. For example, the following schema:
|
type exists for a given struct. For example, the following schema:
|
||||||
|
|
||||||
@@ -231,6 +270,30 @@ schema, as well as a lot of helper functions.
|
|||||||
And example of usage, for the time being, can be found in
|
And example of usage, for the time being, can be found in
|
||||||
`test.cpp/ReflectionTest()`.
|
`test.cpp/ReflectionTest()`.
|
||||||
|
|
||||||
|
## Mini Reflection
|
||||||
|
|
||||||
|
A more limited form of reflection is available for direct inclusion in
|
||||||
|
generated code, which doesn't any (binary) schema access at all. It was designed
|
||||||
|
to keep the overhead of reflection as low as possible (on the order of 2-6
|
||||||
|
bytes per field added to your executable), but doesn't contain all the
|
||||||
|
information the (binary) schema contains.
|
||||||
|
|
||||||
|
You add this information to your generated code by specifying `--reflect-types`
|
||||||
|
(or instead `--reflect-names` if you also want field / enum names).
|
||||||
|
|
||||||
|
You can now use this information, for example to print a FlatBuffer to text:
|
||||||
|
|
||||||
|
auto s = flatbuffers::FlatBufferToString(flatbuf, MonsterTypeTable());
|
||||||
|
|
||||||
|
`MonsterTypeTable()` is declared in the generated code for each type. The
|
||||||
|
string produced is very similar to the JSON produced by the `Parser` based
|
||||||
|
text generator.
|
||||||
|
|
||||||
|
You'll need `flatbuffers/minireflect.h` for this functionality. In there is also
|
||||||
|
a convenient visitor/iterator so you can write your own output / functionality
|
||||||
|
based on the mini reflection tables without having to know the FlatBuffers or
|
||||||
|
reflection encoding.
|
||||||
|
|
||||||
## Storing maps / dictionaries in a FlatBuffer
|
## Storing maps / dictionaries in a FlatBuffer
|
||||||
|
|
||||||
FlatBuffers doesn't support maps natively, but there is support to
|
FlatBuffers doesn't support maps natively, but there is support to
|
||||||
@@ -266,7 +329,7 @@ performs a swap operation on big endian machines), and also because
|
|||||||
the layout of things is generally not known to the user.
|
the layout of things is generally not known to the user.
|
||||||
|
|
||||||
For structs, layout is deterministic and guaranteed to be the same
|
For structs, layout is deterministic and guaranteed to be the same
|
||||||
accross platforms (scalars are aligned to their
|
across platforms (scalars are aligned to their
|
||||||
own size, and structs themselves to their largest member), and you
|
own size, and structs themselves to their largest member), and you
|
||||||
are allowed to access this memory directly by using `sizeof()` and
|
are allowed to access this memory directly by using `sizeof()` and
|
||||||
`memcpy` on the pointer to a struct, or even an array of structs.
|
`memcpy` on the pointer to a struct, or even an array of structs.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ FlatBuffers {#flatbuffers_index}
|
|||||||
# Overview {#flatbuffers_overview}
|
# Overview {#flatbuffers_overview}
|
||||||
|
|
||||||
[FlatBuffers](@ref flatbuffers_overview) is an efficient cross platform
|
[FlatBuffers](@ref flatbuffers_overview) is an efficient cross platform
|
||||||
serialization library for C++, C#, C, Go, Java, JavaScript, PHP, and Python.
|
serialization library for C++, C#, C, Go, Java, JavaScript, TypeScript, PHP, and Python.
|
||||||
It was originally created at Google for game development and other
|
It was originally created at Google for game development and other
|
||||||
performance-critical applications.
|
performance-critical applications.
|
||||||
|
|
||||||
@@ -134,6 +134,10 @@ sections provide a more in-depth usage guide.
|
|||||||
in your own programs.
|
in your own programs.
|
||||||
- How to [use the generated Go code](@ref flatbuffers_guide_use_go) in your
|
- How to [use the generated Go code](@ref flatbuffers_guide_use_go) in your
|
||||||
own programs.
|
own programs.
|
||||||
|
- How to [use the generated JavaScript code](@ref flatbuffers_guide_use_javascript) in your
|
||||||
|
own programs.
|
||||||
|
- How to [use the generated TypeScript code](@ref flatbuffers_guide_use_typescript) in your
|
||||||
|
own programs.
|
||||||
- How to [use FlatBuffers in C with `flatcc`](@ref flatbuffers_guide_use_c) in your
|
- How to [use FlatBuffers in C with `flatcc`](@ref flatbuffers_guide_use_c) in your
|
||||||
own programs.
|
own programs.
|
||||||
- [Support matrix](@ref flatbuffers_support) for platforms/languages/features.
|
- [Support matrix](@ref flatbuffers_support) for platforms/languages/features.
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ map["unknown"].IsNull(); // true
|
|||||||
# Binary encoding
|
# Binary encoding
|
||||||
|
|
||||||
A description of how FlexBuffers are encoded is in the
|
A description of how FlexBuffers are encoded is in the
|
||||||
[internals](Internals.md#flexbuffers) document.
|
[internals](@ref flatbuffers_internals) document.
|
||||||
|
|
||||||
|
|
||||||
# Nesting inside a FlatBuffer
|
# Nesting inside a FlatBuffer
|
||||||
|
|||||||
25
docs/source/Grammar.md
Executable file → Normal file
25
docs/source/Grammar.md
Executable file → Normal file
@@ -4,7 +4,7 @@ Grammar of the schema language {#flatbuffers_grammar}
|
|||||||
schema = include*
|
schema = include*
|
||||||
( namespace\_decl | type\_decl | enum\_decl | root\_decl |
|
( namespace\_decl | type\_decl | enum\_decl | root\_decl |
|
||||||
file_extension_decl | file_identifier_decl |
|
file_extension_decl | file_identifier_decl |
|
||||||
attribute\_decl | object )*
|
attribute\_decl | rpc\_decl | object )*
|
||||||
|
|
||||||
include = `include` string\_constant `;`
|
include = `include` string\_constant `;`
|
||||||
|
|
||||||
@@ -14,16 +14,22 @@ attribute\_decl = `attribute` string\_constant `;`
|
|||||||
|
|
||||||
type\_decl = ( `table` | `struct` ) ident metadata `{` field\_decl+ `}`
|
type\_decl = ( `table` | `struct` ) ident metadata `{` field\_decl+ `}`
|
||||||
|
|
||||||
enum\_decl = ( `enum` | `union` ) ident [ `:` type ] metadata `{` commasep(
|
enum\_decl = ( `enum` ident [ `:` type ] | `union` ident ) metadata `{`
|
||||||
enumval\_decl ) `}`
|
commasep( enumval\_decl ) `}`
|
||||||
|
|
||||||
root\_decl = `root_type` ident `;`
|
root\_decl = `root_type` ident `;`
|
||||||
|
|
||||||
field\_decl = ident `:` type [ `=` scalar ] metadata `;`
|
field\_decl = ident `:` type [ `=` scalar ] metadata `;`
|
||||||
|
|
||||||
|
rpc\_decl = `rpc_service` ident `{` rpc\_method+ `}`
|
||||||
|
|
||||||
|
rpc\_method = ident `(` ident `)` `:` ident metadata `;`
|
||||||
|
|
||||||
type = `bool` | `byte` | `ubyte` | `short` | `ushort` | `int` | `uint` |
|
type = `bool` | `byte` | `ubyte` | `short` | `ushort` | `int` | `uint` |
|
||||||
`float` | `long` | `ulong` | `double`
|
`float` | `long` | `ulong` | `double` |
|
||||||
| `string` | `[` type `]` | ident
|
`int8` | `uint8` | `int16` | `uint16` | `int32` | `uint32`| `int64` | `uint64` |
|
||||||
|
`float32` | `float64` |
|
||||||
|
`string` | `[` type `]` | ident
|
||||||
|
|
||||||
enumval\_decl = ident [ `=` integer\_constant ]
|
enumval\_decl = ident [ `=` integer\_constant ]
|
||||||
|
|
||||||
@@ -43,6 +49,11 @@ file_extension_decl = `file_extension` string\_constant `;`
|
|||||||
|
|
||||||
file_identifier_decl = `file_identifier` string\_constant `;`
|
file_identifier_decl = `file_identifier` string\_constant `;`
|
||||||
|
|
||||||
integer\_constant = -?[0-9]+ | `true` | `false`
|
integer\_constant = `-?[0-9]+` | `true` | `false`
|
||||||
|
|
||||||
|
float\_constant = `-?[0-9]+.[0-9]+((e|E)(+|-)?[0-9]+)?`
|
||||||
|
|
||||||
|
string\_constant = `\".*?\"`
|
||||||
|
|
||||||
|
ident = `[a-zA-Z_][a-zA-Z0-9_]*`
|
||||||
|
|
||||||
float\_constant = -?[0-9]+.[0-9]+((e|E)(+|-)?[0-9]+)?
|
|
||||||
|
|||||||
22
docs/source/Internals.md
Executable file → Normal file
22
docs/source/Internals.md
Executable file → Normal file
@@ -292,6 +292,12 @@ flexibility in which of the children of root object to write first (though in
|
|||||||
this case there's only one string), and what order to write the fields in.
|
this case there's only one string), and what order to write the fields in.
|
||||||
Different orders may also cause different alignments to happen.
|
Different orders may also cause different alignments to happen.
|
||||||
|
|
||||||
|
### Additional reading.
|
||||||
|
|
||||||
|
The author of the C language implementation has made a similar
|
||||||
|
[document](https://github.com/dvidelabs/flatcc/blob/master/doc/binary-format.md#flatbuffers-binary-format)
|
||||||
|
that may further help clarify the format.
|
||||||
|
|
||||||
# FlexBuffers
|
# FlexBuffers
|
||||||
|
|
||||||
The [schema-less](@ref flexbuffers) version of FlatBuffers have their
|
The [schema-less](@ref flexbuffers) version of FlatBuffers have their
|
||||||
@@ -368,6 +374,10 @@ The offset version is useful to encode costly 64bit (or even 32bit) quantities
|
|||||||
into vectors / maps of smaller sizes, and to share / repeat a value multiple
|
into vectors / maps of smaller sizes, and to share / repeat a value multiple
|
||||||
times.
|
times.
|
||||||
|
|
||||||
|
### Booleans and Nulls
|
||||||
|
|
||||||
|
Booleans (`TYPE_BOOL`) and nulls (`TYPE_NULL`) are encoded as inlined unsigned integers.
|
||||||
|
|
||||||
### Blobs, Strings and Keys.
|
### Blobs, Strings and Keys.
|
||||||
|
|
||||||
A blob (`TYPE_BLOB`) is encoded similar to a vector, with one difference: the
|
A blob (`TYPE_BLOB`) is encoded similar to a vector, with one difference: the
|
||||||
@@ -408,19 +418,19 @@ that lookups can be made using binary search.
|
|||||||
|
|
||||||
The reason the key vector is a seperate structure from the value vector is
|
The reason the key vector is a seperate structure from the value vector is
|
||||||
such that it can be shared between multiple value vectors, and also to
|
such that it can be shared between multiple value vectors, and also to
|
||||||
allow it to be treated as its own indivual vector in code.
|
allow it to be treated as its own individual vector in code.
|
||||||
|
|
||||||
An example map { foo: 13, bar: 14 } would be encoded as:
|
An example map { foo: 13, bar: 14 } would be encoded as:
|
||||||
|
|
||||||
0 : uint8_t 'f', 'o', 'o', 0
|
0 : uint8_t 'b', 'a', 'r', 0
|
||||||
4 : uint8_t 'b', 'a', 'r', 0
|
4 : uint8_t 'f', 'o', 'o', 0
|
||||||
8 : uint8_t 2 // key vector of size 2
|
8 : uint8_t 2 // key vector of size 2
|
||||||
// key vector offset points here
|
// key vector offset points here
|
||||||
9 : uint8_t 9, 6 // offsets to foo_key and bar_key
|
9 : uint8_t 9, 6 // offsets to bar_key and foo_key
|
||||||
11: uint8_t 3, 1 // offset to key vector, and its byte width
|
11: uint8_t 2, 1 // offset to key vector, and its byte width
|
||||||
13: uint8_t 2 // value vector of size
|
13: uint8_t 2 // value vector of size
|
||||||
// value vector offset points here
|
// value vector offset points here
|
||||||
14: uint8_t 13, 14 // values
|
14: uint8_t 14, 13 // values
|
||||||
16: uint8_t 4, 4 // types
|
16: uint8_t 4, 4 // types
|
||||||
|
|
||||||
### The root
|
### The root
|
||||||
|
|||||||
2
docs/source/JavaCsharpUsage.md
Executable file → Normal file
2
docs/source/JavaCsharpUsage.md
Executable file → Normal file
@@ -139,7 +139,7 @@ can have fast lookups directly from a FlatBuffer without having to unpack
|
|||||||
your data into a `Dictionary` or similar.
|
your data into a `Dictionary` or similar.
|
||||||
|
|
||||||
To use it:
|
To use it:
|
||||||
- Designate one of the fields in a table as they "key" field. You do this
|
- Designate one of the fields in a table as the "key" field. You do this
|
||||||
by setting the `key` attribute on this field, e.g.
|
by setting the `key` attribute on this field, e.g.
|
||||||
`name:string (key)`.
|
`name:string (key)`.
|
||||||
You may only have one key field, and it must be of string or scalar type.
|
You may only have one key field, and it must be of string or scalar type.
|
||||||
|
|||||||
0
docs/source/JavaScriptUsage.md
Executable file → Normal file
0
docs/source/JavaScriptUsage.md
Executable file → Normal file
27
docs/source/PythonUsage.md
Executable file → Normal file
27
docs/source/PythonUsage.md
Executable file → Normal file
@@ -64,6 +64,33 @@ Now you can access values like this:
|
|||||||
pos = monster.Pos()
|
pos = monster.Pos()
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
## Support for Numpy arrays
|
||||||
|
|
||||||
|
The Flatbuffers python library also has support for accessing scalar
|
||||||
|
vectors as numpy arrays. This can be orders of magnitude faster than
|
||||||
|
iterating over the vector one element at a time, and is particularly
|
||||||
|
useful when unpacking large nested flatbuffers. The generated code for
|
||||||
|
a scalar vector will have a method `<vector name>AsNumpy()`. In the
|
||||||
|
case of the Monster example, you could access the inventory vector
|
||||||
|
like this:
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py}
|
||||||
|
inventory = monster.InventoryAsNumpy()
|
||||||
|
# inventory is a numpy array of type np.dtype('uint8')
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
instead of
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py}
|
||||||
|
inventory = []
|
||||||
|
for i in range(monster.InventoryLength()):
|
||||||
|
inventory.append(int(monster.Inventory(i)))
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Numpy is not a requirement. If numpy is not installed on your system,
|
||||||
|
then attempting to access one of the `*asNumpy()` methods will result
|
||||||
|
in a `NumpyRequiredForThisFeature` exception.
|
||||||
|
|
||||||
## Text Parsing
|
## Text Parsing
|
||||||
|
|
||||||
There currently is no support for parsing text (Schema's and JSON) directly
|
There currently is no support for parsing text (Schema's and JSON) directly
|
||||||
|
|||||||
24
docs/source/Schemas.md
Executable file → Normal file
24
docs/source/Schemas.md
Executable file → Normal file
@@ -84,15 +84,19 @@ parent object, and use no virtual table).
|
|||||||
|
|
||||||
### Types
|
### Types
|
||||||
|
|
||||||
Built-in scalar types are:
|
Built-in scalar types are
|
||||||
|
|
||||||
- 8 bit: `byte`, `ubyte`, `bool`
|
- 8 bit: `byte` (`int8`), `ubyte` (`uint8`), `bool`
|
||||||
|
|
||||||
- 16 bit: `short`, `ushort`
|
- 16 bit: `short` (`int16`), `ushort` (`uint16`)
|
||||||
|
|
||||||
- 32 bit: `int`, `uint`, `float`
|
- 32 bit: `int` (`int32`), `uint` (`uint32`), `float` (`float32`)
|
||||||
|
|
||||||
- 64 bit: `long`, `ulong`, `double`
|
- 64 bit: `long` (`int64`), `ulong` (`uint64`), `double` (`float64`)
|
||||||
|
|
||||||
|
The type names in parentheses are alias names such that for example
|
||||||
|
`uint8` can be used in place of `ubyte`, and `int32` can be used in
|
||||||
|
place of `int` without affecting code generation.
|
||||||
|
|
||||||
Built-in non-scalar types:
|
Built-in non-scalar types:
|
||||||
|
|
||||||
@@ -278,7 +282,10 @@ Current understood attributes:
|
|||||||
IDs allow the fields to be placed in any order in the schema.
|
IDs allow the fields to be placed in any order in the schema.
|
||||||
When a new field is added to the schema it must use the next available ID.
|
When a new field is added to the schema it must use the next available ID.
|
||||||
- `deprecated` (on a field): do not generate accessors for this field
|
- `deprecated` (on a field): do not generate accessors for this field
|
||||||
anymore, code should stop using this data.
|
anymore, code should stop using this data. Old data may still contain this
|
||||||
|
field, but it won't be accessible anymore by newer code. Note that if you
|
||||||
|
deprecate a field that was previous required, old code may fail to validate
|
||||||
|
new data (when using the optional verifier).
|
||||||
- `required` (on a non-scalar table field): this field must always be set.
|
- `required` (on a non-scalar table field): this field must always be set.
|
||||||
By default, all fields are optional, i.e. may be left out. This is
|
By default, all fields are optional, i.e. may be left out. This is
|
||||||
desirable, as it helps with forwards/backwards compatibility, and
|
desirable, as it helps with forwards/backwards compatibility, and
|
||||||
@@ -288,7 +295,10 @@ Current understood attributes:
|
|||||||
constructs FlatBuffers to ensure this field is initialized, so the reading
|
constructs FlatBuffers to ensure this field is initialized, so the reading
|
||||||
code may access it directly, without checking for NULL. If the constructing
|
code may access it directly, without checking for NULL. If the constructing
|
||||||
code does not initialize this field, they will get an assert, and also
|
code does not initialize this field, they will get an assert, and also
|
||||||
the verifier will fail on buffers that have missing required fields.
|
the verifier will fail on buffers that have missing required fields. Note
|
||||||
|
that if you add this attribute to an existing field, this will only be
|
||||||
|
valid if existing data always contains this field / existing code always
|
||||||
|
writes this field.
|
||||||
- `force_align: size` (on a struct): force the alignment of this struct
|
- `force_align: size` (on a struct): force the alignment of this struct
|
||||||
to be something higher than what it is naturally aligned to. Causes
|
to be something higher than what it is naturally aligned to. Causes
|
||||||
these structs to be aligned to that amount inside a buffer, IF that
|
these structs to be aligned to that amount inside a buffer, IF that
|
||||||
|
|||||||
35
docs/source/Support.md
Executable file → Normal file
35
docs/source/Support.md
Executable file → Normal file
@@ -18,27 +18,28 @@ In general:
|
|||||||
|
|
||||||
NOTE: this table is a start, it needs to be extended.
|
NOTE: this table is a start, it needs to be extended.
|
||||||
|
|
||||||
Feature | C++ | Java | C# | Go | Python | JS | C | PHP | Ruby
|
Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Ruby
|
||||||
------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | ------ | --- | ----
|
------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ----
|
||||||
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | WiP
|
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | WiP
|
||||||
JSON parsing | Yes | No | No | No | No | No | Yes | No | No
|
JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No
|
||||||
Simple mutation | Yes | WIP | WIP | No | No | No | No | No | No
|
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No
|
||||||
Reflection | Yes | No | No | No | No | No | Basic | No | No
|
Reflection | Yes | No | No | No | No | No | No | Basic | No | No
|
||||||
Buffer verifier | Yes | No | No | No | No | No | Yes | No | No
|
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No
|
||||||
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | ?
|
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | ?
|
||||||
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | ? | ?
|
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | ?
|
||||||
Performance: | Superb | Great | Great | Great | Ok | ? | Superb | ? | ?
|
Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ?
|
||||||
Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | VS2010 | ? | ?
|
Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | ?
|
||||||
Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | ? | ?
|
Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | ?
|
||||||
Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | ? | ?
|
Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | ?
|
||||||
Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ?
|
Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | ?
|
||||||
Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ?
|
Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | ?
|
||||||
Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ?
|
Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ?
|
||||||
Primary authors (github) | gwvo | gwvo | ev*/js*| rw | rw | evanw/ev* | mik* | ch* | rw
|
Primary authors (github) | gwvo | gwvo | ev*/js*| rw | rw | evanw/ev* | kr | mik* | ch* | rw
|
||||||
|
|
||||||
* ev = evolutional
|
* ev = evolutional
|
||||||
* js = jonsimantov
|
* js = jonsimantov
|
||||||
* mik = mikkelfj
|
* mik = mikkelfj
|
||||||
* ch = chobie
|
* ch = chobie
|
||||||
|
* kr = krojew
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ Please select your desired language for our quest:
|
|||||||
<input type="radio" name="language" value="go">Go</input>
|
<input type="radio" name="language" value="go">Go</input>
|
||||||
<input type="radio" name="language" value="python">Python</input>
|
<input type="radio" name="language" value="python">Python</input>
|
||||||
<input type="radio" name="language" value="javascript">JavaScript</input>
|
<input type="radio" name="language" value="javascript">JavaScript</input>
|
||||||
|
<input type="radio" name="language" value="typescript">TypeScript</input>
|
||||||
<input type="radio" name="language" value="php">PHP</input>
|
<input type="radio" name="language" value="php">PHP</input>
|
||||||
<input type="radio" name="language" value="c">C</input>
|
<input type="radio" name="language" value="c">C</input>
|
||||||
</form>
|
</form>
|
||||||
@@ -122,6 +123,9 @@ For your chosen language, please cross-reference with:
|
|||||||
<div class="language-javascript">
|
<div class="language-javascript">
|
||||||
[samplebinary.js](https://github.com/google/flatbuffers/blob/master/samples/samplebinary.js)
|
[samplebinary.js](https://github.com/google/flatbuffers/blob/master/samples/samplebinary.js)
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
<em>none yet</em>
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
[SampleBinary.php](https://github.com/google/flatbuffers/blob/master/samples/SampleBinary.php)
|
[SampleBinary.php](https://github.com/google/flatbuffers/blob/master/samples/SampleBinary.php)
|
||||||
</div>
|
</div>
|
||||||
@@ -210,12 +214,21 @@ The `Weapon` table is a sub-table used within our FlatBuffer. It is
|
|||||||
used twice: once within the `Monster` table and once within the `Equipment`
|
used twice: once within the `Monster` table and once within the `Equipment`
|
||||||
enum. For our `Monster`, it is used to populate a `vector of tables` via the
|
enum. For our `Monster`, it is used to populate a `vector of tables` via the
|
||||||
`weapons` field within our `Monster`. It is also the only table referenced by
|
`weapons` field within our `Monster`. It is also the only table referenced by
|
||||||
the `Equipment` enum.
|
the `Equipment` union.
|
||||||
|
|
||||||
The last part of the `schema` is the `root_type`. The root type declares what
|
The last part of the `schema` is the `root_type`. The root type declares what
|
||||||
will be the root table for the serialized data. In our case, the root type is
|
will be the root table for the serialized data. In our case, the root type is
|
||||||
our `Monster` table.
|
our `Monster` table.
|
||||||
|
|
||||||
|
The scalar types can also use alias type names such as `int16` instead
|
||||||
|
of `short` and `float32` instead of `float`. Thus we could also write
|
||||||
|
the `Weapon` table as:
|
||||||
|
|
||||||
|
table Weapon {
|
||||||
|
name:string;
|
||||||
|
damage:int16;
|
||||||
|
}
|
||||||
|
|
||||||
#### More Information About Schemas
|
#### More Information About Schemas
|
||||||
|
|
||||||
You can find a complete guide to writing `schema` files in the
|
You can find a complete guide to writing `schema` files in the
|
||||||
@@ -275,7 +288,13 @@ Please be aware of the difference between `flatc` and `flatcc` tools.
|
|||||||
<div class="language-javascript">
|
<div class="language-javascript">
|
||||||
~~~{.sh}
|
~~~{.sh}
|
||||||
cd flatbuffers/sample
|
cd flatbuffers/sample
|
||||||
./../flatc --javascript samples/monster.fbs
|
./../flatc --js samples/monster.fbs
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.sh}
|
||||||
|
cd flatbuffers/sample
|
||||||
|
./../flatc --ts samples/monster.fbs
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
@@ -363,6 +382,11 @@ The first step is to import/include the library, generated files, etc.
|
|||||||
<script src="monster_generated.js"></script> // Generated by `flatc`.
|
<script src="monster_generated.js"></script> // Generated by `flatc`.
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
// note: import flabuffers with your desired import method
|
||||||
|
|
||||||
|
import { MyGame } from './monster_generated';
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
~~~{.php}
|
~~~{.php}
|
||||||
// It is recommended that your use PSR autoload when using FlatBuffers in PHP.
|
// It is recommended that your use PSR autoload when using FlatBuffers in PHP.
|
||||||
@@ -445,6 +469,13 @@ which will grow automatically if needed:
|
|||||||
var builder = new flatbuffers.Builder(1024);
|
var builder = new flatbuffers.Builder(1024);
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.ts}
|
||||||
|
// Create a `flatbuffer.Builder`, which will be used to create our
|
||||||
|
// monsters' FlatBuffers.
|
||||||
|
let builder = new flatbuffers.Builder(1024);
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
~~~{.php}
|
~~~{.php}
|
||||||
// Create a `FlatBufferBuilder`, which will be used to create our
|
// Create a `FlatBufferBuilder`, which will be used to create our
|
||||||
@@ -557,6 +588,24 @@ our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
|
|||||||
var axe = MyGame.Sample.Weapon.endWeapon(builder);
|
var axe = MyGame.Sample.Weapon.endWeapon(builder);
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.js}
|
||||||
|
let weaponOne = builder.createString('Sword');
|
||||||
|
let weaponTwo = builder.createString('Axe');
|
||||||
|
|
||||||
|
// Create the first `Weapon` ('Sword').
|
||||||
|
MyGame.Sample.Weapon.startWeapon(builder);
|
||||||
|
MyGame.Sample.Weapon.addName(builder, weaponOne);
|
||||||
|
MyGame.Sample.Weapon.addDamage(builder, 3);
|
||||||
|
let sword = MyGame.Sample.Weapon.endWeapon(builder);
|
||||||
|
|
||||||
|
// Create the second `Weapon` ('Axe').
|
||||||
|
MyGame.Sample.Weapon.startWeapon(builder);
|
||||||
|
MyGame.Sample.Weapon.addName(builder, weaponTwo);
|
||||||
|
MyGame.Sample.Weapon.addDamage(builder, 5);
|
||||||
|
let axe = MyGame.Sample.Weapon.endWeapon(builder);
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
~~~{.php}
|
~~~{.php}
|
||||||
// Create the `Weapon`s using the `createWeapon()` helper function.
|
// Create the `Weapon`s using the `createWeapon()` helper function.
|
||||||
@@ -604,7 +653,7 @@ traversal. This is generally easy to do on any tree structures.
|
|||||||
|
|
||||||
// Create a `vector` representing the inventory of the Orc. Each number
|
// Create a `vector` representing the inventory of the Orc. Each number
|
||||||
// could correspond to an item that can be claimed after he is slain.
|
// could correspond to an item that can be claimed after he is slain.
|
||||||
unsigned char treasure = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
unsigned char treasure[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||||
auto inventory = builder.CreateVector(treasure, 10);
|
auto inventory = builder.CreateVector(treasure, 10);
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
@@ -675,6 +724,17 @@ traversal. This is generally easy to do on any tree structures.
|
|||||||
var inv = MyGame.Sample.Monster.createInventoryVector(builder, treasure);
|
var inv = MyGame.Sample.Monster.createInventoryVector(builder, treasure);
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.js}
|
||||||
|
// Serialize a name for our monster, called 'Orc'.
|
||||||
|
let 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.
|
||||||
|
let treasure = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||||
|
let inv = MyGame.Sample.Monster.createInventoryVector(builder, treasure);
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
~~~{.php}
|
~~~{.php}
|
||||||
// Serialize a name for our monster, called "Orc".
|
// Serialize a name for our monster, called "Orc".
|
||||||
@@ -710,6 +770,10 @@ adding fields to our monster.
|
|||||||
other `vector`s), collect their offsets into a temporary data structure, and
|
other `vector`s), collect their offsets into a temporary data structure, and
|
||||||
then create an additional `vector` containing their offsets.*
|
then create an additional `vector` containing their offsets.*
|
||||||
|
|
||||||
|
If instead of creating a vector from an existing array you serialize elements
|
||||||
|
individually one by one, take care to note that this happens in reverse order,
|
||||||
|
as buffers are built back to front.
|
||||||
|
|
||||||
For example, take a look at the two `Weapon`s that we created earlier (`Sword`
|
For example, take a look at the two `Weapon`s that we created earlier (`Sword`
|
||||||
and `Axe`). These are both FlatBuffer `table`s, whose offsets we now store in
|
and `Axe`). These are both FlatBuffer `table`s, whose offsets we now store in
|
||||||
memory. Therefore we can create a FlatBuffer `vector` to contain these
|
memory. Therefore we can create a FlatBuffer `vector` to contain these
|
||||||
@@ -774,6 +838,14 @@ offsets.
|
|||||||
var weapons = MyGame.Sample.Monster.createWeaponsVector(builder, weaps);
|
var weapons = MyGame.Sample.Monster.createWeaponsVector(builder, weaps);
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.ts}
|
||||||
|
// Create an array from the two `Weapon`s and pass it to the
|
||||||
|
// `createWeaponsVector()` method to create a FlatBuffer vector.
|
||||||
|
let weaps = [sword, axe];
|
||||||
|
let weapons = MyGame.Sample.Monster.createWeaponsVector(builder, weaps);
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
~~~{.php}
|
~~~{.php}
|
||||||
// Create an array from the two `Weapon`s and pass it to the
|
// Create an array from the two `Weapon`s and pass it to the
|
||||||
@@ -807,7 +879,7 @@ for the `path` field above:
|
|||||||
<div class="language-cpp">
|
<div class="language-cpp">
|
||||||
~~~{.cpp}
|
~~~{.cpp}
|
||||||
Vec3 points[] = { Vec3(1.0f, 2.0f, 3.0f), Vec3(4.0f, 5.0f, 6.0f) };
|
Vec3 points[] = { Vec3(1.0f, 2.0f, 3.0f), Vec3(4.0f, 5.0f, 6.0f) };
|
||||||
auto path = fbb.CreateVectorOfStructs(points, 2);
|
auto path = builder.CreateVectorOfStructs(points, 2);
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
<div class="language-java">
|
<div class="language-java">
|
||||||
@@ -836,7 +908,7 @@ for the `path` field above:
|
|||||||
</div>
|
</div>
|
||||||
<div class="language-python">
|
<div class="language-python">
|
||||||
~~~{.py}
|
~~~{.py}
|
||||||
MyGame.Example.Monster.MonsterStartPathVector(builder, 2)
|
MyGame.Sample.Monster.MonsterStartPathVector(builder, 2)
|
||||||
MyGame.Sample.Vec3.CreateVec3(builder, 1.0, 2.0, 3.0)
|
MyGame.Sample.Vec3.CreateVec3(builder, 1.0, 2.0, 3.0)
|
||||||
MyGame.Sample.Vec3.CreateVec3(builder, 4.0, 5.0, 6.0)
|
MyGame.Sample.Vec3.CreateVec3(builder, 4.0, 5.0, 6.0)
|
||||||
path = builder.EndVector(2)
|
path = builder.EndVector(2)
|
||||||
@@ -844,12 +916,20 @@ for the `path` field above:
|
|||||||
</div>
|
</div>
|
||||||
<div class="language-javascript">
|
<div class="language-javascript">
|
||||||
~~~{.js}
|
~~~{.js}
|
||||||
MyGame.Example.Monster.startPathVector(builder, 2);
|
MyGame.Sample.Monster.startPathVector(builder, 2);
|
||||||
MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0);
|
MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0);
|
||||||
MyGame.Sample.Vec3.createVec3(builder, 4.0, 5.0, 6.0);
|
MyGame.Sample.Vec3.createVec3(builder, 4.0, 5.0, 6.0);
|
||||||
var path = builder.endVector();
|
var path = builder.endVector();
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.ts}
|
||||||
|
MyGame.Sample.Monster.startPathVector(builder, 2);
|
||||||
|
MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0);
|
||||||
|
MyGame.Sample.Vec3.createVec3(builder, 4.0, 5.0, 6.0);
|
||||||
|
let path = builder.endVector();
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
~~~{.php}
|
~~~{.php}
|
||||||
\MyGame\Example\Monster::StartPathVector($builder, 2);
|
\MyGame\Example\Monster::StartPathVector($builder, 2);
|
||||||
@@ -869,15 +949,18 @@ can serialize the monster itself:
|
|||||||
|
|
||||||
<div class="language-cpp">
|
<div class="language-cpp">
|
||||||
~~~{.cpp}
|
~~~{.cpp}
|
||||||
|
// Create the position struct
|
||||||
|
auto position = Vec3(1.0f, 2.0f, 3.0f);
|
||||||
|
|
||||||
// Set his hit points to 300 and his mana to 150.
|
// Set his hit points to 300 and his mana to 150.
|
||||||
int hp = 300;
|
int hp = 300;
|
||||||
int mana = 150;
|
int mana = 150;
|
||||||
|
|
||||||
// Finally, create the monster using the `CreateMonster` helper function
|
// Finally, create the monster using the `CreateMonster` helper function
|
||||||
// to set all fields.
|
// to set all fields.
|
||||||
auto orc = CreateMonster(builder, Vec3(1.0f, 2.0f, 3.0f), mana, hp, name,
|
auto orc = CreateMonster(builder, &position, mana, hp, name, inventory,
|
||||||
inventory, Color_Red, weapons, Equipment_Weapon,
|
Color_Red, weapons, Equipment_Weapon, axe.Union(),
|
||||||
axe.Union(), path);
|
path);
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
<div class="language-java">
|
<div class="language-java">
|
||||||
@@ -964,6 +1047,23 @@ can serialize the monster itself:
|
|||||||
var orc = MyGame.Sample.Monster.endMonster(builder);
|
var orc = MyGame.Sample.Monster.endMonster(builder);
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.ts}
|
||||||
|
// Create our monster by using `startMonster()` and `endMonster()`.
|
||||||
|
MyGame.Sample.Monster.startMonster(builder);
|
||||||
|
MyGame.Sample.Monster.addPos(builder,
|
||||||
|
MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0));
|
||||||
|
MyGame.Sample.Monster.addHp(builder, 300);
|
||||||
|
MyGame.Sample.Monster.addColor(builder, MyGame.Sample.Color.Red)
|
||||||
|
MyGame.Sample.Monster.addName(builder, name);
|
||||||
|
MyGame.Sample.Monster.addInventory(builder, inv);
|
||||||
|
MyGame.Sample.Monster.addWeapons(builder, weapons);
|
||||||
|
MyGame.Sample.Monster.addEquippedType(builder, MyGame.Sample.Equipment.Weapon);
|
||||||
|
MyGame.Sample.Monster.addEquipped(builder, axe);
|
||||||
|
MyGame.Sample.Monster.addPath(builder, path);
|
||||||
|
let orc = MyGame.Sample.Monster.endMonster(builder);
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
~~~{.php}
|
~~~{.php}
|
||||||
// Create our monster by using `StartMonster()` and `EndMonster()`.
|
// Create our monster by using `StartMonster()` and `EndMonster()`.
|
||||||
@@ -1023,14 +1123,14 @@ a bit more flexibility.
|
|||||||
// You can use this code instead of `CreateMonster()`, to create our orc
|
// You can use this code instead of `CreateMonster()`, to create our orc
|
||||||
// manually.
|
// manually.
|
||||||
MonsterBuilder monster_builder(builder);
|
MonsterBuilder monster_builder(builder);
|
||||||
monster_builder.add_pos(&pos);
|
monster_builder.add_pos(&position);
|
||||||
monster_builder.add_hp(hp);
|
monster_builder.add_hp(hp);
|
||||||
monster_builder.add_name(name);
|
monster_builder.add_name(name);
|
||||||
monster_builder.add_inventory(inventory);
|
monster_builder.add_inventory(inventory);
|
||||||
monster_builder.add_color(Color_Red);
|
monster_builder.add_color(Color_Red);
|
||||||
monster_builder.add_weapons(weapons);
|
monster_builder.add_weapons(weapons);
|
||||||
monster_builder.add_equipped_type(Equipment_Weapon);
|
monster_builder.add_equipped_type(Equipment_Weapon);
|
||||||
monster_builder.add_equpped(axe);
|
monster_builder.add_equipped(axe.Union());
|
||||||
auto orc = monster_builder.Finish();
|
auto orc = monster_builder.Finish();
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
@@ -1108,6 +1208,12 @@ Here is a repetition these lines, to help highlight them more clearly:
|
|||||||
MyGame.Sample.Monster.addEquipped(builder, axe); // Union data
|
MyGame.Sample.Monster.addEquipped(builder, axe); // Union data
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.ts}
|
||||||
|
MyGame.Sample.Monster.addEquippedType(builder, MyGame.Sample.Equipment.Weapon); // Union type
|
||||||
|
MyGame.Sample.Monster.addEquipped(builder, axe); // Union data
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
~~~{.php}
|
~~~{.php}
|
||||||
\MyGame\Sample\Monster::AddEquippedType($builder, \MyGame\Sample\Equipment::Weapon); // Union type
|
\MyGame\Sample\Monster::AddEquippedType($builder, \MyGame\Sample\Equipment::Weapon); // Union type
|
||||||
@@ -1162,7 +1268,14 @@ appropriate `finish` method.
|
|||||||
<div class="language-javascript">
|
<div class="language-javascript">
|
||||||
~~~{.js}
|
~~~{.js}
|
||||||
// Call `finish()` to instruct the builder that this monster is complete.
|
// Call `finish()` to instruct the builder that this monster is complete.
|
||||||
builder.finish(orc); // You could also call `MyGame.Example.Monster.finishMonsterBuffer(builder,
|
builder.finish(orc); // You could also call `MyGame.Sample.Monster.finishMonsterBuffer(builder,
|
||||||
|
// orc);`.
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.ts}
|
||||||
|
// Call `finish()` to instruct the builder that this monster is complete.
|
||||||
|
builder.finish(orc); // You could also call `MyGame.Sample.Monster.finishMonsterBuffer(builder,
|
||||||
// orc);`.
|
// orc);`.
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
@@ -1232,6 +1345,12 @@ like so:
|
|||||||
var buf = builder.asUint8Array(); // Of type `Uint8Array`.
|
var buf = builder.asUint8Array(); // Of type `Uint8Array`.
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.ts}
|
||||||
|
// This must be called after `finish()`.
|
||||||
|
let buf = builder.asUint8Array(); // Of type `Uint8Array`.
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
~~~{.php}
|
~~~{.php}
|
||||||
// This must be called after `finish()`.
|
// This must be called after `finish()`.
|
||||||
@@ -1333,6 +1452,13 @@ before:
|
|||||||
<script src="monster_generated.js"></script> // Generated by `flatc`.
|
<script src="monster_generated.js"></script> // Generated by `flatc`.
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.js}
|
||||||
|
// note: import flabuffers with your desired import method
|
||||||
|
|
||||||
|
import { MyGame } from './monster_generated';
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
~~~{.php}
|
~~~{.php}
|
||||||
// It is recommended that your use PSR autoload when using FlatBuffers in PHP.
|
// It is recommended that your use PSR autoload when using FlatBuffers in PHP.
|
||||||
@@ -1380,6 +1506,8 @@ won't work**
|
|||||||
|
|
||||||
// `monster` is of type `Monster *`.
|
// `monster` is of type `Monster *`.
|
||||||
// Note: root object pointers are NOT the same as `buffer_pointer`.
|
// Note: root object pointers are NOT the same as `buffer_pointer`.
|
||||||
|
// `GetMonster` is a convenience function that calls `GetRoot<Monster>`,
|
||||||
|
// the latter is also available for non-root types.
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
<div class="language-java">
|
<div class="language-java">
|
||||||
@@ -1435,6 +1563,15 @@ won't work**
|
|||||||
var monster = MyGame.Sample.Monster.getRootAsMonster(buf);
|
var monster = MyGame.Sample.Monster.getRootAsMonster(buf);
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.ts}
|
||||||
|
let bytes = /* the data you just read, in an object of type "Uint8Array" */
|
||||||
|
let buf = new flatbuffers.ByteBuffer(bytes);
|
||||||
|
|
||||||
|
// Get an accessor to the root object inside the buffer.
|
||||||
|
let monster = MyGame.Sample.Monster.getRootAsMonster(buf);
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
~~~{.php}
|
~~~{.php}
|
||||||
$bytes = /* the data you just read, in a string */
|
$bytes = /* the data you just read, in a string */
|
||||||
@@ -1502,6 +1639,13 @@ accessors for all non-`deprecated` fields. For example:
|
|||||||
var name = $monster.name();
|
var name = $monster.name();
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.ts}
|
||||||
|
let hp = $monster.hp();
|
||||||
|
let mana = $monster.mana();
|
||||||
|
let name = $monster.name();
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
~~~{.php}
|
~~~{.php}
|
||||||
$hp = $monster->getHp();
|
$hp = $monster->getHp();
|
||||||
@@ -1577,6 +1721,14 @@ To access sub-objects, in the case of our `pos`, which is a `Vec3`:
|
|||||||
var z = pos.z();
|
var z = pos.z();
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.ts}
|
||||||
|
let pos = monster.pos();
|
||||||
|
let x = pos.x();
|
||||||
|
let y = pos.y();
|
||||||
|
let z = pos.z();
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
~~~{.php}
|
~~~{.php}
|
||||||
$pos = $monster->getPos();
|
$pos = $monster->getPos();
|
||||||
@@ -1639,6 +1791,12 @@ FlatBuffers `vector`.
|
|||||||
var thirdItem = monster.inventory(2);
|
var thirdItem = monster.inventory(2);
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.ts}
|
||||||
|
let invLength = monster.inventoryLength();
|
||||||
|
let thirdItem = monster.inventory(2);
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
~~~{.php}
|
~~~{.php}
|
||||||
$inv_len = $monster->getInventoryLength();
|
$inv_len = $monster->getInventoryLength();
|
||||||
@@ -1704,6 +1862,13 @@ except your need to handle the result as a FlatBuffer `table`:
|
|||||||
var secondWeaponDamage = monster.weapons(1).damage();
|
var secondWeaponDamage = monster.weapons(1).damage();
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.ts}
|
||||||
|
let weaponsLength = monster.weaponsLength();
|
||||||
|
let secondWeaponName = monster.weapons(1).name();
|
||||||
|
let secondWeaponDamage = monster.weapons(1).damage();
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
~~~{.php}
|
~~~{.php}
|
||||||
$weapons_len = $monster->getWeaponsLength();
|
$weapons_len = $monster->getWeaponsLength();
|
||||||
@@ -1811,6 +1976,16 @@ We can access the type to dynamically cast the data as needed (since the
|
|||||||
}
|
}
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.ts}
|
||||||
|
let unionType = monster.equippedType();
|
||||||
|
|
||||||
|
if (unionType == MyGame.Sample.Equipment.Weapon) {
|
||||||
|
let weapon_name = monster.equipped(new MyGame.Sample.Weapon()).name(); // 'Axe'
|
||||||
|
let weapon_damage = monster.equipped(new MyGame.Sample.Weapon()).damage(); // 5
|
||||||
|
}
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
~~~{.php}
|
~~~{.php}
|
||||||
$union_type = $monster->getEquippedType();
|
$union_type = $monster->getEquippedType();
|
||||||
@@ -1889,7 +2064,12 @@ mutators like so:
|
|||||||
</div>
|
</div>
|
||||||
<div class="language-javascript">
|
<div class="language-javascript">
|
||||||
~~~{.js}
|
~~~{.js}
|
||||||
<API for mutating FlatBuffers is not yet support in JavaScript.>
|
<API for mutating FlatBuffers is not yet supported in JavaScript.>
|
||||||
|
~~~
|
||||||
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
~~~{.ts}
|
||||||
|
<API for mutating FlatBuffers is not yet supported in TypeScript.>
|
||||||
~~~
|
~~~
|
||||||
</div>
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
@@ -2003,6 +2183,9 @@ For your chosen language, see:
|
|||||||
<div class="language-javascript">
|
<div class="language-javascript">
|
||||||
[Use in JavaScript](@ref flatbuffers_guide_use_javascript)
|
[Use in JavaScript](@ref flatbuffers_guide_use_javascript)
|
||||||
</div>
|
</div>
|
||||||
|
<div class="language-typescript">
|
||||||
|
[Use in TypeScript](@ref flatbuffers_guide_use_typescript)
|
||||||
|
</div>
|
||||||
<div class="language-php">
|
<div class="language-php">
|
||||||
[Use in PHP](@ref flatbuffers_guide_use_php)
|
[Use in PHP](@ref flatbuffers_guide_use_php)
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
66
docs/source/TypeScriptUsage.md
Normal file
66
docs/source/TypeScriptUsage.md
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
Use in TypeScript {#flatbuffers_guide_use_typescript}
|
||||||
|
=================
|
||||||
|
|
||||||
|
## Before you get started
|
||||||
|
|
||||||
|
Before diving into the FlatBuffers usage in TypeScript, 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 TypeScript). This page is specifically designed to cover the nuances
|
||||||
|
of FlatBuffers usage in TypeScript.
|
||||||
|
|
||||||
|
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 TypeScript library code location
|
||||||
|
|
||||||
|
The code for the FlatBuffers TypeScript library can be found at
|
||||||
|
`flatbuffers/js` with typings available at @types/flatubffers.
|
||||||
|
|
||||||
|
## Testing the FlatBuffers TypeScript library
|
||||||
|
|
||||||
|
To run the tests, use the [TypeScriptTest.sh](https://github.com/google/
|
||||||
|
flatbuffers/blob/master/tests/TypeScriptTest.sh) shell script.
|
||||||
|
|
||||||
|
*Note: The TypeScript test file requires [Node.js](https://nodejs.org/en/).*
|
||||||
|
|
||||||
|
## Using the FlatBuffers TypeScript libary
|
||||||
|
|
||||||
|
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||||
|
example of how to use FlatBuffers in TypeScript.*
|
||||||
|
|
||||||
|
FlatBuffers supports both reading and writing FlatBuffers in TypeScript.
|
||||||
|
|
||||||
|
To use FlatBuffers in your own code, first generate TypeScript classes from your
|
||||||
|
schema with the `--ts` 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 TypeScript:
|
||||||
|
First, include the library and generated code. Then read the file into an
|
||||||
|
`Uint8Array`. Make a `flatbuffers.ByteBuffer` out of the `Uint8Array`, and pass
|
||||||
|
the ByteBuffer to the `getRootAsMonster` function.
|
||||||
|
|
||||||
|
~~~{.ts}
|
||||||
|
// note: import flabuffers with your desired import method
|
||||||
|
|
||||||
|
import { MyGame } from './monster_generated';
|
||||||
|
|
||||||
|
let data = new Uint8Array(fs.readFileSync('monster.dat'));
|
||||||
|
let buf = new flatbuffers.ByteBuffer(data);
|
||||||
|
|
||||||
|
let monster = MyGame.Example.Monster.getRootAsMonster(buf);
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Now you can access values like this:
|
||||||
|
|
||||||
|
~~~{.ts}
|
||||||
|
let hp = monster.hp();
|
||||||
|
let pos = monster.pos();
|
||||||
|
~~~
|
||||||
|
|
||||||
|
## Text parsing FlatBuffers in TypeScript
|
||||||
|
|
||||||
|
There currently is no support for parsing text (Schema's and JSON) directly
|
||||||
|
from TypeScript.
|
||||||
0
docs/source/WhitePaper.md
Executable file → Normal file
0
docs/source/WhitePaper.md
Executable file → Normal file
0
docs/source/doxyfile
Executable file → Normal file
0
docs/source/doxyfile
Executable file → Normal file
@@ -33,6 +33,8 @@
|
|||||||
title="Use in Java/C#"/>
|
title="Use in Java/C#"/>
|
||||||
<tab type="user" url="@ref flatbuffers_guide_use_javascript"
|
<tab type="user" url="@ref flatbuffers_guide_use_javascript"
|
||||||
title="Use in JavaScript"/>
|
title="Use in JavaScript"/>
|
||||||
|
<tab type="user" url="@ref flatbuffers_guide_use_typescript"
|
||||||
|
title="Use in TypeScript"/>
|
||||||
<tab type="user" url="@ref flatbuffers_guide_use_php"
|
<tab type="user" url="@ref flatbuffers_guide_use_php"
|
||||||
title="Use in PHP"/>
|
title="Use in PHP"/>
|
||||||
<tab type="user" url="@ref flatbuffers_guide_use_python"
|
<tab type="user" url="@ref flatbuffers_guide_use_python"
|
||||||
|
|||||||
@@ -13,6 +13,9 @@
|
|||||||
/// @defgroup flatbuffers_javascript_api JavaScript API
|
/// @defgroup flatbuffers_javascript_api JavaScript API
|
||||||
/// @brief FlatBuffers API for JavaScript
|
/// @brief FlatBuffers API for JavaScript
|
||||||
|
|
||||||
|
/// @defgroup flatbuffers_typescript_api TypeScript API
|
||||||
|
/// @brief FlatBuffers API for TypeScript
|
||||||
|
|
||||||
/// @defgroup flatbuffers_php_api PHP API
|
/// @defgroup flatbuffers_php_api PHP API
|
||||||
/// @brief FlatBuffers API for PHP
|
/// @brief FlatBuffers API for PHP
|
||||||
|
|
||||||
|
|||||||
17
go/BUILD.bazel
Normal file
17
go/BUILD.bazel
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||||
|
|
||||||
|
go_library(
|
||||||
|
name = "go",
|
||||||
|
srcs = [
|
||||||
|
"builder.go",
|
||||||
|
"doc.go",
|
||||||
|
"encode.go",
|
||||||
|
"grpc.go",
|
||||||
|
"lib.go",
|
||||||
|
"sizes.go",
|
||||||
|
"struct.go",
|
||||||
|
"table.go",
|
||||||
|
],
|
||||||
|
importpath = "github.com/google/flatbuffers/go",
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
||||||
@@ -110,6 +110,11 @@ func (b *Builder) WriteVtable() (n UOffsetT) {
|
|||||||
objectOffset := b.Offset()
|
objectOffset := b.Offset()
|
||||||
existingVtable := UOffsetT(0)
|
existingVtable := UOffsetT(0)
|
||||||
|
|
||||||
|
// Trim vtable of trailing zeroes.
|
||||||
|
i := len(b.vtable) - 1;
|
||||||
|
for ; i >= 0 && b.vtable[i] == 0; i-- {}
|
||||||
|
b.vtable = b.vtable[:i + 1];
|
||||||
|
|
||||||
// Search backwards through existing vtables, because similar vtables
|
// Search backwards through existing vtables, because similar vtables
|
||||||
// are likely to have been recently appended. See
|
// are likely to have been recently appended. See
|
||||||
// BenchmarkVtableDeduplication for a case in which this heuristic
|
// BenchmarkVtableDeduplication for a case in which this heuristic
|
||||||
|
|||||||
42
grpc/flatbuffers-java-grpc/pom.xml
Normal file
42
grpc/flatbuffers-java-grpc/pom.xml
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.google.flatbuffers</groupId>
|
||||||
|
<artifactId>flatbuffers-parent</artifactId>
|
||||||
|
<version>1.8.0</version>
|
||||||
|
</parent>
|
||||||
|
<artifactId>flatbuffers-java-grpc</artifactId>
|
||||||
|
<name>${project.artifactId}</name>
|
||||||
|
<packaging>bundle</packaging>
|
||||||
|
<description>
|
||||||
|
Utilities supporting generated code for GRPC
|
||||||
|
</description>
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<name>Wouter van Oortmerssen</name>
|
||||||
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<name>Yuri Finkelstein</name>
|
||||||
|
<url>https://github.com/yfinkelstein</url>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
<properties>
|
||||||
|
<gRPC.version>1.8.0</gRPC.version>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.flatbuffers</groupId>
|
||||||
|
<artifactId>flatbuffers-java</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.grpc</groupId>
|
||||||
|
<artifactId>grpc-core</artifactId>
|
||||||
|
<version>${gRPC.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</project>
|
||||||
|
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
* 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.grpc;
|
||||||
|
|
||||||
|
import com.google.flatbuffers.Table;
|
||||||
|
import io.grpc.Drainable;
|
||||||
|
import io.grpc.KnownLength;
|
||||||
|
import io.grpc.MethodDescriptor;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class FlatbuffersUtils {
|
||||||
|
abstract public static class FBExtactor <T extends Table> {
|
||||||
|
T extract (InputStream stream) throws IOException {
|
||||||
|
if (stream instanceof KnownLength) {
|
||||||
|
int size = stream.available();
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(size);
|
||||||
|
stream.read(buffer.array());
|
||||||
|
return extract(buffer);
|
||||||
|
} else
|
||||||
|
throw new RuntimeException("The class " + stream.getClass().getCanonicalName() + " does not extend from KnownLength ");
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract T extract(ByteBuffer buffer);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static class FBInputStream extends InputStream implements Drainable, KnownLength {
|
||||||
|
private final ByteBuffer buffer;
|
||||||
|
private final int size;
|
||||||
|
@Nullable private ByteArrayInputStream inputStream;
|
||||||
|
|
||||||
|
FBInputStream(ByteBuffer buffer) {
|
||||||
|
this.buffer = buffer;
|
||||||
|
this.size = buffer.remaining();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void makeStreamIfNotAlready() {
|
||||||
|
if (inputStream == null)
|
||||||
|
inputStream = new ByteArrayInputStream(buffer.array(), buffer.position(), size);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int drainTo(OutputStream target) throws IOException {
|
||||||
|
target.write(buffer.array(), buffer.position(), size);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
makeStreamIfNotAlready();
|
||||||
|
return inputStream.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(byte[] b, int off, int len) throws IOException {
|
||||||
|
makeStreamIfNotAlready();
|
||||||
|
if (inputStream == null) {
|
||||||
|
if (len >= size) {
|
||||||
|
System.arraycopy(buffer.array(), buffer.position(), b, off, size);
|
||||||
|
return size;
|
||||||
|
} else {
|
||||||
|
makeStreamIfNotAlready();
|
||||||
|
return inputStream.read(b, off, len);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
return inputStream.read(b, off, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int available() throws IOException {
|
||||||
|
return inputStream == null ? size : inputStream.available();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T extends Table> MethodDescriptor.Marshaller<T> marshaller(final Class<T> clazz, final FBExtactor<T> extractor) {
|
||||||
|
return new MethodDescriptor.ReflectableMarshaller<T>() {
|
||||||
|
@Override
|
||||||
|
public Class<T> getMessageClass() {
|
||||||
|
return clazz;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream stream(T value) {
|
||||||
|
return new FBInputStream (value.getByteBuffer());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public T parse(InputStream stream) {
|
||||||
|
try {
|
||||||
|
return extractor.extract(stream);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
213
grpc/pom.xml
Normal file
213
grpc/pom.xml
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>com.google.flatbuffers</groupId>
|
||||||
|
<artifactId>flatbuffers-parent</artifactId>
|
||||||
|
<packaging>pom</packaging>
|
||||||
|
<version>1.8.0</version>
|
||||||
|
<name>flatbuffers-parent</name>
|
||||||
|
<description>parent pom for flatbuffers java artifacts</description>
|
||||||
|
<properties>
|
||||||
|
<scm.url>https://github.com/google/flatbuffers</scm.url>
|
||||||
|
<scm.connection>scm:git:${scm.url}.git</scm.connection>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<licenses>
|
||||||
|
<license>
|
||||||
|
<name>The Apache Software License, Version 2.0</name>
|
||||||
|
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
|
||||||
|
<distribution>repo</distribution>
|
||||||
|
</license>
|
||||||
|
</licenses>
|
||||||
|
|
||||||
|
<issueManagement>
|
||||||
|
<system>GitHub</system>
|
||||||
|
<url>https://github.com/google/flatbuffers/issues</url>
|
||||||
|
</issueManagement>
|
||||||
|
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<name>Wouter van Oortmerssen</name>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
|
||||||
|
<url>${scm.url}</url>
|
||||||
|
|
||||||
|
<scm>
|
||||||
|
<connection>${scm.connection}</connection>
|
||||||
|
<developerConnection>${scm.connection}</developerConnection>
|
||||||
|
<url>${scm.url}</url>
|
||||||
|
<tag>HEAD</tag>
|
||||||
|
</scm>
|
||||||
|
|
||||||
|
<distributionManagement>
|
||||||
|
<snapshotRepository>
|
||||||
|
<id>ossrh</id>
|
||||||
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
|
</snapshotRepository>
|
||||||
|
</distributionManagement>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.12</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<extensions>
|
||||||
|
<extension>
|
||||||
|
<!--
|
||||||
|
os-maven-plugin is a Maven extension/plugin that generates various useful platform-dependent
|
||||||
|
project properties normalized from ${os.detected.name} and ${os.detected.arch}.
|
||||||
|
-->
|
||||||
|
<groupId>kr.motd.maven</groupId>
|
||||||
|
<artifactId>os-maven-plugin</artifactId>
|
||||||
|
<version>1.5.0.Final</version>
|
||||||
|
</extension>
|
||||||
|
</extensions>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>3.6.1</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-jar-plugin</artifactId>
|
||||||
|
<version>3.0.2</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>3.0.1</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>2.19.1</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<version>2.10.4</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>build-helper-maven-plugin</artifactId>
|
||||||
|
<version>1.12</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-dependency-plugin</artifactId>
|
||||||
|
<version>2.8</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
|
<version>2.7</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-gpg-plugin</artifactId>
|
||||||
|
<version>1.5</version>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-release-plugin</artifactId>
|
||||||
|
<version>2.5.3</version>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>exec-maven-plugin</artifactId>
|
||||||
|
<version>1.5.0</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>1.6</source>
|
||||||
|
<target>1.6</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<includes>
|
||||||
|
<include>**/*Test.java</include>
|
||||||
|
</includes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-sources</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-javadoc-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-javadocs</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
<version>3.0.1</version>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.sonatype.plugins</groupId>
|
||||||
|
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||||
|
<version>1.6.7</version>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<configuration>
|
||||||
|
<serverId>ossrh</serverId>
|
||||||
|
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
|
||||||
|
<autoReleaseAfterClose>true</autoReleaseAfterClose>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-gpg-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>sign-artifacts</id>
|
||||||
|
<phase>verify</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>sign</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-release-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||||
|
<useReleaseProfile>false</useReleaseProfile>
|
||||||
|
<releaseProfiles>release</releaseProfiles>
|
||||||
|
<goals>deploy</goals>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<modules>
|
||||||
|
<!-- consider the benefits of publishing all maven artifacts in this project
|
||||||
|
|
||||||
|
<module>flatbuffers-compiler</module>
|
||||||
|
<module>flatbuffers-java</module>
|
||||||
|
|
||||||
|
-->
|
||||||
|
<module>flatbuffers-java-grpc</module>
|
||||||
|
</modules>
|
||||||
|
|
||||||
|
</project>
|
||||||
@@ -34,6 +34,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "src/compiler/cpp_generator.h"
|
#include "src/compiler/cpp_generator.h"
|
||||||
|
#include "flatbuffers/util.h"
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
@@ -127,8 +128,8 @@ grpc::string GetHeaderPrologue(grpc_generator::File *file,
|
|||||||
printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
|
printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
|
||||||
printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
|
printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
|
||||||
printer->Print(vars, "\n");
|
printer->Print(vars, "\n");
|
||||||
printer->Print(vars, file->additional_headers().c_str());
|
|
||||||
printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
|
printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
|
||||||
|
printer->Print(vars, file->additional_headers().c_str());
|
||||||
printer->Print(vars, "\n");
|
printer->Print(vars, "\n");
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
@@ -158,7 +159,6 @@ grpc::string GetHeaderIncludes(grpc_generator::File *file,
|
|||||||
printer->Print(vars, "namespace grpc {\n");
|
printer->Print(vars, "namespace grpc {\n");
|
||||||
printer->Print(vars, "class CompletionQueue;\n");
|
printer->Print(vars, "class CompletionQueue;\n");
|
||||||
printer->Print(vars, "class Channel;\n");
|
printer->Print(vars, "class Channel;\n");
|
||||||
printer->Print(vars, "class RpcService;\n");
|
|
||||||
printer->Print(vars, "class ServerCompletionQueue;\n");
|
printer->Print(vars, "class ServerCompletionQueue;\n");
|
||||||
printer->Print(vars, "class ServerContext;\n");
|
printer->Print(vars, "class ServerContext;\n");
|
||||||
printer->Print(vars, "} // namespace grpc\n\n");
|
printer->Print(vars, "} // namespace grpc\n\n");
|
||||||
@@ -183,25 +183,38 @@ void PrintHeaderClientMethodInterfaces(
|
|||||||
(*vars)["Request"] = method->input_type_name();
|
(*vars)["Request"] = method->input_type_name();
|
||||||
(*vars)["Response"] = method->output_type_name();
|
(*vars)["Response"] = method->output_type_name();
|
||||||
|
|
||||||
|
struct {
|
||||||
|
grpc::string prefix;
|
||||||
|
grpc::string method_params; // extra arguments to method
|
||||||
|
grpc::string raw_args; // extra arguments to raw version of method
|
||||||
|
} async_prefixes[] = {{"Async", ", void* tag", ", tag"},
|
||||||
|
{"PrepareAsync", "", ""}};
|
||||||
|
|
||||||
if (is_public) {
|
if (is_public) {
|
||||||
if (method->NoStreaming()) {
|
if (method->NoStreaming()) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
"virtual ::grpc::Status $Method$(::grpc::ClientContext* context, "
|
"virtual ::grpc::Status $Method$(::grpc::ClientContext* context, "
|
||||||
"const $Request$& request, $Response$* response) = 0;\n");
|
"const $Request$& request, $Response$* response) = 0;\n");
|
||||||
printer->Print(*vars,
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
"std::unique_ptr< "
|
auto& async_prefix = async_prefixes[i];
|
||||||
"::grpc::ClientAsyncResponseReaderInterface< $Response$>> "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"Async$Method$(::grpc::ClientContext* context, "
|
printer->Print(
|
||||||
"const $Request$& request, "
|
*vars,
|
||||||
"::grpc::CompletionQueue* cq) {\n");
|
"std::unique_ptr< "
|
||||||
printer->Indent();
|
"::grpc::ClientAsyncResponseReaderInterface< $Response$>> "
|
||||||
printer->Print(*vars,
|
"$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
|
||||||
"return std::unique_ptr< "
|
"const $Request$& request, "
|
||||||
"::grpc::ClientAsyncResponseReaderInterface< $Response$>>("
|
"::grpc::CompletionQueue* cq) {\n");
|
||||||
"Async$Method$Raw(context, request, cq));\n");
|
printer->Indent();
|
||||||
printer->Outdent();
|
printer->Print(
|
||||||
printer->Print("}\n");
|
*vars,
|
||||||
|
"return std::unique_ptr< "
|
||||||
|
"::grpc::ClientAsyncResponseReaderInterface< $Response$>>("
|
||||||
|
"$AsyncPrefix$$Method$Raw(context, request, cq));\n");
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
} else if (ClientOnlyStreaming(method)) {
|
} else if (ClientOnlyStreaming(method)) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
@@ -215,19 +228,27 @@ void PrintHeaderClientMethodInterfaces(
|
|||||||
"($Method$Raw(context, response));\n");
|
"($Method$Raw(context, response));\n");
|
||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
printer->Print("}\n");
|
printer->Print("}\n");
|
||||||
printer->Print(
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
*vars,
|
auto& async_prefix = async_prefixes[i];
|
||||||
"std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>"
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
" Async$Method$(::grpc::ClientContext* context, $Response$* "
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
"response, "
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
||||||
"::grpc::CompletionQueue* cq, void* tag) {\n");
|
printer->Print(
|
||||||
printer->Indent();
|
*vars,
|
||||||
printer->Print(*vars,
|
"std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>"
|
||||||
"return std::unique_ptr< "
|
" $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
|
||||||
"::grpc::ClientAsyncWriterInterface< $Request$>>("
|
"$Response$* "
|
||||||
"Async$Method$Raw(context, response, cq, tag));\n");
|
"response, "
|
||||||
printer->Outdent();
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
||||||
printer->Print("}\n");
|
printer->Indent();
|
||||||
|
printer->Print(*vars,
|
||||||
|
"return std::unique_ptr< "
|
||||||
|
"::grpc::ClientAsyncWriterInterface< $Request$>>("
|
||||||
|
"$AsyncPrefix$$Method$Raw(context, response, "
|
||||||
|
"cq$AsyncRawArgs$));\n");
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
} else if (ServerOnlyStreaming(method)) {
|
} else if (ServerOnlyStreaming(method)) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
@@ -241,19 +262,26 @@ void PrintHeaderClientMethodInterfaces(
|
|||||||
"($Method$Raw(context, request));\n");
|
"($Method$Raw(context, request));\n");
|
||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
printer->Print("}\n");
|
printer->Print("}\n");
|
||||||
printer->Print(
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
*vars,
|
auto& async_prefix = async_prefixes[i];
|
||||||
"std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"Async$Method$("
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
"::grpc::ClientContext* context, const $Request$& request, "
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
||||||
"::grpc::CompletionQueue* cq, void* tag) {\n");
|
printer->Print(
|
||||||
printer->Indent();
|
*vars,
|
||||||
printer->Print(*vars,
|
"std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> "
|
||||||
"return std::unique_ptr< "
|
"$AsyncPrefix$$Method$("
|
||||||
"::grpc::ClientAsyncReaderInterface< $Response$>>("
|
"::grpc::ClientContext* context, const $Request$& request, "
|
||||||
"Async$Method$Raw(context, request, cq, tag));\n");
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
||||||
printer->Outdent();
|
printer->Indent();
|
||||||
printer->Print("}\n");
|
printer->Print(
|
||||||
|
*vars,
|
||||||
|
"return std::unique_ptr< "
|
||||||
|
"::grpc::ClientAsyncReaderInterface< $Response$>>("
|
||||||
|
"$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
} else if (method->BidiStreaming()) {
|
} else if (method->BidiStreaming()) {
|
||||||
printer->Print(*vars,
|
printer->Print(*vars,
|
||||||
"std::unique_ptr< ::grpc::ClientReaderWriterInterface< "
|
"std::unique_ptr< ::grpc::ClientReaderWriterInterface< "
|
||||||
@@ -267,61 +295,89 @@ void PrintHeaderClientMethodInterfaces(
|
|||||||
"$Method$Raw(context));\n");
|
"$Method$Raw(context));\n");
|
||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
printer->Print("}\n");
|
printer->Print("}\n");
|
||||||
printer->Print(
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
*vars,
|
auto& async_prefix = async_prefixes[i];
|
||||||
"std::unique_ptr< "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> "
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
"Async$Method$(::grpc::ClientContext* context, "
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
||||||
"::grpc::CompletionQueue* cq, void* tag) {\n");
|
printer->Print(
|
||||||
printer->Indent();
|
*vars,
|
||||||
printer->Print(
|
"std::unique_ptr< "
|
||||||
*vars,
|
"::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> "
|
||||||
"return std::unique_ptr< "
|
"$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
|
||||||
"::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>("
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
||||||
"Async$Method$Raw(context, cq, tag));\n");
|
printer->Indent();
|
||||||
printer->Outdent();
|
printer->Print(
|
||||||
printer->Print("}\n");
|
*vars,
|
||||||
|
"return std::unique_ptr< "
|
||||||
|
"::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>("
|
||||||
|
"$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (method->NoStreaming()) {
|
if (method->NoStreaming()) {
|
||||||
printer->Print(
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
*vars,
|
auto& async_prefix = async_prefixes[i];
|
||||||
"virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"Async$Method$Raw(::grpc::ClientContext* context, "
|
printer->Print(
|
||||||
"const $Request$& request, "
|
*vars,
|
||||||
"::grpc::CompletionQueue* cq) = 0;\n");
|
"virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
|
||||||
|
"$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
|
||||||
|
"const $Request$& request, "
|
||||||
|
"::grpc::CompletionQueue* cq) = 0;\n");
|
||||||
|
}
|
||||||
} else if (ClientOnlyStreaming(method)) {
|
} else if (ClientOnlyStreaming(method)) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
"virtual ::grpc::ClientWriterInterface< $Request$>*"
|
"virtual ::grpc::ClientWriterInterface< $Request$>*"
|
||||||
" $Method$Raw("
|
" $Method$Raw("
|
||||||
"::grpc::ClientContext* context, $Response$* response) = 0;\n");
|
"::grpc::ClientContext* context, $Response$* response) = 0;\n");
|
||||||
printer->Print(*vars,
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
"virtual ::grpc::ClientAsyncWriterInterface< $Request$>*"
|
auto& async_prefix = async_prefixes[i];
|
||||||
" Async$Method$Raw(::grpc::ClientContext* context, "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"$Response$* response, "
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
"::grpc::CompletionQueue* cq, void* tag) = 0;\n");
|
printer->Print(
|
||||||
|
*vars,
|
||||||
|
"virtual ::grpc::ClientAsyncWriterInterface< $Request$>*"
|
||||||
|
" $AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
|
||||||
|
"$Response$* response, "
|
||||||
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
|
||||||
|
}
|
||||||
} else if (ServerOnlyStreaming(method)) {
|
} else if (ServerOnlyStreaming(method)) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
"virtual ::grpc::ClientReaderInterface< $Response$>* $Method$Raw("
|
"virtual ::grpc::ClientReaderInterface< $Response$>* "
|
||||||
|
"$Method$Raw("
|
||||||
"::grpc::ClientContext* context, const $Request$& request) = 0;\n");
|
"::grpc::ClientContext* context, const $Request$& request) = 0;\n");
|
||||||
printer->Print(
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
*vars,
|
auto& async_prefix = async_prefixes[i];
|
||||||
"virtual ::grpc::ClientAsyncReaderInterface< $Response$>* "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"Async$Method$Raw("
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
"::grpc::ClientContext* context, const $Request$& request, "
|
printer->Print(
|
||||||
"::grpc::CompletionQueue* cq, void* tag) = 0;\n");
|
*vars,
|
||||||
|
"virtual ::grpc::ClientAsyncReaderInterface< $Response$>* "
|
||||||
|
"$AsyncPrefix$$Method$Raw("
|
||||||
|
"::grpc::ClientContext* context, const $Request$& request, "
|
||||||
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
|
||||||
|
}
|
||||||
} else if (method->BidiStreaming()) {
|
} else if (method->BidiStreaming()) {
|
||||||
printer->Print(*vars,
|
printer->Print(*vars,
|
||||||
"virtual ::grpc::ClientReaderWriterInterface< $Request$, "
|
"virtual ::grpc::ClientReaderWriterInterface< $Request$, "
|
||||||
"$Response$>* "
|
"$Response$>* "
|
||||||
"$Method$Raw(::grpc::ClientContext* context) = 0;\n");
|
"$Method$Raw(::grpc::ClientContext* context) = 0;\n");
|
||||||
printer->Print(*vars,
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
"virtual ::grpc::ClientAsyncReaderWriterInterface< "
|
auto& async_prefix = async_prefixes[i];
|
||||||
"$Request$, $Response$>* "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"Async$Method$Raw(::grpc::ClientContext* context, "
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
"::grpc::CompletionQueue* cq, void* tag) = 0;\n");
|
printer->Print(
|
||||||
|
*vars,
|
||||||
|
"virtual ::grpc::ClientAsyncReaderWriterInterface< "
|
||||||
|
"$Request$, $Response$>* "
|
||||||
|
"$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
|
||||||
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -333,25 +389,36 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
|
|||||||
(*vars)["Method"] = method->name();
|
(*vars)["Method"] = method->name();
|
||||||
(*vars)["Request"] = method->input_type_name();
|
(*vars)["Request"] = method->input_type_name();
|
||||||
(*vars)["Response"] = method->output_type_name();
|
(*vars)["Response"] = method->output_type_name();
|
||||||
|
struct {
|
||||||
|
grpc::string prefix;
|
||||||
|
grpc::string method_params; // extra arguments to method
|
||||||
|
grpc::string raw_args; // extra arguments to raw version of method
|
||||||
|
} async_prefixes[] = {{"Async", ", void* tag", ", tag"},
|
||||||
|
{"PrepareAsync", "", ""}};
|
||||||
|
|
||||||
if (is_public) {
|
if (is_public) {
|
||||||
if (method->NoStreaming()) {
|
if (method->NoStreaming()) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
"::grpc::Status $Method$(::grpc::ClientContext* context, "
|
"::grpc::Status $Method$(::grpc::ClientContext* context, "
|
||||||
"const $Request$& request, $Response$* response) override;\n");
|
"const $Request$& request, $Response$* response) override;\n");
|
||||||
printer->Print(
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
*vars,
|
auto& async_prefix = async_prefixes[i];
|
||||||
"std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"Async$Method$(::grpc::ClientContext* context, "
|
printer->Print(
|
||||||
"const $Request$& request, "
|
*vars,
|
||||||
"::grpc::CompletionQueue* cq) {\n");
|
"std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> "
|
||||||
printer->Indent();
|
"$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
|
||||||
printer->Print(*vars,
|
"const $Request$& request, "
|
||||||
"return std::unique_ptr< "
|
"::grpc::CompletionQueue* cq) {\n");
|
||||||
"::grpc::ClientAsyncResponseReader< $Response$>>("
|
printer->Indent();
|
||||||
"Async$Method$Raw(context, request, cq));\n");
|
printer->Print(*vars,
|
||||||
printer->Outdent();
|
"return std::unique_ptr< "
|
||||||
printer->Print("}\n");
|
"::grpc::ClientAsyncResponseReader< $Response$>>("
|
||||||
|
"$AsyncPrefix$$Method$Raw(context, request, cq));\n");
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
} else if (ClientOnlyStreaming(method)) {
|
} else if (ClientOnlyStreaming(method)) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
@@ -364,18 +431,25 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
|
|||||||
"($Method$Raw(context, response));\n");
|
"($Method$Raw(context, response));\n");
|
||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
printer->Print("}\n");
|
printer->Print("}\n");
|
||||||
printer->Print(*vars,
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
"std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>"
|
auto& async_prefix = async_prefixes[i];
|
||||||
" Async$Method$(::grpc::ClientContext* context, "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"$Response$* response, "
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
"::grpc::CompletionQueue* cq, void* tag) {\n");
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
||||||
printer->Indent();
|
printer->Print(*vars,
|
||||||
printer->Print(
|
"std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>"
|
||||||
*vars,
|
" $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
|
||||||
"return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>("
|
"$Response$* response, "
|
||||||
"Async$Method$Raw(context, response, cq, tag));\n");
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
||||||
printer->Outdent();
|
printer->Indent();
|
||||||
printer->Print("}\n");
|
printer->Print(
|
||||||
|
*vars,
|
||||||
|
"return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>("
|
||||||
|
"$AsyncPrefix$$Method$Raw(context, response, "
|
||||||
|
"cq$AsyncRawArgs$));\n");
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
} else if (ServerOnlyStreaming(method)) {
|
} else if (ServerOnlyStreaming(method)) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
@@ -389,19 +463,25 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
|
|||||||
"($Method$Raw(context, request));\n");
|
"($Method$Raw(context, request));\n");
|
||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
printer->Print("}\n");
|
printer->Print("}\n");
|
||||||
printer->Print(
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
*vars,
|
auto& async_prefix = async_prefixes[i];
|
||||||
"std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"Async$Method$("
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
"::grpc::ClientContext* context, const $Request$& request, "
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
||||||
"::grpc::CompletionQueue* cq, void* tag) {\n");
|
printer->Print(
|
||||||
printer->Indent();
|
*vars,
|
||||||
printer->Print(
|
"std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> "
|
||||||
*vars,
|
"$AsyncPrefix$$Method$("
|
||||||
"return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>("
|
"::grpc::ClientContext* context, const $Request$& request, "
|
||||||
"Async$Method$Raw(context, request, cq, tag));\n");
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
||||||
printer->Outdent();
|
printer->Indent();
|
||||||
printer->Print("}\n");
|
printer->Print(
|
||||||
|
*vars,
|
||||||
|
"return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>("
|
||||||
|
"$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
} else if (method->BidiStreaming()) {
|
} else if (method->BidiStreaming()) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
@@ -414,53 +494,85 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
|
|||||||
"$Method$Raw(context));\n");
|
"$Method$Raw(context));\n");
|
||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
printer->Print("}\n");
|
printer->Print("}\n");
|
||||||
printer->Print(*vars,
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
"std::unique_ptr< ::grpc::ClientAsyncReaderWriter< "
|
auto& async_prefix = async_prefixes[i];
|
||||||
"$Request$, $Response$>> "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"Async$Method$(::grpc::ClientContext* context, "
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
"::grpc::CompletionQueue* cq, void* tag) {\n");
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
||||||
printer->Indent();
|
printer->Print(*vars,
|
||||||
printer->Print(*vars,
|
"std::unique_ptr< ::grpc::ClientAsyncReaderWriter< "
|
||||||
"return std::unique_ptr< "
|
"$Request$, $Response$>> "
|
||||||
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>("
|
"$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
|
||||||
"Async$Method$Raw(context, cq, tag));\n");
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
||||||
printer->Outdent();
|
printer->Indent();
|
||||||
printer->Print("}\n");
|
printer->Print(
|
||||||
|
*vars,
|
||||||
|
"return std::unique_ptr< "
|
||||||
|
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>("
|
||||||
|
"$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
|
||||||
|
printer->Outdent();
|
||||||
|
printer->Print("}\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (method->NoStreaming()) {
|
if (method->NoStreaming()) {
|
||||||
printer->Print(*vars,
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
"::grpc::ClientAsyncResponseReader< $Response$>* "
|
auto& async_prefix = async_prefixes[i];
|
||||||
"Async$Method$Raw(::grpc::ClientContext* context, "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"const $Request$& request, "
|
printer->Print(
|
||||||
"::grpc::CompletionQueue* cq) override;\n");
|
*vars,
|
||||||
|
"::grpc::ClientAsyncResponseReader< $Response$>* "
|
||||||
|
"$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
|
||||||
|
"const $Request$& request, "
|
||||||
|
"::grpc::CompletionQueue* cq) override;\n");
|
||||||
|
}
|
||||||
} else if (ClientOnlyStreaming(method)) {
|
} else if (ClientOnlyStreaming(method)) {
|
||||||
printer->Print(*vars,
|
printer->Print(*vars,
|
||||||
"::grpc::ClientWriter< $Request$>* $Method$Raw("
|
"::grpc::ClientWriter< $Request$>* $Method$Raw("
|
||||||
"::grpc::ClientContext* context, $Response$* response) "
|
"::grpc::ClientContext* context, $Response$* response) "
|
||||||
"override;\n");
|
"override;\n");
|
||||||
printer->Print(*vars,
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
"::grpc::ClientAsyncWriter< $Request$>* Async$Method$Raw("
|
auto& async_prefix = async_prefixes[i];
|
||||||
"::grpc::ClientContext* context, $Response$* response, "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"::grpc::CompletionQueue* cq, void* tag) override;\n");
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
||||||
|
printer->Print(
|
||||||
|
*vars,
|
||||||
|
"::grpc::ClientAsyncWriter< $Request$>* $AsyncPrefix$$Method$Raw("
|
||||||
|
"::grpc::ClientContext* context, $Response$* response, "
|
||||||
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
|
||||||
|
}
|
||||||
} else if (ServerOnlyStreaming(method)) {
|
} else if (ServerOnlyStreaming(method)) {
|
||||||
printer->Print(*vars,
|
printer->Print(*vars,
|
||||||
"::grpc::ClientReader< $Response$>* $Method$Raw("
|
"::grpc::ClientReader< $Response$>* $Method$Raw("
|
||||||
"::grpc::ClientContext* context, const $Request$& request)"
|
"::grpc::ClientContext* context, const $Request$& request)"
|
||||||
" override;\n");
|
" override;\n");
|
||||||
printer->Print(
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
*vars,
|
auto& async_prefix = async_prefixes[i];
|
||||||
"::grpc::ClientAsyncReader< $Response$>* Async$Method$Raw("
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"::grpc::ClientContext* context, const $Request$& request, "
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
"::grpc::CompletionQueue* cq, void* tag) override;\n");
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
||||||
|
printer->Print(
|
||||||
|
*vars,
|
||||||
|
"::grpc::ClientAsyncReader< $Response$>* $AsyncPrefix$$Method$Raw("
|
||||||
|
"::grpc::ClientContext* context, const $Request$& request, "
|
||||||
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
|
||||||
|
}
|
||||||
} else if (method->BidiStreaming()) {
|
} else if (method->BidiStreaming()) {
|
||||||
printer->Print(*vars,
|
printer->Print(*vars,
|
||||||
"::grpc::ClientReaderWriter< $Request$, $Response$>* "
|
"::grpc::ClientReaderWriter< $Request$, $Response$>* "
|
||||||
"$Method$Raw(::grpc::ClientContext* context) override;\n");
|
"$Method$Raw(::grpc::ClientContext* context) override;\n");
|
||||||
printer->Print(*vars,
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
|
auto& async_prefix = async_prefixes[i];
|
||||||
"Async$Method$Raw(::grpc::ClientContext* context, "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"::grpc::CompletionQueue* cq, void* tag) override;\n");
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
|
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
|
||||||
|
printer->Print(
|
||||||
|
*vars,
|
||||||
|
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
|
||||||
|
"$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
|
||||||
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -469,7 +581,8 @@ void PrintHeaderClientMethodData(grpc_generator::Printer *printer,
|
|||||||
const grpc_generator::Method *method,
|
const grpc_generator::Method *method,
|
||||||
std::map<grpc::string, grpc::string> *vars) {
|
std::map<grpc::string, grpc::string> *vars) {
|
||||||
(*vars)["Method"] = method->name();
|
(*vars)["Method"] = method->name();
|
||||||
printer->Print(*vars, "const ::grpc::RpcMethod rpcmethod_$Method$_;\n");
|
printer->Print(*vars,
|
||||||
|
"const ::grpc::internal::RpcMethod rpcmethod_$Method$_;\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrintHeaderServerMethodSync(grpc_generator::Printer *printer,
|
void PrintHeaderServerMethodSync(grpc_generator::Printer *printer,
|
||||||
@@ -641,7 +754,7 @@ void PrintHeaderServerMethodStreamedUnary(
|
|||||||
printer->Print(*vars,
|
printer->Print(*vars,
|
||||||
"WithStreamedUnaryMethod_$Method$() {\n"
|
"WithStreamedUnaryMethod_$Method$() {\n"
|
||||||
" ::grpc::Service::MarkMethodStreamed($Idx$,\n"
|
" ::grpc::Service::MarkMethodStreamed($Idx$,\n"
|
||||||
" new ::grpc::StreamedUnaryHandler< $Request$, "
|
" new ::grpc::internal::StreamedUnaryHandler< $Request$, "
|
||||||
"$Response$>(std::bind"
|
"$Response$>(std::bind"
|
||||||
"(&WithStreamedUnaryMethod_$Method$<BaseClass>::"
|
"(&WithStreamedUnaryMethod_$Method$<BaseClass>::"
|
||||||
"Streamed$Method$, this, std::placeholders::_1, "
|
"Streamed$Method$, this, std::placeholders::_1, "
|
||||||
@@ -689,15 +802,16 @@ void PrintHeaderServerMethodSplitStreaming(
|
|||||||
"{}\n");
|
"{}\n");
|
||||||
printer->Print(" public:\n");
|
printer->Print(" public:\n");
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
printer->Print(*vars,
|
printer->Print(
|
||||||
"WithSplitStreamingMethod_$Method$() {\n"
|
*vars,
|
||||||
" ::grpc::Service::MarkMethodStreamed($Idx$,\n"
|
"WithSplitStreamingMethod_$Method$() {\n"
|
||||||
" new ::grpc::SplitServerStreamingHandler< $Request$, "
|
" ::grpc::Service::MarkMethodStreamed($Idx$,\n"
|
||||||
"$Response$>(std::bind"
|
" new ::grpc::internal::SplitServerStreamingHandler< $Request$, "
|
||||||
"(&WithSplitStreamingMethod_$Method$<BaseClass>::"
|
"$Response$>(std::bind"
|
||||||
"Streamed$Method$, this, std::placeholders::_1, "
|
"(&WithSplitStreamingMethod_$Method$<BaseClass>::"
|
||||||
"std::placeholders::_2)));\n"
|
"Streamed$Method$, this, std::placeholders::_1, "
|
||||||
"}\n");
|
"std::placeholders::_2)));\n"
|
||||||
|
"}\n");
|
||||||
printer->Print(*vars,
|
printer->Print(*vars,
|
||||||
"~WithSplitStreamingMethod_$Method$() override {\n"
|
"~WithSplitStreamingMethod_$Method$() override {\n"
|
||||||
" BaseClassMustBeDerivedFromService(this);\n"
|
" BaseClassMustBeDerivedFromService(this);\n"
|
||||||
@@ -837,7 +951,8 @@ void PrintHeaderService(grpc_generator::Printer *printer,
|
|||||||
" {\n public:\n");
|
" {\n public:\n");
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
printer->Print(
|
printer->Print(
|
||||||
"Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel);\n");
|
"Stub(const std::shared_ptr< ::grpc::ChannelInterface>& "
|
||||||
|
"channel);\n");
|
||||||
for (int i = 0; i < service->method_count(); ++i) {
|
for (int i = 0; i < service->method_count(); ++i) {
|
||||||
PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
|
PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
|
||||||
}
|
}
|
||||||
@@ -1095,99 +1210,137 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
|
|||||||
(*vars)["Method"] = method->name();
|
(*vars)["Method"] = method->name();
|
||||||
(*vars)["Request"] = method->input_type_name();
|
(*vars)["Request"] = method->input_type_name();
|
||||||
(*vars)["Response"] = method->output_type_name();
|
(*vars)["Response"] = method->output_type_name();
|
||||||
|
struct {
|
||||||
|
grpc::string prefix;
|
||||||
|
grpc::string start; // bool literal expressed as string
|
||||||
|
grpc::string method_params; // extra arguments to method
|
||||||
|
grpc::string create_args; // extra arguments to creator
|
||||||
|
} async_prefixes[] = {{"Async", "true", ", void* tag", ", tag"},
|
||||||
|
{"PrepareAsync", "false", "", ", nullptr"}};
|
||||||
if (method->NoStreaming()) {
|
if (method->NoStreaming()) {
|
||||||
printer->Print(*vars,
|
printer->Print(*vars,
|
||||||
"::grpc::Status $ns$$Service$::Stub::$Method$("
|
"::grpc::Status $ns$$Service$::Stub::$Method$("
|
||||||
"::grpc::ClientContext* context, "
|
"::grpc::ClientContext* context, "
|
||||||
"const $Request$& request, $Response$* response) {\n");
|
"const $Request$& request, $Response$* response) {\n");
|
||||||
printer->Print(*vars,
|
printer->Print(*vars,
|
||||||
" return ::grpc::BlockingUnaryCall(channel_.get(), "
|
" return ::grpc::internal::BlockingUnaryCall"
|
||||||
"rpcmethod_$Method$_, "
|
"(channel_.get(), rpcmethod_$Method$_, "
|
||||||
"context, request, response);\n"
|
"context, request, response);\n}\n\n");
|
||||||
"}\n\n");
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
printer->Print(
|
auto& async_prefix = async_prefixes[i];
|
||||||
*vars,
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"::grpc::ClientAsyncResponseReader< $Response$>* "
|
(*vars)["AsyncStart"] = async_prefix.start;
|
||||||
"$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, "
|
printer->Print(*vars,
|
||||||
"const $Request$& request, "
|
"::grpc::ClientAsyncResponseReader< $Response$>* "
|
||||||
"::grpc::CompletionQueue* cq) {\n");
|
"$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
|
||||||
printer->Print(*vars,
|
"ClientContext* context, "
|
||||||
" return "
|
"const $Request$& request, "
|
||||||
"::grpc::ClientAsyncResponseReader< $Response$>::Create("
|
"::grpc::CompletionQueue* cq) {\n");
|
||||||
"channel_.get(), cq, "
|
printer->Print(
|
||||||
"rpcmethod_$Method$_, "
|
*vars,
|
||||||
"context, request);\n"
|
" return "
|
||||||
"}\n\n");
|
"::grpc::internal::ClientAsyncResponseReaderFactory< $Response$>"
|
||||||
|
"::Create(channel_.get(), cq, "
|
||||||
|
"rpcmethod_$Method$_, "
|
||||||
|
"context, request, $AsyncStart$);\n"
|
||||||
|
"}\n\n");
|
||||||
|
}
|
||||||
} else if (ClientOnlyStreaming(method)) {
|
} else if (ClientOnlyStreaming(method)) {
|
||||||
printer->Print(*vars,
|
printer->Print(*vars,
|
||||||
"::grpc::ClientWriter< $Request$>* "
|
"::grpc::ClientWriter< $Request$>* "
|
||||||
"$ns$$Service$::Stub::$Method$Raw("
|
"$ns$$Service$::Stub::$Method$Raw("
|
||||||
"::grpc::ClientContext* context, $Response$* response) {\n");
|
"::grpc::ClientContext* context, $Response$* response) {\n");
|
||||||
printer->Print(*vars,
|
printer->Print(
|
||||||
" return new ::grpc::ClientWriter< $Request$>("
|
*vars,
|
||||||
"channel_.get(), "
|
" return ::grpc::internal::ClientWriterFactory< $Request$>::Create("
|
||||||
"rpcmethod_$Method$_, "
|
"channel_.get(), "
|
||||||
"context, response);\n"
|
"rpcmethod_$Method$_, "
|
||||||
"}\n\n");
|
"context, response);\n"
|
||||||
printer->Print(*vars,
|
"}\n\n");
|
||||||
"::grpc::ClientAsyncWriter< $Request$>* "
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
"$ns$$Service$::Stub::Async$Method$Raw("
|
auto& async_prefix = async_prefixes[i];
|
||||||
"::grpc::ClientContext* context, $Response$* response, "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"::grpc::CompletionQueue* cq, void* tag) {\n");
|
(*vars)["AsyncStart"] = async_prefix.start;
|
||||||
printer->Print(*vars,
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
" return ::grpc::ClientAsyncWriter< $Request$>::Create("
|
(*vars)["AsyncCreateArgs"] = async_prefix.create_args;
|
||||||
"channel_.get(), cq, "
|
printer->Print(*vars,
|
||||||
"rpcmethod_$Method$_, "
|
"::grpc::ClientAsyncWriter< $Request$>* "
|
||||||
"context, response, tag);\n"
|
"$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
|
||||||
"}\n\n");
|
"::grpc::ClientContext* context, $Response$* response, "
|
||||||
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
||||||
|
printer->Print(
|
||||||
|
*vars,
|
||||||
|
" return ::grpc::internal::ClientAsyncWriterFactory< $Request$>"
|
||||||
|
"::Create(channel_.get(), cq, "
|
||||||
|
"rpcmethod_$Method$_, "
|
||||||
|
"context, response, $AsyncStart$$AsyncCreateArgs$);\n"
|
||||||
|
"}\n\n");
|
||||||
|
}
|
||||||
} else if (ServerOnlyStreaming(method)) {
|
} else if (ServerOnlyStreaming(method)) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
"::grpc::ClientReader< $Response$>* "
|
"::grpc::ClientReader< $Response$>* "
|
||||||
"$ns$$Service$::Stub::$Method$Raw("
|
"$ns$$Service$::Stub::$Method$Raw("
|
||||||
"::grpc::ClientContext* context, const $Request$& request) {\n");
|
"::grpc::ClientContext* context, const $Request$& request) {\n");
|
||||||
printer->Print(*vars,
|
printer->Print(
|
||||||
" return new ::grpc::ClientReader< $Response$>("
|
*vars,
|
||||||
"channel_.get(), "
|
" return ::grpc::internal::ClientReaderFactory< $Response$>::Create("
|
||||||
"rpcmethod_$Method$_, "
|
"channel_.get(), "
|
||||||
"context, request);\n"
|
"rpcmethod_$Method$_, "
|
||||||
"}\n\n");
|
"context, request);\n"
|
||||||
printer->Print(*vars,
|
"}\n\n");
|
||||||
"::grpc::ClientAsyncReader< $Response$>* "
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
"$ns$$Service$::Stub::Async$Method$Raw("
|
auto& async_prefix = async_prefixes[i];
|
||||||
"::grpc::ClientContext* context, const $Request$& request, "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"::grpc::CompletionQueue* cq, void* tag) {\n");
|
(*vars)["AsyncStart"] = async_prefix.start;
|
||||||
printer->Print(*vars,
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
" return ::grpc::ClientAsyncReader< $Response$>::Create("
|
(*vars)["AsyncCreateArgs"] = async_prefix.create_args;
|
||||||
"channel_.get(), cq, "
|
printer->Print(
|
||||||
"rpcmethod_$Method$_, "
|
*vars,
|
||||||
"context, request, tag);\n"
|
"::grpc::ClientAsyncReader< $Response$>* "
|
||||||
"}\n\n");
|
"$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
|
||||||
|
"::grpc::ClientContext* context, const $Request$& request, "
|
||||||
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
||||||
|
printer->Print(
|
||||||
|
*vars,
|
||||||
|
" return ::grpc::internal::ClientAsyncReaderFactory< $Response$>"
|
||||||
|
"::Create(channel_.get(), cq, "
|
||||||
|
"rpcmethod_$Method$_, "
|
||||||
|
"context, request, $AsyncStart$$AsyncCreateArgs$);\n"
|
||||||
|
"}\n\n");
|
||||||
|
}
|
||||||
} else if (method->BidiStreaming()) {
|
} else if (method->BidiStreaming()) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
"::grpc::ClientReaderWriter< $Request$, $Response$>* "
|
"::grpc::ClientReaderWriter< $Request$, $Response$>* "
|
||||||
"$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n");
|
"$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n");
|
||||||
printer->Print(*vars,
|
printer->Print(*vars,
|
||||||
" return new ::grpc::ClientReaderWriter< "
|
" return ::grpc::internal::ClientReaderWriterFactory< "
|
||||||
"$Request$, $Response$>("
|
"$Request$, $Response$>::Create("
|
||||||
"channel_.get(), "
|
"channel_.get(), "
|
||||||
"rpcmethod_$Method$_, "
|
"rpcmethod_$Method$_, "
|
||||||
"context);\n"
|
"context);\n"
|
||||||
"}\n\n");
|
"}\n\n");
|
||||||
printer->Print(
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
*vars,
|
auto& async_prefix = async_prefixes[i];
|
||||||
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, "
|
(*vars)["AsyncStart"] = async_prefix.start;
|
||||||
"::grpc::CompletionQueue* cq, void* tag) {\n");
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
printer->Print(
|
(*vars)["AsyncCreateArgs"] = async_prefix.create_args;
|
||||||
*vars,
|
printer->Print(*vars,
|
||||||
" return "
|
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
|
||||||
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>::Create("
|
"$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
|
||||||
"channel_.get(), cq, "
|
"ClientContext* context, "
|
||||||
"rpcmethod_$Method$_, "
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
|
||||||
"context, tag);\n"
|
printer->Print(*vars,
|
||||||
"}\n\n");
|
" return "
|
||||||
|
"::grpc::internal::ClientAsyncReaderWriterFactory< "
|
||||||
|
"$Request$, $Response$>::Create("
|
||||||
|
"channel_.get(), cq, "
|
||||||
|
"rpcmethod_$Method$_, "
|
||||||
|
"context, $AsyncStart$$AsyncCreateArgs$);\n"
|
||||||
|
"}\n\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1297,7 +1450,7 @@ void PrintSourceService(grpc_generator::Printer *printer,
|
|||||||
printer->Print(*vars,
|
printer->Print(*vars,
|
||||||
", rpcmethod_$Method$_("
|
", rpcmethod_$Method$_("
|
||||||
"$prefix$$Service$_method_names[$Idx$], "
|
"$prefix$$Service$_method_names[$Idx$], "
|
||||||
"::grpc::RpcMethod::$StreamingType$, "
|
"::grpc::internal::RpcMethod::$StreamingType$, "
|
||||||
"channel"
|
"channel"
|
||||||
")\n");
|
")\n");
|
||||||
}
|
}
|
||||||
@@ -1320,38 +1473,38 @@ void PrintSourceService(grpc_generator::Printer *printer,
|
|||||||
if (method->NoStreaming()) {
|
if (method->NoStreaming()) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
"AddMethod(new ::grpc::RpcServiceMethod(\n"
|
"AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
|
||||||
" $prefix$$Service$_method_names[$Idx$],\n"
|
" $prefix$$Service$_method_names[$Idx$],\n"
|
||||||
" ::grpc::RpcMethod::NORMAL_RPC,\n"
|
" ::grpc::internal::RpcMethod::NORMAL_RPC,\n"
|
||||||
" new ::grpc::RpcMethodHandler< $ns$$Service$::Service, "
|
" new ::grpc::internal::RpcMethodHandler< $ns$$Service$::Service, "
|
||||||
"$Request$, "
|
"$Request$, "
|
||||||
"$Response$>(\n"
|
"$Response$>(\n"
|
||||||
" std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
|
" std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
|
||||||
} else if (ClientOnlyStreaming(method.get())) {
|
} else if (ClientOnlyStreaming(method.get())) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
"AddMethod(new ::grpc::RpcServiceMethod(\n"
|
"AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
|
||||||
" $prefix$$Service$_method_names[$Idx$],\n"
|
" $prefix$$Service$_method_names[$Idx$],\n"
|
||||||
" ::grpc::RpcMethod::CLIENT_STREAMING,\n"
|
" ::grpc::internal::RpcMethod::CLIENT_STREAMING,\n"
|
||||||
" new ::grpc::ClientStreamingHandler< "
|
" new ::grpc::internal::ClientStreamingHandler< "
|
||||||
"$ns$$Service$::Service, $Request$, $Response$>(\n"
|
"$ns$$Service$::Service, $Request$, $Response$>(\n"
|
||||||
" std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
|
" std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
|
||||||
} else if (ServerOnlyStreaming(method.get())) {
|
} else if (ServerOnlyStreaming(method.get())) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
"AddMethod(new ::grpc::RpcServiceMethod(\n"
|
"AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
|
||||||
" $prefix$$Service$_method_names[$Idx$],\n"
|
" $prefix$$Service$_method_names[$Idx$],\n"
|
||||||
" ::grpc::RpcMethod::SERVER_STREAMING,\n"
|
" ::grpc::internal::RpcMethod::SERVER_STREAMING,\n"
|
||||||
" new ::grpc::ServerStreamingHandler< "
|
" new ::grpc::internal::ServerStreamingHandler< "
|
||||||
"$ns$$Service$::Service, $Request$, $Response$>(\n"
|
"$ns$$Service$::Service, $Request$, $Response$>(\n"
|
||||||
" std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
|
" std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
|
||||||
} else if (method->BidiStreaming()) {
|
} else if (method->BidiStreaming()) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
"AddMethod(new ::grpc::RpcServiceMethod(\n"
|
"AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
|
||||||
" $prefix$$Service$_method_names[$Idx$],\n"
|
" $prefix$$Service$_method_names[$Idx$],\n"
|
||||||
" ::grpc::RpcMethod::BIDI_STREAMING,\n"
|
" ::grpc::internal::RpcMethod::BIDI_STREAMING,\n"
|
||||||
" new ::grpc::BidiStreamingHandler< "
|
" new ::grpc::internal::BidiStreamingHandler< "
|
||||||
"$ns$$Service$::Service, $Request$, $Response$>(\n"
|
"$ns$$Service$::Service, $Request$, $Response$>(\n"
|
||||||
" std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
|
" std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
|
||||||
}
|
}
|
||||||
@@ -1452,7 +1605,8 @@ grpc::string GetMockIncludes(grpc_generator::File *file,
|
|||||||
|
|
||||||
static const char *headers_strs[] = {
|
static const char *headers_strs[] = {
|
||||||
"grpc++/impl/codegen/async_stream.h",
|
"grpc++/impl/codegen/async_stream.h",
|
||||||
"grpc++/impl/codegen/sync_stream.h", "gmock/gmock.h",
|
"grpc++/impl/codegen/sync_stream.h",
|
||||||
|
"gmock/gmock.h",
|
||||||
};
|
};
|
||||||
std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
|
std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
|
||||||
PrintIncludes(printer.get(), headers, params);
|
PrintIncludes(printer.get(), headers, params);
|
||||||
@@ -1478,50 +1632,83 @@ void PrintMockClientMethods(grpc_generator::Printer *printer,
|
|||||||
(*vars)["Request"] = method->input_type_name();
|
(*vars)["Request"] = method->input_type_name();
|
||||||
(*vars)["Response"] = method->output_type_name();
|
(*vars)["Response"] = method->output_type_name();
|
||||||
|
|
||||||
|
struct {
|
||||||
|
grpc::string prefix;
|
||||||
|
grpc::string method_params; // extra arguments to method
|
||||||
|
int extra_method_param_count;
|
||||||
|
} async_prefixes[] = {{"Async", ", void* tag", 1}, {"PrepareAsync", "", 0}};
|
||||||
|
|
||||||
if (method->NoStreaming()) {
|
if (method->NoStreaming()) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
"MOCK_METHOD3($Method$, ::grpc::Status(::grpc::ClientContext* context, "
|
"MOCK_METHOD3($Method$, ::grpc::Status(::grpc::ClientContext* context, "
|
||||||
"const $Request$& request, $Response$* response));\n");
|
"const $Request$& request, $Response$* response));\n");
|
||||||
printer->Print(*vars,
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
"MOCK_METHOD3(Async$Method$Raw, "
|
auto& async_prefix = async_prefixes[i];
|
||||||
"::grpc::ClientAsyncResponseReaderInterface< $Response$>*"
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"(::grpc::ClientContext* context, const $Request$& request, "
|
printer->Print(
|
||||||
"::grpc::CompletionQueue* cq));\n");
|
*vars,
|
||||||
|
"MOCK_METHOD3($AsyncPrefix$$Method$Raw, "
|
||||||
|
"::grpc::ClientAsyncResponseReaderInterface< $Response$>*"
|
||||||
|
"(::grpc::ClientContext* context, const $Request$& request, "
|
||||||
|
"::grpc::CompletionQueue* cq));\n");
|
||||||
|
}
|
||||||
} else if (ClientOnlyStreaming(method)) {
|
} else if (ClientOnlyStreaming(method)) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
"MOCK_METHOD2($Method$Raw, "
|
"MOCK_METHOD2($Method$Raw, "
|
||||||
"::grpc::ClientWriterInterface< $Request$>*"
|
"::grpc::ClientWriterInterface< $Request$>*"
|
||||||
"(::grpc::ClientContext* context, $Response$* response));\n");
|
"(::grpc::ClientContext* context, $Response$* response));\n");
|
||||||
printer->Print(*vars,
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
"MOCK_METHOD4(Async$Method$Raw, "
|
auto& async_prefix = async_prefixes[i];
|
||||||
"::grpc::ClientAsyncWriterInterface< $Request$>*"
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"(::grpc::ClientContext* context, $Response$* response, "
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
"::grpc::CompletionQueue* cq, void* tag));\n");
|
(*vars)["MockArgs"] =
|
||||||
|
flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
|
||||||
|
printer->Print(*vars,
|
||||||
|
"MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
|
||||||
|
"::grpc::ClientAsyncWriterInterface< $Request$>*"
|
||||||
|
"(::grpc::ClientContext* context, $Response$* response, "
|
||||||
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
|
||||||
|
}
|
||||||
} else if (ServerOnlyStreaming(method)) {
|
} else if (ServerOnlyStreaming(method)) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
"MOCK_METHOD2($Method$Raw, "
|
"MOCK_METHOD2($Method$Raw, "
|
||||||
"::grpc::ClientReaderInterface< $Response$>*"
|
"::grpc::ClientReaderInterface< $Response$>*"
|
||||||
"(::grpc::ClientContext* context, const $Request$& request));\n");
|
"(::grpc::ClientContext* context, const $Request$& request));\n");
|
||||||
printer->Print(*vars,
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
"MOCK_METHOD4(Async$Method$Raw, "
|
auto& async_prefix = async_prefixes[i];
|
||||||
"::grpc::ClientAsyncReaderInterface< $Response$>*"
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"(::grpc::ClientContext* context, const $Request$& request, "
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
"::grpc::CompletionQueue* cq, void* tag));\n");
|
(*vars)["MockArgs"] =
|
||||||
|
flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
|
||||||
|
printer->Print(
|
||||||
|
*vars,
|
||||||
|
"MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
|
||||||
|
"::grpc::ClientAsyncReaderInterface< $Response$>*"
|
||||||
|
"(::grpc::ClientContext* context, const $Request$& request, "
|
||||||
|
"::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
|
||||||
|
}
|
||||||
} else if (method->BidiStreaming()) {
|
} else if (method->BidiStreaming()) {
|
||||||
printer->Print(
|
printer->Print(
|
||||||
*vars,
|
*vars,
|
||||||
"MOCK_METHOD1($Method$Raw, "
|
"MOCK_METHOD1($Method$Raw, "
|
||||||
"::grpc::ClientReaderWriterInterface< $Request$, $Response$>*"
|
"::grpc::ClientReaderWriterInterface< $Request$, $Response$>*"
|
||||||
"(::grpc::ClientContext* context));\n");
|
"(::grpc::ClientContext* context));\n");
|
||||||
printer->Print(
|
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
|
||||||
*vars,
|
auto& async_prefix = async_prefixes[i];
|
||||||
"MOCK_METHOD3(Async$Method$Raw, "
|
(*vars)["AsyncPrefix"] = async_prefix.prefix;
|
||||||
"::grpc::ClientAsyncReaderWriterInterface<$Request$, $Response$>*"
|
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
|
||||||
"(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq, "
|
(*vars)["MockArgs"] =
|
||||||
"void* tag));\n");
|
flatbuffers::NumToString(2 + async_prefix.extra_method_param_count);
|
||||||
|
printer->Print(
|
||||||
|
*vars,
|
||||||
|
"MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
|
||||||
|
"::grpc::ClientAsyncReaderWriterInterface<$Request$, $Response$>*"
|
||||||
|
"(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq"
|
||||||
|
"$AsyncMethodParams$));\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1137
grpc/src/compiler/java_generator.cc
Normal file
1137
grpc/src/compiler/java_generator.cc
Normal file
File diff suppressed because it is too large
Load Diff
87
grpc/src/compiler/java_generator.h
Normal file
87
grpc/src/compiler/java_generator.h
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Google Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef NET_GRPC_COMPILER_JAVA_GENERATOR_H_
|
||||||
|
#define NET_GRPC_COMPILER_JAVA_GENERATOR_H_
|
||||||
|
|
||||||
|
#include <stdlib.h> // for abort()
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "src/compiler/schema_interface.h"
|
||||||
|
|
||||||
|
class LogMessageVoidify {
|
||||||
|
public:
|
||||||
|
LogMessageVoidify() {}
|
||||||
|
// This has to be an operator with a precedence lower than << but
|
||||||
|
// higher than ?:
|
||||||
|
void operator&(std::ostream&) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LogHelper {
|
||||||
|
std::ostream* os_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
LogHelper(std::ostream* os) : os_(os) {}
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning( \
|
||||||
|
disable : 4722) // the flow of control terminates in a destructor
|
||||||
|
// (needed to compile ~LogHelper where destructor emits abort intentionally -
|
||||||
|
// inherited from grpc/java code generator).
|
||||||
|
#endif
|
||||||
|
~LogHelper() {
|
||||||
|
*os_ << std::endl;
|
||||||
|
::abort();
|
||||||
|
}
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
std::ostream& get_os() const { return *os_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Abort the program after logging the mesage if the given condition is not
|
||||||
|
// true. Otherwise, do nothing.
|
||||||
|
#define GRPC_CODEGEN_CHECK(x) \
|
||||||
|
(x) ? (void)0 \
|
||||||
|
: LogMessageVoidify() & LogHelper(&std::cerr).get_os() \
|
||||||
|
<< "CHECK FAILED: " << __FILE__ << ":" \
|
||||||
|
<< __LINE__ << ": "
|
||||||
|
|
||||||
|
// Abort the program after logging the mesage.
|
||||||
|
#define GRPC_CODEGEN_FAIL GRPC_CODEGEN_CHECK(false)
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
namespace grpc_java_generator {
|
||||||
|
struct Parameters {
|
||||||
|
// //Defines the custom parameter types for methods
|
||||||
|
// //eg: flatbuffers uses flatbuffers.Builder as input for the client
|
||||||
|
// and output for the server grpc::string custom_method_io_type;
|
||||||
|
|
||||||
|
// Package name for the service
|
||||||
|
grpc::string package_name;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return the source of the generated service file.
|
||||||
|
grpc::string GenerateServiceSource(grpc_generator::File* file,
|
||||||
|
const grpc_generator::Service* service,
|
||||||
|
grpc_java_generator::Parameters* parameters);
|
||||||
|
|
||||||
|
} // namespace grpc_java_generator
|
||||||
|
|
||||||
|
#endif // NET_GRPC_COMPILER_JAVA_GENERATOR_H_
|
||||||
@@ -40,8 +40,8 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifndef GRPC_CUSTOM_STRING
|
#ifndef GRPC_CUSTOM_STRING
|
||||||
#include <string>
|
# include <string>
|
||||||
#define GRPC_CUSTOM_STRING std::string
|
# define GRPC_CUSTOM_STRING std::string
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace grpc {
|
namespace grpc {
|
||||||
|
|||||||
119
grpc/tests/JavaGrpcTest.java
Normal file
119
grpc/tests/JavaGrpcTest.java
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import MyGame.Example.Monster;
|
||||||
|
import MyGame.Example.MonsterStorageGrpc;
|
||||||
|
import MyGame.Example.Stat;
|
||||||
|
import com.google.flatbuffers.FlatBufferBuilder;
|
||||||
|
import io.grpc.ManagedChannel;
|
||||||
|
import io.grpc.ManagedChannelBuilder;
|
||||||
|
import io.grpc.Server;
|
||||||
|
import io.grpc.ServerBuilder;
|
||||||
|
import org.junit.Assert;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates basic client-server interaction using grpc-java over netty.
|
||||||
|
*/
|
||||||
|
public class JavaGrpcTest {
|
||||||
|
static final String BIG_MONSTER_NAME = "big-monster";
|
||||||
|
static final short nestedMonsterHp = 600;
|
||||||
|
static final short nestedMonsterMana = 1024;
|
||||||
|
static final int numStreamedMsgs = 10;
|
||||||
|
|
||||||
|
static class MyService extends MonsterStorageGrpc.MonsterStorageImplBase {
|
||||||
|
@Override
|
||||||
|
public void store(Monster request, io.grpc.stub.StreamObserver<Stat> responseObserver) {
|
||||||
|
Assert.assertEquals(request.name(), BIG_MONSTER_NAME);
|
||||||
|
Assert.assertEquals(request.hp(), nestedMonsterHp);
|
||||||
|
Assert.assertEquals(request.mana(), nestedMonsterMana);
|
||||||
|
System.out.println("Received store request from " + request.name());
|
||||||
|
// Create a response from the incoming request name.
|
||||||
|
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||||
|
int statOffset = Stat.createStat(builder, builder.createString("Hello " + request.name()), 100, 10);
|
||||||
|
builder.finish(statOffset);
|
||||||
|
Stat stat = Stat.getRootAsStat(builder.dataBuffer());
|
||||||
|
responseObserver.onNext(stat);
|
||||||
|
responseObserver.onCompleted();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void retrieve(Stat request, io.grpc.stub.StreamObserver<Monster> responseObserver) {
|
||||||
|
// Create 10 monsters for streaming response.
|
||||||
|
for (int i=0; i<numStreamedMsgs; i++) {
|
||||||
|
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||||
|
int i1 = builder.createString(request.id() + " No." + i);
|
||||||
|
Monster.startMonster(builder);
|
||||||
|
Monster.addName(builder, i1);
|
||||||
|
int i2 = Monster.endMonster(builder);
|
||||||
|
Monster.finishMonsterBuffer(builder, i2);
|
||||||
|
Monster monster = Monster.getRootAsMonster(builder.dataBuffer());
|
||||||
|
responseObserver.onNext(monster);
|
||||||
|
}
|
||||||
|
responseObserver.onCompleted();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static int startServer() throws IOException {
|
||||||
|
Server server = ServerBuilder.forPort(0).addService(new MyService()).build().start();
|
||||||
|
return server.getPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.junit.Test
|
||||||
|
public void testMonster() throws IOException {
|
||||||
|
int port = startServer();
|
||||||
|
ManagedChannel 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)
|
||||||
|
.directExecutor()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
MonsterStorageGrpc.MonsterStorageBlockingStub stub = MonsterStorageGrpc.newBlockingStub(channel);
|
||||||
|
|
||||||
|
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||||
|
|
||||||
|
int o_string = builder.createString(BIG_MONSTER_NAME);
|
||||||
|
Monster.startMonster(builder);
|
||||||
|
Monster.addName(builder, o_string);
|
||||||
|
Monster.addHp(builder, nestedMonsterHp);
|
||||||
|
Monster.addMana(builder, nestedMonsterMana);
|
||||||
|
int monster1 = Monster.endMonster(builder);
|
||||||
|
Monster.finishMonsterBuffer(builder, monster1);
|
||||||
|
|
||||||
|
ByteBuffer buffer = builder.dataBuffer();
|
||||||
|
Monster monsterRequest = Monster.getRootAsMonster(buffer);
|
||||||
|
Stat stat = stub.store(monsterRequest);
|
||||||
|
Assert.assertEquals(stat.id(), "Hello " + BIG_MONSTER_NAME);
|
||||||
|
System.out.println("Received stat response from service: " + stat.id());
|
||||||
|
|
||||||
|
|
||||||
|
Iterator<Monster> iterator = stub.retrieve(stat);
|
||||||
|
int counter = 0;
|
||||||
|
while(iterator.hasNext()) {
|
||||||
|
Monster m = iterator.next();
|
||||||
|
System.out.println("Received monster " + m.name());
|
||||||
|
counter ++;
|
||||||
|
}
|
||||||
|
Assert.assertEquals(counter, numStreamedMsgs);
|
||||||
|
System.out.println("FlatBuffers GRPC client/server test: completed successfully");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,46 +18,48 @@
|
|||||||
|
|
||||||
#include <grpc++/grpc++.h>
|
#include <grpc++/grpc++.h>
|
||||||
|
|
||||||
#include "monster_test_generated.h"
|
|
||||||
#include "monster_test.grpc.fb.h"
|
#include "monster_test.grpc.fb.h"
|
||||||
|
#include "monster_test_generated.h"
|
||||||
|
|
||||||
using namespace MyGame::Example;
|
using namespace MyGame::Example;
|
||||||
|
|
||||||
// The callback implementation of our server, that derives from the generated
|
// The callback implementation of our server, that derives from the generated
|
||||||
// code. It implements all rpcs specified in the FlatBuffers schema.
|
// code. It implements all rpcs specified in the FlatBuffers schema.
|
||||||
class ServiceImpl final : public MyGame::Example::MonsterStorage::Service {
|
class ServiceImpl final : public MyGame::Example::MonsterStorage::Service {
|
||||||
virtual ::grpc::Status Store(::grpc::ServerContext* context,
|
virtual ::grpc::Status Store(
|
||||||
const flatbuffers::grpc::Message<Monster> *request,
|
::grpc::ServerContext *context,
|
||||||
flatbuffers::grpc::Message<Stat> *response)
|
const flatbuffers::grpc::Message<Monster> *request,
|
||||||
override {
|
flatbuffers::grpc::Message<Stat> *response) override {
|
||||||
// Create a response from the incoming request name.
|
// Create a response from the incoming request name.
|
||||||
fbb_.Clear();
|
fbb_.Clear();
|
||||||
auto stat_offset = CreateStat(fbb_, fbb_.CreateString("Hello, " +
|
auto stat_offset = CreateStat(
|
||||||
request->GetRoot()->name()->str()));
|
fbb_, fbb_.CreateString("Hello, " + request->GetRoot()->name()->str()));
|
||||||
fbb_.Finish(stat_offset);
|
fbb_.Finish(stat_offset);
|
||||||
// Transfer ownership of the message to gRPC
|
// Transfer ownership of the message to gRPC
|
||||||
*response = fbb_.ReleaseMessage<Stat>();
|
*response = fbb_.ReleaseMessage<Stat>();
|
||||||
return grpc::Status::OK;
|
return grpc::Status::OK;
|
||||||
}
|
}
|
||||||
virtual ::grpc::Status Retrieve(::grpc::ServerContext *context,
|
virtual ::grpc::Status Retrieve(
|
||||||
const flatbuffers::grpc::Message<Stat> *request,
|
::grpc::ServerContext *context,
|
||||||
::grpc::ServerWriter< flatbuffers::grpc::Message<Monster>>* writer)
|
const flatbuffers::grpc::Message<Stat> *request,
|
||||||
override {
|
::grpc::ServerWriter<flatbuffers::grpc::Message<Monster>> *writer)
|
||||||
|
override {
|
||||||
|
for (int i = 0; i < 10; i++) {
|
||||||
|
fbb_.Clear();
|
||||||
|
// Create 10 monsters for resposne.
|
||||||
|
auto monster_offset =
|
||||||
|
CreateMonster(fbb_, 0, 0, 0,
|
||||||
|
fbb_.CreateString(request->GetRoot()->id()->str() +
|
||||||
|
" No." + std::to_string(i)));
|
||||||
|
fbb_.Finish(monster_offset);
|
||||||
|
|
||||||
for (int i=0; i<10; i++) {
|
flatbuffers::grpc::Message<Monster> monster =
|
||||||
fbb_.Clear();
|
fbb_.ReleaseMessage<Monster>();
|
||||||
// Create 10 monsters for resposne.
|
|
||||||
auto monster_offset =
|
|
||||||
CreateMonster(fbb_, 0, 0, 0, fbb_.CreateString(
|
|
||||||
request->GetRoot()->id()->str() + " No." + std::to_string(i)));
|
|
||||||
fbb_.Finish(monster_offset);
|
|
||||||
|
|
||||||
flatbuffers::grpc::Message<Monster> monster = fbb_.ReleaseMessage<Monster>();
|
// Send monster to client using streaming.
|
||||||
|
writer->Write(monster);
|
||||||
// Send monster to client using streaming.
|
}
|
||||||
writer->Write(monster);
|
return grpc::Status::OK;
|
||||||
}
|
|
||||||
return grpc::Status::OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -90,7 +92,7 @@ void RunServer() {
|
|||||||
server_instance->Wait();
|
server_instance->Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int /*argc*/, const char * /*argv*/[]) {
|
int main(int /*argc*/, const char * /*argv*/ []) {
|
||||||
// Launch server.
|
// Launch server.
|
||||||
std::thread server_thread(RunServer);
|
std::thread server_thread(RunServer);
|
||||||
|
|
||||||
@@ -103,7 +105,6 @@ int main(int /*argc*/, const char * /*argv*/[]) {
|
|||||||
grpc::InsecureChannelCredentials());
|
grpc::InsecureChannelCredentials());
|
||||||
auto stub = MyGame::Example::MonsterStorage::NewStub(channel);
|
auto stub = MyGame::Example::MonsterStorage::NewStub(channel);
|
||||||
|
|
||||||
|
|
||||||
flatbuffers::grpc::MessageBuilder fbb;
|
flatbuffers::grpc::MessageBuilder fbb;
|
||||||
{
|
{
|
||||||
grpc::ClientContext context;
|
grpc::ClientContext context;
|
||||||
@@ -138,7 +139,7 @@ int main(int /*argc*/, const char * /*argv*/[]) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
|
#if !FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
|
||||||
{
|
{
|
||||||
// Test that an invalid request errors out correctly
|
// Test that an invalid request errors out correctly
|
||||||
grpc::ClientContext context;
|
grpc::ClientContext context;
|
||||||
@@ -149,9 +150,10 @@ int main(int /*argc*/, const char * /*argv*/[]) {
|
|||||||
// matches the protobuf gRPC status code for an unparseable message.
|
// matches the protobuf gRPC status code for an unparseable message.
|
||||||
assert(!status.ok());
|
assert(!status.ok());
|
||||||
assert(status.error_code() == ::grpc::StatusCode::INTERNAL);
|
assert(status.error_code() == ::grpc::StatusCode::INTERNAL);
|
||||||
assert(strcmp(status.error_message().c_str(), "Message verification failed") == 0);
|
assert(strcmp(status.error_message().c_str(),
|
||||||
|
"Message verification failed") == 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
server_instance->Shutdown();
|
server_instance->Shutdown();
|
||||||
|
|
||||||
|
|||||||
4
grpc/tests/java-grpc-test.sh
Executable file
4
grpc/tests/java-grpc-test.sh
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# NOTE: make sure `mvn install` in /gprc is executed before running this test
|
||||||
|
mvn test
|
||||||
73
grpc/tests/pom.xml
Normal file
73
grpc/tests/pom.xml
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>com.google.flatbuffers</groupId>
|
||||||
|
<artifactId>flatbuffers-parent</artifactId>
|
||||||
|
<version>1.8.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.8.0</gRPC.version>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.flatbuffers</groupId>
|
||||||
|
<artifactId>flatbuffers-java</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.flatbuffers</groupId>
|
||||||
|
<artifactId>flatbuffers-java-grpc</artifactId>
|
||||||
|
<version>${project.parent.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.grpc</groupId>
|
||||||
|
<artifactId>grpc-stub</artifactId>
|
||||||
|
<version>${gRPC.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.grpc</groupId>
|
||||||
|
<artifactId>grpc-netty</artifactId>
|
||||||
|
<version>${gRPC.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<version>4.12</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
|
<artifactId>build-helper-maven-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>add-source</id>
|
||||||
|
<phase>generate-sources</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>add-test-source</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<sources>
|
||||||
|
<source>${project.basedir}</source>
|
||||||
|
<source>${project.basedir}/../../tests</source>
|
||||||
|
</sources>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
<!--<testSourceDirectory>${project.basedir}</testSourceDirectory>-->
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
|
|
||||||
@@ -1,20 +1,36 @@
|
|||||||
#ifndef FLATBUFFERS_BASE_H_
|
#ifndef FLATBUFFERS_BASE_H_
|
||||||
#define FLATBUFFERS_BASE_H_
|
#define FLATBUFFERS_BASE_H_
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
|
||||||
|
defined(_MSC_VER) && defined(_DEBUG)
|
||||||
|
#define _CRTDBG_MAP_ALLOC
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#ifndef ARDUINO
|
#ifndef ARDUINO
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <string>
|
|
||||||
#ifndef ARDUINO
|
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
|
||||||
#include <utility>
|
defined(_MSC_VER) && defined(_DEBUG)
|
||||||
#else
|
#include <crtdbg.h>
|
||||||
#include <utility.h>
|
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
|
||||||
|
#define new DEBUG_NEW
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H)
|
||||||
|
#include <utility.h>
|
||||||
|
#else
|
||||||
|
#include <utility>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <set>
|
#include <set>
|
||||||
@@ -29,6 +45,8 @@
|
|||||||
#include <functional>
|
#include <functional>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "flatbuffers/stl_emulation.h"
|
||||||
|
|
||||||
/// @cond FLATBUFFERS_INTERNAL
|
/// @cond FLATBUFFERS_INTERNAL
|
||||||
#if __cplusplus <= 199711L && \
|
#if __cplusplus <= 199711L && \
|
||||||
(!defined(_MSC_VER) || _MSC_VER < 1600) && \
|
(!defined(_MSC_VER) || _MSC_VER < 1600) && \
|
||||||
@@ -82,7 +100,7 @@
|
|||||||
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
|
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
|
||||||
|
|
||||||
#define FLATBUFFERS_VERSION_MAJOR 1
|
#define FLATBUFFERS_VERSION_MAJOR 1
|
||||||
#define FLATBUFFERS_VERSION_MINOR 7
|
#define FLATBUFFERS_VERSION_MINOR 9
|
||||||
#define FLATBUFFERS_VERSION_REVISION 0
|
#define FLATBUFFERS_VERSION_REVISION 0
|
||||||
#define FLATBUFFERS_STRING_EXPAND(X) #X
|
#define FLATBUFFERS_STRING_EXPAND(X) #X
|
||||||
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
|
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
|
||||||
@@ -103,6 +121,13 @@
|
|||||||
#define FLATBUFFERS_CONSTEXPR
|
#define FLATBUFFERS_CONSTEXPR
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (defined(__cplusplus) && __cplusplus >= 201402L) || \
|
||||||
|
(defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
|
||||||
|
#define FLATBUFFERS_CONSTEXPR_CPP14 FLATBUFFERS_CONSTEXPR
|
||||||
|
#else
|
||||||
|
#define FLATBUFFERS_CONSTEXPR_CPP14
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46 || \
|
#if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46 || \
|
||||||
defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026
|
defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026
|
||||||
#define FLATBUFFERS_NOEXCEPT noexcept
|
#define FLATBUFFERS_NOEXCEPT noexcept
|
||||||
@@ -120,8 +145,8 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable: 4127) // C4127: conditional expression is constant
|
#pragma warning(disable: 4127) // C4127: conditional expression is constant
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// @endcond
|
/// @endcond
|
||||||
@@ -150,6 +175,45 @@ typedef uintmax_t largest_scalar_t;
|
|||||||
// We support aligning the contents of buffers up to this size.
|
// We support aligning the contents of buffers up to this size.
|
||||||
#define FLATBUFFERS_MAX_ALIGNMENT 16
|
#define FLATBUFFERS_MAX_ALIGNMENT 16
|
||||||
|
|
||||||
|
template<typename T> T EndianSwap(T t) {
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
|
||||||
|
#define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
|
||||||
|
#define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
|
||||||
|
#else
|
||||||
|
#if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__)
|
||||||
|
// __builtin_bswap16 was missing prior to GCC 4.8.
|
||||||
|
#define FLATBUFFERS_BYTESWAP16(x) \
|
||||||
|
static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16))
|
||||||
|
#else
|
||||||
|
#define FLATBUFFERS_BYTESWAP16 __builtin_bswap16
|
||||||
|
#endif
|
||||||
|
#define FLATBUFFERS_BYTESWAP32 __builtin_bswap32
|
||||||
|
#define FLATBUFFERS_BYTESWAP64 __builtin_bswap64
|
||||||
|
#endif
|
||||||
|
if (sizeof(T) == 1) { // Compile-time if-then's.
|
||||||
|
return t;
|
||||||
|
} else if (sizeof(T) == 2) {
|
||||||
|
union { T t; uint16_t i; } u;
|
||||||
|
u.t = t;
|
||||||
|
u.i = FLATBUFFERS_BYTESWAP16(u.i);
|
||||||
|
return u.t;
|
||||||
|
} else if (sizeof(T) == 4) {
|
||||||
|
union { T t; uint32_t i; } u;
|
||||||
|
u.t = t;
|
||||||
|
u.i = FLATBUFFERS_BYTESWAP32(u.i);
|
||||||
|
return u.t;
|
||||||
|
} else if (sizeof(T) == 8) {
|
||||||
|
union { T t; uint64_t i; } u;
|
||||||
|
u.t = t;
|
||||||
|
u.i = FLATBUFFERS_BYTESWAP64(u.i);
|
||||||
|
return u.t;
|
||||||
|
} else {
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template<typename T> T EndianScalar(T t) {
|
template<typename T> T EndianScalar(T t) {
|
||||||
#if FLATBUFFERS_LITTLEENDIAN
|
#if FLATBUFFERS_LITTLEENDIAN
|
||||||
return t;
|
return t;
|
||||||
@@ -173,5 +237,5 @@ inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
|
|||||||
return ((~buf_size) + 1) & (scalar_size - 1);
|
return ((~buf_size) + 1) & (scalar_size - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
} // namespace flatbuffers
|
||||||
#endif // FLATBUFFERS_BASE_H_
|
#endif // FLATBUFFERS_BASE_H_
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class CodeWriter {
|
|||||||
// Associates a key with a value. All subsequent calls to operator+=, where
|
// Associates a key with a value. All subsequent calls to operator+=, where
|
||||||
// the specified key is contained in {{ and }} delimiters will be replaced by
|
// the specified key is contained in {{ and }} delimiters will be replaced by
|
||||||
// the given value.
|
// the given value.
|
||||||
void SetValue(const std::string& key, const std::string& value) {
|
void SetValue(const std::string &key, const std::string &value) {
|
||||||
value_map_[key] = value;
|
value_map_[key] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,8 +71,7 @@ class BaseGenerator {
|
|||||||
public:
|
public:
|
||||||
virtual bool generate() = 0;
|
virtual bool generate() = 0;
|
||||||
|
|
||||||
static std::string NamespaceDir(const Parser &parser,
|
static std::string NamespaceDir(const Parser &parser, const std::string &path,
|
||||||
const std::string &path,
|
|
||||||
const Namespace &ns);
|
const Namespace &ns);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -128,8 +127,7 @@ struct CommentConfig {
|
|||||||
};
|
};
|
||||||
|
|
||||||
extern void GenComment(const std::vector<std::string> &dc,
|
extern void GenComment(const std::vector<std::string> &dc,
|
||||||
std::string *code_ptr,
|
std::string *code_ptr, const CommentConfig *config,
|
||||||
const CommentConfig *config,
|
|
||||||
const char *prefix = "");
|
const char *prefix = "");
|
||||||
|
|
||||||
} // namespace flatbuffers
|
} // namespace flatbuffers
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -14,15 +14,15 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "flatbuffers/flatbuffers.h"
|
|
||||||
#include "flatbuffers/idl.h"
|
|
||||||
#include "flatbuffers/util.h"
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include "flatbuffers/flatbuffers.h"
|
||||||
|
#include "flatbuffers/idl.h"
|
||||||
|
#include "flatbuffers/util.h"
|
||||||
|
|
||||||
#ifndef FLATC_H_
|
#ifndef FLATC_H_
|
||||||
#define FLATC_H_
|
# define FLATC_H_
|
||||||
|
|
||||||
namespace flatbuffers {
|
namespace flatbuffers {
|
||||||
|
|
||||||
@@ -49,12 +49,10 @@ class FlatCompiler {
|
|||||||
MakeRuleFn make_rule;
|
MakeRuleFn make_rule;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef void (*WarnFn)(const FlatCompiler *flatc,
|
typedef void (*WarnFn)(const FlatCompiler *flatc, const std::string &warn,
|
||||||
const std::string &warn,
|
|
||||||
bool show_exe_name);
|
bool show_exe_name);
|
||||||
|
|
||||||
typedef void (*ErrorFn)(const FlatCompiler *flatc,
|
typedef void (*ErrorFn)(const FlatCompiler *flatc, const std::string &err,
|
||||||
const std::string &err,
|
|
||||||
bool usage, bool show_exe_name);
|
bool usage, bool show_exe_name);
|
||||||
|
|
||||||
// Parameters required to initialize the FlatCompiler.
|
// Parameters required to initialize the FlatCompiler.
|
||||||
@@ -65,21 +63,20 @@ class FlatCompiler {
|
|||||||
warn_fn(nullptr),
|
warn_fn(nullptr),
|
||||||
error_fn(nullptr) {}
|
error_fn(nullptr) {}
|
||||||
|
|
||||||
const Generator* generators;
|
const Generator *generators;
|
||||||
size_t num_generators;
|
size_t num_generators;
|
||||||
WarnFn warn_fn;
|
WarnFn warn_fn;
|
||||||
ErrorFn error_fn;
|
ErrorFn error_fn;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit FlatCompiler(const InitParams& params) : params_(params) {}
|
explicit FlatCompiler(const InitParams ¶ms) : params_(params) {}
|
||||||
|
|
||||||
int Compile(int argc, const char** argv);
|
int Compile(int argc, const char **argv);
|
||||||
|
|
||||||
std::string GetUsageString(const char* program_name) const;
|
std::string GetUsageString(const char *program_name) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ParseFile(flatbuffers::Parser &parser,
|
void ParseFile(flatbuffers::Parser &parser, const std::string &filename,
|
||||||
const std::string &filename,
|
|
||||||
const std::string &contents,
|
const std::string &contents,
|
||||||
std::vector<const char *> &include_directories) const;
|
std::vector<const char *> &include_directories) const;
|
||||||
|
|
||||||
@@ -91,7 +88,6 @@ class FlatCompiler {
|
|||||||
InitParams params_;
|
InitParams params_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
} // namespace flatbuffers
|
||||||
|
|
||||||
#endif // FLATC_H_
|
#endif // FLATC_H_
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -30,13 +30,12 @@ namespace grpc {
|
|||||||
// `grpc_slice` and also provides flatbuffers-specific helpers such as `Verify`
|
// `grpc_slice` and also provides flatbuffers-specific helpers such as `Verify`
|
||||||
// and `GetRoot`. Since it is backed by a `grpc_slice`, the underlying buffer
|
// and `GetRoot`. Since it is backed by a `grpc_slice`, the underlying buffer
|
||||||
// is refcounted and ownership is be managed automatically.
|
// is refcounted and ownership is be managed automatically.
|
||||||
template <class T>
|
template<class T> class Message {
|
||||||
class Message {
|
|
||||||
public:
|
public:
|
||||||
Message() : slice_(grpc_empty_slice()) {}
|
Message() : slice_(grpc_empty_slice()) {}
|
||||||
|
|
||||||
Message(grpc_slice slice, bool add_ref)
|
Message(grpc_slice slice, bool add_ref)
|
||||||
: slice_(add_ref ? grpc_slice_ref(slice) : slice) {}
|
: slice_(add_ref ? grpc_slice_ref(slice) : slice) {}
|
||||||
|
|
||||||
Message &operator=(const Message &other) = delete;
|
Message &operator=(const Message &other) = delete;
|
||||||
|
|
||||||
@@ -105,14 +104,16 @@ class SliceAllocator : public Allocator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
|
virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
|
||||||
size_t new_size) override {
|
size_t new_size, size_t in_use_back,
|
||||||
|
size_t in_use_front) override {
|
||||||
assert(old_p == GRPC_SLICE_START_PTR(slice_));
|
assert(old_p == GRPC_SLICE_START_PTR(slice_));
|
||||||
assert(old_size == GRPC_SLICE_LENGTH(slice_));
|
assert(old_size == GRPC_SLICE_LENGTH(slice_));
|
||||||
assert(new_size > old_size);
|
assert(new_size > old_size);
|
||||||
grpc_slice old_slice = slice_;
|
grpc_slice old_slice = slice_;
|
||||||
grpc_slice new_slice = grpc_slice_malloc(new_size);
|
grpc_slice new_slice = grpc_slice_malloc(new_size);
|
||||||
uint8_t *new_p = GRPC_SLICE_START_PTR(new_slice);
|
uint8_t *new_p = GRPC_SLICE_START_PTR(new_slice);
|
||||||
memcpy(new_p + (new_size - old_size), old_p, old_size);
|
memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
|
||||||
|
in_use_front);
|
||||||
slice_ = new_slice;
|
slice_ = new_slice;
|
||||||
grpc_slice_unref(old_slice);
|
grpc_slice_unref(old_slice);
|
||||||
return new_p;
|
return new_p;
|
||||||
@@ -137,7 +138,7 @@ namespace detail {
|
|||||||
struct SliceAllocatorMember {
|
struct SliceAllocatorMember {
|
||||||
SliceAllocator slice_allocator_;
|
SliceAllocator slice_allocator_;
|
||||||
};
|
};
|
||||||
}
|
} // namespace detail
|
||||||
|
|
||||||
// MessageBuilder is a gRPC-specific FlatBufferBuilder that uses SliceAllocator
|
// MessageBuilder is a gRPC-specific FlatBufferBuilder that uses SliceAllocator
|
||||||
// to allocate gRPC buffers.
|
// to allocate gRPC buffers.
|
||||||
@@ -145,7 +146,7 @@ class MessageBuilder : private detail::SliceAllocatorMember,
|
|||||||
public FlatBufferBuilder {
|
public FlatBufferBuilder {
|
||||||
public:
|
public:
|
||||||
explicit MessageBuilder(uoffset_t initial_size = 1024)
|
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(const MessageBuilder &other) = delete;
|
||||||
MessageBuilder &operator=(const MessageBuilder &other) = delete;
|
MessageBuilder &operator=(const MessageBuilder &other) = delete;
|
||||||
@@ -155,9 +156,8 @@ class MessageBuilder : private detail::SliceAllocatorMember,
|
|||||||
// GetMessage extracts the subslice of the buffer corresponding to the
|
// GetMessage extracts the subslice of the buffer corresponding to the
|
||||||
// flatbuffers-encoded region and wraps it in a `Message<T>` to handle buffer
|
// flatbuffers-encoded region and wraps it in a `Message<T>` to handle buffer
|
||||||
// ownership.
|
// ownership.
|
||||||
template <class T>
|
template<class T> Message<T> GetMessage() {
|
||||||
Message<T> GetMessage() {
|
auto buf_data = buf_.scratch_data(); // pointer to memory
|
||||||
auto buf_data = buf_.buf(); // pointer to memory
|
|
||||||
auto buf_size = buf_.capacity(); // size of memory
|
auto buf_size = buf_.capacity(); // size of memory
|
||||||
auto msg_data = buf_.data(); // pointer to msg
|
auto msg_data = buf_.data(); // pointer to msg
|
||||||
auto msg_size = buf_.size(); // size of msg
|
auto msg_size = buf_.size(); // size of msg
|
||||||
@@ -178,8 +178,7 @@ class MessageBuilder : private detail::SliceAllocatorMember,
|
|||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template<class T> Message<T> ReleaseMessage() {
|
||||||
Message<T> ReleaseMessage() {
|
|
||||||
Message<T> msg = GetMessage<T>();
|
Message<T> msg = GetMessage<T>();
|
||||||
Reset();
|
Reset();
|
||||||
return msg;
|
return msg;
|
||||||
@@ -194,8 +193,7 @@ class MessageBuilder : private detail::SliceAllocatorMember,
|
|||||||
|
|
||||||
namespace grpc {
|
namespace grpc {
|
||||||
|
|
||||||
template <class T>
|
template<class T> class SerializationTraits<flatbuffers::grpc::Message<T>> {
|
||||||
class SerializationTraits<flatbuffers::grpc::Message<T>> {
|
|
||||||
public:
|
public:
|
||||||
static grpc::Status Serialize(const flatbuffers::grpc::Message<T> &msg,
|
static grpc::Status Serialize(const flatbuffers::grpc::Message<T> &msg,
|
||||||
grpc_byte_buffer **buffer, bool *own_buffer) {
|
grpc_byte_buffer **buffer, bool *own_buffer) {
|
||||||
@@ -237,19 +235,19 @@ class SerializationTraits<flatbuffers::grpc::Message<T>> {
|
|||||||
*msg = flatbuffers::grpc::Message<T>(slice, false);
|
*msg = flatbuffers::grpc::Message<T>(slice, false);
|
||||||
}
|
}
|
||||||
grpc_byte_buffer_destroy(buffer);
|
grpc_byte_buffer_destroy(buffer);
|
||||||
#if FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
|
#if FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
|
||||||
return ::grpc::Status::OK;
|
return ::grpc::Status::OK;
|
||||||
#else
|
#else
|
||||||
if (msg->Verify()) {
|
if (msg->Verify()) {
|
||||||
return ::grpc::Status::OK;
|
return ::grpc::Status::OK;
|
||||||
} else {
|
} else {
|
||||||
return ::grpc::Status(::grpc::StatusCode::INTERNAL,
|
return ::grpc::Status(::grpc::StatusCode::INTERNAL,
|
||||||
"Message verification failed");
|
"Message verification failed");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace grpc;
|
} // namespace grpc
|
||||||
|
|
||||||
#endif // FLATBUFFERS_GRPC_H_
|
#endif // FLATBUFFERS_GRPC_H_
|
||||||
|
|||||||
@@ -24,26 +24,22 @@
|
|||||||
|
|
||||||
namespace flatbuffers {
|
namespace flatbuffers {
|
||||||
|
|
||||||
template <typename T>
|
template<typename T> struct FnvTraits {
|
||||||
struct FnvTraits {
|
|
||||||
static const T kFnvPrime;
|
static const T kFnvPrime;
|
||||||
static const T kOffsetBasis;
|
static const T kOffsetBasis;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template<> struct FnvTraits<uint32_t> {
|
||||||
struct FnvTraits<uint32_t> {
|
|
||||||
static const uint32_t kFnvPrime = 0x01000193;
|
static const uint32_t kFnvPrime = 0x01000193;
|
||||||
static const uint32_t kOffsetBasis = 0x811C9DC5;
|
static const uint32_t kOffsetBasis = 0x811C9DC5;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <>
|
template<> struct FnvTraits<uint64_t> {
|
||||||
struct FnvTraits<uint64_t> {
|
|
||||||
static const uint64_t kFnvPrime = 0x00000100000001b3ULL;
|
static const uint64_t kFnvPrime = 0x00000100000001b3ULL;
|
||||||
static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL;
|
static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template<typename T> FLATBUFFERS_CONSTEXPR_CPP14 T HashFnv1(const char *input) {
|
||||||
T HashFnv1(const char *input) {
|
|
||||||
T hash = FnvTraits<T>::kOffsetBasis;
|
T hash = FnvTraits<T>::kOffsetBasis;
|
||||||
for (const char *c = input; *c; ++c) {
|
for (const char *c = input; *c; ++c) {
|
||||||
hash *= FnvTraits<T>::kFnvPrime;
|
hash *= FnvTraits<T>::kFnvPrime;
|
||||||
@@ -52,8 +48,7 @@ T HashFnv1(const char *input) {
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template<typename T> FLATBUFFERS_CONSTEXPR_CPP14 T HashFnv1a(const char *input) {
|
||||||
T HashFnv1a(const char *input) {
|
|
||||||
T hash = FnvTraits<T>::kOffsetBasis;
|
T hash = FnvTraits<T>::kOffsetBasis;
|
||||||
for (const char *c = input; *c; ++c) {
|
for (const char *c = input; *c; ++c) {
|
||||||
hash ^= static_cast<unsigned char>(*c);
|
hash ^= static_cast<unsigned char>(*c);
|
||||||
@@ -62,24 +57,49 @@ T HashFnv1a(const char *input) {
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <> FLATBUFFERS_CONSTEXPR_CPP14 inline uint16_t HashFnv1<uint16_t>(const char *input) {
|
||||||
struct NamedHashFunction {
|
uint32_t hash = HashFnv1<uint32_t>(input);
|
||||||
|
return (hash >> 16) ^ (hash & 0xffff);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <> FLATBUFFERS_CONSTEXPR_CPP14 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 {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
typedef T (*HashFunction)(const char*);
|
typedef T (*HashFunction)(const char *);
|
||||||
HashFunction function;
|
HashFunction function;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const NamedHashFunction<uint16_t> kHashFunctions16[] = {
|
||||||
|
{ "fnv1_16", HashFnv1<uint16_t> },
|
||||||
|
{ "fnv1a_16", HashFnv1a<uint16_t> },
|
||||||
|
};
|
||||||
|
|
||||||
const NamedHashFunction<uint32_t> kHashFunctions32[] = {
|
const NamedHashFunction<uint32_t> kHashFunctions32[] = {
|
||||||
{ "fnv1_32", HashFnv1<uint32_t> },
|
{ "fnv1_32", HashFnv1<uint32_t> },
|
||||||
{ "fnv1a_32", HashFnv1a<uint32_t> },
|
{ "fnv1a_32", HashFnv1a<uint32_t> },
|
||||||
};
|
};
|
||||||
|
|
||||||
const NamedHashFunction<uint64_t> kHashFunctions64[] = {
|
const NamedHashFunction<uint64_t> kHashFunctions64[] = {
|
||||||
{ "fnv1_64", HashFnv1<uint64_t> },
|
{ "fnv1_64", HashFnv1<uint64_t> },
|
||||||
{ "fnv1a_64", HashFnv1a<uint64_t> },
|
{ "fnv1a_64", HashFnv1a<uint64_t> },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline NamedHashFunction<uint16_t>::HashFunction FindHashFunction16(
|
||||||
|
const char *name) {
|
||||||
|
std::size_t size = sizeof(kHashFunctions16) / sizeof(kHashFunctions16[0]);
|
||||||
|
for (std::size_t i = 0; i < size; ++i) {
|
||||||
|
if (std::strcmp(name, kHashFunctions16[i].name) == 0) {
|
||||||
|
return kHashFunctions16[i].function;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
inline NamedHashFunction<uint32_t>::HashFunction FindHashFunction32(
|
inline NamedHashFunction<uint32_t>::HashFunction FindHashFunction32(
|
||||||
const char *name) {
|
const char *name) {
|
||||||
std::size_t size = sizeof(kHashFunctions32) / sizeof(kHashFunctions32[0]);
|
std::size_t size = sizeof(kHashFunctions32) / sizeof(kHashFunctions32[0]);
|
||||||
|
|||||||
@@ -18,14 +18,18 @@
|
|||||||
#define FLATBUFFERS_IDL_H_
|
#define FLATBUFFERS_IDL_H_
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <stack>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <functional>
|
#include <stack>
|
||||||
|
|
||||||
|
#include "flatbuffers/base.h"
|
||||||
#include "flatbuffers/flatbuffers.h"
|
#include "flatbuffers/flatbuffers.h"
|
||||||
|
#include "flatbuffers/flexbuffers.h"
|
||||||
#include "flatbuffers/hash.h"
|
#include "flatbuffers/hash.h"
|
||||||
#include "flatbuffers/reflection.h"
|
#include "flatbuffers/reflection.h"
|
||||||
#include "flatbuffers/flexbuffers.h"
|
|
||||||
|
#if !defined(FLATBUFFERS_CPP98_STL)
|
||||||
|
# include <functional>
|
||||||
|
#endif // !defined(FLATBUFFERS_CPP98_STL)
|
||||||
|
|
||||||
// This file defines the data types representing a parsed IDL (Interface
|
// This file defines the data types representing a parsed IDL (Interface
|
||||||
// Definition Language) / schema file.
|
// Definition Language) / schema file.
|
||||||
@@ -35,6 +39,7 @@ namespace flatbuffers {
|
|||||||
// The order of these matters for Is*() functions below.
|
// The order of these matters for Is*() functions below.
|
||||||
// Additionally, Parser::ParseType assumes bool..string is a contiguous range
|
// Additionally, Parser::ParseType assumes bool..string is a contiguous range
|
||||||
// of type tokens.
|
// of type tokens.
|
||||||
|
// clang-format off
|
||||||
#define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
|
#define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
|
||||||
TD(NONE, "", uint8_t, byte, byte, byte, uint8) \
|
TD(NONE, "", uint8_t, byte, byte, byte, uint8) \
|
||||||
TD(UTYPE, "", uint8_t, byte, byte, byte, uint8) /* begin scalar/int */ \
|
TD(UTYPE, "", uint8_t, byte, byte, byte, uint8) /* begin scalar/int */ \
|
||||||
@@ -105,13 +110,13 @@ inline bool IsFloat (BaseType t) { return t == BASE_TYPE_FLOAT ||
|
|||||||
t == BASE_TYPE_DOUBLE; }
|
t == BASE_TYPE_DOUBLE; }
|
||||||
inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
|
inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
|
||||||
t == BASE_TYPE_ULONG; }
|
t == BASE_TYPE_ULONG; }
|
||||||
|
inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; }
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
extern const char *const kTypeNames[];
|
extern const char *const kTypeNames[];
|
||||||
extern const char kTypeSizes[];
|
extern const char kTypeSizes[];
|
||||||
|
|
||||||
inline size_t SizeOf(BaseType t) {
|
inline size_t SizeOf(BaseType t) { return kTypeSizes[t]; }
|
||||||
return kTypeSizes[t];
|
|
||||||
}
|
|
||||||
|
|
||||||
struct StructDef;
|
struct StructDef;
|
||||||
struct EnumDef;
|
struct EnumDef;
|
||||||
@@ -120,13 +125,12 @@ class Parser;
|
|||||||
// Represents any type in the IDL, which is a combination of the BaseType
|
// Represents any type in the IDL, which is a combination of the BaseType
|
||||||
// and additional information for vectors/structs_.
|
// and additional information for vectors/structs_.
|
||||||
struct Type {
|
struct Type {
|
||||||
explicit Type(BaseType _base_type = BASE_TYPE_NONE,
|
explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr,
|
||||||
StructDef *_sd = nullptr, EnumDef *_ed = nullptr)
|
EnumDef *_ed = nullptr)
|
||||||
: base_type(_base_type),
|
: base_type(_base_type),
|
||||||
element(BASE_TYPE_NONE),
|
element(BASE_TYPE_NONE),
|
||||||
struct_def(_sd),
|
struct_def(_sd),
|
||||||
enum_def(_ed)
|
enum_def(_ed) {}
|
||||||
{}
|
|
||||||
|
|
||||||
bool operator==(const Type &o) {
|
bool operator==(const Type &o) {
|
||||||
return base_type == o.base_type && element == o.element &&
|
return base_type == o.base_type && element == o.element &&
|
||||||
@@ -146,8 +150,9 @@ struct Type {
|
|||||||
|
|
||||||
// Represents a parsed scalar value, it's type, and field offset.
|
// Represents a parsed scalar value, it's type, and field offset.
|
||||||
struct Value {
|
struct Value {
|
||||||
Value() : constant("0"), offset(static_cast<voffset_t>(
|
Value()
|
||||||
~(static_cast<voffset_t>(0U)))) {}
|
: constant("0"),
|
||||||
|
offset(static_cast<voffset_t>(~(static_cast<voffset_t>(0U)))) {}
|
||||||
Type type;
|
Type type;
|
||||||
std::string constant;
|
std::string constant;
|
||||||
voffset_t offset;
|
voffset_t offset;
|
||||||
@@ -158,13 +163,11 @@ struct Value {
|
|||||||
template<typename T> class SymbolTable {
|
template<typename T> class SymbolTable {
|
||||||
public:
|
public:
|
||||||
~SymbolTable() {
|
~SymbolTable() {
|
||||||
for (auto it = vec.begin(); it != vec.end(); ++it) {
|
for (auto it = vec.begin(); it != vec.end(); ++it) { delete *it; }
|
||||||
delete *it;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Add(const std::string &name, T *e) {
|
bool Add(const std::string &name, T *e) {
|
||||||
vec.emplace_back(e);
|
vector_emplace_back(&vec, e);
|
||||||
auto it = dict.find(name);
|
auto it = dict.find(name);
|
||||||
if (it != dict.end()) return true;
|
if (it != dict.end()) return true;
|
||||||
dict[name] = e;
|
dict[name] = e;
|
||||||
@@ -188,13 +191,13 @@ template<typename T> class SymbolTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::map<std::string, T *> dict; // quick lookup
|
std::map<std::string, T *> dict; // quick lookup
|
||||||
std::vector<T *> vec; // Used to iterate in order of insertion
|
std::vector<T *> vec; // Used to iterate in order of insertion
|
||||||
};
|
};
|
||||||
|
|
||||||
// A name space, as set in the schema.
|
// A name space, as set in the schema.
|
||||||
struct Namespace {
|
struct Namespace {
|
||||||
std::vector<std::string> components;
|
Namespace() : from_table(0) {}
|
||||||
|
|
||||||
// Given a (potentally unqualified) name, return the "fully qualified" name
|
// Given a (potentally unqualified) name, return the "fully qualified" name
|
||||||
// which has a full namespaced descriptor.
|
// which has a full namespaced descriptor.
|
||||||
@@ -202,17 +205,23 @@ struct Namespace {
|
|||||||
// the current namespace has.
|
// the current namespace has.
|
||||||
std::string GetFullyQualifiedName(const std::string &name,
|
std::string GetFullyQualifiedName(const std::string &name,
|
||||||
size_t max_components = 1000) const;
|
size_t max_components = 1000) const;
|
||||||
|
|
||||||
|
std::vector<std::string> components;
|
||||||
|
size_t from_table; // Part of the namespace corresponds to a message/table.
|
||||||
};
|
};
|
||||||
|
|
||||||
// Base class for all definition types (fields, structs_, enums_).
|
// Base class for all definition types (fields, structs_, enums_).
|
||||||
struct Definition {
|
struct Definition {
|
||||||
Definition() : generated(false), defined_namespace(nullptr),
|
Definition()
|
||||||
serialized_location(0), index(-1) {}
|
: generated(false),
|
||||||
|
defined_namespace(nullptr),
|
||||||
|
serialized_location(0),
|
||||||
|
index(-1),
|
||||||
|
refcount(1) {}
|
||||||
|
|
||||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<
|
flatbuffers::Offset<
|
||||||
reflection::KeyValue>>>
|
flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
|
||||||
SerializeAttributes(FlatBufferBuilder *builder,
|
SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||||
const Parser &parser) const;
|
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string file;
|
std::string file;
|
||||||
@@ -224,35 +233,42 @@ struct Definition {
|
|||||||
// For use with Serialize()
|
// For use with Serialize()
|
||||||
uoffset_t serialized_location;
|
uoffset_t serialized_location;
|
||||||
int index; // Inside the vector it is stored.
|
int index; // Inside the vector it is stored.
|
||||||
|
int refcount;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FieldDef : public Definition {
|
struct FieldDef : public Definition {
|
||||||
FieldDef() : deprecated(false), required(false), key(false),
|
FieldDef()
|
||||||
flexbuffer(false), padding(0) {}
|
: deprecated(false),
|
||||||
|
required(false),
|
||||||
|
key(false),
|
||||||
|
native_inline(false),
|
||||||
|
flexbuffer(false),
|
||||||
|
nested_flatbuffer(NULL),
|
||||||
|
padding(0) {}
|
||||||
|
|
||||||
Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
|
Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
|
||||||
const Parser &parser) const;
|
const Parser &parser) const;
|
||||||
|
|
||||||
Value value;
|
Value value;
|
||||||
bool deprecated; // Field is allowed to be present in old data, but can't be.
|
bool deprecated; // Field is allowed to be present in old data, but can't be.
|
||||||
// written in new data nor accessed in new code.
|
// written in new data nor accessed in new code.
|
||||||
bool required; // Field must always be present.
|
bool required; // Field must always be present.
|
||||||
bool key; // Field functions as a key for creating sorted vectors.
|
bool key; // Field functions as a key for creating sorted vectors.
|
||||||
bool native_inline; // Field will be defined inline (instead of as a pointer)
|
bool native_inline; // Field will be defined inline (instead of as a pointer)
|
||||||
// for native tables if field is a struct.
|
// for native tables if field is a struct.
|
||||||
bool flexbuffer; // This field contains FlexBuffer data.
|
bool flexbuffer; // This field contains FlexBuffer data.
|
||||||
size_t padding; // Bytes to always pad after this field.
|
StructDef *nested_flatbuffer; // This field contains nested FlatBuffer data.
|
||||||
|
size_t padding; // Bytes to always pad after this field.
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StructDef : public Definition {
|
struct StructDef : public Definition {
|
||||||
StructDef()
|
StructDef()
|
||||||
: fixed(false),
|
: fixed(false),
|
||||||
predecl(true),
|
predecl(true),
|
||||||
sortbysize(true),
|
sortbysize(true),
|
||||||
has_key(false),
|
has_key(false),
|
||||||
minalign(1),
|
minalign(1),
|
||||||
bytesize(0)
|
bytesize(0) {}
|
||||||
{}
|
|
||||||
|
|
||||||
void PadLastField(size_t min_align) {
|
void PadLastField(size_t min_align) {
|
||||||
auto padding = PaddingBytes(bytesize, min_align);
|
auto padding = PaddingBytes(bytesize, min_align);
|
||||||
@@ -264,12 +280,15 @@ struct StructDef : public Definition {
|
|||||||
const Parser &parser) const;
|
const Parser &parser) const;
|
||||||
|
|
||||||
SymbolTable<FieldDef> fields;
|
SymbolTable<FieldDef> fields;
|
||||||
|
|
||||||
bool fixed; // If it's struct, not a table.
|
bool fixed; // If it's struct, not a table.
|
||||||
bool predecl; // If it's used before it was defined.
|
bool predecl; // If it's used before it was defined.
|
||||||
bool sortbysize; // Whether fields come in the declaration or size order.
|
bool sortbysize; // Whether fields come in the declaration or size order.
|
||||||
bool has_key; // It has a key field.
|
bool has_key; // It has a key field.
|
||||||
size_t minalign; // What the whole object needs to be aligned to.
|
size_t minalign; // What the whole object needs to be aligned to.
|
||||||
size_t bytesize; // Size if fixed.
|
size_t bytesize; // Size if fixed.
|
||||||
|
|
||||||
|
flatbuffers::unique_ptr<std::string> original_location;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool IsStruct(const Type &type) {
|
inline bool IsStruct(const Type &type) {
|
||||||
@@ -285,8 +304,7 @@ inline size_t InlineAlignment(const Type &type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct EnumVal {
|
struct EnumVal {
|
||||||
EnumVal(const std::string &_name, int64_t _val)
|
EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
|
||||||
: name(_name), value(_val) {}
|
|
||||||
|
|
||||||
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder) const;
|
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder) const;
|
||||||
|
|
||||||
@@ -299,13 +317,11 @@ struct EnumVal {
|
|||||||
struct EnumDef : public Definition {
|
struct EnumDef : public Definition {
|
||||||
EnumDef() : is_union(false), uses_type_aliases(false) {}
|
EnumDef() : is_union(false), uses_type_aliases(false) {}
|
||||||
|
|
||||||
EnumVal *ReverseLookup(int enum_idx, bool skip_union_default = true) {
|
EnumVal *ReverseLookup(int64_t enum_idx, bool skip_union_default = true) {
|
||||||
for (auto it = vals.vec.begin() + static_cast<int>(is_union &&
|
for (auto it = vals.vec.begin() +
|
||||||
skip_union_default);
|
static_cast<int>(is_union && skip_union_default);
|
||||||
it != vals.vec.end(); ++it) {
|
it != vals.vec.end(); ++it) {
|
||||||
if ((*it)->value == enum_idx) {
|
if ((*it)->value == enum_idx) { return *it; }
|
||||||
return *it;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@@ -323,14 +339,14 @@ inline bool EqualByName(const Type &a, const Type &b) {
|
|||||||
return a.base_type == b.base_type && a.element == b.element &&
|
return a.base_type == b.base_type && a.element == b.element &&
|
||||||
(a.struct_def == b.struct_def ||
|
(a.struct_def == b.struct_def ||
|
||||||
a.struct_def->name == b.struct_def->name) &&
|
a.struct_def->name == b.struct_def->name) &&
|
||||||
(a.enum_def == b.enum_def ||
|
(a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name);
|
||||||
a.enum_def->name == b.enum_def->name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RPCCall {
|
struct RPCCall {
|
||||||
std::string name;
|
std::string name;
|
||||||
SymbolTable<Value> attributes;
|
SymbolTable<Value> attributes;
|
||||||
StructDef *request, *response;
|
StructDef *request, *response;
|
||||||
|
std::vector<std::string> rpc_comment;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ServiceDef : public Definition {
|
struct ServiceDef : public Definition {
|
||||||
@@ -351,70 +367,86 @@ struct IDLOptions {
|
|||||||
bool mutable_buffer;
|
bool mutable_buffer;
|
||||||
bool one_file;
|
bool one_file;
|
||||||
bool proto_mode;
|
bool proto_mode;
|
||||||
|
bool proto_oneof_union;
|
||||||
bool generate_all;
|
bool generate_all;
|
||||||
bool skip_unexpected_fields_in_json;
|
bool skip_unexpected_fields_in_json;
|
||||||
bool generate_name_strings;
|
bool generate_name_strings;
|
||||||
bool escape_proto_identifiers;
|
|
||||||
bool generate_object_based_api;
|
bool generate_object_based_api;
|
||||||
std::string cpp_object_api_pointer_type;
|
std::string cpp_object_api_pointer_type;
|
||||||
std::string cpp_object_api_string_type;
|
std::string cpp_object_api_string_type;
|
||||||
|
bool gen_nullable;
|
||||||
|
std::string object_prefix;
|
||||||
|
std::string object_suffix;
|
||||||
bool union_value_namespacing;
|
bool union_value_namespacing;
|
||||||
bool allow_non_utf8;
|
bool allow_non_utf8;
|
||||||
std::string include_prefix;
|
std::string include_prefix;
|
||||||
bool keep_include_path;
|
bool keep_include_path;
|
||||||
bool binary_schema_comments;
|
bool binary_schema_comments;
|
||||||
bool skip_flatbuffers_import;
|
bool skip_flatbuffers_import;
|
||||||
|
std::string go_import;
|
||||||
std::string go_namespace;
|
std::string go_namespace;
|
||||||
bool reexport_ts_modules;
|
bool reexport_ts_modules;
|
||||||
bool protobuf_ascii_alike;
|
bool protobuf_ascii_alike;
|
||||||
|
bool size_prefixed;
|
||||||
|
|
||||||
// Possible options for the more general generator below.
|
// Possible options for the more general generator below.
|
||||||
enum Language {
|
enum Language {
|
||||||
kJava = 1 << 0,
|
kJava = 1 << 0,
|
||||||
kCSharp = 1 << 1,
|
kCSharp = 1 << 1,
|
||||||
kGo = 1 << 2,
|
kGo = 1 << 2,
|
||||||
kCpp = 1 << 3,
|
kCpp = 1 << 3,
|
||||||
kJs = 1 << 4,
|
kJs = 1 << 4,
|
||||||
kPython = 1 << 5,
|
kPython = 1 << 5,
|
||||||
kPhp = 1 << 6,
|
kPhp = 1 << 6,
|
||||||
kJson = 1 << 7,
|
kJson = 1 << 7,
|
||||||
kBinary = 1 << 8,
|
kBinary = 1 << 8,
|
||||||
kTs = 1 << 9,
|
kTs = 1 << 9,
|
||||||
|
kJsonSchema = 1 << 10,
|
||||||
kMAX
|
kMAX
|
||||||
};
|
};
|
||||||
|
|
||||||
Language lang;
|
Language lang;
|
||||||
|
|
||||||
|
enum MiniReflect { kNone, kTypes, kTypesAndNames };
|
||||||
|
|
||||||
|
MiniReflect mini_reflect;
|
||||||
|
|
||||||
// The corresponding language bit will be set if a language is included
|
// The corresponding language bit will be set if a language is included
|
||||||
// for code generation.
|
// for code generation.
|
||||||
unsigned long lang_to_generate;
|
unsigned long lang_to_generate;
|
||||||
|
|
||||||
IDLOptions()
|
IDLOptions()
|
||||||
: strict_json(false),
|
: strict_json(false),
|
||||||
skip_js_exports(false),
|
skip_js_exports(false),
|
||||||
use_goog_js_export_format(false),
|
use_goog_js_export_format(false),
|
||||||
output_default_scalars_in_json(false),
|
output_default_scalars_in_json(false),
|
||||||
indent_step(2),
|
indent_step(2),
|
||||||
output_enum_identifiers(true), prefixed_enums(true), scoped_enums(false),
|
output_enum_identifiers(true),
|
||||||
include_dependence_headers(true),
|
prefixed_enums(true),
|
||||||
mutable_buffer(false),
|
scoped_enums(false),
|
||||||
one_file(false),
|
include_dependence_headers(true),
|
||||||
proto_mode(false),
|
mutable_buffer(false),
|
||||||
generate_all(false),
|
one_file(false),
|
||||||
skip_unexpected_fields_in_json(false),
|
proto_mode(false),
|
||||||
generate_name_strings(false),
|
proto_oneof_union(false),
|
||||||
escape_proto_identifiers(false),
|
generate_all(false),
|
||||||
generate_object_based_api(false),
|
skip_unexpected_fields_in_json(false),
|
||||||
cpp_object_api_pointer_type("std::unique_ptr"),
|
generate_name_strings(false),
|
||||||
union_value_namespacing(true),
|
generate_object_based_api(false),
|
||||||
allow_non_utf8(false),
|
cpp_object_api_pointer_type("std::unique_ptr"),
|
||||||
keep_include_path(false),
|
gen_nullable(false),
|
||||||
binary_schema_comments(false),
|
object_suffix("T"),
|
||||||
skip_flatbuffers_import(false),
|
union_value_namespacing(true),
|
||||||
reexport_ts_modules(true),
|
allow_non_utf8(false),
|
||||||
protobuf_ascii_alike(false),
|
keep_include_path(false),
|
||||||
lang(IDLOptions::kJava),
|
binary_schema_comments(false),
|
||||||
lang_to_generate(0) {}
|
skip_flatbuffers_import(false),
|
||||||
|
reexport_ts_modules(true),
|
||||||
|
protobuf_ascii_alike(false),
|
||||||
|
size_prefixed(false),
|
||||||
|
lang(IDLOptions::kJava),
|
||||||
|
mini_reflect(IDLOptions::kNone),
|
||||||
|
lang_to_generate(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// This encapsulates where the parser is in the current source file.
|
// This encapsulates where the parser is in the current source file.
|
||||||
@@ -440,7 +472,7 @@ struct ParserState {
|
|||||||
class CheckedError {
|
class CheckedError {
|
||||||
public:
|
public:
|
||||||
explicit CheckedError(bool error)
|
explicit CheckedError(bool error)
|
||||||
: is_error_(error), has_been_checked_(false) {}
|
: is_error_(error), has_been_checked_(false) {}
|
||||||
|
|
||||||
CheckedError &operator=(const CheckedError &other) {
|
CheckedError &operator=(const CheckedError &other) {
|
||||||
is_error_ = other.is_error_;
|
is_error_ = other.is_error_;
|
||||||
@@ -455,7 +487,10 @@ class CheckedError {
|
|||||||
|
|
||||||
~CheckedError() { assert(has_been_checked_); }
|
~CheckedError() { assert(has_been_checked_); }
|
||||||
|
|
||||||
bool Check() { has_been_checked_ = true; return is_error_; }
|
bool Check() {
|
||||||
|
has_been_checked_ = true;
|
||||||
|
return is_error_;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool is_error_;
|
bool is_error_;
|
||||||
@@ -464,23 +499,29 @@ class CheckedError {
|
|||||||
|
|
||||||
// Additionally, in GCC we can get these errors statically, for additional
|
// Additionally, in GCC we can get these errors statically, for additional
|
||||||
// assurance:
|
// assurance:
|
||||||
|
// clang-format off
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#define FLATBUFFERS_CHECKED_ERROR CheckedError \
|
#define FLATBUFFERS_CHECKED_ERROR CheckedError \
|
||||||
__attribute__((warn_unused_result))
|
__attribute__((warn_unused_result))
|
||||||
#else
|
#else
|
||||||
#define FLATBUFFERS_CHECKED_ERROR CheckedError
|
#define FLATBUFFERS_CHECKED_ERROR CheckedError
|
||||||
#endif
|
#endif
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
class Parser : public ParserState {
|
class Parser : public ParserState {
|
||||||
public:
|
public:
|
||||||
explicit Parser(const IDLOptions &options = IDLOptions())
|
explicit Parser(const IDLOptions &options = IDLOptions())
|
||||||
: root_struct_def_(nullptr),
|
: current_namespace_(nullptr),
|
||||||
opts(options),
|
empty_namespace_(nullptr),
|
||||||
uses_flexbuffers_(false),
|
root_struct_def_(nullptr),
|
||||||
source_(nullptr),
|
opts(options),
|
||||||
anonymous_counter(0) {
|
uses_flexbuffers_(false),
|
||||||
// Just in case none are declared:
|
source_(nullptr),
|
||||||
namespaces_.push_back(new Namespace());
|
anonymous_counter(0) {
|
||||||
|
// Start out with the empty namespace being current.
|
||||||
|
empty_namespace_ = new Namespace();
|
||||||
|
namespaces_.push_back(empty_namespace_);
|
||||||
|
current_namespace_ = empty_namespace_;
|
||||||
known_attributes_["deprecated"] = true;
|
known_attributes_["deprecated"] = true;
|
||||||
known_attributes_["required"] = true;
|
known_attributes_["required"] = true;
|
||||||
known_attributes_["key"] = true;
|
known_attributes_["key"] = true;
|
||||||
@@ -495,8 +536,10 @@ class Parser : public ParserState {
|
|||||||
known_attributes_["idempotent"] = true;
|
known_attributes_["idempotent"] = true;
|
||||||
known_attributes_["cpp_type"] = true;
|
known_attributes_["cpp_type"] = true;
|
||||||
known_attributes_["cpp_ptr_type"] = true;
|
known_attributes_["cpp_ptr_type"] = true;
|
||||||
|
known_attributes_["cpp_ptr_type_get"] = true;
|
||||||
known_attributes_["cpp_str_type"] = true;
|
known_attributes_["cpp_str_type"] = true;
|
||||||
known_attributes_["native_inline"] = true;
|
known_attributes_["native_inline"] = true;
|
||||||
|
known_attributes_["native_custom_alloc"] = true;
|
||||||
known_attributes_["native_type"] = true;
|
known_attributes_["native_type"] = true;
|
||||||
known_attributes_["native_default"] = true;
|
known_attributes_["native_default"] = true;
|
||||||
known_attributes_["flexbuffer"] = true;
|
known_attributes_["flexbuffer"] = true;
|
||||||
@@ -548,14 +591,19 @@ class Parser : public ParserState {
|
|||||||
|
|
||||||
FLATBUFFERS_CHECKED_ERROR CheckInRange(int64_t val, int64_t min, int64_t max);
|
FLATBUFFERS_CHECKED_ERROR CheckInRange(int64_t val, int64_t min, int64_t max);
|
||||||
|
|
||||||
private:
|
StructDef *LookupStruct(const std::string &id) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Message(const std::string &msg);
|
||||||
|
void Warning(const std::string &msg);
|
||||||
FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
|
FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
|
FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
|
||||||
FLATBUFFERS_CHECKED_ERROR Next();
|
FLATBUFFERS_CHECKED_ERROR Next();
|
||||||
FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
|
FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
|
||||||
bool Is(int t);
|
bool Is(int t) const;
|
||||||
|
bool IsIdent(const char *id) const;
|
||||||
FLATBUFFERS_CHECKED_ERROR Expect(int t);
|
FLATBUFFERS_CHECKED_ERROR Expect(int t);
|
||||||
std::string TokenToStringId(int t);
|
std::string TokenToStringId(int t) const;
|
||||||
EnumDef *LookupEnum(const std::string &id);
|
EnumDef *LookupEnum(const std::string &id);
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id,
|
FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id,
|
||||||
std::string *last);
|
std::string *last);
|
||||||
@@ -570,22 +618,45 @@ private:
|
|||||||
FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
|
FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
|
||||||
size_t parent_fieldn,
|
size_t parent_fieldn,
|
||||||
const StructDef *parent_struct_def);
|
const StructDef *parent_struct_def);
|
||||||
|
// clang-format off
|
||||||
|
#if defined(FLATBUFFERS_CPP98_STL)
|
||||||
|
typedef CheckedError (*ParseTableDelimitersBody)(
|
||||||
|
const std::string &name, size_t &fieldn, const StructDef *struct_def,
|
||||||
|
void *state);
|
||||||
|
#else
|
||||||
|
typedef std::function<CheckedError(const std::string&, size_t&,
|
||||||
|
const StructDef*, void*)>
|
||||||
|
ParseTableDelimitersBody;
|
||||||
|
#endif // defined(FLATBUFFERS_CPP98_STL)
|
||||||
|
// clang-format on
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
|
FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
|
||||||
const StructDef *struct_def,
|
const StructDef *struct_def,
|
||||||
const std::function<CheckedError(const std::string &name)> &body);
|
ParseTableDelimitersBody body,
|
||||||
|
void *state);
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
|
FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
|
||||||
std::string *value, uoffset_t *ovalue);
|
std::string *value, uoffset_t *ovalue);
|
||||||
void SerializeStruct(const StructDef &struct_def, const Value &val);
|
void SerializeStruct(const StructDef &struct_def, const Value &val);
|
||||||
void AddVector(bool sortbysize, int count);
|
// clang-format off
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(size_t &count,
|
#if defined(FLATBUFFERS_CPP98_STL)
|
||||||
const std::function<CheckedError()> &body);
|
typedef CheckedError (*ParseVectorDelimitersBody)(size_t &count,
|
||||||
|
void *state);
|
||||||
|
#else
|
||||||
|
typedef std::function<CheckedError(size_t&, void*)>
|
||||||
|
ParseVectorDelimitersBody;
|
||||||
|
#endif // defined(FLATBUFFERS_CPP98_STL)
|
||||||
|
// clang-format on
|
||||||
|
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(
|
||||||
|
size_t &count, ParseVectorDelimitersBody body, void *state);
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue);
|
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue);
|
||||||
|
FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field,
|
||||||
|
size_t fieldn,
|
||||||
|
const StructDef *parent_struct_def);
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
|
FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
|
||||||
FLATBUFFERS_CHECKED_ERROR TryTypedValue(int dtoken, bool check, Value &e,
|
FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken, bool check, Value &e,
|
||||||
BaseType req, bool *destmatch);
|
BaseType req, bool *destmatch);
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef* field);
|
FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef* field);
|
||||||
FLATBUFFERS_CHECKED_ERROR TokenError();
|
FLATBUFFERS_CHECKED_ERROR TokenError();
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseSingleValue(Value &e);
|
FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e);
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(Type &type, int64_t *result);
|
FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(Type &type, int64_t *result);
|
||||||
StructDef *LookupCreateStruct(const std::string &name,
|
StructDef *LookupCreateStruct(const std::string &name,
|
||||||
bool create_if_new = true,
|
bool create_if_new = true,
|
||||||
@@ -594,6 +665,9 @@ private:
|
|||||||
FLATBUFFERS_CHECKED_ERROR ParseNamespace();
|
FLATBUFFERS_CHECKED_ERROR ParseNamespace();
|
||||||
FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
|
FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
|
||||||
StructDef **dest);
|
StructDef **dest);
|
||||||
|
FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name,
|
||||||
|
bool is_union,
|
||||||
|
EnumDef **dest);
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseDecl();
|
FLATBUFFERS_CHECKED_ERROR ParseDecl();
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseService();
|
FLATBUFFERS_CHECKED_ERROR ParseService();
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
|
FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
|
||||||
@@ -607,21 +681,29 @@ private:
|
|||||||
FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder);
|
FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder);
|
||||||
FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source,
|
FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source,
|
||||||
const char *source_filename);
|
const char *source_filename);
|
||||||
FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
|
FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source,
|
||||||
const char **include_paths,
|
const char **include_paths,
|
||||||
const char *source_filename,
|
const char *source_filename);
|
||||||
const char *include_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,
|
FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef*> &fields,
|
||||||
StructDef *struct_def,
|
StructDef *struct_def,
|
||||||
const char *suffix,
|
const char *suffix,
|
||||||
BaseType baseType);
|
BaseType baseType);
|
||||||
|
|
||||||
|
bool SupportsVectorOfUnions() const;
|
||||||
|
Namespace *UniqueNamespace(Namespace *ns);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SymbolTable<Type> types_;
|
SymbolTable<Type> types_;
|
||||||
SymbolTable<StructDef> structs_;
|
SymbolTable<StructDef> structs_;
|
||||||
SymbolTable<EnumDef> enums_;
|
SymbolTable<EnumDef> enums_;
|
||||||
SymbolTable<ServiceDef> services_;
|
SymbolTable<ServiceDef> services_;
|
||||||
std::vector<Namespace *> namespaces_;
|
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
|
FlatBufferBuilder builder_; // any data contained in the file
|
||||||
@@ -676,15 +758,12 @@ extern bool GenerateBinary(const Parser &parser,
|
|||||||
|
|
||||||
// Generate a C++ header from the definitions in the Parser object.
|
// Generate a C++ header from the definitions in the Parser object.
|
||||||
// See idl_gen_cpp.
|
// See idl_gen_cpp.
|
||||||
extern std::string GenerateCPP(const Parser &parser,
|
|
||||||
const std::string &include_guard_ident);
|
|
||||||
extern bool GenerateCPP(const Parser &parser,
|
extern bool GenerateCPP(const Parser &parser,
|
||||||
const std::string &path,
|
const std::string &path,
|
||||||
const std::string &file_name);
|
const std::string &file_name);
|
||||||
|
|
||||||
// Generate JavaScript or TypeScript code from the definitions in the Parser object.
|
// Generate JavaScript or TypeScript code from the definitions in the Parser object.
|
||||||
// See idl_gen_js.
|
// See idl_gen_js.
|
||||||
extern std::string GenerateJS(const Parser &parser);
|
|
||||||
extern bool GenerateJS(const Parser &parser,
|
extern bool GenerateJS(const Parser &parser,
|
||||||
const std::string &path,
|
const std::string &path,
|
||||||
const std::string &file_name);
|
const std::string &file_name);
|
||||||
@@ -695,12 +774,6 @@ extern bool GenerateGo(const Parser &parser,
|
|||||||
const std::string &path,
|
const std::string &path,
|
||||||
const std::string &file_name);
|
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 Php code from the definitions in the Parser object.
|
// Generate Php code from the definitions in the Parser object.
|
||||||
// See idl_gen_php.
|
// See idl_gen_php.
|
||||||
extern bool GeneratePhp(const Parser &parser,
|
extern bool GeneratePhp(const Parser &parser,
|
||||||
@@ -713,9 +786,9 @@ extern bool GeneratePython(const Parser &parser,
|
|||||||
const std::string &path,
|
const std::string &path,
|
||||||
const std::string &file_name);
|
const std::string &file_name);
|
||||||
|
|
||||||
// Generate C# files from the definitions in the Parser object.
|
// Generate Json schema file
|
||||||
// See idl_gen_csharp.cpp.
|
// See idl_gen_json_schema.cpp.
|
||||||
extern bool GenerateCSharp(const Parser &parser,
|
extern bool GenerateJsonSchema(const Parser &parser,
|
||||||
const std::string &path,
|
const std::string &path,
|
||||||
const std::string &file_name);
|
const std::string &file_name);
|
||||||
|
|
||||||
@@ -775,6 +848,12 @@ bool GenerateGoGRPC(const Parser &parser,
|
|||||||
const std::string &path,
|
const std::string &path,
|
||||||
const std::string &file_name);
|
const std::string &file_name);
|
||||||
|
|
||||||
|
// Generate GRPC Java classes.
|
||||||
|
// See idl_gen_grpc.cpp
|
||||||
|
bool GenerateJavaGRPC(const Parser &parser,
|
||||||
|
const std::string &path,
|
||||||
|
const std::string &file_name);
|
||||||
|
|
||||||
} // namespace flatbuffers
|
} // namespace flatbuffers
|
||||||
|
|
||||||
#endif // FLATBUFFERS_IDL_H_
|
#endif // FLATBUFFERS_IDL_H_
|
||||||
|
|||||||
337
include/flatbuffers/minireflect.h
Normal file
337
include/flatbuffers/minireflect.h
Normal file
@@ -0,0 +1,337 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 Google Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FLATBUFFERS_MINIREFLECT_H_
|
||||||
|
#define FLATBUFFERS_MINIREFLECT_H_
|
||||||
|
|
||||||
|
#include "flatbuffers/flatbuffers.h"
|
||||||
|
#include "flatbuffers/util.h"
|
||||||
|
|
||||||
|
namespace flatbuffers {
|
||||||
|
|
||||||
|
// Utilities that can be used with the "mini reflection" tables present
|
||||||
|
// in generated code with --reflect-types (only types) or --reflect-names
|
||||||
|
// (also names).
|
||||||
|
// This allows basic reflection functionality such as pretty-printing
|
||||||
|
// that does not require the use of the schema parser or loading of binary
|
||||||
|
// schema files at runtime (reflection.h).
|
||||||
|
|
||||||
|
// For any of the functions below that take `const TypeTable *`, you pass
|
||||||
|
// `FooTypeTable()` if the type of the root is `Foo`.
|
||||||
|
|
||||||
|
// First, a generic iterator that can be used by multiple algorithms.
|
||||||
|
|
||||||
|
struct IterationVisitor {
|
||||||
|
// These mark the scope of a table or struct.
|
||||||
|
virtual void StartSequence() {}
|
||||||
|
virtual void EndSequence() {}
|
||||||
|
// Called for each field regardless of wether it is present or not.
|
||||||
|
// If not present, val == nullptr. set_idx is the index of all set fields.
|
||||||
|
virtual void Field(size_t /*field_idx*/, size_t /*set_idx*/,
|
||||||
|
ElementaryType /*type*/, bool /*is_vector*/,
|
||||||
|
const TypeTable * /*type_table*/, const char * /*name*/,
|
||||||
|
const uint8_t * /*val*/) {}
|
||||||
|
// Called for a value that is actually present, after a field, or as part
|
||||||
|
// of a vector.
|
||||||
|
virtual void UType(uint8_t, const char *) {}
|
||||||
|
virtual void Bool(bool) {}
|
||||||
|
virtual void Char(int8_t, const char *) {}
|
||||||
|
virtual void UChar(uint8_t, const char *) {}
|
||||||
|
virtual void Short(int16_t, const char *) {}
|
||||||
|
virtual void UShort(uint16_t, const char *) {}
|
||||||
|
virtual void Int(int32_t, const char *) {}
|
||||||
|
virtual void UInt(uint32_t, const char *) {}
|
||||||
|
virtual void Long(int64_t) {}
|
||||||
|
virtual void ULong(uint64_t) {}
|
||||||
|
virtual void Float(float) {}
|
||||||
|
virtual void Double(double) {}
|
||||||
|
virtual void String(const String *) {}
|
||||||
|
virtual void Unknown(const uint8_t *) {} // From a future version.
|
||||||
|
// These mark the scope of a vector.
|
||||||
|
virtual void StartVector() {}
|
||||||
|
virtual void EndVector() {}
|
||||||
|
virtual void Element(size_t /*i*/, ElementaryType /*type*/,
|
||||||
|
const TypeTable * /*type_table*/,
|
||||||
|
const uint8_t * /*val*/) {}
|
||||||
|
virtual ~IterationVisitor() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline size_t InlineSize(ElementaryType type, const TypeTable *type_table) {
|
||||||
|
switch (type) {
|
||||||
|
case ET_UTYPE:
|
||||||
|
case ET_BOOL:
|
||||||
|
case ET_CHAR:
|
||||||
|
case ET_UCHAR: return 1;
|
||||||
|
case ET_SHORT:
|
||||||
|
case ET_USHORT: return 2;
|
||||||
|
case ET_INT:
|
||||||
|
case ET_UINT:
|
||||||
|
case ET_FLOAT:
|
||||||
|
case ET_STRING: return 4;
|
||||||
|
case ET_LONG:
|
||||||
|
case ET_ULONG:
|
||||||
|
case ET_DOUBLE: return 8;
|
||||||
|
case ET_SEQUENCE:
|
||||||
|
switch (type_table->st) {
|
||||||
|
case ST_TABLE:
|
||||||
|
case ST_UNION: return 4;
|
||||||
|
case ST_STRUCT: return type_table->values[type_table->num_elems];
|
||||||
|
default: assert(false); return 1;
|
||||||
|
}
|
||||||
|
default: assert(false); return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int32_t LookupEnum(int32_t enum_val, const int32_t *values,
|
||||||
|
size_t num_values) {
|
||||||
|
if (!values) return enum_val;
|
||||||
|
for (size_t i = 0; i < num_values; i++) {
|
||||||
|
if (enum_val == values[i]) return static_cast<int32_t>(i);
|
||||||
|
}
|
||||||
|
return -1; // Unknown enum value.
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> const char *EnumName(T tval, const TypeTable *type_table) {
|
||||||
|
if (!type_table || !type_table->names) return nullptr;
|
||||||
|
auto i = LookupEnum(static_cast<int32_t>(tval), type_table->values,
|
||||||
|
type_table->num_elems);
|
||||||
|
if (i >= 0 && i < static_cast<int32_t>(type_table->num_elems)) {
|
||||||
|
return type_table->names[i];
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IterateObject(const uint8_t *obj, const TypeTable *type_table,
|
||||||
|
IterationVisitor *visitor);
|
||||||
|
|
||||||
|
inline void IterateValue(ElementaryType type, const uint8_t *val,
|
||||||
|
const TypeTable *type_table, const uint8_t *prev_val,
|
||||||
|
soffset_t vector_index, IterationVisitor *visitor) {
|
||||||
|
switch (type) {
|
||||||
|
case ET_UTYPE: {
|
||||||
|
auto tval = *reinterpret_cast<const uint8_t *>(val);
|
||||||
|
visitor->UType(tval, EnumName(tval, type_table));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_BOOL: {
|
||||||
|
visitor->Bool(*reinterpret_cast<const uint8_t *>(val) != 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_CHAR: {
|
||||||
|
auto tval = *reinterpret_cast<const int8_t *>(val);
|
||||||
|
visitor->Char(tval, EnumName(tval, type_table));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_UCHAR: {
|
||||||
|
auto tval = *reinterpret_cast<const uint8_t *>(val);
|
||||||
|
visitor->UChar(tval, EnumName(tval, type_table));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_SHORT: {
|
||||||
|
auto tval = *reinterpret_cast<const int16_t *>(val);
|
||||||
|
visitor->Short(tval, EnumName(tval, type_table));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_USHORT: {
|
||||||
|
auto tval = *reinterpret_cast<const uint16_t *>(val);
|
||||||
|
visitor->UShort(tval, EnumName(tval, type_table));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_INT: {
|
||||||
|
auto tval = *reinterpret_cast<const int32_t *>(val);
|
||||||
|
visitor->Int(tval, EnumName(tval, type_table));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_UINT: {
|
||||||
|
auto tval = *reinterpret_cast<const uint32_t *>(val);
|
||||||
|
visitor->UInt(tval, EnumName(tval, type_table));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_LONG: {
|
||||||
|
visitor->Long(*reinterpret_cast<const int64_t *>(val));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_ULONG: {
|
||||||
|
visitor->ULong(*reinterpret_cast<const uint64_t *>(val));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_FLOAT: {
|
||||||
|
visitor->Float(*reinterpret_cast<const float *>(val));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_DOUBLE: {
|
||||||
|
visitor->Double(*reinterpret_cast<const double *>(val));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_STRING: {
|
||||||
|
val += ReadScalar<uoffset_t>(val);
|
||||||
|
visitor->String(reinterpret_cast<const String *>(val));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_SEQUENCE: {
|
||||||
|
switch (type_table->st) {
|
||||||
|
case ST_TABLE:
|
||||||
|
val += ReadScalar<uoffset_t>(val);
|
||||||
|
IterateObject(val, type_table, visitor);
|
||||||
|
break;
|
||||||
|
case ST_STRUCT: IterateObject(val, type_table, visitor); break;
|
||||||
|
case ST_UNION: {
|
||||||
|
val += ReadScalar<uoffset_t>(val);
|
||||||
|
assert(prev_val);
|
||||||
|
auto union_type = *prev_val; // Always a uint8_t.
|
||||||
|
if (vector_index >= 0) {
|
||||||
|
auto type_vec = reinterpret_cast<const Vector<uint8_t> *>(prev_val);
|
||||||
|
union_type = type_vec->Get(static_cast<uoffset_t>(vector_index));
|
||||||
|
}
|
||||||
|
auto type_code_idx =
|
||||||
|
LookupEnum(union_type, type_table->values, type_table->num_elems);
|
||||||
|
if (type_code_idx >= 0 &&
|
||||||
|
type_code_idx < static_cast<int32_t>(type_table->num_elems)) {
|
||||||
|
auto type_code = type_table->type_codes[type_code_idx];
|
||||||
|
switch (type_code.base_type) {
|
||||||
|
case ET_SEQUENCE: {
|
||||||
|
auto ref = type_table->type_refs[type_code.sequence_ref]();
|
||||||
|
IterateObject(val, ref, visitor);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ET_STRING:
|
||||||
|
visitor->String(reinterpret_cast<const String *>(val));
|
||||||
|
break;
|
||||||
|
default: visitor->Unknown(val);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
visitor->Unknown(val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ST_ENUM: assert(false); break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
visitor->Unknown(val);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void IterateObject(const uint8_t *obj, const TypeTable *type_table,
|
||||||
|
IterationVisitor *visitor) {
|
||||||
|
visitor->StartSequence();
|
||||||
|
const uint8_t *prev_val = nullptr;
|
||||||
|
size_t set_idx = 0;
|
||||||
|
for (size_t i = 0; i < type_table->num_elems; i++) {
|
||||||
|
auto type_code = type_table->type_codes[i];
|
||||||
|
auto type = static_cast<ElementaryType>(type_code.base_type);
|
||||||
|
auto is_vector = type_code.is_vector != 0;
|
||||||
|
auto ref_idx = type_code.sequence_ref;
|
||||||
|
const TypeTable *ref = nullptr;
|
||||||
|
if (ref_idx >= 0) { ref = type_table->type_refs[ref_idx](); }
|
||||||
|
auto name = type_table->names ? type_table->names[i] : nullptr;
|
||||||
|
const uint8_t *val = nullptr;
|
||||||
|
if (type_table->st == ST_TABLE) {
|
||||||
|
val = reinterpret_cast<const Table *>(obj)->GetAddressOf(
|
||||||
|
FieldIndexToOffset(static_cast<voffset_t>(i)));
|
||||||
|
} else {
|
||||||
|
val = obj + type_table->values[i];
|
||||||
|
}
|
||||||
|
visitor->Field(i, set_idx, type, is_vector, ref, name, val);
|
||||||
|
if (val) {
|
||||||
|
set_idx++;
|
||||||
|
if (is_vector) {
|
||||||
|
val += ReadScalar<uoffset_t>(val);
|
||||||
|
auto vec = reinterpret_cast<const Vector<uint8_t> *>(val);
|
||||||
|
visitor->StartVector();
|
||||||
|
auto elem_ptr = vec->Data();
|
||||||
|
for (size_t j = 0; j < vec->size(); j++) {
|
||||||
|
visitor->Element(j, type, ref, elem_ptr);
|
||||||
|
IterateValue(type, elem_ptr, ref, prev_val, static_cast<soffset_t>(j),
|
||||||
|
visitor);
|
||||||
|
elem_ptr += InlineSize(type, ref);
|
||||||
|
}
|
||||||
|
visitor->EndVector();
|
||||||
|
} else {
|
||||||
|
IterateValue(type, val, ref, prev_val, -1, visitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
prev_val = val;
|
||||||
|
}
|
||||||
|
visitor->EndSequence();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void IterateFlatBuffer(const uint8_t *buffer,
|
||||||
|
const TypeTable *type_table,
|
||||||
|
IterationVisitor *callback) {
|
||||||
|
IterateObject(GetRoot<uint8_t>(buffer), type_table, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Outputting a Flatbuffer to a string. Tries to conform as close to JSON /
|
||||||
|
// the output generated by idl_gen_text.cpp.
|
||||||
|
|
||||||
|
struct ToStringVisitor : public IterationVisitor {
|
||||||
|
std::string s;
|
||||||
|
void StartSequence() { s += "{ "; }
|
||||||
|
void EndSequence() { s += " }"; }
|
||||||
|
void Field(size_t /*field_idx*/, size_t set_idx, ElementaryType /*type*/,
|
||||||
|
bool /*is_vector*/, const TypeTable * /*type_table*/,
|
||||||
|
const char *name, const uint8_t *val) {
|
||||||
|
if (!val) return;
|
||||||
|
if (set_idx) s += ", ";
|
||||||
|
if (name) {
|
||||||
|
s += name;
|
||||||
|
s += ": ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template<typename T> void Named(T x, const char *name) {
|
||||||
|
if (name)
|
||||||
|
s += name;
|
||||||
|
else
|
||||||
|
s += NumToString(x);
|
||||||
|
}
|
||||||
|
void UType(uint8_t x, const char *name) { Named(x, name); }
|
||||||
|
void Bool(bool x) { s += x ? "true" : "false"; }
|
||||||
|
void Char(int8_t x, const char *name) { Named(x, name); }
|
||||||
|
void UChar(uint8_t x, const char *name) { Named(x, name); }
|
||||||
|
void Short(int16_t x, const char *name) { Named(x, name); }
|
||||||
|
void UShort(uint16_t x, const char *name) { Named(x, name); }
|
||||||
|
void Int(int32_t x, const char *name) { Named(x, name); }
|
||||||
|
void UInt(uint32_t x, const char *name) { Named(x, name); }
|
||||||
|
void Long(int64_t x) { s += NumToString(x); }
|
||||||
|
void ULong(uint64_t x) { s += NumToString(x); }
|
||||||
|
void Float(float x) { s += NumToString(x); }
|
||||||
|
void Double(double x) { s += NumToString(x); }
|
||||||
|
void String(const struct String *str) {
|
||||||
|
EscapeString(str->c_str(), str->size(), &s, true);
|
||||||
|
}
|
||||||
|
void Unknown(const uint8_t *) { s += "(?)"; }
|
||||||
|
void StartVector() { s += "[ "; }
|
||||||
|
void EndVector() { s += " ]"; }
|
||||||
|
void Element(size_t i, ElementaryType /*type*/,
|
||||||
|
const TypeTable * /*type_table*/, const uint8_t * /*val*/) {
|
||||||
|
if (i) s += ", ";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::string FlatBufferToString(const uint8_t *buffer,
|
||||||
|
const TypeTable *type_table) {
|
||||||
|
ToStringVisitor tostring_visitor;
|
||||||
|
IterateFlatBuffer(buffer, type_table, &tostring_visitor);
|
||||||
|
return tostring_visitor.s;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace flatbuffers
|
||||||
|
|
||||||
|
#endif // FLATBUFFERS_MINIREFLECT_H_
|
||||||
@@ -30,14 +30,18 @@ namespace flatbuffers {
|
|||||||
|
|
||||||
// ------------------------- GETTERS -------------------------
|
// ------------------------- GETTERS -------------------------
|
||||||
|
|
||||||
inline bool IsScalar (reflection::BaseType t) { return t >= reflection::UType &&
|
inline bool IsScalar(reflection::BaseType t) {
|
||||||
t <= reflection::Double; }
|
return t >= reflection::UType && t <= reflection::Double;
|
||||||
inline bool IsInteger(reflection::BaseType t) { return t >= reflection::UType &&
|
}
|
||||||
t <= reflection::ULong; }
|
inline bool IsInteger(reflection::BaseType t) {
|
||||||
inline bool IsFloat (reflection::BaseType t) { return t == reflection::Float ||
|
return t >= reflection::UType && t <= reflection::ULong;
|
||||||
t == reflection::Double; }
|
}
|
||||||
inline bool IsLong (reflection::BaseType t) { return t == reflection::Long ||
|
inline bool IsFloat(reflection::BaseType t) {
|
||||||
t == reflection::ULong; }
|
return t == reflection::Float || t == reflection::Double;
|
||||||
|
}
|
||||||
|
inline bool IsLong(reflection::BaseType t) {
|
||||||
|
return t == reflection::Long || t == reflection::ULong;
|
||||||
|
}
|
||||||
|
|
||||||
// Size of a basic type, don't use with structs.
|
// Size of a basic type, don't use with structs.
|
||||||
inline size_t GetTypeSize(reflection::BaseType base_type) {
|
inline size_t GetTypeSize(reflection::BaseType base_type) {
|
||||||
@@ -48,8 +52,7 @@ inline size_t GetTypeSize(reflection::BaseType base_type) {
|
|||||||
|
|
||||||
// Same as above, but now correctly returns the size of a struct if
|
// Same as above, but now correctly returns the size of a struct if
|
||||||
// the field (or vector element) is a struct.
|
// the field (or vector element) is a struct.
|
||||||
inline size_t GetTypeSizeInline(reflection::BaseType base_type,
|
inline size_t GetTypeSizeInline(reflection::BaseType base_type, int type_index,
|
||||||
int type_index,
|
|
||||||
const reflection::Schema &schema) {
|
const reflection::Schema &schema) {
|
||||||
if (base_type == reflection::Obj &&
|
if (base_type == reflection::Obj &&
|
||||||
schema.objects()->Get(type_index)->is_struct()) {
|
schema.objects()->Get(type_index)->is_struct()) {
|
||||||
@@ -80,16 +83,16 @@ template<typename T> T GetFieldDefaultF(const reflection::Field &field) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get a field, if you know it's an integer, and its exact type.
|
// Get a field, if you know it's an integer, and its exact type.
|
||||||
template<typename T> T GetFieldI(const Table &table,
|
template<typename T>
|
||||||
const reflection::Field &field) {
|
T GetFieldI(const Table &table, const reflection::Field &field) {
|
||||||
assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
||||||
return table.GetField<T>(field.offset(),
|
return table.GetField<T>(field.offset(),
|
||||||
static_cast<T>(field.default_integer()));
|
static_cast<T>(field.default_integer()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a field, if you know it's floating point and its exact type.
|
// Get a field, if you know it's floating point and its exact type.
|
||||||
template<typename T> T GetFieldF(const Table &table,
|
template<typename T>
|
||||||
const reflection::Field &field) {
|
T GetFieldF(const Table &table, const reflection::Field &field) {
|
||||||
assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
||||||
return table.GetField<T>(field.offset(),
|
return table.GetField<T>(field.offset(),
|
||||||
static_cast<T>(field.default_real()));
|
static_cast<T>(field.default_real()));
|
||||||
@@ -103,8 +106,8 @@ inline const String *GetFieldS(const Table &table,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get a field, if you know it's a vector.
|
// Get a field, if you know it's a vector.
|
||||||
template<typename T> Vector<T> *GetFieldV(const Table &table,
|
template<typename T>
|
||||||
const reflection::Field &field) {
|
Vector<T> *GetFieldV(const Table &table, const reflection::Field &field) {
|
||||||
assert(field.type()->base_type() == reflection::Vector &&
|
assert(field.type()->base_type() == reflection::Vector &&
|
||||||
sizeof(T) == GetTypeSize(field.type()->element()));
|
sizeof(T) == GetTypeSize(field.type()->element()));
|
||||||
return table.GetPointer<Vector<T> *>(field.offset());
|
return table.GetPointer<Vector<T> *>(field.offset());
|
||||||
@@ -119,8 +122,7 @@ inline VectorOfAny *GetFieldAnyV(const Table &table,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get a field, if you know it's a table.
|
// Get a field, if you know it's a table.
|
||||||
inline Table *GetFieldT(const Table &table,
|
inline Table *GetFieldT(const Table &table, const reflection::Field &field) {
|
||||||
const reflection::Field &field) {
|
|
||||||
assert(field.type()->base_type() == reflection::Obj ||
|
assert(field.type()->base_type() == reflection::Obj ||
|
||||||
field.type()->base_type() == reflection::Union);
|
field.type()->base_type() == reflection::Union);
|
||||||
return table.GetPointer<Table *>(field.offset());
|
return table.GetPointer<Table *>(field.offset());
|
||||||
@@ -153,8 +155,7 @@ double GetAnyValueF(reflection::BaseType type, const uint8_t *data);
|
|||||||
// All scalars converted using stringstream, strings as-is, and all other
|
// All scalars converted using stringstream, strings as-is, and all other
|
||||||
// data types provide some level of debug-pretty-printing.
|
// data types provide some level of debug-pretty-printing.
|
||||||
std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data,
|
std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data,
|
||||||
const reflection::Schema *schema,
|
const reflection::Schema *schema, int type_index);
|
||||||
int type_index);
|
|
||||||
|
|
||||||
// Get any table field as a 64bit int, regardless of what type it is.
|
// Get any table field as a 64bit int, regardless of what type it is.
|
||||||
inline int64_t GetAnyFieldI(const Table &table,
|
inline int64_t GetAnyFieldI(const Table &table,
|
||||||
@@ -165,14 +166,12 @@ inline int64_t GetAnyFieldI(const Table &table,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get any table field as a double, regardless of what type it is.
|
// Get any table field as a double, regardless of what type it is.
|
||||||
inline double GetAnyFieldF(const Table &table,
|
inline double GetAnyFieldF(const Table &table, const reflection::Field &field) {
|
||||||
const reflection::Field &field) {
|
|
||||||
auto field_ptr = table.GetAddressOf(field.offset());
|
auto field_ptr = table.GetAddressOf(field.offset());
|
||||||
return field_ptr ? GetAnyValueF(field.type()->base_type(), field_ptr)
|
return field_ptr ? GetAnyValueF(field.type()->base_type(), field_ptr)
|
||||||
: field.default_real();
|
: field.default_real();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Get any table field as a string, regardless of what type it is.
|
// Get any table field as a string, regardless of what type it is.
|
||||||
// You may pass nullptr for the schema if you don't care to have fields that
|
// You may pass nullptr for the schema if you don't care to have fields that
|
||||||
// are of table type pretty-printed.
|
// are of table type pretty-printed.
|
||||||
@@ -186,15 +185,13 @@ inline std::string GetAnyFieldS(const Table &table,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get any struct field as a 64bit int, regardless of what type it is.
|
// Get any struct field as a 64bit int, regardless of what type it is.
|
||||||
inline int64_t GetAnyFieldI(const Struct &st,
|
inline int64_t GetAnyFieldI(const Struct &st, const reflection::Field &field) {
|
||||||
const reflection::Field &field) {
|
|
||||||
return GetAnyValueI(field.type()->base_type(),
|
return GetAnyValueI(field.type()->base_type(),
|
||||||
st.GetAddressOf(field.offset()));
|
st.GetAddressOf(field.offset()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get any struct field as a double, regardless of what type it is.
|
// Get any struct field as a double, regardless of what type it is.
|
||||||
inline double GetAnyFieldF(const Struct &st,
|
inline double GetAnyFieldF(const Struct &st, const reflection::Field &field) {
|
||||||
const reflection::Field &field) {
|
|
||||||
return GetAnyValueF(field.type()->base_type(),
|
return GetAnyValueF(field.type()->base_type(),
|
||||||
st.GetAddressOf(field.offset()));
|
st.GetAddressOf(field.offset()));
|
||||||
}
|
}
|
||||||
@@ -228,8 +225,8 @@ inline std::string GetAnyVectorElemS(const VectorOfAny *vec,
|
|||||||
// Get a vector element that's a table/string/vector from a generic vector.
|
// Get a vector element that's a table/string/vector from a generic vector.
|
||||||
// Pass Table/String/VectorOfAny as template parameter.
|
// Pass Table/String/VectorOfAny as template parameter.
|
||||||
// Warning: does no typechecking.
|
// Warning: does no typechecking.
|
||||||
template<typename T> T *GetAnyVectorElemPointer(const VectorOfAny *vec,
|
template<typename T>
|
||||||
size_t i) {
|
T *GetAnyVectorElemPointer(const VectorOfAny *vec, size_t i) {
|
||||||
auto elem_ptr = vec->Data() + sizeof(uoffset_t) * i;
|
auto elem_ptr = vec->Data() + sizeof(uoffset_t) * i;
|
||||||
return (T *)(elem_ptr + ReadScalar<uoffset_t>(elem_ptr));
|
return (T *)(elem_ptr + ReadScalar<uoffset_t>(elem_ptr));
|
||||||
}
|
}
|
||||||
@@ -239,34 +236,32 @@ template<typename T> T *GetAnyVectorElemPointer(const VectorOfAny *vec,
|
|||||||
// Get elem_size from GetTypeSizeInline().
|
// Get elem_size from GetTypeSizeInline().
|
||||||
// Note: little-endian data on all platforms, use EndianScalar() instead of
|
// Note: little-endian data on all platforms, use EndianScalar() instead of
|
||||||
// raw pointer access with scalars).
|
// raw pointer access with scalars).
|
||||||
template<typename T> T *GetAnyVectorElemAddressOf(const VectorOfAny *vec,
|
template<typename T>
|
||||||
size_t i,
|
T *GetAnyVectorElemAddressOf(const VectorOfAny *vec, size_t i,
|
||||||
size_t elem_size) {
|
size_t elem_size) {
|
||||||
// C-cast to allow const conversion.
|
// C-cast to allow const conversion.
|
||||||
return (T *)(vec->Data() + elem_size * i);
|
return (T *)(vec->Data() + elem_size * i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Similarly, for elements of tables.
|
// Similarly, for elements of tables.
|
||||||
template<typename T> T *GetAnyFieldAddressOf(const Table &table,
|
template<typename T>
|
||||||
const reflection::Field &field) {
|
T *GetAnyFieldAddressOf(const Table &table, const reflection::Field &field) {
|
||||||
return (T *)table.GetAddressOf(field.offset());
|
return (T *)table.GetAddressOf(field.offset());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Similarly, for elements of structs.
|
// Similarly, for elements of structs.
|
||||||
template<typename T> T *GetAnyFieldAddressOf(const Struct &st,
|
template<typename T>
|
||||||
const reflection::Field &field) {
|
T *GetAnyFieldAddressOf(const Struct &st, const reflection::Field &field) {
|
||||||
return (T *)st.GetAddressOf(field.offset());
|
return (T *)st.GetAddressOf(field.offset());
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------- SETTERS -------------------------
|
// ------------------------- SETTERS -------------------------
|
||||||
|
|
||||||
// Set any scalar field, if you know its exact type.
|
// Set any scalar field, if you know its exact type.
|
||||||
template<typename T> bool SetField(Table *table, const reflection::Field &field,
|
template<typename T>
|
||||||
T val) {
|
bool SetField(Table *table, const reflection::Field &field, T val) {
|
||||||
reflection::BaseType type = field.type()->base_type();
|
reflection::BaseType type = field.type()->base_type();
|
||||||
if (!IsScalar(type)) {
|
if (!IsScalar(type)) { return false; }
|
||||||
return false;
|
|
||||||
}
|
|
||||||
assert(sizeof(T) == GetTypeSize(type));
|
assert(sizeof(T) == GetTypeSize(type));
|
||||||
T def;
|
T def;
|
||||||
if (IsInteger(type)) {
|
if (IsInteger(type)) {
|
||||||
@@ -306,7 +301,7 @@ inline bool SetAnyFieldF(Table *table, const reflection::Field &field,
|
|||||||
|
|
||||||
// Set any table field as a string, regardless of what type it is.
|
// Set any table field as a string, regardless of what type it is.
|
||||||
inline bool SetAnyFieldS(Table *table, const reflection::Field &field,
|
inline bool SetAnyFieldS(Table *table, const reflection::Field &field,
|
||||||
const char *val) {
|
const char *val) {
|
||||||
auto field_ptr = table->GetAddressOf(field.offset());
|
auto field_ptr = table->GetAddressOf(field.offset());
|
||||||
if (!field_ptr) return false;
|
if (!field_ptr) return false;
|
||||||
SetAnyValueS(field.type()->base_type(), field_ptr, val);
|
SetAnyValueS(field.type()->base_type(), field_ptr, val);
|
||||||
@@ -352,7 +347,6 @@ inline void SetAnyVectorElemS(VectorOfAny *vec, reflection::BaseType elem_type,
|
|||||||
SetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
|
SetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------- RESIZING SETTERS -------------------------
|
// ------------------------- RESIZING SETTERS -------------------------
|
||||||
|
|
||||||
// "smart" pointer for use with resizing vectors: turns a pointer inside
|
// "smart" pointer for use with resizing vectors: turns a pointer inside
|
||||||
@@ -360,26 +354,25 @@ inline void SetAnyVectorElemS(VectorOfAny *vec, reflection::BaseType elem_type,
|
|||||||
template<typename T, typename U> class pointer_inside_vector {
|
template<typename T, typename U> class pointer_inside_vector {
|
||||||
public:
|
public:
|
||||||
pointer_inside_vector(T *ptr, std::vector<U> &vec)
|
pointer_inside_vector(T *ptr, std::vector<U> &vec)
|
||||||
: offset_(reinterpret_cast<uint8_t *>(ptr) -
|
: offset_(reinterpret_cast<uint8_t *>(ptr) -
|
||||||
reinterpret_cast<uint8_t *>(vec.data())),
|
reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec))),
|
||||||
vec_(vec) {}
|
vec_(vec) {}
|
||||||
|
|
||||||
T *operator*() const {
|
T *operator*() const {
|
||||||
return reinterpret_cast<T *>(
|
return reinterpret_cast<T *>(
|
||||||
reinterpret_cast<uint8_t *>(vec_.data()) + offset_);
|
reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec_)) + offset_);
|
||||||
}
|
|
||||||
T *operator->() const {
|
|
||||||
return operator*();
|
|
||||||
}
|
}
|
||||||
|
T *operator->() const { return operator*(); }
|
||||||
void operator=(const pointer_inside_vector &piv);
|
void operator=(const pointer_inside_vector &piv);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
size_t offset_;
|
size_t offset_;
|
||||||
std::vector<U> &vec_;
|
std::vector<U> &vec_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Helper to create the above easily without specifying template args.
|
// Helper to create the above easily without specifying template args.
|
||||||
template<typename T, typename U> pointer_inside_vector<T, U> piv(T *ptr,
|
template<typename T, typename U>
|
||||||
std::vector<U> &vec) {
|
pointer_inside_vector<T, U> piv(T *ptr, std::vector<U> &vec) {
|
||||||
return pointer_inside_vector<T, U>(ptr, vec);
|
return pointer_inside_vector<T, U>(ptr, vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,7 +385,7 @@ inline const reflection::Object &GetUnionType(
|
|||||||
auto enumdef = schema.enums()->Get(unionfield.type()->index());
|
auto enumdef = schema.enums()->Get(unionfield.type()->index());
|
||||||
// TODO: this is clumsy and slow, but no other way to find it?
|
// TODO: this is clumsy and slow, but no other way to find it?
|
||||||
auto type_field = parent.fields()->LookupByKey(
|
auto type_field = parent.fields()->LookupByKey(
|
||||||
(unionfield.name()->str() + UnionTypeFieldSuffix()).c_str());
|
(unionfield.name()->str() + UnionTypeFieldSuffix()).c_str());
|
||||||
assert(type_field);
|
assert(type_field);
|
||||||
auto union_type = GetFieldI<uint8_t>(table, *type_field);
|
auto union_type = GetFieldI<uint8_t>(table, *type_field);
|
||||||
auto enumval = enumdef->values()->LookupByKey(union_type);
|
auto enumval = enumdef->values()->LookupByKey(union_type);
|
||||||
@@ -418,21 +411,18 @@ uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize,
|
|||||||
uoffset_t elem_size, std::vector<uint8_t> *flatbuf,
|
uoffset_t elem_size, std::vector<uint8_t> *flatbuf,
|
||||||
const reflection::Object *root_table = nullptr);
|
const reflection::Object *root_table = nullptr);
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_CPP98_STL
|
template<typename T>
|
||||||
template <typename T>
|
|
||||||
void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
|
void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
|
||||||
const Vector<T> *vec, std::vector<uint8_t> *flatbuf,
|
const Vector<T> *vec, std::vector<uint8_t> *flatbuf,
|
||||||
const reflection::Object *root_table = nullptr) {
|
const reflection::Object *root_table = nullptr) {
|
||||||
auto delta_elem = static_cast<int>(newsize) - static_cast<int>(vec->size());
|
auto delta_elem = static_cast<int>(newsize) - static_cast<int>(vec->size());
|
||||||
auto newelems = ResizeAnyVector(schema, newsize,
|
auto newelems = ResizeAnyVector(
|
||||||
reinterpret_cast<const VectorOfAny *>(vec),
|
schema, newsize, reinterpret_cast<const VectorOfAny *>(vec), vec->size(),
|
||||||
vec->size(),
|
static_cast<uoffset_t>(sizeof(T)), flatbuf, root_table);
|
||||||
static_cast<uoffset_t>(sizeof(T)), flatbuf,
|
|
||||||
root_table);
|
|
||||||
// Set new elements to "val".
|
// Set new elements to "val".
|
||||||
for (int i = 0; i < delta_elem; i++) {
|
for (int i = 0; i < delta_elem; i++) {
|
||||||
auto loc = newelems + i * sizeof(T);
|
auto loc = newelems + i * sizeof(T);
|
||||||
auto is_scalar = std::is_scalar<T>::value;
|
auto is_scalar = flatbuffers::is_scalar<T>::value;
|
||||||
if (is_scalar) {
|
if (is_scalar) {
|
||||||
WriteScalar(loc, val);
|
WriteScalar(loc, val);
|
||||||
} else { // struct
|
} else { // struct
|
||||||
@@ -440,7 +430,6 @@ void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
// Adds any new data (in the form of a new FlatBuffer) to an existing
|
// Adds any new data (in the form of a new FlatBuffer) to an existing
|
||||||
// FlatBuffer. This can be used when any of the above methods are not
|
// FlatBuffer. This can be used when any of the above methods are not
|
||||||
@@ -480,10 +469,8 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
|
|||||||
// root should point to the root type for this flatbuffer.
|
// root should point to the root type for this flatbuffer.
|
||||||
// buf should point to the start of flatbuffer data.
|
// buf should point to the start of flatbuffer data.
|
||||||
// length specifies the size of the flatbuffer data.
|
// length specifies the size of the flatbuffer data.
|
||||||
bool Verify(const reflection::Schema &schema,
|
bool Verify(const reflection::Schema &schema, const reflection::Object &root,
|
||||||
const reflection::Object &root,
|
const uint8_t *buf, size_t length);
|
||||||
const uint8_t *buf,
|
|
||||||
size_t length);
|
|
||||||
|
|
||||||
} // namespace flatbuffers
|
} // namespace flatbuffers
|
||||||
|
|
||||||
|
|||||||
@@ -42,8 +42,31 @@ enum BaseType {
|
|||||||
Union = 16
|
Union = 16
|
||||||
};
|
};
|
||||||
|
|
||||||
inline const char **EnumNamesBaseType() {
|
inline const BaseType (&EnumValuesBaseType())[17] {
|
||||||
static const char *names[] = {
|
static const BaseType values[] = {
|
||||||
|
None,
|
||||||
|
UType,
|
||||||
|
Bool,
|
||||||
|
Byte,
|
||||||
|
UByte,
|
||||||
|
Short,
|
||||||
|
UShort,
|
||||||
|
Int,
|
||||||
|
UInt,
|
||||||
|
Long,
|
||||||
|
ULong,
|
||||||
|
Float,
|
||||||
|
Double,
|
||||||
|
String,
|
||||||
|
Vector,
|
||||||
|
Obj,
|
||||||
|
Union
|
||||||
|
};
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const char * const *EnumNamesBaseType() {
|
||||||
|
static const char * const names[] = {
|
||||||
"None",
|
"None",
|
||||||
"UType",
|
"UType",
|
||||||
"Bool",
|
"Bool",
|
||||||
@@ -107,13 +130,13 @@ struct TypeBuilder {
|
|||||||
void add_index(int32_t index) {
|
void add_index(int32_t index) {
|
||||||
fbb_.AddElement<int32_t>(Type::VT_INDEX, index, -1);
|
fbb_.AddElement<int32_t>(Type::VT_INDEX, index, -1);
|
||||||
}
|
}
|
||||||
TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
explicit TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
: fbb_(_fbb) {
|
: fbb_(_fbb) {
|
||||||
start_ = fbb_.StartTable();
|
start_ = fbb_.StartTable();
|
||||||
}
|
}
|
||||||
TypeBuilder &operator=(const TypeBuilder &);
|
TypeBuilder &operator=(const TypeBuilder &);
|
||||||
flatbuffers::Offset<Type> Finish() {
|
flatbuffers::Offset<Type> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 3);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<Type>(end);
|
auto o = flatbuffers::Offset<Type>(end);
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
@@ -167,13 +190,13 @@ struct KeyValueBuilder {
|
|||||||
void add_value(flatbuffers::Offset<flatbuffers::String> value) {
|
void add_value(flatbuffers::Offset<flatbuffers::String> value) {
|
||||||
fbb_.AddOffset(KeyValue::VT_VALUE, value);
|
fbb_.AddOffset(KeyValue::VT_VALUE, value);
|
||||||
}
|
}
|
||||||
KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
explicit KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
: fbb_(_fbb) {
|
: fbb_(_fbb) {
|
||||||
start_ = fbb_.StartTable();
|
start_ = fbb_.StartTable();
|
||||||
}
|
}
|
||||||
KeyValueBuilder &operator=(const KeyValueBuilder &);
|
KeyValueBuilder &operator=(const KeyValueBuilder &);
|
||||||
flatbuffers::Offset<KeyValue> Finish() {
|
flatbuffers::Offset<KeyValue> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 2);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<KeyValue>(end);
|
auto o = flatbuffers::Offset<KeyValue>(end);
|
||||||
fbb_.Required(o, KeyValue::VT_KEY);
|
fbb_.Required(o, KeyValue::VT_KEY);
|
||||||
return o;
|
return o;
|
||||||
@@ -260,13 +283,13 @@ struct EnumValBuilder {
|
|||||||
void add_union_type(flatbuffers::Offset<Type> union_type) {
|
void add_union_type(flatbuffers::Offset<Type> union_type) {
|
||||||
fbb_.AddOffset(EnumVal::VT_UNION_TYPE, union_type);
|
fbb_.AddOffset(EnumVal::VT_UNION_TYPE, union_type);
|
||||||
}
|
}
|
||||||
EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
explicit EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
: fbb_(_fbb) {
|
: fbb_(_fbb) {
|
||||||
start_ = fbb_.StartTable();
|
start_ = fbb_.StartTable();
|
||||||
}
|
}
|
||||||
EnumValBuilder &operator=(const EnumValBuilder &);
|
EnumValBuilder &operator=(const EnumValBuilder &);
|
||||||
flatbuffers::Offset<EnumVal> Finish() {
|
flatbuffers::Offset<EnumVal> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 4);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<EnumVal>(end);
|
auto o = flatbuffers::Offset<EnumVal>(end);
|
||||||
fbb_.Required(o, EnumVal::VT_NAME);
|
fbb_.Required(o, EnumVal::VT_NAME);
|
||||||
return o;
|
return o;
|
||||||
@@ -375,13 +398,13 @@ struct EnumBuilder {
|
|||||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||||
fbb_.AddOffset(Enum::VT_DOCUMENTATION, documentation);
|
fbb_.AddOffset(Enum::VT_DOCUMENTATION, documentation);
|
||||||
}
|
}
|
||||||
EnumBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
explicit EnumBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
: fbb_(_fbb) {
|
: fbb_(_fbb) {
|
||||||
start_ = fbb_.StartTable();
|
start_ = fbb_.StartTable();
|
||||||
}
|
}
|
||||||
EnumBuilder &operator=(const EnumBuilder &);
|
EnumBuilder &operator=(const EnumBuilder &);
|
||||||
flatbuffers::Offset<Enum> Finish() {
|
flatbuffers::Offset<Enum> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 6);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<Enum>(end);
|
auto o = flatbuffers::Offset<Enum>(end);
|
||||||
fbb_.Required(o, Enum::VT_NAME);
|
fbb_.Required(o, Enum::VT_NAME);
|
||||||
fbb_.Required(o, Enum::VT_VALUES);
|
fbb_.Required(o, Enum::VT_VALUES);
|
||||||
@@ -538,13 +561,13 @@ struct FieldBuilder {
|
|||||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||||
fbb_.AddOffset(Field::VT_DOCUMENTATION, documentation);
|
fbb_.AddOffset(Field::VT_DOCUMENTATION, documentation);
|
||||||
}
|
}
|
||||||
FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
explicit FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
: fbb_(_fbb) {
|
: fbb_(_fbb) {
|
||||||
start_ = fbb_.StartTable();
|
start_ = fbb_.StartTable();
|
||||||
}
|
}
|
||||||
FieldBuilder &operator=(const FieldBuilder &);
|
FieldBuilder &operator=(const FieldBuilder &);
|
||||||
flatbuffers::Offset<Field> Finish() {
|
flatbuffers::Offset<Field> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 11);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<Field>(end);
|
auto o = flatbuffers::Offset<Field>(end);
|
||||||
fbb_.Required(o, Field::VT_NAME);
|
fbb_.Required(o, Field::VT_NAME);
|
||||||
fbb_.Required(o, Field::VT_TYPE);
|
fbb_.Required(o, Field::VT_TYPE);
|
||||||
@@ -689,13 +712,13 @@ struct ObjectBuilder {
|
|||||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||||
fbb_.AddOffset(Object::VT_DOCUMENTATION, documentation);
|
fbb_.AddOffset(Object::VT_DOCUMENTATION, documentation);
|
||||||
}
|
}
|
||||||
ObjectBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
explicit ObjectBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
: fbb_(_fbb) {
|
: fbb_(_fbb) {
|
||||||
start_ = fbb_.StartTable();
|
start_ = fbb_.StartTable();
|
||||||
}
|
}
|
||||||
ObjectBuilder &operator=(const ObjectBuilder &);
|
ObjectBuilder &operator=(const ObjectBuilder &);
|
||||||
flatbuffers::Offset<Object> Finish() {
|
flatbuffers::Offset<Object> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 7);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<Object>(end);
|
auto o = flatbuffers::Offset<Object>(end);
|
||||||
fbb_.Required(o, Object::VT_NAME);
|
fbb_.Required(o, Object::VT_NAME);
|
||||||
fbb_.Required(o, Object::VT_FIELDS);
|
fbb_.Required(o, Object::VT_FIELDS);
|
||||||
@@ -802,13 +825,13 @@ struct SchemaBuilder {
|
|||||||
void add_root_table(flatbuffers::Offset<Object> root_table) {
|
void add_root_table(flatbuffers::Offset<Object> root_table) {
|
||||||
fbb_.AddOffset(Schema::VT_ROOT_TABLE, root_table);
|
fbb_.AddOffset(Schema::VT_ROOT_TABLE, root_table);
|
||||||
}
|
}
|
||||||
SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
explicit SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
: fbb_(_fbb) {
|
: fbb_(_fbb) {
|
||||||
start_ = fbb_.StartTable();
|
start_ = fbb_.StartTable();
|
||||||
}
|
}
|
||||||
SchemaBuilder &operator=(const SchemaBuilder &);
|
SchemaBuilder &operator=(const SchemaBuilder &);
|
||||||
flatbuffers::Offset<Schema> Finish() {
|
flatbuffers::Offset<Schema> Finish() {
|
||||||
const auto end = fbb_.EndTable(start_, 5);
|
const auto end = fbb_.EndTable(start_);
|
||||||
auto o = flatbuffers::Offset<Schema>(end);
|
auto o = flatbuffers::Offset<Schema>(end);
|
||||||
fbb_.Required(o, Schema::VT_OBJECTS);
|
fbb_.Required(o, Schema::VT_OBJECTS);
|
||||||
fbb_.Required(o, Schema::VT_ENUMS);
|
fbb_.Required(o, Schema::VT_ENUMS);
|
||||||
@@ -852,6 +875,10 @@ inline const reflection::Schema *GetSchema(const void *buf) {
|
|||||||
return flatbuffers::GetRoot<reflection::Schema>(buf);
|
return flatbuffers::GetRoot<reflection::Schema>(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const reflection::Schema *GetSizePrefixedSchema(const void *buf) {
|
||||||
|
return flatbuffers::GetSizePrefixedRoot<reflection::Schema>(buf);
|
||||||
|
}
|
||||||
|
|
||||||
inline const char *SchemaIdentifier() {
|
inline const char *SchemaIdentifier() {
|
||||||
return "BFBS";
|
return "BFBS";
|
||||||
}
|
}
|
||||||
@@ -866,6 +893,11 @@ inline bool VerifySchemaBuffer(
|
|||||||
return verifier.VerifyBuffer<reflection::Schema>(SchemaIdentifier());
|
return verifier.VerifyBuffer<reflection::Schema>(SchemaIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool VerifySizePrefixedSchemaBuffer(
|
||||||
|
flatbuffers::Verifier &verifier) {
|
||||||
|
return verifier.VerifySizePrefixedBuffer<reflection::Schema>(SchemaIdentifier());
|
||||||
|
}
|
||||||
|
|
||||||
inline const char *SchemaExtension() {
|
inline const char *SchemaExtension() {
|
||||||
return "bfbs";
|
return "bfbs";
|
||||||
}
|
}
|
||||||
@@ -876,6 +908,12 @@ inline void FinishSchemaBuffer(
|
|||||||
fbb.Finish(root, SchemaIdentifier());
|
fbb.Finish(root, SchemaIdentifier());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void FinishSizePrefixedSchemaBuffer(
|
||||||
|
flatbuffers::FlatBufferBuilder &fbb,
|
||||||
|
flatbuffers::Offset<reflection::Schema> root) {
|
||||||
|
fbb.FinishSizePrefixed(root, SchemaIdentifier());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace reflection
|
} // namespace reflection
|
||||||
|
|
||||||
#endif // FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_
|
#endif // FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_
|
||||||
|
|||||||
@@ -37,18 +37,16 @@ class Registry {
|
|||||||
|
|
||||||
// Generate text from an arbitrary FlatBuffer by looking up its
|
// Generate text from an arbitrary FlatBuffer by looking up its
|
||||||
// file_identifier in the registry.
|
// file_identifier in the registry.
|
||||||
bool FlatBufferToText(const uint8_t *flatbuf, size_t len,
|
bool FlatBufferToText(const uint8_t *flatbuf, size_t len, std::string *dest) {
|
||||||
std::string *dest) {
|
|
||||||
// Get the identifier out of the buffer.
|
// Get the identifier out of the buffer.
|
||||||
// If the buffer is truncated, exit.
|
// If the buffer is truncated, exit.
|
||||||
if (len < sizeof(uoffset_t) +
|
if (len < sizeof(uoffset_t) + FlatBufferBuilder::kFileIdentifierLength) {
|
||||||
FlatBufferBuilder::kFileIdentifierLength) {
|
|
||||||
lasterror_ = "buffer truncated";
|
lasterror_ = "buffer truncated";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::string ident(reinterpret_cast<const char *>(flatbuf) +
|
std::string ident(
|
||||||
sizeof(uoffset_t),
|
reinterpret_cast<const char *>(flatbuf) + sizeof(uoffset_t),
|
||||||
FlatBufferBuilder::kFileIdentifierLength);
|
FlatBufferBuilder::kFileIdentifierLength);
|
||||||
// Load and parse the schema.
|
// Load and parse the schema.
|
||||||
Parser parser;
|
Parser parser;
|
||||||
if (!LoadSchema(ident, &parser)) return false;
|
if (!LoadSchema(ident, &parser)) return false;
|
||||||
@@ -82,38 +80,36 @@ class Registry {
|
|||||||
|
|
||||||
// If schemas used contain include statements, call this function for every
|
// If schemas used contain include statements, call this function for every
|
||||||
// directory the parser should search them for.
|
// directory the parser should search them for.
|
||||||
void AddIncludeDirectory(const char *path) {
|
void AddIncludeDirectory(const char *path) { include_paths_.push_back(path); }
|
||||||
include_paths_.push_back(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns a human readable error if any of the above functions fail.
|
// Returns a human readable error if any of the above functions fail.
|
||||||
const std::string &GetLastError() { return lasterror_; }
|
const std::string &GetLastError() { return lasterror_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool LoadSchema(const std::string &ident, Parser *parser) {
|
bool LoadSchema(const std::string &ident, Parser *parser) {
|
||||||
// Find the schema, if not, exit.
|
// Find the schema, if not, exit.
|
||||||
auto it = schemas_.find(ident);
|
auto it = schemas_.find(ident);
|
||||||
if (it == schemas_.end()) {
|
if (it == schemas_.end()) {
|
||||||
// Don't attach the identifier, since it may not be human readable.
|
// Don't attach the identifier, since it may not be human readable.
|
||||||
lasterror_ = "identifier for this buffer not in the registry";
|
lasterror_ = "identifier for this buffer not in the registry";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto &schema = it->second;
|
auto &schema = it->second;
|
||||||
// Load the schema from disk. If not, exit.
|
// Load the schema from disk. If not, exit.
|
||||||
std::string schematext;
|
std::string schematext;
|
||||||
if (!LoadFile(schema.path_.c_str(), false, &schematext)) {
|
if (!LoadFile(schema.path_.c_str(), false, &schematext)) {
|
||||||
lasterror_ = "could not load schema: " + schema.path_;
|
lasterror_ = "could not load schema: " + schema.path_;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Parse schema.
|
// Parse schema.
|
||||||
parser->opts = opts_;
|
parser->opts = opts_;
|
||||||
if (!parser->Parse(schematext.c_str(), include_paths_.data(),
|
if (!parser->Parse(schematext.c_str(), vector_data(include_paths_),
|
||||||
schema.path_.c_str())) {
|
schema.path_.c_str())) {
|
||||||
lasterror_ = parser->error_;
|
lasterror_ = parser->error_;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Schema {
|
struct Schema {
|
||||||
std::string path_;
|
std::string path_;
|
||||||
|
|||||||
228
include/flatbuffers/stl_emulation.h
Normal file
228
include/flatbuffers/stl_emulation.h
Normal file
@@ -0,0 +1,228 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 Google Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef FLATBUFFERS_STL_EMULATION_H_
|
||||||
|
#define FLATBUFFERS_STL_EMULATION_H_
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
#include <memory>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#if defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
|
||||||
|
#define FLATBUFFERS_CPP98_STL
|
||||||
|
#endif // defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
|
||||||
|
|
||||||
|
#if defined(FLATBUFFERS_CPP98_STL)
|
||||||
|
#include <cctype>
|
||||||
|
#endif // defined(FLATBUFFERS_CPP98_STL)
|
||||||
|
|
||||||
|
// This header provides backwards compatibility for C++98 STLs like stlport.
|
||||||
|
namespace flatbuffers {
|
||||||
|
|
||||||
|
// Retrieve ::back() from a string in a way that is compatible with pre C++11
|
||||||
|
// STLs (e.g stlport).
|
||||||
|
inline char& string_back(std::string &value) {
|
||||||
|
return value[value.length() - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
inline char string_back(const std::string &value) {
|
||||||
|
return value[value.length() - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method that retrieves ::data() from a vector in a way that is
|
||||||
|
// compatible with pre C++11 STLs (e.g stlport).
|
||||||
|
template <typename T> inline T *vector_data(std::vector<T> &vector) {
|
||||||
|
// In some debug environments, operator[] does bounds checking, so &vector[0]
|
||||||
|
// can't be used.
|
||||||
|
return vector.empty() ? nullptr : &vector[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> inline const T *vector_data(
|
||||||
|
const std::vector<T> &vector) {
|
||||||
|
return vector.empty() ? nullptr : &vector[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename V>
|
||||||
|
inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
||||||
|
#if defined(FLATBUFFERS_CPP98_STL)
|
||||||
|
vector->push_back(data);
|
||||||
|
#else
|
||||||
|
vector->emplace_back(std::forward<V>(data));
|
||||||
|
#endif // defined(FLATBUFFERS_CPP98_STL)
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef FLATBUFFERS_CPP98_STL
|
||||||
|
#if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
||||||
|
template <typename T>
|
||||||
|
using numeric_limits = std::numeric_limits<T>;
|
||||||
|
#else
|
||||||
|
template <typename T> class numeric_limits :
|
||||||
|
public std::numeric_limits<T> {};
|
||||||
|
#endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
||||||
|
#else
|
||||||
|
template <typename T> class numeric_limits :
|
||||||
|
public std::numeric_limits<T> {};
|
||||||
|
|
||||||
|
template <> class numeric_limits<unsigned long long> {
|
||||||
|
public:
|
||||||
|
static unsigned long long min() { return 0ULL; }
|
||||||
|
static unsigned long long max() { return ~0ULL; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> class numeric_limits<long long> {
|
||||||
|
public:
|
||||||
|
static long long min() {
|
||||||
|
return static_cast<long long>(1ULL << ((sizeof(long long) << 3) - 1));
|
||||||
|
}
|
||||||
|
static long long max() {
|
||||||
|
return static_cast<long long>(
|
||||||
|
(1ULL << ((sizeof(long long) << 3) - 1)) - 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif // FLATBUFFERS_CPP98_STL
|
||||||
|
|
||||||
|
#if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
||||||
|
#ifndef FLATBUFFERS_CPP98_STL
|
||||||
|
template <typename T> using is_scalar = std::is_scalar<T>;
|
||||||
|
template <typename T, typename U> using is_same = std::is_same<T,U>;
|
||||||
|
template <typename T> using is_floating_point = std::is_floating_point<T>;
|
||||||
|
template <typename T> using is_unsigned = std::is_unsigned<T>;
|
||||||
|
#else
|
||||||
|
// Map C++ TR1 templates defined by stlport.
|
||||||
|
template <typename T> using is_scalar = std::tr1::is_scalar<T>;
|
||||||
|
template <typename T, typename U> using is_same = std::tr1::is_same<T,U>;
|
||||||
|
template <typename T> using is_floating_point =
|
||||||
|
std::tr1::is_floating_point<T>;
|
||||||
|
template <typename T> using is_unsigned = std::tr1::is_unsigned<T>;
|
||||||
|
#endif // !FLATBUFFERS_CPP98_STL
|
||||||
|
#else
|
||||||
|
// MSVC 2010 doesn't support C++11 aliases.
|
||||||
|
template <typename T> struct is_scalar : public std::is_scalar<T> {};
|
||||||
|
template <typename T, typename U> struct is_same : public std::is_same<T,U> {};
|
||||||
|
template <typename T> struct is_floating_point :
|
||||||
|
public std::is_floating_point<T> {};
|
||||||
|
template <typename T> struct is_unsigned : public std::is_unsigned<T> {};
|
||||||
|
#endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
||||||
|
|
||||||
|
#ifndef FLATBUFFERS_CPP98_STL
|
||||||
|
#if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
||||||
|
template <class T> using unique_ptr = std::unique_ptr<T>;
|
||||||
|
#else
|
||||||
|
// MSVC 2010 doesn't support C++11 aliases.
|
||||||
|
// We're manually "aliasing" the class here as we want to bring unique_ptr
|
||||||
|
// into the flatbuffers namespace. We have unique_ptr in the flatbuffers
|
||||||
|
// namespace we have a completely independent implemenation (see below)
|
||||||
|
// for C++98 STL implementations.
|
||||||
|
template <class T> class unique_ptr : public std::unique_ptr<T> {
|
||||||
|
public:
|
||||||
|
unique_ptr() {}
|
||||||
|
explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {}
|
||||||
|
unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); }
|
||||||
|
unique_ptr(unique_ptr&& u) { *this = std::move(u); }
|
||||||
|
unique_ptr& operator=(std::unique_ptr<T>&& u) {
|
||||||
|
std::unique_ptr<T>::reset(u.release());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
unique_ptr& operator=(unique_ptr&& u) {
|
||||||
|
std::unique_ptr<T>::reset(u.release());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
unique_ptr& operator=(T* p) {
|
||||||
|
return std::unique_ptr<T>::operator=(p);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
#endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
||||||
|
#else
|
||||||
|
// Very limited implementation of unique_ptr.
|
||||||
|
// This is provided simply to allow the C++ code generated from the default
|
||||||
|
// settings to function in C++98 environments with no modifications.
|
||||||
|
template <class T> class unique_ptr {
|
||||||
|
public:
|
||||||
|
typedef T element_type;
|
||||||
|
|
||||||
|
unique_ptr() : ptr_(nullptr) {}
|
||||||
|
explicit unique_ptr(T* p) : ptr_(p) {}
|
||||||
|
unique_ptr(unique_ptr&& u) : ptr_(nullptr) { reset(u.release()); }
|
||||||
|
unique_ptr(const unique_ptr& u) : ptr_(nullptr) {
|
||||||
|
reset(const_cast<unique_ptr*>(&u)->release());
|
||||||
|
}
|
||||||
|
~unique_ptr() { reset(); }
|
||||||
|
|
||||||
|
unique_ptr& operator=(const unique_ptr& u) {
|
||||||
|
reset(const_cast<unique_ptr*>(&u)->release());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
unique_ptr& operator=(unique_ptr&& u) {
|
||||||
|
reset(u.release());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
unique_ptr& operator=(T* p) {
|
||||||
|
reset(p);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
const T& operator*() const { return *ptr_; }
|
||||||
|
T* operator->() const { return ptr_; }
|
||||||
|
T* get() const noexcept { return ptr_; }
|
||||||
|
explicit operator bool() const { return ptr_ != nullptr; }
|
||||||
|
|
||||||
|
// modifiers
|
||||||
|
T* release() {
|
||||||
|
T* value = ptr_;
|
||||||
|
ptr_ = nullptr;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(T* p = nullptr) {
|
||||||
|
T* value = ptr_;
|
||||||
|
ptr_ = p;
|
||||||
|
if (value) delete value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(unique_ptr& u) {
|
||||||
|
T* temp_ptr = ptr_;
|
||||||
|
ptr_ = u.ptr_;
|
||||||
|
u.ptr_ = temp_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
T* ptr_;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T> bool operator==(const unique_ptr<T>& x,
|
||||||
|
const unique_ptr<T>& y) {
|
||||||
|
return x.get() == y.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T, class D> bool operator==(const unique_ptr<T>& x,
|
||||||
|
const D* y) {
|
||||||
|
return static_cast<D*>(x.get()) == y;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T> bool operator==(const unique_ptr<T>& x, intptr_t y) {
|
||||||
|
return reinterpret_cast<intptr_t>(x.get()) == y;
|
||||||
|
}
|
||||||
|
#endif // !FLATBUFFERS_CPP98_STL
|
||||||
|
|
||||||
|
} // namespace flatbuffers
|
||||||
|
|
||||||
|
#endif // FLATBUFFERS_STL_EMULATION_H_
|
||||||
@@ -17,32 +17,32 @@
|
|||||||
#ifndef FLATBUFFERS_UTIL_H_
|
#ifndef FLATBUFFERS_UTIL_H_
|
||||||
#define FLATBUFFERS_UTIL_H_
|
#define FLATBUFFERS_UTIL_H_
|
||||||
|
|
||||||
#include <fstream>
|
#include <assert.h>
|
||||||
#include <iomanip>
|
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <fstream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifndef WIN32_LEAN_AND_MEAN
|
# ifndef WIN32_LEAN_AND_MEAN
|
||||||
#define WIN32_LEAN_AND_MEAN
|
# define WIN32_LEAN_AND_MEAN
|
||||||
#endif
|
# endif
|
||||||
#ifndef NOMINMAX
|
# ifndef NOMINMAX
|
||||||
#define NOMINMAX
|
# define NOMINMAX
|
||||||
#endif
|
# endif
|
||||||
#include <windows.h>
|
# include <windows.h> // Must be included before <direct.h>
|
||||||
#include <winbase.h>
|
# include <direct.h>
|
||||||
#include <direct.h>
|
# include <winbase.h>
|
||||||
|
# undef interface // This is also important because of reasons
|
||||||
#else
|
#else
|
||||||
#include <limits.h>
|
# include <limits.h>
|
||||||
#endif
|
#endif
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "flatbuffers/base.h"
|
#include "flatbuffers/base.h"
|
||||||
|
|
||||||
|
|
||||||
namespace flatbuffers {
|
namespace flatbuffers {
|
||||||
|
|
||||||
// Convert an integer or floating point value to a string.
|
// Convert an integer or floating point value to a string.
|
||||||
@@ -60,14 +60,31 @@ template<> inline std::string NumToString<signed char>(signed char t) {
|
|||||||
template<> inline std::string NumToString<unsigned char>(unsigned char t) {
|
template<> inline std::string NumToString<unsigned char>(unsigned char t) {
|
||||||
return NumToString(static_cast<int>(t));
|
return NumToString(static_cast<int>(t));
|
||||||
}
|
}
|
||||||
|
#if defined(FLATBUFFERS_CPP98_STL)
|
||||||
|
template<> inline std::string NumToString<long long>(long long t) {
|
||||||
|
char buf[21]; // (log((1 << 63) - 1) / log(10)) + 2
|
||||||
|
snprintf(buf, sizeof(buf), "%lld", t);
|
||||||
|
return std::string(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline std::string NumToString<unsigned long long>(unsigned long long t) {
|
||||||
|
char buf[22]; // (log((1 << 63) - 1) / log(10)) + 1
|
||||||
|
snprintf(buf, sizeof(buf), "%llu", t);
|
||||||
|
return std::string(buf);
|
||||||
|
}
|
||||||
|
#endif // defined(FLATBUFFERS_CPP98_STL)
|
||||||
|
|
||||||
// Special versions for floats/doubles.
|
// Special versions for floats/doubles.
|
||||||
template<> inline std::string NumToString<double>(double t) {
|
template<typename T> std::string FloatToString(T t, int precision) {
|
||||||
// to_string() prints different numbers of digits for floats depending on
|
// to_string() prints different numbers of digits for floats depending on
|
||||||
// platform and isn't available on Android, so we use stringstream
|
// platform and isn't available on Android, so we use stringstream
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
// Use std::fixed to surpress scientific notation.
|
// Use std::fixed to surpress scientific notation.
|
||||||
ss << std::fixed << t;
|
ss << std::fixed;
|
||||||
|
// Default precision is 6, we want that to be higher for doubles.
|
||||||
|
ss << std::setprecision(precision);
|
||||||
|
ss << t;
|
||||||
auto s = ss.str();
|
auto s = ss.str();
|
||||||
// Sadly, std::fixed turns "1" into "1.00000", so here we undo that.
|
// Sadly, std::fixed turns "1" into "1.00000", so here we undo that.
|
||||||
auto p = s.find_last_not_of('0');
|
auto p = s.find_last_not_of('0');
|
||||||
@@ -77,8 +94,12 @@ template<> inline std::string NumToString<double>(double t) {
|
|||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<> inline std::string NumToString<double>(double t) {
|
||||||
|
return FloatToString(t, 12);
|
||||||
|
}
|
||||||
template<> inline std::string NumToString<float>(float t) {
|
template<> inline std::string NumToString<float>(float t) {
|
||||||
return NumToString(static_cast<double>(t));
|
return FloatToString(t, 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert an integer value to a hexadecimal string.
|
// Convert an integer value to a hexadecimal string.
|
||||||
@@ -86,10 +107,7 @@ template<> inline std::string NumToString<float>(float t) {
|
|||||||
// For example, IntToStringHex(0x23, 8) returns the string "00000023".
|
// For example, IntToStringHex(0x23, 8) returns the string "00000023".
|
||||||
inline std::string IntToStringHex(int i, int xdigits) {
|
inline std::string IntToStringHex(int i, int xdigits) {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << std::setw(xdigits)
|
ss << std::setw(xdigits) << std::setfill('0') << std::hex << std::uppercase
|
||||||
<< std::setfill('0')
|
|
||||||
<< std::hex
|
|
||||||
<< std::uppercase
|
|
||||||
<< i;
|
<< i;
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
@@ -97,21 +115,25 @@ inline std::string IntToStringHex(int i, int xdigits) {
|
|||||||
// Portable implementation of strtoll().
|
// Portable implementation of strtoll().
|
||||||
inline int64_t StringToInt(const char *str, char **endptr = nullptr,
|
inline int64_t StringToInt(const char *str, char **endptr = nullptr,
|
||||||
int base = 10) {
|
int base = 10) {
|
||||||
|
// clang-format off
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
return _strtoi64(str, endptr, base);
|
return _strtoi64(str, endptr, base);
|
||||||
#else
|
#else
|
||||||
return strtoll(str, endptr, base);
|
return strtoll(str, endptr, base);
|
||||||
#endif
|
#endif
|
||||||
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
// Portable implementation of strtoull().
|
// Portable implementation of strtoull().
|
||||||
inline uint64_t StringToUInt(const char *str, char **endptr = nullptr,
|
inline uint64_t StringToUInt(const char *str, char **endptr = nullptr,
|
||||||
int base = 10) {
|
int base = 10) {
|
||||||
|
// clang-format off
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
return _strtoui64(str, endptr, base);
|
return _strtoui64(str, endptr, base);
|
||||||
#else
|
#else
|
||||||
return strtoull(str, endptr, base);
|
return strtoull(str, endptr, base);
|
||||||
#endif
|
#endif
|
||||||
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef bool (*LoadFileFunction)(const char *filename, bool binary,
|
typedef bool (*LoadFileFunction)(const char *filename, bool binary,
|
||||||
@@ -120,9 +142,8 @@ typedef bool (*FileExistsFunction)(const char *filename);
|
|||||||
|
|
||||||
LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function);
|
LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function);
|
||||||
|
|
||||||
FileExistsFunction SetFileExistsFunction(FileExistsFunction
|
FileExistsFunction SetFileExistsFunction(
|
||||||
file_exists_function);
|
FileExistsFunction file_exists_function);
|
||||||
|
|
||||||
|
|
||||||
// Check if file "name" exists.
|
// Check if file "name" exists.
|
||||||
bool FileExists(const char *name);
|
bool FileExists(const char *name);
|
||||||
@@ -202,13 +223,18 @@ inline std::string ConCatPathFileName(const std::string &path,
|
|||||||
const std::string &filename) {
|
const std::string &filename) {
|
||||||
std::string filepath = path;
|
std::string filepath = path;
|
||||||
if (filepath.length()) {
|
if (filepath.length()) {
|
||||||
if (filepath.back() == kPathSeparatorWindows) {
|
char &filepath_last_character = string_back(filepath);
|
||||||
filepath.back() = kPathSeparator;
|
if (filepath_last_character == kPathSeparatorWindows) {
|
||||||
} else if (filepath.back() != kPathSeparator) {
|
filepath_last_character = kPathSeparator;
|
||||||
|
} else if (filepath_last_character != kPathSeparator) {
|
||||||
filepath += kPathSeparator;
|
filepath += kPathSeparator;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
filepath += filename;
|
filepath += filename;
|
||||||
|
// Ignore './' at the start of filepath.
|
||||||
|
if (filepath[0] == '.' && filepath[1] == kPathSeparator) {
|
||||||
|
filepath.erase(0, 2);
|
||||||
|
}
|
||||||
return filepath;
|
return filepath;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,16 +250,19 @@ inline std::string PosixPath(const char *path) {
|
|||||||
inline void EnsureDirExists(const std::string &filepath) {
|
inline void EnsureDirExists(const std::string &filepath) {
|
||||||
auto parent = StripFileName(filepath);
|
auto parent = StripFileName(filepath);
|
||||||
if (parent.length()) EnsureDirExists(parent);
|
if (parent.length()) EnsureDirExists(parent);
|
||||||
|
// clang-format off
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
(void)_mkdir(filepath.c_str());
|
(void)_mkdir(filepath.c_str());
|
||||||
#else
|
#else
|
||||||
mkdir(filepath.c_str(), S_IRWXU|S_IRGRP|S_IXGRP);
|
mkdir(filepath.c_str(), S_IRWXU|S_IRGRP|S_IXGRP);
|
||||||
#endif
|
#endif
|
||||||
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
// Obtains the absolute path from any other path.
|
// Obtains the absolute path from any other path.
|
||||||
// Returns the input path if the absolute path couldn't be resolved.
|
// Returns the input path if the absolute path couldn't be resolved.
|
||||||
inline std::string AbsolutePath(const std::string &filepath) {
|
inline std::string AbsolutePath(const std::string &filepath) {
|
||||||
|
// clang-format off
|
||||||
#ifdef FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
|
#ifdef FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
|
||||||
return filepath;
|
return filepath;
|
||||||
#else
|
#else
|
||||||
@@ -247,6 +276,7 @@ inline std::string AbsolutePath(const std::string &filepath) {
|
|||||||
? abs_path
|
? abs_path
|
||||||
: filepath;
|
: filepath;
|
||||||
#endif // FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
|
#endif // FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
|
||||||
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
// To and from UTF-8 unicode conversion functions
|
// To and from UTF-8 unicode conversion functions
|
||||||
@@ -264,7 +294,7 @@ inline int ToUTF8(uint32_t ucc, std::string *out) {
|
|||||||
uint32_t remain_bits = i * 6;
|
uint32_t remain_bits = i * 6;
|
||||||
// Store first byte:
|
// Store first byte:
|
||||||
(*out) += static_cast<char>((0xFE << (max_bits - remain_bits)) |
|
(*out) += static_cast<char>((0xFE << (max_bits - remain_bits)) |
|
||||||
(ucc >> remain_bits));
|
(ucc >> remain_bits));
|
||||||
// Store remaining bytes:
|
// Store remaining bytes:
|
||||||
for (int j = i - 1; j >= 0; j--) {
|
for (int j = i - 1; j >= 0; j--) {
|
||||||
(*out) += static_cast<char>(((ucc >> (j * 6)) & 0x3F) | 0x80);
|
(*out) += static_cast<char>(((ucc >> (j * 6)) & 0x3F) | 0x80);
|
||||||
@@ -291,12 +321,10 @@ inline int FromUTF8(const char **in) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((**in << len) & 0x80) return -1; // Bit after leading 1's must be 0.
|
if ((static_cast<const unsigned char>(**in) << len) & 0x80) return -1; // Bit after leading 1's must be 0.
|
||||||
if (!len) return *(*in)++;
|
if (!len) return *(*in)++;
|
||||||
// UTF-8 encoded values with a length are between 2 and 4 bytes.
|
// UTF-8 encoded values with a length are between 2 and 4 bytes.
|
||||||
if (len < 2 || len > 4) {
|
if (len < 2 || len > 4) { return -1; }
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// Grab initial bits of the code.
|
// Grab initial bits of the code.
|
||||||
int ucc = *(*in)++ & ((1 << (7 - len)) - 1);
|
int ucc = *(*in)++ & ((1 << (7 - len)) - 1);
|
||||||
for (int i = 0; i < len - 1; i++) {
|
for (int i = 0; i < len - 1; i++) {
|
||||||
@@ -306,28 +334,20 @@ inline int FromUTF8(const char **in) {
|
|||||||
}
|
}
|
||||||
// UTF-8 cannot encode values between 0xD800 and 0xDFFF (reserved for
|
// UTF-8 cannot encode values between 0xD800 and 0xDFFF (reserved for
|
||||||
// UTF-16 surrogate pairs).
|
// UTF-16 surrogate pairs).
|
||||||
if (ucc >= 0xD800 && ucc <= 0xDFFF) {
|
if (ucc >= 0xD800 && ucc <= 0xDFFF) { return -1; }
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
// UTF-8 must represent code points in their shortest possible encoding.
|
// UTF-8 must represent code points in their shortest possible encoding.
|
||||||
switch (len) {
|
switch (len) {
|
||||||
case 2:
|
case 2:
|
||||||
// Two bytes of UTF-8 can represent code points from U+0080 to U+07FF.
|
// Two bytes of UTF-8 can represent code points from U+0080 to U+07FF.
|
||||||
if (ucc < 0x0080 || ucc > 0x07FF) {
|
if (ucc < 0x0080 || ucc > 0x07FF) { return -1; }
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
// Three bytes of UTF-8 can represent code points from U+0800 to U+FFFF.
|
// Three bytes of UTF-8 can represent code points from U+0800 to U+FFFF.
|
||||||
if (ucc < 0x0800 || ucc > 0xFFFF) {
|
if (ucc < 0x0800 || ucc > 0xFFFF) { return -1; }
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
// Four bytes of UTF-8 can represent code points from U+10000 to U+10FFFF.
|
// Four bytes of UTF-8 can represent code points from U+10000 to U+10FFFF.
|
||||||
if (ucc < 0x10000 || ucc > 0x10FFFF) {
|
if (ucc < 0x10000 || ucc > 0x10FFFF) { return -1; }
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return ucc;
|
return ucc;
|
||||||
@@ -406,7 +426,8 @@ inline bool EscapeString(const char *s, size_t length, std::string *_text,
|
|||||||
text += "\\u";
|
text += "\\u";
|
||||||
text += IntToStringHex(ucc, 4);
|
text += IntToStringHex(ucc, 4);
|
||||||
} else if (ucc <= 0x10FFFF) {
|
} else if (ucc <= 0x10FFFF) {
|
||||||
// Encode Unicode SMP values to a surrogate pair using two \u escapes.
|
// Encode Unicode SMP values to a surrogate pair using two \u
|
||||||
|
// escapes.
|
||||||
uint32_t base = ucc - 0x10000;
|
uint32_t base = ucc - 0x10000;
|
||||||
auto high_surrogate = (base >> 10) + 0xD800;
|
auto high_surrogate = (base >> 10) + 0xD800;
|
||||||
auto low_surrogate = (base & 0x03FF) + 0xDC00;
|
auto low_surrogate = (base & 0x03FF) + 0xDC00;
|
||||||
|
|||||||
58
java/com/google/flatbuffers/ByteBufferUtil.java
Normal file
58
java/com/google/flatbuffers/ByteBufferUtil.java
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 Google Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.flatbuffers;
|
||||||
|
|
||||||
|
import static com.google.flatbuffers.Constants.*;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
/// @file
|
||||||
|
/// @addtogroup flatbuffers_java_api
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that collects utility functions around `ByteBuffer`.
|
||||||
|
*/
|
||||||
|
public class ByteBufferUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract the size prefix from a `ByteBuffer`.
|
||||||
|
*
|
||||||
|
* @param bb a size-prefixed buffer
|
||||||
|
* @return the size prefix
|
||||||
|
*/
|
||||||
|
public static int getSizePrefix(ByteBuffer bb) {
|
||||||
|
return bb.getInt(bb.position());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a duplicate of a size-prefixed `ByteBuffer` that has its position
|
||||||
|
* advanced just past the size prefix.
|
||||||
|
*
|
||||||
|
* @param bb a size-prefixed buffer
|
||||||
|
* @return a new buffer on the same underlying data that has skipped the
|
||||||
|
* size prefix
|
||||||
|
*/
|
||||||
|
public static ByteBuffer removeSizePrefix(ByteBuffer bb) {
|
||||||
|
ByteBuffer s = bb.duplicate();
|
||||||
|
s.position(s.position() + SIZE_PREFIX_LENGTH);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
@@ -37,6 +37,8 @@ public class Constants {
|
|||||||
static final int SIZEOF_DOUBLE = 8;
|
static final int SIZEOF_DOUBLE = 8;
|
||||||
/** The number of bytes in a file identifier. */
|
/** The number of bytes in a file identifier. */
|
||||||
static final int FILE_IDENTIFIER_LENGTH = 4;
|
static final int FILE_IDENTIFIER_LENGTH = 4;
|
||||||
|
/** The number of bytes in a size prefix. */
|
||||||
|
public static final int SIZE_PREFIX_LENGTH = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
|||||||
@@ -18,13 +18,13 @@ package com.google.flatbuffers;
|
|||||||
|
|
||||||
import static com.google.flatbuffers.Constants.*;
|
import static com.google.flatbuffers.Constants.*;
|
||||||
|
|
||||||
import java.nio.CharBuffer;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.nio.*;
|
||||||
import java.nio.charset.CharacterCodingException;
|
import java.nio.charset.CharacterCodingException;
|
||||||
import java.nio.charset.CharsetEncoder;
|
import java.nio.charset.CharsetEncoder;
|
||||||
import java.nio.charset.CoderResult;
|
import java.nio.charset.CoderResult;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.ByteOrder;
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
/// @file
|
/// @file
|
||||||
@@ -52,26 +52,51 @@ public class FlatBufferBuilder {
|
|||||||
boolean force_defaults = false; // False omits default values from the serialized data.
|
boolean force_defaults = false; // False omits default values from the serialized data.
|
||||||
CharsetEncoder encoder = utf8charset.newEncoder();
|
CharsetEncoder encoder = utf8charset.newEncoder();
|
||||||
ByteBuffer dst;
|
ByteBuffer dst;
|
||||||
|
ByteBufferFactory bb_factory; // Factory for allocating the internal buffer
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start with a buffer of size `initial_size`, then grow as required.
|
||||||
|
*
|
||||||
|
* @param initial_size The initial size of the internal buffer to use.
|
||||||
|
* @param bb_factory The factory to be used for allocating the internal buffer
|
||||||
|
*/
|
||||||
|
public FlatBufferBuilder(int initial_size, ByteBufferFactory bb_factory) {
|
||||||
|
if (initial_size <= 0) initial_size = 1;
|
||||||
|
space = initial_size;
|
||||||
|
this.bb_factory = bb_factory;
|
||||||
|
bb = bb_factory.newByteBuffer(initial_size);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start with a buffer of size `initial_size`, then grow as required.
|
* Start with a buffer of size `initial_size`, then grow as required.
|
||||||
*
|
*
|
||||||
* @param initial_size The initial size of the internal buffer to use.
|
* @param initial_size The initial size of the internal buffer to use.
|
||||||
*/
|
*/
|
||||||
public FlatBufferBuilder(int initial_size) {
|
public FlatBufferBuilder(int initial_size) {
|
||||||
if (initial_size <= 0) initial_size = 1;
|
this(initial_size, new HeapByteBufferFactory());
|
||||||
space = initial_size;
|
|
||||||
bb = newByteBuffer(initial_size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start with a buffer of 1KiB, then grow as required.
|
* Start with a buffer of 1KiB, then grow as required.
|
||||||
*/
|
*/
|
||||||
public FlatBufferBuilder() {
|
public FlatBufferBuilder() {
|
||||||
this(1024);
|
this(1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alternative constructor allowing reuse of {@link ByteBuffer}s. The builder
|
||||||
|
* can still grow the buffer as necessary. User classes should make sure
|
||||||
|
* to call {@link #dataBuffer()} to obtain the resulting encoded message.
|
||||||
|
*
|
||||||
|
* @param existing_bb The byte buffer to reuse.
|
||||||
|
* @param bb_factory The factory to be used for allocating a new internal buffer if
|
||||||
|
* the existing buffer needs to grow
|
||||||
|
*/
|
||||||
|
public FlatBufferBuilder(ByteBuffer existing_bb, ByteBufferFactory bb_factory) {
|
||||||
|
init(existing_bb, bb_factory);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Alternative constructor allowing reuse of {@link ByteBuffer}s. The builder
|
* Alternative constructor allowing reuse of {@link ByteBuffer}s. The builder
|
||||||
* can still grow the buffer as necessary. User classes should make sure
|
* can still grow the buffer as necessary. User classes should make sure
|
||||||
@@ -80,7 +105,7 @@ public class FlatBufferBuilder {
|
|||||||
* @param existing_bb The byte buffer to reuse.
|
* @param existing_bb The byte buffer to reuse.
|
||||||
*/
|
*/
|
||||||
public FlatBufferBuilder(ByteBuffer existing_bb) {
|
public FlatBufferBuilder(ByteBuffer existing_bb) {
|
||||||
init(existing_bb);
|
init(existing_bb, new HeapByteBufferFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,9 +114,12 @@ public class FlatBufferBuilder {
|
|||||||
* objects that have been allocated for temporary storage.
|
* objects that have been allocated for temporary storage.
|
||||||
*
|
*
|
||||||
* @param existing_bb The byte buffer to reuse.
|
* @param existing_bb The byte buffer to reuse.
|
||||||
|
* @param bb_factory The factory to be used for allocating a new internal buffer if
|
||||||
|
* the existing buffer needs to grow
|
||||||
* @return Returns `this`.
|
* @return Returns `this`.
|
||||||
*/
|
*/
|
||||||
public FlatBufferBuilder init(ByteBuffer existing_bb){
|
public FlatBufferBuilder init(ByteBuffer existing_bb, ByteBufferFactory bb_factory){
|
||||||
|
this.bb_factory = bb_factory;
|
||||||
bb = existing_bb;
|
bb = existing_bb;
|
||||||
bb.clear();
|
bb.clear();
|
||||||
bb.order(ByteOrder.LITTLE_ENDIAN);
|
bb.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
@@ -106,6 +134,39 @@ public class FlatBufferBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An interface that provides a user of the FlatBufferBuilder class the ability to specify
|
||||||
|
* the method in which the internal buffer gets allocated. This allows for alternatives
|
||||||
|
* to the default behavior, which is to allocate memory for a new byte-array
|
||||||
|
* backed `ByteBuffer` array inside the JVM.
|
||||||
|
*
|
||||||
|
* The FlatBufferBuilder class contains the HeapByteBufferFactory class to
|
||||||
|
* preserve the default behavior in the event that the user does not provide
|
||||||
|
* their own implementation of this interface.
|
||||||
|
*/
|
||||||
|
public interface ByteBufferFactory {
|
||||||
|
/**
|
||||||
|
* Create a `ByteBuffer` with a given capacity.
|
||||||
|
*
|
||||||
|
* @param capacity The size of the `ByteBuffer` to allocate.
|
||||||
|
* @return Returns the new `ByteBuffer` that was allocated.
|
||||||
|
*/
|
||||||
|
ByteBuffer newByteBuffer(int capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of the ByteBufferFactory interface that is used when
|
||||||
|
* one is not provided by the user.
|
||||||
|
*
|
||||||
|
* Allocate memory for a new byte-array backed `ByteBuffer` array inside the JVM.
|
||||||
|
*/
|
||||||
|
public static final class HeapByteBufferFactory implements ByteBufferFactory {
|
||||||
|
@Override
|
||||||
|
public ByteBuffer newByteBuffer(int capacity) {
|
||||||
|
return ByteBuffer.allocate(capacity).order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reset the FlatBufferBuilder by purging all data that it holds.
|
* Reset the FlatBufferBuilder by purging all data that it holds.
|
||||||
*/
|
*/
|
||||||
@@ -122,34 +183,22 @@ public class FlatBufferBuilder {
|
|||||||
vector_num_elems = 0;
|
vector_num_elems = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @cond FLATBUFFERS_INTERNAL
|
|
||||||
/**
|
|
||||||
* Create a `ByteBuffer` with a given capacity.
|
|
||||||
*
|
|
||||||
* @param capacity The size of the `ByteBuffer` to allocate.
|
|
||||||
* @return Returns the new `ByteBuffer` that was allocated.
|
|
||||||
*/
|
|
||||||
static ByteBuffer newByteBuffer(int capacity) {
|
|
||||||
ByteBuffer newbb = ByteBuffer.allocate(capacity);
|
|
||||||
newbb.order(ByteOrder.LITTLE_ENDIAN);
|
|
||||||
return newbb;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Doubles the size of the backing {@link ByteBuffer} and copies the old data towards the
|
* Doubles the size of the backing {@link ByteBuffer} and copies the old data towards the
|
||||||
* end of the new buffer (since we build the buffer backwards).
|
* end of the new buffer (since we build the buffer backwards).
|
||||||
*
|
*
|
||||||
* @param bb The current buffer with the existing data.
|
* @param bb The current buffer with the existing data.
|
||||||
|
* @param bb_factory The factory to be used for allocating the new internal buffer
|
||||||
* @return A new byte buffer with the old data copied copied to it. The data is
|
* @return A new byte buffer with the old data copied copied to it. The data is
|
||||||
* located at the end of the buffer.
|
* located at the end of the buffer.
|
||||||
*/
|
*/
|
||||||
static ByteBuffer growByteBuffer(ByteBuffer bb) {
|
static ByteBuffer growByteBuffer(ByteBuffer bb, ByteBufferFactory bb_factory) {
|
||||||
int old_buf_size = bb.capacity();
|
int old_buf_size = bb.capacity();
|
||||||
if ((old_buf_size & 0xC0000000) != 0) // Ensure we don't grow beyond what fits in an int.
|
if ((old_buf_size & 0xC0000000) != 0) // Ensure we don't grow beyond what fits in an int.
|
||||||
throw new AssertionError("FlatBuffers: cannot grow buffer beyond 2 gigabytes.");
|
throw new AssertionError("FlatBuffers: cannot grow buffer beyond 2 gigabytes.");
|
||||||
int new_buf_size = old_buf_size << 1;
|
int new_buf_size = old_buf_size == 0 ? 1 : old_buf_size << 1;
|
||||||
bb.position(0);
|
bb.position(0);
|
||||||
ByteBuffer nbb = newByteBuffer(new_buf_size);
|
ByteBuffer nbb = bb_factory.newByteBuffer(new_buf_size);
|
||||||
nbb.position(new_buf_size - old_buf_size);
|
nbb.position(new_buf_size - old_buf_size);
|
||||||
nbb.put(bb);
|
nbb.put(bb);
|
||||||
return nbb;
|
return nbb;
|
||||||
@@ -192,7 +241,7 @@ public class FlatBufferBuilder {
|
|||||||
// Reallocate the buffer if needed.
|
// Reallocate the buffer if needed.
|
||||||
while (space < align_size + size + additional_bytes) {
|
while (space < align_size + size + additional_bytes) {
|
||||||
int old_buf_size = bb.capacity();
|
int old_buf_size = bb.capacity();
|
||||||
bb = growByteBuffer(bb);
|
bb = growByteBuffer(bb, bb_factory);
|
||||||
space += bb.capacity() - old_buf_size;
|
space += bb.capacity() - old_buf_size;
|
||||||
}
|
}
|
||||||
pad(align_size);
|
pad(align_size);
|
||||||
@@ -695,7 +744,11 @@ public class FlatBufferBuilder {
|
|||||||
addInt(0);
|
addInt(0);
|
||||||
int vtableloc = offset();
|
int vtableloc = offset();
|
||||||
// Write out the current vtable.
|
// Write out the current vtable.
|
||||||
for (int i = vtable_in_use - 1; i >= 0 ; i--) {
|
int i = vtable_in_use - 1;
|
||||||
|
// Trim trailing zeroes.
|
||||||
|
for (; i >= 0 && vtable[i] == 0; i--) {}
|
||||||
|
int trimmed_size = i + 1;
|
||||||
|
for (; i >= 0 ; i--) {
|
||||||
// Offset relative to the start of the table.
|
// Offset relative to the start of the table.
|
||||||
short off = (short)(vtable[i] != 0 ? vtableloc - vtable[i] : 0);
|
short off = (short)(vtable[i] != 0 ? vtableloc - vtable[i] : 0);
|
||||||
addShort(off);
|
addShort(off);
|
||||||
@@ -703,12 +756,12 @@ public class FlatBufferBuilder {
|
|||||||
|
|
||||||
final int standard_fields = 2; // The fields below:
|
final int standard_fields = 2; // The fields below:
|
||||||
addShort((short)(vtableloc - object_start));
|
addShort((short)(vtableloc - object_start));
|
||||||
addShort((short)((vtable_in_use + standard_fields) * SIZEOF_SHORT));
|
addShort((short)((trimmed_size + standard_fields) * SIZEOF_SHORT));
|
||||||
|
|
||||||
// Search for an existing vtable that matches the current one.
|
// Search for an existing vtable that matches the current one.
|
||||||
int existing_vtable = 0;
|
int existing_vtable = 0;
|
||||||
outer_loop:
|
outer_loop:
|
||||||
for (int i = 0; i < num_vtables; i++) {
|
for (i = 0; i < num_vtables; i++) {
|
||||||
int vt1 = bb.capacity() - vtables[i];
|
int vt1 = bb.capacity() - vtables[i];
|
||||||
int vt2 = space;
|
int vt2 = space;
|
||||||
short len = bb.getShort(vt1);
|
short len = bb.getShort(vt1);
|
||||||
@@ -763,14 +816,55 @@ public class FlatBufferBuilder {
|
|||||||
* Finalize a buffer, pointing to the given `root_table`.
|
* Finalize a buffer, pointing to the given `root_table`.
|
||||||
*
|
*
|
||||||
* @param root_table An offset to be added to the buffer.
|
* @param root_table An offset to be added to the buffer.
|
||||||
|
* @param size_prefix Whether to prefix the size to the buffer.
|
||||||
*/
|
*/
|
||||||
public void finish(int root_table) {
|
protected void finish(int root_table, boolean size_prefix) {
|
||||||
prep(minalign, SIZEOF_INT);
|
prep(minalign, SIZEOF_INT + (size_prefix ? SIZEOF_INT : 0));
|
||||||
addOffset(root_table);
|
addOffset(root_table);
|
||||||
|
if (size_prefix) {
|
||||||
|
addInt(bb.capacity() - space);
|
||||||
|
}
|
||||||
bb.position(space);
|
bb.position(space);
|
||||||
finished = true;
|
finished = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize a buffer, pointing to the given `root_table`.
|
||||||
|
*
|
||||||
|
* @param root_table An offset to be added to the buffer.
|
||||||
|
*/
|
||||||
|
public void finish(int root_table) {
|
||||||
|
finish(root_table, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize a buffer, pointing to the given `root_table`, with the size prefixed.
|
||||||
|
*
|
||||||
|
* @param root_table An offset to be added to the buffer.
|
||||||
|
*/
|
||||||
|
public void finishSizePrefixed(int root_table) {
|
||||||
|
finish(root_table, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finalize a buffer, pointing to the given `root_table`.
|
||||||
|
*
|
||||||
|
* @param root_table An offset to be added to the buffer.
|
||||||
|
* @param file_identifier A FlatBuffer file identifier to be added to the buffer before
|
||||||
|
* `root_table`.
|
||||||
|
* @param size_prefix Whether to prefix the size to the buffer.
|
||||||
|
*/
|
||||||
|
protected void finish(int root_table, String file_identifier, boolean size_prefix) {
|
||||||
|
prep(minalign, SIZEOF_INT + FILE_IDENTIFIER_LENGTH + (size_prefix ? SIZEOF_INT : 0));
|
||||||
|
if (file_identifier.length() != FILE_IDENTIFIER_LENGTH)
|
||||||
|
throw new AssertionError("FlatBuffers: file identifier must be length " +
|
||||||
|
FILE_IDENTIFIER_LENGTH);
|
||||||
|
for (int i = FILE_IDENTIFIER_LENGTH - 1; i >= 0; i--) {
|
||||||
|
addByte((byte)file_identifier.charAt(i));
|
||||||
|
}
|
||||||
|
finish(root_table, size_prefix);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finalize a buffer, pointing to the given `root_table`.
|
* Finalize a buffer, pointing to the given `root_table`.
|
||||||
*
|
*
|
||||||
@@ -779,14 +873,18 @@ public class FlatBufferBuilder {
|
|||||||
* `root_table`.
|
* `root_table`.
|
||||||
*/
|
*/
|
||||||
public void finish(int root_table, String file_identifier) {
|
public void finish(int root_table, String file_identifier) {
|
||||||
prep(minalign, SIZEOF_INT + FILE_IDENTIFIER_LENGTH);
|
finish(root_table, file_identifier, false);
|
||||||
if (file_identifier.length() != FILE_IDENTIFIER_LENGTH)
|
}
|
||||||
throw new AssertionError("FlatBuffers: file identifier must be length " +
|
|
||||||
FILE_IDENTIFIER_LENGTH);
|
/**
|
||||||
for (int i = FILE_IDENTIFIER_LENGTH - 1; i >= 0; i--) {
|
* Finalize a buffer, pointing to the given `root_table`, with the size prefixed.
|
||||||
addByte((byte)file_identifier.charAt(i));
|
*
|
||||||
}
|
* @param root_table An offset to be added to the buffer.
|
||||||
finish(root_table);
|
* @param file_identifier A FlatBuffer file identifier to be added to the buffer before
|
||||||
|
* `root_table`.
|
||||||
|
*/
|
||||||
|
public void finishSizePrefixed(int root_table, String file_identifier) {
|
||||||
|
finish(root_table, file_identifier, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -853,6 +951,41 @@ public class FlatBufferBuilder {
|
|||||||
public byte[] sizedByteArray() {
|
public byte[] sizedByteArray() {
|
||||||
return sizedByteArray(space, bb.capacity() - space);
|
return sizedByteArray(space, bb.capacity() - space);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A utility function to return an InputStream to the ByteBuffer data
|
||||||
|
*
|
||||||
|
* @return An InputStream that starts at the beginning of the ByteBuffer data
|
||||||
|
* and can read to the end of it.
|
||||||
|
*/
|
||||||
|
public InputStream sizedInputStream() {
|
||||||
|
finished();
|
||||||
|
ByteBuffer duplicate = bb.duplicate();
|
||||||
|
duplicate.position(space);
|
||||||
|
duplicate.limit(bb.capacity());
|
||||||
|
return new ByteBufferBackedInputStream(duplicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class that allows a user to create an InputStream from a ByteBuffer.
|
||||||
|
*/
|
||||||
|
static class ByteBufferBackedInputStream extends InputStream {
|
||||||
|
|
||||||
|
ByteBuffer buf;
|
||||||
|
|
||||||
|
public ByteBufferBackedInputStream(ByteBuffer buf) {
|
||||||
|
this.buf = buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int read() throws IOException {
|
||||||
|
try {
|
||||||
|
return buf.get() & 0xFF;
|
||||||
|
} catch(BufferUnderflowException e) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ public class Table {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected static int __offset(int vtable_offset, int offset, ByteBuffer bb) {
|
protected static int __offset(int vtable_offset, int offset, ByteBuffer bb) {
|
||||||
int vtable = bb.array().length - offset;
|
int vtable = bb.capacity() - offset;
|
||||||
return bb.getShort(vtable + vtable_offset - bb.getInt(vtable)) + vtable;
|
return bb.getShort(vtable + vtable_offset - bb.getInt(vtable)) + vtable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ public class Table {
|
|||||||
cr.throwException();
|
cr.throwException();
|
||||||
}
|
}
|
||||||
} catch (CharacterCodingException x) {
|
} catch (CharacterCodingException x) {
|
||||||
throw new Error(x);
|
throw new RuntimeException(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dst.flip().toString();
|
return dst.flip().toString();
|
||||||
@@ -172,6 +172,27 @@ public class Table {
|
|||||||
return bb;
|
return bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize vector as a ByteBuffer.
|
||||||
|
*
|
||||||
|
* This is more efficient than using duplicate, since it doesn't copy the data
|
||||||
|
* nor allocattes a new {@link ByteBuffer}, creating no garbage to be collected.
|
||||||
|
*
|
||||||
|
* @param bb The {@link ByteBuffer} for the array
|
||||||
|
* @param vector_offset The position of the vector in the byte buffer
|
||||||
|
* @param elem_size The size of each element in the array
|
||||||
|
* @return The {@link ByteBuffer} for the array
|
||||||
|
*/
|
||||||
|
protected ByteBuffer __vector_in_bytebuffer(ByteBuffer bb, int vector_offset, int elem_size) {
|
||||||
|
int o = this.__offset(vector_offset);
|
||||||
|
if (o == 0) return null;
|
||||||
|
int vectorstart = __vector(o);
|
||||||
|
bb.rewind();
|
||||||
|
bb.limit(vectorstart + __vector_len(o) * elem_size);
|
||||||
|
bb.position(vectorstart);
|
||||||
|
return bb;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize any Table-derived type to point to the union at the given `offset`.
|
* Initialize any Table-derived type to point to the union at the given `offset`.
|
||||||
*
|
*
|
||||||
@@ -245,10 +266,9 @@ public class Table {
|
|||||||
int startPos_1 = offset_1 + SIZEOF_INT;
|
int startPos_1 = offset_1 + SIZEOF_INT;
|
||||||
int startPos_2 = offset_2 + SIZEOF_INT;
|
int startPos_2 = offset_2 + SIZEOF_INT;
|
||||||
int len = Math.min(len_1, len_2);
|
int len = Math.min(len_1, len_2);
|
||||||
byte[] bbArray = bb.array();
|
|
||||||
for(int i = 0; i < len; i++) {
|
for(int i = 0; i < len; i++) {
|
||||||
if (bbArray[i + startPos_1] != bbArray[i + startPos_2])
|
if (bb.get(i + startPos_1) != bb.get(i + startPos_2))
|
||||||
return bbArray[i + startPos_1] - bbArray[i + startPos_2];
|
return bb.get(i + startPos_1) - bb.get(i + startPos_2);
|
||||||
}
|
}
|
||||||
return len_1 - len_2;
|
return len_1 - len_2;
|
||||||
}
|
}
|
||||||
@@ -266,10 +286,9 @@ public class Table {
|
|||||||
int len_2 = key.length;
|
int len_2 = key.length;
|
||||||
int startPos_1 = offset_1 + Constants.SIZEOF_INT;
|
int startPos_1 = offset_1 + Constants.SIZEOF_INT;
|
||||||
int len = Math.min(len_1, len_2);
|
int len = Math.min(len_1, len_2);
|
||||||
byte[] bbArray = bb.array();
|
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
if (bbArray[i + startPos_1] != key[i])
|
if (bb.get(i + startPos_1) != key[i])
|
||||||
return bbArray[i + startPos_1] - key[i];
|
return bb.get(i + startPos_1) - key[i];
|
||||||
}
|
}
|
||||||
return len_1 - len_2;
|
return len_1 - len_2;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -604,23 +604,28 @@ flatbuffers.Builder.prototype.endObject = function() {
|
|||||||
this.addInt32(0);
|
this.addInt32(0);
|
||||||
var vtableloc = this.offset();
|
var vtableloc = this.offset();
|
||||||
|
|
||||||
|
// Trim trailing zeroes.
|
||||||
|
var i = this.vtable_in_use - 1;
|
||||||
|
for (; i >= 0 && this.vtable[i] == 0; i--) {}
|
||||||
|
var trimmed_size = i + 1;
|
||||||
|
|
||||||
// Write out the current vtable.
|
// Write out the current vtable.
|
||||||
for (var i = this.vtable_in_use - 1; i >= 0; i--) {
|
for (; i >= 0; i--) {
|
||||||
// Offset relative to the start of the table.
|
// Offset relative to the start of the table.
|
||||||
this.addInt16(this.vtable[i] != 0 ? vtableloc - this.vtable[i] : 0);
|
this.addInt16(this.vtable[i] != 0 ? vtableloc - this.vtable[i] : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
var standard_fields = 2; // The fields below:
|
var standard_fields = 2; // The fields below:
|
||||||
this.addInt16(vtableloc - this.object_start);
|
this.addInt16(vtableloc - this.object_start);
|
||||||
this.addInt16((this.vtable_in_use + standard_fields) * flatbuffers.SIZEOF_SHORT);
|
var len = (trimmed_size + standard_fields) * flatbuffers.SIZEOF_SHORT;
|
||||||
|
this.addInt16(len);
|
||||||
|
|
||||||
// Search for an existing vtable that matches the current one.
|
// Search for an existing vtable that matches the current one.
|
||||||
var existing_vtable = 0;
|
var existing_vtable = 0;
|
||||||
|
var vt1 = this.space;
|
||||||
outer_loop:
|
outer_loop:
|
||||||
for (var i = 0; i < this.vtables.length; i++) {
|
for (i = 0; i < this.vtables.length; i++) {
|
||||||
var vt1 = this.bb.capacity() - this.vtables[i];
|
var vt2 = this.bb.capacity() - this.vtables[i];
|
||||||
var vt2 = this.space;
|
|
||||||
var len = this.bb.readInt16(vt1);
|
|
||||||
if (len == this.bb.readInt16(vt2)) {
|
if (len == this.bb.readInt16(vt2)) {
|
||||||
for (var j = flatbuffers.SIZEOF_SHORT; j < len; j += flatbuffers.SIZEOF_SHORT) {
|
for (var j = flatbuffers.SIZEOF_SHORT; j < len; j += flatbuffers.SIZEOF_SHORT) {
|
||||||
if (this.bb.readInt16(vt1 + j) != this.bb.readInt16(vt2 + j)) {
|
if (this.bb.readInt16(vt1 + j) != this.bb.readInt16(vt2 + j)) {
|
||||||
|
|||||||
72
net/FlatBuffers/ByteBuffer.cs
Executable file → Normal file
72
net/FlatBuffers/ByteBuffer.cs
Executable file → Normal file
@@ -30,6 +30,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace FlatBuffers
|
namespace FlatBuffers
|
||||||
{
|
{
|
||||||
@@ -38,12 +40,12 @@ namespace FlatBuffers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ByteBuffer
|
public class ByteBuffer
|
||||||
{
|
{
|
||||||
private readonly byte[] _buffer;
|
protected byte[] _buffer;
|
||||||
private int _pos; // Must track start of the buffer.
|
private int _pos; // Must track start of the buffer.
|
||||||
|
|
||||||
public int Length { get { return _buffer.Length; } }
|
public int Length { get { return _buffer.Length; } }
|
||||||
|
|
||||||
public byte[] Data { get { return _buffer; } }
|
public ByteBuffer(int size) : this(new byte[size]) { }
|
||||||
|
|
||||||
public ByteBuffer(byte[] buffer) : this(buffer, 0) { }
|
public ByteBuffer(byte[] buffer) : this(buffer, 0) { }
|
||||||
|
|
||||||
@@ -63,11 +65,64 @@ namespace FlatBuffers
|
|||||||
_pos = 0;
|
_pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a new ByteBuffer on the same underlying data.
|
||||||
|
// The new ByteBuffer's position will be same as this buffer's.
|
||||||
|
public ByteBuffer Duplicate()
|
||||||
|
{
|
||||||
|
return new ByteBuffer(_buffer, Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increases the size of the ByteBuffer, and copies the old data towards
|
||||||
|
// the end of the new buffer.
|
||||||
|
public void GrowFront(int newSize)
|
||||||
|
{
|
||||||
|
if ((Length & 0xC0000000) != 0)
|
||||||
|
throw new Exception(
|
||||||
|
"ByteBuffer: cannot grow buffer beyond 2 gigabytes.");
|
||||||
|
|
||||||
|
if (newSize < Length)
|
||||||
|
throw new Exception("ByteBuffer: cannot truncate buffer.");
|
||||||
|
|
||||||
|
byte[] newBuffer = new byte[newSize];
|
||||||
|
Buffer.BlockCopy(_buffer, 0, newBuffer, newSize - Length,
|
||||||
|
Length);
|
||||||
|
_buffer = newBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] ToArray(int pos, int len)
|
||||||
|
{
|
||||||
|
byte[] arr = new byte[len];
|
||||||
|
Buffer.BlockCopy(_buffer, pos, arr, 0, len);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] ToSizedArray()
|
||||||
|
{
|
||||||
|
return ToArray(Position, Length - Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] ToFullArray()
|
||||||
|
{
|
||||||
|
return ToArray(0, Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArraySegment<byte> ToArraySegment(int pos, int len)
|
||||||
|
{
|
||||||
|
return new ArraySegment<byte>(_buffer, pos, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemoryStream ToMemoryStream(int pos, int len)
|
||||||
|
{
|
||||||
|
return new MemoryStream(_buffer, pos, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !UNSAFE_BYTEBUFFER
|
||||||
// Pre-allocated helper arrays for convertion.
|
// Pre-allocated helper arrays for convertion.
|
||||||
private float[] floathelper = new[] { 0.0f };
|
private float[] floathelper = new[] { 0.0f };
|
||||||
private int[] inthelper = new[] { 0 };
|
private int[] inthelper = new[] { 0 };
|
||||||
private double[] doublehelper = new[] { 0.0 };
|
private double[] doublehelper = new[] { 0.0 };
|
||||||
private ulong[] ulonghelper = new[] { 0UL };
|
private ulong[] ulonghelper = new[] { 0UL };
|
||||||
|
#endif // !UNSAFE_BYTEBUFFER
|
||||||
|
|
||||||
// Helper functions for the unsafe version.
|
// Helper functions for the unsafe version.
|
||||||
static public ushort ReverseBytes(ushort input)
|
static public ushort ReverseBytes(ushort input)
|
||||||
@@ -136,7 +191,6 @@ namespace FlatBuffers
|
|||||||
}
|
}
|
||||||
#endif // !UNSAFE_BYTEBUFFER
|
#endif // !UNSAFE_BYTEBUFFER
|
||||||
|
|
||||||
|
|
||||||
private void AssertOffsetAndLength(int offset, int length)
|
private void AssertOffsetAndLength(int offset, int length)
|
||||||
{
|
{
|
||||||
#if !BYTEBUFFER_NO_BOUNDS_CHECK
|
#if !BYTEBUFFER_NO_BOUNDS_CHECK
|
||||||
@@ -171,6 +225,13 @@ namespace FlatBuffers
|
|||||||
PutByte(offset, value);
|
PutByte(offset, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void PutStringUTF8(int offset, string value)
|
||||||
|
{
|
||||||
|
AssertOffsetAndLength(offset, value.Length);
|
||||||
|
Encoding.UTF8.GetBytes(value, 0, value.Length,
|
||||||
|
_buffer, offset);
|
||||||
|
}
|
||||||
|
|
||||||
#if UNSAFE_BYTEBUFFER
|
#if UNSAFE_BYTEBUFFER
|
||||||
// Unsafe but more efficient versions of Put*.
|
// Unsafe but more efficient versions of Put*.
|
||||||
public void PutShort(int offset, short value)
|
public void PutShort(int offset, short value)
|
||||||
@@ -321,6 +382,11 @@ namespace FlatBuffers
|
|||||||
return _buffer[index];
|
return _buffer[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetStringUTF8(int startPos, int len)
|
||||||
|
{
|
||||||
|
return Encoding.UTF8.GetString(_buffer, startPos, len);
|
||||||
|
}
|
||||||
|
|
||||||
#if UNSAFE_BYTEBUFFER
|
#if UNSAFE_BYTEBUFFER
|
||||||
// Unsafe but more efficient versions of Get*.
|
// Unsafe but more efficient versions of Get*.
|
||||||
public short GetShort(int offset)
|
public short GetShort(int offset)
|
||||||
|
|||||||
BIN
net/FlatBuffers/ByteBuffer.exe
Executable file
BIN
net/FlatBuffers/ByteBuffer.exe
Executable file
Binary file not shown.
39
net/FlatBuffers/ByteBufferUtil.cs
Normal file
39
net/FlatBuffers/ByteBufferUtil.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2017 Google Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace FlatBuffers
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Class that collects utility functions around `ByteBuffer`.
|
||||||
|
/// </summary>
|
||||||
|
public class ByteBufferUtil
|
||||||
|
{
|
||||||
|
// Extract the size prefix from a `ByteBuffer`.
|
||||||
|
public static int GetSizePrefix(ByteBuffer bb) {
|
||||||
|
return bb.GetInt(bb.Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a duplicate of a size-prefixed `ByteBuffer` that has its position
|
||||||
|
// advanced just past the size prefix.
|
||||||
|
public static ByteBuffer RemoveSizePrefix(ByteBuffer bb) {
|
||||||
|
ByteBuffer s = bb.Duplicate();
|
||||||
|
s.Position += FlatBufferConstants.SizePrefixLength;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,7 +59,7 @@ namespace FlatBuffers
|
|||||||
throw new ArgumentOutOfRangeException("initialSize",
|
throw new ArgumentOutOfRangeException("initialSize",
|
||||||
initialSize, "Must be greater than zero");
|
initialSize, "Must be greater than zero");
|
||||||
_space = initialSize;
|
_space = initialSize;
|
||||||
_bb = new ByteBuffer(new byte[initialSize]);
|
_bb = new ByteBuffer(initialSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -99,18 +99,7 @@ namespace FlatBuffers
|
|||||||
// the end of the new buffer (since we build the buffer backwards).
|
// the end of the new buffer (since we build the buffer backwards).
|
||||||
void GrowBuffer()
|
void GrowBuffer()
|
||||||
{
|
{
|
||||||
var oldBuf = _bb.Data;
|
_bb.GrowFront(_bb.Length << 1);
|
||||||
var oldBufSize = oldBuf.Length;
|
|
||||||
if ((oldBufSize & 0xC0000000) != 0)
|
|
||||||
throw new Exception(
|
|
||||||
"FlatBuffers: cannot grow buffer beyond 2 gigabytes.");
|
|
||||||
|
|
||||||
var newBufSize = oldBufSize << 1;
|
|
||||||
var newBuf = new byte[newBufSize];
|
|
||||||
|
|
||||||
Buffer.BlockCopy(oldBuf, 0, newBuf, newBufSize - oldBufSize,
|
|
||||||
oldBufSize);
|
|
||||||
_bb = new ByteBuffer(newBuf, newBufSize);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare to write an element of `size` after `additional_bytes`
|
// Prepare to write an element of `size` after `additional_bytes`
|
||||||
@@ -475,7 +464,7 @@ namespace FlatBuffers
|
|||||||
AddByte(0);
|
AddByte(0);
|
||||||
var utf8StringLen = Encoding.UTF8.GetByteCount(s);
|
var utf8StringLen = Encoding.UTF8.GetByteCount(s);
|
||||||
StartVector(1, utf8StringLen, 1);
|
StartVector(1, utf8StringLen, 1);
|
||||||
Encoding.UTF8.GetBytes(s, 0, s.Length, _bb.Data, _space -= utf8StringLen);
|
_bb.PutStringUTF8(_space -= utf8StringLen, s);
|
||||||
return new StringOffset(EndVector().Value);
|
return new StringOffset(EndVector().Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,7 +489,11 @@ namespace FlatBuffers
|
|||||||
AddInt((int)0);
|
AddInt((int)0);
|
||||||
var vtableloc = Offset;
|
var vtableloc = Offset;
|
||||||
// Write out the current vtable.
|
// Write out the current vtable.
|
||||||
for (int i = _vtableSize - 1; i >= 0 ; i--) {
|
int i = _vtableSize - 1;
|
||||||
|
// Trim trailing zeroes.
|
||||||
|
for (; i >= 0 && _vtable[i] == 0; i--) {}
|
||||||
|
int trimmedSize = i + 1;
|
||||||
|
for (; i >= 0 ; i--) {
|
||||||
// Offset relative to the start of the table.
|
// Offset relative to the start of the table.
|
||||||
short off = (short)(_vtable[i] != 0
|
short off = (short)(_vtable[i] != 0
|
||||||
? vtableloc - _vtable[i]
|
? vtableloc - _vtable[i]
|
||||||
@@ -513,12 +506,12 @@ namespace FlatBuffers
|
|||||||
|
|
||||||
const int standardFields = 2; // The fields below:
|
const int standardFields = 2; // The fields below:
|
||||||
AddShort((short)(vtableloc - _objectStart));
|
AddShort((short)(vtableloc - _objectStart));
|
||||||
AddShort((short)((_vtableSize + standardFields) *
|
AddShort((short)((trimmedSize + standardFields) *
|
||||||
sizeof(short)));
|
sizeof(short)));
|
||||||
|
|
||||||
// Search for an existing vtable that matches the current one.
|
// Search for an existing vtable that matches the current one.
|
||||||
int existingVtable = 0;
|
int existingVtable = 0;
|
||||||
for (int i = 0; i < _numVtables; i++) {
|
for (i = 0; i < _numVtables; i++) {
|
||||||
int vt1 = _bb.Length - _vtables[i];
|
int vt1 = _bb.Length - _vtables[i];
|
||||||
int vt2 = _space;
|
int vt2 = _space;
|
||||||
short len = _bb.GetShort(vt1);
|
short len = _bb.GetShort(vt1);
|
||||||
@@ -576,6 +569,25 @@ namespace FlatBuffers
|
|||||||
}
|
}
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finalize a buffer, pointing to the given `root_table`.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rootTable">
|
||||||
|
/// An offset to be added to the buffer.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="sizePrefix">
|
||||||
|
/// Whether to prefix the size to the buffer.
|
||||||
|
/// </param>
|
||||||
|
protected void Finish(int rootTable, bool sizePrefix)
|
||||||
|
{
|
||||||
|
Prep(_minAlign, sizeof(int) + (sizePrefix ? sizeof(int) : 0));
|
||||||
|
AddOffset(rootTable);
|
||||||
|
if (sizePrefix) {
|
||||||
|
AddInt(_bb.Length - _space);
|
||||||
|
}
|
||||||
|
_bb.Position = _space;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finalize a buffer, pointing to the given `root_table`.
|
/// Finalize a buffer, pointing to the given `root_table`.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -584,9 +596,18 @@ namespace FlatBuffers
|
|||||||
/// </param>
|
/// </param>
|
||||||
public void Finish(int rootTable)
|
public void Finish(int rootTable)
|
||||||
{
|
{
|
||||||
Prep(_minAlign, sizeof(int));
|
Finish(rootTable, false);
|
||||||
AddOffset(rootTable);
|
}
|
||||||
_bb.Position = _space;
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finalize a buffer, pointing to the given `root_table`, with the size prefixed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rootTable">
|
||||||
|
/// An offset to be added to the buffer.
|
||||||
|
/// </param>
|
||||||
|
public void FinishSizePrefixed(int rootTable)
|
||||||
|
{
|
||||||
|
Finish(rootTable, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -611,41 +632,69 @@ namespace FlatBuffers
|
|||||||
/// </returns>
|
/// </returns>
|
||||||
public byte[] SizedByteArray()
|
public byte[] SizedByteArray()
|
||||||
{
|
{
|
||||||
var newArray = new byte[_bb.Data.Length - _bb.Position];
|
return _bb.ToSizedArray();
|
||||||
Buffer.BlockCopy(_bb.Data, _bb.Position, newArray, 0,
|
|
||||||
_bb.Data.Length - _bb.Position);
|
|
||||||
return newArray;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Finalize a buffer, pointing to the given `rootTable`.
|
/// Finalize a buffer, pointing to the given `rootTable`.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="rootTable">
|
/// <param name="rootTable">
|
||||||
/// An offset to be added to the buffer.
|
/// An offset to be added to the buffer.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name="fileIdentifier">
|
/// <param name="fileIdentifier">
|
||||||
/// A FlatBuffer file identifier to be added to the buffer before
|
/// A FlatBuffer file identifier to be added to the buffer before
|
||||||
/// `root_table`.
|
/// `root_table`.
|
||||||
/// </param>
|
/// </param>
|
||||||
public void Finish(int rootTable, string fileIdentifier)
|
/// <param name="sizePrefix">
|
||||||
{
|
/// Whether to prefix the size to the buffer.
|
||||||
Prep(_minAlign, sizeof(int) +
|
/// </param>
|
||||||
FlatBufferConstants.FileIdentifierLength);
|
protected void Finish(int rootTable, string fileIdentifier, bool sizePrefix)
|
||||||
if (fileIdentifier.Length !=
|
{
|
||||||
FlatBufferConstants.FileIdentifierLength)
|
Prep(_minAlign, sizeof(int) + (sizePrefix ? sizeof(int) : 0) +
|
||||||
throw new ArgumentException(
|
FlatBufferConstants.FileIdentifierLength);
|
||||||
"FlatBuffers: file identifier must be length " +
|
if (fileIdentifier.Length !=
|
||||||
FlatBufferConstants.FileIdentifierLength,
|
FlatBufferConstants.FileIdentifierLength)
|
||||||
"fileIdentifier");
|
throw new ArgumentException(
|
||||||
for (int i = FlatBufferConstants.FileIdentifierLength - 1; i >= 0;
|
"FlatBuffers: file identifier must be length " +
|
||||||
i--)
|
FlatBufferConstants.FileIdentifierLength,
|
||||||
{
|
"fileIdentifier");
|
||||||
AddByte((byte)fileIdentifier[i]);
|
for (int i = FlatBufferConstants.FileIdentifierLength - 1; i >= 0;
|
||||||
}
|
i--)
|
||||||
Finish(rootTable);
|
{
|
||||||
|
AddByte((byte)fileIdentifier[i]);
|
||||||
|
}
|
||||||
|
Finish(rootTable, sizePrefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finalize a buffer, pointing to the given `rootTable`.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rootTable">
|
||||||
|
/// An offset to be added to the buffer.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="fileIdentifier">
|
||||||
|
/// A FlatBuffer file identifier to be added to the buffer before
|
||||||
|
/// `root_table`.
|
||||||
|
/// </param>
|
||||||
|
public void Finish(int rootTable, string fileIdentifier)
|
||||||
|
{
|
||||||
|
Finish(rootTable, fileIdentifier, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Finalize a buffer, pointing to the given `rootTable`, with the size prefixed.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rootTable">
|
||||||
|
/// An offset to be added to the buffer.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="fileIdentifier">
|
||||||
|
/// A FlatBuffer file identifier to be added to the buffer before
|
||||||
|
/// `root_table`.
|
||||||
|
/// </param>
|
||||||
|
public void FinishSizePrefixed(int rootTable, string fileIdentifier)
|
||||||
|
{
|
||||||
|
Finish(rootTable, fileIdentifier, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,5 +24,6 @@ namespace FlatBuffers
|
|||||||
public static class FlatBufferConstants
|
public static class FlatBufferConstants
|
||||||
{
|
{
|
||||||
public const int FileIdentifierLength = 4;
|
public const int FileIdentifierLength = 4;
|
||||||
|
public const int SizePrefixLength = 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ namespace FlatBuffers
|
|||||||
offset += bb.GetInt(offset);
|
offset += bb.GetInt(offset);
|
||||||
var len = bb.GetInt(offset);
|
var len = bb.GetInt(offset);
|
||||||
var startPos = offset + sizeof(int);
|
var startPos = offset + sizeof(int);
|
||||||
return Encoding.UTF8.GetString(bb.Data, startPos , len);
|
return bb.GetStringUTF8(startPos, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the length of a vector whose offset is stored at "offset" in this object.
|
// Get the length of a vector whose offset is stored at "offset" in this object.
|
||||||
@@ -91,7 +91,7 @@ namespace FlatBuffers
|
|||||||
|
|
||||||
var pos = this.__vector(o);
|
var pos = this.__vector(o);
|
||||||
var len = this.__vector_len(o);
|
var len = this.__vector_len(o);
|
||||||
return new ArraySegment<byte>(this.bb.Data, pos, len);
|
return bb.ToArraySegment(pos, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize any Table-derived type to point to the union at the given offset.
|
// Initialize any Table-derived type to point to the union at the given offset.
|
||||||
@@ -126,10 +126,11 @@ namespace FlatBuffers
|
|||||||
var startPos_1 = offset_1 + sizeof(int);
|
var startPos_1 = offset_1 + sizeof(int);
|
||||||
var startPos_2 = offset_2 + sizeof(int);
|
var startPos_2 = offset_2 + sizeof(int);
|
||||||
var len = Math.Min(len_1, len_2);
|
var len = Math.Min(len_1, len_2);
|
||||||
byte[] bbArray = bb.Data;
|
|
||||||
for(int i = 0; i < len; i++) {
|
for(int i = 0; i < len; i++) {
|
||||||
if (bbArray[i + startPos_1] != bbArray[i + startPos_2])
|
byte b1 = bb.Get(i + startPos_1);
|
||||||
return bbArray[i + startPos_1] - bbArray[i + startPos_2];
|
byte b2 = bb.Get(i + startPos_2);
|
||||||
|
if (b1 != b2)
|
||||||
|
return b1 - b2;
|
||||||
}
|
}
|
||||||
return len_1 - len_2;
|
return len_1 - len_2;
|
||||||
}
|
}
|
||||||
@@ -142,10 +143,10 @@ namespace FlatBuffers
|
|||||||
var len_2 = key.Length;
|
var len_2 = key.Length;
|
||||||
var startPos_1 = offset_1 + sizeof(int);
|
var startPos_1 = offset_1 + sizeof(int);
|
||||||
var len = Math.Min(len_1, len_2);
|
var len = Math.Min(len_1, len_2);
|
||||||
byte[] bbArray = bb.Data;
|
|
||||||
for (int i = 0; i < len; i++) {
|
for (int i = 0; i < len; i++) {
|
||||||
if (bbArray[i + startPos_1] != key[i])
|
byte b = bb.Get(i + startPos_1);
|
||||||
return bbArray[i + startPos_1] - key[i];
|
if (b != key[i])
|
||||||
|
return b - key[i];
|
||||||
}
|
}
|
||||||
return len_1 - len_2;
|
return len_1 - len_2;
|
||||||
}
|
}
|
||||||
|
|||||||
11
package.json
11
package.json
@@ -1,15 +1,18 @@
|
|||||||
{
|
{
|
||||||
"name": "flatbuffers",
|
"name": "flatbuffers",
|
||||||
"version": "1.7.0",
|
"version": "1.9.0",
|
||||||
"description": "Memory Efficient Serialization Library",
|
"description": "Memory Efficient Serialization Library",
|
||||||
"files": ["js/flatbuffers.js"],
|
"files": ["js/flatbuffers.js", "js/flatbuffers.mjs"],
|
||||||
"main": "js/flatbuffers.js",
|
"main": "js/flatbuffers",
|
||||||
|
"module": "js/flatbuffers.mjs",
|
||||||
"directories": {
|
"directories": {
|
||||||
"doc": "docs",
|
"doc": "docs",
|
||||||
"test": "tests"
|
"test": "tests"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "tests/JavaScriptTest.sh"
|
"test": "tests/JavaScriptTest.sh",
|
||||||
|
"append-esm-export": "sed \"s/this.flatbuffers = flatbuffers;/export { flatbuffers };/\" js/flatbuffers.js >> js/flatbuffers.mjs",
|
||||||
|
"prepublishOnly": "npm run append-esm-export"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|||||||
@@ -812,14 +812,18 @@ class FlatbufferBuilder
|
|||||||
$this->addInt(0);
|
$this->addInt(0);
|
||||||
$vtableloc = $this->offset();
|
$vtableloc = $this->offset();
|
||||||
|
|
||||||
for ($i = $this->vtable_in_use -1; $i >= 0; $i--) {
|
$i = $this->vtable_in_use -1;
|
||||||
|
// Trim trailing zeroes.
|
||||||
|
for (; $i >= 0 && $this->vtable[$i] == 0; $i--) {}
|
||||||
|
$trimmed_size = $i + 1;
|
||||||
|
for (; $i >= 0; $i--) {
|
||||||
$off = ($this->vtable[$i] != 0) ? $vtableloc - $this->vtable[$i] : 0;
|
$off = ($this->vtable[$i] != 0) ? $vtableloc - $this->vtable[$i] : 0;
|
||||||
$this->addShort($off);
|
$this->addShort($off);
|
||||||
}
|
}
|
||||||
|
|
||||||
$standard_fields = 2; // the fields below
|
$standard_fields = 2; // the fields below
|
||||||
$this->addShort($vtableloc - $this->object_start);
|
$this->addShort($vtableloc - $this->object_start);
|
||||||
$this->addShort(($this->vtable_in_use + $standard_fields) * Constants::SIZEOF_SHORT);
|
$this->addShort(($trimmed_size + $standard_fields) * Constants::SIZEOF_SHORT);
|
||||||
|
|
||||||
// search for an existing vtable that matches the current one.
|
// search for an existing vtable that matches the current one.
|
||||||
$existing_vtable = 0;
|
$existing_vtable = 0;
|
||||||
|
|||||||
@@ -28,4 +28,14 @@ abstract class Struct
|
|||||||
* @var ByteBuffer $bb
|
* @var ByteBuffer $bb
|
||||||
*/
|
*/
|
||||||
protected $bb;
|
protected $bb;
|
||||||
|
|
||||||
|
public function setByteBufferPos($pos)
|
||||||
|
{
|
||||||
|
$this->bb_pos = $pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setByteBuffer($bb)
|
||||||
|
{
|
||||||
|
$this->bb = $bb;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,16 @@ abstract class Table
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setByteBufferPos($pos)
|
||||||
|
{
|
||||||
|
$this->bb_pos = $pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setByteBuffer($bb)
|
||||||
|
{
|
||||||
|
$this->bb = $bb;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns actual vtable offset
|
* returns actual vtable offset
|
||||||
*
|
*
|
||||||
@@ -107,8 +117,8 @@ abstract class Table
|
|||||||
protected function __union($table, $offset)
|
protected function __union($table, $offset)
|
||||||
{
|
{
|
||||||
$offset += $this->bb_pos;
|
$offset += $this->bb_pos;
|
||||||
$table->bb_pos = $offset + $this->bb->getInt($offset);
|
$table->setByteBufferPos($offset + $this->bb->getInt($offset));
|
||||||
$table->bb = $this->bb;
|
$table->setByteBuffer($this->bb);
|
||||||
return $table;
|
return $table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
51
pom.xml
51
pom.xml
@@ -5,17 +5,20 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>com.google.flatbuffers</groupId>
|
<groupId>com.google.flatbuffers</groupId>
|
||||||
<artifactId>flatbuffers-java</artifactId>
|
<artifactId>flatbuffers-java</artifactId>
|
||||||
<version>1.7.0-SNAPSHOT</version>
|
<version>1.9.0</version>
|
||||||
<packaging>bundle</packaging>
|
<packaging>bundle</packaging>
|
||||||
<name>FlatBuffers Java API</name>
|
<name>FlatBuffers Java API</name>
|
||||||
<description>
|
<description>
|
||||||
Memory Efficient Serialization Library
|
Memory Efficient Serialization Library
|
||||||
</description>
|
</description>
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<name>Wouter van Oortmerssen</name>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<url>https://github.com/google/flatbuffers</url>
|
<url>https://github.com/google/flatbuffers</url>
|
||||||
<licenses>
|
<licenses>
|
||||||
<license>
|
<license>
|
||||||
@@ -32,6 +35,12 @@
|
|||||||
</scm>
|
</scm>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
<distributionManagement>
|
||||||
|
<snapshotRepository>
|
||||||
|
<id>ossrh</id>
|
||||||
|
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
|
||||||
|
</snapshotRepository>
|
||||||
|
</distributionManagement>
|
||||||
<build>
|
<build>
|
||||||
<sourceDirectory>java</sourceDirectory>
|
<sourceDirectory>java</sourceDirectory>
|
||||||
<plugins>
|
<plugins>
|
||||||
@@ -84,6 +93,42 @@
|
|||||||
<version>3.0.1</version>
|
<version>3.0.1</version>
|
||||||
<extensions>true</extensions>
|
<extensions>true</extensions>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.sonatype.plugins</groupId>
|
||||||
|
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||||
|
<version>1.6.7</version>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<configuration>
|
||||||
|
<serverId>ossrh</serverId>
|
||||||
|
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
|
||||||
|
<autoReleaseAfterClose>true</autoReleaseAfterClose>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-gpg-plugin</artifactId>
|
||||||
|
<version>1.5</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>sign-artifacts</id>
|
||||||
|
<phase>verify</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>sign</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-release-plugin</artifactId>
|
||||||
|
<version>2.5.3</version>
|
||||||
|
<configuration>
|
||||||
|
<autoVersionSubmodules>true</autoVersionSubmodules>
|
||||||
|
<useReleaseProfile>false</useReleaseProfile>
|
||||||
|
<releaseProfiles>release</releaseProfiles>
|
||||||
|
<goals>deploy</goals>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</project>
|
</project>
|
||||||
|
|||||||
2
python/.gitignore
vendored
Normal file
2
python/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/dist/
|
||||||
|
/*.egg-info/
|
||||||
@@ -193,6 +193,10 @@ class Builder(object):
|
|||||||
objectOffset = self.Offset()
|
objectOffset = self.Offset()
|
||||||
existingVtable = None
|
existingVtable = None
|
||||||
|
|
||||||
|
# Trim trailing 0 offsets.
|
||||||
|
while self.current_vtable and self.current_vtable[-1] == 0:
|
||||||
|
self.current_vtable.pop()
|
||||||
|
|
||||||
# Search backwards through existing vtables, because similar vtables
|
# Search backwards through existing vtables, because similar vtables
|
||||||
# are likely to have been recently appended. See
|
# are likely to have been recently appended. See
|
||||||
# BenchmarkVtableDeduplication for a case in which this heuristic
|
# BenchmarkVtableDeduplication for a case in which this heuristic
|
||||||
@@ -417,6 +421,27 @@ class Builder(object):
|
|||||||
|
|
||||||
return self.EndVector(len(x))
|
return self.EndVector(len(x))
|
||||||
|
|
||||||
|
def CreateByteVector(self, x):
|
||||||
|
"""CreateString writes a byte vector."""
|
||||||
|
|
||||||
|
self.assertNotNested()
|
||||||
|
## @cond FLATBUFFERS_INTERNAL
|
||||||
|
self.nested = True
|
||||||
|
## @endcond
|
||||||
|
|
||||||
|
if not isinstance(x, compat.binary_types):
|
||||||
|
raise TypeError("non-byte vector passed to CreateByteVector")
|
||||||
|
|
||||||
|
self.Prep(N.UOffsetTFlags.bytewidth, len(x)*N.Uint8Flags.bytewidth)
|
||||||
|
|
||||||
|
l = UOffsetTFlags.py_type(len(x))
|
||||||
|
## @cond FLATBUFFERS_INTERNAL
|
||||||
|
self.head = UOffsetTFlags.py_type(self.Head() - l)
|
||||||
|
## @endcond
|
||||||
|
self.Bytes[self.Head():self.Head()+l] = x
|
||||||
|
|
||||||
|
return self.EndVector(len(x))
|
||||||
|
|
||||||
## @cond FLATBUFFERS_INTERNAL
|
## @cond FLATBUFFERS_INTERNAL
|
||||||
def assertNested(self):
|
def assertNested(self):
|
||||||
"""
|
"""
|
||||||
@@ -458,14 +483,32 @@ class Builder(object):
|
|||||||
self.current_vtable[slotnum] = self.Offset()
|
self.current_vtable[slotnum] = self.Offset()
|
||||||
## @endcond
|
## @endcond
|
||||||
|
|
||||||
def Finish(self, rootTable):
|
def __Finish(self, rootTable, sizePrefix):
|
||||||
"""Finish finalizes a buffer, pointing to the given `rootTable`."""
|
"""Finish finalizes a buffer, pointing to the given `rootTable`."""
|
||||||
N.enforce_number(rootTable, N.UOffsetTFlags)
|
N.enforce_number(rootTable, N.UOffsetTFlags)
|
||||||
self.Prep(self.minalign, N.UOffsetTFlags.bytewidth)
|
prepSize = N.UOffsetTFlags.bytewidth
|
||||||
|
if sizePrefix:
|
||||||
|
prepSize += N.Int32Flags.bytewidth
|
||||||
|
self.Prep(self.minalign, prepSize)
|
||||||
self.PrependUOffsetTRelative(rootTable)
|
self.PrependUOffsetTRelative(rootTable)
|
||||||
|
if sizePrefix:
|
||||||
|
size = len(self.Bytes) - self.Head()
|
||||||
|
N.enforce_number(size, N.Int32Flags)
|
||||||
|
self.PrependInt32(size)
|
||||||
self.finished = True
|
self.finished = True
|
||||||
return self.Head()
|
return self.Head()
|
||||||
|
|
||||||
|
def Finish(self, rootTable):
|
||||||
|
"""Finish finalizes a buffer, pointing to the given `rootTable`."""
|
||||||
|
return self.__Finish(rootTable, False)
|
||||||
|
|
||||||
|
def FinishSizePrefixed(self, rootTable):
|
||||||
|
"""
|
||||||
|
Finish finalizes a buffer, pointing to the given `rootTable`,
|
||||||
|
with the size prefixed.
|
||||||
|
"""
|
||||||
|
return self.__Finish(rootTable, True)
|
||||||
|
|
||||||
## @cond FLATBUFFERS_INTERNAL
|
## @cond FLATBUFFERS_INTERNAL
|
||||||
def Prepend(self, flags, off):
|
def Prepend(self, flags, off):
|
||||||
self.Prep(flags.bytewidth, 0)
|
self.Prep(flags.bytewidth, 0)
|
||||||
|
|||||||
@@ -12,9 +12,11 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
""" A tiny version of `six` to help with backwards compability. """
|
""" A tiny version of `six` to help with backwards compability. Also includes
|
||||||
|
compatibility helpers for numpy. """
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
import imp
|
||||||
|
|
||||||
PY2 = sys.version_info[0] == 2
|
PY2 = sys.version_info[0] == 2
|
||||||
PY26 = sys.version_info[0:2] == (2, 6)
|
PY26 = sys.version_info[0:2] == (2, 6)
|
||||||
@@ -43,4 +45,37 @@ else:
|
|||||||
memoryview_type = memoryview
|
memoryview_type = memoryview
|
||||||
struct_bool_decl = "?"
|
struct_bool_decl = "?"
|
||||||
|
|
||||||
|
# Helper functions to facilitate making numpy optional instead of required
|
||||||
|
|
||||||
|
def import_numpy():
|
||||||
|
"""
|
||||||
|
Returns the numpy module if it exists on the system,
|
||||||
|
otherwise returns None.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
imp.find_module('numpy')
|
||||||
|
numpy_exists = True
|
||||||
|
except ImportError:
|
||||||
|
numpy_exists = False
|
||||||
|
|
||||||
|
if numpy_exists:
|
||||||
|
# We do this outside of try/except block in case numpy exists
|
||||||
|
# but is not installed correctly. We do not want to catch an
|
||||||
|
# incorrect installation which would manifest as an
|
||||||
|
# ImportError.
|
||||||
|
import numpy as np
|
||||||
|
else:
|
||||||
|
np = None
|
||||||
|
|
||||||
|
return np
|
||||||
|
|
||||||
|
|
||||||
|
class NumpyRequiredForThisFeature(RuntimeError):
|
||||||
|
"""
|
||||||
|
Error raised when user tries to use a feature that
|
||||||
|
requires numpy without having numpy installed.
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
# NOTE: Future Jython support may require code here (look at `six`).
|
# NOTE: Future Jython support may require code here (look at `six`).
|
||||||
|
|||||||
@@ -15,13 +15,26 @@
|
|||||||
from . import number_types as N
|
from . import number_types as N
|
||||||
from . import packer
|
from . import packer
|
||||||
from .compat import memoryview_type
|
from .compat import memoryview_type
|
||||||
|
from .compat import import_numpy, NumpyRequiredForThisFeature
|
||||||
|
|
||||||
|
np = import_numpy()
|
||||||
|
|
||||||
def Get(packer_type, buf, head):
|
def Get(packer_type, buf, head):
|
||||||
""" Get decodes a value at buf[head:] using `packer_type`. """
|
""" Get decodes a value at buf[head] using `packer_type`. """
|
||||||
return packer_type.unpack_from(memoryview_type(buf), head)[0]
|
return packer_type.unpack_from(memoryview_type(buf), head)[0]
|
||||||
|
|
||||||
|
|
||||||
|
def GetVectorAsNumpy(numpy_type, buf, count, offset):
|
||||||
|
""" GetVecAsNumpy decodes values starting at buf[head] as
|
||||||
|
`numpy_type`, where `numpy_type` is a numpy dtype. """
|
||||||
|
if np is not None:
|
||||||
|
# TODO: could set .flags.writeable = False to make users jump through
|
||||||
|
# hoops before modifying...
|
||||||
|
return np.frombuffer(buf, dtype=numpy_type, count=count, offset=offset)
|
||||||
|
else:
|
||||||
|
raise NumpyRequiredForThisFeature('Numpy was not found.')
|
||||||
|
|
||||||
|
|
||||||
def Write(packer_type, buf, head, n):
|
def Write(packer_type, buf, head, n):
|
||||||
""" Write encodes `n` at buf[head:] using `packer_type`. """
|
""" Write encodes `n` at buf[head] using `packer_type`. """
|
||||||
packer_type.pack_into(buf, head, n)
|
packer_type.pack_into(buf, head, n)
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ import collections
|
|||||||
import struct
|
import struct
|
||||||
|
|
||||||
from . import packer
|
from . import packer
|
||||||
|
from .compat import import_numpy, NumpyRequiredForThisFeature
|
||||||
|
|
||||||
|
np = import_numpy()
|
||||||
|
|
||||||
# For reference, see:
|
# For reference, see:
|
||||||
# https://docs.python.org/2/library/ctypes.html#ctypes-fundamental-data-types-2
|
# https://docs.python.org/2/library/ctypes.html#ctypes-fundamental-data-types-2
|
||||||
@@ -170,3 +172,10 @@ def uint64_to_float64(n):
|
|||||||
packed = struct.pack("<1Q", n)
|
packed = struct.pack("<1Q", n)
|
||||||
(unpacked,) = struct.unpack("<1d", packed)
|
(unpacked,) = struct.unpack("<1d", packed)
|
||||||
return unpacked
|
return unpacked
|
||||||
|
|
||||||
|
|
||||||
|
def to_numpy_type(number_type):
|
||||||
|
if np is not None:
|
||||||
|
return np.dtype(number_type.name).newbyteorder('<')
|
||||||
|
else:
|
||||||
|
raise NumpyRequiredForThisFeature('Numpy was not found.')
|
||||||
|
|||||||
@@ -101,6 +101,18 @@ class Table(object):
|
|||||||
return d
|
return d
|
||||||
return self.Get(validator_flags, self.Pos + off)
|
return self.Get(validator_flags, self.Pos + off)
|
||||||
|
|
||||||
|
def GetVectorAsNumpy(self, flags, off):
|
||||||
|
"""
|
||||||
|
GetVectorAsNumpy returns the vector that starts at `Vector(off)`
|
||||||
|
as a numpy array with the type specified by `flags`. The array is
|
||||||
|
a `view` into Bytes, so modifying the returned array will
|
||||||
|
modify Bytes in place.
|
||||||
|
"""
|
||||||
|
offset = self.Vector(off)
|
||||||
|
length = self.VectorLen(off) # TODO: length accounts for bytewidth, right?
|
||||||
|
numpy_dtype = N.to_numpy_type(flags)
|
||||||
|
return encode.GetVectorAsNumpy(numpy_dtype, self.Bytes, length, offset)
|
||||||
|
|
||||||
def GetVOffsetTSlot(self, slot, d):
|
def GetVOffsetTSlot(self, slot, d):
|
||||||
"""
|
"""
|
||||||
GetVOffsetTSlot retrieves the VOffsetT that the given vtable location
|
GetVOffsetTSlot retrieves the VOffsetT that the given vtable location
|
||||||
|
|||||||
28
python/flatbuffers/util.py
Normal file
28
python/flatbuffers/util.py
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Copyright 2017 Google Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
from . import encode
|
||||||
|
from . import number_types
|
||||||
|
from . import packer
|
||||||
|
|
||||||
|
def GetSizePrefix(buf, offset):
|
||||||
|
"""Extract the size prefix from a buffer."""
|
||||||
|
return encode.Get(packer.int32, buf, offset)
|
||||||
|
|
||||||
|
def RemoveSizePrefix(buf, offset):
|
||||||
|
"""
|
||||||
|
Create a slice of a size-prefixed buffer that has
|
||||||
|
its position advanced just past the size prefix.
|
||||||
|
"""
|
||||||
|
return buf, offset + number_types.Int32Flags.bytewidth
|
||||||
@@ -12,11 +12,38 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
|
|
||||||
|
|
||||||
|
def version():
|
||||||
|
version = os.getenv('VERSION', None)
|
||||||
|
if version:
|
||||||
|
# Most git tags are prefixed with 'v' (example: v1.2.3) this is
|
||||||
|
# never desirable for artifact repositories, so we strip the
|
||||||
|
# leading 'v' if it's present.
|
||||||
|
return version[1:] if version.startswith('v') else version
|
||||||
|
else:
|
||||||
|
# Default version is an ISO8601 compiliant datetime. PyPI doesn't allow
|
||||||
|
# the colon ':' character in its versions, and time is required to allow
|
||||||
|
# for multiple publications to master in one day. This datetime string
|
||||||
|
# uses the "basic" ISO8601 format for both its date and time components
|
||||||
|
# to avoid issues with the colon character (ISO requires that date and
|
||||||
|
# time components of a date-time string must be uniformly basic or
|
||||||
|
# extended, which is why the date component does not have dashes.
|
||||||
|
#
|
||||||
|
# Publications using datetime versions should only be made from master
|
||||||
|
# to represent the HEAD moving forward.
|
||||||
|
version = datetime.utcnow().strftime('%Y%m%d%H%M%S')
|
||||||
|
print("VERSION environment variable not set, using datetime instead: {}"
|
||||||
|
.format(version))
|
||||||
|
|
||||||
|
return version
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
name='flatbuffers',
|
name='flatbuffers',
|
||||||
version='2015.05.14.0',
|
version=version(),
|
||||||
license='Apache 2.0',
|
license='Apache 2.0',
|
||||||
author='FlatBuffers Contributors',
|
author='FlatBuffers Contributors',
|
||||||
author_email='me@rwinslow.com',
|
author_email='me@rwinslow.com',
|
||||||
|
|||||||
18
reflection/generate_code.bat
Normal file
18
reflection/generate_code.bat
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
:: Copyright 2015 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.
|
||||||
|
|
||||||
|
set buildtype=Release
|
||||||
|
if "%1"=="-b" set buildtype=%2
|
||||||
|
|
||||||
|
..\%buildtype%\flatc.exe --cpp --no-prefix -o ../include/flatbuffers reflection.fbs
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user