00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #ifndef FLATBUFFERS_H_
00018 #define FLATBUFFERS_H_
00019
00020 #include "flatbuffers/base.h"
00021
00022 namespace flatbuffers {
00023
00024
00025 template<typename T> struct Offset {
00026 uoffset_t o;
00027 Offset() : o(0) {}
00028 Offset(uoffset_t _o) : o(_o) {}
00029 Offset<void> Union() const { return Offset<void>(o); }
00030 bool IsNull() const { return !o; }
00031 };
00032
00033 inline void EndianCheck() {
00034 int endiantest = 1;
00035
00036 FLATBUFFERS_ASSERT(*reinterpret_cast<char *>(&endiantest) ==
00037 FLATBUFFERS_LITTLEENDIAN);
00038 (void)endiantest;
00039 }
00040
00041 template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() {
00042
00043 #ifdef _MSC_VER
00044 return __alignof(T);
00045 #else
00046 #ifndef alignof
00047 return __alignof__(T);
00048 #else
00049 return alignof(T);
00050 #endif
00051 #endif
00052
00053 }
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 template<typename T> struct IndirectHelper {
00064 typedef T return_type;
00065 typedef T mutable_return_type;
00066 static const size_t element_stride = sizeof(T);
00067 static return_type Read(const uint8_t *p, uoffset_t i) {
00068 return EndianScalar((reinterpret_cast<const T *>(p))[i]);
00069 }
00070 };
00071 template<typename T> struct IndirectHelper<Offset<T>> {
00072 typedef const T *return_type;
00073 typedef T *mutable_return_type;
00074 static const size_t element_stride = sizeof(uoffset_t);
00075 static return_type Read(const uint8_t *p, uoffset_t i) {
00076 p += i * sizeof(uoffset_t);
00077 return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p));
00078 }
00079 };
00080 template<typename T> struct IndirectHelper<const T *> {
00081 typedef const T *return_type;
00082 typedef T *mutable_return_type;
00083 static const size_t element_stride = sizeof(T);
00084 static return_type Read(const uint8_t *p, uoffset_t i) {
00085 return reinterpret_cast<const T *>(p + i * sizeof(T));
00086 }
00087 };
00088
00089
00090
00091 template<typename T, typename IT> struct VectorIterator {
00092 typedef std::random_access_iterator_tag iterator_category;
00093 typedef IT value_type;
00094 typedef uoffset_t difference_type;
00095 typedef IT *pointer;
00096 typedef IT &reference;
00097
00098 VectorIterator(const uint8_t *data, uoffset_t i)
00099 : data_(data + IndirectHelper<T>::element_stride * i) {}
00100 VectorIterator(const VectorIterator &other) : data_(other.data_) {}
00101
00102 VectorIterator &operator=(const VectorIterator &other) {
00103 data_ = other.data_;
00104 return *this;
00105 }
00106
00107 VectorIterator &operator=(VectorIterator &&other) {
00108 data_ = other.data_;
00109 return *this;
00110 }
00111
00112 bool operator==(const VectorIterator &other) const {
00113 return data_ == other.data_;
00114 }
00115
00116 bool operator<(const VectorIterator &other) const {
00117 return data_ < other.data_;
00118 }
00119
00120 bool operator!=(const VectorIterator &other) const {
00121 return data_ != other.data_;
00122 }
00123
00124 ptrdiff_t operator-(const VectorIterator &other) const {
00125 return (data_ - other.data_) / IndirectHelper<T>::element_stride;
00126 }
00127
00128 IT operator*() const { return IndirectHelper<T>::Read(data_, 0); }
00129
00130 IT operator->() const { return IndirectHelper<T>::Read(data_, 0); }
00131
00132 VectorIterator &operator++() {
00133 data_ += IndirectHelper<T>::element_stride;
00134 return *this;
00135 }
00136
00137 VectorIterator operator++(int) {
00138 VectorIterator temp(data_, 0);
00139 data_ += IndirectHelper<T>::element_stride;
00140 return temp;
00141 }
00142
00143 VectorIterator operator+(const uoffset_t &offset) const {
00144 return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride,
00145 0);
00146 }
00147
00148 VectorIterator &operator+=(const uoffset_t &offset) {
00149 data_ += offset * IndirectHelper<T>::element_stride;
00150 return *this;
00151 }
00152
00153 VectorIterator &operator--() {
00154 data_ -= IndirectHelper<T>::element_stride;
00155 return *this;
00156 }
00157
00158 VectorIterator operator--(int) {
00159 VectorIterator temp(data_, 0);
00160 data_ -= IndirectHelper<T>::element_stride;
00161 return temp;
00162 }
00163
00164 VectorIterator operator-(const uoffset_t &offset) {
00165 return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride,
00166 0);
00167 }
00168
00169 VectorIterator &operator-=(const uoffset_t &offset) {
00170 data_ -= offset * IndirectHelper<T>::element_stride;
00171 return *this;
00172 }
00173
00174 private:
00175 const uint8_t *data_;
00176 };
00177
00178 struct String;
00179
00180
00181
00182 template<typename T> class Vector {
00183 public:
00184 typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
00185 iterator;
00186 typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
00187 const_iterator;
00188
00189 uoffset_t size() const { return EndianScalar(length_); }
00190
00191
00192 uoffset_t Length() const { return size(); }
00193
00194 typedef typename IndirectHelper<T>::return_type return_type;
00195 typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
00196
00197 return_type Get(uoffset_t i) const {
00198 FLATBUFFERS_ASSERT(i < size());
00199 return IndirectHelper<T>::Read(Data(), i);
00200 }
00201
00202 return_type operator[](uoffset_t i) const { return Get(i); }
00203
00204
00205
00206
00207 template<typename E> E GetEnum(uoffset_t i) const {
00208 return static_cast<E>(Get(i));
00209 }
00210
00211
00212
00213 template<typename U> const U *GetAs(uoffset_t i) const {
00214 return reinterpret_cast<const U *>(Get(i));
00215 }
00216
00217
00218
00219 const String *GetAsString(uoffset_t i) const {
00220 return reinterpret_cast<const String *>(Get(i));
00221 }
00222
00223 const void *GetStructFromOffset(size_t o) const {
00224 return reinterpret_cast<const void *>(Data() + o);
00225 }
00226
00227 iterator begin() { return iterator(Data(), 0); }
00228 const_iterator begin() const { return const_iterator(Data(), 0); }
00229
00230 iterator end() { return iterator(Data(), size()); }
00231 const_iterator end() const { return const_iterator(Data(), size()); }
00232
00233
00234
00235 void Mutate(uoffset_t i, const T &val) {
00236 FLATBUFFERS_ASSERT(i < size());
00237 WriteScalar(data() + i, val);
00238 }
00239
00240
00241
00242
00243 void MutateOffset(uoffset_t i, const uint8_t *val) {
00244 FLATBUFFERS_ASSERT(i < size());
00245 static_assert(sizeof(T) == sizeof(uoffset_t), "Unrelated types");
00246 WriteScalar(data() + i,
00247 static_cast<uoffset_t>(val - (Data() + i * sizeof(uoffset_t))));
00248 }
00249
00250
00251 mutable_return_type GetMutableObject(uoffset_t i) const {
00252 FLATBUFFERS_ASSERT(i < size());
00253 return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i));
00254 }
00255
00256
00257 const uint8_t *Data() const {
00258 return reinterpret_cast<const uint8_t *>(&length_ + 1);
00259 }
00260
00261 uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
00262
00263
00264 const T *data() const { return reinterpret_cast<const T *>(Data()); }
00265 T *data() { return reinterpret_cast<T *>(Data()); }
00266
00267 template<typename K> return_type LookupByKey(K key) const {
00268 void *search_result = std::bsearch(
00269 &key, Data(), size(), IndirectHelper<T>::element_stride, KeyCompare<K>);
00270
00271 if (!search_result) {
00272 return nullptr;
00273 }
00274
00275 const uint8_t *element = reinterpret_cast<const uint8_t *>(search_result);
00276
00277 return IndirectHelper<T>::Read(element, 0);
00278 }
00279
00280 protected:
00281
00282
00283 Vector();
00284
00285 uoffset_t length_;
00286
00287 private:
00288
00289
00290 Vector(const Vector &);
00291
00292 template<typename K> static int KeyCompare(const void *ap, const void *bp) {
00293 const K *key = reinterpret_cast<const K *>(ap);
00294 const uint8_t *data = reinterpret_cast<const uint8_t *>(bp);
00295 auto table = IndirectHelper<T>::Read(data, 0);
00296
00297
00298
00299 return -table->KeyCompareWithValue(*key);
00300 }
00301 };
00302
00303
00304
00305 class VectorOfAny {
00306 public:
00307 uoffset_t size() const { return EndianScalar(length_); }
00308
00309 const uint8_t *Data() const {
00310 return reinterpret_cast<const uint8_t *>(&length_ + 1);
00311 }
00312 uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
00313
00314 protected:
00315 VectorOfAny();
00316
00317 uoffset_t length_;
00318
00319 private:
00320 VectorOfAny(const VectorOfAny &);
00321 };
00322
00323 #ifndef FLATBUFFERS_CPP98_STL
00324 template<typename T, typename U>
00325 Vector<Offset<T>> *VectorCast(Vector<Offset<U>> *ptr) {
00326 static_assert(std::is_base_of<T, U>::value, "Unrelated types");
00327 return reinterpret_cast<Vector<Offset<T>> *>(ptr);
00328 }
00329
00330 template<typename T, typename U>
00331 const Vector<Offset<T>> *VectorCast(const Vector<Offset<U>> *ptr) {
00332 static_assert(std::is_base_of<T, U>::value, "Unrelated types");
00333 return reinterpret_cast<const Vector<Offset<T>> *>(ptr);
00334 }
00335 #endif
00336
00337
00338
00339 template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
00340 return v ? v->Length() : 0;
00341 }
00342
00343 struct String : public Vector<char> {
00344 const char *c_str() const { return reinterpret_cast<const char *>(Data()); }
00345 std::string str() const { return std::string(c_str(), Length()); }
00346
00347
00348 #ifdef FLATBUFFERS_HAS_STRING_VIEW
00349 flatbuffers::string_view string_view() const {
00350 return flatbuffers::string_view(c_str(), Length());
00351 }
00352 #endif // FLATBUFFERS_HAS_STRING_VIEW
00353
00354
00355 bool operator<(const String &o) const {
00356 return strcmp(c_str(), o.c_str()) < 0;
00357 }
00358 };
00359
00360
00361
00362 class Allocator {
00363 public:
00364 virtual ~Allocator() {}
00365
00366
00367 virtual uint8_t *allocate(size_t size) = 0;
00368
00369
00370 virtual void deallocate(uint8_t *p, size_t size) = 0;
00371
00372
00373
00374
00375
00376
00377 virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
00378 size_t new_size, size_t in_use_back,
00379 size_t in_use_front) {
00380 FLATBUFFERS_ASSERT(new_size > old_size);
00381 uint8_t *new_p = allocate(new_size);
00382 memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
00383 in_use_front);
00384 deallocate(old_p, old_size);
00385 return new_p;
00386 }
00387
00388 protected:
00389
00390
00391
00392
00393 void memcpy_downward(uint8_t *old_p, size_t old_size,
00394 uint8_t *new_p, size_t new_size,
00395 size_t in_use_back, size_t in_use_front) {
00396 memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back,
00397 in_use_back);
00398 memcpy(new_p, old_p, in_use_front);
00399 }
00400 };
00401
00402
00403 class DefaultAllocator : public Allocator {
00404 public:
00405 virtual uint8_t *allocate(size_t size) FLATBUFFERS_OVERRIDE {
00406 return new uint8_t[size];
00407 }
00408
00409 virtual void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE {
00410 delete[] p;
00411 }
00412
00413 static DefaultAllocator &instance() {
00414 static DefaultAllocator inst;
00415 return inst;
00416 }
00417 };
00418
00419
00420
00421
00422 class DetachedBuffer {
00423 public:
00424 DetachedBuffer()
00425 : allocator_(nullptr),
00426 own_allocator_(false),
00427 buf_(nullptr),
00428 reserved_(0),
00429 cur_(nullptr),
00430 size_(0) {}
00431
00432 DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf,
00433 size_t reserved, uint8_t *cur, size_t sz)
00434 : allocator_(allocator),
00435 own_allocator_(own_allocator),
00436 buf_(buf),
00437 reserved_(reserved),
00438 cur_(cur),
00439 size_(sz) {
00440 FLATBUFFERS_ASSERT(allocator_);
00441 }
00442
00443 DetachedBuffer(DetachedBuffer &&other)
00444 : allocator_(other.allocator_),
00445 own_allocator_(other.own_allocator_),
00446 buf_(other.buf_),
00447 reserved_(other.reserved_),
00448 cur_(other.cur_),
00449 size_(other.size_) {
00450 other.reset();
00451 }
00452
00453 DetachedBuffer &operator=(DetachedBuffer &&other) {
00454 destroy();
00455
00456 allocator_ = other.allocator_;
00457 own_allocator_ = other.own_allocator_;
00458 buf_ = other.buf_;
00459 reserved_ = other.reserved_;
00460 cur_ = other.cur_;
00461 size_ = other.size_;
00462
00463 other.reset();
00464
00465 return *this;
00466 }
00467
00468 ~DetachedBuffer() { destroy(); }
00469
00470 const uint8_t *data() const { return cur_; }
00471
00472 uint8_t *data() { return cur_; }
00473
00474 size_t size() const { return size_; }
00475
00476
00477 #if 0 // disabled for now due to the ordering of classes in this header
00478 template <class T>
00479 bool Verify() const {
00480 Verifier verifier(data(), size());
00481 return verifier.Verify<T>(nullptr);
00482 }
00483
00484 template <class T>
00485 const T* GetRoot() const {
00486 return flatbuffers::GetRoot<T>(data());
00487 }
00488
00489 template <class T>
00490 T* GetRoot() {
00491 return flatbuffers::GetRoot<T>(data());
00492 }
00493 #endif
00494
00495
00496
00497 FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other))
00498 FLATBUFFERS_DELETE_FUNC(
00499 DetachedBuffer &operator=(const DetachedBuffer &other))
00500
00501 protected:
00502 Allocator *allocator_;
00503 bool own_allocator_;
00504 uint8_t *buf_;
00505 size_t reserved_;
00506 uint8_t *cur_;
00507 size_t size_;
00508
00509 inline void destroy() {
00510 if (buf_) {
00511 FLATBUFFERS_ASSERT(allocator_);
00512 allocator_->deallocate(buf_, reserved_);
00513 }
00514 if (own_allocator_ && allocator_) { delete allocator_; }
00515
00516 reset();
00517 }
00518
00519 inline void reset() {
00520 allocator_ = nullptr;
00521 own_allocator_ = false;
00522 buf_ = nullptr;
00523 reserved_ = 0;
00524 cur_ = nullptr;
00525 size_ = 0;
00526 }
00527 };
00528
00529
00530
00531
00532
00533
00534
00535 class vector_downward {
00536 public:
00537 explicit vector_downward(size_t initial_size,
00538 Allocator *allocator,
00539 bool own_allocator,
00540 size_t buffer_minalign)
00541 : allocator_(allocator ? allocator : &DefaultAllocator::instance()),
00542 own_allocator_(own_allocator),
00543 initial_size_(initial_size),
00544 buffer_minalign_(buffer_minalign),
00545 reserved_(0),
00546 buf_(nullptr),
00547 cur_(nullptr),
00548 scratch_(nullptr) {
00549 FLATBUFFERS_ASSERT(allocator_);
00550 }
00551
00552 ~vector_downward() {
00553 if (buf_) {
00554 FLATBUFFERS_ASSERT(allocator_);
00555 allocator_->deallocate(buf_, reserved_);
00556 }
00557 if (own_allocator_ && allocator_) { delete allocator_; }
00558 }
00559
00560 void reset() {
00561 if (buf_) {
00562 FLATBUFFERS_ASSERT(allocator_);
00563 allocator_->deallocate(buf_, reserved_);
00564 buf_ = nullptr;
00565 }
00566 clear();
00567 }
00568
00569 void clear() {
00570 if (buf_) {
00571 cur_ = buf_ + reserved_;
00572 } else {
00573 reserved_ = 0;
00574 cur_ = nullptr;
00575 }
00576 clear_scratch();
00577 }
00578
00579 void clear_scratch() {
00580 scratch_ = buf_;
00581 }
00582
00583
00584 DetachedBuffer release() {
00585 DetachedBuffer fb(allocator_, own_allocator_, buf_, reserved_, cur_,
00586 size());
00587 allocator_ = nullptr;
00588 own_allocator_ = false;
00589 buf_ = nullptr;
00590 clear();
00591 return fb;
00592 }
00593
00594 size_t ensure_space(size_t len) {
00595 FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_);
00596 if (len > static_cast<size_t>(cur_ - scratch_)) { reallocate(len); }
00597
00598
00599 FLATBUFFERS_ASSERT(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
00600 return len;
00601 }
00602
00603 inline uint8_t *make_space(size_t len) {
00604 cur_ -= ensure_space(len);
00605 return cur_;
00606 }
00607
00608 Allocator &get_allocator() { return *allocator_; }
00609
00610 uoffset_t size() const {
00611 return static_cast<uoffset_t>(reserved_ - (cur_ - buf_));
00612 }
00613
00614 uoffset_t scratch_size() const {
00615 return static_cast<uoffset_t>(scratch_ - buf_);
00616 }
00617
00618 size_t capacity() const { return reserved_; }
00619
00620 uint8_t *data() const {
00621 FLATBUFFERS_ASSERT(cur_);
00622 return cur_;
00623 }
00624
00625 uint8_t *scratch_data() const {
00626 FLATBUFFERS_ASSERT(buf_);
00627 return buf_;
00628 }
00629
00630 uint8_t *scratch_end() const {
00631 FLATBUFFERS_ASSERT(scratch_);
00632 return scratch_;
00633 }
00634
00635 uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; }
00636
00637 void push(const uint8_t *bytes, size_t num) {
00638 memcpy(make_space(num), bytes, num);
00639 }
00640
00641
00642 template<typename T> void push_small(const T &little_endian_t) {
00643 make_space(sizeof(T));
00644 *reinterpret_cast<T *>(cur_) = little_endian_t;
00645 }
00646
00647 template<typename T> void scratch_push_small(const T &t) {
00648 ensure_space(sizeof(T));
00649 *reinterpret_cast<T *>(scratch_) = t;
00650 scratch_ += sizeof(T);
00651 }
00652
00653
00654
00655 void fill(size_t zero_pad_bytes) {
00656 make_space(zero_pad_bytes);
00657 for (size_t i = 0; i < zero_pad_bytes; i++) cur_[i] = 0;
00658 }
00659
00660
00661 void fill_big(size_t zero_pad_bytes) {
00662 memset(make_space(zero_pad_bytes), 0, zero_pad_bytes);
00663 }
00664
00665 void pop(size_t bytes_to_remove) { cur_ += bytes_to_remove; }
00666 void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; }
00667
00668 private:
00669
00670 FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward &))
00671 FLATBUFFERS_DELETE_FUNC(vector_downward &operator=(const vector_downward &))
00672
00673 Allocator *allocator_;
00674 bool own_allocator_;
00675 size_t initial_size_;
00676 size_t buffer_minalign_;
00677 size_t reserved_;
00678 uint8_t *buf_;
00679 uint8_t *cur_;
00680 uint8_t *scratch_;
00681
00682 void reallocate(size_t len) {
00683 FLATBUFFERS_ASSERT(allocator_);
00684 auto old_reserved = reserved_;
00685 auto old_size = size();
00686 auto old_scratch_size = scratch_size();
00687 reserved_ += (std::max)(len,
00688 old_reserved ? old_reserved / 2 : initial_size_);
00689 reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1);
00690 if (buf_) {
00691 buf_ = allocator_->reallocate_downward(buf_, old_reserved, reserved_,
00692 old_size, old_scratch_size);
00693 } else {
00694 buf_ = allocator_->allocate(reserved_);
00695 }
00696 cur_ = buf_ + reserved_ - old_size;
00697 scratch_ = buf_ + old_scratch_size;
00698 }
00699 };
00700
00701
00702 inline voffset_t FieldIndexToOffset(voffset_t field_id) {
00703
00704 const int fixed_fields = 2;
00705 return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t));
00706 }
00707
00708 template<typename T, typename Alloc>
00709 const T *data(const std::vector<T, Alloc> &v) {
00710 return v.empty() ? nullptr : &v.front();
00711 }
00712 template<typename T, typename Alloc> T *data(std::vector<T, Alloc> &v) {
00713 return v.empty() ? nullptr : &v.front();
00714 }
00715
00717
00727 class FlatBufferBuilder {
00728 public:
00740 explicit FlatBufferBuilder(size_t initial_size = 1024,
00741 Allocator *allocator = nullptr,
00742 bool own_allocator = false,
00743 size_t buffer_minalign =
00744 AlignOf<largest_scalar_t>())
00745 : buf_(initial_size, allocator, own_allocator, buffer_minalign),
00746 num_field_loc(0),
00747 max_voffset_(0),
00748 nested(false),
00749 finished(false),
00750 minalign_(1),
00751 force_defaults_(false),
00752 dedup_vtables_(true),
00753 string_pool(nullptr) {
00754 EndianCheck();
00755 }
00756
00757 ~FlatBufferBuilder() {
00758 if (string_pool) delete string_pool;
00759 }
00760
00761 void Reset() {
00762 Clear();
00763 buf_.reset();
00764 }
00765
00768 void Clear() {
00769 ClearOffsets();
00770 buf_.clear();
00771 nested = false;
00772 finished = false;
00773 minalign_ = 1;
00774 if (string_pool) string_pool->clear();
00775 }
00776
00779 uoffset_t GetSize() const { return buf_.size(); }
00780
00784 uint8_t *GetBufferPointer() const {
00785 Finished();
00786 return buf_.data();
00787 }
00788
00791 uint8_t *GetCurrentBufferPointer() const { return buf_.data(); }
00792
00798 DetachedBuffer ReleaseBufferPointer() {
00799 Finished();
00800 return buf_.release();
00801 }
00802
00805 DetachedBuffer Release() {
00806 Finished();
00807 return buf_.release();
00808 }
00809
00815 size_t GetBufferMinAlignment() {
00816 Finished();
00817 return minalign_;
00818 }
00819
00821 void Finished() const {
00822
00823
00824
00825
00826
00827 FLATBUFFERS_ASSERT(finished);
00828 }
00830
00834 void ForceDefaults(bool fd) { force_defaults_ = fd; }
00835
00838 void DedupVtables(bool dedup) { dedup_vtables_ = dedup; }
00839
00841 void Pad(size_t num_bytes) { buf_.fill(num_bytes); }
00842
00843 void TrackMinAlign(size_t elem_size) {
00844 if (elem_size > minalign_) minalign_ = elem_size;
00845 }
00846
00847 void Align(size_t elem_size) {
00848 TrackMinAlign(elem_size);
00849 buf_.fill(PaddingBytes(buf_.size(), elem_size));
00850 }
00851
00852 void PushFlatBuffer(const uint8_t *bytes, size_t size) {
00853 PushBytes(bytes, size);
00854 finished = true;
00855 }
00856
00857 void PushBytes(const uint8_t *bytes, size_t size) { buf_.push(bytes, size); }
00858
00859 void PopBytes(size_t amount) { buf_.pop(amount); }
00860
00861 template<typename T> void AssertScalarT() {
00862
00863 static_assert(flatbuffers::is_scalar<T>::value, "T must be a scalar type");
00864 }
00865
00866
00867 template<typename T> uoffset_t PushElement(T element) {
00868 AssertScalarT<T>();
00869 T litle_endian_element = EndianScalar(element);
00870 Align(sizeof(T));
00871 buf_.push_small(litle_endian_element);
00872 return GetSize();
00873 }
00874
00875 template<typename T> uoffset_t PushElement(Offset<T> off) {
00876
00877 return PushElement(ReferTo(off.o));
00878 }
00879
00880
00881
00882 void TrackField(voffset_t field, uoffset_t off) {
00883 FieldLoc fl = { off, field };
00884 buf_.scratch_push_small(fl);
00885 num_field_loc++;
00886 max_voffset_ = (std::max)(max_voffset_, field);
00887 }
00888
00889
00890 template<typename T> void AddElement(voffset_t field, T e, T def) {
00891
00892 if (e == def && !force_defaults_) return;
00893 auto off = PushElement(e);
00894 TrackField(field, off);
00895 }
00896
00897 template<typename T> void AddOffset(voffset_t field, Offset<T> off) {
00898 if (off.IsNull()) return;
00899 AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
00900 }
00901
00902 template<typename T> void AddStruct(voffset_t field, const T *structptr) {
00903 if (!structptr) return;
00904 Align(AlignOf<T>());
00905 buf_.push_small(*structptr);
00906 TrackField(field, GetSize());
00907 }
00908
00909 void AddStructOffset(voffset_t field, uoffset_t off) {
00910 TrackField(field, off);
00911 }
00912
00913
00914
00915
00916 uoffset_t ReferTo(uoffset_t off) {
00917
00918 Align(sizeof(uoffset_t));
00919
00920 FLATBUFFERS_ASSERT(off && off <= GetSize());
00921 return GetSize() - off + static_cast<uoffset_t>(sizeof(uoffset_t));
00922 }
00923
00924 void NotNested() {
00925
00926
00927
00928
00929
00930
00931
00932
00933 FLATBUFFERS_ASSERT(!nested);
00934
00935 FLATBUFFERS_ASSERT(!num_field_loc);
00936 }
00937
00938
00939
00940 uoffset_t StartTable() {
00941 NotNested();
00942 nested = true;
00943 return GetSize();
00944 }
00945
00946
00947
00948
00949 uoffset_t EndTable(uoffset_t start) {
00950
00951 FLATBUFFERS_ASSERT(nested);
00952
00953
00954 auto vtableoffsetloc = PushElement<soffset_t>(0);
00955
00956
00957
00958
00959
00960 max_voffset_ =
00961 (std::max)(static_cast<voffset_t>(max_voffset_ + sizeof(voffset_t)),
00962 FieldIndexToOffset(0));
00963 buf_.fill_big(max_voffset_);
00964 auto table_object_size = vtableoffsetloc - start;
00965
00966 FLATBUFFERS_ASSERT(table_object_size < 0x10000);
00967 WriteScalar<voffset_t>(buf_.data() + sizeof(voffset_t),
00968 static_cast<voffset_t>(table_object_size));
00969 WriteScalar<voffset_t>(buf_.data(), max_voffset_);
00970
00971 for (auto it = buf_.scratch_end() - num_field_loc * sizeof(FieldLoc);
00972 it < buf_.scratch_end(); it += sizeof(FieldLoc)) {
00973 auto field_location = reinterpret_cast<FieldLoc *>(it);
00974 auto pos = static_cast<voffset_t>(vtableoffsetloc - field_location->off);
00975
00976 FLATBUFFERS_ASSERT(
00977 !ReadScalar<voffset_t>(buf_.data() + field_location->id));
00978 WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
00979 }
00980 ClearOffsets();
00981 auto vt1 = reinterpret_cast<voffset_t *>(buf_.data());
00982 auto vt1_size = ReadScalar<voffset_t>(vt1);
00983 auto vt_use = GetSize();
00984
00985
00986 if (dedup_vtables_) {
00987 for (auto it = buf_.scratch_data(); it < buf_.scratch_end();
00988 it += sizeof(uoffset_t)) {
00989 auto vt_offset_ptr = reinterpret_cast<uoffset_t *>(it);
00990 auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*vt_offset_ptr));
00991 auto vt2_size = *vt2;
00992 if (vt1_size != vt2_size || memcmp(vt2, vt1, vt1_size)) continue;
00993 vt_use = *vt_offset_ptr;
00994 buf_.pop(GetSize() - vtableoffsetloc);
00995 break;
00996 }
00997 }
00998
00999 if (vt_use == GetSize()) { buf_.scratch_push_small(vt_use); }
01000
01001
01002
01003
01004
01005 WriteScalar(buf_.data_at(vtableoffsetloc),
01006 static_cast<soffset_t>(vt_use) -
01007 static_cast<soffset_t>(vtableoffsetloc));
01008
01009 nested = false;
01010 return vtableoffsetloc;
01011 }
01012
01013
01014 uoffset_t EndTable(uoffset_t start, voffset_t ) {
01015 return EndTable(start);
01016 }
01017
01018
01019
01020 template<typename T> void Required(Offset<T> table, voffset_t field) {
01021 auto table_ptr = buf_.data_at(table.o);
01022 auto vtable_ptr = table_ptr - ReadScalar<soffset_t>(table_ptr);
01023 bool ok = ReadScalar<voffset_t>(vtable_ptr + field) != 0;
01024
01025 FLATBUFFERS_ASSERT(ok);
01026 (void)ok;
01027 }
01028
01029 uoffset_t StartStruct(size_t alignment) {
01030 Align(alignment);
01031 return GetSize();
01032 }
01033
01034 uoffset_t EndStruct() { return GetSize(); }
01035
01036 void ClearOffsets() {
01037 buf_.scratch_pop(num_field_loc * sizeof(FieldLoc));
01038 num_field_loc = 0;
01039 max_voffset_ = 0;
01040 }
01041
01042
01043
01044 void PreAlign(size_t len, size_t alignment) {
01045 TrackMinAlign(alignment);
01046 buf_.fill(PaddingBytes(GetSize() + len, alignment));
01047 }
01048 template<typename T> void PreAlign(size_t len) {
01049 AssertScalarT<T>();
01050 PreAlign(len, sizeof(T));
01051 }
01053
01058 Offset<String> CreateString(const char *str, size_t len) {
01059 NotNested();
01060 PreAlign<uoffset_t>(len + 1);
01061 buf_.fill(1);
01062 PushBytes(reinterpret_cast<const uint8_t *>(str), len);
01063 PushElement(static_cast<uoffset_t>(len));
01064 return Offset<String>(GetSize());
01065 }
01066
01070 Offset<String> CreateString(const char *str) {
01071 return CreateString(str, strlen(str));
01072 }
01073
01077 Offset<String> CreateString(char *str) {
01078 return CreateString(str, strlen(str));
01079 }
01080
01084 Offset<String> CreateString(const std::string &str) {
01085 return CreateString(str.c_str(), str.length());
01086 }
01087
01088
01089 #ifdef FLATBUFFERS_HAS_STRING_VIEW
01090
01091
01092
01093 Offset<String> CreateString(flatbuffers::string_view str) {
01094 return CreateString(str.data(), str.size());
01095 }
01096 #endif // FLATBUFFERS_HAS_STRING_VIEW
01097
01098
01102 Offset<String> CreateString(const String *str) {
01103 return str ? CreateString(str->c_str(), str->Length()) : 0;
01104 }
01105
01110 template<typename T> Offset<String> CreateString(const T &str) {
01111 return CreateString(str.c_str(), str.length());
01112 }
01113
01120 Offset<String> CreateSharedString(const char *str, size_t len) {
01121 if (!string_pool)
01122 string_pool = new StringOffsetMap(StringOffsetCompare(buf_));
01123 auto size_before_string = buf_.size();
01124
01125
01126 auto off = CreateString(str, len);
01127 auto it = string_pool->find(off);
01128
01129 if (it != string_pool->end()) {
01130
01131 buf_.pop(buf_.size() - size_before_string);
01132 return *it;
01133 }
01134
01135 string_pool->insert(off);
01136 return off;
01137 }
01138
01144 Offset<String> CreateSharedString(const char *str) {
01145 return CreateSharedString(str, strlen(str));
01146 }
01147
01153 Offset<String> CreateSharedString(const std::string &str) {
01154 return CreateSharedString(str.c_str(), str.length());
01155 }
01156
01162 Offset<String> CreateSharedString(const String *str) {
01163 return CreateSharedString(str->c_str(), str->Length());
01164 }
01165
01167 uoffset_t EndVector(size_t len) {
01168 FLATBUFFERS_ASSERT(nested);
01169 nested = false;
01170 return PushElement(static_cast<uoffset_t>(len));
01171 }
01172
01173 void StartVector(size_t len, size_t elemsize) {
01174 NotNested();
01175 nested = true;
01176 PreAlign<uoffset_t>(len * elemsize);
01177 PreAlign(len * elemsize, elemsize);
01178 }
01179
01180
01181
01182
01183
01184
01185 void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment) {
01186 PreAlign(len * elemsize, alignment);
01187 }
01188
01190
01198 template<typename T> Offset<Vector<T>> CreateVector(const T *v, size_t len) {
01199
01200
01201 AssertScalarT<T>();
01202 StartVector(len, sizeof(T));
01203
01204 #if FLATBUFFERS_LITTLEENDIAN
01205 PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T));
01206 #else
01207 if (sizeof(T) == 1) {
01208 PushBytes(reinterpret_cast<const uint8_t *>(v), len);
01209 } else {
01210 for (auto i = len; i > 0; ) {
01211 PushElement(v[--i]);
01212 }
01213 }
01214 #endif
01215
01216 return Offset<Vector<T>>(EndVector(len));
01217 }
01218
01219 template<typename T>
01220 Offset<Vector<Offset<T>>> CreateVector(const Offset<T> *v, size_t len) {
01221 StartVector(len, sizeof(Offset<T>));
01222 for (auto i = len; i > 0;) { PushElement(v[--i]); }
01223 return Offset<Vector<Offset<T>>>(EndVector(len));
01224 }
01225
01232 template<typename T> Offset<Vector<T>> CreateVector(const std::vector<T> &v) {
01233 return CreateVector(data(v), v.size());
01234 }
01235
01236
01237
01238
01239 Offset<Vector<uint8_t>> CreateVector(const std::vector<bool> &v) {
01240 StartVector(v.size(), sizeof(uint8_t));
01241 for (auto i = v.size(); i > 0;) {
01242 PushElement(static_cast<uint8_t>(v[--i]));
01243 }
01244 return Offset<Vector<uint8_t>>(EndVector(v.size()));
01245 }
01246
01247
01248 #ifndef FLATBUFFERS_CPP98_STL
01249
01250
01251
01252
01253
01254
01255
01256 template<typename T> Offset<Vector<T>> CreateVector(size_t vector_size,
01257 const std::function<T (size_t i)> &f) {
01258 std::vector<T> elems(vector_size);
01259 for (size_t i = 0; i < vector_size; i++) elems[i] = f(i);
01260 return CreateVector(elems);
01261 }
01262 #endif
01263
01264
01274 template<typename T, typename F, typename S>
01275 Offset<Vector<T>> CreateVector(size_t vector_size, F f, S *state) {
01276 std::vector<T> elems(vector_size);
01277 for (size_t i = 0; i < vector_size; i++) elems[i] = f(i, state);
01278 return CreateVector(elems);
01279 }
01280
01287 Offset<Vector<Offset<String>>> CreateVectorOfStrings(
01288 const std::vector<std::string> &v) {
01289 std::vector<Offset<String>> offsets(v.size());
01290 for (size_t i = 0; i < v.size(); i++) offsets[i] = CreateString(v[i]);
01291 return CreateVector(offsets);
01292 }
01293
01301 template<typename T>
01302 Offset<Vector<const T *>> CreateVectorOfStructs(const T *v, size_t len) {
01303 StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>());
01304 PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
01305 return Offset<Vector<const T *>>(EndVector(len));
01306 }
01307
01316 template<typename T, typename S>
01317 Offset<Vector<const T *>> CreateVectorOfNativeStructs(const S *v,
01318 size_t len) {
01319 extern T Pack(const S &);
01320 typedef T (*Pack_t)(const S &);
01321 std::vector<T> vv(len);
01322 std::transform(v, v + len, vv.begin(), *(Pack_t)&Pack);
01323 return CreateVectorOfStructs<T>(vv.data(), vv.size());
01324 }
01325
01326
01327 #ifndef FLATBUFFERS_CPP98_STL
01328
01329
01330
01331
01332
01333
01334
01335
01336 template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
01337 size_t vector_size, const std::function<void(size_t i, T *)> &filler) {
01338 T* structs = StartVectorOfStructs<T>(vector_size);
01339 for (size_t i = 0; i < vector_size; i++) {
01340 filler(i, structs);
01341 structs++;
01342 }
01343 return EndVectorOfStructs<T>(vector_size);
01344 }
01345 #endif
01346
01347
01357 template<typename T, typename F, typename S>
01358 Offset<Vector<const T *>> CreateVectorOfStructs(size_t vector_size, F f,
01359 S *state) {
01360 T *structs = StartVectorOfStructs<T>(vector_size);
01361 for (size_t i = 0; i < vector_size; i++) {
01362 f(i, structs, state);
01363 structs++;
01364 }
01365 return EndVectorOfStructs<T>(vector_size);
01366 }
01367
01374 template<typename T, typename Alloc>
01375 Offset<Vector<const T *>> CreateVectorOfStructs(
01376 const std::vector<T, Alloc> &v) {
01377 return CreateVectorOfStructs(data(v), v.size());
01378 }
01379
01388 template<typename T, typename S>
01389 Offset<Vector<const T *>> CreateVectorOfNativeStructs(
01390 const std::vector<S> &v) {
01391 return CreateVectorOfNativeStructs<T, S>(data(v), v.size());
01392 }
01393
01395 template<typename T> struct StructKeyComparator {
01396 bool operator()(const T &a, const T &b) const {
01397 return a.KeyCompareLessThan(&b);
01398 }
01399
01400 private:
01401 StructKeyComparator &operator=(const StructKeyComparator &);
01402 };
01404
01412 template<typename T>
01413 Offset<Vector<const T *>> CreateVectorOfSortedStructs(std::vector<T> *v) {
01414 return CreateVectorOfSortedStructs(data(*v), v->size());
01415 }
01416
01425 template<typename T, typename S>
01426 Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(
01427 std::vector<S> *v) {
01428 return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size());
01429 }
01430
01439 template<typename T>
01440 Offset<Vector<const T *>> CreateVectorOfSortedStructs(T *v, size_t len) {
01441 std::sort(v, v + len, StructKeyComparator<T>());
01442 return CreateVectorOfStructs(v, len);
01443 }
01444
01454 template<typename T, typename S>
01455 Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(S *v,
01456 size_t len) {
01457 extern T Pack(const S &);
01458 typedef T (*Pack_t)(const S &);
01459 std::vector<T> vv(len);
01460 std::transform(v, v + len, vv.begin(), *(Pack_t)&Pack);
01461 return CreateVectorOfSortedStructs<T>(vv, len);
01462 }
01463
01465 template<typename T> struct TableKeyComparator {
01466 TableKeyComparator(vector_downward &buf) : buf_(buf) {}
01467 bool operator()(const Offset<T> &a, const Offset<T> &b) const {
01468 auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o));
01469 auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o));
01470 return table_a->KeyCompareLessThan(table_b);
01471 }
01472 vector_downward &buf_;
01473
01474 private:
01475 TableKeyComparator &operator=(const TableKeyComparator &);
01476 };
01478
01487 template<typename T>
01488 Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(Offset<T> *v,
01489 size_t len) {
01490 std::sort(v, v + len, TableKeyComparator<T>(buf_));
01491 return CreateVector(v, len);
01492 }
01493
01501 template<typename T>
01502 Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
01503 std::vector<Offset<T>> *v) {
01504 return CreateVectorOfSortedTables(data(*v), v->size());
01505 }
01506
01514 uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
01515 uint8_t **buf) {
01516 NotNested();
01517 StartVector(len, elemsize);
01518 buf_.make_space(len * elemsize);
01519 auto vec_start = GetSize();
01520 auto vec_end = EndVector(len);
01521 *buf = buf_.data_at(vec_start);
01522 return vec_end;
01523 }
01524
01533 template<typename T>
01534 Offset<Vector<T>> CreateUninitializedVector(size_t len, T **buf) {
01535 return CreateUninitializedVector(len, sizeof(T),
01536 reinterpret_cast<uint8_t **>(buf));
01537 }
01538
01540 template<typename T> Offset<const T *> CreateStruct(const T &structobj) {
01541 NotNested();
01542 Align(AlignOf<T>());
01543 buf_.push_small(structobj);
01544 return Offset<const T *>(GetSize());
01545 }
01546
01548 static const size_t kFileIdentifierLength = 4;
01549
01553 template<typename T>
01554 void Finish(Offset<T> root, const char *file_identifier = nullptr) {
01555 Finish(root.o, file_identifier, false);
01556 }
01557
01565 template<typename T>
01566 void FinishSizePrefixed(Offset<T> root,
01567 const char *file_identifier = nullptr) {
01568 Finish(root.o, file_identifier, true);
01569 }
01570
01571 protected:
01572
01573 FlatBufferBuilder(const FlatBufferBuilder &);
01574 FlatBufferBuilder &operator=(const FlatBufferBuilder &);
01575
01576 void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) {
01577 NotNested();
01578 buf_.clear_scratch();
01579
01580 PreAlign((size_prefix ? sizeof(uoffset_t) : 0) + sizeof(uoffset_t) +
01581 (file_identifier ? kFileIdentifierLength : 0),
01582 minalign_);
01583 if (file_identifier) {
01584 FLATBUFFERS_ASSERT(strlen(file_identifier) == kFileIdentifierLength);
01585 PushBytes(reinterpret_cast<const uint8_t *>(file_identifier),
01586 kFileIdentifierLength);
01587 }
01588 PushElement(ReferTo(root));
01589 if (size_prefix) { PushElement(GetSize()); }
01590 finished = true;
01591 }
01592
01593 struct FieldLoc {
01594 uoffset_t off;
01595 voffset_t id;
01596 };
01597
01598 vector_downward buf_;
01599
01600
01601
01602 uoffset_t num_field_loc;
01603
01604
01605 voffset_t max_voffset_;
01606
01607
01608 bool nested;
01609
01610
01611 bool finished;
01612
01613 size_t minalign_;
01614
01615 bool force_defaults_;
01616
01617 bool dedup_vtables_;
01618
01619 struct StringOffsetCompare {
01620 StringOffsetCompare(const vector_downward &buf) : buf_(&buf) {}
01621 bool operator()(const Offset<String> &a, const Offset<String> &b) const {
01622 auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o));
01623 auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o));
01624 return strncmp(stra->c_str(), strb->c_str(),
01625 (std::min)(stra->size(), strb->size()) + 1) < 0;
01626 }
01627 const vector_downward *buf_;
01628 };
01629
01630
01631 typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
01632 StringOffsetMap *string_pool;
01633
01634 private:
01635
01636
01637 template<typename T> T *StartVectorOfStructs(size_t vector_size) {
01638 StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>());
01639 return reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T)));
01640 }
01641
01642
01643
01644 template<typename T>
01645 Offset<Vector<const T *>> EndVectorOfStructs(size_t vector_size) {
01646 return Offset<Vector<const T *>>(EndVector(vector_size));
01647 }
01648 };
01650
01652
01653 template<typename T> T *GetMutableRoot(void *buf) {
01654 EndianCheck();
01655 return reinterpret_cast<T *>(
01656 reinterpret_cast<uint8_t *>(buf) +
01657 EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
01658 }
01659
01660 template<typename T> const T *GetRoot(const void *buf) {
01661 return GetMutableRoot<T>(const_cast<void *>(buf));
01662 }
01663
01664 template<typename T> const T *GetSizePrefixedRoot(const void *buf) {
01665 return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(uoffset_t));
01666 }
01667
01671 template<typename T>
01672 T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
01673 return reinterpret_cast<T *>(fbb.GetCurrentBufferPointer() + fbb.GetSize() -
01674 offset.o);
01675 }
01676
01677 template<typename T>
01678 const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
01679 return GetMutableTemporaryPointer<T>(fbb, offset);
01680 }
01681
01689 inline const char *GetBufferIdentifier(const void *buf, bool size_prefixed = false) {
01690 return reinterpret_cast<const char *>(buf) +
01691 ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t));
01692 }
01693
01694
01695 inline bool BufferHasIdentifier(const void *buf, const char *identifier, bool size_prefixed = false) {
01696 return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier,
01697 FlatBufferBuilder::kFileIdentifierLength) == 0;
01698 }
01699
01700
01701 class Verifier FLATBUFFERS_FINAL_CLASS {
01702 public:
01703 Verifier(const uint8_t *buf, size_t buf_len, uoffset_t _max_depth = 64,
01704 uoffset_t _max_tables = 1000000)
01705 : buf_(buf),
01706 end_(buf + buf_len),
01707 depth_(0),
01708 max_depth_(_max_depth),
01709 num_tables_(0),
01710 max_tables_(_max_tables)
01711
01712 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
01713 , upper_bound_(buf)
01714 #endif
01715
01716 {
01717 }
01718
01719
01720 bool Check(bool ok) const {
01721
01722 #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
01723 FLATBUFFERS_ASSERT(ok);
01724 #endif
01725 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
01726 if (!ok)
01727 upper_bound_ = buf_;
01728 #endif
01729
01730 return ok;
01731 }
01732
01733
01734 bool Verify(const void *elem, size_t elem_len) const {
01735
01736 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
01737 auto upper_bound = reinterpret_cast<const uint8_t *>(elem) + elem_len;
01738 if (upper_bound_ < upper_bound)
01739 upper_bound_ = upper_bound;
01740 #endif
01741
01742 return Check(elem_len <= (size_t)(end_ - buf_) && elem >= buf_ &&
01743 elem <= end_ - elem_len);
01744 }
01745
01746
01747 template<typename T> bool Verify(const void *elem) const {
01748 return Verify(elem, sizeof(T));
01749 }
01750
01751
01752 template<typename T> bool VerifyTable(const T *table) {
01753 return !table || table->Verify(*this);
01754 }
01755
01756
01757 template<typename T> bool Verify(const Vector<T> *vec) const {
01758 const uint8_t *end;
01759 return !vec || VerifyVector(reinterpret_cast<const uint8_t *>(vec),
01760 sizeof(T), &end);
01761 }
01762
01763
01764 template<typename T> bool Verify(const Vector<const T *> *vec) const {
01765 return Verify(reinterpret_cast<const Vector<T> *>(vec));
01766 }
01767
01768
01769 bool Verify(const String *str) const {
01770 const uint8_t *end;
01771 return !str ||
01772 (VerifyVector(reinterpret_cast<const uint8_t *>(str), 1, &end) &&
01773 Verify(end, 1) &&
01774 Check(*end == '\0'));
01775 }
01776
01777
01778 bool VerifyVector(const uint8_t *vec, size_t elem_size,
01779 const uint8_t **end) const {
01780
01781 if (!Verify<uoffset_t>(vec)) return false;
01782
01783
01784 auto size = ReadScalar<uoffset_t>(vec);
01785 auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
01786 if (!Check(size < max_elems))
01787 return false;
01788 auto byte_size = sizeof(size) + elem_size * size;
01789 *end = vec + byte_size;
01790 return Verify(vec, byte_size);
01791 }
01792
01793
01794 bool VerifyVectorOfStrings(const Vector<Offset<String>> *vec) const {
01795 if (vec) {
01796 for (uoffset_t i = 0; i < vec->size(); i++) {
01797 if (!Verify(vec->Get(i))) return false;
01798 }
01799 }
01800 return true;
01801 }
01802
01803
01804 template<typename T> bool VerifyVectorOfTables(const Vector<Offset<T>> *vec) {
01805 if (vec) {
01806 for (uoffset_t i = 0; i < vec->size(); i++) {
01807 if (!vec->Get(i)->Verify(*this)) return false;
01808 }
01809 }
01810 return true;
01811 }
01812
01813 template<typename T>
01814 bool VerifyBufferFromStart(const char *identifier, const uint8_t *start) {
01815 if (identifier &&
01816 (size_t(end_ - start) < 2 * sizeof(flatbuffers::uoffset_t) ||
01817 !BufferHasIdentifier(start, identifier))) {
01818 return false;
01819 }
01820
01821
01822 auto o = VerifyOffset(start);
01823 return o && reinterpret_cast<const T *>(start + o)->Verify(*this)
01824 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
01825 && GetComputedSize()
01826 #endif
01827 ;
01828 }
01829
01830
01831 template<typename T> bool VerifyBuffer() { return VerifyBuffer<T>(nullptr); }
01832
01833 template<typename T> bool VerifyBuffer(const char *identifier) {
01834 return VerifyBufferFromStart<T>(identifier, buf_);
01835 }
01836
01837 template<typename T> bool VerifySizePrefixedBuffer(const char *identifier) {
01838 return Verify<uoffset_t>(buf_) &&
01839 ReadScalar<uoffset_t>(buf_) == end_ - buf_ - sizeof(uoffset_t) &&
01840 VerifyBufferFromStart<T>(identifier, buf_ + sizeof(uoffset_t));
01841 }
01842
01843 uoffset_t VerifyOffset(const uint8_t *start) const {
01844 if (!Verify<uoffset_t>(start)) return false;
01845 auto o = ReadScalar<uoffset_t>(start);
01846 Check(o != 0);
01847 return o;
01848 }
01849
01850
01851
01852
01853
01854 bool VerifyComplexity() {
01855 depth_++;
01856 num_tables_++;
01857 return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_);
01858 }
01859
01860
01861 bool EndTable() {
01862 depth_--;
01863 return true;
01864 }
01865
01866
01867 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
01868
01869 size_t GetComputedSize() const {
01870 uintptr_t size = upper_bound_ - buf_;
01871
01872 size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
01873 return (buf_ + size > end_) ? 0 : size;
01874 }
01875 #endif
01876
01877
01878 private:
01879 const uint8_t *buf_;
01880 const uint8_t *end_;
01881 uoffset_t depth_;
01882 uoffset_t max_depth_;
01883 uoffset_t num_tables_;
01884 uoffset_t max_tables_;
01885
01886 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
01887 mutable const uint8_t *upper_bound_;
01888 #endif
01889
01890 };
01891
01892
01893
01894
01895 struct BufferRefBase {};
01896 template<typename T> struct BufferRef : BufferRefBase {
01897 BufferRef() : buf(nullptr), len(0), must_free(false) {}
01898 BufferRef(uint8_t *_buf, uoffset_t _len)
01899 : buf(_buf), len(_len), must_free(false) {}
01900
01901 ~BufferRef() {
01902 if (must_free) free(buf);
01903 }
01904
01905 const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); }
01906
01907 bool Verify() {
01908 Verifier verifier(buf, len);
01909 return verifier.VerifyBuffer<T>(nullptr);
01910 }
01911
01912 uint8_t *buf;
01913 uoffset_t len;
01914 bool must_free;
01915 };
01916
01917
01918
01919
01920
01921 class Struct FLATBUFFERS_FINAL_CLASS {
01922 public:
01923 template<typename T> T GetField(uoffset_t o) const {
01924 return ReadScalar<T>(&data_[o]);
01925 }
01926
01927 template<typename T> T GetStruct(uoffset_t o) const {
01928 return reinterpret_cast<T>(&data_[o]);
01929 }
01930
01931 const uint8_t *GetAddressOf(uoffset_t o) const { return &data_[o]; }
01932 uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; }
01933
01934 private:
01935 uint8_t data_[1];
01936 };
01937
01938
01939
01940 class Table {
01941 public:
01942 const uint8_t *GetVTable() const {
01943 return data_ - ReadScalar<soffset_t>(data_);
01944 }
01945
01946
01947
01948 voffset_t GetOptionalFieldOffset(voffset_t field) const {
01949
01950 auto vtable = GetVTable();
01951
01952 auto vtsize = ReadScalar<voffset_t>(vtable);
01953
01954
01955 return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
01956 }
01957
01958 template<typename T> T GetField(voffset_t field, T defaultval) const {
01959 auto field_offset = GetOptionalFieldOffset(field);
01960 return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
01961 }
01962
01963 template<typename P> P GetPointer(voffset_t field) {
01964 auto field_offset = GetOptionalFieldOffset(field);
01965 auto p = data_ + field_offset;
01966 return field_offset ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p))
01967 : nullptr;
01968 }
01969 template<typename P> P GetPointer(voffset_t field) const {
01970 return const_cast<Table *>(this)->GetPointer<P>(field);
01971 }
01972
01973 template<typename P> P GetStruct(voffset_t field) const {
01974 auto field_offset = GetOptionalFieldOffset(field);
01975 auto p = const_cast<uint8_t *>(data_ + field_offset);
01976 return field_offset ? reinterpret_cast<P>(p) : nullptr;
01977 }
01978
01979 template<typename T> bool SetField(voffset_t field, T val, T def) {
01980 auto field_offset = GetOptionalFieldOffset(field);
01981 if (!field_offset) return val == def;
01982 WriteScalar(data_ + field_offset, val);
01983 return true;
01984 }
01985
01986 bool SetPointer(voffset_t field, const uint8_t *val) {
01987 auto field_offset = GetOptionalFieldOffset(field);
01988 if (!field_offset) return false;
01989 WriteScalar(data_ + field_offset,
01990 static_cast<uoffset_t>(val - (data_ + field_offset)));
01991 return true;
01992 }
01993
01994 uint8_t *GetAddressOf(voffset_t field) {
01995 auto field_offset = GetOptionalFieldOffset(field);
01996 return field_offset ? data_ + field_offset : nullptr;
01997 }
01998 const uint8_t *GetAddressOf(voffset_t field) const {
01999 return const_cast<Table *>(this)->GetAddressOf(field);
02000 }
02001
02002 bool CheckField(voffset_t field) const {
02003 return GetOptionalFieldOffset(field) != 0;
02004 }
02005
02006
02007
02008 bool VerifyTableStart(Verifier &verifier) const {
02009
02010 if (!verifier.Verify<soffset_t>(data_)) return false;
02011 auto vtable = GetVTable();
02012
02013 return verifier.VerifyComplexity() && verifier.Verify<voffset_t>(vtable) &&
02014 (ReadScalar<voffset_t>(vtable) & (sizeof(voffset_t) - 1)) == 0 &&
02015 verifier.Verify(vtable, ReadScalar<voffset_t>(vtable));
02016 }
02017
02018
02019 template<typename T>
02020 bool VerifyField(const Verifier &verifier, voffset_t field) const {
02021
02022
02023 auto field_offset = GetOptionalFieldOffset(field);
02024
02025 return !field_offset || verifier.Verify<T>(data_ + field_offset);
02026 }
02027
02028
02029 template<typename T>
02030 bool VerifyFieldRequired(const Verifier &verifier, voffset_t field) const {
02031 auto field_offset = GetOptionalFieldOffset(field);
02032 return verifier.Check(field_offset != 0) &&
02033 verifier.Verify<T>(data_ + field_offset);
02034 }
02035
02036
02037 bool VerifyOffset(const Verifier &verifier, voffset_t field) const {
02038 auto field_offset = GetOptionalFieldOffset(field);
02039 return !field_offset || verifier.VerifyOffset(data_ + field_offset);
02040 }
02041
02042 bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const {
02043 auto field_offset = GetOptionalFieldOffset(field);
02044 return verifier.Check(field_offset != 0) &&
02045 verifier.VerifyOffset(data_ + field_offset);
02046 }
02047
02048 private:
02049
02050
02051 Table();
02052 Table(const Table &other);
02053
02054 uint8_t data_[1];
02055 };
02056
02061 inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
02062 auto table = reinterpret_cast<const Table *>(root);
02063 auto vtable = table->GetVTable();
02064
02065 auto start = (std::min)(vtable, reinterpret_cast<const uint8_t *>(root));
02066
02067 start = reinterpret_cast<const uint8_t *>(reinterpret_cast<uintptr_t>(start) &
02068 ~(sizeof(uoffset_t) - 1));
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078 static_assert(FlatBufferBuilder::kFileIdentifierLength == sizeof(uoffset_t),
02079 "file_identifier is assumed to be the same size as uoffset_t");
02080 for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1;
02081 possible_roots; possible_roots--) {
02082 start -= sizeof(uoffset_t);
02083 if (ReadScalar<uoffset_t>(start) + start ==
02084 reinterpret_cast<const uint8_t *>(root))
02085 return start;
02086 }
02087
02088
02089
02090
02091 FLATBUFFERS_ASSERT(false);
02092 return nullptr;
02093 }
02094
02096 inline uoffset_t GetPrefixedSize(const uint8_t* buf){ return ReadScalar<uoffset_t>(buf); }
02097
02098
02099
02100
02101 struct NativeTable {};
02102
02111 typedef uint64_t hash_value_t;
02112
02113 #ifdef FLATBUFFERS_CPP98_STL
02114 typedef void (*resolver_function_t)(void **pointer_adr, hash_value_t hash);
02115 typedef hash_value_t (*rehasher_function_t)(void *pointer);
02116 #else
02117 typedef std::function<void (void **pointer_adr, hash_value_t hash)>
02118 resolver_function_t;
02119 typedef std::function<hash_value_t (void *pointer)> rehasher_function_t;
02120 #endif
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130 template<typename T> bool IsFieldPresent(const T *table, voffset_t field) {
02131
02132 return reinterpret_cast<const Table *>(table)->CheckField(field);
02133 }
02134
02135
02136
02137
02138 inline int LookupEnum(const char **names, const char *name) {
02139 for (const char **p = names; *p; p++)
02140 if (!strcmp(*p, name)) return static_cast<int>(p - names);
02141 return -1;
02142 }
02143
02144
02145
02146
02147
02148
02149
02150
02151
02152
02153
02154
02155 #if defined(_MSC_VER)
02156 #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
02157 __pragma(pack(1)); \
02158 struct __declspec(align(alignment))
02159 #define FLATBUFFERS_STRUCT_END(name, size) \
02160 __pragma(pack()); \
02161 static_assert(sizeof(name) == size, "compiler breaks packing rules")
02162 #elif defined(__GNUC__) || defined(__clang__)
02163 #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
02164 _Pragma("pack(1)") \
02165 struct __attribute__((aligned(alignment)))
02166 #define FLATBUFFERS_STRUCT_END(name, size) \
02167 _Pragma("pack()") \
02168 static_assert(sizeof(name) == size, "compiler breaks packing rules")
02169 #else
02170 #error Unknown compiler, please define structure alignment macros
02171 #endif
02172
02173
02174
02175
02176
02177
02178
02179
02180
02181
02182
02183
02184 enum SequenceType { ST_TABLE, ST_STRUCT, ST_UNION, ST_ENUM };
02185
02186
02187
02188 #define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \
02189 ET(ET_UTYPE) \
02190 ET(ET_BOOL) \
02191 ET(ET_CHAR) \
02192 ET(ET_UCHAR) \
02193 ET(ET_SHORT) \
02194 ET(ET_USHORT) \
02195 ET(ET_INT) \
02196 ET(ET_UINT) \
02197 ET(ET_LONG) \
02198 ET(ET_ULONG) \
02199 ET(ET_FLOAT) \
02200 ET(ET_DOUBLE) \
02201 ET(ET_STRING) \
02202 ET(ET_SEQUENCE) // See SequenceType.
02203
02204 enum ElementaryType {
02205 #define FLATBUFFERS_ET(E) E,
02206 FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
02207 #undef FLATBUFFERS_ET
02208 };
02209
02210 inline const char * const *ElementaryTypeNames() {
02211 static const char * const names[] = {
02212 #define FLATBUFFERS_ET(E) #E,
02213 FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
02214 #undef FLATBUFFERS_ET
02215 };
02216 return names;
02217 }
02218
02219
02220
02221 struct TypeCode {
02222 uint16_t base_type : 4;
02223 uint16_t is_vector : 1;
02224 int16_t sequence_ref : 11;
02225 };
02226
02227 static_assert(sizeof(TypeCode) == 2, "TypeCode");
02228
02229 struct TypeTable;
02230
02231
02232 typedef const TypeTable *(*TypeFunction)();
02233
02234 struct TypeTable {
02235 SequenceType st;
02236 size_t num_elems;
02237 const TypeCode *type_codes;
02238 const TypeFunction *type_refs;
02239 const int32_t *values;
02240 const char * const *names;
02241 };
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251
02252
02253
02254 #if !defined(_WIN32) && !defined(__CYGWIN__)
02255
02256 extern volatile __attribute__((weak)) const char *flatbuffer_version_string;
02257 volatile __attribute__((weak)) const char *flatbuffer_version_string =
02258 "FlatBuffers "
02259 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
02260 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
02261 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
02262
02263 #endif // !defined(_WIN32) && !defined(__CYGWIN__)
02264
02265 #define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\
02266 inline E operator | (E lhs, E rhs){\
02267 return E(T(lhs) | T(rhs));\
02268 }\
02269 inline E operator & (E lhs, E rhs){\
02270 return E(T(lhs) & T(rhs));\
02271 }\
02272 inline E operator ^ (E lhs, E rhs){\
02273 return E(T(lhs) ^ T(rhs));\
02274 }\
02275 inline E operator ~ (E lhs){\
02276 return E(~T(lhs));\
02277 }\
02278 inline E operator |= (E &lhs, E rhs){\
02279 lhs = lhs | rhs;\
02280 return lhs;\
02281 }\
02282 inline E operator &= (E &lhs, E rhs){\
02283 lhs = lhs & rhs;\
02284 return lhs;\
02285 }\
02286 inline E operator ^= (E &lhs, E rhs){\
02287 lhs = lhs ^ rhs;\
02288 return lhs;\
02289 }\
02290 inline bool operator !(E rhs) \
02291 {\
02292 return !bool(T(rhs)); \
02293 }
02294
02295 }
02296
02297 #if defined(_MSC_VER)
02298 #pragma warning(pop)
02299 #endif
02300
02301
02302 #endif // FLATBUFFERS_H_