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


behaviortree_cpp
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Sat Feb 2 2019 04:01:53