• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 6
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;
OffsetOffset145   Offset() : o(0) {}
OffsetOffset146   Offset(uoffset_t _o) : o(_o) {}
UnionOffset147   Offset<void> Union() const { return Offset<void>(o); }
148 };
149 
EndianCheck()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 
EndianSwap(T t)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 
EndianScalar(T t)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 
ReadScalar(const void * p)197 template<typename T> T ReadScalar(const void *p) {
198   return EndianScalar(*reinterpret_cast<const T *>(p));
199 }
200 
WriteScalar(void * p,T t)201 template<typename T> void WriteScalar(void *p, T t) {
202   *reinterpret_cast<T *>(p) = EndianScalar(t);
203 }
204 
AlignOf()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);
ReadIndirectHelper229   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 + sizeof(largest_scalar_t) - 1) &
500         ~(sizeof(largest_scalar_t) - 1)),
501       buf_(allocator.allocate(reserved_)),
502       cur_(buf_ + reserved_),
503       allocator_(allocator) {}
504 
505   ~vector_downward() {
506     if (buf_)
507       allocator_.deallocate(buf_);
508   }
509 
510   void clear() {
511     if (buf_ == nullptr)
512       buf_ = allocator_.allocate(reserved_);
513 
514     cur_ = buf_ + reserved_;
515   }
516 
517   #ifndef FLATBUFFERS_CPP98_STL
518   // Relinquish the pointer to the caller.
519   unique_ptr_t release() {
520     // Actually deallocate from the start of the allocated memory.
521     std::function<void(uint8_t *)> deleter(
522       std::bind(&simple_allocator::deallocate, allocator_, buf_));
523 
524     // Point to the desired offset.
525     unique_ptr_t retval(data(), deleter);
526 
527     // Don't deallocate when this instance is destroyed.
528     buf_ = nullptr;
529     cur_ = nullptr;
530 
531     return retval;
532   }
533   #endif
534 
535   size_t growth_policy(size_t bytes) {
536     return (bytes / 2) & ~(sizeof(largest_scalar_t) - 1);
537   }
538 
539   uint8_t *make_space(size_t len) {
540     if (len > static_cast<size_t>(cur_ - buf_)) {
541       reallocate(len);
542     }
543     cur_ -= len;
544     // Beyond this, signed offsets may not have enough range:
545     // (FlatBuffers > 2GB not supported).
546     assert(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
547     return cur_;
548   }
549 
550   uoffset_t size() const {
551     assert(cur_ != nullptr && buf_ != nullptr);
552     return static_cast<uoffset_t>(reserved_ - (cur_ - buf_));
553   }
554 
555   uint8_t *data() const {
556     assert(cur_ != nullptr);
557     return cur_;
558   }
559 
560   uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; }
561 
562   void push(const uint8_t *bytes, size_t num) {
563     auto dest = make_space(num);
564     memcpy(dest, bytes, num);
565   }
566 
567   // Specialized version of push() that avoids memcpy call for small data.
568   template<typename T> void push_small(T little_endian_t) {
569     auto dest = make_space(sizeof(T));
570     *reinterpret_cast<T *>(dest) = little_endian_t;
571   }
572 
573   // fill() is most frequently called with small byte counts (<= 4),
574   // which is why we're using loops rather than calling memset.
575   void fill(size_t zero_pad_bytes) {
576     auto dest = make_space(zero_pad_bytes);
577     for (size_t i = 0; i < zero_pad_bytes; i++) dest[i] = 0;
578   }
579 
580   // Version for when we know the size is larger.
581   void fill_big(size_t zero_pad_bytes) {
582     auto dest = make_space(zero_pad_bytes);
583     memset(dest, 0, zero_pad_bytes);
584   }
585 
586   void pop(size_t bytes_to_remove) { cur_ += bytes_to_remove; }
587 
588  private:
589   // You shouldn't really be copying instances of this class.
590   vector_downward(const vector_downward &);
591   vector_downward &operator=(const vector_downward &);
592 
593   size_t reserved_;
594   uint8_t *buf_;
595   uint8_t *cur_;  // Points at location between empty (below) and used (above).
596   const simple_allocator &allocator_;
597 
598   void reallocate(size_t len) {
599     auto old_size = size();
600     auto largest_align = AlignOf<largest_scalar_t>();
601     reserved_ += (std::max)(len, growth_policy(reserved_));
602     // Round up to avoid undefined behavior from unaligned loads and stores.
603     reserved_ = (reserved_ + (largest_align - 1)) & ~(largest_align - 1);
604     auto new_buf = allocator_.allocate(reserved_);
605     auto new_cur = new_buf + reserved_ - old_size;
606     memcpy(new_cur, cur_, old_size);
607     cur_ = new_cur;
608     allocator_.deallocate(buf_);
609     buf_ = new_buf;
610   }
611 };
612 
613 // Converts a Field ID to a virtual table offset.
614 inline voffset_t FieldIndexToOffset(voffset_t field_id) {
615   // Should correspond to what EndTable() below builds up.
616   const int fixed_fields = 2;  // Vtable size and Object Size.
617   return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t));
618 }
619 
620 // Computes how many bytes you'd have to pad to be able to write an
621 // "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in
622 // memory).
623 inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
624   return ((~buf_size) + 1) & (scalar_size - 1);
625 }
626 
627 template <typename T> const T* data(const std::vector<T> &v) {
628   return v.empty() ? nullptr : &v.front();
629 }
630 template <typename T> T* data(std::vector<T> &v) {
631   return v.empty() ? nullptr : &v.front();
632 }
633 
634 /// @endcond
635 
636 /// @addtogroup flatbuffers_cpp_api
637 /// @{
638 /// @class FlatBufferBuilder
639 /// @brief Helper class to hold data needed in creation of a FlatBuffer.
640 /// To serialize data, you typically call one of the `Create*()` functions in
641 /// the generated code, which in turn call a sequence of `StartTable`/
642 /// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/
643 /// `CreateVector` functions. Do this is depth-first order to build up a tree to
644 /// the root. `Finish()` wraps up the buffer ready for transport.
645 class FlatBufferBuilder
646 /// @cond FLATBUFFERS_INTERNAL
647 FLATBUFFERS_FINAL_CLASS
648 /// @endcond
649 {
650  public:
651   /// @brief Default constructor for FlatBufferBuilder.
652   /// @param[in] initial_size The initial size of the buffer, in bytes. Defaults
653   /// to`1024`.
654   /// @param[in] allocator A pointer to the `simple_allocator` that should be
655   /// used. Defaults to `nullptr`, which means the `default_allocator` will be
656   /// be used.
657   explicit FlatBufferBuilder(uoffset_t initial_size = 1024,
658                              const simple_allocator *allocator = nullptr)
659       : buf_(initial_size, allocator ? *allocator : default_allocator),
660         nested(false), finished(false), minalign_(1), force_defaults_(false),
661         dedup_vtables_(true), string_pool(nullptr) {
662     offsetbuf_.reserve(16);  // Avoid first few reallocs.
663     vtables_.reserve(16);
664     EndianCheck();
665   }
666 
667   ~FlatBufferBuilder() {
668     if (string_pool) delete string_pool;
669   }
670 
671   /// @brief Reset all the state in this FlatBufferBuilder so it can be reused
672   /// to construct another buffer.
673   void Clear() {
674     buf_.clear();
675     offsetbuf_.clear();
676     nested = false;
677     finished = false;
678     vtables_.clear();
679     minalign_ = 1;
680     if (string_pool) string_pool->clear();
681   }
682 
683   /// @brief The current size of the serialized buffer, counting from the end.
684   /// @return Returns an `uoffset_t` with the current size of the buffer.
685   uoffset_t GetSize() const { return buf_.size(); }
686 
687   /// @brief Get the serialized buffer (after you call `Finish()`).
688   /// @return Returns an `uint8_t` pointer to the FlatBuffer data inside the
689   /// buffer.
690   uint8_t *GetBufferPointer() const {
691     Finished();
692     return buf_.data();
693   }
694 
695   /// @brief Get a pointer to an unfinished buffer.
696   /// @return Returns a `uint8_t` pointer to the unfinished buffer.
697   uint8_t *GetCurrentBufferPointer() const { return buf_.data(); }
698 
699   #ifndef FLATBUFFERS_CPP98_STL
700   /// @brief Get the released pointer to the serialized buffer.
701   /// @warning Do NOT attempt to use this FlatBufferBuilder afterwards!
702   /// @return The `unique_ptr` returned has a special allocator that knows how
703   /// to deallocate this pointer (since it points to the middle of an
704   /// allocation). Thus, do not mix this pointer with other `unique_ptr`'s, or
705   /// call `release()`/`reset()` on it.
706   unique_ptr_t ReleaseBufferPointer() {
707     Finished();
708     return buf_.release();
709   }
710   #endif
711 
712   /// @brief get the minimum alignment this buffer needs to be accessed
713   /// properly. This is only known once all elements have been written (after
714   /// you call Finish()). You can use this information if you need to embed
715   /// a FlatBuffer in some other buffer, such that you can later read it
716   /// without first having to copy it into its own buffer.
717   size_t GetBufferMinAlignment() {
718     Finished();
719     return minalign_;
720   }
721 
722   /// @cond FLATBUFFERS_INTERNAL
723   void Finished() const {
724     // If you get this assert, you're attempting to get access a buffer
725     // which hasn't been finished yet. Be sure to call
726     // FlatBufferBuilder::Finish with your root table.
727     // If you really need to access an unfinished buffer, call
728     // GetCurrentBufferPointer instead.
729     assert(finished);
730   }
731   /// @endcond
732 
733   /// @brief In order to save space, fields that are set to their default value
734   /// don't get serialized into the buffer.
735   /// @param[in] bool fd When set to `true`, always serializes default values.
736   void ForceDefaults(bool fd) { force_defaults_ = fd; }
737 
738   /// @brief By default vtables are deduped in order to save space.
739   /// @param[in] bool dedup When set to `true`, dedup vtables.
740   void DedupVtables(bool dedup) { dedup_vtables_ = dedup; }
741 
742   /// @cond FLATBUFFERS_INTERNAL
743   void Pad(size_t num_bytes) { buf_.fill(num_bytes); }
744 
745   void Align(size_t elem_size) {
746     if (elem_size > minalign_) minalign_ = elem_size;
747     buf_.fill(PaddingBytes(buf_.size(), elem_size));
748   }
749 
750   void PushFlatBuffer(const uint8_t *bytes, size_t size) {
751     PushBytes(bytes, size);
752     finished = true;
753   }
754 
755   void PushBytes(const uint8_t *bytes, size_t size) {
756     buf_.push(bytes, size);
757   }
758 
759   void PopBytes(size_t amount) { buf_.pop(amount); }
760 
761   template<typename T> void AssertScalarT() {
762     #ifndef FLATBUFFERS_CPP98_STL
763     // The code assumes power of 2 sizes and endian-swap-ability.
764     static_assert(std::is_scalar<T>::value
765         // The Offset<T> type is essentially a scalar but fails is_scalar.
766         || sizeof(T) == sizeof(Offset<void>),
767            "T must be a scalar type");
768     #endif
769   }
770 
771   // Write a single aligned scalar to the buffer
772   template<typename T> uoffset_t PushElement(T element) {
773     AssertScalarT<T>();
774     T litle_endian_element = EndianScalar(element);
775     Align(sizeof(T));
776     buf_.push_small(litle_endian_element);
777     return GetSize();
778   }
779 
780   template<typename T> uoffset_t PushElement(Offset<T> off) {
781     // Special case for offsets: see ReferTo below.
782     return PushElement(ReferTo(off.o));
783   }
784 
785   // When writing fields, we track where they are, so we can create correct
786   // vtables later.
787   void TrackField(voffset_t field, uoffset_t off) {
788     FieldLoc fl = { off, field };
789     offsetbuf_.push_back(fl);
790   }
791 
792   // Like PushElement, but additionally tracks the field this represents.
793   template<typename T> void AddElement(voffset_t field, T e, T def) {
794     // We don't serialize values equal to the default.
795     if (e == def && !force_defaults_) return;
796     auto off = PushElement(e);
797     TrackField(field, off);
798   }
799 
800   template<typename T> void AddOffset(voffset_t field, Offset<T> off) {
801     if (!off.o) return;  // An offset of 0 means NULL, don't store.
802     AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
803   }
804 
805   template<typename T> void AddStruct(voffset_t field, const T *structptr) {
806     if (!structptr) return;  // Default, don't store.
807     Align(AlignOf<T>());
808     buf_.push_small(*structptr);
809     TrackField(field, GetSize());
810   }
811 
812   void AddStructOffset(voffset_t field, uoffset_t off) {
813     TrackField(field, off);
814   }
815 
816   // Offsets initially are relative to the end of the buffer (downwards).
817   // This function converts them to be relative to the current location
818   // in the buffer (when stored here), pointing upwards.
819   uoffset_t ReferTo(uoffset_t off) {
820     // Align to ensure GetSize() below is correct.
821     Align(sizeof(uoffset_t));
822     // Offset must refer to something already in buffer.
823     assert(off && off <= GetSize());
824     return GetSize() - off + static_cast<uoffset_t>(sizeof(uoffset_t));
825   }
826 
827   void NotNested() {
828     // If you hit this, you're trying to construct a Table/Vector/String
829     // during the construction of its parent table (between the MyTableBuilder
830     // and table.Finish().
831     // Move the creation of these sub-objects to above the MyTableBuilder to
832     // not get this assert.
833     // Ignoring this assert may appear to work in simple cases, but the reason
834     // it is here is that storing objects in-line may cause vtable offsets
835     // to not fit anymore. It also leads to vtable duplication.
836     assert(!nested);
837   }
838 
839   // From generated code (or from the parser), we call StartTable/EndTable
840   // with a sequence of AddElement calls in between.
841   uoffset_t StartTable() {
842     NotNested();
843     nested = true;
844     return GetSize();
845   }
846 
847   // This finishes one serialized object by generating the vtable if it's a
848   // table, comparing it against existing vtables, and writing the
849   // resulting vtable offset.
850   uoffset_t EndTable(uoffset_t start, voffset_t numfields) {
851     // If you get this assert, a corresponding StartTable wasn't called.
852     assert(nested);
853     // Write the vtable offset, which is the start of any Table.
854     // We fill it's value later.
855     auto vtableoffsetloc = PushElement<soffset_t>(0);
856     // Write a vtable, which consists entirely of voffset_t elements.
857     // It starts with the number of offsets, followed by a type id, followed
858     // by the offsets themselves. In reverse:
859     buf_.fill_big(numfields * sizeof(voffset_t));
860     auto table_object_size = vtableoffsetloc - start;
861     assert(table_object_size < 0x10000);  // Vtable use 16bit offsets.
862     PushElement<voffset_t>(static_cast<voffset_t>(table_object_size));
863     PushElement<voffset_t>(FieldIndexToOffset(numfields));
864     // Write the offsets into the table
865     for (auto field_location = offsetbuf_.begin();
866               field_location != offsetbuf_.end();
867             ++field_location) {
868       auto pos = static_cast<voffset_t>(vtableoffsetloc - field_location->off);
869       // If this asserts, it means you've set a field twice.
870       assert(!ReadScalar<voffset_t>(buf_.data() + field_location->id));
871       WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
872     }
873     offsetbuf_.clear();
874     auto vt1 = reinterpret_cast<voffset_t *>(buf_.data());
875     auto vt1_size = ReadScalar<voffset_t>(vt1);
876     auto vt_use = GetSize();
877     // See if we already have generated a vtable with this exact same
878     // layout before. If so, make it point to the old one, remove this one.
879     if (dedup_vtables_) {
880       for (auto it = vtables_.begin(); it != vtables_.end(); ++it) {
881         auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*it));
882         auto vt2_size = *vt2;
883         if (vt1_size != vt2_size || memcmp(vt2, vt1, vt1_size)) continue;
884         vt_use = *it;
885         buf_.pop(GetSize() - vtableoffsetloc);
886         break;
887       }
888     }
889     // If this is a new vtable, remember it.
890     if (vt_use == GetSize()) {
891       vtables_.push_back(vt_use);
892     }
893     // Fill the vtable offset we created above.
894     // The offset points from the beginning of the object to where the
895     // vtable is stored.
896     // Offsets default direction is downward in memory for future format
897     // flexibility (storing all vtables at the start of the file).
898     WriteScalar(buf_.data_at(vtableoffsetloc),
899                 static_cast<soffset_t>(vt_use) -
900                   static_cast<soffset_t>(vtableoffsetloc));
901 
902     nested = false;
903     return vtableoffsetloc;
904   }
905 
906   // This checks a required field has been set in a given table that has
907   // just been constructed.
908   template<typename T> void Required(Offset<T> table, voffset_t field) {
909     auto table_ptr = buf_.data_at(table.o);
910     auto vtable_ptr = table_ptr - ReadScalar<soffset_t>(table_ptr);
911     bool ok = ReadScalar<voffset_t>(vtable_ptr + field) != 0;
912     // If this fails, the caller will show what field needs to be set.
913     assert(ok);
914     (void)ok;
915   }
916 
917   uoffset_t StartStruct(size_t alignment) {
918     Align(alignment);
919     return GetSize();
920   }
921 
922   uoffset_t EndStruct() { return GetSize(); }
923 
924   void ClearOffsets() { offsetbuf_.clear(); }
925 
926   // Aligns such that when "len" bytes are written, an object can be written
927   // after it with "alignment" without padding.
928   void PreAlign(size_t len, size_t alignment) {
929     buf_.fill(PaddingBytes(GetSize() + len, alignment));
930   }
931   template<typename T> void PreAlign(size_t len) {
932     AssertScalarT<T>();
933     PreAlign(len, sizeof(T));
934   }
935   /// @endcond
936 
937   /// @brief Store a string in the buffer, which can contain any binary data.
938   /// @param[in] str A const char pointer to the data to be stored as a string.
939   /// @param[in] len The number of bytes that should be stored from `str`.
940   /// @return Returns the offset in the buffer where the string starts.
941   Offset<String> CreateString(const char *str, size_t len) {
942     NotNested();
943     PreAlign<uoffset_t>(len + 1);  // Always 0-terminated.
944     buf_.fill(1);
945     PushBytes(reinterpret_cast<const uint8_t *>(str), len);
946     PushElement(static_cast<uoffset_t>(len));
947     return Offset<String>(GetSize());
948   }
949 
950   /// @brief Store a string in the buffer, which is null-terminated.
951   /// @param[in] str A const char pointer to a C-string to add to the buffer.
952   /// @return Returns the offset in the buffer where the string starts.
953   Offset<String> CreateString(const char *str) {
954     return CreateString(str, strlen(str));
955   }
956 
957   /// @brief Store a string in the buffer, which can contain any binary data.
958   /// @param[in] str A const reference to a std::string to store in the buffer.
959   /// @return Returns the offset in the buffer where the string starts.
960   Offset<String> CreateString(const std::string &str) {
961     return CreateString(str.c_str(), str.length());
962   }
963 
964   /// @brief Store a string in the buffer, which can contain any binary data.
965   /// @param[in] str A const pointer to a `String` struct to add to the buffer.
966   /// @return Returns the offset in the buffer where the string starts
967   Offset<String> CreateString(const String *str) {
968     return str ? CreateString(str->c_str(), str->Length()) : 0;
969   }
970 
971   /// @brief Store a string in the buffer, which can contain any binary data.
972   /// If a string with this exact contents has already been serialized before,
973   /// instead simply returns the offset of the existing string.
974   /// @param[in] str A const char pointer to the data to be stored as a string.
975   /// @param[in] len The number of bytes that should be stored from `str`.
976   /// @return Returns the offset in the buffer where the string starts.
977   Offset<String> CreateSharedString(const char *str, size_t len) {
978     if (!string_pool)
979       string_pool = new StringOffsetMap(StringOffsetCompare(buf_));
980     auto size_before_string = buf_.size();
981     // Must first serialize the string, since the set is all offsets into
982     // buffer.
983     auto off = CreateString(str, len);
984     auto it = string_pool->find(off);
985     // If it exists we reuse existing serialized data!
986     if (it != string_pool->end()) {
987       // We can remove the string we serialized.
988       buf_.pop(buf_.size() - size_before_string);
989       return *it;
990     }
991     // Record this string for future use.
992     string_pool->insert(off);
993     return off;
994   }
995 
996   /// @brief Store a string in the buffer, which null-terminated.
997   /// If a string with this exact contents has already been serialized before,
998   /// instead simply returns the offset of the existing string.
999   /// @param[in] str A const char pointer to a C-string to add to the buffer.
1000   /// @return Returns the offset in the buffer where the string starts.
1001   Offset<String> CreateSharedString(const char *str) {
1002     return CreateSharedString(str, strlen(str));
1003   }
1004 
1005   /// @brief Store a string in the buffer, which can contain any binary data.
1006   /// If a string with this exact contents has already been serialized before,
1007   /// instead simply returns the offset of the existing string.
1008   /// @param[in] str A const reference to a std::string to store in the buffer.
1009   /// @return Returns the offset in the buffer where the string starts.
1010   Offset<String> CreateSharedString(const std::string &str) {
1011     return CreateSharedString(str.c_str(), str.length());
1012   }
1013 
1014   /// @brief Store a string in the buffer, which can contain any binary data.
1015   /// If a string with this exact contents has already been serialized before,
1016   /// instead simply returns the offset of the existing string.
1017   /// @param[in] str A const pointer to a `String` struct to add to the buffer.
1018   /// @return Returns the offset in the buffer where the string starts
1019   Offset<String> CreateSharedString(const String *str) {
1020     return CreateSharedString(str->c_str(), str->Length());
1021   }
1022 
1023   /// @cond FLATBUFFERS_INTERNAL
1024   uoffset_t EndVector(size_t len) {
1025     assert(nested);  // Hit if no corresponding StartVector.
1026     nested = false;
1027     return PushElement(static_cast<uoffset_t>(len));
1028   }
1029 
1030   void StartVector(size_t len, size_t elemsize) {
1031     NotNested();
1032     nested = true;
1033     PreAlign<uoffset_t>(len * elemsize);
1034     PreAlign(len * elemsize, elemsize);  // Just in case elemsize > uoffset_t.
1035   }
1036 
1037   // Call this right before StartVector/CreateVector if you want to force the
1038   // alignment to be something different than what the element size would
1039   // normally dictate.
1040   // This is useful when storing a nested_flatbuffer in a vector of bytes,
1041   // or when storing SIMD floats, etc.
1042   void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment) {
1043     PreAlign(len * elemsize, alignment);
1044   }
1045 
1046   uint8_t *ReserveElements(size_t len, size_t elemsize) {
1047     return buf_.make_space(len * elemsize);
1048   }
1049   /// @endcond
1050 
1051   /// @brief Serialize an array into a FlatBuffer `vector`.
1052   /// @tparam T The data type of the array elements.
1053   /// @param[in] v A pointer to the array of type `T` to serialize into the
1054   /// buffer as a `vector`.
1055   /// @param[in] len The number of elements to serialize.
1056   /// @return Returns a typed `Offset` into the serialized data indicating
1057   /// where the vector is stored.
1058   template<typename T> Offset<Vector<T>> CreateVector(const T *v, size_t len) {
1059     StartVector(len, sizeof(T));
1060     for (auto i = len; i > 0; ) {
1061       PushElement(v[--i]);
1062     }
1063     return Offset<Vector<T>>(EndVector(len));
1064   }
1065 
1066   /// @brief Serialize a `std::vector` into a FlatBuffer `vector`.
1067   /// @tparam T The data type of the `std::vector` elements.
1068   /// @param v A const reference to the `std::vector` to serialize into the
1069   /// buffer as a `vector`.
1070   /// @return Returns a typed `Offset` into the serialized data indicating
1071   /// where the vector is stored.
1072   template<typename T> Offset<Vector<T>> CreateVector(const std::vector<T> &v) {
1073     return CreateVector(data(v), v.size());
1074   }
1075 
1076   // vector<bool> may be implemented using a bit-set, so we can't access it as
1077   // an array. Instead, read elements manually.
1078   // Background: https://isocpp.org/blog/2012/11/on-vectorbool
1079   Offset<Vector<uint8_t>> CreateVector(const std::vector<bool> &v) {
1080     StartVector(v.size(), sizeof(uint8_t));
1081     for (auto i = v.size(); i > 0; ) {
1082       PushElement(static_cast<uint8_t>(v[--i]));
1083     }
1084     return Offset<Vector<uint8_t>>(EndVector(v.size()));
1085   }
1086 
1087   #ifndef FLATBUFFERS_CPP98_STL
1088   /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
1089   /// This is a convenience function that takes care of iteration for you.
1090   /// @tparam T The data type of the `std::vector` elements.
1091   /// @param f A function that takes the current iteration 0..vector_size-1 and
1092   /// returns any type that you can construct a FlatBuffers vector out of.
1093   /// @return Returns a typed `Offset` into the serialized data indicating
1094   /// where the vector is stored.
1095   template<typename T> Offset<Vector<T>> CreateVector(size_t vector_size,
1096       const std::function<T (size_t i)> &f) {
1097     std::vector<T> elems(vector_size);
1098     for (size_t i = 0; i < vector_size; i++) elems[i] = f(i);
1099     return CreateVector(elems);
1100   }
1101   #endif
1102 
1103   /// @brief Serialize a `std::vector<std::string>` into a FlatBuffer `vector`.
1104   /// This is a convenience function for a common case.
1105   /// @param v A const reference to the `std::vector` to serialize into the
1106   /// buffer as a `vector`.
1107   /// @return Returns a typed `Offset` into the serialized data indicating
1108   /// where the vector is stored.
1109   Offset<Vector<Offset<String>>> CreateVectorOfStrings(
1110       const std::vector<std::string> &v) {
1111     std::vector<Offset<String>> offsets(v.size());
1112     for (size_t i = 0; i < v.size(); i++) offsets[i] = CreateString(v[i]);
1113     return CreateVector(offsets);
1114   }
1115 
1116   /// @brief Serialize an array of structs into a FlatBuffer `vector`.
1117   /// @tparam T The data type of the struct array elements.
1118   /// @param[in] v A pointer to the array of type `T` to serialize into the
1119   /// buffer as a `vector`.
1120   /// @param[in] len The number of elements to serialize.
1121   /// @return Returns a typed `Offset` into the serialized data indicating
1122   /// where the vector is stored.
1123   template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
1124       const T *v, size_t len) {
1125     StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>());
1126     PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
1127     return Offset<Vector<const T *>>(EndVector(len));
1128   }
1129 
1130   #ifndef FLATBUFFERS_CPP98_STL
1131   /// @brief Serialize an array of structs into a FlatBuffer `vector`.
1132   /// @tparam T The data type of the struct array elements.
1133   /// @param[in] f A function that takes the current iteration 0..vector_size-1
1134   /// and a pointer to the struct that must be filled.
1135   /// @return Returns a typed `Offset` into the serialized data indicating
1136   /// where the vector is stored.
1137   /// This is mostly useful when flatbuffers are generated with mutation
1138   /// accessors.
1139   template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
1140       size_t vector_size, const std::function<void(size_t i, T *)> &filler) {
1141     StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>());
1142     T *structs = reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T)));
1143     for (size_t i = 0; i < vector_size; i++) {
1144       filler(i, structs);
1145       structs++;
1146     }
1147     return Offset<Vector<const T *>>(EndVector(vector_size));
1148   }
1149   #endif
1150 
1151   /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`.
1152   /// @tparam T The data type of the `std::vector` struct elements.
1153   /// @param[in]] v A const reference to the `std::vector` of structs to
1154   /// serialize into the buffer as a `vector`.
1155   /// @return Returns a typed `Offset` into the serialized data indicating
1156   /// where the vector is stored.
1157   template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
1158       const std::vector<T> &v) {
1159     return CreateVectorOfStructs(data(v), v.size());
1160   }
1161 
1162   /// @cond FLATBUFFERS_INTERNAL
1163   template<typename T>
1164   struct TableKeyComparator {
1165   TableKeyComparator(vector_downward& buf) : buf_(buf) {}
1166     bool operator()(const Offset<T> &a, const Offset<T> &b) const {
1167       auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o));
1168       auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o));
1169       return table_a->KeyCompareLessThan(table_b);
1170     }
1171     vector_downward& buf_;
1172 
1173   private:
1174     TableKeyComparator& operator= (const TableKeyComparator&);
1175   };
1176   /// @endcond
1177 
1178   /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
1179   /// in sorted order.
1180   /// @tparam T The data type that the offset refers to.
1181   /// @param[in] v An array of type `Offset<T>` that contains the `table`
1182   /// offsets to store in the buffer in sorted order.
1183   /// @param[in] len The number of elements to store in the `vector`.
1184   /// @return Returns a typed `Offset` into the serialized data indicating
1185   /// where the vector is stored.
1186   template<typename T> Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
1187       Offset<T> *v, size_t len) {
1188     std::sort(v, v + len, TableKeyComparator<T>(buf_));
1189     return CreateVector(v, len);
1190   }
1191 
1192   /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
1193   /// in sorted order.
1194   /// @tparam T The data type that the offset refers to.
1195   /// @param[in] v An array of type `Offset<T>` that contains the `table`
1196   /// offsets to store in the buffer in sorted order.
1197   /// @return Returns a typed `Offset` into the serialized data indicating
1198   /// where the vector is stored.
1199   template<typename T> Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
1200       std::vector<Offset<T>> *v) {
1201     return CreateVectorOfSortedTables(data(*v), v->size());
1202   }
1203 
1204   /// @brief Specialized version of `CreateVector` for non-copying use cases.
1205   /// Write the data any time later to the returned buffer pointer `buf`.
1206   /// @param[in] len The number of elements to store in the `vector`.
1207   /// @param[in] elemsize The size of each element in the `vector`.
1208   /// @param[out] buf A pointer to a `uint8_t` pointer that can be
1209   /// written to at a later time to serialize the data into a `vector`
1210   /// in the buffer.
1211   uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
1212                                       uint8_t **buf) {
1213     NotNested();
1214     StartVector(len, elemsize);
1215     buf_.make_space(len * elemsize);
1216     auto vec_start = GetSize();
1217     auto vec_end = EndVector(len);
1218     *buf = buf_.data_at(vec_start);
1219     return vec_end;
1220   }
1221 
1222   /// @brief Specialized version of `CreateVector` for non-copying use cases.
1223   /// Write the data any time later to the returned buffer pointer `buf`.
1224   /// @tparam T The data type of the data that will be stored in the buffer
1225   /// as a `vector`.
1226   /// @param[in] len The number of elements to store in the `vector`.
1227   /// @param[out] buf A pointer to a pointer of type `T` that can be
1228   /// written to at a later time to serialize the data into a `vector`
1229   /// in the buffer.
1230   template<typename T> Offset<Vector<T>> CreateUninitializedVector(
1231       size_t len, T **buf) {
1232     return CreateUninitializedVector(len, sizeof(T),
1233                                      reinterpret_cast<uint8_t **>(buf));
1234   }
1235 
1236   /// @brief The length of a FlatBuffer file header.
1237   static const size_t kFileIdentifierLength = 4;
1238 
1239   /// @brief Finish serializing a buffer by writing the root offset.
1240   /// @param[in] file_identifier If a `file_identifier` is given, the buffer
1241   /// will be prefixed with a standard FlatBuffers file header.
1242   template<typename T> void Finish(Offset<T> root,
1243                                    const char *file_identifier = nullptr) {
1244 
1245     Finish(root.o, file_identifier, false);
1246   }
1247 
1248   /// @brief Finish a buffer with a 32 bit size field pre-fixed (size of the
1249   /// buffer following the size field). These buffers are NOT compatible
1250   /// with standard buffers created by Finish, i.e. you can't call GetRoot
1251   /// on them, you have to use GetSizePrefixedRoot instead.
1252   /// All >32 bit quantities in this buffer will be aligned when the whole
1253   /// size pre-fixed buffer is aligned.
1254   /// These kinds of buffers are useful for creating a stream of FlatBuffers.
1255   template<typename T> void FinishSizePrefixed(Offset<T> root,
1256                                    const char *file_identifier = nullptr) {
1257     Finish(root.o, file_identifier, true);
1258   }
1259 
1260  private:
1261   // You shouldn't really be copying instances of this class.
1262   FlatBufferBuilder(const FlatBufferBuilder &);
1263   FlatBufferBuilder &operator=(const FlatBufferBuilder &);
1264 
1265   void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) {
1266     NotNested();
1267     // This will cause the whole buffer to be aligned.
1268     PreAlign((size_prefix ? sizeof(uoffset_t) : 0) +
1269              sizeof(uoffset_t) +
1270              (file_identifier ? kFileIdentifierLength : 0),
1271              minalign_);
1272     if (file_identifier) {
1273       assert(strlen(file_identifier) == kFileIdentifierLength);
1274       PushBytes(reinterpret_cast<const uint8_t *>(file_identifier),
1275                 kFileIdentifierLength);
1276     }
1277     PushElement(ReferTo(root));  // Location of root.
1278     if (size_prefix) {
1279       PushElement(GetSize());
1280     }
1281     finished = true;
1282   }
1283 
1284   struct FieldLoc {
1285     uoffset_t off;
1286     voffset_t id;
1287   };
1288 
1289   simple_allocator default_allocator;
1290 
1291   vector_downward buf_;
1292 
1293   // Accumulating offsets of table members while it is being built.
1294   std::vector<FieldLoc> offsetbuf_;
1295 
1296   // Ensure objects are not nested.
1297   bool nested;
1298 
1299   // Ensure the buffer is finished before it is being accessed.
1300   bool finished;
1301 
1302   std::vector<uoffset_t> vtables_;  // todo: Could make this into a map?
1303 
1304   size_t minalign_;
1305 
1306   bool force_defaults_;  // Serialize values equal to their defaults anyway.
1307 
1308   bool dedup_vtables_;
1309 
1310   struct StringOffsetCompare {
1311     StringOffsetCompare(const vector_downward &buf) : buf_(&buf) {}
1312     bool operator() (const Offset<String> &a, const Offset<String> &b) const {
1313       auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o));
1314       auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o));
1315       return strncmp(stra->c_str(), strb->c_str(),
1316                      std::min(stra->size(), strb->size()) + 1) < 0;
1317     }
1318     const vector_downward *buf_;
1319   };
1320 
1321   // For use with CreateSharedString. Instantiated on first use only.
1322   typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
1323   StringOffsetMap *string_pool;
1324 };
1325 /// @}
1326 
1327 /// @cond FLATBUFFERS_INTERNAL
1328 // Helpers to get a typed pointer to the root object contained in the buffer.
1329 template<typename T> T *GetMutableRoot(void *buf) {
1330   EndianCheck();
1331   return reinterpret_cast<T *>(reinterpret_cast<uint8_t *>(buf) +
1332     EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
1333 }
1334 
1335 template<typename T> const T *GetRoot(const void *buf) {
1336   return GetMutableRoot<T>(const_cast<void *>(buf));
1337 }
1338 
1339 template<typename T> const T *GetSizePrefixedRoot(const void *buf) {
1340   return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(uoffset_t));
1341 }
1342 
1343 /// Helpers to get a typed pointer to objects that are currently being built.
1344 /// @warning Creating new objects will lead to reallocations and invalidates
1345 /// the pointer!
1346 template<typename T> T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb,
1347                                                    Offset<T> offset) {
1348   return reinterpret_cast<T *>(fbb.GetCurrentBufferPointer() +
1349     fbb.GetSize() - offset.o);
1350 }
1351 
1352 template<typename T> const T *GetTemporaryPointer(FlatBufferBuilder &fbb,
1353                                                   Offset<T> offset) {
1354   return GetMutableTemporaryPointer<T>(fbb, offset);
1355 }
1356 
1357 // Helper to see if the identifier in a buffer has the expected value.
1358 inline bool BufferHasIdentifier(const void *buf, const char *identifier) {
1359   return strncmp(reinterpret_cast<const char *>(buf) + sizeof(uoffset_t),
1360                  identifier, FlatBufferBuilder::kFileIdentifierLength) == 0;
1361 }
1362 
1363 // Helper class to verify the integrity of a FlatBuffer
1364 class Verifier FLATBUFFERS_FINAL_CLASS {
1365  public:
1366   Verifier(const uint8_t *buf, size_t buf_len, size_t _max_depth = 64,
1367            size_t _max_tables = 1000000)
1368     : buf_(buf), end_(buf + buf_len), depth_(0), max_depth_(_max_depth),
1369       num_tables_(0), max_tables_(_max_tables)
1370     #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1371         , upper_bound_(buf)
1372     #endif
1373     {}
1374 
1375   // Central location where any verification failures register.
1376   bool Check(bool ok) const {
1377     #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
1378       assert(ok);
1379     #endif
1380     #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1381       if (!ok)
1382         upper_bound_ = buf_;
1383     #endif
1384     return ok;
1385   }
1386 
1387   // Verify any range within the buffer.
1388   bool Verify(const void *elem, size_t elem_len) const {
1389     #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1390       auto upper_bound = reinterpret_cast<const uint8_t *>(elem) + elem_len;
1391       if (upper_bound_ < upper_bound)
1392         upper_bound_ =  upper_bound;
1393     #endif
1394     return Check(elem_len <= (size_t) (end_ - buf_) &&
1395                  elem >= buf_ &&
1396                  elem <= end_ - elem_len);
1397   }
1398 
1399   // Verify a range indicated by sizeof(T).
1400   template<typename T> bool Verify(const void *elem) const {
1401     return Verify(elem, sizeof(T));
1402   }
1403 
1404   // Verify a pointer (may be NULL) of a table type.
1405   template<typename T> bool VerifyTable(const T *table) {
1406     return !table || table->Verify(*this);
1407   }
1408 
1409   // Verify a pointer (may be NULL) of any vector type.
1410   template<typename T> bool Verify(const Vector<T> *vec) const {
1411     const uint8_t *end;
1412     return !vec ||
1413            VerifyVector(reinterpret_cast<const uint8_t *>(vec), sizeof(T),
1414                         &end);
1415   }
1416 
1417   // Verify a pointer (may be NULL) of a vector to struct.
1418   template<typename T> bool Verify(const Vector<const T *> *vec) const {
1419     return Verify(reinterpret_cast<const Vector<T> *>(vec));
1420   }
1421 
1422   // Verify a pointer (may be NULL) to string.
1423   bool Verify(const String *str) const {
1424     const uint8_t *end;
1425     return !str ||
1426            (VerifyVector(reinterpret_cast<const uint8_t *>(str), 1, &end) &&
1427             Verify(end, 1) &&      // Must have terminator
1428             Check(*end == '\0'));  // Terminating byte must be 0.
1429   }
1430 
1431   // Common code between vectors and strings.
1432   bool VerifyVector(const uint8_t *vec, size_t elem_size,
1433                     const uint8_t **end) const {
1434     // Check we can read the size field.
1435     if (!Verify<uoffset_t>(vec)) return false;
1436     // Check the whole array. If this is a string, the byte past the array
1437     // must be 0.
1438     auto size = ReadScalar<uoffset_t>(vec);
1439     auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
1440     if (!Check(size < max_elems))
1441       return false;  // Protect against byte_size overflowing.
1442     auto byte_size = sizeof(size) + elem_size * size;
1443     *end = vec + byte_size;
1444     return Verify(vec, byte_size);
1445   }
1446 
1447   // Special case for string contents, after the above has been called.
1448   bool VerifyVectorOfStrings(const Vector<Offset<String>> *vec) const {
1449       if (vec) {
1450         for (uoffset_t i = 0; i < vec->size(); i++) {
1451           if (!Verify(vec->Get(i))) return false;
1452         }
1453       }
1454       return true;
1455   }
1456 
1457   // Special case for table contents, after the above has been called.
1458   template<typename T> bool VerifyVectorOfTables(const Vector<Offset<T>> *vec) {
1459     if (vec) {
1460       for (uoffset_t i = 0; i < vec->size(); i++) {
1461         if (!vec->Get(i)->Verify(*this)) return false;
1462       }
1463     }
1464     return true;
1465   }
1466 
1467   template<typename T> bool VerifyBufferFromStart(const char *identifier,
1468                                                   const uint8_t *start) {
1469     if (identifier &&
1470         (size_t(end_ - start) < 2 * sizeof(flatbuffers::uoffset_t) ||
1471          !BufferHasIdentifier(start, identifier))) {
1472       return false;
1473     }
1474 
1475     // Call T::Verify, which must be in the generated code for this type.
1476     return Verify<uoffset_t>(start) &&
1477       reinterpret_cast<const T *>(start + ReadScalar<uoffset_t>(start))->
1478         Verify(*this)
1479         #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1480           && GetComputedSize()
1481         #endif
1482             ;
1483   }
1484 
1485   // Verify this whole buffer, starting with root type T.
1486   template<typename T> bool VerifyBuffer(const char *identifier) {
1487     return VerifyBufferFromStart<T>(identifier, buf_);
1488   }
1489 
1490   template<typename T> bool VerifySizePrefixedBuffer(const char *identifier) {
1491     return Verify<uoffset_t>(buf_) &&
1492            ReadScalar<uoffset_t>(buf_) == end_ - buf_ - sizeof(uoffset_t) &&
1493            VerifyBufferFromStart<T>(identifier, buf_ + sizeof(uoffset_t));
1494   }
1495 
1496   // Called at the start of a table to increase counters measuring data
1497   // structure depth and amount, and possibly bails out with false if
1498   // limits set by the constructor have been hit. Needs to be balanced
1499   // with EndTable().
1500   bool VerifyComplexity() {
1501     depth_++;
1502     num_tables_++;
1503     return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_);
1504   }
1505 
1506   // Called at the end of a table to pop the depth count.
1507   bool EndTable() {
1508     depth_--;
1509     return true;
1510   }
1511 
1512   #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1513   // Returns the message size in bytes
1514   size_t GetComputedSize() const {
1515     uintptr_t size = upper_bound_ - buf_;
1516     // Align the size to uoffset_t
1517     size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
1518     return (buf_  + size > end_) ?  0 : size;
1519   }
1520   #endif
1521 
1522  private:
1523   const uint8_t *buf_;
1524   const uint8_t *end_;
1525   size_t depth_;
1526   size_t max_depth_;
1527   size_t num_tables_;
1528   size_t max_tables_;
1529 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1530   mutable const uint8_t *upper_bound_;
1531 #endif
1532 };
1533 
1534 // Convenient way to bundle a buffer and its length, to pass it around
1535 // typed by its root.
1536 // A BufferRef does not own its buffer.
1537 struct BufferRefBase {};  // for std::is_base_of
1538 template<typename T> struct BufferRef : BufferRefBase {
1539   BufferRef() : buf(nullptr), len(0), must_free(false) {}
1540   BufferRef(uint8_t *_buf, uoffset_t _len)
1541     : buf(_buf), len(_len), must_free(false) {}
1542 
1543   ~BufferRef() { if (must_free) free(buf); }
1544 
1545   const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); }
1546 
1547   bool Verify() {
1548     Verifier verifier(buf, len);
1549     return verifier.VerifyBuffer<T>(nullptr);
1550   }
1551 
1552   uint8_t *buf;
1553   uoffset_t len;
1554   bool must_free;
1555 };
1556 
1557 // "structs" are flat structures that do not have an offset table, thus
1558 // always have all members present and do not support forwards/backwards
1559 // compatible extensions.
1560 
1561 class Struct FLATBUFFERS_FINAL_CLASS {
1562  public:
1563   template<typename T> T GetField(uoffset_t o) const {
1564     return ReadScalar<T>(&data_[o]);
1565   }
1566 
1567   template<typename T> T GetStruct(uoffset_t o) const {
1568     return reinterpret_cast<T>(&data_[o]);
1569   }
1570 
1571   const uint8_t *GetAddressOf(uoffset_t o) const { return &data_[o]; }
1572   uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; }
1573 
1574  private:
1575   uint8_t data_[1];
1576 };
1577 
1578 // "tables" use an offset table (possibly shared) that allows fields to be
1579 // omitted and added at will, but uses an extra indirection to read.
1580 class Table {
1581  public:
1582   const uint8_t *GetVTable() const {
1583     return data_ - ReadScalar<soffset_t>(data_);
1584   }
1585 
1586   // This gets the field offset for any of the functions below it, or 0
1587   // if the field was not present.
1588   voffset_t GetOptionalFieldOffset(voffset_t field) const {
1589     // The vtable offset is always at the start.
1590     auto vtable = GetVTable();
1591     // The first element is the size of the vtable (fields + type id + itself).
1592     auto vtsize = ReadScalar<voffset_t>(vtable);
1593     // If the field we're accessing is outside the vtable, we're reading older
1594     // data, so it's the same as if the offset was 0 (not present).
1595     return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
1596   }
1597 
1598   template<typename T> T GetField(voffset_t field, T defaultval) const {
1599     auto field_offset = GetOptionalFieldOffset(field);
1600     return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
1601   }
1602 
1603   template<typename P> P GetPointer(voffset_t field) {
1604     auto field_offset = GetOptionalFieldOffset(field);
1605     auto p = data_ + field_offset;
1606     return field_offset
1607       ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p))
1608       : nullptr;
1609   }
1610   template<typename P> P GetPointer(voffset_t field) const {
1611     return const_cast<Table *>(this)->GetPointer<P>(field);
1612   }
1613 
1614   template<typename P> P GetStruct(voffset_t field) const {
1615     auto field_offset = GetOptionalFieldOffset(field);
1616     auto p = const_cast<uint8_t *>(data_ + field_offset);
1617     return field_offset ? reinterpret_cast<P>(p) : nullptr;
1618   }
1619 
1620   template<typename T> bool SetField(voffset_t field, T val) {
1621     auto field_offset = GetOptionalFieldOffset(field);
1622     if (!field_offset) return false;
1623     WriteScalar(data_ + field_offset, val);
1624     return true;
1625   }
1626 
1627   bool SetPointer(voffset_t field, const uint8_t *val) {
1628     auto field_offset = GetOptionalFieldOffset(field);
1629     if (!field_offset) return false;
1630     WriteScalar(data_ + field_offset,
1631                 static_cast<uoffset_t>(val - (data_ + field_offset)));
1632     return true;
1633   }
1634 
1635   uint8_t *GetAddressOf(voffset_t field) {
1636     auto field_offset = GetOptionalFieldOffset(field);
1637     return field_offset ? data_ + field_offset : nullptr;
1638   }
1639   const uint8_t *GetAddressOf(voffset_t field) const {
1640     return const_cast<Table *>(this)->GetAddressOf(field);
1641   }
1642 
1643   bool CheckField(voffset_t field) const {
1644     return GetOptionalFieldOffset(field) != 0;
1645   }
1646 
1647   // Verify the vtable of this table.
1648   // Call this once per table, followed by VerifyField once per field.
1649   bool VerifyTableStart(Verifier &verifier) const {
1650     // Check the vtable offset.
1651     if (!verifier.Verify<soffset_t>(data_)) return false;
1652     auto vtable = GetVTable();
1653     // Check the vtable size field, then check vtable fits in its entirety.
1654     return verifier.VerifyComplexity() &&
1655            verifier.Verify<voffset_t>(vtable) &&
1656            (ReadScalar<voffset_t>(vtable) & (sizeof(voffset_t) - 1)) == 0 &&
1657            verifier.Verify(vtable, ReadScalar<voffset_t>(vtable));
1658   }
1659 
1660   // Verify a particular field.
1661   template<typename T> bool VerifyField(const Verifier &verifier,
1662                                         voffset_t field) const {
1663     // Calling GetOptionalFieldOffset should be safe now thanks to
1664     // VerifyTable().
1665     auto field_offset = GetOptionalFieldOffset(field);
1666     // Check the actual field.
1667     return !field_offset || verifier.Verify<T>(data_ + field_offset);
1668   }
1669 
1670   // VerifyField for required fields.
1671   template<typename T> bool VerifyFieldRequired(const Verifier &verifier,
1672                                         voffset_t field) const {
1673     auto field_offset = GetOptionalFieldOffset(field);
1674     return verifier.Check(field_offset != 0) &&
1675            verifier.Verify<T>(data_ + field_offset);
1676   }
1677 
1678  private:
1679   // private constructor & copy constructor: you obtain instances of this
1680   // class by pointing to existing data only
1681   Table();
1682   Table(const Table &other);
1683 
1684   uint8_t data_[1];
1685 };
1686 
1687 /// @brief This can compute the start of a FlatBuffer from a root pointer, i.e.
1688 /// it is the opposite transformation of GetRoot().
1689 /// This may be useful if you want to pass on a root and have the recipient
1690 /// delete the buffer afterwards.
1691 inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
1692   auto table = reinterpret_cast<const Table *>(root);
1693   auto vtable = table->GetVTable();
1694   // Either the vtable is before the root or after the root.
1695   auto start = std::min(vtable, reinterpret_cast<const uint8_t *>(root));
1696   // Align to at least sizeof(uoffset_t).
1697   start = reinterpret_cast<const uint8_t *>(
1698             reinterpret_cast<uintptr_t>(start) & ~(sizeof(uoffset_t) - 1));
1699   // Additionally, there may be a file_identifier in the buffer, and the root
1700   // offset. The buffer may have been aligned to any size between
1701   // sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align").
1702   // Sadly, the exact alignment is only known when constructing the buffer,
1703   // since it depends on the presence of values with said alignment properties.
1704   // So instead, we simply look at the next uoffset_t values (root,
1705   // file_identifier, and alignment padding) to see which points to the root.
1706   // None of the other values can "impersonate" the root since they will either
1707   // be 0 or four ASCII characters.
1708   static_assert(FlatBufferBuilder::kFileIdentifierLength == sizeof(uoffset_t),
1709                 "file_identifier is assumed to be the same size as uoffset_t");
1710   for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1;
1711        possible_roots;
1712        possible_roots--) {
1713       start -= sizeof(uoffset_t);
1714       if (ReadScalar<uoffset_t>(start) + start ==
1715           reinterpret_cast<const uint8_t *>(root)) return start;
1716   }
1717   // We didn't find the root, either the "root" passed isn't really a root,
1718   // or the buffer is corrupt.
1719   // Assert, because calling this function with bad data may cause reads
1720   // outside of buffer boundaries.
1721   assert(false);
1722   return nullptr;
1723 }
1724 
1725 // Base class for native objects (FlatBuffer data de-serialized into native
1726 // C++ data structures).
1727 // Contains no functionality, purely documentative.
1728 struct NativeTable {
1729 };
1730 
1731 /// @brief Function types to be used with resolving hashes into objects and
1732 /// back again. The resolver gets a pointer to a field inside an object API
1733 /// object that is of the type specified in the schema using the attribute
1734 /// `cpp_type` (it is thus important whatever you write to this address
1735 /// matches that type). The value of this field is initially null, so you
1736 /// may choose to implement a delayed binding lookup using this function
1737 /// if you wish. The resolver does the opposite lookup, for when the object
1738 /// is being serialized again.
1739 typedef uint64_t hash_value_t;
1740 #ifdef FLATBUFFERS_CPP98_STL
1741   typedef void (*resolver_function_t)(void **pointer_adr, hash_value_t hash);
1742   typedef hash_value_t (*rehasher_function_t)(void *pointer);
1743 #else
1744   typedef std::function<void (void **pointer_adr, hash_value_t hash)>
1745           resolver_function_t;
1746   typedef std::function<hash_value_t (void *pointer)> rehasher_function_t;
1747 #endif
1748 
1749 // Helper function to test if a field is present, using any of the field
1750 // enums in the generated code.
1751 // `table` must be a generated table type. Since this is a template parameter,
1752 // this is not typechecked to be a subclass of Table, so beware!
1753 // Note: this function will return false for fields equal to the default
1754 // value, since they're not stored in the buffer (unless force_defaults was
1755 // used).
1756 template<typename T> bool IsFieldPresent(const T *table, voffset_t field) {
1757   // Cast, since Table is a private baseclass of any table types.
1758   return reinterpret_cast<const Table *>(table)->CheckField(field);
1759 }
1760 
1761 // Utility function for reverse lookups on the EnumNames*() functions
1762 // (in the generated C++ code)
1763 // names must be NULL terminated.
1764 inline int LookupEnum(const char **names, const char *name) {
1765   for (const char **p = names; *p; p++)
1766     if (!strcmp(*p, name))
1767       return static_cast<int>(p - names);
1768   return -1;
1769 }
1770 
1771 // These macros allow us to layout a struct with a guarantee that they'll end
1772 // up looking the same on different compilers and platforms.
1773 // It does this by disallowing the compiler to do any padding, and then
1774 // does padding itself by inserting extra padding fields that make every
1775 // element aligned to its own size.
1776 // Additionally, it manually sets the alignment of the struct as a whole,
1777 // which is typically its largest element, or a custom size set in the schema
1778 // by the force_align attribute.
1779 // These are used in the generated code only.
1780 
1781 #if defined(_MSC_VER)
1782   #define MANUALLY_ALIGNED_STRUCT(alignment) \
1783     __pragma(pack(1)); \
1784     struct __declspec(align(alignment))
1785   #define STRUCT_END(name, size) \
1786     __pragma(pack()); \
1787     static_assert(sizeof(name) == size, "compiler breaks packing rules")
1788 #elif defined(__GNUC__) || defined(__clang__)
1789   #define MANUALLY_ALIGNED_STRUCT(alignment) \
1790     _Pragma("pack(1)") \
1791     struct __attribute__((aligned(alignment)))
1792   #define STRUCT_END(name, size) \
1793     _Pragma("pack()") \
1794     static_assert(sizeof(name) == size, "compiler breaks packing rules")
1795 #else
1796   #error Unknown compiler, please define structure alignment macros
1797 #endif
1798 
1799 // String which identifies the current version of FlatBuffers.
1800 // flatbuffer_version_string is used by Google developers to identify which
1801 // applications uploaded to Google Play are using this library.  This allows
1802 // the development team at Google to determine the popularity of the library.
1803 // How it works: Applications that are uploaded to the Google Play Store are
1804 // scanned for this version string.  We track which applications are using it
1805 // to measure popularity.  You are free to remove it (of course) but we would
1806 // appreciate if you left it in.
1807 
1808 // Weak linkage is culled by VS & doesn't work on cygwin.
1809 #if !defined(_WIN32) && !defined(__CYGWIN__)
1810 
1811 extern volatile __attribute__((weak)) const char *flatbuffer_version_string;
1812 volatile __attribute__((weak)) const char *flatbuffer_version_string =
1813   "FlatBuffers "
1814   FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
1815   FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
1816   FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
1817 
1818 #endif  // !defined(_WIN32) && !defined(__CYGWIN__)
1819 
1820 #define DEFINE_BITMASK_OPERATORS(E, T)\
1821     inline E operator | (E lhs, E rhs){\
1822         return E(T(lhs) | T(rhs));\
1823     }\
1824     inline E operator & (E lhs, E rhs){\
1825         return E(T(lhs) & T(rhs));\
1826     }\
1827     inline E operator ^ (E lhs, E rhs){\
1828         return E(T(lhs) ^ T(rhs));\
1829     }\
1830     inline E operator ~ (E lhs){\
1831         return E(~T(lhs));\
1832     }\
1833     inline E operator |= (E &lhs, E rhs){\
1834         lhs = lhs | rhs;\
1835         return lhs;\
1836     }\
1837     inline E operator &= (E &lhs, E rhs){\
1838         lhs = lhs & rhs;\
1839         return lhs;\
1840     }\
1841     inline E operator ^= (E &lhs, E rhs){\
1842         lhs = lhs ^ rhs;\
1843         return lhs;\
1844     }\
1845     inline bool operator !(E rhs) \
1846     {\
1847         return !bool(T(rhs)); \
1848     }
1849 /// @endcond
1850 }  // namespace flatbuffers
1851 
1852 #endif  // FLATBUFFERS_H_
1853