flatbuffers.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2014 Google Inc. All rights reserved.
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00017 #ifndef FLATBUFFERS_H_
00018 #define FLATBUFFERS_H_
00019 
00020 #include "behaviortree_cpp/flatbuffers/base.h"
00021 
00022 #if defined(FLATBUFFERS_NAN_DEFAULTS)
00023 #include <cmath>
00024 #endif
00025 
00026 namespace flatbuffers {
00027 // Generic 'operator==' with conditional specialisations.
00028 template<typename T> inline bool IsTheSameAs(T e, T def) { return e == def; }
00029 
00030 #if defined(FLATBUFFERS_NAN_DEFAULTS) && \
00031     (!defined(_MSC_VER) || _MSC_VER >= 1800)
00032 // Like `operator==(e, def)` with weak NaN if T=(float|double).
00033 template<> inline bool IsTheSameAs<float>(float e, float def) {
00034   return (e == def) || (std::isnan(def) && std::isnan(e));
00035 }
00036 template<> inline bool IsTheSameAs<double>(double e, double def) {
00037   return (e == def) || (std::isnan(def) && std::isnan(e));
00038 }
00039 #endif
00040 
00041 // Wrapper for uoffset_t to allow safe template specialization.
00042 // Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
00043 template<typename T> struct Offset {
00044   uoffset_t o;
00045   Offset() : o(0) {}
00046   Offset(uoffset_t _o) : o(_o) {}
00047   Offset<void> Union() const { return Offset<void>(o); }
00048   bool IsNull() const { return !o; }
00049 };
00050 
00051 inline void EndianCheck() {
00052   int endiantest = 1;
00053   // If this fails, see FLATBUFFERS_LITTLEENDIAN above.
00054   FLATBUFFERS_ASSERT(*reinterpret_cast<char *>(&endiantest) ==
00055                      FLATBUFFERS_LITTLEENDIAN);
00056   (void)endiantest;
00057 }
00058 
00059 template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() {
00060   // clang-format off
00061   #ifdef _MSC_VER
00062     return __alignof(T);
00063   #else
00064     #ifndef alignof
00065       return __alignof__(T);
00066     #else
00067       return alignof(T);
00068     #endif
00069   #endif
00070   // clang-format on
00071 }
00072 
00073 // When we read serialized data from memory, in the case of most scalars,
00074 // we want to just read T, but in the case of Offset, we want to actually
00075 // perform the indirection and return a pointer.
00076 // The template specialization below does just that.
00077 // It is wrapped in a struct since function templates can't overload on the
00078 // return type like this.
00079 // The typedef is for the convenience of callers of this function
00080 // (avoiding the need for a trailing return decltype)
00081 template<typename T> struct IndirectHelper {
00082   typedef T return_type;
00083   typedef T mutable_return_type;
00084   static const size_t element_stride = sizeof(T);
00085   static return_type Read(const uint8_t *p, uoffset_t i) {
00086     return EndianScalar((reinterpret_cast<const T *>(p))[i]);
00087   }
00088 };
00089 template<typename T> struct IndirectHelper<Offset<T>> {
00090   typedef const T *return_type;
00091   typedef T *mutable_return_type;
00092   static const size_t element_stride = sizeof(uoffset_t);
00093   static return_type Read(const uint8_t *p, uoffset_t i) {
00094     p += i * sizeof(uoffset_t);
00095     return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p));
00096   }
00097 };
00098 template<typename T> struct IndirectHelper<const T *> {
00099   typedef const T *return_type;
00100   typedef T *mutable_return_type;
00101   static const size_t element_stride = sizeof(T);
00102   static return_type Read(const uint8_t *p, uoffset_t i) {
00103     return reinterpret_cast<const T *>(p + i * sizeof(T));
00104   }
00105 };
00106 
00107 // An STL compatible iterator implementation for Vector below, effectively
00108 // calling Get() for every element.
00109 template<typename T, typename IT> struct VectorIterator {
00110   typedef std::random_access_iterator_tag iterator_category;
00111   typedef IT value_type;
00112   typedef ptrdiff_t difference_type;
00113   typedef IT *pointer;
00114   typedef IT &reference;
00115 
00116   VectorIterator(const uint8_t *data, uoffset_t i)
00117       : data_(data + IndirectHelper<T>::element_stride * i) {}
00118   VectorIterator(const VectorIterator &other) : data_(other.data_) {}
00119   VectorIterator() : data_(nullptr) {}
00120 
00121   VectorIterator &operator=(const VectorIterator &other) {
00122     data_ = other.data_;
00123     return *this;
00124   }
00125 
00126   // clang-format off
00127   #if !defined(FLATBUFFERS_CPP98_STL)
00128   VectorIterator &operator=(VectorIterator &&other) {
00129     data_ = other.data_;
00130     return *this;
00131   }
00132   #endif  // !defined(FLATBUFFERS_CPP98_STL)
00133   // clang-format on
00134 
00135   bool operator==(const VectorIterator &other) const {
00136     return data_ == other.data_;
00137   }
00138 
00139   bool operator<(const VectorIterator &other) const {
00140     return data_ < other.data_;
00141   }
00142 
00143   bool operator!=(const VectorIterator &other) const {
00144     return data_ != other.data_;
00145   }
00146 
00147   difference_type operator-(const VectorIterator &other) const {
00148     return (data_ - other.data_) / IndirectHelper<T>::element_stride;
00149   }
00150 
00151   IT operator*() const { return IndirectHelper<T>::Read(data_, 0); }
00152 
00153   IT operator->() const { return IndirectHelper<T>::Read(data_, 0); }
00154 
00155   VectorIterator &operator++() {
00156     data_ += IndirectHelper<T>::element_stride;
00157     return *this;
00158   }
00159 
00160   VectorIterator operator++(int) {
00161     VectorIterator temp(data_, 0);
00162     data_ += IndirectHelper<T>::element_stride;
00163     return temp;
00164   }
00165 
00166   VectorIterator operator+(const uoffset_t &offset) const {
00167     return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride,
00168                           0);
00169   }
00170 
00171   VectorIterator &operator+=(const uoffset_t &offset) {
00172     data_ += offset * IndirectHelper<T>::element_stride;
00173     return *this;
00174   }
00175 
00176   VectorIterator &operator--() {
00177     data_ -= IndirectHelper<T>::element_stride;
00178     return *this;
00179   }
00180 
00181   VectorIterator operator--(int) {
00182     VectorIterator temp(data_, 0);
00183     data_ -= IndirectHelper<T>::element_stride;
00184     return temp;
00185   }
00186 
00187   VectorIterator operator-(const uoffset_t &offset) const {
00188     return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride,
00189                           0);
00190   }
00191 
00192   VectorIterator &operator-=(const uoffset_t &offset) {
00193     data_ -= offset * IndirectHelper<T>::element_stride;
00194     return *this;
00195   }
00196 
00197  private:
00198   const uint8_t *data_;
00199 };
00200 
00201 template<typename Iterator> struct VectorReverseIterator :
00202   public std::reverse_iterator<Iterator> {
00203 
00204   explicit VectorReverseIterator(Iterator iter) : iter_(iter) {}
00205 
00206   typename Iterator::value_type operator*() const { return *(iter_ - 1); }
00207 
00208   typename Iterator::value_type operator->() const { return *(iter_ - 1); }
00209 
00210  private:
00211   Iterator iter_;
00212 };
00213 
00214 struct String;
00215 
00216 // This is used as a helper type for accessing vectors.
00217 // Vector::data() assumes the vector elements start after the length field.
00218 template<typename T> class Vector {
00219  public:
00220   typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
00221       iterator;
00222   typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
00223       const_iterator;
00224   typedef VectorReverseIterator<iterator> reverse_iterator;
00225   typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
00226 
00227   uoffset_t size() const { return EndianScalar(length_); }
00228 
00229   // Deprecated: use size(). Here for backwards compatibility.
00230   FLATBUFFERS_ATTRIBUTE(deprecated("use size() instead"))
00231   uoffset_t Length() const { return size(); }
00232 
00233   typedef typename IndirectHelper<T>::return_type return_type;
00234   typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
00235 
00236   return_type Get(uoffset_t i) const {
00237     FLATBUFFERS_ASSERT(i < size());
00238     return IndirectHelper<T>::Read(Data(), i);
00239   }
00240 
00241   return_type operator[](uoffset_t i) const { return Get(i); }
00242 
00243   // If this is a Vector of enums, T will be its storage type, not the enum
00244   // type. This function makes it convenient to retrieve value with enum
00245   // type E.
00246   template<typename E> E GetEnum(uoffset_t i) const {
00247     return static_cast<E>(Get(i));
00248   }
00249 
00250   // If this a vector of unions, this does the cast for you. There's no check
00251   // to make sure this is the right type!
00252   template<typename U> const U *GetAs(uoffset_t i) const {
00253     return reinterpret_cast<const U *>(Get(i));
00254   }
00255 
00256   // If this a vector of unions, this does the cast for you. There's no check
00257   // to make sure this is actually a string!
00258   const String *GetAsString(uoffset_t i) const {
00259     return reinterpret_cast<const String *>(Get(i));
00260   }
00261 
00262   const void *GetStructFromOffset(size_t o) const {
00263     return reinterpret_cast<const void *>(Data() + o);
00264   }
00265 
00266   iterator begin() { return iterator(Data(), 0); }
00267   const_iterator begin() const { return const_iterator(Data(), 0); }
00268 
00269   iterator end() { return iterator(Data(), size()); }
00270   const_iterator end() const { return const_iterator(Data(), size()); }
00271 
00272   reverse_iterator rbegin() { return reverse_iterator(end()); }
00273   const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
00274 
00275   reverse_iterator rend() { return reverse_iterator(end()); }
00276   const_reverse_iterator rend() const { return const_reverse_iterator(end()); }
00277 
00278   const_iterator cbegin() const { return begin(); }
00279 
00280   const_iterator cend() const { return end(); }
00281 
00282   const_reverse_iterator crbegin() const { return rbegin(); }
00283 
00284   const_reverse_iterator crend() const { return rend(); }
00285 
00286   // Change elements if you have a non-const pointer to this object.
00287   // Scalars only. See reflection.h, and the documentation.
00288   void Mutate(uoffset_t i, const T &val) {
00289     FLATBUFFERS_ASSERT(i < size());
00290     WriteScalar(data() + i, val);
00291   }
00292 
00293   // Change an element of a vector of tables (or strings).
00294   // "val" points to the new table/string, as you can obtain from
00295   // e.g. reflection::AddFlatBuffer().
00296   void MutateOffset(uoffset_t i, const uint8_t *val) {
00297     FLATBUFFERS_ASSERT(i < size());
00298     static_assert(sizeof(T) == sizeof(uoffset_t), "Unrelated types");
00299     WriteScalar(data() + i,
00300                 static_cast<uoffset_t>(val - (Data() + i * sizeof(uoffset_t))));
00301   }
00302 
00303   // Get a mutable pointer to tables/strings inside this vector.
00304   mutable_return_type GetMutableObject(uoffset_t i) const {
00305     FLATBUFFERS_ASSERT(i < size());
00306     return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i));
00307   }
00308 
00309   // The raw data in little endian format. Use with care.
00310   const uint8_t *Data() const {
00311     return reinterpret_cast<const uint8_t *>(&length_ + 1);
00312   }
00313 
00314   uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
00315 
00316   // Similarly, but typed, much like std::vector::data
00317   const T *data() const { return reinterpret_cast<const T *>(Data()); }
00318   T *data() { return reinterpret_cast<T *>(Data()); }
00319 
00320   template<typename K> return_type LookupByKey(K key) const {
00321     void *search_result = std::bsearch(
00322         &key, Data(), size(), IndirectHelper<T>::element_stride, KeyCompare<K>);
00323 
00324     if (!search_result) {
00325       return nullptr;  // Key not found.
00326     }
00327 
00328     const uint8_t *element = reinterpret_cast<const uint8_t *>(search_result);
00329 
00330     return IndirectHelper<T>::Read(element, 0);
00331   }
00332 
00333  protected:
00334   // This class is only used to access pre-existing data. Don't ever
00335   // try to construct these manually.
00336   Vector();
00337 
00338   uoffset_t length_;
00339 
00340  private:
00341   // This class is a pointer. Copying will therefore create an invalid object.
00342   // Private and unimplemented copy constructor.
00343   Vector(const Vector &);
00344 
00345   template<typename K> static int KeyCompare(const void *ap, const void *bp) {
00346     const K *key = reinterpret_cast<const K *>(ap);
00347     const uint8_t *data = reinterpret_cast<const uint8_t *>(bp);
00348     auto table = IndirectHelper<T>::Read(data, 0);
00349 
00350     // std::bsearch compares with the operands transposed, so we negate the
00351     // result here.
00352     return -table->KeyCompareWithValue(*key);
00353   }
00354 };
00355 
00356 // Represent a vector much like the template above, but in this case we
00357 // don't know what the element types are (used with reflection.h).
00358 class VectorOfAny {
00359  public:
00360   uoffset_t size() const { return EndianScalar(length_); }
00361 
00362   const uint8_t *Data() const {
00363     return reinterpret_cast<const uint8_t *>(&length_ + 1);
00364   }
00365   uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
00366 
00367  protected:
00368   VectorOfAny();
00369 
00370   uoffset_t length_;
00371 
00372  private:
00373   VectorOfAny(const VectorOfAny &);
00374 };
00375 
00376 #ifndef FLATBUFFERS_CPP98_STL
00377 template<typename T, typename U>
00378 Vector<Offset<T>> *VectorCast(Vector<Offset<U>> *ptr) {
00379   static_assert(std::is_base_of<T, U>::value, "Unrelated types");
00380   return reinterpret_cast<Vector<Offset<T>> *>(ptr);
00381 }
00382 
00383 template<typename T, typename U>
00384 const Vector<Offset<T>> *VectorCast(const Vector<Offset<U>> *ptr) {
00385   static_assert(std::is_base_of<T, U>::value, "Unrelated types");
00386   return reinterpret_cast<const Vector<Offset<T>> *>(ptr);
00387 }
00388 #endif
00389 
00390 // Convenient helper function to get the length of any vector, regardless
00391 // of whether it is null or not (the field is not set).
00392 template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
00393   return v ? v->size() : 0;
00394 }
00395 
00396 // Lexicographically compare two strings (possibly containing nulls), and
00397 // return true if the first is less than the second.
00398 static inline bool StringLessThan(const char *a_data, uoffset_t a_size,
00399                                   const char *b_data, uoffset_t b_size) {
00400   const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size));
00401   return cmp == 0 ? a_size < b_size : cmp < 0;
00402 }
00403 
00404 struct String : public Vector<char> {
00405   const char *c_str() const { return reinterpret_cast<const char *>(Data()); }
00406   std::string str() const { return std::string(c_str(), size()); }
00407 
00408   // clang-format off
00409   #ifdef FLATBUFFERS_HAS_STRING_VIEW
00410   flatbuffers::string_view string_view() const {
00411     return flatbuffers::string_view(c_str(), size());
00412   }
00413   #endif // FLATBUFFERS_HAS_STRING_VIEW
00414   // clang-format on
00415 
00416   bool operator<(const String &o) const {
00417     return StringLessThan(this->data(), this->size(), o.data(), o.size());
00418   }
00419 };
00420 
00421 // Convenience function to get std::string from a String returning an empty
00422 // string on null pointer.
00423 static inline std::string GetString(const String * str) {
00424   return str ? str->str() : "";
00425 }
00426 
00427 // Convenience function to get char* from a String returning an empty string on
00428 // null pointer.
00429 static inline const char * GetCstring(const String * str) {
00430   return str ? str->c_str() : "";
00431 }
00432 
00433 // Allocator interface. This is flatbuffers-specific and meant only for
00434 // `vector_downward` usage.
00435 class Allocator {
00436  public:
00437   virtual ~Allocator() {}
00438 
00439   // Allocate `size` bytes of memory.
00440   virtual uint8_t *allocate(size_t size) = 0;
00441 
00442   // Deallocate `size` bytes of memory at `p` allocated by this allocator.
00443   virtual void deallocate(uint8_t *p, size_t size) = 0;
00444 
00445   // Reallocate `new_size` bytes of memory, replacing the old region of size
00446   // `old_size` at `p`. In contrast to a normal realloc, this grows downwards,
00447   // and is intended specifcally for `vector_downward` use.
00448   // `in_use_back` and `in_use_front` indicate how much of `old_size` is
00449   // actually in use at each end, and needs to be copied.
00450   virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
00451                                        size_t new_size, size_t in_use_back,
00452                                        size_t in_use_front) {
00453     FLATBUFFERS_ASSERT(new_size > old_size);  // vector_downward only grows
00454     uint8_t *new_p = allocate(new_size);
00455     memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
00456                     in_use_front);
00457     deallocate(old_p, old_size);
00458     return new_p;
00459   }
00460 
00461  protected:
00462   // Called by `reallocate_downward` to copy memory from `old_p` of `old_size`
00463   // to `new_p` of `new_size`. Only memory of size `in_use_front` and
00464   // `in_use_back` will be copied from the front and back of the old memory
00465   // allocation.
00466   void memcpy_downward(uint8_t *old_p, size_t old_size,
00467                        uint8_t *new_p, size_t new_size,
00468                        size_t in_use_back, size_t in_use_front) {
00469     memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back,
00470            in_use_back);
00471     memcpy(new_p, old_p, in_use_front);
00472   }
00473 };
00474 
00475 // DefaultAllocator uses new/delete to allocate memory regions
00476 class DefaultAllocator : public Allocator {
00477  public:
00478   uint8_t *allocate(size_t size) FLATBUFFERS_OVERRIDE {
00479     return new uint8_t[size];
00480   }
00481 
00482   void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE {
00483     delete[] p;
00484   }
00485 
00486   static void dealloc(void *p, size_t) {
00487     delete[] static_cast<uint8_t *>(p);
00488   }
00489 };
00490 
00491 // These functions allow for a null allocator to mean use the default allocator,
00492 // as used by DetachedBuffer and vector_downward below.
00493 // This is to avoid having a statically or dynamically allocated default
00494 // allocator, or having to move it between the classes that may own it.
00495 inline uint8_t *Allocate(Allocator *allocator, size_t size) {
00496   return allocator ? allocator->allocate(size)
00497                    : DefaultAllocator().allocate(size);
00498 }
00499 
00500 inline void Deallocate(Allocator *allocator, uint8_t *p, size_t size) {
00501   if (allocator) allocator->deallocate(p, size);
00502   else DefaultAllocator().deallocate(p, size);
00503 }
00504 
00505 inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p,
00506                                    size_t old_size, size_t new_size,
00507                                    size_t in_use_back, size_t in_use_front) {
00508   return allocator
00509       ? allocator->reallocate_downward(old_p, old_size, new_size,
00510                                        in_use_back, in_use_front)
00511       : DefaultAllocator().reallocate_downward(old_p, old_size, new_size,
00512                                                in_use_back, in_use_front);
00513 }
00514 
00515 // DetachedBuffer is a finished flatbuffer memory region, detached from its
00516 // builder. The original memory region and allocator are also stored so that
00517 // the DetachedBuffer can manage the memory lifetime.
00518 class DetachedBuffer {
00519  public:
00520   DetachedBuffer()
00521       : allocator_(nullptr),
00522         own_allocator_(false),
00523         buf_(nullptr),
00524         reserved_(0),
00525         cur_(nullptr),
00526         size_(0) {}
00527 
00528   DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf,
00529                  size_t reserved, uint8_t *cur, size_t sz)
00530       : allocator_(allocator),
00531         own_allocator_(own_allocator),
00532         buf_(buf),
00533         reserved_(reserved),
00534         cur_(cur),
00535         size_(sz) {}
00536 
00537   // clang-format off
00538   #if !defined(FLATBUFFERS_CPP98_STL)
00539   // clang-format on
00540   DetachedBuffer(DetachedBuffer &&other)
00541       : allocator_(other.allocator_),
00542         own_allocator_(other.own_allocator_),
00543         buf_(other.buf_),
00544         reserved_(other.reserved_),
00545         cur_(other.cur_),
00546         size_(other.size_) {
00547     other.reset();
00548   }
00549   // clang-format off
00550   #endif  // !defined(FLATBUFFERS_CPP98_STL)
00551   // clang-format on
00552 
00553   // clang-format off
00554   #if !defined(FLATBUFFERS_CPP98_STL)
00555   // clang-format on
00556   DetachedBuffer &operator=(DetachedBuffer &&other) {
00557     destroy();
00558 
00559     allocator_ = other.allocator_;
00560     own_allocator_ = other.own_allocator_;
00561     buf_ = other.buf_;
00562     reserved_ = other.reserved_;
00563     cur_ = other.cur_;
00564     size_ = other.size_;
00565 
00566     other.reset();
00567 
00568     return *this;
00569   }
00570   // clang-format off
00571   #endif  // !defined(FLATBUFFERS_CPP98_STL)
00572   // clang-format on
00573 
00574   ~DetachedBuffer() { destroy(); }
00575 
00576   const uint8_t *data() const { return cur_; }
00577 
00578   uint8_t *data() { return cur_; }
00579 
00580   size_t size() const { return size_; }
00581 
00582   // clang-format off
00583   #if 0  // disabled for now due to the ordering of classes in this header
00584   template <class T>
00585   bool Verify() const {
00586     Verifier verifier(data(), size());
00587     return verifier.Verify<T>(nullptr);
00588   }
00589 
00590   template <class T>
00591   const T* GetRoot() const {
00592     return flatbuffers::GetRoot<T>(data());
00593   }
00594 
00595   template <class T>
00596   T* GetRoot() {
00597     return flatbuffers::GetRoot<T>(data());
00598   }
00599   #endif
00600   // clang-format on
00601 
00602   // clang-format off
00603   #if !defined(FLATBUFFERS_CPP98_STL)
00604   // clang-format on
00605   // These may change access mode, leave these at end of public section
00606   FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other))
00607   FLATBUFFERS_DELETE_FUNC(
00608       DetachedBuffer &operator=(const DetachedBuffer &other))
00609   // clang-format off
00610   #endif  // !defined(FLATBUFFERS_CPP98_STL)
00611   // clang-format on
00612 
00613 protected:
00614   Allocator *allocator_;
00615   bool own_allocator_;
00616   uint8_t *buf_;
00617   size_t reserved_;
00618   uint8_t *cur_;
00619   size_t size_;
00620 
00621   inline void destroy() {
00622     if (buf_) Deallocate(allocator_, buf_, reserved_);
00623     if (own_allocator_ && allocator_) { delete allocator_; }
00624     reset();
00625   }
00626 
00627   inline void reset() {
00628     allocator_ = nullptr;
00629     own_allocator_ = false;
00630     buf_ = nullptr;
00631     reserved_ = 0;
00632     cur_ = nullptr;
00633     size_ = 0;
00634   }
00635 };
00636 
00637 // This is a minimal replication of std::vector<uint8_t> functionality,
00638 // except growing from higher to lower addresses. i.e push_back() inserts data
00639 // in the lowest address in the vector.
00640 // Since this vector leaves the lower part unused, we support a "scratch-pad"
00641 // that can be stored there for temporary data, to share the allocated space.
00642 // Essentially, this supports 2 std::vectors in a single buffer.
00643 class vector_downward {
00644  public:
00645   explicit vector_downward(size_t initial_size,
00646                            Allocator *allocator,
00647                            bool own_allocator,
00648                            size_t buffer_minalign)
00649       : allocator_(allocator),
00650         own_allocator_(own_allocator),
00651         initial_size_(initial_size),
00652         buffer_minalign_(buffer_minalign),
00653         reserved_(0),
00654         buf_(nullptr),
00655         cur_(nullptr),
00656         scratch_(nullptr) {}
00657 
00658   // clang-format off
00659   #if !defined(FLATBUFFERS_CPP98_STL)
00660   vector_downward(vector_downward &&other)
00661   #else
00662   vector_downward(vector_downward &other)
00663   #endif  // defined(FLATBUFFERS_CPP98_STL)
00664   // clang-format on
00665     : allocator_(other.allocator_),
00666       own_allocator_(other.own_allocator_),
00667       initial_size_(other.initial_size_),
00668       buffer_minalign_(other.buffer_minalign_),
00669       reserved_(other.reserved_),
00670       buf_(other.buf_),
00671       cur_(other.cur_),
00672       scratch_(other.scratch_) {
00673     // No change in other.allocator_
00674     // No change in other.initial_size_
00675     // No change in other.buffer_minalign_
00676     other.own_allocator_ = false;
00677     other.reserved_ = 0;
00678     other.buf_ = nullptr;
00679     other.cur_ = nullptr;
00680     other.scratch_ = nullptr;
00681   }
00682 
00683   // clang-format off
00684   #if !defined(FLATBUFFERS_CPP98_STL)
00685   // clang-format on
00686   vector_downward &operator=(vector_downward &&other) {
00687     // Move construct a temporary and swap idiom
00688     vector_downward temp(std::move(other));
00689     swap(temp);
00690     return *this;
00691   }
00692   // clang-format off
00693   #endif  // defined(FLATBUFFERS_CPP98_STL)
00694   // clang-format on
00695 
00696   ~vector_downward() {
00697     clear_buffer();
00698     clear_allocator();
00699   }
00700 
00701   void reset() {
00702     clear_buffer();
00703     clear();
00704   }
00705 
00706   void clear() {
00707     if (buf_) {
00708       cur_ = buf_ + reserved_;
00709     } else {
00710       reserved_ = 0;
00711       cur_ = nullptr;
00712     }
00713     clear_scratch();
00714   }
00715 
00716   void clear_scratch() {
00717     scratch_ = buf_;
00718   }
00719 
00720   void clear_allocator() {
00721     if (own_allocator_ && allocator_) { delete allocator_; }
00722     allocator_ = nullptr;
00723     own_allocator_ = false;
00724   }
00725 
00726   void clear_buffer() {
00727     if (buf_) Deallocate(allocator_, buf_, reserved_);
00728     buf_ = nullptr;
00729   }
00730 
00731   // Relinquish the pointer to the caller.
00732   uint8_t *release_raw(size_t &allocated_bytes, size_t &offset) {
00733     auto *buf = buf_;
00734     allocated_bytes = reserved_;
00735     offset = static_cast<size_t>(cur_ - buf_);
00736 
00737     // release_raw only relinquishes the buffer ownership.
00738     // Does not deallocate or reset the allocator. Destructor will do that.
00739     buf_ = nullptr;
00740     clear();
00741     return buf;
00742   }
00743 
00744   // Relinquish the pointer to the caller.
00745   DetachedBuffer release() {
00746     // allocator ownership (if any) is transferred to DetachedBuffer.
00747     DetachedBuffer fb(allocator_, own_allocator_, buf_, reserved_, cur_,
00748                       size());
00749     if (own_allocator_) {
00750       allocator_ = nullptr;
00751       own_allocator_ = false;
00752     }
00753     buf_ = nullptr;
00754     clear();
00755     return fb;
00756   }
00757 
00758   size_t ensure_space(size_t len) {
00759     FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_);
00760     if (len > static_cast<size_t>(cur_ - scratch_)) { reallocate(len); }
00761     // Beyond this, signed offsets may not have enough range:
00762     // (FlatBuffers > 2GB not supported).
00763     FLATBUFFERS_ASSERT(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
00764     return len;
00765   }
00766 
00767   inline uint8_t *make_space(size_t len) {
00768     size_t space = ensure_space(len);
00769     cur_ -= space;
00770     return cur_;
00771   }
00772 
00773   // Returns nullptr if using the DefaultAllocator.
00774   Allocator *get_custom_allocator() { return allocator_; }
00775 
00776   uoffset_t size() const {
00777     return static_cast<uoffset_t>(reserved_ - (cur_ - buf_));
00778   }
00779 
00780   uoffset_t scratch_size() const {
00781     return static_cast<uoffset_t>(scratch_ - buf_);
00782   }
00783 
00784   size_t capacity() const { return reserved_; }
00785 
00786   uint8_t *data() const {
00787     FLATBUFFERS_ASSERT(cur_);
00788     return cur_;
00789   }
00790 
00791   uint8_t *scratch_data() const {
00792     FLATBUFFERS_ASSERT(buf_);
00793     return buf_;
00794   }
00795 
00796   uint8_t *scratch_end() const {
00797     FLATBUFFERS_ASSERT(scratch_);
00798     return scratch_;
00799   }
00800 
00801   uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; }
00802 
00803   void push(const uint8_t *bytes, size_t num) {
00804     memcpy(make_space(num), bytes, num);
00805   }
00806 
00807   // Specialized version of push() that avoids memcpy call for small data.
00808   template<typename T> void push_small(const T &little_endian_t) {
00809     make_space(sizeof(T));
00810     *reinterpret_cast<T *>(cur_) = little_endian_t;
00811   }
00812 
00813   template<typename T> void scratch_push_small(const T &t) {
00814     ensure_space(sizeof(T));
00815     *reinterpret_cast<T *>(scratch_) = t;
00816     scratch_ += sizeof(T);
00817   }
00818 
00819   // fill() is most frequently called with small byte counts (<= 4),
00820   // which is why we're using loops rather than calling memset.
00821   void fill(size_t zero_pad_bytes) {
00822     make_space(zero_pad_bytes);
00823     for (size_t i = 0; i < zero_pad_bytes; i++) cur_[i] = 0;
00824   }
00825 
00826   // Version for when we know the size is larger.
00827   void fill_big(size_t zero_pad_bytes) {
00828     memset(make_space(zero_pad_bytes), 0, zero_pad_bytes);
00829   }
00830 
00831   void pop(size_t bytes_to_remove) { cur_ += bytes_to_remove; }
00832   void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; }
00833 
00834   void swap(vector_downward &other) {
00835     using std::swap;
00836     swap(allocator_, other.allocator_);
00837     swap(own_allocator_, other.own_allocator_);
00838     swap(initial_size_, other.initial_size_);
00839     swap(buffer_minalign_, other.buffer_minalign_);
00840     swap(reserved_, other.reserved_);
00841     swap(buf_, other.buf_);
00842     swap(cur_, other.cur_);
00843     swap(scratch_, other.scratch_);
00844   }
00845 
00846   void swap_allocator(vector_downward &other) {
00847     using std::swap;
00848     swap(allocator_, other.allocator_);
00849     swap(own_allocator_, other.own_allocator_);
00850   }
00851 
00852  private:
00853   // You shouldn't really be copying instances of this class.
00854   FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward &))
00855   FLATBUFFERS_DELETE_FUNC(vector_downward &operator=(const vector_downward &))
00856 
00857   Allocator *allocator_;
00858   bool own_allocator_;
00859   size_t initial_size_;
00860   size_t buffer_minalign_;
00861   size_t reserved_;
00862   uint8_t *buf_;
00863   uint8_t *cur_;  // Points at location between empty (below) and used (above).
00864   uint8_t *scratch_;  // Points to the end of the scratchpad in use.
00865 
00866   void reallocate(size_t len) {
00867     auto old_reserved = reserved_;
00868     auto old_size = size();
00869     auto old_scratch_size = scratch_size();
00870     reserved_ += (std::max)(len,
00871                             old_reserved ? old_reserved / 2 : initial_size_);
00872     reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1);
00873     if (buf_) {
00874       buf_ = ReallocateDownward(allocator_, buf_, old_reserved, reserved_,
00875                                 old_size, old_scratch_size);
00876     } else {
00877       buf_ = Allocate(allocator_, reserved_);
00878     }
00879     cur_ = buf_ + reserved_ - old_size;
00880     scratch_ = buf_ + old_scratch_size;
00881   }
00882 };
00883 
00884 // Converts a Field ID to a virtual table offset.
00885 inline voffset_t FieldIndexToOffset(voffset_t field_id) {
00886   // Should correspond to what EndTable() below builds up.
00887   const int fixed_fields = 2;  // Vtable size and Object Size.
00888   return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t));
00889 }
00890 
00891 template<typename T, typename Alloc>
00892 const T *data(const std::vector<T, Alloc> &v) {
00893   return v.empty() ? nullptr : &v.front();
00894 }
00895 template<typename T, typename Alloc> T *data(std::vector<T, Alloc> &v) {
00896   return v.empty() ? nullptr : &v.front();
00897 }
00898 
00900 
00910 class FlatBufferBuilder {
00911  public:
00923   explicit FlatBufferBuilder(size_t initial_size = 1024,
00924                              Allocator *allocator = nullptr,
00925                              bool own_allocator = false,
00926                              size_t buffer_minalign =
00927                                  AlignOf<largest_scalar_t>())
00928       : buf_(initial_size, allocator, own_allocator, buffer_minalign),
00929         num_field_loc(0),
00930         max_voffset_(0),
00931         nested(false),
00932         finished(false),
00933         minalign_(1),
00934         force_defaults_(false),
00935         dedup_vtables_(true),
00936         string_pool(nullptr) {
00937     EndianCheck();
00938   }
00939 
00940   // clang-format off
00942   #if !defined(FLATBUFFERS_CPP98_STL)
00943   FlatBufferBuilder(FlatBufferBuilder &&other)
00944   #else
00945   FlatBufferBuilder(FlatBufferBuilder &other)
00946   #endif  // #if !defined(FLATBUFFERS_CPP98_STL)
00947     : buf_(1024, nullptr, false, AlignOf<largest_scalar_t>()),
00948       num_field_loc(0),
00949       max_voffset_(0),
00950       nested(false),
00951       finished(false),
00952       minalign_(1),
00953       force_defaults_(false),
00954       dedup_vtables_(true),
00955       string_pool(nullptr) {
00956     EndianCheck();
00957     // Default construct and swap idiom.
00958     // Lack of delegating constructors in vs2010 makes it more verbose than needed.
00959     Swap(other);
00960   }
00961   // clang-format on
00962 
00963   // clang-format off
00964   #if !defined(FLATBUFFERS_CPP98_STL)
00965   // clang-format on
00967   FlatBufferBuilder &operator=(FlatBufferBuilder &&other) {
00968     // Move construct a temporary and swap idiom
00969     FlatBufferBuilder temp(std::move(other));
00970     Swap(temp);
00971     return *this;
00972   }
00973   // clang-format off
00974   #endif  // defined(FLATBUFFERS_CPP98_STL)
00975   // clang-format on
00976 
00977   void Swap(FlatBufferBuilder &other) {
00978     using std::swap;
00979     buf_.swap(other.buf_);
00980     swap(num_field_loc, other.num_field_loc);
00981     swap(max_voffset_, other.max_voffset_);
00982     swap(nested, other.nested);
00983     swap(finished, other.finished);
00984     swap(minalign_, other.minalign_);
00985     swap(force_defaults_, other.force_defaults_);
00986     swap(dedup_vtables_, other.dedup_vtables_);
00987     swap(string_pool, other.string_pool);
00988   }
00989 
00990   ~FlatBufferBuilder() {
00991     if (string_pool) delete string_pool;
00992   }
00993 
00994   void Reset() {
00995     Clear();       // clear builder state
00996     buf_.reset();  // deallocate buffer
00997   }
00998 
01001   void Clear() {
01002     ClearOffsets();
01003     buf_.clear();
01004     nested = false;
01005     finished = false;
01006     minalign_ = 1;
01007     if (string_pool) string_pool->clear();
01008   }
01009 
01012   uoffset_t GetSize() const { return buf_.size(); }
01013 
01017   uint8_t *GetBufferPointer() const {
01018     Finished();
01019     return buf_.data();
01020   }
01021 
01024   uint8_t *GetCurrentBufferPointer() const { return buf_.data(); }
01025 
01030   FLATBUFFERS_ATTRIBUTE(deprecated("use Release() instead")) DetachedBuffer
01031   ReleaseBufferPointer() {
01032     Finished();
01033     return buf_.release();
01034   }
01035 
01038   DetachedBuffer Release() {
01039     Finished();
01040     return buf_.release();
01041   }
01042 
01051   uint8_t *ReleaseRaw(size_t &size, size_t &offset) {
01052     Finished();
01053     return buf_.release_raw(size, offset);
01054   }
01055 
01061   size_t GetBufferMinAlignment() {
01062     Finished();
01063     return minalign_;
01064   }
01065 
01067   void Finished() const {
01068     // If you get this assert, you're attempting to get access a buffer
01069     // which hasn't been finished yet. Be sure to call
01070     // FlatBufferBuilder::Finish with your root table.
01071     // If you really need to access an unfinished buffer, call
01072     // GetCurrentBufferPointer instead.
01073     FLATBUFFERS_ASSERT(finished);
01074   }
01076 
01081   void ForceDefaults(bool fd) { force_defaults_ = fd; }
01082 
01085   void DedupVtables(bool dedup) { dedup_vtables_ = dedup; }
01086 
01088   void Pad(size_t num_bytes) { buf_.fill(num_bytes); }
01089 
01090   void TrackMinAlign(size_t elem_size) {
01091     if (elem_size > minalign_) minalign_ = elem_size;
01092   }
01093 
01094   void Align(size_t elem_size) {
01095     TrackMinAlign(elem_size);
01096     buf_.fill(PaddingBytes(buf_.size(), elem_size));
01097   }
01098 
01099   void PushFlatBuffer(const uint8_t *bytes, size_t size) {
01100     PushBytes(bytes, size);
01101     finished = true;
01102   }
01103 
01104   void PushBytes(const uint8_t *bytes, size_t size) { buf_.push(bytes, size); }
01105 
01106   void PopBytes(size_t amount) { buf_.pop(amount); }
01107 
01108   template<typename T> void AssertScalarT() {
01109     // The code assumes power of 2 sizes and endian-swap-ability.
01110     static_assert(flatbuffers::is_scalar<T>::value, "T must be a scalar type");
01111   }
01112 
01113   // Write a single aligned scalar to the buffer
01114   template<typename T> uoffset_t PushElement(T element) {
01115     AssertScalarT<T>();
01116     T litle_endian_element = EndianScalar(element);
01117     Align(sizeof(T));
01118     buf_.push_small(litle_endian_element);
01119     return GetSize();
01120   }
01121 
01122   template<typename T> uoffset_t PushElement(Offset<T> off) {
01123     // Special case for offsets: see ReferTo below.
01124     return PushElement(ReferTo(off.o));
01125   }
01126 
01127   // When writing fields, we track where they are, so we can create correct
01128   // vtables later.
01129   void TrackField(voffset_t field, uoffset_t off) {
01130     FieldLoc fl = { off, field };
01131     buf_.scratch_push_small(fl);
01132     num_field_loc++;
01133     max_voffset_ = (std::max)(max_voffset_, field);
01134   }
01135 
01136   // Like PushElement, but additionally tracks the field this represents.
01137   template<typename T> void AddElement(voffset_t field, T e, T def) {
01138     // We don't serialize values equal to the default.
01139     if (IsTheSameAs(e, def) && !force_defaults_) return;
01140     auto off = PushElement(e);
01141     TrackField(field, off);
01142   }
01143 
01144   template<typename T> void AddOffset(voffset_t field, Offset<T> off) {
01145     if (off.IsNull()) return;  // Don't store.
01146     AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
01147   }
01148 
01149   template<typename T> void AddStruct(voffset_t field, const T *structptr) {
01150     if (!structptr) return;  // Default, don't store.
01151     Align(AlignOf<T>());
01152     buf_.push_small(*structptr);
01153     TrackField(field, GetSize());
01154   }
01155 
01156   void AddStructOffset(voffset_t field, uoffset_t off) {
01157     TrackField(field, off);
01158   }
01159 
01160   // Offsets initially are relative to the end of the buffer (downwards).
01161   // This function converts them to be relative to the current location
01162   // in the buffer (when stored here), pointing upwards.
01163   uoffset_t ReferTo(uoffset_t off) {
01164     // Align to ensure GetSize() below is correct.
01165     Align(sizeof(uoffset_t));
01166     // Offset must refer to something already in buffer.
01167     FLATBUFFERS_ASSERT(off && off <= GetSize());
01168     return GetSize() - off + static_cast<uoffset_t>(sizeof(uoffset_t));
01169   }
01170 
01171   void NotNested() {
01172     // If you hit this, you're trying to construct a Table/Vector/String
01173     // during the construction of its parent table (between the MyTableBuilder
01174     // and table.Finish().
01175     // Move the creation of these sub-objects to above the MyTableBuilder to
01176     // not get this assert.
01177     // Ignoring this assert may appear to work in simple cases, but the reason
01178     // it is here is that storing objects in-line may cause vtable offsets
01179     // to not fit anymore. It also leads to vtable duplication.
01180     FLATBUFFERS_ASSERT(!nested);
01181     // If you hit this, fields were added outside the scope of a table.
01182     FLATBUFFERS_ASSERT(!num_field_loc);
01183   }
01184 
01185   // From generated code (or from the parser), we call StartTable/EndTable
01186   // with a sequence of AddElement calls in between.
01187   uoffset_t StartTable() {
01188     NotNested();
01189     nested = true;
01190     return GetSize();
01191   }
01192 
01193   // This finishes one serialized object by generating the vtable if it's a
01194   // table, comparing it against existing vtables, and writing the
01195   // resulting vtable offset.
01196   uoffset_t EndTable(uoffset_t start) {
01197     // If you get this assert, a corresponding StartTable wasn't called.
01198     FLATBUFFERS_ASSERT(nested);
01199     // Write the vtable offset, which is the start of any Table.
01200     // We fill it's value later.
01201     auto vtableoffsetloc = PushElement<soffset_t>(0);
01202     // Write a vtable, which consists entirely of voffset_t elements.
01203     // It starts with the number of offsets, followed by a type id, followed
01204     // by the offsets themselves. In reverse:
01205     // Include space for the last offset and ensure empty tables have a
01206     // minimum size.
01207     max_voffset_ =
01208         (std::max)(static_cast<voffset_t>(max_voffset_ + sizeof(voffset_t)),
01209                    FieldIndexToOffset(0));
01210     buf_.fill_big(max_voffset_);
01211     auto table_object_size = vtableoffsetloc - start;
01212     // Vtable use 16bit offsets.
01213     FLATBUFFERS_ASSERT(table_object_size < 0x10000);
01214     WriteScalar<voffset_t>(buf_.data() + sizeof(voffset_t),
01215                            static_cast<voffset_t>(table_object_size));
01216     WriteScalar<voffset_t>(buf_.data(), max_voffset_);
01217     // Write the offsets into the table
01218     for (auto it = buf_.scratch_end() - num_field_loc * sizeof(FieldLoc);
01219          it < buf_.scratch_end(); it += sizeof(FieldLoc)) {
01220       auto field_location = reinterpret_cast<FieldLoc *>(it);
01221       auto pos = static_cast<voffset_t>(vtableoffsetloc - field_location->off);
01222       // If this asserts, it means you've set a field twice.
01223       FLATBUFFERS_ASSERT(
01224           !ReadScalar<voffset_t>(buf_.data() + field_location->id));
01225       WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
01226     }
01227     ClearOffsets();
01228     auto vt1 = reinterpret_cast<voffset_t *>(buf_.data());
01229     auto vt1_size = ReadScalar<voffset_t>(vt1);
01230     auto vt_use = GetSize();
01231     // See if we already have generated a vtable with this exact same
01232     // layout before. If so, make it point to the old one, remove this one.
01233     if (dedup_vtables_) {
01234       for (auto it = buf_.scratch_data(); it < buf_.scratch_end();
01235            it += sizeof(uoffset_t)) {
01236         auto vt_offset_ptr = reinterpret_cast<uoffset_t *>(it);
01237         auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*vt_offset_ptr));
01238         auto vt2_size = *vt2;
01239         if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size)) continue;
01240         vt_use = *vt_offset_ptr;
01241         buf_.pop(GetSize() - vtableoffsetloc);
01242         break;
01243       }
01244     }
01245     // If this is a new vtable, remember it.
01246     if (vt_use == GetSize()) { buf_.scratch_push_small(vt_use); }
01247     // Fill the vtable offset we created above.
01248     // The offset points from the beginning of the object to where the
01249     // vtable is stored.
01250     // Offsets default direction is downward in memory for future format
01251     // flexibility (storing all vtables at the start of the file).
01252     WriteScalar(buf_.data_at(vtableoffsetloc),
01253                 static_cast<soffset_t>(vt_use) -
01254                     static_cast<soffset_t>(vtableoffsetloc));
01255 
01256     nested = false;
01257     return vtableoffsetloc;
01258   }
01259 
01260   FLATBUFFERS_ATTRIBUTE(deprecated("call the version above instead"))
01261   uoffset_t EndTable(uoffset_t start, voffset_t /*numfields*/) {
01262     return EndTable(start);
01263   }
01264 
01265   // This checks a required field has been set in a given table that has
01266   // just been constructed.
01267   template<typename T> void Required(Offset<T> table, voffset_t field);
01268 
01269   uoffset_t StartStruct(size_t alignment) {
01270     Align(alignment);
01271     return GetSize();
01272   }
01273 
01274   uoffset_t EndStruct() { return GetSize(); }
01275 
01276   void ClearOffsets() {
01277     buf_.scratch_pop(num_field_loc * sizeof(FieldLoc));
01278     num_field_loc = 0;
01279     max_voffset_ = 0;
01280   }
01281 
01282   // Aligns such that when "len" bytes are written, an object can be written
01283   // after it with "alignment" without padding.
01284   void PreAlign(size_t len, size_t alignment) {
01285     TrackMinAlign(alignment);
01286     buf_.fill(PaddingBytes(GetSize() + len, alignment));
01287   }
01288   template<typename T> void PreAlign(size_t len) {
01289     AssertScalarT<T>();
01290     PreAlign(len, sizeof(T));
01291   }
01293 
01298   Offset<String> CreateString(const char *str, size_t len) {
01299     NotNested();
01300     PreAlign<uoffset_t>(len + 1);  // Always 0-terminated.
01301     buf_.fill(1);
01302     PushBytes(reinterpret_cast<const uint8_t *>(str), len);
01303     PushElement(static_cast<uoffset_t>(len));
01304     return Offset<String>(GetSize());
01305   }
01306 
01310   Offset<String> CreateString(const char *str) {
01311     return CreateString(str, strlen(str));
01312   }
01313 
01317   Offset<String> CreateString(char *str) {
01318     return CreateString(str, strlen(str));
01319   }
01320 
01324   Offset<String> CreateString(const std::string &str) {
01325     return CreateString(str.c_str(), str.length());
01326   }
01327 
01328   // clang-format off
01329   #ifdef FLATBUFFERS_HAS_STRING_VIEW
01330 
01331 
01332 
01333   Offset<String> CreateString(flatbuffers::string_view str) {
01334     return CreateString(str.data(), str.size());
01335   }
01336   #endif // FLATBUFFERS_HAS_STRING_VIEW
01337   // clang-format on
01338 
01342   Offset<String> CreateString(const String *str) {
01343     return str ? CreateString(str->c_str(), str->size()) : 0;
01344   }
01345 
01350   template<typename T> Offset<String> CreateString(const T &str) {
01351     return CreateString(str.c_str(), str.length());
01352   }
01353 
01360   Offset<String> CreateSharedString(const char *str, size_t len) {
01361     if (!string_pool)
01362       string_pool = new StringOffsetMap(StringOffsetCompare(buf_));
01363     auto size_before_string = buf_.size();
01364     // Must first serialize the string, since the set is all offsets into
01365     // buffer.
01366     auto off = CreateString(str, len);
01367     auto it = string_pool->find(off);
01368     // If it exists we reuse existing serialized data!
01369     if (it != string_pool->end()) {
01370       // We can remove the string we serialized.
01371       buf_.pop(buf_.size() - size_before_string);
01372       return *it;
01373     }
01374     // Record this string for future use.
01375     string_pool->insert(off);
01376     return off;
01377   }
01378 
01384   Offset<String> CreateSharedString(const char *str) {
01385     return CreateSharedString(str, strlen(str));
01386   }
01387 
01393   Offset<String> CreateSharedString(const std::string &str) {
01394     return CreateSharedString(str.c_str(), str.length());
01395   }
01396 
01402   Offset<String> CreateSharedString(const String *str) {
01403     return CreateSharedString(str->c_str(), str->size());
01404   }
01405 
01407   uoffset_t EndVector(size_t len) {
01408     FLATBUFFERS_ASSERT(nested);  // Hit if no corresponding StartVector.
01409     nested = false;
01410     return PushElement(static_cast<uoffset_t>(len));
01411   }
01412 
01413   void StartVector(size_t len, size_t elemsize) {
01414     NotNested();
01415     nested = true;
01416     PreAlign<uoffset_t>(len * elemsize);
01417     PreAlign(len * elemsize, elemsize);  // Just in case elemsize > uoffset_t.
01418   }
01419 
01420   // Call this right before StartVector/CreateVector if you want to force the
01421   // alignment to be something different than what the element size would
01422   // normally dictate.
01423   // This is useful when storing a nested_flatbuffer in a vector of bytes,
01424   // or when storing SIMD floats, etc.
01425   void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment) {
01426     PreAlign(len * elemsize, alignment);
01427   }
01428 
01429   // Similar to ForceVectorAlignment but for String fields.
01430   void ForceStringAlignment(size_t len, size_t alignment) {
01431     PreAlign((len + 1) * sizeof(char), alignment);
01432   }
01433 
01435 
01443   template<typename T> Offset<Vector<T>> CreateVector(const T *v, size_t len) {
01444     // If this assert hits, you're specifying a template argument that is
01445     // causing the wrong overload to be selected, remove it.
01446     AssertScalarT<T>();
01447     StartVector(len, sizeof(T));
01448     // clang-format off
01449     #if FLATBUFFERS_LITTLEENDIAN
01450       PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T));
01451     #else
01452       if (sizeof(T) == 1) {
01453         PushBytes(reinterpret_cast<const uint8_t *>(v), len);
01454       } else {
01455         for (auto i = len; i > 0; ) {
01456           PushElement(v[--i]);
01457         }
01458       }
01459     #endif
01460     // clang-format on
01461     return Offset<Vector<T>>(EndVector(len));
01462   }
01463 
01464   template<typename T>
01465   Offset<Vector<Offset<T>>> CreateVector(const Offset<T> *v, size_t len) {
01466     StartVector(len, sizeof(Offset<T>));
01467     for (auto i = len; i > 0;) { PushElement(v[--i]); }
01468     return Offset<Vector<Offset<T>>>(EndVector(len));
01469   }
01470 
01477   template<typename T> Offset<Vector<T>> CreateVector(const std::vector<T> &v) {
01478     return CreateVector(data(v), v.size());
01479   }
01480 
01481   // vector<bool> may be implemented using a bit-set, so we can't access it as
01482   // an array. Instead, read elements manually.
01483   // Background: https://isocpp.org/blog/2012/11/on-vectorbool
01484   Offset<Vector<uint8_t>> CreateVector(const std::vector<bool> &v) {
01485     StartVector(v.size(), sizeof(uint8_t));
01486     for (auto i = v.size(); i > 0;) {
01487       PushElement(static_cast<uint8_t>(v[--i]));
01488     }
01489     return Offset<Vector<uint8_t>>(EndVector(v.size()));
01490   }
01491 
01492   // clang-format off
01493   #ifndef FLATBUFFERS_CPP98_STL
01494 
01495 
01496 
01497 
01498 
01499 
01500 
01501   template<typename T> Offset<Vector<T>> CreateVector(size_t vector_size,
01502       const std::function<T (size_t i)> &f) {
01503     std::vector<T> elems(vector_size);
01504     for (size_t i = 0; i < vector_size; i++) elems[i] = f(i);
01505     return CreateVector(elems);
01506   }
01507   #endif
01508   // clang-format on
01509 
01519   template<typename T, typename F, typename S>
01520   Offset<Vector<T>> CreateVector(size_t vector_size, F f, S *state) {
01521     std::vector<T> elems(vector_size);
01522     for (size_t i = 0; i < vector_size; i++) elems[i] = f(i, state);
01523     return CreateVector(elems);
01524   }
01525 
01532   Offset<Vector<Offset<String>>> CreateVectorOfStrings(
01533       const std::vector<std::string> &v) {
01534     std::vector<Offset<String>> offsets(v.size());
01535     for (size_t i = 0; i < v.size(); i++) offsets[i] = CreateString(v[i]);
01536     return CreateVector(offsets);
01537   }
01538 
01546   template<typename T>
01547   Offset<Vector<const T *>> CreateVectorOfStructs(const T *v, size_t len) {
01548     StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>());
01549     PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
01550     return Offset<Vector<const T *>>(EndVector(len));
01551   }
01552 
01561   template<typename T, typename S>
01562   Offset<Vector<const T *>> CreateVectorOfNativeStructs(const S *v,
01563                                                         size_t len) {
01564     extern T Pack(const S &);
01565     typedef T (*Pack_t)(const S &);
01566     std::vector<T> vv(len);
01567     std::transform(v, v + len, vv.begin(), static_cast<Pack_t&>(Pack));
01568     return CreateVectorOfStructs<T>(vv.data(), vv.size());
01569   }
01570 
01571   // clang-format off
01572   #ifndef FLATBUFFERS_CPP98_STL
01573 
01574 
01575 
01576 
01577 
01578 
01579 
01580 
01581   template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
01582       size_t vector_size, const std::function<void(size_t i, T *)> &filler) {
01583     T* structs = StartVectorOfStructs<T>(vector_size);
01584     for (size_t i = 0; i < vector_size; i++) {
01585       filler(i, structs);
01586       structs++;
01587     }
01588     return EndVectorOfStructs<T>(vector_size);
01589   }
01590   #endif
01591   // clang-format on
01592 
01602   template<typename T, typename F, typename S>
01603   Offset<Vector<const T *>> CreateVectorOfStructs(size_t vector_size, F f,
01604                                                   S *state) {
01605     T *structs = StartVectorOfStructs<T>(vector_size);
01606     for (size_t i = 0; i < vector_size; i++) {
01607       f(i, structs, state);
01608       structs++;
01609     }
01610     return EndVectorOfStructs<T>(vector_size);
01611   }
01612 
01619   template<typename T, typename Alloc>
01620   Offset<Vector<const T *>> CreateVectorOfStructs(
01621       const std::vector<T, Alloc> &v) {
01622     return CreateVectorOfStructs(data(v), v.size());
01623   }
01624 
01633   template<typename T, typename S>
01634   Offset<Vector<const T *>> CreateVectorOfNativeStructs(
01635       const std::vector<S> &v) {
01636     return CreateVectorOfNativeStructs<T, S>(data(v), v.size());
01637   }
01638 
01640   template<typename T> struct StructKeyComparator {
01641     bool operator()(const T &a, const T &b) const {
01642       return a.KeyCompareLessThan(&b);
01643     }
01644 
01645    private:
01646     StructKeyComparator &operator=(const StructKeyComparator &);
01647   };
01649 
01657   template<typename T>
01658   Offset<Vector<const T *>> CreateVectorOfSortedStructs(std::vector<T> *v) {
01659     return CreateVectorOfSortedStructs(data(*v), v->size());
01660   }
01661 
01670   template<typename T, typename S>
01671   Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(
01672       std::vector<S> *v) {
01673     return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size());
01674   }
01675 
01684   template<typename T>
01685   Offset<Vector<const T *>> CreateVectorOfSortedStructs(T *v, size_t len) {
01686     std::sort(v, v + len, StructKeyComparator<T>());
01687     return CreateVectorOfStructs(v, len);
01688   }
01689 
01699   template<typename T, typename S>
01700   Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(S *v,
01701                                                               size_t len) {
01702     extern T Pack(const S &);
01703     typedef T (*Pack_t)(const S &);
01704     std::vector<T> vv(len);
01705     std::transform(v, v + len, vv.begin(), static_cast<Pack_t&>(Pack));
01706     return CreateVectorOfSortedStructs<T>(vv, len);
01707   }
01708 
01710   template<typename T> struct TableKeyComparator {
01711     TableKeyComparator(vector_downward &buf) : buf_(buf) {}
01712     bool operator()(const Offset<T> &a, const Offset<T> &b) const {
01713       auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o));
01714       auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o));
01715       return table_a->KeyCompareLessThan(table_b);
01716     }
01717     vector_downward &buf_;
01718 
01719    private:
01720     TableKeyComparator &operator=(const TableKeyComparator &);
01721   };
01723 
01732   template<typename T>
01733   Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(Offset<T> *v,
01734                                                        size_t len) {
01735     std::sort(v, v + len, TableKeyComparator<T>(buf_));
01736     return CreateVector(v, len);
01737   }
01738 
01746   template<typename T>
01747   Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
01748       std::vector<Offset<T>> *v) {
01749     return CreateVectorOfSortedTables(data(*v), v->size());
01750   }
01751 
01759   uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
01760                                       uint8_t **buf) {
01761     NotNested();
01762     StartVector(len, elemsize);
01763     buf_.make_space(len * elemsize);
01764     auto vec_start = GetSize();
01765     auto vec_end = EndVector(len);
01766     *buf = buf_.data_at(vec_start);
01767     return vec_end;
01768   }
01769 
01778   template<typename T>
01779   Offset<Vector<T>> CreateUninitializedVector(size_t len, T **buf) {
01780     AssertScalarT<T>();
01781     return CreateUninitializedVector(len, sizeof(T),
01782                                      reinterpret_cast<uint8_t **>(buf));
01783   }
01784 
01785   template<typename T>
01786   Offset<Vector<const T*>> CreateUninitializedVectorOfStructs(size_t len, T **buf) {
01787     return CreateUninitializedVector(len, sizeof(T),
01788                                      reinterpret_cast<uint8_t **>(buf));
01789   }
01790 
01791 
01792   // @brief Create a vector of scalar type T given as input a vector of scalar
01793   // type U, useful with e.g. pre "enum class" enums, or any existing scalar
01794   // data of the wrong type.
01795   template<typename T, typename U>
01796   Offset<Vector<T>> CreateVectorScalarCast(const U *v, size_t len) {
01797     AssertScalarT<T>();
01798     AssertScalarT<U>();
01799     StartVector(len, sizeof(T));
01800     for (auto i = len; i > 0;) { PushElement(static_cast<T>(v[--i])); }
01801     return Offset<Vector<T>>(EndVector(len));
01802   }
01803 
01805   template<typename T> Offset<const T *> CreateStruct(const T &structobj) {
01806     NotNested();
01807     Align(AlignOf<T>());
01808     buf_.push_small(structobj);
01809     return Offset<const T *>(GetSize());
01810   }
01811 
01813   static const size_t kFileIdentifierLength = 4;
01814 
01818   template<typename T>
01819   void Finish(Offset<T> root, const char *file_identifier = nullptr) {
01820     Finish(root.o, file_identifier, false);
01821   }
01822 
01830   template<typename T>
01831   void FinishSizePrefixed(Offset<T> root,
01832                           const char *file_identifier = nullptr) {
01833     Finish(root.o, file_identifier, true);
01834   }
01835 
01836   void SwapBufAllocator(FlatBufferBuilder &other) {
01837     buf_.swap_allocator(other.buf_);
01838   }
01839 
01840 protected:
01841 
01842   // You shouldn't really be copying instances of this class.
01843   FlatBufferBuilder(const FlatBufferBuilder &);
01844   FlatBufferBuilder &operator=(const FlatBufferBuilder &);
01845 
01846   void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) {
01847     NotNested();
01848     buf_.clear_scratch();
01849     // This will cause the whole buffer to be aligned.
01850     PreAlign((size_prefix ? sizeof(uoffset_t) : 0) + sizeof(uoffset_t) +
01851                  (file_identifier ? kFileIdentifierLength : 0),
01852              minalign_);
01853     if (file_identifier) {
01854       FLATBUFFERS_ASSERT(strlen(file_identifier) == kFileIdentifierLength);
01855       PushBytes(reinterpret_cast<const uint8_t *>(file_identifier),
01856                 kFileIdentifierLength);
01857     }
01858     PushElement(ReferTo(root));  // Location of root.
01859     if (size_prefix) { PushElement(GetSize()); }
01860     finished = true;
01861   }
01862 
01863   struct FieldLoc {
01864     uoffset_t off;
01865     voffset_t id;
01866   };
01867 
01868   vector_downward buf_;
01869 
01870   // Accumulating offsets of table members while it is being built.
01871   // We store these in the scratch pad of buf_, after the vtable offsets.
01872   uoffset_t num_field_loc;
01873   // Track how much of the vtable is in use, so we can output the most compact
01874   // possible vtable.
01875   voffset_t max_voffset_;
01876 
01877   // Ensure objects are not nested.
01878   bool nested;
01879 
01880   // Ensure the buffer is finished before it is being accessed.
01881   bool finished;
01882 
01883   size_t minalign_;
01884 
01885   bool force_defaults_;  // Serialize values equal to their defaults anyway.
01886 
01887   bool dedup_vtables_;
01888 
01889   struct StringOffsetCompare {
01890     StringOffsetCompare(const vector_downward &buf) : buf_(&buf) {}
01891     bool operator()(const Offset<String> &a, const Offset<String> &b) const {
01892       auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o));
01893       auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o));
01894       return StringLessThan(stra->data(), stra->size(),
01895                             strb->data(), strb->size());
01896     }
01897     const vector_downward *buf_;
01898   };
01899 
01900   // For use with CreateSharedString. Instantiated on first use only.
01901   typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
01902   StringOffsetMap *string_pool;
01903 
01904  private:
01905   // Allocates space for a vector of structures.
01906   // Must be completed with EndVectorOfStructs().
01907   template<typename T> T *StartVectorOfStructs(size_t vector_size) {
01908     StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>());
01909     return reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T)));
01910   }
01911 
01912   // End the vector of structues in the flatbuffers.
01913   // Vector should have previously be started with StartVectorOfStructs().
01914   template<typename T>
01915   Offset<Vector<const T *>> EndVectorOfStructs(size_t vector_size) {
01916     return Offset<Vector<const T *>>(EndVector(vector_size));
01917   }
01918 };
01920 
01922 // Helpers to get a typed pointer to the root object contained in the buffer.
01923 template<typename T> T *GetMutableRoot(void *buf) {
01924   EndianCheck();
01925   return reinterpret_cast<T *>(
01926       reinterpret_cast<uint8_t *>(buf) +
01927       EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
01928 }
01929 
01930 template<typename T> const T *GetRoot(const void *buf) {
01931   return GetMutableRoot<T>(const_cast<void *>(buf));
01932 }
01933 
01934 template<typename T> const T *GetSizePrefixedRoot(const void *buf) {
01935   return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(uoffset_t));
01936 }
01937 
01941 template<typename T>
01942 T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
01943   return reinterpret_cast<T *>(fbb.GetCurrentBufferPointer() + fbb.GetSize() -
01944                                offset.o);
01945 }
01946 
01947 template<typename T>
01948 const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
01949   return GetMutableTemporaryPointer<T>(fbb, offset);
01950 }
01951 
01959 inline const char *GetBufferIdentifier(const void *buf, bool size_prefixed = false) {
01960   return reinterpret_cast<const char *>(buf) +
01961          ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t));
01962 }
01963 
01964 // Helper to see if the identifier in a buffer has the expected value.
01965 inline bool BufferHasIdentifier(const void *buf, const char *identifier, bool size_prefixed = false) {
01966   return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier,
01967                  FlatBufferBuilder::kFileIdentifierLength) == 0;
01968 }
01969 
01970 // Helper class to verify the integrity of a FlatBuffer
01971 class Verifier FLATBUFFERS_FINAL_CLASS {
01972  public:
01973   Verifier(const uint8_t *buf, size_t buf_len, uoffset_t _max_depth = 64,
01974            uoffset_t _max_tables = 1000000, bool _check_alignment = true)
01975       : buf_(buf),
01976         size_(buf_len),
01977         depth_(0),
01978         max_depth_(_max_depth),
01979         num_tables_(0),
01980         max_tables_(_max_tables)
01981   // clang-format off
01982     #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
01983         , upper_bound_(0)
01984     #endif
01985         , check_alignment_(_check_alignment)
01986   // clang-format on
01987   {
01988     FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
01989   }
01990 
01991   // Central location where any verification failures register.
01992   bool Check(bool ok) const {
01993     // clang-format off
01994     #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
01995       FLATBUFFERS_ASSERT(ok);
01996     #endif
01997     #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
01998       if (!ok)
01999         upper_bound_ = 0;
02000     #endif
02001     // clang-format on
02002     return ok;
02003   }
02004 
02005   // Verify any range within the buffer.
02006   bool Verify(size_t elem, size_t elem_len) const {
02007     // clang-format off
02008     #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
02009       auto upper_bound = elem + elem_len;
02010       if (upper_bound_ < upper_bound)
02011         upper_bound_ =  upper_bound;
02012     #endif
02013     // clang-format on
02014     return Check(elem_len < size_ && elem <= size_ - elem_len);
02015   }
02016 
02017   template<typename T> bool VerifyAlignment(size_t elem) const {
02018     return (elem & (sizeof(T) - 1)) == 0 || !check_alignment_;
02019   }
02020 
02021   // Verify a range indicated by sizeof(T).
02022   template<typename T> bool Verify(size_t elem) const {
02023     return VerifyAlignment<T>(elem) && Verify(elem, sizeof(T));
02024   }
02025 
02026   // Verify relative to a known-good base pointer.
02027   bool Verify(const uint8_t *base, voffset_t elem_off, size_t elem_len) const {
02028     return Verify(static_cast<size_t>(base - buf_) + elem_off, elem_len);
02029   }
02030 
02031   template<typename T> bool Verify(const uint8_t *base, voffset_t elem_off)
02032       const {
02033     return Verify(static_cast<size_t>(base - buf_) + elem_off, sizeof(T));
02034   }
02035 
02036   // Verify a pointer (may be NULL) of a table type.
02037   template<typename T> bool VerifyTable(const T *table) {
02038     return !table || table->Verify(*this);
02039   }
02040 
02041   // Verify a pointer (may be NULL) of any vector type.
02042   template<typename T> bool VerifyVector(const Vector<T> *vec) const {
02043     return !vec || VerifyVectorOrString(reinterpret_cast<const uint8_t *>(vec),
02044                                         sizeof(T));
02045   }
02046 
02047   // Verify a pointer (may be NULL) of a vector to struct.
02048   template<typename T> bool VerifyVector(const Vector<const T *> *vec) const {
02049     return VerifyVector(reinterpret_cast<const Vector<T> *>(vec));
02050   }
02051 
02052   // Verify a pointer (may be NULL) to string.
02053   bool VerifyString(const String *str) const {
02054     size_t end;
02055     return !str ||
02056            (VerifyVectorOrString(reinterpret_cast<const uint8_t *>(str),
02057                                  1, &end) &&
02058             Verify(end, 1) &&      // Must have terminator
02059             Check(buf_[end] == '\0'));  // Terminating byte must be 0.
02060   }
02061 
02062   // Common code between vectors and strings.
02063   bool VerifyVectorOrString(const uint8_t *vec, size_t elem_size,
02064                     size_t *end = nullptr) const {
02065     auto veco = static_cast<size_t>(vec - buf_);
02066     // Check we can read the size field.
02067     if (!Verify<uoffset_t>(veco)) return false;
02068     // Check the whole array. If this is a string, the byte past the array
02069     // must be 0.
02070     auto size = ReadScalar<uoffset_t>(vec);
02071     auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
02072     if (!Check(size < max_elems))
02073       return false;  // Protect against byte_size overflowing.
02074     auto byte_size = sizeof(size) + elem_size * size;
02075     if (end) *end = veco + byte_size;
02076     return Verify(veco, byte_size);
02077   }
02078 
02079   // Special case for string contents, after the above has been called.
02080   bool VerifyVectorOfStrings(const Vector<Offset<String>> *vec) const {
02081     if (vec) {
02082       for (uoffset_t i = 0; i < vec->size(); i++) {
02083         if (!VerifyString(vec->Get(i))) return false;
02084       }
02085     }
02086     return true;
02087   }
02088 
02089   // Special case for table contents, after the above has been called.
02090   template<typename T> bool VerifyVectorOfTables(const Vector<Offset<T>> *vec) {
02091     if (vec) {
02092       for (uoffset_t i = 0; i < vec->size(); i++) {
02093         if (!vec->Get(i)->Verify(*this)) return false;
02094       }
02095     }
02096     return true;
02097   }
02098 
02099   bool VerifyTableStart(const uint8_t *table) {
02100     // Check the vtable offset.
02101     auto tableo = static_cast<size_t>(table - buf_);
02102     if (!Verify<soffset_t>(tableo)) return false;
02103     // This offset may be signed, but doing the substraction unsigned always
02104     // gives the result we want.
02105     auto vtableo = tableo - static_cast<size_t>(ReadScalar<soffset_t>(table));
02106     // Check the vtable size field, then check vtable fits in its entirety.
02107     return VerifyComplexity() && Verify<voffset_t>(vtableo) &&
02108            VerifyAlignment<voffset_t>(ReadScalar<voffset_t>(buf_ + vtableo)) &&
02109            Verify(vtableo, ReadScalar<voffset_t>(buf_ + vtableo));
02110   }
02111 
02112   template<typename T>
02113   bool VerifyBufferFromStart(const char *identifier, size_t start) {
02114     if (identifier &&
02115         (size_ < 2 * sizeof(flatbuffers::uoffset_t) ||
02116          !BufferHasIdentifier(buf_ + start, identifier))) {
02117       return false;
02118     }
02119 
02120     // Call T::Verify, which must be in the generated code for this type.
02121     auto o = VerifyOffset(start);
02122     return o && reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this)
02123     // clang-format off
02124     #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
02125            && GetComputedSize()
02126     #endif
02127         ;
02128     // clang-format on
02129   }
02130 
02131   // Verify this whole buffer, starting with root type T.
02132   template<typename T> bool VerifyBuffer() { return VerifyBuffer<T>(nullptr); }
02133 
02134   template<typename T> bool VerifyBuffer(const char *identifier) {
02135     return VerifyBufferFromStart<T>(identifier, 0);
02136   }
02137 
02138   template<typename T> bool VerifySizePrefixedBuffer(const char *identifier) {
02139     return Verify<uoffset_t>(0U) &&
02140            ReadScalar<uoffset_t>(buf_) == size_ - sizeof(uoffset_t) &&
02141            VerifyBufferFromStart<T>(identifier, sizeof(uoffset_t));
02142   }
02143 
02144   uoffset_t VerifyOffset(size_t start) const {
02145     if (!Verify<uoffset_t>(start)) return 0;
02146     auto o = ReadScalar<uoffset_t>(buf_ + start);
02147     // May not point to itself.
02148     if (!Check(o != 0)) return 0;
02149     // Can't wrap around / buffers are max 2GB.
02150     if (!Check(static_cast<soffset_t>(o) >= 0)) return 0;
02151     // Must be inside the buffer to create a pointer from it (pointer outside
02152     // buffer is UB).
02153     if (!Verify(start + o, 1)) return 0;
02154     return o;
02155   }
02156 
02157   uoffset_t VerifyOffset(const uint8_t *base, voffset_t start) const {
02158     return VerifyOffset(static_cast<size_t>(base - buf_) + start);
02159   }
02160 
02161   // Called at the start of a table to increase counters measuring data
02162   // structure depth and amount, and possibly bails out with false if
02163   // limits set by the constructor have been hit. Needs to be balanced
02164   // with EndTable().
02165   bool VerifyComplexity() {
02166     depth_++;
02167     num_tables_++;
02168     return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_);
02169   }
02170 
02171   // Called at the end of a table to pop the depth count.
02172   bool EndTable() {
02173     depth_--;
02174     return true;
02175   }
02176 
02177   // clang-format off
02178   #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
02179   // Returns the message size in bytes
02180   size_t GetComputedSize() const {
02181     uintptr_t size = upper_bound_;
02182     // Align the size to uoffset_t
02183     size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
02184     return (size > size_) ?  0 : size;
02185   }
02186   #endif
02187   // clang-format on
02188 
02189  private:
02190   const uint8_t *buf_;
02191   size_t size_;
02192   uoffset_t depth_;
02193   uoffset_t max_depth_;
02194   uoffset_t num_tables_;
02195   uoffset_t max_tables_;
02196   // clang-format off
02197   #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
02198     mutable size_t upper_bound_;
02199   #endif
02200   // clang-format on
02201   bool check_alignment_;
02202 };
02203 
02204 // Convenient way to bundle a buffer and its length, to pass it around
02205 // typed by its root.
02206 // A BufferRef does not own its buffer.
02207 struct BufferRefBase {};  // for std::is_base_of
02208 template<typename T> struct BufferRef : BufferRefBase {
02209   BufferRef() : buf(nullptr), len(0), must_free(false) {}
02210   BufferRef(uint8_t *_buf, uoffset_t _len)
02211       : buf(_buf), len(_len), must_free(false) {}
02212 
02213   ~BufferRef() {
02214     if (must_free) free(buf);
02215   }
02216 
02217   const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); }
02218 
02219   bool Verify() {
02220     Verifier verifier(buf, len);
02221     return verifier.VerifyBuffer<T>(nullptr);
02222   }
02223 
02224   uint8_t *buf;
02225   uoffset_t len;
02226   bool must_free;
02227 };
02228 
02229 // "structs" are flat structures that do not have an offset table, thus
02230 // always have all members present and do not support forwards/backwards
02231 // compatible extensions.
02232 
02233 class Struct FLATBUFFERS_FINAL_CLASS {
02234  public:
02235   template<typename T> T GetField(uoffset_t o) const {
02236     return ReadScalar<T>(&data_[o]);
02237   }
02238 
02239   template<typename T> T GetStruct(uoffset_t o) const {
02240     return reinterpret_cast<T>(&data_[o]);
02241   }
02242 
02243   const uint8_t *GetAddressOf(uoffset_t o) const { return &data_[o]; }
02244   uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; }
02245 
02246  private:
02247   uint8_t data_[1];
02248 };
02249 
02250 // "tables" use an offset table (possibly shared) that allows fields to be
02251 // omitted and added at will, but uses an extra indirection to read.
02252 class Table {
02253  public:
02254   const uint8_t *GetVTable() const {
02255     return data_ - ReadScalar<soffset_t>(data_);
02256   }
02257 
02258   // This gets the field offset for any of the functions below it, or 0
02259   // if the field was not present.
02260   voffset_t GetOptionalFieldOffset(voffset_t field) const {
02261     // The vtable offset is always at the start.
02262     auto vtable = GetVTable();
02263     // The first element is the size of the vtable (fields + type id + itself).
02264     auto vtsize = ReadScalar<voffset_t>(vtable);
02265     // If the field we're accessing is outside the vtable, we're reading older
02266     // data, so it's the same as if the offset was 0 (not present).
02267     return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
02268   }
02269 
02270   template<typename T> T GetField(voffset_t field, T defaultval) const {
02271     auto field_offset = GetOptionalFieldOffset(field);
02272     return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
02273   }
02274 
02275   template<typename P> P GetPointer(voffset_t field) {
02276     auto field_offset = GetOptionalFieldOffset(field);
02277     auto p = data_ + field_offset;
02278     return field_offset ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p))
02279                         : nullptr;
02280   }
02281   template<typename P> P GetPointer(voffset_t field) const {
02282     return const_cast<Table *>(this)->GetPointer<P>(field);
02283   }
02284 
02285   template<typename P> P GetStruct(voffset_t field) const {
02286     auto field_offset = GetOptionalFieldOffset(field);
02287     auto p = const_cast<uint8_t *>(data_ + field_offset);
02288     return field_offset ? reinterpret_cast<P>(p) : nullptr;
02289   }
02290 
02291   template<typename T> bool SetField(voffset_t field, T val, T def) {
02292     auto field_offset = GetOptionalFieldOffset(field);
02293     if (!field_offset) return IsTheSameAs(val, def);
02294     WriteScalar(data_ + field_offset, val);
02295     return true;
02296   }
02297 
02298   bool SetPointer(voffset_t field, const uint8_t *val) {
02299     auto field_offset = GetOptionalFieldOffset(field);
02300     if (!field_offset) return false;
02301     WriteScalar(data_ + field_offset,
02302                 static_cast<uoffset_t>(val - (data_ + field_offset)));
02303     return true;
02304   }
02305 
02306   uint8_t *GetAddressOf(voffset_t field) {
02307     auto field_offset = GetOptionalFieldOffset(field);
02308     return field_offset ? data_ + field_offset : nullptr;
02309   }
02310   const uint8_t *GetAddressOf(voffset_t field) const {
02311     return const_cast<Table *>(this)->GetAddressOf(field);
02312   }
02313 
02314   bool CheckField(voffset_t field) const {
02315     return GetOptionalFieldOffset(field) != 0;
02316   }
02317 
02318   // Verify the vtable of this table.
02319   // Call this once per table, followed by VerifyField once per field.
02320   bool VerifyTableStart(Verifier &verifier) const {
02321     return verifier.VerifyTableStart(data_);
02322   }
02323 
02324   // Verify a particular field.
02325   template<typename T>
02326   bool VerifyField(const Verifier &verifier, voffset_t field) const {
02327     // Calling GetOptionalFieldOffset should be safe now thanks to
02328     // VerifyTable().
02329     auto field_offset = GetOptionalFieldOffset(field);
02330     // Check the actual field.
02331     return !field_offset || verifier.Verify<T>(data_, field_offset);
02332   }
02333 
02334   // VerifyField for required fields.
02335   template<typename T>
02336   bool VerifyFieldRequired(const Verifier &verifier, voffset_t field) const {
02337     auto field_offset = GetOptionalFieldOffset(field);
02338     return verifier.Check(field_offset != 0) &&
02339            verifier.Verify<T>(data_, field_offset);
02340   }
02341 
02342   // Versions for offsets.
02343   bool VerifyOffset(const Verifier &verifier, voffset_t field) const {
02344     auto field_offset = GetOptionalFieldOffset(field);
02345     return !field_offset || verifier.VerifyOffset(data_, field_offset);
02346   }
02347 
02348   bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const {
02349     auto field_offset = GetOptionalFieldOffset(field);
02350     return verifier.Check(field_offset != 0) &&
02351            verifier.VerifyOffset(data_, field_offset);
02352   }
02353 
02354  private:
02355   // private constructor & copy constructor: you obtain instances of this
02356   // class by pointing to existing data only
02357   Table();
02358   Table(const Table &other);
02359 
02360   uint8_t data_[1];
02361 };
02362 
02363 template<typename T> void FlatBufferBuilder::Required(Offset<T> table,
02364                                                       voffset_t field) {
02365   auto table_ptr = reinterpret_cast<const Table *>(buf_.data_at(table.o));
02366   bool ok = table_ptr->GetOptionalFieldOffset(field) != 0;
02367   // If this fails, the caller will show what field needs to be set.
02368   FLATBUFFERS_ASSERT(ok);
02369   (void)ok;
02370 }
02371 
02376 inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
02377   auto table = reinterpret_cast<const Table *>(root);
02378   auto vtable = table->GetVTable();
02379   // Either the vtable is before the root or after the root.
02380   auto start = (std::min)(vtable, reinterpret_cast<const uint8_t *>(root));
02381   // Align to at least sizeof(uoffset_t).
02382   start = reinterpret_cast<const uint8_t *>(reinterpret_cast<uintptr_t>(start) &
02383                                             ~(sizeof(uoffset_t) - 1));
02384   // Additionally, there may be a file_identifier in the buffer, and the root
02385   // offset. The buffer may have been aligned to any size between
02386   // sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align").
02387   // Sadly, the exact alignment is only known when constructing the buffer,
02388   // since it depends on the presence of values with said alignment properties.
02389   // So instead, we simply look at the next uoffset_t values (root,
02390   // file_identifier, and alignment padding) to see which points to the root.
02391   // None of the other values can "impersonate" the root since they will either
02392   // be 0 or four ASCII characters.
02393   static_assert(FlatBufferBuilder::kFileIdentifierLength == sizeof(uoffset_t),
02394                 "file_identifier is assumed to be the same size as uoffset_t");
02395   for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1;
02396        possible_roots; possible_roots--) {
02397     start -= sizeof(uoffset_t);
02398     if (ReadScalar<uoffset_t>(start) + start ==
02399         reinterpret_cast<const uint8_t *>(root))
02400       return start;
02401   }
02402   // We didn't find the root, either the "root" passed isn't really a root,
02403   // or the buffer is corrupt.
02404   // Assert, because calling this function with bad data may cause reads
02405   // outside of buffer boundaries.
02406   FLATBUFFERS_ASSERT(false);
02407   return nullptr;
02408 }
02409 
02411 inline uoffset_t GetPrefixedSize(const uint8_t* buf){ return ReadScalar<uoffset_t>(buf); }
02412 
02413 // Base class for native objects (FlatBuffer data de-serialized into native
02414 // C++ data structures).
02415 // Contains no functionality, purely documentative.
02416 struct NativeTable {};
02417 
02426 typedef uint64_t hash_value_t;
02427 // clang-format off
02428 #ifdef FLATBUFFERS_CPP98_STL
02429   typedef void (*resolver_function_t)(void **pointer_adr, hash_value_t hash);
02430   typedef hash_value_t (*rehasher_function_t)(void *pointer);
02431 #else
02432   typedef std::function<void (void **pointer_adr, hash_value_t hash)>
02433           resolver_function_t;
02434   typedef std::function<hash_value_t (void *pointer)> rehasher_function_t;
02435 #endif
02436 // clang-format on
02437 
02438 // Helper function to test if a field is present, using any of the field
02439 // enums in the generated code.
02440 // `table` must be a generated table type. Since this is a template parameter,
02441 // this is not typechecked to be a subclass of Table, so beware!
02442 // Note: this function will return false for fields equal to the default
02443 // value, since they're not stored in the buffer (unless force_defaults was
02444 // used).
02445 template<typename T>
02446 bool IsFieldPresent(const T *table, typename T::FlatBuffersVTableOffset field) {
02447   // Cast, since Table is a private baseclass of any table types.
02448   return reinterpret_cast<const Table *>(table)->CheckField(
02449       static_cast<voffset_t>(field));
02450 }
02451 
02452 // Utility function for reverse lookups on the EnumNames*() functions
02453 // (in the generated C++ code)
02454 // names must be NULL terminated.
02455 inline int LookupEnum(const char **names, const char *name) {
02456   for (const char **p = names; *p; p++)
02457     if (!strcmp(*p, name)) return static_cast<int>(p - names);
02458   return -1;
02459 }
02460 
02461 // These macros allow us to layout a struct with a guarantee that they'll end
02462 // up looking the same on different compilers and platforms.
02463 // It does this by disallowing the compiler to do any padding, and then
02464 // does padding itself by inserting extra padding fields that make every
02465 // element aligned to its own size.
02466 // Additionally, it manually sets the alignment of the struct as a whole,
02467 // which is typically its largest element, or a custom size set in the schema
02468 // by the force_align attribute.
02469 // These are used in the generated code only.
02470 
02471 // clang-format off
02472 #if defined(_MSC_VER)
02473   #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
02474     __pragma(pack(1)); \
02475     struct __declspec(align(alignment))
02476   #define FLATBUFFERS_STRUCT_END(name, size) \
02477     __pragma(pack()); \
02478     static_assert(sizeof(name) == size, "compiler breaks packing rules")
02479 #elif defined(__GNUC__) || defined(__clang__)
02480   #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
02481     _Pragma("pack(1)") \
02482     struct __attribute__((aligned(alignment)))
02483   #define FLATBUFFERS_STRUCT_END(name, size) \
02484     _Pragma("pack()") \
02485     static_assert(sizeof(name) == size, "compiler breaks packing rules")
02486 #else
02487   #error Unknown compiler, please define structure alignment macros
02488 #endif
02489 // clang-format on
02490 
02491 // Minimal reflection via code generation.
02492 // Besides full-fat reflection (see reflection.h) and parsing/printing by
02493 // loading schemas (see idl.h), we can also have code generation for mimimal
02494 // reflection data which allows pretty-printing and other uses without needing
02495 // a schema or a parser.
02496 // Generate code with --reflect-types (types only) or --reflect-names (names
02497 // also) to enable.
02498 // See minireflect.h for utilities using this functionality.
02499 
02500 // These types are organized slightly differently as the ones in idl.h.
02501 enum SequenceType { ST_TABLE, ST_STRUCT, ST_UNION, ST_ENUM };
02502 
02503 // Scalars have the same order as in idl.h
02504 // clang-format off
02505 #define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \
02506   ET(ET_UTYPE) \
02507   ET(ET_BOOL) \
02508   ET(ET_CHAR) \
02509   ET(ET_UCHAR) \
02510   ET(ET_SHORT) \
02511   ET(ET_USHORT) \
02512   ET(ET_INT) \
02513   ET(ET_UINT) \
02514   ET(ET_LONG) \
02515   ET(ET_ULONG) \
02516   ET(ET_FLOAT) \
02517   ET(ET_DOUBLE) \
02518   ET(ET_STRING) \
02519   ET(ET_SEQUENCE)  // See SequenceType.
02520 
02521 enum ElementaryType {
02522   #define FLATBUFFERS_ET(E) E,
02523     FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
02524   #undef FLATBUFFERS_ET
02525 };
02526 
02527 inline const char * const *ElementaryTypeNames() {
02528   static const char * const names[] = {
02529     #define FLATBUFFERS_ET(E) #E,
02530       FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
02531     #undef FLATBUFFERS_ET
02532   };
02533   return names;
02534 }
02535 // clang-format on
02536 
02537 // Basic type info cost just 16bits per field!
02538 struct TypeCode {
02539   uint16_t base_type : 4;  // ElementaryType
02540   uint16_t is_vector : 1;
02541   int16_t sequence_ref : 11;  // Index into type_refs below, or -1 for none.
02542 };
02543 
02544 static_assert(sizeof(TypeCode) == 2, "TypeCode");
02545 
02546 struct TypeTable;
02547 
02548 // Signature of the static method present in each type.
02549 typedef const TypeTable *(*TypeFunction)();
02550 
02551 struct TypeTable {
02552   SequenceType st;
02553   size_t num_elems;  // of type_codes, values, names (but not type_refs).
02554   const TypeCode *type_codes;  // num_elems count
02555   const TypeFunction *type_refs;  // less than num_elems entries (see TypeCode).
02556   const int64_t *values;  // Only set for non-consecutive enum/union or structs.
02557   const char * const *names;     // Only set if compiled with --reflect-names.
02558 };
02559 
02560 // String which identifies the current version of FlatBuffers.
02561 // flatbuffer_version_string is used by Google developers to identify which
02562 // applications uploaded to Google Play are using this library.  This allows
02563 // the development team at Google to determine the popularity of the library.
02564 // How it works: Applications that are uploaded to the Google Play Store are
02565 // scanned for this version string.  We track which applications are using it
02566 // to measure popularity.  You are free to remove it (of course) but we would
02567 // appreciate if you left it in.
02568 
02569 // Weak linkage is culled by VS & doesn't work on cygwin.
02570 // clang-format off
02571 #if !defined(_WIN32) && !defined(__CYGWIN__)
02572 
02573 extern volatile __attribute__((weak)) const char *flatbuffer_version_string;
02574 volatile __attribute__((weak)) const char *flatbuffer_version_string =
02575   "FlatBuffers "
02576   FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
02577   FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
02578   FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
02579 
02580 #endif  // !defined(_WIN32) && !defined(__CYGWIN__)
02581 
02582 #define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\
02583     inline E operator | (E lhs, E rhs){\
02584         return E(T(lhs) | T(rhs));\
02585     }\
02586     inline E operator & (E lhs, E rhs){\
02587         return E(T(lhs) & T(rhs));\
02588     }\
02589     inline E operator ^ (E lhs, E rhs){\
02590         return E(T(lhs) ^ T(rhs));\
02591     }\
02592     inline E operator ~ (E lhs){\
02593         return E(~T(lhs));\
02594     }\
02595     inline E operator |= (E &lhs, E rhs){\
02596         lhs = lhs | rhs;\
02597         return lhs;\
02598     }\
02599     inline E operator &= (E &lhs, E rhs){\
02600         lhs = lhs & rhs;\
02601         return lhs;\
02602     }\
02603     inline E operator ^= (E &lhs, E rhs){\
02604         lhs = lhs ^ rhs;\
02605         return lhs;\
02606     }\
02607     inline bool operator !(E rhs) \
02608     {\
02609         return !bool(T(rhs)); \
02610     }
02611 
02612 }  // namespace flatbuffers
02613 
02614 // clang-format on
02615 
02616 #endif  // FLATBUFFERS_H_


behaviortree_cpp
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Sat Jun 8 2019 20:17:15