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