Squashed 'third_party/flatbuffers/' changes from acc9990ab..d6a8dbd26
d6a8dbd26 Experimental fix for failing oss-fuzz coverage build (#6259)
ed391e177 BREAKING: Rust flexbuffers serde human readable set to false (#6257)
a49531414 Update to flags in fuzzing-cmake file (#6256)
de1f0342c Remove _POSIX_C_SOURCE and _XOPEN_SOURCE definitions when compiling o… (#6205)
d0d51e2a5 flatc should support --binary --schema with optional scalar fields. (#6252)
33ab26017 Bump version of rules_go to 0.24.5 (#6234)
febb9d87c Union As Accessors for C# (#6251)
8778dc7c2 Resets buffer without deallocating current pointer (#6247)
aae376e9a Add GetBufferSpan() function to bufferbuilder (#6235)
0ff047148 Modernize android build and sample (#6229)
46a8c7e95 Added required-nested-flatbuffer to monster_test and fixed rust (#6236)
bc56c553e Notify based on Labelling issues and PR (#6241)
07d7cd78a Converted globs to use single quotes (#6240)
cdef70e24 More adjustments to the auto labeler (#6239)
9dd44df35 Updated Lua labeller glob (#6238)
c9b29d088 Support size-prefixed buffers and add tests for size-prefixed messages (#6232)
fba93e0ab Removes duplicate swift in labeler (#6228)
d1a545b1f Added more labels for auto labeler (#6227)
ea92a668d [C#] Optional Scalars (#6217)
6034de286 [Label Bot] Add Java and Kotlin support for the label bot (#6226)
b08b0a440 Implement `Debug` trait for Rust flatbuffers. (#6207)
17ae48dec [Label Bot] Adds some languages to labeler bot (#6222)
fc8097925 Auto Labeler Setup, Just C# for now (#6221)
55658f523 Auto Labeler Setup, Just C# for now (#6218)
14ecfe423 Updated comments and fixed a fundamental type error. (#6214)
a0182cdb1 optional scalars for ts/js (#6215)
0dfcc0a37 Adds NetTest.bat to run .NET Core tests on Windows (#6216)
f9a18ea63 [Java] Implement optional scalars (#6212)
c7586e85a Empties the sharedString map on reset on go and csharp (#6187)
914c64601 Removed C# references from java generator. Move annotations closer to definitions (#6204)
42d7c7997 Adds readable size to asserts in read functions (#6210)
e68e8d7de Refactor idl_gen_rust (#6206)
84809be7e Fix typo in flatbuffers::span declaration. (#6202)
1606fb637 Kotlin test optional enum (#6201)
fe8e3c7e5 Mass Refactoring to use `IsString` and other BASE_TYPE helpers (#6193)
8f6fa4b71 Updated SupportsAdvancedUnionFeatures to look out for string (#6190)
b46db38f5 [JS/TS] Rewrite flexbuffers JS to TS (#6148)
9fa1d2705 Rework enums in rust. (#6098)
a402b3aba idl_gen_json_schema Fix generation of arrays of enums (#6184)
0e1415b99 fix(go_test): remove deprecated grpc call (#6183)
5cd713710 Add generation of JSON Schema to library (#6165)
5be777e1d Bump junit from 4.12 to 4.13.1 in /grpc/tests (#6173)
a49d440ec Bump junit from 4.12 to 4.13.1 in /grpc (#6172)
4ec5e8db9 [C++] Add option to not generate direct copy methods. (#6166)
04bec23a3 Add Array initialization from struct constructor (#5865) (#6147)
77d57fd07 Cast to right type for reserved_ subtraction (#6167)
543c1bbeb Fixed rust nested flatbuffers for tables other than self (#6062)
cb971eece [C++] Fix -Wnarrowing and -Woverflow due to signed bitfields on G++ ARM (#6163)
7b9e61fcc [TS] GRPC Implementation (#6141)
3359e3042 Moved C++ to optional_scalars2 and added some tests. (#6162)
187a4787f [Rust] Upgrade flatbuffers library to 2018 edition (#6159)
08943aa26 Flatbuffer C++ UnpackTo optimization for vectors of non-bool bytes. (#6154)
5975658eb Enables optional enums in swift (#6160)
5d3cf440e Updated Lobster test for optional bools/enums
8ec8322f0 Ruopt enum (#6156)
bbcc85fd4 Fix generation of C++ code with Optional<Enum> (#6155)
0bdf2fa15 [C#] Fix and improve project files (#6142)
2eedc769d possibility to create a vector from an iterator (#6135)
ab01ae162 flatc should output a warning, when an attribute is attached more than once (#6146)
689bfafa7 [Python/JS/TS] Codegen SizeOf method for structs (#6136)
641309a5b unix2dos on tests/FlatBuffers.Test/FlatBuffers.Core.Test.csproj (#6133)
52e362879 SpanT is available in .Net Standard 2.0. (#6137)
dca12522a Add static cast to avoid implicit double promotion. (#6132)
e0bbaa6f9 [C#]Change to ENABLE_SPAN_T that doesn't require UNSAFE_BYTEBUFFER. (#6073)
ab139d6be Revert "[C#] Fix and improve project files (#6116)" (#6130)
34d67b425 Minireflect fixed array (#6129)
96d5e3597 [JS/TS] fix flatbuffers default export (#6123)
eb686a86f Add missed file generated by optional_scalar.fbs (#6125)
750281630 [C#] Fix and improve project files (#6116)
fb4e1c34f Add CharToLower and CharToUpper into util.s (#6126)
8c67b5b12 Add support of Optional<T> scalars to C++ code generator (#6092)
6228b66d3 [Kotlin] Support for optional scalars. (#6115)
e1be8aaad Bump version for latest swift version (#6121)
94873e595 [JS/TS] Modernize TypeScript / JavaScript flatbuffers support (#6095)
b8e87fafe [JS] Add getFullyQualifiedName() (#6119)
f96d1ef74 [Java] allowing larger buffer sizes when growing a byte buffer (#6118)
89435303b [Swift] Migrates struct write APIS to write directly to the buffer (#6093)
c75ae2429 Optional-ness in reflection (#6097)
338944d3d Rename Nullable scalars to Optional scalars (#6112)
f5ab24bc4 Avoid memcpy call for empty vectors (#6111)
92a8c1a0f [JS] FlexBuffers Fix for wrong type of offset and length values (#6107)
6cea45dcd fix c# json serializer commandline argument docs (#6104)
fec58aa12 Fix for issue 6100: incorrect shrinking logic in ResizeContext() (#6102)
71aca81ff [JS] FlexBuffers Support (#5973)
04d87ffec [C++] Small refactoring of the C++ code generator (#6091)
bb25956f0 Wrap verify file id condition in Check call (#6085)
49f4948f0 + Add `removable-media` plug to the snapcraft config (#6083)
eeacc53d2 Adds proper access types for swift object api & flatbuffers & grpc (#6081)
f3003e08d [Lobster] missed a test
d713a0084 [CMake] enabled multi-core builds in VS projects
77f966f89 [Lobster] optional scalars support
e86d5b8e9 [Kotlin] Attach JvmStatic annotation to each method in companion object (#6052)
db2aa9b4e [C#] Cleaned up .NET testing script for Mono (#6016)
63cc0eec4 Adds a serialize helper function to native table (#6059)
c30a87de6 [TS] Fix four bugs with imported types in TypeScript. (#6054)
a0fb30575 [Swift] Append namespace for Swift Grpc implementation (#6049)
77c18c1d6 export a __version__ variable for python module (#5309)
f1f23d08e adding fb import when no other imports are present (#6030)
f1025b284 [Feature] Checks for Nullable strings (#6050)
5d052f4e5 [Swift] RFC: Switch Swift namespace from public enum to ordinary concat with _ (#6045)
18b015d25 Rust codegen improvements and lint fixes (#6046)
d76e93f27 adds code gen for optional scalars in swift (#6038)
82fac326c [C++] Fix compiler error from deleted assignment operator (#6036) (#6047)
043b52bd4 Optional Scalars support for Rust (#6034)
c8fa0afdf Allow to run cpp tests under grpc/tests/ using bazel. (#6040)
6d0aae73c Fix git command executed in wrong folder when doing cmake superbuild (#6039)
ff1b73128 [Swift] Optional Scalars Preparation (#6028)
2e48c8dd3 tests: Check for both quiet and signaling NaN on mipsel/hppa (#6029)
6942704f2 support deprecated flag in json schema (#6022)
9ecd2e16c Flatc parser support for nullable scalars (#6026)
33e2d8079 [Dart] Generate constant values map for enums (#6025)
969d0f7a6 Using proper symbol name for reexport (#6021)
515a4052a Silence false positive "-Wstringop-overflow" on GCC 10.0 to 11.0 (#6020)
36fbe6f13 Updated FB import (#6019)
b69fc8cc9 [Java] Add support for shared strings on FlatBufferBuilder. (#6012)
ab6af18d9 Not using non-existent create method for obj api (#6015)
37a5dee10 Code cleanup + updates test and readme (#6004)
8a721f69a Serde with bytes maps to Blob (#6009)
e810635ea [Swift] FlatBuffers createMonster method doesn't treat struct properly (#5992)
4995e1527 Manage grpc dependency in Bazel's WORKSPACE file. (#5995)
60b6066fe Add warning to schema parser if field name is not snake_case. (#6005)
35d45cac7 [Rust] Flexbuffers dependency cleanup and fixes (#5998)
165a6e3d1 Re-added Evolution Schema Code Generation Command (#5999)
13d3fb2ea Fix RPM install conflict (#6003)
d64078eb2 [Swift] Initialize memory when clear ByteBuffer (#5982)
ca1190a3d [TS] Use proper TypedArray in create*Vector (#5991)
7571b2ac5 [C++] Updates real_path to be truly portable (#5787)
e5a8f76a4 [C++] Generate default member initializers for >= C++11 (#5989)
413bb9b55 [Kotlin] Fix Access to union of vector element (#5994)
f35184aef [Swift] Add parsing from unowned UnsafeMutableRawPointer for ByteBuffer (#5981)
b124b7625 Removed requirement that enums be declared in ascending order. (#5887)
0ec7600c6 Do not remove the last digit from float values (#5974)
14baf45c9 Mark GetBufferMinAlignment() const (#5985)
9abb2ec2c TypeScript/JavaScript docs improvements (#5984)
2e57d80b1 [Swift] Internal library improvements (#5965)
cfc7753a4 [Doc] Added missing letters to compiler options (#5976)
12ddc8a92 Rust Flexbuffers Documentation update (#5979)
24ad35709 [docs] typo: updates monsterdata.json to be valid json (#5978)
cc44a4442 [idl_parser] Mark typefield as deprecated (#5958)
9ab4a5c0e Deleted old stale bot
6682cfe87 Increased Operations per run in stale.yml
64922904b Adding Stale Action to clean up PR and Issues
8e505cb67 [C++] Fixed/Enabled --cpp-ptr-type std::shared_ptr [#5813] (#5959)
a28357d7a Propagate boolean default values from proto to fbs (#5964)
7cb4762a6 [Swift] Improving reallocation time by using memcpy and moving reallocation code to storage (#5960)
4e45f7c9e Fix error in SimpleQSort (#5955)
7ac026405 fix error on GRPC Python - ignore namespace tree if not specified (#5862) (#5922)
108e981db Required is now implemented in swift (#5952)
94a78e385 Fixed: Access violation and ASAN/UNSAN failures with sorted tables
53fb453e0 [rust] Add FlatBufferBuilder::force_defaults API (#5946)
17c1f35fa [FlexBuffer][Java] ReadWriteBuf and ReadBuf interface public (#5948)
2eaf57778 [Java] Grow ArrayReadWriteBuf enough to match requested capacity. (#5921)
666800da3 Adds bool support in structs + updates grpc support + CI upgrades (#5943)
38ed69eb3 fixed mutating inline values (#5942)
d026e6f07 Add static asserts to ensure that reflection API arrays are kept in sync (#5934)
988164f6e [C++] Got rid of memset's in constructors (#5938)
7179a5a8b General Codebase clean up (#5939)
a0da0c08c Add GetStringView like GetString, GetCstring (#5937)
ac203b209 [C#] Add file identifier to ObjectAPI Serialization Utility. (#5920)
8dd1bf25b not creating creation methods when using structs (#5919)
5aa443d98 [Dart] Adding FlexBuffers support (#5853)
0fa087657 [Dart] Getting tests/DartTest.sh to work on master. (#5915)
424a473e1 Schema parser: prohibit declaration of an array of pointers inside structs (#5907)
c3faa8346 Fix Cargo.toml dependencies (#5911)
91399ad05 fix union type names (#5902)
32782e4ad Update Rust Flexbuffers metadata before publishing (#5905)
e7f3b1690 [TS] Make Obj-API work with --short-names (#5898)
12ed1fe4a fixed invalid imports with --gen-all (#5895)
85ee4df7a [C#] Thread safe reads of Double and Float values from a ByteBuffer (#5900)
de89bd193 Implement flexbuffers in python (#5880)
8be05f6bd Rust Flexbuffers (#5669)
870ecbc09 [swift] Moves code to use VTablesStorage (#5888)
c2da8d5d8 [Java][FlexBuffers] Make FlexBuffersBuilder reusable by adding clear() (#5889) (#5890)
e84cbff67 Align package name to FindFlatBuffers.cmake (#5899)
f94e6c84e Small tutorial improvements - documentation only (#5894)
f12cca8bc Attempt at adding Github Actions CI
7e4124d6e Handle git program or .git folder absence (#5878)
a875d247a only add native_include_files if object based api is enabled (#5886)
6e9f5d981 Respect shared attribute in Parser (#5885)
ff1c78233 include/flatbuffers: typo fixes in comments (#5884)
2e9a19673 Updates swift docs for package management (#5883)
e3cb07d32 [Rust] idl_gen_rust.cpp: (Option/required-aware codegen for unions) (#5850)
712866d57 Propagate use_string_pooling in CopyTable (#5879)
44c919a9e Not using reexports with --gen-all (#5873)
99aa1ef21 Added INCLUDE_PREFIX option for flatbuffers_generate_headers (#5866)
40ba170c9 Fixed text in internals doc that implied structs can be root
cb4d0f72e [Swift] Object API support (#5826)
003e16405 [TS] Add Obj API (#5788)
21cf300f4 fix cpp usage markdown error (#5845)
9655e12d6 Upgraded swift implementation for grpc (#5843)
fb96fadc2 [C#] Fix nested structs and arrays in Object API (#5765)
408f11fbd [ts] Fix empty source/dest namespaces when reexporting. (#5841)
a83caf591 Improves performance for the swift library by using structs + a storage class (#5835)
925fab6b1 [Java][FlexBuffers] Optimize Map access (#5735)
d9fecc332 [CMake] : Add precompiled header support with FLATBUFFERS_ENABLE_PCH (#5827)
e9d453240 Added flatbuffers_generate_headers and flatbuffers_generate_binary_files cmake functions. (#5830)
c37c989ed Correct calculation of vector element size (#5831)
6b271b7ec Fix Clang-trunk warnings about special members deprecated in C++20. (#5829)
90f3b8e8c Fix `float_constant` definition in './doc/Grammar.md` (#5828)
3af735934 [csharp] flatc should generate a 'Create…' method for tables with struct field… (#5818)
c4231c3cb Updated doxyfile - added missing files (#5824)
9657df184 Update Grammar.md (#5820)
97ffc590e Include CPack only when explictly packaging (#5817)
8b52af65b [C++] Add max_depth and max_tables parameters to reflection::Verify (#5815)
9b034eee1 Fix interpretation of 'nan(number)' by the idl_parser (#5810)
3e9ac3cff [Scripts] Adds swift to generated code (#5806)
697147a2e updated maven build files
6df40a247 pre-tag version bump for 1.12
0dba63909 Removes the inner loop in the endtable check written tables (#5803)
0e3fdd0ee Escape characters in jsonschema descriptions (#5644)
45a2b07cb Remove `noexcept` qualifier copy-ctor of `union` type (#5800) (#5802)
d10c16314 Replace 'assert' by 'FLATBUFFERS_ASSERT' inside idl_parser.cpp (#5799)
35abb7f89 Add non-nullable modifier to return type of functions never returning null (#5797)
9954e09ab [C++] Generate code for vector force_align attribute. (#5796)
95a21327f rust: pub export the VectorIter type (#5736)
89b6183ee Fix Python min alignment
5a98d65e8 [Rust] Add gen-name-strings for Rust (#5757)
f73d205bc Removed assert that wasn't backwards compatible.
7c37abe92 [C#] add ObjectAPI Serialization Utility (#5785)
4749e77b0 Fixed docs on how to obtain parser error.
6ff189841 Added --filename-suffix and --filename-ext to flatc (#5778)
c9a30c9ca Fixed refractoring issue in reflection/generate_code.sh. Also, mv deletes the original file, so I don't need to clean it up manually in that case. (#5777)
8c02d17be Skip writing reflection_generated.h if not changed (#5776)
34305c4ce [Swift] Adds GRPC to Swift (#5758)
cd88e6b2a [Java][FlexBuffers] Abstract buffer access from ByteBuffer (#5743)
3ec7a53c6 Adds cocoapods and a readme of how to get the package (#5771)
6d44cede7 [snap] Fix versioning (#5727)
cc08c0835 [Python] Fixed potential allignment issue (#5768)
54f8b787c Fix memory leak on cpp object api (#5761)
17557f913 [Python] Fixed issue #5499 (#5764)
d54af8cd4 [C++] Use strong enum type for vectors when scoped-enums is on. (#5750)
173e10fdf [C#] support Json Serialization (#5752)
8f56990f6 FlexBuffers: C++: scalar-only typed vectors were not aligned.
6400c9b05 Bump Rust port to 0.6.1 (#5747)
7418d8587 [C#] support Object API (#5710)
c580fa284 Adds min and max, comments, and all of swift's keywords + fix docs (#5737)
f2a127230 Use VS 2017 and 2019 on CI, fix cast issue in dart_idl (#5740)
316d7c208 Creates a flatbuffers validation function + small fix (#5725)
47026ea6b Added the code to embed the binary schema to the source (--bfbs-gen-embed). (#5701)
3f677f241 [Java][FlexBuffers] Deprecate typed vector strings due to design flaw (#5722)
a593a11e5 [Go] Implements a SharedStrings function (#5733)
7cdfc8475 [Swift] Fix padding function overflow when bufSize is 0 (#5721)
bab2b0db4 Add vcpkg installation instructions (#5732)
89418eb84 [Dart] Fix deprecated field support, inf/nan (#5724)
9cadf05d8 [typescript] Size-prefixed root accessors not taking into account size prefix (#5717)
6da1cf79d [rust] Add use declarations to Rust-generated bindings for imported FB definitions (#5645)
bee1df96d [Go] Replace references to hardcoded ”Monster" etc with idiomatic go wherever possible (#5716)
01189d7ed [C++] Fix for printing of enum in case output_enum_identifiers=1. (#5706)
c4b2b0a25 [Swift] Support create long string (#5709)
a4b2884e4 Added create function for swift (#5707)
04d80f255 [Swift] Swift implementation 🎉🎉 (#5603)
55686100a Changed direct calls to strtod to use StringToNumber
718351831 Document JSON compatibility guarantees. (#5704)
d1b34f0f2 Add CMake 'generated_code' target to simplify resolution of build dependencies (#5697)
21b706196 (Optionally) add an additional suffix namespace to generated fbs files. (#5698)
35daaf83d [Java] Replace Table.UTF8_CHARSET with StandardCharsets.UTF_8 (#5696)
3b458f7a1 Rust: Temporarily disable 2 endianness unit tests (#5695)
a5d9d0f7d [C++17] Add Traits class for Tables and Factory function within it. (#5678)
3cd9b6434 Removed code_generators.cpp from library targets
355dfd48d [rust] Make enum names public (#5690)
bcd58a159 Correct inverted logic around include prefixes. (#5689)
a2c12900a Optimize Pack method using numpy (#5662)
901b89e73 [C++] Add Builder and Table typedefs (#5685)
31f879908 Minor doc updates: FlexBuffers C#, Discord, CppUsage.
8023d99e2 Upgrade rules_go (#5684)
b4154405d Fix --incompatible_load_cc_rules_from_bzl (#5683)
04c17c7a7 Add support for absl::string_view when available (#5682)
62ec7d52c [Bazel] Add support for compatible_with and restricted_to (#5681)
7de668053 CI: New Docker tests for Python with numpy (#5677)
3a70e0b30 Fixed struct initialization error on older versions of C#
9b1320135 Fixed warnings in FlexBuffers.java
5e3916050 Fixed out of date licenses on gRPC Python files.
c95755051 Removed test proto output.
44bf71988 Add flatc '--cpp_std' switch (#5656)
3e8f15df9 Fix for FlexBuffers FBT_VECTOR_STRING size bit-width.
602721a73 Added Check to VerifyAlignment (#5675)
13c05f4da Improve import handling for proto conversion (#5673)
ce3a1c43a [Dart] Fix prepare space for writeListInt64 and writeListUint64 (#5654)
aa75e5734 Make Rust constants public (#5659)
2790fee25 Add namespace qualification to union types (#5666)
eddebec1b Bugfix for Rust generation of union fields named with language keywords (#5592)
030fee36a wrap multiple statements in do {} while(!IsConstTrue(true)) (#5655)
f9724d1bd [gRPC] Uncomment MessageBuilder (#5658)
b20801ca4 Supress unsigned-integer-overflow for PaddingBytes (#5647)
a8e800bd7 Add --force-empty-vectors option (#5653)
d7530ae96 Fixed enum min/max values not properly escaped.
99d11e279 Split Bazel targets into multiple packages (#5640)
4fd8eb214 Remove a static_assert (#5643)
65f870357 Flatbuffers Python Object API (#5616)
75823cc27 [Clang 10]: definition of implicit copy constructor for 'TableKeyComparatoris deprecated #5649 (#5650)
58e279244 [docs]: add missing semicolon (#5648)
3c964e10a [GO] Fix support for enums with underscores and Unions with imported members (#5600)
c3c32ec94 Fix ambiguity of a type deduction in TEST_EQ macro if arguments have `enum class` type. (#5630)
075e8d676 Simplify declarations of x-macro FLATBUFFERS_TD (#5638)
bcf1bd5c9 read vtable size through ReadScalar() (#5636)
136d75fa6 Changed null checks in test. Removed verifier pointer usage (#5634)
091fa1fd1 Add testing of C++ with sanitizers (CI-Docker) (#5631)
ff3781dc2 add namespace prefix in FLATBUFFERS_MAX_BUFFER_SIZE (#5629)
6beb9f49c Support for python grpc - continuing the work from the pull request #4270 #4705 (#5613)
80988ea86 Removed idl_gen_general.cpp and move contents to code_generators.cpp (#5625)
0f2ff7eaa Lua cleanup (#5624)
dda095023 [C++] Adds basic schema evolution tests (#5611)
adbcbba5d [C++, C#, Java] Separated C# and Java generators into their own classes (#5618)
cbbd6aca0 add check for root_type specified for json schema generation (#5622)
405c64e07 [Rust] Bump smallvec version to 1.0 (#5621)
42c08cbca Ran src/clang-format-all.sh (#5617)
33d5dd9bd Improved pull request & clang-format instructions.
105dd528e Change monster_extra generation to use flatbuffers::unique_ptr (#5612)
f0f0efe7b [C++] Refactor to conform to Google C++ style guide (#5608)
e837d5a29 Fixed deprecated method in GRPC Java test.
9834ee978 Fixed Apache license not using canonical version.
44b2ab087 include/flatbuffers/base.h: fix no_sanitize issue with old clang (#5610)
46ae3f80a [C++, Java, C#, TypeScript, JavaScript] Skip generation of mutable union types (#5599)
7b38aa71e flatbuffers.h: fix documentation warning (#5607)
661bedd83 Add Lua FlatbufferBuilder Clean() method to enable reuseable builders (#5606)
8526e12d7 [Kotlin] Fix union vector accessor after change in Java API (#5605)
3c7b660d6 [flatc] Remove an always true condition for flexbuffers (#5604)
964365ba6 [Go] Add UnPackTo functions (#5598)
32254b7ac [Go] Object API support (#5339)
521e255ad Rust: Add idiomatic iterator for Vector type (#5579)
1b85292fd Fix typos in comments (#5590)
480815447 C++ verifier for evolved union fields should return true (#5586)
8d5e424c6 Add ByteBuffer copy for vector of bytes in Java (#5587)
b4774d235 Rust: Fix Copy and Clone impls for a few generic types (#5577)
26f238c24 Add `--clean-first` to the cmake-build command (travis) (#5574)
e93c8c46e Fix Follow implementation for bool (#5554)
e21516b9d Fix issue #5557 (#5573)
fbc11e8ae Avoid intentional unsigned integer overflow getting caught by sanitizers (#5572)
e9d29c21a Python: Add forceDefaults opt to python Builder (#5564)
8bfafc76d Java: Don't annotate vector-of-tables item getters with @nullable. (#5562)
df3e8bf4a Fixed warnings generated by recent JSON sorting feature.
5665cfe49 [Java] byte buffer factory returned buffer capcity is used instead of the requested size (#5558)
5797540ed #5544 Fix of Array of table is not sorted if Create<type>Direct() is used (#5546)
7f1af7cb0 Fix build with gcc version 7.4.0 (#5570)
32f47ad24 Fixed JSON parser not sorting vectors of tables/structs with key.
842f672ba [FlexBuffers][Java] Cache size of Sized objects in FlexBuffers (#5551)
d4cae0a62 Fix issue #5542 (#5543)
f1147f65b Fixed Android STLPort related error.
69d3fec48 Fix namespaced struct/field name collision detection (#5540) (#5545)
cfb4ecf6f [flac] Add FlexBuffers option for generating data (#5519)
a92039687 Update Rust versions under test from 1.30.1 to 1.37.0 (#5538)
625338d09 Adds XOPEN_SOURCE for PATH_MAX and POSIX 1993 for stat (#5529)
3f8ce99c5 [FlexBuffers][Java] Add override Key::toString (#5533)
0798b7b69 [FlexBuffers][Java] Fix wrong access to a string using Reference::asString(). (#5532)
cbdf82e2f Fix Mutate() methods of Array<scalar/struct> (override 5508) (#5526)
e365c502f Java: Added access object for vector of struct and vector of tables. (#5233)
97f3aa917 Fixed DetachedBuffer self move assignment (#5521)
2f5bb2eec Fix buildifier warnings found in new bazel (#5517)
917687c7a Fixed Reflection Verifier not handling vectors of unions.
f9277e691 Fixed GenerateText not handling vectors of unions.
2706381ee Add element size parameter to __vector_as_arraysegment [c#] (#5512)
b5560fcd5 [Java][FlexBuffers] Improve documentation for FlexBuffers in Java. (#5506)
782b865c5 Annotate getters with @Pure when --java-checkerframework is specified. (#5510)
3bfc86eaf [Dart]fix: segment fault with empty namespace when generating dart file (#5507)
c0282873f Rust: Fixed cargo clippy on non-generated code (#5485)
4b870aca9 [Javascript] Fix syntax error for signed enum (#5503)
d0e3870c0 [C#] Fix retrieving enumeration vectors as arrays (#5457)
fb25eb87f Doc typo fixes (#5505)
cb35d3a0e Use all of the available space in the buffer returned by ByteBufferFactory to allow the factory to keep a pool of larger than initialsize sized buffers. (#5500)
8e6cabb31 [FlexBuffers][Java] Implementation of FlexBuffers API (#5476)
bd31dd242 Clarified value reuse in FlexBuffers
65b67d213 Fixed test build invocation of arrays_test.fbs
1fbb71132 FlexBuffers: allow any values to be shared.
cd75a3658 Android: remove app_dummy() calls
ec6b0bf29 Fixed STLPort Android compile error
c11b5d744 [bugfix]flexbuffers isvector bugfix (#5488)
4525c91be Fix incorrect padding in arrays of structs (Issue #5484) (#5491)
b97b342f5 Fixed missing generated code.
c1058a903 C++ IDL generation adds superfluous semicolon in GenTablePost, causing (#5483)
303044934 [go]add Name() for ForceCodec interface (#5486)
a2485d4ec reflection: check for valid union enum value during object verification (#5475)
a20e71ac9 has_method support for primitive fields in java runtime. Changed: idl.h, FlatBufferBuilder.java , idl_gen_general.cpp, idl_parser.cpp, flatc.cpp (#5468)
Change-Id: I836f4b43e6818bb16425a87899e6234ac86242aa
git-subtree-dir: third_party/flatbuffers
git-subtree-split: d6a8dbd26ff08a8868e0d0c1b4b67d31b40e4a7f
diff --git a/src/idl_parser.cpp b/src/idl_parser.cpp
index 31b315c..a87fbce 100644
--- a/src/idl_parser.cpp
+++ b/src/idl_parser.cpp
@@ -15,12 +15,11 @@
*/
#include <algorithm>
+#include <cmath>
#include <list>
#include <string>
#include <utility>
-#include <cmath>
-
#include "flatbuffers/idl.h"
#include "flatbuffers/util.h"
@@ -38,26 +37,22 @@
const double kPi = 3.14159265358979323846;
-const char *const kTypeNames[] = {
// clang-format off
- #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
- CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
+const char *const kTypeNames[] = {
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, ...) \
IDLTYPE,
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
- // clang-format on
nullptr
};
const char kTypeSizes[] = {
-// clang-format off
- #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
- CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
- sizeof(CTYPE),
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ sizeof(CTYPE),
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
- // clang-format on
};
+// clang-format on
// The enums in the reflection schema should match the ones we use internally.
// Compare the last element to check if these go out of sync.
@@ -87,23 +82,45 @@
return true;
}
+static bool IsLowerSnakeCase(const std::string &str) {
+ for (size_t i = 0; i < str.length(); i++) {
+ char c = str[i];
+ if (!check_ascii_range(c, 'a', 'z') && !is_digit(c) && c != '_') {
+ return false;
+ }
+ }
+ return true;
+}
+
// Convert an underscore_based_indentifier in to camelCase.
// Also uppercases the first character if first is true.
std::string MakeCamel(const std::string &in, bool first) {
std::string s;
for (size_t i = 0; i < in.length(); i++) {
if (!i && first)
- s += static_cast<char>(toupper(in[0]));
+ s += CharToUpper(in[0]);
else if (in[i] == '_' && i + 1 < in.length())
- s += static_cast<char>(toupper(in[++i]));
+ s += CharToUpper(in[++i]);
else
s += in[i];
}
return s;
}
-void DeserializeDoc( std::vector<std::string> &doc,
- const Vector<Offset<String>> *documentation) {
+// Convert an underscore_based_identifier in to screaming snake case.
+std::string MakeScreamingCamel(const std::string &in) {
+ std::string s;
+ for (size_t i = 0; i < in.length(); i++) {
+ if (in[i] != '_')
+ s += CharToUpper(in[i]);
+ else
+ s += in[i];
+ }
+ return s;
+}
+
+void DeserializeDoc(std::vector<std::string> &doc,
+ const Vector<Offset<String>> *documentation) {
if (documentation == nullptr) return;
for (uoffset_t index = 0; index < documentation->size(); index++)
doc.push_back(documentation->Get(index)->str());
@@ -211,8 +228,7 @@
#define FLATBUFFERS_TOKEN(NAME, VALUE, STRING) STRING,
FLATBUFFERS_GEN_TOKENS(FLATBUFFERS_TOKEN)
#undef FLATBUFFERS_TOKEN
- #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
- CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, ...) \
IDLTYPE,
FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
@@ -387,7 +403,8 @@
"illegal Unicode sequence (unpaired high surrogate)");
}
// reset if non-printable
- attr_is_trivial_ascii_string_ &= check_ascii_range(*cursor_, ' ', '~');
+ attr_is_trivial_ascii_string_ &=
+ check_ascii_range(*cursor_, ' ', '~');
attribute_ += *cursor_++;
}
@@ -425,11 +442,11 @@
cursor_ += 2;
break;
}
- FLATBUFFERS_FALLTHROUGH(); // else fall thru
+ FLATBUFFERS_FALLTHROUGH(); // else fall thru
default:
const auto has_sign = (c == '+') || (c == '-');
// '-'/'+' and following identifier - can be a predefined constant like:
- // NAN, INF, PI, etc.
+ // NAN, INF, PI, etc or it can be a function name like cos/sin/deg.
if (IsIdentifierStart(c) || (has_sign && IsIdentifierStart(*cursor_))) {
// Collect all chars of an identifier:
const char *start = cursor_ - 1;
@@ -439,14 +456,15 @@
return NoError();
}
- auto dot_lvl = (c == '.') ? 0 : 1; // dot_lvl==0 <=> exactly one '.' seen
- if (!dot_lvl && !is_digit(*cursor_)) return NoError(); // enum?
+ auto dot_lvl =
+ (c == '.') ? 0 : 1; // dot_lvl==0 <=> exactly one '.' seen
+ if (!dot_lvl && !is_digit(*cursor_)) return NoError(); // enum?
// Parser accepts hexadecimal-floating-literal (see C++ 5.13.4).
if (is_digit(c) || has_sign || !dot_lvl) {
const auto start = cursor_ - 1;
auto start_digits = !is_digit(c) ? cursor_ : cursor_ - 1;
- if (!is_digit(c) && is_digit(*cursor_)){
- start_digits = cursor_; // see digit in cursor_ position
+ if (!is_digit(c) && is_digit(*cursor_)) {
+ start_digits = cursor_; // see digit in cursor_ position
c = *cursor_++;
}
// hex-float can't begind with '.'
@@ -489,7 +507,8 @@
}
std::string ch;
ch = c;
- if (false == check_ascii_range(c, ' ', '~')) ch = "code: " + NumToString(c);
+ if (false == check_ascii_range(c, ' ', '~'))
+ ch = "code: " + NumToString(c);
return Error("illegal character: " + ch);
}
}
@@ -618,12 +637,6 @@
"length of fixed-length array must be positive and fit to "
"uint16_t type");
}
- // Check if enum arrays are used in C++ without specifying --scoped-enums
- if ((opts.lang_to_generate & IDLOptions::kCpp) && !opts.scoped_enums &&
- IsEnum(subtype)) {
- return Error(
- "--scoped-enums must be enabled to use enum arrays in C++\n");
- }
type = Type(BASE_TYPE_ARRAY, subtype.struct_def, subtype.enum_def,
fixed_length);
NEXT();
@@ -665,18 +678,28 @@
CheckedError Parser::ParseField(StructDef &struct_def) {
std::string name = attribute_;
- if (LookupStruct(name))
+ if (LookupCreateStruct(name, false, false))
return Error("field name can not be the same as table/struct name");
+ if (!IsLowerSnakeCase(name)) {
+ Warning("field names should be lowercase snake_case, got: " + name);
+ }
+
std::vector<std::string> dc = doc_comment_;
EXPECT(kTokenIdentifier);
EXPECT(':');
Type type;
ECHECK(ParseType(type));
- if (struct_def.fixed && !IsScalar(type.base_type) && !IsStruct(type) &&
- !IsArray(type))
- return Error("structs_ may contain only scalar or struct fields");
+ if (struct_def.fixed) {
+ auto valid = IsScalar(type.base_type) || IsStruct(type);
+ if (!valid && IsArray(type)) {
+ const auto &elem_type = type.VectorType();
+ valid |= IsScalar(elem_type.base_type) || IsStruct(elem_type);
+ }
+ if (!valid)
+ return Error("structs may contain only scalar or struct fields");
+ }
if (!struct_def.fixed && IsArray(type))
return Error("fixed-length array in table must be wrapped in struct");
@@ -693,12 +716,11 @@
// 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) {
+ } else if (IsVector(type) && type.element == BASE_TYPE_UNION) {
// Only cpp, js and ts supports the union vector feature so far.
if (!SupportsAdvancedUnionFeatures()) {
return Error(
- "Vectors of unions are not yet supported in all "
+ "Vectors of unions are not yet supported in at least one of "
"the specified programming languages.");
}
// For vector of union fields, add a second auto-generated vector field to
@@ -718,15 +740,44 @@
if (!IsScalar(type.base_type) ||
(struct_def.fixed && field->value.constant != "0"))
return Error(
- "default values currently only supported for scalars in tables");
+ "default values currently only supported for scalars in tables");
}
+
+ // Mark the optional scalars. Note that a side effect of ParseSingleValue is
+ // fixing field->value.constant to null.
+ if (IsScalar(type.base_type)) {
+ field->optional = (field->value.constant == "null");
+ if (field->optional) {
+ if (type.enum_def && type.enum_def->Lookup("null")) {
+ FLATBUFFERS_ASSERT(IsInteger(type.base_type));
+ return Error(
+ "the default 'null' is reserved for declaring optional scalar "
+ "fields, it conflicts with declaration of enum '" +
+ type.enum_def->name + "'.");
+ }
+ if (field->attributes.Lookup("key")) {
+ return Error(
+ "only a non-optional scalar field can be used as a 'key' field");
+ }
+ if (!SupportsOptionalScalars()) {
+ return Error(
+ "Optional scalars are not yet supported in at least one the of "
+ "the specified programming languages.");
+ }
+ }
+ } else {
+ // For nonscalars, only required fields are non-optional.
+ // At least until https://github.com/google/flatbuffers/issues/6053
+ field->optional = !field->required;
+ }
+
// Append .0 if the value has not it (skip hex and scientific floats).
// This suffix needed for generated C++ code.
if (IsFloat(type.base_type)) {
auto &text = field->value.constant;
FLATBUFFERS_ASSERT(false == text.empty());
auto s = text.c_str();
- while(*s == ' ') s++;
+ while (*s == ' ') s++;
if (*s == '-' || *s == '+') s++;
// 1) A float constants (nan, inf, pi, etc) is a kind of identifier.
// 2) A float number needn't ".0" at the end if it has exponent.
@@ -740,15 +791,15 @@
// Table, struct or string can't have enum_def.
// Default value of union and vector in NONE, NULL translated to "0".
FLATBUFFERS_ASSERT(IsInteger(type.base_type) ||
- (type.base_type == BASE_TYPE_UNION) ||
- (type.base_type == BASE_TYPE_VECTOR) ||
- (type.base_type == BASE_TYPE_ARRAY));
- if (type.base_type == BASE_TYPE_VECTOR) {
+ (type.base_type == BASE_TYPE_UNION) || IsVector(type) ||
+ IsArray(type));
+ if (IsVector(type)) {
// Vector can't use initialization list.
FLATBUFFERS_ASSERT(field->value.constant == "0");
} else {
// All unions should have the NONE ("0") enum value.
auto in_enum = type.enum_def->attributes.Lookup("bit_flags") ||
+ field->IsScalarOptional() ||
type.enum_def->FindByValue(field->value.constant);
if (false == in_enum)
return Error("default value of " + field->value.constant +
@@ -762,7 +813,7 @@
field->deprecated = field->attributes.Lookup("deprecated") != nullptr;
auto hash_name = field->attributes.Lookup("hash");
if (hash_name) {
- switch ((type.base_type == BASE_TYPE_VECTOR) ? type.element : type.base_type) {
+ switch ((IsVector(type)) ? type.element : type.base_type) {
case BASE_TYPE_SHORT:
case BASE_TYPE_USHORT: {
if (FindHashFunction16(hash_name->constant.c_str()) == nullptr)
@@ -786,7 +837,8 @@
}
default:
return Error(
- "only short, ushort, int, uint, long and ulong data types support hashing.");
+ "only short, ushort, int, uint, long and ulong data types support "
+ "hashing.");
}
}
auto cpp_type = field->attributes.Lookup("cpp_type");
@@ -805,9 +857,15 @@
if (field->deprecated && struct_def.fixed)
return Error("can't deprecate fields in a struct");
field->required = field->attributes.Lookup("required") != nullptr;
- if (field->required &&
- (struct_def.fixed || IsScalar(type.base_type)))
+ if (field->required && (struct_def.fixed || IsScalar(type.base_type)))
return Error("only non-scalar fields in tables may be 'required'");
+
+ if (!IsScalar(type.base_type)) {
+ // For nonscalars, only required fields are non-optional.
+ // At least until https://github.com/google/flatbuffers/issues/6053
+ field->optional = !field->required;
+ }
+
field->key = field->attributes.Lookup("key") != nullptr;
if (field->key) {
if (struct_def.has_key) return Error("only one field may be set as 'key'");
@@ -849,8 +907,7 @@
if (field->attributes.Lookup("flexbuffer")) {
field->flexbuffer = true;
uses_flexbuffers_ = true;
- if (type.base_type != BASE_TYPE_VECTOR ||
- type.element != BASE_TYPE_UCHAR)
+ if (type.base_type != BASE_TYPE_VECTOR || type.element != BASE_TYPE_UCHAR)
return Error("flexbuffer attribute may only apply to a vector of ubyte");
}
@@ -869,16 +926,23 @@
val->constant = NumToString(id - 1);
typefield->attributes.Add("id", val);
}
+ // if this field is a union that is deprecated,
+ // the automatically added type field should be deprecated as well
+ if (field->deprecated) { typefield->deprecated = true; }
}
EXPECT(';');
return NoError();
}
-CheckedError Parser::ParseString(Value &val) {
+CheckedError Parser::ParseString(Value &val, bool use_string_pooling) {
auto s = attribute_;
EXPECT(kTokenStringConstant);
- val.constant = NumToString(builder_.CreateString(s).o);
+ if (use_string_pooling) {
+ val.constant = NumToString(builder_.CreateSharedString(s).o);
+ } else {
+ val.constant = NumToString(builder_.CreateString(s).o);
+ }
return NoError();
}
@@ -890,8 +954,7 @@
CheckedError Parser::ParseAnyValue(Value &val, FieldDef *field,
size_t parent_fieldn,
const StructDef *parent_struct_def,
- uoffset_t count,
- bool inside_vector) {
+ uoffset_t count, bool inside_vector) {
switch (val.type.base_type) {
case BASE_TYPE_UNION: {
FLATBUFFERS_ASSERT(field);
@@ -903,14 +966,13 @@
auto &type = elem->second->value.type;
if (type.enum_def == val.type.enum_def) {
if (inside_vector) {
- if (type.base_type == BASE_TYPE_VECTOR &&
- type.element == BASE_TYPE_UTYPE) {
+ if (IsVector(type) && type.element == BASE_TYPE_UTYPE) {
// Vector of union type field.
uoffset_t offset;
ECHECK(atot(elem->first.constant.c_str(), *this, &offset));
vector_of_union_types = reinterpret_cast<Vector<uint8_t> *>(
- builder_.GetCurrentBufferPointer() +
- builder_.GetSize() - offset);
+ builder_.GetCurrentBufferPointer() + builder_.GetSize() -
+ offset);
break;
}
} else {
@@ -952,8 +1014,7 @@
}
}
if (constant.empty() && !vector_of_union_types) {
- return Error("missing type field for this union value: " +
- field->name);
+ return Error("missing type field for this union value: " + field->name);
}
uint8_t enum_idx;
if (vector_of_union_types) {
@@ -972,8 +1033,8 @@
builder_.ClearOffsets();
val.constant = NumToString(builder_.GetSize());
}
- } else if (enum_val->union_type.base_type == BASE_TYPE_STRING) {
- ECHECK(ParseString(val));
+ } else if (IsString(enum_val->union_type)) {
+ ECHECK(ParseString(val, field->shared));
} else {
FLATBUFFERS_ASSERT(false);
}
@@ -983,7 +1044,7 @@
ECHECK(ParseTable(*val.type.struct_def, &val.constant, nullptr));
break;
case BASE_TYPE_STRING: {
- ECHECK(ParseString(val));
+ ECHECK(ParseString(val, field->shared));
break;
}
case BASE_TYPE_VECTOR: {
@@ -1028,10 +1089,9 @@
builder.AddStructOffset(val.offset, builder.GetSize());
}
-template <typename F>
+template<typename F>
CheckedError Parser::ParseTableDelimiters(size_t &fieldn,
- const StructDef *struct_def,
- F body) {
+ const StructDef *struct_def, F body) {
// We allow tables both as JSON object{ .. } with field names
// or vector[..] with all fields in order
char terminator = '}';
@@ -1167,9 +1227,8 @@
if (!struct_def.sortbysize ||
size == SizeOf(field_value.type.base_type)) {
switch (field_value.type.base_type) {
- // clang-format off
- #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
- CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
+// clang-format off
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
case BASE_TYPE_ ## ENUM: \
builder_.Pad(field->padding); \
if (struct_def.fixed) { \
@@ -1183,10 +1242,9 @@
builder_.AddElement(field_value.offset, val, valdef); \
} \
break;
- FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD);
+ FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
- #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
- CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
case BASE_TYPE_ ## ENUM: \
builder_.Pad(field->padding); \
if (IsStruct(field->value.type)) { \
@@ -1197,7 +1255,7 @@
builder_.AddOffset(field_value.offset, val); \
} \
break;
- FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD);
+ FLATBUFFERS_GEN_TYPES_POINTER(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
case BASE_TYPE_ARRAY:
builder_.Pad(field->padding);
@@ -1205,7 +1263,7 @@
reinterpret_cast<const uint8_t*>(field_value.constant.c_str()),
InlineSize(field_value.type));
break;
- // clang-format on
+ // clang-format on
}
}
}
@@ -1231,7 +1289,7 @@
return NoError();
}
-template <typename F>
+template<typename F>
CheckedError Parser::ParseVectorDelimiters(uoffset_t &count, F body) {
EXPECT('[');
for (;;) {
@@ -1245,6 +1303,42 @@
return NoError();
}
+static bool CompareType(const uint8_t *a, const uint8_t *b, BaseType ftype) {
+ switch (ftype) {
+#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ case BASE_TYPE_##ENUM: return ReadScalar<CTYPE>(a) < ReadScalar<CTYPE>(b);
+ FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
+#undef FLATBUFFERS_TD
+ case BASE_TYPE_STRING:
+ // Indirect offset pointer to string pointer.
+ a += ReadScalar<uoffset_t>(a);
+ b += ReadScalar<uoffset_t>(b);
+ return *reinterpret_cast<const String *>(a) <
+ *reinterpret_cast<const String *>(b);
+ default: return false;
+ }
+}
+
+// See below for why we need our own sort :(
+template<typename T, typename F, typename S>
+void SimpleQsort(T *begin, T *end, size_t width, F comparator, S swapper) {
+ if (end - begin <= static_cast<ptrdiff_t>(width)) return;
+ auto l = begin + width;
+ auto r = end;
+ while (l < r) {
+ if (comparator(begin, l)) {
+ r -= width;
+ swapper(l, r);
+ } else {
+ l += width;
+ }
+ }
+ l -= width;
+ swapper(begin, l);
+ SimpleQsort(begin, l, width, comparator, swapper);
+ SimpleQsort(r, end, width, comparator, swapper);
+}
+
CheckedError Parser::ParseVector(const Type &type, uoffset_t *ovalue,
FieldDef *field, size_t fieldn) {
uoffset_t count = 0;
@@ -1259,15 +1353,21 @@
});
ECHECK(err);
- builder_.StartVector(count * InlineSize(type) / InlineAlignment(type),
- InlineAlignment(type));
+ const auto *force_align = field->attributes.Lookup("force_align");
+ const size_t align =
+ force_align ? static_cast<size_t>(atoi(force_align->constant.c_str()))
+ : 1;
+ const size_t len = count * InlineSize(type) / InlineAlignment(type);
+ const size_t elemsize = InlineAlignment(type);
+ if (align > 1) { builder_.ForceVectorAlignment(len, elemsize, align); }
+
+ builder_.StartVector(len, elemsize);
for (uoffset_t i = 0; i < count; i++) {
// start at the back, since we're building the data backwards.
auto &val = field_stack_.back().first;
switch (val.type.base_type) {
- // clang-format off
- #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
- CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
+// clang-format off
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE,...) \
case BASE_TYPE_ ## ENUM: \
if (IsStruct(val.type)) SerializeStruct(*val.type.struct_def, val); \
else { \
@@ -1285,6 +1385,75 @@
builder_.ClearOffsets();
*ovalue = builder_.EndVector(count);
+
+ if (type.base_type == BASE_TYPE_STRUCT && type.struct_def->has_key) {
+ // We should sort this vector. Find the key first.
+ const FieldDef *key = nullptr;
+ for (auto it = type.struct_def->fields.vec.begin();
+ it != type.struct_def->fields.vec.end(); ++it) {
+ if ((*it)->key) {
+ key = (*it);
+ break;
+ }
+ }
+ FLATBUFFERS_ASSERT(key);
+ // Now sort it.
+ // We can't use std::sort because for structs the size is not known at
+ // compile time, and for tables our iterators dereference offsets, so can't
+ // be used to swap elements.
+ // And we can't use C qsort either, since that would force use to use
+ // globals, making parsing thread-unsafe.
+ // So for now, we use SimpleQsort above.
+ // TODO: replace with something better, preferably not recursive.
+ voffset_t offset = key->value.offset;
+ BaseType ftype = key->value.type.base_type;
+
+ if (type.struct_def->fixed) {
+ auto v =
+ reinterpret_cast<VectorOfAny *>(builder_.GetCurrentBufferPointer());
+ SimpleQsort<uint8_t>(
+ v->Data(), v->Data() + v->size() * type.struct_def->bytesize,
+ type.struct_def->bytesize,
+ [&](const uint8_t *a, const uint8_t *b) -> bool {
+ return CompareType(a + offset, b + offset, ftype);
+ },
+ [&](uint8_t *a, uint8_t *b) {
+ // FIXME: faster?
+ for (size_t i = 0; i < type.struct_def->bytesize; i++) {
+ std::swap(a[i], b[i]);
+ }
+ });
+ } else {
+ auto v = reinterpret_cast<Vector<Offset<Table>> *>(
+ builder_.GetCurrentBufferPointer());
+ // Here also can't use std::sort. We do have an iterator type for it,
+ // but it is non-standard as it will dereference the offsets, and thus
+ // can't be used to swap elements.
+ SimpleQsort<Offset<Table>>(
+ v->data(), v->data() + v->size(), 1,
+ [&](const Offset<Table> *_a, const Offset<Table> *_b) -> bool {
+ // Indirect offset pointer to table pointer.
+ auto a = reinterpret_cast<const uint8_t *>(_a) +
+ ReadScalar<uoffset_t>(_a);
+ auto b = reinterpret_cast<const uint8_t *>(_b) +
+ ReadScalar<uoffset_t>(_b);
+ // Fetch field address from table.
+ a = reinterpret_cast<const Table *>(a)->GetAddressOf(offset);
+ b = reinterpret_cast<const Table *>(b)->GetAddressOf(offset);
+ return CompareType(a, b, ftype);
+ },
+ [&](Offset<Table> *a, Offset<Table> *b) {
+ // These are serialized offsets, so are relative where they are
+ // stored in memory, so compute the distance between these pointers:
+ ptrdiff_t diff = (b - a) * sizeof(Offset<Table>);
+ FLATBUFFERS_ASSERT(diff >= 0); // Guaranteed by SimpleQsort.
+ auto udiff = static_cast<uoffset_t>(diff);
+ a->o = EndianScalar(ReadScalar<uoffset_t>(a) - udiff);
+ b->o = EndianScalar(ReadScalar<uoffset_t>(b) + udiff);
+ std::swap(*a, *b);
+ });
+ }
+ }
return NoError();
}
@@ -1312,8 +1481,7 @@
auto &val = *it;
// clang-format off
switch (val.type.base_type) {
- #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
- CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
case BASE_TYPE_ ## ENUM: \
if (IsStruct(val.type)) { \
SerializeStruct(builder, *val.type.struct_def, val); \
@@ -1362,12 +1530,11 @@
nested_parser.enums_.dict.clear();
nested_parser.enums_.vec.clear();
- if (!ok) {
- ECHECK(Error(nested_parser.error_));
- }
+ if (!ok) { ECHECK(Error(nested_parser.error_)); }
// Force alignment for nested flatbuffer
- builder_.ForceVectorAlignment(nested_parser.builder_.GetSize(), sizeof(uint8_t),
- nested_parser.builder_.GetBufferMinAlignment());
+ builder_.ForceVectorAlignment(
+ nested_parser.builder_.GetSize(), sizeof(uint8_t),
+ nested_parser.builder_.GetBufferMinAlignment());
auto off = builder_.CreateVector(nested_parser.builder_.GetBufferPointer(),
nested_parser.builder_.GetSize());
@@ -1383,13 +1550,13 @@
auto name = attribute_;
if (false == (Is(kTokenIdentifier) || Is(kTokenStringConstant)))
return Error("attribute name must be either identifier or string: " +
- name);
+ name);
if (known_attributes_.find(name) == known_attributes_.end())
return Error("user define attributes must be declared before use: " +
name);
NEXT();
auto e = new Value();
- attributes->Add(name, e);
+ if (attributes->Add(name, e)) Warning("attribute already found: " + name);
if (Is(':')) {
NEXT();
ECHECK(ParseSingleValue(&name, *e, true));
@@ -1404,45 +1571,6 @@
return NoError();
}
-CheckedError Parser::TryTypedValue(const std::string *name, int dtoken,
- bool check, Value &e, BaseType req,
- bool *destmatch) {
- bool match = dtoken == token_;
- if (match) {
- FLATBUFFERS_ASSERT(*destmatch == false);
- *destmatch = true;
- e.constant = attribute_;
- // Check token match
- if (!check) {
- if (e.type.base_type == BASE_TYPE_NONE) {
- e.type.base_type = req;
- } else {
- return Error(
- std::string("type mismatch: expecting: ") +
- kTypeNames[e.type.base_type] + ", found: " + kTypeNames[req] +
- ", name: " + (name ? *name : "") + ", value: " + e.constant);
- }
- }
- // The exponent suffix of hexadecimal float-point number is mandatory.
- // A hex-integer constant is forbidden as an initializer of float number.
- if ((kTokenFloatConstant != dtoken) && IsFloat(e.type.base_type)) {
- const auto &s = e.constant;
- const auto k = s.find_first_of("0123456789.");
- if ((std::string::npos != k) && (s.length() > (k + 1)) &&
- (s[k] == '0' && is_alpha_char(s[k + 1], 'X')) &&
- (std::string::npos == s.find_first_of("pP", k + 2))) {
- return Error(
- "invalid number, the exponent suffix of hexadecimal "
- "floating-point literals is mandatory: \"" +
- s + "\"");
- }
- }
-
- NEXT();
- }
- return NoError();
-}
-
CheckedError Parser::ParseEnumFromString(const Type &type,
std::string *result) {
const auto base_type =
@@ -1531,61 +1659,106 @@
if (IsInteger(e.type.base_type)) { e.constant = NumToString(val); }
}
#if defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
-// Normilaze defaults NaN to unsigned quiet-NaN(0).
-static inline void SingleValueRepack(Value& e, float val) {
+// Normalize defaults NaN to unsigned quiet-NaN(0) if value was parsed from
+// hex-float literal.
+static inline void SingleValueRepack(Value &e, float val) {
if (val != val) e.constant = "nan";
}
-static inline void SingleValueRepack(Value& e, double val) {
+static inline void SingleValueRepack(Value &e, double val) {
if (val != val) e.constant = "nan";
}
#endif
-CheckedError Parser::ParseSingleValue(const std::string *name, Value &e,
- bool check_now) {
- // First see if this could be a conversion function:
- if (token_ == kTokenIdentifier && *cursor_ == '(') {
- // todo: Extract processing of conversion functions to ParseFunction.
- const auto functionname = attribute_;
- if (!IsFloat(e.type.base_type)) {
- return Error(functionname + ": type of argument mismatch, expecting: " +
- kTypeNames[BASE_TYPE_DOUBLE] +
- ", found: " + kTypeNames[e.type.base_type] +
- ", name: " + (name ? *name : "") + ", value: " + e.constant);
+CheckedError Parser::ParseFunction(const std::string *name, Value &e) {
+ // Copy name, attribute will be changed on NEXT().
+ const auto functionname = attribute_;
+ if (!IsFloat(e.type.base_type)) {
+ return Error(functionname + ": type of argument mismatch, expecting: " +
+ kTypeNames[BASE_TYPE_DOUBLE] +
+ ", found: " + kTypeNames[e.type.base_type] +
+ ", name: " + (name ? *name : "") + ", value: " + e.constant);
+ }
+ NEXT();
+ EXPECT('(');
+ ECHECK(Recurse([&]() { return ParseSingleValue(name, e, false); }));
+ EXPECT(')');
+ // calculate with double precision
+ double x, y = 0.0;
+ ECHECK(atot(e.constant.c_str(), *this, &x));
+ // clang-format off
+ auto func_match = false;
+ #define FLATBUFFERS_FN_DOUBLE(name, op) \
+ if (!func_match && functionname == name) { y = op; func_match = true; }
+ FLATBUFFERS_FN_DOUBLE("deg", x / kPi * 180);
+ FLATBUFFERS_FN_DOUBLE("rad", x * kPi / 180);
+ FLATBUFFERS_FN_DOUBLE("sin", sin(x));
+ FLATBUFFERS_FN_DOUBLE("cos", cos(x));
+ FLATBUFFERS_FN_DOUBLE("tan", tan(x));
+ FLATBUFFERS_FN_DOUBLE("asin", asin(x));
+ FLATBUFFERS_FN_DOUBLE("acos", acos(x));
+ FLATBUFFERS_FN_DOUBLE("atan", atan(x));
+ // TODO(wvo): add more useful conversion functions here.
+ #undef FLATBUFFERS_FN_DOUBLE
+ // clang-format on
+ if (true != func_match) {
+ return Error(std::string("Unknown conversion function: ") + functionname +
+ ", field name: " + (name ? *name : "") +
+ ", value: " + e.constant);
+ }
+ e.constant = NumToString(y);
+ return NoError();
+}
+
+CheckedError Parser::TryTypedValue(const std::string *name, int dtoken,
+ bool check, Value &e, BaseType req,
+ bool *destmatch) {
+ bool match = dtoken == token_;
+ if (match) {
+ FLATBUFFERS_ASSERT(*destmatch == false);
+ *destmatch = true;
+ e.constant = attribute_;
+ // Check token match
+ if (!check) {
+ if (e.type.base_type == BASE_TYPE_NONE) {
+ e.type.base_type = req;
+ } else {
+ return Error(
+ std::string("type mismatch: expecting: ") +
+ kTypeNames[e.type.base_type] + ", found: " + kTypeNames[req] +
+ ", name: " + (name ? *name : "") + ", value: " + e.constant);
+ }
+ }
+ // The exponent suffix of hexadecimal float-point number is mandatory.
+ // A hex-integer constant is forbidden as an initializer of float number.
+ if ((kTokenFloatConstant != dtoken) && IsFloat(e.type.base_type)) {
+ const auto &s = e.constant;
+ const auto k = s.find_first_of("0123456789.");
+ if ((std::string::npos != k) && (s.length() > (k + 1)) &&
+ (s[k] == '0' && is_alpha_char(s[k + 1], 'X')) &&
+ (std::string::npos == s.find_first_of("pP", k + 2))) {
+ return Error(
+ "invalid number, the exponent suffix of hexadecimal "
+ "floating-point literals is mandatory: \"" +
+ s + "\"");
+ }
}
NEXT();
- EXPECT('(');
- ECHECK(Recurse([&]() { return ParseSingleValue(name, e, false); }));
- EXPECT(')');
- // calculate with double precision
- double x, y = 0.0;
- ECHECK(atot(e.constant.c_str(), *this, &x));
- auto func_match = false;
- // clang-format off
- #define FLATBUFFERS_FN_DOUBLE(name, op) \
- if (!func_match && functionname == name) { y = op; func_match = true; }
- FLATBUFFERS_FN_DOUBLE("deg", x / kPi * 180);
- FLATBUFFERS_FN_DOUBLE("rad", x * kPi / 180);
- FLATBUFFERS_FN_DOUBLE("sin", sin(x));
- FLATBUFFERS_FN_DOUBLE("cos", cos(x));
- FLATBUFFERS_FN_DOUBLE("tan", tan(x));
- FLATBUFFERS_FN_DOUBLE("asin", asin(x));
- FLATBUFFERS_FN_DOUBLE("acos", acos(x));
- FLATBUFFERS_FN_DOUBLE("atan", atan(x));
- // TODO(wvo): add more useful conversion functions here.
- #undef FLATBUFFERS_FN_DOUBLE
- // clang-format on
- if (true != func_match) {
- return Error(std::string("Unknown conversion function: ") + functionname +
- ", field name: " + (name ? *name : "") +
- ", value: " + e.constant);
- }
- e.constant = NumToString(y);
- return NoError();
}
+ return NoError();
+}
- auto match = false;
+CheckedError Parser::ParseSingleValue(const std::string *name, Value &e,
+ bool check_now) {
const auto in_type = e.type.base_type;
+ const auto is_tok_ident = (token_ == kTokenIdentifier);
+ const auto is_tok_string = (token_ == kTokenStringConstant);
+
+ // First see if this could be a conversion function:
+ if (is_tok_ident && *cursor_ == '(') { return ParseFunction(name, e); }
+
// clang-format off
+ auto match = false;
+
#define IF_ECHECK_(force, dtoken, check, req) \
if (!match && ((check) || IsConstTrue(force))) \
ECHECK(TryTypedValue(name, dtoken, check, e, req, &match))
@@ -1593,14 +1766,14 @@
#define FORCE_ECHECK(dtoken, check, req) IF_ECHECK_(true, dtoken, check, req)
// clang-format on
- if (token_ == kTokenStringConstant || token_ == kTokenIdentifier) {
+ if (is_tok_ident || is_tok_string) {
const auto kTokenStringOrIdent = token_;
// The string type is a most probable type, check it first.
TRY_ECHECK(kTokenStringConstant, in_type == BASE_TYPE_STRING,
BASE_TYPE_STRING);
// avoid escaped and non-ascii in the string
- if (!match && (token_ == kTokenStringConstant) && IsScalar(in_type) &&
+ if (!match && is_tok_string && IsScalar(in_type) &&
!attr_is_trivial_ascii_string_) {
return Error(
std::string("type mismatch or invalid value, an initializer of "
@@ -1618,6 +1791,12 @@
TRY_ECHECK(kTokenStringOrIdent, IsBool(in_type), BASE_TYPE_BOOL);
}
}
+ // Check for optional scalars.
+ if (!match && IsScalar(in_type) && attribute_ == "null") {
+ e.constant = "null";
+ NEXT();
+ match = true;
+ }
// Check if this could be a string/identifier enum value.
// Enum can have only true integer base type.
if (!match && IsInteger(in_type) && !IsBool(in_type) &&
@@ -1628,11 +1807,19 @@
}
// Parse a float/integer number from the string.
if (!match) check_now = true; // Re-pack if parsed from string literal.
- if (!match && (token_ == kTokenStringConstant) && IsScalar(in_type)) {
- // remove trailing whitespaces from attribute_
- auto last = attribute_.find_last_not_of(' ');
- if (std::string::npos != last) // has non-whitespace
- attribute_.resize(last + 1);
+ // A "scalar-in-string" value needs extra checks.
+ if (!match && is_tok_string && IsScalar(in_type)) {
+ // Strip trailing whitespaces from attribute_.
+ auto last_non_ws = attribute_.find_last_not_of(' ');
+ if (std::string::npos != last_non_ws) attribute_.resize(last_non_ws + 1);
+ if (IsFloat(e.type.base_type)) {
+ // The functions strtod() and strtof() accept both 'nan' and
+ // 'nan(number)' literals. While 'nan(number)' is rejected by the parser
+ // as an unsupported function if is_tok_ident is true.
+ if (attribute_.find_last_of(')') != std::string::npos) {
+ return Error("invalid number: " + attribute_);
+ }
+ }
}
// Float numbers or nan, inf, pi, etc.
TRY_ECHECK(kTokenStringOrIdent, IsFloat(in_type), BASE_TYPE_FLOAT);
@@ -1658,22 +1845,22 @@
"' to value of <" + std::string(kTypeNames[in_type]) + "> type.";
return Error(msg);
}
- const auto match_type = e.type.base_type; // may differ from in_type
+ const auto match_type = e.type.base_type; // may differ from in_type
// The check_now flag must be true when parse a fbs-schema.
// This flag forces to check default scalar values or metadata of field.
// For JSON parser the flag should be false.
// If it is set for JSON each value will be checked twice (see ParseTable).
- if (check_now && IsScalar(match_type)) {
+ // Special case 'null' since atot can't handle that.
+ if (check_now && IsScalar(match_type) && e.constant != "null") {
// clang-format off
switch (match_type) {
- #define FLATBUFFERS_TD(ENUM, IDLTYPE, \
- CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, RTYPE, KTYPE) \
- case BASE_TYPE_ ## ENUM: {\
- CTYPE val; \
- ECHECK(atot(e.constant.c_str(), *this, &val)); \
- SingleValueRepack(e, val); \
- break; }
- FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD);
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
+ case BASE_TYPE_ ## ENUM: {\
+ CTYPE val; \
+ ECHECK(atot(e.constant.c_str(), *this, &val)); \
+ SingleValueRepack(e, val); \
+ break; }
+ FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
default: break;
}
@@ -1865,21 +2052,16 @@
FLATBUFFERS_CHECKED_ERROR AssignEnumeratorValue(const std::string &value) {
user_value = true;
auto fit = false;
- auto ascending = false;
if (enum_def.IsUInt64()) {
uint64_t u64;
fit = StringToNumber(value.c_str(), &u64);
- ascending = u64 > temp->GetAsUInt64();
temp->value = static_cast<int64_t>(u64); // well-defined since C++20.
} else {
int64_t i64;
fit = StringToNumber(value.c_str(), &i64);
- ascending = i64 > temp->GetAsInt64();
temp->value = i64;
}
if (!fit) return parser.Error("enum value does not fit, \"" + value + "\"");
- if (!ascending && strict_ascending && !enum_def.vals.vec.empty())
- return parser.Error("enum values must be specified in ascending order");
return NoError();
}
@@ -1902,13 +2084,12 @@
FLATBUFFERS_CHECKED_ERROR ValidateValue(int64_t *ev, bool next) {
// clang-format off
switch (enum_def.underlying_type.base_type) {
- #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, \
- PTYPE, RTYPE, KTYPE) \
+ #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, ...) \
case BASE_TYPE_##ENUM: { \
if (!IsInteger(BASE_TYPE_##ENUM)) break; \
return ValidateImpl<BASE_TYPE_##ENUM, CTYPE>(ev, next ? 1 : 0); \
}
- FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD);
+ FLATBUFFERS_GEN_TYPES_SCALAR(FLATBUFFERS_TD)
#undef FLATBUFFERS_TD
default: break;
}
@@ -1916,11 +2097,10 @@
return parser.Error("fatal: invalid enum underlying type");
}
- EnumValBuilder(Parser &_parser, EnumDef &_enum_def, bool strict_order = true)
+ EnumValBuilder(Parser &_parser, EnumDef &_enum_def)
: parser(_parser),
enum_def(_enum_def),
temp(nullptr),
- strict_ascending(strict_order),
user_value(false) {}
~EnumValBuilder() { delete temp; }
@@ -1928,7 +2108,6 @@
Parser &parser;
EnumDef &enum_def;
EnumVal *temp;
- const bool strict_ascending;
bool user_value;
};
@@ -1965,9 +2144,7 @@
// todo: Convert to the Error in the future?
Warning("underlying type of bit_flags enum must be unsigned");
}
- // Protobuf allows them to be specified in any order, so sort afterwards.
- const auto strict_ascending = (false == opts.proto_mode);
- EnumValBuilder evb(*this, *enum_def, strict_ascending);
+ EnumValBuilder evb(*this, *enum_def);
EXPECT('{');
// A lot of code generatos expect that an enum is not-empty.
if ((is_union || Is('}')) && !opts.proto_mode) {
@@ -2011,9 +2188,6 @@
NEXT();
ECHECK(evb.AssignEnumeratorValue(attribute_));
EXPECT(kTokenIntegerConstant);
- } else if (false == strict_ascending) {
- // The opts.proto_mode flag is active.
- return Error("Protobuf mode doesn't allow implicit enum values.");
}
ECHECK(evb.AcceptEnumerator());
@@ -2049,8 +2223,18 @@
}
}
- if (false == strict_ascending)
- enum_def->SortByValue(); // Must be sorted to use MinValue/MaxValue.
+ enum_def->SortByValue(); // Must be sorted to use MinValue/MaxValue.
+
+ // Ensure enum value uniqueness.
+ auto prev_it = enum_def->Vals().begin();
+ for (auto it = prev_it + 1; it != enum_def->Vals().end(); ++it) {
+ auto prev_ev = *prev_it;
+ auto ev = *it;
+ if (prev_ev->GetAsUInt64() == ev->GetAsUInt64())
+ return Error("all enum values must be unique: " + prev_ev->name +
+ " and " + ev->name + " are both " +
+ NumToString(ev->GetAsInt64()));
+ }
if (dest) *dest = enum_def;
types_.Add(current_namespace_->GetFullyQualifiedName(enum_def->name),
@@ -2092,13 +2276,28 @@
return NoError();
}
+bool Parser::SupportsOptionalScalars(const flatbuffers::IDLOptions &opts) {
+ static FLATBUFFERS_CONSTEXPR unsigned long supported_langs =
+ IDLOptions::kRust | IDLOptions::kSwift | IDLOptions::kLobster |
+ IDLOptions::kKotlin | IDLOptions::kCpp | IDLOptions::kJava |
+ IDLOptions::kCSharp | IDLOptions::kTs | IDLOptions::kJs |
+ IDLOptions::kBinary;
+ unsigned long langs = opts.lang_to_generate;
+ return (langs > 0 && langs < IDLOptions::kMAX) && !(langs & ~supported_langs);
+}
+
+bool Parser::SupportsOptionalScalars() const {
+ // Check in general if a language isn't specified.
+ return opts.lang_to_generate == 0 || SupportsOptionalScalars(opts);
+}
+
bool Parser::SupportsAdvancedUnionFeatures() const {
return opts.lang_to_generate != 0 &&
- (opts.lang_to_generate & ~(IDLOptions::kCpp | IDLOptions::kJs |
- IDLOptions::kTs | IDLOptions::kPhp |
- IDLOptions::kJava | IDLOptions::kCSharp |
- IDLOptions::kKotlin |
- IDLOptions::kBinary)) == 0;
+ (opts.lang_to_generate &
+ ~(IDLOptions::kCpp | IDLOptions::kJs | IDLOptions::kTs |
+ IDLOptions::kPhp | IDLOptions::kJava | IDLOptions::kCSharp |
+ IDLOptions::kKotlin | IDLOptions::kBinary | IDLOptions::kSwift)) ==
+ 0;
}
bool Parser::SupportsAdvancedArrayFeatures() const {
@@ -2370,8 +2569,8 @@
if (enums_.Add(current_namespace_->GetFullyQualifiedName(enum_name),
&enum_def))
return Error("enum already exists: " + enum_name);
- enum_def.underlying_type.base_type = is_union ? BASE_TYPE_UTYPE
- : BASE_TYPE_INT;
+ enum_def.underlying_type.base_type =
+ is_union ? BASE_TYPE_UTYPE : BASE_TYPE_INT;
enum_def.underlying_type.enum_def = &enum_def;
if (dest) *dest = &enum_def;
return NoError();
@@ -2479,10 +2678,13 @@
auto val = attribute_;
ECHECK(ParseProtoCurliesOrIdent());
if (key == "default") {
- // Temp: skip non-numeric defaults (enums).
+ // Temp: skip non-numeric and non-boolean defaults (enums).
auto numeric = strpbrk(val.c_str(), "0123456789-+.");
- if (IsScalar(type.base_type) && numeric == val.c_str())
+ if (IsScalar(type.base_type) && numeric == val.c_str()) {
field->value.constant = val;
+ } else if (val == "true") {
+ field->value.constant = val;
+ } // "false" is default, no need to handle explicitly.
} else if (key == "deprecated") {
field->deprecated = val == "true";
}
@@ -2507,8 +2709,8 @@
if (oneof_type.base_type != BASE_TYPE_STRUCT ||
!oneof_type.struct_def || oneof_type.struct_def->fixed)
return Error("oneof '" + name +
- "' cannot be mapped to a union because member '" +
- oneof_field.name + "' is not a table type.");
+ "' cannot be mapped to a union because member '" +
+ oneof_field.name + "' is not a table type.");
EnumValBuilder evb(*this, *oneof_union);
auto ev = evb.CreateEnumerator(oneof_type.struct_def->name);
ev->union_type = oneof_type;
@@ -2667,10 +2869,13 @@
builder->Int(StringToInt(attribute_.c_str()));
EXPECT(kTokenIntegerConstant);
break;
- case kTokenFloatConstant:
- builder->Double(strtod(attribute_.c_str(), nullptr));
+ case kTokenFloatConstant: {
+ double d;
+ StringToNumber(attribute_.c_str(), &d);
+ builder->Double(d);
EXPECT(kTokenFloatConstant);
break;
+ }
default:
if (IsIdent("true")) {
builder->Bool(true);
@@ -2698,7 +2903,13 @@
bool Parser::Parse(const char *source, const char **include_paths,
const char *source_filename) {
FLATBUFFERS_ASSERT(0 == recurse_protection_counter);
- auto r = !ParseRoot(source, include_paths, source_filename).Check();
+ bool r;
+
+ if (opts.use_flexbuffers) {
+ r = ParseFlexBuffer(source, source_filename, &flex_builder_);
+ } else {
+ r = !ParseRoot(source, include_paths, source_filename).Check();
+ }
FLATBUFFERS_ASSERT(0 == recurse_protection_counter);
return r;
}
@@ -2747,7 +2958,7 @@
if (field.value.type.struct_def == &struct_def) {
field.value.type.struct_def = nullptr;
field.value.type.enum_def = enum_def;
- auto &bt = field.value.type.base_type == BASE_TYPE_VECTOR
+ auto &bt = IsVector(field.value.type)
? field.value.type.element
: field.value.type.base_type;
FLATBUFFERS_ASSERT(bt == BASE_TYPE_STRUCT);
@@ -2785,8 +2996,8 @@
for (auto val_it = enum_def.Vals().begin();
val_it != enum_def.Vals().end(); ++val_it) {
auto &val = **val_it;
- if (!SupportsAdvancedUnionFeatures() && val.union_type.struct_def &&
- val.union_type.struct_def->fixed)
+ if (!SupportsAdvancedUnionFeatures() &&
+ (IsStruct(val.union_type) || IsString(val.union_type)))
return Error(
"only tables can be union elements in the generated language: " +
val.name);
@@ -2867,9 +3078,7 @@
// entered into included_files_.
// This is recursive, but only go as deep as the number of include
// statements.
- if (source_filename) {
- included_files_.erase(source_filename);
- }
+ if (source_filename) { included_files_.erase(source_filename); }
return DoParse(source, include_paths, source_filename,
include_filename);
}
@@ -2893,9 +3102,9 @@
uoffset_t toff;
ECHECK(ParseTable(*root_struct_def_, nullptr, &toff));
if (opts.size_prefixed) {
- builder_.FinishSizePrefixed(Offset<Table>(toff), file_identifier_.length()
- ? file_identifier_.c_str()
- : nullptr);
+ builder_.FinishSizePrefixed(
+ Offset<Table>(toff),
+ file_identifier_.length() ? file_identifier_.c_str() : nullptr);
} else {
builder_.Finish(Offset<Table>(toff), file_identifier_.length()
? file_identifier_.c_str()
@@ -2916,8 +3125,7 @@
if (opts.root_type.empty()) {
if (!SetRootType(root_type.c_str()))
return Error("unknown root type: " + root_type);
- if (root_struct_def_->fixed)
- return Error("root type must be a table");
+ if (root_struct_def_->fixed) return Error("root type must be a table");
}
EXPECT(';');
} else if (IsIdent("file_identifier")) {
@@ -3022,10 +3230,9 @@
auto fiid__ = builder_.CreateString(file_identifier_);
auto fext__ = builder_.CreateString(file_extension_);
auto serv__ = builder_.CreateVectorOfSortedTables(&service_offsets);
- auto schema_offset =
- reflection::CreateSchema(builder_, objs__, enum__, fiid__, fext__,
- (root_struct_def_ ? root_struct_def_->serialized_location : 0),
- serv__);
+ auto schema_offset = reflection::CreateSchema(
+ builder_, objs__, enum__, fiid__, fext__,
+ (root_struct_def_ ? root_struct_def_->serialized_location : 0), serv__);
if (opts.size_prefixed) {
builder_.FinishSizePrefixed(schema_offset, reflection::SchemaIdentifier());
} else {
@@ -3071,22 +3278,20 @@
auto flds__ = builder->CreateVectorOfSortedTables(&field_offsets);
auto attr__ = SerializeAttributes(builder, parser);
auto docs__ = parser.opts.binary_schema_comments
- ? builder->CreateVectorOfStrings(doc_comment)
- : 0;
+ ? builder->CreateVectorOfStrings(doc_comment)
+ : 0;
return reflection::CreateObject(*builder, name__, flds__, fixed,
static_cast<int>(minalign),
- static_cast<int>(bytesize),
- attr__, docs__);
+ static_cast<int>(bytesize), attr__, docs__);
}
bool StructDef::Deserialize(Parser &parser, const reflection::Object *object) {
- if (!DeserializeAttributes(parser, object->attributes()))
- return false;
+ if (!DeserializeAttributes(parser, object->attributes())) return false;
DeserializeDoc(doc_comment, object->documentation());
name = parser.UnqualifiedName(object->name()->str());
predecl = false;
sortbysize = attributes.Lookup("original_order") == nullptr && !fixed;
- const auto& of = *(object->fields());
+ const auto &of = *(object->fields());
auto indexes = std::vector<uoffset_t>(of.size());
for (uoffset_t i = 0; i < of.size(); i++) indexes[of.Get(i)->id()] = i;
size_t tmp_struct_size = 0;
@@ -3102,9 +3307,7 @@
// Recompute padding since that's currently not serialized.
auto size = InlineSize(field_def->value.type);
auto next_field =
- i + 1 < indexes.size()
- ? of.Get(indexes[i+1])
- : nullptr;
+ i + 1 < indexes.size() ? of.Get(indexes[i + 1]) : nullptr;
tmp_struct_size += size;
field_def->padding =
next_field ? (next_field->offset() - field_def->value.offset) - size
@@ -3123,15 +3326,17 @@
auto type__ = value.type.Serialize(builder);
auto attr__ = SerializeAttributes(builder, parser);
auto docs__ = parser.opts.binary_schema_comments
- ? builder->CreateVectorOfStrings(doc_comment)
- : 0;
- return reflection::CreateField(*builder, name__, type__, id, value.offset,
+ ? builder->CreateVectorOfStrings(doc_comment)
+ : 0;
+ double d;
+ StringToNumber(value.constant.c_str(), &d);
+ return reflection::CreateField(
+ *builder, name__, type__, id, value.offset,
// Is uint64>max(int64) tested?
IsInteger(value.type.base_type) ? StringToInt(value.constant.c_str()) : 0,
// result may be platform-dependent if underlying is float (not double)
- IsFloat(value.type.base_type) ? strtod(value.constant.c_str(), nullptr)
- : 0.0,
- deprecated, required, key, attr__, docs__);
+ IsFloat(value.type.base_type) ? d : 0.0, deprecated, required, key,
+ attr__, docs__, optional);
// 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.
}
@@ -3139,23 +3344,17 @@
bool FieldDef::Deserialize(Parser &parser, const reflection::Field *field) {
name = field->name()->str();
defined_namespace = parser.current_namespace_;
- if (!value.type.Deserialize(parser, field->type()))
- return false;
+ if (!value.type.Deserialize(parser, field->type())) return false;
value.offset = field->offset();
if (IsInteger(value.type.base_type)) {
value.constant = NumToString(field->default_integer());
} else if (IsFloat(value.type.base_type)) {
value.constant = FloatToString(field->default_real(), 16);
- size_t last_zero = value.constant.find_last_not_of('0');
- if (last_zero != std::string::npos && last_zero != 0) {
- value.constant.erase(last_zero, std::string::npos);
- }
}
deprecated = field->deprecated();
required = field->required();
key = field->key();
- if (!DeserializeAttributes(parser, field->attributes()))
- return false;
+ if (!DeserializeAttributes(parser, field->attributes())) return false;
// TODO: this should probably be handled by a separate attribute
if (attributes.Lookup("flexbuffer")) {
flexbuffer = true;
@@ -3170,6 +3369,7 @@
nested_flatbuffer = parser.LookupStruct(nested_qualified_name);
if (!nested_flatbuffer) return false;
}
+ shared = attributes.Lookup("shared") != nullptr;
DeserializeDoc(doc_comment, field->documentation());
return true;
}
@@ -3179,18 +3379,16 @@
auto name__ = builder->CreateString(name);
auto attr__ = SerializeAttributes(builder, parser);
auto docs__ = parser.opts.binary_schema_comments
- ? builder->CreateVectorOfStrings(doc_comment)
- : 0;
- return reflection::CreateRPCCall(*builder, name__,
- request->serialized_location,
- response->serialized_location,
- attr__, docs__);
+ ? builder->CreateVectorOfStrings(doc_comment)
+ : 0;
+ return reflection::CreateRPCCall(
+ *builder, name__, request->serialized_location,
+ response->serialized_location, attr__, docs__);
}
bool RPCCall::Deserialize(Parser &parser, const reflection::RPCCall *call) {
name = call->name()->str();
- if (!DeserializeAttributes(parser, call->attributes()))
- return false;
+ if (!DeserializeAttributes(parser, call->attributes())) return false;
DeserializeDoc(doc_comment, call->documentation());
request = parser.structs_.Lookup(call->request()->name()->str());
response = parser.structs_.Lookup(call->response()->name()->str());
@@ -3209,8 +3407,8 @@
auto call__ = builder->CreateVector(servicecall_offsets);
auto attr__ = SerializeAttributes(builder, parser);
auto docs__ = parser.opts.binary_schema_comments
- ? builder->CreateVectorOfStrings(doc_comment)
- : 0;
+ ? builder->CreateVectorOfStrings(doc_comment)
+ : 0;
return reflection::CreateService(*builder, name__, call__, attr__, docs__);
}
@@ -3227,8 +3425,7 @@
}
}
}
- if (!DeserializeAttributes(parser, service->attributes()))
- return false;
+ if (!DeserializeAttributes(parser, service->attributes())) return false;
DeserializeDoc(doc_comment, service->documentation());
return true;
}
@@ -3245,8 +3442,8 @@
auto type__ = underlying_type.Serialize(builder);
auto attr__ = SerializeAttributes(builder, parser);
auto docs__ = parser.opts.binary_schema_comments
- ? builder->CreateVectorOfStrings(doc_comment)
- : 0;
+ ? builder->CreateVectorOfStrings(doc_comment)
+ : 0;
return reflection::CreateEnum(*builder, name__, vals__, is_union, type__,
attr__, docs__);
}
@@ -3265,8 +3462,7 @@
if (!underlying_type.Deserialize(parser, _enum->underlying_type())) {
return false;
}
- if (!DeserializeAttributes(parser, _enum->attributes()))
- return false;
+ if (!DeserializeAttributes(parser, _enum->attributes())) return false;
DeserializeDoc(doc_comment, _enum->documentation());
return true;
}
@@ -3276,9 +3472,10 @@
auto name__ = builder->CreateString(name);
auto type__ = union_type.Serialize(builder);
auto docs__ = parser.opts.binary_schema_comments
- ? builder->CreateVectorOfStrings(doc_comment)
- : 0;
- return reflection::CreateEnumVal(*builder, name__, value,
+ ? builder->CreateVectorOfStrings(doc_comment)
+ : 0;
+ return reflection::CreateEnumVal(
+ *builder, name__, value,
union_type.struct_def ? union_type.struct_def->serialized_location : 0,
type__, docs__);
}
@@ -3287,8 +3484,7 @@
const reflection::EnumVal *val) {
name = val->name()->str();
value = val->value();
- if (!union_type.Deserialize(parser, val->union_type()))
- return false;
+ if (!union_type.Deserialize(parser, val->union_type())) return false;
DeserializeDoc(doc_comment, val->documentation());
return true;
}
@@ -3310,8 +3506,7 @@
bool is_series = type->base_type() == reflection::Vector ||
type->base_type() == reflection::Array;
if (type->base_type() == reflection::Obj ||
- (is_series &&
- type->element() == reflection::Obj)) {
+ (is_series && type->element() == reflection::Obj)) {
if (static_cast<size_t>(type->index()) < parser.structs_.vec.size()) {
struct_def = parser.structs_.vec[type->index()];
struct_def->refcount++;
@@ -3352,8 +3547,7 @@
bool Definition::DeserializeAttributes(
Parser &parser, const Vector<Offset<reflection::KeyValue>> *attrs) {
- if (attrs == nullptr)
- return true;
+ if (attrs == nullptr) return true;
for (uoffset_t i = 0; i < attrs->size(); ++i) {
auto kv = attrs->Get(i);
auto value = new Value();
@@ -3373,7 +3567,7 @@
bool Parser::Deserialize(const uint8_t *buf, const size_t size) {
flatbuffers::Verifier verifier(reinterpret_cast<const uint8_t *>(buf), size);
bool size_prefixed = false;
- if(!reflection::SchemaBufferHasIdentifier(buf)) {
+ if (!reflection::SchemaBufferHasIdentifier(buf)) {
if (!flatbuffers::BufferHasIdentifier(buf, reflection::SchemaIdentifier(),
true))
return false;
@@ -3382,9 +3576,7 @@
}
auto verify_fn = size_prefixed ? &reflection::VerifySizePrefixedSchemaBuffer
: &reflection::VerifySchemaBuffer;
- if (!verify_fn(verifier)) {
- return false;
- }
+ if (!verify_fn(verifier)) { return false; }
auto schema = size_prefixed ? reflection::GetSizePrefixedSchema(buf)
: reflection::GetSchema(buf);
return Deserialize(schema);
@@ -3433,7 +3625,7 @@
auto struct_def = structs_.Lookup(qualified_name);
struct_def->defined_namespace =
GetNamespace(qualified_name, namespaces_, namespaces_index);
- if (!struct_def->Deserialize(*this, * it)) { return false; }
+ if (!struct_def->Deserialize(*this, *it)) { return false; }
if (schema->root_table() == *it) { root_struct_def_ = struct_def; }
}
for (auto it = schema->enums()->begin(); it != schema->enums()->end(); ++it) {