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