forked from BigfootDev/flatbuffers
Compare commits
417 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
697147a2e6 | ||
|
|
6df40a2471 | ||
|
|
0dba63909f | ||
|
|
0e3fdd0eea | ||
|
|
45a2b07cbd | ||
|
|
d10c163142 | ||
|
|
35abb7f89b | ||
|
|
9954e09ab7 | ||
|
|
95a21327fc | ||
|
|
89b6183ee9 | ||
|
|
5a98d65e86 | ||
|
|
f73d205bc7 | ||
|
|
7c37abe92d | ||
|
|
4749e77b0e | ||
|
|
6ff1898413 | ||
|
|
c9a30c9ca2 | ||
|
|
8c02d17bea | ||
|
|
34305c4ce4 | ||
|
|
cd88e6b2aa | ||
|
|
3ec7a53c62 | ||
|
|
6d44cede70 | ||
|
|
cc08c0835b | ||
|
|
54f8b787cb | ||
|
|
17557f9131 | ||
|
|
d54af8cd43 | ||
|
|
173e10fdf1 | ||
|
|
8f56990f6c | ||
|
|
6400c9b054 | ||
|
|
7418d85872 | ||
|
|
c580fa284c | ||
|
|
f2a1272303 | ||
|
|
316d7c2089 | ||
|
|
47026ea6ba | ||
|
|
3f677f2414 | ||
|
|
a593a11e59 | ||
|
|
7cdfc8475e | ||
|
|
bab2b0db48 | ||
|
|
89418eb848 | ||
|
|
9cadf05d89 | ||
|
|
6da1cf79d9 | ||
|
|
bee1df96dc | ||
|
|
01189d7edd | ||
|
|
c4b2b0a25d | ||
|
|
a4b2884e4e | ||
|
|
04d80f255d | ||
|
|
55686100aa | ||
|
|
718351831d | ||
|
|
d1b34f0f28 | ||
|
|
21b7061963 | ||
|
|
35daaf83d3 | ||
|
|
3b458f7a17 | ||
|
|
a5d9d0f7d3 | ||
|
|
3cd9b6434a | ||
|
|
355dfd48d1 | ||
|
|
bcd58a159b | ||
|
|
a2c12900aa | ||
|
|
901b89e733 | ||
|
|
31f8799083 | ||
|
|
8023d99e21 | ||
|
|
b4154405d1 | ||
|
|
04c17c7a76 | ||
|
|
62ec7d52ce | ||
|
|
7de668053f | ||
|
|
3a70e0b308 | ||
|
|
9b13201356 | ||
|
|
5e3916050c | ||
|
|
c957550511 | ||
|
|
44bf719883 | ||
|
|
3e8f15df90 | ||
|
|
602721a735 | ||
|
|
13c05f4da3 | ||
|
|
ce3a1c43a2 | ||
|
|
aa75e5734b | ||
|
|
2790fee257 | ||
|
|
eddebec1b6 | ||
|
|
030fee36ab | ||
|
|
f9724d1bde | ||
|
|
b20801ca40 | ||
|
|
a8e800bd7c | ||
|
|
d7530ae961 | ||
|
|
99d11e279f | ||
|
|
4fd8eb214b | ||
|
|
65f8703572 | ||
|
|
75823cc275 | ||
|
|
58e279244c | ||
|
|
3c964e10ab | ||
|
|
c3c32ec942 | ||
|
|
075e8d676b | ||
|
|
bcf1bd5c9e | ||
|
|
136d75fa65 | ||
|
|
091fa1fd1b | ||
|
|
ff3781dc2d | ||
|
|
6beb9f49cb | ||
|
|
80988ea869 | ||
|
|
0f2ff7eaa9 | ||
|
|
dda095023d | ||
|
|
adbcbba5d1 | ||
|
|
cbbd6aca04 | ||
|
|
405c64e07d | ||
|
|
42c08cbca6 | ||
|
|
33d5dd9bdd | ||
|
|
105dd528e9 | ||
|
|
f0f0efe7b8 | ||
|
|
e837d5a296 | ||
|
|
9834ee9787 | ||
|
|
44b2ab087c | ||
|
|
46ae3f80a6 | ||
|
|
7b38aa71e6 | ||
|
|
661bedd837 | ||
|
|
8526e12d73 | ||
|
|
3c7b660d62 | ||
|
|
964365ba69 | ||
|
|
32254b7acd | ||
|
|
521e255ad9 | ||
|
|
1b85292fd3 | ||
|
|
480815447a | ||
|
|
8d5e424c65 | ||
|
|
b4774d2354 | ||
|
|
26f238c248 | ||
|
|
e93c8c46e6 | ||
|
|
e21516b9d7 | ||
|
|
fbc11e8aec | ||
|
|
e9d29c21a7 | ||
|
|
8bfafc76de | ||
|
|
df3e8bf4a7 | ||
|
|
5665cfe492 | ||
|
|
5797540ed0 | ||
|
|
7f1af7cb02 | ||
|
|
32f47ad247 | ||
|
|
842f672baf | ||
|
|
d4cae0a623 | ||
|
|
f1147f65bb | ||
|
|
69d3fec488 | ||
|
|
cfb4ecf6f0 | ||
|
|
a92039687a | ||
|
|
625338d095 | ||
|
|
3f8ce99c50 | ||
|
|
0798b7b698 | ||
|
|
cbdf82e2fb | ||
|
|
e365c502ff | ||
|
|
97f3aa9174 | ||
|
|
2f5bb2eec4 | ||
|
|
917687c7a6 | ||
|
|
f9277e691d | ||
|
|
2706381eef | ||
|
|
b5560fcd52 | ||
|
|
782b865c55 | ||
|
|
3bfc86eaff | ||
|
|
c0282873fb | ||
|
|
4b870aca98 | ||
|
|
d0e3870c0f | ||
|
|
fb25eb87f2 | ||
|
|
cb35d3a0e5 | ||
|
|
8e6cabb31b | ||
|
|
bd31dd2425 | ||
|
|
65b67d2132 | ||
|
|
1fbb711324 | ||
|
|
cd75a36587 | ||
|
|
ec6b0bf297 | ||
|
|
c11b5d7447 | ||
|
|
4525c91be3 | ||
|
|
b97b342f59 | ||
|
|
c1058a903b | ||
|
|
3030449348 | ||
|
|
a2485d4ecc | ||
|
|
a20e71ac96 | ||
|
|
acc9990abd | ||
|
|
2d5315ff0e | ||
|
|
7de1a5e347 | ||
|
|
a4e3ad808e | ||
|
|
c953fa572b | ||
|
|
0c86085a5b | ||
|
|
a1f7ecd148 | ||
|
|
a20c55bea5 | ||
|
|
d7c2b388ef | ||
|
|
9fa8245e81 | ||
|
|
a5ca8bee4d | ||
|
|
09dea79a22 | ||
|
|
b632061eff | ||
|
|
da88be05e1 | ||
|
|
d4fa984f1d | ||
|
|
a0c0131e36 | ||
|
|
de9aa0cdee | ||
|
|
a752d1b88c | ||
|
|
db972be264 | ||
|
|
e304f8c115 | ||
|
|
47c7aa0361 | ||
|
|
7a63792929 | ||
|
|
7d7d796cd0 | ||
|
|
550b386995 | ||
|
|
5479adc80f | ||
|
|
b7012484f3 | ||
|
|
92e9f33036 | ||
|
|
ff1a22a05f | ||
|
|
9fb195cce8 | ||
|
|
7836e65dd4 | ||
|
|
123c7a4890 | ||
|
|
e635141d5b | ||
|
|
0d2cebccfe | ||
|
|
a80db8538c | ||
|
|
a6be1d0d74 | ||
|
|
a7e20b1996 | ||
|
|
4eb3efc221 | ||
|
|
a807fa9567 | ||
|
|
b80ad7e439 | ||
|
|
16aef8ac0d | ||
|
|
b59a1ca2f8 | ||
|
|
4fdfe0d468 | ||
|
|
95004218f7 | ||
|
|
bc7ede8fb3 | ||
|
|
b652fcc3a7 | ||
|
|
c978b9ef1f | ||
|
|
3a88e1031b | ||
|
|
51dd733ba4 | ||
|
|
79f0df3dfc | ||
|
|
9d92fd92e1 | ||
|
|
93f74c0363 | ||
|
|
43dbac5d25 | ||
|
|
53ea1ab1bd | ||
|
|
b10b050ab9 | ||
|
|
563dcd6893 | ||
|
|
30ac512a54 | ||
|
|
b04736f9bd | ||
|
|
bc240b3004 | ||
|
|
0f7e7fd209 | ||
|
|
766ed04422 | ||
|
|
c5e2d37337 | ||
|
|
fe83b68ac6 | ||
|
|
718ddea558 | ||
|
|
8d86b5347f | ||
|
|
39bd667fd0 | ||
|
|
0bb3ce6935 | ||
|
|
b56d60f058 | ||
|
|
bff7ffbc51 | ||
|
|
107c08988a | ||
|
|
f9ebfcb9c4 | ||
|
|
b701c7d56e | ||
|
|
103f61b685 | ||
|
|
e47ca7ab40 | ||
|
|
d79f4e9717 | ||
|
|
5d67693e8f | ||
|
|
af74f87ccd | ||
|
|
b8ef8c1521 | ||
|
|
6cc30b3272 | ||
|
|
e5b6125fa2 | ||
|
|
ac14c8906f | ||
|
|
9936adf473 | ||
|
|
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 |
41
.appveyor/check-generate-code.bat
Normal file
41
.appveyor/check-generate-code.bat
Normal file
@@ -0,0 +1,41 @@
|
||||
:: 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 checkout HEAD -- arrays_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
|
||||
[*.{cpp,cc,h}]
|
||||
end_of_line = LF
|
||||
# Don't set line endings to avoid conflict with core.autocrlf flag.
|
||||
# Line endings on checkout/checkin are controlled by .gitattributes file.
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
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
|
||||
|
||||
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
6
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,6 +1,8 @@
|
||||
Thank you for submitting a PR!
|
||||
|
||||
Please make sure you include the names of the affected language(s) in your PR title.
|
||||
Please delete this standard text once you've created your own description.
|
||||
|
||||
Make sure you include the names of the affected language(s) in your PR title.
|
||||
This helps us get the correct maintainers to look at your issue.
|
||||
|
||||
If you make changes to any of the code generators, be sure to run
|
||||
@@ -11,6 +13,8 @@ If your PR includes C++ code, please adhere to the Google C++ Style Guide,
|
||||
and don't forget we try to support older compilers (e.g. VS2010, GCC 4.6.3),
|
||||
so only some C++11 support is available.
|
||||
|
||||
For any C++ changes, please make sure to run `sh src/clang-format-git.sh`
|
||||
|
||||
Include other details as appropriate.
|
||||
|
||||
Thanks!
|
||||
|
||||
18
.github/stale.yml
vendored
Normal file
18
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 365
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 14
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
activity for 1 year. It will be automatically closed if no further activity occurs.
|
||||
To keep it open, simply post a new comment. Maintainers will re-open on
|
||||
new activity. Thank you for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: false
|
||||
16
.gitignore
vendored
16
.gitignore
vendored
@@ -1,6 +1,12 @@
|
||||
*_wire.txt
|
||||
*_wire.bin
|
||||
.DS_Store
|
||||
**/.build
|
||||
**/Packages
|
||||
/*.xcodeproj
|
||||
**/xcuserdata/
|
||||
**/xcshareddata/
|
||||
**/.swiftpm/
|
||||
*.o
|
||||
*.o.d
|
||||
*.class
|
||||
@@ -26,6 +32,9 @@
|
||||
**/install_manifest.txt
|
||||
**/CMakeCache.txt
|
||||
**/CMakeTestfile.cmake
|
||||
**/CPackConfig.cmake
|
||||
**/CPackSourceConfig.cmake
|
||||
**/compile_commands.json
|
||||
**/Debug/**
|
||||
**/Release/**
|
||||
**/RelWithDebInfo/**
|
||||
@@ -46,6 +55,8 @@ flatsamplebinary
|
||||
flatsamplebinary.exe
|
||||
flatsampletext
|
||||
flatsampletext.exe
|
||||
flatsamplebfbs
|
||||
flatsamplebfbs.exe
|
||||
grpctest
|
||||
grpctest.exe
|
||||
snapshot.sh
|
||||
@@ -109,3 +120,8 @@ dart/.dart_tool/
|
||||
dart/build/
|
||||
dart/doc/api/
|
||||
Cargo.lock
|
||||
.corpus**
|
||||
.seed**
|
||||
grpc/google/
|
||||
**/Package.resolved
|
||||
.clangd/**
|
||||
|
||||
161
.travis.yml
161
.travis.yml
@@ -2,12 +2,18 @@ env:
|
||||
global:
|
||||
# Set at the root level as this is ignored when set under matrix.env.
|
||||
- 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
|
||||
sudo: required
|
||||
dist: xenial
|
||||
language: python
|
||||
python: "3.6"
|
||||
python: "3.7"
|
||||
services:
|
||||
- docker
|
||||
install:
|
||||
@@ -16,6 +22,21 @@ conan-linux: &conan-linux
|
||||
- ./conan/travis/build.sh
|
||||
if: tag IS present
|
||||
|
||||
conan-linux-master: &conan-linux-master
|
||||
os: linux
|
||||
dist: xenial
|
||||
language: python
|
||||
python: "3.7"
|
||||
services:
|
||||
- docker
|
||||
install:
|
||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./conan/travis/install.sh; fi'
|
||||
script:
|
||||
- 'if [ "$TRAVIS_PULL_REQUEST" = "false" ]; then bash ./conan/travis/build.sh; fi'
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
conan-osx: &conan-osx
|
||||
os: osx
|
||||
language: generic
|
||||
@@ -53,7 +74,18 @@ matrix:
|
||||
# branch: master
|
||||
- language: cpp
|
||||
os:
|
||||
- linux
|
||||
- linux
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- docker-ce
|
||||
script:
|
||||
- bash .travis/build-and-run-docker-test-containers.sh
|
||||
|
||||
- language: cpp
|
||||
os:
|
||||
- linux
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
@@ -61,7 +93,7 @@ matrix:
|
||||
env:
|
||||
matrix:
|
||||
- BUILD_TYPE=Debug
|
||||
- BUILD_TYPE=Release CONAN=true
|
||||
- BUILD_TYPE=Release
|
||||
|
||||
before_install:
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
|
||||
@@ -72,10 +104,17 @@ matrix:
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
|
||||
|
||||
script:
|
||||
- bash .travis/check-sources.sh
|
||||
- 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 . && make
|
||||
- LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/google/grpc/install/lib make test ARGS=-V
|
||||
- if [ "$CONAN" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo pip install conan && conan create . google/testing -s build_type=$BUILD_TYPE -tf conan/test_package; 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 . --target all --clean-first -- -j${JOBS}
|
||||
- LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/google/grpc/install/lib ctest --extra-verbose --output-on-failure
|
||||
- bash .travis/check-generate-code.sh
|
||||
|
||||
- language: cpp
|
||||
os: osx
|
||||
@@ -84,30 +123,45 @@ matrix:
|
||||
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 . && make
|
||||
- ./flattests
|
||||
- DYLD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/google/grpc/install/lib ./grpctest
|
||||
- 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-master
|
||||
env: CONAN_GCC_VERSIONS=8 CONAN_DOCKER_IMAGE=conanio/gcc8
|
||||
- <<: *conan-linux
|
||||
env: CONAN_GCC_VERSIONS=4.9 CONAN_DOCKER_IMAGE=lasote/conangcc49
|
||||
env: CONAN_GCC_VERSIONS=4.9 CONAN_DOCKER_IMAGE=conanio/gcc49
|
||||
- <<: *conan-linux
|
||||
env: CONAN_GCC_VERSIONS=5 CONAN_DOCKER_IMAGE=lasote/conangcc5
|
||||
env: CONAN_GCC_VERSIONS=5 CONAN_DOCKER_IMAGE=conanio/gcc5
|
||||
- <<: *conan-linux
|
||||
env: CONAN_GCC_VERSIONS=6 CONAN_DOCKER_IMAGE=lasote/conangcc6
|
||||
env: CONAN_GCC_VERSIONS=6 CONAN_DOCKER_IMAGE=conanio/gcc6
|
||||
- <<: *conan-linux
|
||||
env: CONAN_GCC_VERSIONS=7 CONAN_DOCKER_IMAGE=lasote/conangcc7
|
||||
env: CONAN_GCC_VERSIONS=7 CONAN_DOCKER_IMAGE=conanio/gcc7
|
||||
- <<: *conan-linux
|
||||
env: CONAN_GCC_VERSIONS=8 CONAN_DOCKER_IMAGE=lasote/conangcc8
|
||||
env: CONAN_GCC_VERSIONS=8 CONAN_DOCKER_IMAGE=conanio/gcc8
|
||||
- <<: *conan-linux
|
||||
env: CONAN_CLANG_VERSIONS=3.9 CONAN_DOCKER_IMAGE=lasote/conanclang39
|
||||
env: CONAN_GCC_VERSIONS=9 CONAN_DOCKER_IMAGE=conanio/gcc9
|
||||
- <<: *conan-linux
|
||||
env: CONAN_CLANG_VERSIONS=4.0 CONAN_DOCKER_IMAGE=lasote/conanclang40
|
||||
env: CONAN_CLANG_VERSIONS=3.9 CONAN_DOCKER_IMAGE=conanio/clang39
|
||||
- <<: *conan-linux
|
||||
env: CONAN_CLANG_VERSIONS=5.0 CONAN_DOCKER_IMAGE=lasote/conanclang50
|
||||
env: CONAN_CLANG_VERSIONS=4.0 CONAN_DOCKER_IMAGE=conanio/clang40
|
||||
- <<: *conan-linux
|
||||
env: CONAN_CLANG_VERSIONS=6.0 CONAN_DOCKER_IMAGE=lasote/conanclang60
|
||||
env: CONAN_CLANG_VERSIONS=5.0 CONAN_DOCKER_IMAGE=conanio/clang50
|
||||
- <<: *conan-linux
|
||||
env: CONAN_CLANG_VERSIONS=6.0 CONAN_DOCKER_IMAGE=conanio/clang60
|
||||
- <<: *conan-linux
|
||||
env: CONAN_CLANG_VERSIONS=7.0 CONAN_DOCKER_IMAGE=conanio/clang7
|
||||
- <<: *conan-linux
|
||||
env: CONAN_CLANG_VERSIONS=8 CONAN_DOCKER_IMAGE=conanio/clang8
|
||||
- <<: *conan-osx
|
||||
osx_image: xcode7.3
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=7.3
|
||||
@@ -118,29 +172,50 @@ matrix:
|
||||
osx_image: xcode9
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=9.0
|
||||
- <<: *conan-osx
|
||||
osx_image: xcode9.3
|
||||
osx_image: xcode9.4
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=9.1
|
||||
- <<: *conan-osx
|
||||
osx_image: xcode10.2
|
||||
env: CONAN_APPLE_CLANG_VERSIONS=10.0
|
||||
|
||||
#- language: android
|
||||
# sudo: true
|
||||
# android:
|
||||
# components:
|
||||
# - tools
|
||||
# - platform-tools
|
||||
# - build-tools-25.0.2
|
||||
# - android-25
|
||||
# - extra-android-m2repository
|
||||
# compiler:
|
||||
# - gcc
|
||||
# before_install:
|
||||
# - git clone https://github.com/urho3d/android-ndk.git $HOME/android-ndk-root
|
||||
# - export ANDROID_NDK_HOME=$HOME/android-ndk-root
|
||||
# # Setup environment for Linux build which is required to build the sample.
|
||||
# - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
|
||||
# - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi
|
||||
# - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq g++-$GCC_VERSION; fi
|
||||
# - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq gcc-$GCC_VERSION; fi
|
||||
# - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which g++-$GCC_VERSION) /usr/bin/g++; fi
|
||||
# - if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
|
||||
# script:
|
||||
# - failed=0; for build_gradle in $(git ls-files | grep build.gradle); do ( cd "$(dirname "${build_gradle}")" && ./gradlew build ) || failed=1; done; exit $((failed))
|
||||
- language: android
|
||||
sudo: true
|
||||
dist: trusty
|
||||
android:
|
||||
components:
|
||||
- tools
|
||||
- platform-tools
|
||||
- build-tools-25.0.2
|
||||
- android-25
|
||||
- extra-android-m2repository
|
||||
compiler:
|
||||
- gcc
|
||||
|
||||
before_install:
|
||||
# Output something every 10 minutes or Travis kills the job
|
||||
- while sleep 540; do echo "=====[ $SECONDS seconds still running ]====="; done &
|
||||
# Install the r17c version of the NDK that still so that we can continue to test with gnustl
|
||||
# and stlport.
|
||||
- export ANDROID_NDK_HOME=$HOME/android-ndk
|
||||
- NDK_ZIP=$ANDROID_NDK_HOME/ndk.zip
|
||||
- mkdir -p $ANDROID_NDK_HOME
|
||||
- curl -o $NDK_ZIP https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip
|
||||
- unzip -q -d $ANDROID_NDK_HOME $NDK_ZIP
|
||||
- rm $NDK_ZIP
|
||||
- mv $ANDROID_NDK_HOME/android-ndk-*/* $ANDROID_NDK_HOME
|
||||
- rmdir $ANDROID_NDK_HOME/android-ndk-*
|
||||
- export CMAKE=$(which cmake)
|
||||
# libc required for prebuilt llvm toolchain the NDK r17c.
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq libc6; fi
|
||||
# Setup environment for Linux build which is required to build the sample.
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq g++-$GCC_VERSION; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq gcc-$GCC_VERSION; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which g++-$GCC_VERSION) /usr/bin/g++; fi
|
||||
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
|
||||
script:
|
||||
- failed=0; for build_gradle in $(git ls-files | grep build.gradle); do ( cd "$(dirname "${build_gradle}")" && ./gradlew build ) || failed=1; done; exit $((failed))
|
||||
# Kill the sleep loop
|
||||
- kill %1
|
||||
|
||||
45
.travis/build-and-run-docker-test-containers.sh
Executable file
45
.travis/build-and-run-docker-test-containers.sh
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/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
|
||||
|
||||
docker build -t build_cpp_image -f tests/docker/Dockerfile.testing.cpp.debian_buster .
|
||||
# Run tests with sanitizers (--cap-add SYS_PTRACE), both GCC and Clang.
|
||||
cpp_test_args="--cap-add SYS_PTRACE build_cpp_image sh ./tests/docker/cpp_test.run.sh Debug"
|
||||
docker run --rm $cpp_test_args
|
||||
docker run --rm --env CC=/usr/bin/clang --env CXX=/usr/bin/clang++ $cpp_test_args
|
||||
# Build flatc on debian once to speed up the test loop below.
|
||||
docker run --name flatc_container build_cpp_image sh ./tests/docker/build_flatc.run.sh Debug
|
||||
# All dependent dockers refer to 'flatc_debian_stretch'.
|
||||
docker cp flatc_container:/flatbuffers/flatc flatc_debian_stretch
|
||||
|
||||
for f in $(ls tests/docker/languages | sort)
|
||||
do
|
||||
# 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
|
||||
36
.travis/check-generate-code.sh
Executable file
36
.travis/check-generate-code.sh
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/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
|
||||
git checkout HEAD -- tests/arrays_test.bfbs
|
||||
git checkout HEAD -- samples/monster.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)
|
||||
126
BUILD
126
BUILD
@@ -1,11 +1,9 @@
|
||||
licenses(["notice"])
|
||||
|
||||
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")
|
||||
|
||||
package(
|
||||
default_visibility = ["//visibility:public"],
|
||||
features = [
|
||||
"-layering_check",
|
||||
"-parse_headers",
|
||||
],
|
||||
)
|
||||
|
||||
exports_files([
|
||||
@@ -15,18 +13,10 @@ exports_files([
|
||||
# Public flatc library to compile flatbuffer files at runtime.
|
||||
cc_library(
|
||||
name = "flatbuffers",
|
||||
srcs = [
|
||||
"src/code_generators.cpp",
|
||||
"src/idl_gen_fbs.cpp",
|
||||
"src/idl_gen_general.cpp",
|
||||
"src/idl_gen_text.cpp",
|
||||
"src/idl_parser.cpp",
|
||||
"src/reflection.cpp",
|
||||
"src/util.cpp",
|
||||
],
|
||||
hdrs = [":public_headers"],
|
||||
includes = ["include/"],
|
||||
hdrs = ["//:public_headers"],
|
||||
linkstatic = 1,
|
||||
strip_include_prefix = "/include",
|
||||
deps = ["//src:flatbuffers"],
|
||||
)
|
||||
|
||||
# Public C++ headers for the Flatbuffers library.
|
||||
@@ -42,6 +32,7 @@ filegroup(
|
||||
"include/flatbuffers/minireflect.h",
|
||||
"include/flatbuffers/reflection.h",
|
||||
"include/flatbuffers/reflection_generated.h",
|
||||
"include/flatbuffers/registry.h",
|
||||
"include/flatbuffers/stl_emulation.h",
|
||||
"include/flatbuffers/util.h",
|
||||
],
|
||||
@@ -50,99 +41,38 @@ filegroup(
|
||||
# Public flatc compiler library.
|
||||
cc_library(
|
||||
name = "flatc_library",
|
||||
srcs = [
|
||||
"src/code_generators.cpp",
|
||||
"src/flatc.cpp",
|
||||
"src/idl_gen_fbs.cpp",
|
||||
"src/idl_parser.cpp",
|
||||
"src/reflection.cpp",
|
||||
"src/util.cpp",
|
||||
],
|
||||
hdrs = [
|
||||
"include/flatbuffers/flatc.h",
|
||||
":public_headers",
|
||||
],
|
||||
includes = [
|
||||
"grpc/",
|
||||
"include/",
|
||||
linkstatic = 1,
|
||||
deps = [
|
||||
"//src:flatc_library",
|
||||
],
|
||||
)
|
||||
|
||||
# Public flatc compiler.
|
||||
cc_binary(
|
||||
name = "flatc",
|
||||
srcs = [
|
||||
"grpc/src/compiler/config.h",
|
||||
"grpc/src/compiler/cpp_generator.cc",
|
||||
"grpc/src/compiler/cpp_generator.h",
|
||||
"grpc/src/compiler/go_generator.cc",
|
||||
"grpc/src/compiler/go_generator.h",
|
||||
"grpc/src/compiler/java_generator.cc",
|
||||
"grpc/src/compiler/java_generator.h",
|
||||
"grpc/src/compiler/schema_interface.h",
|
||||
"src/flatc_main.cpp",
|
||||
"src/idl_gen_cpp.cpp",
|
||||
"src/idl_gen_dart.cpp",
|
||||
"src/idl_gen_general.cpp",
|
||||
"src/idl_gen_go.cpp",
|
||||
"src/idl_gen_grpc.cpp",
|
||||
"src/idl_gen_js.cpp",
|
||||
"src/idl_gen_json_schema.cpp",
|
||||
"src/idl_gen_lua.cpp",
|
||||
"src/idl_gen_lobster.cpp",
|
||||
"src/idl_gen_php.cpp",
|
||||
"src/idl_gen_python.cpp",
|
||||
"src/idl_gen_rust.cpp",
|
||||
"src/idl_gen_text.cpp",
|
||||
],
|
||||
includes = [
|
||||
"grpc/",
|
||||
"include/",
|
||||
],
|
||||
deps = [
|
||||
":flatc_library",
|
||||
"//src:flatc",
|
||||
],
|
||||
)
|
||||
|
||||
# Test binary.
|
||||
cc_test(
|
||||
name = "flatbuffers_test",
|
||||
testonly = 1,
|
||||
filegroup(
|
||||
name = "flatc_headers",
|
||||
srcs = [
|
||||
"include/flatbuffers/minireflect.h",
|
||||
"include/flatbuffers/registry.h",
|
||||
"src/code_generators.cpp",
|
||||
"src/idl_gen_fbs.cpp",
|
||||
"src/idl_gen_general.cpp",
|
||||
"src/idl_gen_text.cpp",
|
||||
"src/idl_parser.cpp",
|
||||
"src/reflection.cpp",
|
||||
"src/util.cpp",
|
||||
"tests/monster_test_generated.h",
|
||||
"tests/namespace_test/namespace_test1_generated.h",
|
||||
"tests/namespace_test/namespace_test2_generated.h",
|
||||
"tests/test.cpp",
|
||||
"tests/test_builder.h",
|
||||
"tests/test_assert.h",
|
||||
"tests/test_builder.cpp",
|
||||
"tests/test_assert.cpp",
|
||||
"tests/union_vector/union_vector_generated.h",
|
||||
":public_headers",
|
||||
"include/flatbuffers/flatc.h",
|
||||
],
|
||||
copts = [
|
||||
"-DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE",
|
||||
],
|
||||
data = [
|
||||
":tests/include_test/include_test1.fbs",
|
||||
":tests/include_test/sub/include_test2.fbs",
|
||||
":tests/monster_test.bfbs",
|
||||
":tests/monster_test.fbs",
|
||||
":tests/monsterdata_test.golden",
|
||||
":tests/prototest/imported.proto",
|
||||
":tests/prototest/test.golden",
|
||||
":tests/prototest/test.proto",
|
||||
":tests/prototest/test_union.golden",
|
||||
":tests/union_vector/union_vector.fbs",
|
||||
],
|
||||
includes = ["include/"],
|
||||
visibility = ["//:__subpackages__"],
|
||||
)
|
||||
|
||||
# Library used by flatbuffer_cc_library rules.
|
||||
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",
|
||||
],
|
||||
linkstatic = 1,
|
||||
strip_include_prefix = "/include",
|
||||
)
|
||||
|
||||
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}
|
||||
COMMAND ${FLATBUFFERS_FLATC_EXECUTABLE}
|
||||
ARGS -c -o "${CMAKE_CURRENT_BINARY_DIR}/" ${FILE}
|
||||
DEPENDS ${FILE}
|
||||
COMMENT "Building C++ header for ${FILE}"
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
endforeach()
|
||||
|
||||
@@ -37,5 +37,3 @@ if (UNIX)
|
||||
"${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
|
||||
|
||||
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)
|
||||
298
CMakeLists.txt
298
CMakeLists.txt
@@ -1,4 +1,7 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
cmake_minimum_required(VERSION 2.8.12)
|
||||
# generate compile_commands.json
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
include(CheckCXXSymbolExists)
|
||||
|
||||
project(FlatBuffers)
|
||||
|
||||
@@ -10,12 +13,31 @@ option(FLATBUFFERS_BUILD_FLATLIB "Enable the build of the flatbuffers library"
|
||||
ON)
|
||||
option(FLATBUFFERS_BUILD_FLATC "Enable the build of the flatbuffers compiler"
|
||||
ON)
|
||||
option(FLATBUFFERS_STATIC_FLATC "Build flatbuffers compiler with -static flag"
|
||||
OFF)
|
||||
option(FLATBUFFERS_BUILD_FLATHASH "Enable the build of flathash" ON)
|
||||
option(FLATBUFFERS_BUILD_GRPCTEST "Enable the build of grpctest" OFF)
|
||||
option(FLATBUFFERS_BUILD_SHAREDLIB
|
||||
"Enable the build of the flatbuffers shared library"
|
||||
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)
|
||||
option(FLATBUFFERS_BUILD_CPP17
|
||||
"Enable the build of c++17 test target. \"
|
||||
Requirements: Clang6, GCC7, MSVC2017 (_MSC_VER >= 1914) or higher."
|
||||
OFF)
|
||||
option(FLATBUFFERS_BUILD_LEGACY
|
||||
"Run C++ code generator with '--cpp-std c++0x' switch."
|
||||
OFF)
|
||||
|
||||
if(NOT FLATBUFFERS_BUILD_FLATC AND FLATBUFFERS_BUILD_TESTS)
|
||||
message(WARNING
|
||||
@@ -23,8 +45,29 @@ if(NOT FLATBUFFERS_BUILD_FLATC AND FLATBUFFERS_BUILD_TESTS)
|
||||
set(FLATBUFFERS_BUILD_TESTS OFF)
|
||||
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' and 'strtoull_l' functions.
|
||||
if(NOT DEFINED FLATBUFFERS_LOCALE_INDEPENDENT)
|
||||
set(FLATBUFFERS_LOCALE_INDEPENDENT 0)
|
||||
if(MSVC)
|
||||
check_cxx_symbol_exists(_strtof_l stdlib.h FLATBUFFERS_HAS_STRTOF_L)
|
||||
check_cxx_symbol_exists(_strtoui64_l stdlib.h FLATBUFFERS_HAS_STRTOULL_L)
|
||||
else()
|
||||
check_cxx_symbol_exists(strtof_l stdlib.h FLATBUFFERS_HAS_STRTOF_L)
|
||||
check_cxx_symbol_exists(strtoull_l stdlib.h FLATBUFFERS_HAS_STRTOULL_L)
|
||||
endif()
|
||||
if(FLATBUFFERS_HAS_STRTOF_L AND FLATBUFFERS_HAS_STRTOULL_L)
|
||||
set(FLATBUFFERS_LOCALE_INDEPENDENT 1)
|
||||
endif()
|
||||
endif()
|
||||
add_definitions(-DFLATBUFFERS_LOCALE_INDEPENDENT=$<BOOL:${FLATBUFFERS_LOCALE_INDEPENDENT}>)
|
||||
|
||||
set(FlatBuffers_Library_SRCS
|
||||
include/flatbuffers/code_generators.h
|
||||
include/flatbuffers/base.h
|
||||
include/flatbuffers/flatbuffers.h
|
||||
include/flatbuffers/hash.h
|
||||
@@ -36,7 +79,6 @@ set(FlatBuffers_Library_SRCS
|
||||
include/flatbuffers/flexbuffers.h
|
||||
include/flatbuffers/registry.h
|
||||
include/flatbuffers/minireflect.h
|
||||
src/code_generators.cpp
|
||||
src/idl_parser.cpp
|
||||
src/idl_gen_text.cpp
|
||||
src/reflection.cpp
|
||||
@@ -46,10 +88,12 @@ set(FlatBuffers_Library_SRCS
|
||||
set(FlatBuffers_Compiler_SRCS
|
||||
${FlatBuffers_Library_SRCS}
|
||||
src/idl_gen_cpp.cpp
|
||||
src/idl_gen_csharp.cpp
|
||||
src/idl_gen_dart.cpp
|
||||
src/idl_gen_general.cpp
|
||||
src/idl_gen_kotlin.cpp
|
||||
src/idl_gen_go.cpp
|
||||
src/idl_gen_js.cpp
|
||||
src/idl_gen_java.cpp
|
||||
src/idl_gen_js_ts.cpp
|
||||
src/idl_gen_php.cpp
|
||||
src/idl_gen_python.cpp
|
||||
src/idl_gen_lobster.cpp
|
||||
@@ -58,8 +102,11 @@ set(FlatBuffers_Compiler_SRCS
|
||||
src/idl_gen_fbs.cpp
|
||||
src/idl_gen_grpc.cpp
|
||||
src/idl_gen_json_schema.cpp
|
||||
src/idl_gen_swift.cpp
|
||||
src/flatc.cpp
|
||||
src/flatc_main.cpp
|
||||
include/flatbuffers/code_generators.h
|
||||
src/code_generators.cpp
|
||||
grpc/src/compiler/schema_interface.h
|
||||
grpc/src/compiler/cpp_generator.h
|
||||
grpc/src/compiler/cpp_generator.cc
|
||||
@@ -67,6 +114,11 @@ set(FlatBuffers_Compiler_SRCS
|
||||
grpc/src/compiler/go_generator.cc
|
||||
grpc/src/compiler/java_generator.h
|
||||
grpc/src/compiler/java_generator.cc
|
||||
grpc/src/compiler/python_generator.h
|
||||
grpc/src/compiler/python_private_generator.h
|
||||
grpc/src/compiler/python_generator.cc
|
||||
grpc/src/compiler/swift_generator.h
|
||||
grpc/src/compiler/swift_generator.cc
|
||||
)
|
||||
|
||||
set(FlatHash_SRCS
|
||||
@@ -82,8 +134,35 @@ set(FlatBuffers_Tests_SRCS
|
||||
tests/test_assert.cpp
|
||||
tests/test_builder.h
|
||||
tests/test_builder.cpp
|
||||
tests/native_type_test_impl.h
|
||||
tests/native_type_test_impl.cpp
|
||||
include/flatbuffers/code_generators.h
|
||||
src/code_generators.cpp
|
||||
# file generate by running compiler on tests/monster_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h
|
||||
# file generate by running compiler on namespace_test/namespace_test1.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/namespace_test/namespace_test1_generated.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/namespace_test/namespace_test2_generated.h
|
||||
# file generate by running compiler on union_vector/union_vector.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/union_vector/union_vector_generated.h
|
||||
# file generate by running compiler on tests/arrays_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/arrays_test_generated.h
|
||||
# file generate by running compiler on tests/native_type_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/native_type_test_generated.h
|
||||
# file generate by running compiler on tests/monster_extra.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_extra_generated.h
|
||||
# file generate by running compiler on tests/monster_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_bfbs_generated.h
|
||||
)
|
||||
|
||||
set(FlatBuffers_Tests_CPP17_SRCS
|
||||
${FlatBuffers_Library_SRCS}
|
||||
tests/test_assert.h
|
||||
tests/test_assert.cpp
|
||||
tests/cpp17/test_cpp17.cpp
|
||||
# file generate by running compiler on tests/monster_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/cpp17/generated_cpp17/monster_test_generated.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h
|
||||
)
|
||||
|
||||
set(FlatBuffers_Sample_Binary_SRCS
|
||||
@@ -100,9 +179,18 @@ set(FlatBuffers_Sample_Text_SRCS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
|
||||
)
|
||||
|
||||
set(FlatBuffers_Sample_BFBS_SRCS
|
||||
${FlatBuffers_Library_SRCS}
|
||||
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
|
||||
include/flatbuffers/flatbuffers.h
|
||||
include/flatbuffers/grpc.h
|
||||
include/flatbuffers/util.h
|
||||
src/util.cpp
|
||||
tests/monster_test.grpc.fb.h
|
||||
tests/test_assert.h
|
||||
tests/test_builder.h
|
||||
@@ -111,8 +199,8 @@ set(FlatBuffers_GRPCTest_SRCS
|
||||
tests/test_builder.cpp
|
||||
grpc/tests/grpctest.cpp
|
||||
grpc/tests/message_builder_test.cpp
|
||||
# file generated by running compiler on samples/monster.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
|
||||
# file generate by running compiler on tests/monster_test.fbs
|
||||
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h
|
||||
)
|
||||
|
||||
# source_group(Compiler FILES ${FlatBuffers_Compiler_SRCS})
|
||||
@@ -121,9 +209,11 @@ set(FlatBuffers_GRPCTest_SRCS
|
||||
if(EXISTS "${CMAKE_TOOLCHAIN_FILE}")
|
||||
# do not apply any global settings if the toolchain
|
||||
# is being configured externally
|
||||
message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}.")
|
||||
elseif(APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
|
||||
set(FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wold-style-cast")
|
||||
elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
if(CYGWIN)
|
||||
set(CMAKE_CXX_FLAGS
|
||||
@@ -134,10 +224,11 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
endif(CYGWIN)
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${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 7.0)
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -faligned-new")
|
||||
"${CMAKE_CXX_FLAGS} -faligned-new -Werror=implicit-fallthrough=2")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -Wunused-result -Werror=unused-result -Wunused-parameter -Werror=unused-parameter")
|
||||
@@ -151,6 +242,10 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
|
||||
set(CMAKE_CXX_FLAGS
|
||||
"${CMAKE_CXX_FLAGS} -std=c++0x -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
|
||||
set(FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wold-style-cast")
|
||||
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.8)
|
||||
list(APPEND FLATBUFFERS_PRIVATE_CXX_FLAGS "-Wimplicit-fallthrough" "-Wextra-semi" "-Werror=unused-private-field") # enable warning
|
||||
endif()
|
||||
if(FLATBUFFERS_LIBCXX_WITH_CLANG)
|
||||
if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
|
||||
set(CMAKE_CXX_FLAGS
|
||||
@@ -181,6 +276,32 @@ if(FLATBUFFERS_CODE_COVERAGE)
|
||||
"${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage")
|
||||
endif()
|
||||
|
||||
function(add_fsanitize_to_target _target _sanitizer)
|
||||
if(WIN32)
|
||||
target_compile_definitions(${_target} PRIVATE FLATBUFFERS_MEMORY_LEAK_TRACKING)
|
||||
message(STATUS "Sanitizer MSVC::_CrtDumpMemoryLeaks added to ${_target}")
|
||||
else()
|
||||
# FLATBUFFERS_CODE_SANITIZE: boolean {ON,OFF,YES,NO} or string with list of sanitizer.
|
||||
# List of sanitizer is string starts with '=': "=address,undefined,thread,memory".
|
||||
if((${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") OR
|
||||
((${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9"))
|
||||
)
|
||||
set(_sanitizer_flags "=address,undefined")
|
||||
if(_sanitizer MATCHES "=.*")
|
||||
# override default by user-defined sanitizer list
|
||||
set(_sanitizer_flags ${_sanitizer})
|
||||
endif()
|
||||
target_compile_options(${_target} PRIVATE
|
||||
-g -fsigned-char -fno-omit-frame-pointer
|
||||
"-fsanitize${_sanitizer_flags}")
|
||||
target_link_libraries(${_target} PRIVATE
|
||||
"-fsanitize${_sanitizer_flags}")
|
||||
set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ON)
|
||||
message(STATUS "Sanitizer ${_sanitizer_flags} added to ${_target}")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
if(BIICODE)
|
||||
include(biicode/cmake/biicode.cmake)
|
||||
return()
|
||||
@@ -191,13 +312,18 @@ include_directories(grpc)
|
||||
|
||||
if(FLATBUFFERS_BUILD_FLATLIB)
|
||||
add_library(flatbuffers STATIC ${FlatBuffers_Library_SRCS})
|
||||
# CMake > 2.8.11: Attach header directory for when build via add_subdirectory().
|
||||
# Attach header directory for when build via add_subdirectory().
|
||||
target_include_directories(flatbuffers INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
|
||||
target_compile_options(flatbuffers PRIVATE "${FLATBUFFERS_PRIVATE_CXX_FLAGS}")
|
||||
endif()
|
||||
|
||||
if(FLATBUFFERS_BUILD_FLATC)
|
||||
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)
|
||||
set(FLATBUFFERS_FLATC_EXECUTABLE $<TARGET_FILE:flatc>)
|
||||
endif()
|
||||
@@ -205,6 +331,9 @@ if(FLATBUFFERS_BUILD_FLATC)
|
||||
# Make flatc.exe not depend on runtime dlls for easy distribution.
|
||||
target_compile_options(flatc PUBLIC $<$<CONFIG:Release>:/MT>)
|
||||
endif()
|
||||
if(FLATBUFFERS_STATIC_FLATC AND NOT MSVC)
|
||||
target_link_libraries(flatc PRIVATE -static)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(FLATBUFFERS_BUILD_FLATHASH)
|
||||
@@ -219,48 +348,148 @@ if(FLATBUFFERS_BUILD_SHAREDLIB)
|
||||
# - minor updated when there are additions in API/ABI
|
||||
# - major (ABI number) updated when there are changes in ABI (or removals)
|
||||
set(FlatBuffers_Library_SONAME_MAJOR "1")
|
||||
set(FlatBuffers_Library_SONAME_FULL "${FlatBuffers_Library_SONAME_MAJOR}.10.0")
|
||||
set(FlatBuffers_Library_SONAME_FULL "${FlatBuffers_Library_SONAME_MAJOR}.12.0")
|
||||
set_target_properties(flatbuffers_shared PROPERTIES OUTPUT_NAME flatbuffers
|
||||
SOVERSION "${FlatBuffers_Library_SONAME_MAJOR}"
|
||||
VERSION "${FlatBuffers_Library_SONAME_FULL}")
|
||||
endif()
|
||||
|
||||
function(compile_flatbuffers_schema_to_cpp SRC_FBS)
|
||||
# Global list of generated files.
|
||||
# Use the global property to be independent of PARENT_SCOPE.
|
||||
set_property(GLOBAL PROPERTY FBS_GENERATED_OUTPUTS)
|
||||
|
||||
function(get_generated_output generated_files)
|
||||
get_property(tmp GLOBAL PROPERTY FBS_GENERATED_OUTPUTS)
|
||||
set(${generated_files} ${tmp} PARENT_SCOPE)
|
||||
endfunction(get_generated_output)
|
||||
|
||||
function(register_generated_output file_name)
|
||||
get_property(tmp GLOBAL PROPERTY FBS_GENERATED_OUTPUTS)
|
||||
list(APPEND tmp ${file_name})
|
||||
set_property(GLOBAL PROPERTY FBS_GENERATED_OUTPUTS ${tmp})
|
||||
endfunction(register_generated_output)
|
||||
|
||||
function(compile_flatbuffers_schema_to_cpp_opt SRC_FBS OPT)
|
||||
if(FLATBUFFERS_BUILD_LEGACY)
|
||||
set(OPT ${OPT};--cpp-std c++0x)
|
||||
else()
|
||||
# --cpp-std is defined by flatc default settings.
|
||||
endif()
|
||||
message(STATUS "`${SRC_FBS}`: add generation of C++ code with '${OPT}'")
|
||||
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
|
||||
string(REGEX REPLACE "\\.fbs$" "_generated.h" GEN_HEADER ${SRC_FBS})
|
||||
add_custom_command(
|
||||
OUTPUT ${GEN_HEADER}
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable
|
||||
--gen-object-api --gen-compare -o "${SRC_FBS_DIR}"
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}"
|
||||
--cpp --gen-mutable --gen-object-api --reflect-names
|
||||
--cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs
|
||||
--reflect-names
|
||||
${OPT}
|
||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||
-o "${SRC_FBS_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
DEPENDS flatc)
|
||||
DEPENDS flatc
|
||||
COMMENT "Run generation: '${GEN_HEADER}'")
|
||||
register_generated_output(${GEN_HEADER})
|
||||
endfunction()
|
||||
|
||||
function(compile_flatbuffers_schema_to_cpp SRC_FBS)
|
||||
compile_flatbuffers_schema_to_cpp_opt(${SRC_FBS} "--no-includes;--gen-compare")
|
||||
endfunction()
|
||||
|
||||
function(compile_flatbuffers_schema_to_binary SRC_FBS)
|
||||
message(STATUS "`${SRC_FBS}`: add generation of binary (.bfbs) schema")
|
||||
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
|
||||
string(REGEX REPLACE "\\.fbs$" ".bfbs" GEN_BINARY_SCHEMA ${SRC_FBS})
|
||||
# For details about flags see generate_code.bat(sh)
|
||||
add_custom_command(
|
||||
OUTPUT ${GEN_BINARY_SCHEMA}
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -b --schema -o "${SRC_FBS_DIR}"
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}"
|
||||
-b --schema --bfbs-comments --bfbs-builtins
|
||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||
-o "${SRC_FBS_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
DEPENDS flatc)
|
||||
DEPENDS flatc
|
||||
COMMENT "Run generation: '${GEN_BINARY_SCHEMA}'")
|
||||
register_generated_output(${GEN_BINARY_SCHEMA})
|
||||
endfunction()
|
||||
|
||||
function(compile_flatbuffers_schema_to_embedded_binary SRC_FBS OPT)
|
||||
if(FLATBUFFERS_BUILD_LEGACY)
|
||||
set(OPT ${OPT};--cpp-std c++0x)
|
||||
else()
|
||||
# --cpp-std is defined by flatc default settings.
|
||||
endif()
|
||||
message(STATUS "`${SRC_FBS}`: add generation of C++ embedded binary schema code with '${OPT}'")
|
||||
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
|
||||
string(REGEX REPLACE "\\.fbs$" "_bfbs_generated.h" GEN_BFBS_HEADER ${SRC_FBS})
|
||||
# For details about flags see generate_code.bat(sh)
|
||||
add_custom_command(
|
||||
OUTPUT ${GEN_BFBS_HEADER}
|
||||
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}"
|
||||
--cpp --gen-mutable --gen-object-api --reflect-names
|
||||
--cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs
|
||||
${OPT}
|
||||
--bfbs-comments --bfbs-builtins --bfbs-gen-embed
|
||||
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
|
||||
-o "${SRC_FBS_DIR}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
|
||||
DEPENDS flatc
|
||||
COMMENT "Run generation: '${GEN_BFBS_HEADER}'")
|
||||
register_generated_output(${GEN_BFBS_HEADER})
|
||||
endfunction()
|
||||
|
||||
if(FLATBUFFERS_BUILD_TESTS)
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/samples" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
# TODO Add (monster_test.fbs monsterdata_test.json)->monsterdata_test.mon
|
||||
compile_flatbuffers_schema_to_cpp(tests/monster_test.fbs)
|
||||
compile_flatbuffers_schema_to_binary(tests/monster_test.fbs)
|
||||
compile_flatbuffers_schema_to_cpp(tests/namespace_test/namespace_test1.fbs)
|
||||
compile_flatbuffers_schema_to_cpp(tests/namespace_test/namespace_test2.fbs)
|
||||
compile_flatbuffers_schema_to_cpp(tests/union_vector/union_vector.fbs)
|
||||
compile_flatbuffers_schema_to_cpp_opt(tests/native_type_test.fbs "")
|
||||
compile_flatbuffers_schema_to_cpp_opt(tests/arrays_test.fbs "--scoped-enums;--gen-compare")
|
||||
compile_flatbuffers_schema_to_binary(tests/arrays_test.fbs)
|
||||
compile_flatbuffers_schema_to_embedded_binary(tests/monster_test.fbs "--no-includes;--gen-compare")
|
||||
if(NOT (MSVC AND (MSVC_VERSION LESS 1900)))
|
||||
compile_flatbuffers_schema_to_cpp(tests/monster_extra.fbs) # Test floating-point NAN/INF.
|
||||
endif()
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/tests)
|
||||
add_executable(flattests ${FlatBuffers_Tests_SRCS})
|
||||
add_dependencies(flattests generated_code)
|
||||
set_property(TARGET flattests
|
||||
PROPERTY COMPILE_DEFINITIONS FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
FLATBUFFERS_DEBUG_VERIFICATION_FAILURE=1)
|
||||
if(FLATBUFFERS_CODE_SANITIZE)
|
||||
add_fsanitize_to_target(flattests ${FLATBUFFERS_CODE_SANITIZE})
|
||||
endif()
|
||||
|
||||
compile_flatbuffers_schema_to_cpp(samples/monster.fbs)
|
||||
compile_flatbuffers_schema_to_binary(samples/monster.fbs)
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/samples)
|
||||
add_executable(flatsamplebinary ${FlatBuffers_Sample_Binary_SRCS})
|
||||
add_dependencies(flatsamplebinary generated_code)
|
||||
add_executable(flatsampletext ${FlatBuffers_Sample_Text_SRCS})
|
||||
add_dependencies(flatsampletext generated_code)
|
||||
add_executable(flatsamplebfbs ${FlatBuffers_Sample_BFBS_SRCS})
|
||||
add_dependencies(flatsamplebfbs generated_code)
|
||||
|
||||
if(FLATBUFFERS_BUILD_CPP17)
|
||||
# Don't generate header for flattests_cpp17 target.
|
||||
# This target uses "generated_cpp17/monster_test_generated.h"
|
||||
# produced by direct call of generate_code.bat(sh) script.
|
||||
add_executable(flattests_cpp17 ${FlatBuffers_Tests_CPP17_SRCS})
|
||||
add_dependencies(flattests_cpp17 generated_code)
|
||||
target_compile_features(flattests_cpp17 PRIVATE cxx_std_17)
|
||||
target_compile_definitions(flattests_cpp17 PRIVATE
|
||||
FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
|
||||
FLATBUFFERS_DEBUG_VERIFICATION_FAILURE=1
|
||||
)
|
||||
if(FLATBUFFERS_CODE_SANITIZE)
|
||||
add_fsanitize_to_target(flattests_cpp17 ${FLATBUFFERS_CODE_SANITIZE})
|
||||
endif()
|
||||
endif(FLATBUFFERS_BUILD_CPP17)
|
||||
endif()
|
||||
|
||||
if(FLATBUFFERS_BUILD_GRPCTEST)
|
||||
@@ -277,7 +506,12 @@ if(FLATBUFFERS_BUILD_GRPCTEST)
|
||||
INCLUDE_DIRECTORIES(${PROTOBUF_DOWNLOAD_PATH}/src)
|
||||
LINK_DIRECTORIES(${GRPC_INSTALL_PATH}/lib)
|
||||
add_executable(grpctest ${FlatBuffers_GRPCTest_SRCS})
|
||||
target_link_libraries(grpctest grpc++_unsecure grpc_unsecure gpr pthread dl)
|
||||
add_dependencies(grpctest generated_code)
|
||||
target_link_libraries(grpctest PRIVATE grpc++_unsecure grpc_unsecure gpr pthread dl)
|
||||
if(FLATBUFFERS_CODE_SANITIZE AND NOT WIN32)
|
||||
# GRPC test has problems with alignment and will fail under ASAN/UBSAN.
|
||||
# add_fsanitize_to_target(grpctest ${FLATBUFFERS_CODE_SANITIZE})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(CMake/Version.cmake)
|
||||
@@ -320,7 +554,6 @@ if(FLATBUFFERS_INSTALL)
|
||||
install(
|
||||
TARGETS flatc EXPORT FlatcTargets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
CONFIGURATIONS Release
|
||||
)
|
||||
|
||||
install(
|
||||
@@ -328,7 +561,6 @@ if(FLATBUFFERS_INSTALL)
|
||||
FILE FlatcTargets.cmake
|
||||
NAMESPACE flatbuffers::
|
||||
DESTINATION ${FB_CMAKE_DIR}
|
||||
CONFIGURATIONS Release
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -362,16 +594,34 @@ endif()
|
||||
if(FLATBUFFERS_BUILD_TESTS)
|
||||
enable_testing()
|
||||
|
||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests" DESTINATION
|
||||
"${CMAKE_CURRENT_BINARY_DIR}")
|
||||
add_test(NAME flattests COMMAND flattests)
|
||||
if(FLATBUFFERS_BUILD_CPP17)
|
||||
add_test(NAME flattests_cpp17 COMMAND flattests_cpp17)
|
||||
endif()
|
||||
if(FLATBUFFERS_BUILD_GRPCTEST)
|
||||
add_test(NAME grpctest COMMAND grpctest)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# This target is sync-barrier.
|
||||
# Other generate-dependent targets can depend on 'generated_code' only.
|
||||
get_generated_output(fbs_generated)
|
||||
if(fbs_generated)
|
||||
# message(STATUS "Add generated_code target with files:${fbs_generated}")
|
||||
add_custom_target(generated_code
|
||||
DEPENDS ${fbs_generated}
|
||||
COMMENT "All generated files were updated.")
|
||||
endif()
|
||||
|
||||
include(CMake/BuildFlatBuffers.cmake)
|
||||
|
||||
if(FLATBUFFERS_PACKAGE_DEBIAN)
|
||||
include(CMake/PackageDebian.cmake)
|
||||
if(UNIX)
|
||||
# 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()
|
||||
|
||||
@@ -187,7 +187,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2014 Google Inc.
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
16
WORKSPACE
16
WORKSPACE
@@ -1,2 +1,18 @@
|
||||
workspace(name = "com_github_google_flatbuffers")
|
||||
|
||||
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_go",
|
||||
urls = [
|
||||
"https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/rules_go/releases/download/v0.20.3/rules_go-v0.20.3.tar.gz",
|
||||
"https://github.com/bazelbuild/rules_go/releases/download/v0.20.3/rules_go-v0.20.3.tar.gz",
|
||||
],
|
||||
sha256 = "e88471aea3a3a4f19ec1310a55ba94772d087e9ce46e41ae38ecebe17935de7b",
|
||||
)
|
||||
|
||||
load("@io_bazel_rules_go//go:deps.bzl", "go_rules_dependencies", "go_register_toolchains")
|
||||
|
||||
go_rules_dependencies()
|
||||
|
||||
go_register_toolchains()
|
||||
|
||||
@@ -66,7 +66,7 @@ android {
|
||||
ndkBuild {
|
||||
targets "FlatBufferTest"
|
||||
arguments "-j" + Runtime.getRuntime().availableProcessors()
|
||||
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,7 @@ LOCAL_MODULE := flatbuffers_extra
|
||||
LOCAL_SRC_FILES := src/idl_parser.cpp \
|
||||
src/idl_gen_text.cpp \
|
||||
src/reflection.cpp \
|
||||
src/util.cpp \
|
||||
src/code_generators.cpp
|
||||
src/util.cpp
|
||||
LOCAL_STATIC_LIBRARIES := flatbuffers
|
||||
LOCAL_ARM_MODE := arm
|
||||
include $(BUILD_STATIC_LIBRARY)
|
||||
@@ -51,8 +50,10 @@ LOCAL_SRC_FILES := android/jni/main.cpp \
|
||||
tests/test_builder.h \
|
||||
tests/test_assert.cpp \
|
||||
tests/test_builder.cpp \
|
||||
tests/native_type_test_impl.h \
|
||||
tests/native_type_test_impl.cpp \
|
||||
src/idl_gen_fbs.cpp \
|
||||
src/idl_gen_general.cpp
|
||||
src/code_generators.cpp
|
||||
LOCAL_LDLIBS := -llog -landroid -latomic
|
||||
LOCAL_STATIC_LIBRARIES := android_native_app_glue flatbuffers_extra
|
||||
LOCAL_ARM_MODE := arm
|
||||
|
||||
@@ -18,9 +18,6 @@
|
||||
|
||||
extern int main(int argc, char **argv);
|
||||
|
||||
void android_main(android_app *app) {
|
||||
// Make sure glue isn't stripped.
|
||||
app_dummy();
|
||||
|
||||
void android_main(android_app *) {
|
||||
main(0, NULL);
|
||||
}
|
||||
|
||||
46
appveyor.yml
46
appveyor.yml
@@ -2,19 +2,37 @@ branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
os: Visual Studio 2015
|
||||
|
||||
environment:
|
||||
|
||||
global:
|
||||
# Workaround for https://github.com/conda/conda-build/issues/636
|
||||
PYTHONIOENCODING: UTF-8
|
||||
CONDA_INSTALL_LOCN: "C:\\Miniconda35-x64"
|
||||
CMAKE_OPTIONS: ""
|
||||
CPP_TEST_OPTIONS: ""
|
||||
|
||||
matrix:
|
||||
- CMAKE_VS_VERSION: "10 2010"
|
||||
- CMAKE_VS_VERSION: "12 2013"
|
||||
- CMAKE_VS_VERSION: "14 2015"
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_VS_VERSION: "10 2010"
|
||||
CMAKE_OPTIONS: "-DFLATBUFFERS_BUILD_LEGACY=1"
|
||||
CPP_TEST_OPTIONS: "--std-cpp c++0x"
|
||||
MONSTER_EXTRA: "skip"
|
||||
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_VS_VERSION: "12 2013"
|
||||
MONSTER_EXTRA: "skip"
|
||||
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
CMAKE_VS_VERSION: "14 2015"
|
||||
MONSTER_EXTRA: ""
|
||||
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
CMAKE_VS_VERSION: "15 2017"
|
||||
MONSTER_EXTRA: ""
|
||||
|
||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
CMAKE_VS_VERSION: "16 2019"
|
||||
MONSTER_EXTRA: ""
|
||||
|
||||
platform:
|
||||
- x86
|
||||
@@ -25,9 +43,12 @@ configuration:
|
||||
- Release
|
||||
|
||||
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 %CMAKE_OPTIONS%
|
||||
# This cuts down on a lot of noise generated by xamarin warnings.
|
||||
- del "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
||||
- if exist "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets" del "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
||||
- if exist "C:\Program Files (x86)\MSBuild\15.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets" del "C:\Program Files (x86)\MSBuild\15.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
||||
- if exist "C:\Program Files (x86)\MSBuild\16.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets" del "C:\Program Files (x86)\MSBuild\16.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
|
||||
|
||||
build:
|
||||
project: ALL_BUILD.vcxproj
|
||||
@@ -46,9 +67,10 @@ install:
|
||||
- cargo -V
|
||||
|
||||
test_script:
|
||||
- call .appveyor\check-generate-code.bat -b %CONFIGURATION%
|
||||
- "cd tests"
|
||||
- rem "Building all code"
|
||||
- generate_code.bat -b %CONFIGURATION%
|
||||
- generate_code.bat -b %CONFIGURATION% %CPP_TEST_OPTIONS%
|
||||
- 7z a GeneratedMyGameCode.zip MyGame\
|
||||
- rem "---------------- C++ -----------------"
|
||||
- "cd .."
|
||||
@@ -83,8 +105,16 @@ test_script:
|
||||
# Have to compile this here rather than in "build" above because AppVeyor only
|
||||
# supports building one project??
|
||||
- "cd FlatBuffers.Test"
|
||||
- "copy ..\\monsterdata_test.mon Resources\\"
|
||||
- "copy ..\\monsterdata_test.json Resources\\"
|
||||
- "dotnet new sln"
|
||||
- "dotnet sln add FlatBuffers.Test.csproj"
|
||||
- "nuget restore"
|
||||
- "msbuild.exe /property:Configuration=Release;OutputPath=tempcs /verbosity:minimal FlatBuffers.Test.csproj"
|
||||
- "tempcs\\FlatBuffers.Test.exe"
|
||||
# Run tests with UNSAFE_BYTEBUFFER
|
||||
- "msbuild.exe /property:Configuration=Release;UnsafeByteBuffer=true;OutputPath=tempcsUnsafe /verbosity:minimal FlatBuffers.Test.csproj"
|
||||
- "tempcsUnsafe\\FlatBuffers.Test.exe"
|
||||
# TODO: add more languages.
|
||||
- "cd ..\\.."
|
||||
|
||||
|
||||
261
build_defs.bzl
Normal file
261
build_defs.bzl
Normal file
@@ -0,0 +1,261 @@
|
||||
# Description:
|
||||
# BUILD rules for generating flatbuffer files in various languages.
|
||||
|
||||
"""
|
||||
Rules for building C++ flatbuffers with Bazel.
|
||||
"""
|
||||
|
||||
load("@rules_cc//cc:defs.bzl", "cc_library")
|
||||
|
||||
flatc_path = "@com_github_google_flatbuffers//:flatc"
|
||||
|
||||
DEFAULT_INCLUDE_PATHS = [
|
||||
"./",
|
||||
"$(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_visibility = None,
|
||||
compatible_with = None,
|
||||
restricted_to = None,
|
||||
output_to_bindir = False):
|
||||
"""Generates code files for reading/writing the given flatbuffers in the requested language using the public compiler.
|
||||
|
||||
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_visibility: The visibility of the generated reflection Fileset.
|
||||
output_to_bindir: Passed to genrule for output to bin directory.
|
||||
compatible_with: Optional, The list of environments this rule can be
|
||||
built for, in addition to default-supported environments.
|
||||
restricted_to: Optional, The list of environments this rule can be built
|
||||
for, instead of default-supported environments.
|
||||
output_to_bindir: Passed to genrule for output to bin directory.
|
||||
|
||||
|
||||
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,
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
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],
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
cmd = reflection_genrule_cmd,
|
||||
message = "Generating flatbuffer reflection binary for %s:" % (name),
|
||||
)
|
||||
native.filegroup(
|
||||
name = "%s_out" % reflection_name,
|
||||
srcs = reflection_outs,
|
||||
visibility = reflection_visibility,
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
)
|
||||
|
||||
def flatbuffer_cc_library(
|
||||
name,
|
||||
srcs,
|
||||
srcs_filegroup_name = "",
|
||||
out_prefix = "",
|
||||
includes = [],
|
||||
include_paths = DEFAULT_INCLUDE_PATHS,
|
||||
flatc_args = DEFAULT_FLATC_ARGS,
|
||||
visibility = None,
|
||||
compatible_with = None,
|
||||
restricted_to = None,
|
||||
srcs_filegroup_visibility = None,
|
||||
gen_reflections = False):
|
||||
'''A cc_library with the generated reader/writers for the given flatbuffer definitions.
|
||||
|
||||
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.
|
||||
compatible_with: Optional, The list of environments this rule can be built
|
||||
for, in addition to default-supported environments.
|
||||
restricted_to: Optional, The list of environments this rule can be built
|
||||
for, instead of default-supported environments.
|
||||
|
||||
This produces:
|
||||
filegroup([name]_srcs): all generated .h files.
|
||||
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,
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
reflection_name = reflection_name,
|
||||
reflection_visibility = visibility,
|
||||
)
|
||||
cc_library(
|
||||
name = name,
|
||||
hdrs = [
|
||||
":" + srcs_lib,
|
||||
],
|
||||
srcs = [
|
||||
":" + srcs_lib,
|
||||
],
|
||||
features = [
|
||||
"-parse_headers",
|
||||
],
|
||||
deps = [
|
||||
"@com_github_google_flatbuffers//:runtime_cc",
|
||||
],
|
||||
includes = [],
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
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,
|
||||
compatible_with = compatible_with,
|
||||
restricted_to = restricted_to,
|
||||
visibility = srcs_filegroup_visibility if srcs_filegroup_visibility != None else visibility,
|
||||
)
|
||||
@@ -1,7 +1,10 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from cpt.packager import ConanMultiPackager
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
from cpt.packager import ConanMultiPackager
|
||||
|
||||
|
||||
def set_appveyor_environment():
|
||||
if os.getenv("APPVEYOR") is not None:
|
||||
@@ -13,6 +16,39 @@ def set_appveyor_environment():
|
||||
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")
|
||||
@@ -22,7 +58,8 @@ if __name__ == "__main__":
|
||||
upload_only_when_stable = os.getenv("CONAN_UPLOAD_ONLY_WHEN_STABLE", True)
|
||||
set_appveyor_environment()
|
||||
|
||||
builder = ConanMultiPackager(username=username,
|
||||
builder = ConanMultiPackager(reference=get_reference(username),
|
||||
username=username,
|
||||
login_username=login_username,
|
||||
upload=upload,
|
||||
stable_branch_pattern=stable_branch_pattern,
|
||||
|
||||
@@ -10,15 +10,15 @@ from conans import ConanFile, CMake, tools
|
||||
|
||||
class FlatbuffersConan(ConanFile):
|
||||
name = "flatbuffers"
|
||||
version = "1.10.0"
|
||||
license = "Apache-2.0"
|
||||
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"
|
||||
settings = "os", "compiler", "build_type", "arch"
|
||||
options = {"shared": [True, False], "fPIC": [True, False]}
|
||||
default_options = "shared=False", "fPIC=True"
|
||||
default_options = {"shared": False, "fPIC": True}
|
||||
generators = "cmake"
|
||||
exports = "LICENSE.txt"
|
||||
exports_sources = ["CMake/*", "include/*", "src/*", "grpc/*", "CMakeLists.txt", "conan/CMakeLists.txt"]
|
||||
@@ -57,6 +57,7 @@ class FlatbuffersConan(ConanFile):
|
||||
cmake = self.configure_cmake()
|
||||
cmake.install()
|
||||
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="flatc*", dst="bin", src="bin")
|
||||
if self.settings.os == "Windows" and self.options.shared:
|
||||
|
||||
@@ -492,7 +492,7 @@ class Builder {
|
||||
/// Write the given list of 64-bit float [values].
|
||||
int writeListFloat64(List<double> values) {
|
||||
_ensureNoVTable();
|
||||
_prepare(4, 1 + (2 * values.length));
|
||||
_prepare(_sizeofFloat64, values.length, additionalBytes: _sizeofUint32);
|
||||
final int result = _tail;
|
||||
int tail = _tail;
|
||||
_setUint32AtTail(_buf, tail, values.length);
|
||||
@@ -522,7 +522,7 @@ class Builder {
|
||||
/// Write the given list of signed 64-bit integer [values].
|
||||
int writeListInt64(List<int> values) {
|
||||
_ensureNoVTable();
|
||||
_prepare(_sizeofUint32, 2 * values.length);
|
||||
_prepare(_sizeofInt64, values.length, additionalBytes: _sizeofUint32);
|
||||
final int result = _tail;
|
||||
int tail = _tail;
|
||||
_setUint32AtTail(_buf, tail, values.length);
|
||||
@@ -537,7 +537,7 @@ class Builder {
|
||||
/// Write the given list of signed 64-bit integer [values].
|
||||
int writeListUint64(List<int> values) {
|
||||
_ensureNoVTable();
|
||||
_prepare(_sizeofUint32, 2 * values.length);
|
||||
_prepare(_sizeofUint64, values.length, additionalBytes: _sizeofUint32);
|
||||
final int result = _tail;
|
||||
int tail = _tail;
|
||||
_setUint32AtTail(_buf, tail, values.length);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: flat_buffers
|
||||
version: 1.10.0
|
||||
version: 1.12.0
|
||||
description: >
|
||||
FlatBuffers reading and writing library for Dart. Use the flatc compiler to
|
||||
generate Dart classes for a FlatBuffers schema, and this library to assist with
|
||||
|
||||
@@ -8,8 +8,8 @@ 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.example_generated.dart' as my_game_example;
|
||||
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);
|
||||
|
||||
@@ -8,9 +8,10 @@ import 'package:flat_buffers/flat_buffers.dart' as fb;
|
||||
|
||||
import 'include_test1_my_game.example_generated.dart';
|
||||
import 'include_test2_my_game.example_generated.dart';
|
||||
import './monster_test_my_game.example2_generated.dart' as my_game_example2;
|
||||
import './monster_test_my_game_generated.dart' as my_game;
|
||||
import './monster_test_my_game.example2_generated.dart' as my_game_example2;
|
||||
|
||||
/// Composite components of Monster color.
|
||||
class Color {
|
||||
final int value;
|
||||
const Color._(this.value);
|
||||
@@ -26,7 +27,12 @@ class Color {
|
||||
static bool containsValue(int value) => values.containsKey(value);
|
||||
|
||||
static const Color Red = const Color._(1);
|
||||
|
||||
/// \brief color Green
|
||||
/// Green is bit_flag with value (1u << 1)
|
||||
static const Color Green = const Color._(2);
|
||||
|
||||
/// \brief color Blue (1u << 3)
|
||||
static const Color Blue = const Color._(8);
|
||||
static get values => {1: Red,2: Green,8: Blue,};
|
||||
|
||||
@@ -46,7 +52,48 @@ class _ColorReader extends fb.Reader<Color> {
|
||||
|
||||
@override
|
||||
Color read(fb.BufferContext bc, int offset) =>
|
||||
new Color.fromValue(const fb.Int8Reader().read(bc, offset));
|
||||
new Color.fromValue(const fb.Uint8Reader().read(bc, offset));
|
||||
}
|
||||
|
||||
class Race {
|
||||
final int value;
|
||||
const Race._(this.value);
|
||||
|
||||
factory Race.fromValue(int value) {
|
||||
if (value == null) value = 0;
|
||||
if (!values.containsKey(value)) {
|
||||
throw new StateError('Invalid value $value for bit flag enum Race');
|
||||
}
|
||||
return values[value];
|
||||
}
|
||||
|
||||
static const int minValue = -1;
|
||||
static const int maxValue = 2;
|
||||
static bool containsValue(int value) => values.containsKey(value);
|
||||
|
||||
static const Race None = const Race._(-1);
|
||||
static const Race Human = const Race._(0);
|
||||
static const Race Dwarf = const Race._(1);
|
||||
static const Race Elf = const Race._(2);
|
||||
static get values => {-1: None,0: Human,1: Dwarf,2: Elf,};
|
||||
|
||||
static const fb.Reader<Race> reader = const _RaceReader();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Race{value: $value}';
|
||||
}
|
||||
}
|
||||
|
||||
class _RaceReader extends fb.Reader<Race> {
|
||||
const _RaceReader();
|
||||
|
||||
@override
|
||||
int get size => 1;
|
||||
|
||||
@override
|
||||
Race read(fb.BufferContext bc, int offset) =>
|
||||
new Race.fromValue(const fb.Int8Reader().read(bc, offset));
|
||||
}
|
||||
|
||||
class AnyTypeId {
|
||||
@@ -90,6 +137,88 @@ class _AnyTypeIdReader extends fb.Reader<AnyTypeId> {
|
||||
new AnyTypeId.fromValue(const fb.Uint8Reader().read(bc, offset));
|
||||
}
|
||||
|
||||
class AnyUniqueAliasesTypeId {
|
||||
final int value;
|
||||
const AnyUniqueAliasesTypeId._(this.value);
|
||||
|
||||
factory AnyUniqueAliasesTypeId.fromValue(int value) {
|
||||
if (value == null) value = 0;
|
||||
if (!values.containsKey(value)) {
|
||||
throw new StateError('Invalid value $value for bit flag enum AnyUniqueAliasesTypeId');
|
||||
}
|
||||
return values[value];
|
||||
}
|
||||
|
||||
static const int minValue = 0;
|
||||
static const int maxValue = 3;
|
||||
static bool containsValue(int value) => values.containsKey(value);
|
||||
|
||||
static const AnyUniqueAliasesTypeId NONE = const AnyUniqueAliasesTypeId._(0);
|
||||
static const AnyUniqueAliasesTypeId M = const AnyUniqueAliasesTypeId._(1);
|
||||
static const AnyUniqueAliasesTypeId TS = const AnyUniqueAliasesTypeId._(2);
|
||||
static const AnyUniqueAliasesTypeId M2 = const AnyUniqueAliasesTypeId._(3);
|
||||
static get values => {0: NONE,1: M,2: TS,3: M2,};
|
||||
|
||||
static const fb.Reader<AnyUniqueAliasesTypeId> reader = const _AnyUniqueAliasesTypeIdReader();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AnyUniqueAliasesTypeId{value: $value}';
|
||||
}
|
||||
}
|
||||
|
||||
class _AnyUniqueAliasesTypeIdReader extends fb.Reader<AnyUniqueAliasesTypeId> {
|
||||
const _AnyUniqueAliasesTypeIdReader();
|
||||
|
||||
@override
|
||||
int get size => 1;
|
||||
|
||||
@override
|
||||
AnyUniqueAliasesTypeId read(fb.BufferContext bc, int offset) =>
|
||||
new AnyUniqueAliasesTypeId.fromValue(const fb.Uint8Reader().read(bc, offset));
|
||||
}
|
||||
|
||||
class AnyAmbiguousAliasesTypeId {
|
||||
final int value;
|
||||
const AnyAmbiguousAliasesTypeId._(this.value);
|
||||
|
||||
factory AnyAmbiguousAliasesTypeId.fromValue(int value) {
|
||||
if (value == null) value = 0;
|
||||
if (!values.containsKey(value)) {
|
||||
throw new StateError('Invalid value $value for bit flag enum AnyAmbiguousAliasesTypeId');
|
||||
}
|
||||
return values[value];
|
||||
}
|
||||
|
||||
static const int minValue = 0;
|
||||
static const int maxValue = 3;
|
||||
static bool containsValue(int value) => values.containsKey(value);
|
||||
|
||||
static const AnyAmbiguousAliasesTypeId NONE = const AnyAmbiguousAliasesTypeId._(0);
|
||||
static const AnyAmbiguousAliasesTypeId M1 = const AnyAmbiguousAliasesTypeId._(1);
|
||||
static const AnyAmbiguousAliasesTypeId M2 = const AnyAmbiguousAliasesTypeId._(2);
|
||||
static const AnyAmbiguousAliasesTypeId M3 = const AnyAmbiguousAliasesTypeId._(3);
|
||||
static get values => {0: NONE,1: M1,2: M2,3: M3,};
|
||||
|
||||
static const fb.Reader<AnyAmbiguousAliasesTypeId> reader = const _AnyAmbiguousAliasesTypeIdReader();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AnyAmbiguousAliasesTypeId{value: $value}';
|
||||
}
|
||||
}
|
||||
|
||||
class _AnyAmbiguousAliasesTypeIdReader extends fb.Reader<AnyAmbiguousAliasesTypeId> {
|
||||
const _AnyAmbiguousAliasesTypeIdReader();
|
||||
|
||||
@override
|
||||
int get size => 1;
|
||||
|
||||
@override
|
||||
AnyAmbiguousAliasesTypeId read(fb.BufferContext bc, int offset) =>
|
||||
new AnyAmbiguousAliasesTypeId.fromValue(const fb.Uint8Reader().read(bc, offset));
|
||||
}
|
||||
|
||||
class Test {
|
||||
Test._(this._bc, this._bcOffset);
|
||||
|
||||
@@ -177,7 +306,7 @@ class TestSimpleTableWithEnum {
|
||||
final fb.BufferContext _bc;
|
||||
final int _bcOffset;
|
||||
|
||||
Color get color => new Color.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 4, 2));
|
||||
Color get color => new Color.fromValue(const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 4, 2));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
@@ -205,7 +334,7 @@ class TestSimpleTableWithEnumBuilder {
|
||||
}
|
||||
|
||||
int addColor(Color color) {
|
||||
fbBuilder.addInt8(0, color?.value);
|
||||
fbBuilder.addUint8(0, color?.value);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
@@ -229,7 +358,7 @@ class TestSimpleTableWithEnumObjectBuilder extends fb.ObjectBuilder {
|
||||
assert(fbBuilder != null);
|
||||
|
||||
fbBuilder.startTable();
|
||||
fbBuilder.addInt8(0, _color?.value);
|
||||
fbBuilder.addUint8(0, _color?.value);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
@@ -253,7 +382,7 @@ class Vec3 {
|
||||
double get y => const fb.Float32Reader().read(_bc, _bcOffset + 4);
|
||||
double get z => const fb.Float32Reader().read(_bc, _bcOffset + 8);
|
||||
double get test1 => const fb.Float64Reader().read(_bc, _bcOffset + 16);
|
||||
Color get test2 => new Color.fromValue(const fb.Int8Reader().read(_bc, _bcOffset + 24));
|
||||
Color get test2 => new Color.fromValue(const fb.Uint8Reader().read(_bc, _bcOffset + 24));
|
||||
Test get test3 => Test.reader.read(_bc, _bcOffset + 26);
|
||||
|
||||
@override
|
||||
@@ -284,7 +413,7 @@ class Vec3Builder {
|
||||
fbBuilder.pad(2);
|
||||
test3();
|
||||
fbBuilder.pad(1);
|
||||
fbBuilder.putInt8(test2?.value);
|
||||
fbBuilder.putUint8(test2?.value);
|
||||
fbBuilder.putFloat64(test1);
|
||||
fbBuilder.pad(4);
|
||||
fbBuilder.putFloat32(z);
|
||||
@@ -327,7 +456,7 @@ class Vec3ObjectBuilder extends fb.ObjectBuilder {
|
||||
fbBuilder.pad(2);
|
||||
_test3.finish(fbBuilder);
|
||||
fbBuilder.pad(1);
|
||||
fbBuilder.putInt8(_test2?.value);
|
||||
fbBuilder.putUint8(_test2?.value);
|
||||
fbBuilder.putFloat64(_test1);
|
||||
fbBuilder.pad(4);
|
||||
fbBuilder.putFloat32(_z);
|
||||
@@ -608,7 +737,7 @@ class Monster {
|
||||
int get hp => const fb.Int16Reader().vTableGet(_bc, _bcOffset, 8, 100);
|
||||
String get name => const fb.StringReader().vTableGet(_bc, _bcOffset, 10, null);
|
||||
List<int> get inventory => const fb.ListReader<int>(const fb.Uint8Reader()).vTableGet(_bc, _bcOffset, 14, null);
|
||||
Color get color => new Color.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 16, 8));
|
||||
Color get color => new Color.fromValue(const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 16, 8));
|
||||
AnyTypeId get testType => new AnyTypeId.fromValue(const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 18, 0));
|
||||
dynamic get test {
|
||||
switch (testType?.value) {
|
||||
@@ -620,8 +749,8 @@ class Monster {
|
||||
}
|
||||
List<Test> get test4 => const fb.ListReader<Test>(Test.reader).vTableGet(_bc, _bcOffset, 22, null);
|
||||
List<String> get testarrayofstring => const fb.ListReader<String>(const fb.StringReader()).vTableGet(_bc, _bcOffset, 24, null);
|
||||
/// an example documentation comment: this will end up in the generated code
|
||||
/// multiline too
|
||||
/// an example documentation comment: this will end up in the generated code
|
||||
/// multiline too
|
||||
List<Monster> get testarrayoftables => const fb.ListReader<Monster>(Monster.reader).vTableGet(_bc, _bcOffset, 26, null);
|
||||
Monster get enemy => Monster.reader.vTableGet(_bc, _bcOffset, 28, null);
|
||||
List<int> get testnestedflatbuffer => const fb.ListReader<int>(const fb.Uint8Reader()).vTableGet(_bc, _bcOffset, 30, null);
|
||||
@@ -654,10 +783,30 @@ class Monster {
|
||||
List<int> get vectorOfCoOwningReferences => const fb.ListReader<int>(const fb.Uint64Reader()).vTableGet(_bc, _bcOffset, 84, null);
|
||||
int get nonOwningReference => const fb.Uint64Reader().vTableGet(_bc, _bcOffset, 86, 0);
|
||||
List<int> get vectorOfNonOwningReferences => const fb.ListReader<int>(const fb.Uint64Reader()).vTableGet(_bc, _bcOffset, 88, null);
|
||||
AnyUniqueAliasesTypeId get anyUniqueType => new AnyUniqueAliasesTypeId.fromValue(const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 90, 0));
|
||||
dynamic get anyUnique {
|
||||
switch (anyUniqueType?.value) {
|
||||
case 1: return M.reader.vTableGet(_bc, _bcOffset, 92, null);
|
||||
case 2: return TS.reader.vTableGet(_bc, _bcOffset, 92, null);
|
||||
case 3: return M2.reader.vTableGet(_bc, _bcOffset, 92, null);
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
AnyAmbiguousAliasesTypeId get anyAmbiguousType => new AnyAmbiguousAliasesTypeId.fromValue(const fb.Uint8Reader().vTableGet(_bc, _bcOffset, 94, 0));
|
||||
dynamic get anyAmbiguous {
|
||||
switch (anyAmbiguousType?.value) {
|
||||
case 1: return M1.reader.vTableGet(_bc, _bcOffset, 96, null);
|
||||
case 2: return M2.reader.vTableGet(_bc, _bcOffset, 96, null);
|
||||
case 3: return M3.reader.vTableGet(_bc, _bcOffset, 96, null);
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
List<Color> get vectorOfEnums => const fb.ListReader<Color>(Color.reader).vTableGet(_bc, _bcOffset, 98, null);
|
||||
Race get signedEnum => new Race.fromValue(const fb.Int8Reader().vTableGet(_bc, _bcOffset, 100, -1));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'Monster{pos: $pos, mana: $mana, hp: $hp, name: $name, inventory: $inventory, color: $color, testType: $testType, test: $test, test4: $test4, testarrayofstring: $testarrayofstring, testarrayoftables: $testarrayoftables, enemy: $enemy, testnestedflatbuffer: $testnestedflatbuffer, testempty: $testempty, testbool: $testbool, testhashs32Fnv1: $testhashs32Fnv1, testhashu32Fnv1: $testhashu32Fnv1, testhashs64Fnv1: $testhashs64Fnv1, testhashu64Fnv1: $testhashu64Fnv1, testhashs32Fnv1a: $testhashs32Fnv1a, testhashu32Fnv1a: $testhashu32Fnv1a, testhashs64Fnv1a: $testhashs64Fnv1a, testhashu64Fnv1a: $testhashu64Fnv1a, testarrayofbools: $testarrayofbools, testf: $testf, testf2: $testf2, testf3: $testf3, testarrayofstring2: $testarrayofstring2, testarrayofsortedstruct: $testarrayofsortedstruct, flex: $flex, test5: $test5, vectorOfLongs: $vectorOfLongs, vectorOfDoubles: $vectorOfDoubles, parentNamespaceTest: $parentNamespaceTest, vectorOfReferrables: $vectorOfReferrables, singleWeakReference: $singleWeakReference, vectorOfWeakReferences: $vectorOfWeakReferences, vectorOfStrongReferrables: $vectorOfStrongReferrables, coOwningReference: $coOwningReference, vectorOfCoOwningReferences: $vectorOfCoOwningReferences, nonOwningReference: $nonOwningReference, vectorOfNonOwningReferences: $vectorOfNonOwningReferences}';
|
||||
return 'Monster{pos: $pos, mana: $mana, hp: $hp, name: $name, inventory: $inventory, color: $color, testType: $testType, test: $test, test4: $test4, testarrayofstring: $testarrayofstring, testarrayoftables: $testarrayoftables, enemy: $enemy, testnestedflatbuffer: $testnestedflatbuffer, testempty: $testempty, testbool: $testbool, testhashs32Fnv1: $testhashs32Fnv1, testhashu32Fnv1: $testhashu32Fnv1, testhashs64Fnv1: $testhashs64Fnv1, testhashu64Fnv1: $testhashu64Fnv1, testhashs32Fnv1a: $testhashs32Fnv1a, testhashu32Fnv1a: $testhashu32Fnv1a, testhashs64Fnv1a: $testhashs64Fnv1a, testhashu64Fnv1a: $testhashu64Fnv1a, testarrayofbools: $testarrayofbools, testf: $testf, testf2: $testf2, testf3: $testf3, testarrayofstring2: $testarrayofstring2, testarrayofsortedstruct: $testarrayofsortedstruct, flex: $flex, test5: $test5, vectorOfLongs: $vectorOfLongs, vectorOfDoubles: $vectorOfDoubles, parentNamespaceTest: $parentNamespaceTest, vectorOfReferrables: $vectorOfReferrables, singleWeakReference: $singleWeakReference, vectorOfWeakReferences: $vectorOfWeakReferences, vectorOfStrongReferrables: $vectorOfStrongReferrables, coOwningReference: $coOwningReference, vectorOfCoOwningReferences: $vectorOfCoOwningReferences, nonOwningReference: $nonOwningReference, vectorOfNonOwningReferences: $vectorOfNonOwningReferences, anyUniqueType: $anyUniqueType, anyUnique: $anyUnique, anyAmbiguousType: $anyAmbiguousType, anyAmbiguous: $anyAmbiguous, vectorOfEnums: $vectorOfEnums, signedEnum: $signedEnum}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -701,7 +850,7 @@ class MonsterBuilder {
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addColor(Color color) {
|
||||
fbBuilder.addInt8(6, color?.value);
|
||||
fbBuilder.addUint8(6, color?.value);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addTestType(AnyTypeId testType) {
|
||||
@@ -848,6 +997,30 @@ class MonsterBuilder {
|
||||
fbBuilder.addOffset(42, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addAnyUniqueType(AnyUniqueAliasesTypeId anyUniqueType) {
|
||||
fbBuilder.addUint8(43, anyUniqueType?.value);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addAnyUniqueOffset(int offset) {
|
||||
fbBuilder.addOffset(44, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addAnyAmbiguousType(AnyAmbiguousAliasesTypeId anyAmbiguousType) {
|
||||
fbBuilder.addUint8(45, anyAmbiguousType?.value);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addAnyAmbiguousOffset(int offset) {
|
||||
fbBuilder.addOffset(46, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addVectorOfEnumsOffset(int offset) {
|
||||
fbBuilder.addOffset(47, offset);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
int addSignedEnum(Race signedEnum) {
|
||||
fbBuilder.addInt8(48, signedEnum?.value);
|
||||
return fbBuilder.offset;
|
||||
}
|
||||
|
||||
int finish() {
|
||||
return fbBuilder.endTable();
|
||||
@@ -897,6 +1070,12 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
final List<int> _vectorOfCoOwningReferences;
|
||||
final int _nonOwningReference;
|
||||
final List<int> _vectorOfNonOwningReferences;
|
||||
final AnyUniqueAliasesTypeId _anyUniqueType;
|
||||
final dynamic _anyUnique;
|
||||
final AnyAmbiguousAliasesTypeId _anyAmbiguousType;
|
||||
final dynamic _anyAmbiguous;
|
||||
final List<Color> _vectorOfEnums;
|
||||
final Race _signedEnum;
|
||||
|
||||
MonsterObjectBuilder({
|
||||
Vec3ObjectBuilder pos,
|
||||
@@ -941,6 +1120,12 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
List<int> vectorOfCoOwningReferences,
|
||||
int nonOwningReference,
|
||||
List<int> vectorOfNonOwningReferences,
|
||||
AnyUniqueAliasesTypeId anyUniqueType,
|
||||
dynamic anyUnique,
|
||||
AnyAmbiguousAliasesTypeId anyAmbiguousType,
|
||||
dynamic anyAmbiguous,
|
||||
List<Color> vectorOfEnums,
|
||||
Race signedEnum,
|
||||
})
|
||||
: _pos = pos,
|
||||
_mana = mana,
|
||||
@@ -983,7 +1168,13 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
_coOwningReference = coOwningReference,
|
||||
_vectorOfCoOwningReferences = vectorOfCoOwningReferences,
|
||||
_nonOwningReference = nonOwningReference,
|
||||
_vectorOfNonOwningReferences = vectorOfNonOwningReferences;
|
||||
_vectorOfNonOwningReferences = vectorOfNonOwningReferences,
|
||||
_anyUniqueType = anyUniqueType,
|
||||
_anyUnique = anyUnique,
|
||||
_anyAmbiguousType = anyAmbiguousType,
|
||||
_anyAmbiguous = anyAmbiguous,
|
||||
_vectorOfEnums = vectorOfEnums,
|
||||
_signedEnum = signedEnum;
|
||||
|
||||
/// Finish building, and store into the [fbBuilder].
|
||||
@override
|
||||
@@ -1046,6 +1237,11 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
final int vectorOfNonOwningReferencesOffset = _vectorOfNonOwningReferences?.isNotEmpty == true
|
||||
? fbBuilder.writeListUint64(_vectorOfNonOwningReferences)
|
||||
: null;
|
||||
final int anyUniqueOffset = _anyUnique?.getOrCreateOffset(fbBuilder);
|
||||
final int anyAmbiguousOffset = _anyAmbiguous?.getOrCreateOffset(fbBuilder);
|
||||
final int vectorOfEnumsOffset = _vectorOfEnums?.isNotEmpty == true
|
||||
? fbBuilder.writeListUint8(_vectorOfEnums.map((f) => f.value))
|
||||
: null;
|
||||
|
||||
fbBuilder.startTable();
|
||||
if (_pos != null) {
|
||||
@@ -1059,7 +1255,7 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
if (inventoryOffset != null) {
|
||||
fbBuilder.addOffset(5, inventoryOffset);
|
||||
}
|
||||
fbBuilder.addInt8(6, _color?.value);
|
||||
fbBuilder.addUint8(6, _color?.value);
|
||||
fbBuilder.addUint8(7, _testType?.value);
|
||||
if (testOffset != null) {
|
||||
fbBuilder.addOffset(8, testOffset);
|
||||
@@ -1136,6 +1332,18 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
|
||||
if (vectorOfNonOwningReferencesOffset != null) {
|
||||
fbBuilder.addOffset(42, vectorOfNonOwningReferencesOffset);
|
||||
}
|
||||
fbBuilder.addUint8(43, _anyUniqueType?.value);
|
||||
if (anyUniqueOffset != null) {
|
||||
fbBuilder.addOffset(44, anyUniqueOffset);
|
||||
}
|
||||
fbBuilder.addUint8(45, _anyAmbiguousType?.value);
|
||||
if (anyAmbiguousOffset != null) {
|
||||
fbBuilder.addOffset(46, anyAmbiguousOffset);
|
||||
}
|
||||
if (vectorOfEnumsOffset != null) {
|
||||
fbBuilder.addOffset(47, vectorOfEnumsOffset);
|
||||
}
|
||||
fbBuilder.addInt8(48, _signedEnum?.value);
|
||||
return fbBuilder.endTable();
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,19 @@ Building should also produce two sample executables, `flatsamplebinary` and
|
||||
*Note that you MUST be in the root of the FlatBuffers distribution when you
|
||||
run 'flattests' or `flatsampletext`, or it will fail to load its files.*
|
||||
|
||||
## Building with VCPKG
|
||||
|
||||
You can download and install flatbuffers using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:
|
||||
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
./vcpkg install flatbuffers
|
||||
|
||||
The flatbuffers port in vcpkg is kept up to date by Microsoft team members and community contributors.
|
||||
If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||
|
||||
## Building for Android
|
||||
|
||||
There is a `flatbuffers/android` directory that contains all you need to build
|
||||
@@ -80,6 +93,14 @@ 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 applications on Google Play that integrate this library, usage is tracked.
|
||||
|
||||
@@ -3,7 +3,7 @@ Using the schema compiler {#flatbuffers_guide_using_schema_compiler}
|
||||
|
||||
Usage:
|
||||
|
||||
flatc [ GENERATOR OPTIONS ] [ -o PATH ] [ -I PATH ] [ -S ] FILES...
|
||||
flatc [ GENERATOR OPTIONS ] [ -o PATH ] [ -I PATH ] FILES...
|
||||
[ -- FILES...]
|
||||
|
||||
The files are read and parsed in order, and can contain either schemas
|
||||
@@ -23,6 +23,8 @@ For any schema input files, one or more generators can be specified:
|
||||
|
||||
- `--java`, `-j` : Generate Java code.
|
||||
|
||||
- `--kotlin`, `-k` : Generate Kotlin code.
|
||||
|
||||
- `--csharp`, `-n` : Generate C# code.
|
||||
|
||||
- `--go`, `-g` : Generate Go code.
|
||||
@@ -45,6 +47,8 @@ For any schema input files, one or more generators can be specified:
|
||||
|
||||
- `--rust`, `-r` : Generate Rust code.
|
||||
|
||||
- `--swift`: Generate Swift code.
|
||||
|
||||
For any data input files:
|
||||
|
||||
- `--binary`, `-b` : If data is contained in this file, generate a
|
||||
@@ -72,6 +76,12 @@ Additional options:
|
||||
in quotes, no trailing commas in tables/vectors). By default, no quotes are
|
||||
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
|
||||
when writing JSON text.
|
||||
|
||||
@@ -86,26 +96,54 @@ Additional options:
|
||||
statements) use `--no-includes.`
|
||||
|
||||
- `--no-includes` : Don't generate include statements for included schemas the
|
||||
generated file depends on (C++).
|
||||
generated file depends on (C++ / Python).
|
||||
|
||||
- `--gen-mutable` : Generate additional non-const accessors for mutating
|
||||
FlatBuffers in-place.
|
||||
|
||||
`--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,
|
||||
at the cost of efficiency (object allocation). Recommended only to be used
|
||||
if other options are insufficient.
|
||||
|
||||
- `--gen-compare` : Generate operator== for object-based API types.
|
||||
- `--gen-compare` : Generate operator== for object-based API types.
|
||||
|
||||
- `--gen-onefile` : Generate single output file (useful for C#)
|
||||
- `--gen-nullable` : Add Clang _Nullable for C++ pointer. or @Nullable for Java.
|
||||
|
||||
- `--gen-all`: Generate not just code for the current schema files, but
|
||||
- `--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
|
||||
output (by default the case for C++ and JS), all code will end up in
|
||||
this one file.
|
||||
|
||||
- `--no-js-exports` : Removes Node.js style export lines (useful for JS)
|
||||
- `--cpp-include` : Adds an #include in generated file
|
||||
|
||||
- `--cpp-ptr-type T` : Set object API pointer type (default std::unique_ptr)
|
||||
|
||||
- `--cpp-str-type T` : Set object API string type (default std::string)
|
||||
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.
|
||||
|
||||
- `--cpp-std CPP_STD` : Generate a C++ code using features of selected C++ standard.
|
||||
Supported `CPP_STD` values:
|
||||
* `c++0x` - generate code compatible with old compilers (VS2010).
|
||||
* `c++11` - use C++11 code generator (default);
|
||||
|
||||
- `--object-prefix` : Customise class prefix for C++ object-based API.
|
||||
|
||||
- `--object-suffix` : Customise class suffix for C++ object-based API.
|
||||
|
||||
- `--no-js-exports` : Removes Node.js style export lines (useful for JS)
|
||||
|
||||
- `--goog-js-export` : Uses goog.exportsSymbol and goog.exportsProperty
|
||||
instead of Node.js style exporting. Needed for compatibility with the
|
||||
@@ -115,9 +153,16 @@ Additional options:
|
||||
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.
|
||||
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).
|
||||
Output the corresponding .fbs file.
|
||||
Currently supports: `package`, `message`, `enum`, nested declarations,
|
||||
@@ -125,6 +170,10 @@ Additional options:
|
||||
Does not support, but will skip without error: `option`, `service`,
|
||||
`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
|
||||
output a binary version of the specified schema that itself corresponds
|
||||
to the reflection/reflection.fbs schema. Loading this binary file is the
|
||||
@@ -136,12 +185,29 @@ Additional options:
|
||||
an evolution of. Gives errors if not. Useful to check if schema
|
||||
modifications don't break schema evolution rules.
|
||||
|
||||
- `--conform-includes PATH` : Include path for the schema given with
|
||||
`--conform PATH`.
|
||||
|
||||
- `--filename-suffix SUFFIX` : The suffix appended to the generated
|
||||
file names. Default is '_generated'.
|
||||
|
||||
- `--filename-ext EXTENSION` : The extension appended to the generated
|
||||
file names. Default is language-specific (e.g. "h" for C++). This
|
||||
should not be used when multiple languages are specified.
|
||||
|
||||
- `--include-prefix PATH` : Prefix this path to any generated include
|
||||
statements.
|
||||
|
||||
- `--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-names` : Add minimal type/name reflection.
|
||||
|
||||
- `--root-type T` : Select or override the default root_type.
|
||||
@@ -151,5 +217,8 @@ Additional options:
|
||||
- `--force-empty` : When serializing from object API representation, force
|
||||
strings and vectors to empty rather than null.
|
||||
|
||||
- `--force-empty-vectors` : When serializing from object API representation, force
|
||||
vectors to empty rather than null.
|
||||
|
||||
NOTE: short-form options for generators are deprecated, use the long form
|
||||
whenever possible.
|
||||
|
||||
@@ -35,7 +35,7 @@ The test code itself is located in
|
||||
[test.cpp](https://github.com/google/flatbuffers/blob/master/tests/test.cpp).
|
||||
|
||||
This test file is built alongside `flatc`. To review how to build the project,
|
||||
please read the [Building](@ref flatbuffers_guide_building) documenation.
|
||||
please read the [Building](@ref flatbuffers_guide_building) documentation.
|
||||
|
||||
To run the tests, execute `flattests` from the root `flatbuffers/` directory.
|
||||
For example, on [Linux](https://en.wikipedia.org/wiki/Linux), you would simply
|
||||
@@ -88,6 +88,14 @@ convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
|
||||
|
||||
*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}
|
||||
|
||||
FlatBuffers is all about memory efficiency, which is why its base API is written
|
||||
@@ -106,7 +114,7 @@ To use:
|
||||
MonsterT monsterobj;
|
||||
|
||||
// Deserialize from buffer into object.
|
||||
UnPackTo(&monsterobj, flatbuffer);
|
||||
GetMonster(flatbuffer)->UnPackTo(&monsterobj);
|
||||
|
||||
// Update object directly like a C++ class instance.
|
||||
cout << monsterobj->name; // This is now a std::string!
|
||||
@@ -114,7 +122,7 @@ To use:
|
||||
|
||||
// Serialize into new flatbuffer.
|
||||
FlatBufferBuilder fbb;
|
||||
Pack(fbb, &monsterobj);
|
||||
fbb.Finish(Monster::Pack(fbb, &monsterobj));
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The following attributes are specific to the object-based API code generation:
|
||||
@@ -130,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.
|
||||
|
||||
- `native_custom_alloc`:"custom_allocator" (on a table or struct): When using the
|
||||
object-based API all generated NativeTables that are allocated when unpacking
|
||||
your flatbuffer will use "custom allocator". The allocator is also used by
|
||||
any std::vector that appears in a table defined with `native_custom_alloc`.
|
||||
This can be used to provide allocation from a pool for example, for faster
|
||||
object-based API all generated NativeTables that are allocated when unpacking
|
||||
your flatbuffer will use "custom allocator". The allocator is also used by
|
||||
any std::vector that appears in a table defined with `native_custom_alloc`.
|
||||
This can be used to provide allocation from a pool for example, for faster
|
||||
unpacking when using the object-based API.
|
||||
|
||||
Minimal Example:
|
||||
@@ -151,8 +159,8 @@ The following attributes are specific to the object-based API code generation:
|
||||
typedef T *pointer;
|
||||
|
||||
template <class U>
|
||||
struct rebind {
|
||||
typedef custom_allocator<U> other;
|
||||
struct rebind {
|
||||
typedef custom_allocator<U> other;
|
||||
};
|
||||
|
||||
pointer allocate(const std::size_t n) {
|
||||
@@ -164,7 +172,7 @@ The following attributes are specific to the object-based API code generation:
|
||||
}
|
||||
|
||||
custom_allocator() throw() {}
|
||||
template <class U>
|
||||
template <class U>
|
||||
custom_allocator(const custom_allocator<U>&) throw() {}
|
||||
};
|
||||
|
||||
@@ -208,12 +216,15 @@ The following attributes are specific to the object-based API code generation:
|
||||
|
||||
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
|
||||
necessary to include "external" header files in the generated code. This
|
||||
attribute can be used to directly add an #include directive to the top of
|
||||
the generated code that includes the specified path directly.
|
||||
|
||||
- `force_align`: this attribute may not be respected in the object API,
|
||||
depending on the aligned of the allocator used with `new`.
|
||||
|
||||
# External references.
|
||||
|
||||
An additional feature of the object API is the ability to allow you to load
|
||||
@@ -240,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
|
||||
pointer type (`my_ptr<T>`), or by specifying `naked` as the type to get `T *`
|
||||
pointers. Unlike the smart pointers, naked pointers do not manage memory for
|
||||
you, so you'll have to manage their lifecycles manually.
|
||||
|
||||
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.
|
||||
|
||||
@@ -249,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
|
||||
`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)
|
||||
|
||||
@@ -403,6 +426,8 @@ it, this will provide you an easy way to use that data directly.
|
||||
(see the schema documentation for some specifics on the JSON format
|
||||
accepted).
|
||||
|
||||
Schema evolution compatibility for the JSON format follows the same rules as the binary format (JSON formatted data will be forwards/backwards compatible with schemas that evolve in a compatible way).
|
||||
|
||||
There are two ways to use text formats:
|
||||
|
||||
#### Using the compiler as a conversion tool
|
||||
@@ -454,7 +479,7 @@ include paths. If not specified, any include statements try to resolve from
|
||||
the current directory.
|
||||
|
||||
If there were any parsing errors, `Parse` will return `false`, and
|
||||
`Parser::err` contains a human readable error string with a line number
|
||||
`Parser::error_` contains a human readable error string with a line number
|
||||
etc, which you should present to the creator of that file.
|
||||
|
||||
After each JSON file, the `Parser::fbb` member variable is the
|
||||
@@ -495,4 +520,91 @@ needed to use unions.
|
||||
|
||||
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:
|
||||
- CMake `"CMakeLists.txt"`:
|
||||
- Check existence of `strtol_l` and `strtod_l` in the `<stdlib.h>`.
|
||||
- Compile-time `"/include/base.h"`:
|
||||
- `_MSC_VER >= 1900`: MSVC2012 or higher if build with MSVC.
|
||||
- `_XOPEN_SOURCE>=700`: POSIX-2008 if build with GCC/Clang.
|
||||
|
||||
After detection, the definition `FLATBUFFERS_LOCALE_INDEPENDENT` will be
|
||||
set to `0` or `1`.
|
||||
To override or stop this detection use CMake `-DFLATBUFFERS_LOCALE_INDEPENDENT={0|1}`
|
||||
or predefine `FLATBUFFERS_LOCALE_INDEPENDENT` symbol.
|
||||
|
||||
To test the compatibility of the Flatbuffers library with
|
||||
a specific locale use the environment variable `FLATBUFFERS_TEST_LOCALE`:
|
||||
```sh
|
||||
>FLATBUFFERS_TEST_LOCALE="" ./flattests
|
||||
>FLATBUFFERS_TEST_LOCALE="ru_RU.CP1251" ./flattests
|
||||
```
|
||||
|
||||
## Support of floating-point numbers
|
||||
The Flatbuffers library assumes that a C++ compiler and a CPU are
|
||||
compatible with the `IEEE-754` floating-point standard.
|
||||
The schema and json parser may fail if `fast-math` or `/fp:fast` mode is active.
|
||||
|
||||
### Support of hexadecimal and special floating-point numbers
|
||||
According to the [grammar](@ref flatbuffers_grammar) `fbs` and `json` files
|
||||
may use hexadecimal and special (`NaN`, `Inf`) floating-point literals.
|
||||
The Flatbuffers uses `strtof` and `strtod` functions to parse floating-point
|
||||
literals. The Flatbuffers library has a code to detect a compiler compatibility
|
||||
with the literals. If necessary conditions are met the preprocessor constant
|
||||
`FLATBUFFERS_HAS_NEW_STRTOD` will be set to `1`.
|
||||
The support of floating-point literals will be limited at compile time
|
||||
if `FLATBUFFERS_HAS_NEW_STRTOD` constant is less than `1`.
|
||||
In this case, schemas with hexadecimal or special literals cannot be used.
|
||||
|
||||
### Comparison of floating-point NaN values
|
||||
The floating-point `NaN` (`not a number`) is special value which
|
||||
representing an undefined or unrepresentable value.
|
||||
`NaN` may be explicitly assigned to variables, typically as a representation
|
||||
for missing values or may be a result of a mathematical operation.
|
||||
The `IEEE-754` defines two kind of `NaNs`:
|
||||
- Quiet NaNs, or `qNaNs`.
|
||||
- Signaling NaNs, or `sNaNs`.
|
||||
|
||||
According to the `IEEE-754`, a comparison with `NaN` always returns
|
||||
an unordered result even when compared with itself. As a result, a whole
|
||||
Flatbuffers object will be not equal to itself if has one or more `NaN`.
|
||||
Flatbuffers scalar fields that have the default value are not actually stored
|
||||
in the serialized data but are generated in code (see [Writing a schema](@ref flatbuffers_guide_writing_schema)).
|
||||
Scalar fields with `NaN` defaults break this behavior.
|
||||
If a schema has a lot of `NaN` defaults the Flatbuffers can override
|
||||
the unordered comparison by the ordered: `(NaN==NaN)->true`.
|
||||
This ordered comparison is enabled when compiling a program with the symbol
|
||||
`FLATBUFFERS_NAN_DEFAULTS` defined.
|
||||
Additional computations added by `FLATBUFFERS_NAN_DEFAULTS` are very cheap
|
||||
if GCC or Clang used. These compilers have a compile-time implementation
|
||||
of `isnan` checking which MSVC does not.
|
||||
|
||||
<br>
|
||||
|
||||
175
docs/source/CsharpUsage.md
Normal file
175
docs/source/CsharpUsage.md
Normal file
@@ -0,0 +1,175 @@
|
||||
Use in C# {#flatbuffers_guide_use_c-sharp}
|
||||
==============
|
||||
|
||||
## Before you get started
|
||||
|
||||
Before diving into the FlatBuffers usage in C#, it should be noted that
|
||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to
|
||||
general FlatBuffers usage in all of the supported languages (including C#).
|
||||
This page is designed to cover the nuances of FlatBuffers usage,
|
||||
specific to C#.
|
||||
|
||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
||||
documentation to build `flatc` and should be familiar with
|
||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
||||
|
||||
## FlatBuffers C-sharp code location
|
||||
|
||||
The code for the FlatBuffers C# library can be found at
|
||||
`flatbuffers/net/FlatBuffers`. You can browse the library on the
|
||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/net/
|
||||
FlatBuffers).
|
||||
|
||||
## Testing the FlatBuffers C-sharp libraries
|
||||
|
||||
The code to test the libraries can be found at `flatbuffers/tests`.
|
||||
|
||||
The test code for C# is located in the [FlatBuffers.Test](https://github.com/
|
||||
google/flatbuffers/tree/master/tests/FlatBuffers.Test) subfolder. To run the
|
||||
tests, open `FlatBuffers.Test.csproj` in [Visual Studio](
|
||||
https://www.visualstudio.com), and compile/run the project.
|
||||
|
||||
Optionally, you can run this using [Mono](http://www.mono-project.com/) instead.
|
||||
Once you have installed `Mono`, you can run the tests from the command line
|
||||
by running the following commands from inside the `FlatBuffers.Test` folder:
|
||||
|
||||
~~~{.sh}
|
||||
mcs *.cs ../MyGame/Example/*.cs ../../net/FlatBuffers/*.cs
|
||||
mono Assert.exe
|
||||
~~~
|
||||
|
||||
## Using the FlatBuffers C# library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers in C#.*
|
||||
|
||||
FlatBuffers supports reading and writing binary FlatBuffers in C#.
|
||||
|
||||
To use FlatBuffers in your own code, first generate C# classes from your
|
||||
schema with the `--csharp` option to `flatc`.
|
||||
Then you can include both FlatBuffers and the generated code to read
|
||||
or write a FlatBuffer.
|
||||
|
||||
For example, here is how you would read a FlatBuffer binary file in C#:
|
||||
First, import the library and generated code. Then, you read a FlatBuffer binary
|
||||
file into a `byte[]`. You then turn the `byte[]` into a `ByteBuffer`, which you
|
||||
pass to the `GetRootAsMyRootType` function:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
using MyGame.Example;
|
||||
using FlatBuffers;
|
||||
|
||||
// This snippet ignores exceptions for brevity.
|
||||
byte[] data = File.ReadAllBytes("monsterdata_test.mon");
|
||||
|
||||
ByteBuffer bb = new ByteBuffer(data);
|
||||
Monster monster = Monster.GetRootAsMonster(bb);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Now you can access the data from the `Monster monster`:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
short hp = monster.Hp;
|
||||
Vec3 pos = monster.Pos;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
C# code naming follows standard C# style with `PascalCasing` identifiers,
|
||||
e.g. `GetRootAsMyRootType`. Also, values (except vectors and unions) are
|
||||
available as properties instead of parameterless accessor methods.
|
||||
The performance-enhancing methods to which you can pass an already created
|
||||
object are prefixed with `Get`, e.g.:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
// property
|
||||
var pos = monster.Pos;
|
||||
|
||||
// method filling a preconstructed object
|
||||
var preconstructedPos = new Vec3();
|
||||
monster.GetPos(preconstructedPos);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
## Storing dictionaries in a FlatBuffer
|
||||
|
||||
FlatBuffers doesn't support dictionaries natively, but there is support to
|
||||
emulate their behavior with vectors and binary search, which means you
|
||||
can have fast lookups directly from a FlatBuffer without having to unpack
|
||||
your data into a `Dictionary` or similar.
|
||||
|
||||
To use it:
|
||||
- Designate one of the fields in a table as the "key" field. You do this
|
||||
by setting the `key` attribute on this field, e.g.
|
||||
`name:string (key)`.
|
||||
You may only have one key field, and it must be of string or scalar type.
|
||||
- Write out tables of this type as usual, collect their offsets in an
|
||||
array.
|
||||
- Instead of calling standard generated method,
|
||||
e.g.: `Monster.createTestarrayoftablesVector`,
|
||||
call `CreateSortedVectorOfMonster` in C#
|
||||
which will first sort all offsets such that the tables they refer to
|
||||
are sorted by the key field, then serialize it.
|
||||
- Now when you're accessing the FlatBuffer, you can use
|
||||
the `ByKey` accessor to access elements of the vector, e.g.:
|
||||
`monster.TestarrayoftablesByKey("Frodo")` in C#,
|
||||
which returns an object of the corresponding table type,
|
||||
or `null` if not found.
|
||||
`ByKey` performs a binary search, so should have a similar
|
||||
speed to `Dictionary`, though may be faster because of better caching.
|
||||
`ByKey` only works if the vector has been sorted, it will
|
||||
likely not find elements if it hasn't been sorted.
|
||||
|
||||
## Text parsing
|
||||
|
||||
There currently is no support for parsing text (Schema's and JSON) directly
|
||||
from C#, though you could use the C++ parser through native call
|
||||
interfaces available to each language. Please see the
|
||||
C++ documentation for more on text parsing.
|
||||
|
||||
## Object based API
|
||||
|
||||
FlatBuffers is all about memory efficiency, which is why its base API is written
|
||||
around using as little as possible of it. This does make the API clumsier
|
||||
(requiring pre-order construction of all data, and making mutation harder).
|
||||
|
||||
For times when efficiency is less important a more convenient object based API
|
||||
can be used (through `--gen-object-api`) that is able to unpack & pack a
|
||||
FlatBuffer into objects and standard System.Collections.Generic containers, allowing for convenient
|
||||
construction, access and mutation.
|
||||
|
||||
To use:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
// Deserialize from buffer into object.
|
||||
MonsterT monsterobj = GetMonster(flatbuffer).UnPack();
|
||||
|
||||
// Update object directly like a C# class instance.
|
||||
Console.WriteLine(monsterobj.Name);
|
||||
monsterobj.Name = "Bob"; // Change the name.
|
||||
|
||||
// Serialize into new flatbuffer.
|
||||
FlatBufferBuilder fbb = new FlatBufferBuilder(1);
|
||||
fbb.Finish(Monster.Pack(fbb, monsterobj).Value);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
### Json Serialization
|
||||
|
||||
An additional feature of the object API is the ability to allow you to
|
||||
serialize & deserialize a JSON text.
|
||||
To use Json Serialization, add `--gen-json-serializer` option to `flatc` and
|
||||
add `Newtonsoft.Json` nuget package to csproj.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
// Deserialize MonsterT from json
|
||||
string jsonText = File.ReadAllText(@"Resources/monsterdata_test.json");
|
||||
MonsterT mon = MonsterT.DeserializeFromJson(jsonText);
|
||||
|
||||
// Serialize MonsterT to json
|
||||
string jsonText2 = mon.SerializeToJson();
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* Limitation
|
||||
* `hash` attribute currentry not supported.
|
||||
* NuGet package Dependency
|
||||
* [Newtonsoft.Json](https://github.com/JamesNK/Newtonsoft.Json)
|
||||
|
||||
<br>
|
||||
@@ -16,7 +16,7 @@ documentation to build `flatc` and should be familiar with
|
||||
|
||||
## FlatBuffers Dart library code location
|
||||
|
||||
The code for the FlatBuffers Go library can be found at
|
||||
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).
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ FlatBuffers {#flatbuffers_index}
|
||||
# Overview {#flatbuffers_overview}
|
||||
|
||||
[FlatBuffers](@ref flatbuffers_overview) is an efficient cross platform
|
||||
serialization library for C++, C#, C, Go, Java, JavaScript, Lobster, Lua, TypeScript, PHP, Python, and Rust.
|
||||
serialization library for C++, C#, C, Go, Java, Kotlin, JavaScript, Lobster, Lua, TypeScript, PHP, Python, Rust and Swift.
|
||||
It was originally created at Google for game development and other
|
||||
performance-critical applications.
|
||||
|
||||
@@ -51,7 +51,7 @@ under the Apache license, v2 (see LICENSE.txt).
|
||||
needed (faster and more memory efficient than other JSON
|
||||
parsers).
|
||||
|
||||
Java and Go code supports object-reuse. C# has efficient struct based
|
||||
Java, Kotlin and Go code supports object-reuse. C# has efficient struct based
|
||||
accessors.
|
||||
|
||||
- **Cross platform code with no dependencies** - C++ code will work
|
||||
@@ -108,7 +108,7 @@ sections provide a more in-depth usage guide.
|
||||
present for every object instance.
|
||||
|
||||
- Use `flatc` (the FlatBuffer compiler) to generate a C++ header (or
|
||||
Java/C#/Go/Python.. classes) with helper classes to access and construct
|
||||
Java/Kotlin/C#/Go/Python.. classes) with helper classes to access and construct
|
||||
serialized data. This header (say `mydata_generated.h`) only depends on
|
||||
`flatbuffers.h`, which defines the core functionality.
|
||||
|
||||
@@ -130,8 +130,12 @@ sections provide a more in-depth usage guide.
|
||||
- How to [write a schema](@ref flatbuffers_guide_writing_schema).
|
||||
- How to [use the generated C++ code](@ref flatbuffers_guide_use_cpp) in your
|
||||
own programs.
|
||||
- How to [use the generated Java/C# code](@ref flatbuffers_guide_use_java_c-sharp)
|
||||
- How to [use the generated Java code](@ref flatbuffers_guide_use_java)
|
||||
in your own programs.
|
||||
- How to [use the generated C# code](@ref flatbuffers_guide_use_c-sharp)
|
||||
in your own programs.
|
||||
- How to [use the generated Kotlin code](@ref flatbuffers_guide_use_kotlin)
|
||||
in your own programs.
|
||||
- How to [use the generated Go code](@ref flatbuffers_guide_use_go) in your
|
||||
own programs.
|
||||
- How to [use the generated Lua code](@ref flatbuffers_guide_use_lua) in your
|
||||
@@ -146,6 +150,8 @@ sections provide a more in-depth usage guide.
|
||||
own programs.
|
||||
- How to [use the generated Rust code](@ref flatbuffers_guide_use_rust) in your
|
||||
own programs.
|
||||
- How to [use the generated Swift code](@ref flatbuffers_guide_use_swift) in your
|
||||
own programs.
|
||||
- [Support matrix](@ref flatbuffers_support) for platforms/languages/features.
|
||||
- Some [benchmarks](@ref flatbuffers_benchmarks) showing the advantage of
|
||||
using FlatBuffers.
|
||||
@@ -161,6 +167,7 @@ sections provide a more in-depth usage guide.
|
||||
- [GitHub repository](http://github.com/google/flatbuffers)
|
||||
- [Landing page](http://google.github.io/flatbuffers)
|
||||
- [FlatBuffers Google Group](https://groups.google.com/forum/#!forum/flatbuffers)
|
||||
- [Discord](https://discord.gg/6qgKs3R) and [Gitter](https://gitter.im/lobster_programming_language/community) chat.
|
||||
- [FlatBuffers Issues Tracker](http://github.com/google/flatbuffers/issues)
|
||||
- Independent implementations & tools:
|
||||
- [FlatCC](https://github.com/dvidelabs/flatcc) Alternative FlatBuffers
|
||||
@@ -176,3 +183,6 @@ sections provide a more in-depth usage guide.
|
||||
- [FlatBuffers in Android](http://frogermcs.github.io/flatbuffers-in-android-introdution/)
|
||||
- [Parsing JSON to FlatBuffers in Java](http://frogermcs.github.io/json-parsing-with-flatbuffers-in-android/)
|
||||
- [FlatBuffers in Unity](http://exiin.com/blog/flatbuffers-for-unity-sample-code/)
|
||||
- [FlexBuffers C#](https://github.com/mzaks/FlexBuffers-CSharp) and
|
||||
[article](https://medium.com/@icex33/flexbuffers-for-unity3d-4d1ab5c53fbe?)
|
||||
on its use.
|
||||
|
||||
@@ -29,9 +29,7 @@ FlexBuffers is still slower than regular FlatBuffers though, so we recommend to
|
||||
only use it if you need it.
|
||||
|
||||
|
||||
# Usage
|
||||
|
||||
This is for C++, other languages may follow.
|
||||
# Usage in C++
|
||||
|
||||
Include the header `flexbuffers.h`, which in turn depends on `flatbuffers.h`
|
||||
and `util.h`.
|
||||
@@ -98,10 +96,10 @@ allows a single type, and uses a bit less memory.
|
||||
`IndirectFloat` is an interesting feature that allows you to store values
|
||||
by offset rather than inline. Though that doesn't make any visible change
|
||||
to the user, the consequence is that large values (especially doubles or
|
||||
64 bit ints) that occur more than once can be shared. Another use case is
|
||||
inside of vectors, where the largest element makes up the size of all elements
|
||||
(e.g. a single double forces all elements to 64bit), so storing a lot of small
|
||||
integers together with a double is more efficient if the double is indirect.
|
||||
64 bit ints) that occur more than once can be shared (see ReuseValue).
|
||||
Another use case is inside of vectors, where the largest element makes
|
||||
up the size of all elements (e.g. a single double forces all elements to
|
||||
64bit), so storing a lot of small integers together with a double is more efficient if the double is indirect.
|
||||
|
||||
Accessing it:
|
||||
|
||||
@@ -122,6 +120,46 @@ map["unknown"].IsNull(); // true
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
# Usage in Java
|
||||
|
||||
Java implementation follows the C++ one, closely.
|
||||
|
||||
For creating the equivalent of the same JSON `{ vec: [ -100, "Fred", 4.0 ], foo: 100 }`,
|
||||
one could use the following code:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
|
||||
FlexBuffersBuilder builder = new FlexBuffersBuilder(ByteBuffer.allocate(512),
|
||||
FlexBuffersBuilder.BUILDER_FLAG_SHARE_KEYS_AND_STRINGS);
|
||||
int smap = builder.startMap();
|
||||
int svec = builder.startVector();
|
||||
builder.putInt(-100);
|
||||
builder.putString("Fred");
|
||||
builder.putFloat(4.0);
|
||||
builder.endVector("vec", svec, false, false);
|
||||
builder.putInt("foo", 100);
|
||||
builder.endMap(null, smap);
|
||||
ByteBuffer bb = builder.finish();
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Similarly, to read the data, just:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
|
||||
FlexBuffers.Map map = FlexBuffers.getRoot(bb).asMap();
|
||||
map.size(); // 2
|
||||
FlexBuffers.Vector vec = map.get("vec").asVector();
|
||||
vec.size(); // 3
|
||||
vec.get(0).asLong(); // -100;
|
||||
vec.get(1).asString(); // "Fred";
|
||||
vec.get(1).asLong(); // 0 (Number parsing failed).
|
||||
vec.get(2).asFloat(); // 4.0
|
||||
vec.get(2).asString().isEmpty(); // true (Wrong Type).
|
||||
vec.get(2).asString(); // "" (This still works though).
|
||||
vec.get(2).toString(); // "4.0" (Or have it converted).
|
||||
map.get("foo").asUInt(); // 100
|
||||
map.get("unknown").isNull(); // true
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
# Binary encoding
|
||||
|
||||
A description of how FlexBuffers are encoded is in the
|
||||
|
||||
@@ -14,7 +14,7 @@ attribute\_decl = `attribute` ident | `"`ident`"` `;`
|
||||
|
||||
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 ) `}`
|
||||
|
||||
root\_decl = `root_type` ident `;`
|
||||
@@ -49,11 +49,26 @@ file_extension_decl = `file_extension` 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 = `\".*?\"`
|
||||
|
||||
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`)
|
||||
|
||||
@@ -15,6 +15,12 @@ all commonly used CPUs today. FlatBuffers will also work on big-endian
|
||||
machines, but will be slightly slower because of additional
|
||||
byte-swap intrinsics.
|
||||
|
||||
It is assumed that the following conditions are met, to ensure
|
||||
cross-platform interoperability:
|
||||
- The binary `IEEE-754` format is used for floating-point numbers.
|
||||
- The `two's complemented` representation is used for signed integers.
|
||||
- The endianness is the same for floating-point numbers as for integers.
|
||||
|
||||
On purpose, the format leaves a lot of details about where exactly
|
||||
things live in memory undefined, e.g. fields in a table can have any
|
||||
order, and objects to some extent can be stored in many orders. This is
|
||||
|
||||
@@ -1,41 +1,30 @@
|
||||
Use in Java/C# {#flatbuffers_guide_use_java_c-sharp}
|
||||
Use in Java {#flatbuffers_guide_use_java}
|
||||
==============
|
||||
|
||||
## Before you get started
|
||||
|
||||
Before diving into the FlatBuffers usage in Java or C#, it should be noted that
|
||||
Before diving into the FlatBuffers usage in Java, it should be noted that
|
||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to
|
||||
general FlatBuffers usage in all of the supported languages (including both Java
|
||||
and C#). This page is designed to cover the nuances of FlatBuffers usage,
|
||||
specific to Java and C#.
|
||||
general FlatBuffers usage in all of the supported languages (including Java).
|
||||
This page is designed to cover the nuances of FlatBuffers usage,
|
||||
specific to Java.
|
||||
|
||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
||||
documentation to build `flatc` and should be familiar with
|
||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
||||
|
||||
## FlatBuffers Java and C-sharp code location
|
||||
|
||||
#### Java
|
||||
## FlatBuffers Java code location
|
||||
|
||||
The code for the FlatBuffers Java library can be found at
|
||||
`flatbuffers/java/com/google/flatbuffers`. You can browse the library on the
|
||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/
|
||||
java/com/google/flatbuffers).
|
||||
|
||||
#### C-sharp
|
||||
|
||||
The code for the FlatBuffers C# library can be found at
|
||||
`flatbuffers/net/FlatBuffers`. You can browse the library on the
|
||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/net/
|
||||
FlatBuffers).
|
||||
|
||||
## Testing the FlatBuffers Java and C-sharp libraries
|
||||
## Testing the FlatBuffers Java libraries
|
||||
|
||||
The code to test the libraries can be found at `flatbuffers/tests`.
|
||||
|
||||
#### Java
|
||||
|
||||
The test code for Java is located in [JavaTest.java](https://github.com/google
|
||||
/flatbuffers/blob/master/tests/JavaTest.java).
|
||||
|
||||
@@ -47,31 +36,15 @@ system.
|
||||
*Note: These scripts require that [Java](https://www.oracle.com/java/index.html)
|
||||
is installed.*
|
||||
|
||||
#### C-sharp
|
||||
|
||||
The test code for C# is located in the [FlatBuffers.Test](https://github.com/
|
||||
google/flatbuffers/tree/master/tests/FlatBuffers.Test) subfolder. To run the
|
||||
tests, open `FlatBuffers.Test.csproj` in [Visual Studio](
|
||||
https://www.visualstudio.com), and compile/run the project.
|
||||
|
||||
Optionally, you can run this using [Mono](http://www.mono-project.com/) instead.
|
||||
Once you have installed `Mono`, you can run the tests from the command line
|
||||
by running the following commands from inside the `FlatBuffers.Test` folder:
|
||||
|
||||
~~~{.sh}
|
||||
mcs *.cs ../MyGame/Example/*.cs ../../net/FlatBuffers/*.cs
|
||||
mono Assert.exe
|
||||
~~~
|
||||
|
||||
## Using the FlatBuffers Java (and C#) library
|
||||
## Using the FlatBuffers Java library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers in Java or C#.*
|
||||
example of how to use FlatBuffers in Java.*
|
||||
|
||||
FlatBuffers supports reading and writing binary FlatBuffers in Java and C#.
|
||||
FlatBuffers supports reading and writing binary FlatBuffers in Java.
|
||||
|
||||
To use FlatBuffers in your own code, first generate Java classes from your
|
||||
schema with the `--java` option to `flatc`. (Or for C# with `--csharp`).
|
||||
schema with the `--java` option to `flatc`.
|
||||
Then you can include both FlatBuffers and the generated code to read
|
||||
or write a FlatBuffer.
|
||||
|
||||
@@ -80,11 +53,6 @@ First, import the library and generated code. Then, you read a FlatBuffer binary
|
||||
file into a `byte[]`. You then turn the `byte[]` into a `ByteBuffer`, which you
|
||||
pass to the `getRootAsMyRootType` function:
|
||||
|
||||
*Note: The code here is written from the perspective of Java. Code for both
|
||||
languages is both generated and used in nearly the exact same way, with only
|
||||
minor differences. These differences are
|
||||
[explained in a section below](#differences_in_c-sharp).*
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.java}
|
||||
import MyGame.Example.*;
|
||||
import com.google.flatbuffers.FlatBufferBuilder;
|
||||
@@ -107,30 +75,6 @@ Now you can access the data from the `Monster monster`:
|
||||
Vec3 pos = monster.pos();
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
<a name="differences_in_c-sharp">
|
||||
#### Differences in C-sharp
|
||||
</a>
|
||||
|
||||
C# code works almost identically to Java, with only a few minor differences.
|
||||
You can see an example of C# code in
|
||||
`tests/FlatBuffers.Test/FlatBuffersExampleTests.cs` or
|
||||
`samples/SampleBinary.cs`.
|
||||
|
||||
First of all, naming follows standard C# style with `PascalCasing` identifiers,
|
||||
e.g. `GetRootAsMyRootType`. Also, values (except vectors and unions) are
|
||||
available as properties instead of parameterless accessor methods as in Java.
|
||||
The performance-enhancing methods to which you can pass an already created
|
||||
object are prefixed with `Get`, e.g.:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cs}
|
||||
// property
|
||||
var pos = monster.Pos;
|
||||
|
||||
// method filling a preconstructed object
|
||||
var preconstructedPos = new Vec3();
|
||||
monster.GetPos(preconstructedPos);
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
## Storing dictionaries in a FlatBuffer
|
||||
|
||||
FlatBuffers doesn't support dictionaries natively, but there is support to
|
||||
@@ -147,14 +91,12 @@ To use it:
|
||||
array.
|
||||
- Instead of calling standard generated method,
|
||||
e.g.: `Monster.createTestarrayoftablesVector`,
|
||||
call `CreateSortedVectorOfMonster` in C# or
|
||||
`createSortedVectorOfTables` (from the `FlatBufferBuilder` object) in Java,
|
||||
call `createSortedVectorOfTables` (from the `FlatBufferBuilder` object).
|
||||
which will first sort all offsets such that the tables they refer to
|
||||
are sorted by the key field, then serialize it.
|
||||
- Now when you're accessing the FlatBuffer, you can use
|
||||
the `ByKey` accessor to access elements of the vector, e.g.:
|
||||
`monster.testarrayoftablesByKey("Frodo")` in Java or
|
||||
`monster.TestarrayoftablesByKey("Frodo")` in C#,
|
||||
`monster.testarrayoftablesByKey("Frodo")`.
|
||||
which returns an object of the corresponding table type,
|
||||
or `null` if not found.
|
||||
`ByKey` performs a binary search, so should have a similar
|
||||
@@ -165,7 +107,7 @@ To use it:
|
||||
## Text parsing
|
||||
|
||||
There currently is no support for parsing text (Schema's and JSON) directly
|
||||
from Java or C#, though you could use the C++ parser through native call
|
||||
from Java, though you could use the C++ parser through native call
|
||||
interfaces available to each language. Please see the
|
||||
C++ documentation for more on text parsing.
|
||||
|
||||
84
docs/source/KotlinUsage.md
Normal file
84
docs/source/KotlinUsage.md
Normal file
@@ -0,0 +1,84 @@
|
||||
Use in Kotlin {#flatbuffers_guide_use_kotlin}
|
||||
==============
|
||||
|
||||
## Before you get started
|
||||
|
||||
Before diving into the FlatBuffers usage in Kotlin, it should be noted that
|
||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to
|
||||
general FlatBuffers usage in all of the supported languages (including K).
|
||||
|
||||
This page is designed to cover the nuances of FlatBuffers usage, specific to Kotlin.
|
||||
|
||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
||||
documentation to build `flatc` and should be familiar with
|
||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
||||
|
||||
## Kotlin and FlatBuffers Java code location
|
||||
|
||||
Code generated for Kotlin currently uses the flatbuffers java runtime library. That means that Kotlin generated code can only have Java virtual machine as target architecture (which includes Android). Kotlin Native and Kotlin.js are currently not supported.
|
||||
|
||||
The code for the FlatBuffers Java library can be found at
|
||||
`flatbuffers/java/com/google/flatbuffers`. You can browse the library on the
|
||||
[FlatBuffers GitHub page](https://github.com/google/flatbuffers/tree/master/
|
||||
java/com/google/flatbuffers).
|
||||
|
||||
## Testing FlatBuffers Kotlin
|
||||
|
||||
The test code for Java is located in [KotlinTest.java](https://github.com/google
|
||||
/flatbuffers/blob/master/tests/KotlinTest.kt).
|
||||
|
||||
To run the tests, use [KotlinTest.sh](https://github.com/google/
|
||||
flatbuffers/blob/master/tests/KotlinTest.sh) shell script.
|
||||
|
||||
*Note: These scripts require that [Kotlin](https://kotlinlang.org/) is installed.*
|
||||
|
||||
## Using the FlatBuffers Kotlin library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers in Kotlin.*
|
||||
|
||||
FlatBuffers supports reading and writing binary FlatBuffers in Kotlin.
|
||||
|
||||
To use FlatBuffers in your own code, first generate Java classes from your
|
||||
schema with the `--kotlin` option to `flatc`.
|
||||
Then you can include both FlatBuffers and the generated code to read
|
||||
or write a FlatBuffer.
|
||||
|
||||
For example, here is how you would read a FlatBuffer binary file in Kotlin:
|
||||
First, import the library and generated code. Then, you read a FlatBuffer binary
|
||||
file into a `ByteArray`. You then turn the `ByteArray` into a `ByteBuffer`, which you
|
||||
pass to the `getRootAsMyRootType` function:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.kt}
|
||||
import MyGame.Example.*
|
||||
import com.google.flatbuffers.FlatBufferBuilder
|
||||
|
||||
// This snippet ignores exceptions for brevity.
|
||||
val data = RandomAccessFile(File("monsterdata_test.mon"), "r").use {
|
||||
val temp = ByteArray(it.length().toInt())
|
||||
it.readFully(temp)
|
||||
temp
|
||||
}
|
||||
|
||||
val bb = ByteBuffer.wrap(data)
|
||||
val monster = Monster.getRootAsMonster(bb)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Now you can access the data from the `Monster monster`:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.kt}
|
||||
val hp = monster.hp
|
||||
val pos = monster.pos!!;
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
|
||||
## Differences between Kotlin and Java code
|
||||
|
||||
Kotlin generated code was designed to be as close as possible to the java counterpart, as for now, we only support kotlin on java virtual machine. So the differences in implementation and usage are basically the ones introduced by the Kotlin language itself. You can find more in-depth information [here](https://kotlinlang.org/docs/reference/comparison-to-java.html).
|
||||
|
||||
The most obvious ones are:
|
||||
|
||||
* Fields as accessed as Kotlin [properties](https://kotlinlang.org/docs/reference/properties.html)
|
||||
* Static methods are accessed in [companion object](https://kotlinlang.org/docs/reference/classes.html#companion-objects)
|
||||
@@ -18,7 +18,8 @@ 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`), you can now start using this in
|
||||
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`.
|
||||
|
||||
@@ -67,6 +68,7 @@ It can be run by `cd`ing to the `rust_usage_test` directory and executing: `carg
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.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;
|
||||
@@ -163,4 +165,10 @@ 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
|
||||
|
||||
Built-in scalar types are
|
||||
Built-in scalar types are
|
||||
|
||||
- 8 bit: `byte` (`int8`), `ubyte` (`uint8`), `bool`
|
||||
|
||||
@@ -114,6 +114,27 @@ of same-size data where a `reinterpret_cast` would give you a desirable result,
|
||||
e.g. you could change a `uint` to an `int` if no values in current data use the
|
||||
high bit yet.
|
||||
|
||||
### Arrays
|
||||
|
||||
Arrays are a convenience short-hand for a fixed-length collection of elements.
|
||||
Arrays can be used to replace the following schema:
|
||||
|
||||
struct Vec3 {
|
||||
x:float;
|
||||
y:float;
|
||||
z:float;
|
||||
}
|
||||
|
||||
with the following schema:
|
||||
|
||||
struct Vec3 {
|
||||
v:[float:3];
|
||||
}
|
||||
|
||||
Both representations are binary equivalent.
|
||||
|
||||
Arrays are currently only supported in a `struct`.
|
||||
|
||||
### (Default) Values
|
||||
|
||||
Values are a sequence of digits. Values may be optionally followed by a decimal
|
||||
@@ -141,6 +162,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
|
||||
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
|
||||
deprecation for enums). This requires code to handle forwards compatibility
|
||||
itself, by handling unknown enum values.
|
||||
@@ -150,9 +174,23 @@ itself, by handling unknown enum values.
|
||||
Unions share a lot of properties with enums, but instead of new names
|
||||
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
|
||||
additionally a hidden field with the suffix `_type` is generated that
|
||||
holds the corresponding enum value, allowing you to know which type to
|
||||
cast to at runtime.
|
||||
additionally a field with the suffix `_type` is generated that holds
|
||||
the corresponding enum value, allowing you to know which type to cast
|
||||
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.
|
||||
Note that because a union field is really two fields, it must always be
|
||||
@@ -304,8 +342,14 @@ Current understood attributes:
|
||||
these structs to be aligned to that amount inside a buffer, IF that
|
||||
buffer is allocated with that alignment (which is not necessarily
|
||||
the case for buffers accessed directly inside a `FlatBufferBuilder`).
|
||||
- `bit_flags` (on an enum): the values of this field indicate bits,
|
||||
meaning that any value N specified in the schema will end up
|
||||
Note: currently not guaranteed to have an effect when used with
|
||||
`--object-api`, since that may allocate objects at alignments less than
|
||||
what you specify with `force_align`.
|
||||
- `force_align: size` (on a vector): force the alignment of this vector to be
|
||||
something different than what the element size would normally dictate.
|
||||
Note: Now only work for generated C++ code.
|
||||
- `bit_flags` (on an unsigned enum): the values of this field indicate bits,
|
||||
meaning that any unsigned value N specified in the schema will end up
|
||||
representing 1<<N, or if you don't specify values at all, you'll get
|
||||
the sequence 1, 2, 4, 8, ...
|
||||
- `nested_flatbuffer: "table_name"` (on a field): this indicates that the field
|
||||
@@ -385,6 +429,36 @@ When parsing JSON, it recognizes the following escape codes in strings:
|
||||
It also generates these escape codes back again when generating JSON from a
|
||||
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
|
||||
floating-point literals as well:
|
||||
`[-1.0, 2., .3e0, 3.e4, 0x21.34p-5, -inf, nan]`.
|
||||
|
||||
The following conventions for floating-point numbers are used:
|
||||
- The exponent suffix of hexadecimal floating-point number is mandatory.
|
||||
- Parsed `NaN` converted to unsigned IEEE-754 `quiet-NaN` value.
|
||||
|
||||
Extended floating-point support was tested with:
|
||||
- x64 Windows: `MSVC2015` and higher.
|
||||
- x64 Linux: `LLVM 6.0`, `GCC 4.9` and higher.
|
||||
|
||||
For details, see [Use in C++](@ref flatbuffers_guide_use_cpp) section.
|
||||
|
||||
- For compatibility with a JSON lint tool all numeric literals of scalar
|
||||
fields can be wrapped to quoted string:
|
||||
`"1", "2.0", "0x48A", "0x0C.0Ep-1", "-inf", "true"`.
|
||||
|
||||
## Guidelines
|
||||
|
||||
### Efficiency
|
||||
@@ -492,7 +566,7 @@ with the new schema now cannot read nor write `a` anymore (any existing code
|
||||
that tries to do so will result in compile errors), but can still read
|
||||
old data (they will ignore the field).
|
||||
|
||||
table { c:int a:int; b:int; }
|
||||
table { c:int; a:int; b:int; }
|
||||
|
||||
This is NOT ok, as this makes the schemas incompatible. Old code reading newer
|
||||
data will interpret `c` as if it was `a`, and new code reading old data
|
||||
|
||||
@@ -18,23 +18,23 @@ In general:
|
||||
|
||||
NOTE: this table is a start, it needs to be extended.
|
||||
|
||||
Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Dart | Lobster | Rust
|
||||
------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ------- | ------- | ----
|
||||
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | Yes | Yes | Yes
|
||||
JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No | Yes | No
|
||||
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No | No
|
||||
Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No | No
|
||||
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No | No
|
||||
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | Yes | Yes | Yes
|
||||
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | No | No | Yes
|
||||
Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ? | Great | Superb
|
||||
Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | Yes | Yes | Yes
|
||||
Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes
|
||||
Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes
|
||||
Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ?
|
||||
Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ?
|
||||
Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ? | No | ?
|
||||
Primary authors (github) | aard* | aard* | ev*/js*| rw | rw | evanw/ev* | kr* | mik* | ch* | dnfield | aard* | rw
|
||||
Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Dart | Lobster | Rust | Swift
|
||||
------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ------- | ------- | ------- | ------
|
||||
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | Yes | Yes | Yes | Yes
|
||||
JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No | Yes | No | No
|
||||
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No | No | No | No
|
||||
Reflection | Yes | No | No | No | No | No | No | Basic | No | No | No | No | No
|
||||
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No | No | No | No
|
||||
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | Yes | Yes | Yes | Yes
|
||||
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | No | No | Yes | No
|
||||
Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ? | Great | Superb | ?
|
||||
Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | Yes | Yes | Yes | No
|
||||
Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes | Yes
|
||||
Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | Yes | Yes | Yes | Yes
|
||||
Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ? | No
|
||||
Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | Flutter | Yes | ? | Yes
|
||||
Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ? | No | ? | No
|
||||
Primary authors (github) | aard* | aard* | ev*/js*| rw | rw | evanw/ev* | kr* | mik* | ch* | dnfield | aard* | rw | mi*/mz*
|
||||
|
||||
* aard = aardappel (previously: gwvo)
|
||||
* ev = evolutional
|
||||
@@ -42,5 +42,7 @@ Primary authors (github) | aard* | aard* | ev*/js*| rw | rw | ev
|
||||
* mik = mikkelfj
|
||||
* ch = chobie
|
||||
* kr = krojew
|
||||
* mi = mustiikhalil
|
||||
* mz = mzaks
|
||||
|
||||
<br>
|
||||
|
||||
91
docs/source/SwiftUsage.md
Normal file
91
docs/source/SwiftUsage.md
Normal file
@@ -0,0 +1,91 @@
|
||||
Use in Swift {#flatbuffers_guide_use_swift}
|
||||
=========
|
||||
|
||||
## Before you get started
|
||||
|
||||
Before diving into the FlatBuffers usage in Swift, it should be noted that
|
||||
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide
|
||||
to general FlatBuffers usage in all of the supported languages (including Swift).
|
||||
This page is designed to cover the nuances of FlatBuffers usage, specific to
|
||||
Swift.
|
||||
|
||||
You should also have read the [Building](@ref flatbuffers_guide_building)
|
||||
documentation to build `flatc` and should be familiar with
|
||||
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
|
||||
[Writing a schema](@ref flatbuffers_guide_writing_schema).
|
||||
|
||||
## FlatBuffers Swift library code location
|
||||
|
||||
The code for the FlatBuffers Swift library can be found at
|
||||
`flatbuffers/swift`. You can browse the library code on the [FlatBuffers
|
||||
GitHub page](https://github.com/google/flatbuffers/tree/master/swift).
|
||||
|
||||
## Testing the FlatBuffers Swift library
|
||||
|
||||
The code to test the Swift library can be found at `flatbuffers/Flatbuffers.Test.Swift`.
|
||||
The test code itself is located in [Flatbuffers.Test.Swift](https://github.com/google/flatbuffers/blob/master/tests/FlatBuffers.Test.Swift).
|
||||
|
||||
To run the tests, use the [SwiftTest.sh](https://github.com/google/flatbuffers/blob/master/tests/FlatBuffers.Test.Swift/SwiftTest.sh) shell script.
|
||||
|
||||
*Note: The shell script requires [Swift](https://swift.org) to
|
||||
be installed.*
|
||||
|
||||
## Using the FlatBuffers Swift library
|
||||
|
||||
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
|
||||
example of how to use FlatBuffers in Swift.*
|
||||
|
||||
FlatBuffers supports reading and writing binary FlatBuffers in Swift.
|
||||
|
||||
To use FlatBuffers in your own code, first generate Swift structs from your
|
||||
schema with the `--swift` option to `flatc`. Then include FlatBuffers using `SPM` in
|
||||
by adding the path to `FlatBuffers/swift` into it. The generated code should also be
|
||||
added to xcode or the path of the package you will be using. Note: sometimes xcode cant
|
||||
and wont see the generated files, so it's better that you copy them to xcode.
|
||||
|
||||
For example, here is how you would read a FlatBuffer binary file in Swift: First,
|
||||
include the library and copy thegenerated code. Then read a FlatBuffer binary file or
|
||||
a data object from the server, which you can pass into the `GetRootAsMonster` function.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift}
|
||||
import FlatBuffers
|
||||
|
||||
typealias Monster1 = MyGame.Sample.Monster
|
||||
typealias Vec3 = MyGame.Sample.Vec3
|
||||
|
||||
let path = FileManager.default.currentDirectoryPath
|
||||
let url = URL(fileURLWithPath: path, isDirectory: true).appendingPathComponent("monsterdata_test").appendingPathExtension("mon")
|
||||
guard let data = try? Data(contentsOf: url) else { return }
|
||||
|
||||
let monster = Monster.getRootAsMonster(bb: ByteBuffer(data: data))
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Now you can access values like this:
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift}
|
||||
let hp = monster.hp
|
||||
let pos = monster.pos
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
In some cases it's necessary to modify values in an existing FlatBuffer in place (without creating a copy). For this reason, scalar fields of a Flatbuffer table or struct can be mutated.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.swift}
|
||||
let monster = Monster.getRootAsMonster(bb: ByteBuffer(data: data))
|
||||
|
||||
if !monster.mutate(hp: 10) {
|
||||
fatalError("couldn't mutate")
|
||||
}
|
||||
// mutate a struct field
|
||||
let vec = monster.pos.mutate(z: 4)
|
||||
|
||||
// This mutation will fail because the mana field is not available in
|
||||
// the buffer. It should be set when creating the buffer.
|
||||
if !monster.mutate(mana: 20) {
|
||||
fatalError("couldn't mutate")
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The term `mutate` is used instead of `set` to indicate that this is a special use case. All mutate functions return a boolean value which is false if the field we're trying to mutate is not available in the buffer.
|
||||
|
||||
<br>
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
@@ -43,7 +43,7 @@ First, include the library and generated code. Then read the file into an
|
||||
the ByteBuffer to the `getRootAsMonster` function.
|
||||
|
||||
~~~{.ts}
|
||||
// note: import flabuffers with your desired import method
|
||||
// note: import flatbuffers with your desired import method
|
||||
|
||||
import { MyGame } from './monster_generated';
|
||||
|
||||
|
||||
@@ -778,7 +778,7 @@ INPUT = "FlatBuffers.md" \
|
||||
"../../php/FlatbufferBuilder.php" \
|
||||
"../../net/FlatBuffers/FlatBufferBuilder.cs" \
|
||||
"../../include/flatbuffers/flatbuffers.h" \
|
||||
"../../go/builder.go"
|
||||
"../../go/builder.go" \
|
||||
"../../rust/flatbuffers/src/builder.rs"
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
|
||||
@@ -29,8 +29,10 @@
|
||||
title="Use in C"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_go"
|
||||
title="Use in Go"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_java_c-sharp"
|
||||
title="Use in Java/C#"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_java"
|
||||
title="Use in Java"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_c-sharp"
|
||||
title="Use in C#"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_javascript"
|
||||
title="Use in JavaScript"/>
|
||||
<tab type="user" url="@ref flatbuffers_guide_use_typescript"
|
||||
@@ -45,8 +47,10 @@
|
||||
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"
|
||||
title="Schema-less version"/>
|
||||
title="FlexBuffers (Schema-less version)"/>
|
||||
<tab type="usergroup" url="" title="gRPC">
|
||||
<tab type="user" url="@ref flatbuffers_grpc_guide_use_cpp"
|
||||
title="Use in C++"/>
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
alias(
|
||||
name = "go_default_library",
|
||||
actual = ":go",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go",
|
||||
srcs = [
|
||||
|
||||
@@ -17,6 +17,8 @@ type Builder struct {
|
||||
head UOffsetT
|
||||
nested bool
|
||||
finished bool
|
||||
|
||||
sharedStrings map[string]UOffsetT
|
||||
}
|
||||
|
||||
const fileIdentifierLength = 4
|
||||
@@ -33,7 +35,6 @@ func NewBuilder(initialSize int) *Builder {
|
||||
b.head = UOffsetT(initialSize)
|
||||
b.minalign = 1
|
||||
b.vtables = make([]UOffsetT, 0, 16) // sensible default capacity
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -307,6 +308,20 @@ func (b *Builder) EndVector(vectorNumElems int) UOffsetT {
|
||||
return b.Offset()
|
||||
}
|
||||
|
||||
// CreateSharedString Checks if the string is already written
|
||||
// to the buffer before calling CreateString
|
||||
func (b *Builder) CreateSharedString(s string) UOffsetT {
|
||||
if b.sharedStrings == nil {
|
||||
b.sharedStrings = make(map[string]UOffsetT)
|
||||
}
|
||||
if v, ok := b.sharedStrings[s]; ok {
|
||||
return v
|
||||
}
|
||||
off := b.CreateString(s)
|
||||
b.sharedStrings[s] = off
|
||||
return off
|
||||
}
|
||||
|
||||
// CreateString writes a null-terminated string as a vector.
|
||||
func (b *Builder) CreateString(s string) UOffsetT {
|
||||
b.assertNotNested()
|
||||
|
||||
15
go/grpc.go
15
go/grpc.go
@@ -3,21 +3,36 @@ package flatbuffers
|
||||
// Codec implements gRPC-go Codec which is used to encode and decode messages.
|
||||
var Codec = "flatbuffers"
|
||||
|
||||
// FlatbuffersCodec defines the interface gRPC uses to encode and decode messages. Note
|
||||
// that implementations of this interface must be thread safe; a Codec's
|
||||
// methods can be called from concurrent goroutines.
|
||||
type FlatbuffersCodec struct{}
|
||||
|
||||
// Marshal returns the wire format of v.
|
||||
func (FlatbuffersCodec) Marshal(v interface{}) ([]byte, error) {
|
||||
return v.(*Builder).FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// Unmarshal parses the wire format into v.
|
||||
func (FlatbuffersCodec) Unmarshal(data []byte, v interface{}) error {
|
||||
v.(flatbuffersInit).Init(data, GetUOffsetT(data))
|
||||
return nil
|
||||
}
|
||||
|
||||
// String old gRPC Codec interface func
|
||||
func (FlatbuffersCodec) String() string {
|
||||
return Codec
|
||||
}
|
||||
|
||||
// Name returns the name of the Codec implementation. The returned string
|
||||
// will be used as part of content type in transmission. The result must be
|
||||
// static; the result cannot change between calls.
|
||||
//
|
||||
// add Name() for ForceCodec interface
|
||||
func (FlatbuffersCodec) Name() string {
|
||||
return Codec
|
||||
}
|
||||
|
||||
type flatbuffersInit interface {
|
||||
Init(data []byte, i UOffsetT)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ grpc_1_15_1_githash=1a60e6971f428323245a930031ad267bb3142ba4
|
||||
function build_grpc () {
|
||||
git clone https://github.com/grpc/grpc.git google/grpc
|
||||
cd google/grpc
|
||||
git checkout ${grpc_1_15_1_githash}
|
||||
git checkout ${grpc_1_15_1_githash}
|
||||
git submodule update --init
|
||||
make
|
||||
make install prefix=`pwd`/install
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>com.google.flatbuffers</groupId>
|
||||
<artifactId>flatbuffers-parent</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.12.0</version>
|
||||
</parent>
|
||||
<artifactId>flatbuffers-java-grpc</artifactId>
|
||||
<name>${project.artifactId}</name>
|
||||
@@ -24,7 +24,7 @@
|
||||
</developer>
|
||||
</developers>
|
||||
<properties>
|
||||
<gRPC.version>1.9.0</gRPC.version>
|
||||
<gRPC.version>1.12.0</gRPC.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<groupId>com.google.flatbuffers</groupId>
|
||||
<artifactId>flatbuffers-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>1.10.0</version>
|
||||
<version>1.12.0</version>
|
||||
<name>flatbuffers-parent</name>
|
||||
<description>parent pom for flatbuffers java artifacts</description>
|
||||
<properties>
|
||||
@@ -185,6 +185,12 @@
|
||||
<goals>
|
||||
<goal>sign</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<gpgArguments>
|
||||
<arg>--pinentry-mode</arg>
|
||||
<arg>loopback</arg>
|
||||
</gpgArguments>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
@@ -12,7 +12,8 @@ class GreeterServiceImpl final : public Greeter::Service {
|
||||
grpc::ServerContext *context,
|
||||
const flatbuffers::grpc::Message<HelloRequest> *request_msg,
|
||||
flatbuffers::grpc::Message<HelloReply> *response_msg) override {
|
||||
// flatbuffers::grpc::MessageBuilder mb_;
|
||||
flatbuffers::grpc::MessageBuilder mb_;
|
||||
|
||||
// We call GetRoot to "parse" the message. Verification is already
|
||||
// performed by default. See the notes below for more details.
|
||||
const HelloRequest *request = request_msg->GetRoot();
|
||||
|
||||
107
grpc/src/compiler/BUILD
Normal file
107
grpc/src/compiler/BUILD
Normal file
@@ -0,0 +1,107 @@
|
||||
load("@rules_cc//cc:defs.bzl", "cc_library")
|
||||
|
||||
package(
|
||||
default_visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "common_headers",
|
||||
srcs = [
|
||||
"config.h",
|
||||
"schema_interface.h",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "cpp_generator",
|
||||
srcs = [
|
||||
"cpp_generator.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"cpp_generator.h",
|
||||
":common_headers",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
deps = [
|
||||
"//:flatbuffers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "go_generator",
|
||||
srcs = [
|
||||
"go_generator.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"go_generator.h",
|
||||
":common_headers",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
deps = [
|
||||
"//:flatbuffers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "java_generator",
|
||||
srcs = [
|
||||
"java_generator.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"java_generator.h",
|
||||
":common_headers",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
deps = [
|
||||
"//:flatbuffers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "python_generator",
|
||||
hdrs = [
|
||||
"python_generator.h",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
deps = [
|
||||
":python_generator_private",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "python_generator_private",
|
||||
srcs = [
|
||||
"python_generator.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"python_generator.h",
|
||||
"python_private_generator.h",
|
||||
":common_headers",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//:flatbuffers",
|
||||
],
|
||||
)
|
||||
|
||||
cc_library(
|
||||
name = "swift_generator",
|
||||
srcs = [
|
||||
"swift_generator.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"swift_generator.h",
|
||||
":common_headers",
|
||||
],
|
||||
include_prefix = "src/compiler",
|
||||
strip_include_prefix = "/grpc/src/compiler",
|
||||
deps = [
|
||||
"//:flatbuffers",
|
||||
],
|
||||
)
|
||||
@@ -84,7 +84,7 @@ void GenerateImports(grpc_generator::File *file, grpc_generator::Printer *printe
|
||||
}
|
||||
printer->Print("import (\n");
|
||||
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->Outdent();
|
||||
printer->Print(")\n\n");
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "java_generator.h"
|
||||
#include "src/compiler/java_generator.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
@@ -37,9 +37,6 @@
|
||||
#define XSTR(s) STR(s)
|
||||
#endif
|
||||
|
||||
#ifndef FALLTHROUGH_INTENDED
|
||||
#define FALLTHROUGH_INTENDED
|
||||
#endif
|
||||
|
||||
typedef grpc_generator::Printer Printer;
|
||||
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
|
||||
static string MixedLower(const string& word) {
|
||||
string w;
|
||||
w += (string::value_type)tolower(word[0]);
|
||||
w += static_cast<string::value_type>(tolower(word[0]));
|
||||
bool after_underscore = false;
|
||||
for (size_t i = 1; i < word.length(); ++i) {
|
||||
if (word[i] == '_') {
|
||||
after_underscore = true;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
@@ -92,7 +90,7 @@ static string MixedLower(const string& word) {
|
||||
static string ToAllUpperCase(const string& word) {
|
||||
string w;
|
||||
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])) {
|
||||
w += '_';
|
||||
}
|
||||
@@ -345,8 +343,8 @@ static void PrintMethodFields(Printer* p, VARS& vars,
|
||||
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
vars["arg_in_id"] = to_string((long)2 * i); //trying to make msvc 10 happy
|
||||
vars["arg_out_id"] = to_string((long)2 * i + 1);
|
||||
vars["arg_in_id"] = to_string(2L * i); //trying to make msvc 10 happy
|
||||
vars["arg_out_id"] = to_string(2L * i + 1);
|
||||
vars["method_name"] = method->name();
|
||||
vars["input_type_name"] = method->get_input_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_new_field_name"] = MethodPropertiesGetterName(method.get());
|
||||
vars["method_method_name"] = MethodPropertiesGetterName(method.get());
|
||||
bool client_streaming = method->ClientStreaming();
|
||||
bool server_streaming = method->ServerStreaming();
|
||||
bool client_streaming = method->ClientStreaming() || method->BidiStreaming();
|
||||
bool server_streaming = method->ServerStreaming() || method->BidiStreaming();
|
||||
if (client_streaming) {
|
||||
if (server_streaming) {
|
||||
vars["method_type"] = "BIDI_STREAMING";
|
||||
@@ -478,7 +476,7 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
|
||||
break;
|
||||
case BLOCKING_CLIENT_INTERFACE:
|
||||
interface = true;
|
||||
FALLTHROUGH_INTENDED; // fallthrough
|
||||
FLATBUFFERS_FALLTHROUGH(); // fall thru
|
||||
case BLOCKING_CLIENT_IMPL:
|
||||
call_type = BLOCKING_CALL;
|
||||
stub_name += "BlockingStub";
|
||||
@@ -486,7 +484,7 @@ static void PrintStub(Printer* p, VARS& vars, const ServiceDescriptor* service,
|
||||
break;
|
||||
case FUTURE_CLIENT_INTERFACE:
|
||||
interface = true;
|
||||
FALLTHROUGH_INTENDED; // fallthrough
|
||||
FLATBUFFERS_FALLTHROUGH(); // fall thru
|
||||
case FUTURE_CLIENT_IMPL:
|
||||
call_type = FUTURE_CALL;
|
||||
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["lower_method_name"] = LowerMethodName(&*method);
|
||||
vars["method_method_name"] = MethodPropertiesGetterName(&*method);
|
||||
bool client_streaming = method->ClientStreaming();
|
||||
bool server_streaming = method->ServerStreaming();
|
||||
bool client_streaming = method->ClientStreaming() || method->BidiStreaming();
|
||||
bool server_streaming = method->ServerStreaming() || method->BidiStreaming();
|
||||
|
||||
if (call_type == BLOCKING_CALL && client_streaming) {
|
||||
// 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) {
|
||||
auto method = service->method(i);
|
||||
if (method->ClientStreaming()) {
|
||||
if (method->ClientStreaming() || method->BidiStreaming()) {
|
||||
continue;
|
||||
}
|
||||
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) {
|
||||
auto method = service->method(i);
|
||||
if (!method->ClientStreaming()) {
|
||||
if (!(method->ClientStreaming() || method->BidiStreaming())) {
|
||||
continue;
|
||||
}
|
||||
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["output_type"] = JavaClassName(vars, method->get_output_type_name());
|
||||
vars["method_id_name"] = MethodIdFieldName(&*method);
|
||||
bool client_streaming = method->ClientStreaming();
|
||||
bool server_streaming = method->ServerStreaming();
|
||||
bool client_streaming = method->ClientStreaming() || method->BidiStreaming();
|
||||
bool server_streaming = method->ServerStreaming() || method->BidiStreaming();
|
||||
if (client_streaming) {
|
||||
if (server_streaming) {
|
||||
vars["calls_method"] = "asyncBidiStreamingCall";
|
||||
|
||||
624
grpc/src/compiler/python_generator.cc
Normal file
624
grpc/src/compiler/python_generator.cc
Normal file
@@ -0,0 +1,624 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2015 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
#include "flatbuffers/util.h"
|
||||
#include "src/compiler/python_generator.h"
|
||||
#include "src/compiler/python_private_generator.h"
|
||||
|
||||
using std::make_pair;
|
||||
using std::map;
|
||||
using std::pair;
|
||||
using std::replace;
|
||||
using std::tuple;
|
||||
using std::vector;
|
||||
using std::set;
|
||||
|
||||
namespace grpc_python_generator {
|
||||
|
||||
grpc::string generator_file_name;
|
||||
|
||||
typedef map<grpc::string, grpc::string> StringMap;
|
||||
typedef vector<grpc::string> StringVector;
|
||||
typedef tuple<grpc::string, grpc::string> StringPair;
|
||||
typedef set<StringPair> StringPairSet;
|
||||
|
||||
// Provides RAII indentation handling. Use as:
|
||||
// {
|
||||
// IndentScope raii_my_indent_var_name_here(my_py_printer);
|
||||
// // constructor indented my_py_printer
|
||||
// ...
|
||||
// // destructor called at end of scope, un-indenting my_py_printer
|
||||
// }
|
||||
class IndentScope {
|
||||
public:
|
||||
explicit IndentScope(grpc_generator::Printer* printer) : printer_(printer) {
|
||||
printer_->Indent();
|
||||
}
|
||||
|
||||
~IndentScope() { printer_->Outdent(); }
|
||||
|
||||
private:
|
||||
grpc_generator::Printer* printer_;
|
||||
};
|
||||
|
||||
inline grpc::string StringReplace(grpc::string str, const grpc::string& from,
|
||||
const grpc::string& to, bool replace_all) {
|
||||
size_t pos = 0;
|
||||
|
||||
do {
|
||||
pos = str.find(from, pos);
|
||||
if (pos == grpc::string::npos) {
|
||||
break;
|
||||
}
|
||||
str.replace(pos, from.length(), to);
|
||||
pos += to.length();
|
||||
} while (replace_all);
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
inline grpc::string StringReplace(grpc::string str, const grpc::string& from,
|
||||
const grpc::string& to) {
|
||||
return StringReplace(str, from, to, true);
|
||||
}
|
||||
|
||||
grpc::string ModuleName(const grpc::string& filename,
|
||||
const grpc::string& import_prefix) {
|
||||
grpc::string basename = flatbuffers::StripExtension(filename);
|
||||
basename = StringReplace(basename, "-", "_");
|
||||
basename = StringReplace(basename, "/", ".");
|
||||
return import_prefix + basename + "_fb";
|
||||
}
|
||||
|
||||
grpc::string ModuleAlias(const grpc::string& filename,
|
||||
const grpc::string& import_prefix) {
|
||||
grpc::string module_name = ModuleName(filename, import_prefix);
|
||||
// We can't have dots in the module name, so we replace each with _dot_.
|
||||
// But that could lead to a collision between a.b and a_dot_b, so we also
|
||||
// duplicate each underscore.
|
||||
module_name = StringReplace(module_name, "_", "__");
|
||||
module_name = StringReplace(module_name, ".", "_dot_");
|
||||
return module_name;
|
||||
}
|
||||
|
||||
PrivateGenerator::PrivateGenerator(const GeneratorConfiguration& config_,
|
||||
const grpc_generator::File* file_)
|
||||
: config(config_), file(file_) {}
|
||||
|
||||
void PrivateGenerator::PrintBetaServicer(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out) {
|
||||
StringMap service_dict;
|
||||
service_dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(service_dict, "class Beta$Service$Servicer(object):\n");
|
||||
{
|
||||
IndentScope raii_class_indent(out);
|
||||
out->Print(
|
||||
"\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
|
||||
"\nIt is recommended to use the GA API (classes and functions in this\n"
|
||||
"file not marked beta) for all further purposes. This class was "
|
||||
"generated\n"
|
||||
"only to ease transition from grpcio<0.15.0 to "
|
||||
"grpcio>=0.15.0.\"\"\"\n");
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
grpc::string arg_name =
|
||||
method->ClientStreaming() ? "request_iterator" : "request";
|
||||
StringMap method_dict;
|
||||
method_dict["Method"] = method->name();
|
||||
method_dict["ArgName"] = arg_name;
|
||||
out->Print(method_dict, "def $Method$(self, $ArgName$, context):\n");
|
||||
{
|
||||
IndentScope raii_method_indent(out);
|
||||
out->Print("context.code(beta_interfaces.StatusCode.UNIMPLEMENTED)\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintBetaStub(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out) {
|
||||
StringMap service_dict;
|
||||
service_dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(service_dict, "class Beta$Service$Stub(object):\n");
|
||||
{
|
||||
IndentScope raii_class_indent(out);
|
||||
out->Print(
|
||||
"\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
|
||||
"\nIt is recommended to use the GA API (classes and functions in this\n"
|
||||
"file not marked beta) for all further purposes. This class was "
|
||||
"generated\n"
|
||||
"only to ease transition from grpcio<0.15.0 to "
|
||||
"grpcio>=0.15.0.\"\"\"\n");
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
grpc::string arg_name =
|
||||
method->ClientStreaming() ? "request_iterator" : "request";
|
||||
StringMap method_dict;
|
||||
method_dict["Method"] = method->name();
|
||||
method_dict["ArgName"] = arg_name;
|
||||
out->Print(method_dict,
|
||||
"def $Method$(self, $ArgName$, timeout, metadata=None, "
|
||||
"with_call=False, protocol_options=None):\n");
|
||||
{
|
||||
IndentScope raii_method_indent(out);
|
||||
out->Print("raise NotImplementedError()\n");
|
||||
}
|
||||
if (!method->ServerStreaming()) {
|
||||
out->Print(method_dict, "$Method$.future = None\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintBetaServerFactory(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out) {
|
||||
StringMap service_dict;
|
||||
service_dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(service_dict,
|
||||
"def beta_create_$Service$_server(servicer, pool=None, "
|
||||
"pool_size=None, default_timeout=None, maximum_timeout=None):\n");
|
||||
{
|
||||
IndentScope raii_create_server_indent(out);
|
||||
out->Print(
|
||||
"\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
|
||||
"\nIt is recommended to use the GA API (classes and functions in this\n"
|
||||
"file not marked beta) for all further purposes. This function was\n"
|
||||
"generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
|
||||
"\"\"\"\n");
|
||||
StringMap method_implementation_constructors;
|
||||
StringMap input_message_modules_and_classes;
|
||||
StringMap output_message_modules_and_classes;
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
const grpc::string method_implementation_constructor =
|
||||
grpc::string(method->ClientStreaming() ? "stream_" : "unary_") +
|
||||
grpc::string(method->ServerStreaming() ? "stream_" : "unary_") +
|
||||
"inline";
|
||||
grpc::string input_message_module_and_class = method->get_fb_builder();
|
||||
grpc::string output_message_module_and_class = method->get_fb_builder();
|
||||
method_implementation_constructors.insert(
|
||||
make_pair(method->name(), method_implementation_constructor));
|
||||
input_message_modules_and_classes.insert(
|
||||
make_pair(method->name(), input_message_module_and_class));
|
||||
output_message_modules_and_classes.insert(
|
||||
make_pair(method->name(), output_message_module_and_class));
|
||||
}
|
||||
StringMap method_dict;
|
||||
method_dict["PackageQualifiedServiceName"] = package_qualified_service_name;
|
||||
// out->Print("request_deserializers = {\n");
|
||||
// for (StringMap::iterator name_and_input_module_class_pair =
|
||||
// input_message_modules_and_classes.begin();
|
||||
// name_and_input_module_class_pair !=
|
||||
// input_message_modules_and_classes.end();
|
||||
// name_and_input_module_class_pair++) {
|
||||
// method_dict["MethodName"] = name_and_input_module_class_pair->first;
|
||||
// method_dict["InputTypeModuleAndClass"] =
|
||||
// name_and_input_module_class_pair->second;
|
||||
// IndentScope raii_indent(out);
|
||||
// out->Print(method_dict,
|
||||
// "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
|
||||
// "$InputTypeModuleAndClass$.FromString,\n");
|
||||
// }
|
||||
// out->Print("}\n");
|
||||
// out->Print("response_serializers = {\n");
|
||||
// for (StringMap::iterator name_and_output_module_class_pair =
|
||||
// output_message_modules_and_classes.begin();
|
||||
// name_and_output_module_class_pair !=
|
||||
// output_message_modules_and_classes.end();
|
||||
// name_and_output_module_class_pair++) {
|
||||
// method_dict["MethodName"] = name_and_output_module_class_pair->first;
|
||||
// method_dict["OutputTypeModuleAndClass"] =
|
||||
// name_and_output_module_class_pair->second;
|
||||
// IndentScope raii_indent(out);
|
||||
// out->Print(method_dict,
|
||||
// "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
|
||||
// "$OutputTypeModuleAndClass$.SerializeToString,\n");
|
||||
// }
|
||||
// out->Print("}\n");
|
||||
out->Print("method_implementations = {\n");
|
||||
for (StringMap::iterator name_and_implementation_constructor =
|
||||
method_implementation_constructors.begin();
|
||||
name_and_implementation_constructor !=
|
||||
method_implementation_constructors.end();
|
||||
name_and_implementation_constructor++) {
|
||||
method_dict["Method"] = name_and_implementation_constructor->first;
|
||||
method_dict["Constructor"] = name_and_implementation_constructor->second;
|
||||
IndentScope raii_descriptions_indent(out);
|
||||
const grpc::string method_name =
|
||||
name_and_implementation_constructor->first;
|
||||
out->Print(method_dict,
|
||||
"(\'$PackageQualifiedServiceName$\', \'$Method$\'): "
|
||||
"face_utilities.$Constructor$(servicer.$Method$),\n");
|
||||
}
|
||||
out->Print("}\n");
|
||||
out->Print(
|
||||
"server_options = beta_implementations.server_options("
|
||||
"thread_pool=pool, thread_pool_size=pool_size, "
|
||||
"default_timeout=default_timeout, "
|
||||
"maximum_timeout=maximum_timeout)\n");
|
||||
out->Print(
|
||||
"return beta_implementations.server(method_implementations, "
|
||||
"options=server_options)\n");
|
||||
//"request_deserializers=request_deserializers, "
|
||||
//"response_serializers=response_serializers, "
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintBetaStubFactory(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out) {
|
||||
StringMap dict;
|
||||
dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(dict,
|
||||
"def beta_create_$Service$_stub(channel, host=None,"
|
||||
" metadata_transformer=None, pool=None, pool_size=None):\n");
|
||||
{
|
||||
IndentScope raii_create_server_indent(out);
|
||||
out->Print(
|
||||
"\"\"\"The Beta API is deprecated for 0.15.0 and later.\n"
|
||||
"\nIt is recommended to use the GA API (classes and functions in this\n"
|
||||
"file not marked beta) for all further purposes. This function was\n"
|
||||
"generated only to ease transition from grpcio<0.15.0 to grpcio>=0.15.0"
|
||||
"\"\"\"\n");
|
||||
StringMap method_cardinalities;
|
||||
StringMap input_message_modules_and_classes;
|
||||
StringMap output_message_modules_and_classes;
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
const grpc::string method_cardinality =
|
||||
grpc::string(method->ClientStreaming() ? "STREAM" : "UNARY") +
|
||||
"_" +
|
||||
grpc::string(method->ServerStreaming() ? "STREAM" : "UNARY");
|
||||
grpc::string input_message_module_and_class = method->get_fb_builder();
|
||||
grpc::string output_message_module_and_class = method->get_fb_builder();
|
||||
method_cardinalities.insert(
|
||||
make_pair(method->name(), method_cardinality));
|
||||
input_message_modules_and_classes.insert(
|
||||
make_pair(method->name(), input_message_module_and_class));
|
||||
output_message_modules_and_classes.insert(
|
||||
make_pair(method->name(), output_message_module_and_class));
|
||||
}
|
||||
StringMap method_dict;
|
||||
method_dict["PackageQualifiedServiceName"] = package_qualified_service_name;
|
||||
// out->Print("request_serializers = {\n");
|
||||
// for (StringMap::iterator name_and_input_module_class_pair =
|
||||
// input_message_modules_and_classes.begin();
|
||||
// name_and_input_module_class_pair !=
|
||||
// input_message_modules_and_classes.end();
|
||||
// name_and_input_module_class_pair++) {
|
||||
// method_dict["MethodName"] = name_and_input_module_class_pair->first;
|
||||
// method_dict["InputTypeModuleAndClass"] =
|
||||
// name_and_input_module_class_pair->second;
|
||||
// IndentScope raii_indent(out);
|
||||
// out->Print(method_dict,
|
||||
// "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
|
||||
// "$InputTypeModuleAndClass$.SerializeToString,\n");
|
||||
// }
|
||||
// out->Print("}\n");
|
||||
// out->Print("response_deserializers = {\n");
|
||||
// for (StringMap::iterator name_and_output_module_class_pair =
|
||||
// output_message_modules_and_classes.begin();
|
||||
// name_and_output_module_class_pair !=
|
||||
// output_message_modules_and_classes.end();
|
||||
// name_and_output_module_class_pair++) {
|
||||
// method_dict["MethodName"] = name_and_output_module_class_pair->first;
|
||||
// method_dict["OutputTypeModuleAndClass"] =
|
||||
// name_and_output_module_class_pair->second;
|
||||
// IndentScope raii_indent(out);
|
||||
// out->Print(method_dict,
|
||||
// "(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
|
||||
// "$OutputTypeModuleAndClass$.FromString,\n");
|
||||
// }
|
||||
// out->Print("}\n");
|
||||
out->Print("cardinalities = {\n");
|
||||
for (StringMap::iterator name_and_cardinality =
|
||||
method_cardinalities.begin();
|
||||
name_and_cardinality != method_cardinalities.end();
|
||||
name_and_cardinality++) {
|
||||
method_dict["Method"] = name_and_cardinality->first;
|
||||
method_dict["Cardinality"] = name_and_cardinality->second;
|
||||
IndentScope raii_descriptions_indent(out);
|
||||
out->Print(method_dict,
|
||||
"\'$Method$\': cardinality.Cardinality.$Cardinality$,\n");
|
||||
}
|
||||
out->Print("}\n");
|
||||
out->Print(
|
||||
"stub_options = beta_implementations.stub_options("
|
||||
"host=host, metadata_transformer=metadata_transformer, "
|
||||
"thread_pool=pool, thread_pool_size=pool_size)\n");
|
||||
out->Print(method_dict,
|
||||
"return beta_implementations.dynamic_stub(channel, "
|
||||
"\'$PackageQualifiedServiceName$\', "
|
||||
"cardinalities, options=stub_options)\n");
|
||||
// "request_serializers=request_serializers, "
|
||||
//"response_deserializers=response_deserializers, "
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintStub(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out) {
|
||||
StringMap dict;
|
||||
dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(dict, "class $Service$Stub(object):\n");
|
||||
{
|
||||
IndentScope raii_class_indent(out);
|
||||
out->Print("\n");
|
||||
out->Print("def __init__(self, channel):\n");
|
||||
{
|
||||
IndentScope raii_init_indent(out);
|
||||
out->Print("\"\"\"Constructor.\n");
|
||||
out->Print("\n");
|
||||
out->Print("Args:\n");
|
||||
{
|
||||
IndentScope raii_args_indent(out);
|
||||
out->Print("channel: A grpc.Channel.\n");
|
||||
}
|
||||
out->Print("\"\"\"\n");
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
grpc::string multi_callable_constructor =
|
||||
grpc::string(method->ClientStreaming() ? "stream" : "unary") +
|
||||
"_" +
|
||||
grpc::string(method->ServerStreaming() ? "stream" : "unary");
|
||||
grpc::string request_module_and_class = method->get_fb_builder();
|
||||
grpc::string response_module_and_class = method->get_fb_builder();
|
||||
StringMap method_dict;
|
||||
method_dict["Method"] = method->name();
|
||||
method_dict["MultiCallableConstructor"] = multi_callable_constructor;
|
||||
out->Print(method_dict,
|
||||
"self.$Method$ = channel.$MultiCallableConstructor$(\n");
|
||||
{
|
||||
method_dict["PackageQualifiedService"] =
|
||||
package_qualified_service_name;
|
||||
method_dict["RequestModuleAndClass"] = request_module_and_class;
|
||||
method_dict["ResponseModuleAndClass"] = response_module_and_class;
|
||||
IndentScope raii_first_attribute_indent(out);
|
||||
IndentScope raii_second_attribute_indent(out);
|
||||
out->Print(method_dict, "'/$PackageQualifiedService$/$Method$',\n");
|
||||
out->Print(method_dict,"\n");
|
||||
out->Print(
|
||||
method_dict,"\n");
|
||||
out->Print(")\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintServicer(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out) {
|
||||
StringMap service_dict;
|
||||
service_dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(service_dict, "class $Service$Servicer(object):\n");
|
||||
{
|
||||
IndentScope raii_class_indent(out);
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
grpc::string arg_name =
|
||||
method->ClientStreaming() ? "request_iterator" : "request";
|
||||
StringMap method_dict;
|
||||
method_dict["Method"] = method->name();
|
||||
method_dict["ArgName"] = arg_name;
|
||||
out->Print("\n");
|
||||
out->Print(method_dict, "def $Method$(self, $ArgName$, context):\n");
|
||||
{
|
||||
IndentScope raii_method_indent(out);
|
||||
out->Print("context.set_code(grpc.StatusCode.UNIMPLEMENTED)\n");
|
||||
out->Print("context.set_details('Method not implemented!')\n");
|
||||
out->Print("raise NotImplementedError('Method not implemented!')\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintAddServicerToServer(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out) {
|
||||
StringMap service_dict;
|
||||
service_dict["Service"] = service->name();
|
||||
out->Print("\n\n");
|
||||
out->Print(service_dict,
|
||||
"def add_$Service$Servicer_to_server(servicer, server):\n");
|
||||
{
|
||||
IndentScope raii_class_indent(out);
|
||||
out->Print("rpc_method_handlers = {\n");
|
||||
{
|
||||
IndentScope raii_dict_first_indent(out);
|
||||
IndentScope raii_dict_second_indent(out);
|
||||
for (int i = 0; i < service->method_count(); ++i) {
|
||||
auto method = service->method(i);
|
||||
grpc::string method_handler_constructor =
|
||||
grpc::string(method->ClientStreaming() ? "stream" : "unary") +
|
||||
"_" +
|
||||
grpc::string(method->ServerStreaming() ? "stream" : "unary") +
|
||||
"_rpc_method_handler";
|
||||
grpc::string request_module_and_class = method->get_fb_builder();
|
||||
grpc::string response_module_and_class = method->get_fb_builder();
|
||||
StringMap method_dict;
|
||||
method_dict["Method"] = method->name();
|
||||
method_dict["MethodHandlerConstructor"] = method_handler_constructor;
|
||||
method_dict["RequestModuleAndClass"] = request_module_and_class;
|
||||
method_dict["ResponseModuleAndClass"] = response_module_and_class;
|
||||
out->Print(method_dict,
|
||||
"'$Method$': grpc.$MethodHandlerConstructor$(\n");
|
||||
{
|
||||
IndentScope raii_call_first_indent(out);
|
||||
IndentScope raii_call_second_indent(out);
|
||||
out->Print(method_dict, "servicer.$Method$,\n");
|
||||
out->Print(
|
||||
method_dict,"\n");
|
||||
out->Print(
|
||||
method_dict,
|
||||
"\n");
|
||||
}
|
||||
out->Print("),\n");
|
||||
}
|
||||
}
|
||||
StringMap method_dict;
|
||||
method_dict["PackageQualifiedServiceName"] = package_qualified_service_name;
|
||||
out->Print("}\n");
|
||||
out->Print("generic_handler = grpc.method_handlers_generic_handler(\n");
|
||||
{
|
||||
IndentScope raii_call_first_indent(out);
|
||||
IndentScope raii_call_second_indent(out);
|
||||
out->Print(method_dict,
|
||||
"'$PackageQualifiedServiceName$', rpc_method_handlers)\n");
|
||||
}
|
||||
out->Print("server.add_generic_rpc_handlers((generic_handler,))\n");
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintBetaPreamble(grpc_generator::Printer* out) {
|
||||
StringMap var;
|
||||
var["Package"] = config.beta_package_root;
|
||||
out->Print(var,
|
||||
"from $Package$ import implementations as beta_implementations\n");
|
||||
out->Print(var, "from $Package$ import interfaces as beta_interfaces\n");
|
||||
out->Print("from grpc.framework.common import cardinality\n");
|
||||
out->Print(
|
||||
"from grpc.framework.interfaces.face import utilities as "
|
||||
"face_utilities\n");
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintPreamble(grpc_generator::Printer* out) {
|
||||
StringMap var;
|
||||
var["Package"] = config.grpc_package_root;
|
||||
out->Print(var, "import $Package$\n");
|
||||
out->Print("\n");
|
||||
StringPairSet imports_set;
|
||||
for (int i = 0; i < file->service_count(); ++i) {
|
||||
auto service = file->service(i);
|
||||
for (int j = 0; j < service->method_count(); ++j) {
|
||||
auto method = service.get()->method(j);
|
||||
|
||||
grpc::string input_type_file_name = method->get_fb_builder();
|
||||
grpc::string input_module_name =
|
||||
ModuleName(input_type_file_name, config.import_prefix);
|
||||
grpc::string input_module_alias =
|
||||
ModuleAlias(input_type_file_name, config.import_prefix);
|
||||
imports_set.insert(
|
||||
std::make_tuple(input_module_name, input_module_alias));
|
||||
|
||||
grpc::string output_type_file_name = method->get_fb_builder();
|
||||
grpc::string output_module_name =
|
||||
ModuleName(output_type_file_name, config.import_prefix);
|
||||
grpc::string output_module_alias =
|
||||
ModuleAlias(output_type_file_name, config.import_prefix);
|
||||
imports_set.insert(
|
||||
std::make_tuple(output_module_name, output_module_alias));
|
||||
}
|
||||
}
|
||||
|
||||
for (StringPairSet::iterator it = imports_set.begin();
|
||||
it != imports_set.end(); ++it) {
|
||||
var["ModuleName"] = std::get<0>(*it);
|
||||
var["ModuleAlias"] = std::get<1>(*it);
|
||||
out->Print(var, "import $ModuleName$ as $ModuleAlias$\n");
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintGAServices(grpc_generator::Printer* out) {
|
||||
grpc::string package = file->package();
|
||||
if (!package.empty()) {
|
||||
package = package.append(".");
|
||||
}
|
||||
|
||||
out->Print(file->additional_headers().c_str());
|
||||
|
||||
for (int i = 0; i < file->service_count(); ++i) {
|
||||
auto service = file->service(i);
|
||||
|
||||
grpc::string package_qualified_service_name = package + service->name();
|
||||
PrintStub(package_qualified_service_name, service.get(), out);
|
||||
PrintServicer(service.get(), out);
|
||||
PrintAddServicerToServer(package_qualified_service_name, service.get(),
|
||||
out);
|
||||
}
|
||||
}
|
||||
|
||||
void PrivateGenerator::PrintBetaServices(grpc_generator::Printer* out) {
|
||||
grpc::string package = file->package();
|
||||
if (!package.empty()) {
|
||||
package = package.append(".");
|
||||
}
|
||||
for (int i = 0; i < file->service_count(); ++i) {
|
||||
auto service = file->service(i);
|
||||
|
||||
grpc::string package_qualified_service_name = package + service->name();
|
||||
PrintBetaServicer(service.get(), out);
|
||||
PrintBetaStub(service.get(), out);
|
||||
PrintBetaServerFactory(package_qualified_service_name, service.get(), out);
|
||||
PrintBetaStubFactory(package_qualified_service_name, service.get(), out);
|
||||
}
|
||||
}
|
||||
|
||||
grpc::string PrivateGenerator::GetGrpcServices() {
|
||||
grpc::string output;
|
||||
{
|
||||
// Scope the output stream so it closes and finalizes output to the string.
|
||||
auto out = file->CreatePrinter(&output);
|
||||
out->Print(
|
||||
"# Generated by the gRPC Python protocol compiler plugin. "
|
||||
"DO NOT EDIT!\n");
|
||||
StringMap var;
|
||||
var["Package"] = config.grpc_package_root;
|
||||
out->Print(var, "import $Package$\n");
|
||||
PrintGAServices(out.get());
|
||||
out->Print("try:\n");
|
||||
{
|
||||
IndentScope raii_dict_try_indent(out.get());
|
||||
out->Print(
|
||||
"# THESE ELEMENTS WILL BE DEPRECATED.\n"
|
||||
"# Please use the generated *_pb2_grpc.py files instead.\n");
|
||||
out->Print(var, "import $Package$\n");
|
||||
PrintBetaPreamble(out.get());
|
||||
PrintGAServices(out.get());
|
||||
PrintBetaServices(out.get());
|
||||
}
|
||||
out->Print("except ImportError:\n");
|
||||
{
|
||||
IndentScope raii_dict_except_indent(out.get());
|
||||
out->Print("pass");
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
} // namespace grpc_python_generator
|
||||
40
grpc/src/compiler/python_generator.h
Normal file
40
grpc/src/compiler/python_generator.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2015 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H
|
||||
#define GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "src/compiler/schema_interface.h"
|
||||
|
||||
namespace grpc_python_generator {
|
||||
|
||||
// Data pertaining to configuration of the generator with respect to anything
|
||||
// that may be used internally at Google.
|
||||
struct GeneratorConfiguration {
|
||||
grpc::string grpc_package_root;
|
||||
// TODO(https://github.com/grpc/grpc/issues/8622): Drop this.
|
||||
grpc::string beta_package_root;
|
||||
// TODO(https://github.com/google/protobuf/issues/888): Drop this.
|
||||
grpc::string import_prefix;
|
||||
};
|
||||
|
||||
} // namespace grpc_python_generator
|
||||
|
||||
#endif // GRPC_INTERNAL_COMPILER_PYTHON_GENERATOR_H
|
||||
72
grpc/src/compiler/python_private_generator.h
Normal file
72
grpc/src/compiler/python_private_generator.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2015 gRPC authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRPC_INTERNAL_COMPILER_PYTHON_PRIVATE_GENERATOR_H
|
||||
#define GRPC_INTERNAL_COMPILER_PYTHON_PRIVATE_GENERATOR_H
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "src/compiler/python_generator.h"
|
||||
#include "src/compiler/schema_interface.h"
|
||||
|
||||
namespace grpc_python_generator {
|
||||
|
||||
// Tucks all generator state in an anonymous namespace away from
|
||||
// PythonGrpcGenerator and the header file, mostly to encourage future changes
|
||||
// to not require updates to the grpcio-tools C++ code part. Assumes that it is
|
||||
// only ever used from a single thread.
|
||||
struct PrivateGenerator {
|
||||
const GeneratorConfiguration& config;
|
||||
const grpc_generator::File* file;
|
||||
|
||||
PrivateGenerator(const GeneratorConfiguration& config,
|
||||
const grpc_generator::File* file);
|
||||
|
||||
grpc::string GetGrpcServices();
|
||||
|
||||
private:
|
||||
void PrintPreamble(grpc_generator::Printer* out);
|
||||
void PrintBetaPreamble(grpc_generator::Printer* out);
|
||||
void PrintGAServices(grpc_generator::Printer* out);
|
||||
void PrintBetaServices(grpc_generator::Printer* out);
|
||||
|
||||
void PrintAddServicerToServer(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out);
|
||||
void PrintServicer(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out);
|
||||
void PrintStub(const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out);
|
||||
|
||||
void PrintBetaServicer(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out);
|
||||
void PrintBetaServerFactory(
|
||||
const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service, grpc_generator::Printer* out);
|
||||
void PrintBetaStub(const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out);
|
||||
void PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
|
||||
const grpc_generator::Service* service,
|
||||
grpc_generator::Printer* out);
|
||||
};
|
||||
|
||||
} // namespace grpc_python_generator
|
||||
|
||||
#endif // GRPC_INTERNAL_COMPILER_PYTHON_PRIVATE_GENERATOR_H
|
||||
@@ -1,44 +1,29 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2015, Google Inc.
|
||||
* All rights reserved.
|
||||
* Copyright 2015 gRPC authors.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
|
||||
#define GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
|
||||
|
||||
#include "src/compiler/config.h"
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "src/compiler/config.h"
|
||||
|
||||
#ifndef GRPC_CUSTOM_STRING
|
||||
# include <string>
|
||||
# define GRPC_CUSTOM_STRING std::string
|
||||
@@ -79,6 +64,9 @@ struct Method : public CommentHolder {
|
||||
|
||||
virtual grpc::string get_input_type_name() const = 0;
|
||||
virtual grpc::string get_output_type_name() const = 0;
|
||||
|
||||
virtual grpc::string get_fb_builder() const = 0;
|
||||
|
||||
virtual bool NoStreaming() const = 0;
|
||||
virtual bool ClientStreaming() const = 0;
|
||||
virtual bool ServerStreaming() const = 0;
|
||||
|
||||
308
grpc/src/compiler/swift_generator.cc
Normal file
308
grpc/src/compiler/swift_generator.cc
Normal file
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright 2020 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE: The following implementation is a translation for the Swift-grpc
|
||||
* generator since flatbuffers doesnt allow plugins for now. if an issue arises
|
||||
* please open an issue in the flatbuffers repository. This file should always
|
||||
* be maintained according to the Swift-grpc repository
|
||||
*/
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
||||
#include "flatbuffers/util.h"
|
||||
#include "src/compiler/schema_interface.h"
|
||||
#include "src/compiler/swift_generator.h"
|
||||
|
||||
namespace grpc_swift_generator {
|
||||
|
||||
grpc::string GenerateMessage(const grpc::string &name) {
|
||||
return "Message<" + name + ">";
|
||||
}
|
||||
|
||||
// MARK: - Client
|
||||
|
||||
grpc::string GenerateClientFuncName(const grpc_generator::Method *method) {
|
||||
if (method->NoStreaming()) {
|
||||
return "$GenAccess$ func $MethodName$(_ request: $Input$"
|
||||
", callOptions: CallOptions?$isNil$) -> UnaryCall<$Input$,$Output$>";
|
||||
}
|
||||
|
||||
if (method->ClientStreaming()) {
|
||||
return "$GenAccess$ func $MethodName$"
|
||||
"(callOptions: CallOptions?$isNil$) -> "
|
||||
"ClientStreamingCall<$Input$,$Output$>";
|
||||
}
|
||||
|
||||
if (method->ServerStreaming()) {
|
||||
return "$GenAccess$ func $MethodName$(_ request: $Input$"
|
||||
", callOptions: CallOptions?$isNil$, handler: @escaping ($Output$"
|
||||
") -> Void) -> ServerStreamingCall<$Input$, $Output$>";
|
||||
}
|
||||
return "$GenAccess$ func $MethodName$"
|
||||
"(callOptions: CallOptions?$isNil$, handler: @escaping ($Output$"
|
||||
") -> Void) -> BidirectionalStreamingCall<$Input$, $Output$>";
|
||||
}
|
||||
|
||||
grpc::string GenerateClientFuncBody(const grpc_generator::Method *method) {
|
||||
if (method->NoStreaming()) {
|
||||
return "return self.makeUnaryCall(path: "
|
||||
"\"/$PATH$$ServiceName$/$MethodName$\", request: request, "
|
||||
"callOptions: callOptions ?? self.defaultCallOptions)";
|
||||
}
|
||||
|
||||
if (method->ClientStreaming()) {
|
||||
return "return self.makeClientStreamingCall(path: "
|
||||
"\"/$PATH$$ServiceName$/$MethodName$\", callOptions: callOptions ?? "
|
||||
"self.defaultCallOptions)";
|
||||
}
|
||||
|
||||
if (method->ServerStreaming()) {
|
||||
return "return self.makeServerStreamingCall(path: "
|
||||
"\"/$PATH$$ServiceName$/$MethodName$\", request: request, "
|
||||
"callOptions: callOptions ?? self.defaultCallOptions, handler: "
|
||||
"handler)";
|
||||
}
|
||||
return "return self.makeBidirectionalStreamingCall(path: "
|
||||
"\"/$PATH$$ServiceName$/$MethodName$\", callOptions: callOptions ?? "
|
||||
"self.defaultCallOptions, handler: handler)";
|
||||
}
|
||||
|
||||
void GenerateClientProtocol(const grpc_generator::Service *service,
|
||||
grpc_generator::Printer *printer,
|
||||
std::map<grpc::string, grpc::string> *dictonary) {
|
||||
auto vars = *dictonary;
|
||||
printer->Print(vars, "$ACCESS$ protocol $ServiceName$Service {\n");
|
||||
vars["GenAccess"] = "";
|
||||
for (auto it = 0; it < service->method_count(); it++) {
|
||||
auto method = service->method(it);
|
||||
vars["Input"] = GenerateMessage(method->get_input_type_name());
|
||||
vars["Output"] = GenerateMessage(method->get_output_type_name());
|
||||
vars["MethodName"] = method->name();
|
||||
vars["isNil"] = "";
|
||||
printer->Print("\t");
|
||||
auto func = GenerateClientFuncName(method.get());
|
||||
printer->Print(vars, func.c_str());
|
||||
printer->Print("\n");
|
||||
}
|
||||
printer->Print("}\n\n");
|
||||
}
|
||||
|
||||
void GenerateClientClass(const grpc_generator::Service *service,
|
||||
grpc_generator::Printer *printer,
|
||||
std::map<grpc::string, grpc::string> *dictonary) {
|
||||
auto vars = *dictonary;
|
||||
printer->Print(vars,
|
||||
"$ACCESS$ final class $ServiceName$ServiceClient: GRPCClient, "
|
||||
"$ServiceName$Service {\n");
|
||||
printer->Print(vars, "\t$ACCESS$ let connection: ClientConnection\n");
|
||||
printer->Print(vars, "\t$ACCESS$ var defaultCallOptions: CallOptions\n");
|
||||
printer->Print("\n");
|
||||
printer->Print(vars,
|
||||
"\t$ACCESS$ init(connection: ClientConnection, "
|
||||
"defaultCallOptions: CallOptions = CallOptions()) {\n");
|
||||
printer->Print("\t\tself.connection = connection\n");
|
||||
printer->Print("\t\tself.defaultCallOptions = defaultCallOptions\n");
|
||||
printer->Print("\t}");
|
||||
printer->Print("\n");
|
||||
vars["GenAccess"] = "public";
|
||||
for (auto it = 0; it < service->method_count(); it++) {
|
||||
auto method = service->method(it);
|
||||
vars["Input"] = GenerateMessage(method->get_input_type_name());
|
||||
vars["Output"] = GenerateMessage(method->get_output_type_name());
|
||||
vars["MethodName"] = method->name();
|
||||
vars["isNil"] = " = nil";
|
||||
printer->Print("\n\t");
|
||||
auto func = GenerateClientFuncName(method.get());
|
||||
printer->Print(vars, func.c_str());
|
||||
printer->Print(" {\n");
|
||||
auto body = GenerateClientFuncBody(method.get());
|
||||
printer->Print("\t\t");
|
||||
printer->Print(vars, body.c_str());
|
||||
printer->Print("\n\t}\n");
|
||||
}
|
||||
printer->Print("}\n");
|
||||
}
|
||||
|
||||
// MARK: - Server
|
||||
|
||||
grpc::string GenerateServerFuncName(const grpc_generator::Method *method) {
|
||||
if (method->NoStreaming()) {
|
||||
return "func $MethodName$(_ request: $Input$"
|
||||
", context: StatusOnlyCallContext) -> EventLoopFuture<$Output$>";
|
||||
}
|
||||
|
||||
if (method->ClientStreaming()) {
|
||||
return "func $MethodName$(context: UnaryResponseCallContext<$Output$>) -> "
|
||||
"EventLoopFuture<(StreamEvent<$Input$"
|
||||
">) -> Void>";
|
||||
}
|
||||
|
||||
if (method->ServerStreaming()) {
|
||||
return "func $MethodName$(request: $Input$"
|
||||
", context: StreamingResponseCallContext<$Output$>) -> "
|
||||
"EventLoopFuture<GRPCStatus>";
|
||||
}
|
||||
return "func $MethodName$(context: StreamingResponseCallContext<$Output$>) "
|
||||
"-> EventLoopFuture<(StreamEvent<$Input$>) -> Void>";
|
||||
}
|
||||
|
||||
grpc::string GenerateServerExtensionBody(const grpc_generator::Method *method) {
|
||||
grpc::string start = "\t\tcase \"$MethodName$\":\n\t\t";
|
||||
if (method->NoStreaming()) {
|
||||
return start +
|
||||
"return UnaryCallHandler(callHandlerContext: callHandlerContext) { "
|
||||
"context in"
|
||||
"\n\t\t\t"
|
||||
"return { request in"
|
||||
"\n\t\t\t\t"
|
||||
"self.$MethodName$(request, context: context)"
|
||||
"\n\t\t\t}"
|
||||
"\n\t\t}";
|
||||
}
|
||||
if (method->ClientStreaming()) {
|
||||
return start +
|
||||
"return ClientStreamingCallHandler(callHandlerContext: "
|
||||
"callHandlerContext) { context in"
|
||||
"\n\t\t\t"
|
||||
"return { request in"
|
||||
"\n\t\t\t\t"
|
||||
"self.$MethodName$(request: request, context: context)"
|
||||
"\n\t\t\t}"
|
||||
"\n\t\t}";
|
||||
}
|
||||
if (method->ServerStreaming()) {
|
||||
return start +
|
||||
"return ServerStreamingCallHandler(callHandlerContext: "
|
||||
"callHandlerContext) { context in"
|
||||
"\n\t\t\t"
|
||||
"return { request in"
|
||||
"\n\t\t\t\t"
|
||||
"self.$MethodName$(request: request, context: context)"
|
||||
"\n\t\t\t}"
|
||||
"\n\t\t}";
|
||||
}
|
||||
if (method->BidiStreaming()) {
|
||||
return start +
|
||||
"return BidirectionalStreamingCallHandler(callHandlerContext: "
|
||||
"callHandlerContext) { context in"
|
||||
"\n\t\t\t"
|
||||
"return { request in"
|
||||
"\n\t\t\t\t"
|
||||
"self.$MethodName$(request: request, context: context)"
|
||||
"\n\t\t\t}"
|
||||
"\n\t\t}";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
void GenerateServerProtocol(const grpc_generator::Service *service,
|
||||
grpc_generator::Printer *printer,
|
||||
std::map<grpc::string, grpc::string> *dictonary) {
|
||||
auto vars = *dictonary;
|
||||
printer->Print(
|
||||
vars, "$ACCESS$ protocol $ServiceName$Provider: CallHandlerProvider {\n");
|
||||
for (auto it = 0; it < service->method_count(); it++) {
|
||||
auto method = service->method(it);
|
||||
vars["Input"] = GenerateMessage(method->get_input_type_name());
|
||||
vars["Output"] = GenerateMessage(method->get_output_type_name());
|
||||
vars["MethodName"] = method->name();
|
||||
printer->Print("\t");
|
||||
auto func = GenerateServerFuncName(method.get());
|
||||
printer->Print(vars, func.c_str());
|
||||
printer->Print("\n");
|
||||
}
|
||||
printer->Print("}\n\n");
|
||||
|
||||
printer->Print(vars, "$ACCESS$ extension $ServiceName$Provider {\n");
|
||||
printer->Print(vars,
|
||||
"\tvar serviceName: String { return "
|
||||
"\"$PATH$$ServiceName$\" }\n");
|
||||
printer->Print(
|
||||
"\tfunc handleMethod(_ methodName: String, callHandlerContext: "
|
||||
"CallHandlerContext) -> GRPCCallHandler? {\n");
|
||||
printer->Print("\t\tswitch methodName {\n");
|
||||
for (auto it = 0; it < service->method_count(); it++) {
|
||||
auto method = service->method(it);
|
||||
vars["Input"] = GenerateMessage(method->get_input_type_name());
|
||||
vars["Output"] = GenerateMessage(method->get_output_type_name());
|
||||
vars["MethodName"] = method->name();
|
||||
auto body = GenerateServerExtensionBody(method.get());
|
||||
printer->Print(vars, body.c_str());
|
||||
printer->Print("\n");
|
||||
}
|
||||
printer->Print("\t\tdefault: return nil;\n");
|
||||
printer->Print("\t\t}\n");
|
||||
printer->Print("\t}\n\n");
|
||||
printer->Print("}\n\n");
|
||||
}
|
||||
|
||||
grpc::string Generate(grpc_generator::File *file,
|
||||
const grpc_generator::Service *service) {
|
||||
grpc::string output;
|
||||
std::map<grpc::string, grpc::string> vars;
|
||||
vars["PATH"] = file->package();
|
||||
if (!file->package().empty()) { vars["PATH"].append("."); }
|
||||
vars["ServiceName"] = service->name();
|
||||
vars["ACCESS"] = "public";
|
||||
auto printer = file->CreatePrinter(&output);
|
||||
printer->Print(vars,
|
||||
"/// Usage: instantiate $ServiceName$ServiceClient, then call "
|
||||
"methods of this protocol to make API calls.\n");
|
||||
GenerateClientProtocol(service, &*printer, &vars);
|
||||
GenerateClientClass(service, &*printer, &vars);
|
||||
printer->Print("\n");
|
||||
GenerateServerProtocol(service, &*printer, &vars);
|
||||
return output;
|
||||
}
|
||||
|
||||
grpc::string GenerateHeader() {
|
||||
grpc::string code;
|
||||
code +=
|
||||
"/// The following code is generated by the Flatbuffers library which "
|
||||
"might not be in sync with grpc-swift\n";
|
||||
code +=
|
||||
"/// in case of an issue please open github issue, though it would be "
|
||||
"maintained\n";
|
||||
code += "import Foundation\n";
|
||||
code += "import GRPC\n";
|
||||
code += "import NIO\n";
|
||||
code += "import NIOHTTP1\n";
|
||||
code += "import FlatBuffers\n";
|
||||
code += "\n";
|
||||
code +=
|
||||
"public protocol GRPCFlatBufPayload: GRPCPayload, FlatBufferGRPCMessage "
|
||||
"{}\n";
|
||||
|
||||
code += "public extension GRPCFlatBufPayload {\n";
|
||||
code += " init(serializedByteBuffer: inout NIO.ByteBuffer) throws {\n";
|
||||
code +=
|
||||
" self.init(byteBuffer: FlatBuffers.ByteBuffer(contiguousBytes: "
|
||||
"serializedByteBuffer.readableBytesView, count: "
|
||||
"serializedByteBuffer.readableBytes))\n";
|
||||
code += " }\n";
|
||||
|
||||
code += " func serialize(into buffer: inout NIO.ByteBuffer) throws {\n";
|
||||
code +=
|
||||
" let buf = UnsafeRawBufferPointer(start: self.rawPointer, count: "
|
||||
"Int(self.size))\n";
|
||||
code += " buffer.writeBytes(buf)\n";
|
||||
code += " }\n";
|
||||
code += "}\n";
|
||||
code += "extension Message: GRPCFlatBufPayload {}\n";
|
||||
return code;
|
||||
}
|
||||
} // namespace grpc_swift_generator
|
||||
55
grpc/src/compiler/swift_generator.h
Normal file
55
grpc/src/compiler/swift_generator.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
*
|
||||
* Copyright 2020, Google Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* * Neither the name of Google Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "src/compiler/config.h"
|
||||
#include "src/compiler/schema_interface.h"
|
||||
|
||||
#ifndef GRPC_CUSTOM_STRING
|
||||
# include <string>
|
||||
# define GRPC_CUSTOM_STRING std::string
|
||||
#endif
|
||||
|
||||
namespace grpc {
|
||||
|
||||
typedef GRPC_CUSTOM_STRING string;
|
||||
|
||||
} // namespace grpc
|
||||
|
||||
namespace grpc_swift_generator {
|
||||
grpc::string Generate(grpc_generator::File *file,
|
||||
const grpc_generator::Service *service);
|
||||
grpc::string GenerateHeader();
|
||||
} // namespace grpc_swift_generator
|
||||
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.Server;
|
||||
import io.grpc.ServerBuilder;
|
||||
import io.grpc.stub.StreamObserver;
|
||||
import org.junit.Assert;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.InterruptedException;
|
||||
import java.nio.ByteBuffer;
|
||||
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.
|
||||
*/
|
||||
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 nestedMonsterMana = 1024;
|
||||
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 {
|
||||
@Override
|
||||
@@ -46,10 +57,7 @@ public class JavaGrpcTest {
|
||||
Assert.assertEquals(request.mana(), nestedMonsterMana);
|
||||
System.out.println("Received store request from " + request.name());
|
||||
// Create a response from the incoming request name.
|
||||
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||
int statOffset = Stat.createStat(builder, builder.createString("Hello " + request.name()), 100, 10);
|
||||
builder.finish(statOffset);
|
||||
Stat stat = Stat.getRootAsStat(builder.dataBuffer());
|
||||
Stat stat = GameFactory.createStat("Hello " + request.name(), 100, 10);
|
||||
responseObserver.onNext(stat);
|
||||
responseObserver.onCompleted();
|
||||
}
|
||||
@@ -58,55 +66,101 @@ public class JavaGrpcTest {
|
||||
public void retrieve(Stat request, io.grpc.stub.StreamObserver<Monster> responseObserver) {
|
||||
// Create 10 monsters for streaming response.
|
||||
for (int i=0; i<numStreamedMsgs; i++) {
|
||||
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||
int i1 = builder.createString(request.id() + " No." + i);
|
||||
Monster.startMonster(builder);
|
||||
Monster.addName(builder, i1);
|
||||
int i2 = Monster.endMonster(builder);
|
||||
Monster.finishMonsterBuffer(builder, i2);
|
||||
Monster monster = Monster.getRootAsMonster(builder.dataBuffer());
|
||||
Monster monster = GameFactory.createMonsterFromStat(request, i);
|
||||
responseObserver.onNext(monster);
|
||||
}
|
||||
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();
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int startServer() throws IOException {
|
||||
Server server = ServerBuilder.forPort(0).addService(new MyService()).build().start();
|
||||
return server.getPort();
|
||||
@org.junit.BeforeClass
|
||||
public static void startServer() throws IOException {
|
||||
server = ServerBuilder.forPort(0).addService(new MyService()).build().start();
|
||||
int port = server.getPort();
|
||||
channel = ManagedChannelBuilder.forAddress("localhost", port)
|
||||
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
|
||||
// needing certificates.
|
||||
.usePlaintext()
|
||||
.directExecutor()
|
||||
.build();
|
||||
blockingStub = MonsterStorageGrpc.newBlockingStub(channel);
|
||||
asyncStub = MonsterStorageGrpc.newStub(channel);
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void testMonster() throws IOException {
|
||||
int port = startServer();
|
||||
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", port)
|
||||
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
|
||||
// needing certificates.
|
||||
.usePlaintext(true)
|
||||
.directExecutor()
|
||||
.build();
|
||||
|
||||
MonsterStorageGrpc.MonsterStorageBlockingStub stub = MonsterStorageGrpc.newBlockingStub(channel);
|
||||
|
||||
FlatBufferBuilder builder = new FlatBufferBuilder();
|
||||
|
||||
int o_string = builder.createString(BIG_MONSTER_NAME);
|
||||
Monster.startMonster(builder);
|
||||
Monster.addName(builder, o_string);
|
||||
Monster.addHp(builder, nestedMonsterHp);
|
||||
Monster.addMana(builder, nestedMonsterMana);
|
||||
int monster1 = Monster.endMonster(builder);
|
||||
Monster.finishMonsterBuffer(builder, monster1);
|
||||
|
||||
ByteBuffer buffer = builder.dataBuffer();
|
||||
Monster monsterRequest = Monster.getRootAsMonster(buffer);
|
||||
Stat stat = stub.store(monsterRequest);
|
||||
public void testUnary() throws IOException {
|
||||
Monster monsterRequest = GameFactory.createMonster(BIG_MONSTER_NAME, nestedMonsterHp, nestedMonsterMana);
|
||||
Stat stat = blockingStub.store(monsterRequest);
|
||||
Assert.assertEquals(stat.id(), "Hello " + BIG_MONSTER_NAME);
|
||||
System.out.println("Received stat response from service: " + stat.id());
|
||||
}
|
||||
|
||||
|
||||
Iterator<Monster> iterator = stub.retrieve(stat);
|
||||
@org.junit.Test
|
||||
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;
|
||||
while(iterator.hasNext()) {
|
||||
Monster m = iterator.next();
|
||||
@@ -116,4 +170,73 @@ public class JavaGrpcTest {
|
||||
Assert.assertEquals(counter, numStreamedMsgs);
|
||||
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 (
|
||||
"../../tests/MyGame/Example"
|
||||
|
||||
"context"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
|
||||
@@ -14,15 +14,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include <grpc++/grpc++.h>
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include "monster_test.grpc.fb.h"
|
||||
#include "monster_test_generated.h"
|
||||
#include "test_assert.h"
|
||||
|
||||
using namespace MyGame::Example;
|
||||
using flatbuffers::FlatBufferBuilder;
|
||||
using flatbuffers::grpc::MessageBuilder;
|
||||
|
||||
void message_builder_tests();
|
||||
|
||||
// The callback implementation of our server, that derives from the generated
|
||||
@@ -46,9 +49,9 @@ class ServiceImpl final : public MyGame::Example::MonsterStorage::Service {
|
||||
const flatbuffers::grpc::Message<Stat> *request,
|
||||
::grpc::ServerWriter<flatbuffers::grpc::Message<Monster>> *writer)
|
||||
override {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
fbb_.Clear();
|
||||
// Create 10 monsters for resposne.
|
||||
// Create 5 monsters for resposne.
|
||||
auto monster_offset =
|
||||
CreateMonster(fbb_, 0, 0, 0,
|
||||
fbb_.CreateString(request->GetRoot()->id()->str() +
|
||||
@@ -94,6 +97,43 @@ void RunServer() {
|
||||
server_instance->Wait();
|
||||
}
|
||||
|
||||
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.
|
||||
std::thread server_thread(RunServer);
|
||||
@@ -107,39 +147,11 @@ int grpc_server_test() {
|
||||
grpc::InsecureChannelCredentials());
|
||||
auto stub = MyGame::Example::MonsterStorage::NewStub(channel);
|
||||
|
||||
flatbuffers::grpc::MessageBuilder fbb;
|
||||
{
|
||||
grpc::ClientContext context;
|
||||
// Build a request with the name set.
|
||||
auto monster_offset = CreateMonster(fbb, 0, 0, 0, fbb.CreateString("Fred"));
|
||||
fbb.Finish(monster_offset);
|
||||
auto request = fbb.ReleaseMessage<Monster>();
|
||||
flatbuffers::grpc::Message<Stat> response;
|
||||
StoreRPC<MessageBuilder>(stub.get());
|
||||
StoreRPC<FlatBufferBuilder>(stub.get());
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
RetrieveRPC<MessageBuilder>(stub.get());
|
||||
RetrieveRPC<FlatBufferBuilder>(stub.get());
|
||||
|
||||
#if !FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
|
||||
{
|
||||
@@ -166,7 +178,7 @@ int grpc_server_test() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int /*argc*/, const char * /*argv*/ []) {
|
||||
int main(int /*argc*/, const char * /*argv*/[]) {
|
||||
message_builder_tests();
|
||||
grpc_server_test();
|
||||
|
||||
@@ -178,4 +190,3 @@ int main(int /*argc*/, const char * /*argv*/ []) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
174
grpc/tests/grpctest.py
Normal file
174
grpc/tests/grpctest.py
Normal file
@@ -0,0 +1,174 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
import grpc
|
||||
import flatbuffers
|
||||
|
||||
from concurrent import futures
|
||||
|
||||
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..', 'tests'))
|
||||
import MyGame.Example.Monster as Monster
|
||||
import MyGame.Example.Stat as Stat
|
||||
import MyGame.Example.Vec3 as Vec3
|
||||
import MyGame.Example.Test as Test
|
||||
import MyGame.Example.monster_test_grpc_fb as monster_grpc_fb
|
||||
|
||||
|
||||
test_stat_id = "test_stat_id"
|
||||
test_stat_val = 8
|
||||
test_stat_count = 1
|
||||
|
||||
test_monster_name1 = "test_monster_name1"
|
||||
test_monster_name2 = "test_monster_name2"
|
||||
test_string = "test_string"
|
||||
test_color = 2
|
||||
test_X = 3.0
|
||||
test_Y = 2.0
|
||||
test_Z = 6.0
|
||||
test_test1 = 4.0
|
||||
test_a = 8
|
||||
test_b = 5
|
||||
test_hp = 67
|
||||
test_inventory = [1, 1, 2, 3, 5, 8]
|
||||
test_testtype = 4
|
||||
|
||||
test_monsters_name_retrieve = ["big_monster", "small_monster"]
|
||||
test_no_of_monsters = 2
|
||||
|
||||
|
||||
class MonsterStorage(monster_grpc_fb.MonsterStorageServicer):
|
||||
|
||||
def Store(self, request, context):
|
||||
|
||||
m = Monster.Monster().GetRootAsMonster(request, 0)
|
||||
|
||||
assert m.Name().decode("utf-8") == test_monster_name1
|
||||
|
||||
assert m.Pos().X() == test_X
|
||||
assert m.Pos().Y() == test_Y
|
||||
assert m.Pos().Z() == test_Z
|
||||
assert m.Pos().Test1() == test_test1
|
||||
assert m.Pos().Test2() == test_color
|
||||
test3 = Test.Test()
|
||||
assert m.Pos().Test3(test3).A() == test_a
|
||||
assert m.Pos().Test3(test3).B() == test_b
|
||||
|
||||
assert m.Hp() == test_hp
|
||||
|
||||
assert m.Color() == test_color
|
||||
|
||||
assert m.InventoryLength() == len(test_inventory)
|
||||
for i in range(0, len(test_inventory)):
|
||||
assert m.Inventory(i) == test_inventory[len(test_inventory)-i -1]
|
||||
|
||||
assert m.TestType() == test_testtype
|
||||
|
||||
assert m.Test() is not None
|
||||
table = m.Test()
|
||||
|
||||
m2 = Monster.Monster()
|
||||
m2.Init(table.Bytes, table.Pos)
|
||||
assert m2.Name().decode("utf-8") == test_monster_name2
|
||||
|
||||
m3 = m.Enemy()
|
||||
assert m3.Name().decode("utf-8") == test_monster_name2
|
||||
|
||||
assert m.Testarrayofstring(0).decode("utf-8") == test_string
|
||||
|
||||
b = flatbuffers.Builder(0)
|
||||
i = b.CreateString(test_stat_id)
|
||||
Stat.StatStart(b)
|
||||
Stat.StatAddId(b, i)
|
||||
Stat.StatAddVal(b, test_stat_val)
|
||||
Stat.StatAddCount(b, test_stat_count)
|
||||
b.Finish(Stat.StatEnd(b))
|
||||
return bytes(b.Output())
|
||||
|
||||
def Retrieve(self, request, context):
|
||||
|
||||
s = Stat.Stat().GetRootAsStat(request, 0)
|
||||
|
||||
no_of_monsters = test_no_of_monsters
|
||||
for i in range(0, no_of_monsters):
|
||||
b = flatbuffers.Builder(0)
|
||||
i = b.CreateString(test_monsters_name_retrieve[i])
|
||||
Monster.MonsterStart(b)
|
||||
Monster.MonsterAddName(b, i)
|
||||
b.Finish(Monster.MonsterEnd(b))
|
||||
yield bytes(b.Output())
|
||||
|
||||
|
||||
def serve():
|
||||
|
||||
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
|
||||
monster_grpc_fb.add_MonsterStorageServicer_to_server(MonsterStorage(), server)
|
||||
server.add_insecure_port('[::]:50051')
|
||||
|
||||
server.start()
|
||||
|
||||
run()
|
||||
|
||||
|
||||
def run():
|
||||
|
||||
channel = grpc.insecure_channel('127.0.0.1:50051')
|
||||
stub = monster_grpc_fb.MonsterStorageStub(channel)
|
||||
|
||||
b = flatbuffers.Builder(0)
|
||||
name2 = b.CreateString(test_monster_name2)
|
||||
name1 = b.CreateString(test_monster_name1)
|
||||
Monster.MonsterStart(b)
|
||||
Monster.MonsterAddName(b, name2)
|
||||
monster2 = Monster.MonsterEnd(b)
|
||||
test1 = b.CreateString(test_string)
|
||||
|
||||
Monster.MonsterStartInventoryVector(b, len(test_inventory))
|
||||
for i in range(0, len(test_inventory)):
|
||||
b.PrependByte(test_inventory[i])
|
||||
inv = b.EndVector(len(test_inventory))
|
||||
|
||||
Monster.MonsterStartTest4Vector(b, 2)
|
||||
Test.CreateTest(b, 10, 20)
|
||||
Test.CreateTest(b, 30, 40)
|
||||
test4 = b.EndVector(2)
|
||||
|
||||
Monster.MonsterStartTestarrayofstringVector(b, 1)
|
||||
b.PrependUOffsetTRelative(test1)
|
||||
test_array_of_string = b.EndVector(1)
|
||||
|
||||
Monster.MonsterStart(b)
|
||||
|
||||
Monster.MonsterAddHp(b, test_hp)
|
||||
Monster.MonsterAddName(b, name1)
|
||||
Monster.MonsterAddColor(b, test_color)
|
||||
pos = Vec3.CreateVec3(b, test_X, test_Y, test_Z, test_test1, test_color, test_a, test_b)
|
||||
Monster.MonsterAddPos(b, pos)
|
||||
Monster.MonsterAddInventory(b, inv)
|
||||
Monster.MonsterAddTestType(b, test_testtype)
|
||||
Monster.MonsterAddTest(b, monster2)
|
||||
Monster.MonsterAddTest4(b, test4)
|
||||
Monster.MonsterAddEnemy(b, monster2)
|
||||
Monster.MonsterAddTestarrayofstring(b, test_array_of_string)
|
||||
monster = Monster.MonsterEnd(b)
|
||||
|
||||
b.Finish(monster)
|
||||
|
||||
stat_response = stub.Store(bytes(b.Output()))
|
||||
|
||||
s = Stat.Stat().GetRootAsStat(stat_response, 0)
|
||||
|
||||
assert s.Id().decode("utf-8") == test_stat_id
|
||||
assert s.Val() == test_stat_val
|
||||
assert s.Count() == test_stat_count
|
||||
|
||||
monster_reponses = stub.Retrieve(stat_response)
|
||||
count = 0
|
||||
for monster_reponse in monster_reponses:
|
||||
m = Monster.Monster().GetRootAsMonster(monster_reponse, 0)
|
||||
assert m.Name().decode("utf-8") == test_monsters_name_retrieve[count]
|
||||
count = count + 1
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
serve()
|
||||
@@ -3,133 +3,158 @@
|
||||
#include "test_assert.h"
|
||||
#include "test_builder.h"
|
||||
|
||||
bool verify(flatbuffers::grpc::Message<Monster> &msg, const std::string &expected_name, Color color) {
|
||||
using MyGame::Example::Any_NONE;
|
||||
using MyGame::Example::CreateStat;
|
||||
using MyGame::Example::Vec3;
|
||||
|
||||
bool verify(flatbuffers::grpc::Message<Monster> &msg,
|
||||
const std::string &expected_name, Color expected_color) {
|
||||
const Monster *monster = msg.GetRoot();
|
||||
return (monster->name()->str() == expected_name) && (monster->color() == color);
|
||||
const auto name = monster->name()->str();
|
||||
const auto color = monster->color();
|
||||
TEST_EQ(name, expected_name);
|
||||
TEST_EQ(color, expected_color);
|
||||
return (name == expected_name) && (color == expected_color);
|
||||
}
|
||||
|
||||
bool release_n_verify(flatbuffers::grpc::MessageBuilder &mbb, const std::string &expected_name, Color color) {
|
||||
bool release_n_verify(flatbuffers::grpc::MessageBuilder &mbb,
|
||||
const std::string &expected_name, Color expected_color) {
|
||||
flatbuffers::grpc::Message<Monster> msg = mbb.ReleaseMessage<Monster>();
|
||||
const Monster *monster = msg.GetRoot();
|
||||
return (monster->name()->str() == expected_name) && (monster->color() == color);
|
||||
return verify(msg, expected_name, expected_color);
|
||||
}
|
||||
|
||||
template <>
|
||||
struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder> {
|
||||
static void builder_reusable_after_release_message_test(TestSelector selector) {
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE)) {
|
||||
return;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
flatbuffers::grpc::MessageBuilder b1;
|
||||
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(b1);
|
||||
b1.Finish(root_offset1);
|
||||
buffers.push_back(b1.ReleaseMessage<Monster>());
|
||||
TEST_ASSERT_FUNC(verify(buffers[i], m1_name, m1_color));
|
||||
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;
|
||||
}
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE)) { return; }
|
||||
|
||||
// FIXME: Populate-Release loop fails assert(GRPC_SLICE_IS_EMPTY(slice_)).
|
||||
// FIXME: Populate-Release loop fails assert(GRPC_SLICE_IS_EMPTY(slice_)) in
|
||||
// SliceAllocator::allocate in the second iteration.
|
||||
|
||||
flatbuffers::grpc::MessageBuilder b1;
|
||||
flatbuffers::grpc::MessageBuilder mb;
|
||||
std::vector<flatbuffers::DetachedBuffer> buffers;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
auto root_offset1 = populate1(b1);
|
||||
b1.Finish(root_offset1);
|
||||
buffers.push_back(b1.Release());
|
||||
TEST_ASSERT_FUNC(verify(buffers[i], m1_name, m1_color));
|
||||
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;
|
||||
}
|
||||
if (!selector.count(REUSABLE_AFTER_RELEASE_RAW)) { return; }
|
||||
|
||||
flatbuffers::grpc::MessageBuilder b1;
|
||||
flatbuffers::grpc::MessageBuilder mb;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
auto root_offset1 = populate1(b1);
|
||||
b1.Finish(root_offset1);
|
||||
auto root_offset1 = populate1(mb);
|
||||
mb.Finish(root_offset1);
|
||||
size_t size, offset;
|
||||
grpc_slice slice;
|
||||
const uint8_t *buf = b1.ReleaseRaw(size, offset, slice);
|
||||
TEST_ASSERT_FUNC(verify(buf, offset, m1_name, m1_color));
|
||||
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;
|
||||
}
|
||||
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_)).
|
||||
// FIXME: Release-move_assign loop fails assert(p ==
|
||||
// GRPC_SLICE_START_PTR(slice_)) in DetachedBuffer destructor after all the
|
||||
// iterations
|
||||
|
||||
flatbuffers::grpc::MessageBuilder b1;
|
||||
flatbuffers::grpc::MessageBuilder dst;
|
||||
std::vector<flatbuffers::DetachedBuffer> buffers;
|
||||
|
||||
for (int i = 0; i < 1; ++i) {
|
||||
auto root_offset1 = populate1(b1);
|
||||
b1.Finish(root_offset1);
|
||||
buffers.push_back(b1.Release());
|
||||
TEST_ASSERT_FUNC(verify(buffers[i], m1_name, m1_color));
|
||||
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 b1 back to life.
|
||||
flatbuffers::grpc::MessageBuilder b2;
|
||||
b1 = std::move(b2);
|
||||
TEST_EQ_FUNC(b1.GetSize(), 0);
|
||||
TEST_EQ_FUNC(b2.GetSize(), 0);
|
||||
// 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) {
|
||||
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 b1;
|
||||
flatbuffers::grpc::MessageBuilder dst;
|
||||
std::vector<flatbuffers::grpc::Message<Monster>> buffers;
|
||||
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
auto root_offset1 = populate1(b1);
|
||||
b1.Finish(root_offset1);
|
||||
buffers.push_back(b1.ReleaseMessage<Monster>());
|
||||
TEST_ASSERT_FUNC(verify(buffers[i], m1_name, m1_color));
|
||||
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 b1 back to life.
|
||||
flatbuffers::grpc::MessageBuilder b2;
|
||||
b1 = std::move(b2);
|
||||
TEST_EQ_FUNC(b1.GetSize(), 0);
|
||||
TEST_EQ_FUNC(b2.GetSize(), 0);
|
||||
// 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;
|
||||
}
|
||||
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 b1;
|
||||
flatbuffers::grpc::MessageBuilder dst;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
auto root_offset1 = populate1(b1);
|
||||
b1.Finish(root_offset1);
|
||||
auto root_offset1 = populate1(dst);
|
||||
dst.Finish(root_offset1);
|
||||
size_t size, offset;
|
||||
grpc_slice slice = grpc_empty_slice();
|
||||
const uint8_t *buf = b1.ReleaseRaw(size, offset, slice);
|
||||
TEST_ASSERT_FUNC(verify(buf, offset, m1_name, m1_color));
|
||||
const uint8_t *buf = dst.ReleaseRaw(size, offset, slice);
|
||||
TEST_ASSERT_FUNC(verify(buf, offset, m1_name(), m1_color()));
|
||||
grpc_slice_unref(slice);
|
||||
|
||||
flatbuffers::grpc::MessageBuilder b2;
|
||||
b1 = std::move(b2);
|
||||
TEST_EQ_FUNC(b1.GetSize(), 0);
|
||||
TEST_EQ_FUNC(b2.GetSize(), 0);
|
||||
SrcBuilder src;
|
||||
dst = std::move(src);
|
||||
TEST_EQ_FUNC(dst.GetSize(), 0);
|
||||
TEST_EQ_FUNC(src.GetSize(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,11 +176,11 @@ void slice_allocator_tests() {
|
||||
uint8_t *buf = sa1.allocate(size);
|
||||
TEST_ASSERT_FUNC(buf != 0);
|
||||
buf[0] = 100;
|
||||
buf[size-1] = 200;
|
||||
buf[size - 1] = 200;
|
||||
flatbuffers::grpc::SliceAllocator sa2(std::move(sa1));
|
||||
// buf should be deleted after move-construct
|
||||
// buf should not be deleted after move-construct
|
||||
TEST_EQ_FUNC(buf[0], 100);
|
||||
TEST_EQ_FUNC(buf[size-1], 200);
|
||||
TEST_EQ_FUNC(buf[size - 1], 200);
|
||||
// buf is freed here
|
||||
}
|
||||
|
||||
@@ -170,19 +195,177 @@ void slice_allocator_tests() {
|
||||
}
|
||||
}
|
||||
|
||||
/// This function does not populate exactly the first half of the table. But it
|
||||
/// could.
|
||||
void populate_first_half(MyGame::Example::MonsterBuilder &wrapper,
|
||||
flatbuffers::Offset<flatbuffers::String> name_offset) {
|
||||
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 = 1; initial_size <= 2048; initial_size += 1) {
|
||||
flatbuffers::FlatBufferBuilder fbb(initial_size);
|
||||
auto stat_offset = CreateStat(fbb, fbb.CreateString("SomeId"), 0, 0);
|
||||
flatbuffers::grpc::MessageBuilder mb(std::move(fbb));
|
||||
auto monster_offset =
|
||||
CreateMonster(mb, 0, 150, 100, mb.CreateString(m1_name()), 0,
|
||||
m1_color(), Any_NONE, 0, 0, 0, 0, 0, 0, stat_offset);
|
||||
mb.Finish(monster_offset);
|
||||
{
|
||||
auto mon = flatbuffers::GetRoot<Monster>(mb.GetBufferPointer());
|
||||
TEST_NOTNULL(mon);
|
||||
TEST_NOTNULL(mon->name());
|
||||
TEST_EQ_STR(mon->name()->c_str(), m1_name().c_str());
|
||||
TEST_EQ(mon->color(), m1_color());
|
||||
}
|
||||
TEST_EQ(1, MyGame::Example::Color_Red);
|
||||
TEST_EQ(1, m1_color());
|
||||
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name(), m1_color()));
|
||||
TEST_EQ_FUNC(fbb.GetSize(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/// This test validates correctness of move conversion of FlatBufferBuilder to a
|
||||
/// MessageBuilder DURING a table construction. Half of the table is constructed
|
||||
/// using FlatBufferBuilder and the other half of the table is constructed using
|
||||
/// a MessageBuilder.
|
||||
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::FlatBufferBuilder;
|
||||
using flatbuffers::grpc::MessageBuilder;
|
||||
|
||||
slice_allocator_tests();
|
||||
BuilderTests<flatbuffers::grpc::MessageBuilder>::all_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, // Assertion failed:
|
||||
// (GRPC_SLICE_IS_EMPTY(slice_))
|
||||
// REUSABLE_AFTER_RELEASE_AND_MOVE_ASSIGN, // Assertion failed: (p ==
|
||||
// GRPC_SLICE_START_PTR(slice_)
|
||||
|
||||
REUSABLE_AFTER_RELEASE_RAW,
|
||||
REUSABLE_AFTER_RELEASE_MESSAGE,
|
||||
REUSABLE_AFTER_RELEASE_RAW, REUSABLE_AFTER_RELEASE_MESSAGE,
|
||||
REUSABLE_AFTER_RELEASE_MESSAGE_AND_MOVE_ASSIGN,
|
||||
REUSABLE_AFTER_RELEASE_RAW_AND_MOVE_ASSIGN
|
||||
};
|
||||
|
||||
BuilderReuseTests<flatbuffers::grpc::MessageBuilder>::run_tests(TestSelector(tests, tests+6));
|
||||
BuilderReuseTests<MessageBuilder, MessageBuilder>::run_tests(
|
||||
TestSelector(tests, tests + 6));
|
||||
BuilderReuseTests<MessageBuilder, FlatBufferBuilder>::run_tests(
|
||||
TestSelector(tests, tests + 6));
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
<parent>
|
||||
<groupId>com.google.flatbuffers</groupId>
|
||||
<artifactId>flatbuffers-parent</artifactId>
|
||||
<version>1.10.0</version>
|
||||
<version>1.12.0</version>
|
||||
</parent>
|
||||
<artifactId>grpc-test</artifactId>
|
||||
<description>Example/Test project demonstrating usage of flatbuffers with GRPC-Java instead of protobufs
|
||||
</description>
|
||||
<properties>
|
||||
<gRPC.version>1.9.0</gRPC.version>
|
||||
<gRPC.version>1.12.0</gRPC.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@@ -2,15 +2,26 @@
|
||||
#define FLATBUFFERS_BASE_H_
|
||||
|
||||
// clang-format off
|
||||
|
||||
// If activate should be declared and included first.
|
||||
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
|
||||
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
|
||||
#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
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#if !defined(FLATBUFFERS_ASSERT)
|
||||
#include <assert.h>
|
||||
#define FLATBUFFERS_ASSERT assert
|
||||
#elif defined(FLATBUFFERS_ASSERT_INCLUDE)
|
||||
// Include file with forward declaration
|
||||
#include FLATBUFFERS_ASSERT_INCLUDE
|
||||
#endif
|
||||
|
||||
#ifndef ARDUINO
|
||||
@@ -21,13 +32,6 @@
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
|
||||
defined(_MSC_VER) && defined(_DEBUG)
|
||||
#include <crtdbg.h>
|
||||
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__)
|
||||
#define new DEBUG_NEW
|
||||
#endif
|
||||
|
||||
#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H)
|
||||
#include <utility.h>
|
||||
#else
|
||||
@@ -51,12 +55,37 @@
|
||||
|
||||
#include "flatbuffers/stl_emulation.h"
|
||||
|
||||
#if defined(__ICCARM__)
|
||||
#include <intrinsics.h>
|
||||
#endif
|
||||
|
||||
// Note the __clang__ check is needed, because clang presents itself
|
||||
// as an older GNUC compiler (4.2).
|
||||
// Clang 3.3 and later implement all of the ISO C++ 2011 standard.
|
||||
// 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
|
||||
#if __cplusplus <= 199711L && \
|
||||
(!defined(_MSC_VER) || _MSC_VER < 1600) && \
|
||||
@@ -70,7 +99,7 @@
|
||||
#if !defined(__clang__) && \
|
||||
defined(__GNUC__) && \
|
||||
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600)
|
||||
// Backwards compatability for g++ 4.4, and 4.5 which don't have the nullptr
|
||||
// Backwards compatibility for g++ 4.4, and 4.5 which don't have the nullptr
|
||||
// and constexpr keywords. Note the __clang__ check is needed, because clang
|
||||
// presents itself as an older GNUC compiler.
|
||||
#ifndef nullptr_t
|
||||
@@ -92,8 +121,9 @@
|
||||
#define FLATBUFFERS_LITTLEENDIAN 0
|
||||
#endif // __s390x__
|
||||
#if !defined(FLATBUFFERS_LITTLEENDIAN)
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#ifdef __BIG_ENDIAN__
|
||||
#if defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
|
||||
#if (defined(__BIG_ENDIAN__) || \
|
||||
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
|
||||
#define FLATBUFFERS_LITTLEENDIAN 0
|
||||
#else
|
||||
#define FLATBUFFERS_LITTLEENDIAN 1
|
||||
@@ -110,19 +140,25 @@
|
||||
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
|
||||
|
||||
#define FLATBUFFERS_VERSION_MAJOR 1
|
||||
#define FLATBUFFERS_VERSION_MINOR 10
|
||||
#define FLATBUFFERS_VERSION_MINOR 12
|
||||
#define FLATBUFFERS_VERSION_REVISION 0
|
||||
#define FLATBUFFERS_STRING_EXPAND(X) #X
|
||||
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
|
||||
namespace flatbuffers {
|
||||
// Returns version as string "MAJOR.MINOR.REVISION".
|
||||
const char* FLATBUFFERS_VERSION();
|
||||
}
|
||||
|
||||
#if (!defined(_MSC_VER) || _MSC_VER > 1600) && \
|
||||
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407)) || \
|
||||
defined(__clang__)
|
||||
#define FLATBUFFERS_FINAL_CLASS final
|
||||
#define FLATBUFFERS_OVERRIDE override
|
||||
#define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t
|
||||
#else
|
||||
#define FLATBUFFERS_FINAL_CLASS
|
||||
#define FLATBUFFERS_OVERRIDE
|
||||
#define FLATBUFFERS_VTABLE_UNDERLYING_TYPE
|
||||
#endif
|
||||
|
||||
#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
|
||||
@@ -130,7 +166,7 @@
|
||||
(defined(__cpp_constexpr) && __cpp_constexpr >= 200704)
|
||||
#define FLATBUFFERS_CONSTEXPR constexpr
|
||||
#else
|
||||
#define FLATBUFFERS_CONSTEXPR
|
||||
#define FLATBUFFERS_CONSTEXPR const
|
||||
#endif
|
||||
|
||||
#if (defined(__cplusplus) && __cplusplus >= 201402L) || \
|
||||
@@ -163,7 +199,7 @@
|
||||
// to detect a header that provides an implementation
|
||||
#if defined(__has_include)
|
||||
// Check for std::string_view (in c++17)
|
||||
#if __has_include(<string_view>) && (__cplusplus >= 201606 || _HAS_CXX17)
|
||||
#if __has_include(<string_view>) && (__cplusplus >= 201606 || (defined(_HAS_CXX17) && _HAS_CXX17))
|
||||
#include <string_view>
|
||||
namespace flatbuffers {
|
||||
typedef std::string_view string_view;
|
||||
@@ -176,10 +212,76 @@
|
||||
typedef std::experimental::string_view string_view;
|
||||
}
|
||||
#define FLATBUFFERS_HAS_STRING_VIEW 1
|
||||
// Check for absl::string_view
|
||||
#elif __has_include("absl/strings/string_view.h")
|
||||
#include "absl/strings/string_view.h"
|
||||
namespace flatbuffers {
|
||||
typedef absl::string_view string_view;
|
||||
}
|
||||
#define FLATBUFFERS_HAS_STRING_VIEW 1
|
||||
#endif
|
||||
#endif // __has_include
|
||||
#endif // !FLATBUFFERS_HAS_STRING_VIEW
|
||||
|
||||
#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__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7))
|
||||
#define __supress_ubsan__(type) __attribute__((no_sanitize(type)))
|
||||
#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
|
||||
#define __supress_ubsan__(type) __attribute__((no_sanitize_undefined))
|
||||
#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
|
||||
|
||||
/// @endcond
|
||||
|
||||
/// @file
|
||||
@@ -201,7 +303,7 @@ typedef uint16_t voffset_t;
|
||||
typedef uintmax_t largest_scalar_t;
|
||||
|
||||
// In 32bits, this evaluates to 2GB - 1
|
||||
#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(soffset_t) * 8 - 1)) - 1)
|
||||
#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(::flatbuffers::soffset_t) * 8 - 1)) - 1)
|
||||
|
||||
// We support aligning the contents of buffers up to this size.
|
||||
#define FLATBUFFERS_MAX_ALIGNMENT 16
|
||||
@@ -216,6 +318,11 @@ template<typename T> T EndianSwap(T t) {
|
||||
#define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
|
||||
#define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
|
||||
#define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
|
||||
#elif defined(__ICCARM__)
|
||||
#define FLATBUFFERS_BYTESWAP16 __REV16
|
||||
#define FLATBUFFERS_BYTESWAP32 __REV
|
||||
#define FLATBUFFERS_BYTESWAP64(x) \
|
||||
((__REV(static_cast<uint32_t>(x >> 32U))) | (static_cast<uint64_t>(__REV(static_cast<uint32_t>(x)))) << 32U)
|
||||
#else
|
||||
#if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__)
|
||||
// __builtin_bswap16 was missing prior to GCC 4.8.
|
||||
@@ -230,22 +337,20 @@ template<typename T> T EndianSwap(T t) {
|
||||
if (sizeof(T) == 1) { // Compile-time if-then's.
|
||||
return t;
|
||||
} else if (sizeof(T) == 2) {
|
||||
union { T t; uint16_t i; } u;
|
||||
u.t = t;
|
||||
union { T t; uint16_t i; } u = { t };
|
||||
u.i = FLATBUFFERS_BYTESWAP16(u.i);
|
||||
return u.t;
|
||||
} else if (sizeof(T) == 4) {
|
||||
union { T t; uint32_t i; } u;
|
||||
u.t = t;
|
||||
union { T t; uint32_t i; } u = { t };
|
||||
u.i = FLATBUFFERS_BYTESWAP32(u.i);
|
||||
return u.t;
|
||||
} else if (sizeof(T) == 8) {
|
||||
union { T t; uint64_t i; } u;
|
||||
u.t = t;
|
||||
union { T t; uint64_t i; } u = { t };
|
||||
u.i = FLATBUFFERS_BYTESWAP64(u.i);
|
||||
return u.t;
|
||||
} else {
|
||||
FLATBUFFERS_ASSERT(0);
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,17 +367,29 @@ template<typename T> T EndianScalar(T t) {
|
||||
#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));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
// "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in
|
||||
// memory).
|
||||
__supress_ubsan__("unsigned-integer-overflow")
|
||||
inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
|
||||
return ((~buf_size) + 1) & (scalar_size - 1);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
||||
#include "flatbuffers/idl.h"
|
||||
|
||||
namespace flatbuffers {
|
||||
@@ -26,7 +27,7 @@ namespace flatbuffers {
|
||||
// Utility class to assist in generating code through use of text templates.
|
||||
//
|
||||
// Example code:
|
||||
// CodeWriter code;
|
||||
// CodeWriter code("\t");
|
||||
// code.SetValue("NAME", "Foo");
|
||||
// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
|
||||
// code.SetValue("NAME", "Bar");
|
||||
@@ -38,7 +39,8 @@ namespace flatbuffers {
|
||||
// void Bar() { printf("%s", "Bar"); }
|
||||
class CodeWriter {
|
||||
public:
|
||||
CodeWriter() {}
|
||||
CodeWriter(std::string pad = std::string())
|
||||
: pad_(pad), cur_ident_lvl_(0), ignore_ident_(false) {}
|
||||
|
||||
// Clears the current "written" code.
|
||||
void Clear() {
|
||||
@@ -53,6 +55,11 @@ class CodeWriter {
|
||||
value_map_[key] = value;
|
||||
}
|
||||
|
||||
std::string GetValue(const std::string &key) const {
|
||||
const auto it = value_map_.find(key);
|
||||
return it == value_map_.end() ? "" : it->second;
|
||||
}
|
||||
|
||||
// Appends the given text to the generated code as well as a newline
|
||||
// character. Any text within {{ and }} delimeters is replaced by values
|
||||
// previously stored in the CodeWriter by calling SetValue above. The newline
|
||||
@@ -62,9 +69,22 @@ class CodeWriter {
|
||||
// Returns the current contents of the CodeWriter as a std::string.
|
||||
std::string ToString() const { return stream_.str(); }
|
||||
|
||||
// Increase ident level for writing code
|
||||
void IncrementIdentLevel() { cur_ident_lvl_++; }
|
||||
// Decrease ident level for writing code
|
||||
void DecrementIdentLevel() {
|
||||
if (cur_ident_lvl_) cur_ident_lvl_--;
|
||||
}
|
||||
|
||||
private:
|
||||
std::map<std::string, std::string> value_map_;
|
||||
std::stringstream stream_;
|
||||
std::string pad_;
|
||||
int cur_ident_lvl_;
|
||||
bool ignore_ident_;
|
||||
|
||||
// Add ident padding (tab or space) based on ident level
|
||||
void AppendIdent(std::stringstream &stream);
|
||||
};
|
||||
|
||||
class BaseGenerator {
|
||||
@@ -74,16 +94,20 @@ class BaseGenerator {
|
||||
static std::string NamespaceDir(const Parser &parser, const std::string &path,
|
||||
const Namespace &ns);
|
||||
|
||||
std::string GeneratedFileName(const std::string &path,
|
||||
const std::string &file_name,
|
||||
const IDLOptions &options) const;
|
||||
|
||||
protected:
|
||||
BaseGenerator(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name,
|
||||
const std::string qualifying_start,
|
||||
const std::string qualifying_separator)
|
||||
const std::string &file_name, std::string qualifying_start,
|
||||
std::string qualifying_separator, std::string default_extension)
|
||||
: parser_(parser),
|
||||
path_(path),
|
||||
file_name_(file_name),
|
||||
qualifying_start_(qualifying_start),
|
||||
qualifying_separator_(qualifying_separator) {}
|
||||
qualifying_separator_(qualifying_separator),
|
||||
default_extension_(default_extension) {}
|
||||
virtual ~BaseGenerator() {}
|
||||
|
||||
// No copy/assign.
|
||||
@@ -104,8 +128,9 @@ class BaseGenerator {
|
||||
// which works for js and php
|
||||
virtual const Namespace *CurrentNameSpace() const { return nullptr; }
|
||||
|
||||
// Ensure that a type is prefixed with its namespace whenever it is used
|
||||
// outside of its namespace.
|
||||
// Ensure that a type is prefixed with its namespace even within
|
||||
// its own namespace to avoid conflict between generated method
|
||||
// names and similarly named classes or structs
|
||||
std::string WrapInNameSpace(const Namespace *ns,
|
||||
const std::string &name) const;
|
||||
|
||||
@@ -118,6 +143,7 @@ class BaseGenerator {
|
||||
const std::string &file_name_;
|
||||
const std::string qualifying_start_;
|
||||
const std::string qualifying_separator_;
|
||||
const std::string default_extension_;
|
||||
};
|
||||
|
||||
struct CommentConfig {
|
||||
@@ -130,6 +156,74 @@ extern void GenComment(const std::vector<std::string> &dc,
|
||||
std::string *code_ptr, const CommentConfig *config,
|
||||
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
|
||||
|
||||
#endif // FLATBUFFERS_CODE_GENERATORS_H_
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -14,18 +14,22 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef FLATBUFFERS_FLATC_H_
|
||||
#define FLATBUFFERS_FLATC_H_
|
||||
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include "flatbuffers/flatbuffers.h"
|
||||
#include "flatbuffers/idl.h"
|
||||
#include "flatbuffers/util.h"
|
||||
|
||||
#ifndef FLATC_H_
|
||||
# define FLATC_H_
|
||||
|
||||
namespace flatbuffers {
|
||||
|
||||
extern void LogCompilerWarn(const std::string &warn);
|
||||
extern void LogCompilerError(const std::string &err);
|
||||
|
||||
class FlatCompiler {
|
||||
public:
|
||||
// Output generator for the various programming languages and formats we
|
||||
@@ -80,6 +84,9 @@ class FlatCompiler {
|
||||
const std::string &contents,
|
||||
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 Error(const std::string &err, bool usage = true,
|
||||
@@ -90,4 +97,4 @@ class FlatCompiler {
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATC_H_
|
||||
#endif // FLATBUFFERS_FLATC_H_
|
||||
|
||||
@@ -65,7 +65,9 @@ enum Type {
|
||||
FBT_VECTOR_UINT = 12,
|
||||
FBT_VECTOR_FLOAT = 13,
|
||||
FBT_VECTOR_KEY = 14,
|
||||
FBT_VECTOR_STRING = 15,
|
||||
// DEPRECATED, use FBT_VECTOR or FBT_VECTOR_KEY instead.
|
||||
// Read test.cpp/FlexBuffersDeprecatedTest() for details on why.
|
||||
FBT_VECTOR_STRING_DEPRECATED = 15,
|
||||
FBT_VECTOR_INT2 = 16, // Typed tuple (no type table, no size field).
|
||||
FBT_VECTOR_UINT2 = 17,
|
||||
FBT_VECTOR_FLOAT2 = 18,
|
||||
@@ -88,7 +90,7 @@ inline bool IsTypedVectorElementType(Type t) {
|
||||
}
|
||||
|
||||
inline bool IsTypedVector(Type t) {
|
||||
return (t >= FBT_VECTOR_INT && t <= FBT_VECTOR_STRING) ||
|
||||
return (t >= FBT_VECTOR_INT && t <= FBT_VECTOR_STRING_DEPRECATED) ||
|
||||
t == FBT_VECTOR_BOOL;
|
||||
}
|
||||
|
||||
@@ -153,7 +155,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
|
||||
// the conditionals in ReadSizedScalar. Can also use inline asm.
|
||||
// clang-format off
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && (defined(_M_X64) || defined _M_IX86)
|
||||
uint64_t u = 0;
|
||||
__movsb(reinterpret_cast<uint8_t *>(&u),
|
||||
reinterpret_cast<const uint8_t *>(data), byte_width);
|
||||
@@ -212,26 +214,40 @@ class Object {
|
||||
uint8_t byte_width_;
|
||||
};
|
||||
|
||||
// Stores size in `byte_width_` bytes before data_ pointer.
|
||||
// Object that has a size, obtained either from size prefix, or elsewhere.
|
||||
class Sized : public Object {
|
||||
public:
|
||||
Sized(const uint8_t *data, uint8_t byte_width) : Object(data, byte_width) {}
|
||||
size_t size() const {
|
||||
// Size prefix.
|
||||
Sized(const uint8_t *data, uint8_t byte_width)
|
||||
: Object(data, byte_width), size_(read_size()) {}
|
||||
// Manual size.
|
||||
Sized(const uint8_t *data, uint8_t byte_width, size_t sz)
|
||||
: Object(data, byte_width), size_(sz) {}
|
||||
size_t size() const { return size_; }
|
||||
// Access size stored in `byte_width_` bytes before data_ pointer.
|
||||
size_t read_size() const {
|
||||
return static_cast<size_t>(ReadUInt64(data_ - byte_width_, byte_width_));
|
||||
}
|
||||
|
||||
protected:
|
||||
size_t size_;
|
||||
};
|
||||
|
||||
class String : public Sized {
|
||||
public:
|
||||
// Size prefix.
|
||||
String(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {}
|
||||
// Manual size.
|
||||
String(const uint8_t *data, uint8_t byte_width, size_t sz)
|
||||
: Sized(data, byte_width, sz) {}
|
||||
|
||||
size_t length() const { return size(); }
|
||||
const char *c_str() const { return reinterpret_cast<const char *>(data_); }
|
||||
std::string str() const { return std::string(c_str(), length()); }
|
||||
std::string str() const { return std::string(c_str(), size()); }
|
||||
|
||||
static String EmptyString() {
|
||||
static const uint8_t empty_string[] = { 0 /*len*/, 0 /*terminator*/ };
|
||||
return String(empty_string + 1, 1);
|
||||
static const char *empty_string = "";
|
||||
return String(reinterpret_cast<const uint8_t *>(empty_string), 1, 0);
|
||||
}
|
||||
bool IsTheEmptyString() const { return data_ == EmptyString().data_; }
|
||||
};
|
||||
@@ -279,6 +295,8 @@ class TypedVector : public Sized {
|
||||
|
||||
Type ElementType() { return type_; }
|
||||
|
||||
friend Reference;
|
||||
|
||||
private:
|
||||
Type type_;
|
||||
|
||||
@@ -337,8 +355,24 @@ class Map : public Vector {
|
||||
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 {
|
||||
public:
|
||||
Reference()
|
||||
: data_(nullptr),
|
||||
parent_width_(0),
|
||||
byte_width_(BIT_WIDTH_8),
|
||||
type_(FBT_NULL) {}
|
||||
|
||||
Reference(const uint8_t *data, uint8_t parent_width, uint8_t byte_width,
|
||||
Type type)
|
||||
: data_(data),
|
||||
@@ -368,15 +402,19 @@ class Reference {
|
||||
bool IsString() const { return type_ == FBT_STRING; }
|
||||
bool IsKey() const { return type_ == FBT_KEY; }
|
||||
bool IsVector() const { return type_ == FBT_VECTOR || type_ == FBT_MAP; }
|
||||
bool IsUntypedVector() const { return type_ == FBT_VECTOR; }
|
||||
bool IsTypedVector() const { return flexbuffers::IsTypedVector(type_); }
|
||||
bool IsFixedTypedVector() const { return flexbuffers::IsFixedTypedVector(type_); }
|
||||
bool IsAnyVector() const { return (IsTypedVector() || IsFixedTypedVector() || IsVector());}
|
||||
bool IsFixedTypedVector() const {
|
||||
return flexbuffers::IsFixedTypedVector(type_);
|
||||
}
|
||||
bool IsAnyVector() const {
|
||||
return (IsTypedVector() || IsFixedTypedVector() || IsVector());
|
||||
}
|
||||
bool IsMap() const { return type_ == FBT_MAP; }
|
||||
bool IsBlob() const { return type_ == FBT_BLOB; }
|
||||
|
||||
bool AsBool() const {
|
||||
return (type_ == FBT_BOOL ? ReadUInt64(data_, parent_width_)
|
||||
: AsUInt64()) != 0;
|
||||
: AsUInt64()) != 0;
|
||||
}
|
||||
|
||||
// Reads any type as a int64_t. Never fails, does most sensible conversion.
|
||||
@@ -454,7 +492,11 @@ class Reference {
|
||||
case FBT_INDIRECT_UINT:
|
||||
return static_cast<double>(ReadUInt64(Indirect(), byte_width_));
|
||||
case FBT_NULL: return 0.0;
|
||||
case FBT_STRING: return strtod(AsString().c_str(), nullptr);
|
||||
case FBT_STRING: {
|
||||
double d;
|
||||
flatbuffers::StringToNumber(AsString().c_str(), &d);
|
||||
return d;
|
||||
}
|
||||
case FBT_VECTOR: return static_cast<double>(AsVector().size());
|
||||
case FBT_BOOL:
|
||||
return static_cast<double>(ReadUInt64(data_, parent_width_));
|
||||
@@ -467,24 +509,29 @@ class Reference {
|
||||
float AsFloat() const { return static_cast<float>(AsDouble()); }
|
||||
|
||||
const char *AsKey() const {
|
||||
if (type_ == FBT_KEY) {
|
||||
if (type_ == FBT_KEY || type_ == FBT_STRING) {
|
||||
return reinterpret_cast<const char *>(Indirect());
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// This function returns the empty string if you try to read a not-string.
|
||||
// This function returns the empty string if you try to read something that
|
||||
// is not a string or key.
|
||||
String AsString() const {
|
||||
if (type_ == FBT_STRING) {
|
||||
return String(Indirect(), byte_width_);
|
||||
} else if (type_ == FBT_KEY) {
|
||||
auto key = Indirect();
|
||||
return String(key, byte_width_,
|
||||
strlen(reinterpret_cast<const char *>(key)));
|
||||
} else {
|
||||
return String::EmptyString();
|
||||
}
|
||||
}
|
||||
|
||||
// Unlike AsString(), this will convert any type to a std::string.
|
||||
std::string ToString() {
|
||||
std::string ToString() const {
|
||||
std::string s;
|
||||
ToString(false, false, s);
|
||||
return s;
|
||||
@@ -532,13 +579,15 @@ class Reference {
|
||||
}
|
||||
s += " }";
|
||||
} else if (IsVector()) {
|
||||
s += "[ ";
|
||||
auto v = AsVector();
|
||||
for (size_t i = 0; i < v.size(); i++) {
|
||||
v[i].ToString(true, keys_quoted, s);
|
||||
if (i < v.size() - 1) s += ", ";
|
||||
}
|
||||
s += " ]";
|
||||
AppendToString<Vector>(s, AsVector(), keys_quoted);
|
||||
} else if (IsTypedVector()) {
|
||||
AppendToString<TypedVector>(s, AsTypedVector(), keys_quoted);
|
||||
} else if (IsFixedTypedVector()) {
|
||||
AppendToString<FixedTypedVector>(s, AsFixedTypedVector(), keys_quoted);
|
||||
} else if (IsBlob()) {
|
||||
auto blob = AsBlob();
|
||||
flatbuffers::EscapeString(reinterpret_cast<const char *>(blob.data()),
|
||||
blob.size(), &s, true, false);
|
||||
} else {
|
||||
s += "(?)";
|
||||
}
|
||||
@@ -566,8 +615,18 @@ class Reference {
|
||||
|
||||
TypedVector AsTypedVector() const {
|
||||
if (IsTypedVector()) {
|
||||
return TypedVector(Indirect(), byte_width_,
|
||||
ToTypedVectorElementType(type_));
|
||||
auto tv =
|
||||
TypedVector(Indirect(), byte_width_, ToTypedVectorElementType(type_));
|
||||
if (tv.type_ == FBT_STRING) {
|
||||
// These can't be accessed as strings, since we don't know the bit-width
|
||||
// of the size field, see the declaration of
|
||||
// FBT_VECTOR_STRING_DEPRECATED above for details.
|
||||
// We change the type here to be keys, which are a subtype of strings,
|
||||
// and will ignore the size field. This will truncate strings with
|
||||
// embedded nulls.
|
||||
tv.type_ = FBT_KEY;
|
||||
}
|
||||
return tv;
|
||||
} else {
|
||||
return TypedVector::EmptyTypedVector();
|
||||
}
|
||||
@@ -591,7 +650,7 @@ class Reference {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> T As();
|
||||
template<typename T> T As() const;
|
||||
|
||||
// Experimental: Mutation functions.
|
||||
// These allow scalars in an already created buffer to be updated in-place.
|
||||
@@ -704,35 +763,41 @@ class Reference {
|
||||
};
|
||||
|
||||
// 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 int16_t Reference::As<int16_t>() { return AsInt16(); }
|
||||
template<> inline int32_t Reference::As<int32_t>() { return AsInt32(); }
|
||||
template<> inline int64_t Reference::As<int64_t>() { return AsInt64(); }
|
||||
template<> inline int8_t Reference::As<int8_t>() const { return AsInt8(); }
|
||||
template<> inline int16_t Reference::As<int16_t>() const { return AsInt16(); }
|
||||
template<> inline int32_t Reference::As<int32_t>() const { return AsInt32(); }
|
||||
template<> inline int64_t Reference::As<int64_t>() const { return AsInt64(); }
|
||||
|
||||
template<> inline uint8_t Reference::As<uint8_t>() { return AsUInt8(); }
|
||||
template<> inline uint16_t Reference::As<uint16_t>() { return AsUInt16(); }
|
||||
template<> inline uint32_t Reference::As<uint32_t>() { return AsUInt32(); }
|
||||
template<> inline uint64_t Reference::As<uint64_t>() { return AsUInt64(); }
|
||||
template<> inline uint8_t Reference::As<uint8_t>() const { return AsUInt8(); }
|
||||
template<> inline uint16_t Reference::As<uint16_t>() const {
|
||||
return AsUInt16();
|
||||
}
|
||||
template<> inline uint32_t Reference::As<uint32_t>() const {
|
||||
return AsUInt32();
|
||||
}
|
||||
template<> inline uint64_t Reference::As<uint64_t>() const {
|
||||
return AsUInt64();
|
||||
}
|
||||
|
||||
template<> inline double Reference::As<double>() { return AsDouble(); }
|
||||
template<> inline float Reference::As<float>() { return AsFloat(); }
|
||||
template<> inline double Reference::As<double>() const { return AsDouble(); }
|
||||
template<> inline float Reference::As<float>() const { return AsFloat(); }
|
||||
|
||||
template<> inline String Reference::As<String>() { return AsString(); }
|
||||
template<> inline std::string Reference::As<std::string>() {
|
||||
template<> inline String Reference::As<String>() const { return AsString(); }
|
||||
template<> inline std::string Reference::As<std::string>() const {
|
||||
return AsString().str();
|
||||
}
|
||||
|
||||
template<> inline Blob Reference::As<Blob>() { return AsBlob(); }
|
||||
template<> inline Vector Reference::As<Vector>() { return AsVector(); }
|
||||
template<> inline TypedVector Reference::As<TypedVector>() {
|
||||
template<> inline Blob Reference::As<Blob>() const { return AsBlob(); }
|
||||
template<> inline Vector Reference::As<Vector>() const { return AsVector(); }
|
||||
template<> inline TypedVector Reference::As<TypedVector>() const {
|
||||
return AsTypedVector();
|
||||
}
|
||||
template<> inline FixedTypedVector Reference::As<FixedTypedVector>() {
|
||||
template<> inline FixedTypedVector Reference::As<FixedTypedVector>() const {
|
||||
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) {
|
||||
return static_cast<uint8_t>(bit_width | (type << 2));
|
||||
@@ -1035,7 +1100,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
for (auto key = start; key < stack_.size(); key += 2) {
|
||||
FLATBUFFERS_ASSERT(stack_[key].type_ == FBT_KEY);
|
||||
}
|
||||
// Now sort values, so later we can do a binary seach lookup.
|
||||
// Now sort values, so later we can do a binary search lookup.
|
||||
// We want to sort 2 array elements at a time.
|
||||
struct TwoValue {
|
||||
Value key;
|
||||
@@ -1183,6 +1248,24 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
EndMap(start);
|
||||
}
|
||||
|
||||
// If you wish to share a value explicitly (a value not shared automatically
|
||||
// through one of the BUILDER_FLAG_SHARE_* flags) you can do so with these
|
||||
// functions. Or if you wish to turn those flags off for performance reasons
|
||||
// and still do some explicit sharing. For example:
|
||||
// builder.IndirectDouble(M_PI);
|
||||
// auto id = builder.LastValue(); // Remember where we stored it.
|
||||
// .. more code goes here ..
|
||||
// builder.ReuseValue(id); // Refers to same double by offset.
|
||||
// LastValue works regardless of wether the value has a key or not.
|
||||
// Works on any data type.
|
||||
struct Value;
|
||||
Value LastValue() { return stack_.back(); }
|
||||
void ReuseValue(Value v) { stack_.push_back(v); }
|
||||
void ReuseValue(const char *key, Value v) {
|
||||
Key(key);
|
||||
ReuseValue(v);
|
||||
}
|
||||
|
||||
// Overloaded Add that tries to call the correct function above.
|
||||
void Add(int8_t i) { Int(i); }
|
||||
void Add(int16_t i) { Int(i); }
|
||||
@@ -1308,6 +1391,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
: FBT_INT);
|
||||
}
|
||||
|
||||
public:
|
||||
// This was really intended to be private, except for LastValue/ReuseValue.
|
||||
struct Value {
|
||||
union {
|
||||
int64_t i_;
|
||||
@@ -1377,6 +1462,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
void WriteAny(const Value &val, uint8_t byte_width) {
|
||||
switch (val.type_) {
|
||||
case FBT_NULL:
|
||||
@@ -1409,6 +1495,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
// TODO: instead of asserting, could write vector with larger elements
|
||||
// instead, though that would be wasteful.
|
||||
FLATBUFFERS_ASSERT(WidthU(len) <= bit_width);
|
||||
Align(bit_width);
|
||||
if (!fixed) Write<uint64_t>(len, byte_width);
|
||||
auto vloc = buf_.size();
|
||||
for (size_t i = 0; i < len; i++) Write(elems[i], byte_width);
|
||||
@@ -1420,7 +1507,9 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
|
||||
Value CreateVector(size_t start, size_t vec_len, size_t step, bool typed,
|
||||
bool fixed, const Value *keys = nullptr) {
|
||||
FLATBUFFERS_ASSERT(!fixed || typed); // typed=false, fixed=true combination is not supported.
|
||||
FLATBUFFERS_ASSERT(
|
||||
!fixed ||
|
||||
typed); // typed=false, fixed=true combination is not supported.
|
||||
// Figure out smallest bit width we can store this vector with.
|
||||
auto bit_width = (std::max)(force_min_bit_width_, WidthU(vec_len));
|
||||
auto prefix_elems = 1;
|
||||
@@ -1500,7 +1589,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
|
||||
typedef std::pair<size_t, size_t> StringOffset;
|
||||
struct StringOffsetCompare {
|
||||
explicit StringOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {}
|
||||
explicit StringOffsetCompare(const std::vector<uint8_t> &buf)
|
||||
: buf_(&buf) {}
|
||||
bool operator()(const StringOffset &a, const StringOffset &b) const {
|
||||
auto stra = reinterpret_cast<const char *>(
|
||||
flatbuffers::vector_data(*buf_) + a.first);
|
||||
@@ -1520,8 +1610,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
|
||||
|
||||
} // namespace flexbuffers
|
||||
|
||||
# if defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
# endif
|
||||
#if defined(_MSC_VER)
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif // FLATBUFFERS_FLEXBUFFERS_H_
|
||||
|
||||
@@ -88,8 +88,7 @@ class SliceAllocator : public Allocator {
|
||||
SliceAllocator(const SliceAllocator &other) = delete;
|
||||
SliceAllocator &operator=(const SliceAllocator &other) = delete;
|
||||
|
||||
SliceAllocator(SliceAllocator &&other)
|
||||
: slice_(grpc_empty_slice()) {
|
||||
SliceAllocator(SliceAllocator &&other) : slice_(grpc_empty_slice()) {
|
||||
// default-construct and swap idiom
|
||||
swap(other);
|
||||
}
|
||||
@@ -170,11 +169,37 @@ class MessageBuilder : private detail::SliceAllocatorMember,
|
||||
MessageBuilder &operator=(const MessageBuilder &other) = delete;
|
||||
|
||||
MessageBuilder(MessageBuilder &&other)
|
||||
: FlatBufferBuilder(1024, &slice_allocator_, false) {
|
||||
: FlatBufferBuilder(1024, &slice_allocator_, false) {
|
||||
// Default construct and swap idiom.
|
||||
Swap(other);
|
||||
}
|
||||
|
||||
/// Create a MessageBuilder from a FlatBufferBuilder.
|
||||
explicit MessageBuilder(FlatBufferBuilder &&src,
|
||||
void (*dealloc)(void *,
|
||||
size_t) = &DefaultAllocator::dealloc)
|
||||
: FlatBufferBuilder(1024, &slice_allocator_, false) {
|
||||
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));
|
||||
@@ -185,10 +210,11 @@ class MessageBuilder : private detail::SliceAllocatorMember,
|
||||
void Swap(MessageBuilder &other) {
|
||||
slice_allocator_.swap(other.slice_allocator_);
|
||||
FlatBufferBuilder::Swap(other);
|
||||
// After swapping the FlatBufferBuilder, we swap back the allocator, which restores
|
||||
// the original allocator back in place. This is necessary because MessageBuilder's
|
||||
// allocator is its own member (SliceAllocatorMember). The allocator passed to
|
||||
// FlatBufferBuilder::vector_downward must point to this member.
|
||||
// After swapping the FlatBufferBuilder, we swap back the allocator, which
|
||||
// restores the original allocator back in place. This is necessary because
|
||||
// MessageBuilder's allocator is its own member (SliceAllocatorMember). The
|
||||
// allocator passed to FlatBufferBuilder::vector_downward must point to this
|
||||
// member.
|
||||
buf_.swap_allocator(other.buf_);
|
||||
}
|
||||
|
||||
@@ -208,10 +234,10 @@ class MessageBuilder : private detail::SliceAllocatorMember,
|
||||
// flatbuffers-encoded region and wraps it in a `Message<T>` to handle buffer
|
||||
// ownership.
|
||||
template<class T> Message<T> GetMessage() {
|
||||
auto buf_data = buf_.scratch_data(); // pointer to memory
|
||||
auto buf_size = buf_.capacity(); // size of memory
|
||||
auto msg_data = buf_.data(); // pointer to msg
|
||||
auto msg_size = buf_.size(); // size of msg
|
||||
auto buf_data = buf_.scratch_data(); // pointer to memory
|
||||
auto buf_size = buf_.capacity(); // size of memory
|
||||
auto msg_data = buf_.data(); // pointer to msg
|
||||
auto msg_size = buf_.size(); // size of msg
|
||||
// Do some sanity checks on data/size
|
||||
FLATBUFFERS_ASSERT(msg_data);
|
||||
FLATBUFFERS_ASSERT(msg_size);
|
||||
@@ -250,7 +276,7 @@ template<class T> class SerializationTraits<flatbuffers::grpc::Message<T>> {
|
||||
grpc_byte_buffer **buffer, bool *own_buffer) {
|
||||
// We are passed in a `Message<T>`, which is a wrapper around a
|
||||
// `grpc_slice`. We extract it here using `BorrowSlice()`. The const cast
|
||||
// is necesary because the `grpc_raw_byte_buffer_create` func expects
|
||||
// is necessary because the `grpc_raw_byte_buffer_create` func expects
|
||||
// non-const slices in order to increment their refcounts.
|
||||
grpc_slice *slice = const_cast<grpc_slice *>(&msg.BorrowSlice());
|
||||
// Now use `grpc_raw_byte_buffer_create` to package the single slice into a
|
||||
@@ -282,7 +308,7 @@ template<class T> class SerializationTraits<flatbuffers::grpc::Message<T>> {
|
||||
grpc_byte_buffer_reader_init(&reader, buffer);
|
||||
grpc_slice slice = grpc_byte_buffer_reader_readall(&reader);
|
||||
grpc_byte_buffer_reader_destroy(&reader);
|
||||
// We wrap a `Message<T>` around the slice, but dont increment refcount
|
||||
// We wrap a `Message<T>` around the slice, but don't increment refcount
|
||||
*msg = flatbuffers::grpc::Message<T>(slice, false);
|
||||
}
|
||||
grpc_byte_buffer_destroy(buffer);
|
||||
|
||||
@@ -39,7 +39,7 @@ template<> struct FnvTraits<uint64_t> {
|
||||
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;
|
||||
for (const char *c = input; *c; ++c) {
|
||||
hash *= FnvTraits<T>::kFnvPrime;
|
||||
@@ -48,7 +48,7 @@ template<typename T> FLATBUFFERS_CONSTEXPR_CPP14 T HashFnv1(const char *input) {
|
||||
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;
|
||||
for (const char *c = input; *c; ++c) {
|
||||
hash ^= static_cast<unsigned char>(*c);
|
||||
@@ -57,17 +57,17 @@ template<typename T> FLATBUFFERS_CONSTEXPR_CPP14 T HashFnv1a(const char *input)
|
||||
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);
|
||||
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);
|
||||
return (hash >> 16) ^ (hash & 0xffff);
|
||||
}
|
||||
|
||||
template <typename T> struct NamedHashFunction {
|
||||
template<typename T> struct NamedHashFunction {
|
||||
const char *name;
|
||||
|
||||
typedef T (*HashFunction)(const char *);
|
||||
@@ -75,7 +75,7 @@ template <typename T> struct NamedHashFunction {
|
||||
};
|
||||
|
||||
const NamedHashFunction<uint16_t> kHashFunctions16[] = {
|
||||
{ "fnv1_16", HashFnv1<uint16_t> },
|
||||
{ "fnv1_16", HashFnv1<uint16_t> },
|
||||
{ "fnv1a_16", HashFnv1a<uint16_t> },
|
||||
};
|
||||
|
||||
|
||||
@@ -34,6 +34,12 @@
|
||||
// This file defines the data types representing a parsed IDL (Interface
|
||||
// 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 {
|
||||
|
||||
// The order of these matters for Is*() functions below.
|
||||
@@ -41,25 +47,26 @@ namespace flatbuffers {
|
||||
// of type tokens.
|
||||
// clang-format off
|
||||
#define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
|
||||
TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8) \
|
||||
TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8) /* begin scalar/int */ \
|
||||
TD(BOOL, "bool", uint8_t, boolean,byte, bool, bool, bool) \
|
||||
TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8) \
|
||||
TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8) \
|
||||
TD(SHORT, "short", int16_t, short, int16, short, int16, i16) \
|
||||
TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16, u16) \
|
||||
TD(INT, "int", int32_t, int, int32, int, int32, i32) \
|
||||
TD(UINT, "uint", uint32_t, int, uint32, uint, uint32, u32) \
|
||||
TD(LONG, "long", int64_t, long, int64, long, int64, i64) \
|
||||
TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64, u64) /* end int */ \
|
||||
TD(FLOAT, "float", float, float, float32, float, float32, f32) /* begin float */ \
|
||||
TD(DOUBLE, "double", double, double, float64, double, float64, f64) /* end float/scalar */
|
||||
TD(NONE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) \
|
||||
TD(UTYPE, "", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) /* begin scalar/int */ \
|
||||
TD(BOOL, "bool", uint8_t, boolean,bool, bool, bool, bool, Boolean, Bool) \
|
||||
TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8, Byte, Int8) \
|
||||
TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8, UByte, UInt8) \
|
||||
TD(SHORT, "short", int16_t, short, int16, short, int16, i16, Short, Int16) \
|
||||
TD(USHORT, "ushort", uint16_t, short, uint16, ushort, uint16, u16, UShort, UInt16) \
|
||||
TD(INT, "int", int32_t, int, int32, int, int32, i32, Int, Int32) \
|
||||
TD(UINT, "uint", uint32_t, int, uint32, uint, uint32, u32, UInt, UInt32) \
|
||||
TD(LONG, "long", int64_t, long, int64, long, int64, i64, Long, Int64) \
|
||||
TD(ULONG, "ulong", uint64_t, long, uint64, ulong, uint64, u64, ULong, UInt64) /* end int */ \
|
||||
TD(FLOAT, "float", float, float, float32, float, float32, f32, Float, Float32) /* begin float */ \
|
||||
TD(DOUBLE, "double", double, double, float64, double, float64, f64, Double, Double) /* end float/scalar */
|
||||
#define FLATBUFFERS_GEN_TYPES_POINTER(TD) \
|
||||
TD(STRING, "string", Offset<void>, int, int, StringOffset, int, unused) \
|
||||
TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused) \
|
||||
TD(STRUCT, "", Offset<void>, int, int, int, int, unused) \
|
||||
TD(UNION, "", Offset<void>, int, int, int, int, unused)
|
||||
|
||||
TD(STRING, "string", Offset<void>, int, int, StringOffset, int, unused, Int, Offset<String>) \
|
||||
TD(VECTOR, "", Offset<void>, int, int, VectorOffset, int, unused, Int, Offset<UOffset>) \
|
||||
TD(STRUCT, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>) \
|
||||
TD(UNION, "", Offset<void>, int, int, int, int, unused, Int, Offset<UOffset>)
|
||||
#define FLATBUFFERS_GEN_TYPE_ARRAY(TD) \
|
||||
TD(ARRAY, "", int, int, int, int, int, unused, Int, Offset<UOffset>)
|
||||
// The fields are:
|
||||
// - enum
|
||||
// - FlatBuffers schema type.
|
||||
@@ -69,13 +76,28 @@ namespace flatbuffers {
|
||||
// - C# / .Net type.
|
||||
// - Python type.
|
||||
// - Rust type.
|
||||
// - Kotlin type.
|
||||
|
||||
// using these macros, we can now write code dealing with types just once, e.g.
|
||||
|
||||
/*
|
||||
switch (type) {
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
|
||||
RTYPE) \
|
||||
RTYPE, KTYPE) \
|
||||
case BASE_TYPE_ ## ENUM: \
|
||||
// do something specific to CTYPE here
|
||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
}
|
||||
*/
|
||||
|
||||
// If not all FLATBUFFERS_GEN_() arguments are necessary for implementation
|
||||
// of FLATBUFFERS_TD, you can use a variadic macro (with __VA_ARGS__ if needed).
|
||||
// In the above example, only CTYPE is used to generate the code, it can be rewritten:
|
||||
|
||||
/*
|
||||
switch (type) {
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
|
||||
case BASE_TYPE_ ## ENUM: \
|
||||
// do something specific to CTYPE here
|
||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||
@@ -85,24 +107,23 @@ switch (type) {
|
||||
|
||||
#define FLATBUFFERS_GEN_TYPES(TD) \
|
||||
FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
|
||||
FLATBUFFERS_GEN_TYPES_POINTER(TD)
|
||||
FLATBUFFERS_GEN_TYPES_POINTER(TD) \
|
||||
FLATBUFFERS_GEN_TYPE_ARRAY(TD)
|
||||
|
||||
// Create an enum for all the types above.
|
||||
#ifdef __GNUC__
|
||||
__extension__ // Stop GCC complaining about trailing comma with -Wpendantic.
|
||||
#endif
|
||||
enum BaseType {
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
|
||||
RTYPE) \
|
||||
BASE_TYPE_ ## ENUM,
|
||||
#define FLATBUFFERS_TD(ENUM, ...) \
|
||||
BASE_TYPE_ ## ENUM,
|
||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
};
|
||||
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \
|
||||
RTYPE) \
|
||||
static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \
|
||||
"define largest_scalar_t as " #CTYPE);
|
||||
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
|
||||
static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \
|
||||
"define largest_scalar_t as " #CTYPE);
|
||||
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
|
||||
#undef FLATBUFFERS_TD
|
||||
|
||||
@@ -117,6 +138,13 @@ inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
|
||||
inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; }
|
||||
inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE &&
|
||||
t <= BASE_TYPE_UCHAR; }
|
||||
|
||||
inline bool IsUnsigned(BaseType t) {
|
||||
return (t == BASE_TYPE_UTYPE) || (t == BASE_TYPE_UCHAR) ||
|
||||
(t == BASE_TYPE_USHORT) || (t == BASE_TYPE_UINT) ||
|
||||
(t == BASE_TYPE_ULONG);
|
||||
}
|
||||
|
||||
// clang-format on
|
||||
|
||||
extern const char *const kTypeNames[];
|
||||
@@ -132,26 +160,32 @@ class Parser;
|
||||
// and additional information for vectors/structs_.
|
||||
struct Type {
|
||||
explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr,
|
||||
EnumDef *_ed = nullptr)
|
||||
EnumDef *_ed = nullptr, uint16_t _fixed_length = 0)
|
||||
: base_type(_base_type),
|
||||
element(BASE_TYPE_NONE),
|
||||
struct_def(_sd),
|
||||
enum_def(_ed) {}
|
||||
enum_def(_ed),
|
||||
fixed_length(_fixed_length) {}
|
||||
|
||||
bool operator==(const Type &o) {
|
||||
return base_type == o.base_type && element == o.element &&
|
||||
struct_def == o.struct_def && enum_def == o.enum_def;
|
||||
}
|
||||
|
||||
Type VectorType() const { return Type(element, struct_def, enum_def); }
|
||||
Type VectorType() const {
|
||||
return Type(element, struct_def, enum_def, fixed_length);
|
||||
}
|
||||
|
||||
Offset<reflection::Type> Serialize(FlatBufferBuilder *builder) const;
|
||||
|
||||
bool Deserialize(const Parser &parser, const reflection::Type *type);
|
||||
|
||||
BaseType base_type;
|
||||
BaseType element; // only set if t == BASE_TYPE_VECTOR
|
||||
StructDef *struct_def; // only set if t or element == BASE_TYPE_STRUCT
|
||||
EnumDef *enum_def; // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE,
|
||||
// or for an integral type derived from an enum.
|
||||
uint16_t fixed_length; // only set if t == BASE_TYPE_ARRAY
|
||||
};
|
||||
|
||||
// Represents a parsed scalar value, it's type, and field offset.
|
||||
@@ -216,6 +250,15 @@ struct Namespace {
|
||||
size_t from_table; // Part of the namespace corresponds to a message/table.
|
||||
};
|
||||
|
||||
inline bool operator<(const Namespace &a, const Namespace &b) {
|
||||
size_t min_size = std::min(a.components.size(), b.components.size());
|
||||
for (size_t i = 0; i < min_size; ++i) {
|
||||
if (a.components[i] != b.components[i])
|
||||
return a.components[i] < b.components[i];
|
||||
}
|
||||
return a.components.size() < b.components.size();
|
||||
}
|
||||
|
||||
// Base class for all definition types (fields, structs_, enums_).
|
||||
struct Definition {
|
||||
Definition()
|
||||
@@ -229,6 +272,9 @@ struct Definition {
|
||||
flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
|
||||
SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||
|
||||
bool DeserializeAttributes(Parser &parser,
|
||||
const Vector<Offset<reflection::KeyValue>> *attrs);
|
||||
|
||||
std::string name;
|
||||
std::string file;
|
||||
std::vector<std::string> doc_comment;
|
||||
@@ -247,6 +293,7 @@ struct FieldDef : public Definition {
|
||||
: deprecated(false),
|
||||
required(false),
|
||||
key(false),
|
||||
shared(false),
|
||||
native_inline(false),
|
||||
flexbuffer(false),
|
||||
nested_flatbuffer(NULL),
|
||||
@@ -255,11 +302,15 @@ struct FieldDef : public Definition {
|
||||
Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
|
||||
const Parser &parser) const;
|
||||
|
||||
bool Deserialize(Parser &parser, const reflection::Field *field);
|
||||
|
||||
Value value;
|
||||
bool deprecated; // Field is allowed to be present in old data, but can't be.
|
||||
// written in new data nor accessed in new code.
|
||||
bool required; // Field must always be present.
|
||||
bool key; // Field functions as a key for creating sorted vectors.
|
||||
bool 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)
|
||||
// for native tables if field is a struct.
|
||||
bool flexbuffer; // This field contains FlexBuffer data.
|
||||
@@ -285,6 +336,8 @@ struct StructDef : public Definition {
|
||||
Offset<reflection::Object> Serialize(FlatBufferBuilder *builder,
|
||||
const Parser &parser) const;
|
||||
|
||||
bool Deserialize(Parser &parser, const reflection::Object *object);
|
||||
|
||||
SymbolTable<FieldDef> fields;
|
||||
|
||||
bool fixed; // If it's struct, not a table.
|
||||
@@ -297,48 +350,137 @@ struct StructDef : public Definition {
|
||||
flatbuffers::unique_ptr<std::string> original_location;
|
||||
};
|
||||
|
||||
struct EnumDef;
|
||||
struct EnumValBuilder;
|
||||
|
||||
struct EnumVal {
|
||||
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder,
|
||||
const Parser &parser) const;
|
||||
|
||||
bool Deserialize(const Parser &parser, const reflection::EnumVal *val);
|
||||
|
||||
uint64_t GetAsUInt64() const { return static_cast<uint64_t>(value); }
|
||||
int64_t GetAsInt64() const { return value; }
|
||||
bool IsZero() const { return 0 == value; }
|
||||
bool IsNonZero() const { return !IsZero(); }
|
||||
|
||||
std::string name;
|
||||
std::vector<std::string> doc_comment;
|
||||
Type union_type;
|
||||
|
||||
private:
|
||||
friend EnumDef;
|
||||
friend EnumValBuilder;
|
||||
friend bool operator==(const EnumVal &lhs, const EnumVal &rhs);
|
||||
|
||||
EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
|
||||
EnumVal() : value(0) {}
|
||||
|
||||
int64_t value;
|
||||
};
|
||||
|
||||
struct EnumDef : public Definition {
|
||||
EnumDef() : is_union(false), uses_multiple_type_instances(false) {}
|
||||
|
||||
Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder,
|
||||
const Parser &parser) const;
|
||||
|
||||
bool Deserialize(Parser &parser, const reflection::Enum *values);
|
||||
|
||||
template<typename T> void ChangeEnumValue(EnumVal *ev, T new_val);
|
||||
void SortByValue();
|
||||
void RemoveDuplicates();
|
||||
|
||||
std::string AllFlags() const;
|
||||
const EnumVal *MinValue() const;
|
||||
const EnumVal *MaxValue() const;
|
||||
// Returns the number of integer steps from v1 to v2.
|
||||
uint64_t Distance(const EnumVal *v1, const EnumVal *v2) const;
|
||||
// Returns the number of integer steps from Min to Max.
|
||||
uint64_t Distance() const { return Distance(MinValue(), MaxValue()); }
|
||||
|
||||
EnumVal *ReverseLookup(int64_t enum_idx,
|
||||
bool skip_union_default = false) const;
|
||||
EnumVal *FindByValue(const std::string &constant) const;
|
||||
|
||||
std::string ToString(const EnumVal &ev) const {
|
||||
return IsUInt64() ? NumToString(ev.GetAsUInt64())
|
||||
: NumToString(ev.GetAsInt64());
|
||||
}
|
||||
|
||||
size_t size() const { return vals.vec.size(); }
|
||||
|
||||
const std::vector<EnumVal *> &Vals() const {
|
||||
return vals.vec;
|
||||
}
|
||||
|
||||
const EnumVal *Lookup(const std::string &enum_name) const {
|
||||
return vals.Lookup(enum_name);
|
||||
}
|
||||
|
||||
bool is_union;
|
||||
// Type is a union which uses type aliases where at least one type is
|
||||
// available under two different names.
|
||||
bool uses_multiple_type_instances;
|
||||
Type underlying_type;
|
||||
|
||||
private:
|
||||
bool IsUInt64() const {
|
||||
return (BASE_TYPE_ULONG == underlying_type.base_type);
|
||||
}
|
||||
|
||||
friend EnumValBuilder;
|
||||
SymbolTable<EnumVal> vals;
|
||||
};
|
||||
|
||||
inline bool IsStruct(const Type &type) {
|
||||
return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed;
|
||||
}
|
||||
|
||||
inline bool IsUnion(const Type &type) {
|
||||
return type.enum_def != nullptr && type.enum_def->is_union;
|
||||
}
|
||||
|
||||
inline bool IsVector(const Type &type) {
|
||||
return type.base_type == BASE_TYPE_VECTOR;
|
||||
}
|
||||
|
||||
inline bool IsArray(const Type &type) {
|
||||
return type.base_type == BASE_TYPE_ARRAY;
|
||||
}
|
||||
|
||||
inline bool IsSeries(const Type &type) {
|
||||
return IsVector(type) || IsArray(type);
|
||||
}
|
||||
|
||||
inline bool IsEnum(const Type &type) {
|
||||
return type.enum_def != nullptr && IsInteger(type.base_type);
|
||||
}
|
||||
|
||||
inline size_t InlineSize(const Type &type) {
|
||||
return IsStruct(type) ? type.struct_def->bytesize : SizeOf(type.base_type);
|
||||
return IsStruct(type)
|
||||
? type.struct_def->bytesize
|
||||
: (IsArray(type)
|
||||
? InlineSize(type.VectorType()) * type.fixed_length
|
||||
: SizeOf(type.base_type));
|
||||
}
|
||||
|
||||
inline size_t InlineAlignment(const Type &type) {
|
||||
return IsStruct(type) ? type.struct_def->minalign : SizeOf(type.base_type);
|
||||
}
|
||||
|
||||
struct EnumVal {
|
||||
EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
|
||||
|
||||
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||
|
||||
std::string name;
|
||||
std::vector<std::string> doc_comment;
|
||||
int64_t value;
|
||||
Type union_type;
|
||||
};
|
||||
|
||||
struct EnumDef : public Definition {
|
||||
EnumDef() : is_union(false), uses_type_aliases(false) {}
|
||||
|
||||
EnumVal *ReverseLookup(int64_t enum_idx, bool skip_union_default = true) {
|
||||
for (auto it = vals.vec.begin() +
|
||||
static_cast<int>(is_union && skip_union_default);
|
||||
it != vals.vec.end(); ++it) {
|
||||
if ((*it)->value == enum_idx) { return *it; }
|
||||
}
|
||||
return nullptr;
|
||||
if (IsStruct(type)) {
|
||||
return type.struct_def->minalign;
|
||||
} else if (IsArray(type)) {
|
||||
return IsStruct(type.VectorType()) ? type.struct_def->minalign
|
||||
: SizeOf(type.element);
|
||||
} else {
|
||||
return SizeOf(type.base_type);
|
||||
}
|
||||
|
||||
Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||
|
||||
SymbolTable<EnumVal> vals;
|
||||
bool is_union;
|
||||
bool uses_type_aliases;
|
||||
Type underlying_type;
|
||||
};
|
||||
}
|
||||
inline bool operator==(const EnumVal &lhs, const EnumVal &rhs) {
|
||||
return lhs.value == rhs.value;
|
||||
}
|
||||
inline bool operator!=(const EnumVal &lhs, const EnumVal &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
inline bool EqualByName(const Type &a, const Type &b) {
|
||||
return a.base_type == b.base_type && a.element == b.element &&
|
||||
@@ -348,19 +490,26 @@ inline bool EqualByName(const Type &a, const Type &b) {
|
||||
}
|
||||
|
||||
struct RPCCall : public Definition {
|
||||
Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||
Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder,
|
||||
const Parser &parser) const;
|
||||
|
||||
bool Deserialize(Parser &parser, const reflection::RPCCall *call);
|
||||
|
||||
StructDef *request, *response;
|
||||
};
|
||||
|
||||
struct ServiceDef : public Definition {
|
||||
Offset<reflection::Service> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
|
||||
Offset<reflection::Service> Serialize(FlatBufferBuilder *builder,
|
||||
const Parser &parser) const;
|
||||
bool Deserialize(Parser &parser, const reflection::Service *service);
|
||||
|
||||
SymbolTable<RPCCall> calls;
|
||||
};
|
||||
|
||||
// Container of options that may apply to any of the source/text generators.
|
||||
struct IDLOptions {
|
||||
// Use flexbuffers instead for binary and text generation
|
||||
bool use_flexbuffers;
|
||||
bool strict_json;
|
||||
bool skip_js_exports;
|
||||
bool use_goog_js_export_format;
|
||||
@@ -382,7 +531,10 @@ struct IDLOptions {
|
||||
bool gen_compare;
|
||||
std::string cpp_object_api_pointer_type;
|
||||
std::string cpp_object_api_string_type;
|
||||
bool cpp_object_api_string_flexible_constructor;
|
||||
bool gen_nullable;
|
||||
bool java_checkerframework;
|
||||
bool gen_generated;
|
||||
std::string object_prefix;
|
||||
std::string object_suffix;
|
||||
bool union_value_namespacing;
|
||||
@@ -392,14 +544,23 @@ struct IDLOptions {
|
||||
bool keep_include_path;
|
||||
bool binary_schema_comments;
|
||||
bool binary_schema_builtins;
|
||||
bool binary_schema_gen_embed;
|
||||
bool skip_flatbuffers_import;
|
||||
std::string go_import;
|
||||
std::string go_namespace;
|
||||
bool reexport_ts_modules;
|
||||
bool js_ts_short_names;
|
||||
bool protobuf_ascii_alike;
|
||||
bool size_prefixed;
|
||||
std::string root_type;
|
||||
bool force_defaults;
|
||||
bool java_primitive_has_method;
|
||||
bool cs_gen_json_serializer;
|
||||
std::vector<std::string> cpp_includes;
|
||||
std::string cpp_std;
|
||||
std::string proto_namespace_suffix;
|
||||
std::string filename_suffix;
|
||||
std::string filename_extension;
|
||||
|
||||
// Possible options for the more general generator below.
|
||||
enum Language {
|
||||
@@ -418,6 +579,8 @@ struct IDLOptions {
|
||||
kLua = 1 << 12,
|
||||
kLobster = 1 << 13,
|
||||
kRust = 1 << 14,
|
||||
kKotlin = 1 << 15,
|
||||
kSwift = 1 << 16,
|
||||
kMAX
|
||||
};
|
||||
|
||||
@@ -431,12 +594,17 @@ struct IDLOptions {
|
||||
// for code generation.
|
||||
unsigned long lang_to_generate;
|
||||
|
||||
// If set (default behavior), empty string and vector fields will be set to
|
||||
// nullptr to make the flatbuffer more compact.
|
||||
bool set_empty_to_null;
|
||||
// If set (default behavior), empty string fields will be set to nullptr to
|
||||
// make the flatbuffer more compact.
|
||||
bool set_empty_strings_to_null;
|
||||
|
||||
// If set (default behavior), empty vector fields will be set to nullptr to
|
||||
// make the flatbuffer more compact.
|
||||
bool set_empty_vectors_to_null;
|
||||
|
||||
IDLOptions()
|
||||
: strict_json(false),
|
||||
: use_flexbuffers(false),
|
||||
strict_json(false),
|
||||
skip_js_exports(false),
|
||||
use_goog_js_export_format(false),
|
||||
use_ES6_js_export_format(false),
|
||||
@@ -456,7 +624,10 @@ struct IDLOptions {
|
||||
generate_object_based_api(false),
|
||||
gen_compare(false),
|
||||
cpp_object_api_pointer_type("std::unique_ptr"),
|
||||
cpp_object_api_string_flexible_constructor(false),
|
||||
gen_nullable(false),
|
||||
java_checkerframework(false),
|
||||
gen_generated(false),
|
||||
object_suffix("T"),
|
||||
union_value_namespacing(true),
|
||||
allow_non_utf8(false),
|
||||
@@ -464,21 +635,32 @@ struct IDLOptions {
|
||||
keep_include_path(false),
|
||||
binary_schema_comments(false),
|
||||
binary_schema_builtins(false),
|
||||
binary_schema_gen_embed(false),
|
||||
skip_flatbuffers_import(false),
|
||||
reexport_ts_modules(true),
|
||||
js_ts_short_names(false),
|
||||
protobuf_ascii_alike(false),
|
||||
size_prefixed(false),
|
||||
force_defaults(false),
|
||||
java_primitive_has_method(false),
|
||||
cs_gen_json_serializer(false),
|
||||
filename_suffix("_generated"),
|
||||
filename_extension(),
|
||||
lang(IDLOptions::kJava),
|
||||
mini_reflect(IDLOptions::kNone),
|
||||
lang_to_generate(0),
|
||||
set_empty_to_null(true) {}
|
||||
set_empty_strings_to_null(true),
|
||||
set_empty_vectors_to_null(true) {}
|
||||
};
|
||||
|
||||
// This encapsulates where the parser is in the current source file.
|
||||
struct ParserState {
|
||||
ParserState()
|
||||
: cursor_(nullptr), line_start_(nullptr), line_(0), token_(-1) {}
|
||||
: cursor_(nullptr),
|
||||
line_start_(nullptr),
|
||||
line_(0),
|
||||
token_(-1),
|
||||
attr_is_trivial_ascii_string_(true) {}
|
||||
|
||||
protected:
|
||||
void ResetState(const char *source) {
|
||||
@@ -502,6 +684,10 @@ struct ParserState {
|
||||
int line_; // the current line being parsed
|
||||
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::vector<std::string> doc_comment_;
|
||||
};
|
||||
@@ -557,15 +743,14 @@ class Parser : public ParserState {
|
||||
explicit Parser(const IDLOptions &options = IDLOptions())
|
||||
: current_namespace_(nullptr),
|
||||
empty_namespace_(nullptr),
|
||||
flex_builder_(256, flexbuffers::BUILDER_FLAG_SHARE_ALL),
|
||||
root_struct_def_(nullptr),
|
||||
opts(options),
|
||||
uses_flexbuffers_(false),
|
||||
source_(nullptr),
|
||||
anonymous_counter(0),
|
||||
recurse_protection_counter(0) {
|
||||
if (opts.force_defaults) {
|
||||
builder_.ForceDefaults(true);
|
||||
}
|
||||
if (opts.force_defaults) { builder_.ForceDefaults(true); }
|
||||
// Start out with the empty namespace being current.
|
||||
empty_namespace_ = new Namespace();
|
||||
namespaces_.push_back(empty_namespace_);
|
||||
@@ -573,6 +758,7 @@ class Parser : public ParserState {
|
||||
known_attributes_["deprecated"] = true;
|
||||
known_attributes_["required"] = true;
|
||||
known_attributes_["key"] = true;
|
||||
known_attributes_["shared"] = true;
|
||||
known_attributes_["hash"] = true;
|
||||
known_attributes_["id"] = true;
|
||||
known_attributes_["force_align"] = true;
|
||||
@@ -586,6 +772,7 @@ class Parser : public ParserState {
|
||||
known_attributes_["cpp_ptr_type"] = true;
|
||||
known_attributes_["cpp_ptr_type_get"] = true;
|
||||
known_attributes_["cpp_str_type"] = true;
|
||||
known_attributes_["cpp_str_flex_ctor"] = true;
|
||||
known_attributes_["native_inline"] = true;
|
||||
known_attributes_["native_custom_alloc"] = true;
|
||||
known_attributes_["native_type"] = true;
|
||||
@@ -629,6 +816,15 @@ class Parser : public ParserState {
|
||||
// See reflection/reflection.fbs
|
||||
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
|
||||
// of the schema provided. Returns non-empty error on any problems.
|
||||
std::string ConformTo(const Parser &base);
|
||||
@@ -638,14 +834,15 @@ class Parser : public ParserState {
|
||||
bool ParseFlexBuffer(const char *source, const char *source_filename,
|
||||
flexbuffers::Builder *builder);
|
||||
|
||||
FLATBUFFERS_CHECKED_ERROR CheckInRange(int64_t val, int64_t min, int64_t max);
|
||||
|
||||
StructDef *LookupStruct(const std::string &id) const;
|
||||
|
||||
std::string UnqualifiedName(const std::string &fullQualifiedName);
|
||||
|
||||
FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
|
||||
|
||||
private:
|
||||
void Message(const std::string &msg);
|
||||
void Warning(const std::string &msg);
|
||||
FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
|
||||
FLATBUFFERS_CHECKED_ERROR Next();
|
||||
FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
|
||||
@@ -666,47 +863,36 @@ class Parser : public ParserState {
|
||||
FLATBUFFERS_CHECKED_ERROR ParseComma();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
|
||||
size_t parent_fieldn,
|
||||
const StructDef *parent_struct_def);
|
||||
// clang-format off
|
||||
#if defined(FLATBUFFERS_CPP98_STL)
|
||||
typedef CheckedError (*ParseTableDelimitersBody)(
|
||||
const std::string &name, size_t &fieldn, const StructDef *struct_def,
|
||||
void *state);
|
||||
#else
|
||||
typedef std::function<CheckedError(const std::string&, size_t&,
|
||||
const StructDef*, void*)>
|
||||
ParseTableDelimitersBody;
|
||||
#endif // defined(FLATBUFFERS_CPP98_STL)
|
||||
// clang-format on
|
||||
const StructDef *parent_struct_def,
|
||||
uoffset_t count,
|
||||
bool inside_vector = false);
|
||||
template<typename F>
|
||||
FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
|
||||
const StructDef *struct_def,
|
||||
ParseTableDelimitersBody body,
|
||||
void *state);
|
||||
F body);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
|
||||
std::string *value, uoffset_t *ovalue);
|
||||
void SerializeStruct(const StructDef &struct_def, const Value &val);
|
||||
// clang-format off
|
||||
#if defined(FLATBUFFERS_CPP98_STL)
|
||||
typedef CheckedError (*ParseVectorDelimitersBody)(size_t &count,
|
||||
void *state);
|
||||
#else
|
||||
typedef std::function<CheckedError(size_t&, void*)>
|
||||
ParseVectorDelimitersBody;
|
||||
#endif // defined(FLATBUFFERS_CPP98_STL)
|
||||
// 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,
|
||||
size_t fieldn,
|
||||
const StructDef *parent_struct_def);
|
||||
void SerializeStruct(FlatBufferBuilder &builder, const StructDef &struct_def,
|
||||
const Value &val);
|
||||
template<typename F>
|
||||
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
|
||||
FieldDef *field, size_t fieldn);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseArray(Value &array);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(
|
||||
Value &val, FieldDef *field, size_t fieldn,
|
||||
const StructDef *parent_struct_def);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
|
||||
FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken, bool check, Value &e,
|
||||
BaseType req, bool *destmatch);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef* field);
|
||||
FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken,
|
||||
bool check, Value &e, BaseType req,
|
||||
bool *destmatch);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef *field);
|
||||
FLATBUFFERS_CHECKED_ERROR TokenError();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(Type &type, int64_t *result);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e,
|
||||
bool check_now);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type,
|
||||
std::string *result);
|
||||
StructDef *LookupCreateStruct(const std::string &name,
|
||||
bool create_if_new = true,
|
||||
bool definition = false);
|
||||
@@ -714,8 +900,7 @@ class Parser : public ParserState {
|
||||
FLATBUFFERS_CHECKED_ERROR ParseNamespace();
|
||||
FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
|
||||
StructDef **dest);
|
||||
FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name,
|
||||
bool is_union,
|
||||
FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name, bool is_union,
|
||||
EnumDef **dest);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseDecl();
|
||||
FLATBUFFERS_CHECKED_ERROR ParseService();
|
||||
@@ -731,28 +916,22 @@ class Parser : public ParserState {
|
||||
FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source,
|
||||
const char *source_filename);
|
||||
FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source,
|
||||
const char **include_paths,
|
||||
const char *source_filename);
|
||||
const char **include_paths,
|
||||
const char *source_filename);
|
||||
FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
|
||||
const char **include_paths,
|
||||
const char *source_filename,
|
||||
const char *include_filename);
|
||||
FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef*> &fields,
|
||||
const char **include_paths,
|
||||
const char *source_filename,
|
||||
const char *include_filename);
|
||||
FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef *> &fields,
|
||||
StructDef *struct_def,
|
||||
const char *suffix,
|
||||
BaseType baseType);
|
||||
const char *suffix, BaseType baseType);
|
||||
|
||||
bool SupportsVectorOfUnions() const;
|
||||
bool SupportsAdvancedUnionFeatures() const;
|
||||
bool SupportsAdvancedArrayFeatures() const;
|
||||
Namespace *UniqueNamespace(Namespace *ns);
|
||||
|
||||
enum { kMaxParsingDepth = 64 };
|
||||
FLATBUFFERS_CHECKED_ERROR RecurseError();
|
||||
template<typename F> CheckedError Recurse(F f) {
|
||||
if (++recurse_protection_counter >= kMaxParsingDepth) return RecurseError();
|
||||
auto ce = f();
|
||||
recurse_protection_counter--;
|
||||
return ce;
|
||||
}
|
||||
template<typename F> CheckedError Recurse(F f);
|
||||
|
||||
public:
|
||||
SymbolTable<Type> types_;
|
||||
@@ -762,9 +941,11 @@ class Parser : public ParserState {
|
||||
std::vector<Namespace *> namespaces_;
|
||||
Namespace *current_namespace_;
|
||||
Namespace *empty_namespace_;
|
||||
std::string error_; // User readable error_ if Parse() == false
|
||||
std::string error_; // User readable error_ if Parse() == false
|
||||
|
||||
FlatBufferBuilder builder_; // any data contained in the file
|
||||
flexbuffers::Builder flex_builder_;
|
||||
flexbuffers::Reference flex_root_;
|
||||
StructDef *root_struct_def_;
|
||||
std::string file_identifier_;
|
||||
std::string file_extension_;
|
||||
@@ -793,6 +974,8 @@ class Parser : public ParserState {
|
||||
|
||||
extern std::string MakeCamel(const std::string &in, bool first = true);
|
||||
|
||||
extern std::string MakeScreamingCamel(const std::string &in);
|
||||
|
||||
// Generate text (JSON) from a given FlatBuffer, and a given Parser
|
||||
// object that has been populated with the corresponding schema.
|
||||
// If ident_step is 0, no indentation will be generated. Additionally,
|
||||
@@ -801,152 +984,154 @@ extern std::string MakeCamel(const std::string &in, bool first = true);
|
||||
// strict_json adds "quotes" around field names if true.
|
||||
// If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8
|
||||
// byte arrays in String values), returns false.
|
||||
extern bool GenerateText(const Parser &parser,
|
||||
const void *flatbuffer,
|
||||
extern bool GenerateTextFromTable(const Parser &parser, const void *table,
|
||||
const std::string &tablename,
|
||||
std::string *text);
|
||||
extern bool GenerateText(const Parser &parser, const void *flatbuffer,
|
||||
std::string *text);
|
||||
extern bool GenerateTextFile(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern bool GenerateTextFile(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate binary files from a given FlatBuffer, and a given Parser
|
||||
// object that has been populated with the corresponding schema.
|
||||
// See idl_gen_general.cpp.
|
||||
extern bool GenerateBinary(const Parser &parser,
|
||||
const std::string &path,
|
||||
// See code_generators.cpp.
|
||||
extern bool GenerateBinary(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a C++ header from the definitions in the Parser object.
|
||||
// See idl_gen_cpp.
|
||||
extern bool GenerateCPP(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern bool GenerateCPP(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
extern bool GenerateDart(const Parser &parser,
|
||||
const std::string &path,
|
||||
// Generate C# files from the definitions in the Parser object.
|
||||
// See idl_gen_csharp.cpp.
|
||||
extern bool GenerateCSharp(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
extern bool GenerateDart(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate JavaScript or TypeScript code from the definitions in the Parser object.
|
||||
// See idl_gen_js.
|
||||
extern bool GenerateJS(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
// Generate Java files from the definitions in the Parser object.
|
||||
// See idl_gen_java.cpp.
|
||||
extern bool GenerateJava(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate JavaScript or TypeScript code from the definitions in the Parser
|
||||
// object. See idl_gen_js.
|
||||
extern bool GenerateJSTS(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Go files from the definitions in the Parser object.
|
||||
// See idl_gen_go.cpp.
|
||||
extern bool GenerateGo(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern bool GenerateGo(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Php code from the definitions in the Parser object.
|
||||
// See idl_gen_php.
|
||||
extern bool GeneratePhp(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern bool GeneratePhp(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Python files from the definitions in the Parser object.
|
||||
// See idl_gen_python.cpp.
|
||||
extern bool GeneratePython(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern bool GeneratePython(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Lobster files from the definitions in the Parser object.
|
||||
// See idl_gen_lobster.cpp.
|
||||
extern bool GenerateLobster(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern bool GenerateLobster(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Lua files from the definitions in the Parser object.
|
||||
// See idl_gen_lua.cpp.
|
||||
extern bool GenerateLua(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
extern bool GenerateLua(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Rust files from the definitions in the Parser object.
|
||||
// See idl_gen_rust.cpp.
|
||||
extern bool GenerateRust(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern bool GenerateRust(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Json schema file
|
||||
// See idl_gen_json_schema.cpp.
|
||||
extern bool GenerateJsonSchema(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern bool GenerateJsonSchema(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
extern bool GenerateKotlin(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate Java/C#/.. files from the definitions in the Parser object.
|
||||
// See idl_gen_general.cpp.
|
||||
extern bool GenerateGeneral(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
// Generate Swift classes.
|
||||
// See idl_gen_swift.cpp
|
||||
extern bool GenerateSwift(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a schema file from the internal representation, useful after
|
||||
// parsing a .proto schema.
|
||||
extern std::string GenerateFBS(const Parser &parser,
|
||||
const std::string &file_name);
|
||||
extern bool GenerateFBS(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern bool GenerateFBS(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated JavaScript or TypeScript code.
|
||||
// See idl_gen_js.cpp.
|
||||
extern std::string JSMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
extern std::string JSTSMakeRule(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated C++ header.
|
||||
// See idl_gen_cpp.cpp.
|
||||
extern std::string CPPMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern std::string CPPMakeRule(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated Dart code
|
||||
// see idl_gen_dart.cpp
|
||||
extern std::string DartMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern std::string DartMakeRule(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated Rust code.
|
||||
// See idl_gen_rust.cpp.
|
||||
extern std::string RustMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern std::string RustMakeRule(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated Java/C#/... files.
|
||||
// See idl_gen_general.cpp.
|
||||
extern std::string GeneralMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
// Generate a make rule for generated Java or C# files.
|
||||
// See code_generators.cpp.
|
||||
extern std::string JavaCSharpMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate a make rule for the generated text (JSON) files.
|
||||
// See idl_gen_text.cpp.
|
||||
extern std::string TextMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
extern std::string TextMakeRule(const Parser &parser, const std::string &path,
|
||||
const std::string &file_names);
|
||||
|
||||
// Generate a make rule for the generated binary files.
|
||||
// See idl_gen_general.cpp.
|
||||
extern std::string BinaryMakeRule(const Parser &parser,
|
||||
const std::string &path,
|
||||
// See code_generators.cpp.
|
||||
extern std::string BinaryMakeRule(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate GRPC Cpp interfaces.
|
||||
// See idl_gen_grpc.cpp.
|
||||
bool GenerateCppGRPC(const Parser &parser,
|
||||
const std::string &path,
|
||||
bool GenerateCppGRPC(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate GRPC Go interfaces.
|
||||
// See idl_gen_grpc.cpp.
|
||||
bool GenerateGoGRPC(const Parser &parser,
|
||||
const std::string &path,
|
||||
bool GenerateGoGRPC(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate GRPC Java classes.
|
||||
// See idl_gen_grpc.cpp
|
||||
bool GenerateJavaGRPC(const Parser &parser,
|
||||
const std::string &path,
|
||||
bool GenerateJavaGRPC(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate GRPC Python interfaces.
|
||||
// See idl_gen_grpc.cpp.
|
||||
bool GeneratePythonGRPC(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
// Generate GRPC Swift interfaces.
|
||||
// See idl_gen_grpc.cpp.
|
||||
extern bool GenerateSwiftGRPC(const Parser &parser, const std::string &path,
|
||||
const std::string &file_name);
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_IDL_H_
|
||||
|
||||
@@ -88,27 +88,28 @@ inline size_t InlineSize(ElementaryType type, const TypeTable *type_table) {
|
||||
switch (type_table->st) {
|
||||
case ST_TABLE:
|
||||
case ST_UNION: return 4;
|
||||
case ST_STRUCT: return type_table->values[type_table->num_elems];
|
||||
case ST_STRUCT:
|
||||
return static_cast<size_t>(type_table->values[type_table->num_elems]);
|
||||
default: FLATBUFFERS_ASSERT(false); return 1;
|
||||
}
|
||||
default: FLATBUFFERS_ASSERT(false); return 1;
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
if (!values) return enum_val;
|
||||
for (size_t i = 0; i < num_values; i++) {
|
||||
if (enum_val == values[i]) return static_cast<int32_t>(i);
|
||||
if (enum_val == values[i]) return static_cast<int64_t>(i);
|
||||
}
|
||||
return -1; // Unknown enum value.
|
||||
}
|
||||
|
||||
template<typename T> const char *EnumName(T tval, const TypeTable *type_table) {
|
||||
if (!type_table || !type_table->names) return nullptr;
|
||||
auto i = LookupEnum(static_cast<int32_t>(tval), type_table->values,
|
||||
auto i = LookupEnum(static_cast<int64_t>(tval), type_table->values,
|
||||
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 nullptr;
|
||||
@@ -122,58 +123,58 @@ inline void IterateValue(ElementaryType type, const uint8_t *val,
|
||||
soffset_t vector_index, IterationVisitor *visitor) {
|
||||
switch (type) {
|
||||
case ET_UTYPE: {
|
||||
auto tval = *reinterpret_cast<const uint8_t *>(val);
|
||||
auto tval = ReadScalar<uint8_t>(val);
|
||||
visitor->UType(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_BOOL: {
|
||||
visitor->Bool(*reinterpret_cast<const uint8_t *>(val) != 0);
|
||||
visitor->Bool(ReadScalar<uint8_t>(val) != 0);
|
||||
break;
|
||||
}
|
||||
case ET_CHAR: {
|
||||
auto tval = *reinterpret_cast<const int8_t *>(val);
|
||||
auto tval = ReadScalar<int8_t>(val);
|
||||
visitor->Char(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_UCHAR: {
|
||||
auto tval = *reinterpret_cast<const uint8_t *>(val);
|
||||
auto tval = ReadScalar<uint8_t>(val);
|
||||
visitor->UChar(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_SHORT: {
|
||||
auto tval = *reinterpret_cast<const int16_t *>(val);
|
||||
auto tval = ReadScalar<int16_t>(val);
|
||||
visitor->Short(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_USHORT: {
|
||||
auto tval = *reinterpret_cast<const uint16_t *>(val);
|
||||
auto tval = ReadScalar<uint16_t>(val);
|
||||
visitor->UShort(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_INT: {
|
||||
auto tval = *reinterpret_cast<const int32_t *>(val);
|
||||
auto tval = ReadScalar<int32_t>(val);
|
||||
visitor->Int(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_UINT: {
|
||||
auto tval = *reinterpret_cast<const uint32_t *>(val);
|
||||
auto tval = ReadScalar<uint32_t>(val);
|
||||
visitor->UInt(tval, EnumName(tval, type_table));
|
||||
break;
|
||||
}
|
||||
case ET_LONG: {
|
||||
visitor->Long(*reinterpret_cast<const int64_t *>(val));
|
||||
visitor->Long(ReadScalar<int64_t>(val));
|
||||
break;
|
||||
}
|
||||
case ET_ULONG: {
|
||||
visitor->ULong(*reinterpret_cast<const uint64_t *>(val));
|
||||
visitor->ULong(ReadScalar<uint64_t>(val));
|
||||
break;
|
||||
}
|
||||
case ET_FLOAT: {
|
||||
visitor->Float(*reinterpret_cast<const float *>(val));
|
||||
visitor->Float(ReadScalar<float>(val));
|
||||
break;
|
||||
}
|
||||
case ET_DOUBLE: {
|
||||
visitor->Double(*reinterpret_cast<const double *>(val));
|
||||
visitor->Double(ReadScalar<double>(val));
|
||||
break;
|
||||
}
|
||||
case ET_STRING: {
|
||||
@@ -287,10 +288,20 @@ struct ToStringVisitor : public IterationVisitor {
|
||||
bool q;
|
||||
std::string in;
|
||||
size_t indent_level;
|
||||
ToStringVisitor(std::string delimiter, bool quotes, std::string indent)
|
||||
: d(delimiter), q(quotes), in(indent), indent_level(0) {}
|
||||
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) {}
|
||||
: 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; }
|
||||
@@ -350,30 +361,44 @@ struct ToStringVisitor : public IterationVisitor {
|
||||
void Unknown(const uint8_t *) { s += "(?)"; }
|
||||
void StartVector() {
|
||||
s += "[";
|
||||
s += d;
|
||||
indent_level++;
|
||||
append_indent();
|
||||
if (vector_delimited) {
|
||||
s += d;
|
||||
indent_level++;
|
||||
append_indent();
|
||||
} else {
|
||||
s += " ";
|
||||
}
|
||||
}
|
||||
void EndVector() {
|
||||
s += d;
|
||||
indent_level--;
|
||||
append_indent();
|
||||
if (vector_delimited) {
|
||||
s += d;
|
||||
indent_level--;
|
||||
append_indent();
|
||||
} else {
|
||||
s += " ";
|
||||
}
|
||||
s += "]";
|
||||
}
|
||||
void Element(size_t i, ElementaryType /*type*/,
|
||||
const TypeTable * /*type_table*/, const uint8_t * /*val*/) {
|
||||
if (i) {
|
||||
s += ",";
|
||||
s += d;
|
||||
append_indent();
|
||||
if (vector_delimited) {
|
||||
s += d;
|
||||
append_indent();
|
||||
} else {
|
||||
s += " ";
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline std::string FlatBufferToString(const uint8_t *buffer,
|
||||
const TypeTable *type_table,
|
||||
bool multi_line = false) {
|
||||
ToStringVisitor tostring_visitor(multi_line ? "\n" : " ");
|
||||
bool multi_line = false,
|
||||
bool vector_delimited = true) {
|
||||
ToStringVisitor tostring_visitor(multi_line ? "\n" : " ", false, "",
|
||||
vector_delimited);
|
||||
IterateFlatBuffer(buffer, type_table, &tostring_visitor);
|
||||
return tostring_visitor.s;
|
||||
}
|
||||
|
||||
@@ -228,7 +228,7 @@ inline std::string GetAnyVectorElemS(const VectorOfAny *vec,
|
||||
template<typename T>
|
||||
T *GetAnyVectorElemPointer(const VectorOfAny *vec, size_t i) {
|
||||
auto elem_ptr = vec->Data() + sizeof(uoffset_t) * i;
|
||||
return (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
|
||||
@@ -239,20 +239,19 @@ T *GetAnyVectorElemPointer(const VectorOfAny *vec, size_t i) {
|
||||
template<typename T>
|
||||
T *GetAnyVectorElemAddressOf(const VectorOfAny *vec, size_t i,
|
||||
size_t elem_size) {
|
||||
// C-cast to allow const conversion.
|
||||
return (T *)(vec->Data() + elem_size * i);
|
||||
return reinterpret_cast<T *>(vec->Data() + elem_size * i);
|
||||
}
|
||||
|
||||
// Similarly, for elements of tables.
|
||||
template<typename T>
|
||||
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.
|
||||
template<typename T>
|
||||
T *GetAnyFieldAddressOf(const Struct &st, const reflection::Field &field) {
|
||||
return (T *)st.GetAddressOf(field.offset());
|
||||
return reinterpret_cast<T *>(st.GetAddressOf(field.offset()));
|
||||
}
|
||||
|
||||
// ------------------------- SETTERS -------------------------
|
||||
|
||||
@@ -9,22 +9,31 @@
|
||||
namespace reflection {
|
||||
|
||||
struct Type;
|
||||
struct TypeBuilder;
|
||||
|
||||
struct KeyValue;
|
||||
struct KeyValueBuilder;
|
||||
|
||||
struct EnumVal;
|
||||
struct EnumValBuilder;
|
||||
|
||||
struct Enum;
|
||||
struct EnumBuilder;
|
||||
|
||||
struct Field;
|
||||
struct FieldBuilder;
|
||||
|
||||
struct Object;
|
||||
struct ObjectBuilder;
|
||||
|
||||
struct RPCCall;
|
||||
struct RPCCallBuilder;
|
||||
|
||||
struct Service;
|
||||
struct ServiceBuilder;
|
||||
|
||||
struct Schema;
|
||||
struct SchemaBuilder;
|
||||
|
||||
enum BaseType {
|
||||
None = 0,
|
||||
@@ -43,10 +52,11 @@ enum BaseType {
|
||||
String = 13,
|
||||
Vector = 14,
|
||||
Obj = 15,
|
||||
Union = 16
|
||||
Union = 16,
|
||||
Array = 17
|
||||
};
|
||||
|
||||
inline const BaseType (&EnumValuesBaseType())[17] {
|
||||
inline const BaseType (&EnumValuesBaseType())[18] {
|
||||
static const BaseType values[] = {
|
||||
None,
|
||||
UType,
|
||||
@@ -64,13 +74,14 @@ inline const BaseType (&EnumValuesBaseType())[17] {
|
||||
String,
|
||||
Vector,
|
||||
Obj,
|
||||
Union
|
||||
Union,
|
||||
Array
|
||||
};
|
||||
return values;
|
||||
}
|
||||
|
||||
inline const char * const *EnumNamesBaseType() {
|
||||
static const char * const names[] = {
|
||||
static const char * const names[19] = {
|
||||
"None",
|
||||
"UType",
|
||||
"Bool",
|
||||
@@ -88,52 +99,64 @@ inline const char * const *EnumNamesBaseType() {
|
||||
"Vector",
|
||||
"Obj",
|
||||
"Union",
|
||||
"Array",
|
||||
nullptr
|
||||
};
|
||||
return names;
|
||||
}
|
||||
|
||||
inline const char *EnumNameBaseType(BaseType e) {
|
||||
const size_t index = static_cast<int>(e);
|
||||
if (flatbuffers::IsOutRange(e, None, Array)) return "";
|
||||
const size_t index = static_cast<size_t>(e);
|
||||
return EnumNamesBaseType()[index];
|
||||
}
|
||||
|
||||
struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum {
|
||||
typedef TypeBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_BASE_TYPE = 4,
|
||||
VT_ELEMENT = 6,
|
||||
VT_INDEX = 8
|
||||
VT_INDEX = 8,
|
||||
VT_FIXED_LENGTH = 10
|
||||
};
|
||||
BaseType base_type() const {
|
||||
return static_cast<BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0));
|
||||
reflection::BaseType base_type() const {
|
||||
return static_cast<reflection::BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0));
|
||||
}
|
||||
BaseType element() const {
|
||||
return static_cast<BaseType>(GetField<int8_t>(VT_ELEMENT, 0));
|
||||
reflection::BaseType element() const {
|
||||
return static_cast<reflection::BaseType>(GetField<int8_t>(VT_ELEMENT, 0));
|
||||
}
|
||||
int32_t index() const {
|
||||
return GetField<int32_t>(VT_INDEX, -1);
|
||||
}
|
||||
uint16_t fixed_length() const {
|
||||
return GetField<uint16_t>(VT_FIXED_LENGTH, 0);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
VerifyField<int8_t>(verifier, VT_BASE_TYPE) &&
|
||||
VerifyField<int8_t>(verifier, VT_ELEMENT) &&
|
||||
VerifyField<int32_t>(verifier, VT_INDEX) &&
|
||||
VerifyField<uint16_t>(verifier, VT_FIXED_LENGTH) &&
|
||||
verifier.EndTable();
|
||||
}
|
||||
};
|
||||
|
||||
struct TypeBuilder {
|
||||
typedef Type Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_base_type(BaseType base_type) {
|
||||
void add_base_type(reflection::BaseType base_type) {
|
||||
fbb_.AddElement<int8_t>(Type::VT_BASE_TYPE, static_cast<int8_t>(base_type), 0);
|
||||
}
|
||||
void add_element(BaseType element) {
|
||||
void add_element(reflection::BaseType element) {
|
||||
fbb_.AddElement<int8_t>(Type::VT_ELEMENT, static_cast<int8_t>(element), 0);
|
||||
}
|
||||
void add_index(int32_t index) {
|
||||
fbb_.AddElement<int32_t>(Type::VT_INDEX, index, -1);
|
||||
}
|
||||
void add_fixed_length(uint16_t fixed_length) {
|
||||
fbb_.AddElement<uint16_t>(Type::VT_FIXED_LENGTH, fixed_length, 0);
|
||||
}
|
||||
explicit TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
: fbb_(_fbb) {
|
||||
start_ = fbb_.StartTable();
|
||||
@@ -148,18 +171,21 @@ struct TypeBuilder {
|
||||
|
||||
inline flatbuffers::Offset<Type> CreateType(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
BaseType base_type = None,
|
||||
BaseType element = None,
|
||||
int32_t index = -1) {
|
||||
reflection::BaseType base_type = reflection::None,
|
||||
reflection::BaseType element = reflection::None,
|
||||
int32_t index = -1,
|
||||
uint16_t fixed_length = 0) {
|
||||
TypeBuilder builder_(_fbb);
|
||||
builder_.add_index(index);
|
||||
builder_.add_fixed_length(fixed_length);
|
||||
builder_.add_element(element);
|
||||
builder_.add_base_type(base_type);
|
||||
return builder_.Finish();
|
||||
}
|
||||
|
||||
struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum {
|
||||
typedef KeyValueBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_KEY = 4,
|
||||
VT_VALUE = 6
|
||||
};
|
||||
@@ -186,6 +212,7 @@ struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
};
|
||||
|
||||
struct KeyValueBuilder {
|
||||
typedef KeyValue Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_key(flatbuffers::Offset<flatbuffers::String> key) {
|
||||
@@ -221,14 +248,17 @@ inline flatbuffers::Offset<KeyValue> CreateKeyValueDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *key = nullptr,
|
||||
const char *value = nullptr) {
|
||||
auto key__ = key ? _fbb.CreateString(key) : 0;
|
||||
auto value__ = value ? _fbb.CreateString(value) : 0;
|
||||
return reflection::CreateKeyValue(
|
||||
_fbb,
|
||||
key ? _fbb.CreateString(key) : 0,
|
||||
value ? _fbb.CreateString(value) : 0);
|
||||
key__,
|
||||
value__);
|
||||
}
|
||||
|
||||
struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum {
|
||||
typedef EnumValBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_NAME = 4,
|
||||
VT_VALUE = 6,
|
||||
VT_OBJECT = 8,
|
||||
@@ -247,11 +277,11 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
int KeyCompareWithValue(int64_t val) const {
|
||||
return static_cast<int>(value() > val) - static_cast<int>(value() < val);
|
||||
}
|
||||
const Object *object() const {
|
||||
return GetPointer<const Object *>(VT_OBJECT);
|
||||
const reflection::Object *object() const {
|
||||
return GetPointer<const reflection::Object *>(VT_OBJECT);
|
||||
}
|
||||
const Type *union_type() const {
|
||||
return GetPointer<const Type *>(VT_UNION_TYPE);
|
||||
const reflection::Type *union_type() const {
|
||||
return GetPointer<const reflection::Type *>(VT_UNION_TYPE);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||
@@ -273,6 +303,7 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
};
|
||||
|
||||
struct EnumValBuilder {
|
||||
typedef EnumVal Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
@@ -281,10 +312,10 @@ struct EnumValBuilder {
|
||||
void add_value(int64_t value) {
|
||||
fbb_.AddElement<int64_t>(EnumVal::VT_VALUE, value, 0);
|
||||
}
|
||||
void add_object(flatbuffers::Offset<Object> object) {
|
||||
void add_object(flatbuffers::Offset<reflection::Object> object) {
|
||||
fbb_.AddOffset(EnumVal::VT_OBJECT, object);
|
||||
}
|
||||
void add_union_type(flatbuffers::Offset<Type> union_type) {
|
||||
void add_union_type(flatbuffers::Offset<reflection::Type> union_type) {
|
||||
fbb_.AddOffset(EnumVal::VT_UNION_TYPE, union_type);
|
||||
}
|
||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||
@@ -307,8 +338,8 @@ inline flatbuffers::Offset<EnumVal> CreateEnumVal(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
int64_t value = 0,
|
||||
flatbuffers::Offset<Object> object = 0,
|
||||
flatbuffers::Offset<Type> union_type = 0,
|
||||
flatbuffers::Offset<reflection::Object> object = 0,
|
||||
flatbuffers::Offset<reflection::Type> union_type = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||
EnumValBuilder builder_(_fbb);
|
||||
builder_.add_value(value);
|
||||
@@ -323,20 +354,23 @@ inline flatbuffers::Offset<EnumVal> CreateEnumValDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
int64_t value = 0,
|
||||
flatbuffers::Offset<Object> object = 0,
|
||||
flatbuffers::Offset<Type> union_type = 0,
|
||||
flatbuffers::Offset<reflection::Object> object = 0,
|
||||
flatbuffers::Offset<reflection::Type> union_type = 0,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||
return reflection::CreateEnumVal(
|
||||
_fbb,
|
||||
name ? _fbb.CreateString(name) : 0,
|
||||
name__,
|
||||
value,
|
||||
object,
|
||||
union_type,
|
||||
documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0);
|
||||
documentation__);
|
||||
}
|
||||
|
||||
struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum {
|
||||
typedef EnumBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_NAME = 4,
|
||||
VT_VALUES = 6,
|
||||
VT_IS_UNION = 8,
|
||||
@@ -353,17 +387,17 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
int KeyCompareWithValue(const char *val) const {
|
||||
return strcmp(name()->c_str(), val);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *values() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *>(VT_VALUES);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>> *values() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>> *>(VT_VALUES);
|
||||
}
|
||||
bool is_union() const {
|
||||
return GetField<uint8_t>(VT_IS_UNION, 0) != 0;
|
||||
}
|
||||
const Type *underlying_type() const {
|
||||
return GetPointer<const Type *>(VT_UNDERLYING_TYPE);
|
||||
const reflection::Type *underlying_type() const {
|
||||
return GetPointer<const reflection::Type *>(VT_UNDERLYING_TYPE);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||
@@ -389,21 +423,22 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
};
|
||||
|
||||
struct EnumBuilder {
|
||||
typedef Enum Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(Enum::VT_NAME, name);
|
||||
}
|
||||
void add_values(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<EnumVal>>> values) {
|
||||
void add_values(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>>> values) {
|
||||
fbb_.AddOffset(Enum::VT_VALUES, values);
|
||||
}
|
||||
void add_is_union(bool is_union) {
|
||||
fbb_.AddElement<uint8_t>(Enum::VT_IS_UNION, static_cast<uint8_t>(is_union), 0);
|
||||
}
|
||||
void add_underlying_type(flatbuffers::Offset<Type> underlying_type) {
|
||||
void add_underlying_type(flatbuffers::Offset<reflection::Type> underlying_type) {
|
||||
fbb_.AddOffset(Enum::VT_UNDERLYING_TYPE, underlying_type);
|
||||
}
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) {
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
|
||||
fbb_.AddOffset(Enum::VT_ATTRIBUTES, attributes);
|
||||
}
|
||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||
@@ -427,10 +462,10 @@ struct EnumBuilder {
|
||||
inline flatbuffers::Offset<Enum> CreateEnum(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<EnumVal>>> values = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::EnumVal>>> values = 0,
|
||||
bool is_union = false,
|
||||
flatbuffers::Offset<Type> underlying_type = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<reflection::Type> underlying_type = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||
EnumBuilder builder_(_fbb);
|
||||
builder_.add_documentation(documentation);
|
||||
@@ -445,23 +480,28 @@ inline flatbuffers::Offset<Enum> CreateEnum(
|
||||
inline flatbuffers::Offset<Enum> CreateEnumDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
const std::vector<flatbuffers::Offset<EnumVal>> *values = nullptr,
|
||||
std::vector<flatbuffers::Offset<reflection::EnumVal>> *values = nullptr,
|
||||
bool is_union = false,
|
||||
flatbuffers::Offset<Type> underlying_type = 0,
|
||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||
flatbuffers::Offset<reflection::Type> underlying_type = 0,
|
||||
std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||
auto values__ = values ? _fbb.CreateVectorOfSortedTables<reflection::EnumVal>(values) : 0;
|
||||
auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
|
||||
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||
return reflection::CreateEnum(
|
||||
_fbb,
|
||||
name ? _fbb.CreateString(name) : 0,
|
||||
values ? _fbb.CreateVector<flatbuffers::Offset<EnumVal>>(*values) : 0,
|
||||
name__,
|
||||
values__,
|
||||
is_union,
|
||||
underlying_type,
|
||||
attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0,
|
||||
documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0);
|
||||
attributes__,
|
||||
documentation__);
|
||||
}
|
||||
|
||||
struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum {
|
||||
typedef FieldBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_NAME = 4,
|
||||
VT_TYPE = 6,
|
||||
VT_ID = 8,
|
||||
@@ -483,8 +523,8 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
int KeyCompareWithValue(const char *val) const {
|
||||
return strcmp(name()->c_str(), val);
|
||||
}
|
||||
const Type *type() const {
|
||||
return GetPointer<const Type *>(VT_TYPE);
|
||||
const reflection::Type *type() const {
|
||||
return GetPointer<const reflection::Type *>(VT_TYPE);
|
||||
}
|
||||
uint16_t id() const {
|
||||
return GetField<uint16_t>(VT_ID, 0);
|
||||
@@ -507,8 +547,8 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
bool key() const {
|
||||
return GetField<uint8_t>(VT_KEY, 0) != 0;
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||
@@ -537,12 +577,13 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
};
|
||||
|
||||
struct FieldBuilder {
|
||||
typedef Field Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(Field::VT_NAME, name);
|
||||
}
|
||||
void add_type(flatbuffers::Offset<Type> type) {
|
||||
void add_type(flatbuffers::Offset<reflection::Type> type) {
|
||||
fbb_.AddOffset(Field::VT_TYPE, type);
|
||||
}
|
||||
void add_id(uint16_t id) {
|
||||
@@ -566,7 +607,7 @@ struct FieldBuilder {
|
||||
void add_key(bool key) {
|
||||
fbb_.AddElement<uint8_t>(Field::VT_KEY, static_cast<uint8_t>(key), 0);
|
||||
}
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) {
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
|
||||
fbb_.AddOffset(Field::VT_ATTRIBUTES, attributes);
|
||||
}
|
||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||
@@ -589,7 +630,7 @@ struct FieldBuilder {
|
||||
inline flatbuffers::Offset<Field> CreateField(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<Type> type = 0,
|
||||
flatbuffers::Offset<reflection::Type> type = 0,
|
||||
uint16_t id = 0,
|
||||
uint16_t offset = 0,
|
||||
int64_t default_integer = 0,
|
||||
@@ -597,7 +638,7 @@ inline flatbuffers::Offset<Field> CreateField(
|
||||
bool deprecated = false,
|
||||
bool required = false,
|
||||
bool key = false,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||
FieldBuilder builder_(_fbb);
|
||||
builder_.add_default_real(default_real);
|
||||
@@ -617,7 +658,7 @@ inline flatbuffers::Offset<Field> CreateField(
|
||||
inline flatbuffers::Offset<Field> CreateFieldDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
flatbuffers::Offset<Type> type = 0,
|
||||
flatbuffers::Offset<reflection::Type> type = 0,
|
||||
uint16_t id = 0,
|
||||
uint16_t offset = 0,
|
||||
int64_t default_integer = 0,
|
||||
@@ -625,11 +666,14 @@ inline flatbuffers::Offset<Field> CreateFieldDirect(
|
||||
bool deprecated = false,
|
||||
bool required = false,
|
||||
bool key = false,
|
||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||
std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||
auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
|
||||
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||
return reflection::CreateField(
|
||||
_fbb,
|
||||
name ? _fbb.CreateString(name) : 0,
|
||||
name__,
|
||||
type,
|
||||
id,
|
||||
offset,
|
||||
@@ -638,12 +682,13 @@ inline flatbuffers::Offset<Field> CreateFieldDirect(
|
||||
deprecated,
|
||||
required,
|
||||
key,
|
||||
attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0,
|
||||
documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0);
|
||||
attributes__,
|
||||
documentation__);
|
||||
}
|
||||
|
||||
struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum {
|
||||
typedef ObjectBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_NAME = 4,
|
||||
VT_FIELDS = 6,
|
||||
VT_IS_STRUCT = 8,
|
||||
@@ -661,8 +706,8 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
int KeyCompareWithValue(const char *val) const {
|
||||
return strcmp(name()->c_str(), val);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<Field>> *fields() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Field>> *>(VT_FIELDS);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::Field>> *fields() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Field>> *>(VT_FIELDS);
|
||||
}
|
||||
bool is_struct() const {
|
||||
return GetField<uint8_t>(VT_IS_STRUCT, 0) != 0;
|
||||
@@ -673,8 +718,8 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
int32_t bytesize() const {
|
||||
return GetField<int32_t>(VT_BYTESIZE, 0);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||
@@ -700,12 +745,13 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
};
|
||||
|
||||
struct ObjectBuilder {
|
||||
typedef Object Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(Object::VT_NAME, name);
|
||||
}
|
||||
void add_fields(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> fields) {
|
||||
void add_fields(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Field>>> fields) {
|
||||
fbb_.AddOffset(Object::VT_FIELDS, fields);
|
||||
}
|
||||
void add_is_struct(bool is_struct) {
|
||||
@@ -717,7 +763,7 @@ struct ObjectBuilder {
|
||||
void add_bytesize(int32_t bytesize) {
|
||||
fbb_.AddElement<int32_t>(Object::VT_BYTESIZE, bytesize, 0);
|
||||
}
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) {
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
|
||||
fbb_.AddOffset(Object::VT_ATTRIBUTES, attributes);
|
||||
}
|
||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||
@@ -740,11 +786,11 @@ struct ObjectBuilder {
|
||||
inline flatbuffers::Offset<Object> CreateObject(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> fields = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Field>>> fields = 0,
|
||||
bool is_struct = false,
|
||||
int32_t minalign = 0,
|
||||
int32_t bytesize = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||
ObjectBuilder builder_(_fbb);
|
||||
builder_.add_documentation(documentation);
|
||||
@@ -760,25 +806,30 @@ inline flatbuffers::Offset<Object> CreateObject(
|
||||
inline flatbuffers::Offset<Object> CreateObjectDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
const std::vector<flatbuffers::Offset<Field>> *fields = nullptr,
|
||||
std::vector<flatbuffers::Offset<reflection::Field>> *fields = nullptr,
|
||||
bool is_struct = false,
|
||||
int32_t minalign = 0,
|
||||
int32_t bytesize = 0,
|
||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||
std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||
auto fields__ = fields ? _fbb.CreateVectorOfSortedTables<reflection::Field>(fields) : 0;
|
||||
auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
|
||||
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||
return reflection::CreateObject(
|
||||
_fbb,
|
||||
name ? _fbb.CreateString(name) : 0,
|
||||
fields ? _fbb.CreateVector<flatbuffers::Offset<Field>>(*fields) : 0,
|
||||
name__,
|
||||
fields__,
|
||||
is_struct,
|
||||
minalign,
|
||||
bytesize,
|
||||
attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0,
|
||||
documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0);
|
||||
attributes__,
|
||||
documentation__);
|
||||
}
|
||||
|
||||
struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum {
|
||||
typedef RPCCallBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_NAME = 4,
|
||||
VT_REQUEST = 6,
|
||||
VT_RESPONSE = 8,
|
||||
@@ -794,14 +845,14 @@ struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
int KeyCompareWithValue(const char *val) const {
|
||||
return strcmp(name()->c_str(), val);
|
||||
}
|
||||
const Object *request() const {
|
||||
return GetPointer<const Object *>(VT_REQUEST);
|
||||
const reflection::Object *request() const {
|
||||
return GetPointer<const reflection::Object *>(VT_REQUEST);
|
||||
}
|
||||
const Object *response() const {
|
||||
return GetPointer<const Object *>(VT_RESPONSE);
|
||||
const reflection::Object *response() const {
|
||||
return GetPointer<const reflection::Object *>(VT_RESPONSE);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||
@@ -825,18 +876,19 @@ struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
};
|
||||
|
||||
struct RPCCallBuilder {
|
||||
typedef RPCCall Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(RPCCall::VT_NAME, name);
|
||||
}
|
||||
void add_request(flatbuffers::Offset<Object> request) {
|
||||
void add_request(flatbuffers::Offset<reflection::Object> request) {
|
||||
fbb_.AddOffset(RPCCall::VT_REQUEST, request);
|
||||
}
|
||||
void add_response(flatbuffers::Offset<Object> response) {
|
||||
void add_response(flatbuffers::Offset<reflection::Object> response) {
|
||||
fbb_.AddOffset(RPCCall::VT_RESPONSE, response);
|
||||
}
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) {
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
|
||||
fbb_.AddOffset(RPCCall::VT_ATTRIBUTES, attributes);
|
||||
}
|
||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||
@@ -860,9 +912,9 @@ struct RPCCallBuilder {
|
||||
inline flatbuffers::Offset<RPCCall> CreateRPCCall(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<Object> request = 0,
|
||||
flatbuffers::Offset<Object> response = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<reflection::Object> request = 0,
|
||||
flatbuffers::Offset<reflection::Object> response = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||
RPCCallBuilder builder_(_fbb);
|
||||
builder_.add_documentation(documentation);
|
||||
@@ -876,21 +928,25 @@ inline flatbuffers::Offset<RPCCall> CreateRPCCall(
|
||||
inline flatbuffers::Offset<RPCCall> CreateRPCCallDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
flatbuffers::Offset<Object> request = 0,
|
||||
flatbuffers::Offset<Object> response = 0,
|
||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||
flatbuffers::Offset<reflection::Object> request = 0,
|
||||
flatbuffers::Offset<reflection::Object> response = 0,
|
||||
std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||
auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
|
||||
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||
return reflection::CreateRPCCall(
|
||||
_fbb,
|
||||
name ? _fbb.CreateString(name) : 0,
|
||||
name__,
|
||||
request,
|
||||
response,
|
||||
attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0,
|
||||
documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0);
|
||||
attributes__,
|
||||
documentation__);
|
||||
}
|
||||
|
||||
struct Service FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum {
|
||||
typedef ServiceBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_NAME = 4,
|
||||
VT_CALLS = 6,
|
||||
VT_ATTRIBUTES = 8,
|
||||
@@ -905,11 +961,11 @@ struct Service FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
int KeyCompareWithValue(const char *val) const {
|
||||
return strcmp(name()->c_str(), val);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<RPCCall>> *calls() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<RPCCall>> *>(VT_CALLS);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>> *calls() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>> *>(VT_CALLS);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *attributes() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>> *>(VT_ATTRIBUTES);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
|
||||
@@ -932,15 +988,16 @@ struct Service FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
};
|
||||
|
||||
struct ServiceBuilder {
|
||||
typedef Service Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
|
||||
fbb_.AddOffset(Service::VT_NAME, name);
|
||||
}
|
||||
void add_calls(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<RPCCall>>> calls) {
|
||||
void add_calls(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>>> calls) {
|
||||
fbb_.AddOffset(Service::VT_CALLS, calls);
|
||||
}
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) {
|
||||
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes) {
|
||||
fbb_.AddOffset(Service::VT_ATTRIBUTES, attributes);
|
||||
}
|
||||
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
|
||||
@@ -962,8 +1019,8 @@ struct ServiceBuilder {
|
||||
inline flatbuffers::Offset<Service> CreateService(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::String> name = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<RPCCall>>> calls = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::RPCCall>>> calls = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> attributes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
|
||||
ServiceBuilder builder_(_fbb);
|
||||
builder_.add_documentation(documentation);
|
||||
@@ -976,19 +1033,24 @@ inline flatbuffers::Offset<Service> CreateService(
|
||||
inline flatbuffers::Offset<Service> CreateServiceDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const char *name = nullptr,
|
||||
const std::vector<flatbuffers::Offset<RPCCall>> *calls = nullptr,
|
||||
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
|
||||
std::vector<flatbuffers::Offset<reflection::RPCCall>> *calls = nullptr,
|
||||
std::vector<flatbuffers::Offset<reflection::KeyValue>> *attributes = nullptr,
|
||||
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
|
||||
auto name__ = name ? _fbb.CreateString(name) : 0;
|
||||
auto calls__ = calls ? _fbb.CreateVectorOfSortedTables<reflection::RPCCall>(calls) : 0;
|
||||
auto attributes__ = attributes ? _fbb.CreateVectorOfSortedTables<reflection::KeyValue>(attributes) : 0;
|
||||
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
|
||||
return reflection::CreateService(
|
||||
_fbb,
|
||||
name ? _fbb.CreateString(name) : 0,
|
||||
calls ? _fbb.CreateVector<flatbuffers::Offset<RPCCall>>(*calls) : 0,
|
||||
attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0,
|
||||
documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0);
|
||||
name__,
|
||||
calls__,
|
||||
attributes__,
|
||||
documentation__);
|
||||
}
|
||||
|
||||
struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
enum {
|
||||
typedef SchemaBuilder Builder;
|
||||
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
|
||||
VT_OBJECTS = 4,
|
||||
VT_ENUMS = 6,
|
||||
VT_FILE_IDENT = 8,
|
||||
@@ -996,11 +1058,11 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VT_ROOT_TABLE = 12,
|
||||
VT_SERVICES = 14
|
||||
};
|
||||
const flatbuffers::Vector<flatbuffers::Offset<Object>> *objects() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Object>> *>(VT_OBJECTS);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *objects() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Object>> *>(VT_OBJECTS);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<Enum>> *enums() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Enum>> *>(VT_ENUMS);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>> *enums() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>> *>(VT_ENUMS);
|
||||
}
|
||||
const flatbuffers::String *file_ident() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_FILE_IDENT);
|
||||
@@ -1008,11 +1070,11 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
const flatbuffers::String *file_ext() const {
|
||||
return GetPointer<const flatbuffers::String *>(VT_FILE_EXT);
|
||||
}
|
||||
const Object *root_table() const {
|
||||
return GetPointer<const Object *>(VT_ROOT_TABLE);
|
||||
const reflection::Object *root_table() const {
|
||||
return GetPointer<const reflection::Object *>(VT_ROOT_TABLE);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<Service>> *services() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Service>> *>(VT_SERVICES);
|
||||
const flatbuffers::Vector<flatbuffers::Offset<reflection::Service>> *services() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<reflection::Service>> *>(VT_SERVICES);
|
||||
}
|
||||
bool Verify(flatbuffers::Verifier &verifier) const {
|
||||
return VerifyTableStart(verifier) &&
|
||||
@@ -1036,12 +1098,13 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
};
|
||||
|
||||
struct SchemaBuilder {
|
||||
typedef Schema Table;
|
||||
flatbuffers::FlatBufferBuilder &fbb_;
|
||||
flatbuffers::uoffset_t start_;
|
||||
void add_objects(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Object>>> objects) {
|
||||
void add_objects(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Object>>> objects) {
|
||||
fbb_.AddOffset(Schema::VT_OBJECTS, objects);
|
||||
}
|
||||
void add_enums(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Enum>>> enums) {
|
||||
void add_enums(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>>> enums) {
|
||||
fbb_.AddOffset(Schema::VT_ENUMS, enums);
|
||||
}
|
||||
void add_file_ident(flatbuffers::Offset<flatbuffers::String> file_ident) {
|
||||
@@ -1050,10 +1113,10 @@ struct SchemaBuilder {
|
||||
void add_file_ext(flatbuffers::Offset<flatbuffers::String> file_ext) {
|
||||
fbb_.AddOffset(Schema::VT_FILE_EXT, file_ext);
|
||||
}
|
||||
void add_root_table(flatbuffers::Offset<Object> root_table) {
|
||||
void add_root_table(flatbuffers::Offset<reflection::Object> root_table) {
|
||||
fbb_.AddOffset(Schema::VT_ROOT_TABLE, root_table);
|
||||
}
|
||||
void add_services(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Service>>> services) {
|
||||
void add_services(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Service>>> services) {
|
||||
fbb_.AddOffset(Schema::VT_SERVICES, services);
|
||||
}
|
||||
explicit SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb)
|
||||
@@ -1072,12 +1135,12 @@ struct SchemaBuilder {
|
||||
|
||||
inline flatbuffers::Offset<Schema> CreateSchema(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Object>>> objects = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Enum>>> enums = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Object>>> objects = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Enum>>> enums = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> file_ident = 0,
|
||||
flatbuffers::Offset<flatbuffers::String> file_ext = 0,
|
||||
flatbuffers::Offset<Object> root_table = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Service>>> services = 0) {
|
||||
flatbuffers::Offset<reflection::Object> root_table = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<reflection::Service>>> services = 0) {
|
||||
SchemaBuilder builder_(_fbb);
|
||||
builder_.add_services(services);
|
||||
builder_.add_root_table(root_table);
|
||||
@@ -1090,20 +1153,25 @@ inline flatbuffers::Offset<Schema> CreateSchema(
|
||||
|
||||
inline flatbuffers::Offset<Schema> CreateSchemaDirect(
|
||||
flatbuffers::FlatBufferBuilder &_fbb,
|
||||
const std::vector<flatbuffers::Offset<Object>> *objects = nullptr,
|
||||
const std::vector<flatbuffers::Offset<Enum>> *enums = nullptr,
|
||||
std::vector<flatbuffers::Offset<reflection::Object>> *objects = nullptr,
|
||||
std::vector<flatbuffers::Offset<reflection::Enum>> *enums = nullptr,
|
||||
const char *file_ident = nullptr,
|
||||
const char *file_ext = nullptr,
|
||||
flatbuffers::Offset<Object> root_table = 0,
|
||||
const std::vector<flatbuffers::Offset<Service>> *services = nullptr) {
|
||||
flatbuffers::Offset<reflection::Object> root_table = 0,
|
||||
std::vector<flatbuffers::Offset<reflection::Service>> *services = nullptr) {
|
||||
auto objects__ = objects ? _fbb.CreateVectorOfSortedTables<reflection::Object>(objects) : 0;
|
||||
auto enums__ = enums ? _fbb.CreateVectorOfSortedTables<reflection::Enum>(enums) : 0;
|
||||
auto file_ident__ = file_ident ? _fbb.CreateString(file_ident) : 0;
|
||||
auto file_ext__ = file_ext ? _fbb.CreateString(file_ext) : 0;
|
||||
auto services__ = services ? _fbb.CreateVectorOfSortedTables<reflection::Service>(services) : 0;
|
||||
return reflection::CreateSchema(
|
||||
_fbb,
|
||||
objects ? _fbb.CreateVector<flatbuffers::Offset<Object>>(*objects) : 0,
|
||||
enums ? _fbb.CreateVector<flatbuffers::Offset<Enum>>(*enums) : 0,
|
||||
file_ident ? _fbb.CreateString(file_ident) : 0,
|
||||
file_ext ? _fbb.CreateString(file_ext) : 0,
|
||||
objects__,
|
||||
enums__,
|
||||
file_ident__,
|
||||
file_ext__,
|
||||
root_table,
|
||||
services ? _fbb.CreateVector<flatbuffers::Offset<Service>>(*services) : 0);
|
||||
services__);
|
||||
}
|
||||
|
||||
inline const reflection::Schema *GetSchema(const void *buf) {
|
||||
|
||||
@@ -72,7 +72,7 @@ class Registry {
|
||||
return DetachedBuffer();
|
||||
}
|
||||
// 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.
|
||||
|
||||
@@ -37,9 +37,9 @@
|
||||
// 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))
|
||||
#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
|
||||
|
||||
@@ -88,12 +88,33 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
||||
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||
#else
|
||||
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> {
|
||||
public:
|
||||
static unsigned long long min() { 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> {
|
||||
@@ -105,6 +126,9 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
||||
return static_cast<long long>(
|
||||
(1ULL << ((sizeof(long long) << 3) - 1)) - 1);
|
||||
}
|
||||
static long long lowest() {
|
||||
return numeric_limits<long long>::min();
|
||||
}
|
||||
};
|
||||
#endif // FLATBUFFERS_CPP98_STL
|
||||
|
||||
@@ -114,6 +138,12 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
||||
template <typename T, typename U> using is_same = std::is_same<T,U>;
|
||||
template <typename T> using is_floating_point = std::is_floating_point<T>;
|
||||
template <typename T> using is_unsigned = std::is_unsigned<T>;
|
||||
template <typename T> using is_enum = std::is_enum<T>;
|
||||
template <typename T> using make_unsigned = std::make_unsigned<T>;
|
||||
template<bool B, class T, class F>
|
||||
using conditional = std::conditional<B, T, F>;
|
||||
template<class T, T v>
|
||||
using integral_constant = std::integral_constant<T, v>;
|
||||
#else
|
||||
// Map C++ TR1 templates defined by stlport.
|
||||
template <typename T> using is_scalar = std::tr1::is_scalar<T>;
|
||||
@@ -121,6 +151,22 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
||||
template <typename T> using is_floating_point =
|
||||
std::tr1::is_floating_point<T>;
|
||||
template <typename T> using is_unsigned = std::tr1::is_unsigned<T>;
|
||||
template <typename T> using is_enum = std::tr1::is_enum<T>;
|
||||
// Android NDK doesn't have std::make_unsigned or std::tr1::make_unsigned.
|
||||
template<typename T> struct make_unsigned {
|
||||
static_assert(is_unsigned<T>::value, "Specialization not implemented!");
|
||||
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; };
|
||||
template<bool B, class T, class F>
|
||||
using conditional = std::tr1::conditional<B, T, F>;
|
||||
template<class T, T v>
|
||||
using integral_constant = std::tr1::integral_constant<T, v>;
|
||||
#endif // !FLATBUFFERS_CPP98_STL
|
||||
#else
|
||||
// MSVC 2010 doesn't support C++11 aliases.
|
||||
@@ -129,6 +175,12 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
||||
template <typename T> struct is_floating_point :
|
||||
public std::is_floating_point<T> {};
|
||||
template <typename T> struct is_unsigned : public std::is_unsigned<T> {};
|
||||
template <typename T> struct is_enum : public std::is_enum<T> {};
|
||||
template <typename T> struct make_unsigned : public std::make_unsigned<T> {};
|
||||
template<bool B, class T, class F>
|
||||
struct conditional : public std::conditional<B, T, F> {};
|
||||
template<class T, T v>
|
||||
struct integral_constant : public std::integral_constant<T, v> {};
|
||||
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
|
||||
|
||||
#ifndef FLATBUFFERS_CPP98_STL
|
||||
@@ -231,6 +283,23 @@ inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
|
||||
template <class T> bool operator==(const unique_ptr<T>& x, intptr_t y) {
|
||||
return reinterpret_cast<intptr_t>(x.get()) == y;
|
||||
}
|
||||
|
||||
template <class T> bool operator!=(const unique_ptr<T>& x, decltype(nullptr)) {
|
||||
return !!x;
|
||||
}
|
||||
|
||||
template <class T> bool operator!=(decltype(nullptr), const unique_ptr<T>& x) {
|
||||
return !!x;
|
||||
}
|
||||
|
||||
template <class T> bool operator==(const unique_ptr<T>& x, decltype(nullptr)) {
|
||||
return !x;
|
||||
}
|
||||
|
||||
template <class T> bool operator==(decltype(nullptr), const unique_ptr<T>& x) {
|
||||
return !x;
|
||||
}
|
||||
|
||||
#endif // !FLATBUFFERS_CPP98_STL
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
@@ -17,39 +17,63 @@
|
||||
#ifndef FLATBUFFERS_UTIL_H_
|
||||
#define FLATBUFFERS_UTIL_H_
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#ifndef FLATBUFFERS_PREFER_PRINTF
|
||||
# include <sstream>
|
||||
#else // FLATBUFFERS_PREFER_PRINTF
|
||||
# include <float.h>
|
||||
# include <stdio.h>
|
||||
#endif // FLATBUFFERS_PREFER_PRINTF
|
||||
#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 <errno.h>
|
||||
|
||||
#include "flatbuffers/base.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 {
|
||||
|
||||
// @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;
|
||||
@@ -73,21 +97,22 @@ template<typename T> size_t NumToStringWidth(T t, int precision = 0) {
|
||||
return string_width;
|
||||
}
|
||||
|
||||
template<typename T> std::string NumToStringImplWrapper(T t, const char* fmt,
|
||||
int precision = 0) {
|
||||
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);
|
||||
snprintf(const_cast<char *>(s.data()), (s.size() + 1), fmt, string_width, t);
|
||||
return s;
|
||||
}
|
||||
#endif // FLATBUFFERS_PREFER_PRINTF
|
||||
#endif // FLATBUFFERS_PREFER_PRINTF
|
||||
|
||||
// Convert an integer or floating point value to a string.
|
||||
// In contrast to std::stringstream, "char" values are
|
||||
// converted to a string of digits, and we don't use scientific notation.
|
||||
template<typename T> std::string NumToString(T t) {
|
||||
// clang-format off
|
||||
|
||||
#ifndef FLATBUFFERS_PREFER_PRINTF
|
||||
std::stringstream ss;
|
||||
ss << t;
|
||||
@@ -105,6 +130,9 @@ template<> inline std::string NumToString<signed char>(signed char t) {
|
||||
template<> inline std::string NumToString<unsigned char>(unsigned char t) {
|
||||
return NumToString(static_cast<int>(t));
|
||||
}
|
||||
template<> inline std::string NumToString<char>(char t) {
|
||||
return NumToString(static_cast<int>(t));
|
||||
}
|
||||
#if defined(FLATBUFFERS_CPP98_STL)
|
||||
template<> inline std::string NumToString<long long>(long long t) {
|
||||
char buf[21]; // (log((1 << 63) - 1) / log(10)) + 2
|
||||
@@ -123,6 +151,7 @@ inline std::string NumToString<unsigned long long>(unsigned long long t) {
|
||||
// Special versions for floats/doubles.
|
||||
template<typename T> std::string FloatToString(T t, int precision) {
|
||||
// clang-format off
|
||||
|
||||
#ifndef FLATBUFFERS_PREFER_PRINTF
|
||||
// to_string() prints different numbers of digits for floats depending on
|
||||
// platform and isn't available on Android, so we use stringstream
|
||||
@@ -158,7 +187,9 @@ template<> inline std::string NumToString<float>(float t) {
|
||||
// The returned string length is always xdigits long, prefixed by 0 digits.
|
||||
// For example, IntToStringHex(0x23, 8) returns the string "00000023".
|
||||
inline std::string IntToStringHex(int i, int xdigits) {
|
||||
FLATBUFFERS_ASSERT(i >= 0);
|
||||
// clang-format off
|
||||
|
||||
#ifndef FLATBUFFERS_PREFER_PRINTF
|
||||
std::stringstream ss;
|
||||
ss << std::setw(xdigits) << std::setfill('0') << std::hex << std::uppercase
|
||||
@@ -170,28 +201,193 @@ inline std::string IntToStringHex(int i, int xdigits) {
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
// Portable implementation of strtoll().
|
||||
inline int64_t StringToInt(const char *str, char **endptr = nullptr,
|
||||
int base = 10) {
|
||||
// clang-format off
|
||||
// clang-format off
|
||||
// Use locale independent functions {strtod_l, strtof_l, strtoll_l, strtoull_l}.
|
||||
#if defined(FLATBUFFERS_LOCALE_INDEPENDENT) && (FLATBUFFERS_LOCALE_INDEPENDENT > 0)
|
||||
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
|
||||
return _strtoi64(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
|
||||
return strtoll(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
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Portable implementation of strtoull().
|
||||
inline uint64_t StringToUInt(const char *str, char **endptr = nullptr,
|
||||
int base = 10) {
|
||||
// clang-format off
|
||||
#ifdef _MSC_VER
|
||||
return _strtoui64(str, endptr, base);
|
||||
#else
|
||||
return strtoull(str, endptr, base);
|
||||
#endif
|
||||
// clang-format on
|
||||
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,
|
||||
@@ -220,13 +416,7 @@ bool LoadFile(const char *name, bool binary, std::string *buf);
|
||||
// If "binary" is false data is written using ifstream's
|
||||
// text mode, otherwise data is written with no
|
||||
// transcoding.
|
||||
inline bool SaveFile(const char *name, const char *buf, size_t len,
|
||||
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();
|
||||
}
|
||||
bool SaveFile(const char *name, const char *buf, size_t len, bool binary);
|
||||
|
||||
// Save data "buf" into file "name" returning true if
|
||||
// successful, false otherwise. If "binary" is false
|
||||
@@ -242,100 +432,35 @@ inline bool SaveFile(const char *name, const std::string &buf, bool binary) {
|
||||
// Windows ('/' or '\\') separators are used.
|
||||
|
||||
// Any new separators inserted are always posix.
|
||||
|
||||
// We internally store paths in posix format ('/'). Paths supplied
|
||||
// by the user should go through PosixPath to ensure correct behavior
|
||||
// on Windows when paths are string-compared.
|
||||
|
||||
static const char kPathSeparator = '/';
|
||||
static const char kPathSeparatorWindows = '\\';
|
||||
static const char *PathSeparatorSet = "\\/"; // Intentionally no ':'
|
||||
FLATBUFFERS_CONSTEXPR char kPathSeparator = '/';
|
||||
|
||||
// Returns the path with the extension, if any, removed.
|
||||
inline std::string StripExtension(const std::string &filepath) {
|
||||
size_t i = filepath.find_last_of(".");
|
||||
return i != std::string::npos ? filepath.substr(0, i) : filepath;
|
||||
}
|
||||
std::string StripExtension(const std::string &filepath);
|
||||
|
||||
// Returns the extension, if any.
|
||||
inline std::string GetExtension(const std::string &filepath) {
|
||||
size_t i = filepath.find_last_of(".");
|
||||
return i != std::string::npos ? filepath.substr(i + 1) : "";
|
||||
}
|
||||
std::string GetExtension(const std::string &filepath);
|
||||
|
||||
// Return the last component of the path, after the last separator.
|
||||
inline 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;
|
||||
}
|
||||
std::string StripPath(const std::string &filepath);
|
||||
|
||||
// Strip the last component of the path + separator.
|
||||
inline std::string StripFileName(const std::string &filepath) {
|
||||
size_t i = filepath.find_last_of(PathSeparatorSet);
|
||||
return i != std::string::npos ? filepath.substr(0, i) : "";
|
||||
}
|
||||
std::string StripFileName(const std::string &filepath);
|
||||
|
||||
// Concatenates a path with a filename, regardless of wether the path
|
||||
// ends in a separator or not.
|
||||
inline std::string ConCatPathFileName(const std::string &path,
|
||||
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;
|
||||
}
|
||||
std::string ConCatPathFileName(const std::string &path,
|
||||
const std::string &filename);
|
||||
|
||||
// Replaces any '\\' separators with '/'
|
||||
inline std::string PosixPath(const char *path) {
|
||||
std::string p = path;
|
||||
std::replace(p.begin(), p.end(), '\\', '/');
|
||||
return p;
|
||||
}
|
||||
std::string PosixPath(const char *path);
|
||||
|
||||
// This function ensure a directory exists, by recursively
|
||||
// creating dirs for any parts of the path that don't exist yet.
|
||||
inline void EnsureDirExists(const std::string &filepath) {
|
||||
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
|
||||
}
|
||||
void EnsureDirExists(const std::string &filepath);
|
||||
|
||||
// Obtains the absolute path from any other path.
|
||||
// Returns the input path if the absolute path couldn't be resolved.
|
||||
inline 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
|
||||
}
|
||||
std::string AbsolutePath(const std::string &filepath);
|
||||
|
||||
// To and from UTF-8 unicode conversion functions
|
||||
|
||||
@@ -379,7 +504,8 @@ inline int FromUTF8(const char **in) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((static_cast<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)++;
|
||||
// UTF-8 encoded values with a length are between 2 and 4 bytes.
|
||||
if (len < 2 || len > 4) { return -1; }
|
||||
@@ -438,7 +564,7 @@ inline std::string WordWrap(const std::string in, size_t max_length,
|
||||
|
||||
return wrapped;
|
||||
}
|
||||
#endif // !FLATBUFFERS_PREFER_PRINTF
|
||||
#endif // !FLATBUFFERS_PREFER_PRINTF
|
||||
|
||||
inline bool EscapeString(const char *s, size_t length, std::string *_text,
|
||||
bool allow_non_utf8, bool natural_utf8) {
|
||||
@@ -510,6 +636,48 @@ inline bool EscapeString(const char *s, size_t length, std::string *_text,
|
||||
return true;
|
||||
}
|
||||
|
||||
inline std::string BufferToHexText(const void *buffer, size_t buffer_size,
|
||||
size_t max_length,
|
||||
const std::string &wrapped_line_prefix,
|
||||
const std::string &wrapped_line_suffix) {
|
||||
std::string text = wrapped_line_prefix;
|
||||
size_t start_offset = 0;
|
||||
const char *s = reinterpret_cast<const char *>(buffer);
|
||||
for (size_t i = 0; s && i < buffer_size; i++) {
|
||||
// Last iteration or do we have more?
|
||||
bool have_more = i + 1 < buffer_size;
|
||||
text += "0x";
|
||||
text += IntToStringHex(static_cast<uint8_t>(s[i]), 2);
|
||||
if (have_more) { text += ','; }
|
||||
// If we have more to process and we reached max_length
|
||||
if (have_more &&
|
||||
text.size() + wrapped_line_suffix.size() >= start_offset + max_length) {
|
||||
text += wrapped_line_suffix;
|
||||
text += '\n';
|
||||
start_offset = text.size();
|
||||
text += wrapped_line_prefix;
|
||||
}
|
||||
}
|
||||
text += wrapped_line_suffix;
|
||||
return text;
|
||||
}
|
||||
|
||||
// Remove paired quotes in a string: "text"|'text' -> text.
|
||||
std::string RemoveStringQuotes(const std::string &s);
|
||||
|
||||
// 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);
|
||||
|
||||
// MSVC specific: Send all assert reports to STDOUT to prevent CI hangs.
|
||||
void SetupDefaultCRTReportMode();
|
||||
|
||||
} // namespace flatbuffers
|
||||
|
||||
#endif // FLATBUFFERS_UTIL_H_
|
||||
|
||||
241
java/com/google/flatbuffers/ArrayReadWriteBuf.java
Normal file
241
java/com/google/flatbuffers/ArrayReadWriteBuf.java
Normal file
@@ -0,0 +1,241 @@
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Implements {@code ReadBuf} using an array of bytes
|
||||
* as a backing storage. Using array of bytes are
|
||||
* usually faster than {@code ByteBuffer}.
|
||||
*
|
||||
* This class is not thread-safe, meaning that
|
||||
* it must operate on a single thread. Operating from
|
||||
* multiple thread leads into a undefined behavior
|
||||
*/
|
||||
public class ArrayReadWriteBuf implements ReadWriteBuf {
|
||||
|
||||
private byte[] buffer;
|
||||
private int writePos;
|
||||
|
||||
public ArrayReadWriteBuf() {
|
||||
this(10);
|
||||
}
|
||||
|
||||
public ArrayReadWriteBuf(int initialCapacity) {
|
||||
this(new byte[initialCapacity]);
|
||||
}
|
||||
|
||||
public ArrayReadWriteBuf(byte[] buffer) {
|
||||
this.buffer = buffer;
|
||||
this.writePos = 0;
|
||||
}
|
||||
|
||||
public ArrayReadWriteBuf(byte[] buffer, int startPos) {
|
||||
this.buffer = buffer;
|
||||
this.writePos = startPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(int index) {
|
||||
return buffer[index] != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte get(int index) {
|
||||
return buffer[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort(int index) {
|
||||
return (short) ((buffer[index+ 1] << 8) | (buffer[index] & 0xff));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(int index) {
|
||||
return (((buffer[index + 3]) << 24) |
|
||||
((buffer[index + 2] & 0xff) << 16) |
|
||||
((buffer[index + 1] & 0xff) << 8) |
|
||||
((buffer[index] & 0xff)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(int index) {
|
||||
return ((((long) buffer[index++] & 0xff)) |
|
||||
(((long) buffer[index++] & 0xff) << 8) |
|
||||
(((long) buffer[index++] & 0xff) << 16) |
|
||||
(((long) buffer[index++] & 0xff) << 24) |
|
||||
(((long) buffer[index++] & 0xff) << 32) |
|
||||
(((long) buffer[index++] & 0xff) << 40) |
|
||||
(((long) buffer[index++] & 0xff) << 48) |
|
||||
(((long) buffer[index]) << 56));
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(int index) {
|
||||
return Float.intBitsToFloat(getInt(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble(int index) {
|
||||
return Double.longBitsToDouble(getLong(index));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(int start, int size) {
|
||||
return Utf8Safe.decodeUtf8Array(buffer, start, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] data() {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void putBoolean(boolean value) {
|
||||
setBoolean(writePos, value);
|
||||
writePos++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(byte[] value, int start, int length) {
|
||||
set(writePos, value, start, length);
|
||||
writePos+=length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(byte value) {
|
||||
set(writePos, value);
|
||||
writePos++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putShort(short value) {
|
||||
setShort(writePos, value);
|
||||
writePos +=2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putInt(int value) {
|
||||
setInt(writePos, value);
|
||||
writePos +=4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putLong(long value) {
|
||||
setLong(writePos, value);
|
||||
writePos +=8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putFloat(float value) {
|
||||
setFloat(writePos, value);
|
||||
writePos +=4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putDouble(double value) {
|
||||
setDouble(writePos, value);
|
||||
writePos +=8;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBoolean(int index, boolean value) {
|
||||
set(index, value ? (byte)1 : (byte)0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, byte value) {
|
||||
requestCapacity(index + 1);
|
||||
buffer[index] = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, byte[] toCopy, int start, int length) {
|
||||
requestCapacity(index + (length - start));
|
||||
System.arraycopy(toCopy, start, buffer, index, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setShort(int index, short value) {
|
||||
requestCapacity(index + 2);
|
||||
|
||||
buffer[index++] = (byte) ((value) & 0xff);
|
||||
buffer[index ] = (byte) ((value >> 8) & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInt(int index, int value) {
|
||||
requestCapacity(index + 4);
|
||||
|
||||
buffer[index++] = (byte) ((value) & 0xff);
|
||||
buffer[index++] = (byte) ((value >> 8) & 0xff);
|
||||
buffer[index++] = (byte) ((value >> 16) & 0xff);
|
||||
buffer[index ] = (byte) ((value >> 24) & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLong(int index, long value) {
|
||||
requestCapacity(index + 8);
|
||||
|
||||
int i = (int) value;
|
||||
buffer[index++] = (byte) ((i) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 8) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 16) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 24) & 0xff);
|
||||
i = (int) (value >> 32);
|
||||
buffer[index++] = (byte) ((i) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 8) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 16) & 0xff);
|
||||
buffer[index ] = (byte) ((i >> 24) & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFloat(int index, float value) {
|
||||
requestCapacity(index + 4);
|
||||
|
||||
int iValue = Float.floatToRawIntBits(value);
|
||||
buffer[index++] = (byte) ((iValue) & 0xff);
|
||||
buffer[index++] = (byte) ((iValue >> 8) & 0xff);
|
||||
buffer[index++] = (byte) ((iValue >> 16) & 0xff);
|
||||
buffer[index ] = (byte) ((iValue >> 24) & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDouble(int index, double value) {
|
||||
requestCapacity(index + 8);
|
||||
|
||||
long lValue = Double.doubleToRawLongBits(value);
|
||||
int i = (int) lValue;
|
||||
buffer[index++] = (byte) ((i) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 8) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 16) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 24) & 0xff);
|
||||
i = (int) (lValue >> 32);
|
||||
buffer[index++] = (byte) ((i) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 8) & 0xff);
|
||||
buffer[index++] = (byte) ((i >> 16) & 0xff);
|
||||
buffer[index ] = (byte) ((i >> 24) & 0xff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int limit() {
|
||||
return writePos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int writePosition() {
|
||||
return writePos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requestCapacity(int capacity) {
|
||||
if (buffer.length > capacity) {
|
||||
return true;
|
||||
}
|
||||
// implemented in the same growing fashion as ArrayList
|
||||
int oldCapacity = buffer.length;
|
||||
int newCapacity = oldCapacity + (oldCapacity >> 1);
|
||||
buffer = Arrays.copyOf(buffer, newCapacity);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
96
java/com/google/flatbuffers/BaseVector.java
Normal file
96
java/com/google/flatbuffers/BaseVector.java
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2019 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
|
||||
/**
|
||||
* All vector access objects derive from this class, and add their own accessors.
|
||||
*/
|
||||
public class BaseVector {
|
||||
/** Used to hold the vector data position. */
|
||||
private int vector;
|
||||
/** Used to hold the vector size. */
|
||||
private int length;
|
||||
/** Used to hold the vector element size in table. */
|
||||
private int element_size;
|
||||
/** The underlying ByteBuffer to hold the data of the vector. */
|
||||
protected ByteBuffer bb;
|
||||
|
||||
/**
|
||||
* Get the start data of a vector.
|
||||
*
|
||||
* @return Returns the start of the vector data.
|
||||
*/
|
||||
protected int __vector() {
|
||||
return vector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the element position in vector's ByteBuffer.
|
||||
*
|
||||
* @param j An `int` index of element into a vector.
|
||||
* @return Returns the position of the vector element in a ByteBuffer.
|
||||
*/
|
||||
protected int __element(int j) {
|
||||
return vector + j * element_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-init the internal state with an external buffer {@code ByteBuffer}, an offset within and
|
||||
* element size.
|
||||
*
|
||||
* This method exists primarily to allow recycling vector instances without risking memory leaks
|
||||
* due to {@code ByteBuffer} references.
|
||||
*/
|
||||
protected void __reset(int _vector, int _element_size, ByteBuffer _bb) {
|
||||
bb = _bb;
|
||||
if (bb != null) {
|
||||
vector = _vector;
|
||||
length = bb.getInt(_vector - Constants.SIZEOF_INT);
|
||||
element_size = _element_size;
|
||||
} else {
|
||||
vector = 0;
|
||||
length = 0;
|
||||
element_size = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the internal state with a null {@code ByteBuffer} and a zero position.
|
||||
*
|
||||
* This method exists primarily to allow recycling vector instances without risking memory leaks
|
||||
* due to {@code ByteBuffer} references. The instance will be unusable until it is assigned
|
||||
* again to a {@code ByteBuffer}.
|
||||
*/
|
||||
public void reset() {
|
||||
__reset(0, 0, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the length of a vector.
|
||||
*
|
||||
* @return Returns the length of the vector.
|
||||
*/
|
||||
public int length() {
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
49
java/com/google/flatbuffers/BooleanVector.java
Normal file
49
java/com/google/flatbuffers/BooleanVector.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2019 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import static com.google.flatbuffers.Constants.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Helper type for accessing vector of booleans.
|
||||
*/
|
||||
public final class BooleanVector extends BaseVector {
|
||||
/**
|
||||
* Assigns vector access object to vector data.
|
||||
*
|
||||
* @param _vector Start data of a vector.
|
||||
* @param _bb Table's ByteBuffer.
|
||||
* @return Returns current vector access object assigned to vector data whose offset is stored at
|
||||
* `vector`.
|
||||
*/
|
||||
public BooleanVector __assign(int _vector, ByteBuffer _bb) {
|
||||
__reset(_vector, Constants.SIZEOF_BYTE, _bb); return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the boolean at the given index.
|
||||
*
|
||||
* @param j The index from which the boolean will be read.
|
||||
* @return the boolean value at the given index.
|
||||
*/
|
||||
public boolean get(int j) {
|
||||
return 0 != bb.get(__element(j));
|
||||
}
|
||||
}
|
||||
165
java/com/google/flatbuffers/ByteBufferReadWriteBuf.java
Normal file
165
java/com/google/flatbuffers/ByteBufferReadWriteBuf.java
Normal file
@@ -0,0 +1,165 @@
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
public class ByteBufferReadWriteBuf implements ReadWriteBuf {
|
||||
|
||||
private final ByteBuffer buffer;
|
||||
|
||||
public ByteBufferReadWriteBuf(ByteBuffer bb) {
|
||||
this.buffer = bb;
|
||||
this.buffer.order(ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBoolean(int index) {
|
||||
return get(index) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte get(int index) {
|
||||
return buffer.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getShort(int index) {
|
||||
return buffer.getShort(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getInt(int index) {
|
||||
return buffer.getInt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLong(int index) {
|
||||
return buffer.getLong(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFloat(int index) {
|
||||
return buffer.getFloat(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDouble(int index) {
|
||||
return buffer.getDouble(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getString(int start, int size) {
|
||||
return Utf8Safe.decodeUtf8Buffer(buffer, start, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] data() {
|
||||
return buffer.array();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putBoolean(boolean value) {
|
||||
buffer.put(value ? (byte)1 : (byte)0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(byte[] value, int start, int length) {
|
||||
buffer.put(value, start, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void put(byte value) {
|
||||
buffer.put(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putShort(short value) {
|
||||
buffer.putShort(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putInt(int value) {
|
||||
buffer.putInt(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putLong(long value) {
|
||||
buffer.putLong(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putFloat(float value) {
|
||||
buffer.putFloat(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putDouble(double value) {
|
||||
buffer.putDouble(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBoolean(int index, boolean value) {
|
||||
set(index, value ? (byte)1 : (byte)0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, byte value) {
|
||||
requestCapacity(index + 1);
|
||||
buffer.put(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int index, byte[] value, int start, int length) {
|
||||
requestCapacity(index + (length - start));
|
||||
int curPos = buffer.position();
|
||||
buffer.position(index);
|
||||
buffer.put(value, start, length);
|
||||
buffer.position(curPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setShort(int index, short value) {
|
||||
requestCapacity(index + 2);
|
||||
buffer.putShort(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInt(int index, int value) {
|
||||
requestCapacity(index + 4);
|
||||
buffer.putInt(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLong(int index, long value) {
|
||||
requestCapacity(index + 8);
|
||||
buffer.putLong(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFloat(int index, float value) {
|
||||
requestCapacity(index + 4);
|
||||
buffer.putFloat(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDouble(int index, double value) {
|
||||
requestCapacity(index + 8);
|
||||
buffer.putDouble(index, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int writePosition() {
|
||||
return buffer.position();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int limit() {
|
||||
return buffer.limit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requestCapacity(int capacity) {
|
||||
return capacity <= buffer.limit();
|
||||
}
|
||||
|
||||
}
|
||||
60
java/com/google/flatbuffers/ByteVector.java
Normal file
60
java/com/google/flatbuffers/ByteVector.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2019 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import static com.google.flatbuffers.Constants.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Helper type for accessing vector of signed or unsigned 8-bit values.
|
||||
*/
|
||||
public final class ByteVector extends BaseVector {
|
||||
/**
|
||||
* Assigns vector access object to vector data.
|
||||
*
|
||||
* @param vector Start data of a vector.
|
||||
* @param bb Table's ByteBuffer.
|
||||
* @return Returns current vector access object assigned to vector data whose offset is stored at
|
||||
* `vector`.
|
||||
*/
|
||||
public ByteVector __assign(int vector, ByteBuffer bb) {
|
||||
__reset(vector, Constants.SIZEOF_BYTE, bb); return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the byte at the given index.
|
||||
*
|
||||
* @param j The index from which the byte will be read.
|
||||
* @return the 8-bit value at the given index.
|
||||
*/
|
||||
public byte get(int j) {
|
||||
return bb.get(__element(j));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the byte at the given index, zero-extends it to type int, and returns the result,
|
||||
* which is therefore in the range 0 through 255.
|
||||
*
|
||||
* @param j The index from which the byte will be read.
|
||||
* @return the unsigned 8-bit at the given index.
|
||||
*/
|
||||
public int getAsUnsigned(int j) {
|
||||
return (int) get(j) & 0xFF;
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,14 @@ public class Constants {
|
||||
static final int FILE_IDENTIFIER_LENGTH = 4;
|
||||
/** The number of bytes in a size prefix. */
|
||||
public static final int SIZE_PREFIX_LENGTH = 4;
|
||||
/** A version identifier to force a compile error if someone
|
||||
accidentally tries to build generated code with a runtime of
|
||||
two mismatched version. Versions need to always match, as
|
||||
the runtime and generated code are modified in sync.
|
||||
Changes to the Java implementation need to be sure to change
|
||||
the version here and in the code generator on every possible
|
||||
incompatible change */
|
||||
public static void FLATBUFFERS_1_12_0() {}
|
||||
}
|
||||
|
||||
/// @endcond
|
||||
|
||||
49
java/com/google/flatbuffers/DoubleVector.java
Normal file
49
java/com/google/flatbuffers/DoubleVector.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2019 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import static com.google.flatbuffers.Constants.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Helper type for accessing vector of double values.
|
||||
*/
|
||||
public final class DoubleVector extends BaseVector {
|
||||
/**
|
||||
* Assigns vector access object to vector data.
|
||||
*
|
||||
* @param _vector Start data of a vector.
|
||||
* @param _bb Table's ByteBuffer.
|
||||
* @return Returns current vector access object assigned to vector data whose offset is stored at
|
||||
* `vector`.
|
||||
*/
|
||||
public DoubleVector __assign(int _vector, ByteBuffer _bb) {
|
||||
__reset(_vector, Constants.SIZEOF_DOUBLE, _bb); return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the double value at the given index.
|
||||
*
|
||||
* @param j The index from which the double value will be read.
|
||||
* @return the double value at the given index.
|
||||
*/
|
||||
public double get(int j) {
|
||||
return bb.getDouble(__element(j));
|
||||
}
|
||||
}
|
||||
@@ -21,11 +21,7 @@ import static com.google.flatbuffers.Constants.*;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.*;
|
||||
import java.nio.charset.CharacterCodingException;
|
||||
import java.nio.charset.CharsetEncoder;
|
||||
import java.nio.charset.CoderResult;
|
||||
import java.util.Arrays;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/// @file
|
||||
/// @addtogroup flatbuffers_java_api
|
||||
@@ -39,7 +35,6 @@ public class FlatBufferBuilder {
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
ByteBuffer bb; // Where we construct the FlatBuffer.
|
||||
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[] vtable = null; // The vtable for the current table.
|
||||
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 vector_num_elems = 0; // For the current vector being built.
|
||||
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
|
||||
final Utf8 utf8; // UTF-8 encoder to use
|
||||
/// @endcond
|
||||
|
||||
/**
|
||||
@@ -62,10 +56,32 @@ public class FlatBufferBuilder {
|
||||
* @param bb_factory The factory to be used for allocating the internal buffer
|
||||
*/
|
||||
public FlatBufferBuilder(int initial_size, ByteBufferFactory bb_factory) {
|
||||
if (initial_size <= 0) initial_size = 1;
|
||||
space = initial_size;
|
||||
this(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;
|
||||
}
|
||||
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;
|
||||
space = bb.capacity();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,7 +90,7 @@ public class FlatBufferBuilder {
|
||||
* @param initial_size The initial size of the internal buffer to use.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
public FlatBufferBuilder(ByteBuffer existing_bb) {
|
||||
init(existing_bb, new HeapByteBufferFactory());
|
||||
this(existing_bb, new HeapByteBufferFactory());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -144,14 +160,15 @@ public class FlatBufferBuilder {
|
||||
* preserve the default behavior in the event that the user does not provide
|
||||
* their own implementation of this interface.
|
||||
*/
|
||||
public interface ByteBufferFactory {
|
||||
public static abstract class ByteBufferFactory {
|
||||
/**
|
||||
* 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.
|
||||
* @return Returns the new `ByteBuffer` that was allocated.
|
||||
*/
|
||||
ByteBuffer newByteBuffer(int capacity);
|
||||
public abstract ByteBuffer newByteBuffer(int capacity);
|
||||
|
||||
/**
|
||||
* Release a ByteBuffer. Current {@link FlatBufferBuilder}
|
||||
@@ -162,7 +179,7 @@ public class FlatBufferBuilder {
|
||||
*
|
||||
* @param bb the buffer to release
|
||||
*/
|
||||
default void releaseByteBuffer(ByteBuffer bb) {
|
||||
public void releaseByteBuffer(ByteBuffer bb) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,13 +189,27 @@ public class FlatBufferBuilder {
|
||||
*
|
||||
* 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
|
||||
public ByteBuffer newByteBuffer(int capacity) {
|
||||
return ByteBuffer.allocate(capacity).order(ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to test if a field is present in the table
|
||||
*
|
||||
* @param table Flatbuffer table
|
||||
* @param offset virtual table offset
|
||||
* @return true if the filed is present
|
||||
*/
|
||||
public static boolean isFieldPresent(Table table, int offset) {
|
||||
return table.__offset(offset) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the FlatBufferBuilder by purging all data that it holds.
|
||||
*/
|
||||
@@ -211,6 +242,7 @@ public class FlatBufferBuilder {
|
||||
int new_buf_size = old_buf_size == 0 ? 1 : old_buf_size << 1;
|
||||
bb.position(0);
|
||||
ByteBuffer nbb = bb_factory.newByteBuffer(new_buf_size);
|
||||
new_buf_size = nbb.clear().capacity(); // Ensure the returned buffer is treated as empty
|
||||
nbb.position(new_buf_size - old_buf_size);
|
||||
nbb.put(bb);
|
||||
return nbb;
|
||||
@@ -503,27 +535,12 @@ public class FlatBufferBuilder {
|
||||
* @return The offset in the buffer where the encoded string starts.
|
||||
*/
|
||||
public int createString(CharSequence s) {
|
||||
int length = s.length();
|
||||
int estimatedDstCapacity = (int) (length * encoder.maxBytesPerChar());
|
||||
if (dst == null || dst.capacity() < estimatedDstCapacity) {
|
||||
dst = ByteBuffer.allocate(Math.max(128, estimatedDstCapacity));
|
||||
}
|
||||
|
||||
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);
|
||||
int length = utf8.encodedLength(s);
|
||||
addByte((byte)0);
|
||||
startVector(1, length, 1);
|
||||
bb.position(space -= length);
|
||||
utf8.encodeUtf8(s, bb);
|
||||
return endVector();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -555,6 +572,38 @@ public class FlatBufferBuilder {
|
||||
return endVector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a byte array in the buffer.
|
||||
*
|
||||
* @param arr a source array with data.
|
||||
* @param offset the offset in the source array to start copying from.
|
||||
* @param length the number of bytes to copy from the source array.
|
||||
* @return The offset in the buffer where the encoded array starts.
|
||||
*/
|
||||
public int createByteVector(byte[] arr, int offset, int length) {
|
||||
startVector(1, length, 1);
|
||||
bb.position(space -= length);
|
||||
bb.put(arr, offset, length);
|
||||
return endVector();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a byte array in the buffer.
|
||||
*
|
||||
* The source {@link ByteBuffer} position is advanced by {@link ByteBuffer#remaining()} places
|
||||
* after this call.
|
||||
*
|
||||
* @param byteBuffer A source {@link ByteBuffer} with data.
|
||||
* @return The offset in the buffer where the encoded array starts.
|
||||
*/
|
||||
public int createByteVector(ByteBuffer byteBuffer) {
|
||||
int length = byteBuffer.remaining();
|
||||
startVector(1, length, 1);
|
||||
bb.position(space -= length);
|
||||
bb.put(byteBuffer);
|
||||
return endVector();
|
||||
}
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
/**
|
||||
* Should not be accessing the final buffer before it is finished.
|
||||
@@ -627,7 +676,7 @@ public class FlatBufferBuilder {
|
||||
*
|
||||
* @param numfields The number of fields found in this object.
|
||||
*/
|
||||
public void startObject(int numfields) {
|
||||
public void startTable(int numfields) {
|
||||
notNested();
|
||||
if (vtable == null || vtable.length < numfields) vtable = new int[numfields];
|
||||
vtable_in_use = numfields;
|
||||
@@ -752,11 +801,11 @@ public class FlatBufferBuilder {
|
||||
* Finish off writing the object that is under construction.
|
||||
*
|
||||
* @return The offset to the object inside {@link #dataBuffer()}.
|
||||
* @see #startObject(int)
|
||||
* @see #startTable(int)
|
||||
*/
|
||||
public int endObject() {
|
||||
public int endTable() {
|
||||
if (vtable == null || !nested)
|
||||
throw new AssertionError("FlatBuffers: endObject called without startObject");
|
||||
throw new AssertionError("FlatBuffers: endTable called without startTable");
|
||||
addInt(0);
|
||||
int vtableloc = offset();
|
||||
// Write out the current vtable.
|
||||
|
||||
1102
java/com/google/flatbuffers/FlexBuffers.java
Normal file
1102
java/com/google/flatbuffers/FlexBuffers.java
Normal file
File diff suppressed because it is too large
Load Diff
770
java/com/google/flatbuffers/FlexBuffersBuilder.java
Normal file
770
java/com/google/flatbuffers/FlexBuffersBuilder.java
Normal file
@@ -0,0 +1,770 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
|
||||
import static com.google.flatbuffers.FlexBuffers.*;
|
||||
import static com.google.flatbuffers.FlexBuffers.Unsigned.byteToUnsignedInt;
|
||||
import static com.google.flatbuffers.FlexBuffers.Unsigned.intToUnsignedLong;
|
||||
import static com.google.flatbuffers.FlexBuffers.Unsigned.shortToUnsignedInt;
|
||||
|
||||
/// @file
|
||||
/// @addtogroup flatbuffers_java_api
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* Helper class that builds FlexBuffers
|
||||
* <p> This class presents all necessary APIs to create FlexBuffers. A `ByteBuffer` will be used to store the
|
||||
* data. It can be created internally, or passed down in the constructor.</p>
|
||||
*
|
||||
* <p>There are some limitations when compared to original implementation in C++. Most notably:
|
||||
* <ul>
|
||||
* <li><p> No support for mutations (might change in the future).</p></li>
|
||||
* <li><p> Buffer size limited to {@link Integer#MAX_VALUE}</p></li>
|
||||
* <li><p> Since Java does not support unsigned type, all unsigned operations accepts an immediate higher representation
|
||||
* of similar type.</p></li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
public class FlexBuffersBuilder {
|
||||
|
||||
/**
|
||||
* No keys or strings will be shared
|
||||
*/
|
||||
public static final int BUILDER_FLAG_NONE = 0;
|
||||
/**
|
||||
* Keys will be shared between elements. Identical keys will only be serialized once, thus possibly saving space.
|
||||
* But serialization performance might be slower and consumes more memory.
|
||||
*/
|
||||
public static final int BUILDER_FLAG_SHARE_KEYS = 1;
|
||||
/**
|
||||
* Strings will be shared between elements. Identical strings will only be serialized once, thus possibly saving space.
|
||||
* But serialization performance might be slower and consumes more memory. This is ideal if you expect many repeated
|
||||
* strings on the message.
|
||||
*/
|
||||
public static final int BUILDER_FLAG_SHARE_STRINGS = 2;
|
||||
/**
|
||||
* Strings and keys will be shared between elements.
|
||||
*/
|
||||
public static final int BUILDER_FLAG_SHARE_KEYS_AND_STRINGS = 3;
|
||||
/**
|
||||
* Reserved for the future.
|
||||
*/
|
||||
public static final int BUILDER_FLAG_SHARE_KEY_VECTORS = 4;
|
||||
/**
|
||||
* Reserved for the future.
|
||||
*/
|
||||
public static final int BUILDER_FLAG_SHARE_ALL = 7;
|
||||
|
||||
/// @cond FLATBUFFERS_INTERNAL
|
||||
private static final int WIDTH_8 = 0;
|
||||
private static final int WIDTH_16 = 1;
|
||||
private static final int WIDTH_32 = 2;
|
||||
private static final int WIDTH_64 = 3;
|
||||
private final ReadWriteBuf bb;
|
||||
private final ArrayList<Value> stack = new ArrayList<>();
|
||||
private final HashMap<String, Integer> keyPool = new HashMap<>();
|
||||
private final HashMap<String, Integer> stringPool = new HashMap<>();
|
||||
private final int flags;
|
||||
private boolean finished = false;
|
||||
|
||||
// A lambda to sort map keys
|
||||
private Comparator<Value> keyComparator = new Comparator<Value>() {
|
||||
@Override
|
||||
public int compare(Value o1, Value o2) {
|
||||
int ia = o1.key;
|
||||
int io = o2.key;
|
||||
byte c1, c2;
|
||||
do {
|
||||
c1 = bb.get(ia);
|
||||
c2 = bb.get(io);
|
||||
if (c1 == 0)
|
||||
return c1 - c2;
|
||||
ia++;
|
||||
io++;
|
||||
}
|
||||
while (c1 == c2);
|
||||
return c1 - c2;
|
||||
}
|
||||
};
|
||||
/// @endcond
|
||||
|
||||
/**
|
||||
* Constructs a newly allocated {@code FlexBuffersBuilder} with {@link #BUILDER_FLAG_SHARE_KEYS} set.
|
||||
* @param bufSize size of buffer in bytes.
|
||||
*/
|
||||
public FlexBuffersBuilder(int bufSize) {
|
||||
this(new ArrayReadWriteBuf(bufSize), BUILDER_FLAG_SHARE_KEYS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a newly allocated {@code FlexBuffersBuilder} with {@link #BUILDER_FLAG_SHARE_KEYS} set.
|
||||
*/
|
||||
public FlexBuffersBuilder() {
|
||||
this(256);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a newly allocated {@code FlexBuffersBuilder}.
|
||||
*
|
||||
* @param bb `ByteBuffer` that will hold the message
|
||||
* @param flags Share flags
|
||||
*/
|
||||
@Deprecated
|
||||
public FlexBuffersBuilder(ByteBuffer bb, int flags) {
|
||||
this(new ArrayReadWriteBuf(bb.array()), flags);
|
||||
}
|
||||
|
||||
public FlexBuffersBuilder(ReadWriteBuf bb, int flags) {
|
||||
this.bb = bb;
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a newly allocated {@code FlexBuffersBuilder}.
|
||||
* By default same keys will be serialized only once
|
||||
* @param bb `ByteBuffer` that will hold the message
|
||||
*/
|
||||
public FlexBuffersBuilder(ByteBuffer bb) {
|
||||
this(bb, BUILDER_FLAG_SHARE_KEYS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return `ByteBuffer` containing FlexBuffer message. {@code #finish()} must be called before calling this
|
||||
* function otherwise an assert will trigger.
|
||||
*
|
||||
* @return `ByteBuffer` with finished message
|
||||
*/
|
||||
public ReadWriteBuf getBuffer() {
|
||||
assert (finished);
|
||||
return bb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a single boolean into the buffer
|
||||
* @param val true or false
|
||||
*/
|
||||
public void putBoolean(boolean val) {
|
||||
putBoolean(null, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a single boolean into the buffer
|
||||
* @param key key used to store element in map
|
||||
* @param val true or false
|
||||
*/
|
||||
public void putBoolean(String key, boolean val) {
|
||||
stack.add(Value.bool(putKey(key), val));
|
||||
}
|
||||
|
||||
private int putKey(String key) {
|
||||
if (key == null) {
|
||||
return -1;
|
||||
}
|
||||
int pos = bb.writePosition();
|
||||
if ((flags & BUILDER_FLAG_SHARE_KEYS) != 0) {
|
||||
Integer keyFromPool = keyPool.get(key);
|
||||
if (keyFromPool == null) {
|
||||
byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
|
||||
bb.put(keyBytes, 0, keyBytes.length);
|
||||
bb.put((byte) 0);
|
||||
keyPool.put(key, pos);
|
||||
} else {
|
||||
pos = keyFromPool;
|
||||
}
|
||||
} else {
|
||||
byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
|
||||
bb.put(keyBytes, 0, keyBytes.length);
|
||||
bb.put((byte) 0);
|
||||
keyPool.put(key, pos);
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a integer into the buff
|
||||
* @param val integer
|
||||
*/
|
||||
public void putInt(int val) {
|
||||
putInt(null, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a integer into the buff
|
||||
* @param key key used to store element in map
|
||||
* @param val integer
|
||||
*/
|
||||
public void putInt(String key, int val) {
|
||||
putInt(key, (long) val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a integer into the buff
|
||||
* @param key key used to store element in map
|
||||
* @param val 64-bit integer
|
||||
*/
|
||||
public void putInt(String key, long val) {
|
||||
int iKey = putKey(key);
|
||||
if (Byte.MIN_VALUE <= val && val <= Byte.MAX_VALUE) {
|
||||
stack.add(Value.int8(iKey, (int) val));
|
||||
} else if (Short.MIN_VALUE <= val && val <= Short.MAX_VALUE) {
|
||||
stack.add(Value.int16(iKey, (int) val));
|
||||
} else if (Integer.MIN_VALUE <= val && val <= Integer.MAX_VALUE) {
|
||||
stack.add(Value.int32(iKey, (int) val));
|
||||
} else {
|
||||
stack.add(Value.int64(iKey, val));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a 64-bit integer into the buff
|
||||
* @param value integer
|
||||
*/
|
||||
public void putInt(long value) {
|
||||
putInt(null, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a unsigned integer into the buff.
|
||||
* @param value integer representing unsigned value
|
||||
*/
|
||||
public void putUInt(int value) {
|
||||
putUInt(null, (long) value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a unsigned integer (stored in a signed 64-bit integer) into the buff.
|
||||
* @param value integer representing unsigned value
|
||||
*/
|
||||
public void putUInt(long value) {
|
||||
putUInt(null, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a 64-bit unsigned integer (stored as {@link BigInteger}) into the buff.
|
||||
* Warning: This operation might be very slow.
|
||||
* @param value integer representing unsigned value
|
||||
*/
|
||||
public void putUInt64(BigInteger value) {
|
||||
putUInt64(null, value.longValue());
|
||||
}
|
||||
|
||||
private void putUInt64(String key, long value) {
|
||||
stack.add(Value.uInt64(putKey(key), value));
|
||||
}
|
||||
|
||||
private void putUInt(String key, long value) {
|
||||
int iKey = putKey(key);
|
||||
Value vVal;
|
||||
|
||||
int width = widthUInBits(value);
|
||||
|
||||
if (width == WIDTH_8) {
|
||||
vVal = Value.uInt8(iKey, (int)value);
|
||||
} else if (width == WIDTH_16) {
|
||||
vVal = Value.uInt16(iKey, (int)value);
|
||||
} else if (width == WIDTH_32) {
|
||||
vVal = Value.uInt32(iKey, (int)value);
|
||||
} else {
|
||||
vVal = Value.uInt64(iKey, value);
|
||||
}
|
||||
stack.add(vVal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a 32-bit float into the buff.
|
||||
* @param value float representing value
|
||||
*/
|
||||
public void putFloat(float value) {
|
||||
putFloat(null, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a 32-bit float into the buff.
|
||||
* @param key key used to store element in map
|
||||
* @param value float representing value
|
||||
*/
|
||||
public void putFloat(String key, float val) {
|
||||
stack.add(Value.float32(putKey(key), val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a 64-bit float into the buff.
|
||||
* @param value float representing value
|
||||
*/
|
||||
public void putFloat(double value) {
|
||||
putFloat(null, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a 64-bit float into the buff.
|
||||
* @param key key used to store element in map
|
||||
* @param value float representing value
|
||||
*/
|
||||
public void putFloat(String key, double val) {
|
||||
stack.add(Value.float64(putKey(key), val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a String into the buffer
|
||||
* @param value string
|
||||
* @return start position of string in the buffer
|
||||
*/
|
||||
public int putString(String value) {
|
||||
return putString(null, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a String into the buffer
|
||||
* @param key key used to store element in map
|
||||
* @param value string
|
||||
* @return start position of string in the buffer
|
||||
*/
|
||||
public int putString(String key, String val) {
|
||||
int iKey = putKey(key);
|
||||
if ((flags & FlexBuffersBuilder.BUILDER_FLAG_SHARE_STRINGS) != 0) {
|
||||
Integer i = stringPool.get(val);
|
||||
if (i == null) {
|
||||
Value value = writeString(iKey, val);
|
||||
stringPool.put(val, (int) value.iValue);
|
||||
stack.add(value);
|
||||
return (int) value.iValue;
|
||||
} else {
|
||||
int bitWidth = widthUInBits(val.length());
|
||||
stack.add(Value.blob(iKey, i, FBT_STRING, bitWidth));
|
||||
return i;
|
||||
}
|
||||
} else {
|
||||
Value value = writeString(iKey, val);
|
||||
stack.add(value);
|
||||
return (int) value.iValue;
|
||||
}
|
||||
}
|
||||
|
||||
private Value writeString(int key, String s) {
|
||||
return writeBlob(key, s.getBytes(StandardCharsets.UTF_8), FBT_STRING, true);
|
||||
}
|
||||
|
||||
// in bits to fit a unsigned int
|
||||
static int widthUInBits(long len) {
|
||||
if (len <= byteToUnsignedInt((byte)0xff)) return WIDTH_8;
|
||||
if (len <= shortToUnsignedInt((short)0xffff)) return WIDTH_16;
|
||||
if (len <= intToUnsignedLong(0xffff_ffff)) return WIDTH_32;
|
||||
return WIDTH_64;
|
||||
}
|
||||
|
||||
private Value writeBlob(int key, byte[] blob, int type, boolean trailing) {
|
||||
int bitWidth = widthUInBits(blob.length);
|
||||
int byteWidth = align(bitWidth);
|
||||
writeInt(blob.length, byteWidth);
|
||||
int sloc = bb.writePosition();
|
||||
bb.put(blob, 0, blob.length);
|
||||
if (trailing) {
|
||||
bb.put((byte) 0);
|
||||
}
|
||||
return Value.blob(key, sloc, type, bitWidth);
|
||||
}
|
||||
|
||||
// Align to prepare for writing a scalar with a certain size.
|
||||
private int align(int alignment) {
|
||||
int byteWidth = 1 << alignment;
|
||||
int padBytes = Value.paddingBytes(bb.writePosition(), byteWidth);
|
||||
while (padBytes-- != 0) {
|
||||
bb.put((byte) 0);
|
||||
}
|
||||
return byteWidth;
|
||||
}
|
||||
|
||||
private void writeInt(long value, int byteWidth) {
|
||||
switch (byteWidth) {
|
||||
case 1: bb.put((byte) value); break;
|
||||
case 2: bb.putShort((short) value); break;
|
||||
case 4: bb.putInt((int) value); break;
|
||||
case 8: bb.putLong(value); break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a byte array into the message
|
||||
* @param value byte array
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
public int putBlob(byte[] value) {
|
||||
return putBlob(null, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a byte array into the message
|
||||
* @param key key used to store element in map
|
||||
* @param value byte array
|
||||
* @return position in buffer as the start of byte array
|
||||
*/
|
||||
public int putBlob(String key, byte[] val) {
|
||||
int iKey = putKey(key);
|
||||
Value value = writeBlob(iKey, val, FBT_BLOB, false);
|
||||
stack.add(value);
|
||||
return (int) value.iValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new vector in the buffer.
|
||||
* @return a reference indicating position of the vector in buffer. This
|
||||
* reference must be passed along when the vector is finished using endVector()
|
||||
*/
|
||||
public int startVector() {
|
||||
return stack.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes a vector, but writing the information in the buffer
|
||||
* @param key key used to store element in map
|
||||
* @param start reference for begining of the vector. Returned by {@link startVector()}
|
||||
* @param typed boolean indicating wether vector is typed
|
||||
* @param fixed boolean indicating wether vector is fixed
|
||||
* @return Reference to the vector
|
||||
*/
|
||||
public int endVector(String key, int start, boolean typed, boolean fixed) {
|
||||
int iKey = putKey(key);
|
||||
Value vec = createVector(iKey, start, stack.size() - start, typed, fixed, null);
|
||||
// Remove temp elements and return vector.
|
||||
while (stack.size() > start) {
|
||||
stack.remove(stack.size() - 1);
|
||||
}
|
||||
stack.add(vec);
|
||||
return (int) vec.iValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish writing the message into the buffer. After that no other element must
|
||||
* be inserted into the buffer. Also, you must call this function before start using the
|
||||
* FlexBuffer message
|
||||
* @return `ByteBuffer` containing the FlexBuffer message
|
||||
*/
|
||||
public ByteBuffer finish() {
|
||||
// If you hit this assert, you likely have objects that were never included
|
||||
// in a parent. You need to have exactly one root to finish a buffer.
|
||||
// Check your Start/End calls are matched, and all objects are inside
|
||||
// some other object.
|
||||
assert (stack.size() == 1);
|
||||
// Write root value.
|
||||
int byteWidth = align(stack.get(0).elemWidth(bb.writePosition(), 0));
|
||||
writeAny(stack.get(0), byteWidth);
|
||||
// Write root type.
|
||||
bb.put(stack.get(0).storedPackedType());
|
||||
// Write root size. Normally determined by parent, but root has no parent :)
|
||||
bb.put((byte) byteWidth);
|
||||
this.finished = true;
|
||||
return ByteBuffer.wrap(bb.data(), 0, bb.writePosition());
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a vector based on the elements stored in the stack
|
||||
*
|
||||
* @param key reference to its key
|
||||
* @param start element in the stack
|
||||
* @param length size of the vector
|
||||
* @param typed whether is TypedVector or not
|
||||
* @param fixed whether is Fixed vector or not
|
||||
* @param keys Value representing key vector
|
||||
* @return Value representing the created vector
|
||||
*/
|
||||
private Value createVector(int key, int start, int length, boolean typed, boolean fixed, Value keys) {
|
||||
assert (!fixed || typed); // typed=false, fixed=true combination is not supported.
|
||||
// Figure out smallest bit width we can store this vector with.
|
||||
int bitWidth = Math.max(WIDTH_8, widthUInBits(length));
|
||||
int prefixElems = 1;
|
||||
if (keys != null) {
|
||||
// If this vector is part of a map, we will pre-fix an offset to the keys
|
||||
// to this vector.
|
||||
bitWidth = Math.max(bitWidth, keys.elemWidth(bb.writePosition(), 0));
|
||||
prefixElems += 2;
|
||||
}
|
||||
int vectorType = FBT_KEY;
|
||||
// Check bit widths and types for all elements.
|
||||
for (int i = start; i < stack.size(); i++) {
|
||||
int elemWidth = stack.get(i).elemWidth(bb.writePosition(), i + prefixElems);
|
||||
bitWidth = Math.max(bitWidth, elemWidth);
|
||||
if (typed) {
|
||||
if (i == start) {
|
||||
vectorType = stack.get(i).type;
|
||||
if (!FlexBuffers.isTypedVectorElementType(vectorType)) {
|
||||
throw new FlexBufferException("TypedVector does not support this element type");
|
||||
}
|
||||
} else {
|
||||
// If you get this assert, you are writing a typed vector with
|
||||
// elements that are not all the same type.
|
||||
assert (vectorType == stack.get(i).type);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If you get this assert, your fixed types are not one of:
|
||||
// Int / UInt / Float / Key.
|
||||
assert (!fixed || FlexBuffers.isTypedVectorElementType(vectorType));
|
||||
|
||||
int byteWidth = align(bitWidth);
|
||||
// Write vector. First the keys width/offset if available, and size.
|
||||
if (keys != null) {
|
||||
writeOffset(keys.iValue, byteWidth);
|
||||
writeInt(1L << keys.minBitWidth, byteWidth);
|
||||
}
|
||||
if (!fixed) {
|
||||
writeInt(length, byteWidth);
|
||||
}
|
||||
// Then the actual data.
|
||||
int vloc = bb.writePosition();
|
||||
for (int i = start; i < stack.size(); i++) {
|
||||
writeAny(stack.get(i), byteWidth);
|
||||
}
|
||||
// Then the types.
|
||||
if (!typed) {
|
||||
for (int i = start; i < stack.size(); i++) {
|
||||
bb.put(stack.get(i).storedPackedType(bitWidth));
|
||||
}
|
||||
}
|
||||
return new Value(key, keys != null ? FBT_MAP
|
||||
: (typed ? FlexBuffers.toTypedVector(vectorType, fixed ? length : 0)
|
||||
: FBT_VECTOR), bitWidth, vloc);
|
||||
}
|
||||
|
||||
private void writeOffset(long val, int byteWidth) {
|
||||
int reloff = (int) (bb.writePosition() - val);
|
||||
assert (byteWidth == 8 || reloff < 1L << (byteWidth * 8));
|
||||
writeInt(reloff, byteWidth);
|
||||
}
|
||||
|
||||
private void writeAny(final Value val, int byteWidth) {
|
||||
switch (val.type) {
|
||||
case FBT_NULL:
|
||||
case FBT_BOOL:
|
||||
case FBT_INT:
|
||||
case FBT_UINT:
|
||||
writeInt(val.iValue, byteWidth);
|
||||
break;
|
||||
case FBT_FLOAT:
|
||||
writeDouble(val.dValue, byteWidth);
|
||||
break;
|
||||
default:
|
||||
writeOffset(val.iValue, byteWidth);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void writeDouble(double val, int byteWidth) {
|
||||
if (byteWidth == 4) {
|
||||
bb.putFloat((float) val);
|
||||
} else if (byteWidth == 8) {
|
||||
bb.putDouble(val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a new map in the buffer.
|
||||
* @return a reference indicating position of the map in buffer. This
|
||||
* reference must be passed along when the map is finished using endMap()
|
||||
*/
|
||||
public int startMap() {
|
||||
return stack.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes a map, but writing the information in the buffer
|
||||
* @param key key used to store element in map
|
||||
* @param start reference for begining of the map. Returned by {@link startMap()}
|
||||
* @return Reference to the map
|
||||
*/
|
||||
public int endMap(String key, int start) {
|
||||
int iKey = putKey(key);
|
||||
|
||||
Collections.sort(stack.subList(start, stack.size()), keyComparator);
|
||||
|
||||
Value keys = createKeyVector(start, stack.size() - start);
|
||||
Value vec = createVector(iKey, start, stack.size() - start, false, false, keys);
|
||||
// Remove temp elements and return map.
|
||||
while (stack.size() > start) {
|
||||
stack.remove(stack.size() - 1);
|
||||
}
|
||||
stack.add(vec);
|
||||
return (int) vec.iValue;
|
||||
}
|
||||
|
||||
private Value createKeyVector(int start, int length) {
|
||||
// Figure out smallest bit width we can store this vector with.
|
||||
int bitWidth = Math.max(WIDTH_8, widthUInBits(length));
|
||||
int prefixElems = 1;
|
||||
// Check bit widths and types for all elements.
|
||||
for (int i = start; i < stack.size(); i++) {
|
||||
int elemWidth = Value.elemWidth(FBT_KEY, WIDTH_8, stack.get(i).key, bb.writePosition(), i + prefixElems);
|
||||
bitWidth = Math.max(bitWidth, elemWidth);
|
||||
}
|
||||
|
||||
int byteWidth = align(bitWidth);
|
||||
// Write vector. First the keys width/offset if available, and size.
|
||||
writeInt(length, byteWidth);
|
||||
// Then the actual data.
|
||||
int vloc = bb.writePosition();
|
||||
for (int i = start; i < stack.size(); i++) {
|
||||
int pos = stack.get(i).key;
|
||||
assert(pos != -1);
|
||||
writeOffset(stack.get(i).key, byteWidth);
|
||||
}
|
||||
// Then the types.
|
||||
return new Value(-1, FlexBuffers.toTypedVector(FBT_KEY,0), bitWidth, vloc);
|
||||
}
|
||||
|
||||
private static class Value {
|
||||
final int type;
|
||||
// for scalars, represents scalar size in bytes
|
||||
// for vectors, represents the size
|
||||
// for string, length
|
||||
final int minBitWidth;
|
||||
// float value
|
||||
final double dValue;
|
||||
// integer value
|
||||
long iValue;
|
||||
// position of the key associated with this value in buffer
|
||||
int key;
|
||||
|
||||
Value(int key, int type, int bitWidth, long iValue) {
|
||||
this.key = key;
|
||||
this.type = type;
|
||||
this.minBitWidth = bitWidth;
|
||||
this.iValue = iValue;
|
||||
this.dValue = Double.MIN_VALUE;
|
||||
}
|
||||
|
||||
Value(int key, int type, int bitWidth, double dValue) {
|
||||
this.key = key;
|
||||
this.type = type;
|
||||
this.minBitWidth = bitWidth;
|
||||
this.dValue = dValue;
|
||||
this.iValue = Long.MIN_VALUE;
|
||||
}
|
||||
|
||||
static Value bool(int key, boolean b) {
|
||||
return new Value(key, FBT_BOOL, WIDTH_8, b ? 1 : 0);
|
||||
}
|
||||
|
||||
static Value blob(int key, int position, int type, int bitWidth) {
|
||||
return new Value(key, type, bitWidth, position);
|
||||
}
|
||||
|
||||
static Value int8(int key, int value) {
|
||||
return new Value(key, FBT_INT, WIDTH_8, value);
|
||||
}
|
||||
|
||||
static Value int16(int key, int value) {
|
||||
return new Value(key, FBT_INT, WIDTH_16, value);
|
||||
}
|
||||
|
||||
static Value int32(int key, int value) {
|
||||
return new Value(key, FBT_INT, WIDTH_32, value);
|
||||
}
|
||||
|
||||
static Value int64(int key, long value) {
|
||||
return new Value(key, FBT_INT, WIDTH_64, value);
|
||||
}
|
||||
|
||||
static Value uInt8(int key, int value) {
|
||||
return new Value(key, FBT_UINT, WIDTH_8, value);
|
||||
}
|
||||
|
||||
static Value uInt16(int key, int value) {
|
||||
return new Value(key, FBT_UINT, WIDTH_16, value);
|
||||
}
|
||||
|
||||
static Value uInt32(int key, int value) {
|
||||
return new Value(key, FBT_UINT, WIDTH_32, value);
|
||||
}
|
||||
|
||||
static Value uInt64(int key, long value) {
|
||||
return new Value(key, FBT_UINT, WIDTH_64, value);
|
||||
}
|
||||
|
||||
static Value float32(int key, float value) {
|
||||
return new Value(key, FBT_FLOAT, WIDTH_32, value);
|
||||
}
|
||||
|
||||
static Value float64(int key, double value) {
|
||||
return new Value(key, FBT_FLOAT, WIDTH_64, value);
|
||||
}
|
||||
|
||||
private byte storedPackedType() {
|
||||
return storedPackedType(WIDTH_8);
|
||||
}
|
||||
|
||||
private byte storedPackedType(int parentBitWidth) {
|
||||
return packedType(storedWidth(parentBitWidth), type);
|
||||
}
|
||||
|
||||
private static byte packedType(int bitWidth, int type) {
|
||||
return (byte) (bitWidth | (type << 2));
|
||||
}
|
||||
|
||||
private int storedWidth(int parentBitWidth) {
|
||||
if (FlexBuffers.isTypeInline(type)) {
|
||||
return Math.max(minBitWidth, parentBitWidth);
|
||||
} else {
|
||||
return minBitWidth;
|
||||
}
|
||||
}
|
||||
|
||||
private int elemWidth(int bufSize, int elemIndex) {
|
||||
return elemWidth(type, minBitWidth, iValue, bufSize, elemIndex);
|
||||
}
|
||||
|
||||
private static int elemWidth(int type, int minBitWidth, long iValue, int bufSize, int elemIndex) {
|
||||
if (FlexBuffers.isTypeInline(type)) {
|
||||
return minBitWidth;
|
||||
} else {
|
||||
// We have an absolute offset, but want to store a relative offset
|
||||
// elem_index elements beyond the current buffer end. Since whether
|
||||
// the relative offset fits in a certain byte_width depends on
|
||||
// the size of the elements before it (and their alignment), we have
|
||||
// to test for each size in turn.
|
||||
|
||||
// Original implementation checks for largest scalar
|
||||
// which is long unsigned int
|
||||
for (int byteWidth = 1; byteWidth <= 32; byteWidth *= 2) {
|
||||
// Where are we going to write this offset?
|
||||
int offsetLoc = bufSize + paddingBytes(bufSize, byteWidth) + (elemIndex * byteWidth);
|
||||
// Compute relative offset.
|
||||
long offset = offsetLoc - iValue;
|
||||
// Does it fit?
|
||||
int bitWidth = widthUInBits((int) offset);
|
||||
if (((1L) << bitWidth) == byteWidth)
|
||||
return bitWidth;
|
||||
}
|
||||
assert (false); // Must match one of the sizes above.
|
||||
return WIDTH_64;
|
||||
}
|
||||
}
|
||||
|
||||
private static int paddingBytes(int bufSize, int scalarSize) {
|
||||
return ((~bufSize) + 1) & (scalarSize - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @}
|
||||
49
java/com/google/flatbuffers/FloatVector.java
Normal file
49
java/com/google/flatbuffers/FloatVector.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2019 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import static com.google.flatbuffers.Constants.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Helper type for accessing vector of float values.
|
||||
*/
|
||||
public final class FloatVector extends BaseVector {
|
||||
/**
|
||||
* Assigns vector access object to vector data.
|
||||
*
|
||||
* @param _vector Start data of a vector.
|
||||
* @param _bb Table's ByteBuffer.
|
||||
* @return Returns current vector access object assigned to vector data whose offset is stored at
|
||||
* `vector`.
|
||||
*/
|
||||
public FloatVector __assign(int _vector, ByteBuffer _bb) {
|
||||
__reset(_vector, Constants.SIZEOF_FLOAT, _bb); return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the float value at the given index.
|
||||
*
|
||||
* @param j The index from which the float value will be read.
|
||||
* @return the float value at the given index.
|
||||
*/
|
||||
public float get(int j) {
|
||||
return bb.getFloat(__element(j));
|
||||
}
|
||||
}
|
||||
60
java/com/google/flatbuffers/IntVector.java
Normal file
60
java/com/google/flatbuffers/IntVector.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2019 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import static com.google.flatbuffers.Constants.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Helper type for accessing vector of signed or unsigned 32-bit values.
|
||||
*/
|
||||
public final class IntVector extends BaseVector {
|
||||
/**
|
||||
* Assigns vector access object to vector data.
|
||||
*
|
||||
* @param _vector Start data of a vector.
|
||||
* @param _bb Table's ByteBuffer.
|
||||
* @return Returns current vector access object assigned to vector data whose offset is stored at
|
||||
* `vector`.
|
||||
*/
|
||||
public IntVector __assign(int _vector, ByteBuffer _bb) {
|
||||
__reset(_vector, Constants.SIZEOF_INT, _bb); return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the integer at the given index.
|
||||
*
|
||||
* @param j The index from which the integer will be read.
|
||||
* @return the 32-bit value at the given index.
|
||||
*/
|
||||
public int get(int j) {
|
||||
return bb.getInt(__element(j));
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the integer at the given index, zero-extends it to type long, and returns the result,
|
||||
* which is therefore in the range 0 through 4294967295.
|
||||
*
|
||||
* @param j The index from which the integer will be read.
|
||||
* @return the unsigned 32-bit at the given index.
|
||||
*/
|
||||
public long getAsUnsigned(int j) {
|
||||
return (long) get(j) & 0xFFFFFFFFL;
|
||||
}
|
||||
}
|
||||
49
java/com/google/flatbuffers/LongVector.java
Normal file
49
java/com/google/flatbuffers/LongVector.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2019 Google Inc. All rights reserved.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.flatbuffers;
|
||||
|
||||
import static com.google.flatbuffers.Constants.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
/**
|
||||
* Helper type for accessing vector of long values.
|
||||
*/
|
||||
public final class LongVector extends BaseVector {
|
||||
/**
|
||||
* Assigns vector access object to vector data.
|
||||
*
|
||||
* @param _vector Start data of a vector.
|
||||
* @param _bb Table's ByteBuffer.
|
||||
* @return Returns current vector access object assigned to vector data whose offset is stored at
|
||||
* `vector`.
|
||||
*/
|
||||
public LongVector __assign(int _vector, ByteBuffer _bb) {
|
||||
__reset(_vector, Constants.SIZEOF_LONG, _bb); return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the long value at the given index.
|
||||
*
|
||||
* @param j The index from which the long value will be read.
|
||||
* @return the signed 64-bit value at the given index.
|
||||
*/
|
||||
public long get(int j) {
|
||||
return bb.getLong(__element(j));
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user