| FlatBuffers An open source project by FPL.

- Programmer's Guide
- Platform / Language / Feature support
- Benchmarks
- FlatBuffers white paper
- FlatBuffers internals
- Grammar of the schema language
- API Reference
- Contributing

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