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