Compare commits

..

170 Commits

Author SHA1 Message Date
Wouter van Oortmerssen
bf9eb67ab9 [maven-release-plugin] prepare release 1.11.0
Change-Id: I716f6b915adfa6682b5d864857abf7d491d788b5
2019-04-24 12:09:44 -07:00
Wouter van Oortmerssen
9e7e8cbe9f Bumped version to 1.11.0
Change-Id: I0c87ad2cf8f8768cf40c5b7abea0add087a5518a
2019-04-24 11:34:53 -07:00
Clément Julliard
b72a75f87d Doc: use correct ref types for flatcc string creation. (#5305)
Some string definitions were typed as ns(Weapon_ref_t) while they should
be flatbuffers_string_ref_t. Note that the former was also compiling &
running correctly as both ref types boil down to the same underlying ref
type.
2019-04-24 10:34:21 -07:00
Philipp Wollermann
6cfcd8628a Don't test on Ubuntu 14.04 (#5302)
Ubuntu 14.04 is about to be end-of-life and Bazel CI will stop supporting it shortly afterwards.

Context: https://groups.google.com/d/msg/bazel-dev/_D6XzfNkQQE/8TNKiNmsCAAJ
2019-04-24 10:28:35 -07:00
Damien Lespiau
ddb12c0192 [Javascript] Remove newly introduced trailing whitespace in flatbuffer.js (#5300)
* Remove newly introduced trailing whitespace in flatbuffer.js

The newly introduced clear function has some trailing white space in an
otherwise whitespace clean file. Remove it.

* Remove spurious new line in the BytesBuffer construction

Another spurious white space introduced by the clear() PR.
2019-04-22 11:48:56 -07:00
Wouter van Oortmerssen
2032b94f61 Fixed file access test in the wrong location.
Change-Id: I520339b442306204563d97743efe988eab459c08
2019-04-22 09:58:29 -07:00
Damien Lespiau
860dc803fe docs: Fix where to find the Typescript typings (#5298)
This is what currently rendered:

  /flatubffers

in https://google.github.io/flatbuffers/flatbuffers_guide_use_typescript.html

Besides the typo, @types is being swallowed, the hope is that puting it between
backticks will improve the situation.
2019-04-19 13:09:26 -07:00
Wouter van Oortmerssen
5b43e4bbb8 Fix heap-buffer-overflow if there is a struct within a union
The validator previously did not check if a struct within a union was
valid, causing a heap buffer overflow.  Add a check to make sure that
the struct is valid in this case.

Change-Id: I87d41b12fdfc2a99406789531ba92b841c063c76
2019-04-19 11:49:49 -07:00
Omer Akram
ecd76e898d Update snap include path instruction (#5297) 2019-04-18 15:15:21 -07:00
Wouter van Oortmerssen
f55d4388e0 Update snap to use "flatbuffers" as name 2019-04-18 13:50:04 -07:00
Omer Akram
e7340c390f Add Linux Snap Packaging (#5293)
* SNAP: cleanup

* Lets keep it in devel mode as it requires more testing

* add better description
2019-04-18 12:22:43 -07:00
Nils Berg
90441c2078 fix check for Enum defaults (#5292)
fixes #5288
2019-04-15 11:38:44 -07:00
Nils Berg
cef8f928bb Struct typetable (#5291)
* C++: Generate MiniReflectTypeTable for Structs as well as Tables

* Update generated code

* add test
2019-04-15 11:38:00 -07:00
Vladimir Glavnyy
98b9b5a933 Add logging of warnings from the flatc compiler (#5289) 2019-04-15 11:34:09 -07:00
Wouter van Oortmerssen
d07a3d2f4c Fixed VS2010 build.
Change-Id: I3ee68c5f250d6baa02060ab2ecbc0f0fe254a9d8
2019-04-11 16:14:38 -07:00
Wouter van Oortmerssen
640df2c1f5 Allow Set() methods to handle reference types
Change-Id: I487ded77d28490189dd5d38236cb04bffaf5f11a
2019-04-11 14:18:21 -07:00
Vladimir Glavnyy
60340ac529 Fix the proto-enum leaking issue (#5286)
* Detect leak with sanitizer

* Fix proto-enum leak issue
2019-04-11 13:52:01 -07:00
Vladimir Glavnyy
2bd4a27550 Detect leak with sanitizer (#5283) 2019-04-11 10:15:11 -07:00
Vladimir Glavnyy
23bb57401c Add basic test for enum defaults (#5280) 2019-04-08 10:21:30 -07:00
Vladimir Glavnyy
dd6daa709b Part of #5265, neutral changes (#5281) 2019-04-08 10:05:50 -07:00
Vladimir Glavnyy
dd85c3b721 Enable MSVC assert report box [Abort|Retry|Ignore] if a debugger is present (#5279) 2019-04-08 10:01:41 -07:00
Henry Lee
94cb1ff9ea Add files generated by CMake to git ignore (#5278) 2019-04-05 12:35:40 -07:00
Henry Lee
3ff6cdf491 [C++]Sync the sample monster.fbs file with the tutorial (#5277)
* Fix the header file path in the tutorial doc

* Add the path field in sample/monster.fbs to match the tutorial

* Update the lobster sample file

* Update the binary sample file
2019-04-05 12:34:53 -07:00
Matt Mastracci
c329d6fa90 Ensure we don't subtract with underflow getting enum names (#5246)
* Ensure we don't subtract with underflow getting enum names

* Yep - forgot to run this
2019-04-05 12:30:58 -07:00
Anthony Liot
249f3b3714 Add method GenerateTextFromTable issue #5249 (#5266)
* Create a function GenerateGenerateTextFromTable in order to create a json from any Table

Signed-off-by: Anthony Liot <anthony.liot@gmail.com>

* Update the test to failed if loadfile or parser return false

Signed-off-by: Anthony Liot <anthony.liot@gmail.com>

* Fix snake_case name typo + space before &/*

Signed-off-by: Anthony Liot <anthony.liot@gmail.com>

* use auto

Signed-off-by: Anthony Liot <anthony.liot@gmail.com>

* Use clang-format on the added code

Signed-off-by: Anthony Liot <anthony.liot@gmail.com>
2019-04-05 11:51:29 -07:00
Kamil Rojewski
2d67de3151 Fix for build break in c# vector of unions (#5271) 2019-04-05 11:49:12 -07:00
unexge
5cdbd02404 Fix typo in Go tutorial (#5274) 2019-04-04 12:28:09 -07:00
Vladimir Glavnyy
b2ce86ef8a Add compile-time checking of numerical limits in C++ code. (#5270)
* Add checking of numerical_limits<T> in C++ code.

* Add integer suffixes (LL/ULL) to int64 values in the IntegerBoundaryTest
2019-04-01 12:03:51 -07:00
tymcauley
8e7acae013 Update grammar to reflect required type signature for enum declarations. (#5269) 2019-03-28 10:48:40 -07:00
Austin Schuh
343bbe808e Add missing test data file to BUILD file (#5264)
$ cat
/home/austin/.cache/bazel/_bazel_austin/4b3182bfa237d7e256d9f18ffe58322f/execroot/com_github_google_flatbuffers/bazel-out/k8-opt/testlogs/flatbuffers_test/test.log
exec ${PAGER:-/usr/bin/less} "$0" || exit 1
Executing tests from //:flatbuffers_test
-----------------------------------------------------------------------------
VALUE: "0"
EXPECTED: "1"
TEST FAILED: tests/test.cpp:2029, flatbuffers::LoadFile( (test_data_path
+ "union_vector/union_vector.json").c_str(), false, &jsonfile) in
VALUE: "0"
EXPECTED: "1"
TEST FAILED: tests/test.cpp:2100, parser.Parse(jsonfile.c_str()) in
VALUE: "0"
EXPECTED: "1"
TEST FAILED: tests/test.cpp:2103, VerifyMovieBuffer(jverifier) in
2019-03-25 16:17:18 -07:00
László Csomor
cb9ab2fe58 Bazel CI: fix bad value in yml (#5262)
Use the "simple format" defined here:
69cf7ec23d/buildkite/bazelci.py (L1453)

This will unbreak the "Bazel / FlatBuffers"
pipeline on Bazel CI, see
https://buildkite.com/bazel/flatbuffers
2019-03-25 12:27:35 -07:00
Nikolay Kuznetsov
4cbff97c43 Fix a warning on compiling with clang (#5258) 2019-03-25 12:06:00 -07:00
LouisP
88abae649c Add inequality operator (inspired from #263) (#5257) 2019-03-25 12:04:51 -07:00
Henry Lee
a7461433c6 [C++] Changes in the flathash program (#5255)
* Correct the usage in the flathash program

As it is possible to have -- before the occurrence of the first
input STRING.

* Exit with 1 in the flathash program when an error occurs
2019-03-21 16:23:32 -07:00
Ashay Shirwadkar
440a70f4a3 Fixed tutorial markdown file (#5248)
Path specified in tutorial file was pointing to invalid location.
2019-03-21 15:51:51 -07:00
Wouter van Oortmerssen
02e73e1ae9 Further fixes to make minireflect compatible with old behavior.
Change-Id: I92c257ec4ab4a0cf4676bd98523b766ce25bf4f6
2019-03-21 15:08:04 -07:00
Vladimir Glavnyy
f93d0f6ac1 Unify line ending rules in '.editorconfig' and '.gitattributes' (#5231)
* Unify line ending rules in '.editorconfig' and '.gitattributes'

* Revert '.gitattributes'

- fix invalid comments in the check-source.py
2019-03-18 12:47:07 -07:00
Wouter van Oortmerssen
fd51fadaac Fixed vector_delimited excluding delimiter
Change-Id: I3e758d44b9845d6df91332bb609b4b7ad88659ac
2019-03-18 12:07:36 -07:00
Wouter van Oortmerssen
11198f10f5 Fixed shadowing warning in older gcc for vector_delimited
Change-Id: Ia4d56a5eb086f86eb5d1ad6ddae64e4a51bf3aa3
2019-03-18 10:03:43 -07:00
Wouter van Oortmerssen
3b23ff18ea Made ToStringVisitor backwards compatible with older behavior.
This to support code that relied on tables being multiline,
but not vectors.

This behavior was changed in:
b1a925dfc2 (diff-c45c8fbffbc64f7ff4aa2978612b10d8)

Change-Id: I4c95471b643b2b3fab95e06b1294e19d686b492c
2019-03-14 12:00:44 -07:00
Wouter van Oortmerssen
4f066c39ce Made JS enum declarations compatible with google closure
Original change by: https://github.com/alexames

Change-Id: Ib65bd02156d1c3637ed278a8334a2307caacaa44
2019-03-11 14:33:07 -07:00
Wouter van Oortmerssen
ca68d8b043 Disabled constexpr for hashing functions.
This was incompatible with -Wc++98-c++11-compat on some platforms,
due to local variables in the function.

Change-Id: Idef510c2cefe944eef2e0656f5a219c2158063e6
2019-03-11 14:02:20 -07:00
Vladimir Glavnyy
407fb5d537 Narrows template ascii routines to prevent a possible signed overflow in generic code. (#5232) 2019-03-11 10:26:28 -07:00
Randal Stevens
73a648b685 Fix typo in dart documentation (#5230) 2019-03-11 09:49:17 -07:00
Wouter van Oortmerssen
eb2a81f73d [C++] Object API: document custom string type requirements,
implement better custom string type constructor alternative
for Unpack() and fix bug with vector of custom string types
in Pack().

Squashed commit of the following:

commit e9519c647e
Author: Luca Longinotti <luca.longinotti@inivation.com>
Date:   Tue Mar 5 18:24:49 2019 +0100

    tests: regenerate code, reverts change to CreateVectorOfStrings().

commit 117e3b0679
Author: Luca Longinotti <luca.longinotti@inivation.com>
Date:   Tue Mar 5 18:15:05 2019 +0100

    idl_gen_cpp.cpp: move clang-format on/off outside of declaration, so they are kept properly aligned automatically.

commit 4791923806
Author: Luca Longinotti <luca.longinotti@inivation.com>
Date:   Tue Mar 5 18:11:40 2019 +0100

    idl_gen_cpp.cpp: full clang-format run with provided Google format file, enforce 80 lines width.

commit 2f0402f9ff
Author: Luca Longinotti <luca.longinotti@inivation.com>
Date:   Tue Mar 5 18:09:32 2019 +0100

    CppUsage: address requested changes.
    idl_gen_cpp.cpp: fix formatting, keep CreateVectorOfStrings for normal string cases.

commit 371d4e0b79
Author: Luca Longinotti <luca.longinotti@inivation.com>
Date:   Fri Mar 1 16:35:29 2019 +0100

    Fix compile error with a vector of non-std::strings. CreateVectorOfStrings() expects a vector of std::string types, but that's not always the case.

commit 92b90d7f0f
Author: Luca Longinotti <luca.longinotti@inivation.com>
Date:   Fri Mar 1 16:15:36 2019 +0100

    Document requirement for custom string types to implement empty() and be constructible from std::string.
    Add new option --cpp-str-flex-ctor to construct custom string types not via std::string, but (char * + length).

commit 28cb2e92d5
Author: Luca Longinotti <luca.longinotti@inivation.com>
Date:   Fri Mar 1 14:31:17 2019 +0100

    idl_gen_cpp.cpp: clang-format run, to better separate changes in content from formatting.

Change-Id: I4887ba2f2c632b9e7a8c938659b088cd95690870
2019-03-11 09:42:02 -07:00
bspeice
3968d00568 [Rust] Don't use inner attributes for allow (#5212)
* Don't use inner attributes for `allow`
Messes with being able to easily include elsewhere

* Regenerate tests

* No-op to retrigger CI

* Add the rest of the `allow` attributes
2019-03-09 12:58:27 -08:00
Mathias Svensson
4f10da8d99 Small usability tweaks to the rust codegen. (#5213) 2019-03-08 13:54:57 -08:00
tymcauley
9e82ee2527 Fix rust crate for big-endian targets (#5229)
Thanks for tackling this, @tymcauley !

* big endian docker test -- wip

* tweaks

* tweaks

* tweaks

* docker tweaks

* fix conditional compilation issues

* reactivate other docker tests

* try some more cross-platform config (from tymcauley)

* Update tests/docker/languages/Dockerfile.testing.rust.big_endian.1_30_1

Co-Authored-By: rw <rw@users.noreply.github.com>

* Update tests/docker/languages/Dockerfile.testing.rust.big_endian.1_30_1

Co-Authored-By: rw <rw@users.noreply.github.com>

* Update tests/docker/languages/Dockerfile.testing.rust.big_endian.1_30_1

Co-Authored-By: rw <rw@users.noreply.github.com>

* Resolved Rust warnings during big-endian builds.

* Unify Rust test suites for x86 and MIPS builds.

Note that I had to add four extra packages to the MIPS `Dockerfile`:
`libexpat1`, `libmagic1`, `libmpdec2`, and `libreadline7`. For a reason
I couldn't identify, even the simplest Rust MIPS binaries run with
`qemu-mips` would fail with a segfault when run through this
`Dockerfile`. After installing the `gdb-multiarch` package to attempt to
debug the issue, the binaries ran successfully. I pared down the
packages installed by `gdb-multiarch`, and these four packages are the
minimum subset necessary to get Rust MIPS binaries running under
`qemu-mips`.

* Changed Rust tests to use `Vector`s instead of direct-slice-access.

The direct-slice-access method is not available on big-endian targets,
but `flatbuffers::Vector`s provide an array interface that is available
on all platforms.

* Resolved FooStruct endianness issues using explicit struct constructor.

This more closely resembles how FlatBuffers structs are constructed in
generated Rust code.

* Added explanation of how `FooStruct` parallels generated struct code.

Also collected duplicate implementations of `FooStruct` into a common
location.
2019-03-08 01:06:25 -08:00
Wouter van Oortmerssen
e237f53bfc Removed -Wc++98-compat-extra-semi for compatibility with older clang.
Change-Id: I6dfadb5289a4396ad2f3d16baf1bdb99c7534174
2019-03-07 15:15:22 -08:00
Austin Schuh
98be491e72 Bazel ci (#5228)
* Stop building for Windows until the build passes

ERROR: D:/b/bk-windows-java8-bd0z/bazel/flatbuffers/BUILD:123:1: Couldn't build file _objs/flatbuffers_test/test.obj: undeclared inclusion(s) in rule '//:flatbuffers_test':
this rule is missing dependency declarations for the following files included by 'tests/test.cpp':
  'tests/monster_test_generated.h'
  'tests/monster_extra_generated.h'

The files in tests are being found instead of the generated files since
Windows doesn't have any sandboxing.  For now, let's disable the rules
and come back to it.

* Fix buildifier warnings

Clean up docstrings and add a module docstring.
2019-03-07 15:09:30 -08:00
Wouter van Oortmerssen
71628dad0d Fixed vector of union JSON parsing.
This for some reason never had a test case, and was broken.

Change-Id: If832f5eb8b6c5ba8a75257464892634b38719c55
2019-03-07 15:05:00 -08:00
jean-airoldie
cb7b2bf87e [Rust] Fixed codegen documentation for Tables (#5227) 2019-03-06 12:00:58 -08:00
David Reiss
bfa430309a [Go] Add mutation functions for vector elements (#5221)
Fixes #5206
2019-03-05 21:16:26 -08:00
ll-antn
1c7d91cc55 Clean-up nested_parser on all paths (#5179) (#5184)
* Clean-up nested_parser on all paths (#5179)

* Added test for parsing json with invalid nested flatbuffer

* Removed utf-8 BOM from test.cpp
2019-03-04 11:35:10 -08:00
Laurent Stacul
2e865f4d4e [Fix #5112] flatc generates constructors with memset for non-trivial types (#5222) 2019-03-04 11:10:18 -08:00
csukuangfj
13c9c674fd [doc] fix typos in doc. (#5217) 2019-02-28 21:39:26 +01:00
naure
034275c6e2 Rust: Fix lifetime in union _as_ accessors (#5140)
* Fix lifetime in union _as_ accessors

In the accessors for union field, the return value is implicitly taking the lifetime of &self.
This is irrelevant and prevents usages of the returned value, because it is needlessly bound to the parent field lifetime.

This patch makes the return value inherit the lifetime of the data, like other methods do.
2019-02-26 23:48:54 -08:00
Kulikov Alexey
4e5152d886 Java: Calculation of vtable and vtable size moved to the __init method. (#5210)
vtable and vtable size depends only on `Table#bb_pos` but calculated in
`Table#_offset` method on each field lookup.
Doing this with every call of `Table#__offset` is redundant.

These values can be read once with change of `Table#bb_pos` and reused
for any field lookup.
2019-02-25 23:45:29 +01:00
Kulikov Alexey
dc61512f20 Java: Removed unused duplicate of bytebuffer from "Table#__string" method. (#5211) 2019-02-25 23:28:13 +01:00
Искандаров Егор
1d60824d56 Lua library: fix vtable reuse. (#5214)
Fixed a bug that prevented vtable reuse during buffer construction in the lua library.

Also fixed a bug in vtable equality check that was revealed after the first fix.
2019-02-25 23:27:42 +01:00
Wouter van Oortmerssen
f89badd30f Attempting to make travis not kill the Android build.
Change-Id: Icdff8a90338bd2ff79ff76fe1ebaa3481da8dea4
2019-02-25 14:10:56 -08:00
Marcus Comstedt
1b9d1b0110 IterateValue: Use ReadScalar instead of unportable reinterpret_casts (#5209)
This fixes the testcase MiniReflectFlatBuffersTest.
2019-02-25 21:45:11 +01:00
Brian Wellington
6e2d530d61 Fix incorrect code generation on Solaris Sparc. (#5208)
On Solaris Sparc, calling NumToString() with a char called the primary
version, not the signed char or unsigned char specializations, which
caused integer to string conversions to be missed.
2019-02-25 21:41:31 +01:00
Wouter van Oortmerssen
9bf9b18f0a Added -Wc++98-compat-extra-semi
And fixed 2 more extra semi-colons.

Change-Id: I1ee08e5b2f67cd0c886847c05cd4d63cfcafec3e
2019-02-25 11:42:37 -08:00
Wouter van Oortmerssen
537c6ec1e6 Added -Wextra-semi to Clang build.
Also fixed warnings this generated.

Change-Id: If3607907b2dd609f854b7b81225d9cf66af75a60
2019-02-25 09:14:56 -08:00
Brian Wellington
a1f14005ab Fix big-endian build. (#5205)
For some reason, Offset<T> is being considered a scalar, which
causes EndianSwap to be passed an Offset<T>.  This doesn't work,
as it does not support types with non-trivial constructors.  This
change adds an overload to WriteScalar(), which works around this.
2019-02-22 01:50:05 +01:00
Eric Erhardt
0cdacdfb35 Remove byte* property in ByteBufferAllocator (#5191)
* Remove byte* property in ByteBufferAllocator.

This allows consumers to read/write into native memory, but without
having to always pin the managed `byte[]` when working with managed
memory. This allows for users to not need to Dispose() ByteBuffers
when they are using the default ByteArrayAllocator class.

Instead, we use `Span<byte> GetSpan()` methods to get access to the
underlying memory buffer.

Fix #5181

* Add a set of benchmark tests.

* Add ReadOnly spans.

This allows consumers to use ReadOnlyMemory<byte> as the backing storage
for ByteBuffers, which is useful in read-only scenarios.

* Run tests using ENABLE_SPAN_T in appveyor.

* Fix FlatBuffers.Test.csproj to work on older MSBuild versions.

* Change the test script to test UNSAFE_BYTEBUFFER

* Address PR feedback.

Remove IDisposable from ByteBuffer.

* Respond to PR feedback.
2019-02-21 23:36:55 +01:00
bwelling
bb58442054 Improve endian detection. (#5204)
Add support for using __BYTE_ORDER__, to support platforms where g++
doesn't explicitly define __BIG_ENDIAN__, like Solaris Sparc.
2019-02-21 22:45:11 +01:00
Marc Butler
4567b13115 Add RPM packaging support (#5177)
* Add RPM packaging support

Using the existing PackageDebian as template add support for
generating an rpm with the package target.

* Restore debian package target

Also add an option to advertise the fact.

* Update package description

C-n-p from README.md

* Update rpm package maintainer
2019-02-21 20:06:04 +01:00
Kamil Rojewski
8f8fb2b367 Fixed vector of unions crash in java (#5190)
* Fixed vector of unions crash in java

* Regenerated test code

* Fixed windows tests
2019-02-21 19:50:13 +01:00
Efe Burak
69d761d15e Added .net core project (#5187) 2019-02-21 19:47:19 +01:00
csukuangfj
4f32cbf268 Fix an error in cpp code. (#5189)
Change monster_generate.h to monster_generated.h
2019-02-19 20:23:10 +01:00
Vladimir Glavnyy
0eaaf18192 Utility for checking the encoding and line ending of source files (#5188)
* Add utility for checking the encoding of source files

- accept source files with ASCII or UTF-8 without BOM
- accept only CRLF line ending

* Fix non-ascii symbol in idl_parcer.cpp

* Remove BOM from test.cpp
2019-02-19 20:22:25 +01:00
Wouter van Oortmerssen
957d167199 Fixed use of WIN32 needs to be _WIN32.
Change-Id: Ie1f88ac5613cc09ed1074608dd6517ae20c7973d
2019-02-19 10:49:55 -08:00
Austin Schuh
e9d9d64527 Add presubmit.yml for bazel CI configuration (#5193)
https://github.com/bazelbuild/continuous-integration/tree/master/buildkite#configuring-a-pipeline
2019-02-19 02:55:50 +01:00
Wouter van Oortmerssen
78c50e340b Fix AppVeyor script not including CMake dir
Change-Id: I737a74dd4d31ca6d1559958f4c76e61e1f0a2c64
2019-02-14 16:21:07 -08:00
Christopher Cifra
9d483a3f0b Changed the JavaScript generation to emit createX helper functions just like the TypeScript code generation. I also added code so that the create methods have documentation in both JavaScript and TypeScript. (#5168) 2019-02-15 01:00:33 +01:00
Eric Erhardt
b650dfba49 [C#] Fix FlatBuffers.Tests when ENABLE_SPAN_T is defined (#5182)
There is a test code error that causes the CanReadCppGeneratedWireFile test to fail when ENABLE_SPAN_T is defined. When TestarrayofboolsLength is not 0, then the GetTestarrayofboolsBytes() should have a length.
2019-02-15 00:53:36 +01:00
Aleix Pol
6980818337 Install flatc as requested (#5180)
If FLATBUFFERS_BUILD_FLATC and FLATBUFFERS_INSTALL are set, flatc should
be installed regardless of the configuration.
2019-02-14 22:19:36 +01:00
Kamil Rojewski
224f7527e3 Generting imports for external enums in TS (#5175) 2019-02-14 22:08:55 +01:00
Austin Schuh
a66a88034a Fix bazel build (#5174)
rules_go was out of date.  Update that.  Also, a dependency
monster_extra_cc_fbs snuck in.  So, let's add that.

Fixes: #5163
2019-02-14 22:05:46 +01:00
Gabriel Nützi
e1defaae5e Add flag to make short names in JS/TS. (#5152)
* Add flag to make short names in JS/TS.

* Synced all missing docs in Compiler.md <-> flatc.cpp.

* Review changes.
2019-02-11 21:34:10 +01:00
Enrico Olivelli
78fdce28c7 Make ByteBufferFactory an abstract class in order to make FlatBuffers compatible with Java7. (#5155)
Introduce a HeapByteBufferFactory singleton instance in order to reduce allocations.
Clarify the usage of LITTLE_ENDIAN ByteBuffers in ByteBufferFactory.
2019-02-11 21:02:32 +01:00
iceboy
60e94cf083 Implement (shared) attribute for C++ (#5157)
* Implement native_shared attribute for C++.

Fixes #5141. See also #5145.

* Refine comment in idl.h

* Also refine docs

* Revert "Also refine docs"

This reverts commit 09dab7b45c.

* Also refine docs again.

* grumble
2019-02-11 20:53:45 +01:00
Wouter van Oortmerssen
cf47f27164 Turn on -Werror=unused-private-field for Clang.
Change-Id: Ibabc1456baf190eba191ebe0b81e3d73a4acc98f
2019-02-11 09:55:48 -08:00
Wouter van Oortmerssen
cc7f9b89f3 Made FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE #ifdef out less
This is to protect against cases where part of a project is
compiled with or without this flag, making for very fragile
and hard to find bugs, such as sizeof(Verifier) changing.

Change-Id: I01c895cdc5b44f860e4b0b9c9613bff1983e2b9d
See: https://bugs.chromium.org/p/chromium/issues/detail?id=929847
2019-02-07 16:34:25 -08:00
Wouter van Oortmerssen
600f3fbcd4 Reduced force_align in tests to 8, to work with --object-api.
More detail:
https://github.com/google/flatbuffers/projects/6#card-17401359

See also the .md changes in this commit.

Change-Id: Idfa68b2fd3bdb19979833737d3a3cf83ec1d6775
2019-02-07 14:51:04 -08:00
Charlie Harrison
76a024137f Removing 'using namespace' usage in test_builder (#5154)
* Removing 'using namespace' usage in test_builder

* Fix GRPC tests
2019-02-05 02:07:05 +01:00
Travis Staley
31e34faa15 Changing array to be an associative array so that the Name function can work with non-sequential enums as well as those beginning at something other than zero. (#5151)
Also including the resulting changes in php files.
2019-02-04 23:33:57 +01:00
Jon Kunkee
4d98faa515 Only use __movsb on architectures that support it (#5147)
With the introduction of Windows 10 on ARM (ARM64), code that assumes
that Windows targets are always x86 or x86_64 targets needs to be
updated.

The hot function ReadUInt64 has been optimized in MSVC builds using the
compiler intrinsic __movsb. Since this does not exist on ARM64 Windows,
this change uses the pure C++ path that other platforms use instead.
2019-02-04 18:57:34 +01:00
Henry Lee
d8210d5a83 Make changes on the make_unsigned type trait (#5136)
Fix a typo in the static assert message in `make_unsigned`

Support more specifications for `make_unsigned`
2019-01-28 17:31:58 -08:00
Vladimir Glavnyy
7d3930a2fd Repair fallthrough was broken by d4493165 (#5115) (#5139)
- GCC: fixed broken `fallthrough` (checked with 7.3 and 8.2)
- Clang: added `fallthrough` support
- Clang: added `-Wimplicit-fallthrough` checking
2019-01-28 10:16:12 -08:00
find
347dba8501 delete zero width space characters <U+200B>'s to avoid MSVC warning C4819 (#5133) 2019-01-24 15:02:48 -08:00
Vladimir Glavnyy
fcacb46d01 Replace deprecated Vector::Length() with Vector::size() (#5131)
- enable FLATBUFFERS_ATTRIBUTE if C++17 or higher
2019-01-24 13:33:19 -08:00
Vladimir Glavnyy
3f388ec747 Repair MSVC-CRT leakage detector and enable this detection with Appveyor-CI (#5105) 2019-01-24 13:30:11 -08:00
jean-airoldie
38bf4cfc03 [Rust] Added global namespace imports (#5121)
* [Rust] Added global namespace imports

* Documented the need for global imports

* Added white_space params to GenNamespaceImports

* Removed a \n from GenNamespaceImports
2019-01-24 13:25:56 -08:00
Henry Lee
c2f40c37b2 [C++]Support reverse iterator in Vector (#5128)
* Add `const` keyword to the `operator-(const uoffset_t &)` function in
`VectorIterator`

* Support reverse iterator in Vector

Introduced a new VectorReverseIterator type. We cannot directly use
`std::reverse_iterator<VectorIterator>` because the signature of
`operator*` and `operator->` in the VectorIterator class are not
standard signatures.

Also added `rbegin()`, `rend()`, `cbegin()`, `cend()`, `crbegin()`
and `crend()` in the Vector class.
2019-01-24 13:24:01 -08:00
Vlad Frolov
63d51afd11 [docs] [rust] Add "Useful tools created by others" section (#5127) 2019-01-17 11:56:52 -08:00
Vladimir Glavnyy
d44931656a Fix high certainty warnings from PVS-studio (#5115)
* Fix high certainty warnings from PVS-studio

- Introduced FLATBUFFERS_ATTRIBUTE macro to use [[attribute]] if modern C++ compiler used

* Update the note about __cplusplus usage in the MSVC
2019-01-17 09:49:27 -08:00
Robert
bbfd12eb11 Docker tests for Zend PHP and Mono C#; Python coverage; TODO for HHVM PHP (#5125)
* Docker test for Zend PHP 7.3

* hhvm

* move failing hhvm test to TODO zone

* c# mono 5.18 test

* python coverage reports
2019-01-16 16:41:02 -08:00
cor3ntin
7c94ff6c30 Reference::ToString should be const (#5118) 2019-01-14 09:39:58 -08:00
Vladimir Glavnyy
4fa4d36706 Add default NaN/Inf to C#, Java, Python (#5107)
* Add default NaN/Inf to C#, Java, Python

* Python NaN/Inf test added

* Remove MSVC2010/13 dependent code
2019-01-14 09:23:42 -08:00
unintellisense
46208b1e91 JS- support clear() method on builder (#5109)
* support clearing flatBuffer builder in js

* remove unused member
 reset force_defaults
dont actually need to clear data in bytebuffer
2019-01-14 09:21:42 -08:00
Vladimir Glavnyy
b99332efd7 Move all platform dependent headers and code to util.cpp module (#5106) 2019-01-07 10:12:57 -08:00
Vladimir Glavnyy
dd288f71f3 Add NaN and Inf defaults to the C++ generated code. (#5102)
* Add `NaN` and `Inf` defaults to the C++ generated code.

* Refactoring: add FloatConstantGenerator

* Refactoring-2:

- remove isnan checking for all float/double values
- add most probable implementation of virtual methods of FloatConstantGenerator

* Add conditional (FLATBUFFERS_NAN_DEFAULTS) isnan checking
2019-01-07 10:04:44 -08:00
Yong Tang
155c55900f Add repository name to build_defs.bzl (#5104)
In flatbuffers, build_defs.bzl has been updated to have the
bazel rule `flatbuffer_cc_library` defined. Therefore, it should
be possible to build another application and using `flatbuffer_cc_library`
directly (by `load("@com_github_google_flatbuffers//:build_defs.bzl", "flatbuffer_cc_library")`)

However, when I tried to do the above, I saw the following errors in bazel:
```
ERROR: /root/.cache/bazel/_bazel_root/c27e9809996ce9a9c0ed8dd79ef0897b/external/arrow/BUILD.bazel:12:1: in deps attribute of cc_library rule @arrow//:arrow_format: target '@arrow//:runtime_cc' does not exist. Since this rule was created by the macro 'flatbuffer_cc_library', the error might have been caused by the macro implementation in /root/.cache/bazel/_bazel_root/c27e9809996ce9a9c0ed8dd79ef0897b/external/com_github_google_flatbuffers/build_defs.bzl:216:16
```

The reason for the bazel error was that `//:runtime_cc` and `//:flatc` does not have
the repo name prefixed.

By prefix `` the above bazel build error could be resolved.

This fix should help other programs to use flatbuffers directly through bazel.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
2019-01-07 09:55:55 -08:00
Robert
0eb7b3beb0 [Go] Namespaced imports fix (#5097)
Track and emit required FlatBuffers namespace imports in generated Go code.

Update Go code generator by moving most functionality into the generator class, to facilitate namespace tracking. (Note that the git diff in this combined commit may appear large due to this refactoring, but very little code was actually changed.)
Update Go code generator by tracking namespace imports when generating FlatBuffers code.
Update Go code generator by emitting package imports to correctly reference code in other FlatBuffers namespaces.
Create Go test that checks the usage of InParentNamespace objects (as defined in the example schema).
Create Docker test that checks the Go language port.
Fixes #4883
Fixes #3927

Individual commits:

* remove "static" from soon-to-be method functions
* move almost all functions into class as methods
* set current namespace and emit package names if needed
* track imported namespaces
* parent namespaces work
* docker test for go ^1.11
* update base image name for go docker test
* remove cerr debugging
* formatting fixes
* re-run generate_code.sh
* explicitly test namespace imports and usage
2018-12-27 20:57:19 -05:00
Wouter van Oortmerssen
a821b15634 Added -Werror=implicit-fallthrough=2 to GCC 7 build.
Change-Id: I3f23bb1478763334dbc7e43579555518fb2412c2
2018-12-26 16:03:07 -08:00
Peter Dillinger
87704e987e Performance improvement to generated+supporting PHP (#5080)
By avoiding redundant alignment+alloc checks (startVector does prep) and virtual calls
(by making the class final) in inner loops.
2018-12-20 16:10:20 -08:00
Owen O'Malley
cb99116aca Java: Pulling in protobuf's faster UTF-8 encoder. (#5035)
* Pulling in protobuf's faster UTF-8 encoder.

* Remove Utf8 unsafe code.
2018-12-17 13:53:49 -08:00
Vladimir Glavnyy
9ad73bf5a7 Fix 'no_sanitize_undefined' attribute for GCC4.8 (#5090) 2018-12-17 11:50:31 -08:00
tira-misu
dba962ebb8 Enable flatbuffer to initialize Parser from bfbs (#4283) (#5077)
* Enable flatbuffer to initialize Parser from bfbs (#4283)

Now its possible to generate json data from bfbs data type and flatbuffers data
and visa versa.

* add deserialize functionality in parser from bfbs
* add small usage sample

* Fix build break

* Merge branch 'pr/1' into fix-issue4283

* Fix buildbreak

* Build monster_test.bfbs with --bfbs-builtins

Attribute flexbuffer has be included in bfbs. Only with this attribute test
will run. By initialization a parser by a bfbs the attribute has to be known
for this filed. monsterdata_test.golden has a flexbuffer field so parse would
fail.

* Fix generate_code.sh

* Revert automatic indent changes by IDE

* Auto detect size prefixed binary schema files

* Use identifier (bfbs) to detect schema files
2018-12-13 11:59:27 -08:00
Christian Lang
60a0f35fbc generated cmake command for flatc generation should depend on source file (#5087) 2018-12-13 11:56:51 -08:00
Rob Agar
58e8552da0 Get rid of reproducible build warning by removing build date & time from flatc version (#5086)
* disable reproducible build warning due to date/time macros

* wrapped GCC pragmas in #ifdef _GNUC_

* removed __DATE__ and __TIME__ macros from flatc.cpp
2018-12-10 12:48:09 -08:00
Austin Schuh
d56a4055da Add flatbuffer_cc library support (#5061)
* Add flatbuffer_cc library support

* Update flags so all the tests pass

Tests now all pass!

* Modify the tests to use the generated code

This should be a simple serialize/deserialize test of the new generated
code to make sure the bazel rules are doing something sane.

* Use generated monster_test.fb in testing/test.cpp

cmake drops it's generated code in tests/monster_test_generated.h
Instead of checking that in, let's generate it with bazel.

* Make grpc tests depend on monster_test_generated.h

* Remove redundant cmake dependency

This should address @aardappel's feedback.

* Run flatc for Android as well

This will fix the last travis.ci failure

* Add generated output folder and fix flags

* Move flatbuffers_header_build_rules to the library that uses it

* Use --cpp-ptr-type to fix android

Android was the only target using the STL emulation layer.  It needed
the --cpp-ptr-type flatbuffers::unique_ptr flag to work.  Add it!

* Roll back changes to use autogenerated monster_test_generated.

Flip tests/test.cpp to use the autogenerated file as well.
2018-12-10 12:23:40 -08:00
Kamil Rojewski
30c4948541 Renamed JS generator to explicitly state it generates TS too (#5043) 2018-12-06 11:12:06 -08:00
Simon.S.King
80d148b175 [net] Fix issue #5036 when write a double value into bytebuffer at big endian machine with unsafe mode. (#5076) 2018-12-03 09:50:26 -08:00
Matt Frantz
2aa0d9a54d Support nulls in String compare, CreateSharedString (#5060) 2018-12-03 09:48:50 -08:00
Robert
79cd55bd3a CI: Dockerized language port tests (#5066)
This runs a script in TravisCI that executes a bunch of small Docker image
scripts to test the language ports in isolated environments. This allows us to
test multiple language versions with little additional complexity.

Covers:

+ Java OpenJDK 10.0.2
+ Java OpenJDK 11.0.1
+ Node 10.13.0
+ Node 11.2.0
+ Python CPython 2.7.15
+ Python CPython 3.7.1
+ Rust 1.30.1
2018-11-29 22:03:06 -08:00
Robert
b378b8eb69 Fix create_vector_of_strings to use the stack, and test it. (#5074) 2018-11-29 11:47:28 -08:00
Sumant Tambe
9635d494b3 Fix Java generator bug that ignores bidi streaming attribute (#5063)
* Fix Java generator bug that ignores streaming: bidi attribute
Tests

* Java gRPC client streaming test

* Java gRPC Bidi Streaming Test
2018-11-29 10:33:17 -08:00
Robert
0143f4e364 disable unimportant RAM-heavy test b/c Windows (#5047) 2018-11-16 22:03:51 -08:00
Russell Chou
e161ade68c Make Parser skip files it's seen already. (#5048)
The use case is so we can batch compile a bunch of schemas, some which can depend on each other, without caring about their order.
2018-11-16 17:11:23 -08:00
Wouter van Oortmerssen
f575b02fda Make string/vector field serialization order not depend on optimizer.
Multiple calls of e.g. CreateString inside a call to a CreateTable
could cause those strings to end up in different locations in the
wire format, since order or argument evaluation is undefined.

This is allowed by the FlatBuffer format, but it is not helpful,
especially when debugging the contents of binaries, or comparing
against a "golden" binary for tests etc.

Now making sure that all the CreateTableDirect calls first serialize
sub strings/vectors before calling CreateTable.

Also made similar changes to the serialization of "binary schemas".

Change-Id: I5747c4038b37a0d400aca2bc592bec751cf5c172
2018-11-16 17:08:35 -08:00
Vladimir Glavnyy
5f32f94810 Make the Parser independent from the global C-locale (#5028)
* Make the Parser independent from the global C-locale

* Set a specific test locale using the environment variable FLATBUFFERS_TEST_LOCALE

* Remove redundant static qualifiers
2018-11-16 09:24:06 -08:00
Kamil Rojewski
d6b1ce09cf Fixed double generated file name postfix (#5046)
* Fixed double generated file name postfix

* Fixed missing file postfix on imports without reexports
2018-11-16 09:20:29 -08:00
Austin Schuh
f23009f04f Make flatbuffer C++ tests work when vendored with bazel (#5040)
Tests for third_party code are run out of the main workspace.  This
isn't an issue when the main workspace is the
com_github_google_flatbuffers workspace, but is an issue when you are
running the tests from another repository.

To reproduce, use "git_repository" to add flatbuffers to a project and
then run:
  bazel test @com_github_google_flatbuffers//:flatbuffers_test
2018-11-16 09:19:34 -08:00
Kamil Rojewski
30bae01ea3 Convenient createX methods for TS (#5044) 2018-11-16 09:17:54 -08:00
Shivendra Agarwal
9068b0ee63 flexbuffers blob to string implementation (#5039) 2018-11-15 14:57:05 -08:00
Robert
f8a0d3889b Fix missing doxygen link to Rust docs 2018-11-13 11:10:03 -08:00
Antonio Park
688fc77460 Wrong int32 min-max range definition on numTypes.lua (#5031)
* Update numTypes.lua

int32 range was wrongly defined.

* Update numTypes.lua

Fix number 32 to 31
2018-11-12 09:40:24 -08:00
Uilian Ries
dd8922878d Update Conan version Automatically (#5027)
* #5026 Add FindFlatBuffers.cmake to Conan Package

Signed-off-by: Uilian Ries <uilianries@gmail.com>

* #5026 Build Flatbuffers on OSX 10

Signed-off-by: Uilian Ries <uilianries@gmail.com>

* #5026 Auto update Conan package version

Signed-off-by: Uilian Ries <uilianries@gmail.com>

* #5026 Update Conan docker images

Signed-off-by: Uilian Ries <uilianries@gmail.com>

* #5026 Update tag var on Appveyor

Signed-off-by: Uilian Ries <uilianries@gmail.com>

* #5026 Filter appveyor brach name

Signed-off-by: Uilian Ries <uilianries@gmail.com>
2018-11-12 08:49:42 -08:00
Shivendra Agarwal
ab54e61805 FlexBuffer to JSON convertor for typed and fixedTypedvectors (#4947)
* FlexBuffer to JSON convertor for typed and fixedTypedvectors

* moving the common implementation to template

* signed unsigned comparison fix

* fix a formatting ({

* changing logic to append comma in vector of elements in json
2018-11-12 08:49:11 -08:00
Wouter van Oortmerssen
f445c1eb4a Fixed STLPort build
Change-Id: I2b9508f547667695475be64fa56f64f129603fd4
2018-11-05 16:33:35 -08:00
Wouter van Oortmerssen
980a6d66d3 Fixed vectors of enums in object API serialized incorrectly.
And also added tests for them.

Change-Id: I91af1904105435601287291412e82d5066f476a5
Tested: on Linux.
2018-11-05 14:33:36 -08:00
Wouter van Oortmerssen
21591916af Fixed missing code from @javax.annotation PR.
https://github.com/google/flatbuffers/pull/4986 missed part of the
implementation.

Change-Id: Ie41771eb018a550c289c77ebe9ef5c50d1ad6751
2018-11-02 11:40:21 -07:00
Sumant Tambe
b6c3d7b899 Fix a memory leak in builder test (#5021)
* Fix a memory leak in builder test

* using RAII to free memory
2018-11-02 10:04:58 -07:00
Gabriel Nützi
db0fcdd906 --keep-prefix for JS generator (#5018)
* keep include path

* add option --keep-prefix for js

* format contribution (format whole files before merge!)

* revert util.h : IsAbsPath ...

* JS Generator: only support relatives paths (keep it as it was)
2018-11-02 08:54:43 -07:00
Frank Benkstein
91fe9ba93f make unions with type aliases more usable (#5019)
Some generic C++ and Rust code is not generated when unions use type
aliases because of potential ambiguity. Actually check for this
ambiguity and only disable offending code only if it is found.
2018-11-01 12:51:25 -07:00
Robert
4c3b6c247d Rust: test that no heap allocs happen on hot paths (#5022) 2018-10-31 18:08:14 -07:00
Wouter van Oortmerssen
160e8f2fdc Disallowed 0 byte structs.
This is because they are incompatible with C++ and possibly other
languages that make them minimum size 1 (to make sure multiple
such objects don't reside at the same address). Forcing them to size
1 was also not practical, as that is requires updating the logic
of a lot of implementations and thus possibly backwards incompatible.

More here: https://github.com/google/flatbuffers/issues/4122

Change-Id: I2bfdc8597b7cfd2235bb4074bb2ae06f81f8e57d
2018-10-29 17:40:19 -07:00
Wouter van Oortmerssen
705577de51 Revert "Convert net/FlatBuffers project to be compatible with netstandard (#4811)"
This reverts commit 72b05bc865.

Change-Id: I17510b7fa49b9861ce0a870b16f5c14a41082db5
2018-10-29 17:21:30 -07:00
Vladimir Glavnyy
0fb1d44bc4 Add 'fsanitize=address,undefined' to tests and flatc targets (#5009)
* Add '-fsanitize' optional flags to flattests and flatc targets

Control: -DFLATBUFFERS_CODE_SANITIZE=(ON | OFF | "=memory,undefined")
Travis-CI: building with -DFLATBUFFERS_CODE_SANITIZE=ON

* Fix -pie flag

* Cleanup
2018-10-29 11:29:05 -07:00
Wouter van Oortmerssen
bd20a60d6a Fixed Java gRPC version numbers.
Change-Id: Iff00a48b370f45f80d68e6c6929483d608ce1885
2018-10-25 13:48:41 -07:00
Wouter van Oortmerssen
b78c4332be Fixed npm publish appending multiple copies into .mjs
Change-Id: Id8c373b0f77d9a0f4922257339abb4e01e06c2d4
2018-10-25 13:48:41 -07:00
csmoe
636b516492 clean up unnecessary outer rust gen-snippet (#5013)
* clean up unneeded outer rust gen-snippet

* update generated rust file
2018-10-23 20:16:18 -07:00
Felix Hanley
560718e976 Use stdlib context in generated Go files (#4904) 2018-10-22 16:28:58 -07:00
Doug Muir
ff687ae9c1 Make alignment checking optional. (#5011) 2018-10-22 16:14:44 -07:00
Frank Benkstein
ca417426c7 make flatbuffers::IsFieldPresent safer (#4988)
Give the vtable offset enum inside each table the name
"FlatBuffersVTableOffset" and base type voffset_t so it can be used as a
dependent type in IsFieldPresent. This makes that function slightly
safer since it prevents calling it with arbitrary, non-table types.
Now, the only way to use IsFieldPresent incorrectly is to create your
own type which does not inherit from flatbuffers::Table but has a
dependent voffset convertible type "FlatBuffersVTableOffset".
2018-10-22 15:57:45 -07:00
Vladimir Glavnyy
55b30827f2 Add fuzzer test for scalar numbers in json. (#4996)
* Add fuzzer test for scalar numbers in json. Grammar-based regex used to check correctness.

* Fix conversation
2018-10-22 15:44:18 -07:00
Frank Benkstein
efbb11e093 CI check generate code (#4998)
* call reflection code generation from tests

This simplifies instructions to contributors so they don't forget to update
reflection code.

* add error handling to generate_code scripts

Let them propagate their errors instead of swallowing them so they show
up when called in CI.

* apply editorconfig to shell scripts

* use ordered map in dart codegen

Using an unordered map in the codegen can lead to spurious diffs in the
generated dart code.

* add CI check for generate_code being run

* update reflection_generated.h

* disable diff-check for monster_test.bfbs

Work around #5008.
2018-10-22 15:41:12 -07:00
Frank Benkstein
5c0f914f38 forbid enum values that are out of range (#4977)
* forbid enum values that are out of range

Enum values that are out of range can lead to generated C++ code that does
not compile.  Also forbid boolean enums.

* update enum and union documentation slightly
2018-10-18 10:39:08 -07:00
Sumant Tambe
802639e40d Efficient Conversion of a FlatBufferBuilder to a MessageBuilder (#4980)
* Efficient conversion of FlatBufferBuilder to grpc::MessageBuilder

* Added a variety of tests to validate correctness of the MessageBuilder move operations.
Disable MessageBuilder half-n-half tests on MacOS.

* Fix failing Android build

* Generalized the MessageBuilder move constructor to accept a deallocator
2018-10-18 10:32:59 -07:00
Felix Frank
ad8b1e5dbd [Python] Fast serialization of numpy vectors (#4829)
[Python] Fast serialization of numpy vectors (#4829)
2018-10-15 17:07:08 -07:00
kostya-sh
76d31e1b5e Go - Use Go bool type for bool fields (#4962)
* Use Go bool type for bool fields, and store non-default bool field to test data
2018-10-15 16:55:59 -07:00
Frank Benkstein
20396a1760 disallow c style casts (#4981)
Fixes #4857.
2018-10-15 15:11:31 -07:00
Frank Benkstein
a3d8391f7b don't use std::function in flatbuffers::Parser (#4995)
std::function makes code harder to debug because it requires stepping
through a separate destructor and call operator.  It's use unnecessary
in the Parser since the functions taking functors are private and are
only used within idl_parser.cpp.  Therefore the definitions can stay in
idl_parser.cpp as well.  Only care must be taken that the definitions
appear before use but that's already true and all compilers will
complain equally if it get's violated.  This change might also improve
performance since it might allow inlining where it wasn't possible
before but I haven't measured that.
2018-10-15 12:26:35 -07:00
iceboy
241e87d143 add :runtime_cc target (#4994) 2018-10-15 12:18:15 -07:00
Frank Benkstein
35f0b41fed fix missing newline in flatc help message (#4992) 2018-10-11 15:54:01 -07:00
Frank Benkstein
cb5422c398 fix #4974 (#4989) 2018-10-11 12:40:41 -07:00
Vladimir Glavnyy
4ed6fafdfa Refactoring of idl_parser (#4948)
* Refactoring of numbers parser

More accurate parse of float and double.
Hexadecimal floats.
Check "out-of-range" of uint64 fields.
Check correctness of default values and metadata.

* Remove locale-independent code strtod/strtof from PR #4948.

* small optimization

* Add is_(ascii) functions

* is_ascii cleanup

* Fix format conversation

* Refine number parser

* Make code compatible with Android build

* Remove unnecessary suppression of warning C4127
2018-10-11 10:37:47 -07:00
Frank Benkstein
53ce80ce91 better output on TestError (#4979)
Print a slightly better error message when a TestError fails.
2018-10-11 10:33:12 -07:00
Rikard Lundmark
233976c821 Add @javax.annotation.Generated to generated flatbuffer Java types (#4986)
* Add @javax.annotation.Generated to generated flatbuffer Java types.

* Updating test goldens.
2018-10-08 15:29:22 -07:00
Frank Benkstein
99fe1dc80f don't crash when calling EnumNameXXX on sparse enum (#4982)
Make an out-of-bounds check for enum values before using them to index the
names array.  For consistency with non-sparse enums an empty string is
returned.

Fixes #4821
2018-10-08 14:37:35 -07:00
Michael Edwards
a4f9d1bfcc Fix expected type of enum values in reflection tables (#4944)
Fixes #4930
2018-10-08 14:29:29 -07:00
kostya-sh
a4c362a1ba Use enum types in generated read/mutate methods for Go (#4978) 2018-10-08 14:25:37 -07:00
cor3ntin
7c3c027295 Add missing const on Reference::As<> (#4975)
Reference::As<> was needlessly mutable wich made them
less safe and harder to use
2018-10-08 12:52:01 -07:00
Stewart Miles
569492e890 Disable armeabi builds for Android and re-enable CI builds. (#4970)
armeabi support was removed from the Android NDK so we should no
longer build it.  Since this fixes the Android build failures this
commit also re-enables Travis Android builds.

While re-enabling Android builds, some recent changes broke C++98
support so this fixes those issues as well which include:
- Conditionally compiling use of move constructors, operators and
  std::move.
- Changing sample to use flatbuffers::unique_ptr rather than
  std::unique_ptr.

Finally, added the special "default_ptr_type" value for the
"cpp_ptr_type" attribute.  This expands to the value passed to
the "--cpp-ptr-type" argument of flatc.
2018-10-08 12:43:57 -07:00
Taj Morton
d840856093 In Javascript, generate bidirectional mappings for enums, between Name: Value and between Value: Name. (#4960) 2018-10-04 10:37:22 -07:00
Vladimir Glavnyy
925c1d77fc Fix recursion counter check. Add control to override depth of nested … (#4953)
* Fix recursion counter check. Add control to override depth of nested objects.

* Change if-condition to `>=`
2018-10-04 09:27:37 -07:00
257 changed files with 13213 additions and 3114 deletions

View File

@@ -0,0 +1,40 @@
:: Copyright 2018 Google Inc. All rights reserved.
::
:: Licensed under the Apache License, Version 2.0 (the "License");
:: you may not use this file except in compliance with the License.
:: You may obtain a copy of the License at
::
:: http://www.apache.org/licenses/LICENSE-2.0
::
:: Unless required by applicable law or agreed to in writing, software
:: distributed under the License is distributed on an "AS IS" BASIS,
:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
:: See the License for the specific language governing permissions and
:: limitations under the License.
set buildtype=Release
if "%1"=="-b" set buildtype=%2
cd tests
call generate_code.bat -b %buildtype% || goto FAIL
:: TODO: Release and Debug builds produce differences here for some reason.
git checkout HEAD -- monster_test.bfbs
git -c core.autocrlf=true diff --exit-code --quiet || goto :DIFFFOUND
goto SUCCESS
:DIFFFOUND
@echo "" >&2
@echo "ERROR: ********************************************************" >&2
@echo "ERROR: The following differences were found after running the" >&2
@echo "ERROR: tests/generate_code.sh script. Maybe you forgot to run" >&2
@echo "ERROR: it after making changes in a generator or schema?" >&2
@echo "ERROR: ********************************************************" >&2
@echo "" >&2
@git -c core.autocrlf=true --no-pager diff --binary
:FAIL
set EXITCODE=1
:SUCCESS
cd ..
EXIT /B %EXITCODE%

18
.bazelci/presubmit.yml Normal file
View File

@@ -0,0 +1,18 @@
---
buildifier: latest
platforms:
ubuntu1604:
build_targets:
- "..."
test_targets:
- "..."
ubuntu1804:
build_targets:
- "..."
test_targets:
- "..."
macos:
build_targets:
- "..."
test_targets:
- "..."

View File

@@ -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
View File

@@ -1 +1,2 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text=auto

7
.gitignore vendored
View File

@@ -26,6 +26,9 @@
**/install_manifest.txt
**/CMakeCache.txt
**/CMakeTestfile.cmake
**/CPackConfig.cmake
**/CPackSourceConfig.cmake
**/compile_commands.json
**/Debug/**
**/Release/**
**/RelWithDebInfo/**
@@ -46,6 +49,8 @@ flatsamplebinary
flatsamplebinary.exe
flatsampletext
flatsampletext.exe
flatsamplebfbs
flatsamplebfbs.exe
grpctest
grpctest.exe
snapshot.sh
@@ -109,3 +114,5 @@ dart/.dart_tool/
dart/build/
dart/doc/api/
Cargo.lock
.corpus**
.seed**

View File

@@ -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:
@@ -53,7 +59,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
@@ -72,10 +89,18 @@ 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 . -- -j${JOBS}
- LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/google/grpc/install/lib ctest --extra-verbose --output-on-failure
- bash .travis/check-generate-code.sh
- if [ "$CONAN" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo pip install conan && conan create . flatbuffers/${TRAVIS_BRANCH}@google/testing -s build_type=$BUILD_TYPE -tf conan/test_package; fi
- language: cpp
os: osx
@@ -84,30 +109,37 @@ 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
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_CLANG_VERSIONS=3.9 CONAN_DOCKER_IMAGE=conanio/clang39
- <<: *conan-linux
env: CONAN_CLANG_VERSIONS=4.0 CONAN_DOCKER_IMAGE=lasote/conanclang40
env: CONAN_CLANG_VERSIONS=4.0 CONAN_DOCKER_IMAGE=conanio/clang40
- <<: *conan-linux
env: CONAN_CLANG_VERSIONS=5.0 CONAN_DOCKER_IMAGE=lasote/conanclang50
env: CONAN_CLANG_VERSIONS=5.0 CONAN_DOCKER_IMAGE=conanio/clang50
- <<: *conan-linux
env: CONAN_CLANG_VERSIONS=6.0 CONAN_DOCKER_IMAGE=lasote/conanclang60
env: CONAN_CLANG_VERSIONS=6.0 CONAN_DOCKER_IMAGE=conanio/clang60
- <<: *conan-osx
osx_image: xcode7.3
env: CONAN_APPLE_CLANG_VERSIONS=7.3
@@ -118,29 +150,37 @@ 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
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
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 &
- 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))
# Kill the sleep loop
- kill %1

View File

@@ -0,0 +1,40 @@
#!/bin/bash
#
# Copyright 2018 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -e
# build flatc on debian once to speed up the test loop below
docker build -t build_flatc_debian_stretch -f tests/docker/Dockerfile.testing.build_flatc_debian_stretch .
BUILD_CONTAINER_ID=$(docker create --read-only build_flatc_debian_stretch)
docker cp ${BUILD_CONTAINER_ID}:/code/flatc flatc_debian_stretch
for f in $(ls tests/docker/languages | sort)
do
# docker pull sometimes fails for unknown reasons, probably travisci-related. this retries the pull we need a few times.
REQUIRED_BASE_IMAGE=$(cat tests/docker/languages/${f} | head -n 1 | awk ' { print $2 } ')
set +e
n=0
until [ $n -ge 5 ]
do
docker pull $REQUIRED_BASE_IMAGE && break
n=$[$n+1]
sleep 1
done
set -e
docker build -t $(echo ${f} | cut -f 3- -d .) -f tests/docker/languages/${f} .
echo "TEST OK: ${f}"
done

34
.travis/check-generate-code.sh Executable file
View File

@@ -0,0 +1,34 @@
#!/bin/bash
#
# Copyright 2018 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -e
cd tests
./generate_code.sh
cd ..
# TODO: Linux and macos builds produce differences here for some reason.
git checkout HEAD -- tests/monster_test.bfbs
if ! git diff --quiet; then
echo >&2
echo "ERROR: ********************************************************" >&2
echo "ERROR: The following differences were found after running the" >&2
echo "ERROR: tests/generate_code.sh script. Maybe you forgot to run" >&2
echo "ERROR: it after making changes in a generator or schema?" >&2
echo "ERROR: ********************************************************" >&2
echo >&2
git diff --binary --exit-code
fi

33
.travis/check-sources.sh Normal file
View 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$"

View 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)

48
BUILD
View File

@@ -12,6 +12,8 @@ exports_files([
"LICENSE",
])
load(":build_defs.bzl", "flatbuffer_cc_library")
# Public flatc library to compile flatbuffer files at runtime.
cc_library(
name = "flatbuffers",
@@ -86,10 +88,10 @@ cc_binary(
"src/idl_gen_general.cpp",
"src/idl_gen_go.cpp",
"src/idl_gen_grpc.cpp",
"src/idl_gen_js.cpp",
"src/idl_gen_js_ts.cpp",
"src/idl_gen_json_schema.cpp",
"src/idl_gen_lua.cpp",
"src/idl_gen_lobster.cpp",
"src/idl_gen_lua.cpp",
"src/idl_gen_php.cpp",
"src/idl_gen_python.cpp",
"src/idl_gen_rust.cpp",
@@ -104,6 +106,19 @@ cc_binary(
],
)
cc_library(
name = "runtime_cc",
hdrs = [
"include/flatbuffers/base.h",
"include/flatbuffers/flatbuffers.h",
"include/flatbuffers/flexbuffers.h",
"include/flatbuffers/stl_emulation.h",
"include/flatbuffers/util.h",
],
includes = ["include/"],
linkstatic = 1,
)
# Test binary.
cc_test(
name = "flatbuffers_test",
@@ -118,19 +133,19 @@ cc_test(
"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.cpp",
"tests/test_assert.h",
"tests/test_builder.cpp",
"tests/test_assert.cpp",
"tests/test_builder.h",
"tests/union_vector/union_vector_generated.h",
":public_headers",
],
copts = [
"-DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE",
"-DBAZEL_TEST_DATA_PATH",
],
data = [
":tests/include_test/include_test1.fbs",
@@ -142,7 +157,30 @@ cc_test(
":tests/prototest/test.golden",
":tests/prototest/test.proto",
":tests/prototest/test_union.golden",
":tests/unicode_test.json",
":tests/union_vector/union_vector.fbs",
":tests/union_vector/union_vector.json",
],
includes = ["include/"],
deps = [
":monster_extra_cc_fbs",
":monster_test_cc_fbs",
],
)
# Test bzl rules
flatbuffer_cc_library(
name = "monster_test_cc_fbs",
srcs = ["tests/monster_test.fbs"],
include_paths = ["tests/include_test"],
includes = [
"tests/include_test/include_test1.fbs",
"tests/include_test/sub/include_test2.fbs",
],
)
flatbuffer_cc_library(
name = "monster_extra_cc_fbs",
srcs = ["tests/monster_extra.fbs"],
)

4
CMake/DESCRIPTION.txt Normal file
View 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.

View File

@@ -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()

View File

@@ -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
View 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)

View File

@@ -1,4 +1,7 @@
cmake_minimum_required(VERSION 2.8)
# generate compile_commands.json
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include(CheckCXXSymbolExists)
project(FlatBuffers)
@@ -16,6 +19,16 @@ 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)
if(NOT FLATBUFFERS_BUILD_FLATC AND FLATBUFFERS_BUILD_TESTS)
message(WARNING
@@ -23,6 +36,22 @@ 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' function.
if(NOT DEFINED FLATBUFFERS_LOCALE_INDEPENDENT)
if(MSVC)
check_cxx_symbol_exists(_strtof_l stdlib.h FLATBUFFERS_LOCALE_INDEPENDENT)
else()
check_cxx_symbol_exists(strtof_l stdlib.h FLATBUFFERS_LOCALE_INDEPENDENT)
endif()
endif()
add_definitions(-DFLATBUFFERS_LOCALE_INDEPENDENT=$<BOOL:${FLATBUFFERS_LOCALE_INDEPENDENT}>)
set(FlatBuffers_Library_SRCS
include/flatbuffers/code_generators.h
include/flatbuffers/base.h
@@ -49,7 +78,7 @@ set(FlatBuffers_Compiler_SRCS
src/idl_gen_dart.cpp
src/idl_gen_general.cpp
src/idl_gen_go.cpp
src/idl_gen_js.cpp
src/idl_gen_js_ts.cpp
src/idl_gen_php.cpp
src/idl_gen_python.cpp
src/idl_gen_lobster.cpp
@@ -100,6 +129,14 @@ set(FlatBuffers_Sample_Text_SRCS
${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
)
set(FlatBuffers_Sample_BFBS_SRCS
${FlatBuffers_Library_SRCS}
src/idl_gen_general.cpp
samples/sample_bfbs.cpp
# file generated by running compiler on samples/monster.fbs
${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
)
set(FlatBuffers_GRPCTest_SRCS
include/flatbuffers/flatbuffers.h
include/flatbuffers/grpc.h
@@ -121,9 +158,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 +173,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 +191,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 +225,27 @@ if(FLATBUFFERS_CODE_COVERAGE)
"${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage")
endif()
function(add_fsanitize_to_target _target _sanitizer)
# FLATBUFFERS_CODE_SANITIZE: boolean {ON,OFF,YES,NO} or string with list of sanitizer.
# List of sanitizer is string starts with '=': "=address,undefined,thread,memory".
if((${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") OR
((${CMAKE_CXX_COMPILER_ID} MATCHES "GNU") AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.9"))
)
set(_sanitizer_flags "=address,undefined")
if(_sanitizer MATCHES "=.*")
# override default by user-defined sanitizer list
set(_sanitizer_flags ${_sanitizer})
endif()
target_compile_options(${_target} PRIVATE
-g -fsigned-char -fno-omit-frame-pointer
"-fsanitize${_sanitizer_flags}")
target_link_libraries(${_target} PRIVATE
"-fsanitize${_sanitizer_flags}")
set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ON)
message(STATUS "Sanitizer ${_sanitizer_flags} added to ${_target}")
endif()
endfunction()
if(BIICODE)
include(biicode/cmake/biicode.cmake)
return()
@@ -194,10 +259,15 @@ if(FLATBUFFERS_BUILD_FLATLIB)
# CMake > 2.8.11: Attach header directory for when build via add_subdirectory().
target_include_directories(flatbuffers INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
target_compile_options(flatbuffers PRIVATE "${FLATBUFFERS_PRIVATE_CXX_FLAGS}")
endif()
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()
@@ -219,7 +289,7 @@ 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}.11.0")
set_target_properties(flatbuffers_shared PROPERTIES OUTPUT_NAME flatbuffers
SOVERSION "${FlatBuffers_Library_SONAME_MAJOR}"
VERSION "${FlatBuffers_Library_SONAME_FULL}")
@@ -256,11 +326,20 @@ if(FLATBUFFERS_BUILD_TESTS)
set_property(TARGET flattests
PROPERTY COMPILE_DEFINITIONS FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
FLATBUFFERS_DEBUG_VERIFICATION_FAILURE=1)
if(FLATBUFFERS_CODE_SANITIZE)
if(WIN32)
target_compile_definitions(flattests PRIVATE FLATBUFFERS_MEMORY_LEAK_TRACKING)
message(STATUS "Sanitizer MSVC::_CrtDumpMemoryLeaks added to flattests")
else()
add_fsanitize_to_target(flattests ${FLATBUFFERS_CODE_SANITIZE})
endif()
endif()
compile_flatbuffers_schema_to_cpp(samples/monster.fbs)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/samples)
add_executable(flatsamplebinary ${FlatBuffers_Sample_Binary_SRCS})
add_executable(flatsampletext ${FlatBuffers_Sample_Text_SRCS})
add_executable(flatsamplebfbs ${FlatBuffers_Sample_BFBS_SRCS})
endif()
if(FLATBUFFERS_BUILD_GRPCTEST)
@@ -320,7 +399,6 @@ if(FLATBUFFERS_INSTALL)
install(
TARGETS flatc EXPORT FlatcTargets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
CONFIGURATIONS Release
)
install(
@@ -328,7 +406,6 @@ if(FLATBUFFERS_INSTALL)
FILE FlatcTargets.cmake
NAMESPACE flatbuffers::
DESTINATION ${FB_CMAKE_DIR}
CONFIGURATIONS Release
)
endif()
@@ -372,6 +449,13 @@ 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()

View File

@@ -1,2 +1,15 @@
workspace(name = "com_github_google_flatbuffers")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "io_bazel_rules_go",
sha256 = "492c3ac68ed9dcf527a07e6a1b2dcbf199c6bf8b35517951467ac32e421c06c1",
urls = ["https://github.com/bazelbuild/rules_go/releases/download/0.17.0/rules_go-0.17.0.tar.gz"],
)
load("@io_bazel_rules_go//go:deps.bzl", "go_register_toolchains", "go_rules_dependencies")
go_rules_dependencies()
go_register_toolchains()

View File

@@ -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"
}
}
}

View File

@@ -13,8 +13,13 @@ environment:
matrix:
- CMAKE_VS_VERSION: "10 2010"
MONSTER_EXTRA: "skip"
- CMAKE_VS_VERSION: "12 2013"
MONSTER_EXTRA: "skip"
- CMAKE_VS_VERSION: "14 2015"
MONSTER_EXTRA: ""
platform:
- x86
@@ -25,7 +30,8 @@ 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 .
# 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"
@@ -46,6 +52,7 @@ install:
- cargo -V
test_script:
- call .appveyor\check-generate-code.bat -b %CONFIGURATION%
- "cd tests"
- rem "Building all code"
- generate_code.bat -b %CONFIGURATION%
@@ -85,6 +92,9 @@ test_script:
- "cd FlatBuffers.Test"
- "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 ..\\.."

237
build_defs.bzl Normal file
View File

@@ -0,0 +1,237 @@
# Description:
# BUILD rules for generating flatbuffer files in various languages.
"""
Rules for building C++ flatbuffers with Bazel.
"""
flatc_path = "@com_github_google_flatbuffers//:flatc"
DEFAULT_INCLUDE_PATHS = [
"./",
"$(GENDIR)",
"$(BINDIR)",
]
DEFAULT_FLATC_ARGS = [
"--gen-object-api",
"--gen-compare",
"--no-includes",
"--gen-mutable",
"--reflect-names",
"--cpp-ptr-type flatbuffers::unique_ptr",
]
def flatbuffer_library_public(
name,
srcs,
outs,
language_flag,
out_prefix = "",
includes = [],
include_paths = DEFAULT_INCLUDE_PATHS,
flatc_args = DEFAULT_FLATC_ARGS,
reflection_name = "",
reflection_visiblity = None,
output_to_bindir = False):
"""Generates code files for reading/writing the given flatbuffers in the requested language using the public compiler.
Args:
name: Rule name.
srcs: Source .fbs files. Sent in order to the compiler.
outs: Output files from flatc.
language_flag: Target language flag. One of [-c, -j, -js].
out_prefix: Prepend this path to the front of all generated files except on
single source targets. Usually is a directory name.
includes: Optional, list of filegroups of schemas that the srcs depend on.
include_paths: Optional, list of paths the includes files can be found in.
flatc_args: Optional, list of additional arguments to pass to flatc.
reflection_name: Optional, if set this will generate the flatbuffer
reflection binaries for the schemas.
reflection_visiblity: The visibility of the generated reflection Fileset.
output_to_bindir: Passed to genrule for output to bin directory.
This rule creates a filegroup(name) with all generated source files, and
optionally a Fileset([reflection_name]) with all generated reflection
binaries.
"""
include_paths_cmd = ["-I %s" % (s) for s in include_paths]
# '$(@D)' when given a single source target will give the appropriate
# directory. Appending 'out_prefix' is only necessary when given a build
# target with multiple sources.
output_directory = (
("-o $(@D)/%s" % (out_prefix)) if len(srcs) > 1 else ("-o $(@D)")
)
genrule_cmd = " ".join([
"SRCS=($(SRCS));",
"for f in $${SRCS[@]:0:%s}; do" % len(srcs),
"$(location %s)" % (flatc_path),
" ".join(include_paths_cmd),
" ".join(flatc_args),
language_flag,
output_directory,
"$$f;",
"done",
])
native.genrule(
name = name,
srcs = srcs + includes,
outs = outs,
output_to_bindir = output_to_bindir,
tools = [flatc_path],
cmd = genrule_cmd,
message = "Generating flatbuffer files for %s:" % (name),
)
if reflection_name:
reflection_genrule_cmd = " ".join([
"SRCS=($(SRCS));",
"for f in $${SRCS[@]:0:%s}; do" % len(srcs),
"$(location %s)" % (flatc_path),
"-b --schema",
" ".join(flatc_args),
" ".join(include_paths_cmd),
language_flag,
output_directory,
"$$f;",
"done",
])
reflection_outs = [
(out_prefix + "%s.bfbs") % (s.replace(".fbs", "").split("/")[-1])
for s in srcs
]
native.genrule(
name = "%s_srcs" % reflection_name,
srcs = srcs + includes,
outs = reflection_outs,
output_to_bindir = output_to_bindir,
tools = [flatc_path],
cmd = reflection_genrule_cmd,
message = "Generating flatbuffer reflection binary for %s:" % (name),
)
native.Fileset(
name = reflection_name,
out = "%s_out" % reflection_name,
entries = [
native.FilesetEntry(files = reflection_outs),
],
visibility = reflection_visiblity,
)
def flatbuffer_cc_library(
name,
srcs,
srcs_filegroup_name = "",
out_prefix = "",
includes = [],
include_paths = DEFAULT_INCLUDE_PATHS,
flatc_args = DEFAULT_FLATC_ARGS,
visibility = None,
srcs_filegroup_visibility = None,
gen_reflections = False):
'''A cc_library with the generated reader/writers for the given flatbuffer definitions.
Args:
name: Rule name.
srcs: Source .fbs files. Sent in order to the compiler.
srcs_filegroup_name: Name of the output filegroup that holds srcs. Pass this
filegroup into the `includes` parameter of any other
flatbuffer_cc_library that depends on this one's schemas.
out_prefix: Prepend this path to the front of all generated files. Usually
is a directory name.
includes: Optional, list of filegroups of schemas that the srcs depend on.
** SEE REMARKS BELOW **
include_paths: Optional, list of paths the includes files can be found in.
flatc_args: Optional list of additional arguments to pass to flatc
(e.g. --gen-mutable).
visibility: The visibility of the generated cc_library. By default, use the
default visibility of the project.
srcs_filegroup_visibility: The visibility of the generated srcs filegroup.
By default, use the value of the visibility parameter above.
gen_reflections: Optional, if true this will generate the flatbuffer
reflection binaries for the schemas.
This produces:
filegroup([name]_srcs): all generated .h files.
filegroup(srcs_filegroup_name if specified, or [name]_includes if not):
Other flatbuffer_cc_library's can pass this in for their `includes`
parameter, if they depend on the schemas in this library.
Fileset([name]_reflection): (Optional) all generated reflection binaries.
cc_library([name]): library with sources and flatbuffers deps.
Remarks:
** Because the genrule used to call flatc does not have any trivial way of
computing the output list of files transitively generated by includes and
--gen-includes (the default) being defined for flatc, the --gen-includes
flag will not work as expected. The way around this is to add a dependency
to the flatbuffer_cc_library defined alongside the flatc included Fileset.
For example you might define:
flatbuffer_cc_library(
name = "my_fbs",
srcs = [ "schemas/foo.fbs" ],
includes = [ "//third_party/bazz:bazz_fbs_includes" ],
)
In which foo.fbs includes a few files from the Fileset defined at
//third_party/bazz:bazz_fbs_includes. When compiling the library that
includes foo_generated.h, and therefore has my_fbs as a dependency, it
will fail to find any of the bazz *_generated.h files unless you also
add bazz's flatbuffer_cc_library to your own dependency list, e.g.:
cc_library(
name = "my_lib",
deps = [
":my_fbs",
"//third_party/bazz:bazz_fbs"
],
)
Happy dependent Flatbuffering!
'''
output_headers = [
(out_prefix + "%s_generated.h") % (s.replace(".fbs", "").split("/")[-1])
for s in srcs
]
reflection_name = "%s_reflection" % name if gen_reflections else ""
srcs_lib = "%s_srcs" % (name)
flatbuffer_library_public(
name = srcs_lib,
srcs = srcs,
outs = output_headers,
language_flag = "-c",
out_prefix = out_prefix,
includes = includes,
include_paths = include_paths,
flatc_args = flatc_args,
reflection_name = reflection_name,
reflection_visiblity = visibility,
)
native.cc_library(
name = name,
hdrs = [
":" + srcs_lib,
],
srcs = [
":" + srcs_lib,
],
features = [
"-parse_headers",
],
deps = [
"@com_github_google_flatbuffers//:runtime_cc",
],
includes = [],
linkstatic = 1,
visibility = visibility,
)
# A filegroup for the `srcs`. That is, all the schema files for this
# Flatbuffer set.
native.filegroup(
name = srcs_filegroup_name if srcs_filegroup_name else "%s_includes" % (name),
srcs = srcs,
visibility = srcs_filegroup_visibility if srcs_filegroup_visibility != None else visibility,
)

View File

@@ -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,

View File

@@ -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:

View File

@@ -1,5 +1,5 @@
name: flat_buffers
version: 1.10.0
version: 1.11.0
description: >
FlatBuffers reading and writing library for Dart. Use the flatc compiler to
generate Dart classes for a FlatBuffers schema, and this library to assist with

View File

@@ -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);

View File

@@ -8,8 +8,8 @@ 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;
class Color {
final int value;
@@ -90,6 +90,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 T = const AnyUniqueAliasesTypeId._(2);
static const AnyUniqueAliasesTypeId M2 = const AnyUniqueAliasesTypeId._(3);
static get values => {0: NONE,1: M,2: T,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);
@@ -654,10 +736,29 @@ 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 T.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);
@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}';
}
}
@@ -848,6 +949,26 @@ 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 finish() {
return fbBuilder.endTable();
@@ -897,6 +1018,11 @@ 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;
MonsterObjectBuilder({
Vec3ObjectBuilder pos,
@@ -941,6 +1067,11 @@ class MonsterObjectBuilder extends fb.ObjectBuilder {
List<int> vectorOfCoOwningReferences,
int nonOwningReference,
List<int> vectorOfNonOwningReferences,
AnyUniqueAliasesTypeId anyUniqueType,
dynamic anyUnique,
AnyAmbiguousAliasesTypeId anyAmbiguousType,
dynamic anyAmbiguous,
List<Color> vectorOfEnums,
})
: _pos = pos,
_mana = mana,
@@ -983,7 +1114,12 @@ 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;
/// Finish building, and store into the [fbBuilder].
@override
@@ -1046,6 +1182,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.writeListInt8(_vectorOfEnums.map((f) => f.value))
: null;
fbBuilder.startTable();
if (_pos != null) {
@@ -1136,6 +1277,17 @@ 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);
}
return fbBuilder.endTable();
}

View File

@@ -80,6 +80,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.

View File

@@ -72,6 +72,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.
@@ -91,21 +97,42 @@ Additional options:
- `--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-ptr-type T` : Set object API pointer type (default std::unique_ptr)
- `--cpp-str-type T` : Set object API string type (default std::string)
T::c_str(), T::length() and T::empty() must be supported.
The custom type also needs to be constructible from std::string (see the
--cpp-str-flex-ctor option to change this behavior).
- `--cpp-str-flex-ctor` : Don't construct custom string types by passing
std::string from Flatbuffers, but (char* + length). This allows efficient
construction of custom string types, including zero-copy construction.
- `--object-prefix` : Customise class prefix for C++ object-based API.
- `--object-suffix` : Customise class suffix for C++ object-based API.
- `--no-js-exports` : Removes Node.js style export lines (useful for JS)
- `--goog-js-export` : Uses goog.exportsSymbol and goog.exportsProperty
instead of Node.js style exporting. Needed for compatibility with the
@@ -115,9 +142,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 +159,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 +174,22 @@ 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`.
- `--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.

View File

@@ -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
@@ -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)
@@ -495,4 +518,49 @@ 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:
- `_MSC_VER >= 1900`: check MSVC2012 or higher for MSVC buid
- `_XOPEN_SOURCE>=700`: check POSIX-2008 for GCC/Clang build
- `check_cxx_symbol_exists(strtof_l stdlib.h)`: CMake check of `strtod_f`
After detection, the definition `FLATBUFFERS_LOCALE_INDEPENDENT` will be
set to `0` or `1`.
It is possible to test the compatibility of the Flatbuffers library with
a specific locale using the environment variable `FLATBUFFERS_TEST_LOCALE`:
```sh
>FLATBUFFERS_TEST_LOCALE="" ./flattests
>FLATBUFFERS_TEST_LOCALE="ru_RU.CP1251" ./flattests
```
<br>

View File

@@ -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).

View File

@@ -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`)

View File

@@ -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>

View File

@@ -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`
@@ -141,6 +141,9 @@ is `0`. As you can see in the enum declaration, you specify the underlying
integral type of the enum with `:` (in this case `byte`), which then determines
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 +153,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 +321,11 @@ 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`.
- `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 +405,31 @@ When parsing JSON, it recognizes the following escape codes in strings:
It also generates these escape codes back again when generating JSON from a
binary representation.
When parsing numbers, the parser is more flexible than JSON.
A format of numeric literals is more close to the C/C++.
According to the [grammar](@ref flatbuffers_grammar), it accepts the following
numerical literals:
- An integer literal can have any number of leading zero `0` digits.
Unlike C/C++, the parser ignores a leading zero, not interpreting it as the
beginning of the octal number.
The numbers `[081, -00094]` are equal to `[81, -94]` decimal integers.
- The parser accepts unsigned and signed hexadecimal integer numbers.
For example: `[0x123, +0x45, -0x67]` are equal to `[291, 69, -103]` decimals.
- The format of float-point numbers is fully compatible with C/C++ format.
If a modern C++ compiler is used the parser accepts hexadecimal and special
float-point literals as well:
`[-1.0, 2., .3e0, 3.e4, 0x21.34p-5, -inf, nan]`.
The exponent suffix of hexadecimal float-point number is mandatory.
Extended float-point support was tested with:
- x64 Windows: `MSVC2015` and higher.
- x64 Linux: `LLVM 6.0`, `GCC 4.9` and higher.
- For compatibility with a JSON lint tool all numeric literals of scalar
fields can be wrapped to quoted string:
`"1", "2.0", "0x48A", "0x0C.0Ep-1", "-inf", "true"`.
## Guidelines
### Efficiency

View File

@@ -274,43 +274,43 @@ Please be aware of the difference between `flatc` and `flatcc` tools.
<div class="language-cpp">
~~~{.sh}
cd flatbuffers/sample
cd flatbuffers/samples
./../flatc --cpp monster.fbs
~~~
</div>
<div class="language-java">
~~~{.sh}
cd flatbuffers/sample
cd flatbuffers/samples
./../flatc --java monster.fbs
~~~
</div>
<div class="language-csharp">
~~~{.sh}
cd flatbuffers/sample
cd flatbuffers/samples
./../flatc --csharp monster.fbs
~~~
</div>
<div class="language-go">
~~~{.sh}
cd flatbuffers/sample
cd flatbuffers/samples
./../flatc --go monster.fbs
~~~
</div>
<div class="language-python">
~~~{.sh}
cd flatbuffers/sample
cd flatbuffers/samples
./../flatc --python monster.fbs
~~~
</div>
<div class="language-javascript">
~~~{.sh}
cd flatbuffers/sample
cd flatbuffers/samples
./../flatc --js monster.fbs
~~~
</div>
<div class="language-typescript">
~~~{.sh}
cd flatbuffers/sample
cd flatbuffers/samples
./../flatc --ts monster.fbs
~~~
</div>
@@ -331,25 +331,25 @@ Please be aware of the difference between `flatc` and `flatcc` tools.
</div>
<div class="language-dart">
~~~{.sh}
cd flatbuffers/sample
cd flatbuffers/samples
./../flatc --dart monster.fbs
~~~
</div>
<div class="language-lua">
~~~{.sh}
cd flatbuffers/sample
cd flatbuffers/samples
./../flatc --lua monster.fbs
~~~
</div>
<div class="language-lobster">
~~~{.sh}
cd flatbuffers/sample
cd flatbuffers/samples
./../flatc --lobster monster.fbs
~~~
</div>
<div class="language-rust">
~~~{.sh}
cd flatbuffers/sample
cd flatbuffers/samples
./../flatc --rust monster.fbs
~~~
</div>
@@ -370,7 +370,7 @@ The first step is to import/include the library, generated files, etc.
<div class="language-cpp">
~~~{.cpp}
#include "monster_generate.h" // This was generated by `flatc`.
#include "monster_generated.h" // This was generated by `flatc`.
using namespace MyGame::Sample; // Specified in the schema.
~~~
@@ -495,6 +495,7 @@ The first step is to import/include the library, generated files, etc.
extern crate flatbuffers;
// import the generated code
#[allow(dead_code, unused_imports)]
#[path = "./monster_generated.rs"]
mod monster_generated;
pub use monster_generated::my_game::sample::{get_root_as_monster,
@@ -652,14 +653,14 @@ our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
// Create the first `Weapon` ("Sword").
sample.WeaponStart(builder)
sample.Weapon.AddName(builder, weaponOne)
sample.Weapon.AddDamage(builder, 3)
sample.WeaponAddName(builder, weaponOne)
sample.WeaponAddDamage(builder, 3)
sword := sample.WeaponEnd(builder)
// Create the second `Weapon` ("Axe").
sample.WeaponStart(builder)
sample.Weapon.AddName(builder, weaponTwo)
sample.Weapon.AddDamage(builder, 5)
sample.WeaponAddName(builder, weaponTwo)
sample.WeaponAddDamage(builder, 5)
axe := sample.WeaponEnd(builder)
~~~
</div>
@@ -734,10 +735,10 @@ our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
</div>
<div class="language-c">
~~~{.c}
ns(Weapon_ref_t) weapon_one_name = flatbuffers_string_create_str(B, "Sword");
flatbuffers_string_ref_t weapon_one_name = flatbuffers_string_create_str(B, "Sword");
uint16_t weapon_one_damage = 3;
ns(Weapon_ref_t) weapon_two_name = flatbuffers_string_create_str(B, "Axe");
flatbuffers_string_ref_t weapon_two_name = flatbuffers_string_create_str(B, "Axe");
uint16_t weapon_two_damage = 5;
ns(Weapon_ref_t) sword = ns(Weapon_create(B, weapon_one_name, weapon_one_damage));
@@ -767,7 +768,7 @@ our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
// The genearted ObjectBuilder classes offer an easier to use alternative
// The generated ObjectBuilder classes offer an easier to use alternative
// at the cost of requiring some additional reference allocations. If memory
// usage is critical, or if you'll be working with especially large messages
// or tables, you should prefer using the generated Builder classes.
@@ -1238,7 +1239,7 @@ for the `path` field above:
final vec3Builder = new myGame.Vec3Builder(builder);
vec3Builder.finish(4.0, 5.0, 6.0);
vec3Builder.finish(1.0, 2.0, 3.0);
final int path = builder.endStructVector(2); // the lenght of the vector
final int path = builder.endStructVector(2); // the length of the vector
// Otherwise, using the ObjectBuilder classes:
// The dart implementation provides a simple interface for writing vectors
@@ -1520,7 +1521,7 @@ can serialize the monster itself:
// Create the monster using the `Monster::create` helper function. This
// function accepts a `MonsterArgs` struct, which supplies all of the data
// needed to build a `Monster`. To supply empty/default fields, just use the
// Rust built-in `Default::default()` function, as demononstrated below.
// Rust built-in `Default::default()` function, as demonstrated below.
let orc = Monster::create(&mut builder, &MonsterArgs{
pos: Some(&Vec3::new(1.0f32, 2.0f32, 3.0f32)),
mana: 150,
@@ -1663,7 +1664,7 @@ Here is a repetition these lines, to help highlight them more clearly:
</div>
<div class="language-c">
~~~{.c}
// Add union type and data simultanously.
// Add union type and data simultaneously.
ns(Monster_equipped_Weapon_add(B, axe));
~~~
</div>
@@ -1906,7 +1907,7 @@ like so:
Now you can write the bytes to a file, send them over the network..
**Make sure your file mode (or tranfer protocol) is set to BINARY, not text.**
**Make sure your file mode (or transfer protocol) is set to BINARY, not text.**
If you transfer a FlatBuffer in text mode, the buffer will be corrupted,
which will lead to hard to find problems when you read the buffer.
@@ -1921,7 +1922,7 @@ before:
<div class="language-cpp">
~~~{.cpp}
#include "monster_generate.h" // This was generated by `flatc`.
#include "monster_generated.h" // This was generated by `flatc`.
using namespace MyGame::Sample; // Specified in the schema.
~~~
@@ -2042,6 +2043,7 @@ import './monster_my_game.sample_generated.dart' as myGame;
extern crate flatbuffers;
// import the generated code
#[allow(dead_code, unused_imports)]
#[path = "./monster_generated.rs"]
mod monster_generated;
pub use monster_generated::my_game::sample::{get_root_as_monster,
@@ -2207,7 +2209,7 @@ accessors for all non-`deprecated` fields. For example:
<div class="language-csharp">
~~~{.cs}
// For C#, unlike most other languages support by FlatBuffers, most values (except for
// vectors and unions) are available as propreties instead of asccessor methods.
// vectors and unions) are available as properties instead of accessor methods.
var hp = monster.Hp
var mana = monster.Mana
var name = monster.Name
@@ -2258,7 +2260,7 @@ accessors for all non-`deprecated` fields. For example:
<div class="language-dart">
~~~{.dart}
// For Dart, unlike other languages support by FlatBuffers, most values
// are available as propreties instead of asccessor methods.
// are available as properties instead of accessor methods.
var hp = monster.hp;
var mana = monster.mana;
var name = monster.name;

View File

@@ -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

View File

@@ -45,6 +45,8 @@
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"/>
<tab type="usergroup" url="" title="gRPC">

View File

@@ -6,7 +6,7 @@
<parent>
<groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-parent</artifactId>
<version>1.10.0</version>
<version>1.11.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.11.0</gRPC.version>
</properties>
<dependencies>
<dependency>

View File

@@ -4,7 +4,7 @@
<groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-parent</artifactId>
<packaging>pom</packaging>
<version>1.10.0</version>
<version>1.11.0</version>
<name>flatbuffers-parent</name>
<description>parent pom for flatbuffers java artifacts</description>
<properties>

View File

@@ -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");

View File

@@ -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";

View 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;
}
}

View File

@@ -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.Test
public void testMonster() throws IOException {
int port = startServer();
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", port)
@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(true)
.directExecutor()
.build();
blockingStub = MonsterStorageGrpc.newBlockingStub(channel);
asyncStub = MonsterStorageGrpc.newStub(channel);
}
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);
@org.junit.Test
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);
}
}

View File

@@ -3,10 +3,10 @@ package testing
import (
"../../tests/MyGame/Example"
"context"
"net"
"testing"
"golang.org/x/net/context"
"google.golang.org/grpc"
)

View File

@@ -23,6 +23,9 @@
#include "test_assert.h"
using namespace MyGame::Example;
using flatbuffers::grpc::MessageBuilder;
using flatbuffers::FlatBufferBuilder;
void message_builder_tests();
// The callback implementation of our server, that derives from the generated
@@ -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,45 @@ 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 +149,12 @@ 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);
RetrieveRPC<MessageBuilder>(stub.get());
RetrieveRPC<FlatBufferBuilder>(stub.get());
if (status.ok()) {
auto resp = response.GetRoot()->id();
std::cout << "RPC response: " << resp->str() << std::endl;
} else {
std::cout << "RPC failed" << std::endl;
}
}
{
grpc::ClientContext context;
fbb.Clear();
auto stat_offset = CreateStat(fbb, fbb.CreateString("Fred"));
fbb.Finish(stat_offset);
auto request = fbb.ReleaseMessage<Stat>();
flatbuffers::grpc::Message<Monster> response;
auto stream = stub->Retrieve(&context, request);
while (stream->Read(&response)) {
auto resp = response.GetRoot()->name();
std::cout << "RPC Streaming response: " << resp->str() << std::endl;
}
}
#if !FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
{

View File

@@ -3,6 +3,10 @@
#include "test_assert.h"
#include "test_builder.h"
using MyGame::Example::Vec3;
using MyGame::Example::CreateStat;
using MyGame::Example::Any_NONE;
bool verify(flatbuffers::grpc::Message<Monster> &msg, const std::string &expected_name, Color color) {
const Monster *monster = msg.GetRoot();
return (monster->name()->str() == expected_name) && (monster->color() == color);
@@ -14,19 +18,37 @@ bool release_n_verify(flatbuffers::grpc::MessageBuilder &mbb, const std::string
return (monster->name()->str() == expected_name) && (monster->color() == color);
}
template <>
struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder> {
void builder_move_assign_after_releaseraw_test(flatbuffers::grpc::MessageBuilder dst) {
auto root_offset1 = populate1(dst);
dst.Finish(root_offset1);
size_t size, offset;
grpc_slice slice;
dst.ReleaseRaw(size, offset, slice);
flatbuffers::FlatBufferBuilder src;
auto root_offset2 = populate2(src);
src.Finish(root_offset2);
auto src_size = src.GetSize();
// Move into a released builder.
dst = std::move(src);
TEST_EQ(dst.GetSize(), src_size);
TEST_ASSERT(release_n_verify(dst, m2_name, m2_color));
TEST_EQ(src.GetSize(), 0);
grpc_slice_unref(slice);
}
template <class SrcBuilder>
struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder, SrcBuilder> {
static void builder_reusable_after_release_message_test(TestSelector selector) {
if (!selector.count(REUSABLE_AFTER_RELEASE_MESSAGE)) {
return;
}
flatbuffers::grpc::MessageBuilder b1;
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>());
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));
}
}
@@ -36,14 +58,15 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder> {
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());
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));
}
}
@@ -53,13 +76,13 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder> {
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);
const uint8_t *buf = mb.ReleaseRaw(size, offset, slice);
TEST_ASSERT_FUNC(verify(buf, offset, m1_name, m1_color));
grpc_slice_unref(slice);
}
@@ -70,22 +93,23 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder> {
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());
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);
}
}
@@ -94,20 +118,20 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder> {
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>());
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);
}
}
@@ -116,20 +140,20 @@ struct BuilderReuseTests<flatbuffers::grpc::MessageBuilder> {
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);
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);
}
}
@@ -153,7 +177,7 @@ void slice_allocator_tests() {
buf[0] = 100;
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);
// buf is freed here
@@ -170,13 +194,140 @@ 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 = 4 ; initial_size <= 2048; initial_size *= 2) {
flatbuffers::FlatBufferBuilder fbb(initial_size);
auto stat_offset = CreateStat(fbb, fbb.CreateString("SomeId"), 0, 0);
flatbuffers::grpc::MessageBuilder mb(std::move(fbb));
auto monster_offset = CreateMonster(mb, 0, 150, 100, mb.CreateString(m1_name), 0, m1_color, Any_NONE, 0, 0, 0, 0, 0, 0, stat_offset);
mb.Finish(monster_offset);
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color));
TEST_EQ_FUNC(fbb.GetSize(), 0);
}
}
/// This test validates correctness of move conversion of FlatBufferBuilder to a MessageBuilder DURING
/// a table construction. Half of the table is constructed using FlatBufferBuilder and the other half
/// of the table is constructed using a MessageBuilder.
void builder_move_assign_conversion_before_finish_half_n_half_table_test() {
flatbuffers::FlatBufferBuilder fbb;
flatbuffers::grpc::MessageBuilder mb;
for (int i = 0;i < 5; ++i) {
flatbuffers::FlatBufferBuilder fbb;
auto name_offset = fbb.CreateString(m1_name);
MyGame::Example::MonsterBuilder monsterBuilder(fbb); // starts a table in FlatBufferBuilder
populate_first_half(monsterBuilder, name_offset);
mb = std::move(fbb);
test_only_hack_update_fbb_reference(monsterBuilder, mb); // hack
populate_second_half(monsterBuilder);
mb.Finish(monsterBuilder.Finish()); // ends the table in MessageBuilder
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color));
TEST_EQ_FUNC(fbb.GetSize(), 0);
}
}
/// This test populates a COMPLETE inner table before move conversion and later populates more members in the outer table.
void builder_move_assign_conversion_before_finish_test() {
flatbuffers::FlatBufferBuilder fbb;
flatbuffers::grpc::MessageBuilder mb;
for (int i = 0;i < 5; ++i) {
auto stat_offset = CreateStat(fbb, fbb.CreateString("SomeId"), 0, 0);
mb = std::move(fbb);
auto monster_offset = CreateMonster(mb, 0, 150, 100, mb.CreateString(m1_name), 0, m1_color, Any_NONE, 0, 0, 0, 0, 0, 0, stat_offset);
mb.Finish(monster_offset);
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color));
TEST_EQ_FUNC(fbb.GetSize(), 0);
}
}
/// This test populates data, finishes the buffer, and does move conversion after.
void builder_move_ctor_conversion_after_finish_test() {
flatbuffers::FlatBufferBuilder fbb;
fbb.Finish(populate1(fbb));
flatbuffers::grpc::MessageBuilder mb(std::move(fbb));
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color));
TEST_EQ_FUNC(fbb.GetSize(), 0);
}
/// This test populates data, finishes the buffer, and does move conversion after.
void builder_move_assign_conversion_after_finish_test() {
flatbuffers::FlatBufferBuilder fbb;
flatbuffers::grpc::MessageBuilder mb;
for (int i = 0;i < 5; ++i) {
fbb.Finish(populate1(fbb));
mb = std::move(fbb);
TEST_ASSERT_FUNC(release_n_verify(mb, m1_name, m1_color));
TEST_EQ_FUNC(fbb.GetSize(), 0);
}
}
void message_builder_tests() {
using flatbuffers::grpc::MessageBuilder;
using flatbuffers::FlatBufferBuilder;
slice_allocator_tests();
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,
@@ -184,5 +335,6 @@ void message_builder_tests() {
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));
}

View File

@@ -4,13 +4,13 @@
<parent>
<groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-parent</artifactId>
<version>1.10.0</version>
<version>1.11.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.11.0</gRPC.version>
</properties>
<dependencies>
<dependency>

View File

@@ -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
@@ -57,6 +61,27 @@
// 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) && \
@@ -93,7 +118,8 @@
#endif // __s390x__
#if !defined(FLATBUFFERS_LITTLEENDIAN)
#if defined(__GNUC__) || defined(__clang__)
#ifdef __BIG_ENDIAN__
#if (defined(__BIG_ENDIAN__) || \
(defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
#define FLATBUFFERS_LITTLEENDIAN 0
#else
#define FLATBUFFERS_LITTLEENDIAN 1
@@ -110,7 +136,7 @@
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
#define FLATBUFFERS_VERSION_MAJOR 1
#define FLATBUFFERS_VERSION_MINOR 10
#define FLATBUFFERS_VERSION_MINOR 11
#define FLATBUFFERS_VERSION_REVISION 0
#define FLATBUFFERS_STRING_EXPAND(X) #X
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
@@ -120,9 +146,11 @@
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 +158,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) || \
@@ -180,6 +208,65 @@
#endif // __has_include
#endif // !FLATBUFFERS_HAS_STRING_VIEW
#ifndef FLATBUFFERS_HAS_NEW_STRTOD
// Modern (C++11) strtod and strtof functions are available for use.
// 1) nan/inf strings as argument of strtod;
// 2) hex-float as argument of strtod/strtof.
#if (defined(_MSC_VER) && _MSC_VER >= 1900) || \
(defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \
(defined(__clang__))
#define FLATBUFFERS_HAS_NEW_STRTOD 1
#endif
#endif // !FLATBUFFERS_HAS_NEW_STRTOD
#ifndef FLATBUFFERS_LOCALE_INDEPENDENT
// Enable locale independent functions {strtof_l, strtod_l,strtoll_l, strtoull_l}.
// They are part of the POSIX-2008 but not part of the C/C++ standard.
// GCC/Clang have definition (_XOPEN_SOURCE>=700) if POSIX-2008.
#if ((defined(_MSC_VER) && _MSC_VER >= 1800) || \
(defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE>=700)))
#define FLATBUFFERS_LOCALE_INDEPENDENT 1
#else
#define FLATBUFFERS_LOCALE_INDEPENDENT 0
#endif
#endif // !FLATBUFFERS_LOCALE_INDEPENDENT
// Suppress Undefined Behavior Sanitizer (recoverable only). Usage:
// - __supress_ubsan__("undefined")
// - __supress_ubsan__("signed-integer-overflow")
#if defined(__clang__)
#define __supress_ubsan__(type) __attribute__((no_sanitize(type)))
#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
#define __supress_ubsan__(type) __attribute__((no_sanitize_undefined))
#else
#define __supress_ubsan__(type)
#endif
// This is constexpr function used for checking compile-time constants.
// Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`.
template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) {
return !!t;
}
// Enable C++ attribute [[]] if std:c++17 or higher.
#if ((__cplusplus >= 201703L) \
|| (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L)))
// All attributes unknown to an implementation are ignored without causing an error.
#define FLATBUFFERS_ATTRIBUTE(attr) [[attr]]
#define FLATBUFFERS_FALLTHROUGH() [[fallthrough]]
#else
#define FLATBUFFERS_ATTRIBUTE(attr)
#if FLATBUFFERS_CLANG >= 30800
#define FLATBUFFERS_FALLTHROUGH() [[clang::fallthrough]]
#elif FLATBUFFERS_GCC >= 70300
#define FLATBUFFERS_FALLTHROUGH() [[gnu::fallthrough]]
#else
#define FLATBUFFERS_FALLTHROUGH()
#endif
#endif
/// @endcond
/// @file
@@ -262,14 +349,25 @@ 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).

View File

@@ -130,6 +130,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_

View File

@@ -19,7 +19,25 @@
#include "flatbuffers/base.h"
#if defined(FLATBUFFERS_NAN_DEFAULTS)
#include <cmath>
#endif
namespace flatbuffers {
// Generic 'operator==' with conditional specialisations.
template<typename T> inline bool IsTheSameAs(T e, T def) { return e == def; }
#if defined(FLATBUFFERS_NAN_DEFAULTS) && \
(!defined(_MSC_VER) || _MSC_VER >= 1800)
// Like `operator==(e, def)` with weak NaN if T=(float|double).
template<> inline bool IsTheSameAs<float>(float e, float def) {
return (e == def) || (std::isnan(def) && std::isnan(e));
}
template<> inline bool IsTheSameAs<double>(double e, double def) {
return (e == def) || (std::isnan(def) && std::isnan(e));
}
#endif
// Wrapper for uoffset_t to allow safe template specialization.
// Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
template<typename T> struct Offset {
@@ -98,16 +116,21 @@ template<typename T, typename IT> struct VectorIterator {
VectorIterator(const uint8_t *data, uoffset_t i)
: data_(data + IndirectHelper<T>::element_stride * i) {}
VectorIterator(const VectorIterator &other) : data_(other.data_) {}
VectorIterator() : data_(nullptr) {}
VectorIterator &operator=(const VectorIterator &other) {
data_ = other.data_;
return *this;
}
// clang-format off
#if !defined(FLATBUFFERS_CPP98_STL)
VectorIterator &operator=(VectorIterator &&other) {
data_ = other.data_;
return *this;
}
#endif // !defined(FLATBUFFERS_CPP98_STL)
// clang-format on
bool operator==(const VectorIterator &other) const {
return data_ == other.data_;
@@ -161,7 +184,7 @@ template<typename T, typename IT> struct VectorIterator {
return temp;
}
VectorIterator operator-(const uoffset_t &offset) {
VectorIterator operator-(const uoffset_t &offset) const {
return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride,
0);
}
@@ -175,6 +198,19 @@ template<typename T, typename IT> struct VectorIterator {
const uint8_t *data_;
};
template<typename Iterator> struct VectorReverseIterator :
public std::reverse_iterator<Iterator> {
explicit VectorReverseIterator(Iterator iter) : iter_(iter) {}
typename Iterator::value_type operator*() const { return *(iter_ - 1); }
typename Iterator::value_type operator->() const { return *(iter_ - 1); }
private:
Iterator iter_;
};
struct String;
// This is used as a helper type for accessing vectors.
@@ -185,10 +221,13 @@ template<typename T> class Vector {
iterator;
typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
const_iterator;
typedef VectorReverseIterator<iterator> reverse_iterator;
typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
uoffset_t size() const { return EndianScalar(length_); }
// Deprecated: use size(). Here for backwards compatibility.
FLATBUFFERS_ATTRIBUTE(deprecated("use size() instead"))
uoffset_t Length() const { return size(); }
typedef typename IndirectHelper<T>::return_type return_type;
@@ -230,6 +269,20 @@ template<typename T> class Vector {
iterator end() { return iterator(Data(), size()); }
const_iterator end() const { return const_iterator(Data(), size()); }
reverse_iterator rbegin() { return reverse_iterator(end()); }
const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
reverse_iterator rend() { return reverse_iterator(end()); }
const_reverse_iterator rend() const { return const_reverse_iterator(end()); }
const_iterator cbegin() const { return begin(); }
const_iterator cend() const { return end(); }
const_reverse_iterator crbegin() const { return rbegin(); }
const_reverse_iterator crend() const { return rend(); }
// Change elements if you have a non-const pointer to this object.
// Scalars only. See reflection.h, and the documentation.
void Mutate(uoffset_t i, const T &val) {
@@ -337,23 +390,31 @@ const Vector<Offset<T>> *VectorCast(const Vector<Offset<U>> *ptr) {
// Convenient helper function to get the length of any vector, regardless
// of whether it is null or not (the field is not set).
template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
return v ? v->Length() : 0;
return v ? v->size() : 0;
}
// Lexicographically compare two strings (possibly containing nulls), and
// return true if the first is less than the second.
static inline bool StringLessThan(const char *a_data, uoffset_t a_size,
const char *b_data, uoffset_t b_size) {
const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size));
return cmp == 0 ? a_size < b_size : cmp < 0;
}
struct String : public Vector<char> {
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()); }
// clang-format off
#ifdef FLATBUFFERS_HAS_STRING_VIEW
flatbuffers::string_view string_view() const {
return flatbuffers::string_view(c_str(), Length());
return flatbuffers::string_view(c_str(), size());
}
#endif // FLATBUFFERS_HAS_STRING_VIEW
// clang-format on
bool operator<(const String &o) const {
return strcmp(c_str(), o.c_str()) < 0;
return StringLessThan(this->data(), this->size(), o.data(), o.size());
}
};
@@ -421,6 +482,10 @@ class DefaultAllocator : public Allocator {
void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE {
delete[] p;
}
static void dealloc(void *p, size_t) {
delete[] static_cast<uint8_t *>(p);
}
};
// These functions allow for a null allocator to mean use the default allocator,
@@ -469,6 +534,9 @@ class DetachedBuffer {
cur_(cur),
size_(sz) {}
// clang-format off
#if !defined(FLATBUFFERS_CPP98_STL)
// clang-format on
DetachedBuffer(DetachedBuffer &&other)
: allocator_(other.allocator_),
own_allocator_(other.own_allocator_),
@@ -478,7 +546,13 @@ class DetachedBuffer {
size_(other.size_) {
other.reset();
}
// clang-format off
#endif // !defined(FLATBUFFERS_CPP98_STL)
// clang-format on
// clang-format off
#if !defined(FLATBUFFERS_CPP98_STL)
// clang-format on
DetachedBuffer &operator=(DetachedBuffer &&other) {
destroy();
@@ -493,6 +567,9 @@ class DetachedBuffer {
return *this;
}
// clang-format off
#endif // !defined(FLATBUFFERS_CPP98_STL)
// clang-format on
~DetachedBuffer() { destroy(); }
@@ -522,12 +599,18 @@ class DetachedBuffer {
#endif
// clang-format on
// clang-format off
#if !defined(FLATBUFFERS_CPP98_STL)
// clang-format on
// These may change access mode, leave these at end of public section
FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other))
FLATBUFFERS_DELETE_FUNC(
DetachedBuffer &operator=(const DetachedBuffer &other))
// clang-format off
#endif // !defined(FLATBUFFERS_CPP98_STL)
// clang-format on
protected:
protected:
Allocator *allocator_;
bool own_allocator_;
uint8_t *buf_;
@@ -572,7 +655,13 @@ class vector_downward {
cur_(nullptr),
scratch_(nullptr) {}
// clang-format off
#if !defined(FLATBUFFERS_CPP98_STL)
vector_downward(vector_downward &&other)
#else
vector_downward(vector_downward &other)
#endif // defined(FLATBUFFERS_CPP98_STL)
// clang-format on
: allocator_(other.allocator_),
own_allocator_(other.own_allocator_),
initial_size_(other.initial_size_),
@@ -591,12 +680,18 @@ class vector_downward {
other.scratch_ = nullptr;
}
// clang-format off
#if !defined(FLATBUFFERS_CPP98_STL)
// clang-format on
vector_downward &operator=(vector_downward &&other) {
// Move construct a temporary and swap idiom
vector_downward temp(std::move(other));
swap(temp);
return *this;
}
// clang-format off
#endif // defined(FLATBUFFERS_CPP98_STL)
// clang-format on
~vector_downward() {
clear_buffer();
@@ -842,8 +937,13 @@ class FlatBufferBuilder {
EndianCheck();
}
// clang-format off
/// @brief Move constructor for FlatBufferBuilder.
#if !defined(FLATBUFFERS_CPP98_STL)
FlatBufferBuilder(FlatBufferBuilder &&other)
#else
FlatBufferBuilder(FlatBufferBuilder &other)
#endif // #if !defined(FLATBUFFERS_CPP98_STL)
: buf_(1024, nullptr, false, AlignOf<largest_scalar_t>()),
num_field_loc(0),
max_voffset_(0),
@@ -858,7 +958,11 @@ class FlatBufferBuilder {
// Lack of delegating constructors in vs2010 makes it more verbose than needed.
Swap(other);
}
// clang-format on
// clang-format off
#if !defined(FLATBUFFERS_CPP98_STL)
// clang-format on
/// @brief Move assignment operator for FlatBufferBuilder.
FlatBufferBuilder &operator=(FlatBufferBuilder &&other) {
// Move construct a temporary and swap idiom
@@ -866,6 +970,9 @@ class FlatBufferBuilder {
Swap(temp);
return *this;
}
// clang-format off
#endif // defined(FLATBUFFERS_CPP98_STL)
// clang-format on
void Swap(FlatBufferBuilder &other) {
using std::swap;
@@ -920,8 +1027,8 @@ class FlatBufferBuilder {
/// @warning Do NOT attempt to use this FlatBufferBuilder afterwards!
/// @return A `FlatBuffer` that owns the buffer and its allocator and
/// behaves similar to a `unique_ptr` with a deleter.
/// Deprecated: use Release() instead
DetachedBuffer ReleaseBufferPointer() {
FLATBUFFERS_ATTRIBUTE(deprecated("use Release() instead")) DetachedBuffer
ReleaseBufferPointer() {
Finished();
return buf_.release();
}
@@ -940,7 +1047,7 @@ class FlatBufferBuilder {
/// `FlatBuffer` starts.
/// @return A raw pointer to the start of the memory block containing
/// the serialized `FlatBuffer`.
/// @remark If the allocator is owned, it gets deleted during this call.
/// @remark If the allocator is owned, it gets deleted when the destructor is called..
uint8_t *ReleaseRaw(size_t &size, size_t &offset) {
Finished();
return buf_.release_raw(size, offset);
@@ -1029,7 +1136,7 @@ class FlatBufferBuilder {
// Like PushElement, but additionally tracks the field this represents.
template<typename T> void AddElement(voffset_t field, T e, T def) {
// We don't serialize values equal to the default.
if (e == def && !force_defaults_) return;
if (IsTheSameAs(e, def) && !force_defaults_) return;
auto off = PushElement(e);
TrackField(field, off);
}
@@ -1129,7 +1236,7 @@ class FlatBufferBuilder {
auto vt_offset_ptr = reinterpret_cast<uoffset_t *>(it);
auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*vt_offset_ptr));
auto vt2_size = *vt2;
if (vt1_size != vt2_size || memcmp(vt2, vt1, vt1_size)) continue;
if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size)) continue;
vt_use = *vt_offset_ptr;
buf_.pop(GetSize() - vtableoffsetloc);
break;
@@ -1150,7 +1257,7 @@ class FlatBufferBuilder {
return vtableoffsetloc;
}
// DEPRECATED: call the version above instead.
FLATBUFFERS_ATTRIBUTE(deprecated("call the version above instead"))
uoffset_t EndTable(uoffset_t start, voffset_t /*numfields*/) {
return EndTable(start);
}
@@ -1233,7 +1340,7 @@ class FlatBufferBuilder {
/// @param[in] str A const pointer to a `String` struct to add to the buffer.
/// @return Returns the offset in the buffer where the string starts
Offset<String> CreateString(const String *str) {
return str ? CreateString(str->c_str(), str->Length()) : 0;
return str ? CreateString(str->c_str(), str->size()) : 0;
}
/// @brief Store a string in the buffer, which can contain any binary data.
@@ -1293,7 +1400,7 @@ class FlatBufferBuilder {
/// @param[in] str A const pointer to a `String` struct to add to the buffer.
/// @return Returns the offset in the buffer where the string starts
Offset<String> CreateSharedString(const String *str) {
return CreateSharedString(str->c_str(), str->Length());
return CreateSharedString(str->c_str(), str->size());
}
/// @cond FLATBUFFERS_INTERNAL
@@ -1457,7 +1564,7 @@ class FlatBufferBuilder {
extern T Pack(const S &);
typedef T (*Pack_t)(const S &);
std::vector<T> vv(len);
std::transform(v, v + len, vv.begin(), *(Pack_t)&Pack);
std::transform(v, v + len, vv.begin(), static_cast<Pack_t&>(Pack));
return CreateVectorOfStructs<T>(vv.data(), vv.size());
}
@@ -1595,7 +1702,7 @@ class FlatBufferBuilder {
extern T Pack(const S &);
typedef T (*Pack_t)(const S &);
std::vector<T> vv(len);
std::transform(v, v + len, vv.begin(), *(Pack_t)&Pack);
std::transform(v, v + len, vv.begin(), static_cast<Pack_t&>(Pack));
return CreateVectorOfSortedStructs<T>(vv, len);
}
@@ -1681,6 +1788,19 @@ class FlatBufferBuilder {
reinterpret_cast<uint8_t **>(buf));
}
// @brief Create a vector of scalar type T given as input a vector of scalar
// type U, useful with e.g. pre "enum class" enums, or any existing scalar
// data of the wrong type.
template<typename T, typename U>
Offset<Vector<T>> CreateVectorScalarCast(const U *v, size_t len) {
AssertScalarT<T>();
AssertScalarT<U>();
StartVector(len, sizeof(T));
for (auto i = len; i > 0;) { PushElement(static_cast<T>(v[--i])); }
return Offset<Vector<T>>(EndVector(len));
}
/// @brief Write a struct by itself, typically to be part of a union.
template<typename T> Offset<const T *> CreateStruct(const T &structobj) {
NotNested();
@@ -1713,7 +1833,12 @@ class FlatBufferBuilder {
Finish(root.o, file_identifier, true);
}
protected:
void SwapBufAllocator(FlatBufferBuilder &other) {
buf_.swap_allocator(other.buf_);
}
protected:
// You shouldn't really be copying instances of this class.
FlatBufferBuilder(const FlatBufferBuilder &);
FlatBufferBuilder &operator=(const FlatBufferBuilder &);
@@ -1766,8 +1891,8 @@ class FlatBufferBuilder {
bool operator()(const Offset<String> &a, const Offset<String> &b) const {
auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o));
auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o));
return strncmp(stra->c_str(), strb->c_str(),
(std::min)(stra->size(), strb->size()) + 1) < 0;
return StringLessThan(stra->data(), stra->size(),
strb->data(), strb->size());
}
const vector_downward *buf_;
};
@@ -1846,20 +1971,17 @@ inline bool BufferHasIdentifier(const void *buf, const char *identifier, bool si
class Verifier FLATBUFFERS_FINAL_CLASS {
public:
Verifier(const uint8_t *buf, size_t buf_len, uoffset_t _max_depth = 64,
uoffset_t _max_tables = 1000000)
uoffset_t _max_tables = 1000000, bool _check_alignment = true)
: buf_(buf),
size_(buf_len),
depth_(0),
max_depth_(_max_depth),
num_tables_(0),
max_tables_(_max_tables)
// clang-format off
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
, upper_bound_(0)
#endif
// clang-format on
max_tables_(_max_tables),
upper_bound_(0),
check_alignment_(_check_alignment)
{
assert(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
}
// Central location where any verification failures register.
@@ -1889,7 +2011,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
}
template<typename T> bool VerifyAlignment(size_t elem) const {
return (elem & (sizeof(T) - 1)) == 0;
return (elem & (sizeof(T) - 1)) == 0 || !check_alignment_;
}
// Verify a range indicated by sizeof(T).
@@ -2019,7 +2141,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
if (!Verify<uoffset_t>(start)) return 0;
auto o = ReadScalar<uoffset_t>(buf_ + start);
// May not point to itself.
Check(o != 0);
if (!Check(o != 0)) return 0;
// Can't wrap around / buffers are max 2GB.
if (!Check(static_cast<soffset_t>(o) >= 0)) return 0;
// Must be inside the buffer to create a pointer from it (pointer outside
@@ -2048,17 +2170,22 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
return true;
}
// clang-format off
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
// Returns the message size in bytes
size_t GetComputedSize() const {
uintptr_t size = upper_bound_;
// Align the size to uoffset_t
size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
return (size > size_) ? 0 : size;
// clang-format off
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
uintptr_t size = upper_bound_;
// Align the size to uoffset_t
size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
return (size > size_) ? 0 : size;
#else
// Must turn on FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE for this to work.
(void)upper_bound_;
FLATBUFFERS_ASSERT(false);
return 0;
#endif
// clang-format on
}
#endif
// clang-format on
private:
const uint8_t *buf_;
@@ -2067,11 +2194,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
uoffset_t max_depth_;
uoffset_t num_tables_;
uoffset_t max_tables_;
// clang-format off
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
mutable size_t upper_bound_;
#endif
// clang-format on
mutable size_t upper_bound_;
bool check_alignment_;
};
// Convenient way to bundle a buffer and its length, to pass it around
@@ -2163,7 +2287,7 @@ class Table {
template<typename T> bool SetField(voffset_t field, T val, T def) {
auto field_offset = GetOptionalFieldOffset(field);
if (!field_offset) return val == def;
if (!field_offset) return IsTheSameAs(val, def);
WriteScalar(data_ + field_offset, val);
return true;
}
@@ -2315,9 +2439,11 @@ typedef uint64_t hash_value_t;
// Note: this function will return false for fields equal to the default
// value, since they're not stored in the buffer (unless force_defaults was
// used).
template<typename T> bool IsFieldPresent(const T *table, voffset_t field) {
template<typename T>
bool IsFieldPresent(const T *table, typename T::FlatBuffersVTableOffset field) {
// Cast, since Table is a private baseclass of any table types.
return reinterpret_cast<const Table *>(table)->CheckField(field);
return reinterpret_cast<const Table *>(table)->CheckField(
static_cast<voffset_t>(field));
}
// Utility function for reverse lookups on the EnumNames*() functions
@@ -2342,10 +2468,10 @@ inline int LookupEnum(const char **names, const char *name) {
// clang-format off
#if defined(_MSC_VER)
#define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
__pragma(pack(1)); \
__pragma(pack(1)) \
struct __declspec(align(alignment))
#define FLATBUFFERS_STRUCT_END(name, size) \
__pragma(pack()); \
__pragma(pack()) \
static_assert(sizeof(name) == size, "compiler breaks packing rules")
#elif defined(__GNUC__) || defined(__clang__)
#define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
@@ -2424,7 +2550,7 @@ struct TypeTable {
size_t num_elems; // of type_codes, values, names (but not type_refs).
const TypeCode *type_codes; // num_elems count
const TypeFunction *type_refs; // less than num_elems entries (see TypeCode).
const int32_t *values; // Only set for non-consecutive enum/union or structs.
const int64_t *values; // Only set for non-consecutive enum/union or structs.
const char * const *names; // Only set if compiled with --reflect-names.
};

View File

@@ -80,6 +80,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,

View File

@@ -153,7 +153,7 @@ inline uint64_t ReadUInt64(const uint8_t *data, uint8_t byte_width) {
// constant, which here it isn't. Test if memcpy is still faster than
// 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);
@@ -337,6 +337,16 @@ 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(const uint8_t *data, uint8_t parent_width, uint8_t byte_width,
@@ -484,7 +494,7 @@ class Reference {
}
// 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 +542,14 @@ 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 += "(?)";
}
@@ -591,7 +602,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 +715,35 @@ 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));

View File

@@ -164,7 +164,7 @@ class MessageBuilder : private detail::SliceAllocatorMember,
public FlatBufferBuilder {
public:
explicit MessageBuilder(uoffset_t initial_size = 1024)
: FlatBufferBuilder(initial_size, &slice_allocator_, false) {}
: FlatBufferBuilder(initial_size, &slice_allocator_, false) {}
MessageBuilder(const MessageBuilder &other) = delete;
MessageBuilder &operator=(const MessageBuilder &other) = delete;
@@ -175,6 +175,30 @@ class MessageBuilder : private detail::SliceAllocatorMember,
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));

View File

@@ -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,12 +57,12 @@ 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);
}

View File

@@ -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.
@@ -43,7 +49,7 @@ namespace flatbuffers {
#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(BOOL, "bool", uint8_t, boolean,bool, bool, bool, bool) \
TD(CHAR, "byte", int8_t, byte, int8, sbyte, int8, i8) \
TD(UCHAR, "ubyte", uint8_t, byte, byte, byte, uint8, u8) \
TD(SHORT, "short", int16_t, short, int16, short, int16, i16) \
@@ -147,6 +153,8 @@ struct Type {
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
@@ -229,6 +237,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 +258,7 @@ struct FieldDef : public Definition {
: deprecated(false),
required(false),
key(false),
shared(false),
native_inline(false),
flexbuffer(false),
nested_flatbuffer(NULL),
@@ -255,11 +267,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 +301,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.
@@ -311,9 +329,14 @@ inline size_t InlineAlignment(const Type &type) {
struct EnumVal {
EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
EnumVal() : value(0) {}
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
bool Deserialize(const Parser &parser, const reflection::EnumVal *val);
bool IsZero() const { return 0 == value; }
bool IsNonZero() const { return !IsZero(); }
std::string name;
std::vector<std::string> doc_comment;
int64_t value;
@@ -321,12 +344,12 @@ struct EnumVal {
};
struct EnumDef : public Definition {
EnumDef() : is_union(false), uses_type_aliases(false) {}
EnumDef() : is_union(false), uses_multiple_type_instances(false) {}
EnumVal *ReverseLookup(int64_t enum_idx, bool skip_union_default = true) {
for (auto it = vals.vec.begin() +
for (auto it = Vals().begin() +
static_cast<int>(is_union && skip_union_default);
it != vals.vec.end(); ++it) {
it != Vals().end(); ++it) {
if ((*it)->value == enum_idx) { return *it; }
}
return nullptr;
@@ -334,9 +357,19 @@ struct EnumDef : public Definition {
Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder, const Parser &parser) const;
bool Deserialize(Parser &parser, const reflection::Enum *values);
size_t size() const { return vals.vec.size(); }
const std::vector<EnumVal *> &Vals() const {
return vals.vec;
}
SymbolTable<EnumVal> vals;
bool is_union;
bool uses_type_aliases;
// Type is a union which uses type aliases where at least one type is
// available under two different names.
bool uses_multiple_type_instances;
Type underlying_type;
};
@@ -350,11 +383,14 @@ inline bool EqualByName(const Type &a, const Type &b) {
struct RPCCall : public Definition {
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;
bool Deserialize(Parser &parser, const reflection::Service *service);
SymbolTable<RPCCall> calls;
};
@@ -382,7 +418,9 @@ 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 gen_generated;
std::string object_prefix;
std::string object_suffix;
bool union_value_namespacing;
@@ -396,6 +434,7 @@ struct IDLOptions {
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;
@@ -456,7 +495,9 @@ 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),
gen_generated(false),
object_suffix("T"),
union_value_namespacing(true),
allow_non_utf8(false),
@@ -466,6 +507,7 @@ struct IDLOptions {
binary_schema_builtins(false),
skip_flatbuffers_import(false),
reexport_ts_modules(true),
js_ts_short_names(false),
protobuf_ascii_alike(false),
size_prefixed(false),
force_defaults(false),
@@ -478,7 +520,11 @@ struct IDLOptions {
// 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 +548,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_;
};
@@ -573,6 +623,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 +637,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 +681,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 +699,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(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,37 +728,20 @@ 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);
template<typename F>
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body);
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue,
FieldDef *field, size_t fieldn);
FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field,
size_t fieldn,
const StructDef *parent_struct_def);
@@ -705,8 +750,8 @@ class Parser : public ParserState {
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);
@@ -742,17 +787,11 @@ class Parser : public ParserState {
const char *suffix,
BaseType baseType);
bool SupportsVectorOfUnions() const;
bool SupportsAdvancedUnionFeatures() 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_;
@@ -801,6 +840,10 @@ extern std::string MakeCamel(const std::string &in, bool first = true);
// strict_json adds "quotes" around field names if true.
// If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8
// byte arrays in String values), returns false.
extern bool GenerateTextFromTable(const Parser &parser,
const void *table,
const std::string &tablename,
std::string *text);
extern bool GenerateText(const Parser &parser,
const void *flatbuffer,
std::string *text);
@@ -827,7 +870,7 @@ extern bool GenerateDart(const Parser &parser,
// Generate JavaScript or TypeScript code from the definitions in the Parser object.
// See idl_gen_js.
extern bool GenerateJS(const Parser &parser,
extern bool GenerateJSTS(const Parser &parser,
const std::string &path,
const std::string &file_name);
@@ -858,8 +901,8 @@ extern bool GenerateLobster(const Parser &parser,
// 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);
const std::string &path,
const std::string &file_name);
// Generate Rust files from the definitions in the Parser object.
// See idl_gen_rust.cpp.
@@ -889,7 +932,7 @@ extern bool GenerateFBS(const Parser &parser,
// Generate a make rule for the generated JavaScript or TypeScript code.
// See idl_gen_js.cpp.
extern std::string JSMakeRule(const Parser &parser,
extern std::string JSTSMakeRule(const Parser &parser,
const std::string &path,
const std::string &file_name);

View File

@@ -88,27 +88,27 @@ 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 +122,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 +287,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 +360,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;
}

View File

@@ -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 -------------------------

View File

@@ -94,12 +94,13 @@ inline const char * const *EnumNamesBaseType() {
}
inline const char *EnumNameBaseType(BaseType e) {
const size_t index = static_cast<int>(e);
if (e < None || e > Union) return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesBaseType()[index];
}
struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
enum {
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_BASE_TYPE = 4,
VT_ELEMENT = 6,
VT_INDEX = 8
@@ -159,7 +160,7 @@ inline flatbuffers::Offset<Type> CreateType(
}
struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
enum {
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_KEY = 4,
VT_VALUE = 6
};
@@ -221,14 +222,16 @@ 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 {
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_NAME = 4,
VT_VALUE = 6,
VT_OBJECT = 8,
@@ -326,17 +329,19 @@ inline flatbuffers::Offset<EnumVal> CreateEnumValDirect(
flatbuffers::Offset<Object> object = 0,
flatbuffers::Offset<Type> union_type = 0,
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
auto name__ = name ? _fbb.CreateString(name) : 0;
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
return reflection::CreateEnumVal(
_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 {
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_NAME = 4,
VT_VALUES = 6,
VT_IS_UNION = 8,
@@ -450,18 +455,22 @@ inline flatbuffers::Offset<Enum> CreateEnumDirect(
flatbuffers::Offset<Type> underlying_type = 0,
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
auto name__ = name ? _fbb.CreateString(name) : 0;
auto values__ = values ? _fbb.CreateVector<flatbuffers::Offset<EnumVal>>(*values) : 0;
auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0;
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
return reflection::CreateEnum(
_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 {
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_NAME = 4,
VT_TYPE = 6,
VT_ID = 8,
@@ -627,9 +636,12 @@ inline flatbuffers::Offset<Field> CreateFieldDirect(
bool key = false,
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
auto name__ = name ? _fbb.CreateString(name) : 0;
auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0;
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
return reflection::CreateField(
_fbb,
name ? _fbb.CreateString(name) : 0,
name__,
type,
id,
offset,
@@ -638,12 +650,12 @@ 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 {
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_NAME = 4,
VT_FIELDS = 6,
VT_IS_STRUCT = 8,
@@ -766,19 +778,23 @@ inline flatbuffers::Offset<Object> CreateObjectDirect(
int32_t bytesize = 0,
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
auto name__ = name ? _fbb.CreateString(name) : 0;
auto fields__ = fields ? _fbb.CreateVector<flatbuffers::Offset<Field>>(*fields) : 0;
auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0;
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
return reflection::CreateObject(
_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 {
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_NAME = 4,
VT_REQUEST = 6,
VT_RESPONSE = 8,
@@ -880,17 +896,20 @@ inline flatbuffers::Offset<RPCCall> CreateRPCCallDirect(
flatbuffers::Offset<Object> response = 0,
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
auto name__ = name ? _fbb.CreateString(name) : 0;
auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0;
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
return reflection::CreateRPCCall(
_fbb,
name ? _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 {
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_NAME = 4,
VT_CALLS = 6,
VT_ATTRIBUTES = 8,
@@ -979,16 +998,20 @@ inline flatbuffers::Offset<Service> CreateServiceDirect(
const std::vector<flatbuffers::Offset<RPCCall>> *calls = nullptr,
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
auto name__ = name ? _fbb.CreateString(name) : 0;
auto calls__ = calls ? _fbb.CreateVector<flatbuffers::Offset<RPCCall>>(*calls) : 0;
auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0;
auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0;
return reflection::CreateService(
_fbb,
name ? _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 {
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_OBJECTS = 4,
VT_ENUMS = 6,
VT_FILE_IDENT = 8,
@@ -1096,14 +1119,19 @@ inline flatbuffers::Offset<Schema> CreateSchemaDirect(
const char *file_ext = nullptr,
flatbuffers::Offset<Object> root_table = 0,
const std::vector<flatbuffers::Offset<Service>> *services = nullptr) {
auto objects__ = objects ? _fbb.CreateVector<flatbuffers::Offset<Object>>(*objects) : 0;
auto enums__ = enums ? _fbb.CreateVector<flatbuffers::Offset<Enum>>(*enums) : 0;
auto file_ident__ = file_ident ? _fbb.CreateString(file_ident) : 0;
auto file_ext__ = file_ext ? _fbb.CreateString(file_ext) : 0;
auto services__ = services ? _fbb.CreateVector<flatbuffers::Offset<Service>>(*services) : 0;
return reflection::CreateSchema(
_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) {

View File

@@ -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.

View File

@@ -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,7 @@ 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 make_unsigned = std::make_unsigned<T>;
#else
// Map C++ TR1 templates defined by stlport.
template <typename T> using is_scalar = std::tr1::is_scalar<T>;
@@ -121,6 +146,17 @@ 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>;
// Android NDK doesn't have std::make_unsigned or std::tr1::make_unsigned.
template<typename T> struct make_unsigned {
static_assert(is_unsigned<T>::value, "Specialization not implemented!");
using type = T;
};
template<> struct make_unsigned<char> { using type = unsigned char; };
template<> struct make_unsigned<short> { using type = unsigned short; };
template<> struct make_unsigned<int> { using type = unsigned int; };
template<> struct make_unsigned<long> { using type = unsigned long; };
template<>
struct make_unsigned<long long> { using type = unsigned long long; };
#endif // !FLATBUFFERS_CPP98_STL
#else
// MSVC 2010 doesn't support C++11 aliases.
@@ -129,6 +165,7 @@ 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 make_unsigned : public std::make_unsigned<T> {};
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
#ifndef FLATBUFFERS_CPP98_STL

View File

@@ -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 "flatbuffers/base.h"
#include <errno.h>
#ifndef FLATBUFFERS_PREFER_PRINTF
# include <sstream>
#else // FLATBUFFERS_PREFER_PRINTF
# include <float.h>
# include <stdio.h>
#endif // FLATBUFFERS_PREFER_PRINTF
#include <iomanip>
#include <string>
namespace flatbuffers {
// @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, precision, 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,19 @@ inline bool EscapeString(const char *s, size_t length, std::string *_text,
return true;
}
// Remove paired quotes in a string: "text"|'text' -> text.
std::string RemoveStringQuotes(const std::string &s);
// Change th global C-locale to locale with name <locale_name>.
// Returns an actual locale name in <_value>, useful if locale_name is "" or
// null.
bool SetGlobalTestLocale(const char *locale_name,
std::string *_value = nullptr);
// Read (or test) a value of environment variable.
bool ReadEnvironmentVariable(const char *var_name,
std::string *_value = nullptr);
} // namespace flatbuffers
#endif // FLATBUFFERS_UTIL_H_

View File

@@ -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;
this(initial_size, bb_factory, null, Utf8.getDefault());
}
/**
* Start with a buffer of size `initial_size`, then grow as required.
*
* @param initial_size The initial size of the internal buffer to use.
* @param bb_factory The factory to be used for allocating the internal buffer
* @param existing_bb The byte buffer to reuse.
* @param utf8 The Utf8 codec
*/
public FlatBufferBuilder(int initial_size, ByteBufferFactory bb_factory,
ByteBuffer existing_bb, Utf8 utf8) {
if (initial_size <= 0) {
initial_size = 1;
}
space = initial_size;
this.bb_factory = bb_factory;
bb = bb_factory.newByteBuffer(initial_size);
if (existing_bb != null) {
bb = existing_bb;
bb.clear();
bb.order(ByteOrder.LITTLE_ENDIAN);
} else {
bb = bb_factory.newByteBuffer(initial_size);
}
this.utf8 = utf8;
}
/**
@@ -74,7 +90,7 @@ public class FlatBufferBuilder {
* @param initial_size The initial size of the internal buffer to use.
*/
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,7 +189,10 @@ 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);
@@ -503,27 +523,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();
}
/**

View File

@@ -19,11 +19,7 @@ package com.google.flatbuffers;
import static com.google.flatbuffers.Constants.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
/// @cond FLATBUFFERS_INTERNAL
@@ -31,23 +27,21 @@ import java.nio.charset.CoderResult;
* All tables in the generated code derive from this class, and add their own accessors.
*/
public class Table {
private final static ThreadLocal<CharsetDecoder> UTF8_DECODER = new ThreadLocal<CharsetDecoder>() {
@Override
protected CharsetDecoder initialValue() {
return Charset.forName("UTF-8").newDecoder();
}
};
public final static ThreadLocal<Charset> UTF8_CHARSET = new ThreadLocal<Charset>() {
@Override
protected Charset initialValue() {
return Charset.forName("UTF-8");
}
};
private final static ThreadLocal<CharBuffer> CHAR_BUFFER = new ThreadLocal<CharBuffer>();
/** Used to hold the position of the `bb` buffer. */
protected int bb_pos;
/** The underlying ByteBuffer to hold the data of the Table. */
protected ByteBuffer bb;
/** Used to hold the vtable position. */
protected int vtable_start;
/** Used to hold the vtable size. */
protected int vtable_size;
Utf8 utf8 = Utf8.getDefault();
/**
* Get the underlying ByteBuffer.
@@ -63,8 +57,7 @@ public class Table {
* @return Returns an offset into the object, or `0` if the field is not present.
*/
protected int __offset(int vtable_offset) {
int vtable = bb_pos - bb.getInt(bb_pos);
return vtable_offset < bb.getShort(vtable) ? bb.getShort(vtable + vtable_offset) : 0;
return vtable_offset < vtable_size ? bb.getShort(vtable_start + vtable_offset) : 0;
}
protected static int __offset(int vtable_offset, int offset, ByteBuffer bb) {
@@ -98,34 +91,9 @@ public class Table {
* @return Returns a `String` from the data stored inside the FlatBuffer at `offset`.
*/
protected String __string(int offset) {
CharsetDecoder decoder = UTF8_DECODER.get();
decoder.reset();
offset += bb.getInt(offset);
ByteBuffer src = bb.duplicate().order(ByteOrder.LITTLE_ENDIAN);
int length = src.getInt(offset);
src.position(offset + SIZEOF_INT);
src.limit(offset + SIZEOF_INT + length);
int required = (int)((float)length * decoder.maxCharsPerByte());
CharBuffer dst = CHAR_BUFFER.get();
if (dst == null || dst.capacity() < required) {
dst = CharBuffer.allocate(required);
CHAR_BUFFER.set(dst);
}
dst.clear();
try {
CoderResult cr = decoder.decode(src, dst, true);
if (!cr.isUnderflow()) {
cr.throwException();
}
} catch (CharacterCodingException x) {
throw new RuntimeException(x);
}
return dst.flip().toString();
int length = bb.getInt(offset);
return utf8.decodeUtf8(bb, offset + SIZEOF_INT, length);
}
/**
@@ -204,6 +172,8 @@ public class Table {
offset += bb_pos;
t.bb_pos = offset + bb.getInt(offset);
t.bb = bb;
t.vtable_start = t.bb_pos - bb.getInt(t.bb_pos);
t.vtable_size = bb.getShort(t.vtable_start);
return t;
}
@@ -303,6 +273,8 @@ public class Table {
public void __reset() {
bb = null;
bb_pos = 0;
vtable_start = 0;
vtable_size = 0;
}
}

View File

@@ -0,0 +1,191 @@
/*
* Copyright 2014 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.flatbuffers;
import java.nio.ByteBuffer;
import static java.lang.Character.MIN_HIGH_SURROGATE;
import static java.lang.Character.MIN_LOW_SURROGATE;
import static java.lang.Character.MIN_SUPPLEMENTARY_CODE_POINT;
public abstract class Utf8 {
/**
* Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string,
* this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in
* both time and space.
*
* @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
* surrogates)
*/
public abstract int encodedLength(CharSequence sequence);
/**
* Encodes the given characters to the target {@link ByteBuffer} using UTF-8 encoding.
*
* <p>Selects an optimal algorithm based on the type of {@link ByteBuffer} (i.e. heap or direct)
* and the capabilities of the platform.
*
* @param in the source string to be encoded
* @param out the target buffer to receive the encoded string.
*/
public abstract void encodeUtf8(CharSequence in, ByteBuffer out);
/**
* Decodes the given UTF-8 portion of the {@link ByteBuffer} into a {@link String}.
*
* @throws IllegalArgumentException if the input is not valid UTF-8.
*/
public abstract String decodeUtf8(ByteBuffer buffer, int offset, int length);
private static Utf8 DEFAULT;
/**
* Get the default UTF-8 processor.
* @return the default processor
*/
public static Utf8 getDefault() {
if (DEFAULT == null) {
DEFAULT = new Utf8Safe();
}
return DEFAULT;
}
/**
* Set the default instance of the UTF-8 processor.
* @param instance the new instance to use
*/
public static void setDefault(Utf8 instance) {
DEFAULT = instance;
}
/**
* Utility methods for decoding bytes into {@link String}. Callers are responsible for extracting
* bytes (possibly using Unsafe methods), and checking remaining bytes. All other UTF-8 validity
* checks and codepoint conversion happen in this class.
*/
static class DecodeUtil {
/**
* Returns whether this is a single-byte codepoint (i.e., ASCII) with the form '0XXXXXXX'.
*/
static boolean isOneByte(byte b) {
return b >= 0;
}
/**
* Returns whether this is a two-byte codepoint with the form '10XXXXXX'.
*/
static boolean isTwoBytes(byte b) {
return b < (byte) 0xE0;
}
/**
* Returns whether this is a three-byte codepoint with the form '110XXXXX'.
*/
static boolean isThreeBytes(byte b) {
return b < (byte) 0xF0;
}
static void handleOneByte(byte byte1, char[] resultArr, int resultPos) {
resultArr[resultPos] = (char) byte1;
}
static void handleTwoBytes(
byte byte1, byte byte2, char[] resultArr, int resultPos)
throws IllegalArgumentException {
// Simultaneously checks for illegal trailing-byte in leading position (<= '11000000') and
// overlong 2-byte, '11000001'.
if (byte1 < (byte) 0xC2
|| isNotTrailingByte(byte2)) {
throw new IllegalArgumentException("Invalid UTF-8");
}
resultArr[resultPos] = (char) (((byte1 & 0x1F) << 6) | trailingByteValue(byte2));
}
static void handleThreeBytes(
byte byte1, byte byte2, byte byte3, char[] resultArr, int resultPos)
throws IllegalArgumentException {
if (isNotTrailingByte(byte2)
// overlong? 5 most significant bits must not all be zero
|| (byte1 == (byte) 0xE0 && byte2 < (byte) 0xA0)
// check for illegal surrogate codepoints
|| (byte1 == (byte) 0xED && byte2 >= (byte) 0xA0)
|| isNotTrailingByte(byte3)) {
throw new IllegalArgumentException("Invalid UTF-8");
}
resultArr[resultPos] = (char)
(((byte1 & 0x0F) << 12) | (trailingByteValue(byte2) << 6) | trailingByteValue(byte3));
}
static void handleFourBytes(
byte byte1, byte byte2, byte byte3, byte byte4, char[] resultArr, int resultPos)
throws IllegalArgumentException{
if (isNotTrailingByte(byte2)
// Check that 1 <= plane <= 16. Tricky optimized form of:
// valid 4-byte leading byte?
// if (byte1 > (byte) 0xF4 ||
// overlong? 4 most significant bits must not all be zero
// byte1 == (byte) 0xF0 && byte2 < (byte) 0x90 ||
// codepoint larger than the highest code point (U+10FFFF)?
// byte1 == (byte) 0xF4 && byte2 > (byte) 0x8F)
|| (((byte1 << 28) + (byte2 - (byte) 0x90)) >> 30) != 0
|| isNotTrailingByte(byte3)
|| isNotTrailingByte(byte4)) {
throw new IllegalArgumentException("Invalid UTF-8");
}
int codepoint = ((byte1 & 0x07) << 18)
| (trailingByteValue(byte2) << 12)
| (trailingByteValue(byte3) << 6)
| trailingByteValue(byte4);
resultArr[resultPos] = DecodeUtil.highSurrogate(codepoint);
resultArr[resultPos + 1] = DecodeUtil.lowSurrogate(codepoint);
}
/**
* Returns whether the byte is not a valid continuation of the form '10XXXXXX'.
*/
private static boolean isNotTrailingByte(byte b) {
return b > (byte) 0xBF;
}
/**
* Returns the actual value of the trailing byte (removes the prefix '10') for composition.
*/
private static int trailingByteValue(byte b) {
return b & 0x3F;
}
private static char highSurrogate(int codePoint) {
return (char) ((MIN_HIGH_SURROGATE - (MIN_SUPPLEMENTARY_CODE_POINT >>> 10))
+ (codePoint >>> 10));
}
private static char lowSurrogate(int codePoint) {
return (char) (MIN_LOW_SURROGATE + (codePoint & 0x3ff));
}
}
// These UTF-8 handling methods are copied from Guava's Utf8Unsafe class with a modification to throw
// a protocol buffer local exception. This exception is then caught in CodedOutputStream so it can
// fallback to more lenient behavior.
static class UnpairedSurrogateException extends IllegalArgumentException {
UnpairedSurrogateException(int index, int length) {
super("Unpaired surrogate at index " + index + " of " + length);
}
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright 2014 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.flatbuffers;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.StandardCharsets;
/**
* This class implements the Utf8 API using the Java Utf8 encoder. Use
* Utf8.setDefault(new Utf8Old()); to use it.
*/
public class Utf8Old extends Utf8 {
private static class Cache {
final CharsetEncoder encoder;
final CharsetDecoder decoder;
CharSequence lastInput = null;
ByteBuffer lastOutput = null;
Cache() {
encoder = StandardCharsets.UTF_8.newEncoder();
decoder = StandardCharsets.UTF_8.newDecoder();
}
}
private static final ThreadLocal<Cache> CACHE =
ThreadLocal.withInitial(() -> new Cache());
// Play some games so that the old encoder doesn't pay twice for computing
// the length of the encoded string.
@Override
public int encodedLength(CharSequence in) {
final Cache cache = CACHE.get();
int estimated = (int) (in.length() * cache.encoder.maxBytesPerChar());
if (cache.lastOutput == null || cache.lastOutput.capacity() < estimated) {
cache.lastOutput = ByteBuffer.allocate(Math.max(128, estimated));
}
cache.lastOutput.clear();
cache.lastInput = in;
CharBuffer wrap = (in instanceof CharBuffer) ?
(CharBuffer) in : CharBuffer.wrap(in);
CoderResult result = cache.encoder.encode(wrap, cache.lastOutput, true);
if (result.isError()) {
try {
result.throwException();
} catch (CharacterCodingException e) {
throw new IllegalArgumentException("bad character encoding", e);
}
}
return cache.lastOutput.remaining();
}
@Override
public void encodeUtf8(CharSequence in, ByteBuffer out) {
final Cache cache = CACHE.get();
if (cache.lastInput != in) {
// Update the lastOutput to match our input, although flatbuffer should
// never take this branch.
encodedLength(in);
}
out.put(cache.lastOutput);
}
@Override
public String decodeUtf8(ByteBuffer buffer, int offset, int length) {
CharsetDecoder decoder = CACHE.get().decoder;
decoder.reset();
buffer = buffer.duplicate();
buffer.position(offset);
buffer.limit(offset + length);
try {
CharBuffer result = decoder.decode(buffer);
result.flip();
return result.toString();
} catch (CharacterCodingException e) {
throw new IllegalArgumentException("Bad encoding", e);
}
}
}

View File

@@ -0,0 +1,451 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// 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.
package com.google.flatbuffers;
import java.nio.ByteBuffer;
import static java.lang.Character.MAX_SURROGATE;
import static java.lang.Character.MIN_SUPPLEMENTARY_CODE_POINT;
import static java.lang.Character.MIN_SURROGATE;
import static java.lang.Character.isSurrogatePair;
import static java.lang.Character.toCodePoint;
/**
* A set of low-level, high-performance static utility methods related
* to the UTF-8 character encoding. This class has no dependencies
* outside of the core JDK libraries.
*
* <p>There are several variants of UTF-8. The one implemented by
* this class is the restricted definition of UTF-8 introduced in
* Unicode 3.1, which mandates the rejection of "overlong" byte
* sequences as well as rejection of 3-byte surrogate codepoint byte
* sequences. Note that the UTF-8 decoder included in Oracle's JDK
* has been modified to also reject "overlong" byte sequences, but (as
* of 2011) still accepts 3-byte surrogate codepoint byte sequences.
*
* <p>The byte sequences considered valid by this class are exactly
* those that can be roundtrip converted to Strings and back to bytes
* using the UTF-8 charset, without loss: <pre> {@code
* Arrays.equals(bytes, new String(bytes, Internal.UTF_8).getBytes(Internal.UTF_8))
* }</pre>
*
* <p>See the Unicode Standard,</br>
* Table 3-6. <em>UTF-8 Bit Distribution</em>,</br>
* Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
*/
final public class Utf8Safe extends Utf8 {
/**
* Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string,
* this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in
* both time and space.
*
* @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
* surrogates)
*/
private static int computeEncodedLength(CharSequence sequence) {
// Warning to maintainers: this implementation is highly optimized.
int utf16Length = sequence.length();
int utf8Length = utf16Length;
int i = 0;
// This loop optimizes for pure ASCII.
while (i < utf16Length && sequence.charAt(i) < 0x80) {
i++;
}
// This loop optimizes for chars less than 0x800.
for (; i < utf16Length; i++) {
char c = sequence.charAt(i);
if (c < 0x800) {
utf8Length += ((0x7f - c) >>> 31); // branch free!
} else {
utf8Length += encodedLengthGeneral(sequence, i);
break;
}
}
if (utf8Length < utf16Length) {
// Necessary and sufficient condition for overflow because of maximum 3x expansion
throw new IllegalArgumentException("UTF-8 length does not fit in int: "
+ (utf8Length + (1L << 32)));
}
return utf8Length;
}
private static int encodedLengthGeneral(CharSequence sequence, int start) {
int utf16Length = sequence.length();
int utf8Length = 0;
for (int i = start; i < utf16Length; i++) {
char c = sequence.charAt(i);
if (c < 0x800) {
utf8Length += (0x7f - c) >>> 31; // branch free!
} else {
utf8Length += 2;
// jdk7+: if (Character.isSurrogate(c)) {
if (Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) {
// Check that we have a well-formed surrogate pair.
int cp = Character.codePointAt(sequence, i);
if (cp < MIN_SUPPLEMENTARY_CODE_POINT) {
throw new Utf8Safe.UnpairedSurrogateException(i, utf16Length);
}
i++;
}
}
}
return utf8Length;
}
private static String decodeUtf8Array(byte[] bytes, int index, int size) {
// Bitwise OR combines the sign bits so any negative value fails the check.
if ((index | size | bytes.length - index - size) < 0) {
throw new ArrayIndexOutOfBoundsException(
String.format("buffer length=%d, index=%d, size=%d", bytes.length, index, size));
}
int offset = index;
final int limit = offset + size;
// The longest possible resulting String is the same as the number of input bytes, when it is
// all ASCII. For other cases, this over-allocates and we will truncate in the end.
char[] resultArr = new char[size];
int resultPos = 0;
// Optimize for 100% ASCII (Hotspot loves small simple top-level loops like this).
// This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII).
while (offset < limit) {
byte b = bytes[offset];
if (!DecodeUtil.isOneByte(b)) {
break;
}
offset++;
DecodeUtil.handleOneByte(b, resultArr, resultPos++);
}
while (offset < limit) {
byte byte1 = bytes[offset++];
if (DecodeUtil.isOneByte(byte1)) {
DecodeUtil.handleOneByte(byte1, resultArr, resultPos++);
// It's common for there to be multiple ASCII characters in a run mixed in, so add an
// extra optimized loop to take care of these runs.
while (offset < limit) {
byte b = bytes[offset];
if (!DecodeUtil.isOneByte(b)) {
break;
}
offset++;
DecodeUtil.handleOneByte(b, resultArr, resultPos++);
}
} else if (DecodeUtil.isTwoBytes(byte1)) {
if (offset >= limit) {
throw new IllegalArgumentException("Invalid UTF-8");
}
DecodeUtil.handleTwoBytes(byte1, /* byte2 */ bytes[offset++], resultArr, resultPos++);
} else if (DecodeUtil.isThreeBytes(byte1)) {
if (offset >= limit - 1) {
throw new IllegalArgumentException("Invalid UTF-8");
}
DecodeUtil.handleThreeBytes(
byte1,
/* byte2 */ bytes[offset++],
/* byte3 */ bytes[offset++],
resultArr,
resultPos++);
} else {
if (offset >= limit - 2) {
throw new IllegalArgumentException("Invalid UTF-8");
}
DecodeUtil.handleFourBytes(
byte1,
/* byte2 */ bytes[offset++],
/* byte3 */ bytes[offset++],
/* byte4 */ bytes[offset++],
resultArr,
resultPos++);
// 4-byte case requires two chars.
resultPos++;
}
}
return new String(resultArr, 0, resultPos);
}
private static String decodeUtf8Buffer(ByteBuffer buffer, int offset,
int length) {
// Bitwise OR combines the sign bits so any negative value fails the check.
if ((offset | length | buffer.limit() - offset - length) < 0) {
throw new ArrayIndexOutOfBoundsException(
String.format("buffer limit=%d, index=%d, limit=%d", buffer.limit(),
offset, length));
}
final int limit = offset + length;
// The longest possible resulting String is the same as the number of input bytes, when it is
// all ASCII. For other cases, this over-allocates and we will truncate in the end.
char[] resultArr = new char[length];
int resultPos = 0;
// Optimize for 100% ASCII (Hotspot loves small simple top-level loops like this).
// This simple loop stops when we encounter a byte >= 0x80 (i.e. non-ASCII).
while (offset < limit) {
byte b = buffer.get(offset);
if (!DecodeUtil.isOneByte(b)) {
break;
}
offset++;
DecodeUtil.handleOneByte(b, resultArr, resultPos++);
}
while (offset < limit) {
byte byte1 = buffer.get(offset++);
if (DecodeUtil.isOneByte(byte1)) {
DecodeUtil.handleOneByte(byte1, resultArr, resultPos++);
// It's common for there to be multiple ASCII characters in a run mixed in, so add an
// extra optimized loop to take care of these runs.
while (offset < limit) {
byte b = buffer.get(offset);
if (!DecodeUtil.isOneByte(b)) {
break;
}
offset++;
DecodeUtil.handleOneByte(b, resultArr, resultPos++);
}
} else if (DecodeUtil.isTwoBytes(byte1)) {
if (offset >= limit) {
throw new IllegalArgumentException("Invalid UTF-8");
}
DecodeUtil.handleTwoBytes(
byte1, /* byte2 */ buffer.get(offset++), resultArr, resultPos++);
} else if (DecodeUtil.isThreeBytes(byte1)) {
if (offset >= limit - 1) {
throw new IllegalArgumentException("Invalid UTF-8");
}
DecodeUtil.handleThreeBytes(
byte1,
/* byte2 */ buffer.get(offset++),
/* byte3 */ buffer.get(offset++),
resultArr,
resultPos++);
} else {
if (offset >= limit - 2) {
throw new IllegalArgumentException("Invalid UTF-8");
}
DecodeUtil.handleFourBytes(
byte1,
/* byte2 */ buffer.get(offset++),
/* byte3 */ buffer.get(offset++),
/* byte4 */ buffer.get(offset++),
resultArr,
resultPos++);
// 4-byte case requires two chars.
resultPos++;
}
}
return new String(resultArr, 0, resultPos);
}
@Override
public int encodedLength(CharSequence in) {
return computeEncodedLength(in);
}
/**
* Decodes the given UTF-8 portion of the {@link ByteBuffer} into a {@link String}.
*
* @throws IllegalArgumentException if the input is not valid UTF-8.
*/
@Override
public String decodeUtf8(ByteBuffer buffer, int offset, int length)
throws IllegalArgumentException {
if (buffer.hasArray()) {
return decodeUtf8Array(buffer.array(), buffer.arrayOffset() + offset, length);
} else {
return decodeUtf8Buffer(buffer, offset, length);
}
}
private static void encodeUtf8Buffer(CharSequence in, ByteBuffer out) {
final int inLength = in.length();
int outIx = out.position();
int inIx = 0;
// Since ByteBuffer.putXXX() already checks boundaries for us, no need to explicitly check
// access. Assume the buffer is big enough and let it handle the out of bounds exception
// if it occurs.
try {
// Designed to take advantage of
// https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
for (char c; inIx < inLength && (c = in.charAt(inIx)) < 0x80; ++inIx) {
out.put(outIx + inIx, (byte) c);
}
if (inIx == inLength) {
// Successfully encoded the entire string.
out.position(outIx + inIx);
return;
}
outIx += inIx;
for (char c; inIx < inLength; ++inIx, ++outIx) {
c = in.charAt(inIx);
if (c < 0x80) {
// One byte (0xxx xxxx)
out.put(outIx, (byte) c);
} else if (c < 0x800) {
// Two bytes (110x xxxx 10xx xxxx)
// Benchmarks show put performs better than putShort here (for HotSpot).
out.put(outIx++, (byte) (0xC0 | (c >>> 6)));
out.put(outIx, (byte) (0x80 | (0x3F & c)));
} else if (c < MIN_SURROGATE || MAX_SURROGATE < c) {
// Three bytes (1110 xxxx 10xx xxxx 10xx xxxx)
// Maximum single-char code point is 0xFFFF, 16 bits.
// Benchmarks show put performs better than putShort here (for HotSpot).
out.put(outIx++, (byte) (0xE0 | (c >>> 12)));
out.put(outIx++, (byte) (0x80 | (0x3F & (c >>> 6))));
out.put(outIx, (byte) (0x80 | (0x3F & c)));
} else {
// Four bytes (1111 xxxx 10xx xxxx 10xx xxxx 10xx xxxx)
// Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8
// bytes
final char low;
if (inIx + 1 == inLength || !isSurrogatePair(c, (low = in.charAt(++inIx)))) {
throw new UnpairedSurrogateException(inIx, inLength);
}
// TODO(nathanmittler): Consider using putInt() to improve performance.
int codePoint = toCodePoint(c, low);
out.put(outIx++, (byte) ((0xF << 4) | (codePoint >>> 18)));
out.put(outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 12))));
out.put(outIx++, (byte) (0x80 | (0x3F & (codePoint >>> 6))));
out.put(outIx, (byte) (0x80 | (0x3F & codePoint)));
}
}
// Successfully encoded the entire string.
out.position(outIx);
} catch (IndexOutOfBoundsException e) {
// TODO(nathanmittler): Consider making the API throw IndexOutOfBoundsException instead.
// If we failed in the outer ASCII loop, outIx will not have been updated. In this case,
// use inIx to determine the bad write index.
int badWriteIndex = out.position() + Math.max(inIx, outIx - out.position() + 1);
throw new ArrayIndexOutOfBoundsException(
"Failed writing " + in.charAt(inIx) + " at index " + badWriteIndex);
}
}
private static int encodeUtf8Array(CharSequence in, byte[] out,
int offset, int length) {
int utf16Length = in.length();
int j = offset;
int i = 0;
int limit = offset + length;
// Designed to take advantage of
// https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
for (char c; i < utf16Length && i + j < limit && (c = in.charAt(i)) < 0x80; i++) {
out[j + i] = (byte) c;
}
if (i == utf16Length) {
return j + utf16Length;
}
j += i;
for (char c; i < utf16Length; i++) {
c = in.charAt(i);
if (c < 0x80 && j < limit) {
out[j++] = (byte) c;
} else if (c < 0x800 && j <= limit - 2) { // 11 bits, two UTF-8 bytes
out[j++] = (byte) ((0xF << 6) | (c >>> 6));
out[j++] = (byte) (0x80 | (0x3F & c));
} else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) && j <= limit - 3) {
// Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
out[j++] = (byte) ((0xF << 5) | (c >>> 12));
out[j++] = (byte) (0x80 | (0x3F & (c >>> 6)));
out[j++] = (byte) (0x80 | (0x3F & c));
} else if (j <= limit - 4) {
// Minimum code point represented by a surrogate pair is 0x10000, 17 bits,
// four UTF-8 bytes
final char low;
if (i + 1 == in.length()
|| !Character.isSurrogatePair(c, (low = in.charAt(++i)))) {
throw new UnpairedSurrogateException((i - 1), utf16Length);
}
int codePoint = Character.toCodePoint(c, low);
out[j++] = (byte) ((0xF << 4) | (codePoint >>> 18));
out[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 12)));
out[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 6)));
out[j++] = (byte) (0x80 | (0x3F & codePoint));
} else {
// If we are surrogates and we're not a surrogate pair, always throw an
// UnpairedSurrogateException instead of an ArrayOutOfBoundsException.
if ((Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE)
&& (i + 1 == in.length()
|| !Character.isSurrogatePair(c, in.charAt(i + 1)))) {
throw new UnpairedSurrogateException(i, utf16Length);
}
throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + j);
}
}
return j;
}
/**
* Encodes the given characters to the target {@link ByteBuffer} using UTF-8 encoding.
*
* <p>Selects an optimal algorithm based on the type of {@link ByteBuffer} (i.e. heap or direct)
* and the capabilities of the platform.
*
* @param in the source string to be encoded
* @param out the target buffer to receive the encoded string.
*/
@Override
public void encodeUtf8(CharSequence in, ByteBuffer out) {
if (out.hasArray()) {
int start = out.arrayOffset();
int end = encodeUtf8Array(in, out.array(), start + out.position(),
out.remaining());
out.position(end - start);
} else {
encodeUtf8Buffer(in, out);
}
}
// These UTF-8 handling methods are copied from Guava's Utf8Unsafe class with
// a modification to throw a local exception. This exception can be caught
// to fallback to more lenient behavior.
static class UnpairedSurrogateException extends IllegalArgumentException {
UnpairedSurrogateException(int index, int length) {
super("Unpaired surrogate at index " + index + " of " + length);
}
}
}

View File

@@ -226,6 +226,19 @@ flatbuffers.Builder = function(opt_initial_size) {
this.force_defaults = false;
};
flatbuffers.Builder.prototype.clear = function() {
this.bb.clear();
this.space = this.bb.capacity();
this.minalign = 1;
this.vtable = null;
this.vtable_in_use = 0;
this.isNested = false;
this.object_start = 0;
this.vtables = [];
this.vector_num_elems = 0;
this.force_defaults = false;
};
/**
* In order to save space, fields that are set to their default value
* don't get serialized into the buffer. Forcing defaults provides a
@@ -828,6 +841,10 @@ flatbuffers.ByteBuffer.allocate = function(byte_size) {
return new flatbuffers.ByteBuffer(new Uint8Array(byte_size));
};
flatbuffers.ByteBuffer.prototype.clear = function() {
this.position_ = 0;
};
/**
* Get the underlying `Uint8Array`.
*

View File

@@ -34,7 +34,7 @@ local function vtableEqual(a, objectStart, b)
end
for i, elem in ipairs(a) do
local x = VOffsetT:Unpack(b, i * VOffsetT.bytewidth)
local x = string.unpack(VOffsetT.packFmt, b, 1 + (i - 1) * VOffsetT.bytewidth)
if x ~= 0 or elem ~= 0 then
local y = objectStart - elem
if x ~= y then
@@ -96,11 +96,13 @@ function mt:WriteVtable()
i = i - 1
end
i = #self.vtables
while i >= 1 do
local vt2Offset = self.vtables[i]
local vt2Start = #self.bytes - vt2Offset
local vt2len = VOffsetT:Unpack(self.bytes, vt2Start)
local vt2lenstr = self.bytes:Slice(vt2Start, vt2Start+1)
local vt2Len = string.unpack(VOffsetT.packFmt, vt2lenstr, 1)
local metadata = VtableMetadataFields * VOffsetT.bytewidth
local vt2End = vt2Start + vt2Len
@@ -364,4 +366,4 @@ function mt:Place(x, flags)
self.bytes:Set(d, h)
end
return m
return m

View File

@@ -119,8 +119,8 @@ local int16_mt =
local int32_mt =
{
bytewidth = 4,
min_value = -2^15,
max_value = 2^15-1,
min_value = -2^31,
max_value = 2^31-1,
lua_type = type(1),
name = "int32",
packFmt = "<i4"
@@ -195,4 +195,4 @@ end
GenerateTypes(m)
return m
return m

View File

@@ -42,20 +42,24 @@ using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
#if ENABLE_SPAN_T
using System.Buffers.Binary;
#endif
#if ENABLE_SPAN_T && !UNSAFE_BYTEBUFFER
#error ENABLE_SPAN_T requires UNSAFE_BYTEBUFFER to also be defined
#endif
namespace FlatBuffers
{
public abstract class ByteBufferAllocator : IDisposable
public abstract class ByteBufferAllocator
{
#if UNSAFE_BYTEBUFFER
public unsafe byte* Buffer
{
get;
protected set;
}
#if ENABLE_SPAN_T
public abstract Span<byte> Span { get; }
public abstract ReadOnlySpan<byte> ReadOnlySpan { get; }
public abstract Memory<byte> Memory { get; }
public abstract ReadOnlyMemory<byte> ReadOnlyMemory { get; }
#else
public byte[] Buffer
{
@@ -70,23 +74,17 @@ namespace FlatBuffers
protected set;
}
public abstract void Dispose();
public abstract void GrowFront(int newSize);
#if !ENABLE_SPAN_T
public abstract byte[] ByteArray { get; }
#endif
}
public class ByteArrayAllocator : ByteBufferAllocator
public sealed class ByteArrayAllocator : ByteBufferAllocator
{
private byte[] _buffer;
public ByteArrayAllocator(byte[] buffer)
{
_buffer = buffer;
InitPointer();
InitBuffer();
}
public override void GrowFront(int newSize)
@@ -101,63 +99,29 @@ namespace FlatBuffers
byte[] newBuffer = new byte[newSize];
System.Buffer.BlockCopy(_buffer, 0, newBuffer, newSize - Length, Length);
_buffer = newBuffer;
InitPointer();
InitBuffer();
}
public override void Dispose()
{
GC.SuppressFinalize(this);
#if UNSAFE_BYTEBUFFER
if (_handle.IsAllocated)
{
_handle.Free();
}
#endif
}
#if !ENABLE_SPAN_T
public override byte[] ByteArray
{
get { return _buffer; }
}
#if ENABLE_SPAN_T
public override Span<byte> Span => _buffer;
public override ReadOnlySpan<byte> ReadOnlySpan => _buffer;
public override Memory<byte> Memory => _buffer;
public override ReadOnlyMemory<byte> ReadOnlyMemory => _buffer;
#endif
#if UNSAFE_BYTEBUFFER
private GCHandle _handle;
~ByteArrayAllocator()
{
if (_handle.IsAllocated)
{
_handle.Free();
}
}
#endif
private void InitPointer()
private void InitBuffer()
{
Length = _buffer.Length;
#if UNSAFE_BYTEBUFFER
if (_handle.IsAllocated)
{
_handle.Free();
}
_handle = GCHandle.Alloc(_buffer, GCHandleType.Pinned);
unsafe
{
Buffer = (byte*)_handle.AddrOfPinnedObject().ToPointer();
}
#else
#if !ENABLE_SPAN_T
Buffer = _buffer;
#endif
}
}
/// <summary>
/// Class to mimic Java's ByteBuffer which is used heavily in Flatbuffers.
/// </summary>
public class ByteBuffer : IDisposable
public class ByteBuffer
{
private ByteBufferAllocator _buffer;
private int _pos; // Must track start of the buffer.
@@ -178,15 +142,8 @@ namespace FlatBuffers
_pos = pos;
}
public void Dispose()
public int Position
{
if (_buffer != null)
{
_buffer.Dispose();
}
}
public int Position {
get { return _pos; }
set { _pos = value; }
}
@@ -278,16 +235,10 @@ namespace FlatBuffers
// the buffer position and length.
#if ENABLE_SPAN_T
public T[] ToArray<T>(int pos, int len)
where T: struct
where T : struct
{
unsafe
{
AssertOffsetAndLength(pos, len);
T[] arr = new T[len];
var typed = MemoryMarshal.Cast<byte, T>(new Span<byte>(_buffer.Buffer + pos, _buffer.Length));
typed.Slice(0, arr.Length).CopyTo(arr);
return arr;
}
AssertOffsetAndLength(pos, len);
return MemoryMarshal.Cast<byte, T>(_buffer.ReadOnlySpan.Slice(pos)).Slice(0, len).ToArray();
}
#else
public T[] ToArray<T>(int pos, int len)
@@ -295,7 +246,7 @@ namespace FlatBuffers
{
AssertOffsetAndLength(pos, len);
T[] arr = new T[len];
Buffer.BlockCopy(_buffer.ByteArray, pos, arr, 0, ArraySize(arr));
Buffer.BlockCopy(_buffer.Buffer, pos, arr, 0, ArraySize(arr));
return arr;
}
#endif
@@ -310,23 +261,30 @@ namespace FlatBuffers
return ToArray<byte>(0, Length);
}
#if ENABLE_SPAN_T
public unsafe Span<byte> ToSpan(int pos, int len)
public ReadOnlyMemory<byte> ToReadOnlyMemory(int pos, int len)
{
return new Span<byte>(_buffer.Buffer, _buffer.Length).Slice(pos, len);
return _buffer.ReadOnlyMemory.Slice(pos, len);
}
public Memory<byte> ToMemory(int pos, int len)
{
return _buffer.Memory.Slice(pos, len);
}
public Span<byte> ToSpan(int pos, int len)
{
return _buffer.Span.Slice(pos, len);
}
#else
public ArraySegment<byte> ToArraySegment(int pos, int len)
{
return new ArraySegment<byte>(_buffer.ByteArray, pos, len);
return new ArraySegment<byte>(_buffer.Buffer, pos, len);
}
#endif
#if !ENABLE_SPAN_T
public MemoryStream ToMemoryStream(int pos, int len)
{
return new MemoryStream(_buffer.ByteArray, pos, len);
return new MemoryStream(_buffer.Buffer, pos, len);
}
#endif
@@ -391,15 +349,15 @@ namespace FlatBuffers
{
for (int i = 0; i < count; i++)
{
r |= (ulong)_buffer.Buffer[offset + i] << i * 8;
r |= (ulong)_buffer.Buffer[offset + i] << i * 8;
}
}
else
{
for (int i = 0; i < count; i++)
{
r |= (ulong)_buffer.Buffer[offset + count - 1 - i] << i * 8;
}
for (int i = 0; i < count; i++)
{
r |= (ulong)_buffer.Buffer[offset + count - 1 - i] << i * 8;
}
}
return r;
}
@@ -414,31 +372,26 @@ namespace FlatBuffers
#endif
}
#if UNSAFE_BYTEBUFFER
#if ENABLE_SPAN_T
public unsafe void PutSbyte(int offset, sbyte value)
public void PutSbyte(int offset, sbyte value)
{
AssertOffsetAndLength(offset, sizeof(sbyte));
_buffer.Buffer[offset] = (byte)value;
_buffer.Span[offset] = (byte)value;
}
public unsafe void PutByte(int offset, byte value)
public void PutByte(int offset, byte value)
{
AssertOffsetAndLength(offset, sizeof(byte));
_buffer.Buffer[offset] = value;
_buffer.Span[offset] = value;
}
public unsafe void PutByte(int offset, byte value, int count)
public void PutByte(int offset, byte value, int count)
{
AssertOffsetAndLength(offset, sizeof(byte) * count);
for (var i = 0; i < count; ++i)
_buffer.Buffer[offset + i] = value;
}
// this method exists in order to conform with Java ByteBuffer standards
public void Put(int offset, byte value)
{
PutByte(offset, value);
Span<byte> span = _buffer.Span.Slice(offset, count);
for (var i = 0; i < span.Length; ++i)
span[i] = value;
}
#else
public void PutSbyte(int offset, sbyte value)
@@ -459,13 +412,13 @@ namespace FlatBuffers
for (var i = 0; i < count; ++i)
_buffer.Buffer[offset + i] = value;
}
#endif
// this method exists in order to conform with Java ByteBuffer standards
public void Put(int offset, byte value)
{
PutByte(offset, value);
}
#endif
#if ENABLE_SPAN_T
public unsafe void PutStringUTF8(int offset, string value)
@@ -473,7 +426,10 @@ namespace FlatBuffers
AssertOffsetAndLength(offset, value.Length);
fixed (char* s = value)
{
Encoding.UTF8.GetBytes(s, value.Length, _buffer.Buffer + offset, Length - offset);
fixed (byte* buffer = &MemoryMarshal.GetReference(_buffer.Span))
{
Encoding.UTF8.GetBytes(s, value.Length, buffer + offset, Length - offset);
}
}
}
#else
@@ -481,7 +437,7 @@ namespace FlatBuffers
{
AssertOffsetAndLength(offset, value.Length);
Encoding.UTF8.GetBytes(value, 0, value.Length,
_buffer.ByteArray, offset);
_buffer.Buffer, offset);
}
#endif
@@ -495,10 +451,17 @@ namespace FlatBuffers
public unsafe void PutUshort(int offset, ushort value)
{
AssertOffsetAndLength(offset, sizeof(ushort));
byte* ptr = _buffer.Buffer;
*(ushort*)(ptr + offset) = BitConverter.IsLittleEndian
? value
: ReverseBytes(value);
#if ENABLE_SPAN_T
Span<byte> span = _buffer.Span.Slice(offset);
BinaryPrimitives.WriteUInt16LittleEndian(span, value);
#else
fixed (byte* ptr = _buffer.Buffer)
{
*(ushort*)(ptr + offset) = BitConverter.IsLittleEndian
? value
: ReverseBytes(value);
}
#endif
}
public void PutInt(int offset, int value)
@@ -509,10 +472,17 @@ namespace FlatBuffers
public unsafe void PutUint(int offset, uint value)
{
AssertOffsetAndLength(offset, sizeof(uint));
byte* ptr = _buffer.Buffer;
*(uint*)(ptr + offset) = BitConverter.IsLittleEndian
? value
: ReverseBytes(value);
#if ENABLE_SPAN_T
Span<byte> span = _buffer.Span.Slice(offset);
BinaryPrimitives.WriteUInt32LittleEndian(span, value);
#else
fixed (byte* ptr = _buffer.Buffer)
{
*(uint*)(ptr + offset) = BitConverter.IsLittleEndian
? value
: ReverseBytes(value);
}
#endif
}
public unsafe void PutLong(int offset, long value)
@@ -523,38 +493,56 @@ namespace FlatBuffers
public unsafe void PutUlong(int offset, ulong value)
{
AssertOffsetAndLength(offset, sizeof(ulong));
byte* ptr = _buffer.Buffer;
*(ulong*)(ptr + offset) = BitConverter.IsLittleEndian
? value
: ReverseBytes(value);
#if ENABLE_SPAN_T
Span<byte> span = _buffer.Span.Slice(offset);
BinaryPrimitives.WriteUInt64LittleEndian(span, value);
#else
fixed (byte* ptr = _buffer.Buffer)
{
*(ulong*)(ptr + offset) = BitConverter.IsLittleEndian
? value
: ReverseBytes(value);
}
#endif
}
public unsafe void PutFloat(int offset, float value)
{
AssertOffsetAndLength(offset, sizeof(float));
byte* ptr = _buffer.Buffer;
if (BitConverter.IsLittleEndian)
#if ENABLE_SPAN_T
fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.Span))
#else
fixed (byte* ptr = _buffer.Buffer)
#endif
{
*(float*)(ptr + offset) = value;
}
else
{
*(uint*)(ptr + offset) = ReverseBytes(*(uint*)(&value));
if (BitConverter.IsLittleEndian)
{
*(float*)(ptr + offset) = value;
}
else
{
*(uint*)(ptr + offset) = ReverseBytes(*(uint*)(&value));
}
}
}
public unsafe void PutDouble(int offset, double value)
{
AssertOffsetAndLength(offset, sizeof(double));
byte* ptr = _buffer.Buffer;
if (BitConverter.IsLittleEndian)
#if ENABLE_SPAN_T
fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.Span))
#else
fixed (byte* ptr = _buffer.Buffer)
#endif
{
*(double*)(ptr + offset) = value;
}
else
{
*(ulong*)(ptr + offset) = ReverseBytes(*(ulong*)(ptr + offset));
if (BitConverter.IsLittleEndian)
{
*(double*)(ptr + offset) = value;
}
else
{
*(ulong*)(ptr + offset) = ReverseBytes(*(ulong*)(&value));
}
}
}
#else // !UNSAFE_BYTEBUFFER
@@ -613,17 +601,17 @@ namespace FlatBuffers
#endif // UNSAFE_BYTEBUFFER
#if UNSAFE_BYTEBUFFER
public unsafe sbyte GetSbyte(int index)
#if ENABLE_SPAN_T
public sbyte GetSbyte(int index)
{
AssertOffsetAndLength(index, sizeof(sbyte));
return (sbyte)_buffer.Buffer[index];
return (sbyte)_buffer.ReadOnlySpan[index];
}
public unsafe byte Get(int index)
public byte Get(int index)
{
AssertOffsetAndLength(index, sizeof(byte));
return _buffer.Buffer[index];
return _buffer.ReadOnlySpan[index];
}
#else
public sbyte GetSbyte(int index)
@@ -642,12 +630,15 @@ namespace FlatBuffers
#if ENABLE_SPAN_T
public unsafe string GetStringUTF8(int startPos, int len)
{
return Encoding.UTF8.GetString(_buffer.Buffer + startPos, len);
fixed (byte* buffer = &MemoryMarshal.GetReference(_buffer.ReadOnlySpan.Slice(startPos)))
{
return Encoding.UTF8.GetString(buffer, len);
}
}
#else
public string GetStringUTF8(int startPos, int len)
{
return Encoding.UTF8.GetString(_buffer.ByteArray, startPos, len);
return Encoding.UTF8.GetString(_buffer.Buffer, startPos, len);
}
#endif
@@ -661,12 +652,17 @@ namespace FlatBuffers
public unsafe ushort GetUshort(int offset)
{
AssertOffsetAndLength(offset, sizeof(ushort));
byte* ptr = _buffer.Buffer;
#if ENABLE_SPAN_T
ReadOnlySpan<byte> span = _buffer.ReadOnlySpan.Slice(offset);
return BinaryPrimitives.ReadUInt16LittleEndian(span);
#else
fixed (byte* ptr = _buffer.Buffer)
{
return BitConverter.IsLittleEndian
? *(ushort*)(ptr + offset)
: ReverseBytes(*(ushort*)(ptr + offset));
}
#endif
}
public int GetInt(int offset)
@@ -677,12 +673,17 @@ namespace FlatBuffers
public unsafe uint GetUint(int offset)
{
AssertOffsetAndLength(offset, sizeof(uint));
byte* ptr = _buffer.Buffer;
#if ENABLE_SPAN_T
ReadOnlySpan<byte> span = _buffer.ReadOnlySpan.Slice(offset);
return BinaryPrimitives.ReadUInt32LittleEndian(span);
#else
fixed (byte* ptr = _buffer.Buffer)
{
return BitConverter.IsLittleEndian
? *(uint*)(ptr + offset)
: ReverseBytes(*(uint*)(ptr + offset));
}
#endif
}
public long GetLong(int offset)
@@ -693,18 +694,27 @@ namespace FlatBuffers
public unsafe ulong GetUlong(int offset)
{
AssertOffsetAndLength(offset, sizeof(ulong));
byte* ptr = _buffer.Buffer;
#if ENABLE_SPAN_T
ReadOnlySpan<byte> span = _buffer.ReadOnlySpan.Slice(offset);
return BinaryPrimitives.ReadUInt64LittleEndian(span);
#else
fixed (byte* ptr = _buffer.Buffer)
{
return BitConverter.IsLittleEndian
? *(ulong*)(ptr + offset)
: ReverseBytes(*(ulong*)(ptr + offset));
}
#endif
}
public unsafe float GetFloat(int offset)
{
AssertOffsetAndLength(offset, sizeof(float));
byte* ptr = _buffer.Buffer;
#if ENABLE_SPAN_T
fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.ReadOnlySpan))
#else
fixed (byte* ptr = _buffer.Buffer)
#endif
{
if (BitConverter.IsLittleEndian)
{
@@ -721,7 +731,11 @@ namespace FlatBuffers
public unsafe double GetDouble(int offset)
{
AssertOffsetAndLength(offset, sizeof(double));
byte* ptr = _buffer.Buffer;
#if ENABLE_SPAN_T
fixed (byte* ptr = &MemoryMarshal.GetReference(_buffer.ReadOnlySpan))
#else
fixed (byte* ptr = _buffer.Buffer)
#endif
{
if (BitConverter.IsLittleEndian)
{
@@ -758,7 +772,7 @@ namespace FlatBuffers
public long GetLong(int index)
{
return (long)ReadLittleEndian(index, sizeof(long));
return (long)ReadLittleEndian(index, sizeof(long));
}
public ulong GetUlong(int index)
@@ -819,12 +833,9 @@ namespace FlatBuffers
AssertOffsetAndLength(offset, numBytes);
// if we are LE, just do a block copy
#if ENABLE_SPAN_T
unsafe
{
MemoryMarshal.Cast<T, byte>(x).CopyTo(new Span<byte>(_buffer.Buffer, _buffer.Length).Slice(offset, numBytes));
}
MemoryMarshal.Cast<T, byte>(x).CopyTo(_buffer.Span.Slice(offset, numBytes));
#else
Buffer.BlockCopy(x, 0, _buffer.ByteArray, offset, numBytes);
Buffer.BlockCopy(x, 0, _buffer.Buffer, offset, numBytes);
#endif
}
else
@@ -841,7 +852,7 @@ namespace FlatBuffers
}
#if ENABLE_SPAN_T
public unsafe int Put<T>(int offset, Span<T> x)
public int Put<T>(int offset, Span<T> x)
where T : struct
{
if (x.Length == 0)
@@ -861,7 +872,7 @@ namespace FlatBuffers
offset -= numBytes;
AssertOffsetAndLength(offset, numBytes);
// if we are LE, just do a block copy
MemoryMarshal.Cast<T, byte>(x).CopyTo(new Span<byte>(_buffer.Buffer, _buffer.Length).Slice(offset, numBytes));
MemoryMarshal.Cast<T, byte>(x).CopyTo(_buffer.Span.Slice(offset, numBytes));
}
else
{

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Properties\**" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Remove="Properties\**" />
</ItemGroup>
<ItemGroup>
<None Remove="Properties\**" />
</ItemGroup>
</Project>

View File

@@ -1,16 +1,54 @@
<Project Sdk="Microsoft.NET.Sdk">
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<TargetFrameworks>netstandard1.1;netstandard1.4;netstandard2.0</TargetFrameworks>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{28C00774-1E73-4A75-AD8F-844CD21A064D}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>FlatBuffers</RootNamespace>
<AssemblyName>FlatBuffers</AssemblyName>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<Copyright>Copyright (c) 2015 Google Inc</Copyright>
<RepositoryUrl>https://github.com/google/flatbuffers</RepositoryUrl>
<PackageLicenseUrl>https://github.com/google/flatbuffers/blob/master/LICENSE.txt</PackageLicenseUrl>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Memory" Version="4.5.1" />
<Reference Include="System" />
<Reference Include="System.Core" />
</ItemGroup>
<ItemGroup>
<Compile Include="ByteBuffer.cs" />
<Compile Include="FlatBufferBuilder.cs" />
<Compile Include="FlatBufferConstants.cs" />
<Compile Include="IFlatbufferObject.cs" />
<Compile Include="Offset.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Struct.cs" />
<Compile Include="Table.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -0,0 +1,52 @@
/*
* 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.
*/
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("FlatBuffers")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("FlatBuffers")]
[assembly: AssemblyCopyright("Copyright (c) 2015 Google Inc")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("91c32e64-ef20-47df-9c9f-cec9207bc6df")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -1,8 +1,11 @@
{
"name": "flatbuffers",
"version": "1.10.0",
"version": "1.11.0",
"description": "Memory Efficient Serialization Library",
"files": ["js/flatbuffers.js", "js/flatbuffers.mjs"],
"files": [
"js/flatbuffers.js",
"js/flatbuffers.mjs"
],
"main": "js/flatbuffers",
"module": "js/flatbuffers.mjs",
"directories": {
@@ -11,7 +14,7 @@
},
"scripts": {
"test": "tests/JavaScriptTest.sh",
"append-esm-export": "sed \"s/this.flatbuffers = flatbuffers;/export { flatbuffers };/\" js/flatbuffers.js >> js/flatbuffers.mjs",
"append-esm-export": "sed \"s/this.flatbuffers = flatbuffers;/export { flatbuffers };/\" js/flatbuffers.js > js/flatbuffers.mjs",
"prepublishOnly": "npm run append-esm-export"
},
"repository": {
@@ -26,5 +29,6 @@
"bugs": {
"url": "https://github.com/google/flatbuffers/issues"
},
"homepage": "https://google.github.io/flatbuffers/"
"homepage": "https://google.github.io/flatbuffers/",
"dependencies": {}
}

View File

@@ -21,7 +21,7 @@
namespace Google\FlatBuffers;
class FlatbufferBuilder
final class FlatbufferBuilder
{
/**
* Internal ByteBuffer for the FlatBuffer data.
@@ -278,6 +278,15 @@ class FlatbufferBuilder
{
$this->bb->putDouble($this->space -= 8, $x);
}
/**
* @param $off
*/
public function putOffset($off)
{
$new_off = $this->offset() - $off + Constants::SIZEOF_INT;
$this->putInt($new_off);
}
/// @endcond
/**
@@ -562,9 +571,7 @@ class FlatbufferBuilder
if ($off > $this->offset()) {
throw new \Exception("");
}
$off = $this->offset() - $off + Constants::SIZEOF_INT;
$this->putInt($off);
$this->putOffset($off);
}
/// @cond FLATBUFFERS_INTERNAL

11
pom.xml
View File

@@ -1,11 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-java</artifactId>
<version>1.10.0</version>
<version>1.11.0</version>
<packaging>bundle</packaging>
<name>FlatBuffers Java API</name>
<description>
@@ -32,6 +30,7 @@
<connection>
scm:git:https://github.com/google/flatbuffers.git
</connection>
<tag>1.11.0</tag>
</scm>
<dependencies>
</dependencies>
@@ -78,6 +77,10 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.9.1</version>
<configuration>
<additionalparam>-Xdoclint:none</additionalparam>
<additionalOptions>-Xdoclint:none</additionalOptions>
</configuration>
<executions>
<execution>
<id>attach-javadocs</id>

View File

@@ -21,8 +21,9 @@ from . import packer
from . import compat
from .compat import range_func
from .compat import memoryview_type
from .compat import import_numpy, NumpyRequiredForThisFeature
np = import_numpy()
## @file
## @addtogroup flatbuffers_python_api
## @{
@@ -441,6 +442,41 @@ class Builder(object):
return self.EndVector(len(x))
def CreateNumpyVector(self, x):
"""CreateNumpyVector writes a numpy array into the buffer."""
if np is None:
# Numpy is required for this feature
raise NumpyRequiredForThisFeature("Numpy was not found.")
if not isinstance(x, np.ndarray):
raise TypeError("non-numpy-ndarray passed to CreateNumpyVector")
if x.dtype.kind not in ['b', 'i', 'u', 'f']:
raise TypeError("numpy-ndarray holds elements of unsupported datatype")
if x.ndim > 1:
raise TypeError("multidimensional-ndarray passed to CreateNumpyVector")
self.StartVector(x.itemsize, x.size, x.dtype.alignment)
# Ensure little endian byte ordering
if x.dtype.str[0] == "<":
x_lend = x
else:
x_lend = x.byteswap(inplace=False)
# Calculate total length
l = UOffsetTFlags.py_type(x_lend.itemsize * x_lend.size)
## @cond FLATBUFFERS_INTERNAL
self.head = UOffsetTFlags.py_type(self.Head() - l)
## @endcond
# tobytes ensures c_contiguous ordering
self.Bytes[self.Head():self.Head()+l] = x_lend.tobytes(order='C')
return self.EndVector(x.size)
## @cond FLATBUFFERS_INTERNAL
def assertNested(self):
"""

View File

@@ -15,4 +15,4 @@
set buildtype=Release
if "%1"=="-b" set buildtype=%2
..\%buildtype%\flatc.exe --cpp --no-prefix -o ../include/flatbuffers reflection.fbs
..\%buildtype%\flatc.exe --cpp --no-prefix -o ../include/flatbuffers reflection.fbs || exit /b 1

View File

@@ -13,5 +13,6 @@
# 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
../flatc -c --no-prefix -o ../include/flatbuffers reflection.fbs

View File

@@ -1,6 +1,6 @@
[package]
name = "flatbuffers"
version = "0.5.0"
version = "0.6.0"
authors = ["Robert Winslow <hello@rwinslow.com>", "FlatBuffers Maintainers"]
license = "Apache-2.0"
description = "Official FlatBuffers Rust runtime library."

View File

@@ -29,6 +29,8 @@ use vtable::{VTable, field_index_to_field_offset};
use vtable_writer::VTableWriter;
use vector::{SafeSliceAccess, Vector};
pub const N_SMALLVEC_STRING_VECTOR_CAPACITY: usize = 16;
#[derive(Clone, Copy, Debug)]
struct FieldLoc {
off: UOffsetT,
@@ -268,10 +270,12 @@ impl<'fbb> FlatBufferBuilder<'fbb> {
#[inline]
pub fn create_vector_of_strings<'a, 'b>(&'a mut self, xs: &'b [&'b str]) -> WIPOffset<Vector<'fbb, ForwardsUOffset<&'fbb str>>> {
self.assert_not_nested("create_vector_of_strings can not be called when a table or vector is under construction");
// internally, smallvec can be a stack-allocated or heap-allocated vector.
// we expect it to usually be stack-allocated.
let mut offsets: smallvec::SmallVec<[WIPOffset<&str>; 0]> = smallvec::SmallVec::with_capacity(xs.len());
// internally, smallvec can be a stack-allocated or heap-allocated vector:
// if xs.len() > N_SMALLVEC_STRING_VECTOR_CAPACITY then it will overflow to the heap.
let mut offsets: smallvec::SmallVec<[WIPOffset<&str>; N_SMALLVEC_STRING_VECTOR_CAPACITY]> = smallvec::SmallVec::with_capacity(xs.len());
unsafe { offsets.set_len(xs.len()); }
// note that this happens in reverse, because the buffer is built back-to-front:
for (i, &s) in xs.iter().enumerate().rev() {
let o = self.create_string(s);
offsets[i] = o;

View File

@@ -88,7 +88,7 @@ impl EndianScalar for f32 {
}
#[cfg(not(target_endian = "little"))]
{
byte_swap_f32(&self)
byte_swap_f32(self)
}
}
/// Convert f32 from little-endian to host endian-ness.
@@ -100,7 +100,7 @@ impl EndianScalar for f32 {
}
#[cfg(not(target_endian = "little"))]
{
byte_swap_f32(&self)
byte_swap_f32(self)
}
}
}
@@ -115,7 +115,7 @@ impl EndianScalar for f64 {
}
#[cfg(not(target_endian = "little"))]
{
byte_swap_f64(&self)
byte_swap_f64(self)
}
}
/// Convert f64 from little-endian to host endian-ness.
@@ -127,7 +127,7 @@ impl EndianScalar for f64 {
}
#[cfg(not(target_endian = "little"))]
{
byte_swap_f64(&self)
byte_swap_f64(self)
}
}
}

View File

@@ -19,7 +19,9 @@ use std::mem::size_of;
use std::slice::from_raw_parts;
use std::str::from_utf8_unchecked;
use endian_scalar::{EndianScalar, read_scalar};
#[cfg(target_endian = "little")]
use endian_scalar::EndianScalar;
use endian_scalar::read_scalar;
use follow::Follow;
use primitives::*;
@@ -85,6 +87,7 @@ mod le_safe_slice_impls {
impl super::SafeSliceAccess for f64 {}
}
#[cfg(target_endian = "little")]
pub use self::le_safe_slice_impls::*;
pub fn follow_cast_ref<'a, T: Sized + 'a>(buf: &'a [u8], loc: usize) -> &'a T {
@@ -104,6 +107,7 @@ impl<'a> Follow<'a> for &'a str {
}
}
#[cfg(target_endian = "little")]
fn follow_slice_helper<T>(buf: &[u8], loc: usize) -> &[T] {
let sz = size_of::<T>();
debug_assert!(sz > 0);

View File

@@ -66,7 +66,7 @@ android {
ndkBuild {
targets "FlatBufferSample"
arguments "-j" + Runtime.getRuntime().availableProcessors()
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
abiFilters "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
}
}
}

View File

@@ -42,7 +42,7 @@ fi
echo Compiling and running the C# sample.
# Compile and execute the sample.
csc SampleBinary.cs MyGame/Sample/*.cs ../net/FlatBuffers/*.cs
mcs SampleBinary.cs MyGame/Sample/*.cs ../net/FlatBuffers/*.cs
mono SampleBinary.exe
# Cleanup temporary files.

BIN
samples/monster.bfbs Normal file

Binary file not shown.

View File

@@ -22,6 +22,7 @@ table Monster {
color:Color = Blue;
weapons:[Weapon];
equipped:Equipment;
path:[Vec3];
}
table Weapon {

View File

@@ -18,8 +18,11 @@ struct Weapon;
struct WeaponT;
bool operator==(const Vec3 &lhs, const Vec3 &rhs);
bool operator!=(const Vec3 &lhs, const Vec3 &rhs);
bool operator==(const MonsterT &lhs, const MonsterT &rhs);
bool operator!=(const MonsterT &lhs, const MonsterT &rhs);
bool operator==(const WeaponT &lhs, const WeaponT &rhs);
bool operator!=(const WeaponT &lhs, const WeaponT &rhs);
inline const flatbuffers::TypeTable *Vec3TypeTable();
@@ -55,7 +58,8 @@ inline const char * const *EnumNamesColor() {
}
inline const char *EnumNameColor(Color e) {
const size_t index = static_cast<int>(e);
if (e < Color_Red || e > Color_Blue) return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesColor()[index];
}
@@ -84,7 +88,8 @@ inline const char * const *EnumNamesEquipment() {
}
inline const char *EnumNameEquipment(Equipment e) {
const size_t index = static_cast<int>(e);
if (e < Equipment_NONE || e > Equipment_Weapon) return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesEquipment()[index];
}
@@ -116,10 +121,11 @@ struct EquipmentUnion {
#ifndef FLATBUFFERS_CPP98_STL
template <typename T>
void Set(T&& val) {
using RT = typename std::remove_reference<T>::type;
Reset();
type = EquipmentTraits<typename T::TableType>::enum_value;
type = EquipmentTraits<typename RT::TableType>::enum_value;
if (type != Equipment_NONE) {
value = new T(std::forward<T>(val));
value = new RT(std::forward<T>(val));
}
}
#endif // FLATBUFFERS_CPP98_STL
@@ -153,6 +159,11 @@ inline bool operator==(const EquipmentUnion &lhs, const EquipmentUnion &rhs) {
}
}
}
inline bool operator!=(const EquipmentUnion &lhs, const EquipmentUnion &rhs) {
return !(lhs == rhs);
}
bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *obj, Equipment type);
bool VerifyEquipmentVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
@@ -163,8 +174,11 @@ FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(4) Vec3 FLATBUFFERS_FINAL_CLASS {
float z_;
public:
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
return Vec3TypeTable();
}
Vec3() {
memset(this, 0, sizeof(Vec3));
memset(static_cast<void *>(this), 0, sizeof(Vec3));
}
Vec3(float _x, float _y, float _z)
: x_(flatbuffers::EndianScalar(_x)),
@@ -199,6 +213,11 @@ inline bool operator==(const Vec3 &lhs, const Vec3 &rhs) {
(lhs.z() == rhs.z());
}
inline bool operator!=(const Vec3 &lhs, const Vec3 &rhs) {
return !(lhs == rhs);
}
struct MonsterT : public flatbuffers::NativeTable {
typedef Monster TableType;
flatbuffers::unique_ptr<Vec3> pos;
@@ -209,6 +228,7 @@ struct MonsterT : public flatbuffers::NativeTable {
Color color;
std::vector<flatbuffers::unique_ptr<WeaponT>> weapons;
EquipmentUnion equipped;
std::vector<Vec3> path;
MonsterT()
: mana(150),
hp(100),
@@ -225,15 +245,21 @@ inline bool operator==(const MonsterT &lhs, const MonsterT &rhs) {
(lhs.inventory == rhs.inventory) &&
(lhs.color == rhs.color) &&
(lhs.weapons == rhs.weapons) &&
(lhs.equipped == rhs.equipped);
(lhs.equipped == rhs.equipped) &&
(lhs.path == rhs.path);
}
inline bool operator!=(const MonsterT &lhs, const MonsterT &rhs) {
return !(lhs == rhs);
}
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef MonsterT NativeTableType;
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
return MonsterTypeTable();
}
enum {
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_POS = 4,
VT_MANA = 6,
VT_HP = 8,
@@ -242,7 +268,8 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_COLOR = 16,
VT_WEAPONS = 18,
VT_EQUIPPED_TYPE = 20,
VT_EQUIPPED = 22
VT_EQUIPPED = 22,
VT_PATH = 24
};
const Vec3 *pos() const {
return GetStruct<const Vec3 *>(VT_POS);
@@ -302,6 +329,12 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
void *mutable_equipped() {
return GetPointer<void *>(VT_EQUIPPED);
}
const flatbuffers::Vector<const Vec3 *> *path() const {
return GetPointer<const flatbuffers::Vector<const Vec3 *> *>(VT_PATH);
}
flatbuffers::Vector<const Vec3 *> *mutable_path() {
return GetPointer<flatbuffers::Vector<const Vec3 *> *>(VT_PATH);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<Vec3>(verifier, VT_POS) &&
@@ -318,6 +351,8 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyField<uint8_t>(verifier, VT_EQUIPPED_TYPE) &&
VerifyOffset(verifier, VT_EQUIPPED) &&
VerifyEquipment(verifier, equipped(), equipped_type()) &&
VerifyOffset(verifier, VT_PATH) &&
verifier.VerifyVector(path()) &&
verifier.EndTable();
}
MonsterT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
@@ -359,6 +394,9 @@ struct MonsterBuilder {
void add_equipped(flatbuffers::Offset<void> equipped) {
fbb_.AddOffset(Monster::VT_EQUIPPED, equipped);
}
void add_path(flatbuffers::Offset<flatbuffers::Vector<const Vec3 *>> path) {
fbb_.AddOffset(Monster::VT_PATH, path);
}
explicit MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
@@ -381,8 +419,10 @@ inline flatbuffers::Offset<Monster> CreateMonster(
Color color = Color_Blue,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Weapon>>> weapons = 0,
Equipment equipped_type = Equipment_NONE,
flatbuffers::Offset<void> equipped = 0) {
flatbuffers::Offset<void> equipped = 0,
flatbuffers::Offset<flatbuffers::Vector<const Vec3 *>> path = 0) {
MonsterBuilder builder_(_fbb);
builder_.add_path(path);
builder_.add_equipped(equipped);
builder_.add_weapons(weapons);
builder_.add_inventory(inventory);
@@ -405,18 +445,24 @@ inline flatbuffers::Offset<Monster> CreateMonsterDirect(
Color color = Color_Blue,
const std::vector<flatbuffers::Offset<Weapon>> *weapons = nullptr,
Equipment equipped_type = Equipment_NONE,
flatbuffers::Offset<void> equipped = 0) {
flatbuffers::Offset<void> equipped = 0,
const std::vector<Vec3> *path = nullptr) {
auto name__ = name ? _fbb.CreateString(name) : 0;
auto inventory__ = inventory ? _fbb.CreateVector<uint8_t>(*inventory) : 0;
auto weapons__ = weapons ? _fbb.CreateVector<flatbuffers::Offset<Weapon>>(*weapons) : 0;
auto path__ = path ? _fbb.CreateVectorOfStructs<Vec3>(*path) : 0;
return MyGame::Sample::CreateMonster(
_fbb,
pos,
mana,
hp,
name ? _fbb.CreateString(name) : 0,
inventory ? _fbb.CreateVector<uint8_t>(*inventory) : 0,
name__,
inventory__,
color,
weapons ? _fbb.CreateVector<flatbuffers::Offset<Weapon>>(*weapons) : 0,
weapons__,
equipped_type,
equipped);
equipped,
path__);
}
flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
@@ -436,12 +482,17 @@ inline bool operator==(const WeaponT &lhs, const WeaponT &rhs) {
(lhs.damage == rhs.damage);
}
inline bool operator!=(const WeaponT &lhs, const WeaponT &rhs) {
return !(lhs == rhs);
}
struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef WeaponT NativeTableType;
static const flatbuffers::TypeTable *MiniReflectTypeTable() {
return WeaponTypeTable();
}
enum {
enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE {
VT_NAME = 4,
VT_DAMAGE = 6
};
@@ -504,9 +555,10 @@ inline flatbuffers::Offset<Weapon> CreateWeaponDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const char *name = nullptr,
int16_t damage = 0) {
auto name__ = name ? _fbb.CreateString(name) : 0;
return MyGame::Sample::CreateWeapon(
_fbb,
name ? _fbb.CreateString(name) : 0,
name__,
damage);
}
@@ -530,6 +582,7 @@ inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function
{ auto _e = weapons(); if (_e) { _o->weapons.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->weapons[_i] = flatbuffers::unique_ptr<WeaponT>(_e->Get(_i)->UnPack(_resolver)); } } };
{ auto _e = equipped_type(); _o->equipped.type = _e; };
{ auto _e = equipped(); if (_e) _o->equipped.value = EquipmentUnion::UnPack(_e, equipped_type(), _resolver); };
{ auto _e = path(); if (_e) { _o->path.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->path[_i] = *_e->Get(_i); } } };
}
inline flatbuffers::Offset<Monster> Monster::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -549,6 +602,7 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder
auto _weapons = _o->weapons.size() ? _fbb.CreateVector<flatbuffers::Offset<Weapon>> (_o->weapons.size(), [](size_t i, _VectorArgs *__va) { return CreateWeapon(*__va->__fbb, __va->__o->weapons[i].get(), __va->__rehasher); }, &_va ) : 0;
auto _equipped_type = _o->equipped.type;
auto _equipped = _o->equipped.Pack(_fbb);
auto _path = _o->path.size() ? _fbb.CreateVectorOfStructs(_o->path) : 0;
return MyGame::Sample::CreateMonster(
_fbb,
_pos,
@@ -559,7 +613,8 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder
_color,
_weapons,
_equipped_type,
_equipped);
_equipped,
_path);
}
inline WeaponT *Weapon::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
@@ -704,7 +759,7 @@ inline const flatbuffers::TypeTable *Vec3TypeTable() {
{ flatbuffers::ET_FLOAT, 0, -1 },
{ flatbuffers::ET_FLOAT, 0, -1 }
};
static const int32_t values[] = { 0, 4, 8, 12 };
static const int64_t values[] = { 0, 4, 8, 12 };
static const char * const names[] = {
"x",
"y",
@@ -727,7 +782,8 @@ inline const flatbuffers::TypeTable *MonsterTypeTable() {
{ flatbuffers::ET_CHAR, 0, 1 },
{ flatbuffers::ET_SEQUENCE, 1, 2 },
{ flatbuffers::ET_UTYPE, 0, 3 },
{ flatbuffers::ET_SEQUENCE, 0, 3 }
{ flatbuffers::ET_SEQUENCE, 0, 3 },
{ flatbuffers::ET_SEQUENCE, 1, 0 }
};
static const flatbuffers::TypeFunction type_refs[] = {
Vec3TypeTable,
@@ -745,10 +801,11 @@ inline const flatbuffers::TypeTable *MonsterTypeTable() {
"color",
"weapons",
"equipped_type",
"equipped"
"equipped",
"path"
};
static const flatbuffers::TypeTable tt = {
flatbuffers::ST_TABLE, 10, type_codes, type_refs, nullptr, names
flatbuffers::ST_TABLE, 11, type_codes, type_refs, nullptr, names
};
return &tt;
}

View File

@@ -58,11 +58,15 @@ struct Monster : flatbuffers_handle
buf_.flatbuffers_field_int8(pos_, 20, 0)
def equipped_as_Weapon():
MyGame_Sample_Weapon { buf_, buf_.flatbuffers_field_table(pos_, 22) }
def path(i:int):
MyGame_Sample_Vec3 { buf_, buf_.flatbuffers_field_vector(pos_, 24) + i * 12 }
def path_length():
buf_.flatbuffers_field_vector_len(pos_, 24)
def GetRootAsMonster(buf:string): Monster { buf, buf.flatbuffers_indirect(0) }
def MonsterStart(b_:flatbuffers_builder):
b_.StartObject(10)
b_.StartObject(11)
def MonsterAddPos(b_:flatbuffers_builder, pos:int):
b_.PrependStructSlot(0, pos, 0)
def MonsterAddMana(b_:flatbuffers_builder, mana:int):
@@ -93,6 +97,10 @@ def MonsterAddEquippedType(b_:flatbuffers_builder, equipped_type:int):
b_.PrependUint8Slot(8, equipped_type, 0)
def MonsterAddEquipped(b_:flatbuffers_builder, equipped:int):
b_.PrependUOffsetTRelativeSlot(9, equipped, 0)
def MonsterAddPath(b_:flatbuffers_builder, path:int):
b_.PrependUOffsetTRelativeSlot(10, path, 0)
def MonsterStartPathVector(b_:flatbuffers_builder, n_:int):
b_.StartVector(12, n_, 4)
def MonsterEnd(b_:flatbuffers_builder):
b_.EndObject()

78
samples/sample_bfbs.cpp Normal file
View File

@@ -0,0 +1,78 @@
/*
* 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.
*/
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include "monster_test_generated.h"
#include "monster_generated.h" // Already includes "flatbuffers/flatbuffers.h".
using namespace MyGame::Sample;
// This is an example of parsing text straight into a buffer and then
// generating flatbuffer (JSON) text from the buffer.
int main(int /*argc*/, const char * /*argv*/[]) {
// load FlatBuffer schema (.fbs) and JSON from disk
std::string schema_file;
std::string json_file;
std::string bfbs_file;
bool ok =
flatbuffers::LoadFile("tests/monster_test.fbs", false, &schema_file) &&
flatbuffers::LoadFile("tests/monsterdata_test.golden", false, &json_file) &&
flatbuffers::LoadFile("tests/monster_test.bfbs", true, &bfbs_file);
if (!ok) {
printf("couldn't load files!\n");
return 1;
}
const char *include_directories[] = { "samples", "tests",
"tests/include_test", nullptr };
// parse fbs schema
flatbuffers::Parser parser1;
ok = parser1.Parse(schema_file.c_str(), include_directories);
assert(ok);
// inizialize parser by deserializing bfbs schema
flatbuffers::Parser parser2;
ok = parser2.Deserialize((uint8_t *)bfbs_file.c_str(), bfbs_file.length());
assert(ok);
// parse json in parser from fbs and bfbs
ok = parser1.Parse(json_file.c_str(), include_directories);
assert(ok);
ok = parser2.Parse(json_file.c_str(), include_directories);
assert(ok);
// to ensure it is correct, we now generate text back from the binary,
// and compare the two:
std::string jsongen1;
if (!GenerateText(parser1, parser1.builder_.GetBufferPointer(), &jsongen1)) {
printf("Couldn't serialize parsed data to JSON!\n");
return 1;
}
std::string jsongen2;
if (!GenerateText(parser2, parser2.builder_.GetBufferPointer(), &jsongen2)) {
printf("Couldn't serialize parsed data to JSON!\n");
return 1;
}
if (jsongen1 != jsongen2) {
printf("%s----------------\n%s", jsongen1.c_str(), jsongen2.c_str());
}
printf("The FlatBuffer has been parsed from JSON successfully.\n");
}

37
snap/snapcraft.yaml Normal file
View File

@@ -0,0 +1,37 @@
name: flatbuffers
base: core18
version: latest
version-script: git describe --always | sed -e 's/-/+git/;y/-/./' | tail -c +2
summary: FlatBuffers compiler
description: |
FlatBuffers compiler
NOTE: This snap also ships the necessary header files required to compile
projects using flatbuffers, however, for the compilation to work, you have
to manually add the following path in your project's configuration:
/snap/flatbuffers/current/include
If you need to use flatbuffers headers from a location other than the above
path, it is recommended to not use this snap as that could cause a mismatch.
grade: stable
confinement: strict
parts:
flatc:
plugin: cmake
source: .
configflags:
- -GUnix Makefiles
- -DCMAKE_BUILD_TYPE=Release
build-packages:
- g++
# used to set version number
- git
apps:
flatc:
command: flatc
plugs:
- home

View File

@@ -19,6 +19,8 @@
#include "flatbuffers/base.h"
#include "flatbuffers/util.h"
#include <cmath>
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable : 4127) // C4127: conditional expression is constant
@@ -157,6 +159,123 @@ void GenComment(const std::vector<std::string> &dc, std::string *code_ptr,
}
}
template<typename T>
std::string FloatConstantGenerator::GenFloatConstantImpl(
const FieldDef &field) const {
const auto &constant = field.value.constant;
T v;
auto done = StringToNumber(constant.c_str(), &v);
FLATBUFFERS_ASSERT(done);
if (done) {
#if (!defined(_MSC_VER) || (_MSC_VER >= 1800))
if (std::isnan(v)) return NaN(v);
if (std::isinf(v)) return Inf(v);
#endif
return Value(v, constant);
}
return "#"; // compile time error
}
std::string FloatConstantGenerator::GenFloatConstant(
const FieldDef &field) const {
switch (field.value.type.base_type) {
case BASE_TYPE_FLOAT: return GenFloatConstantImpl<float>(field);
case BASE_TYPE_DOUBLE: return GenFloatConstantImpl<double>(field);
default: {
FLATBUFFERS_ASSERT(false);
return "INVALID_BASE_TYPE";
}
};
}
TypedFloatConstantGenerator::TypedFloatConstantGenerator(
const char *double_prefix, const char *single_prefix,
const char *nan_number, const char *pos_inf_number,
const char *neg_inf_number)
: double_prefix_(double_prefix),
single_prefix_(single_prefix),
nan_number_(nan_number),
pos_inf_number_(pos_inf_number),
neg_inf_number_(neg_inf_number) {}
std::string TypedFloatConstantGenerator::MakeNaN(
const std::string &prefix) const {
return prefix + nan_number_;
}
std::string TypedFloatConstantGenerator::MakeInf(
bool neg, const std::string &prefix) const {
if (neg)
return !neg_inf_number_.empty() ? (prefix + neg_inf_number_)
: ("-" + prefix + pos_inf_number_);
else
return prefix + pos_inf_number_;
}
std::string TypedFloatConstantGenerator::Value(double v,
const std::string &src) const {
(void)v;
return src;
}
std::string TypedFloatConstantGenerator::Inf(double v) const {
return MakeInf(v < 0, double_prefix_);
}
std::string TypedFloatConstantGenerator::NaN(double v) const {
(void)v;
return MakeNaN(double_prefix_);
}
std::string TypedFloatConstantGenerator::Value(float v,
const std::string &src) const {
(void)v;
return src + "f";
}
std::string TypedFloatConstantGenerator::Inf(float v) const {
return MakeInf(v < 0, single_prefix_);
}
std::string TypedFloatConstantGenerator::NaN(float v) const {
(void)v;
return MakeNaN(single_prefix_);
}
SimpleFloatConstantGenerator::SimpleFloatConstantGenerator(
const char *nan_number, const char *pos_inf_number,
const char *neg_inf_number)
: nan_number_(nan_number),
pos_inf_number_(pos_inf_number),
neg_inf_number_(neg_inf_number) {}
std::string SimpleFloatConstantGenerator::Value(double v,
const std::string &src) const {
(void)v;
return src;
}
std::string SimpleFloatConstantGenerator::Inf(double v) const {
return (v < 0) ? neg_inf_number_ : pos_inf_number_;
}
std::string SimpleFloatConstantGenerator::NaN(double v) const {
(void)v;
return nan_number_;
}
std::string SimpleFloatConstantGenerator::Value(float v,
const std::string &src) const {
return this->Value(static_cast<double>(v), src);
}
std::string SimpleFloatConstantGenerator::Inf(float v) const {
return this->Inf(static_cast<double>(v));
}
std::string SimpleFloatConstantGenerator::NaN(float v) const {
return this->NaN(static_cast<double>(v));
}
} // namespace flatbuffers
#if defined(_MSC_VER)

View File

@@ -18,7 +18,7 @@
#include <list>
#define FLATC_VERSION "1.10.0 (" __DATE__ " " __TIME__ ")"
#define FLATC_VERSION "1.11.0"
namespace flatbuffers {
@@ -30,12 +30,23 @@ void FlatCompiler::ParseFile(
include_directories.push_back(local_include_directory.c_str());
include_directories.push_back(nullptr);
if (!parser.Parse(contents.c_str(), &include_directories[0],
filename.c_str()))
filename.c_str())) {
Error(parser.error_, false, false);
}
if (!parser.error_.empty()) { Warn(parser.error_, false); }
include_directories.pop_back();
include_directories.pop_back();
}
void FlatCompiler::LoadBinarySchema(flatbuffers::Parser &parser,
const std::string &filename,
const std::string &contents) {
if (!parser.Deserialize(reinterpret_cast<const uint8_t *>(contents.c_str()),
contents.size())) {
Error("failed to load binary schema: " + filename, false, false);
}
}
void FlatCompiler::Warn(const std::string &warn, bool show_exe_name) const {
params_.warn_fn(this, warn, show_exe_name);
}
@@ -89,45 +100,56 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const {
" --gen-name-strings Generate type name functions for C++.\n"
" --gen-object-api Generate an additional object-based API.\n"
" --gen-compare Generate operator== for object-based API types.\n"
" --cpp-ptr-type T Set object API pointer type (default std::unique_ptr)\n"
" --cpp-str-type T Set object API string type (default std::string)\n"
" T::c_str() and T::length() must be supported\n"
" --gen-nullable Add Clang _Nullable for C++ pointer. or @Nullable for Java\n"
" --gen-generated Add @Generated annotation for Java\n"
" --gen-all Generate not just code for the current schema files,\n"
" but for all files it includes as well.\n"
" If the language uses a single file for output (by default\n"
" the case for C++ and JS), all code will end up in this one\n"
" file.\n"
" --cpp-ptr-type T Set object API pointer type (default std::unique_ptr).\n"
" --cpp-str-type T Set object API string type (default std::string).\n"
" T::c_str(), T::length() and T::empty() must be supported.\n"
" The custom type also needs to be constructible from std::string\n"
" (see the --cpp-str-flex-ctor option to change this behavior).\n"
" --cpp-str-flex-ctor Don't construct custom string types by passing std::string\n"
" from Flatbuffers, but (char* + length).\n"
" --object-prefix Customise class prefix for C++ object-based API.\n"
" --object-suffix Customise class suffix for C++ object-based API.\n"
" Default value is \"T\"\n"
" Default value is \"T\".\n"
" --no-js-exports Removes Node.js style export lines in JS.\n"
" --goog-js-export Uses goog.exports* for closure compiler exporting in JS.\n"
" --es6-js-export Uses ECMAScript 6 export style lines in JS.\n"
" --go-namespace Generate the overrided namespace in Golang.\n"
" --go-import Generate the overrided import for flatbuffers in Golang.\n"
" (default is \"github.com/google/flatbuffers/go\")\n"
" --go-import Generate the overrided import for flatbuffers in Golang\n"
" (default is \"github.com/google/flatbuffers/go\").\n"
" --raw-binary Allow binaries without file_indentifier to be read.\n"
" This may crash flatc given a mismatched schema.\n"
" --size-prefixed Input binaries are size prefixed buffers.\n"
" --proto Input is a .proto, translate to .fbs.\n"
" --oneof-union Translate .proto oneofs to flatbuffer unions.\n"
" --grpc Generate GRPC interfaces for the specified languages\n"
" --schema Serialize schemas instead of JSON (use with -b)\n"
" --grpc Generate GRPC interfaces for the specified languages.\n"
" --schema Serialize schemas instead of JSON (use with -b).\n"
" --bfbs-comments Add doc comments to the binary schema files.\n"
" --bfbs-builtins Add builtin attributes to the binary schema files.\n"
" --conform FILE Specify a schema the following schemas should be\n"
" an evolution of. Gives errors if not.\n"
" --conform-includes Include path for the schema given with --conform\n"
" PATH \n"
" --conform-includes Include path for the schema given with --conform PATH\n"
" --include-prefix Prefix this path to any generated include statements.\n"
" PATH\n"
" --keep-prefix Keep original prefix of schema include statement.\n"
" --no-fb-import Don't include flatbuffers import statement for TypeScript.\n"
" --no-ts-reexport Don't re-export imported dependencies for TypeScript.\n"
" --short-names Use short function names for JS and TypeScript.\n"
" --reflect-types Add minimal type reflection to code generation.\n"
" --reflect-names Add minimal type/name reflection.\n"
" --root-type T Select or override the default root_type\n"
" --force-defaults Emit default values in binary output from JSON\n"
" --force-empty When serializing from object API representation, "
" --force-empty When serializing from object API representation,\n"
" force strings and vectors to empty rather than null.\n"
"FILEs may be schemas (must end in .fbs), or JSON files (conforming to preceding\n"
"schema). FILEs after the -- must be binary flatbuffer format files.\n"
"FILEs may be schemas (must end in .fbs), binary schemas (must end in .bfbs),\n"
"or JSON files (conforming to preceding schema). FILEs after the -- must be\n"
"binary flatbuffer format files.\n"
"Output files are named using the base file name of the input,\n"
"and written to the current directory or the path given by -o.\n"
"example: " << program_name << " -c -b schema1.fbs schema2.fbs data.json\n";
@@ -231,8 +253,12 @@ int FlatCompiler::Compile(int argc, const char **argv) {
} else if (arg == "--cpp-str-type") {
if (++argi >= argc) Error("missing type following" + arg, true);
opts.cpp_object_api_string_type = argv[argi];
} else if (arg == "--cpp-str-flex-ctor") {
opts.cpp_object_api_string_flexible_constructor = true;
} else if (arg == "--gen-nullable") {
opts.gen_nullable = true;
} else if (arg == "--gen-generated") {
opts.gen_generated = true;
} else if (arg == "--object-prefix") {
if (++argi >= argc) Error("missing prefix following" + arg, true);
opts.object_prefix = argv[argi];
@@ -276,6 +302,8 @@ int FlatCompiler::Compile(int argc, const char **argv) {
opts.skip_flatbuffers_import = true;
} else if (arg == "--no-ts-reexport") {
opts.reexport_ts_modules = false;
} else if (arg == "--short-names") {
opts.js_ts_short_names = true;
} else if (arg == "--reflect-types") {
opts.mini_reflect = IDLOptions::kTypes;
} else if (arg == "--reflect-names") {
@@ -320,8 +348,14 @@ int FlatCompiler::Compile(int argc, const char **argv) {
std::string contents;
if (!flatbuffers::LoadFile(conform_to_schema.c_str(), true, &contents))
Error("unable to load schema: " + conform_to_schema);
ParseFile(conform_parser, conform_to_schema, contents,
conform_include_directories);
if (flatbuffers::GetExtension(conform_to_schema) ==
reflection::SchemaExtension()) {
LoadBinarySchema(conform_parser, conform_to_schema, contents);
} else {
ParseFile(conform_parser, conform_to_schema, contents,
conform_include_directories);
}
}
std::unique_ptr<flatbuffers::Parser> parser(new flatbuffers::Parser(opts));
@@ -337,6 +371,7 @@ int FlatCompiler::Compile(int argc, const char **argv) {
static_cast<size_t>(file_it - filenames.begin()) >= binary_files_from;
auto ext = flatbuffers::GetExtension(filename);
auto is_schema = ext == "fbs" || ext == "proto";
auto is_binary_schema = ext == reflection::SchemaExtension();
if (is_binary) {
parser->builder_.Clear();
parser->builder_.PushFlatBuffer(
@@ -363,7 +398,7 @@ int FlatCompiler::Compile(int argc, const char **argv) {
}
} else {
// Check if file contains 0 bytes.
if (contents.length() != strlen(contents.c_str())) {
if (!is_binary_schema && contents.length() != strlen(contents.c_str())) {
Error("input file appears to be binary: " + filename, true);
}
if (is_schema) {
@@ -372,15 +407,19 @@ int FlatCompiler::Compile(int argc, const char **argv) {
// so explicitly using an include.
parser.reset(new flatbuffers::Parser(opts));
}
ParseFile(*parser.get(), filename, contents, include_directories);
if (!is_schema && !parser->builder_.GetSize()) {
// If a file doesn't end in .fbs, it must be json/binary. Ensure we
// didn't just parse a schema with a different extension.
Error(
"input file is neither json nor a .fbs (schema) file: " + filename,
true);
if (is_binary_schema) {
LoadBinarySchema(*parser.get(), filename, contents);
} else {
ParseFile(*parser.get(), filename, contents, include_directories);
if (!is_schema && !parser->builder_.GetSize()) {
// If a file doesn't end in .fbs, it must be json/binary. Ensure we
// didn't just parse a schema with a different extension.
Error("input file is neither json nor a .fbs (schema) file: " +
filename,
true);
}
}
if (is_schema && !conform_to_schema.empty()) {
if ((is_schema || is_binary_schema) && !conform_to_schema.empty()) {
auto err = parser->ConformTo(conform_parser);
if (!err.empty()) Error("schemas don\'t conform: " + err);
}
@@ -398,7 +437,8 @@ int FlatCompiler::Compile(int argc, const char **argv) {
if (generator_enabled[i]) {
if (!print_make_rules) {
flatbuffers::EnsureDirExists(output_path);
if ((!params_.generators[i].schema_only || is_schema) &&
if ((!params_.generators[i].schema_only ||
(is_schema || is_binary_schema)) &&
!params_.generators[i].generate(*parser.get(), output_path,
filebase)) {
Error(std::string("Unable to generate ") +

View File

@@ -55,15 +55,15 @@ int main(int argc, const char *argv[]) {
flatbuffers::GenerateJavaGRPC, flatbuffers::IDLOptions::kJava,
"Generate Java classes for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateJS, "-s", "--js", "JavaScript", true, nullptr,
{ flatbuffers::GenerateJSTS, "-s", "--js", "JavaScript", true, nullptr,
flatbuffers::IDLOptions::kJs,
"Generate JavaScript code for tables/structs", flatbuffers::JSMakeRule },
"Generate JavaScript code for tables/structs", flatbuffers::JSTSMakeRule },
{ flatbuffers::GenerateDart, "-d", "--dart", "Dart", true, nullptr,
flatbuffers::IDLOptions::kDart,
"Generate Dart classes for tables/structs", flatbuffers::DartMakeRule },
{ flatbuffers::GenerateJS, "-T", "--ts", "TypeScript", true, nullptr,
{ flatbuffers::GenerateJSTS, "-T", "--ts", "TypeScript", true, nullptr,
flatbuffers::IDLOptions::kTs,
"Generate TypeScript code for tables/structs", flatbuffers::JSMakeRule },
"Generate TypeScript code for tables/structs", flatbuffers::JSTSMakeRule },
{ flatbuffers::GenerateGeneral, "-n", "--csharp", "C#", true, nullptr,
flatbuffers::IDLOptions::kCSharp,
"Generate C# classes for tables/structs", flatbuffers::GeneralMakeRule },

View File

@@ -25,7 +25,7 @@ enum OutputFormat { kDecimal, kHexadecimal, kHexadecimal0x };
int main(int argc, char *argv[]) {
const char *name = argv[0];
if (argc <= 1) {
printf("%s HASH [OPTION]... STRING... [-- STRING...]\n", name);
printf("%s HASH [OPTION]... [--] STRING...\n", name);
printf("Available hashing algorithms:\n");
printf(" 16 bit:\n");
size_t size = sizeof(flatbuffers::kHashFunctions16) /
@@ -50,7 +50,7 @@ int main(int argc, char *argv[]) {
" -x Output hash in hexadecimal.\n"
" -0x Output hash in hexadecimal and prefix with 0x.\n"
" -c Append the string to the output in a c-style comment.\n");
return 0;
return 1;
}
const char *hash_algorithm = argv[1];
@@ -64,7 +64,7 @@ int main(int argc, char *argv[]) {
if (!hash_function16 && !hash_function32 && !hash_function64) {
printf("\"%s\" is not a known hash algorithm.\n", hash_algorithm);
return 0;
return 1;
}
OutputFormat output_format = kHexadecimal;

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,6 @@
// independent from idl_parser, since this code is not needed for most clients
#include <cassert>
#include <unordered_map>
#include "flatbuffers/code_generators.h"
#include "flatbuffers/flatbuffers.h"
@@ -52,11 +51,11 @@ static const char *keywords[] = {
// and tables) and output them to a single file.
class DartGenerator : public BaseGenerator {
public:
typedef std::unordered_map<std::string, std::string> namespace_code_map;
typedef std::map<std::string, std::string> namespace_code_map;
DartGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
: BaseGenerator(parser, path, file_name, "", "."){};
: BaseGenerator(parser, path, file_name, "", ".") {}
// Iterate through all definitions we haven't generate code for (enums,
// structs, and tables) and output them to a single file.
bool generate() {
@@ -252,12 +251,11 @@ class DartGenerator : public BaseGenerator {
" static bool containsValue(int value) =>"
" values.containsKey(value);\n\n";
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
++it) {
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &ev = **it;
if (!ev.doc_comment.empty()) {
if (it != enum_def.vals.vec.begin()) { code += '\n'; }
if (it != enum_def.Vals().begin()) { code += '\n'; }
GenDocComment(ev.doc_comment, &code, "", " ");
}
code += " static const " + name + " " + ev.name + " = ";
@@ -265,8 +263,7 @@ class DartGenerator : public BaseGenerator {
}
code += " static get values => {";
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
++it) {
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &ev = **it;
code += NumToString(ev.value) + ": " + ev.name + ",";
}
@@ -504,8 +501,9 @@ class DartGenerator : public BaseGenerator {
if (field.value.type.base_type == BASE_TYPE_UNION) {
code += " {\n";
code += " switch (" + field_name + "Type?.value) {\n";
for (auto en_it = field.value.type.enum_def->vals.vec.begin() + 1;
en_it != field.value.type.enum_def->vals.vec.end(); ++en_it) {
auto &enum_def = *field.value.type.enum_def;
for (auto en_it = enum_def.Vals().begin() + 1;
en_it != enum_def.Vals().end(); ++en_it) {
auto &ev = **en_it;
auto enum_name = NamespaceAliasFromUnionType(ev.name);

View File

@@ -96,8 +96,7 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
else
schema += "enum " + enum_def.name + " : ";
schema += GenType(enum_def.underlying_type, true) + " {\n";
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
++it) {
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &ev = **it;
GenComment(ev.doc_comment, &schema, nullptr, " ");
if (enum_def.is_union)

View File

@@ -56,10 +56,18 @@ struct LanguageParameters {
std::string optional_suffix;
std::string includes;
std::string class_annotation;
std::string generated_type_annotation;
CommentConfig comment_config;
const FloatConstantGenerator *float_gen;
};
const LanguageParameters &GetLangParams(IDLOptions::Language lang) {
static TypedFloatConstantGenerator CSharpFloatGen(
"Double.", "Single.", "NaN", "PositiveInfinity", "NegativeInfinity");
static TypedFloatConstantGenerator JavaFloatGen(
"Double.", "Float.", "NaN", "POSITIVE_INFINITY", "NEGATIVE_INFINITY");
static const LanguageParameters language_parameters[] = {
{
IDLOptions::kJava,
@@ -88,11 +96,13 @@ const LanguageParameters &GetLangParams(IDLOptions::Language lang) {
"import java.nio.*;\nimport java.lang.*;\nimport "
"java.util.*;\nimport com.google.flatbuffers.*;\n",
"\n@SuppressWarnings(\"unused\")\n",
"\n@javax.annotation.Generated(value=\"flatc\")\n",
{
"/**",
" *",
" */",
},
&JavaFloatGen
},
{
IDLOptions::kCSharp,
@@ -120,11 +130,13 @@ const LanguageParameters &GetLangParams(IDLOptions::Language lang) {
"?",
"using global::System;\nusing global::FlatBuffers;\n\n",
"",
"",
{
nullptr,
"///",
nullptr,
},
&CSharpFloatGen
},
};
@@ -218,6 +230,9 @@ class GeneralGenerator : public BaseGenerator {
}
code += lang_.class_annotation;
}
if (parser_.opts.gen_generated) {
code += lang_.generated_type_annotation;
}
code += classcode;
if (!namespace_name.empty()) code += lang_.namespace_end;
auto filename = NamespaceDir(ns) + defname + lang_.file_extension;
@@ -291,7 +306,7 @@ class GeneralGenerator : public BaseGenerator {
case BASE_TYPE_UNION:
// Unions in C# use a generic Table-derived type for better type safety
if (lang_.language == IDLOptions::kCSharp) return "TTable";
// fall through
FLATBUFFERS_FALLTHROUGH(); // else fall thru
default: return "Table";
}
}
@@ -312,7 +327,7 @@ class GeneralGenerator : public BaseGenerator {
case BASE_TYPE_UINT: return Type(BASE_TYPE_LONG);
case BASE_TYPE_VECTOR:
if (vectorelem) return DestinationType(type.VectorType(), vectorelem);
// else fall thru
FLATBUFFERS_FALLTHROUGH(); // else fall thru
default: return type;
}
}
@@ -356,7 +371,7 @@ class GeneralGenerator : public BaseGenerator {
case BASE_TYPE_UINT: return " & 0xFFFFFFFFL";
case BASE_TYPE_VECTOR:
if (vectorelem) return DestinationMask(type.VectorType(), vectorelem);
// else fall thru
FLATBUFFERS_FALLTHROUGH(); // else fall thru
default: return "";
}
}
@@ -423,7 +438,8 @@ class GeneralGenerator : public BaseGenerator {
return SourceCastBasic(type, true);
}
std::string GenEnumDefaultValue(const Value &value) const {
std::string GenEnumDefaultValue(const FieldDef &field) const {
auto& value = field.value;
auto enum_def = value.type.enum_def;
auto vec = enum_def->vals.vec;
auto default_value = StringToInt(value.constant.c_str());
@@ -440,19 +456,19 @@ class GeneralGenerator : public BaseGenerator {
return result;
}
std::string GenDefaultValue(const Value &value, bool enableLangOverrides) const {
std::string GenDefaultValue(const FieldDef &field, bool enableLangOverrides) const {
auto& value = field.value;
if (enableLangOverrides) {
// handles both enum case and vector of enum case
if (lang_.language == IDLOptions::kCSharp &&
value.type.enum_def != nullptr &&
value.type.base_type != BASE_TYPE_UNION) {
return GenEnumDefaultValue(value);
return GenEnumDefaultValue(field);
}
}
auto longSuffix = lang_.language == IDLOptions::kJava ? "L" : "";
switch (value.type.base_type) {
case BASE_TYPE_FLOAT: return value.constant + "f";
case BASE_TYPE_BOOL: return value.constant == "0" ? "false" : "true";
case BASE_TYPE_ULONG: {
if (lang_.language != IDLOptions::kJava) return value.constant;
@@ -462,16 +478,21 @@ class GeneralGenerator : public BaseGenerator {
}
case BASE_TYPE_UINT:
case BASE_TYPE_LONG: return value.constant + longSuffix;
default: return value.constant;
default:
if(IsFloat(value.type.base_type))
return lang_.float_gen->GenFloatConstant(field);
else
return value.constant;
}
}
std::string GenDefaultValue(const Value &value) const {
return GenDefaultValue(value, true);
std::string GenDefaultValue(const FieldDef &field) const {
return GenDefaultValue(field, true);
}
std::string GenDefaultValueBasic(const Value &value,
std::string GenDefaultValueBasic(const FieldDef &field,
bool enableLangOverrides) const {
auto& value = field.value;
if (!IsScalar(value.type.base_type)) {
if (enableLangOverrides) {
if (lang_.language == IDLOptions::kCSharp) {
@@ -487,11 +508,11 @@ class GeneralGenerator : public BaseGenerator {
}
return "0";
}
return GenDefaultValue(value, enableLangOverrides);
return GenDefaultValue(field, enableLangOverrides);
}
std::string GenDefaultValueBasic(const Value &value) const {
return GenDefaultValueBasic(value, true);
std::string GenDefaultValueBasic(const FieldDef &field) const {
return GenDefaultValueBasic(field, true);
}
void GenEnum(EnumDef &enum_def, std::string *code_ptr) const {
@@ -522,8 +543,7 @@ class GeneralGenerator : public BaseGenerator {
if (lang_.language == IDLOptions::kJava) {
code += " private " + enum_def.name + "() { }\n";
}
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
++it) {
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &ev = **it;
GenComment(ev.doc_comment, code_ptr, &lang_.comment_config, " ");
if (lang_.language != IDLOptions::kCSharp) {
@@ -553,8 +573,8 @@ class GeneralGenerator : public BaseGenerator {
code += lang_.const_decl;
code += lang_.string_type;
code += "[] names = { ";
auto val = enum_def.vals.vec.front()->value;
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
auto val = enum_def.Vals().front()->value;
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end();
++it) {
while (val++ != (*it)->value) code += "\"\", ";
code += "\"" + (*it)->name + "\", ";
@@ -853,7 +873,15 @@ class GeneralGenerator : public BaseGenerator {
// accessor object. This is to allow object reuse.
code += " public void __init(int _i, ByteBuffer _bb) ";
code += "{ " + lang_.accessor_prefix + "bb_pos = _i; ";
code += lang_.accessor_prefix + "bb = _bb; }\n";
code += lang_.accessor_prefix + "bb = _bb; ";
if (!struct_def.fixed && lang_.language == IDLOptions::kJava) {
code += lang_.accessor_prefix + "vtable_start = " + lang_.accessor_prefix + "bb_pos - ";
code += lang_.accessor_prefix + "bb." + FunctionStart('G') + "etInt(";
code += lang_.accessor_prefix + "bb_pos); " + lang_.accessor_prefix + "vtable_size = ";
code += lang_.accessor_prefix + "bb." + FunctionStart('G') + "etShort(";
code += lang_.accessor_prefix + "vtable_start); ";
}
code += "}\n";
code +=
" public " + struct_def.name + " __assign(int _i, ByteBuffer _bb) ";
code += "{ __init(_i, _bb); return this; }\n\n";
@@ -950,7 +978,7 @@ class GeneralGenerator : public BaseGenerator {
code += offset_prefix + getter;
code += "(o + " + lang_.accessor_prefix + "bb_pos)" + dest_mask;
code += " : " + default_cast;
code += GenDefaultValue(field.value);
code += GenDefaultValue(field);
}
} else {
switch (field.value.type.base_type) {
@@ -1014,6 +1042,8 @@ class GeneralGenerator : public BaseGenerator {
? index
: lang_.accessor_prefix + "__indirect(" + index + ")";
code += ", " + lang_.accessor_prefix + "bb";
} else if (vectortype.base_type == BASE_TYPE_UNION) {
code += index + " - " + lang_.accessor_prefix + "bb_pos";
} else {
code += index;
}
@@ -1272,7 +1302,7 @@ class GeneralGenerator : public BaseGenerator {
// supply all arguments, and thus won't compile when fields are added.
if (lang_.language != IDLOptions::kJava) {
code += " = ";
code += GenDefaultValueBasic(field.value);
code += GenDefaultValueBasic(field);
}
}
code += ") {\n builder.";
@@ -1332,7 +1362,7 @@ class GeneralGenerator : public BaseGenerator {
code += ", ";
if (lang_.language == IDLOptions::kJava)
code += SourceCastBasic(field.value.type);
code += GenDefaultValue(field.value, false);
code += GenDefaultValue(field, false);
code += "); }\n";
if (field.value.type.base_type == BASE_TYPE_VECTOR) {
auto vector_type = field.value.type.VectorType();

File diff suppressed because it is too large Load Diff

View File

@@ -113,12 +113,12 @@ class FlatBufService : public grpc_generator::Service {
int method_count() const {
return static_cast<int>(service_->calls.vec.size());
};
}
std::unique_ptr<const grpc_generator::Method> method(int i) const {
return std::unique_ptr<const grpc_generator::Method>(
new FlatBufMethod(service_->calls.vec[i]));
};
}
private:
const ServiceDef *service_;
@@ -235,7 +235,7 @@ class FlatBufFile : public grpc_generator::File {
int service_count() const {
return static_cast<int>(parser_.services_.vec.size());
};
}
std::unique_ptr<const grpc_generator::Service> service(int i) const {
return std::unique_ptr<const grpc_generator::Service>(

View File

@@ -28,7 +28,7 @@ namespace flatbuffers {
const std::string kGeneratedFileNamePostfix = "_generated";
struct JsLanguageParameters {
struct JsTsLanguageParameters {
IDLOptions::Language language;
std::string file_extension;
};
@@ -41,8 +41,8 @@ struct ReexportDescription {
enum AnnotationType { kParam = 0, kType = 1, kReturns = 2 };
const JsLanguageParameters &GetJsLangParams(IDLOptions::Language lang) {
static JsLanguageParameters js_language_parameters[] = {
const JsTsLanguageParameters &GetJsLangParams(IDLOptions::Language lang) {
static JsTsLanguageParameters js_language_parameters[] = {
{
IDLOptions::kJs,
".js",
@@ -63,23 +63,23 @@ const JsLanguageParameters &GetJsLangParams(IDLOptions::Language lang) {
static std::string GeneratedFileName(const std::string &path,
const std::string &file_name,
const JsLanguageParameters &lang) {
const JsTsLanguageParameters &lang) {
return path + file_name + kGeneratedFileNamePostfix + lang.file_extension;
}
namespace js {
namespace jsts {
// Iterate through all definitions we haven't generate code for (enums, structs,
// and tables) and output them to a single file.
class JsGenerator : public BaseGenerator {
class JsTsGenerator : public BaseGenerator {
public:
typedef std::unordered_set<std::string> imported_fileset;
typedef std::unordered_multimap<std::string, ReexportDescription>
reexport_map;
JsGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
JsTsGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
: BaseGenerator(parser, path, file_name, "", "."),
lang_(GetJsLangParams(parser_.opts.lang)){};
lang_(GetJsLangParams(parser_.opts.lang)) {}
// Iterate through all definitions we haven't generate code for (enums,
// structs, and tables) and output them to a single file.
bool generate() {
@@ -105,10 +105,10 @@ class JsGenerator : public BaseGenerator {
if (lang_.language == IDLOptions::kJs && !exports_code.empty() &&
!parser_.opts.skip_js_exports) {
if( parser_.opts.use_ES6_js_export_format )
code += "// Exports for ECMAScript6 Modules\n";
else
code += "// Exports for Node.js and RequireJS\n";
if (parser_.opts.use_ES6_js_export_format)
code += "// Exports for ECMAScript6 Modules\n";
else
code += "// Exports for Node.js and RequireJS\n";
code += exports_code;
}
@@ -117,7 +117,7 @@ class JsGenerator : public BaseGenerator {
}
private:
JsLanguageParameters lang_;
JsTsLanguageParameters lang_;
// Generate code for imports
void generateImportDependencies(std::string *code_ptr,
@@ -128,8 +128,7 @@ class JsGenerator : public BaseGenerator {
const auto basename =
flatbuffers::StripPath(flatbuffers::StripExtension(file));
if (basename != file_name_) {
const auto file_name = basename + kGeneratedFileNamePostfix;
code += GenPrefixedImport(file, file_name);
code += GenPrefixedImport(file, basename);
}
}
}
@@ -149,10 +148,8 @@ class JsGenerator : public BaseGenerator {
const auto basename =
flatbuffers::StripPath(flatbuffers::StripExtension(file.first));
if (basename != file_name_) {
const auto file_name = basename + kGeneratedFileNamePostfix;
if (imported_files.find(file.first) == imported_files.end()) {
code += GenPrefixedImport(file.first, file_name);
code += GenPrefixedImport(file.first, basename);
imported_files.emplace(file.first);
}
@@ -171,7 +168,8 @@ class JsGenerator : public BaseGenerator {
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
auto &enum_def = **it;
GenEnum(enum_def, enum_code_ptr, exports_code_ptr, reexports);
GenEnum(enum_def, enum_code_ptr, exports_code_ptr, reexports, false);
GenEnum(enum_def, enum_code_ptr, exports_code_ptr, reexports, true);
}
}
@@ -228,7 +226,7 @@ class JsGenerator : public BaseGenerator {
code += "var ";
if (parser_.opts.use_goog_js_export_format) {
exports += "goog.exportSymbol('" + *it + "', " + *it + ");\n";
} else if( parser_.opts.use_ES6_js_export_format){
} else if (parser_.opts.use_ES6_js_export_format) {
exports += "export {" + *it + "};\n";
} else {
exports += "this." + *it + " = " + *it + ";\n";
@@ -325,12 +323,16 @@ class JsGenerator : public BaseGenerator {
// Generate an enum declaration and an enum string lookup table.
void GenEnum(EnumDef &enum_def, std::string *code_ptr,
std::string *exports_ptr, reexport_map &reexports) {
std::string *exports_ptr, reexport_map &reexports,
bool reverse) {
if (enum_def.generated) return;
if (reverse && lang_.language == IDLOptions::kTs) return; // FIXME.
std::string &code = *code_ptr;
std::string &exports = *exports_ptr;
GenDocComment(enum_def.doc_comment, code_ptr, "@enum");
GenDocComment(enum_def.doc_comment, code_ptr,
reverse ? "@enum {string}" : "@enum {number}");
std::string ns = GetNameSpace(enum_def);
std::string enum_def_name = enum_def.name + (reverse ? "Name" : "");
if (lang_.language == IDLOptions::kTs) {
if (!ns.empty()) { code += "export namespace " + ns + "{\n"; }
code += "export enum " + enum_def.name + "{\n";
@@ -338,27 +340,35 @@ class JsGenerator : public BaseGenerator {
if (enum_def.defined_namespace->components.empty()) {
code += "var ";
if (parser_.opts.use_goog_js_export_format) {
exports += "goog.exportSymbol('" + enum_def.name + "', " +
exports += "goog.exportSymbol('" + enum_def_name + "', " +
enum_def.name + ");\n";
} else if (parser_.opts.use_ES6_js_export_format) {
exports += "export {" + enum_def.name + "};\n";
exports += "export {" + enum_def_name + "};\n";
} else {
exports += "this." + enum_def.name + " = " + enum_def.name + ";\n";
exports += "this." + enum_def_name + " = " + enum_def_name + ";\n";
}
}
code += WrapInNameSpace(enum_def) + " = {\n";
code += WrapInNameSpace(enum_def) + (reverse ? "Name" : "") + " = {\n";
}
for (auto it = enum_def.vals.vec.begin(); it != enum_def.vals.vec.end();
++it) {
for (auto it = enum_def.Vals().begin(); it != enum_def.Vals().end(); ++it) {
auto &ev = **it;
if (!ev.doc_comment.empty()) {
if (it != enum_def.vals.vec.begin()) { code += '\n'; }
if (it != enum_def.Vals().begin()) { code += '\n'; }
GenDocComment(ev.doc_comment, code_ptr, "", " ");
}
code += " " + ev.name;
code += lang_.language == IDLOptions::kTs ? "= " : ": ";
code += NumToString(ev.value);
code += (it + 1) != enum_def.vals.vec.end() ? ",\n" : "\n";
// Generate mapping between EnumName: EnumValue(int)
if (reverse) {
code += " " + NumToString(ev.value);
code += lang_.language == IDLOptions::kTs ? "= " : ": ";
code += "'" + ev.name + "'";
} else {
code += " " + ev.name;
code += lang_.language == IDLOptions::kTs ? "= " : ": ";
code += NumToString(ev.value);
}
code += (it + 1) != enum_def.Vals().end() ? ",\n" : "\n";
if (ev.union_type.struct_def) {
ReexportDescription desc = { ev.name,
@@ -446,8 +456,9 @@ class JsGenerator : public BaseGenerator {
case BASE_TYPE_LONG:
case BASE_TYPE_ULONG: {
int64_t constant = StringToInt(value.constant.c_str());
return context + ".createLong(" + NumToString((int32_t)constant) +
", " + NumToString((int32_t)(constant >> 32)) + ")";
return context + ".createLong(" +
NumToString(static_cast<int32_t>(constant)) + ", " +
NumToString(static_cast<int32_t>(constant >> 32)) + ")";
}
default: return value.constant;
@@ -510,10 +521,26 @@ class JsGenerator : public BaseGenerator {
return "NS" + std::to_string(HashFnv1a<uint64_t>(file.c_str()));
}
static std::string GenPrefixedImport(const std::string &full_file_name,
const std::string &base_file_name) {
std::string GenPrefixedImport(const std::string &full_file_name,
const std::string &base_name) {
// Either keep the include path as it was
// or use only the base_name + kGeneratedFileNamePostfix
std::string path;
if (parser_.opts.keep_include_path) {
auto it = parser_.included_files_.find(full_file_name);
FLATBUFFERS_ASSERT(it != parser_.included_files_.end());
path =
flatbuffers::StripExtension(it->second) + kGeneratedFileNamePostfix;
} else {
path = base_name + kGeneratedFileNamePostfix;
}
// Add the include prefix and make the path always relative
path = flatbuffers::ConCatPathFileName(parser_.opts.include_prefix, path);
path = std::string(".") + kPathSeparator + path;
return "import * as " + GenFileNamespacePrefix(full_file_name) +
" from \"./" + base_file_name + "\";\n";
" from \"" + path + "\";\n";
}
// Adds a source-dependent prefix, for of import * statements.
@@ -521,7 +548,9 @@ class JsGenerator : public BaseGenerator {
const std::string &file) {
const auto basename =
flatbuffers::StripPath(flatbuffers::StripExtension(file));
if (basename == file_name_ || parser_.opts.generate_all) { return typeName; }
if (basename == file_name_ || parser_.opts.generate_all) {
return typeName;
}
return GenFileNamespacePrefix(file) + "." + typeName;
}
@@ -668,11 +697,11 @@ class JsGenerator : public BaseGenerator {
GenTypeAnnotation(kParam, object_name + "=", "obj") +
GenTypeAnnotation(kReturns, object_name, "", false));
if (lang_.language == IDLOptions::kTs) {
code += "static getRootAs" + struct_def.name;
code += "static getRoot" + Verbose(struct_def, "As");
code += "(bb:flatbuffers.ByteBuffer, obj?:" + object_name +
"):" + object_name + " {\n";
} else {
code += object_name + ".getRootAs" + struct_def.name;
code += object_name + ".getRoot" + Verbose(struct_def, "As");
code += " = function(bb, obj) {\n";
}
code += " return (obj || new " + object_name;
@@ -736,6 +765,10 @@ class JsGenerator : public BaseGenerator {
GenPrefixedTypeName(GenTypeName(field.value.type, false, true),
field.value.type.enum_def->file) +
" {\n";
if (!parser_.opts.generate_all) {
imported_files.insert(field.value.type.enum_def->file);
}
} else {
code += "):" + GenTypeName(field.value.type, false, true) + " {\n";
}
@@ -849,7 +882,7 @@ class JsGenerator : public BaseGenerator {
code += prefix + ", obj?:" + vectortypename;
if (!parser_.opts.generate_all) {
imported_files.insert(vectortype.struct_def->file);
imported_files.insert(vectortype.struct_def->file);
}
} else if (vectortype.base_type == BASE_TYPE_STRING) {
code += prefix + "):string\n";
@@ -1056,12 +1089,12 @@ class JsGenerator : public BaseGenerator {
"", false));
if (lang_.language == IDLOptions::kTs) {
code +=
"static create" + struct_def.name + "(builder:flatbuffers.Builder";
code += "static create" + Verbose(struct_def) +
"(builder:flatbuffers.Builder";
code += arguments + "):flatbuffers.Offset {\n";
} else {
code +=
object_name + ".create" + struct_def.name + " = function(builder";
code += object_name + ".create" + Verbose(struct_def);
code += " = function(builder";
code += arguments + ") {\n";
}
@@ -1073,10 +1106,10 @@ class JsGenerator : public BaseGenerator {
"builder", false));
if (lang_.language == IDLOptions::kTs) {
code += "static start" + struct_def.name;
code += "(builder:flatbuffers.Builder) {\n";
code += "static start" + Verbose(struct_def) +
"(builder:flatbuffers.Builder) {\n";
} else {
code += object_name + ".start" + struct_def.name;
code += object_name + ".start" + Verbose(struct_def);
code += " = function(builder) {\n";
}
@@ -1089,8 +1122,7 @@ class JsGenerator : public BaseGenerator {
it != struct_def.fields.vec.end(); ++it) {
auto &field = **it;
if (field.deprecated) continue;
auto argname = MakeCamel(field.name, false);
if (!IsScalar(field.value.type.base_type)) { argname += "Offset"; }
const auto argname = GetArgName(field);
// Generate the field insertion method
GenDocComment(
@@ -1100,17 +1132,9 @@ class JsGenerator : public BaseGenerator {
argname, false));
if (lang_.language == IDLOptions::kTs) {
std::string argType;
if (field.value.type.enum_def) {
argType = GenPrefixedTypeName(GenTypeName(field.value.type, true),
field.value.type.enum_def->file);
} else {
argType = GenTypeName(field.value.type, true);
}
code += "static add" + MakeCamel(field.name);
code += "(builder:flatbuffers.Builder, " + argname + ":" + argType +
") {\n";
code += "(builder:flatbuffers.Builder, " + argname + ":" +
GetArgType(field) + ") {\n";
} else {
code += object_name + ".add" + MakeCamel(field.name);
code += " = function(builder, " + argname + ") {\n";
@@ -1195,10 +1219,10 @@ class JsGenerator : public BaseGenerator {
GenTypeAnnotation(kReturns, "flatbuffers.Offset", "", false));
if (lang_.language == IDLOptions::kTs) {
code += "static end" + struct_def.name;
code += "static end" + Verbose(struct_def);
code += "(builder:flatbuffers.Builder):flatbuffers.Offset {\n";
} else {
code += object_name + ".end" + struct_def.name;
code += object_name + ".end" + Verbose(struct_def);
code += " = function(builder) {\n";
}
@@ -1224,11 +1248,11 @@ class JsGenerator : public BaseGenerator {
false));
if (lang_.language == IDLOptions::kTs) {
code += "static finish" + struct_def.name + "Buffer";
code += "static finish" + Verbose(struct_def) + "Buffer";
code +=
"(builder:flatbuffers.Builder, offset:flatbuffers.Offset) {\n";
} else {
code += object_name + ".finish" + struct_def.name + "Buffer";
code += object_name + ".finish" + Verbose(struct_def) + "Buffer";
code += " = function(builder, offset) {\n";
}
@@ -1239,24 +1263,112 @@ class JsGenerator : public BaseGenerator {
code += ");\n";
code += "};\n\n";
}
// Generate a convenient CreateX function
if (lang_.language == IDLOptions::kJs) {
std::string paramDoc =
GenTypeAnnotation(kParam, "flatbuffers.Builder", "builder");
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
const auto &field = **it;
if (field.deprecated)
continue;
paramDoc +=
GenTypeAnnotation(kParam, GetArgType(field), GetArgName(field));
}
paramDoc +=
GenTypeAnnotation(kReturns, "flatbuffers.Offset", "", false);
GenDocComment(code_ptr, paramDoc);
}
if (lang_.language == IDLOptions::kTs) {
code += "static create" + Verbose(struct_def);
code += "(builder:flatbuffers.Builder";
} else {
code += object_name + ".create" + Verbose(struct_def);
code += " = function(builder";
}
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
const auto &field = **it;
if (field.deprecated)
continue;
if (lang_.language == IDLOptions::kTs) {
code += ", " + GetArgName(field) + ":" + GetArgType(field);
} else {
code += ", " + GetArgName(field);
}
}
if (lang_.language == IDLOptions::kTs) {
code += "):flatbuffers.Offset {\n";
code += " " + struct_def.name + ".start" + Verbose(struct_def) +
"(builder);\n";
} else {
code += ") {\n";
code += " " + object_name + ".start" + Verbose(struct_def) +
"(builder);\n";
}
std::string methodPrefix =
lang_.language == IDLOptions::kTs ? struct_def.name : object_name;
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end(); ++it) {
const auto &field = **it;
if (field.deprecated)
continue;
code += " " + methodPrefix + ".add" + MakeCamel(field.name) + "(";
code += "builder, " + GetArgName(field) + ");\n";
}
code += " return " + methodPrefix + ".end" + Verbose(struct_def) +
"(builder);\n";
code += "}\n";
if (lang_.language == IDLOptions::kJs)
code += "\n";
}
if (lang_.language == IDLOptions::kTs) {
if (!object_namespace.empty()) { code += "}\n"; }
if (!object_namespace.empty()) {
code += "}\n";
}
code += "}\n";
}
}
};
} // namespace js
bool GenerateJS(const Parser &parser, const std::string &path,
const std::string &file_name) {
js::JsGenerator generator(parser, path, file_name);
std::string GetArgType(const FieldDef &field) {
if (field.value.type.enum_def)
return GenPrefixedTypeName(GenTypeName(field.value.type, true),
field.value.type.enum_def->file);
return GenTypeName(field.value.type, true);
}
static std::string GetArgName(const FieldDef &field) {
auto argname = MakeCamel(field.name, false);
if (!IsScalar(field.value.type.base_type)) { argname += "Offset"; }
return argname;
}
std::string Verbose(const StructDef &struct_def,
const char* prefix = "")
{
return parser_.opts.js_ts_short_names ? "" : prefix + struct_def.name;
}
};
} // namespace jsts
bool GenerateJSTS(const Parser &parser, const std::string &path,
const std::string &file_name) {
jsts::JsTsGenerator generator(parser, path, file_name);
return generator.generate();
}
std::string JSMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
std::string JSTSMakeRule(const Parser &parser, const std::string &path,
const std::string &file_name) {
FLATBUFFERS_ASSERT(parser.opts.lang <= IDLOptions::kMAX);
const auto &lang = GetJsLangParams(parser.opts.lang);

Some files were not shown because too many files have changed in this diff Show More