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


behaviotree_cpp_v3
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Tue May 4 2021 02:56:24