17 #ifndef FLATBUFFERS_H_
18 #define FLATBUFFERS_H_
28 #include <type_traits>
34 #ifdef _STLPORT_VERSION
35 #define FLATBUFFERS_CPP98_STL
37 #ifndef FLATBUFFERS_CPP98_STL
42 #if __cplusplus <= 199711L && \
43 (!defined(_MSC_VER) || _MSC_VER < 1600) && \
44 (!defined(__GNUC__) || \
45 (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400))
46 #error A C++11 compatible compiler with support for the auto typing is \
47 required for FlatBuffers.
48 #error __cplusplus _MSC_VER __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__
51 #if !defined(__clang__) && \
52 defined(__GNUC__) && \
53 (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600)
58 const class nullptr_t {
60 template<
class T>
inline operator T*()
const {
return 0; }
62 void operator&()
const;
66 #define constexpr const
72 #if !defined(FLATBUFFERS_LITTLEENDIAN)
73 #if defined(__GNUC__) || defined(__clang__)
75 #define FLATBUFFERS_LITTLEENDIAN 0
77 #define FLATBUFFERS_LITTLEENDIAN 1
78 #endif // __BIG_ENDIAN__
79 #elif defined(_MSC_VER)
81 #define FLATBUFFERS_LITTLEENDIAN 0
83 #define FLATBUFFERS_LITTLEENDIAN 1
86 #error Unable to determine endianness, define FLATBUFFERS_LITTLEENDIAN.
88 #endif // !defined(FLATBUFFERS_LITTLEENDIAN)
90 #define FLATBUFFERS_VERSION_MAJOR 1
91 #define FLATBUFFERS_VERSION_MINOR 5
92 #define FLATBUFFERS_VERSION_REVISION 0
93 #define FLATBUFFERS_STRING_EXPAND(X) #X
94 #define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
96 #if (!defined(_MSC_VER) || _MSC_VER > 1600) && \
97 (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407))
98 #define FLATBUFFERS_FINAL_CLASS final
100 #define FLATBUFFERS_FINAL_CLASS
103 #if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
104 (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406))
105 #define FLATBUFFERS_CONSTEXPR constexpr
107 #define FLATBUFFERS_CONSTEXPR
113 namespace flatbuffers {
119 typedef uint32_t uoffset_t;
122 typedef int32_t soffset_t;
126 typedef uint16_t voffset_t;
128 typedef uintmax_t largest_scalar_t;
131 #define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(soffset_t) * 8 - 1)) - 1)
134 #define FLATBUFFERS_MAX_ALIGNMENT 16
136 #ifndef FLATBUFFERS_CPP98_STL
138 typedef std::unique_ptr<uint8_t, std::function<void(uint8_t * )>>
143 template<
typename T>
struct Offset {
146 Offset(uoffset_t _o) : o(_o) {}
147 Offset<void> Union()
const {
return Offset<void>(o); }
150 inline void EndianCheck() {
153 assert(*reinterpret_cast<char *>(&endiantest) == FLATBUFFERS_LITTLEENDIAN);
157 template<
typename T> T EndianSwap(T t) {
158 #if defined(_MSC_VER)
159 #define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
160 #define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
161 #define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
163 #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408
165 #define FLATBUFFERS_BYTESWAP16(x) \
166 static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16))
168 #define FLATBUFFERS_BYTESWAP16 __builtin_bswap16
170 #define FLATBUFFERS_BYTESWAP32 __builtin_bswap32
171 #define FLATBUFFERS_BYTESWAP64 __builtin_bswap64
173 if (
sizeof(T) == 1) {
175 }
else if (
sizeof(T) == 2) {
176 auto r = FLATBUFFERS_BYTESWAP16(*reinterpret_cast<uint16_t *>(&t));
177 return *
reinterpret_cast<T *
>(&r);
178 }
else if (
sizeof(T) == 4) {
179 auto r = FLATBUFFERS_BYTESWAP32(*reinterpret_cast<uint32_t *>(&t));
180 return *
reinterpret_cast<T *
>(&r);
181 }
else if (
sizeof(T) == 8) {
182 auto r = FLATBUFFERS_BYTESWAP64(*reinterpret_cast<uint64_t *>(&t));
183 return *
reinterpret_cast<T *
>(&r);
189 template<
typename T> T EndianScalar(T t) {
190 #if FLATBUFFERS_LITTLEENDIAN
193 return EndianSwap(t);
197 template<
typename T> T ReadScalar(
const void *p) {
198 return EndianScalar(*reinterpret_cast<const T *>(p));
201 template<
typename T>
void WriteScalar(
void *p, T t) {
202 *
reinterpret_cast<T *
>(p) = EndianScalar(t);
205 template<
typename T>
size_t AlignOf() {
210 return __alignof__(T);
225 template<
typename T>
struct IndirectHelper {
226 typedef T return_type;
227 typedef T mutable_return_type;
228 static const size_t element_stride =
sizeof(T);
229 static return_type Read(
const uint8_t *p, uoffset_t i) {
230 return EndianScalar((reinterpret_cast<const T *>(p))[i]);
233 template<
typename T>
struct IndirectHelper<Offset<T>> {
234 typedef const T *return_type;
235 typedef T *mutable_return_type;
236 static const size_t element_stride =
sizeof(uoffset_t);
237 static return_type Read(
const uint8_t *p, uoffset_t i) {
238 p += i *
sizeof(uoffset_t);
239 return reinterpret_cast<return_type
>(p + ReadScalar<uoffset_t>(p));
242 template<
typename T>
struct IndirectHelper<const T *> {
243 typedef const T *return_type;
244 typedef T *mutable_return_type;
245 static const size_t element_stride =
sizeof(T);
246 static return_type Read(
const uint8_t *p, uoffset_t i) {
247 return reinterpret_cast<const T *
>(p + i *
sizeof(T));
253 template<
typename T,
typename IT>
254 struct VectorIterator
255 :
public std::iterator<std::random_access_iterator_tag, IT, uoffset_t> {
257 typedef std::iterator<std::random_access_iterator_tag, IT, uoffset_t> super_type;
260 VectorIterator(
const uint8_t *data, uoffset_t i) :
261 data_(data + IndirectHelper<T>::element_stride * i) {}
262 VectorIterator(
const VectorIterator &other) : data_(other.data_) {}
263 #ifndef FLATBUFFERS_CPP98_STL
264 VectorIterator(VectorIterator &&other) : data_(std::move(other.data_)) {}
267 VectorIterator &operator=(
const VectorIterator &other) {
272 VectorIterator &operator=(VectorIterator &&other) {
277 bool operator==(
const VectorIterator &other)
const {
278 return data_ == other.data_;
281 bool operator!=(
const VectorIterator &other)
const {
282 return data_ != other.data_;
285 ptrdiff_t operator-(
const VectorIterator &other)
const {
286 return (data_ - other.data_) / IndirectHelper<T>::element_stride;
289 typename super_type::value_type operator *()
const {
290 return IndirectHelper<T>::Read(data_, 0);
293 typename super_type::value_type operator->()
const {
294 return IndirectHelper<T>::Read(data_, 0);
297 VectorIterator &operator++() {
298 data_ += IndirectHelper<T>::element_stride;
302 VectorIterator operator++(
int) {
303 VectorIterator temp(data_, 0);
304 data_ += IndirectHelper<T>::element_stride;
308 VectorIterator operator+(
const uoffset_t &offset) {
309 return VectorIterator(data_ + offset * IndirectHelper<T>::element_stride, 0);
312 VectorIterator& operator+=(
const uoffset_t &offset) {
313 data_ += offset * IndirectHelper<T>::element_stride;
317 VectorIterator &operator--() {
318 data_ -= IndirectHelper<T>::element_stride;
322 VectorIterator operator--(
int) {
323 VectorIterator temp(data_, 0);
324 data_ -= IndirectHelper<T>::element_stride;
328 VectorIterator operator-(
const uoffset_t &offset) {
329 return VectorIterator(data_ - offset * IndirectHelper<T>::element_stride, 0);
332 VectorIterator& operator-=(
const uoffset_t &offset) {
333 data_ -= offset * IndirectHelper<T>::element_stride;
338 const uint8_t *data_;
343 template<
typename T>
class Vector {
345 typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
347 typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
350 uoffset_t size()
const {
return EndianScalar(length_); }
353 uoffset_t Length()
const {
return size(); }
355 typedef typename IndirectHelper<T>::return_type return_type;
356 typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
358 return_type Get(uoffset_t i)
const {
360 return IndirectHelper<T>::Read(Data(), i);
363 return_type operator[](uoffset_t i)
const {
return Get(i); }
368 template<
typename E> E GetEnum(uoffset_t i)
const {
369 return static_cast<E
>(Get(i));
372 const void *GetStructFromOffset(
size_t o)
const {
373 return reinterpret_cast<const void *
>(Data() + o);
376 iterator begin() {
return iterator(Data(), 0); }
377 const_iterator begin()
const {
return const_iterator(Data(), 0); }
379 iterator end() {
return iterator(Data(), size()); }
380 const_iterator end()
const {
return const_iterator(Data(), size()); }
384 void Mutate(uoffset_t i,
const T& val) {
386 WriteScalar(data() + i, val);
392 void MutateOffset(uoffset_t i,
const uint8_t *val) {
394 assert(
sizeof(T) ==
sizeof(uoffset_t));
395 WriteScalar(data() + i,
396 static_cast<uoffset_t>(val - (Data() + i *
sizeof(uoffset_t))));
400 mutable_return_type GetMutableObject(uoffset_t i)
const {
402 return const_cast<mutable_return_type
>(IndirectHelper<T>::Read(Data(), i));
406 const uint8_t *Data()
const {
407 return reinterpret_cast<const uint8_t *
>(&length_ + 1);
411 return reinterpret_cast<uint8_t *
>(&length_ + 1);
415 const T *data()
const {
return reinterpret_cast<const T *
>(Data()); }
416 T *data() {
return reinterpret_cast<T *
>(Data()); }
418 template<
typename K> return_type LookupByKey(K key)
const {
419 void *search_result = std::bsearch(&key, Data(), size(),
420 IndirectHelper<T>::element_stride, KeyCompare<K>);
422 if (!search_result) {
426 const uint8_t *element =
reinterpret_cast<const uint8_t *
>(search_result);
428 return IndirectHelper<T>::Read(element, 0);
439 template<
typename K>
static int KeyCompare(
const void *ap,
const void *bp) {
440 const K *key =
reinterpret_cast<const K *
>(ap);
441 const uint8_t *data =
reinterpret_cast<const uint8_t *
>(bp);
442 auto table = IndirectHelper<T>::Read(data, 0);
446 return -table->KeyCompareWithValue(*key);
454 uoffset_t size()
const {
return EndianScalar(length_); }
456 const uint8_t *Data()
const {
457 return reinterpret_cast<const uint8_t *
>(&length_ + 1);
460 return reinterpret_cast<uint8_t *
>(&length_ + 1);
470 template<
typename T>
static inline size_t VectorLength(
const Vector<T> *v) {
471 return v ? v->Length() : 0;
474 struct String :
public Vector<char> {
475 const char *c_str()
const {
return reinterpret_cast<const char *
>(Data()); }
476 std::string str()
const {
return std::string(c_str(), Length()); }
478 bool operator <(
const String &o)
const {
479 return strcmp(c_str(), o.c_str()) < 0;
485 class simple_allocator {
487 virtual ~simple_allocator() {}
488 virtual uint8_t *allocate(
size_t size)
const {
return new uint8_t[size]; }
489 virtual void deallocate(uint8_t *p)
const {
delete[] p; }
495 class vector_downward {
497 explicit vector_downward(
size_t initial_size,
498 const simple_allocator &allocator)
499 : reserved_((initial_size + sizeof(largest_scalar_t) - 1) &
500 ~(sizeof(largest_scalar_t) - 1)),
501 buf_(allocator.allocate(reserved_)),
502 cur_(buf_ + reserved_),
503 allocator_(allocator) {}
507 allocator_.deallocate(buf_);
512 buf_ = allocator_.allocate(reserved_);
514 cur_ = buf_ + reserved_;
517 #ifndef FLATBUFFERS_CPP98_STL
519 unique_ptr_t release() {
521 std::function<void(uint8_t *)> deleter(
522 std::bind(&simple_allocator::deallocate, allocator_, buf_));
525 unique_ptr_t retval(data(), deleter);
535 size_t growth_policy(
size_t bytes) {
536 return (bytes / 2) & ~(
sizeof(largest_scalar_t) - 1);
539 uint8_t *make_space(
size_t len) {
540 if (len > static_cast<size_t>(cur_ - buf_)) {
546 assert(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
550 uoffset_t size()
const {
551 assert(cur_ !=
nullptr && buf_ !=
nullptr);
552 return static_cast<uoffset_t
>(reserved_ - (cur_ - buf_));
555 uint8_t *data()
const {
556 assert(cur_ !=
nullptr);
560 uint8_t *data_at(
size_t offset)
const {
return buf_ + reserved_ - offset; }
562 void push(
const uint8_t *bytes,
size_t num) {
563 auto dest = make_space(num);
564 memcpy(dest, bytes, num);
568 template<
typename T>
void push_small(T little_endian_t) {
569 auto dest = make_space(
sizeof(T));
570 *
reinterpret_cast<T *
>(dest) = little_endian_t;
575 void fill(
size_t zero_pad_bytes) {
576 auto dest = make_space(zero_pad_bytes);
577 for (
size_t i = 0; i < zero_pad_bytes; i++) dest[i] = 0;
581 void fill_big(
size_t zero_pad_bytes) {
582 auto dest = make_space(zero_pad_bytes);
583 memset(dest, 0, zero_pad_bytes);
586 void pop(
size_t bytes_to_remove) { cur_ += bytes_to_remove; }
590 vector_downward(
const vector_downward &);
591 vector_downward &operator=(
const vector_downward &);
596 const simple_allocator &allocator_;
598 void reallocate(
size_t len) {
599 auto old_size = size();
600 auto largest_align = AlignOf<largest_scalar_t>();
601 reserved_ += (std::max)(len, growth_policy(reserved_));
603 reserved_ = (reserved_ + (largest_align - 1)) & ~(largest_align - 1);
604 auto new_buf = allocator_.allocate(reserved_);
605 auto new_cur = new_buf + reserved_ - old_size;
606 memcpy(new_cur, cur_, old_size);
608 allocator_.deallocate(buf_);
614 inline voffset_t FieldIndexToOffset(voffset_t field_id) {
616 const int fixed_fields = 2;
617 return static_cast<voffset_t
>((field_id + fixed_fields) *
sizeof(voffset_t));
623 inline size_t PaddingBytes(
size_t buf_size,
size_t scalar_size) {
624 return ((~buf_size) + 1) & (scalar_size - 1);
627 template <
typename T>
const T* data(
const std::vector<T> &v) {
628 return v.empty() ?
nullptr : &v.front();
630 template <
typename T> T* data(std::vector<T> &v) {
631 return v.empty() ?
nullptr : &v.front();
647 FLATBUFFERS_FINAL_CLASS
658 const simple_allocator *allocator =
nullptr)
659 : buf_(initial_size, allocator ? *allocator : default_allocator),
660 nested(false), finished(false), minalign_(1), force_defaults_(false),
661 dedup_vtables_(true), string_pool(nullptr) {
662 offsetbuf_.reserve(16);
663 vtables_.reserve(16);
668 if (string_pool)
delete string_pool;
680 if (string_pool) string_pool->clear();
685 uoffset_t
GetSize()
const {
return buf_.size(); }
699 #ifndef FLATBUFFERS_CPP98_STL
708 return buf_.release();
723 void Finished()
const {
743 void Pad(
size_t num_bytes) { buf_.fill(num_bytes); }
745 void Align(
size_t elem_size) {
746 if (elem_size > minalign_) minalign_ = elem_size;
747 buf_.fill(PaddingBytes(buf_.size(), elem_size));
750 void PushFlatBuffer(
const uint8_t *bytes,
size_t size) {
751 PushBytes(bytes, size);
755 void PushBytes(
const uint8_t *bytes,
size_t size) {
756 buf_.push(bytes, size);
759 void PopBytes(
size_t amount) { buf_.pop(amount); }
761 template<
typename T>
void AssertScalarT() {
762 #ifndef FLATBUFFERS_CPP98_STL
764 static_assert(std::is_scalar<T>::value
766 ||
sizeof(T) ==
sizeof(Offset<void>),
767 "T must be a scalar type");
772 template<
typename T> uoffset_t PushElement(T element) {
774 T litle_endian_element = EndianScalar(element);
776 buf_.push_small(litle_endian_element);
780 template<
typename T> uoffset_t PushElement(Offset<T> off) {
782 return PushElement(ReferTo(off.o));
787 void TrackField(voffset_t field, uoffset_t off) {
788 FieldLoc fl = { off, field };
789 offsetbuf_.push_back(fl);
793 template<
typename T>
void AddElement(voffset_t field, T e, T def) {
795 if (e == def && !force_defaults_)
return;
796 auto off = PushElement(e);
797 TrackField(field, off);
800 template<
typename T>
void AddOffset(voffset_t field, Offset<T> off) {
802 AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
805 template<
typename T>
void AddStruct(voffset_t field,
const T *structptr) {
806 if (!structptr)
return;
808 buf_.push_small(*structptr);
812 void AddStructOffset(voffset_t field, uoffset_t off) {
813 TrackField(field, off);
819 uoffset_t ReferTo(uoffset_t off) {
821 Align(
sizeof(uoffset_t));
823 assert(off && off <=
GetSize());
824 return GetSize() - off +
static_cast<uoffset_t
>(
sizeof(uoffset_t));
841 uoffset_t StartTable() {
850 uoffset_t EndTable(uoffset_t start, voffset_t numfields) {
855 auto vtableoffsetloc = PushElement<soffset_t>(0);
859 buf_.fill_big(numfields *
sizeof(voffset_t));
860 auto table_object_size = vtableoffsetloc - start;
861 assert(table_object_size < 0x10000);
862 PushElement<voffset_t>(
static_cast<voffset_t
>(table_object_size));
863 PushElement<voffset_t>(FieldIndexToOffset(numfields));
865 for (
auto field_location = offsetbuf_.begin();
866 field_location != offsetbuf_.end();
868 auto pos =
static_cast<voffset_t
>(vtableoffsetloc - field_location->off);
870 assert(!ReadScalar<voffset_t>(buf_.data() + field_location->id));
871 WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
874 auto vt1 =
reinterpret_cast<voffset_t *
>(buf_.data());
875 auto vt1_size = ReadScalar<voffset_t>(vt1);
879 if (dedup_vtables_) {
880 for (
auto it = vtables_.begin(); it != vtables_.end(); ++it) {
881 auto vt2 =
reinterpret_cast<voffset_t *
>(buf_.data_at(*it));
882 auto vt2_size = *vt2;
883 if (vt1_size != vt2_size || memcmp(vt2, vt1, vt1_size))
continue;
885 buf_.pop(
GetSize() - vtableoffsetloc);
891 vtables_.push_back(vt_use);
898 WriteScalar(buf_.data_at(vtableoffsetloc),
899 static_cast<soffset_t
>(vt_use) -
900 static_cast<soffset_t>(vtableoffsetloc));
903 return vtableoffsetloc;
908 template<
typename T>
void Required(Offset<T> table, voffset_t field) {
909 auto table_ptr = buf_.data_at(table.o);
910 auto vtable_ptr = table_ptr - ReadScalar<soffset_t>(table_ptr);
911 bool ok = ReadScalar<voffset_t>(vtable_ptr + field) != 0;
917 uoffset_t StartStruct(
size_t alignment) {
922 uoffset_t EndStruct() {
return GetSize(); }
924 void ClearOffsets() { offsetbuf_.clear(); }
928 void PreAlign(
size_t len,
size_t alignment) {
929 buf_.fill(PaddingBytes(
GetSize() + len, alignment));
931 template<
typename T>
void PreAlign(
size_t len) {
933 PreAlign(len,
sizeof(T));
943 PreAlign<uoffset_t>(len + 1);
945 PushBytes(reinterpret_cast<const uint8_t *>(str), len);
946 PushElement(static_cast<uoffset_t>(len));
947 return Offset<String>(
GetSize());
968 return str ?
CreateString(str->c_str(), str->Length()) : 0;
979 string_pool =
new StringOffsetMap(StringOffsetCompare(buf_));
980 auto size_before_string = buf_.size();
984 auto it = string_pool->find(off);
986 if (it != string_pool->end()) {
988 buf_.pop(buf_.size() - size_before_string);
992 string_pool->insert(off);
1024 uoffset_t EndVector(
size_t len) {
1027 return PushElement(static_cast<uoffset_t>(len));
1030 void StartVector(
size_t len,
size_t elemsize) {
1033 PreAlign<uoffset_t>(len * elemsize);
1034 PreAlign(len * elemsize, elemsize);
1042 void ForceVectorAlignment(
size_t len,
size_t elemsize,
size_t alignment) {
1043 PreAlign(len * elemsize, alignment);
1046 uint8_t *ReserveElements(
size_t len,
size_t elemsize) {
1047 return buf_.make_space(len * elemsize);
1058 template<
typename T> Offset<Vector<T>>
CreateVector(
const T *v,
size_t len) {
1059 StartVector(len,
sizeof(T));
1060 for (
auto i = len; i > 0; ) {
1061 PushElement(v[--i]);
1063 return Offset<Vector<T>>(EndVector(len));
1072 template<
typename T> Offset<Vector<T>>
CreateVector(
const std::vector<T> &v) {
1079 Offset<Vector<uint8_t>>
CreateVector(
const std::vector<bool> &v) {
1080 StartVector(v.size(),
sizeof(uint8_t));
1081 for (
auto i = v.size(); i > 0; ) {
1082 PushElement(static_cast<uint8_t>(v[--i]));
1084 return Offset<Vector<uint8_t>>(EndVector(v.size()));
1087 #ifndef FLATBUFFERS_CPP98_STL
1096 const std::function<T (
size_t i)> &f) {
1097 std::vector<T> elems(vector_size);
1098 for (
size_t i = 0; i < vector_size; i++) elems[i] = f(i);
1110 const std::vector<std::string> &v) {
1111 std::vector<Offset<String>> offsets(v.size());
1112 for (
size_t i = 0; i < v.size(); i++) offsets[i] =
CreateString(v[i]);
1124 const T *v,
size_t len) {
1125 StartVector(len *
sizeof(T) / AlignOf<T>(), AlignOf<T>());
1126 PushBytes(reinterpret_cast<const uint8_t *>(v),
sizeof(T) * len);
1127 return Offset<Vector<const T *>>(EndVector(len));
1130 #ifndef FLATBUFFERS_CPP98_STL
1140 size_t vector_size,
const std::function<
void(
size_t i, T *)> &filler) {
1141 StartVector(vector_size *
sizeof(T) / AlignOf<T>(), AlignOf<T>());
1142 T *structs =
reinterpret_cast<T *
>(buf_.make_space(vector_size *
sizeof(T)));
1143 for (
size_t i = 0; i < vector_size; i++) {
1147 return Offset<Vector<const T *>>(EndVector(vector_size));
1158 const std::vector<T> &v) {
1163 template<
typename T>
1164 struct TableKeyComparator {
1165 TableKeyComparator(vector_downward& buf) : buf_(buf) {}
1166 bool operator()(
const Offset<T> &a,
const Offset<T> &b)
const {
1167 auto table_a =
reinterpret_cast<T *
>(buf_.data_at(a.o));
1168 auto table_b =
reinterpret_cast<T *
>(buf_.data_at(b.o));
1169 return table_a->KeyCompareLessThan(table_b);
1171 vector_downward& buf_;
1174 TableKeyComparator& operator= (
const TableKeyComparator&);
1187 Offset<T> *v,
size_t len) {
1188 std::sort(v, v + len, TableKeyComparator<T>(buf_));
1200 std::vector<Offset<T>> *v) {
1214 StartVector(len, elemsize);
1215 buf_.make_space(len * elemsize);
1217 auto vec_end = EndVector(len);
1218 *buf = buf_.data_at(vec_start);
1231 size_t len, T **buf) {
1233 reinterpret_cast<uint8_t **>(buf));
1242 template<
typename T>
void Finish(Offset<T> root,
1243 const char *file_identifier =
nullptr) {
1245 Finish(root.o, file_identifier,
false);
1256 const char *file_identifier =
nullptr) {
1257 Finish(root.o, file_identifier,
true);
1265 void Finish(uoffset_t root,
const char *file_identifier,
bool size_prefix) {
1268 PreAlign((size_prefix ?
sizeof(uoffset_t) : 0) +
1272 if (file_identifier) {
1274 PushBytes(reinterpret_cast<const uint8_t *>(file_identifier),
1277 PushElement(ReferTo(root));
1289 simple_allocator default_allocator;
1291 vector_downward buf_;
1294 std::vector<FieldLoc> offsetbuf_;
1302 std::vector<uoffset_t> vtables_;
1306 bool force_defaults_;
1308 bool dedup_vtables_;
1310 struct StringOffsetCompare {
1311 StringOffsetCompare(
const vector_downward &buf) : buf_(&buf) {}
1312 bool operator() (
const Offset<String> &a,
const Offset<String> &b)
const {
1313 auto stra =
reinterpret_cast<const String *
>(buf_->data_at(a.o));
1314 auto strb =
reinterpret_cast<const String *
>(buf_->data_at(b.o));
1315 return strncmp(stra->c_str(), strb->c_str(),
1316 std::min(stra->size(), strb->size()) + 1) < 0;
1318 const vector_downward *buf_;
1322 typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
1323 StringOffsetMap *string_pool;
1329 template<
typename T> T *GetMutableRoot(
void *buf) {
1331 return reinterpret_cast<T *
>(
reinterpret_cast<uint8_t *
>(buf) +
1332 EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
1335 template<
typename T>
const T *GetRoot(
const void *buf) {
1336 return GetMutableRoot<T>(
const_cast<void *
>(buf));
1339 template<
typename T>
const T *GetSizePrefixedRoot(
const void *buf) {
1340 return GetRoot<T>(
reinterpret_cast<const uint8_t *
>(buf) +
sizeof(uoffset_t));
1346 template<
typename T> T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb,
1348 return reinterpret_cast<T *
>(fbb.GetCurrentBufferPointer() +
1349 fbb.GetSize() - offset.o);
1352 template<
typename T>
const T *GetTemporaryPointer(FlatBufferBuilder &fbb,
1354 return GetMutableTemporaryPointer<T>(fbb, offset);
1358 inline bool BufferHasIdentifier(
const void *buf,
const char *identifier) {
1359 return strncmp(reinterpret_cast<const char *>(buf) +
sizeof(uoffset_t),
1364 class Verifier FLATBUFFERS_FINAL_CLASS {
1366 Verifier(
const uint8_t *buf,
size_t buf_len,
size_t _max_depth = 64,
1367 size_t _max_tables = 1000000)
1368 : buf_(buf), end_(buf + buf_len), depth_(0), max_depth_(_max_depth),
1369 num_tables_(0), max_tables_(_max_tables)
1370 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1376 bool Check(
bool ok)
const {
1377 #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
1380 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1382 upper_bound_ = buf_;
1388 bool Verify(
const void *elem,
size_t elem_len)
const {
1389 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1390 auto upper_bound =
reinterpret_cast<const uint8_t *
>(elem) + elem_len;
1391 if (upper_bound_ < upper_bound)
1392 upper_bound_ = upper_bound;
1394 return Check(elem_len <= (
size_t) (end_ - buf_) &&
1396 elem <= end_ - elem_len);
1400 template<
typename T>
bool Verify(
const void *elem)
const {
1401 return Verify(elem,
sizeof(T));
1405 template<
typename T>
bool VerifyTable(
const T *table) {
1406 return !table || table->Verify(*
this);
1410 template<
typename T>
bool Verify(
const Vector<T> *vec)
const {
1413 VerifyVector(reinterpret_cast<const uint8_t *>(vec),
sizeof(T),
1418 template<
typename T>
bool Verify(
const Vector<const T *> *vec)
const {
1419 return Verify(
reinterpret_cast<const Vector<T> *
>(vec));
1423 bool Verify(
const String *str)
const {
1426 (VerifyVector(reinterpret_cast<const uint8_t *>(str), 1, &end) &&
1428 Check(*end ==
'\0'));
1432 bool VerifyVector(
const uint8_t *vec,
size_t elem_size,
1433 const uint8_t **end)
const {
1435 if (!Verify<uoffset_t>(vec))
return false;
1438 auto size = ReadScalar<uoffset_t>(vec);
1439 auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
1440 if (!Check(size < max_elems))
1442 auto byte_size =
sizeof(size) + elem_size * size;
1443 *end = vec + byte_size;
1444 return Verify(vec, byte_size);
1448 bool VerifyVectorOfStrings(
const Vector<Offset<String>> *vec)
const {
1450 for (uoffset_t i = 0; i < vec->size(); i++) {
1451 if (!Verify(vec->Get(i)))
return false;
1458 template<
typename T>
bool VerifyVectorOfTables(
const Vector<Offset<T>> *vec) {
1460 for (uoffset_t i = 0; i < vec->size(); i++) {
1461 if (!vec->Get(i)->Verify(*
this))
return false;
1467 template<
typename T>
bool VerifyBufferFromStart(
const char *identifier,
1468 const uint8_t *start) {
1470 (
size_t(end_ - start) < 2 *
sizeof(flatbuffers::uoffset_t) ||
1471 !BufferHasIdentifier(start, identifier))) {
1476 return Verify<uoffset_t>(start) &&
1477 reinterpret_cast<const T *>(start + ReadScalar<uoffset_t>(start))->
1479 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1480 && GetComputedSize()
1486 template<
typename T>
bool VerifyBuffer(
const char *identifier) {
1487 return VerifyBufferFromStart<T>(identifier, buf_);
1490 template<
typename T>
bool VerifySizePrefixedBuffer(
const char *identifier) {
1491 return Verify<uoffset_t>(buf_) &&
1492 ReadScalar<uoffset_t>(buf_) == end_ - buf_ -
sizeof(uoffset_t) &&
1493 VerifyBufferFromStart<T>(identifier, buf_ +
sizeof(uoffset_t));
1500 bool VerifyComplexity() {
1503 return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_);
1512 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1514 size_t GetComputedSize()
const {
1515 uintptr_t size = upper_bound_ - buf_;
1517 size = (size - 1 +
sizeof(uoffset_t)) & ~(
sizeof(uoffset_t) - 1);
1518 return (buf_ + size > end_) ? 0 : size;
1523 const uint8_t *buf_;
1524 const uint8_t *end_;
1529 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1530 mutable const uint8_t *upper_bound_;
1537 struct BufferRefBase {};
1538 template<
typename T>
struct BufferRef : BufferRefBase {
1539 BufferRef() : buf(nullptr), len(0), must_free(false) {}
1540 BufferRef(uint8_t *_buf, uoffset_t _len)
1541 : buf(_buf), len(_len), must_free(false) {}
1543 ~BufferRef() {
if (must_free) free(buf); }
1545 const T *GetRoot()
const {
return flatbuffers::GetRoot<T>(buf); }
1548 Verifier verifier(buf, len);
1549 return verifier.VerifyBuffer<T>(
nullptr);
1561 class Struct FLATBUFFERS_FINAL_CLASS {
1563 template<
typename T> T GetField(uoffset_t o)
const {
1564 return ReadScalar<T>(&data_[o]);
1567 template<
typename T> T GetStruct(uoffset_t o)
const {
1568 return reinterpret_cast<T
>(&data_[o]);
1571 const uint8_t *GetAddressOf(uoffset_t o)
const {
return &data_[o]; }
1572 uint8_t *GetAddressOf(uoffset_t o) {
return &data_[o]; }
1582 const uint8_t *GetVTable()
const {
1583 return data_ - ReadScalar<soffset_t>(data_);
1588 voffset_t GetOptionalFieldOffset(voffset_t field)
const {
1590 auto vtable = GetVTable();
1592 auto vtsize = ReadScalar<voffset_t>(vtable);
1595 return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
1598 template<
typename T> T GetField(voffset_t field, T defaultval)
const {
1599 auto field_offset = GetOptionalFieldOffset(field);
1600 return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
1603 template<
typename P> P GetPointer(voffset_t field) {
1604 auto field_offset = GetOptionalFieldOffset(field);
1605 auto p = data_ + field_offset;
1607 ?
reinterpret_cast<P
>(p + ReadScalar<uoffset_t>(p))
1610 template<
typename P> P GetPointer(voffset_t field)
const {
1611 return const_cast<Table *
>(
this)->GetPointer<P>(field);
1614 template<
typename P> P GetStruct(voffset_t field)
const {
1615 auto field_offset = GetOptionalFieldOffset(field);
1616 auto p =
const_cast<uint8_t *
>(data_ + field_offset);
1617 return field_offset ?
reinterpret_cast<P
>(p) :
nullptr;
1620 template<
typename T>
bool SetField(voffset_t field, T val) {
1621 auto field_offset = GetOptionalFieldOffset(field);
1622 if (!field_offset)
return false;
1623 WriteScalar(data_ + field_offset, val);
1627 bool SetPointer(voffset_t field,
const uint8_t *val) {
1628 auto field_offset = GetOptionalFieldOffset(field);
1629 if (!field_offset)
return false;
1630 WriteScalar(data_ + field_offset,
1631 static_cast<uoffset_t>(val - (data_ + field_offset)));
1635 uint8_t *GetAddressOf(voffset_t field) {
1636 auto field_offset = GetOptionalFieldOffset(field);
1637 return field_offset ? data_ + field_offset :
nullptr;
1639 const uint8_t *GetAddressOf(voffset_t field)
const {
1640 return const_cast<Table *
>(
this)->GetAddressOf(field);
1643 bool CheckField(voffset_t field)
const {
1644 return GetOptionalFieldOffset(field) != 0;
1649 bool VerifyTableStart(Verifier &verifier)
const {
1651 if (!verifier.Verify<soffset_t>(data_))
return false;
1652 auto vtable = GetVTable();
1654 return verifier.VerifyComplexity() &&
1655 verifier.Verify<voffset_t>(vtable) &&
1656 (ReadScalar<voffset_t>(vtable) & (
sizeof(voffset_t) - 1)) == 0 &&
1657 verifier.Verify(vtable, ReadScalar<voffset_t>(vtable));
1661 template<
typename T>
bool VerifyField(
const Verifier &verifier,
1662 voffset_t field)
const {
1665 auto field_offset = GetOptionalFieldOffset(field);
1667 return !field_offset || verifier.Verify<T>(data_ + field_offset);
1671 template<
typename T>
bool VerifyFieldRequired(
const Verifier &verifier,
1672 voffset_t field)
const {
1673 auto field_offset = GetOptionalFieldOffset(field);
1674 return verifier.Check(field_offset != 0) &&
1675 verifier.Verify<T>(data_ + field_offset);
1682 Table(
const Table &other);
1691 inline const uint8_t *GetBufferStartFromRootPointer(
const void *root) {
1692 auto table =
reinterpret_cast<const Table *
>(root);
1693 auto vtable = table->GetVTable();
1695 auto start = std::min(vtable, reinterpret_cast<const uint8_t *>(root));
1697 start =
reinterpret_cast<const uint8_t *
>(
1698 reinterpret_cast<uintptr_t
>(start) & ~(
sizeof(uoffset_t) - 1));
1709 "file_identifier is assumed to be the same size as uoffset_t");
1710 for (
auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT /
sizeof(uoffset_t) + 1;
1713 start -=
sizeof(uoffset_t);
1714 if (ReadScalar<uoffset_t>(start) + start ==
1715 reinterpret_cast<const uint8_t *
>(root))
return start;
1728 struct NativeTable {
1739 typedef uint64_t hash_value_t;
1740 #ifdef FLATBUFFERS_CPP98_STL
1741 typedef void (*resolver_function_t)(
void **pointer_adr, hash_value_t hash);
1742 typedef hash_value_t (*rehasher_function_t)(
void *pointer);
1744 typedef std::function<void (void **pointer_adr, hash_value_t hash)>
1745 resolver_function_t;
1746 typedef std::function<hash_value_t (void *pointer)> rehasher_function_t;
1756 template<
typename T>
bool IsFieldPresent(
const T *table, voffset_t field) {
1758 return reinterpret_cast<const Table *
>(table)->CheckField(field);
1764 inline int LookupEnum(
const char **names,
const char *name) {
1765 for (
const char **p = names; *p; p++)
1766 if (!strcmp(*p, name))
1767 return static_cast<int>(p - names);
1781 #if defined(_MSC_VER)
1782 #define MANUALLY_ALIGNED_STRUCT(alignment) \
1783 __pragma(pack(1)); \
1784 struct __declspec(align(alignment))
1785 #define STRUCT_END(name, size) \
1787 static_assert(sizeof(name) == size, "compiler breaks packing rules")
1788 #elif defined(__GNUC__) || defined(__clang__)
1789 #define MANUALLY_ALIGNED_STRUCT(alignment) \
1790 _Pragma("pack(1)") \
1791 struct __attribute__((aligned(alignment)))
1792 #define STRUCT_END(name, size) \
1794 static_assert(sizeof(name) == size, "compiler breaks packing rules")
1796 #error Unknown compiler, please define structure alignment macros
1809 #if !defined(_WIN32) && !defined(__CYGWIN__)
1811 extern volatile __attribute__((weak)) const
char *flatbuffer_version_string;
1812 volatile __attribute__((weak)) const
char *flatbuffer_version_string =
1814 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
1815 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
1816 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
1818 #endif // !defined(_WIN32) && !defined(__CYGWIN__)
1820 #define DEFINE_BITMASK_OPERATORS(E, T)\
1821 inline E operator | (E lhs, E rhs){\
1822 return E(T(lhs) | T(rhs));\
1824 inline E operator & (E lhs, E rhs){\
1825 return E(T(lhs) & T(rhs));\
1827 inline E operator ^ (E lhs, E rhs){\
1828 return E(T(lhs) ^ T(rhs));\
1830 inline E operator ~ (E lhs){\
1833 inline E operator |= (E &lhs, E rhs){\
1837 inline E operator &= (E &lhs, E rhs){\
1841 inline E operator ^= (E &lhs, E rhs){\
1845 inline bool operator !(E rhs) \
1847 return !bool(T(rhs)); \
1852 #endif // FLATBUFFERS_H_
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:1095
uoffset_t CreateUninitializedVector(size_t len, size_t elemsize, uint8_t **buf)
Specialized version of CreateVector for non-copying use cases.
Definition: flatbuffers.h:1211
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:1139
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:1199
Helper class to hold data needed in creation of a FlatBuffer.
Definition: flatbuffers.h:645
uoffset_t GetSize() const
The current size of the serialized buffer, counting from the end.
Definition: flatbuffers.h:685
FlatBufferBuilder(uoffset_t initial_size=1024, const simple_allocator *allocator=nullptr)
Default constructor for FlatBufferBuilder.
Definition: flatbuffers.h:657
void Clear()
Reset all the state in this FlatBufferBuilder so it can be reused to construct another buffer...
Definition: flatbuffers.h:673
unique_ptr_t ReleaseBufferPointer()
Get the released pointer to the serialized buffer.
Definition: flatbuffers.h:706
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:1255
Offset< String > CreateSharedString(const char *str)
Store a string in the buffer, which null-terminated.
Definition: flatbuffers.h:1001
Offset< String > CreateString(const char *str, size_t len)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:941
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:736
void DedupVtables(bool dedup)
By default vtables are deduped in order to save space.
Definition: flatbuffers.h:740
static const size_t kFileIdentifierLength
The length of a FlatBuffer file header.
Definition: flatbuffers.h:1237
Offset< String > CreateString(const String *str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:967
Offset< String > CreateSharedString(const String *str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1019
Offset< Vector< Offset< String > > > CreateVectorOfStrings(const std::vector< std::string > &v)
Serialize a std::vector into a FlatBuffer vector.
Definition: flatbuffers.h:1109
size_t GetBufferMinAlignment()
get the minimum alignment this buffer needs to be accessed properly.
Definition: flatbuffers.h:717
Offset< Vector< const T * > > CreateVectorOfStructs(const T *v, size_t len)
Serialize an array of structs into a FlatBuffer vector.
Definition: flatbuffers.h:1123
Offset< String > CreateString(const char *str)
Store a string in the buffer, which is null-terminated.
Definition: flatbuffers.h:953
Offset< String > CreateString(const std::string &str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:960
Offset< Vector< T > > CreateVector(const std::vector< T > &v)
Serialize a std::vector into a FlatBuffer vector.
Definition: flatbuffers.h:1072
Offset< Vector< T > > CreateUninitializedVector(size_t len, T **buf)
Specialized version of CreateVector for non-copying use cases.
Definition: flatbuffers.h:1230
uint8_t * GetCurrentBufferPointer() const
Get a pointer to an unfinished buffer.
Definition: flatbuffers.h:697
Offset< Vector< T > > CreateVector(const T *v, size_t len)
Serialize an array into a FlatBuffer vector.
Definition: flatbuffers.h:1058
Offset< String > CreateSharedString(const std::string &str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1010
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:1186
Offset< String > CreateSharedString(const char *str, size_t len)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:977
Offset< Vector< const T * > > CreateVectorOfStructs(const std::vector< T > &v)
Serialize a std::vector of structs into a FlatBuffer vector.
Definition: flatbuffers.h:1157
void Finish(Offset< T > root, const char *file_identifier=nullptr)
Finish serializing a buffer by writing the root offset.
Definition: flatbuffers.h:1242
uint8_t * GetBufferPointer() const
Get the serialized buffer (after you call Finish()).
Definition: flatbuffers.h:690