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