Home | History | Annotate | Download | only in flatbuffers
      1 /*
      2  * Copyright 2014 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_H_
     18 #define FLATBUFFERS_H_
     19 
     20 #include "flatbuffers/base.h"
     21 
     22 #if defined(FLATBUFFERS_NAN_DEFAULTS)
     23 #include <cmath>
     24 #endif
     25 
     26 namespace flatbuffers {
     27 // Generic 'operator==' with conditional specialisations.
     28 template<typename T> inline bool IsTheSameAs(T e, T def) { return e == def; }
     29 
     30 #if defined(FLATBUFFERS_NAN_DEFAULTS) && \
     31     (!defined(_MSC_VER) || _MSC_VER >= 1800)
     32 // Like `operator==(e, def)` with weak NaN if T=(float|double).
     33 template<> inline bool IsTheSameAs<float>(float e, float def) {
     34   return (e == def) || (std::isnan(def) && std::isnan(e));
     35 }
     36 template<> inline bool IsTheSameAs<double>(double e, double def) {
     37   return (e == def) || (std::isnan(def) && std::isnan(e));
     38 }
     39 #endif
     40 
     41 // Wrapper for uoffset_t to allow safe template specialization.
     42 // Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
     43 template<typename T> struct Offset {
     44   uoffset_t o;
     45   Offset() : o(0) {}
     46   Offset(uoffset_t _o) : o(_o) {}
     47   Offset<void> Union() const { return Offset<void>(o); }
     48   bool IsNull() const { return !o; }
     49 };
     50 
     51 inline void EndianCheck() {
     52   int endiantest = 1;
     53   // If this fails, see FLATBUFFERS_LITTLEENDIAN above.
     54   FLATBUFFERS_ASSERT(*reinterpret_cast<char *>(&endiantest) ==
     55                      FLATBUFFERS_LITTLEENDIAN);
     56   (void)endiantest;
     57 }
     58 
     59 template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() {
     60   // clang-format off
     61   #ifdef _MSC_VER
     62     return __alignof(T);
     63   #else
     64     #ifndef alignof
     65       return __alignof__(T);
     66     #else
     67       return alignof(T);
     68     #endif
     69   #endif
     70   // clang-format on
     71 }
     72 
     73 // When we read serialized data from memory, in the case of most scalars,
     74 // we want to just read T, but in the case of Offset, we want to actually
     75 // perform the indirection and return a pointer.
     76 // The template specialization below does just that.
     77 // It is wrapped in a struct since function templates can't overload on the
     78 // return type like this.
     79 // The typedef is for the convenience of callers of this function
     80 // (avoiding the need for a trailing return decltype)
     81 template<typename T> struct IndirectHelper {
     82   typedef T return_type;
     83   typedef T mutable_return_type;
     84   static const size_t element_stride = sizeof(T);
     85   static return_type Read(const uint8_t *p, uoffset_t i) {
     86     return EndianScalar((reinterpret_cast<const T *>(p))[i]);
     87   }
     88 };
     89 template<typename T> struct IndirectHelper<Offset<T>> {
     90   typedef const T *return_type;
     91   typedef T *mutable_return_type;
     92   static const size_t element_stride = sizeof(uoffset_t);
     93   static return_type Read(const uint8_t *p, uoffset_t i) {
     94     p += i * sizeof(uoffset_t);
     95     return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p));
     96   }
     97 };
     98 template<typename T> struct IndirectHelper<const T *> {
     99   typedef const T *return_type;
    100   typedef T *mutable_return_type;
    101   static const size_t element_stride = sizeof(T);
    102   static return_type Read(const uint8_t *p, uoffset_t i) {
    103     return reinterpret_cast<const T *>(p + i * sizeof(T));
    104   }
    105 };
    106 
    107 // An STL compatible iterator implementation for Vector below, effectively
    108 // calling Get() for every element.
    109 template<typename T, typename IT> struct VectorIterator {
    110   typedef std::random_access_iterator_tag iterator_category;
    111   typedef IT value_type;
    112   typedef ptrdiff_t difference_type;
    113   typedef IT *pointer;
    114   typedef IT &reference;
    115 
    116   VectorIterator(const uint8_t *data, uoffset_t i)
    117       : data_(data + IndirectHelper<T>::element_stride * i) {}
    118   VectorIterator(const VectorIterator &other) : data_(other.data_) {}
    119   VectorIterator() : data_(nullptr) {}
    120 
    121   VectorIterator &operator=(const VectorIterator &other) {
    122     data_ = other.data_;
    123     return *this;
    124   }
    125 
    126   // clang-format off
    127   #if !defined(FLATBUFFERS_CPP98_STL)
    128   VectorIterator &operator=(VectorIterator &&other) {
    129     data_ = other.data_;
    130     return *this;
    131   }
    132   #endif  // !defined(FLATBUFFERS_CPP98_STL)
    133   // clang-format on
    134 
    135   bool operator==(const VectorIterator &other) const {
    136     return data_ == other.data_;
    137   }
    138 
    139   bool operator<(const VectorIterator &other) const {
    140     return data_ < other.data_;
    141   }
    142 
    143   bool operator!=(const VectorIterator &other) const {
    144     return data_ != other.data_;
    145   }
    146 
    147   difference_type operator-(const VectorIterator &other) const {
    148     return (data_ - other.data_) / IndirectHelper<T>::element_stride;
    149   }
    150 
    151   IT operator*() const { return IndirectHelper<T>::Read(data_, 0); }
    152 
    153   IT operator->() const { return IndirectHelper<T>::Read(data_, 0); }
    154 
    155   VectorIterator &operator++() {
    156     data_ += IndirectHelper<T>::element_stride;
    157     return *this;
    158   }
    159 
    160   VectorIterator operator++(int) {
    161     VectorIterator temp(data_, 0);
    162     data_ += IndirectHelper<T>::element_stride;
    163     return temp;
    164   }
    165 
    166   VectorIterator operator+(const uoffset_t &offset) const {
    167     return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride,
    168                           0);
    169   }
    170 
    171   VectorIterator &operator+=(const uoffset_t &offset) {
    172     data_ += offset * IndirectHelper<T>::element_stride;
    173     return *this;
    174   }
    175 
    176   VectorIterator &operator--() {
    177     data_ -= IndirectHelper<T>::element_stride;
    178     return *this;
    179   }
    180 
    181   VectorIterator operator--(int) {
    182     VectorIterator temp(data_, 0);
    183     data_ -= IndirectHelper<T>::element_stride;
    184     return temp;
    185   }
    186 
    187   VectorIterator operator-(const uoffset_t &offset) const {
    188     return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride,
    189                           0);
    190   }
    191 
    192   VectorIterator &operator-=(const uoffset_t &offset) {
    193     data_ -= offset * IndirectHelper<T>::element_stride;
    194     return *this;
    195   }
    196 
    197  private:
    198   const uint8_t *data_;
    199 };
    200 
    201 template<typename Iterator> struct VectorReverseIterator :
    202   public std::reverse_iterator<Iterator> {
    203 
    204   explicit VectorReverseIterator(Iterator iter) : iter_(iter) {}
    205 
    206   typename Iterator::value_type operator*() const { return *(iter_ - 1); }
    207 
    208   typename Iterator::value_type operator->() const { return *(iter_ - 1); }
    209 
    210  private:
    211   Iterator iter_;
    212 };
    213 
    214 struct String;
    215 
    216 // This is used as a helper type for accessing vectors.
    217 // Vector::data() assumes the vector elements start after the length field.
    218 template<typename T> class Vector {
    219  public:
    220   typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
    221       iterator;
    222   typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
    223       const_iterator;
    224   typedef VectorReverseIterator<iterator> reverse_iterator;
    225   typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
    226 
    227   uoffset_t size() const { return EndianScalar(length_); }
    228 
    229   // Deprecated: use size(). Here for backwards compatibility.
    230   FLATBUFFERS_ATTRIBUTE(deprecated("use size() instead"))
    231   uoffset_t Length() const { return size(); }
    232 
    233   typedef typename IndirectHelper<T>::return_type return_type;
    234   typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
    235 
    236   return_type Get(uoffset_t i) const {
    237     FLATBUFFERS_ASSERT(i < size());
    238     return IndirectHelper<T>::Read(Data(), i);
    239   }
    240 
    241   return_type operator[](uoffset_t i) const { return Get(i); }
    242 
    243   // If this is a Vector of enums, T will be its storage type, not the enum
    244   // type. This function makes it convenient to retrieve value with enum
    245   // type E.
    246   template<typename E> E GetEnum(uoffset_t i) const {
    247     return static_cast<E>(Get(i));
    248   }
    249 
    250   // If this a vector of unions, this does the cast for you. There's no check
    251   // to make sure this is the right type!
    252   template<typename U> const U *GetAs(uoffset_t i) const {
    253     return reinterpret_cast<const U *>(Get(i));
    254   }
    255 
    256   // If this a vector of unions, this does the cast for you. There's no check
    257   // to make sure this is actually a string!
    258   const String *GetAsString(uoffset_t i) const {
    259     return reinterpret_cast<const String *>(Get(i));
    260   }
    261 
    262   const void *GetStructFromOffset(size_t o) const {
    263     return reinterpret_cast<const void *>(Data() + o);
    264   }
    265 
    266   iterator begin() { return iterator(Data(), 0); }
    267   const_iterator begin() const { return const_iterator(Data(), 0); }
    268 
    269   iterator end() { return iterator(Data(), size()); }
    270   const_iterator end() const { return const_iterator(Data(), size()); }
    271 
    272   reverse_iterator rbegin() { return reverse_iterator(end()); }
    273   const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
    274 
    275   reverse_iterator rend() { return reverse_iterator(end()); }
    276   const_reverse_iterator rend() const { return const_reverse_iterator(end()); }
    277 
    278   const_iterator cbegin() const { return begin(); }
    279 
    280   const_iterator cend() const { return end(); }
    281 
    282   const_reverse_iterator crbegin() const { return rbegin(); }
    283 
    284   const_reverse_iterator crend() const { return rend(); }
    285 
    286   // Change elements if you have a non-const pointer to this object.
    287   // Scalars only. See reflection.h, and the documentation.
    288   void Mutate(uoffset_t i, const T &val) {
    289     FLATBUFFERS_ASSERT(i < size());
    290     WriteScalar(data() + i, val);
    291   }
    292 
    293   // Change an element of a vector of tables (or strings).
    294   // "val" points to the new table/string, as you can obtain from
    295   // e.g. reflection::AddFlatBuffer().
    296   void MutateOffset(uoffset_t i, const uint8_t *val) {
    297     FLATBUFFERS_ASSERT(i < size());
    298     static_assert(sizeof(T) == sizeof(uoffset_t), "Unrelated types");
    299     WriteScalar(data() + i,
    300                 static_cast<uoffset_t>(val - (Data() + i * sizeof(uoffset_t))));
    301   }
    302 
    303   // Get a mutable pointer to tables/strings inside this vector.
    304   mutable_return_type GetMutableObject(uoffset_t i) const {
    305     FLATBUFFERS_ASSERT(i < size());
    306     return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i));
    307   }
    308 
    309   // The raw data in little endian format. Use with care.
    310   const uint8_t *Data() const {
    311     return reinterpret_cast<const uint8_t *>(&length_ + 1);
    312   }
    313 
    314   uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
    315 
    316   // Similarly, but typed, much like std::vector::data
    317   const T *data() const { return reinterpret_cast<const T *>(Data()); }
    318   T *data() { return reinterpret_cast<T *>(Data()); }
    319 
    320   template<typename K> return_type LookupByKey(K key) const {
    321     void *search_result = std::bsearch(
    322         &key, Data(), size(), IndirectHelper<T>::element_stride, KeyCompare<K>);
    323 
    324     if (!search_result) {
    325       return nullptr;  // Key not found.
    326     }
    327 
    328     const uint8_t *element = reinterpret_cast<const uint8_t *>(search_result);
    329 
    330     return IndirectHelper<T>::Read(element, 0);
    331   }
    332 
    333  protected:
    334   // This class is only used to access pre-existing data. Don't ever
    335   // try to construct these manually.
    336   Vector();
    337 
    338   uoffset_t length_;
    339 
    340  private:
    341   // This class is a pointer. Copying will therefore create an invalid object.
    342   // Private and unimplemented copy constructor.
    343   Vector(const Vector &);
    344 
    345   template<typename K> static int KeyCompare(const void *ap, const void *bp) {
    346     const K *key = reinterpret_cast<const K *>(ap);
    347     const uint8_t *data = reinterpret_cast<const uint8_t *>(bp);
    348     auto table = IndirectHelper<T>::Read(data, 0);
    349 
    350     // std::bsearch compares with the operands transposed, so we negate the
    351     // result here.
    352     return -table->KeyCompareWithValue(*key);
    353   }
    354 };
    355 
    356 // Represent a vector much like the template above, but in this case we
    357 // don't know what the element types are (used with reflection.h).
    358 class VectorOfAny {
    359  public:
    360   uoffset_t size() const { return EndianScalar(length_); }
    361 
    362   const uint8_t *Data() const {
    363     return reinterpret_cast<const uint8_t *>(&length_ + 1);
    364   }
    365   uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
    366 
    367  protected:
    368   VectorOfAny();
    369 
    370   uoffset_t length_;
    371 
    372  private:
    373   VectorOfAny(const VectorOfAny &);
    374 };
    375 
    376 #ifndef FLATBUFFERS_CPP98_STL
    377 template<typename T, typename U>
    378 Vector<Offset<T>> *VectorCast(Vector<Offset<U>> *ptr) {
    379   static_assert(std::is_base_of<T, U>::value, "Unrelated types");
    380   return reinterpret_cast<Vector<Offset<T>> *>(ptr);
    381 }
    382 
    383 template<typename T, typename U>
    384 const Vector<Offset<T>> *VectorCast(const Vector<Offset<U>> *ptr) {
    385   static_assert(std::is_base_of<T, U>::value, "Unrelated types");
    386   return reinterpret_cast<const Vector<Offset<T>> *>(ptr);
    387 }
    388 #endif
    389 
    390 // Convenient helper function to get the length of any vector, regardless
    391 // of whether it is null or not (the field is not set).
    392 template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
    393   return v ? v->size() : 0;
    394 }
    395 
    396 // Lexicographically compare two strings (possibly containing nulls), and
    397 // return true if the first is less than the second.
    398 static inline bool StringLessThan(const char *a_data, uoffset_t a_size,
    399                                   const char *b_data, uoffset_t b_size) {
    400   const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size));
    401   return cmp == 0 ? a_size < b_size : cmp < 0;
    402 }
    403 
    404 struct String : public Vector<char> {
    405   const char *c_str() const { return reinterpret_cast<const char *>(Data()); }
    406   std::string str() const { return std::string(c_str(), size()); }
    407 
    408   // clang-format off
    409   #ifdef FLATBUFFERS_HAS_STRING_VIEW
    410   flatbuffers::string_view string_view() const {
    411     return flatbuffers::string_view(c_str(), size());
    412   }
    413   #endif // FLATBUFFERS_HAS_STRING_VIEW
    414   // clang-format on
    415 
    416   bool operator<(const String &o) const {
    417     return StringLessThan(this->data(), this->size(), o.data(), o.size());
    418   }
    419 };
    420 
    421 // Convenience function to get std::string from a String returning an empty
    422 // string on null pointer.
    423 static inline std::string GetString(const String * str) {
    424   return str ? str->str() : "";
    425 }
    426 
    427 // Convenience function to get char* from a String returning an empty string on
    428 // null pointer.
    429 static inline const char * GetCstring(const String * str) {
    430   return str ? str->c_str() : "";
    431 }
    432 
    433 // Allocator interface. This is flatbuffers-specific and meant only for
    434 // `vector_downward` usage.
    435 class Allocator {
    436  public:
    437   virtual ~Allocator() {}
    438 
    439   // Allocate `size` bytes of memory.
    440   virtual uint8_t *allocate(size_t size) = 0;
    441 
    442   // Deallocate `size` bytes of memory at `p` allocated by this allocator.
    443   virtual void deallocate(uint8_t *p, size_t size) = 0;
    444 
    445   // Reallocate `new_size` bytes of memory, replacing the old region of size
    446   // `old_size` at `p`. In contrast to a normal realloc, this grows downwards,
    447   // and is intended specifcally for `vector_downward` use.
    448   // `in_use_back` and `in_use_front` indicate how much of `old_size` is
    449   // actually in use at each end, and needs to be copied.
    450   virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
    451                                        size_t new_size, size_t in_use_back,
    452                                        size_t in_use_front) {
    453     FLATBUFFERS_ASSERT(new_size > old_size);  // vector_downward only grows
    454     uint8_t *new_p = allocate(new_size);
    455     memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
    456                     in_use_front);
    457     deallocate(old_p, old_size);
    458     return new_p;
    459   }
    460 
    461  protected:
    462   // Called by `reallocate_downward` to copy memory from `old_p` of `old_size`
    463   // to `new_p` of `new_size`. Only memory of size `in_use_front` and
    464   // `in_use_back` will be copied from the front and back of the old memory
    465   // allocation.
    466   void memcpy_downward(uint8_t *old_p, size_t old_size,
    467                        uint8_t *new_p, size_t new_size,
    468                        size_t in_use_back, size_t in_use_front) {
    469     memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back,
    470            in_use_back);
    471     memcpy(new_p, old_p, in_use_front);
    472   }
    473 };
    474 
    475 // DefaultAllocator uses new/delete to allocate memory regions
    476 class DefaultAllocator : public Allocator {
    477  public:
    478   uint8_t *allocate(size_t size) FLATBUFFERS_OVERRIDE {
    479     return new uint8_t[size];
    480   }
    481 
    482   void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE {
    483     delete[] p;
    484   }
    485 
    486   static void dealloc(void *p, size_t) {
    487     delete[] static_cast<uint8_t *>(p);
    488   }
    489 };
    490 
    491 // These functions allow for a null allocator to mean use the default allocator,
    492 // as used by DetachedBuffer and vector_downward below.
    493 // This is to avoid having a statically or dynamically allocated default
    494 // allocator, or having to move it between the classes that may own it.
    495 inline uint8_t *Allocate(Allocator *allocator, size_t size) {
    496   return allocator ? allocator->allocate(size)
    497                    : DefaultAllocator().allocate(size);
    498 }
    499 
    500 inline void Deallocate(Allocator *allocator, uint8_t *p, size_t size) {
    501   if (allocator) allocator->deallocate(p, size);
    502   else DefaultAllocator().deallocate(p, size);
    503 }
    504 
    505 inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p,
    506                                    size_t old_size, size_t new_size,
    507                                    size_t in_use_back, size_t in_use_front) {
    508   return allocator
    509       ? allocator->reallocate_downward(old_p, old_size, new_size,
    510                                        in_use_back, in_use_front)
    511       : DefaultAllocator().reallocate_downward(old_p, old_size, new_size,
    512                                                in_use_back, in_use_front);
    513 }
    514 
    515 // DetachedBuffer is a finished flatbuffer memory region, detached from its
    516 // builder. The original memory region and allocator are also stored so that
    517 // the DetachedBuffer can manage the memory lifetime.
    518 class DetachedBuffer {
    519  public:
    520   DetachedBuffer()
    521       : allocator_(nullptr),
    522         own_allocator_(false),
    523         buf_(nullptr),
    524         reserved_(0),
    525         cur_(nullptr),
    526         size_(0) {}
    527 
    528   DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf,
    529                  size_t reserved, uint8_t *cur, size_t sz)
    530       : allocator_(allocator),
    531         own_allocator_(own_allocator),
    532         buf_(buf),
    533         reserved_(reserved),
    534         cur_(cur),
    535         size_(sz) {}
    536 
    537   // clang-format off
    538   #if !defined(FLATBUFFERS_CPP98_STL)
    539   // clang-format on
    540   DetachedBuffer(DetachedBuffer &&other)
    541       : allocator_(other.allocator_),
    542         own_allocator_(other.own_allocator_),
    543         buf_(other.buf_),
    544         reserved_(other.reserved_),
    545         cur_(other.cur_),
    546         size_(other.size_) {
    547     other.reset();
    548   }
    549   // clang-format off
    550   #endif  // !defined(FLATBUFFERS_CPP98_STL)
    551   // clang-format on
    552 
    553   // clang-format off
    554   #if !defined(FLATBUFFERS_CPP98_STL)
    555   // clang-format on
    556   DetachedBuffer &operator=(DetachedBuffer &&other) {
    557     destroy();
    558 
    559     allocator_ = other.allocator_;
    560     own_allocator_ = other.own_allocator_;
    561     buf_ = other.buf_;
    562     reserved_ = other.reserved_;
    563     cur_ = other.cur_;
    564     size_ = other.size_;
    565 
    566     other.reset();
    567 
    568     return *this;
    569   }
    570   // clang-format off
    571   #endif  // !defined(FLATBUFFERS_CPP98_STL)
    572   // clang-format on
    573 
    574   ~DetachedBuffer() { destroy(); }
    575 
    576   const uint8_t *data() const { return cur_; }
    577 
    578   uint8_t *data() { return cur_; }
    579 
    580   size_t size() const { return size_; }
    581 
    582   // clang-format off
    583   #if 0  // disabled for now due to the ordering of classes in this header
    584   template <class T>
    585   bool Verify() const {
    586     Verifier verifier(data(), size());
    587     return verifier.Verify<T>(nullptr);
    588   }
    589 
    590   template <class T>
    591   const T* GetRoot() const {
    592     return flatbuffers::GetRoot<T>(data());
    593   }
    594 
    595   template <class T>
    596   T* GetRoot() {
    597     return flatbuffers::GetRoot<T>(data());
    598   }
    599   #endif
    600   // clang-format on
    601 
    602   // clang-format off
    603   #if !defined(FLATBUFFERS_CPP98_STL)
    604   // clang-format on
    605   // These may change access mode, leave these at end of public section
    606   FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other))
    607   FLATBUFFERS_DELETE_FUNC(
    608       DetachedBuffer &operator=(const DetachedBuffer &other))
    609   // clang-format off
    610   #endif  // !defined(FLATBUFFERS_CPP98_STL)
    611   // clang-format on
    612 
    613 protected:
    614   Allocator *allocator_;
    615   bool own_allocator_;
    616   uint8_t *buf_;
    617   size_t reserved_;
    618   uint8_t *cur_;
    619   size_t size_;
    620 
    621   inline void destroy() {
    622     if (buf_) Deallocate(allocator_, buf_, reserved_);
    623     if (own_allocator_ && allocator_) { delete allocator_; }
    624     reset();
    625   }
    626 
    627   inline void reset() {
    628     allocator_ = nullptr;
    629     own_allocator_ = false;
    630     buf_ = nullptr;
    631     reserved_ = 0;
    632     cur_ = nullptr;
    633     size_ = 0;
    634   }
    635 };
    636 
    637 // This is a minimal replication of std::vector<uint8_t> functionality,
    638 // except growing from higher to lower addresses. i.e push_back() inserts data
    639 // in the lowest address in the vector.
    640 // Since this vector leaves the lower part unused, we support a "scratch-pad"
    641 // that can be stored there for temporary data, to share the allocated space.
    642 // Essentially, this supports 2 std::vectors in a single buffer.
    643 class vector_downward {
    644  public:
    645   explicit vector_downward(size_t initial_size,
    646                            Allocator *allocator,
    647                            bool own_allocator,
    648                            size_t buffer_minalign)
    649       : allocator_(allocator),
    650         own_allocator_(own_allocator),
    651         initial_size_(initial_size),
    652         buffer_minalign_(buffer_minalign),
    653         reserved_(0),
    654         buf_(nullptr),
    655         cur_(nullptr),
    656         scratch_(nullptr) {}
    657 
    658   // clang-format off
    659   #if !defined(FLATBUFFERS_CPP98_STL)
    660   vector_downward(vector_downward &&other)
    661   #else
    662   vector_downward(vector_downward &other)
    663   #endif  // defined(FLATBUFFERS_CPP98_STL)
    664   // clang-format on
    665     : allocator_(other.allocator_),
    666       own_allocator_(other.own_allocator_),
    667       initial_size_(other.initial_size_),
    668       buffer_minalign_(other.buffer_minalign_),
    669       reserved_(other.reserved_),
    670       buf_(other.buf_),
    671       cur_(other.cur_),
    672       scratch_(other.scratch_) {
    673     // No change in other.allocator_
    674     // No change in other.initial_size_
    675     // No change in other.buffer_minalign_
    676     other.own_allocator_ = false;
    677     other.reserved_ = 0;
    678     other.buf_ = nullptr;
    679     other.cur_ = nullptr;
    680     other.scratch_ = nullptr;
    681   }
    682 
    683   // clang-format off
    684   #if !defined(FLATBUFFERS_CPP98_STL)
    685   // clang-format on
    686   vector_downward &operator=(vector_downward &&other) {
    687     // Move construct a temporary and swap idiom
    688     vector_downward temp(std::move(other));
    689     swap(temp);
    690     return *this;
    691   }
    692   // clang-format off
    693   #endif  // defined(FLATBUFFERS_CPP98_STL)
    694   // clang-format on
    695 
    696   ~vector_downward() {
    697     clear_buffer();
    698     clear_allocator();
    699   }
    700 
    701   void reset() {
    702     clear_buffer();
    703     clear();
    704   }
    705 
    706   void clear() {
    707     if (buf_) {
    708       cur_ = buf_ + reserved_;
    709     } else {
    710       reserved_ = 0;
    711       cur_ = nullptr;
    712     }
    713     clear_scratch();
    714   }
    715 
    716   void clear_scratch() {
    717     scratch_ = buf_;
    718   }
    719 
    720   void clear_allocator() {
    721     if (own_allocator_ && allocator_) { delete allocator_; }
    722     allocator_ = nullptr;
    723     own_allocator_ = false;
    724   }
    725 
    726   void clear_buffer() {
    727     if (buf_) Deallocate(allocator_, buf_, reserved_);
    728     buf_ = nullptr;
    729   }
    730 
    731   // Relinquish the pointer to the caller.
    732   uint8_t *release_raw(size_t &allocated_bytes, size_t &offset) {
    733     auto *buf = buf_;
    734     allocated_bytes = reserved_;
    735     offset = static_cast<size_t>(cur_ - buf_);
    736 
    737     // release_raw only relinquishes the buffer ownership.
    738     // Does not deallocate or reset the allocator. Destructor will do that.
    739     buf_ = nullptr;
    740     clear();
    741     return buf;
    742   }
    743 
    744   // Relinquish the pointer to the caller.
    745   DetachedBuffer release() {
    746     // allocator ownership (if any) is transferred to DetachedBuffer.
    747     DetachedBuffer fb(allocator_, own_allocator_, buf_, reserved_, cur_,
    748                       size());
    749     if (own_allocator_) {
    750       allocator_ = nullptr;
    751       own_allocator_ = false;
    752     }
    753     buf_ = nullptr;
    754     clear();
    755     return fb;
    756   }
    757 
    758   size_t ensure_space(size_t len) {
    759     FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_);
    760     if (len > static_cast<size_t>(cur_ - scratch_)) { reallocate(len); }
    761     // Beyond this, signed offsets may not have enough range:
    762     // (FlatBuffers > 2GB not supported).
    763     FLATBUFFERS_ASSERT(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
    764     return len;
    765   }
    766 
    767   inline uint8_t *make_space(size_t len) {
    768     size_t space = ensure_space(len);
    769     cur_ -= space;
    770     return cur_;
    771   }
    772 
    773   // Returns nullptr if using the DefaultAllocator.
    774   Allocator *get_custom_allocator() { return allocator_; }
    775 
    776   uoffset_t size() const {
    777     return static_cast<uoffset_t>(reserved_ - (cur_ - buf_));
    778   }
    779 
    780   uoffset_t scratch_size() const {
    781     return static_cast<uoffset_t>(scratch_ - buf_);
    782   }
    783 
    784   size_t capacity() const { return reserved_; }
    785 
    786   uint8_t *data() const {
    787     FLATBUFFERS_ASSERT(cur_);
    788     return cur_;
    789   }
    790 
    791   uint8_t *scratch_data() const {
    792     FLATBUFFERS_ASSERT(buf_);
    793     return buf_;
    794   }
    795 
    796   uint8_t *scratch_end() const {
    797     FLATBUFFERS_ASSERT(scratch_);
    798     return scratch_;
    799   }
    800 
    801   uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; }
    802 
    803   void push(const uint8_t *bytes, size_t num) {
    804     memcpy(make_space(num), bytes, num);
    805   }
    806 
    807   // Specialized version of push() that avoids memcpy call for small data.
    808   template<typename T> void push_small(const T &little_endian_t) {
    809     make_space(sizeof(T));
    810     *reinterpret_cast<T *>(cur_) = little_endian_t;
    811   }
    812 
    813   template<typename T> void scratch_push_small(const T &t) {
    814     ensure_space(sizeof(T));
    815     *reinterpret_cast<T *>(scratch_) = t;
    816     scratch_ += sizeof(T);
    817   }
    818 
    819   // fill() is most frequently called with small byte counts (<= 4),
    820   // which is why we're using loops rather than calling memset.
    821   void fill(size_t zero_pad_bytes) {
    822     make_space(zero_pad_bytes);
    823     for (size_t i = 0; i < zero_pad_bytes; i++) cur_[i] = 0;
    824   }
    825 
    826   // Version for when we know the size is larger.
    827   void fill_big(size_t zero_pad_bytes) {
    828     memset(make_space(zero_pad_bytes), 0, zero_pad_bytes);
    829   }
    830 
    831   void pop(size_t bytes_to_remove) { cur_ += bytes_to_remove; }
    832   void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; }
    833 
    834   void swap(vector_downward &other) {
    835     using std::swap;
    836     swap(allocator_, other.allocator_);
    837     swap(own_allocator_, other.own_allocator_);
    838     swap(initial_size_, other.initial_size_);
    839     swap(buffer_minalign_, other.buffer_minalign_);
    840     swap(reserved_, other.reserved_);
    841     swap(buf_, other.buf_);
    842     swap(cur_, other.cur_);
    843     swap(scratch_, other.scratch_);
    844   }
    845 
    846   void swap_allocator(vector_downward &other) {
    847     using std::swap;
    848     swap(allocator_, other.allocator_);
    849     swap(own_allocator_, other.own_allocator_);
    850   }
    851 
    852  private:
    853   // You shouldn't really be copying instances of this class.
    854   FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward &))
    855   FLATBUFFERS_DELETE_FUNC(vector_downward &operator=(const vector_downward &))
    856 
    857   Allocator *allocator_;
    858   bool own_allocator_;
    859   size_t initial_size_;
    860   size_t buffer_minalign_;
    861   size_t reserved_;
    862   uint8_t *buf_;
    863   uint8_t *cur_;  // Points at location between empty (below) and used (above).
    864   uint8_t *scratch_;  // Points to the end of the scratchpad in use.
    865 
    866   void reallocate(size_t len) {
    867     auto old_reserved = reserved_;
    868     auto old_size = size();
    869     auto old_scratch_size = scratch_size();
    870     reserved_ += (std::max)(len,
    871                             old_reserved ? old_reserved / 2 : initial_size_);
    872     reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1);
    873     if (buf_) {
    874       buf_ = ReallocateDownward(allocator_, buf_, old_reserved, reserved_,
    875                                 old_size, old_scratch_size);
    876     } else {
    877       buf_ = Allocate(allocator_, reserved_);
    878     }
    879     cur_ = buf_ + reserved_ - old_size;
    880     scratch_ = buf_ + old_scratch_size;
    881   }
    882 };
    883 
    884 // Converts a Field ID to a virtual table offset.
    885 inline voffset_t FieldIndexToOffset(voffset_t field_id) {
    886   // Should correspond to what EndTable() below builds up.
    887   const int fixed_fields = 2;  // Vtable size and Object Size.
    888   return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t));
    889 }
    890 
    891 template<typename T, typename Alloc>
    892 const T *data(const std::vector<T, Alloc> &v) {
    893   return v.empty() ? nullptr : &v.front();
    894 }
    895 template<typename T, typename Alloc> T *data(std::vector<T, Alloc> &v) {
    896   return v.empty() ? nullptr : &v.front();
    897 }
    898 
    899 /// @endcond
    900 
    901 /// @addtogroup flatbuffers_cpp_api
    902 /// @{
    903 /// @class FlatBufferBuilder
    904 /// @brief Helper class to hold data needed in creation of a FlatBuffer.
    905 /// To serialize data, you typically call one of the `Create*()` functions in
    906 /// the generated code, which in turn call a sequence of `StartTable`/
    907 /// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/
    908 /// `CreateVector` functions. Do this is depth-first order to build up a tree to
    909 /// the root. `Finish()` wraps up the buffer ready for transport.
    910 class FlatBufferBuilder {
    911  public:
    912   /// @brief Default constructor for FlatBufferBuilder.
    913   /// @param[in] initial_size The initial size of the buffer, in bytes. Defaults
    914   /// to `1024`.
    915   /// @param[in] allocator An `Allocator` to use. If null will use
    916   /// `DefaultAllocator`.
    917   /// @param[in] own_allocator Whether the builder/vector should own the
    918   /// allocator. Defaults to / `false`.
    919   /// @param[in] buffer_minalign Force the buffer to be aligned to the given
    920   /// minimum alignment upon reallocation. Only needed if you intend to store
    921   /// types with custom alignment AND you wish to read the buffer in-place
    922   /// directly after creation.
    923   explicit FlatBufferBuilder(size_t initial_size = 1024,
    924                              Allocator *allocator = nullptr,
    925                              bool own_allocator = false,
    926                              size_t buffer_minalign =
    927                                  AlignOf<largest_scalar_t>())
    928       : buf_(initial_size, allocator, own_allocator, buffer_minalign),
    929         num_field_loc(0),
    930         max_voffset_(0),
    931         nested(false),
    932         finished(false),
    933         minalign_(1),
    934         force_defaults_(false),
    935         dedup_vtables_(true),
    936         string_pool(nullptr) {
    937     EndianCheck();
    938   }
    939 
    940   // clang-format off
    941   /// @brief Move constructor for FlatBufferBuilder.
    942   #if !defined(FLATBUFFERS_CPP98_STL)
    943   FlatBufferBuilder(FlatBufferBuilder &&other)
    944   #else
    945   FlatBufferBuilder(FlatBufferBuilder &other)
    946   #endif  // #if !defined(FLATBUFFERS_CPP98_STL)
    947     : buf_(1024, nullptr, false, AlignOf<largest_scalar_t>()),
    948       num_field_loc(0),
    949       max_voffset_(0),
    950       nested(false),
    951       finished(false),
    952       minalign_(1),
    953       force_defaults_(false),
    954       dedup_vtables_(true),
    955       string_pool(nullptr) {
    956     EndianCheck();
    957     // Default construct and swap idiom.
    958     // Lack of delegating constructors in vs2010 makes it more verbose than needed.
    959     Swap(other);
    960   }
    961   // clang-format on
    962 
    963   // clang-format off
    964   #if !defined(FLATBUFFERS_CPP98_STL)
    965   // clang-format on
    966   /// @brief Move assignment operator for FlatBufferBuilder.
    967   FlatBufferBuilder &operator=(FlatBufferBuilder &&other) {
    968     // Move construct a temporary and swap idiom
    969     FlatBufferBuilder temp(std::move(other));
    970     Swap(temp);
    971     return *this;
    972   }
    973   // clang-format off
    974   #endif  // defined(FLATBUFFERS_CPP98_STL)
    975   // clang-format on
    976 
    977   void Swap(FlatBufferBuilder &other) {
    978     using std::swap;
    979     buf_.swap(other.buf_);
    980     swap(num_field_loc, other.num_field_loc);
    981     swap(max_voffset_, other.max_voffset_);
    982     swap(nested, other.nested);
    983     swap(finished, other.finished);
    984     swap(minalign_, other.minalign_);
    985     swap(force_defaults_, other.force_defaults_);
    986     swap(dedup_vtables_, other.dedup_vtables_);
    987     swap(string_pool, other.string_pool);
    988   }
    989 
    990   ~FlatBufferBuilder() {
    991     if (string_pool) delete string_pool;
    992   }
    993 
    994   void Reset() {
    995     Clear();       // clear builder state
    996     buf_.reset();  // deallocate buffer
    997   }
    998 
    999   /// @brief Reset all the state in this FlatBufferBuilder so it can be reused
   1000   /// to construct another buffer.
   1001   void Clear() {
   1002     ClearOffsets();
   1003     buf_.clear();
   1004     nested = false;
   1005     finished = false;
   1006     minalign_ = 1;
   1007     if (string_pool) string_pool->clear();
   1008   }
   1009 
   1010   /// @brief The current size of the serialized buffer, counting from the end.
   1011   /// @return Returns an `uoffset_t` with the current size of the buffer.
   1012   uoffset_t GetSize() const { return buf_.size(); }
   1013 
   1014   /// @brief Get the serialized buffer (after you call `Finish()`).
   1015   /// @return Returns an `uint8_t` pointer to the FlatBuffer data inside the
   1016   /// buffer.
   1017   uint8_t *GetBufferPointer() const {
   1018     Finished();
   1019     return buf_.data();
   1020   }
   1021 
   1022   /// @brief Get a pointer to an unfinished buffer.
   1023   /// @return Returns a `uint8_t` pointer to the unfinished buffer.
   1024   uint8_t *GetCurrentBufferPointer() const { return buf_.data(); }
   1025 
   1026   /// @brief Get the released pointer to the serialized buffer.
   1027   /// @warning Do NOT attempt to use this FlatBufferBuilder afterwards!
   1028   /// @return A `FlatBuffer` that owns the buffer and its allocator and
   1029   /// behaves similar to a `unique_ptr` with a deleter.
   1030   FLATBUFFERS_ATTRIBUTE(deprecated("use Release() instead")) DetachedBuffer
   1031   ReleaseBufferPointer() {
   1032     Finished();
   1033     return buf_.release();
   1034   }
   1035 
   1036   /// @brief Get the released DetachedBuffer.
   1037   /// @return A `DetachedBuffer` that owns the buffer and its allocator.
   1038   DetachedBuffer Release() {
   1039     Finished();
   1040     return buf_.release();
   1041   }
   1042 
   1043   /// @brief Get the released pointer to the serialized buffer.
   1044   /// @param The size of the memory block containing
   1045   /// the serialized `FlatBuffer`.
   1046   /// @param The offset from the released pointer where the finished
   1047   /// `FlatBuffer` starts.
   1048   /// @return A raw pointer to the start of the memory block containing
   1049   /// the serialized `FlatBuffer`.
   1050   /// @remark If the allocator is owned, it gets deleted when the destructor is called..
   1051   uint8_t *ReleaseRaw(size_t &size, size_t &offset) {
   1052     Finished();
   1053     return buf_.release_raw(size, offset);
   1054   }
   1055 
   1056   /// @brief get the minimum alignment this buffer needs to be accessed
   1057   /// properly. This is only known once all elements have been written (after
   1058   /// you call Finish()). You can use this information if you need to embed
   1059   /// a FlatBuffer in some other buffer, such that you can later read it
   1060   /// without first having to copy it into its own buffer.
   1061   size_t GetBufferMinAlignment() {
   1062     Finished();
   1063     return minalign_;
   1064   }
   1065 
   1066   /// @cond FLATBUFFERS_INTERNAL
   1067   void Finished() const {
   1068     // If you get this assert, you're attempting to get access a buffer
   1069     // which hasn't been finished yet. Be sure to call
   1070     // FlatBufferBuilder::Finish with your root table.
   1071     // If you really need to access an unfinished buffer, call
   1072     // GetCurrentBufferPointer instead.
   1073     FLATBUFFERS_ASSERT(finished);
   1074   }
   1075   /// @endcond
   1076 
   1077   /// @brief In order to save space, fields that are set to their default value
   1078   /// don't get serialized into the buffer.
   1079   /// @param[in] bool fd When set to `true`, always serializes default values that are set.
   1080   /// Optional fields which are not set explicitly, will still not be serialized.
   1081   void ForceDefaults(bool fd) { force_defaults_ = fd; }
   1082 
   1083   /// @brief By default vtables are deduped in order to save space.
   1084   /// @param[in] bool dedup When set to `true`, dedup vtables.
   1085   void DedupVtables(bool dedup) { dedup_vtables_ = dedup; }
   1086 
   1087   /// @cond FLATBUFFERS_INTERNAL
   1088   void Pad(size_t num_bytes) { buf_.fill(num_bytes); }
   1089 
   1090   void TrackMinAlign(size_t elem_size) {
   1091     if (elem_size > minalign_) minalign_ = elem_size;
   1092   }
   1093 
   1094   void Align(size_t elem_size) {
   1095     TrackMinAlign(elem_size);
   1096     buf_.fill(PaddingBytes(buf_.size(), elem_size));
   1097   }
   1098 
   1099   void PushFlatBuffer(const uint8_t *bytes, size_t size) {
   1100     PushBytes(bytes, size);
   1101     finished = true;
   1102   }
   1103 
   1104   void PushBytes(const uint8_t *bytes, size_t size) { buf_.push(bytes, size); }
   1105 
   1106   void PopBytes(size_t amount) { buf_.pop(amount); }
   1107 
   1108   template<typename T> void AssertScalarT() {
   1109     // The code assumes power of 2 sizes and endian-swap-ability.
   1110     static_assert(flatbuffers::is_scalar<T>::value, "T must be a scalar type");
   1111   }
   1112 
   1113   // Write a single aligned scalar to the buffer
   1114   template<typename T> uoffset_t PushElement(T element) {
   1115     AssertScalarT<T>();
   1116     T litle_endian_element = EndianScalar(element);
   1117     Align(sizeof(T));
   1118     buf_.push_small(litle_endian_element);
   1119     return GetSize();
   1120   }
   1121 
   1122   template<typename T> uoffset_t PushElement(Offset<T> off) {
   1123     // Special case for offsets: see ReferTo below.
   1124     return PushElement(ReferTo(off.o));
   1125   }
   1126 
   1127   // When writing fields, we track where they are, so we can create correct
   1128   // vtables later.
   1129   void TrackField(voffset_t field, uoffset_t off) {
   1130     FieldLoc fl = { off, field };
   1131     buf_.scratch_push_small(fl);
   1132     num_field_loc++;
   1133     max_voffset_ = (std::max)(max_voffset_, field);
   1134   }
   1135 
   1136   // Like PushElement, but additionally tracks the field this represents.
   1137   template<typename T> void AddElement(voffset_t field, T e, T def) {
   1138     // We don't serialize values equal to the default.
   1139     if (IsTheSameAs(e, def) && !force_defaults_) return;
   1140     auto off = PushElement(e);
   1141     TrackField(field, off);
   1142   }
   1143 
   1144   template<typename T> void AddOffset(voffset_t field, Offset<T> off) {
   1145     if (off.IsNull()) return;  // Don't store.
   1146     AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
   1147   }
   1148 
   1149   template<typename T> void AddStruct(voffset_t field, const T *structptr) {
   1150     if (!structptr) return;  // Default, don't store.
   1151     Align(AlignOf<T>());
   1152     buf_.push_small(*structptr);
   1153     TrackField(field, GetSize());
   1154   }
   1155 
   1156   void AddStructOffset(voffset_t field, uoffset_t off) {
   1157     TrackField(field, off);
   1158   }
   1159 
   1160   // Offsets initially are relative to the end of the buffer (downwards).
   1161   // This function converts them to be relative to the current location
   1162   // in the buffer (when stored here), pointing upwards.
   1163   uoffset_t ReferTo(uoffset_t off) {
   1164     // Align to ensure GetSize() below is correct.
   1165     Align(sizeof(uoffset_t));
   1166     // Offset must refer to something already in buffer.
   1167     FLATBUFFERS_ASSERT(off && off <= GetSize());
   1168     return GetSize() - off + static_cast<uoffset_t>(sizeof(uoffset_t));
   1169   }
   1170 
   1171   void NotNested() {
   1172     // If you hit this, you're trying to construct a Table/Vector/String
   1173     // during the construction of its parent table (between the MyTableBuilder
   1174     // and table.Finish().
   1175     // Move the creation of these sub-objects to above the MyTableBuilder to
   1176     // not get this assert.
   1177     // Ignoring this assert may appear to work in simple cases, but the reason
   1178     // it is here is that storing objects in-line may cause vtable offsets
   1179     // to not fit anymore. It also leads to vtable duplication.
   1180     FLATBUFFERS_ASSERT(!nested);
   1181     // If you hit this, fields were added outside the scope of a table.
   1182     FLATBUFFERS_ASSERT(!num_field_loc);
   1183   }
   1184 
   1185   // From generated code (or from the parser), we call StartTable/EndTable
   1186   // with a sequence of AddElement calls in between.
   1187   uoffset_t StartTable() {
   1188     NotNested();
   1189     nested = true;
   1190     return GetSize();
   1191   }
   1192 
   1193   // This finishes one serialized object by generating the vtable if it's a
   1194   // table, comparing it against existing vtables, and writing the
   1195   // resulting vtable offset.
   1196   uoffset_t EndTable(uoffset_t start) {
   1197     // If you get this assert, a corresponding StartTable wasn't called.
   1198     FLATBUFFERS_ASSERT(nested);
   1199     // Write the vtable offset, which is the start of any Table.
   1200     // We fill it's value later.
   1201     auto vtableoffsetloc = PushElement<soffset_t>(0);
   1202     // Write a vtable, which consists entirely of voffset_t elements.
   1203     // It starts with the number of offsets, followed by a type id, followed
   1204     // by the offsets themselves. In reverse:
   1205     // Include space for the last offset and ensure empty tables have a
   1206     // minimum size.
   1207     max_voffset_ =
   1208         (std::max)(static_cast<voffset_t>(max_voffset_ + sizeof(voffset_t)),
   1209                    FieldIndexToOffset(0));
   1210     buf_.fill_big(max_voffset_);
   1211     auto table_object_size = vtableoffsetloc - start;
   1212     // Vtable use 16bit offsets.
   1213     FLATBUFFERS_ASSERT(table_object_size < 0x10000);
   1214     WriteScalar<voffset_t>(buf_.data() + sizeof(voffset_t),
   1215                            static_cast<voffset_t>(table_object_size));
   1216     WriteScalar<voffset_t>(buf_.data(), max_voffset_);
   1217     // Write the offsets into the table
   1218     for (auto it = buf_.scratch_end() - num_field_loc * sizeof(FieldLoc);
   1219          it < buf_.scratch_end(); it += sizeof(FieldLoc)) {
   1220       auto field_location = reinterpret_cast<FieldLoc *>(it);
   1221       auto pos = static_cast<voffset_t>(vtableoffsetloc - field_location->off);
   1222       // If this asserts, it means you've set a field twice.
   1223       FLATBUFFERS_ASSERT(
   1224           !ReadScalar<voffset_t>(buf_.data() + field_location->id));
   1225       WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
   1226     }
   1227     ClearOffsets();
   1228     auto vt1 = reinterpret_cast<voffset_t *>(buf_.data());
   1229     auto vt1_size = ReadScalar<voffset_t>(vt1);
   1230     auto vt_use = GetSize();
   1231     // See if we already have generated a vtable with this exact same
   1232     // layout before. If so, make it point to the old one, remove this one.
   1233     if (dedup_vtables_) {
   1234       for (auto it = buf_.scratch_data(); it < buf_.scratch_end();
   1235            it += sizeof(uoffset_t)) {
   1236         auto vt_offset_ptr = reinterpret_cast<uoffset_t *>(it);
   1237         auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*vt_offset_ptr));
   1238         auto vt2_size = *vt2;
   1239         if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size)) continue;
   1240         vt_use = *vt_offset_ptr;
   1241         buf_.pop(GetSize() - vtableoffsetloc);
   1242         break;
   1243       }
   1244     }
   1245     // If this is a new vtable, remember it.
   1246     if (vt_use == GetSize()) { buf_.scratch_push_small(vt_use); }
   1247     // Fill the vtable offset we created above.
   1248     // The offset points from the beginning of the object to where the
   1249     // vtable is stored.
   1250     // Offsets default direction is downward in memory for future format
   1251     // flexibility (storing all vtables at the start of the file).
   1252     WriteScalar(buf_.data_at(vtableoffsetloc),
   1253                 static_cast<soffset_t>(vt_use) -
   1254                     static_cast<soffset_t>(vtableoffsetloc));
   1255 
   1256     nested = false;
   1257     return vtableoffsetloc;
   1258   }
   1259 
   1260   FLATBUFFERS_ATTRIBUTE(deprecated("call the version above instead"))
   1261   uoffset_t EndTable(uoffset_t start, voffset_t /*numfields*/) {
   1262     return EndTable(start);
   1263   }
   1264 
   1265   // This checks a required field has been set in a given table that has
   1266   // just been constructed.
   1267   template<typename T> void Required(Offset<T> table, voffset_t field);
   1268 
   1269   uoffset_t StartStruct(size_t alignment) {
   1270     Align(alignment);
   1271     return GetSize();
   1272   }
   1273 
   1274   uoffset_t EndStruct() { return GetSize(); }
   1275 
   1276   void ClearOffsets() {
   1277     buf_.scratch_pop(num_field_loc * sizeof(FieldLoc));
   1278     num_field_loc = 0;
   1279     max_voffset_ = 0;
   1280   }
   1281 
   1282   // Aligns such that when "len" bytes are written, an object can be written
   1283   // after it with "alignment" without padding.
   1284   void PreAlign(size_t len, size_t alignment) {
   1285     TrackMinAlign(alignment);
   1286     buf_.fill(PaddingBytes(GetSize() + len, alignment));
   1287   }
   1288   template<typename T> void PreAlign(size_t len) {
   1289     AssertScalarT<T>();
   1290     PreAlign(len, sizeof(T));
   1291   }
   1292   /// @endcond
   1293 
   1294   /// @brief Store a string in the buffer, which can contain any binary data.
   1295   /// @param[in] str A const char pointer to the data to be stored as a string.
   1296   /// @param[in] len The number of bytes that should be stored from `str`.
   1297   /// @return Returns the offset in the buffer where the string starts.
   1298   Offset<String> CreateString(const char *str, size_t len) {
   1299     NotNested();
   1300     PreAlign<uoffset_t>(len + 1);  // Always 0-terminated.
   1301     buf_.fill(1);
   1302     PushBytes(reinterpret_cast<const uint8_t *>(str), len);
   1303     PushElement(static_cast<uoffset_t>(len));
   1304     return Offset<String>(GetSize());
   1305   }
   1306 
   1307   /// @brief Store a string in the buffer, which is null-terminated.
   1308   /// @param[in] str A const char pointer to a C-string to add to the buffer.
   1309   /// @return Returns the offset in the buffer where the string starts.
   1310   Offset<String> CreateString(const char *str) {
   1311     return CreateString(str, strlen(str));
   1312   }
   1313 
   1314   /// @brief Store a string in the buffer, which is null-terminated.
   1315   /// @param[in] str A char pointer to a C-string to add to the buffer.
   1316   /// @return Returns the offset in the buffer where the string starts.
   1317   Offset<String> CreateString(char *str) {
   1318     return CreateString(str, strlen(str));
   1319   }
   1320 
   1321   /// @brief Store a string in the buffer, which can contain any binary data.
   1322   /// @param[in] str A const reference to a std::string to store in the buffer.
   1323   /// @return Returns the offset in the buffer where the string starts.
   1324   Offset<String> CreateString(const std::string &str) {
   1325     return CreateString(str.c_str(), str.length());
   1326   }
   1327 
   1328   // clang-format off
   1329   #ifdef FLATBUFFERS_HAS_STRING_VIEW
   1330   /// @brief Store a string in the buffer, which can contain any binary data.
   1331   /// @param[in] str A const string_view to copy in to the buffer.
   1332   /// @return Returns the offset in the buffer where the string starts.
   1333   Offset<String> CreateString(flatbuffers::string_view str) {
   1334     return CreateString(str.data(), str.size());
   1335   }
   1336   #endif // FLATBUFFERS_HAS_STRING_VIEW
   1337   // clang-format on
   1338 
   1339   /// @brief Store a string in the buffer, which can contain any binary data.
   1340   /// @param[in] str A const pointer to a `String` struct to add to the buffer.
   1341   /// @return Returns the offset in the buffer where the string starts
   1342   Offset<String> CreateString(const String *str) {
   1343     return str ? CreateString(str->c_str(), str->size()) : 0;
   1344   }
   1345 
   1346   /// @brief Store a string in the buffer, which can contain any binary data.
   1347   /// @param[in] str A const reference to a std::string like type with support
   1348   /// of T::c_str() and T::length() to store in the buffer.
   1349   /// @return Returns the offset in the buffer where the string starts.
   1350   template<typename T> Offset<String> CreateString(const T &str) {
   1351     return CreateString(str.c_str(), str.length());
   1352   }
   1353 
   1354   /// @brief Store a string in the buffer, which can contain any binary data.
   1355   /// If a string with this exact contents has already been serialized before,
   1356   /// instead simply returns the offset of the existing string.
   1357   /// @param[in] str A const char pointer to the data to be stored as a string.
   1358   /// @param[in] len The number of bytes that should be stored from `str`.
   1359   /// @return Returns the offset in the buffer where the string starts.
   1360   Offset<String> CreateSharedString(const char *str, size_t len) {
   1361     if (!string_pool)
   1362       string_pool = new StringOffsetMap(StringOffsetCompare(buf_));
   1363     auto size_before_string = buf_.size();
   1364     // Must first serialize the string, since the set is all offsets into
   1365     // buffer.
   1366     auto off = CreateString(str, len);
   1367     auto it = string_pool->find(off);
   1368     // If it exists we reuse existing serialized data!
   1369     if (it != string_pool->end()) {
   1370       // We can remove the string we serialized.
   1371       buf_.pop(buf_.size() - size_before_string);
   1372       return *it;
   1373     }
   1374     // Record this string for future use.
   1375     string_pool->insert(off);
   1376     return off;
   1377   }
   1378 
   1379   /// @brief Store a string in the buffer, which null-terminated.
   1380   /// If a string with this exact contents has already been serialized before,
   1381   /// instead simply returns the offset of the existing string.
   1382   /// @param[in] str A const char pointer to a C-string to add to the buffer.
   1383   /// @return Returns the offset in the buffer where the string starts.
   1384   Offset<String> CreateSharedString(const char *str) {
   1385     return CreateSharedString(str, strlen(str));
   1386   }
   1387 
   1388   /// @brief Store a string in the buffer, which can contain any binary data.
   1389   /// If a string with this exact contents has already been serialized before,
   1390   /// instead simply returns the offset of the existing string.
   1391   /// @param[in] str A const reference to a std::string to store in the buffer.
   1392   /// @return Returns the offset in the buffer where the string starts.
   1393   Offset<String> CreateSharedString(const std::string &str) {
   1394     return CreateSharedString(str.c_str(), str.length());
   1395   }
   1396 
   1397   /// @brief Store a string in the buffer, which can contain any binary data.
   1398   /// If a string with this exact contents has already been serialized before,
   1399   /// instead simply returns the offset of the existing string.
   1400   /// @param[in] str A const pointer to a `String` struct to add to the buffer.
   1401   /// @return Returns the offset in the buffer where the string starts
   1402   Offset<String> CreateSharedString(const String *str) {
   1403     return CreateSharedString(str->c_str(), str->size());
   1404   }
   1405 
   1406   /// @cond FLATBUFFERS_INTERNAL
   1407   uoffset_t EndVector(size_t len) {
   1408     FLATBUFFERS_ASSERT(nested);  // Hit if no corresponding StartVector.
   1409     nested = false;
   1410     return PushElement(static_cast<uoffset_t>(len));
   1411   }
   1412 
   1413   void StartVector(size_t len, size_t elemsize) {
   1414     NotNested();
   1415     nested = true;
   1416     PreAlign<uoffset_t>(len * elemsize);
   1417     PreAlign(len * elemsize, elemsize);  // Just in case elemsize > uoffset_t.
   1418   }
   1419 
   1420   // Call this right before StartVector/CreateVector if you want to force the
   1421   // alignment to be something different than what the element size would
   1422   // normally dictate.
   1423   // This is useful when storing a nested_flatbuffer in a vector of bytes,
   1424   // or when storing SIMD floats, etc.
   1425   void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment) {
   1426     PreAlign(len * elemsize, alignment);
   1427   }
   1428 
   1429   // Similar to ForceVectorAlignment but for String fields.
   1430   void ForceStringAlignment(size_t len, size_t alignment) {
   1431     PreAlign((len + 1) * sizeof(char), alignment);
   1432   }
   1433 
   1434   /// @endcond
   1435 
   1436   /// @brief Serialize an array into a FlatBuffer `vector`.
   1437   /// @tparam T The data type of the array elements.
   1438   /// @param[in] v A pointer to the array of type `T` to serialize into the
   1439   /// buffer as a `vector`.
   1440   /// @param[in] len The number of elements to serialize.
   1441   /// @return Returns a typed `Offset` into the serialized data indicating
   1442   /// where the vector is stored.
   1443   template<typename T> Offset<Vector<T>> CreateVector(const T *v, size_t len) {
   1444     // If this assert hits, you're specifying a template argument that is
   1445     // causing the wrong overload to be selected, remove it.
   1446     AssertScalarT<T>();
   1447     StartVector(len, sizeof(T));
   1448     // clang-format off
   1449     #if FLATBUFFERS_LITTLEENDIAN
   1450       PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T));
   1451     #else
   1452       if (sizeof(T) == 1) {
   1453         PushBytes(reinterpret_cast<const uint8_t *>(v), len);
   1454       } else {
   1455         for (auto i = len; i > 0; ) {
   1456           PushElement(v[--i]);
   1457         }
   1458       }
   1459     #endif
   1460     // clang-format on
   1461     return Offset<Vector<T>>(EndVector(len));
   1462   }
   1463 
   1464   template<typename T>
   1465   Offset<Vector<Offset<T>>> CreateVector(const Offset<T> *v, size_t len) {
   1466     StartVector(len, sizeof(Offset<T>));
   1467     for (auto i = len; i > 0;) { PushElement(v[--i]); }
   1468     return Offset<Vector<Offset<T>>>(EndVector(len));
   1469   }
   1470 
   1471   /// @brief Serialize a `std::vector` into a FlatBuffer `vector`.
   1472   /// @tparam T The data type of the `std::vector` elements.
   1473   /// @param v A const reference to the `std::vector` to serialize into the
   1474   /// buffer as a `vector`.
   1475   /// @return Returns a typed `Offset` into the serialized data indicating
   1476   /// where the vector is stored.
   1477   template<typename T> Offset<Vector<T>> CreateVector(const std::vector<T> &v) {
   1478     return CreateVector(data(v), v.size());
   1479   }
   1480 
   1481   // vector<bool> may be implemented using a bit-set, so we can't access it as
   1482   // an array. Instead, read elements manually.
   1483   // Background: https://isocpp.org/blog/2012/11/on-vectorbool
   1484   Offset<Vector<uint8_t>> CreateVector(const std::vector<bool> &v) {
   1485     StartVector(v.size(), sizeof(uint8_t));
   1486     for (auto i = v.size(); i > 0;) {
   1487       PushElement(static_cast<uint8_t>(v[--i]));
   1488     }
   1489     return Offset<Vector<uint8_t>>(EndVector(v.size()));
   1490   }
   1491 
   1492   // clang-format off
   1493   #ifndef FLATBUFFERS_CPP98_STL
   1494   /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
   1495   /// This is a convenience function that takes care of iteration for you.
   1496   /// @tparam T The data type of the `std::vector` elements.
   1497   /// @param f A function that takes the current iteration 0..vector_size-1 and
   1498   /// returns any type that you can construct a FlatBuffers vector out of.
   1499   /// @return Returns a typed `Offset` into the serialized data indicating
   1500   /// where the vector is stored.
   1501   template<typename T> Offset<Vector<T>> CreateVector(size_t vector_size,
   1502       const std::function<T (size_t i)> &f) {
   1503     std::vector<T> elems(vector_size);
   1504     for (size_t i = 0; i < vector_size; i++) elems[i] = f(i);
   1505     return CreateVector(elems);
   1506   }
   1507   #endif
   1508   // clang-format on
   1509 
   1510   /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
   1511   /// This is a convenience function that takes care of iteration for you.
   1512   /// @tparam T The data type of the `std::vector` elements.
   1513   /// @param f A function that takes the current iteration 0..vector_size-1,
   1514   /// and the state parameter returning any type that you can construct a
   1515   /// FlatBuffers vector out of.
   1516   /// @param state State passed to f.
   1517   /// @return Returns a typed `Offset` into the serialized data indicating
   1518   /// where the vector is stored.
   1519   template<typename T, typename F, typename S>
   1520   Offset<Vector<T>> CreateVector(size_t vector_size, F f, S *state) {
   1521     std::vector<T> elems(vector_size);
   1522     for (size_t i = 0; i < vector_size; i++) elems[i] = f(i, state);
   1523     return CreateVector(elems);
   1524   }
   1525 
   1526   /// @brief Serialize a `std::vector<std::string>` into a FlatBuffer `vector`.
   1527   /// This is a convenience function for a common case.
   1528   /// @param v A const reference to the `std::vector` to serialize into the
   1529   /// buffer as a `vector`.
   1530   /// @return Returns a typed `Offset` into the serialized data indicating
   1531   /// where the vector is stored.
   1532   Offset<Vector<Offset<String>>> CreateVectorOfStrings(
   1533       const std::vector<std::string> &v) {
   1534     std::vector<Offset<String>> offsets(v.size());
   1535     for (size_t i = 0; i < v.size(); i++) offsets[i] = CreateString(v[i]);
   1536     return CreateVector(offsets);
   1537   }
   1538 
   1539   /// @brief Serialize an array of structs into a FlatBuffer `vector`.
   1540   /// @tparam T The data type of the struct array elements.
   1541   /// @param[in] v A pointer to the array of type `T` to serialize into the
   1542   /// buffer as a `vector`.
   1543   /// @param[in] len The number of elements to serialize.
   1544   /// @return Returns a typed `Offset` into the serialized data indicating
   1545   /// where the vector is stored.
   1546   template<typename T>
   1547   Offset<Vector<const T *>> CreateVectorOfStructs(const T *v, size_t len) {
   1548     StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>());
   1549     PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
   1550     return Offset<Vector<const T *>>(EndVector(len));
   1551   }
   1552 
   1553   /// @brief Serialize an array of native structs into a FlatBuffer `vector`.
   1554   /// @tparam T The data type of the struct array elements.
   1555   /// @tparam S The data type of the native struct array elements.
   1556   /// @param[in] v A pointer to the array of type `S` to serialize into the
   1557   /// buffer as a `vector`.
   1558   /// @param[in] len The number of elements to serialize.
   1559   /// @return Returns a typed `Offset` into the serialized data indicating
   1560   /// where the vector is stored.
   1561   template<typename T, typename S>
   1562   Offset<Vector<const T *>> CreateVectorOfNativeStructs(const S *v,
   1563                                                         size_t len) {
   1564     extern T Pack(const S &);
   1565     typedef T (*Pack_t)(const S &);
   1566     std::vector<T> vv(len);
   1567     std::transform(v, v + len, vv.begin(), static_cast<Pack_t&>(Pack));
   1568     return CreateVectorOfStructs<T>(vv.data(), vv.size());
   1569   }
   1570 
   1571   // clang-format off
   1572   #ifndef FLATBUFFERS_CPP98_STL
   1573   /// @brief Serialize an array of structs into a FlatBuffer `vector`.
   1574   /// @tparam T The data type of the struct array elements.
   1575   /// @param[in] f A function that takes the current iteration 0..vector_size-1
   1576   /// and a pointer to the struct that must be filled.
   1577   /// @return Returns a typed `Offset` into the serialized data indicating
   1578   /// where the vector is stored.
   1579   /// This is mostly useful when flatbuffers are generated with mutation
   1580   /// accessors.
   1581   template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
   1582       size_t vector_size, const std::function<void(size_t i, T *)> &filler) {
   1583     T* structs = StartVectorOfStructs<T>(vector_size);
   1584     for (size_t i = 0; i < vector_size; i++) {
   1585       filler(i, structs);
   1586       structs++;
   1587     }
   1588     return EndVectorOfStructs<T>(vector_size);
   1589   }
   1590   #endif
   1591   // clang-format on
   1592 
   1593   /// @brief Serialize an array of structs into a FlatBuffer `vector`.
   1594   /// @tparam T The data type of the struct array elements.
   1595   /// @param[in] f A function that takes the current iteration 0..vector_size-1,
   1596   /// a pointer to the struct that must be filled and the state argument.
   1597   /// @param[in] state Arbitrary state to pass to f.
   1598   /// @return Returns a typed `Offset` into the serialized data indicating
   1599   /// where the vector is stored.
   1600   /// This is mostly useful when flatbuffers are generated with mutation
   1601   /// accessors.
   1602   template<typename T, typename F, typename S>
   1603   Offset<Vector<const T *>> CreateVectorOfStructs(size_t vector_size, F f,
   1604                                                   S *state) {
   1605     T *structs = StartVectorOfStructs<T>(vector_size);
   1606     for (size_t i = 0; i < vector_size; i++) {
   1607       f(i, structs, state);
   1608       structs++;
   1609     }
   1610     return EndVectorOfStructs<T>(vector_size);
   1611   }
   1612 
   1613   /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`.
   1614   /// @tparam T The data type of the `std::vector` struct elements.
   1615   /// @param[in]] v A const reference to the `std::vector` of structs to
   1616   /// serialize into the buffer as a `vector`.
   1617   /// @return Returns a typed `Offset` into the serialized data indicating
   1618   /// where the vector is stored.
   1619   template<typename T, typename Alloc>
   1620   Offset<Vector<const T *>> CreateVectorOfStructs(
   1621       const std::vector<T, Alloc> &v) {
   1622     return CreateVectorOfStructs(data(v), v.size());
   1623   }
   1624 
   1625   /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
   1626   /// `vector`.
   1627   /// @tparam T The data type of the `std::vector` struct elements.
   1628   /// @tparam S The data type of the `std::vector` native struct elements.
   1629   /// @param[in]] v A const reference to the `std::vector` of structs to
   1630   /// serialize into the buffer as a `vector`.
   1631   /// @return Returns a typed `Offset` into the serialized data indicating
   1632   /// where the vector is stored.
   1633   template<typename T, typename S>
   1634   Offset<Vector<const T *>> CreateVectorOfNativeStructs(
   1635       const std::vector<S> &v) {
   1636     return CreateVectorOfNativeStructs<T, S>(data(v), v.size());
   1637   }
   1638 
   1639   /// @cond FLATBUFFERS_INTERNAL
   1640   template<typename T> struct StructKeyComparator {
   1641     bool operator()(const T &a, const T &b) const {
   1642       return a.KeyCompareLessThan(&b);
   1643     }
   1644 
   1645    private:
   1646     StructKeyComparator &operator=(const StructKeyComparator &);
   1647   };
   1648   /// @endcond
   1649 
   1650   /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`
   1651   /// in sorted order.
   1652   /// @tparam T The data type of the `std::vector` struct elements.
   1653   /// @param[in]] v A const reference to the `std::vector` of structs to
   1654   /// serialize into the buffer as a `vector`.
   1655   /// @return Returns a typed `Offset` into the serialized data indicating
   1656   /// where the vector is stored.
   1657   template<typename T>
   1658   Offset<Vector<const T *>> CreateVectorOfSortedStructs(std::vector<T> *v) {
   1659     return CreateVectorOfSortedStructs(data(*v), v->size());
   1660   }
   1661 
   1662   /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
   1663   /// `vector` in sorted order.
   1664   /// @tparam T The data type of the `std::vector` struct elements.
   1665   /// @tparam S The data type of the `std::vector` native struct elements.
   1666   /// @param[in]] v A const reference to the `std::vector` of structs to
   1667   /// serialize into the buffer as a `vector`.
   1668   /// @return Returns a typed `Offset` into the serialized data indicating
   1669   /// where the vector is stored.
   1670   template<typename T, typename S>
   1671   Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(
   1672       std::vector<S> *v) {
   1673     return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size());
   1674   }
   1675 
   1676   /// @brief Serialize an array of structs into a FlatBuffer `vector` in sorted
   1677   /// order.
   1678   /// @tparam T The data type of the struct array elements.
   1679   /// @param[in] v A pointer to the array of type `T` to serialize into the
   1680   /// buffer as a `vector`.
   1681   /// @param[in] len The number of elements to serialize.
   1682   /// @return Returns a typed `Offset` into the serialized data indicating
   1683   /// where the vector is stored.
   1684   template<typename T>
   1685   Offset<Vector<const T *>> CreateVectorOfSortedStructs(T *v, size_t len) {
   1686     std::sort(v, v + len, StructKeyComparator<T>());
   1687     return CreateVectorOfStructs(v, len);
   1688   }
   1689 
   1690   /// @brief Serialize an array of native structs into a FlatBuffer `vector` in
   1691   /// sorted order.
   1692   /// @tparam T The data type of the struct array elements.
   1693   /// @tparam S The data type of the native struct array elements.
   1694   /// @param[in] v A pointer to the array of type `S` to serialize into the
   1695   /// buffer as a `vector`.
   1696   /// @param[in] len The number of elements to serialize.
   1697   /// @return Returns a typed `Offset` into the serialized data indicating
   1698   /// where the vector is stored.
   1699   template<typename T, typename S>
   1700   Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(S *v,
   1701                                                               size_t len) {
   1702     extern T Pack(const S &);
   1703     typedef T (*Pack_t)(const S &);
   1704     std::vector<T> vv(len);
   1705     std::transform(v, v + len, vv.begin(), static_cast<Pack_t&>(Pack));
   1706     return CreateVectorOfSortedStructs<T>(vv, len);
   1707   }
   1708 
   1709   /// @cond FLATBUFFERS_INTERNAL
   1710   template<typename T> struct TableKeyComparator {
   1711     TableKeyComparator(vector_downward &buf) : buf_(buf) {}
   1712     bool operator()(const Offset<T> &a, const Offset<T> &b) const {
   1713       auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o));
   1714       auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o));
   1715       return table_a->KeyCompareLessThan(table_b);
   1716     }
   1717     vector_downward &buf_;
   1718 
   1719    private:
   1720     TableKeyComparator &operator=(const TableKeyComparator &);
   1721   };
   1722   /// @endcond
   1723 
   1724   /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
   1725   /// in sorted order.
   1726   /// @tparam T The data type that the offset refers to.
   1727   /// @param[in] v An array of type `Offset<T>` that contains the `table`
   1728   /// offsets to store in the buffer in sorted order.
   1729   /// @param[in] len The number of elements to store in the `vector`.
   1730   /// @return Returns a typed `Offset` into the serialized data indicating
   1731   /// where the vector is stored.
   1732   template<typename T>
   1733   Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(Offset<T> *v,
   1734                                                        size_t len) {
   1735     std::sort(v, v + len, TableKeyComparator<T>(buf_));
   1736     return CreateVector(v, len);
   1737   }
   1738 
   1739   /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
   1740   /// in sorted order.
   1741   /// @tparam T The data type that the offset refers to.
   1742   /// @param[in] v An array of type `Offset<T>` that contains the `table`
   1743   /// offsets to store in the buffer in sorted order.
   1744   /// @return Returns a typed `Offset` into the serialized data indicating
   1745   /// where the vector is stored.
   1746   template<typename T>
   1747   Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
   1748       std::vector<Offset<T>> *v) {
   1749     return CreateVectorOfSortedTables(data(*v), v->size());
   1750   }
   1751 
   1752   /// @brief Specialized version of `CreateVector` for non-copying use cases.
   1753   /// Write the data any time later to the returned buffer pointer `buf`.
   1754   /// @param[in] len The number of elements to store in the `vector`.
   1755   /// @param[in] elemsize The size of each element in the `vector`.
   1756   /// @param[out] buf A pointer to a `uint8_t` pointer that can be
   1757   /// written to at a later time to serialize the data into a `vector`
   1758   /// in the buffer.
   1759   uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
   1760                                       uint8_t **buf) {
   1761     NotNested();
   1762     StartVector(len, elemsize);
   1763     buf_.make_space(len * elemsize);
   1764     auto vec_start = GetSize();
   1765     auto vec_end = EndVector(len);
   1766     *buf = buf_.data_at(vec_start);
   1767     return vec_end;
   1768   }
   1769 
   1770   /// @brief Specialized version of `CreateVector` for non-copying use cases.
   1771   /// Write the data any time later to the returned buffer pointer `buf`.
   1772   /// @tparam T The data type of the data that will be stored in the buffer
   1773   /// as a `vector`.
   1774   /// @param[in] len The number of elements to store in the `vector`.
   1775   /// @param[out] buf A pointer to a pointer of type `T` that can be
   1776   /// written to at a later time to serialize the data into a `vector`
   1777   /// in the buffer.
   1778   template<typename T>
   1779   Offset<Vector<T>> CreateUninitializedVector(size_t len, T **buf) {
   1780     AssertScalarT<T>();
   1781     return CreateUninitializedVector(len, sizeof(T),
   1782                                      reinterpret_cast<uint8_t **>(buf));
   1783   }
   1784 
   1785   template<typename T>
   1786   Offset<Vector<const T*>> CreateUninitializedVectorOfStructs(size_t len, T **buf) {
   1787     return CreateUninitializedVector(len, sizeof(T),
   1788                                      reinterpret_cast<uint8_t **>(buf));
   1789   }
   1790 
   1791 
   1792   // @brief Create a vector of scalar type T given as input a vector of scalar
   1793   // type U, useful with e.g. pre "enum class" enums, or any existing scalar
   1794   // data of the wrong type.
   1795   template<typename T, typename U>
   1796   Offset<Vector<T>> CreateVectorScalarCast(const U *v, size_t len) {
   1797     AssertScalarT<T>();
   1798     AssertScalarT<U>();
   1799     StartVector(len, sizeof(T));
   1800     for (auto i = len; i > 0;) { PushElement(static_cast<T>(v[--i])); }
   1801     return Offset<Vector<T>>(EndVector(len));
   1802   }
   1803 
   1804   /// @brief Write a struct by itself, typically to be part of a union.
   1805   template<typename T> Offset<const T *> CreateStruct(const T &structobj) {
   1806     NotNested();
   1807     Align(AlignOf<T>());
   1808     buf_.push_small(structobj);
   1809     return Offset<const T *>(GetSize());
   1810   }
   1811 
   1812   /// @brief The length of a FlatBuffer file header.
   1813   static const size_t kFileIdentifierLength = 4;
   1814 
   1815   /// @brief Finish serializing a buffer by writing the root offset.
   1816   /// @param[in] file_identifier If a `file_identifier` is given, the buffer
   1817   /// will be prefixed with a standard FlatBuffers file header.
   1818   template<typename T>
   1819   void Finish(Offset<T> root, const char *file_identifier = nullptr) {
   1820     Finish(root.o, file_identifier, false);
   1821   }
   1822 
   1823   /// @brief Finish a buffer with a 32 bit size field pre-fixed (size of the
   1824   /// buffer following the size field). These buffers are NOT compatible
   1825   /// with standard buffers created by Finish, i.e. you can't call GetRoot
   1826   /// on them, you have to use GetSizePrefixedRoot instead.
   1827   /// All >32 bit quantities in this buffer will be aligned when the whole
   1828   /// size pre-fixed buffer is aligned.
   1829   /// These kinds of buffers are useful for creating a stream of FlatBuffers.
   1830   template<typename T>
   1831   void FinishSizePrefixed(Offset<T> root,
   1832                           const char *file_identifier = nullptr) {
   1833     Finish(root.o, file_identifier, true);
   1834   }
   1835 
   1836   void SwapBufAllocator(FlatBufferBuilder &other) {
   1837     buf_.swap_allocator(other.buf_);
   1838   }
   1839 
   1840 protected:
   1841 
   1842   // You shouldn't really be copying instances of this class.
   1843   FlatBufferBuilder(const FlatBufferBuilder &);
   1844   FlatBufferBuilder &operator=(const FlatBufferBuilder &);
   1845 
   1846   void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) {
   1847     NotNested();
   1848     buf_.clear_scratch();
   1849     // This will cause the whole buffer to be aligned.
   1850     PreAlign((size_prefix ? sizeof(uoffset_t) : 0) + sizeof(uoffset_t) +
   1851                  (file_identifier ? kFileIdentifierLength : 0),
   1852              minalign_);
   1853     if (file_identifier) {
   1854       FLATBUFFERS_ASSERT(strlen(file_identifier) == kFileIdentifierLength);
   1855       PushBytes(reinterpret_cast<const uint8_t *>(file_identifier),
   1856                 kFileIdentifierLength);
   1857     }
   1858     PushElement(ReferTo(root));  // Location of root.
   1859     if (size_prefix) { PushElement(GetSize()); }
   1860     finished = true;
   1861   }
   1862 
   1863   struct FieldLoc {
   1864     uoffset_t off;
   1865     voffset_t id;
   1866   };
   1867 
   1868   vector_downward buf_;
   1869 
   1870   // Accumulating offsets of table members while it is being built.
   1871   // We store these in the scratch pad of buf_, after the vtable offsets.
   1872   uoffset_t num_field_loc;
   1873   // Track how much of the vtable is in use, so we can output the most compact
   1874   // possible vtable.
   1875   voffset_t max_voffset_;
   1876 
   1877   // Ensure objects are not nested.
   1878   bool nested;
   1879 
   1880   // Ensure the buffer is finished before it is being accessed.
   1881   bool finished;
   1882 
   1883   size_t minalign_;
   1884 
   1885   bool force_defaults_;  // Serialize values equal to their defaults anyway.
   1886 
   1887   bool dedup_vtables_;
   1888 
   1889   struct StringOffsetCompare {
   1890     StringOffsetCompare(const vector_downward &buf) : buf_(&buf) {}
   1891     bool operator()(const Offset<String> &a, const Offset<String> &b) const {
   1892       auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o));
   1893       auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o));
   1894       return StringLessThan(stra->data(), stra->size(),
   1895                             strb->data(), strb->size());
   1896     }
   1897     const vector_downward *buf_;
   1898   };
   1899 
   1900   // For use with CreateSharedString. Instantiated on first use only.
   1901   typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
   1902   StringOffsetMap *string_pool;
   1903 
   1904  private:
   1905   // Allocates space for a vector of structures.
   1906   // Must be completed with EndVectorOfStructs().
   1907   template<typename T> T *StartVectorOfStructs(size_t vector_size) {
   1908     StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>());
   1909     return reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T)));
   1910   }
   1911 
   1912   // End the vector of structues in the flatbuffers.
   1913   // Vector should have previously be started with StartVectorOfStructs().
   1914   template<typename T>
   1915   Offset<Vector<const T *>> EndVectorOfStructs(size_t vector_size) {
   1916     return Offset<Vector<const T *>>(EndVector(vector_size));
   1917   }
   1918 };
   1919 /// @}
   1920 
   1921 /// @cond FLATBUFFERS_INTERNAL
   1922 // Helpers to get a typed pointer to the root object contained in the buffer.
   1923 template<typename T> T *GetMutableRoot(void *buf) {
   1924   EndianCheck();
   1925   return reinterpret_cast<T *>(
   1926       reinterpret_cast<uint8_t *>(buf) +
   1927       EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
   1928 }
   1929 
   1930 template<typename T> const T *GetRoot(const void *buf) {
   1931   return GetMutableRoot<T>(const_cast<void *>(buf));
   1932 }
   1933 
   1934 template<typename T> const T *GetSizePrefixedRoot(const void *buf) {
   1935   return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(uoffset_t));
   1936 }
   1937 
   1938 /// Helpers to get a typed pointer to objects that are currently being built.
   1939 /// @warning Creating new objects will lead to reallocations and invalidates
   1940 /// the pointer!
   1941 template<typename T>
   1942 T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
   1943   return reinterpret_cast<T *>(fbb.GetCurrentBufferPointer() + fbb.GetSize() -
   1944                                offset.o);
   1945 }
   1946 
   1947 template<typename T>
   1948 const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
   1949   return GetMutableTemporaryPointer<T>(fbb, offset);
   1950 }
   1951 
   1952 /// @brief Get a pointer to the the file_identifier section of the buffer.
   1953 /// @return Returns a const char pointer to the start of the file_identifier
   1954 /// characters in the buffer.  The returned char * has length
   1955 /// 'flatbuffers::FlatBufferBuilder::kFileIdentifierLength'.
   1956 /// This function is UNDEFINED for FlatBuffers whose schema does not include
   1957 /// a file_identifier (likely points at padding or the start of a the root
   1958 /// vtable).
   1959 inline const char *GetBufferIdentifier(const void *buf, bool size_prefixed = false) {
   1960   return reinterpret_cast<const char *>(buf) +
   1961          ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t));
   1962 }
   1963 
   1964 // Helper to see if the identifier in a buffer has the expected value.
   1965 inline bool BufferHasIdentifier(const void *buf, const char *identifier, bool size_prefixed = false) {
   1966   return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier,
   1967                  FlatBufferBuilder::kFileIdentifierLength) == 0;
   1968 }
   1969 
   1970 // Helper class to verify the integrity of a FlatBuffer
   1971 class Verifier FLATBUFFERS_FINAL_CLASS {
   1972  public:
   1973   Verifier(const uint8_t *buf, size_t buf_len, uoffset_t _max_depth = 64,
   1974            uoffset_t _max_tables = 1000000, bool _check_alignment = true)
   1975       : buf_(buf),
   1976         size_(buf_len),
   1977         depth_(0),
   1978         max_depth_(_max_depth),
   1979         num_tables_(0),
   1980         max_tables_(_max_tables),
   1981         upper_bound_(0),
   1982         check_alignment_(_check_alignment)
   1983   {
   1984     FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
   1985   }
   1986 
   1987   // Central location where any verification failures register.
   1988   bool Check(bool ok) const {
   1989     // clang-format off
   1990     #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
   1991       FLATBUFFERS_ASSERT(ok);
   1992     #endif
   1993     #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
   1994       if (!ok)
   1995         upper_bound_ = 0;
   1996     #endif
   1997     // clang-format on
   1998     return ok;
   1999   }
   2000 
   2001   // Verify any range within the buffer.
   2002   bool Verify(size_t elem, size_t elem_len) const {
   2003     // clang-format off
   2004     #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
   2005       auto upper_bound = elem + elem_len;
   2006       if (upper_bound_ < upper_bound)
   2007         upper_bound_ =  upper_bound;
   2008     #endif
   2009     // clang-format on
   2010     return Check(elem_len < size_ && elem <= size_ - elem_len);
   2011   }
   2012 
   2013   template<typename T> bool VerifyAlignment(size_t elem) const {
   2014     return (elem & (sizeof(T) - 1)) == 0 || !check_alignment_;
   2015   }
   2016 
   2017   // Verify a range indicated by sizeof(T).
   2018   template<typename T> bool Verify(size_t elem) const {
   2019     return VerifyAlignment<T>(elem) && Verify(elem, sizeof(T));
   2020   }
   2021 
   2022   // Verify relative to a known-good base pointer.
   2023   bool Verify(const uint8_t *base, voffset_t elem_off, size_t elem_len) const {
   2024     return Verify(static_cast<size_t>(base - buf_) + elem_off, elem_len);
   2025   }
   2026 
   2027   template<typename T> bool Verify(const uint8_t *base, voffset_t elem_off)
   2028       const {
   2029     return Verify(static_cast<size_t>(base - buf_) + elem_off, sizeof(T));
   2030   }
   2031 
   2032   // Verify a pointer (may be NULL) of a table type.
   2033   template<typename T> bool VerifyTable(const T *table) {
   2034     return !table || table->Verify(*this);
   2035   }
   2036 
   2037   // Verify a pointer (may be NULL) of any vector type.
   2038   template<typename T> bool VerifyVector(const Vector<T> *vec) const {
   2039     return !vec || VerifyVectorOrString(reinterpret_cast<const uint8_t *>(vec),
   2040                                         sizeof(T));
   2041   }
   2042 
   2043   // Verify a pointer (may be NULL) of a vector to struct.
   2044   template<typename T> bool VerifyVector(const Vector<const T *> *vec) const {
   2045     return VerifyVector(reinterpret_cast<const Vector<T> *>(vec));
   2046   }
   2047 
   2048   // Verify a pointer (may be NULL) to string.
   2049   bool VerifyString(const String *str) const {
   2050     size_t end;
   2051     return !str ||
   2052            (VerifyVectorOrString(reinterpret_cast<const uint8_t *>(str),
   2053                                  1, &end) &&
   2054             Verify(end, 1) &&      // Must have terminator
   2055             Check(buf_[end] == '\0'));  // Terminating byte must be 0.
   2056   }
   2057 
   2058   // Common code between vectors and strings.
   2059   bool VerifyVectorOrString(const uint8_t *vec, size_t elem_size,
   2060                     size_t *end = nullptr) const {
   2061     auto veco = static_cast<size_t>(vec - buf_);
   2062     // Check we can read the size field.
   2063     if (!Verify<uoffset_t>(veco)) return false;
   2064     // Check the whole array. If this is a string, the byte past the array
   2065     // must be 0.
   2066     auto size = ReadScalar<uoffset_t>(vec);
   2067     auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
   2068     if (!Check(size < max_elems))
   2069       return false;  // Protect against byte_size overflowing.
   2070     auto byte_size = sizeof(size) + elem_size * size;
   2071     if (end) *end = veco + byte_size;
   2072     return Verify(veco, byte_size);
   2073   }
   2074 
   2075   // Special case for string contents, after the above has been called.
   2076   bool VerifyVectorOfStrings(const Vector<Offset<String>> *vec) const {
   2077     if (vec) {
   2078       for (uoffset_t i = 0; i < vec->size(); i++) {
   2079         if (!VerifyString(vec->Get(i))) return false;
   2080       }
   2081     }
   2082     return true;
   2083   }
   2084 
   2085   // Special case for table contents, after the above has been called.
   2086   template<typename T> bool VerifyVectorOfTables(const Vector<Offset<T>> *vec) {
   2087     if (vec) {
   2088       for (uoffset_t i = 0; i < vec->size(); i++) {
   2089         if (!vec->Get(i)->Verify(*this)) return false;
   2090       }
   2091     }
   2092     return true;
   2093   }
   2094 
   2095   bool VerifyTableStart(const uint8_t *table) {
   2096     // Check the vtable offset.
   2097     auto tableo = static_cast<size_t>(table - buf_);
   2098     if (!Verify<soffset_t>(tableo)) return false;
   2099     // This offset may be signed, but doing the substraction unsigned always
   2100     // gives the result we want.
   2101     auto vtableo = tableo - static_cast<size_t>(ReadScalar<soffset_t>(table));
   2102     // Check the vtable size field, then check vtable fits in its entirety.
   2103     return VerifyComplexity() && Verify<voffset_t>(vtableo) &&
   2104            VerifyAlignment<voffset_t>(ReadScalar<voffset_t>(buf_ + vtableo)) &&
   2105            Verify(vtableo, ReadScalar<voffset_t>(buf_ + vtableo));
   2106   }
   2107 
   2108   template<typename T>
   2109   bool VerifyBufferFromStart(const char *identifier, size_t start) {
   2110     if (identifier &&
   2111         (size_ < 2 * sizeof(flatbuffers::uoffset_t) ||
   2112          !BufferHasIdentifier(buf_ + start, identifier))) {
   2113       return false;
   2114     }
   2115 
   2116     // Call T::Verify, which must be in the generated code for this type.
   2117     auto o = VerifyOffset(start);
   2118     return o && reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this)
   2119     // clang-format off
   2120     #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
   2121            && GetComputedSize()
   2122     #endif
   2123         ;
   2124     // clang-format on
   2125   }
   2126 
   2127   // Verify this whole buffer, starting with root type T.
   2128   template<typename T> bool VerifyBuffer() { return VerifyBuffer<T>(nullptr); }
   2129 
   2130   template<typename T> bool VerifyBuffer(const char *identifier) {
   2131     return VerifyBufferFromStart<T>(identifier, 0);
   2132   }
   2133 
   2134   template<typename T> bool VerifySizePrefixedBuffer(const char *identifier) {
   2135     return Verify<uoffset_t>(0U) &&
   2136            ReadScalar<uoffset_t>(buf_) == size_ - sizeof(uoffset_t) &&
   2137            VerifyBufferFromStart<T>(identifier, sizeof(uoffset_t));
   2138   }
   2139 
   2140   uoffset_t VerifyOffset(size_t start) const {
   2141     if (!Verify<uoffset_t>(start)) return 0;
   2142     auto o = ReadScalar<uoffset_t>(buf_ + start);
   2143     // May not point to itself.
   2144     if (!Check(o != 0)) return 0;
   2145     // Can't wrap around / buffers are max 2GB.
   2146     if (!Check(static_cast<soffset_t>(o) >= 0)) return 0;
   2147     // Must be inside the buffer to create a pointer from it (pointer outside
   2148     // buffer is UB).
   2149     if (!Verify(start + o, 1)) return 0;
   2150     return o;
   2151   }
   2152 
   2153   uoffset_t VerifyOffset(const uint8_t *base, voffset_t start) const {
   2154     return VerifyOffset(static_cast<size_t>(base - buf_) + start);
   2155   }
   2156 
   2157   // Called at the start of a table to increase counters measuring data
   2158   // structure depth and amount, and possibly bails out with false if
   2159   // limits set by the constructor have been hit. Needs to be balanced
   2160   // with EndTable().
   2161   bool VerifyComplexity() {
   2162     depth_++;
   2163     num_tables_++;
   2164     return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_);
   2165   }
   2166 
   2167   // Called at the end of a table to pop the depth count.
   2168   bool EndTable() {
   2169     depth_--;
   2170     return true;
   2171   }
   2172 
   2173   // Returns the message size in bytes
   2174   size_t GetComputedSize() const {
   2175     // clang-format off
   2176     #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
   2177       uintptr_t size = upper_bound_;
   2178       // Align the size to uoffset_t
   2179       size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
   2180       return (size > size_) ?  0 : size;
   2181     #else
   2182       // Must turn on FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE for this to work.
   2183       (void)upper_bound_;
   2184       FLATBUFFERS_ASSERT(false);
   2185       return 0;
   2186     #endif
   2187     // clang-format on
   2188   }
   2189 
   2190  private:
   2191   const uint8_t *buf_;
   2192   size_t size_;
   2193   uoffset_t depth_;
   2194   uoffset_t max_depth_;
   2195   uoffset_t num_tables_;
   2196   uoffset_t max_tables_;
   2197   mutable size_t upper_bound_;
   2198   bool check_alignment_;
   2199 };
   2200 
   2201 // Convenient way to bundle a buffer and its length, to pass it around
   2202 // typed by its root.
   2203 // A BufferRef does not own its buffer.
   2204 struct BufferRefBase {};  // for std::is_base_of
   2205 template<typename T> struct BufferRef : BufferRefBase {
   2206   BufferRef() : buf(nullptr), len(0), must_free(false) {}
   2207   BufferRef(uint8_t *_buf, uoffset_t _len)
   2208       : buf(_buf), len(_len), must_free(false) {}
   2209 
   2210   ~BufferRef() {
   2211     if (must_free) free(buf);
   2212   }
   2213 
   2214   const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); }
   2215 
   2216   bool Verify() {
   2217     Verifier verifier(buf, len);
   2218     return verifier.VerifyBuffer<T>(nullptr);
   2219   }
   2220 
   2221   uint8_t *buf;
   2222   uoffset_t len;
   2223   bool must_free;
   2224 };
   2225 
   2226 // "structs" are flat structures that do not have an offset table, thus
   2227 // always have all members present and do not support forwards/backwards
   2228 // compatible extensions.
   2229 
   2230 class Struct FLATBUFFERS_FINAL_CLASS {
   2231  public:
   2232   template<typename T> T GetField(uoffset_t o) const {
   2233     return ReadScalar<T>(&data_[o]);
   2234   }
   2235 
   2236   template<typename T> T GetStruct(uoffset_t o) const {
   2237     return reinterpret_cast<T>(&data_[o]);
   2238   }
   2239 
   2240   const uint8_t *GetAddressOf(uoffset_t o) const { return &data_[o]; }
   2241   uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; }
   2242 
   2243  private:
   2244   uint8_t data_[1];
   2245 };
   2246 
   2247 // "tables" use an offset table (possibly shared) that allows fields to be
   2248 // omitted and added at will, but uses an extra indirection to read.
   2249 class Table {
   2250  public:
   2251   const uint8_t *GetVTable() const {
   2252     return data_ - ReadScalar<soffset_t>(data_);
   2253   }
   2254 
   2255   // This gets the field offset for any of the functions below it, or 0
   2256   // if the field was not present.
   2257   voffset_t GetOptionalFieldOffset(voffset_t field) const {
   2258     // The vtable offset is always at the start.
   2259     auto vtable = GetVTable();
   2260     // The first element is the size of the vtable (fields + type id + itself).
   2261     auto vtsize = ReadScalar<voffset_t>(vtable);
   2262     // If the field we're accessing is outside the vtable, we're reading older
   2263     // data, so it's the same as if the offset was 0 (not present).
   2264     return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
   2265   }
   2266 
   2267   template<typename T> T GetField(voffset_t field, T defaultval) const {
   2268     auto field_offset = GetOptionalFieldOffset(field);
   2269     return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
   2270   }
   2271 
   2272   template<typename P> P GetPointer(voffset_t field) {
   2273     auto field_offset = GetOptionalFieldOffset(field);
   2274     auto p = data_ + field_offset;
   2275     return field_offset ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p))
   2276                         : nullptr;
   2277   }
   2278   template<typename P> P GetPointer(voffset_t field) const {
   2279     return const_cast<Table *>(this)->GetPointer<P>(field);
   2280   }
   2281 
   2282   template<typename P> P GetStruct(voffset_t field) const {
   2283     auto field_offset = GetOptionalFieldOffset(field);
   2284     auto p = const_cast<uint8_t *>(data_ + field_offset);
   2285     return field_offset ? reinterpret_cast<P>(p) : nullptr;
   2286   }
   2287 
   2288   template<typename T> bool SetField(voffset_t field, T val, T def) {
   2289     auto field_offset = GetOptionalFieldOffset(field);
   2290     if (!field_offset) return IsTheSameAs(val, def);
   2291     WriteScalar(data_ + field_offset, val);
   2292     return true;
   2293   }
   2294 
   2295   bool SetPointer(voffset_t field, const uint8_t *val) {
   2296     auto field_offset = GetOptionalFieldOffset(field);
   2297     if (!field_offset) return false;
   2298     WriteScalar(data_ + field_offset,
   2299                 static_cast<uoffset_t>(val - (data_ + field_offset)));
   2300     return true;
   2301   }
   2302 
   2303   uint8_t *GetAddressOf(voffset_t field) {
   2304     auto field_offset = GetOptionalFieldOffset(field);
   2305     return field_offset ? data_ + field_offset : nullptr;
   2306   }
   2307   const uint8_t *GetAddressOf(voffset_t field) const {
   2308     return const_cast<Table *>(this)->GetAddressOf(field);
   2309   }
   2310 
   2311   bool CheckField(voffset_t field) const {
   2312     return GetOptionalFieldOffset(field) != 0;
   2313   }
   2314 
   2315   // Verify the vtable of this table.
   2316   // Call this once per table, followed by VerifyField once per field.
   2317   bool VerifyTableStart(Verifier &verifier) const {
   2318     return verifier.VerifyTableStart(data_);
   2319   }
   2320 
   2321   // Verify a particular field.
   2322   template<typename T>
   2323   bool VerifyField(const Verifier &verifier, voffset_t field) const {
   2324     // Calling GetOptionalFieldOffset should be safe now thanks to
   2325     // VerifyTable().
   2326     auto field_offset = GetOptionalFieldOffset(field);
   2327     // Check the actual field.
   2328     return !field_offset || verifier.Verify<T>(data_, field_offset);
   2329   }
   2330 
   2331   // VerifyField for required fields.
   2332   template<typename T>
   2333   bool VerifyFieldRequired(const Verifier &verifier, voffset_t field) const {
   2334     auto field_offset = GetOptionalFieldOffset(field);
   2335     return verifier.Check(field_offset != 0) &&
   2336            verifier.Verify<T>(data_, field_offset);
   2337   }
   2338 
   2339   // Versions for offsets.
   2340   bool VerifyOffset(const Verifier &verifier, voffset_t field) const {
   2341     auto field_offset = GetOptionalFieldOffset(field);
   2342     return !field_offset || verifier.VerifyOffset(data_, field_offset);
   2343   }
   2344 
   2345   bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const {
   2346     auto field_offset = GetOptionalFieldOffset(field);
   2347     return verifier.Check(field_offset != 0) &&
   2348            verifier.VerifyOffset(data_, field_offset);
   2349   }
   2350 
   2351  private:
   2352   // private constructor & copy constructor: you obtain instances of this
   2353   // class by pointing to existing data only
   2354   Table();
   2355   Table(const Table &other);
   2356 
   2357   uint8_t data_[1];
   2358 };
   2359 
   2360 template<typename T> void FlatBufferBuilder::Required(Offset<T> table,
   2361                                                       voffset_t field) {
   2362   auto table_ptr = reinterpret_cast<const Table *>(buf_.data_at(table.o));
   2363   bool ok = table_ptr->GetOptionalFieldOffset(field) != 0;
   2364   // If this fails, the caller will show what field needs to be set.
   2365   FLATBUFFERS_ASSERT(ok);
   2366   (void)ok;
   2367 }
   2368 
   2369 /// @brief This can compute the start of a FlatBuffer from a root pointer, i.e.
   2370 /// it is the opposite transformation of GetRoot().
   2371 /// This may be useful if you want to pass on a root and have the recipient
   2372 /// delete the buffer afterwards.
   2373 inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
   2374   auto table = reinterpret_cast<const Table *>(root);
   2375   auto vtable = table->GetVTable();
   2376   // Either the vtable is before the root or after the root.
   2377   auto start = (std::min)(vtable, reinterpret_cast<const uint8_t *>(root));
   2378   // Align to at least sizeof(uoffset_t).
   2379   start = reinterpret_cast<const uint8_t *>(reinterpret_cast<uintptr_t>(start) &
   2380                                             ~(sizeof(uoffset_t) - 1));
   2381   // Additionally, there may be a file_identifier in the buffer, and the root
   2382   // offset. The buffer may have been aligned to any size between
   2383   // sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align").
   2384   // Sadly, the exact alignment is only known when constructing the buffer,
   2385   // since it depends on the presence of values with said alignment properties.
   2386   // So instead, we simply look at the next uoffset_t values (root,
   2387   // file_identifier, and alignment padding) to see which points to the root.
   2388   // None of the other values can "impersonate" the root since they will either
   2389   // be 0 or four ASCII characters.
   2390   static_assert(FlatBufferBuilder::kFileIdentifierLength == sizeof(uoffset_t),
   2391                 "file_identifier is assumed to be the same size as uoffset_t");
   2392   for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1;
   2393        possible_roots; possible_roots--) {
   2394     start -= sizeof(uoffset_t);
   2395     if (ReadScalar<uoffset_t>(start) + start ==
   2396         reinterpret_cast<const uint8_t *>(root))
   2397       return start;
   2398   }
   2399   // We didn't find the root, either the "root" passed isn't really a root,
   2400   // or the buffer is corrupt.
   2401   // Assert, because calling this function with bad data may cause reads
   2402   // outside of buffer boundaries.
   2403   FLATBUFFERS_ASSERT(false);
   2404   return nullptr;
   2405 }
   2406 
   2407 /// @brief This return the prefixed size of a FlatBuffer.
   2408 inline uoffset_t GetPrefixedSize(const uint8_t* buf){ return ReadScalar<uoffset_t>(buf); }
   2409 
   2410 // Base class for native objects (FlatBuffer data de-serialized into native
   2411 // C++ data structures).
   2412 // Contains no functionality, purely documentative.
   2413 struct NativeTable {};
   2414 
   2415 /// @brief Function types to be used with resolving hashes into objects and
   2416 /// back again. The resolver gets a pointer to a field inside an object API
   2417 /// object that is of the type specified in the schema using the attribute
   2418 /// `cpp_type` (it is thus important whatever you write to this address
   2419 /// matches that type). The value of this field is initially null, so you
   2420 /// may choose to implement a delayed binding lookup using this function
   2421 /// if you wish. The resolver does the opposite lookup, for when the object
   2422 /// is being serialized again.
   2423 typedef uint64_t hash_value_t;
   2424 // clang-format off
   2425 #ifdef FLATBUFFERS_CPP98_STL
   2426   typedef void (*resolver_function_t)(void **pointer_adr, hash_value_t hash);
   2427   typedef hash_value_t (*rehasher_function_t)(void *pointer);
   2428 #else
   2429   typedef std::function<void (void **pointer_adr, hash_value_t hash)>
   2430           resolver_function_t;
   2431   typedef std::function<hash_value_t (void *pointer)> rehasher_function_t;
   2432 #endif
   2433 // clang-format on
   2434 
   2435 // Helper function to test if a field is present, using any of the field
   2436 // enums in the generated code.
   2437 // `table` must be a generated table type. Since this is a template parameter,
   2438 // this is not typechecked to be a subclass of Table, so beware!
   2439 // Note: this function will return false for fields equal to the default
   2440 // value, since they're not stored in the buffer (unless force_defaults was
   2441 // used).
   2442 template<typename T>
   2443 bool IsFieldPresent(const T *table, typename T::FlatBuffersVTableOffset field) {
   2444   // Cast, since Table is a private baseclass of any table types.
   2445   return reinterpret_cast<const Table *>(table)->CheckField(
   2446       static_cast<voffset_t>(field));
   2447 }
   2448 
   2449 // Utility function for reverse lookups on the EnumNames*() functions
   2450 // (in the generated C++ code)
   2451 // names must be NULL terminated.
   2452 inline int LookupEnum(const char **names, const char *name) {
   2453   for (const char **p = names; *p; p++)
   2454     if (!strcmp(*p, name)) return static_cast<int>(p - names);
   2455   return -1;
   2456 }
   2457 
   2458 // These macros allow us to layout a struct with a guarantee that they'll end
   2459 // up looking the same on different compilers and platforms.
   2460 // It does this by disallowing the compiler to do any padding, and then
   2461 // does padding itself by inserting extra padding fields that make every
   2462 // element aligned to its own size.
   2463 // Additionally, it manually sets the alignment of the struct as a whole,
   2464 // which is typically its largest element, or a custom size set in the schema
   2465 // by the force_align attribute.
   2466 // These are used in the generated code only.
   2467 
   2468 // clang-format off
   2469 #if defined(_MSC_VER)
   2470   #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
   2471     __pragma(pack(1)) \
   2472     struct __declspec(align(alignment))
   2473   #define FLATBUFFERS_STRUCT_END(name, size) \
   2474     __pragma(pack()) \
   2475     static_assert(sizeof(name) == size, "compiler breaks packing rules")
   2476 #elif defined(__GNUC__) || defined(__clang__)
   2477   #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
   2478     _Pragma("pack(1)") \
   2479     struct __attribute__((aligned(alignment)))
   2480   #define FLATBUFFERS_STRUCT_END(name, size) \
   2481     _Pragma("pack()") \
   2482     static_assert(sizeof(name) == size, "compiler breaks packing rules")
   2483 #else
   2484   #error Unknown compiler, please define structure alignment macros
   2485 #endif
   2486 // clang-format on
   2487 
   2488 // Minimal reflection via code generation.
   2489 // Besides full-fat reflection (see reflection.h) and parsing/printing by
   2490 // loading schemas (see idl.h), we can also have code generation for mimimal
   2491 // reflection data which allows pretty-printing and other uses without needing
   2492 // a schema or a parser.
   2493 // Generate code with --reflect-types (types only) or --reflect-names (names
   2494 // also) to enable.
   2495 // See minireflect.h for utilities using this functionality.
   2496 
   2497 // These types are organized slightly differently as the ones in idl.h.
   2498 enum SequenceType { ST_TABLE, ST_STRUCT, ST_UNION, ST_ENUM };
   2499 
   2500 // Scalars have the same order as in idl.h
   2501 // clang-format off
   2502 #define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \
   2503   ET(ET_UTYPE) \
   2504   ET(ET_BOOL) \
   2505   ET(ET_CHAR) \
   2506   ET(ET_UCHAR) \
   2507   ET(ET_SHORT) \
   2508   ET(ET_USHORT) \
   2509   ET(ET_INT) \
   2510   ET(ET_UINT) \
   2511   ET(ET_LONG) \
   2512   ET(ET_ULONG) \
   2513   ET(ET_FLOAT) \
   2514   ET(ET_DOUBLE) \
   2515   ET(ET_STRING) \
   2516   ET(ET_SEQUENCE)  // See SequenceType.
   2517 
   2518 enum ElementaryType {
   2519   #define FLATBUFFERS_ET(E) E,
   2520     FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
   2521   #undef FLATBUFFERS_ET
   2522 };
   2523 
   2524 inline const char * const *ElementaryTypeNames() {
   2525   static const char * const names[] = {
   2526     #define FLATBUFFERS_ET(E) #E,
   2527       FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
   2528     #undef FLATBUFFERS_ET
   2529   };
   2530   return names;
   2531 }
   2532 // clang-format on
   2533 
   2534 // Basic type info cost just 16bits per field!
   2535 struct TypeCode {
   2536   uint16_t base_type : 4;  // ElementaryType
   2537   uint16_t is_vector : 1;
   2538   int16_t sequence_ref : 11;  // Index into type_refs below, or -1 for none.
   2539 };
   2540 
   2541 static_assert(sizeof(TypeCode) == 2, "TypeCode");
   2542 
   2543 struct TypeTable;
   2544 
   2545 // Signature of the static method present in each type.
   2546 typedef const TypeTable *(*TypeFunction)();
   2547 
   2548 struct TypeTable {
   2549   SequenceType st;
   2550   size_t num_elems;  // of type_codes, values, names (but not type_refs).
   2551   const TypeCode *type_codes;  // num_elems count
   2552   const TypeFunction *type_refs;  // less than num_elems entries (see TypeCode).
   2553   const int64_t *values;  // Only set for non-consecutive enum/union or structs.
   2554   const char * const *names;     // Only set if compiled with --reflect-names.
   2555 };
   2556 
   2557 // String which identifies the current version of FlatBuffers.
   2558 // flatbuffer_version_string is used by Google developers to identify which
   2559 // applications uploaded to Google Play are using this library.  This allows
   2560 // the development team at Google to determine the popularity of the library.
   2561 // How it works: Applications that are uploaded to the Google Play Store are
   2562 // scanned for this version string.  We track which applications are using it
   2563 // to measure popularity.  You are free to remove it (of course) but we would
   2564 // appreciate if you left it in.
   2565 
   2566 // Weak linkage is culled by VS & doesn't work on cygwin.
   2567 // clang-format off
   2568 #if !defined(_WIN32) && !defined(__CYGWIN__)
   2569 
   2570 extern volatile __attribute__((weak)) const char *flatbuffer_version_string;
   2571 volatile __attribute__((weak)) const char *flatbuffer_version_string =
   2572   "FlatBuffers "
   2573   FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
   2574   FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
   2575   FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
   2576 
   2577 #endif  // !defined(_WIN32) && !defined(__CYGWIN__)
   2578 
   2579 #define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\
   2580     inline E operator | (E lhs, E rhs){\
   2581         return E(T(lhs) | T(rhs));\
   2582     }\
   2583     inline E operator & (E lhs, E rhs){\
   2584         return E(T(lhs) & T(rhs));\
   2585     }\
   2586     inline E operator ^ (E lhs, E rhs){\
   2587         return E(T(lhs) ^ T(rhs));\
   2588     }\
   2589     inline E operator ~ (E lhs){\
   2590         return E(~T(lhs));\
   2591     }\
   2592     inline E operator |= (E &lhs, E rhs){\
   2593         lhs = lhs | rhs;\
   2594         return lhs;\
   2595     }\
   2596     inline E operator &= (E &lhs, E rhs){\
   2597         lhs = lhs & rhs;\
   2598         return lhs;\
   2599     }\
   2600     inline E operator ^= (E &lhs, E rhs){\
   2601         lhs = lhs ^ rhs;\
   2602         return lhs;\
   2603     }\
   2604     inline bool operator !(E rhs) \
   2605     {\
   2606         return !bool(T(rhs)); \
   2607     }
   2608 /// @endcond
   2609 }  // namespace flatbuffers
   2610 
   2611 // clang-format on
   2612 
   2613 #endif  // FLATBUFFERS_H_
   2614