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