Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
flatbuffers.h
00001 /* 00002 * Copyright 2014 Google Inc. All rights reserved. 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 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 // Generic 'operator==' with conditional specialisations. 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 // Like `operator==(e, def)` with weak NaN if T=(float|double). 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 // Wrapper for uoffset_t to allow safe template specialization. 00042 // Value is allowed to be 0 to indicate a null object (see e.g. AddOffset). 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 // If this fails, see FLATBUFFERS_LITTLEENDIAN above. 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 // clang-format off 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 // clang-format on 00071 } 00072 00073 // When we read serialized data from memory, in the case of most scalars, 00074 // we want to just read T, but in the case of Offset, we want to actually 00075 // perform the indirection and return a pointer. 00076 // The template specialization below does just that. 00077 // It is wrapped in a struct since function templates can't overload on the 00078 // return type like this. 00079 // The typedef is for the convenience of callers of this function 00080 // (avoiding the need for a trailing return decltype) 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 // An STL compatible iterator implementation for Vector below, effectively 00108 // calling Get() for every element. 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 // clang-format off 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 // clang-format on 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 // This is used as a helper type for accessing vectors. 00217 // Vector::data() assumes the vector elements start after the length field. 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 // Deprecated: use size(). Here for backwards compatibility. 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 // If this is a Vector of enums, T will be its storage type, not the enum 00244 // type. This function makes it convenient to retrieve value with enum 00245 // type E. 00246 template<typename E> E GetEnum(uoffset_t i) const { 00247 return static_cast<E>(Get(i)); 00248 } 00249 00250 // If this a vector of unions, this does the cast for you. There's no check 00251 // to make sure this is the right type! 00252 template<typename U> const U *GetAs(uoffset_t i) const { 00253 return reinterpret_cast<const U *>(Get(i)); 00254 } 00255 00256 // If this a vector of unions, this does the cast for you. There's no check 00257 // to make sure this is actually a string! 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 // Change elements if you have a non-const pointer to this object. 00287 // Scalars only. See reflection.h, and the documentation. 00288 void Mutate(uoffset_t i, const T &val) { 00289 FLATBUFFERS_ASSERT(i < size()); 00290 WriteScalar(data() + i, val); 00291 } 00292 00293 // Change an element of a vector of tables (or strings). 00294 // "val" points to the new table/string, as you can obtain from 00295 // e.g. reflection::AddFlatBuffer(). 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 // Get a mutable pointer to tables/strings inside this vector. 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 // The raw data in little endian format. Use with care. 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 // Similarly, but typed, much like std::vector::data 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; // Key not found. 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 // This class is only used to access pre-existing data. Don't ever 00335 // try to construct these manually. 00336 Vector(); 00337 00338 uoffset_t length_; 00339 00340 private: 00341 // This class is a pointer. Copying will therefore create an invalid object. 00342 // Private and unimplemented copy constructor. 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 // std::bsearch compares with the operands transposed, so we negate the 00351 // result here. 00352 return -table->KeyCompareWithValue(*key); 00353 } 00354 }; 00355 00356 // Represent a vector much like the template above, but in this case we 00357 // don't know what the element types are (used with reflection.h). 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 // Convenient helper function to get the length of any vector, regardless 00391 // of whether it is null or not (the field is not set). 00392 template<typename T> static inline size_t VectorLength(const Vector<T> *v) { 00393 return v ? v->size() : 0; 00394 } 00395 00396 // Lexicographically compare two strings (possibly containing nulls), and 00397 // return true if the first is less than the second. 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 // clang-format off 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 // clang-format on 00415 00416 bool operator<(const String &o) const { 00417 return StringLessThan(this->data(), this->size(), o.data(), o.size()); 00418 } 00419 }; 00420 00421 // Convenience function to get std::string from a String returning an empty 00422 // string on null pointer. 00423 static inline std::string GetString(const String * str) { 00424 return str ? str->str() : ""; 00425 } 00426 00427 // Convenience function to get char* from a String returning an empty string on 00428 // null pointer. 00429 static inline const char * GetCstring(const String * str) { 00430 return str ? str->c_str() : ""; 00431 } 00432 00433 // Allocator interface. This is flatbuffers-specific and meant only for 00434 // `vector_downward` usage. 00435 class Allocator { 00436 public: 00437 virtual ~Allocator() {} 00438 00439 // Allocate `size` bytes of memory. 00440 virtual uint8_t *allocate(size_t size) = 0; 00441 00442 // Deallocate `size` bytes of memory at `p` allocated by this allocator. 00443 virtual void deallocate(uint8_t *p, size_t size) = 0; 00444 00445 // Reallocate `new_size` bytes of memory, replacing the old region of size 00446 // `old_size` at `p`. In contrast to a normal realloc, this grows downwards, 00447 // and is intended specifcally for `vector_downward` use. 00448 // `in_use_back` and `in_use_front` indicate how much of `old_size` is 00449 // actually in use at each end, and needs to be copied. 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); // vector_downward only grows 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 // Called by `reallocate_downward` to copy memory from `old_p` of `old_size` 00463 // to `new_p` of `new_size`. Only memory of size `in_use_front` and 00464 // `in_use_back` will be copied from the front and back of the old memory 00465 // allocation. 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 // DefaultAllocator uses new/delete to allocate memory regions 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 // These functions allow for a null allocator to mean use the default allocator, 00492 // as used by DetachedBuffer and vector_downward below. 00493 // This is to avoid having a statically or dynamically allocated default 00494 // allocator, or having to move it between the classes that may own it. 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 // DetachedBuffer is a finished flatbuffer memory region, detached from its 00516 // builder. The original memory region and allocator are also stored so that 00517 // the DetachedBuffer can manage the memory lifetime. 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 // clang-format off 00538 #if !defined(FLATBUFFERS_CPP98_STL) 00539 // clang-format on 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 // clang-format off 00550 #endif // !defined(FLATBUFFERS_CPP98_STL) 00551 // clang-format on 00552 00553 // clang-format off 00554 #if !defined(FLATBUFFERS_CPP98_STL) 00555 // clang-format on 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 // clang-format off 00571 #endif // !defined(FLATBUFFERS_CPP98_STL) 00572 // clang-format on 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 // clang-format off 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 // clang-format on 00601 00602 // clang-format off 00603 #if !defined(FLATBUFFERS_CPP98_STL) 00604 // clang-format on 00605 // These may change access mode, leave these at end of public section 00606 FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other)) 00607 FLATBUFFERS_DELETE_FUNC( 00608 DetachedBuffer &operator=(const DetachedBuffer &other)) 00609 // clang-format off 00610 #endif // !defined(FLATBUFFERS_CPP98_STL) 00611 // clang-format on 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 // This is a minimal replication of std::vector<uint8_t> functionality, 00638 // except growing from higher to lower addresses. i.e push_back() inserts data 00639 // in the lowest address in the vector. 00640 // Since this vector leaves the lower part unused, we support a "scratch-pad" 00641 // that can be stored there for temporary data, to share the allocated space. 00642 // Essentially, this supports 2 std::vectors in a single buffer. 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 // clang-format off 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 // clang-format on 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 // No change in other.allocator_ 00674 // No change in other.initial_size_ 00675 // No change in other.buffer_minalign_ 00676 other.own_allocator_ = false; 00677 other.reserved_ = 0; 00678 other.buf_ = nullptr; 00679 other.cur_ = nullptr; 00680 other.scratch_ = nullptr; 00681 } 00682 00683 // clang-format off 00684 #if !defined(FLATBUFFERS_CPP98_STL) 00685 // clang-format on 00686 vector_downward &operator=(vector_downward &&other) { 00687 // Move construct a temporary and swap idiom 00688 vector_downward temp(std::move(other)); 00689 swap(temp); 00690 return *this; 00691 } 00692 // clang-format off 00693 #endif // defined(FLATBUFFERS_CPP98_STL) 00694 // clang-format on 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 // Relinquish the pointer to the caller. 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 // release_raw only relinquishes the buffer ownership. 00738 // Does not deallocate or reset the allocator. Destructor will do that. 00739 buf_ = nullptr; 00740 clear(); 00741 return buf; 00742 } 00743 00744 // Relinquish the pointer to the caller. 00745 DetachedBuffer release() { 00746 // allocator ownership (if any) is transferred to DetachedBuffer. 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 // Beyond this, signed offsets may not have enough range: 00762 // (FlatBuffers > 2GB not supported). 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 // Returns nullptr if using the DefaultAllocator. 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 // Specialized version of push() that avoids memcpy call for small data. 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 // fill() is most frequently called with small byte counts (<= 4), 00820 // which is why we're using loops rather than calling memset. 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 // Version for when we know the size is larger. 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 // You shouldn't really be copying instances of this class. 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_; // Points at location between empty (below) and used (above). 00864 uint8_t *scratch_; // Points to the end of the scratchpad in use. 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 // Converts a Field ID to a virtual table offset. 00885 inline voffset_t FieldIndexToOffset(voffset_t field_id) { 00886 // Should correspond to what EndTable() below builds up. 00887 const int fixed_fields = 2; // Vtable size and Object Size. 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 00899 /// @endcond 00900 00901 /// @addtogroup flatbuffers_cpp_api 00902 /// @{ 00903 /// @class FlatBufferBuilder 00904 /// @brief Helper class to hold data needed in creation of a FlatBuffer. 00905 /// To serialize data, you typically call one of the `Create*()` functions in 00906 /// the generated code, which in turn call a sequence of `StartTable`/ 00907 /// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/ 00908 /// `CreateVector` functions. Do this is depth-first order to build up a tree to 00909 /// the root. `Finish()` wraps up the buffer ready for transport. 00910 class FlatBufferBuilder { 00911 public: 00912 /// @brief Default constructor for FlatBufferBuilder. 00913 /// @param[in] initial_size The initial size of the buffer, in bytes. Defaults 00914 /// to `1024`. 00915 /// @param[in] allocator An `Allocator` to use. If null will use 00916 /// `DefaultAllocator`. 00917 /// @param[in] own_allocator Whether the builder/vector should own the 00918 /// allocator. Defaults to / `false`. 00919 /// @param[in] buffer_minalign Force the buffer to be aligned to the given 00920 /// minimum alignment upon reallocation. Only needed if you intend to store 00921 /// types with custom alignment AND you wish to read the buffer in-place 00922 /// directly after creation. 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 // clang-format off 00941 /// @brief Move constructor for FlatBufferBuilder. 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 // Default construct and swap idiom. 00958 // Lack of delegating constructors in vs2010 makes it more verbose than needed. 00959 Swap(other); 00960 } 00961 // clang-format on 00962 00963 // clang-format off 00964 #if !defined(FLATBUFFERS_CPP98_STL) 00965 // clang-format on 00966 /// @brief Move assignment operator for FlatBufferBuilder. 00967 FlatBufferBuilder &operator=(FlatBufferBuilder &&other) { 00968 // Move construct a temporary and swap idiom 00969 FlatBufferBuilder temp(std::move(other)); 00970 Swap(temp); 00971 return *this; 00972 } 00973 // clang-format off 00974 #endif // defined(FLATBUFFERS_CPP98_STL) 00975 // clang-format on 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(); // clear builder state 00996 buf_.reset(); // deallocate buffer 00997 } 00998 00999 /// @brief Reset all the state in this FlatBufferBuilder so it can be reused 01000 /// to construct another buffer. 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 01010 /// @brief The current size of the serialized buffer, counting from the end. 01011 /// @return Returns an `uoffset_t` with the current size of the buffer. 01012 uoffset_t GetSize() const { return buf_.size(); } 01013 01014 /// @brief Get the serialized buffer (after you call `Finish()`). 01015 /// @return Returns an `uint8_t` pointer to the FlatBuffer data inside the 01016 /// buffer. 01017 uint8_t *GetBufferPointer() const { 01018 Finished(); 01019 return buf_.data(); 01020 } 01021 01022 /// @brief Get a pointer to an unfinished buffer. 01023 /// @return Returns a `uint8_t` pointer to the unfinished buffer. 01024 uint8_t *GetCurrentBufferPointer() const { return buf_.data(); } 01025 01026 /// @brief Get the released pointer to the serialized buffer. 01027 /// @warning Do NOT attempt to use this FlatBufferBuilder afterwards! 01028 /// @return A `FlatBuffer` that owns the buffer and its allocator and 01029 /// behaves similar to a `unique_ptr` with a deleter. 01030 FLATBUFFERS_ATTRIBUTE(deprecated("use Release() instead")) DetachedBuffer 01031 ReleaseBufferPointer() { 01032 Finished(); 01033 return buf_.release(); 01034 } 01035 01036 /// @brief Get the released DetachedBuffer. 01037 /// @return A `DetachedBuffer` that owns the buffer and its allocator. 01038 DetachedBuffer Release() { 01039 Finished(); 01040 return buf_.release(); 01041 } 01042 01043 /// @brief Get the released pointer to the serialized buffer. 01044 /// @param The size of the memory block containing 01045 /// the serialized `FlatBuffer`. 01046 /// @param The offset from the released pointer where the finished 01047 /// `FlatBuffer` starts. 01048 /// @return A raw pointer to the start of the memory block containing 01049 /// the serialized `FlatBuffer`. 01050 /// @remark If the allocator is owned, it gets deleted when the destructor is called.. 01051 uint8_t *ReleaseRaw(size_t &size, size_t &offset) { 01052 Finished(); 01053 return buf_.release_raw(size, offset); 01054 } 01055 01056 /// @brief get the minimum alignment this buffer needs to be accessed 01057 /// properly. This is only known once all elements have been written (after 01058 /// you call Finish()). You can use this information if you need to embed 01059 /// a FlatBuffer in some other buffer, such that you can later read it 01060 /// without first having to copy it into its own buffer. 01061 size_t GetBufferMinAlignment() { 01062 Finished(); 01063 return minalign_; 01064 } 01065 01066 /// @cond FLATBUFFERS_INTERNAL 01067 void Finished() const { 01068 // If you get this assert, you're attempting to get access a buffer 01069 // which hasn't been finished yet. Be sure to call 01070 // FlatBufferBuilder::Finish with your root table. 01071 // If you really need to access an unfinished buffer, call 01072 // GetCurrentBufferPointer instead. 01073 FLATBUFFERS_ASSERT(finished); 01074 } 01075 /// @endcond 01076 01077 /// @brief In order to save space, fields that are set to their default value 01078 /// don't get serialized into the buffer. 01079 /// @param[in] bool fd When set to `true`, always serializes default values that are set. 01080 /// Optional fields which are not set explicitly, will still not be serialized. 01081 void ForceDefaults(bool fd) { force_defaults_ = fd; } 01082 01083 /// @brief By default vtables are deduped in order to save space. 01084 /// @param[in] bool dedup When set to `true`, dedup vtables. 01085 void DedupVtables(bool dedup) { dedup_vtables_ = dedup; } 01086 01087 /// @cond FLATBUFFERS_INTERNAL 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 // The code assumes power of 2 sizes and endian-swap-ability. 01110 static_assert(flatbuffers::is_scalar<T>::value, "T must be a scalar type"); 01111 } 01112 01113 // Write a single aligned scalar to the buffer 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 // Special case for offsets: see ReferTo below. 01124 return PushElement(ReferTo(off.o)); 01125 } 01126 01127 // When writing fields, we track where they are, so we can create correct 01128 // vtables later. 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 // Like PushElement, but additionally tracks the field this represents. 01137 template<typename T> void AddElement(voffset_t field, T e, T def) { 01138 // We don't serialize values equal to the default. 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; // Don't store. 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; // Default, don't store. 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 // Offsets initially are relative to the end of the buffer (downwards). 01161 // This function converts them to be relative to the current location 01162 // in the buffer (when stored here), pointing upwards. 01163 uoffset_t ReferTo(uoffset_t off) { 01164 // Align to ensure GetSize() below is correct. 01165 Align(sizeof(uoffset_t)); 01166 // Offset must refer to something already in buffer. 01167 FLATBUFFERS_ASSERT(off && off <= GetSize()); 01168 return GetSize() - off + static_cast<uoffset_t>(sizeof(uoffset_t)); 01169 } 01170 01171 void NotNested() { 01172 // If you hit this, you're trying to construct a Table/Vector/String 01173 // during the construction of its parent table (between the MyTableBuilder 01174 // and table.Finish(). 01175 // Move the creation of these sub-objects to above the MyTableBuilder to 01176 // not get this assert. 01177 // Ignoring this assert may appear to work in simple cases, but the reason 01178 // it is here is that storing objects in-line may cause vtable offsets 01179 // to not fit anymore. It also leads to vtable duplication. 01180 FLATBUFFERS_ASSERT(!nested); 01181 // If you hit this, fields were added outside the scope of a table. 01182 FLATBUFFERS_ASSERT(!num_field_loc); 01183 } 01184 01185 // From generated code (or from the parser), we call StartTable/EndTable 01186 // with a sequence of AddElement calls in between. 01187 uoffset_t StartTable() { 01188 NotNested(); 01189 nested = true; 01190 return GetSize(); 01191 } 01192 01193 // This finishes one serialized object by generating the vtable if it's a 01194 // table, comparing it against existing vtables, and writing the 01195 // resulting vtable offset. 01196 uoffset_t EndTable(uoffset_t start) { 01197 // If you get this assert, a corresponding StartTable wasn't called. 01198 FLATBUFFERS_ASSERT(nested); 01199 // Write the vtable offset, which is the start of any Table. 01200 // We fill it's value later. 01201 auto vtableoffsetloc = PushElement<soffset_t>(0); 01202 // Write a vtable, which consists entirely of voffset_t elements. 01203 // It starts with the number of offsets, followed by a type id, followed 01204 // by the offsets themselves. In reverse: 01205 // Include space for the last offset and ensure empty tables have a 01206 // minimum size. 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 // Vtable use 16bit offsets. 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 // Write the offsets into the table 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 // If this asserts, it means you've set a field twice. 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 // See if we already have generated a vtable with this exact same 01232 // layout before. If so, make it point to the old one, remove this one. 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 // If this is a new vtable, remember it. 01246 if (vt_use == GetSize()) { buf_.scratch_push_small(vt_use); } 01247 // Fill the vtable offset we created above. 01248 // The offset points from the beginning of the object to where the 01249 // vtable is stored. 01250 // Offsets default direction is downward in memory for future format 01251 // flexibility (storing all vtables at the start of the file). 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 /*numfields*/) { 01262 return EndTable(start); 01263 } 01264 01265 // This checks a required field has been set in a given table that has 01266 // just been constructed. 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 // Aligns such that when "len" bytes are written, an object can be written 01283 // after it with "alignment" without padding. 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 } 01292 /// @endcond 01293 01294 /// @brief Store a string in the buffer, which can contain any binary data. 01295 /// @param[in] str A const char pointer to the data to be stored as a string. 01296 /// @param[in] len The number of bytes that should be stored from `str`. 01297 /// @return Returns the offset in the buffer where the string starts. 01298 Offset<String> CreateString(const char *str, size_t len) { 01299 NotNested(); 01300 PreAlign<uoffset_t>(len + 1); // Always 0-terminated. 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 01307 /// @brief Store a string in the buffer, which is null-terminated. 01308 /// @param[in] str A const char pointer to a C-string to add to the buffer. 01309 /// @return Returns the offset in the buffer where the string starts. 01310 Offset<String> CreateString(const char *str) { 01311 return CreateString(str, strlen(str)); 01312 } 01313 01314 /// @brief Store a string in the buffer, which is null-terminated. 01315 /// @param[in] str A char pointer to a C-string to add to the buffer. 01316 /// @return Returns the offset in the buffer where the string starts. 01317 Offset<String> CreateString(char *str) { 01318 return CreateString(str, strlen(str)); 01319 } 01320 01321 /// @brief Store a string in the buffer, which can contain any binary data. 01322 /// @param[in] str A const reference to a std::string to store in the buffer. 01323 /// @return Returns the offset in the buffer where the string starts. 01324 Offset<String> CreateString(const std::string &str) { 01325 return CreateString(str.c_str(), str.length()); 01326 } 01327 01328 // clang-format off 01329 #ifdef FLATBUFFERS_HAS_STRING_VIEW 01330 /// @brief Store a string in the buffer, which can contain any binary data. 01331 /// @param[in] str A const string_view to copy in to the buffer. 01332 /// @return Returns the offset in the buffer where the string starts. 01333 Offset<String> CreateString(flatbuffers::string_view str) { 01334 return CreateString(str.data(), str.size()); 01335 } 01336 #endif // FLATBUFFERS_HAS_STRING_VIEW 01337 // clang-format on 01338 01339 /// @brief Store a string in the buffer, which can contain any binary data. 01340 /// @param[in] str A const pointer to a `String` struct to add to the buffer. 01341 /// @return Returns the offset in the buffer where the string starts 01342 Offset<String> CreateString(const String *str) { 01343 return str ? CreateString(str->c_str(), str->size()) : 0; 01344 } 01345 01346 /// @brief Store a string in the buffer, which can contain any binary data. 01347 /// @param[in] str A const reference to a std::string like type with support 01348 /// of T::c_str() and T::length() to store in the buffer. 01349 /// @return Returns the offset in the buffer where the string starts. 01350 template<typename T> Offset<String> CreateString(const T &str) { 01351 return CreateString(str.c_str(), str.length()); 01352 } 01353 01354 /// @brief Store a string in the buffer, which can contain any binary data. 01355 /// If a string with this exact contents has already been serialized before, 01356 /// instead simply returns the offset of the existing string. 01357 /// @param[in] str A const char pointer to the data to be stored as a string. 01358 /// @param[in] len The number of bytes that should be stored from `str`. 01359 /// @return Returns the offset in the buffer where the string starts. 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 // Must first serialize the string, since the set is all offsets into 01365 // buffer. 01366 auto off = CreateString(str, len); 01367 auto it = string_pool->find(off); 01368 // If it exists we reuse existing serialized data! 01369 if (it != string_pool->end()) { 01370 // We can remove the string we serialized. 01371 buf_.pop(buf_.size() - size_before_string); 01372 return *it; 01373 } 01374 // Record this string for future use. 01375 string_pool->insert(off); 01376 return off; 01377 } 01378 01379 /// @brief Store a string in the buffer, which null-terminated. 01380 /// If a string with this exact contents has already been serialized before, 01381 /// instead simply returns the offset of the existing string. 01382 /// @param[in] str A const char pointer to a C-string to add to the buffer. 01383 /// @return Returns the offset in the buffer where the string starts. 01384 Offset<String> CreateSharedString(const char *str) { 01385 return CreateSharedString(str, strlen(str)); 01386 } 01387 01388 /// @brief Store a string in the buffer, which can contain any binary data. 01389 /// If a string with this exact contents has already been serialized before, 01390 /// instead simply returns the offset of the existing string. 01391 /// @param[in] str A const reference to a std::string to store in the buffer. 01392 /// @return Returns the offset in the buffer where the string starts. 01393 Offset<String> CreateSharedString(const std::string &str) { 01394 return CreateSharedString(str.c_str(), str.length()); 01395 } 01396 01397 /// @brief Store a string in the buffer, which can contain any binary data. 01398 /// If a string with this exact contents has already been serialized before, 01399 /// instead simply returns the offset of the existing string. 01400 /// @param[in] str A const pointer to a `String` struct to add to the buffer. 01401 /// @return Returns the offset in the buffer where the string starts 01402 Offset<String> CreateSharedString(const String *str) { 01403 return CreateSharedString(str->c_str(), str->size()); 01404 } 01405 01406 /// @cond FLATBUFFERS_INTERNAL 01407 uoffset_t EndVector(size_t len) { 01408 FLATBUFFERS_ASSERT(nested); // Hit if no corresponding StartVector. 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); // Just in case elemsize > uoffset_t. 01418 } 01419 01420 // Call this right before StartVector/CreateVector if you want to force the 01421 // alignment to be something different than what the element size would 01422 // normally dictate. 01423 // This is useful when storing a nested_flatbuffer in a vector of bytes, 01424 // or when storing SIMD floats, etc. 01425 void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment) { 01426 PreAlign(len * elemsize, alignment); 01427 } 01428 01429 // Similar to ForceVectorAlignment but for String fields. 01430 void ForceStringAlignment(size_t len, size_t alignment) { 01431 PreAlign((len + 1) * sizeof(char), alignment); 01432 } 01433 01434 /// @endcond 01435 01436 /// @brief Serialize an array into a FlatBuffer `vector`. 01437 /// @tparam T The data type of the array elements. 01438 /// @param[in] v A pointer to the array of type `T` to serialize into the 01439 /// buffer as a `vector`. 01440 /// @param[in] len The number of elements to serialize. 01441 /// @return Returns a typed `Offset` into the serialized data indicating 01442 /// where the vector is stored. 01443 template<typename T> Offset<Vector<T>> CreateVector(const T *v, size_t len) { 01444 // If this assert hits, you're specifying a template argument that is 01445 // causing the wrong overload to be selected, remove it. 01446 AssertScalarT<T>(); 01447 StartVector(len, sizeof(T)); 01448 // clang-format off 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 // clang-format on 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 01471 /// @brief Serialize a `std::vector` into a FlatBuffer `vector`. 01472 /// @tparam T The data type of the `std::vector` elements. 01473 /// @param v A const reference to the `std::vector` to serialize into the 01474 /// buffer as a `vector`. 01475 /// @return Returns a typed `Offset` into the serialized data indicating 01476 /// where the vector is stored. 01477 template<typename T> Offset<Vector<T>> CreateVector(const std::vector<T> &v) { 01478 return CreateVector(data(v), v.size()); 01479 } 01480 01481 // vector<bool> may be implemented using a bit-set, so we can't access it as 01482 // an array. Instead, read elements manually. 01483 // Background: https://isocpp.org/blog/2012/11/on-vectorbool 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 // clang-format off 01493 #ifndef FLATBUFFERS_CPP98_STL 01494 /// @brief Serialize values returned by a function into a FlatBuffer `vector`. 01495 /// This is a convenience function that takes care of iteration for you. 01496 /// @tparam T The data type of the `std::vector` elements. 01497 /// @param f A function that takes the current iteration 0..vector_size-1 and 01498 /// returns any type that you can construct a FlatBuffers vector out of. 01499 /// @return Returns a typed `Offset` into the serialized data indicating 01500 /// where the vector is stored. 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 // clang-format on 01509 01510 /// @brief Serialize values returned by a function into a FlatBuffer `vector`. 01511 /// This is a convenience function that takes care of iteration for you. 01512 /// @tparam T The data type of the `std::vector` elements. 01513 /// @param f A function that takes the current iteration 0..vector_size-1, 01514 /// and the state parameter returning any type that you can construct a 01515 /// FlatBuffers vector out of. 01516 /// @param state State passed to f. 01517 /// @return Returns a typed `Offset` into the serialized data indicating 01518 /// where the vector is stored. 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 01526 /// @brief Serialize a `std::vector<std::string>` into a FlatBuffer `vector`. 01527 /// This is a convenience function for a common case. 01528 /// @param v A const reference to the `std::vector` to serialize into the 01529 /// buffer as a `vector`. 01530 /// @return Returns a typed `Offset` into the serialized data indicating 01531 /// where the vector is stored. 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 01539 /// @brief Serialize an array of structs into a FlatBuffer `vector`. 01540 /// @tparam T The data type of the struct array elements. 01541 /// @param[in] v A pointer to the array of type `T` to serialize into the 01542 /// buffer as a `vector`. 01543 /// @param[in] len The number of elements to serialize. 01544 /// @return Returns a typed `Offset` into the serialized data indicating 01545 /// where the vector is stored. 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 01553 /// @brief Serialize an array of native structs into a FlatBuffer `vector`. 01554 /// @tparam T The data type of the struct array elements. 01555 /// @tparam S The data type of the native struct array elements. 01556 /// @param[in] v A pointer to the array of type `S` to serialize into the 01557 /// buffer as a `vector`. 01558 /// @param[in] len The number of elements to serialize. 01559 /// @return Returns a typed `Offset` into the serialized data indicating 01560 /// where the vector is stored. 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 // clang-format off 01572 #ifndef FLATBUFFERS_CPP98_STL 01573 /// @brief Serialize an array of structs into a FlatBuffer `vector`. 01574 /// @tparam T The data type of the struct array elements. 01575 /// @param[in] f A function that takes the current iteration 0..vector_size-1 01576 /// and a pointer to the struct that must be filled. 01577 /// @return Returns a typed `Offset` into the serialized data indicating 01578 /// where the vector is stored. 01579 /// This is mostly useful when flatbuffers are generated with mutation 01580 /// accessors. 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 // clang-format on 01592 01593 /// @brief Serialize an array of structs into a FlatBuffer `vector`. 01594 /// @tparam T The data type of the struct array elements. 01595 /// @param[in] f A function that takes the current iteration 0..vector_size-1, 01596 /// a pointer to the struct that must be filled and the state argument. 01597 /// @param[in] state Arbitrary state to pass to f. 01598 /// @return Returns a typed `Offset` into the serialized data indicating 01599 /// where the vector is stored. 01600 /// This is mostly useful when flatbuffers are generated with mutation 01601 /// accessors. 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 01613 /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`. 01614 /// @tparam T The data type of the `std::vector` struct elements. 01615 /// @param[in]] v A const reference to the `std::vector` of structs to 01616 /// serialize into the buffer as a `vector`. 01617 /// @return Returns a typed `Offset` into the serialized data indicating 01618 /// where the vector is stored. 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 01625 /// @brief Serialize a `std::vector` of native structs into a FlatBuffer 01626 /// `vector`. 01627 /// @tparam T The data type of the `std::vector` struct elements. 01628 /// @tparam S The data type of the `std::vector` native struct elements. 01629 /// @param[in]] v A const reference to the `std::vector` of structs to 01630 /// serialize into the buffer as a `vector`. 01631 /// @return Returns a typed `Offset` into the serialized data indicating 01632 /// where the vector is stored. 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 01639 /// @cond FLATBUFFERS_INTERNAL 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 }; 01648 /// @endcond 01649 01650 /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector` 01651 /// in sorted order. 01652 /// @tparam T The data type of the `std::vector` struct elements. 01653 /// @param[in]] v A const reference to the `std::vector` of structs to 01654 /// serialize into the buffer as a `vector`. 01655 /// @return Returns a typed `Offset` into the serialized data indicating 01656 /// where the vector is stored. 01657 template<typename T> 01658 Offset<Vector<const T *>> CreateVectorOfSortedStructs(std::vector<T> *v) { 01659 return CreateVectorOfSortedStructs(data(*v), v->size()); 01660 } 01661 01662 /// @brief Serialize a `std::vector` of native structs into a FlatBuffer 01663 /// `vector` in sorted order. 01664 /// @tparam T The data type of the `std::vector` struct elements. 01665 /// @tparam S The data type of the `std::vector` native struct elements. 01666 /// @param[in]] v A const reference to the `std::vector` of structs to 01667 /// serialize into the buffer as a `vector`. 01668 /// @return Returns a typed `Offset` into the serialized data indicating 01669 /// where the vector is stored. 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 01676 /// @brief Serialize an array of structs into a FlatBuffer `vector` in sorted 01677 /// order. 01678 /// @tparam T The data type of the struct array elements. 01679 /// @param[in] v A pointer to the array of type `T` to serialize into the 01680 /// buffer as a `vector`. 01681 /// @param[in] len The number of elements to serialize. 01682 /// @return Returns a typed `Offset` into the serialized data indicating 01683 /// where the vector is stored. 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 01690 /// @brief Serialize an array of native structs into a FlatBuffer `vector` in 01691 /// sorted order. 01692 /// @tparam T The data type of the struct array elements. 01693 /// @tparam S The data type of the native struct array elements. 01694 /// @param[in] v A pointer to the array of type `S` to serialize into the 01695 /// buffer as a `vector`. 01696 /// @param[in] len The number of elements to serialize. 01697 /// @return Returns a typed `Offset` into the serialized data indicating 01698 /// where the vector is stored. 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 01709 /// @cond FLATBUFFERS_INTERNAL 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 }; 01722 /// @endcond 01723 01724 /// @brief Serialize an array of `table` offsets as a `vector` in the buffer 01725 /// in sorted order. 01726 /// @tparam T The data type that the offset refers to. 01727 /// @param[in] v An array of type `Offset<T>` that contains the `table` 01728 /// offsets to store in the buffer in sorted order. 01729 /// @param[in] len The number of elements to store in the `vector`. 01730 /// @return Returns a typed `Offset` into the serialized data indicating 01731 /// where the vector is stored. 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 01739 /// @brief Serialize an array of `table` offsets as a `vector` in the buffer 01740 /// in sorted order. 01741 /// @tparam T The data type that the offset refers to. 01742 /// @param[in] v An array of type `Offset<T>` that contains the `table` 01743 /// offsets to store in the buffer in sorted order. 01744 /// @return Returns a typed `Offset` into the serialized data indicating 01745 /// where the vector is stored. 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 01752 /// @brief Specialized version of `CreateVector` for non-copying use cases. 01753 /// Write the data any time later to the returned buffer pointer `buf`. 01754 /// @param[in] len The number of elements to store in the `vector`. 01755 /// @param[in] elemsize The size of each element in the `vector`. 01756 /// @param[out] buf A pointer to a `uint8_t` pointer that can be 01757 /// written to at a later time to serialize the data into a `vector` 01758 /// in the buffer. 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 01770 /// @brief Specialized version of `CreateVector` for non-copying use cases. 01771 /// Write the data any time later to the returned buffer pointer `buf`. 01772 /// @tparam T The data type of the data that will be stored in the buffer 01773 /// as a `vector`. 01774 /// @param[in] len The number of elements to store in the `vector`. 01775 /// @param[out] buf A pointer to a pointer of type `T` that can be 01776 /// written to at a later time to serialize the data into a `vector` 01777 /// in the buffer. 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 // @brief Create a vector of scalar type T given as input a vector of scalar 01793 // type U, useful with e.g. pre "enum class" enums, or any existing scalar 01794 // data of the wrong type. 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 01804 /// @brief Write a struct by itself, typically to be part of a union. 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 01812 /// @brief The length of a FlatBuffer file header. 01813 static const size_t kFileIdentifierLength = 4; 01814 01815 /// @brief Finish serializing a buffer by writing the root offset. 01816 /// @param[in] file_identifier If a `file_identifier` is given, the buffer 01817 /// will be prefixed with a standard FlatBuffers file header. 01818 template<typename T> 01819 void Finish(Offset<T> root, const char *file_identifier = nullptr) { 01820 Finish(root.o, file_identifier, false); 01821 } 01822 01823 /// @brief Finish a buffer with a 32 bit size field pre-fixed (size of the 01824 /// buffer following the size field). These buffers are NOT compatible 01825 /// with standard buffers created by Finish, i.e. you can't call GetRoot 01826 /// on them, you have to use GetSizePrefixedRoot instead. 01827 /// All >32 bit quantities in this buffer will be aligned when the whole 01828 /// size pre-fixed buffer is aligned. 01829 /// These kinds of buffers are useful for creating a stream of FlatBuffers. 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 // You shouldn't really be copying instances of this class. 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 // This will cause the whole buffer to be aligned. 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)); // Location of 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 // Accumulating offsets of table members while it is being built. 01871 // We store these in the scratch pad of buf_, after the vtable offsets. 01872 uoffset_t num_field_loc; 01873 // Track how much of the vtable is in use, so we can output the most compact 01874 // possible vtable. 01875 voffset_t max_voffset_; 01876 01877 // Ensure objects are not nested. 01878 bool nested; 01879 01880 // Ensure the buffer is finished before it is being accessed. 01881 bool finished; 01882 01883 size_t minalign_; 01884 01885 bool force_defaults_; // Serialize values equal to their defaults anyway. 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 // For use with CreateSharedString. Instantiated on first use only. 01901 typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap; 01902 StringOffsetMap *string_pool; 01903 01904 private: 01905 // Allocates space for a vector of structures. 01906 // Must be completed with EndVectorOfStructs(). 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 // End the vector of structues in the flatbuffers. 01913 // Vector should have previously be started with StartVectorOfStructs(). 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 }; 01919 /// @} 01920 01921 /// @cond FLATBUFFERS_INTERNAL 01922 // Helpers to get a typed pointer to the root object contained in the buffer. 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 01938 /// Helpers to get a typed pointer to objects that are currently being built. 01939 /// @warning Creating new objects will lead to reallocations and invalidates 01940 /// the pointer! 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 01952 /// @brief Get a pointer to the the file_identifier section of the buffer. 01953 /// @return Returns a const char pointer to the start of the file_identifier 01954 /// characters in the buffer. The returned char * has length 01955 /// 'flatbuffers::FlatBufferBuilder::kFileIdentifierLength'. 01956 /// This function is UNDEFINED for FlatBuffers whose schema does not include 01957 /// a file_identifier (likely points at padding or the start of a the root 01958 /// vtable). 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 // Helper to see if the identifier in a buffer has the expected value. 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 // Helper class to verify the integrity of a FlatBuffer 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 upper_bound_(0), 01982 check_alignment_(_check_alignment) 01983 { 01984 FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE); 01985 } 01986 01987 // Central location where any verification failures register. 01988 bool Check(bool ok) const { 01989 // clang-format off 01990 #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE 01991 FLATBUFFERS_ASSERT(ok); 01992 #endif 01993 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE 01994 if (!ok) 01995 upper_bound_ = 0; 01996 #endif 01997 // clang-format on 01998 return ok; 01999 } 02000 02001 // Verify any range within the buffer. 02002 bool Verify(size_t elem, size_t elem_len) const { 02003 // clang-format off 02004 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE 02005 auto upper_bound = elem + elem_len; 02006 if (upper_bound_ < upper_bound) 02007 upper_bound_ = upper_bound; 02008 #endif 02009 // clang-format on 02010 return Check(elem_len < size_ && elem <= size_ - elem_len); 02011 } 02012 02013 template<typename T> bool VerifyAlignment(size_t elem) const { 02014 return (elem & (sizeof(T) - 1)) == 0 || !check_alignment_; 02015 } 02016 02017 // Verify a range indicated by sizeof(T). 02018 template<typename T> bool Verify(size_t elem) const { 02019 return VerifyAlignment<T>(elem) && Verify(elem, sizeof(T)); 02020 } 02021 02022 // Verify relative to a known-good base pointer. 02023 bool Verify(const uint8_t *base, voffset_t elem_off, size_t elem_len) const { 02024 return Verify(static_cast<size_t>(base - buf_) + elem_off, elem_len); 02025 } 02026 02027 template<typename T> bool Verify(const uint8_t *base, voffset_t elem_off) 02028 const { 02029 return Verify(static_cast<size_t>(base - buf_) + elem_off, sizeof(T)); 02030 } 02031 02032 // Verify a pointer (may be NULL) of a table type. 02033 template<typename T> bool VerifyTable(const T *table) { 02034 return !table || table->Verify(*this); 02035 } 02036 02037 // Verify a pointer (may be NULL) of any vector type. 02038 template<typename T> bool VerifyVector(const Vector<T> *vec) const { 02039 return !vec || VerifyVectorOrString(reinterpret_cast<const uint8_t *>(vec), 02040 sizeof(T)); 02041 } 02042 02043 // Verify a pointer (may be NULL) of a vector to struct. 02044 template<typename T> bool VerifyVector(const Vector<const T *> *vec) const { 02045 return VerifyVector(reinterpret_cast<const Vector<T> *>(vec)); 02046 } 02047 02048 // Verify a pointer (may be NULL) to string. 02049 bool VerifyString(const String *str) const { 02050 size_t end; 02051 return !str || 02052 (VerifyVectorOrString(reinterpret_cast<const uint8_t *>(str), 02053 1, &end) && 02054 Verify(end, 1) && // Must have terminator 02055 Check(buf_[end] == '\0')); // Terminating byte must be 0. 02056 } 02057 02058 // Common code between vectors and strings. 02059 bool VerifyVectorOrString(const uint8_t *vec, size_t elem_size, 02060 size_t *end = nullptr) const { 02061 auto veco = static_cast<size_t>(vec - buf_); 02062 // Check we can read the size field. 02063 if (!Verify<uoffset_t>(veco)) return false; 02064 // Check the whole array. If this is a string, the byte past the array 02065 // must be 0. 02066 auto size = ReadScalar<uoffset_t>(vec); 02067 auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size; 02068 if (!Check(size < max_elems)) 02069 return false; // Protect against byte_size overflowing. 02070 auto byte_size = sizeof(size) + elem_size * size; 02071 if (end) *end = veco + byte_size; 02072 return Verify(veco, byte_size); 02073 } 02074 02075 // Special case for string contents, after the above has been called. 02076 bool VerifyVectorOfStrings(const Vector<Offset<String>> *vec) const { 02077 if (vec) { 02078 for (uoffset_t i = 0; i < vec->size(); i++) { 02079 if (!VerifyString(vec->Get(i))) return false; 02080 } 02081 } 02082 return true; 02083 } 02084 02085 // Special case for table contents, after the above has been called. 02086 template<typename T> bool VerifyVectorOfTables(const Vector<Offset<T>> *vec) { 02087 if (vec) { 02088 for (uoffset_t i = 0; i < vec->size(); i++) { 02089 if (!vec->Get(i)->Verify(*this)) return false; 02090 } 02091 } 02092 return true; 02093 } 02094 02095 bool VerifyTableStart(const uint8_t *table) { 02096 // Check the vtable offset. 02097 auto tableo = static_cast<size_t>(table - buf_); 02098 if (!Verify<soffset_t>(tableo)) return false; 02099 // This offset may be signed, but doing the substraction unsigned always 02100 // gives the result we want. 02101 auto vtableo = tableo - static_cast<size_t>(ReadScalar<soffset_t>(table)); 02102 // Check the vtable size field, then check vtable fits in its entirety. 02103 return VerifyComplexity() && Verify<voffset_t>(vtableo) && 02104 VerifyAlignment<voffset_t>(ReadScalar<voffset_t>(buf_ + vtableo)) && 02105 Verify(vtableo, ReadScalar<voffset_t>(buf_ + vtableo)); 02106 } 02107 02108 template<typename T> 02109 bool VerifyBufferFromStart(const char *identifier, size_t start) { 02110 if (identifier && 02111 (size_ < 2 * sizeof(flatbuffers::uoffset_t) || 02112 !BufferHasIdentifier(buf_ + start, identifier))) { 02113 return false; 02114 } 02115 02116 // Call T::Verify, which must be in the generated code for this type. 02117 auto o = VerifyOffset(start); 02118 return o && reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this) 02119 // clang-format off 02120 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE 02121 && GetComputedSize() 02122 #endif 02123 ; 02124 // clang-format on 02125 } 02126 02127 // Verify this whole buffer, starting with root type T. 02128 template<typename T> bool VerifyBuffer() { return VerifyBuffer<T>(nullptr); } 02129 02130 template<typename T> bool VerifyBuffer(const char *identifier) { 02131 return VerifyBufferFromStart<T>(identifier, 0); 02132 } 02133 02134 template<typename T> bool VerifySizePrefixedBuffer(const char *identifier) { 02135 return Verify<uoffset_t>(0U) && 02136 ReadScalar<uoffset_t>(buf_) == size_ - sizeof(uoffset_t) && 02137 VerifyBufferFromStart<T>(identifier, sizeof(uoffset_t)); 02138 } 02139 02140 uoffset_t VerifyOffset(size_t start) const { 02141 if (!Verify<uoffset_t>(start)) return 0; 02142 auto o = ReadScalar<uoffset_t>(buf_ + start); 02143 // May not point to itself. 02144 if (!Check(o != 0)) return 0; 02145 // Can't wrap around / buffers are max 2GB. 02146 if (!Check(static_cast<soffset_t>(o) >= 0)) return 0; 02147 // Must be inside the buffer to create a pointer from it (pointer outside 02148 // buffer is UB). 02149 if (!Verify(start + o, 1)) return 0; 02150 return o; 02151 } 02152 02153 uoffset_t VerifyOffset(const uint8_t *base, voffset_t start) const { 02154 return VerifyOffset(static_cast<size_t>(base - buf_) + start); 02155 } 02156 02157 // Called at the start of a table to increase counters measuring data 02158 // structure depth and amount, and possibly bails out with false if 02159 // limits set by the constructor have been hit. Needs to be balanced 02160 // with EndTable(). 02161 bool VerifyComplexity() { 02162 depth_++; 02163 num_tables_++; 02164 return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_); 02165 } 02166 02167 // Called at the end of a table to pop the depth count. 02168 bool EndTable() { 02169 depth_--; 02170 return true; 02171 } 02172 02173 // Returns the message size in bytes 02174 size_t GetComputedSize() const { 02175 // clang-format off 02176 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE 02177 uintptr_t size = upper_bound_; 02178 // Align the size to uoffset_t 02179 size = (size - 1 + sizeof(uoffset_t)) & ~(sizeof(uoffset_t) - 1); 02180 return (size > size_) ? 0 : size; 02181 #else 02182 // Must turn on FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE for this to work. 02183 (void)upper_bound_; 02184 FLATBUFFERS_ASSERT(false); 02185 return 0; 02186 #endif 02187 // clang-format on 02188 } 02189 02190 private: 02191 const uint8_t *buf_; 02192 size_t size_; 02193 uoffset_t depth_; 02194 uoffset_t max_depth_; 02195 uoffset_t num_tables_; 02196 uoffset_t max_tables_; 02197 mutable size_t upper_bound_; 02198 bool check_alignment_; 02199 }; 02200 02201 // Convenient way to bundle a buffer and its length, to pass it around 02202 // typed by its root. 02203 // A BufferRef does not own its buffer. 02204 struct BufferRefBase {}; // for std::is_base_of 02205 template<typename T> struct BufferRef : BufferRefBase { 02206 BufferRef() : buf(nullptr), len(0), must_free(false) {} 02207 BufferRef(uint8_t *_buf, uoffset_t _len) 02208 : buf(_buf), len(_len), must_free(false) {} 02209 02210 ~BufferRef() { 02211 if (must_free) free(buf); 02212 } 02213 02214 const T *GetRoot() const { return flatbuffers::GetRoot<T>(buf); } 02215 02216 bool Verify() { 02217 Verifier verifier(buf, len); 02218 return verifier.VerifyBuffer<T>(nullptr); 02219 } 02220 02221 uint8_t *buf; 02222 uoffset_t len; 02223 bool must_free; 02224 }; 02225 02226 // "structs" are flat structures that do not have an offset table, thus 02227 // always have all members present and do not support forwards/backwards 02228 // compatible extensions. 02229 02230 class Struct FLATBUFFERS_FINAL_CLASS { 02231 public: 02232 template<typename T> T GetField(uoffset_t o) const { 02233 return ReadScalar<T>(&data_[o]); 02234 } 02235 02236 template<typename T> T GetStruct(uoffset_t o) const { 02237 return reinterpret_cast<T>(&data_[o]); 02238 } 02239 02240 const uint8_t *GetAddressOf(uoffset_t o) const { return &data_[o]; } 02241 uint8_t *GetAddressOf(uoffset_t o) { return &data_[o]; } 02242 02243 private: 02244 uint8_t data_[1]; 02245 }; 02246 02247 // "tables" use an offset table (possibly shared) that allows fields to be 02248 // omitted and added at will, but uses an extra indirection to read. 02249 class Table { 02250 public: 02251 const uint8_t *GetVTable() const { 02252 return data_ - ReadScalar<soffset_t>(data_); 02253 } 02254 02255 // This gets the field offset for any of the functions below it, or 0 02256 // if the field was not present. 02257 voffset_t GetOptionalFieldOffset(voffset_t field) const { 02258 // The vtable offset is always at the start. 02259 auto vtable = GetVTable(); 02260 // The first element is the size of the vtable (fields + type id + itself). 02261 auto vtsize = ReadScalar<voffset_t>(vtable); 02262 // If the field we're accessing is outside the vtable, we're reading older 02263 // data, so it's the same as if the offset was 0 (not present). 02264 return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0; 02265 } 02266 02267 template<typename T> T GetField(voffset_t field, T defaultval) const { 02268 auto field_offset = GetOptionalFieldOffset(field); 02269 return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval; 02270 } 02271 02272 template<typename P> P GetPointer(voffset_t field) { 02273 auto field_offset = GetOptionalFieldOffset(field); 02274 auto p = data_ + field_offset; 02275 return field_offset ? reinterpret_cast<P>(p + ReadScalar<uoffset_t>(p)) 02276 : nullptr; 02277 } 02278 template<typename P> P GetPointer(voffset_t field) const { 02279 return const_cast<Table *>(this)->GetPointer<P>(field); 02280 } 02281 02282 template<typename P> P GetStruct(voffset_t field) const { 02283 auto field_offset = GetOptionalFieldOffset(field); 02284 auto p = const_cast<uint8_t *>(data_ + field_offset); 02285 return field_offset ? reinterpret_cast<P>(p) : nullptr; 02286 } 02287 02288 template<typename T> bool SetField(voffset_t field, T val, T def) { 02289 auto field_offset = GetOptionalFieldOffset(field); 02290 if (!field_offset) return IsTheSameAs(val, def); 02291 WriteScalar(data_ + field_offset, val); 02292 return true; 02293 } 02294 02295 bool SetPointer(voffset_t field, const uint8_t *val) { 02296 auto field_offset = GetOptionalFieldOffset(field); 02297 if (!field_offset) return false; 02298 WriteScalar(data_ + field_offset, 02299 static_cast<uoffset_t>(val - (data_ + field_offset))); 02300 return true; 02301 } 02302 02303 uint8_t *GetAddressOf(voffset_t field) { 02304 auto field_offset = GetOptionalFieldOffset(field); 02305 return field_offset ? data_ + field_offset : nullptr; 02306 } 02307 const uint8_t *GetAddressOf(voffset_t field) const { 02308 return const_cast<Table *>(this)->GetAddressOf(field); 02309 } 02310 02311 bool CheckField(voffset_t field) const { 02312 return GetOptionalFieldOffset(field) != 0; 02313 } 02314 02315 // Verify the vtable of this table. 02316 // Call this once per table, followed by VerifyField once per field. 02317 bool VerifyTableStart(Verifier &verifier) const { 02318 return verifier.VerifyTableStart(data_); 02319 } 02320 02321 // Verify a particular field. 02322 template<typename T> 02323 bool VerifyField(const Verifier &verifier, voffset_t field) const { 02324 // Calling GetOptionalFieldOffset should be safe now thanks to 02325 // VerifyTable(). 02326 auto field_offset = GetOptionalFieldOffset(field); 02327 // Check the actual field. 02328 return !field_offset || verifier.Verify<T>(data_, field_offset); 02329 } 02330 02331 // VerifyField for required fields. 02332 template<typename T> 02333 bool VerifyFieldRequired(const Verifier &verifier, voffset_t field) const { 02334 auto field_offset = GetOptionalFieldOffset(field); 02335 return verifier.Check(field_offset != 0) && 02336 verifier.Verify<T>(data_, field_offset); 02337 } 02338 02339 // Versions for offsets. 02340 bool VerifyOffset(const Verifier &verifier, voffset_t field) const { 02341 auto field_offset = GetOptionalFieldOffset(field); 02342 return !field_offset || verifier.VerifyOffset(data_, field_offset); 02343 } 02344 02345 bool VerifyOffsetRequired(const Verifier &verifier, voffset_t field) const { 02346 auto field_offset = GetOptionalFieldOffset(field); 02347 return verifier.Check(field_offset != 0) && 02348 verifier.VerifyOffset(data_, field_offset); 02349 } 02350 02351 private: 02352 // private constructor & copy constructor: you obtain instances of this 02353 // class by pointing to existing data only 02354 Table(); 02355 Table(const Table &other); 02356 02357 uint8_t data_[1]; 02358 }; 02359 02360 template<typename T> void FlatBufferBuilder::Required(Offset<T> table, 02361 voffset_t field) { 02362 auto table_ptr = reinterpret_cast<const Table *>(buf_.data_at(table.o)); 02363 bool ok = table_ptr->GetOptionalFieldOffset(field) != 0; 02364 // If this fails, the caller will show what field needs to be set. 02365 FLATBUFFERS_ASSERT(ok); 02366 (void)ok; 02367 } 02368 02369 /// @brief This can compute the start of a FlatBuffer from a root pointer, i.e. 02370 /// it is the opposite transformation of GetRoot(). 02371 /// This may be useful if you want to pass on a root and have the recipient 02372 /// delete the buffer afterwards. 02373 inline const uint8_t *GetBufferStartFromRootPointer(const void *root) { 02374 auto table = reinterpret_cast<const Table *>(root); 02375 auto vtable = table->GetVTable(); 02376 // Either the vtable is before the root or after the root. 02377 auto start = (std::min)(vtable, reinterpret_cast<const uint8_t *>(root)); 02378 // Align to at least sizeof(uoffset_t). 02379 start = reinterpret_cast<const uint8_t *>(reinterpret_cast<uintptr_t>(start) & 02380 ~(sizeof(uoffset_t) - 1)); 02381 // Additionally, there may be a file_identifier in the buffer, and the root 02382 // offset. The buffer may have been aligned to any size between 02383 // sizeof(uoffset_t) and FLATBUFFERS_MAX_ALIGNMENT (see "force_align"). 02384 // Sadly, the exact alignment is only known when constructing the buffer, 02385 // since it depends on the presence of values with said alignment properties. 02386 // So instead, we simply look at the next uoffset_t values (root, 02387 // file_identifier, and alignment padding) to see which points to the root. 02388 // None of the other values can "impersonate" the root since they will either 02389 // be 0 or four ASCII characters. 02390 static_assert(FlatBufferBuilder::kFileIdentifierLength == sizeof(uoffset_t), 02391 "file_identifier is assumed to be the same size as uoffset_t"); 02392 for (auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT / sizeof(uoffset_t) + 1; 02393 possible_roots; possible_roots--) { 02394 start -= sizeof(uoffset_t); 02395 if (ReadScalar<uoffset_t>(start) + start == 02396 reinterpret_cast<const uint8_t *>(root)) 02397 return start; 02398 } 02399 // We didn't find the root, either the "root" passed isn't really a root, 02400 // or the buffer is corrupt. 02401 // Assert, because calling this function with bad data may cause reads 02402 // outside of buffer boundaries. 02403 FLATBUFFERS_ASSERT(false); 02404 return nullptr; 02405 } 02406 02407 /// @brief This return the prefixed size of a FlatBuffer. 02408 inline uoffset_t GetPrefixedSize(const uint8_t* buf){ return ReadScalar<uoffset_t>(buf); } 02409 02410 // Base class for native objects (FlatBuffer data de-serialized into native 02411 // C++ data structures). 02412 // Contains no functionality, purely documentative. 02413 struct NativeTable {}; 02414 02415 /// @brief Function types to be used with resolving hashes into objects and 02416 /// back again. The resolver gets a pointer to a field inside an object API 02417 /// object that is of the type specified in the schema using the attribute 02418 /// `cpp_type` (it is thus important whatever you write to this address 02419 /// matches that type). The value of this field is initially null, so you 02420 /// may choose to implement a delayed binding lookup using this function 02421 /// if you wish. The resolver does the opposite lookup, for when the object 02422 /// is being serialized again. 02423 typedef uint64_t hash_value_t; 02424 // clang-format off 02425 #ifdef FLATBUFFERS_CPP98_STL 02426 typedef void (*resolver_function_t)(void **pointer_adr, hash_value_t hash); 02427 typedef hash_value_t (*rehasher_function_t)(void *pointer); 02428 #else 02429 typedef std::function<void (void **pointer_adr, hash_value_t hash)> 02430 resolver_function_t; 02431 typedef std::function<hash_value_t (void *pointer)> rehasher_function_t; 02432 #endif 02433 // clang-format on 02434 02435 // Helper function to test if a field is present, using any of the field 02436 // enums in the generated code. 02437 // `table` must be a generated table type. Since this is a template parameter, 02438 // this is not typechecked to be a subclass of Table, so beware! 02439 // Note: this function will return false for fields equal to the default 02440 // value, since they're not stored in the buffer (unless force_defaults was 02441 // used). 02442 template<typename T> 02443 bool IsFieldPresent(const T *table, typename T::FlatBuffersVTableOffset field) { 02444 // Cast, since Table is a private baseclass of any table types. 02445 return reinterpret_cast<const Table *>(table)->CheckField( 02446 static_cast<voffset_t>(field)); 02447 } 02448 02449 // Utility function for reverse lookups on the EnumNames*() functions 02450 // (in the generated C++ code) 02451 // names must be NULL terminated. 02452 inline int LookupEnum(const char **names, const char *name) { 02453 for (const char **p = names; *p; p++) 02454 if (!strcmp(*p, name)) return static_cast<int>(p - names); 02455 return -1; 02456 } 02457 02458 // These macros allow us to layout a struct with a guarantee that they'll end 02459 // up looking the same on different compilers and platforms. 02460 // It does this by disallowing the compiler to do any padding, and then 02461 // does padding itself by inserting extra padding fields that make every 02462 // element aligned to its own size. 02463 // Additionally, it manually sets the alignment of the struct as a whole, 02464 // which is typically its largest element, or a custom size set in the schema 02465 // by the force_align attribute. 02466 // These are used in the generated code only. 02467 02468 // clang-format off 02469 #if defined(_MSC_VER) 02470 #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \ 02471 __pragma(pack(1)) \ 02472 struct __declspec(align(alignment)) 02473 #define FLATBUFFERS_STRUCT_END(name, size) \ 02474 __pragma(pack()) \ 02475 static_assert(sizeof(name) == size, "compiler breaks packing rules") 02476 #elif defined(__GNUC__) || defined(__clang__) 02477 #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \ 02478 _Pragma("pack(1)") \ 02479 struct __attribute__((aligned(alignment))) 02480 #define FLATBUFFERS_STRUCT_END(name, size) \ 02481 _Pragma("pack()") \ 02482 static_assert(sizeof(name) == size, "compiler breaks packing rules") 02483 #else 02484 #error Unknown compiler, please define structure alignment macros 02485 #endif 02486 // clang-format on 02487 02488 // Minimal reflection via code generation. 02489 // Besides full-fat reflection (see reflection.h) and parsing/printing by 02490 // loading schemas (see idl.h), we can also have code generation for mimimal 02491 // reflection data which allows pretty-printing and other uses without needing 02492 // a schema or a parser. 02493 // Generate code with --reflect-types (types only) or --reflect-names (names 02494 // also) to enable. 02495 // See minireflect.h for utilities using this functionality. 02496 02497 // These types are organized slightly differently as the ones in idl.h. 02498 enum SequenceType { ST_TABLE, ST_STRUCT, ST_UNION, ST_ENUM }; 02499 02500 // Scalars have the same order as in idl.h 02501 // clang-format off 02502 #define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \ 02503 ET(ET_UTYPE) \ 02504 ET(ET_BOOL) \ 02505 ET(ET_CHAR) \ 02506 ET(ET_UCHAR) \ 02507 ET(ET_SHORT) \ 02508 ET(ET_USHORT) \ 02509 ET(ET_INT) \ 02510 ET(ET_UINT) \ 02511 ET(ET_LONG) \ 02512 ET(ET_ULONG) \ 02513 ET(ET_FLOAT) \ 02514 ET(ET_DOUBLE) \ 02515 ET(ET_STRING) \ 02516 ET(ET_SEQUENCE) // See SequenceType. 02517 02518 enum ElementaryType { 02519 #define FLATBUFFERS_ET(E) E, 02520 FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET) 02521 #undef FLATBUFFERS_ET 02522 }; 02523 02524 inline const char * const *ElementaryTypeNames() { 02525 static const char * const names[] = { 02526 #define FLATBUFFERS_ET(E) #E, 02527 FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET) 02528 #undef FLATBUFFERS_ET 02529 }; 02530 return names; 02531 } 02532 // clang-format on 02533 02534 // Basic type info cost just 16bits per field! 02535 struct TypeCode { 02536 uint16_t base_type : 4; // ElementaryType 02537 uint16_t is_vector : 1; 02538 int16_t sequence_ref : 11; // Index into type_refs below, or -1 for none. 02539 }; 02540 02541 static_assert(sizeof(TypeCode) == 2, "TypeCode"); 02542 02543 struct TypeTable; 02544 02545 // Signature of the static method present in each type. 02546 typedef const TypeTable *(*TypeFunction)(); 02547 02548 struct TypeTable { 02549 SequenceType st; 02550 size_t num_elems; // of type_codes, values, names (but not type_refs). 02551 const TypeCode *type_codes; // num_elems count 02552 const TypeFunction *type_refs; // less than num_elems entries (see TypeCode). 02553 const int64_t *values; // Only set for non-consecutive enum/union or structs. 02554 const char * const *names; // Only set if compiled with --reflect-names. 02555 }; 02556 02557 // String which identifies the current version of FlatBuffers. 02558 // flatbuffer_version_string is used by Google developers to identify which 02559 // applications uploaded to Google Play are using this library. This allows 02560 // the development team at Google to determine the popularity of the library. 02561 // How it works: Applications that are uploaded to the Google Play Store are 02562 // scanned for this version string. We track which applications are using it 02563 // to measure popularity. You are free to remove it (of course) but we would 02564 // appreciate if you left it in. 02565 02566 // Weak linkage is culled by VS & doesn't work on cygwin. 02567 // clang-format off 02568 #if !defined(_WIN32) && !defined(__CYGWIN__) 02569 02570 extern volatile __attribute__((weak)) const char *flatbuffer_version_string; 02571 volatile __attribute__((weak)) const char *flatbuffer_version_string = 02572 "FlatBuffers " 02573 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "." 02574 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "." 02575 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION); 02576 02577 #endif // !defined(_WIN32) && !defined(__CYGWIN__) 02578 02579 #define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\ 02580 inline E operator | (E lhs, E rhs){\ 02581 return E(T(lhs) | T(rhs));\ 02582 }\ 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){\ 02590 return E(~T(lhs));\ 02591 }\ 02592 inline E operator |= (E &lhs, E rhs){\ 02593 lhs = lhs | rhs;\ 02594 return lhs;\ 02595 }\ 02596 inline E operator &= (E &lhs, E rhs){\ 02597 lhs = lhs & rhs;\ 02598 return lhs;\ 02599 }\ 02600 inline E operator ^= (E &lhs, E rhs){\ 02601 lhs = lhs ^ rhs;\ 02602 return lhs;\ 02603 }\ 02604 inline bool operator !(E rhs) \ 02605 {\ 02606 return !bool(T(rhs)); \ 02607 } 02608 /// @endcond 02609 } // namespace flatbuffers 02610 02611 // clang-format on 02612 02613 #endif // FLATBUFFERS_H_
Generated on Wed Jul 13 2022 16:03:35 by
1.7.2