17 #ifndef FLATBUFFERS_H_
18 #define FLATBUFFERS_H_
20 #include "flatbuffers/base.h"
28 Offset(uoffset_t _o) : o(_o) {}
30 bool IsNull()
const {
return !o; }
33 inline void EndianCheck() {
36 assert(*reinterpret_cast<char *>(&endiantest) == FLATBUFFERS_LITTLEENDIAN);
40 template<
typename T> T EndianSwap(T t) {
42 #define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
43 #define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
44 #define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
46 #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408
48 #define FLATBUFFERS_BYTESWAP16(x) \
49 static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16))
51 #define FLATBUFFERS_BYTESWAP16 __builtin_bswap16
53 #define FLATBUFFERS_BYTESWAP32 __builtin_bswap32
54 #define FLATBUFFERS_BYTESWAP64 __builtin_bswap64
58 }
else if (
sizeof(T) == 2) {
59 auto r = FLATBUFFERS_BYTESWAP16(*reinterpret_cast<uint16_t *>(&t));
60 return *
reinterpret_cast<T *
>(&r);
61 }
else if (
sizeof(T) == 4) {
62 auto r = FLATBUFFERS_BYTESWAP32(*reinterpret_cast<uint32_t *>(&t));
63 return *
reinterpret_cast<T *
>(&r);
64 }
else if (
sizeof(T) == 8) {
65 auto r = FLATBUFFERS_BYTESWAP64(*reinterpret_cast<uint64_t *>(&t));
66 return *
reinterpret_cast<T *
>(&r);
72 template<
typename T> FLATBUFFERS_CONSTEXPR
size_t AlignOf() {
77 return __alignof__(T);
93 typedef T return_type;
94 typedef T mutable_return_type;
95 static const size_t element_stride =
sizeof(T);
96 static return_type Read(
const uint8_t *p, uoffset_t i) {
97 return EndianScalar((reinterpret_cast<const T *>(p))[i]);
101 typedef const T *return_type;
102 typedef T *mutable_return_type;
103 static const size_t element_stride =
sizeof(uoffset_t);
104 static return_type Read(
const uint8_t *p, uoffset_t i) {
105 p += i *
sizeof(uoffset_t);
106 return reinterpret_cast<return_type
>(p + ReadScalar<uoffset_t>(p));
110 typedef const T *return_type;
111 typedef T *mutable_return_type;
112 static const size_t element_stride =
sizeof(T);
113 static return_type Read(
const uint8_t *p, uoffset_t i) {
114 return reinterpret_cast<const T *
>(p + i *
sizeof(T));
120 template<
typename T,
typename IT>
122 typedef std::random_access_iterator_tag iterator_category;
123 typedef IT value_type;
124 typedef uoffset_t difference_type;
126 typedef IT &reference;
143 return data_ == other.data_;
147 return data_ < other.data_;
151 return data_ != other.data_;
158 IT operator *()
const {
162 IT operator->()
const {
207 const uint8_t *data_;
221 uoffset_t size()
const {
return EndianScalar(length_); }
224 uoffset_t Length()
const {
return size(); }
226 typedef typename IndirectHelper<T>::return_type return_type;
227 typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
229 return_type Get(uoffset_t i)
const {
234 return_type operator[](uoffset_t i)
const {
return Get(i); }
239 template<
typename E> E GetEnum(uoffset_t i)
const {
240 return static_cast<E
>(Get(i));
245 template<
typename U>
const U *GetAs(uoffset_t i)
const {
246 return reinterpret_cast<const U *
>(Get(i));
251 const String *GetAsString(uoffset_t i)
const {
252 return reinterpret_cast<const String *
>(Get(i));
255 const void *GetStructFromOffset(
size_t o)
const {
256 return reinterpret_cast<const void *
>(Data() + o);
259 iterator begin() {
return iterator(Data(), 0); }
260 const_iterator begin()
const {
return const_iterator(Data(), 0); }
262 iterator end() {
return iterator(Data(), size()); }
263 const_iterator end()
const {
return const_iterator(Data(), size()); }
267 void Mutate(uoffset_t i,
const T& val) {
269 WriteScalar(data() + i, val);
275 void MutateOffset(uoffset_t i,
const uint8_t *val) {
277 assert(
sizeof(T) ==
sizeof(uoffset_t));
278 WriteScalar(data() + i,
279 static_cast<uoffset_t>(val - (Data() + i *
sizeof(uoffset_t))));
283 mutable_return_type GetMutableObject(uoffset_t i)
const {
289 const uint8_t *Data()
const {
290 return reinterpret_cast<const uint8_t *
>(&length_ + 1);
294 return reinterpret_cast<uint8_t *
>(&length_ + 1);
298 const T *data()
const {
return reinterpret_cast<const T *
>(Data()); }
299 T *data() {
return reinterpret_cast<T *
>(Data()); }
301 template<
typename K> return_type LookupByKey(K key)
const {
302 void *search_result = std::bsearch(&key, Data(), size(),
305 if (!search_result) {
309 const uint8_t *element =
reinterpret_cast<const uint8_t *
>(search_result);
326 template<
typename K>
static int KeyCompare(
const void *ap,
const void *bp) {
327 const K *key =
reinterpret_cast<const K *
>(ap);
328 const uint8_t *data =
reinterpret_cast<const uint8_t *
>(bp);
333 return -table->KeyCompareWithValue(*key);
341 uoffset_t size()
const {
return EndianScalar(length_); }
343 const uint8_t *Data()
const {
344 return reinterpret_cast<const uint8_t *
>(&length_ + 1);
347 return reinterpret_cast<uint8_t *
>(&length_ + 1);
358 #ifndef FLATBUFFERS_CPP98_STL
359 template<
typename T,
typename U>
361 static_assert(std::is_base_of<T, U>::value,
"Unrelated types");
365 template<
typename T,
typename U>
366 const Vector<Offset<T>> *VectorCast(
const Vector<Offset<U>> *ptr) {
367 static_assert(std::is_base_of<T, U>::value,
"Unrelated types");
368 return reinterpret_cast<const Vector<Offset<T>
> *>(ptr);
374 template<
typename T>
static inline size_t VectorLength(
const Vector<T> *v) {
375 return v ? v->Length() : 0;
379 const char *c_str()
const {
return reinterpret_cast<const char *
>(Data()); }
380 std::string str()
const {
return std::string(c_str(), Length()); }
382 bool operator <(
const String &o)
const {
383 return strcmp(c_str(), o.c_str()) < 0;
394 virtual uint8_t *allocate(
size_t size) = 0;
397 virtual void deallocate(uint8_t *p,
size_t size) = 0;
402 virtual uint8_t *reallocate_downward(uint8_t *old_p,
size_t old_size,
404 assert(new_size > old_size);
405 uint8_t *new_p = allocate(new_size);
406 memcpy(new_p + (new_size - old_size), old_p, old_size);
407 deallocate(old_p, old_size);
415 virtual uint8_t *allocate(
size_t size) FLATBUFFERS_OVERRIDE {
416 return new uint8_t[size];
419 virtual void deallocate(uint8_t *p,
size_t) FLATBUFFERS_OVERRIDE {
434 DetachedBuffer() : allocator_(
nullptr), own_allocator_(
false), buf_(
nullptr),
435 reserved_(0), cur_(
nullptr), size_(0) {}
438 size_t reserved, uint8_t *cur,
size_t sz)
439 : allocator_(allocator), own_allocator_(own_allocator), buf_(buf),
440 reserved_(reserved), cur_(cur), size_(sz) {
445 : allocator_(other.allocator_), own_allocator_(other.own_allocator_),
446 buf_(other.buf_), reserved_(other.reserved_), cur_(other.cur_),
448 other.allocator_ =
nullptr;
449 other.own_allocator_ =
false;
450 other.buf_ =
nullptr;
452 other.cur_ =
nullptr;
457 std::swap(allocator_, other.allocator_);
458 std::swap(own_allocator_, other.own_allocator_);
459 std::swap(buf_, other.buf_);
460 std::swap(reserved_, other.reserved_);
461 std::swap(cur_, other.cur_);
462 std::swap(size_, other.size_);
469 allocator_->deallocate(buf_, reserved_);
471 if (own_allocator_ && allocator_) {
476 const uint8_t *data()
const {
484 size_t size()
const {
488 #if 0 // disabled for now due to the ordering of classes in this header
490 bool Verify()
const {
491 Verifier verifier(data(), size());
492 return verifier.Verify<T>(
nullptr);
496 const T* GetRoot()
const {
497 return flatbuffers::GetRoot<T>(data());
502 return flatbuffers::GetRoot<T>(data());
508 FLATBUFFERS_DELETE_FUNC(
527 bool own_allocator =
false)
528 : allocator_(allocator ? allocator : &DefaultAllocator::instance()),
529 own_allocator_(own_allocator), initial_size_(initial_size), reserved_(0),
530 buf_(
nullptr), cur_(
nullptr) {
537 allocator_->deallocate(buf_, reserved_);
539 if (own_allocator_ && allocator_) {
547 allocator_->deallocate(buf_, reserved_);
556 cur_ = buf_ + reserved_;
566 DetachedBuffer fb(allocator_, own_allocator_, buf_, reserved_, cur_,
568 allocator_ =
nullptr;
569 own_allocator_ =
false;
576 size_t growth_policy(
size_t bytes) {
577 return (bytes == 0) ? initial_size_
578 : ((bytes / 2) & ~(AlignOf<largest_scalar_t>() - 1));
581 uint8_t *make_space(
size_t len) {
582 assert(cur_ >= buf_);
583 if (len > static_cast<size_t>(cur_ - buf_)) {
589 assert(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
593 Allocator &get_allocator() {
return *allocator_; }
595 uoffset_t size()
const {
596 return static_cast<uoffset_t
>(reserved_ - (cur_ - buf_));
599 size_t capacity()
const {
603 uint8_t *buf()
const {
608 uint8_t *data()
const {
613 uint8_t *data_at(
size_t offset)
const {
return buf_ + reserved_ - offset; }
615 void push(
const uint8_t *bytes,
size_t num) {
616 auto dest = make_space(num);
617 memcpy(dest, bytes, num);
621 template<
typename T>
void push_small(
const T& little_endian_t) {
622 auto dest = make_space(
sizeof(T));
623 *
reinterpret_cast<T *
>(dest) = little_endian_t;
628 void fill(
size_t zero_pad_bytes) {
629 auto dest = make_space(zero_pad_bytes);
630 for (
size_t i = 0; i < zero_pad_bytes; i++) dest[i] = 0;
634 void fill_big(
size_t zero_pad_bytes) {
635 auto dest = make_space(zero_pad_bytes);
636 memset(dest, 0, zero_pad_bytes);
639 void pop(
size_t bytes_to_remove) { cur_ += bytes_to_remove; }
648 size_t initial_size_;
653 void reallocate(
size_t len) {
655 auto old_reserved = reserved_;
656 auto old_size = size();
657 reserved_ += (std::max)(len, growth_policy(old_reserved));
658 FLATBUFFERS_CONSTEXPR
size_t alignment = AlignOf<largest_scalar_t>();
659 reserved_ = (reserved_ + alignment - 1) & ~(alignment - 1);
661 buf_ = allocator_->reallocate_downward(buf_, old_reserved, reserved_);
663 buf_ = allocator_->allocate(reserved_);
665 cur_ = buf_ + reserved_ - old_size;
670 inline voffset_t FieldIndexToOffset(voffset_t field_id) {
672 const int fixed_fields = 2;
673 return static_cast<voffset_t
>((field_id + fixed_fields) *
sizeof(voffset_t));
676 template <
typename T>
const T* data(
const std::vector<T> &v) {
677 return v.empty() ?
nullptr : &v.front();
679 template <
typename T> T* data(std::vector<T> &v) {
680 return v.empty() ?
nullptr : &v.front();
706 bool own_allocator =
false)
707 : buf_(initial_size, allocator, own_allocator), nested(false),
708 finished(false), minalign_(1), force_defaults_(false),
709 dedup_vtables_(true), string_pool(nullptr) {
710 offsetbuf_.reserve(16);
711 vtables_.reserve(16);
716 if (string_pool)
delete string_pool;
733 if (string_pool) string_pool->clear();
738 uoffset_t
GetSize()
const {
return buf_.size(); }
759 return buf_.release();
766 return buf_.release();
780 void Finished()
const {
800 void Pad(
size_t num_bytes) { buf_.fill(num_bytes); }
802 void Align(
size_t elem_size) {
803 if (elem_size > minalign_) minalign_ = elem_size;
804 buf_.fill(PaddingBytes(buf_.size(), elem_size));
807 void PushFlatBuffer(
const uint8_t *bytes,
size_t size) {
808 PushBytes(bytes, size);
812 void PushBytes(
const uint8_t *bytes,
size_t size) {
813 buf_.push(bytes, size);
816 void PopBytes(
size_t amount) { buf_.pop(amount); }
818 template<
typename T>
void AssertScalarT() {
819 #ifndef FLATBUFFERS_CPP98_STL
821 static_assert(std::is_scalar<T>::value,
"T must be a scalar type");
826 template<
typename T> uoffset_t PushElement(T element) {
828 T litle_endian_element = EndianScalar(element);
830 buf_.push_small(litle_endian_element);
834 template<
typename T> uoffset_t PushElement(Offset<T> off) {
836 return PushElement(ReferTo(off.o));
841 void TrackField(voffset_t field, uoffset_t off) {
842 FieldLoc fl = { off, field };
843 offsetbuf_.push_back(fl);
847 template<
typename T>
void AddElement(voffset_t field, T e, T def) {
849 if (e == def && !force_defaults_)
return;
850 auto off = PushElement(e);
851 TrackField(field, off);
854 template<
typename T>
void AddOffset(voffset_t field, Offset<T> off) {
855 if (off.IsNull())
return;
856 AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
859 template<
typename T>
void AddStruct(voffset_t field,
const T *structptr) {
860 if (!structptr)
return;
862 buf_.push_small(*structptr);
866 void AddStructOffset(voffset_t field, uoffset_t off) {
867 TrackField(field, off);
873 uoffset_t ReferTo(uoffset_t off) {
875 Align(
sizeof(uoffset_t));
877 assert(off && off <=
GetSize());
878 return GetSize() - off +
static_cast<uoffset_t
>(
sizeof(uoffset_t));
895 uoffset_t StartTable() {
904 uoffset_t EndTable(uoffset_t start, voffset_t numfields) {
909 auto vtableoffsetloc = PushElement<soffset_t>(0);
913 buf_.fill_big(numfields *
sizeof(voffset_t));
914 auto table_object_size = vtableoffsetloc - start;
915 assert(table_object_size < 0x10000);
916 PushElement<voffset_t>(
static_cast<voffset_t
>(table_object_size));
917 PushElement<voffset_t>(FieldIndexToOffset(numfields));
919 for (
auto field_location = offsetbuf_.begin();
920 field_location != offsetbuf_.end();
922 auto pos =
static_cast<voffset_t
>(vtableoffsetloc - field_location->off);
924 assert(!ReadScalar<voffset_t>(buf_.data() + field_location->id));
925 WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
928 auto vt1 =
reinterpret_cast<voffset_t *
>(buf_.data());
929 auto vt1_size = ReadScalar<voffset_t>(vt1);
933 if (dedup_vtables_) {
934 for (
auto it = vtables_.begin(); it != vtables_.end(); ++it) {
935 auto vt2 =
reinterpret_cast<voffset_t *
>(buf_.data_at(*it));
936 auto vt2_size = *vt2;
937 if (vt1_size != vt2_size || memcmp(vt2, vt1, vt1_size))
continue;
939 buf_.pop(
GetSize() - vtableoffsetloc);
945 vtables_.push_back(vt_use);
952 WriteScalar(buf_.data_at(vtableoffsetloc),
953 static_cast<soffset_t
>(vt_use) -
954 static_cast<soffset_t>(vtableoffsetloc));
957 return vtableoffsetloc;
962 template<
typename T>
void Required(Offset<T> table, voffset_t field) {
963 auto table_ptr = buf_.data_at(table.o);
964 auto vtable_ptr = table_ptr - ReadScalar<soffset_t>(table_ptr);
965 bool ok = ReadScalar<voffset_t>(vtable_ptr + field) != 0;
971 uoffset_t StartStruct(
size_t alignment) {
976 uoffset_t EndStruct() {
return GetSize(); }
978 void ClearOffsets() { offsetbuf_.clear(); }
982 void PreAlign(
size_t len,
size_t alignment) {
983 buf_.fill(PaddingBytes(
GetSize() + len, alignment));
985 template<
typename T>
void PreAlign(
size_t len) {
987 PreAlign(len,
sizeof(T));
997 PreAlign<uoffset_t>(len + 1);
999 PushBytes(reinterpret_cast<const uint8_t *>(str), len);
1000 PushElement(static_cast<uoffset_t>(len));
1022 return str ?
CreateString(str->c_str(), str->Length()) : 0;
1029 template<
typename T>
1043 auto size_before_string = buf_.size();
1047 auto it = string_pool->find(off);
1049 if (it != string_pool->end()) {
1051 buf_.pop(buf_.size() - size_before_string);
1055 string_pool->insert(off);
1087 uoffset_t EndVector(
size_t len) {
1090 return PushElement(static_cast<uoffset_t>(len));
1093 void StartVector(
size_t len,
size_t elemsize) {
1096 PreAlign<uoffset_t>(len * elemsize);
1097 PreAlign(len * elemsize, elemsize);
1105 void ForceVectorAlignment(
size_t len,
size_t elemsize,
size_t alignment) {
1106 PreAlign(len * elemsize, alignment);
1109 uint8_t *ReserveElements(
size_t len,
size_t elemsize) {
1110 return buf_.make_space(len * elemsize);
1125 StartVector(len,
sizeof(T));
1126 #if FLATBUFFERS_LITTLEENDIAN
1127 PushBytes(reinterpret_cast<const uint8_t *>(v), len *
sizeof(T));
1129 if (
sizeof(T) == 1) {
1130 PushBytes(reinterpret_cast<const uint8_t *>(v), len);
1132 for (
auto i = len; i > 0; ) {
1133 PushElement(v[--i]);
1142 for (
auto i = len; i > 0; ) {
1143 PushElement(v[--i]);
1145 return Offset<Vector<Offset<T>>>(EndVector(len));
1162 StartVector(v.size(),
sizeof(uint8_t));
1163 for (
auto i = v.size(); i > 0; ) {
1164 PushElement(static_cast<uint8_t>(v[--i]));
1166 return Offset<Vector<uint8_t>>(EndVector(v.size()));
1169 #ifndef FLATBUFFERS_CPP98_STL
1178 const std::function<T (
size_t i)> &f) {
1179 std::vector<T> elems(vector_size);
1180 for (
size_t i = 0; i < vector_size; i++) elems[i] = f(i);
1192 const std::vector<std::string> &v) {
1193 std::vector<Offset<String>> offsets(v.size());
1194 for (
size_t i = 0; i < v.size(); i++) offsets[i] =
CreateString(v[i]);
1206 const T *v,
size_t len) {
1207 StartVector(len *
sizeof(T) / AlignOf<T>(), AlignOf<T>());
1208 PushBytes(reinterpret_cast<const uint8_t *>(v),
sizeof(T) * len);
1221 const S *v,
size_t len) {
1222 extern T Pack(
const S&);
1223 typedef T (*Pack_t)(
const S&);
1224 std::vector<T> vv(len);
1225 std::transform(v, v+len, vv.begin(), *(Pack_t)&Pack);
1226 return CreateVectorOfStructs<T>(vv.data(), vv.size());
1230 #ifndef FLATBUFFERS_CPP98_STL
1240 size_t vector_size,
const std::function<
void(
size_t i, T *)> &filler) {
1241 StartVector(vector_size *
sizeof(T) / AlignOf<T>(), AlignOf<T>());
1242 T *structs =
reinterpret_cast<T *
>(buf_.make_space(vector_size *
sizeof(T)));
1243 for (
size_t i = 0; i < vector_size; i++) {
1258 const std::vector<T> &v) {
1270 const std::vector<S> &v) {
1271 return CreateVectorOfNativeStructs<T, S>(data(v), v.size());
1276 template<
typename T>
1277 struct StructKeyComparator {
1278 bool operator()(
const T &a,
const T &b)
const {
1279 return a.KeyCompareLessThan(&b);
1283 StructKeyComparator& operator= (
const StructKeyComparator&);
1295 std::vector<T> *v) {
1308 std::vector<S> *v) {
1309 return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size());
1322 std::sort(v, v + len, StructKeyComparator<T>());
1337 extern T Pack(
const S&);
1338 typedef T (*Pack_t)(
const S&);
1339 std::vector<T> vv(len);
1340 std::transform(v, v+len, vv.begin(), *(Pack_t)&Pack);
1341 return CreateVectorOfSortedStructs<T>(vv, len);
1345 template<
typename T>
1346 struct TableKeyComparator {
1348 bool operator()(
const Offset<T> &a,
const Offset<T> &b)
const {
1349 auto table_a =
reinterpret_cast<T *
>(buf_.data_at(a.o));
1350 auto table_b =
reinterpret_cast<T *
>(buf_.data_at(b.o));
1351 return table_a->KeyCompareLessThan(table_b);
1353 vector_downward& buf_;
1356 TableKeyComparator& operator= (
const TableKeyComparator&);
1370 std::sort(v, v + len, TableKeyComparator<T>(buf_));
1396 StartVector(len, elemsize);
1397 buf_.make_space(len * elemsize);
1399 auto vec_end = EndVector(len);
1400 *buf = buf_.data_at(vec_start);
1413 size_t len, T **buf) {
1415 reinterpret_cast<uint8_t **>(buf));
1420 Align(AlignOf<T>());
1421 buf_.push_small(structobj);
1432 const char *file_identifier =
nullptr) {
1434 Finish(root.o, file_identifier,
false);
1445 const char *file_identifier =
nullptr) {
1446 Finish(root.o, file_identifier,
true);
1454 void Finish(uoffset_t root,
const char *file_identifier,
bool size_prefix) {
1457 PreAlign((size_prefix ?
sizeof(uoffset_t) : 0) +
1459 (file_identifier ? kFileIdentifierLength : 0),
1461 if (file_identifier) {
1462 assert(strlen(file_identifier) == kFileIdentifierLength);
1463 PushBytes(reinterpret_cast<const uint8_t *>(file_identifier),
1464 kFileIdentifierLength);
1466 PushElement(ReferTo(root));
1481 std::vector<FieldLoc> offsetbuf_;
1489 std::vector<uoffset_t> vtables_;
1493 bool force_defaults_;
1495 bool dedup_vtables_;
1500 auto stra =
reinterpret_cast<const String *
>(buf_->data_at(a.o));
1501 auto strb =
reinterpret_cast<const String *
>(buf_->data_at(b.o));
1502 return strncmp(stra->c_str(), strb->c_str(),
1503 std::min(stra->size(), strb->size()) + 1) < 0;
1510 StringOffsetMap *string_pool;
1516 template<
typename T> T *GetMutableRoot(
void *buf) {
1518 return reinterpret_cast<T *
>(
reinterpret_cast<uint8_t *
>(buf) +
1519 EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
1522 template<
typename T>
const T *GetRoot(
const void *buf) {
1523 return GetMutableRoot<T>(
const_cast<void *
>(buf));
1526 template<
typename T>
const T *GetSizePrefixedRoot(
const void *buf) {
1527 return GetRoot<T>(
reinterpret_cast<const uint8_t *
>(buf) +
sizeof(uoffset_t));
1533 template<
typename T> T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb,
1535 return reinterpret_cast<T *
>(fbb.GetCurrentBufferPointer() +
1536 fbb.GetSize() - offset.o);
1539 template<
typename T>
const T *GetTemporaryPointer(FlatBufferBuilder &fbb,
1541 return GetMutableTemporaryPointer<T>(fbb, offset);
1552 inline const char *GetBufferIdentifier(
const void *buf) {
1553 return reinterpret_cast<const char *
>(buf) +
sizeof(uoffset_t);
1557 inline bool BufferHasIdentifier(
const void *buf,
const char *identifier) {
1558 return strncmp(GetBufferIdentifier(buf),
1563 class Verifier FLATBUFFERS_FINAL_CLASS {
1565 Verifier(
const uint8_t *buf,
size_t buf_len, uoffset_t _max_depth = 64,
1566 uoffset_t _max_tables = 1000000)
1567 : buf_(buf), end_(buf + buf_len), depth_(0), max_depth_(_max_depth),
1568 num_tables_(0), max_tables_(_max_tables)
1569 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1575 bool Check(
bool ok)
const {
1576 #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
1579 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1581 upper_bound_ = buf_;
1587 bool Verify(
const void *elem,
size_t elem_len)
const {
1588 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1589 auto upper_bound =
reinterpret_cast<const uint8_t *
>(elem) + elem_len;
1590 if (upper_bound_ < upper_bound)
1591 upper_bound_ = upper_bound;
1593 return Check(elem_len <= (
size_t) (end_ - buf_) &&
1595 elem <= end_ - elem_len);
1599 template<
typename T>
bool Verify(
const void *elem)
const {
1600 return Verify(elem,
sizeof(T));
1604 template<
typename T>
bool VerifyTable(
const T *table) {
1605 return !table || table->Verify(*
this);
1609 template<
typename T>
bool Verify(
const Vector<T> *vec)
const {
1612 VerifyVector(reinterpret_cast<const uint8_t *>(vec),
sizeof(T),
1617 template<
typename T>
bool Verify(
const Vector<const T *> *vec)
const {
1618 return Verify(
reinterpret_cast<const Vector<T> *
>(vec));
1622 bool Verify(
const String *str)
const {
1625 (VerifyVector(reinterpret_cast<const uint8_t *>(str), 1, &end) &&
1627 Check(*end ==
'\0'));
1631 bool VerifyVector(
const uint8_t *vec,
size_t elem_size,
1632 const uint8_t **end)
const {
1634 if (!Verify<uoffset_t>(vec))
return false;
1637 auto size = ReadScalar<uoffset_t>(vec);
1638 auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
1639 if (!Check(size < max_elems))
1641 auto byte_size =
sizeof(size) + elem_size * size;
1642 *end = vec + byte_size;
1643 return Verify(vec, byte_size);
1647 bool VerifyVectorOfStrings(
const Vector<Offset<String>> *vec)
const {
1649 for (uoffset_t i = 0; i < vec->size(); i++) {
1650 if (!Verify(vec->Get(i)))
return false;
1657 template<
typename T>
bool VerifyVectorOfTables(
const Vector<Offset<T>> *vec) {
1659 for (uoffset_t i = 0; i < vec->size(); i++) {
1660 if (!vec->Get(i)->Verify(*
this))
return false;
1666 template<
typename T>
bool VerifyBufferFromStart(
const char *identifier,
1667 const uint8_t *start) {
1669 (
size_t(end_ - start) < 2 *
sizeof(flatbuffers::uoffset_t) ||
1670 !BufferHasIdentifier(start, identifier))) {
1675 auto o = VerifyOffset(start);
1677 reinterpret_cast<const T *
>(start + o)->
1679 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1680 && GetComputedSize()
1686 template<
typename T>
bool VerifyBuffer() {
1687 return VerifyBuffer<T>(
nullptr);
1690 template<
typename T>
bool VerifyBuffer(
const char *identifier) {
1691 return VerifyBufferFromStart<T>(identifier, buf_);
1694 template<
typename T>
bool VerifySizePrefixedBuffer(
const char *identifier) {
1695 return Verify<uoffset_t>(buf_) &&
1696 ReadScalar<uoffset_t>(buf_) == end_ - buf_ -
sizeof(uoffset_t) &&
1697 VerifyBufferFromStart<T>(identifier, buf_ +
sizeof(uoffset_t));
1700 uoffset_t VerifyOffset(
const uint8_t *start)
const {
1701 if (!Verify<uoffset_t>(start))
return false;
1702 auto o = ReadScalar<uoffset_t>(start);
1711 bool VerifyComplexity() {
1714 return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_);
1723 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1725 size_t GetComputedSize()
const {
1726 uintptr_t size = upper_bound_ - buf_;
1728 size = (size - 1 +
sizeof(uoffset_t)) & ~(
sizeof(uoffset_t) - 1);
1729 return (buf_ + size > end_) ? 0 : size;
1734 const uint8_t *buf_;
1735 const uint8_t *end_;
1737 uoffset_t max_depth_;
1738 uoffset_t num_tables_;
1739 uoffset_t max_tables_;
1740 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1741 mutable const uint8_t *upper_bound_;
1748 struct BufferRefBase {};
1749 template<
typename T>
struct BufferRef : BufferRefBase {
1750 BufferRef() : buf(nullptr), len(0), must_free(false) {}
1751 BufferRef(uint8_t *_buf, uoffset_t _len)
1752 : buf(_buf), len(_len), must_free(false) {}
1754 ~BufferRef() {
if (must_free) free(buf); }
1756 const T *GetRoot()
const {
return flatbuffers::GetRoot<T>(buf); }
1759 Verifier verifier(buf, len);
1760 return verifier.VerifyBuffer<T>(
nullptr);
1772 class Struct FLATBUFFERS_FINAL_CLASS {
1774 template<
typename T> T GetField(uoffset_t o)
const {
1775 return ReadScalar<T>(&data_[o]);
1778 template<
typename T> T GetStruct(uoffset_t o)
const {
1779 return reinterpret_cast<T
>(&data_[o]);
1782 const uint8_t *GetAddressOf(uoffset_t o)
const {
return &data_[o]; }
1783 uint8_t *GetAddressOf(uoffset_t o) {
return &data_[o]; }
1793 const uint8_t *GetVTable()
const {
1794 return data_ - ReadScalar<soffset_t>(data_);
1799 voffset_t GetOptionalFieldOffset(voffset_t field)
const {
1801 auto vtable = GetVTable();
1803 auto vtsize = ReadScalar<voffset_t>(vtable);
1806 return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
1809 template<
typename T> T GetField(voffset_t field, T defaultval)
const {
1810 auto field_offset = GetOptionalFieldOffset(field);
1811 return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
1814 template<
typename P> P GetPointer(voffset_t field) {
1815 auto field_offset = GetOptionalFieldOffset(field);
1816 auto p = data_ + field_offset;
1818 ?
reinterpret_cast<P
>(p + ReadScalar<uoffset_t>(p))
1821 template<
typename P> P GetPointer(voffset_t field)
const {
1822 return const_cast<Table *
>(
this)->GetPointer<P>(field);
1825 template<
typename P> P GetStruct(voffset_t field)
const {
1826 auto field_offset = GetOptionalFieldOffset(field);
1827 auto p =
const_cast<uint8_t *
>(data_ + field_offset);
1828 return field_offset ?
reinterpret_cast<P
>(p) :
nullptr;
1831 template<
typename T>
bool SetField(voffset_t field, T val, T def) {
1832 auto field_offset = GetOptionalFieldOffset(field);
1833 if (!field_offset)
return val == def;
1834 WriteScalar(data_ + field_offset, val);
1838 bool SetPointer(voffset_t field,
const uint8_t *val) {
1839 auto field_offset = GetOptionalFieldOffset(field);
1840 if (!field_offset)
return false;
1841 WriteScalar(data_ + field_offset,
1842 static_cast<uoffset_t>(val - (data_ + field_offset)));
1846 uint8_t *GetAddressOf(voffset_t field) {
1847 auto field_offset = GetOptionalFieldOffset(field);
1848 return field_offset ? data_ + field_offset :
nullptr;
1850 const uint8_t *GetAddressOf(voffset_t field)
const {
1851 return const_cast<Table *
>(
this)->GetAddressOf(field);
1854 bool CheckField(voffset_t field)
const {
1855 return GetOptionalFieldOffset(field) != 0;
1860 bool VerifyTableStart(Verifier &verifier)
const {
1862 if (!verifier.Verify<soffset_t>(data_))
return false;
1863 auto vtable = GetVTable();
1865 return verifier.VerifyComplexity() &&
1866 verifier.Verify<voffset_t>(vtable) &&
1867 (ReadScalar<voffset_t>(vtable) & (
sizeof(voffset_t) - 1)) == 0 &&
1868 verifier.Verify(vtable, ReadScalar<voffset_t>(vtable));
1872 template<
typename T>
bool VerifyField(
const Verifier &verifier,
1873 voffset_t field)
const {
1876 auto field_offset = GetOptionalFieldOffset(field);
1878 return !field_offset || verifier.Verify<T>(data_ + field_offset);
1882 template<
typename T>
bool VerifyFieldRequired(
const Verifier &verifier,
1883 voffset_t field)
const {
1884 auto field_offset = GetOptionalFieldOffset(field);
1885 return verifier.Check(field_offset != 0) &&
1886 verifier.Verify<T>(data_ + field_offset);
1890 bool VerifyOffset(
const Verifier &verifier, voffset_t field)
const {
1891 auto field_offset = GetOptionalFieldOffset(field);
1892 return !field_offset || verifier.VerifyOffset(data_ + field_offset);
1895 bool VerifyOffsetRequired(
const Verifier &verifier, voffset_t field)
const {
1896 auto field_offset = GetOptionalFieldOffset(field);
1897 return verifier.Check(field_offset != 0) &&
1898 verifier.VerifyOffset(data_ + field_offset);
1905 Table(
const Table &other);
1914 inline const uint8_t *GetBufferStartFromRootPointer(
const void *root) {
1915 auto table =
reinterpret_cast<const Table *
>(root);
1916 auto vtable = table->GetVTable();
1918 auto start = std::min(vtable, reinterpret_cast<const uint8_t *>(root));
1920 start =
reinterpret_cast<const uint8_t *
>(
1921 reinterpret_cast<uintptr_t
>(start) & ~(
sizeof(uoffset_t) - 1));
1932 "file_identifier is assumed to be the same size as uoffset_t");
1933 for (
auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT /
sizeof(uoffset_t) + 1;
1936 start -=
sizeof(uoffset_t);
1937 if (ReadScalar<uoffset_t>(start) + start ==
1938 reinterpret_cast<const uint8_t *
>(root))
return start;
1951 struct NativeTable {
1962 typedef uint64_t hash_value_t;
1963 #ifdef FLATBUFFERS_CPP98_STL
1964 typedef void (*resolver_function_t)(
void **pointer_adr, hash_value_t hash);
1965 typedef hash_value_t (*rehasher_function_t)(
void *pointer);
1967 typedef std::function<void (void **pointer_adr, hash_value_t hash)>
1968 resolver_function_t;
1969 typedef std::function<hash_value_t (void *pointer)> rehasher_function_t;
1979 template<
typename T>
bool IsFieldPresent(
const T *table, voffset_t field) {
1981 return reinterpret_cast<const Table *
>(table)->CheckField(field);
1987 inline int LookupEnum(
const char **names,
const char *name) {
1988 for (
const char **p = names; *p; p++)
1989 if (!strcmp(*p, name))
1990 return static_cast<int>(p - names);
2004 #if defined(_MSC_VER)
2005 #define MANUALLY_ALIGNED_STRUCT(alignment) \
2006 __pragma(pack(1)); \
2007 struct __declspec(align(alignment))
2008 #define STRUCT_END(name, size) \
2010 static_assert(sizeof(name) == size, "compiler breaks packing rules")
2011 #elif defined(__GNUC__) || defined(__clang__)
2012 #define MANUALLY_ALIGNED_STRUCT(alignment) \
2013 _Pragma("pack(1)") \
2014 struct __attribute__((aligned(alignment)))
2015 #define STRUCT_END(name, size) \
2017 static_assert(sizeof(name) == size, "compiler breaks packing rules")
2019 #error Unknown compiler, please define structure alignment macros
2032 #if !defined(_WIN32) && !defined(__CYGWIN__)
2034 extern volatile __attribute__((weak)) const
char *flatbuffer_version_string;
2035 volatile __attribute__((weak)) const
char *flatbuffer_version_string =
2037 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
2038 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
2039 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
2041 #endif // !defined(_WIN32) && !defined(__CYGWIN__)
2043 #define DEFINE_BITMASK_OPERATORS(E, T)\
2044 inline E operator | (E lhs, E rhs){\
2045 return E(T(lhs) | T(rhs));\
2047 inline E operator & (E lhs, E rhs){\
2048 return E(T(lhs) & T(rhs));\
2050 inline E operator ^ (E lhs, E rhs){\
2051 return E(T(lhs) ^ T(rhs));\
2053 inline E operator ~ (E lhs){\
2056 inline E operator |= (E &lhs, E rhs){\
2060 inline E operator &= (E &lhs, E rhs){\
2064 inline E operator ^= (E &lhs, E rhs){\
2068 inline bool operator !(E rhs) \
2070 return !bool(T(rhs)); \
2075 #if defined(_MSC_VER)
2076 #pragma warning(pop)
2079 #endif // FLATBUFFERS_H_
Definition: flatbuffers.h:25
Offset< Vector< T > > CreateVector(size_t vector_size, const std::function< T(size_t i)> &f)
Serialize values returned by a function into a FlatBuffer vector.
Definition: flatbuffers.h:1177
uoffset_t CreateUninitializedVector(size_t len, size_t elemsize, uint8_t **buf)
Specialized version of CreateVector for non-copying use cases.
Definition: flatbuffers.h:1393
Offset< Vector< const T * > > CreateVectorOfStructs(size_t vector_size, const std::function< void(size_t i, T *)> &filler)
Serialize an array of structs into a FlatBuffer vector.
Definition: flatbuffers.h:1239
Offset< Vector< const T * > > CreateVectorOfSortedStructs(T *v, size_t len)
Serialize an array of structs into a FlatBuffer vector in sorted order.
Definition: flatbuffers.h:1320
Offset< Vector< const T * > > CreateVectorOfSortedNativeStructs(std::vector< S > *v)
Serialize a std::vector of native structs into a FlatBuffer vector in sorted order.
Definition: flatbuffers.h:1307
Offset< Vector< Offset< T > > > CreateVectorOfSortedTables(std::vector< Offset< T >> *v)
Serialize an array of table offsets as a vector in the buffer in sorted order.
Definition: flatbuffers.h:1381
Definition: flatbuffers.h:121
Helper class to hold data needed in creation of a FlatBuffer.
Definition: flatbuffers.h:694
uoffset_t GetSize() const
The current size of the serialized buffer, counting from the end.
Definition: flatbuffers.h:738
void Clear()
Reset all the state in this FlatBufferBuilder so it can be reused to construct another buffer...
Definition: flatbuffers.h:726
Offset< Vector< const T * > > CreateVectorOfNativeStructs(const S *v, size_t len)
Serialize an array of native structs into a FlatBuffer vector.
Definition: flatbuffers.h:1220
Offset< const T * > CreateStruct(const T &structobj)
Write a struct by itself, typically to be part of a union.
Definition: flatbuffers.h:1419
Definition: flatbuffers.h:22
void FinishSizePrefixed(Offset< T > root, const char *file_identifier=nullptr)
Finish a buffer with a 32 bit size field pre-fixed (size of the buffer following the size field)...
Definition: flatbuffers.h:1444
Definition: flatbuffers.h:432
Offset< String > CreateSharedString(const char *str)
Store a string in the buffer, which null-terminated.
Definition: flatbuffers.h:1064
Definition: flatbuffers.h:339
Definition: flatbuffers.h:92
Offset< String > CreateString(const char *str, size_t len)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:995
void ForceDefaults(bool fd)
In order to save space, fields that are set to their default value don't get serialized into the buff...
Definition: flatbuffers.h:793
Definition: flatbuffers.h:413
void DedupVtables(bool dedup)
By default vtables are deduped in order to save space.
Definition: flatbuffers.h:797
static const size_t kFileIdentifierLength
The length of a FlatBuffer file header.
Definition: flatbuffers.h:1426
Offset< String > CreateString(const String *str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1021
Definition: flatbuffers.h:523
Offset< Vector< const T * > > CreateVectorOfSortedNativeStructs(S *v, size_t len)
Serialize an array of native structs into a FlatBuffer vector in sorted order.
Definition: flatbuffers.h:1335
Offset< String > CreateSharedString(const String *str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1082
Offset< String > CreateString(const T &str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1030
Offset< Vector< const T * > > CreateVectorOfSortedStructs(std::vector< T > *v)
Serialize a std::vector of structs into a FlatBuffer vector in sorted order.
Definition: flatbuffers.h:1294
Offset< Vector< Offset< String > > > CreateVectorOfStrings(const std::vector< std::string > &v)
Serialize a std::vector into a FlatBuffer vector.
Definition: flatbuffers.h:1191
FlatBufferBuilder(size_t initial_size=1024, Allocator *allocator=nullptr, bool own_allocator=false)
Default constructor for FlatBufferBuilder.
Definition: flatbuffers.h:704
size_t GetBufferMinAlignment()
get the minimum alignment this buffer needs to be accessed properly.
Definition: flatbuffers.h:774
Definition: FlatBufferBuilder.cs:25
Offset< Vector< const T * > > CreateVectorOfStructs(const T *v, size_t len)
Serialize an array of structs into a FlatBuffer vector.
Definition: flatbuffers.h:1205
Offset< Vector< const T * > > CreateVectorOfNativeStructs(const std::vector< S > &v)
Serialize a std::vector of native structs into a FlatBuffer vector.
Definition: flatbuffers.h:1269
Offset< String > CreateString(const char *str)
Store a string in the buffer, which is null-terminated.
Definition: flatbuffers.h:1007
Definition: flatbuffers.h:389
Definition: flatbuffers.h:378
Definition: flatbuffers.h:1473
Offset< String > CreateString(const std::string &str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1014
Offset< Vector< T > > CreateVector(const std::vector< T > &v)
Serialize a std::vector into a FlatBuffer vector.
Definition: flatbuffers.h:1154
Offset< Vector< T > > CreateUninitializedVector(size_t len, T **buf)
Specialized version of CreateVector for non-copying use cases.
Definition: flatbuffers.h:1412
uint8_t * GetCurrentBufferPointer() const
Get a pointer to an unfinished buffer.
Definition: flatbuffers.h:750
Offset< Vector< T > > CreateVector(const T *v, size_t len)
Serialize an array into a FlatBuffer vector.
Definition: flatbuffers.h:1121
Offset< String > CreateSharedString(const std::string &str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1073
Offset< Vector< Offset< T > > > CreateVectorOfSortedTables(Offset< T > *v, size_t len)
Serialize an array of table offsets as a vector in the buffer in sorted order.
Definition: flatbuffers.h:1368
DetachedBuffer Release()
Get the released DetachedBuffer.
Definition: flatbuffers.h:764
Offset< String > CreateSharedString(const char *str, size_t len)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1040
Offset< Vector< const T * > > CreateVectorOfStructs(const std::vector< T > &v)
Serialize a std::vector of structs into a FlatBuffer vector.
Definition: flatbuffers.h:1257
Definition: flatbuffers.h:214
DetachedBuffer ReleaseBufferPointer()
Get the released pointer to the serialized buffer.
Definition: flatbuffers.h:757
void Finish(Offset< T > root, const char *file_identifier=nullptr)
Finish serializing a buffer by writing the root offset.
Definition: flatbuffers.h:1431
Definition: flatbuffers.h:1497
uint8_t * GetBufferPointer() const
Get the serialized buffer (after you call Finish()).
Definition: flatbuffers.h:743