LCOV - code coverage report
Current view: top level - third_party/flatbuffers - flexbuffers.h (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 221 403 54.8 %
Date: 2026-06-19 21:24:00 Functions: 54 89 60.7 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2017 Google Inc. All rights reserved.
       3             :  *
       4             :  * Licensed under the Apache License, Version 2.0 (the "License");
       5             :  * you may not use this file except in compliance with the License.
       6             :  * You may obtain a copy of the License at
       7             :  *
       8             :  *     http://www.apache.org/licenses/LICENSE-2.0
       9             :  *
      10             :  * Unless required by applicable law or agreed to in writing, software
      11             :  * distributed under the License is distributed on an "AS IS" BASIS,
      12             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13             :  * See the License for the specific language governing permissions and
      14             :  * limitations under the License.
      15             :  */
      16             : 
      17             : #ifndef FLATBUFFERS_FLEXBUFFERS_H_
      18             : #define FLATBUFFERS_FLEXBUFFERS_H_
      19             : 
      20             : #include <map>
      21             : // Used to select STL variant.
      22             : #include "flatbuffers/base.h"
      23             : // We use the basic binary writing functions from the regular FlatBuffers.
      24             : #include "flatbuffers/util.h"
      25             : 
      26             : #ifdef _MSC_VER
      27             : #  include <intrin.h>
      28             : #endif
      29             : 
      30             : #if defined(_MSC_VER)
      31             : #  pragma warning(push)
      32             : #  pragma warning(disable : 4127)  // C4127: conditional expression is constant
      33             : #endif
      34             : 
      35             : namespace flexbuffers {
      36             : 
      37             : class Reference;
      38             : class Map;
      39             : 
      40             : // These are used in the lower 2 bits of a type field to determine the size of
      41             : // the elements (and or size field) of the item pointed to (e.g. vector).
      42             : enum BitWidth {
      43             :   BIT_WIDTH_8 = 0,
      44             :   BIT_WIDTH_16 = 1,
      45             :   BIT_WIDTH_32 = 2,
      46             :   BIT_WIDTH_64 = 3,
      47             : };
      48             : 
      49             : // These are used as the upper 6 bits of a type field to indicate the actual
      50             : // type.
      51             : enum Type {
      52             :   FBT_NULL = 0,
      53             :   FBT_INT = 1,
      54             :   FBT_UINT = 2,
      55             :   FBT_FLOAT = 3,
      56             :   // Types above stored inline, types below (except FBT_BOOL) store an offset.
      57             :   FBT_KEY = 4,
      58             :   FBT_STRING = 5,
      59             :   FBT_INDIRECT_INT = 6,
      60             :   FBT_INDIRECT_UINT = 7,
      61             :   FBT_INDIRECT_FLOAT = 8,
      62             :   FBT_MAP = 9,
      63             :   FBT_VECTOR = 10,      // Untyped.
      64             :   FBT_VECTOR_INT = 11,  // Typed any size (stores no type table).
      65             :   FBT_VECTOR_UINT = 12,
      66             :   FBT_VECTOR_FLOAT = 13,
      67             :   FBT_VECTOR_KEY = 14,
      68             :   // DEPRECATED, use FBT_VECTOR or FBT_VECTOR_KEY instead.
      69             :   // Read test.cpp/FlexBuffersDeprecatedTest() for details on why.
      70             :   FBT_VECTOR_STRING_DEPRECATED = 15,
      71             :   FBT_VECTOR_INT2 = 16,  // Typed tuple (no type table, no size field).
      72             :   FBT_VECTOR_UINT2 = 17,
      73             :   FBT_VECTOR_FLOAT2 = 18,
      74             :   FBT_VECTOR_INT3 = 19,  // Typed triple (no type table, no size field).
      75             :   FBT_VECTOR_UINT3 = 20,
      76             :   FBT_VECTOR_FLOAT3 = 21,
      77             :   FBT_VECTOR_INT4 = 22,  // Typed quad (no type table, no size field).
      78             :   FBT_VECTOR_UINT4 = 23,
      79             :   FBT_VECTOR_FLOAT4 = 24,
      80             :   FBT_BLOB = 25,
      81             :   FBT_BOOL = 26,
      82             :   FBT_VECTOR_BOOL =
      83             :       36,  // To Allow the same type of conversion of type to vector type
      84             : 
      85             :   FBT_MAX_TYPE = 37
      86             : };
      87             : 
      88      182852 : inline bool IsInline(Type t) { return t <= FBT_FLOAT || t == FBT_BOOL; }
      89             : 
      90             : inline bool IsTypedVectorElementType(Type t) {
      91             :   return (t >= FBT_INT && t <= FBT_STRING) || t == FBT_BOOL;
      92             : }
      93             : 
      94           0 : inline bool IsTypedVector(Type t) {
      95           0 :   return (t >= FBT_VECTOR_INT && t <= FBT_VECTOR_STRING_DEPRECATED) ||
      96           0 :          t == FBT_VECTOR_BOOL;
      97             : }
      98             : 
      99           0 : inline bool IsFixedTypedVector(Type t) {
     100           0 :   return t >= FBT_VECTOR_INT2 && t <= FBT_VECTOR_FLOAT4;
     101             : }
     102             : 
     103             : inline Type ToTypedVector(Type t, size_t fixed_len = 0) {
     104             :   FLATBUFFERS_ASSERT(IsTypedVectorElementType(t));
     105             :   switch (fixed_len) {
     106             :     case 0: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT);
     107             :     case 2: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT2);
     108             :     case 3: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT3);
     109             :     case 4: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT4);
     110             :     default: FLATBUFFERS_ASSERT(0); return FBT_NULL;
     111             :   }
     112             : }
     113             : 
     114           0 : inline Type ToTypedVectorElementType(Type t) {
     115           0 :   FLATBUFFERS_ASSERT(IsTypedVector(t));
     116           0 :   return static_cast<Type>(t - FBT_VECTOR_INT + FBT_INT);
     117             : }
     118             : 
     119           0 : inline Type ToFixedTypedVectorElementType(Type t, uint8_t *len) {
     120           0 :   FLATBUFFERS_ASSERT(IsFixedTypedVector(t));
     121           0 :   auto fixed_type = t - FBT_VECTOR_INT2;
     122           0 :   *len = static_cast<uint8_t>(fixed_type / 3 +
     123             :                               2);  // 3 types each, starting from length 2.
     124           0 :   return static_cast<Type>(fixed_type % 3 + FBT_INT);
     125             : }
     126             : 
     127             : // TODO: implement proper support for 8/16bit floats, or decide not to
     128             : // support them.
     129             : typedef int16_t half;
     130             : typedef int8_t quarter;
     131             : 
     132             : // TODO: can we do this without conditionals using intrinsics or inline asm
     133             : // on some platforms? Given branch prediction the method below should be
     134             : // decently quick, but it is the most frequently executed function.
     135             : // We could do an (unaligned) 64-bit read if we ifdef out the platforms for
     136             : // which that doesn't work (or where we'd read into un-owned memory).
     137             : template<typename R, typename T1, typename T2, typename T4, typename T8>
     138      496383 : R ReadSizedScalar(const uint8_t *data, uint8_t byte_width) {
     139             :   return byte_width < 4
     140      992766 :              ? (byte_width < 2
     141      496383 :                     ? static_cast<R>(flatbuffers::ReadScalar<T1>(data))
     142      184711 :                     : static_cast<R>(flatbuffers::ReadScalar<T2>(data)))
     143             :              : (byte_width < 8
     144           0 :                     ? static_cast<R>(flatbuffers::ReadScalar<T4>(data))
     145      496383 :                     : static_cast<R>(flatbuffers::ReadScalar<T8>(data)));
     146             : }
     147             : 
     148           0 : inline int64_t ReadInt64(const uint8_t *data, uint8_t byte_width) {
     149           0 :   return ReadSizedScalar<int64_t, int8_t, int16_t, int32_t, int64_t>(
     150           0 :       data, byte_width);
     151             : }
     152             : 
     153      496383 : inline uint64_t ReadUInt64(const uint8_t *data, uint8_t byte_width) {
     154             :   // This is the "hottest" function (all offset lookups use this), so worth
     155             :   // optimizing if possible.
     156             :   // TODO: GCC apparently replaces memcpy by a rep movsb, but only if count is a
     157             :   // constant, which here it isn't. Test if memcpy is still faster than
     158             :   // the conditionals in ReadSizedScalar. Can also use inline asm.
     159             : 
     160             :   // clang-format off
     161             :   #if defined(_MSC_VER) && defined(_M_X64) && !defined(_M_ARM64EC)
     162             :   // This is 64-bit Windows only, __movsb does not work on 32-bit Windows.
     163             :     uint64_t u = 0;
     164             :     __movsb(reinterpret_cast<uint8_t *>(&u),
     165             :             reinterpret_cast<const uint8_t *>(data), byte_width);
     166             :     return flatbuffers::EndianScalar(u);
     167             :   #else
     168      496383 :     return ReadSizedScalar<uint64_t, uint8_t, uint16_t, uint32_t, uint64_t>(
     169      496383 :              data, byte_width);
     170             :   #endif
     171             :   // clang-format on
     172             : }
     173             : 
     174           0 : inline double ReadDouble(const uint8_t *data, uint8_t byte_width) {
     175           0 :   return ReadSizedScalar<double, quarter, half, float, double>(data,
     176           0 :                                                                byte_width);
     177             : }
     178             : 
     179      183341 : inline const uint8_t *Indirect(const uint8_t *offset, uint8_t byte_width) {
     180      183341 :   return offset - ReadUInt64(offset, byte_width);
     181             : }
     182             : 
     183             : template<typename T> const uint8_t *Indirect(const uint8_t *offset) {
     184             :   return offset - flatbuffers::ReadScalar<T>(offset);
     185             : }
     186             : 
     187             : inline BitWidth WidthU(uint64_t u) {
     188             : #define FLATBUFFERS_GET_FIELD_BIT_WIDTH(value, width)                   \
     189             :   {                                                                     \
     190             :     if (!((u) & ~((1ULL << (width)) - 1ULL))) return BIT_WIDTH_##width; \
     191             :   }
     192             :   FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 8);
     193             :   FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 16);
     194             :   FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 32);
     195             : #undef FLATBUFFERS_GET_FIELD_BIT_WIDTH
     196             :   return BIT_WIDTH_64;
     197             : }
     198             : 
     199             : inline BitWidth WidthI(int64_t i) {
     200             :   auto u = static_cast<uint64_t>(i) << 1;
     201             :   return WidthU(i >= 0 ? u : ~u);
     202             : }
     203             : 
     204             : inline BitWidth WidthF(double f) {
     205             :   return static_cast<double>(static_cast<float>(f)) == f ? BIT_WIDTH_32
     206             :                                                          : BIT_WIDTH_64;
     207             : }
     208             : 
     209             : // Base class of all types below.
     210             : // Points into the data buffer and allows access to one type.
     211             : class Object {
     212             :  public:
     213      131056 :   Object(const uint8_t *data, uint8_t byte_width)
     214      131056 :       : data_(data), byte_width_(byte_width) {}
     215             : 
     216             :  protected:
     217             :   const uint8_t *data_;
     218             :   uint8_t byte_width_;
     219             : };
     220             : 
     221             : // Object that has a size, obtained either from size prefix, or elsewhere.
     222             : class Sized : public Object {
     223             :  public:
     224             :   // Size prefix.
     225      131056 :   Sized(const uint8_t *data, uint8_t byte_width)
     226      131056 :       : Object(data, byte_width), size_(read_size()) {}
     227             :   // Manual size.
     228           0 :   Sized(const uint8_t *data, uint8_t byte_width, size_t sz)
     229           0 :       : Object(data, byte_width), size_(sz) {}
     230      417644 :   size_t size() const { return size_; }
     231             :   // Access size stored in `byte_width_` bytes before data_ pointer.
     232      131056 :   size_t read_size() const {
     233      131056 :     return static_cast<size_t>(ReadUInt64(data_ - byte_width_, byte_width_));
     234             :   }
     235             : 
     236             :  protected:
     237             :   size_t size_;
     238             : };
     239             : 
     240             : class String : public Sized {
     241             :  public:
     242             :   // Size prefix.
     243        6318 :   String(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {}
     244             :   // Manual size.
     245           0 :   String(const uint8_t *data, uint8_t byte_width, size_t sz)
     246           0 :       : Sized(data, byte_width, sz) {}
     247             : 
     248        2106 :   size_t length() const { return size(); }
     249        6318 :   const char *c_str() const { return reinterpret_cast<const char *>(data_); }
     250             :   std::string str() const { return std::string(c_str(), size()); }
     251             : 
     252           0 :   static String EmptyString() {
     253             :     static const char *empty_string = "";
     254           0 :     return String(reinterpret_cast<const uint8_t *>(empty_string), 1, 0);
     255             :   }
     256             :   bool IsTheEmptyString() const { return data_ == EmptyString().data_; }
     257             : };
     258             : 
     259             : class Blob : public Sized {
     260             :  public:
     261           0 :   Blob(const uint8_t *data_buf, uint8_t byte_width)
     262           0 :       : Sized(data_buf, byte_width) {}
     263             : 
     264           0 :   static Blob EmptyBlob() {
     265             :     static const uint8_t empty_blob[] = { 0 /*len*/ };
     266           0 :     return Blob(empty_blob + 1, 1);
     267             :   }
     268             :   bool IsTheEmptyBlob() const { return data_ == EmptyBlob().data_; }
     269           0 :   const uint8_t *data() const { return data_; }
     270             : };
     271             : 
     272             : class Vector : public Sized {
     273             :  public:
     274       45632 :   Vector(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {}
     275             : 
     276             :   Reference operator[](size_t i) const;
     277             : 
     278           0 :   static Vector EmptyVector() {
     279             :     static const uint8_t empty_vector[] = { 0 /*len*/ };
     280           0 :     return Vector(empty_vector + 1, 1);
     281             :   }
     282             :   bool IsTheEmptyVector() const { return data_ == EmptyVector().data_; }
     283             : };
     284             : 
     285             : class TypedVector : public Sized {
     286             :  public:
     287       33222 :   TypedVector(const uint8_t *data, uint8_t byte_width, Type element_type)
     288       33222 :       : Sized(data, byte_width), type_(element_type) {}
     289             : 
     290             :   Reference operator[](size_t i) const;
     291             : 
     292           0 :   static TypedVector EmptyTypedVector() {
     293             :     static const uint8_t empty_typed_vector[] = { 0 /*len*/ };
     294           0 :     return TypedVector(empty_typed_vector + 1, 1, FBT_INT);
     295             :   }
     296             :   bool IsTheEmptyVector() const {
     297             :     return data_ == TypedVector::EmptyTypedVector().data_;
     298             :   }
     299             : 
     300             :   Type ElementType() { return type_; }
     301             : 
     302             :   friend Reference;
     303             : 
     304             :  private:
     305             :   Type type_;
     306             : 
     307             :   friend Map;
     308             : };
     309             : 
     310             : class FixedTypedVector : public Object {
     311             :  public:
     312           0 :   FixedTypedVector(const uint8_t *data, uint8_t byte_width, Type element_type,
     313             :                    uint8_t len)
     314           0 :       : Object(data, byte_width), type_(element_type), len_(len) {}
     315             : 
     316             :   Reference operator[](size_t i) const;
     317             : 
     318           0 :   static FixedTypedVector EmptyFixedTypedVector() {
     319             :     static const uint8_t fixed_empty_vector[] = { 0 /* unused */ };
     320           0 :     return FixedTypedVector(fixed_empty_vector, 1, FBT_INT, 0);
     321             :   }
     322             :   bool IsTheEmptyFixedTypedVector() const {
     323             :     return data_ == FixedTypedVector::EmptyFixedTypedVector().data_;
     324             :   }
     325             : 
     326             :   Type ElementType() const { return type_; }
     327           0 :   uint8_t size() const { return len_; }
     328             : 
     329             :  private:
     330             :   Type type_;
     331             :   uint8_t len_;
     332             : };
     333             : 
     334             : class Map : public Vector {
     335             :  public:
     336       12392 :   Map(const uint8_t *data, uint8_t byte_width) : Vector(data, byte_width) {}
     337             : 
     338             :   Reference operator[](const char *key) const;
     339             :   Reference operator[](const std::string &key) const;
     340             : 
     341       12392 :   Vector Values() const { return Vector(data_, byte_width_); }
     342             : 
     343       12392 :   TypedVector Keys() const {
     344       12392 :     const size_t num_prefixed_fields = 3;
     345       12392 :     auto keys_offset = data_ - byte_width_ * num_prefixed_fields;
     346       12392 :     return TypedVector(Indirect(keys_offset, byte_width_),
     347             :                        static_cast<uint8_t>(
     348       12392 :                            ReadUInt64(keys_offset + byte_width_, byte_width_)),
     349       12392 :                        FBT_KEY);
     350             :   }
     351             : 
     352           0 :   static Map EmptyMap() {
     353             :     static const uint8_t empty_map[] = {
     354             :       0 /*keys_len*/, 0 /*keys_offset*/, 1 /*keys_width*/, 0 /*len*/
     355             :     };
     356           0 :     return Map(empty_map + 4, 1);
     357             :   }
     358             : 
     359             :   bool IsTheEmptyMap() const { return data_ == EmptyMap().data_; }
     360             : };
     361             : 
     362             : template<typename T>
     363           6 : void AppendToString(std::string &s, T &&v, bool keys_quoted) {
     364           6 :   s += "[ ";
     365          14 :   for (size_t i = 0; i < v.size(); i++) {
     366           8 :     if (i) s += ", ";
     367           8 :     v[i].ToString(true, keys_quoted, s);
     368             :   }
     369           6 :   s += " ]";
     370           6 : }
     371             : 
     372             : class Reference {
     373             :  public:
     374             :   Reference()
     375             :       : data_(nullptr), parent_width_(0), byte_width_(0), type_(FBT_NULL) {}
     376             : 
     377      152221 :   Reference(const uint8_t *data, uint8_t parent_width, uint8_t byte_width,
     378             :             Type type)
     379      152221 :       : data_(data),
     380             :         parent_width_(parent_width),
     381             :         byte_width_(byte_width),
     382      152221 :         type_(type) {}
     383             : 
     384      142502 :   Reference(const uint8_t *data, uint8_t parent_width, uint8_t packed_type)
     385      142502 :       : data_(data), parent_width_(parent_width) {
     386      142502 :     byte_width_ = 1U << static_cast<BitWidth>(packed_type & 3);
     387      142502 :     type_ = static_cast<Type>(packed_type >> 2);
     388      142502 :   }
     389             : 
     390             :   Type GetType() const { return type_; }
     391             : 
     392       39870 :   bool IsNull() const { return type_ == FBT_NULL; }
     393       20840 :   bool IsBool() const { return type_ == FBT_BOOL; }
     394       48032 :   bool IsInt() const { return type_ == FBT_INT || type_ == FBT_INDIRECT_INT; }
     395       48032 :   bool IsUInt() const {
     396       48032 :     return type_ == FBT_UINT || type_ == FBT_INDIRECT_UINT;
     397             :   }
     398             :   bool IsIntOrUint() const { return IsInt() || IsUInt(); }
     399       39870 :   bool IsFloat() const {
     400       39870 :     return type_ == FBT_FLOAT || type_ == FBT_INDIRECT_FLOAT;
     401             :   }
     402             :   bool IsNumeric() const { return IsIntOrUint() || IsFloat(); }
     403             :   bool IsString() const { return type_ == FBT_STRING; }
     404       93147 :   bool IsKey() const { return type_ == FBT_KEY; }
     405           6 :   bool IsVector() const { return type_ == FBT_VECTOR || type_ == FBT_MAP; }
     406             :   bool IsUntypedVector() const { return type_ == FBT_VECTOR; }
     407           0 :   bool IsTypedVector() const { return flexbuffers::IsTypedVector(type_); }
     408           0 :   bool IsFixedTypedVector() const {
     409           0 :     return flexbuffers::IsFixedTypedVector(type_);
     410             :   }
     411             :   bool IsAnyVector() const {
     412             :     return (IsTypedVector() || IsFixedTypedVector() || IsVector());
     413             :   }
     414       12398 :   bool IsMap() const { return type_ == FBT_MAP; }
     415           0 :   bool IsBlob() const { return type_ == FBT_BLOB; }
     416        8442 :   bool AsBool() const {
     417        8442 :     return (type_ == FBT_BOOL ? ReadUInt64(data_, parent_width_)
     418        8442 :                               : AsUInt64()) != 0;
     419             :   }
     420             : 
     421             :   // Reads any type as a int64_t. Never fails, does most sensible conversion.
     422             :   // Truncates floats, strings are attempted to be parsed for a number,
     423             :   // vectors/maps return their size. Returns 0 if all else fails.
     424           0 :   int64_t AsInt64() const {
     425           0 :     if (type_ == FBT_INT) {
     426             :       // A fast path for the common case.
     427           0 :       return ReadInt64(data_, parent_width_);
     428             :     } else
     429           0 :       switch (type_) {
     430           0 :         case FBT_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_);
     431           0 :         case FBT_UINT: return ReadUInt64(data_, parent_width_);
     432           0 :         case FBT_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_);
     433           0 :         case FBT_FLOAT:
     434           0 :           return static_cast<int64_t>(ReadDouble(data_, parent_width_));
     435           0 :         case FBT_INDIRECT_FLOAT:
     436           0 :           return static_cast<int64_t>(ReadDouble(Indirect(), byte_width_));
     437           0 :         case FBT_NULL: return 0;
     438           0 :         case FBT_STRING: return flatbuffers::StringToInt(AsString().c_str());
     439           0 :         case FBT_VECTOR: return static_cast<int64_t>(AsVector().size());
     440           0 :         case FBT_BOOL: return ReadInt64(data_, parent_width_);
     441           0 :         default:
     442             :           // Convert other things to int.
     443           0 :           return 0;
     444             :       }
     445             :   }
     446             : 
     447             :   // TODO: could specialize these to not use AsInt64() if that saves
     448             :   // extension ops in generated code, and use a faster op than ReadInt64.
     449             :   int32_t AsInt32() const { return static_cast<int32_t>(AsInt64()); }
     450             :   int16_t AsInt16() const { return static_cast<int16_t>(AsInt64()); }
     451             :   int8_t AsInt8() const { return static_cast<int8_t>(AsInt64()); }
     452             : 
     453        8162 :   uint64_t AsUInt64() const {
     454        8162 :     if (type_ == FBT_UINT) {
     455             :       // A fast path for the common case.
     456        8162 :       return ReadUInt64(data_, parent_width_);
     457             :     } else
     458           0 :       switch (type_) {
     459           0 :         case FBT_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_);
     460           0 :         case FBT_INT: return ReadInt64(data_, parent_width_);
     461           0 :         case FBT_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_);
     462           0 :         case FBT_FLOAT:
     463           0 :           return static_cast<uint64_t>(ReadDouble(data_, parent_width_));
     464           0 :         case FBT_INDIRECT_FLOAT:
     465           0 :           return static_cast<uint64_t>(ReadDouble(Indirect(), byte_width_));
     466           0 :         case FBT_NULL: return 0;
     467           0 :         case FBT_STRING: return flatbuffers::StringToUInt(AsString().c_str());
     468           0 :         case FBT_VECTOR: return static_cast<uint64_t>(AsVector().size());
     469           0 :         case FBT_BOOL: return ReadUInt64(data_, parent_width_);
     470           0 :         default:
     471             :           // Convert other things to uint.
     472           0 :           return 0;
     473             :       }
     474             :   }
     475             : 
     476             :   uint32_t AsUInt32() const { return static_cast<uint32_t>(AsUInt64()); }
     477             :   uint16_t AsUInt16() const { return static_cast<uint16_t>(AsUInt64()); }
     478             :   uint8_t AsUInt8() const { return static_cast<uint8_t>(AsUInt64()); }
     479             : 
     480           0 :   double AsDouble() const {
     481           0 :     if (type_ == FBT_FLOAT) {
     482             :       // A fast path for the common case.
     483           0 :       return ReadDouble(data_, parent_width_);
     484             :     } else
     485           0 :       switch (type_) {
     486           0 :         case FBT_INDIRECT_FLOAT: return ReadDouble(Indirect(), byte_width_);
     487           0 :         case FBT_INT:
     488           0 :           return static_cast<double>(ReadInt64(data_, parent_width_));
     489           0 :         case FBT_UINT:
     490           0 :           return static_cast<double>(ReadUInt64(data_, parent_width_));
     491           0 :         case FBT_INDIRECT_INT:
     492           0 :           return static_cast<double>(ReadInt64(Indirect(), byte_width_));
     493           0 :         case FBT_INDIRECT_UINT:
     494           0 :           return static_cast<double>(ReadUInt64(Indirect(), byte_width_));
     495           0 :         case FBT_NULL: return 0.0;
     496           0 :         case FBT_STRING: {
     497             :           double d;
     498           0 :           flatbuffers::StringToNumber(AsString().c_str(), &d);
     499           0 :           return d;
     500             :         }
     501           0 :         case FBT_VECTOR: return static_cast<double>(AsVector().size());
     502           0 :         case FBT_BOOL:
     503           0 :           return static_cast<double>(ReadUInt64(data_, parent_width_));
     504           0 :         default:
     505             :           // Convert strings and other things to float.
     506           0 :           return 0;
     507             :       }
     508             :   }
     509             : 
     510             :   float AsFloat() const { return static_cast<float>(AsDouble()); }
     511             : 
     512       45115 :   const char *AsKey() const {
     513       45115 :     if (type_ == FBT_KEY || type_ == FBT_STRING) {
     514       45115 :       return reinterpret_cast<const char *>(Indirect());
     515             :     } else {
     516           0 :       return "";
     517             :     }
     518             :   }
     519             : 
     520             :   // This function returns the empty string if you try to read something that
     521             :   // is not a string or key.
     522           0 :   String AsString() const {
     523           0 :     if (type_ == FBT_STRING) {
     524           0 :       return String(Indirect(), byte_width_);
     525           0 :     } else if (type_ == FBT_KEY) {
     526           0 :       auto key = Indirect();
     527           0 :       return String(key, byte_width_,
     528           0 :                     strlen(reinterpret_cast<const char *>(key)));
     529             :     } else {
     530           0 :       return String::EmptyString();
     531             :     }
     532             :   }
     533             : 
     534             :   // Unlike AsString(), this will convert any type to a std::string.
     535             :   std::string ToString() const {
     536             :     std::string s;
     537             :     ToString(false, false, s);
     538             :     return s;
     539             :   }
     540             : 
     541             :   // Convert any type to a JSON-like string. strings_quoted determines if
     542             :   // string values at the top level receive "" quotes (inside other values
     543             :   // they always do). keys_quoted determines if keys are quoted, at any level.
     544             :   // TODO(wvo): add further options to have indentation/newlines.
     545       95253 :   void ToString(bool strings_quoted, bool keys_quoted, std::string &s) const {
     546       95253 :     if (type_ == FBT_STRING) {
     547        2106 :       String str(Indirect(), byte_width_);
     548        2106 :       if (strings_quoted) {
     549        2106 :         flatbuffers::EscapeString(str.c_str(), str.length(), &s, true, false);
     550             :       } else {
     551           0 :         s.append(str.c_str(), str.length());
     552             :       }
     553       93147 :     } else if (IsKey()) {
     554       45115 :       auto str = AsKey();
     555       45115 :       if (keys_quoted) {
     556       45115 :         flatbuffers::EscapeString(str, strlen(str), &s, true, false);
     557             :       } else {
     558           0 :         s += str;
     559             :       }
     560       48032 :     } else if (IsInt()) {
     561           0 :       s += flatbuffers::NumToString(AsInt64());
     562       48032 :     } else if (IsUInt()) {
     563        8162 :       s += flatbuffers::NumToString(AsUInt64());
     564       39870 :     } else if (IsFloat()) {
     565           0 :       s += flatbuffers::NumToString(AsDouble());
     566       39870 :     } else if (IsNull()) {
     567       19030 :       s += "null";
     568       20840 :     } else if (IsBool()) {
     569        8442 :       s += AsBool() ? "true" : "false";
     570       12398 :     } else if (IsMap()) {
     571       12392 :       s += "{ ";
     572       12392 :       auto m = AsMap();
     573       12392 :       auto keys = m.Keys();
     574       12392 :       auto vals = m.Values();
     575       57507 :       for (size_t i = 0; i < keys.size(); i++) {
     576       45115 :         bool kq = keys_quoted;
     577       45115 :         if (!kq) {
     578             :           // FlexBuffers keys may contain arbitrary characters, only allow
     579             :           // unquoted if it looks like an "identifier":
     580           0 :           const char *p = keys[i].AsKey();
     581           0 :           if (!flatbuffers::is_alpha(*p) && *p != '_') {
     582           0 :             kq = true;
     583             :           } else {
     584           0 :             while (*++p) {
     585           0 :               if (!flatbuffers::is_alnum(*p) && *p != '_') {
     586           0 :                 kq = true;
     587           0 :                 break;
     588             :               }
     589             :             }
     590             :           }
     591             :         }
     592       45115 :         keys[i].ToString(true, kq, s);
     593       45115 :         s += ": ";
     594       45115 :         vals[i].ToString(true, keys_quoted, s);
     595       45115 :         if (i < keys.size() - 1) s += ", ";
     596             :       }
     597       12392 :       s += " }";
     598           6 :     } else if (IsVector()) {
     599           6 :       AppendToString<Vector>(s, AsVector(), keys_quoted);
     600           0 :     } else if (IsTypedVector()) {
     601           0 :       AppendToString<TypedVector>(s, AsTypedVector(), keys_quoted);
     602           0 :     } else if (IsFixedTypedVector()) {
     603           0 :       AppendToString<FixedTypedVector>(s, AsFixedTypedVector(), keys_quoted);
     604           0 :     } else if (IsBlob()) {
     605           0 :       auto blob = AsBlob();
     606           0 :       flatbuffers::EscapeString(reinterpret_cast<const char *>(blob.data()),
     607             :                                 blob.size(), &s, true, false);
     608             :     } else {
     609           0 :       s += "(?)";
     610             :     }
     611       95253 :   }
     612             : 
     613             :   // This function returns the empty blob if you try to read a not-blob.
     614             :   // Strings can be viewed as blobs too.
     615           0 :   Blob AsBlob() const {
     616           0 :     if (type_ == FBT_BLOB || type_ == FBT_STRING) {
     617           0 :       return Blob(Indirect(), byte_width_);
     618             :     } else {
     619           0 :       return Blob::EmptyBlob();
     620             :     }
     621             :   }
     622             : 
     623             :   // This function returns the empty vector if you try to read a not-vector.
     624             :   // Maps can be viewed as vectors too.
     625           6 :   Vector AsVector() const {
     626           6 :     if (type_ == FBT_VECTOR || type_ == FBT_MAP) {
     627           6 :       return Vector(Indirect(), byte_width_);
     628             :     } else {
     629           0 :       return Vector::EmptyVector();
     630             :     }
     631             :   }
     632             : 
     633           0 :   TypedVector AsTypedVector() const {
     634           0 :     if (IsTypedVector()) {
     635             :       auto tv =
     636           0 :           TypedVector(Indirect(), byte_width_, ToTypedVectorElementType(type_));
     637           0 :       if (tv.type_ == FBT_STRING) {
     638             :         // These can't be accessed as strings, since we don't know the bit-width
     639             :         // of the size field, see the declaration of
     640             :         // FBT_VECTOR_STRING_DEPRECATED above for details.
     641             :         // We change the type here to be keys, which are a subtype of strings,
     642             :         // and will ignore the size field. This will truncate strings with
     643             :         // embedded nulls.
     644           0 :         tv.type_ = FBT_KEY;
     645             :       }
     646           0 :       return tv;
     647             :     } else {
     648           0 :       return TypedVector::EmptyTypedVector();
     649             :     }
     650             :   }
     651             : 
     652           0 :   FixedTypedVector AsFixedTypedVector() const {
     653           0 :     if (IsFixedTypedVector()) {
     654           0 :       uint8_t len = 0;
     655           0 :       auto vtype = ToFixedTypedVectorElementType(type_, &len);
     656           0 :       return FixedTypedVector(Indirect(), byte_width_, vtype, len);
     657             :     } else {
     658           0 :       return FixedTypedVector::EmptyFixedTypedVector();
     659             :     }
     660             :   }
     661             : 
     662       12392 :   Map AsMap() const {
     663       12392 :     if (type_ == FBT_MAP) {
     664       12392 :       return Map(Indirect(), byte_width_);
     665             :     } else {
     666           0 :       return Map::EmptyMap();
     667             :     }
     668             :   }
     669             : 
     670             :   template<typename T> T As() const;
     671             : 
     672             :   // Experimental: Mutation functions.
     673             :   // These allow scalars in an already created buffer to be updated in-place.
     674             :   // Since by default scalars are stored in the smallest possible space,
     675             :   // the new value may not fit, in which case these functions return false.
     676             :   // To avoid this, you can construct the values you intend to mutate using
     677             :   // Builder::ForceMinimumBitWidth.
     678             :   bool MutateInt(int64_t i) {
     679             :     if (type_ == FBT_INT) {
     680             :       return Mutate(data_, i, parent_width_, WidthI(i));
     681             :     } else if (type_ == FBT_INDIRECT_INT) {
     682             :       return Mutate(Indirect(), i, byte_width_, WidthI(i));
     683             :     } else if (type_ == FBT_UINT) {
     684             :       auto u = static_cast<uint64_t>(i);
     685             :       return Mutate(data_, u, parent_width_, WidthU(u));
     686             :     } else if (type_ == FBT_INDIRECT_UINT) {
     687             :       auto u = static_cast<uint64_t>(i);
     688             :       return Mutate(Indirect(), u, byte_width_, WidthU(u));
     689             :     } else {
     690             :       return false;
     691             :     }
     692             :   }
     693             : 
     694             :   bool MutateBool(bool b) {
     695             :     return type_ == FBT_BOOL && Mutate(data_, b, parent_width_, BIT_WIDTH_8);
     696             :   }
     697             : 
     698             :   bool MutateUInt(uint64_t u) {
     699             :     if (type_ == FBT_UINT) {
     700             :       return Mutate(data_, u, parent_width_, WidthU(u));
     701             :     } else if (type_ == FBT_INDIRECT_UINT) {
     702             :       return Mutate(Indirect(), u, byte_width_, WidthU(u));
     703             :     } else if (type_ == FBT_INT) {
     704             :       auto i = static_cast<int64_t>(u);
     705             :       return Mutate(data_, i, parent_width_, WidthI(i));
     706             :     } else if (type_ == FBT_INDIRECT_INT) {
     707             :       auto i = static_cast<int64_t>(u);
     708             :       return Mutate(Indirect(), i, byte_width_, WidthI(i));
     709             :     } else {
     710             :       return false;
     711             :     }
     712             :   }
     713             : 
     714             :   bool MutateFloat(float f) {
     715             :     if (type_ == FBT_FLOAT) {
     716             :       return MutateF(data_, f, parent_width_, BIT_WIDTH_32);
     717             :     } else if (type_ == FBT_INDIRECT_FLOAT) {
     718             :       return MutateF(Indirect(), f, byte_width_, BIT_WIDTH_32);
     719             :     } else {
     720             :       return false;
     721             :     }
     722             :   }
     723             : 
     724             :   bool MutateFloat(double d) {
     725             :     if (type_ == FBT_FLOAT) {
     726             :       return MutateF(data_, d, parent_width_, WidthF(d));
     727             :     } else if (type_ == FBT_INDIRECT_FLOAT) {
     728             :       return MutateF(Indirect(), d, byte_width_, WidthF(d));
     729             :     } else {
     730             :       return false;
     731             :     }
     732             :   }
     733             : 
     734             :   bool MutateString(const char *str, size_t len) {
     735             :     auto s = AsString();
     736             :     if (s.IsTheEmptyString()) return false;
     737             :     // This is very strict, could allow shorter strings, but that creates
     738             :     // garbage.
     739             :     if (s.length() != len) return false;
     740             :     memcpy(const_cast<char *>(s.c_str()), str, len);
     741             :     return true;
     742             :   }
     743             :   bool MutateString(const char *str) { return MutateString(str, strlen(str)); }
     744             :   bool MutateString(const std::string &str) {
     745             :     return MutateString(str.data(), str.length());
     746             :   }
     747             : 
     748             :  private:
     749      170949 :   const uint8_t *Indirect() const {
     750      170949 :     return flexbuffers::Indirect(data_, parent_width_);
     751             :   }
     752             : 
     753             :   template<typename T>
     754             :   bool Mutate(const uint8_t *dest, T t, size_t byte_width,
     755             :               BitWidth value_width) {
     756             :     auto fits = static_cast<size_t>(static_cast<size_t>(1U) << value_width) <=
     757             :                 byte_width;
     758             :     if (fits) {
     759             :       t = flatbuffers::EndianScalar(t);
     760             :       memcpy(const_cast<uint8_t *>(dest), &t, byte_width);
     761             :     }
     762             :     return fits;
     763             :   }
     764             : 
     765             :   template<typename T>
     766             :   bool MutateF(const uint8_t *dest, T t, size_t byte_width,
     767             :                BitWidth value_width) {
     768             :     if (byte_width == sizeof(double))
     769             :       return Mutate(dest, static_cast<double>(t), byte_width, value_width);
     770             :     if (byte_width == sizeof(float))
     771             :       return Mutate(dest, static_cast<float>(t), byte_width, value_width);
     772             :     FLATBUFFERS_ASSERT(false);
     773             :     return false;
     774             :   }
     775             : 
     776             :   friend class Verifier;
     777             : 
     778             :   const uint8_t *data_;
     779             :   uint8_t parent_width_;
     780             :   uint8_t byte_width_;
     781             :   Type type_;
     782             : };
     783             : 
     784             : // Template specialization for As().
     785             : template<> inline bool Reference::As<bool>() const { return AsBool(); }
     786             : 
     787             : template<> inline int8_t Reference::As<int8_t>() const { return AsInt8(); }
     788             : template<> inline int16_t Reference::As<int16_t>() const { return AsInt16(); }
     789             : template<> inline int32_t Reference::As<int32_t>() const { return AsInt32(); }
     790             : template<> inline int64_t Reference::As<int64_t>() const { return AsInt64(); }
     791             : 
     792             : template<> inline uint8_t Reference::As<uint8_t>() const { return AsUInt8(); }
     793             : template<> inline uint16_t Reference::As<uint16_t>() const {
     794             :   return AsUInt16();
     795             : }
     796             : template<> inline uint32_t Reference::As<uint32_t>() const {
     797             :   return AsUInt32();
     798             : }
     799             : template<> inline uint64_t Reference::As<uint64_t>() const {
     800             :   return AsUInt64();
     801             : }
     802             : 
     803             : template<> inline double Reference::As<double>() const { return AsDouble(); }
     804             : template<> inline float Reference::As<float>() const { return AsFloat(); }
     805             : 
     806             : template<> inline String Reference::As<String>() const { return AsString(); }
     807             : template<> inline std::string Reference::As<std::string>() const {
     808             :   return AsString().str();
     809             : }
     810             : 
     811             : template<> inline Blob Reference::As<Blob>() const { return AsBlob(); }
     812             : template<> inline Vector Reference::As<Vector>() const { return AsVector(); }
     813             : template<> inline TypedVector Reference::As<TypedVector>() const {
     814             :   return AsTypedVector();
     815             : }
     816             : template<> inline FixedTypedVector Reference::As<FixedTypedVector>() const {
     817             :   return AsFixedTypedVector();
     818             : }
     819             : template<> inline Map Reference::As<Map>() const { return AsMap(); }
     820             : 
     821           0 : inline uint8_t PackedType(BitWidth bit_width, Type type) {
     822           0 :   return static_cast<uint8_t>(bit_width | (type << 2));
     823             : }
     824             : 
     825           0 : inline uint8_t NullPackedType() { return PackedType(BIT_WIDTH_8, FBT_NULL); }
     826             : 
     827             : // Vector accessors.
     828             : // Note: if you try to access outside of bounds, you get a Null value back
     829             : // instead. Normally this would be an assert, but since this is "dynamically
     830             : // typed" data, you may not want that (someone sends you a 2d vector and you
     831             : // wanted 3d).
     832             : // The Null converts seamlessly into a default value for any other type.
     833             : // TODO(wvo): Could introduce an #ifdef that makes this into an assert?
     834      131415 : inline Reference Vector::operator[](size_t i) const {
     835      131415 :   auto len = size();
     836      131415 :   if (i >= len) return Reference(nullptr, 1, NullPackedType());
     837      131415 :   auto packed_type = (data_ + len * byte_width_)[i];
     838      131415 :   auto elem = data_ + i * byte_width_;
     839      131415 :   return Reference(elem, byte_width_, packed_type);
     840             : }
     841             : 
     842      131391 : inline Reference TypedVector::operator[](size_t i) const {
     843      131391 :   auto len = size();
     844      131391 :   if (i >= len) return Reference(nullptr, 1, NullPackedType());
     845      131391 :   auto elem = data_ + i * byte_width_;
     846      131391 :   return Reference(elem, byte_width_, 1, type_);
     847             : }
     848             : 
     849           0 : inline Reference FixedTypedVector::operator[](size_t i) const {
     850           0 :   if (i >= len_) return Reference(nullptr, 1, NullPackedType());
     851           0 :   auto elem = data_ + i * byte_width_;
     852           0 :   return Reference(elem, byte_width_, 1, type_);
     853             : }
     854             : 
     855             : template<typename T> int KeyCompare(const void *key, const void *elem) {
     856             :   auto str_elem = reinterpret_cast<const char *>(
     857             :       Indirect<T>(reinterpret_cast<const uint8_t *>(elem)));
     858             :   auto skey = reinterpret_cast<const char *>(key);
     859             :   return strcmp(skey, str_elem);
     860             : }
     861             : 
     862             : inline Reference Map::operator[](const char *key) const {
     863             :   auto keys = Keys();
     864             :   // We can't pass keys.byte_width_ to the comparison function, so we have
     865             :   // to pick the right one ahead of time.
     866             :   int (*comp)(const void *, const void *) = nullptr;
     867             :   switch (keys.byte_width_) {
     868             :     case 1: comp = KeyCompare<uint8_t>; break;
     869             :     case 2: comp = KeyCompare<uint16_t>; break;
     870             :     case 4: comp = KeyCompare<uint32_t>; break;
     871             :     case 8: comp = KeyCompare<uint64_t>; break;
     872             :     default: FLATBUFFERS_ASSERT(false); return Reference();
     873             :   }
     874             :   auto res = std::bsearch(key, keys.data_, keys.size(), keys.byte_width_, comp);
     875             :   if (!res) return Reference(nullptr, 1, NullPackedType());
     876             :   auto i = (reinterpret_cast<uint8_t *>(res) - keys.data_) / keys.byte_width_;
     877             :   return (*static_cast<const Vector *>(this))[i];
     878             : }
     879             : 
     880             : inline Reference Map::operator[](const std::string &key) const {
     881             :   return (*this)[key.c_str()];
     882             : }
     883             : 
     884        5015 : inline Reference GetRoot(const uint8_t *buffer, size_t size) {
     885             :   // See Finish() below for the serialization counterpart of this.
     886             :   // The root starts at the end of the buffer, so we parse backwards from there.
     887        5015 :   auto end = buffer + size;
     888        5015 :   auto byte_width = *--end;
     889        5015 :   auto packed_type = *--end;
     890        5015 :   end -= byte_width;  // The root data item.
     891        5015 :   return Reference(end, byte_width, packed_type);
     892             : }
     893             : 
     894             : inline Reference GetRoot(const std::vector<uint8_t> &buffer) {
     895             :   return GetRoot(buffer.data(), buffer.size());
     896             : }
     897             : 
     898             : // Flags that configure how the Builder behaves.
     899             : // The "Share" flags determine if the Builder automatically tries to pool
     900             : // this type. Pooling can reduce the size of serialized data if there are
     901             : // multiple maps of the same kind, at the expense of slightly slower
     902             : // serialization (the cost of lookups) and more memory use (std::set).
     903             : // By default this is on for keys, but off for strings.
     904             : // Turn keys off if you have e.g. only one map.
     905             : // Turn strings on if you expect many non-unique string values.
     906             : // Additionally, sharing key vectors can save space if you have maps with
     907             : // identical field populations.
     908             : enum BuilderFlag {
     909             :   BUILDER_FLAG_NONE = 0,
     910             :   BUILDER_FLAG_SHARE_KEYS = 1,
     911             :   BUILDER_FLAG_SHARE_STRINGS = 2,
     912             :   BUILDER_FLAG_SHARE_KEYS_AND_STRINGS = 3,
     913             :   BUILDER_FLAG_SHARE_KEY_VECTORS = 4,
     914             :   BUILDER_FLAG_SHARE_ALL = 7,
     915             : };
     916             : 
     917             : class Builder FLATBUFFERS_FINAL_CLASS {
     918             :  public:
     919             :   Builder(size_t initial_size = 256,
     920             :           BuilderFlag flags = BUILDER_FLAG_SHARE_KEYS)
     921             :       : buf_(initial_size),
     922             :         finished_(false),
     923             :         has_duplicate_keys_(false),
     924             :         flags_(flags),
     925             :         force_min_bit_width_(BIT_WIDTH_8),
     926             :         key_pool(KeyOffsetCompare(buf_)),
     927             :         string_pool(StringOffsetCompare(buf_)) {
     928             :     buf_.clear();
     929             :   }
     930             : 
     931             : #ifdef FLATBUFFERS_DEFAULT_DECLARATION
     932             :   Builder(Builder &&) = default;
     933             :   Builder &operator=(Builder &&) = default;
     934             : #endif
     935             : 
     936             :   /// @brief Get the serialized buffer (after you call `Finish()`).
     937             :   /// @return Returns a vector owned by this class.
     938             :   const std::vector<uint8_t> &GetBuffer() const {
     939             :     Finished();
     940             :     return buf_;
     941             :   }
     942             : 
     943             :   // Size of the buffer. Does not include unfinished values.
     944             :   size_t GetSize() const { return buf_.size(); }
     945             : 
     946             :   // Reset all state so we can re-use the buffer.
     947             :   void Clear() {
     948             :     buf_.clear();
     949             :     stack_.clear();
     950             :     finished_ = false;
     951             :     // flags_ remains as-is;
     952             :     force_min_bit_width_ = BIT_WIDTH_8;
     953             :     key_pool.clear();
     954             :     string_pool.clear();
     955             :   }
     956             : 
     957             :   // All value constructing functions below have two versions: one that
     958             :   // takes a key (for placement inside a map) and one that doesn't (for inside
     959             :   // vectors and elsewhere).
     960             : 
     961             :   void Null() { stack_.push_back(Value()); }
     962             :   void Null(const char *key) {
     963             :     Key(key);
     964             :     Null();
     965             :   }
     966             : 
     967             :   void Int(int64_t i) { stack_.push_back(Value(i, FBT_INT, WidthI(i))); }
     968             :   void Int(const char *key, int64_t i) {
     969             :     Key(key);
     970             :     Int(i);
     971             :   }
     972             : 
     973             :   void UInt(uint64_t u) { stack_.push_back(Value(u, FBT_UINT, WidthU(u))); }
     974             :   void UInt(const char *key, uint64_t u) {
     975             :     Key(key);
     976             :     UInt(u);
     977             :   }
     978             : 
     979             :   void Float(float f) { stack_.push_back(Value(f)); }
     980             :   void Float(const char *key, float f) {
     981             :     Key(key);
     982             :     Float(f);
     983             :   }
     984             : 
     985             :   void Double(double f) { stack_.push_back(Value(f)); }
     986             :   void Double(const char *key, double d) {
     987             :     Key(key);
     988             :     Double(d);
     989             :   }
     990             : 
     991             :   void Bool(bool b) { stack_.push_back(Value(b)); }
     992             :   void Bool(const char *key, bool b) {
     993             :     Key(key);
     994             :     Bool(b);
     995             :   }
     996             : 
     997             :   void IndirectInt(int64_t i) { PushIndirect(i, FBT_INDIRECT_INT, WidthI(i)); }
     998             :   void IndirectInt(const char *key, int64_t i) {
     999             :     Key(key);
    1000             :     IndirectInt(i);
    1001             :   }
    1002             : 
    1003             :   void IndirectUInt(uint64_t u) {
    1004             :     PushIndirect(u, FBT_INDIRECT_UINT, WidthU(u));
    1005             :   }
    1006             :   void IndirectUInt(const char *key, uint64_t u) {
    1007             :     Key(key);
    1008             :     IndirectUInt(u);
    1009             :   }
    1010             : 
    1011             :   void IndirectFloat(float f) {
    1012             :     PushIndirect(f, FBT_INDIRECT_FLOAT, BIT_WIDTH_32);
    1013             :   }
    1014             :   void IndirectFloat(const char *key, float f) {
    1015             :     Key(key);
    1016             :     IndirectFloat(f);
    1017             :   }
    1018             : 
    1019             :   void IndirectDouble(double f) {
    1020             :     PushIndirect(f, FBT_INDIRECT_FLOAT, WidthF(f));
    1021             :   }
    1022             :   void IndirectDouble(const char *key, double d) {
    1023             :     Key(key);
    1024             :     IndirectDouble(d);
    1025             :   }
    1026             : 
    1027             :   size_t Key(const char *str, size_t len) {
    1028             :     auto sloc = buf_.size();
    1029             :     WriteBytes(str, len + 1);
    1030             :     if (flags_ & BUILDER_FLAG_SHARE_KEYS) {
    1031             :       auto it = key_pool.find(sloc);
    1032             :       if (it != key_pool.end()) {
    1033             :         // Already in the buffer. Remove key we just serialized, and use
    1034             :         // existing offset instead.
    1035             :         buf_.resize(sloc);
    1036             :         sloc = *it;
    1037             :       } else {
    1038             :         key_pool.insert(sloc);
    1039             :       }
    1040             :     }
    1041             :     stack_.push_back(Value(static_cast<uint64_t>(sloc), FBT_KEY, BIT_WIDTH_8));
    1042             :     return sloc;
    1043             :   }
    1044             : 
    1045             :   size_t Key(const char *str) { return Key(str, strlen(str)); }
    1046             :   size_t Key(const std::string &str) { return Key(str.c_str(), str.size()); }
    1047             : 
    1048             :   size_t String(const char *str, size_t len) {
    1049             :     auto reset_to = buf_.size();
    1050             :     auto sloc = CreateBlob(str, len, 1, FBT_STRING);
    1051             :     if (flags_ & BUILDER_FLAG_SHARE_STRINGS) {
    1052             :       StringOffset so(sloc, len);
    1053             :       auto it = string_pool.find(so);
    1054             :       if (it != string_pool.end()) {
    1055             :         // Already in the buffer. Remove string we just serialized, and use
    1056             :         // existing offset instead.
    1057             :         buf_.resize(reset_to);
    1058             :         sloc = it->first;
    1059             :         stack_.back().u_ = sloc;
    1060             :       } else {
    1061             :         string_pool.insert(so);
    1062             :       }
    1063             :     }
    1064             :     return sloc;
    1065             :   }
    1066             :   size_t String(const char *str) { return String(str, strlen(str)); }
    1067             :   size_t String(const std::string &str) {
    1068             :     return String(str.c_str(), str.size());
    1069             :   }
    1070             :   void String(const flexbuffers::String &str) {
    1071             :     String(str.c_str(), str.length());
    1072             :   }
    1073             : 
    1074             :   void String(const char *key, const char *str) {
    1075             :     Key(key);
    1076             :     String(str);
    1077             :   }
    1078             :   void String(const char *key, const std::string &str) {
    1079             :     Key(key);
    1080             :     String(str);
    1081             :   }
    1082             :   void String(const char *key, const flexbuffers::String &str) {
    1083             :     Key(key);
    1084             :     String(str);
    1085             :   }
    1086             : 
    1087             :   size_t Blob(const void *data, size_t len) {
    1088             :     return CreateBlob(data, len, 0, FBT_BLOB);
    1089             :   }
    1090             :   size_t Blob(const std::vector<uint8_t> &v) {
    1091             :     return CreateBlob(v.data(), v.size(), 0, FBT_BLOB);
    1092             :   }
    1093             : 
    1094             :   void Blob(const char *key, const void *data, size_t len) {
    1095             :     Key(key);
    1096             :     Blob(data, len);
    1097             :   }
    1098             :   void Blob(const char *key, const std::vector<uint8_t> &v) {
    1099             :     Key(key);
    1100             :     Blob(v);
    1101             :   }
    1102             : 
    1103             :   // TODO(wvo): support all the FlexBuffer types (like flexbuffers::String),
    1104             :   // e.g. Vector etc. Also in overloaded versions.
    1105             :   // Also some FlatBuffers types?
    1106             : 
    1107             :   size_t StartVector() { return stack_.size(); }
    1108             :   size_t StartVector(const char *key) {
    1109             :     Key(key);
    1110             :     return stack_.size();
    1111             :   }
    1112             :   size_t StartMap() { return stack_.size(); }
    1113             :   size_t StartMap(const char *key) {
    1114             :     Key(key);
    1115             :     return stack_.size();
    1116             :   }
    1117             : 
    1118             :   // TODO(wvo): allow this to specify an alignment greater than the natural
    1119             :   // alignment.
    1120             :   size_t EndVector(size_t start, bool typed, bool fixed) {
    1121             :     auto vec = CreateVector(start, stack_.size() - start, 1, typed, fixed);
    1122             :     // Remove temp elements and return vector.
    1123             :     stack_.resize(start);
    1124             :     stack_.push_back(vec);
    1125             :     return static_cast<size_t>(vec.u_);
    1126             :   }
    1127             : 
    1128             :   size_t EndMap(size_t start) {
    1129             :     // We should have interleaved keys and values on the stack.
    1130             :     // Make sure it is an even number:
    1131             :     auto len = stack_.size() - start;
    1132             :     FLATBUFFERS_ASSERT(!(len & 1));
    1133             :     len /= 2;
    1134             :     // Make sure keys are all strings:
    1135             :     for (auto key = start; key < stack_.size(); key += 2) {
    1136             :       FLATBUFFERS_ASSERT(stack_[key].type_ == FBT_KEY);
    1137             :     }
    1138             :     // Now sort values, so later we can do a binary search lookup.
    1139             :     // We want to sort 2 array elements at a time.
    1140             :     struct TwoValue {
    1141             :       Value key;
    1142             :       Value val;
    1143             :     };
    1144             :     // TODO(wvo): strict aliasing?
    1145             :     // TODO(wvo): allow the caller to indicate the data is already sorted
    1146             :     // for maximum efficiency? With an assert to check sortedness to make sure
    1147             :     // we're not breaking binary search.
    1148             :     // Or, we can track if the map is sorted as keys are added which would be
    1149             :     // be quite cheap (cheaper than checking it here), so we can skip this
    1150             :     // step automatically when appliccable, and encourage people to write in
    1151             :     // sorted fashion.
    1152             :     // std::sort is typically already a lot faster on sorted data though.
    1153             :     auto dict = reinterpret_cast<TwoValue *>(stack_.data() + start);
    1154             :     std::sort(
    1155             :         dict, dict + len, [&](const TwoValue &a, const TwoValue &b) -> bool {
    1156             :           auto as = reinterpret_cast<const char *>(buf_.data() + a.key.u_);
    1157             :           auto bs = reinterpret_cast<const char *>(buf_.data() + b.key.u_);
    1158             :           auto comp = strcmp(as, bs);
    1159             :           // We want to disallow duplicate keys, since this results in a
    1160             :           // map where values cannot be found.
    1161             :           // But we can't assert here (since we don't want to fail on
    1162             :           // random JSON input) or have an error mechanism.
    1163             :           // Instead, we set has_duplicate_keys_ in the builder to
    1164             :           // signal this.
    1165             :           // TODO: Have to check for pointer equality, as some sort
    1166             :           // implementation apparently call this function with the same
    1167             :           // element?? Why?
    1168             :           if (!comp && &a != &b) has_duplicate_keys_ = true;
    1169             :           return comp < 0;
    1170             :         });
    1171             :     // First create a vector out of all keys.
    1172             :     // TODO(wvo): if kBuilderFlagShareKeyVectors is true, see if we can share
    1173             :     // the first vector.
    1174             :     auto keys = CreateVector(start, len, 2, true, false);
    1175             :     auto vec = CreateVector(start + 1, len, 2, false, false, &keys);
    1176             :     // Remove temp elements and return map.
    1177             :     stack_.resize(start);
    1178             :     stack_.push_back(vec);
    1179             :     return static_cast<size_t>(vec.u_);
    1180             :   }
    1181             : 
    1182             :   // Call this after EndMap to see if the map had any duplicate keys.
    1183             :   // Any map with such keys won't be able to retrieve all values.
    1184             :   bool HasDuplicateKeys() const { return has_duplicate_keys_; }
    1185             : 
    1186             :   template<typename F> size_t Vector(F f) {
    1187             :     auto start = StartVector();
    1188             :     f();
    1189             :     return EndVector(start, false, false);
    1190             :   }
    1191             :   template<typename F, typename T> size_t Vector(F f, T &state) {
    1192             :     auto start = StartVector();
    1193             :     f(state);
    1194             :     return EndVector(start, false, false);
    1195             :   }
    1196             :   template<typename F> size_t Vector(const char *key, F f) {
    1197             :     auto start = StartVector(key);
    1198             :     f();
    1199             :     return EndVector(start, false, false);
    1200             :   }
    1201             :   template<typename F, typename T>
    1202             :   size_t Vector(const char *key, F f, T &state) {
    1203             :     auto start = StartVector(key);
    1204             :     f(state);
    1205             :     return EndVector(start, false, false);
    1206             :   }
    1207             : 
    1208             :   template<typename T> void Vector(const T *elems, size_t len) {
    1209             :     if (flatbuffers::is_scalar<T>::value) {
    1210             :       // This path should be a lot quicker and use less space.
    1211             :       ScalarVector(elems, len, false);
    1212             :     } else {
    1213             :       auto start = StartVector();
    1214             :       for (size_t i = 0; i < len; i++) Add(elems[i]);
    1215             :       EndVector(start, false, false);
    1216             :     }
    1217             :   }
    1218             :   template<typename T>
    1219             :   void Vector(const char *key, const T *elems, size_t len) {
    1220             :     Key(key);
    1221             :     Vector(elems, len);
    1222             :   }
    1223             :   template<typename T> void Vector(const std::vector<T> &vec) {
    1224             :     Vector(vec.data(), vec.size());
    1225             :   }
    1226             : 
    1227             :   template<typename F> size_t TypedVector(F f) {
    1228             :     auto start = StartVector();
    1229             :     f();
    1230             :     return EndVector(start, true, false);
    1231             :   }
    1232             :   template<typename F, typename T> size_t TypedVector(F f, T &state) {
    1233             :     auto start = StartVector();
    1234             :     f(state);
    1235             :     return EndVector(start, true, false);
    1236             :   }
    1237             :   template<typename F> size_t TypedVector(const char *key, F f) {
    1238             :     auto start = StartVector(key);
    1239             :     f();
    1240             :     return EndVector(start, true, false);
    1241             :   }
    1242             :   template<typename F, typename T>
    1243             :   size_t TypedVector(const char *key, F f, T &state) {
    1244             :     auto start = StartVector(key);
    1245             :     f(state);
    1246             :     return EndVector(start, true, false);
    1247             :   }
    1248             : 
    1249             :   template<typename T> size_t FixedTypedVector(const T *elems, size_t len) {
    1250             :     // We only support a few fixed vector lengths. Anything bigger use a
    1251             :     // regular typed vector.
    1252             :     FLATBUFFERS_ASSERT(len >= 2 && len <= 4);
    1253             :     // And only scalar values.
    1254             :     static_assert(flatbuffers::is_scalar<T>::value, "Unrelated types");
    1255             :     return ScalarVector(elems, len, true);
    1256             :   }
    1257             : 
    1258             :   template<typename T>
    1259             :   size_t FixedTypedVector(const char *key, const T *elems, size_t len) {
    1260             :     Key(key);
    1261             :     return FixedTypedVector(elems, len);
    1262             :   }
    1263             : 
    1264             :   template<typename F> size_t Map(F f) {
    1265             :     auto start = StartMap();
    1266             :     f();
    1267             :     return EndMap(start);
    1268             :   }
    1269             :   template<typename F, typename T> size_t Map(F f, T &state) {
    1270             :     auto start = StartMap();
    1271             :     f(state);
    1272             :     return EndMap(start);
    1273             :   }
    1274             :   template<typename F> size_t Map(const char *key, F f) {
    1275             :     auto start = StartMap(key);
    1276             :     f();
    1277             :     return EndMap(start);
    1278             :   }
    1279             :   template<typename F, typename T> size_t Map(const char *key, F f, T &state) {
    1280             :     auto start = StartMap(key);
    1281             :     f(state);
    1282             :     return EndMap(start);
    1283             :   }
    1284             :   template<typename T> void Map(const std::map<std::string, T> &map) {
    1285             :     auto start = StartMap();
    1286             :     for (auto it = map.begin(); it != map.end(); ++it)
    1287             :       Add(it->first.c_str(), it->second);
    1288             :     EndMap(start);
    1289             :   }
    1290             : 
    1291             :   // If you wish to share a value explicitly (a value not shared automatically
    1292             :   // through one of the BUILDER_FLAG_SHARE_* flags) you can do so with these
    1293             :   // functions. Or if you wish to turn those flags off for performance reasons
    1294             :   // and still do some explicit sharing. For example:
    1295             :   // builder.IndirectDouble(M_PI);
    1296             :   // auto id = builder.LastValue();  // Remember where we stored it.
    1297             :   // .. more code goes here ..
    1298             :   // builder.ReuseValue(id);  // Refers to same double by offset.
    1299             :   // LastValue works regardless of whether the value has a key or not.
    1300             :   // Works on any data type.
    1301             :   struct Value;
    1302             :   Value LastValue() { return stack_.back(); }
    1303             :   void ReuseValue(Value v) { stack_.push_back(v); }
    1304             :   void ReuseValue(const char *key, Value v) {
    1305             :     Key(key);
    1306             :     ReuseValue(v);
    1307             :   }
    1308             : 
    1309             :   // Overloaded Add that tries to call the correct function above.
    1310             :   void Add(int8_t i) { Int(i); }
    1311             :   void Add(int16_t i) { Int(i); }
    1312             :   void Add(int32_t i) { Int(i); }
    1313             :   void Add(int64_t i) { Int(i); }
    1314             :   void Add(uint8_t u) { UInt(u); }
    1315             :   void Add(uint16_t u) { UInt(u); }
    1316             :   void Add(uint32_t u) { UInt(u); }
    1317             :   void Add(uint64_t u) { UInt(u); }
    1318             :   void Add(float f) { Float(f); }
    1319             :   void Add(double d) { Double(d); }
    1320             :   void Add(bool b) { Bool(b); }
    1321             :   void Add(const char *str) { String(str); }
    1322             :   void Add(const std::string &str) { String(str); }
    1323             :   void Add(const flexbuffers::String &str) { String(str); }
    1324             : 
    1325             :   template<typename T> void Add(const std::vector<T> &vec) { Vector(vec); }
    1326             : 
    1327             :   template<typename T> void Add(const char *key, const T &t) {
    1328             :     Key(key);
    1329             :     Add(t);
    1330             :   }
    1331             : 
    1332             :   template<typename T> void Add(const std::map<std::string, T> &map) {
    1333             :     Map(map);
    1334             :   }
    1335             : 
    1336             :   template<typename T> void operator+=(const T &t) { Add(t); }
    1337             : 
    1338             :   // This function is useful in combination with the Mutate* functions above.
    1339             :   // It forces elements of vectors and maps to have a minimum size, such that
    1340             :   // they can later be updated without failing.
    1341             :   // Call with no arguments to reset.
    1342             :   void ForceMinimumBitWidth(BitWidth bw = BIT_WIDTH_8) {
    1343             :     force_min_bit_width_ = bw;
    1344             :   }
    1345             : 
    1346             :   void Finish() {
    1347             :     // If you hit this assert, you likely have objects that were never included
    1348             :     // in a parent. You need to have exactly one root to finish a buffer.
    1349             :     // Check your Start/End calls are matched, and all objects are inside
    1350             :     // some other object.
    1351             :     FLATBUFFERS_ASSERT(stack_.size() == 1);
    1352             : 
    1353             :     // Write root value.
    1354             :     auto byte_width = Align(stack_[0].ElemWidth(buf_.size(), 0));
    1355             :     WriteAny(stack_[0], byte_width);
    1356             :     // Write root type.
    1357             :     Write(stack_[0].StoredPackedType(), 1);
    1358             :     // Write root size. Normally determined by parent, but root has no parent :)
    1359             :     Write(byte_width, 1);
    1360             : 
    1361             :     finished_ = true;
    1362             :   }
    1363             : 
    1364             :  private:
    1365             :   void Finished() const {
    1366             :     // If you get this assert, you're attempting to get access a buffer
    1367             :     // which hasn't been finished yet. Be sure to call
    1368             :     // Builder::Finish with your root object.
    1369             :     FLATBUFFERS_ASSERT(finished_);
    1370             :   }
    1371             : 
    1372             :   // Align to prepare for writing a scalar with a certain size.
    1373             :   uint8_t Align(BitWidth alignment) {
    1374             :     auto byte_width = 1U << alignment;
    1375             :     buf_.insert(buf_.end(), flatbuffers::PaddingBytes(buf_.size(), byte_width),
    1376             :                 0);
    1377             :     return static_cast<uint8_t>(byte_width);
    1378             :   }
    1379             : 
    1380             :   void WriteBytes(const void *val, size_t size) {
    1381             :     buf_.insert(buf_.end(), reinterpret_cast<const uint8_t *>(val),
    1382             :                 reinterpret_cast<const uint8_t *>(val) + size);
    1383             :   }
    1384             : 
    1385             :   template<typename T> void Write(T val, size_t byte_width) {
    1386             :     FLATBUFFERS_ASSERT(sizeof(T) >= byte_width);
    1387             :     val = flatbuffers::EndianScalar(val);
    1388             :     WriteBytes(&val, byte_width);
    1389             :   }
    1390             : 
    1391             :   void WriteDouble(double f, uint8_t byte_width) {
    1392             :     switch (byte_width) {
    1393             :       case 8: Write(f, byte_width); break;
    1394             :       case 4: Write(static_cast<float>(f), byte_width); break;
    1395             :       // case 2: Write(static_cast<half>(f), byte_width); break;
    1396             :       // case 1: Write(static_cast<quarter>(f), byte_width); break;
    1397             :       default: FLATBUFFERS_ASSERT(0);
    1398             :     }
    1399             :   }
    1400             : 
    1401             :   void WriteOffset(uint64_t o, uint8_t byte_width) {
    1402             :     auto reloff = buf_.size() - o;
    1403             :     FLATBUFFERS_ASSERT(byte_width == 8 || reloff < 1ULL << (byte_width * 8));
    1404             :     Write(reloff, byte_width);
    1405             :   }
    1406             : 
    1407             :   template<typename T> void PushIndirect(T val, Type type, BitWidth bit_width) {
    1408             :     auto byte_width = Align(bit_width);
    1409             :     auto iloc = buf_.size();
    1410             :     Write(val, byte_width);
    1411             :     stack_.push_back(Value(static_cast<uint64_t>(iloc), type, bit_width));
    1412             :   }
    1413             : 
    1414           0 :   static BitWidth WidthB(size_t byte_width) {
    1415           0 :     switch (byte_width) {
    1416           0 :       case 1: return BIT_WIDTH_8;
    1417           0 :       case 2: return BIT_WIDTH_16;
    1418           0 :       case 4: return BIT_WIDTH_32;
    1419           0 :       case 8: return BIT_WIDTH_64;
    1420           0 :       default: FLATBUFFERS_ASSERT(false); return BIT_WIDTH_64;
    1421             :     }
    1422             :   }
    1423             : 
    1424             :   template<typename T> static Type GetScalarType() {
    1425             :     static_assert(flatbuffers::is_scalar<T>::value, "Unrelated types");
    1426             :     return flatbuffers::is_floating_point<T>::value
    1427             :                ? FBT_FLOAT
    1428             :                : flatbuffers::is_same<T, bool>::value
    1429             :                      ? FBT_BOOL
    1430             :                      : (flatbuffers::is_unsigned<T>::value ? FBT_UINT
    1431             :                                                            : FBT_INT);
    1432             :   }
    1433             : 
    1434             :  public:
    1435             :   // This was really intended to be private, except for LastValue/ReuseValue.
    1436             :   struct Value {
    1437             :     union {
    1438             :       int64_t i_;
    1439             :       uint64_t u_;
    1440             :       double f_;
    1441             :     };
    1442             : 
    1443             :     Type type_;
    1444             : 
    1445             :     // For scalars: of itself, for vector: of its elements, for string: length.
    1446             :     BitWidth min_bit_width_;
    1447             : 
    1448             :     Value() : i_(0), type_(FBT_NULL), min_bit_width_(BIT_WIDTH_8) {}
    1449             : 
    1450             :     Value(bool b)
    1451             :         : u_(static_cast<uint64_t>(b)),
    1452             :           type_(FBT_BOOL),
    1453             :           min_bit_width_(BIT_WIDTH_8) {}
    1454             : 
    1455             :     Value(int64_t i, Type t, BitWidth bw)
    1456             :         : i_(i), type_(t), min_bit_width_(bw) {}
    1457             :     Value(uint64_t u, Type t, BitWidth bw)
    1458             :         : u_(u), type_(t), min_bit_width_(bw) {}
    1459             : 
    1460             :     Value(float f)
    1461             :         : f_(static_cast<double>(f)),
    1462             :           type_(FBT_FLOAT),
    1463             :           min_bit_width_(BIT_WIDTH_32) {}
    1464             :     Value(double f) : f_(f), type_(FBT_FLOAT), min_bit_width_(WidthF(f)) {}
    1465             : 
    1466             :     uint8_t StoredPackedType(BitWidth parent_bit_width_ = BIT_WIDTH_8) const {
    1467             :       return PackedType(StoredWidth(parent_bit_width_), type_);
    1468             :     }
    1469             : 
    1470             :     BitWidth ElemWidth(size_t buf_size, size_t elem_index) const {
    1471             :       if (IsInline(type_)) {
    1472             :         return min_bit_width_;
    1473             :       } else {
    1474             :         // We have an absolute offset, but want to store a relative offset
    1475             :         // elem_index elements beyond the current buffer end. Since whether
    1476             :         // the relative offset fits in a certain byte_width depends on
    1477             :         // the size of the elements before it (and their alignment), we have
    1478             :         // to test for each size in turn.
    1479             :         for (size_t byte_width = 1;
    1480             :              byte_width <= sizeof(flatbuffers::largest_scalar_t);
    1481             :              byte_width *= 2) {
    1482             :           // Where are we going to write this offset?
    1483             :           auto offset_loc = buf_size +
    1484             :                             flatbuffers::PaddingBytes(buf_size, byte_width) +
    1485             :                             elem_index * byte_width;
    1486             :           // Compute relative offset.
    1487             :           auto offset = offset_loc - u_;
    1488             :           // Does it fit?
    1489             :           auto bit_width = WidthU(offset);
    1490             :           if (static_cast<size_t>(static_cast<size_t>(1U) << bit_width) ==
    1491             :               byte_width)
    1492             :             return bit_width;
    1493             :         }
    1494             :         FLATBUFFERS_ASSERT(false);  // Must match one of the sizes above.
    1495             :         return BIT_WIDTH_64;
    1496             :       }
    1497             :     }
    1498             : 
    1499             :     BitWidth StoredWidth(BitWidth parent_bit_width_ = BIT_WIDTH_8) const {
    1500             :       if (IsInline(type_)) {
    1501             :         return (std::max)(min_bit_width_, parent_bit_width_);
    1502             :       } else {
    1503             :         return min_bit_width_;
    1504             :       }
    1505             :     }
    1506             :   };
    1507             : 
    1508             :  private:
    1509             :   void WriteAny(const Value &val, uint8_t byte_width) {
    1510             :     switch (val.type_) {
    1511             :       case FBT_NULL:
    1512             :       case FBT_INT: Write(val.i_, byte_width); break;
    1513             :       case FBT_BOOL:
    1514             :       case FBT_UINT: Write(val.u_, byte_width); break;
    1515             :       case FBT_FLOAT: WriteDouble(val.f_, byte_width); break;
    1516             :       default: WriteOffset(val.u_, byte_width); break;
    1517             :     }
    1518             :   }
    1519             : 
    1520             :   size_t CreateBlob(const void *data, size_t len, size_t trailing, Type type) {
    1521             :     auto bit_width = WidthU(len);
    1522             :     auto byte_width = Align(bit_width);
    1523             :     Write<uint64_t>(len, byte_width);
    1524             :     auto sloc = buf_.size();
    1525             :     WriteBytes(data, len + trailing);
    1526             :     stack_.push_back(Value(static_cast<uint64_t>(sloc), type, bit_width));
    1527             :     return sloc;
    1528             :   }
    1529             : 
    1530             :   template<typename T>
    1531             :   size_t ScalarVector(const T *elems, size_t len, bool fixed) {
    1532             :     auto vector_type = GetScalarType<T>();
    1533             :     auto byte_width = sizeof(T);
    1534             :     auto bit_width = WidthB(byte_width);
    1535             :     // If you get this assert, you're trying to write a vector with a size
    1536             :     // field that is bigger than the scalars you're trying to write (e.g. a
    1537             :     // byte vector > 255 elements). For such types, write a "blob" instead.
    1538             :     // TODO: instead of asserting, could write vector with larger elements
    1539             :     // instead, though that would be wasteful.
    1540             :     FLATBUFFERS_ASSERT(WidthU(len) <= bit_width);
    1541             :     Align(bit_width);
    1542             :     if (!fixed) Write<uint64_t>(len, byte_width);
    1543             :     auto vloc = buf_.size();
    1544             :     for (size_t i = 0; i < len; i++) Write(elems[i], byte_width);
    1545             :     stack_.push_back(Value(static_cast<uint64_t>(vloc),
    1546             :                            ToTypedVector(vector_type, fixed ? len : 0),
    1547             :                            bit_width));
    1548             :     return vloc;
    1549             :   }
    1550             : 
    1551             :   Value CreateVector(size_t start, size_t vec_len, size_t step, bool typed,
    1552             :                      bool fixed, const Value *keys = nullptr) {
    1553             :     FLATBUFFERS_ASSERT(
    1554             :         !fixed ||
    1555             :         typed);  // typed=false, fixed=true combination is not supported.
    1556             :     // Figure out smallest bit width we can store this vector with.
    1557             :     auto bit_width = (std::max)(force_min_bit_width_, WidthU(vec_len));
    1558             :     auto prefix_elems = 1;
    1559             :     if (keys) {
    1560             :       // If this vector is part of a map, we will pre-fix an offset to the keys
    1561             :       // to this vector.
    1562             :       bit_width = (std::max)(bit_width, keys->ElemWidth(buf_.size(), 0));
    1563             :       prefix_elems += 2;
    1564             :     }
    1565             :     Type vector_type = FBT_KEY;
    1566             :     // Check bit widths and types for all elements.
    1567             :     for (size_t i = start; i < stack_.size(); i += step) {
    1568             :       auto elem_width =
    1569             :           stack_[i].ElemWidth(buf_.size(), i - start + prefix_elems);
    1570             :       bit_width = (std::max)(bit_width, elem_width);
    1571             :       if (typed) {
    1572             :         if (i == start) {
    1573             :           vector_type = stack_[i].type_;
    1574             :         } else {
    1575             :           // If you get this assert, you are writing a typed vector with
    1576             :           // elements that are not all the same type.
    1577             :           FLATBUFFERS_ASSERT(vector_type == stack_[i].type_);
    1578             :         }
    1579             :       }
    1580             :     }
    1581             :     // If you get this assert, your typed types are not one of:
    1582             :     // Int / UInt / Float / Key.
    1583             :     FLATBUFFERS_ASSERT(!typed || IsTypedVectorElementType(vector_type));
    1584             :     auto byte_width = Align(bit_width);
    1585             :     // Write vector. First the keys width/offset if available, and size.
    1586             :     if (keys) {
    1587             :       WriteOffset(keys->u_, byte_width);
    1588             :       Write<uint64_t>(1ULL << keys->min_bit_width_, byte_width);
    1589             :     }
    1590             :     if (!fixed) Write<uint64_t>(vec_len, byte_width);
    1591             :     // Then the actual data.
    1592             :     auto vloc = buf_.size();
    1593             :     for (size_t i = start; i < stack_.size(); i += step) {
    1594             :       WriteAny(stack_[i], byte_width);
    1595             :     }
    1596             :     // Then the types.
    1597             :     if (!typed) {
    1598             :       for (size_t i = start; i < stack_.size(); i += step) {
    1599             :         buf_.push_back(stack_[i].StoredPackedType(bit_width));
    1600             :       }
    1601             :     }
    1602             :     return Value(static_cast<uint64_t>(vloc),
    1603             :                  keys ? FBT_MAP
    1604             :                       : (typed ? ToTypedVector(vector_type, fixed ? vec_len : 0)
    1605             :                                : FBT_VECTOR),
    1606             :                  bit_width);
    1607             :   }
    1608             : 
    1609             :   // You shouldn't really be copying instances of this class.
    1610             :   Builder(const Builder &);
    1611             :   Builder &operator=(const Builder &);
    1612             : 
    1613             :   std::vector<uint8_t> buf_;
    1614             :   std::vector<Value> stack_;
    1615             : 
    1616             :   bool finished_;
    1617             :   bool has_duplicate_keys_;
    1618             : 
    1619             :   BuilderFlag flags_;
    1620             : 
    1621             :   BitWidth force_min_bit_width_;
    1622             : 
    1623             :   struct KeyOffsetCompare {
    1624             :     explicit KeyOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {}
    1625             :     bool operator()(size_t a, size_t b) const {
    1626             :       auto stra = reinterpret_cast<const char *>(buf_->data() + a);
    1627             :       auto strb = reinterpret_cast<const char *>(buf_->data() + b);
    1628             :       return strcmp(stra, strb) < 0;
    1629             :     }
    1630             :     const std::vector<uint8_t> *buf_;
    1631             :   };
    1632             : 
    1633             :   typedef std::pair<size_t, size_t> StringOffset;
    1634             :   struct StringOffsetCompare {
    1635             :     explicit StringOffsetCompare(const std::vector<uint8_t> &buf)
    1636             :         : buf_(&buf) {}
    1637             :     bool operator()(const StringOffset &a, const StringOffset &b) const {
    1638             :       auto stra = buf_->data() + a.first;
    1639             :       auto strb = buf_->data() + b.first;
    1640             :       auto cr = memcmp(stra, strb, (std::min)(a.second, b.second) + 1);
    1641             :       return cr < 0 || (cr == 0 && a.second < b.second);
    1642             :     }
    1643             :     const std::vector<uint8_t> *buf_;
    1644             :   };
    1645             : 
    1646             :   typedef std::set<size_t, KeyOffsetCompare> KeyOffsetMap;
    1647             :   typedef std::set<StringOffset, StringOffsetCompare> StringOffsetMap;
    1648             : 
    1649             :   KeyOffsetMap key_pool;
    1650             :   StringOffsetMap string_pool;
    1651             : 
    1652             :   friend class Verifier;
    1653             : };
    1654             : 
    1655             : // Helper class to verify the integrity of a FlexBuffer
    1656             : class Verifier FLATBUFFERS_FINAL_CLASS {
    1657             :  public:
    1658        6073 :   Verifier(const uint8_t *buf, size_t buf_len,
    1659             :            // Supplying this vector likely results in faster verification
    1660             :            // of larger buffers with many shared keys/strings, but
    1661             :            // comes at the cost of using additional memory the same size of
    1662             :            // the buffer being verified, so it is by default off.
    1663             :            std::vector<uint8_t> *reuse_tracker = nullptr,
    1664             :            bool _check_alignment = true, size_t max_depth = 64)
    1665        6073 :       : buf_(buf),
    1666             :         size_(buf_len),
    1667             :         depth_(0),
    1668             :         max_depth_(max_depth),
    1669             :         num_vectors_(0),
    1670             :         max_vectors_(buf_len),
    1671             :         check_alignment_(_check_alignment),
    1672        6073 :         reuse_tracker_(reuse_tracker) {
    1673        6073 :     FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
    1674        6073 :     if (reuse_tracker_) {
    1675           0 :       reuse_tracker_->clear();
    1676           0 :       reuse_tracker_->resize(size_, PackedType(BIT_WIDTH_8, FBT_NULL));
    1677             :     }
    1678        6073 :   }
    1679             : 
    1680             :  private:
    1681             :   // Central location where any verification failures register.
    1682      869238 :   bool Check(bool ok) const {
    1683             :     // clang-format off
    1684             :     #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
    1685             :       FLATBUFFERS_ASSERT(ok);
    1686             :     #endif
    1687             :     // clang-format on
    1688      869238 :     return ok;
    1689             :   }
    1690             : 
    1691             :   // Verify any range within the buffer.
    1692       70938 :   bool VerifyFrom(size_t elem, size_t elem_len) const {
    1693       70938 :     return Check(elem_len < size_ && elem <= size_ - elem_len);
    1694             :   }
    1695       66714 :   bool VerifyBefore(size_t elem, size_t elem_len) const {
    1696       66714 :     return Check(elem_len <= elem);
    1697             :   }
    1698             : 
    1699       70938 :   bool VerifyFromPointer(const uint8_t *p, size_t len) {
    1700       70938 :     auto o = static_cast<size_t>(p - buf_);
    1701       70938 :     return VerifyFrom(o, len);
    1702             :   }
    1703       66714 :   bool VerifyBeforePointer(const uint8_t *p, size_t len) {
    1704       66714 :     auto o = static_cast<size_t>(p - buf_);
    1705       66714 :     return VerifyBefore(o, len);
    1706             :   }
    1707             : 
    1708      205543 :   bool VerifyByteWidth(size_t width) {
    1709      205543 :     return Check(width == 1 || width == 2 || width == 4 || width == 8);
    1710             :   }
    1711             : 
    1712      178640 :   bool VerifyType(int type) { return Check(type >= 0 && type < FBT_MAX_TYPE); }
    1713             : 
    1714      132160 :   bool VerifyOffset(uint64_t off, const uint8_t *p) {
    1715      264320 :     return Check(off <= static_cast<uint64_t>(size_)) &&
    1716      264320 :            off <= static_cast<uint64_t>(p - buf_);
    1717             :   }
    1718             : 
    1719      111330 :   bool VerifyAlignment(const uint8_t *p, size_t size) const {
    1720      111330 :     auto o = static_cast<size_t>(p - buf_);
    1721      111330 :     return Check((o & (size - 1)) == 0 || !check_alignment_);
    1722             :   }
    1723             : 
    1724             : // Macro, since we want to escape from parent function & use lazy args.
    1725             : #define FLEX_CHECK_VERIFIED(P, PACKED_TYPE)                     \
    1726             :   if (reuse_tracker_) {                                         \
    1727             :     auto packed_type = PACKED_TYPE;                             \
    1728             :     auto existing = (*reuse_tracker_)[P - buf_];                \
    1729             :     if (existing == packed_type) return true;                   \
    1730             :     /* Fail verification if already set with different type! */ \
    1731             :     if (!Check(existing == 0)) return false;                    \
    1732             :     (*reuse_tracker_)[P - buf_] = packed_type;                  \
    1733             :   }
    1734             : 
    1735       45884 :   bool VerifyVector(Reference r, const uint8_t *p, Type elem_type) {
    1736             :     // Any kind of nesting goes thru this function, so guard against that
    1737             :     // here, both with simple nesting checks, and the reuse tracker if on.
    1738       45884 :     depth_++;
    1739       45884 :     num_vectors_++;
    1740       45884 :     if (!Check(depth_ <= max_depth_ && num_vectors_ <= max_vectors_))
    1741           0 :       return false;
    1742       45884 :     auto size_byte_width = r.byte_width_;
    1743       45884 :     if (!VerifyBeforePointer(p, size_byte_width)) return false;
    1744       45884 :     FLEX_CHECK_VERIFIED(p - size_byte_width,
    1745             :                         PackedType(Builder::WidthB(size_byte_width), r.type_));
    1746       45884 :     auto sized = Sized(p, size_byte_width);
    1747       45884 :     auto num_elems = sized.size();
    1748       41672 :     auto elem_byte_width = r.type_ == FBT_STRING || r.type_ == FBT_BLOB
    1749       87556 :                                ? uint8_t(1)
    1750             :                                : r.byte_width_;
    1751       45884 :     auto max_elems = SIZE_MAX / elem_byte_width;
    1752       45884 :     if (!Check(num_elems < max_elems))
    1753           0 :       return false;  // Protect against byte_size overflowing.
    1754       45884 :     auto byte_size = num_elems * elem_byte_width;
    1755       45884 :     if (!VerifyFromPointer(p, byte_size)) return false;
    1756       45884 :     if (elem_type == FBT_NULL) {
    1757             :       // Verify type bytes after the vector.
    1758       20842 :       if (!VerifyFromPointer(p + byte_size, num_elems)) return false;
    1759       20842 :       auto v = Vector(p, size_byte_width);
    1760      107134 :       for (size_t i = 0; i < num_elems; i++)
    1761       86292 :         if (!VerifyRef(v[i])) return false;
    1762       25042 :     } else if (elem_type == FBT_KEY) {
    1763       20830 :       auto v = TypedVector(p, elem_byte_width, FBT_KEY);
    1764      107106 :       for (size_t i = 0; i < num_elems; i++)
    1765       86276 :         if (!VerifyRef(v[i])) return false;
    1766             :     } else {
    1767        4212 :       FLATBUFFERS_ASSERT(IsInline(elem_type));
    1768             :     }
    1769       45884 :     depth_--;
    1770       45884 :     return true;
    1771             :   }
    1772             : 
    1773       20830 :   bool VerifyKeys(const uint8_t *p, uint8_t byte_width) {
    1774             :     // The vector part of the map has already been verified.
    1775       20830 :     const size_t num_prefixed_fields = 3;
    1776       20830 :     if (!VerifyBeforePointer(p, byte_width * num_prefixed_fields)) return false;
    1777       20830 :     p -= byte_width * num_prefixed_fields;
    1778       20830 :     auto off = ReadUInt64(p, byte_width);
    1779       20830 :     if (!VerifyOffset(off, p)) return false;
    1780             :     auto key_byte_with =
    1781       20830 :         static_cast<uint8_t>(ReadUInt64(p + byte_width, byte_width));
    1782       20830 :     if (!VerifyByteWidth(key_byte_with)) return false;
    1783       41660 :     return VerifyVector(Reference(p, byte_width, key_byte_with, FBT_VECTOR_KEY),
    1784       41660 :                         p - off, FBT_KEY);
    1785             :   }
    1786             : 
    1787       86276 :   bool VerifyKey(const uint8_t *p) {
    1788       86276 :     FLEX_CHECK_VERIFIED(p, PackedType(BIT_WIDTH_8, FBT_KEY));
    1789       86276 :     while (p < buf_ + size_)
    1790       86276 :       if (*p++) return true;
    1791           0 :     return false;
    1792             :   }
    1793             : 
    1794             : #undef FLEX_CHECK_VERIFIED
    1795             : 
    1796        4212 :   bool VerifyTerminator(const String &s) {
    1797        4212 :     return VerifyFromPointer(reinterpret_cast<const uint8_t *>(s.c_str()),
    1798        8424 :                              s.size() + 1);
    1799             :   }
    1800             : 
    1801      178640 :   bool VerifyRef(Reference r) {
    1802             :     // r.parent_width_ and r.data_ already verified.
    1803      178640 :     if (!VerifyByteWidth(r.byte_width_) || !VerifyType(r.type_)) {
    1804           0 :       return false;
    1805             :     }
    1806      178640 :     if (IsInline(r.type_)) {
    1807             :       // Inline scalars, don't require further verification.
    1808       67310 :       return true;
    1809             :     }
    1810             :     // All remaining types are an offset.
    1811      111330 :     auto off = ReadUInt64(r.data_, r.parent_width_);
    1812      111330 :     if (!VerifyOffset(off, r.data_)) return false;
    1813      111330 :     auto p = r.Indirect();
    1814      111330 :     if (!VerifyAlignment(p, r.byte_width_)) return false;
    1815      111330 :     switch (r.type_) {
    1816           0 :       case FBT_INDIRECT_INT:
    1817             :       case FBT_INDIRECT_UINT:
    1818           0 :       case FBT_INDIRECT_FLOAT: return VerifyFromPointer(p, r.byte_width_);
    1819       86276 :       case FBT_KEY: return VerifyKey(p);
    1820       20830 :       case FBT_MAP:
    1821       20830 :         return VerifyVector(r, p, FBT_NULL) && VerifyKeys(p, r.byte_width_);
    1822          12 :       case FBT_VECTOR: return VerifyVector(r, p, FBT_NULL);
    1823           0 :       case FBT_VECTOR_INT: return VerifyVector(r, p, FBT_INT);
    1824           0 :       case FBT_VECTOR_BOOL:
    1825           0 :       case FBT_VECTOR_UINT: return VerifyVector(r, p, FBT_UINT);
    1826           0 :       case FBT_VECTOR_FLOAT: return VerifyVector(r, p, FBT_FLOAT);
    1827           0 :       case FBT_VECTOR_KEY: return VerifyVector(r, p, FBT_KEY);
    1828           0 :       case FBT_VECTOR_STRING_DEPRECATED:
    1829             :         // Use of FBT_KEY here intentional, see elsewhere.
    1830           0 :         return VerifyVector(r, p, FBT_KEY);
    1831           0 :       case FBT_BLOB: return VerifyVector(r, p, FBT_UINT);
    1832        4212 :       case FBT_STRING:
    1833        8424 :         return VerifyVector(r, p, FBT_UINT) &&
    1834        8424 :                VerifyTerminator(String(p, r.byte_width_));
    1835           0 :       case FBT_VECTOR_INT2:
    1836             :       case FBT_VECTOR_UINT2:
    1837             :       case FBT_VECTOR_FLOAT2:
    1838             :       case FBT_VECTOR_INT3:
    1839             :       case FBT_VECTOR_UINT3:
    1840             :       case FBT_VECTOR_FLOAT3:
    1841             :       case FBT_VECTOR_INT4:
    1842             :       case FBT_VECTOR_UINT4:
    1843             :       case FBT_VECTOR_FLOAT4: {
    1844           0 :         uint8_t len = 0;
    1845           0 :         auto vtype = ToFixedTypedVectorElementType(r.type_, &len);
    1846           0 :         if (!VerifyType(vtype)) return false;
    1847           0 :         return VerifyFromPointer(p, r.byte_width_ * len);
    1848             :       }
    1849           0 :       default: return false;
    1850             :     }
    1851             :   }
    1852             : 
    1853             :  public:
    1854        6073 :   bool VerifyBuffer() {
    1855        6073 :     if (!Check(size_ >= 3)) return false;
    1856        6073 :     auto end = buf_ + size_;
    1857        6073 :     auto byte_width = *--end;
    1858        6073 :     auto packed_type = *--end;
    1859       12145 :     return VerifyByteWidth(byte_width) && Check(end - buf_ >= byte_width) &&
    1860       12145 :            VerifyRef(Reference(end - byte_width, byte_width, packed_type));
    1861             :   }
    1862             : 
    1863             :  private:
    1864             :   const uint8_t *buf_;
    1865             :   size_t size_;
    1866             :   size_t depth_;
    1867             :   const size_t max_depth_;
    1868             :   size_t num_vectors_;
    1869             :   const size_t max_vectors_;
    1870             :   bool check_alignment_;
    1871             :   std::vector<uint8_t> *reuse_tracker_;
    1872             : };
    1873             : 
    1874             : // Utility function that constructs the Verifier for you, see above for
    1875             : // parameters.
    1876        6073 : inline bool VerifyBuffer(const uint8_t *buf, size_t buf_len,
    1877             :                          std::vector<uint8_t> *reuse_tracker = nullptr) {
    1878        6073 :   Verifier verifier(buf, buf_len, reuse_tracker);
    1879       12146 :   return verifier.VerifyBuffer();
    1880             : }
    1881             : 
    1882             : }  // namespace flexbuffers
    1883             : 
    1884             : #if defined(_MSC_VER)
    1885             : #  pragma warning(pop)
    1886             : #endif
    1887             : 
    1888             : #endif  // FLATBUFFERS_FLEXBUFFERS_H_

Generated by: LCOV version 1.14