diff options
| author | Martin Braun <martin.braun@ettus.com> | 2020-03-03 10:40:21 -0800 | 
|---|---|---|
| committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2020-03-18 12:53:00 -0500 | 
| commit | c755531eac46470e99568adfb62c4fbbc6e860d7 (patch) | |
| tree | 0a730126e593d6f8aa3591e647d55ff251b98cec /host/lib/deps | |
| parent | 3f1554f1a5a71190e2105354b8f6a8faa3347124 (diff) | |
| download | uhd-c755531eac46470e99568adfb62c4fbbc6e860d7.tar.gz uhd-c755531eac46470e99568adfb62c4fbbc6e860d7.tar.bz2 uhd-c755531eac46470e99568adfb62c4fbbc6e860d7.zip | |
lib: deps: Add FlatBuffers 1.11.0 header files
FlatBuffers is used to (de-)serialize calibration data. For most use
cases, only a few headers are required, so we provide them with UHD
instead of requiring all UHD users to install their own version of
FlatBuffers.
This adds the headers to host/lib/deps, and updates the Debian copyright
file appropriately.
Diffstat (limited to 'host/lib/deps')
16 files changed, 9175 insertions, 0 deletions
| diff --git a/host/lib/deps/CMakeLists.txt b/host/lib/deps/CMakeLists.txt index e3dc76ee4..f6acc8543 100644 --- a/host/lib/deps/CMakeLists.txt +++ b/host/lib/deps/CMakeLists.txt @@ -1,5 +1,6 @@  #  # Copyright 2017 Ettus Research, a National Instruments Company +# Copyright 2020 Ettus Research, a National Instruments Brand  #  # SPDX-License-Identifier: GPL-3.0-or-later  # @@ -10,3 +11,4 @@ endif()  if(ENABLE_PYTHON_API)      add_subdirectory(pybind11)  endif() +add_subdirectory(flatbuffers) diff --git a/host/lib/deps/flatbuffers/CMakeLists.txt b/host/lib/deps/flatbuffers/CMakeLists.txt new file mode 100644 index 000000000..aa8de0589 --- /dev/null +++ b/host/lib/deps/flatbuffers/CMakeLists.txt @@ -0,0 +1 @@ +include_directories(include) diff --git a/host/lib/deps/flatbuffers/LICENSE.txt b/host/lib/deps/flatbuffers/LICENSE.txt new file mode 100644 index 000000000..a4c5efd82 --- /dev/null +++ b/host/lib/deps/flatbuffers/LICENSE.txt @@ -0,0 +1,202 @@ + +                                 Apache License +                           Version 2.0, January 2004 +                        http://www.apache.org/licenses/ + +   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +   1. Definitions. + +      "License" shall mean the terms and conditions for use, reproduction, +      and distribution as defined by Sections 1 through 9 of this document. + +      "Licensor" shall mean the copyright owner or entity authorized by +      the copyright owner that is granting the License. + +      "Legal Entity" shall mean the union of the acting entity and all +      other entities that control, are controlled by, or are under common +      control with that entity. For the purposes of this definition, +      "control" means (i) the power, direct or indirect, to cause the +      direction or management of such entity, whether by contract or +      otherwise, or (ii) ownership of fifty percent (50%) or more of the +      outstanding shares, or (iii) beneficial ownership of such entity. + +      "You" (or "Your") shall mean an individual or Legal Entity +      exercising permissions granted by this License. + +      "Source" form shall mean the preferred form for making modifications, +      including but not limited to software source code, documentation +      source, and configuration files. + +      "Object" form shall mean any form resulting from mechanical +      transformation or translation of a Source form, including but +      not limited to compiled object code, generated documentation, +      and conversions to other media types. + +      "Work" shall mean the work of authorship, whether in Source or +      Object form, made available under the License, as indicated by a +      copyright notice that is included in or attached to the work +      (an example is provided in the Appendix below). + +      "Derivative Works" shall mean any work, whether in Source or Object +      form, that is based on (or derived from) the Work and for which the +      editorial revisions, annotations, elaborations, or other modifications +      represent, as a whole, an original work of authorship. For the purposes +      of this License, Derivative Works shall not include works that remain +      separable from, or merely link (or bind by name) to the interfaces of, +      the Work and Derivative Works thereof. + +      "Contribution" shall mean any work of authorship, including +      the original version of the Work and any modifications or additions +      to that Work or Derivative Works thereof, that is intentionally +      submitted to Licensor for inclusion in the Work by the copyright owner +      or by an individual or Legal Entity authorized to submit on behalf of +      the copyright owner. For the purposes of this definition, "submitted" +      means any form of electronic, verbal, or written communication sent +      to the Licensor or its representatives, including but not limited to +      communication on electronic mailing lists, source code control systems, +      and issue tracking systems that are managed by, or on behalf of, the +      Licensor for the purpose of discussing and improving the Work, but +      excluding communication that is conspicuously marked or otherwise +      designated in writing by the copyright owner as "Not a Contribution." + +      "Contributor" shall mean Licensor and any individual or Legal Entity +      on behalf of whom a Contribution has been received by Licensor and +      subsequently incorporated within the Work. + +   2. Grant of Copyright License. Subject to the terms and conditions of +      this License, each Contributor hereby grants to You a perpetual, +      worldwide, non-exclusive, no-charge, royalty-free, irrevocable +      copyright license to reproduce, prepare Derivative Works of, +      publicly display, publicly perform, sublicense, and distribute the +      Work and such Derivative Works in Source or Object form. + +   3. Grant of Patent License. Subject to the terms and conditions of +      this License, each Contributor hereby grants to You a perpetual, +      worldwide, non-exclusive, no-charge, royalty-free, irrevocable +      (except as stated in this section) patent license to make, have made, +      use, offer to sell, sell, import, and otherwise transfer the Work, +      where such license applies only to those patent claims licensable +      by such Contributor that are necessarily infringed by their +      Contribution(s) alone or by combination of their Contribution(s) +      with the Work to which such Contribution(s) was submitted. If You +      institute patent litigation against any entity (including a +      cross-claim or counterclaim in a lawsuit) alleging that the Work +      or a Contribution incorporated within the Work constitutes direct +      or contributory patent infringement, then any patent licenses +      granted to You under this License for that Work shall terminate +      as of the date such litigation is filed. + +   4. Redistribution. You may reproduce and distribute copies of the +      Work or Derivative Works thereof in any medium, with or without +      modifications, and in Source or Object form, provided that You +      meet the following conditions: + +      (a) You must give any other recipients of the Work or +          Derivative Works a copy of this License; and + +      (b) You must cause any modified files to carry prominent notices +          stating that You changed the files; and + +      (c) You must retain, in the Source form of any Derivative Works +          that You distribute, all copyright, patent, trademark, and +          attribution notices from the Source form of the Work, +          excluding those notices that do not pertain to any part of +          the Derivative Works; and + +      (d) If the Work includes a "NOTICE" text file as part of its +          distribution, then any Derivative Works that You distribute must +          include a readable copy of the attribution notices contained +          within such NOTICE file, excluding those notices that do not +          pertain to any part of the Derivative Works, in at least one +          of the following places: within a NOTICE text file distributed +          as part of the Derivative Works; within the Source form or +          documentation, if provided along with the Derivative Works; or, +          within a display generated by the Derivative Works, if and +          wherever such third-party notices normally appear. The contents +          of the NOTICE file are for informational purposes only and +          do not modify the License. You may add Your own attribution +          notices within Derivative Works that You distribute, alongside +          or as an addendum to the NOTICE text from the Work, provided +          that such additional attribution notices cannot be construed +          as modifying the License. + +      You may add Your own copyright statement to Your modifications and +      may provide additional or different license terms and conditions +      for use, reproduction, or distribution of Your modifications, or +      for any such Derivative Works as a whole, provided Your use, +      reproduction, and distribution of the Work otherwise complies with +      the conditions stated in this License. + +   5. Submission of Contributions. Unless You explicitly state otherwise, +      any Contribution intentionally submitted for inclusion in the Work +      by You to the Licensor shall be under the terms and conditions of +      this License, without any additional terms or conditions. +      Notwithstanding the above, nothing herein shall supersede or modify +      the terms of any separate license agreement you may have executed +      with Licensor regarding such Contributions. + +   6. Trademarks. This License does not grant permission to use the trade +      names, trademarks, service marks, or product names of the Licensor, +      except as required for reasonable and customary use in describing the +      origin of the Work and reproducing the content of the NOTICE file. + +   7. Disclaimer of Warranty. Unless required by applicable law or +      agreed to in writing, Licensor provides the Work (and each +      Contributor provides its Contributions) on an "AS IS" BASIS, +      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +      implied, including, without limitation, any warranties or conditions +      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A +      PARTICULAR PURPOSE. You are solely responsible for determining the +      appropriateness of using or redistributing the Work and assume any +      risks associated with Your exercise of permissions under this License. + +   8. Limitation of Liability. In no event and under no legal theory, +      whether in tort (including negligence), contract, or otherwise, +      unless required by applicable law (such as deliberate and grossly +      negligent acts) or agreed to in writing, shall any Contributor be +      liable to You for damages, including any direct, indirect, special, +      incidental, or consequential damages of any character arising as a +      result of this License or out of the use or inability to use the +      Work (including but not limited to damages for loss of goodwill, +      work stoppage, computer failure or malfunction, or any and all +      other commercial damages or losses), even if such Contributor +      has been advised of the possibility of such damages. + +   9. Accepting Warranty or Additional Liability. While redistributing +      the Work or Derivative Works thereof, You may choose to offer, +      and charge a fee for, acceptance of support, warranty, indemnity, +      or other liability obligations and/or rights consistent with this +      License. However, in accepting such obligations, You may act only +      on Your own behalf and on Your sole responsibility, not on behalf +      of any other Contributor, and only if You agree to indemnify, +      defend, and hold each Contributor harmless for any liability +      incurred by, or claims asserted against, such Contributor by reason +      of your accepting any such warranty or additional liability. + +   END OF TERMS AND CONDITIONS + +   APPENDIX: How to apply the Apache License to your work. + +      To apply the Apache License to your work, attach the following +      boilerplate notice, with the fields enclosed by brackets "[]" +      replaced with your own identifying information. (Don't include +      the brackets!)  The text should be enclosed in the appropriate +      comment syntax for the file format. We also recommend that a +      file or class name and description of purpose be included on the +      same "printed page" as the copyright notice for easier +      identification within third-party archives. + +   Copyright 2014 Google Inc. + +   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. diff --git a/host/lib/deps/flatbuffers/README.md b/host/lib/deps/flatbuffers/README.md new file mode 100644 index 000000000..5db31a788 --- /dev/null +++ b/host/lib/deps/flatbuffers/README.md @@ -0,0 +1,24 @@ +# FlatBuffers: Third-Party Dependency for UHD + +Version: 1.11.0 + +FlatBuffers is a serialization library. We use it to serialize/deserialize +calibration data (and possibly other data) that we want to store in binary +format either on device EEPROMs, or on the local filesystem. + +A full installation of FlatBuffers is not required to run UHD, and the headers +are only required to compile libuhd. Therefore, we ship a version of FlatBuffers +with UHD to avoid the requirement for users to install their own version of +FlatBuffers. + +## License for FlatBuffers + +As a separate, third-party project, FlatBuffers has a different license from UHD. +See the LICENSE file in the same directory as this readme. FlatBuffers has an +Apache license. + +## Importing into UHD + +In order to copy FlatBuffers into UHD, only the `include/` subdirectory from the +FlatBuffers repository was copied into UHD, along with the LICENSE file. + diff --git a/host/lib/deps/flatbuffers/include/flatbuffers/base.h b/host/lib/deps/flatbuffers/include/flatbuffers/base.h new file mode 100644 index 000000000..ee8021fde --- /dev/null +++ b/host/lib/deps/flatbuffers/include/flatbuffers/base.h @@ -0,0 +1,379 @@ +#ifndef FLATBUFFERS_BASE_H_ +#define FLATBUFFERS_BASE_H_ + +// clang-format off + +// If activate should be declared and included first. +#if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \ +    defined(_MSC_VER) && defined(_DEBUG) +  // The _CRTDBG_MAP_ALLOC inside <crtdbg.h> will replace +  // calloc/free (etc) to its debug version using #define directives. +  #define _CRTDBG_MAP_ALLOC +  #include <stdlib.h> +  #include <crtdbg.h> +  // Replace operator new by trace-enabled version. +  #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) +  #define new DEBUG_NEW +#endif + +#if !defined(FLATBUFFERS_ASSERT) +#include <assert.h> +#define FLATBUFFERS_ASSERT assert +#elif defined(FLATBUFFERS_ASSERT_INCLUDE) +// Include file with forward declaration +#include FLATBUFFERS_ASSERT_INCLUDE +#endif + +#ifndef ARDUINO +#include <cstdint> +#endif + +#include <cstddef> +#include <cstdlib> +#include <cstring> + +#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H) +  #include <utility.h> +#else +  #include <utility> +#endif + +#include <string> +#include <type_traits> +#include <vector> +#include <set> +#include <algorithm> +#include <iterator> +#include <memory> + +#ifdef _STLPORT_VERSION +  #define FLATBUFFERS_CPP98_STL +#endif +#ifndef FLATBUFFERS_CPP98_STL +  #include <functional> +#endif + +#include "flatbuffers/stl_emulation.h" + +// Note the __clang__ check is needed, because clang presents itself +// as an older GNUC compiler (4.2). +// Clang 3.3 and later implement all of the ISO C++ 2011 standard. +// Clang 3.4 and later implement all of the ISO C++ 2014 standard. +// http://clang.llvm.org/cxx_status.html + +// Note the MSVC value '__cplusplus' may be incorrect: +// The '__cplusplus' predefined macro in the MSVC stuck at the value 199711L, +// indicating (erroneously!) that the compiler conformed to the C++98 Standard. +// This value should be correct starting from MSVC2017-15.7-Preview-3. +// The '__cplusplus' will be valid only if MSVC2017-15.7-P3 and the `/Zc:__cplusplus` switch is set. +// Workaround (for details see MSDN): +// Use the _MSC_VER and _MSVC_LANG definition instead of the __cplusplus  for compatibility. +// The _MSVC_LANG macro reports the Standard version regardless of the '/Zc:__cplusplus' switch. + +#if defined(__GNUC__) && !defined(__clang__) +  #define FLATBUFFERS_GCC (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) +#else +  #define FLATBUFFERS_GCC 0 +#endif + +#if defined(__clang__) +  #define FLATBUFFERS_CLANG (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) +#else +  #define FLATBUFFERS_CLANG 0 +#endif + +/// @cond FLATBUFFERS_INTERNAL +#if __cplusplus <= 199711L && \ +    (!defined(_MSC_VER) || _MSC_VER < 1600) && \ +    (!defined(__GNUC__) || \ +      (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400)) +  #error A C++11 compatible compiler with support for the auto typing is \ +         required for FlatBuffers. +  #error __cplusplus _MSC_VER __GNUC__  __GNUC_MINOR__  __GNUC_PATCHLEVEL__ +#endif + +#if !defined(__clang__) && \ +    defined(__GNUC__) && \ +    (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600) +  // Backwards compatability for g++ 4.4, and 4.5 which don't have the nullptr +  // and constexpr keywords. Note the __clang__ check is needed, because clang +  // presents itself as an older GNUC compiler. +  #ifndef nullptr_t +    const class nullptr_t { +    public: +      template<class T> inline operator T*() const { return 0; } +    private: +      void operator&() const; +    } nullptr = {}; +  #endif +  #ifndef constexpr +    #define constexpr const +  #endif +#endif + +// The wire format uses a little endian encoding (since that's efficient for +// the common platforms). +#if defined(__s390x__) +  #define FLATBUFFERS_LITTLEENDIAN 0 +#endif // __s390x__ +#if !defined(FLATBUFFERS_LITTLEENDIAN) +  #if defined(__GNUC__) || defined(__clang__) +    #if (defined(__BIG_ENDIAN__) || \ +         (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) +      #define FLATBUFFERS_LITTLEENDIAN 0 +    #else +      #define FLATBUFFERS_LITTLEENDIAN 1 +    #endif // __BIG_ENDIAN__ +  #elif defined(_MSC_VER) +    #if defined(_M_PPC) +      #define FLATBUFFERS_LITTLEENDIAN 0 +    #else +      #define FLATBUFFERS_LITTLEENDIAN 1 +    #endif +  #else +    #error Unable to determine endianness, define FLATBUFFERS_LITTLEENDIAN. +  #endif +#endif // !defined(FLATBUFFERS_LITTLEENDIAN) + +#define FLATBUFFERS_VERSION_MAJOR 1 +#define FLATBUFFERS_VERSION_MINOR 11 +#define FLATBUFFERS_VERSION_REVISION 0 +#define FLATBUFFERS_STRING_EXPAND(X) #X +#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X) + +#if (!defined(_MSC_VER) || _MSC_VER > 1600) && \ +    (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407)) || \ +    defined(__clang__) +  #define FLATBUFFERS_FINAL_CLASS final +  #define FLATBUFFERS_OVERRIDE override +  #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t +#else +  #define FLATBUFFERS_FINAL_CLASS +  #define FLATBUFFERS_OVERRIDE +  #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE +#endif + +#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \ +    (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \ +    (defined(__cpp_constexpr) && __cpp_constexpr >= 200704) +  #define FLATBUFFERS_CONSTEXPR constexpr +#else +  #define FLATBUFFERS_CONSTEXPR const +#endif + +#if (defined(__cplusplus) && __cplusplus >= 201402L) || \ +    (defined(__cpp_constexpr) && __cpp_constexpr >= 201304) +  #define FLATBUFFERS_CONSTEXPR_CPP14 FLATBUFFERS_CONSTEXPR +#else +  #define FLATBUFFERS_CONSTEXPR_CPP14 +#endif + +#if (defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \ +    (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023026)) || \ +    defined(__clang__) +  #define FLATBUFFERS_NOEXCEPT noexcept +#else +  #define FLATBUFFERS_NOEXCEPT +#endif + +// NOTE: the FLATBUFFERS_DELETE_FUNC macro may change the access mode to +// private, so be sure to put it at the end or reset access mode explicitly. +#if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \ +    (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404)) || \ +    defined(__clang__) +  #define FLATBUFFERS_DELETE_FUNC(func) func = delete; +#else +  #define FLATBUFFERS_DELETE_FUNC(func) private: func; +#endif + +#ifndef FLATBUFFERS_HAS_STRING_VIEW +  // Only provide flatbuffers::string_view if __has_include can be used +  // to detect a header that provides an implementation +  #if defined(__has_include) +    // Check for std::string_view (in c++17) +    #if __has_include(<string_view>) && (__cplusplus >= 201606 || _HAS_CXX17) +      #include <string_view> +      namespace flatbuffers { +        typedef std::string_view string_view; +      } +      #define FLATBUFFERS_HAS_STRING_VIEW 1 +    // Check for std::experimental::string_view (in c++14, compiler-dependent) +    #elif __has_include(<experimental/string_view>) && (__cplusplus >= 201411) +      #include <experimental/string_view> +      namespace flatbuffers { +        typedef std::experimental::string_view string_view; +      } +      #define FLATBUFFERS_HAS_STRING_VIEW 1 +    #endif +  #endif // __has_include +#endif // !FLATBUFFERS_HAS_STRING_VIEW + +#ifndef FLATBUFFERS_HAS_NEW_STRTOD +  // Modern (C++11) strtod and strtof functions are available for use. +  // 1) nan/inf strings as argument of strtod; +  // 2) hex-float  as argument of  strtod/strtof. +  #if (defined(_MSC_VER) && _MSC_VER >= 1900) || \ +      (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \ +      (defined(__clang__)) +    #define FLATBUFFERS_HAS_NEW_STRTOD 1 +  #endif +#endif // !FLATBUFFERS_HAS_NEW_STRTOD + +#ifndef FLATBUFFERS_LOCALE_INDEPENDENT +  // Enable locale independent functions {strtof_l, strtod_l,strtoll_l, strtoull_l}. +  // They are part of the POSIX-2008 but not part of the C/C++ standard. +  // GCC/Clang have definition (_XOPEN_SOURCE>=700) if POSIX-2008. +  #if ((defined(_MSC_VER) && _MSC_VER >= 1800)            || \ +       (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE>=700))) +    #define FLATBUFFERS_LOCALE_INDEPENDENT 1 +  #else +    #define FLATBUFFERS_LOCALE_INDEPENDENT 0 +  #endif +#endif  // !FLATBUFFERS_LOCALE_INDEPENDENT + +// Suppress Undefined Behavior Sanitizer (recoverable only). Usage: +// - __supress_ubsan__("undefined") +// - __supress_ubsan__("signed-integer-overflow") +#if defined(__clang__) +  #define __supress_ubsan__(type) __attribute__((no_sanitize(type))) +#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409) +  #define __supress_ubsan__(type) __attribute__((no_sanitize_undefined)) +#else +  #define __supress_ubsan__(type) +#endif + +// This is constexpr function used for checking compile-time constants. +// Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`. +template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) { +  return !!t; +} + +// Enable C++ attribute [[]] if std:c++17 or higher. +#if ((__cplusplus >= 201703L) \ +    || (defined(_MSVC_LANG) &&  (_MSVC_LANG >= 201703L))) +  // All attributes unknown to an implementation are ignored without causing an error. +  #define FLATBUFFERS_ATTRIBUTE(attr) [[attr]] + +  #define FLATBUFFERS_FALLTHROUGH() [[fallthrough]] +#else +  #define FLATBUFFERS_ATTRIBUTE(attr) + +  #if FLATBUFFERS_CLANG >= 30800 +    #define FLATBUFFERS_FALLTHROUGH() [[clang::fallthrough]] +  #elif FLATBUFFERS_GCC >= 70300 +    #define FLATBUFFERS_FALLTHROUGH() [[gnu::fallthrough]] +  #else +    #define FLATBUFFERS_FALLTHROUGH() +  #endif +#endif + +/// @endcond + +/// @file +namespace flatbuffers { + +/// @cond FLATBUFFERS_INTERNAL +// Our default offset / size type, 32bit on purpose on 64bit systems. +// Also, using a consistent offset type maintains compatibility of serialized +// offset values between 32bit and 64bit systems. +typedef uint32_t uoffset_t; + +// Signed offsets for references that can go in both directions. +typedef int32_t soffset_t; + +// Offset/index used in v-tables, can be changed to uint8_t in +// format forks to save a bit of space if desired. +typedef uint16_t voffset_t; + +typedef uintmax_t largest_scalar_t; + +// In 32bits, this evaluates to 2GB - 1 +#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(soffset_t) * 8 - 1)) - 1) + +// We support aligning the contents of buffers up to this size. +#define FLATBUFFERS_MAX_ALIGNMENT 16 + +#if defined(_MSC_VER) +  #pragma warning(push) +  #pragma warning(disable: 4127) // C4127: conditional expression is constant +#endif + +template<typename T> T EndianSwap(T t) { +  #if defined(_MSC_VER) +    #define FLATBUFFERS_BYTESWAP16 _byteswap_ushort +    #define FLATBUFFERS_BYTESWAP32 _byteswap_ulong +    #define FLATBUFFERS_BYTESWAP64 _byteswap_uint64 +  #else +    #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__) +      // __builtin_bswap16 was missing prior to GCC 4.8. +      #define FLATBUFFERS_BYTESWAP16(x) \ +        static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16)) +    #else +      #define FLATBUFFERS_BYTESWAP16 __builtin_bswap16 +    #endif +    #define FLATBUFFERS_BYTESWAP32 __builtin_bswap32 +    #define FLATBUFFERS_BYTESWAP64 __builtin_bswap64 +  #endif +  if (sizeof(T) == 1) {   // Compile-time if-then's. +    return t; +  } else if (sizeof(T) == 2) { +    union { T t; uint16_t i; } u; +    u.t = t; +    u.i = FLATBUFFERS_BYTESWAP16(u.i); +    return u.t; +  } else if (sizeof(T) == 4) { +    union { T t; uint32_t i; } u; +    u.t = t; +    u.i = FLATBUFFERS_BYTESWAP32(u.i); +    return u.t; +  } else if (sizeof(T) == 8) { +    union { T t; uint64_t i; } u; +    u.t = t; +    u.i = FLATBUFFERS_BYTESWAP64(u.i); +    return u.t; +  } else { +    FLATBUFFERS_ASSERT(0); +  } +} + +#if defined(_MSC_VER) +  #pragma warning(pop) +#endif + + +template<typename T> T EndianScalar(T t) { +  #if FLATBUFFERS_LITTLEENDIAN +    return t; +  #else +    return EndianSwap(t); +  #endif +} + +template<typename T> +// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details. +__supress_ubsan__("alignment") +T ReadScalar(const void *p) { +  return EndianScalar(*reinterpret_cast<const T *>(p)); +} + +template<typename T> +// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details. +__supress_ubsan__("alignment") +void WriteScalar(void *p, T t) { +  *reinterpret_cast<T *>(p) = EndianScalar(t); +} + +template<typename T> struct Offset; +template<typename T> __supress_ubsan__("alignment") void WriteScalar(void *p, Offset<T> t) { +  *reinterpret_cast<uoffset_t *>(p) = EndianScalar(t.o); +} + +// Computes how many bytes you'd have to pad to be able to write an +// "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in +// memory). +inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) { +  return ((~buf_size) + 1) & (scalar_size - 1); +} + +}  // namespace flatbuffers +#endif  // FLATBUFFERS_BASE_H_ diff --git a/host/lib/deps/flatbuffers/include/flatbuffers/code_generators.h b/host/lib/deps/flatbuffers/include/flatbuffers/code_generators.h new file mode 100644 index 000000000..c2ed707ae --- /dev/null +++ b/host/lib/deps/flatbuffers/include/flatbuffers/code_generators.h @@ -0,0 +1,203 @@ +/* + * 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. + */ + +#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 std::string NamespaceDir(const Parser &parser, const std::string &path, +                                  const Namespace &ns); + + protected: +  BaseGenerator(const Parser &parser, const std::string &path, +                const std::string &file_name, +                const std::string qualifying_start, +                const std::string qualifying_separator) +      : parser_(parser), +        path_(path), +        file_name_(file_name), +        qualifying_start_(qualifying_start), +        qualifying_separator_(qualifying_separator) {} +  virtual ~BaseGenerator() {} + +  // No copy/assign. +  BaseGenerator &operator=(const BaseGenerator &); +  BaseGenerator(const BaseGenerator &); + +  std::string NamespaceDir(const Namespace &ns) const; + +  static const char *FlatBuffersGeneratedWarning(); + +  static std::string FullNamespace(const char *separator, const Namespace &ns); + +  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() 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) const; + +  std::string WrapInNameSpace(const Definition &def) const; + +  std::string GetNameSpace(const Definition &def) const; + +  const Parser &parser_; +  const std::string &path_; +  const std::string &file_name_; +  const std::string qualifying_start_; +  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 = ""); + +class FloatConstantGenerator { + public: +  virtual ~FloatConstantGenerator() {} +  std::string GenFloatConstant(const FieldDef &field) const; + + private: +  virtual std::string Value(double v, const std::string &src) const = 0; +  virtual std::string Inf(double v) const = 0; +  virtual std::string NaN(double v) const = 0; + +  virtual std::string Value(float v, const std::string &src) const = 0; +  virtual std::string Inf(float v) const = 0; +  virtual std::string NaN(float v) const = 0; + +  template<typename T> +  std::string GenFloatConstantImpl(const FieldDef &field) const; +}; + +class SimpleFloatConstantGenerator : public FloatConstantGenerator { + public: +  SimpleFloatConstantGenerator(const char *nan_number, +                               const char *pos_inf_number, +                               const char *neg_inf_number); + + private: +  std::string Value(double v, +                    const std::string &src) const FLATBUFFERS_OVERRIDE; +  std::string Inf(double v) const FLATBUFFERS_OVERRIDE; +  std::string NaN(double v) const FLATBUFFERS_OVERRIDE; + +  std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE; +  std::string Inf(float v) const FLATBUFFERS_OVERRIDE; +  std::string NaN(float v) const FLATBUFFERS_OVERRIDE; + +  const std::string nan_number_; +  const std::string pos_inf_number_; +  const std::string neg_inf_number_; +}; + +// C++, C#, Java like generator. +class TypedFloatConstantGenerator : public FloatConstantGenerator { + public: +  TypedFloatConstantGenerator(const char *double_prefix, +                              const char *single_prefix, const char *nan_number, +                              const char *pos_inf_number, +                              const char *neg_inf_number = ""); + + private: +  std::string Value(double v, +                    const std::string &src) const FLATBUFFERS_OVERRIDE; +  std::string Inf(double v) const FLATBUFFERS_OVERRIDE; + +  std::string NaN(double v) const FLATBUFFERS_OVERRIDE; + +  std::string Value(float v, const std::string &src) const FLATBUFFERS_OVERRIDE; +  std::string Inf(float v) const FLATBUFFERS_OVERRIDE; +  std::string NaN(float v) const FLATBUFFERS_OVERRIDE; + +  std::string MakeNaN(const std::string &prefix) const; +  std::string MakeInf(bool neg, const std::string &prefix) const; + +  const std::string double_prefix_; +  const std::string single_prefix_; +  const std::string nan_number_; +  const std::string pos_inf_number_; +  const std::string neg_inf_number_; +}; + +}  // namespace flatbuffers + +#endif  // FLATBUFFERS_CODE_GENERATORS_H_ diff --git a/host/lib/deps/flatbuffers/include/flatbuffers/flatbuffers.h b/host/lib/deps/flatbuffers/include/flatbuffers/flatbuffers.h new file mode 100644 index 000000000..a1a95f00e --- /dev/null +++ b/host/lib/deps/flatbuffers/include/flatbuffers/flatbuffers.h @@ -0,0 +1,2613 @@ +/* + * 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. + */ + +#ifndef FLATBUFFERS_H_ +#define FLATBUFFERS_H_ + +#include "flatbuffers/base.h" + +#if defined(FLATBUFFERS_NAN_DEFAULTS) +#include <cmath> +#endif + +namespace flatbuffers { +// Generic 'operator==' with conditional specialisations. +template<typename T> inline bool IsTheSameAs(T e, T def) { return e == def; } + +#if defined(FLATBUFFERS_NAN_DEFAULTS) && \ +    (!defined(_MSC_VER) || _MSC_VER >= 1800) +// Like `operator==(e, def)` with weak NaN if T=(float|double). +template<> inline bool IsTheSameAs<float>(float e, float def) { +  return (e == def) || (std::isnan(def) && std::isnan(e)); +} +template<> inline bool IsTheSameAs<double>(double e, double def) { +  return (e == def) || (std::isnan(def) && std::isnan(e)); +} +#endif + +// Wrapper for uoffset_t to allow safe template specialization. +// Value is allowed to be 0 to indicate a null object (see e.g. AddOffset). +template<typename T> struct Offset { +  uoffset_t o; +  Offset() : o(0) {} +  Offset(uoffset_t _o) : o(_o) {} +  Offset<void> Union() const { return Offset<void>(o); } +  bool IsNull() const { return !o; } +}; + +inline void EndianCheck() { +  int endiantest = 1; +  // If this fails, see FLATBUFFERS_LITTLEENDIAN above. +  FLATBUFFERS_ASSERT(*reinterpret_cast<char *>(&endiantest) == +                     FLATBUFFERS_LITTLEENDIAN); +  (void)endiantest; +} + +template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() { +  // clang-format off +  #ifdef _MSC_VER +    return __alignof(T); +  #else +    #ifndef alignof +      return __alignof__(T); +    #else +      return alignof(T); +    #endif +  #endif +  // clang-format on +} + +// When we read serialized data from memory, in the case of most scalars, +// we want to just read T, but in the case of Offset, we want to actually +// perform the indirection and return a pointer. +// The template specialization below does just that. +// It is wrapped in a struct since function templates can't overload on the +// return type like this. +// The typedef is for the convenience of callers of this function +// (avoiding the need for a trailing return decltype) +template<typename T> struct IndirectHelper { +  typedef T return_type; +  typedef T mutable_return_type; +  static const size_t element_stride = sizeof(T); +  static return_type Read(const uint8_t *p, uoffset_t i) { +    return EndianScalar((reinterpret_cast<const T *>(p))[i]); +  } +}; +template<typename T> struct IndirectHelper<Offset<T>> { +  typedef const T *return_type; +  typedef T *mutable_return_type; +  static const size_t element_stride = sizeof(uoffset_t); +  static return_type Read(const uint8_t *p, uoffset_t i) { +    p += i * sizeof(uoffset_t); +    return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p)); +  } +}; +template<typename T> struct IndirectHelper<const T *> { +  typedef const T *return_type; +  typedef T *mutable_return_type; +  static const size_t element_stride = sizeof(T); +  static return_type Read(const uint8_t *p, uoffset_t i) { +    return reinterpret_cast<const T *>(p + i * sizeof(T)); +  } +}; + +// An STL compatible iterator implementation for Vector below, effectively +// calling Get() for every element. +template<typename T, typename IT> struct VectorIterator { +  typedef std::random_access_iterator_tag iterator_category; +  typedef IT value_type; +  typedef ptrdiff_t difference_type; +  typedef IT *pointer; +  typedef IT &reference; + +  VectorIterator(const uint8_t *data, uoffset_t i) +      : data_(data + IndirectHelper<T>::element_stride * i) {} +  VectorIterator(const VectorIterator &other) : data_(other.data_) {} +  VectorIterator() : data_(nullptr) {} + +  VectorIterator &operator=(const VectorIterator &other) { +    data_ = other.data_; +    return *this; +  } + +  // clang-format off +  #if !defined(FLATBUFFERS_CPP98_STL) +  VectorIterator &operator=(VectorIterator &&other) { +    data_ = other.data_; +    return *this; +  } +  #endif  // !defined(FLATBUFFERS_CPP98_STL) +  // clang-format on + +  bool operator==(const VectorIterator &other) const { +    return data_ == other.data_; +  } + +  bool operator<(const VectorIterator &other) const { +    return data_ < other.data_; +  } + +  bool operator!=(const VectorIterator &other) const { +    return data_ != other.data_; +  } + +  difference_type operator-(const VectorIterator &other) const { +    return (data_ - other.data_) / IndirectHelper<T>::element_stride; +  } + +  IT operator*() const { return IndirectHelper<T>::Read(data_, 0); } + +  IT operator->() const { return IndirectHelper<T>::Read(data_, 0); } + +  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) const { +    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) const { +    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_; +}; + +template<typename Iterator> struct VectorReverseIterator : +  public std::reverse_iterator<Iterator> { + +  explicit VectorReverseIterator(Iterator iter) : iter_(iter) {} + +  typename Iterator::value_type operator*() const { return *(iter_ - 1); } + +  typename Iterator::value_type operator->() const { return *(iter_ - 1); } + + private: +  Iterator iter_; +}; + +struct String; + +// This is used as a helper type for accessing vectors. +// Vector::data() assumes the vector elements start after the length field. +template<typename T> class Vector { + public: +  typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type> +      iterator; +  typedef VectorIterator<T, typename IndirectHelper<T>::return_type> +      const_iterator; +  typedef VectorReverseIterator<iterator> reverse_iterator; +  typedef VectorReverseIterator<const_iterator> const_reverse_iterator; + +  uoffset_t size() const { return EndianScalar(length_); } + +  // Deprecated: use size(). Here for backwards compatibility. +  FLATBUFFERS_ATTRIBUTE(deprecated("use size() instead")) +  uoffset_t Length() const { return size(); } + +  typedef typename IndirectHelper<T>::return_type return_type; +  typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type; + +  return_type Get(uoffset_t i) const { +    FLATBUFFERS_ASSERT(i < size()); +    return IndirectHelper<T>::Read(Data(), i); +  } + +  return_type operator[](uoffset_t i) const { return Get(i); } + +  // If this is a Vector of enums, T will be its storage type, not the enum +  // type. This function makes it convenient to retrieve value with enum +  // type E. +  template<typename E> E GetEnum(uoffset_t i) const { +    return static_cast<E>(Get(i)); +  } + +  // If this a vector of unions, this does the cast for you. There's no check +  // to make sure this is the right type! +  template<typename U> const U *GetAs(uoffset_t i) const { +    return reinterpret_cast<const U *>(Get(i)); +  } + +  // If this a vector of unions, this does the cast for you. There's no check +  // to make sure this is actually a string! +  const String *GetAsString(uoffset_t i) const { +    return reinterpret_cast<const String *>(Get(i)); +  } + +  const void *GetStructFromOffset(size_t o) const { +    return reinterpret_cast<const void *>(Data() + o); +  } + +  iterator begin() { return iterator(Data(), 0); } +  const_iterator begin() const { return const_iterator(Data(), 0); } + +  iterator end() { return iterator(Data(), size()); } +  const_iterator end() const { return const_iterator(Data(), size()); } + +  reverse_iterator rbegin() { return reverse_iterator(end()); } +  const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + +  reverse_iterator rend() { return reverse_iterator(end()); } +  const_reverse_iterator rend() const { return const_reverse_iterator(end()); } + +  const_iterator cbegin() const { return begin(); } + +  const_iterator cend() const { return end(); } + +  const_reverse_iterator crbegin() const { return rbegin(); } + +  const_reverse_iterator crend() const { return rend(); } + +  // Change elements if you have a non-const pointer to this object. +  // Scalars only. See reflection.h, and the documentation. +  void Mutate(uoffset_t i, const T &val) { +    FLATBUFFERS_ASSERT(i < size()); +    WriteScalar(data() + i, val); +  } + +  // Change an element of a vector of tables (or strings). +  // "val" points to the new table/string, as you can obtain from +  // e.g. reflection::AddFlatBuffer(). +  void MutateOffset(uoffset_t i, const uint8_t *val) { +    FLATBUFFERS_ASSERT(i < size()); +    static_assert(sizeof(T) == sizeof(uoffset_t), "Unrelated types"); +    WriteScalar(data() + i, +                static_cast<uoffset_t>(val - (Data() + i * sizeof(uoffset_t)))); +  } + +  // Get a mutable pointer to tables/strings inside this vector. +  mutable_return_type GetMutableObject(uoffset_t i) const { +    FLATBUFFERS_ASSERT(i < size()); +    return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i)); +  } + +  // The raw data in little endian format. Use with care. +  const uint8_t *Data() const { +    return reinterpret_cast<const uint8_t *>(&length_ + 1); +  } + +  uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); } + +  // Similarly, but typed, much like std::vector::data +  const T *data() const { return reinterpret_cast<const T *>(Data()); } +  T *data() { return reinterpret_cast<T *>(Data()); } + +  template<typename K> return_type LookupByKey(K key) const { +    void *search_result = std::bsearch( +        &key, Data(), size(), IndirectHelper<T>::element_stride, KeyCompare<K>); + +    if (!search_result) { +      return nullptr;  // Key not found. +    } + +    const uint8_t *element = reinterpret_cast<const uint8_t *>(search_result); + +    return IndirectHelper<T>::Read(element, 0); +  } + + protected: +  // This class is only used to access pre-existing data. Don't ever +  // try to construct these manually. +  Vector(); + +  uoffset_t length_; + + private: +  // This class is a pointer. Copying will therefore create an invalid object. +  // Private and unimplemented copy constructor. +  Vector(const Vector &); + +  template<typename K> static int KeyCompare(const void *ap, const void *bp) { +    const K *key = reinterpret_cast<const K *>(ap); +    const uint8_t *data = reinterpret_cast<const uint8_t *>(bp); +    auto table = IndirectHelper<T>::Read(data, 0); + +    // std::bsearch compares with the operands transposed, so we negate the +    // result here. +    return -table->KeyCompareWithValue(*key); +  } +}; + +// Represent a vector much like the template above, but in this case we +// don't know what the element types are (used with reflection.h). +class VectorOfAny { + public: +  uoffset_t size() const { return EndianScalar(length_); } + +  const uint8_t *Data() const { +    return reinterpret_cast<const uint8_t *>(&length_ + 1); +  } +  uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); } + + protected: +  VectorOfAny(); + +  uoffset_t length_; + + private: +  VectorOfAny(const VectorOfAny &); +}; + +#ifndef FLATBUFFERS_CPP98_STL +template<typename T, typename U> +Vector<Offset<T>> *VectorCast(Vector<Offset<U>> *ptr) { +  static_assert(std::is_base_of<T, U>::value, "Unrelated types"); +  return reinterpret_cast<Vector<Offset<T>> *>(ptr); +} + +template<typename T, typename U> +const Vector<Offset<T>> *VectorCast(const Vector<Offset<U>> *ptr) { +  static_assert(std::is_base_of<T, U>::value, "Unrelated types"); +  return reinterpret_cast<const Vector<Offset<T>> *>(ptr); +} +#endif + +// Convenient helper function to get the length of any vector, regardless +// of whether it is null or not (the field is not set). +template<typename T> static inline size_t VectorLength(const Vector<T> *v) { +  return v ? v->size() : 0; +} + +// Lexicographically compare two strings (possibly containing nulls), and +// return true if the first is less than the second. +static inline bool StringLessThan(const char *a_data, uoffset_t a_size, +                                  const char *b_data, uoffset_t b_size) { +  const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size)); +  return cmp == 0 ? a_size < b_size : cmp < 0; +} + +struct String : public Vector<char> { +  const char *c_str() const { return reinterpret_cast<const char *>(Data()); } +  std::string str() const { return std::string(c_str(), size()); } + +  // clang-format off +  #ifdef FLATBUFFERS_HAS_STRING_VIEW +  flatbuffers::string_view string_view() const { +    return flatbuffers::string_view(c_str(), size()); +  } +  #endif // FLATBUFFERS_HAS_STRING_VIEW +  // clang-format on + +  bool operator<(const String &o) const { +    return StringLessThan(this->data(), this->size(), o.data(), o.size()); +  } +}; + +// Convenience function to get std::string from a String returning an empty +// string on null pointer. +static inline std::string GetString(const String * str) { +  return str ? str->str() : ""; +} + +// Convenience function to get char* from a String returning an empty string on +// null pointer. +static inline const char * GetCstring(const String * str) { +  return str ? str->c_str() : ""; +} + +// Allocator interface. This is flatbuffers-specific and meant only for +// `vector_downward` usage. +class Allocator { + public: +  virtual ~Allocator() {} + +  // Allocate `size` bytes of memory. +  virtual uint8_t *allocate(size_t size) = 0; + +  // Deallocate `size` bytes of memory at `p` allocated by this allocator. +  virtual void deallocate(uint8_t *p, size_t size) = 0; + +  // Reallocate `new_size` bytes of memory, replacing the old region of size +  // `old_size` at `p`. In contrast to a normal realloc, this grows downwards, +  // and is intended specifcally for `vector_downward` use. +  // `in_use_back` and `in_use_front` indicate how much of `old_size` is +  // actually in use at each end, and needs to be copied. +  virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size, +                                       size_t new_size, size_t in_use_back, +                                       size_t in_use_front) { +    FLATBUFFERS_ASSERT(new_size > old_size);  // vector_downward only grows +    uint8_t *new_p = allocate(new_size); +    memcpy_downward(old_p, old_size, new_p, new_size, in_use_back, +                    in_use_front); +    deallocate(old_p, old_size); +    return new_p; +  } + + protected: +  // Called by `reallocate_downward` to copy memory from `old_p` of `old_size` +  // to `new_p` of `new_size`. Only memory of size `in_use_front` and +  // `in_use_back` will be copied from the front and back of the old memory +  // allocation. +  void memcpy_downward(uint8_t *old_p, size_t old_size, +                       uint8_t *new_p, size_t new_size, +                       size_t in_use_back, size_t in_use_front) { +    memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back, +           in_use_back); +    memcpy(new_p, old_p, in_use_front); +  } +}; + +// DefaultAllocator uses new/delete to allocate memory regions +class DefaultAllocator : public Allocator { + public: +  uint8_t *allocate(size_t size) FLATBUFFERS_OVERRIDE { +    return new uint8_t[size]; +  } + +  void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE { +    delete[] p; +  } + +  static void dealloc(void *p, size_t) { +    delete[] static_cast<uint8_t *>(p); +  } +}; + +// These functions allow for a null allocator to mean use the default allocator, +// as used by DetachedBuffer and vector_downward below. +// This is to avoid having a statically or dynamically allocated default +// allocator, or having to move it between the classes that may own it. +inline uint8_t *Allocate(Allocator *allocator, size_t size) { +  return allocator ? allocator->allocate(size) +                   : DefaultAllocator().allocate(size); +} + +inline void Deallocate(Allocator *allocator, uint8_t *p, size_t size) { +  if (allocator) allocator->deallocate(p, size); +  else DefaultAllocator().deallocate(p, size); +} + +inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p, +                                   size_t old_size, size_t new_size, +                                   size_t in_use_back, size_t in_use_front) { +  return allocator +      ? allocator->reallocate_downward(old_p, old_size, new_size, +                                       in_use_back, in_use_front) +      : DefaultAllocator().reallocate_downward(old_p, old_size, new_size, +                                               in_use_back, in_use_front); +} + +// DetachedBuffer is a finished flatbuffer memory region, detached from its +// builder. The original memory region and allocator are also stored so that +// the DetachedBuffer can manage the memory lifetime. +class DetachedBuffer { + public: +  DetachedBuffer() +      : allocator_(nullptr), +        own_allocator_(false), +        buf_(nullptr), +        reserved_(0), +        cur_(nullptr), +        size_(0) {} + +  DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf, +                 size_t reserved, uint8_t *cur, size_t sz) +      : allocator_(allocator), +        own_allocator_(own_allocator), +        buf_(buf), +        reserved_(reserved), +        cur_(cur), +        size_(sz) {} + +  // clang-format off +  #if !defined(FLATBUFFERS_CPP98_STL) +  // clang-format on +  DetachedBuffer(DetachedBuffer &&other) +      : allocator_(other.allocator_), +        own_allocator_(other.own_allocator_), +        buf_(other.buf_), +        reserved_(other.reserved_), +        cur_(other.cur_), +        size_(other.size_) { +    other.reset(); +  } +  // clang-format off +  #endif  // !defined(FLATBUFFERS_CPP98_STL) +  // clang-format on + +  // clang-format off +  #if !defined(FLATBUFFERS_CPP98_STL) +  // clang-format on +  DetachedBuffer &operator=(DetachedBuffer &&other) { +    destroy(); + +    allocator_ = other.allocator_; +    own_allocator_ = other.own_allocator_; +    buf_ = other.buf_; +    reserved_ = other.reserved_; +    cur_ = other.cur_; +    size_ = other.size_; + +    other.reset(); + +    return *this; +  } +  // clang-format off +  #endif  // !defined(FLATBUFFERS_CPP98_STL) +  // clang-format on + +  ~DetachedBuffer() { destroy(); } + +  const uint8_t *data() const { return cur_; } + +  uint8_t *data() { return cur_; } + +  size_t size() const { return size_; } + +  // clang-format off +  #if 0  // disabled for now due to the ordering of classes in this header +  template <class T> +  bool Verify() const { +    Verifier verifier(data(), size()); +    return verifier.Verify<T>(nullptr); +  } + +  template <class T> +  const T* GetRoot() const { +    return flatbuffers::GetRoot<T>(data()); +  } + +  template <class T> +  T* GetRoot() { +    return flatbuffers::GetRoot<T>(data()); +  } +  #endif +  // clang-format on + +  // clang-format off +  #if !defined(FLATBUFFERS_CPP98_STL) +  // clang-format on +  // These may change access mode, leave these at end of public section +  FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other)) +  FLATBUFFERS_DELETE_FUNC( +      DetachedBuffer &operator=(const DetachedBuffer &other)) +  // clang-format off +  #endif  // !defined(FLATBUFFERS_CPP98_STL) +  // clang-format on + +protected: +  Allocator *allocator_; +  bool own_allocator_; +  uint8_t *buf_; +  size_t reserved_; +  uint8_t *cur_; +  size_t size_; + +  inline void destroy() { +    if (buf_) Deallocate(allocator_, buf_, reserved_); +    if (own_allocator_ && allocator_) { delete allocator_; } +    reset(); +  } + +  inline void reset() { +    allocator_ = nullptr; +    own_allocator_ = false; +    buf_ = nullptr; +    reserved_ = 0; +    cur_ = nullptr; +    size_ = 0; +  } +}; + +// This is a minimal replication of std::vector<uint8_t> functionality, +// except growing from higher to lower addresses. i.e push_back() inserts data +// in the lowest address in the vector. +// Since this vector leaves the lower part unused, we support a "scratch-pad" +// that can be stored there for temporary data, to share the allocated space. +// Essentially, this supports 2 std::vectors in a single buffer. +class vector_downward { + public: +  explicit vector_downward(size_t initial_size, +                           Allocator *allocator, +                           bool own_allocator, +                           size_t buffer_minalign) +      : allocator_(allocator), +        own_allocator_(own_allocator), +        initial_size_(initial_size), +        buffer_minalign_(buffer_minalign), +        reserved_(0), +        buf_(nullptr), +        cur_(nullptr), +        scratch_(nullptr) {} + +  // clang-format off +  #if !defined(FLATBUFFERS_CPP98_STL) +  vector_downward(vector_downward &&other) +  #else +  vector_downward(vector_downward &other) +  #endif  // defined(FLATBUFFERS_CPP98_STL) +  // clang-format on +    : allocator_(other.allocator_), +      own_allocator_(other.own_allocator_), +      initial_size_(other.initial_size_), +      buffer_minalign_(other.buffer_minalign_), +      reserved_(other.reserved_), +      buf_(other.buf_), +      cur_(other.cur_), +      scratch_(other.scratch_) { +    // No change in other.allocator_ +    // No change in other.initial_size_ +    // No change in other.buffer_minalign_ +    other.own_allocator_ = false; +    other.reserved_ = 0; +    other.buf_ = nullptr; +    other.cur_ = nullptr; +    other.scratch_ = nullptr; +  } + +  // clang-format off +  #if !defined(FLATBUFFERS_CPP98_STL) +  // clang-format on +  vector_downward &operator=(vector_downward &&other) { +    // Move construct a temporary and swap idiom +    vector_downward temp(std::move(other)); +    swap(temp); +    return *this; +  } +  // clang-format off +  #endif  // defined(FLATBUFFERS_CPP98_STL) +  // clang-format on + +  ~vector_downward() { +    clear_buffer(); +    clear_allocator(); +  } + +  void reset() { +    clear_buffer(); +    clear(); +  } + +  void clear() { +    if (buf_) { +      cur_ = buf_ + reserved_; +    } else { +      reserved_ = 0; +      cur_ = nullptr; +    } +    clear_scratch(); +  } + +  void clear_scratch() { +    scratch_ = buf_; +  } + +  void clear_allocator() { +    if (own_allocator_ && allocator_) { delete allocator_; } +    allocator_ = nullptr; +    own_allocator_ = false; +  } + +  void clear_buffer() { +    if (buf_) Deallocate(allocator_, buf_, reserved_); +    buf_ = nullptr; +  } + +  // Relinquish the pointer to the caller. +  uint8_t *release_raw(size_t &allocated_bytes, size_t &offset) { +    auto *buf = buf_; +    allocated_bytes = reserved_; +    offset = static_cast<size_t>(cur_ - buf_); + +    // release_raw only relinquishes the buffer ownership. +    // Does not deallocate or reset the allocator. Destructor will do that. +    buf_ = nullptr; +    clear(); +    return buf; +  } + +  // Relinquish the pointer to the caller. +  DetachedBuffer release() { +    // allocator ownership (if any) is transferred to DetachedBuffer. +    DetachedBuffer fb(allocator_, own_allocator_, buf_, reserved_, cur_, +                      size()); +    if (own_allocator_) { +      allocator_ = nullptr; +      own_allocator_ = false; +    } +    buf_ = nullptr; +    clear(); +    return fb; +  } + +  size_t ensure_space(size_t len) { +    FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_); +    if (len > static_cast<size_t>(cur_ - scratch_)) { reallocate(len); } +    // Beyond this, signed offsets may not have enough range: +    // (FlatBuffers > 2GB not supported). +    FLATBUFFERS_ASSERT(size() < FLATBUFFERS_MAX_BUFFER_SIZE); +    return len; +  } + +  inline uint8_t *make_space(size_t len) { +    size_t space = ensure_space(len); +    cur_ -= space; +    return cur_; +  } + +  // Returns nullptr if using the DefaultAllocator. +  Allocator *get_custom_allocator() { return allocator_; } + +  uoffset_t size() const { +    return static_cast<uoffset_t>(reserved_ - (cur_ - buf_)); +  } + +  uoffset_t scratch_size() const { +    return static_cast<uoffset_t>(scratch_ - buf_); +  } + +  size_t capacity() const { return reserved_; } + +  uint8_t *data() const { +    FLATBUFFERS_ASSERT(cur_); +    return cur_; +  } + +  uint8_t *scratch_data() const { +    FLATBUFFERS_ASSERT(buf_); +    return buf_; +  } + +  uint8_t *scratch_end() const { +    FLATBUFFERS_ASSERT(scratch_); +    return scratch_; +  } + +  uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; } + +  void push(const uint8_t *bytes, size_t num) { +    memcpy(make_space(num), bytes, num); +  } + +  // Specialized version of push() that avoids memcpy call for small data. +  template<typename T> void push_small(const T &little_endian_t) { +    make_space(sizeof(T)); +    *reinterpret_cast<T *>(cur_) = little_endian_t; +  } + +  template<typename T> void scratch_push_small(const T &t) { +    ensure_space(sizeof(T)); +    *reinterpret_cast<T *>(scratch_) = t; +    scratch_ += sizeof(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) { +    make_space(zero_pad_bytes); +    for (size_t i = 0; i < zero_pad_bytes; i++) cur_[i] = 0; +  } + +  // Version for when we know the size is larger. +  void fill_big(size_t zero_pad_bytes) { +    memset(make_space(zero_pad_bytes), 0, zero_pad_bytes); +  } + +  void pop(size_t bytes_to_remove) { cur_ += bytes_to_remove; } +  void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; } + +  void swap(vector_downward &other) { +    using std::swap; +    swap(allocator_, other.allocator_); +    swap(own_allocator_, other.own_allocator_); +    swap(initial_size_, other.initial_size_); +    swap(buffer_minalign_, other.buffer_minalign_); +    swap(reserved_, other.reserved_); +    swap(buf_, other.buf_); +    swap(cur_, other.cur_); +    swap(scratch_, other.scratch_); +  } + +  void swap_allocator(vector_downward &other) { +    using std::swap; +    swap(allocator_, other.allocator_); +    swap(own_allocator_, other.own_allocator_); +  } + + private: +  // You shouldn't really be copying instances of this class. +  FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward &)) +  FLATBUFFERS_DELETE_FUNC(vector_downward &operator=(const vector_downward &)) + +  Allocator *allocator_; +  bool own_allocator_; +  size_t initial_size_; +  size_t buffer_minalign_; +  size_t reserved_; +  uint8_t *buf_; +  uint8_t *cur_;  // Points at location between empty (below) and used (above). +  uint8_t *scratch_;  // Points to the end of the scratchpad in use. + +  void reallocate(size_t len) { +    auto old_reserved = reserved_; +    auto old_size = size(); +    auto old_scratch_size = scratch_size(); +    reserved_ += (std::max)(len, +                            old_reserved ? old_reserved / 2 : initial_size_); +    reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1); +    if (buf_) { +      buf_ = ReallocateDownward(allocator_, buf_, old_reserved, reserved_, +                                old_size, old_scratch_size); +    } else { +      buf_ = Allocate(allocator_, reserved_); +    } +    cur_ = buf_ + reserved_ - old_size; +    scratch_ = buf_ + old_scratch_size; +  } +}; + +// Converts a Field ID to a virtual table offset. +inline voffset_t FieldIndexToOffset(voffset_t field_id) { +  // Should correspond to what EndTable() below builds up. +  const int fixed_fields = 2;  // Vtable size and Object Size. +  return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t)); +} + +template<typename T, typename Alloc> +const T *data(const std::vector<T, Alloc> &v) { +  return v.empty() ? nullptr : &v.front(); +} +template<typename T, typename Alloc> T *data(std::vector<T, Alloc> &v) { +  return v.empty() ? nullptr : &v.front(); +} + +/// @endcond + +/// @addtogroup flatbuffers_cpp_api +/// @{ +/// @class FlatBufferBuilder +/// @brief Helper class to hold data needed in creation of a FlatBuffer. +/// To serialize data, you typically call one of the `Create*()` functions in +/// the generated code, which in turn call a sequence of `StartTable`/ +/// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/ +/// `CreateVector` functions. Do this is depth-first order to build up a tree to +/// the root. `Finish()` wraps up the buffer ready for transport. +class FlatBufferBuilder { + public: +  /// @brief Default constructor for FlatBufferBuilder. +  /// @param[in] initial_size The initial size of the buffer, in bytes. Defaults +  /// to `1024`. +  /// @param[in] allocator An `Allocator` to use. If null will use +  /// `DefaultAllocator`. +  /// @param[in] own_allocator Whether the builder/vector should own the +  /// allocator. Defaults to / `false`. +  /// @param[in] buffer_minalign Force the buffer to be aligned to the given +  /// minimum alignment upon reallocation. Only needed if you intend to store +  /// types with custom alignment AND you wish to read the buffer in-place +  /// directly after creation. +  explicit FlatBufferBuilder(size_t initial_size = 1024, +                             Allocator *allocator = nullptr, +                             bool own_allocator = false, +                             size_t buffer_minalign = +                                 AlignOf<largest_scalar_t>()) +      : buf_(initial_size, allocator, own_allocator, buffer_minalign), +        num_field_loc(0), +        max_voffset_(0), +        nested(false), +        finished(false), +        minalign_(1), +        force_defaults_(false), +        dedup_vtables_(true), +        string_pool(nullptr) { +    EndianCheck(); +  } + +  // clang-format off +  /// @brief Move constructor for FlatBufferBuilder. +  #if !defined(FLATBUFFERS_CPP98_STL) +  FlatBufferBuilder(FlatBufferBuilder &&other) +  #else +  FlatBufferBuilder(FlatBufferBuilder &other) +  #endif  // #if !defined(FLATBUFFERS_CPP98_STL) +    : buf_(1024, nullptr, false, AlignOf<largest_scalar_t>()), +      num_field_loc(0), +      max_voffset_(0), +      nested(false), +      finished(false), +      minalign_(1), +      force_defaults_(false), +      dedup_vtables_(true), +      string_pool(nullptr) { +    EndianCheck(); +    // Default construct and swap idiom. +    // Lack of delegating constructors in vs2010 makes it more verbose than needed. +    Swap(other); +  } +  // clang-format on + +  // clang-format off +  #if !defined(FLATBUFFERS_CPP98_STL) +  // clang-format on +  /// @brief Move assignment operator for FlatBufferBuilder. +  FlatBufferBuilder &operator=(FlatBufferBuilder &&other) { +    // Move construct a temporary and swap idiom +    FlatBufferBuilder temp(std::move(other)); +    Swap(temp); +    return *this; +  } +  // clang-format off +  #endif  // defined(FLATBUFFERS_CPP98_STL) +  // clang-format on + +  void Swap(FlatBufferBuilder &other) { +    using std::swap; +    buf_.swap(other.buf_); +    swap(num_field_loc, other.num_field_loc); +    swap(max_voffset_, other.max_voffset_); +    swap(nested, other.nested); +    swap(finished, other.finished); +    swap(minalign_, other.minalign_); +    swap(force_defaults_, other.force_defaults_); +    swap(dedup_vtables_, other.dedup_vtables_); +    swap(string_pool, other.string_pool); +  } + +  ~FlatBufferBuilder() { +    if (string_pool) delete string_pool; +  } + +  void Reset() { +    Clear();       // clear builder state +    buf_.reset();  // deallocate buffer +  } + +  /// @brief Reset all the state in this FlatBufferBuilder so it can be reused +  /// to construct another buffer. +  void Clear() { +    ClearOffsets(); +    buf_.clear(); +    nested = false; +    finished = false; +    minalign_ = 1; +    if (string_pool) string_pool->clear(); +  } + +  /// @brief The current size of the serialized buffer, counting from the end. +  /// @return Returns an `uoffset_t` with the current size of the buffer. +  uoffset_t GetSize() const { return buf_.size(); } + +  /// @brief Get the serialized buffer (after you call `Finish()`). +  /// @return Returns an `uint8_t` pointer to the FlatBuffer data inside the +  /// buffer. +  uint8_t *GetBufferPointer() const { +    Finished(); +    return buf_.data(); +  } + +  /// @brief Get a pointer to an unfinished buffer. +  /// @return Returns a `uint8_t` pointer to the unfinished buffer. +  uint8_t *GetCurrentBufferPointer() const { return buf_.data(); } + +  /// @brief Get the released pointer to the serialized buffer. +  /// @warning Do NOT attempt to use this FlatBufferBuilder afterwards! +  /// @return A `FlatBuffer` that owns the buffer and its allocator and +  /// behaves similar to a `unique_ptr` with a deleter. +  FLATBUFFERS_ATTRIBUTE(deprecated("use Release() instead")) DetachedBuffer +  ReleaseBufferPointer() { +    Finished(); +    return buf_.release(); +  } + +  /// @brief Get the released DetachedBuffer. +  /// @return A `DetachedBuffer` that owns the buffer and its allocator. +  DetachedBuffer Release() { +    Finished(); +    return buf_.release(); +  } + +  /// @brief Get the released pointer to the serialized buffer. +  /// @param The size of the memory block containing +  /// the serialized `FlatBuffer`. +  /// @param The offset from the released pointer where the finished +  /// `FlatBuffer` starts. +  /// @return A raw pointer to the start of the memory block containing +  /// the serialized `FlatBuffer`. +  /// @remark If the allocator is owned, it gets deleted when the destructor is called.. +  uint8_t *ReleaseRaw(size_t &size, size_t &offset) { +    Finished(); +    return buf_.release_raw(size, offset); +  } + +  /// @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 +    // which hasn't been finished yet. Be sure to call +    // FlatBufferBuilder::Finish with your root table. +    // If you really need to access an unfinished buffer, call +    // GetCurrentBufferPointer instead. +    FLATBUFFERS_ASSERT(finished); +  } +  /// @endcond + +  /// @brief In order to save space, fields that are set to their default value +  /// don't get serialized into the buffer. +  /// @param[in] bool fd When set to `true`, always serializes default values that are set. +  /// Optional fields which are not set explicitly, will still not be serialized. +  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); } + +  void TrackMinAlign(size_t elem_size) { +    if (elem_size > minalign_) minalign_ = elem_size; +  } + +  void Align(size_t elem_size) { +    TrackMinAlign(elem_size); +    buf_.fill(PaddingBytes(buf_.size(), elem_size)); +  } + +  void PushFlatBuffer(const uint8_t *bytes, size_t size) { +    PushBytes(bytes, size); +    finished = true; +  } + +  void PushBytes(const uint8_t *bytes, size_t size) { buf_.push(bytes, size); } + +  void PopBytes(size_t amount) { buf_.pop(amount); } + +  template<typename T> void AssertScalarT() { +    // The code assumes power of 2 sizes and endian-swap-ability. +    static_assert(flatbuffers::is_scalar<T>::value, "T must be a scalar type"); +  } + +  // Write a single aligned scalar to the buffer +  template<typename T> uoffset_t PushElement(T element) { +    AssertScalarT<T>(); +    T litle_endian_element = EndianScalar(element); +    Align(sizeof(T)); +    buf_.push_small(litle_endian_element); +    return GetSize(); +  } + +  template<typename T> uoffset_t PushElement(Offset<T> off) { +    // Special case for offsets: see ReferTo below. +    return PushElement(ReferTo(off.o)); +  } + +  // When writing fields, we track where they are, so we can create correct +  // vtables later. +  void TrackField(voffset_t field, uoffset_t off) { +    FieldLoc fl = { off, field }; +    buf_.scratch_push_small(fl); +    num_field_loc++; +    max_voffset_ = (std::max)(max_voffset_, field); +  } + +  // Like PushElement, but additionally tracks the field this represents. +  template<typename T> void AddElement(voffset_t field, T e, T def) { +    // We don't serialize values equal to the default. +    if (IsTheSameAs(e, def) && !force_defaults_) return; +    auto off = PushElement(e); +    TrackField(field, off); +  } + +  template<typename T> void AddOffset(voffset_t field, Offset<T> off) { +    if (off.IsNull()) return;  // Don't store. +    AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0)); +  } + +  template<typename T> void AddStruct(voffset_t field, const T *structptr) { +    if (!structptr) return;  // Default, don't store. +    Align(AlignOf<T>()); +    buf_.push_small(*structptr); +    TrackField(field, GetSize()); +  } + +  void AddStructOffset(voffset_t field, uoffset_t off) { +    TrackField(field, off); +  } + +  // Offsets initially are relative to the end of the buffer (downwards). +  // This function converts them to be relative to the current location +  // in the buffer (when stored here), pointing upwards. +  uoffset_t ReferTo(uoffset_t off) { +    // Align to ensure GetSize() below is correct. +    Align(sizeof(uoffset_t)); +    // Offset must refer to something already in buffer. +    FLATBUFFERS_ASSERT(off && off <= GetSize()); +    return GetSize() - off + static_cast<uoffset_t>(sizeof(uoffset_t)); +  } + +  void NotNested() { +    // If you hit this, you're trying to construct a Table/Vector/String +    // during the construction of its parent table (between the MyTableBuilder +    // and table.Finish(). +    // Move the creation of these sub-objects to above the MyTableBuilder to +    // not get this assert. +    // Ignoring this assert may appear to work in simple cases, but the reason +    // it is here is that storing objects in-line may cause vtable offsets +    // to not fit anymore. It also leads to vtable duplication. +    FLATBUFFERS_ASSERT(!nested); +    // If you hit this, fields were added outside the scope of a table. +    FLATBUFFERS_ASSERT(!num_field_loc); +  } + +  // From generated code (or from the parser), we call StartTable/EndTable +  // with a sequence of AddElement calls in between. +  uoffset_t StartTable() { +    NotNested(); +    nested = true; +    return GetSize(); +  } + +  // This finishes one serialized object by generating the vtable if it's a +  // table, comparing it against existing vtables, and writing the +  // resulting vtable offset. +  uoffset_t EndTable(uoffset_t start) { +    // If you get this assert, a corresponding StartTable wasn't called. +    FLATBUFFERS_ASSERT(nested); +    // Write the vtable offset, which is the start of any Table. +    // We fill it's value later. +    auto vtableoffsetloc = PushElement<soffset_t>(0); +    // 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: +    // Include space for the last offset and ensure empty tables have a +    // minimum size. +    max_voffset_ = +        (std::max)(static_cast<voffset_t>(max_voffset_ + sizeof(voffset_t)), +                   FieldIndexToOffset(0)); +    buf_.fill_big(max_voffset_); +    auto table_object_size = vtableoffsetloc - start; +    // Vtable use 16bit offsets. +    FLATBUFFERS_ASSERT(table_object_size < 0x10000); +    WriteScalar<voffset_t>(buf_.data() + sizeof(voffset_t), +                           static_cast<voffset_t>(table_object_size)); +    WriteScalar<voffset_t>(buf_.data(), max_voffset_); +    // Write the offsets into the table +    for (auto it = buf_.scratch_end() - num_field_loc * sizeof(FieldLoc); +         it < buf_.scratch_end(); it += sizeof(FieldLoc)) { +      auto field_location = reinterpret_cast<FieldLoc *>(it); +      auto pos = static_cast<voffset_t>(vtableoffsetloc - field_location->off); +      // If this asserts, it means you've set a field twice. +      FLATBUFFERS_ASSERT( +          !ReadScalar<voffset_t>(buf_.data() + field_location->id)); +      WriteScalar<voffset_t>(buf_.data() + field_location->id, pos); +    } +    ClearOffsets(); +    auto vt1 = reinterpret_cast<voffset_t *>(buf_.data()); +    auto vt1_size = ReadScalar<voffset_t>(vt1); +    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. +    if (dedup_vtables_) { +      for (auto it = buf_.scratch_data(); it < buf_.scratch_end(); +           it += sizeof(uoffset_t)) { +        auto vt_offset_ptr = reinterpret_cast<uoffset_t *>(it); +        auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*vt_offset_ptr)); +        auto vt2_size = *vt2; +        if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size)) continue; +        vt_use = *vt_offset_ptr; +        buf_.pop(GetSize() - vtableoffsetloc); +        break; +      } +    } +    // If this is a new vtable, remember it. +    if (vt_use == GetSize()) { buf_.scratch_push_small(vt_use); } +    // Fill the vtable offset we created above. +    // The offset points from the beginning of the object to where the +    // vtable is stored. +    // Offsets default direction is downward in memory for future format +    // flexibility (storing all vtables at the start of the file). +    WriteScalar(buf_.data_at(vtableoffsetloc), +                static_cast<soffset_t>(vt_use) - +                    static_cast<soffset_t>(vtableoffsetloc)); + +    nested = false; +    return vtableoffsetloc; +  } + +  FLATBUFFERS_ATTRIBUTE(deprecated("call the version above instead")) +  uoffset_t EndTable(uoffset_t start, voffset_t /*numfields*/) { +    return EndTable(start); +  } + +  // This checks a required field has been set in a given table that has +  // just been constructed. +  template<typename T> void Required(Offset<T> table, voffset_t field); + +  uoffset_t StartStruct(size_t alignment) { +    Align(alignment); +    return GetSize(); +  } + +  uoffset_t EndStruct() { return GetSize(); } + +  void ClearOffsets() { +    buf_.scratch_pop(num_field_loc * sizeof(FieldLoc)); +    num_field_loc = 0; +    max_voffset_ = 0; +  } + +  // Aligns such that when "len" bytes are written, an object can be written +  // after it with "alignment" without padding. +  void PreAlign(size_t len, size_t alignment) { +    TrackMinAlign(alignment); +    buf_.fill(PaddingBytes(GetSize() + len, alignment)); +  } +  template<typename T> void PreAlign(size_t len) { +    AssertScalarT<T>(); +    PreAlign(len, sizeof(T)); +  } +  /// @endcond + +  /// @brief Store a string in the buffer, which can contain any binary data. +  /// @param[in] str A const char pointer to the data to be stored as a string. +  /// @param[in] len The number of bytes that should be stored from `str`. +  /// @return Returns the offset in the buffer where the string starts. +  Offset<String> CreateString(const char *str, size_t len) { +    NotNested(); +    PreAlign<uoffset_t>(len + 1);  // Always 0-terminated. +    buf_.fill(1); +    PushBytes(reinterpret_cast<const uint8_t *>(str), len); +    PushElement(static_cast<uoffset_t>(len)); +    return Offset<String>(GetSize()); +  } + +  /// @brief Store a string in the buffer, which is null-terminated. +  /// @param[in] str A const char pointer to a C-string to add to the buffer. +  /// @return Returns the offset in the buffer where the string starts. +  Offset<String> CreateString(const char *str) { +    return CreateString(str, strlen(str)); +  } + +  /// @brief Store a string in the buffer, which is null-terminated. +  /// @param[in] str A char pointer to a C-string to add to the buffer. +  /// @return Returns the offset in the buffer where the string starts. +  Offset<String> CreateString(char *str) { +    return CreateString(str, strlen(str)); +  } + +  /// @brief Store a string in the buffer, which can contain any binary data. +  /// @param[in] str A const reference to a std::string to store in the buffer. +  /// @return Returns the offset in the buffer where the string starts. +  Offset<String> CreateString(const std::string &str) { +    return CreateString(str.c_str(), str.length()); +  } + +  // clang-format off +  #ifdef FLATBUFFERS_HAS_STRING_VIEW +  /// @brief Store a string in the buffer, which can contain any binary data. +  /// @param[in] str A const string_view to copy in to the buffer. +  /// @return Returns the offset in the buffer where the string starts. +  Offset<String> CreateString(flatbuffers::string_view str) { +    return CreateString(str.data(), str.size()); +  } +  #endif // FLATBUFFERS_HAS_STRING_VIEW +  // clang-format on + +  /// @brief Store a string in the buffer, which can contain any binary data. +  /// @param[in] str A const pointer to a `String` struct to add to the buffer. +  /// @return Returns the offset in the buffer where the string starts +  Offset<String> CreateString(const String *str) { +    return str ? CreateString(str->c_str(), str->size()) : 0; +  } + +  /// @brief Store a string in the buffer, which can contain any binary data. +  /// @param[in] str A const reference to a std::string like type with support +  /// of T::c_str() and T::length() to store in the buffer. +  /// @return Returns the offset in the buffer where the string starts. +  template<typename T> Offset<String> CreateString(const T &str) { +    return CreateString(str.c_str(), str.length()); +  } + +  /// @brief Store a string in the buffer, which can contain any binary data. +  /// If a string with this exact contents has already been serialized before, +  /// instead simply returns the offset of the existing string. +  /// @param[in] str A const char pointer to the data to be stored as a string. +  /// @param[in] len The number of bytes that should be stored from `str`. +  /// @return Returns the offset in the buffer where the string starts. +  Offset<String> CreateSharedString(const char *str, size_t len) { +    if (!string_pool) +      string_pool = new StringOffsetMap(StringOffsetCompare(buf_)); +    auto size_before_string = buf_.size(); +    // Must first serialize the string, since the set is all offsets into +    // buffer. +    auto off = CreateString(str, len); +    auto it = string_pool->find(off); +    // If it exists we reuse existing serialized data! +    if (it != string_pool->end()) { +      // We can remove the string we serialized. +      buf_.pop(buf_.size() - size_before_string); +      return *it; +    } +    // Record this string for future use. +    string_pool->insert(off); +    return off; +  } + +  /// @brief Store a string in the buffer, which null-terminated. +  /// If a string with this exact contents has already been serialized before, +  /// instead simply returns the offset of the existing string. +  /// @param[in] str A const char pointer to a C-string to add to the buffer. +  /// @return Returns the offset in the buffer where the string starts. +  Offset<String> CreateSharedString(const char *str) { +    return CreateSharedString(str, strlen(str)); +  } + +  /// @brief Store a string in the buffer, which can contain any binary data. +  /// If a string with this exact contents has already been serialized before, +  /// instead simply returns the offset of the existing string. +  /// @param[in] str A const reference to a std::string to store in the buffer. +  /// @return Returns the offset in the buffer where the string starts. +  Offset<String> CreateSharedString(const std::string &str) { +    return CreateSharedString(str.c_str(), str.length()); +  } + +  /// @brief Store a string in the buffer, which can contain any binary data. +  /// If a string with this exact contents has already been serialized before, +  /// instead simply returns the offset of the existing string. +  /// @param[in] str A const pointer to a `String` struct to add to the buffer. +  /// @return Returns the offset in the buffer where the string starts +  Offset<String> CreateSharedString(const String *str) { +    return CreateSharedString(str->c_str(), str->size()); +  } + +  /// @cond FLATBUFFERS_INTERNAL +  uoffset_t EndVector(size_t len) { +    FLATBUFFERS_ASSERT(nested);  // Hit if no corresponding StartVector. +    nested = false; +    return PushElement(static_cast<uoffset_t>(len)); +  } + +  void StartVector(size_t len, size_t elemsize) { +    NotNested(); +    nested = true; +    PreAlign<uoffset_t>(len * elemsize); +    PreAlign(len * elemsize, elemsize);  // Just in case elemsize > uoffset_t. +  } + +  // Call this right before StartVector/CreateVector if you want to force the +  // alignment to be something different than what the element size would +  // normally dictate. +  // This is useful when storing a nested_flatbuffer in a vector of bytes, +  // or when storing SIMD floats, etc. +  void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment) { +    PreAlign(len * elemsize, alignment); +  } + +  // Similar to ForceVectorAlignment but for String fields. +  void ForceStringAlignment(size_t len, size_t alignment) { +    PreAlign((len + 1) * sizeof(char), alignment); +  } + +  /// @endcond + +  /// @brief Serialize an array into a FlatBuffer `vector`. +  /// @tparam T The data type of the array elements. +  /// @param[in] v A pointer to the array of type `T` to serialize into the +  /// buffer as a `vector`. +  /// @param[in] len The number of elements to serialize. +  /// @return Returns a typed `Offset` into the serialized data indicating +  /// where the vector is stored. +  template<typename T> Offset<Vector<T>> CreateVector(const T *v, size_t len) { +    // If this assert hits, you're specifying a template argument that is +    // causing the wrong overload to be selected, remove it. +    AssertScalarT<T>(); +    StartVector(len, sizeof(T)); +    // clang-format off +    #if FLATBUFFERS_LITTLEENDIAN +      PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T)); +    #else +      if (sizeof(T) == 1) { +        PushBytes(reinterpret_cast<const uint8_t *>(v), len); +      } else { +        for (auto i = len; i > 0; ) { +          PushElement(v[--i]); +        } +      } +    #endif +    // clang-format on +    return Offset<Vector<T>>(EndVector(len)); +  } + +  template<typename T> +  Offset<Vector<Offset<T>>> CreateVector(const Offset<T> *v, size_t len) { +    StartVector(len, sizeof(Offset<T>)); +    for (auto i = len; i > 0;) { PushElement(v[--i]); } +    return Offset<Vector<Offset<T>>>(EndVector(len)); +  } + +  /// @brief Serialize a `std::vector` into a FlatBuffer `vector`. +  /// @tparam T The data type of the `std::vector` elements. +  /// @param v A const reference to the `std::vector` to serialize into the +  /// buffer as a `vector`. +  /// @return Returns a typed `Offset` into the serialized data indicating +  /// where the vector is stored. +  template<typename T> Offset<Vector<T>> CreateVector(const std::vector<T> &v) { +    return CreateVector(data(v), v.size()); +  } + +  // vector<bool> may be implemented using a bit-set, so we can't access it as +  // an array. Instead, read elements manually. +  // Background: https://isocpp.org/blog/2012/11/on-vectorbool +  Offset<Vector<uint8_t>> CreateVector(const std::vector<bool> &v) { +    StartVector(v.size(), sizeof(uint8_t)); +    for (auto i = v.size(); i > 0;) { +      PushElement(static_cast<uint8_t>(v[--i])); +    } +    return Offset<Vector<uint8_t>>(EndVector(v.size())); +  } + +  // clang-format off +  #ifndef FLATBUFFERS_CPP98_STL +  /// @brief Serialize values returned by a function into a FlatBuffer `vector`. +  /// This is a convenience function that takes care of iteration for you. +  /// @tparam T The data type of the `std::vector` elements. +  /// @param f A function that takes the current iteration 0..vector_size-1 and +  /// returns any type that you can construct a FlatBuffers vector out of. +  /// @return Returns a typed `Offset` into the serialized data indicating +  /// where the vector is stored. +  template<typename T> Offset<Vector<T>> CreateVector(size_t vector_size, +      const std::function<T (size_t i)> &f) { +    std::vector<T> elems(vector_size); +    for (size_t i = 0; i < vector_size; i++) elems[i] = f(i); +    return CreateVector(elems); +  } +  #endif +  // clang-format on + +  /// @brief Serialize values returned by a function into a FlatBuffer `vector`. +  /// This is a convenience function that takes care of iteration for you. +  /// @tparam T The data type of the `std::vector` elements. +  /// @param f A function that takes the current iteration 0..vector_size-1, +  /// and the state parameter returning any type that you can construct a +  /// FlatBuffers vector out of. +  /// @param state State passed to f. +  /// @return Returns a typed `Offset` into the serialized data indicating +  /// where the vector is stored. +  template<typename T, typename F, typename S> +  Offset<Vector<T>> CreateVector(size_t vector_size, F f, S *state) { +    std::vector<T> elems(vector_size); +    for (size_t i = 0; i < vector_size; i++) elems[i] = f(i, state); +    return CreateVector(elems); +  } + +  /// @brief Serialize a `std::vector<std::string>` into a FlatBuffer `vector`. +  /// This is a convenience function for a common case. +  /// @param v A const reference to the `std::vector` to serialize into the +  /// buffer as a `vector`. +  /// @return Returns a typed `Offset` into the serialized data indicating +  /// where the vector is stored. +  Offset<Vector<Offset<String>>> CreateVectorOfStrings( +      const std::vector<std::string> &v) { +    std::vector<Offset<String>> offsets(v.size()); +    for (size_t i = 0; i < v.size(); i++) offsets[i] = CreateString(v[i]); +    return CreateVector(offsets); +  } + +  /// @brief Serialize an array of structs into a FlatBuffer `vector`. +  /// @tparam T The data type of the struct array elements. +  /// @param[in] v A pointer to the array of type `T` to serialize into the +  /// buffer as a `vector`. +  /// @param[in] len The number of elements to serialize. +  /// @return Returns a typed `Offset` into the serialized data indicating +  /// where the vector is stored. +  template<typename T> +  Offset<Vector<const T *>> CreateVectorOfStructs(const T *v, size_t len) { +    StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>()); +    PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len); +    return Offset<Vector<const T *>>(EndVector(len)); +  } + +  /// @brief Serialize an array of native structs into a FlatBuffer `vector`. +  /// @tparam T The data type of the struct array elements. +  /// @tparam S The data type of the native struct array elements. +  /// @param[in] v A pointer to the array of type `S` to serialize into the +  /// buffer as a `vector`. +  /// @param[in] len The number of elements to serialize. +  /// @return Returns a typed `Offset` into the serialized data indicating +  /// where the vector is stored. +  template<typename T, typename S> +  Offset<Vector<const T *>> CreateVectorOfNativeStructs(const S *v, +                                                        size_t len) { +    extern T Pack(const S &); +    typedef T (*Pack_t)(const S &); +    std::vector<T> vv(len); +    std::transform(v, v + len, vv.begin(), static_cast<Pack_t&>(Pack)); +    return CreateVectorOfStructs<T>(vv.data(), vv.size()); +  } + +  // clang-format off +  #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) { +    T* structs = StartVectorOfStructs<T>(vector_size); +    for (size_t i = 0; i < vector_size; i++) { +      filler(i, structs); +      structs++; +    } +    return EndVectorOfStructs<T>(vector_size); +  } +  #endif +  // clang-format on + +  /// @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, +  /// a pointer to the struct that must be filled and the state argument. +  /// @param[in] state Arbitrary state to pass to f. +  /// @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, typename F, typename S> +  Offset<Vector<const T *>> CreateVectorOfStructs(size_t vector_size, F f, +                                                  S *state) { +    T *structs = StartVectorOfStructs<T>(vector_size); +    for (size_t i = 0; i < vector_size; i++) { +      f(i, structs, state); +      structs++; +    } +    return EndVectorOfStructs<T>(vector_size); +  } + +  /// @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 +  /// serialize into the buffer as a `vector`. +  /// @return Returns a typed `Offset` into the serialized data indicating +  /// where the vector is stored. +  template<typename T, typename Alloc> +  Offset<Vector<const T *>> CreateVectorOfStructs( +      const std::vector<T, Alloc> &v) { +    return CreateVectorOfStructs(data(v), v.size()); +  } + +  /// @brief Serialize a `std::vector` of native structs into a FlatBuffer +  /// `vector`. +  /// @tparam T The data type of the `std::vector` struct elements. +  /// @tparam S The data type of the `std::vector` native struct elements. +  /// @param[in]] v A const reference to the `std::vector` of structs to +  /// serialize into the buffer as a `vector`. +  /// @return Returns a typed `Offset` into the serialized data indicating +  /// where the vector is stored. +  template<typename T, typename S> +  Offset<Vector<const T *>> CreateVectorOfNativeStructs( +      const std::vector<S> &v) { +    return CreateVectorOfNativeStructs<T, S>(data(v), v.size()); +  } + +  /// @cond FLATBUFFERS_INTERNAL +  template<typename T> struct StructKeyComparator { +    bool operator()(const T &a, const T &b) const { +      return a.KeyCompareLessThan(&b); +    } + +   private: +    StructKeyComparator &operator=(const StructKeyComparator &); +  }; +  /// @endcond + +  /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector` +  /// in sorted order. +  /// @tparam T The data type of the `std::vector` struct elements. +  /// @param[in]] v A const reference to the `std::vector` of structs to +  /// serialize into the buffer as a `vector`. +  /// @return Returns a typed `Offset` into the serialized data indicating +  /// where the vector is stored. +  template<typename T> +  Offset<Vector<const T *>> CreateVectorOfSortedStructs(std::vector<T> *v) { +    return CreateVectorOfSortedStructs(data(*v), v->size()); +  } + +  /// @brief Serialize a `std::vector` of native structs into a FlatBuffer +  /// `vector` in sorted order. +  /// @tparam T The data type of the `std::vector` struct elements. +  /// @tparam S The data type of the `std::vector` native struct elements. +  /// @param[in]] v A const reference to the `std::vector` of structs to +  /// serialize into the buffer as a `vector`. +  /// @return Returns a typed `Offset` into the serialized data indicating +  /// where the vector is stored. +  template<typename T, typename S> +  Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs( +      std::vector<S> *v) { +    return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size()); +  } + +  /// @brief Serialize an array of structs into a FlatBuffer `vector` in sorted +  /// order. +  /// @tparam T The data type of the struct array elements. +  /// @param[in] v A pointer to the array of type `T` to serialize into the +  /// buffer as a `vector`. +  /// @param[in] len The number of elements to serialize. +  /// @return Returns a typed `Offset` into the serialized data indicating +  /// where the vector is stored. +  template<typename T> +  Offset<Vector<const T *>> CreateVectorOfSortedStructs(T *v, size_t len) { +    std::sort(v, v + len, StructKeyComparator<T>()); +    return CreateVectorOfStructs(v, len); +  } + +  /// @brief Serialize an array of native structs into a FlatBuffer `vector` in +  /// sorted order. +  /// @tparam T The data type of the struct array elements. +  /// @tparam S The data type of the native struct array elements. +  /// @param[in] v A pointer to the array of type `S` to serialize into the +  /// buffer as a `vector`. +  /// @param[in] len The number of elements to serialize. +  /// @return Returns a typed `Offset` into the serialized data indicating +  /// where the vector is stored. +  template<typename T, typename S> +  Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(S *v, +                                                              size_t len) { +    extern T Pack(const S &); +    typedef T (*Pack_t)(const S &); +    std::vector<T> vv(len); +    std::transform(v, v + len, vv.begin(), static_cast<Pack_t&>(Pack)); +    return CreateVectorOfSortedStructs<T>(vv, len); +  } + +  /// @cond FLATBUFFERS_INTERNAL +  template<typename T> struct TableKeyComparator { +    TableKeyComparator(vector_downward &buf) : buf_(buf) {} +    bool operator()(const Offset<T> &a, const Offset<T> &b) const { +      auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o)); +      auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o)); +      return table_a->KeyCompareLessThan(table_b); +    } +    vector_downward &buf_; + +   private: +    TableKeyComparator &operator=(const TableKeyComparator &); +  }; +  /// @endcond + +  /// @brief Serialize an array of `table` offsets as a `vector` in the buffer +  /// in sorted order. +  /// @tparam T The data type that the offset refers to. +  /// @param[in] v An array of type `Offset<T>` that contains the `table` +  /// offsets to store in the buffer in sorted order. +  /// @param[in] len The number of elements to store in the `vector`. +  /// @return Returns a typed `Offset` into the serialized data indicating +  /// where the vector is stored. +  template<typename T> +  Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(Offset<T> *v, +                                                       size_t len) { +    std::sort(v, v + len, TableKeyComparator<T>(buf_)); +    return CreateVector(v, len); +  } + +  /// @brief Serialize an array of `table` offsets as a `vector` in the buffer +  /// in sorted order. +  /// @tparam T The data type that the offset refers to. +  /// @param[in] v An array of type `Offset<T>` that contains the `table` +  /// offsets to store in the buffer in sorted order. +  /// @return Returns a typed `Offset` into the serialized data indicating +  /// where the vector is stored. +  template<typename T> +  Offset<Vector<Offset<T>>> CreateVectorOfSortedTables( +      std::vector<Offset<T>> *v) { +    return CreateVectorOfSortedTables(data(*v), v->size()); +  } + +  /// @brief Specialized version of `CreateVector` for non-copying use cases. +  /// Write the data any time later to the returned buffer pointer `buf`. +  /// @param[in] len The number of elements to store in the `vector`. +  /// @param[in] elemsize The size of each element in the `vector`. +  /// @param[out] buf A pointer to a `uint8_t` pointer that can be +  /// written to at a later time to serialize the data into a `vector` +  /// in the buffer. +  uoffset_t CreateUninitializedVector(size_t len, size_t elemsize, +                                      uint8_t **buf) { +    NotNested(); +    StartVector(len, elemsize); +    buf_.make_space(len * elemsize); +    auto vec_start = GetSize(); +    auto vec_end = EndVector(len); +    *buf = buf_.data_at(vec_start); +    return vec_end; +  } + +  /// @brief Specialized version of `CreateVector` for non-copying use cases. +  /// Write the data any time later to the returned buffer pointer `buf`. +  /// @tparam T The data type of the data that will be stored in the buffer +  /// as a `vector`. +  /// @param[in] len The number of elements to store in the `vector`. +  /// @param[out] buf A pointer to a pointer of type `T` that can be +  /// written to at a later time to serialize the data into a `vector` +  /// in the buffer. +  template<typename T> +  Offset<Vector<T>> CreateUninitializedVector(size_t len, T **buf) { +    AssertScalarT<T>(); +    return CreateUninitializedVector(len, sizeof(T), +                                     reinterpret_cast<uint8_t **>(buf)); +  } + +  template<typename T> +  Offset<Vector<const T*>> CreateUninitializedVectorOfStructs(size_t len, T **buf) { +    return CreateUninitializedVector(len, sizeof(T), +                                     reinterpret_cast<uint8_t **>(buf)); +  } + + +  // @brief Create a vector of scalar type T given as input a vector of scalar +  // type U, useful with e.g. pre "enum class" enums, or any existing scalar +  // data of the wrong type. +  template<typename T, typename U> +  Offset<Vector<T>> CreateVectorScalarCast(const U *v, size_t len) { +    AssertScalarT<T>(); +    AssertScalarT<U>(); +    StartVector(len, sizeof(T)); +    for (auto i = len; i > 0;) { PushElement(static_cast<T>(v[--i])); } +    return Offset<Vector<T>>(EndVector(len)); +  } + +  /// @brief Write a struct by itself, typically to be part of a union. +  template<typename T> Offset<const T *> CreateStruct(const T &structobj) { +    NotNested(); +    Align(AlignOf<T>()); +    buf_.push_small(structobj); +    return Offset<const T *>(GetSize()); +  } + +  /// @brief The length of a FlatBuffer file header. +  static const size_t kFileIdentifierLength = 4; + +  /// @brief Finish serializing a buffer by writing the root offset. +  /// @param[in] file_identifier If a `file_identifier` is given, the buffer +  /// will be prefixed with a standard FlatBuffers file header. +  template<typename T> +  void Finish(Offset<T> root, const char *file_identifier = nullptr) { +    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); +  } + +  void SwapBufAllocator(FlatBufferBuilder &other) { +    buf_.swap_allocator(other.buf_); +  } + +protected: + +  // You shouldn't really be copying instances of this class. +  FlatBufferBuilder(const FlatBufferBuilder &); +  FlatBufferBuilder &operator=(const FlatBufferBuilder &); + +  void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) { +    NotNested(); +    buf_.clear_scratch(); +    // 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) { +      FLATBUFFERS_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; +  }; + +  vector_downward buf_; + +  // Accumulating offsets of table members while it is being built. +  // We store these in the scratch pad of buf_, after the vtable offsets. +  uoffset_t num_field_loc; +  // Track how much of the vtable is in use, so we can output the most compact +  // possible vtable. +  voffset_t max_voffset_; + +  // Ensure objects are not nested. +  bool nested; + +  // Ensure the buffer is finished before it is being accessed. +  bool finished; + +  size_t minalign_; + +  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 { +      auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o)); +      auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o)); +      return StringLessThan(stra->data(), stra->size(), +                            strb->data(), strb->size()); +    } +    const vector_downward *buf_; +  }; + +  // For use with CreateSharedString. Instantiated on first use only. +  typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap; +  StringOffsetMap *string_pool; + + private: +  // Allocates space for a vector of structures. +  // Must be completed with EndVectorOfStructs(). +  template<typename T> T *StartVectorOfStructs(size_t vector_size) { +    StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>()); +    return reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T))); +  } + +  // End the vector of structues in the flatbuffers. +  // Vector should have previously be started with StartVectorOfStructs(). +  template<typename T> +  Offset<Vector<const T *>> EndVectorOfStructs(size_t vector_size) { +    return Offset<Vector<const T *>>(EndVector(vector_size)); +  } +}; +/// @} + +/// @cond FLATBUFFERS_INTERNAL +// Helpers to get a typed pointer to the root object contained in the buffer. +template<typename T> T *GetMutableRoot(void *buf) { +  EndianCheck(); +  return reinterpret_cast<T *>( +      reinterpret_cast<uint8_t *>(buf) + +      EndianScalar(*reinterpret_cast<uoffset_t *>(buf))); +} + +template<typename T> const T *GetRoot(const void *buf) { +  return GetMutableRoot<T>(const_cast<void *>(buf)); +} + +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, Offset<T> offset) { +  return reinterpret_cast<T *>(fbb.GetCurrentBufferPointer() + fbb.GetSize() - +                               offset.o); +} + +template<typename T> +const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) { +  return GetMutableTemporaryPointer<T>(fbb, offset); +} + +/// @brief Get a pointer to the the file_identifier section of the buffer. +/// @return Returns a const char pointer to the start of the file_identifier +/// characters in the buffer.  The returned char * has length +/// 'flatbuffers::FlatBufferBuilder::kFileIdentifierLength'. +/// This function is UNDEFINED for FlatBuffers whose schema does not include +/// a file_identifier (likely points at padding or the start of a the root +/// vtable). +inline const char *GetBufferIdentifier(const void *buf, bool size_prefixed = false) { +  return reinterpret_cast<const char *>(buf) + +         ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t)); +} + +// Helper to see if the identifier in a buffer has the expected value. +inline bool BufferHasIdentifier(const void *buf, const char *identifier, bool size_prefixed = false) { +  return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier, +                 FlatBufferBuilder::kFileIdentifierLength) == 0; +} + +// Helper class to verify the integrity of a FlatBuffer +class Verifier FLATBUFFERS_FINAL_CLASS { + public: +  Verifier(const uint8_t *buf, size_t buf_len, uoffset_t _max_depth = 64, +           uoffset_t _max_tables = 1000000, bool _check_alignment = true) +      : buf_(buf), +        size_(buf_len), +        depth_(0), +        max_depth_(_max_depth), +        num_tables_(0), +        max_tables_(_max_tables), +        upper_bound_(0), +        check_alignment_(_check_alignment) +  { +    FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE); +  } + +  // Central location where any verification failures register. +  bool Check(bool ok) const { +    // clang-format off +    #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE +      FLATBUFFERS_ASSERT(ok); +    #endif +    #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE +      if (!ok) +        upper_bound_ = 0; +    #endif +    // clang-format on +    return ok; +  } + +  // Verify any range within the buffer. +  bool Verify(size_t elem, size_t elem_len) const { +    // clang-format off +    #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE +      auto upper_bound = elem + elem_len; +      if (upper_bound_ < upper_bound) +        upper_bound_ =  upper_bound; +    #endif +    // clang-format on +    return Check(elem_len < size_ && elem <= size_ - elem_len); +  } + +  template<typename T> bool VerifyAlignment(size_t elem) const { +    return (elem & (sizeof(T) - 1)) == 0 || !check_alignment_; +  } + +  // Verify a range indicated by sizeof(T). +  template<typename T> bool Verify(size_t elem) const { +    return VerifyAlignment<T>(elem) && Verify(elem, sizeof(T)); +  } + +  // Verify relative to a known-good base pointer. +  bool Verify(const uint8_t *base, voffset_t elem_off, size_t elem_len) const { +    return Verify(static_cast<size_t>(base - buf_) + elem_off, elem_len); +  } + +  template<typename T> bool Verify(const uint8_t *base, voffset_t elem_off) +      const { +    return Verify(static_cast<size_t>(base - buf_) + elem_off, sizeof(T)); +  } + +  // Verify a pointer (may be NULL) of a table type. +  template<typename T> bool VerifyTable(const T *table) { +    return !table || table->Verify(*this); +  } + +  // Verify a pointer (may be NULL) of any vector type. +  template<typename T> bool VerifyVector(const Vector<T> *vec) const { +    return !vec || VerifyVectorOrString(reinterpret_cast<const uint8_t *>(vec), +                                        sizeof(T)); +  } + +  // Verify a pointer (may be NULL) of a vector to struct. +  template<typename T> bool VerifyVector(const Vector<const T *> *vec) const { +    return VerifyVector(reinterpret_cast<const Vector<T> *>(vec)); +  } + +  // Verify a pointer (may be NULL) to string. +  bool VerifyString(const String *str) const { +    size_t end; +    return !str || +           (VerifyVectorOrString(reinterpret_cast<const uint8_t *>(str), +                                 1, &end) && +            Verify(end, 1) &&      // Must have terminator +            Check(buf_[end] == '\0'));  // Terminating byte must be 0. +  } + +  // Common code between vectors and strings. +  bool VerifyVectorOrString(const uint8_t *vec, size_t elem_size, +                    size_t *end = nullptr) const { +    auto veco = static_cast<size_t>(vec - buf_); +    // Check we can read the size field. +    if (!Verify<uoffset_t>(veco)) return false; +    // Check the whole array. If this is a string, the byte past the array +    // must be 0. +    auto size = ReadScalar<uoffset_t>(vec); +    auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size; +    if (!Check(size < max_elems)) +      return false;  // Protect against byte_size overflowing. +    auto byte_size = sizeof(size) + elem_size * size; +    if (end) *end = veco + byte_size; +    return Verify(veco, byte_size); +  } + +  // Special case for string contents, after the above has been called. +  bool VerifyVectorOfStrings(const Vector<Offset<String>> *vec) const { +    if (vec) { +      for (uoffset_t i = 0; i < vec->size(); i++) { +        if (!VerifyString(vec->Get(i))) return false; +      } +    } +    return true; +  } + +  // Special case for table contents, after the above has been called. +  template<typename T> bool VerifyVectorOfTables(const Vector<Offset<T>> *vec) { +    if (vec) { +      for (uoffset_t i = 0; i < vec->size(); i++) { +        if (!vec->Get(i)->Verify(*this)) return false; +      } +    } +    return true; +  } + +  bool VerifyTableStart(const uint8_t *table) { +    // Check the vtable offset. +    auto tableo = static_cast<size_t>(table - buf_); +    if (!Verify<soffset_t>(tableo)) return false; +    // This offset may be signed, but doing the substraction unsigned always +    // gives the result we want. +    auto vtableo = tableo - static_cast<size_t>(ReadScalar<soffset_t>(table)); +    // Check the vtable size field, then check vtable fits in its entirety. +    return VerifyComplexity() && Verify<voffset_t>(vtableo) && +           VerifyAlignment<voffset_t>(ReadScalar<voffset_t>(buf_ + vtableo)) && +           Verify(vtableo, ReadScalar<voffset_t>(buf_ + vtableo)); +  } + +  template<typename T> +  bool VerifyBufferFromStart(const char *identifier, size_t start) { +    if (identifier && +        (size_ < 2 * sizeof(flatbuffers::uoffset_t) || +         !BufferHasIdentifier(buf_ + start, identifier))) { +      return false; +    } + +    // Call T::Verify, which must be in the generated code for this type. +    auto o = VerifyOffset(start); +    return o && reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this) +    // clang-format off +    #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE +           && GetComputedSize() +    #endif +        ; +    // clang-format on +  } + +  // Verify this whole buffer, starting with root type T. +  template<typename T> bool VerifyBuffer() { return VerifyBuffer<T>(nullptr); } + +  template<typename T> bool VerifyBuffer(const char *identifier) { +    return VerifyBufferFromStart<T>(identifier, 0); +  } + +  template<typename T> bool VerifySizePrefixedBuffer(const char *identifier) { +    return Verify<uoffset_t>(0U) && +           ReadScalar<uoffset_t>(buf_) == size_ - sizeof(uoffset_t) && +           VerifyBufferFromStart<T>(identifier, sizeof(uoffset_t)); +  } + +  uoffset_t VerifyOffset(size_t start) const { +    if (!Verify<uoffset_t>(start)) return 0; +    auto o = ReadScalar<uoffset_t>(buf_ + start); +    // May not point to itself. +    if (!Check(o != 0)) return 0; +    // Can't wrap around / buffers are max 2GB. +    if (!Check(static_cast<soffset_t>(o) >= 0)) return 0; +    // Must be inside the buffer to create a pointer from it (pointer outside +    // buffer is UB). +    if (!Verify(start + o, 1)) return 0; +    return o; +  } + +  uoffset_t VerifyOffset(const uint8_t *base, voffset_t start) const { +    return VerifyOffset(static_cast<size_t>(base - buf_) + start); +  } + +  // 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 +  // with EndTable(). +  bool VerifyComplexity() { +    depth_++; +    num_tables_++; +    return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_); +  } + +  // Called at the end of a table to pop the depth count. +  bool EndTable() { +    depth_--; +    return true; +  } + +  // Returns the message size in bytes +  size_t GetComputedSize() const { +    // clang-format off +    #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE +      uintptr_t size = upper_bound_; +      // Align the size to uoffset_t +      size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1); +      return (size > size_) ?  0 : size; +    #else +      // Must turn on FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE for this to work. +      (void)upper_bound_; +      FLATBUFFERS_ASSERT(false); +      return 0; +    #endif +    // clang-format on +  } + + private: +  const uint8_t *buf_; +  size_t size_; +  uoffset_t depth_; +  uoffset_t max_depth_; +  uoffset_t num_tables_; +  uoffset_t max_tables_; +  mutable size_t upper_bound_; +  bool check_alignment_; +}; + +// Convenient way to bundle a buffer and its length, to pass it around +// typed by its root. +// A BufferRef does not own its buffer. +struct BufferRefBase {};  // for std::is_base_of +template<typename T> struct BufferRef : BufferRefBase { +  BufferRef() : buf(nullptr), len(0), must_free(false) {} +  BufferRef(uint8_t *_buf, uoffset_t _len) +      : buf(_buf), len(_len), must_free(false) {} + +  ~BufferRef() { +    if (must_free) free(buf); +  } + +  const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); } + +  bool Verify() { +    Verifier verifier(buf, len); +    return verifier.VerifyBuffer<T>(nullptr); +  } + +  uint8_t *buf; +  uoffset_t len; +  bool must_free; +}; + +// "structs" are flat structures that do not have an offset table, thus +// always have all members present and do not support forwards/backwards +// compatible extensions. + +class Struct FLATBUFFERS_FINAL_CLASS { + public: +  template<typename T> T GetField(uoffset_t o) const { +    return ReadScalar<T>(&data_[o]); +  } + +  template<typename T> T GetStruct(uoffset_t o) const { +    return reinterpret_cast<T>(&data_[o]); +  } + +  const uint8_t *GetAddressOf(uoffset_t o) const { return &data_[o]; } +  uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; } + + private: +  uint8_t data_[1]; +}; + +// "tables" use an offset table (possibly shared) that allows fields to be +// 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 = 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 +    // data, so it's the same as if the offset was 0 (not present). +    return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0; +  } + +  template<typename T> T GetField(voffset_t field, T defaultval) const { +    auto field_offset = GetOptionalFieldOffset(field); +    return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval; +  } + +  template<typename P> P GetPointer(voffset_t field) { +    auto field_offset = GetOptionalFieldOffset(field); +    auto p = data_ + field_offset; +    return field_offset ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p)) +                        : nullptr; +  } +  template<typename P> P GetPointer(voffset_t field) const { +    return const_cast<Table *>(this)->GetPointer<P>(field); +  } + +  template<typename P> P GetStruct(voffset_t field) const { +    auto field_offset = GetOptionalFieldOffset(field); +    auto p = const_cast<uint8_t *>(data_ + field_offset); +    return field_offset ? reinterpret_cast<P>(p) : nullptr; +  } + +  template<typename T> bool SetField(voffset_t field, T val, T def) { +    auto field_offset = GetOptionalFieldOffset(field); +    if (!field_offset) return IsTheSameAs(val, def); +    WriteScalar(data_ + field_offset, val); +    return true; +  } + +  bool SetPointer(voffset_t field, const uint8_t *val) { +    auto field_offset = GetOptionalFieldOffset(field); +    if (!field_offset) return false; +    WriteScalar(data_ + field_offset, +                static_cast<uoffset_t>(val - (data_ + field_offset))); +    return true; +  } + +  uint8_t *GetAddressOf(voffset_t field) { +    auto field_offset = GetOptionalFieldOffset(field); +    return field_offset ? data_ + field_offset : nullptr; +  } +  const uint8_t *GetAddressOf(voffset_t field) const { +    return const_cast<Table *>(this)->GetAddressOf(field); +  } + +  bool CheckField(voffset_t field) const { +    return GetOptionalFieldOffset(field) != 0; +  } + +  // Verify the vtable of this table. +  // Call this once per table, followed by VerifyField once per field. +  bool VerifyTableStart(Verifier &verifier) const { +    return verifier.VerifyTableStart(data_); +  } + +  // Verify a particular field. +  template<typename T> +  bool VerifyField(const Verifier &verifier, voffset_t field) const { +    // Calling GetOptionalFieldOffset should be safe now thanks to +    // VerifyTable(). +    auto field_offset = GetOptionalFieldOffset(field); +    // Check the actual field. +    return !field_offset || verifier.Verify<T>(data_, field_offset); +  } + +  // VerifyField for required fields. +  template<typename T> +  bool VerifyFieldRequired(const Verifier &verifier, voffset_t field) const { +    auto field_offset = GetOptionalFieldOffset(field); +    return verifier.Check(field_offset != 0) && +           verifier.Verify<T>(data_, field_offset); +  } + +  // Versions for offsets. +  bool VerifyOffset(const Verifier &verifier, voffset_t field) const { +    auto field_offset = GetOptionalFieldOffset(field); +    return !field_offset || verifier.VerifyOffset(data_, field_offset); +  } + +  bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const { +    auto field_offset = GetOptionalFieldOffset(field); +    return verifier.Check(field_offset != 0) && +           verifier.VerifyOffset(data_, field_offset); +  } + + private: +  // private constructor & copy constructor: you obtain instances of this +  // class by pointing to existing data only +  Table(); +  Table(const Table &other); + +  uint8_t data_[1]; +}; + +template<typename T> void FlatBufferBuilder::Required(Offset<T> table, +                                                      voffset_t field) { +  auto table_ptr = reinterpret_cast<const Table *>(buf_.data_at(table.o)); +  bool ok = table_ptr->GetOptionalFieldOffset(field) != 0; +  // If this fails, the caller will show what field needs to be set. +  FLATBUFFERS_ASSERT(ok); +  (void)ok; +} + +/// @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. +  FLATBUFFERS_ASSERT(false); +  return nullptr; +} + +/// @brief This return the prefixed size of a FlatBuffer. +inline uoffset_t GetPrefixedSize(const uint8_t* buf){ return ReadScalar<uoffset_t>(buf); } + +// 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; +// clang-format off +#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 +// clang-format on + +// 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, +// this is not typechecked to be a subclass of Table, so beware! +// Note: this function will return false for fields equal to the default +// value, since they're not stored in the buffer (unless force_defaults was +// used). +template<typename T> +bool IsFieldPresent(const T *table, typename T::FlatBuffersVTableOffset field) { +  // Cast, since Table is a private baseclass of any table types. +  return reinterpret_cast<const Table *>(table)->CheckField( +      static_cast<voffset_t>(field)); +} + +// Utility function for reverse lookups on the EnumNames*() functions +// (in the generated C++ code) +// names must be NULL terminated. +inline int LookupEnum(const char **names, const char *name) { +  for (const char **p = names; *p; p++) +    if (!strcmp(*p, name)) return static_cast<int>(p - names); +  return -1; +} + +// These macros allow us to layout a struct with a guarantee that they'll end +// up looking the same on different compilers and platforms. +// It does this by disallowing the compiler to do any padding, and then +// does padding itself by inserting extra padding fields that make every +// element aligned to its own size. +// Additionally, it manually sets the alignment of the struct as a whole, +// which is typically its largest element, or a custom size set in the schema +// by the force_align attribute. +// These are used in the generated code only. + +// clang-format off +#if defined(_MSC_VER) +  #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \ +    __pragma(pack(1)) \ +    struct __declspec(align(alignment)) +  #define FLATBUFFERS_STRUCT_END(name, size) \ +    __pragma(pack()) \ +    static_assert(sizeof(name) == size, "compiler breaks packing rules") +#elif defined(__GNUC__) || defined(__clang__) +  #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \ +    _Pragma("pack(1)") \ +    struct __attribute__((aligned(alignment))) +  #define FLATBUFFERS_STRUCT_END(name, size) \ +    _Pragma("pack()") \ +    static_assert(sizeof(name) == size, "compiler breaks packing rules") +#else +  #error Unknown compiler, please define structure alignment macros +#endif +// clang-format on + +// Minimal reflection via code generation. +// Besides full-fat reflection (see reflection.h) and parsing/printing by +// loading schemas (see idl.h), we can also have code generation for mimimal +// reflection data which allows pretty-printing and other uses without needing +// a schema or a parser. +// Generate code with --reflect-types (types only) or --reflect-names (names +// also) to enable. +// See minireflect.h for utilities using this functionality. + +// These types are organized slightly differently as the ones in idl.h. +enum SequenceType { ST_TABLE, ST_STRUCT, ST_UNION, ST_ENUM }; + +// Scalars have the same order as in idl.h +// clang-format off +#define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \ +  ET(ET_UTYPE) \ +  ET(ET_BOOL) \ +  ET(ET_CHAR) \ +  ET(ET_UCHAR) \ +  ET(ET_SHORT) \ +  ET(ET_USHORT) \ +  ET(ET_INT) \ +  ET(ET_UINT) \ +  ET(ET_LONG) \ +  ET(ET_ULONG) \ +  ET(ET_FLOAT) \ +  ET(ET_DOUBLE) \ +  ET(ET_STRING) \ +  ET(ET_SEQUENCE)  // See SequenceType. + +enum ElementaryType { +  #define FLATBUFFERS_ET(E) E, +    FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET) +  #undef FLATBUFFERS_ET +}; + +inline const char * const *ElementaryTypeNames() { +  static const char * const names[] = { +    #define FLATBUFFERS_ET(E) #E, +      FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET) +    #undef FLATBUFFERS_ET +  }; +  return names; +} +// clang-format on + +// Basic type info cost just 16bits per field! +struct TypeCode { +  uint16_t base_type : 4;  // ElementaryType +  uint16_t is_vector : 1; +  int16_t sequence_ref : 11;  // Index into type_refs below, or -1 for none. +}; + +static_assert(sizeof(TypeCode) == 2, "TypeCode"); + +struct TypeTable; + +// Signature of the static method present in each type. +typedef const TypeTable *(*TypeFunction)(); + +struct TypeTable { +  SequenceType st; +  size_t num_elems;  // of type_codes, values, names (but not type_refs). +  const TypeCode *type_codes;  // num_elems count +  const TypeFunction *type_refs;  // less than num_elems entries (see TypeCode). +  const int64_t *values;  // Only set for non-consecutive enum/union or structs. +  const char * const *names;     // Only set if compiled with --reflect-names. +}; + +// String which identifies the current version of FlatBuffers. +// flatbuffer_version_string is used by Google developers to identify which +// applications uploaded to Google Play are using this library.  This allows +// the development team at Google to determine the popularity of the library. +// How it works: Applications that are uploaded to the Google Play Store are +// scanned for this version string.  We track which applications are using it +// to measure popularity.  You are free to remove it (of course) but we would +// appreciate if you left it in. + +// Weak linkage is culled by VS & doesn't work on cygwin. +// clang-format off +#if !defined(_WIN32) && !defined(__CYGWIN__) + +extern volatile __attribute__((weak)) const char *flatbuffer_version_string; +volatile __attribute__((weak)) const char *flatbuffer_version_string = +  "FlatBuffers " +  FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "." +  FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "." +  FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION); + +#endif  // !defined(_WIN32) && !defined(__CYGWIN__) + +#define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\ +    inline E operator | (E lhs, E rhs){\ +        return E(T(lhs) | T(rhs));\ +    }\ +    inline E operator & (E lhs, E rhs){\ +        return E(T(lhs) & T(rhs));\ +    }\ +    inline E operator ^ (E lhs, E rhs){\ +        return E(T(lhs) ^ T(rhs));\ +    }\ +    inline E operator ~ (E lhs){\ +        return E(~T(lhs));\ +    }\ +    inline E operator |= (E &lhs, E rhs){\ +        lhs = lhs | rhs;\ +        return lhs;\ +    }\ +    inline E operator &= (E &lhs, E rhs){\ +        lhs = lhs & rhs;\ +        return lhs;\ +    }\ +    inline E operator ^= (E &lhs, E rhs){\ +        lhs = lhs ^ rhs;\ +        return lhs;\ +    }\ +    inline bool operator !(E rhs) \ +    {\ +        return !bool(T(rhs)); \ +    } +/// @endcond +}  // namespace flatbuffers + +// clang-format on + +#endif  // FLATBUFFERS_H_ diff --git a/host/lib/deps/flatbuffers/include/flatbuffers/flatc.h b/host/lib/deps/flatbuffers/include/flatbuffers/flatc.h new file mode 100644 index 000000000..f2765d239 --- /dev/null +++ b/host/lib/deps/flatbuffers/include/flatbuffers/flatc.h @@ -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 <functional> +#include <limits> +#include <string> +#include "flatbuffers/flatbuffers.h" +#include "flatbuffers/idl.h" +#include "flatbuffers/util.h" + +#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; +    bool schema_only; +    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 ¶ms) : 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 LoadBinarySchema(Parser &parser, const std::string &filename, +                        const std::string &contents); + +  void Warn(const std::string &warn, bool show_exe_name = true) const; + +  void Error(const std::string &err, bool usage = true, +             bool show_exe_name = true) const; + +  InitParams params_; +}; + +}  // namespace flatbuffers + +#endif  // FLATC_H_ diff --git a/host/lib/deps/flatbuffers/include/flatbuffers/flexbuffers.h b/host/lib/deps/flatbuffers/include/flatbuffers/flexbuffers.h new file mode 100644 index 000000000..7cba5b75b --- /dev/null +++ b/host/lib/deps/flatbuffers/include/flatbuffers/flexbuffers.h @@ -0,0 +1,1538 @@ +/* + * Copyright 2017 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_FLEXBUFFERS_H_ +#define FLATBUFFERS_FLEXBUFFERS_H_ + +#include <map> +// Used to select STL variant. +#include "flatbuffers/base.h" +// We use the basic binary writing functions from the regular FlatBuffers. +#include "flatbuffers/util.h" + +#ifdef _MSC_VER +#  include <intrin.h> +#endif + +#if defined(_MSC_VER) +#  pragma warning(push) +#  pragma warning(disable : 4127)  // C4127: conditional expression is constant +#endif + +namespace flexbuffers { + +class Reference; +class Map; + +// These are used in the lower 2 bits of a type field to determine the size of +// the elements (and or size field) of the item pointed to (e.g. vector). +enum BitWidth { +  BIT_WIDTH_8 = 0, +  BIT_WIDTH_16 = 1, +  BIT_WIDTH_32 = 2, +  BIT_WIDTH_64 = 3, +}; + +// These are used as the upper 6 bits of a type field to indicate the actual +// type. +enum Type { +  FBT_NULL = 0, +  FBT_INT = 1, +  FBT_UINT = 2, +  FBT_FLOAT = 3, +  // Types above stored inline, types below store an offset. +  FBT_KEY = 4, +  FBT_STRING = 5, +  FBT_INDIRECT_INT = 6, +  FBT_INDIRECT_UINT = 7, +  FBT_INDIRECT_FLOAT = 8, +  FBT_MAP = 9, +  FBT_VECTOR = 10,      // Untyped. +  FBT_VECTOR_INT = 11,  // Typed any size (stores no type table). +  FBT_VECTOR_UINT = 12, +  FBT_VECTOR_FLOAT = 13, +  FBT_VECTOR_KEY = 14, +  FBT_VECTOR_STRING = 15, +  FBT_VECTOR_INT2 = 16,  // Typed tuple (no type table, no size field). +  FBT_VECTOR_UINT2 = 17, +  FBT_VECTOR_FLOAT2 = 18, +  FBT_VECTOR_INT3 = 19,  // Typed triple (no type table, no size field). +  FBT_VECTOR_UINT3 = 20, +  FBT_VECTOR_FLOAT3 = 21, +  FBT_VECTOR_INT4 = 22,  // Typed quad (no type table, no size field). +  FBT_VECTOR_UINT4 = 23, +  FBT_VECTOR_FLOAT4 = 24, +  FBT_BLOB = 25, +  FBT_BOOL = 26, +  FBT_VECTOR_BOOL = +      36,  // To Allow the same type of conversion of type to vector type +}; + +inline bool IsInline(Type t) { return t <= FBT_FLOAT || t == FBT_BOOL; } + +inline bool IsTypedVectorElementType(Type t) { +  return (t >= FBT_INT && t <= FBT_STRING) || t == FBT_BOOL; +} + +inline bool IsTypedVector(Type t) { +  return (t >= FBT_VECTOR_INT && t <= FBT_VECTOR_STRING) || +         t == FBT_VECTOR_BOOL; +} + +inline bool IsFixedTypedVector(Type t) { +  return t >= FBT_VECTOR_INT2 && t <= FBT_VECTOR_FLOAT4; +} + +inline Type ToTypedVector(Type t, size_t fixed_len = 0) { +  FLATBUFFERS_ASSERT(IsTypedVectorElementType(t)); +  switch (fixed_len) { +    case 0: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT); +    case 2: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT2); +    case 3: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT3); +    case 4: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT4); +    default: FLATBUFFERS_ASSERT(0); return FBT_NULL; +  } +} + +inline Type ToTypedVectorElementType(Type t) { +  FLATBUFFERS_ASSERT(IsTypedVector(t)); +  return static_cast<Type>(t - FBT_VECTOR_INT + FBT_INT); +} + +inline Type ToFixedTypedVectorElementType(Type t, uint8_t *len) { +  FLATBUFFERS_ASSERT(IsFixedTypedVector(t)); +  auto fixed_type = t - FBT_VECTOR_INT2; +  *len = static_cast<uint8_t>(fixed_type / 3 + +                              2);  // 3 types each, starting from length 2. +  return static_cast<Type>(fixed_type % 3 + FBT_INT); +} + +// TODO: implement proper support for 8/16bit floats, or decide not to +// support them. +typedef int16_t half; +typedef int8_t quarter; + +// TODO: can we do this without conditionals using intrinsics or inline asm +// on some platforms? Given branch prediction the method below should be +// decently quick, but it is the most frequently executed function. +// We could do an (unaligned) 64-bit read if we ifdef out the platforms for +// which that doesn't work (or where we'd read into un-owned memory). +template<typename R, typename T1, typename T2, typename T4, typename T8> +R ReadSizedScalar(const uint8_t *data, uint8_t byte_width) { +  return byte_width < 4 +             ? (byte_width < 2 +                    ? static_cast<R>(flatbuffers::ReadScalar<T1>(data)) +                    : static_cast<R>(flatbuffers::ReadScalar<T2>(data))) +             : (byte_width < 8 +                    ? static_cast<R>(flatbuffers::ReadScalar<T4>(data)) +                    : static_cast<R>(flatbuffers::ReadScalar<T8>(data))); +} + +inline int64_t ReadInt64(const uint8_t *data, uint8_t byte_width) { +  return ReadSizedScalar<int64_t, int8_t, int16_t, int32_t, int64_t>( +      data, byte_width); +} + +inline uint64_t ReadUInt64(const uint8_t *data, uint8_t byte_width) { +  // This is the "hottest" function (all offset lookups use this), so worth +  // optimizing if possible. +  // TODO: GCC apparently replaces memcpy by a rep movsb, but only if count is a +  // constant, which here it isn't. Test if memcpy is still faster than +  // the conditionals in ReadSizedScalar. Can also use inline asm. +  // clang-format off +  #if defined(_MSC_VER) && (defined(_M_X64) || defined _M_IX86) +    uint64_t u = 0; +    __movsb(reinterpret_cast<uint8_t *>(&u), +            reinterpret_cast<const uint8_t *>(data), byte_width); +    return flatbuffers::EndianScalar(u); +  #else +    return ReadSizedScalar<uint64_t, uint8_t, uint16_t, uint32_t, uint64_t>( +             data, byte_width); +  #endif +  // clang-format on +} + +inline double ReadDouble(const uint8_t *data, uint8_t byte_width) { +  return ReadSizedScalar<double, quarter, half, float, double>(data, +                                                               byte_width); +} + +inline const uint8_t *Indirect(const uint8_t *offset, uint8_t byte_width) { +  return offset - ReadUInt64(offset, byte_width); +} + +template<typename T> const uint8_t *Indirect(const uint8_t *offset) { +  return offset - flatbuffers::ReadScalar<T>(offset); +} + +inline BitWidth WidthU(uint64_t u) { +#define FLATBUFFERS_GET_FIELD_BIT_WIDTH(value, width)                   \ +  {                                                                     \ +    if (!((u) & ~((1ULL << (width)) - 1ULL))) return BIT_WIDTH_##width; \ +  } +  FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 8); +  FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 16); +  FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 32); +#undef FLATBUFFERS_GET_FIELD_BIT_WIDTH +  return BIT_WIDTH_64; +} + +inline BitWidth WidthI(int64_t i) { +  auto u = static_cast<uint64_t>(i) << 1; +  return WidthU(i >= 0 ? u : ~u); +} + +inline BitWidth WidthF(double f) { +  return static_cast<double>(static_cast<float>(f)) == f ? BIT_WIDTH_32 +                                                         : BIT_WIDTH_64; +} + +// Base class of all types below. +// Points into the data buffer and allows access to one type. +class Object { + public: +  Object(const uint8_t *data, uint8_t byte_width) +      : data_(data), byte_width_(byte_width) {} + + protected: +  const uint8_t *data_; +  uint8_t byte_width_; +}; + +// Stores size in `byte_width_` bytes before data_ pointer. +class Sized : public Object { + public: +  Sized(const uint8_t *data, uint8_t byte_width) : Object(data, byte_width) {} +  size_t size() const { +    return static_cast<size_t>(ReadUInt64(data_ - byte_width_, byte_width_)); +  } +}; + +class String : public Sized { + public: +  String(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {} + +  size_t length() const { return size(); } +  const char *c_str() const { return reinterpret_cast<const char *>(data_); } +  std::string str() const { return std::string(c_str(), length()); } + +  static String EmptyString() { +    static const uint8_t empty_string[] = { 0 /*len*/, 0 /*terminator*/ }; +    return String(empty_string + 1, 1); +  } +  bool IsTheEmptyString() const { return data_ == EmptyString().data_; } +}; + +class Blob : public Sized { + public: +  Blob(const uint8_t *data_buf, uint8_t byte_width) +      : Sized(data_buf, byte_width) {} + +  static Blob EmptyBlob() { +    static const uint8_t empty_blob[] = { 0 /*len*/ }; +    return Blob(empty_blob + 1, 1); +  } +  bool IsTheEmptyBlob() const { return data_ == EmptyBlob().data_; } +  const uint8_t *data() const { return data_; } +}; + +class Vector : public Sized { + public: +  Vector(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {} + +  Reference operator[](size_t i) const; + +  static Vector EmptyVector() { +    static const uint8_t empty_vector[] = { 0 /*len*/ }; +    return Vector(empty_vector + 1, 1); +  } +  bool IsTheEmptyVector() const { return data_ == EmptyVector().data_; } +}; + +class TypedVector : public Sized { + public: +  TypedVector(const uint8_t *data, uint8_t byte_width, Type element_type) +      : Sized(data, byte_width), type_(element_type) {} + +  Reference operator[](size_t i) const; + +  static TypedVector EmptyTypedVector() { +    static const uint8_t empty_typed_vector[] = { 0 /*len*/ }; +    return TypedVector(empty_typed_vector + 1, 1, FBT_INT); +  } +  bool IsTheEmptyVector() const { +    return data_ == TypedVector::EmptyTypedVector().data_; +  } + +  Type ElementType() { return type_; } + + private: +  Type type_; + +  friend Map; +}; + +class FixedTypedVector : public Object { + public: +  FixedTypedVector(const uint8_t *data, uint8_t byte_width, Type element_type, +                   uint8_t len) +      : Object(data, byte_width), type_(element_type), len_(len) {} + +  Reference operator[](size_t i) const; + +  static FixedTypedVector EmptyFixedTypedVector() { +    static const uint8_t fixed_empty_vector[] = { 0 /* unused */ }; +    return FixedTypedVector(fixed_empty_vector, 1, FBT_INT, 0); +  } +  bool IsTheEmptyFixedTypedVector() const { +    return data_ == FixedTypedVector::EmptyFixedTypedVector().data_; +  } + +  Type ElementType() { return type_; } +  uint8_t size() { return len_; } + + private: +  Type type_; +  uint8_t len_; +}; + +class Map : public Vector { + public: +  Map(const uint8_t *data, uint8_t byte_width) : Vector(data, byte_width) {} + +  Reference operator[](const char *key) const; +  Reference operator[](const std::string &key) const; + +  Vector Values() const { return Vector(data_, byte_width_); } + +  TypedVector Keys() const { +    const size_t num_prefixed_fields = 3; +    auto keys_offset = data_ - byte_width_ * num_prefixed_fields; +    return TypedVector(Indirect(keys_offset, byte_width_), +                       static_cast<uint8_t>( +                           ReadUInt64(keys_offset + byte_width_, byte_width_)), +                       FBT_KEY); +  } + +  static Map EmptyMap() { +    static const uint8_t empty_map[] = { +      0 /*keys_len*/, 0 /*keys_offset*/, 1 /*keys_width*/, 0 /*len*/ +    }; +    return Map(empty_map + 4, 1); +  } + +  bool IsTheEmptyMap() const { return data_ == EmptyMap().data_; } +}; + +template<typename T> +void AppendToString(std::string &s, T &&v, bool keys_quoted) { +    s += "[ "; +    for (size_t i = 0; i < v.size(); i++) { +      if (i) s += ", "; +      v[i].ToString(true, keys_quoted, s); +    } +    s += " ]"; +} + +class Reference { + public: +  Reference(const uint8_t *data, uint8_t parent_width, uint8_t byte_width, +            Type type) +      : data_(data), +        parent_width_(parent_width), +        byte_width_(byte_width), +        type_(type) {} + +  Reference(const uint8_t *data, uint8_t parent_width, uint8_t packed_type) +      : data_(data), parent_width_(parent_width) { +    byte_width_ = 1U << static_cast<BitWidth>(packed_type & 3); +    type_ = static_cast<Type>(packed_type >> 2); +  } + +  Type GetType() const { return type_; } + +  bool IsNull() const { return type_ == FBT_NULL; } +  bool IsBool() const { return type_ == FBT_BOOL; } +  bool IsInt() const { return type_ == FBT_INT || type_ == FBT_INDIRECT_INT; } +  bool IsUInt() const { +    return type_ == FBT_UINT || type_ == FBT_INDIRECT_UINT; +  } +  bool IsIntOrUint() const { return IsInt() || IsUInt(); } +  bool IsFloat() const { +    return type_ == FBT_FLOAT || type_ == FBT_INDIRECT_FLOAT; +  } +  bool IsNumeric() const { return IsIntOrUint() || IsFloat(); } +  bool IsString() const { return type_ == FBT_STRING; } +  bool IsKey() const { return type_ == FBT_KEY; } +  bool IsVector() const { return type_ == FBT_VECTOR || type_ == FBT_MAP; } +  bool IsTypedVector() const { return flexbuffers::IsTypedVector(type_); } +  bool IsFixedTypedVector() const { return flexbuffers::IsFixedTypedVector(type_); } +  bool IsAnyVector() const { return (IsTypedVector() || IsFixedTypedVector() || IsVector());} +  bool IsMap() const { return type_ == FBT_MAP; } +  bool IsBlob() const { return type_ == FBT_BLOB; } + +  bool AsBool() const { +    return (type_ == FBT_BOOL ? ReadUInt64(data_, parent_width_) +                               : AsUInt64()) != 0; +  } + +  // Reads any type as a int64_t. Never fails, does most sensible conversion. +  // Truncates floats, strings are attempted to be parsed for a number, +  // vectors/maps return their size. Returns 0 if all else fails. +  int64_t AsInt64() const { +    if (type_ == FBT_INT) { +      // A fast path for the common case. +      return ReadInt64(data_, parent_width_); +    } else +      switch (type_) { +        case FBT_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_); +        case FBT_UINT: return ReadUInt64(data_, parent_width_); +        case FBT_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_); +        case FBT_FLOAT: +          return static_cast<int64_t>(ReadDouble(data_, parent_width_)); +        case FBT_INDIRECT_FLOAT: +          return static_cast<int64_t>(ReadDouble(Indirect(), byte_width_)); +        case FBT_NULL: return 0; +        case FBT_STRING: return flatbuffers::StringToInt(AsString().c_str()); +        case FBT_VECTOR: return static_cast<int64_t>(AsVector().size()); +        case FBT_BOOL: return ReadInt64(data_, parent_width_); +        default: +          // Convert other things to int. +          return 0; +      } +  } + +  // TODO: could specialize these to not use AsInt64() if that saves +  // extension ops in generated code, and use a faster op than ReadInt64. +  int32_t AsInt32() const { return static_cast<int32_t>(AsInt64()); } +  int16_t AsInt16() const { return static_cast<int16_t>(AsInt64()); } +  int8_t AsInt8() const { return static_cast<int8_t>(AsInt64()); } + +  uint64_t AsUInt64() const { +    if (type_ == FBT_UINT) { +      // A fast path for the common case. +      return ReadUInt64(data_, parent_width_); +    } else +      switch (type_) { +        case FBT_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_); +        case FBT_INT: return ReadInt64(data_, parent_width_); +        case FBT_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_); +        case FBT_FLOAT: +          return static_cast<uint64_t>(ReadDouble(data_, parent_width_)); +        case FBT_INDIRECT_FLOAT: +          return static_cast<uint64_t>(ReadDouble(Indirect(), byte_width_)); +        case FBT_NULL: return 0; +        case FBT_STRING: return flatbuffers::StringToUInt(AsString().c_str()); +        case FBT_VECTOR: return static_cast<uint64_t>(AsVector().size()); +        case FBT_BOOL: return ReadUInt64(data_, parent_width_); +        default: +          // Convert other things to uint. +          return 0; +      } +  } + +  uint32_t AsUInt32() const { return static_cast<uint32_t>(AsUInt64()); } +  uint16_t AsUInt16() const { return static_cast<uint16_t>(AsUInt64()); } +  uint8_t AsUInt8() const { return static_cast<uint8_t>(AsUInt64()); } + +  double AsDouble() const { +    if (type_ == FBT_FLOAT) { +      // A fast path for the common case. +      return ReadDouble(data_, parent_width_); +    } else +      switch (type_) { +        case FBT_INDIRECT_FLOAT: return ReadDouble(Indirect(), byte_width_); +        case FBT_INT: +          return static_cast<double>(ReadInt64(data_, parent_width_)); +        case FBT_UINT: +          return static_cast<double>(ReadUInt64(data_, parent_width_)); +        case FBT_INDIRECT_INT: +          return static_cast<double>(ReadInt64(Indirect(), byte_width_)); +        case FBT_INDIRECT_UINT: +          return static_cast<double>(ReadUInt64(Indirect(), byte_width_)); +        case FBT_NULL: return 0.0; +        case FBT_STRING: return strtod(AsString().c_str(), nullptr); +        case FBT_VECTOR: return static_cast<double>(AsVector().size()); +        case FBT_BOOL: +          return static_cast<double>(ReadUInt64(data_, parent_width_)); +        default: +          // Convert strings and other things to float. +          return 0; +      } +  } + +  float AsFloat() const { return static_cast<float>(AsDouble()); } + +  const char *AsKey() const { +    if (type_ == FBT_KEY) { +      return reinterpret_cast<const char *>(Indirect()); +    } else { +      return ""; +    } +  } + +  // This function returns the empty string if you try to read a not-string. +  String AsString() const { +    if (type_ == FBT_STRING) { +      return String(Indirect(), byte_width_); +    } else { +      return String::EmptyString(); +    } +  } + +  // Unlike AsString(), this will convert any type to a std::string. +  std::string ToString() const { +    std::string s; +    ToString(false, false, s); +    return s; +  } + +  // Convert any type to a JSON-like string. strings_quoted determines if +  // string values at the top level receive "" quotes (inside other values +  // they always do). keys_quoted determines if keys are quoted, at any level. +  // TODO(wvo): add further options to have indentation/newlines. +  void ToString(bool strings_quoted, bool keys_quoted, std::string &s) const { +    if (type_ == FBT_STRING) { +      String str(Indirect(), byte_width_); +      if (strings_quoted) { +        flatbuffers::EscapeString(str.c_str(), str.length(), &s, true, false); +      } else { +        s.append(str.c_str(), str.length()); +      } +    } else if (IsKey()) { +      auto str = AsKey(); +      if (keys_quoted) { +        flatbuffers::EscapeString(str, strlen(str), &s, true, false); +      } else { +        s += str; +      } +    } else if (IsInt()) { +      s += flatbuffers::NumToString(AsInt64()); +    } else if (IsUInt()) { +      s += flatbuffers::NumToString(AsUInt64()); +    } else if (IsFloat()) { +      s += flatbuffers::NumToString(AsDouble()); +    } else if (IsNull()) { +      s += "null"; +    } else if (IsBool()) { +      s += AsBool() ? "true" : "false"; +    } else if (IsMap()) { +      s += "{ "; +      auto m = AsMap(); +      auto keys = m.Keys(); +      auto vals = m.Values(); +      for (size_t i = 0; i < keys.size(); i++) { +        keys[i].ToString(true, keys_quoted, s); +        s += ": "; +        vals[i].ToString(true, keys_quoted, s); +        if (i < keys.size() - 1) s += ", "; +      } +      s += " }"; +    } else if (IsVector()) { +      AppendToString<Vector>(s, AsVector(), keys_quoted); +    } else if (IsTypedVector()) { +      AppendToString<TypedVector>(s, AsTypedVector(), keys_quoted); +    } else if (IsFixedTypedVector()) { +      AppendToString<FixedTypedVector>(s, AsFixedTypedVector(), keys_quoted); +    } else if (IsBlob()) { +      auto blob = AsBlob(); +      flatbuffers::EscapeString(reinterpret_cast<const char*>(blob.data()), blob.size(), &s, true, false); +    } else { +      s += "(?)"; +    } +  } + +  // This function returns the empty blob if you try to read a not-blob. +  // Strings can be viewed as blobs too. +  Blob AsBlob() const { +    if (type_ == FBT_BLOB || type_ == FBT_STRING) { +      return Blob(Indirect(), byte_width_); +    } else { +      return Blob::EmptyBlob(); +    } +  } + +  // This function returns the empty vector if you try to read a not-vector. +  // Maps can be viewed as vectors too. +  Vector AsVector() const { +    if (type_ == FBT_VECTOR || type_ == FBT_MAP) { +      return Vector(Indirect(), byte_width_); +    } else { +      return Vector::EmptyVector(); +    } +  } + +  TypedVector AsTypedVector() const { +    if (IsTypedVector()) { +      return TypedVector(Indirect(), byte_width_, +                         ToTypedVectorElementType(type_)); +    } else { +      return TypedVector::EmptyTypedVector(); +    } +  } + +  FixedTypedVector AsFixedTypedVector() const { +    if (IsFixedTypedVector()) { +      uint8_t len = 0; +      auto vtype = ToFixedTypedVectorElementType(type_, &len); +      return FixedTypedVector(Indirect(), byte_width_, vtype, len); +    } else { +      return FixedTypedVector::EmptyFixedTypedVector(); +    } +  } + +  Map AsMap() const { +    if (type_ == FBT_MAP) { +      return Map(Indirect(), byte_width_); +    } else { +      return Map::EmptyMap(); +    } +  } + +  template<typename T> T As() const; + +  // Experimental: Mutation functions. +  // These allow scalars in an already created buffer to be updated in-place. +  // Since by default scalars are stored in the smallest possible space, +  // the new value may not fit, in which case these functions return false. +  // To avoid this, you can construct the values you intend to mutate using +  // Builder::ForceMinimumBitWidth. +  bool MutateInt(int64_t i) { +    if (type_ == FBT_INT) { +      return Mutate(data_, i, parent_width_, WidthI(i)); +    } else if (type_ == FBT_INDIRECT_INT) { +      return Mutate(Indirect(), i, byte_width_, WidthI(i)); +    } else if (type_ == FBT_UINT) { +      auto u = static_cast<uint64_t>(i); +      return Mutate(data_, u, parent_width_, WidthU(u)); +    } else if (type_ == FBT_INDIRECT_UINT) { +      auto u = static_cast<uint64_t>(i); +      return Mutate(Indirect(), u, byte_width_, WidthU(u)); +    } else { +      return false; +    } +  } + +  bool MutateBool(bool b) { +    return type_ == FBT_BOOL && Mutate(data_, b, parent_width_, BIT_WIDTH_8); +  } + +  bool MutateUInt(uint64_t u) { +    if (type_ == FBT_UINT) { +      return Mutate(data_, u, parent_width_, WidthU(u)); +    } else if (type_ == FBT_INDIRECT_UINT) { +      return Mutate(Indirect(), u, byte_width_, WidthU(u)); +    } else if (type_ == FBT_INT) { +      auto i = static_cast<int64_t>(u); +      return Mutate(data_, i, parent_width_, WidthI(i)); +    } else if (type_ == FBT_INDIRECT_INT) { +      auto i = static_cast<int64_t>(u); +      return Mutate(Indirect(), i, byte_width_, WidthI(i)); +    } else { +      return false; +    } +  } + +  bool MutateFloat(float f) { +    if (type_ == FBT_FLOAT) { +      return MutateF(data_, f, parent_width_, BIT_WIDTH_32); +    } else if (type_ == FBT_INDIRECT_FLOAT) { +      return MutateF(Indirect(), f, byte_width_, BIT_WIDTH_32); +    } else { +      return false; +    } +  } + +  bool MutateFloat(double d) { +    if (type_ == FBT_FLOAT) { +      return MutateF(data_, d, parent_width_, WidthF(d)); +    } else if (type_ == FBT_INDIRECT_FLOAT) { +      return MutateF(Indirect(), d, byte_width_, WidthF(d)); +    } else { +      return false; +    } +  } + +  bool MutateString(const char *str, size_t len) { +    auto s = AsString(); +    if (s.IsTheEmptyString()) return false; +    // This is very strict, could allow shorter strings, but that creates +    // garbage. +    if (s.length() != len) return false; +    memcpy(const_cast<char *>(s.c_str()), str, len); +    return true; +  } +  bool MutateString(const char *str) { return MutateString(str, strlen(str)); } +  bool MutateString(const std::string &str) { +    return MutateString(str.data(), str.length()); +  } + + private: +  const uint8_t *Indirect() const { +    return flexbuffers::Indirect(data_, parent_width_); +  } + +  template<typename T> +  bool Mutate(const uint8_t *dest, T t, size_t byte_width, +              BitWidth value_width) { +    auto fits = static_cast<size_t>(static_cast<size_t>(1U) << value_width) <= +                byte_width; +    if (fits) { +      t = flatbuffers::EndianScalar(t); +      memcpy(const_cast<uint8_t *>(dest), &t, byte_width); +    } +    return fits; +  } + +  template<typename T> +  bool MutateF(const uint8_t *dest, T t, size_t byte_width, +               BitWidth value_width) { +    if (byte_width == sizeof(double)) +      return Mutate(dest, static_cast<double>(t), byte_width, value_width); +    if (byte_width == sizeof(float)) +      return Mutate(dest, static_cast<float>(t), byte_width, value_width); +    FLATBUFFERS_ASSERT(false); +    return false; +  } + +  const uint8_t *data_; +  uint8_t parent_width_; +  uint8_t byte_width_; +  Type type_; +}; + +// Template specialization for As(). +template<> inline bool Reference::As<bool>() const { return AsBool(); } + +template<> inline int8_t Reference::As<int8_t>() const { return AsInt8(); } +template<> inline int16_t Reference::As<int16_t>() const { return AsInt16(); } +template<> inline int32_t Reference::As<int32_t>() const { return AsInt32(); } +template<> inline int64_t Reference::As<int64_t>() const { return AsInt64(); } + +template<> inline uint8_t Reference::As<uint8_t>() const { return AsUInt8(); } +template<> inline uint16_t Reference::As<uint16_t>() const { return AsUInt16(); } +template<> inline uint32_t Reference::As<uint32_t>() const { return AsUInt32(); } +template<> inline uint64_t Reference::As<uint64_t>() const { return AsUInt64(); } + +template<> inline double Reference::As<double>() const { return AsDouble(); } +template<> inline float Reference::As<float>() const { return AsFloat(); } + +template<> inline String Reference::As<String>() const { return AsString(); } +template<> inline std::string Reference::As<std::string>() const { +  return AsString().str(); +} + +template<> inline Blob Reference::As<Blob>() const { return AsBlob(); } +template<> inline Vector Reference::As<Vector>() const { return AsVector(); } +template<> inline TypedVector Reference::As<TypedVector>() const { +  return AsTypedVector(); +} +template<> inline FixedTypedVector Reference::As<FixedTypedVector>() const { +  return AsFixedTypedVector(); +} +template<> inline Map Reference::As<Map>() const { return AsMap(); } + +inline uint8_t PackedType(BitWidth bit_width, Type type) { +  return static_cast<uint8_t>(bit_width | (type << 2)); +} + +inline uint8_t NullPackedType() { return PackedType(BIT_WIDTH_8, FBT_NULL); } + +// Vector accessors. +// Note: if you try to access outside of bounds, you get a Null value back +// instead. Normally this would be an assert, but since this is "dynamically +// typed" data, you may not want that (someone sends you a 2d vector and you +// wanted 3d). +// The Null converts seamlessly into a default value for any other type. +// TODO(wvo): Could introduce an #ifdef that makes this into an assert? +inline Reference Vector::operator[](size_t i) const { +  auto len = size(); +  if (i >= len) return Reference(nullptr, 1, NullPackedType()); +  auto packed_type = (data_ + len * byte_width_)[i]; +  auto elem = data_ + i * byte_width_; +  return Reference(elem, byte_width_, packed_type); +} + +inline Reference TypedVector::operator[](size_t i) const { +  auto len = size(); +  if (i >= len) return Reference(nullptr, 1, NullPackedType()); +  auto elem = data_ + i * byte_width_; +  return Reference(elem, byte_width_, 1, type_); +} + +inline Reference FixedTypedVector::operator[](size_t i) const { +  if (i >= len_) return Reference(nullptr, 1, NullPackedType()); +  auto elem = data_ + i * byte_width_; +  return Reference(elem, byte_width_, 1, type_); +} + +template<typename T> int KeyCompare(const void *key, const void *elem) { +  auto str_elem = reinterpret_cast<const char *>( +      Indirect<T>(reinterpret_cast<const uint8_t *>(elem))); +  auto skey = reinterpret_cast<const char *>(key); +  return strcmp(skey, str_elem); +} + +inline Reference Map::operator[](const char *key) const { +  auto keys = Keys(); +  // We can't pass keys.byte_width_ to the comparison function, so we have +  // to pick the right one ahead of time. +  int (*comp)(const void *, const void *) = nullptr; +  switch (keys.byte_width_) { +    case 1: comp = KeyCompare<uint8_t>; break; +    case 2: comp = KeyCompare<uint16_t>; break; +    case 4: comp = KeyCompare<uint32_t>; break; +    case 8: comp = KeyCompare<uint64_t>; break; +  } +  auto res = std::bsearch(key, keys.data_, keys.size(), keys.byte_width_, comp); +  if (!res) return Reference(nullptr, 1, NullPackedType()); +  auto i = (reinterpret_cast<uint8_t *>(res) - keys.data_) / keys.byte_width_; +  return (*static_cast<const Vector *>(this))[i]; +} + +inline Reference Map::operator[](const std::string &key) const { +  return (*this)[key.c_str()]; +} + +inline Reference GetRoot(const uint8_t *buffer, size_t size) { +  // See Finish() below for the serialization counterpart of this. +  // The root starts at the end of the buffer, so we parse backwards from there. +  auto end = buffer + size; +  auto byte_width = *--end; +  auto packed_type = *--end; +  end -= byte_width;  // The root data item. +  return Reference(end, byte_width, packed_type); +} + +inline Reference GetRoot(const std::vector<uint8_t> &buffer) { +  return GetRoot(flatbuffers::vector_data(buffer), buffer.size()); +} + +// Flags that configure how the Builder behaves. +// The "Share" flags determine if the Builder automatically tries to pool +// this type. Pooling can reduce the size of serialized data if there are +// multiple maps of the same kind, at the expense of slightly slower +// serialization (the cost of lookups) and more memory use (std::set). +// By default this is on for keys, but off for strings. +// Turn keys off if you have e.g. only one map. +// Turn strings on if you expect many non-unique string values. +// Additionally, sharing key vectors can save space if you have maps with +// identical field populations. +enum BuilderFlag { +  BUILDER_FLAG_NONE = 0, +  BUILDER_FLAG_SHARE_KEYS = 1, +  BUILDER_FLAG_SHARE_STRINGS = 2, +  BUILDER_FLAG_SHARE_KEYS_AND_STRINGS = 3, +  BUILDER_FLAG_SHARE_KEY_VECTORS = 4, +  BUILDER_FLAG_SHARE_ALL = 7, +}; + +class Builder FLATBUFFERS_FINAL_CLASS { + public: +  Builder(size_t initial_size = 256, +          BuilderFlag flags = BUILDER_FLAG_SHARE_KEYS) +      : buf_(initial_size), +        finished_(false), +        flags_(flags), +        force_min_bit_width_(BIT_WIDTH_8), +        key_pool(KeyOffsetCompare(buf_)), +        string_pool(StringOffsetCompare(buf_)) { +    buf_.clear(); +  } + +  /// @brief Get the serialized buffer (after you call `Finish()`). +  /// @return Returns a vector owned by this class. +  const std::vector<uint8_t> &GetBuffer() const { +    Finished(); +    return buf_; +  } + +  // Size of the buffer. Does not include unfinished values. +  size_t GetSize() const { return buf_.size(); } + +  // Reset all state so we can re-use the buffer. +  void Clear() { +    buf_.clear(); +    stack_.clear(); +    finished_ = false; +    // flags_ remains as-is; +    force_min_bit_width_ = BIT_WIDTH_8; +    key_pool.clear(); +    string_pool.clear(); +  } + +  // All value constructing functions below have two versions: one that +  // takes a key (for placement inside a map) and one that doesn't (for inside +  // vectors and elsewhere). + +  void Null() { stack_.push_back(Value()); } +  void Null(const char *key) { +    Key(key); +    Null(); +  } + +  void Int(int64_t i) { stack_.push_back(Value(i, FBT_INT, WidthI(i))); } +  void Int(const char *key, int64_t i) { +    Key(key); +    Int(i); +  } + +  void UInt(uint64_t u) { stack_.push_back(Value(u, FBT_UINT, WidthU(u))); } +  void UInt(const char *key, uint64_t u) { +    Key(key); +    UInt(u); +  } + +  void Float(float f) { stack_.push_back(Value(f)); } +  void Float(const char *key, float f) { +    Key(key); +    Float(f); +  } + +  void Double(double f) { stack_.push_back(Value(f)); } +  void Double(const char *key, double d) { +    Key(key); +    Double(d); +  } + +  void Bool(bool b) { stack_.push_back(Value(b)); } +  void Bool(const char *key, bool b) { +    Key(key); +    Bool(b); +  } + +  void IndirectInt(int64_t i) { PushIndirect(i, FBT_INDIRECT_INT, WidthI(i)); } +  void IndirectInt(const char *key, int64_t i) { +    Key(key); +    IndirectInt(i); +  } + +  void IndirectUInt(uint64_t u) { +    PushIndirect(u, FBT_INDIRECT_UINT, WidthU(u)); +  } +  void IndirectUInt(const char *key, uint64_t u) { +    Key(key); +    IndirectUInt(u); +  } + +  void IndirectFloat(float f) { +    PushIndirect(f, FBT_INDIRECT_FLOAT, BIT_WIDTH_32); +  } +  void IndirectFloat(const char *key, float f) { +    Key(key); +    IndirectFloat(f); +  } + +  void IndirectDouble(double f) { +    PushIndirect(f, FBT_INDIRECT_FLOAT, WidthF(f)); +  } +  void IndirectDouble(const char *key, double d) { +    Key(key); +    IndirectDouble(d); +  } + +  size_t Key(const char *str, size_t len) { +    auto sloc = buf_.size(); +    WriteBytes(str, len + 1); +    if (flags_ & BUILDER_FLAG_SHARE_KEYS) { +      auto it = key_pool.find(sloc); +      if (it != key_pool.end()) { +        // Already in the buffer. Remove key we just serialized, and use +        // existing offset instead. +        buf_.resize(sloc); +        sloc = *it; +      } else { +        key_pool.insert(sloc); +      } +    } +    stack_.push_back(Value(static_cast<uint64_t>(sloc), FBT_KEY, BIT_WIDTH_8)); +    return sloc; +  } + +  size_t Key(const char *str) { return Key(str, strlen(str)); } +  size_t Key(const std::string &str) { return Key(str.c_str(), str.size()); } + +  size_t String(const char *str, size_t len) { +    auto reset_to = buf_.size(); +    auto sloc = CreateBlob(str, len, 1, FBT_STRING); +    if (flags_ & BUILDER_FLAG_SHARE_STRINGS) { +      StringOffset so(sloc, len); +      auto it = string_pool.find(so); +      if (it != string_pool.end()) { +        // Already in the buffer. Remove string we just serialized, and use +        // existing offset instead. +        buf_.resize(reset_to); +        sloc = it->first; +        stack_.back().u_ = sloc; +      } else { +        string_pool.insert(so); +      } +    } +    return sloc; +  } +  size_t String(const char *str) { return String(str, strlen(str)); } +  size_t String(const std::string &str) { +    return String(str.c_str(), str.size()); +  } +  void String(const flexbuffers::String &str) { +    String(str.c_str(), str.length()); +  } + +  void String(const char *key, const char *str) { +    Key(key); +    String(str); +  } +  void String(const char *key, const std::string &str) { +    Key(key); +    String(str); +  } +  void String(const char *key, const flexbuffers::String &str) { +    Key(key); +    String(str); +  } + +  size_t Blob(const void *data, size_t len) { +    return CreateBlob(data, len, 0, FBT_BLOB); +  } +  size_t Blob(const std::vector<uint8_t> &v) { +    return CreateBlob(flatbuffers::vector_data(v), v.size(), 0, FBT_BLOB); +  } + +  // TODO(wvo): support all the FlexBuffer types (like flexbuffers::String), +  // e.g. Vector etc. Also in overloaded versions. +  // Also some FlatBuffers types? + +  size_t StartVector() { return stack_.size(); } +  size_t StartVector(const char *key) { +    Key(key); +    return stack_.size(); +  } +  size_t StartMap() { return stack_.size(); } +  size_t StartMap(const char *key) { +    Key(key); +    return stack_.size(); +  } + +  // TODO(wvo): allow this to specify an aligment greater than the natural +  // alignment. +  size_t EndVector(size_t start, bool typed, bool fixed) { +    auto vec = CreateVector(start, stack_.size() - start, 1, typed, fixed); +    // Remove temp elements and return vector. +    stack_.resize(start); +    stack_.push_back(vec); +    return static_cast<size_t>(vec.u_); +  } + +  size_t EndMap(size_t start) { +    // We should have interleaved keys and values on the stack. +    // Make sure it is an even number: +    auto len = stack_.size() - start; +    FLATBUFFERS_ASSERT(!(len & 1)); +    len /= 2; +    // Make sure keys are all strings: +    for (auto key = start; key < stack_.size(); key += 2) { +      FLATBUFFERS_ASSERT(stack_[key].type_ == FBT_KEY); +    } +    // Now sort values, so later we can do a binary seach lookup. +    // We want to sort 2 array elements at a time. +    struct TwoValue { +      Value key; +      Value val; +    }; +    // TODO(wvo): strict aliasing? +    // TODO(wvo): allow the caller to indicate the data is already sorted +    // for maximum efficiency? With an assert to check sortedness to make sure +    // we're not breaking binary search. +    // Or, we can track if the map is sorted as keys are added which would be +    // be quite cheap (cheaper than checking it here), so we can skip this +    // step automatically when appliccable, and encourage people to write in +    // sorted fashion. +    // std::sort is typically already a lot faster on sorted data though. +    auto dict = +        reinterpret_cast<TwoValue *>(flatbuffers::vector_data(stack_) + start); +    std::sort(dict, dict + len, +              [&](const TwoValue &a, const TwoValue &b) -> bool { +                auto as = reinterpret_cast<const char *>( +                    flatbuffers::vector_data(buf_) + a.key.u_); +                auto bs = reinterpret_cast<const char *>( +                    flatbuffers::vector_data(buf_) + b.key.u_); +                auto comp = strcmp(as, bs); +                // If this assertion hits, you've added two keys with the same +                // value to this map. +                // TODO: Have to check for pointer equality, as some sort +                // implementation apparently call this function with the same +                // element?? Why? +                FLATBUFFERS_ASSERT(comp || &a == &b); +                return comp < 0; +              }); +    // First create a vector out of all keys. +    // TODO(wvo): if kBuilderFlagShareKeyVectors is true, see if we can share +    // the first vector. +    auto keys = CreateVector(start, len, 2, true, false); +    auto vec = CreateVector(start + 1, len, 2, false, false, &keys); +    // Remove temp elements and return map. +    stack_.resize(start); +    stack_.push_back(vec); +    return static_cast<size_t>(vec.u_); +  } + +  template<typename F> size_t Vector(F f) { +    auto start = StartVector(); +    f(); +    return EndVector(start, false, false); +  } +  template<typename F, typename T> size_t Vector(F f, T &state) { +    auto start = StartVector(); +    f(state); +    return EndVector(start, false, false); +  } +  template<typename F> size_t Vector(const char *key, F f) { +    auto start = StartVector(key); +    f(); +    return EndVector(start, false, false); +  } +  template<typename F, typename T> +  size_t Vector(const char *key, F f, T &state) { +    auto start = StartVector(key); +    f(state); +    return EndVector(start, false, false); +  } + +  template<typename T> void Vector(const T *elems, size_t len) { +    if (flatbuffers::is_scalar<T>::value) { +      // This path should be a lot quicker and use less space. +      ScalarVector(elems, len, false); +    } else { +      auto start = StartVector(); +      for (size_t i = 0; i < len; i++) Add(elems[i]); +      EndVector(start, false, false); +    } +  } +  template<typename T> +  void Vector(const char *key, const T *elems, size_t len) { +    Key(key); +    Vector(elems, len); +  } +  template<typename T> void Vector(const std::vector<T> &vec) { +    Vector(flatbuffers::vector_data(vec), vec.size()); +  } + +  template<typename F> size_t TypedVector(F f) { +    auto start = StartVector(); +    f(); +    return EndVector(start, true, false); +  } +  template<typename F, typename T> size_t TypedVector(F f, T &state) { +    auto start = StartVector(); +    f(state); +    return EndVector(start, true, false); +  } +  template<typename F> size_t TypedVector(const char *key, F f) { +    auto start = StartVector(key); +    f(); +    return EndVector(start, true, false); +  } +  template<typename F, typename T> +  size_t TypedVector(const char *key, F f, T &state) { +    auto start = StartVector(key); +    f(state); +    return EndVector(start, true, false); +  } + +  template<typename T> size_t FixedTypedVector(const T *elems, size_t len) { +    // We only support a few fixed vector lengths. Anything bigger use a +    // regular typed vector. +    FLATBUFFERS_ASSERT(len >= 2 && len <= 4); +    // And only scalar values. +    static_assert(flatbuffers::is_scalar<T>::value, "Unrelated types"); +    return ScalarVector(elems, len, true); +  } + +  template<typename T> +  size_t FixedTypedVector(const char *key, const T *elems, size_t len) { +    Key(key); +    return FixedTypedVector(elems, len); +  } + +  template<typename F> size_t Map(F f) { +    auto start = StartMap(); +    f(); +    return EndMap(start); +  } +  template<typename F, typename T> size_t Map(F f, T &state) { +    auto start = StartMap(); +    f(state); +    return EndMap(start); +  } +  template<typename F> size_t Map(const char *key, F f) { +    auto start = StartMap(key); +    f(); +    return EndMap(start); +  } +  template<typename F, typename T> size_t Map(const char *key, F f, T &state) { +    auto start = StartMap(key); +    f(state); +    return EndMap(start); +  } +  template<typename T> void Map(const std::map<std::string, T> &map) { +    auto start = StartMap(); +    for (auto it = map.begin(); it != map.end(); ++it) +      Add(it->first.c_str(), it->second); +    EndMap(start); +  } + +  // Overloaded Add that tries to call the correct function above. +  void Add(int8_t i) { Int(i); } +  void Add(int16_t i) { Int(i); } +  void Add(int32_t i) { Int(i); } +  void Add(int64_t i) { Int(i); } +  void Add(uint8_t u) { UInt(u); } +  void Add(uint16_t u) { UInt(u); } +  void Add(uint32_t u) { UInt(u); } +  void Add(uint64_t u) { UInt(u); } +  void Add(float f) { Float(f); } +  void Add(double d) { Double(d); } +  void Add(bool b) { Bool(b); } +  void Add(const char *str) { String(str); } +  void Add(const std::string &str) { String(str); } +  void Add(const flexbuffers::String &str) { String(str); } + +  template<typename T> void Add(const std::vector<T> &vec) { Vector(vec); } + +  template<typename T> void Add(const char *key, const T &t) { +    Key(key); +    Add(t); +  } + +  template<typename T> void Add(const std::map<std::string, T> &map) { +    Map(map); +  } + +  template<typename T> void operator+=(const T &t) { Add(t); } + +  // This function is useful in combination with the Mutate* functions above. +  // It forces elements of vectors and maps to have a minimum size, such that +  // they can later be updated without failing. +  // Call with no arguments to reset. +  void ForceMinimumBitWidth(BitWidth bw = BIT_WIDTH_8) { +    force_min_bit_width_ = bw; +  } + +  void Finish() { +    // If you hit this assert, you likely have objects that were never included +    // in a parent. You need to have exactly one root to finish a buffer. +    // Check your Start/End calls are matched, and all objects are inside +    // some other object. +    FLATBUFFERS_ASSERT(stack_.size() == 1); + +    // Write root value. +    auto byte_width = Align(stack_[0].ElemWidth(buf_.size(), 0)); +    WriteAny(stack_[0], byte_width); +    // Write root type. +    Write(stack_[0].StoredPackedType(), 1); +    // Write root size. Normally determined by parent, but root has no parent :) +    Write(byte_width, 1); + +    finished_ = true; +  } + + private: +  void Finished() const { +    // If you get this assert, you're attempting to get access a buffer +    // which hasn't been finished yet. Be sure to call +    // Builder::Finish with your root object. +    FLATBUFFERS_ASSERT(finished_); +  } + +  // Align to prepare for writing a scalar with a certain size. +  uint8_t Align(BitWidth alignment) { +    auto byte_width = 1U << alignment; +    buf_.insert(buf_.end(), flatbuffers::PaddingBytes(buf_.size(), byte_width), +                0); +    return static_cast<uint8_t>(byte_width); +  } + +  void WriteBytes(const void *val, size_t size) { +    buf_.insert(buf_.end(), reinterpret_cast<const uint8_t *>(val), +                reinterpret_cast<const uint8_t *>(val) + size); +  } + +  template<typename T> void Write(T val, size_t byte_width) { +    FLATBUFFERS_ASSERT(sizeof(T) >= byte_width); +    val = flatbuffers::EndianScalar(val); +    WriteBytes(&val, byte_width); +  } + +  void WriteDouble(double f, uint8_t byte_width) { +    switch (byte_width) { +      case 8: Write(f, byte_width); break; +      case 4: Write(static_cast<float>(f), byte_width); break; +      // case 2: Write(static_cast<half>(f), byte_width); break; +      // case 1: Write(static_cast<quarter>(f), byte_width); break; +      default: FLATBUFFERS_ASSERT(0); +    } +  } + +  void WriteOffset(uint64_t o, uint8_t byte_width) { +    auto reloff = buf_.size() - o; +    FLATBUFFERS_ASSERT(byte_width == 8 || reloff < 1ULL << (byte_width * 8)); +    Write(reloff, byte_width); +  } + +  template<typename T> void PushIndirect(T val, Type type, BitWidth bit_width) { +    auto byte_width = Align(bit_width); +    auto iloc = buf_.size(); +    Write(val, byte_width); +    stack_.push_back(Value(static_cast<uint64_t>(iloc), type, bit_width)); +  } + +  static BitWidth WidthB(size_t byte_width) { +    switch (byte_width) { +      case 1: return BIT_WIDTH_8; +      case 2: return BIT_WIDTH_16; +      case 4: return BIT_WIDTH_32; +      case 8: return BIT_WIDTH_64; +      default: FLATBUFFERS_ASSERT(false); return BIT_WIDTH_64; +    } +  } + +  template<typename T> static Type GetScalarType() { +    static_assert(flatbuffers::is_scalar<T>::value, "Unrelated types"); +    return flatbuffers::is_floating_point<T>::value +               ? FBT_FLOAT +               : flatbuffers::is_same<T, bool>::value +                     ? FBT_BOOL +                     : (flatbuffers::is_unsigned<T>::value ? FBT_UINT +                                                           : FBT_INT); +  } + +  struct Value { +    union { +      int64_t i_; +      uint64_t u_; +      double f_; +    }; + +    Type type_; + +    // For scalars: of itself, for vector: of its elements, for string: length. +    BitWidth min_bit_width_; + +    Value() : i_(0), type_(FBT_NULL), min_bit_width_(BIT_WIDTH_8) {} + +    Value(bool b) +        : u_(static_cast<uint64_t>(b)), +          type_(FBT_BOOL), +          min_bit_width_(BIT_WIDTH_8) {} + +    Value(int64_t i, Type t, BitWidth bw) +        : i_(i), type_(t), min_bit_width_(bw) {} +    Value(uint64_t u, Type t, BitWidth bw) +        : u_(u), type_(t), min_bit_width_(bw) {} + +    Value(float f) : f_(f), type_(FBT_FLOAT), min_bit_width_(BIT_WIDTH_32) {} +    Value(double f) : f_(f), type_(FBT_FLOAT), min_bit_width_(WidthF(f)) {} + +    uint8_t StoredPackedType(BitWidth parent_bit_width_ = BIT_WIDTH_8) const { +      return PackedType(StoredWidth(parent_bit_width_), type_); +    } + +    BitWidth ElemWidth(size_t buf_size, size_t elem_index) const { +      if (IsInline(type_)) { +        return min_bit_width_; +      } else { +        // We have an absolute offset, but want to store a relative offset +        // elem_index elements beyond the current buffer end. Since whether +        // the relative offset fits in a certain byte_width depends on +        // the size of the elements before it (and their alignment), we have +        // to test for each size in turn. +        for (size_t byte_width = 1; +             byte_width <= sizeof(flatbuffers::largest_scalar_t); +             byte_width *= 2) { +          // Where are we going to write this offset? +          auto offset_loc = buf_size + +                            flatbuffers::PaddingBytes(buf_size, byte_width) + +                            elem_index * byte_width; +          // Compute relative offset. +          auto offset = offset_loc - u_; +          // Does it fit? +          auto bit_width = WidthU(offset); +          if (static_cast<size_t>(static_cast<size_t>(1U) << bit_width) == +              byte_width) +            return bit_width; +        } +        FLATBUFFERS_ASSERT(false);  // Must match one of the sizes above. +        return BIT_WIDTH_64; +      } +    } + +    BitWidth StoredWidth(BitWidth parent_bit_width_ = BIT_WIDTH_8) const { +      if (IsInline(type_)) { +        return (std::max)(min_bit_width_, parent_bit_width_); +      } else { +        return min_bit_width_; +      } +    } +  }; + +  void WriteAny(const Value &val, uint8_t byte_width) { +    switch (val.type_) { +      case FBT_NULL: +      case FBT_INT: Write(val.i_, byte_width); break; +      case FBT_BOOL: +      case FBT_UINT: Write(val.u_, byte_width); break; +      case FBT_FLOAT: WriteDouble(val.f_, byte_width); break; +      default: WriteOffset(val.u_, byte_width); break; +    } +  } + +  size_t CreateBlob(const void *data, size_t len, size_t trailing, Type type) { +    auto bit_width = WidthU(len); +    auto byte_width = Align(bit_width); +    Write<uint64_t>(len, byte_width); +    auto sloc = buf_.size(); +    WriteBytes(data, len + trailing); +    stack_.push_back(Value(static_cast<uint64_t>(sloc), type, bit_width)); +    return sloc; +  } + +  template<typename T> +  size_t ScalarVector(const T *elems, size_t len, bool fixed) { +    auto vector_type = GetScalarType<T>(); +    auto byte_width = sizeof(T); +    auto bit_width = WidthB(byte_width); +    // If you get this assert, you're trying to write a vector with a size +    // field that is bigger than the scalars you're trying to write (e.g. a +    // byte vector > 255 elements). For such types, write a "blob" instead. +    // TODO: instead of asserting, could write vector with larger elements +    // instead, though that would be wasteful. +    FLATBUFFERS_ASSERT(WidthU(len) <= bit_width); +    if (!fixed) Write<uint64_t>(len, byte_width); +    auto vloc = buf_.size(); +    for (size_t i = 0; i < len; i++) Write(elems[i], byte_width); +    stack_.push_back(Value(static_cast<uint64_t>(vloc), +                           ToTypedVector(vector_type, fixed ? len : 0), +                           bit_width)); +    return vloc; +  } + +  Value CreateVector(size_t start, size_t vec_len, size_t step, bool typed, +                     bool fixed, const Value *keys = nullptr) { +    FLATBUFFERS_ASSERT(!fixed || typed); // typed=false, fixed=true combination is not supported. +    // Figure out smallest bit width we can store this vector with. +    auto bit_width = (std::max)(force_min_bit_width_, WidthU(vec_len)); +    auto prefix_elems = 1; +    if (keys) { +      // If this vector is part of a map, we will pre-fix an offset to the keys +      // to this vector. +      bit_width = (std::max)(bit_width, keys->ElemWidth(buf_.size(), 0)); +      prefix_elems += 2; +    } +    Type vector_type = FBT_KEY; +    // Check bit widths and types for all elements. +    for (size_t i = start; i < stack_.size(); i += step) { +      auto elem_width = stack_[i].ElemWidth(buf_.size(), i + prefix_elems); +      bit_width = (std::max)(bit_width, elem_width); +      if (typed) { +        if (i == start) { +          vector_type = stack_[i].type_; +        } else { +          // If you get this assert, you are writing a typed vector with +          // elements that are not all the same type. +          FLATBUFFERS_ASSERT(vector_type == stack_[i].type_); +        } +      } +    } +    // If you get this assert, your fixed types are not one of: +    // Int / UInt / Float / Key. +    FLATBUFFERS_ASSERT(!fixed || IsTypedVectorElementType(vector_type)); +    auto byte_width = Align(bit_width); +    // Write vector. First the keys width/offset if available, and size. +    if (keys) { +      WriteOffset(keys->u_, byte_width); +      Write<uint64_t>(1ULL << keys->min_bit_width_, byte_width); +    } +    if (!fixed) Write<uint64_t>(vec_len, byte_width); +    // Then the actual data. +    auto vloc = buf_.size(); +    for (size_t i = start; i < stack_.size(); i += step) { +      WriteAny(stack_[i], byte_width); +    } +    // Then the types. +    if (!typed) { +      for (size_t i = start; i < stack_.size(); i += step) { +        buf_.push_back(stack_[i].StoredPackedType(bit_width)); +      } +    } +    return Value(static_cast<uint64_t>(vloc), +                 keys ? FBT_MAP +                      : (typed ? ToTypedVector(vector_type, fixed ? vec_len : 0) +                               : FBT_VECTOR), +                 bit_width); +  } + +  // You shouldn't really be copying instances of this class. +  Builder(const Builder &); +  Builder &operator=(const Builder &); + +  std::vector<uint8_t> buf_; +  std::vector<Value> stack_; + +  bool finished_; + +  BuilderFlag flags_; + +  BitWidth force_min_bit_width_; + +  struct KeyOffsetCompare { +    explicit KeyOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {} +    bool operator()(size_t a, size_t b) const { +      auto stra = +          reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + a); +      auto strb = +          reinterpret_cast<const char *>(flatbuffers::vector_data(*buf_) + b); +      return strcmp(stra, strb) < 0; +    } +    const std::vector<uint8_t> *buf_; +  }; + +  typedef std::pair<size_t, size_t> StringOffset; +  struct StringOffsetCompare { +    explicit StringOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {} +    bool operator()(const StringOffset &a, const StringOffset &b) const { +      auto stra = reinterpret_cast<const char *>( +          flatbuffers::vector_data(*buf_) + a.first); +      auto strb = reinterpret_cast<const char *>( +          flatbuffers::vector_data(*buf_) + b.first); +      return strncmp(stra, strb, (std::min)(a.second, b.second) + 1) < 0; +    } +    const std::vector<uint8_t> *buf_; +  }; + +  typedef std::set<size_t, KeyOffsetCompare> KeyOffsetMap; +  typedef std::set<StringOffset, StringOffsetCompare> StringOffsetMap; + +  KeyOffsetMap key_pool; +  StringOffsetMap string_pool; +}; + +}  // namespace flexbuffers + +#  if defined(_MSC_VER) +#    pragma warning(pop) +#  endif + +#endif  // FLATBUFFERS_FLEXBUFFERS_H_ diff --git a/host/lib/deps/flatbuffers/include/flatbuffers/hash.h b/host/lib/deps/flatbuffers/include/flatbuffers/hash.h new file mode 100644 index 000000000..16536cb49 --- /dev/null +++ b/host/lib/deps/flatbuffers/include/flatbuffers/hash.h @@ -0,0 +1,127 @@ +/* + * Copyright 2015 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_HASH_H_ +#define FLATBUFFERS_HASH_H_ + +#include <cstdint> +#include <cstring> + +#include "flatbuffers/flatbuffers.h" + +namespace flatbuffers { + +template<typename T> struct FnvTraits { +  static const T kFnvPrime; +  static const T kOffsetBasis; +}; + +template<> struct FnvTraits<uint32_t> { +  static const uint32_t kFnvPrime = 0x01000193; +  static const uint32_t kOffsetBasis = 0x811C9DC5; +}; + +template<> struct FnvTraits<uint64_t> { +  static const uint64_t kFnvPrime = 0x00000100000001b3ULL; +  static const uint64_t kOffsetBasis = 0xcbf29ce484222645ULL; +}; + +template<typename T> T HashFnv1(const char *input) { +  T hash = FnvTraits<T>::kOffsetBasis; +  for (const char *c = input; *c; ++c) { +    hash *= FnvTraits<T>::kFnvPrime; +    hash ^= static_cast<unsigned char>(*c); +  } +  return hash; +} + +template<typename T> T HashFnv1a(const char *input) { +  T hash = FnvTraits<T>::kOffsetBasis; +  for (const char *c = input; *c; ++c) { +    hash ^= static_cast<unsigned char>(*c); +    hash *= FnvTraits<T>::kFnvPrime; +  } +  return hash; +} + +template <> inline uint16_t HashFnv1<uint16_t>(const char *input) { +  uint32_t hash = HashFnv1<uint32_t>(input); +  return (hash >> 16) ^ (hash & 0xffff); +} + +template <> inline uint16_t HashFnv1a<uint16_t>(const char *input) { +  uint32_t hash = HashFnv1a<uint32_t>(input); +  return (hash >> 16) ^ (hash & 0xffff); +} + +template <typename T> struct NamedHashFunction { +  const char *name; + +  typedef T (*HashFunction)(const char *); +  HashFunction function; +}; + +const NamedHashFunction<uint16_t> kHashFunctions16[] = { +  { "fnv1_16",  HashFnv1<uint16_t> }, +  { "fnv1a_16", HashFnv1a<uint16_t> }, +}; + +const NamedHashFunction<uint32_t> kHashFunctions32[] = { +  { "fnv1_32", HashFnv1<uint32_t> }, +  { "fnv1a_32", HashFnv1a<uint32_t> }, +}; + +const NamedHashFunction<uint64_t> kHashFunctions64[] = { +  { "fnv1_64", HashFnv1<uint64_t> }, +  { "fnv1a_64", HashFnv1a<uint64_t> }, +}; + +inline NamedHashFunction<uint16_t>::HashFunction FindHashFunction16( +    const char *name) { +  std::size_t size = sizeof(kHashFunctions16) / sizeof(kHashFunctions16[0]); +  for (std::size_t i = 0; i < size; ++i) { +    if (std::strcmp(name, kHashFunctions16[i].name) == 0) { +      return kHashFunctions16[i].function; +    } +  } +  return nullptr; +} + +inline NamedHashFunction<uint32_t>::HashFunction FindHashFunction32( +    const char *name) { +  std::size_t size = sizeof(kHashFunctions32) / sizeof(kHashFunctions32[0]); +  for (std::size_t i = 0; i < size; ++i) { +    if (std::strcmp(name, kHashFunctions32[i].name) == 0) { +      return kHashFunctions32[i].function; +    } +  } +  return nullptr; +} + +inline NamedHashFunction<uint64_t>::HashFunction FindHashFunction64( +    const char *name) { +  std::size_t size = sizeof(kHashFunctions64) / sizeof(kHashFunctions64[0]); +  for (std::size_t i = 0; i < size; ++i) { +    if (std::strcmp(name, kHashFunctions64[i].name) == 0) { +      return kHashFunctions64[i].function; +    } +  } +  return nullptr; +} + +}  // namespace flatbuffers + +#endif  // FLATBUFFERS_HASH_H_ diff --git a/host/lib/deps/flatbuffers/include/flatbuffers/idl.h b/host/lib/deps/flatbuffers/include/flatbuffers/idl.h new file mode 100644 index 000000000..8299fe0cf --- /dev/null +++ b/host/lib/deps/flatbuffers/include/flatbuffers/idl.h @@ -0,0 +1,995 @@ +/* + * 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. + */ + +#ifndef FLATBUFFERS_IDL_H_ +#define FLATBUFFERS_IDL_H_ + +#include <map> +#include <memory> +#include <stack> + +#include "flatbuffers/base.h" +#include "flatbuffers/flatbuffers.h" +#include "flatbuffers/flexbuffers.h" +#include "flatbuffers/hash.h" +#include "flatbuffers/reflection.h" + +#if !defined(FLATBUFFERS_CPP98_STL) +#  include <functional> +#endif  // !defined(FLATBUFFERS_CPP98_STL) + +// This file defines the data types representing a parsed IDL (Interface +// Definition Language) / schema file. + +// Limits maximum depth of nested objects. +// Prevents stack overflow while parse flatbuffers or json. +#if !defined(FLATBUFFERS_MAX_PARSING_DEPTH) +#  define FLATBUFFERS_MAX_PARSING_DEPTH 64 +#endif + +namespace flatbuffers { + +// The order of these matters for Is*() functions below. +// Additionally, Parser::ParseType assumes bool..string is a contiguous range +// of type tokens. +// clang-format off +#define FLATBUFFERS_GEN_TYPES_SCALAR(TD) \ +  TD(NONE,   "",       uint8_t,  byte,   byte,    byte,   uint8,   u8) \ +  TD(UTYPE,  "",       uint8_t,  byte,   byte,    byte,   uint8,   u8) /* begin scalar/int */ \ +  TD(BOOL,   "bool",   uint8_t,  boolean,bool,    bool,   bool,    bool) \ +  TD(CHAR,   "byte",   int8_t,   byte,   int8,    sbyte,  int8,    i8) \ +  TD(UCHAR,  "ubyte",  uint8_t,  byte,   byte,    byte,   uint8,   u8) \ +  TD(SHORT,  "short",  int16_t,  short,  int16,   short,  int16,   i16) \ +  TD(USHORT, "ushort", uint16_t, short,  uint16,  ushort, uint16,  u16) \ +  TD(INT,    "int",    int32_t,  int,    int32,   int,    int32,   i32) \ +  TD(UINT,   "uint",   uint32_t, int,    uint32,  uint,   uint32,  u32) \ +  TD(LONG,   "long",   int64_t,  long,   int64,   long,   int64,   i64) \ +  TD(ULONG,  "ulong",  uint64_t, long,   uint64,  ulong,  uint64,  u64) /* end int */ \ +  TD(FLOAT,  "float",  float,    float,  float32, float,  float32, f32) /* begin float */ \ +  TD(DOUBLE, "double", double,   double, float64, double, float64, f64) /* end float/scalar */ +#define FLATBUFFERS_GEN_TYPES_POINTER(TD) \ +  TD(STRING, "string", Offset<void>, int, int, StringOffset, int, unused) \ +  TD(VECTOR, "",       Offset<void>, int, int, VectorOffset, int, unused) \ +  TD(STRUCT, "",       Offset<void>, int, int, int,          int, unused) \ +  TD(UNION,  "",       Offset<void>, int, int, int,          int, unused) + +// The fields are: +// - enum +// - FlatBuffers schema type. +// - C++ type. +// - Java type. +// - Go type. +// - C# / .Net type. +// - Python type. +// - Rust type. + +// using these macros, we can now write code dealing with types just once, e.g. + +/* +switch (type) { +  #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \ +                         RTYPE) \ +    case BASE_TYPE_ ## ENUM: \ +      // do something specific to CTYPE here +    FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) +  #undef FLATBUFFERS_TD +} +*/ + +#define FLATBUFFERS_GEN_TYPES(TD) \ +        FLATBUFFERS_GEN_TYPES_SCALAR(TD) \ +        FLATBUFFERS_GEN_TYPES_POINTER(TD) + +// Create an enum for all the types above. +#ifdef __GNUC__ +__extension__  // Stop GCC complaining about trailing comma with -Wpendantic. +#endif +enum BaseType { +  #define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \ +                         RTYPE) \ +      BASE_TYPE_ ## ENUM, +    FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) +  #undef FLATBUFFERS_TD +}; + +#define FLATBUFFERS_TD(ENUM, IDLTYPE, CTYPE, JTYPE, GTYPE, NTYPE, PTYPE, \ +                       RTYPE) \ +    static_assert(sizeof(CTYPE) <= sizeof(largest_scalar_t), \ +                  "define largest_scalar_t as " #CTYPE); +  FLATBUFFERS_GEN_TYPES(FLATBUFFERS_TD) +#undef FLATBUFFERS_TD + +inline bool IsScalar (BaseType t) { return t >= BASE_TYPE_UTYPE && +                                           t <= BASE_TYPE_DOUBLE; } +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; } +inline bool IsBool   (BaseType t) { return t == BASE_TYPE_BOOL; } +inline bool IsOneByte(BaseType t) { return t >= BASE_TYPE_UTYPE && +                                           t <= BASE_TYPE_UCHAR; } +// clang-format on + +extern const char *const kTypeNames[]; +extern const char kTypeSizes[]; + +inline size_t SizeOf(BaseType t) { return kTypeSizes[t]; } + +struct StructDef; +struct EnumDef; +class Parser; + +// Represents any type in the IDL, which is a combination of the BaseType +// and additional information for vectors/structs_. +struct Type { +  explicit Type(BaseType _base_type = BASE_TYPE_NONE, StructDef *_sd = nullptr, +                EnumDef *_ed = nullptr) +      : base_type(_base_type), +        element(BASE_TYPE_NONE), +        struct_def(_sd), +        enum_def(_ed) {} + +  bool operator==(const Type &o) { +    return base_type == o.base_type && element == o.element && +           struct_def == o.struct_def && enum_def == o.enum_def; +  } + +  Type VectorType() const { return Type(element, struct_def, enum_def); } + +  Offset<reflection::Type> Serialize(FlatBufferBuilder *builder) const; + +  bool Deserialize(const Parser &parser, const reflection::Type *type); + +  BaseType base_type; +  BaseType element;       // only set if t == BASE_TYPE_VECTOR +  StructDef *struct_def;  // only set if t or element == BASE_TYPE_STRUCT +  EnumDef *enum_def;      // set if t == BASE_TYPE_UNION / BASE_TYPE_UTYPE, +                          // or for an integral type derived from an enum. +}; + +// Represents a parsed scalar value, it's type, and field offset. +struct Value { +  Value() +      : constant("0"), +        offset(static_cast<voffset_t>(~(static_cast<voffset_t>(0U)))) {} +  Type type; +  std::string constant; +  voffset_t offset; +}; + +// Helper class that retains the original order of a set of identifiers and +// also provides quick lookup. +template<typename T> class SymbolTable { + public: +  ~SymbolTable() { +    for (auto it = vec.begin(); it != vec.end(); ++it) { delete *it; } +  } + +  bool Add(const std::string &name, T *e) { +    vector_emplace_back(&vec, e); +    auto it = dict.find(name); +    if (it != dict.end()) return true; +    dict[name] = e; +    return false; +  } + +  void Move(const std::string &oldname, const std::string &newname) { +    auto it = dict.find(oldname); +    if (it != dict.end()) { +      auto obj = it->second; +      dict.erase(it); +      dict[newname] = obj; +    } else { +      FLATBUFFERS_ASSERT(false); +    } +  } + +  T *Lookup(const std::string &name) const { +    auto it = dict.find(name); +    return it == dict.end() ? nullptr : it->second; +  } + + public: +  std::map<std::string, T *> dict;  // quick lookup +  std::vector<T *> vec;             // Used to iterate in order of insertion +}; + +// A name space, as set in the schema. +struct Namespace { +  Namespace() : from_table(0) {} + +  // Given a (potentally unqualified) name, return the "fully qualified" name +  // which has a full namespaced descriptor. +  // With max_components you can request less than the number of components +  // the current namespace has. +  std::string GetFullyQualifiedName(const std::string &name, +                                    size_t max_components = 1000) const; + +  std::vector<std::string> components; +  size_t from_table;  // Part of the namespace corresponds to a message/table. +}; + +// Base class for all definition types (fields, structs_, enums_). +struct Definition { +  Definition() +      : generated(false), +        defined_namespace(nullptr), +        serialized_location(0), +        index(-1), +        refcount(1) {} + +  flatbuffers::Offset< +      flatbuffers::Vector<flatbuffers::Offset<reflection::KeyValue>>> +  SerializeAttributes(FlatBufferBuilder *builder, const Parser &parser) const; + +  bool DeserializeAttributes(Parser &parser, +                             const Vector<Offset<reflection::KeyValue>> *attrs); + +  std::string name; +  std::string file; +  std::vector<std::string> doc_comment; +  SymbolTable<Value> attributes; +  bool generated;  // did we already output code for this definition? +  Namespace *defined_namespace;  // Where it was defined. + +  // For use with Serialize() +  uoffset_t serialized_location; +  int index;  // Inside the vector it is stored. +  int refcount; +}; + +struct FieldDef : public Definition { +  FieldDef() +      : deprecated(false), +        required(false), +        key(false), +        shared(false), +        native_inline(false), +        flexbuffer(false), +        nested_flatbuffer(NULL), +        padding(0) {} + +  Offset<reflection::Field> Serialize(FlatBufferBuilder *builder, uint16_t id, +                                      const Parser &parser) const; + +  bool Deserialize(Parser &parser, const reflection::Field *field); + +  Value value; +  bool deprecated;  // Field is allowed to be present in old data, but can't be. +                    // written in new data nor accessed in new code. +  bool required;    // Field must always be present. +  bool key;         // Field functions as a key for creating sorted vectors. +  bool shared;  // Field will be using string pooling (i.e. CreateSharedString) +                // as default serialization behavior if field is a string. +  bool native_inline;  // Field will be defined inline (instead of as a pointer) +                       // for native tables if field is a struct. +  bool flexbuffer;     // This field contains FlexBuffer data. +  StructDef *nested_flatbuffer;  // This field contains nested FlatBuffer data. +  size_t padding;                // Bytes to always pad after this field. +}; + +struct StructDef : public Definition { +  StructDef() +      : fixed(false), +        predecl(true), +        sortbysize(true), +        has_key(false), +        minalign(1), +        bytesize(0) {} + +  void PadLastField(size_t min_align) { +    auto padding = PaddingBytes(bytesize, min_align); +    bytesize += padding; +    if (fields.vec.size()) fields.vec.back()->padding = padding; +  } + +  Offset<reflection::Object> Serialize(FlatBufferBuilder *builder, +                                       const Parser &parser) const; + +  bool Deserialize(Parser &parser, const reflection::Object *object); + +  SymbolTable<FieldDef> fields; + +  bool fixed;       // If it's struct, not a table. +  bool predecl;     // If it's used before it was defined. +  bool sortbysize;  // Whether fields come in the declaration or size order. +  bool has_key;     // It has a key field. +  size_t minalign;  // What the whole object needs to be aligned to. +  size_t bytesize;  // Size if fixed. + +  flatbuffers::unique_ptr<std::string> original_location; +}; + +inline bool IsStruct(const Type &type) { +  return type.base_type == BASE_TYPE_STRUCT && type.struct_def->fixed; +} + +inline size_t InlineSize(const Type &type) { +  return IsStruct(type) ? type.struct_def->bytesize : SizeOf(type.base_type); +} + +inline size_t InlineAlignment(const Type &type) { +  return IsStruct(type) ? type.struct_def->minalign : SizeOf(type.base_type); +} + +struct EnumVal { +  EnumVal(const std::string &_name, int64_t _val) : name(_name), value(_val) {} +  EnumVal() : value(0) {} + +  Offset<reflection::EnumVal> Serialize(FlatBufferBuilder *builder, const Parser &parser) const; + +  bool Deserialize(const Parser &parser, const reflection::EnumVal *val); +  bool IsZero() const { return 0 == value; } +  bool IsNonZero() const { return !IsZero(); } + +  std::string name; +  std::vector<std::string> doc_comment; +  int64_t value; +  Type union_type; +}; + +struct EnumDef : public Definition { +  EnumDef() : is_union(false), uses_multiple_type_instances(false) {} + +  EnumVal *ReverseLookup(int64_t enum_idx, bool skip_union_default = true) { +    for (auto it = Vals().begin() + +                   static_cast<int>(is_union && skip_union_default); +         it != Vals().end(); ++it) { +      if ((*it)->value == enum_idx) { return *it; } +    } +    return nullptr; +  } + +  Offset<reflection::Enum> Serialize(FlatBufferBuilder *builder, const Parser &parser) const; + +  bool Deserialize(Parser &parser, const reflection::Enum *values); + +  size_t size() const { return vals.vec.size(); } + +  const std::vector<EnumVal *> &Vals() const { +    return vals.vec; +  } + +  SymbolTable<EnumVal> vals; +  bool is_union; +  // Type is a union which uses type aliases where at least one type is +  // available under two different names. +  bool uses_multiple_type_instances; +  Type underlying_type; +}; + +inline bool EqualByName(const Type &a, const Type &b) { +  return a.base_type == b.base_type && a.element == b.element && +         (a.struct_def == b.struct_def || +          a.struct_def->name == b.struct_def->name) && +         (a.enum_def == b.enum_def || a.enum_def->name == b.enum_def->name); +} + +struct RPCCall : public Definition { +  Offset<reflection::RPCCall> Serialize(FlatBufferBuilder *builder, const Parser &parser) const; + +  bool Deserialize(Parser &parser, const reflection::RPCCall *call); + +  StructDef *request, *response; +}; + +struct ServiceDef : public Definition { +  Offset<reflection::Service> Serialize(FlatBufferBuilder *builder, const Parser &parser) const; +  bool Deserialize(Parser &parser, const reflection::Service *service); + +  SymbolTable<RPCCall> calls; +}; + +// Container of options that may apply to any of the source/text generators. +struct IDLOptions { +  bool strict_json; +  bool skip_js_exports; +  bool use_goog_js_export_format; +  bool use_ES6_js_export_format; +  bool output_default_scalars_in_json; +  int indent_step; +  bool output_enum_identifiers; +  bool prefixed_enums; +  bool scoped_enums; +  bool include_dependence_headers; +  bool mutable_buffer; +  bool one_file; +  bool proto_mode; +  bool proto_oneof_union; +  bool generate_all; +  bool skip_unexpected_fields_in_json; +  bool generate_name_strings; +  bool generate_object_based_api; +  bool gen_compare; +  std::string cpp_object_api_pointer_type; +  std::string cpp_object_api_string_type; +  bool cpp_object_api_string_flexible_constructor; +  bool gen_nullable; +  bool gen_generated; +  std::string object_prefix; +  std::string object_suffix; +  bool union_value_namespacing; +  bool allow_non_utf8; +  bool natural_utf8; +  std::string include_prefix; +  bool keep_include_path; +  bool binary_schema_comments; +  bool binary_schema_builtins; +  bool skip_flatbuffers_import; +  std::string go_import; +  std::string go_namespace; +  bool reexport_ts_modules; +  bool js_ts_short_names; +  bool protobuf_ascii_alike; +  bool size_prefixed; +  std::string root_type; +  bool force_defaults; + +  // Possible options for the more general generator below. +  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, +    kTs = 1 << 9, +    kJsonSchema = 1 << 10, +    kDart = 1 << 11, +    kLua = 1 << 12, +    kLobster = 1 << 13, +    kRust = 1 << 14, +    kMAX +  }; + +  Language lang; + +  enum MiniReflect { kNone, kTypes, kTypesAndNames }; + +  MiniReflect mini_reflect; + +  // The corresponding language bit will be set if a language is included +  // for code generation. +  unsigned long lang_to_generate; + +  // If set (default behavior), empty string and vector fields will be set to +  // nullptr to make the flatbuffer more compact. +  bool set_empty_to_null; + +  IDLOptions() +      : strict_json(false), +        skip_js_exports(false), +        use_goog_js_export_format(false), +        use_ES6_js_export_format(false), +        output_default_scalars_in_json(false), +        indent_step(2), +        output_enum_identifiers(true), +        prefixed_enums(true), +        scoped_enums(false), +        include_dependence_headers(true), +        mutable_buffer(false), +        one_file(false), +        proto_mode(false), +        proto_oneof_union(false), +        generate_all(false), +        skip_unexpected_fields_in_json(false), +        generate_name_strings(false), +        generate_object_based_api(false), +        gen_compare(false), +        cpp_object_api_pointer_type("std::unique_ptr"), +        cpp_object_api_string_flexible_constructor(false), +        gen_nullable(false), +        gen_generated(false), +        object_suffix("T"), +        union_value_namespacing(true), +        allow_non_utf8(false), +        natural_utf8(false), +        keep_include_path(false), +        binary_schema_comments(false), +        binary_schema_builtins(false), +        skip_flatbuffers_import(false), +        reexport_ts_modules(true), +        js_ts_short_names(false), +        protobuf_ascii_alike(false), +        size_prefixed(false), +        force_defaults(false), +        lang(IDLOptions::kJava), +        mini_reflect(IDLOptions::kNone), +        lang_to_generate(0), +        set_empty_to_null(true) {} +}; + +// This encapsulates where the parser is in the current source file. +struct ParserState { +  ParserState() +      : cursor_(nullptr), +        line_start_(nullptr), +        line_(0), +        token_(-1), +        attr_is_trivial_ascii_string_(true) {} + + protected: +  void ResetState(const char *source) { +    cursor_ = source; +    line_ = 0; +    MarkNewLine(); +  } + +  void MarkNewLine() { +    line_start_ = cursor_; +    line_ += 1; +  } + +  int64_t CursorPosition() const { +    FLATBUFFERS_ASSERT(cursor_ && line_start_ && cursor_ >= line_start_); +    return static_cast<int64_t>(cursor_ - line_start_); +  } + +  const char *cursor_; +  const char *line_start_; +  int line_;  // the current line being parsed +  int token_; + +  // Flag: text in attribute_ is true ASCII string without escape +  // sequences. Only printable ASCII (without [\t\r\n]). +  // Used for number-in-string (and base64 string in future). +  bool attr_is_trivial_ascii_string_; +  std::string attribute_; +  std::vector<std::string> doc_comment_; +}; + +// A way to make error propagation less error prone by requiring values to be +// checked. +// Once you create a value of this type you must either: +// - Call Check() on it. +// - Copy or assign it to another value. +// Failure to do so leads to an assert. +// This guarantees that this as return value cannot be ignored. +class CheckedError { + public: +  explicit CheckedError(bool error) +      : is_error_(error), has_been_checked_(false) {} + +  CheckedError &operator=(const CheckedError &other) { +    is_error_ = other.is_error_; +    has_been_checked_ = false; +    other.has_been_checked_ = true; +    return *this; +  } + +  CheckedError(const CheckedError &other) { +    *this = other;  // Use assignment operator. +  } + +  ~CheckedError() { FLATBUFFERS_ASSERT(has_been_checked_); } + +  bool Check() { +    has_been_checked_ = true; +    return is_error_; +  } + + private: +  bool is_error_; +  mutable bool has_been_checked_; +}; + +// Additionally, in GCC we can get these errors statically, for additional +// assurance: +// clang-format off +#ifdef __GNUC__ +#define FLATBUFFERS_CHECKED_ERROR CheckedError \ +          __attribute__((warn_unused_result)) +#else +#define FLATBUFFERS_CHECKED_ERROR CheckedError +#endif +// clang-format on + +class Parser : public ParserState { + public: +  explicit Parser(const IDLOptions &options = IDLOptions()) +      : current_namespace_(nullptr), +        empty_namespace_(nullptr), +        root_struct_def_(nullptr), +        opts(options), +        uses_flexbuffers_(false), +        source_(nullptr), +        anonymous_counter(0), +        recurse_protection_counter(0) { +    if (opts.force_defaults) { +      builder_.ForceDefaults(true); +    } +    // Start out with the empty namespace being current. +    empty_namespace_ = new Namespace(); +    namespaces_.push_back(empty_namespace_); +    current_namespace_ = empty_namespace_; +    known_attributes_["deprecated"] = true; +    known_attributes_["required"] = true; +    known_attributes_["key"] = true; +    known_attributes_["shared"] = true; +    known_attributes_["hash"] = true; +    known_attributes_["id"] = true; +    known_attributes_["force_align"] = true; +    known_attributes_["bit_flags"] = true; +    known_attributes_["original_order"] = true; +    known_attributes_["nested_flatbuffer"] = true; +    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_["cpp_ptr_type_get"] = true; +    known_attributes_["cpp_str_type"] = true; +    known_attributes_["cpp_str_flex_ctor"] = true; +    known_attributes_["native_inline"] = true; +    known_attributes_["native_custom_alloc"] = true; +    known_attributes_["native_type"] = true; +    known_attributes_["native_default"] = true; +    known_attributes_["flexbuffer"] = true; +    known_attributes_["private"] = true; +  } + +  ~Parser() { +    for (auto it = namespaces_.begin(); it != namespaces_.end(); ++it) { +      delete *it; +    } +  } + +  // Parse the string containing either schema or JSON data, which will +  // populate the SymbolTable's or the FlatBufferBuilder above. +  // include_paths is used to resolve any include statements, and typically +  // should at least include the project path (where you loaded source_ from). +  // include_paths must be nullptr terminated if specified. +  // If include_paths is nullptr, it will attempt to load from the current +  // directory. +  // If the source was loaded from a file and isn't an include file, +  // supply its name in source_filename. +  // All paths specified in this call must be in posix format, if you accept +  // paths from user input, please call PosixPath on them first. +  bool Parse(const char *_source, const char **include_paths = nullptr, +             const char *source_filename = nullptr); + +  // Set the root type. May override the one set in the schema. +  bool SetRootType(const char *name); + +  // Mark all definitions as already having code generated. +  void MarkGenerated(); + +  // Get the files recursively included by the given file. The returned +  // container will have at least the given file. +  std::set<std::string> GetIncludedFilesRecursive( +      const std::string &file_name) const; + +  // Fills builder_ with a binary version of the schema parsed. +  // See reflection/reflection.fbs +  void Serialize(); + +  // Deserialize a schema buffer +  bool Deserialize(const uint8_t *buf, const size_t size); + +  // Fills internal structure as if the schema passed had been loaded by parsing +  // with Parse except that included filenames will not be populated. +  bool Deserialize(const reflection::Schema* schema); + +  Type* DeserializeType(const reflection::Type* type); + +  // Checks that the schema represented by this parser is a safe evolution +  // of the schema provided. Returns non-empty error on any problems. +  std::string ConformTo(const Parser &base); + +  // Similar to Parse(), but now only accepts JSON to be parsed into a +  // FlexBuffer. +  bool ParseFlexBuffer(const char *source, const char *source_filename, +                       flexbuffers::Builder *builder); + +  StructDef *LookupStruct(const std::string &id) const; + +  std::string UnqualifiedName(std::string fullQualifiedName); + +  FLATBUFFERS_CHECKED_ERROR Error(const std::string &msg); + + private: +  void Message(const std::string &msg); +  void Warning(const std::string &msg); +  FLATBUFFERS_CHECKED_ERROR ParseHexNum(int nibbles, uint64_t *val); +  FLATBUFFERS_CHECKED_ERROR Next(); +  FLATBUFFERS_CHECKED_ERROR SkipByteOrderMark(); +  bool Is(int t) const; +  bool IsIdent(const char *id) const; +  FLATBUFFERS_CHECKED_ERROR Expect(int t); +  std::string TokenToStringId(int t) const; +  EnumDef *LookupEnum(const std::string &id); +  FLATBUFFERS_CHECKED_ERROR ParseNamespacing(std::string *id, +                                             std::string *last); +  FLATBUFFERS_CHECKED_ERROR ParseTypeIdent(Type &type); +  FLATBUFFERS_CHECKED_ERROR ParseType(Type &type); +  FLATBUFFERS_CHECKED_ERROR AddField(StructDef &struct_def, +                                     const std::string &name, const Type &type, +                                     FieldDef **dest); +  FLATBUFFERS_CHECKED_ERROR ParseField(StructDef &struct_def); +  FLATBUFFERS_CHECKED_ERROR ParseString(Value &val); +  FLATBUFFERS_CHECKED_ERROR ParseComma(); +  FLATBUFFERS_CHECKED_ERROR ParseAnyValue(Value &val, FieldDef *field, +                                          size_t parent_fieldn, +                                          const StructDef *parent_struct_def, +                                          uoffset_t count, +                                          bool inside_vector = false); +  template<typename F> +  FLATBUFFERS_CHECKED_ERROR ParseTableDelimiters(size_t &fieldn, +                                                 const StructDef *struct_def, +                                                 F body); +  FLATBUFFERS_CHECKED_ERROR ParseTable(const StructDef &struct_def, +                                       std::string *value, uoffset_t *ovalue); +  void SerializeStruct(const StructDef &struct_def, const Value &val); +  template<typename F> +  FLATBUFFERS_CHECKED_ERROR ParseVectorDelimiters(uoffset_t &count, F body); +  FLATBUFFERS_CHECKED_ERROR ParseVector(const Type &type, uoffset_t *ovalue, +                                        FieldDef *field, size_t fieldn); +  FLATBUFFERS_CHECKED_ERROR ParseNestedFlatbuffer(Value &val, FieldDef *field, +                                                  size_t fieldn, +                                                  const StructDef *parent_struct_def); +  FLATBUFFERS_CHECKED_ERROR ParseMetaData(SymbolTable<Value> *attributes); +  FLATBUFFERS_CHECKED_ERROR TryTypedValue(const std::string *name, int dtoken, bool check, Value &e, +                                          BaseType req, bool *destmatch); +  FLATBUFFERS_CHECKED_ERROR ParseHash(Value &e, FieldDef* field); +  FLATBUFFERS_CHECKED_ERROR TokenError(); +  FLATBUFFERS_CHECKED_ERROR ParseSingleValue(const std::string *name, Value &e, bool check_now); +  FLATBUFFERS_CHECKED_ERROR ParseEnumFromString(const Type &type, std::string *result); +  StructDef *LookupCreateStruct(const std::string &name, +                                bool create_if_new = true, +                                bool definition = false); +  FLATBUFFERS_CHECKED_ERROR ParseEnum(bool is_union, EnumDef **dest); +  FLATBUFFERS_CHECKED_ERROR ParseNamespace(); +  FLATBUFFERS_CHECKED_ERROR StartStruct(const std::string &name, +                                        StructDef **dest); +  FLATBUFFERS_CHECKED_ERROR StartEnum(const std::string &name, +                                      bool is_union, +                                      EnumDef **dest); +  FLATBUFFERS_CHECKED_ERROR ParseDecl(); +  FLATBUFFERS_CHECKED_ERROR ParseService(); +  FLATBUFFERS_CHECKED_ERROR ParseProtoFields(StructDef *struct_def, +                                             bool isextend, bool inside_oneof); +  FLATBUFFERS_CHECKED_ERROR ParseProtoOption(); +  FLATBUFFERS_CHECKED_ERROR ParseProtoKey(); +  FLATBUFFERS_CHECKED_ERROR ParseProtoDecl(); +  FLATBUFFERS_CHECKED_ERROR ParseProtoCurliesOrIdent(); +  FLATBUFFERS_CHECKED_ERROR ParseTypeFromProtoType(Type *type); +  FLATBUFFERS_CHECKED_ERROR SkipAnyJsonValue(); +  FLATBUFFERS_CHECKED_ERROR ParseFlexBufferValue(flexbuffers::Builder *builder); +  FLATBUFFERS_CHECKED_ERROR StartParseFile(const char *source, +                                           const char *source_filename); +  FLATBUFFERS_CHECKED_ERROR ParseRoot(const char *_source, +                                    const char **include_paths, +                                    const char *source_filename); +  FLATBUFFERS_CHECKED_ERROR DoParse(const char *_source, +                                           const char **include_paths, +                                           const char *source_filename, +                                           const char *include_filename); +  FLATBUFFERS_CHECKED_ERROR CheckClash(std::vector<FieldDef*> &fields, +                                       StructDef *struct_def, +                                       const char *suffix, +                                       BaseType baseType); + +  bool SupportsAdvancedUnionFeatures() const; +  Namespace *UniqueNamespace(Namespace *ns); + +  FLATBUFFERS_CHECKED_ERROR RecurseError(); +  template<typename F> CheckedError Recurse(F f); + + public: +  SymbolTable<Type> types_; +  SymbolTable<StructDef> structs_; +  SymbolTable<EnumDef> enums_; +  SymbolTable<ServiceDef> services_; +  std::vector<Namespace *> namespaces_; +  Namespace *current_namespace_; +  Namespace *empty_namespace_; +  std::string error_;         // User readable error_ if Parse() == false + +  FlatBufferBuilder builder_;  // any data contained in the file +  StructDef *root_struct_def_; +  std::string file_identifier_; +  std::string file_extension_; + +  std::map<std::string, std::string> included_files_; +  std::map<std::string, std::set<std::string>> files_included_per_file_; +  std::vector<std::string> native_included_files_; + +  std::map<std::string, bool> known_attributes_; + +  IDLOptions opts; +  bool uses_flexbuffers_; + + private: +  const char *source_; + +  std::string file_being_parsed_; + +  std::vector<std::pair<Value, FieldDef *>> field_stack_; + +  int anonymous_counter; +  int recurse_protection_counter; +}; + +// Utility functions for multiple generators: + +extern std::string MakeCamel(const std::string &in, bool first = true); + +// 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. +// If the flatbuffer cannot be encoded in JSON (e.g., it contains non-UTF-8 +// byte arrays in String values), returns false. +extern bool GenerateTextFromTable(const Parser &parser, +                                  const void *table, +                                  const std::string &tablename, +                                  std::string *text); +extern bool GenerateText(const Parser &parser, +                         const void *flatbuffer, +                         std::string *text); +extern bool GenerateTextFile(const Parser &parser, +                             const std::string &path, +                             const std::string &file_name); + +// Generate binary files from a given FlatBuffer, and a given Parser +// object that has been populated with the corresponding schema. +// See idl_gen_general.cpp. +extern bool GenerateBinary(const Parser &parser, +                           const std::string &path, +                           const std::string &file_name); + +// Generate a C++ header from the definitions in the Parser object. +// See idl_gen_cpp. +extern bool GenerateCPP(const Parser &parser, +                        const std::string &path, +                        const std::string &file_name); + +extern bool GenerateDart(const Parser &parser, +                         const std::string &path, +                         const std::string &file_name); + +// Generate JavaScript or TypeScript code from the definitions in the Parser object. +// See idl_gen_js. +extern bool GenerateJSTS(const Parser &parser, +                       const std::string &path, +                       const std::string &file_name); + +// Generate Go files from the definitions in the Parser object. +// See idl_gen_go.cpp. +extern bool GenerateGo(const Parser &parser, +                       const std::string &path, +                       const std::string &file_name); + +// Generate Php code from the definitions in the Parser object. +// See idl_gen_php. +extern bool GeneratePhp(const Parser &parser, +                        const std::string &path, +                        const std::string &file_name); + +// Generate Python files from the definitions in the Parser object. +// See idl_gen_python.cpp. +extern bool GeneratePython(const Parser &parser, +                           const std::string &path, +                           const std::string &file_name); + +// Generate Lobster files from the definitions in the Parser object. +// See idl_gen_lobster.cpp. +extern bool GenerateLobster(const Parser &parser, +                            const std::string &path, +                            const std::string &file_name); + +// Generate Lua files from the definitions in the Parser object. +// See idl_gen_lua.cpp. +extern bool GenerateLua(const Parser &parser, +                      const std::string &path, +                      const std::string &file_name); + +// Generate Rust files from the definitions in the Parser object. +// See idl_gen_rust.cpp. +extern bool GenerateRust(const Parser &parser, +                         const std::string &path, +                         const std::string &file_name); + +// Generate Json schema file +// See idl_gen_json_schema.cpp. +extern bool GenerateJsonSchema(const Parser &parser, +                           const std::string &path, +                           const std::string &file_name); + +// Generate Java/C#/.. files from the definitions in the Parser object. +// See idl_gen_general.cpp. +extern bool GenerateGeneral(const Parser &parser, +                            const std::string &path, +                            const std::string &file_name); + +// Generate a schema file from the internal representation, useful after +// parsing a .proto schema. +extern std::string GenerateFBS(const Parser &parser, +                               const std::string &file_name); +extern bool GenerateFBS(const Parser &parser, +                        const std::string &path, +                        const std::string &file_name); + +// Generate a make rule for the generated JavaScript or TypeScript code. +// See idl_gen_js.cpp. +extern std::string JSTSMakeRule(const Parser &parser, +                              const std::string &path, +                              const std::string &file_name); + +// Generate a make rule for the generated C++ header. +// See idl_gen_cpp.cpp. +extern std::string CPPMakeRule(const Parser &parser, +                               const std::string &path, +                               const std::string &file_name); + +// Generate a make rule for the generated Dart code +// see idl_gen_dart.cpp +extern std::string DartMakeRule(const Parser &parser, +                                const std::string &path, +                                const std::string &file_name); + +// Generate a make rule for the generated Rust code. +// See idl_gen_rust.cpp. +extern std::string RustMakeRule(const Parser &parser, +                                const std::string &path, +                                const std::string &file_name); + +// Generate a make rule for the generated Java/C#/... files. +// See idl_gen_general.cpp. +extern std::string GeneralMakeRule(const Parser &parser, +                                   const std::string &path, +                                   const std::string &file_name); + +// Generate a make rule for the generated text (JSON) files. +// See idl_gen_text.cpp. +extern std::string TextMakeRule(const Parser &parser, +                                const std::string &path, +                                const std::string &file_names); + +// Generate a make rule for the generated binary files. +// See idl_gen_general.cpp. +extern std::string BinaryMakeRule(const Parser &parser, +                                  const std::string &path, +                                  const std::string &file_name); + +// Generate GRPC Cpp interfaces. +// See idl_gen_grpc.cpp. +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); + +// Generate GRPC Java classes. +// See idl_gen_grpc.cpp +bool GenerateJavaGRPC(const Parser &parser, +                      const std::string &path, +                      const std::string &file_name); + +}  // namespace flatbuffers + +#endif  // FLATBUFFERS_IDL_H_ diff --git a/host/lib/deps/flatbuffers/include/flatbuffers/minireflect.h b/host/lib/deps/flatbuffers/include/flatbuffers/minireflect.h new file mode 100644 index 000000000..9d648ec08 --- /dev/null +++ b/host/lib/deps/flatbuffers/include/flatbuffers/minireflect.h @@ -0,0 +1,407 @@ +/* + * Copyright 2017 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_MINIREFLECT_H_ +#define FLATBUFFERS_MINIREFLECT_H_ + +#include "flatbuffers/flatbuffers.h" +#include "flatbuffers/util.h" + +namespace flatbuffers { + +// Utilities that can be used with the "mini reflection" tables present +// in generated code with --reflect-types (only types) or --reflect-names +// (also names). +// This allows basic reflection functionality such as pretty-printing +// that does not require the use of the schema parser or loading of binary +// schema files at runtime (reflection.h). + +// For any of the functions below that take `const TypeTable *`, you pass +// `FooTypeTable()` if the type of the root is `Foo`. + +// First, a generic iterator that can be used by multiple algorithms. + +struct IterationVisitor { +  // These mark the scope of a table or struct. +  virtual void StartSequence() {} +  virtual void EndSequence() {} +  // Called for each field regardless of wether it is present or not. +  // If not present, val == nullptr. set_idx is the index of all set fields. +  virtual void Field(size_t /*field_idx*/, size_t /*set_idx*/, +                     ElementaryType /*type*/, bool /*is_vector*/, +                     const TypeTable * /*type_table*/, const char * /*name*/, +                     const uint8_t * /*val*/) {} +  // Called for a value that is actually present, after a field, or as part +  // of a vector. +  virtual void UType(uint8_t, const char *) {} +  virtual void Bool(bool) {} +  virtual void Char(int8_t, const char *) {} +  virtual void UChar(uint8_t, const char *) {} +  virtual void Short(int16_t, const char *) {} +  virtual void UShort(uint16_t, const char *) {} +  virtual void Int(int32_t, const char *) {} +  virtual void UInt(uint32_t, const char *) {} +  virtual void Long(int64_t) {} +  virtual void ULong(uint64_t) {} +  virtual void Float(float) {} +  virtual void Double(double) {} +  virtual void String(const String *) {} +  virtual void Unknown(const uint8_t *) {}  // From a future version. +  // These mark the scope of a vector. +  virtual void StartVector() {} +  virtual void EndVector() {} +  virtual void Element(size_t /*i*/, ElementaryType /*type*/, +                       const TypeTable * /*type_table*/, +                       const uint8_t * /*val*/) {} +  virtual ~IterationVisitor() {} +}; + +inline size_t InlineSize(ElementaryType type, const TypeTable *type_table) { +  switch (type) { +    case ET_UTYPE: +    case ET_BOOL: +    case ET_CHAR: +    case ET_UCHAR: return 1; +    case ET_SHORT: +    case ET_USHORT: return 2; +    case ET_INT: +    case ET_UINT: +    case ET_FLOAT: +    case ET_STRING: return 4; +    case ET_LONG: +    case ET_ULONG: +    case ET_DOUBLE: return 8; +    case ET_SEQUENCE: +      switch (type_table->st) { +        case ST_TABLE: +        case ST_UNION: return 4; +        case ST_STRUCT: return static_cast<size_t>(type_table->values[type_table->num_elems]); +        default: FLATBUFFERS_ASSERT(false); return 1; +      } +    default: FLATBUFFERS_ASSERT(false); return 1; +  } +} + +inline int64_t LookupEnum(int64_t enum_val, const int64_t *values, +                          size_t num_values) { +  if (!values) return enum_val; +  for (size_t i = 0; i < num_values; i++) { +    if (enum_val == values[i]) return static_cast<int64_t>(i); +  } +  return -1;  // Unknown enum value. +} + +template<typename T> const char *EnumName(T tval, const TypeTable *type_table) { +  if (!type_table || !type_table->names) return nullptr; +  auto i = LookupEnum(static_cast<int64_t>(tval), type_table->values, +                      type_table->num_elems); +  if (i >= 0 && i < static_cast<int64_t>(type_table->num_elems)) { +    return type_table->names[i]; +  } +  return nullptr; +} + +void IterateObject(const uint8_t *obj, const TypeTable *type_table, +                   IterationVisitor *visitor); + +inline void IterateValue(ElementaryType type, const uint8_t *val, +                         const TypeTable *type_table, const uint8_t *prev_val, +                         soffset_t vector_index, IterationVisitor *visitor) { +  switch (type) { +    case ET_UTYPE: { +      auto tval = ReadScalar<uint8_t>(val); +      visitor->UType(tval, EnumName(tval, type_table)); +      break; +    } +    case ET_BOOL: { +      visitor->Bool(ReadScalar<uint8_t>(val) != 0); +      break; +    } +    case ET_CHAR: { +      auto tval = ReadScalar<int8_t>(val); +      visitor->Char(tval, EnumName(tval, type_table)); +      break; +    } +    case ET_UCHAR: { +      auto tval = ReadScalar<uint8_t>(val); +      visitor->UChar(tval, EnumName(tval, type_table)); +      break; +    } +    case ET_SHORT: { +      auto tval = ReadScalar<int16_t>(val); +      visitor->Short(tval, EnumName(tval, type_table)); +      break; +    } +    case ET_USHORT: { +      auto tval = ReadScalar<uint16_t>(val); +      visitor->UShort(tval, EnumName(tval, type_table)); +      break; +    } +    case ET_INT: { +      auto tval = ReadScalar<int32_t>(val); +      visitor->Int(tval, EnumName(tval, type_table)); +      break; +    } +    case ET_UINT: { +      auto tval = ReadScalar<uint32_t>(val); +      visitor->UInt(tval, EnumName(tval, type_table)); +      break; +    } +    case ET_LONG: { +      visitor->Long(ReadScalar<int64_t>(val)); +      break; +    } +    case ET_ULONG: { +      visitor->ULong(ReadScalar<uint64_t>(val)); +      break; +    } +    case ET_FLOAT: { +      visitor->Float(ReadScalar<float>(val)); +      break; +    } +    case ET_DOUBLE: { +      visitor->Double(ReadScalar<double>(val)); +      break; +    } +    case ET_STRING: { +      val += ReadScalar<uoffset_t>(val); +      visitor->String(reinterpret_cast<const String *>(val)); +      break; +    } +    case ET_SEQUENCE: { +      switch (type_table->st) { +        case ST_TABLE: +          val += ReadScalar<uoffset_t>(val); +          IterateObject(val, type_table, visitor); +          break; +        case ST_STRUCT: IterateObject(val, type_table, visitor); break; +        case ST_UNION: { +          val += ReadScalar<uoffset_t>(val); +          FLATBUFFERS_ASSERT(prev_val); +          auto union_type = *prev_val;  // Always a uint8_t. +          if (vector_index >= 0) { +            auto type_vec = reinterpret_cast<const Vector<uint8_t> *>(prev_val); +            union_type = type_vec->Get(static_cast<uoffset_t>(vector_index)); +          } +          auto type_code_idx = +              LookupEnum(union_type, type_table->values, type_table->num_elems); +          if (type_code_idx >= 0 && +              type_code_idx < static_cast<int32_t>(type_table->num_elems)) { +            auto type_code = type_table->type_codes[type_code_idx]; +            switch (type_code.base_type) { +              case ET_SEQUENCE: { +                auto ref = type_table->type_refs[type_code.sequence_ref](); +                IterateObject(val, ref, visitor); +                break; +              } +              case ET_STRING: +                visitor->String(reinterpret_cast<const String *>(val)); +                break; +              default: visitor->Unknown(val); +            } +          } else { +            visitor->Unknown(val); +          } +          break; +        } +        case ST_ENUM: FLATBUFFERS_ASSERT(false); break; +      } +      break; +    } +    default: { +      visitor->Unknown(val); +      break; +    } +  } +} + +inline void IterateObject(const uint8_t *obj, const TypeTable *type_table, +                          IterationVisitor *visitor) { +  visitor->StartSequence(); +  const uint8_t *prev_val = nullptr; +  size_t set_idx = 0; +  for (size_t i = 0; i < type_table->num_elems; i++) { +    auto type_code = type_table->type_codes[i]; +    auto type = static_cast<ElementaryType>(type_code.base_type); +    auto is_vector = type_code.is_vector != 0; +    auto ref_idx = type_code.sequence_ref; +    const TypeTable *ref = nullptr; +    if (ref_idx >= 0) { ref = type_table->type_refs[ref_idx](); } +    auto name = type_table->names ? type_table->names[i] : nullptr; +    const uint8_t *val = nullptr; +    if (type_table->st == ST_TABLE) { +      val = reinterpret_cast<const Table *>(obj)->GetAddressOf( +          FieldIndexToOffset(static_cast<voffset_t>(i))); +    } else { +      val = obj + type_table->values[i]; +    } +    visitor->Field(i, set_idx, type, is_vector, ref, name, val); +    if (val) { +      set_idx++; +      if (is_vector) { +        val += ReadScalar<uoffset_t>(val); +        auto vec = reinterpret_cast<const Vector<uint8_t> *>(val); +        visitor->StartVector(); +        auto elem_ptr = vec->Data(); +        for (size_t j = 0; j < vec->size(); j++) { +          visitor->Element(j, type, ref, elem_ptr); +          IterateValue(type, elem_ptr, ref, prev_val, static_cast<soffset_t>(j), +                       visitor); +          elem_ptr += InlineSize(type, ref); +        } +        visitor->EndVector(); +      } else { +        IterateValue(type, val, ref, prev_val, -1, visitor); +      } +    } +    prev_val = val; +  } +  visitor->EndSequence(); +} + +inline void IterateFlatBuffer(const uint8_t *buffer, +                              const TypeTable *type_table, +                              IterationVisitor *callback) { +  IterateObject(GetRoot<uint8_t>(buffer), type_table, callback); +} + +// Outputting a Flatbuffer to a string. Tries to conform as close to JSON / +// the output generated by idl_gen_text.cpp. + +struct ToStringVisitor : public IterationVisitor { +  std::string s; +  std::string d; +  bool q; +  std::string in; +  size_t indent_level; +  bool vector_delimited; +  ToStringVisitor(std::string delimiter, bool quotes, std::string indent, +                  bool vdelimited = true) +      : d(delimiter), +        q(quotes), +        in(indent), +        indent_level(0), +        vector_delimited(vdelimited) {} +  ToStringVisitor(std::string delimiter) +      : d(delimiter), +        q(false), +        in(""), +        indent_level(0), +        vector_delimited(true) {} + +  void append_indent() { +    for (size_t i = 0; i < indent_level; i++) { s += in; } +  } + +  void StartSequence() { +    s += "{"; +    s += d; +    indent_level++; +  } +  void EndSequence() { +    s += d; +    indent_level--; +    append_indent(); +    s += "}"; +  } +  void Field(size_t /*field_idx*/, size_t set_idx, ElementaryType /*type*/, +             bool /*is_vector*/, const TypeTable * /*type_table*/, +             const char *name, const uint8_t *val) { +    if (!val) return; +    if (set_idx) { +      s += ","; +      s += d; +    } +    append_indent(); +    if (name) { +      if (q) s += "\""; +      s += name; +      if (q) s += "\""; +      s += ": "; +    } +  } +  template<typename T> void Named(T x, const char *name) { +    if (name) { +      if (q) s += "\""; +      s += name; +      if (q) s += "\""; +    } else { +      s += NumToString(x); +    } +  } +  void UType(uint8_t x, const char *name) { Named(x, name); } +  void Bool(bool x) { s += x ? "true" : "false"; } +  void Char(int8_t x, const char *name) { Named(x, name); } +  void UChar(uint8_t x, const char *name) { Named(x, name); } +  void Short(int16_t x, const char *name) { Named(x, name); } +  void UShort(uint16_t x, const char *name) { Named(x, name); } +  void Int(int32_t x, const char *name) { Named(x, name); } +  void UInt(uint32_t x, const char *name) { Named(x, name); } +  void Long(int64_t x) { s += NumToString(x); } +  void ULong(uint64_t x) { s += NumToString(x); } +  void Float(float x) { s += NumToString(x); } +  void Double(double x) { s += NumToString(x); } +  void String(const struct String *str) { +    EscapeString(str->c_str(), str->size(), &s, true, false); +  } +  void Unknown(const uint8_t *) { s += "(?)"; } +  void StartVector() { +    s += "["; +    if (vector_delimited) { +      s += d; +      indent_level++; +      append_indent(); +    } else { +      s += " "; +    } +  } +  void EndVector() { +    if (vector_delimited) { +      s += d; +      indent_level--; +      append_indent(); +    } else { +      s += " "; +    } +    s += "]"; +  } +  void Element(size_t i, ElementaryType /*type*/, +               const TypeTable * /*type_table*/, const uint8_t * /*val*/) { +    if (i) { +      s += ","; +      if (vector_delimited) { +        s += d; +        append_indent(); +      } else { +        s += " "; +      } +    } +  } +}; + +inline std::string FlatBufferToString(const uint8_t *buffer, +                                      const TypeTable *type_table, +                                      bool multi_line = false, +                                      bool vector_delimited = true) { +  ToStringVisitor tostring_visitor(multi_line ? "\n" : " ", false, "", +                                   vector_delimited); +  IterateFlatBuffer(buffer, type_table, &tostring_visitor); +  return tostring_visitor.s; +} + +}  // namespace flatbuffers + +#endif  // FLATBUFFERS_MINIREFLECT_H_ diff --git a/host/lib/deps/flatbuffers/include/flatbuffers/reflection.h b/host/lib/deps/flatbuffers/include/flatbuffers/reflection.h new file mode 100644 index 000000000..580ae624b --- /dev/null +++ b/host/lib/deps/flatbuffers/include/flatbuffers/reflection.h @@ -0,0 +1,477 @@ +/* + * Copyright 2015 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_REFLECTION_H_ +#define FLATBUFFERS_REFLECTION_H_ + +// This is somewhat of a circular dependency because flatc (and thus this +// file) is needed to generate this header in the first place. +// Should normally not be a problem since it can be generated by the +// previous version of flatc whenever this code needs to change. +// See reflection/generate_code.sh +#include "flatbuffers/reflection_generated.h" + +// Helper functionality for reflection. + +namespace flatbuffers { + +// ------------------------- GETTERS ------------------------- + +inline bool IsScalar(reflection::BaseType t) { +  return t >= reflection::UType && t <= reflection::Double; +} +inline bool IsInteger(reflection::BaseType t) { +  return t >= reflection::UType && t <= reflection::ULong; +} +inline bool IsFloat(reflection::BaseType t) { +  return t == reflection::Float || t == reflection::Double; +} +inline bool IsLong(reflection::BaseType t) { +  return t == reflection::Long || t == reflection::ULong; +} + +// Size of a basic type, don't use with structs. +inline size_t GetTypeSize(reflection::BaseType base_type) { +  // This needs to correspond to the BaseType enum. +  static size_t sizes[] = { 0, 1, 1, 1, 1, 2, 2, 4, 4, 8, 8, 4, 8, 4, 4, 4, 4 }; +  return sizes[base_type]; +} + +// Same as above, but now correctly returns the size of a struct if +// the field (or vector element) is a struct. +inline size_t GetTypeSizeInline(reflection::BaseType base_type, int type_index, +                                const reflection::Schema &schema) { +  if (base_type == reflection::Obj && +      schema.objects()->Get(type_index)->is_struct()) { +    return schema.objects()->Get(type_index)->bytesize(); +  } else { +    return GetTypeSize(base_type); +  } +} + +// Get the root, regardless of what type it is. +inline Table *GetAnyRoot(uint8_t *flatbuf) { +  return GetMutableRoot<Table>(flatbuf); +} +inline const Table *GetAnyRoot(const uint8_t *flatbuf) { +  return GetRoot<Table>(flatbuf); +} + +// Get a field's default, if you know it's an integer, and its exact type. +template<typename T> T GetFieldDefaultI(const reflection::Field &field) { +  FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type())); +  return static_cast<T>(field.default_integer()); +} + +// Get a field's default, if you know it's floating point and its exact type. +template<typename T> T GetFieldDefaultF(const reflection::Field &field) { +  FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type())); +  return static_cast<T>(field.default_real()); +} + +// Get a field, if you know it's an integer, and its exact type. +template<typename T> +T GetFieldI(const Table &table, const reflection::Field &field) { +  FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type())); +  return table.GetField<T>(field.offset(), +                           static_cast<T>(field.default_integer())); +} + +// Get a field, if you know it's floating point and its exact type. +template<typename T> +T GetFieldF(const Table &table, const reflection::Field &field) { +  FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(field.type()->base_type())); +  return table.GetField<T>(field.offset(), +                           static_cast<T>(field.default_real())); +} + +// Get a field, if you know it's a string. +inline const String *GetFieldS(const Table &table, +                               const reflection::Field &field) { +  FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::String); +  return table.GetPointer<const String *>(field.offset()); +} + +// Get a field, if you know it's a vector. +template<typename T> +Vector<T> *GetFieldV(const Table &table, const reflection::Field &field) { +  FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Vector && +                     sizeof(T) == GetTypeSize(field.type()->element())); +  return table.GetPointer<Vector<T> *>(field.offset()); +} + +// Get a field, if you know it's a vector, generically. +// To actually access elements, use the return value together with +// field.type()->element() in any of GetAnyVectorElemI below etc. +inline VectorOfAny *GetFieldAnyV(const Table &table, +                                 const reflection::Field &field) { +  return table.GetPointer<VectorOfAny *>(field.offset()); +} + +// Get a field, if you know it's a table. +inline Table *GetFieldT(const Table &table, const reflection::Field &field) { +  FLATBUFFERS_ASSERT(field.type()->base_type() == reflection::Obj || +                     field.type()->base_type() == reflection::Union); +  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. +  FLATBUFFERS_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) { +  FLATBUFFERS_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 +// data type returns 0. +int64_t GetAnyValueI(reflection::BaseType type, const uint8_t *data); +// All scalars static cast to double, strings use strtod, every other data +// type is 0.0. +double GetAnyValueF(reflection::BaseType type, const uint8_t *data); +// All scalars converted using stringstream, strings as-is, and all other +// data types provide some level of debug-pretty-printing. +std::string GetAnyValueS(reflection::BaseType type, const uint8_t *data, +                         const reflection::Schema *schema, int type_index); + +// Get any table field as a 64bit int, regardless of what type it is. +inline int64_t GetAnyFieldI(const Table &table, +                            const reflection::Field &field) { +  auto field_ptr = table.GetAddressOf(field.offset()); +  return field_ptr ? GetAnyValueI(field.type()->base_type(), field_ptr) +                   : field.default_integer(); +} + +// Get any table field as a double, regardless of what type it is. +inline double GetAnyFieldF(const Table &table, const reflection::Field &field) { +  auto field_ptr = table.GetAddressOf(field.offset()); +  return field_ptr ? GetAnyValueF(field.type()->base_type(), field_ptr) +                   : field.default_real(); +} + +// Get any table field as a string, regardless of what type it is. +// You may pass nullptr for the schema if you don't care to have fields that +// are of table type pretty-printed. +inline std::string GetAnyFieldS(const Table &table, +                                const reflection::Field &field, +                                const reflection::Schema *schema) { +  auto field_ptr = table.GetAddressOf(field.offset()); +  return field_ptr ? GetAnyValueS(field.type()->base_type(), field_ptr, schema, +                                  field.type()->index()) +                   : ""; +} + +// Get any struct field as a 64bit int, regardless of what type it is. +inline int64_t GetAnyFieldI(const Struct &st, const reflection::Field &field) { +  return GetAnyValueI(field.type()->base_type(), +                      st.GetAddressOf(field.offset())); +} + +// Get any struct field as a double, regardless of what type it is. +inline double GetAnyFieldF(const Struct &st, const reflection::Field &field) { +  return GetAnyValueF(field.type()->base_type(), +                      st.GetAddressOf(field.offset())); +} + +// Get any struct field as a string, regardless of what type it is. +inline std::string GetAnyFieldS(const Struct &st, +                                const reflection::Field &field) { +  return GetAnyValueS(field.type()->base_type(), +                      st.GetAddressOf(field.offset()), nullptr, -1); +} + +// Get any vector element as a 64bit int, regardless of what type it is. +inline int64_t GetAnyVectorElemI(const VectorOfAny *vec, +                                 reflection::BaseType elem_type, size_t i) { +  return GetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i); +} + +// Get any vector element as a double, regardless of what type it is. +inline double GetAnyVectorElemF(const VectorOfAny *vec, +                                reflection::BaseType elem_type, size_t i) { +  return GetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i); +} + +// Get any vector element as a string, regardless of what type it is. +inline std::string GetAnyVectorElemS(const VectorOfAny *vec, +                                     reflection::BaseType elem_type, size_t i) { +  return GetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i, +                      nullptr, -1); +} + +// Get a vector element that's a table/string/vector from a generic vector. +// Pass Table/String/VectorOfAny as template parameter. +// Warning: does no typechecking. +template<typename T> +T *GetAnyVectorElemPointer(const VectorOfAny *vec, size_t i) { +  auto elem_ptr = vec->Data() + sizeof(uoffset_t) * i; +  return reinterpret_cast<T*>(elem_ptr + ReadScalar<uoffset_t>(elem_ptr)); +} + +// Get the inline-address of a vector element. Useful for Structs (pass Struct +// as template arg), or being able to address a range of scalars in-line. +// Get elem_size from GetTypeSizeInline(). +// Note: little-endian data on all platforms, use EndianScalar() instead of +// raw pointer access with scalars). +template<typename T> +T *GetAnyVectorElemAddressOf(const VectorOfAny *vec, size_t i, +                             size_t elem_size) { +  return reinterpret_cast<T *>(vec->Data() + elem_size * i); +} + +// Similarly, for elements of tables. +template<typename T> +T *GetAnyFieldAddressOf(const Table &table, const reflection::Field &field) { +  return reinterpret_cast<T *>(table.GetAddressOf(field.offset())); +} + +// Similarly, for elements of structs. +template<typename T> +T *GetAnyFieldAddressOf(const Struct &st, const reflection::Field &field) { +  return reinterpret_cast<T *>(st.GetAddressOf(field.offset())); +} + +// ------------------------- SETTERS ------------------------- + +// Set any scalar field, if you know its exact type. +template<typename T> +bool SetField(Table *table, const reflection::Field &field, T val) { +  reflection::BaseType type = field.type()->base_type(); +  if (!IsScalar(type)) { return false; } +  FLATBUFFERS_ASSERT(sizeof(T) == GetTypeSize(type)); +  T def; +  if (IsInteger(type)) { +    def = GetFieldDefaultI<T>(field); +  } else { +    FLATBUFFERS_ASSERT(IsFloat(type)); +    def = GetFieldDefaultF<T>(field); +  } +  return table->SetField(field.offset(), val, def); +} + +// Raw helper functions used below: set any value in memory as a 64bit int, a +// double or a string. +// These work for all scalar values, but do nothing for other data types. +// To set a string, see SetString below. +void SetAnyValueI(reflection::BaseType type, uint8_t *data, int64_t val); +void SetAnyValueF(reflection::BaseType type, uint8_t *data, double val); +void SetAnyValueS(reflection::BaseType type, uint8_t *data, const char *val); + +// Set any table field as a 64bit int, regardless of type what it is. +inline bool SetAnyFieldI(Table *table, const reflection::Field &field, +                         int64_t val) { +  auto field_ptr = table->GetAddressOf(field.offset()); +  if (!field_ptr) return val == GetFieldDefaultI<int64_t>(field); +  SetAnyValueI(field.type()->base_type(), field_ptr, val); +  return true; +} + +// Set any table field as a double, regardless of what type it is. +inline bool SetAnyFieldF(Table *table, const reflection::Field &field, +                         double val) { +  auto field_ptr = table->GetAddressOf(field.offset()); +  if (!field_ptr) return val == GetFieldDefaultF<double>(field); +  SetAnyValueF(field.type()->base_type(), field_ptr, val); +  return true; +} + +// Set any table field as a string, regardless of what type it is. +inline bool SetAnyFieldS(Table *table, const reflection::Field &field, +                         const char *val) { +  auto field_ptr = table->GetAddressOf(field.offset()); +  if (!field_ptr) return false; +  SetAnyValueS(field.type()->base_type(), field_ptr, val); +  return true; +} + +// Set any struct field as a 64bit int, regardless of type what it is. +inline void SetAnyFieldI(Struct *st, const reflection::Field &field, +                         int64_t val) { +  SetAnyValueI(field.type()->base_type(), st->GetAddressOf(field.offset()), +               val); +} + +// Set any struct field as a double, regardless of type what it is. +inline void SetAnyFieldF(Struct *st, const reflection::Field &field, +                         double val) { +  SetAnyValueF(field.type()->base_type(), st->GetAddressOf(field.offset()), +               val); +} + +// Set any struct field as a string, regardless of type what it is. +inline void SetAnyFieldS(Struct *st, const reflection::Field &field, +                         const char *val) { +  SetAnyValueS(field.type()->base_type(), st->GetAddressOf(field.offset()), +               val); +} + +// Set any vector element as a 64bit int, regardless of type what it is. +inline void SetAnyVectorElemI(VectorOfAny *vec, reflection::BaseType elem_type, +                              size_t i, int64_t val) { +  SetAnyValueI(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val); +} + +// Set any vector element as a double, regardless of type what it is. +inline void SetAnyVectorElemF(VectorOfAny *vec, reflection::BaseType elem_type, +                              size_t i, double val) { +  SetAnyValueF(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val); +} + +// Set any vector element as a string, regardless of type what it is. +inline void SetAnyVectorElemS(VectorOfAny *vec, reflection::BaseType elem_type, +                              size_t i, const char *val) { +  SetAnyValueS(elem_type, vec->Data() + GetTypeSize(elem_type) * i, val); +} + +// ------------------------- RESIZING SETTERS ------------------------- + +// "smart" pointer for use with resizing vectors: turns a pointer inside +// a vector into a relative offset, such that it is not affected by resizes. +template<typename T, typename U> class pointer_inside_vector { + public: +  pointer_inside_vector(T *ptr, std::vector<U> &vec) +      : offset_(reinterpret_cast<uint8_t *>(ptr) - +                reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec))), +        vec_(vec) {} + +  T *operator*() const { +    return reinterpret_cast<T *>( +        reinterpret_cast<uint8_t *>(flatbuffers::vector_data(vec_)) + offset_); +  } +  T *operator->() const { return operator*(); } +  void operator=(const pointer_inside_vector &piv); + + private: +  size_t offset_; +  std::vector<U> &vec_; +}; + +// Helper to create the above easily without specifying template args. +template<typename T, typename U> +pointer_inside_vector<T, U> piv(T *ptr, std::vector<U> &vec) { +  return pointer_inside_vector<T, U>(ptr, vec); +} + +inline const char *UnionTypeFieldSuffix() { return "_type"; } + +// Helper to figure out the actual table type a union refers to. +inline const reflection::Object &GetUnionType( +    const reflection::Schema &schema, const reflection::Object &parent, +    const reflection::Field &unionfield, const Table &table) { +  auto enumdef = schema.enums()->Get(unionfield.type()->index()); +  // TODO: this is clumsy and slow, but no other way to find it? +  auto type_field = parent.fields()->LookupByKey( +      (unionfield.name()->str() + UnionTypeFieldSuffix()).c_str()); +  FLATBUFFERS_ASSERT(type_field); +  auto union_type = GetFieldI<uint8_t>(table, *type_field); +  auto enumval = enumdef->values()->LookupByKey(union_type); +  return *enumval->object(); +} + +// Changes the contents of a string inside a FlatBuffer. FlatBuffer must +// live inside a std::vector so we can resize the buffer if needed. +// "str" must live inside "flatbuf" and may be invalidated after this call. +// If your FlatBuffer's root table is not the schema's root table, you should +// pass in your root_table type as well. +void SetString(const reflection::Schema &schema, const std::string &val, +               const String *str, std::vector<uint8_t> *flatbuf, +               const reflection::Object *root_table = nullptr); + +// Resizes a flatbuffers::Vector inside a FlatBuffer. FlatBuffer must +// live inside a std::vector so we can resize the buffer if needed. +// "vec" must live inside "flatbuf" and may be invalidated after this call. +// If your FlatBuffer's root table is not the schema's root table, you should +// pass in your root_table type as well. +uint8_t *ResizeAnyVector(const reflection::Schema &schema, uoffset_t newsize, +                         const VectorOfAny *vec, uoffset_t num_elems, +                         uoffset_t elem_size, std::vector<uint8_t> *flatbuf, +                         const reflection::Object *root_table = nullptr); + +template<typename T> +void ResizeVector(const reflection::Schema &schema, uoffset_t newsize, T val, +                  const Vector<T> *vec, std::vector<uint8_t> *flatbuf, +                  const reflection::Object *root_table = nullptr) { +  auto delta_elem = static_cast<int>(newsize) - static_cast<int>(vec->size()); +  auto newelems = ResizeAnyVector( +      schema, newsize, reinterpret_cast<const VectorOfAny *>(vec), vec->size(), +      static_cast<uoffset_t>(sizeof(T)), flatbuf, root_table); +  // Set new elements to "val". +  for (int i = 0; i < delta_elem; i++) { +    auto loc = newelems + i * sizeof(T); +    auto is_scalar = flatbuffers::is_scalar<T>::value; +    if (is_scalar) { +      WriteScalar(loc, val); +    } else {  // struct +      *reinterpret_cast<T *>(loc) = val; +    } +  } +} + +// Adds any new data (in the form of a new FlatBuffer) to an existing +// FlatBuffer. This can be used when any of the above methods are not +// sufficient, in particular for adding new tables and new fields. +// This is potentially slightly less efficient than a FlatBuffer constructed +// in one piece, since the new FlatBuffer doesn't share any vtables with the +// existing one. +// The return value can now be set using Vector::MutateOffset or SetFieldT +// below. +const uint8_t *AddFlatBuffer(std::vector<uint8_t> &flatbuf, +                             const uint8_t *newbuf, size_t newlen); + +inline bool SetFieldT(Table *table, const reflection::Field &field, +                      const uint8_t *val) { +  FLATBUFFERS_ASSERT(sizeof(uoffset_t) == +                     GetTypeSize(field.type()->base_type())); +  return table->SetPointer(field.offset(), val); +} + +// ------------------------- COPYING ------------------------- + +// Generic copying of tables from a FlatBuffer into a FlatBuffer builder. +// Can be used to do any kind of merging/selecting you may want to do out +// of existing buffers. Also useful to reconstruct a whole buffer if the +// above resizing functionality has introduced garbage in a buffer you want +// to remove. +// Note: this does not deal with DAGs correctly. If the table passed forms a +// DAG, the copy will be a tree instead (with duplicates). Strings can be +// shared however, by passing true for use_string_pooling. + +Offset<const Table *> CopyTable(FlatBufferBuilder &fbb, +                                const reflection::Schema &schema, +                                const reflection::Object &objectdef, +                                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_ diff --git a/host/lib/deps/flatbuffers/include/flatbuffers/reflection_generated.h b/host/lib/deps/flatbuffers/include/flatbuffers/reflection_generated.h new file mode 100644 index 000000000..869a9f3f2 --- /dev/null +++ b/host/lib/deps/flatbuffers/include/flatbuffers/reflection_generated.h @@ -0,0 +1,1182 @@ +// automatically generated by the FlatBuffers compiler, do not modify + + +#ifndef FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_ +#define FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_ + +#include "flatbuffers/flatbuffers.h" + +namespace reflection { + +struct Type; + +struct KeyValue; + +struct EnumVal; + +struct Enum; + +struct Field; + +struct Object; + +struct RPCCall; + +struct Service; + +struct Schema; + +enum BaseType { +  None = 0, +  UType = 1, +  Bool = 2, +  Byte = 3, +  UByte = 4, +  Short = 5, +  UShort = 6, +  Int = 7, +  UInt = 8, +  Long = 9, +  ULong = 10, +  Float = 11, +  Double = 12, +  String = 13, +  Vector = 14, +  Obj = 15, +  Union = 16 +}; + +inline const BaseType (&EnumValuesBaseType())[17] { +  static const BaseType values[] = { +    None, +    UType, +    Bool, +    Byte, +    UByte, +    Short, +    UShort, +    Int, +    UInt, +    Long, +    ULong, +    Float, +    Double, +    String, +    Vector, +    Obj, +    Union +  }; +  return values; +} + +inline const char * const *EnumNamesBaseType() { +  static const char * const names[] = { +    "None", +    "UType", +    "Bool", +    "Byte", +    "UByte", +    "Short", +    "UShort", +    "Int", +    "UInt", +    "Long", +    "ULong", +    "Float", +    "Double", +    "String", +    "Vector", +    "Obj", +    "Union", +    nullptr +  }; +  return names; +} + +inline const char *EnumNameBaseType(BaseType e) { +  if (e < None || e > Union) return ""; +  const size_t index = static_cast<size_t>(e); +  return EnumNamesBaseType()[index]; +} + +struct Type FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { +  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { +    VT_BASE_TYPE = 4, +    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); +  } +  bool Verify(flatbuffers::Verifier &verifier) const { +    return VerifyTableStart(verifier) && +           VerifyField<int8_t>(verifier, VT_BASE_TYPE) && +           VerifyField<int8_t>(verifier, VT_ELEMENT) && +           VerifyField<int32_t>(verifier, VT_INDEX) && +           verifier.EndTable(); +  } +}; + +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); +  } +  explicit TypeBuilder(flatbuffers::FlatBufferBuilder &_fbb) +        : fbb_(_fbb) { +    start_ = fbb_.StartTable(); +  } +  TypeBuilder &operator=(const TypeBuilder &); +  flatbuffers::Offset<Type> Finish() { +    const auto end = fbb_.EndTable(start_); +    auto o = flatbuffers::Offset<Type>(end); +    return o; +  } +}; + +inline flatbuffers::Offset<Type> CreateType( +    flatbuffers::FlatBufferBuilder &_fbb, +    BaseType base_type = None, +    BaseType element = None, +    int32_t index = -1) { +  TypeBuilder builder_(_fbb); +  builder_.add_index(index); +  builder_.add_element(element); +  builder_.add_base_type(base_type); +  return builder_.Finish(); +} + +struct KeyValue FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { +  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { +    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); +  } +  bool Verify(flatbuffers::Verifier &verifier) const { +    return VerifyTableStart(verifier) && +           VerifyOffsetRequired(verifier, VT_KEY) && +           verifier.VerifyString(key()) && +           VerifyOffset(verifier, VT_VALUE) && +           verifier.VerifyString(value()) && +           verifier.EndTable(); +  } +}; + +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); +  } +  explicit KeyValueBuilder(flatbuffers::FlatBufferBuilder &_fbb) +        : fbb_(_fbb) { +    start_ = fbb_.StartTable(); +  } +  KeyValueBuilder &operator=(const KeyValueBuilder &); +  flatbuffers::Offset<KeyValue> Finish() { +    const auto end = fbb_.EndTable(start_); +    auto o = flatbuffers::Offset<KeyValue>(end); +    fbb_.Required(o, KeyValue::VT_KEY); +    return o; +  } +}; + +inline flatbuffers::Offset<KeyValue> CreateKeyValue( +    flatbuffers::FlatBufferBuilder &_fbb, +    flatbuffers::Offset<flatbuffers::String> key = 0, +    flatbuffers::Offset<flatbuffers::String> value = 0) { +  KeyValueBuilder builder_(_fbb); +  builder_.add_value(value); +  builder_.add_key(key); +  return builder_.Finish(); +} + +inline flatbuffers::Offset<KeyValue> CreateKeyValueDirect( +    flatbuffers::FlatBufferBuilder &_fbb, +    const char *key = nullptr, +    const char *value = nullptr) { +  auto key__ = key ? _fbb.CreateString(key) : 0; +  auto value__ = value ? _fbb.CreateString(value) : 0; +  return reflection::CreateKeyValue( +      _fbb, +      key__, +      value__); +} + +struct EnumVal FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { +  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { +    VT_NAME = 4, +    VT_VALUE = 6, +    VT_OBJECT = 8, +    VT_UNION_TYPE = 10, +    VT_DOCUMENTATION = 12 +  }; +  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 static_cast<int>(value() > val) - static_cast<int>(value() < val); +  } +  const Object *object() const { +    return GetPointer<const Object *>(VT_OBJECT); +  } +  const Type *union_type() const { +    return GetPointer<const Type *>(VT_UNION_TYPE); +  } +  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) && +           VerifyOffsetRequired(verifier, VT_NAME) && +           verifier.VerifyString(name()) && +           VerifyField<int64_t>(verifier, VT_VALUE) && +           VerifyOffset(verifier, VT_OBJECT) && +           verifier.VerifyTable(object()) && +           VerifyOffset(verifier, VT_UNION_TYPE) && +           verifier.VerifyTable(union_type()) && +           VerifyOffset(verifier, VT_DOCUMENTATION) && +           verifier.VerifyVector(documentation()) && +           verifier.VerifyVectorOfStrings(documentation()) && +           verifier.EndTable(); +  } +}; + +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); +  } +  void add_union_type(flatbuffers::Offset<Type> union_type) { +    fbb_.AddOffset(EnumVal::VT_UNION_TYPE, union_type); +  } +  void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) { +    fbb_.AddOffset(EnumVal::VT_DOCUMENTATION, documentation); +  } +  explicit EnumValBuilder(flatbuffers::FlatBufferBuilder &_fbb) +        : fbb_(_fbb) { +    start_ = fbb_.StartTable(); +  } +  EnumValBuilder &operator=(const EnumValBuilder &); +  flatbuffers::Offset<EnumVal> Finish() { +    const auto end = fbb_.EndTable(start_); +    auto o = flatbuffers::Offset<EnumVal>(end); +    fbb_.Required(o, EnumVal::VT_NAME); +    return o; +  } +}; + +inline flatbuffers::Offset<EnumVal> CreateEnumVal( +    flatbuffers::FlatBufferBuilder &_fbb, +    flatbuffers::Offset<flatbuffers::String> name = 0, +    int64_t value = 0, +    flatbuffers::Offset<Object> object = 0, +    flatbuffers::Offset<Type> union_type = 0, +    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) { +  EnumValBuilder builder_(_fbb); +  builder_.add_value(value); +  builder_.add_documentation(documentation); +  builder_.add_union_type(union_type); +  builder_.add_object(object); +  builder_.add_name(name); +  return builder_.Finish(); +} + +inline flatbuffers::Offset<EnumVal> CreateEnumValDirect( +    flatbuffers::FlatBufferBuilder &_fbb, +    const char *name = nullptr, +    int64_t value = 0, +    flatbuffers::Offset<Object> object = 0, +    flatbuffers::Offset<Type> union_type = 0, +    const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) { +  auto name__ = name ? _fbb.CreateString(name) : 0; +  auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0; +  return reflection::CreateEnumVal( +      _fbb, +      name__, +      value, +      object, +      union_type, +      documentation__); +} + +struct Enum FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { +  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { +    VT_NAME = 4, +    VT_VALUES = 6, +    VT_IS_UNION = 8, +    VT_UNDERLYING_TYPE = 10, +    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::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) && +           VerifyOffsetRequired(verifier, VT_NAME) && +           verifier.VerifyString(name()) && +           VerifyOffsetRequired(verifier, VT_VALUES) && +           verifier.VerifyVector(values()) && +           verifier.VerifyVectorOfTables(values()) && +           VerifyField<uint8_t>(verifier, VT_IS_UNION) && +           VerifyOffsetRequired(verifier, VT_UNDERLYING_TYPE) && +           verifier.VerifyTable(underlying_type()) && +           VerifyOffset(verifier, VT_ATTRIBUTES) && +           verifier.VerifyVector(attributes()) && +           verifier.VerifyVectorOfTables(attributes()) && +           VerifyOffset(verifier, VT_DOCUMENTATION) && +           verifier.VerifyVector(documentation()) && +           verifier.VerifyVectorOfStrings(documentation()) && +           verifier.EndTable(); +  } +}; + +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); +  } +  void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) { +    fbb_.AddOffset(Enum::VT_DOCUMENTATION, documentation); +  } +  explicit EnumBuilder(flatbuffers::FlatBufferBuilder &_fbb) +        : fbb_(_fbb) { +    start_ = fbb_.StartTable(); +  } +  EnumBuilder &operator=(const EnumBuilder &); +  flatbuffers::Offset<Enum> Finish() { +    const auto end = fbb_.EndTable(start_); +    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, +    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<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); +  builder_.add_name(name); +  builder_.add_is_union(is_union); +  return builder_.Finish(); +} + +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, +    const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) { +  auto name__ = name ? _fbb.CreateString(name) : 0; +  auto values__ = values ? _fbb.CreateVector<flatbuffers::Offset<EnumVal>>(*values) : 0; +  auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0; +  auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0; +  return reflection::CreateEnum( +      _fbb, +      name__, +      values__, +      is_union, +      underlying_type, +      attributes__, +      documentation__); +} + +struct Field FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { +  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { +    VT_NAME = 4, +    VT_TYPE = 6, +    VT_ID = 8, +    VT_OFFSET = 10, +    VT_DEFAULT_INTEGER = 12, +    VT_DEFAULT_REAL = 14, +    VT_DEPRECATED = 16, +    VT_REQUIRED = 18, +    VT_KEY = 20, +    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::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) && +           VerifyOffsetRequired(verifier, VT_NAME) && +           verifier.VerifyString(name()) && +           VerifyOffsetRequired(verifier, VT_TYPE) && +           verifier.VerifyTable(type()) && +           VerifyField<uint16_t>(verifier, VT_ID) && +           VerifyField<uint16_t>(verifier, VT_OFFSET) && +           VerifyField<int64_t>(verifier, VT_DEFAULT_INTEGER) && +           VerifyField<double>(verifier, VT_DEFAULT_REAL) && +           VerifyField<uint8_t>(verifier, VT_DEPRECATED) && +           VerifyField<uint8_t>(verifier, VT_REQUIRED) && +           VerifyField<uint8_t>(verifier, VT_KEY) && +           VerifyOffset(verifier, VT_ATTRIBUTES) && +           verifier.VerifyVector(attributes()) && +           verifier.VerifyVectorOfTables(attributes()) && +           VerifyOffset(verifier, VT_DOCUMENTATION) && +           verifier.VerifyVector(documentation()) && +           verifier.VerifyVectorOfStrings(documentation()) && +           verifier.EndTable(); +  } +}; + +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); +  } +  void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) { +    fbb_.AddOffset(Field::VT_DOCUMENTATION, documentation); +  } +  explicit FieldBuilder(flatbuffers::FlatBufferBuilder &_fbb) +        : fbb_(_fbb) { +    start_ = fbb_.StartTable(); +  } +  FieldBuilder &operator=(const FieldBuilder &); +  flatbuffers::Offset<Field> Finish() { +    const auto end = fbb_.EndTable(start_); +    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, +    flatbuffers::Offset<flatbuffers::String> name = 0, +    flatbuffers::Offset<Type> type = 0, +    uint16_t id = 0, +    uint16_t offset = 0, +    int64_t default_integer = 0, +    double default_real = 0.0, +    bool deprecated = false, +    bool required = false, +    bool key = false, +    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); +  builder_.add_offset(offset); +  builder_.add_id(id); +  builder_.add_key(key); +  builder_.add_required(required); +  builder_.add_deprecated(deprecated); +  return builder_.Finish(); +} + +inline flatbuffers::Offset<Field> CreateFieldDirect( +    flatbuffers::FlatBufferBuilder &_fbb, +    const char *name = nullptr, +    flatbuffers::Offset<Type> type = 0, +    uint16_t id = 0, +    uint16_t offset = 0, +    int64_t default_integer = 0, +    double default_real = 0.0, +    bool deprecated = false, +    bool required = false, +    bool key = false, +    const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr, +    const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) { +  auto name__ = name ? _fbb.CreateString(name) : 0; +  auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0; +  auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0; +  return reflection::CreateField( +      _fbb, +      name__, +      type, +      id, +      offset, +      default_integer, +      default_real, +      deprecated, +      required, +      key, +      attributes__, +      documentation__); +} + +struct Object FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { +  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { +    VT_NAME = 4, +    VT_FIELDS = 6, +    VT_IS_STRUCT = 8, +    VT_MINALIGN = 10, +    VT_BYTESIZE = 12, +    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::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) && +           VerifyOffsetRequired(verifier, VT_NAME) && +           verifier.VerifyString(name()) && +           VerifyOffsetRequired(verifier, VT_FIELDS) && +           verifier.VerifyVector(fields()) && +           verifier.VerifyVectorOfTables(fields()) && +           VerifyField<uint8_t>(verifier, VT_IS_STRUCT) && +           VerifyField<int32_t>(verifier, VT_MINALIGN) && +           VerifyField<int32_t>(verifier, VT_BYTESIZE) && +           VerifyOffset(verifier, VT_ATTRIBUTES) && +           verifier.VerifyVector(attributes()) && +           verifier.VerifyVectorOfTables(attributes()) && +           VerifyOffset(verifier, VT_DOCUMENTATION) && +           verifier.VerifyVector(documentation()) && +           verifier.VerifyVectorOfStrings(documentation()) && +           verifier.EndTable(); +  } +}; + +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); +  } +  void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) { +    fbb_.AddOffset(Object::VT_DOCUMENTATION, documentation); +  } +  explicit ObjectBuilder(flatbuffers::FlatBufferBuilder &_fbb) +        : fbb_(_fbb) { +    start_ = fbb_.StartTable(); +  } +  ObjectBuilder &operator=(const ObjectBuilder &); +  flatbuffers::Offset<Object> Finish() { +    const auto end = fbb_.EndTable(start_); +    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, +    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<flatbuffers::String>>> documentation = 0) { +  ObjectBuilder builder_(_fbb); +  builder_.add_documentation(documentation); +  builder_.add_attributes(attributes); +  builder_.add_bytesize(bytesize); +  builder_.add_minalign(minalign); +  builder_.add_fields(fields); +  builder_.add_name(name); +  builder_.add_is_struct(is_struct); +  return builder_.Finish(); +} + +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, +    const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) { +  auto name__ = name ? _fbb.CreateString(name) : 0; +  auto fields__ = fields ? _fbb.CreateVector<flatbuffers::Offset<Field>>(*fields) : 0; +  auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0; +  auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0; +  return reflection::CreateObject( +      _fbb, +      name__, +      fields__, +      is_struct, +      minalign, +      bytesize, +      attributes__, +      documentation__); +} + +struct RPCCall FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { +  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { +    VT_NAME = 4, +    VT_REQUEST = 6, +    VT_RESPONSE = 8, +    VT_ATTRIBUTES = 10, +    VT_DOCUMENTATION = 12 +  }; +  const flatbuffers::String *name() const { +    return GetPointer<const flatbuffers::String *>(VT_NAME); +  } +  bool KeyCompareLessThan(const RPCCall *o) const { +    return *name() < *o->name(); +  } +  int KeyCompareWithValue(const char *val) const { +    return strcmp(name()->c_str(), val); +  } +  const Object *request() const { +    return GetPointer<const Object *>(VT_REQUEST); +  } +  const Object *response() const { +    return GetPointer<const Object *>(VT_RESPONSE); +  } +  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) && +           VerifyOffsetRequired(verifier, VT_NAME) && +           verifier.VerifyString(name()) && +           VerifyOffsetRequired(verifier, VT_REQUEST) && +           verifier.VerifyTable(request()) && +           VerifyOffsetRequired(verifier, VT_RESPONSE) && +           verifier.VerifyTable(response()) && +           VerifyOffset(verifier, VT_ATTRIBUTES) && +           verifier.VerifyVector(attributes()) && +           verifier.VerifyVectorOfTables(attributes()) && +           VerifyOffset(verifier, VT_DOCUMENTATION) && +           verifier.VerifyVector(documentation()) && +           verifier.VerifyVectorOfStrings(documentation()) && +           verifier.EndTable(); +  } +}; + +struct RPCCallBuilder { +  flatbuffers::FlatBufferBuilder &fbb_; +  flatbuffers::uoffset_t start_; +  void add_name(flatbuffers::Offset<flatbuffers::String> name) { +    fbb_.AddOffset(RPCCall::VT_NAME, name); +  } +  void add_request(flatbuffers::Offset<Object> request) { +    fbb_.AddOffset(RPCCall::VT_REQUEST, request); +  } +  void add_response(flatbuffers::Offset<Object> response) { +    fbb_.AddOffset(RPCCall::VT_RESPONSE, response); +  } +  void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) { +    fbb_.AddOffset(RPCCall::VT_ATTRIBUTES, attributes); +  } +  void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) { +    fbb_.AddOffset(RPCCall::VT_DOCUMENTATION, documentation); +  } +  explicit RPCCallBuilder(flatbuffers::FlatBufferBuilder &_fbb) +        : fbb_(_fbb) { +    start_ = fbb_.StartTable(); +  } +  RPCCallBuilder &operator=(const RPCCallBuilder &); +  flatbuffers::Offset<RPCCall> Finish() { +    const auto end = fbb_.EndTable(start_); +    auto o = flatbuffers::Offset<RPCCall>(end); +    fbb_.Required(o, RPCCall::VT_NAME); +    fbb_.Required(o, RPCCall::VT_REQUEST); +    fbb_.Required(o, RPCCall::VT_RESPONSE); +    return o; +  } +}; + +inline flatbuffers::Offset<RPCCall> CreateRPCCall( +    flatbuffers::FlatBufferBuilder &_fbb, +    flatbuffers::Offset<flatbuffers::String> name = 0, +    flatbuffers::Offset<Object> request = 0, +    flatbuffers::Offset<Object> response = 0, +    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0, +    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) { +  RPCCallBuilder builder_(_fbb); +  builder_.add_documentation(documentation); +  builder_.add_attributes(attributes); +  builder_.add_response(response); +  builder_.add_request(request); +  builder_.add_name(name); +  return builder_.Finish(); +} + +inline flatbuffers::Offset<RPCCall> CreateRPCCallDirect( +    flatbuffers::FlatBufferBuilder &_fbb, +    const char *name = nullptr, +    flatbuffers::Offset<Object> request = 0, +    flatbuffers::Offset<Object> response = 0, +    const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr, +    const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) { +  auto name__ = name ? _fbb.CreateString(name) : 0; +  auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0; +  auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0; +  return reflection::CreateRPCCall( +      _fbb, +      name__, +      request, +      response, +      attributes__, +      documentation__); +} + +struct Service FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { +  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { +    VT_NAME = 4, +    VT_CALLS = 6, +    VT_ATTRIBUTES = 8, +    VT_DOCUMENTATION = 10 +  }; +  const flatbuffers::String *name() const { +    return GetPointer<const flatbuffers::String *>(VT_NAME); +  } +  bool KeyCompareLessThan(const Service *o) const { +    return *name() < *o->name(); +  } +  int KeyCompareWithValue(const char *val) const { +    return strcmp(name()->c_str(), val); +  } +  const flatbuffers::Vector<flatbuffers::Offset<RPCCall>> *calls() const { +    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<RPCCall>> *>(VT_CALLS); +  } +  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) && +           VerifyOffsetRequired(verifier, VT_NAME) && +           verifier.VerifyString(name()) && +           VerifyOffset(verifier, VT_CALLS) && +           verifier.VerifyVector(calls()) && +           verifier.VerifyVectorOfTables(calls()) && +           VerifyOffset(verifier, VT_ATTRIBUTES) && +           verifier.VerifyVector(attributes()) && +           verifier.VerifyVectorOfTables(attributes()) && +           VerifyOffset(verifier, VT_DOCUMENTATION) && +           verifier.VerifyVector(documentation()) && +           verifier.VerifyVectorOfStrings(documentation()) && +           verifier.EndTable(); +  } +}; + +struct ServiceBuilder { +  flatbuffers::FlatBufferBuilder &fbb_; +  flatbuffers::uoffset_t start_; +  void add_name(flatbuffers::Offset<flatbuffers::String> name) { +    fbb_.AddOffset(Service::VT_NAME, name); +  } +  void add_calls(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<RPCCall>>> calls) { +    fbb_.AddOffset(Service::VT_CALLS, calls); +  } +  void add_attributes(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes) { +    fbb_.AddOffset(Service::VT_ATTRIBUTES, attributes); +  } +  void add_documentation(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation) { +    fbb_.AddOffset(Service::VT_DOCUMENTATION, documentation); +  } +  explicit ServiceBuilder(flatbuffers::FlatBufferBuilder &_fbb) +        : fbb_(_fbb) { +    start_ = fbb_.StartTable(); +  } +  ServiceBuilder &operator=(const ServiceBuilder &); +  flatbuffers::Offset<Service> Finish() { +    const auto end = fbb_.EndTable(start_); +    auto o = flatbuffers::Offset<Service>(end); +    fbb_.Required(o, Service::VT_NAME); +    return o; +  } +}; + +inline flatbuffers::Offset<Service> CreateService( +    flatbuffers::FlatBufferBuilder &_fbb, +    flatbuffers::Offset<flatbuffers::String> name = 0, +    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<RPCCall>>> calls = 0, +    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<KeyValue>>> attributes = 0, +    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> documentation = 0) { +  ServiceBuilder builder_(_fbb); +  builder_.add_documentation(documentation); +  builder_.add_attributes(attributes); +  builder_.add_calls(calls); +  builder_.add_name(name); +  return builder_.Finish(); +} + +inline flatbuffers::Offset<Service> CreateServiceDirect( +    flatbuffers::FlatBufferBuilder &_fbb, +    const char *name = nullptr, +    const std::vector<flatbuffers::Offset<RPCCall>> *calls = nullptr, +    const std::vector<flatbuffers::Offset<KeyValue>> *attributes = nullptr, +    const std::vector<flatbuffers::Offset<flatbuffers::String>> *documentation = nullptr) { +  auto name__ = name ? _fbb.CreateString(name) : 0; +  auto calls__ = calls ? _fbb.CreateVector<flatbuffers::Offset<RPCCall>>(*calls) : 0; +  auto attributes__ = attributes ? _fbb.CreateVector<flatbuffers::Offset<KeyValue>>(*attributes) : 0; +  auto documentation__ = documentation ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*documentation) : 0; +  return reflection::CreateService( +      _fbb, +      name__, +      calls__, +      attributes__, +      documentation__); +} + +struct Schema FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { +  enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { +    VT_OBJECTS = 4, +    VT_ENUMS = 6, +    VT_FILE_IDENT = 8, +    VT_FILE_EXT = 10, +    VT_ROOT_TABLE = 12, +    VT_SERVICES = 14 +  }; +  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<Service>> *services() const { +    return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<Service>> *>(VT_SERVICES); +  } +  bool Verify(flatbuffers::Verifier &verifier) const { +    return VerifyTableStart(verifier) && +           VerifyOffsetRequired(verifier, VT_OBJECTS) && +           verifier.VerifyVector(objects()) && +           verifier.VerifyVectorOfTables(objects()) && +           VerifyOffsetRequired(verifier, VT_ENUMS) && +           verifier.VerifyVector(enums()) && +           verifier.VerifyVectorOfTables(enums()) && +           VerifyOffset(verifier, VT_FILE_IDENT) && +           verifier.VerifyString(file_ident()) && +           VerifyOffset(verifier, VT_FILE_EXT) && +           verifier.VerifyString(file_ext()) && +           VerifyOffset(verifier, VT_ROOT_TABLE) && +           verifier.VerifyTable(root_table()) && +           VerifyOffset(verifier, VT_SERVICES) && +           verifier.VerifyVector(services()) && +           verifier.VerifyVectorOfTables(services()) && +           verifier.EndTable(); +  } +}; + +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); +  } +  void add_services(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Service>>> services) { +    fbb_.AddOffset(Schema::VT_SERVICES, services); +  } +  explicit SchemaBuilder(flatbuffers::FlatBufferBuilder &_fbb) +        : fbb_(_fbb) { +    start_ = fbb_.StartTable(); +  } +  SchemaBuilder &operator=(const SchemaBuilder &); +  flatbuffers::Offset<Schema> Finish() { +    const auto end = fbb_.EndTable(start_); +    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, +    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, +    flatbuffers::Offset<flatbuffers::String> file_ext = 0, +    flatbuffers::Offset<Object> root_table = 0, +    flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<Service>>> services = 0) { +  SchemaBuilder builder_(_fbb); +  builder_.add_services(services); +  builder_.add_root_table(root_table); +  builder_.add_file_ext(file_ext); +  builder_.add_file_ident(file_ident); +  builder_.add_enums(enums); +  builder_.add_objects(objects); +  return builder_.Finish(); +} + +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, +    const std::vector<flatbuffers::Offset<Service>> *services = nullptr) { +  auto objects__ = objects ? _fbb.CreateVector<flatbuffers::Offset<Object>>(*objects) : 0; +  auto enums__ = enums ? _fbb.CreateVector<flatbuffers::Offset<Enum>>(*enums) : 0; +  auto file_ident__ = file_ident ? _fbb.CreateString(file_ident) : 0; +  auto file_ext__ = file_ext ? _fbb.CreateString(file_ext) : 0; +  auto services__ = services ? _fbb.CreateVector<flatbuffers::Offset<Service>>(*services) : 0; +  return reflection::CreateSchema( +      _fbb, +      objects__, +      enums__, +      file_ident__, +      file_ext__, +      root_table, +      services__); +} + +inline const reflection::Schema *GetSchema(const void *buf) { +  return flatbuffers::GetRoot<reflection::Schema>(buf); +} + +inline const reflection::Schema *GetSizePrefixedSchema(const void *buf) { +  return flatbuffers::GetSizePrefixedRoot<reflection::Schema>(buf); +} + +inline const char *SchemaIdentifier() { +  return "BFBS"; +} + +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 VerifySizePrefixedSchemaBuffer( +    flatbuffers::Verifier &verifier) { +  return verifier.VerifySizePrefixedBuffer<reflection::Schema>(SchemaIdentifier()); +} + +inline const char *SchemaExtension() { +  return "bfbs"; +} + +inline void FinishSchemaBuffer( +    flatbuffers::FlatBufferBuilder &fbb, +    flatbuffers::Offset<reflection::Schema> root) { +  fbb.Finish(root, SchemaIdentifier()); +} + +inline void FinishSizePrefixedSchemaBuffer( +    flatbuffers::FlatBufferBuilder &fbb, +    flatbuffers::Offset<reflection::Schema> root) { +  fbb.FinishSizePrefixed(root, SchemaIdentifier()); +} + +}  // namespace reflection + +#endif  // FLATBUFFERS_GENERATED_REFLECTION_REFLECTION_H_ diff --git a/host/lib/deps/flatbuffers/include/flatbuffers/stl_emulation.h b/host/lib/deps/flatbuffers/include/flatbuffers/stl_emulation.h new file mode 100644 index 000000000..6f6e76642 --- /dev/null +++ b/host/lib/deps/flatbuffers/include/flatbuffers/stl_emulation.h @@ -0,0 +1,275 @@ +/* + * Copyright 2017 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + *     http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FLATBUFFERS_STL_EMULATION_H_ +#define FLATBUFFERS_STL_EMULATION_H_ + +// clang-format off + +#include <string> +#include <type_traits> +#include <vector> +#include <memory> +#include <limits> + +#if defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL) +  #define FLATBUFFERS_CPP98_STL +#endif  // defined(_STLPORT_VERSION) && !defined(FLATBUFFERS_CPP98_STL) + +#if defined(FLATBUFFERS_CPP98_STL) +  #include <cctype> +#endif  // defined(FLATBUFFERS_CPP98_STL) + +// Check if we can use template aliases +// Not possible if Microsoft Compiler before 2012 +// Possible is the language feature __cpp_alias_templates is defined well +// Or possible if the C++ std is C+11 or newer +#if (defined(_MSC_VER) && _MSC_VER > 1700 /* MSVC2012 */) \ +    || (defined(__cpp_alias_templates) && __cpp_alias_templates >= 200704) \ +    || (defined(__cplusplus) && __cplusplus >= 201103L) +  #define FLATBUFFERS_TEMPLATES_ALIASES +#endif + +// This header provides backwards compatibility for C++98 STLs like stlport. +namespace flatbuffers { + +// Retrieve ::back() from a string in a way that is compatible with pre C++11 +// STLs (e.g stlport). +inline char& string_back(std::string &value) { +  return value[value.length() - 1]; +} + +inline char string_back(const std::string &value) { +  return value[value.length() - 1]; +} + +// Helper method that retrieves ::data() from a vector in a way that is +// compatible with pre C++11 STLs (e.g stlport). +template <typename T> inline T *vector_data(std::vector<T> &vector) { +  // In some debug environments, operator[] does bounds checking, so &vector[0] +  // can't be used. +  return vector.empty() ? nullptr : &vector[0]; +} + +template <typename T> inline const T *vector_data( +    const std::vector<T> &vector) { +  return vector.empty() ? nullptr : &vector[0]; +} + +template <typename T, typename V> +inline void vector_emplace_back(std::vector<T> *vector, V &&data) { +  #if defined(FLATBUFFERS_CPP98_STL) +    vector->push_back(data); +  #else +    vector->emplace_back(std::forward<V>(data)); +  #endif  // defined(FLATBUFFERS_CPP98_STL) +} + +#ifndef FLATBUFFERS_CPP98_STL +  #if defined(FLATBUFFERS_TEMPLATES_ALIASES) +    template <typename T> +    using numeric_limits = std::numeric_limits<T>; +  #else +    template <typename T> class numeric_limits : +      public std::numeric_limits<T> {}; +  #endif  // defined(FLATBUFFERS_TEMPLATES_ALIASES) +#else +  template <typename T> class numeric_limits : +      public std::numeric_limits<T> { +    public: +      // Android NDK fix. +      static T lowest() { +        return std::numeric_limits<T>::min(); +      } +  }; + +  template <> class numeric_limits<float> :  +      public std::numeric_limits<float> { +    public: +      static float lowest() { return -FLT_MAX; } +  }; + +  template <> class numeric_limits<double> :  +      public std::numeric_limits<double> { +    public: +      static double lowest() { return -DBL_MAX; } +  }; + +  template <> class numeric_limits<unsigned long long> { +   public: +    static unsigned long long min() { return 0ULL; } +    static unsigned long long max() { return ~0ULL; } +    static unsigned long long lowest() { +      return numeric_limits<unsigned long long>::min(); +    } +  }; + +  template <> class numeric_limits<long long> { +   public: +    static long long min() { +      return static_cast<long long>(1ULL << ((sizeof(long long) << 3) - 1)); +    } +    static long long max() { +      return static_cast<long long>( +          (1ULL << ((sizeof(long long) << 3) - 1)) - 1); +    } +    static long long lowest() { +      return numeric_limits<long long>::min(); +    } +  }; +#endif  // FLATBUFFERS_CPP98_STL + +#if defined(FLATBUFFERS_TEMPLATES_ALIASES) +  #ifndef FLATBUFFERS_CPP98_STL +    template <typename T> using is_scalar = std::is_scalar<T>; +    template <typename T, typename U> using is_same = std::is_same<T,U>; +    template <typename T> using is_floating_point = std::is_floating_point<T>; +    template <typename T> using is_unsigned = std::is_unsigned<T>; +    template <typename T> using make_unsigned = std::make_unsigned<T>; +  #else +    // Map C++ TR1 templates defined by stlport. +    template <typename T> using is_scalar = std::tr1::is_scalar<T>; +    template <typename T, typename U> using is_same = std::tr1::is_same<T,U>; +    template <typename T> using is_floating_point = +        std::tr1::is_floating_point<T>; +    template <typename T> using is_unsigned = std::tr1::is_unsigned<T>; +    // Android NDK doesn't have std::make_unsigned or std::tr1::make_unsigned. +    template<typename T> struct make_unsigned { +      static_assert(is_unsigned<T>::value, "Specialization not implemented!"); +      using type = T; +    }; +    template<> struct make_unsigned<char> { using type = unsigned char; }; +    template<> struct make_unsigned<short> { using type = unsigned short; }; +    template<> struct make_unsigned<int> { using type = unsigned int; }; +    template<> struct make_unsigned<long> { using type = unsigned long; }; +    template<> +    struct make_unsigned<long long> { using type = unsigned long long; }; +  #endif  // !FLATBUFFERS_CPP98_STL +#else +  // MSVC 2010 doesn't support C++11 aliases. +  template <typename T> struct is_scalar : public std::is_scalar<T> {}; +  template <typename T, typename U> struct is_same : public std::is_same<T,U> {}; +  template <typename T> struct is_floating_point : +        public std::is_floating_point<T> {}; +  template <typename T> struct is_unsigned : public std::is_unsigned<T> {}; +  template <typename T> struct make_unsigned : public std::make_unsigned<T> {}; +#endif  // defined(FLATBUFFERS_TEMPLATES_ALIASES) + +#ifndef FLATBUFFERS_CPP98_STL +  #if defined(FLATBUFFERS_TEMPLATES_ALIASES) +    template <class T> using unique_ptr = std::unique_ptr<T>; +  #else +    // MSVC 2010 doesn't support C++11 aliases. +    // We're manually "aliasing" the class here as we want to bring unique_ptr +    // into the flatbuffers namespace.  We have unique_ptr in the flatbuffers +    // namespace we have a completely independent implemenation (see below) +    // for C++98 STL implementations. +    template <class T> class unique_ptr : public std::unique_ptr<T> { +     public: +      unique_ptr() {} +      explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {} +      unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); } +      unique_ptr(unique_ptr&& u) { *this = std::move(u); } +      unique_ptr& operator=(std::unique_ptr<T>&& u) { +        std::unique_ptr<T>::reset(u.release()); +        return *this; +      } +      unique_ptr& operator=(unique_ptr&& u) { +        std::unique_ptr<T>::reset(u.release()); +        return *this; +      } +      unique_ptr& operator=(T* p) { +        return std::unique_ptr<T>::operator=(p); +      } +    }; +  #endif  // defined(FLATBUFFERS_TEMPLATES_ALIASES) +#else +  // Very limited implementation of unique_ptr. +  // This is provided simply to allow the C++ code generated from the default +  // settings to function in C++98 environments with no modifications. +  template <class T> class unique_ptr { +   public: +    typedef T element_type; + +    unique_ptr() : ptr_(nullptr) {} +    explicit unique_ptr(T* p) : ptr_(p) {} +    unique_ptr(unique_ptr&& u) : ptr_(nullptr) { reset(u.release()); } +    unique_ptr(const unique_ptr& u) : ptr_(nullptr) { +      reset(const_cast<unique_ptr*>(&u)->release()); +    } +    ~unique_ptr() { reset(); } + +    unique_ptr& operator=(const unique_ptr& u) { +      reset(const_cast<unique_ptr*>(&u)->release()); +      return *this; +    } + +    unique_ptr& operator=(unique_ptr&& u) { +      reset(u.release()); +      return *this; +    } + +    unique_ptr& operator=(T* p) { +      reset(p); +      return *this; +    } + +    const T& operator*() const { return *ptr_; } +    T* operator->() const { return ptr_; } +    T* get() const noexcept { return ptr_; } +    explicit operator bool() const { return ptr_ != nullptr; } + +    // modifiers +    T* release() { +      T* value = ptr_; +      ptr_ = nullptr; +      return value; +    } + +    void reset(T* p = nullptr) { +      T* value = ptr_; +      ptr_ = p; +      if (value) delete value; +    } + +    void swap(unique_ptr& u) { +      T* temp_ptr = ptr_; +      ptr_ = u.ptr_; +      u.ptr_ = temp_ptr; +    } + +   private: +    T* ptr_; +  }; + +  template <class T> bool operator==(const unique_ptr<T>& x, +                                     const unique_ptr<T>& y) { +    return x.get() == y.get(); +  } + +  template <class T, class D> bool operator==(const unique_ptr<T>& x, +                                              const D* y) { +    return static_cast<D*>(x.get()) == y; +  } + +  template <class T> bool operator==(const unique_ptr<T>& x, intptr_t y) { +    return reinterpret_cast<intptr_t>(x.get()) == y; +  } +#endif  // !FLATBUFFERS_CPP98_STL + +}  // namespace flatbuffers + +#endif  // FLATBUFFERS_STL_EMULATION_H_ diff --git a/host/lib/deps/flatbuffers/include/flatbuffers/util.h b/host/lib/deps/flatbuffers/include/flatbuffers/util.h new file mode 100644 index 000000000..4367bbecf --- /dev/null +++ b/host/lib/deps/flatbuffers/include/flatbuffers/util.h @@ -0,0 +1,654 @@ +/* + * 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. + */ + +#ifndef FLATBUFFERS_UTIL_H_ +#define FLATBUFFERS_UTIL_H_ + +#include "flatbuffers/base.h" + +#include <errno.h> + +#ifndef FLATBUFFERS_PREFER_PRINTF +#  include <sstream> +#else  // FLATBUFFERS_PREFER_PRINTF +#  include <float.h> +#  include <stdio.h> +#endif  // FLATBUFFERS_PREFER_PRINTF + +#include <iomanip> +#include <string> + +namespace flatbuffers { + +// @locale-independent functions for ASCII characters set. + +// Fast checking that character lies in closed range: [a <= x <= b] +// using one compare (conditional branch) operator. +inline bool check_ascii_range(char x, char a, char b) { +  FLATBUFFERS_ASSERT(a <= b); +  // (Hacker's Delight): `a <= x <= b` <=> `(x-a) <={u} (b-a)`. +  // The x, a, b will be promoted to int and subtracted without overflow. +  return static_cast<unsigned int>(x - a) <= static_cast<unsigned int>(b - a); +} + +// Case-insensitive isalpha +inline bool is_alpha(char c) { +  // ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF). +  return check_ascii_range(c & 0xDF, 'a' & 0xDF, 'z' & 0xDF); +} + +// Check (case-insensitive) that `c` is equal to alpha. +inline bool is_alpha_char(char c, char alpha) { +  FLATBUFFERS_ASSERT(is_alpha(alpha)); +  // ASCII only: alpha to upper case => reset bit 0x20 (~0x20 = 0xDF). +  return ((c & 0xDF) == (alpha & 0xDF)); +} + +// https://en.cppreference.com/w/cpp/string/byte/isxdigit +// isdigit and isxdigit are the only standard narrow character classification +// functions that are not affected by the currently installed C locale. although +// some implementations (e.g. Microsoft in 1252 codepage) may classify +// additional single-byte characters as digits. +inline bool is_digit(char c) { return check_ascii_range(c, '0', '9'); } + +inline bool is_xdigit(char c) { +  // Replace by look-up table. +  return is_digit(c) || check_ascii_range(c & 0xDF, 'a' & 0xDF, 'f' & 0xDF); +} + +// Case-insensitive isalnum +inline bool is_alnum(char c) { return is_alpha(c) || is_digit(c); } + +// @end-locale-independent functions for ASCII character set + +#ifdef FLATBUFFERS_PREFER_PRINTF +template<typename T> size_t IntToDigitCount(T t) { +  size_t digit_count = 0; +  // Count the sign for negative numbers +  if (t < 0) digit_count++; +  // Count a single 0 left of the dot for fractional numbers +  if (-1 < t && t < 1) digit_count++; +  // Count digits until fractional part +  T eps = std::numeric_limits<float>::epsilon(); +  while (t <= (-1 + eps) || (1 - eps) <= t) { +    t /= 10; +    digit_count++; +  } +  return digit_count; +} + +template<typename T> size_t NumToStringWidth(T t, int precision = 0) { +  size_t string_width = IntToDigitCount(t); +  // Count the dot for floating point numbers +  if (precision) string_width += (precision + 1); +  return string_width; +} + +template<typename T> +std::string NumToStringImplWrapper(T t, const char *fmt, int precision = 0) { +  size_t string_width = NumToStringWidth(t, precision); +  std::string s(string_width, 0x00); +  // Allow snprintf to use std::string trailing null to detect buffer overflow +  snprintf(const_cast<char *>(s.data()), (s.size() + 1), fmt, precision, t); +  return s; +} +#endif  // FLATBUFFERS_PREFER_PRINTF + +// Convert an integer or floating point value to a string. +// In contrast to std::stringstream, "char" values are +// converted to a string of digits, and we don't use scientific notation. +template<typename T> std::string NumToString(T t) { +  // clang-format off + +  #ifndef FLATBUFFERS_PREFER_PRINTF +    std::stringstream ss; +    ss << t; +    return ss.str(); +  #else // FLATBUFFERS_PREFER_PRINTF +    auto v = static_cast<long long>(t); +    return NumToStringImplWrapper(v, "%.*lld"); +  #endif // FLATBUFFERS_PREFER_PRINTF +  // clang-format on +} +// Avoid char types used as character data. +template<> inline std::string NumToString<signed char>(signed char t) { +  return NumToString(static_cast<int>(t)); +} +template<> inline std::string NumToString<unsigned char>(unsigned char t) { +  return NumToString(static_cast<int>(t)); +} +template<> inline std::string NumToString<char>(char t) { +  return NumToString(static_cast<int>(t)); +} +#if defined(FLATBUFFERS_CPP98_STL) +template<> inline std::string NumToString<long long>(long long t) { +  char buf[21];  // (log((1 << 63) - 1) / log(10)) + 2 +  snprintf(buf, sizeof(buf), "%lld", t); +  return std::string(buf); +} + +template<> +inline std::string NumToString<unsigned long long>(unsigned long long t) { +  char buf[22];  // (log((1 << 63) - 1) / log(10)) + 1 +  snprintf(buf, sizeof(buf), "%llu", t); +  return std::string(buf); +} +#endif  // defined(FLATBUFFERS_CPP98_STL) + +// Special versions for floats/doubles. +template<typename T> std::string FloatToString(T t, int precision) { +  // clang-format off + +  #ifndef FLATBUFFERS_PREFER_PRINTF +    // to_string() prints different numbers of digits for floats depending on +    // platform and isn't available on Android, so we use stringstream +    std::stringstream ss; +    // Use std::fixed to suppress scientific notation. +    ss << std::fixed; +    // Default precision is 6, we want that to be higher for doubles. +    ss << std::setprecision(precision); +    ss << t; +    auto s = ss.str(); +  #else // FLATBUFFERS_PREFER_PRINTF +    auto v = static_cast<double>(t); +    auto s = NumToStringImplWrapper(v, "%0.*f", precision); +  #endif // FLATBUFFERS_PREFER_PRINTF +  // clang-format on +  // Sadly, std::fixed turns "1" into "1.00000", so here we undo that. +  auto p = s.find_last_not_of('0'); +  if (p != std::string::npos) { +    // Strip trailing zeroes. If it is a whole number, keep one zero. +    s.resize(p + (s[p] == '.' ? 2 : 1)); +  } +  return s; +} + +template<> inline std::string NumToString<double>(double t) { +  return FloatToString(t, 12); +} +template<> inline std::string NumToString<float>(float t) { +  return FloatToString(t, 6); +} + +// Convert an integer value to a hexadecimal string. +// The returned string length is always xdigits long, prefixed by 0 digits. +// For example, IntToStringHex(0x23, 8) returns the string "00000023". +inline std::string IntToStringHex(int i, int xdigits) { +  FLATBUFFERS_ASSERT(i >= 0); +  // clang-format off + +  #ifndef FLATBUFFERS_PREFER_PRINTF +    std::stringstream ss; +    ss << std::setw(xdigits) << std::setfill('0') << std::hex << std::uppercase +       << i; +    return ss.str(); +  #else // FLATBUFFERS_PREFER_PRINTF +    return NumToStringImplWrapper(i, "%.*X", xdigits); +  #endif // FLATBUFFERS_PREFER_PRINTF +  // clang-format on +} + +// clang-format off +// Use locale independent functions {strtod_l, strtof_l, strtoll_l, strtoull_l}. +#if defined(FLATBUFFERS_LOCALE_INDEPENDENT) && (FLATBUFFERS_LOCALE_INDEPENDENT > 0) +  class ClassicLocale { +    #ifdef _MSC_VER +      typedef _locale_t locale_type; +    #else +      typedef locale_t locale_type;  // POSIX.1-2008 locale_t type +    #endif +    ClassicLocale(); +    ~ClassicLocale(); +    locale_type locale_; +    static ClassicLocale instance_; +  public: +    static locale_type Get() { return instance_.locale_; } +  }; + +  #ifdef _MSC_VER +    #define __strtoull_impl(s, pe, b) _strtoui64_l(s, pe, b, ClassicLocale::Get()) +    #define __strtoll_impl(s, pe, b) _strtoi64_l(s, pe, b, ClassicLocale::Get()) +    #define __strtod_impl(s, pe) _strtod_l(s, pe, ClassicLocale::Get()) +    #define __strtof_impl(s, pe) _strtof_l(s, pe, ClassicLocale::Get()) +  #else +    #define __strtoull_impl(s, pe, b) strtoull_l(s, pe, b, ClassicLocale::Get()) +    #define __strtoll_impl(s, pe, b) strtoll_l(s, pe, b, ClassicLocale::Get()) +    #define __strtod_impl(s, pe) strtod_l(s, pe, ClassicLocale::Get()) +    #define __strtof_impl(s, pe) strtof_l(s, pe, ClassicLocale::Get()) +  #endif +#else +  #define __strtod_impl(s, pe) strtod(s, pe) +  #define __strtof_impl(s, pe) static_cast<float>(strtod(s, pe)) +  #ifdef _MSC_VER +    #define __strtoull_impl(s, pe, b) _strtoui64(s, pe, b) +    #define __strtoll_impl(s, pe, b) _strtoi64(s, pe, b) +  #else +    #define __strtoull_impl(s, pe, b) strtoull(s, pe, b) +    #define __strtoll_impl(s, pe, b) strtoll(s, pe, b) +  #endif +#endif + +inline void strtoval_impl(int64_t *val, const char *str, char **endptr, +                                 int base) { +    *val = __strtoll_impl(str, endptr, base); +} + +inline void strtoval_impl(uint64_t *val, const char *str, char **endptr, +                                 int base) { +  *val = __strtoull_impl(str, endptr, base); +} + +inline void strtoval_impl(double *val, const char *str, char **endptr) { +  *val = __strtod_impl(str, endptr); +} + +// UBSAN: double to float is safe if numeric_limits<float>::is_iec559 is true. +__supress_ubsan__("float-cast-overflow") +inline void strtoval_impl(float *val, const char *str, char **endptr) { +  *val = __strtof_impl(str, endptr); +} +#undef __strtoull_impl +#undef __strtoll_impl +#undef __strtod_impl +#undef __strtof_impl +// clang-format on + +// Adaptor for strtoull()/strtoll(). +// Flatbuffers accepts numbers with any count of leading zeros (-009 is -9), +// while strtoll with base=0 interprets first leading zero as octal prefix. +// In future, it is possible to add prefixed 0b0101. +// 1) Checks errno code for overflow condition (out of range). +// 2) If base <= 0, function try to detect base of number by prefix. +// +// Return value (like strtoull and strtoll, but reject partial result): +// - If successful, an integer value corresponding to the str is returned. +// - If full string conversion can't be performed, 0 is returned. +// - If the converted value falls out of range of corresponding return type, a +// range error occurs. In this case value MAX(T)/MIN(T) is returned. +template<typename T> +inline bool StringToIntegerImpl(T *val, const char *const str, +                                const int base = 0, +                                const bool check_errno = true) { +  // T is int64_t or uint64_T +  FLATBUFFERS_ASSERT(str); +  if (base <= 0) { +    auto s = str; +    while (*s && !is_digit(*s)) s++; +    if (s[0] == '0' && is_alpha_char(s[1], 'X')) +      return StringToIntegerImpl(val, str, 16, check_errno); +    // if a prefix not match, try base=10 +    return StringToIntegerImpl(val, str, 10, check_errno); +  } else { +    if (check_errno) errno = 0;  // clear thread-local errno +    auto endptr = str; +    strtoval_impl(val, str, const_cast<char **>(&endptr), base); +    if ((*endptr != '\0') || (endptr == str)) { +      *val = 0;      // erase partial result +      return false;  // invalid string +    } +    // errno is out-of-range, return MAX/MIN +    if (check_errno && errno) return false; +    return true; +  } +} + +template<typename T> +inline bool StringToFloatImpl(T *val, const char *const str) { +  // Type T must be either float or double. +  FLATBUFFERS_ASSERT(str && val); +  auto end = str; +  strtoval_impl(val, str, const_cast<char **>(&end)); +  auto done = (end != str) && (*end == '\0'); +  if (!done) *val = 0;  // erase partial result +  return done; +} + +// Convert a string to an instance of T. +// Return value (matched with StringToInteger64Impl and strtod): +// - If successful, a numeric value corresponding to the str is returned. +// - If full string conversion can't be performed, 0 is returned. +// - If the converted value falls out of range of corresponding return type, a +// range error occurs. In this case value MAX(T)/MIN(T) is returned. +template<typename T> inline bool StringToNumber(const char *s, T *val) { +  FLATBUFFERS_ASSERT(s && val); +  int64_t i64; +  // The errno check isn't needed, will return MAX/MIN on overflow. +  if (StringToIntegerImpl(&i64, s, 0, false)) { +    const int64_t max = flatbuffers::numeric_limits<T>::max(); +    const int64_t min = flatbuffers::numeric_limits<T>::lowest(); +    if (i64 > max) { +      *val = static_cast<T>(max); +      return false; +    } +    if (i64 < min) { +      // For unsigned types return max to distinguish from +      // "no conversion can be performed" when 0 is returned. +      *val = static_cast<T>(flatbuffers::is_unsigned<T>::value ? max : min); +      return false; +    } +    *val = static_cast<T>(i64); +    return true; +  } +  *val = 0; +  return false; +} + +template<> inline bool StringToNumber<int64_t>(const char *str, int64_t *val) { +  return StringToIntegerImpl(val, str); +} + +template<> +inline bool StringToNumber<uint64_t>(const char *str, uint64_t *val) { +  if (!StringToIntegerImpl(val, str)) return false; +  // The strtoull accepts negative numbers: +  // If the minus sign was part of the input sequence, the numeric value +  // calculated from the sequence of digits is negated as if by unary minus +  // in the result type, which applies unsigned integer wraparound rules. +  // Fix this behaviour (except -0). +  if (*val) { +    auto s = str; +    while (*s && !is_digit(*s)) s++; +    s = (s > str) ? (s - 1) : s;  // step back to one symbol +    if (*s == '-') { +      // For unsigned types return the max to distinguish from +      // "no conversion can be performed". +      *val = flatbuffers::numeric_limits<uint64_t>::max(); +      return false; +    } +  } +  return true; +} + +template<> inline bool StringToNumber(const char *s, float *val) { +  return StringToFloatImpl(val, s); +} + +template<> inline bool StringToNumber(const char *s, double *val) { +  return StringToFloatImpl(val, s); +} + +inline int64_t StringToInt(const char *s, int base = 10) { +  int64_t val; +  return StringToIntegerImpl(&val, s, base) ? val : 0; +} + +inline uint64_t StringToUInt(const char *s, int base = 10) { +  uint64_t val; +  return StringToIntegerImpl(&val, s, base) ? val : 0; +} + +typedef bool (*LoadFileFunction)(const char *filename, bool binary, +                                 std::string *dest); +typedef bool (*FileExistsFunction)(const char *filename); + +LoadFileFunction SetLoadFileFunction(LoadFileFunction load_file_function); + +FileExistsFunction SetFileExistsFunction( +    FileExistsFunction file_exists_function); + +// Check if file "name" exists. +bool FileExists(const char *name); + +// Check if "name" exists and it is also a directory. +bool DirExists(const char *name); + +// Load file "name" into "buf" returning true if successful +// false otherwise.  If "binary" is false data is read +// using ifstream's text mode, otherwise data is read with +// no transcoding. +bool LoadFile(const char *name, bool binary, std::string *buf); + +// Save data "buf" of length "len" bytes into a file +// "name" returning true if successful, false otherwise. +// If "binary" is false data is written using ifstream's +// text mode, otherwise data is written with no +// transcoding. +bool SaveFile(const char *name, const char *buf, size_t len, bool binary); + +// Save data "buf" into file "name" returning true if +// successful, false otherwise.  If "binary" is false +// data is written using ifstream's text mode, otherwise +// data is written with no transcoding. +inline bool SaveFile(const char *name, const std::string &buf, bool binary) { +  return SaveFile(name, buf.c_str(), buf.size(), binary); +} + +// Functionality for minimalistic portable path handling. + +// The functions below behave correctly regardless of whether posix ('/') or +// Windows ('/' or '\\') separators are used. + +// Any new separators inserted are always posix. +FLATBUFFERS_CONSTEXPR char kPathSeparator = '/'; + +// Returns the path with the extension, if any, removed. +std::string StripExtension(const std::string &filepath); + +// Returns the extension, if any. +std::string GetExtension(const std::string &filepath); + +// Return the last component of the path, after the last separator. +std::string StripPath(const std::string &filepath); + +// Strip the last component of the path + separator. +std::string StripFileName(const std::string &filepath); + +// Concatenates a path with a filename, regardless of wether the path +// ends in a separator or not. +std::string ConCatPathFileName(const std::string &path, +                               const std::string &filename); + +// Replaces any '\\' separators with '/' +std::string PosixPath(const char *path); + +// This function ensure a directory exists, by recursively +// creating dirs for any parts of the path that don't exist yet. +void EnsureDirExists(const std::string &filepath); + +// Obtains the absolute path from any other path. +// Returns the input path if the absolute path couldn't be resolved. +std::string AbsolutePath(const std::string &filepath); + +// To and from UTF-8 unicode conversion functions + +// Convert a unicode code point into a UTF-8 representation by appending it +// to a string. Returns the number of bytes generated. +inline int ToUTF8(uint32_t ucc, std::string *out) { +  FLATBUFFERS_ASSERT(!(ucc & 0x80000000));  // Top bit can't be set. +  // 6 possible encodings: http://en.wikipedia.org/wiki/UTF-8 +  for (int i = 0; i < 6; i++) { +    // Max bits this encoding can represent. +    uint32_t max_bits = 6 + i * 5 + static_cast<int>(!i); +    if (ucc < (1u << max_bits)) {  // does it fit? +      // Remaining bits not encoded in the first byte, store 6 bits each +      uint32_t remain_bits = i * 6; +      // Store first byte: +      (*out) += static_cast<char>((0xFE << (max_bits - remain_bits)) | +                                  (ucc >> remain_bits)); +      // Store remaining bytes: +      for (int j = i - 1; j >= 0; j--) { +        (*out) += static_cast<char>(((ucc >> (j * 6)) & 0x3F) | 0x80); +      } +      return i + 1;  // Return the number of bytes added. +    } +  } +  FLATBUFFERS_ASSERT(0);  // Impossible to arrive here. +  return -1; +} + +// Converts whatever prefix of the incoming string corresponds to a valid +// UTF-8 sequence into a unicode code. The incoming pointer will have been +// advanced past all bytes parsed. +// returns -1 upon corrupt UTF-8 encoding (ignore the incoming pointer in +// this case). +inline int FromUTF8(const char **in) { +  int len = 0; +  // Count leading 1 bits. +  for (int mask = 0x80; mask >= 0x04; mask >>= 1) { +    if (**in & mask) { +      len++; +    } else { +      break; +    } +  } +  if ((static_cast<unsigned char>(**in) << len) & 0x80) +    return -1;  // Bit after leading 1's must be 0. +  if (!len) return *(*in)++; +  // UTF-8 encoded values with a length are between 2 and 4 bytes. +  if (len < 2 || len > 4) { return -1; } +  // Grab initial bits of the code. +  int ucc = *(*in)++ & ((1 << (7 - len)) - 1); +  for (int i = 0; i < len - 1; i++) { +    if ((**in & 0xC0) != 0x80) return -1;  // Upper bits must 1 0. +    ucc <<= 6; +    ucc |= *(*in)++ & 0x3F;  // Grab 6 more bits of the code. +  } +  // UTF-8 cannot encode values between 0xD800 and 0xDFFF (reserved for +  // UTF-16 surrogate pairs). +  if (ucc >= 0xD800 && ucc <= 0xDFFF) { return -1; } +  // UTF-8 must represent code points in their shortest possible encoding. +  switch (len) { +    case 2: +      // Two bytes of UTF-8 can represent code points from U+0080 to U+07FF. +      if (ucc < 0x0080 || ucc > 0x07FF) { return -1; } +      break; +    case 3: +      // Three bytes of UTF-8 can represent code points from U+0800 to U+FFFF. +      if (ucc < 0x0800 || ucc > 0xFFFF) { return -1; } +      break; +    case 4: +      // Four bytes of UTF-8 can represent code points from U+10000 to U+10FFFF. +      if (ucc < 0x10000 || ucc > 0x10FFFF) { return -1; } +      break; +  } +  return ucc; +} + +#ifndef FLATBUFFERS_PREFER_PRINTF +// Wraps a string to a maximum length, inserting new lines where necessary. Any +// existing whitespace will be collapsed down to a single space. A prefix or +// suffix can be provided, which will be inserted before or after a wrapped +// line, respectively. +inline std::string WordWrap(const std::string in, size_t max_length, +                            const std::string wrapped_line_prefix, +                            const std::string wrapped_line_suffix) { +  std::istringstream in_stream(in); +  std::string wrapped, line, word; + +  in_stream >> word; +  line = word; + +  while (in_stream >> word) { +    if ((line.length() + 1 + word.length() + wrapped_line_suffix.length()) < +        max_length) { +      line += " " + word; +    } else { +      wrapped += line + wrapped_line_suffix + "\n"; +      line = wrapped_line_prefix + word; +    } +  } +  wrapped += line; + +  return wrapped; +} +#endif  // !FLATBUFFERS_PREFER_PRINTF + +inline bool EscapeString(const char *s, size_t length, std::string *_text, +                         bool allow_non_utf8, bool natural_utf8) { +  std::string &text = *_text; +  text += "\""; +  for (uoffset_t i = 0; i < length; i++) { +    char c = s[i]; +    switch (c) { +      case '\n': text += "\\n"; break; +      case '\t': text += "\\t"; break; +      case '\r': text += "\\r"; break; +      case '\b': text += "\\b"; break; +      case '\f': text += "\\f"; break; +      case '\"': text += "\\\""; break; +      case '\\': text += "\\\\"; break; +      default: +        if (c >= ' ' && c <= '~') { +          text += c; +        } else { +          // Not printable ASCII data. Let's see if it's valid UTF-8 first: +          const char *utf8 = s + i; +          int ucc = FromUTF8(&utf8); +          if (ucc < 0) { +            if (allow_non_utf8) { +              text += "\\x"; +              text += IntToStringHex(static_cast<uint8_t>(c), 2); +            } else { +              // There are two cases here: +              // +              // 1) We reached here by parsing an IDL file. In that case, +              // we previously checked for non-UTF-8, so we shouldn't reach +              // here. +              // +              // 2) We reached here by someone calling GenerateText() +              // on a previously-serialized flatbuffer. The data might have +              // non-UTF-8 Strings, or might be corrupt. +              // +              // In both cases, we have to give up and inform the caller +              // they have no JSON. +              return false; +            } +          } else { +            if (natural_utf8) { +              // utf8 points to past all utf-8 bytes parsed +              text.append(s + i, static_cast<size_t>(utf8 - s - i)); +            } else if (ucc <= 0xFFFF) { +              // Parses as Unicode within JSON's \uXXXX range, so use that. +              text += "\\u"; +              text += IntToStringHex(ucc, 4); +            } else if (ucc <= 0x10FFFF) { +              // Encode Unicode SMP values to a surrogate pair using two \u +              // escapes. +              uint32_t base = ucc - 0x10000; +              auto high_surrogate = (base >> 10) + 0xD800; +              auto low_surrogate = (base & 0x03FF) + 0xDC00; +              text += "\\u"; +              text += IntToStringHex(high_surrogate, 4); +              text += "\\u"; +              text += IntToStringHex(low_surrogate, 4); +            } +            // Skip past characters recognized. +            i = static_cast<uoffset_t>(utf8 - s - 1); +          } +        } +        break; +    } +  } +  text += "\""; +  return true; +} + +// Remove paired quotes in a string: "text"|'text' -> text. +std::string RemoveStringQuotes(const std::string &s); + +// Change th global C-locale to locale with name <locale_name>. +// Returns an actual locale name in <_value>, useful if locale_name is "" or +// null. +bool SetGlobalTestLocale(const char *locale_name, +                         std::string *_value = nullptr); + +// Read (or test) a value of environment variable. +bool ReadEnvironmentVariable(const char *var_name, +                             std::string *_value = nullptr); + +}  // namespace flatbuffers + +#endif  // FLATBUFFERS_UTIL_H_ | 
