Compare commits

..

181 Commits

Author SHA1 Message Date
Wouter van Oortmerssen
cebdad4d23 Updated version numbers to 1.6
Change-Id: I215fcc7581253f14171b513d4fc75da960b2064a
2017-02-15 14:36:51 -08:00
Sahil Jain
d798100be9 Round vector_downward initial size up (#4179) 2017-02-15 11:42:01 -08:00
Wouter van Oortmerssen
1fb6b9ee6f Added doc comments to the binary schema.
Change-Id: I87f291ab6e07b1425850cae25ed500db594f17c8
Tested: on Linux.
2017-02-13 16:47:17 -08:00
Wouter van Oortmerssen
2d6e8f096b Fixed sorting assertion with some std::sort implementations.
Change-Id: Idd925c9cc5cd2a35e06f4d832734180f5c38378e
Tested: on Linux.
2017-02-13 09:50:35 -08:00
Shintaro Abe
ec8038cc3d JS: add package.json to publish the npm pacakge (#4166)
* JS: add package.json to publish the npm pacakge

* JS: update package.json to set version and author
2017-02-10 14:19:11 -08:00
Wouter van Oortmerssen
2df3d1c965 Added missing generated code.
Change-Id: If3d2e11627b6d08bc6433941208ead577aa0e3b9
2017-02-10 13:28:15 -08:00
Wouter van Oortmerssen
2272229983 Added --prefix-include option for generated includes.
Change-Id: I288cda33345362f9aec5cbe309e590bf64f328e1
Tested: on Linux.
2017-02-10 13:24:54 -08:00
水樹素子
b7bfecb4ee Add move constructor to generated union class. (#4167)
* Add move constructor to generated union class.

* Unused default

* Add generated code
2017-02-10 10:32:34 -08:00
sjoblom65
c7c4bbfce2 Error C2668: 'Service::Version2::CreateServiceValues' : ambiguous call to overloaded function (#4161)
* Update idl_gen_cpp.cpp

Fix for: error C2668: 'Service::Version2::CreateServiceValues' : ambiguous call to overloaded function #4145

* Update idl_gen_cpp.cpp

Also needed the same change in the getPostTable

* Add files via upload

New generation from running generate_test.bat

* Add files via upload

Lets try this without added line feeds

* Added a test for a potential "ambiguous call to overloaded function"

* Change to a better name of the table.

Didn't like the Service in the name.

* Reverted back to the original
2017-02-10 10:25:11 -08:00
Wouter van Oortmerssen
d7ba17dfe5 Changes to make flatbuffers javascript compatible with the closure compiler.
Change-Id: Iab8d66a8f34910029deb8a5ff5ec7ba50c5b3421
2017-02-08 17:14:35 -08:00
Wouter van Oortmerssen
60b11435e6 Fixed missing '
Change-Id: I25110bbb171a27626ec6416b810399069d590279
2017-02-08 17:04:44 -08:00
Wouter van Oortmerssen
ed2110d7b3 Fixed link to Google C++ Style Guide.
Change-Id: Ifb955f3daefedae2cb9930a365c4c7e0641776b4
2017-02-08 16:37:25 -08:00
Wouter van Oortmerssen
a9514de978 Fixed vector test on Windows 2017-02-08 15:59:52 -08:00
Wouter van Oortmerssen
c57ab92e60 Fixes for Windows compiler errors.
Change-Id: I909ea6866089f36f9cb79d435bbecd29623fd8f7
2017-02-08 15:38:18 -08:00
Wouter van Oortmerssen
f878024d0b Fixed the Android build.
Change-Id: Iabb9448b4f161bba465d455c28bb826529649d30
Tested: on Android.
2017-02-08 15:13:57 -08:00
Wouter van Oortmerssen
aac6be1153 First attempt at SchemaLess FlatBuffers.
Change-Id: I86b9d002f3441ef9efdb70e059b8530ab2d74bb8
Tested: on Linux.
2017-02-08 15:13:56 -08:00
Wouter van Oortmerssen
dabe030890 Added PULL_REQUEST_TEMPLATE.md
Change-Id: Iad9c09434f87219e384b294d6221f4cac7a839eb
2017-02-08 10:15:26 -08:00
Wouter van Oortmerssen
29574282a2 JSON parser wasn't handling ulong values correctly.
It passed all scalar ints thru a int64_t, which would truncate
uint64_t values with the upper bit set.

Change-Id: I38fb8c68c911ae44d9863f8e35c2429ca0ab51e5
Tested: on Linux.
2017-02-01 14:18:28 -08:00
Benjamin Lerman
2dd6ba57d1 Add utility method to build a vector of struct in-place. (#4153)
Change-Id: I6df195cbae621cf2bf6b4f3b56f68be80dc23152
2017-02-01 09:22:56 -08:00
Wouter van Oortmerssen
6cc2307c71 Remove max_message_size arg, which is not passed to Deserialize func.
Change-Id: Icc7b4c1cf626f49d0529ff4f66503ea8381bf67c
2017-01-30 14:54:51 -08:00
Wouter van Oortmerssen
74c8c7137a A bug fix to the union vector feature in FlatBuffers.
Change-Id: I302245969f6ec2443572799732fce2aa7c071879
2017-01-30 14:02:40 -08:00
Wouter van Oortmerssen
f9055ff9a7 Merge branch 'master' of https://github.com/google/flatbuffers 2017-01-27 15:30:27 -08:00
Wouter van Oortmerssen
9b3d8b318a Added tracking of order of types declared.
Change-Id: Iade313c99f119dcf1619674260648a33f61dc030
2017-01-27 15:30:08 -08:00
Wouter van Oortmerssen
87e29b25de Some small speed optimizations to the core copying functions.
Change-Id: Id8c1afb84f4ab0e2edca4290e3de5589fa06e578
Tested: on Linux.
2017-01-27 11:26:35 -08:00
Robert
f7bc9bd51b Merge pull request #4146 from zchee/go-test-fix_struct
go: fix unknown field 'UOffset' to 'Pos'
2017-01-26 20:45:49 -08:00
Wouter van Oortmerssen
3dee617c86 Fix unused variable build warning on Mac.
Change-Id: I330187be6a96bfd388c2776f676d47a9145d5e4a
2017-01-25 14:39:14 -08:00
Wouter van Oortmerssen
2fb25e2bb3 Moved union vector test to file dependent section.
Change-Id: I3a1fcf167eb0d0a51ef838e54246ef867e752218
2017-01-25 14:09:18 -08:00
Wouter van Oortmerssen
b395359b6e Allow the flatbuffer compiler (flatc) to be built as a library.
Change-Id: I71baff427243f96be1596b01ff3405fdf39386d7
2017-01-25 13:41:34 -08:00
gbeili
fd61d70205 minor fixes to the union vector code styles (#4149) 2017-01-25 09:34:37 -08:00
jsanmiya
4f4495a693 Merge pull request #4148 from gbeili/vector_unions
C++ Union Vector
2017-01-24 14:33:32 -08:00
Bei Li
68bbe983e9 Union Vector 2017-01-24 11:52:36 -08:00
Florin Pățan
bbef92c17d Reword comment so that code editors can mark deprecation correctly (#4147) 2017-01-23 13:40:50 -08:00
Koichi Shiraishi
25c884158f go: fix unknown field 'UOffset' to 'Pos'
Signed-off-by: Koichi Shiraishi <zchee.io@gmail.com>
2017-01-22 20:16:52 +09:00
Wouter van Oortmerssen
3f936c5655 More native code gen functionality.
Allow tables to be mapped to native types directly.  For example, a table
representing a vector3 (eg. table Vec3 { x:float; y:float; z:float; }) can
be mapped to a "mathfu::vec3" native type in NativeTables.  This requires
users to provide Pack and UnPack functions that convert between the
Table and native types.  This is done by adding the "native_type" attribute
to the table definition.

To support user-defined flatbuffers::Pack and flatbuffers::UnPack functions,
support a "native_include" markup that will generate a corresponding

Also add an UnPackTo function which allows users to pass in a pointer to
a NativeTable object into which to UnPack the Table.  The existing UnPack
function is now simply:

  NativeTable* UnPack() {
    NativeTable* obj = new NativeTable();
    Table::UnPackTo(obj);
    return obj;
  }

Finally, allow native types to be given a default value as well which are
set in the NativeTable constructor.  This is done by providing a
"native_default" attribute to the member of a table.

Change-Id: Ic45cb48b0e6d7cfa5734b24819e54aa96d847cfd
2017-01-18 16:23:35 -08:00
Wouter van Oortmerssen
42a265b419 Add no-op for padding variables to prevent clang compiler warning.
Change-Id: I119ee7109bfa2b0be0f468d2b2be459f45d1bb11
2017-01-18 16:17:08 -08:00
Wouter van Oortmerssen
4bc4979acc Fix compiler warning on Visual Studio.
Change-Id: Ifda5f2c32c6484508d5e12a463d6373798f1f523
2017-01-18 16:09:35 -08:00
Wouter van Oortmerssen
b095367d17 Merge branch 'master' of https://github.com/google/flatbuffers 2017-01-18 14:58:09 -08:00
Wouter van Oortmerssen
eac2905568 Fixed unions not being parsed correctly in JSON.
This would happen if they were supplied in an order that does not match
the schema relative to other fields. It now supports any ordering.

Change-Id: I9d309cd4e6e5c470f01d9d431806eba4f9f46559
Tested: on Linux.
2017-01-18 14:54:16 -08:00
Georges Savoundararadj
12fd0c6838 GenEnum: bit_flags: Remove useless conditions (#4141)
The conditions to add the "NONE" or "ANY" value in the enum were useless
because the user cannot provide a zero value or a bitmask (for "ANY") in
the bit_flags enum type.
2017-01-18 09:59:13 -08:00
Wouter van Oortmerssen
19101826a8 Fix unused field warning in clang.
Change-Id: I71d590a1e5b2709f0e2dcf97faaebda5cb918fc7
Tested: on Linux.
2017-01-13 18:30:57 -08:00
Wouter van Oortmerssen
7b94eab2b1 Add CodeWriter utility class.
Helps simplify code generation code.  Instead of this:
  code += "inline const " + cpp_qualified_name + " *Get";
  code += name;
  code += "(const void *buf) {\n  return flatbuffers::GetRoot<";
  code += cpp_qualified_name + ">(buf);\n}\n\n";

You do this:
  code.SetValue("NAME", struct_def.name);
  code.SetValue("CPP_NAME", cpp_qualified_name);
  code += "inline const {{CPP_NAME}} *Get{{NAME}}(const void *buf) {";
  code += "  return flatbuffers::GetRoot<{{CPP_NAME}}>(buf);";
  code += "}";
  code += "";

Updated the CPP code generator to use the CodeWriter class.  Most of the
changes in the generated code are white-space changes, esp. around new
lines (since the code generator class automatically appends new lines
when appending a string).  Actual code changes include:

* Renamed "rehasher" to "_rehasher" for consistency with other args in
  Pack function.

* Renamed "union_obj" to "obj: in UnPack function.

* Always do "(void)_o;" to prevent unused variable warning in Create
  function (instead of only doing it if there are no fields) in order
  to avoid two-passes.

* Renamed padding variables from __paddingX to paddingX__.
  "Each name that contains a double underscore (_ _) [...] is reserved
   to the implementation for any use."  C++ standards 17.4.3.1.2.

* Add braces around switch cases.

* Calculate index as a separate statement in EnumName function, eg.
    const size_t index = ...;
    return EnumNamesX()[index];
  vs.
    return EnumNamesX()[...];

* Stored end table offset in variable in Finish() functions, eg.
    const auto end = fbb_.EndTable(start_, ...);
    auto o = flatbuffers::Offset<T>(end);
  vs.
    auto o = flatbuffers::Offset<T>(fbb_.EndTable(start, ...));

* Separate reinterpret_cast calls from function calls in Union
  functions, eg.
    auto ptr = reinterpret_cast<const T *>(obj);
    return ptr->UnPack(resolver);
  vs.
    return reinterpret_cast<const T *>(obj)->UnPack(resolver);

* Removed unecessary (void)(padding__X) no-ops from constructors, eg.
    Test(int16_t a, int8_t b) : ... {
      (void)__padding0;  // <-- Removed this line.
    }

In the idl_gen_cpp.cpp file itself, I refactored some code generation into
new functions: GenParam, GenNativeTable, GenVerifyCall, GenBuilders,
GenUnpackFieldStatement, and GenCreateParam.

Change-Id: I727b1bd8719d05b7ce33cbce00eb58fda817b25d
2017-01-13 17:44:42 -08:00
gbeili
1a21b54560 Add a builder option to enable/disable vtables deduplication. (#4132)
* Add a builder option to enable/disable vtables deduplication.

* address code review comments
2017-01-11 10:36:18 -08:00
Pascal S. de Kloe
b55f18649a Resolve Go fmt and vet warnings (#4134)
* Resolve Go fmt and vet warnings.

* Undo generated code gofmt.
2017-01-09 17:13:44 -08:00
Wouter van Oortmerssen
e2373668d9 Merge branch 'master' of https://github.com/google/flatbuffers 2017-01-09 15:55:18 -08:00
Wouter van Oortmerssen
8c1a723ba5 Fixed GRPC method name generation.
Change-Id: I827b7e9aee1edb77752322455f7b6fafac16fb1d
Tested: on Linux.
2017-01-09 15:54:31 -08:00
Mateusz Pusz
ab7949dc16 Cold part of make_space() code moved to reallocate member function. (#4130)
Change makes make_space() code much friendlier for the compiler to inline which makes significant (measurable) performance improvements.
2017-01-09 10:10:11 -08:00
Wouter van Oortmerssen
2c4dce5ba7 Re-applied reverted fix, adding missing codegen files.
Change-Id: I301d29835fb0baffd859950eb0fb3056e4f4d66b
2017-01-04 10:41:31 -08:00
Wouter van Oortmerssen
cc84240098 Misc idl_gen_cpp cleanup
- Update to be const-correct where possible.
- Consistently pass |code| as pointer instead of non-const-ref.
- No newlines (\n) characters in the middle of code strings.
- Use if-else if-else statements instead of nested ternary operators.
- Ensure all lines end at 80 chars.
- Make utility functions static.

From cl/143505731.

Change-Id: If0fab9ee75de5af963367a948dddf53af93f73b4
2017-01-04 10:12:39 -08:00
Wouter van Oortmerssen
b29ba4c70c Updated version to 1.5
Change-Id: I34007829cdd3ad024df21f68bb369016d5d21131
2017-01-03 14:56:44 -08:00
Yonggang Li
fea6b525ee fix memory leak (#4126) 2017-01-03 13:54:15 -08:00
CarsarSky
69dc71b5ed Fix C++ gRPC test with streaming method (#4123) 2016-12-28 11:50:41 -08:00
Wouter van Oortmerssen
1a89682251 Merge branch 'master' of https://github.com/google/flatbuffers 2016-12-21 18:06:10 -08:00
Wouter van Oortmerssen
5fd0fefab6 Fixed empty structs generating illegal constructor in C++.
Change-Id: I60418d597b497c3cfa655ad76b3128351e9139f2
2016-12-21 18:04:31 -08:00
Ankur Dave
f8a964d2b0 Fix call to Verifier::VerifyBuffer from BufferRef (#4124)
3a1f776132 added a required identifier parameter
to Verifier::VerifyBuffer but did not update the templated call site in
BufferRef. This causes errors like the following when trying to instantiate the
call site by calling BufferRef::Verify():

    include/flatbuffers/flatbuffers.h: In instantiation of ‘bool flatbuffers::BufferRef<T>::Verify() [with T = MyType]’:
    MyApp.cpp:16:3:   required from here
    include/flatbuffers/flatbuffers.h:1421:37: error: no matching function for call to ‘flatbuffers::Verifier::VerifyBuffer()’
         return verifier.VerifyBuffer<T>();
                                         ^
    include/flatbuffers/flatbuffers.h:1421:37: note: candidate is:
    include/flatbuffers/flatbuffers.h:1352:29: note: template<class T> bool flatbuffers::Verifier::VerifyBuffer(const char*)
       template<typename T> bool VerifyBuffer(const char *identifier) {
                                 ^
    include/flatbuffers/flatbuffers.h:1352:29: note:   template argument deduction/substitution failed:
    include/flatbuffers/flatbuffers.h:1421:37: note:   candidate expects 1 argument, 0 provided
         return verifier.VerifyBuffer<T>();
                                         ^

This commit fixes the BufferRef call site by adding a nullptr argument.
2016-12-21 17:49:45 -08:00
Zarian Waheed
84033ae035 Added helper methods to access struct through reflection. (#4120)
* Added helper methods to access struct through reflection. Also added unit test for it.

* Added a TODO comment to check for the is_struct flag.
2016-12-21 17:48:21 -08:00
Wouter van Oortmerssen
b9efbf6a3d Fixed more Windows build errors.
Change-Id: I556e1c103e8501dc144b16c8698463253de6f4fb
2016-12-21 17:45:27 -08:00
Wouter van Oortmerssen
13194ececa Fixed Windows compiler warning.
Change-Id: I12b31227d4545a8897f638754d6a9ccd029f177e
2016-12-21 16:16:52 -08:00
wvo
9ec9303abb Go related style fixes.
Change-Id: Ie854ace69a21ef685e1ade5584f9d9ce4e8b41f1
2016-12-21 14:32:44 -08:00
Wouter van Oortmerssen
03ee3db240 Fixed Windows build errors.
Change-Id: I11548bfa3cfe307598eb59c56412974c349d614d
2016-12-19 17:04:35 -08:00
Wouter van Oortmerssen
cf825b8819 Added missing generated code from previous commits.
Change-Id: Id7053e4cb5a085a4b047c86ff1f2269329ff7f54
2016-12-19 16:28:06 -08:00
Wouter van Oortmerssen
377a8ba6b2 Merge branch 'master' of https://github.com/google/flatbuffers 2016-12-19 16:26:57 -08:00
Wouter van Oortmerssen
13cf6e66e3 Merge "Documentation improvements: style guide & guide lines." into ub-games-master 2016-12-20 00:25:31 +00:00
Wouter van Oortmerssen
81b6bacead Documentation improvements: style guide & guide lines.
Bug: 22346508
Change-Id: I3f6e6b2811adaaf9d79faca8cdd00af3927299b5
2016-12-19 16:04:08 -08:00
Wouter van Oortmerssen
e6fa14a08d Add default values (if they exist) to native tables.
From cl/142307012.

Change-Id: I54d550573f6506b92ad18e7cc90bcd8589259e52
2016-12-19 15:43:03 -08:00
Wouter van Oortmerssen
c66683f27f Add ::Set function to Unions to make memory ownership clear.
Unions own the NativeTable* value member because they need to destroy them
when the Union goes out of scope.  Currently, the data is destroyed by calling
delete, which means that the member needs to be allocated with new.  However,
making the allocation the responsibility of the client and the destruction
the responsibility of the Union can lead to potential errors.  Adding a
Set function will ensure that the memory is allocated correctly so that it
can be deleted later.

From cl/142161569.

Change-Id: I4605f26d2749164819bfae0140e5fae08442b50a
2016-12-19 15:21:08 -08:00
Zarian Waheed
6d6271db2f Changes for verifying a buffer dynamically using reflection. (#4102)
* Changes for verifying a buffer dynamically using reflection.

* Fixing build issues on linux and applied code reformatting.

* Fixing the file order in cmake file that was messing up the macro based code inclusion.

Added tests for reflection based verification.

* Changes for verifying a buffer dynamically using reflection.

Fixing build issues on linux and applied code reformatting.

Fixing the file order in cmake file that was messing up the macro based code inclusion.

Added tests for reflection based verification.

* Incorporated the code review changes that were requested:

1. Changed the Verify function signature.
2. Changed the variable names to use snake_case.
3. Added better comments.
4. Refactored duplicate code.
5. Changed the verifier class so that it has the same size when compiled with or without FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE macro.

* Setting FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE and FLATBUFFERS_DEBUG_VERIFICATION_FAILURE through cmake for flattests so that it gets propagted to all translation units of flattests.

* Making the Verifier struct fields the same in all cases. Also reverting the target_compile_definitions change in cmake file because build machine on travis does not have cmake version 3.0 or higher which was the version when target_compile_definitions was added in cmake.

* Defining macros through cmake in a portable way using functions that are available in cmake 2.8.
2016-12-16 08:46:30 -08:00
krupnov
ab76c57ec8 random access iterator for vector added (#4119)
* random access iterator for vector added

* Style changes
2016-12-16 08:37:04 -08:00
Wouter van Oortmerssen
d1e8899310 Fixed JS outputting helper for Int64Array.
Change-Id: I7d23fa3416feb78ea18d2c451e7b4e1d9be11bfc
2016-12-14 10:35:26 -08:00
Wouter van Oortmerssen
ccba2edb7c Made GRPC generator missing into a warning.
Change-Id: Iceb1f5b78cff6227905b8a23eb70e9ef6ce909ed
2016-12-14 10:32:44 -08:00
Wouter van Oortmerssen
2a7a44be33 Improving AppVeyor CI with other languages.
Change-Id: Iff630905b5f90814c5f728e3c0e10f7fcd67c7fe
2016-12-12 18:02:13 -08:00
Ricardo Quesada
6301da75d1 add weapon + equipment to json example (#4114)
update json with documentation

removed comments
2016-12-12 14:12:56 -08:00
Robert
059661b9ac Merge pull request #4112 from manolama/tweaks
Restore the ''import "unsafe'' removed in 36daedf35fd0cc2ad0e5e24d187…
2016-12-09 14:29:57 -08:00
Manolama
dc5975ba7a Restore the ''import "unsafe'' removed in 36daedf35f.
This was causing build failures with tools dependent on Flatbuffers in Go.
E.g.
go/src/github.com/google/flatbuffers/go/sizes.go:50: undefined: unsafe in unsafe.Pointer
2016-12-08 22:19:33 -08:00
Robert
0de4f3f75b Create basic issue template (#4107)
* Create basic issue template

* Update ISSUE_TEMPLATE.md
2016-12-07 14:17:30 -08:00
Robert
b59aafc659 Merge pull request #3791 from mmastrac/master
Avoid unsafe when sizing types
2016-12-07 11:51:11 -08:00
Robert
92a6ae93fa Merge pull request #3977 from gonzaloserrano/feature/go-generic-deserialitzation
Add a generic way to deserialize a flatbuffer in Go.
2016-12-07 11:17:55 -08:00
Ronak Jain
a31ddd2bb3 Support for Golang GRPC (Experimental) (#4082)
* support for grpc golang

* refactored grpc go generator

* added grpc-go test and refactored

* refactored idl_gen_grpc.cpp

* fixed grpc generate method name

* refactored flatc and fixed line length issue

* added codec to go lib and fixed formatting issues

* fixed spacing issues
2016-12-05 13:20:38 -08:00
Wouter van Oortmerssen
bc2ec7119b Adds typedefs and functions to help write generic code.
The following changes have been made to the C++ codegen to enable writing generic code
that uses the Table and NativeTable types.

- Adds TableType and NativeTableType typedefs to NativeTable and Table structs.
- Adds GetFullyQualifiedName() to NativeTables if --gen-name-strings is set.
- Adds a static Pack function to Tables that simply calls the global CreateX functions.

See cr/140391505 as an example of improved usage.

From cl/140529288.

Change-Id: Idec137c16129e15c1783f94fabdcea24aeeaaef6
2016-12-02 14:25:39 -08:00
Wouter van Oortmerssen
641b397f8b Allows structs to be stored directly as member variables.
Introduce a "native_inline" attribute that can be applied on fields that are structs.
This results in NativeTable code generation that sets the struct "inline" rather than
storing it in a pointer.

From cl/140527470.

Change-Id: I208724f552b8b921b20923e0bf82f42cb3582416
2016-12-02 14:25:08 -08:00
Wouter van Oortmerssen
d342918790 Merge branch 'master' of https://github.com/google/flatbuffers
Change-Id: I02b00b22cdd2d1bd32de3273ff69185c9b0f4e5b
2016-11-21 15:20:33 -08:00
The Gitter Badger
c4377390a8 Add Gitter badge (#4075) 2016-11-18 11:42:50 -08:00
benssson
5608be0f96 Fixed javascript helper for typed arrays of scalars not taking into (#4068)
account underlying buffer's byte offset.
2016-11-18 11:42:50 -08:00
Antoine Descamps
dbecdf209d [PHP] Use mb_detect_encoding when available (#3952)
I've faced an issue where I want to serialize UTF-8 emojis and FlatBufferBuilder::is_utf8 would return false on them.
I was not able to add the corresponding hexadecimal code because I don't understand how the whole thing works but what i've done is using the `mb_detect_encoding` function which handles correctly all supposed UTF-8 characters.
2016-11-16 09:54:57 -08:00
garretmcgraw
c05803bf96 Making flatbuffers JSON parsing deal with unexpected null values when unknown JSON is allowed. (#4083) 2016-11-09 14:38:48 -08:00
Michael Paulson
d298adc4e6 chore(lint) (#4079)
* chore(lint)

I accidentally let 2 pieces of lint in with my generated code.

* fix(generate-code): I did not generate all the required code for tests.
2016-11-07 10:27:26 -08:00
Wouter van Oortmerssen
c2050aa0e3 Merge branch 'master' of https://github.com/google/flatbuffers 2016-11-07 10:09:42 -08:00
Wouter van Oortmerssen
290e9f270b Fixes to support GCC 4.4.7
Fixed generation of a trailing comma and removed unnecessary use of a lambda.

Change-Id: I9993f6eb83e2ebc36fc40295a2059c340c1fbe03
Tested: on Linux.
2016-11-07 09:51:28 -08:00
The Gitter Badger
76ae10df42 Add Gitter badge (#4075) 2016-11-02 14:05:31 -07:00
benssson
cf0d7829a6 Fixed javascript helper for typed arrays of scalars not taking into (#4068)
account underlying buffer's byte offset.
2016-10-26 10:29:36 -07:00
Wouter van Oortmerssen
af21b9064d Change docs to not encourage use of 1 byte buffers.
Change-Id: Ib0b1692044f35e374a0f7c0359c94319f4a25619
2016-10-24 10:29:09 -07:00
Wouter van Oortmerssen
e31fbb0b23 Fixed STLPort error for missing vector::data()
Change-Id: I06fb61edf018adf0f26a81de4596b4972226e466
Tested: on Android.
Bug: 30263829
2016-10-21 17:35:41 -07:00
Wouter van Oortmerssen
43ba7c6369 Merge branch 'master' of https://github.com/google/flatbuffers 2016-10-21 16:57:50 -07:00
Wouter van Oortmerssen
dae513e0e7 Made nesting vs inline clearer in the docs.
Also fixed structs not being created inline in the tutorial,
which would actually have bad consequences if used.

Change-Id: Idce215c61a1b24a297cee76f625052bb2722e970
2016-10-21 15:22:14 -07:00
cajun-rat
d8944e45a2 Fix Closure Compiler warnings (#4067)
* Make parameter order in jsdocs match function

When the order doesn't match the Google Closure Javascript compiler generates
warnings

* Prefix optional parameters with opt_

The Closure Compiler emits warnings when this isn't the case
2016-10-21 14:52:42 -07:00
Baptiste Lepilleur
5b5fcbfc00 Java: fix unsigned default value code generation and add 'L' suffix for long default value (#4051)
* Java: emit "signed" equivalent of unsigned default value in generated code and add "L" suffix to long default value.

* Updated generated code

* Only convert ulong to "signed" equivalent. ubyte and ushort don't need specific handling as "user facing" type is int. uint need 'L' suffix as "user facing" type is long.

* Added missing cast to primitive type of default value which is in "user facing" type in builder.add<type>() calls.

* Do not cast default value to actual type in C#.
2016-10-21 14:27:15 -07:00
Wouter van Oortmerssen
6862b2ff08 Added functionality to obtain a buffer pointer from a root.
Change-Id: Ia63e41d0304e8668ea4ce09a4c31dd999eb96994
Tested: on Linux.
Bug: 32218623
2016-10-19 16:24:24 -07:00
Wouter van Oortmerssen
22e87071dd Fixed lambda return value error on VS2010.
Change-Id: I6d0e8469bfa5b4c8a3f1cb119e186f4cf62c76ae
2016-10-17 15:04:12 -07:00
Wouter van Oortmerssen
606098cac8 Fixed unused variable warnings, and made sure they are on.
Tested on Linux.

Change-Id: Ie18d6857f9ae8b1c3953a116203b4a8bb70a2ede
2016-10-17 13:06:11 -07:00
Wouter van Oortmerssen
b5c622762b Fixed broken traits codegen for --scoped-enums.
Change-Id: I5f538d12ea37d11d2e239ddde32eefcdd91e347b
Tested: on Linux.
2016-10-17 11:53:28 -07:00
Wouter van Oortmerssen
2beb985fcc Merge branch 'master' of https://github.com/google/flatbuffers 2016-10-17 10:46:14 -07:00
Zhe Wang
fd97404c51 Add missing include (#4052) 2016-10-17 09:57:46 -07:00
Wouter van Oortmerssen
d9fe4e2769 Allow other pointer types than unique_ptr for object API.
Change-Id: I945890ce667a2f5a6c0495e78fd5326ed33b9914
Tested: on Linux.
Bug: 30135763
2016-10-17 09:54:52 -07:00
Wouter van Oortmerssen
424fc0c3ac Fixed inconsistent use of namespace directory prefixing.
Change-Id: I2cab7a1f68b8e643c1057e0a366572421a94ed41
Tested: on Linux.
2016-10-12 16:05:57 -07:00
Wouter van Oortmerssen
c81239f6ea Fix lambda compilation error in VS.
Change-Id: I814008b6eeffec9bd4b8810e4b29db9ea6218bb8
2016-10-12 14:51:02 -07:00
Wouter van Oortmerssen
b830dac266 Added missing generated code files.
Change-Id: Ifb977411b65f8721cf9db891d7a62798bd593c0c
2016-10-12 14:40:35 -07:00
Wouter van Oortmerssen
dc38f93ca8 Merge branch 'master' of https://github.com/google/flatbuffers 2016-10-12 14:39:36 -07:00
Wouter van Oortmerssen
f9025eeb52 Clarified tutorial w.r.t reading/writing buffers.
Bug: 30736848

Signed-off-by: Wouter van Oortmerssen <wvo@google.com>
2016-10-12 14:30:31 -07:00
Wouter van Oortmerssen
486c048a0d Added support for size prefixed buffers.
These are useful for streaming FlatBuffers. The functionality
ensures proper alignment of the whole buffer.

Tested: on OS X.
Bug: 27123865

Change-Id: Ic7d75a618c1bb470ea44c4dcf202ff71f2b3f4f1
Signed-off-by: Wouter van Oortmerssen <wvo@google.com>
2016-10-12 14:30:31 -07:00
Wouter van Oortmerssen
ab51b03093 Fixed line numbers being off in multi-line comments.
Change-Id: I4c27892c249527980d8f52a2cca801dace70289f
2016-10-12 11:22:20 -07:00
Wouter van Oortmerssen
dc2fa215b8 External references for the object API thru a resolver function.
This allows hashed string fields to be used for lookup of any
C++ objects, a pointer to which are then stored in the object
besides the original hash for easy access.

Change-Id: I2247a13c349b905f1c54660becde2c818ad23e97
Tested: on Linux.
Bug: 30204449
2016-10-12 11:22:20 -07:00
Baptiste Lepilleur
199157e8f4 flatc java generator: namespace_test2.fbs is missing namespace prefix for referToA2() return type (#4040)
* Fix flatc generating incorrect java/c# code for namespace_test2.fbs. In code for TableInC, method referToA2() returned type SecondTableInA instead of NamespaceA.SecondTableInA.

* Updated generated code.

* Fixed indendation.
2016-10-07 09:42:29 -07:00
Andrew Hundt
520d68449f CMake now accepts external toolchain configuration (#4045)
Resolves #4038
Related to https://github.com/ruslo/hunter/pull/529
2016-10-05 13:20:30 -07:00
jbrads
b075b8c49d Generate type traits for unions to map a type to the corresponding u… (#4032)
*  Generate type traits for unions to map a type to the corresponding union enum value.

* Fixed break with union enum type traits when type is in a namespace.

* Fixed spacing and variable names in type traits generation to match style guidelines.

*  Fixed spacing in type traits generation to match style guidelines.

* Regenerated test schema header.
2016-10-03 14:14:25 -07:00
Wouter van Oortmerssen
f6c1a1ebcf Merge pull request #4025 from paszea/reflection_fqn
serialize fully qualified struct & enum name in schema binary
2016-09-21 11:06:34 -07:00
Wouter van Oortmerssen
c4aede2268 Merge pull request #4027 from kimsin3003/csharp
Added IFlatbufferObject.cs file to project for .net.
2016-09-19 10:02:50 -07:00
FTT\kimsin
4a43c2bb2c Added IFlatbufferObject.cs file to project for .net.
Before edition, IFlatbufferObject.cs file wasn't in the project and building the project throwed error.
2016-09-19 16:16:15 +09:00
Jason Sanmiya
b2e55c556e Merge "Fix Windows warnings." into ub-games-master 2016-09-15 18:42:42 +00:00
Xun Liu
df0991b7de serialize fully qualified struct & enum name in schema binary 2016-09-15 10:42:23 -07:00
Wouter van Oortmerssen
3368407aff Add a --conform-includes flag to specify include path for the conform schema
(mirrored from cl 133146933)

Change-Id: I61385289728777cae83139fef0229001d92382ca
2016-09-14 11:39:33 -07:00
Wouter van Oortmerssen
25f3f358a0 Merge pull request #4021 from mogemimi/remove-extra-semi
Remove extra semicolon
2016-09-14 09:18:40 -07:00
mogemimi
00e8aa87b3 Remove extra semicolon 2016-09-13 20:59:57 +09:00
Wouter van Oortmerssen
09ee46a83e Merge pull request #4020 from albertofem/feature/allow_public_accessor_net
Allow access to underlying ByteBuffer in C#
2016-09-12 10:35:16 -07:00
Alberto Fernández
02dfa64a89 Allow access to underlying ByteBuffer 2016-09-12 09:35:08 +02:00
Wouter van Oortmerssen
f136570417 Merge pull request #4004 from sahiljain/fix-3909
Return error when full string cannot be parsed into int
2016-09-09 17:01:05 -07:00
Sahil Jain
b6ba322a04 Return error when full string cannot be parsed into int 2016-09-09 19:47:20 -04:00
Wouter van Oortmerssen
4b79ff5351 Merge pull request #4017 from changnet/master
option to build shared library,defeault off
2016-09-09 16:21:27 -07:00
Wouter van Oortmerssen
edd77ae2f3 Merge pull request #4010 from rgilles/master
Isolate the complied Java classes into a target folder.
2016-09-09 15:28:37 -07:00
Jason Sanmiya
985de211af Fix Windows warnings.
Cmake issued a warning when the variable is in quotation marks
in an if statement.

Visual Studio upgrades constants to int and issues a truncation
warning, so inserted a cast.

Change-Id: I60cdcb5c2565cd5e97f80b9c2ff1e6abc32b1deb
Tested: Builds without warning on VS2015.
2016-09-09 14:51:33 -07:00
Wouter van Oortmerssen
8e3fa336eb Merge pull request #3998 from aardappel/master
Switched C# accessors from classes to structs
2016-09-07 16:59:42 -07:00
Romain Gilles
582fd90c4a Use the find -exec instead of find ... | xargs otherwise when there is error log in the output of the build. 2016-09-06 23:28:22 +02:00
changnet
a15659e9f8 option to build shared library,defeault off 2016-09-07 01:12:04 +08:00
Romain Gilles
afd230af8d Remove commented line. Add a last step that remove the target folder after the build and the tests execution. 2016-09-01 13:01:07 +02:00
Wouter van Oortmerssen
52ca75506a Switched C# accessors from classes to structs 2016-08-31 17:34:51 -07:00
Romain Gilles
3bb9b839b8 Add remove of remaining class files before running the build 2016-08-30 10:18:47 +02:00
Romain Gilles
5e7bfd0461 Isolate the complied Java classes into a target folder + log java version.
It is a common practice to put all the compiled classes into a
dedicated folder in order to:
 - avoid to mix the code and the complied classes
 - to allow a simple way to remove the complied classes

Add log of java version in order to make it explicit to the end user.
2016-08-29 11:26:31 +02:00
Wouter van Oortmerssen
d05d114523 Merge pull request #4007 from TGIshib/key
lookupByKey corrections
2016-08-26 15:26:40 -07:00
TGIshib
722b903f89 Remove languages check 2016-08-27 01:21:15 +03:00
TGIshib
2ff6152204 Update idl_gen_general.cpp 2016-08-27 00:42:06 +03:00
TGIshib
98f9af8ecc Merge remote-tracking branch 'refs/remotes/google/master' into key
# Conflicts:
#	src/idl_gen_general.cpp
2016-08-27 00:35:06 +03:00
Wouter van Oortmerssen
481d332e72 Fixed compile error in LookupByKey fix.
Change-Id: Ice94f09197235cf71b41a22d0767bd7b119284e1
2016-08-26 14:18:04 -07:00
TGIshib
1a18122e3f Last idl_gen_general.cpp update 2016-08-27 00:04:25 +03:00
Wouter van Oortmerssen
ee56418cef Undo compile Java classes into target folder.
This was causing class loader errors on Java 1.6.

Change-Id: Id1d9e7e369aad639115664c43a867c4d3a82f9f1
Tested: on Linux.
2016-08-26 14:02:00 -07:00
Wouter van Oortmerssen
e1f8037cb5 Fixed Java LookupByKey functionality for Java 1.6
Tested: on Linux.

Change-Id: Iea336f75a3b6e722743563813c3c9ed9db4d02fe
2016-08-26 13:58:16 -07:00
TGIshib
ea9ee4c99e Update idl_gen_general.cpp 2016-08-26 23:47:23 +03:00
TGIshib
4026117ba1 Correct idl_gen_general 2016-08-26 23:15:25 +03:00
Wouter van Oortmerssen
49ee30a207 Merge pull request #3978 from TGIshib/key
Find by key on C# and Java (2)
2016-08-26 12:03:28 -07:00
TGIshib
7c69c5dc3d Fix lookupByKey, improve compareStrings 2016-08-26 19:41:32 +03:00
Wouter van Oortmerssen
223ebebbeb Merge pull request #4003 from rgilles/master
Isolate the complied Java classes into a target folder.
2016-08-26 09:22:29 -07:00
Romain Gilles
f96eb472b3 Isolate the complied Java classes into a target folder.
It is a common practice to put all the compiled classes into a
dedicated folder in order to:
 - void to mixing the code and the complied classes
 - to allow a simple way to remove the complied classes
2016-08-25 10:40:41 +02:00
Wouter van Oortmerssen
c1b0abe079 Merge branch 'master' of https://github.com/google/flatbuffers 2016-08-24 18:07:18 -07:00
Wouter van Oortmerssen
b04e21db16 Fixed --scoped-enums not always generating type prefixes.
Change-Id: Ib5b0ae75617e18094ac31eb5e11d10e5d592cf9b
Tested: on Linux.
2016-08-24 18:05:49 -07:00
Wouter van Oortmerssen
756050b62c Fixed "unknown command-line argument" output format.
Change-Id: Idd49bc61118c29d6d7364d2cd54a6f7932917570
2016-08-24 17:09:25 -07:00
Wouter van Oortmerssen
ef67a58410 Merge pull request #4001 from vitalyisaev2/master
Debianization with CPack
2016-08-24 15:03:31 -07:00
Wouter van Oortmerssen
2da0821286 Merge pull request #3994 from royalharsh/python_grpc
Initial grpc support for other languages
2016-08-24 14:59:32 -07:00
Vitaly Isaev
928effd198 Debianization with CPack 2016-08-25 00:00:22 +03:00
Harsh Vardhan
2e7806ede0 Initial support to add other languages to flatbuffers 2016-08-24 23:42:59 +05:30
Wouter van Oortmerssen
67967476b2 Merge pull request #4000 from sahiljain/fix-3966
Remove Struct::GetPointer() useless method
2016-08-24 10:34:32 -07:00
Wouter van Oortmerssen
79d127c863 Merge pull request #2133 from evolutional/cs-bounds-check
C#: added #define BYTEBUFFER_NO_BOUNDS_CHECK
2016-08-24 09:26:06 -07:00
Sahil Jain
4f3e1c2831 Remove Struct::GetPointer() useless method 2016-08-24 04:12:25 -04:00
gonzaloserrano
199a49b5b3 Add a generic way to deserialize a flatbuffer in Go.
Similar to what protobufs does with its `Message` interface, introduce here such interface and create a generic `GetRootAs` method to deserialize a flatbuffer.
2016-08-23 16:38:22 +02:00
Wouter van Oortmerssen
96ab6ade5a Merge pull request #3993 from bhamiltoncx/generate-text-failure
Allow GenerateText() to indicate failure to encode flatbuffer to JSON
2016-08-22 11:32:52 -07:00
TGIshib
9f16090f90 Improve LookupByKey , update docs 2016-08-22 18:10:52 +03:00
Robert
63b240ec7b Merge pull request #3995 from rw/go-remove-unused-initializer
Remove invalid vector item heap alloc
2016-08-20 22:07:10 -07:00
rw
c4ba502f57 Remove invalid vector item heap alloc
Fixes #3986
2016-08-20 20:33:36 -07:00
Ben Hamilton
94d5643f97 Allow GenerateText() to indicate failure to encode flatbuffer to JSON (i.e., non-UTF-8 string data) 2016-08-18 10:23:26 -07:00
Wouter van Oortmerssen
f0d91fa143 Merge pull request #3992 from akazakov/master
Add byte array and unintialized array creation to FlatBufferBuilder
2016-08-17 09:03:46 -07:00
Artem Kazakov
726a5f523e add byte array and unintialized array creation to FlatBufferBuilder 2016-08-16 16:26:53 -04:00
TGIshib
fa74ce6d16 Update idl_gen_general.cpp 2016-08-15 13:30:30 +03:00
TGIshib
8fdced4e11 Update 2016-08-14 14:58:51 +03:00
TGIshib
9031597f49 Merge remote-tracking branch 'refs/remotes/google/master' into key 2016-08-13 16:28:38 +03:00
TGIshib
dc7f5bc0d8 Remake 2016-08-03 13:29:50 +03:00
TGIshib
867dfc5957 Merge remote-tracking branch 'refs/remotes/google/master' 2016-08-02 12:41:20 +03:00
TGIshib
52acb4b347 Merge remote-tracking branch 'refs/remotes/google/master' 2016-07-31 17:08:25 +03:00
TGIshib
4c861daa3e Merge remote-tracking branch 'refs/remotes/google/master' 2016-07-28 21:58:45 +03:00
TGIshib
b7a26d73ee Merge remote-tracking branch 'refs/remotes/google/master' 2016-07-26 00:07:23 +03:00
Raman
1ba4d3c4c7 Update idl_gen_general.cpp 2016-07-25 23:04:01 +02:00
Raman
06c1ad5a73 Merge pull request #3 from TGIshib/key
Update idl_gen_general.cpp
2016-07-23 15:17:28 +03:00
Raman
38b3893211 Update idl_gen_general.cpp 2016-07-23 14:16:30 +02:00
Matt Mastracci
36daedf35f Avoid unsafe when sizing types 2016-07-18 18:48:39 -06:00
Raman
247388a20c Merge pull request #2 from TGIshib/hex-bug
Fixed bug with negative hex constants (2).
2016-07-12 20:52:16 +03:00
Oli Wilkinson
4802e8a285 C# added BYTEBUFFER_NO_BOUNDS_CHECK #define
Removes the bounds checking on the ByteBuffer Get/Put operations. Can be dangerous when used with UNSAFE_BYTEBUFFER but results in increased performance. Use at your own risk!
2015-12-14 21:06:29 -05:00
128 changed files with 9998 additions and 2945 deletions

12
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,12 @@
Thank you for submitting an issue!
Please make sure you include the names of the affected language(s), compiler version(s), operating system version(s), and FlatBuffers version(s) in your issue title.
This helps us get the correct maintainers to look at your issue. Here are examples of good titles:
- Crash when accessing FlatBuffer [C++, gcc 4.8, OS X, master]
- Flatc converts a protobuf 'bytes' field to 'string' in fbs schema file [all languages, FlatBuffers 1.4]
Include other details as appropriate.
Thanks!

16
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,16 @@
Thank you for submitting a PR!
Please make sure you include the names of the affected language(s) in your PR title.
This helps us get the correct maintainers to look at your issue.
If you make changes to any of the code generators, be sure to run
`cd tests && sh generate_code.sh` (or equivalent .bat) and include the generated
code changes in the PR. This allows us to better see the effect of the PR.
If your PR includes C++ code, please adhere to the Google C++ Style Guide,
and don't forget we try to support older compilers (e.g. VS2010, GCC 4.6.3),
so only some C++11 support is available.
Include other details as appropriate.
Thanks!

2
.gitignore vendored
View File

@@ -64,3 +64,5 @@ target
build/VS2010/FlatBuffers.sdf
build/VS2010/FlatBuffers.opensdf
build/VS2010/ipch/**/*.ipch
*.so
Testing/Temporary

57
CMake/PackageDebian.cmake Normal file
View File

@@ -0,0 +1,57 @@
# ------------------- Debianization ---------------------
if (UNIX)
# Set build environment
SET(CPACK_GENERATOR "TGZ;DEB")
SET(CPACK_SOURCE_TGZ "ON")
# Common package information
SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY
"FlatBuffers is an efficient cross platform serialization library for C++, with support for Java, C# and Go. It was created at Google specifically for game development and other performance-critical applications.")
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})
SET(CPACK_PACKAGE_VERSION "${VERSION_MAJOR}.${VERSION_MINOR}.${VERSION_PATCH}-${VERSION_COMMIT}")
SET(CPACK_DEBIAN_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}")
# Derive architecture
IF(NOT CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
FIND_PROGRAM(DPKG_CMD dpkg)
IF(NOT DPKG_CMD)
MESSAGE(STATUS "Can not find dpkg in your path, default to i386.")
SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE i386)
ENDIF(NOT DPKG_CMD)
EXECUTE_PROCESS(COMMAND "${DPKG_CMD}" --print-architecture
OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE
OUTPUT_STRIP_TRAILING_WHITESPACE
)
ENDIF(NOT CPACK_DEBIAN_PACKAGE_ARCHITECTURE)
# Package name
SET(CPACK_DEBIAN_PACKAGE_NAME "flatbuffers")
SET(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE.txt)
SET(CPACK_PACKAGE_FILE_NAME
"${CPACK_DEBIAN_PACKAGE_NAME}_${CPACK_DEBIAN_PACKAGE_VERSION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}")
endif(UNIX)
INCLUDE(CPack)

View File

@@ -12,6 +12,9 @@ option(FLATBUFFERS_BUILD_FLATC "Enable the build of the flatbuffers compiler"
ON)
option(FLATBUFFERS_BUILD_FLATHASH "Enable the build of flathash" ON)
option(FLATBUFFERS_BUILD_GRPCTEST "Enable the build of grpctest" OFF)
option(FLATBUFFERS_BUILD_SHAREDLIB
"Enable the build of the flatbuffers shared library"
OFF)
if(NOT FLATBUFFERS_BUILD_FLATC AND FLATBUFFERS_BUILD_TESTS)
message(WARNING
@@ -27,6 +30,8 @@ set(FlatBuffers_Library_SRCS
include/flatbuffers/util.h
include/flatbuffers/reflection.h
include/flatbuffers/reflection_generated.h
include/flatbuffers/flexbuffers.h
src/code_generators.cpp
src/idl_parser.cpp
src/idl_gen_text.cpp
src/reflection.cpp
@@ -44,8 +49,12 @@ set(FlatBuffers_Compiler_SRCS
src/idl_gen_fbs.cpp
src/idl_gen_grpc.cpp
src/flatc.cpp
src/flatc_main.cpp
grpc/src/compiler/schema_interface.h
grpc/src/compiler/cpp_generator.h
grpc/src/compiler/cpp_generator.cc
grpc/src/compiler/go_generator.h
grpc/src/compiler/go_generator.cc
)
set(FlatHash_SRCS
@@ -56,7 +65,6 @@ set(FlatHash_SRCS
set(FlatBuffers_Tests_SRCS
${FlatBuffers_Library_SRCS}
src/idl_gen_fbs.cpp
src/idl_gen_general.cpp
tests/test.cpp
# file generate by running compiler on tests/monster_test.fbs
${CMAKE_CURRENT_BINARY_DIR}/tests/monster_test_generated.h
@@ -70,13 +78,7 @@ set(FlatBuffers_Sample_Binary_SRCS
)
set(FlatBuffers_Sample_Text_SRCS
include/flatbuffers/flatbuffers.h
include/flatbuffers/hash.h
include/flatbuffers/idl.h
include/flatbuffers/util.h
src/idl_parser.cpp
src/idl_gen_text.cpp
src/util.cpp
${FlatBuffers_Library_SRCS}
samples/sample_text.cpp
# file generated by running compiler on samples/monster.fbs
${CMAKE_CURRENT_BINARY_DIR}/samples/monster_generated.h
@@ -95,7 +97,10 @@ set(FlatBuffers_GRPCTest_SRCS
# source_group(Compiler FILES ${FlatBuffers_Compiler_SRCS})
# source_group(Tests FILES ${FlatBuffers_Tests_SRCS})
if(APPLE)
if(EXISTS "${CMAKE_TOOLCHAIN_FILE}")
# do not apply any global settings if the toolchain
# is being configured externally
elseif(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -stdlib=libc++")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra")
elseif(CMAKE_COMPILER_IS_GNUCXX)
@@ -110,7 +115,8 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
"${CMAKE_CXX_FLAGS} -Wall -pedantic -Werror -Wextra -Werror=shadow")
if (GCC_VERSION VERSION_GREATER 4.4)
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -Wunused-result -Werror=unused-result")
"${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
@@ -118,7 +124,7 @@ elseif(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -fsigned-char")
elseif("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
elseif(${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -std=c++0x -stdlib=libc++ -Wall -pedantic -Werror \
-Wextra")
@@ -163,6 +169,11 @@ if(FLATBUFFERS_BUILD_FLATHASH)
add_executable(flathash ${FlatHash_SRCS})
endif()
if(FLATBUFFERS_BUILD_SHAREDLIB)
add_library(flatbuffers_shared SHARED ${FlatBuffers_Library_SRCS})
set_target_properties(flatbuffers_shared PROPERTIES OUTPUT_NAME flatbuffers)
endif()
function(compile_flatbuffers_schema_to_cpp SRC_FBS)
get_filename_component(SRC_FBS_DIR ${SRC_FBS} PATH)
string(REGEX REPLACE "\\.fbs$" "_generated.h" GEN_HEADER ${SRC_FBS})
@@ -188,6 +199,9 @@ if(FLATBUFFERS_BUILD_TESTS)
compile_flatbuffers_schema_to_cpp(tests/monster_test.fbs)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/tests)
add_executable(flattests ${FlatBuffers_Tests_SRCS})
set_property(TARGET flattests
PROPERTY COMPILE_DEFINITIONS FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
FLATBUFFERS_DEBUG_VERIFICATION_FAILURE=1)
compile_flatbuffers_schema_to_cpp(samples/monster.fbs)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/samples)
@@ -211,6 +225,9 @@ if(FLATBUFFERS_INSTALL)
if(FLATBUFFERS_BUILD_FLATC)
install(TARGETS flatc DESTINATION bin)
endif()
if(FLATBUFFERS_BUILD_SHAREDLIB)
install(TARGETS flatbuffers_shared DESTINATION lib)
endif()
endif()
if(FLATBUFFERS_BUILD_TESTS)
@@ -222,3 +239,7 @@ if(FLATBUFFERS_BUILD_TESTS)
endif()
include(CMake/BuildFlatBuffers.cmake)
if(FLATBUFFERS_PACKAGE_DEBIAN)
include(CMake/PackageDebian.cmake)
endif()

View File

@@ -25,7 +25,7 @@ use Github pull requests for this purpose.
Some tips for good pull requests:
* Use our code
[style guide](http://google-styleguide.googlecode.com/svn/trunk/cppguide.html).
[style guide](https://google.github.io/styleguide/cppguide.html).
When in doubt, try to stay true to the existing code of the project.
* Write a descriptive commit message. What problem are you solving and what
are the consequences? Where and what did you test? Some good tips:

View File

@@ -24,7 +24,9 @@ LOCAL_PATH := $(call realpath-portable,$(LOCAL_PATH))
include $(CLEAR_VARS)
LOCAL_MODULE := flatbuffers
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_EXPORT_CPPFLAGS := -std=c++11 -fexceptions -Wall -Wno-literal-suffix
LOCAL_EXPORT_CPPFLAGS := -std=c++11 -fexceptions -Wall \
-DFLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
include $(BUILD_STATIC_LIBRARY)
# static library that additionally includes text parsing/generation/reflection
@@ -34,7 +36,8 @@ LOCAL_MODULE := flatbuffers_extra
LOCAL_SRC_FILES := src/idl_parser.cpp \
src/idl_gen_text.cpp \
src/reflection.cpp \
src/util.cpp
src/util.cpp \
src/code_generators.cpp
LOCAL_STATIC_LIBRARIES := flatbuffers
include $(BUILD_STATIC_LIBRARY)

View File

@@ -14,13 +14,33 @@ configuration:
before_build:
- cmake -G"Visual Studio 10 2010"
# This cuts down on a lot of noise generated by xamarin warnings.
- del "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets"
build:
project: ALL_BUILD.vcxproj
verbosity: minimal
#test_script:
# - Debug/flattests.exe
test_script:
- rem "---------------- C++ -----------------"
- "%CONFIGURATION%\\flattests.exe"
- rem "---------------- Java -----------------"
- "cd tests"
- "java -version"
- "JavaTest.bat"
- rem "---------------- JS -----------------"
- "node --version"
- "..\\%CONFIGURATION%\\flatc -b monster_test.fbs unicode_test.json"
- "node JavaScriptTest"
- rem "---------------- C# -----------------"
# Have to compile this here rather than in "build" above because AppVeyor only
# supports building one project??
- "cd FlatBuffers.Test"
- "msbuild.exe /property:Configuration=Release;OutputPath=tempcs /verbosity:minimal FlatBuffers.Test.csproj"
- "tempcs\\FlatBuffers.Test.exe"
# TODO: add more languages.
- "cd ..\\.."
#artifacts:
# - path: Release/flatc.exe
# name: flatc.exe
artifacts:
- path: $(CONFIGURATION)\\flatc.exe
name: flatc.exe

View File

@@ -93,6 +93,12 @@ Additional options:
output (by default the case for C++ and JS), all code will end up in
this one file.
- `--no-js-exports` : Removes Node.js style export lines (useful for JS)
- `--goog-js-export` : Uses goog.exportsSymbol and goog.exportsProperty
instead of Node.js style exporting. Needed for compatibility with the
Google closure compiler (useful for JS).
- `--raw-binary` : Allow binaries without a file_indentifier to be read.
This may crash flatc given a mismatched schema.
@@ -108,9 +114,14 @@ Additional options:
to the reflection/reflection.fbs schema. Loading this binary file is the
basis for reflection functionality.
- `--bfbs-comments`: Add doc comments to the binary schema files.
- `--conform FILE` : Specify a schema the following schemas should be
an evolution of. Gives errors if not. Useful to check if schema
modifications don't break schema evolution rules.
- `--include-prefix PATH` : Prefix this path to any generated include
statements.
NOTE: short-form options for generators are deprecated, use the long form
whenever possible.

View File

@@ -85,7 +85,7 @@ convenient accessors for all fields, e.g. `hp()`, `mana()`, etc:
*Note: That we never stored a `mana` value, so it will return the default.*
## Object based API.
## Object based API. {#flatbuffers_cpp_object_based_api}
FlatBuffers is all about memory efficiency, which is why its base API is written
around using as little as possible of it. This does make the API clumsier
@@ -99,13 +99,107 @@ construction, access and mutation.
To use:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
auto monsterobj = GetMonster(buffer)->UnPack();
// Autogenerated class from table Monster.
MonsterT monsterobj;
// Deserialize from buffer into object.
UnPackTo(&monsterobj, flatbuffer);
// Update object directly like a C++ class instance.
cout << monsterobj->name; // This is now a std::string!
monsterobj->name = "Bob"; // Change the name.
// Serialize into new flatbuffer.
FlatBufferBuilder fbb;
CreateMonster(fbb, monsterobj.get()); // Serialize into new buffer.
Pack(fbb, &monsterobj);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The following attributes are specific to the object-based API code generation:
- `native_inline` (on a field): Because FlatBuffer tables and structs are
optionally present in a given buffer, they are best represented as pointers
(specifically std::unique_ptrs) in the native class since they can be null.
This attribute changes the member declaration to use the type directly
rather than wrapped in a unique_ptr.
- `native_default`: "value" (on a field): For members that are declared
"native_inline", the value specified with this attribute will be included
verbatim in the class constructor initializer list for this member.
- `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:
struct Vec2 {
x: float;
y: float;
}
generates the following Object-Based API class:
struct Vec2T : flatbuffers::NativeTable {
float x;
float y;
};
However, it can be useful to instead use a user-defined C++ type since it
can provide more functionality, eg.
struct vector2 {
float x = 0, y = 0;
vector2 operator+(vector2 rhs) const { ... }
vector2 operator-(vector2 rhs) const { ... }
float length() const { ... }
// etc.
};
The `native_type` attribute will replace the usage of the generated class
with the given type. So, continuing with the example, the generated
code would use |vector2| in place of |Vec2T| for all generated code.
However, becuase the native_type is unknown to flatbuffers, the user must
provide the following functions to aide in the serialization process:
namespace flatbuffers {
FlatbufferStruct Pack(const native_type& obj);
native_type UnPack(const FlatbufferStruct& obj);
}
Finally, the following top-level attribute
- native_include: "path" (at file level): Because the `native_type` attribute
can be used to introduce types that are unknown to flatbuffers, it may be
necessary to include "external" header files in the generated code. This
attribute can be used to directly add an #include directive to the top of
the generated code that includes the specified path directly.
# External references.
An additional feature of the object API is the ability to allow you to load
multiple independent FlatBuffers, and have them refer to eachothers objects
using hashes which are then represented as typed pointers in the object API.
To make this work have a field in the objects you want to referred to which is
using the string hashing feature (see `hash` attribute in the
[schema](@ref flatbuffers_guide_writing_schema) documentation). Then you have
a similar hash in the field referring to it, along with a `cpp_type`
attribute specifying the C++ type this will refer to (this can be any C++
type, and will get a `*` added).
Then, in JSON or however you create these buffers, make sure they use the
same string (or hash).
When you call `UnPack` (or `Create`), you'll need a function that maps from
hash to the object (see `resolver_function_t` for details).
# Using different pointer types.
By default the object tree is built out of `std::unique_ptr`, but you can
influence this either globally (using the `--cpp-ptr-type` argument to
`flatc`) or per field (using the `cpp_ptr_type` attribute) to by any smart
pointer type (`my_ptr<T>`), or by specifying `naked` as the type to get `T *`
pointers. Unlike the smart pointers, naked pointers do not manage memory for
you, so you'll have to manage their lifecycles manually.
## Reflection (& Resizing)
There is experimental support for reflection in FlatBuffers, allowing you to

View File

@@ -78,6 +78,9 @@ inefficiency, but also forces you to write *more* code to access data
In this context, it is only a better choice for systems that have very
little to no information ahead of time about what data needs to be stored.
If you do need to store data that doesn't fit a schema, FlatBuffers also
offers a schema-less (self-describing) version!
Read more about the "why" of FlatBuffers in the
[white paper](@ref flatbuffers_white_paper).
@@ -138,6 +141,8 @@ sections provide a more in-depth usage guide.
using FlatBuffers.
- A [white paper](@ref flatbuffers_white_paper) explaining the "why" of
FlatBuffers.
- How to use the [schema-less](@ref flexbuffers) version of
FlatBuffers.
- A description of the [internals](@ref flatbuffers_internals) of FlatBuffers.
- A formal [grammar](@ref flatbuffers_grammar) of the schema language.

156
docs/source/FlexBuffers.md Normal file
View File

@@ -0,0 +1,156 @@
FlexBuffers {#flexbuffers}
==========
FlatBuffers was designed around schemas, because when you want maximum
performance and data consistency, strong typing is helpful.
There are however times when you want to store data that doesn't fit a
schema, because you can't know ahead of time what all needs to be stored.
For this, FlatBuffers has a dedicated format, called FlexBuffers.
This is a binary format that can be used in conjunction
with FlatBuffers (by storing a part of a buffer in FlexBuffers
format), or also as its own independent serialization format.
While it loses the strong typing, you retain the most unique advantage
FlatBuffers has over other serialization formats (schema-based or not):
FlexBuffers can also be accessed without parsing / copying / object allocation.
This is a huge win in efficiency / memory friendly-ness, and allows unique
use cases such as mmap-ing large amounts of free-form data.
FlexBuffers' design and implementation allows for a very compact encoding,
combining automatic pooling of strings with automatic sizing of containers to
their smallest possible representation (8/16/32/64 bits). Many values and
offsets can be encoded in just 8 bits. While a schema-less representation is
usually more bulky because of the need to be self-descriptive, FlexBuffers
generates smaller binaries for many cases than regular FlatBuffers.
FlexBuffers is still slower than regular FlatBuffers though, so we recommend to
only use it if you need it.
# Usage
This is for C++, other languages may follow.
Include the header `flexbuffers.h`, which in turn depends on `flatbuffers.h`
and `util.h`.
To create a buffer:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
flexbuffers::Builder fbb;
fbb.Int(13);
fbb.Finish();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You create any value, followed by `Finish`. Unlike FlatBuffers which requires
the root value to be a table, here any value can be the root, including a lonely
int value.
You can now access the `std::vector<uint8_t>` that contains the encoded value
as `fbb.GetBuffer()`. Write it, send it, or store it in a parent FlatBuffer. In
this case, the buffer is just 3 bytes in size.
To read this value back, you could just say:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
auto root = flexbuffers::GetRoot(my_buffer);
int64_t i = root.AsInt64();
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
FlexBuffers stores ints only as big as needed, so it doesn't differentiate
between different sizes of ints. You can ask for the 64 bit version,
regardless of what you put in. In fact, since you demand to read the root
as an int, if you supply a buffer that actually contains a float, or a
string with numbers in it, it will convert it for you on the fly as well,
or return 0 if it can't. If instead you actually want to know what is inside
the buffer before you access it, you can call `root.GetType()` or `root.IsInt()`
etc.
Here's a slightly more complex value you could write instead of `fbb.Int` above:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
fbb.Map([&]() {
fbb.Vector("vec", [&]() {
fbb.Int(-100);
fbb.String("Fred");
fbb.IndirectFloat(4.0f);
});
fbb.UInt("foo", 100);
});
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This stores the equivalent of the JSON value
`{ vec: [ -100, "Fred", 4.0 ], foo: 100 }`. The root is a dictionary that has
just two key-value pairs, with keys `vec` and `foo`. Unlike FlatBuffers, it
actually has to store these keys in the buffer (which it does only once if
you store multiple such objects, by pooling key values), but also unlike
FlatBuffers it has no restriction on the keys (fields) that you use.
The map constructor uses a C++11 Lambda to group its children, but you can
also use more conventional start/end calls if you prefer.
The first value in the map is a vector. You'll notice that unlike FlatBuffers,
you can use mixed types. There is also a `TypedVector` variant that only
allows a single type, and uses a bit less memory.
`IndirectFloat` is an interesting feature that allows you to store values
by offset rather than inline. Though that doesn't make any visible change
to the user, the consequence is that large values (especially doubles or
64 bit ints) that occur more than once can be shared. Another use case is
inside of vectors, where the largest element makes up the size of all elements
(e.g. a single double forces all elements to 64bit), so storing a lot of small
integers together with a double is more efficient if the double is indirect.
Accessing it:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.cpp}
auto map = flexbuffers::GetRoot(my_buffer).AsMap();
map.size(); // 2
auto vec = map["vec"].AsVector();
vec.size(); // 3
vec[0].AsInt64(); // -100;
vec[1].AsString().c_str(); // "Fred";
vec[1].AsInt64(); // 0 (Number parsing failed).
vec[2].AsDouble(); // 4.0
vec[2].AsString().IsTheEmptyString(); // true (Wrong Type).
vec[2].AsString().c_str(); // "" (This still works though).
vec[2].ToString().c_str(); // "4" (Or have it converted).
map["foo"].AsUInt8(); // 100
map["unknown"].IsNull(); // true
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Binary encoding
A description of how FlexBuffers are encoded is in the
[internals](@ref flatbuffers_internals) document.
# Efficiency tips
* Vectors generally are a lot more efficient than maps, so prefer them over maps
when possible for small objects. Instead of a map with keys `x`, `y` and `z`,
use a vector. Better yet, use a typed vector. Or even better, use a fixed
size typed vector.
* Maps are backwards compatible with vectors, and can be iterated as such.
You can iterate either just the values (`map.Values()`), or in parallel with
the keys vector (`map.Keys()`). If you intend
to access most or all elements, this is faster than looking up each element
by key, since that involves a binary search of the key vector.
* When possible, don't mix values that require a big bit width (such as double)
in a large vector of smaller values, since all elements will take on this
width. Use `IndirectDouble` when this is a possibility. Note that
integers automatically use the smallest width possible, i.e. if you ask
to serialize an int64_t whose value is actually small, you will use less
bits. Doubles are represented as floats whenever possible losslessly, but
this is only possible for few values.
Since nested vectors/maps are stored over offsets, they typically don't
affect the vector width.
* To store large arrays of byte data, use a blob. If you'd use a typed
vector, the bit width of the size field may make it use more space than
expected, and may not be compatible with `memcpy`.
Similarly, large arrays of (u)int16_t may be better off stored as a
binary blob if their size could exceed 64k elements.
Construction and use are otherwise similar to strings.

View File

@@ -292,4 +292,148 @@ 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.
# FlexBuffers
The [schema-less](@ref flexbuffers) version of FlatBuffers have their
own encoding, detailed here.
It shares many properties mentioned above, in that all data is accessed
over offsets, all scalars are aligned to their own size, and
all data is always stored in little endian format.
One difference is that FlexBuffers are built front to back, so children are
stored before parents, and the root of the data starts at the last byte.
Another difference is that scalar data is stored with a variable number of bits
(8/16/32/64). The current width is always determined by the *parent*, i.e. if
the scalar sits in a vector, the vector determines the bit width for all
elements at once. Selecting the minimum bit width for a particular vector is
something the encoder does automatically and thus is typically of no concern
to the user, though being aware of this feature (and not sticking a double in
the same vector as a bunch of byte sized elements) is helpful for efficiency.
Unlike FlatBuffers there is only one kind of offset, and that is an unsigned
integer indicating the number of bytes in a negative direction from the address
of itself (where the offset is stored).
### Vectors
The representation of the vector is at the core of how FlexBuffers works (since
maps are really just a combination of 2 vectors), so it is worth starting there.
As mentioned, a vector is governed by a single bit width (supplied by its
parent). This includes the size field. For example, a vector that stores the
integer values `1, 2, 3` is encoded as follows:
uint8_t 3, 1, 2, 3, 4, 4, 4
The first `3` is the size field, and is placed before the vector (an offset
from the parent to this vector points to the first element, not the size
field, so the size field is effectively at index -1).
Since this is an untyped vector `SL_VECTOR`, it is followed by 3 type
bytes (one per element of the vector), which are always following the vector,
and are always a uint8_t even if the vector is made up of bigger scalars.
### Types
A type byte is made up of 2 components (see flexbuffers.h for exact values):
* 2 lower bits representing the bit-width of the child (8, 16, 32, 64).
This is only used if the child is accessed over an offset, such as a child
vector. It is ignored for inline types.
* 6 bits representing the actual type (see flexbuffers.h).
Thus, in this example `4` means 8 bit child (value 0, unused, since the value is
in-line), type `SL_INT` (value 1).
### Typed Vectors
These are like the Vectors above, but omit the type bytes. The type is instead
determined by the vector type supplied by the parent. Typed vectors are only
available for a subset of types for which these savings can be significant,
namely inline signed/unsigned integers (`TYPE_VECTOR_INT` / `TYPE_VECTOR_UINT`),
floats (`TYPE_VECTOR_FLOAT`), and keys (`TYPE_VECTOR_KEY`, see below).
Additionally, for scalars, there are fixed length vectors of sizes 2 / 3 / 4
that don't store the size (`TYPE_VECTOR_INT2` etc.), for an additional savings
in space when storing common vector or color data.
### Scalars
FlexBuffers supports integers (`TYPE_INT` and `TYPE_UINT`) and floats
(`TYPE_FLOAT`), available in the bit-widths mentioned above. They can be stored
both inline and over an offset (`TYPE_INDIRECT_*`).
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.
### Blobs, Strings and Keys.
A blob (`TYPE_BLOB`) is encoded similar to a vector, with one difference: the
elements are always `uint8_t`. The parent bit width only determines the width of
the size field, allowing blobs to be large without the elements being large.
Strings (`TYPE_STRING`) are similar to blobs, except they have an additional 0
termination byte for convenience, and they MUST be UTF-8 encoded (since an
accessor in a language that does not support pointers to UTF-8 data may have to
convert them to a native string type).
A "Key" (`TYPE_KEY`) is similar to a string, but doesn't store the size
field. They're so named because they are used with maps, which don't care
for the size, and can thus be even more compact. Unlike strings, keys cannot
contain bytes of value 0 as part of their data (size can only be determined by
`strlen`), so while you can use them outside the context of maps if you so
desire, you're usually better off with strings.
### Maps
A map (`TYPE_MAP`) is like an (untyped) vector, but with 2 prefixes before the
size field:
| index | field |
| ----: | :----------------------------------------------------------- |
| -3 | An offset to the keys vector (may be shared between tables). |
| -2 | Byte width of the keys vector. |
| -1 | Size (from here on it is compatible with `TYPE_VECTOR`) |
| 0 | Elements. |
| Size | Types. |
Since a map is otherwise the same as a vector, it can be iterated like
a vector (which is probably faster than lookup by key).
The keys vector is a typed vector of keys. Both the keys and corresponding
values *have* to be stored in sorted order (as determined by `strcmp`), such
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.
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
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
13: uint8_t 2 // value vector of size
// value vector offset points here
14: uint8_t 13, 14 // values
16: uint8_t 4, 4 // types
### The root
As mentioned, the root starts at the end of the buffer.
The last uint8_t is the width in bytes of the root (normally the parent
determines the width, but the root has no parent). The uint8_t before this is
the type of the root, and the bytes before that are the root value (of the
number of bytes specified by the last byte).
So for example, the integer value `13` as root would be:
uint8_t 13, 4, 1 // Value, type, root byte width.
<br>

View File

@@ -131,6 +131,36 @@ object are prefixed with `Get`, e.g.:
monster.GetPos(preconstructedPos);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Storing dictionaries in a FlatBuffer
FlatBuffers doesn't support dictionaries natively, but there is support to
emulate their behavior with vectors and binary search, which means you
can have fast lookups directly from a FlatBuffer without having to unpack
your data into a `Dictionary` or similar.
To use it:
- Designate one of the fields in a table as they "key" field. You do this
by setting the `key` attribute on this field, e.g.
`name:string (key)`.
You may only have one key field, and it must be of string or scalar type.
- Write out tables of this type as usual, collect their offsets in an
array.
- Instead of calling standard generated method,
e.g.: `Monster.createTestarrayoftablesVector`,
call `CreateMySortedVectorOfTables` in C# or
`createSortedVectorOfTables` (from the `FlatBufferBuilder` object) in Java,
which will first sort all offsets such that the tables they refer to
are sorted by the key field, then serialize it.
- Now when you're accessing the FlatBuffer, you can use `LookupByKey`
to access elements of the vector, e.g.:
`Monster.lookupByKey(tablesVectorOffset, "Frodo", dataBuffer)`,
which returns an object of the corresponding table type,
or `null` if not found.
`LookupByKey` performs a binary search, so should have a similar speed to
`Dictionary`, though may be faster because of better caching. `LookupByKey`
only works if the vector has been sorted, it will likely not find elements
if it hasn't been sorted.
## Text parsing
There currently is no support for parsing text (Schema's and JSON) directly

View File

@@ -158,6 +158,10 @@ If you have a need to distinguish between different FlatBuffers in a more
open-ended way, for example for use as files, see the file identification
feature below.
There is an experimental support only in C++ for a vector of unions
(and types). In the example IDL file above, use [Any] to add a
vector of Any to Monster table.
### Namespaces
These will generate the corresponding namespace in C++ for all helper
@@ -285,9 +289,6 @@ Current understood attributes:
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.
- `original_order` (on a table): since elements in a table do not need
to be stored in any particular order, they are often optimized for
space by sorting them to size. This attribute stops that from happening.
- `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
@@ -304,6 +305,18 @@ Current understood attributes:
- `key` (on a field): this field is meant to be used as a key when sorting
a vector of the type of table it sits in. Can be used for in-place
binary search.
- `hash` (on a field). This is an (un)signed 32/64 bit integer field, whose
value during JSON parsing is allowed to be a string, which will then be
stored as its hash. The value of attribute is the hashing algorithm to
use, one of `fnv1_32` `fnv1_64` `fnv1a_32` `fnv1a_64`.
- `original_order` (on a table): since elements in a table do not need
to be stored in any particular order, they are often optimized for
space by sorting them to size. This attribute stops that from happening.
There should generally not be any reason to use this flag.
- 'native_*'. Several attributes have been added to support the [C++ object
Based API](@ref flatbuffers_cpp_object_based_api). All such attributes
are prefixed with the term "native_".
## JSON Parsing
@@ -359,6 +372,66 @@ When parsing JSON, it recognizes the following escape codes in strings:
It also generates these escape codes back again when generating JSON from a
binary representation.
## Guidelines
### Efficiency
FlatBuffers is all about efficiency, but to realize that efficiency you
require an efficient schema. There are usually multiple choices on
how to represent data that have vastly different size characteristics.
It is very common nowadays to represent any kind of data as dictionaries
(as in e.g. JSON), because of its flexibility and extensibility. While
it is possible to emulate this in FlatBuffers (as a vector
of tables with key and value(s)), this is a bad match for a strongly
typed system like FlatBuffers, leading to relatively large binaries.
FlatBuffer tables are more flexible than classes/structs in most systems,
since having a large number of fields only few of which are actually
used is still efficient. You should thus try to organize your data
as much as possible such that you can use tables where you might be
tempted to use a dictionary.
Similarly, strings as values should only be used when they are
truely open-ended. If you can, always use an enum instead.
FlatBuffers doesn't have inheritance, so the way to represent a set
of related data structures is a union. Unions do have a cost however,
so an alternative to a union is to have a single table that has
all the fields of all the data structures you are trying to
represent, if they are relatively similar / share many fields.
Again, this is efficient because optional fields are cheap.
FlatBuffers supports the full range of integer sizes, so try to pick
the smallest size needed, rather than defaulting to int/long.
Remember that you can share data (refer to the same string/table
within a buffer), so factoring out repeating data into its own
data structure may be worth it.
### Style guide
Identifiers in a schema are meant to translate to many different programming
languages, so using the style of your "main" language is generally a bad idea.
For this reason, below is a suggested style guide to adhere to, to keep schemas
consistent for interoperation regardless of the target language.
Where possible, the code generators for specific languages will generate
identifiers that adhere to the language style, based on the schema identifiers.
- Table, struct, enum and rpc names (types): UpperCamelCase.
- Table and struct field names: snake_case. This is translated to lowerCamelCase
automatically for some languages, e.g. Java.
- Enum values: UpperCamelCase.
- namespaces: UpperCamelCase.
Formatting (this is less important, but still worth adhering to):
- Opening brace: on the same line as the start of the declaration.
- Spacing: Indent by 2 spaces. None around `:` for types, on both sides for `=`.
For an example, see the schema at the top of this file.
## Gotchas
### Schemas and version control

View File

@@ -399,55 +399,56 @@ The first step is to import/include the library, generated files, etc.
Now we are ready to start building some buffers. In order to start, we need
to create an instance of the `FlatBufferBuilder`, which will contain the buffer
as it grows:
as it grows. You can pass an initial size of the buffer (here 1024 bytes),
which will grow automatically if needed:
<div class="language-cpp">
~~~{.cpp}
// Create a `FlatBufferBuilder`, which will be used to create our
// monsters' FlatBuffers.
flatbuffers::FlatBufferBuilder builder;
flatbuffers::FlatBufferBuilder builder(1024);
~~~
</div>
<div class="language-java">
~~~{.java}
// Create a `FlatBufferBuilder`, which will be used to create our
// monsters' FlatBuffers.
FlatBufferBuilder builder = new FlatBufferBuilder(0);
FlatBufferBuilder builder = new FlatBufferBuilder(1024);
~~~
</div>
<div class="language-csharp">
~~~{.cs}
// Create a `FlatBufferBuilder`, which will be used to create our
// monsters' FlatBuffers.
var builder = new FlatBufferBuilder(1);
var builder = new FlatBufferBuilder(1024);
~~~
</div>
<div class="language-go">
~~~{.go}
// Create a `FlatBufferBuilder`, which will be used to create our
// monsters' FlatBuffers.
builder := flatbuffers.NewBuilder(0)
builder := flatbuffers.NewBuilder(1024)
~~~
</div>
<div class="language-python">
~~~{.py}
# Create a `FlatBufferBuilder`, which will be used to create our
# monsters' FlatBuffers.
builder = flatbuffers.Builder(0)
builder = flatbuffers.Builder(1024)
~~~
</div>
<div class="language-javascript">
~~~{.js}
// Create a `flatbuffer.Builder`, which will be used to create our
// monsters' FlatBuffers.
var builder = new flatbuffers.Builder(1);
var builder = new flatbuffers.Builder(1024);
~~~
</div>
<div class="language-php">
~~~{.php}
// Create a `FlatBufferBuilder`, which will be used to create our
// monsters' FlatBuffers.
$builder = new Google\FlatBuffers\FlatbufferBuilder(0);
$builder = new Google\FlatBuffers\FlatbufferBuilder(1024);
~~~
</div>
<div class="language-c">
@@ -798,58 +799,6 @@ elements by calling a lambda. For the common case of `std::vector<std::string>`
there's also `CreateVectorOfStrings`.
</div>
To create a `struct`, use the `Vec3` class/struct that was generated by
the schema compiler:
<div class="language-cpp">
~~~{.cpp}
// Create a `Vec3`, representing the Orc's position in 3-D space.
auto pos = Vec3(1.0f, 2.0f, 3.0f);
~~~
</div>
<div class="language-java">
~~~{.java}
// Create a `Vec3`, representing the Orc's position in 3-D space.
int pos = Vec3.createVec3(builder, 1.0f, 2.0f, 3.0f);
~~~
</div>
<div class="language-csharp">
~~~{.cs}
// Create a `Vec3`, representing the Orc's position in 3-D space.
var pos = Vec3.CreateVec3(builder, 1.0f, 2.0f, 3.0f);
~~~
</div>
<div class="language-go">
~~~{.go}
// Create a `Vec3`, representing the Orc's position in 3-D space.
pos := sample.CreateVec3(builder, 1.0, 2.0, 3.0)
~~~
</div>
<div class="language-python">
~~~{.py}
# Create a `Vec3`, representing the Orc's position in 3-D space.
pos = MyGame.Sample.Vec3.CreateVec3(builder, 1.0, 2.0, 3.0)
~~~
</div>
<div class="language-javascript">
~~~{.js}
// Create a `Vec3`, representing the Orc's position in 3-D space.
var pos = MyGame.Sample.Vec3.createVec3(builder, 1.0, 2.0, 3.0);
~~~
</div>
<div class="language-php">
~~~{.js}
// Create a `Vec3`, representing the Orc's position in 3-D space.
$pos = \MyGame\Sample\Vec3::CreateVec3($builder, 1.0, 2.0, 3.0);
~~~
</div>
<div class="language-c">
~~~{.c}
// Create a `Vec3`, representing the Orc's position in 3-D space.
ns(Vec3_t) pos = { 1.0f, 2.0f, 3.0f };
~~~
</div>
We have now serialized the non-scalar components of the orc, so we
can serialize the monster itself:
@@ -861,15 +810,16 @@ can serialize the monster itself:
// Finally, create the monster using the `CreateMonster` helper function
// to set all fields.
auto orc = CreateMonster(builder, &pos, mana, hp, name, inventory, Color_Red,
weapons, Equipment_Weapon, axe.Union());
auto orc = CreateMonster(builder, Vec3(1.0f, 2.0f, 3.0f), mana, hp, name,
inventory, Color_Red, weapons, Equipment_Weapon,
axe.Union());
~~~
</div>
<div class="language-java">
~~~{.java}
// Create our monster using `startMonster()` and `endMonster()`.
Monster.startMonster(builder);
Monster.addPos(builder, pos);
Monster.addPos(builder, Vec3.createVec3(builder, 1.0f, 2.0f, 3.0f));
Monster.addName(builder, name);
Monster.addColor(builder, Color.Red);
Monster.addHp(builder, (short)300);
@@ -884,7 +834,7 @@ can serialize the monster itself:
~~~{.cs}
// Create our monster using `StartMonster()` and `EndMonster()`.
Monster.StartMonster(builder);
Monster.AddPos(builder, pos);
Monster.AddPos(builder, Vec3.CreateVec3(builder, 1.0f, 2.0f, 3.0f));
Monster.AddHp(builder, (short)300);
Monster.AddName(builder, name);
Monster.AddInventory(builder, inv);
@@ -899,7 +849,7 @@ can serialize the monster itself:
~~~{.go}
// Create our monster using `MonsterStart()` and `MonsterEnd()`.
sample.MonsterStart(builder)
sample.MonsterAddPos(builder, pos)
sample.MonsterAddPos(builder, sample.CreateVec3(builder, 1.0, 2.0, 3.0))
sample.MonsterAddHp(builder, 300)
sample.MonsterAddName(builder, name)
sample.MonsterAddInventory(builder, inv)
@@ -914,7 +864,8 @@ can serialize the monster itself:
~~~{.py}
# Create our monster by using `MonsterStart()` and `MonsterEnd()`.
MyGame.Sample.Monster.MonsterStart(builder)
MyGame.Sample.Monster.MonsterAddPos(builder, pos)
MyGame.Sample.Monster.MonsterAddPos(builder,
MyGame.Sample.Vec3.CreateVec3(builder, 1.0, 2.0, 3.0))
MyGame.Sample.Monster.MonsterAddHp(builder, 300)
MyGame.Sample.Monster.MonsterAddName(builder, name)
MyGame.Sample.Monster.MonsterAddInventory(builder, inv)
@@ -931,7 +882,8 @@ can serialize the monster itself:
~~~{.js}
// Create our monster by using `startMonster()` and `endMonster()`.
MyGame.Sample.Monster.startMonster(builder);
MyGame.Sample.Monster.addPos(builder, pos);
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);
@@ -946,7 +898,8 @@ can serialize the monster itself:
~~~{.php}
// Create our monster by using `StartMonster()` and `EndMonster()`.
\MyGame\Sample\Monster::StartMonster($builder);
\MyGame\Sample\Monster::AddPos($builder, $pos);
\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::AddName($builder, $name);
\MyGame\Sample\Monster::AddInventory($builder, $inv);
@@ -966,11 +919,21 @@ can serialize the monster itself:
// Define an equipment union. `create` calls in C has a single
// argument for unions where C++ has both a type and a data argument.
ns(Equipment_union_ref_t) equipped = ns(Equipment_as_Weapon(axe));
ns(Vec3_t) pos = { 1.0f, 2.0f, 3.0f };
ns(Monster_create_as_root(B, &pos, mana, hp, name, inventory, ns(Color_Red),
weapons, equipped));
~~~
</div>
Note how we create `Vec3` struct in-line in the table. Unlike tables, structs
are simple combinations of scalars that are always stored inline, just like
scalars themselves.
**Important**: you should not nest tables or any other objects, which is why
we created all the strings/vectors/tables that this monster refers to before
`start`. If you try to create any of them between `start` and `end`, you
will get an assert/exception/panic depending on your language.
*Note: Since we are passing `150` as the `mana` field, which happens to be the
default value, the field will not actually be written to the buffer, since the
default value will be returned on query anyway. This is a nice space savings,
@@ -1231,6 +1194,11 @@ like so:
~~~
</div>
Now you can write the bytes to a file, send them over the network..
**Make sure your file mode (or tranfer protocol) is set to BINARY, not text.**
If you transfer a FlatBuffer in text mode, the buffer will be corrupted,
which will lead to hard to find problems when you read the buffer.
#### Reading Orc FlatBuffers
Now that we have successfully created an `Orc` FlatBuffer, the monster data can
@@ -1326,92 +1294,82 @@ before:
~~~
</div>
Then, assuming you have a variable containing to the bytes of data from disk,
network, etc., you can create a monster from this data:
Then, assuming you have a buffer of bytes received from disk,
network, etc., you can create start accessing the buffer like so:
**Again, make sure you read the bytes in BINARY mode, otherwise the code below
won't work**
<div class="language-cpp">
~~~{.cpp}
// We can access the buffer we just made directly. Pretend this came over a
// network, was read off of disk, etc.
auto buffer_pointer = builder.GetBufferPointer();
uint8_t *buffer_pointer = /* the data you just read */;
// Deserialize the data from the buffer.
// Get a pointer to the root object inside the buffer.
auto monster = GetMonster(buffer_pointer);
// `monster` is of type`Monster *`, and points to somewhere inside the buffer.
// `monster` is of type `Monster *`.
// Note: root object pointers are NOT the same as `buffer_pointer`.
~~~
</div>
<div class="language-java">
~~~{.java}
// We can access the buffer we just made directly. Pretend this came over a
// network, was read off of disk, etc.
java.nio.ByteBuffer buf = builder.dataBuffer();
byte[] bytes = /* the data you just read */
java.nio.ByteBuffer buf = java.nio.ByteBuffer.wrap(bytes);
// Deserialize the data from the buffer.
// Get an accessor to the root object inside the buffer.
Monster monster = Monster.getRootAsMonster(buf);
~~~
</div>
<div class="language-csharp">
~~~{.cs}
// We can access the buffer we just made directly. Pretend this came over a
// network, was read off of disk, etc.
var buf = builder.DataBuffer;
byte[] bytes = /* the data you just read */
var buf = new ByteBuffer(bytes);
// Deserialize the data from the buffer.
// Get an accessor to the root object inside the buffer.
var monster = Monster.GetRootAsMonster(buf);
~~~
</div>
<div class="language-go">
~~~{.go}
// We can access the buffer we just made directly. Pretend this came over a
// network, was read off of disk, etc.
buf := builder.FinishedBytes()
var buf []byte = /* the data you just read */
// Deserialize the data from the buffer.
// Get an accessor to the root object inside the buffer.
monster := sample.GetRootAsMonster(buf, 0)
// Note: We use `0` for the offset here, since we got the data using the
// `builder.FinishedBytes()` method. This simulates the data you would
// store/receive in your FlatBuffer. If you wanted to read from the
// `builder.Bytes` directly, you would need to pass in the offset of
// `builder.Head()`, as the builder actually constructs the buffer backwards.
// Note: We use `0` for the offset here, which is typical for most buffers
// you would read. If you wanted to read from `builder.Bytes` directly, you
// would need to pass in the offset of `builder.Head()`, as the builder
// constructs the buffer backwards, so may not start at offset 0.
~~~
</div>
<div class="language-python">
~~~{.py}
# We can access the buffer we just made directly. Pretend this came over a
# network, was read off of disk, etc.
buf = builder.Output()
buf = /* the data you just read, in an object of type "bytearray" */
# Deserialize the data from the buffer.
// Get an accessor to the root object inside the buffer.
monster = MyGame.Sample.Monster.Monster.GetRootAsMonster(buf, 0)
# Note: We use `0` for the offset here, since we got the data using the
# `builder.Output()` method. This simulates the data you would store/receive
# in your FlatBuffer. If you wanted to read from the `builder.Bytes` directly,
# Note: We use `0` for the offset here, which is typical for most buffers
# you would read. If you wanted to read from the `builder.Bytes` directly,
# you would need to pass in the offset of `builder.Head()`, as the builder
# actually constructs the buffer backwards.
# constructs the buffer backwards, so may not start at offset 0.
~~~
</div>
<div class="language-javascript">
~~~{.js}
// We can access the buffer we just made directly. Pretend this came over a
// network, was read off of disk, etc.
var buf = builder.dataBuffer();
var bytes = /* the data you just read, in an object of type "Uint8Array" */
var buf = new flatbuffers.ByteBuffer(bytes);
// Deserialize the data from the buffer.
// Get an accessor to the root object inside the buffer.
var monster = MyGame.Sample.Monster.getRootAsMonster(buf);
~~~
</div>
<div class="language-php">
~~~{.php}
// We can access the buffer we just made directly. Pretend this came over a
// network, was read off of disk, etc.
$buf = $builder->dataBuffer();
$bytes = /* the data you just read, in a string */
$buf = Google\FlatBuffers\ByteBuffer::wrap($bytes);
// Deserialize the data from the buffer.
// Get an accessor to the root object inside the buffer.
$monster = \MyGame\Sample\Monster::GetRootAsMonster($buf);
~~~
</div>

View File

@@ -759,6 +759,7 @@ INPUT = "FlatBuffers.md" \
"Support.md" \
"Benchmarks.md" \
"WhitePaper.md" \
"FlexBuffers.md" \
"Internals.md" \
"Grammar.md" \
"../../CONTRIBUTING.md" \

View File

@@ -37,6 +37,8 @@
title="Use in PHP"/>
<tab type="user" url="@ref flatbuffers_guide_use_python"
title="Use in Python"/>
<tab type="user" url="@ref flexbuffers"
title="Schema-less version"/>
</tab>
<tab type="user" url="@ref flatbuffers_support"
title="Platform / Language / Feature support"/>

23
go/grpc.go Normal file
View File

@@ -0,0 +1,23 @@
package flatbuffers
// Codec implements gRPC-go Codec which is used to encode and decode messages.
var Codec = "flatbuffers"
type FlatbuffersCodec struct{}
func (FlatbuffersCodec) Marshal(v interface{}) ([]byte, error) {
return v.(*Builder).FinishedBytes(), nil
}
func (FlatbuffersCodec) Unmarshal(data []byte, v interface{}) error {
v.(flatbuffersInit).Init(data, GetUOffsetT(data))
return nil
}
func (FlatbuffersCodec) String() string {
return Codec
}
type flatbuffersInit interface {
Init(data []byte, i UOffsetT)
}

13
go/lib.go Normal file
View File

@@ -0,0 +1,13 @@
package flatbuffers
// FlatBuffer is the interface that represents a flatbuffer.
type FlatBuffer interface {
Table() Table
Init(buf []byte, i UOffsetT)
}
// GetRootAs is a generic helper to initialize a FlatBuffer with the provided buffer bytes and its data offset.
func GetRootAs(buf []byte, offset UOffsetT, fb FlatBuffer) {
n := GetUOffsetT(buf[offset:])
fb.Init(buf, n+offset)
}

View File

@@ -1,47 +1,52 @@
package flatbuffers
import "unsafe"
import (
"unsafe"
)
var (
const (
// See http://golang.org/ref/spec#Numeric_types
// SizeUint8 is the byte size of a uint8.
SizeUint8 = int(unsafe.Sizeof(uint8(0)))
SizeUint8 = 1
// SizeUint16 is the byte size of a uint16.
SizeUint16 = int(unsafe.Sizeof(uint16(0)))
SizeUint16 = 2
// SizeUint32 is the byte size of a uint32.
SizeUint32 = int(unsafe.Sizeof(uint32(0)))
SizeUint32 = 4
// SizeUint64 is the byte size of a uint64.
SizeUint64 = int(unsafe.Sizeof(uint64(0)))
SizeUint64 = 8
// SizeInt8 is the byte size of a int8.
SizeInt8 = int(unsafe.Sizeof(int8(0)))
// SizeInt8 is the byte size of a int8.
SizeInt8 = 1
// SizeInt16 is the byte size of a int16.
SizeInt16 = int(unsafe.Sizeof(int16(0)))
SizeInt16 = 2
// SizeInt32 is the byte size of a int32.
SizeInt32 = int(unsafe.Sizeof(int32(0)))
SizeInt32 = 4
// SizeInt64 is the byte size of a int64.
SizeInt64 = int(unsafe.Sizeof(int64(0)))
SizeInt64 = 8
// SizeFloat32 is the byte size of a float32.
SizeFloat32 = int(unsafe.Sizeof(float32(0)))
SizeFloat32 = 4
// SizeFloat64 is the byte size of a float64.
SizeFloat64 = int(unsafe.Sizeof(float64(0)))
SizeFloat64 = 8
// SizeByte is the byte size of a byte.
// The `byte` type is aliased (by Go definition) to uint8.
SizeByte = SizeUint8
SizeByte = 1
// SizeBool is the byte size of a bool.
// The `bool` type is aliased (by flatbuffers convention) to uint8.
SizeBool = SizeUint8
SizeBool = 1
// SizeSOffsetT is the byte size of an SOffsetT.
SizeSOffsetT = int(unsafe.Sizeof(SOffsetT(0)))
// The `SOffsetT` type is aliased (by flatbuffers convention) to int32.
SizeSOffsetT = 4
// SizeUOffsetT is the byte size of an UOffsetT.
SizeUOffsetT = int(unsafe.Sizeof(UOffsetT(0)))
// The `UOffsetT` type is aliased (by flatbuffers convention) to uint32.
SizeUOffsetT = 4
// SizeVOffsetT is the byte size of an VOffsetT.
SizeVOffsetT = int(unsafe.Sizeof(VOffsetT(0)))
// The `VOffsetT` type is aliased (by flatbuffers convention) to uint16.
SizeVOffsetT = 2
)
// byteSliceToString converts a []byte to string without a heap allocation.

View File

@@ -10,7 +10,7 @@ type Table struct {
// Offset provides access into the Table's vtable.
//
// Deprecated fields are ignored by checking against the vtable's length.
// Fields which are deprecated are ignored by checking against the vtable's length.
func (t *Table) Offset(vtableOffset VOffsetT) VOffsetT {
vtable := UOffsetT(SOffsetT(t.Pos) - t.GetSOffsetT(t.Pos))
if vtableOffset < t.GetVOffsetT(vtable) {

View File

@@ -67,7 +67,8 @@ grpc::string FilenameIdentifier(const grpc::string &filename) {
template<class T, size_t N>
T *array_end(T (&array)[N]) { return array + N; }
void PrintIncludes(Printer *printer, const std::vector<grpc::string>& headers, const Parameters &params) {
void PrintIncludes(grpc_generator::Printer *printer,
const std::vector<grpc::string>& headers, const Parameters &params) {
std::map<grpc::string, grpc::string> vars;
vars["l"] = params.use_system_headers ? '<' : '"';
@@ -86,7 +87,7 @@ void PrintIncludes(Printer *printer, const std::vector<grpc::string>& headers, c
}
}
grpc::string GetHeaderPrologue(File *file, const Parameters & /*params*/) {
grpc::string GetHeaderPrologue(grpc_generator::File *file, const Parameters & /*params*/) {
grpc::string output;
{
// Scope the output stream so it closes and finalizes output to the string.
@@ -106,12 +107,13 @@ grpc::string GetHeaderPrologue(File *file, const Parameters & /*params*/) {
printer->Print(vars, "#define GRPC_$filename_identifier$__INCLUDED\n");
printer->Print(vars, "\n");
printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
printer->Print(vars, file->additional_headers().c_str());
printer->Print(vars, "\n");
}
return output;
}
grpc::string GetHeaderIncludes(File *file,
grpc::string GetHeaderIncludes(grpc_generator::File *file,
const Parameters &params) {
grpc::string output;
{
@@ -122,7 +124,6 @@ grpc::string GetHeaderIncludes(File *file,
static const char *headers_strs[] = {
"grpc++/impl/codegen/async_stream.h",
"grpc++/impl/codegen/async_unary_call.h",
"grpc++/impl/codegen/proto_utils.h",
"grpc++/impl/codegen/rpc_method.h",
"grpc++/impl/codegen/service_type.h",
"grpc++/impl/codegen/status.h",
@@ -154,7 +155,7 @@ grpc::string GetHeaderIncludes(File *file,
}
void PrintHeaderClientMethodInterfaces(
Printer *printer, const Method *method,
grpc_generator::Printer *printer, const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars, bool is_public) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
@@ -303,8 +304,8 @@ void PrintHeaderClientMethodInterfaces(
}
}
void PrintHeaderClientMethod(Printer *printer,
const Method *method,
void PrintHeaderClientMethod(grpc_generator::Printer *printer,
const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars,
bool is_public) {
(*vars)["Method"] = method->name();
@@ -445,13 +446,13 @@ void PrintHeaderClientMethod(Printer *printer,
}
}
void PrintHeaderClientMethodData(Printer *printer, const Method *method,
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");
}
void PrintHeaderServerMethodSync(Printer *printer, const Method *method,
void PrintHeaderServerMethodSync(grpc_generator::Printer *printer, const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
@@ -483,8 +484,8 @@ void PrintHeaderServerMethodSync(Printer *printer, const Method *method,
}
void PrintHeaderServerMethodAsync(
Printer *printer,
const Method *method,
grpc_generator::Printer *printer,
const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
@@ -599,8 +600,8 @@ void PrintHeaderServerMethodAsync(
}
void PrintHeaderServerMethodGeneric(
Printer *printer,
const Method *method,
grpc_generator::Printer *printer,
const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
@@ -669,8 +670,8 @@ void PrintHeaderServerMethodGeneric(
printer->Print(*vars, "};\n");
}
void PrintHeaderService(Printer *printer,
const Service *service,
void PrintHeaderService(grpc_generator::Printer *printer,
const grpc_generator::Service *service,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Service"] = service->name();
@@ -764,7 +765,7 @@ void PrintHeaderService(Printer *printer,
printer->Print("};\n");
}
grpc::string GetHeaderServices(File *file,
grpc::string GetHeaderServices(grpc_generator::File *file,
const Parameters &params) {
grpc::string output;
{
@@ -795,7 +796,7 @@ grpc::string GetHeaderServices(File *file,
return output;
}
grpc::string GetHeaderEpilogue(File *file, const Parameters & /*params*/) {
grpc::string GetHeaderEpilogue(grpc_generator::File *file, const Parameters & /*params*/) {
grpc::string output;
{
// Scope the output stream so it closes and finalizes output to the string.
@@ -821,7 +822,7 @@ grpc::string GetHeaderEpilogue(File *file, const Parameters & /*params*/) {
return output;
}
grpc::string GetSourcePrologue(File *file, const Parameters & /*params*/) {
grpc::string GetSourcePrologue(grpc_generator::File *file, const Parameters & /*params*/) {
grpc::string output;
{
// Scope the output stream so it closes and finalizes output to the string.
@@ -839,13 +840,12 @@ grpc::string GetSourcePrologue(File *file, const Parameters & /*params*/) {
printer->Print(vars, "// source: $filename$\n\n");
printer->Print(vars, "#include \"$filename_base$$message_header_ext$\"\n");
printer->Print(vars, "#include \"$filename_base$$service_header_ext$\"\n");
printer->Print(vars, file->additional_headers().c_str());
printer->Print(vars, "\n");
printer->Print("\n");
}
return output;
}
grpc::string GetSourceIncludes(File *file,
grpc::string GetSourceIncludes(grpc_generator::File *file,
const Parameters &params) {
grpc::string output;
{
@@ -867,6 +867,7 @@ grpc::string GetSourceIncludes(File *file,
PrintIncludes(printer.get(), headers, params);
if (!file->package().empty()) {
printer->Print("\n");
std::vector<grpc::string> parts = file->package_parts();
for (auto part = parts.begin(); part != parts.end(); part++) {
@@ -880,8 +881,8 @@ grpc::string GetSourceIncludes(File *file,
return output;
}
void PrintSourceClientMethod(Printer *printer,
const Method *method,
void PrintSourceClientMethod(grpc_generator::Printer *printer,
const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
@@ -981,8 +982,8 @@ void PrintSourceClientMethod(Printer *printer,
}
}
void PrintSourceServerMethod(Printer *printer,
const Method *method,
void PrintSourceServerMethod(grpc_generator::Printer *printer,
const grpc_generator::Method *method,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] = method->input_type_name();
@@ -1040,8 +1041,8 @@ void PrintSourceServerMethod(Printer *printer,
}
}
void PrintSourceService(Printer *printer,
const Service *service,
void PrintSourceService(grpc_generator::Printer *printer,
const grpc_generator::Service *service,
std::map<grpc::string, grpc::string> *vars) {
(*vars)["Service"] = service->name();
@@ -1153,7 +1154,7 @@ void PrintSourceService(Printer *printer,
}
}
grpc::string GetSourceServices(File *file,
grpc::string GetSourceServices(grpc_generator::File *file,
const Parameters &params) {
grpc::string output;
{
@@ -1182,7 +1183,7 @@ grpc::string GetSourceServices(File *file,
return output;
}
grpc::string GetSourceEpilogue(File *file, const Parameters & /*params*/) {
grpc::string GetSourceEpilogue(grpc_generator::File *file, const Parameters & /*params*/) {
grpc::string temp;
if (!file->package().empty()) {

View File

@@ -41,16 +41,7 @@
#include <memory>
#include <vector>
#ifndef GRPC_CUSTOM_STRING
#include <string>
#define GRPC_CUSTOM_STRING std::string
#endif
namespace grpc {
typedef GRPC_CUSTOM_STRING string;
} // namespace grpc
#include "src/compiler/schema_interface.h"
namespace grpc_cpp_generator {
@@ -64,83 +55,29 @@ struct Parameters {
grpc::string grpc_search_path;
};
// An abstract interface representing a method.
struct Method {
virtual ~Method() {}
virtual grpc::string name() const = 0;
virtual grpc::string input_type_name() const = 0;
virtual grpc::string output_type_name() const = 0;
virtual bool NoStreaming() const = 0;
virtual bool ClientOnlyStreaming() const = 0;
virtual bool ServerOnlyStreaming() const = 0;
virtual bool BidiStreaming() const = 0;
};
// An abstract interface representing a service.
struct Service {
virtual ~Service() {}
virtual grpc::string name() const = 0;
virtual int method_count() const = 0;
virtual std::unique_ptr<const Method> method(int i) const = 0;
};
struct Printer {
virtual ~Printer() {}
virtual void Print(const std::map<grpc::string, grpc::string> &vars,
const char *template_string) = 0;
virtual void Print(const char *string) = 0;
virtual void Indent() = 0;
virtual void Outdent() = 0;
};
// An interface that allows the source generated to be output using various
// libraries/idls/serializers.
struct File {
virtual ~File() {}
virtual grpc::string filename() const = 0;
virtual grpc::string filename_without_ext() const = 0;
virtual grpc::string message_header_ext() const = 0;
virtual grpc::string service_header_ext() const = 0;
virtual grpc::string package() const = 0;
virtual std::vector<grpc::string> package_parts() const = 0;
virtual grpc::string additional_headers() const = 0;
virtual int service_count() const = 0;
virtual std::unique_ptr<const Service> service(int i) const = 0;
virtual std::unique_ptr<Printer> CreatePrinter(grpc::string *str) const = 0;
};
// Return the prologue of the generated header file.
grpc::string GetHeaderPrologue(File *file, const Parameters &params);
grpc::string GetHeaderPrologue(grpc_generator::File *file, const Parameters &params);
// Return the includes needed for generated header file.
grpc::string GetHeaderIncludes(File *file, const Parameters &params);
grpc::string GetHeaderIncludes(grpc_generator::File *file, const Parameters &params);
// Return the includes needed for generated source file.
grpc::string GetSourceIncludes(File *file, const Parameters &params);
grpc::string GetSourceIncludes(grpc_generator::File *file, const Parameters &params);
// Return the epilogue of the generated header file.
grpc::string GetHeaderEpilogue(File *file, const Parameters &params);
grpc::string GetHeaderEpilogue(grpc_generator::File *file, const Parameters &params);
// Return the prologue of the generated source file.
grpc::string GetSourcePrologue(File *file, const Parameters &params);
grpc::string GetSourcePrologue(grpc_generator::File *file, const Parameters &params);
// Return the services for generated header file.
grpc::string GetHeaderServices(File *file, const Parameters &params);
grpc::string GetHeaderServices(grpc_generator::File *file, const Parameters &params);
// Return the services for generated source file.
grpc::string GetSourceServices(File *file, const Parameters &params);
grpc::string GetSourceServices(grpc_generator::File *file, const Parameters &params);
// Return the epilogue of the generated source file.
grpc::string GetSourceEpilogue(File *file, const Parameters &params);
grpc::string GetSourceEpilogue(grpc_generator::File *file, const Parameters &params);
} // namespace grpc_cpp_generator

View File

@@ -0,0 +1,437 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation AN/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <map>
#include <cctype>
#include <sstream>
#include "src/compiler/go_generator.h"
template <class T>
grpc::string as_string(T x) {
std::ostringstream out;
out << x;
return out.str();
}
namespace grpc_go_generator {
// Returns string with first letter to lowerCase
grpc::string unexportName(grpc::string s) {
if (s.empty())
return s;
s[0] = static_cast<char>(std::tolower(s[0]));
return s;
}
// Returns string with first letter to uppercase
grpc::string exportName(grpc::string s) {
if (s.empty())
return s;
s[0] = static_cast<char>(std::toupper(s[0]));
return s;
}
// Generates imports for the service
void GenerateImports(grpc_generator::File *file, grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> vars) {
vars["filename"] = file->filename();
printer->Print("//Generated by gRPC Go plugin\n");
printer->Print("//If you make any local changes, they will be lost\n");
printer->Print(vars, "//source: $filename$\n\n");
printer->Print(vars, "package $Package$\n\n");
if (file->additional_imports() != "") {
printer->Print(file->additional_imports().c_str());
printer->Print("\n\n");
}
printer->Print("import (\n");
printer->Indent();
printer->Print(vars, "$context$ \"golang.org/x/net/context\"\n");
printer->Print(vars, "$grpc$ \"google.golang.org/grpc\"\n");
printer->Outdent();
printer->Print(")\n\n");
}
// Generates Server method signature source
void GenerateServerMethodSignature(const grpc_generator::Method *method, grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> vars) {
vars["Method"] = exportName(method->name());
vars["Request"] = method->input_name();
vars["Response"] = (vars["CustomMethodIO"] == "") ? method->output_name() : vars["CustomMethodIO"];
if (method->NoStreaming()) {
printer->Print(vars, "$Method$($context$.Context, *$Request$) (*$Response$, error)");
} else if (method->ServerOnlyStreaming()) {
printer->Print(vars, "$Method$(*$Request$, $Service$_$Method$Server) error");
} else {
printer->Print(vars, "$Method$($Service$_$Method$Server) error");
}
}
void GenerateServerMethod(const grpc_generator::Method *method, grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> vars) {
vars["Method"] = exportName(method->name());
vars["Request"] = method->input_name();
vars["Response"] = (vars["CustomMethodIO"] == "") ? method->output_name() : vars["CustomMethodIO"];
vars["FullMethodName"] = "/" + vars["Package"] + "." + vars["Service"] + "/" + vars["Method"];
vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
if (method->NoStreaming()) {
printer->Print(vars, "func $Handler$(srv interface{}, ctx $context$.Context,\n\tdec func(interface{}) error, interceptor $grpc$.UnaryServerInterceptor) (interface{}, error) {\n");
printer->Indent();
printer->Print(vars, "in := new($Request$)\n");
printer->Print("if err := dec(in); err != nil { return nil, err }\n");
printer->Print(vars, "if interceptor == nil { return srv.($Service$Server).$Method$(ctx, in) }\n");
printer->Print(vars, "info := &$grpc$.UnaryServerInfo{\n");
printer->Indent();
printer->Print("Server: srv,\n");
printer->Print(vars, "FullMethod: \"$FullMethodName$\",\n");
printer->Outdent();
printer->Print("}\n\n");
printer->Print(vars, "handler := func(ctx $context$.Context, req interface{}) (interface{}, error) {\n");
printer->Indent();
printer->Print(vars, "return srv.($Service$Server).$Method$(ctx, req.(* $Request$))\n");
printer->Outdent();
printer->Print("}\n");
printer->Print("return interceptor(ctx, in, info, handler)\n");
printer->Outdent();
printer->Print("}\n\n");
return;
}
vars["StreamType"] = vars["ServiceUnexported"] + vars["Method"] + "Server";
printer->Print(vars, "func $Handler$(srv interface{}, stream $grpc$.ServerStream) error {\n");
printer->Indent();
if (method->ServerOnlyStreaming()) {
printer->Print(vars, "m := new($Request$)\n");
printer->Print(vars, "if err := stream.RecvMsg(m); err != nil { return err }\n");
printer->Print(vars, "return srv.($Service$Server).$Method$(m, &$StreamType${stream})\n");
} else {
printer->Print(vars, "return srv.($Service$Server).$Method$(&$StreamType${stream})\n");
}
printer->Outdent();
printer->Print("}\n\n");
bool genSend = method->BidiStreaming() || method->ServerOnlyStreaming();
bool genRecv = method->BidiStreaming() || method->ClientOnlyStreaming();
bool genSendAndClose = method->ClientOnlyStreaming();
printer->Print(vars, "type $Service$_$Method$Server interface { \n");
printer->Indent();
if (genSend) {
printer->Print(vars, "Send(* $Response$) error\n");
}
if (genRecv) {
printer->Print(vars, "Recv() (* $Request$, error)\n");
}
if (genSendAndClose) {
printer->Print(vars, "SendAndClose(* $Response$) error\n");
}
printer->Print(vars, "$grpc$.ServerStream\n");
printer->Outdent();
printer->Print("}\n\n");
printer->Print(vars, "type $StreamType$ struct {\n");
printer->Indent();
printer->Print(vars, "$grpc$.ServerStream\n");
printer->Outdent();
printer->Print("}\n\n");
if (genSend) {
printer->Print(vars, "func (x *$StreamType$) Send(m *$Response$) error {\n");
printer->Indent();
printer->Print("return x.ServerStream.SendMsg(m)\n");
printer->Outdent();
printer->Print("}\n\n");
}
if (genRecv) {
printer->Print(vars, "func (x *$StreamType$) Recv() (*$Request$, error) {\n");
printer->Indent();
printer->Print(vars, "m := new($Request$)\n");
printer->Print("if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err }\n");
printer->Print("return m, nil\n");
printer->Outdent();
printer->Print("}\n\n");
}
if (genSendAndClose) {
printer->Print(vars, "func (x *$StreamType$) SendAndClose(m *$Response$) error {\n");
printer->Indent();
printer->Print("return x.ServerStream.SendMsg(m)\n");
printer->Outdent();
printer->Print("}\n\n");
}
}
// Generates Client method signature source
void GenerateClientMethodSignature(const grpc_generator::Method *method, grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> vars) {
vars["Method"] = exportName(method->name());
vars["Request"] = ", in *" + ((vars["CustomMethodIO"] == "") ? method->input_name() : vars["CustomMethodIO"]);
if (method->ClientOnlyStreaming() || method->BidiStreaming()) {
vars["Request"] = "";
}
vars["Response"] = "* " + method->output_name();
if (method->ClientOnlyStreaming() || method->BidiStreaming() || method->ServerOnlyStreaming()) {
vars["Response"] = vars["Service"] + "_" + vars["Method"] + "Client" ;
}
printer->Print(vars, "$Method$(ctx $context$.Context$Request$, \n\topts... $grpc$.CallOption) ($Response$, error)");
}
// Generates Client method source
void GenerateClientMethod(const grpc_generator::Method *method, grpc_generator::Printer *printer,
std::map<grpc::string, grpc::string> vars) {
printer->Print(vars, "func (c *$ServiceUnexported$Client) ");
GenerateClientMethodSignature(method, printer, vars);
printer->Print(" {\n");
printer->Indent();
vars["Method"] = exportName(method->name());
vars["Request"] = (vars["CustomMethodIO"] == "") ? method->input_name() : vars["CustomMethodIO"];
vars["Response"] = method->output_name();
vars["FullMethodName"] = "/" + vars["Package"] + "." + vars["Service"] + "/" + vars["Method"];
if (method->NoStreaming()) {
printer->Print(vars, "out := new($Response$)\n");
printer->Print(vars, "err := $grpc$.Invoke(ctx, \"$FullMethodName$\", in, out, c.cc, opts...)\n");
printer->Print("if err != nil { return nil, err }\n");
printer->Print("return out, nil\n");
printer->Outdent();
printer->Print("}\n\n");
return;
}
vars["StreamType"] = vars["ServiceUnexported"] + vars["Method"] + "Client";
printer->Print(vars, "stream, err := $grpc$.NewClientStream(ctx, &$MethodDesc$, c.cc, \"$FullMethodName$\", opts...)\n");
printer->Print("if err != nil { return nil, err }\n");
printer->Print(vars, "x := &$StreamType${stream}\n");
if (method->ServerOnlyStreaming()) {
printer->Print("if err := x.ClientStream.SendMsg(in); err != nil { return nil, err }\n");
printer->Print("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }\n");
}
printer->Print("return x,nil\n");
printer->Outdent();
printer->Print("}\n\n");
bool genSend = method->BidiStreaming() || method->ClientOnlyStreaming();
bool genRecv = method->BidiStreaming() || method->ServerOnlyStreaming();
bool genCloseAndRecv = method->ClientOnlyStreaming();
//Stream interface
printer->Print(vars, "type $Service$_$Method$Client interface {\n");
printer->Indent();
if (genSend) {
printer->Print(vars, "Send(*$Request$) error\n");
}
if (genRecv) {
printer->Print(vars, "Recv() (*$Response$, error)\n");
}
if (genCloseAndRecv) {
printer->Print(vars, "CloseAndRecv() (*$Response$, error)\n");
}
printer->Print(vars, "$grpc$.ClientStream\n");
printer->Outdent();
printer->Print("}\n\n");
//Stream Client
printer->Print(vars, "type $StreamType$ struct{\n");
printer->Indent();
printer->Print(vars, "$grpc$.ClientStream\n");
printer->Outdent();
printer->Print("}\n\n");
if (genSend) {
printer->Print(vars, "func (x *$StreamType$) Send(m *$Request$) error {\n");
printer->Indent();
printer->Print("return x.ClientStream.SendMsg(m)\n");
printer->Outdent();
printer->Print("}\n\n");
}
if (genRecv) {
printer->Print(vars, "func (x *$StreamType$) Recv() (*$Response$, error) {\n");
printer->Indent();
printer->Print(vars, "m := new($Response$)\n");
printer->Print("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }\n");
printer->Print("return m, nil\n");
printer->Outdent();
printer->Print("}\n\n");
}
if (genCloseAndRecv) {
printer->Print(vars, "func (x *$StreamType$) CloseAndRecv() (*$Response$, error) {\n");
printer->Indent();
printer->Print("if err := x.ClientStream.CloseSend(); err != nil { return nil, err }\n");
printer->Print(vars, "m := new ($Response$)\n");
printer->Print("if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }\n");
printer->Print("return m, nil\n");
printer->Outdent();
printer->Print("}\n\n");
}
}
// Generates client API for the service
void GenerateService(const grpc_generator::Service *service, grpc_generator::Printer* printer,
std::map<grpc::string, grpc::string> vars) {
vars["Service"] = exportName(service->name());
// Client Interface
printer->Print(vars, "// Client API for $Service$ service\n");
printer->Print(vars, "type $Service$Client interface{\n");
printer->Indent();
for (int i = 0; i < service->method_count(); i++) {
GenerateClientMethodSignature(service->method(i).get(), printer, vars);
printer->Print("\n");
}
printer->Outdent();
printer->Print("}\n\n");
// Client structure
vars["ServiceUnexported"] = unexportName(vars["Service"]);
printer->Print(vars, "type $ServiceUnexported$Client struct {\n");
printer->Indent();
printer->Print(vars, "cc *$grpc$.ClientConn\n");
printer->Outdent();
printer->Print("}\n\n");
// NewClient
printer->Print(vars, "func New$Service$Client(cc *$grpc$.ClientConn) $Service$Client {\n");
printer->Indent();
printer->Print(vars, "return &$ServiceUnexported$Client{cc}");
printer->Outdent();
printer->Print("\n}\n\n");
int unary_methods = 0, streaming_methods = 0;
vars["ServiceDesc"] = "_" + vars["Service"] + "_serviceDesc";
for (int i = 0; i < service->method_count(); i++) {
auto method = service->method(i);
if (method->NoStreaming()) {
vars["MethodDesc"] = vars["ServiceDesc"] + ".Method[" + as_string(unary_methods) + "]";
unary_methods++;
} else {
vars["MethodDesc"] = vars["ServiceDesc"] + ".Streams[" + as_string(streaming_methods) + "]";
streaming_methods++;
}
GenerateClientMethod(method.get(), printer, vars);
}
//Server Interface
printer->Print(vars, "// Server API for $Service$ service\n");
printer->Print(vars, "type $Service$Server interface {\n");
printer->Indent();
for (int i = 0; i < service->method_count(); i++) {
GenerateServerMethodSignature(service->method(i).get(), printer, vars);
printer->Print("\n");
}
printer->Outdent();
printer->Print("}\n\n");
// Server registration.
printer->Print(vars, "func Register$Service$Server(s *$grpc$.Server, srv $Service$Server) {\n");
printer->Indent();
printer->Print(vars, "s.RegisterService(&$ServiceDesc$, srv)\n");
printer->Outdent();
printer->Print("}\n\n");
for (int i = 0; i < service->method_count(); i++) {
GenerateServerMethod(service->method(i).get(), printer, vars);
printer->Print("\n");
}
//Service Descriptor
printer->Print(vars, "var $ServiceDesc$ = $grpc$.ServiceDesc{\n");
printer->Indent();
printer->Print(vars, "ServiceName: \"$Package$.$Service$\",\n");
printer->Print(vars, "HandlerType: (*$Service$Server)(nil),\n");
printer->Print(vars, "Methods: []$grpc$.MethodDesc{\n");
printer->Indent();
for (int i = 0; i < service->method_count(); i++) {
auto method = service->method(i);
vars["Method"] = method->name();
vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
if (method->NoStreaming()) {
printer->Print("{\n");
printer->Indent();
printer->Print(vars, "MethodName: \"$Method$\",\n");
printer->Print(vars, "Handler: $Handler$, \n");
printer->Outdent();
printer->Print("},\n");
}
}
printer->Outdent();
printer->Print("},\n");
printer->Print(vars, "Streams: []$grpc$.StreamDesc{\n");
printer->Indent();
for (int i = 0; i < service->method_count(); i++) {
auto method = service->method(i);
vars["Method"] = method->name();
vars["Handler"] = "_" + vars["Service"] + "_" + vars["Method"] + "_Handler";
if (!method->NoStreaming()) {
printer->Print("{\n");
printer->Indent();
printer->Print(vars, "StreamName: \"$Method$\",\n");
printer->Print(vars, "Handler: $Handler$, \n");
if (method->ClientOnlyStreaming()) {
printer->Print("ClientStreams: true,\n");
} else if (method->ServerOnlyStreaming()) {
printer->Print("ServerStreams: true,\n");
} else {
printer->Print("ServerStreams: true,\n");
printer->Print("ClientStreams: true,\n");
}
printer->Outdent();
printer->Print("},\n");
}
}
printer->Outdent();
printer->Print("},\n");
printer->Outdent();
printer->Print("}\n\n");
}
// Returns source for the service
grpc::string GenerateServiceSource(grpc_generator::File *file,
const grpc_generator::Service *service,
grpc_go_generator::Parameters *parameters) {
grpc::string out;
auto p = file->CreatePrinter(&out);
auto printer = p.get();
std::map<grpc::string, grpc::string> vars;
vars["Package"] = parameters->package_name;
vars["grpc"] = "grpc";
vars["context"] = "context";
GenerateImports(file, printer, vars);
if (parameters->custom_method_io_type != "") {
vars["CustomMethodIO"] = parameters->custom_method_io_type;
}
GenerateService(service, printer, vars);
return out;
}
}// Namespace grpc_go_generator

View File

@@ -0,0 +1,61 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_INTERNAL_COMPILER_GO_GENERATOR_H
#define GRPC_INTERNAL_COMPILER_GO_GENERATOR_H
//go generator is used to generate GRPC code for serialization system, such as flatbuffers
#include <memory>
#include <vector>
#include "src/compiler/schema_interface.h"
namespace grpc_go_generator {
struct Parameters {
//Defines the custom parameter types for methods
//eg: flatbuffers uses flatbuffers.Builder as input for the client and output for the server
grpc::string custom_method_io_type;
//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_go_generator::Parameters *parameters);
}
#endif // GRPC_INTERNAL_COMPILER_GO_GENERATOR_H

View File

@@ -0,0 +1,112 @@
/*
*
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
#define GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H
#include <map>
#include <memory>
#include <vector>
#ifndef GRPC_CUSTOM_STRING
#include <string>
#define GRPC_CUSTOM_STRING std::string
#endif
namespace grpc {
typedef GRPC_CUSTOM_STRING string;
} // namespace grpc
namespace grpc_generator {
// An abstract interface representing a method.
struct Method {
virtual ~Method() {}
virtual grpc::string name() const = 0;
virtual grpc::string input_type_name() const = 0;
virtual grpc::string output_type_name() const = 0;
virtual grpc::string input_name() const = 0;
virtual grpc::string output_name() const = 0;
virtual bool NoStreaming() const = 0;
virtual bool ClientOnlyStreaming() const = 0;
virtual bool ServerOnlyStreaming() const = 0;
virtual bool BidiStreaming() const = 0;
};
// An abstract interface representing a service.
struct Service {
virtual ~Service() {}
virtual grpc::string name() const = 0;
virtual int method_count() const = 0;
virtual std::unique_ptr<const Method> method(int i) const = 0;
};
struct Printer {
virtual ~Printer() {}
virtual void Print(const std::map<grpc::string, grpc::string> &vars,
const char *template_string) = 0;
virtual void Print(const char *string) = 0;
virtual void Indent() = 0;
virtual void Outdent() = 0;
};
// An interface that allows the source generated to be output using various
// libraries/idls/serializers.
struct File {
virtual ~File() {}
virtual grpc::string filename() const = 0;
virtual grpc::string filename_without_ext() const = 0;
virtual grpc::string message_header_ext() const = 0;
virtual grpc::string service_header_ext() const = 0;
virtual grpc::string package() const = 0;
virtual std::vector<grpc::string> package_parts() const = 0;
virtual grpc::string additional_headers() const = 0;
virtual grpc::string additional_imports() const = 0;
virtual int service_count() const = 0;
virtual std::unique_ptr<const Service> service(int i) const = 0;
virtual std::unique_ptr<Printer> CreatePrinter(grpc::string *str) const = 0;
};
} // namespace grpc_generator
#endif // GRPC_INTERNAL_COMPILER_SCHEMA_INTERFACE_H

93
grpc/tests/go_test.go Normal file
View File

@@ -0,0 +1,93 @@
package testing
import (
"../../tests/MyGame/Example"
"net"
"testing"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
type server struct{}
// test used to send and receive in grpc methods
var test = "Flatbuffers"
var addr = "0.0.0.0:50051"
// gRPC server store method
func (s *server) Store(context context.Context, in *Example.Monster) (*flatbuffers.Builder, error) {
b := flatbuffers.NewBuilder(0)
i := b.CreateString(test)
Example.StatStart(b)
Example.StatAddId(b, i)
b.Finish(Example.StatEnd(b))
return b, nil
}
// gRPC server retrieve method
func (s *server) Retrieve(context context.Context, in *Example.Stat) (*flatbuffers.Builder, error) {
b := flatbuffers.NewBuilder(0)
i := b.CreateString(test)
Example.MonsterStart(b)
Example.MonsterAddName(b, i)
b.Finish(Example.MonsterEnd(b))
return b, nil
}
func StoreClient(c Example.MonsterStorageClient, t *testing.T) {
b := flatbuffers.NewBuilder(0)
i := b.CreateString(test)
Example.MonsterStart(b)
Example.MonsterAddName(b, i)
b.Finish(Example.MonsterEnd(b))
out, err := c.Store(context.Background(), b)
if err != nil {
t.Fatalf("Store client failed: %v", err)
}
if string(out.Id()) != test {
t.Errorf("StoreClient failed: expected=%s, got=%s\n", test, out.Id())
t.Fail()
}
}
func RetrieveClient(c Example.MonsterStorageClient, t *testing.T) {
b := flatbuffers.NewBuilder(0)
i := b.CreateString(test)
Example.StatStart(b)
Example.StatAddId(b, i)
b.Finish(Example.StatEnd(b))
out, err := c.Retrieve(context.Background(), b)
if err != nil {
t.Fatalf("Retrieve client failed: %v", err)
}
if string(out.Name()) != test {
t.Errorf("RetrieveClient failed: expected=%s, got=%s\n", test, out.Name())
t.Fail()
}
}
func TestGRPC(t *testing.T) {
lis, err := net.Listen("tcp", addr)
if err != nil {
t.Fatalf("Failed to listen: %v", err)
}
ser := grpc.NewServer(grpc.CustomCodec(flatbuffers.FlatbuffersCodec{}))
Example.RegisterMonsterStorageServer(ser, &server{})
go func() {
if err := ser.Serve(lis); err != nil {
t.Fatalf("Failed to serve: %v", err)
t.FailNow()
}
}()
conn, err := grpc.Dial(addr, grpc.WithInsecure(), grpc.WithCodec(flatbuffers.FlatbuffersCodec{}))
if err != nil {
t.Fatalf("Failed to connect: %v", err)
}
defer conn.Close()
client := Example.NewMonsterStorageClient(conn)
StoreClient(client, t)
RetrieveClient(client, t)
}

View File

@@ -44,7 +44,7 @@ class ServiceImpl final : public MyGame::Example::MonsterStorage::Service {
}
virtual ::grpc::Status Retrieve(::grpc::ServerContext *context,
const flatbuffers::BufferRef<Stat> *request,
flatbuffers::BufferRef<Monster> *response)
::grpc::ServerWriter< flatbuffers::BufferRef<Monster>>* writer)
override {
assert(false); // We're not actually using this RPC.
return grpc::Status::CANCELLED;

View File

@@ -17,25 +17,63 @@
#ifndef FLATBUFFERS_CODE_GENERATORS_H_
#define FLATBUFFERS_CODE_GENERATORS_H_
#include <map>
#include <sstream>
#include "flatbuffers/idl.h"
namespace flatbuffers {
// Utility class to assist in generating code through use of text templates.
//
// Example code:
// CodeWriter code;
// code.SetValue("NAME", "Foo");
// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
// code.SetValue("NAME", "Bar");
// code += "void {{NAME}}() { printf("%s", "{{NAME}}"); }";
// std::cout << code.ToString() << std::endl;
//
// Output:
// void Foo() { printf("%s", "Foo"); }
// void Bar() { printf("%s", "Bar"); }
class CodeWriter {
public:
CodeWriter() {}
// Clears the current "written" code.
void Clear() {
stream_.str("");
stream_.clear();
}
// 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) {
value_map_[key] = value;
}
// Appends the given text to the generated code as well as a newline
// character. Any text within {{ and }} delimeters is replaced by values
// previously stored in the CodeWriter by calling SetValue above. The newline
// will be suppressed if the text ends with the \\ character.
void operator+=(std::string text);
// Returns the current contents of the CodeWriter as a std::string.
std::string ToString() const { return stream_.str(); }
private:
std::map<std::string, std::string> value_map_;
std::stringstream stream_;
};
class BaseGenerator {
public:
virtual bool generate() = 0;
static const std::string NamespaceDir(const Parser &parser,
const std::string &path,
const Namespace &ns) {
EnsureDirExists(path.c_str());
if (parser.opts.one_file) return path;
std::string namespace_dir = path; // Either empty or ends in separator.
auto &namespaces = ns.components;
for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
namespace_dir += *it + kPathSeparator;
EnsureDirExists(namespace_dir.c_str());
}
return namespace_dir;
}
static std::string NamespaceDir(const Parser &parser,
const std::string &path,
const Namespace &ns);
protected:
BaseGenerator(const Parser &parser, const std::string &path,
@@ -46,71 +84,35 @@ class BaseGenerator {
path_(path),
file_name_(file_name),
qualifying_start_(qualifying_start),
qualifying_separator_(qualifying_separator){};
virtual ~BaseGenerator(){};
qualifying_separator_(qualifying_separator) {}
virtual ~BaseGenerator() {}
// No copy/assign.
BaseGenerator &operator=(const BaseGenerator &);
BaseGenerator(const BaseGenerator &);
const std::string NamespaceDir(const Namespace &ns) {
return BaseGenerator::NamespaceDir(parser_, path_, ns);
}
std::string NamespaceDir(const Namespace &ns) const;
const char *FlatBuffersGeneratedWarning() {
return "automatically generated by the FlatBuffers compiler,"
" do not modify\n\n";
}
static const char *FlatBuffersGeneratedWarning();
bool IsEverythingGenerated() {
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
if (!(*it)->generated) return false;
}
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
if (!(*it)->generated) return false;
}
return true;
}
bool IsEverythingGenerated() const;
std::string FullNamespace(const char *separator, const Namespace &ns) {
std::string namespace_name;
auto &namespaces = ns.components;
for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
if (namespace_name.length()) namespace_name += separator;
namespace_name += *it;
}
return namespace_name;
}
static std::string FullNamespace(const char *separator, const Namespace &ns);
const std::string LastNamespacePart(const Namespace &ns) {
auto &namespaces = ns.components;
if (namespaces.size())
return *(namespaces.end() - 1);
else
return std::string("");
}
static std::string LastNamespacePart(const Namespace &ns);
// tracks the current namespace for early exit in WrapInNameSpace
// c++, java and csharp returns a different namespace from
// the following default (no early exit, always fully qualify),
// which works for js and php
virtual const Namespace *CurrentNameSpace() { return nullptr; }
virtual const Namespace *CurrentNameSpace() const { return nullptr; }
// Ensure that a type is prefixed with its namespace whenever it is used
// outside of its namespace.
std::string WrapInNameSpace(const Namespace *ns, const std::string &name) {
if (CurrentNameSpace() == ns) return name;
std::string qualified_name = qualifying_start_;
for (auto it = ns->components.begin(); it != ns->components.end(); ++it)
qualified_name += *it + qualifying_separator_;
return qualified_name + name;
}
std::string WrapInNameSpace(const Namespace *ns,
const std::string &name) const;
std::string WrapInNameSpace(const Definition &def) {
return WrapInNameSpace(def.defined_namespace, def.name);
}
std::string WrapInNameSpace(const Definition &def) const;
const Parser &parser_;
const std::string &path_;
@@ -119,6 +121,17 @@ class BaseGenerator {
const std::string qualifying_separator_;
};
struct CommentConfig {
const char *first_line;
const char *content_line_prefix;
const char *last_line;
};
extern void GenComment(const std::vector<std::string> &dc,
std::string *code_ptr,
const CommentConfig *config,
const char *prefix = "");
} // namespace flatbuffers
#endif // FLATBUFFERS_CODE_GENERATORS_H_

View File

@@ -88,7 +88,7 @@
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
#define FLATBUFFERS_VERSION_MAJOR 1
#define FLATBUFFERS_VERSION_MINOR 0
#define FLATBUFFERS_VERSION_MINOR 6
#define FLATBUFFERS_VERSION_REVISION 0
#define FLATBUFFERS_STRING_EXPAND(X) #X
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
@@ -130,6 +130,9 @@ typedef uintmax_t largest_scalar_t;
// In 32bits, this evaluates to 2GB - 1
#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(soffset_t) * 8 - 1)) - 1)
// We support aligning the contents of buffers up to this size.
#define FLATBUFFERS_MAX_ALIGNMENT 16
#ifndef FLATBUFFERS_CPP98_STL
// Pointer to relinquished memory.
typedef std::unique_ptr<uint8_t, std::function<void(uint8_t * /* unused */)>>
@@ -249,13 +252,13 @@ template<typename T> struct IndirectHelper<const T *> {
// calling Get() for every element.
template<typename T, typename IT>
struct VectorIterator
: public std::iterator<std::input_iterator_tag, IT, uoffset_t> {
: public std::iterator<std::random_access_iterator_tag, IT, uoffset_t> {
typedef std::iterator<std::input_iterator_tag, IT, uoffset_t> super_type;
typedef std::iterator<std::random_access_iterator_tag, IT, uoffset_t> super_type;
public:
VectorIterator(const uint8_t *data, uoffset_t i) :
data_(data + IndirectHelper<T>::element_stride * i) {};
data_(data + IndirectHelper<T>::element_stride * i) {}
VectorIterator(const VectorIterator &other) : data_(other.data_) {}
#ifndef FLATBUFFERS_CPP98_STL
VectorIterator(VectorIterator &&other) : data_(std::move(other.data_)) {}
@@ -271,15 +274,15 @@ public:
return *this;
}
bool operator==(const VectorIterator& other) const {
bool operator==(const VectorIterator &other) const {
return data_ == other.data_;
}
bool operator!=(const VectorIterator& other) const {
bool operator!=(const VectorIterator &other) const {
return data_ != other.data_;
}
ptrdiff_t operator-(const VectorIterator& other) const {
ptrdiff_t operator-(const VectorIterator &other) const {
return (data_ - other.data_) / IndirectHelper<T>::element_stride;
}
@@ -297,11 +300,40 @@ public:
}
VectorIterator operator++(int) {
VectorIterator temp(data_,0);
VectorIterator temp(data_, 0);
data_ += IndirectHelper<T>::element_stride;
return temp;
}
VectorIterator operator+(const uoffset_t &offset) {
return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride, 0);
}
VectorIterator& operator+=(const uoffset_t &offset) {
data_ += offset * IndirectHelper<T>::element_stride;
return *this;
}
VectorIterator &operator--() {
data_ -= IndirectHelper<T>::element_stride;
return *this;
}
VectorIterator operator--(int) {
VectorIterator temp(data_, 0);
data_ -= IndirectHelper<T>::element_stride;
return temp;
}
VectorIterator operator-(const uoffset_t &offset) {
return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride, 0);
}
VectorIterator& operator-=(const uoffset_t &offset) {
data_ -= offset * IndirectHelper<T>::element_stride;
return *this;
}
private:
const uint8_t *data_;
};
@@ -464,12 +496,11 @@ class vector_downward {
public:
explicit vector_downward(size_t initial_size,
const simple_allocator &allocator)
: reserved_(initial_size),
: reserved_((initial_size + sizeof(largest_scalar_t) - 1) &
~(sizeof(largest_scalar_t) - 1)),
buf_(allocator.allocate(reserved_)),
cur_(buf_ + reserved_),
allocator_(allocator) {
assert((initial_size & (sizeof(largest_scalar_t) - 1)) == 0);
}
allocator_(allocator) {}
~vector_downward() {
if (buf_)
@@ -507,17 +538,7 @@ class vector_downward {
uint8_t *make_space(size_t len) {
if (len > static_cast<size_t>(cur_ - buf_)) {
auto old_size = size();
auto largest_align = AlignOf<largest_scalar_t>();
reserved_ += (std::max)(len, growth_policy(reserved_));
// Round up to avoid undefined behavior from unaligned loads and stores.
reserved_ = (reserved_ + (largest_align - 1)) & ~(largest_align - 1);
auto new_buf = allocator_.allocate(reserved_);
auto new_cur = new_buf + reserved_ - old_size;
memcpy(new_cur, cur_, old_size);
cur_ = new_cur;
allocator_.deallocate(buf_);
buf_ = new_buf;
reallocate(len);
}
cur_ -= len;
// Beyond this, signed offsets may not have enough range:
@@ -538,18 +559,30 @@ class vector_downward {
uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; }
// push() & fill() are most frequently called with small byte counts (<= 4),
// which is why we're using loops rather than calling memcpy/memset.
void push(const uint8_t *bytes, size_t num) {
auto dest = make_space(num);
for (size_t i = 0; i < num; i++) dest[i] = bytes[i];
memcpy(dest, bytes, num);
}
// Specialized version of push() that avoids memcpy call for small data.
template<typename T> void push_small(T little_endian_t) {
auto dest = make_space(sizeof(T));
*reinterpret_cast<T *>(dest) = little_endian_t;
}
// fill() is most frequently called with small byte counts (<= 4),
// which is why we're using loops rather than calling memset.
void fill(size_t zero_pad_bytes) {
auto dest = make_space(zero_pad_bytes);
for (size_t i = 0; i < zero_pad_bytes; i++) dest[i] = 0;
}
// Version for when we know the size is larger.
void fill_big(size_t zero_pad_bytes) {
auto dest = make_space(zero_pad_bytes);
memset(dest, 0, zero_pad_bytes);
}
void pop(size_t bytes_to_remove) { cur_ += bytes_to_remove; }
private:
@@ -561,6 +594,20 @@ class vector_downward {
uint8_t *buf_;
uint8_t *cur_; // Points at location between empty (below) and used (above).
const simple_allocator &allocator_;
void reallocate(size_t len) {
auto old_size = size();
auto largest_align = AlignOf<largest_scalar_t>();
reserved_ += (std::max)(len, growth_policy(reserved_));
// Round up to avoid undefined behavior from unaligned loads and stores.
reserved_ = (reserved_ + (largest_align - 1)) & ~(largest_align - 1);
auto new_buf = allocator_.allocate(reserved_);
auto new_cur = new_buf + reserved_ - old_size;
memcpy(new_cur, cur_, old_size);
cur_ = new_cur;
allocator_.deallocate(buf_);
buf_ = new_buf;
}
};
// Converts a Field ID to a virtual table offset.
@@ -580,6 +627,10 @@ inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
template <typename T> const T* data(const std::vector<T> &v) {
return v.empty() ? nullptr : &v.front();
}
template <typename T> T* data(std::vector<T> &v) {
return v.empty() ? nullptr : &v.front();
}
/// @endcond
/// @addtogroup flatbuffers_cpp_api
@@ -607,7 +658,7 @@ FLATBUFFERS_FINAL_CLASS
const simple_allocator *allocator = nullptr)
: buf_(initial_size, allocator ? *allocator : default_allocator),
nested(false), finished(false), minalign_(1), force_defaults_(false),
string_pool(nullptr) {
dedup_vtables_(true), string_pool(nullptr) {
offsetbuf_.reserve(16); // Avoid first few reallocs.
vtables_.reserve(16);
EndianCheck();
@@ -658,6 +709,16 @@ FLATBUFFERS_FINAL_CLASS
}
#endif
/// @brief get the minimum alignment this buffer needs to be accessed
/// properly. This is only known once all elements have been written (after
/// you call Finish()). You can use this information if you need to embed
/// a FlatBuffer in some other buffer, such that you can later read it
/// without first having to copy it into its own buffer.
size_t GetBufferMinAlignment() {
Finished();
return minalign_;
}
/// @cond FLATBUFFERS_INTERNAL
void Finished() const {
// If you get this assert, you're attempting to get access a buffer
@@ -674,6 +735,10 @@ FLATBUFFERS_FINAL_CLASS
/// @param[in] bool fd When set to `true`, always serializes default values.
void ForceDefaults(bool fd) { force_defaults_ = fd; }
/// @brief By default vtables are deduped in order to save space.
/// @param[in] bool dedup When set to `true`, dedup vtables.
void DedupVtables(bool dedup) { dedup_vtables_ = dedup; }
/// @cond FLATBUFFERS_INTERNAL
void Pad(size_t num_bytes) { buf_.fill(num_bytes); }
@@ -708,7 +773,7 @@ FLATBUFFERS_FINAL_CLASS
AssertScalarT<T>();
T litle_endian_element = EndianScalar(element);
Align(sizeof(T));
PushBytes(reinterpret_cast<uint8_t *>(&litle_endian_element), sizeof(T));
buf_.push_small(litle_endian_element);
return GetSize();
}
@@ -740,7 +805,7 @@ FLATBUFFERS_FINAL_CLASS
template<typename T> void AddStruct(voffset_t field, const T *structptr) {
if (!structptr) return; // Default, don't store.
Align(AlignOf<T>());
PushBytes(reinterpret_cast<const uint8_t *>(structptr), sizeof(T));
buf_.push_small(*structptr);
TrackField(field, GetSize());
}
@@ -791,7 +856,7 @@ FLATBUFFERS_FINAL_CLASS
// Write a vtable, which consists entirely of voffset_t elements.
// It starts with the number of offsets, followed by a type id, followed
// by the offsets themselves. In reverse:
buf_.fill(numfields * sizeof(voffset_t));
buf_.fill_big(numfields * sizeof(voffset_t));
auto table_object_size = vtableoffsetloc - start;
assert(table_object_size < 0x10000); // Vtable use 16bit offsets.
PushElement<voffset_t>(static_cast<voffset_t>(table_object_size));
@@ -811,13 +876,15 @@ FLATBUFFERS_FINAL_CLASS
auto vt_use = GetSize();
// See if we already have generated a vtable with this exact same
// layout before. If so, make it point to the old one, remove this one.
for (auto it = vtables_.begin(); it != vtables_.end(); ++it) {
auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*it));
auto vt2_size = *vt2;
if (vt1_size != vt2_size || memcmp(vt2, vt1, vt1_size)) continue;
vt_use = *it;
buf_.pop(GetSize() - vtableoffsetloc);
break;
if (dedup_vtables_) {
for (auto it = vtables_.begin(); it != vtables_.end(); ++it) {
auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*it));
auto vt2_size = *vt2;
if (vt1_size != vt2_size || memcmp(vt2, vt1, vt1_size)) continue;
vt_use = *it;
buf_.pop(GetSize() - vtableoffsetloc);
break;
}
}
// If this is a new vtable, remember it.
if (vt_use == GetSize()) {
@@ -1060,6 +1127,27 @@ FLATBUFFERS_FINAL_CLASS
return Offset<Vector<const T *>>(EndVector(len));
}
#ifndef FLATBUFFERS_CPP98_STL
/// @brief Serialize an array of structs into a FlatBuffer `vector`.
/// @tparam T The data type of the struct array elements.
/// @param[in] f A function that takes the current iteration 0..vector_size-1
/// and a pointer to the struct that must be filled.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
/// This is mostly useful when flatbuffers are generated with mutation
/// accessors.
template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
size_t vector_size, const std::function<void(size_t i, T *)> &filler) {
StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>());
T *structs = reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T)));
for (size_t i = 0; i < vector_size; i++) {
filler(i, structs);
structs++;
}
return Offset<Vector<const T *>>(EndVector(vector_size));
}
#endif
/// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`.
/// @tparam T The data type of the `std::vector` struct elements.
/// @param[in]] v A const reference to the `std::vector` of structs to
@@ -1110,7 +1198,7 @@ FLATBUFFERS_FINAL_CLASS
/// where the vector is stored.
template<typename T> Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
std::vector<Offset<T>> *v) {
return CreateVectorOfSortedTables(v->data(), v->size());
return CreateVectorOfSortedTables(data(*v), v->size());
}
/// @brief Specialized version of `CreateVector` for non-copying use cases.
@@ -1153,17 +1241,20 @@ FLATBUFFERS_FINAL_CLASS
/// will be prefixed with a standard FlatBuffers file header.
template<typename T> void Finish(Offset<T> root,
const char *file_identifier = nullptr) {
NotNested();
// This will cause the whole buffer to be aligned.
PreAlign(sizeof(uoffset_t) + (file_identifier ? kFileIdentifierLength : 0),
minalign_);
if (file_identifier) {
assert(strlen(file_identifier) == kFileIdentifierLength);
buf_.push(reinterpret_cast<const uint8_t *>(file_identifier),
kFileIdentifierLength);
}
PushElement(ReferTo(root.o)); // Location of root.
finished = true;
Finish(root.o, file_identifier, false);
}
/// @brief Finish a buffer with a 32 bit size field pre-fixed (size of the
/// buffer following the size field). These buffers are NOT compatible
/// with standard buffers created by Finish, i.e. you can't call GetRoot
/// on them, you have to use GetSizePrefixedRoot instead.
/// All >32 bit quantities in this buffer will be aligned when the whole
/// size pre-fixed buffer is aligned.
/// These kinds of buffers are useful for creating a stream of FlatBuffers.
template<typename T> void FinishSizePrefixed(Offset<T> root,
const char *file_identifier = nullptr) {
Finish(root.o, file_identifier, true);
}
private:
@@ -1171,6 +1262,25 @@ FLATBUFFERS_FINAL_CLASS
FlatBufferBuilder(const FlatBufferBuilder &);
FlatBufferBuilder &operator=(const FlatBufferBuilder &);
void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) {
NotNested();
// This will cause the whole buffer to be aligned.
PreAlign((size_prefix ? sizeof(uoffset_t) : 0) +
sizeof(uoffset_t) +
(file_identifier ? kFileIdentifierLength : 0),
minalign_);
if (file_identifier) {
assert(strlen(file_identifier) == kFileIdentifierLength);
PushBytes(reinterpret_cast<const uint8_t *>(file_identifier),
kFileIdentifierLength);
}
PushElement(ReferTo(root)); // Location of root.
if (size_prefix) {
PushElement(GetSize());
}
finished = true;
}
struct FieldLoc {
uoffset_t off;
voffset_t id;
@@ -1195,6 +1305,8 @@ FLATBUFFERS_FINAL_CLASS
bool force_defaults_; // Serialize values equal to their defaults anyway.
bool dedup_vtables_;
struct StringOffsetCompare {
StringOffsetCompare(const vector_downward &buf) : buf_(&buf) {}
bool operator() (const Offset<String> &a, const Offset<String> &b) const {
@@ -1224,7 +1336,11 @@ template<typename T> const T *GetRoot(const void *buf) {
return GetMutableRoot<T>(const_cast<void *>(buf));
}
/// Helpers to get a typed pointer to objects that are currently beeing built.
template<typename T> const T *GetSizePrefixedRoot(const void *buf) {
return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(uoffset_t));
}
/// Helpers to get a typed pointer to objects that are currently being built.
/// @warning Creating new objects will lead to reallocations and invalidates
/// the pointer!
template<typename T> T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb,
@@ -1252,7 +1368,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
: buf_(buf), end_(buf + buf_len), depth_(0), max_depth_(_max_depth),
num_tables_(0), max_tables_(_max_tables)
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
, upper_bound_(buf)
, upper_bound_(buf)
#endif
{}
@@ -1348,16 +1464,17 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
return true;
}
// Verify this whole buffer, starting with root type T.
template<typename T> bool VerifyBuffer(const char *identifier) {
if (identifier && (size_t(end_ - buf_) < 2 * sizeof(flatbuffers::uoffset_t) ||
!BufferHasIdentifier(buf_, identifier))) {
template<typename T> bool VerifyBufferFromStart(const char *identifier,
const uint8_t *start) {
if (identifier &&
(size_t(end_ - start) < 2 * sizeof(flatbuffers::uoffset_t) ||
!BufferHasIdentifier(start, identifier))) {
return false;
}
// Call T::Verify, which must be in the generated code for this type.
return Verify<uoffset_t>(buf_) &&
reinterpret_cast<const T *>(buf_ + ReadScalar<uoffset_t>(buf_))->
return Verify<uoffset_t>(start) &&
reinterpret_cast<const T *>(start + ReadScalar<uoffset_t>(start))->
Verify(*this)
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
&& GetComputedSize()
@@ -1365,6 +1482,17 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
;
}
// Verify this whole buffer, starting with root type T.
template<typename T> bool VerifyBuffer(const char *identifier) {
return VerifyBufferFromStart<T>(identifier, buf_);
}
template<typename T> bool VerifySizePrefixedBuffer(const char *identifier) {
return Verify<uoffset_t>(buf_) &&
ReadScalar<uoffset_t>(buf_) == end_ - buf_ - sizeof(uoffset_t) &&
VerifyBufferFromStart<T>(identifier, buf_ + sizeof(uoffset_t));
}
// Called at the start of a table to increase counters measuring data
// structure depth and amount, and possibly bails out with false if
// limits set by the constructor have been hit. Needs to be balanced
@@ -1398,9 +1526,9 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
size_t max_depth_;
size_t num_tables_;
size_t max_tables_;
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
mutable const uint8_t *upper_bound_;
#endif
#endif
};
// Convenient way to bundle a buffer and its length, to pass it around
@@ -1418,7 +1546,7 @@ template<typename T> struct BufferRef : BufferRefBase {
bool Verify() {
Verifier verifier(buf, len);
return verifier.VerifyBuffer<T>();
return verifier.VerifyBuffer<T>(nullptr);
}
uint8_t *buf;
@@ -1436,11 +1564,6 @@ class Struct FLATBUFFERS_FINAL_CLASS {
return ReadScalar<T>(&data_[o]);
}
template<typename T> T GetPointer(uoffset_t o) const {
auto p = &data_[o];
return reinterpret_cast<T>(p + ReadScalar<uoffset_t>(p));
}
template<typename T> T GetStruct(uoffset_t o) const {
return reinterpret_cast<T>(&data_[o]);
}
@@ -1456,11 +1579,15 @@ class Struct FLATBUFFERS_FINAL_CLASS {
// omitted and added at will, but uses an extra indirection to read.
class Table {
public:
const uint8_t *GetVTable() const {
return data_ - ReadScalar<soffset_t>(data_);
}
// This gets the field offset for any of the functions below it, or 0
// if the field was not present.
voffset_t GetOptionalFieldOffset(voffset_t field) const {
// The vtable offset is always at the start.
auto vtable = data_ - ReadScalar<soffset_t>(data_);
auto vtable = GetVTable();
// The first element is the size of the vtable (fields + type id + itself).
auto vtsize = ReadScalar<voffset_t>(vtable);
// If the field we're accessing is outside the vtable, we're reading older
@@ -1513,8 +1640,6 @@ class Table {
return const_cast<Table *>(this)->GetAddressOf(field);
}
uint8_t *GetVTable() { return data_ - ReadScalar<soffset_t>(data_); }
bool CheckField(voffset_t field) const {
return GetOptionalFieldOffset(field) != 0;
}
@@ -1524,7 +1649,7 @@ class Table {
bool VerifyTableStart(Verifier &verifier) const {
// Check the vtable offset.
if (!verifier.Verify<soffset_t>(data_)) return false;
auto vtable = data_ - ReadScalar<soffset_t>(data_);
auto vtable = GetVTable();
// Check the vtable size field, then check vtable fits in its entirety.
return verifier.VerifyComplexity() &&
verifier.Verify<voffset_t>(vtable) &&
@@ -1559,12 +1684,68 @@ class Table {
uint8_t data_[1];
};
/// @brief This can compute the start of a FlatBuffer from a root pointer, i.e.
/// it is the opposite transformation of GetRoot().
/// This may be useful if you want to pass on a root and have the recipient
/// delete the buffer afterwards.
inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
auto table = reinterpret_cast<const Table *>(root);
auto vtable = table->GetVTable();
// Either the vtable is before the root or after the root.
auto start = std::min(vtable, reinterpret_cast<const uint8_t *>(root));
// Align to at least sizeof(uoffset_t).
start = reinterpret_cast<const uint8_t *>(
reinterpret_cast<uintptr_t>(start) & ~(sizeof(uoffset_t) - 1));
// Additionally, there may be a file_identifier in the buffer, and the root
// offset. The buffer may have been aligned to any size between
// sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align").
// Sadly, the exact alignment is only known when constructing the buffer,
// since it depends on the presence of values with said alignment properties.
// So instead, we simply look at the next uoffset_t values (root,
// file_identifier, and alignment padding) to see which points to the root.
// None of the other values can "impersonate" the root since they will either
// be 0 or four ASCII characters.
static_assert(FlatBufferBuilder::kFileIdentifierLength == sizeof(uoffset_t),
"file_identifier is assumed to be the same size as uoffset_t");
for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1;
possible_roots;
possible_roots--) {
start -= sizeof(uoffset_t);
if (ReadScalar<uoffset_t>(start) + start ==
reinterpret_cast<const uint8_t *>(root)) return start;
}
// We didn't find the root, either the "root" passed isn't really a root,
// or the buffer is corrupt.
// Assert, because calling this function with bad data may cause reads
// outside of buffer boundaries.
assert(false);
return nullptr;
}
// Base class for native objects (FlatBuffer data de-serialized into native
// C++ data structures).
// Contains no functionality, purely documentative.
struct NativeTable {
};
/// @brief Function types to be used with resolving hashes into objects and
/// back again. The resolver gets a pointer to a field inside an object API
/// object that is of the type specified in the schema using the attribute
/// `cpp_type` (it is thus important whatever you write to this address
/// matches that type). The value of this field is initially null, so you
/// may choose to implement a delayed binding lookup using this function
/// if you wish. The resolver does the opposite lookup, for when the object
/// is being serialized again.
typedef uint64_t hash_value_t;
#ifdef FLATBUFFERS_CPP98_STL
typedef void (*resolver_function_t)(void **pointer_adr, hash_value_t hash);
typedef hash_value_t (*rehasher_function_t)(void *pointer);
#else
typedef std::function<void (void **pointer_adr, hash_value_t hash)>
resolver_function_t;
typedef std::function<hash_value_t (void *pointer)> rehasher_function_t;
#endif
// Helper function to test if a field is present, using any of the field
// enums in the generated code.
// `table` must be a generated table type. Since this is a template parameter,

View File

@@ -0,0 +1,96 @@
/*
* 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.
*/
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include <functional>
#include <limits>
#include <string>
#ifndef FLATC_H_
#define FLATC_H_
namespace flatbuffers {
class FlatCompiler {
public:
// Output generator for the various programming languages and formats we
// support.
struct Generator {
typedef bool (*GenerateFn)(const flatbuffers::Parser &parser,
const std::string &path,
const std::string &file_name);
typedef std::string (*MakeRuleFn)(const flatbuffers::Parser &parser,
const std::string &path,
const std::string &file_name);
GenerateFn generate;
const char *generator_opt_short;
const char *generator_opt_long;
const char *lang_name;
GenerateFn generateGRPC;
flatbuffers::IDLOptions::Language lang;
const char *generator_help;
MakeRuleFn make_rule;
};
typedef void (*WarnFn)(const FlatCompiler *flatc,
const std::string &warn,
bool show_exe_name);
typedef void (*ErrorFn)(const FlatCompiler *flatc,
const std::string &err,
bool usage, bool show_exe_name);
// Parameters required to initialize the FlatCompiler.
struct InitParams {
InitParams()
: generators(nullptr),
num_generators(0),
warn_fn(nullptr),
error_fn(nullptr) {}
const Generator* generators;
size_t num_generators;
WarnFn warn_fn;
ErrorFn error_fn;
};
explicit FlatCompiler(const InitParams& params) : params_(params) {}
int Compile(int argc, const char** argv);
std::string GetUsageString(const char* program_name) const;
private:
void ParseFile(flatbuffers::Parser &parser,
const std::string &filename,
const std::string &contents,
std::vector<const char *> &include_directories) const;
void Warn(const std::string &warn, bool show_exe_name = true) const;
void Error(const std::string &err, bool usage = true,
bool show_exe_name = true) const;
InitParams params_;
};
} // namespace flatbuffers
#endif // FLATC_H_

File diff suppressed because it is too large Load Diff

View File

@@ -43,9 +43,7 @@ class SerializationTraits<T, typename std::enable_if<std::is_base_of<
// There is no de-serialization step in FlatBuffers, so we just receive
// the data from GRPC.
static grpc::Status Deserialize(grpc_byte_buffer *buffer,
T *msg,
int max_message_size) {
static grpc::Status Deserialize(grpc_byte_buffer *buffer, T *msg) {
// TODO(wvo): make this more efficient / zero copy when possible.
auto len = grpc_byte_buffer_length(buffer);
msg->buf = reinterpret_cast<uint8_t *>(malloc(len));

View File

@@ -102,6 +102,8 @@ inline bool IsInteger(BaseType t) { return t >= BASE_TYPE_UTYPE &&
t <= BASE_TYPE_ULONG; }
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; }
extern const char *const kTypeNames[];
extern const char kTypeSizes[];
@@ -234,6 +236,8 @@ struct FieldDef : public Definition {
// 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.
size_t padding; // Bytes to always pad after this field.
};
@@ -333,6 +337,7 @@ struct ServiceDef : public Definition {
struct IDLOptions {
bool strict_json;
bool skip_js_exports;
bool use_goog_js_export_format;
bool output_default_scalars_in_json;
int indent_step;
bool output_enum_identifiers;
@@ -347,17 +352,36 @@ struct IDLOptions {
bool generate_name_strings;
bool escape_proto_identifiers;
bool generate_object_based_api;
std::string cpp_object_api_pointer_type;
bool union_value_namespacing;
bool allow_non_utf8;
std::string include_prefix;
bool binary_schema_comments;
// Possible options for the more general generator below.
enum Language { kJava, kCSharp, kGo, kMAX };
enum Language {
kJava = 1 << 0,
kCSharp = 1 << 1,
kGo = 1 << 2,
kCpp = 1 << 3,
kJs = 1 << 4,
kPython = 1 << 5,
kPhp = 1 << 6,
kJson = 1 << 7,
kBinary = 1 << 8,
kMAX
};
Language lang;
// 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),
@@ -370,9 +394,12 @@ struct IDLOptions {
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),
lang(IDLOptions::kJava) {}
binary_schema_comments(false),
lang(IDLOptions::kJava),
lang_to_generate(0) {}
};
// This encapsulates where the parser is in the current source file.
@@ -450,6 +477,11 @@ class Parser : public ParserState {
known_attributes_["csharp_partial"] = true;
known_attributes_["streaming"] = true;
known_attributes_["idempotent"] = true;
known_attributes_["cpp_type"] = true;
known_attributes_["cpp_ptr_type"] = true;
known_attributes_["native_inline"] = true;
known_attributes_["native_type"] = true;
known_attributes_["native_default"] = true;
}
~Parser() {
@@ -493,7 +525,7 @@ class Parser : public ParserState {
private:
FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg);
FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, int64_t *val);
FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val);
FLATBUFFERS_CHECKED_ERROR Next();
FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark();
bool Is(int t);
@@ -551,6 +583,7 @@ private:
BaseType baseType);
public:
SymbolTable<Type> types_;
SymbolTable<StructDef> structs_;
SymbolTable<EnumDef> enums_;
SymbolTable<ServiceDef> services_;
@@ -564,6 +597,7 @@ private:
std::map<std::string, bool> included_files_;
std::map<std::string, std::set<std::string>> files_included_per_file_;
std::vector<std::string> native_included_files_;
std::map<std::string, bool> known_attributes_;
@@ -583,20 +617,15 @@ private:
extern std::string MakeCamel(const std::string &in, bool first = true);
struct CommentConfig;
extern void GenComment(const std::vector<std::string> &dc,
std::string *code_ptr,
const CommentConfig *config,
const char *prefix = "");
// Generate text (JSON) from a given FlatBuffer, and a given Parser
// object that has been populated with the corresponding schema.
// If ident_step is 0, no indentation will be generated. Additionally,
// if it is less than 0, no linefeeds will be generated either.
// See idl_gen_text.cpp.
// strict_json adds "quotes" around field names if true.
extern void GenerateText(const Parser &parser,
// If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8
// byte arrays in String values), returns false.
extern bool GenerateText(const Parser &parser,
const void *flatbuffer,
std::string *text);
extern bool GenerateTextFile(const Parser &parser,
@@ -640,8 +669,8 @@ extern bool GenerateJava(const Parser &parser,
// Generate Php code from the definitions in the Parser object.
// See idl_gen_php.
extern bool GeneratePhp(const Parser &parser,
const std::string &path,
const std::string &file_name);
const std::string &path,
const std::string &file_name);
// Generate Python files from the definitions in the Parser object.
// See idl_gen_python.cpp.
@@ -699,11 +728,17 @@ extern std::string BinaryMakeRule(const Parser &parser,
const std::string &path,
const std::string &file_name);
// Generate GRPC interfaces.
// Generate GRPC Cpp interfaces.
// See idl_gen_grpc.cpp.
bool GenerateGRPC(const Parser &parser,
const std::string &path,
const std::string &file_name);
bool GenerateCppGRPC(const Parser &parser,
const std::string &path,
const std::string &file_name);
// Generate GRPC Go interfaces.
// See idl_gen_grpc.cpp.
bool GenerateGoGRPC(const Parser &parser,
const std::string &path,
const std::string &file_name);
} // namespace flatbuffers

View File

@@ -105,6 +105,22 @@ inline Table *GetFieldT(const Table &table,
return table.GetPointer<Table *>(field.offset());
}
// Get a field, if you know it's a struct.
inline const Struct *GetFieldStruct(const Table &table,
const reflection::Field &field) {
// TODO: This does NOT check if the field is a table or struct, but we'd need
// access to the schema to check the is_struct flag.
assert(field.type()->base_type() == reflection::Obj);
return table.GetStruct<const Struct *>(field.offset());
}
// Get a structure's field, if you know it's a struct.
inline const Struct *GetFieldStruct(const Struct &structure,
const reflection::Field &field) {
assert(field.type()->base_type() == reflection::Obj);
return structure.GetStruct<const Struct *>(field.offset());
}
// Raw helper functions used below: get any value in memory as a 64bit int, a
// double or a string.
// All scalars get static_cast to an int64_t, strings use strtoull, every other
@@ -428,6 +444,15 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
const Table &table,
bool use_string_pooling = false);
// Verifies the provided flatbuffer using reflection.
// 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);
} // namespace flatbuffers
#endif // FLATBUFFERS_REFLECTION_H_

View File

@@ -1,5 +1,6 @@
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_
#define FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_
@@ -38,15 +39,37 @@ enum BaseType {
String = 13,
Vector = 14,
Obj = 15,
Union = 16,
Union = 16
};
inline const char **EnumNamesBaseType() {
static const char *names[] = { "None", "UType", "Bool", "Byte", "UByte", "Short", "UShort", "Int", "UInt", "Long", "ULong", "Float", "Double", "String", "Vector", "Obj", "Union", nullptr };
static const char *names[] = {
"None",
"UType",
"Bool",
"Byte",
"UByte",
"Short",
"UShort",
"Int",
"UInt",
"Long",
"ULong",
"Float",
"Double",
"String",
"Vector",
"Obj",
"Union",
nullptr
};
return names;
}
inline const char *EnumNameBaseType(BaseType e) { return EnumNamesBaseType()[static_cast<int>(e)]; }
inline const char *EnumNameBaseType(BaseType e) {
const size_t index = static_cast<int>(e);
return EnumNamesBaseType()[index];
}
struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
enum {
@@ -54,9 +77,15 @@ struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_ELEMENT = 6,
VT_INDEX = 8
};
BaseType base_type() const { return static_cast<BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0)); }
BaseType element() const { return static_cast<BaseType>(GetField<int8_t>(VT_ELEMENT, 0)); }
int32_t index() const { return GetField<int32_t>(VT_INDEX, -1); }
BaseType base_type() const {
return static_cast<BaseType>(GetField<int8_t>(VT_BASE_TYPE, 0));
}
BaseType element() const {
return static_cast<BaseType>(GetField<int8_t>(VT_ELEMENT, 0));
}
int32_t index() const {
return GetField<int32_t>(VT_INDEX, -1);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<int8_t>(verifier, VT_BASE_TYPE) &&
@@ -69,18 +98,29 @@ struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
struct TypeBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_base_type(BaseType base_type) { fbb_.AddElement<int8_t>(Type::VT_BASE_TYPE, static_cast<int8_t>(base_type), 0); }
void add_element(BaseType element) { fbb_.AddElement<int8_t>(Type::VT_ELEMENT, static_cast<int8_t>(element), 0); }
void add_index(int32_t index) { fbb_.AddElement<int32_t>(Type::VT_INDEX, index, -1); }
TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
void add_base_type(BaseType base_type) {
fbb_.AddElement<int8_t>(Type::VT_BASE_TYPE, static_cast<int8_t>(base_type), 0);
}
void add_element(BaseType element) {
fbb_.AddElement<int8_t>(Type::VT_ELEMENT, static_cast<int8_t>(element), 0);
}
void add_index(int32_t index) {
fbb_.AddElement<int32_t>(Type::VT_INDEX, index, -1);
}
TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
TypeBuilder &operator=(const TypeBuilder &);
flatbuffers::Offset<Type> Finish() {
auto o = flatbuffers::Offset<Type>(fbb_.EndTable(start_, 3));
const auto end = fbb_.EndTable(start_, 3);
auto o = flatbuffers::Offset<Type>(end);
return o;
}
};
inline flatbuffers::Offset<Type> CreateType(flatbuffers::FlatBufferBuilder &_fbb,
inline flatbuffers::Offset<Type> CreateType(
flatbuffers::FlatBufferBuilder &_fbb,
BaseType base_type = None,
BaseType element = None,
int32_t index = -1) {
@@ -96,10 +136,18 @@ struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_KEY = 4,
VT_VALUE = 6
};
const flatbuffers::String *key() const { return GetPointer<const flatbuffers::String *>(VT_KEY); }
bool KeyCompareLessThan(const KeyValue *o) const { return *key() < *o->key(); }
int KeyCompareWithValue(const char *val) const { return strcmp(key()->c_str(), val); }
const flatbuffers::String *value() const { return GetPointer<const flatbuffers::String *>(VT_VALUE); }
const flatbuffers::String *key() const {
return GetPointer<const flatbuffers::String *>(VT_KEY);
}
bool KeyCompareLessThan(const KeyValue *o) const {
return *key() < *o->key();
}
int KeyCompareWithValue(const char *val) const {
return strcmp(key()->c_str(), val);
}
const flatbuffers::String *value() const {
return GetPointer<const flatbuffers::String *>(VT_VALUE);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_KEY) &&
@@ -113,18 +161,27 @@ struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
struct KeyValueBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_key(flatbuffers::Offset<flatbuffers::String> key) { fbb_.AddOffset(KeyValue::VT_KEY, key); }
void add_value(flatbuffers::Offset<flatbuffers::String> value) { fbb_.AddOffset(KeyValue::VT_VALUE, value); }
KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
void add_key(flatbuffers::Offset<flatbuffers::String> key) {
fbb_.AddOffset(KeyValue::VT_KEY, key);
}
void add_value(flatbuffers::Offset<flatbuffers::String> value) {
fbb_.AddOffset(KeyValue::VT_VALUE, value);
}
KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
KeyValueBuilder &operator=(const KeyValueBuilder &);
flatbuffers::Offset<KeyValue> Finish() {
auto o = flatbuffers::Offset<KeyValue>(fbb_.EndTable(start_, 2));
fbb_.Required(o, KeyValue::VT_KEY); // key
const auto end = fbb_.EndTable(start_, 2);
auto o = flatbuffers::Offset<KeyValue>(end);
fbb_.Required(o, KeyValue::VT_KEY);
return o;
}
};
inline flatbuffers::Offset<KeyValue> CreateKeyValue(flatbuffers::FlatBufferBuilder &_fbb,
inline flatbuffers::Offset<KeyValue> CreateKeyValue(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::String> key = 0,
flatbuffers::Offset<flatbuffers::String> value = 0) {
KeyValueBuilder builder_(_fbb);
@@ -133,10 +190,14 @@ inline flatbuffers::Offset<KeyValue> CreateKeyValue(flatbuffers::FlatBufferBuild
return builder_.Finish();
}
inline flatbuffers::Offset<KeyValue> CreateKeyValueDirect(flatbuffers::FlatBufferBuilder &_fbb,
inline flatbuffers::Offset<KeyValue> CreateKeyValueDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const char *key = nullptr,
const char *value = nullptr) {
return CreateKeyValue(_fbb, key ? _fbb.CreateString(key) : 0, value ? _fbb.CreateString(value) : 0);
return reflection::CreateKeyValue(
_fbb,
key ? _fbb.CreateString(key) : 0,
value ? _fbb.CreateString(value) : 0);
}
struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -145,11 +206,28 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_VALUE = 6,
VT_OBJECT = 8
};
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(VT_NAME); }
int64_t value() const { return GetField<int64_t>(VT_VALUE, 0); }
bool KeyCompareLessThan(const EnumVal *o) const { return value() < o->value(); }
int KeyCompareWithValue(int64_t val) const { return value() < val ? -1 : value() > val; }
const Object *object() const { return GetPointer<const Object *>(VT_OBJECT); }
const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(VT_NAME);
}
int64_t value() const {
return GetField<int64_t>(VT_VALUE, 0);
}
bool KeyCompareLessThan(const EnumVal *o) const {
return value() < o->value();
}
int KeyCompareWithValue(int64_t val) const {
const auto key = value();
if (key < val) {
return -1;
} else if (key > val) {
return 1;
} else {
return 0;
}
}
const Object *object() const {
return GetPointer<const Object *>(VT_OBJECT);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
@@ -164,19 +242,30 @@ struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
struct EnumValBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(EnumVal::VT_NAME, name); }
void add_value(int64_t value) { fbb_.AddElement<int64_t>(EnumVal::VT_VALUE, value, 0); }
void add_object(flatbuffers::Offset<Object> object) { fbb_.AddOffset(EnumVal::VT_OBJECT, object); }
EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
fbb_.AddOffset(EnumVal::VT_NAME, name);
}
void add_value(int64_t value) {
fbb_.AddElement<int64_t>(EnumVal::VT_VALUE, value, 0);
}
void add_object(flatbuffers::Offset<Object> object) {
fbb_.AddOffset(EnumVal::VT_OBJECT, object);
}
EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
EnumValBuilder &operator=(const EnumValBuilder &);
flatbuffers::Offset<EnumVal> Finish() {
auto o = flatbuffers::Offset<EnumVal>(fbb_.EndTable(start_, 3));
fbb_.Required(o, EnumVal::VT_NAME); // name
const auto end = fbb_.EndTable(start_, 3);
auto o = flatbuffers::Offset<EnumVal>(end);
fbb_.Required(o, EnumVal::VT_NAME);
return o;
}
};
inline flatbuffers::Offset<EnumVal> CreateEnumVal(flatbuffers::FlatBufferBuilder &_fbb,
inline flatbuffers::Offset<EnumVal> CreateEnumVal(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::String> name = 0,
int64_t value = 0,
flatbuffers::Offset<Object> object = 0) {
@@ -187,11 +276,16 @@ inline flatbuffers::Offset<EnumVal> CreateEnumVal(flatbuffers::FlatBufferBuilder
return builder_.Finish();
}
inline flatbuffers::Offset<EnumVal> CreateEnumValDirect(flatbuffers::FlatBufferBuilder &_fbb,
inline flatbuffers::Offset<EnumVal> CreateEnumValDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const char *name = nullptr,
int64_t value = 0,
flatbuffers::Offset<Object> object = 0) {
return CreateEnumVal(_fbb, name ? _fbb.CreateString(name) : 0, value, object);
return reflection::CreateEnumVal(
_fbb,
name ? _fbb.CreateString(name) : 0,
value,
object);
}
struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -200,15 +294,33 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_VALUES = 6,
VT_IS_UNION = 8,
VT_UNDERLYING_TYPE = 10,
VT_ATTRIBUTES = 12
VT_ATTRIBUTES = 12,
VT_DOCUMENTATION = 14
};
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(VT_NAME); }
bool KeyCompareLessThan(const Enum *o) const { return *name() < *o->name(); }
int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); }
const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *values() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *>(VT_VALUES); }
bool is_union() const { return GetField<uint8_t>(VT_IS_UNION, 0) != 0; }
const Type *underlying_type() const { return GetPointer<const Type *>(VT_UNDERLYING_TYPE); }
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES); }
const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(VT_NAME);
}
bool KeyCompareLessThan(const Enum *o) const {
return *name() < *o->name();
}
int KeyCompareWithValue(const char *val) const {
return strcmp(name()->c_str(), val);
}
const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *values() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<EnumVal>> *>(VT_VALUES);
}
bool is_union() const {
return GetField<uint8_t>(VT_IS_UNION, 0) != 0;
}
const Type *underlying_type() const {
return GetPointer<const Type *>(VT_UNDERLYING_TYPE);
}
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES);
}
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
@@ -222,6 +334,9 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyField<flatbuffers::uoffset_t>(verifier, VT_ATTRIBUTES) &&
verifier.Verify(attributes()) &&
verifier.VerifyVectorOfTables(attributes()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_DOCUMENTATION) &&
verifier.Verify(documentation()) &&
verifier.VerifyVectorOfStrings(documentation()) &&
verifier.EndTable();
}
};
@@ -229,29 +344,49 @@ struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
struct EnumBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(Enum::VT_NAME, name); }
void add_values(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<EnumVal>>> values) { fbb_.AddOffset(Enum::VT_VALUES, values); }
void add_is_union(bool is_union) { fbb_.AddElement<uint8_t>(Enum::VT_IS_UNION, static_cast<uint8_t>(is_union), 0); }
void add_underlying_type(flatbuffers::Offset<Type> underlying_type) { fbb_.AddOffset(Enum::VT_UNDERLYING_TYPE, underlying_type); }
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) { fbb_.AddOffset(Enum::VT_ATTRIBUTES, attributes); }
EnumBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
fbb_.AddOffset(Enum::VT_NAME, name);
}
void add_values(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<EnumVal>>> values) {
fbb_.AddOffset(Enum::VT_VALUES, values);
}
void add_is_union(bool is_union) {
fbb_.AddElement<uint8_t>(Enum::VT_IS_UNION, static_cast<uint8_t>(is_union), 0);
}
void add_underlying_type(flatbuffers::Offset<Type> underlying_type) {
fbb_.AddOffset(Enum::VT_UNDERLYING_TYPE, underlying_type);
}
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) {
fbb_.AddOffset(Enum::VT_ATTRIBUTES, attributes);
}
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
fbb_.AddOffset(Enum::VT_DOCUMENTATION, documentation);
}
EnumBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
EnumBuilder &operator=(const EnumBuilder &);
flatbuffers::Offset<Enum> Finish() {
auto o = flatbuffers::Offset<Enum>(fbb_.EndTable(start_, 5));
fbb_.Required(o, Enum::VT_NAME); // name
fbb_.Required(o, Enum::VT_VALUES); // values
fbb_.Required(o, Enum::VT_UNDERLYING_TYPE); // underlying_type
const auto end = fbb_.EndTable(start_, 6);
auto o = flatbuffers::Offset<Enum>(end);
fbb_.Required(o, Enum::VT_NAME);
fbb_.Required(o, Enum::VT_VALUES);
fbb_.Required(o, Enum::VT_UNDERLYING_TYPE);
return o;
}
};
inline flatbuffers::Offset<Enum> CreateEnum(flatbuffers::FlatBufferBuilder &_fbb,
inline flatbuffers::Offset<Enum> CreateEnum(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::String> name = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<EnumVal>>> values = 0,
bool is_union = false,
flatbuffers::Offset<Type> underlying_type = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0) {
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
EnumBuilder builder_(_fbb);
builder_.add_documentation(documentation);
builder_.add_attributes(attributes);
builder_.add_underlying_type(underlying_type);
builder_.add_values(values);
@@ -260,13 +395,22 @@ inline flatbuffers::Offset<Enum> CreateEnum(flatbuffers::FlatBufferBuilder &_fbb
return builder_.Finish();
}
inline flatbuffers::Offset<Enum> CreateEnumDirect(flatbuffers::FlatBufferBuilder &_fbb,
inline flatbuffers::Offset<Enum> CreateEnumDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const char *name = nullptr,
const std::vector<flatbuffers::Offset<EnumVal>> *values = nullptr,
bool is_union = false,
flatbuffers::Offset<Type> underlying_type = 0,
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr) {
return CreateEnum(_fbb, name ? _fbb.CreateString(name) : 0, values ? _fbb.CreateVector<flatbuffers::Offset<EnumVal>>(*values) : 0, is_union, underlying_type, attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0);
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
return reflection::CreateEnum(
_fbb,
name ? _fbb.CreateString(name) : 0,
values ? _fbb.CreateVector<flatbuffers::Offset<EnumVal>>(*values) : 0,
is_union,
underlying_type,
attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0,
documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0);
}
struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -280,20 +424,48 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_DEPRECATED = 16,
VT_REQUIRED = 18,
VT_KEY = 20,
VT_ATTRIBUTES = 22
VT_ATTRIBUTES = 22,
VT_DOCUMENTATION = 24
};
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(VT_NAME); }
bool KeyCompareLessThan(const Field *o) const { return *name() < *o->name(); }
int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); }
const Type *type() const { return GetPointer<const Type *>(VT_TYPE); }
uint16_t id() const { return GetField<uint16_t>(VT_ID, 0); }
uint16_t offset() const { return GetField<uint16_t>(VT_OFFSET, 0); }
int64_t default_integer() const { return GetField<int64_t>(VT_DEFAULT_INTEGER, 0); }
double default_real() const { return GetField<double>(VT_DEFAULT_REAL, 0.0); }
bool deprecated() const { return GetField<uint8_t>(VT_DEPRECATED, 0) != 0; }
bool required() const { return GetField<uint8_t>(VT_REQUIRED, 0) != 0; }
bool key() const { return GetField<uint8_t>(VT_KEY, 0) != 0; }
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES); }
const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(VT_NAME);
}
bool KeyCompareLessThan(const Field *o) const {
return *name() < *o->name();
}
int KeyCompareWithValue(const char *val) const {
return strcmp(name()->c_str(), val);
}
const Type *type() const {
return GetPointer<const Type *>(VT_TYPE);
}
uint16_t id() const {
return GetField<uint16_t>(VT_ID, 0);
}
uint16_t offset() const {
return GetField<uint16_t>(VT_OFFSET, 0);
}
int64_t default_integer() const {
return GetField<int64_t>(VT_DEFAULT_INTEGER, 0);
}
double default_real() const {
return GetField<double>(VT_DEFAULT_REAL, 0.0);
}
bool deprecated() const {
return GetField<uint8_t>(VT_DEPRECATED, 0) != 0;
}
bool required() const {
return GetField<uint8_t>(VT_REQUIRED, 0) != 0;
}
bool key() const {
return GetField<uint8_t>(VT_KEY, 0) != 0;
}
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES);
}
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
@@ -310,6 +482,9 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyField<flatbuffers::uoffset_t>(verifier, VT_ATTRIBUTES) &&
verifier.Verify(attributes()) &&
verifier.VerifyVectorOfTables(attributes()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_DOCUMENTATION) &&
verifier.Verify(documentation()) &&
verifier.VerifyVectorOfStrings(documentation()) &&
verifier.EndTable();
}
};
@@ -317,27 +492,55 @@ struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
struct FieldBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(Field::VT_NAME, name); }
void add_type(flatbuffers::Offset<Type> type) { fbb_.AddOffset(Field::VT_TYPE, type); }
void add_id(uint16_t id) { fbb_.AddElement<uint16_t>(Field::VT_ID, id, 0); }
void add_offset(uint16_t offset) { fbb_.AddElement<uint16_t>(Field::VT_OFFSET, offset, 0); }
void add_default_integer(int64_t default_integer) { fbb_.AddElement<int64_t>(Field::VT_DEFAULT_INTEGER, default_integer, 0); }
void add_default_real(double default_real) { fbb_.AddElement<double>(Field::VT_DEFAULT_REAL, default_real, 0.0); }
void add_deprecated(bool deprecated) { fbb_.AddElement<uint8_t>(Field::VT_DEPRECATED, static_cast<uint8_t>(deprecated), 0); }
void add_required(bool required) { fbb_.AddElement<uint8_t>(Field::VT_REQUIRED, static_cast<uint8_t>(required), 0); }
void add_key(bool key) { fbb_.AddElement<uint8_t>(Field::VT_KEY, static_cast<uint8_t>(key), 0); }
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) { fbb_.AddOffset(Field::VT_ATTRIBUTES, attributes); }
FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
fbb_.AddOffset(Field::VT_NAME, name);
}
void add_type(flatbuffers::Offset<Type> type) {
fbb_.AddOffset(Field::VT_TYPE, type);
}
void add_id(uint16_t id) {
fbb_.AddElement<uint16_t>(Field::VT_ID, id, 0);
}
void add_offset(uint16_t offset) {
fbb_.AddElement<uint16_t>(Field::VT_OFFSET, offset, 0);
}
void add_default_integer(int64_t default_integer) {
fbb_.AddElement<int64_t>(Field::VT_DEFAULT_INTEGER, default_integer, 0);
}
void add_default_real(double default_real) {
fbb_.AddElement<double>(Field::VT_DEFAULT_REAL, default_real, 0.0);
}
void add_deprecated(bool deprecated) {
fbb_.AddElement<uint8_t>(Field::VT_DEPRECATED, static_cast<uint8_t>(deprecated), 0);
}
void add_required(bool required) {
fbb_.AddElement<uint8_t>(Field::VT_REQUIRED, static_cast<uint8_t>(required), 0);
}
void add_key(bool key) {
fbb_.AddElement<uint8_t>(Field::VT_KEY, static_cast<uint8_t>(key), 0);
}
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) {
fbb_.AddOffset(Field::VT_ATTRIBUTES, attributes);
}
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
fbb_.AddOffset(Field::VT_DOCUMENTATION, documentation);
}
FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
FieldBuilder &operator=(const FieldBuilder &);
flatbuffers::Offset<Field> Finish() {
auto o = flatbuffers::Offset<Field>(fbb_.EndTable(start_, 10));
fbb_.Required(o, Field::VT_NAME); // name
fbb_.Required(o, Field::VT_TYPE); // type
const auto end = fbb_.EndTable(start_, 11);
auto o = flatbuffers::Offset<Field>(end);
fbb_.Required(o, Field::VT_NAME);
fbb_.Required(o, Field::VT_TYPE);
return o;
}
};
inline flatbuffers::Offset<Field> CreateField(flatbuffers::FlatBufferBuilder &_fbb,
inline flatbuffers::Offset<Field> CreateField(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::String> name = 0,
flatbuffers::Offset<Type> type = 0,
uint16_t id = 0,
@@ -347,10 +550,12 @@ inline flatbuffers::Offset<Field> CreateField(flatbuffers::FlatBufferBuilder &_f
bool deprecated = false,
bool required = false,
bool key = false,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0) {
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
FieldBuilder builder_(_fbb);
builder_.add_default_real(default_real);
builder_.add_default_integer(default_integer);
builder_.add_documentation(documentation);
builder_.add_attributes(attributes);
builder_.add_type(type);
builder_.add_name(name);
@@ -362,7 +567,8 @@ inline flatbuffers::Offset<Field> CreateField(flatbuffers::FlatBufferBuilder &_f
return builder_.Finish();
}
inline flatbuffers::Offset<Field> CreateFieldDirect(flatbuffers::FlatBufferBuilder &_fbb,
inline flatbuffers::Offset<Field> CreateFieldDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const char *name = nullptr,
flatbuffers::Offset<Type> type = 0,
uint16_t id = 0,
@@ -372,8 +578,21 @@ inline flatbuffers::Offset<Field> CreateFieldDirect(flatbuffers::FlatBufferBuild
bool deprecated = false,
bool required = false,
bool key = false,
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr) {
return CreateField(_fbb, name ? _fbb.CreateString(name) : 0, type, id, offset, default_integer, default_real, deprecated, required, key, attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0);
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
return reflection::CreateField(
_fbb,
name ? _fbb.CreateString(name) : 0,
type,
id,
offset,
default_integer,
default_real,
deprecated,
required,
key,
attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0,
documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0);
}
struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -383,16 +602,36 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_IS_STRUCT = 8,
VT_MINALIGN = 10,
VT_BYTESIZE = 12,
VT_ATTRIBUTES = 14
VT_ATTRIBUTES = 14,
VT_DOCUMENTATION = 16
};
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(VT_NAME); }
bool KeyCompareLessThan(const Object *o) const { return *name() < *o->name(); }
int KeyCompareWithValue(const char *val) const { return strcmp(name()->c_str(), val); }
const flatbuffers::Vector<flatbuffers::Offset<Field>> *fields() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Field>> *>(VT_FIELDS); }
bool is_struct() const { return GetField<uint8_t>(VT_IS_STRUCT, 0) != 0; }
int32_t minalign() const { return GetField<int32_t>(VT_MINALIGN, 0); }
int32_t bytesize() const { return GetField<int32_t>(VT_BYTESIZE, 0); }
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES); }
const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(VT_NAME);
}
bool KeyCompareLessThan(const Object *o) const {
return *name() < *o->name();
}
int KeyCompareWithValue(const char *val) const {
return strcmp(name()->c_str(), val);
}
const flatbuffers::Vector<flatbuffers::Offset<Field>> *fields() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Field>> *>(VT_FIELDS);
}
bool is_struct() const {
return GetField<uint8_t>(VT_IS_STRUCT, 0) != 0;
}
int32_t minalign() const {
return GetField<int32_t>(VT_MINALIGN, 0);
}
int32_t bytesize() const {
return GetField<int32_t>(VT_BYTESIZE, 0);
}
const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *attributes() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<KeyValue>> *>(VT_ATTRIBUTES);
}
const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *documentation() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_DOCUMENTATION);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
@@ -406,6 +645,9 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyField<flatbuffers::uoffset_t>(verifier, VT_ATTRIBUTES) &&
verifier.Verify(attributes()) &&
verifier.VerifyVectorOfTables(attributes()) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_DOCUMENTATION) &&
verifier.Verify(documentation()) &&
verifier.VerifyVectorOfStrings(documentation()) &&
verifier.EndTable();
}
};
@@ -413,30 +655,52 @@ struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
struct ObjectBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(Object::VT_NAME, name); }
void add_fields(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> fields) { fbb_.AddOffset(Object::VT_FIELDS, fields); }
void add_is_struct(bool is_struct) { fbb_.AddElement<uint8_t>(Object::VT_IS_STRUCT, static_cast<uint8_t>(is_struct), 0); }
void add_minalign(int32_t minalign) { fbb_.AddElement<int32_t>(Object::VT_MINALIGN, minalign, 0); }
void add_bytesize(int32_t bytesize) { fbb_.AddElement<int32_t>(Object::VT_BYTESIZE, bytesize, 0); }
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) { fbb_.AddOffset(Object::VT_ATTRIBUTES, attributes); }
ObjectBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
fbb_.AddOffset(Object::VT_NAME, name);
}
void add_fields(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> fields) {
fbb_.AddOffset(Object::VT_FIELDS, fields);
}
void add_is_struct(bool is_struct) {
fbb_.AddElement<uint8_t>(Object::VT_IS_STRUCT, static_cast<uint8_t>(is_struct), 0);
}
void add_minalign(int32_t minalign) {
fbb_.AddElement<int32_t>(Object::VT_MINALIGN, minalign, 0);
}
void add_bytesize(int32_t bytesize) {
fbb_.AddElement<int32_t>(Object::VT_BYTESIZE, bytesize, 0);
}
void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) {
fbb_.AddOffset(Object::VT_ATTRIBUTES, attributes);
}
void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) {
fbb_.AddOffset(Object::VT_DOCUMENTATION, documentation);
}
ObjectBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
ObjectBuilder &operator=(const ObjectBuilder &);
flatbuffers::Offset<Object> Finish() {
auto o = flatbuffers::Offset<Object>(fbb_.EndTable(start_, 6));
fbb_.Required(o, Object::VT_NAME); // name
fbb_.Required(o, Object::VT_FIELDS); // fields
const auto end = fbb_.EndTable(start_, 7);
auto o = flatbuffers::Offset<Object>(end);
fbb_.Required(o, Object::VT_NAME);
fbb_.Required(o, Object::VT_FIELDS);
return o;
}
};
inline flatbuffers::Offset<Object> CreateObject(flatbuffers::FlatBufferBuilder &_fbb,
inline flatbuffers::Offset<Object> CreateObject(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::String> name = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Field>>> fields = 0,
bool is_struct = false,
int32_t minalign = 0,
int32_t bytesize = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0) {
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) {
ObjectBuilder builder_(_fbb);
builder_.add_documentation(documentation);
builder_.add_attributes(attributes);
builder_.add_bytesize(bytesize);
builder_.add_minalign(minalign);
@@ -446,14 +710,24 @@ inline flatbuffers::Offset<Object> CreateObject(flatbuffers::FlatBufferBuilder &
return builder_.Finish();
}
inline flatbuffers::Offset<Object> CreateObjectDirect(flatbuffers::FlatBufferBuilder &_fbb,
inline flatbuffers::Offset<Object> CreateObjectDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const char *name = nullptr,
const std::vector<flatbuffers::Offset<Field>> *fields = nullptr,
bool is_struct = false,
int32_t minalign = 0,
int32_t bytesize = 0,
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr) {
return CreateObject(_fbb, name ? _fbb.CreateString(name) : 0, fields ? _fbb.CreateVector<flatbuffers::Offset<Field>>(*fields) : 0, is_struct, minalign, bytesize, attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0);
const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr,
const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) {
return reflection::CreateObject(
_fbb,
name ? _fbb.CreateString(name) : 0,
fields ? _fbb.CreateVector<flatbuffers::Offset<Field>>(*fields) : 0,
is_struct,
minalign,
bytesize,
attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0,
documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0);
}
struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
@@ -464,11 +738,21 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_FILE_EXT = 10,
VT_ROOT_TABLE = 12
};
const flatbuffers::Vector<flatbuffers::Offset<Object>> *objects() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Object>> *>(VT_OBJECTS); }
const flatbuffers::Vector<flatbuffers::Offset<Enum>> *enums() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Enum>> *>(VT_ENUMS); }
const flatbuffers::String *file_ident() const { return GetPointer<const flatbuffers::String *>(VT_FILE_IDENT); }
const flatbuffers::String *file_ext() const { return GetPointer<const flatbuffers::String *>(VT_FILE_EXT); }
const Object *root_table() const { return GetPointer<const Object *>(VT_ROOT_TABLE); }
const flatbuffers::Vector<flatbuffers::Offset<Object>> *objects() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Object>> *>(VT_OBJECTS);
}
const flatbuffers::Vector<flatbuffers::Offset<Enum>> *enums() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Enum>> *>(VT_ENUMS);
}
const flatbuffers::String *file_ident() const {
return GetPointer<const flatbuffers::String *>(VT_FILE_IDENT);
}
const flatbuffers::String *file_ext() const {
return GetPointer<const flatbuffers::String *>(VT_FILE_EXT);
}
const Object *root_table() const {
return GetPointer<const Object *>(VT_ROOT_TABLE);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyFieldRequired<flatbuffers::uoffset_t>(verifier, VT_OBJECTS) &&
@@ -490,22 +774,37 @@ struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
struct SchemaBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_objects(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Object>>> objects) { fbb_.AddOffset(Schema::VT_OBJECTS, objects); }
void add_enums(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Enum>>> enums) { fbb_.AddOffset(Schema::VT_ENUMS, enums); }
void add_file_ident(flatbuffers::Offset<flatbuffers::String> file_ident) { fbb_.AddOffset(Schema::VT_FILE_IDENT, file_ident); }
void add_file_ext(flatbuffers::Offset<flatbuffers::String> file_ext) { fbb_.AddOffset(Schema::VT_FILE_EXT, file_ext); }
void add_root_table(flatbuffers::Offset<Object> root_table) { fbb_.AddOffset(Schema::VT_ROOT_TABLE, root_table); }
SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
void add_objects(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Object>>> objects) {
fbb_.AddOffset(Schema::VT_OBJECTS, objects);
}
void add_enums(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Enum>>> enums) {
fbb_.AddOffset(Schema::VT_ENUMS, enums);
}
void add_file_ident(flatbuffers::Offset<flatbuffers::String> file_ident) {
fbb_.AddOffset(Schema::VT_FILE_IDENT, file_ident);
}
void add_file_ext(flatbuffers::Offset<flatbuffers::String> file_ext) {
fbb_.AddOffset(Schema::VT_FILE_EXT, file_ext);
}
void add_root_table(flatbuffers::Offset<Object> root_table) {
fbb_.AddOffset(Schema::VT_ROOT_TABLE, root_table);
}
SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
SchemaBuilder &operator=(const SchemaBuilder &);
flatbuffers::Offset<Schema> Finish() {
auto o = flatbuffers::Offset<Schema>(fbb_.EndTable(start_, 5));
fbb_.Required(o, Schema::VT_OBJECTS); // objects
fbb_.Required(o, Schema::VT_ENUMS); // enums
const auto end = fbb_.EndTable(start_, 5);
auto o = flatbuffers::Offset<Schema>(end);
fbb_.Required(o, Schema::VT_OBJECTS);
fbb_.Required(o, Schema::VT_ENUMS);
return o;
}
};
inline flatbuffers::Offset<Schema> CreateSchema(flatbuffers::FlatBufferBuilder &_fbb,
inline flatbuffers::Offset<Schema> CreateSchema(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Object>>> objects = 0,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Enum>>> enums = 0,
flatbuffers::Offset<flatbuffers::String> file_ident = 0,
@@ -520,26 +819,49 @@ inline flatbuffers::Offset<Schema> CreateSchema(flatbuffers::FlatBufferBuilder &
return builder_.Finish();
}
inline flatbuffers::Offset<Schema> CreateSchemaDirect(flatbuffers::FlatBufferBuilder &_fbb,
inline flatbuffers::Offset<Schema> CreateSchemaDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const std::vector<flatbuffers::Offset<Object>> *objects = nullptr,
const std::vector<flatbuffers::Offset<Enum>> *enums = nullptr,
const char *file_ident = nullptr,
const char *file_ext = nullptr,
flatbuffers::Offset<Object> root_table = 0) {
return CreateSchema(_fbb, objects ? _fbb.CreateVector<flatbuffers::Offset<Object>>(*objects) : 0, enums ? _fbb.CreateVector<flatbuffers::Offset<Enum>>(*enums) : 0, file_ident ? _fbb.CreateString(file_ident) : 0, file_ext ? _fbb.CreateString(file_ext) : 0, root_table);
return reflection::CreateSchema(
_fbb,
objects ? _fbb.CreateVector<flatbuffers::Offset<Object>>(*objects) : 0,
enums ? _fbb.CreateVector<flatbuffers::Offset<Enum>>(*enums) : 0,
file_ident ? _fbb.CreateString(file_ident) : 0,
file_ext ? _fbb.CreateString(file_ext) : 0,
root_table);
}
inline const reflection::Schema *GetSchema(const void *buf) { return flatbuffers::GetRoot<reflection::Schema>(buf); }
inline const reflection::Schema *GetSchema(const void *buf) {
return flatbuffers::GetRoot<reflection::Schema>(buf);
}
inline const char *SchemaIdentifier() { return "BFBS"; }
inline const char *SchemaIdentifier() {
return "BFBS";
}
inline bool SchemaBufferHasIdentifier(const void *buf) { return flatbuffers::BufferHasIdentifier(buf, SchemaIdentifier()); }
inline bool SchemaBufferHasIdentifier(const void *buf) {
return flatbuffers::BufferHasIdentifier(
buf, SchemaIdentifier());
}
inline bool VerifySchemaBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<reflection::Schema>(SchemaIdentifier()); }
inline bool VerifySchemaBuffer(
flatbuffers::Verifier &verifier) {
return verifier.VerifyBuffer<reflection::Schema>(SchemaIdentifier());
}
inline const char *SchemaExtension() { return "bfbs"; }
inline const char *SchemaExtension() {
return "bfbs";
}
inline void FinishSchemaBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<reflection::Schema> root) { fbb.Finish(root, SchemaIdentifier()); }
inline void FinishSchemaBuffer(
flatbuffers::FlatBufferBuilder &fbb,
flatbuffers::Offset<reflection::Schema> root) {
fbb.Finish(root, SchemaIdentifier());
}
} // namespace reflection

View File

@@ -95,20 +95,22 @@ inline std::string IntToStringHex(int i, int xdigits) {
}
// Portable implementation of strtoll().
inline int64_t StringToInt(const char *str, int base = 10) {
inline int64_t StringToInt(const char *str, char **endptr = nullptr,
int base = 10) {
#ifdef _MSC_VER
return _strtoi64(str, nullptr, base);
return _strtoi64(str, endptr, base);
#else
return strtoll(str, nullptr, base);
return strtoll(str, endptr, base);
#endif
}
// Portable implementation of strtoull().
inline int64_t StringToUInt(const char *str, int base = 10) {
inline uint64_t StringToUInt(const char *str, char **endptr = nullptr,
int base = 10) {
#ifdef _MSC_VER
return _strtoui64(str, nullptr, base);
return _strtoui64(str, endptr, base);
#else
return strtoull(str, nullptr, base);
return strtoull(str, endptr, base);
#endif
}

View File

@@ -367,6 +367,53 @@ public class FlatBufferBuilder {
}
/// @endcond
/**
* Create a new array/vector and return a ByteBuffer to be filled later.
* Call {@link #endVector} after this method to get an offset to the beginning
* of vector.
*
* @param elem_size the size of each element in bytes.
* @param num_elems number of elements in the vector.
* @param alignment byte alignment.
* @return ByteBuffer with position and limit set to the space allocated for the array.
*/
public ByteBuffer createUnintializedVector(int elem_size, int num_elems, int alignment) {
int length = elem_size * num_elems;
startVector(elem_size, num_elems, alignment);
bb.position(space -= length);
// Slice and limit the copy vector to point to the 'array'
ByteBuffer copy = bb.slice().order(ByteOrder.LITTLE_ENDIAN);
copy.limit(length);
return copy;
}
/**
* Create a vector of tables.
*
* @param offsets Offsets of the tables.
* @return Returns offset of the vector.
*/
public int createVectorOfTables(int[] offsets) {
notNested();
startVector(Constants.SIZEOF_INT, offsets.length, Constants.SIZEOF_INT);
for(int i = offsets.length - 1; i >= 0; i--) addOffset(offsets[i]);
return endVector();
}
/**
* Create a vector of sorted by the key tables.
*
* @param obj Instance of the table subclass.
* @param offsets Offsets of the tables.
* @return Returns offset of the sorted vector.
*/
public <T extends Table> int createSortedVectorOfTables(T obj, int[] offsets) {
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.
@@ -413,6 +460,20 @@ public class FlatBufferBuilder {
return endVector();
}
/**
* Create a byte array in the buffer.
*
* @param arr A source array with data
* @return The offset in the buffer where the encoded array starts.
*/
public int createByteVector(byte[] arr) {
int length = arr.length;
startVector(1, length, 1);
bb.position(space -= length);
bb.put(arr);
return endVector();
}
/// @cond FLATBUFFERS_INTERNAL
/**
* Should not be accessing the final buffer before it is finished.

View File

@@ -37,6 +37,12 @@ public class Table {
return Charset.forName("UTF-8").newDecoder();
}
};
public final static ThreadLocal<Charset> UTF8_CHARSET = new ThreadLocal<Charset>() {
@Override
protected Charset initialValue() {
return Charset.forName("UTF-8");
}
};
private final static ThreadLocal<CharBuffer> CHAR_BUFFER = new ThreadLocal<CharBuffer>();
/** Used to hold the position of the `bb` buffer. */
protected int bb_pos;
@@ -61,6 +67,11 @@ public class Table {
return vtable_offset < bb.getShort(vtable) ? bb.getShort(vtable + vtable_offset) : 0;
}
protected static int __offset(int vtable_offset, int offset, ByteBuffer bb) {
int vtable = bb.array().length - offset;
return bb.getShort(vtable + vtable_offset - bb.getInt(vtable)) + vtable;
}
/**
* Retrieve a relative offset.
*
@@ -71,6 +82,10 @@ public class Table {
return offset + bb.getInt(offset);
}
protected static int __indirect(int offset, ByteBuffer bb) {
return offset + bb.getInt(offset);
}
/**
* Create a Java `String` from UTF-8 data stored inside the FlatBuffer.
*
@@ -188,6 +203,76 @@ public class Table {
}
return true;
}
/**
* Sort tables by the key.
*
* @param offsets An 'int' indexes of the tables into the bb.
* @param bb A {@code ByteBuffer} to get the tables.
*/
protected void sortTables(int[] offsets, final ByteBuffer bb) {
Integer[] off = new Integer[offsets.length];
for (int i = 0; i < offsets.length; i++) off[i] = offsets[i];
java.util.Arrays.sort(off, new java.util.Comparator<Integer>() {
public int compare(Integer o1, Integer o2) {
return keysCompare(o1, o2, bb);
}
});
for (int i = 0; i < offsets.length; i++) offsets[i] = off[i];
}
/**
* Compare two tables by the key.
*
* @param o1 An 'Integer' index of the first key into the bb.
* @param o2 An 'Integer' index of the second key into the bb.
* @param bb A {@code ByteBuffer} to get the keys.
*/
protected int keysCompare(Integer o1, Integer o2, ByteBuffer bb) { return 0; }
/**
* Compare two strings in the buffer.
*
* @param offset_1 An 'int' index of the first string into the bb.
* @param offset_2 An 'int' index of the second string into the bb.
* @param bb A {@code ByteBuffer} to get the strings.
*/
protected static int compareStrings(int offset_1, int offset_2, ByteBuffer bb) {
offset_1 += bb.getInt(offset_1);
offset_2 += bb.getInt(offset_2);
int len_1 = bb.getInt(offset_1);
int len_2 = bb.getInt(offset_2);
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];
}
return len_1 - len_2;
}
/**
* Compare string from the buffer with the 'String' object.
*
* @param offset_1 An 'int' index of the first string into the bb.
* @param key Second string as a byte array.
* @param bb A {@code ByteBuffer} to get the first string.
*/
protected static int compareStrings(int offset_1, byte[] key, ByteBuffer bb) {
offset_1 += bb.getInt(offset_1);
int len_1 = bb.getInt(offset_1);
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];
}
return len_1 - len_2;
}
}
/// @endcond

View File

@@ -2,6 +2,15 @@
/// @addtogroup flatbuffers_javascript_api
/// @{
/// @cond FLATBUFFERS_INTERNAL
/**
* @fileoverview
*
* Need to suppress 'global this' error so the Node.js export line doesn't cause
* closure compile to error out.
* @suppress {globalThis}
*/
/**
* @const
* @namespace
@@ -75,8 +84,8 @@ flatbuffers.isLittleEndian = new Uint16Array(new Uint8Array([1, 0]).buffer)[0] =
/**
* @constructor
* @param {number} high
* @param {number} low
* @param {number} high
*/
flatbuffers.Long = function(low, high) {
/**
@@ -93,8 +102,8 @@ flatbuffers.Long = function(low, high) {
};
/**
* @param {number} high
* @param {number} low
* @param {number} high
* @returns {flatbuffers.Long}
*/
flatbuffers.Long.create = function(low, high) {
@@ -129,11 +138,13 @@ flatbuffers.Long.ZERO = new flatbuffers.Long(0, 0);
* Create a FlatBufferBuilder.
*
* @constructor
* @param {number=} initial_size
* @param {number=} opt_initial_size
*/
flatbuffers.Builder = function(initial_size) {
if (!initial_size) {
initial_size = 1024;
flatbuffers.Builder = function(opt_initial_size) {
if (!opt_initial_size) {
var initial_size = 1024;
} else {
var initial_size = opt_initial_size;
}
/**
@@ -528,6 +539,10 @@ flatbuffers.Builder.prototype.offset = function() {
* @param {flatbuffers.ByteBuffer} bb The current buffer with the existing data
* @returns {flatbuffers.ByteBuffer} A new byte buffer with the old data copied
* to it. The data is located at the end of the buffer.
*
* uint8Array.set() formally takes {Array<number>|ArrayBufferView}, so to pass
* it a uint8Array we need to suppress the type check:
* @suppress {checkTypes}
*/
flatbuffers.Builder.growByteBuffer = function(bb) {
var old_buf_size = bb.capacity();
@@ -642,10 +657,11 @@ outer_loop:
* Finalize a buffer, poiting to the given `root_table`.
*
* @param {flatbuffers.Offset} root_table
* @param {string=} file_identifier
* @param {string=} opt_file_identifier
*/
flatbuffers.Builder.prototype.finish = function(root_table, file_identifier) {
if (file_identifier) {
flatbuffers.Builder.prototype.finish = function(root_table, opt_file_identifier) {
if (opt_file_identifier) {
var file_identifier = opt_file_identifier;
this.prep(this.minalign, flatbuffers.SIZEOF_INT +
flatbuffers.FILE_IDENTIFIER_LENGTH);
if (file_identifier.length != flatbuffers.FILE_IDENTIFIER_LENGTH) {
@@ -1018,10 +1034,10 @@ flatbuffers.ByteBuffer.prototype.__union = function(t, offset) {
* FlatBuffer later on.
*
* @param {number} offset
* @param {flatbuffers.Encoding=} optionalEncoding Defaults to UTF16_STRING
* @param {flatbuffers.Encoding=} opt_encoding Defaults to UTF16_STRING
* @returns {string|Uint8Array}
*/
flatbuffers.ByteBuffer.prototype.__string = function(offset, optionalEncoding) {
flatbuffers.ByteBuffer.prototype.__string = function(offset, opt_encoding) {
offset += this.readInt32(offset);
var length = this.readInt32(offset);
@@ -1030,7 +1046,7 @@ flatbuffers.ByteBuffer.prototype.__string = function(offset, optionalEncoding) {
offset += flatbuffers.SIZEOF_INT;
if (optionalEncoding === flatbuffers.Encoding.UTF8_BYTES) {
if (opt_encoding === flatbuffers.Encoding.UTF8_BYTES) {
return this.bytes_.subarray(offset, offset + length);
}

View File

@@ -14,7 +14,20 @@
* limitations under the License.
*/
//#define UNSAFE_BYTEBUFFER // uncomment this line to use faster ByteBuffer
// There are 2 #defines that have an impact on performance of this ByteBuffer implementation
//
// UNSAFE_BYTEBUFFER
// This will use unsafe code to manipulate the underlying byte array. This
// can yield a reasonable performance increase.
//
// BYTEBUFFER_NO_BOUNDS_CHECK
// This will disable the bounds check asserts to the byte array. This can
// yield a small performance gain in normal code..
//
// Using UNSAFE_BYTEBUFFER and BYTEBUFFER_NO_BOUNDS_CHECK together can yield a
// performance gain of ~15% for some operations, however doing so is potentially
// dangerous. Do so at your own risk!
//
using System;
@@ -22,9 +35,6 @@ namespace FlatBuffers
{
/// <summary>
/// Class to mimic Java's ByteBuffer which is used heavily in Flatbuffers.
/// If your execution environment allows unsafe code, you should enable
/// unsafe code in your project and #define UNSAFE_BYTEBUFFER to use a
/// MUCH faster version of ByteBuffer.
/// </summary>
public class ByteBuffer
{
@@ -126,11 +136,14 @@ namespace FlatBuffers
}
#endif // !UNSAFE_BYTEBUFFER
private void AssertOffsetAndLength(int offset, int length)
{
#if !BYTEBUFFER_NO_BOUNDS_CHECK
if (offset < 0 ||
offset > _buffer.Length - length)
throw new ArgumentOutOfRangeException();
#endif
}
public void PutSbyte(int offset, sbyte value)
@@ -200,7 +213,6 @@ namespace FlatBuffers
public unsafe void PutUlong(int offset, ulong value)
{
AssertOffsetAndLength(offset, sizeof(ulong));
fixed (byte* ptr = _buffer)
{
*(ulong*)(ptr + offset) = BitConverter.IsLittleEndian

View File

@@ -296,6 +296,18 @@ namespace FlatBuffers
return new VectorOffset(Offset);
}
/// <summary>
/// Creates a vector of tables.
/// </summary>
/// <param name="offsets">Offsets of the tables.</param>
public VectorOffset CreateVectorOfTables<T>(Offset<T>[] offsets) where T : struct
{
NotNested();
StartVector(sizeof(int), offsets.Length, sizeof(int));
for (int i = offsets.Length - 1; i >= 0; i--) AddOffset(offsets[i].Value);
return EndVector();
}
/// @cond FLATBUFFERS_INTENRAL
public void Nested(int obj)
{

View File

@@ -37,6 +37,7 @@
<Compile Include="ByteBuffer.cs" />
<Compile Include="FlatBufferBuilder.cs" />
<Compile Include="FlatBufferConstants.cs" />
<Compile Include="IFlatbufferObject.cs" />
<Compile Include="Offset.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Struct.cs" />

View File

@@ -0,0 +1,28 @@
/*
* 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.
*/
namespace FlatBuffers
{
/// <summary>
/// This is the base for both structs and tables.
/// </summary>
public interface IFlatbufferObject
{
void __init(int _i, ByteBuffer _bb);
ByteBuffer ByteBuffer { get; }
}
}

View File

@@ -19,7 +19,7 @@ namespace FlatBuffers
/// <summary>
/// Offset class for typesafe assignments.
/// </summary>
public struct Offset<T> where T : class
public struct Offset<T> where T : struct
{
public int Value;
public Offset(int value)

View File

@@ -19,9 +19,9 @@ namespace FlatBuffers
/// <summary>
/// All structs in the generated code derive from this class, and add their own accessors.
/// </summary>
public abstract class Struct
public struct Struct
{
protected int bb_pos;
protected ByteBuffer bb;
public int bb_pos;
public ByteBuffer bb;
}
}
}

View File

@@ -20,31 +20,42 @@ using System.Text;
namespace FlatBuffers
{
/// <summary>
/// All tables in the generated code derive from this class, and add their own accessors.
/// All tables in the generated code derive from this struct, and add their own accessors.
/// </summary>
public abstract class Table
public struct Table
{
protected int bb_pos;
protected ByteBuffer bb;
public int bb_pos;
public ByteBuffer bb;
public ByteBuffer ByteBuffer { get { return bb; } }
// Look up a field in the vtable, return an offset into the object, or 0 if the field is not
// present.
protected int __offset(int vtableOffset)
public int __offset(int vtableOffset)
{
int vtable = bb_pos - bb.GetInt(bb_pos);
return vtableOffset < bb.GetShort(vtable) ? (int)bb.GetShort(vtable + vtableOffset) : 0;
}
public static int __offset(int vtableOffset, int offset, ByteBuffer bb)
{
int vtable = bb.Length - offset;
return (int)bb.GetShort(vtable + vtableOffset - bb.GetInt(vtable)) + vtable;
}
// Retrieve the relative offset stored at "offset"
protected int __indirect(int offset)
public int __indirect(int offset)
{
return offset + bb.GetInt(offset);
}
public static int __indirect(int offset, ByteBuffer bb)
{
return offset + bb.GetInt(offset);
}
// Create a .NET String from UTF-8 data stored inside the flatbuffer.
protected string __string(int offset)
public string __string(int offset)
{
offset += bb.GetInt(offset);
var len = bb.GetInt(offset);
@@ -53,7 +64,7 @@ namespace FlatBuffers
}
// Get the length of a vector whose offset is stored at "offset" in this object.
protected int __vector_len(int offset)
public int __vector_len(int offset)
{
offset += bb_pos;
offset += bb.GetInt(offset);
@@ -61,7 +72,7 @@ namespace FlatBuffers
}
// Get the start of data of a vector whose offset is stored at "offset" in this object.
protected int __vector(int offset)
public int __vector(int offset)
{
offset += bb_pos;
return offset + bb.GetInt(offset) + sizeof(int); // data starts after the length
@@ -70,7 +81,8 @@ namespace FlatBuffers
// Get the data of a vector whoses offset is stored at "offset" in this object as an
// ArraySegment&lt;byte&gt;. If the vector is not present in the ByteBuffer,
// then a null value will be returned.
protected ArraySegment<byte>? __vector_as_arraysegment(int offset) {
public ArraySegment<byte>? __vector_as_arraysegment(int offset)
{
var o = this.__offset(offset);
if (0 == o)
{
@@ -83,15 +95,15 @@ namespace FlatBuffers
}
// Initialize any Table-derived type to point to the union at the given offset.
protected TTable __union<TTable>(TTable t, int offset) where TTable : Table
public T __union<T>(int offset) where T : struct, IFlatbufferObject
{
offset += bb_pos;
t.bb_pos = offset + bb.GetInt(offset);
t.bb = bb;
T t = new T();
t.__init(offset + bb.GetInt(offset), bb);
return t;
}
protected static bool __has_identifier(ByteBuffer bb, string ident)
public static bool __has_identifier(ByteBuffer bb, string ident)
{
if (ident.Length != FlatBufferConstants.FileIdentifierLength)
throw new ArgumentException("FlatBuffers: file identifier must be length " + FlatBufferConstants.FileIdentifierLength, "ident");
@@ -104,6 +116,38 @@ namespace FlatBuffers
return true;
}
// Compare strings in the ByteBuffer.
public static int CompareStrings(int offset_1, int offset_2, ByteBuffer bb)
{
offset_1 += bb.GetInt(offset_1);
offset_2 += bb.GetInt(offset_2);
var len_1 = bb.GetInt(offset_1);
var len_2 = bb.GetInt(offset_2);
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];
}
return len_1 - len_2;
}
// Compare string from the ByteBuffer with the string object
public static int CompareStrings(int offset_1, byte[] key, ByteBuffer bb)
{
offset_1 += bb.GetInt(offset_1);
var len_1 = bb.GetInt(offset_1);
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];
}
return len_1 - len_2;
}
}
}

27
package.json Normal file
View File

@@ -0,0 +1,27 @@
{
"name": "flatbuffers",
"version": "1.6.0",
"description": "Memory Efficient Serialization Library",
"files": ["js/flatbuffers.js"],
"main": "js/flatbuffers.js",
"directories": {
"doc": "docs",
"test": "tests"
},
"scripts": {
"test": "tests/JavaScriptTest.sh"
},
"repository": {
"type": "git",
"url": "git+https://github.com/google/flatbuffers.git"
},
"keywords": [
"flatbuffers"
],
"author": "The FlatBuffers project",
"license": "SEE LICENSE IN LICENSE.txt",
"bugs": {
"url": "https://github.com/google/flatbuffers/issues"
},
"homepage": "https://google.github.io/flatbuffers/"
}

View File

@@ -593,6 +593,10 @@ class FlatbufferBuilder
protected function is_utf8($bytes)
{
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 */

View File

@@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.google.flatbuffers</groupId>
<artifactId>flatbuffers-java</artifactId>
<version>1.4.0-SNAPSHOT</version>
<version>1.6.0-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>FlatBuffers Java API</name>
<description>

View File

@@ -1,5 +1,7 @@
![logo](http://google.github.io/flatbuffers/fpl_logo_small.png) FlatBuffers
===========
[![Join the chat at https://gitter.im/google/flatbuffers](https://badges.gitter.im/google/flatbuffers.svg)](https://gitter.im/google/flatbuffers?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Build Status](https://travis-ci.org/google/flatbuffers.svg?branch=master)](https://travis-ci.org/google/flatbuffers) [![Build status](https://ci.appveyor.com/api/projects/status/yg5idd2fnusv1n10?svg=true)](https://ci.appveyor.com/project/gwvo/flatbuffers)
**FlatBuffers** is an efficient cross platform serialization library for games and

View File

@@ -51,6 +51,7 @@ table Enum {
is_union:bool = false;
underlying_type:Type (required);
attributes:[KeyValue];
documentation:[string];
}
table Field {
@@ -64,6 +65,7 @@ table Field {
required:bool = false;
key:bool = false;
attributes:[KeyValue];
documentation:[string];
}
table Object { // Used for both tables and structs.
@@ -73,6 +75,7 @@ table Object { // Used for both tables and structs.
minalign:int;
bytesize:int; // For structs.
attributes:[KeyValue];
documentation:[string];
}
table Schema {

View File

@@ -1,5 +1,6 @@
// automatically generated by the FlatBuffers compiler, do not modify
#ifndef FLATBUFFERS_GENERATED_MONSTER_MYGAME_SAMPLE_H_
#define FLATBUFFERS_GENERATED_MONSTER_MYGAME_SAMPLE_H_
@@ -25,11 +26,19 @@ enum Color {
};
inline const char **EnumNamesColor() {
static const char *names[] = { "Red", "Green", "Blue", nullptr };
static const char *names[] = {
"Red",
"Green",
"Blue",
nullptr
};
return names;
}
inline const char *EnumNameColor(Color e) { return EnumNamesColor()[static_cast<int>(e)]; }
inline const char *EnumNameColor(Color e) {
const size_t index = static_cast<int>(e);
return EnumNamesColor()[index];
}
enum Equipment {
Equipment_NONE = 0,
@@ -38,29 +47,61 @@ enum Equipment {
Equipment_MAX = Equipment_Weapon
};
struct EquipmentUnion {
Equipment type;
flatbuffers::NativeTable *table;
EquipmentUnion() : type(Equipment_NONE), table(nullptr) {}
EquipmentUnion(const EquipmentUnion &);
EquipmentUnion &operator=(const EquipmentUnion &);
~EquipmentUnion();
static flatbuffers::NativeTable *UnPack(const void *union_obj, Equipment type);
flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb) const;
WeaponT *AsWeapon() { return type == Equipment_Weapon ? reinterpret_cast<WeaponT *>(table) : nullptr; }
};
inline const char **EnumNamesEquipment() {
static const char *names[] = { "NONE", "Weapon", nullptr };
static const char *names[] = {
"NONE",
"Weapon",
nullptr
};
return names;
}
inline const char *EnumNameEquipment(Equipment e) { return EnumNamesEquipment()[static_cast<int>(e)]; }
inline const char *EnumNameEquipment(Equipment e) {
const size_t index = static_cast<int>(e);
return EnumNamesEquipment()[index];
}
inline bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *union_obj, Equipment type);
template<typename T> struct EquipmentTraits {
static const Equipment enum_value = Equipment_NONE;
};
template<> struct EquipmentTraits<Weapon> {
static const Equipment enum_value = Equipment_Weapon;
};
struct EquipmentUnion {
Equipment type;
flatbuffers::NativeTable *table;
EquipmentUnion() : type(Equipment_NONE), table(nullptr) {}
EquipmentUnion(EquipmentUnion&& u):
type(std::move(u.type)), table(std::move(u.table)) {}
EquipmentUnion(const EquipmentUnion &);
EquipmentUnion &operator=(const EquipmentUnion &);
~EquipmentUnion() { Reset(); }
void Reset();
template <typename T>
void Set(T&& value) {
Reset();
type = EquipmentTraits<typename T::TableType>::enum_value;
if (type != Equipment_NONE) {
table = new T(std::forward<T>(value));
}
}
static flatbuffers::NativeTable *UnPack(const void *obj, Equipment type, const flatbuffers::resolver_function_t *resolver);
flatbuffers::Offset<void> Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher = nullptr) const;
WeaponT *AsWeapon() {
return type == Equipment_Weapon ?
reinterpret_cast<WeaponT *>(table) : nullptr;
}
};
bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *obj, Equipment type);
bool VerifyEquipmentVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types);
MANUALLY_ALIGNED_STRUCT(4) Vec3 FLATBUFFERS_FINAL_CLASS {
private:
@@ -69,21 +110,40 @@ MANUALLY_ALIGNED_STRUCT(4) Vec3 FLATBUFFERS_FINAL_CLASS {
float z_;
public:
Vec3() { memset(this, 0, sizeof(Vec3)); }
Vec3(const Vec3 &_o) { memcpy(this, &_o, sizeof(Vec3)); }
Vec3() {
memset(this, 0, sizeof(Vec3));
}
Vec3(const Vec3 &_o) {
memcpy(this, &_o, sizeof(Vec3));
}
Vec3(float _x, float _y, float _z)
: x_(flatbuffers::EndianScalar(_x)), y_(flatbuffers::EndianScalar(_y)), z_(flatbuffers::EndianScalar(_z)) { }
float x() const { return flatbuffers::EndianScalar(x_); }
void mutate_x(float _x) { flatbuffers::WriteScalar(&x_, _x); }
float y() const { return flatbuffers::EndianScalar(y_); }
void mutate_y(float _y) { flatbuffers::WriteScalar(&y_, _y); }
float z() const { return flatbuffers::EndianScalar(z_); }
void mutate_z(float _z) { flatbuffers::WriteScalar(&z_, _z); }
: x_(flatbuffers::EndianScalar(_x)),
y_(flatbuffers::EndianScalar(_y)),
z_(flatbuffers::EndianScalar(_z)) {
}
float x() const {
return flatbuffers::EndianScalar(x_);
}
void mutate_x(float _x) {
flatbuffers::WriteScalar(&x_, _x);
}
float y() const {
return flatbuffers::EndianScalar(y_);
}
void mutate_y(float _y) {
flatbuffers::WriteScalar(&y_, _y);
}
float z() const {
return flatbuffers::EndianScalar(z_);
}
void mutate_z(float _z) {
flatbuffers::WriteScalar(&z_, _z);
}
};
STRUCT_END(Vec3, 12);
struct MonsterT : public flatbuffers::NativeTable {
typedef Monster TableType;
std::unique_ptr<Vec3> pos;
int16_t mana;
int16_t hp;
@@ -92,9 +152,15 @@ struct MonsterT : public flatbuffers::NativeTable {
Color color;
std::vector<std::unique_ptr<WeaponT>> weapons;
EquipmentUnion equipped;
MonsterT()
: mana(150),
hp(100),
color(Color_Blue) {
}
};
struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef MonsterT NativeTableType;
enum {
VT_POS = 4,
VT_MANA = 6,
@@ -106,24 +172,60 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VT_EQUIPPED_TYPE = 20,
VT_EQUIPPED = 22
};
const Vec3 *pos() const { return GetStruct<const Vec3 *>(VT_POS); }
Vec3 *mutable_pos() { return GetStruct<Vec3 *>(VT_POS); }
int16_t mana() const { return GetField<int16_t>(VT_MANA, 150); }
bool mutate_mana(int16_t _mana) { return SetField(VT_MANA, _mana); }
int16_t hp() const { return GetField<int16_t>(VT_HP, 100); }
bool mutate_hp(int16_t _hp) { return SetField(VT_HP, _hp); }
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(VT_NAME); }
flatbuffers::String *mutable_name() { return GetPointer<flatbuffers::String *>(VT_NAME); }
const flatbuffers::Vector<uint8_t> *inventory() const { return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_INVENTORY); }
flatbuffers::Vector<uint8_t> *mutable_inventory() { return GetPointer<flatbuffers::Vector<uint8_t> *>(VT_INVENTORY); }
Color color() const { return static_cast<Color>(GetField<int8_t>(VT_COLOR, 2)); }
bool mutate_color(Color _color) { return SetField(VT_COLOR, static_cast<int8_t>(_color)); }
const flatbuffers::Vector<flatbuffers::Offset<Weapon>> *weapons() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Weapon>> *>(VT_WEAPONS); }
flatbuffers::Vector<flatbuffers::Offset<Weapon>> *mutable_weapons() { return GetPointer<flatbuffers::Vector<flatbuffers::Offset<Weapon>> *>(VT_WEAPONS); }
Equipment equipped_type() const { return static_cast<Equipment>(GetField<uint8_t>(VT_EQUIPPED_TYPE, 0)); }
bool mutate_equipped_type(Equipment _equipped_type) { return SetField(VT_EQUIPPED_TYPE, static_cast<uint8_t>(_equipped_type)); }
const void *equipped() const { return GetPointer<const void *>(VT_EQUIPPED); }
void *mutable_equipped() { return GetPointer<void *>(VT_EQUIPPED); }
const Vec3 *pos() const {
return GetStruct<const Vec3 *>(VT_POS);
}
Vec3 *mutable_pos() {
return GetStruct<Vec3 *>(VT_POS);
}
int16_t mana() const {
return GetField<int16_t>(VT_MANA, 150);
}
bool mutate_mana(int16_t _mana) {
return SetField(VT_MANA, _mana);
}
int16_t hp() const {
return GetField<int16_t>(VT_HP, 100);
}
bool mutate_hp(int16_t _hp) {
return SetField(VT_HP, _hp);
}
const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(VT_NAME);
}
flatbuffers::String *mutable_name() {
return GetPointer<flatbuffers::String *>(VT_NAME);
}
const flatbuffers::Vector<uint8_t> *inventory() const {
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_INVENTORY);
}
flatbuffers::Vector<uint8_t> *mutable_inventory() {
return GetPointer<flatbuffers::Vector<uint8_t> *>(VT_INVENTORY);
}
Color color() const {
return static_cast<Color>(GetField<int8_t>(VT_COLOR, 2));
}
bool mutate_color(Color _color) {
return SetField(VT_COLOR, static_cast<int8_t>(_color));
}
const flatbuffers::Vector<flatbuffers::Offset<Weapon>> *weapons() const {
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Weapon>> *>(VT_WEAPONS);
}
flatbuffers::Vector<flatbuffers::Offset<Weapon>> *mutable_weapons() {
return GetPointer<flatbuffers::Vector<flatbuffers::Offset<Weapon>> *>(VT_WEAPONS);
}
Equipment equipped_type() const {
return static_cast<Equipment>(GetField<uint8_t>(VT_EQUIPPED_TYPE, 0));
}
bool mutate_equipped_type(Equipment _equipped_type) {
return SetField(VT_EQUIPPED_TYPE, static_cast<uint8_t>(_equipped_type));
}
const void *equipped() const {
return GetPointer<const void *>(VT_EQUIPPED);
}
void *mutable_equipped() {
return GetPointer<void *>(VT_EQUIPPED);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<Vec3>(verifier, VT_POS) &&
@@ -142,30 +244,55 @@ struct Monster FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyEquipment(verifier, equipped(), equipped_type()) &&
verifier.EndTable();
}
std::unique_ptr<MonsterT> UnPack() const;
MonsterT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
void UnPackTo(MonsterT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
static flatbuffers::Offset<Monster> Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
};
struct MonsterBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_pos(const Vec3 *pos) { fbb_.AddStruct(Monster::VT_POS, pos); }
void add_mana(int16_t mana) { fbb_.AddElement<int16_t>(Monster::VT_MANA, mana, 150); }
void add_hp(int16_t hp) { fbb_.AddElement<int16_t>(Monster::VT_HP, hp, 100); }
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(Monster::VT_NAME, name); }
void add_inventory(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory) { fbb_.AddOffset(Monster::VT_INVENTORY, inventory); }
void add_color(Color color) { fbb_.AddElement<int8_t>(Monster::VT_COLOR, static_cast<int8_t>(color), 2); }
void add_weapons(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Weapon>>> weapons) { fbb_.AddOffset(Monster::VT_WEAPONS, weapons); }
void add_equipped_type(Equipment equipped_type) { fbb_.AddElement<uint8_t>(Monster::VT_EQUIPPED_TYPE, static_cast<uint8_t>(equipped_type), 0); }
void add_equipped(flatbuffers::Offset<void> equipped) { fbb_.AddOffset(Monster::VT_EQUIPPED, equipped); }
MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
void add_pos(const Vec3 *pos) {
fbb_.AddStruct(Monster::VT_POS, pos);
}
void add_mana(int16_t mana) {
fbb_.AddElement<int16_t>(Monster::VT_MANA, mana, 150);
}
void add_hp(int16_t hp) {
fbb_.AddElement<int16_t>(Monster::VT_HP, hp, 100);
}
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
fbb_.AddOffset(Monster::VT_NAME, name);
}
void add_inventory(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> inventory) {
fbb_.AddOffset(Monster::VT_INVENTORY, inventory);
}
void add_color(Color color) {
fbb_.AddElement<int8_t>(Monster::VT_COLOR, static_cast<int8_t>(color), 2);
}
void add_weapons(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Weapon>>> weapons) {
fbb_.AddOffset(Monster::VT_WEAPONS, weapons);
}
void add_equipped_type(Equipment equipped_type) {
fbb_.AddElement<uint8_t>(Monster::VT_EQUIPPED_TYPE, static_cast<uint8_t>(equipped_type), 0);
}
void add_equipped(flatbuffers::Offset<void> equipped) {
fbb_.AddOffset(Monster::VT_EQUIPPED, equipped);
}
MonsterBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
MonsterBuilder &operator=(const MonsterBuilder &);
flatbuffers::Offset<Monster> Finish() {
auto o = flatbuffers::Offset<Monster>(fbb_.EndTable(start_, 10));
const auto end = fbb_.EndTable(start_, 10);
auto o = flatbuffers::Offset<Monster>(end);
return o;
}
};
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb,
inline flatbuffers::Offset<Monster> CreateMonster(
flatbuffers::FlatBufferBuilder &_fbb,
const Vec3 *pos = 0,
int16_t mana = 150,
int16_t hp = 100,
@@ -188,7 +315,8 @@ inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder
return builder_.Finish();
}
inline flatbuffers::Offset<Monster> CreateMonsterDirect(flatbuffers::FlatBufferBuilder &_fbb,
inline flatbuffers::Offset<Monster> CreateMonsterDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const Vec3 *pos = 0,
int16_t mana = 150,
int16_t hp = 100,
@@ -198,25 +326,48 @@ inline flatbuffers::Offset<Monster> CreateMonsterDirect(flatbuffers::FlatBufferB
const std::vector<flatbuffers::Offset<Weapon>> *weapons = nullptr,
Equipment equipped_type = Equipment_NONE,
flatbuffers::Offset<void> equipped = 0) {
return CreateMonster(_fbb, pos, mana, hp, name ? _fbb.CreateString(name) : 0, inventory ? _fbb.CreateVector<uint8_t>(*inventory) : 0, color, weapons ? _fbb.CreateVector<flatbuffers::Offset<Weapon>>(*weapons) : 0, equipped_type, equipped);
return MyGame::Sample::CreateMonster(
_fbb,
pos,
mana,
hp,
name ? _fbb.CreateString(name) : 0,
inventory ? _fbb.CreateVector<uint8_t>(*inventory) : 0,
color,
weapons ? _fbb.CreateVector<flatbuffers::Offset<Weapon>>(*weapons) : 0,
equipped_type,
equipped);
}
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o);
flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
struct WeaponT : public flatbuffers::NativeTable {
typedef Weapon TableType;
std::string name;
int16_t damage;
WeaponT()
: damage(0) {
}
};
struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
typedef WeaponT NativeTableType;
enum {
VT_NAME = 4,
VT_DAMAGE = 6
};
const flatbuffers::String *name() const { return GetPointer<const flatbuffers::String *>(VT_NAME); }
flatbuffers::String *mutable_name() { return GetPointer<flatbuffers::String *>(VT_NAME); }
int16_t damage() const { return GetField<int16_t>(VT_DAMAGE, 0); }
bool mutate_damage(int16_t _damage) { return SetField(VT_DAMAGE, _damage); }
const flatbuffers::String *name() const {
return GetPointer<const flatbuffers::String *>(VT_NAME);
}
flatbuffers::String *mutable_name() {
return GetPointer<flatbuffers::String *>(VT_NAME);
}
int16_t damage() const {
return GetField<int16_t>(VT_DAMAGE, 0);
}
bool mutate_damage(int16_t _damage) {
return SetField(VT_DAMAGE, _damage);
}
bool Verify(flatbuffers::Verifier &verifier) const {
return VerifyTableStart(verifier) &&
VerifyField<flatbuffers::uoffset_t>(verifier, VT_NAME) &&
@@ -224,23 +375,34 @@ struct Weapon FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
VerifyField<int16_t>(verifier, VT_DAMAGE) &&
verifier.EndTable();
}
std::unique_ptr<WeaponT> UnPack() const;
WeaponT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const;
void UnPackTo(WeaponT *_o, const flatbuffers::resolver_function_t *_resolver = nullptr) const;
static flatbuffers::Offset<Weapon> Pack(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT* _o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
};
struct WeaponBuilder {
flatbuffers::FlatBufferBuilder &fbb_;
flatbuffers::uoffset_t start_;
void add_name(flatbuffers::Offset<flatbuffers::String> name) { fbb_.AddOffset(Weapon::VT_NAME, name); }
void add_damage(int16_t damage) { fbb_.AddElement<int16_t>(Weapon::VT_DAMAGE, damage, 0); }
WeaponBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); }
void add_name(flatbuffers::Offset<flatbuffers::String> name) {
fbb_.AddOffset(Weapon::VT_NAME, name);
}
void add_damage(int16_t damage) {
fbb_.AddElement<int16_t>(Weapon::VT_DAMAGE, damage, 0);
}
WeaponBuilder(flatbuffers::FlatBufferBuilder &_fbb)
: fbb_(_fbb) {
start_ = fbb_.StartTable();
}
WeaponBuilder &operator=(const WeaponBuilder &);
flatbuffers::Offset<Weapon> Finish() {
auto o = flatbuffers::Offset<Weapon>(fbb_.EndTable(start_, 2));
const auto end = fbb_.EndTable(start_, 2);
auto o = flatbuffers::Offset<Weapon>(end);
return o;
}
};
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb,
inline flatbuffers::Offset<Weapon> CreateWeapon(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::String> name = 0,
int16_t damage = 0) {
WeaponBuilder builder_(_fbb);
@@ -249,92 +411,176 @@ inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &
return builder_.Finish();
}
inline flatbuffers::Offset<Weapon> CreateWeaponDirect(flatbuffers::FlatBufferBuilder &_fbb,
inline flatbuffers::Offset<Weapon> CreateWeaponDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const char *name = nullptr,
int16_t damage = 0) {
return CreateWeapon(_fbb, name ? _fbb.CreateString(name) : 0, damage);
return MyGame::Sample::CreateWeapon(
_fbb,
name ? _fbb.CreateString(name) : 0,
damage);
}
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o);
flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr);
inline std::unique_ptr<MonsterT> Monster::UnPack() const {
inline MonsterT *Monster::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
auto _o = new MonsterT();
UnPackTo(_o, _resolver);
return _o;
}
inline void Monster::UnPackTo(MonsterT *_o, const flatbuffers::resolver_function_t *_resolver) const {
(void)_o;
(void)_resolver;
{ auto _e = pos(); if (_e) _o->pos = std::unique_ptr<Vec3>(new Vec3(*_e)); };
{ auto _e = mana(); _o->mana = _e; };
{ auto _e = hp(); _o->hp = _e; };
{ auto _e = name(); if (_e) _o->name = _e->str(); };
{ auto _e = inventory(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inventory.push_back(_e->Get(_i)); } } };
{ auto _e = inventory(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->inventory.push_back(_e->Get(_i)); } };
{ auto _e = color(); _o->color = _e; };
{ auto _e = weapons(); if (_e) { for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->weapons.push_back(_e->Get(_i)->UnPack()); } } };
{ auto _e = weapons(); if (_e) for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->weapons.push_back(std::unique_ptr<WeaponT>(_e->Get(_i)->UnPack(_resolver))); } };
{ auto _e = equipped_type(); _o->equipped.type = _e; };
{ auto _e = equipped(); if (_e) _o->equipped.table = EquipmentUnion::UnPack(_e, equipped_type()); };
return std::unique_ptr<MonsterT>(_o);
{ auto _e = equipped(); if (_e) _o->equipped.table = EquipmentUnion::UnPack(_e, equipped_type(),_resolver); };
}
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o) {
return CreateMonster(_fbb,
_o->pos ? _o->pos.get() : 0,
_o->mana,
_o->hp,
_o->name.size() ? _fbb.CreateString(_o->name) : 0,
_o->inventory.size() ? _fbb.CreateVector(_o->inventory) : 0,
_o->color,
_o->weapons.size() ? _fbb.CreateVector<flatbuffers::Offset<Weapon>>(_o->weapons.size(), [&](size_t i) { return CreateWeapon(_fbb, _o->weapons[i].get()); }) : 0,
_o->equipped.type,
_o->equipped.Pack(_fbb));
inline flatbuffers::Offset<Monster> Monster::Pack(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
return CreateMonster(_fbb, _o, _rehasher);
}
inline std::unique_ptr<WeaponT> Weapon::UnPack() const {
inline flatbuffers::Offset<Monster> CreateMonster(flatbuffers::FlatBufferBuilder &_fbb, const MonsterT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
(void)_rehasher;
(void)_o;
auto _pos = _o->pos ? _o->pos.get() : 0;
auto _mana = _o->mana;
auto _hp = _o->hp;
auto _name = _o->name.size() ? _fbb.CreateString(_o->name) : 0;
auto _inventory = _o->inventory.size() ? _fbb.CreateVector(_o->inventory) : 0;
auto _color = _o->color;
auto _weapons = _o->weapons.size() ? _fbb.CreateVector<flatbuffers::Offset<Weapon>>(_o->weapons.size(), [&](size_t i) { return CreateWeapon(_fbb, _o->weapons[i].get(), _rehasher); }) : 0;
auto _equipped_type = _o->equipped.type;
auto _equipped = _o->equipped.Pack(_fbb);
return MyGame::Sample::CreateMonster(
_fbb,
_pos,
_mana,
_hp,
_name,
_inventory,
_color,
_weapons,
_equipped_type,
_equipped);
}
inline WeaponT *Weapon::UnPack(const flatbuffers::resolver_function_t *_resolver) const {
auto _o = new WeaponT();
UnPackTo(_o, _resolver);
return _o;
}
inline void Weapon::UnPackTo(WeaponT *_o, const flatbuffers::resolver_function_t *_resolver) const {
(void)_o;
(void)_resolver;
{ auto _e = name(); if (_e) _o->name = _e->str(); };
{ auto _e = damage(); _o->damage = _e; };
return std::unique_ptr<WeaponT>(_o);
}
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o) {
return CreateWeapon(_fbb,
_o->name.size() ? _fbb.CreateString(_o->name) : 0,
_o->damage);
inline flatbuffers::Offset<Weapon> Weapon::Pack(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT* _o, const flatbuffers::rehasher_function_t *_rehasher) {
return CreateWeapon(_fbb, _o, _rehasher);
}
inline bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *union_obj, Equipment type) {
inline flatbuffers::Offset<Weapon> CreateWeapon(flatbuffers::FlatBufferBuilder &_fbb, const WeaponT *_o, const flatbuffers::rehasher_function_t *_rehasher) {
(void)_rehasher;
(void)_o;
auto _name = _o->name.size() ? _fbb.CreateString(_o->name) : 0;
auto _damage = _o->damage;
return MyGame::Sample::CreateWeapon(
_fbb,
_name,
_damage);
}
inline bool VerifyEquipment(flatbuffers::Verifier &verifier, const void *obj, Equipment type) {
switch (type) {
case Equipment_NONE: return true;
case Equipment_Weapon: return verifier.VerifyTable(reinterpret_cast<const Weapon *>(union_obj));
case Equipment_NONE: {
return true;
}
case Equipment_Weapon: {
auto ptr = reinterpret_cast<const Weapon *>(obj);
return verifier.VerifyTable(ptr);
}
default: return false;
}
}
inline flatbuffers::NativeTable *EquipmentUnion::UnPack(const void *union_obj, Equipment type) {
inline bool VerifyEquipmentVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<uint8_t> *types) {
if (values->size() != types->size()) return false;
for (flatbuffers::uoffset_t i = 0; i < values->size(); ++i) {
if (!VerifyEquipment(
verifier, values->Get(i), types->GetEnum<Equipment>(i))) {
return false;
}
}
return true;
}
inline flatbuffers::NativeTable *EquipmentUnion::UnPack(const void *obj, Equipment type, const flatbuffers::resolver_function_t *resolver) {
switch (type) {
case Equipment_NONE: return nullptr;
case Equipment_Weapon: return reinterpret_cast<const Weapon *>(union_obj)->UnPack().release();
case Equipment_Weapon: {
auto ptr = reinterpret_cast<const Weapon *>(obj);
return ptr->UnPack(resolver);
}
default: return nullptr;
}
}
inline flatbuffers::Offset<void> EquipmentUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb) const {
inline flatbuffers::Offset<void> EquipmentUnion::Pack(flatbuffers::FlatBufferBuilder &_fbb, const flatbuffers::rehasher_function_t *_rehasher) const {
switch (type) {
case Equipment_NONE: return 0;
case Equipment_Weapon: return CreateWeapon(_fbb, reinterpret_cast<const WeaponT *>(table)).Union();
case Equipment_Weapon: {
auto ptr = reinterpret_cast<const WeaponT *>(table);
return CreateWeapon(_fbb, ptr, _rehasher).Union();
}
default: return 0;
}
}
inline EquipmentUnion::~EquipmentUnion() {
inline void EquipmentUnion::Reset() {
switch (type) {
case Equipment_Weapon: delete reinterpret_cast<WeaponT *>(table); break;
default:;
case Equipment_Weapon: {
auto ptr = reinterpret_cast<WeaponT *>(table);
delete ptr;
break;
}
default: break;
}
table = nullptr;
type = Equipment_NONE;
}
inline const MyGame::Sample::Monster *GetMonster(const void *buf) { return flatbuffers::GetRoot<MyGame::Sample::Monster>(buf); }
inline const MyGame::Sample::Monster *GetMonster(const void *buf) {
return flatbuffers::GetRoot<MyGame::Sample::Monster>(buf);
}
inline Monster *GetMutableMonster(void *buf) { return flatbuffers::GetMutableRoot<Monster>(buf); }
inline Monster *GetMutableMonster(void *buf) {
return flatbuffers::GetMutableRoot<Monster>(buf);
}
inline bool VerifyMonsterBuffer(flatbuffers::Verifier &verifier) { return verifier.VerifyBuffer<MyGame::Sample::Monster>(nullptr); }
inline bool VerifyMonsterBuffer(
flatbuffers::Verifier &verifier) {
return verifier.VerifyBuffer<MyGame::Sample::Monster>(nullptr);
}
inline void FinishMonsterBuffer(flatbuffers::FlatBufferBuilder &fbb, flatbuffers::Offset<MyGame::Sample::Monster> root) { fbb.Finish(root); }
inline void FinishMonsterBuffer(
flatbuffers::FlatBufferBuilder &fbb,
flatbuffers::Offset<MyGame::Sample::Monster> root) {
fbb.Finish(root);
}
inline std::unique_ptr<MonsterT> UnPackMonster(
const void *buf,
const flatbuffers::resolver_function_t *res = nullptr) {
return std::unique_ptr<MonsterT>(GetMonster(buf)->UnPack(res));
}
} // namespace Sample
} // namespace MyGame

View File

@@ -5,5 +5,21 @@
z: 3
},
hp: 300,
name: "Orc"
name: "Orc",
weapons:[
{
name: "axe",
damage:100
},
{
name: "bow",
damage:90
}
],
equipped_type: "Weapon",
equipped:
{
name: "bow",
damage:90
}
}

View File

@@ -19,147 +19,147 @@
package main
import (
flatbuffers "github.com/google/flatbuffers/go"
"fmt"
"strconv"
sample "MyGame/Sample"
sample "MyGame/Sample"
"fmt"
flatbuffers "github.com/google/flatbuffers/go"
"strconv"
)
// Example how to use Flatbuffers to create and read binary buffers.
func main() {
builder := flatbuffers.NewBuilder(0)
builder := flatbuffers.NewBuilder(0)
// Create some weapons for our Monster ("Sword" and "Axe").
weaponOne := builder.CreateString("Sword")
weaponTwo := builder.CreateString("Axe")
// Create some weapons for our Monster ("Sword" and "Axe").
weaponOne := builder.CreateString("Sword")
weaponTwo := builder.CreateString("Axe")
sample.WeaponStart(builder)
sample.WeaponAddName(builder, weaponOne)
sample.WeaponAddDamage(builder, 3)
sword := sample.WeaponEnd(builder)
sample.WeaponStart(builder)
sample.WeaponAddName(builder, weaponOne)
sample.WeaponAddDamage(builder, 3)
sword := sample.WeaponEnd(builder)
sample.WeaponStart(builder)
sample.WeaponAddName(builder, weaponTwo)
sample.WeaponAddDamage(builder, 5)
axe := sample.WeaponEnd(builder)
sample.WeaponStart(builder)
sample.WeaponAddName(builder, weaponTwo)
sample.WeaponAddDamage(builder, 5)
axe := sample.WeaponEnd(builder)
// Serialize the FlatBuffer data.
name := builder.CreateString("Orc")
// Serialize the FlatBuffer data.
name := builder.CreateString("Orc")
sample.MonsterStartInventoryVector(builder, 10)
// Note: Since we prepend the bytes, this loop iterates in reverse.
for i := 9; i >= 0; i-- {
builder.PrependByte(byte(i))
}
inv := builder.EndVector(10)
sample.MonsterStartInventoryVector(builder, 10)
// Note: Since we prepend the bytes, this loop iterates in reverse.
for i := 9; i >= 0; i-- {
builder.PrependByte(byte(i))
}
inv := builder.EndVector(10)
sample.MonsterStartWeaponsVector(builder, 2)
// Note: Since we prepend the weapons, prepend in reverse order.
builder.PrependUOffsetT(axe)
builder.PrependUOffsetT(sword)
weapons := builder.EndVector(2)
sample.MonsterStartWeaponsVector(builder, 2)
// Note: Since we prepend the weapons, prepend in reverse order.
builder.PrependUOffsetT(axe)
builder.PrependUOffsetT(sword)
weapons := builder.EndVector(2)
pos := sample.CreateVec3(builder, 1.0, 2.0, 3.0)
pos := sample.CreateVec3(builder, 1.0, 2.0, 3.0)
sample.MonsterStart(builder)
sample.MonsterAddPos(builder, pos)
sample.MonsterAddHp(builder, 300)
sample.MonsterAddName(builder, name)
sample.MonsterAddInventory(builder, inv)
sample.MonsterAddColor(builder, sample.ColorRed)
sample.MonsterAddWeapons(builder, weapons)
sample.MonsterAddEquippedType(builder, sample.EquipmentWeapon)
sample.MonsterAddEquipped(builder, axe)
orc := sample.MonsterEnd(builder)
sample.MonsterStart(builder)
sample.MonsterAddPos(builder, pos)
sample.MonsterAddHp(builder, 300)
sample.MonsterAddName(builder, name)
sample.MonsterAddInventory(builder, inv)
sample.MonsterAddColor(builder, sample.ColorRed)
sample.MonsterAddWeapons(builder, weapons)
sample.MonsterAddEquippedType(builder, sample.EquipmentWeapon)
sample.MonsterAddEquipped(builder, axe)
orc := sample.MonsterEnd(builder)
builder.Finish(orc)
builder.Finish(orc)
// We now have a FlatBuffer that we could store on disk or send over a network.
// We now have a FlatBuffer that we could store on disk or send over a network.
// ...Saving to file or sending over a network code goes here...
// ...Saving to file or sending over a network code goes here...
// Instead, we are going to access this buffer right away (as if we just received it).
// Instead, we are going to access this buffer right away (as if we just received it).
buf := builder.FinishedBytes()
buf := builder.FinishedBytes()
// Note: We use `0` for the offset here, since we got the data using the
// `builder.FinishedBytes()` method. This simulates the data you would store/receive in your
// FlatBuffer. If you wanted to read from the `builder.Bytes` directly, you would need to
// pass in the offset of `builder.Head()`, as the builder actually constructs the buffer
// backwards.
monster := sample.GetRootAsMonster(buf, 0)
// Note: We use `0` for the offset here, since we got the data using the
// `builder.FinishedBytes()` method. This simulates the data you would store/receive in your
// FlatBuffer. If you wanted to read from the `builder.Bytes` directly, you would need to
// pass in the offset of `builder.Head()`, as the builder actually constructs the buffer
// backwards.
monster := sample.GetRootAsMonster(buf, 0)
// Note: We did not set the `mana` field explicitly, so we get the
// default value.
assert(monster.Mana() == 150, "`monster.Mana()`", strconv.Itoa(int(monster.Mana())), "150")
assert(monster.Hp() == 300, "`monster.Hp()`", strconv.Itoa(int(monster.Hp())), "300")
assert(string(monster.Name()) == "Orc", "`string(monster.Name())`", string(monster.Name()),
"\"Orc\"")
assert(monster.Color() == sample.ColorRed, "`monster.Color()`",
strconv.Itoa(int(monster.Color())), strconv.Itoa(int(sample.ColorRed)))
// Note: We did not set the `mana` field explicitly, so we get the
// default value.
assert(monster.Mana() == 150, "`monster.Mana()`", strconv.Itoa(int(monster.Mana())), "150")
assert(monster.Hp() == 300, "`monster.Hp()`", strconv.Itoa(int(monster.Hp())), "300")
assert(string(monster.Name()) == "Orc", "`string(monster.Name())`", string(monster.Name()),
"\"Orc\"")
assert(monster.Color() == sample.ColorRed, "`monster.Color()`",
strconv.Itoa(int(monster.Color())), strconv.Itoa(int(sample.ColorRed)))
// Note: Whenever you access a new object, like in `Pos()`, a new temporary accessor object
// gets created. If your code is very performance sensitive, you can pass in a pointer to an
// existing `Vec3` instead of `nil`. This allows you to reuse it across many calls to reduce
// the amount of object allocation/garbage collection.
assert(monster.Pos(nil).X() == 1.0, "`monster.Pos(nil).X()`",
strconv.FormatFloat(float64(monster.Pos(nil).X()), 'f', 1, 32), "1.0")
assert(monster.Pos(nil).Y() == 2.0, "`monster.Pos(nil).Y()`",
strconv.FormatFloat(float64(monster.Pos(nil).Y()), 'f', 1, 32), "2.0")
assert(monster.Pos(nil).Z() == 3.0, "`monster.Pos(nil).Z()`",
strconv.FormatFloat(float64(monster.Pos(nil).Z()), 'f', 1, 32), "3.0")
// Note: Whenever you access a new object, like in `Pos()`, a new temporary accessor object
// gets created. If your code is very performance sensitive, you can pass in a pointer to an
// existing `Vec3` instead of `nil`. This allows you to reuse it across many calls to reduce
// the amount of object allocation/garbage collection.
assert(monster.Pos(nil).X() == 1.0, "`monster.Pos(nil).X()`",
strconv.FormatFloat(float64(monster.Pos(nil).X()), 'f', 1, 32), "1.0")
assert(monster.Pos(nil).Y() == 2.0, "`monster.Pos(nil).Y()`",
strconv.FormatFloat(float64(monster.Pos(nil).Y()), 'f', 1, 32), "2.0")
assert(monster.Pos(nil).Z() == 3.0, "`monster.Pos(nil).Z()`",
strconv.FormatFloat(float64(monster.Pos(nil).Z()), 'f', 1, 32), "3.0")
// For vectors, like `Inventory`, they have a method suffixed with 'Length' that can be used
// to query the length of the vector. You can index the vector by passing an index value
// into the accessor.
for i := 0; i < monster.InventoryLength(); i++ {
assert(monster.Inventory(i) == byte(i), "`monster.Inventory(i)`",
strconv.Itoa(int(monster.Inventory(i))), strconv.Itoa(int(byte(i))))
}
// For vectors, like `Inventory`, they have a method suffixed with 'Length' that can be used
// to query the length of the vector. You can index the vector by passing an index value
// into the accessor.
for i := 0; i < monster.InventoryLength(); i++ {
assert(monster.Inventory(i) == byte(i), "`monster.Inventory(i)`",
strconv.Itoa(int(monster.Inventory(i))), strconv.Itoa(int(byte(i))))
}
expectedWeaponNames := []string{"Sword", "Axe"}
expectedWeaponDamages := []int{3, 5}
weapon := new(sample.Weapon) // We need a `sample.Weapon` to pass into `monster.Weapons()`
// to capture the output of that function.
for i := 0; i < monster.WeaponsLength(); i++ {
if monster.Weapons(weapon, i) {
assert(string(weapon.Name()) == expectedWeaponNames[i], "`weapon.Name()`",
string(weapon.Name()), expectedWeaponNames[i])
assert(int(weapon.Damage()) == expectedWeaponDamages[i],
"`weapon.Damage()`", strconv.Itoa(int(weapon.Damage())),
strconv.Itoa(expectedWeaponDamages[i]))
}
}
expectedWeaponNames := []string{"Sword", "Axe"}
expectedWeaponDamages := []int{3, 5}
weapon := new(sample.Weapon) // We need a `sample.Weapon` to pass into `monster.Weapons()`
// to capture the output of that function.
for i := 0; i < monster.WeaponsLength(); i++ {
if monster.Weapons(weapon, i) {
assert(string(weapon.Name()) == expectedWeaponNames[i], "`weapon.Name()`",
string(weapon.Name()), expectedWeaponNames[i])
assert(int(weapon.Damage()) == expectedWeaponDamages[i],
"`weapon.Damage()`", strconv.Itoa(int(weapon.Damage())),
strconv.Itoa(expectedWeaponDamages[i]))
}
}
// For FlatBuffer `union`s, you can get the type of the union, as well as the union
// data itself.
assert(monster.EquippedType() == sample.EquipmentWeapon, "`monster.EquippedType()`",
strconv.Itoa(int(monster.EquippedType())), strconv.Itoa(int(sample.EquipmentWeapon)))
// For FlatBuffer `union`s, you can get the type of the union, as well as the union
// data itself.
assert(monster.EquippedType() == sample.EquipmentWeapon, "`monster.EquippedType()`",
strconv.Itoa(int(monster.EquippedType())), strconv.Itoa(int(sample.EquipmentWeapon)))
unionTable := new(flatbuffers.Table)
if monster.Equipped(unionTable) {
// An example of how you can appropriately convert the table depending on the
// FlatBuffer `union` type. You could add `else if` and `else` clauses to handle
// other FlatBuffer `union` types for this field. (Similarly, this could be
// done in a switch statement.)
if monster.EquippedType() == sample.EquipmentWeapon {
unionWeapon := new(sample.Weapon)
unionWeapon.Init(unionTable.Bytes, unionTable.Pos)
unionTable := new(flatbuffers.Table)
if monster.Equipped(unionTable) {
// An example of how you can appropriately convert the table depending on the
// FlatBuffer `union` type. You could add `else if` and `else` clauses to handle
// other FlatBuffer `union` types for this field. (Similarly, this could be
// done in a switch statement.)
if monster.EquippedType() == sample.EquipmentWeapon {
unionWeapon := new(sample.Weapon)
unionWeapon.Init(unionTable.Bytes, unionTable.Pos)
assert(string(unionWeapon.Name()) == "Axe", "`unionWeapon.Name()`",
string(unionWeapon.Name()), "Axe")
assert(int(unionWeapon.Damage()) == 5, "`unionWeapon.Damage()`",
strconv.Itoa(int(unionWeapon.Damage())), strconv.Itoa(5))
}
}
assert(string(unionWeapon.Name()) == "Axe", "`unionWeapon.Name()`",
string(unionWeapon.Name()), "Axe")
assert(int(unionWeapon.Damage()) == 5, "`unionWeapon.Damage()`",
strconv.Itoa(int(unionWeapon.Damage())), strconv.Itoa(5))
}
}
fmt.Printf("The FlatBuffer was successfully created and verified!\n")
fmt.Printf("The FlatBuffer was successfully created and verified!\n")
}
// A helper function to print out if an assertion failed.
func assert(assertPassed bool, codeExecuted string, actualValue string, expectedValue string) {
if assertPassed == false {
panic("Assert failed! " + codeExecuted + " (" + actualValue +
") was not equal to " + expectedValue + ".")
}
if assertPassed == false {
panic("Assert failed! " + codeExecuted + " (" + actualValue +
") was not equal to " + expectedValue + ".")
}
}

View File

@@ -46,7 +46,10 @@ int main(int /*argc*/, const char * /*argv*/[]) {
// to ensure it is correct, we now generate text back from the binary,
// and compare the two:
std::string jsongen;
GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen);
if (!GenerateText(parser, parser.builder_.GetBufferPointer(), &jsongen)) {
printf("Couldn't serialize parsed data to JSON!\n");
return 1;
}
if (jsongen != jsonfile) {
printf("%s----------------\n%s", jsongen.c_str(), jsonfile.c_str());

158
src/code_generators.cpp Normal file
View File

@@ -0,0 +1,158 @@
/*
* 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.
*/
#include "flatbuffers/code_generators.h"
#include <assert.h>
#include "flatbuffers/util.h"
namespace flatbuffers {
void CodeWriter::operator+=(std::string text) {
while (true) {
auto begin = text.find("{{");
if (begin == std::string::npos) {
break;
}
auto end = text.find("}}");
if (end == std::string::npos || end < begin) {
break;
}
// Write all the text before the first {{ into the stream.
stream_.write(text.c_str(), begin);
// The key is between the {{ and }}.
const std::string key = text.substr(begin + 2, end - begin - 2);
// Find the value associated with the key. If it exists, write the
// value into the stream, otherwise write the key itself into the stream.
auto iter = value_map_.find(key);
if (iter != value_map_.end()) {
const std::string &value = iter->second;
stream_ << value;
} else {
assert(false && "could not find key");
stream_ << key;
}
// Update the text to everything after the }}.
text = text.substr(end + 2);
}
if (!text.empty() && text.back() == '\\') {
text.pop_back();
stream_ << text;
} else {
stream_ << text << std::endl;
}
}
const char *BaseGenerator::FlatBuffersGeneratedWarning() {
return "automatically generated by the FlatBuffers compiler,"
" do not modify\n\n";
}
std::string BaseGenerator::NamespaceDir(const Parser &parser,
const std::string &path,
const Namespace &ns) {
EnsureDirExists(path.c_str());
if (parser.opts.one_file) return path;
std::string namespace_dir = path; // Either empty or ends in separator.
auto &namespaces = ns.components;
for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
namespace_dir += *it + kPathSeparator;
EnsureDirExists(namespace_dir.c_str());
}
return namespace_dir;
}
std::string BaseGenerator::NamespaceDir(const Namespace &ns) const {
return BaseGenerator::NamespaceDir(parser_, path_, ns);
}
bool BaseGenerator::IsEverythingGenerated() const {
for (auto it = parser_.enums_.vec.begin(); it != parser_.enums_.vec.end();
++it) {
if (!(*it)->generated) return false;
}
for (auto it = parser_.structs_.vec.begin();
it != parser_.structs_.vec.end(); ++it) {
if (!(*it)->generated) return false;
}
return true;
}
std::string BaseGenerator::FullNamespace(const char *separator,
const Namespace &ns) {
std::string namespace_name;
auto &namespaces = ns.components;
for (auto it = namespaces.begin(); it != namespaces.end(); ++it) {
if (namespace_name.length()) namespace_name += separator;
namespace_name += *it;
}
return namespace_name;
}
std::string BaseGenerator::LastNamespacePart(const Namespace &ns) {
if (!ns.components.empty())
return ns.components.back();
else
return std::string("");
}
// Ensure that a type is prefixed with its namespace whenever it is used
// outside of its namespace.
std::string BaseGenerator::WrapInNameSpace(const Namespace *ns,
const std::string &name) const {
if (CurrentNameSpace() == ns) return name;
std::string qualified_name = qualifying_start_;
for (auto it = ns->components.begin(); it != ns->components.end(); ++it)
qualified_name += *it + qualifying_separator_;
return qualified_name + name;
}
std::string BaseGenerator::WrapInNameSpace(const Definition &def) const {
return WrapInNameSpace(def.defined_namespace, def.name);
}
// Generate a documentation comment, if available.
void GenComment(const std::vector<std::string> &dc, std::string *code_ptr,
const CommentConfig *config, const char *prefix) {
if (dc.begin() == dc.end()) {
// Don't output empty comment blocks with 0 lines of comment content.
return;
}
std::string &code = *code_ptr;
if (config != nullptr && config->first_line != nullptr) {
code += std::string(prefix) + std::string(config->first_line) + "\n";
}
std::string line_prefix = std::string(prefix) +
((config != nullptr && config->content_line_prefix != nullptr) ?
config->content_line_prefix : "///");
for (auto it = dc.begin();
it != dc.end();
++it) {
code += line_prefix + *it + "\n";
}
if (config != nullptr && config->last_line != nullptr) {
code += std::string(prefix) + std::string(config->last_line) + "\n";
}
}
} // namespace flatbuffers

View File

@@ -14,92 +14,50 @@
* limitations under the License.
*/
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include <limits>
#include "flatbuffers/flatc.h"
#define FLATC_VERSION "1.4.0 (" __DATE__ ")"
#define FLATC_VERSION "1.6.0 (" __DATE__ ")"
static void Error(const std::string &err, bool usage = false,
bool show_exe_name = true);
namespace flatbuffers {
// This struct allows us to create a table of all possible output generators
// for the various programming languages and formats we support.
struct Generator {
bool (*generate)(const flatbuffers::Parser &parser,
const std::string &path,
const std::string &file_name);
const char *generator_opt_short;
const char *generator_opt_long;
const char *lang_name;
flatbuffers::IDLOptions::Language lang;
const char *generator_help;
void FlatCompiler::ParseFile(
flatbuffers::Parser &parser,
const std::string &filename,
const std::string &contents,
std::vector<const char *> &include_directories) const {
auto local_include_directory = flatbuffers::StripFileName(filename);
include_directories.push_back(local_include_directory.c_str());
include_directories.push_back(nullptr);
if (!parser.Parse(contents.c_str(), &include_directories[0],
filename.c_str()))
Error(parser.error_, false, false);
include_directories.pop_back();
include_directories.pop_back();
}
std::string (*make_rule)(const flatbuffers::Parser &parser,
const std::string &path,
const std::string &file_name);
};
void FlatCompiler::Warn(const std::string &warn, bool show_exe_name) const {
params_.warn_fn(this, warn, show_exe_name);
}
const Generator generators[] = {
{ flatbuffers::GenerateBinary, "-b", "--binary", "binary",
flatbuffers::IDLOptions::kMAX,
"Generate wire format binaries for any data definitions",
flatbuffers::BinaryMakeRule },
{ flatbuffers::GenerateTextFile, "-t", "--json", "text",
flatbuffers::IDLOptions::kMAX,
"Generate text output for any data definitions",
flatbuffers::TextMakeRule },
{ flatbuffers::GenerateCPP, "-c", "--cpp", "C++",
flatbuffers::IDLOptions::kMAX,
"Generate C++ headers for tables/structs",
flatbuffers::CPPMakeRule },
{ flatbuffers::GenerateGo, "-g", "--go", "Go",
flatbuffers::IDLOptions::kGo,
"Generate Go files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateGeneral, "-j", "--java", "Java",
flatbuffers::IDLOptions::kJava,
"Generate Java classes for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateJS, "-s", "--js", "JavaScript",
flatbuffers::IDLOptions::kMAX,
"Generate JavaScript code for tables/structs",
flatbuffers::JSMakeRule },
{ flatbuffers::GenerateGeneral, "-n", "--csharp", "C#",
flatbuffers::IDLOptions::kCSharp,
"Generate C# classes for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePython, "-p", "--python", "Python",
flatbuffers::IDLOptions::kMAX,
"Generate Python files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePhp, nullptr, "--php", "PHP",
flatbuffers::IDLOptions::kMAX,
"Generate PHP files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateGRPC, nullptr, "--grpc", "GRPC",
flatbuffers::IDLOptions::kMAX,
"Generate GRPC interfaces",
flatbuffers::CPPMakeRule },
};
void FlatCompiler::Error(const std::string &err, bool usage,
bool show_exe_name) const {
params_.error_fn(this, err, usage, show_exe_name);
}
const char *g_program_name = nullptr;
flatbuffers::Parser *g_parser = nullptr;
std::string FlatCompiler::GetUsageString(const char* program_name) const {
std::stringstream ss;
ss << "Usageaa: " << program_name << " [OPTION]... FILE... [-- FILE...]\n";
for (size_t i = 0; i < params_.num_generators; ++i) {
const Generator& g = params_.generators[i];
static void Error(const std::string &err, bool usage, bool show_exe_name) {
if (show_exe_name) printf("%s: ", g_program_name);
printf("%s\n", err.c_str());
if (usage) {
printf("usage: %s [OPTION]... FILE... [-- FILE...]\n", g_program_name);
for (size_t i = 0; i < sizeof(generators) / sizeof(generators[0]); ++i)
printf(" %-12s %s %s.\n",
generators[i].generator_opt_long,
generators[i].generator_opt_short
? generators[i].generator_opt_short
: " ",
generators[i].generator_help);
printf(
std::stringstream full_name;
full_name << std::setw(12) << std::left << g.generator_opt_long;
const char *name = g.generator_opt_short ? g.generator_opt_short : " ";
const char *help = g.generator_help;
ss << " " << full_name.str() << " " << name << " " << help << ".\n";
}
ss <<
" -o PATH Prefix PATH to all generated files.\n"
" -I PATH Search for includes in the specified path.\n"
" -M Print make rules for generated files.\n"
@@ -126,52 +84,51 @@ static void Error(const std::string &err, bool usage, bool show_exe_name) {
" --gen-onefile Generate single output file for C#.\n"
" --gen-name-strings Generate type name functions for C++.\n"
" --escape-proto-ids Disable appending '_' in namespaces names.\n"
" --gen-object-api Generate an additional object-based API\n"
" --gen-object-api Generate an additional object-based API.\n"
" --cpp-ptr-type T Set object API pointer type (default std::unique_ptr)\n"
" --no-js-exports Removes Node.js style export lines in JS.\n"
" --goog-js-export Uses goog.exports* for closure compiler exporting in JS.\n"
" --raw-binary Allow binaries without file_indentifier to be read.\n"
" This may crash flatc given a mismatched schema.\n"
" --proto Input is a .proto, translate to .fbs.\n"
" --grpc Generate GRPC interfaces for the specified languages\n"
" --schema Serialize schemas instead of JSON (use with -b)\n"
" --bfbs-comments Add doc comments to the binary schema files.\n"
" --conform FILE Specify a schema the following schemas should be\n"
" an evolution of. Gives errors if not.\n"
" --conform-includes Include path for the schema given with --conform\n"
" PATH \n"
" --include-prefix Prefix this path to any generated include statements.\n"
" PATH\n"
"FILEs may be schemas, or JSON files (conforming to preceding schema)\n"
"FILEs after the -- must be binary flatbuffer format files.\n"
"Output files are named using the base file name of the input,\n"
"and written to the current directory or the path given by -o.\n"
"example: %s -c -b schema1.fbs schema2.fbs data.json\n",
g_program_name);
"example: " << program_name << " -c -b schema1.fbs schema2.fbs data.json\n";
return ss.str();
}
int FlatCompiler::Compile(int argc, const char** argv) {
if (params_.generators == nullptr || params_.num_generators == 0) {
return 0;
}
if (g_parser) delete g_parser;
exit(1);
}
static void ParseFile(flatbuffers::Parser &parser, const std::string &filename,
const std::string &contents,
std::vector<const char *> &include_directories) {
auto local_include_directory = flatbuffers::StripFileName(filename);
include_directories.push_back(local_include_directory.c_str());
include_directories.push_back(nullptr);
if (!parser.Parse(contents.c_str(), &include_directories[0],
filename.c_str()))
Error(parser.error_, false, false);
include_directories.pop_back();
include_directories.pop_back();
}
int main(int argc, const char *argv[]) {
g_program_name = argv[0];
flatbuffers::IDLOptions opts;
std::string output_path;
const size_t num_generators = sizeof(generators) / sizeof(generators[0]);
bool generator_enabled[num_generators] = { false };
bool any_generator = false;
bool print_make_rules = false;
bool raw_binary = false;
bool schema_binary = false;
bool grpc_enabled = false;
std::vector<std::string> filenames;
std::vector<const char *> include_directories;
std::vector<const char *> conform_include_directories;
std::vector<bool> generator_enabled(params_.num_generators, false);
size_t binary_files_from = std::numeric_limits<size_t>::max();
std::string conform_to_schema;
for (int argi = 1; argi < argc; argi++) {
for (int argi = 0; argi < argc; argi++) {
std::string arg = argv[argi];
if (arg[0] == '-') {
if (filenames.size() && arg[1] != '-')
@@ -185,12 +142,22 @@ int main(int argc, const char *argv[]) {
} else if(arg == "--conform") {
if (++argi >= argc) Error("missing path following" + arg, true);
conform_to_schema = argv[argi];
} else if (arg == "--conform-includes") {
if (++argi >= argc) Error("missing path following" + arg, true);
conform_include_directories.push_back(argv[argi]);
} else if (arg == "--include-prefix") {
if (++argi >= argc) Error("missing path following" + arg, true);
opts.include_prefix = argv[argi];
if (opts.include_prefix.back() != '/' &&
opts.include_prefix.back() != '\\') opts.include_prefix += "/";
} else if(arg == "--strict-json") {
opts.strict_json = true;
} else if(arg == "--allow-non-utf8") {
opts.allow_non_utf8 = true;
} else if(arg == "--no-js-exports") {
opts.skip_js_exports = true;
} else if(arg == "--goog-js-export") {
opts.use_goog_js_export_format = true;
} else if(arg == "--defaults-json") {
opts.output_default_scalars_in_json = true;
} else if (arg == "--unknown-json") {
@@ -208,6 +175,9 @@ int main(int argc, const char *argv[]) {
opts.generate_name_strings = true;
} else if(arg == "--gen-object-api") {
opts.generate_object_based_api = true;
} else if (arg == "--cpp-ptr-type") {
if (++argi >= argc) Error("missing type following" + arg, true);
opts.cpp_object_api_pointer_type = argv[argi];
} else if(arg == "--gen-all") {
opts.generate_all = true;
opts.include_dependence_headers = false;
@@ -233,17 +203,22 @@ int main(int argc, const char *argv[]) {
} else if(arg == "--version") {
printf("flatc version %s\n", FLATC_VERSION);
exit(0);
} else if(arg == "--grpc") {
grpc_enabled = true;
} else if(arg == "--bfbs-comments") {
opts.binary_schema_comments = true;
} else {
for (size_t i = 0; i < num_generators; ++i) {
if (arg == generators[i].generator_opt_long ||
(generators[i].generator_opt_short &&
arg == generators[i].generator_opt_short)) {
for (size_t i = 0; i < params_.num_generators; ++i) {
if (arg == params_.generators[i].generator_opt_long ||
(params_.generators[i].generator_opt_short &&
arg == params_.generators[i].generator_opt_short)) {
generator_enabled[i] = true;
any_generator = true;
opts.lang_to_generate |= params_.generators[i].lang;
goto found;
}
}
Error("unknown commandline argument" + arg, true);
Error("unknown commandline argument: " + arg, true);
found:;
}
} else {
@@ -265,11 +240,12 @@ int main(int argc, const char *argv[]) {
std::string contents;
if (!flatbuffers::LoadFile(conform_to_schema.c_str(), true, &contents))
Error("unable to load schema: " + conform_to_schema);
ParseFile(conform_parser, conform_to_schema, contents, include_directories);
ParseFile(conform_parser, conform_to_schema, contents,
conform_include_directories);
}
// Now process the files:
g_parser = new flatbuffers::Parser(opts);
std::unique_ptr<flatbuffers::Parser> parser(new flatbuffers::Parser(opts));
for (auto file_it = filenames.begin();
file_it != filenames.end();
++file_it) {
@@ -280,8 +256,8 @@ int main(int argc, const char *argv[]) {
bool is_binary = static_cast<size_t>(file_it - filenames.begin()) >=
binary_files_from;
if (is_binary) {
g_parser->builder_.Clear();
g_parser->builder_.PushFlatBuffer(
parser->builder_.Clear();
parser->builder_.PushFlatBuffer(
reinterpret_cast<const uint8_t *>(contents.c_str()),
contents.length());
if (!raw_binary) {
@@ -290,17 +266,17 @@ int main(int argc, const char *argv[]) {
// does not contain a file identifier.
// We'd expect that typically any binary used as a file would have
// such an identifier, so by default we require them to match.
if (!g_parser->file_identifier_.length()) {
if (!parser->file_identifier_.length()) {
Error("current schema has no file_identifier: cannot test if \"" +
*file_it +
"\" matches the schema, use --raw-binary to read this file"
" anyway.");
} else if (!flatbuffers::BufferHasIdentifier(contents.c_str(),
g_parser->file_identifier_.c_str())) {
parser->file_identifier_.c_str())) {
Error("binary \"" +
*file_it +
"\" does not have expected file_identifier \"" +
g_parser->file_identifier_ +
parser->file_identifier_ +
"\", use --raw-binary to read this file anyway.");
}
}
@@ -314,51 +290,62 @@ int main(int argc, const char *argv[]) {
// If we're processing multiple schemas, make sure to start each
// one from scratch. If it depends on previous schemas it must do
// so explicitly using an include.
delete g_parser;
g_parser = new flatbuffers::Parser(opts);
parser.reset(new flatbuffers::Parser(opts));
}
ParseFile(*g_parser, *file_it, contents, include_directories);
ParseFile(*parser.get(), *file_it, contents, include_directories);
if (is_schema && !conform_to_schema.empty()) {
auto err = g_parser->ConformTo(conform_parser);
auto err = parser->ConformTo(conform_parser);
if (!err.empty()) Error("schemas don\'t conform: " + err);
}
if (schema_binary) {
g_parser->Serialize();
g_parser->file_extension_ = reflection::SchemaExtension();
parser->Serialize();
parser->file_extension_ = reflection::SchemaExtension();
}
}
std::string filebase = flatbuffers::StripPath(
flatbuffers::StripExtension(*file_it));
for (size_t i = 0; i < num_generators; ++i) {
g_parser->opts.lang = generators[i].lang;
for (size_t i = 0; i < params_.num_generators; ++i) {
parser->opts.lang = params_.generators[i].lang;
if (generator_enabled[i]) {
if (!print_make_rules) {
flatbuffers::EnsureDirExists(output_path);
if (!generators[i].generate(*g_parser, output_path, filebase)) {
if (!params_.generators[i].generate(*parser.get(), output_path, filebase)) {
Error(std::string("Unable to generate ") +
generators[i].lang_name +
params_.generators[i].lang_name +
" for " +
filebase);
}
} else {
std::string make_rule = generators[i].make_rule(
*g_parser, output_path, *file_it);
std::string make_rule = params_.generators[i].make_rule(
*parser.get(), output_path, *file_it);
if (!make_rule.empty())
printf("%s\n", flatbuffers::WordWrap(
make_rule, 80, " ", " \\").c_str());
}
if (grpc_enabled) {
if (params_.generators[i].generateGRPC != nullptr) {
if (!params_.generators[i].generateGRPC(*parser.get(), output_path,
filebase)) {
Error(std::string("Unable to generate GRPC interface for") +
params_.generators[i].lang_name);
}
} else {
Warn(std::string("GRPC interface generator not implemented for ")
+ params_.generators[i].lang_name);
}
}
}
}
if (opts.proto_mode) GenerateFBS(*g_parser, output_path, filebase);
if (opts.proto_mode) GenerateFBS(*parser.get(), output_path, filebase);
// We do not want to generate code for the definitions in this file
// in any files coming up next.
g_parser->MarkGenerated();
parser->MarkGenerated();
}
delete g_parser;
return 0;
}
} // namespace flatbuffers

104
src/flatc_main.cpp Normal file
View File

@@ -0,0 +1,104 @@
/*
* 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.
*/
#include "flatbuffers/flatc.h"
static const char *g_program_name = nullptr;
static void Warn(const flatbuffers::FlatCompiler *flatc,
const std::string &warn,
bool show_exe_name) {
(void)flatc;
if (show_exe_name) {
printf("%s: ", g_program_name);
}
printf("warning: %s\n", warn.c_str());
}
static void Error(const flatbuffers::FlatCompiler *flatc,
const std::string &err,
bool usage,
bool show_exe_name) {
if (show_exe_name) {
printf("%s: ", g_program_name);
}
printf("error: %s\n", err.c_str());
if (usage) {
printf("%s", flatc->GetUsageString(g_program_name).c_str());
}
exit(1);
}
int main(int argc, const char *argv[]) {
g_program_name = argv[0];
const flatbuffers::FlatCompiler::Generator generators[] = {
{ flatbuffers::GenerateBinary, "-b", "--binary", "binary",
nullptr,
flatbuffers::IDLOptions::kBinary,
"Generate wire format binaries for any data definitions",
flatbuffers::BinaryMakeRule },
{ flatbuffers::GenerateTextFile, "-t", "--json", "text",
nullptr,
flatbuffers::IDLOptions::kJson,
"Generate text output for any data definitions",
flatbuffers::TextMakeRule },
{ flatbuffers::GenerateCPP, "-c", "--cpp", "C++",
flatbuffers::GenerateCppGRPC,
flatbuffers::IDLOptions::kCpp,
"Generate C++ headers for tables/structs",
flatbuffers::CPPMakeRule },
{ flatbuffers::GenerateGo, "-g", "--go", "Go",
flatbuffers::GenerateGoGRPC,
flatbuffers::IDLOptions::kGo,
"Generate Go files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateGeneral, "-j", "--java", "Java",
nullptr,
flatbuffers::IDLOptions::kJava,
"Generate Java classes for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GenerateJS, "-s", "--js", "JavaScript",
nullptr,
flatbuffers::IDLOptions::kJs,
"Generate JavaScript code for tables/structs",
flatbuffers::JSMakeRule },
{ flatbuffers::GenerateGeneral, "-n", "--csharp", "C#",
nullptr,
flatbuffers::IDLOptions::kCSharp,
"Generate C# classes for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePython, "-p", "--python", "Python",
nullptr,
flatbuffers::IDLOptions::kPython,
"Generate Python files for tables/structs",
flatbuffers::GeneralMakeRule },
{ flatbuffers::GeneratePhp, nullptr, "--php", "PHP",
nullptr,
flatbuffers::IDLOptions::kPhp,
"Generate PHP files for tables/structs",
flatbuffers::GeneralMakeRule },
};
flatbuffers::FlatCompiler::InitParams params;
params.generators = generators;
params.num_generators = sizeof(generators) / sizeof(generators[0]);
params.warn_fn = Warn;
params.error_fn = Error;
flatbuffers::FlatCompiler flatc(params);
return flatc.Compile(argc - 1, argv + 1);
}

File diff suppressed because it is too large Load Diff

View File

@@ -19,6 +19,7 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include "flatbuffers/code_generators.h"
namespace flatbuffers {

File diff suppressed because it is too large Load Diff

View File

@@ -144,6 +144,23 @@ static void InitializeExisting(const StructDef &struct_def,
code += "}\n\n";
}
// Implement the table accessor
static void GenTableAccessor(const StructDef &struct_def,
std::string *code_ptr) {
std::string &code = *code_ptr;
GenReceiver(struct_def, code_ptr);
code += " Table() flatbuffers.Table ";
code += "{\n";
if (struct_def.fixed) {
code += "\treturn rcv._tab.Table\n";
} else {
code += "\treturn rcv._tab\n";
}
code += "}\n\n";
}
// Get the length of a vector.
static void GetVectorLen(const StructDef &struct_def,
const FieldDef &field,
@@ -288,9 +305,6 @@ static void GetMemberOfVectorOfStruct(const StructDef &struct_def,
if (!(vectortype.struct_def->fixed)) {
code += "\t\tx = rcv._tab.Indirect(x)\n";
}
code += "\t\tif obj == nil {\n";
code += "\t\t\tobj = new(" + TypeName(field) + ")\n";
code += "\t\t}\n";
code += "\t\tobj.Init(rcv._tab.Bytes, x)\n";
code += "\t\treturn true\n\t}\n";
code += "\treturn false\n";
@@ -594,6 +608,10 @@ static void GenStruct(const StructDef &struct_def,
// Generate the Init method that sets the field in a pre-existing
// accessor object. This is to allow object reuse.
InitializeExisting(struct_def, code_ptr);
// Generate _tab accessor
GenTableAccessor(struct_def, code_ptr);
// Generate struct fields accessors
for (auto it = struct_def.fields.vec.begin();
it != struct_def.fields.vec.end();
++it) {
@@ -604,6 +622,7 @@ static void GenStruct(const StructDef &struct_def,
GenStructMutator(struct_def, field, code_ptr);
}
// Generate builders
if (struct_def.fixed) {
// create a struct constructor function
GenStructBuilder(struct_def, code_ptr);

View File

@@ -19,12 +19,14 @@
#include "flatbuffers/flatbuffers.h"
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
#include "flatbuffers/code_generators.h"
#include "src/compiler/cpp_generator.h"
#include "src/compiler/go_generator.h"
namespace flatbuffers {
class FlatBufMethod : public grpc_cpp_generator::Method {
class FlatBufMethod : public grpc_generator::Method {
public:
enum Streaming { kNone, kClient, kServer, kBiDi };
@@ -52,6 +54,14 @@ class FlatBufMethod : public grpc_cpp_generator::Method {
return GRPCType(*method_->response);
}
std::string input_name() const {
return (*method_->request).name;
}
std::string output_name() const {
return (*method_->response).name;
}
bool NoStreaming() const { return streaming_ == kNone; }
bool ClientOnlyStreaming() const { return streaming_ == kClient; }
bool ServerOnlyStreaming() const { return streaming_ == kServer; }
@@ -62,7 +72,7 @@ class FlatBufMethod : public grpc_cpp_generator::Method {
Streaming streaming_;
};
class FlatBufService : public grpc_cpp_generator::Service {
class FlatBufService : public grpc_generator::Service {
public:
FlatBufService(const ServiceDef *service) : service_(service) {}
@@ -72,8 +82,8 @@ class FlatBufService : public grpc_cpp_generator::Service {
return static_cast<int>(service_->calls.vec.size());
};
std::unique_ptr<const grpc_cpp_generator::Method> method(int i) const {
return std::unique_ptr<const grpc_cpp_generator::Method>(
std::unique_ptr<const grpc_generator::Method> method(int i) const {
return std::unique_ptr<const grpc_generator::Method>(
new FlatBufMethod(service_->calls.vec[i]));
};
@@ -81,7 +91,7 @@ class FlatBufService : public grpc_cpp_generator::Service {
const ServiceDef *service_;
};
class FlatBufPrinter : public grpc_cpp_generator::Printer {
class FlatBufPrinter : public grpc_generator::Printer {
public:
FlatBufPrinter(std::string *str)
: str_(str), escape_char_('$'), indent_(0) {}
@@ -133,7 +143,7 @@ class FlatBufPrinter : public grpc_cpp_generator::Printer {
int indent_;
};
class FlatBufFile : public grpc_cpp_generator::File {
class FlatBufFile : public grpc_generator::File {
public:
FlatBufFile(const Parser &parser, const std::string &file_name)
: parser_(parser), file_name_(file_name) {}
@@ -159,17 +169,21 @@ class FlatBufFile : public grpc_cpp_generator::File {
return "#include \"flatbuffers/grpc.h\"\n";
}
std::string additional_imports() const {
return "import \"github.com/google/flatbuffers/go\"";
}
int service_count() const {
return static_cast<int>(parser_.services_.vec.size());
};
std::unique_ptr<const grpc_cpp_generator::Service> service(int i) const {
return std::unique_ptr<const grpc_cpp_generator::Service> (
std::unique_ptr<const grpc_generator::Service> service(int i) const {
return std::unique_ptr<const grpc_generator::Service> (
new FlatBufService(parser_.services_.vec[i]));
}
std::unique_ptr<grpc_cpp_generator::Printer> CreatePrinter(std::string *str) const {
return std::unique_ptr<grpc_cpp_generator::Printer>(
std::unique_ptr<grpc_generator::Printer> CreatePrinter(std::string *str) const {
return std::unique_ptr<grpc_generator::Printer>(
new FlatBufPrinter(str));
}
@@ -178,7 +192,47 @@ class FlatBufFile : public grpc_cpp_generator::File {
const std::string &file_name_;
};
bool GenerateGRPC(const Parser &parser,
class GoGRPCGenerator : public flatbuffers::BaseGenerator {
public:
GoGRPCGenerator(const Parser &parser, const std::string &path,
const std::string &file_name)
: BaseGenerator(parser, path, file_name, "", "" /*Unused*/),
parser_(parser), path_(path), file_name_(file_name) {}
bool generate() {
FlatBufFile file(parser_, file_name_);
grpc_go_generator::Parameters p;
p.custom_method_io_type = "flatbuffers.Builder";
for (int i = 0; i < file.service_count(); i++) {
auto service = file.service(i);
const Definition *def = parser_.services_.vec[i];
p.package_name = LastNamespacePart(*(def->defined_namespace));
std::string output = grpc_go_generator::GenerateServiceSource(&file, service.get(), &p);
std::string filename = NamespaceDir(*def->defined_namespace) + def->name + "_grpc.go";
if (!flatbuffers::SaveFile(filename.c_str(), output, false))
return false;
}
return true;
}
protected:
const Parser &parser_;
const std::string &path_, &file_name_;
};
bool GenerateGoGRPC(const Parser &parser,
const std::string &path,
const std::string &file_name) {
int nservices = 0;
for (auto it = parser.services_.vec.begin();
it != parser.services_.vec.end(); ++it) {
if (!(*it)->generated) nservices++;
}
if (!nservices) return true;
return GoGRPCGenerator(parser, path, file_name).generate();
}
bool GenerateCppGRPC(const Parser &parser,
const std::string &/*path*/,
const std::string &file_name) {

View File

@@ -113,7 +113,11 @@ class JsGenerator : public BaseGenerator {
code += "/**\n * @const\n * @namespace\n */\n";
if (it->find('.') == std::string::npos) {
code += "var ";
exports += "this." + *it + " = " + *it + ";\n";
if(parser_.opts.use_goog_js_export_format) {
exports += "goog.exportSymbol('" + *it + "', " + *it + ");\n";
} else {
exports += "this." + *it + " = " + *it + ";\n";
}
}
code += *it + " = " + *it + " || {};\n\n";
}
@@ -172,7 +176,12 @@ void GenEnum(EnumDef &enum_def, std::string *code_ptr,
GenDocComment(enum_def.doc_comment, code_ptr, "@enum");
if (enum_def.defined_namespace->components.empty()) {
code += "var ";
exports += "this." + enum_def.name + " = " + enum_def.name + ";\n";
if(parser_.opts.use_goog_js_export_format) {
exports += "goog.exportSymbol('" + enum_def.name + "', " + enum_def.name +
");\n";
} else {
exports += "this." + enum_def.name + " = " + enum_def.name + ";\n";
}
}
code += WrapInNameSpace(enum_def) + " = {\n";
for (auto it = enum_def.vals.vec.begin();
@@ -236,6 +245,9 @@ std::string GenDefaultValue(const Value &value, const std::string &context) {
if (auto val = value.type.enum_def->ReverseLookup(
atoi(value.constant.c_str()), false)) {
return WrapInNameSpace(*value.type.enum_def) + "." + val->name;
} else {
return "/** @type {" + WrapInNameSpace(*value.type.enum_def) + "} */ ("
+ value.constant + ")";
}
}
@@ -371,7 +383,12 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
std::string object_name = WrapInNameSpace(struct_def);
GenDocComment(struct_def.doc_comment, code_ptr, "@constructor");
if (isStatement) {
exports += "this." + struct_def.name + " = " + struct_def.name + ";\n";
if(parser_.opts.use_goog_js_export_format) {
exports += "goog.exportSymbol('" + struct_def.name + "', " +
struct_def.name + ");\n";
} else {
exports += "this." + struct_def.name + " = " + struct_def.name + ";\n";
}
code += "function " + object_name;
} else {
code += object_name + " = function";
@@ -526,7 +543,13 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
field.value.type.element == BASE_TYPE_ULONG) {
code += "this.bb.createLong(0, 0)";
} else if (IsScalar(field.value.type.element)) {
code += "0";
if (field.value.type.enum_def) {
code += "/** @type {" +
WrapInNameSpace(*field.value.type.enum_def) + "} */ (" +
field.value.constant + ")";
} else {
code += "0";
}
} else {
code += "null";
}
@@ -550,6 +573,12 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
}
code += "};\n\n";
if(parser_.opts.use_goog_js_export_format) {
exports += "goog.exportProperty(" + object_name + ".prototype, '" +
MakeCamel(field.name, false) + "', " + object_name + ".prototype." +
MakeCamel(field.name, false) + ");\n";
}
// Adds the mutable scalar value to the output
if (IsScalar(field.value.type.base_type) && parser.opts.mutable_buffer) {
std::string annotations = "@param {" + GenTypeName(field.value.type, true) + "} value\n";
@@ -557,13 +586,19 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
"@returns {boolean}");
code += object_name + ".prototype.mutate_" + field.name + " = function(value) {\n";
code += " var offset = this.bb.__offset(this.bb_pos, " + NumToString(field.value.offset) + ")\n\n";
code += " var offset = this.bb.__offset(this.bb_pos, " + NumToString(field.value.offset) + ");\n\n";
code += " if (offset === 0) {\n";
code += " return false;\n";
code += " }\n\n";
code += " this.bb.write" + MakeCamel(GenType(field.value.type)) + "(this.bb_pos + offset, value);\n";
code += " return true;\n";
code += "}\n\n";
code += "};\n\n";
if(parser_.opts.use_goog_js_export_format) {
exports += "goog.exportProperty(" + object_name +
".prototype, 'mutate_" + field.name + "', " + object_name +
".prototype.mutate_" + field.name + ");\n";
}
}
// Emit vector helpers
@@ -574,15 +609,27 @@ void GenStruct(const Parser &parser, StructDef &struct_def, std::string *code_pt
code += "Length = function() {\n" + offset_prefix;
code += "this.bb.__vector_len(this.bb_pos + offset) : 0;\n};\n\n";
if(parser_.opts.use_goog_js_export_format) {
exports += "goog.exportProperty(" + object_name + ".prototype, '" +
MakeCamel(field.name, false) + "Length', " + object_name +
".prototype." + MakeCamel(field.name, false) + "Length);\n";
}
// For scalar types, emit a typed array helper
auto vectorType = field.value.type.VectorType();
if (IsScalar(vectorType.base_type)) {
if (IsScalar(vectorType.base_type) && !IsLong(vectorType.base_type)) {
GenDocComment(code_ptr, "@returns {" + GenType(vectorType) + "Array}");
code += object_name + ".prototype." + MakeCamel(field.name, false);
code += "Array = function() {\n" + offset_prefix;
code += "new " + GenType(vectorType) + "Array(this.bb.bytes().buffer, "
"this.bb.__vector(this.bb_pos + offset), "
"this.bb.bytes().byteOffset + this.bb.__vector(this.bb_pos + offset), "
"this.bb.__vector_len(this.bb_pos + offset)) : null;\n};\n\n";
if(parser_.opts.use_goog_js_export_format) {
exports += "goog.exportProperty(" + object_name + ".prototype, '" +
MakeCamel(field.name, false) + "Array', " + object_name +
".prototype." + MakeCamel(field.name, false) + "Array);\n";
}
}
}
}

View File

@@ -89,10 +89,10 @@ namespace php {
code += classcode;
std::string filename = NamespaceDir(*def.defined_namespace) +
kPathSeparator + def.name + ".php";
def.name + ".php";
return SaveFile(filename.c_str(), code, false);
}
// Begin a class declaration.
static void BeginClass(const StructDef &struct_def, std::string *code_ptr) {
std::string &code = *code_ptr;
@@ -955,7 +955,7 @@ namespace php {
code += Indent + Indent + "return $builder->offset();\n";
code += Indent + "}\n";
}
};
} // namespace php

View File

@@ -655,7 +655,7 @@ class PythonGenerator : public BaseGenerator {
BeginFile(LastNamespacePart(*def.defined_namespace), needs_imports, &code);
code += classcode;
std::string filename = NamespaceDir(*def.defined_namespace) +
kPathSeparator + def.name + ".py";
def.name + ".py";
return SaveFile(filename.c_str(), code, false);
}
};

View File

@@ -22,7 +22,7 @@
namespace flatbuffers {
static void GenStruct(const StructDef &struct_def, const Table *table,
static bool GenStruct(const StructDef &struct_def, const Table *table,
int indent, const IDLOptions &opts,
std::string *_text);
@@ -48,7 +48,7 @@ void OutputIdentifier(const std::string &name, const IDLOptions &opts,
// Print (and its template specialization below for pointers) generate text
// for a single FlatBuffer value into JSON format.
// The general case for scalars:
template<typename T> void Print(T val, Type type, int /*indent*/,
template<typename T> bool Print(T val, Type type, int /*indent*/,
StructDef * /*union_sd*/,
const IDLOptions &opts,
std::string *_text) {
@@ -57,7 +57,7 @@ template<typename T> void Print(T val, Type type, int /*indent*/,
auto enum_val = type.enum_def->ReverseLookup(static_cast<int>(val));
if (enum_val) {
OutputIdentifier(enum_val->name, opts, _text);
return;
return true;
}
}
@@ -66,10 +66,12 @@ template<typename T> void Print(T val, Type type, int /*indent*/,
} else {
text += NumToString(val);
}
return true;
}
// Print a vector a sequence of JSON values, comma separated, wrapped in "[]".
template<typename T> void PrintVector(const Vector<T> &v, Type type,
template<typename T> bool PrintVector(const Vector<T> &v, Type type,
int indent, const IDLOptions &opts,
std::string *_text) {
std::string &text = *_text;
@@ -81,19 +83,25 @@ template<typename T> void PrintVector(const Vector<T> &v, Type type,
text += NewLine(opts);
}
text.append(indent + Indent(opts), ' ');
if (IsStruct(type))
Print(v.GetStructFromOffset(i * type.struct_def->bytesize), type,
indent + Indent(opts), nullptr, opts, _text);
else
Print(v[i], type, indent + Indent(opts), nullptr,
opts, _text);
if (IsStruct(type)) {
if (!Print(v.GetStructFromOffset(i * type.struct_def->bytesize), type,
indent + Indent(opts), nullptr, opts, _text)) {
return false;
}
} else {
if (!Print(v[i], type, indent + Indent(opts), nullptr,
opts, _text)) {
return false;
}
}
}
text += NewLine(opts);
text.append(indent, ' ');
text += "]";
return true;
}
static void EscapeString(const String &s, std::string *_text, const IDLOptions& opts) {
static bool EscapeString(const String &s, std::string *_text, const IDLOptions& opts) {
std::string &text = *_text;
text += "\"";
for (uoffset_t i = 0; i < s.size(); i++) {
@@ -118,9 +126,19 @@ static void EscapeString(const String &s, std::string *_text, const IDLOptions&
text += "\\x";
text += IntToStringHex(static_cast<uint8_t>(c), 2);
} else {
// We previously checked for non-UTF-8 and returned a parse error,
// so we shouldn't reach here.
assert(0);
// There are two cases here:
//
// 1) We reached here by parsing an IDL file. In that case,
// we previously checked for non-UTF-8, so we shouldn't reach
// here.
//
// 2) We reached here by someone calling GenerateText()
// on a previously-serialized flatbuffer. The data might have
// non-UTF-8 Strings, or might be corrupt.
//
// In both cases, we have to give up and inform the caller
// they have no JSON.
return false;
}
} else {
if (ucc <= 0xFFFF) {
@@ -130,12 +148,12 @@ static void EscapeString(const String &s, std::string *_text, const IDLOptions&
} else if (ucc <= 0x10FFFF) {
// Encode Unicode SMP values to a surrogate pair using two \u escapes.
uint32_t base = ucc - 0x10000;
uint16_t highSurrogate = (base >> 10) + 0xD800;
uint16_t lowSurrogate = (base & 0x03FF) + 0xDC00;
auto high_surrogate = (base >> 10) + 0xD800;
auto low_surrogate = (base & 0x03FF) + 0xDC00;
text += "\\u";
text += IntToStringHex(highSurrogate, 4);
text += IntToStringHex(high_surrogate, 4);
text += "\\u";
text += IntToStringHex(lowSurrogate, 4);
text += IntToStringHex(low_surrogate, 4);
}
// Skip past characters recognized.
i = static_cast<uoffset_t>(utf8 - s.c_str() - 1);
@@ -145,10 +163,11 @@ static void EscapeString(const String &s, std::string *_text, const IDLOptions&
}
}
text += "\"";
return true;
}
// Specialization of Print above for pointer types.
template<> void Print<const void *>(const void *val,
template<> bool Print<const void *>(const void *val,
Type type, int indent,
StructDef *union_sd,
const IDLOptions &opts,
@@ -158,21 +177,27 @@ template<> void Print<const void *>(const void *val,
// If this assert hits, you have an corrupt buffer, a union type field
// was not present or was out of range.
assert(union_sd);
GenStruct(*union_sd,
reinterpret_cast<const Table *>(val),
indent,
opts,
_text);
if (!GenStruct(*union_sd,
reinterpret_cast<const Table *>(val),
indent,
opts,
_text)) {
return false;
}
break;
case BASE_TYPE_STRUCT:
GenStruct(*type.struct_def,
reinterpret_cast<const Table *>(val),
indent,
opts,
_text);
if (!GenStruct(*type.struct_def,
reinterpret_cast<const Table *>(val),
indent,
opts,
_text)) {
return false;
}
break;
case BASE_TYPE_STRING: {
EscapeString(*reinterpret_cast<const String *>(val), _text, opts);
if (!EscapeString(*reinterpret_cast<const String *>(val), _text, opts)) {
return false;
}
break;
}
case BASE_TYPE_VECTOR:
@@ -182,31 +207,35 @@ template<> void Print<const void *>(const void *val,
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \
PTYPE) \
case BASE_TYPE_ ## ENUM: \
PrintVector<CTYPE>( \
*reinterpret_cast<const Vector<CTYPE> *>(val), \
type, indent, opts, _text); break;
if (!PrintVector<CTYPE>( \
*reinterpret_cast<const Vector<CTYPE> *>(val), \
type, indent, opts, _text)) { \
return false; \
} \
break;
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
}
break;
default: assert(0);
}
return true;
}
// Generate text for a scalar field.
template<typename T> static void GenField(const FieldDef &fd,
template<typename T> static bool GenField(const FieldDef &fd,
const Table *table, bool fixed,
const IDLOptions &opts,
int indent,
std::string *_text) {
Print(fixed ?
return Print(fixed ?
reinterpret_cast<const Struct *>(table)->GetField<T>(fd.value.offset) :
table->GetField<T>(fd.value.offset, 0), fd.value.type, indent, nullptr,
opts, _text);
}
// Generate text for non-scalar field.
static void GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
static bool GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
int indent, StructDef *union_sd,
const IDLOptions &opts, std::string *_text) {
const void *val = nullptr;
@@ -220,12 +249,12 @@ static void GenFieldOffset(const FieldDef &fd, const Table *table, bool fixed,
? table->GetStruct<const void *>(fd.value.offset)
: table->GetPointer<const void *>(fd.value.offset);
}
Print(val, fd.value.type, indent, union_sd, opts, _text);
return Print(val, fd.value.type, indent, union_sd, opts, _text);
}
// Generate text for a struct or table, values separated by commas, indented,
// and bracketed by "{}"
static void GenStruct(const StructDef &struct_def, const Table *table,
static bool GenStruct(const StructDef &struct_def, const Table *table,
int indent, const IDLOptions &opts,
std::string *_text) {
std::string &text = *_text;
@@ -253,8 +282,10 @@ static void GenStruct(const StructDef &struct_def, const Table *table,
#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \
PTYPE) \
case BASE_TYPE_ ## ENUM: \
GenField<CTYPE>(fd, table, struct_def.fixed, \
opts, indent + Indent(opts), _text); \
if (!GenField<CTYPE>(fd, table, struct_def.fixed, \
opts, indent + Indent(opts), _text)) { \
return false; \
} \
break;
FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
@@ -264,8 +295,10 @@ static void GenStruct(const StructDef &struct_def, const Table *table,
case BASE_TYPE_ ## ENUM:
FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts),
union_sd, opts, _text);
if (!GenFieldOffset(fd, table, struct_def.fixed, indent + Indent(opts),
union_sd, opts, _text)) {
return false;
}
break;
}
if (fd.value.type.base_type == BASE_TYPE_UTYPE) {
@@ -284,20 +317,24 @@ static void GenStruct(const StructDef &struct_def, const Table *table,
text += NewLine(opts);
text.append(indent, ' ');
text += "}";
return true;
}
// Generate a text representation of a flatbuffer in JSON format.
void GenerateText(const Parser &parser, const void *flatbuffer,
bool GenerateText(const Parser &parser, const void *flatbuffer,
std::string *_text) {
std::string &text = *_text;
assert(parser.root_struct_def_); // call SetRootType()
text.reserve(1024); // Reduce amount of inevitable reallocs.
GenStruct(*parser.root_struct_def_,
GetRoot<Table>(flatbuffer),
0,
parser.opts,
_text);
if (!GenStruct(*parser.root_struct_def_,
GetRoot<Table>(flatbuffer),
0,
parser.opts,
_text)) {
return false;
}
text += NewLine(parser.opts);
return true;
}
std::string TextFileName(const std::string &path,
@@ -310,7 +347,9 @@ bool GenerateTextFile(const Parser &parser,
const std::string &file_name) {
if (!parser.builder_.GetSize() || !parser.root_struct_def_) return true;
std::string text;
GenerateText(parser, parser.builder_.GetBufferPointer(), &text);
if (!GenerateText(parser, parser.builder_.GetBufferPointer(), &text)) {
return false;
}
return flatbuffers::SaveFile(TextFileName(path, file_name).c_str(),
text,
false);

View File

@@ -109,6 +109,12 @@ template<typename T> inline CheckedError atot(const char *s, Parser &parser,
*val = (T)i;
return NoError();
}
template<> inline CheckedError atot<uint64_t>(const char *s, Parser &parser,
uint64_t *val) {
(void)parser;
*val = StringToUInt(s);
return NoError();
}
template<> inline CheckedError atot<bool>(const char *s, Parser &parser,
bool *val) {
(void)parser;
@@ -149,8 +155,7 @@ std::string Namespace::GetFullyQualifiedName(const std::string &name,
}
stream << components[i];
}
stream << "." << name;
if (name.length()) stream << "." << name;
return stream.str();
}
@@ -175,7 +180,8 @@ std::string Namespace::GetFullyQualifiedName(const std::string &name,
TD(Include, 269, "include") \
TD(Attribute, 270, "attribute") \
TD(Null, 271, "null") \
TD(Service, 272, "rpc_service")
TD(Service, 272, "rpc_service") \
TD(NativeInclude, 273, "native_include")
#ifdef __GNUC__
__extension__ // Stop GCC complaining about trailing comma with -Wpendantic.
#endif
@@ -213,13 +219,13 @@ std::string Parser::TokenToStringId(int t) {
}
// Parses exactly nibbles worth of hex digits into a number, or error.
CheckedError Parser::ParseHexNum(int nibbles, int64_t *val) {
CheckedError Parser::ParseHexNum(int nibbles, uint64_t *val) {
for (int i = 0; i < nibbles; i++)
if (!isxdigit(static_cast<const unsigned char>(cursor_[i])))
return Error("escape code must be followed by " + NumToString(nibbles) +
" hex digits");
std::string target(cursor_, cursor_ + nibbles);
*val = StringToUInt(target.c_str(), 16);
*val = StringToUInt(target.c_str(), nullptr, 16);
cursor_ += nibbles;
return NoError();
}
@@ -280,14 +286,14 @@ CheckedError Parser::Next() {
case '/': attribute_ += '/'; cursor_++; break;
case 'x': { // Not in the JSON standard
cursor_++;
int64_t val;
uint64_t val;
ECHECK(ParseHexNum(2, &val));
attribute_ += static_cast<char>(val);
break;
}
case 'u': {
cursor_++;
int64_t val;
uint64_t val;
ECHECK(ParseHexNum(4, &val));
if (val >= 0xD800 && val <= 0xDBFF) {
if (unicode_high_surrogate != -1) {
@@ -352,6 +358,7 @@ CheckedError Parser::Next() {
cursor_++;
// TODO: make nested.
while (*cursor_ != '*' || cursor_[1] != '/') {
if (*cursor_ == '\n') line_++;
if (!*cursor_) return Error("end of file in comment");
cursor_++;
}
@@ -432,12 +439,17 @@ CheckedError Parser::Next() {
token_ = kTokenService;
return NoError();
}
if (attribute_ == "native_include") {
token_ = kTokenNativeInclude;
return NoError();
}
// If not, it is a user-defined identifier:
token_ = kTokenIdentifier;
return NoError();
} else if (isdigit(static_cast<unsigned char>(c)) || c == '-') {
const char *start = cursor_ - 1;
if (c == '-' && *cursor_ == '0' && (cursor_[1] == 'x' || cursor_[1] == 'X')) {
if (c == '-' && *cursor_ == '0' &&
(cursor_[1] == 'x' || cursor_[1] == 'X')) {
++start;
++cursor_;
attribute_.append(&c, &c + 1);
@@ -447,7 +459,8 @@ CheckedError Parser::Next() {
cursor_++;
while (isxdigit(static_cast<unsigned char>(*cursor_))) cursor_++;
attribute_.append(start + 2, cursor_);
attribute_ = NumToString(StringToUInt(attribute_.c_str(), 16));
attribute_ = NumToString(static_cast<int64_t>(
StringToUInt(attribute_.c_str(), nullptr, 16)));
token_ = kTokenIntegerConstant;
return NoError();
}
@@ -549,12 +562,6 @@ CheckedError Parser::ParseType(Type &type) {
return Error(
"nested vector types not supported (wrap in table first).");
}
if (subtype.base_type == BASE_TYPE_UNION) {
// We could support this if we stored a struct of 2 elements per
// union element.
return Error(
"vector of union types not supported (wrap in table first).");
}
type = Type(BASE_TYPE_VECTOR, subtype.struct_def, subtype.enum_def);
type.element = subtype.base_type;
EXPECT(']');
@@ -606,6 +613,19 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
// with a special suffix.
ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(),
type.enum_def->underlying_type, &typefield));
} else if (type.base_type == BASE_TYPE_VECTOR &&
type.element == BASE_TYPE_UNION) {
// Only cpp supports the union vector feature so far.
if (opts.lang_to_generate != IDLOptions::kCpp) {
return Error("Vectors of unions are not yet supported in all "
"the specified programming languages.");
}
// For vector of union fields, add a second auto-generated vector field to
// hold the types, with a special suffix.
Type union_vector(BASE_TYPE_VECTOR, nullptr, type.enum_def);
union_vector.element = BASE_TYPE_UTYPE;
ECHECK(AddField(struct_def, name + UnionTypeFieldSuffix(),
union_vector, &typefield));
}
FieldDef *field;
@@ -657,6 +677,11 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
"only int, uint, long and ulong data types support hashing.");
}
}
auto cpp_type = field->attributes.Lookup("cpp_type");
if (cpp_type) {
if (!hash_name)
return Error("cpp_type can only be used with a hashed field");
}
if (field->deprecated && struct_def.fixed)
return Error("can't deprecate fields in a struct");
field->required = field->attributes.Lookup("required") != nullptr;
@@ -674,6 +699,11 @@ CheckedError Parser::ParseField(StructDef &struct_def) {
return Error("'key' field must be string or scalar type");
}
}
field->native_inline = field->attributes.Lookup("native_inline") != nullptr;
if (field->native_inline && !IsStruct(field->value.type))
return Error("native_inline can only be defined on structs'");
auto nested = field->attributes.Lookup("nested_flatbuffer");
if (nested) {
if (nested->type.base_type != BASE_TYPE_STRING)
@@ -712,8 +742,17 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
case BASE_TYPE_UNION: {
assert(field);
std::string constant;
if (!parent_fieldn ||
field_stack_.back().second->value.type.base_type != BASE_TYPE_UTYPE) {
// Find corresponding type field we may have already parsed.
for (auto elem = field_stack_.rbegin();
elem != field_stack_.rbegin() + parent_fieldn; ++elem) {
auto &type = elem->second->value.type;
if (type.base_type == BASE_TYPE_UTYPE &&
type.enum_def == val.type.enum_def) {
constant = elem->first.constant;
break;
}
}
if (constant.empty()) {
// We haven't seen the type field yet. Sadly a lot of JSON writers
// output these in alphabetical order, meaning it comes after this
// value. So we scan past the value to find it, then come back here.
@@ -740,8 +779,6 @@ CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
constant = type_val.constant;
// Got the information we needed, now rewind:
*static_cast<ParserState *>(this) = backup;
} else {
constant = field_stack_.back().first.constant;
}
uint8_t enum_idx;
ECHECK(atot(constant.c_str(), *this, &enum_idx));
@@ -820,16 +857,18 @@ CheckedError Parser::ParseTable(const StructDef &struct_def, std::string *value,
} else {
Value val = field->value;
ECHECK(ParseAnyValue(val, field, fieldn, &struct_def));
size_t i = field_stack_.size();
// Hardcoded insertion-sort with error-check.
// If fields are specified in order, then this loop exits immediately.
for (; i > field_stack_.size() - fieldn; i--) {
auto existing_field = field_stack_[i - 1].second;
auto elem = field_stack_.rbegin();
for (; elem != field_stack_.rbegin() + fieldn; ++elem) {
auto existing_field = elem->second;
if (existing_field == field)
return Error("field set more than once: " + field->name);
if (existing_field->value.offset < field->value.offset) break;
}
field_stack_.insert(field_stack_.begin() + i, std::make_pair(val, field));
// Note: elem points to before the insertion point, thus .base() points
// to the correct spot.
field_stack_.insert(elem.base(), std::make_pair(val, field));
fieldn++;
}
}
@@ -1093,10 +1132,15 @@ CheckedError Parser::ParseSingleValue(Value &e) {
NEXT();
} else { // Numeric constant in string.
if (IsInteger(e.type.base_type)) {
// TODO(wvo): do we want to check for garbage after the number?
e.constant = NumToString(StringToInt(attribute_.c_str()));
char *end;
e.constant = NumToString(StringToInt(attribute_.c_str(), &end));
if (*end)
return Error("invalid integer: " + attribute_);
} else if (IsFloat(e.type.base_type)) {
e.constant = NumToString(strtod(attribute_.c_str(), nullptr));
char *end;
e.constant = NumToString(strtod(attribute_.c_str(), &end));
if (*end)
return Error("invalid float: " + attribute_);
} else {
assert(0); // Shouldn't happen, we covered all types.
e.constant = "0";
@@ -1278,6 +1322,8 @@ CheckedError Parser::ParseEnum(bool is_union, EnumDef **dest) {
}
}
if (dest) *dest = &enum_def;
types_.Add(namespaces_.back()->GetFullyQualifiedName(enum_def.name),
new Type(BASE_TYPE_UNION, nullptr, &enum_def));
return NoError();
}
@@ -1341,10 +1387,11 @@ CheckedError Parser::ParseDecl() {
auto align = static_cast<size_t>(atoi(force_align->constant.c_str()));
if (force_align->type.base_type != BASE_TYPE_INT ||
align < struct_def->minalign ||
align > 16 ||
align > FLATBUFFERS_MAX_ALIGNMENT ||
align & (align - 1))
return Error("force_align must be a power of two integer ranging from the"
"struct\'s natural alignment to 16");
"struct\'s natural alignment to " +
NumToString(FLATBUFFERS_MAX_ALIGNMENT));
struct_def->minalign = align;
}
struct_def->PadLastField(struct_def->minalign);
@@ -1382,6 +1429,8 @@ CheckedError Parser::ParseDecl() {
ECHECK(CheckClash(fields, struct_def, "_byte_vector", BASE_TYPE_STRING));
ECHECK(CheckClash(fields, struct_def, "ByteVector", BASE_TYPE_STRING));
EXPECT('}');
types_.Add(namespaces_.back()->GetFullyQualifiedName(struct_def->name),
new Type(BASE_TYPE_STRUCT, struct_def, nullptr));
return NoError();
}
@@ -1819,6 +1868,7 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
source_ = cursor_ = source;
line_ = 1;
error_.clear();
field_stack_.clear();
builder_.Clear();
// Start with a blank namespace just in case this file doesn't have one.
namespaces_.push_back(new Namespace());
@@ -1831,6 +1881,10 @@ CheckedError Parser::DoParse(const char *source, const char **include_paths,
(attribute_ == "option" || attribute_ == "syntax" ||
attribute_ == "package")) {
ECHECK(ParseProtoDecl());
} else if (Is(kTokenNativeInclude)) {
NEXT();
native_included_files_.emplace_back(attribute_);
EXPECT(kTokenStringConstant);
} else if (Is(kTokenInclude) ||
(opts.proto_mode &&
attribute_ == "import" &&
@@ -1977,7 +2031,8 @@ std::set<std::string> Parser::GetIncludedFilesRecursive(
// Schema serialization functionality:
template<typename T> bool compareName(const T* a, const T* b) {
return a->name < b->name;
return a->defined_namespace->GetFullyQualifiedName(a->name)
< b->defined_namespace->GetFullyQualifiedName(b->name);
}
template<typename T> void AssignIndices(const std::vector<T *> &defvec) {
@@ -2023,14 +2078,19 @@ Offset<reflection::Object> StructDef::Serialize(FlatBufferBuilder *builder,
(*it)->Serialize(builder,
static_cast<uint16_t>(it - fields.vec.begin()), parser));
}
auto qualified_name = defined_namespace->GetFullyQualifiedName(name);
return reflection::CreateObject(*builder,
builder->CreateString(name),
builder->CreateString(qualified_name),
builder->CreateVectorOfSortedTables(
&field_offsets),
fixed,
static_cast<int>(minalign),
static_cast<int>(bytesize),
SerializeAttributes(builder, parser));
SerializeAttributes(builder, parser),
parser.opts.binary_schema_comments
? builder->CreateVectorOfStrings(
doc_comment)
: 0);
}
Offset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder,
@@ -2050,7 +2110,10 @@ Offset<reflection::Field> FieldDef::Serialize(FlatBufferBuilder *builder,
deprecated,
required,
key,
SerializeAttributes(builder, parser));
SerializeAttributes(builder, parser),
parser.opts.binary_schema_comments
? builder->CreateVectorOfStrings(doc_comment)
: 0);
// TODO: value.constant is almost always "0", we could save quite a bit of
// space by sharing it. Same for common values of value.type.
}
@@ -2061,12 +2124,16 @@ Offset<reflection::Enum> EnumDef::Serialize(FlatBufferBuilder *builder,
for (auto it = vals.vec.begin(); it != vals.vec.end(); ++it) {
enumval_offsets.push_back((*it)->Serialize(builder));
}
auto qualified_name = defined_namespace->GetFullyQualifiedName(name);
return reflection::CreateEnum(*builder,
builder->CreateString(name),
builder->CreateString(qualified_name),
builder->CreateVector(enumval_offsets),
is_union,
underlying_type.Serialize(builder),
SerializeAttributes(builder, parser));
SerializeAttributes(builder, parser),
parser.opts.binary_schema_comments
? builder->CreateVectorOfStrings(doc_comment)
: 0);
}
Offset<reflection::EnumVal> EnumVal::Serialize(FlatBufferBuilder *builder) const

View File

@@ -180,7 +180,8 @@ class ResizeContext {
// Check if the range between first (lower address) and second straddles
// the insertion point. If it does, change the offset at offsetloc (of
// type T, with direction D).
template<typename T, int D> void Straddle(void *first, void *second,
template<typename T, int D> void Straddle(const void *first,
const void *second,
void *offsetloc) {
if (first <= startptr_ && second >= startptr_) {
WriteScalar<T>(offsetloc, ReadScalar<T>(offsetloc) + delta_ * D);
@@ -194,9 +195,9 @@ class ResizeContext {
// resize actually happens.
// This must be checked for every offset, since we can't know which offsets
// will straddle and which won't.
uint8_t &DagCheck(void *offsetloc) {
auto dag_idx = reinterpret_cast<uoffset_t *>(offsetloc) -
reinterpret_cast<uoffset_t *>(buf_.data());
uint8_t &DagCheck(const void *offsetloc) {
auto dag_idx = reinterpret_cast<const uoffset_t *>(offsetloc) -
reinterpret_cast<const uoffset_t *>(buf_.data());
return dag_check_[dag_idx];
}
@@ -480,4 +481,230 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
}
}
bool VerifyStruct(flatbuffers::Verifier &v,
const flatbuffers::Table &parent_table,
voffset_t field_offset,
const reflection::Object &obj,
bool required) {
auto offset = parent_table.GetOptionalFieldOffset(field_offset);
if (required && !offset) {
return false;
}
return !offset || v.Verify(reinterpret_cast<const uint8_t*>(&parent_table)
+ offset, obj.bytesize());
}
bool VerifyVectorOfStructs(flatbuffers::Verifier &v,
const flatbuffers::Table &parent_table,
voffset_t field_offset,
const reflection::Object &obj,
bool required) {
auto p = parent_table.GetPointer<const uint8_t*>(field_offset);
const uint8_t* end;
if (required && !p) {
return false;
}
return !p || v.VerifyVector(p, obj.bytesize(), &end);
}
// forward declare to resolve cyclic deps between VerifyObject and VerifyVector
bool VerifyObject(flatbuffers::Verifier &v,
const reflection::Schema &schema,
const reflection::Object &obj,
const flatbuffers::Table *table,
bool isRequired);
bool VerifyVector(flatbuffers::Verifier &v,
const reflection::Schema &schema,
const flatbuffers::Table &table,
const reflection::Field &vec_field) {
assert(vec_field.type()->base_type() == reflection::Vector);
if (!table.VerifyField<uoffset_t>(v, vec_field.offset()))
return false;
switch (vec_field.type()->element()) {
case reflection::None:
assert(false);
break;
case reflection::UType:
return v.Verify(flatbuffers::GetFieldV<uint8_t>(table, vec_field));
case reflection::Bool:
case reflection::Byte:
case reflection::UByte:
return v.Verify(flatbuffers::GetFieldV<int8_t>(table, vec_field));
case reflection::Short:
case reflection::UShort:
return v.Verify(flatbuffers::GetFieldV<int16_t>(table, vec_field));
case reflection::Int:
case reflection::UInt:
return v.Verify(flatbuffers::GetFieldV<int32_t>(table, vec_field));
case reflection::Long:
case reflection::ULong:
return v.Verify(flatbuffers::GetFieldV<int64_t>(table, vec_field));
case reflection::Float:
return v.Verify(flatbuffers::GetFieldV<float>(table, vec_field));
case reflection::Double:
return v.Verify(flatbuffers::GetFieldV<double>(table, vec_field));
case reflection::String: {
auto vecString =
flatbuffers::GetFieldV<flatbuffers::
Offset<flatbuffers::String>>(table, vec_field);
if (v.Verify(vecString) && v.VerifyVectorOfStrings(vecString)) {
return true;
} else {
return false;
}
}
case reflection::Vector:
assert(false);
break;
case reflection::Obj: {
auto obj = schema.objects()->Get(vec_field.type()->index());
if (obj->is_struct()) {
if (!VerifyVectorOfStructs(v, table, vec_field.offset(), *obj,
vec_field.required())) {
return false;
}
} else {
auto vec =
flatbuffers::GetFieldV<flatbuffers::
Offset<flatbuffers::Table>>(table, vec_field);
if (!v.Verify(vec))
return false;
if (vec) {
for (uoffset_t j = 0; j < vec->size(); j++) {
if (!VerifyObject(v, schema, *obj, vec->Get(j), true)) {
return false;
}
}
}
}
return true;
}
case reflection::Union:
assert(false);
break;
default:
assert(false);
break;
}
return false;
}
bool VerifyObject(flatbuffers::Verifier &v,
const reflection::Schema &schema,
const reflection::Object &obj,
const flatbuffers::Table *table,
bool required) {
if (!table) {
if (!required)
return true;
else
return false;
}
if (!table->VerifyTableStart(v))
return false;
for (uoffset_t i = 0; i < obj.fields()->size(); i++) {
auto field_def = obj.fields()->Get(i);
switch (field_def->type()->base_type()) {
case reflection::None:
assert(false);
break;
case reflection::UType:
if (!table->VerifyField<uint8_t>(v, field_def->offset()))
return false;
break;
case reflection::Bool:
case reflection::Byte:
case reflection::UByte:
if (!table->VerifyField<int8_t>(v, field_def->offset()))
return false;
break;
case reflection::Short:
case reflection::UShort:
if (!table->VerifyField<int16_t>(v, field_def->offset()))
return false;
break;
case reflection::Int:
case reflection::UInt:
if (!table->VerifyField<int32_t>(v, field_def->offset()))
return false;
break;
case reflection::Long:
case reflection::ULong:
if (!table->VerifyField<int64_t>(v, field_def->offset()))
return false;
break;
case reflection::Float:
if (!table->VerifyField<float>(v, field_def->offset()))
return false;
break;
case reflection::Double:
if (!table->VerifyField<double>(v, field_def->offset()))
return false;
break;
case reflection::String:
if (!table->VerifyField<uoffset_t>(v, field_def->offset()) ||
!v.Verify(flatbuffers::GetFieldS(*table, *field_def))) {
return false;
}
break;
case reflection::Vector:
if (!VerifyVector(v, schema, *table, *field_def))
return false;
break;
case reflection::Obj: {
auto child_obj = schema.objects()->Get(field_def->type()->index());
if (child_obj->is_struct()) {
if (!VerifyStruct(v, *table, field_def->offset(), *child_obj,
field_def->required())) {
return false;
}
} else {
if (!VerifyObject(v, schema, *child_obj,
flatbuffers::GetFieldT(*table, *field_def),
field_def->required())) {
return false;
}
}
break;
}
case reflection::Union: {
// get union type from the prev field
voffset_t utype_offset = field_def->offset() - sizeof(voffset_t);
auto utype = table->GetField<uint8_t>(utype_offset, 0);
if (utype != 0) {
// Means we have this union field present
auto fb_enum = schema.enums()->Get(field_def->type()->index());
auto child_obj = fb_enum->values()->Get(utype)->object();
if (!VerifyObject(v, schema, *child_obj,
flatbuffers::GetFieldT(*table, *field_def),
field_def->required())) {
return false;
}
}
break;
}
default:
assert(false);
break;
}
}
return true;
}
bool Verify(const reflection::Schema &schema,
const reflection::Object &root,
const uint8_t *buf,
size_t length) {
Verifier v(buf, length);
return VerifyObject(v, schema, root, flatbuffers::GetAnyRoot(buf), true);
}
} // namespace flatbuffers

View File

@@ -40,6 +40,7 @@ namespace FlatBuffers.Test
Assert.AreEqual((byte)99, buffer[0]);
}
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod]
public void ByteBuffer_PutByteCannotPutAtOffsetPastLength()
{
@@ -47,6 +48,7 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutByte(1, 99));
}
#endif
[FlatBuffersTestMethod]
public void ByteBuffer_PutShortPopulatesBufferCorrectly()
@@ -60,6 +62,7 @@ namespace FlatBuffers.Test
Assert.AreEqual((byte)0, buffer[1]);
}
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod]
public void ByteBuffer_PutShortCannotPutAtOffsetPastLength()
{
@@ -67,7 +70,9 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutShort(2, 99));
}
#endif
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod]
public void ByteBuffer_PutShortChecksLength()
{
@@ -83,6 +88,7 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutShort(1, 99));
}
#endif
[FlatBuffersTestMethod]
public void ByteBuffer_PutIntPopulatesBufferCorrectly()
@@ -98,6 +104,7 @@ namespace FlatBuffers.Test
Assert.AreEqual(0x0A, buffer[3]);
}
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod]
public void ByteBuffer_PutIntCannotPutAtOffsetPastLength()
{
@@ -121,6 +128,7 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutInt(2, 0x0A0B0C0D));
}
#endif
[FlatBuffersTestMethod]
public void ByteBuffer_PutLongPopulatesBufferCorrectly()
@@ -140,6 +148,7 @@ namespace FlatBuffers.Test
Assert.AreEqual(0x01, buffer[7]);
}
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod]
public void ByteBuffer_PutLongCannotPutAtOffsetPastLength()
{
@@ -163,6 +172,7 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(() => uut.PutLong(2, 0x010203040A0B0C0D));
}
#endif
[FlatBuffersTestMethod]
public void ByteBuffer_GetByteReturnsCorrectData()
@@ -173,6 +183,7 @@ namespace FlatBuffers.Test
Assert.AreEqual((byte)99, uut.Get(0));
}
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod]
public void ByteBuffer_GetByteChecksOffset()
{
@@ -180,6 +191,7 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(()=>uut.Get(1));
}
#endif
[FlatBuffersTestMethod]
public void ByteBuffer_GetShortReturnsCorrectData()
@@ -191,6 +203,7 @@ namespace FlatBuffers.Test
Assert.AreEqual(1, uut.GetShort(0));
}
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod]
public void ByteBuffer_GetShortChecksOffset()
{
@@ -206,6 +219,7 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetShort(1));
}
#endif
[FlatBuffersTestMethod]
public void ByteBuffer_GetIntReturnsCorrectData()
@@ -219,6 +233,7 @@ namespace FlatBuffers.Test
Assert.AreEqual(0x0A0B0C0D, uut.GetInt(0));
}
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod]
public void ByteBuffer_GetIntChecksOffset()
{
@@ -234,6 +249,7 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetInt(0));
}
#endif
[FlatBuffersTestMethod]
public void ByteBuffer_GetLongReturnsCorrectData()
@@ -251,6 +267,7 @@ namespace FlatBuffers.Test
Assert.AreEqual(0x010203040A0B0C0D, uut.GetLong(0));
}
#if !BYTEBUFFER_NO_BOUNDS_CHECK
[FlatBuffersTestMethod]
public void ByteBuffer_GetLongChecksOffset()
{
@@ -266,6 +283,7 @@ namespace FlatBuffers.Test
var uut = new ByteBuffer(buffer);
Assert.Throws<ArgumentOutOfRangeException>(() => uut.GetLong(0));
}
#endif
[FlatBuffersTestMethod]
public void ByteBuffer_ReverseBytesUshort()

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -41,6 +41,9 @@
<Compile Include="..\..\net\FlatBuffers\ByteBuffer.cs">
<Link>FlatBuffers\ByteBuffer.cs</Link>
</Compile>
<Compile Include="..\..\net\FlatBuffers\IFlatbufferObject.cs">
<Link>FlatBuffers\IFlatbufferObject.cs</Link>
</Compile>
<Compile Include="..\..\net\FlatBuffers\Offset.cs">
<Link>FlatBuffers\Offset.cs</Link>
</Compile>
@@ -116,4 +119,4 @@
<Target Name="AfterBuild">
</Target>
-->
</Project>
</Project>

View File

@@ -39,6 +39,19 @@ namespace FlatBuffers.Test
// better for performance.
var fbb = new FlatBufferBuilder(1);
StringOffset[] names = { fbb.CreateString("Frodo"), fbb.CreateString("Barney"), fbb.CreateString("Wilma") };
Offset<Monster>[] off = new Offset<Monster>[3];
Monster.StartMonster(fbb);
Monster.AddName(fbb, names[0]);
off[0] = Monster.EndMonster(fbb);
Monster.StartMonster(fbb);
Monster.AddName(fbb, names[1]);
off[1] = Monster.EndMonster(fbb);
Monster.StartMonster(fbb);
Monster.AddName(fbb, names[2]);
off[2] = Monster.EndMonster(fbb);
var sortMons = Monster.CreateMySortedVectorOfTables(fbb, off);
// We set up the same values as monsterdata.json:
var str = fbb.CreateString("MyMonster");
@@ -79,6 +92,7 @@ namespace FlatBuffers.Test
Monster.AddTest4(fbb, test4);
Monster.AddTestarrayofstring(fbb, testArrayOfString);
Monster.AddTestbool(fbb, false);
Monster.AddTestarrayoftables(fbb, sortMons);
var mon = Monster.EndMonster(fbb);
Monster.FinishMonsterBuffer(fbb, mon);
@@ -103,6 +117,16 @@ namespace FlatBuffers.Test
Assert.AreEqual(monster.MutateMana((short)10), false);
Assert.AreEqual(monster.Mana, (short)150);
// Accessing a vector of sorted by the key tables
Assert.AreEqual(monster.Testarrayoftables(0).Value.Name, "Barney");
Assert.AreEqual(monster.Testarrayoftables(1).Value.Name, "Frodo");
Assert.AreEqual(monster.Testarrayoftables(2).Value.Name, "Wilma");
// Example of searching for a table by the key
Assert.IsTrue(Monster.LookupByKey(sortMons, "Frodo", fbb.DataBuffer) != null);
Assert.IsTrue(Monster.LookupByKey(sortMons, "Barney", fbb.DataBuffer) != null);
Assert.IsTrue(Monster.LookupByKey(sortMons, "Wilma", fbb.DataBuffer)!= null);
// testType is an existing field and mutating it should succeed
Assert.AreEqual(monster.TestType, Any.Monster);
Assert.AreEqual(monster.MutateTestType(Any.NONE), true);
@@ -119,7 +143,7 @@ namespace FlatBuffers.Test
for (int i = 0; i < monster.InventoryLength; i++)
{
Assert.AreEqual(monster.GetInventory(i), i + 1);
Assert.AreEqual(monster.Inventory(i), i + 1);
}
//reverse mutation
@@ -130,7 +154,7 @@ namespace FlatBuffers.Test
Assert.AreEqual(monster.MutateInventory(4, 4), true);
// get a struct field and edit one of its fields
Vec3 pos = monster.Pos;
Vec3 pos = (Vec3)monster.Pos;
Assert.AreEqual(pos.X, 1.0f);
pos.MutateX(55.0f);
Assert.AreEqual(pos.X, 55.0f);
@@ -148,21 +172,20 @@ namespace FlatBuffers.Test
Assert.AreEqual(150, monster.Mana);
Assert.AreEqual("MyMonster", monster.Name);
var pos = monster.Pos;
var pos = monster.Pos.Value;
Assert.AreEqual(1.0f, pos.X);
Assert.AreEqual(2.0f, pos.Y);
Assert.AreEqual(3.0f, pos.Z);
Assert.AreEqual(3.0f, pos.Test1);
Assert.AreEqual(Color.Green, pos.Test2);
var t = pos.Test3;
var t = (MyGame.Example.Test)pos.Test3;
Assert.AreEqual((short)5, t.A);
Assert.AreEqual((sbyte)6, t.B);
Assert.AreEqual(Any.Monster, monster.TestType);
var monster2 = new Monster();
Assert.IsTrue(monster.GetTest(monster2) != null);
var monster2 = monster.Test<Monster>().Value;
Assert.AreEqual("Fred", monster2.Name);
@@ -170,19 +193,19 @@ namespace FlatBuffers.Test
var invsum = 0;
for (var i = 0; i < monster.InventoryLength; i++)
{
invsum += monster.GetInventory(i);
invsum += monster.Inventory(i);
}
Assert.AreEqual(10, invsum);
var test0 = monster.GetTest4(0);
var test1 = monster.GetTest4(1);
var test0 = monster.Test4(0).Value;
var test1 = monster.Test4(1).Value;
Assert.AreEqual(2, monster.Test4Length);
Assert.AreEqual(100, test0.A + test0.B + test1.A + test1.B);
Assert.AreEqual(2, monster.TestarrayofstringLength);
Assert.AreEqual("test1", monster.GetTestarrayofstring(0));
Assert.AreEqual("test2", monster.GetTestarrayofstring(1));
Assert.AreEqual("test1", monster.Testarrayofstring(0));
Assert.AreEqual("test2", monster.Testarrayofstring(1));
Assert.AreEqual(false, monster.Testbool);
@@ -245,10 +268,10 @@ namespace FlatBuffers.Test
Monster.AddTestnestedflatbuffer(fbb2, nestedBuffer);
var monster = Monster.EndMonster(fbb2);
Monster.FinishMonsterBuffer(fbb2, monster);
// Now test the data extracted from the nested buffer
var mons = Monster.GetRootAsMonster(fbb2.DataBuffer);
var nestedMonster = mons.TestnestedflatbufferAsMonster();
var nestedMonster = mons.GetTestnestedflatbufferAsMonster().Value;
Assert.AreEqual(nestedMonsterMana, nestedMonster.Mana);
Assert.AreEqual(nestedMonsterHp, nestedMonster.Hp);

View File

@@ -19,133 +19,135 @@ namespace FlatBuffers.Test
/// <summary>
/// A test Table object that gives easy access to the slot data
/// </summary>
internal class TestTable : Table
internal struct TestTable
{
Table t;
public TestTable(ByteBuffer bb, int pos)
{
base.bb = bb;
base.bb_pos = pos;
t.bb = bb;
t.bb_pos = pos;
}
public bool GetSlot(int slot, bool def)
{
var off = base.__offset(slot);
var off = t.__offset(slot);
if (off == 0)
{
return def;
}
return bb.GetSbyte(bb_pos + off) != 0;
return t.bb.GetSbyte(t.bb_pos + off) != 0;
}
public sbyte GetSlot(int slot, sbyte def)
{
var off = base.__offset(slot);
var off = t.__offset(slot);
if (off == 0)
{
return def;
}
return bb.GetSbyte(bb_pos + off);
return t.bb.GetSbyte(t.bb_pos + off);
}
public byte GetSlot(int slot, byte def)
{
var off = base.__offset(slot);
var off = t.__offset(slot);
if (off == 0)
{
return def;
}
return bb.Get(bb_pos + off);
return t.bb.Get(t.bb_pos + off);
}
public short GetSlot(int slot, short def)
{
var off = base.__offset(slot);
var off = t.__offset(slot);
if (off == 0)
{
return def;
}
return bb.GetShort(bb_pos + off);
return t.bb.GetShort(t.bb_pos + off);
}
public ushort GetSlot(int slot, ushort def)
{
var off = base.__offset(slot);
var off = t.__offset(slot);
if (off == 0)
{
return def;
}
return bb.GetUshort(bb_pos + off);
return t.bb.GetUshort(t.bb_pos + off);
}
public int GetSlot(int slot, int def)
{
var off = base.__offset(slot);
var off = t.__offset(slot);
if (off == 0)
{
return def;
}
return bb.GetInt(bb_pos + off);
return t.bb.GetInt(t.bb_pos + off);
}
public uint GetSlot(int slot, uint def)
{
var off = base.__offset(slot);
var off = t.__offset(slot);
if (off == 0)
{
return def;
}
return bb.GetUint(bb_pos + off);
return t.bb.GetUint(t.bb_pos + off);
}
public long GetSlot(int slot, long def)
{
var off = base.__offset(slot);
var off = t.__offset(slot);
if (off == 0)
{
return def;
}
return bb.GetLong(bb_pos + off);
return t.bb.GetLong(t.bb_pos + off);
}
public ulong GetSlot(int slot, ulong def)
{
var off = base.__offset(slot);
var off = t.__offset(slot);
if (off == 0)
{
return def;
}
return bb.GetUlong(bb_pos + off);
return t.bb.GetUlong(t.bb_pos + off);
}
public float GetSlot(int slot, float def)
{
var off = base.__offset(slot);
var off = t.__offset(slot);
if (off == 0)
{
return def;
}
return bb.GetFloat(bb_pos + off);
return t.bb.GetFloat(t.bb_pos + off);
}
public double GetSlot(int slot, double def)
{
var off = base.__offset(slot);
var off = t.__offset(slot);
if (off == 0)
{
return def;
}
return bb.GetDouble(bb_pos + off);
return t.bb.GetDouble(t.bb_pos + off);
}
}
}
}

View File

@@ -51,6 +51,19 @@ class JavaTest {
// better for performance.
FlatBufferBuilder fbb = new FlatBufferBuilder(1);
int[] names = {fbb.createString("Frodo"), fbb.createString("Barney"), fbb.createString("Wilma")};
int[] off = new int[3];
Monster.startMonster(fbb);
Monster.addName(fbb, names[0]);
off[0] = Monster.endMonster(fbb);
Monster.startMonster(fbb);
Monster.addName(fbb, names[1]);
off[1] = Monster.endMonster(fbb);
Monster.startMonster(fbb);
Monster.addName(fbb, names[2]);
off[2] = Monster.endMonster(fbb);
int sortMons = fbb.createSortedVectorOfTables(new Monster(), off);
// We set up the same values as monsterdata.json:
int str = fbb.createString("MyMonster");
@@ -84,6 +97,7 @@ class JavaTest {
Monster.addTestarrayofstring(fbb, testArrayOfString);
Monster.addTestbool(fbb, false);
Monster.addTesthashu32Fnv1(fbb, Integer.MAX_VALUE + 1L);
Monster.addTestarrayoftables(fbb, sortMons);
int mon = Monster.endMonster(fbb);
Monster.finishMonsterBuffer(fbb, mon);
@@ -121,6 +135,16 @@ class JavaTest {
// the mana field should retain its default value
TestEq(monster.mutateMana((short)10), false);
TestEq(monster.mana(), (short)150);
// Accessing a vector of sorted by the key tables
TestEq(monster.testarrayoftables(0).name(), "Barney");
TestEq(monster.testarrayoftables(1).name(), "Frodo");
TestEq(monster.testarrayoftables(2).name(), "Wilma");
// Example of searching for a table by the key
TestEq(Monster.lookupByKey(sortMons, "Frodo", fbb.dataBuffer()).name(), "Frodo");
TestEq(Monster.lookupByKey(sortMons, "Barney", fbb.dataBuffer()).name(), "Barney");
TestEq(Monster.lookupByKey(sortMons, "Wilma", fbb.dataBuffer()).name(), "Wilma");
// testType is an existing field and mutating it should succeed
TestEq(monster.testType(), (byte)Any.Monster);
@@ -161,6 +185,10 @@ class JavaTest {
TestNestedFlatBuffer();
TestCreateByteVector();
TestCreateUninitializedVector();
System.out.println("FlatBuffers test: completed successfully");
}
@@ -281,6 +309,44 @@ class JavaTest {
TestEq(nestedMonsterName, nestedMonster.name());
}
static void TestCreateByteVector() {
FlatBufferBuilder fbb = new FlatBufferBuilder(16);
int str = fbb.createString("MyMonster");
byte[] inventory = new byte[] { 0, 1, 2, 3, 4 };
int vec = fbb.createByteVector(inventory);
Monster.startMonster(fbb);
Monster.addInventory(fbb, vec);
Monster.addName(fbb, str);
int monster1 = Monster.endMonster(fbb);
Monster.finishMonsterBuffer(fbb, monster1);
Monster monsterObject = Monster.getRootAsMonster(fbb.dataBuffer());
TestEq(monsterObject.inventory(1), (int)inventory[1]);
TestEq(monsterObject.inventoryLength(), inventory.length);
TestEq(ByteBuffer.wrap(inventory), monsterObject.inventoryAsByteBuffer());
}
static void TestCreateUninitializedVector() {
FlatBufferBuilder fbb = new FlatBufferBuilder(16);
int str = fbb.createString("MyMonster");
byte[] inventory = new byte[] { 0, 1, 2, 3, 4 };
ByteBuffer bb = fbb.createUnintializedVector(1, inventory.length, 1);
for (byte i:inventory) {
bb.put(i);
}
int vec = fbb.endVector();
Monster.startMonster(fbb);
Monster.addInventory(fbb, vec);
Monster.addName(fbb, str);
int monster1 = Monster.endMonster(fbb);
Monster.finishMonsterBuffer(fbb, monster1);
Monster monsterObject = Monster.getRootAsMonster(fbb.dataBuffer());
TestEq(monsterObject.inventory(1), (int)inventory[1]);
TestEq(monsterObject.inventoryLength(), inventory.length);
TestEq(ByteBuffer.wrap(inventory), monsterObject.inventoryAsByteBuffer());
}
static <T> void TestEq(T a, T b) {
if (!a.equals(b)) {
System.out.println("" + a.getClass().getName() + " " + b.getClass().getName());

View File

@@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
#
# Copyright 2014 Google Inc. All rights reserved.
#
@@ -16,14 +16,29 @@
echo Compile then run the Java test.
java -version
testdir=$(readlink -fn `dirname $0`)
thisdir=$(readlink -fn `pwd`)
targetdir=${testdir}/target
if [[ "$testdir" != "$thisdir" ]]; then
echo error: must be run from inside the ${testdir} directory
echo you ran it from ${thisdir}
exit 1
fi
javac -classpath ${testdir}/../java:${testdir}:${testdir}/namespace_test JavaTest.java
java -classpath ${testdir}/../java:${testdir}:${testdir}/namespace_test JavaTest
find .. -type f -name "*.class" -exec rm {} \;
if [[ -e "${targetdir}" ]]; then
echo "clean target"
rm -rf ${targetdir}
fi
mkdir ${targetdir}
javac -d ${targetdir} -classpath ${testdir}/../java:${testdir}:${testdir}/namespace_test JavaTest.java
java -classpath ${targetdir} JavaTest
rm -rf ${targetdir}

View File

@@ -7,79 +7,77 @@ using System;
using FlatBuffers;
/// an example documentation comment: monster object
public sealed class Monster : Table {
public struct Monster : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static Monster GetRootAsMonster(ByteBuffer _bb) { return GetRootAsMonster(_bb, new Monster()); }
public static Monster GetRootAsMonster(ByteBuffer _bb, Monster obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public static bool MonsterBufferHasIdentifier(ByteBuffer _bb) { return __has_identifier(_bb, "MONS"); }
public Monster __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
public static Monster GetRootAsMonster(ByteBuffer _bb, Monster obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public static bool MonsterBufferHasIdentifier(ByteBuffer _bb) { return Table.__has_identifier(_bb, "MONS"); }
public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
public Monster __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public Vec3 Pos { get { return GetPos(new Vec3()); } }
public Vec3 GetPos(Vec3 obj) { int o = __offset(4); return o != 0 ? obj.__init(o + bb_pos, bb) : null; }
public short Mana { get { int o = __offset(6); return o != 0 ? bb.GetShort(o + bb_pos) : (short)150; } }
public bool MutateMana(short mana) { int o = __offset(6); if (o != 0) { bb.PutShort(o + bb_pos, mana); return true; } else { return false; } }
public short Hp { get { int o = __offset(8); return o != 0 ? bb.GetShort(o + bb_pos) : (short)100; } }
public bool MutateHp(short hp) { int o = __offset(8); if (o != 0) { bb.PutShort(o + bb_pos, hp); return true; } else { return false; } }
public string Name { get { int o = __offset(10); return o != 0 ? __string(o + bb_pos) : null; } }
public ArraySegment<byte>? GetNameBytes() { return __vector_as_arraysegment(10); }
public byte GetInventory(int j) { int o = __offset(14); return o != 0 ? bb.Get(__vector(o) + j * 1) : (byte)0; }
public int InventoryLength { get { int o = __offset(14); return o != 0 ? __vector_len(o) : 0; } }
public ArraySegment<byte>? GetInventoryBytes() { return __vector_as_arraysegment(14); }
public bool MutateInventory(int j, byte inventory) { int o = __offset(14); if (o != 0) { bb.Put(__vector(o) + j * 1, inventory); return true; } else { return false; } }
public Color Color { get { int o = __offset(16); return o != 0 ? (Color)bb.GetSbyte(o + bb_pos) : Color.Blue; } }
public bool MutateColor(Color color) { int o = __offset(16); if (o != 0) { bb.PutSbyte(o + bb_pos, (sbyte)color); return true; } else { return false; } }
public Any TestType { get { int o = __offset(18); return o != 0 ? (Any)bb.Get(o + bb_pos) : Any.NONE; } }
public bool MutateTestType(Any test_type) { int o = __offset(18); if (o != 0) { bb.Put(o + bb_pos, (byte)test_type); return true; } else { return false; } }
public TTable GetTest<TTable>(TTable obj) where TTable : Table { int o = __offset(20); return o != 0 ? __union(obj, o) : null; }
public Test GetTest4(int j) { return GetTest4(new Test(), j); }
public Test GetTest4(Test obj, int j) { int o = __offset(22); return o != 0 ? obj.__init(__vector(o) + j * 4, bb) : null; }
public int Test4Length { get { int o = __offset(22); return o != 0 ? __vector_len(o) : 0; } }
public string GetTestarrayofstring(int j) { int o = __offset(24); return o != 0 ? __string(__vector(o) + j * 4) : null; }
public int TestarrayofstringLength { get { int o = __offset(24); return o != 0 ? __vector_len(o) : 0; } }
public Vec3? Pos { get { int o = __p.__offset(4); return o != 0 ? (Vec3?)(new Vec3()).__assign(o + __p.bb_pos, __p.bb) : null; } }
public short Mana { get { int o = __p.__offset(6); return o != 0 ? __p.bb.GetShort(o + __p.bb_pos) : (short)150; } }
public bool MutateMana(short mana) { int o = __p.__offset(6); if (o != 0) { __p.bb.PutShort(o + __p.bb_pos, mana); return true; } else { return false; } }
public short Hp { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetShort(o + __p.bb_pos) : (short)100; } }
public bool MutateHp(short hp) { int o = __p.__offset(8); if (o != 0) { __p.bb.PutShort(o + __p.bb_pos, hp); return true; } else { return false; } }
public string Name { get { int o = __p.__offset(10); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
public ArraySegment<byte>? GetNameBytes() { return __p.__vector_as_arraysegment(10); }
public byte Inventory(int j) { int o = __p.__offset(14); return o != 0 ? __p.bb.Get(__p.__vector(o) + j * 1) : (byte)0; }
public int InventoryLength { get { int o = __p.__offset(14); return o != 0 ? __p.__vector_len(o) : 0; } }
public ArraySegment<byte>? GetInventoryBytes() { return __p.__vector_as_arraysegment(14); }
public bool MutateInventory(int j, byte inventory) { int o = __p.__offset(14); if (o != 0) { __p.bb.Put(__p.__vector(o) + j * 1, inventory); return true; } else { return false; } }
public Color Color { get { int o = __p.__offset(16); return o != 0 ? (Color)__p.bb.GetSbyte(o + __p.bb_pos) : Color.Blue; } }
public bool MutateColor(Color color) { int o = __p.__offset(16); if (o != 0) { __p.bb.PutSbyte(o + __p.bb_pos, (sbyte)color); return true; } else { return false; } }
public Any TestType { get { int o = __p.__offset(18); return o != 0 ? (Any)__p.bb.Get(o + __p.bb_pos) : Any.NONE; } }
public bool MutateTestType(Any test_type) { int o = __p.__offset(18); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (byte)test_type); return true; } else { return false; } }
public TTable? Test<TTable>() where TTable : struct, IFlatbufferObject { int o = __p.__offset(20); return o != 0 ? (TTable?)__p.__union<TTable>(o) : null; }
public Test? Test4(int j) { int o = __p.__offset(22); return o != 0 ? (Test?)(new Test()).__assign(__p.__vector(o) + j * 4, __p.bb) : null; }
public int Test4Length { get { int o = __p.__offset(22); return o != 0 ? __p.__vector_len(o) : 0; } }
public string Testarrayofstring(int j) { int o = __p.__offset(24); return o != 0 ? __p.__string(__p.__vector(o) + j * 4) : null; }
public int TestarrayofstringLength { get { int o = __p.__offset(24); return o != 0 ? __p.__vector_len(o) : 0; } }
/// an example documentation comment: this will end up in the generated code
/// multiline too
public Monster GetTestarrayoftables(int j) { return GetTestarrayoftables(new Monster(), j); }
public Monster GetTestarrayoftables(Monster obj, int j) { int o = __offset(26); return o != 0 ? obj.__init(__indirect(__vector(o) + j * 4), bb) : null; }
public int TestarrayoftablesLength { get { int o = __offset(26); return o != 0 ? __vector_len(o) : 0; } }
public Monster Enemy { get { return GetEnemy(new Monster()); } }
public Monster GetEnemy(Monster obj) { int o = __offset(28); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
public byte GetTestnestedflatbuffer(int j) { int o = __offset(30); return o != 0 ? bb.Get(__vector(o) + j * 1) : (byte)0; }
public int TestnestedflatbufferLength { get { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; } }
public ArraySegment<byte>? GetTestnestedflatbufferBytes() { return __vector_as_arraysegment(30); }
public Monster TestnestedflatbufferAsMonster() { return GetTestnestedflatbufferAsMonster(new Monster()); }
public Monster GetTestnestedflatbufferAsMonster(Monster obj) { int o = __offset(30); return o != 0 ? obj.__init(__indirect(__vector(o)), bb) : null; }
public bool MutateTestnestedflatbuffer(int j, byte testnestedflatbuffer) { int o = __offset(30); if (o != 0) { bb.Put(__vector(o) + j * 1, testnestedflatbuffer); return true; } else { return false; } }
public Stat Testempty { get { return GetTestempty(new Stat()); } }
public Stat GetTestempty(Stat obj) { int o = __offset(32); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
public bool Testbool { get { int o = __offset(34); return o != 0 ? 0!=bb.Get(o + bb_pos) : (bool)false; } }
public bool MutateTestbool(bool testbool) { int o = __offset(34); if (o != 0) { bb.Put(o + bb_pos, (byte)(testbool ? 1 : 0)); return true; } else { return false; } }
public int Testhashs32Fnv1 { get { int o = __offset(36); return o != 0 ? bb.GetInt(o + bb_pos) : (int)0; } }
public bool MutateTesthashs32Fnv1(int testhashs32_fnv1) { int o = __offset(36); if (o != 0) { bb.PutInt(o + bb_pos, testhashs32_fnv1); return true; } else { return false; } }
public uint Testhashu32Fnv1 { get { int o = __offset(38); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
public bool MutateTesthashu32Fnv1(uint testhashu32_fnv1) { int o = __offset(38); if (o != 0) { bb.PutUint(o + bb_pos, testhashu32_fnv1); return true; } else { return false; } }
public long Testhashs64Fnv1 { get { int o = __offset(40); return o != 0 ? bb.GetLong(o + bb_pos) : (long)0; } }
public bool MutateTesthashs64Fnv1(long testhashs64_fnv1) { int o = __offset(40); if (o != 0) { bb.PutLong(o + bb_pos, testhashs64_fnv1); return true; } else { return false; } }
public ulong Testhashu64Fnv1 { get { int o = __offset(42); return o != 0 ? bb.GetUlong(o + bb_pos) : (ulong)0; } }
public bool MutateTesthashu64Fnv1(ulong testhashu64_fnv1) { int o = __offset(42); if (o != 0) { bb.PutUlong(o + bb_pos, testhashu64_fnv1); return true; } else { return false; } }
public int Testhashs32Fnv1a { get { int o = __offset(44); return o != 0 ? bb.GetInt(o + bb_pos) : (int)0; } }
public bool MutateTesthashs32Fnv1a(int testhashs32_fnv1a) { int o = __offset(44); if (o != 0) { bb.PutInt(o + bb_pos, testhashs32_fnv1a); return true; } else { return false; } }
public uint Testhashu32Fnv1a { get { int o = __offset(46); return o != 0 ? bb.GetUint(o + bb_pos) : (uint)0; } }
public bool MutateTesthashu32Fnv1a(uint testhashu32_fnv1a) { int o = __offset(46); if (o != 0) { bb.PutUint(o + bb_pos, testhashu32_fnv1a); return true; } else { return false; } }
public long Testhashs64Fnv1a { get { int o = __offset(48); return o != 0 ? bb.GetLong(o + bb_pos) : (long)0; } }
public bool MutateTesthashs64Fnv1a(long testhashs64_fnv1a) { int o = __offset(48); if (o != 0) { bb.PutLong(o + bb_pos, testhashs64_fnv1a); return true; } else { return false; } }
public ulong Testhashu64Fnv1a { get { int o = __offset(50); return o != 0 ? bb.GetUlong(o + bb_pos) : (ulong)0; } }
public bool MutateTesthashu64Fnv1a(ulong testhashu64_fnv1a) { int o = __offset(50); if (o != 0) { bb.PutUlong(o + bb_pos, testhashu64_fnv1a); return true; } else { return false; } }
public bool GetTestarrayofbools(int j) { int o = __offset(52); return o != 0 ? 0!=bb.Get(__vector(o) + j * 1) : false; }
public int TestarrayofboolsLength { get { int o = __offset(52); return o != 0 ? __vector_len(o) : 0; } }
public ArraySegment<byte>? GetTestarrayofboolsBytes() { return __vector_as_arraysegment(52); }
public bool MutateTestarrayofbools(int j, bool testarrayofbools) { int o = __offset(52); if (o != 0) { bb.Put(__vector(o) + j * 1, (byte)(testarrayofbools ? 1 : 0)); return true; } else { return false; } }
public float Testf { get { int o = __offset(54); return o != 0 ? bb.GetFloat(o + bb_pos) : (float)3.14159f; } }
public bool MutateTestf(float testf) { int o = __offset(54); if (o != 0) { bb.PutFloat(o + bb_pos, testf); return true; } else { return false; } }
public float Testf2 { get { int o = __offset(56); return o != 0 ? bb.GetFloat(o + bb_pos) : (float)3.0f; } }
public bool MutateTestf2(float testf2) { int o = __offset(56); if (o != 0) { bb.PutFloat(o + bb_pos, testf2); return true; } else { return false; } }
public float Testf3 { get { int o = __offset(58); return o != 0 ? bb.GetFloat(o + bb_pos) : (float)0.0f; } }
public bool MutateTestf3(float testf3) { int o = __offset(58); if (o != 0) { bb.PutFloat(o + bb_pos, testf3); return true; } else { return false; } }
public string GetTestarrayofstring2(int j) { int o = __offset(60); return o != 0 ? __string(__vector(o) + j * 4) : null; }
public int Testarrayofstring2Length { get { int o = __offset(60); return o != 0 ? __vector_len(o) : 0; } }
public Monster? Testarrayoftables(int j) { int o = __p.__offset(26); return o != 0 ? (Monster?)(new Monster()).__assign(__p.__indirect(__p.__vector(o) + j * 4), __p.bb) : null; }
public int TestarrayoftablesLength { get { int o = __p.__offset(26); return o != 0 ? __p.__vector_len(o) : 0; } }
public Monster? Enemy { get { int o = __p.__offset(28); return o != 0 ? (Monster?)(new Monster()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
public byte Testnestedflatbuffer(int j) { int o = __p.__offset(30); return o != 0 ? __p.bb.Get(__p.__vector(o) + j * 1) : (byte)0; }
public int TestnestedflatbufferLength { get { int o = __p.__offset(30); return o != 0 ? __p.__vector_len(o) : 0; } }
public ArraySegment<byte>? GetTestnestedflatbufferBytes() { return __p.__vector_as_arraysegment(30); }
public Monster? GetTestnestedflatbufferAsMonster() { int o = __p.__offset(30); return o != 0 ? (Monster?)(new Monster()).__assign(__p.__indirect(__p.__vector(o)), __p.bb) : null; }
public bool MutateTestnestedflatbuffer(int j, byte testnestedflatbuffer) { int o = __p.__offset(30); if (o != 0) { __p.bb.Put(__p.__vector(o) + j * 1, testnestedflatbuffer); return true; } else { return false; } }
public Stat? Testempty { get { int o = __p.__offset(32); return o != 0 ? (Stat?)(new Stat()).__assign(__p.__indirect(o + __p.bb_pos), __p.bb) : null; } }
public bool Testbool { get { int o = __p.__offset(34); return o != 0 ? 0!=__p.bb.Get(o + __p.bb_pos) : (bool)false; } }
public bool MutateTestbool(bool testbool) { int o = __p.__offset(34); if (o != 0) { __p.bb.Put(o + __p.bb_pos, (byte)(testbool ? 1 : 0)); return true; } else { return false; } }
public int Testhashs32Fnv1 { get { int o = __p.__offset(36); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } }
public bool MutateTesthashs32Fnv1(int testhashs32_fnv1) { int o = __p.__offset(36); if (o != 0) { __p.bb.PutInt(o + __p.bb_pos, testhashs32_fnv1); return true; } else { return false; } }
public uint Testhashu32Fnv1 { get { int o = __p.__offset(38); return o != 0 ? __p.bb.GetUint(o + __p.bb_pos) : (uint)0; } }
public bool MutateTesthashu32Fnv1(uint testhashu32_fnv1) { int o = __p.__offset(38); if (o != 0) { __p.bb.PutUint(o + __p.bb_pos, testhashu32_fnv1); return true; } else { return false; } }
public long Testhashs64Fnv1 { get { int o = __p.__offset(40); return o != 0 ? __p.bb.GetLong(o + __p.bb_pos) : (long)0; } }
public bool MutateTesthashs64Fnv1(long testhashs64_fnv1) { int o = __p.__offset(40); if (o != 0) { __p.bb.PutLong(o + __p.bb_pos, testhashs64_fnv1); return true; } else { return false; } }
public ulong Testhashu64Fnv1 { get { int o = __p.__offset(42); return o != 0 ? __p.bb.GetUlong(o + __p.bb_pos) : (ulong)0; } }
public bool MutateTesthashu64Fnv1(ulong testhashu64_fnv1) { int o = __p.__offset(42); if (o != 0) { __p.bb.PutUlong(o + __p.bb_pos, testhashu64_fnv1); return true; } else { return false; } }
public int Testhashs32Fnv1a { get { int o = __p.__offset(44); return o != 0 ? __p.bb.GetInt(o + __p.bb_pos) : (int)0; } }
public bool MutateTesthashs32Fnv1a(int testhashs32_fnv1a) { int o = __p.__offset(44); if (o != 0) { __p.bb.PutInt(o + __p.bb_pos, testhashs32_fnv1a); return true; } else { return false; } }
public uint Testhashu32Fnv1a { get { int o = __p.__offset(46); return o != 0 ? __p.bb.GetUint(o + __p.bb_pos) : (uint)0; } }
public bool MutateTesthashu32Fnv1a(uint testhashu32_fnv1a) { int o = __p.__offset(46); if (o != 0) { __p.bb.PutUint(o + __p.bb_pos, testhashu32_fnv1a); return true; } else { return false; } }
public long Testhashs64Fnv1a { get { int o = __p.__offset(48); return o != 0 ? __p.bb.GetLong(o + __p.bb_pos) : (long)0; } }
public bool MutateTesthashs64Fnv1a(long testhashs64_fnv1a) { int o = __p.__offset(48); if (o != 0) { __p.bb.PutLong(o + __p.bb_pos, testhashs64_fnv1a); return true; } else { return false; } }
public ulong Testhashu64Fnv1a { get { int o = __p.__offset(50); return o != 0 ? __p.bb.GetUlong(o + __p.bb_pos) : (ulong)0; } }
public bool MutateTesthashu64Fnv1a(ulong testhashu64_fnv1a) { int o = __p.__offset(50); if (o != 0) { __p.bb.PutUlong(o + __p.bb_pos, testhashu64_fnv1a); return true; } else { return false; } }
public bool Testarrayofbools(int j) { int o = __p.__offset(52); return o != 0 ? 0!=__p.bb.Get(__p.__vector(o) + j * 1) : false; }
public int TestarrayofboolsLength { get { int o = __p.__offset(52); return o != 0 ? __p.__vector_len(o) : 0; } }
public ArraySegment<byte>? GetTestarrayofboolsBytes() { return __p.__vector_as_arraysegment(52); }
public bool MutateTestarrayofbools(int j, bool testarrayofbools) { int o = __p.__offset(52); if (o != 0) { __p.bb.Put(__p.__vector(o) + j * 1, (byte)(testarrayofbools ? 1 : 0)); return true; } else { return false; } }
public float Testf { get { int o = __p.__offset(54); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)3.14159f; } }
public bool MutateTestf(float testf) { int o = __p.__offset(54); if (o != 0) { __p.bb.PutFloat(o + __p.bb_pos, testf); return true; } else { return false; } }
public float Testf2 { get { int o = __p.__offset(56); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)3.0f; } }
public bool MutateTestf2(float testf2) { int o = __p.__offset(56); if (o != 0) { __p.bb.PutFloat(o + __p.bb_pos, testf2); return true; } else { return false; } }
public float Testf3 { get { int o = __p.__offset(58); return o != 0 ? __p.bb.GetFloat(o + __p.bb_pos) : (float)0.0f; } }
public bool MutateTestf3(float testf3) { int o = __p.__offset(58); if (o != 0) { __p.bb.PutFloat(o + __p.bb_pos, testf3); return true; } else { return false; } }
public string Testarrayofstring2(int j) { int o = __p.__offset(60); return o != 0 ? __p.__string(__p.__vector(o) + j * 4) : null; }
public int Testarrayofstring2Length { get { int o = __p.__offset(60); return o != 0 ? __p.__vector_len(o) : 0; } }
public static void StartMonster(FlatBufferBuilder builder) { builder.StartObject(29); }
public static void AddPos(FlatBufferBuilder builder, Offset<Vec3> posOffset) { builder.AddStruct(0, posOffset.Value, 0); }
@@ -129,6 +127,34 @@ public sealed class Monster : Table {
return new Offset<Monster>(o);
}
public static void FinishMonsterBuffer(FlatBufferBuilder builder, Offset<Monster> offset) { builder.Finish(offset.Value, "MONS"); }
public static VectorOffset CreateMySortedVectorOfTables(FlatBufferBuilder builder, Offset<Monster>[] offsets) {
Array.Sort(offsets, (Offset<Monster> o1, Offset<Monster> o2) => Table.CompareStrings(Table.__offset(10, o1.Value, builder.DataBuffer), Table.__offset(10, o2.Value, builder.DataBuffer), builder.DataBuffer));
return builder.CreateVectorOfTables(offsets);
}
public static Monster? LookupByKey(VectorOffset vectorOffset, string key, ByteBuffer bb) {
byte[] byteKey = System.Text.Encoding.UTF8.GetBytes(key);
int vectorLocation = bb.Length - vectorOffset.Value;
int span = bb.GetInt(vectorLocation);
int start = 0;
vectorLocation += 4;
while (span != 0) {
int middle = span / 2;
int tableOffset = Table.__indirect(vectorLocation + 4 * (start + middle), bb);
int comp = Table.CompareStrings(Table.__offset(10, bb.Length - tableOffset, bb), byteKey, bb);
if (comp > 0) {
span = middle;
} else if (comp < 0) {
middle++;
start += middle;
span -= middle;
} else {
return new Monster().__assign(tableOffset, bb);
}
}
return null;
}
};

View File

@@ -23,6 +23,10 @@ func (rcv *Monster) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Pos = i
}
func (rcv *Monster) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *Monster) Pos(obj *Vec3) *Vec3 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
@@ -131,9 +135,6 @@ func (rcv *Monster) Test4(obj *Test, j int) bool {
if o != 0 {
x := rcv._tab.Vector(o)
x += flatbuffers.UOffsetT(j) * 4
if obj == nil {
obj = new(Test)
}
obj.Init(rcv._tab.Bytes, x)
return true
}
@@ -173,9 +174,6 @@ func (rcv *Monster) Testarrayoftables(obj *Monster, j int) bool {
x := rcv._tab.Vector(o)
x += flatbuffers.UOffsetT(j) * 4
x = rcv._tab.Indirect(x)
if obj == nil {
obj = new(Monster)
}
obj.Init(rcv._tab.Bytes, x)
return true
}

View File

@@ -13,12 +13,13 @@ import com.google.flatbuffers.*;
*/
public final class Monster extends Table {
public static Monster getRootAsMonster(ByteBuffer _bb) { return getRootAsMonster(_bb, new Monster()); }
public static Monster getRootAsMonster(ByteBuffer _bb, Monster obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public static Monster getRootAsMonster(ByteBuffer _bb, Monster obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public static boolean MonsterBufferHasIdentifier(ByteBuffer _bb) { return __has_identifier(_bb, "MONS"); }
public Monster __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
public Monster __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public Vec3 pos() { return pos(new Vec3()); }
public Vec3 pos(Vec3 obj) { int o = __offset(4); return o != 0 ? obj.__init(o + bb_pos, bb) : null; }
public Vec3 pos(Vec3 obj) { int o = __offset(4); return o != 0 ? obj.__assign(o + bb_pos, bb) : null; }
public short mana() { int o = __offset(6); return o != 0 ? bb.getShort(o + bb_pos) : 150; }
public boolean mutateMana(short mana) { int o = __offset(6); if (o != 0) { bb.putShort(o + bb_pos, mana); return true; } else { return false; } }
public short hp() { int o = __offset(8); return o != 0 ? bb.getShort(o + bb_pos) : 100; }
@@ -35,7 +36,7 @@ public final class Monster extends Table {
public boolean mutateTestType(byte test_type) { int o = __offset(18); if (o != 0) { bb.put(o + bb_pos, test_type); return true; } else { return false; } }
public Table test(Table obj) { int o = __offset(20); return o != 0 ? __union(obj, o) : null; }
public Test test4(int j) { return test4(new Test(), j); }
public Test test4(Test obj, int j) { int o = __offset(22); return o != 0 ? obj.__init(__vector(o) + j * 4, bb) : null; }
public Test test4(Test obj, int j) { int o = __offset(22); return o != 0 ? obj.__assign(__vector(o) + j * 4, bb) : null; }
public int test4Length() { int o = __offset(22); return o != 0 ? __vector_len(o) : 0; }
public String testarrayofstring(int j) { int o = __offset(24); return o != 0 ? __string(__vector(o) + j * 4) : null; }
public int testarrayofstringLength() { int o = __offset(24); return o != 0 ? __vector_len(o) : 0; }
@@ -44,35 +45,35 @@ public final class Monster extends Table {
* multiline too
*/
public Monster testarrayoftables(int j) { return testarrayoftables(new Monster(), j); }
public Monster testarrayoftables(Monster obj, int j) { int o = __offset(26); return o != 0 ? obj.__init(__indirect(__vector(o) + j * 4), bb) : null; }
public Monster testarrayoftables(Monster obj, int j) { int o = __offset(26); return o != 0 ? obj.__assign(__indirect(__vector(o) + j * 4), bb) : null; }
public int testarrayoftablesLength() { int o = __offset(26); return o != 0 ? __vector_len(o) : 0; }
public Monster enemy() { return enemy(new Monster()); }
public Monster enemy(Monster obj) { int o = __offset(28); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
public Monster enemy(Monster obj) { int o = __offset(28); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; }
public int testnestedflatbuffer(int j) { int o = __offset(30); return o != 0 ? bb.get(__vector(o) + j * 1) & 0xFF : 0; }
public int testnestedflatbufferLength() { int o = __offset(30); return o != 0 ? __vector_len(o) : 0; }
public ByteBuffer testnestedflatbufferAsByteBuffer() { return __vector_as_bytebuffer(30, 1); }
public Monster testnestedflatbufferAsMonster() { return testnestedflatbufferAsMonster(new Monster()); }
public Monster testnestedflatbufferAsMonster(Monster obj) { int o = __offset(30); return o != 0 ? obj.__init(__indirect(__vector(o)), bb) : null; }
public Monster testnestedflatbufferAsMonster(Monster obj) { int o = __offset(30); return o != 0 ? obj.__assign(__indirect(__vector(o)), bb) : null; }
public boolean mutateTestnestedflatbuffer(int j, int testnestedflatbuffer) { int o = __offset(30); if (o != 0) { bb.put(__vector(o) + j * 1, (byte)testnestedflatbuffer); return true; } else { return false; } }
public Stat testempty() { return testempty(new Stat()); }
public Stat testempty(Stat obj) { int o = __offset(32); return o != 0 ? obj.__init(__indirect(o + bb_pos), bb) : null; }
public Stat testempty(Stat obj) { int o = __offset(32); return o != 0 ? obj.__assign(__indirect(o + bb_pos), bb) : null; }
public boolean testbool() { int o = __offset(34); return o != 0 ? 0!=bb.get(o + bb_pos) : false; }
public boolean mutateTestbool(boolean testbool) { int o = __offset(34); if (o != 0) { bb.put(o + bb_pos, (byte)(testbool ? 1 : 0)); return true; } else { return false; } }
public int testhashs32Fnv1() { int o = __offset(36); return o != 0 ? bb.getInt(o + bb_pos) : 0; }
public boolean mutateTesthashs32Fnv1(int testhashs32_fnv1) { int o = __offset(36); if (o != 0) { bb.putInt(o + bb_pos, testhashs32_fnv1); return true; } else { return false; } }
public long testhashu32Fnv1() { int o = __offset(38); return o != 0 ? (long)bb.getInt(o + bb_pos) & 0xFFFFFFFFL : 0; }
public long testhashu32Fnv1() { int o = __offset(38); return o != 0 ? (long)bb.getInt(o + bb_pos) & 0xFFFFFFFFL : 0L; }
public boolean mutateTesthashu32Fnv1(long testhashu32_fnv1) { int o = __offset(38); if (o != 0) { bb.putInt(o + bb_pos, (int)testhashu32_fnv1); return true; } else { return false; } }
public long testhashs64Fnv1() { int o = __offset(40); return o != 0 ? bb.getLong(o + bb_pos) : 0; }
public long testhashs64Fnv1() { int o = __offset(40); return o != 0 ? bb.getLong(o + bb_pos) : 0L; }
public boolean mutateTesthashs64Fnv1(long testhashs64_fnv1) { int o = __offset(40); if (o != 0) { bb.putLong(o + bb_pos, testhashs64_fnv1); return true; } else { return false; } }
public long testhashu64Fnv1() { int o = __offset(42); return o != 0 ? bb.getLong(o + bb_pos) : 0; }
public long testhashu64Fnv1() { int o = __offset(42); return o != 0 ? bb.getLong(o + bb_pos) : 0L; }
public boolean mutateTesthashu64Fnv1(long testhashu64_fnv1) { int o = __offset(42); if (o != 0) { bb.putLong(o + bb_pos, testhashu64_fnv1); return true; } else { return false; } }
public int testhashs32Fnv1a() { int o = __offset(44); return o != 0 ? bb.getInt(o + bb_pos) : 0; }
public boolean mutateTesthashs32Fnv1a(int testhashs32_fnv1a) { int o = __offset(44); if (o != 0) { bb.putInt(o + bb_pos, testhashs32_fnv1a); return true; } else { return false; } }
public long testhashu32Fnv1a() { int o = __offset(46); return o != 0 ? (long)bb.getInt(o + bb_pos) & 0xFFFFFFFFL : 0; }
public long testhashu32Fnv1a() { int o = __offset(46); return o != 0 ? (long)bb.getInt(o + bb_pos) & 0xFFFFFFFFL : 0L; }
public boolean mutateTesthashu32Fnv1a(long testhashu32_fnv1a) { int o = __offset(46); if (o != 0) { bb.putInt(o + bb_pos, (int)testhashu32_fnv1a); return true; } else { return false; } }
public long testhashs64Fnv1a() { int o = __offset(48); return o != 0 ? bb.getLong(o + bb_pos) : 0; }
public long testhashs64Fnv1a() { int o = __offset(48); return o != 0 ? bb.getLong(o + bb_pos) : 0L; }
public boolean mutateTesthashs64Fnv1a(long testhashs64_fnv1a) { int o = __offset(48); if (o != 0) { bb.putLong(o + bb_pos, testhashs64_fnv1a); return true; } else { return false; } }
public long testhashu64Fnv1a() { int o = __offset(50); return o != 0 ? bb.getLong(o + bb_pos) : 0; }
public long testhashu64Fnv1a() { int o = __offset(50); return o != 0 ? bb.getLong(o + bb_pos) : 0L; }
public boolean mutateTesthashu64Fnv1a(long testhashu64_fnv1a) { int o = __offset(50); if (o != 0) { bb.putLong(o + bb_pos, testhashu64_fnv1a); return true; } else { return false; } }
public boolean testarrayofbools(int j) { int o = __offset(52); return o != 0 ? 0!=bb.get(__vector(o) + j * 1) : false; }
public int testarrayofboolsLength() { int o = __offset(52); return o != 0 ? __vector_len(o) : 0; }
@@ -113,13 +114,13 @@ public final class Monster extends Table {
public static void addTestempty(FlatBufferBuilder builder, int testemptyOffset) { builder.addOffset(14, testemptyOffset, 0); }
public static void addTestbool(FlatBufferBuilder builder, boolean testbool) { builder.addBoolean(15, testbool, false); }
public static void addTesthashs32Fnv1(FlatBufferBuilder builder, int testhashs32Fnv1) { builder.addInt(16, testhashs32Fnv1, 0); }
public static void addTesthashu32Fnv1(FlatBufferBuilder builder, long testhashu32Fnv1) { builder.addInt(17, (int)testhashu32Fnv1, 0); }
public static void addTesthashs64Fnv1(FlatBufferBuilder builder, long testhashs64Fnv1) { builder.addLong(18, testhashs64Fnv1, 0); }
public static void addTesthashu64Fnv1(FlatBufferBuilder builder, long testhashu64Fnv1) { builder.addLong(19, testhashu64Fnv1, 0); }
public static void addTesthashu32Fnv1(FlatBufferBuilder builder, long testhashu32Fnv1) { builder.addInt(17, (int)testhashu32Fnv1, (int)0L); }
public static void addTesthashs64Fnv1(FlatBufferBuilder builder, long testhashs64Fnv1) { builder.addLong(18, testhashs64Fnv1, 0L); }
public static void addTesthashu64Fnv1(FlatBufferBuilder builder, long testhashu64Fnv1) { builder.addLong(19, testhashu64Fnv1, 0L); }
public static void addTesthashs32Fnv1a(FlatBufferBuilder builder, int testhashs32Fnv1a) { builder.addInt(20, testhashs32Fnv1a, 0); }
public static void addTesthashu32Fnv1a(FlatBufferBuilder builder, long testhashu32Fnv1a) { builder.addInt(21, (int)testhashu32Fnv1a, 0); }
public static void addTesthashs64Fnv1a(FlatBufferBuilder builder, long testhashs64Fnv1a) { builder.addLong(22, testhashs64Fnv1a, 0); }
public static void addTesthashu64Fnv1a(FlatBufferBuilder builder, long testhashu64Fnv1a) { builder.addLong(23, testhashu64Fnv1a, 0); }
public static void addTesthashu32Fnv1a(FlatBufferBuilder builder, long testhashu32Fnv1a) { builder.addInt(21, (int)testhashu32Fnv1a, (int)0L); }
public static void addTesthashs64Fnv1a(FlatBufferBuilder builder, long testhashs64Fnv1a) { builder.addLong(22, testhashs64Fnv1a, 0L); }
public static void addTesthashu64Fnv1a(FlatBufferBuilder builder, long testhashu64Fnv1a) { builder.addLong(23, testhashu64Fnv1a, 0L); }
public static void addTestarrayofbools(FlatBufferBuilder builder, int testarrayofboolsOffset) { builder.addOffset(24, testarrayofboolsOffset, 0); }
public static int createTestarrayofboolsVector(FlatBufferBuilder builder, boolean[] data) { builder.startVector(1, data.length, 1); for (int i = data.length - 1; i >= 0; i--) builder.addBoolean(data[i]); return builder.endVector(); }
public static void startTestarrayofboolsVector(FlatBufferBuilder builder, int numElems) { builder.startVector(1, numElems, 1); }
@@ -135,5 +136,31 @@ public final class Monster extends Table {
return o;
}
public static void finishMonsterBuffer(FlatBufferBuilder builder, int offset) { builder.finish(offset, "MONS"); }
@Override
protected int keysCompare(Integer o1, Integer o2, ByteBuffer _bb) { return compareStrings(__offset(10, o1, _bb), __offset(10, o2, _bb), _bb); }
public static Monster lookupByKey(int vectorOffset, String key, ByteBuffer bb) {
byte[] byteKey = key.getBytes(Table.UTF8_CHARSET.get());
int vectorLocation = bb.array().length - vectorOffset;
int span = bb.getInt(vectorLocation);
int start = 0;
vectorLocation += 4;
while (span != 0) {
int middle = span / 2;
int tableOffset = __indirect(vectorLocation + 4 * (start + middle), bb);
int comp = compareStrings(__offset(10, bb.array().length - tableOffset, bb), byteKey, bb);
if (comp > 0) {
span = middle;
} else if (comp < 0) {
middle++;
start += middle;
span -= middle;
} else {
return new Monster().__assign(tableOffset, bb);
}
}
return null;
}
}

View File

@@ -0,0 +1,127 @@
//Generated by gRPC Go plugin
//If you make any local changes, they will be lost
//source: monster_test
package Example
import "github.com/google/flatbuffers/go"
import (
context "golang.org/x/net/context"
grpc "google.golang.org/grpc"
)
// Client API for MonsterStorage service
type MonsterStorageClient interface{
Store(ctx context.Context, in *flatbuffers.Builder,
opts... grpc.CallOption) (* Stat, error)
Retrieve(ctx context.Context, in *flatbuffers.Builder,
opts... grpc.CallOption) (MonsterStorage_RetrieveClient, error)
}
type monsterStorageClient struct {
cc *grpc.ClientConn
}
func NewMonsterStorageClient(cc *grpc.ClientConn) MonsterStorageClient {
return &monsterStorageClient{cc}
}
func (c *monsterStorageClient) Store(ctx context.Context, in *flatbuffers.Builder,
opts... grpc.CallOption) (* Stat, error) {
out := new(Stat)
err := grpc.Invoke(ctx, "/Example.MonsterStorage/Store", in, out, c.cc, opts...)
if err != nil { return nil, err }
return out, nil
}
func (c *monsterStorageClient) Retrieve(ctx context.Context, in *flatbuffers.Builder,
opts... grpc.CallOption) (MonsterStorage_RetrieveClient, error) {
stream, err := grpc.NewClientStream(ctx, &_MonsterStorage_serviceDesc.Streams[0], c.cc, "/Example.MonsterStorage/Retrieve", opts...)
if err != nil { return nil, err }
x := &monsterStorageRetrieveClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil { return nil, err }
if err := x.ClientStream.CloseSend(); err != nil { return nil, err }
return x,nil
}
type MonsterStorage_RetrieveClient interface {
Recv() (*Monster, error)
grpc.ClientStream
}
type monsterStorageRetrieveClient struct{
grpc.ClientStream
}
func (x *monsterStorageRetrieveClient) Recv() (*Monster, error) {
m := new(Monster)
if err := x.ClientStream.RecvMsg(m); err != nil { return nil, err }
return m, nil
}
// Server API for MonsterStorage service
type MonsterStorageServer interface {
Store(context.Context, *Monster) (*flatbuffers.Builder, error)
Retrieve(*Stat, MonsterStorage_RetrieveServer) error
}
func RegisterMonsterStorageServer(s *grpc.Server, srv MonsterStorageServer) {
s.RegisterService(&_MonsterStorage_serviceDesc, srv)
}
func _MonsterStorage_Store_Handler(srv interface{}, ctx context.Context,
dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Monster)
if err := dec(in); err != nil { return nil, err }
if interceptor == nil { return srv.(MonsterStorageServer).Store(ctx, in) }
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/Example.MonsterStorage/Store",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MonsterStorageServer).Store(ctx, req.(* Monster))
}
return interceptor(ctx, in, info, handler)
}
func _MonsterStorage_Retrieve_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(Stat)
if err := stream.RecvMsg(m); err != nil { return err }
return srv.(MonsterStorageServer).Retrieve(m, &monsterStorageRetrieveServer{stream})
}
type MonsterStorage_RetrieveServer interface {
Send(* flatbuffers.Builder) error
grpc.ServerStream
}
type monsterStorageRetrieveServer struct {
grpc.ServerStream
}
func (x *monsterStorageRetrieveServer) Send(m *flatbuffers.Builder) error {
return x.ServerStream.SendMsg(m)
}
var _MonsterStorage_serviceDesc = grpc.ServiceDesc{
ServiceName: "Example.MonsterStorage",
HandlerType: (*MonsterStorageServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "Store",
Handler: _MonsterStorage_Store_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "Retrieve",
Handler: _MonsterStorage_Retrieve_Handler,
ServerStreams: true,
},
},
}

View File

@@ -6,17 +6,21 @@ namespace MyGame.Example
using System;
using FlatBuffers;
public sealed class Stat : Table {
public struct Stat : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static Stat GetRootAsStat(ByteBuffer _bb) { return GetRootAsStat(_bb, new Stat()); }
public static Stat GetRootAsStat(ByteBuffer _bb, Stat obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public Stat __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
public static Stat GetRootAsStat(ByteBuffer _bb, Stat obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
public Stat __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public string Id { get { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; } }
public ArraySegment<byte>? GetIdBytes() { return __vector_as_arraysegment(4); }
public long Val { get { int o = __offset(6); return o != 0 ? bb.GetLong(o + bb_pos) : (long)0; } }
public bool MutateVal(long val) { int o = __offset(6); if (o != 0) { bb.PutLong(o + bb_pos, val); return true; } else { return false; } }
public ushort Count { get { int o = __offset(8); return o != 0 ? bb.GetUshort(o + bb_pos) : (ushort)0; } }
public bool MutateCount(ushort count) { int o = __offset(8); if (o != 0) { bb.PutUshort(o + bb_pos, count); return true; } else { return false; } }
public string Id { get { int o = __p.__offset(4); return o != 0 ? __p.__string(o + __p.bb_pos) : null; } }
public ArraySegment<byte>? GetIdBytes() { return __p.__vector_as_arraysegment(4); }
public long Val { get { int o = __p.__offset(6); return o != 0 ? __p.bb.GetLong(o + __p.bb_pos) : (long)0; } }
public bool MutateVal(long val) { int o = __p.__offset(6); if (o != 0) { __p.bb.PutLong(o + __p.bb_pos, val); return true; } else { return false; } }
public ushort Count { get { int o = __p.__offset(8); return o != 0 ? __p.bb.GetUshort(o + __p.bb_pos) : (ushort)0; } }
public bool MutateCount(ushort count) { int o = __p.__offset(8); if (o != 0) { __p.bb.PutUshort(o + __p.bb_pos, count); return true; } else { return false; } }
public static Offset<Stat> CreateStat(FlatBufferBuilder builder,
StringOffset idOffset = default(StringOffset),

View File

@@ -22,6 +22,10 @@ func (rcv *Stat) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Pos = i
}
func (rcv *Stat) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *Stat) Id() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {

View File

@@ -10,12 +10,13 @@ import com.google.flatbuffers.*;
@SuppressWarnings("unused")
public final class Stat extends Table {
public static Stat getRootAsStat(ByteBuffer _bb) { return getRootAsStat(_bb, new Stat()); }
public static Stat getRootAsStat(ByteBuffer _bb, Stat obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public Stat __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
public static Stat getRootAsStat(ByteBuffer _bb, Stat obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
public Stat __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public String id() { int o = __offset(4); return o != 0 ? __string(o + bb_pos) : null; }
public ByteBuffer idAsByteBuffer() { return __vector_as_bytebuffer(4, 1); }
public long val() { int o = __offset(6); return o != 0 ? bb.getLong(o + bb_pos) : 0; }
public long val() { int o = __offset(6); return o != 0 ? bb.getLong(o + bb_pos) : 0L; }
public boolean mutateVal(long val) { int o = __offset(6); if (o != 0) { bb.putLong(o + bb_pos, val); return true; } else { return false; } }
public int count() { int o = __offset(8); return o != 0 ? bb.getShort(o + bb_pos) & 0xFFFF : 0; }
public boolean mutateCount(int count) { int o = __offset(8); if (o != 0) { bb.putShort(o + bb_pos, (short)count); return true; } else { return false; } }
@@ -33,8 +34,8 @@ public final class Stat extends Table {
public static void startStat(FlatBufferBuilder builder) { builder.startObject(3); }
public static void addId(FlatBufferBuilder builder, int idOffset) { builder.addOffset(0, idOffset, 0); }
public static void addVal(FlatBufferBuilder builder, long val) { builder.addLong(1, val, 0); }
public static void addCount(FlatBufferBuilder builder, int count) { builder.addShort(2, (short)count, 0); }
public static void addVal(FlatBufferBuilder builder, long val) { builder.addLong(1, val, 0L); }
public static void addCount(FlatBufferBuilder builder, int count) { builder.addShort(2, (short)count, (short)0); }
public static int endStat(FlatBufferBuilder builder) {
int o = builder.endObject();
return o;

View File

@@ -6,13 +6,17 @@ namespace MyGame.Example
using System;
using FlatBuffers;
public sealed class Test : Struct {
public Test __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
public struct Test : IFlatbufferObject
{
private Struct __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
public Test __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public short A { get { return bb.GetShort(bb_pos + 0); } }
public void MutateA(short a) { bb.PutShort(bb_pos + 0, a); }
public sbyte B { get { return bb.GetSbyte(bb_pos + 2); } }
public void MutateB(sbyte b) { bb.PutSbyte(bb_pos + 2, b); }
public short A { get { return __p.bb.GetShort(__p.bb_pos + 0); } }
public void MutateA(short a) { __p.bb.PutShort(__p.bb_pos + 0, a); }
public sbyte B { get { return __p.bb.GetSbyte(__p.bb_pos + 2); } }
public void MutateB(sbyte b) { __p.bb.PutSbyte(__p.bb_pos + 2, b); }
public static Offset<Test> CreateTest(FlatBufferBuilder builder, short A, sbyte B) {
builder.Prep(2, 4);

View File

@@ -15,6 +15,10 @@ func (rcv *Test) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Pos = i
}
func (rcv *Test) Table() flatbuffers.Table {
return rcv._tab.Table
}
func (rcv *Test) A() int16 {
return rcv._tab.GetInt16(rcv._tab.Pos + flatbuffers.UOffsetT(0))
}

View File

@@ -9,7 +9,8 @@ import com.google.flatbuffers.*;
@SuppressWarnings("unused")
public final class Test extends Struct {
public Test __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
public Test __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public short a() { return bb.getShort(bb_pos + 0); }
public void mutateA(short a) { bb.putShort(bb_pos + 0, a); }

View File

@@ -6,13 +6,17 @@ namespace MyGame.Example
using System;
using FlatBuffers;
public partial class TestSimpleTableWithEnum : Table {
public partial struct TestSimpleTableWithEnum : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static TestSimpleTableWithEnum GetRootAsTestSimpleTableWithEnum(ByteBuffer _bb) { return GetRootAsTestSimpleTableWithEnum(_bb, new TestSimpleTableWithEnum()); }
public static TestSimpleTableWithEnum GetRootAsTestSimpleTableWithEnum(ByteBuffer _bb, TestSimpleTableWithEnum obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public TestSimpleTableWithEnum __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
public static TestSimpleTableWithEnum GetRootAsTestSimpleTableWithEnum(ByteBuffer _bb, TestSimpleTableWithEnum obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
public TestSimpleTableWithEnum __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public Color Color { get { int o = __offset(4); return o != 0 ? (Color)bb.GetSbyte(o + bb_pos) : Color.Green; } }
public bool MutateColor(Color color) { int o = __offset(4); if (o != 0) { bb.PutSbyte(o + bb_pos, (sbyte)color); return true; } else { return false; } }
public Color Color { get { int o = __p.__offset(4); return o != 0 ? (Color)__p.bb.GetSbyte(o + __p.bb_pos) : Color.Green; } }
public bool MutateColor(Color color) { int o = __p.__offset(4); if (o != 0) { __p.bb.PutSbyte(o + __p.bb_pos, (sbyte)color); return true; } else { return false; } }
public static Offset<TestSimpleTableWithEnum> CreateTestSimpleTableWithEnum(FlatBufferBuilder builder,
Color color = Color.Green) {

View File

@@ -22,6 +22,10 @@ func (rcv *TestSimpleTableWithEnum) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Pos = i
}
func (rcv *TestSimpleTableWithEnum) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *TestSimpleTableWithEnum) Color() int8 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {

View File

@@ -10,8 +10,9 @@ import com.google.flatbuffers.*;
@SuppressWarnings("unused")
public final class TestSimpleTableWithEnum extends Table {
public static TestSimpleTableWithEnum getRootAsTestSimpleTableWithEnum(ByteBuffer _bb) { return getRootAsTestSimpleTableWithEnum(_bb, new TestSimpleTableWithEnum()); }
public static TestSimpleTableWithEnum getRootAsTestSimpleTableWithEnum(ByteBuffer _bb, TestSimpleTableWithEnum obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public TestSimpleTableWithEnum __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
public static TestSimpleTableWithEnum getRootAsTestSimpleTableWithEnum(ByteBuffer _bb, TestSimpleTableWithEnum obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
public TestSimpleTableWithEnum __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public byte color() { int o = __offset(4); return o != 0 ? bb.get(o + bb_pos) : 2; }
public boolean mutateColor(byte color) { int o = __offset(4); if (o != 0) { bb.put(o + bb_pos, color); return true; } else { return false; } }

View File

@@ -6,21 +6,24 @@ namespace MyGame.Example
using System;
using FlatBuffers;
public sealed class Vec3 : Struct {
public Vec3 __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
public struct Vec3 : IFlatbufferObject
{
private Struct __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
public Vec3 __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public float X { get { return bb.GetFloat(bb_pos + 0); } }
public void MutateX(float x) { bb.PutFloat(bb_pos + 0, x); }
public float Y { get { return bb.GetFloat(bb_pos + 4); } }
public void MutateY(float y) { bb.PutFloat(bb_pos + 4, y); }
public float Z { get { return bb.GetFloat(bb_pos + 8); } }
public void MutateZ(float z) { bb.PutFloat(bb_pos + 8, z); }
public double Test1 { get { return bb.GetDouble(bb_pos + 16); } }
public void MutateTest1(double test1) { bb.PutDouble(bb_pos + 16, test1); }
public Color Test2 { get { return (Color)bb.GetSbyte(bb_pos + 24); } }
public void MutateTest2(Color test2) { bb.PutSbyte(bb_pos + 24, (sbyte)test2); }
public Test Test3 { get { return GetTest3(new Test()); } }
public Test GetTest3(Test obj) { return obj.__init(bb_pos + 26, bb); }
public float X { get { return __p.bb.GetFloat(__p.bb_pos + 0); } }
public void MutateX(float x) { __p.bb.PutFloat(__p.bb_pos + 0, x); }
public float Y { get { return __p.bb.GetFloat(__p.bb_pos + 4); } }
public void MutateY(float y) { __p.bb.PutFloat(__p.bb_pos + 4, y); }
public float Z { get { return __p.bb.GetFloat(__p.bb_pos + 8); } }
public void MutateZ(float z) { __p.bb.PutFloat(__p.bb_pos + 8, z); }
public double Test1 { get { return __p.bb.GetDouble(__p.bb_pos + 16); } }
public void MutateTest1(double test1) { __p.bb.PutDouble(__p.bb_pos + 16, test1); }
public Color Test2 { get { return (Color)__p.bb.GetSbyte(__p.bb_pos + 24); } }
public void MutateTest2(Color test2) { __p.bb.PutSbyte(__p.bb_pos + 24, (sbyte)test2); }
public Test Test3 { get { return (new Test()).__assign(__p.bb_pos + 26, __p.bb); } }
public static Offset<Vec3> CreateVec3(FlatBufferBuilder builder, float X, float Y, float Z, double Test1, Color Test2, short test3_A, sbyte test3_B) {
builder.Prep(16, 32);

View File

@@ -15,6 +15,10 @@ func (rcv *Vec3) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Pos = i
}
func (rcv *Vec3) Table() flatbuffers.Table {
return rcv._tab.Table
}
func (rcv *Vec3) X() float32 {
return rcv._tab.GetFloat32(rcv._tab.Pos + flatbuffers.UOffsetT(0))
}

View File

@@ -9,7 +9,8 @@ import com.google.flatbuffers.*;
@SuppressWarnings("unused")
public final class Vec3 extends Struct {
public Vec3 __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
public Vec3 __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public float x() { return bb.getFloat(bb_pos + 0); }
public void mutateX(float x) { bb.putFloat(bb_pos + 0, x); }
@@ -22,7 +23,7 @@ public final class Vec3 extends Struct {
public byte test2() { return bb.get(bb_pos + 24); }
public void mutateTest2(byte test2) { bb.put(bb_pos + 24, test2); }
public Test test3() { return test3(new Test()); }
public Test test3(Test obj) { return obj.__init(bb_pos + 26, bb); }
public Test test3(Test obj) { return obj.__assign(bb_pos + 26, bb); }
public static int createVec3(FlatBufferBuilder builder, float x, float y, float z, double test1, byte test2, short test3_a, byte test3_b) {
builder.prep(16, 32);

View File

@@ -6,16 +6,20 @@ namespace MyGame.Example2
using System;
using FlatBuffers;
public sealed class Monster : Table {
public struct Monster : IFlatbufferObject
{
private Table __p;
public ByteBuffer ByteBuffer { get { return __p.bb; } }
public static Monster GetRootAsMonster(ByteBuffer _bb) { return GetRootAsMonster(_bb, new Monster()); }
public static Monster GetRootAsMonster(ByteBuffer _bb, Monster obj) { return (obj.__init(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public Monster __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
public static Monster GetRootAsMonster(ByteBuffer _bb, Monster obj) { return (obj.__assign(_bb.GetInt(_bb.Position) + _bb.Position, _bb)); }
public void __init(int _i, ByteBuffer _bb) { __p.bb_pos = _i; __p.bb = _bb; }
public Monster __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public static void StartMonster(FlatBufferBuilder builder) { builder.StartObject(0); }
public static Offset<MyGame.Example2.Monster> EndMonster(FlatBufferBuilder builder) {
public static Offset<Monster> EndMonster(FlatBufferBuilder builder) {
int o = builder.EndObject();
return new Offset<MyGame.Example2.Monster>(o);
return new Offset<Monster>(o);
}
};

View File

@@ -22,6 +22,10 @@ func (rcv *Monster) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Pos = i
}
func (rcv *Monster) Table() flatbuffers.Table {
return rcv._tab
}
func MonsterStart(builder *flatbuffers.Builder) {
builder.StartObject(0)
}

View File

@@ -10,8 +10,9 @@ import com.google.flatbuffers.*;
@SuppressWarnings("unused")
public final class Monster extends Table {
public static Monster getRootAsMonster(ByteBuffer _bb) { return getRootAsMonster(_bb, new Monster()); }
public static Monster getRootAsMonster(ByteBuffer _bb, Monster obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__init(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public Monster __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; return this; }
public static Monster getRootAsMonster(ByteBuffer _bb, Monster obj) { _bb.order(ByteOrder.LITTLE_ENDIAN); return (obj.__assign(_bb.getInt(_bb.position()) + _bb.position(), _bb)); }
public void __init(int _i, ByteBuffer _bb) { bb_pos = _i; bb = _bb; }
public Monster __assign(int _i, ByteBuffer _bb) { __init(_i, _bb); return this; }
public static void startMonster(FlatBufferBuilder builder) { builder.startObject(0); }

View File

@@ -12,6 +12,9 @@
:: See the License for the specific language governing permissions and
:: limitations under the License.
..\flatc.exe --cpp --java --csharp --go --binary --python --js --php --grpc --gen-mutable --gen-object-api --no-includes monster_test.fbs monsterdata_test.json
..\flatc.exe --cpp --java --csharp --go --binary --python --js --php --gen-mutable -o namespace_test namespace_test\namespace_test1.fbs namespace_test\namespace_test2.fbs
..\flatc.exe --binary --schema monster_test.fbs
set buildtype=Release
if "%1"=="-b" set buildtype=%2
..\%buildtype%\flatc.exe --cpp --java --csharp --go --binary --python --js --php --grpc --gen-mutable --gen-object-api --no-includes monster_test.fbs monsterdata_test.json
..\%buildtype%\flatc.exe --cpp --java --csharp --go --binary --python --js --php --gen-mutable -o namespace_test namespace_test\namespace_test1.fbs namespace_test\namespace_test2.fbs
..\%buildtype%\flatc.exe --binary --schema monster_test.fbs

3
tests/generate_code.sh Normal file → Executable file
View File

@@ -16,7 +16,8 @@
../flatc --cpp --java --csharp --go --binary --python --js --php --grpc --gen-mutable --gen-object-api --no-includes monster_test.fbs monsterdata_test.json
../flatc --cpp --java --csharp --go --binary --python --js --php --gen-mutable -o namespace_test namespace_test/namespace_test1.fbs namespace_test/namespace_test2.fbs
../flatc --binary --schema monster_test.fbs
../flatc --cpp -o union_vector ./union_vector/union_vector.fbs
../flatc -b --schema --bfbs-comments monster_test.fbs
cd ../samples
../flatc --cpp --gen-mutable --gen-object-api monster.fbs
cd ../reflection

View File

@@ -78,6 +78,7 @@ func TestAll(t *testing.T) {
// Verify that GetRootAs works for non-root tables
CheckGetRootAsForNonRootTable(t.Fatalf)
CheckTableAccessors(t.Fatalf)
// Verify that using the generated Go code builds a buffer without
// returning errors:
@@ -137,155 +138,159 @@ func TestAll(t *testing.T) {
// CheckReadBuffer checks that the given buffer is evaluated correctly
// as the example Monster.
func CheckReadBuffer(buf []byte, offset flatbuffers.UOffsetT, fail func(string, ...interface{})) {
monster := example.GetRootAsMonster(buf, offset)
if got := monster.Hp(); 80 != got {
fail(FailString("hp", 80, got))
}
// default
if got := monster.Mana(); 150 != got {
fail(FailString("mana", 150, got))
}
if got := monster.Name(); !bytes.Equal([]byte("MyMonster"), got) {
fail(FailString("name", "MyMonster", got))
}
// initialize a Vec3 from Pos()
vec := new(example.Vec3)
vec = monster.Pos(vec)
if vec == nil {
fail("vec3 initialization failed")
}
// check that new allocs equal given ones:
vec2 := monster.Pos(nil)
if !reflect.DeepEqual(vec, vec2) {
fail("fresh allocation failed")
}
// verify the properties of the Vec3
if got := vec.X(); float32(1.0) != got {
fail(FailString("Pos.X", float32(1.0), got))
}
if got := vec.Y(); float32(2.0) != got {
fail(FailString("Pos.Y", float32(2.0), got))
}
if got := vec.Z(); float32(3.0) != got {
fail(FailString("Pos.Z", float32(3.0), got))
}
if got := vec.Test1(); float64(3.0) != got {
fail(FailString("Pos.Test1", float64(3.0), got))
}
if got := vec.Test2(); int8(2) != got {
fail(FailString("Pos.Test2", int8(2), got))
}
// initialize a Test from Test3(...)
t := new(example.Test)
t = vec.Test3(t)
if t == nil {
fail("vec.Test3(&t) failed")
}
// check that new allocs equal given ones:
t2 := vec.Test3(nil)
if !reflect.DeepEqual(t, t2) {
fail("fresh allocation failed")
}
// verify the properties of the Test
if got := t.A(); int16(5) != got {
fail(FailString("t.A()", int16(5), got))
}
if got := t.B(); int8(6) != got {
fail(FailString("t.B()", int8(6), got))
}
if got := monster.TestType(); example.AnyMonster != got {
fail(FailString("monster.TestType()", example.AnyMonster, got))
}
// initialize a Table from a union field Test(...)
var table2 flatbuffers.Table
if ok := monster.Test(&table2); !ok {
fail("monster.Test(&monster2) failed")
}
// initialize a Monster from the Table from the union
var monster2 example.Monster
monster2.Init(table2.Bytes, table2.Pos)
if got := monster2.Name(); !bytes.Equal([]byte("Fred"), got) {
fail(FailString("monster2.Name()", "Fred", got))
}
inventorySlice := monster.InventoryBytes()
if len(inventorySlice) != monster.InventoryLength() {
fail(FailString("len(monster.InventoryBytes) != monster.InventoryLength", len(inventorySlice), monster.InventoryLength()))
}
if got := monster.InventoryLength(); 5 != got {
fail(FailString("monster.InventoryLength", 5, got))
}
invsum := 0
l := monster.InventoryLength()
for i := 0; i < l; i++ {
v := monster.Inventory(i)
if v != inventorySlice[i] {
fail(FailString("monster inventory slice[i] != Inventory(i)", v, inventorySlice[i]))
// try the two ways of generating a monster
monster1 := example.GetRootAsMonster(buf, offset)
monster2 := &example.Monster{}
flatbuffers.GetRootAs(buf, offset, monster2)
for _, monster := range []*example.Monster{monster1, monster2} {
if got := monster.Hp(); 80 != got {
fail(FailString("hp", 80, got))
}
invsum += int(v)
}
if invsum != 10 {
fail(FailString("monster inventory sum", 10, invsum))
}
if got := monster.Test4Length(); 2 != got {
fail(FailString("monster.Test4Length()", 2, got))
}
// default
if got := monster.Mana(); 150 != got {
fail(FailString("mana", 150, got))
}
var test0 example.Test
ok := monster.Test4(&test0, 0)
if !ok {
fail(FailString("monster.Test4(&test0, 0)", true, ok))
}
if got := monster.Name(); !bytes.Equal([]byte("MyMonster"), got) {
fail(FailString("name", "MyMonster", got))
}
var test1 example.Test
ok = monster.Test4(&test1, 1)
if !ok {
fail(FailString("monster.Test4(&test1, 1)", true, ok))
}
// initialize a Vec3 from Pos()
vec := new(example.Vec3)
vec = monster.Pos(vec)
if vec == nil {
fail("vec3 initialization failed")
}
// the position of test0 and test1 are swapped in monsterdata_java_wire
// and monsterdata_test_wire, so ignore ordering
v0 := test0.A()
v1 := test0.B()
v2 := test1.A()
v3 := test1.B()
sum := int(v0) + int(v1) + int(v2) + int(v3)
// check that new allocs equal given ones:
vec2 := monster.Pos(nil)
if !reflect.DeepEqual(vec, vec2) {
fail("fresh allocation failed")
}
if 100 != sum {
fail(FailString("test0 and test1 sum", 100, sum))
}
// verify the properties of the Vec3
if got := vec.X(); float32(1.0) != got {
fail(FailString("Pos.X", float32(1.0), got))
}
if got := monster.TestarrayofstringLength(); 2 != got {
fail(FailString("Testarrayofstring length", 2, got))
}
if got := vec.Y(); float32(2.0) != got {
fail(FailString("Pos.Y", float32(2.0), got))
}
if got := monster.Testarrayofstring(0); !bytes.Equal([]byte("test1"), got) {
fail(FailString("Testarrayofstring(0)", "test1", got))
}
if got := vec.Z(); float32(3.0) != got {
fail(FailString("Pos.Z", float32(3.0), got))
}
if got := monster.Testarrayofstring(1); !bytes.Equal([]byte("test2"), got) {
fail(FailString("Testarrayofstring(1)", "test2", got))
if got := vec.Test1(); float64(3.0) != got {
fail(FailString("Pos.Test1", float64(3.0), got))
}
if got := vec.Test2(); int8(2) != got {
fail(FailString("Pos.Test2", int8(2), got))
}
// initialize a Test from Test3(...)
t := new(example.Test)
t = vec.Test3(t)
if t == nil {
fail("vec.Test3(&t) failed")
}
// check that new allocs equal given ones:
t2 := vec.Test3(nil)
if !reflect.DeepEqual(t, t2) {
fail("fresh allocation failed")
}
// verify the properties of the Test
if got := t.A(); int16(5) != got {
fail(FailString("t.A()", int16(5), got))
}
if got := t.B(); int8(6) != got {
fail(FailString("t.B()", int8(6), got))
}
if got := monster.TestType(); example.AnyMonster != got {
fail(FailString("monster.TestType()", example.AnyMonster, got))
}
// initialize a Table from a union field Test(...)
var table2 flatbuffers.Table
if ok := monster.Test(&table2); !ok {
fail("monster.Test(&monster2) failed")
}
// initialize a Monster from the Table from the union
var monster2 example.Monster
monster2.Init(table2.Bytes, table2.Pos)
if got := monster2.Name(); !bytes.Equal([]byte("Fred"), got) {
fail(FailString("monster2.Name()", "Fred", got))
}
inventorySlice := monster.InventoryBytes()
if len(inventorySlice) != monster.InventoryLength() {
fail(FailString("len(monster.InventoryBytes) != monster.InventoryLength", len(inventorySlice), monster.InventoryLength()))
}
if got := monster.InventoryLength(); 5 != got {
fail(FailString("monster.InventoryLength", 5, got))
}
invsum := 0
l := monster.InventoryLength()
for i := 0; i < l; i++ {
v := monster.Inventory(i)
if v != inventorySlice[i] {
fail(FailString("monster inventory slice[i] != Inventory(i)", v, inventorySlice[i]))
}
invsum += int(v)
}
if invsum != 10 {
fail(FailString("monster inventory sum", 10, invsum))
}
if got := monster.Test4Length(); 2 != got {
fail(FailString("monster.Test4Length()", 2, got))
}
var test0 example.Test
ok := monster.Test4(&test0, 0)
if !ok {
fail(FailString("monster.Test4(&test0, 0)", true, ok))
}
var test1 example.Test
ok = monster.Test4(&test1, 1)
if !ok {
fail(FailString("monster.Test4(&test1, 1)", true, ok))
}
// the position of test0 and test1 are swapped in monsterdata_java_wire
// and monsterdata_test_wire, so ignore ordering
v0 := test0.A()
v1 := test0.B()
v2 := test1.A()
v3 := test1.B()
sum := int(v0) + int(v1) + int(v2) + int(v3)
if 100 != sum {
fail(FailString("test0 and test1 sum", 100, sum))
}
if got := monster.TestarrayofstringLength(); 2 != got {
fail(FailString("Testarrayofstring length", 2, got))
}
if got := monster.Testarrayofstring(0); !bytes.Equal([]byte("test1"), got) {
fail(FailString("Testarrayofstring(0)", "test1", got))
}
if got := monster.Testarrayofstring(1); !bytes.Equal([]byte("test2"), got) {
fail(FailString("Testarrayofstring(1)", "test2", got))
}
}
}
@@ -1161,6 +1166,38 @@ func CheckGeneratedBuild(fail func(string, ...interface{})) ([]byte, flatbuffers
return b.Bytes, b.Head()
}
// CheckTableAccessors checks that the table accessors work as expected.
func CheckTableAccessors(fail func(string, ...interface{})) {
// test struct accessor
b := flatbuffers.NewBuilder(0)
pos := example.CreateVec3(b, 1.0, 2.0, 3.0, 3.0, 4, 5, 6)
b.Finish(pos)
vec3Bytes := b.FinishedBytes()
vec3 := &example.Vec3{}
flatbuffers.GetRootAs(vec3Bytes, 0, vec3)
if bytes.Compare(vec3Bytes, vec3.Table().Bytes) != 0 {
fail("invalid vec3 table")
}
// test table accessor
b = flatbuffers.NewBuilder(0)
str := b.CreateString("MyStat")
example.StatStart(b)
example.StatAddId(b, str)
example.StatAddVal(b, 12345678)
example.StatAddCount(b, 12345)
pos = example.StatEnd(b)
b.Finish(pos)
statBytes := b.FinishedBytes()
stat := &example.Stat{}
flatbuffers.GetRootAs(statBytes, 0, stat)
if bytes.Compare(statBytes, stat.Table().Bytes) != 0 {
fail("invalid stat table")
}
}
// CheckVtableDeduplication verifies that vtables are deduplicated.
func CheckVtableDeduplication(fail func(string, ...interface{})) {
b := flatbuffers.NewBuilder(0)
@@ -1214,9 +1251,9 @@ func CheckVtableDeduplication(fail func(string, ...interface{})) {
len(want), want, len(got), got)
}
table0 := &flatbuffers.Table{b.Bytes, flatbuffers.UOffsetT(len(b.Bytes)) - obj0}
table1 := &flatbuffers.Table{b.Bytes, flatbuffers.UOffsetT(len(b.Bytes)) - obj1}
table2 := &flatbuffers.Table{b.Bytes, flatbuffers.UOffsetT(len(b.Bytes)) - obj2}
table0 := &flatbuffers.Table{Bytes: b.Bytes, Pos: flatbuffers.UOffsetT(len(b.Bytes)) - obj0}
table1 := &flatbuffers.Table{Bytes: b.Bytes, Pos: flatbuffers.UOffsetT(len(b.Bytes)) - obj1}
table2 := &flatbuffers.Table{Bytes: b.Bytes, Pos: flatbuffers.UOffsetT(len(b.Bytes)) - obj2}
testTable := func(tab *flatbuffers.Table, a flatbuffers.VOffsetT, b, c, d byte) {
// vtable size

Binary file not shown.

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