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 0
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)
133 #ifndef FLATBUFFERS_CPP98_STL
135 typedef std::unique_ptr<uint8_t, std::function<void(uint8_t * )>>
140 template<
typename T>
struct Offset {
143 Offset(uoffset_t _o) : o(_o) {}
144 Offset<void> Union()
const {
return Offset<void>(o); }
147 inline void EndianCheck() {
150 assert(*reinterpret_cast<char *>(&endiantest) == FLATBUFFERS_LITTLEENDIAN);
154 template<
typename T> T EndianSwap(T t) {
155 #if defined(_MSC_VER)
156 #define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
157 #define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
158 #define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
160 #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408
162 #define FLATBUFFERS_BYTESWAP16(x) \
163 static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16))
165 #define FLATBUFFERS_BYTESWAP16 __builtin_bswap16
167 #define FLATBUFFERS_BYTESWAP32 __builtin_bswap32
168 #define FLATBUFFERS_BYTESWAP64 __builtin_bswap64
170 if (
sizeof(T) == 1) {
172 }
else if (
sizeof(T) == 2) {
173 auto r = FLATBUFFERS_BYTESWAP16(*reinterpret_cast<uint16_t *>(&t));
174 return *
reinterpret_cast<T *
>(&r);
175 }
else if (
sizeof(T) == 4) {
176 auto r = FLATBUFFERS_BYTESWAP32(*reinterpret_cast<uint32_t *>(&t));
177 return *
reinterpret_cast<T *
>(&r);
178 }
else if (
sizeof(T) == 8) {
179 auto r = FLATBUFFERS_BYTESWAP64(*reinterpret_cast<uint64_t *>(&t));
180 return *
reinterpret_cast<T *
>(&r);
186 template<
typename T> T EndianScalar(T t) {
187 #if FLATBUFFERS_LITTLEENDIAN
190 return EndianSwap(t);
194 template<
typename T> T ReadScalar(
const void *p) {
195 return EndianScalar(*reinterpret_cast<const T *>(p));
198 template<
typename T>
void WriteScalar(
void *p, T t) {
199 *
reinterpret_cast<T *
>(p) = EndianScalar(t);
202 template<
typename T>
size_t AlignOf() {
207 return __alignof__(T);
222 template<
typename T>
struct IndirectHelper {
223 typedef T return_type;
224 typedef T mutable_return_type;
225 static const size_t element_stride =
sizeof(T);
226 static return_type Read(
const uint8_t *p, uoffset_t i) {
227 return EndianScalar((reinterpret_cast<const T *>(p))[i]);
230 template<
typename T>
struct IndirectHelper<Offset<T>> {
231 typedef const T *return_type;
232 typedef T *mutable_return_type;
233 static const size_t element_stride =
sizeof(uoffset_t);
234 static return_type Read(
const uint8_t *p, uoffset_t i) {
235 p += i *
sizeof(uoffset_t);
236 return reinterpret_cast<return_type
>(p + ReadScalar<uoffset_t>(p));
239 template<
typename T>
struct IndirectHelper<const T *> {
240 typedef const T *return_type;
241 typedef T *mutable_return_type;
242 static const size_t element_stride =
sizeof(T);
243 static return_type Read(
const uint8_t *p, uoffset_t i) {
244 return reinterpret_cast<const T *
>(p + i *
sizeof(T));
250 template<
typename T,
typename IT>
251 struct VectorIterator
252 :
public std::iterator<std::input_iterator_tag, IT, uoffset_t> {
254 typedef std::iterator<std::input_iterator_tag, IT, uoffset_t> super_type;
257 VectorIterator(
const uint8_t *data, uoffset_t i) :
258 data_(data + IndirectHelper<T>::element_stride * i) {}
259 VectorIterator(
const VectorIterator &other) : data_(other.data_) {}
260 #ifndef FLATBUFFERS_CPP98_STL
261 VectorIterator(VectorIterator &&other) : data_(std::move(other.data_)) {}
264 VectorIterator &operator=(
const VectorIterator &other) {
269 VectorIterator &operator=(VectorIterator &&other) {
274 bool operator==(
const VectorIterator& other)
const {
275 return data_ == other.data_;
278 bool operator!=(
const VectorIterator& other)
const {
279 return data_ != other.data_;
282 ptrdiff_t operator-(
const VectorIterator& other)
const {
283 return (data_ - other.data_) / IndirectHelper<T>::element_stride;
286 typename super_type::value_type operator *()
const {
287 return IndirectHelper<T>::Read(data_, 0);
290 typename super_type::value_type operator->()
const {
291 return IndirectHelper<T>::Read(data_, 0);
294 VectorIterator &operator++() {
295 data_ += IndirectHelper<T>::element_stride;
299 VectorIterator operator++(
int) {
300 VectorIterator temp(data_,0);
301 data_ += IndirectHelper<T>::element_stride;
306 const uint8_t *data_;
311 template<
typename T>
class Vector {
313 typedef VectorIterator<T, typename IndirectHelper<T>::mutable_return_type>
315 typedef VectorIterator<T, typename IndirectHelper<T>::return_type>
318 uoffset_t size()
const {
return EndianScalar(length_); }
321 uoffset_t Length()
const {
return size(); }
323 typedef typename IndirectHelper<T>::return_type return_type;
324 typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
326 return_type Get(uoffset_t i)
const {
328 return IndirectHelper<T>::Read(Data(), i);
331 return_type operator[](uoffset_t i)
const {
return Get(i); }
336 template<
typename E> E GetEnum(uoffset_t i)
const {
337 return static_cast<E
>(Get(i));
340 const void *GetStructFromOffset(
size_t o)
const {
341 return reinterpret_cast<const void *
>(Data() + o);
344 iterator begin() {
return iterator(Data(), 0); }
345 const_iterator begin()
const {
return const_iterator(Data(), 0); }
347 iterator end() {
return iterator(Data(), size()); }
348 const_iterator end()
const {
return const_iterator(Data(), size()); }
352 void Mutate(uoffset_t i,
const T& val) {
354 WriteScalar(data() + i, val);
360 void MutateOffset(uoffset_t i,
const uint8_t *val) {
362 assert(
sizeof(T) ==
sizeof(uoffset_t));
363 WriteScalar(data() + i,
364 static_cast<uoffset_t>(val - (Data() + i *
sizeof(uoffset_t))));
368 mutable_return_type GetMutableObject(uoffset_t i)
const {
370 return const_cast<mutable_return_type
>(IndirectHelper<T>::Read(Data(), i));
374 const uint8_t *Data()
const {
375 return reinterpret_cast<const uint8_t *
>(&length_ + 1);
379 return reinterpret_cast<uint8_t *
>(&length_ + 1);
383 const T *data()
const {
return reinterpret_cast<const T *
>(Data()); }
384 T *data() {
return reinterpret_cast<T *
>(Data()); }
386 template<
typename K> return_type LookupByKey(K key)
const {
387 void *search_result = std::bsearch(&key, Data(), size(),
388 IndirectHelper<T>::element_stride, KeyCompare<K>);
390 if (!search_result) {
394 const uint8_t *element =
reinterpret_cast<const uint8_t *
>(search_result);
396 return IndirectHelper<T>::Read(element, 0);
407 template<
typename K>
static int KeyCompare(
const void *ap,
const void *bp) {
408 const K *key =
reinterpret_cast<const K *
>(ap);
409 const uint8_t *data =
reinterpret_cast<const uint8_t *
>(bp);
410 auto table = IndirectHelper<T>::Read(data, 0);
414 return -table->KeyCompareWithValue(*key);
422 uoffset_t size()
const {
return EndianScalar(length_); }
424 const uint8_t *Data()
const {
425 return reinterpret_cast<const uint8_t *
>(&length_ + 1);
428 return reinterpret_cast<uint8_t *
>(&length_ + 1);
438 template<
typename T>
static inline size_t VectorLength(
const Vector<T> *v) {
439 return v ? v->Length() : 0;
442 struct String :
public Vector<char> {
443 const char *c_str()
const {
return reinterpret_cast<const char *
>(Data()); }
444 std::string str()
const {
return std::string(c_str(), Length()); }
446 bool operator <(
const String &o)
const {
447 return strcmp(c_str(), o.c_str()) < 0;
453 class simple_allocator {
455 virtual ~simple_allocator() {}
456 virtual uint8_t *allocate(
size_t size)
const {
return new uint8_t[size]; }
457 virtual void deallocate(uint8_t *p)
const {
delete[] p; }
463 class vector_downward {
465 explicit vector_downward(
size_t initial_size,
466 const simple_allocator &allocator)
467 : reserved_(initial_size),
468 buf_(allocator.allocate(reserved_)),
469 cur_(buf_ + reserved_),
470 allocator_(allocator) {
471 assert((initial_size & (
sizeof(largest_scalar_t) - 1)) == 0);
476 allocator_.deallocate(buf_);
481 buf_ = allocator_.allocate(reserved_);
483 cur_ = buf_ + reserved_;
486 #ifndef FLATBUFFERS_CPP98_STL
488 unique_ptr_t release() {
490 std::function<void(uint8_t *)> deleter(
491 std::bind(&simple_allocator::deallocate, allocator_, buf_));
494 unique_ptr_t retval(data(), deleter);
504 size_t growth_policy(
size_t bytes) {
505 return (bytes / 2) & ~(
sizeof(largest_scalar_t) - 1);
508 uint8_t *make_space(
size_t len) {
509 if (len > static_cast<size_t>(cur_ - buf_)) {
510 auto old_size = size();
511 auto largest_align = AlignOf<largest_scalar_t>();
512 reserved_ += (std::max)(len, growth_policy(reserved_));
514 reserved_ = (reserved_ + (largest_align - 1)) & ~(largest_align - 1);
515 auto new_buf = allocator_.allocate(reserved_);
516 auto new_cur = new_buf + reserved_ - old_size;
517 memcpy(new_cur, cur_, old_size);
519 allocator_.deallocate(buf_);
525 assert(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
529 uoffset_t size()
const {
530 assert(cur_ !=
nullptr && buf_ !=
nullptr);
531 return static_cast<uoffset_t
>(reserved_ - (cur_ - buf_));
534 uint8_t *data()
const {
535 assert(cur_ !=
nullptr);
539 uint8_t *data_at(
size_t offset)
const {
return buf_ + reserved_ - offset; }
543 void push(
const uint8_t *bytes,
size_t num) {
544 auto dest = make_space(num);
545 for (
size_t i = 0; i < num; i++) dest[i] = bytes[i];
548 void fill(
size_t zero_pad_bytes) {
549 auto dest = make_space(zero_pad_bytes);
550 for (
size_t i = 0; i < zero_pad_bytes; i++) dest[i] = 0;
553 void pop(
size_t bytes_to_remove) { cur_ += bytes_to_remove; }
557 vector_downward(
const vector_downward &);
558 vector_downward &operator=(
const vector_downward &);
563 const simple_allocator &allocator_;
567 inline voffset_t FieldIndexToOffset(voffset_t field_id) {
569 const int fixed_fields = 2;
570 return static_cast<voffset_t
>((field_id + fixed_fields) *
sizeof(voffset_t));
576 inline size_t PaddingBytes(
size_t buf_size,
size_t scalar_size) {
577 return ((~buf_size) + 1) & (scalar_size - 1);
580 template <
typename T>
const T* data(
const std::vector<T> &v) {
581 return v.empty() ?
nullptr : &v.front();
596 FLATBUFFERS_FINAL_CLASS
607 const simple_allocator *allocator =
nullptr)
608 : buf_(initial_size, allocator ? *allocator : default_allocator),
609 nested(false), finished(false), minalign_(1), force_defaults_(false),
610 string_pool(nullptr) {
611 offsetbuf_.reserve(16);
612 vtables_.reserve(16);
617 if (string_pool)
delete string_pool;
629 if (string_pool) string_pool->clear();
634 uoffset_t
GetSize()
const {
return buf_.size(); }
648 #ifndef FLATBUFFERS_CPP98_STL
657 return buf_.release();
672 void Finished()
const {
688 void Pad(
size_t num_bytes) { buf_.fill(num_bytes); }
690 void Align(
size_t elem_size) {
691 if (elem_size > minalign_) minalign_ = elem_size;
692 buf_.fill(PaddingBytes(buf_.size(), elem_size));
695 void PushFlatBuffer(
const uint8_t *bytes,
size_t size) {
696 PushBytes(bytes, size);
700 void PushBytes(
const uint8_t *bytes,
size_t size) {
701 buf_.push(bytes, size);
704 void PopBytes(
size_t amount) { buf_.pop(amount); }
706 template<
typename T>
void AssertScalarT() {
707 #ifndef FLATBUFFERS_CPP98_STL
709 static_assert(std::is_scalar<T>::value
711 ||
sizeof(T) ==
sizeof(Offset<void>),
712 "T must be a scalar type");
717 template<
typename T> uoffset_t PushElement(T element) {
719 T litle_endian_element = EndianScalar(element);
721 PushBytes(reinterpret_cast<uint8_t *>(&litle_endian_element),
sizeof(T));
725 template<
typename T> uoffset_t PushElement(Offset<T> off) {
727 return PushElement(ReferTo(off.o));
732 void TrackField(voffset_t field, uoffset_t off) {
733 FieldLoc fl = { off, field };
734 offsetbuf_.push_back(fl);
738 template<
typename T>
void AddElement(voffset_t field, T e, T def) {
740 if (e == def && !force_defaults_)
return;
741 auto off = PushElement(e);
742 TrackField(field, off);
745 template<
typename T>
void AddOffset(voffset_t field, Offset<T> off) {
747 AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
750 template<
typename T>
void AddStruct(voffset_t field,
const T *structptr) {
751 if (!structptr)
return;
753 PushBytes(reinterpret_cast<const uint8_t *>(structptr),
sizeof(T));
757 void AddStructOffset(voffset_t field, uoffset_t off) {
758 TrackField(field, off);
764 uoffset_t ReferTo(uoffset_t off) {
766 Align(
sizeof(uoffset_t));
768 assert(off && off <=
GetSize());
769 return GetSize() - off +
static_cast<uoffset_t
>(
sizeof(uoffset_t));
786 uoffset_t StartTable() {
795 uoffset_t EndTable(uoffset_t start, voffset_t numfields) {
800 auto vtableoffsetloc = PushElement<soffset_t>(0);
804 buf_.fill(numfields *
sizeof(voffset_t));
805 auto table_object_size = vtableoffsetloc - start;
806 assert(table_object_size < 0x10000);
807 PushElement<voffset_t>(
static_cast<voffset_t
>(table_object_size));
808 PushElement<voffset_t>(FieldIndexToOffset(numfields));
810 for (
auto field_location = offsetbuf_.begin();
811 field_location != offsetbuf_.end();
813 auto pos =
static_cast<voffset_t
>(vtableoffsetloc - field_location->off);
815 assert(!ReadScalar<voffset_t>(buf_.data() + field_location->id));
816 WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
819 auto vt1 =
reinterpret_cast<voffset_t *
>(buf_.data());
820 auto vt1_size = ReadScalar<voffset_t>(vt1);
824 for (
auto it = vtables_.begin(); it != vtables_.end(); ++it) {
825 auto vt2 =
reinterpret_cast<voffset_t *
>(buf_.data_at(*it));
826 auto vt2_size = *vt2;
827 if (vt1_size != vt2_size || memcmp(vt2, vt1, vt1_size))
continue;
829 buf_.pop(
GetSize() - vtableoffsetloc);
834 vtables_.push_back(vt_use);
841 WriteScalar(buf_.data_at(vtableoffsetloc),
842 static_cast<soffset_t
>(vt_use) -
843 static_cast<soffset_t>(vtableoffsetloc));
846 return vtableoffsetloc;
851 template<
typename T>
void Required(Offset<T> table, voffset_t field) {
852 auto table_ptr = buf_.data_at(table.o);
853 auto vtable_ptr = table_ptr - ReadScalar<soffset_t>(table_ptr);
854 bool ok = ReadScalar<voffset_t>(vtable_ptr + field) != 0;
860 uoffset_t StartStruct(
size_t alignment) {
865 uoffset_t EndStruct() {
return GetSize(); }
867 void ClearOffsets() { offsetbuf_.clear(); }
871 void PreAlign(
size_t len,
size_t alignment) {
872 buf_.fill(PaddingBytes(
GetSize() + len, alignment));
874 template<
typename T>
void PreAlign(
size_t len) {
876 PreAlign(len,
sizeof(T));
886 PreAlign<uoffset_t>(len + 1);
888 PushBytes(reinterpret_cast<const uint8_t *>(str), len);
889 PushElement(static_cast<uoffset_t>(len));
890 return Offset<String>(
GetSize());
911 return str ?
CreateString(str->c_str(), str->Length()) : 0;
922 string_pool =
new StringOffsetMap(StringOffsetCompare(buf_));
923 auto size_before_string = buf_.size();
927 auto it = string_pool->find(off);
929 if (it != string_pool->end()) {
931 buf_.pop(buf_.size() - size_before_string);
935 string_pool->insert(off);
967 uoffset_t EndVector(
size_t len) {
970 return PushElement(static_cast<uoffset_t>(len));
973 void StartVector(
size_t len,
size_t elemsize) {
976 PreAlign<uoffset_t>(len * elemsize);
977 PreAlign(len * elemsize, elemsize);
985 void ForceVectorAlignment(
size_t len,
size_t elemsize,
size_t alignment) {
986 PreAlign(len * elemsize, alignment);
989 uint8_t *ReserveElements(
size_t len,
size_t elemsize) {
990 return buf_.make_space(len * elemsize);
1001 template<
typename T> Offset<Vector<T>>
CreateVector(
const T *v,
size_t len) {
1002 StartVector(len,
sizeof(T));
1003 for (
auto i = len; i > 0; ) {
1004 PushElement(v[--i]);
1006 return Offset<Vector<T>>(EndVector(len));
1015 template<
typename T> Offset<Vector<T>>
CreateVector(
const std::vector<T> &v) {
1022 Offset<Vector<uint8_t>>
CreateVector(
const std::vector<bool> &v) {
1023 StartVector(v.size(),
sizeof(uint8_t));
1024 for (
auto i = v.size(); i > 0; ) {
1025 PushElement(static_cast<uint8_t>(v[--i]));
1027 return Offset<Vector<uint8_t>>(EndVector(v.size()));
1030 #ifndef FLATBUFFERS_CPP98_STL
1039 const std::function<T (
size_t i)> &f) {
1040 std::vector<T> elems(vector_size);
1041 for (
size_t i = 0; i < vector_size; i++) elems[i] = f(i);
1053 const std::vector<std::string> &v) {
1054 std::vector<Offset<String>> offsets(v.size());
1055 for (
size_t i = 0; i < v.size(); i++) offsets[i] =
CreateString(v[i]);
1067 const T *v,
size_t len) {
1068 StartVector(len *
sizeof(T) / AlignOf<T>(), AlignOf<T>());
1069 PushBytes(reinterpret_cast<const uint8_t *>(v),
sizeof(T) * len);
1070 return Offset<Vector<const T *>>(EndVector(len));
1080 const std::vector<T> &v) {
1085 template<
typename T>
1086 struct TableKeyComparator {
1087 TableKeyComparator(vector_downward& buf) : buf_(buf) {}
1088 bool operator()(
const Offset<T> &a,
const Offset<T> &b)
const {
1089 auto table_a =
reinterpret_cast<T *
>(buf_.data_at(a.o));
1090 auto table_b =
reinterpret_cast<T *
>(buf_.data_at(b.o));
1091 return table_a->KeyCompareLessThan(table_b);
1093 vector_downward& buf_;
1096 TableKeyComparator& operator= (
const TableKeyComparator&);
1109 Offset<T> *v,
size_t len) {
1110 std::sort(v, v + len, TableKeyComparator<T>(buf_));
1122 std::vector<Offset<T>> *v) {
1136 StartVector(len, elemsize);
1137 buf_.make_space(len * elemsize);
1139 auto vec_end = EndVector(len);
1140 *buf = buf_.data_at(vec_start);
1153 size_t len, T **buf) {
1155 reinterpret_cast<uint8_t **>(buf));
1164 template<
typename T>
void Finish(Offset<T> root,
1165 const char *file_identifier =
nullptr) {
1167 Finish(root.o, file_identifier,
false);
1178 const char *file_identifier =
nullptr) {
1179 Finish(root.o, file_identifier,
true);
1187 void Finish(uoffset_t root,
const char *file_identifier,
bool size_prefix) {
1190 PreAlign((size_prefix ?
sizeof(uoffset_t) : 0) +
1194 if (file_identifier) {
1196 buf_.push(reinterpret_cast<const uint8_t *>(file_identifier),
1199 PushElement(ReferTo(root));
1211 simple_allocator default_allocator;
1213 vector_downward buf_;
1216 std::vector<FieldLoc> offsetbuf_;
1224 std::vector<uoffset_t> vtables_;
1228 bool force_defaults_;
1230 struct StringOffsetCompare {
1231 StringOffsetCompare(
const vector_downward &buf) : buf_(&buf) {}
1232 bool operator() (
const Offset<String> &a,
const Offset<String> &b)
const {
1233 auto stra =
reinterpret_cast<const String *
>(buf_->data_at(a.o));
1234 auto strb =
reinterpret_cast<const String *
>(buf_->data_at(b.o));
1235 return strncmp(stra->c_str(), strb->c_str(),
1236 std::min(stra->size(), strb->size()) + 1) < 0;
1238 const vector_downward *buf_;
1242 typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
1243 StringOffsetMap *string_pool;
1249 template<
typename T> T *GetMutableRoot(
void *buf) {
1251 return reinterpret_cast<T *
>(
reinterpret_cast<uint8_t *
>(buf) +
1252 EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
1255 template<
typename T>
const T *GetRoot(
const void *buf) {
1256 return GetMutableRoot<T>(
const_cast<void *
>(buf));
1259 template<
typename T>
const T *GetSizePrefixedRoot(
const void *buf) {
1260 return GetRoot<T>(
reinterpret_cast<const uint8_t *
>(buf) +
sizeof(uoffset_t));
1266 template<
typename T> T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb,
1268 return reinterpret_cast<T *
>(fbb.GetCurrentBufferPointer() +
1269 fbb.GetSize() - offset.o);
1272 template<
typename T>
const T *GetTemporaryPointer(FlatBufferBuilder &fbb,
1274 return GetMutableTemporaryPointer<T>(fbb, offset);
1278 inline bool BufferHasIdentifier(
const void *buf,
const char *identifier) {
1279 return strncmp(reinterpret_cast<const char *>(buf) +
sizeof(uoffset_t),
1284 class Verifier FLATBUFFERS_FINAL_CLASS {
1286 Verifier(
const uint8_t *buf,
size_t buf_len,
size_t _max_depth = 64,
1287 size_t _max_tables = 1000000)
1288 : buf_(buf), end_(buf + buf_len), depth_(0), max_depth_(_max_depth),
1289 num_tables_(0), max_tables_(_max_tables)
1290 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1296 bool Check(
bool ok)
const {
1297 #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
1300 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1302 upper_bound_ = buf_;
1308 bool Verify(
const void *elem,
size_t elem_len)
const {
1309 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1310 auto upper_bound =
reinterpret_cast<const uint8_t *
>(elem) + elem_len;
1311 if (upper_bound_ < upper_bound)
1312 upper_bound_ = upper_bound;
1314 return Check(elem_len <= (
size_t) (end_ - buf_) &&
1316 elem <= end_ - elem_len);
1320 template<
typename T>
bool Verify(
const void *elem)
const {
1321 return Verify(elem,
sizeof(T));
1325 template<
typename T>
bool VerifyTable(
const T *table) {
1326 return !table || table->Verify(*
this);
1330 template<
typename T>
bool Verify(
const Vector<T> *vec)
const {
1333 VerifyVector(reinterpret_cast<const uint8_t *>(vec),
sizeof(T),
1338 template<
typename T>
bool Verify(
const Vector<const T *> *vec)
const {
1339 return Verify(
reinterpret_cast<const Vector<T> *
>(vec));
1343 bool Verify(
const String *str)
const {
1346 (VerifyVector(reinterpret_cast<const uint8_t *>(str), 1, &end) &&
1348 Check(*end ==
'\0'));
1352 bool VerifyVector(
const uint8_t *vec,
size_t elem_size,
1353 const uint8_t **end)
const {
1355 if (!Verify<uoffset_t>(vec))
return false;
1358 auto size = ReadScalar<uoffset_t>(vec);
1359 auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
1360 if (!Check(size < max_elems))
1362 auto byte_size =
sizeof(size) + elem_size * size;
1363 *end = vec + byte_size;
1364 return Verify(vec, byte_size);
1368 bool VerifyVectorOfStrings(
const Vector<Offset<String>> *vec)
const {
1370 for (uoffset_t i = 0; i < vec->size(); i++) {
1371 if (!Verify(vec->Get(i)))
return false;
1378 template<
typename T>
bool VerifyVectorOfTables(
const Vector<Offset<T>> *vec) {
1380 for (uoffset_t i = 0; i < vec->size(); i++) {
1381 if (!vec->Get(i)->Verify(*
this))
return false;
1387 template<
typename T>
bool VerifyBufferFromStart(
const char *identifier,
1388 const uint8_t *start) {
1390 (
size_t(end_ - start) < 2 *
sizeof(flatbuffers::uoffset_t) ||
1391 !BufferHasIdentifier(start, identifier))) {
1396 return Verify<uoffset_t>(start) &&
1397 reinterpret_cast<const T *>(start + ReadScalar<uoffset_t>(start))->
1399 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1400 && GetComputedSize()
1406 template<
typename T>
bool VerifyBuffer(
const char *identifier) {
1407 return VerifyBufferFromStart<T>(identifier, buf_);
1410 template<
typename T>
bool VerifySizePrefixedBuffer(
const char *identifier) {
1411 return Verify<uoffset_t>(buf_) &&
1412 ReadScalar<uoffset_t>(buf_) == end_ - buf_ -
sizeof(uoffset_t) &&
1413 VerifyBufferFromStart<T>(identifier, buf_ +
sizeof(uoffset_t));
1420 bool VerifyComplexity() {
1423 return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_);
1432 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1434 size_t GetComputedSize()
const {
1435 uintptr_t size = upper_bound_ - buf_;
1437 size = (size - 1 +
sizeof(uoffset_t)) & ~(
sizeof(uoffset_t) - 1);
1438 return (buf_ + size > end_) ? 0 : size;
1443 const uint8_t *buf_;
1444 const uint8_t *end_;
1449 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
1450 mutable const uint8_t *upper_bound_;
1457 struct BufferRefBase {};
1458 template<
typename T>
struct BufferRef : BufferRefBase {
1459 BufferRef() : buf(nullptr), len(0), must_free(false) {}
1460 BufferRef(uint8_t *_buf, uoffset_t _len)
1461 : buf(_buf), len(_len), must_free(false) {}
1463 ~BufferRef() {
if (must_free) free(buf); }
1465 const T *GetRoot()
const {
return flatbuffers::GetRoot<T>(buf); }
1468 Verifier verifier(buf, len);
1469 return verifier.VerifyBuffer<T>();
1481 class Struct FLATBUFFERS_FINAL_CLASS {
1483 template<
typename T> T GetField(uoffset_t o)
const {
1484 return ReadScalar<T>(&data_[o]);
1487 template<
typename T> T GetStruct(uoffset_t o)
const {
1488 return reinterpret_cast<T
>(&data_[o]);
1491 const uint8_t *GetAddressOf(uoffset_t o)
const {
return &data_[o]; }
1492 uint8_t *GetAddressOf(uoffset_t o) {
return &data_[o]; }
1504 voffset_t GetOptionalFieldOffset(voffset_t field)
const {
1506 auto vtable = data_ - ReadScalar<soffset_t>(data_);
1508 auto vtsize = ReadScalar<voffset_t>(vtable);
1511 return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
1514 template<
typename T> T GetField(voffset_t field, T defaultval)
const {
1515 auto field_offset = GetOptionalFieldOffset(field);
1516 return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
1519 template<
typename P> P GetPointer(voffset_t field) {
1520 auto field_offset = GetOptionalFieldOffset(field);
1521 auto p = data_ + field_offset;
1523 ?
reinterpret_cast<P
>(p + ReadScalar<uoffset_t>(p))
1526 template<
typename P> P GetPointer(voffset_t field)
const {
1527 return const_cast<Table *
>(
this)->GetPointer<P>(field);
1530 template<
typename P> P GetStruct(voffset_t field)
const {
1531 auto field_offset = GetOptionalFieldOffset(field);
1532 auto p =
const_cast<uint8_t *
>(data_ + field_offset);
1533 return field_offset ?
reinterpret_cast<P
>(p) :
nullptr;
1536 template<
typename T>
bool SetField(voffset_t field, T val) {
1537 auto field_offset = GetOptionalFieldOffset(field);
1538 if (!field_offset)
return false;
1539 WriteScalar(data_ + field_offset, val);
1543 bool SetPointer(voffset_t field,
const uint8_t *val) {
1544 auto field_offset = GetOptionalFieldOffset(field);
1545 if (!field_offset)
return false;
1546 WriteScalar(data_ + field_offset,
1547 static_cast<uoffset_t>(val - (data_ + field_offset)));
1551 uint8_t *GetAddressOf(voffset_t field) {
1552 auto field_offset = GetOptionalFieldOffset(field);
1553 return field_offset ? data_ + field_offset :
nullptr;
1555 const uint8_t *GetAddressOf(voffset_t field)
const {
1556 return const_cast<Table *
>(
this)->GetAddressOf(field);
1559 uint8_t *GetVTable() {
return data_ - ReadScalar<soffset_t>(data_); }
1561 bool CheckField(voffset_t field)
const {
1562 return GetOptionalFieldOffset(field) != 0;
1567 bool VerifyTableStart(Verifier &verifier)
const {
1569 if (!verifier.Verify<soffset_t>(data_))
return false;
1570 auto vtable = data_ - ReadScalar<soffset_t>(data_);
1572 return verifier.VerifyComplexity() &&
1573 verifier.Verify<voffset_t>(vtable) &&
1574 (ReadScalar<voffset_t>(vtable) & (
sizeof(voffset_t) - 1)) == 0 &&
1575 verifier.Verify(vtable, ReadScalar<voffset_t>(vtable));
1579 template<
typename T>
bool VerifyField(
const Verifier &verifier,
1580 voffset_t field)
const {
1583 auto field_offset = GetOptionalFieldOffset(field);
1585 return !field_offset || verifier.Verify<T>(data_ + field_offset);
1589 template<
typename T>
bool VerifyFieldRequired(
const Verifier &verifier,
1590 voffset_t field)
const {
1591 auto field_offset = GetOptionalFieldOffset(field);
1592 return verifier.Check(field_offset != 0) &&
1593 verifier.Verify<T>(data_ + field_offset);
1600 Table(
const Table &other);
1608 struct NativeTable {
1619 typedef uint64_t hash_value_t;
1620 #ifdef FLATBUFFERS_CPP98_STL
1621 typedef void (*resolver_function_t)(
void **pointer_adr, hash_value_t hash);
1622 typedef hash_value_t (*rehasher_function_t)(
void *pointer);
1624 typedef std::function<void (void **pointer_adr, hash_value_t hash)>
1625 resolver_function_t;
1626 typedef std::function<hash_value_t (void *pointer)> rehasher_function_t;
1636 template<
typename T>
bool IsFieldPresent(
const T *table, voffset_t field) {
1638 return reinterpret_cast<const Table *
>(table)->CheckField(field);
1644 inline int LookupEnum(
const char **names,
const char *name) {
1645 for (
const char **p = names; *p; p++)
1646 if (!strcmp(*p, name))
1647 return static_cast<int>(p - names);
1661 #if defined(_MSC_VER)
1662 #define MANUALLY_ALIGNED_STRUCT(alignment) \
1663 __pragma(pack(1)); \
1664 struct __declspec(align(alignment))
1665 #define STRUCT_END(name, size) \
1667 static_assert(sizeof(name) == size, "compiler breaks packing rules")
1668 #elif defined(__GNUC__) || defined(__clang__)
1669 #define MANUALLY_ALIGNED_STRUCT(alignment) \
1670 _Pragma("pack(1)") \
1671 struct __attribute__((aligned(alignment)))
1672 #define STRUCT_END(name, size) \
1674 static_assert(sizeof(name) == size, "compiler breaks packing rules")
1676 #error Unknown compiler, please define structure alignment macros
1689 #if !defined(_WIN32) && !defined(__CYGWIN__)
1691 extern volatile __attribute__((weak)) const
char *flatbuffer_version_string;
1692 volatile __attribute__((weak)) const
char *flatbuffer_version_string =
1694 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
1695 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
1696 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
1698 #endif // !defined(_WIN32) && !defined(__CYGWIN__)
1700 #define DEFINE_BITMASK_OPERATORS(E, T)\
1701 inline E operator | (E lhs, E rhs){\
1702 return E(T(lhs) | T(rhs));\
1704 inline E operator & (E lhs, E rhs){\
1705 return E(T(lhs) & T(rhs));\
1707 inline E operator ^ (E lhs, E rhs){\
1708 return E(T(lhs) ^ T(rhs));\
1710 inline E operator ~ (E lhs){\
1713 inline E operator |= (E &lhs, E rhs){\
1717 inline E operator &= (E &lhs, E rhs){\
1721 inline E operator ^= (E &lhs, E rhs){\
1725 inline bool operator !(E rhs) \
1727 return !bool(T(rhs)); \
1732 #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:1038
uoffset_t CreateUninitializedVector(size_t len, size_t elemsize, uint8_t **buf)
Specialized version of CreateVector for non-copying use cases.
Definition: flatbuffers.h:1133
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:1121
Helper class to hold data needed in creation of a FlatBuffer.
Definition: flatbuffers.h:594
uoffset_t GetSize() const
The current size of the serialized buffer, counting from the end.
Definition: flatbuffers.h:634
FlatBufferBuilder(uoffset_t initial_size=1024, const simple_allocator *allocator=nullptr)
Default constructor for FlatBufferBuilder.
Definition: flatbuffers.h:606
void Clear()
Reset all the state in this FlatBufferBuilder so it can be reused to construct another buffer...
Definition: flatbuffers.h:622
unique_ptr_t ReleaseBufferPointer()
Get the released pointer to the serialized buffer.
Definition: flatbuffers.h:655
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:1177
Offset< String > CreateSharedString(const char *str)
Store a string in the buffer, which null-terminated.
Definition: flatbuffers.h:944
Offset< String > CreateString(const char *str, size_t len)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:884
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:685
static const size_t kFileIdentifierLength
The length of a FlatBuffer file header.
Definition: flatbuffers.h:1159
Offset< String > CreateString(const String *str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:910
Offset< String > CreateSharedString(const String *str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:962
Offset< Vector< Offset< String > > > CreateVectorOfStrings(const std::vector< std::string > &v)
Serialize a std::vector into a FlatBuffer vector.
Definition: flatbuffers.h:1052
size_t GetBufferMinAlignment()
get the minimum alignment this buffer needs to be accessed properly.
Definition: flatbuffers.h:666
Offset< Vector< const T * > > CreateVectorOfStructs(const T *v, size_t len)
Serialize an array of structs into a FlatBuffer vector.
Definition: flatbuffers.h:1066
Offset< String > CreateString(const char *str)
Store a string in the buffer, which is null-terminated.
Definition: flatbuffers.h:896
Offset< String > CreateString(const std::string &str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:903
Offset< Vector< T > > CreateVector(const std::vector< T > &v)
Serialize a std::vector into a FlatBuffer vector.
Definition: flatbuffers.h:1015
Offset< Vector< T > > CreateUninitializedVector(size_t len, T **buf)
Specialized version of CreateVector for non-copying use cases.
Definition: flatbuffers.h:1152
uint8_t * GetCurrentBufferPointer() const
Get a pointer to an unfinished buffer.
Definition: flatbuffers.h:646
Offset< Vector< T > > CreateVector(const T *v, size_t len)
Serialize an array into a FlatBuffer vector.
Definition: flatbuffers.h:1001
Offset< String > CreateSharedString(const std::string &str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:953
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:1108
Offset< String > CreateSharedString(const char *str, size_t len)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:920
Offset< Vector< const T * > > CreateVectorOfStructs(const std::vector< T > &v)
Serialize a std::vector of structs into a FlatBuffer vector.
Definition: flatbuffers.h:1079
void Finish(Offset< T > root, const char *file_identifier=nullptr)
Finish serializing a buffer by writing the root offset.
Definition: flatbuffers.h:1164
uint8_t * GetBufferPointer() const
Get the serialized buffer (after you call Finish()).
Definition: flatbuffers.h:639