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