mirror of
https://github.com/google/flatbuffers.git
synced 2026-06-13 08:14:31 +00:00
Compare commits
315 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf9eb67ab9 | ||
|
|
9e7e8cbe9f | ||
|
|
b72a75f87d | ||
|
|
6cfcd8628a | ||
|
|
ddb12c0192 | ||
|
|
2032b94f61 | ||
|
|
860dc803fe | ||
|
|
5b43e4bbb8 | ||
|
|
ecd76e898d | ||
|
|
f55d4388e0 | ||
|
|
e7340c390f | ||
|
|
90441c2078 | ||
|
|
cef8f928bb | ||
|
|
98b9b5a933 | ||
|
|
d07a3d2f4c | ||
|
|
640df2c1f5 | ||
|
|
60340ac529 | ||
|
|
2bd4a27550 | ||
|
|
23bb57401c | ||
|
|
dd6daa709b | ||
|
|
dd85c3b721 | ||
|
|
94cb1ff9ea | ||
|
|
3ff6cdf491 | ||
|
|
c329d6fa90 | ||
|
|
249f3b3714 | ||
|
|
2d67de3151 | ||
|
|
5cdbd02404 | ||
|
|
b2ce86ef8a | ||
|
|
8e7acae013 | ||
|
|
343bbe808e | ||
|
|
cb9ab2fe58 | ||
|
|
4cbff97c43 | ||
|
|
88abae649c | ||
|
|
a7461433c6 | ||
|
|
440a70f4a3 | ||
|
|
02e73e1ae9 | ||
|
|
f93d0f6ac1 | ||
|
|
fd51fadaac | ||
|
|
11198f10f5 | ||
|
|
3b23ff18ea | ||
|
|
4f066c39ce | ||
|
|
ca68d8b043 | ||
|
|
407fb5d537 | ||
|
|
73a648b685 | ||
|
|
eb2a81f73d | ||
|
|
3968d00568 | ||
|
|
4f10da8d99 | ||
|
|
9e82ee2527 | ||
|
|
e237f53bfc | ||
|
|
98be491e72 | ||
|
|
71628dad0d | ||
|
|
cb7b2bf87e | ||
|
|
bfa430309a | ||
|
|
1c7d91cc55 | ||
|
|
2e865f4d4e | ||
|
|
13c9c674fd | ||
|
|
034275c6e2 | ||
|
|
4e5152d886 | ||
|
|
dc61512f20 | ||
|
|
1d60824d56 | ||
|
|
f89badd30f | ||
|
|
1b9d1b0110 | ||
|
|
6e2d530d61 | ||
|
|
9bf9b18f0a | ||
|
|
537c6ec1e6 | ||
|
|
a1f14005ab | ||
|
|
0cdacdfb35 | ||
|
|
bb58442054 | ||
|
|
4567b13115 | ||
|
|
8f8fb2b367 | ||
|
|
69d761d15e | ||
|
|
4f32cbf268 | ||
|
|
0eaaf18192 | ||
|
|
957d167199 | ||
|
|
e9d9d64527 | ||
|
|
78c50e340b | ||
|
|
9d483a3f0b | ||
|
|
b650dfba49 | ||
|
|
6980818337 | ||
|
|
224f7527e3 | ||
|
|
a66a88034a | ||
|
|
e1defaae5e | ||
|
|
78fdce28c7 | ||
|
|
60e94cf083 | ||
|
|
cf47f27164 | ||
|
|
cc7f9b89f3 | ||
|
|
600f3fbcd4 | ||
|
|
76a024137f | ||
|
|
31e34faa15 | ||
|
|
4d98faa515 | ||
|
|
d8210d5a83 | ||
|
|
7d3930a2fd | ||
|
|
347dba8501 | ||
|
|
fcacb46d01 | ||
|
|
3f388ec747 | ||
|
|
38bf4cfc03 | ||
|
|
c2f40c37b2 | ||
|
|
63d51afd11 | ||
|
|
d44931656a | ||
|
|
bbfd12eb11 | ||
|
|
7c94ff6c30 | ||
|
|
4fa4d36706 | ||
|
|
46208b1e91 | ||
|
|
b99332efd7 | ||
|
|
dd288f71f3 | ||
|
|
155c55900f | ||
|
|
0eb7b3beb0 | ||
|
|
a821b15634 | ||
|
|
87704e987e | ||
|
|
cb99116aca | ||
|
|
9ad73bf5a7 | ||
|
|
dba962ebb8 | ||
|
|
60a0f35fbc | ||
|
|
58e8552da0 | ||
|
|
d56a4055da | ||
|
|
30c4948541 | ||
|
|
80d148b175 | ||
|
|
2aa0d9a54d | ||
|
|
79cd55bd3a | ||
|
|
b378b8eb69 | ||
|
|
9635d494b3 | ||
|
|
0143f4e364 | ||
|
|
e161ade68c | ||
|
|
f575b02fda | ||
|
|
5f32f94810 | ||
|
|
d6b1ce09cf | ||
|
|
f23009f04f | ||
|
|
30bae01ea3 | ||
|
|
9068b0ee63 | ||
|
|
f8a0d3889b | ||
|
|
688fc77460 | ||
|
|
dd8922878d | ||
|
|
ab54e61805 | ||
|
|
f445c1eb4a | ||
|
|
980a6d66d3 | ||
|
|
21591916af | ||
|
|
b6c3d7b899 | ||
|
|
db0fcdd906 | ||
|
|
91fe9ba93f | ||
|
|
4c3b6c247d | ||
|
|
160e8f2fdc | ||
|
|
705577de51 | ||
|
|
0fb1d44bc4 | ||
|
|
bd20a60d6a | ||
|
|
b78c4332be | ||
|
|
636b516492 | ||
|
|
560718e976 | ||
|
|
ff687ae9c1 | ||
|
|
ca417426c7 | ||
|
|
55b30827f2 | ||
|
|
efbb11e093 | ||
|
|
5c0f914f38 | ||
|
|
802639e40d | ||
|
|
ad8b1e5dbd | ||
|
|
76d31e1b5e | ||
|
|
20396a1760 | ||
|
|
a3d8391f7b | ||
|
|
241e87d143 | ||
|
|
35f0b41fed | ||
|
|
cb5422c398 | ||
|
|
4ed6fafdfa | ||
|
|
53ce80ce91 | ||
|
|
233976c821 | ||
|
|
99fe1dc80f | ||
|
|
a4f9d1bfcc | ||
|
|
a4c362a1ba | ||
|
|
7c3c027295 | ||
|
|
569492e890 | ||
|
|
d840856093 | ||
|
|
925c1d77fc | ||
|
|
c0698cc33f | ||
|
|
ea8a4296e7 | ||
|
|
f85af46262 | ||
|
|
7a43775661 | ||
|
|
062dcf7007 | ||
|
|
ebb410062b | ||
|
|
4b864fd172 | ||
|
|
7e711f80d7 | ||
|
|
bf871ffd7f | ||
|
|
a89be8739c | ||
|
|
0bffce5aef | ||
|
|
d48f08acfe | ||
|
|
43132560f9 | ||
|
|
c56fff88a2 | ||
|
|
49fed8c4f6 | ||
|
|
b1a925dfc2 | ||
|
|
33791dc7b0 | ||
|
|
873a60b0d8 | ||
|
|
4b10656f9b | ||
|
|
e317b148dc | ||
|
|
ed03faaf07 | ||
|
|
02a7807dd8 | ||
|
|
615885e889 | ||
|
|
528ccdd458 | ||
|
|
c23ba6756f | ||
|
|
10e1d1a69e | ||
|
|
660c491265 | ||
|
|
c504a45404 | ||
|
|
919c929d30 | ||
|
|
ba4a02b46a | ||
|
|
be3d0b9c64 | ||
|
|
872fad049e | ||
|
|
9e648c392b | ||
|
|
d4f65bb8a3 | ||
|
|
3c54fd964b | ||
|
|
e7578548a5 | ||
|
|
99acd0bcd7 | ||
|
|
d0321df8cf | ||
|
|
e1f48ad35a | ||
|
|
d8f49e18d7 | ||
|
|
1f5eae5d6a | ||
|
|
ea9d60bbdf | ||
|
|
c2c3a84aaf | ||
|
|
1f03becd24 | ||
|
|
c721009491 | ||
|
|
55289c55bf | ||
|
|
ed2415eb72 | ||
|
|
aaa89429d3 | ||
|
|
12e5cf0b29 | ||
|
|
75601b81cc | ||
|
|
e203882d54 | ||
|
|
b9f1103b8a | ||
|
|
fd40cc61a4 | ||
|
|
38a6623f34 | ||
|
|
27e4f43b77 | ||
|
|
42515cfd33 | ||
|
|
5d3648b88a | ||
|
|
fc3ce7d1ab | ||
|
|
4898809eca | ||
|
|
ca5aaf62d3 | ||
|
|
c80f8d18c1 | ||
|
|
0d1559bdd4 | ||
|
|
8b39a0ee53 | ||
|
|
f675f6433c | ||
|
|
118093b613 | ||
|
|
1bb2a3bd08 | ||
|
|
2361dfb66a | ||
|
|
7b50004ec9 | ||
|
|
6e185d06a7 | ||
|
|
c949229395 | ||
|
|
e1d5fda5d4 | ||
|
|
a2603ec27e | ||
|
|
5f1b1ad42c | ||
|
|
4235a25640 | ||
|
|
88cd182349 | ||
|
|
7c824ef690 | ||
|
|
6bfa107f4e | ||
|
|
0cd8daf14e | ||
|
|
79f2adc50a | ||
|
|
dcfe38c58f | ||
|
|
51d9641de6 | ||
|
|
af6c0e6839 | ||
|
|
7c3cb5caa1 | ||
|
|
8f1bebba05 | ||
|
|
cda1525f84 | ||
|
|
72b05bc865 | ||
|
|
b3e4d9169b | ||
|
|
e2eb6af3e3 | ||
|
|
b188fde27e | ||
|
|
ba5eb3b5cf | ||
|
|
8ea293b988 | ||
|
|
f19803d364 | ||
|
|
b2d69aacf4 | ||
|
|
3331805a1c | ||
|
|
ea06768ad1 | ||
|
|
741c63052d | ||
|
|
e9912e9298 | ||
|
|
7dbc8f564a | ||
|
|
a2fe49b498 | ||
|
|
7dd5cfb510 | ||
|
|
00b741e5fb | ||
|
|
bb321fbe19 | ||
|
|
7330436713 | ||
|
|
f9c64891dd | ||
|
|
b752e4a9bb | ||
|
|
3e3c770c4e | ||
|
|
5a3f18d17d | ||
|
|
10bdcefa4a | ||
|
|
9bab626cbf | ||
|
|
effb608027 | ||
|
|
a96f2bd6ca | ||
|
|
ab3b721a54 | ||
|
|
4cfe36ae8e | ||
|
|
c7a797b966 | ||
|
|
ecc07e7793 | ||
|
|
43944a0ab1 | ||
|
|
27ce09860a | ||
|
|
3a2f6d5300 | ||
|
|
06d3229dc3 | ||
|
|
348fcb5b88 | ||
|
|
b4ca4d3cde | ||
|
|
0848f58cdd | ||
|
|
8e42f44807 | ||
|
|
88912640d0 | ||
|
|
c43a0beff0 | ||
|
|
a9640bd9e1 | ||
|
|
f11ffedb2b | ||
|
|
5d42c8352e | ||
|
|
7c1203d44c | ||
|
|
a0a33d94a7 | ||
|
|
b10123ff63 | ||
|
|
3a2c535592 | ||
|
|
6621424308 | ||
|
|
d215852f52 | ||
|
|
12c4c2238c | ||
|
|
85faa46fb3 | ||
|
|
cc354ea368 | ||
|
|
bed19a5340 | ||
|
|
9bb88a026a | ||
|
|
34cb163e38 | ||
|
|
a66f9e769b | ||
|
|
86153fd740 | ||
|
|
7eb4c6098e | ||
|
|
af3c598189 | ||
|
|
eac0bc6490 |
40
.appveyor/check-generate-code.bat
Normal file
40
.appveyor/check-generate-code.bat
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
:: Copyright 2018 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
|
||||||
|
|
||||||
|
cd tests
|
||||||
|
call generate_code.bat -b %buildtype% || goto FAIL
|
||||||
|
|
||||||
|
:: TODO: Release and Debug builds produce differences here for some reason.
|
||||||
|
git checkout HEAD -- monster_test.bfbs
|
||||||
|
|
||||||
|
git -c core.autocrlf=true diff --exit-code --quiet || goto :DIFFFOUND
|
||||||
|
goto SUCCESS
|
||||||
|
|
||||||
|
:DIFFFOUND
|
||||||
|
@echo "" >&2
|
||||||
|
@echo "ERROR: ********************************************************" >&2
|
||||||
|
@echo "ERROR: The following differences were found after running the" >&2
|
||||||
|
@echo "ERROR: tests/generate_code.sh script. Maybe you forgot to run" >&2
|
||||||
|
@echo "ERROR: it after making changes in a generator or schema?" >&2
|
||||||
|
@echo "ERROR: ********************************************************" >&2
|
||||||
|
@echo "" >&2
|
||||||
|
@git -c core.autocrlf=true --no-pager diff --binary
|
||||||
|
|
||||||
|
:FAIL
|
||||||
|
set EXITCODE=1
|
||||||
|
:SUCCESS
|
||||||
|
cd ..
|
||||||
|
EXIT /B %EXITCODE%
|
||||||
18
.bazelci/presubmit.yml
Normal file
18
.bazelci/presubmit.yml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
buildifier: latest
|
||||||
|
platforms:
|
||||||
|
ubuntu1604:
|
||||||
|
build_targets:
|
||||||
|
- "..."
|
||||||
|
test_targets:
|
||||||
|
- "..."
|
||||||
|
ubuntu1804:
|
||||||
|
build_targets:
|
||||||
|
- "..."
|
||||||
|
test_targets:
|
||||||
|
- "..."
|
||||||
|
macos:
|
||||||
|
build_targets:
|
||||||
|
- "..."
|
||||||
|
test_targets:
|
||||||
|
- "..."
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
root = true
|
root = true
|
||||||
[*.{cpp,cc,h}]
|
# Don't set line endings to avoid conflict with core.autocrlf flag.
|
||||||
end_of_line = LF
|
# Line endings on checkout/checkin are controlled by .gitattributes file.
|
||||||
|
[*]
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
|
||||||
|
|||||||
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1 +1,2 @@
|
|||||||
|
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||||
* text=auto
|
* text=auto
|
||||||
|
|||||||
23
.gitignore
vendored
23
.gitignore
vendored
@@ -12,8 +12,11 @@
|
|||||||
*.vcxproj.user
|
*.vcxproj.user
|
||||||
*.sln
|
*.sln
|
||||||
*.suo
|
*.suo
|
||||||
|
*.opendb
|
||||||
*.keystore
|
*.keystore
|
||||||
|
**/.vs/**
|
||||||
**/bin/**
|
**/bin/**
|
||||||
|
!tests/rust_usage_test/bin/**
|
||||||
**/gen/**
|
**/gen/**
|
||||||
**/libs/**
|
**/libs/**
|
||||||
**/obj/**
|
**/obj/**
|
||||||
@@ -23,8 +26,13 @@
|
|||||||
**/install_manifest.txt
|
**/install_manifest.txt
|
||||||
**/CMakeCache.txt
|
**/CMakeCache.txt
|
||||||
**/CMakeTestfile.cmake
|
**/CMakeTestfile.cmake
|
||||||
|
**/CPackConfig.cmake
|
||||||
|
**/CPackSourceConfig.cmake
|
||||||
|
**/compile_commands.json
|
||||||
**/Debug/**
|
**/Debug/**
|
||||||
**/Release/**
|
**/Release/**
|
||||||
|
**/RelWithDebInfo/**
|
||||||
|
**/x64/ #build artifacts from VS
|
||||||
build.xml
|
build.xml
|
||||||
local.properties
|
local.properties
|
||||||
project.properties
|
project.properties
|
||||||
@@ -41,15 +49,20 @@ flatsamplebinary
|
|||||||
flatsamplebinary.exe
|
flatsamplebinary.exe
|
||||||
flatsampletext
|
flatsampletext
|
||||||
flatsampletext.exe
|
flatsampletext.exe
|
||||||
|
flatsamplebfbs
|
||||||
|
flatsamplebfbs.exe
|
||||||
grpctest
|
grpctest
|
||||||
grpctest.exe
|
grpctest.exe
|
||||||
snapshot.sh
|
snapshot.sh
|
||||||
tags
|
tags
|
||||||
|
tests/dart_gen
|
||||||
tests/go_gen
|
tests/go_gen
|
||||||
tests/monsterdata_java_wire.mon
|
tests/monsterdata_java_wire.mon
|
||||||
tests/monsterdata_java_wire_sp.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/monsterdata_lobster_wire.mon
|
||||||
|
tests/monsterdata_rust_wire.mon
|
||||||
tests/unicode_test.mon
|
tests/unicode_test.mon
|
||||||
tests/ts/
|
tests/ts/
|
||||||
tests/php/
|
tests/php/
|
||||||
@@ -93,3 +106,13 @@ js/flatbuffers.mjs
|
|||||||
.ninja_log
|
.ninja_log
|
||||||
build.ninja
|
build.ninja
|
||||||
rules.ninja
|
rules.ninja
|
||||||
|
.vscode
|
||||||
|
dart/.pub/
|
||||||
|
dart/.packages
|
||||||
|
dart/pubspec.lock
|
||||||
|
dart/.dart_tool/
|
||||||
|
dart/build/
|
||||||
|
dart/doc/api/
|
||||||
|
Cargo.lock
|
||||||
|
.corpus**
|
||||||
|
.seed**
|
||||||
|
|||||||
125
.travis.yml
125
.travis.yml
@@ -2,6 +2,35 @@ env:
|
|||||||
global:
|
global:
|
||||||
# Set at the root level as this is ignored when set under matrix.env.
|
# Set at the root level as this is ignored when set under matrix.env.
|
||||||
- GCC_VERSION="4.9"
|
- GCC_VERSION="4.9"
|
||||||
|
# Fail on first error if UBSAN or ASAN enabled for a target
|
||||||
|
- UBSAN_OPTIONS=halt_on_error=1
|
||||||
|
- ASAN_OPTIONS=halt_on_error=1
|
||||||
|
# Travis machines have 2 cores
|
||||||
|
- JOBS=2
|
||||||
|
- MAKEFLAGS="-j 2"
|
||||||
|
|
||||||
|
conan-linux: &conan-linux
|
||||||
|
os: linux
|
||||||
|
dist: xenial
|
||||||
|
language: python
|
||||||
|
python: "3.7"
|
||||||
|
services:
|
||||||
|
- docker
|
||||||
|
install:
|
||||||
|
- ./conan/travis/install.sh
|
||||||
|
script:
|
||||||
|
- ./conan/travis/build.sh
|
||||||
|
if: tag IS present
|
||||||
|
|
||||||
|
conan-osx: &conan-osx
|
||||||
|
os: osx
|
||||||
|
language: generic
|
||||||
|
install:
|
||||||
|
- ./conan/travis/install.sh
|
||||||
|
script:
|
||||||
|
- ./conan/travis/build.sh
|
||||||
|
if: tag IS present
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
#- language: python
|
#- language: python
|
||||||
@@ -30,20 +59,26 @@ matrix:
|
|||||||
# branch: master
|
# branch: master
|
||||||
- language: cpp
|
- language: cpp
|
||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
- osx
|
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
packages:
|
||||||
|
- docker-ce
|
||||||
|
script:
|
||||||
|
- bash .travis/build-and-run-docker-test-containers.sh
|
||||||
|
|
||||||
|
- language: cpp
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
|
|
||||||
compiler:
|
compiler:
|
||||||
- gcc
|
- gcc
|
||||||
#- clang
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
matrix:
|
matrix:
|
||||||
- BUILD_TYPE=Debug BIICODE=false
|
- BUILD_TYPE=Debug
|
||||||
- BUILD_TYPE=Release BIICODE=false CONAN=true
|
- BUILD_TYPE=Release CONAN=true
|
||||||
# biicode .deb files no longer available.
|
|
||||||
# - BUILD_TYPE=Release BIICODE=true
|
|
||||||
# - BUILD_TYPE=Debug BIICODE=true
|
|
||||||
|
|
||||||
before_install:
|
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 add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
|
||||||
@@ -54,9 +89,72 @@ matrix:
|
|||||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
|
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- if [ "$BIICODE" == "false" ]; then cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE . && make && make test; fi
|
- bash .travis/check-sources.sh
|
||||||
- if [ "$BIICODE" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then ./biicode/support/bii-travis.sh $BUILD_TYPE; fi
|
- bash grpc/build_grpc.sh
|
||||||
- if [ "$CONAN" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo pip install conan && conan create . flatbuffers/testing -s build_type=$BUILD_TYPE; fi
|
- cmake .
|
||||||
|
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
||||||
|
-DFLATBUFFERS_BUILD_GRPCTEST=ON
|
||||||
|
-DGRPC_INSTALL_PATH=$TRAVIS_BUILD_DIR/google/grpc/install
|
||||||
|
-DPROTOBUF_DOWNLOAD_PATH=$TRAVIS_BUILD_DIR/google/grpc/third_party/protobuf
|
||||||
|
-DFLATBUFFERS_CODE_SANITIZE=ON
|
||||||
|
- cmake --build . -- -j${JOBS}
|
||||||
|
- LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/google/grpc/install/lib ctest --extra-verbose --output-on-failure
|
||||||
|
- bash .travis/check-generate-code.sh
|
||||||
|
- if [ "$CONAN" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo pip install conan && conan create . flatbuffers/${TRAVIS_BRANCH}@google/testing -s build_type=$BUILD_TYPE -tf conan/test_package; fi
|
||||||
|
|
||||||
|
- language: cpp
|
||||||
|
os: osx
|
||||||
|
osx_image: xcode9.3
|
||||||
|
env:
|
||||||
|
matrix:
|
||||||
|
- BUILD_TYPE=Debug
|
||||||
|
- BUILD_TYPE=Release
|
||||||
|
|
||||||
|
script:
|
||||||
|
- bash grpc/build_grpc.sh
|
||||||
|
- cmake .
|
||||||
|
-DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
||||||
|
-DFLATBUFFERS_BUILD_GRPCTEST=ON
|
||||||
|
-DGRPC_INSTALL_PATH=$TRAVIS_BUILD_DIR/google/grpc/install
|
||||||
|
-DPROTOBUF_DOWNLOAD_PATH=$TRAVIS_BUILD_DIR/google/grpc/third_party/protobuf
|
||||||
|
-DFLATBUFFERS_CODE_SANITIZE=ON
|
||||||
|
- cmake --build . -- -j${JOBS}
|
||||||
|
- DYLD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/google/grpc/install/lib ctest --extra-verbose --output-on-failure
|
||||||
|
- bash .travis/check-generate-code.sh
|
||||||
|
|
||||||
|
- <<: *conan-linux
|
||||||
|
env: CONAN_GCC_VERSIONS=4.9 CONAN_DOCKER_IMAGE=conanio/gcc49
|
||||||
|
- <<: *conan-linux
|
||||||
|
env: CONAN_GCC_VERSIONS=5 CONAN_DOCKER_IMAGE=conanio/gcc5
|
||||||
|
- <<: *conan-linux
|
||||||
|
env: CONAN_GCC_VERSIONS=6 CONAN_DOCKER_IMAGE=conanio/gcc6
|
||||||
|
- <<: *conan-linux
|
||||||
|
env: CONAN_GCC_VERSIONS=7 CONAN_DOCKER_IMAGE=conanio/gcc7
|
||||||
|
- <<: *conan-linux
|
||||||
|
env: CONAN_GCC_VERSIONS=8 CONAN_DOCKER_IMAGE=conanio/gcc8
|
||||||
|
- <<: *conan-linux
|
||||||
|
env: CONAN_CLANG_VERSIONS=3.9 CONAN_DOCKER_IMAGE=conanio/clang39
|
||||||
|
- <<: *conan-linux
|
||||||
|
env: CONAN_CLANG_VERSIONS=4.0 CONAN_DOCKER_IMAGE=conanio/clang40
|
||||||
|
- <<: *conan-linux
|
||||||
|
env: CONAN_CLANG_VERSIONS=5.0 CONAN_DOCKER_IMAGE=conanio/clang50
|
||||||
|
- <<: *conan-linux
|
||||||
|
env: CONAN_CLANG_VERSIONS=6.0 CONAN_DOCKER_IMAGE=conanio/clang60
|
||||||
|
- <<: *conan-osx
|
||||||
|
osx_image: xcode7.3
|
||||||
|
env: CONAN_APPLE_CLANG_VERSIONS=7.3
|
||||||
|
- <<: *conan-osx
|
||||||
|
osx_image: xcode8.3
|
||||||
|
env: CONAN_APPLE_CLANG_VERSIONS=8.1
|
||||||
|
- <<: *conan-osx
|
||||||
|
osx_image: xcode9
|
||||||
|
env: CONAN_APPLE_CLANG_VERSIONS=9.0
|
||||||
|
- <<: *conan-osx
|
||||||
|
osx_image: xcode9.4
|
||||||
|
env: CONAN_APPLE_CLANG_VERSIONS=9.1
|
||||||
|
- <<: *conan-osx
|
||||||
|
osx_image: xcode10
|
||||||
|
env: CONAN_APPLE_CLANG_VERSIONS=10.0
|
||||||
|
|
||||||
- language: android
|
- language: android
|
||||||
sudo: true
|
sudo: true
|
||||||
@@ -69,7 +167,10 @@ matrix:
|
|||||||
- extra-android-m2repository
|
- extra-android-m2repository
|
||||||
compiler:
|
compiler:
|
||||||
- gcc
|
- gcc
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
|
# Output something every 10 minutes or Travis kills the job
|
||||||
|
- while sleep 540; do echo "=====[ $SECONDS seconds still running ]====="; done &
|
||||||
- git clone https://github.com/urho3d/android-ndk.git $HOME/android-ndk-root
|
- git clone https://github.com/urho3d/android-ndk.git $HOME/android-ndk-root
|
||||||
- export ANDROID_NDK_HOME=$HOME/android-ndk-root
|
- export ANDROID_NDK_HOME=$HOME/android-ndk-root
|
||||||
# Setup environment for Linux build which is required to build the sample.
|
# Setup environment for Linux build which is required to build the sample.
|
||||||
@@ -81,3 +182,5 @@ matrix:
|
|||||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
|
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
|
||||||
script:
|
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))
|
- failed=0; for build_gradle in $(git ls-files | grep build.gradle); do ( cd "$(dirname "${build_gradle}")" && ./gradlew build ) || failed=1; done; exit $((failed))
|
||||||
|
# Kill the sleep loop
|
||||||
|
- kill %1
|
||||||
|
|||||||
40
.travis/build-and-run-docker-test-containers.sh
Executable file
40
.travis/build-and-run-docker-test-containers.sh
Executable file
@@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Copyright 2018 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 -e
|
||||||
|
|
||||||
|
# build flatc on debian once to speed up the test loop below
|
||||||
|
docker build -t build_flatc_debian_stretch -f tests/docker/Dockerfile.testing.build_flatc_debian_stretch .
|
||||||
|
BUILD_CONTAINER_ID=$(docker create --read-only build_flatc_debian_stretch)
|
||||||
|
docker cp ${BUILD_CONTAINER_ID}:/code/flatc flatc_debian_stretch
|
||||||
|
|
||||||
|
for f in $(ls tests/docker/languages | sort)
|
||||||
|
do
|
||||||
|
# docker pull sometimes fails for unknown reasons, probably travisci-related. this retries the pull we need a few times.
|
||||||
|
REQUIRED_BASE_IMAGE=$(cat tests/docker/languages/${f} | head -n 1 | awk ' { print $2 } ')
|
||||||
|
|
||||||
|
set +e
|
||||||
|
n=0
|
||||||
|
until [ $n -ge 5 ]
|
||||||
|
do
|
||||||
|
docker pull $REQUIRED_BASE_IMAGE && break
|
||||||
|
n=$[$n+1]
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
set -e
|
||||||
|
|
||||||
|
docker build -t $(echo ${f} | cut -f 3- -d .) -f tests/docker/languages/${f} .
|
||||||
|
echo "TEST OK: ${f}"
|
||||||
|
done
|
||||||
34
.travis/check-generate-code.sh
Executable file
34
.travis/check-generate-code.sh
Executable file
@@ -0,0 +1,34 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Copyright 2018 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 -e
|
||||||
|
|
||||||
|
cd tests
|
||||||
|
./generate_code.sh
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
# TODO: Linux and macos builds produce differences here for some reason.
|
||||||
|
git checkout HEAD -- tests/monster_test.bfbs
|
||||||
|
|
||||||
|
if ! git diff --quiet; then
|
||||||
|
echo >&2
|
||||||
|
echo "ERROR: ********************************************************" >&2
|
||||||
|
echo "ERROR: The following differences were found after running the" >&2
|
||||||
|
echo "ERROR: tests/generate_code.sh script. Maybe you forgot to run" >&2
|
||||||
|
echo "ERROR: it after making changes in a generator or schema?" >&2
|
||||||
|
echo "ERROR: ********************************************************" >&2
|
||||||
|
echo >&2
|
||||||
|
git diff --binary --exit-code
|
||||||
|
fi
|
||||||
33
.travis/check-sources.sh
Normal file
33
.travis/check-sources.sh
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Copyright 2018 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 -e
|
||||||
|
|
||||||
|
if [ -n "$1" ]; then
|
||||||
|
scan_dir="$1"
|
||||||
|
else
|
||||||
|
scan_dir="$( pwd )"
|
||||||
|
fi
|
||||||
|
|
||||||
|
py_checker="$0.py"
|
||||||
|
|
||||||
|
echo "scan root directory = '$scan_dir'"
|
||||||
|
python3 --version
|
||||||
|
# Scan recursively and search all *.cpp and *.h files using regex patterns.
|
||||||
|
# Assume that script running from a root of Flatbuffers working dir.
|
||||||
|
python3 $py_checker "ascii" "$scan_dir/include" "\.h$"
|
||||||
|
python3 $py_checker "ascii" "$scan_dir/src" "\.cpp$"
|
||||||
|
python3 $py_checker "ascii" "$scan_dir/tests" "\.h$"
|
||||||
|
python3 $py_checker "utf-8" "$scan_dir/tests" "\.cpp$"
|
||||||
35
.travis/check-sources.sh.py
Normal file
35
.travis/check-sources.sh.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
import os
|
||||||
|
import re
|
||||||
|
import sys
|
||||||
|
|
||||||
|
def check_encoding(encoding, scan_dir, regex_pattern):
|
||||||
|
fname = None
|
||||||
|
try:
|
||||||
|
assert encoding in ['ascii', 'utf-8'], "unexpected encoding"
|
||||||
|
cmp = re.compile(regex_pattern)
|
||||||
|
for root, dirs, files in os.walk(scan_dir):
|
||||||
|
fname = root
|
||||||
|
cmp_list = [f for f in files if cmp.search(f) is not None]
|
||||||
|
for f in cmp_list:
|
||||||
|
fname = os.path.join(root, f)
|
||||||
|
with open(fname, mode='rb') as test_file:
|
||||||
|
btext = test_file.read()
|
||||||
|
# check encoding
|
||||||
|
btext.decode(encoding=encoding, errors="strict")
|
||||||
|
if encoding == "utf-8" and btext.startswith(b'\xEF\xBB\xBF'):
|
||||||
|
raise ValueError("unexpected BOM in file")
|
||||||
|
# check LF line endings
|
||||||
|
LF = btext.count(b'\n')
|
||||||
|
CR = btext.count(b'\r')
|
||||||
|
if CR!=0:
|
||||||
|
raise ValueError("invalid line endings: LF({})/CR({})".format(LF, CR))
|
||||||
|
except Exception as err:
|
||||||
|
print("ERROR with [{}]: {}".format(fname, err))
|
||||||
|
return -1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# python check-sources.sh.py 'ascii' '.' '.*\.(cpp|h)$'
|
||||||
|
res = check_encoding(sys.argv[1], sys.argv[2], sys.argv[3])
|
||||||
|
sys.exit(0 if res == 0 else -1)
|
||||||
61
BUILD
61
BUILD
@@ -1,3 +1,5 @@
|
|||||||
|
licenses(["notice"])
|
||||||
|
|
||||||
package(
|
package(
|
||||||
default_visibility = ["//visibility:public"],
|
default_visibility = ["//visibility:public"],
|
||||||
features = [
|
features = [
|
||||||
@@ -10,10 +12,7 @@ exports_files([
|
|||||||
"LICENSE",
|
"LICENSE",
|
||||||
])
|
])
|
||||||
|
|
||||||
FLATBUFFERS_COPTS = [
|
load(":build_defs.bzl", "flatbuffer_cc_library")
|
||||||
"-Wno-implicit-fallthrough",
|
|
||||||
"-linclude",
|
|
||||||
]
|
|
||||||
|
|
||||||
# Public flatc library to compile flatbuffer files at runtime.
|
# Public flatc library to compile flatbuffer files at runtime.
|
||||||
cc_library(
|
cc_library(
|
||||||
@@ -28,7 +27,6 @@ cc_library(
|
|||||||
"src/util.cpp",
|
"src/util.cpp",
|
||||||
],
|
],
|
||||||
hdrs = [":public_headers"],
|
hdrs = [":public_headers"],
|
||||||
copts = FLATBUFFERS_COPTS,
|
|
||||||
includes = ["include/"],
|
includes = ["include/"],
|
||||||
linkstatic = 1,
|
linkstatic = 1,
|
||||||
)
|
)
|
||||||
@@ -43,6 +41,7 @@ filegroup(
|
|||||||
"include/flatbuffers/flexbuffers.h",
|
"include/flatbuffers/flexbuffers.h",
|
||||||
"include/flatbuffers/hash.h",
|
"include/flatbuffers/hash.h",
|
||||||
"include/flatbuffers/idl.h",
|
"include/flatbuffers/idl.h",
|
||||||
|
"include/flatbuffers/minireflect.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/stl_emulation.h",
|
||||||
@@ -65,7 +64,6 @@ cc_library(
|
|||||||
"include/flatbuffers/flatc.h",
|
"include/flatbuffers/flatc.h",
|
||||||
":public_headers",
|
":public_headers",
|
||||||
],
|
],
|
||||||
copts = FLATBUFFERS_COPTS,
|
|
||||||
includes = [
|
includes = [
|
||||||
"grpc/",
|
"grpc/",
|
||||||
"include/",
|
"include/",
|
||||||
@@ -86,16 +84,19 @@ cc_binary(
|
|||||||
"grpc/src/compiler/schema_interface.h",
|
"grpc/src/compiler/schema_interface.h",
|
||||||
"src/flatc_main.cpp",
|
"src/flatc_main.cpp",
|
||||||
"src/idl_gen_cpp.cpp",
|
"src/idl_gen_cpp.cpp",
|
||||||
|
"src/idl_gen_dart.cpp",
|
||||||
"src/idl_gen_general.cpp",
|
"src/idl_gen_general.cpp",
|
||||||
"src/idl_gen_go.cpp",
|
"src/idl_gen_go.cpp",
|
||||||
"src/idl_gen_grpc.cpp",
|
"src/idl_gen_grpc.cpp",
|
||||||
"src/idl_gen_js.cpp",
|
"src/idl_gen_js_ts.cpp",
|
||||||
"src/idl_gen_json_schema.cpp",
|
"src/idl_gen_json_schema.cpp",
|
||||||
|
"src/idl_gen_lobster.cpp",
|
||||||
|
"src/idl_gen_lua.cpp",
|
||||||
"src/idl_gen_php.cpp",
|
"src/idl_gen_php.cpp",
|
||||||
"src/idl_gen_python.cpp",
|
"src/idl_gen_python.cpp",
|
||||||
|
"src/idl_gen_rust.cpp",
|
||||||
"src/idl_gen_text.cpp",
|
"src/idl_gen_text.cpp",
|
||||||
],
|
],
|
||||||
copts = FLATBUFFERS_COPTS,
|
|
||||||
includes = [
|
includes = [
|
||||||
"grpc/",
|
"grpc/",
|
||||||
"include/",
|
"include/",
|
||||||
@@ -105,6 +106,19 @@ cc_binary(
|
|||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "runtime_cc",
|
||||||
|
hdrs = [
|
||||||
|
"include/flatbuffers/base.h",
|
||||||
|
"include/flatbuffers/flatbuffers.h",
|
||||||
|
"include/flatbuffers/flexbuffers.h",
|
||||||
|
"include/flatbuffers/stl_emulation.h",
|
||||||
|
"include/flatbuffers/util.h",
|
||||||
|
],
|
||||||
|
includes = ["include/"],
|
||||||
|
linkstatic = 1,
|
||||||
|
)
|
||||||
|
|
||||||
# Test binary.
|
# Test binary.
|
||||||
cc_test(
|
cc_test(
|
||||||
name = "flatbuffers_test",
|
name = "flatbuffers_test",
|
||||||
@@ -119,15 +133,19 @@ cc_test(
|
|||||||
"src/idl_parser.cpp",
|
"src/idl_parser.cpp",
|
||||||
"src/reflection.cpp",
|
"src/reflection.cpp",
|
||||||
"src/util.cpp",
|
"src/util.cpp",
|
||||||
"tests/monster_test_generated.h",
|
|
||||||
"tests/namespace_test/namespace_test1_generated.h",
|
"tests/namespace_test/namespace_test1_generated.h",
|
||||||
"tests/namespace_test/namespace_test2_generated.h",
|
"tests/namespace_test/namespace_test2_generated.h",
|
||||||
"tests/test.cpp",
|
"tests/test.cpp",
|
||||||
|
"tests/test_assert.cpp",
|
||||||
|
"tests/test_assert.h",
|
||||||
|
"tests/test_builder.cpp",
|
||||||
|
"tests/test_builder.h",
|
||||||
"tests/union_vector/union_vector_generated.h",
|
"tests/union_vector/union_vector_generated.h",
|
||||||
":public_headers",
|
":public_headers",
|
||||||
],
|
],
|
||||||
copts = FLATBUFFERS_COPTS + [
|
copts = [
|
||||||
"-DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE",
|
"-DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE",
|
||||||
|
"-DBAZEL_TEST_DATA_PATH",
|
||||||
],
|
],
|
||||||
data = [
|
data = [
|
||||||
":tests/include_test/include_test1.fbs",
|
":tests/include_test/include_test1.fbs",
|
||||||
@@ -139,7 +157,30 @@ cc_test(
|
|||||||
":tests/prototest/test.golden",
|
":tests/prototest/test.golden",
|
||||||
":tests/prototest/test.proto",
|
":tests/prototest/test.proto",
|
||||||
":tests/prototest/test_union.golden",
|
":tests/prototest/test_union.golden",
|
||||||
|
":tests/unicode_test.json",
|
||||||
":tests/union_vector/union_vector.fbs",
|
":tests/union_vector/union_vector.fbs",
|
||||||
|
":tests/union_vector/union_vector.json",
|
||||||
],
|
],
|
||||||
includes = ["include/"],
|
includes = ["include/"],
|
||||||
|
deps = [
|
||||||
|
":monster_extra_cc_fbs",
|
||||||
|
":monster_test_cc_fbs",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
# Test bzl rules
|
||||||
|
|
||||||
|
flatbuffer_cc_library(
|
||||||
|
name = "monster_test_cc_fbs",
|
||||||
|
srcs = ["tests/monster_test.fbs"],
|
||||||
|
include_paths = ["tests/include_test"],
|
||||||
|
includes = [
|
||||||
|
"tests/include_test/include_test1.fbs",
|
||||||
|
"tests/include_test/sub/include_test2.fbs",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
flatbuffer_cc_library(
|
||||||
|
name = "monster_extra_cc_fbs",
|
||||||
|
srcs = ["tests/monster_extra.fbs"],
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -71,6 +71,8 @@ function(build_flatbuffers flatbuffers_schemas
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(working_dir "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
|
||||||
set(schema_glob "*.fbs")
|
set(schema_glob "*.fbs")
|
||||||
# Generate the include files parameters.
|
# Generate the include files parameters.
|
||||||
set(include_params "")
|
set(include_params "")
|
||||||
@@ -97,7 +99,8 @@ function(build_flatbuffers flatbuffers_schemas
|
|||||||
-o ${generated_includes_dir}
|
-o ${generated_includes_dir}
|
||||||
${include_params}
|
${include_params}
|
||||||
-c ${schema}
|
-c ${schema}
|
||||||
DEPENDS ${FLATC_TARGET} ${schema} ${additional_dependencies})
|
DEPENDS ${FLATC_TARGET} ${schema} ${additional_dependencies}
|
||||||
|
WORKING_DIRECTORY "${working_dir}")
|
||||||
list(APPEND all_generated_files ${generated_include})
|
list(APPEND all_generated_files ${generated_include})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -109,7 +112,8 @@ function(build_flatbuffers flatbuffers_schemas
|
|||||||
-o ${binary_schemas_dir}
|
-o ${binary_schemas_dir}
|
||||||
${include_params}
|
${include_params}
|
||||||
${schema}
|
${schema}
|
||||||
DEPENDS ${FLATC_TARGET} ${schema} ${additional_dependencies})
|
DEPENDS ${FLATC_TARGET} ${schema} ${additional_dependencies}
|
||||||
|
WORKING_DIRECTORY "${working_dir}")
|
||||||
list(APPEND all_generated_files ${binary_schema})
|
list(APPEND all_generated_files ${binary_schema})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
4
CMake/DESCRIPTION.txt
Normal file
4
CMake/DESCRIPTION.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
FlatBuffers is a cross platform serialization library architected for
|
||||||
|
maximum memory efficiency. It allows you to directly access serialized
|
||||||
|
data without parsing/unpacking it first, while still having great
|
||||||
|
forwards/backwards compatibility.
|
||||||
@@ -45,6 +45,7 @@ if(FLATBUFFERS_FOUND)
|
|||||||
add_custom_command(OUTPUT ${FLATC_OUTPUT}
|
add_custom_command(OUTPUT ${FLATC_OUTPUT}
|
||||||
COMMAND ${FLATBUFFERS_FLATC_EXECUTABLE}
|
COMMAND ${FLATBUFFERS_FLATC_EXECUTABLE}
|
||||||
ARGS -c -o "${CMAKE_CURRENT_BINARY_DIR}/" ${FILE}
|
ARGS -c -o "${CMAKE_CURRENT_BINARY_DIR}/" ${FILE}
|
||||||
|
DEPENDS ${FILE}
|
||||||
COMMENT "Building C++ header for ${FILE}"
|
COMMENT "Building C++ header for ${FILE}"
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|||||||
@@ -37,5 +37,3 @@ if (UNIX)
|
|||||||
"${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
|
"${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
|
||||||
|
|
||||||
endif(UNIX)
|
endif(UNIX)
|
||||||
|
|
||||||
INCLUDE(CPack)
|
|
||||||
|
|||||||
34
CMake/PackageRedhat.cmake
Normal file
34
CMake/PackageRedhat.cmake
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
if (UNIX)
|
||||||
|
set(CPACK_GENERATOR "RPM")
|
||||||
|
set(CPACK_SOURCE_TGZ "ON")
|
||||||
|
|
||||||
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "FlatBuffers serialization library and schema compiler.")
|
||||||
|
|
||||||
|
set(CPACK_RPM_PACKAGE_HOMEPAGE "https://github.com/google/flatbuffers")
|
||||||
|
set(CPACK_RPM_PACKAGE_MAINTAINER "Marc Butler <mockbutler@gmail.com>")
|
||||||
|
|
||||||
|
set(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
|
||||||
|
set(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
|
||||||
|
set(CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH})
|
||||||
|
set(CPACK_PACKAGE_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_COMMIT}")
|
||||||
|
set(CPACK_RPM_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}")
|
||||||
|
|
||||||
|
set(CPACK_RPM_PACKAGE_NAME "flatbuffers")
|
||||||
|
|
||||||
|
# Assume this is not a cross complation build.
|
||||||
|
if(NOT CPACK_RPM_PACKAGE_ARCHITECTURE)
|
||||||
|
set(CPACK_RPM_PACKAGE_ARCHITECTURE "${CMAKE_SYSTEM_PROCESSOR}")
|
||||||
|
endif(NOT CPACK_RPM_PACKAGE_ARCHITECTURE)
|
||||||
|
|
||||||
|
set(CPACK_RPM_PACKAGE_VENDOR "Google, Inc.")
|
||||||
|
set(CPACK_RPM_PACKAGE_LICENSE "Apache 2.0")
|
||||||
|
set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE.txt)
|
||||||
|
set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_SOURCE_DIR}/CMake/DESCRIPTION.txt)
|
||||||
|
|
||||||
|
# This may reduce rpm compatiblity with very old systems.
|
||||||
|
set(CPACK_RPM_COMPRESSION_TYPE lzma)
|
||||||
|
|
||||||
|
set(CPACK_RPM_PACKAGE_NAME "flatbuffers")
|
||||||
|
set(CPACK_PACKAGE_FILE_NAME
|
||||||
|
"${CPACK_RPM_PACKAGE_NAME}_${CPACK_RPM_PACKAGE_VERSION}_${CPACK_RPM_PACKAGE_ARCHITECTURE}")
|
||||||
|
endif(UNIX)
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
find_program(GIT git)
|
find_program(GIT git)
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND ${GIT} describe
|
COMMAND ${GIT} describe
|
||||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
OUTPUT_VARIABLE GIT_DESCRIBE_DIRTY
|
OUTPUT_VARIABLE GIT_DESCRIBE_DIRTY
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
)
|
)
|
||||||
|
|||||||
147
CMakeLists.txt
147
CMakeLists.txt
@@ -1,4 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 2.8)
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
# generate compile_commands.json
|
||||||
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
include(CheckCXXSymbolExists)
|
||||||
|
|
||||||
project(FlatBuffers)
|
project(FlatBuffers)
|
||||||
|
|
||||||
@@ -15,6 +18,17 @@ option(FLATBUFFERS_BUILD_GRPCTEST "Enable the build of grpctest" OFF)
|
|||||||
option(FLATBUFFERS_BUILD_SHAREDLIB
|
option(FLATBUFFERS_BUILD_SHAREDLIB
|
||||||
"Enable the build of the flatbuffers shared library"
|
"Enable the build of the flatbuffers shared library"
|
||||||
OFF)
|
OFF)
|
||||||
|
option(FLATBUFFERS_LIBCXX_WITH_CLANG "Force libc++ when using Clang" ON)
|
||||||
|
# NOTE: Sanitizer check only works on Linux & OSX (gcc & llvm).
|
||||||
|
option(FLATBUFFERS_CODE_SANITIZE
|
||||||
|
"Add '-fsanitize' flags to 'flattests' and 'flatc' targets."
|
||||||
|
OFF)
|
||||||
|
option(FLATBUFFERS_PACKAGE_REDHAT
|
||||||
|
"Build an rpm using the 'package' target."
|
||||||
|
OFF)
|
||||||
|
option(FLATBUFFERS_PACKAGE_DEBIAN
|
||||||
|
"Build an deb using the 'package' target."
|
||||||
|
OFF)
|
||||||
|
|
||||||
if(NOT FLATBUFFERS_BUILD_FLATC AND FLATBUFFERS_BUILD_TESTS)
|
if(NOT FLATBUFFERS_BUILD_FLATC AND FLATBUFFERS_BUILD_TESTS)
|
||||||
message(WARNING
|
message(WARNING
|
||||||
@@ -22,6 +36,22 @@ if(NOT FLATBUFFERS_BUILD_FLATC AND FLATBUFFERS_BUILD_TESTS)
|
|||||||
set(FLATBUFFERS_BUILD_TESTS OFF)
|
set(FLATBUFFERS_BUILD_TESTS OFF)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(DEFINED FLATBUFFERS_MAX_PARSING_DEPTH)
|
||||||
|
# Override the default recursion depth limit.
|
||||||
|
add_definitions(-DFLATBUFFERS_MAX_PARSING_DEPTH=${FLATBUFFERS_MAX_PARSING_DEPTH})
|
||||||
|
message(STATUS "FLATBUFFERS_MAX_PARSING_DEPTH: ${FLATBUFFERS_MAX_PARSING_DEPTH}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Auto-detect locale-narrow 'strtod_l' function.
|
||||||
|
if(NOT DEFINED FLATBUFFERS_LOCALE_INDEPENDENT)
|
||||||
|
if(MSVC)
|
||||||
|
check_cxx_symbol_exists(_strtof_l stdlib.h FLATBUFFERS_LOCALE_INDEPENDENT)
|
||||||
|
else()
|
||||||
|
check_cxx_symbol_exists(strtof_l stdlib.h FLATBUFFERS_LOCALE_INDEPENDENT)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
add_definitions(-DFLATBUFFERS_LOCALE_INDEPENDENT=$<BOOL:${FLATBUFFERS_LOCALE_INDEPENDENT}>)
|
||||||
|
|
||||||
set(FlatBuffers_Library_SRCS
|
set(FlatBuffers_Library_SRCS
|
||||||
include/flatbuffers/code_generators.h
|
include/flatbuffers/code_generators.h
|
||||||
include/flatbuffers/base.h
|
include/flatbuffers/base.h
|
||||||
@@ -45,11 +75,15 @@ set(FlatBuffers_Library_SRCS
|
|||||||
set(FlatBuffers_Compiler_SRCS
|
set(FlatBuffers_Compiler_SRCS
|
||||||
${FlatBuffers_Library_SRCS}
|
${FlatBuffers_Library_SRCS}
|
||||||
src/idl_gen_cpp.cpp
|
src/idl_gen_cpp.cpp
|
||||||
|
src/idl_gen_dart.cpp
|
||||||
src/idl_gen_general.cpp
|
src/idl_gen_general.cpp
|
||||||
src/idl_gen_go.cpp
|
src/idl_gen_go.cpp
|
||||||
src/idl_gen_js.cpp
|
src/idl_gen_js_ts.cpp
|
||||||
src/idl_gen_php.cpp
|
src/idl_gen_php.cpp
|
||||||
src/idl_gen_python.cpp
|
src/idl_gen_python.cpp
|
||||||
|
src/idl_gen_lobster.cpp
|
||||||
|
src/idl_gen_lua.cpp
|
||||||
|
src/idl_gen_rust.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/idl_gen_json_schema.cpp
|
||||||
@@ -73,6 +107,10 @@ set(FlatBuffers_Tests_SRCS
|
|||||||
${FlatBuffers_Library_SRCS}
|
${FlatBuffers_Library_SRCS}
|
||||||
src/idl_gen_fbs.cpp
|
src/idl_gen_fbs.cpp
|
||||||
tests/test.cpp
|
tests/test.cpp
|
||||||
|
tests/test_assert.h
|
||||||
|
tests/test_assert.cpp
|
||||||
|
tests/test_builder.h
|
||||||
|
tests/test_builder.cpp
|
||||||
# file generate by running compiler on tests/monster_test.fbs
|
# file generate by running compiler on tests/monster_test.fbs
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h
|
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h
|
||||||
)
|
)
|
||||||
@@ -91,12 +129,25 @@ set(FlatBuffers_Sample_Text_SRCS
|
|||||||
${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
|
${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
set(FlatBuffers_Sample_BFBS_SRCS
|
||||||
|
${FlatBuffers_Library_SRCS}
|
||||||
|
src/idl_gen_general.cpp
|
||||||
|
samples/sample_bfbs.cpp
|
||||||
|
# file generated by running compiler on samples/monster.fbs
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
|
||||||
|
)
|
||||||
|
|
||||||
set(FlatBuffers_GRPCTest_SRCS
|
set(FlatBuffers_GRPCTest_SRCS
|
||||||
include/flatbuffers/flatbuffers.h
|
include/flatbuffers/flatbuffers.h
|
||||||
include/flatbuffers/grpc.h
|
include/flatbuffers/grpc.h
|
||||||
tests/monster_test.grpc.fb.h
|
tests/monster_test.grpc.fb.h
|
||||||
|
tests/test_assert.h
|
||||||
|
tests/test_builder.h
|
||||||
tests/monster_test.grpc.fb.cc
|
tests/monster_test.grpc.fb.cc
|
||||||
|
tests/test_assert.cpp
|
||||||
|
tests/test_builder.cpp
|
||||||
grpc/tests/grpctest.cpp
|
grpc/tests/grpctest.cpp
|
||||||
|
grpc/tests/message_builder_test.cpp
|
||||||
# file generated by running compiler on samples/monster.fbs
|
# file generated by running compiler on samples/monster.fbs
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
|
${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
|
||||||
)
|
)
|
||||||
@@ -107,9 +158,11 @@ set(FlatBuffers_GRPCTest_SRCS
|
|||||||
if(EXISTS "${CMAKE_TOOLCHAIN_FILE}")
|
if(EXISTS "${CMAKE_TOOLCHAIN_FILE}")
|
||||||
# do not apply any global settings if the toolchain
|
# do not apply any global settings if the toolchain
|
||||||
# is being configured externally
|
# is being configured externally
|
||||||
|
message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}.")
|
||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
|
||||||
|
set(FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wold-style-cast")
|
||||||
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
if(CYGWIN)
|
if(CYGWIN)
|
||||||
set(CMAKE_CXX_FLAGS
|
set(CMAKE_CXX_FLAGS
|
||||||
@@ -120,10 +173,11 @@ 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")
|
||||||
|
set(FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wold-style-cast")
|
||||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.4)
|
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.4)
|
||||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0)
|
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0)
|
||||||
set(CMAKE_CXX_FLAGS
|
set(CMAKE_CXX_FLAGS
|
||||||
"${CMAKE_CXX_FLAGS} -faligned-new")
|
"${CMAKE_CXX_FLAGS} -faligned-new -Werror=implicit-fallthrough=2")
|
||||||
endif()
|
endif()
|
||||||
set(CMAKE_CXX_FLAGS
|
set(CMAKE_CXX_FLAGS
|
||||||
"${CMAKE_CXX_FLAGS} -Wunused-result -Werror=unused-result -Wunused-parameter -Werror=unused-parameter")
|
"${CMAKE_CXX_FLAGS} -Wunused-result -Werror=unused-result -Wunused-parameter -Werror=unused-parameter")
|
||||||
@@ -137,14 +191,20 @@ 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 -Wextra -Wno-unused-parameter")
|
"${CMAKE_CXX_FLAGS} -std=c++0x -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
|
||||||
if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
|
set(FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wold-style-cast")
|
||||||
set(CMAKE_CXX_FLAGS
|
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.8)
|
||||||
"${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
list(APPEND FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wimplicit-fallthrough" "-Wextra-semi" "-Werror=unused-private-field") # enable warning
|
||||||
endif()
|
endif()
|
||||||
if(NOT ("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD" OR
|
if(FLATBUFFERS_LIBCXX_WITH_CLANG)
|
||||||
"${CMAKE_SYSTEM_NAME}" MATCHES "Linux"))
|
if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
|
||||||
set(CMAKE_EXE_LINKER_FLAGS
|
set(CMAKE_CXX_FLAGS
|
||||||
"${CMAKE_EXE_LINKER_FLAGS} -lc++abi")
|
"${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||||
|
endif()
|
||||||
|
if(NOT ("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD" OR
|
||||||
|
"${CMAKE_SYSTEM_NAME}" MATCHES "Linux"))
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS
|
||||||
|
"${CMAKE_EXE_LINKER_FLAGS} -lc++abi")
|
||||||
|
endif()
|
||||||
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
|
||||||
@@ -165,6 +225,27 @@ if(FLATBUFFERS_CODE_COVERAGE)
|
|||||||
"${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage")
|
"${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
function(add_fsanitize_to_target _target _sanitizer)
|
||||||
|
# FLATBUFFERS_CODE_SANITIZE: boolean {ON,OFF,YES,NO} or string with list of sanitizer.
|
||||||
|
# List of sanitizer is string starts with '=': "=address,undefined,thread,memory".
|
||||||
|
if((${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") OR
|
||||||
|
((${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9"))
|
||||||
|
)
|
||||||
|
set(_sanitizer_flags "=address,undefined")
|
||||||
|
if(_sanitizer MATCHES "=.*")
|
||||||
|
# override default by user-defined sanitizer list
|
||||||
|
set(_sanitizer_flags ${_sanitizer})
|
||||||
|
endif()
|
||||||
|
target_compile_options(${_target} PRIVATE
|
||||||
|
-g -fsigned-char -fno-omit-frame-pointer
|
||||||
|
"-fsanitize${_sanitizer_flags}")
|
||||||
|
target_link_libraries(${_target} PRIVATE
|
||||||
|
"-fsanitize${_sanitizer_flags}")
|
||||||
|
set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||||
|
message(STATUS "Sanitizer ${_sanitizer_flags} added to ${_target}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
if(BIICODE)
|
if(BIICODE)
|
||||||
include(biicode/cmake/biicode.cmake)
|
include(biicode/cmake/biicode.cmake)
|
||||||
return()
|
return()
|
||||||
@@ -174,11 +255,19 @@ include_directories(include)
|
|||||||
include_directories(grpc)
|
include_directories(grpc)
|
||||||
|
|
||||||
if(FLATBUFFERS_BUILD_FLATLIB)
|
if(FLATBUFFERS_BUILD_FLATLIB)
|
||||||
add_library(flatbuffers STATIC ${FlatBuffers_Library_SRCS})
|
add_library(flatbuffers STATIC ${FlatBuffers_Library_SRCS})
|
||||||
|
# CMake > 2.8.11: Attach header directory for when build via add_subdirectory().
|
||||||
|
target_include_directories(flatbuffers INTERFACE
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
|
||||||
|
target_compile_options(flatbuffers PRIVATE "${FLATBUFFERS_PRIVATE_CXX_FLAGS}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(FLATBUFFERS_BUILD_FLATC)
|
if(FLATBUFFERS_BUILD_FLATC)
|
||||||
add_executable(flatc ${FlatBuffers_Compiler_SRCS})
|
add_executable(flatc ${FlatBuffers_Compiler_SRCS})
|
||||||
|
target_compile_options(flatc PRIVATE "${FLATBUFFERS_PRIVATE_CXX_FLAGS}")
|
||||||
|
if(FLATBUFFERS_CODE_SANITIZE AND NOT WIN32)
|
||||||
|
add_fsanitize_to_target(flatc ${FLATBUFFERS_CODE_SANITIZE})
|
||||||
|
endif()
|
||||||
if(NOT FLATBUFFERS_FLATC_EXECUTABLE)
|
if(NOT FLATBUFFERS_FLATC_EXECUTABLE)
|
||||||
set(FLATBUFFERS_FLATC_EXECUTABLE $<TARGET_FILE:flatc>)
|
set(FLATBUFFERS_FLATC_EXECUTABLE $<TARGET_FILE:flatc>)
|
||||||
endif()
|
endif()
|
||||||
@@ -200,7 +289,7 @@ if(FLATBUFFERS_BUILD_SHAREDLIB)
|
|||||||
# - minor updated when there are additions in API/ABI
|
# - minor updated when there are additions in API/ABI
|
||||||
# - major (ABI number) updated when there are changes in ABI (or removals)
|
# - major (ABI number) updated when there are changes in ABI (or removals)
|
||||||
set(FlatBuffers_Library_SONAME_MAJOR "1")
|
set(FlatBuffers_Library_SONAME_MAJOR "1")
|
||||||
set(FlatBuffers_Library_SONAME_FULL "${FlatBuffers_Library_SONAME_MAJOR}.9.0")
|
set(FlatBuffers_Library_SONAME_FULL "${FlatBuffers_Library_SONAME_MAJOR}.11.0")
|
||||||
set_target_properties(flatbuffers_shared PROPERTIES OUTPUT_NAME flatbuffers
|
set_target_properties(flatbuffers_shared PROPERTIES OUTPUT_NAME flatbuffers
|
||||||
SOVERSION "${FlatBuffers_Library_SONAME_MAJOR}"
|
SOVERSION "${FlatBuffers_Library_SONAME_MAJOR}"
|
||||||
VERSION "${FlatBuffers_Library_SONAME_FULL}")
|
VERSION "${FlatBuffers_Library_SONAME_FULL}")
|
||||||
@@ -212,7 +301,7 @@ function(compile_flatbuffers_schema_to_cpp SRC_FBS)
|
|||||||
add_custom_command(
|
add_custom_command(
|
||||||
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 --gen-compare -o "${SRC_FBS_DIR}"
|
||||||
--cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs
|
--cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs
|
||||||
--reflect-names
|
--reflect-names
|
||||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||||
@@ -237,17 +326,35 @@ if(FLATBUFFERS_BUILD_TESTS)
|
|||||||
set_property(TARGET flattests
|
set_property(TARGET flattests
|
||||||
PROPERTY COMPILE_DEFINITIONS FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
PROPERTY COMPILE_DEFINITIONS FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||||
FLATBUFFERS_DEBUG_VERIFICATION_FAILURE=1)
|
FLATBUFFERS_DEBUG_VERIFICATION_FAILURE=1)
|
||||||
|
if(FLATBUFFERS_CODE_SANITIZE)
|
||||||
|
if(WIN32)
|
||||||
|
target_compile_definitions(flattests PRIVATE FLATBUFFERS_MEMORY_LEAK_TRACKING)
|
||||||
|
message(STATUS "Sanitizer MSVC::_CrtDumpMemoryLeaks added to flattests")
|
||||||
|
else()
|
||||||
|
add_fsanitize_to_target(flattests ${FLATBUFFERS_CODE_SANITIZE})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
compile_flatbuffers_schema_to_cpp(samples/monster.fbs)
|
compile_flatbuffers_schema_to_cpp(samples/monster.fbs)
|
||||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/samples)
|
include_directories(${CMAKE_CURRENT_BINARY_DIR}/samples)
|
||||||
add_executable(flatsamplebinary ${FlatBuffers_Sample_Binary_SRCS})
|
add_executable(flatsamplebinary ${FlatBuffers_Sample_Binary_SRCS})
|
||||||
add_executable(flatsampletext ${FlatBuffers_Sample_Text_SRCS})
|
add_executable(flatsampletext ${FlatBuffers_Sample_Text_SRCS})
|
||||||
|
add_executable(flatsamplebfbs ${FlatBuffers_Sample_BFBS_SRCS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(FLATBUFFERS_BUILD_GRPCTEST)
|
if(FLATBUFFERS_BUILD_GRPCTEST)
|
||||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
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()
|
||||||
|
if(NOT GRPC_INSTALL_PATH)
|
||||||
|
message(SEND_ERROR "GRPC_INSTALL_PATH variable is not defined. See grpc/README.md")
|
||||||
|
endif()
|
||||||
|
if(NOT PROTOBUF_DOWNLOAD_PATH)
|
||||||
|
message(SEND_ERROR "PROTOBUF_DOWNLOAD_PATH variable is not defined. See grpc/README.md")
|
||||||
|
endif()
|
||||||
|
INCLUDE_DIRECTORIES(${GRPC_INSTALL_PATH}/include)
|
||||||
|
INCLUDE_DIRECTORIES(${PROTOBUF_DOWNLOAD_PATH}/src)
|
||||||
|
LINK_DIRECTORIES(${GRPC_INSTALL_PATH}/lib)
|
||||||
add_executable(grpctest ${FlatBuffers_GRPCTest_SRCS})
|
add_executable(grpctest ${FlatBuffers_GRPCTest_SRCS})
|
||||||
target_link_libraries(grpctest grpc++_unsecure grpc_unsecure gpr pthread dl)
|
target_link_libraries(grpctest grpc++_unsecure grpc_unsecure gpr pthread dl)
|
||||||
endif()
|
endif()
|
||||||
@@ -292,7 +399,6 @@ if(FLATBUFFERS_INSTALL)
|
|||||||
install(
|
install(
|
||||||
TARGETS flatc EXPORT FlatcTargets
|
TARGETS flatc EXPORT FlatcTargets
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
CONFIGURATIONS Release
|
|
||||||
)
|
)
|
||||||
|
|
||||||
install(
|
install(
|
||||||
@@ -300,7 +406,6 @@ if(FLATBUFFERS_INSTALL)
|
|||||||
FILE FlatcTargets.cmake
|
FILE FlatcTargets.cmake
|
||||||
NAMESPACE flatbuffers::
|
NAMESPACE flatbuffers::
|
||||||
DESTINATION ${FB_CMAKE_DIR}
|
DESTINATION ${FB_CMAKE_DIR}
|
||||||
CONFIGURATIONS Release
|
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -337,10 +442,20 @@ if(FLATBUFFERS_BUILD_TESTS)
|
|||||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests" DESTINATION
|
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests" DESTINATION
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}")
|
"${CMAKE_CURRENT_BINARY_DIR}")
|
||||||
add_test(NAME flattests COMMAND flattests)
|
add_test(NAME flattests COMMAND flattests)
|
||||||
|
if(FLATBUFFERS_BUILD_GRPCTEST)
|
||||||
|
add_test(NAME grpctest COMMAND grpctest)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include(CMake/BuildFlatBuffers.cmake)
|
include(CMake/BuildFlatBuffers.cmake)
|
||||||
|
|
||||||
if(FLATBUFFERS_PACKAGE_DEBIAN)
|
if(UNIX)
|
||||||
include(CMake/PackageDebian.cmake)
|
# Use of CPack only supported on Linux systems.
|
||||||
|
if(FLATBUFFERS_PACKAGE_DEBIAN)
|
||||||
|
include(CMake/PackageDebian.cmake)
|
||||||
|
endif()
|
||||||
|
if (FLATBUFFERS_PACKAGE_REDHAT)
|
||||||
|
include(CMake/PackageRedhat.cmake)
|
||||||
|
endif()
|
||||||
|
include(CPack)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
13
WORKSPACE
13
WORKSPACE
@@ -1,2 +1,15 @@
|
|||||||
workspace(name = "com_github_google_flatbuffers")
|
workspace(name = "com_github_google_flatbuffers")
|
||||||
|
|
||||||
|
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||||
|
|
||||||
|
http_archive(
|
||||||
|
name = "io_bazel_rules_go",
|
||||||
|
sha256 = "492c3ac68ed9dcf527a07e6a1b2dcbf199c6bf8b35517951467ac32e421c06c1",
|
||||||
|
urls = ["https://github.com/bazelbuild/rules_go/releases/download/0.17.0/rules_go-0.17.0.tar.gz"],
|
||||||
|
)
|
||||||
|
|
||||||
|
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
|
||||||
|
|
||||||
|
go_rules_dependencies()
|
||||||
|
|
||||||
|
go_register_toolchains()
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ android {
|
|||||||
ndkBuild {
|
ndkBuild {
|
||||||
targets "FlatBufferTest"
|
targets "FlatBufferTest"
|
||||||
arguments "-j" + Runtime.getRuntime().availableProcessors()
|
arguments "-j" + Runtime.getRuntime().availableProcessors()
|
||||||
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ include $(CLEAR_VARS)
|
|||||||
LOCAL_MODULE := FlatBufferTest
|
LOCAL_MODULE := FlatBufferTest
|
||||||
LOCAL_SRC_FILES := android/jni/main.cpp \
|
LOCAL_SRC_FILES := android/jni/main.cpp \
|
||||||
tests/test.cpp \
|
tests/test.cpp \
|
||||||
|
tests/test_assert.h \
|
||||||
|
tests/test_builder.h \
|
||||||
|
tests/test_assert.cpp \
|
||||||
|
tests/test_builder.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 -latomic
|
LOCAL_LDLIBS := -llog -landroid -latomic
|
||||||
|
|||||||
24
appveyor.yml
24
appveyor.yml
@@ -13,7 +13,13 @@ environment:
|
|||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
- CMAKE_VS_VERSION: "10 2010"
|
- CMAKE_VS_VERSION: "10 2010"
|
||||||
|
MONSTER_EXTRA: "skip"
|
||||||
|
|
||||||
|
- CMAKE_VS_VERSION: "12 2013"
|
||||||
|
MONSTER_EXTRA: "skip"
|
||||||
|
|
||||||
- CMAKE_VS_VERSION: "14 2015"
|
- CMAKE_VS_VERSION: "14 2015"
|
||||||
|
MONSTER_EXTRA: ""
|
||||||
|
|
||||||
platform:
|
platform:
|
||||||
- x86
|
- x86
|
||||||
@@ -24,7 +30,8 @@ configuration:
|
|||||||
- Release
|
- Release
|
||||||
|
|
||||||
before_build:
|
before_build:
|
||||||
- cmake -G"Visual Studio %CMAKE_VS_VERSION%"
|
- set MONSTER_EXTRA=%MONSTER_EXTRA%
|
||||||
|
- cmake -G"Visual Studio %CMAKE_VS_VERSION%" -DFLATBUFFERS_CODE_SANITIZE=1 .
|
||||||
# This cuts down on a lot of noise generated by xamarin warnings.
|
# This cuts down on a lot of noise generated by xamarin warnings.
|
||||||
- del "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
- del "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
||||||
|
|
||||||
@@ -32,10 +39,20 @@ build:
|
|||||||
project: ALL_BUILD.vcxproj
|
project: ALL_BUILD.vcxproj
|
||||||
verbosity: minimal
|
verbosity: minimal
|
||||||
|
|
||||||
|
after_build:
|
||||||
|
- python conan/appveyor/install.py
|
||||||
|
- python conan/appveyor/build.py
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- set PATH=%CONDA_INSTALL_LOCN%;%CONDA_INSTALL_LOCN%\scripts;%PATH%;
|
- set PATH=%CONDA_INSTALL_LOCN%;%CONDA_INSTALL_LOCN%\scripts;%PATH%;
|
||||||
|
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
|
||||||
|
- rustup-init.exe -y
|
||||||
|
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
|
||||||
|
- rustc -V
|
||||||
|
- cargo -V
|
||||||
|
|
||||||
test_script:
|
test_script:
|
||||||
|
- call .appveyor\check-generate-code.bat -b %CONFIGURATION%
|
||||||
- "cd tests"
|
- "cd tests"
|
||||||
- rem "Building all code"
|
- rem "Building all code"
|
||||||
- generate_code.bat -b %CONFIGURATION%
|
- generate_code.bat -b %CONFIGURATION%
|
||||||
@@ -47,6 +64,8 @@ test_script:
|
|||||||
- rem "---------------- Java -----------------"
|
- rem "---------------- Java -----------------"
|
||||||
- "java -version"
|
- "java -version"
|
||||||
- "JavaTest.bat"
|
- "JavaTest.bat"
|
||||||
|
- rem "---------------- Rust ----------------"
|
||||||
|
- "RustTest.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"
|
||||||
@@ -73,6 +92,9 @@ test_script:
|
|||||||
- "cd FlatBuffers.Test"
|
- "cd FlatBuffers.Test"
|
||||||
- "msbuild.exe /property:Configuration=Release;OutputPath=tempcs /verbosity:minimal FlatBuffers.Test.csproj"
|
- "msbuild.exe /property:Configuration=Release;OutputPath=tempcs /verbosity:minimal FlatBuffers.Test.csproj"
|
||||||
- "tempcs\\FlatBuffers.Test.exe"
|
- "tempcs\\FlatBuffers.Test.exe"
|
||||||
|
# Run tests with UNSAFE_BYTEBUFFER
|
||||||
|
- "msbuild.exe /property:Configuration=Release;UnsafeByteBuffer=true;OutputPath=tempcsUnsafe /verbosity:minimal FlatBuffers.Test.csproj"
|
||||||
|
- "tempcsUnsafe\\FlatBuffers.Test.exe"
|
||||||
# TODO: add more languages.
|
# TODO: add more languages.
|
||||||
- "cd ..\\.."
|
- "cd ..\\.."
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
# Biicode configuration file
|
|
||||||
[paths]
|
|
||||||
include
|
|
||||||
[mains]
|
|
||||||
!android/*
|
|
||||||
[tests]
|
|
||||||
tests/*
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
Biicode C/C++ dependency manager
|
|
||||||
=================================
|
|
||||||
|
|
||||||
[](https://www.biicode.com/fenix/flatbuffers)
|
|
||||||
|
|
||||||
New with biicode? Check the [Getting Started Guide](http://docs.biicode.com/c++/gettingstarted.html).
|
|
||||||
|
|
||||||
How to build it?
|
|
||||||
------------------
|
|
||||||
Building it is too easy:
|
|
||||||
|
|
||||||
$ git clone git@github.com:google/flatbuffers.git
|
|
||||||
$ cd flatbuffers
|
|
||||||
$ bii init -L && bii build
|
|
||||||
$ ./bin/any_executable
|
|
||||||
|
|
||||||
Or run its tests:
|
|
||||||
|
|
||||||
$ bii test
|
|
||||||
|
|
||||||
You can check [the examples/flatbuffers block](https://www.biicode.com/examples/flatbuffers).
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
set(BII_TESTS_WORKING_DIR ${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
# Copying data files to project/bin folder
|
|
||||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/samples")
|
|
||||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/samples/monster.fbs"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/samples/monsterdata.json"
|
|
||||||
DESTINATION
|
|
||||||
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/samples")
|
|
||||||
endif()
|
|
||||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/tests")
|
|
||||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests"
|
|
||||||
DESTINATION
|
|
||||||
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
ADD_BIICODE_TARGETS()
|
|
||||||
|
|
||||||
string(REPLACE " " ";" REPLACED_FLAGS ${CMAKE_CXX_FLAGS})
|
|
||||||
target_compile_options(${BII_BLOCK_TARGET} INTERFACE ${REPLACED_FLAGS})
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
sudo apt-get update -qq
|
|
||||||
sudo apt-get install libglu1-mesa-dev xorg-dev
|
|
||||||
wget http://www.biicode.com/downloads/latest/ubuntu64
|
|
||||||
mv ubuntu64 bii-ubuntu64.deb
|
|
||||||
(sudo dpkg -i bii-ubuntu64.deb) && sudo apt-get -f install
|
|
||||||
rm bii-ubuntu64.deb
|
|
||||||
wget https://s3.amazonaws.com/biibinaries/thirdparty/cmake-3.0.2-Linux-64.tar.gz
|
|
||||||
tar -xzf cmake-3.0.2-Linux-64.tar.gz
|
|
||||||
sudo cp -fR cmake-3.0.2-Linux-64/* /usr
|
|
||||||
rm -rf cmake-3.0.2-Linux-64
|
|
||||||
rm cmake-3.0.2-Linux-64.tar.gz
|
|
||||||
|
|
||||||
cmake --version
|
|
||||||
bii init -l && bii configure -DCMAKE_BUILD_TYPE=$1 && bii test
|
|
||||||
237
build_defs.bzl
Normal file
237
build_defs.bzl
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
# Description:
|
||||||
|
# BUILD rules for generating flatbuffer files in various languages.
|
||||||
|
|
||||||
|
"""
|
||||||
|
Rules for building C++ flatbuffers with Bazel.
|
||||||
|
"""
|
||||||
|
|
||||||
|
flatc_path = "@com_github_google_flatbuffers//:flatc"
|
||||||
|
|
||||||
|
DEFAULT_INCLUDE_PATHS = [
|
||||||
|
"./",
|
||||||
|
"$(GENDIR)",
|
||||||
|
"$(BINDIR)",
|
||||||
|
]
|
||||||
|
|
||||||
|
DEFAULT_FLATC_ARGS = [
|
||||||
|
"--gen-object-api",
|
||||||
|
"--gen-compare",
|
||||||
|
"--no-includes",
|
||||||
|
"--gen-mutable",
|
||||||
|
"--reflect-names",
|
||||||
|
"--cpp-ptr-type flatbuffers::unique_ptr",
|
||||||
|
]
|
||||||
|
|
||||||
|
def flatbuffer_library_public(
|
||||||
|
name,
|
||||||
|
srcs,
|
||||||
|
outs,
|
||||||
|
language_flag,
|
||||||
|
out_prefix = "",
|
||||||
|
includes = [],
|
||||||
|
include_paths = DEFAULT_INCLUDE_PATHS,
|
||||||
|
flatc_args = DEFAULT_FLATC_ARGS,
|
||||||
|
reflection_name = "",
|
||||||
|
reflection_visiblity = None,
|
||||||
|
output_to_bindir = False):
|
||||||
|
"""Generates code files for reading/writing the given flatbuffers in the requested language using the public compiler.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: Rule name.
|
||||||
|
srcs: Source .fbs files. Sent in order to the compiler.
|
||||||
|
outs: Output files from flatc.
|
||||||
|
language_flag: Target language flag. One of [-c, -j, -js].
|
||||||
|
out_prefix: Prepend this path to the front of all generated files except on
|
||||||
|
single source targets. Usually is a directory name.
|
||||||
|
includes: Optional, list of filegroups of schemas that the srcs depend on.
|
||||||
|
include_paths: Optional, list of paths the includes files can be found in.
|
||||||
|
flatc_args: Optional, list of additional arguments to pass to flatc.
|
||||||
|
reflection_name: Optional, if set this will generate the flatbuffer
|
||||||
|
reflection binaries for the schemas.
|
||||||
|
reflection_visiblity: The visibility of the generated reflection Fileset.
|
||||||
|
output_to_bindir: Passed to genrule for output to bin directory.
|
||||||
|
|
||||||
|
|
||||||
|
This rule creates a filegroup(name) with all generated source files, and
|
||||||
|
optionally a Fileset([reflection_name]) with all generated reflection
|
||||||
|
binaries.
|
||||||
|
"""
|
||||||
|
include_paths_cmd = ["-I %s" % (s) for s in include_paths]
|
||||||
|
|
||||||
|
# '$(@D)' when given a single source target will give the appropriate
|
||||||
|
# directory. Appending 'out_prefix' is only necessary when given a build
|
||||||
|
# target with multiple sources.
|
||||||
|
output_directory = (
|
||||||
|
("-o $(@D)/%s" % (out_prefix)) if len(srcs) > 1 else ("-o $(@D)")
|
||||||
|
)
|
||||||
|
genrule_cmd = " ".join([
|
||||||
|
"SRCS=($(SRCS));",
|
||||||
|
"for f in $${SRCS[@]:0:%s}; do" % len(srcs),
|
||||||
|
"$(location %s)" % (flatc_path),
|
||||||
|
" ".join(include_paths_cmd),
|
||||||
|
" ".join(flatc_args),
|
||||||
|
language_flag,
|
||||||
|
output_directory,
|
||||||
|
"$$f;",
|
||||||
|
"done",
|
||||||
|
])
|
||||||
|
native.genrule(
|
||||||
|
name = name,
|
||||||
|
srcs = srcs + includes,
|
||||||
|
outs = outs,
|
||||||
|
output_to_bindir = output_to_bindir,
|
||||||
|
tools = [flatc_path],
|
||||||
|
cmd = genrule_cmd,
|
||||||
|
message = "Generating flatbuffer files for %s:" % (name),
|
||||||
|
)
|
||||||
|
if reflection_name:
|
||||||
|
reflection_genrule_cmd = " ".join([
|
||||||
|
"SRCS=($(SRCS));",
|
||||||
|
"for f in $${SRCS[@]:0:%s}; do" % len(srcs),
|
||||||
|
"$(location %s)" % (flatc_path),
|
||||||
|
"-b --schema",
|
||||||
|
" ".join(flatc_args),
|
||||||
|
" ".join(include_paths_cmd),
|
||||||
|
language_flag,
|
||||||
|
output_directory,
|
||||||
|
"$$f;",
|
||||||
|
"done",
|
||||||
|
])
|
||||||
|
reflection_outs = [
|
||||||
|
(out_prefix + "%s.bfbs") % (s.replace(".fbs", "").split("/")[-1])
|
||||||
|
for s in srcs
|
||||||
|
]
|
||||||
|
native.genrule(
|
||||||
|
name = "%s_srcs" % reflection_name,
|
||||||
|
srcs = srcs + includes,
|
||||||
|
outs = reflection_outs,
|
||||||
|
output_to_bindir = output_to_bindir,
|
||||||
|
tools = [flatc_path],
|
||||||
|
cmd = reflection_genrule_cmd,
|
||||||
|
message = "Generating flatbuffer reflection binary for %s:" % (name),
|
||||||
|
)
|
||||||
|
native.Fileset(
|
||||||
|
name = reflection_name,
|
||||||
|
out = "%s_out" % reflection_name,
|
||||||
|
entries = [
|
||||||
|
native.FilesetEntry(files = reflection_outs),
|
||||||
|
],
|
||||||
|
visibility = reflection_visiblity,
|
||||||
|
)
|
||||||
|
|
||||||
|
def flatbuffer_cc_library(
|
||||||
|
name,
|
||||||
|
srcs,
|
||||||
|
srcs_filegroup_name = "",
|
||||||
|
out_prefix = "",
|
||||||
|
includes = [],
|
||||||
|
include_paths = DEFAULT_INCLUDE_PATHS,
|
||||||
|
flatc_args = DEFAULT_FLATC_ARGS,
|
||||||
|
visibility = None,
|
||||||
|
srcs_filegroup_visibility = None,
|
||||||
|
gen_reflections = False):
|
||||||
|
'''A cc_library with the generated reader/writers for the given flatbuffer definitions.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: Rule name.
|
||||||
|
srcs: Source .fbs files. Sent in order to the compiler.
|
||||||
|
srcs_filegroup_name: Name of the output filegroup that holds srcs. Pass this
|
||||||
|
filegroup into the `includes` parameter of any other
|
||||||
|
flatbuffer_cc_library that depends on this one's schemas.
|
||||||
|
out_prefix: Prepend this path to the front of all generated files. Usually
|
||||||
|
is a directory name.
|
||||||
|
includes: Optional, list of filegroups of schemas that the srcs depend on.
|
||||||
|
** SEE REMARKS BELOW **
|
||||||
|
include_paths: Optional, list of paths the includes files can be found in.
|
||||||
|
flatc_args: Optional list of additional arguments to pass to flatc
|
||||||
|
(e.g. --gen-mutable).
|
||||||
|
visibility: The visibility of the generated cc_library. By default, use the
|
||||||
|
default visibility of the project.
|
||||||
|
srcs_filegroup_visibility: The visibility of the generated srcs filegroup.
|
||||||
|
By default, use the value of the visibility parameter above.
|
||||||
|
gen_reflections: Optional, if true this will generate the flatbuffer
|
||||||
|
reflection binaries for the schemas.
|
||||||
|
|
||||||
|
This produces:
|
||||||
|
filegroup([name]_srcs): all generated .h files.
|
||||||
|
filegroup(srcs_filegroup_name if specified, or [name]_includes if not):
|
||||||
|
Other flatbuffer_cc_library's can pass this in for their `includes`
|
||||||
|
parameter, if they depend on the schemas in this library.
|
||||||
|
Fileset([name]_reflection): (Optional) all generated reflection binaries.
|
||||||
|
cc_library([name]): library with sources and flatbuffers deps.
|
||||||
|
|
||||||
|
Remarks:
|
||||||
|
** Because the genrule used to call flatc does not have any trivial way of
|
||||||
|
computing the output list of files transitively generated by includes and
|
||||||
|
--gen-includes (the default) being defined for flatc, the --gen-includes
|
||||||
|
flag will not work as expected. The way around this is to add a dependency
|
||||||
|
to the flatbuffer_cc_library defined alongside the flatc included Fileset.
|
||||||
|
For example you might define:
|
||||||
|
|
||||||
|
flatbuffer_cc_library(
|
||||||
|
name = "my_fbs",
|
||||||
|
srcs = [ "schemas/foo.fbs" ],
|
||||||
|
includes = [ "//third_party/bazz:bazz_fbs_includes" ],
|
||||||
|
)
|
||||||
|
|
||||||
|
In which foo.fbs includes a few files from the Fileset defined at
|
||||||
|
//third_party/bazz:bazz_fbs_includes. When compiling the library that
|
||||||
|
includes foo_generated.h, and therefore has my_fbs as a dependency, it
|
||||||
|
will fail to find any of the bazz *_generated.h files unless you also
|
||||||
|
add bazz's flatbuffer_cc_library to your own dependency list, e.g.:
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "my_lib",
|
||||||
|
deps = [
|
||||||
|
":my_fbs",
|
||||||
|
"//third_party/bazz:bazz_fbs"
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
Happy dependent Flatbuffering!
|
||||||
|
'''
|
||||||
|
output_headers = [
|
||||||
|
(out_prefix + "%s_generated.h") % (s.replace(".fbs", "").split("/")[-1])
|
||||||
|
for s in srcs
|
||||||
|
]
|
||||||
|
reflection_name = "%s_reflection" % name if gen_reflections else ""
|
||||||
|
|
||||||
|
srcs_lib = "%s_srcs" % (name)
|
||||||
|
flatbuffer_library_public(
|
||||||
|
name = srcs_lib,
|
||||||
|
srcs = srcs,
|
||||||
|
outs = output_headers,
|
||||||
|
language_flag = "-c",
|
||||||
|
out_prefix = out_prefix,
|
||||||
|
includes = includes,
|
||||||
|
include_paths = include_paths,
|
||||||
|
flatc_args = flatc_args,
|
||||||
|
reflection_name = reflection_name,
|
||||||
|
reflection_visiblity = visibility,
|
||||||
|
)
|
||||||
|
native.cc_library(
|
||||||
|
name = name,
|
||||||
|
hdrs = [
|
||||||
|
":" + srcs_lib,
|
||||||
|
],
|
||||||
|
srcs = [
|
||||||
|
":" + srcs_lib,
|
||||||
|
],
|
||||||
|
features = [
|
||||||
|
"-parse_headers",
|
||||||
|
],
|
||||||
|
deps = [
|
||||||
|
"@com_github_google_flatbuffers//:runtime_cc",
|
||||||
|
],
|
||||||
|
includes = [],
|
||||||
|
linkstatic = 1,
|
||||||
|
visibility = visibility,
|
||||||
|
)
|
||||||
|
|
||||||
|
# A filegroup for the `srcs`. That is, all the schema files for this
|
||||||
|
# Flatbuffer set.
|
||||||
|
native.filegroup(
|
||||||
|
name = srcs_filegroup_name if srcs_filegroup_name else "%s_includes" % (name),
|
||||||
|
srcs = srcs,
|
||||||
|
visibility = srcs_filegroup_visibility if srcs_filegroup_visibility != None else visibility,
|
||||||
|
)
|
||||||
12
conan/CMakeLists.txt
Normal file
12
conan/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
cmake_minimum_required(VERSION 2.8)
|
||||||
|
|
||||||
|
message(STATUS "Conan FlatBuffers Wrapper")
|
||||||
|
|
||||||
|
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||||
|
conan_basic_setup()
|
||||||
|
|
||||||
|
if (WIN32 AND MSVC AND FLATBUFFERS_BUILD_SHAREDLIB)
|
||||||
|
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||||
|
endif(WIN32 AND MSVC AND FLATBUFFERS_BUILD_SHAREDLIB)
|
||||||
|
|
||||||
|
include(${CMAKE_SOURCE_DIR}/CMakeListsOriginal.txt)
|
||||||
8
conan/appveyor/build.py
Normal file
8
conan/appveyor/build.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import os
|
||||||
|
|
||||||
|
if os.getenv("APPVEYOR_REPO_TAG") != "true":
|
||||||
|
print("Skip build step. It's not TAG")
|
||||||
|
else:
|
||||||
|
os.system("python conan/build.py")
|
||||||
8
conan/appveyor/install.py
Normal file
8
conan/appveyor/install.py
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import os
|
||||||
|
|
||||||
|
if os.getenv("APPVEYOR_REPO_TAG") != "true":
|
||||||
|
print("Skip step. It's not TAG")
|
||||||
|
else:
|
||||||
|
os.system("pip install conan conan-package-tools")
|
||||||
69
conan/build.py
Normal file
69
conan/build.py
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import subprocess
|
||||||
|
from cpt.packager import ConanMultiPackager
|
||||||
|
|
||||||
|
|
||||||
|
def set_appveyor_environment():
|
||||||
|
if os.getenv("APPVEYOR") is not None:
|
||||||
|
compiler_version = os.getenv("CMAKE_VS_VERSION").split(" ")[0].replace('"', '')
|
||||||
|
os.environ["CONAN_VISUAL_VERSIONS"] = compiler_version
|
||||||
|
os.environ["CONAN_STABLE_BRANCH_PATTERN"] = "master"
|
||||||
|
ci_platform = os.getenv("Platform").replace('"', '')
|
||||||
|
ci_platform = "x86" if ci_platform == "x86" else "x86_64"
|
||||||
|
os.environ["CONAN_ARCHS"] = ci_platform
|
||||||
|
os.environ["CONAN_BUILD_TYPES"] = os.getenv("Configuration").replace('"', '')
|
||||||
|
|
||||||
|
|
||||||
|
def get_branch():
|
||||||
|
try:
|
||||||
|
for line in subprocess.check_output("git branch", shell=True).decode().splitlines():
|
||||||
|
line = line.strip()
|
||||||
|
if line.startswith("*") and " (HEAD detached" not in line:
|
||||||
|
return line.replace("*", "", 1).strip()
|
||||||
|
return ""
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
return ""
|
||||||
|
|
||||||
|
|
||||||
|
def get_version():
|
||||||
|
version = get_branch()
|
||||||
|
if os.getenv("TRAVIS", False):
|
||||||
|
version = os.getenv("TRAVIS_BRANCH")
|
||||||
|
|
||||||
|
if os.getenv("APPVEYOR", False):
|
||||||
|
version = os.getenv("APPVEYOR_REPO_BRANCH")
|
||||||
|
if os.getenv("APPVEYOR_REPO_TAG") == "true":
|
||||||
|
version = os.getenv("APPVEYOR_REPO_TAG_NAME")
|
||||||
|
|
||||||
|
match = re.search(r"v(\d+\.\d+\.\d+.*)", version)
|
||||||
|
if match:
|
||||||
|
return match.group(1)
|
||||||
|
return version
|
||||||
|
|
||||||
|
|
||||||
|
def get_reference(username):
|
||||||
|
return "flatbuffers/{}@google/stable".format(get_version())
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
login_username = os.getenv("CONAN_LOGIN_USERNAME", "aardappel")
|
||||||
|
username = os.getenv("CONAN_USERNAME", "google")
|
||||||
|
upload = os.getenv("CONAN_UPLOAD", "https://api.bintray.com/conan/aardappel/flatbuffers")
|
||||||
|
stable_branch_pattern = os.getenv("CONAN_STABLE_BRANCH_PATTERN", r"v\d+\.\d+\.\d+.*")
|
||||||
|
test_folder = os.getenv("CPT_TEST_FOLDER", os.path.join("conan", "test_package"))
|
||||||
|
upload_only_when_stable = os.getenv("CONAN_UPLOAD_ONLY_WHEN_STABLE", True)
|
||||||
|
set_appveyor_environment()
|
||||||
|
|
||||||
|
builder = ConanMultiPackager(reference=get_reference(username),
|
||||||
|
username=username,
|
||||||
|
login_username=login_username,
|
||||||
|
upload=upload,
|
||||||
|
stable_branch_pattern=stable_branch_pattern,
|
||||||
|
upload_only_when_stable=upload_only_when_stable,
|
||||||
|
test_folder=test_folder)
|
||||||
|
builder.add_common_builds(pure_c=False)
|
||||||
|
builder.run()
|
||||||
9
conan/test_package/CMakeLists.txt
Normal file
9
conan/test_package/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
project(test_package CXX)
|
||||||
|
cmake_minimum_required(VERSION 2.8.11)
|
||||||
|
|
||||||
|
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
||||||
|
conan_basic_setup()
|
||||||
|
|
||||||
|
add_executable(${PROJECT_NAME} test_package.cpp)
|
||||||
|
target_link_libraries(${PROJECT_NAME} ${CONAN_LIBS})
|
||||||
|
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 11)
|
||||||
21
conan/test_package/conanfile.py
Normal file
21
conan/test_package/conanfile.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from conans import ConanFile, CMake
|
||||||
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
class TestPackageConan(ConanFile):
|
||||||
|
settings = "os", "compiler", "build_type", "arch"
|
||||||
|
generators = "cmake"
|
||||||
|
|
||||||
|
def build(self):
|
||||||
|
cmake = CMake(self)
|
||||||
|
cmake.configure()
|
||||||
|
cmake.build()
|
||||||
|
|
||||||
|
def test(self):
|
||||||
|
bin_path = os.path.join("bin", "test_package")
|
||||||
|
self.run(bin_path, run_environment=True)
|
||||||
|
self.run("flatc --version", run_environment=True)
|
||||||
|
self.run("flathash fnv1_16 conan", run_environment=True)
|
||||||
35
conan/test_package/test_package.cpp
Normal file
35
conan/test_package/test_package.cpp
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 Google Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <iostream>
|
||||||
|
#include "flatbuffers/util.h"
|
||||||
|
|
||||||
|
// Test to validate Conan package generated
|
||||||
|
|
||||||
|
int main(int /*argc*/, const char * /*argv*/ []) {
|
||||||
|
|
||||||
|
const std::string filename("conanbuildinfo.cmake");
|
||||||
|
|
||||||
|
if (flatbuffers::FileExists(filename.c_str())) {
|
||||||
|
std::cout << "File " << filename << " exists.\n";
|
||||||
|
} else {
|
||||||
|
std::cout << "File " << filename << " does not exist.\n";
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
14
conan/travis/build.sh
Executable file
14
conan/travis/build.sh
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
|
||||||
|
if [[ "$(uname -s)" == 'Darwin' ]]; then
|
||||||
|
if which pyenv > /dev/null; then
|
||||||
|
eval "$(pyenv init -)"
|
||||||
|
fi
|
||||||
|
pyenv activate conan
|
||||||
|
fi
|
||||||
|
|
||||||
|
conan user
|
||||||
|
python conan/build.py
|
||||||
22
conan/travis/install.sh
Executable file
22
conan/travis/install.sh
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
set -x
|
||||||
|
|
||||||
|
if [[ "$(uname -s)" == 'Darwin' ]]; then
|
||||||
|
brew update || brew update
|
||||||
|
brew outdated pyenv || brew upgrade pyenv
|
||||||
|
brew install pyenv-virtualenv
|
||||||
|
brew install cmake || true
|
||||||
|
|
||||||
|
if which pyenv > /dev/null; then
|
||||||
|
eval "$(pyenv init -)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
pyenv install 2.7.10
|
||||||
|
pyenv virtualenv 2.7.10 conan
|
||||||
|
pyenv rehash
|
||||||
|
pyenv activate conan
|
||||||
|
fi
|
||||||
|
|
||||||
|
pip install -U conan_package_tools conan
|
||||||
62
conanfile.py
62
conanfile.py
@@ -4,50 +4,72 @@
|
|||||||
"""Conan recipe package for Google FlatBuffers
|
"""Conan recipe package for Google FlatBuffers
|
||||||
"""
|
"""
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
from conans import ConanFile, CMake, tools
|
from conans import ConanFile, CMake, tools
|
||||||
|
|
||||||
|
|
||||||
class FlatbuffersConan(ConanFile):
|
class FlatbuffersConan(ConanFile):
|
||||||
name = "flatbuffers"
|
name = "flatbuffers"
|
||||||
version = "1.9.0"
|
license = "Apache-2.0"
|
||||||
license = "https://github.com/google/flatbuffers/blob/master/LICENSE.txt"
|
|
||||||
url = "https://github.com/google/flatbuffers"
|
url = "https://github.com/google/flatbuffers"
|
||||||
|
homepage = "http://google.github.io/flatbuffers/"
|
||||||
|
author = "Wouter van Oortmerssen"
|
||||||
|
topics = ("conan", "flatbuffers", "serialization", "rpc", "json-parser")
|
||||||
description = "Memory Efficient Serialization Library"
|
description = "Memory Efficient Serialization Library"
|
||||||
settings = "os", "compiler", "build_type", "arch", "os_build", "arch_build"
|
settings = "os", "compiler", "build_type", "arch"
|
||||||
options = {"shared": [True, False]}
|
options = {"shared": [True, False], "fPIC": [True, False]}
|
||||||
default_options = "shared=False"
|
default_options = {"shared": False, "fPIC": True}
|
||||||
generators = "cmake"
|
generators = "cmake"
|
||||||
exports = "LICENSE.txt"
|
exports = "LICENSE.txt"
|
||||||
exports_sources = ["CMake/*", "include/*", "src/*", "grpc/*", "CMakeLists.txt"]
|
exports_sources = ["CMake/*", "include/*", "src/*", "grpc/*", "CMakeLists.txt", "conan/CMakeLists.txt"]
|
||||||
|
|
||||||
def _inject_magic_lines(self):
|
def source(self):
|
||||||
"""Inject Conan setup in cmake file to solve exteral dependencies.
|
"""Wrap the original CMake file to call conan_basic_setup
|
||||||
"""
|
"""
|
||||||
conan_magic_lines = '''project(FlatBuffers)
|
shutil.move("CMakeLists.txt", "CMakeListsOriginal.txt")
|
||||||
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
|
shutil.move(os.path.join("conan", "CMakeLists.txt"), "CMakeLists.txt")
|
||||||
conan_basic_setup()
|
|
||||||
'''
|
def config_options(self):
|
||||||
tools.replace_in_file("CMakeLists.txt", "project(FlatBuffers)", conan_magic_lines)
|
"""Remove fPIC option on Windows platform
|
||||||
|
"""
|
||||||
|
if self.settings.os == "Windows":
|
||||||
|
self.options.remove("fPIC")
|
||||||
|
|
||||||
|
def configure_cmake(self):
|
||||||
|
"""Create CMake instance and execute configure step
|
||||||
|
"""
|
||||||
|
cmake = CMake(self)
|
||||||
|
cmake.definitions["FLATBUFFERS_BUILD_TESTS"] = False
|
||||||
|
cmake.definitions["FLATBUFFERS_BUILD_SHAREDLIB"] = self.options.shared
|
||||||
|
cmake.definitions["FLATBUFFERS_BUILD_FLATLIB"] = not self.options.shared
|
||||||
|
cmake.configure()
|
||||||
|
return cmake
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
"""Configure, build and install FlatBuffers using CMake.
|
"""Configure, build and install FlatBuffers using CMake.
|
||||||
"""
|
"""
|
||||||
self._inject_magic_lines()
|
cmake = self.configure_cmake()
|
||||||
cmake = CMake(self)
|
|
||||||
cmake.definitions["FLATBUFFERS_BUILD_TESTS"] = False
|
|
||||||
cmake.definitions["FLATBUFFERS_BUILD_SHAREDLIB"] = self.options.shared
|
|
||||||
cmake.configure()
|
|
||||||
cmake.build()
|
cmake.build()
|
||||||
cmake.install()
|
|
||||||
|
|
||||||
def package(self):
|
def package(self):
|
||||||
"""Copy Flatbuffers' artifacts to package folder
|
"""Copy Flatbuffers' artifacts to package folder
|
||||||
"""
|
"""
|
||||||
|
cmake = self.configure_cmake()
|
||||||
|
cmake.install()
|
||||||
self.copy(pattern="LICENSE.txt", dst="licenses")
|
self.copy(pattern="LICENSE.txt", dst="licenses")
|
||||||
|
self.copy(pattern="FindFlatBuffers.cmake", dst=os.path.join("lib", "cmake", "flatbuffers"), src="CMake")
|
||||||
self.copy(pattern="flathash*", dst="bin", src="bin")
|
self.copy(pattern="flathash*", dst="bin", src="bin")
|
||||||
|
self.copy(pattern="flatc*", dst="bin", src="bin")
|
||||||
|
if self.settings.os == "Windows" and self.options.shared:
|
||||||
|
if self.settings.compiler == "Visual Studio":
|
||||||
|
shutil.move(os.path.join(self.package_folder, "lib", "%s.dll" % self.name),
|
||||||
|
os.path.join(self.package_folder, "bin", "%s.dll" % self.name))
|
||||||
|
elif self.settings.compiler == "gcc":
|
||||||
|
shutil.move(os.path.join(self.package_folder, "lib", "lib%s.dll" % self.name),
|
||||||
|
os.path.join(self.package_folder, "bin", "lib%s.dll" % self.name))
|
||||||
|
|
||||||
def package_info(self):
|
def package_info(self):
|
||||||
"""Collect built libraries names and solve flatc path.
|
"""Collect built libraries names and solve flatc path.
|
||||||
"""
|
"""
|
||||||
self.cpp_info.libs = tools.collect_libs(self)
|
self.cpp_info.libs = tools.collect_libs(self)
|
||||||
self.env_info.PATH.append(os.path.join(self.package_folder, "bin"))
|
self.user_info.flatc = os.path.join(self.package_folder, "bin", "flatc")
|
||||||
|
|||||||
14
dart/CHANGELOG.md
Normal file
14
dart/CHANGELOG.md
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# CHANGELOG
|
||||||
|
|
||||||
|
## 1.9.2
|
||||||
|
|
||||||
|
- Ensure `_writeString` adds enough padding to null terminate strings.
|
||||||
|
|
||||||
|
## 1.9.1
|
||||||
|
|
||||||
|
- Changed constant identifiers to be compatible with Dart 2.x
|
||||||
|
- No longer supports Dart 1.x
|
||||||
|
|
||||||
|
## 1.9.0
|
||||||
|
|
||||||
|
- Initial release, supports Dart 1.x and many dev versions of Dart 2.x
|
||||||
233
dart/LICENSE
Normal file
233
dart/LICENSE
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
The code in lib/flat_buffers.dart is based on code that was releases under the
|
||||||
|
following license:
|
||||||
|
|
||||||
|
Copyright 2012, the Dart project authors. All rights reserved.
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
* Neither the name of Google Inc. nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
To the extent permissible, the changes to that code and the other assets in
|
||||||
|
this package are licensed under the Apache2 license:
|
||||||
|
|
||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright 2014 Google Inc.
|
||||||
|
|
||||||
|
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.
|
||||||
13
dart/README.md
Normal file
13
dart/README.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# FlatBuffers for Dart
|
||||||
|
|
||||||
|
This package is used to read and write FlatBuffer files in Dart.
|
||||||
|
|
||||||
|
Most consumers will want to use the [`flatc`](https://github.com/google/flatbuffers)
|
||||||
|
compiler to generate Dart code from a FlatBuffers IDL schema. For example, the
|
||||||
|
`monster_my_game.sample_generated.dart` was generated with `flatc` from
|
||||||
|
`monster.fbs` in the example folder. The generated classes can be used to read
|
||||||
|
or write binary files that are interoperable with other languages and platforms
|
||||||
|
supported by FlatBuffers, as illustrated in the `example.dart` in the
|
||||||
|
examples folder.
|
||||||
|
|
||||||
|
Additional documentation and examples are available [at the FlatBuffers site](https://google.github.io/flatbuffers/index.html)
|
||||||
155
dart/example/example.dart
Normal file
155
dart/example/example.dart
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 Dan Field. 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 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||||
|
import './monster_my_game.sample_generated.dart' as myGame;
|
||||||
|
|
||||||
|
// Example how to use FlatBuffers to create and read binary buffers.
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
builderTest();
|
||||||
|
objectBuilderTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
void builderTest() {
|
||||||
|
final builder = new fb.Builder(initialSize: 1024);
|
||||||
|
final int weaponOneName = builder.writeString("Sword");
|
||||||
|
final int weaponOneDamage = 3;
|
||||||
|
|
||||||
|
final int weaponTwoName = builder.writeString("Axe");
|
||||||
|
final int weaponTwoDamage = 5;
|
||||||
|
|
||||||
|
final swordBuilder = new myGame.WeaponBuilder(builder)
|
||||||
|
..begin()
|
||||||
|
..addNameOffset(weaponOneName)
|
||||||
|
..addDamage(weaponOneDamage);
|
||||||
|
final int sword = swordBuilder.finish();
|
||||||
|
|
||||||
|
final axeBuilder = new myGame.WeaponBuilder(builder)
|
||||||
|
..begin()
|
||||||
|
..addNameOffset(weaponTwoName)
|
||||||
|
..addDamage(weaponTwoDamage);
|
||||||
|
final int axe = axeBuilder.finish();
|
||||||
|
|
||||||
|
// Serialize a name for our monster, called "Orc".
|
||||||
|
final int name = builder.writeString('Orc');
|
||||||
|
|
||||||
|
// Create a list representing the inventory of the Orc. Each number
|
||||||
|
// could correspond to an item that can be claimed after he is slain.
|
||||||
|
final List<int> treasure = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||||
|
final inventory = builder.writeListUint8(treasure);
|
||||||
|
final weapons = builder.writeList([sword, axe]);
|
||||||
|
|
||||||
|
// Struct builders are very easy to reuse.
|
||||||
|
final vec3Builder = new myGame.Vec3Builder(builder);
|
||||||
|
|
||||||
|
vec3Builder.finish(4.0, 5.0, 6.0);
|
||||||
|
vec3Builder.finish(1.0, 2.0, 3.0);
|
||||||
|
// Set his hit points to 300 and his mana to 150.
|
||||||
|
final int hp = 300;
|
||||||
|
final int mana = 150;
|
||||||
|
|
||||||
|
final monster = new myGame.MonsterBuilder(builder)
|
||||||
|
..begin()
|
||||||
|
..addNameOffset(name)
|
||||||
|
..addInventoryOffset(inventory)
|
||||||
|
..addWeaponsOffset(weapons)
|
||||||
|
..addEquippedType(myGame.EquipmentTypeId.Weapon)
|
||||||
|
..addEquippedOffset(axe)
|
||||||
|
..addHp(hp)
|
||||||
|
..addMana(mana)
|
||||||
|
..addPos(vec3Builder.finish(1.0, 2.0, 3.0))
|
||||||
|
..addColor(myGame.Color.Red);
|
||||||
|
|
||||||
|
final int monsteroff = monster.finish();
|
||||||
|
final buffer = builder.finish(monsteroff);
|
||||||
|
if (verify(buffer)) {
|
||||||
|
print(
|
||||||
|
"The FlatBuffer was successfully created with a builder and verified!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void objectBuilderTest() {
|
||||||
|
// Create the builder here so we can use it for both weapons and equipped
|
||||||
|
// the actual data will only be written to the buffer once.
|
||||||
|
var axe = new myGame.WeaponObjectBuilder(name: 'Axe', damage: 5);
|
||||||
|
|
||||||
|
var monsterBuilder = new myGame.MonsterObjectBuilder(
|
||||||
|
pos: new myGame.Vec3ObjectBuilder(x: 1.0, y: 2.0, z: 3.0),
|
||||||
|
mana: 150,
|
||||||
|
hp: 300,
|
||||||
|
name: 'Orc',
|
||||||
|
inventory: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
|
||||||
|
color: myGame.Color.Red,
|
||||||
|
weapons: [new myGame.WeaponObjectBuilder(name: 'Sword', damage: 3), axe],
|
||||||
|
equippedType: myGame.EquipmentTypeId.Weapon,
|
||||||
|
equipped: axe,
|
||||||
|
);
|
||||||
|
|
||||||
|
var buffer = monsterBuilder.toBytes();
|
||||||
|
|
||||||
|
// We now have a FlatBuffer we can store on disk or send over a network.
|
||||||
|
|
||||||
|
// ** file/network code goes here :) **
|
||||||
|
|
||||||
|
// Instead, we're going to access it right away (as if we just received it).
|
||||||
|
if (verify(buffer)) {
|
||||||
|
print(
|
||||||
|
"The FlatBuffer was successfully created with an object builder and verified!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool verify(List<int> buffer) {
|
||||||
|
// Get access to the root:
|
||||||
|
var monster = new myGame.Monster(buffer);
|
||||||
|
|
||||||
|
// Get and test some scalar types from the FlatBuffer.
|
||||||
|
assert(monster.hp == 80);
|
||||||
|
assert(monster.mana == 150); // default
|
||||||
|
assert(monster.name == "MyMonster");
|
||||||
|
|
||||||
|
// Get and test a field of the FlatBuffer's `struct`.
|
||||||
|
var pos = monster.pos;
|
||||||
|
assert(pos != null);
|
||||||
|
assert(pos.z == 3.0);
|
||||||
|
|
||||||
|
// Get a test an element from the `inventory` FlatBuffer's `vector`.
|
||||||
|
var inv = monster.inventory;
|
||||||
|
assert(inv != null);
|
||||||
|
assert(inv.length == 10);
|
||||||
|
assert(inv[9] == 9);
|
||||||
|
|
||||||
|
// Get and test the `weapons` FlatBuffers's `vector`.
|
||||||
|
var expected_weapon_names = ["Sword", "Axe"];
|
||||||
|
var expected_weapon_damages = [3, 5];
|
||||||
|
var weps = monster.weapons;
|
||||||
|
for (int i = 0; i < weps.length; i++) {
|
||||||
|
assert(weps[i].name == expected_weapon_names[i]);
|
||||||
|
assert(weps[i].damage == expected_weapon_damages[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get and test the `Equipment` union (`equipped` field).
|
||||||
|
assert(monster.equippedType.value == myGame.EquipmentTypeId.Weapon.value);
|
||||||
|
assert(monster.equippedType == myGame.EquipmentTypeId.Weapon);
|
||||||
|
|
||||||
|
assert(monster.equipped is myGame.Weapon);
|
||||||
|
var equipped = monster.equipped as myGame.Weapon;
|
||||||
|
assert(equipped.name == "Axe");
|
||||||
|
assert(equipped.damage == 5);
|
||||||
|
|
||||||
|
print(monster);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
440
dart/example/monster_my_game.sample_generated.dart
Normal file
440
dart/example/monster_my_game.sample_generated.dart
Normal file
@@ -0,0 +1,440 @@
|
|||||||
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
// ignore_for_file: unused_import, non_constant_identifier_names
|
||||||
|
|
||||||
|
library my_game.sample;
|
||||||
|
|
||||||
|
import 'dart:typed_data' show Uint8List;
|
||||||
|
import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||||
|
|
||||||
|
|
||||||
|
class Color {
|
||||||
|
final int value;
|
||||||
|
const Color._(this.value);
|
||||||
|
|
||||||
|
factory Color.fromValue(int value) {
|
||||||
|
if (value == null) return null;
|
||||||
|
if (!values.containsKey(value)) {
|
||||||
|
throw new StateError('Invalid value $value for bit flag enum Color');
|
||||||
|
}
|
||||||
|
return values[value];
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int minValue = 0;
|
||||||
|
static const int maxValue = 2;
|
||||||
|
static bool containsValue(int value) => values.containsKey(value);
|
||||||
|
|
||||||
|
static const Color Red = const Color._(0);
|
||||||
|
static const Color Green = const Color._(1);
|
||||||
|
static const Color Blue = const Color._(2);
|
||||||
|
static get values => {0: Red,1: Green,2: Blue,};
|
||||||
|
|
||||||
|
static const fb.Reader<Color> reader = const _ColorReader();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'Color{value: $value}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ColorReader extends fb.Reader<Color> {
|
||||||
|
const _ColorReader();
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get size => 1;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Color read(fb.BufferContext bc, int offset) =>
|
||||||
|
new Color.fromValue(const fb.Int8Reader().read(bc, offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
class EquipmentTypeId {
|
||||||
|
final int value;
|
||||||
|
const EquipmentTypeId._(this.value);
|
||||||
|
|
||||||
|
factory EquipmentTypeId.fromValue(int value) {
|
||||||
|
if (value == null) return null;
|
||||||
|
if (!values.containsKey(value)) {
|
||||||
|
throw new StateError('Invalid value $value for bit flag enum EquipmentTypeId');
|
||||||
|
}
|
||||||
|
return values[value];
|
||||||
|
}
|
||||||
|
|
||||||
|
static const int minValue = 0;
|
||||||
|
static const int maxValue = 1;
|
||||||
|
static bool containsValue(int value) => values.containsKey(value);
|
||||||
|
|
||||||
|
static const EquipmentTypeId NONE = const EquipmentTypeId._(0);
|
||||||
|
static const EquipmentTypeId Weapon = const EquipmentTypeId._(1);
|
||||||
|
static get values => {0: NONE,1: Weapon,};
|
||||||
|
|
||||||
|
static const fb.Reader<EquipmentTypeId> reader = const _EquipmentTypeIdReader();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'EquipmentTypeId{value: $value}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _EquipmentTypeIdReader extends fb.Reader<EquipmentTypeId> {
|
||||||
|
const _EquipmentTypeIdReader();
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get size => 1;
|
||||||
|
|
||||||
|
@override
|
||||||
|
EquipmentTypeId read(fb.BufferContext bc, int offset) =>
|
||||||
|
new EquipmentTypeId.fromValue(const fb.Uint8Reader().read(bc, offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
class Vec3 {
|
||||||
|
Vec3._(this._bc, this._bcOffset);
|
||||||
|
|
||||||
|
static const fb.Reader<Vec3> reader = const _Vec3Reader();
|
||||||
|
|
||||||
|
final fb.BufferContext _bc;
|
||||||
|
final int _bcOffset;
|
||||||
|
|
||||||
|
double get x => const fb.Float32Reader().read(_bc, _bcOffset + 0);
|
||||||
|
double get y => const fb.Float32Reader().read(_bc, _bcOffset + 4);
|
||||||
|
double get z => const fb.Float32Reader().read(_bc, _bcOffset + 8);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'Vec3{x: $x, y: $y, z: $z}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _Vec3Reader extends fb.StructReader<Vec3> {
|
||||||
|
const _Vec3Reader();
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get size => 12;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Vec3 createObject(fb.BufferContext bc, int offset) =>
|
||||||
|
new Vec3._(bc, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
class Vec3Builder {
|
||||||
|
Vec3Builder(this.fbBuilder) {
|
||||||
|
assert(fbBuilder != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final fb.Builder fbBuilder;
|
||||||
|
|
||||||
|
int finish(double x, double y, double z) {
|
||||||
|
fbBuilder.putFloat32(z);
|
||||||
|
fbBuilder.putFloat32(y);
|
||||||
|
fbBuilder.putFloat32(x);
|
||||||
|
return fbBuilder.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class Vec3ObjectBuilder extends fb.ObjectBuilder {
|
||||||
|
final double _x;
|
||||||
|
final double _y;
|
||||||
|
final double _z;
|
||||||
|
|
||||||
|
Vec3ObjectBuilder({
|
||||||
|
double x,
|
||||||
|
double y,
|
||||||
|
double z,
|
||||||
|
})
|
||||||
|
: _x = x,
|
||||||
|
_y = y,
|
||||||
|
_z = z;
|
||||||
|
|
||||||
|
/// Finish building, and store into the [fbBuilder].
|
||||||
|
@override
|
||||||
|
int finish(
|
||||||
|
fb.Builder fbBuilder) {
|
||||||
|
assert(fbBuilder != null);
|
||||||
|
|
||||||
|
fbBuilder.putFloat32(_z);
|
||||||
|
fbBuilder.putFloat32(_y);
|
||||||
|
fbBuilder.putFloat32(_x);
|
||||||
|
return fbBuilder.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convenience method to serialize to byte list.
|
||||||
|
@override
|
||||||
|
Uint8List toBytes([String fileIdentifier]) {
|
||||||
|
fb.Builder fbBuilder = new fb.Builder();
|
||||||
|
int offset = finish(fbBuilder);
|
||||||
|
return fbBuilder.finish(offset, fileIdentifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Monster {
|
||||||
|
Monster._(this._bc, this._bcOffset);
|
||||||
|
factory Monster(List<int> bytes) {
|
||||||
|
fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes);
|
||||||
|
return reader.read(rootRef, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const fb.Reader<Monster> reader = const _MonsterReader();
|
||||||
|
|
||||||
|
final fb.BufferContext _bc;
|
||||||
|
final int _bcOffset;
|
||||||
|
|
||||||
|
Vec3 get pos => Vec3.reader.vTableGet(_bc, _bcOffset, 4, null);
|
||||||
|
int get mana => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 6, 150);
|
||||||
|
int get hp => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 8, 100);
|
||||||
|
String get name => const fb.StringReader().vTableGet(_bc, _bcOffset, 10, null);
|
||||||
|
List<int> get inventory => const fb.ListReader<int>(const fb.Uint8Reader()).vTableGet(_bc, _bcOffset, 14, null);
|
||||||
|
Color get color => new Color.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 16, 2));
|
||||||
|
List<Weapon> get weapons => const fb.ListReader<Weapon>(Weapon.reader).vTableGet(_bc, _bcOffset, 18, null);
|
||||||
|
EquipmentTypeId get equippedType => new EquipmentTypeId.fromValue(const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 20, null));
|
||||||
|
dynamic get equipped {
|
||||||
|
switch (equippedType?.value) {
|
||||||
|
case 1: return Weapon.reader.vTableGet(_bc, _bcOffset, 22, null);
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
List<Vec3> get path => const fb.ListReader<Vec3>(Vec3.reader).vTableGet(_bc, _bcOffset, 24, null);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'Monster{pos: $pos, mana: $mana, hp: $hp, name: $name, inventory: $inventory, color: $color, weapons: $weapons, equippedType: $equippedType, equipped: $equipped, path: $path}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MonsterReader extends fb.TableReader<Monster> {
|
||||||
|
const _MonsterReader();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Monster createObject(fb.BufferContext bc, int offset) =>
|
||||||
|
new Monster._(bc, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
class MonsterBuilder {
|
||||||
|
MonsterBuilder(this.fbBuilder) {
|
||||||
|
assert(fbBuilder != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final fb.Builder fbBuilder;
|
||||||
|
|
||||||
|
void begin() {
|
||||||
|
fbBuilder.startTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
int addPos(int offset) {
|
||||||
|
fbBuilder.addStruct(0, offset);
|
||||||
|
return fbBuilder.offset;
|
||||||
|
}
|
||||||
|
int addMana(int mana) {
|
||||||
|
fbBuilder.addInt16(1, mana);
|
||||||
|
return fbBuilder.offset;
|
||||||
|
}
|
||||||
|
int addHp(int hp) {
|
||||||
|
fbBuilder.addInt16(2, hp);
|
||||||
|
return fbBuilder.offset;
|
||||||
|
}
|
||||||
|
int addNameOffset(int offset) {
|
||||||
|
fbBuilder.addOffset(3, offset);
|
||||||
|
return fbBuilder.offset;
|
||||||
|
}
|
||||||
|
int addInventoryOffset(int offset) {
|
||||||
|
fbBuilder.addOffset(5, offset);
|
||||||
|
return fbBuilder.offset;
|
||||||
|
}
|
||||||
|
int addColor(Color color) {
|
||||||
|
fbBuilder.addInt8(6, color?.value);
|
||||||
|
return fbBuilder.offset;
|
||||||
|
}
|
||||||
|
int addWeaponsOffset(int offset) {
|
||||||
|
fbBuilder.addOffset(7, offset);
|
||||||
|
return fbBuilder.offset;
|
||||||
|
}
|
||||||
|
int addEquippedType(EquipmentTypeId equippedType) {
|
||||||
|
fbBuilder.addUint8(8, equippedType?.value);
|
||||||
|
return fbBuilder.offset;
|
||||||
|
}
|
||||||
|
int addEquippedOffset(int offset) {
|
||||||
|
fbBuilder.addOffset(9, offset);
|
||||||
|
return fbBuilder.offset;
|
||||||
|
}
|
||||||
|
int addPathOffset(int offset) {
|
||||||
|
fbBuilder.addOffset(10, offset);
|
||||||
|
return fbBuilder.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
int finish() {
|
||||||
|
return fbBuilder.endTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||||
|
final Vec3ObjectBuilder _pos;
|
||||||
|
final int _mana;
|
||||||
|
final int _hp;
|
||||||
|
final String _name;
|
||||||
|
final List<int> _inventory;
|
||||||
|
final Color _color;
|
||||||
|
final List<WeaponObjectBuilder> _weapons;
|
||||||
|
final EquipmentTypeId _equippedType;
|
||||||
|
final dynamic _equipped;
|
||||||
|
final List<Vec3ObjectBuilder> _path;
|
||||||
|
|
||||||
|
MonsterObjectBuilder({
|
||||||
|
Vec3ObjectBuilder pos,
|
||||||
|
int mana,
|
||||||
|
int hp,
|
||||||
|
String name,
|
||||||
|
List<int> inventory,
|
||||||
|
Color color,
|
||||||
|
List<WeaponObjectBuilder> weapons,
|
||||||
|
EquipmentTypeId equippedType,
|
||||||
|
dynamic equipped,
|
||||||
|
List<Vec3ObjectBuilder> path,
|
||||||
|
})
|
||||||
|
: _pos = pos,
|
||||||
|
_mana = mana,
|
||||||
|
_hp = hp,
|
||||||
|
_name = name,
|
||||||
|
_inventory = inventory,
|
||||||
|
_color = color,
|
||||||
|
_weapons = weapons,
|
||||||
|
_equippedType = equippedType,
|
||||||
|
_equipped = equipped,
|
||||||
|
_path = path;
|
||||||
|
|
||||||
|
/// Finish building, and store into the [fbBuilder].
|
||||||
|
@override
|
||||||
|
int finish(
|
||||||
|
fb.Builder fbBuilder) {
|
||||||
|
assert(fbBuilder != null);
|
||||||
|
final int nameOffset = fbBuilder.writeString(_name);
|
||||||
|
final int inventoryOffset = _inventory?.isNotEmpty == true
|
||||||
|
? fbBuilder.writeListUint8(_inventory)
|
||||||
|
: null;
|
||||||
|
final int weaponsOffset = _weapons?.isNotEmpty == true
|
||||||
|
? fbBuilder.writeList(_weapons.map((b) => b.getOrCreateOffset(fbBuilder)).toList())
|
||||||
|
: null;
|
||||||
|
final int equippedOffset = _equipped?.getOrCreateOffset(fbBuilder);
|
||||||
|
final int pathOffset = _path?.isNotEmpty == true
|
||||||
|
? fbBuilder.writeListOfStructs(_path)
|
||||||
|
: null;
|
||||||
|
|
||||||
|
fbBuilder.startTable();
|
||||||
|
if (_pos != null) {
|
||||||
|
fbBuilder.addStruct(0, _pos.finish(fbBuilder));
|
||||||
|
}
|
||||||
|
fbBuilder.addInt16(1, _mana);
|
||||||
|
fbBuilder.addInt16(2, _hp);
|
||||||
|
if (nameOffset != null) {
|
||||||
|
fbBuilder.addOffset(3, nameOffset);
|
||||||
|
}
|
||||||
|
if (inventoryOffset != null) {
|
||||||
|
fbBuilder.addOffset(5, inventoryOffset);
|
||||||
|
}
|
||||||
|
fbBuilder.addInt8(6, _color?.value);
|
||||||
|
if (weaponsOffset != null) {
|
||||||
|
fbBuilder.addOffset(7, weaponsOffset);
|
||||||
|
}
|
||||||
|
fbBuilder.addUint8(8, _equippedType?.value);
|
||||||
|
if (equippedOffset != null) {
|
||||||
|
fbBuilder.addOffset(9, equippedOffset);
|
||||||
|
}
|
||||||
|
if (pathOffset != null) {
|
||||||
|
fbBuilder.addOffset(10, pathOffset);
|
||||||
|
}
|
||||||
|
return fbBuilder.endTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convenience method to serialize to byte list.
|
||||||
|
@override
|
||||||
|
Uint8List toBytes([String fileIdentifier]) {
|
||||||
|
fb.Builder fbBuilder = new fb.Builder();
|
||||||
|
int offset = finish(fbBuilder);
|
||||||
|
return fbBuilder.finish(offset, fileIdentifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Weapon {
|
||||||
|
Weapon._(this._bc, this._bcOffset);
|
||||||
|
factory Weapon(List<int> bytes) {
|
||||||
|
fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes);
|
||||||
|
return reader.read(rootRef, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const fb.Reader<Weapon> reader = const _WeaponReader();
|
||||||
|
|
||||||
|
final fb.BufferContext _bc;
|
||||||
|
final int _bcOffset;
|
||||||
|
|
||||||
|
String get name => const fb.StringReader().vTableGet(_bc, _bcOffset, 4, null);
|
||||||
|
int get damage => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 6, null);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'Weapon{name: $name, damage: $damage}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _WeaponReader extends fb.TableReader<Weapon> {
|
||||||
|
const _WeaponReader();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Weapon createObject(fb.BufferContext bc, int offset) =>
|
||||||
|
new Weapon._(bc, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
class WeaponBuilder {
|
||||||
|
WeaponBuilder(this.fbBuilder) {
|
||||||
|
assert(fbBuilder != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
final fb.Builder fbBuilder;
|
||||||
|
|
||||||
|
void begin() {
|
||||||
|
fbBuilder.startTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
int addNameOffset(int offset) {
|
||||||
|
fbBuilder.addOffset(0, offset);
|
||||||
|
return fbBuilder.offset;
|
||||||
|
}
|
||||||
|
int addDamage(int damage) {
|
||||||
|
fbBuilder.addInt16(1, damage);
|
||||||
|
return fbBuilder.offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
int finish() {
|
||||||
|
return fbBuilder.endTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class WeaponObjectBuilder extends fb.ObjectBuilder {
|
||||||
|
final String _name;
|
||||||
|
final int _damage;
|
||||||
|
|
||||||
|
WeaponObjectBuilder({
|
||||||
|
String name,
|
||||||
|
int damage,
|
||||||
|
})
|
||||||
|
: _name = name,
|
||||||
|
_damage = damage;
|
||||||
|
|
||||||
|
/// Finish building, and store into the [fbBuilder].
|
||||||
|
@override
|
||||||
|
int finish(
|
||||||
|
fb.Builder fbBuilder) {
|
||||||
|
assert(fbBuilder != null);
|
||||||
|
final int nameOffset = fbBuilder.writeString(_name);
|
||||||
|
|
||||||
|
fbBuilder.startTable();
|
||||||
|
if (nameOffset != null) {
|
||||||
|
fbBuilder.addOffset(0, nameOffset);
|
||||||
|
}
|
||||||
|
fbBuilder.addInt16(1, _damage);
|
||||||
|
return fbBuilder.endTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convenience method to serialize to byte list.
|
||||||
|
@override
|
||||||
|
Uint8List toBytes([String fileIdentifier]) {
|
||||||
|
fb.Builder fbBuilder = new fb.Builder();
|
||||||
|
int offset = finish(fbBuilder);
|
||||||
|
return fbBuilder.finish(offset, fileIdentifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
1241
dart/lib/flat_buffers.dart
Normal file
1241
dart/lib/flat_buffers.dart
Normal file
File diff suppressed because it is too large
Load Diff
20
tests/fuzzer/build_fuzzer.sh → dart/publish.sh
Normal file → Executable file
20
tests/fuzzer/build_fuzzer.sh → dart/publish.sh
Normal file → Executable file
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/sh
|
||||||
#
|
#
|
||||||
# Copyright 2015 Google Inc. All rights reserved.
|
# Copyright 2018 Google Inc. All rights reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
@@ -13,8 +13,16 @@
|
|||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# 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.
|
||||||
|
#
|
||||||
|
# Note to pub consumers: this file is used to assist with publishing the
|
||||||
|
# pub package from the flatbuffers repository and is not meant for general use.
|
||||||
|
# As pub does not currently provide a way to exclude files, it is included here.
|
||||||
|
|
||||||
git clone https://chromium.googlesource.com/chromium/llvm-project/llvm/lib/Fuzzer
|
command -v pub >/dev/null 2>&1 || { echo >&2 "Require `pub` but it's not installed. Aborting."; exit 1; }
|
||||||
clang++ -c -g -O2 -std=c++11 Fuzzer/*.cpp -IFuzzer
|
|
||||||
ar ruv libFuzzer.a Fuzzer*.o
|
cp ../samples/monster.fbs example/
|
||||||
rm -rf Fuzzer *.o
|
cp ../tests/monster_test.fbs test/
|
||||||
|
pub publish
|
||||||
|
|
||||||
|
rm example/monster.fbs
|
||||||
|
rm test/monster_test.fbs
|
||||||
20
dart/pubspec.yaml
Normal file
20
dart/pubspec.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
name: flat_buffers
|
||||||
|
version: 1.11.0
|
||||||
|
description: >
|
||||||
|
FlatBuffers reading and writing library for Dart. Use the flatc compiler to
|
||||||
|
generate Dart classes for a FlatBuffers schema, and this library to assist with
|
||||||
|
reading and writing the binary format.
|
||||||
|
|
||||||
|
Based on original work by Konstantin Scheglov and Paul Berry of the Dart SDK team.
|
||||||
|
authors:
|
||||||
|
- Dan Field <dfield@gmail.com>
|
||||||
|
- Konstantin Scheglov
|
||||||
|
- Paul Berry
|
||||||
|
homepage: https://github.com/google/flatbuffers
|
||||||
|
documentation: https://google.github.io/flatbuffers/index.html
|
||||||
|
dev_dependencies:
|
||||||
|
test: ^1.3.0
|
||||||
|
test_reflective_loader: ^0.1.4
|
||||||
|
path: ^1.5.1
|
||||||
|
environment:
|
||||||
|
sdk: '>=2.0.0-dev.28.0 <3.0.0'
|
||||||
573
dart/test/flat_buffers_test.dart
Normal file
573
dart/test/flat_buffers_test.dart
Normal file
@@ -0,0 +1,573 @@
|
|||||||
|
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
import 'dart:typed_data';
|
||||||
|
import 'dart:io' as io;
|
||||||
|
|
||||||
|
import 'package:path/path.dart' as path;
|
||||||
|
|
||||||
|
import 'package:flat_buffers/flat_buffers.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||||
|
|
||||||
|
import './monster_test_my_game.example_generated.dart' as example;
|
||||||
|
|
||||||
|
main() {
|
||||||
|
defineReflectiveSuite(() {
|
||||||
|
defineReflectiveTests(BuilderTest);
|
||||||
|
defineReflectiveTests(CheckOtherLangaugesData);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
int indexToField(int index) {
|
||||||
|
return (1 + 1 + index) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@reflectiveTest
|
||||||
|
class CheckOtherLangaugesData {
|
||||||
|
test_cppData() async {
|
||||||
|
List<int> data = await new io.File(path.join(
|
||||||
|
path.dirname(io.Platform.script.path),
|
||||||
|
'monsterdata_test.mon',
|
||||||
|
))
|
||||||
|
.readAsBytes();
|
||||||
|
example.Monster mon = new example.Monster(data);
|
||||||
|
expect(mon.hp, 80);
|
||||||
|
expect(mon.mana, 150);
|
||||||
|
expect(mon.name, 'MyMonster');
|
||||||
|
expect(mon.pos.x, 1.0);
|
||||||
|
expect(mon.pos.y, 2.0);
|
||||||
|
expect(mon.pos.z, 3.0);
|
||||||
|
expect(mon.pos.test1, 3.0);
|
||||||
|
expect(mon.pos.test2.value, 2.0);
|
||||||
|
expect(mon.pos.test3.a, 5);
|
||||||
|
expect(mon.pos.test3.b, 6);
|
||||||
|
expect(mon.testType.value, example.AnyTypeId.Monster.value);
|
||||||
|
expect(mon.test is example.Monster, true);
|
||||||
|
final monster2 = mon.test as example.Monster;
|
||||||
|
expect(monster2.name, "Fred");
|
||||||
|
|
||||||
|
expect(mon.inventory.length, 5);
|
||||||
|
expect(mon.inventory.reduce((cur, next) => cur + next), 10);
|
||||||
|
expect(mon.test4.length, 2);
|
||||||
|
expect(
|
||||||
|
mon.test4[0].a + mon.test4[0].b + mon.test4[1].a + mon.test4[1].b, 100);
|
||||||
|
expect(mon.testarrayofstring.length, 2);
|
||||||
|
expect(mon.testarrayofstring[0], "test1");
|
||||||
|
expect(mon.testarrayofstring[1], "test2");
|
||||||
|
|
||||||
|
// this will fail if accessing any field fails.
|
||||||
|
expect(mon.toString(),
|
||||||
|
'Monster{pos: Vec3{x: 1.0, y: 2.0, z: 3.0, test1: 3.0, test2: Color{value: 2}, test3: Test{a: 5, b: 6}}, mana: 150, hp: 80, name: MyMonster, inventory: [0, 1, 2, 3, 4], color: Color{value: 8}, testType: AnyTypeId{value: 1}, test: Monster{pos: null, mana: 150, hp: 100, name: Fred, inventory: null, color: Color{value: 8}, testType: AnyTypeId{value: 0}, test: null, test4: null, testarrayofstring: null, testarrayoftables: null, enemy: null, testnestedflatbuffer: null, testempty: null, testbool: false, testhashs32Fnv1: 0, testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, testf2: 3.0, testf3: 0.0, testarrayofstring2: null, testarrayofsortedstruct: null, flex: null, test5: null, vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, vectorOfReferrables: null, singleWeakReference: 0, vectorOfWeakReferences: null, vectorOfStrongReferrables: null, coOwningReference: 0, vectorOfCoOwningReferences: null, nonOwningReference: 0, vectorOfNonOwningReferences: null}, test4: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], testarrayofstring: [test1, test2], testarrayoftables: null, enemy: Monster{pos: null, mana: 150, hp: 100, name: Fred, inventory: null, color: Color{value: 8}, testType: AnyTypeId{value: 0}, test: null, test4: null, testarrayofstring: null, testarrayoftables: null, enemy: null, testnestedflatbuffer: null, testempty: null, testbool: false, testhashs32Fnv1: 0, testhashu32Fnv1: 0, testhashs64Fnv1: 0, testhashu64Fnv1: 0, testhashs32Fnv1a: 0, testhashu32Fnv1a: 0, testhashs64Fnv1a: 0, testhashu64Fnv1a: 0, testarrayofbools: null, testf: 3.14159, testf2: 3.0, testf3: 0.0, testarrayofstring2: null, testarrayofsortedstruct: null, flex: null, test5: null, vectorOfLongs: null, vectorOfDoubles: null, parentNamespaceTest: null, vectorOfReferrables: null, singleWeakReference: 0, vectorOfWeakReferences: null, vectorOfStrongReferrables: null, coOwningReference: 0, vectorOfCoOwningReferences: null, nonOwningReference: 0, vectorOfNonOwningReferences: null}, testnestedflatbuffer: null, testempty: null, testbool: false, testhashs32Fnv1: -579221183, testhashu32Fnv1: 3715746113, testhashs64Fnv1: 7930699090847568257, testhashu64Fnv1: 7930699090847568257, testhashs32Fnv1a: -1904106383, testhashu32Fnv1a: 2390860913, testhashs64Fnv1a: 4898026182817603057, testhashu64Fnv1a: 4898026182817603057, testarrayofbools: [true, false, true], testf: 3.14159, testf2: 3.0, testf3: 0.0, testarrayofstring2: null, testarrayofsortedstruct: null, flex: null, test5: [Test{a: 10, b: 20}, Test{a: 30, b: 40}], vectorOfLongs: [1, 100, 10000, 1000000, 100000000], vectorOfDoubles: [-1.7976931348623157e+308, 0.0, 1.7976931348623157e+308], parentNamespaceTest: null, vectorOfReferrables: null, singleWeakReference: 0, vectorOfWeakReferences: null, vectorOfStrongReferrables: null, coOwningReference: 0, vectorOfCoOwningReferences: null, nonOwningReference: 0, vectorOfNonOwningReferences: null}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@reflectiveTest
|
||||||
|
class BuilderTest {
|
||||||
|
void test_monsterBuilder() {
|
||||||
|
final fbBuilder = new Builder();
|
||||||
|
final str = fbBuilder.writeString('MyMonster');
|
||||||
|
|
||||||
|
fbBuilder.writeString('test1');
|
||||||
|
fbBuilder.writeString('test2');
|
||||||
|
final testArrayOfString = fbBuilder.endStructVector(2);
|
||||||
|
|
||||||
|
final fred = fbBuilder.writeString('Fred');
|
||||||
|
|
||||||
|
final List<int> treasure = [0, 1, 2, 3, 4];
|
||||||
|
final inventory = fbBuilder.writeListUint8(treasure);
|
||||||
|
|
||||||
|
final monBuilder = new example.MonsterBuilder(fbBuilder)
|
||||||
|
..begin()
|
||||||
|
..addNameOffset(fred);
|
||||||
|
final mon2 = monBuilder.finish();
|
||||||
|
|
||||||
|
final testBuilder = new example.TestBuilder(fbBuilder);
|
||||||
|
testBuilder.finish(10, 20);
|
||||||
|
testBuilder.finish(30, 40);
|
||||||
|
final test4 = fbBuilder.endStructVector(2);
|
||||||
|
|
||||||
|
|
||||||
|
monBuilder
|
||||||
|
..begin()
|
||||||
|
..addPos(
|
||||||
|
new example.Vec3Builder(fbBuilder).finish(
|
||||||
|
1.0,
|
||||||
|
2.0,
|
||||||
|
3.0,
|
||||||
|
3.0,
|
||||||
|
example.Color.Green,
|
||||||
|
() => testBuilder.finish(5, 6),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
..addHp(80)
|
||||||
|
..addNameOffset(str)
|
||||||
|
..addInventoryOffset(inventory)
|
||||||
|
..addTestType(example.AnyTypeId.Monster)
|
||||||
|
..addTestOffset(mon2)
|
||||||
|
..addTest4Offset(test4)
|
||||||
|
..addTestarrayofstringOffset(testArrayOfString);
|
||||||
|
final mon = monBuilder.finish();
|
||||||
|
fbBuilder.finish(mon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_error_addInt32_withoutStartTable() {
|
||||||
|
Builder builder = new Builder();
|
||||||
|
expect(() {
|
||||||
|
builder.addInt32(0, 0);
|
||||||
|
}, throwsStateError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_error_addOffset_withoutStartTable() {
|
||||||
|
Builder builder = new Builder();
|
||||||
|
expect(() {
|
||||||
|
builder.addOffset(0, 0);
|
||||||
|
}, throwsStateError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_error_endTable_withoutStartTable() {
|
||||||
|
Builder builder = new Builder();
|
||||||
|
expect(() {
|
||||||
|
builder.endTable();
|
||||||
|
}, throwsStateError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_error_startTable_duringTable() {
|
||||||
|
Builder builder = new Builder();
|
||||||
|
builder.startTable();
|
||||||
|
expect(() {
|
||||||
|
builder.startTable();
|
||||||
|
}, throwsStateError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_error_writeString_duringTable() {
|
||||||
|
Builder builder = new Builder();
|
||||||
|
builder.startTable();
|
||||||
|
expect(() {
|
||||||
|
builder.writeString('12345');
|
||||||
|
}, throwsStateError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_file_identifier() {
|
||||||
|
Uint8List byteList;
|
||||||
|
{
|
||||||
|
Builder builder = new Builder(initialSize: 0);
|
||||||
|
builder.startTable();
|
||||||
|
int offset = builder.endTable();
|
||||||
|
byteList = builder.finish(offset, 'Az~ÿ');
|
||||||
|
}
|
||||||
|
// Convert byteList to a ByteData so that we can read data from it.
|
||||||
|
ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes);
|
||||||
|
// First 4 bytes are an offset to the table data.
|
||||||
|
int tableDataLoc = byteData.getUint32(0, Endian.little);
|
||||||
|
// Next 4 bytes are the file identifier.
|
||||||
|
expect(byteData.getUint8(4), 65); // 'a'
|
||||||
|
expect(byteData.getUint8(5), 122); // 'z'
|
||||||
|
expect(byteData.getUint8(6), 126); // '~'
|
||||||
|
expect(byteData.getUint8(7), 255); // 'ÿ'
|
||||||
|
// First 4 bytes of the table data are a backwards offset to the vtable.
|
||||||
|
int vTableLoc = tableDataLoc -
|
||||||
|
byteData.getInt32(tableDataLoc, Endian.little);
|
||||||
|
// First 2 bytes of the vtable are the size of the vtable in bytes, which
|
||||||
|
// should be 4.
|
||||||
|
expect(byteData.getUint16(vTableLoc, Endian.little), 4);
|
||||||
|
// Next 2 bytes are the size of the object in bytes (including the vtable
|
||||||
|
// pointer), which should be 4.
|
||||||
|
expect(byteData.getUint16(vTableLoc + 2, Endian.little), 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_low() {
|
||||||
|
Builder builder = new Builder(initialSize: 0);
|
||||||
|
expect((builder..putUint8(1)).lowFinish(), [1]);
|
||||||
|
expect((builder..putUint32(2)).lowFinish(), [2, 0, 0, 0, 0, 0, 0, 1]);
|
||||||
|
expect((builder..putUint8(3)).lowFinish(),
|
||||||
|
[0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
|
||||||
|
expect((builder..putUint8(4)).lowFinish(),
|
||||||
|
[0, 0, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
|
||||||
|
expect((builder..putUint8(5)).lowFinish(),
|
||||||
|
[0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
|
||||||
|
expect((builder..putUint32(6)).lowFinish(),
|
||||||
|
[6, 0, 0, 0, 0, 5, 4, 3, 2, 0, 0, 0, 0, 0, 0, 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_table_default() {
|
||||||
|
List<int> byteList;
|
||||||
|
{
|
||||||
|
Builder builder = new Builder(initialSize: 0);
|
||||||
|
builder.startTable();
|
||||||
|
builder.addInt32(0, 10, 10);
|
||||||
|
builder.addInt32(1, 20, 10);
|
||||||
|
int offset = builder.endTable();
|
||||||
|
byteList = builder.finish(offset);
|
||||||
|
}
|
||||||
|
// read and verify
|
||||||
|
BufferContext buffer = new BufferContext.fromBytes(byteList);
|
||||||
|
int objectOffset = buffer.derefObject(0);
|
||||||
|
// was not written, so uses the new default value
|
||||||
|
expect(
|
||||||
|
const Int32Reader()
|
||||||
|
.vTableGet(buffer, objectOffset, indexToField(0), 15),
|
||||||
|
15);
|
||||||
|
// has the written value
|
||||||
|
expect(
|
||||||
|
const Int32Reader()
|
||||||
|
.vTableGet(buffer, objectOffset, indexToField(1), 15),
|
||||||
|
20);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_table_format() {
|
||||||
|
Uint8List byteList;
|
||||||
|
{
|
||||||
|
Builder builder = new Builder(initialSize: 0);
|
||||||
|
builder.startTable();
|
||||||
|
builder.addInt32(0, 10);
|
||||||
|
builder.addInt32(1, 20);
|
||||||
|
builder.addInt32(2, 30);
|
||||||
|
byteList = builder.finish(builder.endTable());
|
||||||
|
}
|
||||||
|
// Convert byteList to a ByteData so that we can read data from it.
|
||||||
|
ByteData byteData = byteList.buffer.asByteData(byteList.offsetInBytes);
|
||||||
|
// First 4 bytes are an offset to the table data.
|
||||||
|
int tableDataLoc = byteData.getUint32(0, Endian.little);
|
||||||
|
// First 4 bytes of the table data are a backwards offset to the vtable.
|
||||||
|
int vTableLoc = tableDataLoc -
|
||||||
|
byteData.getInt32(tableDataLoc, Endian.little);
|
||||||
|
// First 2 bytes of the vtable are the size of the vtable in bytes, which
|
||||||
|
// should be 10.
|
||||||
|
expect(byteData.getUint16(vTableLoc, Endian.little), 10);
|
||||||
|
// Next 2 bytes are the size of the object in bytes (including the vtable
|
||||||
|
// pointer), which should be 16.
|
||||||
|
expect(byteData.getUint16(vTableLoc + 2, Endian.little), 16);
|
||||||
|
// Remaining 6 bytes are the offsets within the object where the ints are
|
||||||
|
// located.
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
int offset =
|
||||||
|
byteData.getUint16(vTableLoc + 4 + 2 * i, Endian.little);
|
||||||
|
expect(byteData.getInt32(tableDataLoc + offset, Endian.little),
|
||||||
|
10 + 10 * i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_table_string() {
|
||||||
|
String latinString = 'test';
|
||||||
|
String unicodeString = 'Проба пера';
|
||||||
|
List<int> byteList;
|
||||||
|
{
|
||||||
|
Builder builder = new Builder(initialSize: 0);
|
||||||
|
int latinStringOffset = builder.writeString(latinString);
|
||||||
|
int unicodeStringOffset = builder.writeString(unicodeString);
|
||||||
|
builder.startTable();
|
||||||
|
builder.addOffset(0, latinStringOffset);
|
||||||
|
builder.addOffset(1, unicodeStringOffset);
|
||||||
|
int offset = builder.endTable();
|
||||||
|
byteList = builder.finish(offset);
|
||||||
|
}
|
||||||
|
// read and verify
|
||||||
|
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||||
|
int objectOffset = buf.derefObject(0);
|
||||||
|
expect(const StringReader().vTableGet(buf, objectOffset, indexToField(0)),
|
||||||
|
latinString);
|
||||||
|
expect(const StringReader().vTableGet(buf, objectOffset, indexToField(1)),
|
||||||
|
unicodeString);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_table_types() {
|
||||||
|
List<int> byteList;
|
||||||
|
{
|
||||||
|
Builder builder = new Builder(initialSize: 0);
|
||||||
|
int stringOffset = builder.writeString('12345');
|
||||||
|
builder.startTable();
|
||||||
|
builder.addBool(0, true);
|
||||||
|
builder.addInt8(1, 10);
|
||||||
|
builder.addInt32(2, 20);
|
||||||
|
builder.addOffset(3, stringOffset);
|
||||||
|
builder.addInt32(4, 40);
|
||||||
|
builder.addUint32(5, 0x9ABCDEF0);
|
||||||
|
builder.addUint8(6, 0x9A);
|
||||||
|
int offset = builder.endTable();
|
||||||
|
byteList = builder.finish(offset);
|
||||||
|
}
|
||||||
|
// read and verify
|
||||||
|
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||||
|
int objectOffset = buf.derefObject(0);
|
||||||
|
expect(
|
||||||
|
const BoolReader().vTableGet(buf, objectOffset, indexToField(0)), true);
|
||||||
|
expect(
|
||||||
|
const Int8Reader().vTableGet(buf, objectOffset, indexToField(1)), 10);
|
||||||
|
expect(
|
||||||
|
const Int32Reader().vTableGet(buf, objectOffset, indexToField(2)), 20);
|
||||||
|
expect(const StringReader().vTableGet(buf, objectOffset, indexToField(3)),
|
||||||
|
'12345');
|
||||||
|
expect(
|
||||||
|
const Int32Reader().vTableGet(buf, objectOffset, indexToField(4)), 40);
|
||||||
|
expect(const Uint32Reader().vTableGet(buf, objectOffset, indexToField(5)),
|
||||||
|
0x9ABCDEF0);
|
||||||
|
expect(const Uint8Reader().vTableGet(buf, objectOffset, indexToField(6)),
|
||||||
|
0x9A);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_writeList_of_Uint32() {
|
||||||
|
List<int> values = <int>[10, 100, 12345, 0x9abcdef0];
|
||||||
|
// write
|
||||||
|
List<int> byteList;
|
||||||
|
{
|
||||||
|
Builder builder = new Builder(initialSize: 0);
|
||||||
|
int offset = builder.writeListUint32(values);
|
||||||
|
byteList = builder.finish(offset);
|
||||||
|
}
|
||||||
|
// read and verify
|
||||||
|
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||||
|
List<int> items = const Uint32ListReader().read(buf, 0);
|
||||||
|
expect(items, hasLength(4));
|
||||||
|
expect(items, orderedEquals(values));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_writeList_ofBool() {
|
||||||
|
void verifyListBooleans(int len, List<int> trueBits) {
|
||||||
|
// write
|
||||||
|
List<int> byteList;
|
||||||
|
{
|
||||||
|
Builder builder = new Builder(initialSize: 0);
|
||||||
|
List<bool> values = new List<bool>.filled(len, false);
|
||||||
|
for (int bit in trueBits) {
|
||||||
|
values[bit] = true;
|
||||||
|
}
|
||||||
|
int offset = builder.writeListBool(values);
|
||||||
|
byteList = builder.finish(offset);
|
||||||
|
}
|
||||||
|
// read and verify
|
||||||
|
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||||
|
List<bool> items = const BoolListReader().read(buf, 0);
|
||||||
|
expect(items, hasLength(len));
|
||||||
|
for (int i = 0; i < items.length; i++) {
|
||||||
|
expect(items[i], trueBits.contains(i), reason: 'bit $i of $len');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyListBooleans(0, <int>[]);
|
||||||
|
verifyListBooleans(1, <int>[]);
|
||||||
|
verifyListBooleans(1, <int>[0]);
|
||||||
|
verifyListBooleans(31, <int>[0, 1]);
|
||||||
|
verifyListBooleans(31, <int>[1, 2, 24, 25, 30]);
|
||||||
|
verifyListBooleans(31, <int>[0, 30]);
|
||||||
|
verifyListBooleans(32, <int>[1, 2, 24, 25, 31]);
|
||||||
|
verifyListBooleans(33, <int>[1, 2, 24, 25, 32]);
|
||||||
|
verifyListBooleans(33, <int>[1, 2, 24, 25, 31, 32]);
|
||||||
|
verifyListBooleans(63, <int>[]);
|
||||||
|
verifyListBooleans(63, <int>[0, 1, 2, 61, 62]);
|
||||||
|
verifyListBooleans(63, new List<int>.generate(63, (i) => i));
|
||||||
|
verifyListBooleans(64, <int>[]);
|
||||||
|
verifyListBooleans(64, <int>[0, 1, 2, 61, 62, 63]);
|
||||||
|
verifyListBooleans(64, <int>[1, 2, 62]);
|
||||||
|
verifyListBooleans(64, <int>[0, 1, 2, 63]);
|
||||||
|
verifyListBooleans(64, new List<int>.generate(64, (i) => i));
|
||||||
|
verifyListBooleans(100, <int>[0, 3, 30, 60, 90, 99]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_writeList_ofInt32() {
|
||||||
|
List<int> byteList;
|
||||||
|
{
|
||||||
|
Builder builder = new Builder(initialSize: 0);
|
||||||
|
int offset = builder.writeListInt32(<int>[1, 2, 3, 4, 5]);
|
||||||
|
byteList = builder.finish(offset);
|
||||||
|
}
|
||||||
|
// read and verify
|
||||||
|
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||||
|
List<int> items = const ListReader<int>(const Int32Reader()).read(buf, 0);
|
||||||
|
expect(items, hasLength(5));
|
||||||
|
expect(items, orderedEquals(<int>[1, 2, 3, 4, 5]));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_writeList_ofFloat64() {
|
||||||
|
List<double> values = <double>[-1.234567, 3.4E+9, -5.6E-13, 7.8, 12.13];
|
||||||
|
// write
|
||||||
|
List<int> byteList;
|
||||||
|
{
|
||||||
|
Builder builder = new Builder(initialSize: 0);
|
||||||
|
int offset = builder.writeListFloat64(values);
|
||||||
|
byteList = builder.finish(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read and verify
|
||||||
|
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||||
|
List<double> items = const Float64ListReader().read(buf, 0);
|
||||||
|
|
||||||
|
expect(items, hasLength(values.length));
|
||||||
|
for (int i = 0; i < values.length; i++) {
|
||||||
|
expect(values[i], closeTo(items[i], .001));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_writeList_ofFloat32() {
|
||||||
|
List<double> values = [1.0, 2.23, -3.213, 7.8, 12.13];
|
||||||
|
// write
|
||||||
|
List<int> byteList;
|
||||||
|
{
|
||||||
|
Builder builder = new Builder(initialSize: 0);
|
||||||
|
int offset = builder.writeListFloat32(values);
|
||||||
|
byteList = builder.finish(offset);
|
||||||
|
}
|
||||||
|
// read and verify
|
||||||
|
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||||
|
List<double> items = const Float32ListReader().read(buf, 0);
|
||||||
|
expect(items, hasLength(5));
|
||||||
|
for (int i = 0; i < values.length; i++) {
|
||||||
|
expect(values[i], closeTo(items[i], .001));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_writeList_ofObjects() {
|
||||||
|
List<int> byteList;
|
||||||
|
{
|
||||||
|
Builder builder = new Builder(initialSize: 0);
|
||||||
|
// write the object #1
|
||||||
|
int object1;
|
||||||
|
{
|
||||||
|
builder.startTable();
|
||||||
|
builder.addInt32(0, 10);
|
||||||
|
builder.addInt32(1, 20);
|
||||||
|
object1 = builder.endTable();
|
||||||
|
}
|
||||||
|
// write the object #1
|
||||||
|
int object2;
|
||||||
|
{
|
||||||
|
builder.startTable();
|
||||||
|
builder.addInt32(0, 100);
|
||||||
|
builder.addInt32(1, 200);
|
||||||
|
object2 = builder.endTable();
|
||||||
|
}
|
||||||
|
// write the list
|
||||||
|
int offset = builder.writeList([object1, object2]);
|
||||||
|
byteList = builder.finish(offset);
|
||||||
|
}
|
||||||
|
// read and verify
|
||||||
|
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||||
|
List<TestPointImpl> items =
|
||||||
|
const ListReader<TestPointImpl>(const TestPointReader()).read(buf, 0);
|
||||||
|
expect(items, hasLength(2));
|
||||||
|
expect(items[0].x, 10);
|
||||||
|
expect(items[0].y, 20);
|
||||||
|
expect(items[1].x, 100);
|
||||||
|
expect(items[1].y, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_writeList_ofStrings_asRoot() {
|
||||||
|
List<int> byteList;
|
||||||
|
{
|
||||||
|
Builder builder = new Builder(initialSize: 0);
|
||||||
|
int str1 = builder.writeString('12345');
|
||||||
|
int str2 = builder.writeString('ABC');
|
||||||
|
int offset = builder.writeList([str1, str2]);
|
||||||
|
byteList = builder.finish(offset);
|
||||||
|
}
|
||||||
|
// read and verify
|
||||||
|
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||||
|
List<String> items =
|
||||||
|
const ListReader<String>(const StringReader()).read(buf, 0);
|
||||||
|
expect(items, hasLength(2));
|
||||||
|
expect(items, contains('12345'));
|
||||||
|
expect(items, contains('ABC'));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_writeList_ofStrings_inObject() {
|
||||||
|
List<int> byteList;
|
||||||
|
{
|
||||||
|
Builder builder = new Builder(initialSize: 0);
|
||||||
|
int listOffset = builder.writeList(
|
||||||
|
[builder.writeString('12345'), builder.writeString('ABC')]);
|
||||||
|
builder.startTable();
|
||||||
|
builder.addOffset(0, listOffset);
|
||||||
|
int offset = builder.endTable();
|
||||||
|
byteList = builder.finish(offset);
|
||||||
|
}
|
||||||
|
// read and verify
|
||||||
|
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||||
|
StringListWrapperImpl reader = new StringListWrapperReader().read(buf, 0);
|
||||||
|
List<String> items = reader.items;
|
||||||
|
expect(items, hasLength(2));
|
||||||
|
expect(items, contains('12345'));
|
||||||
|
expect(items, contains('ABC'));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_writeList_ofUint32() {
|
||||||
|
List<int> byteList;
|
||||||
|
{
|
||||||
|
Builder builder = new Builder(initialSize: 0);
|
||||||
|
int offset = builder.writeListUint32(<int>[1, 2, 0x9ABCDEF0]);
|
||||||
|
byteList = builder.finish(offset);
|
||||||
|
}
|
||||||
|
// read and verify
|
||||||
|
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||||
|
List<int> items = const Uint32ListReader().read(buf, 0);
|
||||||
|
expect(items, hasLength(3));
|
||||||
|
expect(items, orderedEquals(<int>[1, 2, 0x9ABCDEF0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_writeList_ofUint16() {
|
||||||
|
List<int> byteList;
|
||||||
|
{
|
||||||
|
Builder builder = new Builder(initialSize: 0);
|
||||||
|
int offset = builder.writeListUint16(<int>[1, 2, 60000]);
|
||||||
|
byteList = builder.finish(offset);
|
||||||
|
}
|
||||||
|
// read and verify
|
||||||
|
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||||
|
List<int> items = const Uint16ListReader().read(buf, 0);
|
||||||
|
expect(items, hasLength(3));
|
||||||
|
expect(items, orderedEquals(<int>[1, 2, 60000]));
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_writeList_ofUint8() {
|
||||||
|
List<int> byteList;
|
||||||
|
{
|
||||||
|
Builder builder = new Builder(initialSize: 0);
|
||||||
|
int offset = builder.writeListUint8(<int>[1, 2, 3, 4, 0x9A]);
|
||||||
|
byteList = builder.finish(offset);
|
||||||
|
}
|
||||||
|
// read and verify
|
||||||
|
BufferContext buf = new BufferContext.fromBytes(byteList);
|
||||||
|
List<int> items = const Uint8ListReader().read(buf, 0);
|
||||||
|
expect(items, hasLength(5));
|
||||||
|
expect(items, orderedEquals(<int>[1, 2, 3, 4, 0x9A]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class StringListWrapperImpl {
|
||||||
|
final BufferContext bp;
|
||||||
|
final int offset;
|
||||||
|
|
||||||
|
StringListWrapperImpl(this.bp, this.offset);
|
||||||
|
|
||||||
|
List<String> get items => const ListReader<String>(const StringReader())
|
||||||
|
.vTableGet(bp, offset, indexToField(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
class StringListWrapperReader extends TableReader<StringListWrapperImpl> {
|
||||||
|
const StringListWrapperReader();
|
||||||
|
|
||||||
|
@override
|
||||||
|
StringListWrapperImpl createObject(BufferContext object, int offset) {
|
||||||
|
return new StringListWrapperImpl(object, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestPointImpl {
|
||||||
|
final BufferContext bp;
|
||||||
|
final int offset;
|
||||||
|
|
||||||
|
TestPointImpl(this.bp, this.offset);
|
||||||
|
|
||||||
|
int get x => const Int32Reader().vTableGet(bp, offset, indexToField(0), 0);
|
||||||
|
|
||||||
|
int get y => const Int32Reader().vTableGet(bp, offset, indexToField(1), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestPointReader extends TableReader<TestPointImpl> {
|
||||||
|
const TestPointReader();
|
||||||
|
|
||||||
|
@override
|
||||||
|
TestPointImpl createObject(BufferContext object, int offset) {
|
||||||
|
return new TestPointImpl(object, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
62
dart/test/monster_test_my_game.example2_generated.dart
Normal file
62
dart/test/monster_test_my_game.example2_generated.dart
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
// ignore_for_file: unused_import, unused_field, unused_local_variable
|
||||||
|
|
||||||
|
library my_game.example2;
|
||||||
|
|
||||||
|
import 'dart:typed_data' show Uint8List;
|
||||||
|
import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||||
|
|
||||||
|
import 'include_test1_my_game.example2_generated.dart';
|
||||||
|
import 'include_test2_my_game.example2_generated.dart';
|
||||||
|
import './monster_test_my_game_generated.dart' as my_game;
|
||||||
|
import './monster_test_my_game.example_generated.dart' as my_game_example;
|
||||||
|
|
||||||
|
class Monster {
|
||||||
|
Monster._(this._bc, this._bcOffset);
|
||||||
|
factory Monster(List<int> bytes) {
|
||||||
|
fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes);
|
||||||
|
return reader.read(rootRef, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const fb.Reader<Monster> reader = const _MonsterReader();
|
||||||
|
|
||||||
|
final fb.BufferContext _bc;
|
||||||
|
final int _bcOffset;
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'Monster{}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MonsterReader extends fb.TableReader<Monster> {
|
||||||
|
const _MonsterReader();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Monster createObject(fb.BufferContext bc, int offset) =>
|
||||||
|
new Monster._(bc, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||||
|
|
||||||
|
MonsterObjectBuilder();
|
||||||
|
|
||||||
|
/// Finish building, and store into the [fbBuilder].
|
||||||
|
@override
|
||||||
|
int finish(
|
||||||
|
fb.Builder fbBuilder) {
|
||||||
|
assert(fbBuilder != null);
|
||||||
|
|
||||||
|
fbBuilder.startTable();
|
||||||
|
return fbBuilder.endTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convenience method to serialize to byte list.
|
||||||
|
@override
|
||||||
|
Uint8List toBytes([String fileIdentifier]) {
|
||||||
|
fb.Builder fbBuilder = new fb.Builder();
|
||||||
|
int offset = finish(fbBuilder);
|
||||||
|
return fbBuilder.finish(offset, fileIdentifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
1486
dart/test/monster_test_my_game.example_generated.dart
Normal file
1486
dart/test/monster_test_my_game.example_generated.dart
Normal file
File diff suppressed because it is too large
Load Diff
62
dart/test/monster_test_my_game_generated.dart
Normal file
62
dart/test/monster_test_my_game_generated.dart
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
// automatically generated by the FlatBuffers compiler, do not modify
|
||||||
|
// ignore_for_file: unused_import, unused_field, unused_local_variable
|
||||||
|
|
||||||
|
library my_game;
|
||||||
|
|
||||||
|
import 'dart:typed_data' show Uint8List;
|
||||||
|
import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||||
|
|
||||||
|
import 'include_test1_my_game_generated.dart';
|
||||||
|
import 'include_test2_my_game_generated.dart';
|
||||||
|
import './monster_test_my_game.example_generated.dart' as my_game_example;
|
||||||
|
import './monster_test_my_game.example2_generated.dart' as my_game_example2;
|
||||||
|
|
||||||
|
class InParentNamespace {
|
||||||
|
InParentNamespace._(this._bc, this._bcOffset);
|
||||||
|
factory InParentNamespace(List<int> bytes) {
|
||||||
|
fb.BufferContext rootRef = new fb.BufferContext.fromBytes(bytes);
|
||||||
|
return reader.read(rootRef, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const fb.Reader<InParentNamespace> reader = const _InParentNamespaceReader();
|
||||||
|
|
||||||
|
final fb.BufferContext _bc;
|
||||||
|
final int _bcOffset;
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'InParentNamespace{}';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _InParentNamespaceReader extends fb.TableReader<InParentNamespace> {
|
||||||
|
const _InParentNamespaceReader();
|
||||||
|
|
||||||
|
@override
|
||||||
|
InParentNamespace createObject(fb.BufferContext bc, int offset) =>
|
||||||
|
new InParentNamespace._(bc, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
class InParentNamespaceObjectBuilder extends fb.ObjectBuilder {
|
||||||
|
|
||||||
|
InParentNamespaceObjectBuilder();
|
||||||
|
|
||||||
|
/// Finish building, and store into the [fbBuilder].
|
||||||
|
@override
|
||||||
|
int finish(
|
||||||
|
fb.Builder fbBuilder) {
|
||||||
|
assert(fbBuilder != null);
|
||||||
|
|
||||||
|
fbBuilder.startTable();
|
||||||
|
return fbBuilder.endTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convenience method to serialize to byte list.
|
||||||
|
@override
|
||||||
|
Uint8List toBytes([String fileIdentifier]) {
|
||||||
|
fb.Builder fbBuilder = new fb.Builder();
|
||||||
|
int offset = finish(fbBuilder);
|
||||||
|
return fbBuilder.finish(offset, fileIdentifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,9 +8,9 @@ you to build project/make files for any platform. For details on `cmake`, see
|
|||||||
<https://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" -DCMAKE_BUILD_TYPE=Release
|
||||||
cmake -G "Visual Studio 10"
|
cmake -G "Visual Studio 10" -DCMAKE_BUILD_TYPE=Release
|
||||||
cmake -G "Xcode"
|
cmake -G "Xcode" -DCMAKE_BUILD_TYPE=Release
|
||||||
|
|
||||||
Then, build as normal for your platform. This should result in a `flatc`
|
Then, build as normal for your platform. This should result in a `flatc`
|
||||||
executable, essential for the next steps.
|
executable, essential for the next steps.
|
||||||
@@ -41,7 +41,7 @@ running the `android_sample.sh` script. Optionally, you may go to the
|
|||||||
`flatbuffers/samples/android` folder and build the sample with the
|
`flatbuffers/samples/android` folder and build the sample with the
|
||||||
`build_apk.sh` script or `ndk_build` / `adb` etc.
|
`build_apk.sh` script or `ndk_build` / `adb` etc.
|
||||||
|
|
||||||
## Using FlatBuffers in your own projects.
|
## Using FlatBuffers in your own projects
|
||||||
|
|
||||||
For C++, there is usually no runtime to compile, as the code consists of a
|
For C++, there is usually no runtime to compile, as the code consists of a
|
||||||
single header, `include/flatbuffers/flatbuffers.h`. You should add the
|
single header, `include/flatbuffers/flatbuffers.h`. You should add the
|
||||||
@@ -55,6 +55,39 @@ To see how to include FlatBuffers in any of our supported languages, please
|
|||||||
view the [Tutorial](@ref flatbuffers_guide_tutorial) and select your appropriate
|
view the [Tutorial](@ref flatbuffers_guide_tutorial) and select your appropriate
|
||||||
language using the radio buttons.
|
language using the radio buttons.
|
||||||
|
|
||||||
|
### Using in CMake-based projects
|
||||||
|
If you want to use FlatBuffers in a project which already uses CMake, then a more
|
||||||
|
robust and flexible approach is to build FlatBuffers as part of that project directly.
|
||||||
|
This is done by making the FlatBuffers source code available to the main build
|
||||||
|
and adding it using CMake's `add_subdirectory()` command. This has the
|
||||||
|
significant advantage that the same compiler and linker settings are used
|
||||||
|
between FlatBuffers and the rest of your project, so issues associated with using
|
||||||
|
incompatible libraries (eg debug/release), etc. are avoided. This is
|
||||||
|
particularly useful on Windows.
|
||||||
|
|
||||||
|
Suppose you put FlatBuffers source code in directory `${FLATBUFFERS_SRC_DIR}`.
|
||||||
|
To build it as part of your project, add following code to your `CMakeLists.txt` file:
|
||||||
|
```cmake
|
||||||
|
# Add FlatBuffers directly to our build. This defines the `flatbuffers` target.
|
||||||
|
add_subdirectory(${FLATBUFFERS_SRC_DIR}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/flatbuffers-build
|
||||||
|
EXCLUDE_FROM_ALL)
|
||||||
|
|
||||||
|
# Now simply link against flatbuffers as needed to your already declared target.
|
||||||
|
# The flatbuffers target carry header search path automatically if CMake > 2.8.11.
|
||||||
|
target_link_libraries(own_project_target PRIVATE flatbuffers)
|
||||||
|
```
|
||||||
|
When build your project the `flatbuffers` library will be compiled and linked
|
||||||
|
to a target as part of your project.
|
||||||
|
|
||||||
|
#### Override default depth limit of nested objects
|
||||||
|
To override [the depth limit of recursion](@ref flatbuffers_guide_use_cpp),
|
||||||
|
add this directive:
|
||||||
|
```cmake
|
||||||
|
set(FLATBUFFERS_MAX_PARSING_DEPTH 16)
|
||||||
|
```
|
||||||
|
to `CMakeLists.txt` file before `add_subdirectory(${FLATBUFFERS_SRC_DIR})` line.
|
||||||
|
|
||||||
#### For Google Play apps
|
#### For Google Play apps
|
||||||
|
|
||||||
For applications on Google Play that integrate this library, usage is tracked.
|
For applications on Google Play that integrate this library, usage is tracked.
|
||||||
|
|||||||
@@ -31,10 +31,20 @@ For any schema input files, one or more generators can be specified:
|
|||||||
|
|
||||||
- `--js`, `-s`: Generate JavaScript code.
|
- `--js`, `-s`: Generate JavaScript code.
|
||||||
|
|
||||||
|
- `--ts`: Generate TypeScript code.
|
||||||
|
|
||||||
- `--php`: Generate PHP code.
|
- `--php`: Generate PHP code.
|
||||||
|
|
||||||
- `--grpc`: Generate RPC stub code for GRPC.
|
- `--grpc`: Generate RPC stub code for GRPC.
|
||||||
|
|
||||||
|
- `--dart`: Generate Dart code.
|
||||||
|
|
||||||
|
- `--lua`: Generate Lua code.
|
||||||
|
|
||||||
|
- `--lobster`: Generate Lobster code.
|
||||||
|
|
||||||
|
- `--rust`, `-r` : Generate Rust code.
|
||||||
|
|
||||||
For any data input files:
|
For any data input files:
|
||||||
|
|
||||||
- `--binary`, `-b` : If data is contained in this file, generate a
|
- `--binary`, `-b` : If data is contained in this file, generate a
|
||||||
@@ -62,6 +72,12 @@ Additional options:
|
|||||||
in quotes, no trailing commas in tables/vectors). By default, no quotes are
|
in quotes, no trailing commas in tables/vectors). By default, no quotes are
|
||||||
required/generated, and trailing commas are allowed.
|
required/generated, and trailing commas are allowed.
|
||||||
|
|
||||||
|
- `--allow-non-utf8` : Pass non-UTF-8 input through parser and emit nonstandard
|
||||||
|
\x escapes in JSON. (Default is to raise parse error on non-UTF-8 input.)
|
||||||
|
|
||||||
|
- `--natural-utf8` : Output strings with UTF-8 as human-readable strings.
|
||||||
|
By default, UTF-8 characters are printed as \uXXXX escapes."
|
||||||
|
|
||||||
- `--defaults-json` : Output fields whose value is equal to the default value
|
- `--defaults-json` : Output fields whose value is equal to the default value
|
||||||
when writing JSON text.
|
when writing JSON text.
|
||||||
|
|
||||||
@@ -81,27 +97,61 @@ Additional options:
|
|||||||
- `--gen-mutable` : Generate additional non-const accessors for mutating
|
- `--gen-mutable` : Generate additional non-const accessors for mutating
|
||||||
FlatBuffers in-place.
|
FlatBuffers in-place.
|
||||||
|
|
||||||
`--gen-object-api` : Generate an additional object-based API. This API is
|
- `--gen-onefile` : Generate single output file for C# and Go.
|
||||||
|
|
||||||
|
- `--gen-name-strings` : Generate type name functions for C++.
|
||||||
|
|
||||||
|
- `--gen-object-api` : Generate an additional object-based API. This API is
|
||||||
more convenient for object construction and mutation than the base API,
|
more convenient for object construction and mutation than the base API,
|
||||||
at the cost of efficiency (object allocation). Recommended only to be used
|
at the cost of efficiency (object allocation). Recommended only to be used
|
||||||
if other options are insufficient.
|
if other options are insufficient.
|
||||||
|
|
||||||
- `--gen-onefile` : Generate single output file (useful for C#)
|
- `--gen-compare` : Generate operator== for object-based API types.
|
||||||
|
|
||||||
- `--gen-all`: Generate not just code for the current schema files, but
|
- `--gen-nullable` : Add Clang _Nullable for C++ pointer. or @Nullable for Java.
|
||||||
|
|
||||||
|
- `--gen-generated` : Add @Generated annotation for Java.
|
||||||
|
|
||||||
|
- `--gen-all` : Generate not just code for the current schema files, but
|
||||||
for all files it includes as well. If the language uses a single file for
|
for all files it includes as well. If the language uses a single file for
|
||||||
output (by default the case for C++ and JS), all code will end up in
|
output (by default the case for C++ and JS), all code will end up in
|
||||||
this one file.
|
this one file.
|
||||||
|
|
||||||
- `--no-js-exports` : Removes Node.js style export lines (useful for JS)
|
- `--cpp-ptr-type T` : Set object API pointer type (default std::unique_ptr)
|
||||||
|
|
||||||
|
- `--cpp-str-type T` : Set object API string type (default std::string)
|
||||||
|
T::c_str(), T::length() and T::empty() must be supported.
|
||||||
|
The custom type also needs to be constructible from std::string (see the
|
||||||
|
--cpp-str-flex-ctor option to change this behavior).
|
||||||
|
|
||||||
|
- `--cpp-str-flex-ctor` : Don't construct custom string types by passing
|
||||||
|
std::string from Flatbuffers, but (char* + length). This allows efficient
|
||||||
|
construction of custom string types, including zero-copy construction.
|
||||||
|
|
||||||
|
- `--object-prefix` : Customise class prefix for C++ object-based API.
|
||||||
|
|
||||||
|
- `--object-suffix` : Customise class suffix for C++ object-based API.
|
||||||
|
|
||||||
|
- `--no-js-exports` : Removes Node.js style export lines (useful for JS)
|
||||||
|
|
||||||
- `--goog-js-export` : Uses goog.exportsSymbol and goog.exportsProperty
|
- `--goog-js-export` : Uses goog.exportsSymbol and goog.exportsProperty
|
||||||
instead of Node.js style exporting. Needed for compatibility with the
|
instead of Node.js style exporting. Needed for compatibility with the
|
||||||
Google closure compiler (useful for JS).
|
Google closure compiler (useful for JS).
|
||||||
|
|
||||||
|
- `--es6-js-export` : Generates ECMAScript v6 style export definitions
|
||||||
|
instead of Node.js style exporting. Useful when integrating flatbuffers
|
||||||
|
with modern Javascript projects.
|
||||||
|
|
||||||
|
- `--go-namespace` : Generate the overrided namespace in Golang.
|
||||||
|
|
||||||
|
- `--go-import` : Generate the overrided import for flatbuffers in Golang.
|
||||||
|
(default is "github.com/google/flatbuffers/go").
|
||||||
|
|
||||||
- `--raw-binary` : Allow binaries without a file_indentifier to be read.
|
- `--raw-binary` : Allow binaries without a file_indentifier to be read.
|
||||||
This may crash flatc given a mismatched schema.
|
This may crash flatc given a mismatched schema.
|
||||||
|
|
||||||
|
- `--size-prefixed` : Input binaries are size prefixed buffers.
|
||||||
|
|
||||||
- `--proto`: Expect input files to be .proto files (protocol buffers).
|
- `--proto`: Expect input files to be .proto files (protocol buffers).
|
||||||
Output the corresponding .fbs file.
|
Output the corresponding .fbs file.
|
||||||
Currently supports: `package`, `message`, `enum`, nested declarations,
|
Currently supports: `package`, `message`, `enum`, nested declarations,
|
||||||
@@ -109,6 +159,10 @@ Additional options:
|
|||||||
Does not support, but will skip without error: `option`, `service`,
|
Does not support, but will skip without error: `option`, `service`,
|
||||||
`extensions`, and most everything else.
|
`extensions`, and most everything else.
|
||||||
|
|
||||||
|
- `--oneof-union` : Translate .proto oneofs to flatbuffer unions.
|
||||||
|
|
||||||
|
- `--grpc` : Generate GRPC interfaces for the specified languages.
|
||||||
|
|
||||||
- `--schema`: Serialize schemas instead of JSON (use with -b). This will
|
- `--schema`: Serialize schemas instead of JSON (use with -b). This will
|
||||||
output a binary version of the specified schema that itself corresponds
|
output a binary version of the specified schema that itself corresponds
|
||||||
to the reflection/reflection.fbs schema. Loading this binary file is the
|
to the reflection/reflection.fbs schema. Loading this binary file is the
|
||||||
@@ -120,13 +174,30 @@ Additional options:
|
|||||||
an evolution of. Gives errors if not. Useful to check if schema
|
an evolution of. Gives errors if not. Useful to check if schema
|
||||||
modifications don't break schema evolution rules.
|
modifications don't break schema evolution rules.
|
||||||
|
|
||||||
|
- `--conform-includes PATH` : Include path for the schema given with
|
||||||
|
`--conform PATH`.
|
||||||
|
|
||||||
- `--include-prefix PATH` : Prefix this path to any generated include
|
- `--include-prefix PATH` : Prefix this path to any generated include
|
||||||
statements.
|
statements.
|
||||||
|
|
||||||
- `--keep-prefix` : Keep original prefix of schema include statement.
|
- `--keep-prefix` : Keep original prefix of schema include statement.
|
||||||
|
|
||||||
|
- `--no-fb-impor` : Don't include flatbuffers import statement for TypeScript.
|
||||||
|
|
||||||
|
- `--no-ts-reexpor` : Don't re-export imported dependencies for TypeScript.
|
||||||
|
|
||||||
|
- `--short-name` : Use short function names for JS and TypeScript.
|
||||||
|
|
||||||
- `--reflect-types` : Add minimal type reflection to code generation.
|
- `--reflect-types` : Add minimal type reflection to code generation.
|
||||||
|
|
||||||
- `--reflect-names` : Add minimal type/name reflection.
|
- `--reflect-names` : Add minimal type/name reflection.
|
||||||
|
|
||||||
|
- `--root-type T` : Select or override the default root_type.
|
||||||
|
|
||||||
|
- `--force-defaults` : Emit default values in binary output from JSON.
|
||||||
|
|
||||||
|
- `--force-empty` : When serializing from object API representation, force
|
||||||
|
strings and vectors to empty rather than null.
|
||||||
|
|
||||||
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.
|
||||||
|
|||||||
@@ -59,15 +59,18 @@ a `char *` array, which you pass to `GetMonster()`.
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||||
#include "flatbuffers/flatbuffers.h"
|
#include "flatbuffers/flatbuffers.h"
|
||||||
#include "monster_test_generate.h"
|
#include "monster_test_generate.h"
|
||||||
#include <cstdio> // For printing and file access.
|
#include <iostream> // C++ header file for printing
|
||||||
|
#include <fstream> // C++ header file for file access
|
||||||
|
|
||||||
FILE* file = fopen("monsterdata_test.mon", "rb");
|
|
||||||
fseek(file, 0L, SEEK_END);
|
std::ifstream infile;
|
||||||
int length = ftell(file);
|
infile.open("monsterdata_test.mon", std::ios::binary | std::ios::in);
|
||||||
fseek(file, 0L, SEEK_SET);
|
infile.seekg(0,std::ios::end);
|
||||||
|
int length = infile.tellg();
|
||||||
|
infile.seekg(0,std::ios::beg);
|
||||||
char *data = new char[length];
|
char *data = new char[length];
|
||||||
fread(data, sizeof(char), length, file);
|
infile.read(data, length);
|
||||||
fclose(file);
|
infile.close();
|
||||||
|
|
||||||
auto monster = GetMonster(data);
|
auto monster = GetMonster(data);
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
@@ -78,13 +81,21 @@ If you look in your generated header, you'll see it has
|
|||||||
convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
|
convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
|
||||||
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
|
||||||
printf("%d\n", monster->hp()); // `80`
|
std::cout << "hp : " << monster->hp() << std::endl; // `80`
|
||||||
printf("%d\n", monster->mana()); // default value of `150`
|
std::cout << "mana : " << monster->mana() << std::endl; // default value of `150`
|
||||||
printf("%s\n", monster->name()->c_str()); // "MyMonster"
|
std::cout << "name : " << monster->name()->c_str() << std::endl; // "MyMonster"
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
*Note: That we never stored a `mana` value, so it will return the default.*
|
*Note: That we never stored a `mana` value, so it will return the default.*
|
||||||
|
|
||||||
|
The following attributes are supported:
|
||||||
|
|
||||||
|
- `shared` (on a field): For string fields, this enables the usage of string
|
||||||
|
pooling (i.e. `CreateSharedString`) as default serialization behavior.
|
||||||
|
|
||||||
|
Specifically, `CreateXxxDirect` functions and `Pack` functions for object
|
||||||
|
based API (see below) will use `CreateSharedString` to create strings.
|
||||||
|
|
||||||
## Object based API. {#flatbuffers_cpp_object_based_api}
|
## Object based API. {#flatbuffers_cpp_object_based_api}
|
||||||
|
|
||||||
FlatBuffers is all about memory efficiency, which is why its base API is written
|
FlatBuffers is all about memory efficiency, which is why its base API is written
|
||||||
@@ -127,10 +138,10 @@ The following attributes are specific to the object-based API code generation:
|
|||||||
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
|
- `native_custom_alloc`:"custom_allocator" (on a table or struct): When using the
|
||||||
object-based API all generated NativeTables that are allocated when unpacking
|
object-based API all generated NativeTables that are allocated when unpacking
|
||||||
your flatbuffer will use "custom allocator". The allocator is also used by
|
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`.
|
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
|
This can be used to provide allocation from a pool for example, for faster
|
||||||
unpacking when using the object-based API.
|
unpacking when using the object-based API.
|
||||||
|
|
||||||
Minimal Example:
|
Minimal Example:
|
||||||
@@ -148,8 +159,8 @@ The following attributes are specific to the object-based API code generation:
|
|||||||
typedef T *pointer;
|
typedef T *pointer;
|
||||||
|
|
||||||
template <class U>
|
template <class U>
|
||||||
struct rebind {
|
struct rebind {
|
||||||
typedef custom_allocator<U> other;
|
typedef custom_allocator<U> other;
|
||||||
};
|
};
|
||||||
|
|
||||||
pointer allocate(const std::size_t n) {
|
pointer allocate(const std::size_t n) {
|
||||||
@@ -161,7 +172,7 @@ The following attributes are specific to the object-based API code generation:
|
|||||||
}
|
}
|
||||||
|
|
||||||
custom_allocator() throw() {}
|
custom_allocator() throw() {}
|
||||||
template <class U>
|
template <class U>
|
||||||
custom_allocator(const custom_allocator<U>&) throw() {}
|
custom_allocator(const custom_allocator<U>&) throw() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -205,12 +216,15 @@ The following attributes are specific to the object-based API code generation:
|
|||||||
|
|
||||||
Finally, the following top-level attribute
|
Finally, the following top-level attribute
|
||||||
|
|
||||||
- native_include: "path" (at file level): Because the `native_type` attribute
|
- `native_include`: "path" (at file level): Because the `native_type` attribute
|
||||||
can be used to introduce types that are unknown to flatbuffers, it may be
|
can be used to introduce types that are unknown to flatbuffers, it may be
|
||||||
necessary to include "external" header files in the generated code. This
|
necessary to include "external" header files in the generated code. This
|
||||||
attribute can be used to directly add an #include directive to the top of
|
attribute can be used to directly add an #include directive to the top of
|
||||||
the generated code that includes the specified path directly.
|
the generated code that includes the specified path directly.
|
||||||
|
|
||||||
|
- `force_align`: this attribute may not be respected in the object API,
|
||||||
|
depending on the aligned of the allocator used with `new`.
|
||||||
|
|
||||||
# External references.
|
# External references.
|
||||||
|
|
||||||
An additional feature of the object API is the ability to allow you to load
|
An additional feature of the object API is the ability to allow you to load
|
||||||
@@ -237,8 +251,9 @@ influence this either globally (using the `--cpp-ptr-type` argument to
|
|||||||
`flatc`) or per field (using the `cpp_ptr_type` attribute) to by any smart
|
`flatc`) or per field (using the `cpp_ptr_type` attribute) to by any smart
|
||||||
pointer type (`my_ptr<T>`), or by specifying `naked` as the type to get `T *`
|
pointer type (`my_ptr<T>`), or by specifying `naked` as the type to get `T *`
|
||||||
pointers. Unlike the smart pointers, naked pointers do not manage memory for
|
pointers. Unlike the smart pointers, naked pointers do not manage memory for
|
||||||
you, so you'll have to manage their lifecycles manually.
|
you, so you'll have to manage their lifecycles manually. To reference the
|
||||||
|
pointer type specified by the `--cpp-ptr-type` argument to `flatc` from a
|
||||||
|
flatbuffer field set the `cpp_ptr_type` attribute to `default_ptr_type`.
|
||||||
|
|
||||||
# Using different string type.
|
# Using different string type.
|
||||||
|
|
||||||
@@ -246,7 +261,18 @@ By default the object tree is built out of `std::string`, but you can
|
|||||||
influence this either globally (using the `--cpp-str-type` argument to
|
influence this either globally (using the `--cpp-str-type` argument to
|
||||||
`flatc`) or per field using the `cpp_str_type` attribute.
|
`flatc`) or per field using the `cpp_str_type` attribute.
|
||||||
|
|
||||||
The type must support T::c_str() and T::length() as member functions.
|
The type must support T::c_str(), T::length() and T::empty() as member functions.
|
||||||
|
|
||||||
|
Further, the type must be constructible from std::string, as by default a
|
||||||
|
std::string instance is constructed and then used to initialize the custom
|
||||||
|
string type. This behavior impedes efficient and zero-copy construction of
|
||||||
|
custom string types; the `--cpp-str-flex-ctor` argument to `flatc` or the
|
||||||
|
per field attribute `cpp_str_flex_ctor` can be used to change this behavior,
|
||||||
|
so that the custom string type is constructed by passing the pointer and
|
||||||
|
length of the FlatBuffers String. The custom string class will require a
|
||||||
|
constructor in the following format: custom_str_class(const char *, size_t).
|
||||||
|
Please note that the character array is not guaranteed to be NULL terminated,
|
||||||
|
you should always use the provided size to determine end of string.
|
||||||
|
|
||||||
## Reflection (& Resizing)
|
## Reflection (& Resizing)
|
||||||
|
|
||||||
@@ -492,4 +518,49 @@ needed to use unions.
|
|||||||
|
|
||||||
To use scalars, simply wrap them in a struct.
|
To use scalars, simply wrap them in a struct.
|
||||||
|
|
||||||
|
## Depth limit of nested objects and stack-overflow control
|
||||||
|
The parser of Flatbuffers schema or json-files is kind of recursive parser.
|
||||||
|
To avoid stack-overflow problem the parser has a built-in limiter of
|
||||||
|
recursion depth. Number of nested declarations in a schema or number of
|
||||||
|
nested json-objects is limited. By default, this depth limit set to `64`.
|
||||||
|
It is possible to override this limit with `FLATBUFFERS_MAX_PARSING_DEPTH`
|
||||||
|
definition. This definition can be helpful for testing purposes or embedded
|
||||||
|
applications. For details see [build](@ref flatbuffers_guide_building) of
|
||||||
|
CMake-based projects.
|
||||||
|
|
||||||
|
## Dependence from C-locale {#flatbuffers_locale_cpp}
|
||||||
|
The Flatbuffers [grammar](@ref flatbuffers grammar) uses ASCII
|
||||||
|
character set for identifiers, alphanumeric literals, reserved words.
|
||||||
|
|
||||||
|
Internal implementation of the Flatbuffers depends from functions which
|
||||||
|
depend from C-locale: `strtod()` or `strtof()`, for example.
|
||||||
|
The library expects the dot `.` symbol as the separator of an integer
|
||||||
|
part from the fractional part of a float number.
|
||||||
|
Another separator symbols (`,` for example) will break the compatibility
|
||||||
|
and may lead to an error while parsing a Flatbuffers schema or a json file.
|
||||||
|
|
||||||
|
The Standard C locale is a global resource, there is only one locale for
|
||||||
|
the entire application. Some modern compilers and platforms have
|
||||||
|
locale-independent or locale-narrow functions `strtof_l`, `strtod_l`,
|
||||||
|
`strtoll_l`, `strtoull_l` to resolve this dependency.
|
||||||
|
These functions use specified locale rather than the global or per-thread
|
||||||
|
locale instead. They are part of POSIX-2008 but not part of the C/C++
|
||||||
|
standard library, therefore, may be missing on some platforms.
|
||||||
|
|
||||||
|
The Flatbuffers library try to detect these functions at configuration and
|
||||||
|
compile time:
|
||||||
|
- `_MSC_VER >= 1900`: check MSVC2012 or higher for MSVC buid
|
||||||
|
- `_XOPEN_SOURCE>=700`: check POSIX-2008 for GCC/Clang build
|
||||||
|
- `check_cxx_symbol_exists(strtof_l stdlib.h)`: CMake check of `strtod_f`
|
||||||
|
|
||||||
|
After detection, the definition `FLATBUFFERS_LOCALE_INDEPENDENT` will be
|
||||||
|
set to `0` or `1`.
|
||||||
|
|
||||||
|
It is possible to test the compatibility of the Flatbuffers library with
|
||||||
|
a specific locale using the environment variable `FLATBUFFERS_TEST_LOCALE`:
|
||||||
|
```sh
|
||||||
|
>FLATBUFFERS_TEST_LOCALE="" ./flattests
|
||||||
|
>FLATBUFFERS_TEST_LOCALE="ru_RU.CP1251" ./flattests
|
||||||
|
```
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|||||||
108
docs/source/DartUsage.md
Normal file
108
docs/source/DartUsage.md
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
Use in Dart {#flatbuffers_guide_use_dart}
|
||||||
|
===========
|
||||||
|
|
||||||
|
## Before you get started
|
||||||
|
|
||||||
|
Before diving into the FlatBuffers usage in Dart, 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 Dart).
|
||||||
|
This page is designed to cover the nuances of FlatBuffers usage, specific to
|
||||||
|
Dart.
|
||||||
|
|
||||||
|
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 Dart library code location
|
||||||
|
|
||||||
|
The code for the FlatBuffers Dart library can be found at
|
||||||
|
`flatbuffers/dart`. You can browse the library code on the [FlatBuffers
|
||||||
|
GitHub page](https://github.com/google/flatbuffers/tree/master/dart).
|
||||||
|
|
||||||
|
## Testing the FlatBuffers Dart library
|
||||||
|
|
||||||
|
The code to test the Dart library can be found at `flatbuffers/tests`.
|
||||||
|
The test code itself is located in [dart_test.dart](https://github.com/google/
|
||||||
|
flatbuffers/blob/master/tests/dart_test.dart).
|
||||||
|
|
||||||
|
To run the tests, use the [DartTest.sh](https://github.com/google/flatbuffers/
|
||||||
|
blob/master/tests/DartTest.sh) shell script.
|
||||||
|
|
||||||
|
*Note: The shell script requires the [Dart SDK](https://www.dartlang.org/tools/sdk)
|
||||||
|
to be installed.*
|
||||||
|
|
||||||
|
## Using the FlatBuffers Dart library
|
||||||
|
|
||||||
|
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||||
|
example of how to use FlatBuffers in Dart.*
|
||||||
|
|
||||||
|
FlatBuffers supports reading and writing binary FlatBuffers in Dart.
|
||||||
|
|
||||||
|
To use FlatBuffers in your own code, first generate Dart classes from your
|
||||||
|
schema with the `--dart` 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 Dart: First,
|
||||||
|
include the library and generated code. Then read a FlatBuffer binary file into
|
||||||
|
a `List<int>`, which you pass to the factory constructor for `Monster`:
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.dart}
|
||||||
|
import 'dart:io' as io;
|
||||||
|
|
||||||
|
import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||||
|
import './monster_my_game.sample_generated.dart' as myGame;
|
||||||
|
|
||||||
|
List<int> data = await new io.File('monster.dat').readAsBytes();
|
||||||
|
var monster = new myGame.Monster(data);
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Now you can access values like this:
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.dart}
|
||||||
|
var hp = monster.hp;
|
||||||
|
var pos = monster.pos;
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
## Differences from the Dart SDK Front End flat_buffers
|
||||||
|
|
||||||
|
The work in this repository is signfiicantly based on the implementation used
|
||||||
|
internally by the Dart SDK in the front end/analyzer package. Several
|
||||||
|
significant changes have been made.
|
||||||
|
|
||||||
|
1. Support for packed boolean lists has been removed. This is not standard
|
||||||
|
in other implementations and is not compatible with them. Do note that,
|
||||||
|
like in the JavaScript implementation, __null values in boolean lists
|
||||||
|
will be treated as false__. It is also still entirely possible to pack data
|
||||||
|
in a single scalar field, but that would have to be done on the application
|
||||||
|
side.
|
||||||
|
2. The SDK implementation supports enums with regular Dart enums, which
|
||||||
|
works if enums are always indexed at 1; however, FlatBuffers does not
|
||||||
|
require that. This implementation uses specialized enum-like classes to
|
||||||
|
ensure proper mapping from FlatBuffers to Dart and other platforms.
|
||||||
|
3. The SDK implementation does not appear to support FlatBuffer structs or
|
||||||
|
vectors of structs - it treated everything as a built-in scalar or a table.
|
||||||
|
This implementation treats structs in a way that is compatible with other
|
||||||
|
non-Dart implementations, and properly handles vectors of structs. Many of
|
||||||
|
the methods prefixed with 'low' have been prepurposed to support this.
|
||||||
|
4. The SDK implementation treats int64 and uint64 as float64s. This
|
||||||
|
implementation does not. This may cause problems with JavaScript
|
||||||
|
compatibility - however, it should be possible to use the JavaScript
|
||||||
|
implementation, or to do a customized implementation that treats all 64 bit
|
||||||
|
numbers as floats. Supporting the Dart VM and Flutter was a more important
|
||||||
|
goal of this implementation. Support for 16 bit integers was also added.
|
||||||
|
5. The code generation in this offers an "ObjectBuilder", which generates code
|
||||||
|
very similar to the SDK classes that consume FlatBuffers, as well as Builder
|
||||||
|
classes, which produces code which more closely resembles the builders in
|
||||||
|
other languages. The ObjectBuilder classes are easier to use, at the cost of
|
||||||
|
additional references allocated.
|
||||||
|
|
||||||
|
## Text Parsing
|
||||||
|
|
||||||
|
There currently is no support for parsing text (Schema's and JSON) directly
|
||||||
|
from Dart, though you could use the C++ parser through Dart Native Extensions.
|
||||||
|
Please see the C++ documentation for more on text parsing (note that this is
|
||||||
|
not currently an option in Flutter - follow [this issue](https://github.com/flutter/flutter/issues/7053)
|
||||||
|
for the latest).
|
||||||
|
|
||||||
|
<br>
|
||||||
@@ -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, TypeScript, PHP, and Python.
|
serialization library for C++, C#, C, Go, Java, JavaScript, Lobster, Lua, TypeScript, PHP, Python, and Rust.
|
||||||
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,12 +134,18 @@ 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 Lua code](@ref flatbuffers_guide_use_lua) in your
|
||||||
|
own programs.
|
||||||
- How to [use the generated JavaScript code](@ref flatbuffers_guide_use_javascript) in your
|
- How to [use the generated JavaScript code](@ref flatbuffers_guide_use_javascript) in your
|
||||||
own programs.
|
own programs.
|
||||||
- How to [use the generated TypeScript code](@ref flatbuffers_guide_use_typescript) in your
|
- How to [use the generated TypeScript code](@ref flatbuffers_guide_use_typescript) in your
|
||||||
own programs.
|
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.
|
||||||
|
- How to [use the generated Lobster code](@ref flatbuffers_guide_use_lobster) in your
|
||||||
|
own programs.
|
||||||
|
- How to [use the generated Rust code](@ref flatbuffers_guide_use_rust) in your
|
||||||
|
own programs.
|
||||||
- [Support matrix](@ref flatbuffers_support) for platforms/languages/features.
|
- [Support matrix](@ref flatbuffers_support) for platforms/languages/features.
|
||||||
- Some [benchmarks](@ref flatbuffers_benchmarks) showing the advantage of
|
- Some [benchmarks](@ref flatbuffers_benchmarks) showing the advantage of
|
||||||
using FlatBuffers.
|
using FlatBuffers.
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ include = `include` string\_constant `;`
|
|||||||
|
|
||||||
namespace\_decl = `namespace` ident ( `.` ident )* `;`
|
namespace\_decl = `namespace` ident ( `.` ident )* `;`
|
||||||
|
|
||||||
attribute\_decl = `attribute` string\_constant `;`
|
attribute\_decl = `attribute` ident | `"`ident`"` `;`
|
||||||
|
|
||||||
type\_decl = ( `table` | `struct` ) ident metadata `{` field\_decl+ `}`
|
type\_decl = ( `table` | `struct` ) ident metadata `{` field\_decl+ `}`
|
||||||
|
|
||||||
enum\_decl = ( `enum` ident [ `:` type ] | `union` ident ) metadata `{`
|
enum\_decl = ( `enum` ident `:` type | `union` ident ) metadata `{`
|
||||||
commasep( enumval\_decl ) `}`
|
commasep( enumval\_decl ) `}`
|
||||||
|
|
||||||
root\_decl = `root_type` ident `;`
|
root\_decl = `root_type` ident `;`
|
||||||
@@ -49,11 +49,26 @@ 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`
|
|
||||||
|
|
||||||
float\_constant = `-?[0-9]+.[0-9]+((e|E)(+|-)?[0-9]+)?`
|
|
||||||
|
|
||||||
string\_constant = `\".*?\"`
|
string\_constant = `\".*?\"`
|
||||||
|
|
||||||
ident = `[a-zA-Z_][a-zA-Z0-9_]*`
|
ident = `[a-zA-Z_][a-zA-Z0-9_]*`
|
||||||
|
|
||||||
|
`[:digit:]` = `[0-9]`
|
||||||
|
|
||||||
|
`[:xdigit:]` = `[0-9a-fA-F]`
|
||||||
|
|
||||||
|
dec\_integer\_constant = `[-+]?[:digit:]+`
|
||||||
|
|
||||||
|
hex\_integer\_constant = `[-+]?0[xX][:xdigit:]+`
|
||||||
|
|
||||||
|
integer\_constant = dec\_integer\_constant | hex\_integer\_constant
|
||||||
|
|
||||||
|
dec\_float\_constant = `[-+]?(([.][:digit:]+)|([:digit:]+[.][:digit:]*)|([:digit:]+))([eE][-+]?[:digit:]+)?`
|
||||||
|
|
||||||
|
hex\_float\_constant = `[-+]?0[xX](([.][:xdigit:]+)|([:xdigit:]+[.][:xdigit:]*)|([:xdigit:]+))([pP][-+]?[:digit:]+)`
|
||||||
|
|
||||||
|
special\_float\_constant = `[-+]?(nan|inf|infinity)`
|
||||||
|
|
||||||
|
float\_constant = decimal\_float\_constant | hexadecimal\_float\_constant | special\_float\_constant
|
||||||
|
|
||||||
|
boolean\_constant = `(true|false)` | (integer\_constant ? `true` : `false`)
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ Unions share a lot with enums.
|
|||||||
Predeclare all data types since circular references between types are allowed
|
Predeclare all data types since circular references between types are allowed
|
||||||
(circular references between object are not, though).
|
(circular references between object are not, though).
|
||||||
|
|
||||||
MANUALLY_ALIGNED_STRUCT(4) Vec3 {
|
FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vec3 {
|
||||||
private:
|
private:
|
||||||
float x_;
|
float x_;
|
||||||
float y_;
|
float y_;
|
||||||
@@ -183,7 +183,7 @@ Predeclare all data types since circular references between types are allowed
|
|||||||
float y() const { return flatbuffers::EndianScalar(y_); }
|
float y() const { return flatbuffers::EndianScalar(y_); }
|
||||||
float z() const { return flatbuffers::EndianScalar(z_); }
|
float z() const { return flatbuffers::EndianScalar(z_); }
|
||||||
};
|
};
|
||||||
STRUCT_END(Vec3, 12);
|
FLATBUFFERS_STRUCT_END(Vec3, 12);
|
||||||
|
|
||||||
These ugly macros do a couple of things: they turn off any padding the compiler
|
These ugly macros do a couple of things: they turn off any padding the compiler
|
||||||
might normally do, since we add padding manually (though none in this example),
|
might normally do, since we add padding manually (though none in this example),
|
||||||
|
|||||||
85
docs/source/LobsterUsage.md
Normal file
85
docs/source/LobsterUsage.md
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
Use in Lobster {#flatbuffers_guide_use_lobster}
|
||||||
|
==============
|
||||||
|
|
||||||
|
## Before you get started
|
||||||
|
|
||||||
|
Before diving into the FlatBuffers usage in Lobster, 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 Lobster). This
|
||||||
|
page is designed to cover the nuances of FlatBuffers usage, specific to
|
||||||
|
Lobster.
|
||||||
|
|
||||||
|
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 Lobster library code location
|
||||||
|
|
||||||
|
The code for the FlatBuffers Lobster library can be found at
|
||||||
|
`flatbuffers/lobster`. You can browse the library code on the
|
||||||
|
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/
|
||||||
|
lobster).
|
||||||
|
|
||||||
|
## Testing the FlatBuffers Lobster library
|
||||||
|
|
||||||
|
The code to test the Lobster library can be found at `flatbuffers/tests`.
|
||||||
|
The test code itself is located in [lobstertest.lobster](https://github.com/google/
|
||||||
|
flatbuffers/blob/master/tests/lobstertest.lobster).
|
||||||
|
|
||||||
|
To run the tests, run `lobster lobstertest.lobster`. To obtain Lobster itself,
|
||||||
|
go to the [Lobster homepage](http://strlen.com/lobster) or
|
||||||
|
[github](https://github.com/aardappel/lobster) to learn how to build it for your
|
||||||
|
platform.
|
||||||
|
|
||||||
|
## Using the FlatBuffers Lobster library
|
||||||
|
|
||||||
|
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||||
|
example of how to use FlatBuffers in Lobster.*
|
||||||
|
|
||||||
|
There is support for both reading and writing FlatBuffers in Lobster.
|
||||||
|
|
||||||
|
To use FlatBuffers in your own code, first generate Lobster classes from your
|
||||||
|
schema with the `--lobster` 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 Lobster:
|
||||||
|
First, import the library and the generated code. Then read a FlatBuffer binary
|
||||||
|
file into a string, which you pass to the `GetRootAsMonster` function:
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lobster}
|
||||||
|
include "monster_generated.lobster"
|
||||||
|
|
||||||
|
let fb = read_file("monsterdata_test.mon")
|
||||||
|
assert fb
|
||||||
|
let monster = MyGame_Example_GetRootAsMonster(fb)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Now you can access values like this:
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lobster}
|
||||||
|
let hp = monster.hp
|
||||||
|
let pos = monster.pos
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
As you can see, even though `hp` and `pos` are functions that access FlatBuffer
|
||||||
|
data in-place in the string buffer, they appear as field accesses.
|
||||||
|
|
||||||
|
## Speed
|
||||||
|
|
||||||
|
Using FlatBuffers in Lobster should be relatively fast, as the implementation
|
||||||
|
makes use of native support for writing binary values, and access of vtables.
|
||||||
|
Both generated code and the runtime library are therefore small and fast.
|
||||||
|
|
||||||
|
Actual speed will depend on wether you use Lobster as bytecode VM or compiled to
|
||||||
|
C++.
|
||||||
|
|
||||||
|
## Text Parsing
|
||||||
|
|
||||||
|
Lobster has full support for parsing JSON into FlatBuffers, or generating
|
||||||
|
JSON from FlatBuffers. See `samples/sample_test.lobster` for an example.
|
||||||
|
|
||||||
|
This uses the C++ parser and generator underneath, so should be both fast and
|
||||||
|
conformant.
|
||||||
|
|
||||||
|
<br>
|
||||||
81
docs/source/LuaUsage.md
Normal file
81
docs/source/LuaUsage.md
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
Use in Lua {#flatbuffers_guide_use_lua}
|
||||||
|
=============
|
||||||
|
|
||||||
|
## Before you get started
|
||||||
|
|
||||||
|
Before diving into the FlatBuffers usage in Lua, 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 Lua). This
|
||||||
|
page is designed to cover the nuances of FlatBuffers usage, specific to
|
||||||
|
Lua.
|
||||||
|
|
||||||
|
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 Lua library code location
|
||||||
|
|
||||||
|
The code for the FlatBuffers Lua library can be found at
|
||||||
|
`flatbuffers/lua`. You can browse the library code on the
|
||||||
|
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/lua).
|
||||||
|
|
||||||
|
## Testing the FlatBuffers Lua library
|
||||||
|
|
||||||
|
The code to test the Lua library can be found at `flatbuffers/tests`.
|
||||||
|
The test code itself is located in [luatest.lua](https://github.com/google/
|
||||||
|
flatbuffers/blob/master/tests/luatest.lua).
|
||||||
|
|
||||||
|
To run the tests, use the [LuaTest.sh](https://github.com/google/flatbuffers/
|
||||||
|
blob/master/tests/LuaTest.sh) shell script.
|
||||||
|
|
||||||
|
*Note: This script requires [Lua 5.3](https://www.lua.org/) to be
|
||||||
|
installed.*
|
||||||
|
|
||||||
|
## Using the FlatBuffers Lua library
|
||||||
|
|
||||||
|
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||||
|
example of how to use FlatBuffers in Lua.*
|
||||||
|
|
||||||
|
There is support for both reading and writing FlatBuffers in Lua.
|
||||||
|
|
||||||
|
To use FlatBuffers in your own code, first generate Lua classes from your
|
||||||
|
schema with the `--lua` 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 Lua:
|
||||||
|
First, require the module and the generated code. Then read a FlatBuffer binary
|
||||||
|
file into a `string`, which you pass to the `GetRootAsMonster` function:
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lua}
|
||||||
|
-- require the library
|
||||||
|
local flatbuffers = require("flatbuffers")
|
||||||
|
|
||||||
|
-- require the generated code
|
||||||
|
local monster = require("MyGame.Sample.Monster")
|
||||||
|
|
||||||
|
-- read the flatbuffer from a file into a string
|
||||||
|
local f = io.open('monster.dat', 'rb')
|
||||||
|
local buf = f:read('*a')
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
-- parse the flatbuffer to get an instance to the root monster
|
||||||
|
local monster1 = monster.GetRootAsMonster(buf, 0)
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Now you can access values like this:
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.lua}
|
||||||
|
-- use the : notation to access member data
|
||||||
|
local hp = monster1:Hp()
|
||||||
|
local pos = monster1:Pos()
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
||||||
|
## Text Parsing
|
||||||
|
|
||||||
|
There currently is no support for parsing text (Schema's and JSON) directly
|
||||||
|
from Lua, though you could use the C++ parser through SWIG or ctypes. Please
|
||||||
|
see the C++ documentation for more on text parsing.
|
||||||
|
|
||||||
|
<br>
|
||||||
174
docs/source/RustUsage.md
Normal file
174
docs/source/RustUsage.md
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
Use in Rust {#flatbuffers_guide_use_rust}
|
||||||
|
==========
|
||||||
|
|
||||||
|
## Before you get started
|
||||||
|
|
||||||
|
Before diving into the FlatBuffers usage in Rust, 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 Rust).
|
||||||
|
This page is designed to cover the nuances of FlatBuffers usage, specific to
|
||||||
|
Rust.
|
||||||
|
|
||||||
|
#### Prerequisites
|
||||||
|
|
||||||
|
This page assumes you have written a FlatBuffers schema and compiled it
|
||||||
|
with the Schema Compiler. If you have not, please see
|
||||||
|
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler)
|
||||||
|
and [Writing a schema](@ref flatbuffers_guide_writing_schema).
|
||||||
|
|
||||||
|
Assuming you wrote a schema, say `mygame.fbs` (though the extension doesn't
|
||||||
|
matter), you've generated a Rust file called `mygame_generated.rs` using the
|
||||||
|
compiler (e.g. `flatc --rust mygame.fbs` or via helpers listed in "Useful
|
||||||
|
tools created by others" section bellow), you can now start using this in
|
||||||
|
your program by including the file. As noted, this header relies on the crate
|
||||||
|
`flatbuffers`, which should be in your include `Cargo.toml`.
|
||||||
|
|
||||||
|
## FlatBuffers Rust library code location
|
||||||
|
|
||||||
|
The code for the FlatBuffers Rust library can be found at
|
||||||
|
`flatbuffers/rust`. You can browse the library code on the
|
||||||
|
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/rust).
|
||||||
|
|
||||||
|
## Testing the FlatBuffers Rust library
|
||||||
|
|
||||||
|
The code to test the Rust library can be found at `flatbuffers/tests/rust_usage_test`.
|
||||||
|
The test code itself is located in
|
||||||
|
[integration_test.rs](https://github.com/google/flatbuffers/blob/master/tests/rust_usage_test/tests/integration_test.rs)
|
||||||
|
|
||||||
|
This test file requires `flatc` to be present. To review how to build the project,
|
||||||
|
please read the [Building](@ref flatbuffers_guide_building) documenation.
|
||||||
|
|
||||||
|
To run the tests, execute `RustTest.sh` from the `flatbuffers/tests` directory.
|
||||||
|
For example, on [Linux](https://en.wikipedia.org/wiki/Linux), you would simply
|
||||||
|
run: `cd tests && ./RustTest.sh`.
|
||||||
|
|
||||||
|
*Note: The shell script requires [Rust](https://www.rust-lang.org) to
|
||||||
|
be installed.*
|
||||||
|
|
||||||
|
## Using the FlatBuffers Rust library
|
||||||
|
|
||||||
|
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||||
|
example of how to use FlatBuffers in Rust.*
|
||||||
|
|
||||||
|
FlatBuffers supports both reading and writing FlatBuffers in Rust.
|
||||||
|
|
||||||
|
To use FlatBuffers in your code, first generate the Rust modules from your
|
||||||
|
schema with the `--rust` option to `flatc`. Then you can import both FlatBuffers
|
||||||
|
and the generated code to read or write FlatBuffers.
|
||||||
|
|
||||||
|
For example, here is how you would read a FlatBuffer binary file in Rust:
|
||||||
|
First, include the library and generated code. Then read the file into
|
||||||
|
a `u8` vector, which you pass, as a byte slice, to `get_root_as_monster()`.
|
||||||
|
|
||||||
|
This full example program is available in the Rust test suite:
|
||||||
|
[monster_example.rs](https://github.com/google/flatbuffers/blob/master/tests/rust_usage_test/bin/monster_example.rs)
|
||||||
|
|
||||||
|
It can be run by `cd`ing to the `rust_usage_test` directory and executing: `cargo run monster_example`.
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs}
|
||||||
|
extern crate flatbuffers;
|
||||||
|
|
||||||
|
#[allow(dead_code, unused_imports)]
|
||||||
|
#[path = "../../monster_test_generated.rs"]
|
||||||
|
mod monster_test_generated;
|
||||||
|
pub use monster_test_generated::my_game;
|
||||||
|
|
||||||
|
use std::io::Read;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let mut f = std::fs::File::open("../monsterdata_test.mon").unwrap();
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
f.read_to_end(&mut buf).expect("file reading failed");
|
||||||
|
|
||||||
|
let monster = my_game::example::get_root_as_monster(&buf[..]);
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
`monster` is of type `Monster`, and points to somewhere *inside* your
|
||||||
|
buffer (root object pointers are not the same as `buffer_pointer` !).
|
||||||
|
If you look in your generated header, you'll see it has
|
||||||
|
convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
|
||||||
|
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.rs}
|
||||||
|
println!("{}", monster.hp()); // `80`
|
||||||
|
println!("{}", monster.mana()); // default value of `150`
|
||||||
|
println!("{:?}", monster.name()); // Some("MyMonster")
|
||||||
|
}
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
*Note: That we never stored a `mana` value, so it will return the default.*
|
||||||
|
|
||||||
|
## Direct memory access
|
||||||
|
|
||||||
|
As you can see from the above examples, all elements in a buffer are
|
||||||
|
accessed through generated accessors. This is because everything is
|
||||||
|
stored in little endian format on all platforms (the accessor
|
||||||
|
performs a swap operation on big endian machines), and also because
|
||||||
|
the layout of things is generally not known to the user.
|
||||||
|
|
||||||
|
For structs, layout is deterministic and guaranteed to be the same
|
||||||
|
across platforms (scalars are aligned to their
|
||||||
|
own size, and structs themselves to their largest member), and you
|
||||||
|
are allowed to access this memory directly by using `safe_slice` and
|
||||||
|
on the reference to a struct, or even an array of structs.
|
||||||
|
|
||||||
|
To compute offsets to sub-elements of a struct, make sure they
|
||||||
|
are structs themselves, as then you can use the pointers to
|
||||||
|
figure out the offset without having to hardcode it. This is
|
||||||
|
handy for use of arrays of structs with calls like `glVertexAttribPointer`
|
||||||
|
in OpenGL or similar APIs.
|
||||||
|
|
||||||
|
It is important to note is that structs are still little endian on all
|
||||||
|
machines, so only use tricks like this if you can guarantee you're not
|
||||||
|
shipping on a big endian machine (using an `#[cfg(target_endian = "little")]`
|
||||||
|
attribute would be wise).
|
||||||
|
|
||||||
|
The special function `safe_slice` is implemented on Vector objects that are
|
||||||
|
represented in memory the same way as they are represented on the wire. This
|
||||||
|
function is always available on vectors of struct, bool, u8, and i8. It is
|
||||||
|
conditionally-compiled on little-endian systems for all the remaining scalar
|
||||||
|
types.
|
||||||
|
|
||||||
|
The FlatBufferBuilder function `create_vector_direct` is implemented for all
|
||||||
|
types that are endian-safe to write with a `memcpy`. It is the write-equivalent
|
||||||
|
of `safe_slice`.
|
||||||
|
|
||||||
|
## Access of untrusted buffers
|
||||||
|
|
||||||
|
The generated accessor functions access fields over offsets, which is
|
||||||
|
very quick. These offsets are used to index into Rust slices, so they are
|
||||||
|
bounds-checked by the Rust runtime. However, our Rust implementation may
|
||||||
|
change: we may convert access functions to use direct pointer dereferencing, to
|
||||||
|
improve lookup speed. As a result, users should not rely on the aforementioned
|
||||||
|
bounds-checking behavior.
|
||||||
|
|
||||||
|
When you're processing large amounts of data from a source you know (e.g.
|
||||||
|
your own generated data on disk), this is acceptable, but when reading
|
||||||
|
data from the network that can potentially have been modified by an
|
||||||
|
attacker, this is undesirable.
|
||||||
|
|
||||||
|
The C++ port provides a buffer verifier. At this time, Rust does not. Rust may
|
||||||
|
provide a verifier in a future version. In the meantime, Rust users can access
|
||||||
|
the buffer verifier generated by the C++ port through a foreign function
|
||||||
|
interface (FFI).
|
||||||
|
|
||||||
|
## Threading
|
||||||
|
|
||||||
|
Reading a FlatBuffer does not touch any memory outside the original buffer,
|
||||||
|
and is entirely read-only (all immutable), so is safe to access from multiple
|
||||||
|
threads even without synchronisation primitives.
|
||||||
|
|
||||||
|
Creating a FlatBuffer is not thread safe. All state related to building
|
||||||
|
a FlatBuffer is contained in a FlatBufferBuilder instance, and no memory
|
||||||
|
outside of it is touched. To make this thread safe, either do not
|
||||||
|
share instances of FlatBufferBuilder between threads (recommended), or
|
||||||
|
manually wrap it in synchronisation primitives. There's no automatic way to
|
||||||
|
accomplish this, by design, as we feel multithreaded construction
|
||||||
|
of a single buffer will be rare, and synchronisation overhead would be costly.
|
||||||
|
|
||||||
|
## Useful tools created by others
|
||||||
|
|
||||||
|
* [flatc-rust](https://github.com/frol/flatc-rust) - FlatBuffers compiler
|
||||||
|
(flatc) as API for transparent `.fbs` to `.rs` code-generation via Cargo
|
||||||
|
build scripts integration.
|
||||||
|
|
||||||
|
<br>
|
||||||
@@ -84,7 +84,7 @@ parent object, and use no virtual table).
|
|||||||
|
|
||||||
### Types
|
### Types
|
||||||
|
|
||||||
Built-in scalar types are
|
Built-in scalar types are
|
||||||
|
|
||||||
- 8 bit: `byte` (`int8`), `ubyte` (`uint8`), `bool`
|
- 8 bit: `byte` (`int8`), `ubyte` (`uint8`), `bool`
|
||||||
|
|
||||||
@@ -141,6 +141,9 @@ is `0`. As you can see in the enum declaration, you specify the underlying
|
|||||||
integral type of the enum with `:` (in this case `byte`), which then determines
|
integral type of the enum with `:` (in this case `byte`), which then determines
|
||||||
the type of any fields declared with this enum type.
|
the type of any fields declared with this enum type.
|
||||||
|
|
||||||
|
Only integer types are allowed, i.e. `byte`, `ubyte`, `short` `ushort`, `int`,
|
||||||
|
`uint`, `long` and `ulong`.
|
||||||
|
|
||||||
Typically, enum values should only ever be added, never removed (there is no
|
Typically, enum values should only ever be added, never removed (there is no
|
||||||
deprecation for enums). This requires code to handle forwards compatibility
|
deprecation for enums). This requires code to handle forwards compatibility
|
||||||
itself, by handling unknown enum values.
|
itself, by handling unknown enum values.
|
||||||
@@ -150,9 +153,23 @@ itself, by handling unknown enum values.
|
|||||||
Unions share a lot of properties with enums, but instead of new names
|
Unions share a lot of properties with enums, but instead of new names
|
||||||
for constants, you use names of tables. You can then declare
|
for constants, you use names of tables. You can then declare
|
||||||
a union field, which can hold a reference to any of those types, and
|
a union field, which can hold a reference to any of those types, and
|
||||||
additionally a hidden field with the suffix `_type` is generated that
|
additionally a field with the suffix `_type` is generated that holds
|
||||||
holds the corresponding enum value, allowing you to know which type to
|
the corresponding enum value, allowing you to know which type to cast
|
||||||
cast to at runtime.
|
to at runtime.
|
||||||
|
|
||||||
|
It's possible to give an alias name to a type union. This way a type can even be
|
||||||
|
used to mean different things depending on the name used:
|
||||||
|
|
||||||
|
table PointPosition { x:uint; y:uint; }
|
||||||
|
table MarkerPosition {}
|
||||||
|
union Position {
|
||||||
|
Start:MarkerPosition,
|
||||||
|
Point:PointPosition,
|
||||||
|
Finish:MarkerPosition
|
||||||
|
}
|
||||||
|
|
||||||
|
Unions contain a special `NONE` marker to denote that no value is stored so that
|
||||||
|
name cannot be used as an alias.
|
||||||
|
|
||||||
Unions are a good way to be able to send multiple message types as a FlatBuffer.
|
Unions are a good way to be able to send multiple message types as a FlatBuffer.
|
||||||
Note that because a union field is really two fields, it must always be
|
Note that because a union field is really two fields, it must always be
|
||||||
@@ -304,8 +321,11 @@ Current understood attributes:
|
|||||||
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
|
||||||
buffer is allocated with that alignment (which is not necessarily
|
buffer is allocated with that alignment (which is not necessarily
|
||||||
the case for buffers accessed directly inside a `FlatBufferBuilder`).
|
the case for buffers accessed directly inside a `FlatBufferBuilder`).
|
||||||
- `bit_flags` (on an enum): the values of this field indicate bits,
|
Note: currently not guaranteed to have an effect when used with
|
||||||
meaning that any value N specified in the schema will end up
|
`--object-api`, since that may allocate objects at alignments less than
|
||||||
|
what you specify with `force_align`.
|
||||||
|
- `bit_flags` (on an unsigned enum): the values of this field indicate bits,
|
||||||
|
meaning that any unsigned value N specified in the schema will end up
|
||||||
representing 1<<N, or if you don't specify values at all, you'll get
|
representing 1<<N, or if you don't specify values at all, you'll get
|
||||||
the sequence 1, 2, 4, 8, ...
|
the sequence 1, 2, 4, 8, ...
|
||||||
- `nested_flatbuffer: "table_name"` (on a field): this indicates that the field
|
- `nested_flatbuffer: "table_name"` (on a field): this indicates that the field
|
||||||
@@ -385,6 +405,31 @@ When parsing JSON, it recognizes the following escape codes in strings:
|
|||||||
It also generates these escape codes back again when generating JSON from a
|
It also generates these escape codes back again when generating JSON from a
|
||||||
binary representation.
|
binary representation.
|
||||||
|
|
||||||
|
When parsing numbers, the parser is more flexible than JSON.
|
||||||
|
A format of numeric literals is more close to the C/C++.
|
||||||
|
According to the [grammar](@ref flatbuffers_grammar), it accepts the following
|
||||||
|
numerical literals:
|
||||||
|
|
||||||
|
- An integer literal can have any number of leading zero `0` digits.
|
||||||
|
Unlike C/C++, the parser ignores a leading zero, not interpreting it as the
|
||||||
|
beginning of the octal number.
|
||||||
|
The numbers `[081, -00094]` are equal to `[81, -94]` decimal integers.
|
||||||
|
- The parser accepts unsigned and signed hexadecimal integer numbers.
|
||||||
|
For example: `[0x123, +0x45, -0x67]` are equal to `[291, 69, -103]` decimals.
|
||||||
|
- The format of float-point numbers is fully compatible with C/C++ format.
|
||||||
|
If a modern C++ compiler is used the parser accepts hexadecimal and special
|
||||||
|
float-point literals as well:
|
||||||
|
`[-1.0, 2., .3e0, 3.e4, 0x21.34p-5, -inf, nan]`.
|
||||||
|
The exponent suffix of hexadecimal float-point number is mandatory.
|
||||||
|
|
||||||
|
Extended float-point support was tested with:
|
||||||
|
- x64 Windows: `MSVC2015` and higher.
|
||||||
|
- x64 Linux: `LLVM 6.0`, `GCC 4.9` and higher.
|
||||||
|
|
||||||
|
- For compatibility with a JSON lint tool all numeric literals of scalar
|
||||||
|
fields can be wrapped to quoted string:
|
||||||
|
`"1", "2.0", "0x48A", "0x0C.0Ep-1", "-inf", "true"`.
|
||||||
|
|
||||||
## Guidelines
|
## Guidelines
|
||||||
|
|
||||||
### Efficiency
|
### Efficiency
|
||||||
|
|||||||
@@ -18,24 +18,25 @@ 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 | TS | C | PHP | Ruby
|
Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Dart | Lobster | Rust
|
||||||
------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ----
|
------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ------- | ------- | ----
|
||||||
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | WiP
|
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | Yes | Yes | Yes
|
||||||
JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No
|
JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No | Yes | No
|
||||||
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No
|
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No | No
|
||||||
Reflection | Yes | No | No | No | No | No | No | Basic | No | No
|
Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No | No
|
||||||
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No
|
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No | No
|
||||||
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | ?
|
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | Yes | Yes | Yes
|
||||||
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | ?
|
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | No | No | Yes
|
||||||
Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ?
|
Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ? | Great | Superb
|
||||||
Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | ?
|
Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | Yes | Yes | Yes
|
||||||
Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | ?
|
Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes
|
||||||
Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | ?
|
Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes
|
||||||
Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | ?
|
Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ?
|
||||||
Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | ?
|
Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ?
|
||||||
Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ?
|
Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ? | No | ?
|
||||||
Primary authors (github) | gwvo | gwvo | ev*/js*| rw | rw | evanw/ev* | kr | mik* | ch* | rw
|
Primary authors (github) | aard* | aard* | ev*/js*| rw | rw | evanw/ev* | kr* | mik* | ch* | dnfield | aard* | rw
|
||||||
|
|
||||||
|
* aard = aardappel (previously: gwvo)
|
||||||
* ev = evolutional
|
* ev = evolutional
|
||||||
* js = jonsimantov
|
* js = jonsimantov
|
||||||
* mik = mikkelfj
|
* mik = mikkelfj
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -17,7 +17,7 @@ documentation to build `flatc` and should be familiar with
|
|||||||
## FlatBuffers TypeScript library code location
|
## FlatBuffers TypeScript library code location
|
||||||
|
|
||||||
The code for the FlatBuffers TypeScript library can be found at
|
The code for the FlatBuffers TypeScript library can be found at
|
||||||
`flatbuffers/js` with typings available at @types/flatubffers.
|
`flatbuffers/js` with typings available at `@types/flatbuffers`.
|
||||||
|
|
||||||
## Testing the FlatBuffers TypeScript library
|
## Testing the FlatBuffers TypeScript library
|
||||||
|
|
||||||
|
|||||||
@@ -751,11 +751,16 @@ INPUT = "FlatBuffers.md" \
|
|||||||
"Schemas.md" \
|
"Schemas.md" \
|
||||||
"CppUsage.md" \
|
"CppUsage.md" \
|
||||||
"CUsage.md" \
|
"CUsage.md" \
|
||||||
|
"DartUsage.md" \
|
||||||
"GoUsage.md" \
|
"GoUsage.md" \
|
||||||
"JavaCsharpUsage.md" \
|
"JavaCsharpUsage.md" \
|
||||||
"JavaScriptUsage.md" \
|
"JavaScriptUsage.md" \
|
||||||
|
"TypeScriptUsage.md" \
|
||||||
"PHPUsage.md" \
|
"PHPUsage.md" \
|
||||||
"PythonUsage.md" \
|
"PythonUsage.md" \
|
||||||
|
"LuaUsage.md" \
|
||||||
|
"LobsterUsage.md" \
|
||||||
|
"RustUsage.md" \
|
||||||
"Support.md" \
|
"Support.md" \
|
||||||
"Benchmarks.md" \
|
"Benchmarks.md" \
|
||||||
"WhitePaper.md" \
|
"WhitePaper.md" \
|
||||||
@@ -774,6 +779,7 @@ INPUT = "FlatBuffers.md" \
|
|||||||
"../../net/FlatBuffers/FlatBufferBuilder.cs" \
|
"../../net/FlatBuffers/FlatBufferBuilder.cs" \
|
||||||
"../../include/flatbuffers/flatbuffers.h" \
|
"../../include/flatbuffers/flatbuffers.h" \
|
||||||
"../../go/builder.go"
|
"../../go/builder.go"
|
||||||
|
"../../rust/flatbuffers/src/builder.rs"
|
||||||
|
|
||||||
# This tag can be used to specify the character encoding of the source files
|
# This tag can be used to specify the character encoding of the source files
|
||||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||||
|
|||||||
@@ -39,6 +39,14 @@
|
|||||||
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"
|
||||||
title="Use in Python"/>
|
title="Use in Python"/>
|
||||||
|
<tab type="user" url="@ref flatbuffers_guide_use_dart"
|
||||||
|
title="Use in Dart"/>
|
||||||
|
<tab type="user" url="@ref flatbuffers_guide_use_lua"
|
||||||
|
title="Use in Lua"/>
|
||||||
|
<tab type="user" url="@ref flatbuffers_guide_use_lobster"
|
||||||
|
title="Use in Lobster"/>
|
||||||
|
<tab type="user" url="@ref flatbuffers_guide_use_rust"
|
||||||
|
title="Use in Rust"/>
|
||||||
<tab type="user" url="@ref flexbuffers"
|
<tab type="user" url="@ref flexbuffers"
|
||||||
title="Schema-less version"/>
|
title="Schema-less version"/>
|
||||||
<tab type="usergroup" url="" title="gRPC">
|
<tab type="usergroup" url="" title="gRPC">
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ type Builder struct {
|
|||||||
finished bool
|
finished bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fileIdentifierLength = 4
|
||||||
|
|
||||||
// NewBuilder initializes a Builder of size `initial_size`.
|
// NewBuilder initializes a Builder of size `initial_size`.
|
||||||
// The internal buffer is grown as needed.
|
// The internal buffer is grown as needed.
|
||||||
func NewBuilder(initialSize int) *Builder {
|
func NewBuilder(initialSize int) *Builder {
|
||||||
@@ -80,7 +82,6 @@ func (b *Builder) StartObject(numfields int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
b.objectEnd = b.Offset()
|
b.objectEnd = b.Offset()
|
||||||
b.minalign = 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteVtable serializes the vtable for the current object, if applicable.
|
// WriteVtable serializes the vtable for the current object, if applicable.
|
||||||
@@ -111,9 +112,10 @@ func (b *Builder) WriteVtable() (n UOffsetT) {
|
|||||||
existingVtable := UOffsetT(0)
|
existingVtable := UOffsetT(0)
|
||||||
|
|
||||||
// Trim vtable of trailing zeroes.
|
// Trim vtable of trailing zeroes.
|
||||||
i := len(b.vtable) - 1;
|
i := len(b.vtable) - 1
|
||||||
for ; i >= 0 && b.vtable[i] == 0; i-- {}
|
for ; i >= 0 && b.vtable[i] == 0; i-- {
|
||||||
b.vtable = b.vtable[:i + 1];
|
}
|
||||||
|
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
|
||||||
@@ -540,6 +542,23 @@ func (b *Builder) Slot(slotnum int) {
|
|||||||
b.vtable[slotnum] = UOffsetT(b.Offset())
|
b.vtable[slotnum] = UOffsetT(b.Offset())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FinishWithFileIdentifier finalizes a buffer, pointing to the given `rootTable`.
|
||||||
|
// as well as applys a file identifier
|
||||||
|
func (b *Builder) FinishWithFileIdentifier(rootTable UOffsetT, fid []byte) {
|
||||||
|
if fid == nil || len(fid) != fileIdentifierLength {
|
||||||
|
panic("incorrect file identifier length")
|
||||||
|
}
|
||||||
|
// In order to add a file identifier to the flatbuffer message, we need
|
||||||
|
// to prepare an alignment and file identifier length
|
||||||
|
b.Prep(b.minalign, SizeInt32+fileIdentifierLength)
|
||||||
|
for i := fileIdentifierLength - 1; i >= 0; i-- {
|
||||||
|
// place the file identifier
|
||||||
|
b.PlaceByte(fid[i])
|
||||||
|
}
|
||||||
|
// finish
|
||||||
|
b.Finish(rootTable)
|
||||||
|
}
|
||||||
|
|
||||||
// Finish finalizes a buffer, pointing to the given `rootTable`.
|
// Finish finalizes a buffer, pointing to the given `rootTable`.
|
||||||
func (b *Builder) Finish(rootTable UOffsetT) {
|
func (b *Builder) Finish(rootTable UOffsetT) {
|
||||||
b.assertNotNested()
|
b.assertNotNested()
|
||||||
|
|||||||
34
go/encode.go
34
go/encode.go
@@ -36,6 +36,7 @@ func GetUint8(buf []byte) (n uint8) {
|
|||||||
|
|
||||||
// GetUint16 decodes a little-endian uint16 from a byte slice.
|
// GetUint16 decodes a little-endian uint16 from a byte slice.
|
||||||
func GetUint16(buf []byte) (n uint16) {
|
func GetUint16(buf []byte) (n uint16) {
|
||||||
|
_ = buf[1] // Force one bounds check. See: golang.org/issue/14808
|
||||||
n |= uint16(buf[0])
|
n |= uint16(buf[0])
|
||||||
n |= uint16(buf[1]) << 8
|
n |= uint16(buf[1]) << 8
|
||||||
return
|
return
|
||||||
@@ -43,6 +44,7 @@ func GetUint16(buf []byte) (n uint16) {
|
|||||||
|
|
||||||
// GetUint32 decodes a little-endian uint32 from a byte slice.
|
// GetUint32 decodes a little-endian uint32 from a byte slice.
|
||||||
func GetUint32(buf []byte) (n uint32) {
|
func GetUint32(buf []byte) (n uint32) {
|
||||||
|
_ = buf[3] // Force one bounds check. See: golang.org/issue/14808
|
||||||
n |= uint32(buf[0])
|
n |= uint32(buf[0])
|
||||||
n |= uint32(buf[1]) << 8
|
n |= uint32(buf[1]) << 8
|
||||||
n |= uint32(buf[2]) << 16
|
n |= uint32(buf[2]) << 16
|
||||||
@@ -52,6 +54,7 @@ func GetUint32(buf []byte) (n uint32) {
|
|||||||
|
|
||||||
// GetUint64 decodes a little-endian uint64 from a byte slice.
|
// GetUint64 decodes a little-endian uint64 from a byte slice.
|
||||||
func GetUint64(buf []byte) (n uint64) {
|
func GetUint64(buf []byte) (n uint64) {
|
||||||
|
_ = buf[7] // Force one bounds check. See: golang.org/issue/14808
|
||||||
n |= uint64(buf[0])
|
n |= uint64(buf[0])
|
||||||
n |= uint64(buf[1]) << 8
|
n |= uint64(buf[1]) << 8
|
||||||
n |= uint64(buf[2]) << 16
|
n |= uint64(buf[2]) << 16
|
||||||
@@ -71,6 +74,7 @@ func GetInt8(buf []byte) (n int8) {
|
|||||||
|
|
||||||
// GetInt16 decodes a little-endian int16 from a byte slice.
|
// GetInt16 decodes a little-endian int16 from a byte slice.
|
||||||
func GetInt16(buf []byte) (n int16) {
|
func GetInt16(buf []byte) (n int16) {
|
||||||
|
_ = buf[1] // Force one bounds check. See: golang.org/issue/14808
|
||||||
n |= int16(buf[0])
|
n |= int16(buf[0])
|
||||||
n |= int16(buf[1]) << 8
|
n |= int16(buf[1]) << 8
|
||||||
return
|
return
|
||||||
@@ -78,6 +82,7 @@ func GetInt16(buf []byte) (n int16) {
|
|||||||
|
|
||||||
// GetInt32 decodes a little-endian int32 from a byte slice.
|
// GetInt32 decodes a little-endian int32 from a byte slice.
|
||||||
func GetInt32(buf []byte) (n int32) {
|
func GetInt32(buf []byte) (n int32) {
|
||||||
|
_ = buf[3] // Force one bounds check. See: golang.org/issue/14808
|
||||||
n |= int32(buf[0])
|
n |= int32(buf[0])
|
||||||
n |= int32(buf[1]) << 8
|
n |= int32(buf[1]) << 8
|
||||||
n |= int32(buf[2]) << 16
|
n |= int32(buf[2]) << 16
|
||||||
@@ -87,6 +92,7 @@ func GetInt32(buf []byte) (n int32) {
|
|||||||
|
|
||||||
// GetInt64 decodes a little-endian int64 from a byte slice.
|
// GetInt64 decodes a little-endian int64 from a byte slice.
|
||||||
func GetInt64(buf []byte) (n int64) {
|
func GetInt64(buf []byte) (n int64) {
|
||||||
|
_ = buf[7] // Force one bounds check. See: golang.org/issue/14808
|
||||||
n |= int64(buf[0])
|
n |= int64(buf[0])
|
||||||
n |= int64(buf[1]) << 8
|
n |= int64(buf[1]) << 8
|
||||||
n |= int64(buf[2]) << 16
|
n |= int64(buf[2]) << 16
|
||||||
@@ -145,12 +151,14 @@ func WriteUint8(buf []byte, n uint8) {
|
|||||||
|
|
||||||
// WriteUint16 encodes a little-endian uint16 into a byte slice.
|
// WriteUint16 encodes a little-endian uint16 into a byte slice.
|
||||||
func WriteUint16(buf []byte, n uint16) {
|
func WriteUint16(buf []byte, n uint16) {
|
||||||
|
_ = buf[1] // Force one bounds check. See: golang.org/issue/14808
|
||||||
buf[0] = byte(n)
|
buf[0] = byte(n)
|
||||||
buf[1] = byte(n >> 8)
|
buf[1] = byte(n >> 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteUint32 encodes a little-endian uint32 into a byte slice.
|
// WriteUint32 encodes a little-endian uint32 into a byte slice.
|
||||||
func WriteUint32(buf []byte, n uint32) {
|
func WriteUint32(buf []byte, n uint32) {
|
||||||
|
_ = buf[3] // Force one bounds check. See: golang.org/issue/14808
|
||||||
buf[0] = byte(n)
|
buf[0] = byte(n)
|
||||||
buf[1] = byte(n >> 8)
|
buf[1] = byte(n >> 8)
|
||||||
buf[2] = byte(n >> 16)
|
buf[2] = byte(n >> 16)
|
||||||
@@ -159,9 +167,15 @@ func WriteUint32(buf []byte, n uint32) {
|
|||||||
|
|
||||||
// WriteUint64 encodes a little-endian uint64 into a byte slice.
|
// WriteUint64 encodes a little-endian uint64 into a byte slice.
|
||||||
func WriteUint64(buf []byte, n uint64) {
|
func WriteUint64(buf []byte, n uint64) {
|
||||||
for i := uint(0); i < uint(SizeUint64); i++ {
|
_ = buf[7] // Force one bounds check. See: golang.org/issue/14808
|
||||||
buf[i] = byte(n >> (i * 8))
|
buf[0] = byte(n)
|
||||||
}
|
buf[1] = byte(n >> 8)
|
||||||
|
buf[2] = byte(n >> 16)
|
||||||
|
buf[3] = byte(n >> 24)
|
||||||
|
buf[4] = byte(n >> 32)
|
||||||
|
buf[5] = byte(n >> 40)
|
||||||
|
buf[6] = byte(n >> 48)
|
||||||
|
buf[7] = byte(n >> 56)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteInt8 encodes a little-endian int8 into a byte slice.
|
// WriteInt8 encodes a little-endian int8 into a byte slice.
|
||||||
@@ -171,12 +185,14 @@ func WriteInt8(buf []byte, n int8) {
|
|||||||
|
|
||||||
// WriteInt16 encodes a little-endian int16 into a byte slice.
|
// WriteInt16 encodes a little-endian int16 into a byte slice.
|
||||||
func WriteInt16(buf []byte, n int16) {
|
func WriteInt16(buf []byte, n int16) {
|
||||||
|
_ = buf[1] // Force one bounds check. See: golang.org/issue/14808
|
||||||
buf[0] = byte(n)
|
buf[0] = byte(n)
|
||||||
buf[1] = byte(n >> 8)
|
buf[1] = byte(n >> 8)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteInt32 encodes a little-endian int32 into a byte slice.
|
// WriteInt32 encodes a little-endian int32 into a byte slice.
|
||||||
func WriteInt32(buf []byte, n int32) {
|
func WriteInt32(buf []byte, n int32) {
|
||||||
|
_ = buf[3] // Force one bounds check. See: golang.org/issue/14808
|
||||||
buf[0] = byte(n)
|
buf[0] = byte(n)
|
||||||
buf[1] = byte(n >> 8)
|
buf[1] = byte(n >> 8)
|
||||||
buf[2] = byte(n >> 16)
|
buf[2] = byte(n >> 16)
|
||||||
@@ -185,9 +201,15 @@ func WriteInt32(buf []byte, n int32) {
|
|||||||
|
|
||||||
// WriteInt64 encodes a little-endian int64 into a byte slice.
|
// WriteInt64 encodes a little-endian int64 into a byte slice.
|
||||||
func WriteInt64(buf []byte, n int64) {
|
func WriteInt64(buf []byte, n int64) {
|
||||||
for i := uint(0); i < uint(SizeInt64); i++ {
|
_ = buf[7] // Force one bounds check. See: golang.org/issue/14808
|
||||||
buf[i] = byte(n >> (i * 8))
|
buf[0] = byte(n)
|
||||||
}
|
buf[1] = byte(n >> 8)
|
||||||
|
buf[2] = byte(n >> 16)
|
||||||
|
buf[3] = byte(n >> 24)
|
||||||
|
buf[4] = byte(n >> 32)
|
||||||
|
buf[5] = byte(n >> 40)
|
||||||
|
buf[6] = byte(n >> 48)
|
||||||
|
buf[7] = byte(n >> 56)
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteFloat32 encodes a little-endian float32 into a byte slice.
|
// WriteFloat32 encodes a little-endian float32 into a byte slice.
|
||||||
|
|||||||
@@ -9,3 +9,23 @@ from GRPC, and work with both the Protobuf and FlatBuffers code generator.
|
|||||||
the GRPC libraries for this to compile. This test will build using the
|
the GRPC libraries for this to compile. This test will build using the
|
||||||
`FLATBUFFERS_BUILD_GRPCTEST` option to the main FlatBuffers CMake project.
|
`FLATBUFFERS_BUILD_GRPCTEST` option to the main FlatBuffers CMake project.
|
||||||
|
|
||||||
|
## Building Flatbuffers with gRPC
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
1. Download, build and install gRPC. See [instructions](https://github.com/grpc/grpc/tree/master/src/cpp).
|
||||||
|
* Lets say your gRPC clone is at `/your/path/to/grpc_repo`.
|
||||||
|
* Install gRPC in a custom directory by running `make install prefix=/your/path/to/grpc_repo/install`.
|
||||||
|
2. `export GRPC_INSTALL_PATH=/your/path/to/grpc_repo/install`
|
||||||
|
3. `export PROTOBUF_DOWNLOAD_PATH=/your/path/to/grpc_repo/third_party/protobuf`
|
||||||
|
4. `mkdir build ; cd build`
|
||||||
|
5. `cmake -DFLATBUFFERS_BUILD_GRPCTEST=ON -DGRPC_INSTALL_PATH=${GRPC_INSTALL_PATH} -DPROTOBUF_DOWNLOAD_PATH=${PROTOBUF_DOWNLOAD_PATH} ..`
|
||||||
|
6. `make`
|
||||||
|
|
||||||
|
## Running FlatBuffer gRPC tests
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
1. `ln -s ${GRPC_INSTALL_PATH}/lib/libgrpc++_unsecure.so.6 ${GRPC_INSTALL_PATH}/lib/libgrpc++_unsecure.so.1`
|
||||||
|
2. `export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${GRPC_INSTALL_PATH}/lib`
|
||||||
|
3. `make test ARGS=-V`
|
||||||
|
|||||||
21
grpc/build_grpc.sh
Executable file
21
grpc/build_grpc.sh
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
grpc_1_15_1_githash=1a60e6971f428323245a930031ad267bb3142ba4
|
||||||
|
|
||||||
|
function build_grpc () {
|
||||||
|
git clone https://github.com/grpc/grpc.git google/grpc
|
||||||
|
cd google/grpc
|
||||||
|
git checkout ${grpc_1_15_1_githash}
|
||||||
|
git submodule update --init
|
||||||
|
make
|
||||||
|
make install prefix=`pwd`/install
|
||||||
|
if [ ! -f ${GRPC_INSTALL_PATH}/lib/libgrpc++_unsecure.so.1 ]; then
|
||||||
|
ln -s ${GRPC_INSTALL_PATH}/lib/libgrpc++_unsecure.so.6 ${GRPC_INSTALL_PATH}/lib/libgrpc++_unsecure.so.1
|
||||||
|
fi
|
||||||
|
cd ../..
|
||||||
|
}
|
||||||
|
|
||||||
|
GRPC_INSTALL_PATH=`pwd`/google/grpc/install
|
||||||
|
PROTOBUF_DOWNLOAD_PATH=`pwd`/google/grpc/third_party/protobuf
|
||||||
|
|
||||||
|
build_grpc
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.google.flatbuffers</groupId>
|
<groupId>com.google.flatbuffers</groupId>
|
||||||
<artifactId>flatbuffers-parent</artifactId>
|
<artifactId>flatbuffers-parent</artifactId>
|
||||||
<version>1.8.0</version>
|
<version>1.11.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>flatbuffers-java-grpc</artifactId>
|
<artifactId>flatbuffers-java-grpc</artifactId>
|
||||||
<name>${project.artifactId}</name>
|
<name>${project.artifactId}</name>
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
</developer>
|
</developer>
|
||||||
</developers>
|
</developers>
|
||||||
<properties>
|
<properties>
|
||||||
<gRPC.version>1.8.0</gRPC.version>
|
<gRPC.version>1.11.0</gRPC.version>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<groupId>com.google.flatbuffers</groupId>
|
<groupId>com.google.flatbuffers</groupId>
|
||||||
<artifactId>flatbuffers-parent</artifactId>
|
<artifactId>flatbuffers-parent</artifactId>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<version>1.8.0</version>
|
<version>1.11.0</version>
|
||||||
<name>flatbuffers-parent</name>
|
<name>flatbuffers-parent</name>
|
||||||
<description>parent pom for flatbuffers java artifacts</description>
|
<description>parent pom for flatbuffers java artifacts</description>
|
||||||
<properties>
|
<properties>
|
||||||
@@ -201,7 +201,7 @@
|
|||||||
</build>
|
</build>
|
||||||
|
|
||||||
<modules>
|
<modules>
|
||||||
<!-- consider the benefits of publishing all maven artifacts in this project
|
<!-- consider the benefits of publishing all maven artifacts in this project
|
||||||
|
|
||||||
<module>flatbuffers-compiler</module>
|
<module>flatbuffers-compiler</module>
|
||||||
<module>flatbuffers-java</module>
|
<module>flatbuffers-java</module>
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ void GenerateImports(grpc_generator::File *file, grpc_generator::Printer *printe
|
|||||||
}
|
}
|
||||||
printer->Print("import (\n");
|
printer->Print("import (\n");
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
printer->Print(vars, "$context$ \"golang.org/x/net/context\"\n");
|
printer->Print(vars, "$context$ \"context\"\n");
|
||||||
printer->Print(vars, "$grpc$ \"google.golang.org/grpc\"\n");
|
printer->Print(vars, "$grpc$ \"google.golang.org/grpc\"\n");
|
||||||
printer->Outdent();
|
printer->Outdent();
|
||||||
printer->Print(")\n\n");
|
printer->Print(")\n\n");
|
||||||
@@ -110,7 +110,7 @@ void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::
|
|||||||
vars["Method"] = exportName(method->name());
|
vars["Method"] = exportName(method->name());
|
||||||
vars["Request"] = method->get_input_type_name();
|
vars["Request"] = method->get_input_type_name();
|
||||||
vars["Response"] = (vars["CustomMethodIO"] == "") ? method->get_output_type_name() : vars["CustomMethodIO"];
|
vars["Response"] = (vars["CustomMethodIO"] == "") ? method->get_output_type_name() : vars["CustomMethodIO"];
|
||||||
vars["FullMethodName"] = "/" + vars["Package"] + "." + vars["Service"] + "/" + vars["Method"];
|
vars["FullMethodName"] = "/" + vars["ServicePrefix"] + "." + vars["Service"] + "/" + vars["Method"];
|
||||||
vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
|
vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
|
||||||
if (method->NoStreaming()) {
|
if (method->NoStreaming()) {
|
||||||
printer->Print(vars, "func $Handler$(srv interface{}, ctx $context$.Context,\n\tdec func(interface{}) error, interceptor $grpc$.UnaryServerInterceptor) (interface{}, error) {\n");
|
printer->Print(vars, "func $Handler$(srv interface{}, ctx $context$.Context,\n\tdec func(interface{}) error, interceptor $grpc$.UnaryServerInterceptor) (interface{}, error) {\n");
|
||||||
@@ -223,7 +223,7 @@ void GenerateClientMethod(const grpc_generator::Method *method, grpc_generator::
|
|||||||
vars["Method"] = exportName(method->name());
|
vars["Method"] = exportName(method->name());
|
||||||
vars["Request"] = (vars["CustomMethodIO"] == "") ? method->get_input_type_name() : vars["CustomMethodIO"];
|
vars["Request"] = (vars["CustomMethodIO"] == "") ? method->get_input_type_name() : vars["CustomMethodIO"];
|
||||||
vars["Response"] = method->get_output_type_name();
|
vars["Response"] = method->get_output_type_name();
|
||||||
vars["FullMethodName"] = "/" + vars["Package"] + "." + vars["Service"] + "/" + vars["Method"];
|
vars["FullMethodName"] = "/" + vars["ServicePrefix"] + "." + vars["Service"] + "/" + vars["Method"];
|
||||||
if (method->NoStreaming()) {
|
if (method->NoStreaming()) {
|
||||||
printer->Print(vars, "out := new($Response$)\n");
|
printer->Print(vars, "out := new($Response$)\n");
|
||||||
printer->Print(vars, "err := $grpc$.Invoke(ctx, \"$FullMethodName$\", in, out, c.cc, opts...)\n");
|
printer->Print(vars, "err := $grpc$.Invoke(ctx, \"$FullMethodName$\", in, out, c.cc, opts...)\n");
|
||||||
@@ -374,7 +374,7 @@ void GenerateService(const grpc_generator::Service *service, grpc_generator::Pri
|
|||||||
//Service Descriptor
|
//Service Descriptor
|
||||||
printer->Print(vars, "var $ServiceDesc$ = $grpc$.ServiceDesc{\n");
|
printer->Print(vars, "var $ServiceDesc$ = $grpc$.ServiceDesc{\n");
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
printer->Print(vars, "ServiceName: \"$Package$.$Service$\",\n");
|
printer->Print(vars, "ServiceName: \"$ServicePrefix$.$Service$\",\n");
|
||||||
printer->Print(vars, "HandlerType: (*$Service$Server)(nil),\n");
|
printer->Print(vars, "HandlerType: (*$Service$Server)(nil),\n");
|
||||||
printer->Print(vars, "Methods: []$grpc$.MethodDesc{\n");
|
printer->Print(vars, "Methods: []$grpc$.MethodDesc{\n");
|
||||||
printer->Indent();
|
printer->Indent();
|
||||||
@@ -433,6 +433,7 @@ grpc::string GenerateServiceSource(grpc_generator::File *file,
|
|||||||
auto printer = p.get();
|
auto printer = p.get();
|
||||||
std::map<grpc::string, grpc::string> vars;
|
std::map<grpc::string, grpc::string> vars;
|
||||||
vars["Package"] = parameters->package_name;
|
vars["Package"] = parameters->package_name;
|
||||||
|
vars["ServicePrefix"] = parameters->service_prefix;
|
||||||
vars["grpc"] = "grpc";
|
vars["grpc"] = "grpc";
|
||||||
vars["context"] = "context";
|
vars["context"] = "context";
|
||||||
GenerateImports(file, printer, vars);
|
GenerateImports(file, printer, vars);
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ struct Parameters {
|
|||||||
|
|
||||||
//Package name for the service
|
//Package name for the service
|
||||||
grpc::string package_name;
|
grpc::string package_name;
|
||||||
|
|
||||||
|
//Prefix for RPC Calls
|
||||||
|
grpc::string service_prefix;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return the source of the generated service file.
|
// Return the source of the generated service file.
|
||||||
|
|||||||
@@ -37,9 +37,6 @@
|
|||||||
#define XSTR(s) STR(s)
|
#define XSTR(s) STR(s)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef FALLTHROUGH_INTENDED
|
|
||||||
#define FALLTHROUGH_INTENDED
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef grpc_generator::Printer Printer;
|
typedef grpc_generator::Printer Printer;
|
||||||
typedef std::map<grpc::string, grpc::string> VARS;
|
typedef std::map<grpc::string, grpc::string> VARS;
|
||||||
@@ -72,13 +69,14 @@ void GenerateImports(grpc_generator::File* file,
|
|||||||
// - remove embedded underscores & capitalize the following letter
|
// - remove embedded underscores & capitalize the following letter
|
||||||
static string MixedLower(const string& word) {
|
static string MixedLower(const string& word) {
|
||||||
string w;
|
string w;
|
||||||
w += (string::value_type)tolower(word[0]);
|
w += static_cast<string::value_type>(tolower(word[0]));
|
||||||
bool after_underscore = false;
|
bool after_underscore = false;
|
||||||
for (size_t i = 1; i < word.length(); ++i) {
|
for (size_t i = 1; i < word.length(); ++i) {
|
||||||
if (word[i] == '_') {
|
if (word[i] == '_') {
|
||||||
after_underscore = true;
|
after_underscore = true;
|
||||||
} else {
|
} else {
|
||||||
w += after_underscore ? (string::value_type)toupper(word[i]) : word[i];
|
w += after_underscore ? static_cast<string::value_type>(toupper(word[i]))
|
||||||
|
: word[i];
|
||||||
after_underscore = false;
|
after_underscore = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,7 +90,7 @@ static string MixedLower(const string& word) {
|
|||||||
static string ToAllUpperCase(const string& word) {
|
static string ToAllUpperCase(const string& word) {
|
||||||
string w;
|
string w;
|
||||||
for (size_t i = 0; i < word.length(); ++i) {
|
for (size_t i = 0; i < word.length(); ++i) {
|
||||||
w += (string::value_type)toupper(word[i]);
|
w += static_cast<string::value_type>(toupper(word[i]));
|
||||||
if ((i < word.length() - 1) && islower(word[i]) && isupper(word[i + 1])) {
|
if ((i < word.length() - 1) && islower(word[i]) && isupper(word[i + 1])) {
|
||||||
w += '_';
|
w += '_';
|
||||||
}
|
}
|
||||||
@@ -345,8 +343,8 @@ static void PrintMethodFields(Printer* p, VARS& vars,
|
|||||||
|
|
||||||
for (int i = 0; i < service->method_count(); ++i) {
|
for (int i = 0; i < service->method_count(); ++i) {
|
||||||
auto method = service->method(i);
|
auto method = service->method(i);
|
||||||
vars["arg_in_id"] = to_string((long)2 * i); //trying to make msvc 10 happy
|
vars["arg_in_id"] = to_string(2L * i); //trying to make msvc 10 happy
|
||||||
vars["arg_out_id"] = to_string((long)2 * i + 1);
|
vars["arg_out_id"] = to_string(2L * i + 1);
|
||||||
vars["method_name"] = method->name();
|
vars["method_name"] = method->name();
|
||||||
vars["input_type_name"] = method->get_input_type_name();
|
vars["input_type_name"] = method->get_input_type_name();
|
||||||
vars["output_type_name"] = method->get_output_type_name();
|
vars["output_type_name"] = method->get_output_type_name();
|
||||||
@@ -355,8 +353,8 @@ static void PrintMethodFields(Printer* p, VARS& vars,
|
|||||||
vars["method_field_name"] = MethodPropertiesFieldName(method.get());
|
vars["method_field_name"] = MethodPropertiesFieldName(method.get());
|
||||||
vars["method_new_field_name"] = MethodPropertiesGetterName(method.get());
|
vars["method_new_field_name"] = MethodPropertiesGetterName(method.get());
|
||||||
vars["method_method_name"] = MethodPropertiesGetterName(method.get());
|
vars["method_method_name"] = MethodPropertiesGetterName(method.get());
|
||||||
bool client_streaming = method->ClientStreaming();
|
bool client_streaming = method->ClientStreaming() || method->BidiStreaming();
|
||||||
bool server_streaming = method->ServerStreaming();
|
bool server_streaming = method->ServerStreaming() || method->BidiStreaming();
|
||||||
if (client_streaming) {
|
if (client_streaming) {
|
||||||
if (server_streaming) {
|
if (server_streaming) {
|
||||||
vars["method_type"] = "BIDI_STREAMING";
|
vars["method_type"] = "BIDI_STREAMING";
|
||||||
@@ -478,7 +476,7 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
|
|||||||
break;
|
break;
|
||||||
case BLOCKING_CLIENT_INTERFACE:
|
case BLOCKING_CLIENT_INTERFACE:
|
||||||
interface = true;
|
interface = true;
|
||||||
FALLTHROUGH_INTENDED; // fallthrough
|
FLATBUFFERS_FALLTHROUGH(); // fall thru
|
||||||
case BLOCKING_CLIENT_IMPL:
|
case BLOCKING_CLIENT_IMPL:
|
||||||
call_type = BLOCKING_CALL;
|
call_type = BLOCKING_CALL;
|
||||||
stub_name += "BlockingStub";
|
stub_name += "BlockingStub";
|
||||||
@@ -486,7 +484,7 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
|
|||||||
break;
|
break;
|
||||||
case FUTURE_CLIENT_INTERFACE:
|
case FUTURE_CLIENT_INTERFACE:
|
||||||
interface = true;
|
interface = true;
|
||||||
FALLTHROUGH_INTENDED; // fallthrough
|
FLATBUFFERS_FALLTHROUGH(); // fall thru
|
||||||
case FUTURE_CLIENT_IMPL:
|
case FUTURE_CLIENT_IMPL:
|
||||||
call_type = FUTURE_CALL;
|
call_type = FUTURE_CALL;
|
||||||
stub_name += "FutureStub";
|
stub_name += "FutureStub";
|
||||||
@@ -548,8 +546,8 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
|
|||||||
vars["output_type"] = JavaClassName(vars, method->get_output_type_name());
|
vars["output_type"] = JavaClassName(vars, method->get_output_type_name());
|
||||||
vars["lower_method_name"] = LowerMethodName(&*method);
|
vars["lower_method_name"] = LowerMethodName(&*method);
|
||||||
vars["method_method_name"] = MethodPropertiesGetterName(&*method);
|
vars["method_method_name"] = MethodPropertiesGetterName(&*method);
|
||||||
bool client_streaming = method->ClientStreaming();
|
bool client_streaming = method->ClientStreaming() || method->BidiStreaming();
|
||||||
bool server_streaming = method->ServerStreaming();
|
bool server_streaming = method->ServerStreaming() || method->BidiStreaming();
|
||||||
|
|
||||||
if (call_type == BLOCKING_CALL && client_streaming) {
|
if (call_type == BLOCKING_CALL && client_streaming) {
|
||||||
// Blocking client interface with client streaming is not available
|
// Blocking client interface with client streaming is not available
|
||||||
@@ -759,7 +757,7 @@ static void PrintMethodHandlerClass(Printer* p, VARS& vars,
|
|||||||
|
|
||||||
for (int i = 0; i < service->method_count(); ++i) {
|
for (int i = 0; i < service->method_count(); ++i) {
|
||||||
auto method = service->method(i);
|
auto method = service->method(i);
|
||||||
if (method->ClientStreaming()) {
|
if (method->ClientStreaming() || method->BidiStreaming()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
vars["method_id_name"] = MethodIdFieldName(&*method);
|
vars["method_id_name"] = MethodIdFieldName(&*method);
|
||||||
@@ -793,7 +791,7 @@ static void PrintMethodHandlerClass(Printer* p, VARS& vars,
|
|||||||
|
|
||||||
for (int i = 0; i < service->method_count(); ++i) {
|
for (int i = 0; i < service->method_count(); ++i) {
|
||||||
auto method = service->method(i);
|
auto method = service->method(i);
|
||||||
if (!method->ClientStreaming()) {
|
if (!(method->ClientStreaming() || method->BidiStreaming())) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
vars["method_id_name"] = MethodIdFieldName(&*method);
|
vars["method_id_name"] = MethodIdFieldName(&*method);
|
||||||
@@ -929,8 +927,8 @@ static void PrintBindServiceMethodBody(Printer* p, VARS& vars,
|
|||||||
vars["input_type"] = JavaClassName(vars, method->get_input_type_name());
|
vars["input_type"] = JavaClassName(vars, method->get_input_type_name());
|
||||||
vars["output_type"] = JavaClassName(vars, method->get_output_type_name());
|
vars["output_type"] = JavaClassName(vars, method->get_output_type_name());
|
||||||
vars["method_id_name"] = MethodIdFieldName(&*method);
|
vars["method_id_name"] = MethodIdFieldName(&*method);
|
||||||
bool client_streaming = method->ClientStreaming();
|
bool client_streaming = method->ClientStreaming() || method->BidiStreaming();
|
||||||
bool server_streaming = method->ServerStreaming();
|
bool server_streaming = method->ServerStreaming() || method->BidiStreaming();
|
||||||
if (client_streaming) {
|
if (client_streaming) {
|
||||||
if (server_streaming) {
|
if (server_streaming) {
|
||||||
vars["calls_method"] = "asyncBidiStreamingCall";
|
vars["calls_method"] = "asyncBidiStreamingCall";
|
||||||
|
|||||||
@@ -65,8 +65,6 @@ class LogHelper {
|
|||||||
// Abort the program after logging the mesage.
|
// Abort the program after logging the mesage.
|
||||||
#define GRPC_CODEGEN_FAIL GRPC_CODEGEN_CHECK(false)
|
#define GRPC_CODEGEN_FAIL GRPC_CODEGEN_CHECK(false)
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
namespace grpc_java_generator {
|
namespace grpc_java_generator {
|
||||||
struct Parameters {
|
struct Parameters {
|
||||||
// //Defines the custom parameter types for methods
|
// //Defines the custom parameter types for methods
|
||||||
|
|||||||
42
grpc/tests/GameFactory.java
Normal file
42
grpc/tests/GameFactory.java
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import MyGame.Example.Monster;
|
||||||
|
import MyGame.Example.Stat;
|
||||||
|
import com.google.flatbuffers.FlatBufferBuilder;
|
||||||
|
|
||||||
|
class GameFactory {
|
||||||
|
public static Monster createMonster(String monsterName, short nestedMonsterHp, short nestedMonsterMana) {
|
||||||
|
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||||
|
|
||||||
|
int name_offset = builder.createString(monsterName);
|
||||||
|
Monster.startMonster(builder);
|
||||||
|
Monster.addName(builder, name_offset);
|
||||||
|
Monster.addHp(builder, nestedMonsterHp);
|
||||||
|
Monster.addMana(builder, nestedMonsterMana);
|
||||||
|
int monster_offset = Monster.endMonster(builder);
|
||||||
|
Monster.finishMonsterBuffer(builder, monster_offset);
|
||||||
|
|
||||||
|
ByteBuffer buffer = builder.dataBuffer();
|
||||||
|
Monster monster = Monster.getRootAsMonster(buffer);
|
||||||
|
return monster;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Monster createMonsterFromStat(Stat stat, int seqNo) {
|
||||||
|
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||||
|
int name_offset = builder.createString(stat.id() + " No." + seqNo);
|
||||||
|
Monster.startMonster(builder);
|
||||||
|
Monster.addName(builder, name_offset);
|
||||||
|
int monster_offset = Monster.endMonster(builder);
|
||||||
|
Monster.finishMonsterBuffer(builder, monster_offset);
|
||||||
|
Monster monster = Monster.getRootAsMonster(builder.dataBuffer());
|
||||||
|
return monster;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Stat createStat(String greeting, long val, int count) {
|
||||||
|
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||||
|
int statOffset = Stat.createStat(builder, builder.createString(greeting), val, count);
|
||||||
|
builder.finish(statOffset);
|
||||||
|
Stat stat = Stat.getRootAsStat(builder.dataBuffer());
|
||||||
|
return stat;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -22,21 +22,32 @@ import io.grpc.ManagedChannel;
|
|||||||
import io.grpc.ManagedChannelBuilder;
|
import io.grpc.ManagedChannelBuilder;
|
||||||
import io.grpc.Server;
|
import io.grpc.Server;
|
||||||
import io.grpc.ServerBuilder;
|
import io.grpc.ServerBuilder;
|
||||||
|
import io.grpc.stub.StreamObserver;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.lang.InterruptedException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Demonstrates basic client-server interaction using grpc-java over netty.
|
* Demonstrates basic client-server interaction using grpc-java over netty.
|
||||||
*/
|
*/
|
||||||
public class JavaGrpcTest {
|
public class JavaGrpcTest {
|
||||||
static final String BIG_MONSTER_NAME = "big-monster";
|
static final String BIG_MONSTER_NAME = "Cyberdemon";
|
||||||
static final short nestedMonsterHp = 600;
|
static final short nestedMonsterHp = 600;
|
||||||
static final short nestedMonsterMana = 1024;
|
static final short nestedMonsterMana = 1024;
|
||||||
static final int numStreamedMsgs = 10;
|
static final int numStreamedMsgs = 10;
|
||||||
|
static final int timeoutMs = 3000;
|
||||||
|
static Server server;
|
||||||
|
static ManagedChannel channel;
|
||||||
|
static MonsterStorageGrpc.MonsterStorageBlockingStub blockingStub;
|
||||||
|
static MonsterStorageGrpc.MonsterStorageStub asyncStub;
|
||||||
|
|
||||||
static class MyService extends MonsterStorageGrpc.MonsterStorageImplBase {
|
static class MyService extends MonsterStorageGrpc.MonsterStorageImplBase {
|
||||||
@Override
|
@Override
|
||||||
@@ -46,10 +57,7 @@ public class JavaGrpcTest {
|
|||||||
Assert.assertEquals(request.mana(), nestedMonsterMana);
|
Assert.assertEquals(request.mana(), nestedMonsterMana);
|
||||||
System.out.println("Received store request from " + request.name());
|
System.out.println("Received store request from " + request.name());
|
||||||
// Create a response from the incoming request name.
|
// Create a response from the incoming request name.
|
||||||
FlatBufferBuilder builder = new FlatBufferBuilder();
|
Stat stat = GameFactory.createStat("Hello " + request.name(), 100, 10);
|
||||||
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.onNext(stat);
|
||||||
responseObserver.onCompleted();
|
responseObserver.onCompleted();
|
||||||
}
|
}
|
||||||
@@ -58,55 +66,101 @@ public class JavaGrpcTest {
|
|||||||
public void retrieve(Stat request, io.grpc.stub.StreamObserver<Monster> responseObserver) {
|
public void retrieve(Stat request, io.grpc.stub.StreamObserver<Monster> responseObserver) {
|
||||||
// Create 10 monsters for streaming response.
|
// Create 10 monsters for streaming response.
|
||||||
for (int i=0; i<numStreamedMsgs; i++) {
|
for (int i=0; i<numStreamedMsgs; i++) {
|
||||||
FlatBufferBuilder builder = new FlatBufferBuilder();
|
Monster monster = GameFactory.createMonsterFromStat(request, i);
|
||||||
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.onNext(monster);
|
||||||
}
|
}
|
||||||
responseObserver.onCompleted();
|
responseObserver.onCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamObserver<Monster> getMaxHitPoint(final StreamObserver<Stat> responseObserver) {
|
||||||
|
return computeMinMax(responseObserver, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StreamObserver<Monster> getMinMaxHitPoints(final StreamObserver<Stat> responseObserver) {
|
||||||
|
return computeMinMax(responseObserver, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private StreamObserver<Monster> computeMinMax(final StreamObserver<Stat> responseObserver, final boolean includeMin) {
|
||||||
|
final AtomicInteger maxHp = new AtomicInteger(Integer.MIN_VALUE);
|
||||||
|
final AtomicReference<String> maxHpMonsterName = new AtomicReference<String>();
|
||||||
|
final AtomicInteger maxHpCount = new AtomicInteger();
|
||||||
|
|
||||||
|
final AtomicInteger minHp = new AtomicInteger(Integer.MAX_VALUE);
|
||||||
|
final AtomicReference<String> minHpMonsterName = new AtomicReference<String>();
|
||||||
|
final AtomicInteger minHpCount = new AtomicInteger();
|
||||||
|
|
||||||
|
return new StreamObserver<Monster>() {
|
||||||
|
public void onNext(Monster monster) {
|
||||||
|
if (monster.hp() > maxHp.get()) {
|
||||||
|
// Found a monster of higher hit points.
|
||||||
|
maxHp.set(monster.hp());
|
||||||
|
maxHpMonsterName.set(monster.name());
|
||||||
|
maxHpCount.set(1);
|
||||||
|
}
|
||||||
|
else if (monster.hp() == maxHp.get()) {
|
||||||
|
// Count how many times we saw a monster of current max hit points.
|
||||||
|
maxHpCount.getAndIncrement();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (monster.hp() < minHp.get()) {
|
||||||
|
// Found a monster of a lower hit points.
|
||||||
|
minHp.set(monster.hp());
|
||||||
|
minHpMonsterName.set(monster.name());
|
||||||
|
minHpCount.set(1);
|
||||||
|
}
|
||||||
|
else if (monster.hp() == minHp.get()) {
|
||||||
|
// Count how many times we saw a monster of current min hit points.
|
||||||
|
minHpCount.getAndIncrement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void onCompleted() {
|
||||||
|
Stat maxHpStat = GameFactory.createStat(maxHpMonsterName.get(), maxHp.get(), maxHpCount.get());
|
||||||
|
// Send max hit points first.
|
||||||
|
responseObserver.onNext(maxHpStat);
|
||||||
|
if (includeMin) {
|
||||||
|
// Send min hit points.
|
||||||
|
Stat minHpStat = GameFactory.createStat(minHpMonsterName.get(), minHp.get(), minHpCount.get());
|
||||||
|
responseObserver.onNext(minHpStat);
|
||||||
|
}
|
||||||
|
responseObserver.onCompleted();
|
||||||
|
}
|
||||||
|
public void onError(Throwable t) {
|
||||||
|
// Not expected
|
||||||
|
Assert.fail();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@org.junit.BeforeClass
|
||||||
private static int startServer() throws IOException {
|
public static void startServer() throws IOException {
|
||||||
Server server = ServerBuilder.forPort(0).addService(new MyService()).build().start();
|
server = ServerBuilder.forPort(0).addService(new MyService()).build().start();
|
||||||
return server.getPort();
|
int port = server.getPort();
|
||||||
}
|
channel = ManagedChannelBuilder.forAddress("localhost", port)
|
||||||
|
|
||||||
@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
|
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
|
||||||
// needing certificates.
|
// needing certificates.
|
||||||
.usePlaintext(true)
|
.usePlaintext(true)
|
||||||
.directExecutor()
|
.directExecutor()
|
||||||
.build();
|
.build();
|
||||||
|
blockingStub = MonsterStorageGrpc.newBlockingStub(channel);
|
||||||
|
asyncStub = MonsterStorageGrpc.newStub(channel);
|
||||||
|
}
|
||||||
|
|
||||||
MonsterStorageGrpc.MonsterStorageBlockingStub stub = MonsterStorageGrpc.newBlockingStub(channel);
|
@org.junit.Test
|
||||||
|
public void testUnary() throws IOException {
|
||||||
FlatBufferBuilder builder = new FlatBufferBuilder();
|
Monster monsterRequest = GameFactory.createMonster(BIG_MONSTER_NAME, nestedMonsterHp, nestedMonsterMana);
|
||||||
|
Stat stat = blockingStub.store(monsterRequest);
|
||||||
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);
|
Assert.assertEquals(stat.id(), "Hello " + BIG_MONSTER_NAME);
|
||||||
System.out.println("Received stat response from service: " + stat.id());
|
System.out.println("Received stat response from service: " + stat.id());
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.junit.Test
|
||||||
Iterator<Monster> iterator = stub.retrieve(stat);
|
public void testServerStreaming() throws IOException {
|
||||||
|
Monster monsterRequest = GameFactory.createMonster(BIG_MONSTER_NAME, nestedMonsterHp, nestedMonsterMana);
|
||||||
|
Stat stat = blockingStub.store(monsterRequest);
|
||||||
|
Iterator<Monster> iterator = blockingStub.retrieve(stat);
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
while(iterator.hasNext()) {
|
while(iterator.hasNext()) {
|
||||||
Monster m = iterator.next();
|
Monster m = iterator.next();
|
||||||
@@ -116,4 +170,73 @@ public class JavaGrpcTest {
|
|||||||
Assert.assertEquals(counter, numStreamedMsgs);
|
Assert.assertEquals(counter, numStreamedMsgs);
|
||||||
System.out.println("FlatBuffers GRPC client/server test: completed successfully");
|
System.out.println("FlatBuffers GRPC client/server test: completed successfully");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@org.junit.Test
|
||||||
|
public void testClientStreaming() throws IOException, InterruptedException {
|
||||||
|
final AtomicReference<Stat> maxHitStat = new AtomicReference<Stat>();
|
||||||
|
final CountDownLatch streamAlive = new CountDownLatch(1);
|
||||||
|
|
||||||
|
StreamObserver<Stat> statObserver = new StreamObserver<Stat>() {
|
||||||
|
public void onCompleted() {
|
||||||
|
streamAlive.countDown();
|
||||||
|
}
|
||||||
|
public void onError(Throwable ex) { }
|
||||||
|
public void onNext(Stat stat) {
|
||||||
|
maxHitStat.set(stat);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
StreamObserver<Monster> monsterStream = asyncStub.getMaxHitPoint(statObserver);
|
||||||
|
short count = 10;
|
||||||
|
for (short i = 0;i < count; ++i) {
|
||||||
|
Monster monster = GameFactory.createMonster(BIG_MONSTER_NAME + i, (short) (nestedMonsterHp * i), nestedMonsterMana);
|
||||||
|
monsterStream.onNext(monster);
|
||||||
|
}
|
||||||
|
monsterStream.onCompleted();
|
||||||
|
// Wait a little bit for the server to send the stats of the monster with the max hit-points.
|
||||||
|
streamAlive.await(timeoutMs, TimeUnit.MILLISECONDS);
|
||||||
|
Assert.assertEquals(maxHitStat.get().id(), BIG_MONSTER_NAME + (count - 1));
|
||||||
|
Assert.assertEquals(maxHitStat.get().val(), nestedMonsterHp * (count - 1));
|
||||||
|
Assert.assertEquals(maxHitStat.get().count(), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@org.junit.Test
|
||||||
|
public void testBiDiStreaming() throws IOException, InterruptedException {
|
||||||
|
final AtomicReference<Stat> maxHitStat = new AtomicReference<Stat>();
|
||||||
|
final AtomicReference<Stat> minHitStat = new AtomicReference<Stat>();
|
||||||
|
final CountDownLatch streamAlive = new CountDownLatch(1);
|
||||||
|
|
||||||
|
StreamObserver<Stat> statObserver = new StreamObserver<Stat>() {
|
||||||
|
public void onCompleted() {
|
||||||
|
streamAlive.countDown();
|
||||||
|
}
|
||||||
|
public void onError(Throwable ex) { }
|
||||||
|
public void onNext(Stat stat) {
|
||||||
|
// We expect the server to send the max stat first and then the min stat.
|
||||||
|
if (maxHitStat.get() == null) {
|
||||||
|
maxHitStat.set(stat);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
minHitStat.set(stat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
StreamObserver<Monster> monsterStream = asyncStub.getMinMaxHitPoints(statObserver);
|
||||||
|
short count = 10;
|
||||||
|
for (short i = 0;i < count; ++i) {
|
||||||
|
Monster monster = GameFactory.createMonster(BIG_MONSTER_NAME + i, (short) (nestedMonsterHp * i), nestedMonsterMana);
|
||||||
|
monsterStream.onNext(monster);
|
||||||
|
}
|
||||||
|
monsterStream.onCompleted();
|
||||||
|
|
||||||
|
// Wait a little bit for the server to send the stats of the monster with the max and min hit-points.
|
||||||
|
streamAlive.await(timeoutMs, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
Assert.assertEquals(maxHitStat.get().id(), BIG_MONSTER_NAME + (count - 1));
|
||||||
|
Assert.assertEquals(maxHitStat.get().val(), nestedMonsterHp * (count - 1));
|
||||||
|
Assert.assertEquals(maxHitStat.get().count(), 1);
|
||||||
|
|
||||||
|
Assert.assertEquals(minHitStat.get().id(), BIG_MONSTER_NAME + 0);
|
||||||
|
Assert.assertEquals(minHitStat.get().val(), nestedMonsterHp * 0);
|
||||||
|
Assert.assertEquals(minHitStat.get().count(), 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ package testing
|
|||||||
import (
|
import (
|
||||||
"../../tests/MyGame/Example"
|
"../../tests/MyGame/Example"
|
||||||
|
|
||||||
|
"context"
|
||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,13 @@
|
|||||||
|
|
||||||
#include "monster_test.grpc.fb.h"
|
#include "monster_test.grpc.fb.h"
|
||||||
#include "monster_test_generated.h"
|
#include "monster_test_generated.h"
|
||||||
|
#include "test_assert.h"
|
||||||
|
|
||||||
using namespace MyGame::Example;
|
using namespace MyGame::Example;
|
||||||
|
using flatbuffers::grpc::MessageBuilder;
|
||||||
|
using flatbuffers::FlatBufferBuilder;
|
||||||
|
|
||||||
|
void message_builder_tests();
|
||||||
|
|
||||||
// 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.
|
||||||
@@ -44,9 +49,9 @@ class ServiceImpl final : public MyGame::Example::MonsterStorage::Service {
|
|||||||
const flatbuffers::grpc::Message<Stat> *request,
|
const flatbuffers::grpc::Message<Stat> *request,
|
||||||
::grpc::ServerWriter<flatbuffers::grpc::Message<Monster>> *writer)
|
::grpc::ServerWriter<flatbuffers::grpc::Message<Monster>> *writer)
|
||||||
override {
|
override {
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
fbb_.Clear();
|
fbb_.Clear();
|
||||||
// Create 10 monsters for resposne.
|
// Create 5 monsters for resposne.
|
||||||
auto monster_offset =
|
auto monster_offset =
|
||||||
CreateMonster(fbb_, 0, 0, 0,
|
CreateMonster(fbb_, 0, 0, 0,
|
||||||
fbb_.CreateString(request->GetRoot()->id()->str() +
|
fbb_.CreateString(request->GetRoot()->id()->str() +
|
||||||
@@ -92,7 +97,46 @@ void RunServer() {
|
|||||||
server_instance->Wait();
|
server_instance->Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int /*argc*/, const char * /*argv*/ []) {
|
template <class Builder>
|
||||||
|
void StoreRPC(MonsterStorage::Stub *stub) {
|
||||||
|
Builder fbb;
|
||||||
|
grpc::ClientContext context;
|
||||||
|
// Build a request with the name set.
|
||||||
|
auto monster_offset = CreateMonster(fbb, 0, 0, 0, fbb.CreateString("Fred"));
|
||||||
|
MessageBuilder mb(std::move(fbb));
|
||||||
|
mb.Finish(monster_offset);
|
||||||
|
auto request = mb.ReleaseMessage<Monster>();
|
||||||
|
flatbuffers::grpc::Message<Stat> response;
|
||||||
|
|
||||||
|
// The actual RPC.
|
||||||
|
auto status = stub->Store(&context, request, &response);
|
||||||
|
|
||||||
|
if (status.ok()) {
|
||||||
|
auto resp = response.GetRoot()->id();
|
||||||
|
std::cout << "RPC response: " << resp->str() << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "RPC failed" << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Builder>
|
||||||
|
void RetrieveRPC(MonsterStorage::Stub *stub) {
|
||||||
|
Builder fbb;
|
||||||
|
grpc::ClientContext context;
|
||||||
|
fbb.Clear();
|
||||||
|
auto stat_offset = CreateStat(fbb, fbb.CreateString("Fred"));
|
||||||
|
fbb.Finish(stat_offset);
|
||||||
|
auto request = MessageBuilder(std::move(fbb)).ReleaseMessage<Stat>();
|
||||||
|
|
||||||
|
flatbuffers::grpc::Message<Monster> response;
|
||||||
|
auto stream = stub->Retrieve(&context, request);
|
||||||
|
while (stream->Read(&response)) {
|
||||||
|
auto resp = response.GetRoot()->name();
|
||||||
|
std::cout << "RPC Streaming response: " << resp->str() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int grpc_server_test() {
|
||||||
// Launch server.
|
// Launch server.
|
||||||
std::thread server_thread(RunServer);
|
std::thread server_thread(RunServer);
|
||||||
|
|
||||||
@@ -105,39 +149,12 @@ 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;
|
StoreRPC<MessageBuilder>(stub.get());
|
||||||
{
|
StoreRPC<FlatBufferBuilder>(stub.get());
|
||||||
grpc::ClientContext context;
|
|
||||||
// Build a request with the name set.
|
|
||||||
auto monster_offset = CreateMonster(fbb, 0, 0, 0, fbb.CreateString("Fred"));
|
|
||||||
fbb.Finish(monster_offset);
|
|
||||||
auto request = fbb.ReleaseMessage<Monster>();
|
|
||||||
flatbuffers::grpc::Message<Stat> response;
|
|
||||||
|
|
||||||
// The actual RPC.
|
RetrieveRPC<MessageBuilder>(stub.get());
|
||||||
auto status = stub->Store(&context, request, &response);
|
RetrieveRPC<FlatBufferBuilder>(stub.get());
|
||||||
|
|
||||||
if (status.ok()) {
|
|
||||||
auto resp = response.GetRoot()->id();
|
|
||||||
std::cout << "RPC response: " << resp->str() << std::endl;
|
|
||||||
} else {
|
|
||||||
std::cout << "RPC failed" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{
|
|
||||||
grpc::ClientContext context;
|
|
||||||
fbb.Clear();
|
|
||||||
auto stat_offset = CreateStat(fbb, fbb.CreateString("Fred"));
|
|
||||||
fbb.Finish(stat_offset);
|
|
||||||
auto request = fbb.ReleaseMessage<Stat>();
|
|
||||||
|
|
||||||
flatbuffers::grpc::Message<Monster> response;
|
|
||||||
auto stream = stub->Retrieve(&context, request);
|
|
||||||
while (stream->Read(&response)) {
|
|
||||||
auto resp = response.GetRoot()->name();
|
|
||||||
std::cout << "RPC Streaming response: " << resp->str() << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
|
#if !FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
|
||||||
{
|
{
|
||||||
@@ -163,3 +180,17 @@ int main(int /*argc*/, const char * /*argv*/ []) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int main(int /*argc*/, const char * /*argv*/ []) {
|
||||||
|
message_builder_tests();
|
||||||
|
grpc_server_test();
|
||||||
|
|
||||||
|
if (!testing_fails) {
|
||||||
|
TEST_OUTPUT_LINE("ALL TESTS PASSED");
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
TEST_OUTPUT_LINE("%d FAILED TESTS", testing_fails);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
340
grpc/tests/message_builder_test.cpp
Normal file
340
grpc/tests/message_builder_test.cpp
Normal file
@@ -0,0 +1,340 @@
|
|||||||
|
#include "flatbuffers/grpc.h"
|
||||||
|
#include "monster_test_generated.h"
|
||||||
|
#include "test_assert.h"
|
||||||
|
#include "test_builder.h"
|
||||||
|
|
||||||
|
using MyGame::Example::Vec3;
|
||||||
|
using MyGame::Example::CreateStat;
|
||||||
|
using MyGame::Example::Any_NONE;
|
||||||
|
|
||||||
|
bool verify(flatbuffers::grpc::Message<Monster> &msg, const std::string &expected_name, Color color) {
|
||||||
|
const Monster *monster = msg.GetRoot();
|
||||||
|
return (monster->name()->str() == expected_name) && (monster->color() == color);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool release_n_verify(flatbuffers::grpc::MessageBuilder &mbb, const std::string &expected_name, Color color) {
|
||||||
|
flatbuffers::grpc::Message<Monster> msg = mbb.ReleaseMessage<Monster>();
|
||||||
|
const Monster *monster = msg.GetRoot();
|
||||||
|
return (monster->name()->str() == expected_name) && (monster->color() == color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void builder_move_assign_after_releaseraw_test(flatbuffers::grpc::MessageBuilder dst) {
|
||||||
|
auto root_offset1 = populate1(dst);
|
||||||
|
dst.Finish(root_offset1);
|
||||||
|
size_t size, offset;
|
||||||
|
grpc_slice slice;
|
||||||
|
dst.ReleaseRaw(size, offset, slice);
|
||||||
|
flatbuffers::FlatBufferBuilder src;
|
||||||
|
auto root_offset2 = populate2(src);
|
||||||
|
src.Finish(root_offset2);
|
||||||
|
auto src_size = src.GetSize();
|
||||||
|
// Move into a released builder.
|
||||||
|
dst = std::move(src);
|
||||||
|
TEST_EQ(dst.GetSize(), src_size);
|
||||||
|
TEST_ASSERT(release_n_verify(dst, m2_name, m2_color));
|
||||||
|
TEST_EQ(src.GetSize(), 0);
|
||||||
|
grpc_slice_unref(slice);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class SrcBuilder>
|
||||||
|
struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
|
||||||
|
static void builder_reusable_after_release_message_test(TestSelector selector) {
|
||||||
|
if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flatbuffers::grpc::MessageBuilder mb;
|
||||||
|
std::vector<flatbuffers::grpc::Message<Monster>> buffers;
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
auto root_offset1 = populate1(mb);
|
||||||
|
mb.Finish(root_offset1);
|
||||||
|
buffers.push_back(mb.ReleaseMessage<Monster>());
|
||||||
|
TEST_ASSERT_FUNC(verify(buffers[i], m1_name, m1_color));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void builder_reusable_after_release_test(TestSelector selector) {
|
||||||
|
if (!selector.count(REUSABLE_AFTER_RELEASE)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Populate-Release loop fails assert(GRPC_SLICE_IS_EMPTY(slice_)) in SliceAllocator::allocate
|
||||||
|
// in the second iteration.
|
||||||
|
|
||||||
|
flatbuffers::grpc::MessageBuilder mb;
|
||||||
|
std::vector<flatbuffers::DetachedBuffer> buffers;
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
auto root_offset1 = populate1(mb);
|
||||||
|
mb.Finish(root_offset1);
|
||||||
|
buffers.push_back(mb.Release());
|
||||||
|
TEST_ASSERT_FUNC(verify(buffers[i], m1_name, m1_color));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void builder_reusable_after_releaseraw_test(TestSelector selector) {
|
||||||
|
if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flatbuffers::grpc::MessageBuilder mb;
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
auto root_offset1 = populate1(mb);
|
||||||
|
mb.Finish(root_offset1);
|
||||||
|
size_t size, offset;
|
||||||
|
grpc_slice slice;
|
||||||
|
const uint8_t *buf = mb.ReleaseRaw(size, offset, slice);
|
||||||
|
TEST_ASSERT_FUNC(verify(buf, offset, m1_name, m1_color));
|
||||||
|
grpc_slice_unref(slice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void builder_reusable_after_release_and_move_assign_test(TestSelector selector) {
|
||||||
|
if (!selector.count(REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Release-move_assign loop fails assert(p == GRPC_SLICE_START_PTR(slice_))
|
||||||
|
// in DetachedBuffer destructor after all the iterations
|
||||||
|
|
||||||
|
flatbuffers::grpc::MessageBuilder dst;
|
||||||
|
std::vector<flatbuffers::DetachedBuffer> buffers;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; ++i) {
|
||||||
|
auto root_offset1 = populate1(dst);
|
||||||
|
dst.Finish(root_offset1);
|
||||||
|
buffers.push_back(dst.Release());
|
||||||
|
TEST_ASSERT_FUNC(verify(buffers[i], m1_name, m1_color));
|
||||||
|
|
||||||
|
// bring dst back to life.
|
||||||
|
SrcBuilder src;
|
||||||
|
dst = std::move(src);
|
||||||
|
TEST_EQ_FUNC(dst.GetSize(), 0);
|
||||||
|
TEST_EQ_FUNC(src.GetSize(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void builder_reusable_after_release_message_and_move_assign_test(TestSelector selector) {
|
||||||
|
if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flatbuffers::grpc::MessageBuilder dst;
|
||||||
|
std::vector<flatbuffers::grpc::Message<Monster>> buffers;
|
||||||
|
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
auto root_offset1 = populate1(dst);
|
||||||
|
dst.Finish(root_offset1);
|
||||||
|
buffers.push_back(dst.ReleaseMessage<Monster>());
|
||||||
|
TEST_ASSERT_FUNC(verify(buffers[i], m1_name, m1_color));
|
||||||
|
|
||||||
|
// bring dst back to life.
|
||||||
|
SrcBuilder src;
|
||||||
|
dst = std::move(src);
|
||||||
|
TEST_EQ_FUNC(dst.GetSize(), 0);
|
||||||
|
TEST_EQ_FUNC(src.GetSize(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void builder_reusable_after_releaseraw_and_move_assign_test(TestSelector selector) {
|
||||||
|
if (!selector.count(REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
flatbuffers::grpc::MessageBuilder dst;
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
auto root_offset1 = populate1(dst);
|
||||||
|
dst.Finish(root_offset1);
|
||||||
|
size_t size, offset;
|
||||||
|
grpc_slice slice = grpc_empty_slice();
|
||||||
|
const uint8_t *buf = dst.ReleaseRaw(size, offset, slice);
|
||||||
|
TEST_ASSERT_FUNC(verify(buf, offset, m1_name, m1_color));
|
||||||
|
grpc_slice_unref(slice);
|
||||||
|
|
||||||
|
SrcBuilder src;
|
||||||
|
dst = std::move(src);
|
||||||
|
TEST_EQ_FUNC(dst.GetSize(), 0);
|
||||||
|
TEST_EQ_FUNC(src.GetSize(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void run_tests(TestSelector selector) {
|
||||||
|
builder_reusable_after_release_test(selector);
|
||||||
|
builder_reusable_after_release_message_test(selector);
|
||||||
|
builder_reusable_after_releaseraw_test(selector);
|
||||||
|
builder_reusable_after_release_and_move_assign_test(selector);
|
||||||
|
builder_reusable_after_releaseraw_and_move_assign_test(selector);
|
||||||
|
builder_reusable_after_release_message_and_move_assign_test(selector);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void slice_allocator_tests() {
|
||||||
|
// move-construct no-delete test
|
||||||
|
{
|
||||||
|
size_t size = 2048;
|
||||||
|
flatbuffers::grpc::SliceAllocator sa1;
|
||||||
|
uint8_t *buf = sa1.allocate(size);
|
||||||
|
TEST_ASSERT_FUNC(buf != 0);
|
||||||
|
buf[0] = 100;
|
||||||
|
buf[size-1] = 200;
|
||||||
|
flatbuffers::grpc::SliceAllocator sa2(std::move(sa1));
|
||||||
|
// buf should not be deleted after move-construct
|
||||||
|
TEST_EQ_FUNC(buf[0], 100);
|
||||||
|
TEST_EQ_FUNC(buf[size-1], 200);
|
||||||
|
// buf is freed here
|
||||||
|
}
|
||||||
|
|
||||||
|
// move-assign test
|
||||||
|
{
|
||||||
|
flatbuffers::grpc::SliceAllocator sa1, sa2;
|
||||||
|
uint8_t *buf = sa1.allocate(2048);
|
||||||
|
sa1 = std::move(sa2);
|
||||||
|
// sa1 deletes previously allocated memory in move-assign.
|
||||||
|
// So buf is no longer usable here.
|
||||||
|
TEST_ASSERT_FUNC(buf != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This function does not populate exactly the first half of the table. But it could.
|
||||||
|
void populate_first_half(MyGame::Example::MonsterBuilder &wrapper, flatbuffers::Offset<flatbuffers::String> name_offset) {
|
||||||
|
wrapper.add_name(name_offset);
|
||||||
|
wrapper.add_color(m1_color);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This function does not populate exactly the second half of the table. But it could.
|
||||||
|
void populate_second_half(MyGame::Example::MonsterBuilder &wrapper) {
|
||||||
|
wrapper.add_hp(77);
|
||||||
|
wrapper.add_mana(88);
|
||||||
|
Vec3 vec3;
|
||||||
|
wrapper.add_pos(&vec3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This function is a hack to update the FlatBufferBuilder reference (fbb_) in the MonsterBuilder object.
|
||||||
|
/// This function will break if fbb_ is not the first member in MonsterBuilder. In that case, some offset must be added.
|
||||||
|
/// This function is used exclusively for testing correctness of move operations between FlatBufferBuilders.
|
||||||
|
/// If MonsterBuilder had a fbb_ pointer, this hack would be unnecessary. That involves a code-generator change though.
|
||||||
|
void test_only_hack_update_fbb_reference(MyGame::Example::MonsterBuilder &monsterBuilder,
|
||||||
|
flatbuffers::grpc::MessageBuilder &mb) {
|
||||||
|
*reinterpret_cast<flatbuffers::FlatBufferBuilder **>(&monsterBuilder) = &mb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This test validates correctness of move conversion of FlatBufferBuilder to a MessageBuilder DURING
|
||||||
|
/// a table construction. Half of the table is constructed using FlatBufferBuilder and the other half
|
||||||
|
/// of the table is constructed using a MessageBuilder.
|
||||||
|
void builder_move_ctor_conversion_before_finish_half_n_half_table_test() {
|
||||||
|
for (size_t initial_size = 4 ; initial_size <= 2048; initial_size *= 2) {
|
||||||
|
flatbuffers::FlatBufferBuilder fbb(initial_size);
|
||||||
|
auto name_offset = fbb.CreateString(m1_name);
|
||||||
|
MyGame::Example::MonsterBuilder monsterBuilder(fbb); // starts a table in FlatBufferBuilder
|
||||||
|
populate_first_half(monsterBuilder, name_offset);
|
||||||
|
flatbuffers::grpc::MessageBuilder mb(std::move(fbb));
|
||||||
|
test_only_hack_update_fbb_reference(monsterBuilder, mb); // hack
|
||||||
|
populate_second_half(monsterBuilder);
|
||||||
|
mb.Finish(monsterBuilder.Finish()); // ends the table in MessageBuilder
|
||||||
|
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color));
|
||||||
|
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This test populates a COMPLETE inner table before move conversion and later populates more members in the outer table.
|
||||||
|
void builder_move_ctor_conversion_before_finish_test() {
|
||||||
|
for (size_t initial_size = 4 ; initial_size <= 2048; initial_size *= 2) {
|
||||||
|
flatbuffers::FlatBufferBuilder fbb(initial_size);
|
||||||
|
auto stat_offset = CreateStat(fbb, fbb.CreateString("SomeId"), 0, 0);
|
||||||
|
flatbuffers::grpc::MessageBuilder mb(std::move(fbb));
|
||||||
|
auto monster_offset = CreateMonster(mb, 0, 150, 100, mb.CreateString(m1_name), 0, m1_color, Any_NONE, 0, 0, 0, 0, 0, 0, stat_offset);
|
||||||
|
mb.Finish(monster_offset);
|
||||||
|
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color));
|
||||||
|
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This test validates correctness of move conversion of FlatBufferBuilder to a MessageBuilder DURING
|
||||||
|
/// a table construction. Half of the table is constructed using FlatBufferBuilder and the other half
|
||||||
|
/// of the table is constructed using a MessageBuilder.
|
||||||
|
void builder_move_assign_conversion_before_finish_half_n_half_table_test() {
|
||||||
|
flatbuffers::FlatBufferBuilder fbb;
|
||||||
|
flatbuffers::grpc::MessageBuilder mb;
|
||||||
|
|
||||||
|
for (int i = 0;i < 5; ++i) {
|
||||||
|
flatbuffers::FlatBufferBuilder fbb;
|
||||||
|
auto name_offset = fbb.CreateString(m1_name);
|
||||||
|
MyGame::Example::MonsterBuilder monsterBuilder(fbb); // starts a table in FlatBufferBuilder
|
||||||
|
populate_first_half(monsterBuilder, name_offset);
|
||||||
|
mb = std::move(fbb);
|
||||||
|
test_only_hack_update_fbb_reference(monsterBuilder, mb); // hack
|
||||||
|
populate_second_half(monsterBuilder);
|
||||||
|
mb.Finish(monsterBuilder.Finish()); // ends the table in MessageBuilder
|
||||||
|
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color));
|
||||||
|
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This test populates a COMPLETE inner table before move conversion and later populates more members in the outer table.
|
||||||
|
void builder_move_assign_conversion_before_finish_test() {
|
||||||
|
flatbuffers::FlatBufferBuilder fbb;
|
||||||
|
flatbuffers::grpc::MessageBuilder mb;
|
||||||
|
|
||||||
|
for (int i = 0;i < 5; ++i) {
|
||||||
|
auto stat_offset = CreateStat(fbb, fbb.CreateString("SomeId"), 0, 0);
|
||||||
|
mb = std::move(fbb);
|
||||||
|
auto monster_offset = CreateMonster(mb, 0, 150, 100, mb.CreateString(m1_name), 0, m1_color, Any_NONE, 0, 0, 0, 0, 0, 0, stat_offset);
|
||||||
|
mb.Finish(monster_offset);
|
||||||
|
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color));
|
||||||
|
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This test populates data, finishes the buffer, and does move conversion after.
|
||||||
|
void builder_move_ctor_conversion_after_finish_test() {
|
||||||
|
flatbuffers::FlatBufferBuilder fbb;
|
||||||
|
fbb.Finish(populate1(fbb));
|
||||||
|
flatbuffers::grpc::MessageBuilder mb(std::move(fbb));
|
||||||
|
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color));
|
||||||
|
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This test populates data, finishes the buffer, and does move conversion after.
|
||||||
|
void builder_move_assign_conversion_after_finish_test() {
|
||||||
|
flatbuffers::FlatBufferBuilder fbb;
|
||||||
|
flatbuffers::grpc::MessageBuilder mb;
|
||||||
|
|
||||||
|
for (int i = 0;i < 5; ++i) {
|
||||||
|
fbb.Finish(populate1(fbb));
|
||||||
|
mb = std::move(fbb);
|
||||||
|
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color));
|
||||||
|
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void message_builder_tests() {
|
||||||
|
using flatbuffers::grpc::MessageBuilder;
|
||||||
|
using flatbuffers::FlatBufferBuilder;
|
||||||
|
|
||||||
|
slice_allocator_tests();
|
||||||
|
|
||||||
|
#ifndef __APPLE__
|
||||||
|
builder_move_ctor_conversion_before_finish_half_n_half_table_test();
|
||||||
|
builder_move_assign_conversion_before_finish_half_n_half_table_test();
|
||||||
|
#endif // __APPLE__
|
||||||
|
builder_move_ctor_conversion_before_finish_test();
|
||||||
|
builder_move_assign_conversion_before_finish_test();
|
||||||
|
|
||||||
|
builder_move_ctor_conversion_after_finish_test();
|
||||||
|
builder_move_assign_conversion_after_finish_test();
|
||||||
|
|
||||||
|
BuilderTests<MessageBuilder, MessageBuilder>::all_tests();
|
||||||
|
BuilderTests<MessageBuilder, FlatBufferBuilder>::all_tests();
|
||||||
|
|
||||||
|
BuilderReuseTestSelector tests[6] = {
|
||||||
|
//REUSABLE_AFTER_RELEASE, // Assertion failed: (GRPC_SLICE_IS_EMPTY(slice_))
|
||||||
|
//REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN, // Assertion failed: (p == GRPC_SLICE_START_PTR(slice_)
|
||||||
|
|
||||||
|
REUSABLE_AFTER_RELEASE_RAW,
|
||||||
|
REUSABLE_AFTER_RELEASE_MESSAGE,
|
||||||
|
REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN,
|
||||||
|
REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN
|
||||||
|
};
|
||||||
|
|
||||||
|
BuilderReuseTests<MessageBuilder, MessageBuilder>::run_tests(TestSelector(tests, tests+6));
|
||||||
|
BuilderReuseTests<MessageBuilder, FlatBufferBuilder>::run_tests(TestSelector(tests, tests+6));
|
||||||
|
}
|
||||||
@@ -4,13 +4,13 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>com.google.flatbuffers</groupId>
|
<groupId>com.google.flatbuffers</groupId>
|
||||||
<artifactId>flatbuffers-parent</artifactId>
|
<artifactId>flatbuffers-parent</artifactId>
|
||||||
<version>1.8.0</version>
|
<version>1.11.0</version>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>grpc-test</artifactId>
|
<artifactId>grpc-test</artifactId>
|
||||||
<description>Example/Test project demonstrating usage of flatbuffers with GRPC-Java instead of protobufs
|
<description>Example/Test project demonstrating usage of flatbuffers with GRPC-Java instead of protobufs
|
||||||
</description>
|
</description>
|
||||||
<properties>
|
<properties>
|
||||||
<gRPC.version>1.8.0</gRPC.version>
|
<gRPC.version>1.11.0</gRPC.version>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -2,12 +2,27 @@
|
|||||||
#define FLATBUFFERS_BASE_H_
|
#define FLATBUFFERS_BASE_H_
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|
||||||
|
// If activate should be declared and included first.
|
||||||
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
|
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
|
||||||
defined(_MSC_VER) && defined(_DEBUG)
|
defined(_MSC_VER) && defined(_DEBUG)
|
||||||
|
// The _CRTDBG_MAP_ALLOC inside <crtdbg.h> will replace
|
||||||
|
// calloc/free (etc) to its debug version using #define directives.
|
||||||
#define _CRTDBG_MAP_ALLOC
|
#define _CRTDBG_MAP_ALLOC
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <crtdbg.h>
|
||||||
|
// Replace operator new by trace-enabled version.
|
||||||
|
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
|
||||||
|
#define new DEBUG_NEW
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(FLATBUFFERS_ASSERT)
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#define FLATBUFFERS_ASSERT assert
|
||||||
|
#elif defined(FLATBUFFERS_ASSERT_INCLUDE)
|
||||||
|
// Include file with forward declaration
|
||||||
|
#include FLATBUFFERS_ASSERT_INCLUDE
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef ARDUINO
|
#ifndef ARDUINO
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
@@ -17,13 +32,6 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
|
|
||||||
defined(_MSC_VER) && defined(_DEBUG)
|
|
||||||
#include <crtdbg.h>
|
|
||||||
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
|
|
||||||
#define new DEBUG_NEW
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H)
|
#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H)
|
||||||
#include <utility.h>
|
#include <utility.h>
|
||||||
#else
|
#else
|
||||||
@@ -47,6 +55,33 @@
|
|||||||
|
|
||||||
#include "flatbuffers/stl_emulation.h"
|
#include "flatbuffers/stl_emulation.h"
|
||||||
|
|
||||||
|
// Note the __clang__ check is needed, because clang presents itself
|
||||||
|
// as an older GNUC compiler (4.2).
|
||||||
|
// Clang 3.3 and later implement all of the ISO C++ 2011 standard.
|
||||||
|
// Clang 3.4 and later implement all of the ISO C++ 2014 standard.
|
||||||
|
// http://clang.llvm.org/cxx_status.html
|
||||||
|
|
||||||
|
// Note the MSVC value '__cplusplus' may be incorrect:
|
||||||
|
// The '__cplusplus' predefined macro in the MSVC stuck at the value 199711L,
|
||||||
|
// indicating (erroneously!) that the compiler conformed to the C++98 Standard.
|
||||||
|
// This value should be correct starting from MSVC2017-15.7-Preview-3.
|
||||||
|
// The '__cplusplus' will be valid only if MSVC2017-15.7-P3 and the `/Zc:__cplusplus` switch is set.
|
||||||
|
// Workaround (for details see MSDN):
|
||||||
|
// Use the _MSC_VER and _MSVC_LANG definition instead of the __cplusplus for compatibility.
|
||||||
|
// The _MSVC_LANG macro reports the Standard version regardless of the '/Zc:__cplusplus' switch.
|
||||||
|
|
||||||
|
#if defined(__GNUC__) && !defined(__clang__)
|
||||||
|
#define FLATBUFFERS_GCC (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
|
||||||
|
#else
|
||||||
|
#define FLATBUFFERS_GCC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define FLATBUFFERS_CLANG (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
|
||||||
|
#else
|
||||||
|
#define FLATBUFFERS_CLANG 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/// @cond FLATBUFFERS_INTERNAL
|
/// @cond FLATBUFFERS_INTERNAL
|
||||||
#if __cplusplus <= 199711L && \
|
#if __cplusplus <= 199711L && \
|
||||||
(!defined(_MSC_VER) || _MSC_VER < 1600) && \
|
(!defined(_MSC_VER) || _MSC_VER < 1600) && \
|
||||||
@@ -83,7 +118,8 @@
|
|||||||
#endif // __s390x__
|
#endif // __s390x__
|
||||||
#if !defined(FLATBUFFERS_LITTLEENDIAN)
|
#if !defined(FLATBUFFERS_LITTLEENDIAN)
|
||||||
#if defined(__GNUC__) || defined(__clang__)
|
#if defined(__GNUC__) || defined(__clang__)
|
||||||
#ifdef __BIG_ENDIAN__
|
#if (defined(__BIG_ENDIAN__) || \
|
||||||
|
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||||
#define FLATBUFFERS_LITTLEENDIAN 0
|
#define FLATBUFFERS_LITTLEENDIAN 0
|
||||||
#else
|
#else
|
||||||
#define FLATBUFFERS_LITTLEENDIAN 1
|
#define FLATBUFFERS_LITTLEENDIAN 1
|
||||||
@@ -100,25 +136,29 @@
|
|||||||
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
|
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
|
||||||
|
|
||||||
#define FLATBUFFERS_VERSION_MAJOR 1
|
#define FLATBUFFERS_VERSION_MAJOR 1
|
||||||
#define FLATBUFFERS_VERSION_MINOR 9
|
#define FLATBUFFERS_VERSION_MINOR 11
|
||||||
#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)
|
||||||
|
|
||||||
#if (!defined(_MSC_VER) || _MSC_VER > 1600) && \
|
#if (!defined(_MSC_VER) || _MSC_VER > 1600) && \
|
||||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407))
|
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407)) || \
|
||||||
|
defined(__clang__)
|
||||||
#define FLATBUFFERS_FINAL_CLASS final
|
#define FLATBUFFERS_FINAL_CLASS final
|
||||||
#define FLATBUFFERS_OVERRIDE override
|
#define FLATBUFFERS_OVERRIDE override
|
||||||
|
#define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t
|
||||||
#else
|
#else
|
||||||
#define FLATBUFFERS_FINAL_CLASS
|
#define FLATBUFFERS_FINAL_CLASS
|
||||||
#define FLATBUFFERS_OVERRIDE
|
#define FLATBUFFERS_OVERRIDE
|
||||||
|
#define FLATBUFFERS_VTABLE_UNDERLYING_TYPE
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
|
#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
|
||||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406))
|
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \
|
||||||
|
(defined(__cpp_constexpr) && __cpp_constexpr >= 200704)
|
||||||
#define FLATBUFFERS_CONSTEXPR constexpr
|
#define FLATBUFFERS_CONSTEXPR constexpr
|
||||||
#else
|
#else
|
||||||
#define FLATBUFFERS_CONSTEXPR
|
#define FLATBUFFERS_CONSTEXPR const
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(__cplusplus) && __cplusplus >= 201402L) || \
|
#if (defined(__cplusplus) && __cplusplus >= 201402L) || \
|
||||||
@@ -128,8 +168,9 @@
|
|||||||
#define FLATBUFFERS_CONSTEXPR_CPP14
|
#define FLATBUFFERS_CONSTEXPR_CPP14
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46 || \
|
#if (defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \
|
||||||
defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026
|
(defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023026)) || \
|
||||||
|
defined(__clang__)
|
||||||
#define FLATBUFFERS_NOEXCEPT noexcept
|
#define FLATBUFFERS_NOEXCEPT noexcept
|
||||||
#else
|
#else
|
||||||
#define FLATBUFFERS_NOEXCEPT
|
#define FLATBUFFERS_NOEXCEPT
|
||||||
@@ -138,15 +179,92 @@
|
|||||||
// NOTE: the FLATBUFFERS_DELETE_FUNC macro may change the access mode to
|
// NOTE: the FLATBUFFERS_DELETE_FUNC macro may change the access mode to
|
||||||
// private, so be sure to put it at the end or reset access mode explicitly.
|
// private, so be sure to put it at the end or reset access mode explicitly.
|
||||||
#if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \
|
#if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \
|
||||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404))
|
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404)) || \
|
||||||
|
defined(__clang__)
|
||||||
#define FLATBUFFERS_DELETE_FUNC(func) func = delete;
|
#define FLATBUFFERS_DELETE_FUNC(func) func = delete;
|
||||||
#else
|
#else
|
||||||
#define FLATBUFFERS_DELETE_FUNC(func) private: func;
|
#define FLATBUFFERS_DELETE_FUNC(func) private: func;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#ifndef FLATBUFFERS_HAS_STRING_VIEW
|
||||||
#pragma warning(push)
|
// Only provide flatbuffers::string_view if __has_include can be used
|
||||||
#pragma warning(disable: 4127) // C4127: conditional expression is constant
|
// to detect a header that provides an implementation
|
||||||
|
#if defined(__has_include)
|
||||||
|
// Check for std::string_view (in c++17)
|
||||||
|
#if __has_include(<string_view>) && (__cplusplus >= 201606 || _HAS_CXX17)
|
||||||
|
#include <string_view>
|
||||||
|
namespace flatbuffers {
|
||||||
|
typedef std::string_view string_view;
|
||||||
|
}
|
||||||
|
#define FLATBUFFERS_HAS_STRING_VIEW 1
|
||||||
|
// Check for std::experimental::string_view (in c++14, compiler-dependent)
|
||||||
|
#elif __has_include(<experimental/string_view>) && (__cplusplus >= 201411)
|
||||||
|
#include <experimental/string_view>
|
||||||
|
namespace flatbuffers {
|
||||||
|
typedef std::experimental::string_view string_view;
|
||||||
|
}
|
||||||
|
#define FLATBUFFERS_HAS_STRING_VIEW 1
|
||||||
|
#endif
|
||||||
|
#endif // __has_include
|
||||||
|
#endif // !FLATBUFFERS_HAS_STRING_VIEW
|
||||||
|
|
||||||
|
#ifndef FLATBUFFERS_HAS_NEW_STRTOD
|
||||||
|
// Modern (C++11) strtod and strtof functions are available for use.
|
||||||
|
// 1) nan/inf strings as argument of strtod;
|
||||||
|
// 2) hex-float as argument of strtod/strtof.
|
||||||
|
#if (defined(_MSC_VER) && _MSC_VER >= 1900) || \
|
||||||
|
(defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \
|
||||||
|
(defined(__clang__))
|
||||||
|
#define FLATBUFFERS_HAS_NEW_STRTOD 1
|
||||||
|
#endif
|
||||||
|
#endif // !FLATBUFFERS_HAS_NEW_STRTOD
|
||||||
|
|
||||||
|
#ifndef FLATBUFFERS_LOCALE_INDEPENDENT
|
||||||
|
// Enable locale independent functions {strtof_l, strtod_l,strtoll_l, strtoull_l}.
|
||||||
|
// They are part of the POSIX-2008 but not part of the C/C++ standard.
|
||||||
|
// GCC/Clang have definition (_XOPEN_SOURCE>=700) if POSIX-2008.
|
||||||
|
#if ((defined(_MSC_VER) && _MSC_VER >= 1800) || \
|
||||||
|
(defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE>=700)))
|
||||||
|
#define FLATBUFFERS_LOCALE_INDEPENDENT 1
|
||||||
|
#else
|
||||||
|
#define FLATBUFFERS_LOCALE_INDEPENDENT 0
|
||||||
|
#endif
|
||||||
|
#endif // !FLATBUFFERS_LOCALE_INDEPENDENT
|
||||||
|
|
||||||
|
// Suppress Undefined Behavior Sanitizer (recoverable only). Usage:
|
||||||
|
// - __supress_ubsan__("undefined")
|
||||||
|
// - __supress_ubsan__("signed-integer-overflow")
|
||||||
|
#if defined(__clang__)
|
||||||
|
#define __supress_ubsan__(type) __attribute__((no_sanitize(type)))
|
||||||
|
#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
|
||||||
|
#define __supress_ubsan__(type) __attribute__((no_sanitize_undefined))
|
||||||
|
#else
|
||||||
|
#define __supress_ubsan__(type)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// This is constexpr function used for checking compile-time constants.
|
||||||
|
// Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`.
|
||||||
|
template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) {
|
||||||
|
return !!t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable C++ attribute [[]] if std:c++17 or higher.
|
||||||
|
#if ((__cplusplus >= 201703L) \
|
||||||
|
|| (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L)))
|
||||||
|
// All attributes unknown to an implementation are ignored without causing an error.
|
||||||
|
#define FLATBUFFERS_ATTRIBUTE(attr) [[attr]]
|
||||||
|
|
||||||
|
#define FLATBUFFERS_FALLTHROUGH() [[fallthrough]]
|
||||||
|
#else
|
||||||
|
#define FLATBUFFERS_ATTRIBUTE(attr)
|
||||||
|
|
||||||
|
#if FLATBUFFERS_CLANG >= 30800
|
||||||
|
#define FLATBUFFERS_FALLTHROUGH() [[clang::fallthrough]]
|
||||||
|
#elif FLATBUFFERS_GCC >= 70300
|
||||||
|
#define FLATBUFFERS_FALLTHROUGH() [[gnu::fallthrough]]
|
||||||
|
#else
|
||||||
|
#define FLATBUFFERS_FALLTHROUGH()
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// @endcond
|
/// @endcond
|
||||||
@@ -175,6 +293,11 @@ 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
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable: 4127) // C4127: conditional expression is constant
|
||||||
|
#endif
|
||||||
|
|
||||||
template<typename T> T EndianSwap(T t) {
|
template<typename T> T EndianSwap(T t) {
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
|
#define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
|
||||||
@@ -209,10 +332,14 @@ template<typename T> T EndianSwap(T t) {
|
|||||||
u.i = FLATBUFFERS_BYTESWAP64(u.i);
|
u.i = FLATBUFFERS_BYTESWAP64(u.i);
|
||||||
return u.t;
|
return u.t;
|
||||||
} else {
|
} else {
|
||||||
assert(0);
|
FLATBUFFERS_ASSERT(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#pragma warning(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
template<typename T> T EndianScalar(T t) {
|
template<typename T> T EndianScalar(T t) {
|
||||||
#if FLATBUFFERS_LITTLEENDIAN
|
#if FLATBUFFERS_LITTLEENDIAN
|
||||||
@@ -222,14 +349,25 @@ template<typename T> T EndianScalar(T t) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> T ReadScalar(const void *p) {
|
template<typename T>
|
||||||
|
// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
|
||||||
|
__supress_ubsan__("alignment")
|
||||||
|
T ReadScalar(const void *p) {
|
||||||
return EndianScalar(*reinterpret_cast<const T *>(p));
|
return EndianScalar(*reinterpret_cast<const T *>(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void WriteScalar(void *p, T t) {
|
template<typename T>
|
||||||
|
// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
|
||||||
|
__supress_ubsan__("alignment")
|
||||||
|
void WriteScalar(void *p, T t) {
|
||||||
*reinterpret_cast<T *>(p) = EndianScalar(t);
|
*reinterpret_cast<T *>(p) = EndianScalar(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T> struct Offset;
|
||||||
|
template<typename T> __supress_ubsan__("alignment") void WriteScalar(void *p, Offset<T> t) {
|
||||||
|
*reinterpret_cast<uoffset_t *>(p) = EndianScalar(t.o);
|
||||||
|
}
|
||||||
|
|
||||||
// Computes how many bytes you'd have to pad to be able to write an
|
// Computes how many bytes you'd have to pad to be able to write an
|
||||||
// "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in
|
// "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in
|
||||||
// memory).
|
// memory).
|
||||||
|
|||||||
@@ -130,6 +130,74 @@ extern void GenComment(const std::vector<std::string> &dc,
|
|||||||
std::string *code_ptr, const CommentConfig *config,
|
std::string *code_ptr, const CommentConfig *config,
|
||||||
const char *prefix = "");
|
const char *prefix = "");
|
||||||
|
|
||||||
|
class FloatConstantGenerator {
|
||||||
|
public:
|
||||||
|
virtual ~FloatConstantGenerator() {}
|
||||||
|
std::string GenFloatConstant(const FieldDef &field) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual std::string Value(double v, const std::string &src) const = 0;
|
||||||
|
virtual std::string Inf(double v) const = 0;
|
||||||
|
virtual std::string NaN(double v) const = 0;
|
||||||
|
|
||||||
|
virtual std::string Value(float v, const std::string &src) const = 0;
|
||||||
|
virtual std::string Inf(float v) const = 0;
|
||||||
|
virtual std::string NaN(float v) const = 0;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::string GenFloatConstantImpl(const FieldDef &field) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SimpleFloatConstantGenerator : public FloatConstantGenerator {
|
||||||
|
public:
|
||||||
|
SimpleFloatConstantGenerator(const char *nan_number,
|
||||||
|
const char *pos_inf_number,
|
||||||
|
const char *neg_inf_number);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string Value(double v,
|
||||||
|
const std::string &src) const FLATBUFFERS_OVERRIDE;
|
||||||
|
std::string Inf(double v) const FLATBUFFERS_OVERRIDE;
|
||||||
|
std::string NaN(double v) const FLATBUFFERS_OVERRIDE;
|
||||||
|
|
||||||
|
std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE;
|
||||||
|
std::string Inf(float v) const FLATBUFFERS_OVERRIDE;
|
||||||
|
std::string NaN(float v) const FLATBUFFERS_OVERRIDE;
|
||||||
|
|
||||||
|
const std::string nan_number_;
|
||||||
|
const std::string pos_inf_number_;
|
||||||
|
const std::string neg_inf_number_;
|
||||||
|
};
|
||||||
|
|
||||||
|
// C++, C#, Java like generator.
|
||||||
|
class TypedFloatConstantGenerator : public FloatConstantGenerator {
|
||||||
|
public:
|
||||||
|
TypedFloatConstantGenerator(const char *double_prefix,
|
||||||
|
const char *single_prefix, const char *nan_number,
|
||||||
|
const char *pos_inf_number,
|
||||||
|
const char *neg_inf_number = "");
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string Value(double v,
|
||||||
|
const std::string &src) const FLATBUFFERS_OVERRIDE;
|
||||||
|
std::string Inf(double v) const FLATBUFFERS_OVERRIDE;
|
||||||
|
|
||||||
|
std::string NaN(double v) const FLATBUFFERS_OVERRIDE;
|
||||||
|
|
||||||
|
std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE;
|
||||||
|
std::string Inf(float v) const FLATBUFFERS_OVERRIDE;
|
||||||
|
std::string NaN(float v) const FLATBUFFERS_OVERRIDE;
|
||||||
|
|
||||||
|
std::string MakeNaN(const std::string &prefix) const;
|
||||||
|
std::string MakeInf(bool neg, const std::string &prefix) const;
|
||||||
|
|
||||||
|
const std::string double_prefix_;
|
||||||
|
const std::string single_prefix_;
|
||||||
|
const std::string nan_number_;
|
||||||
|
const std::string pos_inf_number_;
|
||||||
|
const std::string neg_inf_number_;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace flatbuffers
|
} // namespace flatbuffers
|
||||||
|
|
||||||
#endif // FLATBUFFERS_CODE_GENERATORS_H_
|
#endif // FLATBUFFERS_CODE_GENERATORS_H_
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -80,6 +80,9 @@ class FlatCompiler {
|
|||||||
const std::string &contents,
|
const std::string &contents,
|
||||||
std::vector<const char *> &include_directories) const;
|
std::vector<const char *> &include_directories) const;
|
||||||
|
|
||||||
|
void LoadBinarySchema(Parser &parser, const std::string &filename,
|
||||||
|
const std::string &contents);
|
||||||
|
|
||||||
void Warn(const std::string &warn, bool show_exe_name = true) const;
|
void Warn(const std::string &warn, bool show_exe_name = true) const;
|
||||||
|
|
||||||
void Error(const std::string &err, bool usage = true,
|
void Error(const std::string &err, bool usage = true,
|
||||||
|
|||||||
@@ -49,75 +49,75 @@ enum BitWidth {
|
|||||||
// These are used as the upper 6 bits of a type field to indicate the actual
|
// These are used as the upper 6 bits of a type field to indicate the actual
|
||||||
// type.
|
// type.
|
||||||
enum Type {
|
enum Type {
|
||||||
TYPE_NULL = 0,
|
FBT_NULL = 0,
|
||||||
TYPE_INT = 1,
|
FBT_INT = 1,
|
||||||
TYPE_UINT = 2,
|
FBT_UINT = 2,
|
||||||
TYPE_FLOAT = 3,
|
FBT_FLOAT = 3,
|
||||||
// Types above stored inline, types below store an offset.
|
// Types above stored inline, types below store an offset.
|
||||||
TYPE_KEY = 4,
|
FBT_KEY = 4,
|
||||||
TYPE_STRING = 5,
|
FBT_STRING = 5,
|
||||||
TYPE_INDIRECT_INT = 6,
|
FBT_INDIRECT_INT = 6,
|
||||||
TYPE_INDIRECT_UINT = 7,
|
FBT_INDIRECT_UINT = 7,
|
||||||
TYPE_INDIRECT_FLOAT = 8,
|
FBT_INDIRECT_FLOAT = 8,
|
||||||
TYPE_MAP = 9,
|
FBT_MAP = 9,
|
||||||
TYPE_VECTOR = 10, // Untyped.
|
FBT_VECTOR = 10, // Untyped.
|
||||||
TYPE_VECTOR_INT = 11, // Typed any size (stores no type table).
|
FBT_VECTOR_INT = 11, // Typed any size (stores no type table).
|
||||||
TYPE_VECTOR_UINT = 12,
|
FBT_VECTOR_UINT = 12,
|
||||||
TYPE_VECTOR_FLOAT = 13,
|
FBT_VECTOR_FLOAT = 13,
|
||||||
TYPE_VECTOR_KEY = 14,
|
FBT_VECTOR_KEY = 14,
|
||||||
TYPE_VECTOR_STRING = 15,
|
FBT_VECTOR_STRING = 15,
|
||||||
TYPE_VECTOR_INT2 = 16, // Typed tuple (no type table, no size field).
|
FBT_VECTOR_INT2 = 16, // Typed tuple (no type table, no size field).
|
||||||
TYPE_VECTOR_UINT2 = 17,
|
FBT_VECTOR_UINT2 = 17,
|
||||||
TYPE_VECTOR_FLOAT2 = 18,
|
FBT_VECTOR_FLOAT2 = 18,
|
||||||
TYPE_VECTOR_INT3 = 19, // Typed triple (no type table, no size field).
|
FBT_VECTOR_INT3 = 19, // Typed triple (no type table, no size field).
|
||||||
TYPE_VECTOR_UINT3 = 20,
|
FBT_VECTOR_UINT3 = 20,
|
||||||
TYPE_VECTOR_FLOAT3 = 21,
|
FBT_VECTOR_FLOAT3 = 21,
|
||||||
TYPE_VECTOR_INT4 = 22, // Typed quad (no type table, no size field).
|
FBT_VECTOR_INT4 = 22, // Typed quad (no type table, no size field).
|
||||||
TYPE_VECTOR_UINT4 = 23,
|
FBT_VECTOR_UINT4 = 23,
|
||||||
TYPE_VECTOR_FLOAT4 = 24,
|
FBT_VECTOR_FLOAT4 = 24,
|
||||||
TYPE_BLOB = 25,
|
FBT_BLOB = 25,
|
||||||
TYPE_BOOL = 26,
|
FBT_BOOL = 26,
|
||||||
TYPE_VECTOR_BOOL =
|
FBT_VECTOR_BOOL =
|
||||||
36, // To Allow the same type of conversion of type to vector type
|
36, // To Allow the same type of conversion of type to vector type
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool IsInline(Type t) { return t <= TYPE_FLOAT || t == TYPE_BOOL; }
|
inline bool IsInline(Type t) { return t <= FBT_FLOAT || t == FBT_BOOL; }
|
||||||
|
|
||||||
inline bool IsTypedVectorElementType(Type t) {
|
inline bool IsTypedVectorElementType(Type t) {
|
||||||
return (t >= TYPE_INT && t <= TYPE_STRING) || t == TYPE_BOOL;
|
return (t >= FBT_INT && t <= FBT_STRING) || t == FBT_BOOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsTypedVector(Type t) {
|
inline bool IsTypedVector(Type t) {
|
||||||
return (t >= TYPE_VECTOR_INT && t <= TYPE_VECTOR_STRING) ||
|
return (t >= FBT_VECTOR_INT && t <= FBT_VECTOR_STRING) ||
|
||||||
t == TYPE_VECTOR_BOOL;
|
t == FBT_VECTOR_BOOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool IsFixedTypedVector(Type t) {
|
inline bool IsFixedTypedVector(Type t) {
|
||||||
return t >= TYPE_VECTOR_INT2 && t <= TYPE_VECTOR_FLOAT4;
|
return t >= FBT_VECTOR_INT2 && t <= FBT_VECTOR_FLOAT4;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Type ToTypedVector(Type t, size_t fixed_len = 0) {
|
inline Type ToTypedVector(Type t, size_t fixed_len = 0) {
|
||||||
assert(IsTypedVectorElementType(t));
|
FLATBUFFERS_ASSERT(IsTypedVectorElementType(t));
|
||||||
switch (fixed_len) {
|
switch (fixed_len) {
|
||||||
case 0: return static_cast<Type>(t - TYPE_INT + TYPE_VECTOR_INT);
|
case 0: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT);
|
||||||
case 2: return static_cast<Type>(t - TYPE_INT + TYPE_VECTOR_INT2);
|
case 2: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT2);
|
||||||
case 3: return static_cast<Type>(t - TYPE_INT + TYPE_VECTOR_INT3);
|
case 3: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT3);
|
||||||
case 4: return static_cast<Type>(t - TYPE_INT + TYPE_VECTOR_INT4);
|
case 4: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT4);
|
||||||
default: assert(0); return TYPE_NULL;
|
default: FLATBUFFERS_ASSERT(0); return FBT_NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Type ToTypedVectorElementType(Type t) {
|
inline Type ToTypedVectorElementType(Type t) {
|
||||||
assert(IsTypedVector(t));
|
FLATBUFFERS_ASSERT(IsTypedVector(t));
|
||||||
return static_cast<Type>(t - TYPE_VECTOR_INT + TYPE_INT);
|
return static_cast<Type>(t - FBT_VECTOR_INT + FBT_INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Type ToFixedTypedVectorElementType(Type t, uint8_t *len) {
|
inline Type ToFixedTypedVectorElementType(Type t, uint8_t *len) {
|
||||||
assert(IsFixedTypedVector(t));
|
FLATBUFFERS_ASSERT(IsFixedTypedVector(t));
|
||||||
auto fixed_type = t - TYPE_VECTOR_INT2;
|
auto fixed_type = t - FBT_VECTOR_INT2;
|
||||||
*len = static_cast<uint8_t>(fixed_type / 3 +
|
*len = static_cast<uint8_t>(fixed_type / 3 +
|
||||||
2); // 3 types each, starting from length 2.
|
2); // 3 types each, starting from length 2.
|
||||||
return static_cast<Type>(fixed_type % 3 + TYPE_INT);
|
return static_cast<Type>(fixed_type % 3 + FBT_INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: implement proper support for 8/16bit floats, or decide not to
|
// TODO: implement proper support for 8/16bit floats, or decide not to
|
||||||
@@ -153,7 +153,7 @@ inline uint64_t ReadUInt64(const uint8_t *data, uint8_t byte_width) {
|
|||||||
// constant, which here it isn't. Test if memcpy is still faster than
|
// constant, which here it isn't. Test if memcpy is still faster than
|
||||||
// the conditionals in ReadSizedScalar. Can also use inline asm.
|
// the conditionals in ReadSizedScalar. Can also use inline asm.
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#ifdef _MSC_VER
|
#if defined(_MSC_VER) && (defined(_M_X64) || defined _M_IX86)
|
||||||
uint64_t u = 0;
|
uint64_t u = 0;
|
||||||
__movsb(reinterpret_cast<uint8_t *>(&u),
|
__movsb(reinterpret_cast<uint8_t *>(&u),
|
||||||
reinterpret_cast<const uint8_t *>(data), byte_width);
|
reinterpret_cast<const uint8_t *>(data), byte_width);
|
||||||
@@ -271,7 +271,7 @@ class TypedVector : public Sized {
|
|||||||
|
|
||||||
static TypedVector EmptyTypedVector() {
|
static TypedVector EmptyTypedVector() {
|
||||||
static const uint8_t empty_typed_vector[] = { 0 /*len*/ };
|
static const uint8_t empty_typed_vector[] = { 0 /*len*/ };
|
||||||
return TypedVector(empty_typed_vector + 1, 1, TYPE_INT);
|
return TypedVector(empty_typed_vector + 1, 1, FBT_INT);
|
||||||
}
|
}
|
||||||
bool IsTheEmptyVector() const {
|
bool IsTheEmptyVector() const {
|
||||||
return data_ == TypedVector::EmptyTypedVector().data_;
|
return data_ == TypedVector::EmptyTypedVector().data_;
|
||||||
@@ -295,7 +295,7 @@ class FixedTypedVector : public Object {
|
|||||||
|
|
||||||
static FixedTypedVector EmptyFixedTypedVector() {
|
static FixedTypedVector EmptyFixedTypedVector() {
|
||||||
static const uint8_t fixed_empty_vector[] = { 0 /* unused */ };
|
static const uint8_t fixed_empty_vector[] = { 0 /* unused */ };
|
||||||
return FixedTypedVector(fixed_empty_vector, 1, TYPE_INT, 0);
|
return FixedTypedVector(fixed_empty_vector, 1, FBT_INT, 0);
|
||||||
}
|
}
|
||||||
bool IsTheEmptyFixedTypedVector() const {
|
bool IsTheEmptyFixedTypedVector() const {
|
||||||
return data_ == FixedTypedVector::EmptyFixedTypedVector().data_;
|
return data_ == FixedTypedVector::EmptyFixedTypedVector().data_;
|
||||||
@@ -324,7 +324,7 @@ class Map : public Vector {
|
|||||||
return TypedVector(Indirect(keys_offset, byte_width_),
|
return TypedVector(Indirect(keys_offset, byte_width_),
|
||||||
static_cast<uint8_t>(
|
static_cast<uint8_t>(
|
||||||
ReadUInt64(keys_offset + byte_width_, byte_width_)),
|
ReadUInt64(keys_offset + byte_width_, byte_width_)),
|
||||||
TYPE_KEY);
|
FBT_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Map EmptyMap() {
|
static Map EmptyMap() {
|
||||||
@@ -337,6 +337,16 @@ class Map : public Vector {
|
|||||||
bool IsTheEmptyMap() const { return data_ == EmptyMap().data_; }
|
bool IsTheEmptyMap() const { return data_ == EmptyMap().data_; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void AppendToString(std::string &s, T &&v, bool keys_quoted) {
|
||||||
|
s += "[ ";
|
||||||
|
for (size_t i = 0; i < v.size(); i++) {
|
||||||
|
if (i) s += ", ";
|
||||||
|
v[i].ToString(true, keys_quoted, s);
|
||||||
|
}
|
||||||
|
s += " ]";
|
||||||
|
}
|
||||||
|
|
||||||
class Reference {
|
class Reference {
|
||||||
public:
|
public:
|
||||||
Reference(const uint8_t *data, uint8_t parent_width, uint8_t byte_width,
|
Reference(const uint8_t *data, uint8_t parent_width, uint8_t byte_width,
|
||||||
@@ -354,25 +364,28 @@ class Reference {
|
|||||||
|
|
||||||
Type GetType() const { return type_; }
|
Type GetType() const { return type_; }
|
||||||
|
|
||||||
bool IsNull() const { return type_ == TYPE_NULL; }
|
bool IsNull() const { return type_ == FBT_NULL; }
|
||||||
bool IsBool() const { return type_ == TYPE_BOOL; }
|
bool IsBool() const { return type_ == FBT_BOOL; }
|
||||||
bool IsInt() const { return type_ == TYPE_INT || type_ == TYPE_INDIRECT_INT; }
|
bool IsInt() const { return type_ == FBT_INT || type_ == FBT_INDIRECT_INT; }
|
||||||
bool IsUInt() const {
|
bool IsUInt() const {
|
||||||
return type_ == TYPE_UINT || type_ == TYPE_INDIRECT_UINT;
|
return type_ == FBT_UINT || type_ == FBT_INDIRECT_UINT;
|
||||||
}
|
}
|
||||||
bool IsIntOrUint() const { return IsInt() || IsUInt(); }
|
bool IsIntOrUint() const { return IsInt() || IsUInt(); }
|
||||||
bool IsFloat() const {
|
bool IsFloat() const {
|
||||||
return type_ == TYPE_FLOAT || type_ == TYPE_INDIRECT_FLOAT;
|
return type_ == FBT_FLOAT || type_ == FBT_INDIRECT_FLOAT;
|
||||||
}
|
}
|
||||||
bool IsNumeric() const { return IsIntOrUint() || IsFloat(); }
|
bool IsNumeric() const { return IsIntOrUint() || IsFloat(); }
|
||||||
bool IsString() const { return type_ == TYPE_STRING; }
|
bool IsString() const { return type_ == FBT_STRING; }
|
||||||
bool IsKey() const { return type_ == TYPE_KEY; }
|
bool IsKey() const { return type_ == FBT_KEY; }
|
||||||
bool IsVector() const { return type_ == TYPE_VECTOR || type_ == TYPE_MAP; }
|
bool IsVector() const { return type_ == FBT_VECTOR || type_ == FBT_MAP; }
|
||||||
bool IsMap() const { return type_ == TYPE_MAP; }
|
bool IsTypedVector() const { return flexbuffers::IsTypedVector(type_); }
|
||||||
bool IsBlob() const { return type_ == TYPE_BLOB; }
|
bool IsFixedTypedVector() const { return flexbuffers::IsFixedTypedVector(type_); }
|
||||||
|
bool IsAnyVector() const { return (IsTypedVector() || IsFixedTypedVector() || IsVector());}
|
||||||
|
bool IsMap() const { return type_ == FBT_MAP; }
|
||||||
|
bool IsBlob() const { return type_ == FBT_BLOB; }
|
||||||
|
|
||||||
bool AsBool() const {
|
bool AsBool() const {
|
||||||
return (type_ == TYPE_BOOL ? ReadUInt64(data_, parent_width_)
|
return (type_ == FBT_BOOL ? ReadUInt64(data_, parent_width_)
|
||||||
: AsUInt64()) != 0;
|
: AsUInt64()) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,22 +393,22 @@ class Reference {
|
|||||||
// Truncates floats, strings are attempted to be parsed for a number,
|
// Truncates floats, strings are attempted to be parsed for a number,
|
||||||
// vectors/maps return their size. Returns 0 if all else fails.
|
// vectors/maps return their size. Returns 0 if all else fails.
|
||||||
int64_t AsInt64() const {
|
int64_t AsInt64() const {
|
||||||
if (type_ == TYPE_INT) {
|
if (type_ == FBT_INT) {
|
||||||
// A fast path for the common case.
|
// A fast path for the common case.
|
||||||
return ReadInt64(data_, parent_width_);
|
return ReadInt64(data_, parent_width_);
|
||||||
} else
|
} else
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
case TYPE_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_);
|
case FBT_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_);
|
||||||
case TYPE_UINT: return ReadUInt64(data_, parent_width_);
|
case FBT_UINT: return ReadUInt64(data_, parent_width_);
|
||||||
case TYPE_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_);
|
case FBT_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_);
|
||||||
case TYPE_FLOAT:
|
case FBT_FLOAT:
|
||||||
return static_cast<int64_t>(ReadDouble(data_, parent_width_));
|
return static_cast<int64_t>(ReadDouble(data_, parent_width_));
|
||||||
case TYPE_INDIRECT_FLOAT:
|
case FBT_INDIRECT_FLOAT:
|
||||||
return static_cast<int64_t>(ReadDouble(Indirect(), byte_width_));
|
return static_cast<int64_t>(ReadDouble(Indirect(), byte_width_));
|
||||||
case TYPE_NULL: return 0;
|
case FBT_NULL: return 0;
|
||||||
case TYPE_STRING: return flatbuffers::StringToInt(AsString().c_str());
|
case FBT_STRING: return flatbuffers::StringToInt(AsString().c_str());
|
||||||
case TYPE_VECTOR: return static_cast<int64_t>(AsVector().size());
|
case FBT_VECTOR: return static_cast<int64_t>(AsVector().size());
|
||||||
case TYPE_BOOL: return ReadInt64(data_, parent_width_);
|
case FBT_BOOL: return ReadInt64(data_, parent_width_);
|
||||||
default:
|
default:
|
||||||
// Convert other things to int.
|
// Convert other things to int.
|
||||||
return 0;
|
return 0;
|
||||||
@@ -409,22 +422,22 @@ class Reference {
|
|||||||
int8_t AsInt8() const { return static_cast<int8_t>(AsInt64()); }
|
int8_t AsInt8() const { return static_cast<int8_t>(AsInt64()); }
|
||||||
|
|
||||||
uint64_t AsUInt64() const {
|
uint64_t AsUInt64() const {
|
||||||
if (type_ == TYPE_UINT) {
|
if (type_ == FBT_UINT) {
|
||||||
// A fast path for the common case.
|
// A fast path for the common case.
|
||||||
return ReadUInt64(data_, parent_width_);
|
return ReadUInt64(data_, parent_width_);
|
||||||
} else
|
} else
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
case TYPE_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_);
|
case FBT_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_);
|
||||||
case TYPE_INT: return ReadInt64(data_, parent_width_);
|
case FBT_INT: return ReadInt64(data_, parent_width_);
|
||||||
case TYPE_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_);
|
case FBT_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_);
|
||||||
case TYPE_FLOAT:
|
case FBT_FLOAT:
|
||||||
return static_cast<uint64_t>(ReadDouble(data_, parent_width_));
|
return static_cast<uint64_t>(ReadDouble(data_, parent_width_));
|
||||||
case TYPE_INDIRECT_FLOAT:
|
case FBT_INDIRECT_FLOAT:
|
||||||
return static_cast<uint64_t>(ReadDouble(Indirect(), byte_width_));
|
return static_cast<uint64_t>(ReadDouble(Indirect(), byte_width_));
|
||||||
case TYPE_NULL: return 0;
|
case FBT_NULL: return 0;
|
||||||
case TYPE_STRING: return flatbuffers::StringToUInt(AsString().c_str());
|
case FBT_STRING: return flatbuffers::StringToUInt(AsString().c_str());
|
||||||
case TYPE_VECTOR: return static_cast<uint64_t>(AsVector().size());
|
case FBT_VECTOR: return static_cast<uint64_t>(AsVector().size());
|
||||||
case TYPE_BOOL: return ReadUInt64(data_, parent_width_);
|
case FBT_BOOL: return ReadUInt64(data_, parent_width_);
|
||||||
default:
|
default:
|
||||||
// Convert other things to uint.
|
// Convert other things to uint.
|
||||||
return 0;
|
return 0;
|
||||||
@@ -436,24 +449,24 @@ class Reference {
|
|||||||
uint8_t AsUInt8() const { return static_cast<uint8_t>(AsUInt64()); }
|
uint8_t AsUInt8() const { return static_cast<uint8_t>(AsUInt64()); }
|
||||||
|
|
||||||
double AsDouble() const {
|
double AsDouble() const {
|
||||||
if (type_ == TYPE_FLOAT) {
|
if (type_ == FBT_FLOAT) {
|
||||||
// A fast path for the common case.
|
// A fast path for the common case.
|
||||||
return ReadDouble(data_, parent_width_);
|
return ReadDouble(data_, parent_width_);
|
||||||
} else
|
} else
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
case TYPE_INDIRECT_FLOAT: return ReadDouble(Indirect(), byte_width_);
|
case FBT_INDIRECT_FLOAT: return ReadDouble(Indirect(), byte_width_);
|
||||||
case TYPE_INT:
|
case FBT_INT:
|
||||||
return static_cast<double>(ReadInt64(data_, parent_width_));
|
return static_cast<double>(ReadInt64(data_, parent_width_));
|
||||||
case TYPE_UINT:
|
case FBT_UINT:
|
||||||
return static_cast<double>(ReadUInt64(data_, parent_width_));
|
return static_cast<double>(ReadUInt64(data_, parent_width_));
|
||||||
case TYPE_INDIRECT_INT:
|
case FBT_INDIRECT_INT:
|
||||||
return static_cast<double>(ReadInt64(Indirect(), byte_width_));
|
return static_cast<double>(ReadInt64(Indirect(), byte_width_));
|
||||||
case TYPE_INDIRECT_UINT:
|
case FBT_INDIRECT_UINT:
|
||||||
return static_cast<double>(ReadUInt64(Indirect(), byte_width_));
|
return static_cast<double>(ReadUInt64(Indirect(), byte_width_));
|
||||||
case TYPE_NULL: return 0.0;
|
case FBT_NULL: return 0.0;
|
||||||
case TYPE_STRING: return strtod(AsString().c_str(), nullptr);
|
case FBT_STRING: return strtod(AsString().c_str(), nullptr);
|
||||||
case TYPE_VECTOR: return static_cast<double>(AsVector().size());
|
case FBT_VECTOR: return static_cast<double>(AsVector().size());
|
||||||
case TYPE_BOOL:
|
case FBT_BOOL:
|
||||||
return static_cast<double>(ReadUInt64(data_, parent_width_));
|
return static_cast<double>(ReadUInt64(data_, parent_width_));
|
||||||
default:
|
default:
|
||||||
// Convert strings and other things to float.
|
// Convert strings and other things to float.
|
||||||
@@ -464,7 +477,7 @@ class Reference {
|
|||||||
float AsFloat() const { return static_cast<float>(AsDouble()); }
|
float AsFloat() const { return static_cast<float>(AsDouble()); }
|
||||||
|
|
||||||
const char *AsKey() const {
|
const char *AsKey() const {
|
||||||
if (type_ == TYPE_KEY) {
|
if (type_ == FBT_KEY) {
|
||||||
return reinterpret_cast<const char *>(Indirect());
|
return reinterpret_cast<const char *>(Indirect());
|
||||||
} else {
|
} else {
|
||||||
return "";
|
return "";
|
||||||
@@ -473,7 +486,7 @@ class Reference {
|
|||||||
|
|
||||||
// This function returns the empty string if you try to read a not-string.
|
// This function returns the empty string if you try to read a not-string.
|
||||||
String AsString() const {
|
String AsString() const {
|
||||||
if (type_ == TYPE_STRING) {
|
if (type_ == FBT_STRING) {
|
||||||
return String(Indirect(), byte_width_);
|
return String(Indirect(), byte_width_);
|
||||||
} else {
|
} else {
|
||||||
return String::EmptyString();
|
return String::EmptyString();
|
||||||
@@ -481,7 +494,7 @@ class Reference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unlike AsString(), this will convert any type to a std::string.
|
// Unlike AsString(), this will convert any type to a std::string.
|
||||||
std::string ToString() {
|
std::string ToString() const {
|
||||||
std::string s;
|
std::string s;
|
||||||
ToString(false, false, s);
|
ToString(false, false, s);
|
||||||
return s;
|
return s;
|
||||||
@@ -492,17 +505,17 @@ class Reference {
|
|||||||
// they always do). keys_quoted determines if keys are quoted, at any level.
|
// they always do). keys_quoted determines if keys are quoted, at any level.
|
||||||
// TODO(wvo): add further options to have indentation/newlines.
|
// TODO(wvo): add further options to have indentation/newlines.
|
||||||
void ToString(bool strings_quoted, bool keys_quoted, std::string &s) const {
|
void ToString(bool strings_quoted, bool keys_quoted, std::string &s) const {
|
||||||
if (type_ == TYPE_STRING) {
|
if (type_ == FBT_STRING) {
|
||||||
String str(Indirect(), byte_width_);
|
String str(Indirect(), byte_width_);
|
||||||
if (strings_quoted) {
|
if (strings_quoted) {
|
||||||
flatbuffers::EscapeString(str.c_str(), str.length(), &s, true);
|
flatbuffers::EscapeString(str.c_str(), str.length(), &s, true, false);
|
||||||
} else {
|
} else {
|
||||||
s.append(str.c_str(), str.length());
|
s.append(str.c_str(), str.length());
|
||||||
}
|
}
|
||||||
} else if (IsKey()) {
|
} else if (IsKey()) {
|
||||||
auto str = AsKey();
|
auto str = AsKey();
|
||||||
if (keys_quoted) {
|
if (keys_quoted) {
|
||||||
flatbuffers::EscapeString(str, strlen(str), &s, true);
|
flatbuffers::EscapeString(str, strlen(str), &s, true, false);
|
||||||
} else {
|
} else {
|
||||||
s += str;
|
s += str;
|
||||||
}
|
}
|
||||||
@@ -529,13 +542,14 @@ class Reference {
|
|||||||
}
|
}
|
||||||
s += " }";
|
s += " }";
|
||||||
} else if (IsVector()) {
|
} else if (IsVector()) {
|
||||||
s += "[ ";
|
AppendToString<Vector>(s, AsVector(), keys_quoted);
|
||||||
auto v = AsVector();
|
} else if (IsTypedVector()) {
|
||||||
for (size_t i = 0; i < v.size(); i++) {
|
AppendToString<TypedVector>(s, AsTypedVector(), keys_quoted);
|
||||||
v[i].ToString(true, keys_quoted, s);
|
} else if (IsFixedTypedVector()) {
|
||||||
if (i < v.size() - 1) s += ", ";
|
AppendToString<FixedTypedVector>(s, AsFixedTypedVector(), keys_quoted);
|
||||||
}
|
} else if (IsBlob()) {
|
||||||
s += " ]";
|
auto blob = AsBlob();
|
||||||
|
flatbuffers::EscapeString(reinterpret_cast<const char*>(blob.data()), blob.size(), &s, true, false);
|
||||||
} else {
|
} else {
|
||||||
s += "(?)";
|
s += "(?)";
|
||||||
}
|
}
|
||||||
@@ -544,7 +558,7 @@ class Reference {
|
|||||||
// This function returns the empty blob if you try to read a not-blob.
|
// This function returns the empty blob if you try to read a not-blob.
|
||||||
// Strings can be viewed as blobs too.
|
// Strings can be viewed as blobs too.
|
||||||
Blob AsBlob() const {
|
Blob AsBlob() const {
|
||||||
if (type_ == TYPE_BLOB || type_ == TYPE_STRING) {
|
if (type_ == FBT_BLOB || type_ == FBT_STRING) {
|
||||||
return Blob(Indirect(), byte_width_);
|
return Blob(Indirect(), byte_width_);
|
||||||
} else {
|
} else {
|
||||||
return Blob::EmptyBlob();
|
return Blob::EmptyBlob();
|
||||||
@@ -554,7 +568,7 @@ class Reference {
|
|||||||
// This function returns the empty vector if you try to read a not-vector.
|
// This function returns the empty vector if you try to read a not-vector.
|
||||||
// Maps can be viewed as vectors too.
|
// Maps can be viewed as vectors too.
|
||||||
Vector AsVector() const {
|
Vector AsVector() const {
|
||||||
if (type_ == TYPE_VECTOR || type_ == TYPE_MAP) {
|
if (type_ == FBT_VECTOR || type_ == FBT_MAP) {
|
||||||
return Vector(Indirect(), byte_width_);
|
return Vector(Indirect(), byte_width_);
|
||||||
} else {
|
} else {
|
||||||
return Vector::EmptyVector();
|
return Vector::EmptyVector();
|
||||||
@@ -562,7 +576,7 @@ class Reference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TypedVector AsTypedVector() const {
|
TypedVector AsTypedVector() const {
|
||||||
if (IsTypedVector(type_)) {
|
if (IsTypedVector()) {
|
||||||
return TypedVector(Indirect(), byte_width_,
|
return TypedVector(Indirect(), byte_width_,
|
||||||
ToTypedVectorElementType(type_));
|
ToTypedVectorElementType(type_));
|
||||||
} else {
|
} else {
|
||||||
@@ -571,7 +585,7 @@ class Reference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FixedTypedVector AsFixedTypedVector() const {
|
FixedTypedVector AsFixedTypedVector() const {
|
||||||
if (IsFixedTypedVector(type_)) {
|
if (IsFixedTypedVector()) {
|
||||||
uint8_t len = 0;
|
uint8_t len = 0;
|
||||||
auto vtype = ToFixedTypedVectorElementType(type_, &len);
|
auto vtype = ToFixedTypedVectorElementType(type_, &len);
|
||||||
return FixedTypedVector(Indirect(), byte_width_, vtype, len);
|
return FixedTypedVector(Indirect(), byte_width_, vtype, len);
|
||||||
@@ -581,14 +595,14 @@ class Reference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Map AsMap() const {
|
Map AsMap() const {
|
||||||
if (type_ == TYPE_MAP) {
|
if (type_ == FBT_MAP) {
|
||||||
return Map(Indirect(), byte_width_);
|
return Map(Indirect(), byte_width_);
|
||||||
} else {
|
} else {
|
||||||
return Map::EmptyMap();
|
return Map::EmptyMap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> T As();
|
template<typename T> T As() const;
|
||||||
|
|
||||||
// Experimental: Mutation functions.
|
// Experimental: Mutation functions.
|
||||||
// These allow scalars in an already created buffer to be updated in-place.
|
// These allow scalars in an already created buffer to be updated in-place.
|
||||||
@@ -597,14 +611,14 @@ class Reference {
|
|||||||
// To avoid this, you can construct the values you intend to mutate using
|
// To avoid this, you can construct the values you intend to mutate using
|
||||||
// Builder::ForceMinimumBitWidth.
|
// Builder::ForceMinimumBitWidth.
|
||||||
bool MutateInt(int64_t i) {
|
bool MutateInt(int64_t i) {
|
||||||
if (type_ == TYPE_INT) {
|
if (type_ == FBT_INT) {
|
||||||
return Mutate(data_, i, parent_width_, WidthI(i));
|
return Mutate(data_, i, parent_width_, WidthI(i));
|
||||||
} else if (type_ == TYPE_INDIRECT_INT) {
|
} else if (type_ == FBT_INDIRECT_INT) {
|
||||||
return Mutate(Indirect(), i, byte_width_, WidthI(i));
|
return Mutate(Indirect(), i, byte_width_, WidthI(i));
|
||||||
} else if (type_ == TYPE_UINT) {
|
} else if (type_ == FBT_UINT) {
|
||||||
auto u = static_cast<uint64_t>(i);
|
auto u = static_cast<uint64_t>(i);
|
||||||
return Mutate(data_, u, parent_width_, WidthU(u));
|
return Mutate(data_, u, parent_width_, WidthU(u));
|
||||||
} else if (type_ == TYPE_INDIRECT_UINT) {
|
} else if (type_ == FBT_INDIRECT_UINT) {
|
||||||
auto u = static_cast<uint64_t>(i);
|
auto u = static_cast<uint64_t>(i);
|
||||||
return Mutate(Indirect(), u, byte_width_, WidthU(u));
|
return Mutate(Indirect(), u, byte_width_, WidthU(u));
|
||||||
} else {
|
} else {
|
||||||
@@ -613,18 +627,18 @@ class Reference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool MutateBool(bool b) {
|
bool MutateBool(bool b) {
|
||||||
return type_ == TYPE_BOOL && Mutate(data_, b, parent_width_, BIT_WIDTH_8);
|
return type_ == FBT_BOOL && Mutate(data_, b, parent_width_, BIT_WIDTH_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MutateUInt(uint64_t u) {
|
bool MutateUInt(uint64_t u) {
|
||||||
if (type_ == TYPE_UINT) {
|
if (type_ == FBT_UINT) {
|
||||||
return Mutate(data_, u, parent_width_, WidthU(u));
|
return Mutate(data_, u, parent_width_, WidthU(u));
|
||||||
} else if (type_ == TYPE_INDIRECT_UINT) {
|
} else if (type_ == FBT_INDIRECT_UINT) {
|
||||||
return Mutate(Indirect(), u, byte_width_, WidthU(u));
|
return Mutate(Indirect(), u, byte_width_, WidthU(u));
|
||||||
} else if (type_ == TYPE_INT) {
|
} else if (type_ == FBT_INT) {
|
||||||
auto i = static_cast<int64_t>(u);
|
auto i = static_cast<int64_t>(u);
|
||||||
return Mutate(data_, i, parent_width_, WidthI(i));
|
return Mutate(data_, i, parent_width_, WidthI(i));
|
||||||
} else if (type_ == TYPE_INDIRECT_INT) {
|
} else if (type_ == FBT_INDIRECT_INT) {
|
||||||
auto i = static_cast<int64_t>(u);
|
auto i = static_cast<int64_t>(u);
|
||||||
return Mutate(Indirect(), i, byte_width_, WidthI(i));
|
return Mutate(Indirect(), i, byte_width_, WidthI(i));
|
||||||
} else {
|
} else {
|
||||||
@@ -633,9 +647,9 @@ class Reference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool MutateFloat(float f) {
|
bool MutateFloat(float f) {
|
||||||
if (type_ == TYPE_FLOAT) {
|
if (type_ == FBT_FLOAT) {
|
||||||
return MutateF(data_, f, parent_width_, BIT_WIDTH_32);
|
return MutateF(data_, f, parent_width_, BIT_WIDTH_32);
|
||||||
} else if (type_ == TYPE_INDIRECT_FLOAT) {
|
} else if (type_ == FBT_INDIRECT_FLOAT) {
|
||||||
return MutateF(Indirect(), f, byte_width_, BIT_WIDTH_32);
|
return MutateF(Indirect(), f, byte_width_, BIT_WIDTH_32);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@@ -643,9 +657,9 @@ class Reference {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool MutateFloat(double d) {
|
bool MutateFloat(double d) {
|
||||||
if (type_ == TYPE_FLOAT) {
|
if (type_ == FBT_FLOAT) {
|
||||||
return MutateF(data_, d, parent_width_, WidthF(d));
|
return MutateF(data_, d, parent_width_, WidthF(d));
|
||||||
} else if (type_ == TYPE_INDIRECT_FLOAT) {
|
} else if (type_ == FBT_INDIRECT_FLOAT) {
|
||||||
return MutateF(Indirect(), d, byte_width_, WidthF(d));
|
return MutateF(Indirect(), d, byte_width_, WidthF(d));
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@@ -690,7 +704,7 @@ class Reference {
|
|||||||
return Mutate(dest, static_cast<double>(t), byte_width, value_width);
|
return Mutate(dest, static_cast<double>(t), byte_width, value_width);
|
||||||
if (byte_width == sizeof(float))
|
if (byte_width == sizeof(float))
|
||||||
return Mutate(dest, static_cast<float>(t), byte_width, value_width);
|
return Mutate(dest, static_cast<float>(t), byte_width, value_width);
|
||||||
assert(false);
|
FLATBUFFERS_ASSERT(false);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -701,41 +715,41 @@ class Reference {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Template specialization for As().
|
// Template specialization for As().
|
||||||
template<> inline bool Reference::As<bool>() { return AsBool(); }
|
template<> inline bool Reference::As<bool>() const { return AsBool(); }
|
||||||
|
|
||||||
template<> inline int8_t Reference::As<int8_t>() { return AsInt8(); }
|
template<> inline int8_t Reference::As<int8_t>() const { return AsInt8(); }
|
||||||
template<> inline int16_t Reference::As<int16_t>() { return AsInt16(); }
|
template<> inline int16_t Reference::As<int16_t>() const { return AsInt16(); }
|
||||||
template<> inline int32_t Reference::As<int32_t>() { return AsInt32(); }
|
template<> inline int32_t Reference::As<int32_t>() const { return AsInt32(); }
|
||||||
template<> inline int64_t Reference::As<int64_t>() { return AsInt64(); }
|
template<> inline int64_t Reference::As<int64_t>() const { return AsInt64(); }
|
||||||
|
|
||||||
template<> inline uint8_t Reference::As<uint8_t>() { return AsUInt8(); }
|
template<> inline uint8_t Reference::As<uint8_t>() const { return AsUInt8(); }
|
||||||
template<> inline uint16_t Reference::As<uint16_t>() { return AsUInt16(); }
|
template<> inline uint16_t Reference::As<uint16_t>() const { return AsUInt16(); }
|
||||||
template<> inline uint32_t Reference::As<uint32_t>() { return AsUInt32(); }
|
template<> inline uint32_t Reference::As<uint32_t>() const { return AsUInt32(); }
|
||||||
template<> inline uint64_t Reference::As<uint64_t>() { return AsUInt64(); }
|
template<> inline uint64_t Reference::As<uint64_t>() const { return AsUInt64(); }
|
||||||
|
|
||||||
template<> inline double Reference::As<double>() { return AsDouble(); }
|
template<> inline double Reference::As<double>() const { return AsDouble(); }
|
||||||
template<> inline float Reference::As<float>() { return AsFloat(); }
|
template<> inline float Reference::As<float>() const { return AsFloat(); }
|
||||||
|
|
||||||
template<> inline String Reference::As<String>() { return AsString(); }
|
template<> inline String Reference::As<String>() const { return AsString(); }
|
||||||
template<> inline std::string Reference::As<std::string>() {
|
template<> inline std::string Reference::As<std::string>() const {
|
||||||
return AsString().str();
|
return AsString().str();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> inline Blob Reference::As<Blob>() { return AsBlob(); }
|
template<> inline Blob Reference::As<Blob>() const { return AsBlob(); }
|
||||||
template<> inline Vector Reference::As<Vector>() { return AsVector(); }
|
template<> inline Vector Reference::As<Vector>() const { return AsVector(); }
|
||||||
template<> inline TypedVector Reference::As<TypedVector>() {
|
template<> inline TypedVector Reference::As<TypedVector>() const {
|
||||||
return AsTypedVector();
|
return AsTypedVector();
|
||||||
}
|
}
|
||||||
template<> inline FixedTypedVector Reference::As<FixedTypedVector>() {
|
template<> inline FixedTypedVector Reference::As<FixedTypedVector>() const {
|
||||||
return AsFixedTypedVector();
|
return AsFixedTypedVector();
|
||||||
}
|
}
|
||||||
template<> inline Map Reference::As<Map>() { return AsMap(); }
|
template<> inline Map Reference::As<Map>() const { return AsMap(); }
|
||||||
|
|
||||||
inline uint8_t PackedType(BitWidth bit_width, Type type) {
|
inline uint8_t PackedType(BitWidth bit_width, Type type) {
|
||||||
return static_cast<uint8_t>(bit_width | (type << 2));
|
return static_cast<uint8_t>(bit_width | (type << 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint8_t NullPackedType() { return PackedType(BIT_WIDTH_8, TYPE_NULL); }
|
inline uint8_t NullPackedType() { return PackedType(BIT_WIDTH_8, FBT_NULL); }
|
||||||
|
|
||||||
// Vector accessors.
|
// Vector accessors.
|
||||||
// Note: if you try to access outside of bounds, you get a Null value back
|
// Note: if you try to access outside of bounds, you get a Null value back
|
||||||
@@ -870,16 +884,16 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
Null();
|
Null();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Int(int64_t i) { stack_.push_back(Value(i, TYPE_INT, WidthI(i))); }
|
void Int(int64_t i) { stack_.push_back(Value(i, FBT_INT, WidthI(i))); }
|
||||||
void Int(const char *key, int64_t i) {
|
void Int(const char *key, int64_t i) {
|
||||||
Key(key);
|
Key(key);
|
||||||
Int(i);
|
Int(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UInt(uint64_t u) { stack_.push_back(Value(u, TYPE_UINT, WidthU(u))); }
|
void UInt(uint64_t u) { stack_.push_back(Value(u, FBT_UINT, WidthU(u))); }
|
||||||
void UInt(const char *key, uint64_t u) {
|
void UInt(const char *key, uint64_t u) {
|
||||||
Key(key);
|
Key(key);
|
||||||
Int(u);
|
UInt(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Float(float f) { stack_.push_back(Value(f)); }
|
void Float(float f) { stack_.push_back(Value(f)); }
|
||||||
@@ -900,14 +914,14 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
Bool(b);
|
Bool(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IndirectInt(int64_t i) { PushIndirect(i, TYPE_INDIRECT_INT, WidthI(i)); }
|
void IndirectInt(int64_t i) { PushIndirect(i, FBT_INDIRECT_INT, WidthI(i)); }
|
||||||
void IndirectInt(const char *key, int64_t i) {
|
void IndirectInt(const char *key, int64_t i) {
|
||||||
Key(key);
|
Key(key);
|
||||||
IndirectInt(i);
|
IndirectInt(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IndirectUInt(uint64_t u) {
|
void IndirectUInt(uint64_t u) {
|
||||||
PushIndirect(u, TYPE_INDIRECT_UINT, WidthU(u));
|
PushIndirect(u, FBT_INDIRECT_UINT, WidthU(u));
|
||||||
}
|
}
|
||||||
void IndirectUInt(const char *key, uint64_t u) {
|
void IndirectUInt(const char *key, uint64_t u) {
|
||||||
Key(key);
|
Key(key);
|
||||||
@@ -915,7 +929,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IndirectFloat(float f) {
|
void IndirectFloat(float f) {
|
||||||
PushIndirect(f, TYPE_INDIRECT_FLOAT, BIT_WIDTH_32);
|
PushIndirect(f, FBT_INDIRECT_FLOAT, BIT_WIDTH_32);
|
||||||
}
|
}
|
||||||
void IndirectFloat(const char *key, float f) {
|
void IndirectFloat(const char *key, float f) {
|
||||||
Key(key);
|
Key(key);
|
||||||
@@ -923,7 +937,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IndirectDouble(double f) {
|
void IndirectDouble(double f) {
|
||||||
PushIndirect(f, TYPE_INDIRECT_FLOAT, WidthF(f));
|
PushIndirect(f, FBT_INDIRECT_FLOAT, WidthF(f));
|
||||||
}
|
}
|
||||||
void IndirectDouble(const char *key, double d) {
|
void IndirectDouble(const char *key, double d) {
|
||||||
Key(key);
|
Key(key);
|
||||||
@@ -944,7 +958,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
key_pool.insert(sloc);
|
key_pool.insert(sloc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stack_.push_back(Value(static_cast<uint64_t>(sloc), TYPE_KEY, BIT_WIDTH_8));
|
stack_.push_back(Value(static_cast<uint64_t>(sloc), FBT_KEY, BIT_WIDTH_8));
|
||||||
return sloc;
|
return sloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -953,7 +967,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
|
|
||||||
size_t String(const char *str, size_t len) {
|
size_t String(const char *str, size_t len) {
|
||||||
auto reset_to = buf_.size();
|
auto reset_to = buf_.size();
|
||||||
auto sloc = CreateBlob(str, len, 1, TYPE_STRING);
|
auto sloc = CreateBlob(str, len, 1, FBT_STRING);
|
||||||
if (flags_ & BUILDER_FLAG_SHARE_STRINGS) {
|
if (flags_ & BUILDER_FLAG_SHARE_STRINGS) {
|
||||||
StringOffset so(sloc, len);
|
StringOffset so(sloc, len);
|
||||||
auto it = string_pool.find(so);
|
auto it = string_pool.find(so);
|
||||||
@@ -991,10 +1005,10 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t Blob(const void *data, size_t len) {
|
size_t Blob(const void *data, size_t len) {
|
||||||
return CreateBlob(data, len, 0, TYPE_BLOB);
|
return CreateBlob(data, len, 0, FBT_BLOB);
|
||||||
}
|
}
|
||||||
size_t Blob(const std::vector<uint8_t> &v) {
|
size_t Blob(const std::vector<uint8_t> &v) {
|
||||||
return CreateBlob(flatbuffers::vector_data(v), v.size(), 0, TYPE_BLOB);
|
return CreateBlob(flatbuffers::vector_data(v), v.size(), 0, FBT_BLOB);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(wvo): support all the FlexBuffer types (like flexbuffers::String),
|
// TODO(wvo): support all the FlexBuffer types (like flexbuffers::String),
|
||||||
@@ -1026,11 +1040,11 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
// We should have interleaved keys and values on the stack.
|
// We should have interleaved keys and values on the stack.
|
||||||
// Make sure it is an even number:
|
// Make sure it is an even number:
|
||||||
auto len = stack_.size() - start;
|
auto len = stack_.size() - start;
|
||||||
assert(!(len & 1));
|
FLATBUFFERS_ASSERT(!(len & 1));
|
||||||
len /= 2;
|
len /= 2;
|
||||||
// Make sure keys are all strings:
|
// Make sure keys are all strings:
|
||||||
for (auto key = start; key < stack_.size(); key += 2) {
|
for (auto key = start; key < stack_.size(); key += 2) {
|
||||||
assert(stack_[key].type_ == TYPE_KEY);
|
FLATBUFFERS_ASSERT(stack_[key].type_ == FBT_KEY);
|
||||||
}
|
}
|
||||||
// Now sort values, so later we can do a binary seach lookup.
|
// Now sort values, so later we can do a binary seach lookup.
|
||||||
// We want to sort 2 array elements at a time.
|
// We want to sort 2 array elements at a time.
|
||||||
@@ -1061,7 +1075,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
// TODO: Have to check for pointer equality, as some sort
|
// TODO: Have to check for pointer equality, as some sort
|
||||||
// implementation apparently call this function with the same
|
// implementation apparently call this function with the same
|
||||||
// element?? Why?
|
// element?? Why?
|
||||||
assert(comp || &a == &b);
|
FLATBUFFERS_ASSERT(comp || &a == &b);
|
||||||
return comp < 0;
|
return comp < 0;
|
||||||
});
|
});
|
||||||
// First create a vector out of all keys.
|
// First create a vector out of all keys.
|
||||||
@@ -1141,9 +1155,9 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
template<typename T> size_t FixedTypedVector(const T *elems, size_t len) {
|
template<typename T> size_t FixedTypedVector(const T *elems, size_t len) {
|
||||||
// We only support a few fixed vector lengths. Anything bigger use a
|
// We only support a few fixed vector lengths. Anything bigger use a
|
||||||
// regular typed vector.
|
// regular typed vector.
|
||||||
assert(len >= 2 && len <= 4);
|
FLATBUFFERS_ASSERT(len >= 2 && len <= 4);
|
||||||
// And only scalar values.
|
// And only scalar values.
|
||||||
assert(flatbuffers::is_scalar<T>::value);
|
static_assert(flatbuffers::is_scalar<T>::value, "Unrelated types");
|
||||||
return ScalarVector(elems, len, true);
|
return ScalarVector(elems, len, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1222,7 +1236,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
// in a parent. You need to have exactly one root to finish a buffer.
|
// in a parent. You need to have exactly one root to finish a buffer.
|
||||||
// Check your Start/End calls are matched, and all objects are inside
|
// Check your Start/End calls are matched, and all objects are inside
|
||||||
// some other object.
|
// some other object.
|
||||||
assert(stack_.size() == 1);
|
FLATBUFFERS_ASSERT(stack_.size() == 1);
|
||||||
|
|
||||||
// Write root value.
|
// Write root value.
|
||||||
auto byte_width = Align(stack_[0].ElemWidth(buf_.size(), 0));
|
auto byte_width = Align(stack_[0].ElemWidth(buf_.size(), 0));
|
||||||
@@ -1240,7 +1254,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
// If you get this assert, you're attempting to get access a buffer
|
// If you get this assert, you're attempting to get access a buffer
|
||||||
// which hasn't been finished yet. Be sure to call
|
// which hasn't been finished yet. Be sure to call
|
||||||
// Builder::Finish with your root object.
|
// Builder::Finish with your root object.
|
||||||
assert(finished_);
|
FLATBUFFERS_ASSERT(finished_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Align to prepare for writing a scalar with a certain size.
|
// Align to prepare for writing a scalar with a certain size.
|
||||||
@@ -1257,7 +1271,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void Write(T val, size_t byte_width) {
|
template<typename T> void Write(T val, size_t byte_width) {
|
||||||
assert(sizeof(T) >= byte_width);
|
FLATBUFFERS_ASSERT(sizeof(T) >= byte_width);
|
||||||
val = flatbuffers::EndianScalar(val);
|
val = flatbuffers::EndianScalar(val);
|
||||||
WriteBytes(&val, byte_width);
|
WriteBytes(&val, byte_width);
|
||||||
}
|
}
|
||||||
@@ -1268,13 +1282,13 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
case 4: Write(static_cast<float>(f), byte_width); break;
|
case 4: Write(static_cast<float>(f), byte_width); break;
|
||||||
// case 2: Write(static_cast<half>(f), byte_width); break;
|
// case 2: Write(static_cast<half>(f), byte_width); break;
|
||||||
// case 1: Write(static_cast<quarter>(f), byte_width); break;
|
// case 1: Write(static_cast<quarter>(f), byte_width); break;
|
||||||
default: assert(0);
|
default: FLATBUFFERS_ASSERT(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WriteOffset(uint64_t o, uint8_t byte_width) {
|
void WriteOffset(uint64_t o, uint8_t byte_width) {
|
||||||
auto reloff = buf_.size() - o;
|
auto reloff = buf_.size() - o;
|
||||||
assert(byte_width == 8 || reloff < 1ULL << (byte_width * 8));
|
FLATBUFFERS_ASSERT(byte_width == 8 || reloff < 1ULL << (byte_width * 8));
|
||||||
Write(reloff, byte_width);
|
Write(reloff, byte_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1291,18 +1305,18 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
case 2: return BIT_WIDTH_16;
|
case 2: return BIT_WIDTH_16;
|
||||||
case 4: return BIT_WIDTH_32;
|
case 4: return BIT_WIDTH_32;
|
||||||
case 8: return BIT_WIDTH_64;
|
case 8: return BIT_WIDTH_64;
|
||||||
default: assert(false); return BIT_WIDTH_64;
|
default: FLATBUFFERS_ASSERT(false); return BIT_WIDTH_64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> static Type GetScalarType() {
|
template<typename T> static Type GetScalarType() {
|
||||||
assert(flatbuffers::is_scalar<T>::value);
|
static_assert(flatbuffers::is_scalar<T>::value, "Unrelated types");
|
||||||
return flatbuffers::is_floating_point<T>::value
|
return flatbuffers::is_floating_point<T>::value
|
||||||
? TYPE_FLOAT
|
? FBT_FLOAT
|
||||||
: flatbuffers::is_same<T, bool>::value
|
: flatbuffers::is_same<T, bool>::value
|
||||||
? TYPE_BOOL
|
? FBT_BOOL
|
||||||
: (flatbuffers::is_unsigned<T>::value ? TYPE_UINT
|
: (flatbuffers::is_unsigned<T>::value ? FBT_UINT
|
||||||
: TYPE_INT);
|
: FBT_INT);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Value {
|
struct Value {
|
||||||
@@ -1317,11 +1331,11 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
// For scalars: of itself, for vector: of its elements, for string: length.
|
// For scalars: of itself, for vector: of its elements, for string: length.
|
||||||
BitWidth min_bit_width_;
|
BitWidth min_bit_width_;
|
||||||
|
|
||||||
Value() : i_(0), type_(TYPE_NULL), min_bit_width_(BIT_WIDTH_8) {}
|
Value() : i_(0), type_(FBT_NULL), min_bit_width_(BIT_WIDTH_8) {}
|
||||||
|
|
||||||
Value(bool b)
|
Value(bool b)
|
||||||
: u_(static_cast<uint64_t>(b)),
|
: u_(static_cast<uint64_t>(b)),
|
||||||
type_(TYPE_BOOL),
|
type_(FBT_BOOL),
|
||||||
min_bit_width_(BIT_WIDTH_8) {}
|
min_bit_width_(BIT_WIDTH_8) {}
|
||||||
|
|
||||||
Value(int64_t i, Type t, BitWidth bw)
|
Value(int64_t i, Type t, BitWidth bw)
|
||||||
@@ -1329,8 +1343,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
Value(uint64_t u, Type t, BitWidth bw)
|
Value(uint64_t u, Type t, BitWidth bw)
|
||||||
: u_(u), type_(t), min_bit_width_(bw) {}
|
: u_(u), type_(t), min_bit_width_(bw) {}
|
||||||
|
|
||||||
Value(float f) : f_(f), type_(TYPE_FLOAT), min_bit_width_(BIT_WIDTH_32) {}
|
Value(float f) : f_(f), type_(FBT_FLOAT), min_bit_width_(BIT_WIDTH_32) {}
|
||||||
Value(double f) : f_(f), type_(TYPE_FLOAT), min_bit_width_(WidthF(f)) {}
|
Value(double f) : f_(f), type_(FBT_FLOAT), min_bit_width_(WidthF(f)) {}
|
||||||
|
|
||||||
uint8_t StoredPackedType(BitWidth parent_bit_width_ = BIT_WIDTH_8) const {
|
uint8_t StoredPackedType(BitWidth parent_bit_width_ = BIT_WIDTH_8) const {
|
||||||
return PackedType(StoredWidth(parent_bit_width_), type_);
|
return PackedType(StoredWidth(parent_bit_width_), type_);
|
||||||
@@ -1360,7 +1374,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
byte_width)
|
byte_width)
|
||||||
return bit_width;
|
return bit_width;
|
||||||
}
|
}
|
||||||
assert(false); // Must match one of the sizes above.
|
FLATBUFFERS_ASSERT(false); // Must match one of the sizes above.
|
||||||
return BIT_WIDTH_64;
|
return BIT_WIDTH_64;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1376,11 +1390,11 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
|
|
||||||
void WriteAny(const Value &val, uint8_t byte_width) {
|
void WriteAny(const Value &val, uint8_t byte_width) {
|
||||||
switch (val.type_) {
|
switch (val.type_) {
|
||||||
case TYPE_NULL:
|
case FBT_NULL:
|
||||||
case TYPE_INT: Write(val.i_, byte_width); break;
|
case FBT_INT: Write(val.i_, byte_width); break;
|
||||||
case TYPE_BOOL:
|
case FBT_BOOL:
|
||||||
case TYPE_UINT: Write(val.u_, byte_width); break;
|
case FBT_UINT: Write(val.u_, byte_width); break;
|
||||||
case TYPE_FLOAT: WriteDouble(val.f_, byte_width); break;
|
case FBT_FLOAT: WriteDouble(val.f_, byte_width); break;
|
||||||
default: WriteOffset(val.u_, byte_width); break;
|
default: WriteOffset(val.u_, byte_width); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1405,7 +1419,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
// byte vector > 255 elements). For such types, write a "blob" instead.
|
// byte vector > 255 elements). For such types, write a "blob" instead.
|
||||||
// TODO: instead of asserting, could write vector with larger elements
|
// TODO: instead of asserting, could write vector with larger elements
|
||||||
// instead, though that would be wasteful.
|
// instead, though that would be wasteful.
|
||||||
assert(WidthU(len) <= bit_width);
|
FLATBUFFERS_ASSERT(WidthU(len) <= bit_width);
|
||||||
if (!fixed) Write<uint64_t>(len, byte_width);
|
if (!fixed) Write<uint64_t>(len, byte_width);
|
||||||
auto vloc = buf_.size();
|
auto vloc = buf_.size();
|
||||||
for (size_t i = 0; i < len; i++) Write(elems[i], byte_width);
|
for (size_t i = 0; i < len; i++) Write(elems[i], byte_width);
|
||||||
@@ -1417,6 +1431,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
|
|
||||||
Value CreateVector(size_t start, size_t vec_len, size_t step, bool typed,
|
Value CreateVector(size_t start, size_t vec_len, size_t step, bool typed,
|
||||||
bool fixed, const Value *keys = nullptr) {
|
bool fixed, const Value *keys = nullptr) {
|
||||||
|
FLATBUFFERS_ASSERT(!fixed || typed); // typed=false, fixed=true combination is not supported.
|
||||||
// Figure out smallest bit width we can store this vector with.
|
// Figure out smallest bit width we can store this vector with.
|
||||||
auto bit_width = (std::max)(force_min_bit_width_, WidthU(vec_len));
|
auto bit_width = (std::max)(force_min_bit_width_, WidthU(vec_len));
|
||||||
auto prefix_elems = 1;
|
auto prefix_elems = 1;
|
||||||
@@ -1426,7 +1441,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
bit_width = (std::max)(bit_width, keys->ElemWidth(buf_.size(), 0));
|
bit_width = (std::max)(bit_width, keys->ElemWidth(buf_.size(), 0));
|
||||||
prefix_elems += 2;
|
prefix_elems += 2;
|
||||||
}
|
}
|
||||||
Type vector_type = TYPE_KEY;
|
Type vector_type = FBT_KEY;
|
||||||
// Check bit widths and types for all elements.
|
// Check bit widths and types for all elements.
|
||||||
for (size_t i = start; i < stack_.size(); i += step) {
|
for (size_t i = start; i < stack_.size(); i += step) {
|
||||||
auto elem_width = stack_[i].ElemWidth(buf_.size(), i + prefix_elems);
|
auto elem_width = stack_[i].ElemWidth(buf_.size(), i + prefix_elems);
|
||||||
@@ -1437,13 +1452,13 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
} else {
|
} else {
|
||||||
// If you get this assert, you are writing a typed vector with
|
// If you get this assert, you are writing a typed vector with
|
||||||
// elements that are not all the same type.
|
// elements that are not all the same type.
|
||||||
assert(vector_type == stack_[i].type_);
|
FLATBUFFERS_ASSERT(vector_type == stack_[i].type_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If you get this assert, your fixed types are not one of:
|
// If you get this assert, your fixed types are not one of:
|
||||||
// Int / UInt / Float / Key.
|
// Int / UInt / Float / Key.
|
||||||
assert(IsTypedVectorElementType(vector_type));
|
FLATBUFFERS_ASSERT(!fixed || IsTypedVectorElementType(vector_type));
|
||||||
auto byte_width = Align(bit_width);
|
auto byte_width = Align(bit_width);
|
||||||
// Write vector. First the keys width/offset if available, and size.
|
// Write vector. First the keys width/offset if available, and size.
|
||||||
if (keys) {
|
if (keys) {
|
||||||
@@ -1463,9 +1478,9 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Value(static_cast<uint64_t>(vloc),
|
return Value(static_cast<uint64_t>(vloc),
|
||||||
keys ? TYPE_MAP
|
keys ? FBT_MAP
|
||||||
: (typed ? ToTypedVector(vector_type, fixed ? vec_len : 0)
|
: (typed ? ToTypedVector(vector_type, fixed ? vec_len : 0)
|
||||||
: TYPE_VECTOR),
|
: FBT_VECTOR),
|
||||||
bit_width);
|
bit_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1483,7 +1498,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
BitWidth force_min_bit_width_;
|
BitWidth force_min_bit_width_;
|
||||||
|
|
||||||
struct KeyOffsetCompare {
|
struct KeyOffsetCompare {
|
||||||
KeyOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {}
|
explicit KeyOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {}
|
||||||
bool operator()(size_t a, size_t b) const {
|
bool operator()(size_t a, size_t b) const {
|
||||||
auto stra =
|
auto stra =
|
||||||
reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + a);
|
reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + a);
|
||||||
@@ -1496,7 +1511,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
|||||||
|
|
||||||
typedef std::pair<size_t, size_t> StringOffset;
|
typedef std::pair<size_t, size_t> StringOffset;
|
||||||
struct StringOffsetCompare {
|
struct StringOffsetCompare {
|
||||||
StringOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {}
|
explicit StringOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {}
|
||||||
bool operator()(const StringOffset &a, const StringOffset &b) const {
|
bool operator()(const StringOffset &a, const StringOffset &b) const {
|
||||||
auto stra = reinterpret_cast<const char *>(
|
auto stra = reinterpret_cast<const char *>(
|
||||||
flatbuffers::vector_data(*buf_) + a.first);
|
flatbuffers::vector_data(*buf_) + a.first);
|
||||||
|
|||||||
@@ -88,17 +88,35 @@ class SliceAllocator : public Allocator {
|
|||||||
SliceAllocator(const SliceAllocator &other) = delete;
|
SliceAllocator(const SliceAllocator &other) = delete;
|
||||||
SliceAllocator &operator=(const SliceAllocator &other) = delete;
|
SliceAllocator &operator=(const SliceAllocator &other) = delete;
|
||||||
|
|
||||||
|
SliceAllocator(SliceAllocator &&other)
|
||||||
|
: slice_(grpc_empty_slice()) {
|
||||||
|
// default-construct and swap idiom
|
||||||
|
swap(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
SliceAllocator &operator=(SliceAllocator &&other) {
|
||||||
|
// move-construct and swap idiom
|
||||||
|
SliceAllocator temp(std::move(other));
|
||||||
|
swap(temp);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(SliceAllocator &other) {
|
||||||
|
using std::swap;
|
||||||
|
swap(slice_, other.slice_);
|
||||||
|
}
|
||||||
|
|
||||||
virtual ~SliceAllocator() { grpc_slice_unref(slice_); }
|
virtual ~SliceAllocator() { grpc_slice_unref(slice_); }
|
||||||
|
|
||||||
virtual uint8_t *allocate(size_t size) override {
|
virtual uint8_t *allocate(size_t size) override {
|
||||||
assert(GRPC_SLICE_IS_EMPTY(slice_));
|
FLATBUFFERS_ASSERT(GRPC_SLICE_IS_EMPTY(slice_));
|
||||||
slice_ = grpc_slice_malloc(size);
|
slice_ = grpc_slice_malloc(size);
|
||||||
return GRPC_SLICE_START_PTR(slice_);
|
return GRPC_SLICE_START_PTR(slice_);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void deallocate(uint8_t *p, size_t size) override {
|
virtual void deallocate(uint8_t *p, size_t size) override {
|
||||||
assert(p == GRPC_SLICE_START_PTR(slice_));
|
FLATBUFFERS_ASSERT(p == GRPC_SLICE_START_PTR(slice_));
|
||||||
assert(size == GRPC_SLICE_LENGTH(slice_));
|
FLATBUFFERS_ASSERT(size == GRPC_SLICE_LENGTH(slice_));
|
||||||
grpc_slice_unref(slice_);
|
grpc_slice_unref(slice_);
|
||||||
slice_ = grpc_empty_slice();
|
slice_ = grpc_empty_slice();
|
||||||
}
|
}
|
||||||
@@ -106,9 +124,9 @@ 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, size_t in_use_back,
|
size_t new_size, size_t in_use_back,
|
||||||
size_t in_use_front) override {
|
size_t in_use_front) override {
|
||||||
assert(old_p == GRPC_SLICE_START_PTR(slice_));
|
FLATBUFFERS_ASSERT(old_p == GRPC_SLICE_START_PTR(slice_));
|
||||||
assert(old_size == GRPC_SLICE_LENGTH(slice_));
|
FLATBUFFERS_ASSERT(old_size == GRPC_SLICE_LENGTH(slice_));
|
||||||
assert(new_size > old_size);
|
FLATBUFFERS_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);
|
||||||
@@ -121,8 +139,8 @@ class SliceAllocator : public Allocator {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
grpc_slice &get_slice(uint8_t *p, size_t size) {
|
grpc_slice &get_slice(uint8_t *p, size_t size) {
|
||||||
assert(p == GRPC_SLICE_START_PTR(slice_));
|
FLATBUFFERS_ASSERT(p == GRPC_SLICE_START_PTR(slice_));
|
||||||
assert(size == GRPC_SLICE_LENGTH(slice_));
|
FLATBUFFERS_ASSERT(size == GRPC_SLICE_LENGTH(slice_));
|
||||||
return slice_;
|
return slice_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,11 +164,68 @@ 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;
|
||||||
|
|
||||||
|
MessageBuilder(MessageBuilder &&other)
|
||||||
|
: FlatBufferBuilder(1024, &slice_allocator_, false) {
|
||||||
|
// Default construct and swap idiom.
|
||||||
|
Swap(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a MessageBuilder from a FlatBufferBuilder.
|
||||||
|
explicit MessageBuilder(FlatBufferBuilder &&src, void (*dealloc)(void*, size_t) = &DefaultAllocator::dealloc)
|
||||||
|
: FlatBufferBuilder(1024, &slice_allocator_, false) {
|
||||||
|
src.Swap(*this);
|
||||||
|
src.SwapBufAllocator(*this);
|
||||||
|
if (buf_.capacity()) {
|
||||||
|
uint8_t *buf = buf_.scratch_data(); // pointer to memory
|
||||||
|
size_t capacity = buf_.capacity(); // size of memory
|
||||||
|
slice_allocator_.slice_ = grpc_slice_new_with_len(buf, capacity, dealloc);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
slice_allocator_.slice_ = grpc_empty_slice();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Move-assign a FlatBufferBuilder to a MessageBuilder.
|
||||||
|
/// Only FlatBufferBuilder with default allocator (basically, nullptr) is supported.
|
||||||
|
MessageBuilder &operator=(FlatBufferBuilder &&src) {
|
||||||
|
// Move construct a temporary and swap
|
||||||
|
MessageBuilder temp(std::move(src));
|
||||||
|
Swap(temp);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageBuilder &operator=(MessageBuilder &&other) {
|
||||||
|
// Move construct a temporary and swap
|
||||||
|
MessageBuilder temp(std::move(other));
|
||||||
|
Swap(temp);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Swap(MessageBuilder &other) {
|
||||||
|
slice_allocator_.swap(other.slice_allocator_);
|
||||||
|
FlatBufferBuilder::Swap(other);
|
||||||
|
// After swapping the FlatBufferBuilder, we swap back the allocator, which restores
|
||||||
|
// the original allocator back in place. This is necessary because MessageBuilder's
|
||||||
|
// allocator is its own member (SliceAllocatorMember). The allocator passed to
|
||||||
|
// FlatBufferBuilder::vector_downward must point to this member.
|
||||||
|
buf_.swap_allocator(other.buf_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Releases the ownership of the buffer pointer.
|
||||||
|
// Returns the size, offset, and the original grpc_slice that
|
||||||
|
// allocated the buffer. Also see grpc_slice_unref().
|
||||||
|
uint8_t *ReleaseRaw(size_t &size, size_t &offset, grpc_slice &slice) {
|
||||||
|
uint8_t *buf = FlatBufferBuilder::ReleaseRaw(size, offset);
|
||||||
|
slice = slice_allocator_.slice_;
|
||||||
|
slice_allocator_.slice_ = grpc_empty_slice();
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
~MessageBuilder() {}
|
~MessageBuilder() {}
|
||||||
|
|
||||||
// GetMessage extracts the subslice of the buffer corresponding to the
|
// GetMessage extracts the subslice of the buffer corresponding to the
|
||||||
@@ -162,10 +237,10 @@ class MessageBuilder : private detail::SliceAllocatorMember,
|
|||||||
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
|
||||||
// Do some sanity checks on data/size
|
// Do some sanity checks on data/size
|
||||||
assert(msg_data);
|
FLATBUFFERS_ASSERT(msg_data);
|
||||||
assert(msg_size);
|
FLATBUFFERS_ASSERT(msg_size);
|
||||||
assert(msg_data >= buf_data);
|
FLATBUFFERS_ASSERT(msg_data >= buf_data);
|
||||||
assert(msg_data + msg_size <= buf_data + buf_size);
|
FLATBUFFERS_ASSERT(msg_data + msg_size <= buf_data + buf_size);
|
||||||
// Calculate offsets from the buffer start
|
// Calculate offsets from the buffer start
|
||||||
auto begin = msg_data - buf_data;
|
auto begin = msg_data - buf_data;
|
||||||
auto end = begin + msg_size;
|
auto end = begin + msg_size;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ template<> struct FnvTraits<uint64_t> {
|
|||||||
static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL;
|
static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> FLATBUFFERS_CONSTEXPR_CPP14 T HashFnv1(const char *input) {
|
template<typename T> 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;
|
||||||
@@ -48,7 +48,7 @@ template<typename T> FLATBUFFERS_CONSTEXPR_CPP14 T HashFnv1(const char *input) {
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> FLATBUFFERS_CONSTEXPR_CPP14 T HashFnv1a(const char *input) {
|
template<typename T> 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);
|
||||||
@@ -57,12 +57,12 @@ template<typename T> FLATBUFFERS_CONSTEXPR_CPP14 T HashFnv1a(const char *input)
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> FLATBUFFERS_CONSTEXPR_CPP14 inline uint16_t HashFnv1<uint16_t>(const char *input) {
|
template <> inline uint16_t HashFnv1<uint16_t>(const char *input) {
|
||||||
uint32_t hash = HashFnv1<uint32_t>(input);
|
uint32_t hash = HashFnv1<uint32_t>(input);
|
||||||
return (hash >> 16) ^ (hash & 0xffff);
|
return (hash >> 16) ^ (hash & 0xffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> FLATBUFFERS_CONSTEXPR_CPP14 inline uint16_t HashFnv1a<uint16_t>(const char *input) {
|
template <> inline uint16_t HashFnv1a<uint16_t>(const char *input) {
|
||||||
uint32_t hash = HashFnv1a<uint32_t>(input);
|
uint32_t hash = HashFnv1a<uint32_t>(input);
|
||||||
return (hash >> 16) ^ (hash & 0xffff);
|
return (hash >> 16) ^ (hash & 0xffff);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,12 @@
|
|||||||
// 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.
|
||||||
|
|
||||||
|
// Limits maximum depth of nested objects.
|
||||||
|
// Prevents stack overflow while parse flatbuffers or json.
|
||||||
|
#if !defined(FLATBUFFERS_MAX_PARSING_DEPTH)
|
||||||
|
# define FLATBUFFERS_MAX_PARSING_DEPTH 64
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace flatbuffers {
|
namespace flatbuffers {
|
||||||
|
|
||||||
// The order of these matters for Is*() functions below.
|
// The order of these matters for Is*() functions below.
|
||||||
@@ -41,24 +47,24 @@ namespace flatbuffers {
|
|||||||
// of type tokens.
|
// of type tokens.
|
||||||
// clang-format off
|
// 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, u8) \
|
||||||
TD(UTYPE, "", uint8_t, byte, byte, byte, uint8) /* begin scalar/int */ \
|
TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8) /* begin scalar/int */ \
|
||||||
TD(BOOL, "bool", uint8_t, boolean,byte, bool, bool) \
|
TD(BOOL, "bool", uint8_t, boolean,bool, bool, bool, bool) \
|
||||||
TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8) \
|
TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8) \
|
||||||
TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8) \
|
TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8) \
|
||||||
TD(SHORT, "short", int16_t, short, int16, short, int16) \
|
TD(SHORT, "short", int16_t, short, int16, short, int16, i16) \
|
||||||
TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16) \
|
TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16, u16) \
|
||||||
TD(INT, "int", int32_t, int, int32, int, int32) \
|
TD(INT, "int", int32_t, int, int32, int, int32, i32) \
|
||||||
TD(UINT, "uint", uint32_t, int, uint32, uint, uint32) \
|
TD(UINT, "uint", uint32_t, int, uint32, uint, uint32, u32) \
|
||||||
TD(LONG, "long", int64_t, long, int64, long, int64) \
|
TD(LONG, "long", int64_t, long, int64, long, int64, i64) \
|
||||||
TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64) /* end int */ \
|
TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64, u64) /* end int */ \
|
||||||
TD(FLOAT, "float", float, float, float32, float, float32) /* begin float */ \
|
TD(FLOAT, "float", float, float, float32, float, float32, f32) /* begin float */ \
|
||||||
TD(DOUBLE, "double", double, double, float64, double, float64) /* end float/scalar */
|
TD(DOUBLE, "double", double, double, float64, double, float64, f64) /* end float/scalar */
|
||||||
#define FLATBUFFERS_GEN_TYPES_POINTER(TD) \
|
#define FLATBUFFERS_GEN_TYPES_POINTER(TD) \
|
||||||
TD(STRING, "string", Offset<void>, int, int, StringOffset, int) \
|
TD(STRING, "string", Offset<void>, int, int, StringOffset, int, unused) \
|
||||||
TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int) \
|
TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused) \
|
||||||
TD(STRUCT, "", Offset<void>, int, int, int, int) \
|
TD(STRUCT, "", Offset<void>, int, int, int, int, unused) \
|
||||||
TD(UNION, "", Offset<void>, int, int, int, int)
|
TD(UNION, "", Offset<void>, int, int, int, int, unused)
|
||||||
|
|
||||||
// The fields are:
|
// The fields are:
|
||||||
// - enum
|
// - enum
|
||||||
@@ -68,12 +74,14 @@ namespace flatbuffers {
|
|||||||
// - Go type.
|
// - Go type.
|
||||||
// - C# / .Net type.
|
// - C# / .Net type.
|
||||||
// - Python type.
|
// - Python type.
|
||||||
|
// - Rust type.
|
||||||
|
|
||||||
// using these macros, we can now write code dealing with types just once, e.g.
|
// using these macros, we can now write code dealing with types just once, e.g.
|
||||||
|
|
||||||
/*
|
/*
|
||||||
switch (type) {
|
switch (type) {
|
||||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
|
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
|
||||||
|
RTYPE) \
|
||||||
case BASE_TYPE_ ## ENUM: \
|
case BASE_TYPE_ ## ENUM: \
|
||||||
// do something specific to CTYPE here
|
// do something specific to CTYPE here
|
||||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||||
@@ -90,13 +98,15 @@ switch (type) {
|
|||||||
__extension__ // Stop GCC complaining about trailing comma with -Wpendantic.
|
__extension__ // Stop GCC complaining about trailing comma with -Wpendantic.
|
||||||
#endif
|
#endif
|
||||||
enum BaseType {
|
enum BaseType {
|
||||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
|
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
|
||||||
|
RTYPE) \
|
||||||
BASE_TYPE_ ## ENUM,
|
BASE_TYPE_ ## ENUM,
|
||||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||||
#undef FLATBUFFERS_TD
|
#undef FLATBUFFERS_TD
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
|
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
|
||||||
|
RTYPE) \
|
||||||
static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \
|
static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \
|
||||||
"define largest_scalar_t as " #CTYPE);
|
"define largest_scalar_t as " #CTYPE);
|
||||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||||
@@ -111,6 +121,8 @@ inline bool IsFloat (BaseType t) { return t == BASE_TYPE_FLOAT ||
|
|||||||
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; }
|
inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; }
|
||||||
|
inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE &&
|
||||||
|
t <= BASE_TYPE_UCHAR; }
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
extern const char *const kTypeNames[];
|
extern const char *const kTypeNames[];
|
||||||
@@ -141,6 +153,8 @@ struct Type {
|
|||||||
|
|
||||||
Offset<reflection::Type> Serialize(FlatBufferBuilder *builder) const;
|
Offset<reflection::Type> Serialize(FlatBufferBuilder *builder) const;
|
||||||
|
|
||||||
|
bool Deserialize(const Parser &parser, const reflection::Type *type);
|
||||||
|
|
||||||
BaseType base_type;
|
BaseType base_type;
|
||||||
BaseType element; // only set if t == BASE_TYPE_VECTOR
|
BaseType element; // only set if t == BASE_TYPE_VECTOR
|
||||||
StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT
|
StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT
|
||||||
@@ -181,7 +195,7 @@ template<typename T> class SymbolTable {
|
|||||||
dict.erase(it);
|
dict.erase(it);
|
||||||
dict[newname] = obj;
|
dict[newname] = obj;
|
||||||
} else {
|
} else {
|
||||||
assert(false);
|
FLATBUFFERS_ASSERT(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,6 +237,9 @@ struct Definition {
|
|||||||
flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
|
flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
|
||||||
SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
|
SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||||
|
|
||||||
|
bool DeserializeAttributes(Parser &parser,
|
||||||
|
const Vector<Offset<reflection::KeyValue>> *attrs);
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::string file;
|
std::string file;
|
||||||
std::vector<std::string> doc_comment;
|
std::vector<std::string> doc_comment;
|
||||||
@@ -241,6 +258,7 @@ struct FieldDef : public Definition {
|
|||||||
: deprecated(false),
|
: deprecated(false),
|
||||||
required(false),
|
required(false),
|
||||||
key(false),
|
key(false),
|
||||||
|
shared(false),
|
||||||
native_inline(false),
|
native_inline(false),
|
||||||
flexbuffer(false),
|
flexbuffer(false),
|
||||||
nested_flatbuffer(NULL),
|
nested_flatbuffer(NULL),
|
||||||
@@ -249,11 +267,15 @@ struct FieldDef : public Definition {
|
|||||||
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;
|
||||||
|
|
||||||
|
bool Deserialize(Parser &parser, const reflection::Field *field);
|
||||||
|
|
||||||
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 shared; // Field will be using string pooling (i.e. CreateSharedString)
|
||||||
|
// as default serialization behavior if field is a string.
|
||||||
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.
|
||||||
@@ -279,6 +301,8 @@ struct StructDef : public Definition {
|
|||||||
Offset<reflection::Object> Serialize(FlatBufferBuilder *builder,
|
Offset<reflection::Object> Serialize(FlatBufferBuilder *builder,
|
||||||
const Parser &parser) const;
|
const Parser &parser) const;
|
||||||
|
|
||||||
|
bool Deserialize(Parser &parser, const reflection::Object *object);
|
||||||
|
|
||||||
SymbolTable<FieldDef> fields;
|
SymbolTable<FieldDef> fields;
|
||||||
|
|
||||||
bool fixed; // If it's struct, not a table.
|
bool fixed; // If it's struct, not a table.
|
||||||
@@ -305,8 +329,13 @@ inline size_t InlineAlignment(const Type &type) {
|
|||||||
|
|
||||||
struct EnumVal {
|
struct EnumVal {
|
||||||
EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
|
EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
|
||||||
|
EnumVal() : value(0) {}
|
||||||
|
|
||||||
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder) const;
|
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||||
|
|
||||||
|
bool Deserialize(const Parser &parser, const reflection::EnumVal *val);
|
||||||
|
bool IsZero() const { return 0 == value; }
|
||||||
|
bool IsNonZero() const { return !IsZero(); }
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
std::vector<std::string> doc_comment;
|
std::vector<std::string> doc_comment;
|
||||||
@@ -315,23 +344,32 @@ struct EnumVal {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct EnumDef : public Definition {
|
struct EnumDef : public Definition {
|
||||||
EnumDef() : is_union(false), uses_type_aliases(false) {}
|
EnumDef() : is_union(false), uses_multiple_type_instances(false) {}
|
||||||
|
|
||||||
EnumVal *ReverseLookup(int64_t enum_idx, bool skip_union_default = true) {
|
EnumVal *ReverseLookup(int64_t enum_idx, bool skip_union_default = true) {
|
||||||
for (auto it = vals.vec.begin() +
|
for (auto it = Vals().begin() +
|
||||||
static_cast<int>(is_union && skip_union_default);
|
static_cast<int>(is_union && skip_union_default);
|
||||||
it != vals.vec.end(); ++it) {
|
it != Vals().end(); ++it) {
|
||||||
if ((*it)->value == enum_idx) { return *it; }
|
if ((*it)->value == enum_idx) { return *it; }
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder,
|
Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||||
const Parser &parser) const;
|
|
||||||
|
bool Deserialize(Parser &parser, const reflection::Enum *values);
|
||||||
|
|
||||||
|
size_t size() const { return vals.vec.size(); }
|
||||||
|
|
||||||
|
const std::vector<EnumVal *> &Vals() const {
|
||||||
|
return vals.vec;
|
||||||
|
}
|
||||||
|
|
||||||
SymbolTable<EnumVal> vals;
|
SymbolTable<EnumVal> vals;
|
||||||
bool is_union;
|
bool is_union;
|
||||||
bool uses_type_aliases;
|
// Type is a union which uses type aliases where at least one type is
|
||||||
|
// available under two different names.
|
||||||
|
bool uses_multiple_type_instances;
|
||||||
Type underlying_type;
|
Type underlying_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -342,14 +380,18 @@ inline bool EqualByName(const Type &a, const Type &b) {
|
|||||||
(a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name);
|
(a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct RPCCall {
|
struct RPCCall : public Definition {
|
||||||
std::string name;
|
Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||||
SymbolTable<Value> attributes;
|
|
||||||
|
bool Deserialize(Parser &parser, const reflection::RPCCall *call);
|
||||||
|
|
||||||
StructDef *request, *response;
|
StructDef *request, *response;
|
||||||
std::vector<std::string> rpc_comment;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ServiceDef : public Definition {
|
struct ServiceDef : public Definition {
|
||||||
|
Offset<reflection::Service> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||||
|
bool Deserialize(Parser &parser, const reflection::Service *service);
|
||||||
|
|
||||||
SymbolTable<RPCCall> calls;
|
SymbolTable<RPCCall> calls;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -358,6 +400,7 @@ struct IDLOptions {
|
|||||||
bool strict_json;
|
bool strict_json;
|
||||||
bool skip_js_exports;
|
bool skip_js_exports;
|
||||||
bool use_goog_js_export_format;
|
bool use_goog_js_export_format;
|
||||||
|
bool use_ES6_js_export_format;
|
||||||
bool output_default_scalars_in_json;
|
bool output_default_scalars_in_json;
|
||||||
int indent_step;
|
int indent_step;
|
||||||
bool output_enum_identifiers;
|
bool output_enum_identifiers;
|
||||||
@@ -372,22 +415,30 @@ struct IDLOptions {
|
|||||||
bool skip_unexpected_fields_in_json;
|
bool skip_unexpected_fields_in_json;
|
||||||
bool generate_name_strings;
|
bool generate_name_strings;
|
||||||
bool generate_object_based_api;
|
bool generate_object_based_api;
|
||||||
|
bool gen_compare;
|
||||||
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 cpp_object_api_string_flexible_constructor;
|
||||||
bool gen_nullable;
|
bool gen_nullable;
|
||||||
|
bool gen_generated;
|
||||||
std::string object_prefix;
|
std::string object_prefix;
|
||||||
std::string object_suffix;
|
std::string object_suffix;
|
||||||
bool union_value_namespacing;
|
bool union_value_namespacing;
|
||||||
bool allow_non_utf8;
|
bool allow_non_utf8;
|
||||||
|
bool natural_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 binary_schema_builtins;
|
||||||
bool skip_flatbuffers_import;
|
bool skip_flatbuffers_import;
|
||||||
std::string go_import;
|
std::string go_import;
|
||||||
std::string go_namespace;
|
std::string go_namespace;
|
||||||
bool reexport_ts_modules;
|
bool reexport_ts_modules;
|
||||||
|
bool js_ts_short_names;
|
||||||
bool protobuf_ascii_alike;
|
bool protobuf_ascii_alike;
|
||||||
bool size_prefixed;
|
bool size_prefixed;
|
||||||
|
std::string root_type;
|
||||||
|
bool force_defaults;
|
||||||
|
|
||||||
// Possible options for the more general generator below.
|
// Possible options for the more general generator below.
|
||||||
enum Language {
|
enum Language {
|
||||||
@@ -402,6 +453,10 @@ struct IDLOptions {
|
|||||||
kBinary = 1 << 8,
|
kBinary = 1 << 8,
|
||||||
kTs = 1 << 9,
|
kTs = 1 << 9,
|
||||||
kJsonSchema = 1 << 10,
|
kJsonSchema = 1 << 10,
|
||||||
|
kDart = 1 << 11,
|
||||||
|
kLua = 1 << 12,
|
||||||
|
kLobster = 1 << 13,
|
||||||
|
kRust = 1 << 14,
|
||||||
kMAX
|
kMAX
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -415,10 +470,15 @@ struct IDLOptions {
|
|||||||
// for code generation.
|
// for code generation.
|
||||||
unsigned long lang_to_generate;
|
unsigned long lang_to_generate;
|
||||||
|
|
||||||
|
// If set (default behavior), empty string and vector fields will be set to
|
||||||
|
// nullptr to make the flatbuffer more compact.
|
||||||
|
bool set_empty_to_null;
|
||||||
|
|
||||||
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),
|
||||||
|
use_ES6_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),
|
output_enum_identifiers(true),
|
||||||
@@ -433,31 +493,65 @@ struct IDLOptions {
|
|||||||
skip_unexpected_fields_in_json(false),
|
skip_unexpected_fields_in_json(false),
|
||||||
generate_name_strings(false),
|
generate_name_strings(false),
|
||||||
generate_object_based_api(false),
|
generate_object_based_api(false),
|
||||||
|
gen_compare(false),
|
||||||
cpp_object_api_pointer_type("std::unique_ptr"),
|
cpp_object_api_pointer_type("std::unique_ptr"),
|
||||||
|
cpp_object_api_string_flexible_constructor(false),
|
||||||
gen_nullable(false),
|
gen_nullable(false),
|
||||||
|
gen_generated(false),
|
||||||
object_suffix("T"),
|
object_suffix("T"),
|
||||||
union_value_namespacing(true),
|
union_value_namespacing(true),
|
||||||
allow_non_utf8(false),
|
allow_non_utf8(false),
|
||||||
|
natural_utf8(false),
|
||||||
keep_include_path(false),
|
keep_include_path(false),
|
||||||
binary_schema_comments(false),
|
binary_schema_comments(false),
|
||||||
|
binary_schema_builtins(false),
|
||||||
skip_flatbuffers_import(false),
|
skip_flatbuffers_import(false),
|
||||||
reexport_ts_modules(true),
|
reexport_ts_modules(true),
|
||||||
|
js_ts_short_names(false),
|
||||||
protobuf_ascii_alike(false),
|
protobuf_ascii_alike(false),
|
||||||
size_prefixed(false),
|
size_prefixed(false),
|
||||||
|
force_defaults(false),
|
||||||
lang(IDLOptions::kJava),
|
lang(IDLOptions::kJava),
|
||||||
mini_reflect(IDLOptions::kNone),
|
mini_reflect(IDLOptions::kNone),
|
||||||
lang_to_generate(0) {}
|
lang_to_generate(0),
|
||||||
|
set_empty_to_null(true) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// This encapsulates where the parser is in the current source file.
|
// This encapsulates where the parser is in the current source file.
|
||||||
struct ParserState {
|
struct ParserState {
|
||||||
ParserState() : cursor_(nullptr), line_(1), token_(-1) {}
|
ParserState()
|
||||||
|
: cursor_(nullptr),
|
||||||
|
line_start_(nullptr),
|
||||||
|
line_(0),
|
||||||
|
token_(-1),
|
||||||
|
attr_is_trivial_ascii_string_(true) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
void ResetState(const char *source) {
|
||||||
|
cursor_ = source;
|
||||||
|
line_ = 0;
|
||||||
|
MarkNewLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MarkNewLine() {
|
||||||
|
line_start_ = cursor_;
|
||||||
|
line_ += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t CursorPosition() const {
|
||||||
|
FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_);
|
||||||
|
return static_cast<int64_t>(cursor_ - line_start_);
|
||||||
|
}
|
||||||
|
|
||||||
const char *cursor_;
|
const char *cursor_;
|
||||||
|
const char *line_start_;
|
||||||
int line_; // the current line being parsed
|
int line_; // the current line being parsed
|
||||||
int token_;
|
int token_;
|
||||||
|
|
||||||
|
// Flag: text in attribute_ is true ASCII string without escape
|
||||||
|
// sequences. Only printable ASCII (without [\t\r\n]).
|
||||||
|
// Used for number-in-string (and base64 string in future).
|
||||||
|
bool attr_is_trivial_ascii_string_;
|
||||||
std::string attribute_;
|
std::string attribute_;
|
||||||
std::vector<std::string> doc_comment_;
|
std::vector<std::string> doc_comment_;
|
||||||
};
|
};
|
||||||
@@ -485,7 +579,7 @@ class CheckedError {
|
|||||||
*this = other; // Use assignment operator.
|
*this = other; // Use assignment operator.
|
||||||
}
|
}
|
||||||
|
|
||||||
~CheckedError() { assert(has_been_checked_); }
|
~CheckedError() { FLATBUFFERS_ASSERT(has_been_checked_); }
|
||||||
|
|
||||||
bool Check() {
|
bool Check() {
|
||||||
has_been_checked_ = true;
|
has_been_checked_ = true;
|
||||||
@@ -517,7 +611,11 @@ class Parser : public ParserState {
|
|||||||
opts(options),
|
opts(options),
|
||||||
uses_flexbuffers_(false),
|
uses_flexbuffers_(false),
|
||||||
source_(nullptr),
|
source_(nullptr),
|
||||||
anonymous_counter(0) {
|
anonymous_counter(0),
|
||||||
|
recurse_protection_counter(0) {
|
||||||
|
if (opts.force_defaults) {
|
||||||
|
builder_.ForceDefaults(true);
|
||||||
|
}
|
||||||
// Start out with the empty namespace being current.
|
// Start out with the empty namespace being current.
|
||||||
empty_namespace_ = new Namespace();
|
empty_namespace_ = new Namespace();
|
||||||
namespaces_.push_back(empty_namespace_);
|
namespaces_.push_back(empty_namespace_);
|
||||||
@@ -525,6 +623,7 @@ class Parser : public ParserState {
|
|||||||
known_attributes_["deprecated"] = true;
|
known_attributes_["deprecated"] = true;
|
||||||
known_attributes_["required"] = true;
|
known_attributes_["required"] = true;
|
||||||
known_attributes_["key"] = true;
|
known_attributes_["key"] = true;
|
||||||
|
known_attributes_["shared"] = true;
|
||||||
known_attributes_["hash"] = true;
|
known_attributes_["hash"] = true;
|
||||||
known_attributes_["id"] = true;
|
known_attributes_["id"] = true;
|
||||||
known_attributes_["force_align"] = true;
|
known_attributes_["force_align"] = true;
|
||||||
@@ -538,11 +637,13 @@ class Parser : public ParserState {
|
|||||||
known_attributes_["cpp_ptr_type"] = true;
|
known_attributes_["cpp_ptr_type"] = true;
|
||||||
known_attributes_["cpp_ptr_type_get"] = true;
|
known_attributes_["cpp_ptr_type_get"] = true;
|
||||||
known_attributes_["cpp_str_type"] = true;
|
known_attributes_["cpp_str_type"] = true;
|
||||||
|
known_attributes_["cpp_str_flex_ctor"] = true;
|
||||||
known_attributes_["native_inline"] = true;
|
known_attributes_["native_inline"] = true;
|
||||||
known_attributes_["native_custom_alloc"] = 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;
|
||||||
|
known_attributes_["private"] = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
~Parser() {
|
~Parser() {
|
||||||
@@ -580,6 +681,15 @@ class Parser : public ParserState {
|
|||||||
// See reflection/reflection.fbs
|
// See reflection/reflection.fbs
|
||||||
void Serialize();
|
void Serialize();
|
||||||
|
|
||||||
|
// Deserialize a schema buffer
|
||||||
|
bool Deserialize(const uint8_t *buf, const size_t size);
|
||||||
|
|
||||||
|
// Fills internal structure as if the schema passed had been loaded by parsing
|
||||||
|
// with Parse except that included filenames will not be populated.
|
||||||
|
bool Deserialize(const reflection::Schema* schema);
|
||||||
|
|
||||||
|
Type* DeserializeType(const reflection::Type* type);
|
||||||
|
|
||||||
// Checks that the schema represented by this parser is a safe evolution
|
// Checks that the schema represented by this parser is a safe evolution
|
||||||
// of the schema provided. Returns non-empty error on any problems.
|
// of the schema provided. Returns non-empty error on any problems.
|
||||||
std::string ConformTo(const Parser &base);
|
std::string ConformTo(const Parser &base);
|
||||||
@@ -589,14 +699,15 @@ class Parser : public ParserState {
|
|||||||
bool ParseFlexBuffer(const char *source, const char *source_filename,
|
bool ParseFlexBuffer(const char *source, const char *source_filename,
|
||||||
flexbuffers::Builder *builder);
|
flexbuffers::Builder *builder);
|
||||||
|
|
||||||
FLATBUFFERS_CHECKED_ERROR CheckInRange(int64_t val, int64_t min, int64_t max);
|
|
||||||
|
|
||||||
StructDef *LookupStruct(const std::string &id) const;
|
StructDef *LookupStruct(const std::string &id) const;
|
||||||
|
|
||||||
|
std::string UnqualifiedName(std::string fullQualifiedName);
|
||||||
|
|
||||||
|
FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Message(const std::string &msg);
|
void Message(const std::string &msg);
|
||||||
void Warning(const std::string &msg);
|
void Warning(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();
|
||||||
@@ -617,37 +728,20 @@ class Parser : public ParserState {
|
|||||||
FLATBUFFERS_CHECKED_ERROR ParseComma();
|
FLATBUFFERS_CHECKED_ERROR ParseComma();
|
||||||
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
|
uoffset_t count,
|
||||||
#if defined(FLATBUFFERS_CPP98_STL)
|
bool inside_vector = false);
|
||||||
typedef CheckedError (*ParseTableDelimitersBody)(
|
template<typename F>
|
||||||
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,
|
||||||
ParseTableDelimitersBody body,
|
F 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);
|
||||||
// clang-format off
|
template<typename F>
|
||||||
#if defined(FLATBUFFERS_CPP98_STL)
|
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body);
|
||||||
typedef CheckedError (*ParseVectorDelimitersBody)(size_t &count,
|
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
|
||||||
void *state);
|
FieldDef *field, size_t fieldn);
|
||||||
#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 ParseNestedFlatbuffer(Value &val, FieldDef *field,
|
FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field,
|
||||||
size_t fieldn,
|
size_t fieldn,
|
||||||
const StructDef *parent_struct_def);
|
const StructDef *parent_struct_def);
|
||||||
@@ -656,8 +750,8 @@ class Parser : public ParserState {
|
|||||||
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(const std::string *name, Value &e);
|
FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e, bool check_now);
|
||||||
FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(Type &type, int64_t *result);
|
FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type, std::string *result);
|
||||||
StructDef *LookupCreateStruct(const std::string &name,
|
StructDef *LookupCreateStruct(const std::string &name,
|
||||||
bool create_if_new = true,
|
bool create_if_new = true,
|
||||||
bool definition = false);
|
bool definition = false);
|
||||||
@@ -693,9 +787,12 @@ class Parser : public ParserState {
|
|||||||
const char *suffix,
|
const char *suffix,
|
||||||
BaseType baseType);
|
BaseType baseType);
|
||||||
|
|
||||||
bool SupportsVectorOfUnions() const;
|
bool SupportsAdvancedUnionFeatures() const;
|
||||||
Namespace *UniqueNamespace(Namespace *ns);
|
Namespace *UniqueNamespace(Namespace *ns);
|
||||||
|
|
||||||
|
FLATBUFFERS_CHECKED_ERROR RecurseError();
|
||||||
|
template<typename F> CheckedError Recurse(F f);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SymbolTable<Type> types_;
|
SymbolTable<Type> types_;
|
||||||
SymbolTable<StructDef> structs_;
|
SymbolTable<StructDef> structs_;
|
||||||
@@ -728,6 +825,7 @@ class Parser : public ParserState {
|
|||||||
std::vector<std::pair<Value, FieldDef *>> field_stack_;
|
std::vector<std::pair<Value, FieldDef *>> field_stack_;
|
||||||
|
|
||||||
int anonymous_counter;
|
int anonymous_counter;
|
||||||
|
int recurse_protection_counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Utility functions for multiple generators:
|
// Utility functions for multiple generators:
|
||||||
@@ -742,6 +840,10 @@ extern std::string MakeCamel(const std::string &in, bool first = true);
|
|||||||
// strict_json adds "quotes" around field names if true.
|
// strict_json adds "quotes" around field names if true.
|
||||||
// If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8
|
// If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8
|
||||||
// byte arrays in String values), returns false.
|
// byte arrays in String values), returns false.
|
||||||
|
extern bool GenerateTextFromTable(const Parser &parser,
|
||||||
|
const void *table,
|
||||||
|
const std::string &tablename,
|
||||||
|
std::string *text);
|
||||||
extern bool GenerateText(const Parser &parser,
|
extern bool GenerateText(const Parser &parser,
|
||||||
const void *flatbuffer,
|
const void *flatbuffer,
|
||||||
std::string *text);
|
std::string *text);
|
||||||
@@ -762,9 +864,13 @@ extern bool GenerateCPP(const Parser &parser,
|
|||||||
const std::string &path,
|
const std::string &path,
|
||||||
const std::string &file_name);
|
const std::string &file_name);
|
||||||
|
|
||||||
|
extern bool GenerateDart(const Parser &parser,
|
||||||
|
const std::string &path,
|
||||||
|
const std::string &file_name);
|
||||||
|
|
||||||
// Generate JavaScript or TypeScript code from the definitions in the Parser object.
|
// Generate JavaScript or TypeScript code from the definitions in the Parser object.
|
||||||
// See idl_gen_js.
|
// See idl_gen_js.
|
||||||
extern bool GenerateJS(const Parser &parser,
|
extern bool GenerateJSTS(const Parser &parser,
|
||||||
const std::string &path,
|
const std::string &path,
|
||||||
const std::string &file_name);
|
const std::string &file_name);
|
||||||
|
|
||||||
@@ -786,6 +892,24 @@ 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 Lobster files from the definitions in the Parser object.
|
||||||
|
// See idl_gen_lobster.cpp.
|
||||||
|
extern bool GenerateLobster(const Parser &parser,
|
||||||
|
const std::string &path,
|
||||||
|
const std::string &file_name);
|
||||||
|
|
||||||
|
// Generate Lua files from the definitions in the Parser object.
|
||||||
|
// See idl_gen_lua.cpp.
|
||||||
|
extern bool GenerateLua(const Parser &parser,
|
||||||
|
const std::string &path,
|
||||||
|
const std::string &file_name);
|
||||||
|
|
||||||
|
// Generate Rust files from the definitions in the Parser object.
|
||||||
|
// See idl_gen_rust.cpp.
|
||||||
|
extern bool GenerateRust(const Parser &parser,
|
||||||
|
const std::string &path,
|
||||||
|
const std::string &file_name);
|
||||||
|
|
||||||
// Generate Json schema file
|
// Generate Json schema file
|
||||||
// See idl_gen_json_schema.cpp.
|
// See idl_gen_json_schema.cpp.
|
||||||
extern bool GenerateJsonSchema(const Parser &parser,
|
extern bool GenerateJsonSchema(const Parser &parser,
|
||||||
@@ -808,7 +932,7 @@ extern bool GenerateFBS(const Parser &parser,
|
|||||||
|
|
||||||
// Generate a make rule for the generated JavaScript or TypeScript code.
|
// Generate a make rule for the generated JavaScript or TypeScript code.
|
||||||
// See idl_gen_js.cpp.
|
// See idl_gen_js.cpp.
|
||||||
extern std::string JSMakeRule(const Parser &parser,
|
extern std::string JSTSMakeRule(const Parser &parser,
|
||||||
const std::string &path,
|
const std::string &path,
|
||||||
const std::string &file_name);
|
const std::string &file_name);
|
||||||
|
|
||||||
@@ -818,6 +942,18 @@ extern std::string CPPMakeRule(const Parser &parser,
|
|||||||
const std::string &path,
|
const std::string &path,
|
||||||
const std::string &file_name);
|
const std::string &file_name);
|
||||||
|
|
||||||
|
// Generate a make rule for the generated Dart code
|
||||||
|
// see idl_gen_dart.cpp
|
||||||
|
extern std::string DartMakeRule(const Parser &parser,
|
||||||
|
const std::string &path,
|
||||||
|
const std::string &file_name);
|
||||||
|
|
||||||
|
// Generate a make rule for the generated Rust code.
|
||||||
|
// See idl_gen_rust.cpp.
|
||||||
|
extern std::string RustMakeRule(const Parser &parser,
|
||||||
|
const std::string &path,
|
||||||
|
const std::string &file_name);
|
||||||
|
|
||||||
// Generate a make rule for the generated Java/C#/... files.
|
// Generate a make rule for the generated Java/C#/... files.
|
||||||
// See idl_gen_general.cpp.
|
// See idl_gen_general.cpp.
|
||||||
extern std::string GeneralMakeRule(const Parser &parser,
|
extern std::string GeneralMakeRule(const Parser &parser,
|
||||||
|
|||||||
@@ -88,27 +88,27 @@ inline size_t InlineSize(ElementaryType type, const TypeTable *type_table) {
|
|||||||
switch (type_table->st) {
|
switch (type_table->st) {
|
||||||
case ST_TABLE:
|
case ST_TABLE:
|
||||||
case ST_UNION: return 4;
|
case ST_UNION: return 4;
|
||||||
case ST_STRUCT: return type_table->values[type_table->num_elems];
|
case ST_STRUCT: return static_cast<size_t>(type_table->values[type_table->num_elems]);
|
||||||
default: assert(false); return 1;
|
default: FLATBUFFERS_ASSERT(false); return 1;
|
||||||
}
|
}
|
||||||
default: assert(false); return 1;
|
default: FLATBUFFERS_ASSERT(false); return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int32_t LookupEnum(int32_t enum_val, const int32_t *values,
|
inline int64_t LookupEnum(int64_t enum_val, const int64_t *values,
|
||||||
size_t num_values) {
|
size_t num_values) {
|
||||||
if (!values) return enum_val;
|
if (!values) return enum_val;
|
||||||
for (size_t i = 0; i < num_values; i++) {
|
for (size_t i = 0; i < num_values; i++) {
|
||||||
if (enum_val == values[i]) return static_cast<int32_t>(i);
|
if (enum_val == values[i]) return static_cast<int64_t>(i);
|
||||||
}
|
}
|
||||||
return -1; // Unknown enum value.
|
return -1; // Unknown enum value.
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> const char *EnumName(T tval, const TypeTable *type_table) {
|
template<typename T> const char *EnumName(T tval, const TypeTable *type_table) {
|
||||||
if (!type_table || !type_table->names) return nullptr;
|
if (!type_table || !type_table->names) return nullptr;
|
||||||
auto i = LookupEnum(static_cast<int32_t>(tval), type_table->values,
|
auto i = LookupEnum(static_cast<int64_t>(tval), type_table->values,
|
||||||
type_table->num_elems);
|
type_table->num_elems);
|
||||||
if (i >= 0 && i < static_cast<int32_t>(type_table->num_elems)) {
|
if (i >= 0 && i < static_cast<int64_t>(type_table->num_elems)) {
|
||||||
return type_table->names[i];
|
return type_table->names[i];
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -122,58 +122,58 @@ inline void IterateValue(ElementaryType type, const uint8_t *val,
|
|||||||
soffset_t vector_index, IterationVisitor *visitor) {
|
soffset_t vector_index, IterationVisitor *visitor) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ET_UTYPE: {
|
case ET_UTYPE: {
|
||||||
auto tval = *reinterpret_cast<const uint8_t *>(val);
|
auto tval = ReadScalar<uint8_t>(val);
|
||||||
visitor->UType(tval, EnumName(tval, type_table));
|
visitor->UType(tval, EnumName(tval, type_table));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ET_BOOL: {
|
case ET_BOOL: {
|
||||||
visitor->Bool(*reinterpret_cast<const uint8_t *>(val) != 0);
|
visitor->Bool(ReadScalar<uint8_t>(val) != 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ET_CHAR: {
|
case ET_CHAR: {
|
||||||
auto tval = *reinterpret_cast<const int8_t *>(val);
|
auto tval = ReadScalar<int8_t>(val);
|
||||||
visitor->Char(tval, EnumName(tval, type_table));
|
visitor->Char(tval, EnumName(tval, type_table));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ET_UCHAR: {
|
case ET_UCHAR: {
|
||||||
auto tval = *reinterpret_cast<const uint8_t *>(val);
|
auto tval = ReadScalar<uint8_t>(val);
|
||||||
visitor->UChar(tval, EnumName(tval, type_table));
|
visitor->UChar(tval, EnumName(tval, type_table));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ET_SHORT: {
|
case ET_SHORT: {
|
||||||
auto tval = *reinterpret_cast<const int16_t *>(val);
|
auto tval = ReadScalar<int16_t>(val);
|
||||||
visitor->Short(tval, EnumName(tval, type_table));
|
visitor->Short(tval, EnumName(tval, type_table));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ET_USHORT: {
|
case ET_USHORT: {
|
||||||
auto tval = *reinterpret_cast<const uint16_t *>(val);
|
auto tval = ReadScalar<uint16_t>(val);
|
||||||
visitor->UShort(tval, EnumName(tval, type_table));
|
visitor->UShort(tval, EnumName(tval, type_table));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ET_INT: {
|
case ET_INT: {
|
||||||
auto tval = *reinterpret_cast<const int32_t *>(val);
|
auto tval = ReadScalar<int32_t>(val);
|
||||||
visitor->Int(tval, EnumName(tval, type_table));
|
visitor->Int(tval, EnumName(tval, type_table));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ET_UINT: {
|
case ET_UINT: {
|
||||||
auto tval = *reinterpret_cast<const uint32_t *>(val);
|
auto tval = ReadScalar<uint32_t>(val);
|
||||||
visitor->UInt(tval, EnumName(tval, type_table));
|
visitor->UInt(tval, EnumName(tval, type_table));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ET_LONG: {
|
case ET_LONG: {
|
||||||
visitor->Long(*reinterpret_cast<const int64_t *>(val));
|
visitor->Long(ReadScalar<int64_t>(val));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ET_ULONG: {
|
case ET_ULONG: {
|
||||||
visitor->ULong(*reinterpret_cast<const uint64_t *>(val));
|
visitor->ULong(ReadScalar<uint64_t>(val));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ET_FLOAT: {
|
case ET_FLOAT: {
|
||||||
visitor->Float(*reinterpret_cast<const float *>(val));
|
visitor->Float(ReadScalar<float>(val));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ET_DOUBLE: {
|
case ET_DOUBLE: {
|
||||||
visitor->Double(*reinterpret_cast<const double *>(val));
|
visitor->Double(ReadScalar<double>(val));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ET_STRING: {
|
case ET_STRING: {
|
||||||
@@ -190,7 +190,7 @@ inline void IterateValue(ElementaryType type, const uint8_t *val,
|
|||||||
case ST_STRUCT: IterateObject(val, type_table, visitor); break;
|
case ST_STRUCT: IterateObject(val, type_table, visitor); break;
|
||||||
case ST_UNION: {
|
case ST_UNION: {
|
||||||
val += ReadScalar<uoffset_t>(val);
|
val += ReadScalar<uoffset_t>(val);
|
||||||
assert(prev_val);
|
FLATBUFFERS_ASSERT(prev_val);
|
||||||
auto union_type = *prev_val; // Always a uint8_t.
|
auto union_type = *prev_val; // Always a uint8_t.
|
||||||
if (vector_index >= 0) {
|
if (vector_index >= 0) {
|
||||||
auto type_vec = reinterpret_cast<const Vector<uint8_t> *>(prev_val);
|
auto type_vec = reinterpret_cast<const Vector<uint8_t> *>(prev_val);
|
||||||
@@ -217,7 +217,7 @@ inline void IterateValue(ElementaryType type, const uint8_t *val,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ST_ENUM: assert(false); break;
|
case ST_ENUM: FLATBUFFERS_ASSERT(false); break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -283,23 +283,64 @@ inline void IterateFlatBuffer(const uint8_t *buffer,
|
|||||||
|
|
||||||
struct ToStringVisitor : public IterationVisitor {
|
struct ToStringVisitor : public IterationVisitor {
|
||||||
std::string s;
|
std::string s;
|
||||||
void StartSequence() { s += "{ "; }
|
std::string d;
|
||||||
void EndSequence() { s += " }"; }
|
bool q;
|
||||||
|
std::string in;
|
||||||
|
size_t indent_level;
|
||||||
|
bool vector_delimited;
|
||||||
|
ToStringVisitor(std::string delimiter, bool quotes, std::string indent,
|
||||||
|
bool vdelimited = true)
|
||||||
|
: d(delimiter),
|
||||||
|
q(quotes),
|
||||||
|
in(indent),
|
||||||
|
indent_level(0),
|
||||||
|
vector_delimited(vdelimited) {}
|
||||||
|
ToStringVisitor(std::string delimiter)
|
||||||
|
: d(delimiter),
|
||||||
|
q(false),
|
||||||
|
in(""),
|
||||||
|
indent_level(0),
|
||||||
|
vector_delimited(true) {}
|
||||||
|
|
||||||
|
void append_indent() {
|
||||||
|
for (size_t i = 0; i < indent_level; i++) { s += in; }
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartSequence() {
|
||||||
|
s += "{";
|
||||||
|
s += d;
|
||||||
|
indent_level++;
|
||||||
|
}
|
||||||
|
void EndSequence() {
|
||||||
|
s += d;
|
||||||
|
indent_level--;
|
||||||
|
append_indent();
|
||||||
|
s += "}";
|
||||||
|
}
|
||||||
void Field(size_t /*field_idx*/, size_t set_idx, ElementaryType /*type*/,
|
void Field(size_t /*field_idx*/, size_t set_idx, ElementaryType /*type*/,
|
||||||
bool /*is_vector*/, const TypeTable * /*type_table*/,
|
bool /*is_vector*/, const TypeTable * /*type_table*/,
|
||||||
const char *name, const uint8_t *val) {
|
const char *name, const uint8_t *val) {
|
||||||
if (!val) return;
|
if (!val) return;
|
||||||
if (set_idx) s += ", ";
|
if (set_idx) {
|
||||||
|
s += ",";
|
||||||
|
s += d;
|
||||||
|
}
|
||||||
|
append_indent();
|
||||||
if (name) {
|
if (name) {
|
||||||
|
if (q) s += "\"";
|
||||||
s += name;
|
s += name;
|
||||||
|
if (q) s += "\"";
|
||||||
s += ": ";
|
s += ": ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template<typename T> void Named(T x, const char *name) {
|
template<typename T> void Named(T x, const char *name) {
|
||||||
if (name)
|
if (name) {
|
||||||
|
if (q) s += "\"";
|
||||||
s += name;
|
s += name;
|
||||||
else
|
if (q) s += "\"";
|
||||||
|
} else {
|
||||||
s += NumToString(x);
|
s += NumToString(x);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void UType(uint8_t x, const char *name) { Named(x, name); }
|
void UType(uint8_t x, const char *name) { Named(x, name); }
|
||||||
void Bool(bool x) { s += x ? "true" : "false"; }
|
void Bool(bool x) { s += x ? "true" : "false"; }
|
||||||
@@ -314,20 +355,49 @@ struct ToStringVisitor : public IterationVisitor {
|
|||||||
void Float(float x) { s += NumToString(x); }
|
void Float(float x) { s += NumToString(x); }
|
||||||
void Double(double x) { s += NumToString(x); }
|
void Double(double x) { s += NumToString(x); }
|
||||||
void String(const struct String *str) {
|
void String(const struct String *str) {
|
||||||
EscapeString(str->c_str(), str->size(), &s, true);
|
EscapeString(str->c_str(), str->size(), &s, true, false);
|
||||||
}
|
}
|
||||||
void Unknown(const uint8_t *) { s += "(?)"; }
|
void Unknown(const uint8_t *) { s += "(?)"; }
|
||||||
void StartVector() { s += "[ "; }
|
void StartVector() {
|
||||||
void EndVector() { s += " ]"; }
|
s += "[";
|
||||||
|
if (vector_delimited) {
|
||||||
|
s += d;
|
||||||
|
indent_level++;
|
||||||
|
append_indent();
|
||||||
|
} else {
|
||||||
|
s += " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void EndVector() {
|
||||||
|
if (vector_delimited) {
|
||||||
|
s += d;
|
||||||
|
indent_level--;
|
||||||
|
append_indent();
|
||||||
|
} else {
|
||||||
|
s += " ";
|
||||||
|
}
|
||||||
|
s += "]";
|
||||||
|
}
|
||||||
void Element(size_t i, ElementaryType /*type*/,
|
void Element(size_t i, ElementaryType /*type*/,
|
||||||
const TypeTable * /*type_table*/, const uint8_t * /*val*/) {
|
const TypeTable * /*type_table*/, const uint8_t * /*val*/) {
|
||||||
if (i) s += ", ";
|
if (i) {
|
||||||
|
s += ",";
|
||||||
|
if (vector_delimited) {
|
||||||
|
s += d;
|
||||||
|
append_indent();
|
||||||
|
} else {
|
||||||
|
s += " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::string FlatBufferToString(const uint8_t *buffer,
|
inline std::string FlatBufferToString(const uint8_t *buffer,
|
||||||
const TypeTable *type_table) {
|
const TypeTable *type_table,
|
||||||
ToStringVisitor tostring_visitor;
|
bool multi_line = false,
|
||||||
|
bool vector_delimited = true) {
|
||||||
|
ToStringVisitor tostring_visitor(multi_line ? "\n" : " ", false, "",
|
||||||
|
vector_delimited);
|
||||||
IterateFlatBuffer(buffer, type_table, &tostring_visitor);
|
IterateFlatBuffer(buffer, type_table, &tostring_visitor);
|
||||||
return tostring_visitor.s;
|
return tostring_visitor.s;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,20 +72,20 @@ inline const Table *GetAnyRoot(const uint8_t *flatbuf) {
|
|||||||
|
|
||||||
// Get a field's default, if you know it's an integer, and its exact type.
|
// Get a field's default, if you know it's an integer, and its exact type.
|
||||||
template<typename T> T GetFieldDefaultI(const reflection::Field &field) {
|
template<typename T> T GetFieldDefaultI(const reflection::Field &field) {
|
||||||
assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
||||||
return static_cast<T>(field.default_integer());
|
return static_cast<T>(field.default_integer());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a field's default, if you know it's floating point and its exact type.
|
// Get a field's default, if you know it's floating point and its exact type.
|
||||||
template<typename T> T GetFieldDefaultF(const reflection::Field &field) {
|
template<typename T> T GetFieldDefaultF(const reflection::Field &field) {
|
||||||
assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
||||||
return static_cast<T>(field.default_real());
|
return static_cast<T>(field.default_real());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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>
|
template<typename T>
|
||||||
T GetFieldI(const Table &table, const reflection::Field &field) {
|
T GetFieldI(const Table &table, const reflection::Field &field) {
|
||||||
assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
FLATBUFFERS_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()));
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,7 @@ T GetFieldI(const Table &table, const reflection::Field &field) {
|
|||||||
// 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>
|
template<typename T>
|
||||||
T GetFieldF(const Table &table, const reflection::Field &field) {
|
T GetFieldF(const Table &table, const reflection::Field &field) {
|
||||||
assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
|
FLATBUFFERS_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()));
|
||||||
}
|
}
|
||||||
@@ -101,15 +101,15 @@ T GetFieldF(const Table &table, const reflection::Field &field) {
|
|||||||
// Get a field, if you know it's a string.
|
// Get a field, if you know it's a string.
|
||||||
inline const String *GetFieldS(const Table &table,
|
inline const String *GetFieldS(const Table &table,
|
||||||
const reflection::Field &field) {
|
const reflection::Field &field) {
|
||||||
assert(field.type()->base_type() == reflection::String);
|
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::String);
|
||||||
return table.GetPointer<const String *>(field.offset());
|
return table.GetPointer<const String *>(field.offset());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a field, if you know it's a vector.
|
// Get a field, if you know it's a vector.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Vector<T> *GetFieldV(const Table &table, const reflection::Field &field) {
|
Vector<T> *GetFieldV(const Table &table, const reflection::Field &field) {
|
||||||
assert(field.type()->base_type() == reflection::Vector &&
|
FLATBUFFERS_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());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,8 +123,8 @@ 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, const reflection::Field &field) {
|
inline Table *GetFieldT(const Table &table, const reflection::Field &field) {
|
||||||
assert(field.type()->base_type() == reflection::Obj ||
|
FLATBUFFERS_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());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,14 +133,14 @@ inline const Struct *GetFieldStruct(const Table &table,
|
|||||||
const reflection::Field &field) {
|
const reflection::Field &field) {
|
||||||
// TODO: This does NOT check if the field is a table or struct, but we'd need
|
// TODO: This does NOT check if the field is a table or struct, but we'd need
|
||||||
// access to the schema to check the is_struct flag.
|
// access to the schema to check the is_struct flag.
|
||||||
assert(field.type()->base_type() == reflection::Obj);
|
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj);
|
||||||
return table.GetStruct<const Struct *>(field.offset());
|
return table.GetStruct<const Struct *>(field.offset());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a structure's field, if you know it's a struct.
|
// Get a structure's field, if you know it's a struct.
|
||||||
inline const Struct *GetFieldStruct(const Struct &structure,
|
inline const Struct *GetFieldStruct(const Struct &structure,
|
||||||
const reflection::Field &field) {
|
const reflection::Field &field) {
|
||||||
assert(field.type()->base_type() == reflection::Obj);
|
FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj);
|
||||||
return structure.GetStruct<const Struct *>(field.offset());
|
return structure.GetStruct<const Struct *>(field.offset());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,7 +228,7 @@ inline std::string GetAnyVectorElemS(const VectorOfAny *vec,
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
T *GetAnyVectorElemPointer(const VectorOfAny *vec, 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 reinterpret_cast<T*>(elem_ptr + ReadScalar<uoffset_t>(elem_ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the inline-address of a vector element. Useful for Structs (pass Struct
|
// Get the inline-address of a vector element. Useful for Structs (pass Struct
|
||||||
@@ -239,20 +239,19 @@ T *GetAnyVectorElemPointer(const VectorOfAny *vec, size_t i) {
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
T *GetAnyVectorElemAddressOf(const VectorOfAny *vec, 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.
|
return reinterpret_cast<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>
|
template<typename T>
|
||||||
T *GetAnyFieldAddressOf(const Table &table, const reflection::Field &field) {
|
T *GetAnyFieldAddressOf(const Table &table, const reflection::Field &field) {
|
||||||
return (T *)table.GetAddressOf(field.offset());
|
return reinterpret_cast<T *>(table.GetAddressOf(field.offset()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Similarly, for elements of structs.
|
// Similarly, for elements of structs.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
T *GetAnyFieldAddressOf(const Struct &st, const reflection::Field &field) {
|
T *GetAnyFieldAddressOf(const Struct &st, const reflection::Field &field) {
|
||||||
return (T *)st.GetAddressOf(field.offset());
|
return reinterpret_cast<T *>(st.GetAddressOf(field.offset()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------- SETTERS -------------------------
|
// ------------------------- SETTERS -------------------------
|
||||||
@@ -262,12 +261,12 @@ template<typename T>
|
|||||||
bool SetField(Table *table, const reflection::Field &field, 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)) { return false; }
|
if (!IsScalar(type)) { return false; }
|
||||||
assert(sizeof(T) == GetTypeSize(type));
|
FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(type));
|
||||||
T def;
|
T def;
|
||||||
if (IsInteger(type)) {
|
if (IsInteger(type)) {
|
||||||
def = GetFieldDefaultI<T>(field);
|
def = GetFieldDefaultI<T>(field);
|
||||||
} else {
|
} else {
|
||||||
assert(IsFloat(type));
|
FLATBUFFERS_ASSERT(IsFloat(type));
|
||||||
def = GetFieldDefaultF<T>(field);
|
def = GetFieldDefaultF<T>(field);
|
||||||
}
|
}
|
||||||
return table->SetField(field.offset(), val, def);
|
return table->SetField(field.offset(), val, def);
|
||||||
@@ -386,7 +385,7 @@ inline const reflection::Object &GetUnionType(
|
|||||||
// 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);
|
FLATBUFFERS_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);
|
||||||
return *enumval->object();
|
return *enumval->object();
|
||||||
@@ -444,7 +443,8 @@ const uint8_t *AddFlatBuffer(std::vector<uint8_t> &flatbuf,
|
|||||||
|
|
||||||
inline bool SetFieldT(Table *table, const reflection::Field &field,
|
inline bool SetFieldT(Table *table, const reflection::Field &field,
|
||||||
const uint8_t *val) {
|
const uint8_t *val) {
|
||||||
assert(sizeof(uoffset_t) == GetTypeSize(field.type()->base_type()));
|
FLATBUFFERS_ASSERT(sizeof(uoffset_t) ==
|
||||||
|
GetTypeSize(field.type()->base_type()));
|
||||||
return table->SetPointer(field.offset(), val);
|
return table->SetPointer(field.offset(), val);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ struct Field;
|
|||||||
|
|
||||||
struct Object;
|
struct Object;
|
||||||
|
|
||||||
|
struct RPCCall;
|
||||||
|
|
||||||
|
struct Service;
|
||||||
|
|
||||||
struct Schema;
|
struct Schema;
|
||||||
|
|
||||||
enum BaseType {
|
enum BaseType {
|
||||||
@@ -90,12 +94,13 @@ inline const char * const *EnumNamesBaseType() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline const char *EnumNameBaseType(BaseType e) {
|
inline const char *EnumNameBaseType(BaseType e) {
|
||||||
const size_t index = static_cast<int>(e);
|
if (e < None || e > Union) return "";
|
||||||
|
const size_t index = static_cast<size_t>(e);
|
||||||
return EnumNamesBaseType()[index];
|
return EnumNamesBaseType()[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
enum {
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
VT_BASE_TYPE = 4,
|
VT_BASE_TYPE = 4,
|
||||||
VT_ELEMENT = 6,
|
VT_ELEMENT = 6,
|
||||||
VT_INDEX = 8
|
VT_INDEX = 8
|
||||||
@@ -155,7 +160,7 @@ inline flatbuffers::Offset<Type> CreateType(
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
enum {
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
VT_KEY = 4,
|
VT_KEY = 4,
|
||||||
VT_VALUE = 6
|
VT_VALUE = 6
|
||||||
};
|
};
|
||||||
@@ -174,9 +179,9 @@ struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
VerifyOffsetRequired(verifier, VT_KEY) &&
|
VerifyOffsetRequired(verifier, VT_KEY) &&
|
||||||
verifier.Verify(key()) &&
|
verifier.VerifyString(key()) &&
|
||||||
VerifyOffset(verifier, VT_VALUE) &&
|
VerifyOffset(verifier, VT_VALUE) &&
|
||||||
verifier.Verify(value()) &&
|
verifier.VerifyString(value()) &&
|
||||||
verifier.EndTable();
|
verifier.EndTable();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -217,18 +222,21 @@ inline flatbuffers::Offset<KeyValue> CreateKeyValueDirect(
|
|||||||
flatbuffers::FlatBufferBuilder &_fbb,
|
flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
const char *key = nullptr,
|
const char *key = nullptr,
|
||||||
const char *value = nullptr) {
|
const char *value = nullptr) {
|
||||||
|
auto key__ = key ? _fbb.CreateString(key) : 0;
|
||||||
|
auto value__ = value ? _fbb.CreateString(value) : 0;
|
||||||
return reflection::CreateKeyValue(
|
return reflection::CreateKeyValue(
|
||||||
_fbb,
|
_fbb,
|
||||||
key ? _fbb.CreateString(key) : 0,
|
key__,
|
||||||
value ? _fbb.CreateString(value) : 0);
|
value__);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
enum {
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
VT_NAME = 4,
|
VT_NAME = 4,
|
||||||
VT_VALUE = 6,
|
VT_VALUE = 6,
|
||||||
VT_OBJECT = 8,
|
VT_OBJECT = 8,
|
||||||
VT_UNION_TYPE = 10
|
VT_UNION_TYPE = 10,
|
||||||
|
VT_DOCUMENTATION = 12
|
||||||
};
|
};
|
||||||
const flatbuffers::String *name() const {
|
const flatbuffers::String *name() const {
|
||||||
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||||
@@ -240,14 +248,7 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
return value() < o->value();
|
return value() < o->value();
|
||||||
}
|
}
|
||||||
int KeyCompareWithValue(int64_t val) const {
|
int KeyCompareWithValue(int64_t val) const {
|
||||||
const auto key = value();
|
return static_cast<int>(value() > val) - static_cast<int>(value() < val);
|
||||||
if (key < val) {
|
|
||||||
return -1;
|
|
||||||
} else if (key > val) {
|
|
||||||
return 1;
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const Object *object() const {
|
const Object *object() const {
|
||||||
return GetPointer<const Object *>(VT_OBJECT);
|
return GetPointer<const Object *>(VT_OBJECT);
|
||||||
@@ -255,15 +256,21 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
const Type *union_type() const {
|
const Type *union_type() const {
|
||||||
return GetPointer<const Type *>(VT_UNION_TYPE);
|
return GetPointer<const Type *>(VT_UNION_TYPE);
|
||||||
}
|
}
|
||||||
|
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||||
|
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||||
|
}
|
||||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
VerifyOffsetRequired(verifier, VT_NAME) &&
|
VerifyOffsetRequired(verifier, VT_NAME) &&
|
||||||
verifier.Verify(name()) &&
|
verifier.VerifyString(name()) &&
|
||||||
VerifyField<int64_t>(verifier, VT_VALUE) &&
|
VerifyField<int64_t>(verifier, VT_VALUE) &&
|
||||||
VerifyOffset(verifier, VT_OBJECT) &&
|
VerifyOffset(verifier, VT_OBJECT) &&
|
||||||
verifier.VerifyTable(object()) &&
|
verifier.VerifyTable(object()) &&
|
||||||
VerifyOffset(verifier, VT_UNION_TYPE) &&
|
VerifyOffset(verifier, VT_UNION_TYPE) &&
|
||||||
verifier.VerifyTable(union_type()) &&
|
verifier.VerifyTable(union_type()) &&
|
||||||
|
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
||||||
|
verifier.VerifyVector(documentation()) &&
|
||||||
|
verifier.VerifyVectorOfStrings(documentation()) &&
|
||||||
verifier.EndTable();
|
verifier.EndTable();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -283,6 +290,9 @@ 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);
|
||||||
}
|
}
|
||||||
|
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||||
|
fbb_.AddOffset(EnumVal::VT_DOCUMENTATION, documentation);
|
||||||
|
}
|
||||||
explicit EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
explicit EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
: fbb_(_fbb) {
|
: fbb_(_fbb) {
|
||||||
start_ = fbb_.StartTable();
|
start_ = fbb_.StartTable();
|
||||||
@@ -301,9 +311,11 @@ inline flatbuffers::Offset<EnumVal> CreateEnumVal(
|
|||||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||||
int64_t value = 0,
|
int64_t value = 0,
|
||||||
flatbuffers::Offset<Object> object = 0,
|
flatbuffers::Offset<Object> object = 0,
|
||||||
flatbuffers::Offset<Type> union_type = 0) {
|
flatbuffers::Offset<Type> union_type = 0,
|
||||||
|
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||||
EnumValBuilder builder_(_fbb);
|
EnumValBuilder builder_(_fbb);
|
||||||
builder_.add_value(value);
|
builder_.add_value(value);
|
||||||
|
builder_.add_documentation(documentation);
|
||||||
builder_.add_union_type(union_type);
|
builder_.add_union_type(union_type);
|
||||||
builder_.add_object(object);
|
builder_.add_object(object);
|
||||||
builder_.add_name(name);
|
builder_.add_name(name);
|
||||||
@@ -315,17 +327,21 @@ inline flatbuffers::Offset<EnumVal> CreateEnumValDirect(
|
|||||||
const char *name = nullptr,
|
const char *name = nullptr,
|
||||||
int64_t value = 0,
|
int64_t value = 0,
|
||||||
flatbuffers::Offset<Object> object = 0,
|
flatbuffers::Offset<Object> object = 0,
|
||||||
flatbuffers::Offset<Type> union_type = 0) {
|
flatbuffers::Offset<Type> union_type = 0,
|
||||||
|
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||||
|
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||||
|
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||||
return reflection::CreateEnumVal(
|
return reflection::CreateEnumVal(
|
||||||
_fbb,
|
_fbb,
|
||||||
name ? _fbb.CreateString(name) : 0,
|
name__,
|
||||||
value,
|
value,
|
||||||
object,
|
object,
|
||||||
union_type);
|
union_type,
|
||||||
|
documentation__);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
enum {
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
VT_NAME = 4,
|
VT_NAME = 4,
|
||||||
VT_VALUES = 6,
|
VT_VALUES = 6,
|
||||||
VT_IS_UNION = 8,
|
VT_IS_UNION = 8,
|
||||||
@@ -360,18 +376,18 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
VerifyOffsetRequired(verifier, VT_NAME) &&
|
VerifyOffsetRequired(verifier, VT_NAME) &&
|
||||||
verifier.Verify(name()) &&
|
verifier.VerifyString(name()) &&
|
||||||
VerifyOffsetRequired(verifier, VT_VALUES) &&
|
VerifyOffsetRequired(verifier, VT_VALUES) &&
|
||||||
verifier.Verify(values()) &&
|
verifier.VerifyVector(values()) &&
|
||||||
verifier.VerifyVectorOfTables(values()) &&
|
verifier.VerifyVectorOfTables(values()) &&
|
||||||
VerifyField<uint8_t>(verifier, VT_IS_UNION) &&
|
VerifyField<uint8_t>(verifier, VT_IS_UNION) &&
|
||||||
VerifyOffsetRequired(verifier, VT_UNDERLYING_TYPE) &&
|
VerifyOffsetRequired(verifier, VT_UNDERLYING_TYPE) &&
|
||||||
verifier.VerifyTable(underlying_type()) &&
|
verifier.VerifyTable(underlying_type()) &&
|
||||||
VerifyOffset(verifier, VT_ATTRIBUTES) &&
|
VerifyOffset(verifier, VT_ATTRIBUTES) &&
|
||||||
verifier.Verify(attributes()) &&
|
verifier.VerifyVector(attributes()) &&
|
||||||
verifier.VerifyVectorOfTables(attributes()) &&
|
verifier.VerifyVectorOfTables(attributes()) &&
|
||||||
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
||||||
verifier.Verify(documentation()) &&
|
verifier.VerifyVector(documentation()) &&
|
||||||
verifier.VerifyVectorOfStrings(documentation()) &&
|
verifier.VerifyVectorOfStrings(documentation()) &&
|
||||||
verifier.EndTable();
|
verifier.EndTable();
|
||||||
}
|
}
|
||||||
@@ -439,18 +455,22 @@ inline flatbuffers::Offset<Enum> CreateEnumDirect(
|
|||||||
flatbuffers::Offset<Type> underlying_type = 0,
|
flatbuffers::Offset<Type> underlying_type = 0,
|
||||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||||
|
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||||
|
auto values__ = values ? _fbb.CreateVector<flatbuffers::Offset<EnumVal>>(*values) : 0;
|
||||||
|
auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0;
|
||||||
|
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||||
return reflection::CreateEnum(
|
return reflection::CreateEnum(
|
||||||
_fbb,
|
_fbb,
|
||||||
name ? _fbb.CreateString(name) : 0,
|
name__,
|
||||||
values ? _fbb.CreateVector<flatbuffers::Offset<EnumVal>>(*values) : 0,
|
values__,
|
||||||
is_union,
|
is_union,
|
||||||
underlying_type,
|
underlying_type,
|
||||||
attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0,
|
attributes__,
|
||||||
documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0);
|
documentation__);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
enum {
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
VT_NAME = 4,
|
VT_NAME = 4,
|
||||||
VT_TYPE = 6,
|
VT_TYPE = 6,
|
||||||
VT_ID = 8,
|
VT_ID = 8,
|
||||||
@@ -505,7 +525,7 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
VerifyOffsetRequired(verifier, VT_NAME) &&
|
VerifyOffsetRequired(verifier, VT_NAME) &&
|
||||||
verifier.Verify(name()) &&
|
verifier.VerifyString(name()) &&
|
||||||
VerifyOffsetRequired(verifier, VT_TYPE) &&
|
VerifyOffsetRequired(verifier, VT_TYPE) &&
|
||||||
verifier.VerifyTable(type()) &&
|
verifier.VerifyTable(type()) &&
|
||||||
VerifyField<uint16_t>(verifier, VT_ID) &&
|
VerifyField<uint16_t>(verifier, VT_ID) &&
|
||||||
@@ -516,10 +536,10 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
VerifyField<uint8_t>(verifier, VT_REQUIRED) &&
|
VerifyField<uint8_t>(verifier, VT_REQUIRED) &&
|
||||||
VerifyField<uint8_t>(verifier, VT_KEY) &&
|
VerifyField<uint8_t>(verifier, VT_KEY) &&
|
||||||
VerifyOffset(verifier, VT_ATTRIBUTES) &&
|
VerifyOffset(verifier, VT_ATTRIBUTES) &&
|
||||||
verifier.Verify(attributes()) &&
|
verifier.VerifyVector(attributes()) &&
|
||||||
verifier.VerifyVectorOfTables(attributes()) &&
|
verifier.VerifyVectorOfTables(attributes()) &&
|
||||||
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
||||||
verifier.Verify(documentation()) &&
|
verifier.VerifyVector(documentation()) &&
|
||||||
verifier.VerifyVectorOfStrings(documentation()) &&
|
verifier.VerifyVectorOfStrings(documentation()) &&
|
||||||
verifier.EndTable();
|
verifier.EndTable();
|
||||||
}
|
}
|
||||||
@@ -616,9 +636,12 @@ inline flatbuffers::Offset<Field> CreateFieldDirect(
|
|||||||
bool key = false,
|
bool key = false,
|
||||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||||
|
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||||
|
auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0;
|
||||||
|
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||||
return reflection::CreateField(
|
return reflection::CreateField(
|
||||||
_fbb,
|
_fbb,
|
||||||
name ? _fbb.CreateString(name) : 0,
|
name__,
|
||||||
type,
|
type,
|
||||||
id,
|
id,
|
||||||
offset,
|
offset,
|
||||||
@@ -627,12 +650,12 @@ inline flatbuffers::Offset<Field> CreateFieldDirect(
|
|||||||
deprecated,
|
deprecated,
|
||||||
required,
|
required,
|
||||||
key,
|
key,
|
||||||
attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0,
|
attributes__,
|
||||||
documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0);
|
documentation__);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
enum {
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
VT_NAME = 4,
|
VT_NAME = 4,
|
||||||
VT_FIELDS = 6,
|
VT_FIELDS = 6,
|
||||||
VT_IS_STRUCT = 8,
|
VT_IS_STRUCT = 8,
|
||||||
@@ -671,18 +694,18 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
VerifyOffsetRequired(verifier, VT_NAME) &&
|
VerifyOffsetRequired(verifier, VT_NAME) &&
|
||||||
verifier.Verify(name()) &&
|
verifier.VerifyString(name()) &&
|
||||||
VerifyOffsetRequired(verifier, VT_FIELDS) &&
|
VerifyOffsetRequired(verifier, VT_FIELDS) &&
|
||||||
verifier.Verify(fields()) &&
|
verifier.VerifyVector(fields()) &&
|
||||||
verifier.VerifyVectorOfTables(fields()) &&
|
verifier.VerifyVectorOfTables(fields()) &&
|
||||||
VerifyField<uint8_t>(verifier, VT_IS_STRUCT) &&
|
VerifyField<uint8_t>(verifier, VT_IS_STRUCT) &&
|
||||||
VerifyField<int32_t>(verifier, VT_MINALIGN) &&
|
VerifyField<int32_t>(verifier, VT_MINALIGN) &&
|
||||||
VerifyField<int32_t>(verifier, VT_BYTESIZE) &&
|
VerifyField<int32_t>(verifier, VT_BYTESIZE) &&
|
||||||
VerifyOffset(verifier, VT_ATTRIBUTES) &&
|
VerifyOffset(verifier, VT_ATTRIBUTES) &&
|
||||||
verifier.Verify(attributes()) &&
|
verifier.VerifyVector(attributes()) &&
|
||||||
verifier.VerifyVectorOfTables(attributes()) &&
|
verifier.VerifyVectorOfTables(attributes()) &&
|
||||||
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
||||||
verifier.Verify(documentation()) &&
|
verifier.VerifyVector(documentation()) &&
|
||||||
verifier.VerifyVectorOfStrings(documentation()) &&
|
verifier.VerifyVectorOfStrings(documentation()) &&
|
||||||
verifier.EndTable();
|
verifier.EndTable();
|
||||||
}
|
}
|
||||||
@@ -755,24 +778,246 @@ inline flatbuffers::Offset<Object> CreateObjectDirect(
|
|||||||
int32_t bytesize = 0,
|
int32_t bytesize = 0,
|
||||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||||
|
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||||
|
auto fields__ = fields ? _fbb.CreateVector<flatbuffers::Offset<Field>>(*fields) : 0;
|
||||||
|
auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0;
|
||||||
|
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||||
return reflection::CreateObject(
|
return reflection::CreateObject(
|
||||||
_fbb,
|
_fbb,
|
||||||
name ? _fbb.CreateString(name) : 0,
|
name__,
|
||||||
fields ? _fbb.CreateVector<flatbuffers::Offset<Field>>(*fields) : 0,
|
fields__,
|
||||||
is_struct,
|
is_struct,
|
||||||
minalign,
|
minalign,
|
||||||
bytesize,
|
bytesize,
|
||||||
attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0,
|
attributes__,
|
||||||
documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0);
|
documentation__);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
|
VT_NAME = 4,
|
||||||
|
VT_REQUEST = 6,
|
||||||
|
VT_RESPONSE = 8,
|
||||||
|
VT_ATTRIBUTES = 10,
|
||||||
|
VT_DOCUMENTATION = 12
|
||||||
|
};
|
||||||
|
const flatbuffers::String *name() const {
|
||||||
|
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||||
|
}
|
||||||
|
bool KeyCompareLessThan(const RPCCall *o) const {
|
||||||
|
return *name() < *o->name();
|
||||||
|
}
|
||||||
|
int KeyCompareWithValue(const char *val) const {
|
||||||
|
return strcmp(name()->c_str(), val);
|
||||||
|
}
|
||||||
|
const Object *request() const {
|
||||||
|
return GetPointer<const Object *>(VT_REQUEST);
|
||||||
|
}
|
||||||
|
const Object *response() const {
|
||||||
|
return GetPointer<const Object *>(VT_RESPONSE);
|
||||||
|
}
|
||||||
|
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const {
|
||||||
|
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES);
|
||||||
|
}
|
||||||
|
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||||
|
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||||
|
}
|
||||||
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
|
return VerifyTableStart(verifier) &&
|
||||||
|
VerifyOffsetRequired(verifier, VT_NAME) &&
|
||||||
|
verifier.VerifyString(name()) &&
|
||||||
|
VerifyOffsetRequired(verifier, VT_REQUEST) &&
|
||||||
|
verifier.VerifyTable(request()) &&
|
||||||
|
VerifyOffsetRequired(verifier, VT_RESPONSE) &&
|
||||||
|
verifier.VerifyTable(response()) &&
|
||||||
|
VerifyOffset(verifier, VT_ATTRIBUTES) &&
|
||||||
|
verifier.VerifyVector(attributes()) &&
|
||||||
|
verifier.VerifyVectorOfTables(attributes()) &&
|
||||||
|
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
||||||
|
verifier.VerifyVector(documentation()) &&
|
||||||
|
verifier.VerifyVectorOfStrings(documentation()) &&
|
||||||
|
verifier.EndTable();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct RPCCallBuilder {
|
||||||
|
flatbuffers::FlatBufferBuilder &fbb_;
|
||||||
|
flatbuffers::uoffset_t start_;
|
||||||
|
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||||
|
fbb_.AddOffset(RPCCall::VT_NAME, name);
|
||||||
|
}
|
||||||
|
void add_request(flatbuffers::Offset<Object> request) {
|
||||||
|
fbb_.AddOffset(RPCCall::VT_REQUEST, request);
|
||||||
|
}
|
||||||
|
void add_response(flatbuffers::Offset<Object> response) {
|
||||||
|
fbb_.AddOffset(RPCCall::VT_RESPONSE, response);
|
||||||
|
}
|
||||||
|
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) {
|
||||||
|
fbb_.AddOffset(RPCCall::VT_ATTRIBUTES, attributes);
|
||||||
|
}
|
||||||
|
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||||
|
fbb_.AddOffset(RPCCall::VT_DOCUMENTATION, documentation);
|
||||||
|
}
|
||||||
|
explicit RPCCallBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
|
: fbb_(_fbb) {
|
||||||
|
start_ = fbb_.StartTable();
|
||||||
|
}
|
||||||
|
RPCCallBuilder &operator=(const RPCCallBuilder &);
|
||||||
|
flatbuffers::Offset<RPCCall> Finish() {
|
||||||
|
const auto end = fbb_.EndTable(start_);
|
||||||
|
auto o = flatbuffers::Offset<RPCCall>(end);
|
||||||
|
fbb_.Required(o, RPCCall::VT_NAME);
|
||||||
|
fbb_.Required(o, RPCCall::VT_REQUEST);
|
||||||
|
fbb_.Required(o, RPCCall::VT_RESPONSE);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline flatbuffers::Offset<RPCCall> CreateRPCCall(
|
||||||
|
flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
|
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||||
|
flatbuffers::Offset<Object> request = 0,
|
||||||
|
flatbuffers::Offset<Object> response = 0,
|
||||||
|
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0,
|
||||||
|
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||||
|
RPCCallBuilder builder_(_fbb);
|
||||||
|
builder_.add_documentation(documentation);
|
||||||
|
builder_.add_attributes(attributes);
|
||||||
|
builder_.add_response(response);
|
||||||
|
builder_.add_request(request);
|
||||||
|
builder_.add_name(name);
|
||||||
|
return builder_.Finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline flatbuffers::Offset<RPCCall> CreateRPCCallDirect(
|
||||||
|
flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
|
const char *name = nullptr,
|
||||||
|
flatbuffers::Offset<Object> request = 0,
|
||||||
|
flatbuffers::Offset<Object> response = 0,
|
||||||
|
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||||
|
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||||
|
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||||
|
auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0;
|
||||||
|
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||||
|
return reflection::CreateRPCCall(
|
||||||
|
_fbb,
|
||||||
|
name__,
|
||||||
|
request,
|
||||||
|
response,
|
||||||
|
attributes__,
|
||||||
|
documentation__);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Service FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
|
VT_NAME = 4,
|
||||||
|
VT_CALLS = 6,
|
||||||
|
VT_ATTRIBUTES = 8,
|
||||||
|
VT_DOCUMENTATION = 10
|
||||||
|
};
|
||||||
|
const flatbuffers::String *name() const {
|
||||||
|
return GetPointer<const flatbuffers::String *>(VT_NAME);
|
||||||
|
}
|
||||||
|
bool KeyCompareLessThan(const Service *o) const {
|
||||||
|
return *name() < *o->name();
|
||||||
|
}
|
||||||
|
int KeyCompareWithValue(const char *val) const {
|
||||||
|
return strcmp(name()->c_str(), val);
|
||||||
|
}
|
||||||
|
const flatbuffers::Vector<flatbuffers::Offset<RPCCall>> *calls() const {
|
||||||
|
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<RPCCall>> *>(VT_CALLS);
|
||||||
|
}
|
||||||
|
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const {
|
||||||
|
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES);
|
||||||
|
}
|
||||||
|
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||||
|
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||||
|
}
|
||||||
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
|
return VerifyTableStart(verifier) &&
|
||||||
|
VerifyOffsetRequired(verifier, VT_NAME) &&
|
||||||
|
verifier.VerifyString(name()) &&
|
||||||
|
VerifyOffset(verifier, VT_CALLS) &&
|
||||||
|
verifier.VerifyVector(calls()) &&
|
||||||
|
verifier.VerifyVectorOfTables(calls()) &&
|
||||||
|
VerifyOffset(verifier, VT_ATTRIBUTES) &&
|
||||||
|
verifier.VerifyVector(attributes()) &&
|
||||||
|
verifier.VerifyVectorOfTables(attributes()) &&
|
||||||
|
VerifyOffset(verifier, VT_DOCUMENTATION) &&
|
||||||
|
verifier.VerifyVector(documentation()) &&
|
||||||
|
verifier.VerifyVectorOfStrings(documentation()) &&
|
||||||
|
verifier.EndTable();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ServiceBuilder {
|
||||||
|
flatbuffers::FlatBufferBuilder &fbb_;
|
||||||
|
flatbuffers::uoffset_t start_;
|
||||||
|
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||||
|
fbb_.AddOffset(Service::VT_NAME, name);
|
||||||
|
}
|
||||||
|
void add_calls(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<RPCCall>>> calls) {
|
||||||
|
fbb_.AddOffset(Service::VT_CALLS, calls);
|
||||||
|
}
|
||||||
|
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) {
|
||||||
|
fbb_.AddOffset(Service::VT_ATTRIBUTES, attributes);
|
||||||
|
}
|
||||||
|
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||||
|
fbb_.AddOffset(Service::VT_DOCUMENTATION, documentation);
|
||||||
|
}
|
||||||
|
explicit ServiceBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
|
: fbb_(_fbb) {
|
||||||
|
start_ = fbb_.StartTable();
|
||||||
|
}
|
||||||
|
ServiceBuilder &operator=(const ServiceBuilder &);
|
||||||
|
flatbuffers::Offset<Service> Finish() {
|
||||||
|
const auto end = fbb_.EndTable(start_);
|
||||||
|
auto o = flatbuffers::Offset<Service>(end);
|
||||||
|
fbb_.Required(o, Service::VT_NAME);
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline flatbuffers::Offset<Service> CreateService(
|
||||||
|
flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
|
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||||
|
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<RPCCall>>> calls = 0,
|
||||||
|
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0,
|
||||||
|
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||||
|
ServiceBuilder builder_(_fbb);
|
||||||
|
builder_.add_documentation(documentation);
|
||||||
|
builder_.add_attributes(attributes);
|
||||||
|
builder_.add_calls(calls);
|
||||||
|
builder_.add_name(name);
|
||||||
|
return builder_.Finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline flatbuffers::Offset<Service> CreateServiceDirect(
|
||||||
|
flatbuffers::FlatBufferBuilder &_fbb,
|
||||||
|
const char *name = nullptr,
|
||||||
|
const std::vector<flatbuffers::Offset<RPCCall>> *calls = nullptr,
|
||||||
|
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||||
|
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||||
|
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||||
|
auto calls__ = calls ? _fbb.CreateVector<flatbuffers::Offset<RPCCall>>(*calls) : 0;
|
||||||
|
auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0;
|
||||||
|
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||||
|
return reflection::CreateService(
|
||||||
|
_fbb,
|
||||||
|
name__,
|
||||||
|
calls__,
|
||||||
|
attributes__,
|
||||||
|
documentation__);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||||
enum {
|
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||||
VT_OBJECTS = 4,
|
VT_OBJECTS = 4,
|
||||||
VT_ENUMS = 6,
|
VT_ENUMS = 6,
|
||||||
VT_FILE_IDENT = 8,
|
VT_FILE_IDENT = 8,
|
||||||
VT_FILE_EXT = 10,
|
VT_FILE_EXT = 10,
|
||||||
VT_ROOT_TABLE = 12
|
VT_ROOT_TABLE = 12,
|
||||||
|
VT_SERVICES = 14
|
||||||
};
|
};
|
||||||
const flatbuffers::Vector<flatbuffers::Offset<Object>> *objects() const {
|
const flatbuffers::Vector<flatbuffers::Offset<Object>> *objects() const {
|
||||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Object>> *>(VT_OBJECTS);
|
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Object>> *>(VT_OBJECTS);
|
||||||
@@ -789,20 +1034,26 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
|||||||
const Object *root_table() const {
|
const Object *root_table() const {
|
||||||
return GetPointer<const Object *>(VT_ROOT_TABLE);
|
return GetPointer<const Object *>(VT_ROOT_TABLE);
|
||||||
}
|
}
|
||||||
|
const flatbuffers::Vector<flatbuffers::Offset<Service>> *services() const {
|
||||||
|
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Service>> *>(VT_SERVICES);
|
||||||
|
}
|
||||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||||
return VerifyTableStart(verifier) &&
|
return VerifyTableStart(verifier) &&
|
||||||
VerifyOffsetRequired(verifier, VT_OBJECTS) &&
|
VerifyOffsetRequired(verifier, VT_OBJECTS) &&
|
||||||
verifier.Verify(objects()) &&
|
verifier.VerifyVector(objects()) &&
|
||||||
verifier.VerifyVectorOfTables(objects()) &&
|
verifier.VerifyVectorOfTables(objects()) &&
|
||||||
VerifyOffsetRequired(verifier, VT_ENUMS) &&
|
VerifyOffsetRequired(verifier, VT_ENUMS) &&
|
||||||
verifier.Verify(enums()) &&
|
verifier.VerifyVector(enums()) &&
|
||||||
verifier.VerifyVectorOfTables(enums()) &&
|
verifier.VerifyVectorOfTables(enums()) &&
|
||||||
VerifyOffset(verifier, VT_FILE_IDENT) &&
|
VerifyOffset(verifier, VT_FILE_IDENT) &&
|
||||||
verifier.Verify(file_ident()) &&
|
verifier.VerifyString(file_ident()) &&
|
||||||
VerifyOffset(verifier, VT_FILE_EXT) &&
|
VerifyOffset(verifier, VT_FILE_EXT) &&
|
||||||
verifier.Verify(file_ext()) &&
|
verifier.VerifyString(file_ext()) &&
|
||||||
VerifyOffset(verifier, VT_ROOT_TABLE) &&
|
VerifyOffset(verifier, VT_ROOT_TABLE) &&
|
||||||
verifier.VerifyTable(root_table()) &&
|
verifier.VerifyTable(root_table()) &&
|
||||||
|
VerifyOffset(verifier, VT_SERVICES) &&
|
||||||
|
verifier.VerifyVector(services()) &&
|
||||||
|
verifier.VerifyVectorOfTables(services()) &&
|
||||||
verifier.EndTable();
|
verifier.EndTable();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -825,6 +1076,9 @@ 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);
|
||||||
}
|
}
|
||||||
|
void add_services(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Service>>> services) {
|
||||||
|
fbb_.AddOffset(Schema::VT_SERVICES, services);
|
||||||
|
}
|
||||||
explicit SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
explicit SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||||
: fbb_(_fbb) {
|
: fbb_(_fbb) {
|
||||||
start_ = fbb_.StartTable();
|
start_ = fbb_.StartTable();
|
||||||
@@ -845,8 +1099,10 @@ inline flatbuffers::Offset<Schema> CreateSchema(
|
|||||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Enum>>> enums = 0,
|
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Enum>>> enums = 0,
|
||||||
flatbuffers::Offset<flatbuffers::String> file_ident = 0,
|
flatbuffers::Offset<flatbuffers::String> file_ident = 0,
|
||||||
flatbuffers::Offset<flatbuffers::String> file_ext = 0,
|
flatbuffers::Offset<flatbuffers::String> file_ext = 0,
|
||||||
flatbuffers::Offset<Object> root_table = 0) {
|
flatbuffers::Offset<Object> root_table = 0,
|
||||||
|
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Service>>> services = 0) {
|
||||||
SchemaBuilder builder_(_fbb);
|
SchemaBuilder builder_(_fbb);
|
||||||
|
builder_.add_services(services);
|
||||||
builder_.add_root_table(root_table);
|
builder_.add_root_table(root_table);
|
||||||
builder_.add_file_ext(file_ext);
|
builder_.add_file_ext(file_ext);
|
||||||
builder_.add_file_ident(file_ident);
|
builder_.add_file_ident(file_ident);
|
||||||
@@ -861,14 +1117,21 @@ inline flatbuffers::Offset<Schema> CreateSchemaDirect(
|
|||||||
const std::vector<flatbuffers::Offset<Enum>> *enums = nullptr,
|
const std::vector<flatbuffers::Offset<Enum>> *enums = nullptr,
|
||||||
const char *file_ident = nullptr,
|
const char *file_ident = nullptr,
|
||||||
const char *file_ext = nullptr,
|
const char *file_ext = nullptr,
|
||||||
flatbuffers::Offset<Object> root_table = 0) {
|
flatbuffers::Offset<Object> root_table = 0,
|
||||||
|
const std::vector<flatbuffers::Offset<Service>> *services = nullptr) {
|
||||||
|
auto objects__ = objects ? _fbb.CreateVector<flatbuffers::Offset<Object>>(*objects) : 0;
|
||||||
|
auto enums__ = enums ? _fbb.CreateVector<flatbuffers::Offset<Enum>>(*enums) : 0;
|
||||||
|
auto file_ident__ = file_ident ? _fbb.CreateString(file_ident) : 0;
|
||||||
|
auto file_ext__ = file_ext ? _fbb.CreateString(file_ext) : 0;
|
||||||
|
auto services__ = services ? _fbb.CreateVector<flatbuffers::Offset<Service>>(*services) : 0;
|
||||||
return reflection::CreateSchema(
|
return reflection::CreateSchema(
|
||||||
_fbb,
|
_fbb,
|
||||||
objects ? _fbb.CreateVector<flatbuffers::Offset<Object>>(*objects) : 0,
|
objects__,
|
||||||
enums ? _fbb.CreateVector<flatbuffers::Offset<Enum>>(*enums) : 0,
|
enums__,
|
||||||
file_ident ? _fbb.CreateString(file_ident) : 0,
|
file_ident__,
|
||||||
file_ext ? _fbb.CreateString(file_ext) : 0,
|
file_ext__,
|
||||||
root_table);
|
root_table,
|
||||||
|
services__);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const reflection::Schema *GetSchema(const void *buf) {
|
inline const reflection::Schema *GetSchema(const void *buf) {
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ class Registry {
|
|||||||
return DetachedBuffer();
|
return DetachedBuffer();
|
||||||
}
|
}
|
||||||
// We have a valid FlatBuffer. Detach it from the builder and return.
|
// We have a valid FlatBuffer. Detach it from the builder and return.
|
||||||
return parser.builder_.ReleaseBufferPointer();
|
return parser.builder_.Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Modify any parsing / output options used by the other functions.
|
// Modify any parsing / output options used by the other functions.
|
||||||
|
|||||||
@@ -33,6 +33,16 @@
|
|||||||
#include <cctype>
|
#include <cctype>
|
||||||
#endif // defined(FLATBUFFERS_CPP98_STL)
|
#endif // defined(FLATBUFFERS_CPP98_STL)
|
||||||
|
|
||||||
|
// Check if we can use template aliases
|
||||||
|
// Not possible if Microsoft Compiler before 2012
|
||||||
|
// Possible is the language feature __cpp_alias_templates is defined well
|
||||||
|
// Or possible if the C++ std is C+11 or newer
|
||||||
|
#if (defined(_MSC_VER) && _MSC_VER > 1700 /* MSVC2012 */) \
|
||||||
|
|| (defined(__cpp_alias_templates) && __cpp_alias_templates >= 200704) \
|
||||||
|
|| (defined(__cplusplus) && __cplusplus >= 201103L)
|
||||||
|
#define FLATBUFFERS_TEMPLATES_ALIASES
|
||||||
|
#endif
|
||||||
|
|
||||||
// This header provides backwards compatibility for C++98 STLs like stlport.
|
// This header provides backwards compatibility for C++98 STLs like stlport.
|
||||||
namespace flatbuffers {
|
namespace flatbuffers {
|
||||||
|
|
||||||
@@ -69,21 +79,42 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_CPP98_STL
|
#ifndef FLATBUFFERS_CPP98_STL
|
||||||
#if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
#if defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using numeric_limits = std::numeric_limits<T>;
|
using numeric_limits = std::numeric_limits<T>;
|
||||||
#else
|
#else
|
||||||
template <typename T> class numeric_limits :
|
template <typename T> class numeric_limits :
|
||||||
public std::numeric_limits<T> {};
|
public std::numeric_limits<T> {};
|
||||||
#endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||||
#else
|
#else
|
||||||
template <typename T> class numeric_limits :
|
template <typename T> class numeric_limits :
|
||||||
public std::numeric_limits<T> {};
|
public std::numeric_limits<T> {
|
||||||
|
public:
|
||||||
|
// Android NDK fix.
|
||||||
|
static T lowest() {
|
||||||
|
return std::numeric_limits<T>::min();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> class numeric_limits<float> :
|
||||||
|
public std::numeric_limits<float> {
|
||||||
|
public:
|
||||||
|
static float lowest() { return -FLT_MAX; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template <> class numeric_limits<double> :
|
||||||
|
public std::numeric_limits<double> {
|
||||||
|
public:
|
||||||
|
static double lowest() { return -DBL_MAX; }
|
||||||
|
};
|
||||||
|
|
||||||
template <> class numeric_limits<unsigned long long> {
|
template <> class numeric_limits<unsigned long long> {
|
||||||
public:
|
public:
|
||||||
static unsigned long long min() { return 0ULL; }
|
static unsigned long long min() { return 0ULL; }
|
||||||
static unsigned long long max() { return ~0ULL; }
|
static unsigned long long max() { return ~0ULL; }
|
||||||
|
static unsigned long long lowest() {
|
||||||
|
return numeric_limits<unsigned long long>::min();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> class numeric_limits<long long> {
|
template <> class numeric_limits<long long> {
|
||||||
@@ -95,15 +126,19 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
|||||||
return static_cast<long long>(
|
return static_cast<long long>(
|
||||||
(1ULL << ((sizeof(long long) << 3) - 1)) - 1);
|
(1ULL << ((sizeof(long long) << 3) - 1)) - 1);
|
||||||
}
|
}
|
||||||
|
static long long lowest() {
|
||||||
|
return numeric_limits<long long>::min();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
#endif // FLATBUFFERS_CPP98_STL
|
#endif // FLATBUFFERS_CPP98_STL
|
||||||
|
|
||||||
#if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
#if defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||||
#ifndef FLATBUFFERS_CPP98_STL
|
#ifndef FLATBUFFERS_CPP98_STL
|
||||||
template <typename T> using is_scalar = std::is_scalar<T>;
|
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, 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_floating_point = std::is_floating_point<T>;
|
||||||
template <typename T> using is_unsigned = std::is_unsigned<T>;
|
template <typename T> using is_unsigned = std::is_unsigned<T>;
|
||||||
|
template <typename T> using make_unsigned = std::make_unsigned<T>;
|
||||||
#else
|
#else
|
||||||
// Map C++ TR1 templates defined by stlport.
|
// Map C++ TR1 templates defined by stlport.
|
||||||
template <typename T> using is_scalar = std::tr1::is_scalar<T>;
|
template <typename T> using is_scalar = std::tr1::is_scalar<T>;
|
||||||
@@ -111,6 +146,17 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
|||||||
template <typename T> using is_floating_point =
|
template <typename T> using is_floating_point =
|
||||||
std::tr1::is_floating_point<T>;
|
std::tr1::is_floating_point<T>;
|
||||||
template <typename T> using is_unsigned = std::tr1::is_unsigned<T>;
|
template <typename T> using is_unsigned = std::tr1::is_unsigned<T>;
|
||||||
|
// Android NDK doesn't have std::make_unsigned or std::tr1::make_unsigned.
|
||||||
|
template<typename T> struct make_unsigned {
|
||||||
|
static_assert(is_unsigned<T>::value, "Specialization not implemented!");
|
||||||
|
using type = T;
|
||||||
|
};
|
||||||
|
template<> struct make_unsigned<char> { using type = unsigned char; };
|
||||||
|
template<> struct make_unsigned<short> { using type = unsigned short; };
|
||||||
|
template<> struct make_unsigned<int> { using type = unsigned int; };
|
||||||
|
template<> struct make_unsigned<long> { using type = unsigned long; };
|
||||||
|
template<>
|
||||||
|
struct make_unsigned<long long> { using type = unsigned long long; };
|
||||||
#endif // !FLATBUFFERS_CPP98_STL
|
#endif // !FLATBUFFERS_CPP98_STL
|
||||||
#else
|
#else
|
||||||
// MSVC 2010 doesn't support C++11 aliases.
|
// MSVC 2010 doesn't support C++11 aliases.
|
||||||
@@ -119,10 +165,11 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
|||||||
template <typename T> struct is_floating_point :
|
template <typename T> struct is_floating_point :
|
||||||
public std::is_floating_point<T> {};
|
public std::is_floating_point<T> {};
|
||||||
template <typename T> struct is_unsigned : public std::is_unsigned<T> {};
|
template <typename T> struct is_unsigned : public std::is_unsigned<T> {};
|
||||||
#endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
template <typename T> struct make_unsigned : public std::make_unsigned<T> {};
|
||||||
|
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||||
|
|
||||||
#ifndef FLATBUFFERS_CPP98_STL
|
#ifndef FLATBUFFERS_CPP98_STL
|
||||||
#if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
#if defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||||
template <class T> using unique_ptr = std::unique_ptr<T>;
|
template <class T> using unique_ptr = std::unique_ptr<T>;
|
||||||
#else
|
#else
|
||||||
// MSVC 2010 doesn't support C++11 aliases.
|
// MSVC 2010 doesn't support C++11 aliases.
|
||||||
@@ -148,7 +195,7 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
|||||||
return std::unique_ptr<T>::operator=(p);
|
return std::unique_ptr<T>::operator=(p);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
#endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
|
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||||
#else
|
#else
|
||||||
// Very limited implementation of unique_ptr.
|
// Very limited implementation of unique_ptr.
|
||||||
// This is provided simply to allow the C++ code generated from the default
|
// This is provided simply to allow the C++ code generated from the default
|
||||||
|
|||||||
@@ -17,41 +17,111 @@
|
|||||||
#ifndef FLATBUFFERS_UTIL_H_
|
#ifndef FLATBUFFERS_UTIL_H_
|
||||||
#define FLATBUFFERS_UTIL_H_
|
#define FLATBUFFERS_UTIL_H_
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
|
||||||
#ifdef _WIN32
|
|
||||||
# ifndef WIN32_LEAN_AND_MEAN
|
|
||||||
# define WIN32_LEAN_AND_MEAN
|
|
||||||
# endif
|
|
||||||
# ifndef NOMINMAX
|
|
||||||
# define NOMINMAX
|
|
||||||
# endif
|
|
||||||
# include <windows.h> // Must be included before <direct.h>
|
|
||||||
# include <direct.h>
|
|
||||||
# include <winbase.h>
|
|
||||||
# undef interface // This is also important because of reasons
|
|
||||||
#else
|
|
||||||
# include <limits.h>
|
|
||||||
#endif
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include "flatbuffers/base.h"
|
#include "flatbuffers/base.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#ifndef FLATBUFFERS_PREFER_PRINTF
|
||||||
|
# include <sstream>
|
||||||
|
#else // FLATBUFFERS_PREFER_PRINTF
|
||||||
|
# include <float.h>
|
||||||
|
# include <stdio.h>
|
||||||
|
#endif // FLATBUFFERS_PREFER_PRINTF
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace flatbuffers {
|
namespace flatbuffers {
|
||||||
|
|
||||||
|
// @locale-independent functions for ASCII characters set.
|
||||||
|
|
||||||
|
// Fast checking that character lies in closed range: [a <= x <= b]
|
||||||
|
// using one compare (conditional branch) operator.
|
||||||
|
inline bool check_ascii_range(char x, char a, char b) {
|
||||||
|
FLATBUFFERS_ASSERT(a <= b);
|
||||||
|
// (Hacker's Delight): `a <= x <= b` <=> `(x-a) <={u} (b-a)`.
|
||||||
|
// The x, a, b will be promoted to int and subtracted without overflow.
|
||||||
|
return static_cast<unsigned int>(x - a) <= static_cast<unsigned int>(b - a);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case-insensitive isalpha
|
||||||
|
inline bool is_alpha(char c) {
|
||||||
|
// ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF).
|
||||||
|
return check_ascii_range(c & 0xDF, 'a' & 0xDF, 'z' & 0xDF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check (case-insensitive) that `c` is equal to alpha.
|
||||||
|
inline bool is_alpha_char(char c, char alpha) {
|
||||||
|
FLATBUFFERS_ASSERT(is_alpha(alpha));
|
||||||
|
// ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF).
|
||||||
|
return ((c & 0xDF) == (alpha & 0xDF));
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://en.cppreference.com/w/cpp/string/byte/isxdigit
|
||||||
|
// isdigit and isxdigit are the only standard narrow character classification
|
||||||
|
// functions that are not affected by the currently installed C locale. although
|
||||||
|
// some implementations (e.g. Microsoft in 1252 codepage) may classify
|
||||||
|
// additional single-byte characters as digits.
|
||||||
|
inline bool is_digit(char c) { return check_ascii_range(c, '0', '9'); }
|
||||||
|
|
||||||
|
inline bool is_xdigit(char c) {
|
||||||
|
// Replace by look-up table.
|
||||||
|
return is_digit(c) || check_ascii_range(c & 0xDF, 'a' & 0xDF, 'f' & 0xDF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Case-insensitive isalnum
|
||||||
|
inline bool is_alnum(char c) { return is_alpha(c) || is_digit(c); }
|
||||||
|
|
||||||
|
// @end-locale-independent functions for ASCII character set
|
||||||
|
|
||||||
|
#ifdef FLATBUFFERS_PREFER_PRINTF
|
||||||
|
template<typename T> size_t IntToDigitCount(T t) {
|
||||||
|
size_t digit_count = 0;
|
||||||
|
// Count the sign for negative numbers
|
||||||
|
if (t < 0) digit_count++;
|
||||||
|
// Count a single 0 left of the dot for fractional numbers
|
||||||
|
if (-1 < t && t < 1) digit_count++;
|
||||||
|
// Count digits until fractional part
|
||||||
|
T eps = std::numeric_limits<float>::epsilon();
|
||||||
|
while (t <= (-1 + eps) || (1 - eps) <= t) {
|
||||||
|
t /= 10;
|
||||||
|
digit_count++;
|
||||||
|
}
|
||||||
|
return digit_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> size_t NumToStringWidth(T t, int precision = 0) {
|
||||||
|
size_t string_width = IntToDigitCount(t);
|
||||||
|
// Count the dot for floating point numbers
|
||||||
|
if (precision) string_width += (precision + 1);
|
||||||
|
return string_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
std::string NumToStringImplWrapper(T t, const char *fmt, int precision = 0) {
|
||||||
|
size_t string_width = NumToStringWidth(t, precision);
|
||||||
|
std::string s(string_width, 0x00);
|
||||||
|
// Allow snprintf to use std::string trailing null to detect buffer overflow
|
||||||
|
snprintf(const_cast<char *>(s.data()), (s.size() + 1), fmt, precision, t);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
#endif // FLATBUFFERS_PREFER_PRINTF
|
||||||
|
|
||||||
// Convert an integer or floating point value to a string.
|
// Convert an integer or floating point value to a string.
|
||||||
// In contrast to std::stringstream, "char" values are
|
// In contrast to std::stringstream, "char" values are
|
||||||
// converted to a string of digits, and we don't use scientific notation.
|
// converted to a string of digits, and we don't use scientific notation.
|
||||||
template<typename T> std::string NumToString(T t) {
|
template<typename T> std::string NumToString(T t) {
|
||||||
std::stringstream ss;
|
// clang-format off
|
||||||
ss << t;
|
|
||||||
return ss.str();
|
#ifndef FLATBUFFERS_PREFER_PRINTF
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << t;
|
||||||
|
return ss.str();
|
||||||
|
#else // FLATBUFFERS_PREFER_PRINTF
|
||||||
|
auto v = static_cast<long long>(t);
|
||||||
|
return NumToStringImplWrapper(v, "%.*lld");
|
||||||
|
#endif // FLATBUFFERS_PREFER_PRINTF
|
||||||
|
// clang-format on
|
||||||
}
|
}
|
||||||
// Avoid char types used as character data.
|
// Avoid char types used as character data.
|
||||||
template<> inline std::string NumToString<signed char>(signed char t) {
|
template<> inline std::string NumToString<signed char>(signed char t) {
|
||||||
@@ -60,6 +130,9 @@ 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));
|
||||||
}
|
}
|
||||||
|
template<> inline std::string NumToString<char>(char t) {
|
||||||
|
return NumToString(static_cast<int>(t));
|
||||||
|
}
|
||||||
#if defined(FLATBUFFERS_CPP98_STL)
|
#if defined(FLATBUFFERS_CPP98_STL)
|
||||||
template<> inline std::string NumToString<long long>(long long t) {
|
template<> inline std::string NumToString<long long>(long long t) {
|
||||||
char buf[21]; // (log((1 << 63) - 1) / log(10)) + 2
|
char buf[21]; // (log((1 << 63) - 1) / log(10)) + 2
|
||||||
@@ -77,15 +150,23 @@ inline std::string NumToString<unsigned long long>(unsigned long long t) {
|
|||||||
|
|
||||||
// Special versions for floats/doubles.
|
// Special versions for floats/doubles.
|
||||||
template<typename T> std::string FloatToString(T t, int precision) {
|
template<typename T> std::string FloatToString(T t, int precision) {
|
||||||
// to_string() prints different numbers of digits for floats depending on
|
// clang-format off
|
||||||
// platform and isn't available on Android, so we use stringstream
|
|
||||||
std::stringstream ss;
|
#ifndef FLATBUFFERS_PREFER_PRINTF
|
||||||
// Use std::fixed to surpress scientific notation.
|
// to_string() prints different numbers of digits for floats depending on
|
||||||
ss << std::fixed;
|
// platform and isn't available on Android, so we use stringstream
|
||||||
// Default precision is 6, we want that to be higher for doubles.
|
std::stringstream ss;
|
||||||
ss << std::setprecision(precision);
|
// Use std::fixed to suppress scientific notation.
|
||||||
ss << t;
|
ss << std::fixed;
|
||||||
auto s = ss.str();
|
// Default precision is 6, we want that to be higher for doubles.
|
||||||
|
ss << std::setprecision(precision);
|
||||||
|
ss << t;
|
||||||
|
auto s = ss.str();
|
||||||
|
#else // FLATBUFFERS_PREFER_PRINTF
|
||||||
|
auto v = static_cast<double>(t);
|
||||||
|
auto s = NumToStringImplWrapper(v, "%0.*f", precision);
|
||||||
|
#endif // FLATBUFFERS_PREFER_PRINTF
|
||||||
|
// clang-format on
|
||||||
// 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');
|
||||||
if (p != std::string::npos) {
|
if (p != std::string::npos) {
|
||||||
@@ -106,34 +187,207 @@ template<> inline std::string NumToString<float>(float t) {
|
|||||||
// The returned string length is always xdigits long, prefixed by 0 digits.
|
// The returned string length is always xdigits long, prefixed by 0 digits.
|
||||||
// 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;
|
FLATBUFFERS_ASSERT(i >= 0);
|
||||||
ss << std::setw(xdigits) << std::setfill('0') << std::hex << std::uppercase
|
|
||||||
<< i;
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Portable implementation of strtoll().
|
|
||||||
inline int64_t StringToInt(const char *str, char **endptr = nullptr,
|
|
||||||
int base = 10) {
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
#ifdef _MSC_VER
|
|
||||||
return _strtoi64(str, endptr, base);
|
#ifndef FLATBUFFERS_PREFER_PRINTF
|
||||||
#else
|
std::stringstream ss;
|
||||||
return strtoll(str, endptr, base);
|
ss << std::setw(xdigits) << std::setfill('0') << std::hex << std::uppercase
|
||||||
#endif
|
<< i;
|
||||||
|
return ss.str();
|
||||||
|
#else // FLATBUFFERS_PREFER_PRINTF
|
||||||
|
return NumToStringImplWrapper(i, "%.*X", xdigits);
|
||||||
|
#endif // FLATBUFFERS_PREFER_PRINTF
|
||||||
// clang-format on
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
// Portable implementation of strtoull().
|
// clang-format off
|
||||||
inline uint64_t StringToUInt(const char *str, char **endptr = nullptr,
|
// Use locale independent functions {strtod_l, strtof_l, strtoll_l, strtoull_l}.
|
||||||
int base = 10) {
|
#if defined(FLATBUFFERS_LOCALE_INDEPENDENT) && (FLATBUFFERS_LOCALE_INDEPENDENT > 0)
|
||||||
// clang-format off
|
class ClassicLocale {
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
typedef _locale_t locale_type;
|
||||||
|
#else
|
||||||
|
typedef locale_t locale_type; // POSIX.1-2008 locale_t type
|
||||||
|
#endif
|
||||||
|
ClassicLocale();
|
||||||
|
~ClassicLocale();
|
||||||
|
locale_type locale_;
|
||||||
|
static ClassicLocale instance_;
|
||||||
|
public:
|
||||||
|
static locale_type Get() { return instance_.locale_; }
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
return _strtoui64(str, endptr, base);
|
#define __strtoull_impl(s, pe, b) _strtoui64_l(s, pe, b, ClassicLocale::Get())
|
||||||
|
#define __strtoll_impl(s, pe, b) _strtoi64_l(s, pe, b, ClassicLocale::Get())
|
||||||
|
#define __strtod_impl(s, pe) _strtod_l(s, pe, ClassicLocale::Get())
|
||||||
|
#define __strtof_impl(s, pe) _strtof_l(s, pe, ClassicLocale::Get())
|
||||||
#else
|
#else
|
||||||
return strtoull(str, endptr, base);
|
#define __strtoull_impl(s, pe, b) strtoull_l(s, pe, b, ClassicLocale::Get())
|
||||||
|
#define __strtoll_impl(s, pe, b) strtoll_l(s, pe, b, ClassicLocale::Get())
|
||||||
|
#define __strtod_impl(s, pe) strtod_l(s, pe, ClassicLocale::Get())
|
||||||
|
#define __strtof_impl(s, pe) strtof_l(s, pe, ClassicLocale::Get())
|
||||||
#endif
|
#endif
|
||||||
// clang-format on
|
#else
|
||||||
|
#define __strtod_impl(s, pe) strtod(s, pe)
|
||||||
|
#define __strtof_impl(s, pe) static_cast<float>(strtod(s, pe))
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define __strtoull_impl(s, pe, b) _strtoui64(s, pe, b)
|
||||||
|
#define __strtoll_impl(s, pe, b) _strtoi64(s, pe, b)
|
||||||
|
#else
|
||||||
|
#define __strtoull_impl(s, pe, b) strtoull(s, pe, b)
|
||||||
|
#define __strtoll_impl(s, pe, b) strtoll(s, pe, b)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
inline void strtoval_impl(int64_t *val, const char *str, char **endptr,
|
||||||
|
int base) {
|
||||||
|
*val = __strtoll_impl(str, endptr, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void strtoval_impl(uint64_t *val, const char *str, char **endptr,
|
||||||
|
int base) {
|
||||||
|
*val = __strtoull_impl(str, endptr, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void strtoval_impl(double *val, const char *str, char **endptr) {
|
||||||
|
*val = __strtod_impl(str, endptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
// UBSAN: double to float is safe if numeric_limits<float>::is_iec559 is true.
|
||||||
|
__supress_ubsan__("float-cast-overflow")
|
||||||
|
inline void strtoval_impl(float *val, const char *str, char **endptr) {
|
||||||
|
*val = __strtof_impl(str, endptr);
|
||||||
|
}
|
||||||
|
#undef __strtoull_impl
|
||||||
|
#undef __strtoll_impl
|
||||||
|
#undef __strtod_impl
|
||||||
|
#undef __strtof_impl
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
// Adaptor for strtoull()/strtoll().
|
||||||
|
// Flatbuffers accepts numbers with any count of leading zeros (-009 is -9),
|
||||||
|
// while strtoll with base=0 interprets first leading zero as octal prefix.
|
||||||
|
// In future, it is possible to add prefixed 0b0101.
|
||||||
|
// 1) Checks errno code for overflow condition (out of range).
|
||||||
|
// 2) If base <= 0, function try to detect base of number by prefix.
|
||||||
|
//
|
||||||
|
// Return value (like strtoull and strtoll, but reject partial result):
|
||||||
|
// - If successful, an integer value corresponding to the str is returned.
|
||||||
|
// - If full string conversion can't be performed, 0 is returned.
|
||||||
|
// - If the converted value falls out of range of corresponding return type, a
|
||||||
|
// range error occurs. In this case value MAX(T)/MIN(T) is returned.
|
||||||
|
template<typename T>
|
||||||
|
inline bool StringToIntegerImpl(T *val, const char *const str,
|
||||||
|
const int base = 0,
|
||||||
|
const bool check_errno = true) {
|
||||||
|
// T is int64_t or uint64_T
|
||||||
|
FLATBUFFERS_ASSERT(str);
|
||||||
|
if (base <= 0) {
|
||||||
|
auto s = str;
|
||||||
|
while (*s && !is_digit(*s)) s++;
|
||||||
|
if (s[0] == '0' && is_alpha_char(s[1], 'X'))
|
||||||
|
return StringToIntegerImpl(val, str, 16, check_errno);
|
||||||
|
// if a prefix not match, try base=10
|
||||||
|
return StringToIntegerImpl(val, str, 10, check_errno);
|
||||||
|
} else {
|
||||||
|
if (check_errno) errno = 0; // clear thread-local errno
|
||||||
|
auto endptr = str;
|
||||||
|
strtoval_impl(val, str, const_cast<char **>(&endptr), base);
|
||||||
|
if ((*endptr != '\0') || (endptr == str)) {
|
||||||
|
*val = 0; // erase partial result
|
||||||
|
return false; // invalid string
|
||||||
|
}
|
||||||
|
// errno is out-of-range, return MAX/MIN
|
||||||
|
if (check_errno && errno) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline bool StringToFloatImpl(T *val, const char *const str) {
|
||||||
|
// Type T must be either float or double.
|
||||||
|
FLATBUFFERS_ASSERT(str && val);
|
||||||
|
auto end = str;
|
||||||
|
strtoval_impl(val, str, const_cast<char **>(&end));
|
||||||
|
auto done = (end != str) && (*end == '\0');
|
||||||
|
if (!done) *val = 0; // erase partial result
|
||||||
|
return done;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert a string to an instance of T.
|
||||||
|
// Return value (matched with StringToInteger64Impl and strtod):
|
||||||
|
// - If successful, a numeric value corresponding to the str is returned.
|
||||||
|
// - If full string conversion can't be performed, 0 is returned.
|
||||||
|
// - If the converted value falls out of range of corresponding return type, a
|
||||||
|
// range error occurs. In this case value MAX(T)/MIN(T) is returned.
|
||||||
|
template<typename T> inline bool StringToNumber(const char *s, T *val) {
|
||||||
|
FLATBUFFERS_ASSERT(s && val);
|
||||||
|
int64_t i64;
|
||||||
|
// The errno check isn't needed, will return MAX/MIN on overflow.
|
||||||
|
if (StringToIntegerImpl(&i64, s, 0, false)) {
|
||||||
|
const int64_t max = flatbuffers::numeric_limits<T>::max();
|
||||||
|
const int64_t min = flatbuffers::numeric_limits<T>::lowest();
|
||||||
|
if (i64 > max) {
|
||||||
|
*val = static_cast<T>(max);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (i64 < min) {
|
||||||
|
// For unsigned types return max to distinguish from
|
||||||
|
// "no conversion can be performed" when 0 is returned.
|
||||||
|
*val = static_cast<T>(flatbuffers::is_unsigned<T>::value ? max : min);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*val = static_cast<T>(i64);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*val = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> inline bool StringToNumber<int64_t>(const char *str, int64_t *val) {
|
||||||
|
return StringToIntegerImpl(val, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
inline bool StringToNumber<uint64_t>(const char *str, uint64_t *val) {
|
||||||
|
if (!StringToIntegerImpl(val, str)) return false;
|
||||||
|
// The strtoull accepts negative numbers:
|
||||||
|
// If the minus sign was part of the input sequence, the numeric value
|
||||||
|
// calculated from the sequence of digits is negated as if by unary minus
|
||||||
|
// in the result type, which applies unsigned integer wraparound rules.
|
||||||
|
// Fix this behaviour (except -0).
|
||||||
|
if (*val) {
|
||||||
|
auto s = str;
|
||||||
|
while (*s && !is_digit(*s)) s++;
|
||||||
|
s = (s > str) ? (s - 1) : s; // step back to one symbol
|
||||||
|
if (*s == '-') {
|
||||||
|
// For unsigned types return the max to distinguish from
|
||||||
|
// "no conversion can be performed".
|
||||||
|
*val = flatbuffers::numeric_limits<uint64_t>::max();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> inline bool StringToNumber(const char *s, float *val) {
|
||||||
|
return StringToFloatImpl(val, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<> inline bool StringToNumber(const char *s, double *val) {
|
||||||
|
return StringToFloatImpl(val, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int64_t StringToInt(const char *s, int base = 10) {
|
||||||
|
int64_t val;
|
||||||
|
return StringToIntegerImpl(&val, s, base) ? val : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint64_t StringToUInt(const char *s, int base = 10) {
|
||||||
|
uint64_t val;
|
||||||
|
return StringToIntegerImpl(&val, s, base) ? val : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef bool (*LoadFileFunction)(const char *filename, bool binary,
|
typedef bool (*LoadFileFunction)(const char *filename, bool binary,
|
||||||
@@ -162,13 +416,7 @@ bool LoadFile(const char *name, bool binary, std::string *buf);
|
|||||||
// If "binary" is false data is written using ifstream's
|
// If "binary" is false data is written using ifstream's
|
||||||
// text mode, otherwise data is written with no
|
// text mode, otherwise data is written with no
|
||||||
// transcoding.
|
// transcoding.
|
||||||
inline bool SaveFile(const char *name, const char *buf, size_t len,
|
bool SaveFile(const char *name, const char *buf, size_t len, bool binary);
|
||||||
bool binary) {
|
|
||||||
std::ofstream ofs(name, binary ? std::ofstream::binary : std::ofstream::out);
|
|
||||||
if (!ofs.is_open()) return false;
|
|
||||||
ofs.write(buf, len);
|
|
||||||
return !ofs.bad();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save data "buf" into file "name" returning true if
|
// Save data "buf" into file "name" returning true if
|
||||||
// successful, false otherwise. If "binary" is false
|
// successful, false otherwise. If "binary" is false
|
||||||
@@ -184,107 +432,42 @@ inline bool SaveFile(const char *name, const std::string &buf, bool binary) {
|
|||||||
// Windows ('/' or '\\') separators are used.
|
// Windows ('/' or '\\') separators are used.
|
||||||
|
|
||||||
// Any new separators inserted are always posix.
|
// Any new separators inserted are always posix.
|
||||||
|
FLATBUFFERS_CONSTEXPR char kPathSeparator = '/';
|
||||||
// We internally store paths in posix format ('/'). Paths supplied
|
|
||||||
// by the user should go through PosixPath to ensure correct behavior
|
|
||||||
// on Windows when paths are string-compared.
|
|
||||||
|
|
||||||
static const char kPathSeparator = '/';
|
|
||||||
static const char kPathSeparatorWindows = '\\';
|
|
||||||
static const char *PathSeparatorSet = "\\/"; // Intentionally no ':'
|
|
||||||
|
|
||||||
// Returns the path with the extension, if any, removed.
|
// Returns the path with the extension, if any, removed.
|
||||||
inline std::string StripExtension(const std::string &filepath) {
|
std::string StripExtension(const std::string &filepath);
|
||||||
size_t i = filepath.find_last_of(".");
|
|
||||||
return i != std::string::npos ? filepath.substr(0, i) : filepath;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the extension, if any.
|
// Returns the extension, if any.
|
||||||
inline std::string GetExtension(const std::string &filepath) {
|
std::string GetExtension(const std::string &filepath);
|
||||||
size_t i = filepath.find_last_of(".");
|
|
||||||
return i != std::string::npos ? filepath.substr(i + 1) : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the last component of the path, after the last separator.
|
// Return the last component of the path, after the last separator.
|
||||||
inline std::string StripPath(const std::string &filepath) {
|
std::string StripPath(const std::string &filepath);
|
||||||
size_t i = filepath.find_last_of(PathSeparatorSet);
|
|
||||||
return i != std::string::npos ? filepath.substr(i + 1) : filepath;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Strip the last component of the path + separator.
|
// Strip the last component of the path + separator.
|
||||||
inline std::string StripFileName(const std::string &filepath) {
|
std::string StripFileName(const std::string &filepath);
|
||||||
size_t i = filepath.find_last_of(PathSeparatorSet);
|
|
||||||
return i != std::string::npos ? filepath.substr(0, i) : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Concatenates a path with a filename, regardless of wether the path
|
// Concatenates a path with a filename, regardless of wether the path
|
||||||
// ends in a separator or not.
|
// ends in a separator or not.
|
||||||
inline std::string ConCatPathFileName(const std::string &path,
|
std::string ConCatPathFileName(const std::string &path,
|
||||||
const std::string &filename) {
|
const std::string &filename);
|
||||||
std::string filepath = path;
|
|
||||||
if (filepath.length()) {
|
|
||||||
char &filepath_last_character = string_back(filepath);
|
|
||||||
if (filepath_last_character == kPathSeparatorWindows) {
|
|
||||||
filepath_last_character = kPathSeparator;
|
|
||||||
} else if (filepath_last_character != kPathSeparator) {
|
|
||||||
filepath += kPathSeparator;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
filepath += filename;
|
|
||||||
// Ignore './' at the start of filepath.
|
|
||||||
if (filepath[0] == '.' && filepath[1] == kPathSeparator) {
|
|
||||||
filepath.erase(0, 2);
|
|
||||||
}
|
|
||||||
return filepath;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replaces any '\\' separators with '/'
|
// Replaces any '\\' separators with '/'
|
||||||
inline std::string PosixPath(const char *path) {
|
std::string PosixPath(const char *path);
|
||||||
std::string p = path;
|
|
||||||
std::replace(p.begin(), p.end(), '\\', '/');
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function ensure a directory exists, by recursively
|
// This function ensure a directory exists, by recursively
|
||||||
// creating dirs for any parts of the path that don't exist yet.
|
// creating dirs for any parts of the path that don't exist yet.
|
||||||
inline void EnsureDirExists(const std::string &filepath) {
|
void EnsureDirExists(const std::string &filepath);
|
||||||
auto parent = StripFileName(filepath);
|
|
||||||
if (parent.length()) EnsureDirExists(parent);
|
|
||||||
// clang-format off
|
|
||||||
#ifdef _WIN32
|
|
||||||
(void)_mkdir(filepath.c_str());
|
|
||||||
#else
|
|
||||||
mkdir(filepath.c_str(), S_IRWXU|S_IRGRP|S_IXGRP);
|
|
||||||
#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) {
|
std::string AbsolutePath(const std::string &filepath);
|
||||||
// clang-format off
|
|
||||||
#ifdef FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
|
|
||||||
return filepath;
|
|
||||||
#else
|
|
||||||
#ifdef _WIN32
|
|
||||||
char abs_path[MAX_PATH];
|
|
||||||
return GetFullPathNameA(filepath.c_str(), MAX_PATH, abs_path, nullptr)
|
|
||||||
#else
|
|
||||||
char abs_path[PATH_MAX];
|
|
||||||
return realpath(filepath.c_str(), abs_path)
|
|
||||||
#endif
|
|
||||||
? abs_path
|
|
||||||
: filepath;
|
|
||||||
#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
|
||||||
|
|
||||||
// Convert a unicode code point into a UTF-8 representation by appending it
|
// Convert a unicode code point into a UTF-8 representation by appending it
|
||||||
// to a string. Returns the number of bytes generated.
|
// to a string. Returns the number of bytes generated.
|
||||||
inline int ToUTF8(uint32_t ucc, std::string *out) {
|
inline int ToUTF8(uint32_t ucc, std::string *out) {
|
||||||
assert(!(ucc & 0x80000000)); // Top bit can't be set.
|
FLATBUFFERS_ASSERT(!(ucc & 0x80000000)); // Top bit can't be set.
|
||||||
// 6 possible encodings: http://en.wikipedia.org/wiki/UTF-8
|
// 6 possible encodings: http://en.wikipedia.org/wiki/UTF-8
|
||||||
for (int i = 0; i < 6; i++) {
|
for (int i = 0; i < 6; i++) {
|
||||||
// Max bits this encoding can represent.
|
// Max bits this encoding can represent.
|
||||||
@@ -302,7 +485,7 @@ inline int ToUTF8(uint32_t ucc, std::string *out) {
|
|||||||
return i + 1; // Return the number of bytes added.
|
return i + 1; // Return the number of bytes added.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(0); // Impossible to arrive here.
|
FLATBUFFERS_ASSERT(0); // Impossible to arrive here.
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -321,7 +504,8 @@ inline int FromUTF8(const char **in) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((static_cast<const unsigned char>(**in) << len) & 0x80) return -1; // Bit after leading 1's must be 0.
|
if ((static_cast<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) { return -1; }
|
if (len < 2 || len > 4) { return -1; }
|
||||||
@@ -353,6 +537,7 @@ inline int FromUTF8(const char **in) {
|
|||||||
return ucc;
|
return ucc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef FLATBUFFERS_PREFER_PRINTF
|
||||||
// Wraps a string to a maximum length, inserting new lines where necessary. Any
|
// Wraps a string to a maximum length, inserting new lines where necessary. Any
|
||||||
// existing whitespace will be collapsed down to a single space. A prefix or
|
// existing whitespace will be collapsed down to a single space. A prefix or
|
||||||
// suffix can be provided, which will be inserted before or after a wrapped
|
// suffix can be provided, which will be inserted before or after a wrapped
|
||||||
@@ -379,9 +564,10 @@ inline std::string WordWrap(const std::string in, size_t max_length,
|
|||||||
|
|
||||||
return wrapped;
|
return wrapped;
|
||||||
}
|
}
|
||||||
|
#endif // !FLATBUFFERS_PREFER_PRINTF
|
||||||
|
|
||||||
inline bool EscapeString(const char *s, size_t length, std::string *_text,
|
inline bool EscapeString(const char *s, size_t length, std::string *_text,
|
||||||
bool allow_non_utf8) {
|
bool allow_non_utf8, bool natural_utf8) {
|
||||||
std::string &text = *_text;
|
std::string &text = *_text;
|
||||||
text += "\"";
|
text += "\"";
|
||||||
for (uoffset_t i = 0; i < length; i++) {
|
for (uoffset_t i = 0; i < length; i++) {
|
||||||
@@ -421,7 +607,10 @@ inline bool EscapeString(const char *s, size_t length, std::string *_text,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (ucc <= 0xFFFF) {
|
if (natural_utf8) {
|
||||||
|
// utf8 points to past all utf-8 bytes parsed
|
||||||
|
text.append(s + i, static_cast<size_t>(utf8 - s - i));
|
||||||
|
} else if (ucc <= 0xFFFF) {
|
||||||
// Parses as Unicode within JSON's \uXXXX range, so use that.
|
// Parses as Unicode within JSON's \uXXXX range, so use that.
|
||||||
text += "\\u";
|
text += "\\u";
|
||||||
text += IntToStringHex(ucc, 4);
|
text += IntToStringHex(ucc, 4);
|
||||||
@@ -447,6 +636,19 @@ inline bool EscapeString(const char *s, size_t length, std::string *_text,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove paired quotes in a string: "text"|'text' -> text.
|
||||||
|
std::string RemoveStringQuotes(const std::string &s);
|
||||||
|
|
||||||
|
// Change th global C-locale to locale with name <locale_name>.
|
||||||
|
// Returns an actual locale name in <_value>, useful if locale_name is "" or
|
||||||
|
// null.
|
||||||
|
bool SetGlobalTestLocale(const char *locale_name,
|
||||||
|
std::string *_value = nullptr);
|
||||||
|
|
||||||
|
// Read (or test) a value of environment variable.
|
||||||
|
bool ReadEnvironmentVariable(const char *var_name,
|
||||||
|
std::string *_value = nullptr);
|
||||||
|
|
||||||
} // namespace flatbuffers
|
} // namespace flatbuffers
|
||||||
|
|
||||||
#endif // FLATBUFFERS_UTIL_H_
|
#endif // FLATBUFFERS_UTIL_H_
|
||||||
|
|||||||
@@ -21,11 +21,7 @@ import static com.google.flatbuffers.Constants.*;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
import java.nio.charset.CharacterCodingException;
|
|
||||||
import java.nio.charset.CharsetEncoder;
|
|
||||||
import java.nio.charset.CoderResult;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.nio.charset.Charset;
|
|
||||||
|
|
||||||
/// @file
|
/// @file
|
||||||
/// @addtogroup flatbuffers_java_api
|
/// @addtogroup flatbuffers_java_api
|
||||||
@@ -39,7 +35,6 @@ public class FlatBufferBuilder {
|
|||||||
/// @cond FLATBUFFERS_INTERNAL
|
/// @cond FLATBUFFERS_INTERNAL
|
||||||
ByteBuffer bb; // Where we construct the FlatBuffer.
|
ByteBuffer bb; // Where we construct the FlatBuffer.
|
||||||
int space; // Remaining space in the ByteBuffer.
|
int space; // Remaining space in the ByteBuffer.
|
||||||
static final Charset utf8charset = Charset.forName("UTF-8"); // The UTF-8 character set used by FlatBuffers.
|
|
||||||
int minalign = 1; // Minimum alignment encountered so far.
|
int minalign = 1; // Minimum alignment encountered so far.
|
||||||
int[] vtable = null; // The vtable for the current table.
|
int[] vtable = null; // The vtable for the current table.
|
||||||
int vtable_in_use = 0; // The amount of fields we're actually using.
|
int vtable_in_use = 0; // The amount of fields we're actually using.
|
||||||
@@ -50,9 +45,8 @@ public class FlatBufferBuilder {
|
|||||||
int num_vtables = 0; // Number of entries in `vtables` in use.
|
int num_vtables = 0; // Number of entries in `vtables` in use.
|
||||||
int vector_num_elems = 0; // For the current vector being built.
|
int vector_num_elems = 0; // For the current vector being built.
|
||||||
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();
|
|
||||||
ByteBuffer dst;
|
|
||||||
ByteBufferFactory bb_factory; // Factory for allocating the internal buffer
|
ByteBufferFactory bb_factory; // Factory for allocating the internal buffer
|
||||||
|
final Utf8 utf8; // UTF-8 encoder to use
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -62,10 +56,32 @@ public class FlatBufferBuilder {
|
|||||||
* @param bb_factory The factory to be used for allocating the internal buffer
|
* @param bb_factory The factory to be used for allocating the internal buffer
|
||||||
*/
|
*/
|
||||||
public FlatBufferBuilder(int initial_size, ByteBufferFactory bb_factory) {
|
public FlatBufferBuilder(int initial_size, ByteBufferFactory bb_factory) {
|
||||||
if (initial_size <= 0) initial_size = 1;
|
this(initial_size, bb_factory, null, Utf8.getDefault());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* @param existing_bb The byte buffer to reuse.
|
||||||
|
* @param utf8 The Utf8 codec
|
||||||
|
*/
|
||||||
|
public FlatBufferBuilder(int initial_size, ByteBufferFactory bb_factory,
|
||||||
|
ByteBuffer existing_bb, Utf8 utf8) {
|
||||||
|
if (initial_size <= 0) {
|
||||||
|
initial_size = 1;
|
||||||
|
}
|
||||||
space = initial_size;
|
space = initial_size;
|
||||||
this.bb_factory = bb_factory;
|
this.bb_factory = bb_factory;
|
||||||
bb = bb_factory.newByteBuffer(initial_size);
|
if (existing_bb != null) {
|
||||||
|
bb = existing_bb;
|
||||||
|
bb.clear();
|
||||||
|
bb.order(ByteOrder.LITTLE_ENDIAN);
|
||||||
|
} else {
|
||||||
|
bb = bb_factory.newByteBuffer(initial_size);
|
||||||
|
}
|
||||||
|
this.utf8 = utf8;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -74,7 +90,7 @@ public class FlatBufferBuilder {
|
|||||||
* @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) {
|
||||||
this(initial_size, new HeapByteBufferFactory());
|
this(initial_size, HeapByteBufferFactory.INSTANCE, null, Utf8.getDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -94,7 +110,7 @@ public class FlatBufferBuilder {
|
|||||||
* the existing buffer needs to grow
|
* the existing buffer needs to grow
|
||||||
*/
|
*/
|
||||||
public FlatBufferBuilder(ByteBuffer existing_bb, ByteBufferFactory bb_factory) {
|
public FlatBufferBuilder(ByteBuffer existing_bb, ByteBufferFactory bb_factory) {
|
||||||
init(existing_bb, bb_factory);
|
this(existing_bb.capacity(), bb_factory, existing_bb, Utf8.getDefault());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,7 +121,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, new HeapByteBufferFactory());
|
this(existing_bb, new HeapByteBufferFactory());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -144,14 +160,27 @@ public class FlatBufferBuilder {
|
|||||||
* preserve the default behavior in the event that the user does not provide
|
* preserve the default behavior in the event that the user does not provide
|
||||||
* their own implementation of this interface.
|
* their own implementation of this interface.
|
||||||
*/
|
*/
|
||||||
public interface ByteBufferFactory {
|
public static abstract class ByteBufferFactory {
|
||||||
/**
|
/**
|
||||||
* Create a `ByteBuffer` with a given capacity.
|
* Create a `ByteBuffer` with a given capacity.
|
||||||
|
* The returned ByteBuf must have a ByteOrder.LITTLE_ENDIAN ByteOrder.
|
||||||
*
|
*
|
||||||
* @param capacity The size of the `ByteBuffer` to allocate.
|
* @param capacity The size of the `ByteBuffer` to allocate.
|
||||||
* @return Returns the new `ByteBuffer` that was allocated.
|
* @return Returns the new `ByteBuffer` that was allocated.
|
||||||
*/
|
*/
|
||||||
ByteBuffer newByteBuffer(int capacity);
|
public abstract ByteBuffer newByteBuffer(int capacity);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release a ByteBuffer. Current {@link FlatBufferBuilder}
|
||||||
|
* released any reference to it, so it is safe to dispose the buffer
|
||||||
|
* or return it to a pool.
|
||||||
|
* It is not guaranteed that the buffer has been created
|
||||||
|
* with {@link #newByteBuffer(int) }.
|
||||||
|
*
|
||||||
|
* @param bb the buffer to release
|
||||||
|
*/
|
||||||
|
public void releaseByteBuffer(ByteBuffer bb) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -160,7 +189,10 @@ public class FlatBufferBuilder {
|
|||||||
*
|
*
|
||||||
* Allocate memory for a new byte-array backed `ByteBuffer` array inside the JVM.
|
* Allocate memory for a new byte-array backed `ByteBuffer` array inside the JVM.
|
||||||
*/
|
*/
|
||||||
public static final class HeapByteBufferFactory implements ByteBufferFactory {
|
public static final class HeapByteBufferFactory extends ByteBufferFactory {
|
||||||
|
|
||||||
|
public static final HeapByteBufferFactory INSTANCE = new HeapByteBufferFactory();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ByteBuffer newByteBuffer(int capacity) {
|
public ByteBuffer newByteBuffer(int capacity) {
|
||||||
return ByteBuffer.allocate(capacity).order(ByteOrder.LITTLE_ENDIAN);
|
return ByteBuffer.allocate(capacity).order(ByteOrder.LITTLE_ENDIAN);
|
||||||
@@ -241,7 +273,11 @@ 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_factory);
|
ByteBuffer old = bb;
|
||||||
|
bb = growByteBuffer(old, bb_factory);
|
||||||
|
if (old != bb) {
|
||||||
|
bb_factory.releaseByteBuffer(old);
|
||||||
|
}
|
||||||
space += bb.capacity() - old_buf_size;
|
space += bb.capacity() - old_buf_size;
|
||||||
}
|
}
|
||||||
pad(align_size);
|
pad(align_size);
|
||||||
@@ -487,27 +523,12 @@ public class FlatBufferBuilder {
|
|||||||
* @return The offset in the buffer where the encoded string starts.
|
* @return The offset in the buffer where the encoded string starts.
|
||||||
*/
|
*/
|
||||||
public int createString(CharSequence s) {
|
public int createString(CharSequence s) {
|
||||||
int length = s.length();
|
int length = utf8.encodedLength(s);
|
||||||
int estimatedDstCapacity = (int) (length * encoder.maxBytesPerChar());
|
addByte((byte)0);
|
||||||
if (dst == null || dst.capacity() < estimatedDstCapacity) {
|
startVector(1, length, 1);
|
||||||
dst = ByteBuffer.allocate(Math.max(128, estimatedDstCapacity));
|
bb.position(space -= length);
|
||||||
}
|
utf8.encodeUtf8(s, bb);
|
||||||
|
return endVector();
|
||||||
dst.clear();
|
|
||||||
|
|
||||||
CharBuffer src = s instanceof CharBuffer ? (CharBuffer) s :
|
|
||||||
CharBuffer.wrap(s);
|
|
||||||
CoderResult result = encoder.encode(src, dst, true);
|
|
||||||
if (result.isError()) {
|
|
||||||
try {
|
|
||||||
result.throwException();
|
|
||||||
} catch (CharacterCodingException x) {
|
|
||||||
throw new Error(x);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dst.flip();
|
|
||||||
return createString(dst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -28,6 +28,20 @@ public class Struct {
|
|||||||
protected int bb_pos;
|
protected int bb_pos;
|
||||||
/** The underlying ByteBuffer to hold the data of the Struct. */
|
/** The underlying ByteBuffer to hold the data of the Struct. */
|
||||||
protected ByteBuffer bb;
|
protected ByteBuffer bb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets internal state with a null {@code ByteBuffer} and a zero position.
|
||||||
|
*
|
||||||
|
* This method exists primarily to allow recycling Struct instances without risking memory leaks
|
||||||
|
* due to {@code ByteBuffer} references. The instance will be unusable until it is assigned
|
||||||
|
* again to a {@code ByteBuffer}.
|
||||||
|
*
|
||||||
|
* @param struct the instance to reset to initial state
|
||||||
|
*/
|
||||||
|
public void __reset() {
|
||||||
|
bb = null;
|
||||||
|
bb_pos = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
|||||||
@@ -19,11 +19,7 @@ package com.google.flatbuffers;
|
|||||||
import static com.google.flatbuffers.Constants.*;
|
import static com.google.flatbuffers.Constants.*;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.nio.CharBuffer;
|
|
||||||
import java.nio.charset.CharacterCodingException;
|
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.CharsetDecoder;
|
|
||||||
import java.nio.charset.CoderResult;
|
|
||||||
|
|
||||||
/// @cond FLATBUFFERS_INTERNAL
|
/// @cond FLATBUFFERS_INTERNAL
|
||||||
|
|
||||||
@@ -31,23 +27,21 @@ import java.nio.charset.CoderResult;
|
|||||||
* All tables in the generated code derive from this class, and add their own accessors.
|
* All tables in the generated code derive from this class, and add their own accessors.
|
||||||
*/
|
*/
|
||||||
public class Table {
|
public class Table {
|
||||||
private final static ThreadLocal<CharsetDecoder> UTF8_DECODER = new ThreadLocal<CharsetDecoder>() {
|
|
||||||
@Override
|
|
||||||
protected CharsetDecoder initialValue() {
|
|
||||||
return Charset.forName("UTF-8").newDecoder();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
public final static ThreadLocal<Charset> UTF8_CHARSET = new ThreadLocal<Charset>() {
|
public final static ThreadLocal<Charset> UTF8_CHARSET = new ThreadLocal<Charset>() {
|
||||||
@Override
|
@Override
|
||||||
protected Charset initialValue() {
|
protected Charset initialValue() {
|
||||||
return Charset.forName("UTF-8");
|
return Charset.forName("UTF-8");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private final static ThreadLocal<CharBuffer> CHAR_BUFFER = new ThreadLocal<CharBuffer>();
|
|
||||||
/** Used to hold the position of the `bb` buffer. */
|
/** Used to hold the position of the `bb` buffer. */
|
||||||
protected int bb_pos;
|
protected int bb_pos;
|
||||||
/** The underlying ByteBuffer to hold the data of the Table. */
|
/** The underlying ByteBuffer to hold the data of the Table. */
|
||||||
protected ByteBuffer bb;
|
protected ByteBuffer bb;
|
||||||
|
/** Used to hold the vtable position. */
|
||||||
|
protected int vtable_start;
|
||||||
|
/** Used to hold the vtable size. */
|
||||||
|
protected int vtable_size;
|
||||||
|
Utf8 utf8 = Utf8.getDefault();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the underlying ByteBuffer.
|
* Get the underlying ByteBuffer.
|
||||||
@@ -63,8 +57,7 @@ public class Table {
|
|||||||
* @return Returns an offset into the object, or `0` if the field is not present.
|
* @return Returns an offset into the object, or `0` if the field is not present.
|
||||||
*/
|
*/
|
||||||
protected int __offset(int vtable_offset) {
|
protected int __offset(int vtable_offset) {
|
||||||
int vtable = bb_pos - bb.getInt(bb_pos);
|
return vtable_offset < vtable_size ? bb.getShort(vtable_start + vtable_offset) : 0;
|
||||||
return vtable_offset < bb.getShort(vtable) ? bb.getShort(vtable + vtable_offset) : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static int __offset(int vtable_offset, int offset, ByteBuffer bb) {
|
protected static int __offset(int vtable_offset, int offset, ByteBuffer bb) {
|
||||||
@@ -98,34 +91,9 @@ public class Table {
|
|||||||
* @return Returns a `String` from the data stored inside the FlatBuffer at `offset`.
|
* @return Returns a `String` from the data stored inside the FlatBuffer at `offset`.
|
||||||
*/
|
*/
|
||||||
protected String __string(int offset) {
|
protected String __string(int offset) {
|
||||||
CharsetDecoder decoder = UTF8_DECODER.get();
|
|
||||||
decoder.reset();
|
|
||||||
|
|
||||||
offset += bb.getInt(offset);
|
offset += bb.getInt(offset);
|
||||||
ByteBuffer src = bb.duplicate().order(ByteOrder.LITTLE_ENDIAN);
|
int length = bb.getInt(offset);
|
||||||
int length = src.getInt(offset);
|
return utf8.decodeUtf8(bb, offset + SIZEOF_INT, length);
|
||||||
src.position(offset + SIZEOF_INT);
|
|
||||||
src.limit(offset + SIZEOF_INT + length);
|
|
||||||
|
|
||||||
int required = (int)((float)length * decoder.maxCharsPerByte());
|
|
||||||
CharBuffer dst = CHAR_BUFFER.get();
|
|
||||||
if (dst == null || dst.capacity() < required) {
|
|
||||||
dst = CharBuffer.allocate(required);
|
|
||||||
CHAR_BUFFER.set(dst);
|
|
||||||
}
|
|
||||||
|
|
||||||
dst.clear();
|
|
||||||
|
|
||||||
try {
|
|
||||||
CoderResult cr = decoder.decode(src, dst, true);
|
|
||||||
if (!cr.isUnderflow()) {
|
|
||||||
cr.throwException();
|
|
||||||
}
|
|
||||||
} catch (CharacterCodingException x) {
|
|
||||||
throw new RuntimeException(x);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dst.flip().toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -204,6 +172,8 @@ public class Table {
|
|||||||
offset += bb_pos;
|
offset += bb_pos;
|
||||||
t.bb_pos = offset + bb.getInt(offset);
|
t.bb_pos = offset + bb.getInt(offset);
|
||||||
t.bb = bb;
|
t.bb = bb;
|
||||||
|
t.vtable_start = t.bb_pos - bb.getInt(t.bb_pos);
|
||||||
|
t.vtable_size = bb.getShort(t.vtable_start);
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,6 +262,20 @@ public class Table {
|
|||||||
}
|
}
|
||||||
return len_1 - len_2;
|
return len_1 - len_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the internal state with a null {@code ByteBuffer} and a zero position.
|
||||||
|
*
|
||||||
|
* This method exists primarily to allow recycling Table instances without risking memory leaks
|
||||||
|
* due to {@code ByteBuffer} references. The instance will be unusable until it is assigned
|
||||||
|
* again to a {@code ByteBuffer}.
|
||||||
|
*/
|
||||||
|
public void __reset() {
|
||||||
|
bb = null;
|
||||||
|
bb_pos = 0;
|
||||||
|
vtable_start = 0;
|
||||||
|
vtable_size = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @endcond
|
/// @endcond
|
||||||
|
|||||||
191
java/com/google/flatbuffers/Utf8.java
Normal file
191
java/com/google/flatbuffers/Utf8.java
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.flatbuffers;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import static java.lang.Character.MIN_HIGH_SURROGATE;
|
||||||
|
import static java.lang.Character.MIN_LOW_SURROGATE;
|
||||||
|
import static java.lang.Character.MIN_SUPPLEMENTARY_CODE_POINT;
|
||||||
|
|
||||||
|
public abstract class Utf8 {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string,
|
||||||
|
* this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in
|
||||||
|
* both time and space.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
|
||||||
|
* surrogates)
|
||||||
|
*/
|
||||||
|
public abstract int encodedLength(CharSequence sequence);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes the given characters to the target {@link ByteBuffer} using UTF-8 encoding.
|
||||||
|
*
|
||||||
|
* <p>Selects an optimal algorithm based on the type of {@link ByteBuffer} (i.e. heap or direct)
|
||||||
|
* and the capabilities of the platform.
|
||||||
|
*
|
||||||
|
* @param in the source string to be encoded
|
||||||
|
* @param out the target buffer to receive the encoded string.
|
||||||
|
*/
|
||||||
|
public abstract void encodeUtf8(CharSequence in, ByteBuffer out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes the given UTF-8 portion of the {@link ByteBuffer} into a {@link String}.
|
||||||
|
*
|
||||||
|
* @throws IllegalArgumentException if the input is not valid UTF-8.
|
||||||
|
*/
|
||||||
|
public abstract String decodeUtf8(ByteBuffer buffer, int offset, int length);
|
||||||
|
|
||||||
|
private static Utf8 DEFAULT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the default UTF-8 processor.
|
||||||
|
* @return the default processor
|
||||||
|
*/
|
||||||
|
public static Utf8 getDefault() {
|
||||||
|
if (DEFAULT == null) {
|
||||||
|
DEFAULT = new Utf8Safe();
|
||||||
|
}
|
||||||
|
return DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the default instance of the UTF-8 processor.
|
||||||
|
* @param instance the new instance to use
|
||||||
|
*/
|
||||||
|
public static void setDefault(Utf8 instance) {
|
||||||
|
DEFAULT = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility methods for decoding bytes into {@link String}. Callers are responsible for extracting
|
||||||
|
* bytes (possibly using Unsafe methods), and checking remaining bytes. All other UTF-8 validity
|
||||||
|
* checks and codepoint conversion happen in this class.
|
||||||
|
*/
|
||||||
|
static class DecodeUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this is a single-byte codepoint (i.e., ASCII) with the form '0XXXXXXX'.
|
||||||
|
*/
|
||||||
|
static boolean isOneByte(byte b) {
|
||||||
|
return b >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this is a two-byte codepoint with the form '10XXXXXX'.
|
||||||
|
*/
|
||||||
|
static boolean isTwoBytes(byte b) {
|
||||||
|
return b < (byte) 0xE0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this is a three-byte codepoint with the form '110XXXXX'.
|
||||||
|
*/
|
||||||
|
static boolean isThreeBytes(byte b) {
|
||||||
|
return b < (byte) 0xF0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleOneByte(byte byte1, char[] resultArr, int resultPos) {
|
||||||
|
resultArr[resultPos] = (char) byte1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleTwoBytes(
|
||||||
|
byte byte1, byte byte2, char[] resultArr, int resultPos)
|
||||||
|
throws IllegalArgumentException {
|
||||||
|
// Simultaneously checks for illegal trailing-byte in leading position (<= '11000000') and
|
||||||
|
// overlong 2-byte, '11000001'.
|
||||||
|
if (byte1 < (byte) 0xC2
|
||||||
|
|| isNotTrailingByte(byte2)) {
|
||||||
|
throw new IllegalArgumentException("Invalid UTF-8");
|
||||||
|
}
|
||||||
|
resultArr[resultPos] = (char) (((byte1 & 0x1F) << 6) | trailingByteValue(byte2));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleThreeBytes(
|
||||||
|
byte byte1, byte byte2, byte byte3, char[] resultArr, int resultPos)
|
||||||
|
throws IllegalArgumentException {
|
||||||
|
if (isNotTrailingByte(byte2)
|
||||||
|
// overlong? 5 most significant bits must not all be zero
|
||||||
|
|| (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
|
||||||
|
// check for illegal surrogate codepoints
|
||||||
|
|| (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
|
||||||
|
|| isNotTrailingByte(byte3)) {
|
||||||
|
throw new IllegalArgumentException("Invalid UTF-8");
|
||||||
|
}
|
||||||
|
resultArr[resultPos] = (char)
|
||||||
|
(((byte1 & 0x0F) << 12) | (trailingByteValue(byte2) << 6) | trailingByteValue(byte3));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handleFourBytes(
|
||||||
|
byte byte1, byte byte2, byte byte3, byte byte4, char[] resultArr, int resultPos)
|
||||||
|
throws IllegalArgumentException{
|
||||||
|
if (isNotTrailingByte(byte2)
|
||||||
|
// Check that 1 <= plane <= 16. Tricky optimized form of:
|
||||||
|
// valid 4-byte leading byte?
|
||||||
|
// if (byte1 > (byte) 0xF4 ||
|
||||||
|
// overlong? 4 most significant bits must not all be zero
|
||||||
|
// byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
|
||||||
|
// codepoint larger than the highest code point (U+10FFFF)?
|
||||||
|
// byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
|
||||||
|
|| (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
|
||||||
|
|| isNotTrailingByte(byte3)
|
||||||
|
|| isNotTrailingByte(byte4)) {
|
||||||
|
throw new IllegalArgumentException("Invalid UTF-8");
|
||||||
|
}
|
||||||
|
int codepoint = ((byte1 & 0x07) << 18)
|
||||||
|
| (trailingByteValue(byte2) << 12)
|
||||||
|
| (trailingByteValue(byte3) << 6)
|
||||||
|
| trailingByteValue(byte4);
|
||||||
|
resultArr[resultPos] = DecodeUtil.highSurrogate(codepoint);
|
||||||
|
resultArr[resultPos + 1] = DecodeUtil.lowSurrogate(codepoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the byte is not a valid continuation of the form '10XXXXXX'.
|
||||||
|
*/
|
||||||
|
private static boolean isNotTrailingByte(byte b) {
|
||||||
|
return b > (byte) 0xBF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the actual value of the trailing byte (removes the prefix '10') for composition.
|
||||||
|
*/
|
||||||
|
private static int trailingByteValue(byte b) {
|
||||||
|
return b & 0x3F;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static char highSurrogate(int codePoint) {
|
||||||
|
return (char) ((MIN_HIGH_SURROGATE - (MIN_SUPPLEMENTARY_CODE_POINT >>> 10))
|
||||||
|
+ (codePoint >>> 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static char lowSurrogate(int codePoint) {
|
||||||
|
return (char) (MIN_LOW_SURROGATE + (codePoint & 0x3ff));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// These UTF-8 handling methods are copied from Guava's Utf8Unsafe class with a modification to throw
|
||||||
|
// a protocol buffer local exception. This exception is then caught in CodedOutputStream so it can
|
||||||
|
// fallback to more lenient behavior.
|
||||||
|
static class UnpairedSurrogateException extends IllegalArgumentException {
|
||||||
|
UnpairedSurrogateException(int index, int length) {
|
||||||
|
super("Unpaired surrogate at index " + index + " of " + length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
99
java/com/google/flatbuffers/Utf8Old.java
Normal file
99
java/com/google/flatbuffers/Utf8Old.java
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2014 Google Inc. All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.google.flatbuffers;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.CharBuffer;
|
||||||
|
import java.nio.charset.CharacterCodingException;
|
||||||
|
import java.nio.charset.CharsetDecoder;
|
||||||
|
import java.nio.charset.CharsetEncoder;
|
||||||
|
import java.nio.charset.CoderResult;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class implements the Utf8 API using the Java Utf8 encoder. Use
|
||||||
|
* Utf8.setDefault(new Utf8Old()); to use it.
|
||||||
|
*/
|
||||||
|
public class Utf8Old extends Utf8 {
|
||||||
|
|
||||||
|
private static class Cache {
|
||||||
|
final CharsetEncoder encoder;
|
||||||
|
final CharsetDecoder decoder;
|
||||||
|
CharSequence lastInput = null;
|
||||||
|
ByteBuffer lastOutput = null;
|
||||||
|
|
||||||
|
Cache() {
|
||||||
|
encoder = StandardCharsets.UTF_8.newEncoder();
|
||||||
|
decoder = StandardCharsets.UTF_8.newDecoder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final ThreadLocal<Cache> CACHE =
|
||||||
|
ThreadLocal.withInitial(() -> new Cache());
|
||||||
|
|
||||||
|
// Play some games so that the old encoder doesn't pay twice for computing
|
||||||
|
// the length of the encoded string.
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int encodedLength(CharSequence in) {
|
||||||
|
final Cache cache = CACHE.get();
|
||||||
|
int estimated = (int) (in.length() * cache.encoder.maxBytesPerChar());
|
||||||
|
if (cache.lastOutput == null || cache.lastOutput.capacity() < estimated) {
|
||||||
|
cache.lastOutput = ByteBuffer.allocate(Math.max(128, estimated));
|
||||||
|
}
|
||||||
|
cache.lastOutput.clear();
|
||||||
|
cache.lastInput = in;
|
||||||
|
CharBuffer wrap = (in instanceof CharBuffer) ?
|
||||||
|
(CharBuffer) in : CharBuffer.wrap(in);
|
||||||
|
CoderResult result = cache.encoder.encode(wrap, cache.lastOutput, true);
|
||||||
|
if (result.isError()) {
|
||||||
|
try {
|
||||||
|
result.throwException();
|
||||||
|
} catch (CharacterCodingException e) {
|
||||||
|
throw new IllegalArgumentException("bad character encoding", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cache.lastOutput.remaining();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void encodeUtf8(CharSequence in, ByteBuffer out) {
|
||||||
|
final Cache cache = CACHE.get();
|
||||||
|
if (cache.lastInput != in) {
|
||||||
|
// Update the lastOutput to match our input, although flatbuffer should
|
||||||
|
// never take this branch.
|
||||||
|
encodedLength(in);
|
||||||
|
}
|
||||||
|
out.put(cache.lastOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String decodeUtf8(ByteBuffer buffer, int offset, int length) {
|
||||||
|
CharsetDecoder decoder = CACHE.get().decoder;
|
||||||
|
decoder.reset();
|
||||||
|
buffer = buffer.duplicate();
|
||||||
|
buffer.position(offset);
|
||||||
|
buffer.limit(offset + length);
|
||||||
|
try {
|
||||||
|
CharBuffer result = decoder.decode(buffer);
|
||||||
|
result.flip();
|
||||||
|
return result.toString();
|
||||||
|
} catch (CharacterCodingException e) {
|
||||||
|
throw new IllegalArgumentException("Bad encoding", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user