17 #ifndef FLATBUFFERS_H_
18 #define FLATBUFFERS_H_
27 #include <type_traits>
35 #if __cplusplus <= 199711L && \
36 (!defined(_MSC_VER) || _MSC_VER < 1600) && \
37 (!defined(__GNUC__) || \
38 (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400))
39 #error A C++11 compatible compiler with support for the auto typing is required for FlatBuffers.
40 #error __cplusplus _MSC_VER __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__
43 #if !defined(__clang__) && \
44 defined(__GNUC__) && \
45 (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600)
50 const class nullptr_t {
52 template<
class T>
inline operator T*()
const {
return 0; }
54 void operator&()
const;
58 #define constexpr const
64 #if !defined(FLATBUFFERS_LITTLEENDIAN)
65 #if defined(__GNUC__) || defined(__clang__)
67 #define FLATBUFFERS_LITTLEENDIAN 0
69 #define FLATBUFFERS_LITTLEENDIAN 1
70 #endif // __BIG_ENDIAN__
71 #elif defined(_MSC_VER)
73 #define FLATBUFFERS_LITTLEENDIAN 0
75 #define FLATBUFFERS_LITTLEENDIAN 1
78 #error Unable to determine endianness, define FLATBUFFERS_LITTLEENDIAN.
80 #endif // !defined(FLATBUFFERS_LITTLEENDIAN)
82 #define FLATBUFFERS_VERSION_MAJOR 1
83 #define FLATBUFFERS_VERSION_MINOR 0
84 #define FLATBUFFERS_VERSION_REVISION 0
85 #define FLATBUFFERS_STRING_EXPAND(X) #X
86 #define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
88 #if (!defined(_MSC_VER) || _MSC_VER > 1600) && \
89 (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407))
90 #define FLATBUFFERS_FINAL_CLASS final
92 #define FLATBUFFERS_FINAL_CLASS
95 #if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
96 (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406))
97 #define FLATBUFFERS_CONSTEXPR constexpr
99 #define FLATBUFFERS_CONSTEXPR
105 namespace flatbuffers {
111 typedef uint32_t uoffset_t;
114 typedef int32_t soffset_t;
118 typedef uint16_t voffset_t;
120 typedef uintmax_t largest_scalar_t;
123 #define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(soffset_t) * 8 - 1)) - 1)
126 typedef std::unique_ptr<uint8_t, std::function<void(uint8_t * )>>
130 template<
typename T>
struct Offset {
133 Offset(uoffset_t _o) : o(_o) {}
134 Offset<void> Union()
const {
return Offset<void>(o); }
137 inline void EndianCheck() {
140 assert(*reinterpret_cast<char *>(&endiantest) == FLATBUFFERS_LITTLEENDIAN);
144 template<
typename T> T EndianScalar(T t) {
145 #if FLATBUFFERS_LITTLEENDIAN
148 #if defined(_MSC_VER)
149 #pragma push_macro("__builtin_bswap16")
150 #pragma push_macro("__builtin_bswap32")
151 #pragma push_macro("__builtin_bswap64")
152 #define __builtin_bswap16 _byteswap_ushort
153 #define __builtin_bswap32 _byteswap_ulong
154 #define __builtin_bswap64 _byteswap_uint64
158 if (
sizeof(T) == 1) {
160 }
else if (
sizeof(T) == 2) {
161 auto r = __builtin_bswap16(*reinterpret_cast<uint16_t *>(&t));
162 return *
reinterpret_cast<T *
>(&r);
163 }
else if (
sizeof(T) == 4) {
164 auto r = __builtin_bswap32(*reinterpret_cast<uint32_t *>(&t));
165 return *
reinterpret_cast<T *
>(&r);
166 }
else if (
sizeof(T) == 8) {
167 auto r = __builtin_bswap64(*reinterpret_cast<uint64_t *>(&t));
168 return *
reinterpret_cast<T *
>(&r);
172 #if defined(_MSC_VER)
173 #pragma pop_macro("__builtin_bswap16")
174 #pragma pop_macro("__builtin_bswap32")
175 #pragma pop_macro("__builtin_bswap64")
180 template<
typename T> T ReadScalar(
const void *p) {
181 return EndianScalar(*reinterpret_cast<const T *>(p));
184 template<
typename T>
void WriteScalar(
void *p, T t) {
185 *
reinterpret_cast<T *
>(p) = EndianScalar(t);
188 template<
typename T>
size_t AlignOf() {
193 return __alignof__(T);
208 template<
typename T>
struct IndirectHelper {
209 typedef T return_type;
210 static const size_t element_stride =
sizeof(T);
211 static return_type Read(
const uint8_t *p, uoffset_t i) {
212 return EndianScalar((reinterpret_cast<const T *>(p))[i]);
215 template<
typename T>
struct IndirectHelper<Offset<T>> {
216 typedef const T *return_type;
217 static const size_t element_stride =
sizeof(uoffset_t);
218 static return_type Read(
const uint8_t *p, uoffset_t i) {
219 p += i *
sizeof(uoffset_t);
220 return reinterpret_cast<return_type
>(p + ReadScalar<uoffset_t>(p));
223 template<
typename T>
struct IndirectHelper<const T *> {
224 typedef const T *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 reinterpret_cast<const T *
>(p + i *
sizeof(T));
233 template<
typename T,
bool bConst>
234 struct VectorIterator :
public
235 std::iterator < std::input_iterator_tag,
236 typename std::conditional < bConst,
237 const typename IndirectHelper<T>::return_type,
238 typename IndirectHelper<T>::return_type > ::type, uoffset_t > {
240 typedef std::iterator<std::input_iterator_tag,
241 typename std::conditional<bConst,
242 const typename IndirectHelper<T>::return_type,
243 typename IndirectHelper<T>::return_type>::type, uoffset_t> super_type;
246 VectorIterator(
const uint8_t *data, uoffset_t i) :
247 data_(data + IndirectHelper<T>::element_stride * i) {};
248 VectorIterator(
const VectorIterator &other) : data_(other.data_) {}
249 VectorIterator(VectorIterator &&other) : data_(std::move(other.data_)) {}
251 VectorIterator &operator=(
const VectorIterator &other) {
256 VectorIterator &operator=(VectorIterator &&other) {
261 bool operator==(
const VectorIterator& other)
const {
262 return data_ == other.data_;
265 bool operator!=(
const VectorIterator& other)
const {
266 return data_ != other.data_;
269 ptrdiff_t operator-(
const VectorIterator& other)
const {
270 return (data_ - other.data_) / IndirectHelper<T>::element_stride;
273 typename super_type::value_type operator *()
const {
274 return IndirectHelper<T>::Read(data_, 0);
277 typename super_type::value_type operator->()
const {
278 return IndirectHelper<T>::Read(data_, 0);
281 VectorIterator &operator++() {
282 data_ += IndirectHelper<T>::element_stride;
286 VectorIterator operator++(
int) {
287 VectorIterator temp(data_);
288 data_ += IndirectHelper<T>::element_stride;
293 const uint8_t *data_;
298 template<
typename T>
class Vector {
300 typedef VectorIterator<T, false> iterator;
301 typedef VectorIterator<T, true> const_iterator;
303 uoffset_t size()
const {
return EndianScalar(length_); }
306 uoffset_t Length()
const {
return size(); }
308 typedef typename IndirectHelper<T>::return_type return_type;
310 return_type Get(uoffset_t i)
const {
312 return IndirectHelper<T>::Read(Data(), i);
315 return_type operator[](uoffset_t i)
const {
return Get(i); }
320 template<
typename E> E GetEnum(uoffset_t i)
const {
321 return static_cast<E
>(Get(i));
324 const void *GetStructFromOffset(
size_t o)
const {
325 return reinterpret_cast<const void *
>(Data() + o);
328 iterator begin() {
return iterator(Data(), 0); }
329 const_iterator begin()
const {
return const_iterator(Data(), 0); }
331 iterator end() {
return iterator(Data(), size()); }
332 const_iterator end()
const {
return const_iterator(Data(), size()); }
336 void Mutate(uoffset_t i, T val) {
338 WriteScalar(data() + i, val);
344 void MutateOffset(uoffset_t i,
const uint8_t *val) {
346 assert(
sizeof(T) ==
sizeof(uoffset_t));
347 WriteScalar(data() + i, val - (Data() + i *
sizeof(uoffset_t)));
351 const uint8_t *Data()
const {
352 return reinterpret_cast<const uint8_t *
>(&length_ + 1);
356 return reinterpret_cast<uint8_t *
>(&length_ + 1);
360 const T *data()
const {
return reinterpret_cast<const T *
>(Data()); }
361 T *data() {
return reinterpret_cast<T *
>(Data()); }
363 template<
typename K> return_type LookupByKey(K key)
const {
364 void *search_result = std::bsearch(&key, Data(), size(),
365 IndirectHelper<T>::element_stride, KeyCompare<K>);
367 if (!search_result) {
371 const uint8_t *element =
reinterpret_cast<const uint8_t *
>(search_result);
373 return IndirectHelper<T>::Read(element, 0);
384 template<
typename K>
static int KeyCompare(
const void *ap,
const void *bp) {
385 const K *key =
reinterpret_cast<const K *
>(ap);
386 const uint8_t *data =
reinterpret_cast<const uint8_t *
>(bp);
387 auto table = IndirectHelper<T>::Read(data, 0);
391 return -table->KeyCompareWithValue(*key);
399 uoffset_t size()
const {
return EndianScalar(length_); }
401 const uint8_t *Data()
const {
402 return reinterpret_cast<const uint8_t *
>(&length_ + 1);
405 return reinterpret_cast<uint8_t *
>(&length_ + 1);
415 template<
typename T>
static inline size_t VectorLength(
const Vector<T> *v) {
416 return v ? v->Length() : 0;
419 struct String :
public Vector<char> {
420 const char *c_str()
const {
return reinterpret_cast<const char *
>(Data()); }
421 std::string str()
const {
return std::string(c_str(), Length()); }
423 bool operator <(
const String &o)
const {
424 return strcmp(c_str(), o.c_str()) < 0;
430 class simple_allocator {
432 virtual ~simple_allocator() {}
433 virtual uint8_t *allocate(
size_t size)
const {
return new uint8_t[size]; }
434 virtual void deallocate(uint8_t *p)
const {
delete[] p; }
440 class vector_downward {
442 explicit vector_downward(
size_t initial_size,
443 const simple_allocator &allocator)
444 : reserved_(initial_size),
445 buf_(allocator.allocate(reserved_)),
446 cur_(buf_ + reserved_),
447 allocator_(allocator) {
448 assert((initial_size & (
sizeof(largest_scalar_t) - 1)) == 0);
453 allocator_.deallocate(buf_);
458 buf_ = allocator_.allocate(reserved_);
460 cur_ = buf_ + reserved_;
464 unique_ptr_t release() {
466 std::function<void(uint8_t *)> deleter(
467 std::bind(&simple_allocator::deallocate, allocator_, buf_));
470 unique_ptr_t retval(data(), deleter);
479 size_t growth_policy(
size_t bytes) {
480 return (bytes / 2) & ~(
sizeof(largest_scalar_t) - 1);
483 uint8_t *make_space(
size_t len) {
484 if (len > static_cast<size_t>(cur_ - buf_)) {
485 auto old_size = size();
486 auto largest_align = AlignOf<largest_scalar_t>();
487 reserved_ += (std::max)(len, growth_policy(reserved_));
489 reserved_ = (reserved_ + (largest_align - 1)) & ~(largest_align - 1);
490 auto new_buf = allocator_.allocate(reserved_);
491 auto new_cur = new_buf + reserved_ - old_size;
492 memcpy(new_cur, cur_, old_size);
494 allocator_.deallocate(buf_);
500 assert(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
504 uoffset_t size()
const {
505 assert(cur_ !=
nullptr && buf_ !=
nullptr);
506 return static_cast<uoffset_t
>(reserved_ - (cur_ - buf_));
509 uint8_t *data()
const {
510 assert(cur_ !=
nullptr);
514 uint8_t *data_at(
size_t offset)
const {
return buf_ + reserved_ - offset; }
518 void push(
const uint8_t *bytes,
size_t num) {
519 auto dest = make_space(num);
520 for (
size_t i = 0; i < num; i++) dest[i] = bytes[i];
523 void fill(
size_t zero_pad_bytes) {
524 auto dest = make_space(zero_pad_bytes);
525 for (
size_t i = 0; i < zero_pad_bytes; i++) dest[i] = 0;
528 void pop(
size_t bytes_to_remove) { cur_ += bytes_to_remove; }
532 vector_downward(
const vector_downward &);
533 vector_downward &operator=(
const vector_downward &);
538 const simple_allocator &allocator_;
542 inline voffset_t FieldIndexToOffset(voffset_t field_id) {
544 const int fixed_fields = 2;
545 return static_cast<voffset_t
>((field_id + fixed_fields) *
sizeof(voffset_t));
551 inline size_t PaddingBytes(
size_t buf_size,
size_t scalar_size) {
552 return ((~buf_size) + 1) & (scalar_size - 1);
567 FLATBUFFERS_FINAL_CLASS
578 const simple_allocator *allocator =
nullptr)
579 : buf_(initial_size, allocator ? *allocator : default_allocator),
580 nested(false), finished(false), minalign_(1), force_defaults_(false),
581 string_pool(nullptr) {
582 offsetbuf_.reserve(16);
583 vtables_.reserve(16);
588 if (string_pool)
delete string_pool;
600 if (string_pool) string_pool->clear();
605 uoffset_t
GetSize()
const {
return buf_.size(); }
627 return buf_.release();
631 void Finished()
const {
647 void Pad(
size_t num_bytes) { buf_.fill(num_bytes); }
649 void Align(
size_t elem_size) {
650 if (elem_size > minalign_) minalign_ = elem_size;
651 buf_.fill(PaddingBytes(buf_.size(), elem_size));
654 void PushFlatBuffer(
const uint8_t *bytes,
size_t size) {
655 PushBytes(bytes, size);
659 void PushBytes(
const uint8_t *bytes,
size_t size) {
660 buf_.push(bytes, size);
663 void PopBytes(
size_t amount) { buf_.pop(amount); }
665 template<
typename T>
void AssertScalarT() {
667 static_assert(std::is_scalar<T>::value
669 ||
sizeof(T) ==
sizeof(Offset<void>),
670 "T must be a scalar type");
674 template<
typename T> uoffset_t PushElement(T element) {
676 T litle_endian_element = EndianScalar(element);
678 PushBytes(reinterpret_cast<uint8_t *>(&litle_endian_element),
sizeof(T));
682 template<
typename T> uoffset_t PushElement(Offset<T> off) {
684 return PushElement(ReferTo(off.o));
689 void TrackField(voffset_t field, uoffset_t off) {
690 FieldLoc fl = { off, field };
691 offsetbuf_.push_back(fl);
695 template<
typename T>
void AddElement(voffset_t field, T e, T def) {
697 if (e == def && !force_defaults_)
return;
698 auto off = PushElement(e);
699 TrackField(field, off);
702 template<
typename T>
void AddOffset(voffset_t field, Offset<T> off) {
704 AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
707 template<
typename T>
void AddStruct(voffset_t field,
const T *structptr) {
708 if (!structptr)
return;
710 PushBytes(reinterpret_cast<const uint8_t *>(structptr),
sizeof(T));
714 void AddStructOffset(voffset_t field, uoffset_t off) {
715 TrackField(field, off);
721 uoffset_t ReferTo(uoffset_t off) {
723 Align(
sizeof(uoffset_t));
725 assert(off && off <=
GetSize());
726 return GetSize() - off +
static_cast<uoffset_t
>(
sizeof(uoffset_t));
743 uoffset_t StartTable() {
752 uoffset_t EndTable(uoffset_t start, voffset_t numfields) {
757 auto vtableoffsetloc = PushElement<soffset_t>(0);
761 buf_.fill(numfields *
sizeof(voffset_t));
762 auto table_object_size = vtableoffsetloc - start;
763 assert(table_object_size < 0x10000);
764 PushElement<voffset_t>(
static_cast<voffset_t
>(table_object_size));
765 PushElement<voffset_t>(FieldIndexToOffset(numfields));
767 for (
auto field_location = offsetbuf_.begin();
768 field_location != offsetbuf_.end();
770 auto pos =
static_cast<voffset_t
>(vtableoffsetloc - field_location->off);
772 assert(!ReadScalar<voffset_t>(buf_.data() + field_location->id));
773 WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
776 auto vt1 =
reinterpret_cast<voffset_t *
>(buf_.data());
777 auto vt1_size = ReadScalar<voffset_t>(vt1);
781 for (
auto it = vtables_.begin(); it != vtables_.end(); ++it) {
782 auto vt2 =
reinterpret_cast<voffset_t *
>(buf_.data_at(*it));
783 auto vt2_size = *vt2;
784 if (vt1_size != vt2_size || memcmp(vt2, vt1, vt1_size))
continue;
786 buf_.pop(
GetSize() - vtableoffsetloc);
791 vtables_.push_back(vt_use);
798 WriteScalar(buf_.data_at(vtableoffsetloc),
799 static_cast<soffset_t
>(vt_use) -
800 static_cast<soffset_t>(vtableoffsetloc));
803 return vtableoffsetloc;
808 template<
typename T>
void Required(Offset<T> table, voffset_t field) {
809 auto table_ptr = buf_.data_at(table.o);
810 auto vtable_ptr = table_ptr - ReadScalar<soffset_t>(table_ptr);
811 bool ok = ReadScalar<voffset_t>(vtable_ptr + field) != 0;
817 uoffset_t StartStruct(
size_t alignment) {
822 uoffset_t EndStruct() {
return GetSize(); }
824 void ClearOffsets() { offsetbuf_.clear(); }
828 void PreAlign(
size_t len,
size_t alignment) {
829 buf_.fill(PaddingBytes(
GetSize() + len, alignment));
831 template<
typename T>
void PreAlign(
size_t len) {
833 PreAlign(len,
sizeof(T));
843 PreAlign<uoffset_t>(len + 1);
845 PushBytes(reinterpret_cast<const uint8_t *>(str), len);
846 PushElement(static_cast<uoffset_t>(len));
847 return Offset<String>(
GetSize());
879 string_pool =
new StringOffsetMap(StringOffsetCompare(buf_));
880 auto size_before_string = buf_.size();
884 auto it = string_pool->find(off);
886 if (it != string_pool->end()) {
888 buf_.pop(buf_.size() - size_before_string);
892 string_pool->insert(off);
924 uoffset_t EndVector(
size_t len) {
927 return PushElement(static_cast<uoffset_t>(len));
930 void StartVector(
size_t len,
size_t elemsize) {
933 PreAlign<uoffset_t>(len * elemsize);
934 PreAlign(len * elemsize, elemsize);
942 void ForceVectorAlignment(
size_t len,
size_t elemsize,
size_t alignment) {
943 PreAlign(len * elemsize, alignment);
946 uint8_t *ReserveElements(
size_t len,
size_t elemsize) {
947 return buf_.make_space(len * elemsize);
958 template<
typename T> Offset<Vector<T>>
CreateVector(
const T *v,
size_t len) {
959 StartVector(len,
sizeof(T));
960 for (
auto i = len; i > 0; ) {
963 return Offset<Vector<T>>(EndVector(len));
972 template<
typename T> Offset<Vector<T>>
CreateVector(
const std::vector<T> &v) {
984 const T *v,
size_t len) {
985 StartVector(len *
sizeof(T) / AlignOf<T>(), AlignOf<T>());
986 PushBytes(reinterpret_cast<const uint8_t *>(v),
sizeof(T) * len);
987 return Offset<Vector<const T *>>(EndVector(len));
997 const std::vector<T> &v) {
1002 template<
typename T>
1003 struct TableKeyComparator {
1004 TableKeyComparator(vector_downward& buf) : buf_(buf) {}
1005 bool operator()(
const Offset<T> &a,
const Offset<T> &b)
const {
1006 auto table_a =
reinterpret_cast<T *
>(buf_.data_at(a.o));
1007 auto table_b =
reinterpret_cast<T *
>(buf_.data_at(b.o));
1008 return table_a->KeyCompareLessThan(table_b);
1010 vector_downward& buf_;
1013 TableKeyComparator& operator= (
const TableKeyComparator&);
1026 Offset<T> *v,
size_t len) {
1027 std::sort(v, v + len, TableKeyComparator<T>(buf_));
1039 std::vector<Offset<T>> *v) {
1053 StartVector(len, elemsize);
1054 *buf = buf_.make_space(len * elemsize);
1055 return EndVector(len);
1067 size_t len, T **buf) {
1069 reinterpret_cast<uint8_t **>(buf));
1078 template<
typename T>
void Finish(Offset<T> root,
1079 const char *file_identifier =
nullptr) {
1084 if (file_identifier) {
1085 assert(strlen(file_identifier) == kFileIdentifierLength);
1086 buf_.push(reinterpret_cast<const uint8_t *>(file_identifier),
1087 kFileIdentifierLength);
1089 PushElement(ReferTo(root.o));
1103 simple_allocator default_allocator;
1105 vector_downward buf_;
1108 std::vector<FieldLoc> offsetbuf_;
1116 std::vector<uoffset_t> vtables_;
1120 bool force_defaults_;
1122 struct StringOffsetCompare {
1123 StringOffsetCompare(
const vector_downward &buf) : buf_(&buf) {}
1124 bool operator() (
const Offset<String> &a,
const Offset<String> &b)
const {
1125 auto stra =
reinterpret_cast<const String *
>(buf_->data_at(a.o));
1126 auto strb =
reinterpret_cast<const String *
>(buf_->data_at(b.o));
1127 return strncmp(stra->c_str(), strb->c_str(),
1128 std::min(stra->size(), strb->size()) + 1) < 0;
1130 const vector_downward *buf_;
1134 typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
1135 StringOffsetMap *string_pool;
1141 template<
typename T> T *GetMutableRoot(
void *buf) {
1143 return reinterpret_cast<T *
>(
reinterpret_cast<uint8_t *
>(buf) +
1144 EndianScalar(*reinterpret_cast<uoffset_t *>(buf)));
1147 template<
typename T>
const T *GetRoot(
const void *buf) {
1148 return GetMutableRoot<T>(
const_cast<void *
>(buf));
1152 inline bool BufferHasIdentifier(
const void *buf,
const char *identifier) {
1153 return strncmp(reinterpret_cast<const char *>(buf) +
sizeof(uoffset_t),
1158 class Verifier FLATBUFFERS_FINAL_CLASS {
1160 Verifier(
const uint8_t *buf,
size_t buf_len,
size_t _max_depth = 64,
1161 size_t _max_tables = 1000000)
1162 : buf_(buf), end_(buf + buf_len), depth_(0), max_depth_(_max_depth),
1163 num_tables_(0), max_tables_(_max_tables)
1167 bool Check(
bool ok)
const {
1168 #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
1175 bool Verify(
const void *elem,
size_t elem_len)
const {
1176 return Check(elem_len <= (
size_t) (end_ - buf_) &&
1178 elem <= end_ - elem_len);
1182 template<
typename T>
bool Verify(
const void *elem)
const {
1183 return Verify(elem,
sizeof(T));
1187 template<
typename T>
bool VerifyTable(
const T *table) {
1188 return !table || table->Verify(*
this);
1192 template<
typename T>
bool Verify(
const Vector<T> *vec)
const {
1195 VerifyVector(reinterpret_cast<const uint8_t *>(vec),
sizeof(T),
1200 template<
typename T>
bool Verify(
const Vector<const T *> *vec)
const {
1201 return Verify(
reinterpret_cast<const Vector<T> *
>(vec));
1205 bool Verify(
const String *str)
const {
1208 (VerifyVector(reinterpret_cast<const uint8_t *>(str), 1, &end) &&
1210 Check(*end ==
'\0'));
1214 bool VerifyVector(
const uint8_t *vec,
size_t elem_size,
1215 const uint8_t **end)
const {
1217 if (!Verify<uoffset_t>(vec))
return false;
1220 auto size = ReadScalar<uoffset_t>(vec);
1221 auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
1222 Check(size < max_elems);
1223 auto byte_size =
sizeof(size) + elem_size * size;
1224 *end = vec + byte_size;
1225 return Verify(vec, byte_size);
1229 bool VerifyVectorOfStrings(
const Vector<Offset<String>> *vec)
const {
1231 for (uoffset_t i = 0; i < vec->size(); i++) {
1232 if (!Verify(vec->Get(i)))
return false;
1239 template<
typename T>
bool VerifyVectorOfTables(
const Vector<Offset<T>> *vec) {
1241 for (uoffset_t i = 0; i < vec->size(); i++) {
1242 if (!vec->Get(i)->Verify(*
this))
return false;
1249 template<
typename T>
bool VerifyBuffer() {
1251 return Verify<uoffset_t>(buf_) &&
1252 reinterpret_cast<const T *>(buf_ + ReadScalar<uoffset_t>(buf_))->
1260 bool VerifyComplexity() {
1263 return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_);
1273 const uint8_t *buf_;
1274 const uint8_t *end_;
1285 class Struct FLATBUFFERS_FINAL_CLASS {
1287 template<
typename T> T GetField(uoffset_t o)
const {
1288 return ReadScalar<T>(&data_[o]);
1291 template<
typename T> T GetPointer(uoffset_t o)
const {
1293 return reinterpret_cast<T
>(p + ReadScalar<uoffset_t>(p));
1296 template<
typename T> T GetStruct(uoffset_t o)
const {
1297 return reinterpret_cast<T
>(&data_[o]);
1300 const uint8_t *GetAddressOf(uoffset_t o)
const {
return &data_[o]; }
1301 uint8_t *GetAddressOf(uoffset_t o) {
return &data_[o]; }
1313 voffset_t GetOptionalFieldOffset(voffset_t field)
const {
1315 auto vtable = data_ - ReadScalar<soffset_t>(data_);
1317 auto vtsize = ReadScalar<voffset_t>(vtable);
1320 return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
1323 template<
typename T> T GetField(voffset_t field, T defaultval)
const {
1324 auto field_offset = GetOptionalFieldOffset(field);
1325 return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
1328 template<
typename P> P GetPointer(voffset_t field) {
1329 auto field_offset = GetOptionalFieldOffset(field);
1330 auto p = data_ + field_offset;
1332 ?
reinterpret_cast<P
>(p + ReadScalar<uoffset_t>(p))
1335 template<
typename P> P GetPointer(voffset_t field)
const {
1336 return const_cast<Table *
>(
this)->GetPointer<P>(field);
1339 template<
typename P> P GetStruct(voffset_t field)
const {
1340 auto field_offset = GetOptionalFieldOffset(field);
1341 auto p =
const_cast<uint8_t *
>(data_ + field_offset);
1342 return field_offset ?
reinterpret_cast<P
>(p) :
nullptr;
1345 template<
typename T>
bool SetField(voffset_t field, T val) {
1346 auto field_offset = GetOptionalFieldOffset(field);
1347 if (!field_offset)
return false;
1348 WriteScalar(data_ + field_offset, val);
1352 bool SetPointer(voffset_t field,
const uint8_t *val) {
1353 auto field_offset = GetOptionalFieldOffset(field);
1354 if (!field_offset)
return false;
1355 WriteScalar(data_ + field_offset, val - (data_ + field_offset));
1359 uint8_t *GetAddressOf(voffset_t field) {
1360 auto field_offset = GetOptionalFieldOffset(field);
1361 return field_offset ? data_ + field_offset :
nullptr;
1363 const uint8_t *GetAddressOf(voffset_t field)
const {
1364 return const_cast<Table *
>(
this)->GetAddressOf(field);
1367 uint8_t *GetVTable() {
return data_ - ReadScalar<soffset_t>(data_); }
1369 bool CheckField(voffset_t field)
const {
1370 return GetOptionalFieldOffset(field) != 0;
1375 bool VerifyTableStart(Verifier &verifier)
const {
1377 if (!verifier.Verify<soffset_t>(data_))
return false;
1378 auto vtable = data_ - ReadScalar<soffset_t>(data_);
1380 return verifier.VerifyComplexity() &&
1381 verifier.Verify<voffset_t>(vtable) &&
1382 verifier.Verify(vtable, ReadScalar<voffset_t>(vtable));
1386 template<
typename T>
bool VerifyField(
const Verifier &verifier,
1387 voffset_t field)
const {
1390 auto field_offset = GetOptionalFieldOffset(field);
1392 return !field_offset || verifier.Verify<T>(data_ + field_offset);
1396 template<
typename T>
bool VerifyFieldRequired(
const Verifier &verifier,
1397 voffset_t field)
const {
1398 auto field_offset = GetOptionalFieldOffset(field);
1399 return verifier.Check(field_offset != 0) &&
1400 verifier.Verify<T>(data_ + field_offset);
1407 Table(
const Table &other);
1419 template<
typename T>
bool IsFieldPresent(
const T *table, voffset_t field) {
1421 return reinterpret_cast<const Table *
>(table)->CheckField(field);
1427 inline int LookupEnum(
const char **names,
const char *name) {
1428 for (
const char **p = names; *p; p++)
1429 if (!strcmp(*p, name))
1430 return static_cast<int>(p - names);
1444 #if defined(_MSC_VER)
1445 #define MANUALLY_ALIGNED_STRUCT(alignment) \
1446 __pragma(pack(1)); \
1447 struct __declspec(align(alignment))
1448 #define STRUCT_END(name, size) \
1450 static_assert(sizeof(name) == size, "compiler breaks packing rules")
1451 #elif defined(__GNUC__) || defined(__clang__)
1452 #define MANUALLY_ALIGNED_STRUCT(alignment) \
1453 _Pragma("pack(1)") \
1454 struct __attribute__((aligned(alignment)))
1455 #define STRUCT_END(name, size) \
1457 static_assert(sizeof(name) == size, "compiler breaks packing rules")
1459 #error Unknown compiler, please define structure alignment macros
1472 #if !defined(_WIN32) && !defined(__CYGWIN__)
1474 extern volatile __attribute__((weak)) const
char *flatbuffer_version_string;
1475 volatile __attribute__((weak)) const
char *flatbuffer_version_string =
1477 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
1478 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
1479 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
1481 #endif // !defined(_WIN32) && !defined(__CYGWIN__)
1486 #endif // FLATBUFFERS_H_
uoffset_t CreateUninitializedVector(size_t len, size_t elemsize, uint8_t **buf)
Specialized version of CreateVector for non-copying use cases.
Definition: flatbuffers.h:1050
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:1038
Helper class to hold data needed in creation of a FlatBuffer.
Definition: flatbuffers.h:565
uoffset_t GetSize() const
The current size of the serialized buffer, counting from the end.
Definition: flatbuffers.h:605
FlatBufferBuilder(uoffset_t initial_size=1024, const simple_allocator *allocator=nullptr)
Default constructor for FlatBufferBuilder.
Definition: flatbuffers.h:577
void Clear()
Reset all the state in this FlatBufferBuilder so it can be reused to construct another buffer...
Definition: flatbuffers.h:593
unique_ptr_t ReleaseBufferPointer()
Get the released pointer to the serialized buffer.
Definition: flatbuffers.h:625
Offset< String > CreateSharedString(const char *str)
Store a string in the buffer, which null-terminated.
Definition: flatbuffers.h:901
Offset< String > CreateString(const char *str, size_t len)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:841
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:644
static const size_t kFileIdentifierLength
The length of a FlatBuffer file header.
Definition: flatbuffers.h:1073
Offset< String > CreateString(const String *str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:867
Offset< String > CreateSharedString(const String *str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:919
Offset< Vector< const T * > > CreateVectorOfStructs(const T *v, size_t len)
Serialize an array of structs into a FlatBuffer vector.
Definition: flatbuffers.h:983
Offset< String > CreateString(const char *str)
Store a string in the buffer, which is null-terminated.
Definition: flatbuffers.h:853
Offset< String > CreateString(const std::string &str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:860
Offset< Vector< T > > CreateVector(const std::vector< T > &v)
Serialize a std::vector into a FlatBuffer vector.
Definition: flatbuffers.h:972
Offset< Vector< T > > CreateUninitializedVector(size_t len, T **buf)
Specialized version of CreateVector for non-copying use cases.
Definition: flatbuffers.h:1066
uint8_t * GetCurrentBufferPointer() const
Get a pointer to an unfinished buffer.
Definition: flatbuffers.h:617
Offset< Vector< T > > CreateVector(const T *v, size_t len)
Serialize an array into a FlatBuffer vector.
Definition: flatbuffers.h:958
Offset< String > CreateSharedString(const std::string &str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:910
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:1025
Offset< String > CreateSharedString(const char *str, size_t len)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:877
Offset< Vector< const T * > > CreateVectorOfStructs(const std::vector< T > &v)
Serialize a std::vector of structs into a FlatBuffer vector.
Definition: flatbuffers.h:996
void Finish(Offset< T > root, const char *file_identifier=nullptr)
Finish serializing a buffer by writing the root offset.
Definition: flatbuffers.h:1078
uint8_t * GetBufferPointer() const
Get the serialized buffer (after you call Finish()).
Definition: flatbuffers.h:610