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