github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/executor/_include/flatbuffers/flexbuffers.h (about)

     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  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  inline bool IsTypedVector(Type t) {
    95    return (t >= FBT_VECTOR_INT && t <= FBT_VECTOR_STRING_DEPRECATED) ||
    96           t == FBT_VECTOR_BOOL;
    97  }
    98  
    99  inline bool IsFixedTypedVector(Type t) {
   100    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  inline Type ToTypedVectorElementType(Type t) {
   115    FLATBUFFERS_ASSERT(IsTypedVector(t));
   116    return static_cast<Type>(t - FBT_VECTOR_INT + FBT_INT);
   117  }
   118  
   119  inline Type ToFixedTypedVectorElementType(Type t, uint8_t *len) {
   120    FLATBUFFERS_ASSERT(IsFixedTypedVector(t));
   121    auto fixed_type = t - FBT_VECTOR_INT2;
   122    *len = static_cast<uint8_t>(fixed_type / 3 +
   123                                2);  // 3 types each, starting from length 2.
   124    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  R ReadSizedScalar(const uint8_t *data, uint8_t byte_width) {
   139    return byte_width < 4
   140               ? (byte_width < 2
   141                      ? static_cast<R>(flatbuffers::ReadScalar<T1>(data))
   142                      : static_cast<R>(flatbuffers::ReadScalar<T2>(data)))
   143               : (byte_width < 8
   144                      ? static_cast<R>(flatbuffers::ReadScalar<T4>(data))
   145                      : static_cast<R>(flatbuffers::ReadScalar<T8>(data)));
   146  }
   147  
   148  inline int64_t ReadInt64(const uint8_t *data, uint8_t byte_width) {
   149    return ReadSizedScalar<int64_t, int8_t, int16_t, int32_t, int64_t>(
   150        data, byte_width);
   151  }
   152  
   153  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      return ReadSizedScalar<uint64_t, uint8_t, uint16_t, uint32_t, uint64_t>(
   169               data, byte_width);
   170    #endif
   171    // clang-format on
   172  }
   173  
   174  inline double ReadDouble(const uint8_t *data, uint8_t byte_width) {
   175    return ReadSizedScalar<double, quarter, half, float, double>(data,
   176                                                                 byte_width);
   177  }
   178  
   179  inline const uint8_t *Indirect(const uint8_t *offset, uint8_t byte_width) {
   180    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    Object(const uint8_t *data, uint8_t byte_width)
   214        : 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    Sized(const uint8_t *data, uint8_t byte_width)
   226        : Object(data, byte_width), size_(read_size()) {}
   227    // Manual size.
   228    Sized(const uint8_t *data, uint8_t byte_width, size_t sz)
   229        : Object(data, byte_width), size_(sz) {}
   230    size_t size() const { return size_; }
   231    // Access size stored in `byte_width_` bytes before data_ pointer.
   232    size_t read_size() const {
   233      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    String(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {}
   244    // Manual size.
   245    String(const uint8_t *data, uint8_t byte_width, size_t sz)
   246        : Sized(data, byte_width, sz) {}
   247  
   248    size_t length() const { return size(); }
   249    const char *c_str() const { return reinterpret_cast<const char *>(data_); }
   250    std::string str() const { return std::string(c_str(), size()); }
   251  
   252    static String EmptyString() {
   253      static const char *empty_string = "";
   254      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    Blob(const uint8_t *data_buf, uint8_t byte_width)
   262        : Sized(data_buf, byte_width) {}
   263  
   264    static Blob EmptyBlob() {
   265      static const uint8_t empty_blob[] = { 0 /*len*/ };
   266      return Blob(empty_blob + 1, 1);
   267    }
   268    bool IsTheEmptyBlob() const { return data_ == EmptyBlob().data_; }
   269    const uint8_t *data() const { return data_; }
   270  };
   271  
   272  class Vector : public Sized {
   273   public:
   274    Vector(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {}
   275  
   276    Reference operator[](size_t i) const;
   277  
   278    static Vector EmptyVector() {
   279      static const uint8_t empty_vector[] = { 0 /*len*/ };
   280      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    TypedVector(const uint8_t *data, uint8_t byte_width, Type element_type)
   288        : Sized(data, byte_width), type_(element_type) {}
   289  
   290    Reference operator[](size_t i) const;
   291  
   292    static TypedVector EmptyTypedVector() {
   293      static const uint8_t empty_typed_vector[] = { 0 /*len*/ };
   294      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    FixedTypedVector(const uint8_t *data, uint8_t byte_width, Type element_type,
   313                     uint8_t len)
   314        : Object(data, byte_width), type_(element_type), len_(len) {}
   315  
   316    Reference operator[](size_t i) const;
   317  
   318    static FixedTypedVector EmptyFixedTypedVector() {
   319      static const uint8_t fixed_empty_vector[] = { 0 /* unused */ };
   320      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    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    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    Vector Values() const { return Vector(data_, byte_width_); }
   342  
   343    TypedVector Keys() const {
   344      const size_t num_prefixed_fields = 3;
   345      auto keys_offset = data_ - byte_width_ * num_prefixed_fields;
   346      return TypedVector(Indirect(keys_offset, byte_width_),
   347                         static_cast<uint8_t>(
   348                             ReadUInt64(keys_offset + byte_width_, byte_width_)),
   349                         FBT_KEY);
   350    }
   351  
   352    static Map EmptyMap() {
   353      static const uint8_t empty_map[] = {
   354        0 /*keys_len*/, 0 /*keys_offset*/, 1 /*keys_width*/, 0 /*len*/
   355      };
   356      return Map(empty_map + 4, 1);
   357    }
   358  
   359    bool IsTheEmptyMap() const { return data_ == EmptyMap().data_; }
   360  };
   361  
   362  template<typename T>
   363  void AppendToString(std::string &s, T &&v, bool keys_quoted) {
   364    s += "[ ";
   365    for (size_t i = 0; i < v.size(); i++) {
   366      if (i) s += ", ";
   367      v[i].ToString(true, keys_quoted, s);
   368    }
   369    s += " ]";
   370  }
   371  
   372  class Reference {
   373   public:
   374    Reference()
   375        : data_(nullptr), parent_width_(0), byte_width_(0), type_(FBT_NULL) {}
   376  
   377    Reference(const uint8_t *data, uint8_t parent_width, uint8_t byte_width,
   378              Type type)
   379        : data_(data),
   380          parent_width_(parent_width),
   381          byte_width_(byte_width),
   382          type_(type) {}
   383  
   384    Reference(const uint8_t *data, uint8_t parent_width, uint8_t packed_type)
   385        : data_(data), parent_width_(parent_width) {
   386      byte_width_ = 1U << static_cast<BitWidth>(packed_type & 3);
   387      type_ = static_cast<Type>(packed_type >> 2);
   388    }
   389  
   390    Type GetType() const { return type_; }
   391  
   392    bool IsNull() const { return type_ == FBT_NULL; }
   393    bool IsBool() const { return type_ == FBT_BOOL; }
   394    bool IsInt() const { return type_ == FBT_INT || type_ == FBT_INDIRECT_INT; }
   395    bool IsUInt() const {
   396      return type_ == FBT_UINT || type_ == FBT_INDIRECT_UINT;
   397    }
   398    bool IsIntOrUint() const { return IsInt() || IsUInt(); }
   399    bool IsFloat() const {
   400      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    bool IsKey() const { return type_ == FBT_KEY; }
   405    bool IsVector() const { return type_ == FBT_VECTOR || type_ == FBT_MAP; }
   406    bool IsUntypedVector() const { return type_ == FBT_VECTOR; }
   407    bool IsTypedVector() const { return flexbuffers::IsTypedVector(type_); }
   408    bool IsFixedTypedVector() const {
   409      return flexbuffers::IsFixedTypedVector(type_);
   410    }
   411    bool IsAnyVector() const {
   412      return (IsTypedVector() || IsFixedTypedVector() || IsVector());
   413    }
   414    bool IsMap() const { return type_ == FBT_MAP; }
   415    bool IsBlob() const { return type_ == FBT_BLOB; }
   416    bool AsBool() const {
   417      return (type_ == FBT_BOOL ? ReadUInt64(data_, parent_width_)
   418                                : 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    int64_t AsInt64() const {
   425      if (type_ == FBT_INT) {
   426        // A fast path for the common case.
   427        return ReadInt64(data_, parent_width_);
   428      } else
   429        switch (type_) {
   430          case FBT_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_);
   431          case FBT_UINT: return ReadUInt64(data_, parent_width_);
   432          case FBT_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_);
   433          case FBT_FLOAT:
   434            return static_cast<int64_t>(ReadDouble(data_, parent_width_));
   435          case FBT_INDIRECT_FLOAT:
   436            return static_cast<int64_t>(ReadDouble(Indirect(), byte_width_));
   437          case FBT_NULL: return 0;
   438          case FBT_STRING: return flatbuffers::StringToInt(AsString().c_str());
   439          case FBT_VECTOR: return static_cast<int64_t>(AsVector().size());
   440          case FBT_BOOL: return ReadInt64(data_, parent_width_);
   441          default:
   442            // Convert other things to int.
   443            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    uint64_t AsUInt64() const {
   454      if (type_ == FBT_UINT) {
   455        // A fast path for the common case.
   456        return ReadUInt64(data_, parent_width_);
   457      } else
   458        switch (type_) {
   459          case FBT_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_);
   460          case FBT_INT: return ReadInt64(data_, parent_width_);
   461          case FBT_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_);
   462          case FBT_FLOAT:
   463            return static_cast<uint64_t>(ReadDouble(data_, parent_width_));
   464          case FBT_INDIRECT_FLOAT:
   465            return static_cast<uint64_t>(ReadDouble(Indirect(), byte_width_));
   466          case FBT_NULL: return 0;
   467          case FBT_STRING: return flatbuffers::StringToUInt(AsString().c_str());
   468          case FBT_VECTOR: return static_cast<uint64_t>(AsVector().size());
   469          case FBT_BOOL: return ReadUInt64(data_, parent_width_);
   470          default:
   471            // Convert other things to uint.
   472            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    double AsDouble() const {
   481      if (type_ == FBT_FLOAT) {
   482        // A fast path for the common case.
   483        return ReadDouble(data_, parent_width_);
   484      } else
   485        switch (type_) {
   486          case FBT_INDIRECT_FLOAT: return ReadDouble(Indirect(), byte_width_);
   487          case FBT_INT:
   488            return static_cast<double>(ReadInt64(data_, parent_width_));
   489          case FBT_UINT:
   490            return static_cast<double>(ReadUInt64(data_, parent_width_));
   491          case FBT_INDIRECT_INT:
   492            return static_cast<double>(ReadInt64(Indirect(), byte_width_));
   493          case FBT_INDIRECT_UINT:
   494            return static_cast<double>(ReadUInt64(Indirect(), byte_width_));
   495          case FBT_NULL: return 0.0;
   496          case FBT_STRING: {
   497            double d;
   498            flatbuffers::StringToNumber(AsString().c_str(), &d);
   499            return d;
   500          }
   501          case FBT_VECTOR: return static_cast<double>(AsVector().size());
   502          case FBT_BOOL:
   503            return static_cast<double>(ReadUInt64(data_, parent_width_));
   504          default:
   505            // Convert strings and other things to float.
   506            return 0;
   507        }
   508    }
   509  
   510    float AsFloat() const { return static_cast<float>(AsDouble()); }
   511  
   512    const char *AsKey() const {
   513      if (type_ == FBT_KEY || type_ == FBT_STRING) {
   514        return reinterpret_cast<const char *>(Indirect());
   515      } else {
   516        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    String AsString() const {
   523      if (type_ == FBT_STRING) {
   524        return String(Indirect(), byte_width_);
   525      } else if (type_ == FBT_KEY) {
   526        auto key = Indirect();
   527        return String(key, byte_width_,
   528                      strlen(reinterpret_cast<const char *>(key)));
   529      } else {
   530        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    void ToString(bool strings_quoted, bool keys_quoted, std::string &s) const {
   546      if (type_ == FBT_STRING) {
   547        String str(Indirect(), byte_width_);
   548        if (strings_quoted) {
   549          flatbuffers::EscapeString(str.c_str(), str.length(), &s, true, false);
   550        } else {
   551          s.append(str.c_str(), str.length());
   552        }
   553      } else if (IsKey()) {
   554        auto str = AsKey();
   555        if (keys_quoted) {
   556          flatbuffers::EscapeString(str, strlen(str), &s, true, false);
   557        } else {
   558          s += str;
   559        }
   560      } else if (IsInt()) {
   561        s += flatbuffers::NumToString(AsInt64());
   562      } else if (IsUInt()) {
   563        s += flatbuffers::NumToString(AsUInt64());
   564      } else if (IsFloat()) {
   565        s += flatbuffers::NumToString(AsDouble());
   566      } else if (IsNull()) {
   567        s += "null";
   568      } else if (IsBool()) {
   569        s += AsBool() ? "true" : "false";
   570      } else if (IsMap()) {
   571        s += "{ ";
   572        auto m = AsMap();
   573        auto keys = m.Keys();
   574        auto vals = m.Values();
   575        for (size_t i = 0; i < keys.size(); i++) {
   576          bool kq = keys_quoted;
   577          if (!kq) {
   578            // FlexBuffers keys may contain arbitrary characters, only allow
   579            // unquoted if it looks like an "identifier":
   580            const char *p = keys[i].AsKey();
   581            if (!flatbuffers::is_alpha(*p) && *p != '_') {
   582              kq = true;
   583            } else {
   584              while (*++p) {
   585                if (!flatbuffers::is_alnum(*p) && *p != '_') {
   586                  kq = true;
   587                  break;
   588                }
   589              }
   590            }
   591          }
   592          keys[i].ToString(true, kq, s);
   593          s += ": ";
   594          vals[i].ToString(true, keys_quoted, s);
   595          if (i < keys.size() - 1) s += ", ";
   596        }
   597        s += " }";
   598      } else if (IsVector()) {
   599        AppendToString<Vector>(s, AsVector(), keys_quoted);
   600      } else if (IsTypedVector()) {
   601        AppendToString<TypedVector>(s, AsTypedVector(), keys_quoted);
   602      } else if (IsFixedTypedVector()) {
   603        AppendToString<FixedTypedVector>(s, AsFixedTypedVector(), keys_quoted);
   604      } else if (IsBlob()) {
   605        auto blob = AsBlob();
   606        flatbuffers::EscapeString(reinterpret_cast<const char *>(blob.data()),
   607                                  blob.size(), &s, true, false);
   608      } else {
   609        s += "(?)";
   610      }
   611    }
   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    Blob AsBlob() const {
   616      if (type_ == FBT_BLOB || type_ == FBT_STRING) {
   617        return Blob(Indirect(), byte_width_);
   618      } else {
   619        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    Vector AsVector() const {
   626      if (type_ == FBT_VECTOR || type_ == FBT_MAP) {
   627        return Vector(Indirect(), byte_width_);
   628      } else {
   629        return Vector::EmptyVector();
   630      }
   631    }
   632  
   633    TypedVector AsTypedVector() const {
   634      if (IsTypedVector()) {
   635        auto tv =
   636            TypedVector(Indirect(), byte_width_, ToTypedVectorElementType(type_));
   637        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          tv.type_ = FBT_KEY;
   645        }
   646        return tv;
   647      } else {
   648        return TypedVector::EmptyTypedVector();
   649      }
   650    }
   651  
   652    FixedTypedVector AsFixedTypedVector() const {
   653      if (IsFixedTypedVector()) {
   654        uint8_t len = 0;
   655        auto vtype = ToFixedTypedVectorElementType(type_, &len);
   656        return FixedTypedVector(Indirect(), byte_width_, vtype, len);
   657      } else {
   658        return FixedTypedVector::EmptyFixedTypedVector();
   659      }
   660    }
   661  
   662    Map AsMap() const {
   663      if (type_ == FBT_MAP) {
   664        return Map(Indirect(), byte_width_);
   665      } else {
   666        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    const uint8_t *Indirect() const {
   750      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  inline uint8_t PackedType(BitWidth bit_width, Type type) {
   822    return static_cast<uint8_t>(bit_width | (type << 2));
   823  }
   824  
   825  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  inline Reference Vector::operator[](size_t i) const {
   835    auto len = size();
   836    if (i >= len) return Reference(nullptr, 1, NullPackedType());
   837    auto packed_type = (data_ + len * byte_width_)[i];
   838    auto elem = data_ + i * byte_width_;
   839    return Reference(elem, byte_width_, packed_type);
   840  }
   841  
   842  inline Reference TypedVector::operator[](size_t i) const {
   843    auto len = size();
   844    if (i >= len) return Reference(nullptr, 1, NullPackedType());
   845    auto elem = data_ + i * byte_width_;
   846    return Reference(elem, byte_width_, 1, type_);
   847  }
   848  
   849  inline Reference FixedTypedVector::operator[](size_t i) const {
   850    if (i >= len_) return Reference(nullptr, 1, NullPackedType());
   851    auto elem = data_ + i * byte_width_;
   852    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  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    auto end = buffer + size;
   888    auto byte_width = *--end;
   889    auto packed_type = *--end;
   890    end -= byte_width;  // The root data item.
   891    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    static BitWidth WidthB(size_t byte_width) {
  1415      switch (byte_width) {
  1416        case 1: return BIT_WIDTH_8;
  1417        case 2: return BIT_WIDTH_16;
  1418        case 4: return BIT_WIDTH_32;
  1419        case 8: return BIT_WIDTH_64;
  1420        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    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        : 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          reuse_tracker_(reuse_tracker) {
  1673      FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
  1674      if (reuse_tracker_) {
  1675        reuse_tracker_->clear();
  1676        reuse_tracker_->resize(size_, PackedType(BIT_WIDTH_8, FBT_NULL));
  1677      }
  1678    }
  1679  
  1680   private:
  1681    // Central location where any verification failures register.
  1682    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      return ok;
  1689    }
  1690  
  1691    // Verify any range within the buffer.
  1692    bool VerifyFrom(size_t elem, size_t elem_len) const {
  1693      return Check(elem_len < size_ && elem <= size_ - elem_len);
  1694    }
  1695    bool VerifyBefore(size_t elem, size_t elem_len) const {
  1696      return Check(elem_len <= elem);
  1697    }
  1698  
  1699    bool VerifyFromPointer(const uint8_t *p, size_t len) {
  1700      auto o = static_cast<size_t>(p - buf_);
  1701      return VerifyFrom(o, len);
  1702    }
  1703    bool VerifyBeforePointer(const uint8_t *p, size_t len) {
  1704      auto o = static_cast<size_t>(p - buf_);
  1705      return VerifyBefore(o, len);
  1706    }
  1707  
  1708    bool VerifyByteWidth(size_t width) {
  1709      return Check(width == 1 || width == 2 || width == 4 || width == 8);
  1710    }
  1711  
  1712    bool VerifyType(int type) { return Check(type >= 0 && type < FBT_MAX_TYPE); }
  1713  
  1714    bool VerifyOffset(uint64_t off, const uint8_t *p) {
  1715      return Check(off <= static_cast<uint64_t>(size_)) &&
  1716             off <= static_cast<uint64_t>(p - buf_);
  1717    }
  1718  
  1719    bool VerifyAlignment(const uint8_t *p, size_t size) const {
  1720      auto o = static_cast<size_t>(p - buf_);
  1721      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    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      depth_++;
  1739      num_vectors_++;
  1740      if (!Check(depth_ <= max_depth_ && num_vectors_ <= max_vectors_))
  1741        return false;
  1742      auto size_byte_width = r.byte_width_;
  1743      if (!VerifyBeforePointer(p, size_byte_width)) return false;
  1744      FLEX_CHECK_VERIFIED(p - size_byte_width,
  1745                          PackedType(Builder::WidthB(size_byte_width), r.type_));
  1746      auto sized = Sized(p, size_byte_width);
  1747      auto num_elems = sized.size();
  1748      auto elem_byte_width = r.type_ == FBT_STRING || r.type_ == FBT_BLOB
  1749                                 ? uint8_t(1)
  1750                                 : r.byte_width_;
  1751      auto max_elems = SIZE_MAX / elem_byte_width;
  1752      if (!Check(num_elems < max_elems))
  1753        return false;  // Protect against byte_size overflowing.
  1754      auto byte_size = num_elems * elem_byte_width;
  1755      if (!VerifyFromPointer(p, byte_size)) return false;
  1756      if (elem_type == FBT_NULL) {
  1757        // Verify type bytes after the vector.
  1758        if (!VerifyFromPointer(p + byte_size, num_elems)) return false;
  1759        auto v = Vector(p, size_byte_width);
  1760        for (size_t i = 0; i < num_elems; i++)
  1761          if (!VerifyRef(v[i])) return false;
  1762      } else if (elem_type == FBT_KEY) {
  1763        auto v = TypedVector(p, elem_byte_width, FBT_KEY);
  1764        for (size_t i = 0; i < num_elems; i++)
  1765          if (!VerifyRef(v[i])) return false;
  1766      } else {
  1767        FLATBUFFERS_ASSERT(IsInline(elem_type));
  1768      }
  1769      depth_--;
  1770      return true;
  1771    }
  1772  
  1773    bool VerifyKeys(const uint8_t *p, uint8_t byte_width) {
  1774      // The vector part of the map has already been verified.
  1775      const size_t num_prefixed_fields = 3;
  1776      if (!VerifyBeforePointer(p, byte_width * num_prefixed_fields)) return false;
  1777      p -= byte_width * num_prefixed_fields;
  1778      auto off = ReadUInt64(p, byte_width);
  1779      if (!VerifyOffset(off, p)) return false;
  1780      auto key_byte_with =
  1781          static_cast<uint8_t>(ReadUInt64(p + byte_width, byte_width));
  1782      if (!VerifyByteWidth(key_byte_with)) return false;
  1783      return VerifyVector(Reference(p, byte_width, key_byte_with, FBT_VECTOR_KEY),
  1784                          p - off, FBT_KEY);
  1785    }
  1786  
  1787    bool VerifyKey(const uint8_t *p) {
  1788      FLEX_CHECK_VERIFIED(p, PackedType(BIT_WIDTH_8, FBT_KEY));
  1789      while (p < buf_ + size_)
  1790        if (*p++) return true;
  1791      return false;
  1792    }
  1793  
  1794  #undef FLEX_CHECK_VERIFIED
  1795  
  1796    bool VerifyTerminator(const String &s) {
  1797      return VerifyFromPointer(reinterpret_cast<const uint8_t *>(s.c_str()),
  1798                               s.size() + 1);
  1799    }
  1800  
  1801    bool VerifyRef(Reference r) {
  1802      // r.parent_width_ and r.data_ already verified.
  1803      if (!VerifyByteWidth(r.byte_width_) || !VerifyType(r.type_)) {
  1804        return false;
  1805      }
  1806      if (IsInline(r.type_)) {
  1807        // Inline scalars, don't require further verification.
  1808        return true;
  1809      }
  1810      // All remaining types are an offset.
  1811      auto off = ReadUInt64(r.data_, r.parent_width_);
  1812      if (!VerifyOffset(off, r.data_)) return false;
  1813      auto p = r.Indirect();
  1814      if (!VerifyAlignment(p, r.byte_width_)) return false;
  1815      switch (r.type_) {
  1816        case FBT_INDIRECT_INT:
  1817        case FBT_INDIRECT_UINT:
  1818        case FBT_INDIRECT_FLOAT: return VerifyFromPointer(p, r.byte_width_);
  1819        case FBT_KEY: return VerifyKey(p);
  1820        case FBT_MAP:
  1821          return VerifyVector(r, p, FBT_NULL) && VerifyKeys(p, r.byte_width_);
  1822        case FBT_VECTOR: return VerifyVector(r, p, FBT_NULL);
  1823        case FBT_VECTOR_INT: return VerifyVector(r, p, FBT_INT);
  1824        case FBT_VECTOR_BOOL:
  1825        case FBT_VECTOR_UINT: return VerifyVector(r, p, FBT_UINT);
  1826        case FBT_VECTOR_FLOAT: return VerifyVector(r, p, FBT_FLOAT);
  1827        case FBT_VECTOR_KEY: return VerifyVector(r, p, FBT_KEY);
  1828        case FBT_VECTOR_STRING_DEPRECATED:
  1829          // Use of FBT_KEY here intentional, see elsewhere.
  1830          return VerifyVector(r, p, FBT_KEY);
  1831        case FBT_BLOB: return VerifyVector(r, p, FBT_UINT);
  1832        case FBT_STRING:
  1833          return VerifyVector(r, p, FBT_UINT) &&
  1834                 VerifyTerminator(String(p, r.byte_width_));
  1835        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          uint8_t len = 0;
  1845          auto vtype = ToFixedTypedVectorElementType(r.type_, &len);
  1846          if (!VerifyType(vtype)) return false;
  1847          return VerifyFromPointer(p, r.byte_width_ * len);
  1848        }
  1849        default: return false;
  1850      }
  1851    }
  1852  
  1853   public:
  1854    bool VerifyBuffer() {
  1855      if (!Check(size_ >= 3)) return false;
  1856      auto end = buf_ + size_;
  1857      auto byte_width = *--end;
  1858      auto packed_type = *--end;
  1859      return VerifyByteWidth(byte_width) && Check(end - buf_ >= byte_width) &&
  1860             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  inline bool VerifyBuffer(const uint8_t *buf, size_t buf_len,
  1877                           std::vector<uint8_t> *reuse_tracker = nullptr) {
  1878    Verifier verifier(buf, buf_len, reuse_tracker);
  1879    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_