FlatBuffers
An open source project by FPL.
 All Classes Namespaces Files Functions Variables Properties Groups Pages
flatbuffers.h
Go to the documentation of this file.
1 /*
2  * Copyright 2014 Google Inc. All rights reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef FLATBUFFERS_H_
18 #define FLATBUFFERS_H_
19 
20 #include <assert.h>
21 
22 #ifndef ARDUINO
23 #include <cstdint>
24 #endif
25 #include <cstddef>
26 #include <cstdlib>
27 #include <cstring>
28 #include <string>
29 #ifndef ARDUINO
30 #include <utility>
31 #else
32 #include <utility.h>
33 #endif
34 #include <type_traits>
35 #include <vector>
36 #include <set>
37 #include <algorithm>
38 #include <memory>
39 
40 #ifdef _STLPORT_VERSION
41  #define FLATBUFFERS_CPP98_STL
42 #endif
43 #ifndef FLATBUFFERS_CPP98_STL
44  #include <functional>
45 #endif
46 
47 /// @cond FLATBUFFERS_INTERNAL
48 #if __cplusplus <= 199711L && \
49  (!defined(_MSC_VER) || _MSC_VER < 1600) && \
50  (!defined(__GNUC__) || \
51  (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400))
52  #error A C++11 compatible compiler with support for the auto typing is \
53  required for FlatBuffers.
54  #error __cplusplus _MSC_VER __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__
55 #endif
56 
57 #if !defined(__clang__) && \
58  defined(__GNUC__) && \
59  (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600)
60  // Backwards compatability for g++ 4.4, and 4.5 which don't have the nullptr
61  // and constexpr keywords. Note the __clang__ check is needed, because clang
62  // presents itself as an older GNUC compiler.
63  #ifndef nullptr_t
64  const class nullptr_t {
65  public:
66  template<class T> inline operator T*() const { return 0; }
67  private:
68  void operator&() const;
69  } nullptr = {};
70  #endif
71  #ifndef constexpr
72  #define constexpr const
73  #endif
74 #endif
75 
76 // The wire format uses a little endian encoding (since that's efficient for
77 // the common platforms).
78 #if defined(__s390x__)
79  #define FLATBUFFERS_LITTLEENDIAN 0
80 #endif // __s390x__
81 #if !defined(FLATBUFFERS_LITTLEENDIAN)
82  #if defined(__GNUC__) || defined(__clang__)
83  #ifdef __BIG_ENDIAN__
84  #define FLATBUFFERS_LITTLEENDIAN 0
85  #else
86  #define FLATBUFFERS_LITTLEENDIAN 1
87  #endif // __BIG_ENDIAN__
88  #elif defined(_MSC_VER)
89  #if defined(_M_PPC)
90  #define FLATBUFFERS_LITTLEENDIAN 0
91  #else
92  #define FLATBUFFERS_LITTLEENDIAN 1
93  #endif
94  #else
95  #error Unable to determine endianness, define FLATBUFFERS_LITTLEENDIAN.
96  #endif
97 #endif // !defined(FLATBUFFERS_LITTLEENDIAN)
98 
99 #define FLATBUFFERS_VERSION_MAJOR 1
100 #define FLATBUFFERS_VERSION_MINOR 6
101 #define FLATBUFFERS_VERSION_REVISION 0
102 #define FLATBUFFERS_STRING_EXPAND(X) #X
103 #define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
104 
105 #if (!defined(_MSC_VER) || _MSC_VER > 1600) && \
106  (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407))
107  #define FLATBUFFERS_FINAL_CLASS final
108 #else
109  #define FLATBUFFERS_FINAL_CLASS
110 #endif
111 
112 #if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
113  (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406))
114  #define FLATBUFFERS_CONSTEXPR constexpr
115 #else
116  #define FLATBUFFERS_CONSTEXPR
117 #endif
118 
119 #if defined(__GXX_EXPERIMENTAL_CXX0X__) && __GNUC__ * 10 + __GNUC_MINOR__ >= 46 || \
120  defined(_MSC_FULL_VER) && _MSC_FULL_VER >= 190023026
121  #define FLATBUFFERS_NOEXCEPT noexcept
122 #else
123  #define FLATBUFFERS_NOEXCEPT
124 #endif
125 
126 #if defined(_MSC_VER)
127 #pragma warning(push)
128 #pragma warning(disable: 4127) // C4127: conditional expression is constant
129 #endif
130 
131 /// @endcond
132 
133 /// @file
134 namespace flatbuffers {
135 
136 /// @cond FLATBUFFERS_INTERNAL
137 // Our default offset / size type, 32bit on purpose on 64bit systems.
138 // Also, using a consistent offset type maintains compatibility of serialized
139 // offset values between 32bit and 64bit systems.
140 typedef uint32_t uoffset_t;
141 
142 // Signed offsets for references that can go in both directions.
143 typedef int32_t soffset_t;
144 
145 // Offset/index used in v-tables, can be changed to uint8_t in
146 // format forks to save a bit of space if desired.
147 typedef uint16_t voffset_t;
148 
149 typedef uintmax_t largest_scalar_t;
150 
151 // In 32bits, this evaluates to 2GB - 1
152 #define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(soffset_t) * 8 - 1)) - 1)
153 
154 // We support aligning the contents of buffers up to this size.
155 #define FLATBUFFERS_MAX_ALIGNMENT 16
156 
157 #ifndef FLATBUFFERS_CPP98_STL
158 // Pointer to relinquished memory.
159 typedef std::unique_ptr<uint8_t, std::function<void(uint8_t * /* unused */)>>
160  unique_ptr_t;
161 #endif
162 
163 // Wrapper for uoffset_t to allow safe template specialization.
164 // Value is allowed to be 0 to indicate a null object (see e.g. AddOffset).
165 template<typename T> struct Offset {
166  uoffset_t o;
167  Offset() : o(0) {}
168  Offset(uoffset_t _o) : o(_o) {}
169  Offset<void> Union() const { return Offset<void>(o); }
170  bool IsNull() const { return !o; }
171 };
172 
173 inline void EndianCheck() {
174  int endiantest = 1;
175  // If this fails, see FLATBUFFERS_LITTLEENDIAN above.
176  assert(*reinterpret_cast<char *>(&endiantest) == FLATBUFFERS_LITTLEENDIAN);
177  (void)endiantest;
178 }
179 
180 template<typename T> T EndianSwap(T t) {
181  #if defined(_MSC_VER)
182  #define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
183  #define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
184  #define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
185  #else
186  #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408
187  // __builtin_bswap16 was missing prior to GCC 4.8.
188  #define FLATBUFFERS_BYTESWAP16(x) \
189  static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16))
190  #else
191  #define FLATBUFFERS_BYTESWAP16 __builtin_bswap16
192  #endif
193  #define FLATBUFFERS_BYTESWAP32 __builtin_bswap32
194  #define FLATBUFFERS_BYTESWAP64 __builtin_bswap64
195  #endif
196  if (sizeof(T) == 1) { // Compile-time if-then's.
197  return t;
198  } else if (sizeof(T) == 2) {
199  auto r = FLATBUFFERS_BYTESWAP16(*reinterpret_cast<uint16_t *>(&t));
200  return *reinterpret_cast<T *>(&r);
201  } else if (sizeof(T) == 4) {
202  auto r = FLATBUFFERS_BYTESWAP32(*reinterpret_cast<uint32_t *>(&t));
203  return *reinterpret_cast<T *>(&r);
204  } else if (sizeof(T) == 8) {
205  auto r = FLATBUFFERS_BYTESWAP64(*reinterpret_cast<uint64_t *>(&t));
206  return *reinterpret_cast<T *>(&r);
207  } else {
208  assert(0);
209  }
210 }
211 
212 template<typename T> T EndianScalar(T t) {
213  #if FLATBUFFERS_LITTLEENDIAN
214  return t;
215  #else
216  return EndianSwap(t);
217  #endif
218 }
219 
220 template<typename T> T ReadScalar(const void *p) {
221  return EndianScalar(*reinterpret_cast<const T *>(p));
222 }
223 
224 template<typename T> void WriteScalar(void *p, T t) {
225  *reinterpret_cast<T *>(p) = EndianScalar(t);
226 }
227 
228 template<typename T> size_t AlignOf() {
229  #ifdef _MSC_VER
230  return __alignof(T);
231  #else
232  #ifndef alignof
233  return __alignof__(T);
234  #else
235  return alignof(T);
236  #endif
237  #endif
238 }
239 
240 // When we read serialized data from memory, in the case of most scalars,
241 // we want to just read T, but in the case of Offset, we want to actually
242 // perform the indirection and return a pointer.
243 // The template specialization below does just that.
244 // It is wrapped in a struct since function templates can't overload on the
245 // return type like this.
246 // The typedef is for the convenience of callers of this function
247 // (avoiding the need for a trailing return decltype)
248 template<typename T> struct IndirectHelper {
249  typedef T return_type;
250  typedef T mutable_return_type;
251  static const size_t element_stride = sizeof(T);
252  static return_type Read(const uint8_t *p, uoffset_t i) {
253  return EndianScalar((reinterpret_cast<const T *>(p))[i]);
254  }
255 };
256 template<typename T> struct IndirectHelper<Offset<T>> {
257  typedef const T *return_type;
258  typedef T *mutable_return_type;
259  static const size_t element_stride = sizeof(uoffset_t);
260  static return_type Read(const uint8_t *p, uoffset_t i) {
261  p += i * sizeof(uoffset_t);
262  return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p));
263  }
264 };
265 template<typename T> struct IndirectHelper<const T *> {
266  typedef const T *return_type;
267  typedef T *mutable_return_type;
268  static const size_t element_stride = sizeof(T);
269  static return_type Read(const uint8_t *p, uoffset_t i) {
270  return reinterpret_cast<const T *>(p + i * sizeof(T));
271  }
272 };
273 
274 // An STL compatible iterator implementation for Vector below, effectively
275 // calling Get() for every element.
276 template<typename T, typename IT>
277 struct VectorIterator
278  : public std::iterator<std::random_access_iterator_tag, IT, uoffset_t> {
279 
280  typedef std::iterator<std::random_access_iterator_tag, IT, uoffset_t> super_type;
281 
282 public:
283  VectorIterator(const uint8_t *data, uoffset_t i) :
284  data_(data + IndirectHelper<T>::element_stride * i) {}
285  VectorIterator(const VectorIterator &other) : data_(other.data_) {}
286  #ifndef FLATBUFFERS_CPP98_STL
287  VectorIterator(VectorIterator &&other) : data_(std::move(other.data_)) {}
288  #endif
289 
290  VectorIterator &operator=(const VectorIterator &other) {
291  data_ = other.data_;
292  return *this;
293  }
294 
295  VectorIterator &operator=(VectorIterator &&other) {
296  data_ = other.data_;
297  return *this;
298  }
299 
300  bool operator==(const VectorIterator &other) const {
301  return data_ == other.data_;
302  }
303 
304  bool operator<(const VectorIterator &other) const {
305  return data_ < other.data_;
306  }
307 
308  bool operator!=(const VectorIterator &other) const {
309  return data_ != other.data_;
310  }
311 
312  ptrdiff_t operator-(const VectorIterator &other) const {
313  return (data_ - other.data_) / IndirectHelper<T>::element_stride;
314  }
315 
316  typename super_type::value_type operator *() const {
317  return IndirectHelper<T>::Read(data_, 0);
318  }
319 
320  typename super_type::value_type operator->() const {
321  return IndirectHelper<T>::Read(data_, 0);
322  }
323 
324  VectorIterator &operator++() {
325  data_ += IndirectHelper<T>::element_stride;
326  return *this;
327  }
328 
329  VectorIterator operator++(int) {
330  VectorIterator temp(data_, 0);
331  data_ += IndirectHelper<T>::element_stride;
332  return temp;
333  }
334 
335  VectorIterator operator+(const uoffset_t &offset) const {
336  return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride, 0);
337  }
338 
339  VectorIterator& operator+=(const uoffset_t &offset) {
340  data_ += offset * IndirectHelper<T>::element_stride;
341  return *this;
342  }
343 
344  VectorIterator &operator--() {
345  data_ -= IndirectHelper<T>::element_stride;
346  return *this;
347  }
348 
349  VectorIterator operator--(int) {
350  VectorIterator temp(data_, 0);
351  data_ -= IndirectHelper<T>::element_stride;
352  return temp;
353  }
354 
355  VectorIterator operator-(const uoffset_t &offset) {
356  return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride, 0);
357  }
358 
359  VectorIterator& operator-=(const uoffset_t &offset) {
360  data_ -= offset * IndirectHelper<T>::element_stride;
361  return *this;
362  }
363 
364 private:
365  const uint8_t *data_;
366 };
367 
368 struct String;
369 
370 // This is used as a helper type for accessing vectors.
371 // Vector::data() assumes the vector elements start after the length field.
372 template<typename T> class Vector {
373 public:
374  typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
375  iterator;
376  typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
377  const_iterator;
378 
379  uoffset_t size() const { return EndianScalar(length_); }
380 
381  // Deprecated: use size(). Here for backwards compatibility.
382  uoffset_t Length() const { return size(); }
383 
384  typedef typename IndirectHelper<T>::return_type return_type;
385  typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
386 
387  return_type Get(uoffset_t i) const {
388  assert(i < size());
389  return IndirectHelper<T>::Read(Data(), i);
390  }
391 
392  return_type operator[](uoffset_t i) const { return Get(i); }
393 
394  // If this is a Vector of enums, T will be its storage type, not the enum
395  // type. This function makes it convenient to retrieve value with enum
396  // type E.
397  template<typename E> E GetEnum(uoffset_t i) const {
398  return static_cast<E>(Get(i));
399  }
400 
401  // If this a vector of unions, this does the cast for you. There's no check
402  // to make sure this is the right type!
403  template<typename U> const U *GetAs(uoffset_t i) const {
404  return reinterpret_cast<const U *>(Get(i));
405  }
406 
407  // If this a vector of unions, this does the cast for you. There's no check
408  // to make sure this is actually a string!
409  const String *GetAsString(uoffset_t i) const {
410  return reinterpret_cast<const String *>(Get(i));
411  }
412 
413  const void *GetStructFromOffset(size_t o) const {
414  return reinterpret_cast<const void *>(Data() + o);
415  }
416 
417  iterator begin() { return iterator(Data(), 0); }
418  const_iterator begin() const { return const_iterator(Data(), 0); }
419 
420  iterator end() { return iterator(Data(), size()); }
421  const_iterator end() const { return const_iterator(Data(), size()); }
422 
423  // Change elements if you have a non-const pointer to this object.
424  // Scalars only. See reflection.h, and the documentation.
425  void Mutate(uoffset_t i, const T& val) {
426  assert(i < size());
427  WriteScalar(data() + i, val);
428  }
429 
430  // Change an element of a vector of tables (or strings).
431  // "val" points to the new table/string, as you can obtain from
432  // e.g. reflection::AddFlatBuffer().
433  void MutateOffset(uoffset_t i, const uint8_t *val) {
434  assert(i < size());
435  assert(sizeof(T) == sizeof(uoffset_t));
436  WriteScalar(data() + i,
437  static_cast<uoffset_t>(val - (Data() + i * sizeof(uoffset_t))));
438  }
439 
440  // Get a mutable pointer to tables/strings inside this vector.
441  mutable_return_type GetMutableObject(uoffset_t i) const {
442  assert(i < size());
443  return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i));
444  }
445 
446  // The raw data in little endian format. Use with care.
447  const uint8_t *Data() const {
448  return reinterpret_cast<const uint8_t *>(&length_ + 1);
449  }
450 
451  uint8_t *Data() {
452  return reinterpret_cast<uint8_t *>(&length_ + 1);
453  }
454 
455  // Similarly, but typed, much like std::vector::data
456  const T *data() const { return reinterpret_cast<const T *>(Data()); }
457  T *data() { return reinterpret_cast<T *>(Data()); }
458 
459  template<typename K> return_type LookupByKey(K key) const {
460  void *search_result = std::bsearch(&key, Data(), size(),
461  IndirectHelper<T>::element_stride, KeyCompare<K>);
462 
463  if (!search_result) {
464  return nullptr; // Key not found.
465  }
466 
467  const uint8_t *element = reinterpret_cast<const uint8_t *>(search_result);
468 
469  return IndirectHelper<T>::Read(element, 0);
470  }
471 
472 protected:
473  // This class is only used to access pre-existing data. Don't ever
474  // try to construct these manually.
475  Vector();
476 
477  uoffset_t length_;
478 
479 private:
480  // This class is a pointer. Copying will therefore create an invalid object.
481  // Private and unimplemented copy constructor.
482  Vector(const Vector&);
483 
484  template<typename K> static int KeyCompare(const void *ap, const void *bp) {
485  const K *key = reinterpret_cast<const K *>(ap);
486  const uint8_t *data = reinterpret_cast<const uint8_t *>(bp);
487  auto table = IndirectHelper<T>::Read(data, 0);
488 
489  // std::bsearch compares with the operands transposed, so we negate the
490  // result here.
491  return -table->KeyCompareWithValue(*key);
492  }
493 };
494 
495 // Represent a vector much like the template above, but in this case we
496 // don't know what the element types are (used with reflection.h).
497 class VectorOfAny {
498 public:
499  uoffset_t size() const { return EndianScalar(length_); }
500 
501  const uint8_t *Data() const {
502  return reinterpret_cast<const uint8_t *>(&length_ + 1);
503  }
504  uint8_t *Data() {
505  return reinterpret_cast<uint8_t *>(&length_ + 1);
506  }
507 protected:
508  VectorOfAny();
509 
510  uoffset_t length_;
511 
512 private:
513  VectorOfAny(const VectorOfAny&);
514 };
515 
516 #ifndef FLATBUFFERS_CPP98_STL
517 template<typename T, typename U>
518 Vector<Offset<T>> *VectorCast(Vector<Offset<U>> *ptr) {
519  static_assert(std::is_base_of<T, U>::value, "Unrelated types");
520  return reinterpret_cast<Vector<Offset<T>> *>(ptr);
521 }
522 
523 template<typename T, typename U>
524 const Vector<Offset<T>> *VectorCast(const Vector<Offset<U>> *ptr) {
525  static_assert(std::is_base_of<T, U>::value, "Unrelated types");
526  return reinterpret_cast<const Vector<Offset<T>> *>(ptr);
527 }
528 #endif
529 
530 // Convenient helper function to get the length of any vector, regardless
531 // of wether it is null or not (the field is not set).
532 template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
533  return v ? v->Length() : 0;
534 }
535 
536 struct String : public Vector<char> {
537  const char *c_str() const { return reinterpret_cast<const char *>(Data()); }
538  std::string str() const { return std::string(c_str(), Length()); }
539 
540  bool operator <(const String &o) const {
541  return strcmp(c_str(), o.c_str()) < 0;
542  }
543 };
544 
545 // Simple indirection for buffer allocation, to allow this to be overridden
546 // with custom allocation (see the FlatBufferBuilder constructor).
547 class simple_allocator {
548  public:
549  virtual ~simple_allocator() {}
550  virtual uint8_t *allocate(size_t size) const { return new uint8_t[size]; }
551  virtual void deallocate(uint8_t *p) const { delete[] p; }
552 };
553 
554 // This is a minimal replication of std::vector<uint8_t> functionality,
555 // except growing from higher to lower addresses. i.e push_back() inserts data
556 // in the lowest address in the vector.
557 class vector_downward {
558  public:
559  explicit vector_downward(size_t initial_size,
560  const simple_allocator &allocator)
561  : reserved_((initial_size + sizeof(largest_scalar_t) - 1) &
562  ~(sizeof(largest_scalar_t) - 1)),
563  buf_(allocator.allocate(reserved_)),
564  cur_(buf_ + reserved_),
565  allocator_(allocator) {}
566 
567  ~vector_downward() {
568  if (buf_)
569  allocator_.deallocate(buf_);
570  }
571 
572  void clear() {
573  if (buf_ == nullptr)
574  buf_ = allocator_.allocate(reserved_);
575 
576  cur_ = buf_ + reserved_;
577  }
578 
579  #ifndef FLATBUFFERS_CPP98_STL
580  // Relinquish the pointer to the caller.
581  unique_ptr_t release() {
582  // Actually deallocate from the start of the allocated memory.
583  std::function<void(uint8_t *)> deleter(
584  std::bind(&simple_allocator::deallocate, allocator_, buf_));
585 
586  // Point to the desired offset.
587  unique_ptr_t retval(data(), deleter);
588 
589  // Don't deallocate when this instance is destroyed.
590  buf_ = nullptr;
591  cur_ = nullptr;
592 
593  return retval;
594  }
595  #endif
596 
597  size_t growth_policy(size_t bytes) {
598  return (bytes / 2) & ~(sizeof(largest_scalar_t) - 1);
599  }
600 
601  uint8_t *make_space(size_t len) {
602  if (len > static_cast<size_t>(cur_ - buf_)) {
603  reallocate(len);
604  }
605  cur_ -= len;
606  // Beyond this, signed offsets may not have enough range:
607  // (FlatBuffers > 2GB not supported).
608  assert(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
609  return cur_;
610  }
611 
612  uoffset_t size() const {
613  assert(cur_ != nullptr && buf_ != nullptr);
614  return static_cast<uoffset_t>(reserved_ - (cur_ - buf_));
615  }
616 
617  uint8_t *data() const {
618  assert(cur_ != nullptr);
619  return cur_;
620  }
621 
622  uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; }
623 
624  void push(const uint8_t *bytes, size_t num) {
625  auto dest = make_space(num);
626  memcpy(dest, bytes, num);
627  }
628 
629  // Specialized version of push() that avoids memcpy call for small data.
630  template<typename T> void push_small(const T& little_endian_t) {
631  auto dest = make_space(sizeof(T));
632  *reinterpret_cast<T *>(dest) = little_endian_t;
633  }
634 
635  // fill() is most frequently called with small byte counts (<= 4),
636  // which is why we're using loops rather than calling memset.
637  void fill(size_t zero_pad_bytes) {
638  auto dest = make_space(zero_pad_bytes);
639  for (size_t i = 0; i < zero_pad_bytes; i++) dest[i] = 0;
640  }
641 
642  // Version for when we know the size is larger.
643  void fill_big(size_t zero_pad_bytes) {
644  auto dest = make_space(zero_pad_bytes);
645  memset(dest, 0, zero_pad_bytes);
646  }
647 
648  void pop(size_t bytes_to_remove) { cur_ += bytes_to_remove; }
649 
650  private:
651  // You shouldn't really be copying instances of this class.
652  vector_downward(const vector_downward &);
653  vector_downward &operator=(const vector_downward &);
654 
655  size_t reserved_;
656  uint8_t *buf_;
657  uint8_t *cur_; // Points at location between empty (below) and used (above).
658  const simple_allocator &allocator_;
659 
660  void reallocate(size_t len) {
661  auto old_size = size();
662  auto largest_align = AlignOf<largest_scalar_t>();
663  reserved_ += (std::max)(len, growth_policy(reserved_));
664  // Round up to avoid undefined behavior from unaligned loads and stores.
665  reserved_ = (reserved_ + (largest_align - 1)) & ~(largest_align - 1);
666  auto new_buf = allocator_.allocate(reserved_);
667  auto new_cur = new_buf + reserved_ - old_size;
668  memcpy(new_cur, cur_, old_size);
669  cur_ = new_cur;
670  allocator_.deallocate(buf_);
671  buf_ = new_buf;
672  }
673 };
674 
675 // Converts a Field ID to a virtual table offset.
676 inline voffset_t FieldIndexToOffset(voffset_t field_id) {
677  // Should correspond to what EndTable() below builds up.
678  const int fixed_fields = 2; // Vtable size and Object Size.
679  return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t));
680 }
681 
682 // Computes how many bytes you'd have to pad to be able to write an
683 // "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in
684 // memory).
685 inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
686  return ((~buf_size) + 1) & (scalar_size - 1);
687 }
688 
689 template <typename T> const T* data(const std::vector<T> &v) {
690  return v.empty() ? nullptr : &v.front();
691 }
692 template <typename T> T* data(std::vector<T> &v) {
693  return v.empty() ? nullptr : &v.front();
694 }
695 
696 /// @endcond
697 
698 /// @addtogroup flatbuffers_cpp_api
699 /// @{
700 /// @class FlatBufferBuilder
701 /// @brief Helper class to hold data needed in creation of a FlatBuffer.
702 /// To serialize data, you typically call one of the `Create*()` functions in
703 /// the generated code, which in turn call a sequence of `StartTable`/
704 /// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/
705 /// `CreateVector` functions. Do this is depth-first order to build up a tree to
706 /// the root. `Finish()` wraps up the buffer ready for transport.
708 /// @cond FLATBUFFERS_INTERNAL
709 FLATBUFFERS_FINAL_CLASS
710 /// @endcond
711 {
712  public:
713  /// @brief Default constructor for FlatBufferBuilder.
714  /// @param[in] initial_size The initial size of the buffer, in bytes. Defaults
715  /// to`1024`.
716  /// @param[in] allocator A pointer to the `simple_allocator` that should be
717  /// used. Defaults to `nullptr`, which means the `default_allocator` will be
718  /// be used.
719  explicit FlatBufferBuilder(uoffset_t initial_size = 1024,
720  const simple_allocator *allocator = nullptr)
721  : buf_(initial_size, allocator ? *allocator : default_allocator),
722  nested(false), finished(false), minalign_(1), force_defaults_(false),
723  dedup_vtables_(true), string_pool(nullptr) {
724  offsetbuf_.reserve(16); // Avoid first few reallocs.
725  vtables_.reserve(16);
726  EndianCheck();
727  }
728 
729  ~FlatBufferBuilder() {
730  if (string_pool) delete string_pool;
731  }
732 
733  /// @brief Reset all the state in this FlatBufferBuilder so it can be reused
734  /// to construct another buffer.
735  void Clear() {
736  buf_.clear();
737  offsetbuf_.clear();
738  nested = false;
739  finished = false;
740  vtables_.clear();
741  minalign_ = 1;
742  if (string_pool) string_pool->clear();
743  }
744 
745  /// @brief The current size of the serialized buffer, counting from the end.
746  /// @return Returns an `uoffset_t` with the current size of the buffer.
747  uoffset_t GetSize() const { return buf_.size(); }
748 
749  /// @brief Get the serialized buffer (after you call `Finish()`).
750  /// @return Returns an `uint8_t` pointer to the FlatBuffer data inside the
751  /// buffer.
752  uint8_t *GetBufferPointer() const {
753  Finished();
754  return buf_.data();
755  }
756 
757  /// @brief Get a pointer to an unfinished buffer.
758  /// @return Returns a `uint8_t` pointer to the unfinished buffer.
759  uint8_t *GetCurrentBufferPointer() const { return buf_.data(); }
760 
761  #ifndef FLATBUFFERS_CPP98_STL
762  /// @brief Get the released pointer to the serialized buffer.
763  /// @warning Do NOT attempt to use this FlatBufferBuilder afterwards!
764  /// @return The `unique_ptr` returned has a special allocator that knows how
765  /// to deallocate this pointer (since it points to the middle of an
766  /// allocation). Thus, do not mix this pointer with other `unique_ptr`'s, or
767  /// call `release()`/`reset()` on it.
768  unique_ptr_t ReleaseBufferPointer() {
769  Finished();
770  return buf_.release();
771  }
772  #endif
773 
774  /// @brief get the minimum alignment this buffer needs to be accessed
775  /// properly. This is only known once all elements have been written (after
776  /// you call Finish()). You can use this information if you need to embed
777  /// a FlatBuffer in some other buffer, such that you can later read it
778  /// without first having to copy it into its own buffer.
780  Finished();
781  return minalign_;
782  }
783 
784  /// @cond FLATBUFFERS_INTERNAL
785  void Finished() const {
786  // If you get this assert, you're attempting to get access a buffer
787  // which hasn't been finished yet. Be sure to call
788  // FlatBufferBuilder::Finish with your root table.
789  // If you really need to access an unfinished buffer, call
790  // GetCurrentBufferPointer instead.
791  assert(finished);
792  }
793  /// @endcond
794 
795  /// @brief In order to save space, fields that are set to their default value
796  /// don't get serialized into the buffer.
797  /// @param[in] bool fd When set to `true`, always serializes default values.
798  void ForceDefaults(bool fd) { force_defaults_ = fd; }
799 
800  /// @brief By default vtables are deduped in order to save space.
801  /// @param[in] bool dedup When set to `true`, dedup vtables.
802  void DedupVtables(bool dedup) { dedup_vtables_ = dedup; }
803 
804  /// @cond FLATBUFFERS_INTERNAL
805  void Pad(size_t num_bytes) { buf_.fill(num_bytes); }
806 
807  void Align(size_t elem_size) {
808  if (elem_size > minalign_) minalign_ = elem_size;
809  buf_.fill(PaddingBytes(buf_.size(), elem_size));
810  }
811 
812  void PushFlatBuffer(const uint8_t *bytes, size_t size) {
813  PushBytes(bytes, size);
814  finished = true;
815  }
816 
817  void PushBytes(const uint8_t *bytes, size_t size) {
818  buf_.push(bytes, size);
819  }
820 
821  void PopBytes(size_t amount) { buf_.pop(amount); }
822 
823  template<typename T> void AssertScalarT() {
824  #ifndef FLATBUFFERS_CPP98_STL
825  // The code assumes power of 2 sizes and endian-swap-ability.
826  static_assert(std::is_scalar<T>::value, "T must be a scalar type");
827  #endif
828  }
829 
830  // Write a single aligned scalar to the buffer
831  template<typename T> uoffset_t PushElement(T element) {
832  AssertScalarT<T>();
833  T litle_endian_element = EndianScalar(element);
834  Align(sizeof(T));
835  buf_.push_small(litle_endian_element);
836  return GetSize();
837  }
838 
839  template<typename T> uoffset_t PushElement(Offset<T> off) {
840  // Special case for offsets: see ReferTo below.
841  return PushElement(ReferTo(off.o));
842  }
843 
844  // When writing fields, we track where they are, so we can create correct
845  // vtables later.
846  void TrackField(voffset_t field, uoffset_t off) {
847  FieldLoc fl = { off, field };
848  offsetbuf_.push_back(fl);
849  }
850 
851  // Like PushElement, but additionally tracks the field this represents.
852  template<typename T> void AddElement(voffset_t field, T e, T def) {
853  // We don't serialize values equal to the default.
854  if (e == def && !force_defaults_) return;
855  auto off = PushElement(e);
856  TrackField(field, off);
857  }
858 
859  template<typename T> void AddOffset(voffset_t field, Offset<T> off) {
860  if (off.IsNull()) return; // Don't store.
861  AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
862  }
863 
864  template<typename T> void AddStruct(voffset_t field, const T *structptr) {
865  if (!structptr) return; // Default, don't store.
866  Align(AlignOf<T>());
867  buf_.push_small(*structptr);
868  TrackField(field, GetSize());
869  }
870 
871  void AddStructOffset(voffset_t field, uoffset_t off) {
872  TrackField(field, off);
873  }
874 
875  // Offsets initially are relative to the end of the buffer (downwards).
876  // This function converts them to be relative to the current location
877  // in the buffer (when stored here), pointing upwards.
878  uoffset_t ReferTo(uoffset_t off) {
879  // Align to ensure GetSize() below is correct.
880  Align(sizeof(uoffset_t));
881  // Offset must refer to something already in buffer.
882  assert(off && off <= GetSize());
883  return GetSize() - off + static_cast<uoffset_t>(sizeof(uoffset_t));
884  }
885 
886  void NotNested() {
887  // If you hit this, you're trying to construct a Table/Vector/String
888  // during the construction of its parent table (between the MyTableBuilder
889  // and table.Finish().
890  // Move the creation of these sub-objects to above the MyTableBuilder to
891  // not get this assert.
892  // Ignoring this assert may appear to work in simple cases, but the reason
893  // it is here is that storing objects in-line may cause vtable offsets
894  // to not fit anymore. It also leads to vtable duplication.
895  assert(!nested);
896  }
897 
898  // From generated code (or from the parser), we call StartTable/EndTable
899  // with a sequence of AddElement calls in between.
900  uoffset_t StartTable() {
901  NotNested();
902  nested = true;
903  return GetSize();
904  }
905 
906  // This finishes one serialized object by generating the vtable if it's a
907  // table, comparing it against existing vtables, and writing the
908  // resulting vtable offset.
909  uoffset_t EndTable(uoffset_t start, voffset_t numfields) {
910  // If you get this assert, a corresponding StartTable wasn't called.
911  assert(nested);
912  // Write the vtable offset, which is the start of any Table.
913  // We fill it's value later.
914  auto vtableoffsetloc = PushElement<soffset_t>(0);
915  // Write a vtable, which consists entirely of voffset_t elements.
916  // It starts with the number of offsets, followed by a type id, followed
917  // by the offsets themselves. In reverse:
918  buf_.fill_big(numfields * sizeof(voffset_t));
919  auto table_object_size = vtableoffsetloc - start;
920  assert(table_object_size < 0x10000); // Vtable use 16bit offsets.
921  PushElement<voffset_t>(static_cast<voffset_t>(table_object_size));
922  PushElement<voffset_t>(FieldIndexToOffset(numfields));
923  // Write the offsets into the table
924  for (auto field_location = offsetbuf_.begin();
925  field_location != offsetbuf_.end();
926  ++field_location) {
927  auto pos = static_cast<voffset_t>(vtableoffsetloc - field_location->off);
928  // If this asserts, it means you've set a field twice.
929  assert(!ReadScalar<voffset_t>(buf_.data() + field_location->id));
930  WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
931  }
932  offsetbuf_.clear();
933  auto vt1 = reinterpret_cast<voffset_t *>(buf_.data());
934  auto vt1_size = ReadScalar<voffset_t>(vt1);
935  auto vt_use = GetSize();
936  // See if we already have generated a vtable with this exact same
937  // layout before. If so, make it point to the old one, remove this one.
938  if (dedup_vtables_) {
939  for (auto it = vtables_.begin(); it != vtables_.end(); ++it) {
940  auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*it));
941  auto vt2_size = *vt2;
942  if (vt1_size != vt2_size || memcmp(vt2, vt1, vt1_size)) continue;
943  vt_use = *it;
944  buf_.pop(GetSize() - vtableoffsetloc);
945  break;
946  }
947  }
948  // If this is a new vtable, remember it.
949  if (vt_use == GetSize()) {
950  vtables_.push_back(vt_use);
951  }
952  // Fill the vtable offset we created above.
953  // The offset points from the beginning of the object to where the
954  // vtable is stored.
955  // Offsets default direction is downward in memory for future format
956  // flexibility (storing all vtables at the start of the file).
957  WriteScalar(buf_.data_at(vtableoffsetloc),
958  static_cast<soffset_t>(vt_use) -
959  static_cast<soffset_t>(vtableoffsetloc));
960 
961  nested = false;
962  return vtableoffsetloc;
963  }
964 
965  // This checks a required field has been set in a given table that has
966  // just been constructed.
967  template<typename T> void Required(Offset<T> table, voffset_t field) {
968  auto table_ptr = buf_.data_at(table.o);
969  auto vtable_ptr = table_ptr - ReadScalar<soffset_t>(table_ptr);
970  bool ok = ReadScalar<voffset_t>(vtable_ptr + field) != 0;
971  // If this fails, the caller will show what field needs to be set.
972  assert(ok);
973  (void)ok;
974  }
975 
976  uoffset_t StartStruct(size_t alignment) {
977  Align(alignment);
978  return GetSize();
979  }
980 
981  uoffset_t EndStruct() { return GetSize(); }
982 
983  void ClearOffsets() { offsetbuf_.clear(); }
984 
985  // Aligns such that when "len" bytes are written, an object can be written
986  // after it with "alignment" without padding.
987  void PreAlign(size_t len, size_t alignment) {
988  buf_.fill(PaddingBytes(GetSize() + len, alignment));
989  }
990  template<typename T> void PreAlign(size_t len) {
991  AssertScalarT<T>();
992  PreAlign(len, sizeof(T));
993  }
994  /// @endcond
995 
996  /// @brief Store a string in the buffer, which can contain any binary data.
997  /// @param[in] str A const char pointer to the data to be stored as a string.
998  /// @param[in] len The number of bytes that should be stored from `str`.
999  /// @return Returns the offset in the buffer where the string starts.
1000  Offset<String> CreateString(const char *str, size_t len) {
1001  NotNested();
1002  PreAlign<uoffset_t>(len + 1); // Always 0-terminated.
1003  buf_.fill(1);
1004  PushBytes(reinterpret_cast<const uint8_t *>(str), len);
1005  PushElement(static_cast<uoffset_t>(len));
1006  return Offset<String>(GetSize());
1007  }
1008 
1009  /// @brief Store a string in the buffer, which is null-terminated.
1010  /// @param[in] str A const char pointer to a C-string to add to the buffer.
1011  /// @return Returns the offset in the buffer where the string starts.
1012  Offset<String> CreateString(const char *str) {
1013  return CreateString(str, strlen(str));
1014  }
1015 
1016  /// @brief Store a string in the buffer, which can contain any binary data.
1017  /// @param[in] str A const reference to a std::string to store in the buffer.
1018  /// @return Returns the offset in the buffer where the string starts.
1019  Offset<String> CreateString(const std::string &str) {
1020  return CreateString(str.c_str(), str.length());
1021  }
1022 
1023  /// @brief Store a string in the buffer, which can contain any binary data.
1024  /// @param[in] str A const pointer to a `String` struct to add to the buffer.
1025  /// @return Returns the offset in the buffer where the string starts
1026  Offset<String> CreateString(const String *str) {
1027  return str ? CreateString(str->c_str(), str->Length()) : 0;
1028  }
1029 
1030  /// @brief Store a string in the buffer, which can contain any binary data.
1031  /// @param[in] str A const reference to a std::string like type with support
1032  /// of T::c_str() and T::length() to store in the buffer.
1033  /// @return Returns the offset in the buffer where the string starts.
1034  template<typename T>
1035  Offset<String> CreateString(const T &str) {
1036  return CreateString(str.c_str(), str.length());
1037  }
1038 
1039  /// @brief Store a string in the buffer, which can contain any binary data.
1040  /// If a string with this exact contents has already been serialized before,
1041  /// instead simply returns the offset of the existing string.
1042  /// @param[in] str A const char pointer to the data to be stored as a string.
1043  /// @param[in] len The number of bytes that should be stored from `str`.
1044  /// @return Returns the offset in the buffer where the string starts.
1045  Offset<String> CreateSharedString(const char *str, size_t len) {
1046  if (!string_pool)
1047  string_pool = new StringOffsetMap(StringOffsetCompare(buf_));
1048  auto size_before_string = buf_.size();
1049  // Must first serialize the string, since the set is all offsets into
1050  // buffer.
1051  auto off = CreateString(str, len);
1052  auto it = string_pool->find(off);
1053  // If it exists we reuse existing serialized data!
1054  if (it != string_pool->end()) {
1055  // We can remove the string we serialized.
1056  buf_.pop(buf_.size() - size_before_string);
1057  return *it;
1058  }
1059  // Record this string for future use.
1060  string_pool->insert(off);
1061  return off;
1062  }
1063 
1064  /// @brief Store a string in the buffer, which null-terminated.
1065  /// If a string with this exact contents has already been serialized before,
1066  /// instead simply returns the offset of the existing string.
1067  /// @param[in] str A const char pointer to a C-string to add to the buffer.
1068  /// @return Returns the offset in the buffer where the string starts.
1069  Offset<String> CreateSharedString(const char *str) {
1070  return CreateSharedString(str, strlen(str));
1071  }
1072 
1073  /// @brief Store a string in the buffer, which can contain any binary data.
1074  /// If a string with this exact contents has already been serialized before,
1075  /// instead simply returns the offset of the existing string.
1076  /// @param[in] str A const reference to a std::string to store in the buffer.
1077  /// @return Returns the offset in the buffer where the string starts.
1078  Offset<String> CreateSharedString(const std::string &str) {
1079  return CreateSharedString(str.c_str(), str.length());
1080  }
1081 
1082  /// @brief Store a string in the buffer, which can contain any binary data.
1083  /// If a string with this exact contents has already been serialized before,
1084  /// instead simply returns the offset of the existing string.
1085  /// @param[in] str A const pointer to a `String` struct to add to the buffer.
1086  /// @return Returns the offset in the buffer where the string starts
1087  Offset<String> CreateSharedString(const String *str) {
1088  return CreateSharedString(str->c_str(), str->Length());
1089  }
1090 
1091  /// @cond FLATBUFFERS_INTERNAL
1092  uoffset_t EndVector(size_t len) {
1093  assert(nested); // Hit if no corresponding StartVector.
1094  nested = false;
1095  return PushElement(static_cast<uoffset_t>(len));
1096  }
1097 
1098  void StartVector(size_t len, size_t elemsize) {
1099  NotNested();
1100  nested = true;
1101  PreAlign<uoffset_t>(len * elemsize);
1102  PreAlign(len * elemsize, elemsize); // Just in case elemsize > uoffset_t.
1103  }
1104 
1105  // Call this right before StartVector/CreateVector if you want to force the
1106  // alignment to be something different than what the element size would
1107  // normally dictate.
1108  // This is useful when storing a nested_flatbuffer in a vector of bytes,
1109  // or when storing SIMD floats, etc.
1110  void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment) {
1111  PreAlign(len * elemsize, alignment);
1112  }
1113 
1114  uint8_t *ReserveElements(size_t len, size_t elemsize) {
1115  return buf_.make_space(len * elemsize);
1116  }
1117  /// @endcond
1118 
1119  /// @brief Serialize an array into a FlatBuffer `vector`.
1120  /// @tparam T The data type of the array elements.
1121  /// @param[in] v A pointer to the array of type `T` to serialize into the
1122  /// buffer as a `vector`.
1123  /// @param[in] len The number of elements to serialize.
1124  /// @return Returns a typed `Offset` into the serialized data indicating
1125  /// where the vector is stored.
1126  template<typename T> Offset<Vector<T>> CreateVector(const T *v, size_t len) {
1127  StartVector(len, sizeof(T));
1128  if (sizeof(T) == 1) {
1129  PushBytes(reinterpret_cast<const uint8_t *>(v), len);
1130  } else {
1131  for (auto i = len; i > 0; ) {
1132  PushElement(v[--i]);
1133  }
1134  }
1135  return Offset<Vector<T>>(EndVector(len));
1136  }
1137 
1138  /// @brief Serialize a `std::vector` into a FlatBuffer `vector`.
1139  /// @tparam T The data type of the `std::vector` elements.
1140  /// @param v A const reference to the `std::vector` to serialize into the
1141  /// buffer as a `vector`.
1142  /// @return Returns a typed `Offset` into the serialized data indicating
1143  /// where the vector is stored.
1144  template<typename T> Offset<Vector<T>> CreateVector(const std::vector<T> &v) {
1145  return CreateVector(data(v), v.size());
1146  }
1147 
1148  // vector<bool> may be implemented using a bit-set, so we can't access it as
1149  // an array. Instead, read elements manually.
1150  // Background: https://isocpp.org/blog/2012/11/on-vectorbool
1151  Offset<Vector<uint8_t>> CreateVector(const std::vector<bool> &v) {
1152  StartVector(v.size(), sizeof(uint8_t));
1153  for (auto i = v.size(); i > 0; ) {
1154  PushElement(static_cast<uint8_t>(v[--i]));
1155  }
1156  return Offset<Vector<uint8_t>>(EndVector(v.size()));
1157  }
1158 
1159  #ifndef FLATBUFFERS_CPP98_STL
1160  /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
1161  /// This is a convenience function that takes care of iteration for you.
1162  /// @tparam T The data type of the `std::vector` elements.
1163  /// @param f A function that takes the current iteration 0..vector_size-1 and
1164  /// returns any type that you can construct a FlatBuffers vector out of.
1165  /// @return Returns a typed `Offset` into the serialized data indicating
1166  /// where the vector is stored.
1167  template<typename T> Offset<Vector<T>> CreateVector(size_t vector_size,
1168  const std::function<T (size_t i)> &f) {
1169  std::vector<T> elems(vector_size);
1170  for (size_t i = 0; i < vector_size; i++) elems[i] = f(i);
1171  return CreateVector(elems);
1172  }
1173  #endif
1174 
1175  /// @brief Serialize a `std::vector<std::string>` into a FlatBuffer `vector`.
1176  /// This is a convenience function for a common case.
1177  /// @param v A const reference to the `std::vector` to serialize into the
1178  /// buffer as a `vector`.
1179  /// @return Returns a typed `Offset` into the serialized data indicating
1180  /// where the vector is stored.
1181  Offset<Vector<Offset<String>>> CreateVectorOfStrings(
1182  const std::vector<std::string> &v) {
1183  std::vector<Offset<String>> offsets(v.size());
1184  for (size_t i = 0; i < v.size(); i++) offsets[i] = CreateString(v[i]);
1185  return CreateVector(offsets);
1186  }
1187 
1188  /// @brief Serialize an array of structs into a FlatBuffer `vector`.
1189  /// @tparam T The data type of the struct array elements.
1190  /// @param[in] v A pointer to the array of type `T` to serialize into the
1191  /// buffer as a `vector`.
1192  /// @param[in] len The number of elements to serialize.
1193  /// @return Returns a typed `Offset` into the serialized data indicating
1194  /// where the vector is stored.
1195  template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
1196  const T *v, size_t len) {
1197  StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>());
1198  PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
1199  return Offset<Vector<const T *>>(EndVector(len));
1200  }
1201 
1202  /// @brief Serialize an array of native structs into a FlatBuffer `vector`.
1203  /// @tparam T The data type of the struct array elements.
1204  /// @tparam S The data type of the native struct array elements.
1205  /// @param[in] v A pointer to the array of type `S` to serialize into the
1206  /// buffer as a `vector`.
1207  /// @param[in] len The number of elements to serialize.
1208  /// @return Returns a typed `Offset` into the serialized data indicating
1209  /// where the vector is stored.
1210  template<typename T, typename S> Offset<Vector<const T *>> CreateVectorOfNativeStructs(
1211  const S *v, size_t len) {
1212  extern T Pack(const S&);
1213  typedef T (*Pack_t)(const S&);
1214  std::vector<T> vv(len);
1215  std::transform(v, v+len, vv.begin(), *(Pack_t)&Pack);
1216  return CreateVectorOfStructs<T>(vv.data(), vv.size());
1217  }
1218 
1219 
1220  #ifndef FLATBUFFERS_CPP98_STL
1221  /// @brief Serialize an array of structs into a FlatBuffer `vector`.
1222  /// @tparam T The data type of the struct array elements.
1223  /// @param[in] f A function that takes the current iteration 0..vector_size-1
1224  /// and a pointer to the struct that must be filled.
1225  /// @return Returns a typed `Offset` into the serialized data indicating
1226  /// where the vector is stored.
1227  /// This is mostly useful when flatbuffers are generated with mutation
1228  /// accessors.
1229  template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
1230  size_t vector_size, const std::function<void(size_t i, T *)> &filler) {
1231  StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>());
1232  T *structs = reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T)));
1233  for (size_t i = 0; i < vector_size; i++) {
1234  filler(i, structs);
1235  structs++;
1236  }
1237  return Offset<Vector<const T *>>(EndVector(vector_size));
1238  }
1239  #endif
1240 
1241  /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`.
1242  /// @tparam T The data type of the `std::vector` struct elements.
1243  /// @param[in]] v A const reference to the `std::vector` of structs to
1244  /// serialize into the buffer as a `vector`.
1245  /// @return Returns a typed `Offset` into the serialized data indicating
1246  /// where the vector is stored.
1247  template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
1248  const std::vector<T> &v) {
1249  return CreateVectorOfStructs(data(v), v.size());
1250  }
1251 
1252  /// @brief Serialize a `std::vector` of native structs into a FlatBuffer `vector`.
1253  /// @tparam T The data type of the `std::vector` struct elements.
1254  /// @tparam S The data type of the `std::vector` native struct elements.
1255  /// @param[in]] v A const reference to the `std::vector` of structs to
1256  /// serialize into the buffer as a `vector`.
1257  /// @return Returns a typed `Offset` into the serialized data indicating
1258  /// where the vector is stored.
1259  template<typename T, typename S> Offset<Vector<const T *>> CreateVectorOfNativeStructs(
1260  const std::vector<S> &v) {
1261  return CreateVectorOfNativeStructs<T, S>(data(v), v.size());
1262  }
1263 
1264 
1265  /// @cond FLATBUFFERS_INTERNAL
1266  template<typename T>
1267  struct StructKeyComparator {
1268  bool operator()(const T &a, const T &b) const {
1269  return a.KeyCompareLessThan(&b);
1270  }
1271 
1272  private:
1273  StructKeyComparator& operator= (const StructKeyComparator&);
1274  };
1275  /// @endcond
1276 
1277  /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`
1278  /// in sorted order.
1279  /// @tparam T The data type of the `std::vector` struct elements.
1280  /// @param[in]] v A const reference to the `std::vector` of structs to
1281  /// serialize into the buffer as a `vector`.
1282  /// @return Returns a typed `Offset` into the serialized data indicating
1283  /// where the vector is stored.
1284  template<typename T> Offset<Vector<const T *>> CreateVectorOfSortedStructs(
1285  std::vector<T> *v) {
1286  return CreateVectorOfSortedStructs(data(*v), v->size());
1287  }
1288 
1289  /// @brief Serialize a `std::vector` of native structs into a FlatBuffer `vector`
1290  /// in sorted order.
1291  /// @tparam T The data type of the `std::vector` struct elements.
1292  /// @tparam S The data type of the `std::vector` native struct elements.
1293  /// @param[in]] v A const reference to the `std::vector` of structs to
1294  /// serialize into the buffer as a `vector`.
1295  /// @return Returns a typed `Offset` into the serialized data indicating
1296  /// where the vector is stored.
1297  template<typename T, typename S> Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(
1298  std::vector<S> *v) {
1299  return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size());
1300  }
1301 
1302  /// @brief Serialize an array of structs into a FlatBuffer `vector` in sorted
1303  /// order.
1304  /// @tparam T The data type of the struct array elements.
1305  /// @param[in] v A pointer to the array of type `T` to serialize into the
1306  /// buffer as a `vector`.
1307  /// @param[in] len The number of elements to serialize.
1308  /// @return Returns a typed `Offset` into the serialized data indicating
1309  /// where the vector is stored.
1310  template<typename T> Offset<Vector<const T *>> CreateVectorOfSortedStructs(
1311  T *v, size_t len) {
1312  std::sort(v, v + len, StructKeyComparator<T>());
1313  return CreateVectorOfStructs(v, len);
1314  }
1315 
1316  /// @brief Serialize an array of native structs into a FlatBuffer `vector` in sorted
1317  /// order.
1318  /// @tparam T The data type of the struct array elements.
1319  /// @tparam S The data type of the native struct array elements.
1320  /// @param[in] v A pointer to the array of type `S` to serialize into the
1321  /// buffer as a `vector`.
1322  /// @param[in] len The number of elements to serialize.
1323  /// @return Returns a typed `Offset` into the serialized data indicating
1324  /// where the vector is stored.
1325  template<typename T, typename S> Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(
1326  S *v, size_t len) {
1327  extern T Pack(const S&);
1328  typedef T (*Pack_t)(const S&);
1329  std::vector<T> vv(len);
1330  std::transform(v, v+len, vv.begin(), *(Pack_t)&Pack);
1331  return CreateVectorOfSortedStructs<T>(vv, len);
1332  }
1333 
1334  /// @cond FLATBUFFERS_INTERNAL
1335  template<typename T>
1336  struct TableKeyComparator {
1337  TableKeyComparator(vector_downward& buf) : buf_(buf) {}
1338  bool operator()(const Offset<T> &a, const Offset<T> &b) const {
1339  auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o));
1340  auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o));
1341  return table_a->KeyCompareLessThan(table_b);
1342  }
1343  vector_downward& buf_;
1344 
1345  private:
1346  TableKeyComparator& operator= (const TableKeyComparator&);
1347  };
1348  /// @endcond
1349 
1350  /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
1351  /// in sorted order.
1352  /// @tparam T The data type that the offset refers to.
1353  /// @param[in] v An array of type `Offset<T>` that contains the `table`
1354  /// offsets to store in the buffer in sorted order.
1355  /// @param[in] len The number of elements to store in the `vector`.
1356  /// @return Returns a typed `Offset` into the serialized data indicating
1357  /// where the vector is stored.
1358  template<typename T> Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
1359  Offset<T> *v, size_t len) {
1360  std::sort(v, v + len, TableKeyComparator<T>(buf_));
1361  return CreateVector(v, len);
1362  }
1363 
1364  /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
1365  /// in sorted order.
1366  /// @tparam T The data type that the offset refers to.
1367  /// @param[in] v An array of type `Offset<T>` that contains the `table`
1368  /// offsets to store in the buffer in sorted order.
1369  /// @return Returns a typed `Offset` into the serialized data indicating
1370  /// where the vector is stored.
1371  template<typename T> Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
1372  std::vector<Offset<T>> *v) {
1373  return CreateVectorOfSortedTables(data(*v), v->size());
1374  }
1375 
1376  /// @brief Specialized version of `CreateVector` for non-copying use cases.
1377  /// Write the data any time later to the returned buffer pointer `buf`.
1378  /// @param[in] len The number of elements to store in the `vector`.
1379  /// @param[in] elemsize The size of each element in the `vector`.
1380  /// @param[out] buf A pointer to a `uint8_t` pointer that can be
1381  /// written to at a later time to serialize the data into a `vector`
1382  /// in the buffer.
1383  uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
1384  uint8_t **buf) {
1385  NotNested();
1386  StartVector(len, elemsize);
1387  buf_.make_space(len * elemsize);
1388  auto vec_start = GetSize();
1389  auto vec_end = EndVector(len);
1390  *buf = buf_.data_at(vec_start);
1391  return vec_end;
1392  }
1393 
1394  /// @brief Specialized version of `CreateVector` for non-copying use cases.
1395  /// Write the data any time later to the returned buffer pointer `buf`.
1396  /// @tparam T The data type of the data that will be stored in the buffer
1397  /// as a `vector`.
1398  /// @param[in] len The number of elements to store in the `vector`.
1399  /// @param[out] buf A pointer to a pointer of type `T` that can be
1400  /// written to at a later time to serialize the data into a `vector`
1401  /// in the buffer.
1402  template<typename T> Offset<Vector<T>> CreateUninitializedVector(
1403  size_t len, T **buf) {
1404  return CreateUninitializedVector(len, sizeof(T),
1405  reinterpret_cast<uint8_t **>(buf));
1406  }
1407 
1408  /// @brief Write a struct by itself, typically to be part of a union.
1409  template<typename T> Offset<const T *> CreateStruct(const T &structobj) {
1410  Align(AlignOf<T>());
1411  buf_.push_small(structobj);
1412  return Offset<const T *>(GetSize());
1413  }
1414 
1415  /// @brief The length of a FlatBuffer file header.
1416  static const size_t kFileIdentifierLength = 4;
1417 
1418  /// @brief Finish serializing a buffer by writing the root offset.
1419  /// @param[in] file_identifier If a `file_identifier` is given, the buffer
1420  /// will be prefixed with a standard FlatBuffers file header.
1421  template<typename T> void Finish(Offset<T> root,
1422  const char *file_identifier = nullptr) {
1423 
1424  Finish(root.o, file_identifier, false);
1425  }
1426 
1427  /// @brief Finish a buffer with a 32 bit size field pre-fixed (size of the
1428  /// buffer following the size field). These buffers are NOT compatible
1429  /// with standard buffers created by Finish, i.e. you can't call GetRoot
1430  /// on them, you have to use GetSizePrefixedRoot instead.
1431  /// All >32 bit quantities in this buffer will be aligned when the whole
1432  /// size pre-fixed buffer is aligned.
1433  /// These kinds of buffers are useful for creating a stream of FlatBuffers.
1434  template<typename T> void FinishSizePrefixed(Offset<T> root,
1435  const char *file_identifier = nullptr) {
1436  Finish(root.o, file_identifier, true);
1437  }
1438 
1439  private:
1440  // You shouldn't really be copying instances of this class.
1442  FlatBufferBuilder &operator=(const FlatBufferBuilder &);
1443 
1444  void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) {
1445  NotNested();
1446  // This will cause the whole buffer to be aligned.
1447  PreAlign((size_prefix ? sizeof(uoffset_t) : 0) +
1448  sizeof(uoffset_t) +
1449  (file_identifier ? kFileIdentifierLength : 0),
1450  minalign_);
1451  if (file_identifier) {
1452  assert(strlen(file_identifier) == kFileIdentifierLength);
1453  PushBytes(reinterpret_cast<const uint8_t *>(file_identifier),
1455  }
1456  PushElement(ReferTo(root)); // Location of root.
1457  if (size_prefix) {
1458  PushElement(GetSize());
1459  }
1460  finished = true;
1461  }
1462 
1463  struct FieldLoc {
1464  uoffset_t off;
1465  voffset_t id;
1466  };
1467 
1468  simple_allocator default_allocator;
1469 
1470  vector_downward buf_;
1471 
1472  // Accumulating offsets of table members while it is being built.
1473  std::vector<FieldLoc> offsetbuf_;
1474 
1475  // Ensure objects are not nested.
1476  bool nested;
1477 
1478  // Ensure the buffer is finished before it is being accessed.
1479  bool finished;
1480 
1481  std::vector<uoffset_t> vtables_; // todo: Could make this into a map?
1482 
1483  size_t minalign_;
1484 
1485  bool force_defaults_; // Serialize values equal to their defaults anyway.
1486 
1487  bool dedup_vtables_;
1488 
1489  struct StringOffsetCompare {
1490  StringOffsetCompare(const vector_downward &buf) : buf_(&buf) {}
1491  bool operator() (const Offset<String> &a, const Offset<String> &b) const {
1492  auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o));
1493  auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o));
1494  return strncmp(stra->c_str(), strb->c_str(),
1495  std::min(stra->size(), strb->size()) + 1) < 0;
1496  }
1497  const vector_downward *buf_;
1498  };
1499 
1500  // For use with CreateSharedString. Instantiated on first use only.
1501  typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
1502  StringOffsetMap *string_pool;
1503 };
1504 /// @}
1505 
1506 /// @cond FLATBUFFERS_INTERNAL
1507 // Helpers to get a typed pointer to the root object contained in the buffer.
1508 template<typename T> T *GetMutableRoot(void *buf) {
1509  EndianCheck();
1510  return reinterpret_cast<T *>(reinterpret_cast<uint8_t *>(buf) +
1511  EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
1512 }
1513 
1514 template<typename T> const T *GetRoot(const void *buf) {
1515  return GetMutableRoot<T>(const_cast<void *>(buf));
1516 }
1517 
1518 template<typename T> const T *GetSizePrefixedRoot(const void *buf) {
1519  return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(uoffset_t));
1520 }
1521 
1522 /// Helpers to get a typed pointer to objects that are currently being built.
1523 /// @warning Creating new objects will lead to reallocations and invalidates
1524 /// the pointer!
1525 template<typename T> T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb,
1526  Offset<T> offset) {
1527  return reinterpret_cast<T *>(fbb.GetCurrentBufferPointer() +
1528  fbb.GetSize() - offset.o);
1529 }
1530 
1531 template<typename T> const T *GetTemporaryPointer(FlatBufferBuilder &fbb,
1532  Offset<T> offset) {
1533  return GetMutableTemporaryPointer<T>(fbb, offset);
1534 }
1535 
1536 // Helper to see if the identifier in a buffer has the expected value.
1537 inline bool BufferHasIdentifier(const void *buf, const char *identifier) {
1538  return strncmp(reinterpret_cast<const char *>(buf) + sizeof(uoffset_t),
1539  identifier, FlatBufferBuilder::kFileIdentifierLength) == 0;
1540 }
1541 
1542 // Helper class to verify the integrity of a FlatBuffer
1543 class Verifier FLATBUFFERS_FINAL_CLASS {
1544  public:
1545  Verifier(const uint8_t *buf, size_t buf_len, uoffset_t _max_depth = 64,
1546  uoffset_t _max_tables = 1000000)
1547  : buf_(buf), end_(buf + buf_len), depth_(0), max_depth_(_max_depth),
1548  num_tables_(0), max_tables_(_max_tables)
1549  #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1550  , upper_bound_(buf)
1551  #endif
1552  {}
1553 
1554  // Central location where any verification failures register.
1555  bool Check(bool ok) const {
1556  #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
1557  assert(ok);
1558  #endif
1559  #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1560  if (!ok)
1561  upper_bound_ = buf_;
1562  #endif
1563  return ok;
1564  }
1565 
1566  // Verify any range within the buffer.
1567  bool Verify(const void *elem, size_t elem_len) const {
1568  #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1569  auto upper_bound = reinterpret_cast<const uint8_t *>(elem) + elem_len;
1570  if (upper_bound_ < upper_bound)
1571  upper_bound_ = upper_bound;
1572  #endif
1573  return Check(elem_len <= (size_t) (end_ - buf_) &&
1574  elem >= buf_ &&
1575  elem <= end_ - elem_len);
1576  }
1577 
1578  // Verify a range indicated by sizeof(T).
1579  template<typename T> bool Verify(const void *elem) const {
1580  return Verify(elem, sizeof(T));
1581  }
1582 
1583  // Verify a pointer (may be NULL) of a table type.
1584  template<typename T> bool VerifyTable(const T *table) {
1585  return !table || table->Verify(*this);
1586  }
1587 
1588  // Verify a pointer (may be NULL) of any vector type.
1589  template<typename T> bool Verify(const Vector<T> *vec) const {
1590  const uint8_t *end;
1591  return !vec ||
1592  VerifyVector(reinterpret_cast<const uint8_t *>(vec), sizeof(T),
1593  &end);
1594  }
1595 
1596  // Verify a pointer (may be NULL) of a vector to struct.
1597  template<typename T> bool Verify(const Vector<const T *> *vec) const {
1598  return Verify(reinterpret_cast<const Vector<T> *>(vec));
1599  }
1600 
1601  // Verify a pointer (may be NULL) to string.
1602  bool Verify(const String *str) const {
1603  const uint8_t *end;
1604  return !str ||
1605  (VerifyVector(reinterpret_cast<const uint8_t *>(str), 1, &end) &&
1606  Verify(end, 1) && // Must have terminator
1607  Check(*end == '\0')); // Terminating byte must be 0.
1608  }
1609 
1610  // Common code between vectors and strings.
1611  bool VerifyVector(const uint8_t *vec, size_t elem_size,
1612  const uint8_t **end) const {
1613  // Check we can read the size field.
1614  if (!Verify<uoffset_t>(vec)) return false;
1615  // Check the whole array. If this is a string, the byte past the array
1616  // must be 0.
1617  auto size = ReadScalar<uoffset_t>(vec);
1618  auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
1619  if (!Check(size < max_elems))
1620  return false; // Protect against byte_size overflowing.
1621  auto byte_size = sizeof(size) + elem_size * size;
1622  *end = vec + byte_size;
1623  return Verify(vec, byte_size);
1624  }
1625 
1626  // Special case for string contents, after the above has been called.
1627  bool VerifyVectorOfStrings(const Vector<Offset<String>> *vec) const {
1628  if (vec) {
1629  for (uoffset_t i = 0; i < vec->size(); i++) {
1630  if (!Verify(vec->Get(i))) return false;
1631  }
1632  }
1633  return true;
1634  }
1635 
1636  // Special case for table contents, after the above has been called.
1637  template<typename T> bool VerifyVectorOfTables(const Vector<Offset<T>> *vec) {
1638  if (vec) {
1639  for (uoffset_t i = 0; i < vec->size(); i++) {
1640  if (!vec->Get(i)->Verify(*this)) return false;
1641  }
1642  }
1643  return true;
1644  }
1645 
1646  template<typename T> bool VerifyBufferFromStart(const char *identifier,
1647  const uint8_t *start) {
1648  if (identifier &&
1649  (size_t(end_ - start) < 2 * sizeof(flatbuffers::uoffset_t) ||
1650  !BufferHasIdentifier(start, identifier))) {
1651  return false;
1652  }
1653 
1654  // Call T::Verify, which must be in the generated code for this type.
1655  auto o = VerifyOffset(start);
1656  return o &&
1657  reinterpret_cast<const T *>(start + o)->
1658  Verify(*this)
1659  #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1660  && GetComputedSize()
1661  #endif
1662  ;
1663  }
1664 
1665  // Verify this whole buffer, starting with root type T.
1666  template<typename T> bool VerifyBuffer() {
1667  return VerifyBuffer<T>(nullptr);
1668  }
1669 
1670  template<typename T> bool VerifyBuffer(const char *identifier) {
1671  return VerifyBufferFromStart<T>(identifier, buf_);
1672  }
1673 
1674  template<typename T> bool VerifySizePrefixedBuffer(const char *identifier) {
1675  return Verify<uoffset_t>(buf_) &&
1676  ReadScalar<uoffset_t>(buf_) == end_ - buf_ - sizeof(uoffset_t) &&
1677  VerifyBufferFromStart<T>(identifier, buf_ + sizeof(uoffset_t));
1678  }
1679 
1680  uoffset_t VerifyOffset(const uint8_t *start) const {
1681  if (!Verify<uoffset_t>(start)) return false;
1682  auto o = ReadScalar<uoffset_t>(start);
1683  Check(o != 0);
1684  return o;
1685  }
1686 
1687  // Called at the start of a table to increase counters measuring data
1688  // structure depth and amount, and possibly bails out with false if
1689  // limits set by the constructor have been hit. Needs to be balanced
1690  // with EndTable().
1691  bool VerifyComplexity() {
1692  depth_++;
1693  num_tables_++;
1694  return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_);
1695  }
1696 
1697  // Called at the end of a table to pop the depth count.
1698  bool EndTable() {
1699  depth_--;
1700  return true;
1701  }
1702 
1703  #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1704  // Returns the message size in bytes
1705  size_t GetComputedSize() const {
1706  uintptr_t size = upper_bound_ - buf_;
1707  // Align the size to uoffset_t
1708  size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
1709  return (buf_ + size > end_) ? 0 : size;
1710  }
1711  #endif
1712 
1713  private:
1714  const uint8_t *buf_;
1715  const uint8_t *end_;
1716  uoffset_t depth_;
1717  uoffset_t max_depth_;
1718  uoffset_t num_tables_;
1719  uoffset_t max_tables_;
1720 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1721  mutable const uint8_t *upper_bound_;
1722 #endif
1723 };
1724 
1725 // Convenient way to bundle a buffer and its length, to pass it around
1726 // typed by its root.
1727 // A BufferRef does not own its buffer.
1728 struct BufferRefBase {}; // for std::is_base_of
1729 template<typename T> struct BufferRef : BufferRefBase {
1730  BufferRef() : buf(nullptr), len(0), must_free(false) {}
1731  BufferRef(uint8_t *_buf, uoffset_t _len)
1732  : buf(_buf), len(_len), must_free(false) {}
1733 
1734  ~BufferRef() { if (must_free) free(buf); }
1735 
1736  const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); }
1737 
1738  bool Verify() {
1739  Verifier verifier(buf, len);
1740  return verifier.VerifyBuffer<T>(nullptr);
1741  }
1742 
1743  uint8_t *buf;
1744  uoffset_t len;
1745  bool must_free;
1746 };
1747 
1748 // "structs" are flat structures that do not have an offset table, thus
1749 // always have all members present and do not support forwards/backwards
1750 // compatible extensions.
1751 
1752 class Struct FLATBUFFERS_FINAL_CLASS {
1753  public:
1754  template<typename T> T GetField(uoffset_t o) const {
1755  return ReadScalar<T>(&data_[o]);
1756  }
1757 
1758  template<typename T> T GetStruct(uoffset_t o) const {
1759  return reinterpret_cast<T>(&data_[o]);
1760  }
1761 
1762  const uint8_t *GetAddressOf(uoffset_t o) const { return &data_[o]; }
1763  uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; }
1764 
1765  private:
1766  uint8_t data_[1];
1767 };
1768 
1769 // "tables" use an offset table (possibly shared) that allows fields to be
1770 // omitted and added at will, but uses an extra indirection to read.
1771 class Table {
1772  public:
1773  const uint8_t *GetVTable() const {
1774  return data_ - ReadScalar<soffset_t>(data_);
1775  }
1776 
1777  // This gets the field offset for any of the functions below it, or 0
1778  // if the field was not present.
1779  voffset_t GetOptionalFieldOffset(voffset_t field) const {
1780  // The vtable offset is always at the start.
1781  auto vtable = GetVTable();
1782  // The first element is the size of the vtable (fields + type id + itself).
1783  auto vtsize = ReadScalar<voffset_t>(vtable);
1784  // If the field we're accessing is outside the vtable, we're reading older
1785  // data, so it's the same as if the offset was 0 (not present).
1786  return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
1787  }
1788 
1789  template<typename T> T GetField(voffset_t field, T defaultval) const {
1790  auto field_offset = GetOptionalFieldOffset(field);
1791  return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
1792  }
1793 
1794  template<typename P> P GetPointer(voffset_t field) {
1795  auto field_offset = GetOptionalFieldOffset(field);
1796  auto p = data_ + field_offset;
1797  return field_offset
1798  ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p))
1799  : nullptr;
1800  }
1801  template<typename P> P GetPointer(voffset_t field) const {
1802  return const_cast<Table *>(this)->GetPointer<P>(field);
1803  }
1804 
1805  template<typename P> P GetStruct(voffset_t field) const {
1806  auto field_offset = GetOptionalFieldOffset(field);
1807  auto p = const_cast<uint8_t *>(data_ + field_offset);
1808  return field_offset ? reinterpret_cast<P>(p) : nullptr;
1809  }
1810 
1811  template<typename T> bool SetField(voffset_t field, T val, T def) {
1812  auto field_offset = GetOptionalFieldOffset(field);
1813  if (!field_offset) return val == def;
1814  WriteScalar(data_ + field_offset, val);
1815  return true;
1816  }
1817 
1818  bool SetPointer(voffset_t field, const uint8_t *val) {
1819  auto field_offset = GetOptionalFieldOffset(field);
1820  if (!field_offset) return false;
1821  WriteScalar(data_ + field_offset,
1822  static_cast<uoffset_t>(val - (data_ + field_offset)));
1823  return true;
1824  }
1825 
1826  uint8_t *GetAddressOf(voffset_t field) {
1827  auto field_offset = GetOptionalFieldOffset(field);
1828  return field_offset ? data_ + field_offset : nullptr;
1829  }
1830  const uint8_t *GetAddressOf(voffset_t field) const {
1831  return const_cast<Table *>(this)->GetAddressOf(field);
1832  }
1833 
1834  bool CheckField(voffset_t field) const {
1835  return GetOptionalFieldOffset(field) != 0;
1836  }
1837 
1838  // Verify the vtable of this table.
1839  // Call this once per table, followed by VerifyField once per field.
1840  bool VerifyTableStart(Verifier &verifier) const {
1841  // Check the vtable offset.
1842  if (!verifier.Verify<soffset_t>(data_)) return false;
1843  auto vtable = GetVTable();
1844  // Check the vtable size field, then check vtable fits in its entirety.
1845  return verifier.VerifyComplexity() &&
1846  verifier.Verify<voffset_t>(vtable) &&
1847  (ReadScalar<voffset_t>(vtable) & (sizeof(voffset_t) - 1)) == 0 &&
1848  verifier.Verify(vtable, ReadScalar<voffset_t>(vtable));
1849  }
1850 
1851  // Verify a particular field.
1852  template<typename T> bool VerifyField(const Verifier &verifier,
1853  voffset_t field) const {
1854  // Calling GetOptionalFieldOffset should be safe now thanks to
1855  // VerifyTable().
1856  auto field_offset = GetOptionalFieldOffset(field);
1857  // Check the actual field.
1858  return !field_offset || verifier.Verify<T>(data_ + field_offset);
1859  }
1860 
1861  // VerifyField for required fields.
1862  template<typename T> bool VerifyFieldRequired(const Verifier &verifier,
1863  voffset_t field) const {
1864  auto field_offset = GetOptionalFieldOffset(field);
1865  return verifier.Check(field_offset != 0) &&
1866  verifier.Verify<T>(data_ + field_offset);
1867  }
1868 
1869  // Versions for offsets.
1870  bool VerifyOffset(const Verifier &verifier, voffset_t field) const {
1871  auto field_offset = GetOptionalFieldOffset(field);
1872  return !field_offset || verifier.VerifyOffset(data_ + field_offset);
1873  }
1874 
1875  bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const {
1876  auto field_offset = GetOptionalFieldOffset(field);
1877  return verifier.Check(field_offset != 0) &&
1878  verifier.VerifyOffset(data_ + field_offset);
1879  }
1880 
1881  private:
1882  // private constructor & copy constructor: you obtain instances of this
1883  // class by pointing to existing data only
1884  Table();
1885  Table(const Table &other);
1886 
1887  uint8_t data_[1];
1888 };
1889 
1890 /// @brief This can compute the start of a FlatBuffer from a root pointer, i.e.
1891 /// it is the opposite transformation of GetRoot().
1892 /// This may be useful if you want to pass on a root and have the recipient
1893 /// delete the buffer afterwards.
1894 inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
1895  auto table = reinterpret_cast<const Table *>(root);
1896  auto vtable = table->GetVTable();
1897  // Either the vtable is before the root or after the root.
1898  auto start = std::min(vtable, reinterpret_cast<const uint8_t *>(root));
1899  // Align to at least sizeof(uoffset_t).
1900  start = reinterpret_cast<const uint8_t *>(
1901  reinterpret_cast<uintptr_t>(start) & ~(sizeof(uoffset_t) - 1));
1902  // Additionally, there may be a file_identifier in the buffer, and the root
1903  // offset. The buffer may have been aligned to any size between
1904  // sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align").
1905  // Sadly, the exact alignment is only known when constructing the buffer,
1906  // since it depends on the presence of values with said alignment properties.
1907  // So instead, we simply look at the next uoffset_t values (root,
1908  // file_identifier, and alignment padding) to see which points to the root.
1909  // None of the other values can "impersonate" the root since they will either
1910  // be 0 or four ASCII characters.
1911  static_assert(FlatBufferBuilder::kFileIdentifierLength == sizeof(uoffset_t),
1912  "file_identifier is assumed to be the same size as uoffset_t");
1913  for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1;
1914  possible_roots;
1915  possible_roots--) {
1916  start -= sizeof(uoffset_t);
1917  if (ReadScalar<uoffset_t>(start) + start ==
1918  reinterpret_cast<const uint8_t *>(root)) return start;
1919  }
1920  // We didn't find the root, either the "root" passed isn't really a root,
1921  // or the buffer is corrupt.
1922  // Assert, because calling this function with bad data may cause reads
1923  // outside of buffer boundaries.
1924  assert(false);
1925  return nullptr;
1926 }
1927 
1928 // Base class for native objects (FlatBuffer data de-serialized into native
1929 // C++ data structures).
1930 // Contains no functionality, purely documentative.
1931 struct NativeTable {
1932 };
1933 
1934 /// @brief Function types to be used with resolving hashes into objects and
1935 /// back again. The resolver gets a pointer to a field inside an object API
1936 /// object that is of the type specified in the schema using the attribute
1937 /// `cpp_type` (it is thus important whatever you write to this address
1938 /// matches that type). The value of this field is initially null, so you
1939 /// may choose to implement a delayed binding lookup using this function
1940 /// if you wish. The resolver does the opposite lookup, for when the object
1941 /// is being serialized again.
1942 typedef uint64_t hash_value_t;
1943 #ifdef FLATBUFFERS_CPP98_STL
1944  typedef void (*resolver_function_t)(void **pointer_adr, hash_value_t hash);
1945  typedef hash_value_t (*rehasher_function_t)(void *pointer);
1946 #else
1947  typedef std::function<void (void **pointer_adr, hash_value_t hash)>
1948  resolver_function_t;
1949  typedef std::function<hash_value_t (void *pointer)> rehasher_function_t;
1950 #endif
1951 
1952 // Helper function to test if a field is present, using any of the field
1953 // enums in the generated code.
1954 // `table` must be a generated table type. Since this is a template parameter,
1955 // this is not typechecked to be a subclass of Table, so beware!
1956 // Note: this function will return false for fields equal to the default
1957 // value, since they're not stored in the buffer (unless force_defaults was
1958 // used).
1959 template<typename T> bool IsFieldPresent(const T *table, voffset_t field) {
1960  // Cast, since Table is a private baseclass of any table types.
1961  return reinterpret_cast<const Table *>(table)->CheckField(field);
1962 }
1963 
1964 // Utility function for reverse lookups on the EnumNames*() functions
1965 // (in the generated C++ code)
1966 // names must be NULL terminated.
1967 inline int LookupEnum(const char **names, const char *name) {
1968  for (const char **p = names; *p; p++)
1969  if (!strcmp(*p, name))
1970  return static_cast<int>(p - names);
1971  return -1;
1972 }
1973 
1974 // These macros allow us to layout a struct with a guarantee that they'll end
1975 // up looking the same on different compilers and platforms.
1976 // It does this by disallowing the compiler to do any padding, and then
1977 // does padding itself by inserting extra padding fields that make every
1978 // element aligned to its own size.
1979 // Additionally, it manually sets the alignment of the struct as a whole,
1980 // which is typically its largest element, or a custom size set in the schema
1981 // by the force_align attribute.
1982 // These are used in the generated code only.
1983 
1984 #if defined(_MSC_VER)
1985  #define MANUALLY_ALIGNED_STRUCT(alignment) \
1986  __pragma(pack(1)); \
1987  struct __declspec(align(alignment))
1988  #define STRUCT_END(name, size) \
1989  __pragma(pack()); \
1990  static_assert(sizeof(name) == size, "compiler breaks packing rules")
1991 #elif defined(__GNUC__) || defined(__clang__)
1992  #define MANUALLY_ALIGNED_STRUCT(alignment) \
1993  _Pragma("pack(1)") \
1994  struct __attribute__((aligned(alignment)))
1995  #define STRUCT_END(name, size) \
1996  _Pragma("pack()") \
1997  static_assert(sizeof(name) == size, "compiler breaks packing rules")
1998 #else
1999  #error Unknown compiler, please define structure alignment macros
2000 #endif
2001 
2002 // String which identifies the current version of FlatBuffers.
2003 // flatbuffer_version_string is used by Google developers to identify which
2004 // applications uploaded to Google Play are using this library. This allows
2005 // the development team at Google to determine the popularity of the library.
2006 // How it works: Applications that are uploaded to the Google Play Store are
2007 // scanned for this version string. We track which applications are using it
2008 // to measure popularity. You are free to remove it (of course) but we would
2009 // appreciate if you left it in.
2010 
2011 // Weak linkage is culled by VS & doesn't work on cygwin.
2012 #if !defined(_WIN32) && !defined(__CYGWIN__)
2013 
2014 extern volatile __attribute__((weak)) const char *flatbuffer_version_string;
2015 volatile __attribute__((weak)) const char *flatbuffer_version_string =
2016  "FlatBuffers "
2017  FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
2018  FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
2019  FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
2020 
2021 #endif // !defined(_WIN32) && !defined(__CYGWIN__)
2022 
2023 #define DEFINE_BITMASK_OPERATORS(E, T)\
2024  inline E operator | (E lhs, E rhs){\
2025  return E(T(lhs) | T(rhs));\
2026  }\
2027  inline E operator & (E lhs, E rhs){\
2028  return E(T(lhs) & T(rhs));\
2029  }\
2030  inline E operator ^ (E lhs, E rhs){\
2031  return E(T(lhs) ^ T(rhs));\
2032  }\
2033  inline E operator ~ (E lhs){\
2034  return E(~T(lhs));\
2035  }\
2036  inline E operator |= (E &lhs, E rhs){\
2037  lhs = lhs | rhs;\
2038  return lhs;\
2039  }\
2040  inline E operator &= (E &lhs, E rhs){\
2041  lhs = lhs & rhs;\
2042  return lhs;\
2043  }\
2044  inline E operator ^= (E &lhs, E rhs){\
2045  lhs = lhs ^ rhs;\
2046  return lhs;\
2047  }\
2048  inline bool operator !(E rhs) \
2049  {\
2050  return !bool(T(rhs)); \
2051  }
2052 /// @endcond
2053 } // namespace flatbuffers
2054 
2055 #if defined(_MSC_VER)
2056 #pragma warning(pop)
2057 #endif
2058 
2059 #endif // FLATBUFFERS_H_
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:1167
uoffset_t CreateUninitializedVector(size_t len, size_t elemsize, uint8_t **buf)
Specialized version of CreateVector for non-copying use cases.
Definition: flatbuffers.h:1383
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:1229
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:1310
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:1297
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:1371
Helper class to hold data needed in creation of a FlatBuffer.
Definition: flatbuffers.h:707
uoffset_t GetSize() const
The current size of the serialized buffer, counting from the end.
Definition: flatbuffers.h:747
FlatBufferBuilder(uoffset_t initial_size=1024, const simple_allocator *allocator=nullptr)
Default constructor for FlatBufferBuilder.
Definition: flatbuffers.h:719
void Clear()
Reset all the state in this FlatBufferBuilder so it can be reused to construct another buffer...
Definition: flatbuffers.h:735
Offset< Vector< const T * > > CreateVectorOfNativeStructs(const S *v, size_t len)
Serialize an array of native structs into a FlatBuffer vector.
Definition: flatbuffers.h:1210
Offset< const T * > CreateStruct(const T &structobj)
Write a struct by itself, typically to be part of a union.
Definition: flatbuffers.h:1409
unique_ptr_t ReleaseBufferPointer()
Get the released pointer to the serialized buffer.
Definition: flatbuffers.h:768
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:1434
Offset< String > CreateSharedString(const char *str)
Store a string in the buffer, which null-terminated.
Definition: flatbuffers.h:1069
Offset< String > CreateString(const char *str, size_t len)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1000
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:798
void DedupVtables(bool dedup)
By default vtables are deduped in order to save space.
Definition: flatbuffers.h:802
static const size_t kFileIdentifierLength
The length of a FlatBuffer file header.
Definition: flatbuffers.h:1416
Offset< String > CreateString(const String *str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1026
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:1325
Offset< String > CreateSharedString(const String *str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1087
Offset< String > CreateString(const T &str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1035
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:1284
Offset< Vector< Offset< String > > > CreateVectorOfStrings(const std::vector< std::string > &v)
Serialize a std::vector into a FlatBuffer vector.
Definition: flatbuffers.h:1181
size_t GetBufferMinAlignment()
get the minimum alignment this buffer needs to be accessed properly.
Definition: flatbuffers.h:779
Offset< Vector< const T * > > CreateVectorOfStructs(const T *v, size_t len)
Serialize an array of structs into a FlatBuffer vector.
Definition: flatbuffers.h:1195
Offset< Vector< const T * > > CreateVectorOfNativeStructs(const std::vector< S > &v)
Serialize a std::vector of native structs into a FlatBuffer vector.
Definition: flatbuffers.h:1259
Offset< String > CreateString(const char *str)
Store a string in the buffer, which is null-terminated.
Definition: flatbuffers.h:1012
Offset< String > CreateString(const std::string &str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1019
Offset< Vector< T > > CreateVector(const std::vector< T > &v)
Serialize a std::vector into a FlatBuffer vector.
Definition: flatbuffers.h:1144
Offset< Vector< T > > CreateUninitializedVector(size_t len, T **buf)
Specialized version of CreateVector for non-copying use cases.
Definition: flatbuffers.h:1402
uint8_t * GetCurrentBufferPointer() const
Get a pointer to an unfinished buffer.
Definition: flatbuffers.h:759
Offset< Vector< T > > CreateVector(const T *v, size_t len)
Serialize an array into a FlatBuffer vector.
Definition: flatbuffers.h:1126
Offset< String > CreateSharedString(const std::string &str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1078
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:1358
Offset< String > CreateSharedString(const char *str, size_t len)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1045
Offset< Vector< const T * > > CreateVectorOfStructs(const std::vector< T > &v)
Serialize a std::vector of structs into a FlatBuffer vector.
Definition: flatbuffers.h:1247
void Finish(Offset< T > root, const char *file_identifier=nullptr)
Finish serializing a buffer by writing the root offset.
Definition: flatbuffers.h:1421
uint8_t * GetBufferPointer() const
Get the serialized buffer (after you call Finish()).
Definition: flatbuffers.h:752