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 {
33 // Generic 'operator==' with conditional specialisations.
34 // T e - new value of a scalar field.
35 // T def - default of scalar (is known at compile-time).
36 template <typename T>
37 inline bool IsTheSameAs(T e, T def)
38 {
39  return e == def;
40 }
41 
42 #if defined(FLATBUFFERS_NAN_DEFAULTS) && defined(FLATBUFFERS_HAS_NEW_STRTOD) && \
43  (FLATBUFFERS_HAS_NEW_STRTOD > 0)
44 // Like `operator==(e, def)` with weak NaN if T=(float|double).
45 template <typename T>
46 inline bool IsFloatTheSameAs(T e, T def)
47 {
48  return (e == def) || ((def != def) && (e != e));
49 }
50 template <>
51 inline bool IsTheSameAs<float>(float e, float def)
52 {
53  return IsFloatTheSameAs(e, def);
54 }
55 template <>
56 inline bool IsTheSameAs<double>(double e, double def)
57 {
58  return IsFloatTheSameAs(e, def);
59 }
60 #endif
61 
62 // Check 'v' is out of closed range [low; high].
63 // Workaround for GCC warning [-Werror=type-limits]:
64 // comparison is always true due to limited range of data type.
65 template <typename T>
66 inline bool IsOutRange(const T& v, const T& low, const T& high)
67 {
68  return (v < low) || (high < v);
69 }
70 
71 // Check 'v' is in closed range [low; high].
72 template <typename T>
73 inline bool IsInRange(const T& v, const T& low, const T& high)
74 {
75  return !IsOutRange(v, low, high);
76 }
77 
78 // Wrapper for uoffset_t to allow safe template specialization.
79 // Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
80 template <typename T>
81 struct Offset
82 {
83  uoffset_t o;
84  Offset() : o(0)
85  {}
86  Offset(uoffset_t _o) : o(_o)
87  {}
89  {
90  return Offset<void>(o);
91  }
92  bool IsNull() const
93  {
94  return !o;
95  }
96 };
97 
98 inline void EndianCheck()
99 {
100  int endiantest = 1;
101  // If this fails, see FLATBUFFERS_LITTLEENDIAN above.
102  FLATBUFFERS_ASSERT(*reinterpret_cast<char*>(&endiantest) == FLATBUFFERS_LITTLEENDIAN);
103  (void)endiantest;
104 }
105 
106 template <typename T>
107 FLATBUFFERS_CONSTEXPR size_t AlignOf()
108 {
109  // clang-format off
110  #ifdef _MSC_VER
111  return __alignof(T);
112  #else
113  #ifndef alignof
114  return __alignof__(T);
115  #else
116  return alignof(T);
117  #endif
118  #endif
119  // clang-format on
120 }
121 
122 // When we read serialized data from memory, in the case of most scalars,
123 // we want to just read T, but in the case of Offset, we want to actually
124 // perform the indirection and return a pointer.
125 // The template specialization below does just that.
126 // It is wrapped in a struct since function templates can't overload on the
127 // return type like this.
128 // The typedef is for the convenience of callers of this function
129 // (avoiding the need for a trailing return decltype)
130 template <typename T>
132 {
133  typedef T return_type;
135  static const size_t element_stride = sizeof(T);
136  static return_type Read(const uint8_t* p, uoffset_t i)
137  {
138  return EndianScalar((reinterpret_cast<const T*>(p))[i]);
139  }
140 };
141 template <typename T>
143 {
144  typedef const T* return_type;
146  static const size_t element_stride = sizeof(uoffset_t);
147  static return_type Read(const uint8_t* p, uoffset_t i)
148  {
149  p += i * sizeof(uoffset_t);
150  return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p));
151  }
152 };
153 template <typename T>
154 struct IndirectHelper<const T*>
155 {
156  typedef const T* return_type;
158  static const size_t element_stride = sizeof(T);
159  static return_type Read(const uint8_t* p, uoffset_t i)
160  {
161  return reinterpret_cast<const T*>(p + i * sizeof(T));
162  }
163 };
164 
165 // An STL compatible iterator implementation for Vector below, effectively
166 // calling Get() for every element.
167 template <typename T, typename IT>
169 {
170  typedef std::random_access_iterator_tag iterator_category;
171  typedef IT value_type;
172  typedef ptrdiff_t difference_type;
173  typedef IT* pointer;
174  typedef IT& reference;
175 
176  VectorIterator(const uint8_t* data, uoffset_t i) :
177  data_(data + IndirectHelper<T>::element_stride * i)
178  {}
179  VectorIterator(const VectorIterator& other) : data_(other.data_)
180  {}
181  VectorIterator() : data_(nullptr)
182  {}
183 
185  {
186  data_ = other.data_;
187  return *this;
188  }
189 
190  // clang-format off
191  #if !defined(FLATBUFFERS_CPP98_STL)
193  data_ = other.data_;
194  return *this;
195  }
196  #endif // !defined(FLATBUFFERS_CPP98_STL)
197  // clang-format on
198 
199  bool operator==(const VectorIterator& other) const
200  {
201  return data_ == other.data_;
202  }
203 
204  bool operator<(const VectorIterator& other) const
205  {
206  return data_ < other.data_;
207  }
208 
209  bool operator!=(const VectorIterator& other) const
210  {
211  return data_ != other.data_;
212  }
213 
214  difference_type operator-(const VectorIterator& other) const
215  {
216  return (data_ - other.data_) / IndirectHelper<T>::element_stride;
217  }
218 
219  IT operator*() const
220  {
221  return IndirectHelper<T>::Read(data_, 0);
222  }
223 
224  IT operator->() const
225  {
226  return IndirectHelper<T>::Read(data_, 0);
227  }
228 
230  {
232  return *this;
233  }
234 
236  {
237  VectorIterator temp(data_, 0);
239  return temp;
240  }
241 
242  VectorIterator operator+(const uoffset_t& offset) const
243  {
244  return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride, 0);
245  }
246 
247  VectorIterator& operator+=(const uoffset_t& offset)
248  {
249  data_ += offset * IndirectHelper<T>::element_stride;
250  return *this;
251  }
252 
254  {
256  return *this;
257  }
258 
260  {
261  VectorIterator temp(data_, 0);
263  return temp;
264  }
265 
266  VectorIterator operator-(const uoffset_t& offset) const
267  {
268  return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride, 0);
269  }
270 
271  VectorIterator& operator-=(const uoffset_t& offset)
272  {
273  data_ -= offset * IndirectHelper<T>::element_stride;
274  return *this;
275  }
276 
277 private:
278  const uint8_t* data_;
279 };
280 
281 template <typename Iterator>
282 struct VectorReverseIterator : public std::reverse_iterator<Iterator>
283 {
284  explicit VectorReverseIterator(Iterator iter) : std::reverse_iterator<Iterator>(iter)
285  {}
286 
287  typename Iterator::value_type operator*() const
288  {
289  return *(std::reverse_iterator<Iterator>::current);
290  }
291 
292  typename Iterator::value_type operator->() const
293  {
294  return *(std::reverse_iterator<Iterator>::current);
295  }
296 };
297 
298 struct String;
299 
300 // This is used as a helper type for accessing vectors.
301 // Vector::data() assumes the vector elements start after the length field.
302 template <typename T>
303 class Vector
304 {
305 public:
310 
311  uoffset_t size() const
312  {
313  return EndianScalar(length_);
314  }
315 
316  // Deprecated: use size(). Here for backwards compatibility.
317  FLATBUFFERS_ATTRIBUTE(deprecated("use size() instead"))
318  uoffset_t Length() const
319  {
320  return size();
321  }
322 
325  typedef return_type value_type;
326 
327  return_type Get(uoffset_t i) const
328  {
329  FLATBUFFERS_ASSERT(i < size());
330  return IndirectHelper<T>::Read(Data(), i);
331  }
332 
333  return_type operator[](uoffset_t i) const
334  {
335  return Get(i);
336  }
337 
338  // If this is a Vector of enums, T will be its storage type, not the enum
339  // type. This function makes it convenient to retrieve value with enum
340  // type E.
341  template <typename E>
342  E GetEnum(uoffset_t i) const
343  {
344  return static_cast<E>(Get(i));
345  }
346 
347  // If this a vector of unions, this does the cast for you. There's no check
348  // to make sure this is the right type!
349  template <typename U>
350  const U* GetAs(uoffset_t i) const
351  {
352  return reinterpret_cast<const U*>(Get(i));
353  }
354 
355  // If this a vector of unions, this does the cast for you. There's no check
356  // to make sure this is actually a string!
357  const String* GetAsString(uoffset_t i) const
358  {
359  return reinterpret_cast<const String*>(Get(i));
360  }
361 
362  const void* GetStructFromOffset(size_t o) const
363  {
364  return reinterpret_cast<const void*>(Data() + o);
365  }
366 
367  iterator begin()
368  {
369  return iterator(Data(), 0);
370  }
371  const_iterator begin() const
372  {
373  return const_iterator(Data(), 0);
374  }
375 
376  iterator end()
377  {
378  return iterator(Data(), size());
379  }
380  const_iterator end() const
381  {
382  return const_iterator(Data(), size());
383  }
384 
385  reverse_iterator rbegin()
386  {
387  return reverse_iterator(end() - 1);
388  }
389  const_reverse_iterator rbegin() const
390  {
391  return const_reverse_iterator(end() - 1);
392  }
393 
394  reverse_iterator rend()
395  {
396  return reverse_iterator(begin() - 1);
397  }
398  const_reverse_iterator rend() const
399  {
400  return const_reverse_iterator(begin() - 1);
401  }
402 
403  const_iterator cbegin() const
404  {
405  return begin();
406  }
407 
408  const_iterator cend() const
409  {
410  return end();
411  }
412 
413  const_reverse_iterator crbegin() const
414  {
415  return rbegin();
416  }
417 
418  const_reverse_iterator crend() const
419  {
420  return rend();
421  }
422 
423  // Change elements if you have a non-const pointer to this object.
424  // Scalars only. See reflection.h, and the documentation.
425  void Mutate(uoffset_t i, const T& val)
426  {
427  FLATBUFFERS_ASSERT(i < size());
428  WriteScalar(data() + i, val);
429  }
430 
431  // Change an element of a vector of tables (or strings).
432  // "val" points to the new table/string, as you can obtain from
433  // e.g. reflection::AddFlatBuffer().
434  void MutateOffset(uoffset_t i, const uint8_t* val)
435  {
436  FLATBUFFERS_ASSERT(i < size());
437  static_assert(sizeof(T) == sizeof(uoffset_t), "Unrelated types");
438  WriteScalar(data() + i,
439  static_cast<uoffset_t>(val - (Data() + i * sizeof(uoffset_t))));
440  }
441 
442  // Get a mutable pointer to tables/strings inside this vector.
443  mutable_return_type GetMutableObject(uoffset_t i) const
444  {
445  FLATBUFFERS_ASSERT(i < size());
446  return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i));
447  }
448 
449  // The raw data in little endian format. Use with care.
450  const uint8_t* Data() const
451  {
452  return reinterpret_cast<const uint8_t*>(&length_ + 1);
453  }
454 
455  uint8_t* Data()
456  {
457  return reinterpret_cast<uint8_t*>(&length_ + 1);
458  }
459 
460  // Similarly, but typed, much like std::vector::data
461  const T* data() const
462  {
463  return reinterpret_cast<const T*>(Data());
464  }
465  T* data()
466  {
467  return reinterpret_cast<T*>(Data());
468  }
469 
470  template <typename K>
471  return_type LookupByKey(K key) const
472  {
473  void* search_result = std::bsearch(&key, Data(), size(),
474  IndirectHelper<T>::element_stride, KeyCompare<K>);
475 
476  if (!search_result)
477  {
478  return nullptr; // Key not found.
479  }
480 
481  const uint8_t* element = reinterpret_cast<const uint8_t*>(search_result);
482 
483  return IndirectHelper<T>::Read(element, 0);
484  }
485 
486 protected:
487  // This class is only used to access pre-existing data. Don't ever
488  // try to construct these manually.
489  Vector();
490 
491  uoffset_t length_;
492 
493 private:
494  // This class is a pointer. Copying will therefore create an invalid object.
495  // Private and unimplemented copy constructor.
496  Vector(const Vector&);
497  Vector& operator=(const Vector&);
498 
499  template <typename K>
500  static int KeyCompare(const void* ap, const void* bp)
501  {
502  const K* key = reinterpret_cast<const K*>(ap);
503  const uint8_t* data = reinterpret_cast<const uint8_t*>(bp);
504  auto table = IndirectHelper<T>::Read(data, 0);
505 
506  // std::bsearch compares with the operands transposed, so we negate the
507  // result here.
508  return -table->KeyCompareWithValue(*key);
509  }
510 };
511 
512 // Represent a vector much like the template above, but in this case we
513 // don't know what the element types are (used with reflection.h).
515 {
516 public:
517  uoffset_t size() const
518  {
519  return EndianScalar(length_);
520  }
521 
522  const uint8_t* Data() const
523  {
524  return reinterpret_cast<const uint8_t*>(&length_ + 1);
525  }
526  uint8_t* Data()
527  {
528  return reinterpret_cast<uint8_t*>(&length_ + 1);
529  }
530 
531 protected:
532  VectorOfAny();
533 
534  uoffset_t length_;
535 
536 private:
537  VectorOfAny(const VectorOfAny&);
538  VectorOfAny& operator=(const VectorOfAny&);
539 };
540 
541 #ifndef FLATBUFFERS_CPP98_STL
542 template <typename T, typename U>
544 {
545  static_assert(std::is_base_of<T, U>::value, "Unrelated types");
546  return reinterpret_cast<Vector<Offset<T>>*>(ptr);
547 }
548 
549 template <typename T, typename U>
551 {
552  static_assert(std::is_base_of<T, U>::value, "Unrelated types");
553  return reinterpret_cast<const Vector<Offset<T>>*>(ptr);
554 }
555 #endif
556 
557 // Convenient helper function to get the length of any vector, regardless
558 // of whether it is null or not (the field is not set).
559 template <typename T>
560 static inline size_t VectorLength(const Vector<T>* v)
561 {
562  return v ? v->size() : 0;
563 }
564 
565 // This is used as a helper type for accessing arrays.
566 template <typename T, uint16_t length>
567 class Array
568 {
573 
574 public:
575  typedef uint16_t size_type;
579 
580  FLATBUFFERS_CONSTEXPR uint16_t size() const
581  {
582  return length;
583  }
584 
585  return_type Get(uoffset_t i) const
586  {
587  FLATBUFFERS_ASSERT(i < size());
589  }
590 
591  return_type operator[](uoffset_t i) const
592  {
593  return Get(i);
594  }
595 
596  // If this is a Vector of enums, T will be its storage type, not the enum
597  // type. This function makes it convenient to retrieve value with enum
598  // type E.
599  template <typename E>
600  E GetEnum(uoffset_t i) const
601  {
602  return static_cast<E>(Get(i));
603  }
604 
605  const_iterator begin() const
606  {
607  return const_iterator(Data(), 0);
608  }
609  const_iterator end() const
610  {
611  return const_iterator(Data(), size());
612  }
613 
614  const_reverse_iterator rbegin() const
615  {
616  return const_reverse_iterator(end());
617  }
618  const_reverse_iterator rend() const
619  {
620  return const_reverse_iterator(end());
621  }
622 
623  const_iterator cbegin() const
624  {
625  return begin();
626  }
627  const_iterator cend() const
628  {
629  return end();
630  }
631 
632  const_reverse_iterator crbegin() const
633  {
634  return rbegin();
635  }
636  const_reverse_iterator crend() const
637  {
638  return rend();
639  }
640 
641  // Get a mutable pointer to elements inside this array.
642  // This method used to mutate arrays of structs followed by a @p Mutate
643  // operation. For primitive types use @p Mutate directly.
644  // @warning Assignments and reads to/from the dereferenced pointer are not
645  // automatically converted to the correct endianness.
647  GetMutablePointer(uoffset_t i) const
648  {
649  FLATBUFFERS_ASSERT(i < size());
650  return const_cast<T*>(&data()[i]);
651  }
652 
653  // Change elements if you have a non-const pointer to this object.
654  void Mutate(uoffset_t i, const T& val)
655  {
656  MutateImpl(scalar_tag(), i, val);
657  }
658 
659  // The raw data in little endian format. Use with care.
660  const uint8_t* Data() const
661  {
662  return data_;
663  }
664 
665  uint8_t* Data()
666  {
667  return data_;
668  }
669 
670  // Similarly, but typed, much like std::vector::data
671  const T* data() const
672  {
673  return reinterpret_cast<const T*>(Data());
674  }
675  T* data()
676  {
677  return reinterpret_cast<T*>(Data());
678  }
679 
680  // Copy data from a span with endian conversion.
681  // If this Array and the span overlap, the behavior is undefined.
682  void CopyFromSpan(flatbuffers::span<const T, length> src)
683  {
684  const auto p1 = reinterpret_cast<const uint8_t*>(src.data());
685  const auto p2 = Data();
686  FLATBUFFERS_ASSERT(!(p1 >= p2 && p1 < (p2 + length)) &&
687  !(p2 >= p1 && p2 < (p1 + length)));
688  (void)p1;
689  (void)p2;
690 
691  CopyFromSpanImpl(
693  !scalar_tag::value || sizeof(T) == 1 || FLATBUFFERS_LITTLEENDIAN > (), src);
694  }
695 
696 protected:
698  {
699  FLATBUFFERS_ASSERT(i < size());
700  WriteScalar(data() + i, val);
701  }
702 
704  {
705  *(GetMutablePointer(i)) = val;
706  }
707 
709  flatbuffers::span<const T, length> src)
710  {
711  // Use std::memcpy() instead of std::copy() to avoid preformance degradation
712  // due to aliasing if T is char or unsigned char.
713  // The size is known at compile time, so memcpy would be inlined.
714  std::memcpy(data(), src.data(), length * sizeof(T));
715  }
716 
717  // Copy data from flatbuffers::span with endian conversion.
719  flatbuffers::span<const T, length> src)
720  {
721  for (size_type k = 0; k < length; k++)
722  {
723  Mutate(k, src[k]);
724  }
725  }
726 
727  // This class is only used to access pre-existing data. Don't ever
728  // try to construct these manually.
729  // 'constexpr' allows us to use 'size()' at compile time.
730  // @note Must not use 'FLATBUFFERS_CONSTEXPR' here, as const is not allowed on
731  // a constructor.
732 #if defined(__cpp_constexpr)
733  constexpr Array();
734 #else
735  Array();
736 #endif
737 
738  uint8_t data_[length * sizeof(T)];
739 
740 private:
741  // This class is a pointer. Copying will therefore create an invalid object.
742  // Private and unimplemented copy constructor.
743  Array(const Array&);
744  Array& operator=(const Array&);
745 };
746 
747 // Specialization for Array[struct] with access using Offset<void> pointer.
748 // This specialization used by idl_gen_text.cpp.
749 template <typename T, uint16_t length>
750 class Array<Offset<T>, length>
751 {
752  static_assert(flatbuffers::is_same<T, void>::value, "unexpected type T");
753 
754 public:
755  typedef const void* return_type;
756 
757  const uint8_t* Data() const
758  {
759  return data_;
760  }
761 
762  // Make idl_gen_text.cpp::PrintContainer happy.
763  return_type operator[](uoffset_t) const
764  {
765  FLATBUFFERS_ASSERT(false);
766  return nullptr;
767  }
768 
769 private:
770  // This class is only used to access pre-existing data.
771  Array();
772  Array(const Array&);
773  Array& operator=(const Array&);
774 
775  uint8_t data_[1];
776 };
777 
778 // Cast a raw T[length] to a raw flatbuffers::Array<T, length>
779 // without endian conversion. Use with care.
780 template <typename T, uint16_t length>
781 Array<T, length>& CastToArray(T (&arr)[length])
782 {
783  return *reinterpret_cast<Array<T, length>*>(arr);
784 }
785 
786 template <typename T, uint16_t length>
787 const Array<T, length>& CastToArray(const T (&arr)[length])
788 {
789  return *reinterpret_cast<const Array<T, length>*>(arr);
790 }
791 
792 template <typename E, typename T, uint16_t length>
794 {
795  static_assert(sizeof(E) == sizeof(T), "invalid enum type E");
796  return *reinterpret_cast<Array<E, length>*>(arr);
797 }
798 
799 template <typename E, typename T, uint16_t length>
800 const Array<E, length>& CastToArrayOfEnum(const T (&arr)[length])
801 {
802  static_assert(sizeof(E) == sizeof(T), "invalid enum type E");
803  return *reinterpret_cast<const Array<E, length>*>(arr);
804 }
805 
806 // Lexicographically compare two strings (possibly containing nulls), and
807 // return true if the first is less than the second.
808 static inline bool StringLessThan(const char* a_data, uoffset_t a_size,
809  const char* b_data, uoffset_t b_size)
810 {
811  const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size));
812  return cmp == 0 ? a_size < b_size : cmp < 0;
813 }
814 
815 struct String : public Vector<char>
816 {
817  const char* c_str() const
818  {
819  return reinterpret_cast<const char*>(Data());
820  }
821  std::string str() const
822  {
823  return std::string(c_str(), size());
824  }
825 
826  // clang-format off
827  #ifdef FLATBUFFERS_HAS_STRING_VIEW
828  flatbuffers::string_view string_view() const {
829  return flatbuffers::string_view(c_str(), size());
830  }
831  #endif // FLATBUFFERS_HAS_STRING_VIEW
832  // clang-format on
833 
834  bool operator<(const String& o) const
835  {
836  return StringLessThan(this->data(), this->size(), o.data(), o.size());
837  }
838 };
839 
840 // Convenience function to get std::string from a String returning an empty
841 // string on null pointer.
842 static inline std::string GetString(const String* str)
843 {
844  return str ? str->str() : "";
845 }
846 
847 // Convenience function to get char* from a String returning an empty string on
848 // null pointer.
849 static inline const char* GetCstring(const String* str)
850 {
851  return str ? str->c_str() : "";
852 }
853 
854 #ifdef FLATBUFFERS_HAS_STRING_VIEW
855 // Convenience function to get string_view from a String returning an empty
856 // string_view on null pointer.
857 static inline flatbuffers::string_view GetStringView(const String* str)
858 {
859  return str ? str->string_view() : flatbuffers::string_view();
860 }
861 #endif // FLATBUFFERS_HAS_STRING_VIEW
862 
863 // Allocator interface. This is flatbuffers-specific and meant only for
864 // `vector_downward` usage.
866 {
867 public:
868  virtual ~Allocator()
869  {}
870 
871  // Allocate `size` bytes of memory.
872  virtual uint8_t* allocate(size_t size) = 0;
873 
874  // Deallocate `size` bytes of memory at `p` allocated by this allocator.
875  virtual void deallocate(uint8_t* p, size_t size) = 0;
876 
877  // Reallocate `new_size` bytes of memory, replacing the old region of size
878  // `old_size` at `p`. In contrast to a normal realloc, this grows downwards,
879  // and is intended specifcally for `vector_downward` use.
880  // `in_use_back` and `in_use_front` indicate how much of `old_size` is
881  // actually in use at each end, and needs to be copied.
882  virtual uint8_t* reallocate_downward(uint8_t* old_p, size_t old_size, size_t new_size,
883  size_t in_use_back, size_t in_use_front)
884  {
885  FLATBUFFERS_ASSERT(new_size > old_size); // vector_downward only grows
886  uint8_t* new_p = allocate(new_size);
887  memcpy_downward(old_p, old_size, new_p, new_size, in_use_back, in_use_front);
888  deallocate(old_p, old_size);
889  return new_p;
890  }
891 
892 protected:
893  // Called by `reallocate_downward` to copy memory from `old_p` of `old_size`
894  // to `new_p` of `new_size`. Only memory of size `in_use_front` and
895  // `in_use_back` will be copied from the front and back of the old memory
896  // allocation.
897  void memcpy_downward(uint8_t* old_p, size_t old_size, uint8_t* new_p, size_t new_size,
898  size_t in_use_back, size_t in_use_front)
899  {
900  memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back, in_use_back);
901  memcpy(new_p, old_p, in_use_front);
902  }
903 };
904 
905 // DefaultAllocator uses new/delete to allocate memory regions
907 {
908 public:
909  uint8_t* allocate(size_t size) FLATBUFFERS_OVERRIDE
910  {
911  return new uint8_t[size];
912  }
913 
914  void deallocate(uint8_t* p, size_t) FLATBUFFERS_OVERRIDE
915  {
916  delete[] p;
917  }
918 
919  static void dealloc(void* p, size_t)
920  {
921  delete[] static_cast<uint8_t*>(p);
922  }
923 };
924 
925 // These functions allow for a null allocator to mean use the default allocator,
926 // as used by DetachedBuffer and vector_downward below.
927 // This is to avoid having a statically or dynamically allocated default
928 // allocator, or having to move it between the classes that may own it.
929 inline uint8_t* Allocate(Allocator* allocator, size_t size)
930 {
931  return allocator ? allocator->allocate(size) : DefaultAllocator().allocate(size);
932 }
933 
934 inline void Deallocate(Allocator* allocator, uint8_t* p, size_t size)
935 {
936  if (allocator)
937  allocator->deallocate(p, size);
938  else
939  DefaultAllocator().deallocate(p, size);
940 }
941 
942 inline uint8_t* ReallocateDownward(Allocator* allocator, uint8_t* old_p, size_t old_size,
943  size_t new_size, size_t in_use_back,
944  size_t in_use_front)
945 {
946  return allocator ? allocator->reallocate_downward(old_p, old_size, new_size,
947  in_use_back, in_use_front) :
948  DefaultAllocator().reallocate_downward(old_p, old_size, new_size,
949  in_use_back, in_use_front);
950 }
951 
952 // DetachedBuffer is a finished flatbuffer memory region, detached from its
953 // builder. The original memory region and allocator are also stored so that
954 // the DetachedBuffer can manage the memory lifetime.
956 {
957 public:
959  allocator_(nullptr),
960  own_allocator_(false),
961  buf_(nullptr),
962  reserved_(0),
963  cur_(nullptr),
964  size_(0)
965  {}
966 
967  DetachedBuffer(Allocator* allocator, bool own_allocator, uint8_t* buf, size_t reserved,
968  uint8_t* cur, size_t sz) :
969  allocator_(allocator),
970  own_allocator_(own_allocator),
971  buf_(buf),
972  reserved_(reserved),
973  cur_(cur),
974  size_(sz)
975  {}
976 
977  // clang-format off
978  #if !defined(FLATBUFFERS_CPP98_STL)
979  // clang-format on
981  allocator_(other.allocator_),
982  own_allocator_(other.own_allocator_),
983  buf_(other.buf_),
984  reserved_(other.reserved_),
985  cur_(other.cur_),
986  size_(other.size_)
987  {
988  other.reset();
989  }
990  // clang-format off
991  #endif // !defined(FLATBUFFERS_CPP98_STL)
992  // clang-format on
993 
994  // clang-format off
995  #if !defined(FLATBUFFERS_CPP98_STL)
996  // clang-format on
998  {
999  if (this == &other)
1000  return *this;
1001 
1002  destroy();
1003 
1004  allocator_ = other.allocator_;
1005  own_allocator_ = other.own_allocator_;
1006  buf_ = other.buf_;
1007  reserved_ = other.reserved_;
1008  cur_ = other.cur_;
1009  size_ = other.size_;
1010 
1011  other.reset();
1012 
1013  return *this;
1014  }
1015  // clang-format off
1016  #endif // !defined(FLATBUFFERS_CPP98_STL)
1017  // clang-format on
1018 
1020  {
1021  destroy();
1022  }
1023 
1024  const uint8_t* data() const
1025  {
1026  return cur_;
1027  }
1028 
1029  uint8_t* data()
1030  {
1031  return cur_;
1032  }
1033 
1034  size_t size() const
1035  {
1036  return size_;
1037  }
1038 
1039  // clang-format off
1040  #if 0 // disabled for now due to the ordering of classes in this header
1041  template <class T>
1042  bool Verify() const {
1043  Verifier verifier(data(), size());
1044  return verifier.Verify<T>(nullptr);
1045  }
1046 
1047  template <class T>
1048  const T* GetRoot() const {
1049  return flatbuffers::GetRoot<T>(data());
1050  }
1051 
1052  template <class T>
1053  T* GetRoot() {
1054  return flatbuffers::GetRoot<T>(data());
1055  }
1056  #endif
1057  // clang-format on
1058 
1059  // clang-format off
1060  #if !defined(FLATBUFFERS_CPP98_STL)
1061  // clang-format on
1062  // These may change access mode, leave these at end of public section
1063  FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer& other));
1064  FLATBUFFERS_DELETE_FUNC(DetachedBuffer& operator=(const DetachedBuffer& other));
1065  // clang-format off
1066  #endif // !defined(FLATBUFFERS_CPP98_STL)
1067  // clang-format on
1068 
1069 protected:
1072  uint8_t* buf_;
1073  size_t reserved_;
1074  uint8_t* cur_;
1075  size_t size_;
1076 
1077  inline void destroy()
1078  {
1079  if (buf_)
1080  Deallocate(allocator_, buf_, reserved_);
1081  if (own_allocator_ && allocator_)
1082  {
1083  delete allocator_;
1084  }
1085  reset();
1086  }
1087 
1088  inline void reset()
1089  {
1090  allocator_ = nullptr;
1091  own_allocator_ = false;
1092  buf_ = nullptr;
1093  reserved_ = 0;
1094  cur_ = nullptr;
1095  size_ = 0;
1096  }
1097 };
1098 
1099 // This is a minimal replication of std::vector<uint8_t> functionality,
1100 // except growing from higher to lower addresses. i.e push_back() inserts data
1101 // in the lowest address in the vector.
1102 // Since this vector leaves the lower part unused, we support a "scratch-pad"
1103 // that can be stored there for temporary data, to share the allocated space.
1104 // Essentially, this supports 2 std::vectors in a single buffer.
1106 {
1107 public:
1108  explicit vector_downward(size_t initial_size, Allocator* allocator, bool own_allocator,
1109  size_t buffer_minalign) :
1110  allocator_(allocator),
1111  own_allocator_(own_allocator),
1112  initial_size_(initial_size),
1113  buffer_minalign_(buffer_minalign),
1114  reserved_(0),
1115  buf_(nullptr),
1116  cur_(nullptr),
1117  scratch_(nullptr)
1118  {}
1119 
1120  // clang-format off
1121  #if !defined(FLATBUFFERS_CPP98_STL)
1123  #else
1125  #endif // defined(FLATBUFFERS_CPP98_STL)
1126  // clang-format on
1127  :
1128  allocator_(other.allocator_),
1129  own_allocator_(other.own_allocator_),
1130  initial_size_(other.initial_size_),
1131  buffer_minalign_(other.buffer_minalign_),
1132  reserved_(other.reserved_),
1133  buf_(other.buf_),
1134  cur_(other.cur_),
1135  scratch_(other.scratch_)
1136  {
1137  // No change in other.allocator_
1138  // No change in other.initial_size_
1139  // No change in other.buffer_minalign_
1140  other.own_allocator_ = false;
1141  other.reserved_ = 0;
1142  other.buf_ = nullptr;
1143  other.cur_ = nullptr;
1144  other.scratch_ = nullptr;
1145  }
1146 
1147  // clang-format off
1148  #if !defined(FLATBUFFERS_CPP98_STL)
1149  // clang-format on
1151  {
1152  // Move construct a temporary and swap idiom
1153  vector_downward temp(std::move(other));
1154  swap(temp);
1155  return *this;
1156  }
1157  // clang-format off
1158  #endif // defined(FLATBUFFERS_CPP98_STL)
1159  // clang-format on
1160 
1162  {
1163  clear_buffer();
1164  clear_allocator();
1165  }
1166 
1167  void reset()
1168  {
1169  clear_buffer();
1170  clear();
1171  }
1172 
1173  void clear()
1174  {
1175  if (buf_)
1176  {
1177  cur_ = buf_ + reserved_;
1178  }
1179  else
1180  {
1181  reserved_ = 0;
1182  cur_ = nullptr;
1183  }
1184  clear_scratch();
1185  }
1186 
1188  {
1189  scratch_ = buf_;
1190  }
1191 
1193  {
1194  if (own_allocator_ && allocator_)
1195  {
1196  delete allocator_;
1197  }
1198  allocator_ = nullptr;
1199  own_allocator_ = false;
1200  }
1201 
1203  {
1204  if (buf_)
1205  Deallocate(allocator_, buf_, reserved_);
1206  buf_ = nullptr;
1207  }
1208 
1209  // Relinquish the pointer to the caller.
1210  uint8_t* release_raw(size_t& allocated_bytes, size_t& offset)
1211  {
1212  auto* buf = buf_;
1213  allocated_bytes = reserved_;
1214  offset = static_cast<size_t>(cur_ - buf_);
1215 
1216  // release_raw only relinquishes the buffer ownership.
1217  // Does not deallocate or reset the allocator. Destructor will do that.
1218  buf_ = nullptr;
1219  clear();
1220  return buf;
1221  }
1222 
1223  // Relinquish the pointer to the caller.
1225  {
1226  // allocator ownership (if any) is transferred to DetachedBuffer.
1227  DetachedBuffer fb(allocator_, own_allocator_, buf_, reserved_, cur_, size());
1228  if (own_allocator_)
1229  {
1230  allocator_ = nullptr;
1231  own_allocator_ = false;
1232  }
1233  buf_ = nullptr;
1234  clear();
1235  return fb;
1236  }
1237 
1238  size_t ensure_space(size_t len)
1239  {
1240  FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_);
1241  if (len > static_cast<size_t>(cur_ - scratch_))
1242  {
1243  reallocate(len);
1244  }
1245  // Beyond this, signed offsets may not have enough range:
1246  // (FlatBuffers > 2GB not supported).
1247  FLATBUFFERS_ASSERT(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
1248  return len;
1249  }
1250 
1251  inline uint8_t* make_space(size_t len)
1252  {
1253  size_t space = ensure_space(len);
1254  cur_ -= space;
1255  return cur_;
1256  }
1257 
1258  // Returns nullptr if using the DefaultAllocator.
1260  {
1261  return allocator_;
1262  }
1263 
1264  uoffset_t size() const
1265  {
1266  return static_cast<uoffset_t>(reserved_ - static_cast<size_t>(cur_ - buf_));
1267  }
1268 
1269  uoffset_t scratch_size() const
1270  {
1271  return static_cast<uoffset_t>(scratch_ - buf_);
1272  }
1273 
1274  size_t capacity() const
1275  {
1276  return reserved_;
1277  }
1278 
1279  uint8_t* data() const
1280  {
1281  FLATBUFFERS_ASSERT(cur_);
1282  return cur_;
1283  }
1284 
1285  uint8_t* scratch_data() const
1286  {
1287  FLATBUFFERS_ASSERT(buf_);
1288  return buf_;
1289  }
1290 
1291  uint8_t* scratch_end() const
1292  {
1293  FLATBUFFERS_ASSERT(scratch_);
1294  return scratch_;
1295  }
1296 
1297  uint8_t* data_at(size_t offset) const
1298  {
1299  return buf_ + reserved_ - offset;
1300  }
1301 
1302  void push(const uint8_t* bytes, size_t num)
1303  {
1304  if (num > 0)
1305  {
1306  memcpy(make_space(num), bytes, num);
1307  }
1308  }
1309 
1310  // Specialized version of push() that avoids memcpy call for small data.
1311  template <typename T>
1312  void push_small(const T& little_endian_t)
1313  {
1314  make_space(sizeof(T));
1315  *reinterpret_cast<T*>(cur_) = little_endian_t;
1316  }
1317 
1318  template <typename T>
1319  void scratch_push_small(const T& t)
1320  {
1321  ensure_space(sizeof(T));
1322  *reinterpret_cast<T*>(scratch_) = t;
1323  scratch_ += sizeof(T);
1324  }
1325 
1326  // fill() is most frequently called with small byte counts (<= 4),
1327  // which is why we're using loops rather than calling memset.
1328  void fill(size_t zero_pad_bytes)
1329  {
1330  make_space(zero_pad_bytes);
1331  for (size_t i = 0; i < zero_pad_bytes; i++)
1332  cur_[i] = 0;
1333  }
1334 
1335  // Version for when we know the size is larger.
1336  // Precondition: zero_pad_bytes > 0
1337  void fill_big(size_t zero_pad_bytes)
1338  {
1339  memset(make_space(zero_pad_bytes), 0, zero_pad_bytes);
1340  }
1341 
1342  void pop(size_t bytes_to_remove)
1343  {
1344  cur_ += bytes_to_remove;
1345  }
1346  void scratch_pop(size_t bytes_to_remove)
1347  {
1348  scratch_ -= bytes_to_remove;
1349  }
1350 
1351  void swap(vector_downward& other)
1352  {
1353  using std::swap;
1354  swap(allocator_, other.allocator_);
1355  swap(own_allocator_, other.own_allocator_);
1356  swap(initial_size_, other.initial_size_);
1357  swap(buffer_minalign_, other.buffer_minalign_);
1358  swap(reserved_, other.reserved_);
1359  swap(buf_, other.buf_);
1360  swap(cur_, other.cur_);
1361  swap(scratch_, other.scratch_);
1362  }
1363 
1365  {
1366  using std::swap;
1367  swap(allocator_, other.allocator_);
1368  swap(own_allocator_, other.own_allocator_);
1369  }
1370 
1371 private:
1372  // You shouldn't really be copying instances of this class.
1373  FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward&));
1374  FLATBUFFERS_DELETE_FUNC(vector_downward& operator=(const vector_downward&));
1375 
1380  size_t reserved_;
1381  uint8_t* buf_;
1382  uint8_t* cur_; // Points at location between empty (below) and used (above).
1383  uint8_t* scratch_; // Points to the end of the scratchpad in use.
1384 
1385  void reallocate(size_t len)
1386  {
1387  auto old_reserved = reserved_;
1388  auto old_size = size();
1389  auto old_scratch_size = scratch_size();
1390  reserved_ += (std::max)(len, old_reserved ? old_reserved / 2 : initial_size_);
1391  reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1);
1392  if (buf_)
1393  {
1394  buf_ = ReallocateDownward(allocator_, buf_, old_reserved, reserved_, old_size,
1395  old_scratch_size);
1396  }
1397  else
1398  {
1399  buf_ = Allocate(allocator_, reserved_);
1400  }
1401  cur_ = buf_ + reserved_ - old_size;
1402  scratch_ = buf_ + old_scratch_size;
1403  }
1404 };
1405 
1406 // Converts a Field ID to a virtual table offset.
1407 inline voffset_t FieldIndexToOffset(voffset_t field_id)
1408 {
1409  // Should correspond to what EndTable() below builds up.
1410  const int fixed_fields = 2; // Vtable size and Object Size.
1411  return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t));
1412 }
1413 
1414 template <typename T, typename Alloc>
1415 const T* data(const std::vector<T, Alloc>& v)
1416 {
1417  // Eventually the returned pointer gets passed down to memcpy, so
1418  // we need it to be non-null to avoid undefined behavior.
1419  static uint8_t t;
1420  return v.empty() ? reinterpret_cast<const T*>(&t) : &v.front();
1421 }
1422 template <typename T, typename Alloc>
1423 T* data(std::vector<T, Alloc>& v)
1424 {
1425  // Eventually the returned pointer gets passed down to memcpy, so
1426  // we need it to be non-null to avoid undefined behavior.
1427  static uint8_t t;
1428  return v.empty() ? reinterpret_cast<T*>(&t) : &v.front();
1429 }
1430 
1432 
1443 {
1444 public:
1456  explicit FlatBufferBuilder(size_t initial_size = 1024, Allocator* allocator = nullptr,
1457  bool own_allocator = false,
1458  size_t buffer_minalign = AlignOf<largest_scalar_t>()) :
1459  buf_(initial_size, allocator, own_allocator, buffer_minalign),
1460  num_field_loc(0),
1461  max_voffset_(0),
1462  nested(false),
1463  finished(false),
1464  minalign_(1),
1465  force_defaults_(false),
1466  dedup_vtables_(true),
1467  string_pool(nullptr)
1468  {
1469  EndianCheck();
1470  }
1471 
1472  // clang-format off
1474  #if !defined(FLATBUFFERS_CPP98_STL)
1476  #else
1478  #endif // #if !defined(FLATBUFFERS_CPP98_STL)
1479  : buf_(1024, nullptr, false, AlignOf<largest_scalar_t>()),
1480  num_field_loc(0),
1481  max_voffset_(0),
1482  nested(false),
1483  finished(false),
1484  minalign_(1),
1485  force_defaults_(false),
1486  dedup_vtables_(true),
1487  string_pool(nullptr) {
1488  EndianCheck();
1489  // Default construct and swap idiom.
1490  // Lack of delegating constructors in vs2010 makes it more verbose than needed.
1491  Swap(other);
1492  }
1493  // clang-format on
1494 
1495  // clang-format off
1496  #if !defined(FLATBUFFERS_CPP98_STL)
1497  // clang-format on
1500  {
1501  // Move construct a temporary and swap idiom
1502  FlatBufferBuilder temp(std::move(other));
1503  Swap(temp);
1504  return *this;
1505  }
1506  // clang-format off
1507  #endif // defined(FLATBUFFERS_CPP98_STL)
1508  // clang-format on
1509 
1511  {
1512  using std::swap;
1513  buf_.swap(other.buf_);
1514  swap(num_field_loc, other.num_field_loc);
1515  swap(max_voffset_, other.max_voffset_);
1516  swap(nested, other.nested);
1517  swap(finished, other.finished);
1518  swap(minalign_, other.minalign_);
1519  swap(force_defaults_, other.force_defaults_);
1520  swap(dedup_vtables_, other.dedup_vtables_);
1521  swap(string_pool, other.string_pool);
1522  }
1523 
1525  {
1526  if (string_pool)
1527  delete string_pool;
1528  }
1529 
1530  void Reset()
1531  {
1532  Clear(); // clear builder state
1533  buf_.reset(); // deallocate buffer
1534  }
1535 
1538  void Clear()
1539  {
1540  ClearOffsets();
1541  buf_.clear();
1542  nested = false;
1543  finished = false;
1544  minalign_ = 1;
1545  if (string_pool)
1546  string_pool->clear();
1547  }
1548 
1551  uoffset_t GetSize() const
1552  {
1553  return buf_.size();
1554  }
1555 
1559  uint8_t* GetBufferPointer() const
1560  {
1561  Finished();
1562  return buf_.data();
1563  }
1564 
1568  flatbuffers::span<uint8_t> GetBufferSpan() const
1569  {
1570  Finished();
1571  return flatbuffers::span<uint8_t>(buf_.data(), buf_.size());
1572  }
1573 
1576  uint8_t* GetCurrentBufferPointer() const
1577  {
1578  return buf_.data();
1579  }
1580 
1585  FLATBUFFERS_ATTRIBUTE(deprecated("use Release() instead"))
1586  DetachedBuffer ReleaseBufferPointer()
1587  {
1588  Finished();
1589  return buf_.release();
1590  }
1591 
1595  {
1596  Finished();
1597  return buf_.release();
1598  }
1599 
1609  uint8_t* ReleaseRaw(size_t& size, size_t& offset)
1610  {
1611  Finished();
1612  return buf_.release_raw(size, offset);
1613  }
1614 
1620  size_t GetBufferMinAlignment() const
1621  {
1622  Finished();
1623  return minalign_;
1624  }
1625 
1627  void Finished() const
1628  {
1629  // If you get this assert, you're attempting to get access a buffer
1630  // which hasn't been finished yet. Be sure to call
1631  // FlatBufferBuilder::Finish with your root table.
1632  // If you really need to access an unfinished buffer, call
1633  // GetCurrentBufferPointer instead.
1634  FLATBUFFERS_ASSERT(finished);
1635  }
1637 
1643  void ForceDefaults(bool fd)
1644  {
1645  force_defaults_ = fd;
1646  }
1647 
1650  void DedupVtables(bool dedup)
1651  {
1652  dedup_vtables_ = dedup;
1653  }
1654 
1656  void Pad(size_t num_bytes)
1657  {
1658  buf_.fill(num_bytes);
1659  }
1660 
1661  void TrackMinAlign(size_t elem_size)
1662  {
1663  if (elem_size > minalign_)
1664  minalign_ = elem_size;
1665  }
1666 
1667  void Align(size_t elem_size)
1668  {
1669  TrackMinAlign(elem_size);
1670  buf_.fill(PaddingBytes(buf_.size(), elem_size));
1671  }
1672 
1673  void PushFlatBuffer(const uint8_t* bytes, size_t size)
1674  {
1675  PushBytes(bytes, size);
1676  finished = true;
1677  }
1678 
1679  void PushBytes(const uint8_t* bytes, size_t size)
1680  {
1681  buf_.push(bytes, size);
1682  }
1683 
1684  void PopBytes(size_t amount)
1685  {
1686  buf_.pop(amount);
1687  }
1688 
1689  template <typename T>
1690  void AssertScalarT()
1691  {
1692  // The code assumes power of 2 sizes and endian-swap-ability.
1693  static_assert(flatbuffers::is_scalar<T>::value, "T must be a scalar type");
1694  }
1695 
1696  // Write a single aligned scalar to the buffer
1697  template <typename T>
1698  uoffset_t PushElement(T element)
1699  {
1700  AssertScalarT<T>();
1701  T litle_endian_element = EndianScalar(element);
1702  Align(sizeof(T));
1703  buf_.push_small(litle_endian_element);
1704  return GetSize();
1705  }
1706 
1707  template <typename T>
1708  uoffset_t PushElement(Offset<T> off)
1709  {
1710  // Special case for offsets: see ReferTo below.
1711  return PushElement(ReferTo(off.o));
1712  }
1713 
1714  // When writing fields, we track where they are, so we can create correct
1715  // vtables later.
1716  void TrackField(voffset_t field, uoffset_t off)
1717  {
1718  FieldLoc fl = {off, field};
1719  buf_.scratch_push_small(fl);
1720  num_field_loc++;
1721  max_voffset_ = (std::max)(max_voffset_, field);
1722  }
1723 
1724  // Like PushElement, but additionally tracks the field this represents.
1725  template <typename T>
1726  void AddElement(voffset_t field, T e, T def)
1727  {
1728  // We don't serialize values equal to the default.
1729  if (IsTheSameAs(e, def) && !force_defaults_)
1730  return;
1731  auto off = PushElement(e);
1732  TrackField(field, off);
1733  }
1734 
1735  template <typename T>
1736  void AddElement(voffset_t field, T e)
1737  {
1738  auto off = PushElement(e);
1739  TrackField(field, off);
1740  }
1741 
1742  template <typename T>
1743  void AddOffset(voffset_t field, Offset<T> off)
1744  {
1745  if (off.IsNull())
1746  return; // Don't store.
1747  AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
1748  }
1749 
1750  template <typename T>
1751  void AddStruct(voffset_t field, const T* structptr)
1752  {
1753  if (!structptr)
1754  return; // Default, don't store.
1755  Align(AlignOf<T>());
1756  buf_.push_small(*structptr);
1757  TrackField(field, GetSize());
1758  }
1759 
1760  void AddStructOffset(voffset_t field, uoffset_t off)
1761  {
1762  TrackField(field, off);
1763  }
1764 
1765  // Offsets initially are relative to the end of the buffer (downwards).
1766  // This function converts them to be relative to the current location
1767  // in the buffer (when stored here), pointing upwards.
1768  uoffset_t ReferTo(uoffset_t off)
1769  {
1770  // Align to ensure GetSize() below is correct.
1771  Align(sizeof(uoffset_t));
1772  // Offset must refer to something already in buffer.
1773  FLATBUFFERS_ASSERT(off && off <= GetSize());
1774  return GetSize() - off + static_cast<uoffset_t>(sizeof(uoffset_t));
1775  }
1776 
1777  void NotNested()
1778  {
1779  // If you hit this, you're trying to construct a Table/Vector/String
1780  // during the construction of its parent table (between the MyTableBuilder
1781  // and table.Finish().
1782  // Move the creation of these sub-objects to above the MyTableBuilder to
1783  // not get this assert.
1784  // Ignoring this assert may appear to work in simple cases, but the reason
1785  // it is here is that storing objects in-line may cause vtable offsets
1786  // to not fit anymore. It also leads to vtable duplication.
1787  FLATBUFFERS_ASSERT(!nested);
1788  // If you hit this, fields were added outside the scope of a table.
1789  FLATBUFFERS_ASSERT(!num_field_loc);
1790  }
1791 
1792  // From generated code (or from the parser), we call StartTable/EndTable
1793  // with a sequence of AddElement calls in between.
1794  uoffset_t StartTable()
1795  {
1796  NotNested();
1797  nested = true;
1798  return GetSize();
1799  }
1800 
1801  // This finishes one serialized object by generating the vtable if it's a
1802  // table, comparing it against existing vtables, and writing the
1803  // resulting vtable offset.
1804  uoffset_t EndTable(uoffset_t start)
1805  {
1806  // If you get this assert, a corresponding StartTable wasn't called.
1807  FLATBUFFERS_ASSERT(nested);
1808  // Write the vtable offset, which is the start of any Table.
1809  // We fill it's value later.
1810  auto vtableoffsetloc = PushElement<soffset_t>(0);
1811  // Write a vtable, which consists entirely of voffset_t elements.
1812  // It starts with the number of offsets, followed by a type id, followed
1813  // by the offsets themselves. In reverse:
1814  // Include space for the last offset and ensure empty tables have a
1815  // minimum size.
1816  max_voffset_ = (std::max)(static_cast<voffset_t>(max_voffset_ + sizeof(voffset_t)),
1817  FieldIndexToOffset(0));
1818  buf_.fill_big(max_voffset_);
1819  auto table_object_size = vtableoffsetloc - start;
1820  // Vtable use 16bit offsets.
1821  FLATBUFFERS_ASSERT(table_object_size < 0x10000);
1822  WriteScalar<voffset_t>(buf_.data() + sizeof(voffset_t),
1823  static_cast<voffset_t>(table_object_size));
1824  WriteScalar<voffset_t>(buf_.data(), max_voffset_);
1825  // Write the offsets into the table
1826  for (auto it = buf_.scratch_end() - num_field_loc * sizeof(FieldLoc);
1827  it < buf_.scratch_end(); it += sizeof(FieldLoc))
1828  {
1829  auto field_location = reinterpret_cast<FieldLoc*>(it);
1830  auto pos = static_cast<voffset_t>(vtableoffsetloc - field_location->off);
1831  // If this asserts, it means you've set a field twice.
1832  FLATBUFFERS_ASSERT(!ReadScalar<voffset_t>(buf_.data() + field_location->id));
1833  WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
1834  }
1835  ClearOffsets();
1836  auto vt1 = reinterpret_cast<voffset_t*>(buf_.data());
1837  auto vt1_size = ReadScalar<voffset_t>(vt1);
1838  auto vt_use = GetSize();
1839  // See if we already have generated a vtable with this exact same
1840  // layout before. If so, make it point to the old one, remove this one.
1841  if (dedup_vtables_)
1842  {
1843  for (auto it = buf_.scratch_data(); it < buf_.scratch_end();
1844  it += sizeof(uoffset_t))
1845  {
1846  auto vt_offset_ptr = reinterpret_cast<uoffset_t*>(it);
1847  auto vt2 = reinterpret_cast<voffset_t*>(buf_.data_at(*vt_offset_ptr));
1848  auto vt2_size = ReadScalar<voffset_t>(vt2);
1849  if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size))
1850  continue;
1851  vt_use = *vt_offset_ptr;
1852  buf_.pop(GetSize() - vtableoffsetloc);
1853  break;
1854  }
1855  }
1856  // If this is a new vtable, remember it.
1857  if (vt_use == GetSize())
1858  {
1859  buf_.scratch_push_small(vt_use);
1860  }
1861  // Fill the vtable offset we created above.
1862  // The offset points from the beginning of the object to where the
1863  // vtable is stored.
1864  // Offsets default direction is downward in memory for future format
1865  // flexibility (storing all vtables at the start of the file).
1866  WriteScalar(buf_.data_at(vtableoffsetloc),
1867  static_cast<soffset_t>(vt_use) - static_cast<soffset_t>(vtableoffsetloc));
1868 
1869  nested = false;
1870  return vtableoffsetloc;
1871  }
1872 
1873  FLATBUFFERS_ATTRIBUTE(deprecated("call the version above instead"))
1874  uoffset_t EndTable(uoffset_t start, voffset_t /*numfields*/)
1875  {
1876  return EndTable(start);
1877  }
1878 
1879  // This checks a required field has been set in a given table that has
1880  // just been constructed.
1881  template <typename T>
1882  void Required(Offset<T> table, voffset_t field);
1883 
1884  uoffset_t StartStruct(size_t alignment)
1885  {
1886  Align(alignment);
1887  return GetSize();
1888  }
1889 
1890  uoffset_t EndStruct()
1891  {
1892  return GetSize();
1893  }
1894 
1895  void ClearOffsets()
1896  {
1897  buf_.scratch_pop(num_field_loc * sizeof(FieldLoc));
1898  num_field_loc = 0;
1899  max_voffset_ = 0;
1900  }
1901 
1902  // Aligns such that when "len" bytes are written, an object can be written
1903  // after it with "alignment" without padding.
1904  void PreAlign(size_t len, size_t alignment)
1905  {
1906  TrackMinAlign(alignment);
1907  buf_.fill(PaddingBytes(GetSize() + len, alignment));
1908  }
1909  template <typename T>
1910  void PreAlign(size_t len)
1911  {
1912  AssertScalarT<T>();
1913  PreAlign(len, sizeof(T));
1914  }
1916 
1921  Offset<String> CreateString(const char* str, size_t len)
1922  {
1923  NotNested();
1924  PreAlign<uoffset_t>(len + 1); // Always 0-terminated.
1925  buf_.fill(1);
1926  PushBytes(reinterpret_cast<const uint8_t*>(str), len);
1927  PushElement(static_cast<uoffset_t>(len));
1928  return Offset<String>(GetSize());
1929  }
1930 
1934  Offset<String> CreateString(const char* str)
1935  {
1936  return CreateString(str, strlen(str));
1937  }
1938 
1943  {
1944  return CreateString(str, strlen(str));
1945  }
1946 
1950  Offset<String> CreateString(const std::string& str)
1951  {
1952  return CreateString(str.c_str(), str.length());
1953  }
1954 
1955  // clang-format off
1956  #ifdef FLATBUFFERS_HAS_STRING_VIEW
1957  Offset<String> CreateString(flatbuffers::string_view str) {
1961  return CreateString(str.data(), str.size());
1962  }
1963  #endif // FLATBUFFERS_HAS_STRING_VIEW
1964  // clang-format on
1965 
1970  {
1971  return str ? CreateString(str->c_str(), str->size()) : 0;
1972  }
1973 
1978  template <typename T>
1980  {
1981  return CreateString(str.c_str(), str.length());
1982  }
1983 
1990  Offset<String> CreateSharedString(const char* str, size_t len)
1991  {
1992  if (!string_pool)
1993  string_pool = new StringOffsetMap(StringOffsetCompare(buf_));
1994  auto size_before_string = buf_.size();
1995  // Must first serialize the string, since the set is all offsets into
1996  // buffer.
1997  auto off = CreateString(str, len);
1998  auto it = string_pool->find(off);
1999  // If it exists we reuse existing serialized data!
2000  if (it != string_pool->end())
2001  {
2002  // We can remove the string we serialized.
2003  buf_.pop(buf_.size() - size_before_string);
2004  return *it;
2005  }
2006  // Record this string for future use.
2007  string_pool->insert(off);
2008  return off;
2009  }
2010 
2011 #ifdef FLATBUFFERS_HAS_STRING_VIEW
2012  Offset<String> CreateSharedString(const flatbuffers::string_view str)
2018  {
2019  return CreateSharedString(str.data(), str.size());
2020  }
2021 #else
2022  Offset<String> CreateSharedString(const char* str)
2028  {
2029  return CreateSharedString(str, strlen(str));
2030  }
2031 
2037  Offset<String> CreateSharedString(const std::string& str)
2038  {
2039  return CreateSharedString(str.c_str(), str.length());
2040  }
2041 #endif
2042 
2049  {
2050  return CreateSharedString(str->c_str(), str->size());
2051  }
2052 
2054  uoffset_t EndVector(size_t len)
2055  {
2056  FLATBUFFERS_ASSERT(nested); // Hit if no corresponding StartVector.
2057  nested = false;
2058  return PushElement(static_cast<uoffset_t>(len));
2059  }
2060 
2061  void StartVector(size_t len, size_t elemsize)
2062  {
2063  NotNested();
2064  nested = true;
2065  PreAlign<uoffset_t>(len * elemsize);
2066  PreAlign(len * elemsize, elemsize); // Just in case elemsize > uoffset_t.
2067  }
2068 
2069  // Call this right before StartVector/CreateVector if you want to force the
2070  // alignment to be something different than what the element size would
2071  // normally dictate.
2072  // This is useful when storing a nested_flatbuffer in a vector of bytes,
2073  // or when storing SIMD floats, etc.
2074  void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment)
2075  {
2076  FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment));
2077  PreAlign(len * elemsize, alignment);
2078  }
2079 
2080  // Similar to ForceVectorAlignment but for String fields.
2081  void ForceStringAlignment(size_t len, size_t alignment)
2082  {
2083  FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment));
2084  PreAlign((len + 1) * sizeof(char), alignment);
2085  }
2086 
2088 
2096  template <typename T>
2097  Offset<Vector<T>> CreateVector(const T* v, size_t len)
2098  {
2099  // If this assert hits, you're specifying a template argument that is
2100  // causing the wrong overload to be selected, remove it.
2101  AssertScalarT<T>();
2102  StartVector(len, sizeof(T));
2103  if (len == 0)
2104  {
2105  return Offset<Vector<T>>(EndVector(len));
2106  }
2107  // clang-format off
2108  #if FLATBUFFERS_LITTLEENDIAN
2109  PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T));
2110  #else
2111  if (sizeof(T) == 1) {
2112  PushBytes(reinterpret_cast<const uint8_t *>(v), len);
2113  } else {
2114  for (auto i = len; i > 0; ) {
2115  PushElement(v[--i]);
2116  }
2117  }
2118  #endif
2119  // clang-format on
2120  return Offset<Vector<T>>(EndVector(len));
2121  }
2122 
2123  template <typename T>
2125  {
2126  StartVector(len, sizeof(Offset<T>));
2127  for (auto i = len; i > 0;)
2128  {
2129  PushElement(v[--i]);
2130  }
2131  return Offset<Vector<Offset<T>>>(EndVector(len));
2132  }
2133 
2140  template <typename T>
2141  Offset<Vector<T>> CreateVector(const std::vector<T>& v)
2142  {
2143  return CreateVector(data(v), v.size());
2144  }
2145 
2146  // vector<bool> may be implemented using a bit-set, so we can't access it as
2147  // an array. Instead, read elements manually.
2148  // Background: https://isocpp.org/blog/2012/11/on-vectorbool
2149  Offset<Vector<uint8_t>> CreateVector(const std::vector<bool>& v)
2150  {
2151  StartVector(v.size(), sizeof(uint8_t));
2152  for (auto i = v.size(); i > 0;)
2153  {
2154  PushElement(static_cast<uint8_t>(v[--i]));
2155  }
2156  return Offset<Vector<uint8_t>>(EndVector(v.size()));
2157  }
2158 
2159  // clang-format off
2160  #ifndef FLATBUFFERS_CPP98_STL
2161  template<typename T> Offset<Vector<T>> CreateVector(size_t vector_size,
2169  const std::function<T (size_t i)> &f) {
2170  std::vector<T> elems(vector_size);
2171  for (size_t i = 0; i < vector_size; i++) elems[i] = f(i);
2172  return CreateVector(elems);
2173  }
2174  #endif
2175  // clang-format on
2176 
2186  template <typename T, typename F, typename S>
2187  Offset<Vector<T>> CreateVector(size_t vector_size, F f, S* state)
2188  {
2189  std::vector<T> elems(vector_size);
2190  for (size_t i = 0; i < vector_size; i++)
2191  elems[i] = f(i, state);
2192  return CreateVector(elems);
2193  }
2194 
2201  Offset<Vector<Offset<String>>> CreateVectorOfStrings(const std::vector<std::string>& v)
2202  {
2203  std::vector<Offset<String>> offsets(v.size());
2204  for (size_t i = 0; i < v.size(); i++)
2205  offsets[i] = CreateString(v[i]);
2206  return CreateVector(offsets);
2207  }
2208 
2216  template <typename T>
2218  {
2219  StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>());
2220  PushBytes(reinterpret_cast<const uint8_t*>(v), sizeof(T) * len);
2221  return Offset<Vector<const T*>>(EndVector(len));
2222  }
2223 
2234  template <typename T, typename S>
2236  T((*const pack_func)(const S&)))
2237  {
2238  FLATBUFFERS_ASSERT(pack_func);
2239  std::vector<T> vv(len);
2240  std::transform(v, v + len, vv.begin(), pack_func);
2241  return CreateVectorOfStructs<T>(data(vv), vv.size());
2242  }
2243 
2252  template <typename T, typename S>
2254  {
2255  extern T Pack(const S&);
2256  return CreateVectorOfNativeStructs(v, len, Pack);
2257  }
2258 
2259  // clang-format off
2260  #ifndef FLATBUFFERS_CPP98_STL
2261  template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
2270  size_t vector_size, const std::function<void(size_t i, T *)> &filler) {
2271  T* structs = StartVectorOfStructs<T>(vector_size);
2272  for (size_t i = 0; i < vector_size; i++) {
2273  filler(i, structs);
2274  structs++;
2275  }
2276  return EndVectorOfStructs<T>(vector_size);
2277  }
2278  #endif
2279  // clang-format on
2280 
2290  template <typename T, typename F, typename S>
2291  Offset<Vector<const T*>> CreateVectorOfStructs(size_t vector_size, F f, S* state)
2292  {
2293  T* structs = StartVectorOfStructs<T>(vector_size);
2294  for (size_t i = 0; i < vector_size; i++)
2295  {
2296  f(i, structs, state);
2297  structs++;
2298  }
2299  return EndVectorOfStructs<T>(vector_size);
2300  }
2301 
2308  template <typename T, typename Alloc>
2309  Offset<Vector<const T*>> CreateVectorOfStructs(const std::vector<T, Alloc>& v)
2310  {
2311  return CreateVectorOfStructs(data(v), v.size());
2312  }
2313 
2324  template <typename T, typename S>
2326  T((*const pack_func)(const S&)))
2327  {
2328  return CreateVectorOfNativeStructs<T, S>(data(v), v.size(), pack_func);
2329  }
2330 
2339  template <typename T, typename S>
2341  {
2342  return CreateVectorOfNativeStructs<T, S>(data(v), v.size());
2343  }
2344 
2346  template <typename T>
2347  struct StructKeyComparator
2348  {
2349  bool operator()(const T& a, const T& b) const
2350  {
2351  return a.KeyCompareLessThan(&b);
2352  }
2353 
2354  FLATBUFFERS_DELETE_FUNC(StructKeyComparator& operator=(const StructKeyComparator&));
2355  };
2357 
2365  template <typename T>
2367  {
2368  return CreateVectorOfSortedStructs(data(*v), v->size());
2369  }
2370 
2379  template <typename T, typename S>
2381  {
2382  return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size());
2383  }
2384 
2393  template <typename T>
2395  {
2396  std::sort(v, v + len, StructKeyComparator<T>());
2397  return CreateVectorOfStructs(v, len);
2398  }
2399 
2409  template <typename T, typename S>
2411  {
2412  extern T Pack(const S&);
2413  typedef T (*Pack_t)(const S&);
2414  std::vector<T> vv(len);
2415  std::transform(v, v + len, vv.begin(), static_cast<Pack_t&>(Pack));
2416  return CreateVectorOfSortedStructs<T>(vv, len);
2417  }
2418 
2420  template <typename T>
2421  struct TableKeyComparator
2422  {
2423  TableKeyComparator(vector_downward& buf) : buf_(buf)
2424  {}
2425  TableKeyComparator(const TableKeyComparator& other) : buf_(other.buf_)
2426  {}
2427  bool operator()(const Offset<T>& a, const Offset<T>& b) const
2428  {
2429  auto table_a = reinterpret_cast<T*>(buf_.data_at(a.o));
2430  auto table_b = reinterpret_cast<T*>(buf_.data_at(b.o));
2431  return table_a->KeyCompareLessThan(table_b);
2432  }
2433  vector_downward& buf_;
2434 
2435  private:
2436  FLATBUFFERS_DELETE_FUNC(
2437  TableKeyComparator& operator=(const TableKeyComparator& other));
2438  };
2440 
2449  template <typename T>
2451  {
2452  std::sort(v, v + len, TableKeyComparator<T>(buf_));
2453  return CreateVector(v, len);
2454  }
2455 
2463  template <typename T>
2465  {
2466  return CreateVectorOfSortedTables(data(*v), v->size());
2467  }
2468 
2476  uoffset_t CreateUninitializedVector(size_t len, size_t elemsize, uint8_t** buf)
2477  {
2478  NotNested();
2479  StartVector(len, elemsize);
2480  buf_.make_space(len * elemsize);
2481  auto vec_start = GetSize();
2482  auto vec_end = EndVector(len);
2483  *buf = buf_.data_at(vec_start);
2484  return vec_end;
2485  }
2486 
2495  template <typename T>
2497  {
2498  AssertScalarT<T>();
2499  return CreateUninitializedVector(len, sizeof(T), reinterpret_cast<uint8_t**>(buf));
2500  }
2501 
2502  template <typename T>
2504  {
2505  return CreateUninitializedVector(len, sizeof(T), reinterpret_cast<uint8_t**>(buf));
2506  }
2507 
2508  // @brief Create a vector of scalar type T given as input a vector of scalar
2509  // type U, useful with e.g. pre "enum class" enums, or any existing scalar
2510  // data of the wrong type.
2511  template <typename T, typename U>
2512  Offset<Vector<T>> CreateVectorScalarCast(const U* v, size_t len)
2513  {
2514  AssertScalarT<T>();
2515  AssertScalarT<U>();
2516  StartVector(len, sizeof(T));
2517  for (auto i = len; i > 0;)
2518  {
2519  PushElement(static_cast<T>(v[--i]));
2520  }
2521  return Offset<Vector<T>>(EndVector(len));
2522  }
2523 
2525  template <typename T>
2526  Offset<const T*> CreateStruct(const T& structobj)
2527  {
2528  NotNested();
2529  Align(AlignOf<T>());
2530  buf_.push_small(structobj);
2531  return Offset<const T*>(GetSize());
2532  }
2533 
2535  static const size_t kFileIdentifierLength = 4;
2536 
2540  template <typename T>
2541  void Finish(Offset<T> root, const char* file_identifier = nullptr)
2542  {
2543  Finish(root.o, file_identifier, false);
2544  }
2545 
2553  template <typename T>
2554  void FinishSizePrefixed(Offset<T> root, const char* file_identifier = nullptr)
2555  {
2556  Finish(root.o, file_identifier, true);
2557  }
2558 
2560  {
2561  buf_.swap_allocator(other.buf_);
2562  }
2563 
2564 protected:
2565  // You shouldn't really be copying instances of this class.
2567  FlatBufferBuilder& operator=(const FlatBufferBuilder&);
2568 
2569  void Finish(uoffset_t root, const char* file_identifier, bool size_prefix)
2570  {
2571  NotNested();
2572  buf_.clear_scratch();
2573  // This will cause the whole buffer to be aligned.
2574  PreAlign((size_prefix ? sizeof(uoffset_t) : 0) + sizeof(uoffset_t) +
2575  (file_identifier ? kFileIdentifierLength : 0),
2576  minalign_);
2577  if (file_identifier)
2578  {
2579  FLATBUFFERS_ASSERT(strlen(file_identifier) == kFileIdentifierLength);
2580  PushBytes(reinterpret_cast<const uint8_t*>(file_identifier), kFileIdentifierLength);
2581  }
2582  PushElement(ReferTo(root)); // Location of root.
2583  if (size_prefix)
2584  {
2585  PushElement(GetSize());
2586  }
2587  finished = true;
2588  }
2589 
2590  struct FieldLoc
2591  {
2592  uoffset_t off;
2593  voffset_t id;
2594  };
2595 
2597 
2598  // Accumulating offsets of table members while it is being built.
2599  // We store these in the scratch pad of buf_, after the vtable offsets.
2600  uoffset_t num_field_loc;
2601  // Track how much of the vtable is in use, so we can output the most compact
2602  // possible vtable.
2603  voffset_t max_voffset_;
2604 
2605  // Ensure objects are not nested.
2606  bool nested;
2607 
2608  // Ensure the buffer is finished before it is being accessed.
2609  bool finished;
2610 
2611  size_t minalign_;
2612 
2613  bool force_defaults_; // Serialize values equal to their defaults anyway.
2614 
2616 
2618  {
2619  StringOffsetCompare(const vector_downward& buf) : buf_(&buf)
2620  {}
2621  bool operator()(const Offset<String>& a, const Offset<String>& b) const
2622  {
2623  auto stra = reinterpret_cast<const String*>(buf_->data_at(a.o));
2624  auto strb = reinterpret_cast<const String*>(buf_->data_at(b.o));
2625  return StringLessThan(stra->data(), stra->size(), strb->data(), strb->size());
2626  }
2628  };
2629 
2630  // For use with CreateSharedString. Instantiated on first use only.
2631  typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
2632  StringOffsetMap* string_pool;
2633 
2634 private:
2635  // Allocates space for a vector of structures.
2636  // Must be completed with EndVectorOfStructs().
2637  template <typename T>
2638  T* StartVectorOfStructs(size_t vector_size)
2639  {
2640  StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>());
2641  return reinterpret_cast<T*>(buf_.make_space(vector_size * sizeof(T)));
2642  }
2643 
2644  // End the vector of structues in the flatbuffers.
2645  // Vector should have previously be started with StartVectorOfStructs().
2646  template <typename T>
2648  {
2649  return Offset<Vector<const T*>>(EndVector(vector_size));
2650  }
2651 };
2653 
2655 // Helpers to get a typed pointer to the root object contained in the buffer.
2656 template <typename T>
2657 T* GetMutableRoot(void* buf)
2658 {
2659  EndianCheck();
2660  return reinterpret_cast<T*>(reinterpret_cast<uint8_t*>(buf) +
2661  EndianScalar(*reinterpret_cast<uoffset_t*>(buf)));
2662 }
2663 
2664 template <typename T>
2665 const T* GetRoot(const void* buf)
2666 {
2667  return GetMutableRoot<T>(const_cast<void*>(buf));
2668 }
2669 
2670 template <typename T>
2671 const T* GetSizePrefixedRoot(const void* buf)
2672 {
2673  return GetRoot<T>(reinterpret_cast<const uint8_t*>(buf) + sizeof(uoffset_t));
2674 }
2675 
2679 template <typename T>
2680 T* GetMutableTemporaryPointer(FlatBufferBuilder& fbb, Offset<T> offset)
2681 {
2682  return reinterpret_cast<T*>(fbb.GetCurrentBufferPointer() + fbb.GetSize() - offset.o);
2683 }
2684 
2685 template <typename T>
2686 const T* GetTemporaryPointer(FlatBufferBuilder& fbb, Offset<T> offset)
2687 {
2688  return GetMutableTemporaryPointer<T>(fbb, offset);
2689 }
2690 
2698 inline const char* GetBufferIdentifier(const void* buf, bool size_prefixed = false)
2699 {
2700  return reinterpret_cast<const char*>(buf) +
2701  ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t));
2702 }
2703 
2704 // Helper to see if the identifier in a buffer has the expected value.
2705 inline bool BufferHasIdentifier(const void* buf, const char* identifier,
2706  bool size_prefixed = false)
2707 {
2708  return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier,
2710 }
2711 
2712 // Helper class to verify the integrity of a FlatBuffer
2713 class Verifier FLATBUFFERS_FINAL_CLASS
2714 {
2715 public:
2716  Verifier(const uint8_t* buf, size_t buf_len, uoffset_t _max_depth = 64,
2717  uoffset_t _max_tables = 1000000, bool _check_alignment = true) :
2718  buf_(buf),
2719  size_(buf_len),
2720  depth_(0),
2721  max_depth_(_max_depth),
2722  num_tables_(0),
2723  max_tables_(_max_tables),
2724  upper_bound_(0),
2725  check_alignment_(_check_alignment)
2726  {
2727  FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
2728  }
2729 
2730  // Central location where any verification failures register.
2731  bool Check(bool ok) const
2732  {
2733  // clang-format off
2734  #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
2735  FLATBUFFERS_ASSERT(ok);
2736  #endif
2737  #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
2738  if (!ok)
2739  upper_bound_ = 0;
2740  #endif
2741  // clang-format on
2742  return ok;
2743  }
2744 
2745  // Verify any range within the buffer.
2746  bool Verify(size_t elem, size_t elem_len) const
2747  {
2748  // clang-format off
2749  #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
2750  auto upper_bound = elem + elem_len;
2751  if (upper_bound_ < upper_bound)
2752  upper_bound_ = upper_bound;
2753  #endif
2754  // clang-format on
2755  return Check(elem_len < size_ && elem <= size_ - elem_len);
2756  }
2757 
2758  template <typename T>
2759  bool VerifyAlignment(size_t elem) const
2760  {
2761  return Check((elem & (sizeof(T) - 1)) == 0 || !check_alignment_);
2762  }
2763 
2764  // Verify a range indicated by sizeof(T).
2765  template <typename T>
2766  bool Verify(size_t elem) const
2767  {
2768  return VerifyAlignment<T>(elem) && Verify(elem, sizeof(T));
2769  }
2770 
2771  bool VerifyFromPointer(const uint8_t* p, size_t len)
2772  {
2773  auto o = static_cast<size_t>(p - buf_);
2774  return Verify(o, len);
2775  }
2776 
2777  // Verify relative to a known-good base pointer.
2778  bool Verify(const uint8_t* base, voffset_t elem_off, size_t elem_len) const
2779  {
2780  return Verify(static_cast<size_t>(base - buf_) + elem_off, elem_len);
2781  }
2782 
2783  template <typename T>
2784  bool Verify(const uint8_t* base, voffset_t elem_off) const
2785  {
2786  return Verify(static_cast<size_t>(base - buf_) + elem_off, sizeof(T));
2787  }
2788 
2789  // Verify a pointer (may be NULL) of a table type.
2790  template <typename T>
2791  bool VerifyTable(const T* table)
2792  {
2793  return !table || table->Verify(*this);
2794  }
2795 
2796  // Verify a pointer (may be NULL) of any vector type.
2797  template <typename T>
2798  bool VerifyVector(const Vector<T>* vec) const
2799  {
2800  return !vec || VerifyVectorOrString(reinterpret_cast<const uint8_t*>(vec), sizeof(T));
2801  }
2802 
2803  // Verify a pointer (may be NULL) of a vector to struct.
2804  template <typename T>
2805  bool VerifyVector(const Vector<const T*>* vec) const
2806  {
2807  return VerifyVector(reinterpret_cast<const Vector<T>*>(vec));
2808  }
2809 
2810  // Verify a pointer (may be NULL) to string.
2811  bool VerifyString(const String* str) const
2812  {
2813  size_t end;
2814  return !str ||
2815  (VerifyVectorOrString(reinterpret_cast<const uint8_t*>(str), 1, &end) &&
2816  Verify(end, 1) && // Must have terminator
2817  Check(buf_[end] == '\0')); // Terminating byte must be 0.
2818  }
2819 
2820  // Common code between vectors and strings.
2821  bool VerifyVectorOrString(const uint8_t* vec, size_t elem_size,
2822  size_t* end = nullptr) const
2823  {
2824  auto veco = static_cast<size_t>(vec - buf_);
2825  // Check we can read the size field.
2826  if (!Verify<uoffset_t>(veco))
2827  return false;
2828  // Check the whole array. If this is a string, the byte past the array
2829  // must be 0.
2830  auto size = ReadScalar<uoffset_t>(vec);
2831  auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
2832  if (!Check(size < max_elems))
2833  return false; // Protect against byte_size overflowing.
2834  auto byte_size = sizeof(size) + elem_size * size;
2835  if (end)
2836  *end = veco + byte_size;
2837  return Verify(veco, byte_size);
2838  }
2839 
2840  // Special case for string contents, after the above has been called.
2841  bool VerifyVectorOfStrings(const Vector<Offset<String>>* vec) const
2842  {
2843  if (vec)
2844  {
2845  for (uoffset_t i = 0; i < vec->size(); i++)
2846  {
2847  if (!VerifyString(vec->Get(i)))
2848  return false;
2849  }
2850  }
2851  return true;
2852  }
2853 
2854  // Special case for table contents, after the above has been called.
2855  template <typename T>
2856  bool VerifyVectorOfTables(const Vector<Offset<T>>* vec)
2857  {
2858  if (vec)
2859  {
2860  for (uoffset_t i = 0; i < vec->size(); i++)
2861  {
2862  if (!vec->Get(i)->Verify(*this))
2863  return false;
2864  }
2865  }
2866  return true;
2867  }
2868 
2869  __supress_ubsan__("unsigned-integer-overflow") bool VerifyTableStart(
2870  const uint8_t* table)
2871  {
2872  // Check the vtable offset.
2873  auto tableo = static_cast<size_t>(table - buf_);
2874  if (!Verify<soffset_t>(tableo))
2875  return false;
2876  // This offset may be signed, but doing the subtraction unsigned always
2877  // gives the result we want.
2878  auto vtableo = tableo - static_cast<size_t>(ReadScalar<soffset_t>(table));
2879  // Check the vtable size field, then check vtable fits in its entirety.
2880  return VerifyComplexity() && Verify<voffset_t>(vtableo) &&
2881  VerifyAlignment<voffset_t>(ReadScalar<voffset_t>(buf_ + vtableo)) &&
2882  Verify(vtableo, ReadScalar<voffset_t>(buf_ + vtableo));
2883  }
2884 
2885  template <typename T>
2886  bool VerifyBufferFromStart(const char* identifier, size_t start)
2887  {
2888  if (identifier && !Check((size_ >= 2 * sizeof(flatbuffers::uoffset_t) &&
2889  BufferHasIdentifier(buf_ + start, identifier))))
2890  {
2891  return false;
2892  }
2893 
2894  // Call T::Verify, which must be in the generated code for this type.
2895  auto o = VerifyOffset(start);
2896  return o && reinterpret_cast<const T*>(buf_ + start + o)->Verify(*this)
2897  // clang-format off
2898  #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
2899  && GetComputedSize()
2900  #endif
2901  ;
2902  // clang-format on
2903  }
2904 
2905  // Verify this whole buffer, starting with root type T.
2906  template <typename T>
2907  bool VerifyBuffer()
2908  {
2909  return VerifyBuffer<T>(nullptr);
2910  }
2911 
2912  template <typename T>
2913  bool VerifyBuffer(const char* identifier)
2914  {
2915  return VerifyBufferFromStart<T>(identifier, 0);
2916  }
2917 
2918  template <typename T>
2919  bool VerifySizePrefixedBuffer(const char* identifier)
2920  {
2921  return Verify<uoffset_t>(0U) &&
2922  ReadScalar<uoffset_t>(buf_) == size_ - sizeof(uoffset_t) &&
2923  VerifyBufferFromStart<T>(identifier, sizeof(uoffset_t));
2924  }
2925 
2926  uoffset_t VerifyOffset(size_t start) const
2927  {
2928  if (!Verify<uoffset_t>(start))
2929  return 0;
2930  auto o = ReadScalar<uoffset_t>(buf_ + start);
2931  // May not point to itself.
2932  if (!Check(o != 0))
2933  return 0;
2934  // Can't wrap around / buffers are max 2GB.
2935  if (!Check(static_cast<soffset_t>(o) >= 0))
2936  return 0;
2937  // Must be inside the buffer to create a pointer from it (pointer outside
2938  // buffer is UB).
2939  if (!Verify(start + o, 1))
2940  return 0;
2941  return o;
2942  }
2943 
2944  uoffset_t VerifyOffset(const uint8_t* base, voffset_t start) const
2945  {
2946  return VerifyOffset(static_cast<size_t>(base - buf_) + start);
2947  }
2948 
2949  // Called at the start of a table to increase counters measuring data
2950  // structure depth and amount, and possibly bails out with false if
2951  // limits set by the constructor have been hit. Needs to be balanced
2952  // with EndTable().
2953  bool VerifyComplexity()
2954  {
2955  depth_++;
2956  num_tables_++;
2957  return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_);
2958  }
2959 
2960  // Called at the end of a table to pop the depth count.
2961  bool EndTable()
2962  {
2963  depth_--;
2964  return true;
2965  }
2966 
2967  // Returns the message size in bytes
2968  size_t GetComputedSize() const
2969  {
2970  // clang-format off
2971  #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
2972  uintptr_t size = upper_bound_;
2973  // Align the size to uoffset_t
2974  size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
2975  return (size > size_) ? 0 : size;
2976  #else
2977  // Must turn on FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE for this to work.
2978  (void)upper_bound_;
2979  FLATBUFFERS_ASSERT(false);
2980  return 0;
2981  #endif
2982  // clang-format on
2983  }
2984 
2985 private:
2986  const uint8_t* buf_;
2987  size_t size_;
2988  uoffset_t depth_;
2989  uoffset_t max_depth_;
2990  uoffset_t num_tables_;
2991  uoffset_t max_tables_;
2992  mutable size_t upper_bound_;
2993  bool check_alignment_;
2994 };
2995 
2996 // Convenient way to bundle a buffer and its length, to pass it around
2997 // typed by its root.
2998 // A BufferRef does not own its buffer.
2999 struct BufferRefBase
3000 {
3001 }; // for std::is_base_of
3002 template <typename T>
3003 struct BufferRef : BufferRefBase
3004 {
3005  BufferRef() : buf(nullptr), len(0), must_free(false)
3006  {}
3007  BufferRef(uint8_t* _buf, uoffset_t _len) : buf(_buf), len(_len), must_free(false)
3008  {}
3009 
3010  ~BufferRef()
3011  {
3012  if (must_free)
3013  free(buf);
3014  }
3015 
3016  const T* GetRoot() const
3017  {
3018  return flatbuffers::GetRoot<T>(buf);
3019  }
3020 
3021  bool Verify()
3022  {
3023  Verifier verifier(buf, len);
3024  return verifier.VerifyBuffer<T>(nullptr);
3025  }
3026 
3027  uint8_t* buf;
3028  uoffset_t len;
3029  bool must_free;
3030 };
3031 
3032 // "structs" are flat structures that do not have an offset table, thus
3033 // always have all members present and do not support forwards/backwards
3034 // compatible extensions.
3035 
3036 class Struct FLATBUFFERS_FINAL_CLASS
3037 {
3038 public:
3039  template <typename T>
3040  T GetField(uoffset_t o) const
3041  {
3042  return ReadScalar<T>(&data_[o]);
3043  }
3044 
3045  template <typename T>
3046  T GetStruct(uoffset_t o) const
3047  {
3048  return reinterpret_cast<T>(&data_[o]);
3049  }
3050 
3051  const uint8_t* GetAddressOf(uoffset_t o) const
3052  {
3053  return &data_[o];
3054  }
3055  uint8_t* GetAddressOf(uoffset_t o)
3056  {
3057  return &data_[o];
3058  }
3059 
3060 private:
3061  // private constructor & copy constructor: you obtain instances of this
3062  // class by pointing to existing data only
3063  Struct();
3064  Struct(const Struct&);
3065  Struct& operator=(const Struct&);
3066 
3067  uint8_t data_[1];
3068 };
3069 
3070 // "tables" use an offset table (possibly shared) that allows fields to be
3071 // omitted and added at will, but uses an extra indirection to read.
3072 class Table
3073 {
3074 public:
3075  const uint8_t* GetVTable() const
3076  {
3077  return data_ - ReadScalar<soffset_t>(data_);
3078  }
3079 
3080  // This gets the field offset for any of the functions below it, or 0
3081  // if the field was not present.
3082  voffset_t GetOptionalFieldOffset(voffset_t field) const
3083  {
3084  // The vtable offset is always at the start.
3085  auto vtable = GetVTable();
3086  // The first element is the size of the vtable (fields + type id + itself).
3087  auto vtsize = ReadScalar<voffset_t>(vtable);
3088  // If the field we're accessing is outside the vtable, we're reading older
3089  // data, so it's the same as if the offset was 0 (not present).
3090  return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
3091  }
3092 
3093  template <typename T>
3094  T GetField(voffset_t field, T defaultval) const
3095  {
3096  auto field_offset = GetOptionalFieldOffset(field);
3097  return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
3098  }
3099 
3100  template <typename P>
3101  P GetPointer(voffset_t field)
3102  {
3103  auto field_offset = GetOptionalFieldOffset(field);
3104  auto p = data_ + field_offset;
3105  return field_offset ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p)) : nullptr;
3106  }
3107  template <typename P>
3108  P GetPointer(voffset_t field) const
3109  {
3110  return const_cast<Table*>(this)->GetPointer<P>(field);
3111  }
3112 
3113  template <typename P>
3114  P GetStruct(voffset_t field) const
3115  {
3116  auto field_offset = GetOptionalFieldOffset(field);
3117  auto p = const_cast<uint8_t*>(data_ + field_offset);
3118  return field_offset ? reinterpret_cast<P>(p) : nullptr;
3119  }
3120 
3121  template <typename Raw, typename Face>
3122  flatbuffers::Optional<Face> GetOptional(voffset_t field) const
3123  {
3124  auto field_offset = GetOptionalFieldOffset(field);
3125  auto p = data_ + field_offset;
3126  return field_offset ? Optional<Face>(static_cast<Face>(ReadScalar<Raw>(p))) :
3127  Optional<Face>();
3128  }
3129 
3130  template <typename T>
3131  bool SetField(voffset_t field, T val, T def)
3132  {
3133  auto field_offset = GetOptionalFieldOffset(field);
3134  if (!field_offset)
3135  return IsTheSameAs(val, def);
3136  WriteScalar(data_ + field_offset, val);
3137  return true;
3138  }
3139  template <typename T>
3140  bool SetField(voffset_t field, T val)
3141  {
3142  auto field_offset = GetOptionalFieldOffset(field);
3143  if (!field_offset)
3144  return false;
3145  WriteScalar(data_ + field_offset, val);
3146  return true;
3147  }
3148 
3149  bool SetPointer(voffset_t field, const uint8_t* val)
3150  {
3151  auto field_offset = GetOptionalFieldOffset(field);
3152  if (!field_offset)
3153  return false;
3154  WriteScalar(data_ + field_offset,
3155  static_cast<uoffset_t>(val - (data_ + field_offset)));
3156  return true;
3157  }
3158 
3159  uint8_t* GetAddressOf(voffset_t field)
3160  {
3161  auto field_offset = GetOptionalFieldOffset(field);
3162  return field_offset ? data_ + field_offset : nullptr;
3163  }
3164  const uint8_t* GetAddressOf(voffset_t field) const
3165  {
3166  return const_cast<Table*>(this)->GetAddressOf(field);
3167  }
3168 
3169  bool CheckField(voffset_t field) const
3170  {
3171  return GetOptionalFieldOffset(field) != 0;
3172  }
3173 
3174  // Verify the vtable of this table.
3175  // Call this once per table, followed by VerifyField once per field.
3176  bool VerifyTableStart(Verifier& verifier) const
3177  {
3178  return verifier.VerifyTableStart(data_);
3179  }
3180 
3181  // Verify a particular field.
3182  template <typename T>
3183  bool VerifyField(const Verifier& verifier, voffset_t field) const
3184  {
3185  // Calling GetOptionalFieldOffset should be safe now thanks to
3186  // VerifyTable().
3187  auto field_offset = GetOptionalFieldOffset(field);
3188  // Check the actual field.
3189  return !field_offset || verifier.Verify<T>(data_, field_offset);
3190  }
3191 
3192  // VerifyField for required fields.
3193  template <typename T>
3194  bool VerifyFieldRequired(const Verifier& verifier, voffset_t field) const
3195  {
3196  auto field_offset = GetOptionalFieldOffset(field);
3197  return verifier.Check(field_offset != 0) && verifier.Verify<T>(data_, field_offset);
3198  }
3199 
3200  // Versions for offsets.
3201  bool VerifyOffset(const Verifier& verifier, voffset_t field) const
3202  {
3203  auto field_offset = GetOptionalFieldOffset(field);
3204  return !field_offset || verifier.VerifyOffset(data_, field_offset);
3205  }
3206 
3207  bool VerifyOffsetRequired(const Verifier& verifier, voffset_t field) const
3208  {
3209  auto field_offset = GetOptionalFieldOffset(field);
3210  return verifier.Check(field_offset != 0) &&
3211  verifier.VerifyOffset(data_, field_offset);
3212  }
3213 
3214 private:
3215  // private constructor & copy constructor: you obtain instances of this
3216  // class by pointing to existing data only
3217  Table();
3218  Table(const Table& other);
3219  Table& operator=(const Table&);
3220 
3221  uint8_t data_[1];
3222 };
3223 
3224 // This specialization allows avoiding warnings like:
3225 // MSVC C4800: type: forcing value to bool 'true' or 'false'.
3226 template <>
3227 inline flatbuffers::Optional<bool>
3228 Table::GetOptional<uint8_t, bool>(voffset_t field) const
3229 {
3230  auto field_offset = GetOptionalFieldOffset(field);
3231  auto p = data_ + field_offset;
3232  return field_offset ? Optional<bool>(ReadScalar<uint8_t>(p) != 0) : Optional<bool>();
3233 }
3234 
3235 template <typename T>
3236 void FlatBufferBuilder::Required(Offset<T> table, voffset_t field)
3237 {
3238  auto table_ptr = reinterpret_cast<const Table*>(buf_.data_at(table.o));
3239  bool ok = table_ptr->GetOptionalFieldOffset(field) != 0;
3240  // If this fails, the caller will show what field needs to be set.
3241  FLATBUFFERS_ASSERT(ok);
3242  (void)ok;
3243 }
3244 
3249 inline const uint8_t* GetBufferStartFromRootPointer(const void* root)
3250 {
3251  auto table = reinterpret_cast<const Table*>(root);
3252  auto vtable = table->GetVTable();
3253  // Either the vtable is before the root or after the root.
3254  auto start = (std::min)(vtable, reinterpret_cast<const uint8_t*>(root));
3255  // Align to at least sizeof(uoffset_t).
3256  start = reinterpret_cast<const uint8_t*>(reinterpret_cast<uintptr_t>(start) &
3257  ~(sizeof(uoffset_t) - 1));
3258  // Additionally, there may be a file_identifier in the buffer, and the root
3259  // offset. The buffer may have been aligned to any size between
3260  // sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align").
3261  // Sadly, the exact alignment is only known when constructing the buffer,
3262  // since it depends on the presence of values with said alignment properties.
3263  // So instead, we simply look at the next uoffset_t values (root,
3264  // file_identifier, and alignment padding) to see which points to the root.
3265  // None of the other values can "impersonate" the root since they will either
3266  // be 0 or four ASCII characters.
3267  static_assert(FlatBufferBuilder::kFileIdentifierLength == sizeof(uoffset_t), "file_"
3268  "identifie"
3269  "r "
3270  "is "
3271  "assumed "
3272  "to be "
3273  "the same "
3274  "size as "
3275  "uoffset_"
3276  "t");
3277  for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1;
3278  possible_roots; possible_roots--)
3279  {
3280  start -= sizeof(uoffset_t);
3281  if (ReadScalar<uoffset_t>(start) + start == reinterpret_cast<const uint8_t*>(root))
3282  return start;
3283  }
3284  // We didn't find the root, either the "root" passed isn't really a root,
3285  // or the buffer is corrupt.
3286  // Assert, because calling this function with bad data may cause reads
3287  // outside of buffer boundaries.
3288  FLATBUFFERS_ASSERT(false);
3289  return nullptr;
3290 }
3291 
3293 inline uoffset_t GetPrefixedSize(const uint8_t* buf)
3294 {
3295  return ReadScalar<uoffset_t>(buf);
3296 }
3297 
3298 // Base class for native objects (FlatBuffer data de-serialized into native
3299 // C++ data structures).
3300 // Contains no functionality, purely documentative.
3301 struct NativeTable
3302 {
3303 };
3304 
3313 typedef uint64_t hash_value_t;
3314 // clang-format off
3315 #ifdef FLATBUFFERS_CPP98_STL
3316  typedef void (*resolver_function_t)(void **pointer_adr, hash_value_t hash);
3317  typedef hash_value_t (*rehasher_function_t)(void *pointer);
3318 #else
3319  typedef std::function<void (void **pointer_adr, hash_value_t hash)>
3320  resolver_function_t;
3321  typedef std::function<hash_value_t (void *pointer)> rehasher_function_t;
3322 #endif
3323 // clang-format on
3324 
3325 // Helper function to test if a field is present, using any of the field
3326 // enums in the generated code.
3327 // `table` must be a generated table type. Since this is a template parameter,
3328 // this is not typechecked to be a subclass of Table, so beware!
3329 // Note: this function will return false for fields equal to the default
3330 // value, since they're not stored in the buffer (unless force_defaults was
3331 // used).
3332 template <typename T>
3333 bool IsFieldPresent(const T* table, typename T::FlatBuffersVTableOffset field)
3334 {
3335  // Cast, since Table is a private baseclass of any table types.
3336  return reinterpret_cast<const Table*>(table)->CheckField(static_cast<voffset_t>(field));
3337 }
3338 
3339 // Utility function for reverse lookups on the EnumNames*() functions
3340 // (in the generated C++ code)
3341 // names must be NULL terminated.
3342 inline int LookupEnum(const char** names, const char* name)
3343 {
3344  for (const char** p = names; *p; p++)
3345  if (!strcmp(*p, name))
3346  return static_cast<int>(p - names);
3347  return -1;
3348 }
3349 
3350 // These macros allow us to layout a struct with a guarantee that they'll end
3351 // up looking the same on different compilers and platforms.
3352 // It does this by disallowing the compiler to do any padding, and then
3353 // does padding itself by inserting extra padding fields that make every
3354 // element aligned to its own size.
3355 // Additionally, it manually sets the alignment of the struct as a whole,
3356 // which is typically its largest element, or a custom size set in the schema
3357 // by the force_align attribute.
3358 // These are used in the generated code only.
3359 
3360 // clang-format off
3361 #if defined(_MSC_VER)
3362  #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
3363  __pragma(pack(1)) \
3364  struct __declspec(align(alignment))
3365  #define FLATBUFFERS_STRUCT_END(name, size) \
3366  __pragma(pack()) \
3367  static_assert(sizeof(name) == size, "compiler breaks packing rules")
3368 #elif defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
3369  #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
3370  _Pragma("pack(1)") \
3371  struct __attribute__((aligned(alignment)))
3372  #define FLATBUFFERS_STRUCT_END(name, size) \
3373  _Pragma("pack()") \
3374  static_assert(sizeof(name) == size, "compiler breaks packing rules")
3375 #else
3376  #error Unknown compiler, please define structure alignment macros
3377 #endif
3378 // clang-format on
3379 
3380 // Minimal reflection via code generation.
3381 // Besides full-fat reflection (see reflection.h) and parsing/printing by
3382 // loading schemas (see idl.h), we can also have code generation for mimimal
3383 // reflection data which allows pretty-printing and other uses without needing
3384 // a schema or a parser.
3385 // Generate code with --reflect-types (types only) or --reflect-names (names
3386 // also) to enable.
3387 // See minireflect.h for utilities using this functionality.
3388 
3389 // These types are organized slightly differently as the ones in idl.h.
3390 enum SequenceType
3391 {
3392  ST_TABLE,
3393  ST_STRUCT,
3394  ST_UNION,
3395  ST_ENUM
3396 };
3397 
3398 // Scalars have the same order as in idl.h
3399 // clang-format off
3400 #define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \
3401  ET(ET_UTYPE) \
3402  ET(ET_BOOL) \
3403  ET(ET_CHAR) \
3404  ET(ET_UCHAR) \
3405  ET(ET_SHORT) \
3406  ET(ET_USHORT) \
3407  ET(ET_INT) \
3408  ET(ET_UINT) \
3409  ET(ET_LONG) \
3410  ET(ET_ULONG) \
3411  ET(ET_FLOAT) \
3412  ET(ET_DOUBLE) \
3413  ET(ET_STRING) \
3414  ET(ET_SEQUENCE) // See SequenceType.
3415 
3416 enum ElementaryType {
3417  #define FLATBUFFERS_ET(E) E,
3418  FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
3419  #undef FLATBUFFERS_ET
3420 };
3421 
3422 inline const char * const *ElementaryTypeNames() {
3423  static const char * const names[] = {
3424  #define FLATBUFFERS_ET(E) #E,
3425  FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
3426  #undef FLATBUFFERS_ET
3427  };
3428  return names;
3429 }
3430 // clang-format on
3431 
3432 // Basic type info cost just 16bits per field!
3433 // We're explicitly defining the signedness since the signedness of integer
3434 // bitfields is otherwise implementation-defined and causes warnings on older
3435 // GCC compilers.
3436 struct TypeCode
3437 {
3438  // ElementaryType
3439  unsigned short base_type : 4;
3440  // Either vector (in table) or array (in struct)
3441  unsigned short is_repeating : 1;
3442  // Index into type_refs below, or -1 for none.
3443  signed short sequence_ref : 11;
3444 };
3445 
3446 static_assert(sizeof(TypeCode) == 2, "TypeCode");
3447 
3448 struct TypeTable;
3449 
3450 // Signature of the static method present in each type.
3451 typedef const TypeTable* (*TypeFunction)();
3452 
3453 struct TypeTable
3454 {
3455  SequenceType st;
3456  size_t num_elems; // of type_codes, values, names (but not type_refs).
3457  const TypeCode* type_codes; // num_elems count
3458  const TypeFunction* type_refs; // less than num_elems entries (see TypeCode).
3459  const int16_t* array_sizes; // less than num_elems entries (see TypeCode).
3460  const int64_t* values; // Only set for non-consecutive enum/union or structs.
3461  const char* const* names; // Only set if compiled with --reflect-names.
3462 };
3463 
3464 // String which identifies the current version of FlatBuffers.
3465 // flatbuffer_version_string is used by Google developers to identify which
3466 // applications uploaded to Google Play are using this library. This allows
3467 // the development team at Google to determine the popularity of the library.
3468 // How it works: Applications that are uploaded to the Google Play Store are
3469 // scanned for this version string. We track which applications are using it
3470 // to measure popularity. You are free to remove it (of course) but we would
3471 // appreciate if you left it in.
3472 
3473 // Weak linkage is culled by VS & doesn't work on cygwin.
3474 // clang-format off
3475 #if !defined(_WIN32) && !defined(__CYGWIN__)
3476 
3477 extern volatile __attribute__((weak)) const char *flatbuffer_version_string;
3478 volatile __attribute__((weak)) const char *flatbuffer_version_string =
3479  "FlatBuffers "
3480  FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
3481  FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
3482  FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
3483 
3484 #endif // !defined(_WIN32) && !defined(__CYGWIN__)
3485 
3486 #define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\
3487  inline E operator | (E lhs, E rhs){\
3488  return E(T(lhs) | T(rhs));\
3489  }\
3490  inline E operator & (E lhs, E rhs){\
3491  return E(T(lhs) & T(rhs));\
3492  }\
3493  inline E operator ^ (E lhs, E rhs){\
3494  return E(T(lhs) ^ T(rhs));\
3495  }\
3496  inline E operator ~ (E lhs){\
3497  return E(~T(lhs));\
3498  }\
3499  inline E operator |= (E &lhs, E rhs){\
3500  lhs = lhs | rhs;\
3501  return lhs;\
3502  }\
3503  inline E operator &= (E &lhs, E rhs){\
3504  lhs = lhs & rhs;\
3505  return lhs;\
3506  }\
3507  inline E operator ^= (E &lhs, E rhs){\
3508  lhs = lhs ^ rhs;\
3509  return lhs;\
3510  }\
3511  inline bool operator !(E rhs) \
3512  {\
3513  return !bool(T(rhs)); \
3514  }
3515 } // namespace flatbuffers
3517 
3518 // clang-format on
3519 
3520 #endif // FLATBUFFERS_H_
FLATBUFFERS_CONSTEXPR size_t AlignOf()
Definition: flatbuffers.h:107
const_iterator cbegin() const
Definition: flatbuffers.h:623
VectorIterator operator-(const uoffset_t &offset) const
Definition: flatbuffers.h:266
const_reverse_iterator crend() const
Definition: flatbuffers.h:418
Iterator::value_type operator*() const
Definition: flatbuffers.h:287
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:882
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:2394
const T * data(const std::vector< T, Alloc > &v)
Definition: flatbuffers.h:1415
flatbuffers::conditional< scalar_tag::value, void, T * >::type GetMutablePointer(uoffset_t i) const
Definition: flatbuffers.h:647
VectorIterator & operator+=(const uoffset_t &offset)
Definition: flatbuffers.h:247
void Mutate(uoffset_t i, const T &val)
Definition: flatbuffers.h:425
VectorIterator< T, return_type > const_iterator
Definition: flatbuffers.h:577
uint8_t * allocate(size_t size) FLATBUFFERS_OVERRIDE
Definition: flatbuffers.h:909
Allocator * get_custom_allocator()
Definition: flatbuffers.h:1259
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:897
IndirectHelper< T >::return_type return_type
Definition: flatbuffers.h:323
const_reverse_iterator crend() const
Definition: flatbuffers.h:636
VectorIterator operator++(int)
Definition: flatbuffers.h:235
StringOffsetMap * string_pool
Definition: flatbuffers.h:2632
const String * GetAsString(uoffset_t i) const
Definition: flatbuffers.h:357
return_type LookupByKey(K key) const
Definition: flatbuffers.h:471
VectorIterator< T, typename IndirectHelper< T >::mutable_return_type > iterator
Definition: flatbuffers.h:306
const char * c_str() const
Definition: flatbuffers.h:817
void fill(size_t zero_pad_bytes)
Definition: flatbuffers.h:1328
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:1643
FLATBUFFERS_ATTRIBUTE(deprecated("use Release() instead")) DetachedBuffer ReleaseBufferPointer()
Get the released pointer to the serialized buffer.
Definition: flatbuffers.h:1585
const_reverse_iterator rend() const
Definition: flatbuffers.h:398
bool IsTheSameAs(T e, T def)
Definition: flatbuffers.h:37
bool operator()(const Offset< String > &a, const Offset< String > &b) const
Definition: flatbuffers.h:2621
vector_downward(vector_downward &&other)
Definition: flatbuffers.h:1122
const_iterator end() const
Definition: flatbuffers.h:609
const_iterator cend() const
Definition: flatbuffers.h:627
static int KeyCompare(const void *ap, const void *bp)
Definition: flatbuffers.h:500
Vector< Offset< T > > * VectorCast(Vector< Offset< U >> *ptr)
Definition: flatbuffers.h:543
const uint8_t * Data() const
Definition: flatbuffers.h:450
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:2496
voffset_t FieldIndexToOffset(voffset_t field_id)
Definition: flatbuffers.h:1407
VectorIterator & operator=(const VectorIterator &other)
Definition: flatbuffers.h:184
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:2291
FLATBUFFERS_CONSTEXPR uint16_t size() const
Definition: flatbuffers.h:580
void CopyFromSpanImpl(flatbuffers::integral_constant< bool, true >, flatbuffers::span< const T, length > src)
Definition: flatbuffers.h:708
void MutateOffset(uoffset_t i, const uint8_t *val)
Definition: flatbuffers.h:434
const uint8_t * Data() const
Definition: flatbuffers.h:660
return_type Get(uoffset_t i) const
Definition: flatbuffers.h:327
void Finish(Offset< T > root, const char *file_identifier=nullptr)
Finish serializing a buffer by writing the root offset.
Definition: flatbuffers.h:2541
Offset< Vector< T > > CreateVector(const std::vector< T > &v)
Serialize a std::vector into a FlatBuffer vector.
Definition: flatbuffers.h:2141
uint8_t * GetBufferPointer() const
Get the serialized buffer (after you call Finish()).
Definition: flatbuffers.h:1559
E GetEnum(uoffset_t i) const
Definition: flatbuffers.h:342
difference_type operator-(const VectorIterator &other) const
Definition: flatbuffers.h:214
static void dealloc(void *p, size_t)
Definition: flatbuffers.h:919
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:2235
uint8_t * scratch_data() const
Definition: flatbuffers.h:1285
bool operator!=(const VectorIterator &other) const
Definition: flatbuffers.h:209
void MutateImpl(flatbuffers::integral_constant< bool, true >, uoffset_t i, const T &val)
Definition: flatbuffers.h:697
Array< E, length > & CastToArrayOfEnum(T(&arr)[length])
Definition: flatbuffers.h:793
Definition: any.hpp:455
const U * GetAs(uoffset_t i) const
Definition: flatbuffers.h:350
uint8_t * Data()
Definition: flatbuffers.h:455
void swap(linb::any &lhs, linb::any &rhs) noexcept
Definition: any.hpp:457
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:2325
VectorReverseIterator< const_iterator > const_reverse_iterator
Definition: flatbuffers.h:578
void MutateImpl(flatbuffers::integral_constant< bool, false >, uoffset_t i, const T &val)
Definition: flatbuffers.h:703
VectorIterator(const uint8_t *data, uoffset_t i)
Definition: flatbuffers.h:176
Offset< String > CreateString(const char *str, size_t len)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1921
vector_downward(size_t initial_size, Allocator *allocator, bool own_allocator, size_t buffer_minalign)
Definition: flatbuffers.h:1108
Offset< String > CreateString(const char *str)
Store a string in the buffer, which is null-terminated.
Definition: flatbuffers.h:1934
Offset< Vector< const T * > > CreateVectorOfStructs(const T *v, size_t len)
Serialize an array of structs into a FlatBuffer vector.
Definition: flatbuffers.h:2217
IndirectHelper< T >::mutable_return_type mutable_return_type
Definition: flatbuffers.h:324
bool operator<(const VectorIterator &other) const
Definition: flatbuffers.h:204
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:2201
void SwapBufAllocator(FlatBufferBuilder &other)
Definition: flatbuffers.h:2559
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:1456
void swap(vector_downward &other)
Definition: flatbuffers.h:1351
static bool StringLessThan(const char *a_data, uoffset_t a_size, const char *b_data, uoffset_t b_size)
Definition: flatbuffers.h:808
T * StartVectorOfStructs(size_t vector_size)
Definition: flatbuffers.h:2638
void CopyFromSpanImpl(flatbuffers::integral_constant< bool, false >, flatbuffers::span< const T, length > src)
Definition: flatbuffers.h:718
const uint8_t * Data() const
Definition: flatbuffers.h:522
Offset(uoffset_t _o)
Definition: flatbuffers.h:86
const_reverse_iterator crbegin() const
Definition: flatbuffers.h:413
flatbuffers::conditional< scalar_tag::value, T, const T * >::type IndirectHelperType
Definition: flatbuffers.h:572
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:2366
const_iterator begin() const
Definition: flatbuffers.h:605
Offset< String > CreateString(const T &str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1979
uint8_t * GetCurrentBufferPointer() const
Get a pointer to an unfinished buffer.
Definition: flatbuffers.h:1576
Helper class to hold data needed in creation of a FlatBuffer. To serialize data, you typically call o...
Definition: flatbuffers.h:1442
VectorIterator< T, typename IndirectHelper< T >::return_type > const_iterator
Definition: flatbuffers.h:307
static return_type Read(const uint8_t *p, uoffset_t i)
Definition: flatbuffers.h:159
uoffset_t scratch_size() const
Definition: flatbuffers.h:1269
const_iterator cbegin() const
Definition: flatbuffers.h:403
uint8_t * scratch_end() const
Definition: flatbuffers.h:1291
Array< T, length > & CastToArray(T(&arr)[length])
Definition: flatbuffers.h:781
Offset< Vector< const T * > > CreateVectorOfStructs(const std::vector< T, Alloc > &v)
Serialize a std::vector of structs into a FlatBuffer vector.
Definition: flatbuffers.h:2309
const_reverse_iterator rbegin() const
Definition: flatbuffers.h:389
uint8_t * make_space(size_t len)
Definition: flatbuffers.h:1251
mutable_return_type GetMutableObject(uoffset_t i) const
Definition: flatbuffers.h:443
DetachedBuffer(DetachedBuffer &&other)
Definition: flatbuffers.h:980
flatbuffers::integral_constant< bool, flatbuffers::is_scalar< T >::value > scalar_tag
Definition: flatbuffers.h:570
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:942
void Deallocate(Allocator *allocator, uint8_t *p, size_t size)
Definition: flatbuffers.h:934
Offset< Vector< const T * > > EndVectorOfStructs(size_t vector_size)
Definition: flatbuffers.h:2647
return_type operator[](uoffset_t) const
Definition: flatbuffers.h:763
void push(const uint8_t *bytes, size_t num)
Definition: flatbuffers.h:1302
void pop(size_t bytes_to_remove)
Definition: flatbuffers.h:1342
FLATBUFFERS_ATTRIBUTE(deprecated("use size() instead")) uoffset_t Length() const
Definition: flatbuffers.h:317
VectorIterator & operator--()
Definition: flatbuffers.h:253
uint8_t * Allocate(Allocator *allocator, size_t size)
Definition: flatbuffers.h:929
void DedupVtables(bool dedup)
By default vtables are deduped in order to save space.
Definition: flatbuffers.h:1650
void Mutate(uoffset_t i, const T &val)
Definition: flatbuffers.h:654
void push_small(const T &little_endian_t)
Definition: flatbuffers.h:1312
vector_downward & operator=(vector_downward &&other)
Definition: flatbuffers.h:1150
virtual uint8_t * allocate(size_t size)=0
static std::string GetString(const String *str)
Definition: flatbuffers.h:842
uint8_t * Data()
Definition: flatbuffers.h:665
DetachedBuffer Release()
Get the released DetachedBuffer.
Definition: flatbuffers.h:1594
const_iterator cend() const
Definition: flatbuffers.h:408
Offset< String > CreateString(char *str)
Store a string in the buffer, which is null-terminated.
Definition: flatbuffers.h:1942
FlatBufferBuilder & operator=(FlatBufferBuilder &&other)
Move assignment operator for FlatBufferBuilder.
Definition: flatbuffers.h:1499
uoffset_t size() const
Definition: flatbuffers.h:311
VectorIterator operator--(int)
Definition: flatbuffers.h:259
Iterator::value_type operator->() const
Definition: flatbuffers.h:292
void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE
Definition: flatbuffers.h:914
void Finish(uoffset_t root, const char *file_identifier, bool size_prefix)
Definition: flatbuffers.h:2569
return_type Get(uoffset_t i) const
Definition: flatbuffers.h:585
Offset< Vector< uint8_t > > CreateVector(const std::vector< bool > &v)
Definition: flatbuffers.h:2149
void scratch_pop(size_t bytes_to_remove)
Definition: flatbuffers.h:1346
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:1620
void fill_big(size_t zero_pad_bytes)
Definition: flatbuffers.h:1337
void scratch_push_small(const T &t)
Definition: flatbuffers.h:1319
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:2187
void CopyFromSpan(flatbuffers::span< const T, length > src)
Definition: flatbuffers.h:682
#define FLATBUFFERS_ASSERT
Definition: base.h:21
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:2380
VectorReverseIterator< const_iterator > const_reverse_iterator
Definition: flatbuffers.h:309
bool IsInRange(const T &v, const T &low, const T &high)
Definition: flatbuffers.h:73
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:2450
void reallocate(size_t len)
Definition: flatbuffers.h:1385
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:2410
flatbuffers::span< uint8_t > GetBufferSpan() const
Get the serialized buffer (after you call Finish()) as a span.
Definition: flatbuffers.h:1568
uint8_t * data_at(size_t offset) const
Definition: flatbuffers.h:1297
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:2476
static const size_t kFileIdentifierLength
The length of a FlatBuffer file header.
Definition: flatbuffers.h:2535
bool operator==(const VectorIterator &other) const
Definition: flatbuffers.h:199
VectorReverseIterator< iterator > reverse_iterator
Definition: flatbuffers.h:308
const T * data() const
Definition: flatbuffers.h:671
Offset< Vector< T > > CreateVector(const T *v, size_t len)
Serialize an array into a FlatBuffer vector.
Definition: flatbuffers.h:2097
Offset< void > Union() const
Definition: flatbuffers.h:88
uoffset_t size() const
Definition: flatbuffers.h:517
std::random_access_iterator_tag iterator_category
Definition: flatbuffers.h:170
const uint8_t * data() const
Definition: flatbuffers.h:1024
VectorIterator operator+(const uoffset_t &offset) const
Definition: flatbuffers.h:242
static size_t VectorLength(const Vector< T > *v)
Definition: flatbuffers.h:560
std::set< Offset< String >, StringOffsetCompare > StringOffsetMap
Definition: flatbuffers.h:2631
reverse_iterator rbegin()
Definition: flatbuffers.h:385
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:1990
bool IsOutRange(const T &v, const T &low, const T &high)
Definition: flatbuffers.h:66
void swap(message_t &a, message_t &b) ZMQ_NOTHROW
size_t ensure_space(size_t len)
Definition: flatbuffers.h:1238
DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf, size_t reserved, uint8_t *cur, size_t sz)
Definition: flatbuffers.h:967
return_type value_type
Definition: flatbuffers.h:325
DetachedBuffer & operator=(DetachedBuffer &&other)
Definition: flatbuffers.h:997
const_iterator begin() const
Definition: flatbuffers.h:371
Offset< const T * > CreateStruct(const T &structobj)
Write a struct by itself, typically to be part of a union.
Definition: flatbuffers.h:2526
E GetEnum(uoffset_t i) const
Definition: flatbuffers.h:600
VectorIterator(const VectorIterator &other)
Definition: flatbuffers.h:179
VectorIterator & operator=(VectorIterator &&other)
Definition: flatbuffers.h:192
uoffset_t GetSize() const
The current size of the serialized buffer, counting from the end.
Definition: flatbuffers.h:1551
const_iterator end() const
Definition: flatbuffers.h:380
VectorIterator & operator++()
Definition: flatbuffers.h:229
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:2037
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:2554
Offset< String > CreateString(const String *str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1969
Offset< Vector< const T * > > CreateVectorOfNativeStructs(const std::vector< S > &v)
Serialize a std::vector of native structs into a FlatBuffer vector.
Definition: flatbuffers.h:2340
uint8_t * ReleaseRaw(size_t &size, size_t &offset)
Get the released pointer to the serialized buffer.
Definition: flatbuffers.h:1609
void Clear()
Reset all the state in this FlatBufferBuilder so it can be reused to construct another buffer...
Definition: flatbuffers.h:1538
static return_type Read(const uint8_t *p, uoffset_t i)
Definition: flatbuffers.h:136
return_type operator[](uoffset_t i) const
Definition: flatbuffers.h:333
const void * GetStructFromOffset(size_t o) const
Definition: flatbuffers.h:362
return_type operator[](uoffset_t i) const
Definition: flatbuffers.h:591
Offset< Vector< Offset< T > > > CreateVector(const Offset< T > *v, size_t len)
Definition: flatbuffers.h:2124
Offset< String > CreateString(const std::string &str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1950
static const char * GetCstring(const String *str)
Definition: flatbuffers.h:849
static return_type Read(const uint8_t *p, uoffset_t i)
Definition: flatbuffers.h:147
VectorIterator & operator-=(const uoffset_t &offset)
Definition: flatbuffers.h:271
Offset< Vector< const T * > > CreateUninitializedVectorOfStructs(size_t len, T **buf)
Definition: flatbuffers.h:2503
uint8_t * release_raw(size_t &allocated_bytes, size_t &offset)
Definition: flatbuffers.h:1210
void EndianCheck()
Definition: flatbuffers.h:98
std::string str() const
Definition: flatbuffers.h:821
void Swap(FlatBufferBuilder &other)
Definition: flatbuffers.h:1510
IndirectHelper< IndirectHelperType >::return_type return_type
Definition: flatbuffers.h:576
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:2464
bool operator<(const String &o) const
Definition: flatbuffers.h:834
FlatBufferBuilder(FlatBufferBuilder &&other)
Move constructor for FlatBufferBuilder.
Definition: flatbuffers.h:1475
const_reverse_iterator rend() const
Definition: flatbuffers.h:618
virtual void deallocate(uint8_t *p, size_t size)=0
bool IsNull() const
Definition: flatbuffers.h:92
Offset< Vector< const T * > > CreateVectorOfNativeStructs(const S *v, size_t len)
Serialize an array of native structs into a FlatBuffer vector.
Definition: flatbuffers.h:2253
void swap_allocator(vector_downward &other)
Definition: flatbuffers.h:1364
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:2048
const_reverse_iterator crbegin() const
Definition: flatbuffers.h:632
const_reverse_iterator rbegin() const
Definition: flatbuffers.h:614
reverse_iterator rend()
Definition: flatbuffers.h:394
const T * data() const
Definition: flatbuffers.h:461
Offset< Vector< T > > CreateVectorScalarCast(const U *v, size_t len)
Definition: flatbuffers.h:2512


behaviortree_cpp_v3
Author(s): Michele Colledanchise, Davide Faconti
autogenerated on Mon Jul 3 2023 02:50:14