Compare commits

...

199 Commits

Author SHA1 Message Date
Wouter van Oortmerssen
34aea4361f Updated version numbers to 1.8.0
Change-Id: I9cf9fe1e2572d3f9c4066624a87249ca1e62a297
2017-11-20 09:46:03 -08:00
Wouter van Oortmerssen
be1ad33910 Missing generated code files.
Change-Id: I8808b0b419981ba7d0699da4a1effb0b660a21cb
2017-11-20 09:19:35 -08:00
MikkelFJ
0cf04ad9d5 Document type aliases (#4499) 2017-11-17 08:57:01 -08:00
Dan Douglas
fe483fa380 fix typo (#4495)
`Equipment` is a union, not an enum.
2017-11-16 16:03:16 -08:00
Wouter van Oortmerssen
8a8dc4e111 Fixed potential strict-aliasing violation in big-endian code.
Also added a test.

Tested on: Linux.

Change-Id: I7b3230f8f6043eec139d5e3e8c9cb45814124274
2017-11-16 14:21:11 -08:00
red1939
7e803c410c Add exports for all targets (#4491)
Each target that will be installed will also generate a target that will be
included by CMake config file.
2017-11-16 12:51:25 -08:00
Hong Wu
1336d26252 c++ Tutorial fix (#4494) 2017-11-16 10:09:48 -08:00
Louis-Paul CORDIER
853f7033e0 Remove copy constructor to make flatbuffers struct trivially copyable… (#4476)
* Remove copy constructor to make flatbuffers struct trivially copyable + add tests.

* Add support non c++11 compliant compilers.

* Fix std::trivially_copyiable test for non-C++11 compliant compilers.

* Fix trivially_copyable not part of glibc < 5 even with c++11 switch enabled.
2017-11-16 10:08:41 -08:00
David Komer
e2c7196ea8 tutorial docs (#4492) 2017-11-16 08:51:35 -08:00
Angela Sheu
61fe2a4fac Fix valid params limit exceeded for generated table constructor (#4490) 2017-11-13 13:39:49 -08:00
Wouter van Oortmerssen
d233b38008 Made stl_emulation.h usable by itself.
Change-Id: I1d9d301412fe0a036f12eb2cc82a3fbee5bb838d
2017-11-09 15:48:35 -08:00
Sergey Avseyev
ca52bfefc0 Specify ABI version for shared library (#4479) 2017-11-09 14:39:32 -08:00
Sergey Avseyev
2edb1dcdda Use CMake install directories instead of hardcoded (#4481) 2017-11-06 10:38:53 -08:00
Sergey Avseyev
6eb031de9a Text files should not have executable bit set (#4480) 2017-11-06 10:20:22 -08:00
Lawrence Chan
5f2af34e02 Link grpctest with libgrpc_unsecure explicitly (#4474) 2017-11-06 08:43:22 -08:00
Wouter van Oortmerssen
f3f113b24a Updated pom.xml to be able to deploy to Maven central.
Change-Id: Ie28dda5e1854eeff3e254e975925ff846c137008
2017-10-26 16:14:16 -07:00
stefan301
6bb0a728d3 Added missing EndTable() call to VerifyObject() (#4468)
VerifyObject called VerifyTableStart() but not EndTable(). This made Verifier::VerifyComplexity() increase depth_ with each table, not with the depth of tables.

https://groups.google.com/forum/#!topic/flatbuffers/OpxtW5UFAdg
2017-10-23 09:15:18 -07:00
Alex Ames
97face1527 Changed how vector_data works. (#4467)
In some debug environments using vector[i] does bounds checking even
though the standard specifies that it should not. Using
*(vector.begin()) sidesteps this though, giving the same result without
the bounds checking.
2017-10-20 16:49:15 -07:00
Alex Ames
f2627e16ac Fixed CMake build issue when building with Clang. (#4465) 2017-10-20 16:29:51 -07:00
Yonggang Li
01bac38c84 Nullable java (#4455)
* add _Nullable Support for C++ interface

* generate @Nullable for Java generated code
2017-10-16 09:24:11 -07:00
Stewart Miles
a1b5f565d9 Merge pull request #4459 from stewartmiles/master
Report a build failure when any Android build fails.
2017-10-13 17:55:51 -07:00
Stewart Miles
0780a7db24 Report a build failure when any Android build fails.
The travis script was only failing if the last Android build fails.
This changes the script to report a failure if any of the Android
projects fail to build.
2017-10-13 17:35:57 -07:00
Stewart Miles
9234ddcf11 Fixed Android build failure caused by use of C++11 limits.
f2b3705c2c caused Android builds
to fail.  This switches limit constants to use limits templates in
stl_emulation.h.
2017-10-13 17:35:57 -07:00
Stewart Miles
6d9a226f75 Merge pull request #4458 from a-maurice/master
Use flatbuffer unique_ptr instead of std's.
2017-10-13 16:44:02 -07:00
Anthony
b0fd1a8c66 Use flatbuffer unique_ptr instead of std's.
Stlport does not have std unique_ptr, so using the one provided by
flatbuffers.
Also fixing a problem with the flatbuffer unique_ptr, and a test.
2017-10-13 16:21:34 -07:00
Wouter van Oortmerssen
a0e5d78353 Add new flatbuffer_go_library to generate Go library for flatbuffers
This CL also introduces the following changes to allow the generation of the
Go library for flatbuffers:

- add support for --gen-onefile for Go to simplify the build rule (mapping each
  input .fbs to a single separate .go file)

- add a new --go-import flag to override the default import line (currently
  github.com/google/flatbuffers/go)

- add new go_library in BUILD for flatbuffer (for files in flatbuffers/go)

(mirrored from cr/171126159)

Change-Id: I83e705a9a9d9544837af0baf9366ec37757799aa
2017-10-09 09:27:30 -07:00
Brian Chavez
bc8a1608a8 Spelling error in C# and Java documentation (#4454) 2017-10-09 08:42:34 -07:00
Yonggang Li
30e7d16104 _Nullable cpp interface (#4451)
* add _Nullable Support for C++ interface

* add _Nullable Support for C++ interface
2017-10-09 08:40:17 -07:00
Wouter van Oortmerssen
9c3920d0ab Improved .proto conversion.
- Allowed enums to be declared before use.
- Generalized parsing of `required`.
- Reworked escaping of namespaces.
- Escaping field names that are C++ keywords.
- Many smaller fixes.

Change-Id: Ie580de7b70dc208f676f4f71bb0d061808648b8d
Tested: on Linux.
2017-10-06 16:08:00 -07:00
Aaron
5b4acf809e [C++] Add explicit keyword on generated constructors for Builder structs (#4452)
* Add explicit keyword on C++ generated constructors for Builder structs

* Add missing generated code for review
2017-10-06 08:50:24 -07:00
Robert
86fb05d320 Python: CreateByteVector function in builder. (#4453) 2017-10-06 08:34:07 -07:00
Dariusz Ostolski
5e4739184f Fix issue #4389, if field is ommitted the return type is the same for… (#4444)
* Fix issue #4389, if field is ommitted the return type is the same for python generator

* Fix issue #4389, bytes is returned when field is omitted

* Fix issue #4389, added generated python code after generator modification
2017-10-05 14:07:42 -07:00
Louis-Paul CORDIER
971a68110e Add template version for As method. (#4443)
* Add template version for As method.

* Fix compilation error on Linux.

* Fix linux issue (2).

* Linux fix (3)

* Add few tests.
2017-10-02 14:38:38 -07:00
Wouter van Oortmerssen
7a6b2bf521 Fixed TypeTable function not being inline.
Change-Id: Id335980daf909e885ed26a21b64623b78d01fb49
Tested: on OS X.
2017-09-25 11:44:58 -07:00
Wouter van Oortmerssen
03e2899985 Made the parser not have any hard-coded keywords.
This prevented any keywords showing up as JSON field names, for example.

Change-Id: Ie9d0cada96778e06016ca02ca96d052410a37038
Tested: on Linux.
2017-09-22 16:30:26 -07:00
Wouter van Oortmerssen
72a99abfb7 Added support for mini-reflection tables.
Change-Id: I83453d074685fa57bbf1c7c87b1d9392ce972085
Tested: on Linux.
2017-09-22 16:17:02 -07:00
endorph-soft
21a8121982 Add constant accessors to C++ unions (#4433)
* Add constant accessors to C++ unions

* Remove redundant const pointer return type

* Update generate_code.bat to reflect generate_code.sh

* Add updated generated files

* Remove extra space from generated code

* Update generated files

* Change directory back to tests after generating code
2017-09-21 14:06:20 -07:00
Khem Raj
28920aff8f Fix build with clang on big-endian targets (#4440)
* flatbuffers: Move EndianSwap template to flatbuffers/base.h

Clang complains
call to function 'EndianSwap' that is neither visible in the template definition nor found by argument-dependent lookup
     return EndianSwap(t);

This seems to be due to limitation of two-phase lookup of dependent names in template definitions

Its not being found using associated namespaces therefore
it has to be made visible at the template definition site as well

Signed-off-by: Khem Raj <raj.khem@gmail.com>

* use __builtin_bswap16 when building with clang

clang pretends to be gcc 4.2.0 and therefore the code does
not use __builtin_bswap16 but tries to synthesize it

Signed-off-by: Khem Raj <raj.khem@gmail.com>
2017-09-21 08:51:08 -07:00
schoetbi
77b22aed5a idl_gen_json_schema.cpp: Fixed detection of enum types (#4438) 2017-09-14 09:25:43 -07:00
Lukas Bergdoll
cc25516d3e [C++] Fix DetachedBuffer move assignment lifetime (#4437)
* Fix DetachedBuffer move assignment lifetime

DetachedBuffer move assignment now destroys it's own content,
rather than waiting for the destructor of other.
See more under #4435

Add missing function return type

* Rename empty_assign to reset

Reset after destroy
reset() now operates on itself
2017-09-14 09:22:55 -07:00
Wouter van Oortmerssen
1d444f63d3 Fixed .proto not being accepted as schema file.
Change-Id: I1ccd52a847930fa636d24f9490d57577b8775d08
2017-09-12 11:36:38 -07:00
Wouter van Oortmerssen
5fa00630af Forgot to bump flatc version to 1.7.1
Change-Id: I480a08f445858bce3d0336c2b22da30d64f90012
2017-09-07 14:35:59 -07:00
rouzier
97af3d798b Update doc (#4427) 2017-09-07 11:52:58 -07:00
schoetbi
bb736091f3 Every type gets additionalProperties set to "false" (#4424)
#4423
2017-08-31 08:56:04 -07:00
endorph-soft
d5b4db0692 C++ Customise prefix/suffix of object API [Issue #4419] (#4422)
* Allow prefix/suffix of C++ Object API classes to be customised

* Address review comments
2017-08-31 08:54:03 -07:00
Wouter van Oortmerssen
5808f7fb03 Updated C# test project. 2017-08-25 11:47:19 -07:00
Wouter van Oortmerssen
42611f9a83 Fixed VS memory tracking leaking into user code 2017-08-25 11:29:58 -07:00
Wouter van Oortmerssen
1f0bd12851 Disabled numpy test in appveyor due to timeout.
It pulls in a LOT of dependencies, this will need to be done better.

Change-Id: Ib27effead194f6836facca01e9454a6037ad837a
2017-08-24 13:46:46 -07:00
Wouter van Oortmerssen
321a1c9dc0 Cleaned up namespace handling.
A Namespace object is now guaranteed unique.
This cleaned up some old workarounds and latent bugs.

Change-Id: Ic3f12d89947871b03b2c449ba51b3186f953adde
Tested: on Linux.
Bug: 21336857
2017-08-24 13:39:45 -07:00
Wouter van Oortmerssen
ac1015e3c4 Trimmed vtables of trailing zeroes.
This is something the format supports, but none of the builders
were doing. Can save 10-20% on FlatBuffer binary size!

Also fixed the Go tests.

Change-Id: I616c56ce9bbcfcaee23aa24f0532fcb60b6a8c75
Tested: on Linux.
2017-08-24 09:35:54 -07:00
Younguk Kim
513958ea72 Fix use of min and max when Windows.h is imported (#4411) 2017-08-17 09:35:50 -07:00
Wouter van Oortmerssen
2f2e4cced4 Noted that benchmarks are for C++
Change-Id: I12fbba7ffd2db47502a05eb06cedab49fd99c366
2017-08-14 16:36:42 -07:00
Wouter van Oortmerssen
f779962e3e Explained GetRoot<Monster> vs GetMonster.
Change-Id: Ic302096c07551b5c1aff0b261a329c46964cf337
2017-08-14 15:34:15 -07:00
Wouter van Oortmerssen
69776b9e7e Fixed .proto -> .fbs translating type bytes incorrectly.
Change-Id: Idb607360123d12c73dd1e045305007120b12131b
Tested: on Linux.
2017-08-14 14:45:29 -07:00
Wouter van Oortmerssen
00d726fc4c Further grammar.md fixes: union types, idents, string constants.
Change-Id: I51db0511c52c79f2b322a1fdef798b061941887b
2017-08-14 12:18:06 -07:00
Wouter van Oortmerssen
ad0f48d7e7 Fixed up grammar.md with rpc's and new scalar types.
Change-Id: Ie2965f48810bf24cccf098b69a9d471583efc3bf
2017-08-14 11:58:25 -07:00
Wouter van Oortmerssen
801e1b7699 Missing FieldDef initializer.
Change-Id: I5ed1f77868e201d7231102a106e08f3376b6adcf
2017-08-14 10:52:25 -07:00
Wouter van Oortmerssen
432e7582c6 Fixed file_identifier/extension leaking from included file.
Change-Id: I470143411e4ce6322e018a27bcc9cd40c15d9bf1
Tested: on Linux.
2017-08-14 10:41:39 -07:00
Wouter van Oortmerssen
d76113100a Cleaned up test output.
Change-Id: I4bec0e728cc162aa3f19091a0d154124ffbccdff
2017-08-14 09:30:10 -07:00
Wouter van Oortmerssen
dca33ddb75 Fixed root_type leaking in from included files.
Change-Id: I9378e375901f8a883eaeb2182955d690c358ed4b
Tested: on Linux.
2017-08-14 09:28:14 -07:00
rouzier
76744a4345 C++ Add new type vector_bool flexbuffers (#4410)
* Add new type vector_bool

* Update stl_emulation.h

Fix Is same typo

* Update stl_emulation.h
2017-08-14 08:44:56 -07:00
rouzier
b4e91091ec Internal doc (#4409)
* Add information about flexbuffer bool and null encoding

* Fix spelling errors

* Fix encoding example for flexbuffer map
2017-08-14 08:33:38 -07:00
Wouter van Oortmerssen
d5f5d382eb Added VS crtdbg memory leak tracking 2017-08-11 12:24:33 -07:00
Wouter van Oortmerssen
ffddbdc7ab Added missing generated code.
Change-Id: I7201d6891f56094178656a76bf0f87cf36d12554
2017-08-11 09:28:06 -07:00
Kamil Rojewski
46bb05d952 Vector of unions for TS/JS and PHP (#4404)
* Eclipse ignore

* TypeScript support

* Prefixing enums

* Test results

* Merged JS and TS generators

* Fixed AppVeyor build problems

* Fixed more AppVeyor build problems

* Fixed more AppVeyor build problems

* Changed TS flag to options struct

* Storing options by value

* Removed unneeded const

* Re-export support for unions

* Uint support

* Casting bools to numbers for mutation

* TS shell tests

* Reverted generates js test file to original version

* Backing up js tests and properly generating test data

* Not importing flatbuffers for TS test generation

* Not overwriting generated js for tests

* AppVeyor test fixes

* Generating the most strict TS code possible

* Not returning null when creating vectors

* Not returning null from struct contructors

* Vector of unions for ts/js

* Sanity check for languages

* Indentation fix + output test files

* Vectors of unions for php

* Fixes to union vector handling + tests
2017-08-11 09:24:36 -07:00
Kamil Rojewski
7cc72e4b11 Copying required field to union type vector (#4407)
* Eclipse ignore

* TypeScript support

* Prefixing enums

* Test results

* Merged JS and TS generators

* Fixed AppVeyor build problems

* Fixed more AppVeyor build problems

* Fixed more AppVeyor build problems

* Changed TS flag to options struct

* Storing options by value

* Removed unneeded const

* Re-export support for unions

* Uint support

* Casting bools to numbers for mutation

* TS shell tests

* Reverted generates js test file to original version

* Backing up js tests and properly generating test data

* Not importing flatbuffers for TS test generation

* Not overwriting generated js for tests

* AppVeyor test fixes

* Generating the most strict TS code possible

* Not returning null when creating vectors

* Not returning null from struct contructors

* Copying required field to union type vector

* Removed unneccessary bool
2017-08-11 09:19:28 -07:00
Wouter van Oortmerssen
a6a3f59253 Make flatc not silently skip schema files not ending in .fbs
Change-Id: I58463b321703b2ef0dc3f3062633909b86eca1a9
Tested: on Linux.
2017-08-10 16:31:25 -07:00
Wouter van Oortmerssen
8a58aafda1 Make it an error if a field has the same name as a table.
Change-Id: Ie5a3bb5a3643cd48e1cc75fe170a7b8a7c2cc8ed
Tested: on Linux.
2017-08-10 14:22:03 -07:00
Wouter van Oortmerssen
8dc1641c8a Forgot to update pom.xml in recent 1.7.1 release.
Change-Id: Ia6d6967546c0a2a5340a93e54c46d2630fff92fe
2017-08-10 11:35:58 -07:00
Wouter van Oortmerssen
4b27c92910 Misc documentation fixes.
Change-Id: Id7be5baba7d8a11ca050e8d94d95857406690378
2017-08-10 11:25:13 -07:00
Wouter van Oortmerssen
7fe281295f Fixed clang-tidy warnings.
Change-Id: Ib94ef29254c116b60e4ff298baa2ce323ac9655c
Tested: on Linux.
2017-08-07 15:33:36 -07:00
Wouter van Oortmerssen
917ff81b46 Added missing generated code from past commits.
Change-Id: I43e8de5a2ac224836a79661cc03bf37ac6d509fe
2017-08-07 14:55:05 -07:00
Wouter van Oortmerssen
8a2cc7cc4e Linked to Mikkel's binary format documentation.
Change-Id: I5054e37833d59bbe925cac2000a453fbee8ef54b
2017-08-07 14:53:54 -07:00
Wouter van Oortmerssen
a64d968473 Public accessor for buffer size of flexbuffers::Builder
Change-Id: Iff7895aebeba9c2940e26a3edbdf2d3f1b0d9b17
2017-08-07 13:24:42 -07:00
rouzier
a2b1bfc107 [c++] Add support for boolean types in flexbuffers (#4386)
* Add support for boolean types in flexbuffers

* Simplify casting number <=> boolean

* Added comments for tests

* Add proper support for Booleans

* Bad rebase

* No special case for strings

* Removed unused test

* Simplify logic
2017-08-04 08:04:28 -07:00
MikkelFJ
f2b3705c2c Add scalar type aliases for int8, uint8, ..., f32, f64 (#4400)
* Add type aliases

* Add generated code

* Rebase master
2017-08-02 08:07:43 -07:00
Kevin Rose
3282a84e30 [Python] (scalar) vector reading speedup via numpy (#4390)
* Add numpy accessor to python flatbuffers scalar vectors

* Update python tests to test numpy vector accessor

* Update appveyor CI to run Python tests, save generated code as artifact

* Update example generated python code

* Add numpy info to python usage docs

* Update test schema and python tests w/ multi-byte vector

* did not mean to push profiling code

* adding float64 numpy tests
2017-08-01 08:34:00 -07:00
Christian Helmich
89a68942ac Added support for nested flatbuffers serializing to json (#4391)
* added bool for nested_flatbuffer
setting bool flag nested_flatbuffer according to attributes
setting nested type

* added JSON serialization for nested flatbuffers

* simplified lookup of nested_flatbuffer StructDef

* added nested_flatbuffer parsing workound relying on flexbuffers

* moved nested flatbuffer parsing into its own function for clarity
removed flexbuffers workound to simplify and speed up nested_flatbuffer parsing
added support for 'legacy' nested_flatbuffers, ubyte arrays

* inlined functions for nested parser init/clean since only used once

* whitespace formatting

* changed type of FieldDef.nested_flatbuffer from bool to StructDef*
removed subsequent type lookups

* removed copies of unrequired data when initializing nested parser

* applied changes requested by reviewer

* removed superfluous lookup of nested_flatbuffer field attributes

* renamed camelCased variables to snake_case
2017-07-28 10:27:51 -07:00
Manuel Kroiss
360c34467c Adding accessors for IsBlob and Blob.data (#4398) 2017-07-27 09:06:02 -07:00
Stewart Miles
265e43faf0 Merge pull request #4395 from stewartmiles/master
Test case for CreateVectorOfStructs() using a callback.
2017-07-24 15:35:16 -07:00
Stewart Miles
f064a6cc60 Test case for CreateVectorOfStructs() using a callback.
Fixes issue #4392, also fixed C++98 compatible code generation in tests.

Change-Id: Ia5833026e615ad19d24a0439bdba2e3b45c5f86c
2017-07-24 14:19:49 -07:00
Christian Helmich
7fead0f140 forwarding IDLOptions.strict_json to flexbuffers .ToString() (#4394) 2017-07-24 09:33:40 -07:00
Stewart Miles
d6f14b704f Merge pull request #4383 from stewartmiles/master
C++98 (stlport) support for core FlatBuffers and FlexBuffers.
2017-07-20 12:24:38 -07:00
Stewart Miles
a892322203 C++98 (stlport) support for core FlatBuffers and FlexBuffers.
* Added internal - limited - implementation of flatbuffers::unique_ptr
  for STLs that don't ship with std::unique_ptr.  In C++11 and beyond
  this is just an alias for std::unique_ptr.
* Aliased used type traits structs is_scalar is_floating_point is_unsigned
  into flatbuffers namespace so they can be replaced in C++98 implementations.
  Right now these point at stlport's TR1 implementations.
* Wrapped vector::data() in vector_data().
* Wrapped vector::emplace_back() in vector_emplace_back().
* Wrapper string::back() in string_back().
* Added variants of FlatBufferBuilder::CreateVector() and
  FlatBufferBuilder::CreateVectorOfStructs() that allow the use of plain
  function pointers.
  Generated code has also been modified to use plain functions to build objects
  rather than std::function() so all generated code will work in C++98
  applications.
* Added flexbuffers::Builder::Vector(), flexbuffers::Builder::TypedVector()
  and flexbuffers::Builder::Map() methods that allow the use of plain function
  pointers.
* Changed Parser to internally use plain function pointers when parsing table
  and vector delimiters.
* Added specializations of NumToString() for 64-bit types that aren't supported
  by stringstream in stlport.
* Overloaded numeric_limits for 64-bit types not supported by stlport.
* Replaced build_apk.sh (which was broken by deprecation of the
  "android" tool in the Android SDK) with build.gradle and the
  appropriate gradle wrapper to build an APK.
* Switched Android build to build against all STL variants.
* Updated travis configuration to build Android test and sample.

Tested:
* Verified all tests continue to work on Linux, OSX and Android.
* Verified Travis build is green.

Change-Id: I9e634363793f85b9f141d21454b10686020a2065
2017-07-20 11:01:00 -07:00
schoetbi
2e2063cbeb idl_parser.cpp ignores $schema in input json (#4382)
* idl_parser.cpp ignores $schema in input json
#4381

* idl_parser.cpp: Fixed ci error signed unsigned comparison

* idl_parser.cpp: replaced case insensitive search for $schema with case sensitive search

* idl_parser.cpp: Expecting a string constant after $schema
#4382
2017-07-19 08:58:48 -07:00
Alex Wasserman
625c989875 Java: Added ByteBufferFactory interface and sizedInputStream method. (#4379)
The ByteBufferFactory interface gives the user an option to specify
the method in which the internal ByteBuffer is allocated. This provides
flexibility in the type of ByteBuffer that can be used.
The sizedInputStream method is an alternative to sizedByteArray that
does not make a copy of the data in memory.
2017-07-13 08:33:32 -07:00
schoetbi
f20204180d Json schema (#4369)
* Added empty generator for json schema (idl_gen_json_schema.cpp)
#4360

* JsonSchemaGenerator: output of tables implemented

current problems:
- typenames are not correct
- array types need to be deduced

#4360

* JsonSchemaGenerator: Corrected generation of typenames
Current problems: enum types not written correctly
#4360

* JsonSchemaGenerator: Added generation of enum types
#4360

* idl_gen_json_schema.cpp: Write required properties to schema
#4360

* idl_gen_json_schema.cpp: Export Types including namespace
#4360

* idl_gen_json_schema.cpp: Fixed Json format
#4360

* idl_gen_json_schema.cpp: Formatted according to google code style
#4360

* Checked in monster_test.bfbs with changes from master

* Added idl_gen_json_schema.cpp in CMakeLists.txt

* generate_code.bat: Added generation of json schema

* Added todo.md

* generate_code.sh: Added generation of json schema

* Addressed some review issues
- removed command line arg -S
- removed new lines
- fixed codestyle in template functions
- removed usage of stringstream
- idented json schema
#4360

* removed auto in idl_gen_json_schema.cpp

* idl_gen_json_schema.cpp: changed iterator declarations to auto
#4360

* deleted todo.md

* idl_gen_json_schema.cpp: Removed keyword "override" so that vs2010 can compile

* idl_gen_json_schema.cpp: switch statement in GenType handeles all enum-members

* idl_gen_json_schema.cpp: Removed cerr output

* idl_gen_json_schema.cpp: Avoid vector copying

* idl_gen_json_schema.cpp: Fixed identation of json schema output

* idl_gen_json_schema.cpp: Do not output empty descriptions
2017-07-10 08:05:59 -07:00
Robbie McElrath
0e85eeef2c Make inter-file cycles compile (#4364) 2017-06-26 09:07:02 -07:00
Andrei Stoica
b0fa5e0f42 Make flatbuffers work with ArduinoSTL (#4357) (#4361)
*Keep legacy compatibility with StandardCplusplus lib (utility.h)
2017-06-21 08:26:37 -07:00
Wouter van Oortmerssen
25a15950f5 Avoiding wrong template specialization on new CreateVector
Change-Id: I0da57cc71318ea13c10b547e2dfe3a2d4f32b4d9
Tested: on OS X.
2017-06-20 09:42:07 -07:00
Wouter van Oortmerssen
6f94fb51b1 Updated version numbers to 1.7.0
Change-Id: If2802ca48b61cfa7e5ec131e2a268400523217e2
2017-06-16 16:15:02 -07:00
Christopher Berner
57f3752d5e Optimize CreateVector for types > 1 byte on little endian (#4355)
This gives a 10x speed up in my test, when creating a Vector of floats
2017-06-16 15:29:47 -07:00
Wouter van Oortmerssen
f52f848b95 Added move assignment operator to DetachedBuffer.
Change-Id: I4610946ac27d9d0d73c2fc2e4834bd2cfed88cdc
Tested: on Linux.
2017-06-16 15:22:40 -07:00
Wouter van Oortmerssen
3c3742a54a Adding a method to get the file identifier from a flatbuffer.
Change-Id: Ie28fd1f0b463aac23647d38921600f15c8b7c10a
2017-06-16 12:30:36 -07:00
Wouter van Oortmerssen
f325cce6fd Initial support for parsing (and generating) Protobuf ASCII.
Change-Id: I955b4b3eed27f26773d7dc0acceff13c88d1333d
Tested: on Linux.
2017-06-16 11:57:58 -07:00
Wouter van Oortmerssen
88a85ffbbd Added convenient schema registry.
Change-Id: I9d71375059369fbc538d0d051d8d2885e467bf29
Tested: on Mac OS X.
2017-06-16 11:10:07 -07:00
Wouter van Oortmerssen
35cbd23f63 Fixed missing lambda return type.
Change-Id: I48d41a240c8bf362b1f931f20a3ed9ae64f2d295
2017-06-16 09:54:25 -07:00
Stephen Lane-Walsh
210a1ab969 Fixed build error in Visual Studio 2017 (#4353)
flatbuffers.h(591): error C2220: warning treated as error - no 'object' file generated
flatbuffers.h(591): warning C4267: 'return': conversion from 'size_t' to 'flatbuffers::uoffset_t', possible loss of data
2017-06-16 09:53:53 -07:00
Lawrence Chan
90c8ded449 gRPC: fix memory leak (#4351)
SerializationTraits<T>::Deserialize _transfers_ ownership of the buffer,
so we must destroy it.

This commit also includes some misc fixes:
- Use grpc::Status::OK rather than default ctor for clarity.
- Check for a null buffer passed into Deserialize, and handle it the
  same way as the protobuf deserializer.
2017-06-13 08:50:27 -07:00
Wouter van Oortmerssen
8f864aad7b Added (nested) FlexBuffer JSON parsing and output.
FlexBuffer parser is just 40 lines of code (on top of existing parser!).

Change-Id: Idebebadafb661ca5333f5621139031f6df3c3e1a
Tested: on Linux.
2017-06-12 16:40:47 -07:00
Wouter van Oortmerssen
dddd0865cb Added nested FlexBuffer parsing
Change-Id: I918b66eb5646d035e3aae675f745802eb54b03ea
2017-06-12 14:34:45 -07:00
Christopher Berner
0a81eb6463 Fix memory leak in Message move operator (#4344) 2017-06-12 11:23:55 -07:00
Guillaume Giraud
b1740688bf [cpp] Json parsing: adding support for parsing nested lists and top level lists (#4338)
* Extended json parsing capability: add support for parsing nested lists and top level lists

* Stylistic conformance with surrounding code + generalized comments

* More code tidy-up for stylistic conformance with surrounding code

* Blank lines

* Reverted changes related to top-level list parsing

* Styling: newline before else

* Taking out ProcessTableFields which is no longer needed as the top level list change was reverted.
2017-06-07 16:58:19 -07:00
Stephan T. Lavavej
86b505e412 [C++] Remove std::iterator usage (#4340) (#4341)
* [C++] Remove std::iterator usage (#4340)

Inheriting from std::iterator has never been required, and it's
deprecated in C++17. It can be replaced by directly providing typedefs.

Include <iterator> for std::random_access_iterator_tag.

Note that structs default to public access control.

* [C++] Change whitespace style in typedefs.
2017-06-07 16:26:06 -07:00
Lawrence Chan
da67c0a71f [C++] Improve flatbuffers + gRPC integration (#4310)
* Rework flatbuffers + gRPC integration

- Introduce `flatbuffers::grpc::Message<T>`, a `grpc_slice`-backed
message buffer that handles refcounting and allows flatbuffers to
transfer ownership to gRPC efficiently. This replaces
`flatbuffers::BufferRef<T>`, which required a copy call and was also
unsafe w.r.t. buffer lifetime.
- Introduce `flatbuffers::grpc::MessageBuilder`, a gRPC-specific builder
that forces a `grpc_slice`-backed allocator and also adds some helpful
`Message<T>`-related methods.
- Update serializers accordingly (now zero-copy between flatbuffers and
gRPC).

* gRPC: verify messages by default, but allow user to override

* gRPC: fix some formatting issues

* Disable verification by default, but add helper method

* Make FlatBufferBuilder fields protected + remove vec accessor

* Use bool add_ref parameter to toggle refcount incr

* Remove unnecessary inline specifiers

* Fix formatting

* Use auto

* Remove empty lines

* Use grpc_slice helper macros

* Simplify reset code

* Disable Message copy ctor and assignment by default

* Remove unused member

* Enable gRPC verification by default

* Use auto

* Bake in message verification (remove template specialization)

* Add RoundUp func

* Consolidate gRPC message copy flag

* Make vector_downward allocations fully lazy

* Test message verification failure code/message

* Add grpctest verification test comments

* Simplify reallocate implementation

* Make initial_size a size_t

* Use ternary op for growth_policy

* Use truthiness rather than dont explicit nullptr check

* Indent preprocessor directives

* Remove grpc message copy/assignment

* Fix a few bugs

* Add gRPC example

* Add basic gRPC docs

* Use doxygen EXAMPLE_PATH + @include

* Reference example fbs in grpc docs

* Move gRPC examples into grpc/samples

* Fix pointer/reference formatting

* Use std::function rather than templated callback func

* Create fresh message builder for each request

* Use Clear() in Reset() impl

* Use FLATBUFFERS_CONSTEXPR
2017-06-07 13:56:49 -07:00
rufeooo
dadd1a926e Generate a C++ function for EnumValues{{ENUM_NAME}} (#4337)
* enables "for each" logic on enumeration types
2017-06-07 13:49:56 -07:00
vabr-g
01c50d57a6 [C++] Remove std::move around a raw pointer in flatbuffers.h (#4339)
* Remove std::move around a raw pointer

Calling std::move on a raw pointer has no advantage to just copying its value. Moreover, it is confusing, because it indicates that the argument is movable in some non-trivial way (e.g., is it actually meant to be a smart pointer?). More context in https://crbug.com/729393.

* Remove the move constructor altogether
2017-06-05 10:33:04 -07:00
Wouter van Oortmerssen
e9f1f4d9b7 Disallowing field name same as table name.
Change-Id: I4b5d822cc4eda975949d1b7cf33674c5bbf9d4b1
Tested: on Linux.
2017-06-02 15:55:02 -07:00
Wouter van Oortmerssen
dd05f3249a Added test for nested FlatBuffers functionality.
Also fixed that the parsing test wasn't calling the buffer
testing function.

Change-Id: I5baae071bf0832c7797b4ef1d19d9b015e3ff5bc
Tested: on Linux.
2017-06-02 12:36:18 -07:00
AntonYudintsev
43611fcc0b refactor flatbuffers.h and util.h so FlexBuffers do not depend on flatbuffers.h (#4331)
FlexBuffers are actually completely unrelated to FlatBuffers and can be used separately.
However, since they utilize several utility functions from flatbuffer.h, they require this header file, which creates unreasonable dependency.
By moving those utility functions to separate base header, both libraries can use same code but still be independent
2017-06-02 10:26:11 -07:00
Pavel Kalinnikov
642254bee6 Track included files in PATH-agnostic way. (#4329)
* Track included files in PATH-agnostic way.

Use full paths as keys in the map of included files. Store logical
include path as a value, in order to put it to the generated file.

* Fix tests by accepting null |include_filename|.

* Fix self-includes code generators.
2017-06-02 08:50:18 -07:00
Wouter van Oortmerssen
22743ca45a Fixed --keep-prefix functionality.
Changing to keep include prefixes had two side effects: the main
file being parsed wasn't filtered out anymore, and include directory
paths would be added to the path in the include statement.

Also moved the include_test*.fbs files to sub directories so we
can actually test the handling of -I etc.

tested: on Linux.

Change-Id: Ibae095cea7ab0cccbac15cfb5171719f6b5cad8c
2017-05-24 16:26:57 -07:00
Lawrence Chan
fb87c0d3c6 [C++] Improve Allocator handling (#4312)
* Improve Allocator handling

- Templatize Allocator on vector_downward, and make it own the allocator
instance so it can manage lifetimes.
- Templatize + rename FlatBufferBuilderT accordingly, and add a typedef
to FlatBufferBuilder so old code continues to work.
- Fix some issues with the release deleter
- More details in github issue #4311

* Fix constexpr for older MSVC

* Reimplement allocator improvements via inheritance

Instead of templates, use an abstract base class and some unique_ptrs to
implement the new and improved allocator.

* Fix misplaced newline

* Add missing override keyword

* Add macro for func delete to support older compilers

* Explicitly move BufferDeleter (maybe fixes VS 10?)

* Revert previous attempt at VS10 fix

* Try yet another workaround for MS 10

* Use FLATBUFFERS_NOEXCEPT macro

* Add FLATBUFFERS_OVERRIDE macro

* Fix some issues with MSVC 16 hack

* Remove dep on unique_ptr

* Update DEPRECATED macro with a message

* Sigh, no delegating ctors before c++11

* Fix simple_allocator stub

* Relax FlatBufferBuilder ctor

* Add vector_downward reset + assert in clear

* Rename DetachedBuffer to FlatBuffer + remove unnecessary deprecations

* Add flatbuffers::FlatBufferBuilder::Release()

* Address remaining allocator-improvements comments
2017-05-24 13:55:15 -07:00
Wouter van Oortmerssen
398ae0cb6b Some code in the samples and docs still used old C# API.
Change-Id: I7914c88ad7b31baa7586771423069dc2b90d534f
Tested: on Linux.
2017-05-22 15:14:46 -07:00
Wouter van Oortmerssen
aaf5598a03 Standardized internal path handling on Posix separators.
There were several possible bugs involving paths not being
recognized as being the same on Windows. Rather than trying
to ensure all code deals with / and \ correctly, paths now
get transformed to / on input, fixing all current and
future such bugs.

Tested: on OS X.
2017-05-18 17:22:47 -07:00
Kamil Rojewski
3d2cf554d7 Fix for invalid null returns (#4318)
* Eclipse ignore

* TypeScript support

* Prefixing enums

* Test results

* Merged JS and TS generators

* Fixed AppVeyor build problems

* Fixed more AppVeyor build problems

* Fixed more AppVeyor build problems

* Changed TS flag to options struct

* Storing options by value

* Removed unneeded const

* Re-export support for unions

* Uint support

* Casting bools to numbers for mutation

* TS shell tests

* Reverted generates js test file to original version

* Backing up js tests and properly generating test data

* Not importing flatbuffers for TS test generation

* Not overwriting generated js for tests

* AppVeyor test fixes

* Generating the most strict TS code possible

* Not returning null when creating vectors

* Not returning null from struct contructors
2017-05-18 10:30:30 -07:00
sfariv
55dec4d2f8 added check for presence of required fields. (flatc) c++ (#4316)
* added check for presence of required fields.

* updates to resolve Travis CI build error.

* fixes for resolving appveyor build errors.

* fixes for resolving appveyor build errors.

* fixes for resolving appveyor build errors.

* updates per aardappel's comments.

* updated a variable's name.

* updates per aardappel's comments.
2017-05-18 09:32:04 -07:00
schoetbi
0f5f7faa9f C#: Added <autogenerated> in cs generator file header comment (#4291)
* Added <autogenerated> in cs generator file header comment
#4287

* CS: Added xml-correct file header comment including "<auto-generated>...</auto-generated>"
code_generators.cpp: FlatBuffersGeneratedWarning() function replaced by compile time constant "GeneratedWarning"
 also removed extra newlines at end of GeneratedWarning to be able to generate a xml well formed file comment for cs files
#4291

* code_generators: Changed static string GeneratedWarning back to function FlatBuffersGeneratedWarning()
#4291

* Added modified Unit-Test files
#4291

* idl_gen_general: Add autogenerated only in C# code
#4291
2017-05-16 14:28:34 -07:00
Wouter van Oortmerssen
90daabd5b1 Made root test path configurable.
Change-Id: I9629a7648f0c3346c4724ca8938fed47d7828018
Tested: on Linux.
2017-05-15 16:57:39 -07:00
Wouter van Oortmerssen
262e1d7bf9 Updated tutorial with a vector of structs example.
Since it wasn't documented and very different from a vector of
tables, this has caused a lot of confusion in the past.

Change-Id: Iab47c61b55c19abe5c4f25c86d71335a6b6321ca
2017-05-15 13:41:27 -07:00
Wouter van Oortmerssen
c559eb451e Made codegen always output a file, even on an empty schema.
Previously, we had a check to simply skip such files, but this
tends to make build systems unhappy.

This only affects C++ and JS, since other language output per-class
files.

Change-Id: I54224642725bbafb9f6e1654ed3693e62ca9f7d7
Tested: on Linux.
2017-05-12 16:08:58 -07:00
Lawrence Chan
6a7ec85e83 [C++] Fix code gen indentation when empty Print (#4313)
* Fix C++ code gen indentation when empty Print

* Also commit modified tests/monster_test.bfbs
2017-05-12 14:36:35 -07:00
akamat-ibm
81ecc98e02 Adding support for s390x (#4297)
* changes to support s390x

* added flag for s390x

* Adding support for Linux s390x
2017-05-12 10:12:19 -07:00
Per Grön
9aeeddf5ac C++/Go: Update gRPC related code to work with gRPC 1.3+ (#4305)
* Don't fail the build on unused parameters

gRPC headers have unused parameters so this breaks the test build.

* Pull in updated compiler files from gRPC

There have been some API breaks in gRPC lately. This commit
pulls in the most recent version of the files in this repo
that are just copied from gRPC.

* Modify the gRPC files so that they can work with Flatbuffers

The files taken from gRPC do not work out-of-the-box with Flatbuffers.
This commit modifies them so that they work. Hopefully this commit
will be able to serve as a guide or maybe even be cherry-picked on
top of new versions of those files as newer versions from gRPC are
pulled in.

* Adjust the rest of Flatbuffers to work with the new gRPC

* Change idl_gen_grpc.cpp to work with the new API
* Add missing #include in flatbuffers/grpc.h
* Run tests/generate_code.sh and check in the results
* Don't link with grpc++_unsecure and (secure) grpc. That's just weird

* Revert unrelated JS/TS test changes

* Simplify compiler/config.h

There is no need to import this file from gRPC. In fact, it probably
makes sense to not do so, since it seems to be intended to have
project specific configuration in it.

* Don't emit C++ types in the Go gRPC code generator

* Don't emit C++ #includes in generated gRPC code

Before this PR, there was a Go-specific additional_includes method
in schema_interface.h, which is shared with the gRPC repo. The
additional parameter to FlatBufFile in idl_gen_grpc.cpp makes that
unnecessary, which means we need less Flatbuffer-specific changes
in gRPC.
2017-05-12 09:48:17 -07:00
Wouter van Oortmerssen
c7bfe06c54 Reverting part of PR #4286
This is because it trips up the Closure compiler with errors like:

ERROR - assignment to property bb of SomeTable
found : undefined
required: (flatbuffers.ByteBuffer|null)
this.bb = undefined;
^^^^^^^^^^^^^^^^^^^

Change-Id: Iaf032b5249ec655e151331e81532e549c12bcd78
2017-05-10 18:04:53 -07:00
Wouter van Oortmerssen
349a391208 Removed unnecessary check for Offset in AssertScalarT()
This will avoid it accidentally accepting structs of size 4.

Change-Id: I251285ae1e4bffb859367dcf89562741a3980bba
Tested: on Linux.
2017-05-10 18:00:27 -07:00
Wouter van Oortmerssen
9d01bfaea3 Added error message for union values out of range.
Change-Id: I481afcde6a554d1cad519ff95acac7f38a7f4ee5
Tested: on Linux.
2017-05-10 17:21:47 -07:00
Travis Wellman
cfbab31fb1 cleaning up JavaTest.sh - quote paths, and less error-prone deletion (#4301) 2017-05-10 16:45:08 -07:00
Wouter van Oortmerssen
cb2481efdc Ensured flatc.exe is statically linked on Windows 2017-05-10 16:20:53 -07:00
Wouter van Oortmerssen
d7ac3788e8 Clarified the semantics of the Offset type.
Change-Id: Iccc36d24321ac4d556692ac715c0cc69a2c9e09e
Tested: on Linux.
2017-05-10 14:55:11 -07:00
Wouter van Oortmerssen
a0a313b101 Added missing js/ts generated code.
Change-Id: I146e9e1b8f997c11d1675dbef1b958ddbd181092
2017-05-10 13:25:51 -07:00
Wouter van Oortmerssen
93c0960c3a Added --keep-prefix to not strip schema include path in C++ includes.
Change-Id: I3c6356fc6664072796f273096df64829108b4a34
Tested: on Linux.
2017-05-10 13:21:20 -07:00
Wouter van Oortmerssen
04d734d6d2 Added more test scripts: Mono on Linux, and one for all.
Change-Id: Ia107557225db27b396f0d666c5c5b1b324ea22fa
Tested: on Linux.
2017-05-10 12:55:27 -07:00
Wouter van Oortmerssen
8468ea1ab4 Fixed LookupByKey for Java & C#
Change-Id: I05c02223675dee241d1ae8cb466e5186444058c8
Tested: on Linux.
2017-05-10 12:55:27 -07:00
水樹素子
0920d663d5 [C++] Add grpc/streaming test and fix Deserialize (#4296)
* [C++] Add delete msg->buf

* [C++] Add grpc streaming test

* Use free instead of delete

* Refactoring grpctest
2017-05-08 13:49:34 -07:00
Heiko Becker
bbb72f0b73 Tweak fallthrough comments to get recognized by gcc7 (#4298)
GCC gained a new warning, -Wimplicit-fallthrough, which warns about
implicitly falling through a case statement. The regular expressions
used at the default level (-Wimplicit-fallthrough=3) don't match with
a colon at the end. The comment also needs to be followed (after
optional whitespace and other comments) by a 'case' or 'default'
keyword, i.e. it will not be recognized with a '}' between the comment
and the keyword.
2017-05-08 13:35:55 -07:00
moti
8f8a27d6e5 [C++] Add grpc_slice_unref(slice) (#4294) 2017-05-04 15:44:31 -07:00
Kamil Rojewski
86777bd66b Generating the most strict TS code possible (#4286)
* Eclipse ignore

* TypeScript support

* Prefixing enums

* Test results

* Merged JS and TS generators

* Fixed AppVeyor build problems

* Fixed more AppVeyor build problems

* Fixed more AppVeyor build problems

* Changed TS flag to options struct

* Storing options by value

* Removed unneeded const

* Re-export support for unions

* Uint support

* Casting bools to numbers for mutation

* TS shell tests

* Reverted generates js test file to original version

* Backing up js tests and properly generating test data

* Not importing flatbuffers for TS test generation

* Not overwriting generated js for tests

* AppVeyor test fixes

* Generating the most strict TS code possible
2017-05-01 16:05:53 -07:00
Wouter van Oortmerssen
8b92122f33 Made the verifier catch zero-offsets.
Zero offsets are non-sensical in FlatBuffers (since offsets are
relative to themselves) but were allowed by the verifier. This could
cause buffers made up of all zeroes to be interpreted as correct
buffers with an empty root object.

Generally, not allowing such offsets will make the verifier more
likely to catch problems earlier.

Change-Id: I54010bea29721b326ff8e5348fcd9fe78e5e7506
Tested: on Linux.
2017-04-26 14:26:18 -07:00
Wouter van Oortmerssen
e93a5652d0 Fixes for VS 2015 build.
Change-Id: I23280e611163a89b8eba7b9b0016c297fea2396e
2017-04-24 10:48:35 -07:00
Wouter van Oortmerssen
0c80b3a7cc Added VS 2015 test to AppVeyor CI.
Change-Id: I354c13fbe6f159058fbeff47100ef357e99c6cd5
2017-04-24 10:06:55 -07:00
Wouter van Oortmerssen
f52ddfbd68 Fix Android STLPort build.
Change-Id: Iceca7b8b455c8463d9b82b928332a875dee3d19e
2017-04-21 10:50:03 -07:00
Kamil Rojewski
808b44f87a TS tests fixes (#4265)
* Eclipse ignore

* TypeScript support

* Prefixing enums

* Test results

* Merged JS and TS generators

* Fixed AppVeyor build problems

* Fixed more AppVeyor build problems

* Fixed more AppVeyor build problems

* Changed TS flag to options struct

* Storing options by value

* Removed unneeded const

* Re-export support for unions

* Uint support

* Casting bools to numbers for mutation

* TS shell tests

* Reverted generates js test file to original version

* Backing up js tests and properly generating test data

* Not importing flatbuffers for TS test generation

* Not overwriting generated js for tests

* AppVeyor test fixes
2017-04-21 09:29:42 -07:00
Wouter van Oortmerssen
340d1a3447 Fix FlexBuffers writing incomplete length for 64-bit vectors. 2017-04-19 17:51:52 -07:00
Carlos Sanchez
ba20d9bff3 Added a clear function for purging all data that is holded by the FlatBuffer. (#4259) 2017-04-19 17:06:33 -07:00
Dmitry Ermolov
370693a200 Specify `std' namespace for remove function (#4268) 2017-04-19 16:55:41 -07:00
Christian Helmich
33932ceea4 Fixed CreateVectorOfStructs for native_type (2nd try) (#4276)
* Added support for serializing native_type with CreateVectorOfNativeStructs

* Added support for serializing native_type with CreateVectorOfSortedNativeStructs

* Added C++ code generation for vectors of native_types
2017-04-19 10:14:31 -07:00
Per Eckerdal
fb03f78fb4 Fix minor const correctness issue (#4271) 2017-04-19 08:56:55 -07:00
Wouter van Oortmerssen
523f3833eb VS fix for ambiguous union assignment operator.
Change-Id: I1c37db1ced462fd558d3e893a501341f3eca6379
2017-04-17 18:00:41 -07:00
Wouter van Oortmerssen
46497e4f9a Fixed hashed values in JSON for signed ints.
Change-Id: Iae389c6dc9776058b39f4017d30efbf9580aced1
Tested: on Linux.
2017-04-17 17:40:02 -07:00
Wouter van Oortmerssen
b627b7c6c6 Undo PR: make flatbuffers.js into a UMD module (#4228)
This PR did not work in all JS environments and caused
downstream breakage.

Change-Id: Ib565129e26622d02bad2d45816bd05f6b961b994
2017-04-17 17:31:03 -07:00
Wouter van Oortmerssen
e093f72d00 Improved union copy constructor.
It now at least works in simple cases.

Change-Id: I3af0738e676e62166b69accaa6bd19f531fbe5ee
Tested: on Linux.
2017-04-17 17:27:20 -07:00
Wouter van Oortmerssen
728bb64fed Fixed clang needing union copy constructor.
Move constructors are present, which it should use instead.

This is a temp fix to make it compile, but eventually we should
generate a proper copy constructor just in-case people want to
copy objects with unions.

Tested on: Linux, OS X.

Change-Id: Idf85419995c96f5959061882157541573e306083
2017-04-17 14:01:43 -07:00
Jason Stubbs
a07f0d428d [C++] fix bounds checking on integer parsing (#4250)
* fix bounds checking on integer parsing

the previous code was allowing 255 for int8_t, similar for int16_t
and int32_t, and even negative values for unsignd types.

this patch fixes bounds checking for 8-bit, 16-bit and 32-bit types.
testing for both acceptable values and unacceptable values at the
boundaries are also improved.

bounds checking on 64-bit types isn't addressed by this patch.

* fix 'unary minus operator applied to unsigned type, result still unsigned'

* fix & placement
2017-04-17 11:19:43 -07:00
Wouter van Oortmerssen
b90d4e049d VS warning fixes.
Change-Id: I19662241d56560c064cff73dbebfb2a81d226934
2017-04-12 17:56:19 -07:00
Wouter van Oortmerssen
b0752e179b Added support for structs and strings in unions.
(C++ only for now).
Also fixed vector of union support in the object API.

Bug: 36902939
Change-Id: I935f4cc2c303a4728e26c7916a8ec0adcd6f84cb
Tested: on Linux.
2017-04-12 17:47:47 -07:00
schoetbi
1fc12e0e5b C++ fixed compile error C2678 with msvc when using std::find_if on vectors (#4262)
In Debug mode it is checked that iterator begin is less than end
therefore the operator< in class VectorIterator is needed
2017-04-12 16:37:22 -07:00
chronoxor
e6fa7b1133 Fix Visual Studio 2017 new warning (C4244: 'argument': conversion fro… (#4261)
* Fix Visual Studio 2017 new warning (C4244: 'argument': conversion from 'int' to 'const char', possible loss of data)

* Fix Visual Studio 2017 pedantic warnings

* Fix Visual Studio 2017 pedantic warnings
2017-04-12 13:13:10 -07:00
Kamil Rojewski
28e7dbd3d3 TypeScript support (#4232)
* Eclipse ignore

* TypeScript support

* Prefixing enums

* Test results

* Merged JS and TS generators

* Fixed AppVeyor build problems

* Fixed more AppVeyor build problems

* Fixed more AppVeyor build problems

* Changed TS flag to options struct

* Storing options by value

* Removed unneeded const

* Re-export support for unions

* Uint support

* Casting bools to numbers for mutation

* TS shell tests

* Reverted generates js test file to original version

* Backing up js tests and properly generating test data
2017-04-10 10:01:13 -07:00
Iain van der Bloat
adc50051e0 make flatbuffers.js into a UMD module (#4228) 2017-04-07 17:14:01 -07:00
moti
2aec880347 [C++]Use noexcept in union type move ctor/Add move assingment (#4249)
* Use noexcept in union type move ctor/Add move assingment

* Add NOEXCEPT macro to deal with _MS_VER/Remove delegating ctor in union type class

* Add FLATBUFFERS_NOEXCEPT to generated union class
2017-03-29 18:00:20 -07:00
Wouter van Oortmerssen
238a8ebb15 Suppress warning in Flatbuffer VS2010 builds.
Change-Id: I4f66a96ba581704c1a384cc700b8fb731d3eeed4
2017-03-29 12:01:11 -07:00
Wouter van Oortmerssen
86992476da Update StackOverflow links to have relevant queries.
Change-Id: I59159fb7205e4802f041b749d502a8f305d4176c
2017-03-29 11:58:42 -07:00
Wouter van Oortmerssen
751aeabc80 Updated .gitignore for C#
Change-Id: I6c253b0ded187a4945f5e862aae721cf4fda6398
2017-03-29 11:55:20 -07:00
Wouter van Oortmerssen
b4bb1b103f Fix flatc code gen.
Mutable functions should return a non-const reference to the member variable.

Change-Id: I833077d2c9a38a5d71868e43aca6b250d79b6625
2017-03-29 11:51:20 -07:00
Wouter van Oortmerssen
cffd187fc7 Added missing generated code for C#
Change-Id: I1affced255eb96977119d8480793b5bba42f065f
2017-03-29 11:51:02 -07:00
Spencer Bench
ccfa317486 C#: Fixed possible conflicts between usings and user-supplied namespace (#4247)
* C#: Fixed possible conflicts between usings and user-supplied namespace

C#: Added the global qualifier to using directives to prevent possible conflicts with the user-supplied namespace. Also prevents unintentional type hiding. Resolves issue #4242.

* Updated C# generated code files
2017-03-29 11:09:25 -07:00
tianyapiaozi
a5cc2092a6 Support binary search for struct in cpp (#4245)
* Support binary search for struct in cpp

CreateVectorOfSortedStruct is provided for convenience.

* fix continuous-integration error

* add generated files

* compile Ability.cs in csharp test

* compile Ability.cs in csharp

* modify according to code review
2017-03-29 09:51:12 -07:00
Wouter van Oortmerssen
89041a1686 Add a VectorCast function that safely casts from
Vector<Offset<T>> to Vector<Offset<U>> if U is a base
class of T.

This is useful for when you want to generically
iterate over a vector of objects that derive from
flatbuffers::Table.

Change-Id: I59161e3b9f40501f72e02b46509be9dc8ab86c6b
2017-03-27 17:50:30 -07:00
Wouter van Oortmerssen
7a36419f24 Fixing closure compile compatibility when --gen-mutable is used.
Change-Id: I8bf575ba6dc795d2d2eec02fa8977dcc2594eaa6
2017-03-27 17:50:30 -07:00
Jesper Stemann Andersen
281284fa5d Fixed building and warnings on Arduino (16 bit platform). (#4197)
Building on Arduino fixed by conditional includes of cstdint and utility. In the Standard C++ for Arduino (port of uClibc++):
* cstdint is not present.
* utility is named utility.h.

Replaced size_t with uoffset_t for Verifier::max_tables_, max_depth_, depth_, and num_tables_ to ensure 32-bit values are used (and not 16-bit) - gave rise to a warning.
2017-03-27 09:38:04 -07:00
Lawrence Chan
1a27c7017a C++: Add default value handling to mutation/SetField code (#4230)
* Add default value handling to mutation/SetField code

* Shorten reflection SetField impl

* Modify impl to work with C++03

* Add more mutation tests

* Fail SetField if non-scalar

* Add IsScalar/IsInteger/IsFloat for reflection::BaseType

* Use new IsScalar/IsInteger/IsFloat in reflection SetField

* Assume scalar is either int or float
2017-03-20 17:36:27 -07:00
Flier Lu
b8f5f84437 add command line argument for go namespace (#4222) 2017-03-20 16:08:35 -07:00
Alexander Gallego
f2071e4f80 Add arbitrary string type to the native object API (#4218)
* Custom strings are very common for optimizations around small objects
  or growth style optimizations, i.e.: grow at 1.57 times vs doubling vs..

  A second common strategy is to cooperate w/ the memory allocator
  see FBString[1] and seastar[2] string for examples.

[1] fbstring: https://github.com/facebook/folly/blob/master/folly/docs/FBString.md
[2] sstring: https://github.com/scylladb/seastar/blob/master/core/sstring.hh
2017-03-20 16:02:04 -07:00
Jun Hyeon, Nam
9c25ecdcd1 C++: add String::str() function (#4234)
for convenience
2017-03-18 10:09:56 -07:00
Jun Hyeon, Nam
1beed12e59 fixed duplicate symbol error in flexbuffers.h (#4233)
1. modified the function that omitted inline.
2. changed the static global functions to inline functions.
2017-03-18 10:08:39 -07:00
Flier Lu
4cd71d67f1 GO: add _ postfix to identiy conflict golang keyword (#4221)
* add _ postfix to identiy conflict golang keyword

* make VS2010 happy
2017-03-15 18:34:53 -07:00
Aaron Hudon
d9bc5ec047 fixed flag for javascript (#4223)
--javascript flag does not work in the 1.6 flatc.exe, changed to --js
2017-03-15 15:16:43 -07:00
Koichi Shiraishi
c04c143cf0 tests: update monster_test.bfbs binary file with generate_code.sh (#4220)
Signed-off-by: Koichi Shiraishi <zchee.io@gmail.com>
2017-03-15 14:53:37 -07:00
Koichi Shiraishi
c6aae45364 sample: update auto-generated monster_generated.h (#4219)
Signed-off-by: Koichi Shiraishi <zchee.io@gmail.com>
2017-03-15 14:52:47 -07:00
Alexander Theißen
7f2a1c90d5 Prevent flatbuffers::Vector and flatbuffers::VectorOfAny to be copied (#4217) 2017-03-13 08:53:30 -07:00
chronoxor
f5387387de Pedantic Visual Studio build (/W4 /WX) (#4214)
* Pedantic Visual Studio build (/W4 /WX)

* Pedantic Visual Studio build (/W4 /WX)

* Pedantic Visual Studio build (/W4 /WX)

* Remove /wd4512 from CMakeLists.txt

* Suppress Visual Studio 4512 warning ('class' : assignment operator could not be generated)
2017-03-10 10:27:30 -08:00
Louis-Paul CORDIER
e7e4dc755d NoError was returning on DoParse method when file was empty (#4208)
* NoError was returning on DoParse method when file was empty.

* change NoError message in DoParse.
2017-03-10 08:50:44 -08:00
chronoxor
b8224809ad VS2015 warning "conditional expression is constant" (#4210)
* VS2015 warning "conditional expression is constant"

* VS2015 warning "conditional expression is constant"
2017-03-08 13:34:38 -08:00
Dale Lukas Peterson
bb22fb5756 Fix broken symlink to CONTRIBUTING.md (#4212) 2017-03-08 13:16:11 -08:00
Christian Helmich
ff274771ba fixed path being ignored in GenerateCppGRPC (#4207) 2017-03-08 09:08:40 -08:00
Hadriel Kaplan
15bf626191 Add a backwards-compatible version of VerifyBuffer() (#4201) 2017-03-08 08:25:37 -08:00
Zarian Waheed
ac106e835c Fixing broken link and added missing <map> header include. (#4199) 2017-03-03 09:47:52 -08:00
xiaohaoliang
640b525e83 optimization of FlatBufferBuilder::CreateVector() (#4198)
optimization of FlatBufferBuilder::CreateVector()
1. optimization of FlatBufferBuilder::CreateVector() for "1 == sizeof(T)" ( such as [byte], [ubyte]).
2. For my project, it was about 10x improvement on flatbuffers serialization.
3. why not "string": "string, which may only hold UTF-8 or 7-bit ASCII. For other text encodings or general binary data use vectors ([byte] or [ubyte]) instead."
2017-03-03 09:40:43 -08:00
Raman
0b379211dc Fixed problem with uint keys (#4172)
* Fixed problem with uint keys

* removed excess check

* Resolved problem with big uint, ubyte keys in Java
2017-02-28 14:16:50 -08:00
Louis-Paul CORDIER
bb223da258 C++ generator: Pre-allocating std::vector in UnPack methods. (#4187) 2017-02-25 22:10:17 -08:00
Andrei Lebedev
17c5f89d4f Fixed move constructor in generated union class (#4192)
* Fixed move constructor in generated union class

* Removed delegating constructor
2017-02-25 22:06:48 -08:00
Andrei Lebedev
695d26183a Remove libc++ and c++abi requirement on Linux with clang (#4189) 2017-02-25 21:47:57 -08:00
Kameiha
f5120a2aaf more safer (#4186)
push_small(T little_endian_t) => push_small(const T& little_endian_t)
2017-02-25 21:24:43 -08:00
Franken
037314a059 [C++] Additional accessors for fields of union types. (#4184)
* Additional accessors for fields of union types.

* Reveal the hidden parameter.

* External explicit specializations for templated accessors.

* Changes according to code style. Generated code included as well.
2017-02-25 21:23:32 -08:00
litianzhao
ebcfbbadf0 fix #4180: Long.prototype.toFloat64() overflow (#4182) 2017-02-20 11:20:56 -08:00
Wouter van Oortmerssen
6561c7a31f Temporarily disabled VS2010 warning 4512.
Change-Id: Ib75b4cc651ac8f67cd262c8293fca1ac590f6b71
2017-02-15 17:46:00 -08:00
Wouter van Oortmerssen
a6d98fb067 Fixed VS x64 warnings in flexbuffers.h 2017-02-15 17:41:00 -08:00
Wouter van Oortmerssen
3a2d3a232f Removed spurious "aa" from flatc usage message.
Change-Id: Ia1812d594882ce6c51002d07827ccec267d138bb
2017-02-15 14:59:25 -08:00
198 changed files with 18272 additions and 3693 deletions

0
.gitattributes vendored Executable file → Normal file
View File

15
.gitignore vendored Executable file → Normal file
View File

@@ -5,6 +5,7 @@
*.o.d
*.class
*.a
*.swp
*~
*.vcxproj
*.vcxproj.filters
@@ -43,11 +44,14 @@ flatsampletext.exe
grpctest
grpctest.exe
snapshot.sh
tags
tests/go_gen
tests/monsterdata_java_wire.mon
tests/monsterdata_go_wire.mon
tests/monsterdata_javascript_wire.mon
tests/unicode_test.mon
tests/ts/
tests/php/
CMakeLists.txt.user
CMakeScripts/**
CTestTestfile.cmake
@@ -66,3 +70,14 @@ build/VS2010/FlatBuffers.opensdf
build/VS2010/ipch/**/*.ipch
*.so
Testing/Temporary
.cproject
.settings/
.project
net/**/obj
node_modules/
android/.externalNativeBuild/
android/.gradle/
android/build/
samples/android/.externalNativeBuild/
samples/android/.gradle/
samples/android/build/

View File

@@ -1,31 +1,58 @@
language: cpp
os:
- linux
- osx
compiler:
- gcc
#- clang
env:
matrix:
- BUILD_TYPE=Debug BIICODE=false
- BUILD_TYPE=Release BIICODE=false
# biicode .deb files no longer available.
# - BUILD_TYPE=Release BIICODE=true
# - BUILD_TYPE=Debug BIICODE=true
global:
# Set at the root level as this is ignored when set under matrix.env.
- GCC_VERSION="4.9"
matrix:
include:
- language: cpp
os:
- linux
- osx
compiler:
- gcc
#- clang
env:
matrix:
- BUILD_TYPE=Debug BIICODE=false
- BUILD_TYPE=Release BIICODE=false
# biicode .deb files no longer available.
# - BUILD_TYPE=Release BIICODE=true
# - BUILD_TYPE=Debug BIICODE=true
before_install:
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq g++-$GCC_VERSION; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq gcc-$GCC_VERSION; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which g++-$GCC_VERSION) /usr/bin/g++; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
script:
- if [ "$BIICODE" == "false" ]; then cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE . && make && make test; fi
- if [ "$BIICODE" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then ./biicode/support/bii-travis.sh $BUILD_TYPE; fi
before_install:
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq g++-$GCC_VERSION; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq gcc-$GCC_VERSION; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which g++-$GCC_VERSION) /usr/bin/g++; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
script:
- if [ "$BIICODE" == "false" ]; then cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE . && make && make test; fi
- if [ "$BIICODE" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then ./biicode/support/bii-travis.sh $BUILD_TYPE; fi
- 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))

View File

@@ -0,0 +1,4 @@
include("${CMAKE_CURRENT_LIST_DIR}/FlatbuffersTargets.cmake" OPTIONAL)
include("${CMAKE_CURRENT_LIST_DIR}/FlatcTargets.cmake" OPTIONAL)
include("${CMAKE_CURRENT_LIST_DIR}/FlatbuffersSharedTargets.cmake" OPTIONAL)

View File

@@ -24,13 +24,17 @@ endif()
set(FlatBuffers_Library_SRCS
include/flatbuffers/code_generators.h
include/flatbuffers/base.h
include/flatbuffers/flatbuffers.h
include/flatbuffers/hash.h
include/flatbuffers/idl.h
include/flatbuffers/util.h
include/flatbuffers/reflection.h
include/flatbuffers/reflection_generated.h
include/flatbuffers/stl_emulation.h
include/flatbuffers/flexbuffers.h
include/flatbuffers/registry.h
include/flatbuffers/minireflect.h
src/code_generators.cpp
src/idl_parser.cpp
src/idl_gen_text.cpp
@@ -48,6 +52,7 @@ set(FlatBuffers_Compiler_SRCS
src/idl_gen_python.cpp
src/idl_gen_fbs.cpp
src/idl_gen_grpc.cpp
src/idl_gen_json_schema.cpp
src/flatc.cpp
src/flatc_main.cpp
grpc/src/compiler/schema_interface.h
@@ -102,7 +107,7 @@ if(EXISTS "${CMAKE_TOOLCHAIN_FILE}")
# is being configured externally
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")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
elseif(CMAKE_COMPILER_IS_GNUCXX)
if(CYGWIN)
set(CMAKE_CXX_FLAGS
@@ -126,9 +131,13 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -std=c++0x -stdlib=libc++ -Wall -pedantic -Werror \
-Wextra")
if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD")
"${CMAKE_CXX_FLAGS} -std=c++0x -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -stdlib=libc++")
endif()
if(NOT ("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD" OR
"${CMAKE_SYSTEM_NAME}" MATCHES "Linux"))
set(CMAKE_EXE_LINKER_FLAGS
"${CMAKE_EXE_LINKER_FLAGS} -lc++abi")
endif()
@@ -138,6 +147,11 @@ elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -fsigned-char")
elseif(MSVC)
# Visual Studio pedantic build settings
# warning C4512: assignment operator could not be generated
# warning C4316: object allocated on the heap may not be aligned
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4 /WX /wd4512 /wd4316")
endif()
if(FLATBUFFERS_CODE_COVERAGE)
@@ -163,6 +177,10 @@ if(FLATBUFFERS_BUILD_FLATC)
if(NOT FLATBUFFERS_FLATC_EXECUTABLE)
set(FLATBUFFERS_FLATC_EXECUTABLE $<TARGET_FILE:flatc>)
endif()
if(MSVC)
# Make flatc.exe not depend on runtime dlls for easy distribution.
target_compile_options(flatc PUBLIC $<$<CONFIG:Release>:/MT>)
endif()
endif()
if(FLATBUFFERS_BUILD_FLATHASH)
@@ -171,7 +189,16 @@ endif()
if(FLATBUFFERS_BUILD_SHAREDLIB)
add_library(flatbuffers_shared SHARED ${FlatBuffers_Library_SRCS})
set_target_properties(flatbuffers_shared PROPERTIES OUTPUT_NAME flatbuffers)
# Shared object version: "major.minor.micro"
# - micro updated every release when there is no API/ABI changes
# - minor updated when there are additions in API/ABI
# - major (ABI number) updated when there are changes in ABI (or removals)
set(FlatBuffers_Library_SONAME_MAJOR "1")
set(FlatBuffers_Library_SONAME_FULL "${FlatBuffers_Library_SONAME_MAJOR}.8.0")
set_target_properties(flatbuffers_shared PROPERTIES OUTPUT_NAME flatbuffers
SOVERSION "${FlatBuffers_Library_SONAME_MAJOR}"
VERSION "${FlatBuffers_Library_SONAME_FULL}")
endif()
function(compile_flatbuffers_schema_to_cpp SRC_FBS)
@@ -181,6 +208,9 @@ function(compile_flatbuffers_schema_to_cpp SRC_FBS)
OUTPUT ${GEN_HEADER}
COMMAND "${FLATBUFFERS_FLATC_EXECUTABLE}" -c --no-includes --gen-mutable
--gen-object-api -o "${SRC_FBS_DIR}"
--cpp-ptr-type flatbuffers::unique_ptr # Used to test with C++98 STLs
--reflect-names
-I "${CMAKE_CURRENT_SOURCE_DIR}/tests/include_test"
"${CMAKE_CURRENT_SOURCE_DIR}/${SRC_FBS}"
DEPENDS flatc)
endfunction()
@@ -211,22 +241,67 @@ endif()
if(FLATBUFFERS_BUILD_GRPCTEST)
if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter -Wno-shadow")
endif()
add_executable(grpctest ${FlatBuffers_GRPCTest_SRCS})
target_link_libraries(grpctest grpc++_unsecure grpc pthread dl)
target_link_libraries(grpctest grpc++_unsecure grpc_unsecure pthread dl)
endif()
if(FLATBUFFERS_INSTALL)
install(DIRECTORY include/flatbuffers DESTINATION include)
include(GNUInstallDirs)
install(DIRECTORY include/flatbuffers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
set(FB_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/flatbuffers")
install(
FILES "CMake/FlatbuffersConfig.cmake"
DESTINATION ${FB_CMAKE_DIR}
)
if(FLATBUFFERS_BUILD_FLATLIB)
install(TARGETS flatbuffers DESTINATION lib)
install(
TARGETS flatbuffers EXPORT FlatbuffersTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
install(EXPORT FlatbuffersTargets
FILE FlatbuffersTargets.cmake
NAMESPACE flatbuffers::
DESTINATION ${FB_CMAKE_DIR}
)
endif()
if(FLATBUFFERS_BUILD_FLATC)
install(TARGETS flatc DESTINATION bin)
install(
TARGETS flatc EXPORT FlatcTargets
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
CONFIGURATIONS Release
)
install(
EXPORT FlatcTargets
FILE FlatcTargets.cmake
NAMESPACE flatbuffers::
DESTINATION ${FB_CMAKE_DIR}
CONFIGURATIONS Release
)
endif()
if(FLATBUFFERS_BUILD_SHAREDLIB)
install(TARGETS flatbuffers_shared DESTINATION lib)
install(
TARGETS flatbuffers_shared EXPORT FlatbuffersSharedTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
install(
EXPORT FlatbuffersSharedTargets
FILE FlatbuffersSharedTargets.cmake
NAMESPACE flatbuffers::
DESTINATION ${FB_CMAKE_DIR}
)
endif()
endif()

0
android/.project Executable file → Normal file
View File

11
android/AndroidManifest.xml Executable file → Normal file
View File

@@ -17,17 +17,14 @@
-->
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.FlatBufferTest"
android:versionCode="1"
android:versionName="1.0">
package="com.example.FlatBufferTest">
<uses-feature android:glEsVersion="0x00020000"></uses-feature>
<!-- This is the platform API where NativeActivity was introduced. -->
<uses-sdk android:minSdkVersion="9" />
<!-- This .apk has no Java code itself, so set hasCode to false. -->
<application android:label="@string/app_name" android:hasCode="false">
<application android:label="@string/app_name"
android:hasCode="false"
android:allowBackup="false">
<!-- Our activity is the built-in NativeActivity framework class.
This will take care of integrating with our NDK code. -->
<activity android:name="android.app.NativeActivity"

108
android/build.gradle Normal file
View File

@@ -0,0 +1,108 @@
// Copyright (c) 2017 Google, Inc.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
}
}
allprojects {
repositories {
jcenter()
}
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion '25.0.2'
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
res.srcDirs = ['res']
}
}
externalNativeBuild {
ndkBuild {
path "jni/Android.mk"
}
}
defaultConfig {
applicationId 'com.example.FlatBufferTest'
// This is the platform API where NativeActivity was introduced.
minSdkVersion 9
targetSdkVersion 25
versionCode 1
versionName "1.0"
buildTypes {
release {
minifyEnabled false
}
}
externalNativeBuild {
ndkBuild {
targets "FlatBufferTest"
arguments "-j" + Runtime.getRuntime().availableProcessors()
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
}
}
}
lintOptions {
abortOnError false
}
// Build with each STL variant.
productFlavors {
stlport {
applicationIdSuffix ".stlport"
versionNameSuffix "-stlport"
externalNativeBuild {
ndkBuild {
arguments "APP_STL=stlport_static"
}
}
}
gnustl {
applicationIdSuffix ".gnustl"
versionNameSuffix "-gnustl"
externalNativeBuild {
ndkBuild {
arguments "APP_STL=gnustl_static"
}
}
}
libcpp {
applicationIdSuffix ".libcpp"
versionNameSuffix "-libcpp"
externalNativeBuild {
ndkBuild {
arguments "APP_STL=c++_static"
}
}
}
}
}

View File

@@ -1,511 +0,0 @@
#!/bin/bash -eu
#
# Copyright (c) 2013 Google, Inc.
#
# This software is provided 'as-is', without any express or implied
# warranty. In no event will the authors be held liable for any damages
# arising from the use of this software.
# Permission is granted to anyone to use this software for any purpose,
# including commercial applications, and to alter it and redistribute it
# freely, subject to the following restrictions:
# 1. The origin of this software must not be misrepresented; you must not
# claim that you wrote the original software. If you use this software
# in a product, an acknowledgment in the product documentation would be
# appreciated but is not required.
# 2. Altered source versions must be plainly marked as such, and must not be
# misrepresented as being the original software.
# 3. This notice may not be removed or altered from any source distribution.
#
# Build, deploy, debug / execute a native Android package based upon
# NativeActivity.
declare -r script_directory=$(dirname $0)
declare -r android_root=${script_directory}/../../../../../../
declare -r script_name=$(basename $0)
declare -r android_manifest=AndroidManifest.xml
declare -r os_name=$(uname -s)
# Minimum Android target version supported by this project.
: ${BUILDAPK_ANDROID_TARGET_MINVERSION:=10}
# Directory containing the Android SDK
# (http://developer.android.com/sdk/index.html).
: ${ANDROID_SDK_HOME:=}
# Directory containing the Android NDK
# (http://developer.android.com/tools/sdk/ndk/index.html).
: ${NDK_HOME:=}
# Display script help and exit.
usage() {
echo "
Build the Android package in the current directory and deploy it to a
connected device.
Usage: ${script_name} \\
[ADB_DEVICE=serial_number] [BUILD=0] [DEPLOY=0] [RUN_DEBUGGER=1] \
[LAUNCH=0] [SWIG_BIN=swig_binary_directory] [SWIG_LIB=swig_include_directory] [ndk-build arguments ...]
ADB_DEVICE=serial_number:
serial_number specifies the device to deploy the built apk to if multiple
Android devices are connected to the host.
BUILD=0:
Disables the build of the package.
DEPLOY=0:
Disables the deployment of the built apk to the Android device.
RUN_DEBUGGER=1:
Launches the application in gdb after it has been deployed. To debug in
gdb, NDK_DEBUG=1 must also be specified on the command line to build a
debug apk.
LAUNCH=0:
Disable the launch of the apk on the Android device.
SWIG_BIN=swig_binary_directory:
The directory where the SWIG binary lives. No need to set this if SWIG is
installed and point to from your PATH variable.
SWIG_LIB=swig_include_directory:
The directory where SWIG shared include files are, usually obtainable from
commandline with \"swig -swiglib\". No need to set this if SWIG is installed
and point to from your PATH variable.
ndk-build arguments...:
Additional arguments for ndk-build. See ndk-build -h for more information.
" >&2
exit 1
}
# Get the number of CPU cores present on the host.
get_number_of_cores() {
case ${os_name} in
Darwin)
sysctl hw.ncpu | awk '{ print $2 }'
;;
CYGWIN*|Linux)
awk '/^processor/ { n=$3 } END { print n + 1 }' /proc/cpuinfo
;;
*)
echo 1
;;
esac
}
# Get the package name from an AndroidManifest.xml file.
get_package_name_from_manifest() {
xmllint --xpath 'string(/manifest/@package)' "${1}"
}
# Get the library name from an AndroidManifest.xml file.
get_library_name_from_manifest() {
echo "\
setns android=http://schemas.android.com/apk/res/android
xpath string(/manifest/application/activity\
[@android:name=\"android.app.NativeActivity\"]/meta-data\
[@android:name=\"android.app.lib_name\"]/@android:value)" |
xmllint --shell "${1}" | awk '/Object is a string/ { print $NF }'
}
# Get the number of Android devices connected to the system.
get_number_of_devices_connected() {
adb devices -l | \
awk '/^..*$/ { if (p) { print $0 } }
/List of devices attached/ { p = 1 }' | \
wc -l
return ${PIPESTATUS[0]}
}
# Kill a process and its' children. This is provided for cygwin which
# doesn't ship with pkill.
kill_process_group() {
local parent_pid="${1}"
local child_pid=
for child_pid in $(ps -f | \
awk '{ if ($3 == '"${parent_pid}"') { print $2 } }'); do
kill_process_group "${child_pid}"
done
kill "${parent_pid}" 2>/dev/null
}
# Find and run "adb".
adb() {
local adb_path=
for path in "$(which adb 2>/dev/null)" \
"${ANDROID_SDK_HOME}/sdk/platform-tools/adb" \
"${android_root}/prebuilts/sdk/platform-tools/adb"; do
if [[ -e "${path}" ]]; then
adb_path="${path}"
break
fi
done
if [[ "${adb_path}" == "" ]]; then
echo -e "Unable to find adb." \
"\nAdd the Android ADT sdk/platform-tools directory to the" \
"PATH." >&2
exit 1
fi
"${adb_path}" "$@"
}
# Find and run "android".
android() {
local android_executable=android
if echo "${os_name}" | grep -q CYGWIN; then
android_executable=android.bat
fi
local android_path=
for path in "$(which ${android_executable})" \
"${ANDROID_SDK_HOME}/sdk/tools/${android_executable}" \
"${android_root}/prebuilts/sdk/tools/${android_executable}"; do
if [[ -e "${path}" ]]; then
android_path="${path}"
break
fi
done
if [[ "${android_path}" == "" ]]; then
echo -e "Unable to find android tool." \
"\nAdd the Android ADT sdk/tools directory to the PATH." >&2
exit 1
fi
# Make sure ant is installed.
if [[ "$(which ant)" == "" ]]; then
echo -e "Unable to find ant." \
"\nPlease install ant and add to the PATH." >&2
exit 1
fi
"${android_path}" "$@"
}
# Find and run "ndk-build"
ndkbuild() {
local ndkbuild_path=
for path in "$(which ndk-build 2>/dev/null)" \
"${NDK_HOME}/ndk-build" \
"${android_root}/prebuilts/ndk/current/ndk-build"; do
if [[ -e "${path}" ]]; then
ndkbuild_path="${path}"
break
fi
done
if [[ "${ndkbuild_path}" == "" ]]; then
echo -e "Unable to find ndk-build." \
"\nAdd the Android NDK directory to the PATH." >&2
exit 1
fi
"${ndkbuild_path}" "$@"
}
# Get file modification time of $1 in seconds since the epoch.
stat_mtime() {
local filename="${1}"
case ${os_name} in
Darwin) stat -f%m "${filename}" 2>/dev/null || echo 0 ;;
*) stat -c%Y "${filename}" 2>/dev/null || echo 0 ;;
esac
}
# Build the native (C/C++) build targets in the current directory.
build_native_targets() {
# Save the list of output modules in the install directory so that it's
# possible to restore their timestamps after the build is complete. This
# works around a bug in ndk/build/core/setup-app.mk which results in the
# unconditional execution of the clean-installed-binaries rule.
restore_libraries="$(find libs -type f 2>/dev/null | \
sed -E 's@^libs/(.*)@\1@')"
# Build native code.
ndkbuild -j$(get_number_of_cores) "$@"
# Restore installed libraries.
# Obviously this is a nasty hack (along with ${restore_libraries} above) as
# it assumes it knows where the NDK will be placing output files.
(
IFS=$'\n'
for libpath in ${restore_libraries}; do
source_library="obj/local/${libpath}"
target_library="libs/${libpath}"
if [[ -e "${source_library}" ]]; then
cp -a "${source_library}" "${target_library}"
fi
done
)
}
# Select the oldest installed android build target that is at least as new as
# BUILDAPK_ANDROID_TARGET_MINVERSION. If a suitable build target isn't found,
# this function prints an error message and exits with an error.
select_android_build_target() {
local -r android_targets_installed=$( \
android list targets | \
awk -F'"' '/^id:.*android/ { print $2 }')
local android_build_target=
for android_target in $(echo "${android_targets_installed}" | \
awk -F- '{ print $2 }' | sort -n); do
local isNumber='^[0-9]+$'
# skip preview API releases e.g. 'android-L'
if [[ $android_target =~ $isNumber ]]; then
if [[ $((android_target)) -ge \
$((BUILDAPK_ANDROID_TARGET_MINVERSION)) ]]; then
android_build_target="android-${android_target}"
break
fi
# else
# The API version is a letter, so skip it.
fi
done
if [[ "${android_build_target}" == "" ]]; then
echo -e \
"Found installed Android targets:" \
"$(echo ${android_targets_installed} | sed 's/ /\n /g;s/^/\n /;')" \
"\nAndroid SDK platform" \
"android-$((BUILDAPK_ANDROID_TARGET_MINVERSION))" \
"must be installed to build this project." \
"\nUse the \"android\" application to install API" \
"$((BUILDAPK_ANDROID_TARGET_MINVERSION)) or newer." >&2
exit 1
fi
echo "${android_build_target}"
}
# Sign unsigned apk $1 and write the result to $2 with key store file $3 and
# password $4.
# If a key store file $3 and password $4 aren't specified, a temporary
# (60 day) key is generated and used to sign the package.
sign_apk() {
local unsigned_apk="${1}"
local signed_apk="${2}"
if [[ $(stat_mtime "${unsigned_apk}") -gt \
$(stat_mtime "${signed_apk}") ]]; then
local -r key_alias=$(basename ${signed_apk} .apk)
local keystore="${3}"
local key_password="${4}"
[[ "${keystore}" == "" ]] && keystore="${unsigned_apk}.keystore"
[[ "${key_password}" == "" ]] && \
key_password="${key_alias}123456"
if [[ ! -e ${keystore} ]]; then
keytool -genkey -v -dname "cn=, ou=${key_alias}, o=fpl" \
-storepass ${key_password} \
-keypass ${key_password} -keystore ${keystore} \
-alias ${key_alias} -keyalg RSA -keysize 2048 -validity 60
fi
cp "${unsigned_apk}" "${signed_apk}"
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 \
-keystore ${keystore} -storepass ${key_password} \
-keypass ${key_password} "${signed_apk}" ${key_alias}
fi
}
# Build the apk $1 for package filename $2 in the current directory using the
# ant build target $3.
build_apk() {
local -r output_apk="${1}"
local -r package_filename="${2}"
local -r ant_target="${3}"
# Get the list of installed android targets and select the oldest target
# that is at least as new as BUILDAPK_ANDROID_TARGET_MINVERSION.
local -r android_build_target=$(select_android_build_target)
[[ "${android_build_target}" == "" ]] && exit 1
echo "Building ${output_apk} for target ${android_build_target}" >&2
# Create / update build.xml and local.properties files.
if [[ $(stat_mtime "${android_manifest}") -gt \
$(stat_mtime build.xml) ]]; then
android update project --target "${android_build_target}" \
-n ${package_filename} --path .
fi
# Use ant to build the apk.
ant -quiet ${ant_target}
# Sign release apks with a temporary key as these packages will not be
# redistributed.
local unsigned_apk="bin/${package_filename}-${ant_target}-unsigned.apk"
if [[ "${ant_target}" == "release" ]]; then
sign_apk "${unsigned_apk}" "${output_apk}" "" ""
fi
}
# Uninstall package $1 and install apk $2 on device $3 where $3 is "-s device"
# or an empty string. If $3 is an empty string adb will fail when multiple
# devices are connected to the host system.
install_apk() {
local -r uninstall_package_name="${1}"
local -r install_apk="${2}"
local -r adb_device="${3}"
# Uninstall the package if it's already installed.
adb ${adb_device} uninstall "${uninstall_package_name}" 1>&2 > /dev/null || \
true # no error check
# Install the apk.
# NOTE: The following works around adb not returning an error code when
# it fails to install an apk.
echo "Install ${install_apk}" >&2
local -r adb_install_result=$(adb ${adb_device} install "${install_apk}")
echo "${adb_install_result}"
if echo "${adb_install_result}" | grep -qF 'Failure ['; then
exit 1
fi
}
# Launch previously installed package $1 on device $2.
# If $2 is an empty string adb will fail when multiple devices are connected
# to the host system.
launch_package() {
(
# Determine the SDK version of Android on the device.
local -r android_sdk_version=$(
adb ${adb_device} shell cat system/build.prop | \
awk -F= '/ro.build.version.sdk/ {
v=$2; sub(/[ \r\n]/, "", v); print v
}')
# Clear logs from previous runs.
# Note that logcat does not just 'tail' the logs, it dumps the entire log
# history.
adb ${adb_device} logcat -c
local finished_msg='Displayed '"${package_name}"
local timeout_msg='Activity destroy timeout.*'"${package_name}"
# Maximum time to wait before stopping log monitoring. 0 = infinity.
local launch_timeout=0
# If this is a Gingerbread device, kill log monitoring after 10 seconds.
if [[ $((android_sdk_version)) -le 10 ]]; then
launch_timeout=10
fi
# Display logcat in the background.
# Stop displaying the log when the app launch / execution completes or the
# logcat
(
adb ${adb_device} logcat | \
awk "
{
print \$0
}
/ActivityManager.*: ${finished_msg}/ {
exit 0
}
/ActivityManager.*: ${timeout_msg}/ {
exit 0
}" &
adb_logcat_pid=$!;
if [[ $((launch_timeout)) -gt 0 ]]; then
sleep $((launch_timeout));
kill ${adb_logcat_pid};
else
wait ${adb_logcat_pid};
fi
) &
logcat_pid=$!
# Kill adb logcat if this shell exits.
trap "kill_process_group ${logcat_pid}" SIGINT SIGTERM EXIT
# If the SDK is newer than 10, "am" supports stopping an activity.
adb_stop_activity=
if [[ $((android_sdk_version)) -gt 10 ]]; then
adb_stop_activity=-S
fi
# Launch the activity and wait for it to complete.
adb ${adb_device} shell am start ${adb_stop_activity} -n \
${package_name}/android.app.NativeActivity
wait "${logcat_pid}"
)
}
# See usage().
main() {
# Parse arguments for this script.
local adb_device=
local ant_target=release
local disable_deploy=0
local disable_build=0
local run_debugger=0
local launch=1
local build_package=1
for opt; do
case ${opt} in
# NDK_DEBUG=0 tells ndk-build to build this as debuggable but to not
# modify the underlying code whereas NDK_DEBUG=1 also builds as debuggable
# but does modify the code
NDK_DEBUG=1) ant_target=debug ;;
NDK_DEBUG=0) ant_target=debug ;;
ADB_DEVICE*) adb_device="$(\
echo "${opt}" | sed -E 's/^ADB_DEVICE=([^ ]+)$/-s \1/;t;s/.*//')" ;;
BUILD=0) disable_build=1 ;;
DEPLOY=0) disable_deploy=1 ;;
RUN_DEBUGGER=1) run_debugger=1 ;;
LAUNCH=0) launch=0 ;;
clean) build_package=0 disable_deploy=1 launch=0 ;;
-h|--help|help) usage ;;
esac
done
# If a target device hasn't been specified and multiple devices are connected
# to the host machine, display an error.
local -r devices_connected=$(get_number_of_devices_connected)
if [[ "${adb_device}" == "" && $((devices_connected)) -gt 1 && \
($((disable_deploy)) -eq 0 || $((launch)) -ne 0 || \
$((run_debugger)) -ne 0) ]]; then
if [[ $((disable_deploy)) -ne 0 ]]; then
echo "Deployment enabled, disable using DEPLOY=0" >&2
fi
if [[ $((launch)) -ne 0 ]]; then
echo "Launch enabled." >&2
fi
if [[ $((disable_deploy)) -eq 0 ]]; then
echo "Deployment enabled." >&2
fi
if [[ $((run_debugger)) -ne 0 ]]; then
echo "Debugger launch enabled." >&2
fi
echo "
Multiple Android devices are connected to this host. Either disable deployment
and execution of the built .apk using:
\"${script_name} DEPLOY=0 LAUNCH=0\"
or specify a device to deploy to using:
\"${script_name} ADB_DEVICE=\${device_serial}\".
The Android devices connected to this machine are:
$(adb devices -l)
" >&2
exit 1
fi
if [[ $((disable_build)) -eq 0 ]]; then
# Build the native target.
build_native_targets "$@"
fi
# Get the package name from the manifest.
local -r package_name=$(get_package_name_from_manifest "${android_manifest}")
if [[ "${package_name}" == "" ]]; then
echo -e "No package name specified in ${android_manifest},"\
"skipping apk build, deploy"
"\nand launch steps." >&2
exit 0
fi
local -r package_basename=${package_name/*./}
local package_filename=$(get_library_name_from_manifest ${android_manifest})
[[ "${package_filename}" == "" ]] && package_filename="${package_basename}"
# Output apk name.
local -r output_apk="bin/${package_filename}-${ant_target}.apk"
if [[ $((disable_build)) -eq 0 && $((build_package)) -eq 1 ]]; then
# Build the apk.
build_apk "${output_apk}" "${package_filename}" "${ant_target}"
fi
# Deploy to the device.
if [[ $((disable_deploy)) -eq 0 ]]; then
install_apk "${package_name}" "${output_apk}" "${adb_device}"
fi
if [[ "${ant_target}" == "debug" && $((run_debugger)) -eq 1 ]]; then
# Start debugging.
ndk-gdb ${adb_device} --start
elif [[ $((launch)) -eq 1 ]]; then
launch_package "${package_name}" "${adb_device}"
fi
}
main "$@"

Binary file not shown.

View File

@@ -0,0 +1,6 @@
#Mon Jun 19 11:54:59 PDT 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-all.zip

172
android/gradlew vendored Executable file
View File

@@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

84
android/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

3
android/jni/Android.mk Executable file → Normal file
View File

@@ -39,6 +39,7 @@ LOCAL_SRC_FILES := src/idl_parser.cpp \
src/util.cpp \
src/code_generators.cpp
LOCAL_STATIC_LIBRARIES := flatbuffers
LOCAL_ARM_MODE := arm
include $(BUILD_STATIC_LIBRARY)
# FlatBuffers test
@@ -48,7 +49,7 @@ LOCAL_SRC_FILES := android/jni/main.cpp \
tests/test.cpp \
src/idl_gen_fbs.cpp \
src/idl_gen_general.cpp
LOCAL_LDLIBS := -llog -landroid
LOCAL_LDLIBS := -llog -landroid -latomic
LOCAL_STATIC_LIBRARIES := android_native_app_glue flatbuffers_extra
LOCAL_ARM_MODE := arm
include $(BUILD_SHARED_LIBRARY)

6
android/jni/Application.mk Executable file → Normal file
View File

@@ -13,10 +13,8 @@
# 2. Altered source versions must be plainly marked as such, and must not be
# misrepresented as being the original software.
# 3. This notice may not be removed or altered from any source distribution.
APP_PLATFORM := android-10
APP_PLATFORM := android-9
APP_PROJECT_PATH := $(call my-dir)/..
APP_STL := gnustl_static
APP_STL ?= stlport_static
APP_ABI := armeabi-v7a
APP_CPPFLAGS += -std=c++11

0
android/jni/build_flatc.bat Executable file → Normal file
View File

0
android/res/values/strings.xml Executable file → Normal file
View File

View File

@@ -4,6 +4,17 @@ branches:
os: Visual Studio 2015
environment:
global:
# Workaround for https://github.com/conda/conda-build/issues/636
PYTHONIOENCODING: UTF-8
CONDA_INSTALL_LOCN: "C:\\Miniconda35-x64"
matrix:
- CMAKE_VS_VERSION: "10 2010"
- CMAKE_VS_VERSION: "14 2015"
platform:
- x86
- x64
@@ -13,7 +24,7 @@ configuration:
- Release
before_build:
- cmake -G"Visual Studio 10 2010"
- cmake -G"Visual Studio %CMAKE_VS_VERSION%"
# 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"
@@ -21,17 +32,41 @@ build:
project: ALL_BUILD.vcxproj
verbosity: minimal
install:
- set PATH=%CONDA_INSTALL_LOCN%;%CONDA_INSTALL_LOCN%\scripts;%PATH%;
test_script:
- rem "---------------- C++ -----------------"
- "%CONFIGURATION%\\flattests.exe"
- rem "---------------- Java -----------------"
- "cd tests"
- rem "Building all code"
- generate_code.bat -b %CONFIGURATION%
- 7z a GeneratedMyGameCode.zip MyGame\
- rem "---------------- C++ -----------------"
- "cd .."
- "%CONFIGURATION%\\flattests.exe"
- "cd tests"
- rem "---------------- Java -----------------"
- "java -version"
- "JavaTest.bat"
- rem "---------------- JS -----------------"
- "node --version"
- "..\\%CONFIGURATION%\\flatc -b monster_test.fbs unicode_test.json"
- "node JavaScriptTest"
- "..\\%CONFIGURATION%\\flatc -b -I include_test monster_test.fbs unicode_test.json"
- "node JavaScriptTest ./monster_test_generated"
- rem "-------------- Python ---------------"
- where python
- python --version
- where pip
- pip --version
- where conda
- conda --version
- rem "installing flatbuffers python library"
- pip install ../python
- rem "testing without installing Numpy"
- python py_test.py 0 0 0
- rem "testing after installing Numpy - disabled"
# FIXME: This has a LOT of unnecessary dependencies and makes the tests fail
# with timeouts.
# - conda install --yes numpy
# - python py_test.py 0 0 0
- rem "---------------- C# -----------------"
# Have to compile this here rather than in "build" above because AppVeyor only
# supports building one project??
@@ -42,5 +77,7 @@ test_script:
- "cd ..\\.."
artifacts:
- path: $(CONFIGURATION)\\flatc.exe
- path: $(CONFIGURATION)\flatc.exe
name: flatc.exe
- path: tests\GeneratedMyGameCode.zip
name: GeneratedMyGameCode.zip

0
docs/footer.html Executable file → Normal file
View File

2
docs/source/Benchmarks.md Executable file → Normal file
View File

@@ -1,4 +1,4 @@
Benchmarks {#flatbuffers_benchmarks}
C++ Benchmarks {#flatbuffers_benchmarks}
==========
Comparing against other serialization solutions, running on Windows 7

0
docs/source/Building.md Executable file → Normal file
View File

View File

@@ -1 +1 @@
../../CONTRIBUTING
../../CONTRIBUTING.md

7
docs/source/Compiler.md Executable file → Normal file
View File

@@ -29,7 +29,7 @@ For any schema input files, one or more generators can be specified:
- `--python`, `-p`: Generate Python code.
- `--javascript`, `-s`: Generate JavaScript code.
- `--js`, `-s`: Generate JavaScript code.
- `--php`: Generate PHP code.
@@ -123,5 +123,10 @@ Additional options:
- `--include-prefix PATH` : Prefix this path to any generated include
statements.
- `--keep-prefix` : Keep original prefix of schema include statement.
- `--reflect-types` : Add minimal type reflection to code generation.
- `--reflect-names` : Add minimal type/name reflection.
NOTE: short-form options for generators are deprecated, use the long form
whenever possible.

51
docs/source/CppUsage.md Executable file → Normal file
View File

@@ -200,6 +200,15 @@ 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.
# Using different string type.
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.
## Reflection (& Resizing)
There is experimental support for reflection in FlatBuffers, allowing you to
@@ -222,6 +231,30 @@ schema, as well as a lot of helper functions.
And example of usage, for the time being, can be found in
`test.cpp/ReflectionTest()`.
## Mini Reflection
A more limited form of reflection is available for direct inclusion in
generated code, which doesn't any (binary) schema access at all. It was designed
to keep the overhead of reflection as low as possible (on the order of 2-6
bytes per field added to your executable), but doesn't contain all the
information the (binary) schema contains.
You add this information to your generated code by specifying `--reflect-types`
(or instead `--reflect-names` if you also want field / enum names).
You can now use this information, for example to print a FlatBuffer to text:
auto s = flatbuffers::FlatBufferToString(flatbuf, MonsterTypeTable());
`MonsterTypeTable()` is declared in the generated code for each type. The
string produced is very similar to the JSON produced by the `Parser` based
text generator.
You'll need `flatbuffers/minireflect.h` for this functionality. In there is also
a convenient visitor/iterator so you can write your own output / functionality
based on the mini reflection tables without having to know the FlatBuffers or
reflection encoding.
## Storing maps / dictionaries in a FlatBuffer
FlatBuffers doesn't support maps natively, but there is support to
@@ -402,4 +435,22 @@ manually wrap it in synchronisation primites. 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.
## Advanced union features
The C++ implementation currently supports vectors of unions (i.e. you can
declare a field as `[T]` where `T` is a union type instead of a table type). It
also supports structs and strings in unions, besides tables.
For an example of these features, see `tests/union_vector`, and
`UnionVectorTest` in `test.cpp`.
Since these features haven't been ported to other languages yet, if you
choose to use them, you won't be able to use these buffers in other languages
(`flatc` will refuse to compile a schema that uses these features).
These features reduce the amount of "table wrapping" that was previously
needed to use unions.
To use scalars, simply wrap them in a struct.
<br>

View File

@@ -128,6 +128,16 @@ A description of how FlexBuffers are encoded is in the
[internals](@ref flatbuffers_internals) document.
# Nesting inside a FlatBuffer
You can mark a field as containing a FlexBuffer, e.g.
a:[ubyte] (flexbuffer);
A special accessor will be generated that allows you to access the root value
directly, e.g. `a_flexbuffer_root().AsInt64()`.
# Efficiency tips
* Vectors generally are a lot more efficient than maps, so prefer them over maps

25
docs/source/Grammar.md Executable file → Normal file
View File

@@ -4,7 +4,7 @@ Grammar of the schema language {#flatbuffers_grammar}
schema = include*
( namespace\_decl | type\_decl | enum\_decl | root\_decl |
file_extension_decl | file_identifier_decl |
attribute\_decl | object )*
attribute\_decl | rpc\_decl | object )*
include = `include` string\_constant `;`
@@ -14,16 +14,22 @@ attribute\_decl = `attribute` string\_constant `;`
type\_decl = ( `table` | `struct` ) ident metadata `{` field\_decl+ `}`
enum\_decl = ( `enum` | `union` ) ident [ `:` type ] metadata `{` commasep(
enumval\_decl ) `}`
enum\_decl = ( `enum` ident [ `:` type ] | `union` ident ) metadata `{`
commasep( enumval\_decl ) `}`
root\_decl = `root_type` ident `;`
field\_decl = ident `:` type [ `=` scalar ] metadata `;`
rpc\_decl = `rpc_service` ident `{` rpc\_method+ `}`
rpc\_method = ident `(` ident `)` `:` ident metadata `;`
type = `bool` | `byte` | `ubyte` | `short` | `ushort` | `int` | `uint` |
`float` | `long` | `ulong` | `double`
| `string` | `[` type `]` | ident
`float` | `long` | `ulong` | `double` |
`int8` | `uint8` | `int16` | `uint16` | `int32` | `uint32`| `int64` | `uint64` |
`float32` | `float64` |
`string` | `[` type `]` | ident
enumval\_decl = ident [ `=` integer\_constant ]
@@ -43,6 +49,11 @@ file_extension_decl = `file_extension` string\_constant `;`
file_identifier_decl = `file_identifier` string\_constant `;`
integer\_constant = -?[0-9]+ | `true` | `false`
integer\_constant = `-?[0-9]+` | `true` | `false`
float\_constant = `-?[0-9]+.[0-9]+((e|E)(+|-)?[0-9]+)?`
string\_constant = `\".*?\"`
ident = `[a-zA-Z_][a-zA-Z0-9_]*`
float\_constant = -?[0-9]+.[0-9]+((e|E)(+|-)?[0-9]+)?

22
docs/source/Internals.md Executable file → Normal file
View File

@@ -292,6 +292,12 @@ flexibility in which of the children of root object to write first (though in
this case there's only one string), and what order to write the fields in.
Different orders may also cause different alignments to happen.
### Additional reading.
The author of the C language implementation has made a similar
[document](https://github.com/dvidelabs/flatcc/blob/master/doc/binary-format.md#flatbuffers-binary-format)
that may further help clarify the format.
# FlexBuffers
The [schema-less](@ref flexbuffers) version of FlatBuffers have their
@@ -368,6 +374,10 @@ The offset version is useful to encode costly 64bit (or even 32bit) quantities
into vectors / maps of smaller sizes, and to share / repeat a value multiple
times.
### Booleans and Nulls
Booleans (`TYPE_BOOL`) and nulls (`TYPE_NULL`) are encoded as inlined unsigned integers.
### Blobs, Strings and Keys.
A blob (`TYPE_BLOB`) is encoded similar to a vector, with one difference: the
@@ -408,19 +418,19 @@ that lookups can be made using binary search.
The reason the key vector is a seperate structure from the value vector is
such that it can be shared between multiple value vectors, and also to
allow it to be treated as its own indivual vector in code.
allow it to be treated as its own individual vector in code.
An example map { foo: 13, bar: 14 } would be encoded as:
0 : uint8_t 'f', 'o', 'o', 0
4 : uint8_t 'b', 'a', 'r', 0
0 : uint8_t 'b', 'a', 'r', 0
4 : uint8_t 'f', 'o', 'o', 0
8 : uint8_t 2 // key vector of size 2
// key vector offset points here
9 : uint8_t 9, 6 // offsets to foo_key and bar_key
11: uint8_t 3, 1 // offset to key vector, and its byte width
9 : uint8_t 9, 6 // offsets to bar_key and foo_key
11: uint8_t 2, 1 // offset to key vector, and its byte width
13: uint8_t 2 // value vector of size
// value vector offset points here
14: uint8_t 13, 14 // values
14: uint8_t 14, 13 // values
16: uint8_t 4, 4 // types
### The root

19
docs/source/JavaCsharpUsage.md Executable file → Normal file
View File

@@ -139,7 +139,7 @@ can have fast lookups directly from a FlatBuffer without having to unpack
your data into a `Dictionary` or similar.
To use it:
- Designate one of the fields in a table as they "key" field. You do this
- Designate one of the fields in a table as the "key" field. You do this
by setting the `key` attribute on this field, e.g.
`name:string (key)`.
You may only have one key field, and it must be of string or scalar type.
@@ -147,19 +147,20 @@ To use it:
array.
- Instead of calling standard generated method,
e.g.: `Monster.createTestarrayoftablesVector`,
call `CreateMySortedVectorOfTables` in C# or
call `CreateSortedVectorOfMonster` in C# or
`createSortedVectorOfTables` (from the `FlatBufferBuilder` object) in Java,
which will first sort all offsets such that the tables they refer to
are sorted by the key field, then serialize it.
- Now when you're accessing the FlatBuffer, you can use `LookupByKey`
to access elements of the vector, e.g.:
`Monster.lookupByKey(tablesVectorOffset, "Frodo", dataBuffer)`,
- Now when you're accessing the FlatBuffer, you can use
the `ByKey` accessor to access elements of the vector, e.g.:
`monster.testarrayoftablesByKey("Frodo")` in Java or
`monster.TestarrayoftablesByKey("Frodo")` in C#,
which returns an object of the corresponding table type,
or `null` if not found.
`LookupByKey` performs a binary search, so should have a similar speed to
`Dictionary`, though may be faster because of better caching. `LookupByKey`
only works if the vector has been sorted, it will likely not find elements
if it hasn't been sorted.
`ByKey` performs a binary search, so should have a similar
speed to `Dictionary`, though may be faster because of better caching.
`ByKey` only works if the vector has been sorted, it will
likely not find elements if it hasn't been sorted.
## Text parsing

0
docs/source/JavaScriptUsage.md Executable file → Normal file
View File

27
docs/source/PythonUsage.md Executable file → Normal file
View File

@@ -64,6 +64,33 @@ Now you can access values like this:
pos = monster.Pos()
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Support for Numpy arrays
The Flatbuffers python library also has support for accessing scalar
vectors as numpy arrays. This can be orders of magnitude faster than
iterating over the vector one element at a time, and is particularly
useful when unpacking large nested flatbuffers. The generated code for
a scalar vector will have a method `<vector name>AsNumpy()`. In the
case of the Monster example, you could access the inventory vector
like this:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py}
inventory = monster.InventoryAsNumpy()
# inventory is a numpy array of type np.dtype('uint8')
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
instead of
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.py}
inventory = []
for i in range(monster.InventoryLength()):
inventory.append(int(monster.Inventory(i)))
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Numpy is not a requirement. If numpy is not installed on your system,
then attempting to access one of the `*asNumpy()` methods will result
in a `NumpyRequiredForThisFeature` exception.
## Text Parsing
There currently is no support for parsing text (Schema's and JSON) directly

27
docs/source/Schemas.md Executable file → Normal file
View File

@@ -84,15 +84,19 @@ parent object, and use no virtual table).
### Types
Built-in scalar types are:
Built-in scalar types are
- 8 bit: `byte`, `ubyte`, `bool`
- 8 bit: `byte` (`int8`), `ubyte` (`uint8`), `bool`
- 16 bit: `short`, `ushort`
- 16 bit: `short` (`int16`), `ushort` (`uint16`)
- 32 bit: `int`, `uint`, `float`
- 32 bit: `int` (`int32`), `uint` (`uint32`), `float` (`float32`)
- 64 bit: `long`, `ulong`, `double`
- 64 bit: `long` (`int64`), `ulong` (`uint64`), `double` (`float64`)
The type names in parentheses are alias names such that for example
`uint8` can be used in place of `ubyte`, and `int32` can be used in
place of `int` without affecting code generation.
Built-in non-scalar types:
@@ -278,7 +282,10 @@ Current understood attributes:
IDs allow the fields to be placed in any order in the schema.
When a new field is added to the schema it must use the next available ID.
- `deprecated` (on a field): do not generate accessors for this field
anymore, code should stop using this data.
anymore, code should stop using this data. Old data may still contain this
field, but it won't be accessible anymore by newer code. Note that if you
deprecate a field that was previous required, old code may fail to validate
new data (when using the optional verifier).
- `required` (on a non-scalar table field): this field must always be set.
By default, all fields are optional, i.e. may be left out. This is
desirable, as it helps with forwards/backwards compatibility, and
@@ -288,7 +295,10 @@ Current understood attributes:
constructs FlatBuffers to ensure this field is initialized, so the reading
code may access it directly, without checking for NULL. If the constructing
code does not initialize this field, they will get an assert, and also
the verifier will fail on buffers that have missing required fields.
the verifier will fail on buffers that have missing required fields. Note
that if you add this attribute to an existing field, this will only be
valid if existing data always contains this field / existing code always
writes this field.
- `force_align: size` (on a struct): force the alignment of this struct
to be something higher than what it is naturally aligned to. Causes
these structs to be aligned to that amount inside a buffer, IF that
@@ -302,6 +312,9 @@ Current understood attributes:
(which must be a vector of ubyte) contains flatbuffer data, for which the
root type is given by `table_name`. The generated code will then produce
a convenient accessor for the nested FlatBuffer.
- `flexbuffer` (on a field): this indicates that the field
(which must be a vector of ubyte) contains flexbuffer data. The generated
code will then produce a convenient accessor for the FlexBuffer root.
- `key` (on a field): this field is meant to be used as a key when sorting
a vector of the type of table it sits in. Can be used for in-place
binary search.

0
docs/source/Support.md Executable file → Normal file
View File

View File

@@ -160,6 +160,7 @@ the `schema` that defines the template for our monsters:
color:Color = Blue; // Enum.
weapons:[Weapon]; // Vector of tables.
equipped:Equipment; // Union.
path:[Vec3]; // Vector of structs.
}
table Weapon {
@@ -209,12 +210,21 @@ The `Weapon` table is a sub-table used within our FlatBuffer. It is
used twice: once within the `Monster` table and once within the `Equipment`
enum. For our `Monster`, it is used to populate a `vector of tables` via the
`weapons` field within our `Monster`. It is also the only table referenced by
the `Equipment` enum.
the `Equipment` union.
The last part of the `schema` is the `root_type`. The root type declares what
will be the root table for the serialized data. In our case, the root type is
our `Monster` table.
The scalar types can also use alias type names such as `int16` instead
of `short` and `float32` instead of `float`. Thus we could also write
the `Weapon` table as:
table Weapon {
name:string;
damage:int16;
}
#### More Information About Schemas
You can find a complete guide to writing `schema` files in the
@@ -603,7 +613,7 @@ traversal. This is generally easy to do on any tree structures.
// Create a `vector` representing the inventory of the Orc. Each number
// could correspond to an item that can be claimed after he is slain.
unsigned char treasure = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
unsigned char treasure[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
auto inventory = builder.CreateVector(treasure, 10);
~~~
</div>
@@ -709,6 +719,10 @@ adding fields to our monster.
other `vector`s), collect their offsets into a temporary data structure, and
then create an additional `vector` containing their offsets.*
If instead of creating a vector from an existing array you serialize elements
individually one by one, take care to note that this happens in reverse order,
as buffers are built back to front.
For example, take a look at the two `Weapon`s that we created earlier (`Sword`
and `Axe`). These are both FlatBuffer `table`s, whose offsets we now store in
memory. Therefore we can create a FlatBuffer `vector` to contain these
@@ -799,6 +813,70 @@ elements by calling a lambda. For the common case of `std::vector<std::string>`
there's also `CreateVectorOfStrings`.
</div>
Note that vectors of structs are serialized differently from tables, since
structs are stored in-line in the vector. For example, to create a vector
for the `path` field above:
<div class="language-cpp">
~~~{.cpp}
Vec3 points[] = { Vec3(1.0f, 2.0f, 3.0f), Vec3(4.0f, 5.0f, 6.0f) };
auto path = builder.CreateVectorOfStructs(points, 2);
~~~
</div>
<div class="language-java">
~~~{.java}
Monster.startPathVector(fbb, 2);
Vec3.createVec3(builder, 1.0f, 2.0f, 3.0f);
Vec3.createVec3(builder, 4.0f, 5.0f, 6.0f);
int path = fbb.endVector();
~~~
</div>
<div class="language-csharp">
~~~{.cs}
Monster.StartPathVector(fbb, 2);
Vec3.CreateVec3(builder, 1.0f, 2.0f, 3.0f);
Vec3.CreateVec3(builder, 4.0f, 5.0f, 6.0f);
var path = fbb.EndVector();
~~~
</div>
<div class="language-go">
~~~{.go}
sample.MonsterStartPathVector(builder, 2)
sample.CreateVec3(builder, 1.0, 2.0, 3.0)
sample.CreateVec3(builder, 4.0, 5.0, 6.0)
path := builder.EndVector(2)
~~~
</div>
<div class="language-python">
~~~{.py}
MyGame.Sample.Monster.MonsterStartPathVector(builder, 2)
MyGame.Sample.Vec3.CreateVec3(builder, 1.0, 2.0, 3.0)
MyGame.Sample.Vec3.CreateVec3(builder, 4.0, 5.0, 6.0)
path = builder.EndVector(2)
~~~
</div>
<div class="language-javascript">
~~~{.js}
MyGame.Sample.Monster.startPathVector(builder, 2);
MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0);
MyGame.Sample.Vec3.createVec3(builder, 4.0, 5.0, 6.0);
var path = builder.endVector();
~~~
</div>
<div class="language-php">
~~~{.php}
\MyGame\Example\Monster::StartPathVector($builder, 2);
\MyGame\Sample\Vec3::CreateVec3($builder, 1.0, 2.0, 3.0);
\MyGame\Sample\Vec3::CreateVec3($builder, 1.0, 2.0, 3.0);
$path = $builder->endVector();
~~~
</div>
<div class="language-c">
~~~{.c}
// TBD
~~~
</div>
We have now serialized the non-scalar components of the orc, so we
can serialize the monster itself:
@@ -812,7 +890,7 @@ can serialize the monster itself:
// to set all fields.
auto orc = CreateMonster(builder, Vec3(1.0f, 2.0f, 3.0f), mana, hp, name,
inventory, Color_Red, weapons, Equipment_Weapon,
axe.Union());
axe.Union(), path);
~~~
</div>
<div class="language-java">
@@ -827,6 +905,7 @@ can serialize the monster itself:
Monster.addWeapons(builder, weapons);
Monster.addEquippedType(builder, Equipment.Weapon);
Monster.addEquipped(builder, axe);
Monster.addPath(builder, path);
int orc = Monster.endMonster(builder);
~~~
</div>
@@ -842,6 +921,7 @@ can serialize the monster itself:
Monster.AddWeapons(builder, weapons);
Monster.AddEquippedType(builder, Equipment.Weapon);
Monster.AddEquipped(builder, axe.Value); // Axe
Monster.AddPath(builder, path);
var orc = Monster.EndMonster(builder);
~~~
</div>
@@ -857,6 +937,7 @@ can serialize the monster itself:
sample.MonsterAddWeapons(builder, weapons)
sample.MonsterAddEquippedType(builder, sample.EquipmentWeapon)
sample.MonsterAddEquipped(builder, axe)
sample.MonsterAddPath(builder, path)
orc := sample.MonsterEnd(builder)
~~~
</div>
@@ -875,6 +956,7 @@ can serialize the monster itself:
MyGame.Sample.Monster.MonsterAddEquippedType(
builder, MyGame.Sample.Equipment.Equipment().Weapon)
MyGame.Sample.Monster.MonsterAddEquipped(builder, axe)
MyGame.Sample.Monster.MonsterAddPath(builder, path)
orc = MyGame.Sample.Monster.MonsterEnd(builder)
~~~
</div>
@@ -891,6 +973,7 @@ can serialize the monster itself:
MyGame.Sample.Monster.addWeapons(builder, weapons);
MyGame.Sample.Monster.addEquippedType(builder, MyGame.Sample.Equipment.Weapon);
MyGame.Sample.Monster.addEquipped(builder, axe);
MyGame.Sample.Monster.addPath(builder, path);
var orc = MyGame.Sample.Monster.endMonster(builder);
~~~
</div>
@@ -907,6 +990,7 @@ can serialize the monster itself:
\MyGame\Sample\Monster::AddWeapons($builder, $weapons);
\MyGame\Sample\Monster::AddEquippedType($builder, \MyGame\Sample\Equipment::Weapon);
\MyGame\Sample\Monster::AddEquipped($builder, $axe);
\MyGame\Sample\Monster::AddPath($builder, $path);
$orc = \MyGame\Sample\Monster::EndMonster($builder);
~~~
</div>
@@ -921,7 +1005,7 @@ can serialize the monster itself:
ns(Equipment_union_ref_t) equipped = ns(Equipment_as_Weapon(axe));
ns(Vec3_t) pos = { 1.0f, 2.0f, 3.0f };
ns(Monster_create_as_root(B, &pos, mana, hp, name, inventory, ns(Color_Red),
weapons, equipped));
weapons, equipped, path));
~~~
</div>
@@ -929,10 +1013,10 @@ Note how we create `Vec3` struct in-line in the table. Unlike tables, structs
are simple combinations of scalars that are always stored inline, just like
scalars themselves.
**Important**: you should not nest tables or any other objects, which is why
we created all the strings/vectors/tables that this monster refers to before
`start`. If you try to create any of them between `start` and `end`, you
will get an assert/exception/panic depending on your language.
**Important**: Unlike structs, you should not nest tables or other objects,
which is why we created all the strings/vectors/tables that this monster refers
to before `start`. If you try to create any of them between `start` and `end`,
you will get an assert/exception/panic depending on your language.
*Note: Since we are passing `150` as the `mana` field, which happens to be the
default value, the field will not actually be written to the buffer, since the
@@ -953,13 +1037,14 @@ a bit more flexibility.
// manually.
MonsterBuilder monster_builder(builder);
monster_builder.add_pos(&pos);
auto pos = Vec3(1.0f, 2.0f, 3.0f);
monster_builder.add_hp(hp);
monster_builder.add_name(name);
monster_builder.add_inventory(inventory);
monster_builder.add_color(Color_Red);
monster_builder.add_weapons(weapons);
monster_builder.add_equipped_type(Equipment_Weapon);
monster_builder.add_equpped(axe);
monster_builder.add_equpped(axe.Union());
auto orc = monster_builder.Finish();
~~~
</div>
@@ -1091,7 +1176,7 @@ appropriate `finish` method.
<div class="language-javascript">
~~~{.js}
// Call `finish()` to instruct the builder that this monster is complete.
builder.finish(orc); // You could also call `MyGame.Example.Monster.finishMonsterBuffer(builder,
builder.finish(orc); // You could also call `MyGame.Sample.Monster.finishMonsterBuffer(builder,
// orc);`.
~~~
</div>
@@ -1309,6 +1394,8 @@ won't work**
// `monster` is of type `Monster *`.
// Note: root object pointers are NOT the same as `buffer_pointer`.
// `GetMonster` is a convenience function that calls `GetRoot<Monster>`,
// the latter is also available for non-root types.
~~~
</div>
<div class="language-java">
@@ -1470,10 +1557,10 @@ To access sub-objects, in the case of our `pos`, which is a `Vec3`:
</div>
<div class="language-csharp">
~~~{.cs}
var pos = monster.Pos
var x = pos.X
var y = pos.Y
var z = pos.Z
var pos = monster.Pos.Value;
var x = pos.X;
var y = pos.Y;
var z = pos.Z;
~~~
</div>
<div class="language-go">
@@ -1547,7 +1634,7 @@ FlatBuffers `vector`.
<div class="language-csharp">
~~~{.cs}
int invLength = monster.InventoryLength;
var thirdItem = monster.GetInventory(2);
var thirdItem = monster.Inventory(2);
~~~
</div>
<div class="language-go">
@@ -1604,8 +1691,8 @@ except your need to handle the result as a FlatBuffer `table`:
<div class="language-csharp">
~~~{.cs}
int weaponsLength = monster.WeaponsLength;
var secondWeaponName = monster.GetWeapons(1).Name;
var secondWeaponDamage = monster.GetWeapons(1).Damage;
var secondWeaponName = monster.Weapons(1).Name;
var secondWeaponDamage = monster.Weapons(1).Damage;
~~~
</div>
<div class="language-go">
@@ -1687,8 +1774,7 @@ We can access the type to dynamically cast the data as needed (since the
var unionType = monster.EquippedType;
if (unionType == Equipment.Weapon) {
var weapon = (Weapon)monster.GetEquipped(new Weapon()); // Requires explicit cast
// to `Weapon`.
var weapon = monster.Equipped<Weapon>().Value;
var weaponName = weapon.Name; // "Axe"
var weaponDamage = weapon.Damage; // 5

0
docs/source/WhitePaper.md Executable file → Normal file
View File

7
docs/source/doxyfile Executable file → Normal file
View File

@@ -765,6 +765,7 @@ INPUT = "FlatBuffers.md" \
"../../CONTRIBUTING.md" \
"Tutorial.md" \
"GoApi.md" \
"gRPC/CppUsage.md" \
"groups" \
"../../java/com/google/flatbuffers" \
"../../python/flatbuffers/builder.py" \
@@ -883,21 +884,21 @@ EXCLUDE_SYMBOLS =
# that contain example code fragments that are included (see the \include
# command).
EXAMPLE_PATH = "GoApi_generated.txt"
EXAMPLE_PATH = "GoApi_generated.txt" "../../grpc/samples"
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
# *.h) to filter out the source-files in the directories. If left blank all
# files are included.
EXAMPLE_PATTERNS = *
EXAMPLE_PATTERNS = *.cpp *.h *.txt *.fbs
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude commands
# irrespective of the value of the RECURSIVE tag.
# The default value is: NO.
EXAMPLE_RECURSIVE = NO
EXAMPLE_RECURSIVE = YES
# The IMAGE_PATH tag can be used to specify one or more files or directories
# that contain images that are to be included in the documentation (see the

View File

@@ -39,6 +39,10 @@
title="Use in Python"/>
<tab type="user" url="@ref flexbuffers"
title="Schema-less version"/>
<tab type="usergroup" url="" title="gRPC">
<tab type="user" url="@ref flatbuffers_grpc_guide_use_cpp"
title="Use in C++"/>
</tab>
</tab>
<tab type="user" url="@ref flatbuffers_support"
title="Platform / Language / Feature support"/>

View File

@@ -0,0 +1,29 @@
Use in C++ {#flatbuffers_grpc_guide_use_cpp}
==========
## Before you get started
Before diving into the FlatBuffers gRPC usage in C++, you should already be
familiar with the following:
- FlatBuffers as a serialization format
- [gRPC](http://www.grpc.io/docs/) usage
## Using the FlatBuffers gRPC C++ library
NOTE: The examples below are also in the `grpc/samples/greeter` directory.
We will illustrate usage with the following schema:
@include grpc/samples/greeter/greeter.fbs
When we run `flatc`, we pass in the `--grpc` option and generage an additional
`greeter.grpc.fb.h` and `greeter.grpc.fb.cc`.
Example server code looks like this:
@include grpc/samples/greeter/server.cpp
Example client code looks like this:
@include grpc/samples/greeter/client.cpp

View File

@@ -110,6 +110,11 @@ func (b *Builder) WriteVtable() (n UOffsetT) {
objectOffset := b.Offset()
existingVtable := UOffsetT(0)
// Trim vtable of trailing zeroes.
i := len(b.vtable) - 1;
for ; i >= 0 && b.vtable[i] == 0; i-- {}
b.vtable = b.vtable[:i + 1];
// Search backwards through existing vtables, because similar vtables
// are likely to have been recently appended. See
// BenchmarkVtableDeduplication for a case in which this heuristic

View File

@@ -0,0 +1,14 @@
CXXFLAGS ?= -I../../../include
LDFLAGS ?=
.PHONY: all
all: server client
greeter_generated.h: greeter.fbs
flatc --grpc --cpp $<
server: server.cpp greeter.grpc.fb.cc greeter_generated.h greeter.grpc.fb.h
g++ -std=c++11 -O2 $(CXXFLAGS) $(LDFLAGS) -lgpr -lgrpc -lgrpc++ server.cpp greeter.grpc.fb.cc -o $@
client: client.cpp greeter.grpc.fb.cc greeter_generated.h greeter.grpc.fb.h
g++ -std=c++11 -O2 $(CXXFLAGS) $(LDFLAGS) -lgpr -lgrpc -lgrpc++ client.cpp greeter.grpc.fb.cc -o $@

View File

@@ -0,0 +1,85 @@
#include "greeter.grpc.fb.h"
#include "greeter_generated.h"
#include <grpc++/grpc++.h>
#include <iostream>
#include <memory>
#include <string>
class GreeterClient {
public:
GreeterClient(std::shared_ptr<grpc::Channel> channel)
: stub_(Greeter::NewStub(channel)) {}
std::string SayHello(const std::string &name) {
flatbuffers::grpc::MessageBuilder mb;
auto name_offset = mb.CreateString(name);
auto request_offset = CreateHelloRequest(mb, name_offset);
mb.Finish(request_offset);
auto request_msg = mb.ReleaseMessage<HelloRequest>();
flatbuffers::grpc::Message<HelloReply> response_msg;
grpc::ClientContext context;
auto status = stub_->SayHello(&context, request_msg, &response_msg);
if (status.ok()) {
const HelloReply *response = response_msg.GetRoot();
return response->message()->str();
} else {
std::cerr << status.error_code() << ": " << status.error_message()
<< std::endl;
return "RPC failed";
}
}
void SayManyHellos(const std::string &name, int num_greetings,
std::function<void(const std::string &)> callback) {
flatbuffers::grpc::MessageBuilder mb;
auto name_offset = mb.CreateString(name);
auto request_offset =
CreateManyHellosRequest(mb, name_offset, num_greetings);
mb.Finish(request_offset);
auto request_msg = mb.ReleaseMessage<ManyHellosRequest>();
flatbuffers::grpc::Message<HelloReply> response_msg;
grpc::ClientContext context;
auto stream = stub_->SayManyHellos(&context, request_msg);
while (stream->Read(&response_msg)) {
const HelloReply *response = response_msg.GetRoot();
callback(response->message()->str());
}
auto status = stream->Finish();
if (!status.ok()) {
std::cerr << status.error_code() << ": " << status.error_message()
<< std::endl;
callback("RPC failed");
}
}
private:
std::unique_ptr<Greeter::Stub> stub_;
};
int main(int argc, char **argv) {
std::string server_address("localhost:50051");
auto channel =
grpc::CreateChannel(server_address, grpc::InsecureChannelCredentials());
GreeterClient greeter(channel);
std::string name("world");
std::string message = greeter.SayHello(name);
std::cerr << "Greeter received: " << message << std::endl;
int num_greetings = 10;
greeter.SayManyHellos(name, num_greetings, [](const std::string &message) {
std::cerr << "Greeter received: " << message << std::endl;
});
return 0;
}

View File

@@ -0,0 +1,17 @@
table HelloReply {
message:string;
}
table HelloRequest {
name:string;
}
table ManyHellosRequest {
name:string;
num_greetings:int;
}
rpc_service Greeter {
SayHello(HelloRequest):HelloReply;
SayManyHellos(ManyHellosRequest):HelloReply (streaming: "server");
}

View File

@@ -0,0 +1,80 @@
#include "greeter.grpc.fb.h"
#include "greeter_generated.h"
#include <grpc++/grpc++.h>
#include <iostream>
#include <memory>
#include <string>
class GreeterServiceImpl final : public Greeter::Service {
virtual grpc::Status SayHello(
grpc::ServerContext *context,
const flatbuffers::grpc::Message<HelloRequest> *request_msg,
flatbuffers::grpc::Message<HelloReply> *response_msg) override {
// flatbuffers::grpc::MessageBuilder mb_;
// We call GetRoot to "parse" the message. Verification is already
// performed by default. See the notes below for more details.
const HelloRequest *request = request_msg->GetRoot();
// Fields are retrieved as usual with FlatBuffers
const std::string &name = request->name()->str();
// `flatbuffers::grpc::MessageBuilder` is a `FlatBufferBuilder` with a
// special allocator for efficient gRPC buffer transfer, but otherwise
// usage is the same as usual.
auto msg_offset = mb_.CreateString("Hello, " + name);
auto hello_offset = CreateHelloReply(mb_, msg_offset);
mb_.Finish(hello_offset);
// The `ReleaseMessage<T>()` function detaches the message from the
// builder, so we can transfer the resopnse to gRPC while simultaneously
// detaching that memory buffer from the builer.
*response_msg = mb_.ReleaseMessage<HelloReply>();
assert(response_msg->Verify());
// Return an OK status.
return grpc::Status::OK;
}
virtual grpc::Status SayManyHellos(
grpc::ServerContext *context,
const flatbuffers::grpc::Message<ManyHellosRequest> *request_msg,
grpc::ServerWriter<flatbuffers::grpc::Message<HelloReply>> *writer)
override {
// The streaming usage below is simply a combination of standard gRPC
// streaming with the FlatBuffers usage shown above.
const ManyHellosRequest *request = request_msg->GetRoot();
const std::string &name = request->name()->str();
int num_greetings = request->num_greetings();
for (int i = 0; i < num_greetings; i++) {
auto msg_offset = mb_.CreateString("Many hellos, " + name);
auto hello_offset = CreateHelloReply(mb_, msg_offset);
mb_.Finish(hello_offset);
writer->Write(mb_.ReleaseMessage<HelloReply>());
}
return grpc::Status::OK;
}
flatbuffers::grpc::MessageBuilder mb_;
};
void RunServer() {
std::string server_address("0.0.0.0:50051");
GreeterServiceImpl service;
grpc::ServerBuilder builder;
builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
builder.RegisterService(&service);
std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
std::cerr << "Server listening on " << server_address << std::endl;
server->Wait();
}
int main(int argc, const char *argv[]) {
RunServer();
return 0;
}

View File

@@ -0,0 +1,40 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef SRC_COMPILER_CONFIG_H
#define SRC_COMPILER_CONFIG_H
// This file is here only because schema_interface.h, which is copied from gRPC,
// includes it. There is nothing for Flatbuffers to configure.
#endif // SRC_COMPILER_CONFIG_H

File diff suppressed because it is too large Load Diff

View File

@@ -41,8 +41,20 @@
#include <memory>
#include <vector>
#include "src/compiler/config.h"
#include "src/compiler/schema_interface.h"
#ifndef GRPC_CUSTOM_STRING
#include <string>
#define GRPC_CUSTOM_STRING std::string
#endif
namespace grpc {
typedef GRPC_CUSTOM_STRING string;
} // namespace grpc
namespace grpc_cpp_generator {
// Contains all the parameters that are parsed from the command line.
@@ -53,31 +65,73 @@ struct Parameters {
bool use_system_headers;
// Prefix to any grpc include
grpc::string grpc_search_path;
// Generate GMOCK code to facilitate unit testing.
bool generate_mock_code;
};
// Return the prologue of the generated header file.
grpc::string GetHeaderPrologue(grpc_generator::File *file, const Parameters &params);
grpc::string GetHeaderPrologue(grpc_generator::File *file,
const Parameters &params);
// Return the includes needed for generated header file.
grpc::string GetHeaderIncludes(grpc_generator::File *file, const Parameters &params);
grpc::string GetHeaderIncludes(grpc_generator::File *file,
const Parameters &params);
// Return the includes needed for generated source file.
grpc::string GetSourceIncludes(grpc_generator::File *file, const Parameters &params);
grpc::string GetSourceIncludes(grpc_generator::File *file,
const Parameters &params);
// Return the epilogue of the generated header file.
grpc::string GetHeaderEpilogue(grpc_generator::File *file, const Parameters &params);
grpc::string GetHeaderEpilogue(grpc_generator::File *file,
const Parameters &params);
// Return the prologue of the generated source file.
grpc::string GetSourcePrologue(grpc_generator::File *file, const Parameters &params);
grpc::string GetSourcePrologue(grpc_generator::File *file,
const Parameters &params);
// Return the services for generated header file.
grpc::string GetHeaderServices(grpc_generator::File *file, const Parameters &params);
grpc::string GetHeaderServices(grpc_generator::File *file,
const Parameters &params);
// Return the services for generated source file.
grpc::string GetSourceServices(grpc_generator::File *file, const Parameters &params);
grpc::string GetSourceServices(grpc_generator::File *file,
const Parameters &params);
// Return the epilogue of the generated source file.
grpc::string GetSourceEpilogue(grpc_generator::File *file, const Parameters &params);
grpc::string GetSourceEpilogue(grpc_generator::File *file,
const Parameters &params);
// Return the prologue of the generated mock file.
grpc::string GetMockPrologue(grpc_generator::File *file,
const Parameters &params);
// Return the includes needed for generated mock file.
grpc::string GetMockIncludes(grpc_generator::File *file,
const Parameters &params);
// Return the services for generated mock file.
grpc::string GetMockServices(grpc_generator::File *file,
const Parameters &params);
// Return the epilogue of generated mock file.
grpc::string GetMockEpilogue(grpc_generator::File *file,
const Parameters &params);
// Return the prologue of the generated mock file.
grpc::string GetMockPrologue(grpc_generator::File *file,
const Parameters &params);
// Return the includes needed for generated mock file.
grpc::string GetMockIncludes(grpc_generator::File *file,
const Parameters &params);
// Return the services for generated mock file.
grpc::string GetMockServices(grpc_generator::File *file,
const Parameters &params);
// Return the epilogue of generated mock file.
grpc::string GetMockEpilogue(grpc_generator::File *file,
const Parameters &params);
} // namespace grpc_cpp_generator

View File

@@ -44,6 +44,14 @@ grpc::string as_string(T x) {
return out.str();
}
inline bool ClientOnlyStreaming(const grpc_generator::Method *method) {
return method->ClientStreaming() && !method->ServerStreaming();
}
inline bool ServerOnlyStreaming(const grpc_generator::Method *method) {
return !method->ClientStreaming() && method->ServerStreaming();
}
namespace grpc_go_generator {
// Returns string with first letter to lowerCase
@@ -70,8 +78,8 @@ void GenerateImports(grpc_generator::File *file, grpc_generator::Printer *printe
printer->Print("//If you make any local changes, they will be lost\n");
printer->Print(vars, "//source: $filename$\n\n");
printer->Print(vars, "package $Package$\n\n");
if (file->additional_imports() != "") {
printer->Print(file->additional_imports().c_str());
if (file->additional_headers() != "") {
printer->Print(file->additional_headers().c_str());
printer->Print("\n\n");
}
printer->Print("import (\n");
@@ -86,11 +94,11 @@ void GenerateImports(grpc_generator::File *file, grpc_generator::Printer *printe
void GenerateServerMethodSignature(const grpc_generator::Method *method, grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> vars) {
vars["Method"] = exportName(method->name());
vars["Request"] = method->input_name();
vars["Response"] = (vars["CustomMethodIO"] == "") ? method->output_name() : vars["CustomMethodIO"];
vars["Request"] = method->get_input_type_name();
vars["Response"] = (vars["CustomMethodIO"] == "") ? method->get_output_type_name() : vars["CustomMethodIO"];
if (method->NoStreaming()) {
printer->Print(vars, "$Method$($context$.Context, *$Request$) (*$Response$, error)");
} else if (method->ServerOnlyStreaming()) {
} else if (ServerOnlyStreaming(method)) {
printer->Print(vars, "$Method$(*$Request$, $Service$_$Method$Server) error");
} else {
printer->Print(vars, "$Method$($Service$_$Method$Server) error");
@@ -100,8 +108,8 @@ void GenerateServerMethodSignature(const grpc_generator::Method *method, grpc_ge
void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> vars) {
vars["Method"] = exportName(method->name());
vars["Request"] = method->input_name();
vars["Response"] = (vars["CustomMethodIO"] == "") ? method->output_name() : vars["CustomMethodIO"];
vars["Request"] = method->get_input_type_name();
vars["Response"] = (vars["CustomMethodIO"] == "") ? method->get_output_type_name() : vars["CustomMethodIO"];
vars["FullMethodName"] = "/" + vars["Package"] + "." + vars["Service"] + "/" + vars["Method"];
vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
if (method->NoStreaming()) {
@@ -129,7 +137,7 @@ void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::
vars["StreamType"] = vars["ServiceUnexported"] + vars["Method"] + "Server";
printer->Print(vars, "func $Handler$(srv interface{}, stream $grpc$.ServerStream) error {\n");
printer->Indent();
if (method->ServerOnlyStreaming()) {
if (ServerOnlyStreaming(method)) {
printer->Print(vars, "m := new($Request$)\n");
printer->Print(vars, "if err := stream.RecvMsg(m); err != nil { return err }\n");
printer->Print(vars, "return srv.($Service$Server).$Method$(m, &$StreamType${stream})\n");
@@ -139,9 +147,9 @@ void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::
printer->Outdent();
printer->Print("}\n\n");
bool genSend = method->BidiStreaming() || method->ServerOnlyStreaming();
bool genRecv = method->BidiStreaming() || method->ClientOnlyStreaming();
bool genSendAndClose = method->ClientOnlyStreaming();
bool genSend = method->BidiStreaming() || ServerOnlyStreaming(method);
bool genRecv = method->BidiStreaming() || ClientOnlyStreaming(method);
bool genSendAndClose = ClientOnlyStreaming(method);
printer->Print(vars, "type $Service$_$Method$Server interface { \n");
printer->Indent();
@@ -194,12 +202,12 @@ void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::
void GenerateClientMethodSignature(const grpc_generator::Method *method, grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> vars) {
vars["Method"] = exportName(method->name());
vars["Request"] = ", in *" + ((vars["CustomMethodIO"] == "") ? method->input_name() : vars["CustomMethodIO"]);
if (method->ClientOnlyStreaming() || method->BidiStreaming()) {
vars["Request"] = ", in *" + ((vars["CustomMethodIO"] == "") ? method->get_input_type_name() : vars["CustomMethodIO"]);
if (ClientOnlyStreaming(method) || method->BidiStreaming()) {
vars["Request"] = "";
}
vars["Response"] = "* " + method->output_name();
if (method->ClientOnlyStreaming() || method->BidiStreaming() || method->ServerOnlyStreaming()) {
vars["Response"] = "* " + method->get_output_type_name();
if (ClientOnlyStreaming(method) || method->BidiStreaming() || ServerOnlyStreaming(method)) {
vars["Response"] = vars["Service"] + "_" + vars["Method"] + "Client" ;
}
printer->Print(vars, "$Method$(ctx $context$.Context$Request$, \n\topts... $grpc$.CallOption) ($Response$, error)");
@@ -213,8 +221,8 @@ void GenerateClientMethod(const grpc_generator::Method *method, grpc_generator::
printer->Print(" {\n");
printer->Indent();
vars["Method"] = exportName(method->name());
vars["Request"] = (vars["CustomMethodIO"] == "") ? method->input_name() : vars["CustomMethodIO"];
vars["Response"] = method->output_name();
vars["Request"] = (vars["CustomMethodIO"] == "") ? method->get_input_type_name() : vars["CustomMethodIO"];
vars["Response"] = method->get_output_type_name();
vars["FullMethodName"] = "/" + vars["Package"] + "." + vars["Service"] + "/" + vars["Method"];
if (method->NoStreaming()) {
printer->Print(vars, "out := new($Response$)\n");
@@ -230,7 +238,7 @@ void GenerateClientMethod(const grpc_generator::Method *method, grpc_generator::
printer->Print("if err != nil { return nil, err }\n");
printer->Print(vars, "x := &$StreamType${stream}\n");
if (method->ServerOnlyStreaming()) {
if (ServerOnlyStreaming(method)) {
printer->Print("if err := x.ClientStream.SendMsg(in); err != nil { return nil, err }\n");
printer->Print("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }\n");
}
@@ -238,9 +246,9 @@ void GenerateClientMethod(const grpc_generator::Method *method, grpc_generator::
printer->Outdent();
printer->Print("}\n\n");
bool genSend = method->BidiStreaming() || method->ClientOnlyStreaming();
bool genRecv = method->BidiStreaming() || method->ServerOnlyStreaming();
bool genCloseAndRecv = method->ClientOnlyStreaming();
bool genSend = method->BidiStreaming() || ClientOnlyStreaming(method);
bool genRecv = method->BidiStreaming() || ServerOnlyStreaming(method);
bool genCloseAndRecv = ClientOnlyStreaming(method);
//Stream interface
printer->Print(vars, "type $Service$_$Method$Client interface {\n");
@@ -396,9 +404,9 @@ void GenerateService(const grpc_generator::Service *service, grpc_generator::Pri
printer->Indent();
printer->Print(vars, "StreamName: \"$Method$\",\n");
printer->Print(vars, "Handler: $Handler$, \n");
if (method->ClientOnlyStreaming()) {
if (ClientOnlyStreaming(method.get())) {
printer->Print("ClientStreams: true,\n");
} else if (method->ServerOnlyStreaming()) {
} else if (ServerOnlyStreaming(method.get())) {
printer->Print("ServerStreams: true,\n");
} else {
printer->Print("ServerStreams: true,\n");

View File

@@ -43,12 +43,12 @@
namespace grpc_go_generator {
struct Parameters {
//Defines the custom parameter types for methods
//eg: flatbuffers uses flatbuffers.Builder as input for the client and output for the server
grpc::string custom_method_io_type;
//Defines the custom parameter types for methods
//eg: flatbuffers uses flatbuffers.Builder as input for the client and output for the server
grpc::string custom_method_io_type;
//Package name for the service
grpc::string package_name;
//Package name for the service
grpc::string package_name;
};
// Return the source of the generated service file.

View File

@@ -34,79 +34,93 @@
#ifndef GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
#define GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
#include <map>
#include "src/compiler/config.h"
#include <memory>
#include <vector>
#ifndef GRPC_CUSTOM_STRING
#include <string>
#define GRPC_CUSTOM_STRING std::string
#endif
#ifndef GRPC_CUSTOM_STRING
#include <string>
#define GRPC_CUSTOM_STRING std::string
#endif
namespace grpc {
typedef GRPC_CUSTOM_STRING string;
typedef GRPC_CUSTOM_STRING string;
} // namespace grpc
namespace grpc_generator {
// An abstract interface representing a method.
struct Method {
virtual ~Method() {}
// A common interface for objects having comments in the source.
// Return formatted comments to be inserted in generated code.
struct CommentHolder {
virtual ~CommentHolder() {}
virtual grpc::string GetLeadingComments(const grpc::string prefix) const = 0;
virtual grpc::string GetTrailingComments(const grpc::string prefix) const = 0;
virtual std::vector<grpc::string> GetAllComments() const = 0;
};
virtual grpc::string name() const = 0;
// An abstract interface representing a method.
struct Method : public CommentHolder {
virtual ~Method() {}
virtual grpc::string input_type_name() const = 0;
virtual grpc::string output_type_name() const = 0;
virtual grpc::string input_name() const = 0;
virtual grpc::string output_name() const = 0;
virtual grpc::string name() const = 0;
virtual bool NoStreaming() const = 0;
virtual bool ClientOnlyStreaming() const = 0;
virtual bool ServerOnlyStreaming() const = 0;
virtual bool BidiStreaming() const = 0;
};
virtual grpc::string input_type_name() const = 0;
virtual grpc::string output_type_name() const = 0;
// An abstract interface representing a service.
struct Service {
virtual ~Service() {}
virtual bool get_module_and_message_path_input(
grpc::string *str, grpc::string generator_file_name,
bool generate_in_pb2_grpc, grpc::string import_prefix) const = 0;
virtual bool get_module_and_message_path_output(
grpc::string *str, grpc::string generator_file_name,
bool generate_in_pb2_grpc, grpc::string import_prefix) const = 0;
virtual grpc::string name() const = 0;
virtual grpc::string get_input_type_name() const = 0;
virtual grpc::string get_output_type_name() const = 0;
virtual bool NoStreaming() const = 0;
virtual bool ClientStreaming() const = 0;
virtual bool ServerStreaming() const = 0;
virtual bool BidiStreaming() const = 0;
};
virtual int method_count() const = 0;
virtual std::unique_ptr<const Method> method(int i) const = 0;
};
// An abstract interface representing a service.
struct Service : public CommentHolder {
virtual ~Service() {}
struct Printer {
virtual ~Printer() {}
virtual grpc::string name() const = 0;
virtual void Print(const std::map<grpc::string, grpc::string> &vars,
const char *template_string) = 0;
virtual void Print(const char *string) = 0;
virtual void Indent() = 0;
virtual void Outdent() = 0;
};
virtual int method_count() const = 0;
virtual std::unique_ptr<const Method> method(int i) const = 0;
};
// An interface that allows the source generated to be output using various
// libraries/idls/serializers.
struct File {
virtual ~File() {}
struct Printer {
virtual ~Printer() {}
virtual grpc::string filename() const = 0;
virtual grpc::string filename_without_ext() const = 0;
virtual grpc::string message_header_ext() const = 0;
virtual grpc::string service_header_ext() const = 0;
virtual grpc::string package() const = 0;
virtual std::vector<grpc::string> package_parts() const = 0;
virtual grpc::string additional_headers() const = 0;
virtual grpc::string additional_imports() const = 0;
virtual void Print(const std::map<grpc::string, grpc::string> &vars,
const char *template_string) = 0;
virtual void Print(const char *string) = 0;
virtual void Indent() = 0;
virtual void Outdent() = 0;
};
virtual int service_count() const = 0;
virtual std::unique_ptr<const Service> service(int i) const = 0;
// An interface that allows the source generated to be output using various
// libraries/idls/serializers.
struct File : public CommentHolder {
virtual ~File() {}
virtual std::unique_ptr<Printer> CreatePrinter(grpc::string *str) const = 0;
};
} // namespace grpc_generator
virtual grpc::string filename() const = 0;
virtual grpc::string filename_without_ext() const = 0;
virtual grpc::string package() const = 0;
virtual std::vector<grpc::string> package_parts() const = 0;
virtual grpc::string additional_headers() const = 0;
virtual int service_count() const = 0;
virtual std::unique_ptr<const Service> service(int i) const = 0;
virtual std::unique_ptr<Printer> CreatePrinter(grpc::string *str) const = 0;
};
} // namespace grpc_generator
#endif // GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H

View File

@@ -27,31 +27,41 @@ using namespace MyGame::Example;
// code. It implements all rpcs specified in the FlatBuffers schema.
class ServiceImpl final : public MyGame::Example::MonsterStorage::Service {
virtual ::grpc::Status Store(::grpc::ServerContext* context,
const flatbuffers::BufferRef<Monster> *request,
flatbuffers::BufferRef<Stat> *response)
const flatbuffers::grpc::Message<Monster> *request,
flatbuffers::grpc::Message<Stat> *response)
override {
// Create a response from the incoming request name.
fbb_.Clear();
auto stat_offset = CreateStat(fbb_, fbb_.CreateString("Hello, " +
request->GetRoot()->name()->str()));
fbb_.Finish(stat_offset);
// Since we keep reusing the same FlatBufferBuilder, the memory it owns
// remains valid until the next call (this BufferRef doesn't own the
// memory it points to).
*response = flatbuffers::BufferRef<Stat>(fbb_.GetBufferPointer(),
fbb_.GetSize());
// Transfer ownership of the message to gRPC
*response = fbb_.ReleaseMessage<Stat>();
return grpc::Status::OK;
}
virtual ::grpc::Status Retrieve(::grpc::ServerContext *context,
const flatbuffers::BufferRef<Stat> *request,
::grpc::ServerWriter< flatbuffers::BufferRef<Monster>>* writer)
override {
assert(false); // We're not actually using this RPC.
return grpc::Status::CANCELLED;
const flatbuffers::grpc::Message<Stat> *request,
::grpc::ServerWriter< flatbuffers::grpc::Message<Monster>>* writer)
override {
for (int i=0; i<10; i++) {
fbb_.Clear();
// Create 10 monsters for resposne.
auto monster_offset =
CreateMonster(fbb_, 0, 0, 0, fbb_.CreateString(
request->GetRoot()->id()->str() + " No." + std::to_string(i)));
fbb_.Finish(monster_offset);
flatbuffers::grpc::Message<Monster> monster = fbb_.ReleaseMessage<Monster>();
// Send monster to client using streaming.
writer->Write(monster);
}
return grpc::Status::OK;
}
private:
flatbuffers::FlatBufferBuilder fbb_;
flatbuffers::grpc::MessageBuilder fbb_;
};
// Track the server instance, so we can terminate it later.
@@ -93,25 +103,55 @@ int main(int /*argc*/, const char * /*argv*/[]) {
grpc::InsecureChannelCredentials());
auto stub = MyGame::Example::MonsterStorage::NewStub(channel);
grpc::ClientContext context;
// Build a request with the name set.
flatbuffers::FlatBufferBuilder fbb;
auto monster_offset = CreateMonster(fbb, 0, 0, 0, fbb.CreateString("Fred"));
fbb.Finish(monster_offset);
auto request = flatbuffers::BufferRef<Monster>(fbb.GetBufferPointer(),
fbb.GetSize());
flatbuffers::BufferRef<Stat> response;
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;
// The actual RPC.
auto status = stub->Store(&context, request, &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;
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
{
// Test that an invalid request errors out correctly
grpc::ClientContext context;
flatbuffers::grpc::Message<Monster> request; // simulate invalid message
flatbuffers::grpc::Message<Stat> response;
auto status = stub->Store(&context, request, &response);
// The rpc status should be INTERNAL to indicate a verification error. This
// matches the protobuf gRPC status code for an unparseable message.
assert(!status.ok());
assert(status.error_code() == ::grpc::StatusCode::INTERNAL);
assert(strcmp(status.error_message().c_str(), "Message verification failed") == 0);
}
#endif
server_instance->Shutdown();
@@ -121,4 +161,3 @@ int main(int /*argc*/, const char * /*argv*/[]) {
return 0;
}

233
include/flatbuffers/base.h Normal file
View File

@@ -0,0 +1,233 @@
#ifndef FLATBUFFERS_BASE_H_
#define FLATBUFFERS_BASE_H_
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
defined(_MSC_VER) && defined(_DEBUG)
#define _CRTDBG_MAP_ALLOC
#endif
#include <assert.h>
#ifndef ARDUINO
#include <cstdint>
#endif
#include <cstddef>
#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
#include <utility>
#endif
#include <string>
#include <type_traits>
#include <vector>
#include <set>
#include <algorithm>
#include <iterator>
#include <memory>
#ifdef _STLPORT_VERSION
#define FLATBUFFERS_CPP98_STL
#endif
#ifndef FLATBUFFERS_CPP98_STL
#include <functional>
#endif
#include "flatbuffers/stl_emulation.h"
/// @cond FLATBUFFERS_INTERNAL
#if __cplusplus <= 199711L && \
(!defined(_MSC_VER) || _MSC_VER < 1600) && \
(!defined(__GNUC__) || \
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400))
#error A C++11 compatible compiler with support for the auto typing is \
required for FlatBuffers.
#error __cplusplus _MSC_VER __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__
#endif
#if !defined(__clang__) && \
defined(__GNUC__) && \
(__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600)
// Backwards compatability for g++ 4.4, and 4.5 which don't have the nullptr
// and constexpr keywords. Note the __clang__ check is needed, because clang
// presents itself as an older GNUC compiler.
#ifndef nullptr_t
const class nullptr_t {
public:
template<class T> inline operator T*() const { return 0; }
private:
void operator&() const;
} nullptr = {};
#endif
#ifndef constexpr
#define constexpr const
#endif
#endif
// The wire format uses a little endian encoding (since that's efficient for
// the common platforms).
#if defined(__s390x__)
#define FLATBUFFERS_LITTLEENDIAN 0
#endif // __s390x__
#if !defined(FLATBUFFERS_LITTLEENDIAN)
#if defined(__GNUC__) || defined(__clang__)
#ifdef __BIG_ENDIAN__
#define FLATBUFFERS_LITTLEENDIAN 0
#else
#define FLATBUFFERS_LITTLEENDIAN 1
#endif // __BIG_ENDIAN__
#elif defined(_MSC_VER)
#if defined(_M_PPC)
#define FLATBUFFERS_LITTLEENDIAN 0
#else
#define FLATBUFFERS_LITTLEENDIAN 1
#endif
#else
#error Unable to determine endianness, define FLATBUFFERS_LITTLEENDIAN.
#endif
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
#define FLATBUFFERS_VERSION_MAJOR 1
#define FLATBUFFERS_VERSION_MINOR 8
#define FLATBUFFERS_VERSION_REVISION 0
#define FLATBUFFERS_STRING_EXPAND(X) #X
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
#if (!defined(_MSC_VER) || _MSC_VER > 1600) && \
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407))
#define FLATBUFFERS_FINAL_CLASS final
#define FLATBUFFERS_OVERRIDE override
#else
#define FLATBUFFERS_FINAL_CLASS
#define FLATBUFFERS_OVERRIDE
#endif
#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406))
#define FLATBUFFERS_CONSTEXPR constexpr
#else
#define FLATBUFFERS_CONSTEXPR
#endif
#if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46 || \
defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026
#define FLATBUFFERS_NOEXCEPT noexcept
#else
#define FLATBUFFERS_NOEXCEPT
#endif
// NOTE: the FLATBUFFERS_DELETE_FUNC macro may change the access mode to
// private, so be sure to put it at the end or reset access mode explicitly.
#if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \
(!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404))
#define FLATBUFFERS_DELETE_FUNC(func) func = delete;
#else
#define FLATBUFFERS_DELETE_FUNC(func) private: func;
#endif
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4127) // C4127: conditional expression is constant
#endif
/// @endcond
/// @file
namespace flatbuffers {
/// @cond FLATBUFFERS_INTERNAL
// Our default offset / size type, 32bit on purpose on 64bit systems.
// Also, using a consistent offset type maintains compatibility of serialized
// offset values between 32bit and 64bit systems.
typedef uint32_t uoffset_t;
// Signed offsets for references that can go in both directions.
typedef int32_t soffset_t;
// Offset/index used in v-tables, can be changed to uint8_t in
// format forks to save a bit of space if desired.
typedef uint16_t voffset_t;
typedef uintmax_t largest_scalar_t;
// In 32bits, this evaluates to 2GB - 1
#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(soffset_t) * 8 - 1)) - 1)
// We support aligning the contents of buffers up to this size.
#define FLATBUFFERS_MAX_ALIGNMENT 16
template<typename T> T EndianSwap(T t) {
#if defined(_MSC_VER)
#define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
#define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
#define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
#else
#if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__)
// __builtin_bswap16 was missing prior to GCC 4.8.
#define FLATBUFFERS_BYTESWAP16(x) \
static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16))
#else
#define FLATBUFFERS_BYTESWAP16 __builtin_bswap16
#endif
#define FLATBUFFERS_BYTESWAP32 __builtin_bswap32
#define FLATBUFFERS_BYTESWAP64 __builtin_bswap64
#endif
if (sizeof(T) == 1) { // Compile-time if-then's.
return t;
} else if (sizeof(T) == 2) {
union { T t; uint16_t i; } u;
u.t = t;
u.i = FLATBUFFERS_BYTESWAP16(u.i);
return u.t;
} else if (sizeof(T) == 4) {
union { T t; uint32_t i; } u;
u.t = t;
u.i = FLATBUFFERS_BYTESWAP32(u.i);
return u.t;
} else if (sizeof(T) == 8) {
union { T t; uint64_t i; } u;
u.t = t;
u.i = FLATBUFFERS_BYTESWAP64(u.i);
return u.t;
} else {
assert(0);
}
}
template<typename T> T EndianScalar(T t) {
#if FLATBUFFERS_LITTLEENDIAN
return t;
#else
return EndianSwap(t);
#endif
}
template<typename T> T ReadScalar(const void *p) {
return EndianScalar(*reinterpret_cast<const T *>(p));
}
template<typename T> void WriteScalar(void *p, T t) {
*reinterpret_cast<T *>(p) = EndianScalar(t);
}
// 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).
inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
return ((~buf_size) + 1) & (scalar_size - 1);
}
} // namespace flatbuffers
#endif // FLATBUFFERS_BASE_H_

View File

@@ -95,8 +95,6 @@ class BaseGenerator {
static const char *FlatBuffersGeneratedWarning();
bool IsEverythingGenerated() const;
static std::string FullNamespace(const char *separator, const Namespace &ns);
static std::string LastNamespacePart(const Namespace &ns);
@@ -114,6 +112,8 @@ class BaseGenerator {
std::string WrapInNameSpace(const Definition &def) const;
std::string GetNameSpace(const Definition &def) const;
const Parser &parser_;
const std::string &path_;
const std::string &file_name_;

File diff suppressed because it is too large Load Diff

View File

@@ -42,6 +42,7 @@ class FlatCompiler {
const char *generator_opt_short;
const char *generator_opt_long;
const char *lang_name;
bool schema_only;
GenerateFn generateGRPC;
flatbuffers::IDLOptions::Language lang;
const char *generator_help;

View File

@@ -17,14 +17,21 @@
#ifndef FLATBUFFERS_FLEXBUFFERS_H_
#define FLATBUFFERS_FLEXBUFFERS_H_
#include <map>
// Used to select STL variant.
#include "flatbuffers/base.h"
// We use the basic binary writing functions from the regular FlatBuffers.
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/util.h"
#ifdef _MSC_VER
#include <intrin.h>
#endif
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4127) // C4127: conditional expression is constant
#endif
namespace flexbuffers {
class Reference;
@@ -69,23 +76,25 @@ enum Type {
TYPE_VECTOR_UINT4 = 23,
TYPE_VECTOR_FLOAT4 = 24,
TYPE_BLOB = 25,
TYPE_BOOL = 26,
TYPE_VECTOR_BOOL = 36, // To Allow the same type of conversion of type to vector type
};
inline bool IsInline(Type t) { return t <= TYPE_FLOAT; }
inline bool IsInline(Type t) { return t <= TYPE_FLOAT || t == TYPE_BOOL; }
inline bool IsTypedVectorElementType(Type t) {
return t >= TYPE_INT && t <= TYPE_STRING;
return (t >= TYPE_INT && t <= TYPE_STRING) || t == TYPE_BOOL;
}
inline bool IsTypedVector(Type t) {
return t >= TYPE_VECTOR_INT && t <= TYPE_VECTOR_STRING;
return (t >= TYPE_VECTOR_INT && t <= TYPE_VECTOR_STRING) || t == TYPE_VECTOR_BOOL;
}
inline bool IsFixedTypedVector(Type t) {
return t >= TYPE_VECTOR_INT2 && t <= TYPE_VECTOR_FLOAT4;
}
inline Type ToTypedVector(Type t, int fixed_len = 0) {
inline Type ToTypedVector(Type t, size_t fixed_len = 0) {
assert(IsTypedVectorElementType(t));
switch (fixed_len) {
case 0: return static_cast<Type>(t - TYPE_INT + TYPE_VECTOR_INT);
@@ -104,7 +113,7 @@ inline Type ToTypedVectorElementType(Type t) {
inline Type ToFixedTypedVectorElementType(Type t, uint8_t *len) {
assert(IsFixedTypedVector(t));
auto fixed_type = t - TYPE_VECTOR_INT2;
*len = fixed_type / 3 + 2; // 3 types each, starting from length 2.
*len = static_cast<uint8_t>(fixed_type / 3 + 2); // 3 types each, starting from length 2.
return static_cast<Type>(fixed_type % 3 + TYPE_INT);
}
@@ -155,7 +164,7 @@ inline double ReadDouble(const uint8_t *data, uint8_t byte_width) {
byte_width);
}
const uint8_t *Indirect(const uint8_t *offset, uint8_t byte_width) {
inline const uint8_t *Indirect(const uint8_t *offset, uint8_t byte_width) {
return offset - ReadUInt64(offset, byte_width);
}
@@ -163,7 +172,7 @@ template<typename T> const uint8_t *Indirect(const uint8_t *offset) {
return offset - flatbuffers::ReadScalar<T>(offset);
}
static BitWidth WidthU(uint64_t u) {
inline BitWidth WidthU(uint64_t u) {
#define FLATBUFFERS_GET_FIELD_BIT_WIDTH(value, width) { \
if (!((u) & ~((1ULL << (width)) - 1ULL))) return BIT_WIDTH_##width; \
}
@@ -174,12 +183,12 @@ static BitWidth WidthU(uint64_t u) {
return BIT_WIDTH_64;
}
static BitWidth WidthI(int64_t i) {
inline BitWidth WidthI(int64_t i) {
auto u = static_cast<uint64_t>(i) << 1;
return WidthU(i >= 0 ? u : ~u);
}
static BitWidth WidthF(double f) {
inline BitWidth WidthF(double f) {
return static_cast<double>(static_cast<float>(f)) == f ? BIT_WIDTH_32
: BIT_WIDTH_64;
}
@@ -212,6 +221,7 @@ class String : public Sized {
size_t length() const { return size(); }
const char *c_str() const { return reinterpret_cast<const char *>(data_); }
std::string str() const { return std::string(c_str(), length()); }
static String EmptyString() {
static const uint8_t empty_string[] = { 0/*len*/, 0/*terminator*/ };
@@ -222,14 +232,15 @@ class String : public Sized {
class Blob : public Sized {
public:
Blob(const uint8_t *data, uint8_t byte_width)
: Sized(data, byte_width) {}
Blob(const uint8_t *data_buf, uint8_t byte_width)
: Sized(data_buf, byte_width) {}
static Blob EmptyBlob() {
static const uint8_t empty_blob[] = { 0/*len*/ };
return Blob(empty_blob + 1, 1);
}
bool IsTheEmptyBlob() const { return data_ == EmptyBlob().data_; }
const uint8_t *data() const { return data_; }
};
class Vector : public Sized {
@@ -340,6 +351,7 @@ class Reference {
Type GetType() const { return type_; }
bool IsNull() const { return type_ == TYPE_NULL; }
bool IsBool() const { return type_ == TYPE_BOOL; }
bool IsInt() const { return type_ == TYPE_INT ||
type_ == TYPE_INDIRECT_INT; }
bool IsUInt() const { return type_ == TYPE_UINT||
@@ -352,6 +364,11 @@ class Reference {
bool IsKey() const { return type_ == TYPE_KEY; }
bool IsVector() const { return type_ == TYPE_VECTOR || type_ == TYPE_MAP; }
bool IsMap() const { return type_ == TYPE_MAP; }
bool IsBlob() const { return type_ == TYPE_BLOB; }
bool AsBool() const {
return (type_ == TYPE_BOOL ? ReadUInt64(data_, parent_width_) : AsUInt64()) != 0;
}
// Reads any type as a int64_t. Never fails, does most sensible conversion.
// Truncates floats, strings are attempted to be parsed for a number,
@@ -371,6 +388,7 @@ class Reference {
case TYPE_NULL: return 0;
case TYPE_STRING: return flatbuffers::StringToInt(AsString().c_str());
case TYPE_VECTOR: return static_cast<int64_t>(AsVector().size());
case TYPE_BOOL: return ReadInt64(data_, parent_width_);
default:
// Convert other things to int.
return 0;
@@ -398,6 +416,7 @@ class Reference {
case TYPE_NULL: return 0;
case TYPE_STRING: return flatbuffers::StringToUInt(AsString().c_str());
case TYPE_VECTOR: return static_cast<uint64_t>(AsVector().size());
case TYPE_BOOL: return ReadUInt64(data_, parent_width_);
default:
// Convert other things to uint.
return 0;
@@ -425,6 +444,8 @@ class Reference {
case TYPE_NULL: return 0.0;
case TYPE_STRING: return strtod(AsString().c_str(), nullptr);
case TYPE_VECTOR: return static_cast<double>(AsVector().size());
case TYPE_BOOL: return static_cast<double>(
ReadUInt64(data_, parent_width_));
default:
// Convert strings and other things to float.
return 0;
@@ -451,25 +472,63 @@ class Reference {
}
// Unlike AsString(), this will convert any type to a std::string.
std::string ToString() const {
std::string ToString() {
std::string s;
ToString(false, false, s);
return s;
}
// Convert any type to a JSON-like string. strings_quoted determines if
// string values at the top level receive "" quotes (inside other values
// they always do). keys_quoted determines if keys are quoted, at any level.
// TODO(wvo): add further options to have indentation/newlines.
void ToString(bool strings_quoted, bool keys_quoted, std::string &s) const {
if (type_ == TYPE_STRING) {
return String(Indirect(), byte_width_).c_str();
String str(Indirect(), byte_width_);
if (strings_quoted) {
flatbuffers::EscapeString(str.c_str(), str.length(), &s, true);
} else {
s.append(str.c_str(), str.length());
}
} else if (IsKey()) {
return AsKey();
auto str = AsKey();
if (keys_quoted) {
flatbuffers::EscapeString(str, strlen(str), &s, true);
} else {
s += str;
}
} else if (IsInt()) {
return flatbuffers::NumToString(AsInt64());
s += flatbuffers::NumToString(AsInt64());
} else if (IsUInt()) {
return flatbuffers::NumToString(AsUInt64());
s += flatbuffers::NumToString(AsUInt64());
} else if (IsFloat()) {
return flatbuffers::NumToString(AsDouble());
s += flatbuffers::NumToString(AsDouble());
} else if (IsNull()) {
return "null";
s += "null";
} else if (IsBool()) {
s += AsBool() ? "true" : "false";
} else if (IsMap()) {
return "{..}"; // TODO: show elements.
s += "{ ";
auto m = AsMap();
auto keys = m.Keys();
auto vals = m.Values();
for (size_t i = 0; i < keys.size(); i++) {
keys[i].ToString(true, keys_quoted, s);
s += ": ";
vals[i].ToString(true, keys_quoted, s);
if (i < keys.size() - 1) s += ", ";
}
s += " }";
} else if (IsVector()) {
return "[..]"; // TODO: show elements.
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 += " ]";
} else {
return "(?)";
s += "(?)";
}
}
@@ -520,6 +579,8 @@ class Reference {
}
}
template<typename T> T As();
// Experimental: Mutation functions.
// These allow scalars in an already created buffer to be updated in-place.
// Since by default scalars are stored in the smallest possible space,
@@ -542,6 +603,10 @@ class Reference {
}
}
bool MutateBool(bool b) {
return type_ == TYPE_BOOL && Mutate(data_, b, parent_width_, BIT_WIDTH_8);
}
bool MutateUInt(uint64_t u) {
if (type_ == TYPE_UINT) {
return Mutate(data_, u, parent_width_, WidthU(u));
@@ -601,7 +666,7 @@ class Reference {
template<typename T> bool Mutate(const uint8_t *dest, T t, size_t byte_width,
BitWidth value_width) {
auto fits = (1U << value_width) <= byte_width;
auto fits = static_cast<size_t>(static_cast<size_t>(1U) << value_width) <= byte_width;
if (fits) {
t = flatbuffers::EndianScalar(t);
memcpy(const_cast<uint8_t *>(dest), &t, byte_width);
@@ -625,6 +690,31 @@ class Reference {
Type type_;
};
// Template specialization for As().
template<> inline bool Reference::As<bool>() { 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 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 double Reference::As<double>() { return AsDouble(); }
template<> inline float Reference::As<float>() { return AsFloat(); }
template<> inline String Reference::As<String>() { return AsString(); }
template<> inline std::string Reference::As<std::string>() { 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>() { return AsTypedVector(); }
template<> inline FixedTypedVector Reference::As<FixedTypedVector>() { return AsFixedTypedVector(); }
template<> inline Map Reference::As<Map>() { return AsMap(); }
inline uint8_t PackedType(BitWidth bit_width, Type type) {
return static_cast<uint8_t>(bit_width | (type << 2));
}
@@ -701,7 +791,7 @@ inline Reference GetRoot(const uint8_t *buffer, size_t size) {
}
inline Reference GetRoot(const std::vector<uint8_t> &buffer) {
return GetRoot(buffer.data(), buffer.size());
return GetRoot(flatbuffers::vector_data(buffer), buffer.size());
}
// Flags that configure how the Builder behaves.
@@ -740,6 +830,22 @@ class Builder FLATBUFFERS_FINAL_CLASS {
return buf_;
}
// Size of the buffer. Does not include unfinished values.
size_t GetSize() const {
return buf_.size();
}
// Reset all state so we can re-use the buffer.
void Clear() {
buf_.clear();
stack_.clear();
finished_ = false;
// flags_ remains as-is;
force_min_bit_width_ = BIT_WIDTH_8;
key_pool.clear();
string_pool.clear();
}
// All value constructing functions below have two versions: one that
// takes a key (for placement inside a map) and one that doesn't (for inside
// vectors and elsewhere).
@@ -759,7 +865,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
void Double(double f) { stack_.push_back(Value(f)); }
void Double(const char *key, double d) { Key(key); Double(d); }
void Bool(bool b) { Int(static_cast<int64_t>(b)); }
void Bool(bool b) { stack_.push_back(Value(b)); }
void Bool(const char *key, bool b) { Key(key); Bool(b); }
void IndirectInt(int64_t i) {
@@ -860,7 +966,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
return CreateBlob(data, len, 0, TYPE_BLOB);
}
size_t Blob(const std::vector<uint8_t> &v) {
return CreateBlob(v.data(), v.size(), 0, TYPE_BLOB);
return CreateBlob(flatbuffers::vector_data(v), v.size(), 0, TYPE_BLOB);
}
// TODO(wvo): support all the FlexBuffer types (like flexbuffers::String),
@@ -904,11 +1010,15 @@ class Builder FLATBUFFERS_FINAL_CLASS {
// step automatically when appliccable, and encourage people to write in
// sorted fashion.
// std::sort is typically already a lot faster on sorted data though.
auto dict = reinterpret_cast<TwoValue *>(stack_.data() + start);
auto dict =
reinterpret_cast<TwoValue *>(flatbuffers::vector_data(stack_) +
start);
std::sort(dict, dict + len,
[&](const TwoValue &a, const TwoValue &b) -> bool {
auto as = reinterpret_cast<const char *>(buf_.data() + a.key.u_);
auto bs = reinterpret_cast<const char *>(buf_.data() + b.key.u_);
auto as = reinterpret_cast<const char *>(
flatbuffers::vector_data(buf_) + a.key.u_);
auto bs = reinterpret_cast<const char *>(
flatbuffers::vector_data(buf_) + b.key.u_);
auto comp = strcmp(as, bs);
// If this assertion hits, you've added two keys with the same value to
// this map.
@@ -933,13 +1043,25 @@ class Builder FLATBUFFERS_FINAL_CLASS {
f();
return EndVector(start, false, false);
}
template <typename F, typename T> size_t Vector(F f, T &state) {
auto start = StartVector();
f(state);
return EndVector(start, false, false);
}
template<typename F> size_t Vector(const char *key, F f) {
auto start = StartVector(key);
f();
return EndVector(start, false, false);
}
template <typename F, typename T> size_t Vector(const char *key, F f,
T &state) {
auto start = StartVector(key);
f(state);
return EndVector(start, false, false);
}
template<typename T> void Vector(const T *elems, size_t len) {
if (std::is_scalar<T>::value) {
if (flatbuffers::is_scalar<T>::value) {
// This path should be a lot quicker and use less space.
ScalarVector(elems, len, false);
} else {
@@ -954,7 +1076,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
Vector(elems, len);
}
template<typename T> void Vector(const std::vector<T> &vec) {
Vector(vec.data(), vec.size());
Vector(flatbuffers::vector_data(vec), vec.size());
}
template<typename F> size_t TypedVector(F f) {
@@ -962,18 +1084,29 @@ class Builder FLATBUFFERS_FINAL_CLASS {
f();
return EndVector(start, true, false);
}
template <typename F, typename T> size_t TypedVector(F f, T &state) {
auto start = StartVector();
f(state);
return EndVector(start, true, false);
}
template<typename F> size_t TypedVector(const char *key, F f) {
auto start = StartVector(key);
f();
return EndVector(start, true, false);
}
template <typename F, typename T> size_t TypedVector(const char *key, F f,
T &state) {
auto start = StartVector(key);
f(state);
return EndVector(start, true, false);
}
template<typename T> size_t FixedTypedVector(const T *elems, size_t len) {
// We only support a few fixed vector lengths. Anything bigger use a
// regular typed vector.
assert(len >= 2 && len <= 4);
// And only scalar values.
assert(std::is_scalar<T>::value);
assert(flatbuffers::is_scalar<T>::value);
return ScalarVector(elems, len, true);
}
@@ -988,11 +1121,22 @@ class Builder FLATBUFFERS_FINAL_CLASS {
f();
return EndMap(start);
}
template <typename F, typename T> size_t Map(F f, T &state) {
auto start = StartMap();
f(state);
return EndMap(start);
}
template<typename F> size_t Map(const char *key, F f) {
auto start = StartMap(key);
f();
return EndMap(start);
}
template <typename F, typename T> size_t Map(const char *key, F f,
T &state) {
auto start = StartMap(key);
f(state);
return EndMap(start);
}
template<typename T> void Map(const std::map<std::string, T> &map) {
auto start = StartMap();
for (auto it = map.begin(); it != map.end(); ++it)
@@ -1072,7 +1216,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
auto byte_width = 1U << alignment;
buf_.insert(buf_.end(), flatbuffers::PaddingBytes(buf_.size(), byte_width),
0);
return byte_width;
return static_cast<uint8_t>(byte_width);
}
void WriteBytes(const void *val, size_t size) {
@@ -1081,8 +1225,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
reinterpret_cast<const uint8_t *>(val) + size);
}
// For values T >= byte_width
template<typename T> void Write(T val, uint8_t byte_width) {
template<typename T> void Write(T val, size_t byte_width) {
assert(sizeof(T) >= byte_width);
val = flatbuffers::EndianScalar(val);
WriteBytes(&val, byte_width);
}
@@ -1121,10 +1265,11 @@ class Builder FLATBUFFERS_FINAL_CLASS {
}
template<typename T> static Type GetScalarType() {
assert(std::is_scalar<T>::value);
return std::is_floating_point<T>::value
assert(flatbuffers::is_scalar<T>::value);
return flatbuffers::is_floating_point<T>::value
? TYPE_FLOAT
: (std::is_unsigned<T>::value ? TYPE_UINT : TYPE_INT);
: flatbuffers::is_same<T, bool>::value ? TYPE_BOOL
: (flatbuffers::is_unsigned<T>::value ? TYPE_UINT : TYPE_INT);
}
struct Value {
@@ -1141,6 +1286,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
Value() : i_(0), type_(TYPE_NULL), min_bit_width_(BIT_WIDTH_8) {}
Value(bool b) : u_(static_cast<uint64_t>(b)), type_(TYPE_BOOL), min_bit_width_(BIT_WIDTH_8) {}
Value(int64_t i, Type t, BitWidth bw)
: i_(i), type_(t), min_bit_width_(bw) {}
Value(uint64_t u, Type t, BitWidth bw)
@@ -1176,7 +1323,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
auto offset = offset_loc - u_;
// Does it fit?
auto bit_width = WidthU(offset);
if (1U << bit_width == byte_width) return bit_width;
if (static_cast<size_t>(static_cast<size_t>(1U) << bit_width) == byte_width)
return bit_width;
}
assert(false); // Must match one of the sizes above.
return BIT_WIDTH_64;
@@ -1185,7 +1333,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
BitWidth StoredWidth(BitWidth parent_bit_width_ = BIT_WIDTH_8) const {
if (IsInline(type_)) {
return std::max(min_bit_width_, parent_bit_width_);
return (std::max)(min_bit_width_, parent_bit_width_);
} else {
return min_bit_width_;
}
@@ -1198,6 +1346,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
case TYPE_INT:
Write(val.i_, byte_width);
break;
case TYPE_BOOL:
case TYPE_UINT:
Write(val.u_, byte_width);
break;
@@ -1231,7 +1380,7 @@ class Builder FLATBUFFERS_FINAL_CLASS {
// TODO: instead of asserting, could write vector with larger elements
// instead, though that would be wasteful.
assert(WidthU(len) <= bit_width);
if (!fixed) Write(len, byte_width);
if (!fixed) Write<uint64_t>(len, byte_width);
auto vloc = buf_.size();
for (size_t i = 0; i < len; i++) Write(elems[i], byte_width);
stack_.push_back(Value(static_cast<uint64_t>(vloc),
@@ -1243,19 +1392,19 @@ class Builder FLATBUFFERS_FINAL_CLASS {
Value CreateVector(size_t start, size_t vec_len, size_t step, bool typed,
bool fixed, const Value *keys = nullptr) {
// Figure out smallest bit width we can store this vector with.
auto bit_width = std::max(force_min_bit_width_, WidthU(vec_len));
auto bit_width = (std::max)(force_min_bit_width_, WidthU(vec_len));
auto prefix_elems = 1;
if (keys) {
// If this vector is part of a map, we will pre-fix an offset to the keys
// to this vector.
bit_width = std::max(bit_width, keys->ElemWidth(buf_.size(), 0));
bit_width = (std::max)(bit_width, keys->ElemWidth(buf_.size(), 0));
prefix_elems += 2;
}
Type vector_type = TYPE_KEY;
// Check bit widths and types for all elements.
for (size_t i = start; i < stack_.size(); i += step) {
auto elem_width = stack_[i].ElemWidth(buf_.size(), i + prefix_elems);
bit_width = std::max(bit_width, elem_width);
bit_width = (std::max)(bit_width, elem_width);
if (typed) {
if (i == start) {
vector_type = stack_[i].type_;
@@ -1273,9 +1422,9 @@ class Builder FLATBUFFERS_FINAL_CLASS {
// Write vector. First the keys width/offset if available, and size.
if (keys) {
WriteOffset(keys->u_, byte_width);
Write(1U << keys->min_bit_width_, byte_width);
Write<uint64_t>(1ULL << keys->min_bit_width_, byte_width);
}
if (!fixed) Write(vec_len, byte_width);
if (!fixed) Write<uint64_t>(vec_len, byte_width);
// Then the actual data.
auto vloc = buf_.size();
for (size_t i = start; i < stack_.size(); i += step) {
@@ -1310,9 +1459,11 @@ class Builder FLATBUFFERS_FINAL_CLASS {
struct KeyOffsetCompare {
KeyOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {}
bool operator() (size_t a, size_t b) const {
auto stra = reinterpret_cast<const char *>(buf_->data() + a);
auto strb = reinterpret_cast<const char *>(buf_->data() + b);
bool operator()(size_t a, size_t b) const {
auto stra =
reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + a);
auto strb =
reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + b);
return strcmp(stra, strb) < 0;
}
const std::vector<uint8_t> *buf_;
@@ -1321,10 +1472,12 @@ class Builder FLATBUFFERS_FINAL_CLASS {
typedef std::pair<size_t, size_t> StringOffset;
struct StringOffsetCompare {
StringOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {}
bool operator() (const StringOffset &a, const StringOffset &b) const {
auto stra = reinterpret_cast<const char *>(buf_->data() + a.first);
auto strb = reinterpret_cast<const char *>(buf_->data() + b.first);
return strncmp(stra, strb, std::min(a.second, b.second) + 1) < 0;
bool operator()(const StringOffset &a, const StringOffset &b) const {
auto stra = reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) +
a.first);
auto strb = reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) +
b.first);
return strncmp(stra, strb, (std::min)(a.second, b.second) + 1) < 0;
}
const std::vector<uint8_t> *buf_;
};
@@ -1338,4 +1491,8 @@ class Builder FLATBUFFERS_FINAL_CLASS {
} // namespace flexbuffers
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#endif // FLATBUFFERS_FLEXBUFFERS_H_

View File

@@ -19,49 +19,234 @@
// Helper functionality to glue FlatBuffers and GRPC.
#include "flatbuffers/flatbuffers.h"
#include "grpc++/support/byte_buffer.h"
#include "grpc/byte_buffer_reader.h"
namespace flatbuffers {
namespace grpc {
// Message is a typed wrapper around a buffer that manages the underlying
// `grpc_slice` and also provides flatbuffers-specific helpers such as `Verify`
// and `GetRoot`. Since it is backed by a `grpc_slice`, the underlying buffer
// is refcounted and ownership is be managed automatically.
template <class T>
class Message {
public:
Message() : slice_(grpc_empty_slice()) {}
Message(grpc_slice slice, bool add_ref)
: slice_(add_ref ? grpc_slice_ref(slice) : slice) {}
Message &operator=(const Message &other) = delete;
Message(Message &&other) : slice_(other.slice_) {
other.slice_ = grpc_empty_slice();
}
Message(const Message &other) = delete;
Message &operator=(Message &&other) {
grpc_slice_unref(slice_);
slice_ = other.slice_;
other.slice_ = grpc_empty_slice();
return *this;
}
~Message() { grpc_slice_unref(slice_); }
const uint8_t *mutable_data() const { return GRPC_SLICE_START_PTR(slice_); }
const uint8_t *data() const { return GRPC_SLICE_START_PTR(slice_); }
size_t size() const { return GRPC_SLICE_LENGTH(slice_); }
bool Verify() const {
Verifier verifier(data(), size());
return verifier.VerifyBuffer<T>(nullptr);
}
T *GetMutableRoot() { return flatbuffers::GetMutableRoot<T>(mutable_data()); }
const T *GetRoot() const { return flatbuffers::GetRoot<T>(data()); }
// This is only intended for serializer use, or if you know what you're doing
const grpc_slice &BorrowSlice() const { return slice_; }
private:
grpc_slice slice_;
};
class MessageBuilder;
// SliceAllocator is a gRPC-specific allocator that uses the `grpc_slice`
// refcounted slices to manage memory ownership. This makes it easy and
// efficient to transfer buffers to gRPC.
class SliceAllocator : public Allocator {
public:
SliceAllocator() : slice_(grpc_empty_slice()) {}
SliceAllocator(const SliceAllocator &other) = delete;
SliceAllocator &operator=(const SliceAllocator &other) = delete;
virtual ~SliceAllocator() { grpc_slice_unref(slice_); }
virtual uint8_t *allocate(size_t size) override {
assert(GRPC_SLICE_IS_EMPTY(slice_));
slice_ = grpc_slice_malloc(size);
return GRPC_SLICE_START_PTR(slice_);
}
virtual void deallocate(uint8_t *p, size_t size) override {
assert(p == GRPC_SLICE_START_PTR(slice_));
assert(size == GRPC_SLICE_LENGTH(slice_));
grpc_slice_unref(slice_);
slice_ = grpc_empty_slice();
}
virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
size_t new_size) override {
assert(old_p == GRPC_SLICE_START_PTR(slice_));
assert(old_size == GRPC_SLICE_LENGTH(slice_));
assert(new_size > old_size);
grpc_slice old_slice = slice_;
grpc_slice new_slice = grpc_slice_malloc(new_size);
uint8_t *new_p = GRPC_SLICE_START_PTR(new_slice);
memcpy(new_p + (new_size - old_size), old_p, old_size);
slice_ = new_slice;
grpc_slice_unref(old_slice);
return new_p;
}
private:
grpc_slice &get_slice(uint8_t *p, size_t size) {
assert(p == GRPC_SLICE_START_PTR(slice_));
assert(size == GRPC_SLICE_LENGTH(slice_));
return slice_;
}
grpc_slice slice_;
friend class MessageBuilder;
};
// SliceAllocatorMember is a hack to ensure that the MessageBuilder's
// slice_allocator_ member is constructed before the FlatBufferBuilder, since
// the allocator is used in the FlatBufferBuilder ctor.
namespace detail {
struct SliceAllocatorMember {
SliceAllocator slice_allocator_;
};
}
// MessageBuilder is a gRPC-specific FlatBufferBuilder that uses SliceAllocator
// to allocate gRPC buffers.
class MessageBuilder : private detail::SliceAllocatorMember,
public FlatBufferBuilder {
public:
explicit MessageBuilder(uoffset_t initial_size = 1024)
: FlatBufferBuilder(initial_size, &slice_allocator_, false) {}
MessageBuilder(const MessageBuilder &other) = delete;
MessageBuilder &operator=(const MessageBuilder &other) = delete;
~MessageBuilder() {}
// GetMessage extracts the subslice of the buffer corresponding to the
// flatbuffers-encoded region and wraps it in a `Message<T>` to handle buffer
// ownership.
template <class T>
Message<T> GetMessage() {
auto buf_data = buf_.buf(); // pointer to memory
auto buf_size = buf_.capacity(); // size of memory
auto msg_data = buf_.data(); // pointer to msg
auto msg_size = buf_.size(); // size of msg
// Do some sanity checks on data/size
assert(msg_data);
assert(msg_size);
assert(msg_data >= buf_data);
assert(msg_data + msg_size <= buf_data + buf_size);
// Calculate offsets from the buffer start
auto begin = msg_data - buf_data;
auto end = begin + msg_size;
// Get the slice we are working with (no refcount change)
grpc_slice slice = slice_allocator_.get_slice(buf_data, buf_size);
// Extract a subslice of the existing slice (increment refcount)
grpc_slice subslice = grpc_slice_sub(slice, begin, end);
// Wrap the subslice in a `Message<T>`, but don't increment refcount
Message<T> msg(subslice, false);
return msg;
}
template <class T>
Message<T> ReleaseMessage() {
Message<T> msg = GetMessage<T>();
Reset();
return msg;
}
private:
// SliceAllocator slice_allocator_; // part of SliceAllocatorMember
};
} // namespace grpc
} // namespace flatbuffers
namespace grpc {
template <class T>
class SerializationTraits<T, typename std::enable_if<std::is_base_of<
flatbuffers::BufferRefBase, T>::value>::type> {
class SerializationTraits<flatbuffers::grpc::Message<T>> {
public:
// The type we're passing here is a BufferRef, which is already serialized
// FlatBuffer data, which then gets passed to GRPC.
static grpc::Status Serialize(const T& msg,
grpc_byte_buffer **buffer,
bool *own_buffer) {
// TODO(wvo): make this work without copying.
auto slice = gpr_slice_from_copied_buffer(
reinterpret_cast<const char *>(msg.buf), msg.len);
*buffer = grpc_raw_byte_buffer_create(&slice, 1);
static grpc::Status Serialize(const flatbuffers::grpc::Message<T> &msg,
grpc_byte_buffer **buffer, bool *own_buffer) {
// We are passed in a `Message<T>`, which is a wrapper around a
// `grpc_slice`. We extract it here using `BorrowSlice()`. The const cast
// is necesary because the `grpc_raw_byte_buffer_create` func expects
// non-const slices in order to increment their refcounts.
grpc_slice *slice = const_cast<grpc_slice *>(&msg.BorrowSlice());
// Now use `grpc_raw_byte_buffer_create` to package the single slice into a
// `grpc_byte_buffer`, incrementing the refcount in the process.
*buffer = grpc_raw_byte_buffer_create(slice, 1);
*own_buffer = true;
return grpc::Status();
return grpc::Status::OK;
}
// There is no de-serialization step in FlatBuffers, so we just receive
// the data from GRPC.
static grpc::Status Deserialize(grpc_byte_buffer *buffer, T *msg) {
// TODO(wvo): make this more efficient / zero copy when possible.
auto len = grpc_byte_buffer_length(buffer);
msg->buf = reinterpret_cast<uint8_t *>(malloc(len));
msg->len = static_cast<flatbuffers::uoffset_t>(len);
msg->must_free = true;
uint8_t *current = msg->buf;
grpc_byte_buffer_reader reader;
grpc_byte_buffer_reader_init(&reader, buffer);
gpr_slice slice;
while (grpc_byte_buffer_reader_next(&reader, &slice)) {
memcpy(current, GPR_SLICE_START_PTR(slice), GPR_SLICE_LENGTH(slice));
current += GPR_SLICE_LENGTH(slice);
gpr_slice_unref(slice);
// Deserialize by pulling the
static grpc::Status Deserialize(grpc_byte_buffer *buffer,
flatbuffers::grpc::Message<T> *msg) {
if (!buffer) {
return ::grpc::Status(::grpc::StatusCode::INTERNAL, "No payload");
}
// Check if this is a single uncompressed slice.
if ((buffer->type == GRPC_BB_RAW) &&
(buffer->data.raw.compression == GRPC_COMPRESS_NONE) &&
(buffer->data.raw.slice_buffer.count == 1)) {
// If it is, then we can reference the `grpc_slice` directly.
grpc_slice slice = buffer->data.raw.slice_buffer.slices[0];
// We wrap a `Message<T>` around the slice, incrementing the refcount.
*msg = flatbuffers::grpc::Message<T>(slice, true);
} else {
// Otherwise, we need to use `grpc_byte_buffer_reader_readall` to read
// `buffer` into a single contiguous `grpc_slice`. The gRPC reader gives
// us back a new slice with the refcount already incremented.
grpc_byte_buffer_reader reader;
grpc_byte_buffer_reader_init(&reader, buffer);
grpc_slice slice = grpc_byte_buffer_reader_readall(&reader);
grpc_byte_buffer_reader_destroy(&reader);
// We wrap a `Message<T>` around the slice, but dont increment refcount
*msg = flatbuffers::grpc::Message<T>(slice, false);
}
GPR_ASSERT(current == msg->buf + msg->len);
grpc_byte_buffer_reader_destroy(&reader);
grpc_byte_buffer_destroy(buffer);
return grpc::Status();
#if FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
return ::grpc::Status::OK;
#else
if (msg->Verify()) {
return ::grpc::Status::OK;
} else {
return ::grpc::Status(::grpc::StatusCode::INTERNAL,
"Message verification failed");
}
#endif
}
};

View File

@@ -20,11 +20,16 @@
#include <map>
#include <stack>
#include <memory>
#include <functional>
#include "flatbuffers/base.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/hash.h"
#include "flatbuffers/reflection.h"
#include "flatbuffers/flexbuffers.h"
#if !defined(FLATBUFFERS_CPP98_STL)
#include <functional>
#endif // !defined(FLATBUFFERS_CPP98_STL)
// This file defines the data types representing a parsed IDL (Interface
// Definition Language) / schema file.
@@ -104,6 +109,7 @@ inline bool IsFloat (BaseType t) { return t == BASE_TYPE_FLOAT ||
t == BASE_TYPE_DOUBLE; }
inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
t == BASE_TYPE_ULONG; }
inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; }
extern const char *const kTypeNames[];
extern const char kTypeSizes[];
@@ -163,7 +169,7 @@ template<typename T> class SymbolTable {
}
bool Add(const std::string &name, T *e) {
vec.emplace_back(e);
vector_emplace_back(&vec, e);
auto it = dict.find(name);
if (it != dict.end()) return true;
dict[name] = e;
@@ -193,7 +199,8 @@ template<typename T> class SymbolTable {
// A name space, as set in the schema.
struct Namespace {
std::vector<std::string> components;
Namespace() : from_table(0) {}
// Given a (potentally unqualified) name, return the "fully qualified" name
// which has a full namespaced descriptor.
@@ -201,12 +208,15 @@ struct Namespace {
// the current namespace has.
std::string GetFullyQualifiedName(const std::string &name,
size_t max_components = 1000) const;
std::vector<std::string> components;
size_t from_table; // Part of the namespace corresponds to a message/table.
};
// Base class for all definition types (fields, structs_, enums_).
struct Definition {
Definition() : generated(false), defined_namespace(nullptr),
serialized_location(0), index(-1) {}
serialized_location(0), index(-1), refcount(1) {}
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<
reflection::KeyValue>>>
@@ -223,21 +233,26 @@ struct Definition {
// For use with Serialize()
uoffset_t serialized_location;
int index; // Inside the vector it is stored.
int refcount;
};
struct FieldDef : public Definition {
FieldDef() : deprecated(false), required(false), key(false), padding(0) {}
FieldDef() : deprecated(false), required(false), key(false),
native_inline(false), flexbuffer(false), nested_flatbuffer(NULL),
padding(0) {}
Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id,
const Parser &parser) const;
Value value;
bool deprecated; // Field is allowed to be present in old data, but can't be
bool deprecated; // Field is allowed to be present in old data, but can't be.
// written in new data nor accessed in new code.
bool required; // Field must always be present.
bool key; // Field functions as a key for creating sorted vectors.
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.
StructDef *nested_flatbuffer; // This field contains nested FlatBuffer data.
size_t padding; // Bytes to always pad after this field.
};
@@ -261,12 +276,15 @@ struct StructDef : public Definition {
const Parser &parser) const;
SymbolTable<FieldDef> fields;
bool fixed; // If it's struct, not a table.
bool predecl; // If it's used before it was defined.
bool sortbysize; // Whether fields come in the declaration or size order.
bool has_key; // It has a key field.
size_t minalign; // What the whole object needs to be aligned to.
size_t bytesize; // Size if fixed.
flatbuffers::unique_ptr<std::string> original_location;
};
inline bool IsStruct(const Type &type) {
@@ -283,18 +301,18 @@ inline size_t InlineAlignment(const Type &type) {
struct EnumVal {
EnumVal(const std::string &_name, int64_t _val)
: name(_name), value(_val), struct_def(nullptr) {}
: name(_name), value(_val) {}
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder) const;
std::string name;
std::vector<std::string> doc_comment;
int64_t value;
StructDef *struct_def; // only set if this is a union
Type union_type;
};
struct EnumDef : public Definition {
EnumDef() : is_union(false) {}
EnumDef() : is_union(false), uses_type_aliases(false) {}
EnumVal *ReverseLookup(int enum_idx, bool skip_union_default = true) {
for (auto it = vals.vec.begin() + static_cast<int>(is_union &&
@@ -312,6 +330,7 @@ struct EnumDef : public Definition {
SymbolTable<EnumVal> vals;
bool is_union;
bool uses_type_aliases;
Type underlying_type;
};
@@ -350,13 +369,22 @@ struct IDLOptions {
bool generate_all;
bool skip_unexpected_fields_in_json;
bool generate_name_strings;
bool escape_proto_identifiers;
bool generate_object_based_api;
std::string cpp_object_api_pointer_type;
std::string cpp_object_api_string_type;
bool gen_nullable;
std::string object_prefix;
std::string object_suffix;
bool union_value_namespacing;
bool allow_non_utf8;
std::string include_prefix;
bool keep_include_path;
bool binary_schema_comments;
bool skip_flatbuffers_import;
std::string go_import;
std::string go_namespace;
bool reexport_ts_modules;
bool protobuf_ascii_alike;
// Possible options for the more general generator below.
enum Language {
@@ -369,11 +397,17 @@ struct IDLOptions {
kPhp = 1 << 6,
kJson = 1 << 7,
kBinary = 1 << 8,
kTs = 1 << 9,
kJsonSchema = 1 << 10,
kMAX
};
Language lang;
enum MiniReflect { kNone, kTypes, kTypesAndNames };
MiniReflect mini_reflect;
// The corresponding language bit will be set if a language is included
// for code generation.
unsigned long lang_to_generate;
@@ -392,13 +426,19 @@ struct IDLOptions {
generate_all(false),
skip_unexpected_fields_in_json(false),
generate_name_strings(false),
escape_proto_identifiers(false),
generate_object_based_api(false),
cpp_object_api_pointer_type("std::unique_ptr"),
gen_nullable(false),
object_suffix("T"),
union_value_namespacing(true),
allow_non_utf8(false),
keep_include_path(false),
binary_schema_comments(false),
skip_flatbuffers_import(false),
reexport_ts_modules(true),
protobuf_ascii_alike(false),
lang(IDLOptions::kJava),
mini_reflect(IDLOptions::kNone),
lang_to_generate(0) {}
};
@@ -459,12 +499,17 @@ class CheckedError {
class Parser : public ParserState {
public:
explicit Parser(const IDLOptions &options = IDLOptions())
: root_struct_def_(nullptr),
: current_namespace_(nullptr),
empty_namespace_(nullptr),
root_struct_def_(nullptr),
opts(options),
uses_flexbuffers_(false),
source_(nullptr),
anonymous_counter(0) {
// Just in case none are declared:
namespaces_.push_back(new Namespace());
// Start out with the empty namespace being current.
empty_namespace_ = new Namespace();
namespaces_.push_back(empty_namespace_);
current_namespace_ = empty_namespace_;
known_attributes_["deprecated"] = true;
known_attributes_["required"] = true;
known_attributes_["key"] = true;
@@ -479,9 +524,11 @@ class Parser : public ParserState {
known_attributes_["idempotent"] = true;
known_attributes_["cpp_type"] = true;
known_attributes_["cpp_ptr_type"] = true;
known_attributes_["cpp_str_type"] = true;
known_attributes_["native_inline"] = true;
known_attributes_["native_type"] = true;
known_attributes_["native_default"] = true;
known_attributes_["flexbuffer"] = true;
}
~Parser() {
@@ -499,6 +546,8 @@ class Parser : public ParserState {
// directory.
// If the source was loaded from a file and isn't an include file,
// supply its name in source_filename.
// All paths specified in this call must be in posix format, if you accept
// paths from user input, please call PosixPath on them first.
bool Parse(const char *_source, const char **include_paths = nullptr,
const char *source_filename = nullptr);
@@ -521,14 +570,24 @@ class Parser : public ParserState {
// of the schema provided. Returns non-empty error on any problems.
std::string ConformTo(const Parser &base);
FLATBUFFERS_CHECKED_ERROR CheckBitsFit(int64_t val, size_t bits);
// Similar to Parse(), but now only accepts JSON to be parsed into a
// FlexBuffer.
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;
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();
bool Is(int t);
bool IsIdent(const char *id);
FLATBUFFERS_CHECKED_ERROR Expect(int t);
std::string TokenToStringId(int t);
EnumDef *LookupEnum(const std::string &id);
@@ -540,18 +599,46 @@ private:
const std::string &name, const Type &type,
FieldDef **dest);
FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def);
FLATBUFFERS_CHECKED_ERROR ParseString(Value &val);
FLATBUFFERS_CHECKED_ERROR ParseComma();
FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
size_t parent_fieldn,
const StructDef *parent_struct_def);
#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)
FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
const StructDef *struct_def,
ParseTableDelimitersBody body,
void *state);
FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
std::string *value, uoffset_t *ovalue);
void SerializeStruct(const StructDef &struct_def, const Value &val);
void AddVector(bool sortbysize, int count);
#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)
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(
size_t &count, ParseVectorDelimitersBody body, void *state);
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue);
FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field,
size_t fieldn,
const StructDef *parent_struct_def);
FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
FLATBUFFERS_CHECKED_ERROR TryTypedValue(int dtoken, bool check, Value &e,
BaseType req, bool *destmatch);
FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef* field);
FLATBUFFERS_CHECKED_ERROR TokenError();
FLATBUFFERS_CHECKED_ERROR ParseSingleValue(Value &e);
FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(Type &type, int64_t *result);
StructDef *LookupCreateStruct(const std::string &name,
@@ -571,23 +658,32 @@ private:
FLATBUFFERS_CHECKED_ERROR ParseProtoCurliesOrIdent();
FLATBUFFERS_CHECKED_ERROR ParseTypeFromProtoType(Type *type);
FLATBUFFERS_CHECKED_ERROR SkipAnyJsonValue();
FLATBUFFERS_CHECKED_ERROR SkipJsonObject();
FLATBUFFERS_CHECKED_ERROR SkipJsonArray();
FLATBUFFERS_CHECKED_ERROR SkipJsonString();
FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder);
FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source,
const char *source_filename);
FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source,
const char **include_paths,
const char *source_filename);
FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
const char **include_paths,
const char *source_filename,
const char *include_filename);
FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef*> &fields,
StructDef *struct_def,
const char *suffix,
BaseType baseType);
bool SupportsVectorOfUnions() const;
Namespace *UniqueNamespace(Namespace *ns);
public:
SymbolTable<Type> types_;
SymbolTable<StructDef> structs_;
SymbolTable<EnumDef> enums_;
SymbolTable<ServiceDef> services_;
std::vector<Namespace *> namespaces_;
Namespace *current_namespace_;
Namespace *empty_namespace_;
std::string error_; // User readable error_ if Parse() == false
FlatBufferBuilder builder_; // any data contained in the file
@@ -595,13 +691,14 @@ private:
std::string file_identifier_;
std::string file_extension_;
std::map<std::string, bool> included_files_;
std::map<std::string, std::string> included_files_;
std::map<std::string, std::set<std::string>> files_included_per_file_;
std::vector<std::string> native_included_files_;
std::map<std::string, bool> known_attributes_;
IDLOptions opts;
bool uses_flexbuffers_;
private:
const char *source_;
@@ -647,7 +744,7 @@ extern bool GenerateCPP(const Parser &parser,
const std::string &path,
const std::string &file_name);
// Generate JavaScript code from the definitions in the Parser object.
// Generate JavaScript or TypeScript code from the definitions in the Parser object.
// See idl_gen_js.
extern std::string GenerateJS(const Parser &parser);
extern bool GenerateJS(const Parser &parser,
@@ -678,6 +775,12 @@ extern bool GeneratePython(const Parser &parser,
const std::string &path,
const std::string &file_name);
// Generate Json schema file
// See idl_gen_json_schema.cpp.
extern bool GenerateJsonSchema(const Parser &parser,
const std::string &path,
const std::string &file_name);
// Generate C# files from the definitions in the Parser object.
// See idl_gen_csharp.cpp.
extern bool GenerateCSharp(const Parser &parser,
@@ -698,7 +801,7 @@ extern bool GenerateFBS(const Parser &parser,
const std::string &path,
const std::string &file_name);
// Generate a make rule for the generated JavaScript code.
// Generate a make rule for the generated JavaScript or TypeScript code.
// See idl_gen_js.cpp.
extern std::string JSMakeRule(const Parser &parser,
const std::string &path,
@@ -743,4 +846,3 @@ bool GenerateGoGRPC(const Parser &parser,
} // namespace flatbuffers
#endif // FLATBUFFERS_IDL_H_

View File

@@ -0,0 +1,352 @@
/*
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FLATBUFFERS_MINIREFLECT_H_
#define FLATBUFFERS_MINIREFLECT_H_
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/util.h"
namespace flatbuffers {
// Utilities that can be used with the "mini reflection" tables present
// in generated code with --reflect-types (only types) or --reflect-names
// (also names).
// This allows basic reflection functionality such as pretty-printing
// that does not require the use of the schema parser or loading of binary
// schema files at runtime (reflection.h).
// For any of the functions below that take `const TypeTable *`, you pass
// `FooTypeTable()` if the type of the root is `Foo`.
// First, a generic iterator that can be used by multiple algorithms.
struct IterationVisitor {
// These mark the scope of a table or struct.
virtual void StartSequence() {}
virtual void EndSequence() {}
// Called for each field regardless of wether it is present or not.
// If not present, val == nullptr. set_idx is the index of all set fields.
virtual void Field(size_t /*field_idx*/, size_t /*set_idx*/,
ElementaryType /*type*/, bool /*is_vector*/,
const TypeTable * /*type_table*/, const char * /*name*/,
const uint8_t * /*val*/) {}
// Called for a value that is actually present, after a field, or as part
// of a vector.
virtual void UType(uint8_t, const char *) {}
virtual void Bool(bool) {}
virtual void Char(int8_t, const char *) {}
virtual void UChar(uint8_t, const char *) {}
virtual void Short(int16_t, const char *) {}
virtual void UShort(uint16_t, const char *) {}
virtual void Int(int32_t, const char *) {}
virtual void UInt(uint32_t, const char *) {}
virtual void Long(int64_t) {}
virtual void ULong(uint64_t) {}
virtual void Float(float) {}
virtual void Double(double) {}
virtual void String(const String *) {}
virtual void Unknown(const uint8_t *) {} // From a future version.
// These mark the scope of a vector.
virtual void StartVector() {}
virtual void EndVector() {}
virtual void Element(size_t /*i*/, ElementaryType /*type*/,
const TypeTable * /*type_table*/,
const uint8_t * /*val*/)
{}
virtual ~IterationVisitor() {}
};
inline size_t InlineSize(ElementaryType type, const TypeTable *type_table) {
switch (type) {
case ET_UTYPE:
case ET_BOOL:
case ET_CHAR:
case ET_UCHAR:
return 1;
case ET_SHORT:
case ET_USHORT:
return 2;
case ET_INT:
case ET_UINT:
case ET_FLOAT:
case ET_STRING:
return 4;
case ET_LONG:
case ET_ULONG:
case ET_DOUBLE:
return 8;
case ET_SEQUENCE:
switch (type_table->st) {
case ST_TABLE:
case ST_UNION:
return 4;
case ST_STRUCT:
return type_table->values[type_table->num_elems];
default:
assert(false);
return 1;
}
default:
assert(false);
return 1;
}
}
inline int32_t LookupEnum(int32_t enum_val, const int32_t *values,
size_t num_values) {
if (!values) return enum_val;
for (size_t i = 0; i < num_values; i++) {
if (enum_val == values[i]) return static_cast<int32_t>(i);
}
return -1; // Unknown enum value.
}
template<typename T> const char *EnumName(T tval, const TypeTable *type_table) {
if (!type_table || !type_table->names) return nullptr;
auto i = LookupEnum(static_cast<int32_t>(tval), type_table->values,
type_table->num_elems);
if (i >= 0 && i < static_cast<int32_t>(type_table->num_elems)) {
return type_table->names[i];
}
return nullptr;
}
void IterateObject(const uint8_t *obj, const TypeTable *type_table,
IterationVisitor *visitor);
inline void IterateValue(ElementaryType type, const uint8_t *val,
const TypeTable *type_table,
const uint8_t *prev_val,
soffset_t vector_index,
IterationVisitor *visitor) {
switch (type) {
case ET_UTYPE: {
auto tval = *reinterpret_cast<const uint8_t *>(val);
visitor->UType(tval, EnumName(tval, type_table));
break;
}
case ET_BOOL: {
visitor->Bool(*reinterpret_cast<const uint8_t *>(val) != 0);
break;
}
case ET_CHAR: {
auto tval = *reinterpret_cast<const int8_t *>(val);
visitor->Char(tval, EnumName(tval, type_table));
break;
}
case ET_UCHAR: {
auto tval = *reinterpret_cast<const uint8_t *>(val);
visitor->UChar(tval, EnumName(tval, type_table));
break;
}
case ET_SHORT: {
auto tval = *reinterpret_cast<const int16_t *>(val);
visitor->Short(tval, EnumName(tval, type_table));
break;
}
case ET_USHORT: {
auto tval = *reinterpret_cast<const uint16_t *>(val);
visitor->UShort(tval, EnumName(tval, type_table));
break;
}
case ET_INT: {
auto tval = *reinterpret_cast<const int32_t *>(val);
visitor->Int(tval, EnumName(tval, type_table));
break;
}
case ET_UINT: {
auto tval = *reinterpret_cast<const uint32_t *>(val);
visitor->UInt(tval, EnumName(tval, type_table));
break;
}
case ET_LONG: {
visitor->Long(*reinterpret_cast<const int64_t *>(val));
break;
}
case ET_ULONG: {
visitor->ULong(*reinterpret_cast<const uint64_t *>(val));
break;
}
case ET_FLOAT: {
visitor->Float(*reinterpret_cast<const float *>(val));
break;
}
case ET_DOUBLE: {
visitor->Double(*reinterpret_cast<const double *>(val));
break;
}
case ET_STRING: {
val += ReadScalar<uoffset_t>(val);
visitor->String(reinterpret_cast<const String *>(val));
break;
}
case ET_SEQUENCE: {
switch (type_table->st) {
case ST_TABLE:
val += ReadScalar<uoffset_t>(val);
IterateObject(val, type_table, visitor);
break;
case ST_STRUCT:
IterateObject(val, type_table, visitor);
break;
case ST_UNION: {
val += ReadScalar<uoffset_t>(val);
assert(prev_val);
auto union_type = *prev_val; // Always a uint8_t.
if (vector_index >= 0) {
auto type_vec = reinterpret_cast<const Vector<uint8_t> *>(prev_val);
union_type = type_vec->Get(static_cast<uoffset_t>(vector_index));
}
auto type_code_idx = LookupEnum(union_type, type_table->values,
type_table->num_elems);
if (type_code_idx >= 0 && type_code_idx <
static_cast<int32_t>(type_table->num_elems)) {
auto type_code = type_table->type_codes[type_code_idx];
switch (type_code.base_type) {
case ET_SEQUENCE: {
auto ref = type_table->type_refs[type_code.sequence_ref]();
IterateObject(val, ref, visitor);
break;
}
case ET_STRING:
visitor->String(reinterpret_cast<const String *>(val));
break;
default:
visitor->Unknown(val);
}
} else {
visitor->Unknown(val);
}
break;
}
case ST_ENUM:
assert(false);
break;
}
break;
}
default: {
visitor->Unknown(val);
break;
}
}
}
inline void IterateObject(const uint8_t *obj, const TypeTable *type_table,
IterationVisitor *visitor) {
visitor->StartSequence();
const uint8_t *prev_val = nullptr;
size_t set_idx = 0;
for (size_t i = 0; i < type_table->num_elems; i++) {
auto type_code = type_table->type_codes[i];
auto type = static_cast<ElementaryType>(type_code.base_type);
auto is_vector = type_code.is_vector != 0;
auto ref_idx = type_code.sequence_ref;
const TypeTable *ref = nullptr;
if (ref_idx >= 0) {
ref = type_table->type_refs[ref_idx]();
}
auto name = type_table->names ? type_table->names[i] : nullptr;
const uint8_t *val = nullptr;
if (type_table->st == ST_TABLE) {
val = reinterpret_cast<const Table *>(obj)->GetAddressOf(
FieldIndexToOffset(static_cast<voffset_t>(i)));
} else {
val = obj + type_table->values[i];
}
visitor->Field(i, set_idx, type, is_vector, ref, name, val);
if (val) {
set_idx++;
if (is_vector) {
val += ReadScalar<uoffset_t>(val);
auto vec = reinterpret_cast<const Vector<uint8_t> *>(val);
visitor->StartVector();
auto elem_ptr = vec->Data();
for (size_t j = 0; j < vec->size(); j++) {
visitor->Element(j, type, ref, elem_ptr);
IterateValue(type, elem_ptr, ref, prev_val, static_cast<soffset_t>(j),
visitor);
elem_ptr += InlineSize(type, ref);
}
visitor->EndVector();
} else {
IterateValue(type, val, ref, prev_val, -1, visitor);
}
}
prev_val = val;
}
visitor->EndSequence();
}
inline void IterateFlatBuffer(const uint8_t *buffer,
const TypeTable *type_table,
IterationVisitor *callback) {
IterateObject(GetRoot<uint8_t>(buffer), type_table, callback);
}
// Outputting a Flatbuffer to a string. Tries to conform as close to JSON /
// the output generated by idl_gen_text.cpp.
struct ToStringVisitor : public IterationVisitor {
std::string s;
void StartSequence() { s += "{ "; }
void EndSequence() { s += " }"; }
void Field(size_t /*field_idx*/, size_t set_idx, ElementaryType /*type*/,
bool /*is_vector*/, const TypeTable * /*type_table*/,
const char *name, const uint8_t *val) {
if (!val) return;
if (set_idx) s += ", ";
if (name) { s += name; s += ": "; }
}
template<typename T> void Named(T x, const char *name) {
if (name) s+= name;
else s+= NumToString(x);
}
void UType(uint8_t x, const char *name) { Named(x, name); }
void Bool(bool x) { s+= x ? "true" : "false"; }
void Char(int8_t x, const char *name) { Named(x, name); }
void UChar(uint8_t x, const char *name) { Named(x, name); }
void Short(int16_t x, const char *name) { Named(x, name); }
void UShort(uint16_t x, const char *name) { Named(x, name); }
void Int(int32_t x, const char *name) { Named(x, name); }
void UInt(uint32_t x, const char *name) { Named(x, name); }
void Long(int64_t x) { s+= NumToString(x); }
void ULong(uint64_t x) { s+= NumToString(x); }
void Float(float x) { s+= NumToString(x); }
void Double(double x) { s+= NumToString(x); }
void String(const struct String *str) {
EscapeString(str->c_str(), str->size(), &s, true);
}
void Unknown(const uint8_t *) { s += "(?)"; }
void StartVector() { s += "[ "; }
void EndVector() { s += " ]"; }
void Element(size_t i, ElementaryType /*type*/,
const TypeTable * /*type_table*/, const uint8_t * /*val*/) {
if (i) s += ", ";
}
};
inline std::string FlatBufferToString(const uint8_t *buffer,
const TypeTable *type_table) {
ToStringVisitor tostring_visitor;
IterateFlatBuffer(buffer, type_table, &tostring_visitor);
return tostring_visitor.s;
}
} // namespace flatbuffers
#endif // FLATBUFFERS_MINIREFLECT_H_

View File

@@ -30,6 +30,15 @@ namespace flatbuffers {
// ------------------------- GETTERS -------------------------
inline bool IsScalar (reflection::BaseType t) { return t >= reflection::UType &&
t <= reflection::Double; }
inline bool IsInteger(reflection::BaseType t) { return t >= reflection::UType &&
t <= reflection::ULong; }
inline bool IsFloat (reflection::BaseType t) { return t == reflection::Float ||
t == reflection::Double; }
inline bool IsLong (reflection::BaseType t) { return t == reflection::Long ||
t == reflection::ULong; }
// Size of a basic type, don't use with structs.
inline size_t GetTypeSize(reflection::BaseType base_type) {
// This needs to correspond to the BaseType enum.
@@ -58,6 +67,18 @@ inline const Table *GetAnyRoot(const uint8_t *flatbuf) {
return GetRoot<Table>(flatbuf);
}
// Get a field's default, if you know it's an integer, and its exact type.
template<typename T> T GetFieldDefaultI(const reflection::Field &field) {
assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
return static_cast<T>(field.default_integer());
}
// Get a field's default, if you know it's floating point and its exact type.
template<typename T> T GetFieldDefaultF(const reflection::Field &field) {
assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
return static_cast<T>(field.default_real());
}
// Get a field, if you know it's an integer, and its exact type.
template<typename T> T GetFieldI(const Table &table,
const reflection::Field &field) {
@@ -242,8 +263,19 @@ template<typename T> T *GetAnyFieldAddressOf(const Struct &st,
// Set any scalar field, if you know its exact type.
template<typename T> bool SetField(Table *table, const reflection::Field &field,
T val) {
assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
return table->SetField(field.offset(), val);
reflection::BaseType type = field.type()->base_type();
if (!IsScalar(type)) {
return false;
}
assert(sizeof(T) == GetTypeSize(type));
T def;
if (IsInteger(type)) {
def = GetFieldDefaultI<T>(field);
} else {
assert(IsFloat(type));
def = GetFieldDefaultF<T>(field);
}
return table->SetField(field.offset(), val, def);
}
// Raw helper functions used below: set any value in memory as a 64bit int, a
@@ -258,7 +290,7 @@ void SetAnyValueS(reflection::BaseType type, uint8_t *data, const char *val);
inline bool SetAnyFieldI(Table *table, const reflection::Field &field,
int64_t val) {
auto field_ptr = table->GetAddressOf(field.offset());
if (!field_ptr) return false;
if (!field_ptr) return val == GetFieldDefaultI<int64_t>(field);
SetAnyValueI(field.type()->base_type(), field_ptr, val);
return true;
}
@@ -267,7 +299,7 @@ inline bool SetAnyFieldI(Table *table, const reflection::Field &field,
inline bool SetAnyFieldF(Table *table, const reflection::Field &field,
double val) {
auto field_ptr = table->GetAddressOf(field.offset());
if (!field_ptr) return false;
if (!field_ptr) return val == GetFieldDefaultF<double>(field);
SetAnyValueF(field.type()->base_type(), field_ptr, val);
return true;
}
@@ -329,12 +361,13 @@ template<typename T, typename U> class pointer_inside_vector {
public:
pointer_inside_vector(T *ptr, std::vector<U> &vec)
: offset_(reinterpret_cast<uint8_t *>(ptr) -
reinterpret_cast<uint8_t *>(vec.data())),
reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec))),
vec_(vec) {}
T *operator*() const {
return reinterpret_cast<T *>(
reinterpret_cast<uint8_t *>(vec_.data()) + offset_);
reinterpret_cast<uint8_t *>(
flatbuffers::vector_data(vec_)) + offset_);
}
T *operator->() const {
return operator*();
@@ -386,7 +419,6 @@ uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize,
uoffset_t elem_size, std::vector<uint8_t> *flatbuf,
const reflection::Object *root_table = nullptr);
#ifndef FLATBUFFERS_CPP98_STL
template <typename T>
void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
const Vector<T> *vec, std::vector<uint8_t> *flatbuf,
@@ -400,7 +432,7 @@ void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
// Set new elements to "val".
for (int i = 0; i < delta_elem; i++) {
auto loc = newelems + i * sizeof(T);
auto is_scalar = std::is_scalar<T>::value;
auto is_scalar = flatbuffers::is_scalar<T>::value;
if (is_scalar) {
WriteScalar(loc, val);
} else { // struct
@@ -408,7 +440,6 @@ void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
}
}
}
#endif
// Adds any new data (in the form of a new FlatBuffer) to an existing
// FlatBuffer. This can be used when any of the above methods are not

View File

@@ -42,6 +42,29 @@ enum BaseType {
Union = 16
};
inline BaseType (&EnumValuesBaseType())[17] {
static BaseType values[] = {
None,
UType,
Bool,
Byte,
UByte,
Short,
UShort,
Int,
UInt,
Long,
ULong,
Float,
Double,
String,
Vector,
Obj,
Union
};
return values;
}
inline const char **EnumNamesBaseType() {
static const char *names[] = {
"None",
@@ -113,7 +136,7 @@ struct TypeBuilder {
}
TypeBuilder &operator=(const TypeBuilder &);
flatbuffers::Offset<Type> Finish() {
const auto end = fbb_.EndTable(start_, 3);
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Type>(end);
return o;
}
@@ -150,9 +173,9 @@ struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_KEY) &&
VerifyOffsetRequired(verifier, VT_KEY) &&
verifier.Verify(key()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_VALUE) &&
VerifyOffset(verifier, VT_VALUE) &&
verifier.Verify(value()) &&
verifier.EndTable();
}
@@ -173,7 +196,7 @@ struct KeyValueBuilder {
}
KeyValueBuilder &operator=(const KeyValueBuilder &);
flatbuffers::Offset<KeyValue> Finish() {
const auto end = fbb_.EndTable(start_, 2);
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<KeyValue>(end);
fbb_.Required(o, KeyValue::VT_KEY);
return o;
@@ -204,7 +227,8 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
enum {
VT_NAME = 4,
VT_VALUE = 6,
VT_OBJECT = 8
VT_OBJECT = 8,
VT_UNION_TYPE = 10
};
const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(VT_NAME);
@@ -228,13 +252,18 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
const Object *object() const {
return GetPointer<const Object *>(VT_OBJECT);
}
const Type *union_type() const {
return GetPointer<const Type *>(VT_UNION_TYPE);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
VerifyOffsetRequired(verifier, VT_NAME) &&
verifier.Verify(name()) &&
VerifyField<int64_t>(verifier, VT_VALUE) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_OBJECT) &&
VerifyOffset(verifier, VT_OBJECT) &&
verifier.VerifyTable(object()) &&
VerifyOffset(verifier, VT_UNION_TYPE) &&
verifier.VerifyTable(union_type()) &&
verifier.EndTable();
}
};
@@ -251,13 +280,16 @@ struct EnumValBuilder {
void add_object(flatbuffers::Offset<Object> object) {
fbb_.AddOffset(EnumVal::VT_OBJECT, object);
}
void add_union_type(flatbuffers::Offset<Type> union_type) {
fbb_.AddOffset(EnumVal::VT_UNION_TYPE, union_type);
}
EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
EnumValBuilder &operator=(const EnumValBuilder &);
flatbuffers::Offset<EnumVal> Finish() {
const auto end = fbb_.EndTable(start_, 3);
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<EnumVal>(end);
fbb_.Required(o, EnumVal::VT_NAME);
return o;
@@ -268,9 +300,11 @@ inline flatbuffers::Offset<EnumVal> CreateEnumVal(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::String> name = 0,
int64_t value = 0,
flatbuffers::Offset<Object> object = 0) {
flatbuffers::Offset<Object> object = 0,
flatbuffers::Offset<Type> union_type = 0) {
EnumValBuilder builder_(_fbb);
builder_.add_value(value);
builder_.add_union_type(union_type);
builder_.add_object(object);
builder_.add_name(name);
return builder_.Finish();
@@ -280,12 +314,14 @@ inline flatbuffers::Offset<EnumVal> CreateEnumValDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const char *name = nullptr,
int64_t value = 0,
flatbuffers::Offset<Object> object = 0) {
flatbuffers::Offset<Object> object = 0,
flatbuffers::Offset<Type> union_type = 0) {
return reflection::CreateEnumVal(
_fbb,
name ? _fbb.CreateString(name) : 0,
value,
object);
object,
union_type);
}
struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -323,18 +359,18 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
VerifyOffsetRequired(verifier, VT_NAME) &&
verifier.Verify(name()) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_VALUES) &&
VerifyOffsetRequired(verifier, VT_VALUES) &&
verifier.Verify(values()) &&
verifier.VerifyVectorOfTables(values()) &&
VerifyField<uint8_t>(verifier, VT_IS_UNION) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_UNDERLYING_TYPE) &&
VerifyOffsetRequired(verifier, VT_UNDERLYING_TYPE) &&
verifier.VerifyTable(underlying_type()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_ATTRIBUTES) &&
VerifyOffset(verifier, VT_ATTRIBUTES) &&
verifier.Verify(attributes()) &&
verifier.VerifyVectorOfTables(attributes()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_DOCUMENTATION) &&
VerifyOffset(verifier, VT_DOCUMENTATION) &&
verifier.Verify(documentation()) &&
verifier.VerifyVectorOfStrings(documentation()) &&
verifier.EndTable();
@@ -368,7 +404,7 @@ struct EnumBuilder {
}
EnumBuilder &operator=(const EnumBuilder &);
flatbuffers::Offset<Enum> Finish() {
const auto end = fbb_.EndTable(start_, 6);
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Enum>(end);
fbb_.Required(o, Enum::VT_NAME);
fbb_.Required(o, Enum::VT_VALUES);
@@ -468,9 +504,9 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
VerifyOffsetRequired(verifier, VT_NAME) &&
verifier.Verify(name()) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_TYPE) &&
VerifyOffsetRequired(verifier, VT_TYPE) &&
verifier.VerifyTable(type()) &&
VerifyField<uint16_t>(verifier, VT_ID) &&
VerifyField<uint16_t>(verifier, VT_OFFSET) &&
@@ -479,10 +515,10 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyField<uint8_t>(verifier, VT_DEPRECATED) &&
VerifyField<uint8_t>(verifier, VT_REQUIRED) &&
VerifyField<uint8_t>(verifier, VT_KEY) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_ATTRIBUTES) &&
VerifyOffset(verifier, VT_ATTRIBUTES) &&
verifier.Verify(attributes()) &&
verifier.VerifyVectorOfTables(attributes()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_DOCUMENTATION) &&
VerifyOffset(verifier, VT_DOCUMENTATION) &&
verifier.Verify(documentation()) &&
verifier.VerifyVectorOfStrings(documentation()) &&
verifier.EndTable();
@@ -531,7 +567,7 @@ struct FieldBuilder {
}
FieldBuilder &operator=(const FieldBuilder &);
flatbuffers::Offset<Field> Finish() {
const auto end = fbb_.EndTable(start_, 11);
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Field>(end);
fbb_.Required(o, Field::VT_NAME);
fbb_.Required(o, Field::VT_TYPE);
@@ -634,18 +670,18 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
VerifyOffsetRequired(verifier, VT_NAME) &&
verifier.Verify(name()) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_FIELDS) &&
VerifyOffsetRequired(verifier, VT_FIELDS) &&
verifier.Verify(fields()) &&
verifier.VerifyVectorOfTables(fields()) &&
VerifyField<uint8_t>(verifier, VT_IS_STRUCT) &&
VerifyField<int32_t>(verifier, VT_MINALIGN) &&
VerifyField<int32_t>(verifier, VT_BYTESIZE) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_ATTRIBUTES) &&
VerifyOffset(verifier, VT_ATTRIBUTES) &&
verifier.Verify(attributes()) &&
verifier.VerifyVectorOfTables(attributes()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_DOCUMENTATION) &&
VerifyOffset(verifier, VT_DOCUMENTATION) &&
verifier.Verify(documentation()) &&
verifier.VerifyVectorOfStrings(documentation()) &&
verifier.EndTable();
@@ -682,7 +718,7 @@ struct ObjectBuilder {
}
ObjectBuilder &operator=(const ObjectBuilder &);
flatbuffers::Offset<Object> Finish() {
const auto end = fbb_.EndTable(start_, 7);
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Object>(end);
fbb_.Required(o, Object::VT_NAME);
fbb_.Required(o, Object::VT_FIELDS);
@@ -755,17 +791,17 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_OBJECTS) &&
VerifyOffsetRequired(verifier, VT_OBJECTS) &&
verifier.Verify(objects()) &&
verifier.VerifyVectorOfTables(objects()) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_ENUMS) &&
VerifyOffsetRequired(verifier, VT_ENUMS) &&
verifier.Verify(enums()) &&
verifier.VerifyVectorOfTables(enums()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_FILE_IDENT) &&
VerifyOffset(verifier, VT_FILE_IDENT) &&
verifier.Verify(file_ident()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_FILE_EXT) &&
VerifyOffset(verifier, VT_FILE_EXT) &&
verifier.Verify(file_ext()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_ROOT_TABLE) &&
VerifyOffset(verifier, VT_ROOT_TABLE) &&
verifier.VerifyTable(root_table()) &&
verifier.EndTable();
}
@@ -795,7 +831,7 @@ struct SchemaBuilder {
}
SchemaBuilder &operator=(const SchemaBuilder &);
flatbuffers::Offset<Schema> Finish() {
const auto end = fbb_.EndTable(start_, 5);
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Schema>(end);
fbb_.Required(o, Schema::VT_OBJECTS);
fbb_.Required(o, Schema::VT_ENUMS);

View File

@@ -0,0 +1,131 @@
/*
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FLATBUFFERS_REGISTRY_H_
#define FLATBUFFERS_REGISTRY_H_
#include "flatbuffers/idl.h"
namespace flatbuffers {
// Convenience class to easily parse or generate text for arbitrary FlatBuffers.
// Simply pre-populate it with all schema filenames that may be in use, and
// This class will look them up using the file_identifier declared in the
// schema.
class Registry {
public:
// Call this for all schemas that may be in use. The identifier has
// a function in the generated code, e.g. MonsterIdentifier().
void Register(const char *file_identifier, const char *schema_path) {
Schema schema;
schema.path_ = schema_path;
schemas_[file_identifier] = schema;
}
// Generate text from an arbitrary FlatBuffer by looking up its
// file_identifier in the registry.
bool FlatBufferToText(const uint8_t *flatbuf, size_t len,
std::string *dest) {
// Get the identifier out of the buffer.
// If the buffer is truncated, exit.
if (len < sizeof(uoffset_t) +
FlatBufferBuilder::kFileIdentifierLength) {
lasterror_ = "buffer truncated";
return false;
}
std::string ident(reinterpret_cast<const char *>(flatbuf) +
sizeof(uoffset_t),
FlatBufferBuilder::kFileIdentifierLength);
// Load and parse the schema.
Parser parser;
if (!LoadSchema(ident, &parser)) return false;
// Now we're ready to generate text.
if (!GenerateText(parser, flatbuf, dest)) {
lasterror_ = "unable to generate text for FlatBuffer binary";
return false;
}
return true;
}
// Converts a binary buffer to text using one of the schemas in the registry,
// use the file_identifier to indicate which.
// If DetachedBuffer::data() is null then parsing failed.
DetachedBuffer TextToFlatBuffer(const char *text,
const char *file_identifier) {
// Load and parse the schema.
Parser parser;
if (!LoadSchema(file_identifier, &parser)) return DetachedBuffer();
// Parse the text.
if (!parser.Parse(text)) {
lasterror_ = parser.error_;
return DetachedBuffer();
}
// We have a valid FlatBuffer. Detach it from the builder and return.
return parser.builder_.ReleaseBufferPointer();
}
// Modify any parsing / output options used by the other functions.
void SetOptions(const IDLOptions &opts) { opts_ = opts; }
// If schemas used contain include statements, call this function for every
// directory the parser should search them for.
void AddIncludeDirectory(const char *path) {
include_paths_.push_back(path);
}
// Returns a human readable error if any of the above functions fail.
const std::string &GetLastError() { return lasterror_; }
private:
bool LoadSchema(const std::string &ident, Parser *parser) {
// Find the schema, if not, exit.
auto it = schemas_.find(ident);
if (it == schemas_.end()) {
// Don't attach the identifier, since it may not be human readable.
lasterror_ = "identifier for this buffer not in the registry";
return false;
}
auto &schema = it->second;
// Load the schema from disk. If not, exit.
std::string schematext;
if (!LoadFile(schema.path_.c_str(), false, &schematext)) {
lasterror_ = "could not load schema: " + schema.path_;
return false;
}
// Parse schema.
parser->opts = opts_;
if (!parser->Parse(schematext.c_str(), vector_data(include_paths_),
schema.path_.c_str())) {
lasterror_ = parser->error_;
return false;
}
return true;
}
struct Schema {
std::string path_;
// TODO(wvo) optionally cache schema file or parsed schema here.
};
std::string lasterror_;
IDLOptions opts_;
std::vector<const char *> include_paths_;
std::map<std::string, Schema> schemas_;
};
} // namespace flatbuffers
#endif // FLATBUFFERS_REGISTRY_H_

View File

@@ -0,0 +1,222 @@
/*
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FLATBUFFERS_STL_EMULATION_H_
#define FLATBUFFERS_STL_EMULATION_H_
#include <string>
#include <type_traits>
#include <vector>
#include <memory>
#include <limits>
#if defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
#define FLATBUFFERS_CPP98_STL
#endif // defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL)
#if defined(FLATBUFFERS_CPP98_STL)
#include <cctype>
#endif // defined(FLATBUFFERS_CPP98_STL)
// This header provides backwards compatibility for C++98 STLs like stlport.
namespace flatbuffers {
// Retrieve ::back() from a string in a way that is compatible with pre C++11
// STLs (e.g stlport).
inline char string_back(const std::string &value) {
return value[value.length() - 1];
}
// Helper method that retrieves ::data() from a vector in a way that is
// compatible with pre C++11 STLs (e.g stlport).
template <typename T> inline T *vector_data(std::vector<T> &vector) {
// In some debug environments, operator[] does bounds checking, so &vector[0]
// can't be used.
return &(*vector.begin());
}
template <typename T> inline const T *vector_data(
const std::vector<T> &vector) {
return &(*vector.begin());
}
template <typename T, typename V>
inline void vector_emplace_back(std::vector<T> *vector, V &&data) {
#if defined(FLATBUFFERS_CPP98_STL)
vector->push_back(data);
#else
vector->emplace_back(std::forward<V>(data));
#endif // defined(FLATBUFFERS_CPP98_STL)
}
#ifndef FLATBUFFERS_CPP98_STL
#if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
template <typename T>
using numeric_limits = std::numeric_limits<T>;
#else
template <typename T> class numeric_limits :
public std::numeric_limits<T> {};
#endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
#else
template <typename T> class numeric_limits :
public std::numeric_limits<T> {};
template <> class numeric_limits<unsigned long long> {
public:
static unsigned long long min() { return 0ULL; }
static unsigned long long max() { return ~0ULL; }
};
template <> class numeric_limits<long long> {
public:
static long long min() {
return static_cast<long long>(1ULL << ((sizeof(long long) << 3) - 1));
}
static long long max() {
return static_cast<long long>(
(1ULL << ((sizeof(long long) << 3) - 1)) - 1);
}
};
#endif // FLATBUFFERS_CPP98_STL
#if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
#ifndef FLATBUFFERS_CPP98_STL
template <typename T> using is_scalar = std::is_scalar<T>;
template <typename T, typename U> using is_same = std::is_same<T,U>;
template <typename T> using is_floating_point = std::is_floating_point<T>;
template <typename T> using is_unsigned = std::is_unsigned<T>;
#else
// Map C++ TR1 templates defined by stlport.
template <typename T> using is_scalar = std::tr1::is_scalar<T>;
template <typename T, typename U> using is_same = std::tr1::is_same<T,U>;
template <typename T> using is_floating_point =
std::tr1::is_floating_point<T>;
template <typename T> using is_unsigned = std::tr1::is_unsigned<T>;
#endif // !FLATBUFFERS_CPP98_STL
#else
// MSVC 2010 doesn't support C++11 aliases.
template <typename T> struct is_scalar : public std::is_scalar<T> {};
template <typename T, typename U> struct is_same : public std::is_same<T,U> {};
template <typename T> struct is_floating_point :
public std::is_floating_point<T> {};
template <typename T> struct is_unsigned : public std::is_unsigned<T> {};
#endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
#ifndef FLATBUFFERS_CPP98_STL
#if !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
template <class T> using unique_ptr = std::unique_ptr<T>;
#else
// MSVC 2010 doesn't support C++11 aliases.
// We're manually "aliasing" the class here as we want to bring unique_ptr
// into the flatbuffers namespace. We have unique_ptr in the flatbuffers
// namespace we have a completely independent implemenation (see below)
// for C++98 STL implementations.
template <class T> class unique_ptr : public std::unique_ptr<T> {
public:
unique_ptr() {}
explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {}
unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); }
unique_ptr(unique_ptr&& u) { *this = std::move(u); }
unique_ptr& operator=(std::unique_ptr<T>&& u) {
std::unique_ptr<T>::reset(u.release());
return *this;
}
unique_ptr& operator=(unique_ptr&& u) {
std::unique_ptr<T>::reset(u.release());
return *this;
}
unique_ptr& operator=(T* p) {
return std::unique_ptr<T>::operator=(p);
}
};
#endif // !(defined(_MSC_VER) && _MSC_VER <= 1700 /* MSVC2012 */)
#else
// Very limited implementation of unique_ptr.
// This is provided simply to allow the C++ code generated from the default
// settings to function in C++98 environments with no modifications.
template <class T> class unique_ptr {
public:
typedef T element_type;
unique_ptr() : ptr_(nullptr) {}
explicit unique_ptr(T* p) : ptr_(p) {}
unique_ptr(unique_ptr&& u) : ptr_(nullptr) { reset(u.release()); }
unique_ptr(const unique_ptr& u) : ptr_(nullptr) {
reset(const_cast<unique_ptr*>(&u)->release());
}
~unique_ptr() { reset(); }
unique_ptr& operator=(const unique_ptr& u) {
reset(const_cast<unique_ptr*>(&u)->release());
return *this;
}
unique_ptr& operator=(unique_ptr&& u) {
reset(u.release());
return *this;
}
unique_ptr& operator=(T* p) {
reset(p);
return *this;
}
const T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
T* get() const noexcept { return ptr_; }
explicit operator bool() const { return ptr_ != nullptr; }
// modifiers
T* release() {
T* value = ptr_;
ptr_ = nullptr;
return value;
}
void reset(T* p = nullptr) {
T* value = ptr_;
ptr_ = p;
if (value) delete value;
}
void swap(unique_ptr& u) {
T* temp_ptr = ptr_;
ptr_ = u.ptr_;
u.ptr_ = temp_ptr;
}
private:
T* ptr_;
};
template <class T> bool operator==(const unique_ptr<T>& x,
const unique_ptr<T>& y) {
return x.get() == y.get();
}
template <class T, class D> bool operator==(const unique_ptr<T>& x,
const D* y) {
return static_cast<D*>(x.get()) == y;
}
template <class T> bool operator==(const unique_ptr<T>& x, intptr_t y) {
return reinterpret_cast<intptr_t>(x.get()) == y;
}
#endif // !FLATBUFFERS_CPP98_STL
} // namespace flatbuffers
#endif // FLATBUFFERS_STL_EMULATION_H_

View File

@@ -40,7 +40,8 @@
#include <sys/types.h>
#include <sys/stat.h>
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/base.h"
namespace flatbuffers {
@@ -59,6 +60,20 @@ 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));
}
#if defined(FLATBUFFERS_CPP98_STL)
template <> inline std::string NumToString<long long>(long long t) {
char buf[21]; // (log((1 << 63) - 1) / log(10)) + 2
snprintf(buf, sizeof(buf), "%lld", t);
return std::string(buf);
}
template <> inline std::string NumToString<unsigned long long>(
unsigned long long t) {
char buf[22]; // (log((1 << 63) - 1) / log(10)) + 1
snprintf(buf, sizeof(buf), "%llu", t);
return std::string(buf);
}
#endif // defined(FLATBUFFERS_CPP98_STL)
// Special versions for floats/doubles.
template<> inline std::string NumToString<double>(double t) {
@@ -71,9 +86,8 @@ template<> inline std::string NumToString<double>(double t) {
// Sadly, std::fixed turns "1" into "1.00000", so here we undo that.
auto p = s.find_last_not_of('0');
if (p != std::string::npos) {
s.resize(p + 1); // Strip trailing zeroes.
if (s[s.size() - 1] == '.')
s.erase(s.size() - 1, 1); // Strip '.' if a whole number.
// Strip trailing zeroes. If it is a whole number, keep one zero.
s.resize(p + (s[p] == '.' ? 2 : 1));
}
return s;
}
@@ -157,16 +171,20 @@ inline bool SaveFile(const char *name, const std::string &buf, bool binary) {
return SaveFile(name, buf.c_str(), buf.size(), binary);
}
// Functionality for minimalistic portable path handling:
// Functionality for minimalistic portable path handling.
static const char kPosixPathSeparator = '/';
#ifdef _WIN32
static const char kPathSeparator = '\\';
// The functions below behave correctly regardless of whether posix ('/') or
// 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 ':'
#else
static const char kPathSeparator = kPosixPathSeparator;
static const char *PathSeparatorSet = "/";
#endif // _WIN32
// Returns the path with the extension, if any, removed.
inline std::string StripExtension(const std::string &filepath) {
@@ -197,13 +215,25 @@ inline std::string StripFileName(const std::string &filepath) {
inline std::string ConCatPathFileName(const std::string &path,
const std::string &filename) {
std::string filepath = path;
if (path.length() && path[path.size() - 1] != kPathSeparator &&
path[path.size() - 1] != kPosixPathSeparator)
filepath += kPathSeparator;
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;
return filepath;
}
// Replaces any '\\' separators with '/'
inline std::string PosixPath(const char *path) {
std::string p = path;
std::replace(p.begin(), p.end(), '\\', '/');
return p;
}
// This function ensure a directory exists, by recursively
// creating dirs for any parts of the path that don't exist yet.
inline void EnsureDirExists(const std::string &filepath) {
@@ -345,6 +375,72 @@ inline std::string WordWrap(const std::string in, size_t max_length,
return wrapped;
}
inline bool EscapeString(const char *s, size_t length, std::string *_text,
bool allow_non_utf8) {
std::string &text = *_text;
text += "\"";
for (uoffset_t i = 0; i < length; i++) {
char c = s[i];
switch (c) {
case '\n': text += "\\n"; break;
case '\t': text += "\\t"; break;
case '\r': text += "\\r"; break;
case '\b': text += "\\b"; break;
case '\f': text += "\\f"; break;
case '\"': text += "\\\""; break;
case '\\': text += "\\\\"; break;
default:
if (c >= ' ' && c <= '~') {
text += c;
} else {
// Not printable ASCII data. Let's see if it's valid UTF-8 first:
const char *utf8 = s + i;
int ucc = FromUTF8(&utf8);
if (ucc < 0) {
if (allow_non_utf8) {
text += "\\x";
text += IntToStringHex(static_cast<uint8_t>(c), 2);
} else {
// There are two cases here:
//
// 1) We reached here by parsing an IDL file. In that case,
// we previously checked for non-UTF-8, so we shouldn't reach
// here.
//
// 2) We reached here by someone calling GenerateText()
// on a previously-serialized flatbuffer. The data might have
// non-UTF-8 Strings, or might be corrupt.
//
// In both cases, we have to give up and inform the caller
// they have no JSON.
return false;
}
} else {
if (ucc <= 0xFFFF) {
// Parses as Unicode within JSON's \uXXXX range, so use that.
text += "\\u";
text += IntToStringHex(ucc, 4);
} else if (ucc <= 0x10FFFF) {
// Encode Unicode SMP values to a surrogate pair using two \u escapes.
uint32_t base = ucc - 0x10000;
auto high_surrogate = (base >> 10) + 0xD800;
auto low_surrogate = (base & 0x03FF) + 0xDC00;
text += "\\u";
text += IntToStringHex(high_surrogate, 4);
text += "\\u";
text += IntToStringHex(low_surrogate, 4);
}
// Skip past characters recognized.
i = static_cast<uoffset_t>(utf8 - s - 1);
}
}
break;
}
}
text += "\"";
return true;
}
} // namespace flatbuffers
#endif // FLATBUFFERS_UTIL_H_

View File

@@ -18,13 +18,13 @@ package com.google.flatbuffers;
import static com.google.flatbuffers.Constants.*;
import java.nio.CharBuffer;
import java.io.IOException;
import java.io.InputStream;
import java.nio.*;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.util.Arrays;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.charset.Charset;
/// @file
@@ -52,26 +52,51 @@ public class FlatBufferBuilder {
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
/// @endcond
/**
* Start with a buffer of size `initial_size`, then grow as required.
*
* @param initial_size The initial size of the internal buffer to use.
* @param bb_factory The factory to be used for allocating the internal buffer
*/
public FlatBufferBuilder(int initial_size, ByteBufferFactory bb_factory) {
if (initial_size <= 0) initial_size = 1;
space = initial_size;
this.bb_factory = bb_factory;
bb = bb_factory.newByteBuffer(initial_size);
}
/**
* Start with a buffer of size `initial_size`, then grow as required.
*
* @param initial_size The initial size of the internal buffer to use.
*/
public FlatBufferBuilder(int initial_size) {
if (initial_size <= 0) initial_size = 1;
space = initial_size;
bb = newByteBuffer(initial_size);
this(initial_size, new HeapByteBufferFactory());
}
/**
* Start with a buffer of 1KiB, then grow as required.
*/
/**
* Start with a buffer of 1KiB, then grow as required.
*/
public FlatBufferBuilder() {
this(1024);
}
/**
* Alternative constructor allowing reuse of {@link ByteBuffer}s. The builder
* can still grow the buffer as necessary. User classes should make sure
* to call {@link #dataBuffer()} to obtain the resulting encoded message.
*
* @param existing_bb The byte buffer to reuse.
* @param bb_factory The factory to be used for allocating a new internal buffer if
* the existing buffer needs to grow
*/
public FlatBufferBuilder(ByteBuffer existing_bb, ByteBufferFactory bb_factory) {
init(existing_bb, bb_factory);
}
/**
* Alternative constructor allowing reuse of {@link ByteBuffer}s. The builder
* can still grow the buffer as necessary. User classes should make sure
@@ -80,7 +105,7 @@ public class FlatBufferBuilder {
* @param existing_bb The byte buffer to reuse.
*/
public FlatBufferBuilder(ByteBuffer existing_bb) {
init(existing_bb);
init(existing_bb, new HeapByteBufferFactory());
}
/**
@@ -89,9 +114,12 @@ public class FlatBufferBuilder {
* objects that have been allocated for temporary storage.
*
* @param existing_bb The byte buffer to reuse.
* @param bb_factory The factory to be used for allocating a new internal buffer if
* the existing buffer needs to grow
* @return Returns `this`.
*/
public FlatBufferBuilder init(ByteBuffer existing_bb){
public FlatBufferBuilder init(ByteBuffer existing_bb, ByteBufferFactory bb_factory){
this.bb_factory = bb_factory;
bb = existing_bb;
bb.clear();
bb.order(ByteOrder.LITTLE_ENDIAN);
@@ -106,17 +134,53 @@ public class FlatBufferBuilder {
return this;
}
/// @cond FLATBUFFERS_INTERNAL
/**
* Create a `ByteBuffer` with a given capacity.
* An interface that provides a user of the FlatBufferBuilder class the ability to specify
* the method in which the internal buffer gets allocated. This allows for alternatives
* to the default behavior, which is to allocate memory for a new byte-array
* backed `ByteBuffer` array inside the JVM.
*
* @param capacity The size of the `ByteBuffer` to allocate.
* @return Returns the new `ByteBuffer` that was allocated.
* The FlatBufferBuilder class contains the HeapByteBufferFactory class to
* preserve the default behavior in the event that the user does not provide
* their own implementation of this interface.
*/
static ByteBuffer newByteBuffer(int capacity) {
ByteBuffer newbb = ByteBuffer.allocate(capacity);
newbb.order(ByteOrder.LITTLE_ENDIAN);
return newbb;
public interface ByteBufferFactory {
/**
* Create a `ByteBuffer` with a given capacity.
*
* @param capacity The size of the `ByteBuffer` to allocate.
* @return Returns the new `ByteBuffer` that was allocated.
*/
ByteBuffer newByteBuffer(int capacity);
}
/**
* An implementation of the ByteBufferFactory interface that is used when
* one is not provided by the user.
*
* Allocate memory for a new byte-array backed `ByteBuffer` array inside the JVM.
*/
public static final class HeapByteBufferFactory implements ByteBufferFactory {
@Override
public ByteBuffer newByteBuffer(int capacity) {
return ByteBuffer.allocate(capacity).order(ByteOrder.LITTLE_ENDIAN);
}
}
/**
* Reset the FlatBufferBuilder by purging all data that it holds.
*/
public void clear(){
space = bb.capacity();
bb.clear();
minalign = 1;
while(vtable_in_use > 0) vtable[--vtable_in_use] = 0;
vtable_in_use = 0;
nested = false;
finished = false;
object_start = 0;
num_vtables = 0;
vector_num_elems = 0;
}
/**
@@ -124,16 +188,17 @@ public class FlatBufferBuilder {
* end of the new buffer (since we build the buffer backwards).
*
* @param bb The current buffer with the existing data.
* @param bb_factory The factory to be used for allocating the new internal buffer
* @return A new byte buffer with the old data copied copied to it. The data is
* located at the end of the buffer.
*/
static ByteBuffer growByteBuffer(ByteBuffer bb) {
static ByteBuffer growByteBuffer(ByteBuffer bb, ByteBufferFactory bb_factory) {
int old_buf_size = bb.capacity();
if ((old_buf_size & 0xC0000000) != 0) // Ensure we don't grow beyond what fits in an int.
throw new AssertionError("FlatBuffers: cannot grow buffer beyond 2 gigabytes.");
int new_buf_size = old_buf_size << 1;
bb.position(0);
ByteBuffer nbb = newByteBuffer(new_buf_size);
ByteBuffer nbb = bb_factory.newByteBuffer(new_buf_size);
nbb.position(new_buf_size - old_buf_size);
nbb.put(bb);
return nbb;
@@ -176,7 +241,7 @@ public class FlatBufferBuilder {
// Reallocate the buffer if needed.
while (space < align_size + size + additional_bytes) {
int old_buf_size = bb.capacity();
bb = growByteBuffer(bb);
bb = growByteBuffer(bb, bb_factory);
space += bb.capacity() - old_buf_size;
}
pad(align_size);
@@ -413,7 +478,7 @@ public class FlatBufferBuilder {
obj.sortTables(offsets, bb);
return createVectorOfTables(offsets);
}
/**
* Encode the string `s` in the buffer using UTF-8. If {@code s} is
* already a {@link CharBuffer}, this method is allocation free.
@@ -679,7 +744,11 @@ public class FlatBufferBuilder {
addInt(0);
int vtableloc = offset();
// Write out the current vtable.
for (int i = vtable_in_use - 1; i >= 0 ; i--) {
int i = vtable_in_use - 1;
// Trim trailing zeroes.
for (; i >= 0 && vtable[i] == 0; i--) {}
int trimmed_size = i + 1;
for (; i >= 0 ; i--) {
// Offset relative to the start of the table.
short off = (short)(vtable[i] != 0 ? vtableloc - vtable[i] : 0);
addShort(off);
@@ -687,12 +756,12 @@ public class FlatBufferBuilder {
final int standard_fields = 2; // The fields below:
addShort((short)(vtableloc - object_start));
addShort((short)((vtable_in_use + standard_fields) * SIZEOF_SHORT));
addShort((short)((trimmed_size + standard_fields) * SIZEOF_SHORT));
// Search for an existing vtable that matches the current one.
int existing_vtable = 0;
outer_loop:
for (int i = 0; i < num_vtables; i++) {
for (i = 0; i < num_vtables; i++) {
int vt1 = bb.capacity() - vtables[i];
int vt2 = space;
short len = bb.getShort(vt1);
@@ -837,6 +906,41 @@ public class FlatBufferBuilder {
public byte[] sizedByteArray() {
return sizedByteArray(space, bb.capacity() - space);
}
/**
* A utility function to return an InputStream to the ByteBuffer data
*
* @return An InputStream that starts at the beginning of the ByteBuffer data
* and can read to the end of it.
*/
public InputStream sizedInputStream() {
finished();
ByteBuffer duplicate = bb.duplicate();
duplicate.position(space);
duplicate.limit(bb.capacity());
return new ByteBufferBackedInputStream(duplicate);
}
/**
* A class that allows a user to create an InputStream from a ByteBuffer.
*/
static class ByteBufferBackedInputStream extends InputStream {
ByteBuffer buf;
public ByteBufferBackedInputStream(ByteBuffer buf) {
this.buf = buf;
}
public int read() throws IOException {
try {
return buf.get() & 0xFF;
} catch(BufferUnderflowException e) {
return -1;
}
}
}
}
/// @}

View File

@@ -68,7 +68,7 @@ public class Table {
}
protected static int __offset(int vtable_offset, int offset, ByteBuffer bb) {
int vtable = bb.array().length - offset;
int vtable = bb.capacity() - offset;
return bb.getShort(vtable + vtable_offset - bb.getInt(vtable)) + vtable;
}
@@ -245,10 +245,9 @@ public class Table {
int startPos_1 = offset_1 + SIZEOF_INT;
int startPos_2 = offset_2 + SIZEOF_INT;
int len = Math.min(len_1, len_2);
byte[] bbArray = bb.array();
for(int i = 0; i < len; i++) {
if (bbArray[i + startPos_1] != bbArray[i + startPos_2])
return bbArray[i + startPos_1] - bbArray[i + startPos_2];
if (bb.get(i + startPos_1) != bb.get(i + startPos_2))
return bb.get(i + startPos_1) - bb.get(i + startPos_2);
}
return len_1 - len_2;
}
@@ -266,10 +265,9 @@ public class Table {
int len_2 = key.length;
int startPos_1 = offset_1 + Constants.SIZEOF_INT;
int len = Math.min(len_1, len_2);
byte[] bbArray = bb.array();
for (int i = 0; i < len; i++) {
if (bbArray[i + startPos_1] != key[i])
return bbArray[i + startPos_1] - key[i];
if (bb.get(i + startPos_1) != key[i])
return bb.get(i + startPos_1) - key[i];
}
return len_1 - len_2;
}

View File

@@ -115,7 +115,7 @@ flatbuffers.Long.create = function(low, high) {
* @returns {number}
*/
flatbuffers.Long.prototype.toFloat64 = function() {
return this.low + this.high * 0x100000000;
return (this.low >>> 0) + this.high * 0x100000000;
};
/**
@@ -604,23 +604,28 @@ flatbuffers.Builder.prototype.endObject = function() {
this.addInt32(0);
var vtableloc = this.offset();
// Trim trailing zeroes.
var i = this.vtable_in_use - 1;
for (; i >= 0 && this.vtable[i] == 0; i--) {}
var trimmed_size = i + 1;
// Write out the current vtable.
for (var i = this.vtable_in_use - 1; i >= 0; i--) {
for (; i >= 0; i--) {
// Offset relative to the start of the table.
this.addInt16(this.vtable[i] != 0 ? vtableloc - this.vtable[i] : 0);
}
var standard_fields = 2; // The fields below:
this.addInt16(vtableloc - this.object_start);
this.addInt16((this.vtable_in_use + standard_fields) * flatbuffers.SIZEOF_SHORT);
var len = (trimmed_size + standard_fields) * flatbuffers.SIZEOF_SHORT;
this.addInt16(len);
// Search for an existing vtable that matches the current one.
var existing_vtable = 0;
var vt1 = this.space;
outer_loop:
for (var i = 0; i < this.vtables.length; i++) {
var vt1 = this.bb.capacity() - this.vtables[i];
var vt2 = this.space;
var len = this.bb.readInt16(vt1);
for (i = 0; i < this.vtables.length; i++) {
var vt2 = this.bb.capacity() - this.vtables[i];
if (len == this.bb.readInt16(vt2)) {
for (var j = flatbuffers.SIZEOF_SHORT; j < len; j += flatbuffers.SIZEOF_SHORT) {
if (this.bb.readInt16(vt1 + j) != this.bb.readInt16(vt2 + j)) {
@@ -944,9 +949,17 @@ flatbuffers.ByteBuffer.prototype.readFloat64 = function(offset) {
/**
* @param {number} offset
* @param {number} value
* @param {number|boolean} value
*/
flatbuffers.ByteBuffer.prototype.writeInt8 = function(offset, value) {
this.bytes_[offset] = /** @type {number} */(value);
};
/**
* @param {number} offset
* @param {number} value
*/
flatbuffers.ByteBuffer.prototype.writeUint8 = function(offset, value) {
this.bytes_[offset] = value;
};
@@ -959,6 +972,15 @@ flatbuffers.ByteBuffer.prototype.writeInt16 = function(offset, value) {
this.bytes_[offset + 1] = value >> 8;
};
/**
* @param {number} offset
* @param {number} value
*/
flatbuffers.ByteBuffer.prototype.writeUint16 = function(offset, value) {
this.bytes_[offset] = value;
this.bytes_[offset + 1] = value >> 8;
};
/**
* @param {number} offset
* @param {number} value
@@ -970,6 +992,17 @@ flatbuffers.ByteBuffer.prototype.writeInt32 = function(offset, value) {
this.bytes_[offset + 3] = value >> 24;
};
/**
* @param {number} offset
* @param {number} value
*/
flatbuffers.ByteBuffer.prototype.writeUint32 = function(offset, value) {
this.bytes_[offset] = value;
this.bytes_[offset + 1] = value >> 8;
this.bytes_[offset + 2] = value >> 16;
this.bytes_[offset + 3] = value >> 24;
};
/**
* @param {number} offset
* @param {flatbuffers.Long} value
@@ -979,6 +1012,15 @@ flatbuffers.ByteBuffer.prototype.writeInt64 = function(offset, value) {
this.writeInt32(offset + 4, value.high);
};
/**
* @param {number} offset
* @param {flatbuffers.Long} value
*/
flatbuffers.ByteBuffer.prototype.writeUint64 = function(offset, value) {
this.writeUint32(offset, value.low);
this.writeUint32(offset + 4, value.high);
};
/**
* @param {number} offset
* @param {number} value

0
net/FlatBuffers/ByteBuffer.cs Executable file → Normal file
View File

View File

@@ -500,7 +500,11 @@ namespace FlatBuffers
AddInt((int)0);
var vtableloc = Offset;
// Write out the current vtable.
for (int i = _vtableSize - 1; i >= 0 ; i--) {
int i = _vtableSize - 1;
// Trim trailing zeroes.
for (; i >= 0 && _vtable[i] == 0; i--) {}
int trimmedSize = i + 1;
for (; i >= 0 ; i--) {
// Offset relative to the start of the table.
short off = (short)(_vtable[i] != 0
? vtableloc - _vtable[i]
@@ -513,12 +517,12 @@ namespace FlatBuffers
const int standardFields = 2; // The fields below:
AddShort((short)(vtableloc - _objectStart));
AddShort((short)((_vtableSize + standardFields) *
AddShort((short)((trimmedSize + standardFields) *
sizeof(short)));
// Search for an existing vtable that matches the current one.
int existingVtable = 0;
for (int i = 0; i < _numVtables; i++) {
for (i = 0; i < _numVtables; i++) {
int vt1 = _bb.Length - _vtables[i];
int vt2 = _space;
short len = _bb.GetShort(vt1);

View File

@@ -1,6 +1,6 @@
{
"name": "flatbuffers",
"version": "1.6.0",
"version": "1.8.0",
"description": "Memory Efficient Serialization Library",
"files": ["js/flatbuffers.js"],
"main": "js/flatbuffers.js",

View File

@@ -596,7 +596,7 @@ class FlatbufferBuilder
if (function_exists('mb_detect_encoding')) {
return (bool) mb_detect_encoding($bytes, 'UTF-8', true);
}
$len = strlen($bytes);
if ($len < 1) {
/* NOTE: always return 1 when passed string is null */
@@ -812,14 +812,18 @@ class FlatbufferBuilder
$this->addInt(0);
$vtableloc = $this->offset();
for ($i = $this->vtable_in_use -1; $i >= 0; $i--) {
$i = $this->vtable_in_use -1;
// Trim trailing zeroes.
for (; $i >= 0 && $this->vtable[$i] == 0; $i--) {}
$trimmed_size = $i + 1;
for (; $i >= 0; $i--) {
$off = ($this->vtable[$i] != 0) ? $vtableloc - $this->vtable[$i] : 0;
$this->addShort($off);
}
$standard_fields = 2; // the fields below
$this->addShort($vtableloc - $this->object_start);
$this->addShort(($this->vtable_in_use + $standard_fields) * Constants::SIZEOF_SHORT);
$this->addShort(($trimmed_size + $standard_fields) * Constants::SIZEOF_SHORT);
// search for an existing vtable that matches the current one.
$existing_vtable = 0;

View File

@@ -28,4 +28,14 @@ abstract class Struct
* @var ByteBuffer $bb
*/
protected $bb;
public function setByteBufferPos($pos)
{
$this->bb_pos = $pos;
}
public function setByteBuffer($bb)
{
$this->bb = $bb;
}
}

View File

@@ -32,6 +32,16 @@ abstract class Table
{
}
public function setByteBufferPos($pos)
{
$this->bb_pos = $pos;
}
public function setByteBuffer($bb)
{
$this->bb = $bb;
}
/**
* returns actual vtable offset
*
@@ -107,8 +117,8 @@ abstract class Table
protected function __union($table, $offset)
{
$offset += $this->bb_pos;
$table->bb_pos = $offset + $this->bb->getInt($offset);
$table->bb = $this->bb;
$table->setByteBufferPos($offset + $this->bb->getInt($offset));
$table->setByteBuffer($this->bb);
return $table;
}

51
pom.xml
View File

@@ -5,17 +5,20 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-java</artifactId>
<version>1.6.0-SNAPSHOT</version>
<version>1.8.0</version>
<packaging>bundle</packaging>
<name>FlatBuffers Java API</name>
<description>
Memory Efficient Serialization Library
</description>
<developers>
<developer>
<name>Wouter van Oortmerssen</name>
</developer>
</developers>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<url>https://github.com/google/flatbuffers</url>
<licenses>
<license>
@@ -32,6 +35,12 @@
</scm>
<dependencies>
</dependencies>
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
<build>
<sourceDirectory>java</sourceDirectory>
<plugins>
@@ -84,6 +93,42 @@
<version>3.0.1</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.7</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
<configuration>
<autoVersionSubmodules>true</autoVersionSubmodules>
<useReleaseProfile>false</useReleaseProfile>
<releaseProfiles>release</releaseProfiles>
<goals>deploy</goals>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -193,6 +193,10 @@ class Builder(object):
objectOffset = self.Offset()
existingVtable = None
# Trim trailing 0 offsets.
while self.current_vtable and self.current_vtable[-1] == 0:
self.current_vtable.pop()
# Search backwards through existing vtables, because similar vtables
# are likely to have been recently appended. See
# BenchmarkVtableDeduplication for a case in which this heuristic
@@ -417,6 +421,27 @@ class Builder(object):
return self.EndVector(len(x))
def CreateByteVector(self, x):
"""CreateString writes a byte vector."""
self.assertNotNested()
## @cond FLATBUFFERS_INTERNAL
self.nested = True
## @endcond
if not isinstance(x, compat.binary_types):
raise TypeError("non-byte vector passed to CreateByteVector")
self.Prep(N.UOffsetTFlags.bytewidth, len(x)*N.Uint8Flags.bytewidth)
l = UOffsetTFlags.py_type(len(x))
## @cond FLATBUFFERS_INTERNAL
self.head = UOffsetTFlags.py_type(self.Head() - l)
## @endcond
self.Bytes[self.Head():self.Head()+l] = x
return self.EndVector(len(x))
## @cond FLATBUFFERS_INTERNAL
def assertNested(self):
"""

View File

@@ -12,9 +12,11 @@
# See the License for the specific language governing permissions and
# limitations under the License.
""" A tiny version of `six` to help with backwards compability. """
""" A tiny version of `six` to help with backwards compability. Also includes
compatibility helpers for numpy. """
import sys
import imp
PY2 = sys.version_info[0] == 2
PY26 = sys.version_info[0:2] == (2, 6)
@@ -43,4 +45,37 @@ else:
memoryview_type = memoryview
struct_bool_decl = "?"
# Helper functions to facilitate making numpy optional instead of required
def import_numpy():
"""
Returns the numpy module if it exists on the system,
otherwise returns None.
"""
try:
imp.find_module('numpy')
numpy_exists = True
except ImportError:
numpy_exists = False
if numpy_exists:
# We do this outside of try/except block in case numpy exists
# but is not installed correctly. We do not want to catch an
# incorrect installation which would manifest as an
# ImportError.
import numpy as np
else:
np = None
return np
class NumpyRequiredForThisFeature(RuntimeError):
"""
Error raised when user tries to use a feature that
requires numpy without having numpy installed.
"""
pass
# NOTE: Future Jython support may require code here (look at `six`).

View File

@@ -15,13 +15,26 @@
from . import number_types as N
from . import packer
from .compat import memoryview_type
from .compat import import_numpy, NumpyRequiredForThisFeature
np = import_numpy()
def Get(packer_type, buf, head):
""" Get decodes a value at buf[head:] using `packer_type`. """
""" Get decodes a value at buf[head] using `packer_type`. """
return packer_type.unpack_from(memoryview_type(buf), head)[0]
def GetVectorAsNumpy(numpy_type, buf, count, offset):
""" GetVecAsNumpy decodes values starting at buf[head] as
`numpy_type`, where `numpy_type` is a numpy dtype. """
if np is not None:
# TODO: could set .flags.writeable = False to make users jump through
# hoops before modifying...
return np.frombuffer(buf, dtype=numpy_type, count=count, offset=offset)
else:
raise NumpyRequiredForThisFeature('Numpy was not found.')
def Write(packer_type, buf, head, n):
""" Write encodes `n` at buf[head:] using `packer_type`. """
""" Write encodes `n` at buf[head] using `packer_type`. """
packer_type.pack_into(buf, head, n)

View File

@@ -16,7 +16,9 @@ import collections
import struct
from . import packer
from .compat import import_numpy, NumpyRequiredForThisFeature
np = import_numpy()
# For reference, see:
# https://docs.python.org/2/library/ctypes.html#ctypes-fundamental-data-types-2
@@ -170,3 +172,10 @@ def uint64_to_float64(n):
packed = struct.pack("<1Q", n)
(unpacked,) = struct.unpack("<1d", packed)
return unpacked
def to_numpy_type(number_type):
if np is not None:
return np.dtype(number_type.name).newbyteorder('<')
else:
raise NumpyRequiredForThisFeature('Numpy was not found.')

View File

@@ -101,6 +101,18 @@ class Table(object):
return d
return self.Get(validator_flags, self.Pos + off)
def GetVectorAsNumpy(self, flags, off):
"""
GetVectorAsNumpy returns the vector that starts at `Vector(off)`
as a numpy array with the type specified by `flags`. The array is
a `view` into Bytes, so modifying the returned array will
modify Bytes in place.
"""
offset = self.Vector(off)
length = self.VectorLen(off) # TODO: length accounts for bytewidth, right?
numpy_dtype = N.to_numpy_type(flags)
return encode.GetVectorAsNumpy(numpy_dtype, self.Bytes, length, offset)
def GetVOffsetTSlot(self, slot, d):
"""
GetVOffsetTSlot retrieves the VOffsetT that the given vtable location

2
readme.md Executable file → Normal file
View File

@@ -54,6 +54,6 @@ you would leave it in.
[`flatbuffers` tag]: https://stackoverflow.com/questions/tagged/flatbuffers
[FlatBuffers Google Group]: https://groups.google.com/forum/#!forum/flatbuffers
[FlatBuffers Issues Tracker]: http://github.com/google/flatbuffers/issues
[stackoverflow.com]: http://www.stackoverflow.com
[stackoverflow.com]: http://stackoverflow.com/search?q=flatbuffers
[landing page]: http://google.github.io/flatbuffers
[LICENSE]: https://github.com/google/flatbuffers/blob/master/LICENSE.txt

View File

@@ -42,7 +42,8 @@ table KeyValue {
table EnumVal {
name:string (required);
value:long (key);
object:Object; // Only if part of a union.
object:Object; // Will be deprecated in favor of union_type in the future.
union_type:Type;
}
table Enum {

View File

@@ -81,22 +81,19 @@ class SampleBinary
Assert(monster.Color == Color.Red, "monster.Color", Convert.ToString(monster.Color),
Convert.ToString(Color.Red));
// C# also allows you to use performance-enhanced methods to fill an object that has already
// been created. These functions are prefixed with "Get". For example: `monster.GetPos()`.
var myAlreadyCreatedVector = new Vec3();
monster.GetPos(myAlreadyCreatedVector); // Instead of `var myNewVec3 = monster.Pos`.
Assert(myAlreadyCreatedVector.X == 1.0f, "myAlreadyCreatedVector.X",
Convert.ToString(myAlreadyCreatedVector.X), Convert.ToString(1.0f));
Assert(myAlreadyCreatedVector.Y == 2.0f, "myAlreadyCreatedVector.Y",
Convert.ToString(myAlreadyCreatedVector.Y), Convert.ToString(2.0f));
Assert(myAlreadyCreatedVector.Z == 3.0f, "myAlreadyCreatedVector.Z",
Convert.ToString(myAlreadyCreatedVector.Z), Convert.ToString(3.0f));
var vec = monster.Pos.Value;
Assert(vec.X == 1.0f, "vec.X",
Convert.ToString(vec.X), Convert.ToString(1.0f));
Assert(vec.Y == 2.0f, "vec.Y",
Convert.ToString(vec.Y), Convert.ToString(2.0f));
Assert(vec.Z == 3.0f, "vec.Z",
Convert.ToString(vec.Z), Convert.ToString(3.0f));
// Get and test the `Inventory` FlatBuffer `vector`.
for (int i = 0; i < monster.InventoryLength; i++)
{
Assert(monster.GetInventory(i) == i, "monster.GetInventory",
Convert.ToString(monster.GetInventory(i)), Convert.ToString(i));
Assert(monster.Inventory(i) == i, "monster.Inventory",
Convert.ToString(monster.Inventory(i)), Convert.ToString(i));
}
// Get and test the `Weapons` FlatBuffer `vector` of `table`s.
@@ -104,17 +101,17 @@ class SampleBinary
var expectedWeaponDamages = new short[] {3, 5};
for (int i = 0; i < monster.WeaponsLength; i++)
{
Assert(monster.GetWeapons(i).Name.Equals(expectedWeaponNames[i], StringComparison.Ordinal),
"monster.GetWeapons", monster.GetWeapons(i).Name, expectedWeaponNames[i]);
Assert(monster.GetWeapons(i).Damage == expectedWeaponDamages[i], "monster.GetWeapons",
Convert.ToString(monster.GetWeapons(i).Damage),
Assert(monster.Weapons(i).Value.Name.Equals(expectedWeaponNames[i], StringComparison.Ordinal),
"monster.Weapons", monster.Weapons(i).Value.Name, expectedWeaponNames[i]);
Assert(monster.Weapons(i).Value.Damage == expectedWeaponDamages[i], "monster.GetWeapons",
Convert.ToString(monster.Weapons(i).Value.Damage),
Convert.ToString(expectedWeaponDamages[i]));
}
// Get and test the `Equipped` FlatBuffer `union`.
Assert(monster.EquippedType == Equipment.Weapon, "monster.EquippedType",
Convert.ToString(monster.EquippedType), Convert.ToString(Equipment.Weapon));
var equipped = (Weapon)monster.GetEquipped(new Weapon());
var equipped = monster.Equipped<Weapon>().Value;
Assert(equipped.Name.Equals("Axe", StringComparison.Ordinal), "equipped.Name", equipped.Name,
"Axe");
Assert(equipped.Damage == 5, "equipped.Damage", Convert.ToString(equipped.Damage),

11
samples/android/AndroidManifest.xml Executable file → Normal file
View File

@@ -17,17 +17,14 @@
-->
<!-- BEGIN_INCLUDE(manifest) -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.samples.FlatBufferSample"
android:versionCode="1"
android:versionName="1.0">
package="com.samples.FlatBufferSample">
<uses-feature android:glEsVersion="0x00020000"></uses-feature>
<!-- This is the platform API where NativeActivity was introduced. -->
<uses-sdk android:minSdkVersion="9" />
<!-- This .apk has no Java code itself, so set hasCode to false. -->
<application android:label="@string/app_name" android:hasCode="false">
<application android:label="@string/app_name"
android:hasCode="false"
android:allowBackup="false">
<!-- Our activity is the built-in NativeActivity framework class.
This will take care of integrating with our NDK code. -->
<activity android:name="android.app.NativeActivity"

View File

@@ -0,0 +1,108 @@
// Copyright (c) 2017 Google, Inc.
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
}
}
allprojects {
repositories {
jcenter()
}
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion '25.0.2'
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
res.srcDirs = ['res']
}
}
externalNativeBuild {
ndkBuild {
path "jni/Android.mk"
}
}
defaultConfig {
applicationId 'com.samples.FlatBufferSample'
// This is the platform API where NativeActivity was introduced.
minSdkVersion 9
targetSdkVersion 25
versionCode 1
versionName "1.0"
buildTypes {
release {
minifyEnabled false
}
}
externalNativeBuild {
ndkBuild {
targets "FlatBufferSample"
arguments "-j" + Runtime.getRuntime().availableProcessors()
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
}
}
}
lintOptions {
abortOnError false
}
// Build with each STL variant.
productFlavors {
stlport {
applicationIdSuffix ".stlport"
versionNameSuffix "-stlport"
externalNativeBuild {
ndkBuild {
arguments "APP_STL=stlport_static"
}
}
}
gnustl {
applicationIdSuffix ".gnustl"
versionNameSuffix "-gnustl"
externalNativeBuild {
ndkBuild {
arguments "APP_STL=gnustl_static"
}
}
}
libcpp {
applicationIdSuffix ".libcpp"
versionNameSuffix "-libcpp"
externalNativeBuild {
ndkBuild {
arguments "APP_STL=c++_static"
}
}
}
}
}

View File

@@ -1,511 +0,0 @@
#!/bin/bash -eu
#
# Copyright (c) 2013 Google, Inc.
#
# This software is provided 'as-is', without any express or implied
# warranty. In no event will the authors be held liable for any damages
# arising from the use of this software.
# Permission is granted to anyone to use this software for any purpose,
# including commercial applications, and to alter it and redistribute it
# freely, subject to the following restrictions:
# 1. The origin of this software must not be misrepresented; you must not
# claim that you wrote the original software. If you use this software
# in a product, an acknowledgment in the product documentation would be
# appreciated but is not required.
# 2. Altered source versions must be plainly marked as such, and must not be
# misrepresented as being the original software.
# 3. This notice may not be removed or altered from any source distribution.
#
# Build, deploy, debug / execute a native Android package based upon
# NativeActivity.
declare -r script_directory=$(dirname $0)
declare -r android_root=${script_directory}/../../../../../../
declare -r script_name=$(basename $0)
declare -r android_manifest=AndroidManifest.xml
declare -r os_name=$(uname -s)
# Minimum Android target version supported by this project.
: ${BUILDAPK_ANDROID_TARGET_MINVERSION:=10}
# Directory containing the Android SDK
# (http://developer.android.com/sdk/index.html).
: ${ANDROID_SDK_HOME:=}
# Directory containing the Android NDK
# (http://developer.android.com/tools/sdk/ndk/index.html).
: ${NDK_HOME:=}
# Display script help and exit.
usage() {
echo "
Build the Android package in the current directory and deploy it to a
connected device.
Usage: ${script_name} \\
[ADB_DEVICE=serial_number] [BUILD=0] [DEPLOY=0] [RUN_DEBUGGER=1] \
[LAUNCH=0] [SWIG_BIN=swig_binary_directory] [SWIG_LIB=swig_include_directory] [ndk-build arguments ...]
ADB_DEVICE=serial_number:
serial_number specifies the device to deploy the built apk to if multiple
Android devices are connected to the host.
BUILD=0:
Disables the build of the package.
DEPLOY=0:
Disables the deployment of the built apk to the Android device.
RUN_DEBUGGER=1:
Launches the application in gdb after it has been deployed. To debug in
gdb, NDK_DEBUG=1 must also be specified on the command line to build a
debug apk.
LAUNCH=0:
Disable the launch of the apk on the Android device.
SWIG_BIN=swig_binary_directory:
The directory where the SWIG binary lives. No need to set this if SWIG is
installed and point to from your PATH variable.
SWIG_LIB=swig_include_directory:
The directory where SWIG shared include files are, usually obtainable from
commandline with \"swig -swiglib\". No need to set this if SWIG is installed
and point to from your PATH variable.
ndk-build arguments...:
Additional arguments for ndk-build. See ndk-build -h for more information.
" >&2
exit 1
}
# Get the number of CPU cores present on the host.
get_number_of_cores() {
case ${os_name} in
Darwin)
sysctl hw.ncpu | awk '{ print $2 }'
;;
CYGWIN*|Linux)
awk '/^processor/ { n=$3 } END { print n + 1 }' /proc/cpuinfo
;;
*)
echo 1
;;
esac
}
# Get the package name from an AndroidManifest.xml file.
get_package_name_from_manifest() {
xmllint --xpath 'string(/manifest/@package)' "${1}"
}
# Get the library name from an AndroidManifest.xml file.
get_library_name_from_manifest() {
echo "\
setns android=http://schemas.android.com/apk/res/android
xpath string(/manifest/application/activity\
[@android:name=\"android.app.NativeActivity\"]/meta-data\
[@android:name=\"android.app.lib_name\"]/@android:value)" |
xmllint --shell "${1}" | awk '/Object is a string/ { print $NF }'
}
# Get the number of Android devices connected to the system.
get_number_of_devices_connected() {
adb devices -l | \
awk '/^..*$/ { if (p) { print $0 } }
/List of devices attached/ { p = 1 }' | \
wc -l
return ${PIPESTATUS[0]}
}
# Kill a process and its' children. This is provided for cygwin which
# doesn't ship with pkill.
kill_process_group() {
local parent_pid="${1}"
local child_pid=
for child_pid in $(ps -f | \
awk '{ if ($3 == '"${parent_pid}"') { print $2 } }'); do
kill_process_group "${child_pid}"
done
kill "${parent_pid}" 2>/dev/null
}
# Find and run "adb".
adb() {
local adb_path=
for path in "$(which adb 2>/dev/null)" \
"${ANDROID_SDK_HOME}/sdk/platform-tools/adb" \
"${android_root}/prebuilts/sdk/platform-tools/adb"; do
if [[ -e "${path}" ]]; then
adb_path="${path}"
break
fi
done
if [[ "${adb_path}" == "" ]]; then
echo -e "Unable to find adb." \
"\nAdd the Android ADT sdk/platform-tools directory to the" \
"PATH." >&2
exit 1
fi
"${adb_path}" "$@"
}
# Find and run "android".
android() {
local android_executable=android
if echo "${os_name}" | grep -q CYGWIN; then
android_executable=android.bat
fi
local android_path=
for path in "$(which ${android_executable})" \
"${ANDROID_SDK_HOME}/sdk/tools/${android_executable}" \
"${android_root}/prebuilts/sdk/tools/${android_executable}"; do
if [[ -e "${path}" ]]; then
android_path="${path}"
break
fi
done
if [[ "${android_path}" == "" ]]; then
echo -e "Unable to find android tool." \
"\nAdd the Android ADT sdk/tools directory to the PATH." >&2
exit 1
fi
# Make sure ant is installed.
if [[ "$(which ant)" == "" ]]; then
echo -e "Unable to find ant." \
"\nPlease install ant and add to the PATH." >&2
exit 1
fi
"${android_path}" "$@"
}
# Find and run "ndk-build"
ndkbuild() {
local ndkbuild_path=
for path in "$(which ndk-build 2>/dev/null)" \
"${NDK_HOME}/ndk-build" \
"${android_root}/prebuilts/ndk/current/ndk-build"; do
if [[ -e "${path}" ]]; then
ndkbuild_path="${path}"
break
fi
done
if [[ "${ndkbuild_path}" == "" ]]; then
echo -e "Unable to find ndk-build." \
"\nAdd the Android NDK directory to the PATH." >&2
exit 1
fi
"${ndkbuild_path}" "$@"
}
# Get file modification time of $1 in seconds since the epoch.
stat_mtime() {
local filename="${1}"
case ${os_name} in
Darwin) stat -f%m "${filename}" 2>/dev/null || echo 0 ;;
*) stat -c%Y "${filename}" 2>/dev/null || echo 0 ;;
esac
}
# Build the native (C/C++) build targets in the current directory.
build_native_targets() {
# Save the list of output modules in the install directory so that it's
# possible to restore their timestamps after the build is complete. This
# works around a bug in ndk/build/core/setup-app.mk which results in the
# unconditional execution of the clean-installed-binaries rule.
restore_libraries="$(find libs -type f 2>/dev/null | \
sed -E 's@^libs/(.*)@\1@')"
# Build native code.
ndkbuild -j$(get_number_of_cores) "$@"
# Restore installed libraries.
# Obviously this is a nasty hack (along with ${restore_libraries} above) as
# it assumes it knows where the NDK will be placing output files.
(
IFS=$'\n'
for libpath in ${restore_libraries}; do
source_library="obj/local/${libpath}"
target_library="libs/${libpath}"
if [[ -e "${source_library}" ]]; then
cp -a "${source_library}" "${target_library}"
fi
done
)
}
# Select the oldest installed android build target that is at least as new as
# BUILDAPK_ANDROID_TARGET_MINVERSION. If a suitable build target isn't found,
# this function prints an error message and exits with an error.
select_android_build_target() {
local -r android_targets_installed=$( \
android list targets | \
awk -F'"' '/^id:.*android/ { print $2 }')
local android_build_target=
for android_target in $(echo "${android_targets_installed}" | \
awk -F- '{ print $2 }' | sort -n); do
local isNumber='^[0-9]+$'
# skip preview API releases e.g. 'android-L'
if [[ $android_target =~ $isNumber ]]; then
if [[ $((android_target)) -ge \
$((BUILDAPK_ANDROID_TARGET_MINVERSION)) ]]; then
android_build_target="android-${android_target}"
break
fi
# else
# The API version is a letter, so skip it.
fi
done
if [[ "${android_build_target}" == "" ]]; then
echo -e \
"Found installed Android targets:" \
"$(echo ${android_targets_installed} | sed 's/ /\n /g;s/^/\n /;')" \
"\nAndroid SDK platform" \
"android-$((BUILDAPK_ANDROID_TARGET_MINVERSION))" \
"must be installed to build this project." \
"\nUse the \"android\" application to install API" \
"$((BUILDAPK_ANDROID_TARGET_MINVERSION)) or newer." >&2
exit 1
fi
echo "${android_build_target}"
}
# Sign unsigned apk $1 and write the result to $2 with key store file $3 and
# password $4.
# If a key store file $3 and password $4 aren't specified, a temporary
# (60 day) key is generated and used to sign the package.
sign_apk() {
local unsigned_apk="${1}"
local signed_apk="${2}"
if [[ $(stat_mtime "${unsigned_apk}") -gt \
$(stat_mtime "${signed_apk}") ]]; then
local -r key_alias=$(basename ${signed_apk} .apk)
local keystore="${3}"
local key_password="${4}"
[[ "${keystore}" == "" ]] && keystore="${unsigned_apk}.keystore"
[[ "${key_password}" == "" ]] && \
key_password="${key_alias}123456"
if [[ ! -e ${keystore} ]]; then
keytool -genkey -v -dname "cn=, ou=${key_alias}, o=fpl" \
-storepass ${key_password} \
-keypass ${key_password} -keystore ${keystore} \
-alias ${key_alias} -keyalg RSA -keysize 2048 -validity 60
fi
cp "${unsigned_apk}" "${signed_apk}"
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 \
-keystore ${keystore} -storepass ${key_password} \
-keypass ${key_password} "${signed_apk}" ${key_alias}
fi
}
# Build the apk $1 for package filename $2 in the current directory using the
# ant build target $3.
build_apk() {
local -r output_apk="${1}"
local -r package_filename="${2}"
local -r ant_target="${3}"
# Get the list of installed android targets and select the oldest target
# that is at least as new as BUILDAPK_ANDROID_TARGET_MINVERSION.
local -r android_build_target=$(select_android_build_target)
[[ "${android_build_target}" == "" ]] && exit 1
echo "Building ${output_apk} for target ${android_build_target}" >&2
# Create / update build.xml and local.properties files.
if [[ $(stat_mtime "${android_manifest}") -gt \
$(stat_mtime build.xml) ]]; then
android update project --target "${android_build_target}" \
-n ${package_filename} --path .
fi
# Use ant to build the apk.
ant -quiet ${ant_target}
# Sign release apks with a temporary key as these packages will not be
# redistributed.
local unsigned_apk="bin/${package_filename}-${ant_target}-unsigned.apk"
if [[ "${ant_target}" == "release" ]]; then
sign_apk "${unsigned_apk}" "${output_apk}" "" ""
fi
}
# Uninstall package $1 and install apk $2 on device $3 where $3 is "-s device"
# or an empty string. If $3 is an empty string adb will fail when multiple
# devices are connected to the host system.
install_apk() {
local -r uninstall_package_name="${1}"
local -r install_apk="${2}"
local -r adb_device="${3}"
# Uninstall the package if it's already installed.
adb ${adb_device} uninstall "${uninstall_package_name}" 1>&2 > /dev/null || \
true # no error check
# Install the apk.
# NOTE: The following works around adb not returning an error code when
# it fails to install an apk.
echo "Install ${install_apk}" >&2
local -r adb_install_result=$(adb ${adb_device} install "${install_apk}")
echo "${adb_install_result}"
if echo "${adb_install_result}" | grep -qF 'Failure ['; then
exit 1
fi
}
# Launch previously installed package $1 on device $2.
# If $2 is an empty string adb will fail when multiple devices are connected
# to the host system.
launch_package() {
(
# Determine the SDK version of Android on the device.
local -r android_sdk_version=$(
adb ${adb_device} shell cat system/build.prop | \
awk -F= '/ro.build.version.sdk/ {
v=$2; sub(/[ \r\n]/, "", v); print v
}')
# Clear logs from previous runs.
# Note that logcat does not just 'tail' the logs, it dumps the entire log
# history.
adb ${adb_device} logcat -c
local finished_msg='Displayed '"${package_name}"
local timeout_msg='Activity destroy timeout.*'"${package_name}"
# Maximum time to wait before stopping log monitoring. 0 = infinity.
local launch_timeout=0
# If this is a Gingerbread device, kill log monitoring after 10 seconds.
if [[ $((android_sdk_version)) -le 10 ]]; then
launch_timeout=10
fi
# Display logcat in the background.
# Stop displaying the log when the app launch / execution completes or the
# logcat
(
adb ${adb_device} logcat | \
awk "
{
print \$0
}
/ActivityManager.*: ${finished_msg}/ {
exit 0
}
/ActivityManager.*: ${timeout_msg}/ {
exit 0
}" &
adb_logcat_pid=$!;
if [[ $((launch_timeout)) -gt 0 ]]; then
sleep $((launch_timeout));
kill ${adb_logcat_pid};
else
wait ${adb_logcat_pid};
fi
) &
logcat_pid=$!
# Kill adb logcat if this shell exits.
trap "kill_process_group ${logcat_pid}" SIGINT SIGTERM EXIT
# If the SDK is newer than 10, "am" supports stopping an activity.
adb_stop_activity=
if [[ $((android_sdk_version)) -gt 10 ]]; then
adb_stop_activity=-S
fi
# Launch the activity and wait for it to complete.
adb ${adb_device} shell am start ${adb_stop_activity} -n \
${package_name}/android.app.NativeActivity
wait "${logcat_pid}"
)
}
# See usage().
main() {
# Parse arguments for this script.
local adb_device=
local ant_target=release
local disable_deploy=0
local disable_build=0
local run_debugger=0
local launch=1
local build_package=1
for opt; do
case ${opt} in
# NDK_DEBUG=0 tells ndk-build to build this as debuggable but to not
# modify the underlying code whereas NDK_DEBUG=1 also builds as debuggable
# but does modify the code
NDK_DEBUG=1) ant_target=debug ;;
NDK_DEBUG=0) ant_target=debug ;;
ADB_DEVICE*) adb_device="$(\
echo "${opt}" | sed -E 's/^ADB_DEVICE=([^ ]+)$/-s \1/;t;s/.*//')" ;;
BUILD=0) disable_build=1 ;;
DEPLOY=0) disable_deploy=1 ;;
RUN_DEBUGGER=1) run_debugger=1 ;;
LAUNCH=0) launch=0 ;;
clean) build_package=0 disable_deploy=1 launch=0 ;;
-h|--help|help) usage ;;
esac
done
# If a target device hasn't been specified and multiple devices are connected
# to the host machine, display an error.
local -r devices_connected=$(get_number_of_devices_connected)
if [[ "${adb_device}" == "" && $((devices_connected)) -gt 1 && \
($((disable_deploy)) -eq 0 || $((launch)) -ne 0 || \
$((run_debugger)) -ne 0) ]]; then
if [[ $((disable_deploy)) -ne 0 ]]; then
echo "Deployment enabled, disable using DEPLOY=0" >&2
fi
if [[ $((launch)) -ne 0 ]]; then
echo "Launch enabled." >&2
fi
if [[ $((disable_deploy)) -eq 0 ]]; then
echo "Deployment enabled." >&2
fi
if [[ $((run_debugger)) -ne 0 ]]; then
echo "Debugger launch enabled." >&2
fi
echo "
Multiple Android devices are connected to this host. Either disable deployment
and execution of the built .apk using:
\"${script_name} DEPLOY=0 LAUNCH=0\"
or specify a device to deploy to using:
\"${script_name} ADB_DEVICE=\${device_serial}\".
The Android devices connected to this machine are:
$(adb devices -l)
" >&2
exit 1
fi
if [[ $((disable_build)) -eq 0 ]]; then
# Build the native target.
build_native_targets "$@"
fi
# Get the package name from the manifest.
local -r package_name=$(get_package_name_from_manifest "${android_manifest}")
if [[ "${package_name}" == "" ]]; then
echo -e "No package name specified in ${android_manifest},"\
"skipping apk build, deploy"
"\nand launch steps." >&2
exit 0
fi
local -r package_basename=${package_name/*./}
local package_filename=$(get_library_name_from_manifest ${android_manifest})
[[ "${package_filename}" == "" ]] && package_filename="${package_basename}"
# Output apk name.
local -r output_apk="bin/${package_filename}-${ant_target}.apk"
if [[ $((disable_build)) -eq 0 && $((build_package)) -eq 1 ]]; then
# Build the apk.
build_apk "${output_apk}" "${package_filename}" "${ant_target}"
fi
# Deploy to the device.
if [[ $((disable_deploy)) -eq 0 ]]; then
install_apk "${package_name}" "${output_apk}" "${adb_device}"
fi
if [[ "${ant_target}" == "debug" && $((run_debugger)) -eq 1 ]]; then
# Start debugging.
ndk-gdb ${adb_device} --start
elif [[ $((launch)) -eq 1 ]]; then
launch_package "${package_name}" "${adb_device}"
fi
}
main "$@"

Binary file not shown.

View File

@@ -0,0 +1,6 @@
#Mon Jun 19 11:54:59 PDT 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.0-all.zip

172
samples/android/gradlew vendored Executable file
View File

@@ -0,0 +1,172 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

84
samples/android/gradlew.bat vendored Normal file
View File

@@ -0,0 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

2
samples/android/jni/Android.mk Executable file → Normal file
View File

@@ -38,7 +38,7 @@ $(info $(LOCAL_C_INCLUDES))
LOCAL_SRC_FILES := main.cpp
LOCAL_CPPFLAGS := -std=c++11 -fexceptions -Wall -Wno-literal-suffix
LOCAL_LDLIBS := -llog -landroid
LOCAL_LDLIBS := -llog -landroid -latomic
LOCAL_ARM_MODE := arm
LOCAL_STATIC_LIBRARIES := android_native_app_glue flatbuffers

6
samples/android/jni/Application.mk Executable file → Normal file
View File

@@ -13,10 +13,8 @@
# 2. Altered source versions must be plainly marked as such, and must not be
# misrepresented as being the original software.
# 3. This notice may not be removed or altered from any source distribution.
APP_PLATFORM := android-10
APP_PLATFORM := android-9
APP_PROJECT_PATH := $(call my-dir)/..
APP_STL := gnustl_static
APP_STL ?= stlport_static
APP_ABI := armeabi-v7a
APP_CPPFLAGS += -std=c++11

0
samples/android/res/values/strings.xml Executable file → Normal file
View File

View File

@@ -29,8 +29,7 @@ fi
# Execute `build_apk.sh` to build and run the android app.
cd android
./build_apk.sh
./gradlew build
# Cleanup the temporary files.
rm build.xml local.properties proguard-project.txt project.properties
rm -rf bin libs obj

0
samples/monster.fbs Executable file → Normal file
View File

View File

@@ -25,6 +25,15 @@ enum Color {
Color_MAX = Color_Blue
};
inline Color (&EnumValuesColor())[3] {
static Color values[] = {
Color_Red,
Color_Green,
Color_Blue
};
return values;
}
inline const char **EnumNamesColor() {
static const char *names[] = {
"Red",
@@ -47,6 +56,14 @@ enum Equipment {
Equipment_MAX = Equipment_Weapon
};
inline Equipment (&EnumValuesEquipment())[2] {
static Equipment values[] = {
Equipment_NONE,
Equipment_Weapon
};
return values;
}
inline const char **EnumNamesEquipment() {
static const char *names[] = {
"NONE",
@@ -71,32 +88,42 @@ template<> struct EquipmentTraits<Weapon> {
struct EquipmentUnion {
Equipment type;
flatbuffers::NativeTable *table;
void *value;
EquipmentUnion() : type(Equipment_NONE), table(nullptr) {}
EquipmentUnion(EquipmentUnion&& u):
type(std::move(u.type)), table(std::move(u.table)) {}
EquipmentUnion(const EquipmentUnion &);
EquipmentUnion &operator=(const EquipmentUnion &);
EquipmentUnion() : type(Equipment_NONE), value(nullptr) {}
EquipmentUnion(EquipmentUnion&& u) FLATBUFFERS_NOEXCEPT :
type(Equipment_NONE), value(nullptr)
{ std::swap(type, u.type); std::swap(value, u.value); }
EquipmentUnion(const EquipmentUnion &) FLATBUFFERS_NOEXCEPT;
EquipmentUnion &operator=(const EquipmentUnion &u) FLATBUFFERS_NOEXCEPT
{ EquipmentUnion t(u); std::swap(type, t.type); std::swap(value, t.value); return *this; }
EquipmentUnion &operator=(EquipmentUnion &&u) FLATBUFFERS_NOEXCEPT
{ std::swap(type, u.type); std::swap(value, u.value); return *this; }
~EquipmentUnion() { Reset(); }
void Reset();
#ifndef FLATBUFFERS_CPP98_STL
template <typename T>
void Set(T&& value) {
void Set(T&& val) {
Reset();
type = EquipmentTraits<typename T::TableType>::enum_value;
if (type != Equipment_NONE) {
table = new T(std::forward<T>(value));
value = new T(std::forward<T>(val));
}
}
#endif // FLATBUFFERS_CPP98_STL
static flatbuffers::NativeTable *UnPack(const void *obj, Equipment type, const flatbuffers::resolver_function_t *resolver);
static void *UnPack(const void *obj, Equipment type, const flatbuffers::resolver_function_t *resolver);
flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher = nullptr) const;
WeaponT *AsWeapon() {
return type == Equipment_Weapon ?
reinterpret_cast<WeaponT *>(table) : nullptr;
reinterpret_cast<WeaponT *>(value) : nullptr;
}
const WeaponT *AsWeapon() const {
return type == Equipment_Weapon ?
reinterpret_cast<const WeaponT *>(value) : nullptr;
}
};
@@ -113,9 +140,6 @@ MANUALLY_ALIGNED_STRUCT(4) Vec3 FLATBUFFERS_FINAL_CLASS {
Vec3() {
memset(this, 0, sizeof(Vec3));
}
Vec3(const Vec3 &_o) {
memcpy(this, &_o, sizeof(Vec3));
}
Vec3(float _x, float _y, float _z)
: x_(flatbuffers::EndianScalar(_x)),
y_(flatbuffers::EndianScalar(_y)),
@@ -144,13 +168,13 @@ STRUCT_END(Vec3, 12);
struct MonsterT : public flatbuffers::NativeTable {
typedef Monster TableType;
std::unique_ptr<Vec3> pos;
flatbuffers::unique_ptr<Vec3> pos;
int16_t mana;
int16_t hp;
std::string name;
std::vector<uint8_t> inventory;
Color color;
std::vector<std::unique_ptr<WeaponT>> weapons;
std::vector<flatbuffers::unique_ptr<WeaponT>> weapons;
EquipmentUnion equipped;
MonsterT()
: mana(150),
@@ -182,13 +206,13 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
return GetField<int16_t>(VT_MANA, 150);
}
bool mutate_mana(int16_t _mana) {
return SetField(VT_MANA, _mana);
return SetField<int16_t>(VT_MANA, _mana, 150);
}
int16_t hp() const {
return GetField<int16_t>(VT_HP, 100);
}
bool mutate_hp(int16_t _hp) {
return SetField(VT_HP, _hp);
return SetField<int16_t>(VT_HP, _hp, 100);
}
const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(VT_NAME);
@@ -206,7 +230,7 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
return static_cast<Color>(GetField<int8_t>(VT_COLOR, 2));
}
bool mutate_color(Color _color) {
return SetField(VT_COLOR, static_cast<int8_t>(_color));
return SetField<int8_t>(VT_COLOR, static_cast<int8_t>(_color), 2);
}
const flatbuffers::Vector<flatbuffers::Offset<Weapon>> *weapons() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Weapon>> *>(VT_WEAPONS);
@@ -218,11 +242,15 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
return static_cast<Equipment>(GetField<uint8_t>(VT_EQUIPPED_TYPE, 0));
}
bool mutate_equipped_type(Equipment _equipped_type) {
return SetField(VT_EQUIPPED_TYPE, static_cast<uint8_t>(_equipped_type));
return SetField<uint8_t>(VT_EQUIPPED_TYPE, static_cast<uint8_t>(_equipped_type), 0);
}
const void *equipped() const {
return GetPointer<const void *>(VT_EQUIPPED);
}
template<typename T> const T *equipped_as() const;
const Weapon *equipped_as_Weapon() const {
return equipped_type() == Equipment_Weapon ? static_cast<const Weapon *>(equipped()) : nullptr;
}
void *mutable_equipped() {
return GetPointer<void *>(VT_EQUIPPED);
}
@@ -231,16 +259,16 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyField<Vec3>(verifier, VT_POS) &&
VerifyField<int16_t>(verifier, VT_MANA) &&
VerifyField<int16_t>(verifier, VT_HP) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
VerifyOffset(verifier, VT_NAME) &&
verifier.Verify(name()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_INVENTORY) &&
VerifyOffset(verifier, VT_INVENTORY) &&
verifier.Verify(inventory()) &&
VerifyField<int8_t>(verifier, VT_COLOR) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_WEAPONS) &&
VerifyOffset(verifier, VT_WEAPONS) &&
verifier.Verify(weapons()) &&
verifier.VerifyVectorOfTables(weapons()) &&
VerifyField<uint8_t>(verifier, VT_EQUIPPED_TYPE) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_EQUIPPED) &&
VerifyOffset(verifier, VT_EQUIPPED) &&
VerifyEquipment(verifier, equipped(), equipped_type()) &&
verifier.EndTable();
}
@@ -249,6 +277,10 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
static flatbuffers::Offset<Monster> Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
};
template<> inline const Weapon *Monster::equipped_as<Weapon>() const {
return equipped_as_Weapon();
}
struct MonsterBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
@@ -279,13 +311,13 @@ struct MonsterBuilder {
void add_equipped(flatbuffers::Offset<void> equipped) {
fbb_.AddOffset(Monster::VT_EQUIPPED, equipped);
}
MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb)
explicit MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
MonsterBuilder &operator=(const MonsterBuilder &);
flatbuffers::Offset<Monster> Finish() {
const auto end = fbb_.EndTable(start_, 10);
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Monster>(end);
return o;
}
@@ -366,11 +398,11 @@ struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
return GetField<int16_t>(VT_DAMAGE, 0);
}
bool mutate_damage(int16_t _damage) {
return SetField(VT_DAMAGE, _damage);
return SetField<int16_t>(VT_DAMAGE, _damage, 0);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
VerifyOffset(verifier, VT_NAME) &&
verifier.Verify(name()) &&
VerifyField<int16_t>(verifier, VT_DAMAGE) &&
verifier.EndTable();
@@ -389,13 +421,13 @@ struct WeaponBuilder {
void add_damage(int16_t damage) {
fbb_.AddElement<int16_t>(Weapon::VT_DAMAGE, damage, 0);
}
WeaponBuilder(flatbuffers::FlatBufferBuilder &_fbb)
explicit WeaponBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
WeaponBuilder &operator=(const WeaponBuilder &);
flatbuffers::Offset<Weapon> Finish() {
const auto end = fbb_.EndTable(start_, 2);
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<Weapon>(end);
return o;
}
@@ -432,15 +464,15 @@ inline MonsterT *Monster::UnPack(const flatbuffers::resolver_function_t *_resolv
inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function_t *_resolver) const {
(void)_o;
(void)_resolver;
{ auto _e = pos(); if (_e) _o->pos = std::unique_ptr<Vec3>(new Vec3(*_e)); };
{ auto _e = pos(); if (_e) _o->pos = flatbuffers::unique_ptr<Vec3>(new Vec3(*_e)); };
{ auto _e = mana(); _o->mana = _e; };
{ auto _e = hp(); _o->hp = _e; };
{ auto _e = name(); if (_e) _o->name = _e->str(); };
{ auto _e = inventory(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inventory.push_back(_e->Get(_i)); } };
{ auto _e = inventory(); if (_e) { _o->inventory.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inventory[_i] = _e->Get(_i); } } };
{ auto _e = color(); _o->color = _e; };
{ auto _e = weapons(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->weapons.push_back(std::unique_ptr<WeaponT>(_e->Get(_i)->UnPack(_resolver))); } };
{ 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.table = EquipmentUnion::UnPack(_e, equipped_type(),_resolver); };
{ auto _e = equipped(); if (_e) _o->equipped.value = EquipmentUnion::UnPack(_e, equipped_type(), _resolver); };
}
inline flatbuffers::Offset<Monster> Monster::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
@@ -450,13 +482,14 @@ inline flatbuffers::Offset<Monster> Monster::Pack(flatbuffers::FlatBufferBuilder
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
(void)_rehasher;
(void)_o;
struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const MonsterT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
auto _pos = _o->pos ? _o->pos.get() : 0;
auto _mana = _o->mana;
auto _hp = _o->hp;
auto _name = _o->name.size() ? _fbb.CreateString(_o->name) : 0;
auto _name = _o->name.empty() ? 0 : _fbb.CreateString(_o->name);
auto _inventory = _o->inventory.size() ? _fbb.CreateVector(_o->inventory) : 0;
auto _color = _o->color;
auto _weapons = _o->weapons.size() ? _fbb.CreateVector<flatbuffers::Offset<Weapon>>(_o->weapons.size(), [&](size_t i) { return CreateWeapon(_fbb, _o->weapons[i].get(), _rehasher); }) : 0;
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);
return MyGame::Sample::CreateMonster(
@@ -492,7 +525,8 @@ inline flatbuffers::Offset<Weapon> Weapon::Pack(flatbuffers::FlatBufferBuilder &
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
(void)_rehasher;
(void)_o;
auto _name = _o->name.size() ? _fbb.CreateString(_o->name) : 0;
struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const WeaponT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va;
auto _name = _o->name.empty() ? 0 : _fbb.CreateString(_o->name);
auto _damage = _o->damage;
return MyGame::Sample::CreateWeapon(
_fbb,
@@ -524,7 +558,7 @@ inline bool VerifyEquipmentVector(flatbuffers::Verifier &verifier, const flatbuf
return true;
}
inline flatbuffers::NativeTable *EquipmentUnion::UnPack(const void *obj, Equipment type, const flatbuffers::resolver_function_t *resolver) {
inline void *EquipmentUnion::UnPack(const void *obj, Equipment type, const flatbuffers::resolver_function_t *resolver) {
switch (type) {
case Equipment_Weapon: {
auto ptr = reinterpret_cast<const Weapon *>(obj);
@@ -537,26 +571,151 @@ inline flatbuffers::NativeTable *EquipmentUnion::UnPack(const void *obj, Equipme
inline flatbuffers::Offset<void> EquipmentUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher) const {
switch (type) {
case Equipment_Weapon: {
auto ptr = reinterpret_cast<const WeaponT *>(table);
auto ptr = reinterpret_cast<const WeaponT *>(value);
return CreateWeapon(_fbb, ptr, _rehasher).Union();
}
default: return 0;
}
}
inline EquipmentUnion::EquipmentUnion(const EquipmentUnion &u) FLATBUFFERS_NOEXCEPT : type(u.type), value(nullptr) {
switch (type) {
case Equipment_Weapon: {
value = new WeaponT(*reinterpret_cast<WeaponT *>(u.value));
break;
}
default:
break;
}
}
inline void EquipmentUnion::Reset() {
switch (type) {
case Equipment_Weapon: {
auto ptr = reinterpret_cast<WeaponT *>(table);
auto ptr = reinterpret_cast<WeaponT *>(value);
delete ptr;
break;
}
default: break;
}
table = nullptr;
value = nullptr;
type = Equipment_NONE;
}
inline flatbuffers::TypeTable *Vec3TypeTable();
inline flatbuffers::TypeTable *MonsterTypeTable();
inline flatbuffers::TypeTable *WeaponTypeTable();
inline flatbuffers::TypeTable *ColorTypeTable() {
static flatbuffers::TypeCode type_codes[] = {
{ flatbuffers::ET_CHAR, 0, 0 },
{ flatbuffers::ET_CHAR, 0, 0 },
{ flatbuffers::ET_CHAR, 0, 0 }
};
static flatbuffers::TypeFunction type_refs[] = {
ColorTypeTable
};
static const char *names[] = {
"Red",
"Green",
"Blue"
};
static flatbuffers::TypeTable tt = {
flatbuffers::ST_ENUM, 3, type_codes, type_refs, nullptr, names
};
return &tt;
}
inline flatbuffers::TypeTable *EquipmentTypeTable() {
static flatbuffers::TypeCode type_codes[] = {
{ flatbuffers::ET_SEQUENCE, 0, -1 },
{ flatbuffers::ET_SEQUENCE, 0, 0 }
};
static flatbuffers::TypeFunction type_refs[] = {
WeaponTypeTable
};
static const char *names[] = {
"NONE",
"Weapon"
};
static flatbuffers::TypeTable tt = {
flatbuffers::ST_UNION, 2, type_codes, type_refs, nullptr, names
};
return &tt;
}
inline flatbuffers::TypeTable *Vec3TypeTable() {
static flatbuffers::TypeCode type_codes[] = {
{ flatbuffers::ET_FLOAT, 0, -1 },
{ flatbuffers::ET_FLOAT, 0, -1 },
{ flatbuffers::ET_FLOAT, 0, -1 }
};
static const int32_t values[] = { 0, 4, 8, 12 };
static const char *names[] = {
"x",
"y",
"z"
};
static flatbuffers::TypeTable tt = {
flatbuffers::ST_STRUCT, 3, type_codes, nullptr, values, names
};
return &tt;
}
inline flatbuffers::TypeTable *MonsterTypeTable() {
static flatbuffers::TypeCode type_codes[] = {
{ flatbuffers::ET_SEQUENCE, 0, 0 },
{ flatbuffers::ET_SHORT, 0, -1 },
{ flatbuffers::ET_SHORT, 0, -1 },
{ flatbuffers::ET_STRING, 0, -1 },
{ flatbuffers::ET_BOOL, 0, -1 },
{ flatbuffers::ET_UCHAR, 1, -1 },
{ flatbuffers::ET_CHAR, 0, 1 },
{ flatbuffers::ET_SEQUENCE, 1, 2 },
{ flatbuffers::ET_UTYPE, 0, 3 },
{ flatbuffers::ET_SEQUENCE, 0, 3 }
};
static flatbuffers::TypeFunction type_refs[] = {
Vec3TypeTable,
ColorTypeTable,
WeaponTypeTable,
EquipmentTypeTable
};
static const char *names[] = {
"pos",
"mana",
"hp",
"name",
"friendly",
"inventory",
"color",
"weapons",
"equipped_type",
"equipped"
};
static flatbuffers::TypeTable tt = {
flatbuffers::ST_TABLE, 10, type_codes, type_refs, nullptr, names
};
return &tt;
}
inline flatbuffers::TypeTable *WeaponTypeTable() {
static flatbuffers::TypeCode type_codes[] = {
{ flatbuffers::ET_STRING, 0, -1 },
{ flatbuffers::ET_SHORT, 0, -1 }
};
static const char *names[] = {
"name",
"damage"
};
static flatbuffers::TypeTable tt = {
flatbuffers::ST_TABLE, 2, type_codes, nullptr, nullptr, names
};
return &tt;
}
inline const MyGame::Sample::Monster *GetMonster(const void *buf) {
return flatbuffers::GetRoot<MyGame::Sample::Monster>(buf);
}
@@ -576,10 +735,10 @@ inline void FinishMonsterBuffer(
fbb.Finish(root);
}
inline std::unique_ptr<MonsterT> UnPackMonster(
inline flatbuffers::unique_ptr<MonsterT> UnPackMonster(
const void *buf,
const flatbuffers::resolver_function_t *res = nullptr) {
return std::unique_ptr<MonsterT>(GetMonster(buf)->UnPack(res));
return flatbuffers::unique_ptr<MonsterT>(GetMonster(buf)->UnPack(res));
}
} // namespace Sample

0
samples/monsterdata.json Executable file → Normal file
View File

View File

@@ -16,8 +16,14 @@
#include "flatbuffers/code_generators.h"
#include <assert.h>
#include "flatbuffers/base.h"
#include "flatbuffers/util.h"
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4127) // C4127: conditional expression is constant
#endif
namespace flatbuffers {
void CodeWriter::operator+=(std::string text) {
@@ -53,7 +59,7 @@ void CodeWriter::operator+=(std::string text) {
// Update the text to everything after the }}.
text = text.substr(end + 2);
}
if (!text.empty() && text.back() == '\\') {
if (!text.empty() && string_back(text) == '\\') {
text.pop_back();
stream_ << text;
} else {
@@ -63,7 +69,7 @@ void CodeWriter::operator+=(std::string text) {
const char *BaseGenerator::FlatBuffersGeneratedWarning() {
return "automatically generated by the FlatBuffers compiler,"
" do not modify\n\n";
" do not modify";
}
std::string BaseGenerator::NamespaceDir(const Parser &parser,
@@ -84,18 +90,6 @@ std::string BaseGenerator::NamespaceDir(const Namespace &ns) const {
return BaseGenerator::NamespaceDir(parser_, path_, ns);
}
bool BaseGenerator::IsEverythingGenerated() const {
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
if (!(*it)->generated) return false;
}
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
if (!(*it)->generated) return false;
}
return true;
}
std::string BaseGenerator::FullNamespace(const char *separator,
const Namespace &ns) {
std::string namespace_name;
@@ -130,6 +124,20 @@ std::string BaseGenerator::WrapInNameSpace(const Definition &def) const {
return WrapInNameSpace(def.defined_namespace, def.name);
}
std::string BaseGenerator::GetNameSpace(const Definition &def) const {
const Namespace *ns = def.defined_namespace;
if (CurrentNameSpace() == ns) return "";
std::string qualified_name = qualifying_start_;
for (auto it = ns->components.begin(); it != ns->components.end(); ++it) {
qualified_name += *it;
if ((it + 1) != ns->components.end()) {
qualified_name += qualifying_separator_;
}
}
return qualified_name;
}
// Generate a documentation comment, if available.
void GenComment(const std::vector<std::string> &dc, std::string *code_ptr,
const CommentConfig *config, const char *prefix) {
@@ -156,3 +164,7 @@ void GenComment(const std::vector<std::string> &dc, std::string *code_ptr,
}
} // namespace flatbuffers
#if defined(_MSC_VER)
#pragma warning(pop)
#endif

View File

@@ -16,7 +16,9 @@
#include "flatbuffers/flatc.h"
#define FLATC_VERSION "1.6.0 (" __DATE__ ")"
#include <list>
#define FLATC_VERSION "1.8.0 (" __DATE__ ")"
namespace flatbuffers {
@@ -46,7 +48,7 @@ void FlatCompiler::Error(const std::string &err, bool usage,
std::string FlatCompiler::GetUsageString(const char* program_name) const {
std::stringstream ss;
ss << "Usageaa: " << program_name << " [OPTION]... FILE... [-- FILE...]\n";
ss << "Usage: " << program_name << " [OPTION]... FILE... [-- FILE...]\n";
for (size_t i = 0; i < params_.num_generators; ++i) {
const Generator& g = params_.generators[i];
@@ -81,13 +83,21 @@ std::string FlatCompiler::GetUsageString(const char* program_name) const {
" --no-includes Don\'t generate include statements for included\n"
" schemas the generated file depends on (C++).\n"
" --gen-mutable Generate accessors that can mutate buffers in-place.\n"
" --gen-onefile Generate single output file for C#.\n"
" --gen-onefile Generate single output file for C# and Go.\n"
" --gen-name-strings Generate type name functions for C++.\n"
" --escape-proto-ids Disable appending '_' in namespaces names.\n"
" --gen-object-api Generate an additional object-based API.\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"
" --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"
" --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"
" --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"
" --raw-binary Allow binaries without file_indentifier to be read.\n"
" This may crash flatc given a mismatched schema.\n"
" --proto Input is a .proto, translate to .fbs.\n"
@@ -100,8 +110,13 @@ std::string FlatCompiler::GetUsageString(const char* program_name) const {
" PATH \n"
" --include-prefix Prefix this path to any generated include statements.\n"
" PATH\n"
"FILEs may be schemas, or JSON files (conforming to preceding schema)\n"
"FILEs after the -- must be binary flatbuffer format files.\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"
" --reflect-types Add minimal type reflection to code generation.\n"
" --reflect-names Add minimal type/name reflection.\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"
"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";
@@ -122,6 +137,7 @@ int FlatCompiler::Compile(int argc, const char** argv) {
bool schema_binary = false;
bool grpc_enabled = false;
std::vector<std::string> filenames;
std::list<std::string> include_directories_storage;
std::vector<const char *> include_directories;
std::vector<const char *> conform_include_directories;
std::vector<bool> generator_enabled(params_.num_generators, false);
@@ -135,21 +151,29 @@ int FlatCompiler::Compile(int argc, const char** argv) {
Error("invalid option location: " + arg, true);
if (arg == "-o") {
if (++argi >= argc) Error("missing path following: " + arg, true);
output_path = flatbuffers::ConCatPathFileName(argv[argi], "");
output_path = flatbuffers::ConCatPathFileName(
flatbuffers::PosixPath(argv[argi]), "");
} else if(arg == "-I") {
if (++argi >= argc) Error("missing path following" + arg, true);
include_directories.push_back(argv[argi]);
include_directories_storage.push_back(
flatbuffers::PosixPath(argv[argi]));
include_directories.push_back(
include_directories_storage.back().c_str());
} else if(arg == "--conform") {
if (++argi >= argc) Error("missing path following" + arg, true);
conform_to_schema = argv[argi];
conform_to_schema = flatbuffers::PosixPath(argv[argi]);
} else if (arg == "--conform-includes") {
if (++argi >= argc) Error("missing path following" + arg, true);
conform_include_directories.push_back(argv[argi]);
include_directories_storage.push_back(
flatbuffers::PosixPath(argv[argi]));
conform_include_directories.push_back(
include_directories_storage.back().c_str());
} else if (arg == "--include-prefix") {
if (++argi >= argc) Error("missing path following" + arg, true);
opts.include_prefix = argv[argi];
if (opts.include_prefix.back() != '/' &&
opts.include_prefix.back() != '\\') opts.include_prefix += "/";
opts.include_prefix = flatbuffers::ConCatPathFileName(
flatbuffers::PosixPath(argv[argi]), "");
} else if(arg == "--keep-prefix") {
opts.keep_include_path = true;
} else if(arg == "--strict-json") {
opts.strict_json = true;
} else if(arg == "--allow-non-utf8") {
@@ -158,6 +182,12 @@ int FlatCompiler::Compile(int argc, const char** argv) {
opts.skip_js_exports = true;
} else if(arg == "--goog-js-export") {
opts.use_goog_js_export_format = true;
} else if(arg == "--go-namespace") {
if (++argi >= argc) Error("missing golang namespace" + arg, true);
opts.go_namespace = argv[argi];
} else if(arg == "--go-import") {
if (++argi >= argc) Error("missing golang import" + arg, true);
opts.go_import = argv[argi];
} else if(arg == "--defaults-json") {
opts.output_default_scalars_in_json = true;
} else if (arg == "--unknown-json") {
@@ -178,6 +208,17 @@ int FlatCompiler::Compile(int argc, const char** argv) {
} else if (arg == "--cpp-ptr-type") {
if (++argi >= argc) Error("missing type following" + arg, true);
opts.cpp_object_api_pointer_type = argv[argi];
} 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 == "--gen-nullable") {
opts.gen_nullable = true;
} else if (arg == "--object-prefix") {
if (++argi >= argc) Error("missing prefix following" + arg, true);
opts.object_prefix = argv[argi];
} else if (arg == "--object-suffix") {
if (++argi >= argc) Error("missing suffix following" + arg, true);
opts.object_suffix = argv[argi];
} else if(arg == "--gen-all") {
opts.generate_all = true;
opts.include_dependence_headers = false;
@@ -194,8 +235,6 @@ int FlatCompiler::Compile(int argc, const char** argv) {
binary_files_from = filenames.size();
} else if(arg == "--proto") {
opts.proto_mode = true;
} else if(arg == "--escape-proto-ids") {
opts.escape_proto_identifiers = true;
} else if(arg == "--schema") {
schema_binary = true;
} else if(arg == "-M") {
@@ -207,6 +246,14 @@ int FlatCompiler::Compile(int argc, const char** argv) {
grpc_enabled = true;
} else if(arg == "--bfbs-comments") {
opts.binary_schema_comments = true;
} else if(arg == "--no-fb-import") {
opts.skip_flatbuffers_import = true;
} else if(arg == "--no-ts-reexport") {
opts.reexport_ts_modules = false;
} else if(arg == "--reflect-types") {
opts.mini_reflect = IDLOptions::kTypes;
} else if(arg == "--reflect-names") {
opts.mini_reflect = IDLOptions::kTypesAndNames;
} else {
for (size_t i = 0; i < params_.num_generators; ++i) {
if (arg == params_.generators[i].generator_opt_long ||
@@ -222,7 +269,7 @@ int FlatCompiler::Compile(int argc, const char** argv) {
found:;
}
} else {
filenames.push_back(argv[argi]);
filenames.push_back(flatbuffers::PosixPath(argv[argi]));
}
}
@@ -249,101 +296,110 @@ int FlatCompiler::Compile(int argc, const char** argv) {
for (auto file_it = filenames.begin();
file_it != filenames.end();
++file_it) {
std::string contents;
if (!flatbuffers::LoadFile(file_it->c_str(), true, &contents))
Error("unable to load file: " + *file_it);
auto &filename = *file_it;
std::string contents;
if (!flatbuffers::LoadFile(filename.c_str(), true, &contents))
Error("unable to load file: " + filename);
bool is_binary = static_cast<size_t>(file_it - filenames.begin()) >=
binary_files_from;
if (is_binary) {
parser->builder_.Clear();
parser->builder_.PushFlatBuffer(
reinterpret_cast<const uint8_t *>(contents.c_str()),
contents.length());
if (!raw_binary) {
// Generally reading binaries that do not correspond to the schema
// will crash, and sadly there's no way around that when the binary
// does not contain a file identifier.
// We'd expect that typically any binary used as a file would have
// such an identifier, so by default we require them to match.
if (!parser->file_identifier_.length()) {
Error("current schema has no file_identifier: cannot test if \"" +
*file_it +
"\" matches the schema, use --raw-binary to read this file"
" anyway.");
} else if (!flatbuffers::BufferHasIdentifier(contents.c_str(),
parser->file_identifier_.c_str())) {
Error("binary \"" +
*file_it +
"\" does not have expected file_identifier \"" +
parser->file_identifier_ +
"\", use --raw-binary to read this file anyway.");
}
}
} else {
// Check if file contains 0 bytes.
if (contents.length() != strlen(contents.c_str())) {
Error("input file appears to be binary: " + *file_it, true);
}
auto is_schema = flatbuffers::GetExtension(*file_it) == "fbs";
if (is_schema) {
// If we're processing multiple schemas, make sure to start each
// one from scratch. If it depends on previous schemas it must do
// so explicitly using an include.
parser.reset(new flatbuffers::Parser(opts));
}
ParseFile(*parser.get(), *file_it, contents, include_directories);
if (is_schema && !conform_to_schema.empty()) {
auto err = parser->ConformTo(conform_parser);
if (!err.empty()) Error("schemas don\'t conform: " + err);
}
if (schema_binary) {
parser->Serialize();
parser->file_extension_ = reflection::SchemaExtension();
bool is_binary = static_cast<size_t>(file_it - filenames.begin()) >=
binary_files_from;
auto ext = flatbuffers::GetExtension(filename);
auto is_schema = ext == "fbs" || ext == "proto";
if (is_binary) {
parser->builder_.Clear();
parser->builder_.PushFlatBuffer(
reinterpret_cast<const uint8_t *>(contents.c_str()),
contents.length());
if (!raw_binary) {
// Generally reading binaries that do not correspond to the schema
// will crash, and sadly there's no way around that when the binary
// does not contain a file identifier.
// We'd expect that typically any binary used as a file would have
// such an identifier, so by default we require them to match.
if (!parser->file_identifier_.length()) {
Error("current schema has no file_identifier: cannot test if \"" +
filename +
"\" matches the schema, use --raw-binary to read this file"
" anyway.");
} else if (!flatbuffers::BufferHasIdentifier(contents.c_str(),
parser->file_identifier_.c_str())) {
Error("binary \"" +
filename +
"\" does not have expected file_identifier \"" +
parser->file_identifier_ +
"\", use --raw-binary to read this file anyway.");
}
}
} else {
// Check if file contains 0 bytes.
if (contents.length() != strlen(contents.c_str())) {
Error("input file appears to be binary: " + filename, true);
}
if (is_schema) {
// If we're processing multiple schemas, make sure to start each
// one from scratch. If it depends on previous schemas it must do
// 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_schema && !conform_to_schema.empty()) {
auto err = parser->ConformTo(conform_parser);
if (!err.empty()) Error("schemas don\'t conform: " + err);
}
if (schema_binary) {
parser->Serialize();
parser->file_extension_ = reflection::SchemaExtension();
}
}
std::string filebase = flatbuffers::StripPath(
flatbuffers::StripExtension(*file_it));
std::string filebase = flatbuffers::StripPath(
flatbuffers::StripExtension(filename));
for (size_t i = 0; i < params_.num_generators; ++i) {
parser->opts.lang = params_.generators[i].lang;
if (generator_enabled[i]) {
if (!print_make_rules) {
flatbuffers::EnsureDirExists(output_path);
if (!params_.generators[i].generate(*parser.get(), output_path, filebase)) {
Error(std::string("Unable to generate ") +
params_.generators[i].lang_name +
" for " +
filebase);
for (size_t i = 0; i < params_.num_generators; ++i) {
parser->opts.lang = params_.generators[i].lang;
if (generator_enabled[i]) {
if (!print_make_rules) {
flatbuffers::EnsureDirExists(output_path);
if ((!params_.generators[i].schema_only || is_schema) &&
!params_.generators[i].generate(*parser.get(), output_path, filebase)) {
Error(std::string("Unable to generate ") +
params_.generators[i].lang_name +
" for " +
filebase);
}
} else {
std::string make_rule = params_.generators[i].make_rule(
*parser.get(), output_path, filename);
if (!make_rule.empty())
printf("%s\n", flatbuffers::WordWrap(
make_rule, 80, " ", " \\").c_str());
}
if (grpc_enabled) {
if (params_.generators[i].generateGRPC != nullptr) {
if (!params_.generators[i].generateGRPC(*parser.get(), output_path,
filebase)) {
Error(std::string("Unable to generate GRPC interface for") +
params_.generators[i].lang_name);
}
} else {
std::string make_rule = params_.generators[i].make_rule(
*parser.get(), output_path, *file_it);
if (!make_rule.empty())
printf("%s\n", flatbuffers::WordWrap(
make_rule, 80, " ", " \\").c_str());
}
if (grpc_enabled) {
if (params_.generators[i].generateGRPC != nullptr) {
if (!params_.generators[i].generateGRPC(*parser.get(), output_path,
filebase)) {
Error(std::string("Unable to generate GRPC interface for") +
params_.generators[i].lang_name);
}
} else {
Warn(std::string("GRPC interface generator not implemented for ")
+ params_.generators[i].lang_name);
}
Warn(std::string("GRPC interface generator not implemented for ")
+ params_.generators[i].lang_name);
}
}
}
}
if (opts.proto_mode) GenerateFBS(*parser.get(), output_path, filebase);
if (opts.proto_mode) GenerateFBS(*parser.get(), output_path, filebase);
// We do not want to generate code for the definitions in this file
// in any files coming up next.
parser->MarkGenerated();
// We do not want to generate code for the definitions in this file
// in any files coming up next.
parser->MarkGenerated();
}
return 0;
}

View File

@@ -46,52 +46,62 @@ int main(int argc, const char *argv[]) {
g_program_name = argv[0];
const flatbuffers::FlatCompiler::Generator generators[] = {
{ flatbuffers::GenerateBinary, "-b", "--binary", "binary",
{ flatbuffers::GenerateBinary, "-b", "--binary", "binary", false,
nullptr,
flatbuffers::IDLOptions::kBinary,
"Generate wire format binaries for any data definitions",
flatbuffers::BinaryMakeRule },
{ flatbuffers::GenerateTextFile, "-t", "--json", "text",
{ flatbuffers::GenerateTextFile, "-t", "--json", "text", false,
nullptr,
flatbuffers::IDLOptions::kJson,
"Generate text output for any data definitions",
flatbuffers::TextMakeRule },
{ flatbuffers::GenerateCPP, "-c", "--cpp", "C++",
{ flatbuffers::GenerateCPP, "-c", "--cpp", "C++", true,
flatbuffers::GenerateCppGRPC,
flatbuffers::IDLOptions::kCpp,
"Generate C++ headers for tables/structs",
flatbuffers::CPPMakeRule },
{ flatbuffers::GenerateGo, "-g", "--go", "Go",
{ flatbuffers::GenerateGo, "-g", "--go", "Go", true,
flatbuffers::GenerateGoGRPC,
flatbuffers::IDLOptions::kGo,
"Generate Go files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateGeneral, "-j", "--java", "Java",
{ flatbuffers::GenerateGeneral, "-j", "--java", "Java", true,
nullptr,
flatbuffers::IDLOptions::kJava,
"Generate Java classes for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateJS, "-s", "--js", "JavaScript",
{ flatbuffers::GenerateJS, "-s", "--js", "JavaScript", true,
nullptr,
flatbuffers::IDLOptions::kJs,
"Generate JavaScript code for tables/structs",
flatbuffers::JSMakeRule },
{ flatbuffers::GenerateGeneral, "-n", "--csharp", "C#",
{ flatbuffers::GenerateJS, "-T", "--ts", "TypeScript", true,
nullptr,
flatbuffers::IDLOptions::kTs,
"Generate TypeScript code for tables/structs",
flatbuffers::JSMakeRule },
{ flatbuffers::GenerateGeneral, "-n", "--csharp", "C#", true,
nullptr,
flatbuffers::IDLOptions::kCSharp,
"Generate C# classes for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePython, "-p", "--python", "Python",
{ flatbuffers::GeneratePython, "-p", "--python", "Python", true,
nullptr,
flatbuffers::IDLOptions::kPython,
"Generate Python files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePhp, nullptr, "--php", "PHP",
{ flatbuffers::GeneratePhp, nullptr, "--php", "PHP", true,
nullptr,
flatbuffers::IDLOptions::kPhp,
"Generate PHP files for tables/structs",
flatbuffers::GeneralMakeRule },
};
{ flatbuffers::GenerateJsonSchema, nullptr, "--jsonschema", "JsonSchema", true,
nullptr,
flatbuffers::IDLOptions::kJsonSchema,
"Generate Json schema",
flatbuffers::GeneralMakeRule },
};
flatbuffers::FlatCompiler::InitParams params;
params.generators = generators;

File diff suppressed because it is too large Load Diff

View File

@@ -23,18 +23,20 @@
namespace flatbuffers {
static std::string GenType(const Type &type) {
static std::string GenType(const Type &type, bool underlying = false) {
switch (type.base_type) {
case BASE_TYPE_STRUCT:
return type.struct_def->defined_namespace->GetFullyQualifiedName(
type.struct_def->name);
case BASE_TYPE_UNION:
return type.enum_def->defined_namespace->GetFullyQualifiedName(
type.enum_def->name);
case BASE_TYPE_VECTOR:
return "[" + GenType(type.VectorType()) + "]";
default:
return kTypeNames[type.base_type];
if (type.enum_def && !underlying) {
return type.enum_def->defined_namespace->GetFullyQualifiedName(
type.enum_def->name);
} else {
return kTypeNames[type.base_type];
}
}
}
@@ -54,14 +56,13 @@ static void GenNameSpace(const Namespace &name_space, std::string *_schema,
// Generate a flatbuffer schema from the Parser's internal representation.
std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
// Proto namespaces may clash with table names, so we have to prefix all:
if (!parser.opts.escape_proto_identifiers) {
for (auto it = parser.namespaces_.begin(); it != parser.namespaces_.end();
++it) {
for (auto comp = (*it)->components.begin(); comp != (*it)->components.end();
++comp) {
(*comp) = "_" + (*comp);
}
// Proto namespaces may clash with table names, escape the ones that were
// generated from a table:
for (auto it = parser.namespaces_.begin(); it != parser.namespaces_.end();
++it) {
auto &ns = **it;
for (size_t i = 0; i < ns.from_table; i++) {
ns.components[ns.components.size() - 1 - i] += "_";
}
}
@@ -72,12 +73,12 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
int num_includes = 0;
for (auto it = parser.included_files_.begin();
it != parser.included_files_.end(); ++it) {
if (it->second.empty())
continue;
auto basename = flatbuffers::StripPath(
flatbuffers::StripExtension(it->first));
if (basename != file_name) {
schema += "include \"" + basename + ".fbs\";\n";
num_includes++;
}
flatbuffers::StripExtension(it->second));
schema += "include \"" + basename + ".fbs\";\n";
num_includes++;
}
if (num_includes) schema += "\n";
#endif
@@ -90,7 +91,7 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
GenNameSpace(*enum_def.defined_namespace, &schema, &last_namespace);
GenComment(enum_def.doc_comment, &schema, nullptr);
schema += "enum " + enum_def.name + " : ";
schema += GenType(enum_def.underlying_type) + " {\n";
schema += GenType(enum_def.underlying_type, true) + " {\n";
for (auto it = enum_def.vals.vec.begin();
it != enum_def.vals.vec.end(); ++it) {
auto &ev = **it;
@@ -109,11 +110,13 @@ std::string GenerateFBS(const Parser &parser, const std::string &file_name) {
for (auto field_it = struct_def.fields.vec.begin();
field_it != struct_def.fields.vec.end(); ++field_it) {
auto &field = **field_it;
GenComment(field.doc_comment, &schema, nullptr, " ");
schema += " " + field.name + ":" + GenType(field.value.type);
if (field.value.constant != "0") schema += " = " + field.value.constant;
if (field.required) schema += " (required)";
schema += ";\n";
if (field.value.type.base_type != BASE_TYPE_UTYPE) {
GenComment(field.doc_comment, &schema, nullptr, " ");
schema += " " + field.name + ":" + GenType(field.value.type);
if (field.value.constant != "0") schema += " = " + field.value.constant;
if (field.required) schema += " (required)";
schema += ";\n";
}
}
schema += "}\n\n";
}

View File

@@ -20,7 +20,10 @@
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include "flatbuffers/code_generators.h"
#include <algorithm>
#if defined(FLATBUFFERS_CPP98_STL)
#include <cctype>
#endif // defined(FLATBUFFERS_CPP98_STL)
namespace flatbuffers {
@@ -67,6 +70,7 @@ struct LanguageParameters {
std::string accessor_prefix_static;
std::string optional_suffix;
std::string includes;
std::string class_annotation;
CommentConfig comment_config;
};
@@ -96,8 +100,8 @@ const LanguageParameters& GetLangParams(IDLOptions::Language lang) {
"",
"",
"",
"import java.nio.*;\nimport java.lang.*;\nimport java.util.*;\n"
"import com.google.flatbuffers.*;\n\n@SuppressWarnings(\"unused\")\n",
"import java.nio.*;\nimport java.lang.*;\nimport java.util.*;\nimport com.google.flatbuffers.*;\n",
"\n@SuppressWarnings(\"unused\")\n",
{
"/**",
" *",
@@ -128,7 +132,8 @@ const LanguageParameters& GetLangParams(IDLOptions::Language lang) {
"__p.",
"Table.",
"?",
"using System;\nusing FlatBuffers;\n\n",
"using global::System;\nusing global::FlatBuffers;\n\n",
"",
{
nullptr,
"///",
@@ -158,7 +163,7 @@ class GeneralGenerator : public BaseGenerator {
GeneralGenerator &operator=(const GeneralGenerator &);
bool generate() {
std::string one_file_code;
cur_name_space_ = parser_.namespaces_.back();
cur_name_space_ = parser_.current_namespace_;
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
@@ -191,7 +196,7 @@ class GeneralGenerator : public BaseGenerator {
}
if (parser_.opts.one_file) {
return SaveType(file_name_, *parser_.namespaces_.back(),
return SaveType(file_name_, *parser_.current_namespace_,
one_file_code, true);
}
return true;
@@ -204,13 +209,26 @@ class GeneralGenerator : public BaseGenerator {
if (!classcode.length()) return true;
std::string code;
code = code + "// " + FlatBuffersGeneratedWarning();
if (lang_.language == IDLOptions::kCSharp) {
code = "// <auto-generated>\n"
"// " + std::string(FlatBuffersGeneratedWarning()) + "\n"
"// </auto-generated>\n\n";
} else {
code = "// " + std::string(FlatBuffersGeneratedWarning()) + "\n\n";
}
std::string namespace_name = FullNamespace(".", ns);
if (!namespace_name.empty()) {
code += lang_.namespace_ident + namespace_name + lang_.namespace_begin;
code += "\n\n";
}
if (needs_includes) code += lang_.includes;
if (needs_includes) {
code += lang_.includes;
if (parser_.opts.gen_nullable) {
code += "\nimport javax.annotation.Nullable;\n";
}
code += lang_.class_annotation;
}
code += classcode;
if (!namespace_name.empty()) code += lang_.namespace_end;
auto filename = NamespaceDir(ns) + defname + lang_.file_extension;
@@ -225,20 +243,28 @@ class GeneralGenerator : public BaseGenerator {
: upper);
}
std::string GenNullableAnnotation(const Type& t) {
return lang_.language == IDLOptions::kJava
&& parser_.opts.gen_nullable
&& !IsScalar(DestinationType(t, true).base_type) ? " @Nullable ": "";
}
static bool IsEnum(const Type& type) {
return type.enum_def != nullptr && IsInteger(type.base_type);
}
std::string GenTypeBasic(const Type &type, bool enableLangOverrides) {
static const char *java_typename[] = {
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
#JTYPE,
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
};
static const char *csharp_typename[] = {
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
#define FLATBUFFERS_TD(ENUM, IDLTYPE, \
CTYPE, JTYPE, GTYPE, NTYPE, PTYPE) \
#NTYPE,
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
@@ -301,7 +327,7 @@ Type DestinationType(const Type &type, bool vectorelem) {
case BASE_TYPE_VECTOR:
if (vectorelem)
return DestinationType(type.VectorType(), vectorelem);
// else fall thru:
// else fall thru
default: return type;
}
}
@@ -348,7 +374,7 @@ std::string DestinationMask(const Type &type, bool vectorelem) {
case BASE_TYPE_VECTOR:
if (vectorelem)
return DestinationMask(type.VectorType(), vectorelem);
// else fall thru:
// else fall thru
default: return "";
}
}
@@ -587,6 +613,22 @@ std::string GenGetter(const Type &type) {
}
}
// Returns the function name that is able to read a value of the given type.
std::string GenGetterForLookupByKey(flatbuffers::FieldDef *key_field,
const std::string &data_buffer,
const char *num = nullptr) {
auto type = key_field->value.type;
auto dest_mask = DestinationMask(type, true);
auto dest_cast = DestinationCast(type);
auto getter = data_buffer + "." + FunctionStart('G') + "et";
if (GenTypeBasic(type, false) != "byte") {
getter += MakeCamel(GenTypeBasic(type, false));
}
getter = dest_cast + getter + "(" + GenOffsetGetter(key_field, num) + ")"
+ dest_mask;
return getter;
}
// Direct mutation is only allowed for scalar fields.
// Hence a setter method will only be generated for such fields.
std::string GenSetter(const Type &type) {
@@ -668,7 +710,7 @@ void GenStructBody(const StructDef &struct_def, std::string *code_ptr,
std::string GenByteBufferLength(const char *bb_name) {
std::string bb_len = bb_name;
if (lang_.language == IDLOptions::kCSharp) bb_len += ".Length";
else bb_len += ".array().length";
else bb_len += ".capacity()";
return bb_len;
}
@@ -699,12 +741,11 @@ std::string GenLookupKeyGetter(flatbuffers::FieldDef *key_field) {
key_getter += GenOffsetGetter(key_field);
key_getter += ", byteKey, bb);\n";
} else {
auto get_val = GenGetter(key_field->value.type) +
"(" + GenOffsetGetter(key_field) + ")";
auto get_val = GenGetterForLookupByKey(key_field, "bb");
if (lang_.language == IDLOptions::kCSharp) {
key_getter += "int comp = " + get_val + ".CompareTo(key);\n";
} else {
key_getter += GenTypeGet(key_field->value.type) + " val = ";
key_getter += GenTypeNameDest(key_field->value.type) + " val = ";
key_getter += get_val + ";\n";
key_getter += " int comp = val > key ? 1 : val < key ? -1 : 0;\n";
}
@@ -728,20 +769,17 @@ std::string GenKeyGetter(flatbuffers::FieldDef *key_field) {
key_getter += ";";
}
else {
auto field_getter = data_buffer + GenGetter(key_field->value.type).substr(2) +
"(" + GenOffsetGetter(key_field, "o1") + ")";
auto field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o1");
if (lang_.language == IDLOptions::kCSharp) {
key_getter += field_getter;
field_getter = data_buffer + GenGetter(key_field->value.type).substr(2) +
"(" + GenOffsetGetter(key_field, "o2") + ")";
field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o2");
key_getter += ".CompareTo(" + field_getter + ")";
}
else {
key_getter += "\n " + GenTypeGet(key_field->value.type) + " val_1 = ";
key_getter += field_getter + ";\n " + GenTypeGet(key_field->value.type);
key_getter += "\n " + GenTypeNameDest(key_field->value.type) + " val_1 = ";
key_getter += field_getter + ";\n " + GenTypeNameDest(key_field->value.type);
key_getter += " val_2 = ";
field_getter = data_buffer + GenGetter(key_field->value.type).substr(2) +
"(" + GenOffsetGetter(key_field, "o2") + ")";
field_getter = GenGetterForLookupByKey(key_field, data_buffer, "o2");
key_getter += field_getter + ";\n";
key_getter += " return val_1 > val_2 ? 1 : val_1 < val_2 ? -1 : 0;\n ";
}
@@ -845,7 +883,8 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
std::string dest_mask = DestinationMask(field.value.type, true);
std::string dest_cast = DestinationCast(field.value.type);
std::string src_cast = SourceCast(field.value.type);
std::string method_start = " public " + type_name_dest + optional + " " +
std::string method_start = " public " + GenNullableAnnotation(field.value.type) +
type_name_dest + optional + " " +
MakeCamel(field.name, lang_.first_camel_upper);
std::string obj = lang_.language == IDLOptions::kCSharp
? "(new " + type_name + "())"
@@ -993,6 +1032,26 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
code += lang_.accessor_prefix + "__vector_len(o) : 0; ";
code += lang_.getter_suffix;
code += "}\n";
// See if we should generate a by-key accessor.
if (field.value.type.element == BASE_TYPE_STRUCT &&
!field.value.type.struct_def->fixed) {
auto &sd = *field.value.type.struct_def;
auto &fields = sd.fields.vec;
for (auto kit = fields.begin(); kit != fields.end(); ++kit) {
auto &key_field = **kit;
if (key_field.key) {
code += " public " + sd.name + lang_.optional_suffix + " ";
code += MakeCamel(field.name, lang_.first_camel_upper) + "ByKey(";
code += GenTypeNameDest(key_field.value.type) + " key)";
code += offset_prefix;
code += sd.name + ".__lookup_by_key(";
code += lang_.accessor_prefix + "__vector(o), key, ";
code += lang_.accessor_prefix + "bb) : null; ";
code += "}\n";
break;
}
}
}
}
// Generate a ByteBuffer accessor for strings & vectors of scalars.
if ((field.value.type.base_type == BASE_TYPE_VECTOR &&
@@ -1023,28 +1082,24 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
}
}
// generate object accessors if is nested_flatbuffer
auto nested = field.attributes.Lookup("nested_flatbuffer");
if (nested) {
auto nested_qualified_name =
parser_.namespaces_.back()->GetFullyQualifiedName(nested->constant);
auto nested_type = parser_.structs_.Lookup(nested_qualified_name);
auto nested_type_name = WrapInNameSpace(*nested_type);
auto nestedMethodName = MakeCamel(field.name, lang_.first_camel_upper)
if (field.nested_flatbuffer) {
auto nested_type_name = WrapInNameSpace(*field.nested_flatbuffer);
auto nested_method_name = MakeCamel(field.name, lang_.first_camel_upper)
+ "As" + nested_type_name;
auto getNestedMethodName = nestedMethodName;
auto get_nested_method_name = nested_method_name;
if (lang_.language == IDLOptions::kCSharp) {
getNestedMethodName = "Get" + nestedMethodName;
get_nested_method_name = "Get" + nested_method_name;
conditional_cast = "(" + nested_type_name + lang_.optional_suffix + ")";
}
if (lang_.language != IDLOptions::kCSharp) {
code += " public " + nested_type_name + lang_.optional_suffix + " ";
code += nestedMethodName + "() { return ";
code += getNestedMethodName + "(new " + nested_type_name + "()); }\n";
code += nested_method_name + "() { return ";
code += get_nested_method_name + "(new " + nested_type_name + "()); }\n";
} else {
obj = "(new " + nested_type_name + "())";
}
code += " public " + nested_type_name + lang_.optional_suffix + " ";
code += getNestedMethodName + "(";
code += get_nested_method_name + "(";
if (lang_.language != IDLOptions::kCSharp)
code += nested_type_name + " obj";
code += ") { int o = " + lang_.accessor_prefix + "__offset(";
@@ -1127,7 +1182,9 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
num_fields++;
}
}
if (has_no_struct_fields && num_fields) {
// JVM specifications restrict default constructor params to be < 255.
// Longs and doubles take up 2 units, so we set the limit to be < 127.
if (has_no_struct_fields && num_fields && num_fields < 127) {
// Generate a table constructor of the form:
// public static int createName(FlatBufferBuilder builder, args...)
code += " public static " + GenOffsetType(struct_def) + " ";
@@ -1279,7 +1336,9 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
code += "); }\n";
}
}
if (struct_def.has_key) {
// Only generate key compare function for table,
// because `key_field` is not set for struct
if (struct_def.has_key && !struct_def.fixed) {
if (lang_.language == IDLOptions::kJava) {
code += "\n @Override\n protected int keysCompare(";
code += "Integer o1, Integer o2, ByteBuffer _bb) {";
@@ -1288,7 +1347,8 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
}
else {
code += "\n public static VectorOffset ";
code += "CreateMySortedVectorOfTables(FlatBufferBuilder builder, ";
code += "CreateSortedVectorOf" + struct_def.name;
code += "(FlatBufferBuilder builder, ";
code += "Offset<" + struct_def.name + ">";
code += "[] offsets) {\n";
code += " Array.Sort(offsets, (Offset<" + struct_def.name +
@@ -1298,8 +1358,8 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
}
code += "\n public static " + struct_def.name + lang_.optional_suffix;
code += " " + FunctionStart('L') + "ookupByKey(" + GenVectorOffsetType();
code += " vectorOffset, " + GenTypeGet(key_field->value.type);
code += " __lookup_by_key(int vectorLocation, ";
code += GenTypeNameDest(key_field->value.type);
code += " key, ByteBuffer bb) {\n";
if (key_field->value.type.base_type == BASE_TYPE_STRING) {
code += " byte[] byteKey = ";
@@ -1308,13 +1368,9 @@ void GenStruct(StructDef &struct_def, std::string *code_ptr) {
else
code += "System.Text.Encoding.UTF8.GetBytes(key);\n";
}
code += " int vectorLocation = " + GenByteBufferLength("bb");
code += " - vectorOffset";
if (lang_.language == IDLOptions::kCSharp) code += ".Value";
code += ";\n int span = ";
code += "bb." + FunctionStart('G') + "etInt(vectorLocation);\n";
code += " int span = ";
code += "bb." + FunctionStart('G') + "etInt(vectorLocation - 4);\n";
code += " int start = 0;\n";
code += " vectorLocation += 4;\n";
code += " while (span != 0) {\n";
code += " int middle = span / 2;\n";
code += GenLookupKeyGetter(key_field);

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