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