Compare commits

..

170 Commits

Author SHA1 Message Date
Wouter van Oortmerssen
20a400e940 Update version number to 1.9
Change-Id: I0b0ed43129c4d8fc88a177792df50adfeb52a1e3
2018-04-05 15:11:52 -07:00
Wouter van Oortmerssen
676f0248aa Added missing generated code files.
Change-Id: I59af6ca1825870461c0badc7e7a045b97befdc1a
2018-04-05 15:01:35 -07:00
Kamil Rojewski
34b8b80f15 Missing TS links in docs (#4693)
* 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

* Fix for strictPropertyInitialization

* Fix for new aligned operator new for gcc >= 7.1

* Not generating imports/ns prefixes with --gen-all

* TypeScript docs

* Missing imports of enums

* Missing TS links
2018-04-05 09:54:37 -07:00
Juyeon Yoon
0998861e0f Remove line break of CMakeLists.txt (#4691)
Fix #4650
2018-04-05 09:17:33 -07:00
David Stephan
2e3d3cbcb5 Fix typos in C++ tutorial (#4685)
CreateMonster and MonsterBuilder examples fixed for C++
2018-04-02 09:25:05 -07:00
Kamil Rojewski
d3a00f7730 Fix for missing enum imports (#4683)
* 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

* Fix for strictPropertyInitialization

* Fix for new aligned operator new for gcc >= 7.1

* Not generating imports/ns prefixes with --gen-all

* TypeScript docs

* Missing imports of enums
2018-03-26 10:29:45 -07:00
Kamil Rojewski
cc54963830 TypeScript docs (#4680)
* 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

* Fix for strictPropertyInitialization

* Fix for new aligned operator new for gcc >= 7.1

* Not generating imports/ns prefixes with --gen-all

* TypeScript docs
2018-03-23 09:01:39 -07:00
Flaviu
79f62ee353 Const correctness in generated code and in code generators. Added missing \reflection\generate_code.bat file. (#4679) 2018-03-23 08:58:07 -07:00
Andreas Bergmeier
c0a6e5120d [C++, Go, Bazel]: Fix up Bazel support (#4672)
* Add Bazel support for Go library

* Make flatc compile again.

Was missing java_generator, which is now referenced from source.
2018-03-15 12:31:16 -07:00
Robert Schmidtke
08cf50c54a Java/C#/Python prefixed size support (#4445)
* initial changes to support size prefixed buffers in Java

* add slice equivalent to CSharp ByteBuffer

* resolve TODO for slicing in CSharp code generation

* add newly generated Java and CSharp test sources

* fix typo in comment

* add FinishSizePrefixed methods to CSharp FlatBufferBuilder as well

* add option to allow writing the prefix as well

* generate size-prefixed monster binary as well

* extend JavaTest to test the size prefixed binary as well

* use constants for size prefix length

* fuse common code for getRootAs and getSizePrefixedRootAs

* pulled file identifier out of if

* add FinishSizePrefixed, GetSizePrefixedRootAs support for Python

* Revert "extend JavaTest to test the size prefixed binary as well"

This reverts commit 68be4420dd.

* Revert "generate size-prefixed monster binary as well"

This reverts commit 2939516fdf.

* fix ByteBuffer.cs Slice() method; add proper CSharp and Java tests

* fix unused parameter

* increment version number

* pulled out generated methods into separate utility class

* pulled out generated methods into separate utility class for Python

* fix indentation

* remove unnecessary comment

* fix newline and copyright

* add ByteBufferUtil to csproj compilation

* hide ByteBuffer's internal data; track offset into parent's array

* test unsafe versions as well; compile and run in debug mode

* clarify help text for size prefix

* move ByteBuffer slicing behavior to subclass

* fix protection levels

* add size prefix support for text generation

* add ByteBufferSlice to csproj compilation

* revert size prefix handling for nested buffers

* use duplicate instead of slice for removing size prefix

* remove slice subclass and use duplicate for removing size prefix

* remove slice specific tests

* remove superfluous command line option
2018-03-12 11:30:46 -07:00
Sergey Avseyev
6b3f057bdc Remove unnecessary const qualifier from cast (#4666)
Const does not make sense here, and compiler actually throws warning
(error with -Werror) when you would try to compile it.

    In file included from include/flatbuffers/flexbuffers.h:24,
                     from include/flatbuffers/idl.h:26,
                     from include/flatbuffers/code_generators.h:22,
                     from src/code_generators.cpp:17:
    include/flatbuffers/util.h: In function ‘int flatbuffers::FromUTF8(const char**)’:
    include/flatbuffers/util.h:325:44: error: type qualifiers ignored on cast result type [-Werror=ignored-qualifiers]
       if ((static_cast<const unsigned char>(tmp) << len) & 0x80) return -1;  // Bit after leading 1's must be 0.
                                            ^
    cc1plus: all warnings being treated as errors

This warning caught by gcc8:

    $ g++ --version
    g++ (GCC) 8.0.1 20180222 (Red Hat 8.0.1-0.16)
2018-03-12 08:22:17 -07:00
ianXian
60de374486 Convert to unsigned char before applying bit shift operator (#4664)
* Convert to unsigned char before applying bit shift operator

* convert to const unsigned char inline

* convert to unsigned char inline
2018-03-09 09:45:47 -08:00
desqaz
e78825e7a0 Json : Add --size-prefixed option to flatc (#4645)
to be able to convert to json size prefixed buffers.
2018-03-09 08:21:28 -08:00
Montoli
cc158e7009 Swapped the order of two conditions in an assert. (#4663)
An assert in flexbuffers was bit-shifting a 64-bit number by
64 bits, which throws up warnings in some automated tools.

The same assert also checks to see if the number of bytes
being shifted is 8.  Swapped the order, so that the bitshift
only occurs if the number of bits being shifted is not 64.

Should be the same behavior, but plays nicer with diagnostic
tools.
2018-03-08 14:18:41 -08:00
desqaz
5377957b14 Update .gitignore with Ninja stuff (#4659) 2018-03-08 10:36:27 -08:00
Wouter van Oortmerssen
4bc6de9a88 Fix broken Java/C# codegen 2018-03-05 16:37:04 -08:00
Wouter van Oortmerssen
3a62813f0e Added missing generated code files.
Change-Id: Ie1cab284cb6e0fe5bd2b2c293c3136c148927ac3
2018-03-05 15:47:16 -08:00
Nik Hemmings
fb94af8899 Protobufs: Added '--oneof-union' option. (#4647)
* Added '--oneof-union' option.

Used with the .proto -> .fbs converter, will translate protobuff oneofs to flatbuffer unions.
Updated proto test to check both methods of converting oneofs.

* Added '--oneof-union' option.

Used with the .proto -> .fbs converter, will translate protobuff oneofs to flatbuffer unions.
Updated proto test to check both methods of converting oneofs.

* FlatBuffers: Moved MakeCamel() into idl_parser.cpp

Removes library dependency on Java/C# generator code.
2018-03-05 08:45:25 -08:00
smillius
77b458bee5 Make nested flatbuffer lookup consistent. (#4656)
Lookup type of nested flatbuffer field with either raw name or fully qualified name as already done in the parser.
LookupCreateStruct tries both the raw name and the fully qualified one.
Without this, we cannot reference types outside of the current namespace, e.g. in a different module.
2018-03-05 08:44:14 -08:00
Christian Helmich
9ce98dd77d Support attribute "cpp_ptr_type" on table elements marked as "hash" (#4643)
* added intended use-cases to monster_test.fbs

* added check for `cpp_ptr_type` on hashed fields
added default value 'naked' to `cpp_ptr_type` on hashed fields

* added C++ generation of cpp_type vectors
removed ctor call for vector fields
added condition !vector for cpp_type check
added Pack() and UnPack() code generation for vector of hashes
added generation of correct resolve/rehash for cpp_type elements

* added attribute 'cpp_ptr_type_get' to hold accessor for pointer types possible where '.get()' does not work
use case: cpp_ptr_type:"std::weak_ptr", cpp_ptr_type_get:".lock().get()"

* run flatc to re-generate headers

* added bool param is_ctor to GetDefaultScalarValue() to differentiate between usage places

* modified monster_test.fbs to remove usage of shared_ptr/weak_ptr
reason: STLport does not support std::shared_ptr and std::weak_ptr

* run flatc again to re-generate headers

* fixed symbol unique_ptr not in namespace std when building with STLport
2018-03-05 08:40:55 -08:00
Mitchel
4ea1be53d4 Java + C#, reuse object in lookup_by_key (#4648)
* Java + C#, reuse object in lookup_by_key

* Java + C#, reuse object in lookup_by_key
2018-03-02 15:22:46 -08:00
Mitchel
0068b25132 Fix for Java infinite loop encoding into 0-sized buffer (#4654) 2018-03-02 15:21:08 -08:00
Christian Helmich
ec74f58b94 made HashFnv functions constexpr (#4640)
* added FLATBUFFERS_CONSTEXPR_CPP14 define for C++14 and above constexpr

* made HashFnv functions constexpr (depending on FLATBUFFERS_CONSTEXPR)
2018-03-02 09:13:55 -08:00
Kamil Rojewski
48d8232584 Not generating imports/ns prefixes with --gen-all (#4644)
* 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

* Fix for strictPropertyInitialization

* Fix for new aligned operator new for gcc >= 7.1

* Not generating imports/ns prefixes with --gen-all
2018-02-26 08:56:04 -08:00
Mitchel
55ddb84eb2 In Java, allow reusing ByteBuffer in getters (#4633)
* In Java, allow reusing ByteBuffer in getters

* In Java, allow reusing ByteBuffer in getters

* In Java, allow reusing ByteBuffer in getters
2018-02-23 14:01:05 -08:00
Christian Helmich
6e2e909b5c template specialized Hash functions for 16-bit hash types (#4631)
added access to HashFunction for 16 bit
2018-02-23 10:29:37 -08:00
Philip S Doctor
b24c0b07a3 When Java raises a CharacterCodingException, the catch block rethrows this exception as a java.lang.Error. Per the docs https://docs.oracle.com/javase/8/docs/api/java/lang/Error.html an Error is a serious problem that applications should not attempt to catch such as ThreadDeath. In this case, it is reasonable for a consumer to try to catch this error as it likely indicates a problem with the underlying data. (#4630)
As Error does not inherit from Exception, a generic `catch(Exception ex)` will not catch this error.

A simple change from `Error` to `Exception` is not sufficient as an `Exception` is checked by the compiler, so in order to keep this issue unchecked, I am proposing raising a `RuntimeException` which is not checked, but is still a subclass of `Exception`.

The only possible breaking change would be if a consumer was explicitly catching `Error` already for this library.

https://github.com/google/flatbuffers/issues/4629
2018-02-22 14:54:35 -08:00
Christian Helmich
59e26017cb added support for parsing hash on vector elements (#4502)
* added support for parsing hash on vector elements

reversed check for scalar to check for vector

added C++ generation of cpp_type vectors

removed ctor call for vector fields
added condition !vector for cpp_type check

added Pack() and UnPack() code generation for vector of hashes

* schema change:
added table Referrable and weak references towards it from Monster

added single_weak_reference to Monster table
changed order with vector_of_weak_references

* re-generated monster schema dependent code

added Referrable.cs to FlatBuffers.Test.csproj
2018-02-22 11:04:26 -08:00
desqaz
132e6a8220 Add new c++ helpers to ease usage of size prefixed FlatBuffers (#4626)
It was missing some helpers when we choose to use
size prefixed FlatBuffers.

* Add general helper : GetPrefixedSize
* Add generated helpers :
 * GetSizePrefixedXXX
 * VerfifySizePrefixedXXXBuffer
 * FinishSizePrefixedXXXBuffer
2018-02-22 09:19:08 -08:00
Masato Nagai
19c81b11b3 [C++] better type mismatch error (#4623)
* better parse error

* pass str as a pointer instead of a reference for more efficient performance
2018-02-16 08:32:50 -08:00
Alexander Gallego
36f8564846 C++: mini_reflect: Add DefaultTypeTable (#4614)
* mini_reflect: Add DefaultTypeTable

Currently it's very easy to make a mistake when it comes to
instantiating the TypeTable to print a buffer because it is not type
safe.

This will allow us to write safer cpp code:

flatbuffers::FlatBufferToString(reinterpret_cast<const uint8_t *>(&t),
                                decltype(t)::DefaultTypeTable());

* c++: mini_reflect: update generated code

* Ensure types and names are set for mini_reflect

* c++: mini_refelct: update unit tests with new typed TypeTable

* Adding PR feedback of sylte and naming convention
2018-02-15 14:58:06 -08:00
Dmitry Volosnykh
daf0a420be Support version compatibility checks via find_package command (#4625) 2018-02-15 13:39:15 -08:00
Kamil Rojewski
474ba68bba Fix for aligned new for gcc >= 7.1 (#4621)
* 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

* Fix for strictPropertyInitialization

* Fix for new aligned operator new for gcc >= 7.1
2018-02-12 08:37:51 -08:00
vglavnyy
9de0861104 Fix vector_data failure under debug (#4606) 2018-02-08 15:15:17 -08:00
Wouter van Oortmerssen
b513db86c7 Misc fixes from internal integration / clang tidy.
Change-Id: Ic5e8f6a423b426abb9f8b90d39db0f85f28b94be
Tested: on Linux.
2018-02-08 14:58:16 -08:00
Sergey Avseyev
6a1acdc23b Fix compiler errors in parser (#4612)
src/idl_parser.cpp: In member function 'flatbuffers::CheckedError flatbuffers::Parser::ParseHexNum(int, uint64_t*)':
src/idl_parser.cpp:220:62: error: type qualifiers ignored on cast result type [-Werror=ignored-qualifiers]
     if (!isxdigit(static_cast<const unsigned char>(cursor_[i])))
                                                              ^
src/idl_parser.cpp: In member function 'flatbuffers::CheckedError flatbuffers::Parser::Next()':
src/idl_parser.cpp:260:62: error: type qualifiers ignored on cast result type [-Werror=ignored-qualifiers]
         if(!isdigit(static_cast<const unsigned char>(*cursor_))) return NoError();
                                                              ^
cc1plus: all warnings being treated as errors
2018-02-05 12:04:55 -08:00
Joe Schafer
c696422558 Add initial Bazel WORKSPACE and BUILD (#4608)
For #4574.

To test:

    bazel test --verbose_failures //:flatbuffers_test
2018-02-05 10:23:15 -08:00
Wouter van Oortmerssen
e93d2bda07 Cleaned up & fixed buffer alignment handling.
- Fixed ForceVectorAlignment (and possibly other call-sites) not
  setting minalign_.
- Fixed flipped alignment parameters in CopyTable (reflection).
- Made aligment for FlatBufferBuilder internal buffer configurable
  (useful when reading a constructed buffer directly).
- Ensured Alignment rounding is always up.

Change-Id: I33ca4887d92a09cb11a369c14a109f4b07ae707a
Tested: on Linux.
2018-01-29 11:46:30 -08:00
Wouter van Oortmerssen
bbf4dac6a3 Made doubles output with higher precision in JSON and elsewhere.
Change-Id: I5dd8f3a7c315c40b86a67aba5c2cca4d36363523
Tested: on Linux.
2018-01-22 10:24:45 -08:00
Wouter van Oortmerssen
8df2d9a3ef Removed truncating of enum vals to int in ReverseLookup.
Some implementations (e.g. C++98) won't support 64-bit enum values,
but there is no reason to silently truncate them.

Change-Id: I8629563523a96e887068f9c0efcd53741f60e0d6
Tested: on Linux.
2018-01-22 09:51:17 -08:00
Li-Deng
462ce03ebe Fix the spell mistake (#4599) 2018-01-22 09:08:13 -08:00
Wouter van Oortmerssen
020012e69c Fixed native_include not requiring a ; terminator.
Change-Id: Ic4f49e94c67ba23f07e5ba7e87ca94e8db5d5906
Tested: on Linux.
2018-01-22 09:06:13 -08:00
Wouter van Oortmerssen
f431a96523 New error: declaring an enum field without a default in range of the enum.
Change-Id: I4db7f032440c00d31c7434975b8a3f17c29d74b9
Tested: on Linux.
2018-01-18 12:06:01 -08:00
Wouter van Oortmerssen
3694ae0817 Disallow defaults on structs.
Change-Id: Ia098126c92ea6f8abe94561bd9c09b29ac8f61f5
Context: https://github.com/google/flatbuffers/issues/4591
Tested: on Linux.
2018-01-18 11:41:43 -08:00
Wouter van Oortmerssen
2265129e14 Removed date/time from generated code, causing commit polution.
Change-Id: I79724416110a3d2241d7eeecf0e12aa6d5b760a0
2018-01-18 11:21:10 -08:00
Wouter van Oortmerssen
4bddc6cc0c Added missing generated code.
Change-Id: I9420bf01d2bdb6ccfe3703c835297be73457c0d7
2018-01-18 11:20:58 -08:00
vglavnyy
e162366b3f Removed internal variable with name "data" inside a generated method _nested_root(). Local variable with name "data" violates [-Werror=shadow]. (#4587) 2018-01-18 11:15:31 -08:00
Wouter van Oortmerssen
fee9afd80b Use CreateVectorOfStructs when creating a vector of structs.
(mirrored from cl/180944741)

Change-Id: Ib9f1613ccc355528c5c495fd953a9b3944ecb4ce
2018-01-18 11:07:37 -08:00
Daniel Lin
98f681deb0 Author: Daniel Lin <danielin@umich.edi> (#4595)
Date:   Mon Jan 15 11:38:20 2018 -0200

Compilation failure with grpc.h

If cmake run with flag FLATBUFFERS_BUILD_GRPCTEST=ON
compilation fails.

Fix :
	-Fix argument list for overriden function in grpc.
	-Fix member function name called by FlatBufferBuilder from
	buf() to scratch_data()
2018-01-18 08:51:57 -08:00
Wouter van Oortmerssen
5cee340ad3 Cleaned up FlatBufferBuilder clearing.
Change-Id: I81cf4d268670bdd11d1d56ca9f2de78c120df842
Tested: on Linux.
2018-01-16 10:17:20 -08:00
Uilian Ries
f0769b60ab #4522 Conan package support (#4590)
- Added Conan recipe to build Flatbuffers
- Added Travis job to create Conan package

Signed-off-by: Uilian Ries <uilianries@gmail.com>
2018-01-12 08:18:20 -08:00
Wouter van Oortmerssen
79b80f84df Reduced FlatBufferBuilder from 3 buffers to 1
Previously, FlatBufferBuilder used 3 resizable buffers:
- serialization (vector_downward)
- field offsets (std::vector)
- vtable offsets (std::vector)

Since the serialization buffer grows downwards, the bottom part of
it can be used as a "scratchpad" storage for the other two. Since
field offsets are only accumulated during table construction, and
vtable offsets only after table construction, the two can trivially
share the same storage.

Not only does this reduce the amount of allocation, it also removes
the bulk of std::vector usage from FlatBufferBuilder which was
the #1 cause of slow-down in debug mode, see e.g.:
https://stackoverflow.com/questions/36085285/any-way-to-improve-flatbuffer-performance-in-debug-c-msvc

Change-Id: I0224cf2f2a863d2d7ef762bc9163b52fdc149522
Tested: on Linux.
2018-01-11 11:13:23 -08:00
Andrew Gunnerson
dfe68566e4 Add char * overload for FlatBufferBuilder::CreateString() (#4583)
Without this change, the compiler tries to select the following overload
when CreateString is passed a `char *`:

    template<typename T>
    Offset<String> CreateString(const T &str) {
      return CreateString(str.c_str(), str.length());
    }

which is not valid since char pointers don't have methods.

(Fixes #4579)

Signed-off-by: Andrew Gunnerson <chenxiaolong@cxl.epac.to>
2018-01-08 08:26:19 -08:00
brianhall77
0aa36101f4 Portable range check for *cursor_ value. (#4582)
Avoids the following compile error when char is unsigned:

error: comparison of unsigned expression >= 0 is always true [-Werror,-Wtautological-unsigned-zero-compare]
2018-01-04 16:03:03 -08:00
vglavnyy
70f345012d GenerateText generate a text string for default identifier of enum and float scalar. An enum identifier printed as the strictly quoted string. (#4527) 2018-01-04 10:12:18 -08:00
Andrei Polushin
a056402f56 Remove unused declarations (#4578) 2018-01-04 10:01:41 -08:00
Darío Hereñú
d7b1d418ee Update URL (#4576) 2018-01-04 09:10:03 -08:00
Bastien Brunnenstein
9dae3eac60 Fix error in ConCatPathFileName (#4575) 2018-01-04 09:09:09 -08:00
Yuri Finkelstein
99a8a68a80 new maven jar called flatbuffers-java-grpc which contains utility … (#4558)
* new maven jar called flatbuffers-java-grpc which contains utility class supporting generated code for grpc over flatbuffers; grpc java unit test based on maven and junit (maven is used only for simplicity of testing); removed straneous namespace_test/NamespaceA/TableInC.java which is not longer used in the test and no longer generated but contains complilation errors if java compiler picks it up

* moved java grpc tests files according to review request

* Added missing generated code for Java gRPC.

Change-Id: Iada090fe2e99b80a4b7c2f8e39c838a992a1feae

* added missing name and url
2017-12-28 15:26:29 -08:00
Wouter van Oortmerssen
0c86929e39 Added missing nullptr check in vector of union verifiers.
Change-Id: Iec720991e68ad27580537135bfd8eb4159333921
Tested: on Linux.
2017-12-28 10:09:48 -08:00
Wouter van Oortmerssen
b24f2016a1 Disabled python in travis.yml pending fix.
Change-Id: I6d2a9cc8b32c531d4a1e272ddf29974a0a1a2ee3
2017-12-28 09:56:57 -08:00
Josh Ventura
1d73b3b9fc Various build fixes; update checked-in codegen. (#4572) 2017-12-28 09:10:55 -08:00
Yuri Finkelstein
a4dbe13486 fixed java codegen bug documented in #4563 (#4565)
* grpc bindings generator for Java and a few minor supporting changes in improvements

* restored formatting before my previous changes for ease of review

* Fixed grpc java code generation bug resulting in duplicate extractor declarations in case the same is used in more than a single RPC method

* fixed previous merge issue

* removed extra space

* restored extra space

* restored extra space

* fixed java codegen bug documented in https://github.com/google/flatbuffers/issues/4563
2017-12-21 13:32:34 -08:00
Wouter van Oortmerssen
89711c9c47 Made all C++ files clang-formatted.
Also added missing generated files.

Change-Id: Ifd22a643a08e3f2edfce92812ed57b87fc0e1875
2017-12-21 11:45:02 -08:00
Yuri Finkelstein
5d9930aa0d added config files for popular formatting tools (#4554)
* added config files for popular formatting tools

* edited and moved formatting files to root per review suggestion
2017-12-21 10:18:20 -08:00
Yuri Finkelstein
8518b3fb4e grpc bindings generator for Java and a few minor supporting changes i… (#4553)
* grpc bindings generator for Java and a few minor supporting changes in improvements

* restored formatting before my previous changes for ease of review

* Fixed grpc java code generation bug resulting in duplicate extractor declarations in case the same is used in more than a single RPC method
2017-12-21 09:55:57 -08:00
Yuri Finkelstein
61f4a46c43 synchronized grpc cpp_generator with latest version as of today: grpc-1.8.1. (#4556)
* updateed cpp_generator.cc to be compatible with the latest grpc version

* preserved the original license

* synchronized grpc cpp_generator with latest version as of today: GRPC 1.8.1. Regenerated test/monster_test.grpc.fb.* files and verified that grpctest is nicely passing

* fixed merge glitch
2017-12-21 08:49:00 -08:00
Yuri Finkelstein
dd73b53e28 updated cpp_generator.cc to be compatible with the latest grpc version (#4551)
* updateed cpp_generator.cc to be compatible with the latest grpc version

* preserved the original license
2017-12-18 14:17:59 -08:00
xgdgsc
c1901f2c01 update mutation status in doc (#4549) 2017-12-18 09:14:15 -08:00
Robert
4071b6f68b Merge pull request #4516 from mikeholler/travis
Add support for Python lib continuous deployment.
2017-12-14 13:20:18 -08:00
Kamil Rojewski
142401f50a Fix for strictPropertyInitialization for TS (#4540)
* 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

* Fix for strictPropertyInitialization
2017-12-14 08:30:02 -08:00
Mike Holler
7799642270 Change mikeholler to PYPI_USERNAME 2017-12-13 15:14:01 -06:00
Wouter van Oortmerssen
67b29d4e43 Fixed CreateStruct not testing for nesting.
Change-Id: I16bf46682ad68c62b778ed1514b6b706c8cb8f6f
Tested: on Linux.
2017-12-07 11:16:19 -08:00
Bastien Brunnenstein
85b131a719 Replace the non standard M_PI with a constant (#4528) 2017-12-04 15:06:13 -08:00
Paul Taylor
0e8a21854c publish additional js/flatbuffers.mjs to npm to support ESModules in node (#4504) 2017-12-01 14:18:43 -08:00
rmawatson
53a897731e this is allow custom allocator for obj-api structs/tables. (#4520)
added "native_custom_alloc" attribute to tables/structs, eg.

table parent_table( native_custom_alloc:"custom_alloc_name" ) {
...
}

with a custom allocator defined as

template <typename T> class custom_alloc_name : public std::allocator<T> {
public:

 typedef T*       pointer;

 template <class U>
 struct rebind {
  typedef custom_alloc_name<U> other;
 };

 pointer allocate(const std::size_t n) {
      return ....;
 }

 void deallocate(T* ptr, std::size_t n) {
    ...
 }

 custom_alloc_name() throw() {}
 template <class U> custom_alloc_name(const custom_alloc_name<U>&) throw() {}
};
};
2017-12-01 09:15:41 -08:00
Bastien Brunnenstein
ba08b0ec02 Add include directory to CMake install targets (#4510) 2017-11-30 08:45:58 -08:00
Mike Holler
da0bda6be3 Fixed prod PyPI URL and deploy block list. 2017-11-27 16:10:43 -06:00
Mike Holler
617bbc9b0c Added all_branches to tags: true block 2017-11-27 13:59:01 -06:00
Michael Holler
0c8b4c7614 Add support for Python lib continuous deployment.
Use a combination of travis and twine to publish to PyPI. New
publications will be made:

* When `master` is updated. This will trigger the publication of a
  the Python artifact versioned an iso-compliant build datetime. In this
  way, the cutting edge version will always be available via PyPI.
* When a new git tag is pushed. Tag pushes trigger the publication of
  a python artifact with the same version as the git tag, with the
  leading `v` stripped if present (`v1.2.3` becomes `1.2.3`).

Publications rely on Travis having a PYPI_PASSWORD environment set in
the project settings. See the Travis CI documentation for information on
[setting environment variables which containing sensitive data][1]. Make
extra sure the "Display value in build log" switch is OFF.

In addition to setting the previously mentioned `PYPI_PASSWORD`
environment variable, the owner of the PyPI `flatbuffers` repository
should, after merging this commit into master, add his own commit to
change `mikeholler` in `.travis/deploy-python.sh` to his username. It's
also recommended that the owner of `flatbuffers` use a separate account
in the unlikely event that the environment variable somehow becomes
compromised. Again, this is very unlikely, since the environment
variable is only set for "safe" builds approved by maintainers (not on
random pull requests).

[1]: https://docs.travis-ci.com/user/environment-variables/#Defining-Variables-in-Repository-Settings
2017-11-27 13:14:33 -06:00
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
208 changed files with 22456 additions and 8216 deletions

13
.clang-format Normal file
View File

@@ -0,0 +1,13 @@
---
Language: Cpp
BasedOnStyle: Google
DerivePointerAlignment: false
PointerAlignment: Right
IndentPPDirectives: AfterHash
Cpp11BracedListStyle: false
AlwaysBreakTemplateDeclarations: false
AllowShortCaseLabelsOnASingleLine: true
SpaceAfterTemplateKeyword: false
AllowShortBlocksOnASingleLine: true
...

7
.editorconfig Normal file
View File

@@ -0,0 +1,7 @@
root = true
[*.{cpp,cc,h}]
end_of_line = LF
indent_style = space
indent_size = 2
insert_final_newline = true

0
.gitattributes vendored Executable file → Normal file
View File

21
.gitignore vendored Executable file → Normal file
View File

@@ -5,6 +5,7 @@
*.o.d
*.class
*.a
*.swp
*~
*.vcxproj
*.vcxproj.filters
@@ -43,15 +44,19 @@ flatsampletext.exe
grpctest
grpctest.exe
snapshot.sh
tags
tests/go_gen
tests/monsterdata_java_wire.mon
tests/monsterdata_java_wire_sp.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
FlatbuffersConfigVersion.cmake
FlatBuffers.cbp
build/Xcode/FlatBuffers.xcodeproj/project.xcworkspace/**
build/Xcode/FlatBuffers.xcodeproj/xcuserdata/**
@@ -72,3 +77,19 @@ Testing/Temporary
.project
net/**/obj
node_modules/
android/.externalNativeBuild/
android/.gradle/
android/build/
samples/android/.externalNativeBuild/
samples/android/.gradle/
samples/android/build/
js/flatbuffers.mjs
/bazel-bin
/bazel-flatbuffers
/bazel-genfiles
/bazel-out
/bazel-testlogs
.ninja_deps
.ninja_log
build.ninja
rules.ninja

View File

@@ -1,31 +1,83 @@
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: python
# python: "2.7"
# install:
# - "pip install wheel twine"
# script:
# - "cd python/"
# - 'VERSION="$TRAVIS_TAG" python setup.py sdist bdist_wheel'
# - "cd ../"
# deploy:
# # Checkpointed release builds.
# - provider: script
# script: .travis/deploy-python.sh
# skip_cleanup: true
# on:
# tags: true
# # all_branches must be set with tags: true. See below post:
# # https://stackoverflow.com/a/27775257/1076585
# all_branches: true
# # Produce a new build for the cutting edge when master changes.
# - provider: script
# script: .travis/deploy-python.sh
# skip_cleanup: true
# on:
# branch: master
- language: cpp
os:
- linux
- osx
before_install:
- 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
compiler:
- gcc
#- clang
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
env:
matrix:
- BUILD_TYPE=Debug BIICODE=false
- BUILD_TYPE=Release BIICODE=false CONAN=true
# biicode .deb files no longer available.
# - BUILD_TYPE=Release BIICODE=true
# - BUILD_TYPE=Debug BIICODE=true
before_install:
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq g++-$GCC_VERSION; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq gcc-$GCC_VERSION; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which g++-$GCC_VERSION) /usr/bin/g++; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
script:
- if [ "$BIICODE" == "false" ]; then cmake -DCMAKE_BUILD_TYPE=$BUILD_TYPE . && make && make test; fi
- if [ "$BIICODE" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then ./biicode/support/bii-travis.sh $BUILD_TYPE; fi
- if [ "$CONAN" == "true" ] && [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo pip install conan && conan create . flatbuffers/testing -s build_type=$BUILD_TYPE; fi
- language: android
sudo: true
android:
components:
- tools
- platform-tools
- build-tools-25.0.2
- android-25
- extra-android-m2repository
compiler:
- gcc
before_install:
- git clone https://github.com/urho3d/android-ndk.git $HOME/android-ndk-root
- export ANDROID_NDK_HOME=$HOME/android-ndk-root
# Setup environment for Linux build which is required to build the sample.
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get update -qq; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq g++-$GCC_VERSION; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo apt-get install -qq gcc-$GCC_VERSION; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which g++-$GCC_VERSION) /usr/bin/g++; fi
- if [ "$TRAVIS_OS_NAME" == "linux" ]; then sudo ln -s -v -f $(which gcc-$GCC_VERSION) /usr/bin/gcc; fi
script:
- failed=0; for build_gradle in $(git ls-files | grep build.gradle); do ( cd "$(dirname "${build_gradle}")" && ./gradlew build ) || failed=1; done; exit $((failed))

12
.travis/deploy-python.sh Executable file
View File

@@ -0,0 +1,12 @@
#!/bin/bash
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
PROD_REPOSITORY="https://upload.pypi.org/legacy/"
TEST_REPOSITORY="https://test.pypi.org/legacy/"
twine upload \
--username "$PYPI_USERNAME" \
--password "$PYPI_PASSWORD" \
--repository-url "$PROD_REPOSITORY" \
"$DIR/../python/dist/"*

145
BUILD Normal file
View File

@@ -0,0 +1,145 @@
package(
default_visibility = ["//visibility:public"],
features = [
"-layering_check",
"-parse_headers",
],
)
exports_files([
"LICENSE",
])
FLATBUFFERS_COPTS = [
"-Wno-implicit-fallthrough",
"-linclude",
]
# Public flatc library to compile flatbuffer files at runtime.
cc_library(
name = "flatbuffers",
srcs = [
"src/code_generators.cpp",
"src/idl_gen_fbs.cpp",
"src/idl_gen_general.cpp",
"src/idl_gen_text.cpp",
"src/idl_parser.cpp",
"src/reflection.cpp",
"src/util.cpp",
],
hdrs = [":public_headers"],
copts = FLATBUFFERS_COPTS,
includes = ["include/"],
linkstatic = 1,
)
# Public C++ headers for the Flatbuffers library.
filegroup(
name = "public_headers",
srcs = [
"include/flatbuffers/base.h",
"include/flatbuffers/code_generators.h",
"include/flatbuffers/flatbuffers.h",
"include/flatbuffers/flexbuffers.h",
"include/flatbuffers/hash.h",
"include/flatbuffers/idl.h",
"include/flatbuffers/reflection.h",
"include/flatbuffers/reflection_generated.h",
"include/flatbuffers/stl_emulation.h",
"include/flatbuffers/util.h",
],
)
# Public flatc compiler library.
cc_library(
name = "flatc_library",
srcs = [
"src/code_generators.cpp",
"src/flatc.cpp",
"src/idl_gen_fbs.cpp",
"src/idl_parser.cpp",
"src/reflection.cpp",
"src/util.cpp",
],
hdrs = [
"include/flatbuffers/flatc.h",
":public_headers",
],
copts = FLATBUFFERS_COPTS,
includes = [
"grpc/",
"include/",
],
)
# Public flatc compiler.
cc_binary(
name = "flatc",
srcs = [
"grpc/src/compiler/config.h",
"grpc/src/compiler/cpp_generator.cc",
"grpc/src/compiler/cpp_generator.h",
"grpc/src/compiler/go_generator.cc",
"grpc/src/compiler/go_generator.h",
"grpc/src/compiler/java_generator.cc",
"grpc/src/compiler/java_generator.h",
"grpc/src/compiler/schema_interface.h",
"src/flatc_main.cpp",
"src/idl_gen_cpp.cpp",
"src/idl_gen_general.cpp",
"src/idl_gen_go.cpp",
"src/idl_gen_grpc.cpp",
"src/idl_gen_js.cpp",
"src/idl_gen_json_schema.cpp",
"src/idl_gen_php.cpp",
"src/idl_gen_python.cpp",
"src/idl_gen_text.cpp",
],
copts = FLATBUFFERS_COPTS,
includes = [
"grpc/",
"include/",
],
deps = [
":flatc_library",
],
)
# Test binary.
cc_test(
name = "flatbuffers_test",
testonly = 1,
srcs = [
"include/flatbuffers/minireflect.h",
"include/flatbuffers/registry.h",
"src/code_generators.cpp",
"src/idl_gen_fbs.cpp",
"src/idl_gen_general.cpp",
"src/idl_gen_text.cpp",
"src/idl_parser.cpp",
"src/reflection.cpp",
"src/util.cpp",
"tests/monster_test_generated.h",
"tests/namespace_test/namespace_test1_generated.h",
"tests/namespace_test/namespace_test2_generated.h",
"tests/test.cpp",
"tests/union_vector/union_vector_generated.h",
":public_headers",
],
copts = FLATBUFFERS_COPTS + [
"-DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE",
],
data = [
":tests/include_test/include_test1.fbs",
":tests/include_test/sub/include_test2.fbs",
":tests/monster_test.bfbs",
":tests/monster_test.fbs",
":tests/monsterdata_test.golden",
":tests/prototest/imported.proto",
":tests/prototest/test.golden",
":tests/prototest/test.proto",
":tests/prototest/test_union.golden",
":tests/union_vector/union_vector.fbs",
],
includes = ["include/"],
)

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

@@ -0,0 +1,11 @@
set(PACKAGE_VERSION "@VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@")
# Check whether the requested PACKAGE_FIND_VERSION is compatible
if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_COMPATIBLE FALSE)
else()
set(PACKAGE_VERSION_COMPATIBLE TRUE)
if ("${PACKAGE_VERSION}" VERSION_EQUAL "${PACKAGE_FIND_VERSION}")
set(PACKAGE_VERSION_EXACT TRUE)
endif()
endif()

View File

@@ -11,22 +11,6 @@ if (UNIX)
SET(CPACK_DEBIAN_PACKAGE_HOMEPAGE "https://github.com/google/flatbuffers")
SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Vitaly Isaev <vitalyisaev2@gmail.com>")
# Derive package version from git
EXECUTE_PROCESS(
COMMAND date +%Y%m%d
OUTPUT_VARIABLE DATE
OUTPUT_STRIP_TRAILING_WHITESPACE
)
EXECUTE_PROCESS(
COMMAND git describe
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_DESCRIBE_DIRTY
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GIT_DESCRIBE_DIRTY}")
string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${GIT_DESCRIBE_DIRTY}")
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${GIT_DESCRIBE_DIRTY}")
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+\\-([0-9]+).*" "\\1" VERSION_COMMIT "${GIT_DESCRIBE_DIRTY}")
SET(CPACK_PACKAGE_VERSION_MAJOR ${VERSION_MAJOR})
SET(CPACK_PACKAGE_VERSION_MINOR ${VERSION_MINOR})
SET(CPACK_PACKAGE_VERSION_PATCH ${VERSION_PATCH})
@@ -49,7 +33,7 @@ if (UNIX)
# Package name
SET(CPACK_DEBIAN_PACKAGE_NAME "flatbuffers")
SET(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE.txt)
SET(CPACK_PACKAGE_FILE_NAME
SET(CPACK_PACKAGE_FILE_NAME
"${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
endif(UNIX)

11
CMake/Version.cmake Normal file
View File

@@ -0,0 +1,11 @@
find_program(GIT git)
execute_process(
COMMAND ${GIT} describe
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE GIT_DESCRIBE_DIRTY
OUTPUT_STRIP_TRAILING_WHITESPACE
)
string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${GIT_DESCRIBE_DIRTY}")
string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${GIT_DESCRIBE_DIRTY}")
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_PATCH "${GIT_DESCRIBE_DIRTY}")
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+\\-([0-9]+).*" "\\1" VERSION_COMMIT "${GIT_DESCRIBE_DIRTY}")

View File

@@ -31,8 +31,10 @@ set(FlatBuffers_Library_SRCS
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
@@ -50,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
@@ -57,6 +60,8 @@ set(FlatBuffers_Compiler_SRCS
grpc/src/compiler/cpp_generator.cc
grpc/src/compiler/go_generator.h
grpc/src/compiler/go_generator.cc
grpc/src/compiler/java_generator.h
grpc/src/compiler/java_generator.cc
)
set(FlatHash_SRCS
@@ -115,10 +120,13 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
endif(CYGWIN)
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra -Werror=shadow")
if (GCC_VERSION VERSION_GREATER 4.4)
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.4)
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0)
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -faligned-new")
endif()
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -Wunused-result -Werror=unused-result \
-Wunused-parameter -Werror=unused-parameter")
"${CMAKE_CXX_FLAGS} -Wunused-result -Werror=unused-result -Wunused-parameter -Werror=unused-parameter")
endif()
# Certain platforms such as ARM do not use signed chars by default
@@ -128,8 +136,7 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -std=c++0x -Wall -pedantic -Werror \
-Wextra -Wno-unused-parameter")
"${CMAKE_CXX_FLAGS} -std=c++0x -Wall -pedantic -Werror -Wextra -Wno-unused-parameter")
if(NOT "${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -stdlib=libc++")
@@ -187,7 +194,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}.9.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)
@@ -197,6 +213,8 @@ 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)
@@ -231,19 +249,85 @@ if(FLATBUFFERS_BUILD_GRPCTEST)
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 pthread dl)
target_link_libraries(grpctest grpc++_unsecure grpc_unsecure gpr pthread dl)
endif()
include(CMake/Version.cmake)
if(FLATBUFFERS_INSTALL)
install(DIRECTORY include/flatbuffers DESTINATION include)
include(GNUInstallDirs)
install(DIRECTORY include/flatbuffers DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
set(FB_CMAKE_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/flatbuffers")
configure_file(CMake/FlatbuffersConfigVersion.cmake.in FlatbuffersConfigVersion.cmake @ONLY)
install(
FILES "CMake/FlatbuffersConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/FlatbuffersConfigVersion.cmake"
DESTINATION ${FB_CMAKE_DIR}
)
if(FLATBUFFERS_BUILD_FLATLIB)
install(TARGETS flatbuffers DESTINATION lib)
if(CMAKE_VERSION VERSION_LESS 3.0)
install(
TARGETS flatbuffers EXPORT FlatbuffersTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
else()
install(
TARGETS flatbuffers EXPORT FlatbuffersTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
endif()
install(EXPORT FlatbuffersTargets
FILE FlatbuffersTargets.cmake
NAMESPACE flatbuffers::
DESTINATION ${FB_CMAKE_DIR}
)
endif()
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)
if(CMAKE_VERSION VERSION_LESS 3.0)
install(
TARGETS flatbuffers_shared EXPORT FlatbuffersSharedTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
else()
install(
TARGETS flatbuffers_shared EXPORT FlatbuffersSharedTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
endif()
install(
EXPORT FlatbuffersSharedTargets
FILE FlatbuffersSharedTargets.cmake
NAMESPACE flatbuffers::
DESTINATION ${FB_CMAKE_DIR}
)
endif()
endif()

2
WORKSPACE Normal file
View File

@@ -0,0 +1,2 @@
workspace(name = "com_github_google_flatbuffers")

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

@@ -5,6 +5,12 @@ 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"
@@ -26,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 -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??
@@ -47,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

53
conanfile.py Normal file
View File

@@ -0,0 +1,53 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Conan recipe package for Google FlatBuffers
"""
import os
from conans import ConanFile, CMake, tools
class FlatbuffersConan(ConanFile):
name = "flatbuffers"
version = "1.9.0"
license = "https://github.com/google/flatbuffers/blob/master/LICENSE.txt"
url = "https://github.com/google/flatbuffers"
description = "Memory Efficient Serialization Library"
settings = "os", "compiler", "build_type", "arch", "os_build", "arch_build"
options = {"shared": [True, False]}
default_options = "shared=False"
generators = "cmake"
exports = "LICENSE.txt"
exports_sources = ["CMake/*", "include/*", "src/*", "grpc/*", "CMakeLists.txt"]
def _inject_magic_lines(self):
"""Inject Conan setup in cmake file to solve exteral dependencies.
"""
conan_magic_lines = '''project(FlatBuffers)
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()
'''
tools.replace_in_file("CMakeLists.txt", "project(FlatBuffers)", conan_magic_lines)
def build(self):
"""Configure, build and install FlatBuffers using CMake.
"""
self._inject_magic_lines()
cmake = CMake(self)
cmake.definitions["FLATBUFFERS_BUILD_TESTS"] = False
cmake.definitions["FLATBUFFERS_BUILD_SHAREDLIB"] = self.options.shared
cmake.configure()
cmake.build()
cmake.install()
def package(self):
"""Copy Flatbuffers' artifacts to package folder
"""
self.copy(pattern="LICENSE.txt", dst="licenses")
self.copy(pattern="flathash*", dst="bin", src="bin")
def package_info(self):
"""Collect built libraries names and solve flatc path.
"""
self.cpp_info.libs = tools.collect_libs(self)
self.env_info.PATH.append(os.path.join(self.package_folder, "bin"))

0
docs/footer.html Executable file → Normal file
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

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

@@ -5,7 +5,7 @@ Building {#flatbuffers_guide_building}
The distribution comes with a `cmake` file that should allow
you to build project/make files for any platform. For details on `cmake`, see
<http://www.cmake.org>. In brief, depending on your platform, use one of
<https://www.cmake.org>. In brief, depending on your platform, use one of
e.g.:
cmake -G "Unix Makefiles"

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

@@ -125,5 +125,8 @@ Additional options:
- `--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.

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

@@ -126,6 +126,45 @@ The following attributes are specific to the object-based API code generation:
"native_inline", the value specified with this attribute will be included
verbatim in the class constructor initializer list for this member.
- `native_custom_alloc`:"custom_allocator" (on a table or struct): When using the
object-based API all generated NativeTables that are allocated when unpacking
your flatbuffer will use "custom allocator". The allocator is also used by
any std::vector that appears in a table defined with `native_custom_alloc`.
This can be used to provide allocation from a pool for example, for faster
unpacking when using the object-based API.
Minimal Example:
schema:
table mytable(native_custom_alloc:"custom_allocator") {
...
}
with custom_allocator defined before flatbuffers.h is included, as:
template <typename T> struct custom_allocator : public std::allocator<T> {
typedef T *pointer;
template <class U>
struct rebind {
typedef custom_allocator<U> other;
};
pointer allocate(const std::size_t n) {
return std::allocator<T>::allocate(n);
}
void deallocate(T* ptr, std::size_t n) {
return std::allocator<T>::deallocate(ptr,n);
}
custom_allocator() throw() {}
template <class U>
custom_allocator(const custom_allocator<U>&) throw() {}
};
- `native_type`' "type" (on a struct): In some cases, a more optimal C++ data
type exists for a given struct. For example, the following schema:
@@ -231,6 +270,30 @@ schema, as well as a lot of helper functions.
And example of usage, for the time being, can be found in
`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
@@ -266,7 +329,7 @@ performs a swap operation on big endian machines), and also because
the layout of things is generally not known to the user.
For structs, layout is deterministic and guaranteed to be the same
accross platforms (scalars are aligned to their
across platforms (scalars are aligned to their
own size, and structs themselves to their largest member), and you
are allowed to access this memory directly by using `sizeof()` and
`memcpy` on the pointer to a struct, or even an array of structs.

View File

@@ -4,7 +4,7 @@ FlatBuffers {#flatbuffers_index}
# Overview {#flatbuffers_overview}
[FlatBuffers](@ref flatbuffers_overview) is an efficient cross platform
serialization library for C++, C#, C, Go, Java, JavaScript, PHP, and Python.
serialization library for C++, C#, C, Go, Java, JavaScript, TypeScript, PHP, and Python.
It was originally created at Google for game development and other
performance-critical applications.
@@ -134,6 +134,10 @@ sections provide a more in-depth usage guide.
in your own programs.
- How to [use the generated Go code](@ref flatbuffers_guide_use_go) in your
own programs.
- How to [use the generated JavaScript code](@ref flatbuffers_guide_use_javascript) in your
own programs.
- How to [use the generated TypeScript code](@ref flatbuffers_guide_use_typescript) in your
own programs.
- How to [use FlatBuffers in C with `flatcc`](@ref flatbuffers_guide_use_c) in your
own programs.
- [Support matrix](@ref flatbuffers_support) for platforms/languages/features.

View File

@@ -125,7 +125,7 @@ map["unknown"].IsNull(); // true
# Binary encoding
A description of how FlexBuffers are encoded is in the
[internals](Internals.md#flexbuffers) document.
[internals](@ref flatbuffers_internals) document.
# Nesting inside a FlatBuffer

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

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

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

24
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

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

@@ -18,27 +18,28 @@ In general:
NOTE: this table is a start, it needs to be extended.
Feature | C++ | Java | C# | Go | Python | JS | C | PHP | Ruby
------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | ------ | --- | ----
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | WiP
JSON parsing | Yes | No | No | No | No | No | Yes | No | No
Simple mutation | Yes | WIP | WIP | No | No | No | No | No | No
Reflection | Yes | No | No | No | No | No | Basic | No | No
Buffer verifier | Yes | No | No | No | No | No | Yes | No | No
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | ?
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | ? | ?
Performance: | Superb | Great | Great | Great | Ok | ? | Superb | ? | ?
Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | VS2010 | ? | ?
Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | ? | ?
Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | ? | ?
Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ?
Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ?
Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ?
Primary authors (github) | gwvo | gwvo | ev*/js*| rw | rw | evanw/ev* | mik* | ch* | rw
Feature | C++ | Java | C# | Go | Python | JS | TS | C | PHP | Ruby
------------------------------ | ------ | ------ | ------ | ------ | ------ | --------- | --------- | ------ | --- | ----
Codegen for all basic features | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | WiP | WiP
JSON parsing | Yes | No | No | No | No | No | No | Yes | No | No
Simple mutation | Yes | Yes | Yes | Yes | No | No | No | No | No | No
Reflection | Yes | No | No | No | No | No | No | Basic | No | No
Buffer verifier | Yes | No | No | No | No | No | No | Yes | No | No
Testing: basic | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | ? | ?
Testing: fuzz | Yes | No | No | Yes | Yes | No | No | No | ? | ?
Performance: | Superb | Great | Great | Great | Ok | ? | ? | Superb | ? | ?
Platform: Windows | VS2010 | Yes | Yes | ? | ? | ? | Yes | VS2010 | ? | ?
Platform: Linux | GCC282 | Yes | ? | Yes | Yes | ? | Yes | Yes | ? | ?
Platform: OS X | Xcode4 | ? | ? | ? | Yes | ? | Yes | Yes | ? | ?
Platform: Android | NDK10d | Yes | ? | ? | ? | ? | ? | ? | ? | ?
Platform: iOS | ? | ? | ? | ? | ? | ? | ? | ? | ? | ?
Engine: Unity | ? | ? | Yes | ? | ? | ? | ? | ? | ? | ?
Primary authors (github) | gwvo | gwvo | ev*/js*| rw | rw | evanw/ev* | kr | mik* | ch* | rw
* ev = evolutional
* js = jonsimantov
* mik = mikkelfj
* ch = chobie
* kr = krojew
<br>

View File

@@ -27,6 +27,7 @@ Please select your desired language for our quest:
<input type="radio" name="language" value="go">Go</input>
<input type="radio" name="language" value="python">Python</input>
<input type="radio" name="language" value="javascript">JavaScript</input>
<input type="radio" name="language" value="typescript">TypeScript</input>
<input type="radio" name="language" value="php">PHP</input>
<input type="radio" name="language" value="c">C</input>
</form>
@@ -122,6 +123,9 @@ For your chosen language, please cross-reference with:
<div class="language-javascript">
[samplebinary.js](https://github.com/google/flatbuffers/blob/master/samples/samplebinary.js)
</div>
<div class="language-typescript">
<em>none yet</em>
</div>
<div class="language-php">
[SampleBinary.php](https://github.com/google/flatbuffers/blob/master/samples/SampleBinary.php)
</div>
@@ -210,12 +214,21 @@ The `Weapon` table is a sub-table used within our FlatBuffer. It is
used twice: once within the `Monster` table and once within the `Equipment`
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
@@ -275,7 +288,13 @@ Please be aware of the difference between `flatc` and `flatcc` tools.
<div class="language-javascript">
~~~{.sh}
cd flatbuffers/sample
./../flatc --javascript samples/monster.fbs
./../flatc --js samples/monster.fbs
~~~
</div>
<div class="language-typescript">
~~~{.sh}
cd flatbuffers/sample
./../flatc --ts samples/monster.fbs
~~~
</div>
<div class="language-php">
@@ -363,6 +382,11 @@ The first step is to import/include the library, generated files, etc.
<script src="monster_generated.js"></script> // Generated by `flatc`.
~~~
</div>
<div class="language-typescript">
// note: import flabuffers with your desired import method
import { MyGame } from './monster_generated';
</div>
<div class="language-php">
~~~{.php}
// It is recommended that your use PSR autoload when using FlatBuffers in PHP.
@@ -445,6 +469,13 @@ which will grow automatically if needed:
var builder = new flatbuffers.Builder(1024);
~~~
</div>
<div class="language-typescript">
~~~{.ts}
// Create a `flatbuffer.Builder`, which will be used to create our
// monsters' FlatBuffers.
let builder = new flatbuffers.Builder(1024);
~~~
</div>
<div class="language-php">
~~~{.php}
// Create a `FlatBufferBuilder`, which will be used to create our
@@ -557,6 +588,24 @@ our `orc` Monster, lets create some `Weapon`s: a `Sword` and an `Axe`.
var axe = MyGame.Sample.Weapon.endWeapon(builder);
~~~
</div>
<div class="language-typescript">
~~~{.js}
let weaponOne = builder.createString('Sword');
let weaponTwo = builder.createString('Axe');
// Create the first `Weapon` ('Sword').
MyGame.Sample.Weapon.startWeapon(builder);
MyGame.Sample.Weapon.addName(builder, weaponOne);
MyGame.Sample.Weapon.addDamage(builder, 3);
let sword = MyGame.Sample.Weapon.endWeapon(builder);
// Create the second `Weapon` ('Axe').
MyGame.Sample.Weapon.startWeapon(builder);
MyGame.Sample.Weapon.addName(builder, weaponTwo);
MyGame.Sample.Weapon.addDamage(builder, 5);
let axe = MyGame.Sample.Weapon.endWeapon(builder);
~~~
</div>
<div class="language-php">
~~~{.php}
// Create the `Weapon`s using the `createWeapon()` helper function.
@@ -604,7 +653,7 @@ traversal. This is generally easy to do on any tree structures.
// Create a `vector` representing the inventory of the Orc. Each number
// 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>
@@ -675,6 +724,17 @@ traversal. This is generally easy to do on any tree structures.
var inv = MyGame.Sample.Monster.createInventoryVector(builder, treasure);
~~~
</div>
<div class="language-typescript">
~~~{.js}
// Serialize a name for our monster, called 'Orc'.
let name = builder.createString('Orc');
// Create a `vector` representing the inventory of the Orc. Each number
// could correspond to an item that can be claimed after he is slain.
let treasure = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let inv = MyGame.Sample.Monster.createInventoryVector(builder, treasure);
~~~
</div>
<div class="language-php">
~~~{.php}
// Serialize a name for our monster, called "Orc".
@@ -710,6 +770,10 @@ adding fields to our monster.
other `vector`s), collect their offsets into a temporary data structure, and
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
@@ -774,6 +838,14 @@ offsets.
var weapons = MyGame.Sample.Monster.createWeaponsVector(builder, weaps);
~~~
</div>
<div class="language-typescript">
~~~{.ts}
// Create an array from the two `Weapon`s and pass it to the
// `createWeaponsVector()` method to create a FlatBuffer vector.
let weaps = [sword, axe];
let weapons = MyGame.Sample.Monster.createWeaponsVector(builder, weaps);
~~~
</div>
<div class="language-php">
~~~{.php}
// Create an array from the two `Weapon`s and pass it to the
@@ -807,7 +879,7 @@ for the `path` field above:
<div class="language-cpp">
~~~{.cpp}
Vec3 points[] = { Vec3(1.0f, 2.0f, 3.0f), Vec3(4.0f, 5.0f, 6.0f) };
auto path = fbb.CreateVectorOfStructs(points, 2);
auto path = builder.CreateVectorOfStructs(points, 2);
~~~
</div>
<div class="language-java">
@@ -836,7 +908,7 @@ for the `path` field above:
</div>
<div class="language-python">
~~~{.py}
MyGame.Example.Monster.MonsterStartPathVector(builder, 2)
MyGame.Sample.Monster.MonsterStartPathVector(builder, 2)
MyGame.Sample.Vec3.CreateVec3(builder, 1.0, 2.0, 3.0)
MyGame.Sample.Vec3.CreateVec3(builder, 4.0, 5.0, 6.0)
path = builder.EndVector(2)
@@ -844,12 +916,20 @@ for the `path` field above:
</div>
<div class="language-javascript">
~~~{.js}
MyGame.Example.Monster.startPathVector(builder, 2);
MyGame.Sample.Monster.startPathVector(builder, 2);
MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0);
MyGame.Sample.Vec3.createVec3(builder, 4.0, 5.0, 6.0);
var path = builder.endVector();
~~~
</div>
<div class="language-typescript">
~~~{.ts}
MyGame.Sample.Monster.startPathVector(builder, 2);
MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0);
MyGame.Sample.Vec3.createVec3(builder, 4.0, 5.0, 6.0);
let path = builder.endVector();
~~~
</div>
<div class="language-php">
~~~{.php}
\MyGame\Example\Monster::StartPathVector($builder, 2);
@@ -869,15 +949,18 @@ can serialize the monster itself:
<div class="language-cpp">
~~~{.cpp}
// Create the position struct
auto position = Vec3(1.0f, 2.0f, 3.0f);
// Set his hit points to 300 and his mana to 150.
int hp = 300;
int mana = 150;
// Finally, create the monster using the `CreateMonster` helper function
// 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(), path);
auto orc = CreateMonster(builder, &position, mana, hp, name, inventory,
Color_Red, weapons, Equipment_Weapon, axe.Union(),
path);
~~~
</div>
<div class="language-java">
@@ -964,6 +1047,23 @@ can serialize the monster itself:
var orc = MyGame.Sample.Monster.endMonster(builder);
~~~
</div>
<div class="language-typescript">
~~~{.ts}
// Create our monster by using `startMonster()` and `endMonster()`.
MyGame.Sample.Monster.startMonster(builder);
MyGame.Sample.Monster.addPos(builder,
MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0));
MyGame.Sample.Monster.addHp(builder, 300);
MyGame.Sample.Monster.addColor(builder, MyGame.Sample.Color.Red)
MyGame.Sample.Monster.addName(builder, name);
MyGame.Sample.Monster.addInventory(builder, inv);
MyGame.Sample.Monster.addWeapons(builder, weapons);
MyGame.Sample.Monster.addEquippedType(builder, MyGame.Sample.Equipment.Weapon);
MyGame.Sample.Monster.addEquipped(builder, axe);
MyGame.Sample.Monster.addPath(builder, path);
let orc = MyGame.Sample.Monster.endMonster(builder);
~~~
</div>
<div class="language-php">
~~~{.php}
// Create our monster by using `StartMonster()` and `EndMonster()`.
@@ -1023,14 +1123,14 @@ a bit more flexibility.
// You can use this code instead of `CreateMonster()`, to create our orc
// manually.
MonsterBuilder monster_builder(builder);
monster_builder.add_pos(&pos);
monster_builder.add_pos(&position);
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_equipped(axe.Union());
auto orc = monster_builder.Finish();
~~~
</div>
@@ -1108,6 +1208,12 @@ Here is a repetition these lines, to help highlight them more clearly:
MyGame.Sample.Monster.addEquipped(builder, axe); // Union data
~~~
</div>
<div class="language-typescript">
~~~{.ts}
MyGame.Sample.Monster.addEquippedType(builder, MyGame.Sample.Equipment.Weapon); // Union type
MyGame.Sample.Monster.addEquipped(builder, axe); // Union data
~~~
</div>
<div class="language-php">
~~~{.php}
\MyGame\Sample\Monster::AddEquippedType($builder, \MyGame\Sample\Equipment::Weapon); // Union type
@@ -1162,7 +1268,14 @@ 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>
<div class="language-typescript">
~~~{.ts}
// Call `finish()` to instruct the builder that this monster is complete.
builder.finish(orc); // You could also call `MyGame.Sample.Monster.finishMonsterBuffer(builder,
// orc);`.
~~~
</div>
@@ -1232,6 +1345,12 @@ like so:
var buf = builder.asUint8Array(); // Of type `Uint8Array`.
~~~
</div>
<div class="language-typescript">
~~~{.ts}
// This must be called after `finish()`.
let buf = builder.asUint8Array(); // Of type `Uint8Array`.
~~~
</div>
<div class="language-php">
~~~{.php}
// This must be called after `finish()`.
@@ -1333,6 +1452,13 @@ before:
<script src="monster_generated.js"></script> // Generated by `flatc`.
~~~
</div>
<div class="language-typescript">
~~~{.js}
// note: import flabuffers with your desired import method
import { MyGame } from './monster_generated';
~~~
</div>
<div class="language-php">
~~~{.php}
// It is recommended that your use PSR autoload when using FlatBuffers in PHP.
@@ -1380,6 +1506,8 @@ won't work**
// `monster` is of type `Monster *`.
// 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">
@@ -1435,6 +1563,15 @@ won't work**
var monster = MyGame.Sample.Monster.getRootAsMonster(buf);
~~~
</div>
<div class="language-typescript">
~~~{.ts}
let bytes = /* the data you just read, in an object of type "Uint8Array" */
let buf = new flatbuffers.ByteBuffer(bytes);
// Get an accessor to the root object inside the buffer.
let monster = MyGame.Sample.Monster.getRootAsMonster(buf);
~~~
</div>
<div class="language-php">
~~~{.php}
$bytes = /* the data you just read, in a string */
@@ -1502,6 +1639,13 @@ accessors for all non-`deprecated` fields. For example:
var name = $monster.name();
~~~
</div>
<div class="language-typescript">
~~~{.ts}
let hp = $monster.hp();
let mana = $monster.mana();
let name = $monster.name();
~~~
</div>
<div class="language-php">
~~~{.php}
$hp = $monster->getHp();
@@ -1577,6 +1721,14 @@ To access sub-objects, in the case of our `pos`, which is a `Vec3`:
var z = pos.z();
~~~
</div>
<div class="language-typescript">
~~~{.ts}
let pos = monster.pos();
let x = pos.x();
let y = pos.y();
let z = pos.z();
~~~
</div>
<div class="language-php">
~~~{.php}
$pos = $monster->getPos();
@@ -1639,6 +1791,12 @@ FlatBuffers `vector`.
var thirdItem = monster.inventory(2);
~~~
</div>
<div class="language-typescript">
~~~{.ts}
let invLength = monster.inventoryLength();
let thirdItem = monster.inventory(2);
~~~
</div>
<div class="language-php">
~~~{.php}
$inv_len = $monster->getInventoryLength();
@@ -1704,6 +1862,13 @@ except your need to handle the result as a FlatBuffer `table`:
var secondWeaponDamage = monster.weapons(1).damage();
~~~
</div>
<div class="language-typescript">
~~~{.ts}
let weaponsLength = monster.weaponsLength();
let secondWeaponName = monster.weapons(1).name();
let secondWeaponDamage = monster.weapons(1).damage();
~~~
</div>
<div class="language-php">
~~~{.php}
$weapons_len = $monster->getWeaponsLength();
@@ -1811,6 +1976,16 @@ We can access the type to dynamically cast the data as needed (since the
}
~~~
</div>
<div class="language-typescript">
~~~{.ts}
let unionType = monster.equippedType();
if (unionType == MyGame.Sample.Equipment.Weapon) {
let weapon_name = monster.equipped(new MyGame.Sample.Weapon()).name(); // 'Axe'
let weapon_damage = monster.equipped(new MyGame.Sample.Weapon()).damage(); // 5
}
~~~
</div>
<div class="language-php">
~~~{.php}
$union_type = $monster->getEquippedType();
@@ -1889,7 +2064,12 @@ mutators like so:
</div>
<div class="language-javascript">
~~~{.js}
<API for mutating FlatBuffers is not yet support in JavaScript.>
<API for mutating FlatBuffers is not yet supported in JavaScript.>
~~~
</div>
<div class="language-typescript">
~~~{.ts}
<API for mutating FlatBuffers is not yet supported in TypeScript.>
~~~
</div>
<div class="language-php">
@@ -2003,6 +2183,9 @@ For your chosen language, see:
<div class="language-javascript">
[Use in JavaScript](@ref flatbuffers_guide_use_javascript)
</div>
<div class="language-typescript">
[Use in TypeScript](@ref flatbuffers_guide_use_typescript)
</div>
<div class="language-php">
[Use in PHP](@ref flatbuffers_guide_use_php)
</div>

View File

@@ -0,0 +1,66 @@
Use in TypeScript {#flatbuffers_guide_use_typescript}
=================
## Before you get started
Before diving into the FlatBuffers usage in TypeScript, it should be noted that
the [Tutorial](@ref flatbuffers_guide_tutorial) page has a complete guide to
general FlatBuffers usage in all of the supported languages
(including TypeScript). This page is specifically designed to cover the nuances
of FlatBuffers usage in TypeScript.
You should also have read the [Building](@ref flatbuffers_guide_building)
documentation to build `flatc` and should be familiar with
[Using the schema compiler](@ref flatbuffers_guide_using_schema_compiler) and
[Writing a schema](@ref flatbuffers_guide_writing_schema).
## FlatBuffers TypeScript library code location
The code for the FlatBuffers TypeScript library can be found at
`flatbuffers/js` with typings available at @types/flatubffers.
## Testing the FlatBuffers TypeScript library
To run the tests, use the [TypeScriptTest.sh](https://github.com/google/
flatbuffers/blob/master/tests/TypeScriptTest.sh) shell script.
*Note: The TypeScript test file requires [Node.js](https://nodejs.org/en/).*
## Using the FlatBuffers TypeScript libary
*Note: See [Tutorial](@ref flatbuffers_guide_tutorial) for a more in-depth
example of how to use FlatBuffers in TypeScript.*
FlatBuffers supports both reading and writing FlatBuffers in TypeScript.
To use FlatBuffers in your own code, first generate TypeScript classes from your
schema with the `--ts` option to `flatc`. Then you can include both FlatBuffers
and the generated code to read or write a FlatBuffer.
For example, here is how you would read a FlatBuffer binary file in TypeScript:
First, include the library and generated code. Then read the file into an
`Uint8Array`. Make a `flatbuffers.ByteBuffer` out of the `Uint8Array`, and pass
the ByteBuffer to the `getRootAsMonster` function.
~~~{.ts}
// note: import flabuffers with your desired import method
import { MyGame } from './monster_generated';
let data = new Uint8Array(fs.readFileSync('monster.dat'));
let buf = new flatbuffers.ByteBuffer(data);
let monster = MyGame.Example.Monster.getRootAsMonster(buf);
~~~
Now you can access values like this:
~~~{.ts}
let hp = monster.hp();
let pos = monster.pos();
~~~
## Text parsing FlatBuffers in TypeScript
There currently is no support for parsing text (Schema's and JSON) directly
from TypeScript.

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

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

View File

@@ -33,6 +33,8 @@
title="Use in Java/C#"/>
<tab type="user" url="@ref flatbuffers_guide_use_javascript"
title="Use in JavaScript"/>
<tab type="user" url="@ref flatbuffers_guide_use_typescript"
title="Use in TypeScript"/>
<tab type="user" url="@ref flatbuffers_guide_use_php"
title="Use in PHP"/>
<tab type="user" url="@ref flatbuffers_guide_use_python"

View File

@@ -13,6 +13,9 @@
/// @defgroup flatbuffers_javascript_api JavaScript API
/// @brief FlatBuffers API for JavaScript
/// @defgroup flatbuffers_typescript_api TypeScript API
/// @brief FlatBuffers API for TypeScript
/// @defgroup flatbuffers_php_api PHP API
/// @brief FlatBuffers API for PHP

17
go/BUILD.bazel Normal file
View File

@@ -0,0 +1,17 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go",
srcs = [
"builder.go",
"doc.go",
"encode.go",
"grpc.go",
"lib.go",
"sizes.go",
"struct.go",
"table.go",
],
importpath = "github.com/google/flatbuffers/go",
visibility = ["//visibility:public"],
)

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,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-parent</artifactId>
<version>1.8.0</version>
</parent>
<artifactId>flatbuffers-java-grpc</artifactId>
<name>${project.artifactId}</name>
<packaging>bundle</packaging>
<description>
Utilities supporting generated code for GRPC
</description>
<developers>
<developer>
<name>Wouter van Oortmerssen</name>
</developer>
<developer>
<name>Yuri Finkelstein</name>
<url>https://github.com/yfinkelstein</url>
</developer>
</developers>
<properties>
<gRPC.version>1.8.0</gRPC.version>
</properties>
<dependencies>
<dependency>
<groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-java</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-core</artifactId>
<version>${gRPC.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,117 @@
/*
* Copyright 2014 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.flatbuffers.grpc;
import com.google.flatbuffers.Table;
import io.grpc.Drainable;
import io.grpc.KnownLength;
import io.grpc.MethodDescriptor;
import javax.annotation.Nullable;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
public class FlatbuffersUtils {
abstract public static class FBExtactor <T extends Table> {
T extract (InputStream stream) throws IOException {
if (stream instanceof KnownLength) {
int size = stream.available();
ByteBuffer buffer = ByteBuffer.allocate(size);
stream.read(buffer.array());
return extract(buffer);
} else
throw new RuntimeException("The class " + stream.getClass().getCanonicalName() + " does not extend from KnownLength ");
}
public abstract T extract(ByteBuffer buffer);
}
static class FBInputStream extends InputStream implements Drainable, KnownLength {
private final ByteBuffer buffer;
private final int size;
@Nullable private ByteArrayInputStream inputStream;
FBInputStream(ByteBuffer buffer) {
this.buffer = buffer;
this.size = buffer.remaining();
}
private void makeStreamIfNotAlready() {
if (inputStream == null)
inputStream = new ByteArrayInputStream(buffer.array(), buffer.position(), size);
}
@Override
public int drainTo(OutputStream target) throws IOException {
target.write(buffer.array(), buffer.position(), size);
return size;
}
@Override
public int read() throws IOException {
makeStreamIfNotAlready();
return inputStream.read();
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
makeStreamIfNotAlready();
if (inputStream == null) {
if (len >= size) {
System.arraycopy(buffer.array(), buffer.position(), b, off, size);
return size;
} else {
makeStreamIfNotAlready();
return inputStream.read(b, off, len);
}
} else
return inputStream.read(b, off, len);
}
@Override
public int available() throws IOException {
return inputStream == null ? size : inputStream.available();
}
}
public static <T extends Table> MethodDescriptor.Marshaller<T> marshaller(final Class<T> clazz, final FBExtactor<T> extractor) {
return new MethodDescriptor.ReflectableMarshaller<T>() {
@Override
public Class<T> getMessageClass() {
return clazz;
}
@Override
public InputStream stream(T value) {
return new FBInputStream (value.getByteBuffer());
}
@Override
public T parse(InputStream stream) {
try {
return extractor.extract(stream);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
};
}
}

213
grpc/pom.xml Normal file
View File

@@ -0,0 +1,213 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-parent</artifactId>
<packaging>pom</packaging>
<version>1.8.0</version>
<name>flatbuffers-parent</name>
<description>parent pom for flatbuffers java artifacts</description>
<properties>
<scm.url>https://github.com/google/flatbuffers</scm.url>
<scm.connection>scm:git:${scm.url}.git</scm.connection>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<issueManagement>
<system>GitHub</system>
<url>https://github.com/google/flatbuffers/issues</url>
</issueManagement>
<developers>
<developer>
<name>Wouter van Oortmerssen</name>
</developer>
</developers>
<url>${scm.url}</url>
<scm>
<connection>${scm.connection}</connection>
<developerConnection>${scm.connection}</developerConnection>
<url>${scm.url}</url>
<tag>HEAD</tag>
</scm>
<distributionManagement>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<extensions>
<extension>
<!--
os-maven-plugin is a Maven extension/plugin that generates various useful platform-dependent
project properties normalized from ${os.detected.name} and ${os.detected.arch}.
-->
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.5.0.Final</version>
</extension>
</extensions>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.12</version>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.8</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.7</version>
</plugin>
<plugin>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.5.0</version>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<includes>
<include>**/*Test.java</include>
</includes>
</configuration>
</plugin>
<plugin>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-javadoc-plugin</artifactId>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>3.0.1</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.7</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>true</autoReleaseAfterClose>
</configuration>
</plugin>
<plugin>
<artifactId>maven-gpg-plugin</artifactId>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-release-plugin</artifactId>
<configuration>
<autoVersionSubmodules>true</autoVersionSubmodules>
<useReleaseProfile>false</useReleaseProfile>
<releaseProfiles>release</releaseProfiles>
<goals>deploy</goals>
</configuration>
</plugin>
</plugins>
</build>
<modules>
<!-- consider the benefits of publishing all maven artifacts in this project
<module>flatbuffers-compiler</module>
<module>flatbuffers-java</module>
-->
<module>flatbuffers-java-grpc</module>
</modules>
</project>

View File

@@ -34,6 +34,7 @@
#include <map>
#include "src/compiler/cpp_generator.h"
#include "flatbuffers/util.h"
#include <sstream>
@@ -127,8 +128,8 @@ grpc::string GetHeaderPrologue(grpc_generator::File *file,
printer->Print(vars, "#ifndef GRPC_$filename_identifier$__INCLUDED\n");
printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
printer->Print(vars, "\n");
printer->Print(vars, file->additional_headers().c_str());
printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
printer->Print(vars, file->additional_headers().c_str());
printer->Print(vars, "\n");
}
return output;
@@ -158,7 +159,6 @@ grpc::string GetHeaderIncludes(grpc_generator::File *file,
printer->Print(vars, "namespace grpc {\n");
printer->Print(vars, "class CompletionQueue;\n");
printer->Print(vars, "class Channel;\n");
printer->Print(vars, "class RpcService;\n");
printer->Print(vars, "class ServerCompletionQueue;\n");
printer->Print(vars, "class ServerContext;\n");
printer->Print(vars, "} // namespace grpc\n\n");
@@ -183,25 +183,38 @@ void PrintHeaderClientMethodInterfaces(
(*vars)["Request"] = method->input_type_name();
(*vars)["Response"] = method->output_type_name();
struct {
grpc::string prefix;
grpc::string method_params; // extra arguments to method
grpc::string raw_args; // extra arguments to raw version of method
} async_prefixes[] = {{"Async", ", void* tag", ", tag"},
{"PrepareAsync", "", ""}};
if (is_public) {
if (method->NoStreaming()) {
printer->Print(
*vars,
"virtual ::grpc::Status $Method$(::grpc::ClientContext* context, "
"const $Request$& request, $Response$* response) = 0;\n");
printer->Print(*vars,
"std::unique_ptr< "
"::grpc::ClientAsyncResponseReaderInterface< $Response$>> "
"Async$Method$(::grpc::ClientContext* context, "
"const $Request$& request, "
"::grpc::CompletionQueue* cq) {\n");
printer->Indent();
printer->Print(*vars,
"return std::unique_ptr< "
"::grpc::ClientAsyncResponseReaderInterface< $Response$>>("
"Async$Method$Raw(context, request, cq));\n");
printer->Outdent();
printer->Print("}\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
printer->Print(
*vars,
"std::unique_ptr< "
"::grpc::ClientAsyncResponseReaderInterface< $Response$>> "
"$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
"const $Request$& request, "
"::grpc::CompletionQueue* cq) {\n");
printer->Indent();
printer->Print(
*vars,
"return std::unique_ptr< "
"::grpc::ClientAsyncResponseReaderInterface< $Response$>>("
"$AsyncPrefix$$Method$Raw(context, request, cq));\n");
printer->Outdent();
printer->Print("}\n");
}
} else if (ClientOnlyStreaming(method)) {
printer->Print(
*vars,
@@ -215,19 +228,27 @@ void PrintHeaderClientMethodInterfaces(
"($Method$Raw(context, response));\n");
printer->Outdent();
printer->Print("}\n");
printer->Print(
*vars,
"std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>"
" Async$Method$(::grpc::ClientContext* context, $Response$* "
"response, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Indent();
printer->Print(*vars,
"return std::unique_ptr< "
"::grpc::ClientAsyncWriterInterface< $Request$>>("
"Async$Method$Raw(context, response, cq, tag));\n");
printer->Outdent();
printer->Print("}\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
printer->Print(
*vars,
"std::unique_ptr< ::grpc::ClientAsyncWriterInterface< $Request$>>"
" $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
"$Response$* "
"response, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
printer->Indent();
printer->Print(*vars,
"return std::unique_ptr< "
"::grpc::ClientAsyncWriterInterface< $Request$>>("
"$AsyncPrefix$$Method$Raw(context, response, "
"cq$AsyncRawArgs$));\n");
printer->Outdent();
printer->Print("}\n");
}
} else if (ServerOnlyStreaming(method)) {
printer->Print(
*vars,
@@ -241,19 +262,26 @@ void PrintHeaderClientMethodInterfaces(
"($Method$Raw(context, request));\n");
printer->Outdent();
printer->Print("}\n");
printer->Print(
*vars,
"std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> "
"Async$Method$("
"::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Indent();
printer->Print(*vars,
"return std::unique_ptr< "
"::grpc::ClientAsyncReaderInterface< $Response$>>("
"Async$Method$Raw(context, request, cq, tag));\n");
printer->Outdent();
printer->Print("}\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
printer->Print(
*vars,
"std::unique_ptr< ::grpc::ClientAsyncReaderInterface< $Response$>> "
"$AsyncPrefix$$Method$("
"::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
printer->Indent();
printer->Print(
*vars,
"return std::unique_ptr< "
"::grpc::ClientAsyncReaderInterface< $Response$>>("
"$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
printer->Outdent();
printer->Print("}\n");
}
} else if (method->BidiStreaming()) {
printer->Print(*vars,
"std::unique_ptr< ::grpc::ClientReaderWriterInterface< "
@@ -267,61 +295,89 @@ void PrintHeaderClientMethodInterfaces(
"$Method$Raw(context));\n");
printer->Outdent();
printer->Print("}\n");
printer->Print(
*vars,
"std::unique_ptr< "
"::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> "
"Async$Method$(::grpc::ClientContext* context, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Indent();
printer->Print(
*vars,
"return std::unique_ptr< "
"::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>("
"Async$Method$Raw(context, cq, tag));\n");
printer->Outdent();
printer->Print("}\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
printer->Print(
*vars,
"std::unique_ptr< "
"::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>> "
"$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
printer->Indent();
printer->Print(
*vars,
"return std::unique_ptr< "
"::grpc::ClientAsyncReaderWriterInterface< $Request$, $Response$>>("
"$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
printer->Outdent();
printer->Print("}\n");
}
}
} else {
if (method->NoStreaming()) {
printer->Print(
*vars,
"virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
"Async$Method$Raw(::grpc::ClientContext* context, "
"const $Request$& request, "
"::grpc::CompletionQueue* cq) = 0;\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
printer->Print(
*vars,
"virtual ::grpc::ClientAsyncResponseReaderInterface< $Response$>* "
"$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
"const $Request$& request, "
"::grpc::CompletionQueue* cq) = 0;\n");
}
} else if (ClientOnlyStreaming(method)) {
printer->Print(
*vars,
"virtual ::grpc::ClientWriterInterface< $Request$>*"
" $Method$Raw("
"::grpc::ClientContext* context, $Response$* response) = 0;\n");
printer->Print(*vars,
"virtual ::grpc::ClientAsyncWriterInterface< $Request$>*"
" Async$Method$Raw(::grpc::ClientContext* context, "
"$Response$* response, "
"::grpc::CompletionQueue* cq, void* tag) = 0;\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
printer->Print(
*vars,
"virtual ::grpc::ClientAsyncWriterInterface< $Request$>*"
" $AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
"$Response$* response, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
}
} else if (ServerOnlyStreaming(method)) {
printer->Print(
*vars,
"virtual ::grpc::ClientReaderInterface< $Response$>* $Method$Raw("
"virtual ::grpc::ClientReaderInterface< $Response$>* "
"$Method$Raw("
"::grpc::ClientContext* context, const $Request$& request) = 0;\n");
printer->Print(
*vars,
"virtual ::grpc::ClientAsyncReaderInterface< $Response$>* "
"Async$Method$Raw("
"::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq, void* tag) = 0;\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
printer->Print(
*vars,
"virtual ::grpc::ClientAsyncReaderInterface< $Response$>* "
"$AsyncPrefix$$Method$Raw("
"::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
}
} else if (method->BidiStreaming()) {
printer->Print(*vars,
"virtual ::grpc::ClientReaderWriterInterface< $Request$, "
"$Response$>* "
"$Method$Raw(::grpc::ClientContext* context) = 0;\n");
printer->Print(*vars,
"virtual ::grpc::ClientAsyncReaderWriterInterface< "
"$Request$, $Response$>* "
"Async$Method$Raw(::grpc::ClientContext* context, "
"::grpc::CompletionQueue* cq, void* tag) = 0;\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
printer->Print(
*vars,
"virtual ::grpc::ClientAsyncReaderWriterInterface< "
"$Request$, $Response$>* "
"$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) = 0;\n");
}
}
}
}
@@ -333,25 +389,36 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
(*vars)["Response"] = method->output_type_name();
struct {
grpc::string prefix;
grpc::string method_params; // extra arguments to method
grpc::string raw_args; // extra arguments to raw version of method
} async_prefixes[] = {{"Async", ", void* tag", ", tag"},
{"PrepareAsync", "", ""}};
if (is_public) {
if (method->NoStreaming()) {
printer->Print(
*vars,
"::grpc::Status $Method$(::grpc::ClientContext* context, "
"const $Request$& request, $Response$* response) override;\n");
printer->Print(
*vars,
"std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> "
"Async$Method$(::grpc::ClientContext* context, "
"const $Request$& request, "
"::grpc::CompletionQueue* cq) {\n");
printer->Indent();
printer->Print(*vars,
"return std::unique_ptr< "
"::grpc::ClientAsyncResponseReader< $Response$>>("
"Async$Method$Raw(context, request, cq));\n");
printer->Outdent();
printer->Print("}\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
printer->Print(
*vars,
"std::unique_ptr< ::grpc::ClientAsyncResponseReader< $Response$>> "
"$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
"const $Request$& request, "
"::grpc::CompletionQueue* cq) {\n");
printer->Indent();
printer->Print(*vars,
"return std::unique_ptr< "
"::grpc::ClientAsyncResponseReader< $Response$>>("
"$AsyncPrefix$$Method$Raw(context, request, cq));\n");
printer->Outdent();
printer->Print("}\n");
}
} else if (ClientOnlyStreaming(method)) {
printer->Print(
*vars,
@@ -364,18 +431,25 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"($Method$Raw(context, response));\n");
printer->Outdent();
printer->Print("}\n");
printer->Print(*vars,
"std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>"
" Async$Method$(::grpc::ClientContext* context, "
"$Response$* response, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Indent();
printer->Print(
*vars,
"return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>("
"Async$Method$Raw(context, response, cq, tag));\n");
printer->Outdent();
printer->Print("}\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
printer->Print(*vars,
"std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>"
" $AsyncPrefix$$Method$(::grpc::ClientContext* context, "
"$Response$* response, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
printer->Indent();
printer->Print(
*vars,
"return std::unique_ptr< ::grpc::ClientAsyncWriter< $Request$>>("
"$AsyncPrefix$$Method$Raw(context, response, "
"cq$AsyncRawArgs$));\n");
printer->Outdent();
printer->Print("}\n");
}
} else if (ServerOnlyStreaming(method)) {
printer->Print(
*vars,
@@ -389,19 +463,25 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"($Method$Raw(context, request));\n");
printer->Outdent();
printer->Print("}\n");
printer->Print(
*vars,
"std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> "
"Async$Method$("
"::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Indent();
printer->Print(
*vars,
"return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>("
"Async$Method$Raw(context, request, cq, tag));\n");
printer->Outdent();
printer->Print("}\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
printer->Print(
*vars,
"std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>> "
"$AsyncPrefix$$Method$("
"::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
printer->Indent();
printer->Print(
*vars,
"return std::unique_ptr< ::grpc::ClientAsyncReader< $Response$>>("
"$AsyncPrefix$$Method$Raw(context, request, cq$AsyncRawArgs$));\n");
printer->Outdent();
printer->Print("}\n");
}
} else if (method->BidiStreaming()) {
printer->Print(
*vars,
@@ -414,53 +494,85 @@ void PrintHeaderClientMethod(grpc_generator::Printer *printer,
"$Method$Raw(context));\n");
printer->Outdent();
printer->Print("}\n");
printer->Print(*vars,
"std::unique_ptr< ::grpc::ClientAsyncReaderWriter< "
"$Request$, $Response$>> "
"Async$Method$(::grpc::ClientContext* context, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Indent();
printer->Print(*vars,
"return std::unique_ptr< "
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>("
"Async$Method$Raw(context, cq, tag));\n");
printer->Outdent();
printer->Print("}\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
printer->Print(*vars,
"std::unique_ptr< ::grpc::ClientAsyncReaderWriter< "
"$Request$, $Response$>> "
"$AsyncPrefix$$Method$(::grpc::ClientContext* context, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
printer->Indent();
printer->Print(
*vars,
"return std::unique_ptr< "
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>>("
"$AsyncPrefix$$Method$Raw(context, cq$AsyncRawArgs$));\n");
printer->Outdent();
printer->Print("}\n");
}
}
} else {
if (method->NoStreaming()) {
printer->Print(*vars,
"::grpc::ClientAsyncResponseReader< $Response$>* "
"Async$Method$Raw(::grpc::ClientContext* context, "
"const $Request$& request, "
"::grpc::CompletionQueue* cq) override;\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
printer->Print(
*vars,
"::grpc::ClientAsyncResponseReader< $Response$>* "
"$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
"const $Request$& request, "
"::grpc::CompletionQueue* cq) override;\n");
}
} else if (ClientOnlyStreaming(method)) {
printer->Print(*vars,
"::grpc::ClientWriter< $Request$>* $Method$Raw("
"::grpc::ClientContext* context, $Response$* response) "
"override;\n");
printer->Print(*vars,
"::grpc::ClientAsyncWriter< $Request$>* Async$Method$Raw("
"::grpc::ClientContext* context, $Response$* response, "
"::grpc::CompletionQueue* cq, void* tag) override;\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
printer->Print(
*vars,
"::grpc::ClientAsyncWriter< $Request$>* $AsyncPrefix$$Method$Raw("
"::grpc::ClientContext* context, $Response$* response, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
}
} else if (ServerOnlyStreaming(method)) {
printer->Print(*vars,
"::grpc::ClientReader< $Response$>* $Method$Raw("
"::grpc::ClientContext* context, const $Request$& request)"
" override;\n");
printer->Print(
*vars,
"::grpc::ClientAsyncReader< $Response$>* Async$Method$Raw("
"::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq, void* tag) override;\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
printer->Print(
*vars,
"::grpc::ClientAsyncReader< $Response$>* $AsyncPrefix$$Method$Raw("
"::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
}
} else if (method->BidiStreaming()) {
printer->Print(*vars,
"::grpc::ClientReaderWriter< $Request$, $Response$>* "
"$Method$Raw(::grpc::ClientContext* context) override;\n");
printer->Print(*vars,
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
"Async$Method$Raw(::grpc::ClientContext* context, "
"::grpc::CompletionQueue* cq, void* tag) override;\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncRawArgs"] = async_prefix.raw_args;
printer->Print(
*vars,
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
"$AsyncPrefix$$Method$Raw(::grpc::ClientContext* context, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) override;\n");
}
}
}
}
@@ -469,7 +581,8 @@ void PrintHeaderClientMethodData(grpc_generator::Printer *printer,
const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
printer->Print(*vars, "const ::grpc::RpcMethod rpcmethod_$Method$_;\n");
printer->Print(*vars,
"const ::grpc::internal::RpcMethod rpcmethod_$Method$_;\n");
}
void PrintHeaderServerMethodSync(grpc_generator::Printer *printer,
@@ -641,7 +754,7 @@ void PrintHeaderServerMethodStreamedUnary(
printer->Print(*vars,
"WithStreamedUnaryMethod_$Method$() {\n"
" ::grpc::Service::MarkMethodStreamed($Idx$,\n"
" new ::grpc::StreamedUnaryHandler< $Request$, "
" new ::grpc::internal::StreamedUnaryHandler< $Request$, "
"$Response$>(std::bind"
"(&WithStreamedUnaryMethod_$Method$<BaseClass>::"
"Streamed$Method$, this, std::placeholders::_1, "
@@ -689,15 +802,16 @@ void PrintHeaderServerMethodSplitStreaming(
"{}\n");
printer->Print(" public:\n");
printer->Indent();
printer->Print(*vars,
"WithSplitStreamingMethod_$Method$() {\n"
" ::grpc::Service::MarkMethodStreamed($Idx$,\n"
" new ::grpc::SplitServerStreamingHandler< $Request$, "
"$Response$>(std::bind"
"(&WithSplitStreamingMethod_$Method$<BaseClass>::"
"Streamed$Method$, this, std::placeholders::_1, "
"std::placeholders::_2)));\n"
"}\n");
printer->Print(
*vars,
"WithSplitStreamingMethod_$Method$() {\n"
" ::grpc::Service::MarkMethodStreamed($Idx$,\n"
" new ::grpc::internal::SplitServerStreamingHandler< $Request$, "
"$Response$>(std::bind"
"(&WithSplitStreamingMethod_$Method$<BaseClass>::"
"Streamed$Method$, this, std::placeholders::_1, "
"std::placeholders::_2)));\n"
"}\n");
printer->Print(*vars,
"~WithSplitStreamingMethod_$Method$() override {\n"
" BaseClassMustBeDerivedFromService(this);\n"
@@ -837,7 +951,8 @@ void PrintHeaderService(grpc_generator::Printer *printer,
" {\n public:\n");
printer->Indent();
printer->Print(
"Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel);\n");
"Stub(const std::shared_ptr< ::grpc::ChannelInterface>& "
"channel);\n");
for (int i = 0; i < service->method_count(); ++i) {
PrintHeaderClientMethod(printer, service->method(i).get(), vars, true);
}
@@ -1095,99 +1210,137 @@ void PrintSourceClientMethod(grpc_generator::Printer *printer,
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
(*vars)["Response"] = method->output_type_name();
struct {
grpc::string prefix;
grpc::string start; // bool literal expressed as string
grpc::string method_params; // extra arguments to method
grpc::string create_args; // extra arguments to creator
} async_prefixes[] = {{"Async", "true", ", void* tag", ", tag"},
{"PrepareAsync", "false", "", ", nullptr"}};
if (method->NoStreaming()) {
printer->Print(*vars,
"::grpc::Status $ns$$Service$::Stub::$Method$("
"::grpc::ClientContext* context, "
"const $Request$& request, $Response$* response) {\n");
printer->Print(*vars,
" return ::grpc::BlockingUnaryCall(channel_.get(), "
"rpcmethod_$Method$_, "
"context, request, response);\n"
"}\n\n");
printer->Print(
*vars,
"::grpc::ClientAsyncResponseReader< $Response$>* "
"$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, "
"const $Request$& request, "
"::grpc::CompletionQueue* cq) {\n");
printer->Print(*vars,
" return "
"::grpc::ClientAsyncResponseReader< $Response$>::Create("
"channel_.get(), cq, "
"rpcmethod_$Method$_, "
"context, request);\n"
"}\n\n");
" return ::grpc::internal::BlockingUnaryCall"
"(channel_.get(), rpcmethod_$Method$_, "
"context, request, response);\n}\n\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncStart"] = async_prefix.start;
printer->Print(*vars,
"::grpc::ClientAsyncResponseReader< $Response$>* "
"$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
"ClientContext* context, "
"const $Request$& request, "
"::grpc::CompletionQueue* cq) {\n");
printer->Print(
*vars,
" return "
"::grpc::internal::ClientAsyncResponseReaderFactory< $Response$>"
"::Create(channel_.get(), cq, "
"rpcmethod_$Method$_, "
"context, request, $AsyncStart$);\n"
"}\n\n");
}
} else if (ClientOnlyStreaming(method)) {
printer->Print(*vars,
"::grpc::ClientWriter< $Request$>* "
"$ns$$Service$::Stub::$Method$Raw("
"::grpc::ClientContext* context, $Response$* response) {\n");
printer->Print(*vars,
" return new ::grpc::ClientWriter< $Request$>("
"channel_.get(), "
"rpcmethod_$Method$_, "
"context, response);\n"
"}\n\n");
printer->Print(*vars,
"::grpc::ClientAsyncWriter< $Request$>* "
"$ns$$Service$::Stub::Async$Method$Raw("
"::grpc::ClientContext* context, $Response$* response, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Print(*vars,
" return ::grpc::ClientAsyncWriter< $Request$>::Create("
"channel_.get(), cq, "
"rpcmethod_$Method$_, "
"context, response, tag);\n"
"}\n\n");
printer->Print(
*vars,
" return ::grpc::internal::ClientWriterFactory< $Request$>::Create("
"channel_.get(), "
"rpcmethod_$Method$_, "
"context, response);\n"
"}\n\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncStart"] = async_prefix.start;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncCreateArgs"] = async_prefix.create_args;
printer->Print(*vars,
"::grpc::ClientAsyncWriter< $Request$>* "
"$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
"::grpc::ClientContext* context, $Response$* response, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
printer->Print(
*vars,
" return ::grpc::internal::ClientAsyncWriterFactory< $Request$>"
"::Create(channel_.get(), cq, "
"rpcmethod_$Method$_, "
"context, response, $AsyncStart$$AsyncCreateArgs$);\n"
"}\n\n");
}
} else if (ServerOnlyStreaming(method)) {
printer->Print(
*vars,
"::grpc::ClientReader< $Response$>* "
"$ns$$Service$::Stub::$Method$Raw("
"::grpc::ClientContext* context, const $Request$& request) {\n");
printer->Print(*vars,
" return new ::grpc::ClientReader< $Response$>("
"channel_.get(), "
"rpcmethod_$Method$_, "
"context, request);\n"
"}\n\n");
printer->Print(*vars,
"::grpc::ClientAsyncReader< $Response$>* "
"$ns$$Service$::Stub::Async$Method$Raw("
"::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Print(*vars,
" return ::grpc::ClientAsyncReader< $Response$>::Create("
"channel_.get(), cq, "
"rpcmethod_$Method$_, "
"context, request, tag);\n"
"}\n\n");
printer->Print(
*vars,
" return ::grpc::internal::ClientReaderFactory< $Response$>::Create("
"channel_.get(), "
"rpcmethod_$Method$_, "
"context, request);\n"
"}\n\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncStart"] = async_prefix.start;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncCreateArgs"] = async_prefix.create_args;
printer->Print(
*vars,
"::grpc::ClientAsyncReader< $Response$>* "
"$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw("
"::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
printer->Print(
*vars,
" return ::grpc::internal::ClientAsyncReaderFactory< $Response$>"
"::Create(channel_.get(), cq, "
"rpcmethod_$Method$_, "
"context, request, $AsyncStart$$AsyncCreateArgs$);\n"
"}\n\n");
}
} else if (method->BidiStreaming()) {
printer->Print(
*vars,
"::grpc::ClientReaderWriter< $Request$, $Response$>* "
"$ns$$Service$::Stub::$Method$Raw(::grpc::ClientContext* context) {\n");
printer->Print(*vars,
" return new ::grpc::ClientReaderWriter< "
"$Request$, $Response$>("
" return ::grpc::internal::ClientReaderWriterFactory< "
"$Request$, $Response$>::Create("
"channel_.get(), "
"rpcmethod_$Method$_, "
"context);\n"
"}\n\n");
printer->Print(
*vars,
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
"$ns$$Service$::Stub::Async$Method$Raw(::grpc::ClientContext* context, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Print(
*vars,
" return "
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>::Create("
"channel_.get(), cq, "
"rpcmethod_$Method$_, "
"context, tag);\n"
"}\n\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncStart"] = async_prefix.start;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["AsyncCreateArgs"] = async_prefix.create_args;
printer->Print(*vars,
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
"$ns$$Service$::Stub::$AsyncPrefix$$Method$Raw(::grpc::"
"ClientContext* context, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$) {\n");
printer->Print(*vars,
" return "
"::grpc::internal::ClientAsyncReaderWriterFactory< "
"$Request$, $Response$>::Create("
"channel_.get(), cq, "
"rpcmethod_$Method$_, "
"context, $AsyncStart$$AsyncCreateArgs$);\n"
"}\n\n");
}
}
}
@@ -1297,7 +1450,7 @@ void PrintSourceService(grpc_generator::Printer *printer,
printer->Print(*vars,
", rpcmethod_$Method$_("
"$prefix$$Service$_method_names[$Idx$], "
"::grpc::RpcMethod::$StreamingType$, "
"::grpc::internal::RpcMethod::$StreamingType$, "
"channel"
")\n");
}
@@ -1320,38 +1473,38 @@ void PrintSourceService(grpc_generator::Printer *printer,
if (method->NoStreaming()) {
printer->Print(
*vars,
"AddMethod(new ::grpc::RpcServiceMethod(\n"
"AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
" $prefix$$Service$_method_names[$Idx$],\n"
" ::grpc::RpcMethod::NORMAL_RPC,\n"
" new ::grpc::RpcMethodHandler< $ns$$Service$::Service, "
" ::grpc::internal::RpcMethod::NORMAL_RPC,\n"
" new ::grpc::internal::RpcMethodHandler< $ns$$Service$::Service, "
"$Request$, "
"$Response$>(\n"
" std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
} else if (ClientOnlyStreaming(method.get())) {
printer->Print(
*vars,
"AddMethod(new ::grpc::RpcServiceMethod(\n"
"AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
" $prefix$$Service$_method_names[$Idx$],\n"
" ::grpc::RpcMethod::CLIENT_STREAMING,\n"
" new ::grpc::ClientStreamingHandler< "
" ::grpc::internal::RpcMethod::CLIENT_STREAMING,\n"
" new ::grpc::internal::ClientStreamingHandler< "
"$ns$$Service$::Service, $Request$, $Response$>(\n"
" std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
} else if (ServerOnlyStreaming(method.get())) {
printer->Print(
*vars,
"AddMethod(new ::grpc::RpcServiceMethod(\n"
"AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
" $prefix$$Service$_method_names[$Idx$],\n"
" ::grpc::RpcMethod::SERVER_STREAMING,\n"
" new ::grpc::ServerStreamingHandler< "
" ::grpc::internal::RpcMethod::SERVER_STREAMING,\n"
" new ::grpc::internal::ServerStreamingHandler< "
"$ns$$Service$::Service, $Request$, $Response$>(\n"
" std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
} else if (method->BidiStreaming()) {
printer->Print(
*vars,
"AddMethod(new ::grpc::RpcServiceMethod(\n"
"AddMethod(new ::grpc::internal::RpcServiceMethod(\n"
" $prefix$$Service$_method_names[$Idx$],\n"
" ::grpc::RpcMethod::BIDI_STREAMING,\n"
" new ::grpc::BidiStreamingHandler< "
" ::grpc::internal::RpcMethod::BIDI_STREAMING,\n"
" new ::grpc::internal::BidiStreamingHandler< "
"$ns$$Service$::Service, $Request$, $Response$>(\n"
" std::mem_fn(&$ns$$Service$::Service::$Method$), this)));\n");
}
@@ -1452,7 +1605,8 @@ grpc::string GetMockIncludes(grpc_generator::File *file,
static const char *headers_strs[] = {
"grpc++/impl/codegen/async_stream.h",
"grpc++/impl/codegen/sync_stream.h", "gmock/gmock.h",
"grpc++/impl/codegen/sync_stream.h",
"gmock/gmock.h",
};
std::vector<grpc::string> headers(headers_strs, array_end(headers_strs));
PrintIncludes(printer.get(), headers, params);
@@ -1478,50 +1632,83 @@ void PrintMockClientMethods(grpc_generator::Printer *printer,
(*vars)["Request"] = method->input_type_name();
(*vars)["Response"] = method->output_type_name();
struct {
grpc::string prefix;
grpc::string method_params; // extra arguments to method
int extra_method_param_count;
} async_prefixes[] = {{"Async", ", void* tag", 1}, {"PrepareAsync", "", 0}};
if (method->NoStreaming()) {
printer->Print(
*vars,
"MOCK_METHOD3($Method$, ::grpc::Status(::grpc::ClientContext* context, "
"const $Request$& request, $Response$* response));\n");
printer->Print(*vars,
"MOCK_METHOD3(Async$Method$Raw, "
"::grpc::ClientAsyncResponseReaderInterface< $Response$>*"
"(::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq));\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
printer->Print(
*vars,
"MOCK_METHOD3($AsyncPrefix$$Method$Raw, "
"::grpc::ClientAsyncResponseReaderInterface< $Response$>*"
"(::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq));\n");
}
} else if (ClientOnlyStreaming(method)) {
printer->Print(
*vars,
"MOCK_METHOD2($Method$Raw, "
"::grpc::ClientWriterInterface< $Request$>*"
"(::grpc::ClientContext* context, $Response$* response));\n");
printer->Print(*vars,
"MOCK_METHOD4(Async$Method$Raw, "
"::grpc::ClientAsyncWriterInterface< $Request$>*"
"(::grpc::ClientContext* context, $Response$* response, "
"::grpc::CompletionQueue* cq, void* tag));\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["MockArgs"] =
flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
printer->Print(*vars,
"MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
"::grpc::ClientAsyncWriterInterface< $Request$>*"
"(::grpc::ClientContext* context, $Response$* response, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
}
} else if (ServerOnlyStreaming(method)) {
printer->Print(
*vars,
"MOCK_METHOD2($Method$Raw, "
"::grpc::ClientReaderInterface< $Response$>*"
"(::grpc::ClientContext* context, const $Request$& request));\n");
printer->Print(*vars,
"MOCK_METHOD4(Async$Method$Raw, "
"::grpc::ClientAsyncReaderInterface< $Response$>*"
"(::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq, void* tag));\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["MockArgs"] =
flatbuffers::NumToString(3 + async_prefix.extra_method_param_count);
printer->Print(
*vars,
"MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
"::grpc::ClientAsyncReaderInterface< $Response$>*"
"(::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq$AsyncMethodParams$));\n");
}
} else if (method->BidiStreaming()) {
printer->Print(
*vars,
"MOCK_METHOD1($Method$Raw, "
"::grpc::ClientReaderWriterInterface< $Request$, $Response$>*"
"(::grpc::ClientContext* context));\n");
printer->Print(
*vars,
"MOCK_METHOD3(Async$Method$Raw, "
"::grpc::ClientAsyncReaderWriterInterface<$Request$, $Response$>*"
"(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq, "
"void* tag));\n");
for (size_t i = 0; i < sizeof(async_prefixes)/sizeof(async_prefixes[0]); i ++) {
auto& async_prefix = async_prefixes[i];
(*vars)["AsyncPrefix"] = async_prefix.prefix;
(*vars)["AsyncMethodParams"] = async_prefix.method_params;
(*vars)["MockArgs"] =
flatbuffers::NumToString(2 + async_prefix.extra_method_param_count);
printer->Print(
*vars,
"MOCK_METHOD$MockArgs$($AsyncPrefix$$Method$Raw, "
"::grpc::ClientAsyncReaderWriterInterface<$Request$, $Response$>*"
"(::grpc::ClientContext* context, ::grpc::CompletionQueue* cq"
"$AsyncMethodParams$));\n");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,87 @@
/*
* Copyright 2016 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef NET_GRPC_COMPILER_JAVA_GENERATOR_H_
#define NET_GRPC_COMPILER_JAVA_GENERATOR_H_
#include <stdlib.h> // for abort()
#include <iostream>
#include <map>
#include <string>
#include "src/compiler/schema_interface.h"
class LogMessageVoidify {
public:
LogMessageVoidify() {}
// This has to be an operator with a precedence lower than << but
// higher than ?:
void operator&(std::ostream&) {}
};
class LogHelper {
std::ostream* os_;
public:
LogHelper(std::ostream* os) : os_(os) {}
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning( \
disable : 4722) // the flow of control terminates in a destructor
// (needed to compile ~LogHelper where destructor emits abort intentionally -
// inherited from grpc/java code generator).
#endif
~LogHelper() {
*os_ << std::endl;
::abort();
}
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
std::ostream& get_os() const { return *os_; }
};
// Abort the program after logging the mesage if the given condition is not
// true. Otherwise, do nothing.
#define GRPC_CODEGEN_CHECK(x) \
(x) ? (void)0 \
: LogMessageVoidify() & LogHelper(&std::cerr).get_os() \
<< "CHECK FAILED: " << __FILE__ << ":" \
<< __LINE__ << ": "
// Abort the program after logging the mesage.
#define GRPC_CODEGEN_FAIL GRPC_CODEGEN_CHECK(false)
using namespace std;
namespace grpc_java_generator {
struct Parameters {
// //Defines the custom parameter types for methods
// //eg: flatbuffers uses flatbuffers.Builder as input for the client
// and output for the server grpc::string custom_method_io_type;
// Package name for the service
grpc::string package_name;
};
// Return the source of the generated service file.
grpc::string GenerateServiceSource(grpc_generator::File* file,
const grpc_generator::Service* service,
grpc_java_generator::Parameters* parameters);
} // namespace grpc_java_generator
#endif // NET_GRPC_COMPILER_JAVA_GENERATOR_H_

View File

@@ -40,8 +40,8 @@
#include <vector>
#ifndef GRPC_CUSTOM_STRING
#include <string>
#define GRPC_CUSTOM_STRING std::string
# include <string>
# define GRPC_CUSTOM_STRING std::string
#endif
namespace grpc {

View File

@@ -0,0 +1,119 @@
/*
* Copyright 2014 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import MyGame.Example.Monster;
import MyGame.Example.MonsterStorageGrpc;
import MyGame.Example.Stat;
import com.google.flatbuffers.FlatBufferBuilder;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import io.grpc.Server;
import io.grpc.ServerBuilder;
import org.junit.Assert;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Iterator;
/**
* Demonstrates basic client-server interaction using grpc-java over netty.
*/
public class JavaGrpcTest {
static final String BIG_MONSTER_NAME = "big-monster";
static final short nestedMonsterHp = 600;
static final short nestedMonsterMana = 1024;
static final int numStreamedMsgs = 10;
static class MyService extends MonsterStorageGrpc.MonsterStorageImplBase {
@Override
public void store(Monster request, io.grpc.stub.StreamObserver<Stat> responseObserver) {
Assert.assertEquals(request.name(), BIG_MONSTER_NAME);
Assert.assertEquals(request.hp(), nestedMonsterHp);
Assert.assertEquals(request.mana(), nestedMonsterMana);
System.out.println("Received store request from " + request.name());
// Create a response from the incoming request name.
FlatBufferBuilder builder = new FlatBufferBuilder();
int statOffset = Stat.createStat(builder, builder.createString("Hello " + request.name()), 100, 10);
builder.finish(statOffset);
Stat stat = Stat.getRootAsStat(builder.dataBuffer());
responseObserver.onNext(stat);
responseObserver.onCompleted();
}
@Override
public void retrieve(Stat request, io.grpc.stub.StreamObserver<Monster> responseObserver) {
// Create 10 monsters for streaming response.
for (int i=0; i<numStreamedMsgs; i++) {
FlatBufferBuilder builder = new FlatBufferBuilder();
int i1 = builder.createString(request.id() + " No." + i);
Monster.startMonster(builder);
Monster.addName(builder, i1);
int i2 = Monster.endMonster(builder);
Monster.finishMonsterBuffer(builder, i2);
Monster monster = Monster.getRootAsMonster(builder.dataBuffer());
responseObserver.onNext(monster);
}
responseObserver.onCompleted();
}
}
private static int startServer() throws IOException {
Server server = ServerBuilder.forPort(0).addService(new MyService()).build().start();
return server.getPort();
}
@org.junit.Test
public void testMonster() throws IOException {
int port = startServer();
ManagedChannel channel = ManagedChannelBuilder.forAddress("localhost", port)
// Channels are secure by default (via SSL/TLS). For the example we disable TLS to avoid
// needing certificates.
.usePlaintext(true)
.directExecutor()
.build();
MonsterStorageGrpc.MonsterStorageBlockingStub stub = MonsterStorageGrpc.newBlockingStub(channel);
FlatBufferBuilder builder = new FlatBufferBuilder();
int o_string = builder.createString(BIG_MONSTER_NAME);
Monster.startMonster(builder);
Monster.addName(builder, o_string);
Monster.addHp(builder, nestedMonsterHp);
Monster.addMana(builder, nestedMonsterMana);
int monster1 = Monster.endMonster(builder);
Monster.finishMonsterBuffer(builder, monster1);
ByteBuffer buffer = builder.dataBuffer();
Monster monsterRequest = Monster.getRootAsMonster(buffer);
Stat stat = stub.store(monsterRequest);
Assert.assertEquals(stat.id(), "Hello " + BIG_MONSTER_NAME);
System.out.println("Received stat response from service: " + stat.id());
Iterator<Monster> iterator = stub.retrieve(stat);
int counter = 0;
while(iterator.hasNext()) {
Monster m = iterator.next();
System.out.println("Received monster " + m.name());
counter ++;
}
Assert.assertEquals(counter, numStreamedMsgs);
System.out.println("FlatBuffers GRPC client/server test: completed successfully");
}
}

View File

@@ -18,46 +18,48 @@
#include <grpc++/grpc++.h>
#include "monster_test_generated.h"
#include "monster_test.grpc.fb.h"
#include "monster_test_generated.h"
using namespace MyGame::Example;
// The callback implementation of our server, that derives from the generated
// 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::grpc::Message<Monster> *request,
flatbuffers::grpc::Message<Stat> *response)
override {
virtual ::grpc::Status Store(
::grpc::ServerContext *context,
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()));
auto stat_offset = CreateStat(
fbb_, fbb_.CreateString("Hello, " + request->GetRoot()->name()->str()));
fbb_.Finish(stat_offset);
// Transfer ownership of the message to gRPC
*response = fbb_.ReleaseMessage<Stat>();
return grpc::Status::OK;
}
virtual ::grpc::Status Retrieve(::grpc::ServerContext *context,
const flatbuffers::grpc::Message<Stat> *request,
::grpc::ServerWriter< flatbuffers::grpc::Message<Monster>>* writer)
override {
virtual ::grpc::Status Retrieve(
::grpc::ServerContext *context,
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);
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>();
flatbuffers::grpc::Message<Monster> monster = fbb_.ReleaseMessage<Monster>();
// Send monster to client using streaming.
writer->Write(monster);
}
return grpc::Status::OK;
// Send monster to client using streaming.
writer->Write(monster);
}
return grpc::Status::OK;
}
private:
@@ -90,7 +92,7 @@ void RunServer() {
server_instance->Wait();
}
int main(int /*argc*/, const char * /*argv*/[]) {
int main(int /*argc*/, const char * /*argv*/ []) {
// Launch server.
std::thread server_thread(RunServer);
@@ -103,7 +105,6 @@ int main(int /*argc*/, const char * /*argv*/[]) {
grpc::InsecureChannelCredentials());
auto stub = MyGame::Example::MonsterStorage::NewStub(channel);
flatbuffers::grpc::MessageBuilder fbb;
{
grpc::ClientContext context;
@@ -138,7 +139,7 @@ int main(int /*argc*/, const char * /*argv*/[]) {
}
}
#if !FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
#if !FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
{
// Test that an invalid request errors out correctly
grpc::ClientContext context;
@@ -149,9 +150,10 @@ int main(int /*argc*/, const char * /*argv*/[]) {
// 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);
assert(strcmp(status.error_message().c_str(),
"Message verification failed") == 0);
}
#endif
#endif
server_instance->Shutdown();

4
grpc/tests/java-grpc-test.sh Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
# NOTE: make sure `mvn install` in /gprc is executed before running this test
mvn test

73
grpc/tests/pom.xml Normal file
View File

@@ -0,0 +1,73 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-parent</artifactId>
<version>1.8.0</version>
</parent>
<artifactId>grpc-test</artifactId>
<description>Example/Test project demonstrating usage of flatbuffers with GRPC-Java instead of protobufs
</description>
<properties>
<gRPC.version>1.8.0</gRPC.version>
</properties>
<dependencies>
<dependency>
<groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-java</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-java-grpc</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>${gRPC.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>${gRPC.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-test-source</goal>
</goals>
<configuration>
<sources>
<source>${project.basedir}</source>
<source>${project.basedir}/../../tests</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
<!--<testSourceDirectory>${project.basedir}</testSourceDirectory>-->
</build>
</project>

View File

@@ -1,20 +1,36 @@
#ifndef FLATBUFFERS_BASE_H_
#define FLATBUFFERS_BASE_H_
// clang-format off
#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \
defined(_MSC_VER) && defined(_DEBUG)
#define _CRTDBG_MAP_ALLOC
#endif
#include <assert.h>
#ifndef ARDUINO
#include <cstdint>
#endif
#include <cstddef>
#include <cstdlib>
#include <cstring>
#include <string>
#ifndef ARDUINO
#include <utility>
#else
#include <utility.h>
#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>
@@ -29,6 +45,8 @@
#include <functional>
#endif
#include "flatbuffers/stl_emulation.h"
/// @cond FLATBUFFERS_INTERNAL
#if __cplusplus <= 199711L && \
(!defined(_MSC_VER) || _MSC_VER < 1600) && \
@@ -82,7 +100,7 @@
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
#define FLATBUFFERS_VERSION_MAJOR 1
#define FLATBUFFERS_VERSION_MINOR 7
#define FLATBUFFERS_VERSION_MINOR 9
#define FLATBUFFERS_VERSION_REVISION 0
#define FLATBUFFERS_STRING_EXPAND(X) #X
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
@@ -103,6 +121,13 @@
#define FLATBUFFERS_CONSTEXPR
#endif
#if (defined(__cplusplus) && __cplusplus >= 201402L) || \
(defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
#define FLATBUFFERS_CONSTEXPR_CPP14 FLATBUFFERS_CONSTEXPR
#else
#define FLATBUFFERS_CONSTEXPR_CPP14
#endif
#if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46 || \
defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026
#define FLATBUFFERS_NOEXCEPT noexcept
@@ -120,8 +145,8 @@
#endif
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable: 4127) // C4127: conditional expression is constant
#pragma warning(push)
#pragma warning(disable: 4127) // C4127: conditional expression is constant
#endif
/// @endcond
@@ -150,6 +175,45 @@ typedef uintmax_t largest_scalar_t;
// 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;
@@ -173,5 +237,5 @@ 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

@@ -49,7 +49,7 @@ class CodeWriter {
// Associates a key with a value. All subsequent calls to operator+=, where
// the specified key is contained in {{ and }} delimiters will be replaced by
// the given value.
void SetValue(const std::string& key, const std::string& value) {
void SetValue(const std::string &key, const std::string &value) {
value_map_[key] = value;
}
@@ -71,8 +71,7 @@ class BaseGenerator {
public:
virtual bool generate() = 0;
static std::string NamespaceDir(const Parser &parser,
const std::string &path,
static std::string NamespaceDir(const Parser &parser, const std::string &path,
const Namespace &ns);
protected:
@@ -128,8 +127,7 @@ struct CommentConfig {
};
extern void GenComment(const std::vector<std::string> &dc,
std::string *code_ptr,
const CommentConfig *config,
std::string *code_ptr, const CommentConfig *config,
const char *prefix = "");
} // namespace flatbuffers

File diff suppressed because it is too large Load Diff

View File

@@ -14,15 +14,15 @@
* limitations under the License.
*/
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include <functional>
#include <limits>
#include <string>
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#ifndef FLATC_H_
#define FLATC_H_
# define FLATC_H_
namespace flatbuffers {
@@ -49,12 +49,10 @@ class FlatCompiler {
MakeRuleFn make_rule;
};
typedef void (*WarnFn)(const FlatCompiler *flatc,
const std::string &warn,
typedef void (*WarnFn)(const FlatCompiler *flatc, const std::string &warn,
bool show_exe_name);
typedef void (*ErrorFn)(const FlatCompiler *flatc,
const std::string &err,
typedef void (*ErrorFn)(const FlatCompiler *flatc, const std::string &err,
bool usage, bool show_exe_name);
// Parameters required to initialize the FlatCompiler.
@@ -65,21 +63,20 @@ class FlatCompiler {
warn_fn(nullptr),
error_fn(nullptr) {}
const Generator* generators;
const Generator *generators;
size_t num_generators;
WarnFn warn_fn;
ErrorFn error_fn;
};
explicit FlatCompiler(const InitParams& params) : params_(params) {}
explicit FlatCompiler(const InitParams &params) : params_(params) {}
int Compile(int argc, const char** argv);
int Compile(int argc, const char **argv);
std::string GetUsageString(const char* program_name) const;
std::string GetUsageString(const char *program_name) const;
private:
void ParseFile(flatbuffers::Parser &parser,
const std::string &filename,
void ParseFile(flatbuffers::Parser &parser, const std::string &filename,
const std::string &contents,
std::vector<const char *> &include_directories) const;
@@ -91,7 +88,6 @@ class FlatCompiler {
InitParams params_;
};
} // namespace flatbuffers
#endif // FLATC_H_

File diff suppressed because it is too large Load Diff

View File

@@ -30,13 +30,12 @@ namespace grpc {
// `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 {
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) {}
: slice_(add_ref ? grpc_slice_ref(slice) : slice) {}
Message &operator=(const Message &other) = delete;
@@ -105,14 +104,16 @@ class SliceAllocator : public Allocator {
}
virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
size_t new_size) override {
size_t new_size, size_t in_use_back,
size_t in_use_front) override {
assert(old_p == GRPC_SLICE_START_PTR(slice_));
assert(old_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);
memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
in_use_front);
slice_ = new_slice;
grpc_slice_unref(old_slice);
return new_p;
@@ -137,7 +138,7 @@ namespace detail {
struct SliceAllocatorMember {
SliceAllocator slice_allocator_;
};
}
} // namespace detail
// MessageBuilder is a gRPC-specific FlatBufferBuilder that uses SliceAllocator
// to allocate gRPC buffers.
@@ -145,7 +146,7 @@ class MessageBuilder : private detail::SliceAllocatorMember,
public FlatBufferBuilder {
public:
explicit MessageBuilder(uoffset_t initial_size = 1024)
: FlatBufferBuilder(initial_size, &slice_allocator_, false) {}
: FlatBufferBuilder(initial_size, &slice_allocator_, false) {}
MessageBuilder(const MessageBuilder &other) = delete;
MessageBuilder &operator=(const MessageBuilder &other) = delete;
@@ -155,9 +156,8 @@ class MessageBuilder : private detail::SliceAllocatorMember,
// 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
template<class T> Message<T> GetMessage() {
auto buf_data = buf_.scratch_data(); // pointer to memory
auto buf_size = buf_.capacity(); // size of memory
auto msg_data = buf_.data(); // pointer to msg
auto msg_size = buf_.size(); // size of msg
@@ -178,8 +178,7 @@ class MessageBuilder : private detail::SliceAllocatorMember,
return msg;
}
template <class T>
Message<T> ReleaseMessage() {
template<class T> Message<T> ReleaseMessage() {
Message<T> msg = GetMessage<T>();
Reset();
return msg;
@@ -194,8 +193,7 @@ class MessageBuilder : private detail::SliceAllocatorMember,
namespace grpc {
template <class T>
class SerializationTraits<flatbuffers::grpc::Message<T>> {
template<class T> class SerializationTraits<flatbuffers::grpc::Message<T>> {
public:
static grpc::Status Serialize(const flatbuffers::grpc::Message<T> &msg,
grpc_byte_buffer **buffer, bool *own_buffer) {
@@ -237,19 +235,19 @@ class SerializationTraits<flatbuffers::grpc::Message<T>> {
*msg = flatbuffers::grpc::Message<T>(slice, false);
}
grpc_byte_buffer_destroy(buffer);
#if FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
#if FLATBUFFERS_GRPC_DISABLE_AUTO_VERIFICATION
return ::grpc::Status::OK;
#else
#else
if (msg->Verify()) {
return ::grpc::Status::OK;
} else {
return ::grpc::Status(::grpc::StatusCode::INTERNAL,
"Message verification failed");
}
#endif
#endif
}
};
} // namespace grpc;
} // namespace grpc
#endif // FLATBUFFERS_GRPC_H_

View File

@@ -24,26 +24,22 @@
namespace flatbuffers {
template <typename T>
struct FnvTraits {
template<typename T> struct FnvTraits {
static const T kFnvPrime;
static const T kOffsetBasis;
};
template <>
struct FnvTraits<uint32_t> {
template<> struct FnvTraits<uint32_t> {
static const uint32_t kFnvPrime = 0x01000193;
static const uint32_t kOffsetBasis = 0x811C9DC5;
};
template <>
struct FnvTraits<uint64_t> {
template<> struct FnvTraits<uint64_t> {
static const uint64_t kFnvPrime = 0x00000100000001b3ULL;
static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL;
};
template <typename T>
T HashFnv1(const char *input) {
template<typename T> FLATBUFFERS_CONSTEXPR_CPP14 T HashFnv1(const char *input) {
T hash = FnvTraits<T>::kOffsetBasis;
for (const char *c = input; *c; ++c) {
hash *= FnvTraits<T>::kFnvPrime;
@@ -52,8 +48,7 @@ T HashFnv1(const char *input) {
return hash;
}
template <typename T>
T HashFnv1a(const char *input) {
template<typename T> FLATBUFFERS_CONSTEXPR_CPP14 T HashFnv1a(const char *input) {
T hash = FnvTraits<T>::kOffsetBasis;
for (const char *c = input; *c; ++c) {
hash ^= static_cast<unsigned char>(*c);
@@ -62,24 +57,49 @@ T HashFnv1a(const char *input) {
return hash;
}
template <typename T>
struct NamedHashFunction {
template <> FLATBUFFERS_CONSTEXPR_CPP14 inline uint16_t HashFnv1<uint16_t>(const char *input) {
uint32_t hash = HashFnv1<uint32_t>(input);
return (hash >> 16) ^ (hash & 0xffff);
}
template <> FLATBUFFERS_CONSTEXPR_CPP14 inline uint16_t HashFnv1a<uint16_t>(const char *input) {
uint32_t hash = HashFnv1a<uint32_t>(input);
return (hash >> 16) ^ (hash & 0xffff);
}
template <typename T> struct NamedHashFunction {
const char *name;
typedef T (*HashFunction)(const char*);
typedef T (*HashFunction)(const char *);
HashFunction function;
};
const NamedHashFunction<uint16_t> kHashFunctions16[] = {
{ "fnv1_16", HashFnv1<uint16_t> },
{ "fnv1a_16", HashFnv1a<uint16_t> },
};
const NamedHashFunction<uint32_t> kHashFunctions32[] = {
{ "fnv1_32", HashFnv1<uint32_t> },
{ "fnv1_32", HashFnv1<uint32_t> },
{ "fnv1a_32", HashFnv1a<uint32_t> },
};
const NamedHashFunction<uint64_t> kHashFunctions64[] = {
{ "fnv1_64", HashFnv1<uint64_t> },
{ "fnv1_64", HashFnv1<uint64_t> },
{ "fnv1a_64", HashFnv1a<uint64_t> },
};
inline NamedHashFunction<uint16_t>::HashFunction FindHashFunction16(
const char *name) {
std::size_t size = sizeof(kHashFunctions16) / sizeof(kHashFunctions16[0]);
for (std::size_t i = 0; i < size; ++i) {
if (std::strcmp(name, kHashFunctions16[i].name) == 0) {
return kHashFunctions16[i].function;
}
}
return nullptr;
}
inline NamedHashFunction<uint32_t>::HashFunction FindHashFunction32(
const char *name) {
std::size_t size = sizeof(kHashFunctions32) / sizeof(kHashFunctions32[0]);

View File

@@ -18,14 +18,18 @@
#define FLATBUFFERS_IDL_H_
#include <map>
#include <stack>
#include <memory>
#include <functional>
#include <stack>
#include "flatbuffers/base.h"
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/flexbuffers.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.
@@ -35,6 +39,7 @@ namespace flatbuffers {
// The order of these matters for Is*() functions below.
// Additionally, Parser::ParseType assumes bool..string is a contiguous range
// of type tokens.
// clang-format off
#define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \
TD(NONE, "", uint8_t, byte, byte, byte, uint8) \
TD(UTYPE, "", uint8_t, byte, byte, byte, uint8) /* begin scalar/int */ \
@@ -105,13 +110,13 @@ inline bool IsFloat (BaseType t) { return t == BASE_TYPE_FLOAT ||
t == BASE_TYPE_DOUBLE; }
inline bool IsLong (BaseType t) { return t == BASE_TYPE_LONG ||
t == BASE_TYPE_ULONG; }
inline bool IsBool (BaseType t) { return t == BASE_TYPE_BOOL; }
// clang-format on
extern const char *const kTypeNames[];
extern const char kTypeSizes[];
inline size_t SizeOf(BaseType t) {
return kTypeSizes[t];
}
inline size_t SizeOf(BaseType t) { return kTypeSizes[t]; }
struct StructDef;
struct EnumDef;
@@ -120,13 +125,12 @@ class Parser;
// Represents any type in the IDL, which is a combination of the BaseType
// and additional information for vectors/structs_.
struct Type {
explicit Type(BaseType _base_type = BASE_TYPE_NONE,
StructDef *_sd = nullptr, EnumDef *_ed = nullptr)
: base_type(_base_type),
element(BASE_TYPE_NONE),
struct_def(_sd),
enum_def(_ed)
{}
explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr,
EnumDef *_ed = nullptr)
: base_type(_base_type),
element(BASE_TYPE_NONE),
struct_def(_sd),
enum_def(_ed) {}
bool operator==(const Type &o) {
return base_type == o.base_type && element == o.element &&
@@ -146,8 +150,9 @@ struct Type {
// Represents a parsed scalar value, it's type, and field offset.
struct Value {
Value() : constant("0"), offset(static_cast<voffset_t>(
~(static_cast<voffset_t>(0U)))) {}
Value()
: constant("0"),
offset(static_cast<voffset_t>(~(static_cast<voffset_t>(0U)))) {}
Type type;
std::string constant;
voffset_t offset;
@@ -158,13 +163,11 @@ struct Value {
template<typename T> class SymbolTable {
public:
~SymbolTable() {
for (auto it = vec.begin(); it != vec.end(); ++it) {
delete *it;
}
for (auto it = vec.begin(); it != vec.end(); ++it) { delete *it; }
}
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;
@@ -188,13 +191,13 @@ template<typename T> class SymbolTable {
}
public:
std::map<std::string, T *> dict; // quick lookup
std::vector<T *> vec; // Used to iterate in order of insertion
std::map<std::string, T *> dict; // quick lookup
std::vector<T *> vec; // Used to iterate in order of insertion
};
// 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.
@@ -202,17 +205,23 @@ 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) {}
Definition()
: generated(false),
defined_namespace(nullptr),
serialized_location(0),
index(-1),
refcount(1) {}
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<
reflection::KeyValue>>>
SerializeAttributes(FlatBufferBuilder *builder,
const Parser &parser) const;
flatbuffers::Offset<
flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>>
SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const;
std::string name;
std::string file;
@@ -224,35 +233,42 @@ 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),
flexbuffer(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.
// 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 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.
size_t padding; // Bytes to always pad after this field.
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.
};
struct StructDef : public Definition {
StructDef()
: fixed(false),
predecl(true),
sortbysize(true),
has_key(false),
minalign(1),
bytesize(0)
{}
: fixed(false),
predecl(true),
sortbysize(true),
has_key(false),
minalign(1),
bytesize(0) {}
void PadLastField(size_t min_align) {
auto padding = PaddingBytes(bytesize, min_align);
@@ -264,12 +280,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) {
@@ -285,8 +304,7 @@ inline size_t InlineAlignment(const Type &type) {
}
struct EnumVal {
EnumVal(const std::string &_name, int64_t _val)
: name(_name), value(_val) {}
EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {}
Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder) const;
@@ -299,13 +317,11 @@ struct EnumVal {
struct EnumDef : public Definition {
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 &&
skip_union_default);
it != vals.vec.end(); ++it) {
if ((*it)->value == enum_idx) {
return *it;
}
EnumVal *ReverseLookup(int64_t enum_idx, bool skip_union_default = true) {
for (auto it = vals.vec.begin() +
static_cast<int>(is_union && skip_union_default);
it != vals.vec.end(); ++it) {
if ((*it)->value == enum_idx) { return *it; }
}
return nullptr;
}
@@ -323,14 +339,14 @@ inline bool EqualByName(const Type &a, const Type &b) {
return a.base_type == b.base_type && a.element == b.element &&
(a.struct_def == b.struct_def ||
a.struct_def->name == b.struct_def->name) &&
(a.enum_def == b.enum_def ||
a.enum_def->name == b.enum_def->name);
(a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name);
}
struct RPCCall {
std::string name;
SymbolTable<Value> attributes;
StructDef *request, *response;
std::vector<std::string> rpc_comment;
};
struct ServiceDef : public Definition {
@@ -351,70 +367,86 @@ struct IDLOptions {
bool mutable_buffer;
bool one_file;
bool proto_mode;
bool proto_oneof_union;
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;
bool size_prefixed;
// Possible options for the more general generator below.
enum Language {
kJava = 1 << 0,
kJava = 1 << 0,
kCSharp = 1 << 1,
kGo = 1 << 2,
kCpp = 1 << 3,
kJs = 1 << 4,
kGo = 1 << 2,
kCpp = 1 << 3,
kJs = 1 << 4,
kPython = 1 << 5,
kPhp = 1 << 6,
kJson = 1 << 7,
kPhp = 1 << 6,
kJson = 1 << 7,
kBinary = 1 << 8,
kTs = 1 << 9,
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;
IDLOptions()
: strict_json(false),
skip_js_exports(false),
use_goog_js_export_format(false),
output_default_scalars_in_json(false),
indent_step(2),
output_enum_identifiers(true), prefixed_enums(true), scoped_enums(false),
include_dependence_headers(true),
mutable_buffer(false),
one_file(false),
proto_mode(false),
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"),
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),
lang_to_generate(0) {}
: strict_json(false),
skip_js_exports(false),
use_goog_js_export_format(false),
output_default_scalars_in_json(false),
indent_step(2),
output_enum_identifiers(true),
prefixed_enums(true),
scoped_enums(false),
include_dependence_headers(true),
mutable_buffer(false),
one_file(false),
proto_mode(false),
proto_oneof_union(false),
generate_all(false),
skip_unexpected_fields_in_json(false),
generate_name_strings(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),
size_prefixed(false),
lang(IDLOptions::kJava),
mini_reflect(IDLOptions::kNone),
lang_to_generate(0) {}
};
// This encapsulates where the parser is in the current source file.
@@ -440,7 +472,7 @@ struct ParserState {
class CheckedError {
public:
explicit CheckedError(bool error)
: is_error_(error), has_been_checked_(false) {}
: is_error_(error), has_been_checked_(false) {}
CheckedError &operator=(const CheckedError &other) {
is_error_ = other.is_error_;
@@ -455,7 +487,10 @@ class CheckedError {
~CheckedError() { assert(has_been_checked_); }
bool Check() { has_been_checked_ = true; return is_error_; }
bool Check() {
has_been_checked_ = true;
return is_error_;
}
private:
bool is_error_;
@@ -464,23 +499,29 @@ class CheckedError {
// Additionally, in GCC we can get these errors statically, for additional
// assurance:
// clang-format off
#ifdef __GNUC__
#define FLATBUFFERS_CHECKED_ERROR CheckedError \
__attribute__((warn_unused_result))
#else
#define FLATBUFFERS_CHECKED_ERROR CheckedError
#endif
// clang-format on
class Parser : public ParserState {
public:
explicit Parser(const IDLOptions &options = IDLOptions())
: 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());
: current_namespace_(nullptr),
empty_namespace_(nullptr),
root_struct_def_(nullptr),
opts(options),
uses_flexbuffers_(false),
source_(nullptr),
anonymous_counter(0) {
// Start out with the empty namespace being current.
empty_namespace_ = new Namespace();
namespaces_.push_back(empty_namespace_);
current_namespace_ = empty_namespace_;
known_attributes_["deprecated"] = true;
known_attributes_["required"] = true;
known_attributes_["key"] = true;
@@ -495,8 +536,10 @@ class Parser : public ParserState {
known_attributes_["idempotent"] = true;
known_attributes_["cpp_type"] = true;
known_attributes_["cpp_ptr_type"] = true;
known_attributes_["cpp_ptr_type_get"] = true;
known_attributes_["cpp_str_type"] = true;
known_attributes_["native_inline"] = true;
known_attributes_["native_custom_alloc"] = true;
known_attributes_["native_type"] = true;
known_attributes_["native_default"] = true;
known_attributes_["flexbuffer"] = true;
@@ -548,14 +591,19 @@ class Parser : public ParserState {
FLATBUFFERS_CHECKED_ERROR CheckInRange(int64_t val, int64_t min, int64_t max);
private:
StructDef *LookupStruct(const std::string &id) const;
private:
void Message(const std::string &msg);
void Warning(const std::string &msg);
FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
FLATBUFFERS_CHECKED_ERROR Next();
FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
bool Is(int t);
bool Is(int t) const;
bool IsIdent(const char *id) const;
FLATBUFFERS_CHECKED_ERROR Expect(int t);
std::string TokenToStringId(int t);
std::string TokenToStringId(int t) const;
EnumDef *LookupEnum(const std::string &id);
FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id,
std::string *last);
@@ -570,22 +618,45 @@ private:
FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field,
size_t parent_fieldn,
const StructDef *parent_struct_def);
// clang-format off
#if defined(FLATBUFFERS_CPP98_STL)
typedef CheckedError (*ParseTableDelimitersBody)(
const std::string &name, size_t &fieldn, const StructDef *struct_def,
void *state);
#else
typedef std::function<CheckedError(const std::string&, size_t&,
const StructDef*, void*)>
ParseTableDelimitersBody;
#endif // defined(FLATBUFFERS_CPP98_STL)
// clang-format on
FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn,
const StructDef *struct_def,
const std::function<CheckedError(const std::string &name)> &body);
ParseTableDelimitersBody body,
void *state);
FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def,
std::string *value, uoffset_t *ovalue);
void SerializeStruct(const StructDef &struct_def, const Value &val);
void AddVector(bool sortbysize, int count);
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(size_t &count,
const std::function<CheckedError()> &body);
// clang-format off
#if defined(FLATBUFFERS_CPP98_STL)
typedef CheckedError (*ParseVectorDelimitersBody)(size_t &count,
void *state);
#else
typedef std::function<CheckedError(size_t&, void*)>
ParseVectorDelimitersBody;
#endif // defined(FLATBUFFERS_CPP98_STL)
// clang-format on
FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(
size_t &count, ParseVectorDelimitersBody body, void *state);
FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue);
FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field,
size_t fieldn,
const StructDef *parent_struct_def);
FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes);
FLATBUFFERS_CHECKED_ERROR TryTypedValue(int dtoken, bool check, Value &e,
FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken, bool check, Value &e,
BaseType req, bool *destmatch);
FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef* field);
FLATBUFFERS_CHECKED_ERROR TokenError();
FLATBUFFERS_CHECKED_ERROR ParseSingleValue(Value &e);
FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e);
FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(Type &type, int64_t *result);
StructDef *LookupCreateStruct(const std::string &name,
bool create_if_new = true,
@@ -594,6 +665,9 @@ private:
FLATBUFFERS_CHECKED_ERROR ParseNamespace();
FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name,
StructDef **dest);
FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name,
bool is_union,
EnumDef **dest);
FLATBUFFERS_CHECKED_ERROR ParseDecl();
FLATBUFFERS_CHECKED_ERROR ParseService();
FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def,
@@ -607,21 +681,29 @@ private:
FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder);
FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source,
const char *source_filename);
FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source,
FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source,
const char **include_paths,
const char *source_filename,
const char *include_filename);
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
@@ -676,15 +758,12 @@ extern bool GenerateBinary(const Parser &parser,
// Generate a C++ header from the definitions in the Parser object.
// See idl_gen_cpp.
extern std::string GenerateCPP(const Parser &parser,
const std::string &include_guard_ident);
extern bool GenerateCPP(const Parser &parser,
const std::string &path,
const std::string &file_name);
// Generate JavaScript or TypeScript code from the definitions in the Parser object.
// See idl_gen_js.
extern std::string GenerateJS(const Parser &parser);
extern bool GenerateJS(const Parser &parser,
const std::string &path,
const std::string &file_name);
@@ -695,12 +774,6 @@ extern bool GenerateGo(const Parser &parser,
const std::string &path,
const std::string &file_name);
// Generate Java files from the definitions in the Parser object.
// See idl_gen_java.cpp.
extern bool GenerateJava(const Parser &parser,
const std::string &path,
const std::string &file_name);
// Generate Php code from the definitions in the Parser object.
// See idl_gen_php.
extern bool GeneratePhp(const Parser &parser,
@@ -713,9 +786,9 @@ extern bool GeneratePython(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,
// 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);
@@ -775,6 +848,12 @@ bool GenerateGoGRPC(const Parser &parser,
const std::string &path,
const std::string &file_name);
// Generate GRPC Java classes.
// See idl_gen_grpc.cpp
bool GenerateJavaGRPC(const Parser &parser,
const std::string &path,
const std::string &file_name);
} // namespace flatbuffers
#endif // FLATBUFFERS_IDL_H_

View File

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

View File

@@ -30,14 +30,18 @@ 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; }
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) {
@@ -48,8 +52,7 @@ inline size_t GetTypeSize(reflection::BaseType base_type) {
// Same as above, but now correctly returns the size of a struct if
// the field (or vector element) is a struct.
inline size_t GetTypeSizeInline(reflection::BaseType base_type,
int type_index,
inline size_t GetTypeSizeInline(reflection::BaseType base_type, int type_index,
const reflection::Schema &schema) {
if (base_type == reflection::Obj &&
schema.objects()->Get(type_index)->is_struct()) {
@@ -80,16 +83,16 @@ template<typename T> T GetFieldDefaultF(const reflection::Field &field) {
}
// Get a field, if you know it's an integer, and its exact type.
template<typename T> T GetFieldI(const Table &table,
const reflection::Field &field) {
template<typename T>
T GetFieldI(const Table &table, const reflection::Field &field) {
assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
return table.GetField<T>(field.offset(),
static_cast<T>(field.default_integer()));
}
// Get a field, if you know it's floating point and its exact type.
template<typename T> T GetFieldF(const Table &table,
const reflection::Field &field) {
template<typename T>
T GetFieldF(const Table &table, const reflection::Field &field) {
assert(sizeof(T) == GetTypeSize(field.type()->base_type()));
return table.GetField<T>(field.offset(),
static_cast<T>(field.default_real()));
@@ -103,8 +106,8 @@ inline const String *GetFieldS(const Table &table,
}
// Get a field, if you know it's a vector.
template<typename T> Vector<T> *GetFieldV(const Table &table,
const reflection::Field &field) {
template<typename T>
Vector<T> *GetFieldV(const Table &table, const reflection::Field &field) {
assert(field.type()->base_type() == reflection::Vector &&
sizeof(T) == GetTypeSize(field.type()->element()));
return table.GetPointer<Vector<T> *>(field.offset());
@@ -119,8 +122,7 @@ inline VectorOfAny *GetFieldAnyV(const Table &table,
}
// Get a field, if you know it's a table.
inline Table *GetFieldT(const Table &table,
const reflection::Field &field) {
inline Table *GetFieldT(const Table &table, const reflection::Field &field) {
assert(field.type()->base_type() == reflection::Obj ||
field.type()->base_type() == reflection::Union);
return table.GetPointer<Table *>(field.offset());
@@ -153,8 +155,7 @@ double GetAnyValueF(reflection::BaseType type, const uint8_t *data);
// All scalars converted using stringstream, strings as-is, and all other
// data types provide some level of debug-pretty-printing.
std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data,
const reflection::Schema *schema,
int type_index);
const reflection::Schema *schema, int type_index);
// Get any table field as a 64bit int, regardless of what type it is.
inline int64_t GetAnyFieldI(const Table &table,
@@ -165,14 +166,12 @@ inline int64_t GetAnyFieldI(const Table &table,
}
// Get any table field as a double, regardless of what type it is.
inline double GetAnyFieldF(const Table &table,
const reflection::Field &field) {
inline double GetAnyFieldF(const Table &table, const reflection::Field &field) {
auto field_ptr = table.GetAddressOf(field.offset());
return field_ptr ? GetAnyValueF(field.type()->base_type(), field_ptr)
: field.default_real();
}
// Get any table field as a string, regardless of what type it is.
// You may pass nullptr for the schema if you don't care to have fields that
// are of table type pretty-printed.
@@ -186,15 +185,13 @@ inline std::string GetAnyFieldS(const Table &table,
}
// Get any struct field as a 64bit int, regardless of what type it is.
inline int64_t GetAnyFieldI(const Struct &st,
const reflection::Field &field) {
inline int64_t GetAnyFieldI(const Struct &st, const reflection::Field &field) {
return GetAnyValueI(field.type()->base_type(),
st.GetAddressOf(field.offset()));
}
// Get any struct field as a double, regardless of what type it is.
inline double GetAnyFieldF(const Struct &st,
const reflection::Field &field) {
inline double GetAnyFieldF(const Struct &st, const reflection::Field &field) {
return GetAnyValueF(field.type()->base_type(),
st.GetAddressOf(field.offset()));
}
@@ -228,8 +225,8 @@ inline std::string GetAnyVectorElemS(const VectorOfAny *vec,
// Get a vector element that's a table/string/vector from a generic vector.
// Pass Table/String/VectorOfAny as template parameter.
// Warning: does no typechecking.
template<typename T> T *GetAnyVectorElemPointer(const VectorOfAny *vec,
size_t i) {
template<typename T>
T *GetAnyVectorElemPointer(const VectorOfAny *vec, size_t i) {
auto elem_ptr = vec->Data() + sizeof(uoffset_t) * i;
return (T *)(elem_ptr + ReadScalar<uoffset_t>(elem_ptr));
}
@@ -239,34 +236,32 @@ template<typename T> T *GetAnyVectorElemPointer(const VectorOfAny *vec,
// Get elem_size from GetTypeSizeInline().
// Note: little-endian data on all platforms, use EndianScalar() instead of
// raw pointer access with scalars).
template<typename T> T *GetAnyVectorElemAddressOf(const VectorOfAny *vec,
size_t i,
size_t elem_size) {
template<typename T>
T *GetAnyVectorElemAddressOf(const VectorOfAny *vec, size_t i,
size_t elem_size) {
// C-cast to allow const conversion.
return (T *)(vec->Data() + elem_size * i);
}
// Similarly, for elements of tables.
template<typename T> T *GetAnyFieldAddressOf(const Table &table,
const reflection::Field &field) {
template<typename T>
T *GetAnyFieldAddressOf(const Table &table, const reflection::Field &field) {
return (T *)table.GetAddressOf(field.offset());
}
// Similarly, for elements of structs.
template<typename T> T *GetAnyFieldAddressOf(const Struct &st,
const reflection::Field &field) {
template<typename T>
T *GetAnyFieldAddressOf(const Struct &st, const reflection::Field &field) {
return (T *)st.GetAddressOf(field.offset());
}
// ------------------------- SETTERS -------------------------
// Set any scalar field, if you know its exact type.
template<typename T> bool SetField(Table *table, const reflection::Field &field,
T val) {
template<typename T>
bool SetField(Table *table, const reflection::Field &field, T val) {
reflection::BaseType type = field.type()->base_type();
if (!IsScalar(type)) {
return false;
}
if (!IsScalar(type)) { return false; }
assert(sizeof(T) == GetTypeSize(type));
T def;
if (IsInteger(type)) {
@@ -306,7 +301,7 @@ inline bool SetAnyFieldF(Table *table, const reflection::Field &field,
// Set any table field as a string, regardless of what type it is.
inline bool SetAnyFieldS(Table *table, const reflection::Field &field,
const char *val) {
const char *val) {
auto field_ptr = table->GetAddressOf(field.offset());
if (!field_ptr) return false;
SetAnyValueS(field.type()->base_type(), field_ptr, val);
@@ -352,7 +347,6 @@ inline void SetAnyVectorElemS(VectorOfAny *vec, reflection::BaseType elem_type,
SetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val);
}
// ------------------------- RESIZING SETTERS -------------------------
// "smart" pointer for use with resizing vectors: turns a pointer inside
@@ -360,26 +354,25 @@ inline void SetAnyVectorElemS(VectorOfAny *vec, reflection::BaseType elem_type,
template<typename T, typename U> class pointer_inside_vector {
public:
pointer_inside_vector(T *ptr, std::vector<U> &vec)
: offset_(reinterpret_cast<uint8_t *>(ptr) -
reinterpret_cast<uint8_t *>(vec.data())),
vec_(vec) {}
: offset_(reinterpret_cast<uint8_t *>(ptr) -
reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec))),
vec_(vec) {}
T *operator*() const {
return reinterpret_cast<T *>(
reinterpret_cast<uint8_t *>(vec_.data()) + offset_);
}
T *operator->() const {
return operator*();
reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec_)) + offset_);
}
T *operator->() const { return operator*(); }
void operator=(const pointer_inside_vector &piv);
private:
size_t offset_;
std::vector<U> &vec_;
};
// Helper to create the above easily without specifying template args.
template<typename T, typename U> pointer_inside_vector<T, U> piv(T *ptr,
std::vector<U> &vec) {
template<typename T, typename U>
pointer_inside_vector<T, U> piv(T *ptr, std::vector<U> &vec) {
return pointer_inside_vector<T, U>(ptr, vec);
}
@@ -392,7 +385,7 @@ inline const reflection::Object &GetUnionType(
auto enumdef = schema.enums()->Get(unionfield.type()->index());
// TODO: this is clumsy and slow, but no other way to find it?
auto type_field = parent.fields()->LookupByKey(
(unionfield.name()->str() + UnionTypeFieldSuffix()).c_str());
(unionfield.name()->str() + UnionTypeFieldSuffix()).c_str());
assert(type_field);
auto union_type = GetFieldI<uint8_t>(table, *type_field);
auto enumval = enumdef->values()->LookupByKey(union_type);
@@ -418,21 +411,18 @@ uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize,
uoffset_t elem_size, std::vector<uint8_t> *flatbuf,
const reflection::Object *root_table = nullptr);
#ifndef FLATBUFFERS_CPP98_STL
template <typename T>
template<typename T>
void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
const Vector<T> *vec, std::vector<uint8_t> *flatbuf,
const reflection::Object *root_table = nullptr) {
auto delta_elem = static_cast<int>(newsize) - static_cast<int>(vec->size());
auto newelems = ResizeAnyVector(schema, newsize,
reinterpret_cast<const VectorOfAny *>(vec),
vec->size(),
static_cast<uoffset_t>(sizeof(T)), flatbuf,
root_table);
auto newelems = ResizeAnyVector(
schema, newsize, reinterpret_cast<const VectorOfAny *>(vec), vec->size(),
static_cast<uoffset_t>(sizeof(T)), flatbuf, root_table);
// 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
@@ -440,7 +430,6 @@ void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val,
}
}
}
#endif
// Adds any new data (in the form of a new FlatBuffer) to an existing
// FlatBuffer. This can be used when any of the above methods are not
@@ -480,10 +469,8 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
// root should point to the root type for this flatbuffer.
// buf should point to the start of flatbuffer data.
// length specifies the size of the flatbuffer data.
bool Verify(const reflection::Schema &schema,
const reflection::Object &root,
const uint8_t *buf,
size_t length);
bool Verify(const reflection::Schema &schema, const reflection::Object &root,
const uint8_t *buf, size_t length);
} // namespace flatbuffers

View File

@@ -42,8 +42,31 @@ enum BaseType {
Union = 16
};
inline const char **EnumNamesBaseType() {
static const char *names[] = {
inline const BaseType (&EnumValuesBaseType())[17] {
static const BaseType values[] = {
None,
UType,
Bool,
Byte,
UByte,
Short,
UShort,
Int,
UInt,
Long,
ULong,
Float,
Double,
String,
Vector,
Obj,
Union
};
return values;
}
inline const char * const *EnumNamesBaseType() {
static const char * const names[] = {
"None",
"UType",
"Bool",
@@ -107,13 +130,13 @@ struct TypeBuilder {
void add_index(int32_t index) {
fbb_.AddElement<int32_t>(Type::VT_INDEX, index, -1);
}
TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb)
explicit TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
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;
}
@@ -167,13 +190,13 @@ struct KeyValueBuilder {
void add_value(flatbuffers::Offset<flatbuffers::String> value) {
fbb_.AddOffset(KeyValue::VT_VALUE, value);
}
KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb)
explicit KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
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;
@@ -260,13 +283,13 @@ struct EnumValBuilder {
void add_union_type(flatbuffers::Offset<Type> union_type) {
fbb_.AddOffset(EnumVal::VT_UNION_TYPE, union_type);
}
EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb)
explicit EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
EnumValBuilder &operator=(const EnumValBuilder &);
flatbuffers::Offset<EnumVal> Finish() {
const auto end = fbb_.EndTable(start_, 4);
const auto end = fbb_.EndTable(start_);
auto o = flatbuffers::Offset<EnumVal>(end);
fbb_.Required(o, EnumVal::VT_NAME);
return o;
@@ -375,13 +398,13 @@ struct EnumBuilder {
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
fbb_.AddOffset(Enum::VT_DOCUMENTATION, documentation);
}
EnumBuilder(flatbuffers::FlatBufferBuilder &_fbb)
explicit EnumBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
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);
@@ -538,13 +561,13 @@ struct FieldBuilder {
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
fbb_.AddOffset(Field::VT_DOCUMENTATION, documentation);
}
FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb)
explicit FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
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);
@@ -689,13 +712,13 @@ struct ObjectBuilder {
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
fbb_.AddOffset(Object::VT_DOCUMENTATION, documentation);
}
ObjectBuilder(flatbuffers::FlatBufferBuilder &_fbb)
explicit ObjectBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
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);
@@ -802,13 +825,13 @@ struct SchemaBuilder {
void add_root_table(flatbuffers::Offset<Object> root_table) {
fbb_.AddOffset(Schema::VT_ROOT_TABLE, root_table);
}
SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb)
explicit SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
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);
@@ -852,6 +875,10 @@ inline const reflection::Schema *GetSchema(const void *buf) {
return flatbuffers::GetRoot<reflection::Schema>(buf);
}
inline const reflection::Schema *GetSizePrefixedSchema(const void *buf) {
return flatbuffers::GetSizePrefixedRoot<reflection::Schema>(buf);
}
inline const char *SchemaIdentifier() {
return "BFBS";
}
@@ -866,6 +893,11 @@ inline bool VerifySchemaBuffer(
return verifier.VerifyBuffer<reflection::Schema>(SchemaIdentifier());
}
inline bool VerifySizePrefixedSchemaBuffer(
flatbuffers::Verifier &verifier) {
return verifier.VerifySizePrefixedBuffer<reflection::Schema>(SchemaIdentifier());
}
inline const char *SchemaExtension() {
return "bfbs";
}
@@ -876,6 +908,12 @@ inline void FinishSchemaBuffer(
fbb.Finish(root, SchemaIdentifier());
}
inline void FinishSizePrefixedSchemaBuffer(
flatbuffers::FlatBufferBuilder &fbb,
flatbuffers::Offset<reflection::Schema> root) {
fbb.FinishSizePrefixed(root, SchemaIdentifier());
}
} // namespace reflection
#endif // FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_

View File

@@ -37,18 +37,16 @@ class Registry {
// 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) {
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) {
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);
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;
@@ -82,38 +80,36 @@ class Registry {
// 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);
}
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(), include_paths_.data(),
schema.path_.c_str())) {
lasterror_ = parser->error_;
return false;
}
return true;
}
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_;

View File

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

View File

@@ -17,32 +17,32 @@
#ifndef FLATBUFFERS_UTIL_H_
#define FLATBUFFERS_UTIL_H_
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <assert.h>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <string>
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#include <winbase.h>
#include <direct.h>
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# ifndef NOMINMAX
# define NOMINMAX
# endif
# include <windows.h> // Must be included before <direct.h>
# include <direct.h>
# include <winbase.h>
# undef interface // This is also important because of reasons
#else
#include <limits.h>
# include <limits.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "flatbuffers/base.h"
namespace flatbuffers {
// Convert an integer or floating point value to a string.
@@ -60,14 +60,31 @@ template<> inline std::string NumToString<signed char>(signed char t) {
template<> inline std::string NumToString<unsigned char>(unsigned char t) {
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) {
template<typename T> std::string FloatToString(T t, int precision) {
// to_string() prints different numbers of digits for floats depending on
// platform and isn't available on Android, so we use stringstream
std::stringstream ss;
// Use std::fixed to surpress scientific notation.
ss << std::fixed << t;
ss << std::fixed;
// Default precision is 6, we want that to be higher for doubles.
ss << std::setprecision(precision);
ss << t;
auto s = ss.str();
// Sadly, std::fixed turns "1" into "1.00000", so here we undo that.
auto p = s.find_last_not_of('0');
@@ -77,8 +94,12 @@ template<> inline std::string NumToString<double>(double t) {
}
return s;
}
template<> inline std::string NumToString<double>(double t) {
return FloatToString(t, 12);
}
template<> inline std::string NumToString<float>(float t) {
return NumToString(static_cast<double>(t));
return FloatToString(t, 6);
}
// Convert an integer value to a hexadecimal string.
@@ -86,10 +107,7 @@ template<> inline std::string NumToString<float>(float t) {
// For example, IntToStringHex(0x23, 8) returns the string "00000023".
inline std::string IntToStringHex(int i, int xdigits) {
std::stringstream ss;
ss << std::setw(xdigits)
<< std::setfill('0')
<< std::hex
<< std::uppercase
ss << std::setw(xdigits) << std::setfill('0') << std::hex << std::uppercase
<< i;
return ss.str();
}
@@ -97,21 +115,25 @@ inline std::string IntToStringHex(int i, int xdigits) {
// Portable implementation of strtoll().
inline int64_t StringToInt(const char *str, char **endptr = nullptr,
int base = 10) {
// clang-format off
#ifdef _MSC_VER
return _strtoi64(str, endptr, base);
#else
return strtoll(str, endptr, base);
#endif
// clang-format on
}
// Portable implementation of strtoull().
inline uint64_t StringToUInt(const char *str, char **endptr = nullptr,
int base = 10) {
// clang-format off
#ifdef _MSC_VER
return _strtoui64(str, endptr, base);
#else
return strtoull(str, endptr, base);
#endif
// clang-format on
}
typedef bool (*LoadFileFunction)(const char *filename, bool binary,
@@ -120,9 +142,8 @@ typedef bool (*FileExistsFunction)(const char *filename);
LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function);
FileExistsFunction SetFileExistsFunction(FileExistsFunction
file_exists_function);
FileExistsFunction SetFileExistsFunction(
FileExistsFunction file_exists_function);
// Check if file "name" exists.
bool FileExists(const char *name);
@@ -202,13 +223,18 @@ inline std::string ConCatPathFileName(const std::string &path,
const std::string &filename) {
std::string filepath = path;
if (filepath.length()) {
if (filepath.back() == kPathSeparatorWindows) {
filepath.back() = kPathSeparator;
} else if (filepath.back() != kPathSeparator) {
char &filepath_last_character = string_back(filepath);
if (filepath_last_character == kPathSeparatorWindows) {
filepath_last_character = kPathSeparator;
} else if (filepath_last_character != kPathSeparator) {
filepath += kPathSeparator;
}
}
filepath += filename;
// Ignore './' at the start of filepath.
if (filepath[0] == '.' && filepath[1] == kPathSeparator) {
filepath.erase(0, 2);
}
return filepath;
}
@@ -224,16 +250,19 @@ inline std::string PosixPath(const char *path) {
inline void EnsureDirExists(const std::string &filepath) {
auto parent = StripFileName(filepath);
if (parent.length()) EnsureDirExists(parent);
// clang-format off
#ifdef _WIN32
(void)_mkdir(filepath.c_str());
#else
mkdir(filepath.c_str(), S_IRWXU|S_IRGRP|S_IXGRP);
#endif
// clang-format on
}
// Obtains the absolute path from any other path.
// Returns the input path if the absolute path couldn't be resolved.
inline std::string AbsolutePath(const std::string &filepath) {
// clang-format off
#ifdef FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
return filepath;
#else
@@ -247,6 +276,7 @@ inline std::string AbsolutePath(const std::string &filepath) {
? abs_path
: filepath;
#endif // FLATBUFFERS_NO_ABSOLUTE_PATH_RESOLUTION
// clang-format on
}
// To and from UTF-8 unicode conversion functions
@@ -264,7 +294,7 @@ inline int ToUTF8(uint32_t ucc, std::string *out) {
uint32_t remain_bits = i * 6;
// Store first byte:
(*out) += static_cast<char>((0xFE << (max_bits - remain_bits)) |
(ucc >> remain_bits));
(ucc >> remain_bits));
// Store remaining bytes:
for (int j = i - 1; j >= 0; j--) {
(*out) += static_cast<char>(((ucc >> (j * 6)) & 0x3F) | 0x80);
@@ -291,12 +321,10 @@ inline int FromUTF8(const char **in) {
break;
}
}
if ((**in << len) & 0x80) return -1; // Bit after leading 1's must be 0.
if ((static_cast<const unsigned char>(**in) << len) & 0x80) return -1; // Bit after leading 1's must be 0.
if (!len) return *(*in)++;
// UTF-8 encoded values with a length are between 2 and 4 bytes.
if (len < 2 || len > 4) {
return -1;
}
if (len < 2 || len > 4) { return -1; }
// Grab initial bits of the code.
int ucc = *(*in)++ & ((1 << (7 - len)) - 1);
for (int i = 0; i < len - 1; i++) {
@@ -306,28 +334,20 @@ inline int FromUTF8(const char **in) {
}
// UTF-8 cannot encode values between 0xD800 and 0xDFFF (reserved for
// UTF-16 surrogate pairs).
if (ucc >= 0xD800 && ucc <= 0xDFFF) {
return -1;
}
if (ucc >= 0xD800 && ucc <= 0xDFFF) { return -1; }
// UTF-8 must represent code points in their shortest possible encoding.
switch (len) {
case 2:
// Two bytes of UTF-8 can represent code points from U+0080 to U+07FF.
if (ucc < 0x0080 || ucc > 0x07FF) {
return -1;
}
if (ucc < 0x0080 || ucc > 0x07FF) { return -1; }
break;
case 3:
// Three bytes of UTF-8 can represent code points from U+0800 to U+FFFF.
if (ucc < 0x0800 || ucc > 0xFFFF) {
return -1;
}
if (ucc < 0x0800 || ucc > 0xFFFF) { return -1; }
break;
case 4:
// Four bytes of UTF-8 can represent code points from U+10000 to U+10FFFF.
if (ucc < 0x10000 || ucc > 0x10FFFF) {
return -1;
}
if (ucc < 0x10000 || ucc > 0x10FFFF) { return -1; }
break;
}
return ucc;
@@ -406,7 +426,8 @@ inline bool EscapeString(const char *s, size_t length, std::string *_text,
text += "\\u";
text += IntToStringHex(ucc, 4);
} else if (ucc <= 0x10FFFF) {
// Encode Unicode SMP values to a surrogate pair using two \u escapes.
// Encode Unicode SMP values to a surrogate pair using two \u
// escapes.
uint32_t base = ucc - 0x10000;
auto high_surrogate = (base >> 10) + 0xD800;
auto low_surrogate = (base & 0x03FF) + 0xDC00;

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.flatbuffers;
import static com.google.flatbuffers.Constants.*;
import java.nio.ByteBuffer;
/// @file
/// @addtogroup flatbuffers_java_api
/// @{
/**
* Class that collects utility functions around `ByteBuffer`.
*/
public class ByteBufferUtil {
/**
* Extract the size prefix from a `ByteBuffer`.
*
* @param bb a size-prefixed buffer
* @return the size prefix
*/
public static int getSizePrefix(ByteBuffer bb) {
return bb.getInt(bb.position());
}
/**
* Create a duplicate of a size-prefixed `ByteBuffer` that has its position
* advanced just past the size prefix.
*
* @param bb a size-prefixed buffer
* @return a new buffer on the same underlying data that has skipped the
* size prefix
*/
public static ByteBuffer removeSizePrefix(ByteBuffer bb) {
ByteBuffer s = bb.duplicate();
s.position(s.position() + SIZE_PREFIX_LENGTH);
return s;
}
}
/// @}

View File

@@ -37,6 +37,8 @@ public class Constants {
static final int SIZEOF_DOUBLE = 8;
/** The number of bytes in a file identifier. */
static final int FILE_IDENTIFIER_LENGTH = 4;
/** The number of bytes in a size prefix. */
public static final int SIZE_PREFIX_LENGTH = 4;
}
/// @endcond

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,6 +134,39 @@ public class FlatBufferBuilder {
return this;
}
/**
* An interface that provides a user of the FlatBufferBuilder class the ability to specify
* the method in which the internal buffer gets allocated. This allows for alternatives
* to the default behavior, which is to allocate memory for a new byte-array
* backed `ByteBuffer` array inside the JVM.
*
* The FlatBufferBuilder class contains the HeapByteBufferFactory class to
* preserve the default behavior in the event that the user does not provide
* their own implementation of this interface.
*/
public interface ByteBufferFactory {
/**
* Create a `ByteBuffer` with a given capacity.
*
* @param capacity The size of the `ByteBuffer` to allocate.
* @return Returns the new `ByteBuffer` that was allocated.
*/
ByteBuffer newByteBuffer(int capacity);
}
/**
* An implementation of the ByteBufferFactory interface that is used when
* one is not provided by the user.
*
* Allocate memory for a new byte-array backed `ByteBuffer` array inside the JVM.
*/
public static final class HeapByteBufferFactory implements ByteBufferFactory {
@Override
public ByteBuffer newByteBuffer(int capacity) {
return ByteBuffer.allocate(capacity).order(ByteOrder.LITTLE_ENDIAN);
}
}
/**
* Reset the FlatBufferBuilder by purging all data that it holds.
*/
@@ -122,34 +183,22 @@ public class FlatBufferBuilder {
vector_num_elems = 0;
}
/// @cond FLATBUFFERS_INTERNAL
/**
* Create a `ByteBuffer` with a given capacity.
*
* @param capacity The size of the `ByteBuffer` to allocate.
* @return Returns the new `ByteBuffer` that was allocated.
*/
static ByteBuffer newByteBuffer(int capacity) {
ByteBuffer newbb = ByteBuffer.allocate(capacity);
newbb.order(ByteOrder.LITTLE_ENDIAN);
return newbb;
}
/**
* Doubles the size of the backing {@link ByteBuffer} and copies the old data towards the
* 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;
int new_buf_size = old_buf_size == 0 ? 1 : 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;
@@ -192,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);
@@ -429,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.
@@ -695,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);
@@ -703,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);
@@ -763,14 +816,55 @@ public class FlatBufferBuilder {
* Finalize a buffer, pointing to the given `root_table`.
*
* @param root_table An offset to be added to the buffer.
* @param size_prefix Whether to prefix the size to the buffer.
*/
public void finish(int root_table) {
prep(minalign, SIZEOF_INT);
protected void finish(int root_table, boolean size_prefix) {
prep(minalign, SIZEOF_INT + (size_prefix ? SIZEOF_INT : 0));
addOffset(root_table);
if (size_prefix) {
addInt(bb.capacity() - space);
}
bb.position(space);
finished = true;
}
/**
* Finalize a buffer, pointing to the given `root_table`.
*
* @param root_table An offset to be added to the buffer.
*/
public void finish(int root_table) {
finish(root_table, false);
}
/**
* Finalize a buffer, pointing to the given `root_table`, with the size prefixed.
*
* @param root_table An offset to be added to the buffer.
*/
public void finishSizePrefixed(int root_table) {
finish(root_table, true);
}
/**
* Finalize a buffer, pointing to the given `root_table`.
*
* @param root_table An offset to be added to the buffer.
* @param file_identifier A FlatBuffer file identifier to be added to the buffer before
* `root_table`.
* @param size_prefix Whether to prefix the size to the buffer.
*/
protected void finish(int root_table, String file_identifier, boolean size_prefix) {
prep(minalign, SIZEOF_INT + FILE_IDENTIFIER_LENGTH + (size_prefix ? SIZEOF_INT : 0));
if (file_identifier.length() != FILE_IDENTIFIER_LENGTH)
throw new AssertionError("FlatBuffers: file identifier must be length " +
FILE_IDENTIFIER_LENGTH);
for (int i = FILE_IDENTIFIER_LENGTH - 1; i >= 0; i--) {
addByte((byte)file_identifier.charAt(i));
}
finish(root_table, size_prefix);
}
/**
* Finalize a buffer, pointing to the given `root_table`.
*
@@ -779,14 +873,18 @@ public class FlatBufferBuilder {
* `root_table`.
*/
public void finish(int root_table, String file_identifier) {
prep(minalign, SIZEOF_INT + FILE_IDENTIFIER_LENGTH);
if (file_identifier.length() != FILE_IDENTIFIER_LENGTH)
throw new AssertionError("FlatBuffers: file identifier must be length " +
FILE_IDENTIFIER_LENGTH);
for (int i = FILE_IDENTIFIER_LENGTH - 1; i >= 0; i--) {
addByte((byte)file_identifier.charAt(i));
}
finish(root_table);
finish(root_table, file_identifier, false);
}
/**
* Finalize a buffer, pointing to the given `root_table`, with the size prefixed.
*
* @param root_table An offset to be added to the buffer.
* @param file_identifier A FlatBuffer file identifier to be added to the buffer before
* `root_table`.
*/
public void finishSizePrefixed(int root_table, String file_identifier) {
finish(root_table, file_identifier, true);
}
/**
@@ -853,6 +951,41 @@ public class FlatBufferBuilder {
public byte[] sizedByteArray() {
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;
}
@@ -122,7 +122,7 @@ public class Table {
cr.throwException();
}
} catch (CharacterCodingException x) {
throw new Error(x);
throw new RuntimeException(x);
}
return dst.flip().toString();
@@ -172,6 +172,27 @@ public class Table {
return bb;
}
/**
* Initialize vector as a ByteBuffer.
*
* This is more efficient than using duplicate, since it doesn't copy the data
* nor allocattes a new {@link ByteBuffer}, creating no garbage to be collected.
*
* @param bb The {@link ByteBuffer} for the array
* @param vector_offset The position of the vector in the byte buffer
* @param elem_size The size of each element in the array
* @return The {@link ByteBuffer} for the array
*/
protected ByteBuffer __vector_in_bytebuffer(ByteBuffer bb, int vector_offset, int elem_size) {
int o = this.__offset(vector_offset);
if (o == 0) return null;
int vectorstart = __vector(o);
bb.rewind();
bb.limit(vectorstart + __vector_len(o) * elem_size);
bb.position(vectorstart);
return bb;
}
/**
* Initialize any Table-derived type to point to the union at the given `offset`.
*
@@ -245,10 +266,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 +286,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

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

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

@@ -30,6 +30,8 @@
//
using System;
using System.IO;
using System.Text;
namespace FlatBuffers
{
@@ -38,12 +40,12 @@ namespace FlatBuffers
/// </summary>
public class ByteBuffer
{
private readonly byte[] _buffer;
protected byte[] _buffer;
private int _pos; // Must track start of the buffer.
public int Length { get { return _buffer.Length; } }
public byte[] Data { get { return _buffer; } }
public ByteBuffer(int size) : this(new byte[size]) { }
public ByteBuffer(byte[] buffer) : this(buffer, 0) { }
@@ -63,11 +65,64 @@ namespace FlatBuffers
_pos = 0;
}
// Create a new ByteBuffer on the same underlying data.
// The new ByteBuffer's position will be same as this buffer's.
public ByteBuffer Duplicate()
{
return new ByteBuffer(_buffer, Position);
}
// Increases the size of the ByteBuffer, and copies the old data towards
// the end of the new buffer.
public void GrowFront(int newSize)
{
if ((Length & 0xC0000000) != 0)
throw new Exception(
"ByteBuffer: cannot grow buffer beyond 2 gigabytes.");
if (newSize < Length)
throw new Exception("ByteBuffer: cannot truncate buffer.");
byte[] newBuffer = new byte[newSize];
Buffer.BlockCopy(_buffer, 0, newBuffer, newSize - Length,
Length);
_buffer = newBuffer;
}
public byte[] ToArray(int pos, int len)
{
byte[] arr = new byte[len];
Buffer.BlockCopy(_buffer, pos, arr, 0, len);
return arr;
}
public byte[] ToSizedArray()
{
return ToArray(Position, Length - Position);
}
public byte[] ToFullArray()
{
return ToArray(0, Length);
}
public ArraySegment<byte> ToArraySegment(int pos, int len)
{
return new ArraySegment<byte>(_buffer, pos, len);
}
public MemoryStream ToMemoryStream(int pos, int len)
{
return new MemoryStream(_buffer, pos, len);
}
#if !UNSAFE_BYTEBUFFER
// Pre-allocated helper arrays for convertion.
private float[] floathelper = new[] { 0.0f };
private int[] inthelper = new[] { 0 };
private double[] doublehelper = new[] { 0.0 };
private ulong[] ulonghelper = new[] { 0UL };
#endif // !UNSAFE_BYTEBUFFER
// Helper functions for the unsafe version.
static public ushort ReverseBytes(ushort input)
@@ -136,7 +191,6 @@ namespace FlatBuffers
}
#endif // !UNSAFE_BYTEBUFFER
private void AssertOffsetAndLength(int offset, int length)
{
#if !BYTEBUFFER_NO_BOUNDS_CHECK
@@ -171,6 +225,13 @@ namespace FlatBuffers
PutByte(offset, value);
}
public void PutStringUTF8(int offset, string value)
{
AssertOffsetAndLength(offset, value.Length);
Encoding.UTF8.GetBytes(value, 0, value.Length,
_buffer, offset);
}
#if UNSAFE_BYTEBUFFER
// Unsafe but more efficient versions of Put*.
public void PutShort(int offset, short value)
@@ -321,6 +382,11 @@ namespace FlatBuffers
return _buffer[index];
}
public string GetStringUTF8(int startPos, int len)
{
return Encoding.UTF8.GetString(_buffer, startPos, len);
}
#if UNSAFE_BYTEBUFFER
// Unsafe but more efficient versions of Get*.
public short GetShort(int offset)

BIN
net/FlatBuffers/ByteBuffer.exe Executable file

Binary file not shown.

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2017 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System;
namespace FlatBuffers
{
/// <summary>
/// Class that collects utility functions around `ByteBuffer`.
/// </summary>
public class ByteBufferUtil
{
// Extract the size prefix from a `ByteBuffer`.
public static int GetSizePrefix(ByteBuffer bb) {
return bb.GetInt(bb.Position);
}
// Create a duplicate of a size-prefixed `ByteBuffer` that has its position
// advanced just past the size prefix.
public static ByteBuffer RemoveSizePrefix(ByteBuffer bb) {
ByteBuffer s = bb.Duplicate();
s.Position += FlatBufferConstants.SizePrefixLength;
return s;
}
}
}

View File

@@ -59,7 +59,7 @@ namespace FlatBuffers
throw new ArgumentOutOfRangeException("initialSize",
initialSize, "Must be greater than zero");
_space = initialSize;
_bb = new ByteBuffer(new byte[initialSize]);
_bb = new ByteBuffer(initialSize);
}
/// <summary>
@@ -99,18 +99,7 @@ namespace FlatBuffers
// the end of the new buffer (since we build the buffer backwards).
void GrowBuffer()
{
var oldBuf = _bb.Data;
var oldBufSize = oldBuf.Length;
if ((oldBufSize & 0xC0000000) != 0)
throw new Exception(
"FlatBuffers: cannot grow buffer beyond 2 gigabytes.");
var newBufSize = oldBufSize << 1;
var newBuf = new byte[newBufSize];
Buffer.BlockCopy(oldBuf, 0, newBuf, newBufSize - oldBufSize,
oldBufSize);
_bb = new ByteBuffer(newBuf, newBufSize);
_bb.GrowFront(_bb.Length << 1);
}
// Prepare to write an element of `size` after `additional_bytes`
@@ -475,7 +464,7 @@ namespace FlatBuffers
AddByte(0);
var utf8StringLen = Encoding.UTF8.GetByteCount(s);
StartVector(1, utf8StringLen, 1);
Encoding.UTF8.GetBytes(s, 0, s.Length, _bb.Data, _space -= utf8StringLen);
_bb.PutStringUTF8(_space -= utf8StringLen, s);
return new StringOffset(EndVector().Value);
}
@@ -500,7 +489,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 +506,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);
@@ -576,6 +569,25 @@ namespace FlatBuffers
}
/// @endcond
/// <summary>
/// Finalize a buffer, pointing to the given `root_table`.
/// </summary>
/// <param name="rootTable">
/// An offset to be added to the buffer.
/// </param>
/// <param name="sizePrefix">
/// Whether to prefix the size to the buffer.
/// </param>
protected void Finish(int rootTable, bool sizePrefix)
{
Prep(_minAlign, sizeof(int) + (sizePrefix ? sizeof(int) : 0));
AddOffset(rootTable);
if (sizePrefix) {
AddInt(_bb.Length - _space);
}
_bb.Position = _space;
}
/// <summary>
/// Finalize a buffer, pointing to the given `root_table`.
/// </summary>
@@ -584,9 +596,18 @@ namespace FlatBuffers
/// </param>
public void Finish(int rootTable)
{
Prep(_minAlign, sizeof(int));
AddOffset(rootTable);
_bb.Position = _space;
Finish(rootTable, false);
}
/// <summary>
/// Finalize a buffer, pointing to the given `root_table`, with the size prefixed.
/// </summary>
/// <param name="rootTable">
/// An offset to be added to the buffer.
/// </param>
public void FinishSizePrefixed(int rootTable)
{
Finish(rootTable, true);
}
/// <summary>
@@ -611,41 +632,69 @@ namespace FlatBuffers
/// </returns>
public byte[] SizedByteArray()
{
var newArray = new byte[_bb.Data.Length - _bb.Position];
Buffer.BlockCopy(_bb.Data, _bb.Position, newArray, 0,
_bb.Data.Length - _bb.Position);
return newArray;
return _bb.ToSizedArray();
}
/// <summary>
/// Finalize a buffer, pointing to the given `rootTable`.
/// </summary>
/// <param name="rootTable">
/// An offset to be added to the buffer.
/// </param>
/// <param name="fileIdentifier">
/// A FlatBuffer file identifier to be added to the buffer before
/// `root_table`.
/// </param>
public void Finish(int rootTable, string fileIdentifier)
{
Prep(_minAlign, sizeof(int) +
FlatBufferConstants.FileIdentifierLength);
if (fileIdentifier.Length !=
FlatBufferConstants.FileIdentifierLength)
throw new ArgumentException(
"FlatBuffers: file identifier must be length " +
FlatBufferConstants.FileIdentifierLength,
"fileIdentifier");
for (int i = FlatBufferConstants.FileIdentifierLength - 1; i >= 0;
i--)
{
AddByte((byte)fileIdentifier[i]);
}
Finish(rootTable);
/// <summary>
/// Finalize a buffer, pointing to the given `rootTable`.
/// </summary>
/// <param name="rootTable">
/// An offset to be added to the buffer.
/// </param>
/// <param name="fileIdentifier">
/// A FlatBuffer file identifier to be added to the buffer before
/// `root_table`.
/// </param>
/// <param name="sizePrefix">
/// Whether to prefix the size to the buffer.
/// </param>
protected void Finish(int rootTable, string fileIdentifier, bool sizePrefix)
{
Prep(_minAlign, sizeof(int) + (sizePrefix ? sizeof(int) : 0) +
FlatBufferConstants.FileIdentifierLength);
if (fileIdentifier.Length !=
FlatBufferConstants.FileIdentifierLength)
throw new ArgumentException(
"FlatBuffers: file identifier must be length " +
FlatBufferConstants.FileIdentifierLength,
"fileIdentifier");
for (int i = FlatBufferConstants.FileIdentifierLength - 1; i >= 0;
i--)
{
AddByte((byte)fileIdentifier[i]);
}
Finish(rootTable, sizePrefix);
}
/// <summary>
/// Finalize a buffer, pointing to the given `rootTable`.
/// </summary>
/// <param name="rootTable">
/// An offset to be added to the buffer.
/// </param>
/// <param name="fileIdentifier">
/// A FlatBuffer file identifier to be added to the buffer before
/// `root_table`.
/// </param>
public void Finish(int rootTable, string fileIdentifier)
{
Finish(rootTable, fileIdentifier, false);
}
/// <summary>
/// Finalize a buffer, pointing to the given `rootTable`, with the size prefixed.
/// </summary>
/// <param name="rootTable">
/// An offset to be added to the buffer.
/// </param>
/// <param name="fileIdentifier">
/// A FlatBuffer file identifier to be added to the buffer before
/// `root_table`.
/// </param>
public void FinishSizePrefixed(int rootTable, string fileIdentifier)
{
Finish(rootTable, fileIdentifier, true);
}
}
}

View File

@@ -24,5 +24,6 @@ namespace FlatBuffers
public static class FlatBufferConstants
{
public const int FileIdentifierLength = 4;
public const int SizePrefixLength = 4;
}
}

View File

@@ -60,7 +60,7 @@ namespace FlatBuffers
offset += bb.GetInt(offset);
var len = bb.GetInt(offset);
var startPos = offset + sizeof(int);
return Encoding.UTF8.GetString(bb.Data, startPos , len);
return bb.GetStringUTF8(startPos, len);
}
// Get the length of a vector whose offset is stored at "offset" in this object.
@@ -91,7 +91,7 @@ namespace FlatBuffers
var pos = this.__vector(o);
var len = this.__vector_len(o);
return new ArraySegment<byte>(this.bb.Data, pos, len);
return bb.ToArraySegment(pos, len);
}
// Initialize any Table-derived type to point to the union at the given offset.
@@ -126,10 +126,11 @@ namespace FlatBuffers
var startPos_1 = offset_1 + sizeof(int);
var startPos_2 = offset_2 + sizeof(int);
var len = Math.Min(len_1, len_2);
byte[] bbArray = bb.Data;
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];
byte b1 = bb.Get(i + startPos_1);
byte b2 = bb.Get(i + startPos_2);
if (b1 != b2)
return b1 - b2;
}
return len_1 - len_2;
}
@@ -142,10 +143,10 @@ namespace FlatBuffers
var len_2 = key.Length;
var startPos_1 = offset_1 + sizeof(int);
var len = Math.Min(len_1, len_2);
byte[] bbArray = bb.Data;
for (int i = 0; i < len; i++) {
if (bbArray[i + startPos_1] != key[i])
return bbArray[i + startPos_1] - key[i];
byte b = bb.Get(i + startPos_1);
if (b != key[i])
return b - key[i];
}
return len_1 - len_2;
}

View File

@@ -1,15 +1,18 @@
{
"name": "flatbuffers",
"version": "1.7.0",
"version": "1.9.0",
"description": "Memory Efficient Serialization Library",
"files": ["js/flatbuffers.js"],
"main": "js/flatbuffers.js",
"files": ["js/flatbuffers.js", "js/flatbuffers.mjs"],
"main": "js/flatbuffers",
"module": "js/flatbuffers.mjs",
"directories": {
"doc": "docs",
"test": "tests"
},
"scripts": {
"test": "tests/JavaScriptTest.sh"
"test": "tests/JavaScriptTest.sh",
"append-esm-export": "sed \"s/this.flatbuffers = flatbuffers;/export { flatbuffers };/\" js/flatbuffers.js >> js/flatbuffers.mjs",
"prepublishOnly": "npm run append-esm-export"
},
"repository": {
"type": "git",

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.7.0-SNAPSHOT</version>
<version>1.9.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>

2
python/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/dist/
/*.egg-info/

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):
"""
@@ -458,14 +483,32 @@ class Builder(object):
self.current_vtable[slotnum] = self.Offset()
## @endcond
def Finish(self, rootTable):
def __Finish(self, rootTable, sizePrefix):
"""Finish finalizes a buffer, pointing to the given `rootTable`."""
N.enforce_number(rootTable, N.UOffsetTFlags)
self.Prep(self.minalign, N.UOffsetTFlags.bytewidth)
prepSize = N.UOffsetTFlags.bytewidth
if sizePrefix:
prepSize += N.Int32Flags.bytewidth
self.Prep(self.minalign, prepSize)
self.PrependUOffsetTRelative(rootTable)
if sizePrefix:
size = len(self.Bytes) - self.Head()
N.enforce_number(size, N.Int32Flags)
self.PrependInt32(size)
self.finished = True
return self.Head()
def Finish(self, rootTable):
"""Finish finalizes a buffer, pointing to the given `rootTable`."""
return self.__Finish(rootTable, False)
def FinishSizePrefixed(self, rootTable):
"""
Finish finalizes a buffer, pointing to the given `rootTable`,
with the size prefixed.
"""
return self.__Finish(rootTable, True)
## @cond FLATBUFFERS_INTERNAL
def Prepend(self, flags, off):
self.Prep(flags.bytewidth, 0)

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

View File

@@ -0,0 +1,28 @@
# Copyright 2017 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from . import encode
from . import number_types
from . import packer
def GetSizePrefix(buf, offset):
"""Extract the size prefix from a buffer."""
return encode.Get(packer.int32, buf, offset)
def RemoveSizePrefix(buf, offset):
"""
Create a slice of a size-prefixed buffer that has
its position advanced just past the size prefix.
"""
return buf, offset + number_types.Int32Flags.bytewidth

View File

@@ -12,11 +12,38 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import os
from datetime import datetime
from setuptools import setup
def version():
version = os.getenv('VERSION', None)
if version:
# Most git tags are prefixed with 'v' (example: v1.2.3) this is
# never desirable for artifact repositories, so we strip the
# leading 'v' if it's present.
return version[1:] if version.startswith('v') else version
else:
# Default version is an ISO8601 compiliant datetime. PyPI doesn't allow
# the colon ':' character in its versions, and time is required to allow
# for multiple publications to master in one day. This datetime string
# uses the "basic" ISO8601 format for both its date and time components
# to avoid issues with the colon character (ISO requires that date and
# time components of a date-time string must be uniformly basic or
# extended, which is why the date component does not have dashes.
#
# Publications using datetime versions should only be made from master
# to represent the HEAD moving forward.
version = datetime.utcnow().strftime('%Y%m%d%H%M%S')
print("VERSION environment variable not set, using datetime instead: {}"
.format(version))
return version
setup(
name='flatbuffers',
version='2015.05.14.0',
version=version(),
license='Apache 2.0',
author='FlatBuffers Contributors',
author_email='me@rwinslow.com',

0
readme.md Executable file → Normal file
View File

View File

@@ -0,0 +1,18 @@
:: Copyright 2015 Google Inc. All rights reserved.
::
:: Licensed under the Apache License, Version 2.0 (the "License");
:: you may not use this file except in compliance with the License.
:: You may obtain a copy of the License at
::
:: http://www.apache.org/licenses/LICENSE-2.0
::
:: Unless required by applicable law or agreed to in writing, software
:: distributed under the License is distributed on an "AS IS" BASIS,
:: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
:: See the License for the specific language governing permissions and
:: limitations under the License.
set buildtype=Release
if "%1"=="-b" set buildtype=%2
..\%buildtype%\flatc.exe --cpp --no-prefix -o ../include/flatbuffers reflection.fbs

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