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