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