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 #if defined(FLATBUFFERS_NAN_DEFAULTS)
00023 #include <cmath>
00024 #endif
00025
00026 namespace flatbuffers {
00027
00028 template<typename T> inline bool IsTheSameAs(T e, T def) { return e == def; }
00029
00030 #if defined(FLATBUFFERS_NAN_DEFAULTS) && \
00031 (!defined(_MSC_VER) || _MSC_VER >= 1800)
00032
00033 template<> inline bool IsTheSameAs<float>(float e, float def) {
00034 return (e == def) || (std::isnan(def) && std::isnan(e));
00035 }
00036 template<> inline bool IsTheSameAs<double>(double e, double def) {
00037 return (e == def) || (std::isnan(def) && std::isnan(e));
00038 }
00039 #endif
00040
00041
00042
00043 template<typename T> struct Offset {
00044 uoffset_t o;
00045 Offset() : o(0) {}
00046 Offset(uoffset_t _o) : o(_o) {}
00047 Offset<void> Union() const { return Offset<void>(o); }
00048 bool IsNull() const { return !o; }
00049 };
00050
00051 inline void EndianCheck() {
00052 int endiantest = 1;
00053
00054 FLATBUFFERS_ASSERT(*reinterpret_cast<char *>(&endiantest) ==
00055 FLATBUFFERS_LITTLEENDIAN);
00056 (void)endiantest;
00057 }
00058
00059 template<typename T> FLATBUFFERS_CONSTEXPR size_t AlignOf() {
00060
00061 #ifdef _MSC_VER
00062 return __alignof(T);
00063 #else
00064 #ifndef alignof
00065 return __alignof__(T);
00066 #else
00067 return alignof(T);
00068 #endif
00069 #endif
00070
00071 }
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 template<typename T> struct IndirectHelper {
00082 typedef T return_type;
00083 typedef T mutable_return_type;
00084 static const size_t element_stride = sizeof(T);
00085 static return_type Read(const uint8_t *p, uoffset_t i) {
00086 return EndianScalar((reinterpret_cast<const T *>(p))[i]);
00087 }
00088 };
00089 template<typename T> struct IndirectHelper<Offset<T>> {
00090 typedef const T *return_type;
00091 typedef T *mutable_return_type;
00092 static const size_t element_stride = sizeof(uoffset_t);
00093 static return_type Read(const uint8_t *p, uoffset_t i) {
00094 p += i * sizeof(uoffset_t);
00095 return reinterpret_cast<return_type>(p + ReadScalar<uoffset_t>(p));
00096 }
00097 };
00098 template<typename T> struct IndirectHelper<const T *> {
00099 typedef const T *return_type;
00100 typedef T *mutable_return_type;
00101 static const size_t element_stride = sizeof(T);
00102 static return_type Read(const uint8_t *p, uoffset_t i) {
00103 return reinterpret_cast<const T *>(p + i * sizeof(T));
00104 }
00105 };
00106
00107
00108
00109 template<typename T, typename IT> struct VectorIterator {
00110 typedef std::random_access_iterator_tag iterator_category;
00111 typedef IT value_type;
00112 typedef ptrdiff_t difference_type;
00113 typedef IT *pointer;
00114 typedef IT &reference;
00115
00116 VectorIterator(const uint8_t *data, uoffset_t i)
00117 : data_(data + IndirectHelper<T>::element_stride * i) {}
00118 VectorIterator(const VectorIterator &other) : data_(other.data_) {}
00119 VectorIterator() : data_(nullptr) {}
00120
00121 VectorIterator &operator=(const VectorIterator &other) {
00122 data_ = other.data_;
00123 return *this;
00124 }
00125
00126
00127 #if !defined(FLATBUFFERS_CPP98_STL)
00128 VectorIterator &operator=(VectorIterator &&other) {
00129 data_ = other.data_;
00130 return *this;
00131 }
00132 #endif // !defined(FLATBUFFERS_CPP98_STL)
00133
00134
00135 bool operator==(const VectorIterator &other) const {
00136 return data_ == other.data_;
00137 }
00138
00139 bool operator<(const VectorIterator &other) const {
00140 return data_ < other.data_;
00141 }
00142
00143 bool operator!=(const VectorIterator &other) const {
00144 return data_ != other.data_;
00145 }
00146
00147 difference_type operator-(const VectorIterator &other) const {
00148 return (data_ - other.data_) / IndirectHelper<T>::element_stride;
00149 }
00150
00151 IT operator*() const { return IndirectHelper<T>::Read(data_, 0); }
00152
00153 IT operator->() const { return IndirectHelper<T>::Read(data_, 0); }
00154
00155 VectorIterator &operator++() {
00156 data_ += IndirectHelper<T>::element_stride;
00157 return *this;
00158 }
00159
00160 VectorIterator operator++(int) {
00161 VectorIterator temp(data_, 0);
00162 data_ += IndirectHelper<T>::element_stride;
00163 return temp;
00164 }
00165
00166 VectorIterator operator+(const uoffset_t &offset) const {
00167 return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride,
00168 0);
00169 }
00170
00171 VectorIterator &operator+=(const uoffset_t &offset) {
00172 data_ += offset * IndirectHelper<T>::element_stride;
00173 return *this;
00174 }
00175
00176 VectorIterator &operator--() {
00177 data_ -= IndirectHelper<T>::element_stride;
00178 return *this;
00179 }
00180
00181 VectorIterator operator--(int) {
00182 VectorIterator temp(data_, 0);
00183 data_ -= IndirectHelper<T>::element_stride;
00184 return temp;
00185 }
00186
00187 VectorIterator operator-(const uoffset_t &offset) const {
00188 return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride,
00189 0);
00190 }
00191
00192 VectorIterator &operator-=(const uoffset_t &offset) {
00193 data_ -= offset * IndirectHelper<T>::element_stride;
00194 return *this;
00195 }
00196
00197 private:
00198 const uint8_t *data_;
00199 };
00200
00201 template<typename Iterator> struct VectorReverseIterator :
00202 public std::reverse_iterator<Iterator> {
00203
00204 explicit VectorReverseIterator(Iterator iter) : iter_(iter) {}
00205
00206 typename Iterator::value_type operator*() const { return *(iter_ - 1); }
00207
00208 typename Iterator::value_type operator->() const { return *(iter_ - 1); }
00209
00210 private:
00211 Iterator iter_;
00212 };
00213
00214 struct String;
00215
00216
00217
00218 template<typename T> class Vector {
00219 public:
00220 typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
00221 iterator;
00222 typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
00223 const_iterator;
00224 typedef VectorReverseIterator<iterator> reverse_iterator;
00225 typedef VectorReverseIterator<const_iterator> const_reverse_iterator;
00226
00227 uoffset_t size() const { return EndianScalar(length_); }
00228
00229
00230 FLATBUFFERS_ATTRIBUTE(deprecated("use size() instead"))
00231 uoffset_t Length() const { return size(); }
00232
00233 typedef typename IndirectHelper<T>::return_type return_type;
00234 typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
00235
00236 return_type Get(uoffset_t i) const {
00237 FLATBUFFERS_ASSERT(i < size());
00238 return IndirectHelper<T>::Read(Data(), i);
00239 }
00240
00241 return_type operator[](uoffset_t i) const { return Get(i); }
00242
00243
00244
00245
00246 template<typename E> E GetEnum(uoffset_t i) const {
00247 return static_cast<E>(Get(i));
00248 }
00249
00250
00251
00252 template<typename U> const U *GetAs(uoffset_t i) const {
00253 return reinterpret_cast<const U *>(Get(i));
00254 }
00255
00256
00257
00258 const String *GetAsString(uoffset_t i) const {
00259 return reinterpret_cast<const String *>(Get(i));
00260 }
00261
00262 const void *GetStructFromOffset(size_t o) const {
00263 return reinterpret_cast<const void *>(Data() + o);
00264 }
00265
00266 iterator begin() { return iterator(Data(), 0); }
00267 const_iterator begin() const { return const_iterator(Data(), 0); }
00268
00269 iterator end() { return iterator(Data(), size()); }
00270 const_iterator end() const { return const_iterator(Data(), size()); }
00271
00272 reverse_iterator rbegin() { return reverse_iterator(end()); }
00273 const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); }
00274
00275 reverse_iterator rend() { return reverse_iterator(end()); }
00276 const_reverse_iterator rend() const { return const_reverse_iterator(end()); }
00277
00278 const_iterator cbegin() const { return begin(); }
00279
00280 const_iterator cend() const { return end(); }
00281
00282 const_reverse_iterator crbegin() const { return rbegin(); }
00283
00284 const_reverse_iterator crend() const { return rend(); }
00285
00286
00287
00288 void Mutate(uoffset_t i, const T &val) {
00289 FLATBUFFERS_ASSERT(i < size());
00290 WriteScalar(data() + i, val);
00291 }
00292
00293
00294
00295
00296 void MutateOffset(uoffset_t i, const uint8_t *val) {
00297 FLATBUFFERS_ASSERT(i < size());
00298 static_assert(sizeof(T) == sizeof(uoffset_t), "Unrelated types");
00299 WriteScalar(data() + i,
00300 static_cast<uoffset_t>(val - (Data() + i * sizeof(uoffset_t))));
00301 }
00302
00303
00304 mutable_return_type GetMutableObject(uoffset_t i) const {
00305 FLATBUFFERS_ASSERT(i < size());
00306 return const_cast<mutable_return_type>(IndirectHelper<T>::Read(Data(), i));
00307 }
00308
00309
00310 const uint8_t *Data() const {
00311 return reinterpret_cast<const uint8_t *>(&length_ + 1);
00312 }
00313
00314 uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
00315
00316
00317 const T *data() const { return reinterpret_cast<const T *>(Data()); }
00318 T *data() { return reinterpret_cast<T *>(Data()); }
00319
00320 template<typename K> return_type LookupByKey(K key) const {
00321 void *search_result = std::bsearch(
00322 &key, Data(), size(), IndirectHelper<T>::element_stride, KeyCompare<K>);
00323
00324 if (!search_result) {
00325 return nullptr;
00326 }
00327
00328 const uint8_t *element = reinterpret_cast<const uint8_t *>(search_result);
00329
00330 return IndirectHelper<T>::Read(element, 0);
00331 }
00332
00333 protected:
00334
00335
00336 Vector();
00337
00338 uoffset_t length_;
00339
00340 private:
00341
00342
00343 Vector(const Vector &);
00344
00345 template<typename K> static int KeyCompare(const void *ap, const void *bp) {
00346 const K *key = reinterpret_cast<const K *>(ap);
00347 const uint8_t *data = reinterpret_cast<const uint8_t *>(bp);
00348 auto table = IndirectHelper<T>::Read(data, 0);
00349
00350
00351
00352 return -table->KeyCompareWithValue(*key);
00353 }
00354 };
00355
00356
00357
00358 class VectorOfAny {
00359 public:
00360 uoffset_t size() const { return EndianScalar(length_); }
00361
00362 const uint8_t *Data() const {
00363 return reinterpret_cast<const uint8_t *>(&length_ + 1);
00364 }
00365 uint8_t *Data() { return reinterpret_cast<uint8_t *>(&length_ + 1); }
00366
00367 protected:
00368 VectorOfAny();
00369
00370 uoffset_t length_;
00371
00372 private:
00373 VectorOfAny(const VectorOfAny &);
00374 };
00375
00376 #ifndef FLATBUFFERS_CPP98_STL
00377 template<typename T, typename U>
00378 Vector<Offset<T>> *VectorCast(Vector<Offset<U>> *ptr) {
00379 static_assert(std::is_base_of<T, U>::value, "Unrelated types");
00380 return reinterpret_cast<Vector<Offset<T>> *>(ptr);
00381 }
00382
00383 template<typename T, typename U>
00384 const Vector<Offset<T>> *VectorCast(const Vector<Offset<U>> *ptr) {
00385 static_assert(std::is_base_of<T, U>::value, "Unrelated types");
00386 return reinterpret_cast<const Vector<Offset<T>> *>(ptr);
00387 }
00388 #endif
00389
00390
00391
00392 template<typename T> static inline size_t VectorLength(const Vector<T> *v) {
00393 return v ? v->size() : 0;
00394 }
00395
00396
00397
00398 static inline bool StringLessThan(const char *a_data, uoffset_t a_size,
00399 const char *b_data, uoffset_t b_size) {
00400 const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size));
00401 return cmp == 0 ? a_size < b_size : cmp < 0;
00402 }
00403
00404 struct String : public Vector<char> {
00405 const char *c_str() const { return reinterpret_cast<const char *>(Data()); }
00406 std::string str() const { return std::string(c_str(), size()); }
00407
00408
00409 #ifdef FLATBUFFERS_HAS_STRING_VIEW
00410 flatbuffers::string_view string_view() const {
00411 return flatbuffers::string_view(c_str(), size());
00412 }
00413 #endif // FLATBUFFERS_HAS_STRING_VIEW
00414
00415
00416 bool operator<(const String &o) const {
00417 return StringLessThan(this->data(), this->size(), o.data(), o.size());
00418 }
00419 };
00420
00421
00422
00423 static inline std::string GetString(const String * str) {
00424 return str ? str->str() : "";
00425 }
00426
00427
00428
00429 static inline const char * GetCstring(const String * str) {
00430 return str ? str->c_str() : "";
00431 }
00432
00433
00434
00435 class Allocator {
00436 public:
00437 virtual ~Allocator() {}
00438
00439
00440 virtual uint8_t *allocate(size_t size) = 0;
00441
00442
00443 virtual void deallocate(uint8_t *p, size_t size) = 0;
00444
00445
00446
00447
00448
00449
00450 virtual uint8_t *reallocate_downward(uint8_t *old_p, size_t old_size,
00451 size_t new_size, size_t in_use_back,
00452 size_t in_use_front) {
00453 FLATBUFFERS_ASSERT(new_size > old_size);
00454 uint8_t *new_p = allocate(new_size);
00455 memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
00456 in_use_front);
00457 deallocate(old_p, old_size);
00458 return new_p;
00459 }
00460
00461 protected:
00462
00463
00464
00465
00466 void memcpy_downward(uint8_t *old_p, size_t old_size,
00467 uint8_t *new_p, size_t new_size,
00468 size_t in_use_back, size_t in_use_front) {
00469 memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back,
00470 in_use_back);
00471 memcpy(new_p, old_p, in_use_front);
00472 }
00473 };
00474
00475
00476 class DefaultAllocator : public Allocator {
00477 public:
00478 uint8_t *allocate(size_t size) FLATBUFFERS_OVERRIDE {
00479 return new uint8_t[size];
00480 }
00481
00482 void deallocate(uint8_t *p, size_t) FLATBUFFERS_OVERRIDE {
00483 delete[] p;
00484 }
00485
00486 static void dealloc(void *p, size_t) {
00487 delete[] static_cast<uint8_t *>(p);
00488 }
00489 };
00490
00491
00492
00493
00494
00495 inline uint8_t *Allocate(Allocator *allocator, size_t size) {
00496 return allocator ? allocator->allocate(size)
00497 : DefaultAllocator().allocate(size);
00498 }
00499
00500 inline void Deallocate(Allocator *allocator, uint8_t *p, size_t size) {
00501 if (allocator) allocator->deallocate(p, size);
00502 else DefaultAllocator().deallocate(p, size);
00503 }
00504
00505 inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p,
00506 size_t old_size, size_t new_size,
00507 size_t in_use_back, size_t in_use_front) {
00508 return allocator
00509 ? allocator->reallocate_downward(old_p, old_size, new_size,
00510 in_use_back, in_use_front)
00511 : DefaultAllocator().reallocate_downward(old_p, old_size, new_size,
00512 in_use_back, in_use_front);
00513 }
00514
00515
00516
00517
00518 class DetachedBuffer {
00519 public:
00520 DetachedBuffer()
00521 : allocator_(nullptr),
00522 own_allocator_(false),
00523 buf_(nullptr),
00524 reserved_(0),
00525 cur_(nullptr),
00526 size_(0) {}
00527
00528 DetachedBuffer(Allocator *allocator, bool own_allocator, uint8_t *buf,
00529 size_t reserved, uint8_t *cur, size_t sz)
00530 : allocator_(allocator),
00531 own_allocator_(own_allocator),
00532 buf_(buf),
00533 reserved_(reserved),
00534 cur_(cur),
00535 size_(sz) {}
00536
00537
00538 #if !defined(FLATBUFFERS_CPP98_STL)
00539
00540 DetachedBuffer(DetachedBuffer &&other)
00541 : allocator_(other.allocator_),
00542 own_allocator_(other.own_allocator_),
00543 buf_(other.buf_),
00544 reserved_(other.reserved_),
00545 cur_(other.cur_),
00546 size_(other.size_) {
00547 other.reset();
00548 }
00549
00550 #endif // !defined(FLATBUFFERS_CPP98_STL)
00551
00552
00553
00554 #if !defined(FLATBUFFERS_CPP98_STL)
00555
00556 DetachedBuffer &operator=(DetachedBuffer &&other) {
00557 destroy();
00558
00559 allocator_ = other.allocator_;
00560 own_allocator_ = other.own_allocator_;
00561 buf_ = other.buf_;
00562 reserved_ = other.reserved_;
00563 cur_ = other.cur_;
00564 size_ = other.size_;
00565
00566 other.reset();
00567
00568 return *this;
00569 }
00570
00571 #endif // !defined(FLATBUFFERS_CPP98_STL)
00572
00573
00574 ~DetachedBuffer() { destroy(); }
00575
00576 const uint8_t *data() const { return cur_; }
00577
00578 uint8_t *data() { return cur_; }
00579
00580 size_t size() const { return size_; }
00581
00582
00583 #if 0 // disabled for now due to the ordering of classes in this header
00584 template <class T>
00585 bool Verify() const {
00586 Verifier verifier(data(), size());
00587 return verifier.Verify<T>(nullptr);
00588 }
00589
00590 template <class T>
00591 const T* GetRoot() const {
00592 return flatbuffers::GetRoot<T>(data());
00593 }
00594
00595 template <class T>
00596 T* GetRoot() {
00597 return flatbuffers::GetRoot<T>(data());
00598 }
00599 #endif
00600
00601
00602
00603 #if !defined(FLATBUFFERS_CPP98_STL)
00604
00605
00606 FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other))
00607 FLATBUFFERS_DELETE_FUNC(
00608 DetachedBuffer &operator=(const DetachedBuffer &other))
00609
00610 #endif // !defined(FLATBUFFERS_CPP98_STL)
00611
00612
00613 protected:
00614 Allocator *allocator_;
00615 bool own_allocator_;
00616 uint8_t *buf_;
00617 size_t reserved_;
00618 uint8_t *cur_;
00619 size_t size_;
00620
00621 inline void destroy() {
00622 if (buf_) Deallocate(allocator_, buf_, reserved_);
00623 if (own_allocator_ && allocator_) { delete allocator_; }
00624 reset();
00625 }
00626
00627 inline void reset() {
00628 allocator_ = nullptr;
00629 own_allocator_ = false;
00630 buf_ = nullptr;
00631 reserved_ = 0;
00632 cur_ = nullptr;
00633 size_ = 0;
00634 }
00635 };
00636
00637
00638
00639
00640
00641
00642
00643 class vector_downward {
00644 public:
00645 explicit vector_downward(size_t initial_size,
00646 Allocator *allocator,
00647 bool own_allocator,
00648 size_t buffer_minalign)
00649 : allocator_(allocator),
00650 own_allocator_(own_allocator),
00651 initial_size_(initial_size),
00652 buffer_minalign_(buffer_minalign),
00653 reserved_(0),
00654 buf_(nullptr),
00655 cur_(nullptr),
00656 scratch_(nullptr) {}
00657
00658
00659 #if !defined(FLATBUFFERS_CPP98_STL)
00660 vector_downward(vector_downward &&other)
00661 #else
00662 vector_downward(vector_downward &other)
00663 #endif // defined(FLATBUFFERS_CPP98_STL)
00664
00665 : allocator_(other.allocator_),
00666 own_allocator_(other.own_allocator_),
00667 initial_size_(other.initial_size_),
00668 buffer_minalign_(other.buffer_minalign_),
00669 reserved_(other.reserved_),
00670 buf_(other.buf_),
00671 cur_(other.cur_),
00672 scratch_(other.scratch_) {
00673
00674
00675
00676 other.own_allocator_ = false;
00677 other.reserved_ = 0;
00678 other.buf_ = nullptr;
00679 other.cur_ = nullptr;
00680 other.scratch_ = nullptr;
00681 }
00682
00683
00684 #if !defined(FLATBUFFERS_CPP98_STL)
00685
00686 vector_downward &operator=(vector_downward &&other) {
00687
00688 vector_downward temp(std::move(other));
00689 swap(temp);
00690 return *this;
00691 }
00692
00693 #endif // defined(FLATBUFFERS_CPP98_STL)
00694
00695
00696 ~vector_downward() {
00697 clear_buffer();
00698 clear_allocator();
00699 }
00700
00701 void reset() {
00702 clear_buffer();
00703 clear();
00704 }
00705
00706 void clear() {
00707 if (buf_) {
00708 cur_ = buf_ + reserved_;
00709 } else {
00710 reserved_ = 0;
00711 cur_ = nullptr;
00712 }
00713 clear_scratch();
00714 }
00715
00716 void clear_scratch() {
00717 scratch_ = buf_;
00718 }
00719
00720 void clear_allocator() {
00721 if (own_allocator_ && allocator_) { delete allocator_; }
00722 allocator_ = nullptr;
00723 own_allocator_ = false;
00724 }
00725
00726 void clear_buffer() {
00727 if (buf_) Deallocate(allocator_, buf_, reserved_);
00728 buf_ = nullptr;
00729 }
00730
00731
00732 uint8_t *release_raw(size_t &allocated_bytes, size_t &offset) {
00733 auto *buf = buf_;
00734 allocated_bytes = reserved_;
00735 offset = static_cast<size_t>(cur_ - buf_);
00736
00737
00738
00739 buf_ = nullptr;
00740 clear();
00741 return buf;
00742 }
00743
00744
00745 DetachedBuffer release() {
00746
00747 DetachedBuffer fb(allocator_, own_allocator_, buf_, reserved_, cur_,
00748 size());
00749 if (own_allocator_) {
00750 allocator_ = nullptr;
00751 own_allocator_ = false;
00752 }
00753 buf_ = nullptr;
00754 clear();
00755 return fb;
00756 }
00757
00758 size_t ensure_space(size_t len) {
00759 FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_);
00760 if (len > static_cast<size_t>(cur_ - scratch_)) { reallocate(len); }
00761
00762
00763 FLATBUFFERS_ASSERT(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
00764 return len;
00765 }
00766
00767 inline uint8_t *make_space(size_t len) {
00768 size_t space = ensure_space(len);
00769 cur_ -= space;
00770 return cur_;
00771 }
00772
00773
00774 Allocator *get_custom_allocator() { return allocator_; }
00775
00776 uoffset_t size() const {
00777 return static_cast<uoffset_t>(reserved_ - (cur_ - buf_));
00778 }
00779
00780 uoffset_t scratch_size() const {
00781 return static_cast<uoffset_t>(scratch_ - buf_);
00782 }
00783
00784 size_t capacity() const { return reserved_; }
00785
00786 uint8_t *data() const {
00787 FLATBUFFERS_ASSERT(cur_);
00788 return cur_;
00789 }
00790
00791 uint8_t *scratch_data() const {
00792 FLATBUFFERS_ASSERT(buf_);
00793 return buf_;
00794 }
00795
00796 uint8_t *scratch_end() const {
00797 FLATBUFFERS_ASSERT(scratch_);
00798 return scratch_;
00799 }
00800
00801 uint8_t *data_at(size_t offset) const { return buf_ + reserved_ - offset; }
00802
00803 void push(const uint8_t *bytes, size_t num) {
00804 memcpy(make_space(num), bytes, num);
00805 }
00806
00807
00808 template<typename T> void push_small(const T &little_endian_t) {
00809 make_space(sizeof(T));
00810 *reinterpret_cast<T *>(cur_) = little_endian_t;
00811 }
00812
00813 template<typename T> void scratch_push_small(const T &t) {
00814 ensure_space(sizeof(T));
00815 *reinterpret_cast<T *>(scratch_) = t;
00816 scratch_ += sizeof(T);
00817 }
00818
00819
00820
00821 void fill(size_t zero_pad_bytes) {
00822 make_space(zero_pad_bytes);
00823 for (size_t i = 0; i < zero_pad_bytes; i++) cur_[i] = 0;
00824 }
00825
00826
00827 void fill_big(size_t zero_pad_bytes) {
00828 memset(make_space(zero_pad_bytes), 0, zero_pad_bytes);
00829 }
00830
00831 void pop(size_t bytes_to_remove) { cur_ += bytes_to_remove; }
00832 void scratch_pop(size_t bytes_to_remove) { scratch_ -= bytes_to_remove; }
00833
00834 void swap(vector_downward &other) {
00835 using std::swap;
00836 swap(allocator_, other.allocator_);
00837 swap(own_allocator_, other.own_allocator_);
00838 swap(initial_size_, other.initial_size_);
00839 swap(buffer_minalign_, other.buffer_minalign_);
00840 swap(reserved_, other.reserved_);
00841 swap(buf_, other.buf_);
00842 swap(cur_, other.cur_);
00843 swap(scratch_, other.scratch_);
00844 }
00845
00846 void swap_allocator(vector_downward &other) {
00847 using std::swap;
00848 swap(allocator_, other.allocator_);
00849 swap(own_allocator_, other.own_allocator_);
00850 }
00851
00852 private:
00853
00854 FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward &))
00855 FLATBUFFERS_DELETE_FUNC(vector_downward &operator=(const vector_downward &))
00856
00857 Allocator *allocator_;
00858 bool own_allocator_;
00859 size_t initial_size_;
00860 size_t buffer_minalign_;
00861 size_t reserved_;
00862 uint8_t *buf_;
00863 uint8_t *cur_;
00864 uint8_t *scratch_;
00865
00866 void reallocate(size_t len) {
00867 auto old_reserved = reserved_;
00868 auto old_size = size();
00869 auto old_scratch_size = scratch_size();
00870 reserved_ += (std::max)(len,
00871 old_reserved ? old_reserved / 2 : initial_size_);
00872 reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1);
00873 if (buf_) {
00874 buf_ = ReallocateDownward(allocator_, buf_, old_reserved, reserved_,
00875 old_size, old_scratch_size);
00876 } else {
00877 buf_ = Allocate(allocator_, reserved_);
00878 }
00879 cur_ = buf_ + reserved_ - old_size;
00880 scratch_ = buf_ + old_scratch_size;
00881 }
00882 };
00883
00884
00885 inline voffset_t FieldIndexToOffset(voffset_t field_id) {
00886
00887 const int fixed_fields = 2;
00888 return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t));
00889 }
00890
00891 template<typename T, typename Alloc>
00892 const T *data(const std::vector<T, Alloc> &v) {
00893 return v.empty() ? nullptr : &v.front();
00894 }
00895 template<typename T, typename Alloc> T *data(std::vector<T, Alloc> &v) {
00896 return v.empty() ? nullptr : &v.front();
00897 }
00898
00900
00910 class FlatBufferBuilder {
00911 public:
00923 explicit FlatBufferBuilder(size_t initial_size = 1024,
00924 Allocator *allocator = nullptr,
00925 bool own_allocator = false,
00926 size_t buffer_minalign =
00927 AlignOf<largest_scalar_t>())
00928 : buf_(initial_size, allocator, own_allocator, buffer_minalign),
00929 num_field_loc(0),
00930 max_voffset_(0),
00931 nested(false),
00932 finished(false),
00933 minalign_(1),
00934 force_defaults_(false),
00935 dedup_vtables_(true),
00936 string_pool(nullptr) {
00937 EndianCheck();
00938 }
00939
00940
00942 #if !defined(FLATBUFFERS_CPP98_STL)
00943 FlatBufferBuilder(FlatBufferBuilder &&other)
00944 #else
00945 FlatBufferBuilder(FlatBufferBuilder &other)
00946 #endif // #if !defined(FLATBUFFERS_CPP98_STL)
00947 : buf_(1024, nullptr, false, AlignOf<largest_scalar_t>()),
00948 num_field_loc(0),
00949 max_voffset_(0),
00950 nested(false),
00951 finished(false),
00952 minalign_(1),
00953 force_defaults_(false),
00954 dedup_vtables_(true),
00955 string_pool(nullptr) {
00956 EndianCheck();
00957
00958
00959 Swap(other);
00960 }
00961
00962
00963
00964 #if !defined(FLATBUFFERS_CPP98_STL)
00965
00967 FlatBufferBuilder &operator=(FlatBufferBuilder &&other) {
00968
00969 FlatBufferBuilder temp(std::move(other));
00970 Swap(temp);
00971 return *this;
00972 }
00973
00974 #endif // defined(FLATBUFFERS_CPP98_STL)
00975
00976
00977 void Swap(FlatBufferBuilder &other) {
00978 using std::swap;
00979 buf_.swap(other.buf_);
00980 swap(num_field_loc, other.num_field_loc);
00981 swap(max_voffset_, other.max_voffset_);
00982 swap(nested, other.nested);
00983 swap(finished, other.finished);
00984 swap(minalign_, other.minalign_);
00985 swap(force_defaults_, other.force_defaults_);
00986 swap(dedup_vtables_, other.dedup_vtables_);
00987 swap(string_pool, other.string_pool);
00988 }
00989
00990 ~FlatBufferBuilder() {
00991 if (string_pool) delete string_pool;
00992 }
00993
00994 void Reset() {
00995 Clear();
00996 buf_.reset();
00997 }
00998
01001 void Clear() {
01002 ClearOffsets();
01003 buf_.clear();
01004 nested = false;
01005 finished = false;
01006 minalign_ = 1;
01007 if (string_pool) string_pool->clear();
01008 }
01009
01012 uoffset_t GetSize() const { return buf_.size(); }
01013
01017 uint8_t *GetBufferPointer() const {
01018 Finished();
01019 return buf_.data();
01020 }
01021
01024 uint8_t *GetCurrentBufferPointer() const { return buf_.data(); }
01025
01030 FLATBUFFERS_ATTRIBUTE(deprecated("use Release() instead")) DetachedBuffer
01031 ReleaseBufferPointer() {
01032 Finished();
01033 return buf_.release();
01034 }
01035
01038 DetachedBuffer Release() {
01039 Finished();
01040 return buf_.release();
01041 }
01042
01051 uint8_t *ReleaseRaw(size_t &size, size_t &offset) {
01052 Finished();
01053 return buf_.release_raw(size, offset);
01054 }
01055
01061 size_t GetBufferMinAlignment() {
01062 Finished();
01063 return minalign_;
01064 }
01065
01067 void Finished() const {
01068
01069
01070
01071
01072
01073 FLATBUFFERS_ASSERT(finished);
01074 }
01076
01081 void ForceDefaults(bool fd) { force_defaults_ = fd; }
01082
01085 void DedupVtables(bool dedup) { dedup_vtables_ = dedup; }
01086
01088 void Pad(size_t num_bytes) { buf_.fill(num_bytes); }
01089
01090 void TrackMinAlign(size_t elem_size) {
01091 if (elem_size > minalign_) minalign_ = elem_size;
01092 }
01093
01094 void Align(size_t elem_size) {
01095 TrackMinAlign(elem_size);
01096 buf_.fill(PaddingBytes(buf_.size(), elem_size));
01097 }
01098
01099 void PushFlatBuffer(const uint8_t *bytes, size_t size) {
01100 PushBytes(bytes, size);
01101 finished = true;
01102 }
01103
01104 void PushBytes(const uint8_t *bytes, size_t size) { buf_.push(bytes, size); }
01105
01106 void PopBytes(size_t amount) { buf_.pop(amount); }
01107
01108 template<typename T> void AssertScalarT() {
01109
01110 static_assert(flatbuffers::is_scalar<T>::value, "T must be a scalar type");
01111 }
01112
01113
01114 template<typename T> uoffset_t PushElement(T element) {
01115 AssertScalarT<T>();
01116 T litle_endian_element = EndianScalar(element);
01117 Align(sizeof(T));
01118 buf_.push_small(litle_endian_element);
01119 return GetSize();
01120 }
01121
01122 template<typename T> uoffset_t PushElement(Offset<T> off) {
01123
01124 return PushElement(ReferTo(off.o));
01125 }
01126
01127
01128
01129 void TrackField(voffset_t field, uoffset_t off) {
01130 FieldLoc fl = { off, field };
01131 buf_.scratch_push_small(fl);
01132 num_field_loc++;
01133 max_voffset_ = (std::max)(max_voffset_, field);
01134 }
01135
01136
01137 template<typename T> void AddElement(voffset_t field, T e, T def) {
01138
01139 if (IsTheSameAs(e, def) && !force_defaults_) return;
01140 auto off = PushElement(e);
01141 TrackField(field, off);
01142 }
01143
01144 template<typename T> void AddOffset(voffset_t field, Offset<T> off) {
01145 if (off.IsNull()) return;
01146 AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
01147 }
01148
01149 template<typename T> void AddStruct(voffset_t field, const T *structptr) {
01150 if (!structptr) return;
01151 Align(AlignOf<T>());
01152 buf_.push_small(*structptr);
01153 TrackField(field, GetSize());
01154 }
01155
01156 void AddStructOffset(voffset_t field, uoffset_t off) {
01157 TrackField(field, off);
01158 }
01159
01160
01161
01162
01163 uoffset_t ReferTo(uoffset_t off) {
01164
01165 Align(sizeof(uoffset_t));
01166
01167 FLATBUFFERS_ASSERT(off && off <= GetSize());
01168 return GetSize() - off + static_cast<uoffset_t>(sizeof(uoffset_t));
01169 }
01170
01171 void NotNested() {
01172
01173
01174
01175
01176
01177
01178
01179
01180 FLATBUFFERS_ASSERT(!nested);
01181
01182 FLATBUFFERS_ASSERT(!num_field_loc);
01183 }
01184
01185
01186
01187 uoffset_t StartTable() {
01188 NotNested();
01189 nested = true;
01190 return GetSize();
01191 }
01192
01193
01194
01195
01196 uoffset_t EndTable(uoffset_t start) {
01197
01198 FLATBUFFERS_ASSERT(nested);
01199
01200
01201 auto vtableoffsetloc = PushElement<soffset_t>(0);
01202
01203
01204
01205
01206
01207 max_voffset_ =
01208 (std::max)(static_cast<voffset_t>(max_voffset_ + sizeof(voffset_t)),
01209 FieldIndexToOffset(0));
01210 buf_.fill_big(max_voffset_);
01211 auto table_object_size = vtableoffsetloc - start;
01212
01213 FLATBUFFERS_ASSERT(table_object_size < 0x10000);
01214 WriteScalar<voffset_t>(buf_.data() + sizeof(voffset_t),
01215 static_cast<voffset_t>(table_object_size));
01216 WriteScalar<voffset_t>(buf_.data(), max_voffset_);
01217
01218 for (auto it = buf_.scratch_end() - num_field_loc * sizeof(FieldLoc);
01219 it < buf_.scratch_end(); it += sizeof(FieldLoc)) {
01220 auto field_location = reinterpret_cast<FieldLoc *>(it);
01221 auto pos = static_cast<voffset_t>(vtableoffsetloc - field_location->off);
01222
01223 FLATBUFFERS_ASSERT(
01224 !ReadScalar<voffset_t>(buf_.data() + field_location->id));
01225 WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
01226 }
01227 ClearOffsets();
01228 auto vt1 = reinterpret_cast<voffset_t *>(buf_.data());
01229 auto vt1_size = ReadScalar<voffset_t>(vt1);
01230 auto vt_use = GetSize();
01231
01232
01233 if (dedup_vtables_) {
01234 for (auto it = buf_.scratch_data(); it < buf_.scratch_end();
01235 it += sizeof(uoffset_t)) {
01236 auto vt_offset_ptr = reinterpret_cast<uoffset_t *>(it);
01237 auto vt2 = reinterpret_cast<voffset_t *>(buf_.data_at(*vt_offset_ptr));
01238 auto vt2_size = *vt2;
01239 if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size)) continue;
01240 vt_use = *vt_offset_ptr;
01241 buf_.pop(GetSize() - vtableoffsetloc);
01242 break;
01243 }
01244 }
01245
01246 if (vt_use == GetSize()) { buf_.scratch_push_small(vt_use); }
01247
01248
01249
01250
01251
01252 WriteScalar(buf_.data_at(vtableoffsetloc),
01253 static_cast<soffset_t>(vt_use) -
01254 static_cast<soffset_t>(vtableoffsetloc));
01255
01256 nested = false;
01257 return vtableoffsetloc;
01258 }
01259
01260 FLATBUFFERS_ATTRIBUTE(deprecated("call the version above instead"))
01261 uoffset_t EndTable(uoffset_t start, voffset_t ) {
01262 return EndTable(start);
01263 }
01264
01265
01266
01267 template<typename T> void Required(Offset<T> table, voffset_t field);
01268
01269 uoffset_t StartStruct(size_t alignment) {
01270 Align(alignment);
01271 return GetSize();
01272 }
01273
01274 uoffset_t EndStruct() { return GetSize(); }
01275
01276 void ClearOffsets() {
01277 buf_.scratch_pop(num_field_loc * sizeof(FieldLoc));
01278 num_field_loc = 0;
01279 max_voffset_ = 0;
01280 }
01281
01282
01283
01284 void PreAlign(size_t len, size_t alignment) {
01285 TrackMinAlign(alignment);
01286 buf_.fill(PaddingBytes(GetSize() + len, alignment));
01287 }
01288 template<typename T> void PreAlign(size_t len) {
01289 AssertScalarT<T>();
01290 PreAlign(len, sizeof(T));
01291 }
01293
01298 Offset<String> CreateString(const char *str, size_t len) {
01299 NotNested();
01300 PreAlign<uoffset_t>(len + 1);
01301 buf_.fill(1);
01302 PushBytes(reinterpret_cast<const uint8_t *>(str), len);
01303 PushElement(static_cast<uoffset_t>(len));
01304 return Offset<String>(GetSize());
01305 }
01306
01310 Offset<String> CreateString(const char *str) {
01311 return CreateString(str, strlen(str));
01312 }
01313
01317 Offset<String> CreateString(char *str) {
01318 return CreateString(str, strlen(str));
01319 }
01320
01324 Offset<String> CreateString(const std::string &str) {
01325 return CreateString(str.c_str(), str.length());
01326 }
01327
01328
01329 #ifdef FLATBUFFERS_HAS_STRING_VIEW
01330
01331
01332
01333 Offset<String> CreateString(flatbuffers::string_view str) {
01334 return CreateString(str.data(), str.size());
01335 }
01336 #endif // FLATBUFFERS_HAS_STRING_VIEW
01337
01338
01342 Offset<String> CreateString(const String *str) {
01343 return str ? CreateString(str->c_str(), str->size()) : 0;
01344 }
01345
01350 template<typename T> Offset<String> CreateString(const T &str) {
01351 return CreateString(str.c_str(), str.length());
01352 }
01353
01360 Offset<String> CreateSharedString(const char *str, size_t len) {
01361 if (!string_pool)
01362 string_pool = new StringOffsetMap(StringOffsetCompare(buf_));
01363 auto size_before_string = buf_.size();
01364
01365
01366 auto off = CreateString(str, len);
01367 auto it = string_pool->find(off);
01368
01369 if (it != string_pool->end()) {
01370
01371 buf_.pop(buf_.size() - size_before_string);
01372 return *it;
01373 }
01374
01375 string_pool->insert(off);
01376 return off;
01377 }
01378
01384 Offset<String> CreateSharedString(const char *str) {
01385 return CreateSharedString(str, strlen(str));
01386 }
01387
01393 Offset<String> CreateSharedString(const std::string &str) {
01394 return CreateSharedString(str.c_str(), str.length());
01395 }
01396
01402 Offset<String> CreateSharedString(const String *str) {
01403 return CreateSharedString(str->c_str(), str->size());
01404 }
01405
01407 uoffset_t EndVector(size_t len) {
01408 FLATBUFFERS_ASSERT(nested);
01409 nested = false;
01410 return PushElement(static_cast<uoffset_t>(len));
01411 }
01412
01413 void StartVector(size_t len, size_t elemsize) {
01414 NotNested();
01415 nested = true;
01416 PreAlign<uoffset_t>(len * elemsize);
01417 PreAlign(len * elemsize, elemsize);
01418 }
01419
01420
01421
01422
01423
01424
01425 void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment) {
01426 PreAlign(len * elemsize, alignment);
01427 }
01428
01429
01430 void ForceStringAlignment(size_t len, size_t alignment) {
01431 PreAlign((len + 1) * sizeof(char), alignment);
01432 }
01433
01435
01443 template<typename T> Offset<Vector<T>> CreateVector(const T *v, size_t len) {
01444
01445
01446 AssertScalarT<T>();
01447 StartVector(len, sizeof(T));
01448
01449 #if FLATBUFFERS_LITTLEENDIAN
01450 PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T));
01451 #else
01452 if (sizeof(T) == 1) {
01453 PushBytes(reinterpret_cast<const uint8_t *>(v), len);
01454 } else {
01455 for (auto i = len; i > 0; ) {
01456 PushElement(v[--i]);
01457 }
01458 }
01459 #endif
01460
01461 return Offset<Vector<T>>(EndVector(len));
01462 }
01463
01464 template<typename T>
01465 Offset<Vector<Offset<T>>> CreateVector(const Offset<T> *v, size_t len) {
01466 StartVector(len, sizeof(Offset<T>));
01467 for (auto i = len; i > 0;) { PushElement(v[--i]); }
01468 return Offset<Vector<Offset<T>>>(EndVector(len));
01469 }
01470
01477 template<typename T> Offset<Vector<T>> CreateVector(const std::vector<T> &v) {
01478 return CreateVector(data(v), v.size());
01479 }
01480
01481
01482
01483
01484 Offset<Vector<uint8_t>> CreateVector(const std::vector<bool> &v) {
01485 StartVector(v.size(), sizeof(uint8_t));
01486 for (auto i = v.size(); i > 0;) {
01487 PushElement(static_cast<uint8_t>(v[--i]));
01488 }
01489 return Offset<Vector<uint8_t>>(EndVector(v.size()));
01490 }
01491
01492
01493 #ifndef FLATBUFFERS_CPP98_STL
01494
01495
01496
01497
01498
01499
01500
01501 template<typename T> Offset<Vector<T>> CreateVector(size_t vector_size,
01502 const std::function<T (size_t i)> &f) {
01503 std::vector<T> elems(vector_size);
01504 for (size_t i = 0; i < vector_size; i++) elems[i] = f(i);
01505 return CreateVector(elems);
01506 }
01507 #endif
01508
01509
01519 template<typename T, typename F, typename S>
01520 Offset<Vector<T>> CreateVector(size_t vector_size, F f, S *state) {
01521 std::vector<T> elems(vector_size);
01522 for (size_t i = 0; i < vector_size; i++) elems[i] = f(i, state);
01523 return CreateVector(elems);
01524 }
01525
01532 Offset<Vector<Offset<String>>> CreateVectorOfStrings(
01533 const std::vector<std::string> &v) {
01534 std::vector<Offset<String>> offsets(v.size());
01535 for (size_t i = 0; i < v.size(); i++) offsets[i] = CreateString(v[i]);
01536 return CreateVector(offsets);
01537 }
01538
01546 template<typename T>
01547 Offset<Vector<const T *>> CreateVectorOfStructs(const T *v, size_t len) {
01548 StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>());
01549 PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
01550 return Offset<Vector<const T *>>(EndVector(len));
01551 }
01552
01561 template<typename T, typename S>
01562 Offset<Vector<const T *>> CreateVectorOfNativeStructs(const S *v,
01563 size_t len) {
01564 extern T Pack(const S &);
01565 typedef T (*Pack_t)(const S &);
01566 std::vector<T> vv(len);
01567 std::transform(v, v + len, vv.begin(), static_cast<Pack_t&>(Pack));
01568 return CreateVectorOfStructs<T>(vv.data(), vv.size());
01569 }
01570
01571
01572 #ifndef FLATBUFFERS_CPP98_STL
01573
01574
01575
01576
01577
01578
01579
01580
01581 template<typename T> Offset<Vector<const T *>> CreateVectorOfStructs(
01582 size_t vector_size, const std::function<void(size_t i, T *)> &filler) {
01583 T* structs = StartVectorOfStructs<T>(vector_size);
01584 for (size_t i = 0; i < vector_size; i++) {
01585 filler(i, structs);
01586 structs++;
01587 }
01588 return EndVectorOfStructs<T>(vector_size);
01589 }
01590 #endif
01591
01592
01602 template<typename T, typename F, typename S>
01603 Offset<Vector<const T *>> CreateVectorOfStructs(size_t vector_size, F f,
01604 S *state) {
01605 T *structs = StartVectorOfStructs<T>(vector_size);
01606 for (size_t i = 0; i < vector_size; i++) {
01607 f(i, structs, state);
01608 structs++;
01609 }
01610 return EndVectorOfStructs<T>(vector_size);
01611 }
01612
01619 template<typename T, typename Alloc>
01620 Offset<Vector<const T *>> CreateVectorOfStructs(
01621 const std::vector<T, Alloc> &v) {
01622 return CreateVectorOfStructs(data(v), v.size());
01623 }
01624
01633 template<typename T, typename S>
01634 Offset<Vector<const T *>> CreateVectorOfNativeStructs(
01635 const std::vector<S> &v) {
01636 return CreateVectorOfNativeStructs<T, S>(data(v), v.size());
01637 }
01638
01640 template<typename T> struct StructKeyComparator {
01641 bool operator()(const T &a, const T &b) const {
01642 return a.KeyCompareLessThan(&b);
01643 }
01644
01645 private:
01646 StructKeyComparator &operator=(const StructKeyComparator &);
01647 };
01649
01657 template<typename T>
01658 Offset<Vector<const T *>> CreateVectorOfSortedStructs(std::vector<T> *v) {
01659 return CreateVectorOfSortedStructs(data(*v), v->size());
01660 }
01661
01670 template<typename T, typename S>
01671 Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(
01672 std::vector<S> *v) {
01673 return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size());
01674 }
01675
01684 template<typename T>
01685 Offset<Vector<const T *>> CreateVectorOfSortedStructs(T *v, size_t len) {
01686 std::sort(v, v + len, StructKeyComparator<T>());
01687 return CreateVectorOfStructs(v, len);
01688 }
01689
01699 template<typename T, typename S>
01700 Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(S *v,
01701 size_t len) {
01702 extern T Pack(const S &);
01703 typedef T (*Pack_t)(const S &);
01704 std::vector<T> vv(len);
01705 std::transform(v, v + len, vv.begin(), static_cast<Pack_t&>(Pack));
01706 return CreateVectorOfSortedStructs<T>(vv, len);
01707 }
01708
01710 template<typename T> struct TableKeyComparator {
01711 TableKeyComparator(vector_downward &buf) : buf_(buf) {}
01712 bool operator()(const Offset<T> &a, const Offset<T> &b) const {
01713 auto table_a = reinterpret_cast<T *>(buf_.data_at(a.o));
01714 auto table_b = reinterpret_cast<T *>(buf_.data_at(b.o));
01715 return table_a->KeyCompareLessThan(table_b);
01716 }
01717 vector_downward &buf_;
01718
01719 private:
01720 TableKeyComparator &operator=(const TableKeyComparator &);
01721 };
01723
01732 template<typename T>
01733 Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(Offset<T> *v,
01734 size_t len) {
01735 std::sort(v, v + len, TableKeyComparator<T>(buf_));
01736 return CreateVector(v, len);
01737 }
01738
01746 template<typename T>
01747 Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
01748 std::vector<Offset<T>> *v) {
01749 return CreateVectorOfSortedTables(data(*v), v->size());
01750 }
01751
01759 uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
01760 uint8_t **buf) {
01761 NotNested();
01762 StartVector(len, elemsize);
01763 buf_.make_space(len * elemsize);
01764 auto vec_start = GetSize();
01765 auto vec_end = EndVector(len);
01766 *buf = buf_.data_at(vec_start);
01767 return vec_end;
01768 }
01769
01778 template<typename T>
01779 Offset<Vector<T>> CreateUninitializedVector(size_t len, T **buf) {
01780 AssertScalarT<T>();
01781 return CreateUninitializedVector(len, sizeof(T),
01782 reinterpret_cast<uint8_t **>(buf));
01783 }
01784
01785 template<typename T>
01786 Offset<Vector<const T*>> CreateUninitializedVectorOfStructs(size_t len, T **buf) {
01787 return CreateUninitializedVector(len, sizeof(T),
01788 reinterpret_cast<uint8_t **>(buf));
01789 }
01790
01791
01792
01793
01794
01795 template<typename T, typename U>
01796 Offset<Vector<T>> CreateVectorScalarCast(const U *v, size_t len) {
01797 AssertScalarT<T>();
01798 AssertScalarT<U>();
01799 StartVector(len, sizeof(T));
01800 for (auto i = len; i > 0;) { PushElement(static_cast<T>(v[--i])); }
01801 return Offset<Vector<T>>(EndVector(len));
01802 }
01803
01805 template<typename T> Offset<const T *> CreateStruct(const T &structobj) {
01806 NotNested();
01807 Align(AlignOf<T>());
01808 buf_.push_small(structobj);
01809 return Offset<const T *>(GetSize());
01810 }
01811
01813 static const size_t kFileIdentifierLength = 4;
01814
01818 template<typename T>
01819 void Finish(Offset<T> root, const char *file_identifier = nullptr) {
01820 Finish(root.o, file_identifier, false);
01821 }
01822
01830 template<typename T>
01831 void FinishSizePrefixed(Offset<T> root,
01832 const char *file_identifier = nullptr) {
01833 Finish(root.o, file_identifier, true);
01834 }
01835
01836 void SwapBufAllocator(FlatBufferBuilder &other) {
01837 buf_.swap_allocator(other.buf_);
01838 }
01839
01840 protected:
01841
01842
01843 FlatBufferBuilder(const FlatBufferBuilder &);
01844 FlatBufferBuilder &operator=(const FlatBufferBuilder &);
01845
01846 void Finish(uoffset_t root, const char *file_identifier, bool size_prefix) {
01847 NotNested();
01848 buf_.clear_scratch();
01849
01850 PreAlign((size_prefix ? sizeof(uoffset_t) : 0) + sizeof(uoffset_t) +
01851 (file_identifier ? kFileIdentifierLength : 0),
01852 minalign_);
01853 if (file_identifier) {
01854 FLATBUFFERS_ASSERT(strlen(file_identifier) == kFileIdentifierLength);
01855 PushBytes(reinterpret_cast<const uint8_t *>(file_identifier),
01856 kFileIdentifierLength);
01857 }
01858 PushElement(ReferTo(root));
01859 if (size_prefix) { PushElement(GetSize()); }
01860 finished = true;
01861 }
01862
01863 struct FieldLoc {
01864 uoffset_t off;
01865 voffset_t id;
01866 };
01867
01868 vector_downward buf_;
01869
01870
01871
01872 uoffset_t num_field_loc;
01873
01874
01875 voffset_t max_voffset_;
01876
01877
01878 bool nested;
01879
01880
01881 bool finished;
01882
01883 size_t minalign_;
01884
01885 bool force_defaults_;
01886
01887 bool dedup_vtables_;
01888
01889 struct StringOffsetCompare {
01890 StringOffsetCompare(const vector_downward &buf) : buf_(&buf) {}
01891 bool operator()(const Offset<String> &a, const Offset<String> &b) const {
01892 auto stra = reinterpret_cast<const String *>(buf_->data_at(a.o));
01893 auto strb = reinterpret_cast<const String *>(buf_->data_at(b.o));
01894 return StringLessThan(stra->data(), stra->size(),
01895 strb->data(), strb->size());
01896 }
01897 const vector_downward *buf_;
01898 };
01899
01900
01901 typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
01902 StringOffsetMap *string_pool;
01903
01904 private:
01905
01906
01907 template<typename T> T *StartVectorOfStructs(size_t vector_size) {
01908 StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>());
01909 return reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T)));
01910 }
01911
01912
01913
01914 template<typename T>
01915 Offset<Vector<const T *>> EndVectorOfStructs(size_t vector_size) {
01916 return Offset<Vector<const T *>>(EndVector(vector_size));
01917 }
01918 };
01920
01922
01923 template<typename T> T *GetMutableRoot(void *buf) {
01924 EndianCheck();
01925 return reinterpret_cast<T *>(
01926 reinterpret_cast<uint8_t *>(buf) +
01927 EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
01928 }
01929
01930 template<typename T> const T *GetRoot(const void *buf) {
01931 return GetMutableRoot<T>(const_cast<void *>(buf));
01932 }
01933
01934 template<typename T> const T *GetSizePrefixedRoot(const void *buf) {
01935 return GetRoot<T>(reinterpret_cast<const uint8_t *>(buf) + sizeof(uoffset_t));
01936 }
01937
01941 template<typename T>
01942 T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
01943 return reinterpret_cast<T *>(fbb.GetCurrentBufferPointer() + fbb.GetSize() -
01944 offset.o);
01945 }
01946
01947 template<typename T>
01948 const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
01949 return GetMutableTemporaryPointer<T>(fbb, offset);
01950 }
01951
01959 inline const char *GetBufferIdentifier(const void *buf, bool size_prefixed = false) {
01960 return reinterpret_cast<const char *>(buf) +
01961 ((size_prefixed) ? 2 * sizeof(uoffset_t) : sizeof(uoffset_t));
01962 }
01963
01964
01965 inline bool BufferHasIdentifier(const void *buf, const char *identifier, bool size_prefixed = false) {
01966 return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier,
01967 FlatBufferBuilder::kFileIdentifierLength) == 0;
01968 }
01969
01970
01971 class Verifier FLATBUFFERS_FINAL_CLASS {
01972 public:
01973 Verifier(const uint8_t *buf, size_t buf_len, uoffset_t _max_depth = 64,
01974 uoffset_t _max_tables = 1000000, bool _check_alignment = true)
01975 : buf_(buf),
01976 size_(buf_len),
01977 depth_(0),
01978 max_depth_(_max_depth),
01979 num_tables_(0),
01980 max_tables_(_max_tables)
01981
01982 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
01983 , upper_bound_(0)
01984 #endif
01985 , check_alignment_(_check_alignment)
01986
01987 {
01988 FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
01989 }
01990
01991
01992 bool Check(bool ok) const {
01993
01994 #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
01995 FLATBUFFERS_ASSERT(ok);
01996 #endif
01997 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
01998 if (!ok)
01999 upper_bound_ = 0;
02000 #endif
02001
02002 return ok;
02003 }
02004
02005
02006 bool Verify(size_t elem, size_t elem_len) const {
02007
02008 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
02009 auto upper_bound = elem + elem_len;
02010 if (upper_bound_ < upper_bound)
02011 upper_bound_ = upper_bound;
02012 #endif
02013
02014 return Check(elem_len < size_ && elem <= size_ - elem_len);
02015 }
02016
02017 template<typename T> bool VerifyAlignment(size_t elem) const {
02018 return (elem & (sizeof(T) - 1)) == 0 || !check_alignment_;
02019 }
02020
02021
02022 template<typename T> bool Verify(size_t elem) const {
02023 return VerifyAlignment<T>(elem) && Verify(elem, sizeof(T));
02024 }
02025
02026
02027 bool Verify(const uint8_t *base, voffset_t elem_off, size_t elem_len) const {
02028 return Verify(static_cast<size_t>(base - buf_) + elem_off, elem_len);
02029 }
02030
02031 template<typename T> bool Verify(const uint8_t *base, voffset_t elem_off)
02032 const {
02033 return Verify(static_cast<size_t>(base - buf_) + elem_off, sizeof(T));
02034 }
02035
02036
02037 template<typename T> bool VerifyTable(const T *table) {
02038 return !table || table->Verify(*this);
02039 }
02040
02041
02042 template<typename T> bool VerifyVector(const Vector<T> *vec) const {
02043 return !vec || VerifyVectorOrString(reinterpret_cast<const uint8_t *>(vec),
02044 sizeof(T));
02045 }
02046
02047
02048 template<typename T> bool VerifyVector(const Vector<const T *> *vec) const {
02049 return VerifyVector(reinterpret_cast<const Vector<T> *>(vec));
02050 }
02051
02052
02053 bool VerifyString(const String *str) const {
02054 size_t end;
02055 return !str ||
02056 (VerifyVectorOrString(reinterpret_cast<const uint8_t *>(str),
02057 1, &end) &&
02058 Verify(end, 1) &&
02059 Check(buf_[end] == '\0'));
02060 }
02061
02062
02063 bool VerifyVectorOrString(const uint8_t *vec, size_t elem_size,
02064 size_t *end = nullptr) const {
02065 auto veco = static_cast<size_t>(vec - buf_);
02066
02067 if (!Verify<uoffset_t>(veco)) return false;
02068
02069
02070 auto size = ReadScalar<uoffset_t>(vec);
02071 auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
02072 if (!Check(size < max_elems))
02073 return false;
02074 auto byte_size = sizeof(size) + elem_size * size;
02075 if (end) *end = veco + byte_size;
02076 return Verify(veco, byte_size);
02077 }
02078
02079
02080 bool VerifyVectorOfStrings(const Vector<Offset<String>> *vec) const {
02081 if (vec) {
02082 for (uoffset_t i = 0; i < vec->size(); i++) {
02083 if (!VerifyString(vec->Get(i))) return false;
02084 }
02085 }
02086 return true;
02087 }
02088
02089
02090 template<typename T> bool VerifyVectorOfTables(const Vector<Offset<T>> *vec) {
02091 if (vec) {
02092 for (uoffset_t i = 0; i < vec->size(); i++) {
02093 if (!vec->Get(i)->Verify(*this)) return false;
02094 }
02095 }
02096 return true;
02097 }
02098
02099 bool VerifyTableStart(const uint8_t *table) {
02100
02101 auto tableo = static_cast<size_t>(table - buf_);
02102 if (!Verify<soffset_t>(tableo)) return false;
02103
02104
02105 auto vtableo = tableo - static_cast<size_t>(ReadScalar<soffset_t>(table));
02106
02107 return VerifyComplexity() && Verify<voffset_t>(vtableo) &&
02108 VerifyAlignment<voffset_t>(ReadScalar<voffset_t>(buf_ + vtableo)) &&
02109 Verify(vtableo, ReadScalar<voffset_t>(buf_ + vtableo));
02110 }
02111
02112 template<typename T>
02113 bool VerifyBufferFromStart(const char *identifier, size_t start) {
02114 if (identifier &&
02115 (size_ < 2 * sizeof(flatbuffers::uoffset_t) ||
02116 !BufferHasIdentifier(buf_ + start, identifier))) {
02117 return false;
02118 }
02119
02120
02121 auto o = VerifyOffset(start);
02122 return o && reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this)
02123
02124 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
02125 && GetComputedSize()
02126 #endif
02127 ;
02128
02129 }
02130
02131
02132 template<typename T> bool VerifyBuffer() { return VerifyBuffer<T>(nullptr); }
02133
02134 template<typename T> bool VerifyBuffer(const char *identifier) {
02135 return VerifyBufferFromStart<T>(identifier, 0);
02136 }
02137
02138 template<typename T> bool VerifySizePrefixedBuffer(const char *identifier) {
02139 return Verify<uoffset_t>(0U) &&
02140 ReadScalar<uoffset_t>(buf_) == size_ - sizeof(uoffset_t) &&
02141 VerifyBufferFromStart<T>(identifier, sizeof(uoffset_t));
02142 }
02143
02144 uoffset_t VerifyOffset(size_t start) const {
02145 if (!Verify<uoffset_t>(start)) return 0;
02146 auto o = ReadScalar<uoffset_t>(buf_ + start);
02147
02148 if (!Check(o != 0)) return 0;
02149
02150 if (!Check(static_cast<soffset_t>(o) >= 0)) return 0;
02151
02152
02153 if (!Verify(start + o, 1)) return 0;
02154 return o;
02155 }
02156
02157 uoffset_t VerifyOffset(const uint8_t *base, voffset_t start) const {
02158 return VerifyOffset(static_cast<size_t>(base - buf_) + start);
02159 }
02160
02161
02162
02163
02164
02165 bool VerifyComplexity() {
02166 depth_++;
02167 num_tables_++;
02168 return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_);
02169 }
02170
02171
02172 bool EndTable() {
02173 depth_--;
02174 return true;
02175 }
02176
02177
02178 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
02179
02180 size_t GetComputedSize() const {
02181 uintptr_t size = upper_bound_;
02182
02183 size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1);
02184 return (size > size_) ? 0 : size;
02185 }
02186 #endif
02187
02188
02189 private:
02190 const uint8_t *buf_;
02191 size_t size_;
02192 uoffset_t depth_;
02193 uoffset_t max_depth_;
02194 uoffset_t num_tables_;
02195 uoffset_t max_tables_;
02196
02197 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
02198 mutable size_t upper_bound_;
02199 #endif
02200
02201 bool check_alignment_;
02202 };
02203
02204
02205
02206
02207 struct BufferRefBase {};
02208 template<typename T> struct BufferRef : BufferRefBase {
02209 BufferRef() : buf(nullptr), len(0), must_free(false) {}
02210 BufferRef(uint8_t *_buf, uoffset_t _len)
02211 : buf(_buf), len(_len), must_free(false) {}
02212
02213 ~BufferRef() {
02214 if (must_free) free(buf);
02215 }
02216
02217 const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); }
02218
02219 bool Verify() {
02220 Verifier verifier(buf, len);
02221 return verifier.VerifyBuffer<T>(nullptr);
02222 }
02223
02224 uint8_t *buf;
02225 uoffset_t len;
02226 bool must_free;
02227 };
02228
02229
02230
02231
02232
02233 class Struct FLATBUFFERS_FINAL_CLASS {
02234 public:
02235 template<typename T> T GetField(uoffset_t o) const {
02236 return ReadScalar<T>(&data_[o]);
02237 }
02238
02239 template<typename T> T GetStruct(uoffset_t o) const {
02240 return reinterpret_cast<T>(&data_[o]);
02241 }
02242
02243 const uint8_t *GetAddressOf(uoffset_t o) const { return &data_[o]; }
02244 uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; }
02245
02246 private:
02247 uint8_t data_[1];
02248 };
02249
02250
02251
02252 class Table {
02253 public:
02254 const uint8_t *GetVTable() const {
02255 return data_ - ReadScalar<soffset_t>(data_);
02256 }
02257
02258
02259
02260 voffset_t GetOptionalFieldOffset(voffset_t field) const {
02261
02262 auto vtable = GetVTable();
02263
02264 auto vtsize = ReadScalar<voffset_t>(vtable);
02265
02266
02267 return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
02268 }
02269
02270 template<typename T> T GetField(voffset_t field, T defaultval) const {
02271 auto field_offset = GetOptionalFieldOffset(field);
02272 return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
02273 }
02274
02275 template<typename P> P GetPointer(voffset_t field) {
02276 auto field_offset = GetOptionalFieldOffset(field);
02277 auto p = data_ + field_offset;
02278 return field_offset ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p))
02279 : nullptr;
02280 }
02281 template<typename P> P GetPointer(voffset_t field) const {
02282 return const_cast<Table *>(this)->GetPointer<P>(field);
02283 }
02284
02285 template<typename P> P GetStruct(voffset_t field) const {
02286 auto field_offset = GetOptionalFieldOffset(field);
02287 auto p = const_cast<uint8_t *>(data_ + field_offset);
02288 return field_offset ? reinterpret_cast<P>(p) : nullptr;
02289 }
02290
02291 template<typename T> bool SetField(voffset_t field, T val, T def) {
02292 auto field_offset = GetOptionalFieldOffset(field);
02293 if (!field_offset) return IsTheSameAs(val, def);
02294 WriteScalar(data_ + field_offset, val);
02295 return true;
02296 }
02297
02298 bool SetPointer(voffset_t field, const uint8_t *val) {
02299 auto field_offset = GetOptionalFieldOffset(field);
02300 if (!field_offset) return false;
02301 WriteScalar(data_ + field_offset,
02302 static_cast<uoffset_t>(val - (data_ + field_offset)));
02303 return true;
02304 }
02305
02306 uint8_t *GetAddressOf(voffset_t field) {
02307 auto field_offset = GetOptionalFieldOffset(field);
02308 return field_offset ? data_ + field_offset : nullptr;
02309 }
02310 const uint8_t *GetAddressOf(voffset_t field) const {
02311 return const_cast<Table *>(this)->GetAddressOf(field);
02312 }
02313
02314 bool CheckField(voffset_t field) const {
02315 return GetOptionalFieldOffset(field) != 0;
02316 }
02317
02318
02319
02320 bool VerifyTableStart(Verifier &verifier) const {
02321 return verifier.VerifyTableStart(data_);
02322 }
02323
02324
02325 template<typename T>
02326 bool VerifyField(const Verifier &verifier, voffset_t field) const {
02327
02328
02329 auto field_offset = GetOptionalFieldOffset(field);
02330
02331 return !field_offset || verifier.Verify<T>(data_, field_offset);
02332 }
02333
02334
02335 template<typename T>
02336 bool VerifyFieldRequired(const Verifier &verifier, voffset_t field) const {
02337 auto field_offset = GetOptionalFieldOffset(field);
02338 return verifier.Check(field_offset != 0) &&
02339 verifier.Verify<T>(data_, field_offset);
02340 }
02341
02342
02343 bool VerifyOffset(const Verifier &verifier, voffset_t field) const {
02344 auto field_offset = GetOptionalFieldOffset(field);
02345 return !field_offset || verifier.VerifyOffset(data_, field_offset);
02346 }
02347
02348 bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const {
02349 auto field_offset = GetOptionalFieldOffset(field);
02350 return verifier.Check(field_offset != 0) &&
02351 verifier.VerifyOffset(data_, field_offset);
02352 }
02353
02354 private:
02355
02356
02357 Table();
02358 Table(const Table &other);
02359
02360 uint8_t data_[1];
02361 };
02362
02363 template<typename T> void FlatBufferBuilder::Required(Offset<T> table,
02364 voffset_t field) {
02365 auto table_ptr = reinterpret_cast<const Table *>(buf_.data_at(table.o));
02366 bool ok = table_ptr->GetOptionalFieldOffset(field) != 0;
02367
02368 FLATBUFFERS_ASSERT(ok);
02369 (void)ok;
02370 }
02371
02376 inline const uint8_t *GetBufferStartFromRootPointer(const void *root) {
02377 auto table = reinterpret_cast<const Table *>(root);
02378 auto vtable = table->GetVTable();
02379
02380 auto start = (std::min)(vtable, reinterpret_cast<const uint8_t *>(root));
02381
02382 start = reinterpret_cast<const uint8_t *>(reinterpret_cast<uintptr_t>(start) &
02383 ~(sizeof(uoffset_t) - 1));
02384
02385
02386
02387
02388
02389
02390
02391
02392
02393 static_assert(FlatBufferBuilder::kFileIdentifierLength == sizeof(uoffset_t),
02394 "file_identifier is assumed to be the same size as uoffset_t");
02395 for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1;
02396 possible_roots; possible_roots--) {
02397 start -= sizeof(uoffset_t);
02398 if (ReadScalar<uoffset_t>(start) + start ==
02399 reinterpret_cast<const uint8_t *>(root))
02400 return start;
02401 }
02402
02403
02404
02405
02406 FLATBUFFERS_ASSERT(false);
02407 return nullptr;
02408 }
02409
02411 inline uoffset_t GetPrefixedSize(const uint8_t* buf){ return ReadScalar<uoffset_t>(buf); }
02412
02413
02414
02415
02416 struct NativeTable {};
02417
02426 typedef uint64_t hash_value_t;
02427
02428 #ifdef FLATBUFFERS_CPP98_STL
02429 typedef void (*resolver_function_t)(void **pointer_adr, hash_value_t hash);
02430 typedef hash_value_t (*rehasher_function_t)(void *pointer);
02431 #else
02432 typedef std::function<void (void **pointer_adr, hash_value_t hash)>
02433 resolver_function_t;
02434 typedef std::function<hash_value_t (void *pointer)> rehasher_function_t;
02435 #endif
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445 template<typename T>
02446 bool IsFieldPresent(const T *table, typename T::FlatBuffersVTableOffset field) {
02447
02448 return reinterpret_cast<const Table *>(table)->CheckField(
02449 static_cast<voffset_t>(field));
02450 }
02451
02452
02453
02454
02455 inline int LookupEnum(const char **names, const char *name) {
02456 for (const char **p = names; *p; p++)
02457 if (!strcmp(*p, name)) return static_cast<int>(p - names);
02458 return -1;
02459 }
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472 #if defined(_MSC_VER)
02473 #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
02474 __pragma(pack(1)); \
02475 struct __declspec(align(alignment))
02476 #define FLATBUFFERS_STRUCT_END(name, size) \
02477 __pragma(pack()); \
02478 static_assert(sizeof(name) == size, "compiler breaks packing rules")
02479 #elif defined(__GNUC__) || defined(__clang__)
02480 #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
02481 _Pragma("pack(1)") \
02482 struct __attribute__((aligned(alignment)))
02483 #define FLATBUFFERS_STRUCT_END(name, size) \
02484 _Pragma("pack()") \
02485 static_assert(sizeof(name) == size, "compiler breaks packing rules")
02486 #else
02487 #error Unknown compiler, please define structure alignment macros
02488 #endif
02489
02490
02491
02492
02493
02494
02495
02496
02497
02498
02499
02500
02501 enum SequenceType { ST_TABLE, ST_STRUCT, ST_UNION, ST_ENUM };
02502
02503
02504
02505 #define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \
02506 ET(ET_UTYPE) \
02507 ET(ET_BOOL) \
02508 ET(ET_CHAR) \
02509 ET(ET_UCHAR) \
02510 ET(ET_SHORT) \
02511 ET(ET_USHORT) \
02512 ET(ET_INT) \
02513 ET(ET_UINT) \
02514 ET(ET_LONG) \
02515 ET(ET_ULONG) \
02516 ET(ET_FLOAT) \
02517 ET(ET_DOUBLE) \
02518 ET(ET_STRING) \
02519 ET(ET_SEQUENCE) // See SequenceType.
02520
02521 enum ElementaryType {
02522 #define FLATBUFFERS_ET(E) E,
02523 FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
02524 #undef FLATBUFFERS_ET
02525 };
02526
02527 inline const char * const *ElementaryTypeNames() {
02528 static const char * const names[] = {
02529 #define FLATBUFFERS_ET(E) #E,
02530 FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
02531 #undef FLATBUFFERS_ET
02532 };
02533 return names;
02534 }
02535
02536
02537
02538 struct TypeCode {
02539 uint16_t base_type : 4;
02540 uint16_t is_vector : 1;
02541 int16_t sequence_ref : 11;
02542 };
02543
02544 static_assert(sizeof(TypeCode) == 2, "TypeCode");
02545
02546 struct TypeTable;
02547
02548
02549 typedef const TypeTable *(*TypeFunction)();
02550
02551 struct TypeTable {
02552 SequenceType st;
02553 size_t num_elems;
02554 const TypeCode *type_codes;
02555 const TypeFunction *type_refs;
02556 const int64_t *values;
02557 const char * const *names;
02558 };
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571 #if !defined(_WIN32) && !defined(__CYGWIN__)
02572
02573 extern volatile __attribute__((weak)) const char *flatbuffer_version_string;
02574 volatile __attribute__((weak)) const char *flatbuffer_version_string =
02575 "FlatBuffers "
02576 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
02577 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
02578 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
02579
02580 #endif // !defined(_WIN32) && !defined(__CYGWIN__)
02581
02582 #define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\
02583 inline E operator | (E lhs, E rhs){\
02584 return E(T(lhs) | T(rhs));\
02585 }\
02586 inline E operator & (E lhs, E rhs){\
02587 return E(T(lhs) & T(rhs));\
02588 }\
02589 inline E operator ^ (E lhs, E rhs){\
02590 return E(T(lhs) ^ T(rhs));\
02591 }\
02592 inline E operator ~ (E lhs){\
02593 return E(~T(lhs));\
02594 }\
02595 inline E operator |= (E &lhs, E rhs){\
02596 lhs = lhs | rhs;\
02597 return lhs;\
02598 }\
02599 inline E operator &= (E &lhs, E rhs){\
02600 lhs = lhs & rhs;\
02601 return lhs;\
02602 }\
02603 inline E operator ^= (E &lhs, E rhs){\
02604 lhs = lhs ^ rhs;\
02605 return lhs;\
02606 }\
02607 inline bool operator !(E rhs) \
02608 {\
02609 return !bool(T(rhs)); \
02610 }
02611
02612 }
02613
02614
02615
02616 #endif // FLATBUFFERS_H_