17 #ifndef FLATBUFFERS_H_
18 #define FLATBUFFERS_H_
20 #include "flatbuffers/base.h"
21 #include "flatbuffers/stl_emulation.h"
23 #ifndef FLATBUFFERS_CPP98_STL
24 # include <functional>
27 #if defined(FLATBUFFERS_NAN_DEFAULTS)
31 namespace flatbuffers {
35 template<
typename T>
inline bool IsTheSameAs(T e, T def) {
return e == def; }
37 #if defined(FLATBUFFERS_NAN_DEFAULTS) && \
38 defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0)
40 template<
typename T>
inline bool IsFloatTheSameAs(T e, T def) {
41 return (e == def) || ((def != def) && (e != e));
43 template<>
inline bool IsTheSameAs<float>(
float e,
float def) {
44 return IsFloatTheSameAs(e, def);
46 template<>
inline bool IsTheSameAs<double>(
double e,
double def) {
47 return IsFloatTheSameAs(e, def);
55 inline bool IsOutRange(
const T &v,
const T &low,
const T &high) {
56 return (v < low) || (high < v);
61 inline bool IsInRange(
const T &v,
const T &low,
const T &high) {
62 return !IsOutRange(v, low, high);
70 Offset(uoffset_t _o) : o(_o) {}
72 bool IsNull()
const {
return !o; }
75 inline void EndianCheck() {
78 FLATBUFFERS_ASSERT(*
reinterpret_cast<char *
>(&endiantest) ==
79 FLATBUFFERS_LITTLEENDIAN);
83 template<
typename T> FLATBUFFERS_CONSTEXPR
size_t AlignOf() {
89 return __alignof__(T);
106 typedef T return_type;
107 typedef T mutable_return_type;
108 static const size_t element_stride =
sizeof(T);
109 static return_type Read(
const uint8_t *p, uoffset_t i) {
110 return EndianScalar((
reinterpret_cast<const T *
>(p))[i]);
114 typedef const T *return_type;
115 typedef T *mutable_return_type;
116 static const size_t element_stride =
sizeof(uoffset_t);
117 static return_type Read(
const uint8_t *p, uoffset_t i) {
118 p += i *
sizeof(uoffset_t);
119 return reinterpret_cast<return_type
>(p + ReadScalar<uoffset_t>(p));
123 typedef const T *return_type;
124 typedef T *mutable_return_type;
125 static const size_t element_stride =
sizeof(T);
126 static return_type Read(
const uint8_t *p, uoffset_t i) {
127 return reinterpret_cast<const T *
>(p + i *
sizeof(T));
134 typedef std::random_access_iterator_tag iterator_category;
135 typedef IT value_type;
136 typedef ptrdiff_t difference_type;
138 typedef IT &reference;
151 #if !defined(FLATBUFFERS_CPP98_STL)
160 return data_ == other.data_;
164 return data_ < other.data_;
168 return data_ != other.data_;
226 const uint8_t *data_;
229 template<
typename Iterator>
232 : std::reverse_iterator<Iterator>(iter) {}
236 typename Iterator::value_type operator*()
const {
237 auto tmp = std::reverse_iterator<Iterator>::current;
243 typename Iterator::value_type operator->()
const {
244 auto tmp = std::reverse_iterator<Iterator>::current;
262 typedef typename flatbuffers::bool_constant<flatbuffers::is_scalar<T>::value>
265 static FLATBUFFERS_CONSTEXPR
bool is_span_observable =
266 scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN ||
sizeof(T) == 1);
268 uoffset_t size()
const {
return EndianScalar(length_); }
271 FLATBUFFERS_ATTRIBUTE(deprecated(
"use size() instead"))
272 uoffset_t Length()
const {
return size(); }
274 typedef typename IndirectHelper<T>::return_type return_type;
275 typedef typename IndirectHelper<T>::mutable_return_type mutable_return_type;
276 typedef return_type value_type;
278 return_type Get(uoffset_t i)
const {
279 FLATBUFFERS_ASSERT(i < size());
283 return_type operator[](uoffset_t i)
const {
return Get(i); }
288 template<
typename E> E GetEnum(uoffset_t i)
const {
289 return static_cast<E
>(Get(i));
294 template<
typename U>
const U *GetAs(uoffset_t i)
const {
295 return reinterpret_cast<const U *
>(Get(i));
300 const String *GetAsString(uoffset_t i)
const {
301 return reinterpret_cast<const String *
>(Get(i));
304 const void *GetStructFromOffset(
size_t o)
const {
305 return reinterpret_cast<const void *
>(Data() + o);
334 void Mutate(uoffset_t i,
const T &val) {
335 FLATBUFFERS_ASSERT(i < size());
336 WriteScalar(data() + i, val);
342 void MutateOffset(uoffset_t i,
const uint8_t *val) {
343 FLATBUFFERS_ASSERT(i < size());
344 static_assert(
sizeof(T) ==
sizeof(uoffset_t),
"Unrelated types");
345 WriteScalar(data() + i,
346 static_cast<uoffset_t
>(val - (Data() + i *
sizeof(uoffset_t))));
350 mutable_return_type GetMutableObject(uoffset_t i)
const {
351 FLATBUFFERS_ASSERT(i < size());
356 const uint8_t *Data()
const {
357 return reinterpret_cast<const uint8_t *
>(&length_ + 1);
360 uint8_t *Data() {
return reinterpret_cast<uint8_t *
>(&length_ + 1); }
363 const T *data()
const {
return reinterpret_cast<const T *
>(Data()); }
364 T *data() {
return reinterpret_cast<T *
>(Data()); }
366 template<
typename K> return_type LookupByKey(K key)
const {
367 void *search_result = std::bsearch(
370 if (!search_result) {
374 const uint8_t *element =
reinterpret_cast<const uint8_t *
>(search_result);
392 template<
typename K>
static int KeyCompare(
const void *ap,
const void *bp) {
393 const K *key =
reinterpret_cast<const K *
>(ap);
394 const uint8_t *data =
reinterpret_cast<const uint8_t *
>(bp);
399 return -table->KeyCompareWithValue(*key);
404 FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(
Vector<U> &vec)
405 FLATBUFFERS_NOEXCEPT {
407 "wrong type U, only LE-scalar, or byte types are allowed");
408 return span<U>(vec.data(), vec.size());
412 FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U> make_span(
413 const Vector<U> &vec) FLATBUFFERS_NOEXCEPT {
414 static_assert(Vector<U>::is_span_observable,
415 "wrong type U, only LE-scalar, or byte types are allowed");
416 return span<const U>(vec.data(), vec.size());
420 FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<uint8_t> make_bytes_span(
421 Vector<U> &vec) FLATBUFFERS_NOEXCEPT {
422 static_assert(Vector<U>::scalar_tag::value,
423 "wrong type U, only LE-scalar, or byte types are allowed");
424 return span<uint8_t>(vec.Data(), vec.size() *
sizeof(U));
428 FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const uint8_t> make_bytes_span(
429 const Vector<U> &vec) FLATBUFFERS_NOEXCEPT {
430 static_assert(Vector<U>::scalar_tag::value,
431 "wrong type U, only LE-scalar, or byte types are allowed");
432 return span<const uint8_t>(vec.Data(), vec.size() *
sizeof(U));
439 uoffset_t size()
const {
return EndianScalar(length_); }
441 const uint8_t *Data()
const {
442 return reinterpret_cast<const uint8_t *
>(&length_ + 1);
444 uint8_t *Data() {
return reinterpret_cast<uint8_t *
>(&length_ + 1); }
456 #ifndef FLATBUFFERS_CPP98_STL
457 template<
typename T,
typename U>
459 static_assert(std::is_base_of<T, U>::value,
"Unrelated types");
463 template<
typename T,
typename U>
464 const Vector<Offset<T>> *VectorCast(
const Vector<Offset<U>> *ptr) {
465 static_assert(std::is_base_of<T, U>::value,
"Unrelated types");
466 return reinterpret_cast<const Vector<Offset<T>
> *>(ptr);
472 template<
typename T>
static inline size_t VectorLength(
const Vector<T> *v) {
473 return v ? v->size() : 0;
477 template<
typename T, u
int16_t length>
class Array {
479 typedef typename flatbuffers::bool_constant<flatbuffers::is_scalar<T>::value>
482 typename flatbuffers::conditional<scalar_tag::value, T, const T *>::type
486 typedef uint16_t size_type;
487 typedef typename IndirectHelper<IndirectHelperType>::return_type return_type;
492 static FLATBUFFERS_CONSTEXPR
bool is_span_observable =
493 (scalar_tag::value && (FLATBUFFERS_LITTLEENDIAN ||
sizeof(T) == 1)) ||
496 FLATBUFFERS_CONSTEXPR uint16_t size()
const {
return length; }
498 return_type Get(uoffset_t i)
const {
499 FLATBUFFERS_ASSERT(i < size());
503 return_type operator[](uoffset_t i)
const {
return Get(i); }
508 template<
typename E> E GetEnum(uoffset_t i)
const {
509 return static_cast<E
>(Get(i));
533 typename flatbuffers::conditional<scalar_tag::value, void, T *>::type
534 GetMutablePointer(uoffset_t i)
const {
535 FLATBUFFERS_ASSERT(i < size());
536 return const_cast<T *
>(&data()[i]);
540 void Mutate(uoffset_t i,
const T &val) { MutateImpl(scalar_tag(), i, val); }
543 const uint8_t *Data()
const {
return data_; }
545 uint8_t *Data() {
return data_; }
548 const T *data()
const {
return reinterpret_cast<const T *
>(Data()); }
549 T *data() {
return reinterpret_cast<T *
>(Data()); }
553 void CopyFromSpan(flatbuffers::span<const T, length> src) {
554 const auto p1 =
reinterpret_cast<const uint8_t *
>(src.data());
555 const auto p2 = Data();
556 FLATBUFFERS_ASSERT(!(p1 >= p2 && p1 < (p2 + length)) &&
557 !(p2 >= p1 && p2 < (p1 + length)));
560 CopyFromSpanImpl(flatbuffers::bool_constant<is_span_observable>(), src);
564 void MutateImpl(flatbuffers::true_type, uoffset_t i,
const T &val) {
565 FLATBUFFERS_ASSERT(i < size());
566 WriteScalar(data() + i, val);
569 void MutateImpl(flatbuffers::false_type, uoffset_t i,
const T &val) {
570 *(GetMutablePointer(i)) = val;
573 void CopyFromSpanImpl(flatbuffers::true_type,
574 flatbuffers::span<const T, length> src) {
578 std::memcpy(data(), src.data(), length *
sizeof(T));
582 void CopyFromSpanImpl(flatbuffers::false_type,
583 flatbuffers::span<const T, length> src) {
584 for (size_type k = 0; k < length; k++) { Mutate(k, src[k]); }
592 #if defined(__cpp_constexpr)
598 uint8_t data_[length *
sizeof(T)];
609 template<
typename T, u
int16_t length>
class Array<
Offset<T>, length> {
610 static_assert(flatbuffers::is_same<T, void>::value,
"unexpected type T");
613 typedef const void *return_type;
615 const uint8_t *Data()
const {
return data_; }
618 return_type operator[](uoffset_t)
const {
619 FLATBUFFERS_ASSERT(
false);
632 template<
class U, u
int16_t N>
633 FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U, N> make_span(
Array<U, N> &arr)
634 FLATBUFFERS_NOEXCEPT {
637 "wrong type U, only plain struct, LE-scalar, or byte types are allowed");
638 return span<U, N>(arr.data(), N);
641 template<
class U, u
int16_t N>
642 FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U, N> make_span(
643 const Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
645 Array<U, N>::is_span_observable,
646 "wrong type U, only plain struct, LE-scalar, or byte types are allowed");
647 return span<const U, N>(arr.data(), N);
650 template<
class U, u
int16_t N>
651 FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<uint8_t,
sizeof(U) * N>
652 make_bytes_span(Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
653 static_assert(Array<U, N>::is_span_observable,
654 "internal error, Array<T> might hold only scalars or structs");
655 return span<uint8_t, sizeof(U) * N>(arr.Data(),
sizeof(U) * N);
658 template<
class U, u
int16_t N>
659 FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<
const uint8_t,
sizeof(U) * N>
660 make_bytes_span(
const Array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
661 static_assert(Array<U, N>::is_span_observable,
662 "internal error, Array<T> might hold only scalars or structs");
663 return span<const uint8_t, sizeof(U) * N>(arr.Data(),
sizeof(U) * N);
669 template<
typename T, u
int16_t length>
670 Array<T, length> &CastToArray(T (&arr)[length]) {
671 return *
reinterpret_cast<Array<T, length> *
>(arr);
674 template<
typename T, u
int16_t length>
675 const Array<T, length> &CastToArray(
const T (&arr)[length]) {
676 return *
reinterpret_cast<const Array<T, length> *
>(arr);
679 template<
typename E,
typename T, u
int16_t length>
680 Array<E, length> &CastToArrayOfEnum(T (&arr)[length]) {
681 static_assert(
sizeof(E) ==
sizeof(T),
"invalid enum type E");
682 return *
reinterpret_cast<Array<E, length> *
>(arr);
685 template<
typename E,
typename T, u
int16_t length>
686 const Array<E, length> &CastToArrayOfEnum(
const T (&arr)[length]) {
687 static_assert(
sizeof(E) ==
sizeof(T),
"invalid enum type E");
688 return *
reinterpret_cast<const Array<E, length> *
>(arr);
693 static inline bool StringLessThan(
const char *a_data, uoffset_t a_size,
694 const char *b_data, uoffset_t b_size) {
695 const auto cmp = memcmp(a_data, b_data, (std::min)(a_size, b_size));
696 return cmp == 0 ? a_size < b_size : cmp < 0;
700 const char *c_str()
const {
return reinterpret_cast<const char *
>(Data()); }
701 std::string str()
const {
return std::string(c_str(), size()); }
704 #ifdef FLATBUFFERS_HAS_STRING_VIEW
705 flatbuffers::string_view string_view()
const {
706 return flatbuffers::string_view(c_str(), size());
711 bool operator<(
const String &o)
const {
712 return StringLessThan(this->data(), this->size(), o.data(), o.size());
718 static inline std::string GetString(
const String *str) {
719 return str ? str->str() :
"";
724 static inline const char *GetCstring(
const String *str) {
725 return str ? str->c_str() :
"";
728 #ifdef FLATBUFFERS_HAS_STRING_VIEW
731 static inline flatbuffers::string_view GetStringView(
const String *str) {
732 return str ? str->string_view() : flatbuffers::string_view();
743 virtual uint8_t *allocate(
size_t size) = 0;
746 virtual void deallocate(uint8_t *p,
size_t size) = 0;
753 virtual uint8_t *reallocate_downward(uint8_t *old_p,
size_t old_size,
754 size_t new_size,
size_t in_use_back,
755 size_t in_use_front) {
756 FLATBUFFERS_ASSERT(new_size > old_size);
757 uint8_t *new_p = allocate(new_size);
758 memcpy_downward(old_p, old_size, new_p, new_size, in_use_back,
760 deallocate(old_p, old_size);
769 void memcpy_downward(uint8_t *old_p,
size_t old_size, uint8_t *new_p,
770 size_t new_size,
size_t in_use_back,
771 size_t in_use_front) {
772 memcpy(new_p + new_size - in_use_back, old_p + old_size - in_use_back,
774 memcpy(new_p, old_p, in_use_front);
781 uint8_t *allocate(
size_t size) FLATBUFFERS_OVERRIDE {
782 return new uint8_t[size];
785 void deallocate(uint8_t *p,
size_t) FLATBUFFERS_OVERRIDE {
delete[] p; }
787 static void dealloc(
void *p,
size_t) {
delete[]
static_cast<uint8_t *
>(p); }
794 inline uint8_t *Allocate(
Allocator *allocator,
size_t size) {
795 return allocator ? allocator->allocate(size)
799 inline void Deallocate(Allocator *allocator, uint8_t *p,
size_t size) {
801 allocator->deallocate(p, size);
803 DefaultAllocator().deallocate(p, size);
806 inline uint8_t *ReallocateDownward(Allocator *allocator, uint8_t *old_p,
807 size_t old_size,
size_t new_size,
808 size_t in_use_back,
size_t in_use_front) {
809 return allocator ? allocator->reallocate_downward(old_p, old_size, new_size,
810 in_use_back, in_use_front)
811 : DefaultAllocator().reallocate_downward(
812 old_p, old_size, new_size, in_use_back, in_use_front);
821 : allocator_(
nullptr),
822 own_allocator_(
false),
829 size_t reserved, uint8_t *cur,
size_t sz)
830 : allocator_(allocator),
831 own_allocator_(own_allocator),
838 #if !defined(FLATBUFFERS_CPP98_STL)
841 : allocator_(other.allocator_),
842 own_allocator_(other.own_allocator_),
844 reserved_(other.reserved_),
854 #if !defined(FLATBUFFERS_CPP98_STL)
857 if (
this == &other)
return *
this;
861 allocator_ = other.allocator_;
862 own_allocator_ = other.own_allocator_;
864 reserved_ = other.reserved_;
878 const uint8_t *data()
const {
return cur_; }
880 uint8_t *data() {
return cur_; }
882 size_t size()
const {
return size_; }
887 bool Verify()
const {
888 Verifier verifier(data(), size());
889 return verifier.Verify<T>(
nullptr);
893 const T* GetRoot()
const {
894 return flatbuffers::GetRoot<T>(data());
899 return flatbuffers::GetRoot<T>(data());
905 #if !defined(FLATBUFFERS_CPP98_STL)
909 FLATBUFFERS_DELETE_FUNC(
923 inline void destroy() {
924 if (buf_) Deallocate(allocator_, buf_, reserved_);
925 if (own_allocator_ && allocator_) {
delete allocator_; }
929 inline void reset() {
930 allocator_ =
nullptr;
931 own_allocator_ =
false;
948 bool own_allocator,
size_t buffer_minalign)
949 : allocator_(allocator),
950 own_allocator_(own_allocator),
951 initial_size_(initial_size),
952 buffer_minalign_(buffer_minalign),
959 #if !defined(FLATBUFFERS_CPP98_STL)
965 : allocator_(other.allocator_),
966 own_allocator_(other.own_allocator_),
967 initial_size_(other.initial_size_),
968 buffer_minalign_(other.buffer_minalign_),
969 reserved_(other.reserved_),
972 scratch_(other.scratch_) {
976 other.own_allocator_ =
false;
978 other.buf_ =
nullptr;
979 other.cur_ =
nullptr;
980 other.scratch_ =
nullptr;
984 #if !defined(FLATBUFFERS_CPP98_STL)
1008 cur_ = buf_ + reserved_;
1016 void clear_scratch() { scratch_ = buf_; }
1018 void clear_allocator() {
1019 if (own_allocator_ && allocator_) {
delete allocator_; }
1020 allocator_ =
nullptr;
1021 own_allocator_ =
false;
1024 void clear_buffer() {
1025 if (buf_) Deallocate(allocator_, buf_, reserved_);
1030 uint8_t *release_raw(
size_t &allocated_bytes,
size_t &offset) {
1032 allocated_bytes = reserved_;
1033 offset =
static_cast<size_t>(cur_ - buf_);
1045 DetachedBuffer fb(allocator_, own_allocator_, buf_, reserved_, cur_,
1047 if (own_allocator_) {
1048 allocator_ =
nullptr;
1049 own_allocator_ =
false;
1056 size_t ensure_space(
size_t len) {
1057 FLATBUFFERS_ASSERT(cur_ >= scratch_ && scratch_ >= buf_);
1058 if (len >
static_cast<size_t>(cur_ - scratch_)) { reallocate(len); }
1061 FLATBUFFERS_ASSERT(size() < FLATBUFFERS_MAX_BUFFER_SIZE);
1065 inline uint8_t *make_space(
size_t len) {
1066 size_t space = ensure_space(len);
1072 Allocator *get_custom_allocator() {
return allocator_; }
1074 uoffset_t size()
const {
1075 return static_cast<uoffset_t
>(reserved_ -
static_cast<size_t>(cur_ - buf_));
1078 uoffset_t scratch_size()
const {
1079 return static_cast<uoffset_t
>(scratch_ - buf_);
1082 size_t capacity()
const {
return reserved_; }
1084 uint8_t *data()
const {
1085 FLATBUFFERS_ASSERT(cur_);
1089 uint8_t *scratch_data()
const {
1090 FLATBUFFERS_ASSERT(buf_);
1094 uint8_t *scratch_end()
const {
1095 FLATBUFFERS_ASSERT(scratch_);
1099 uint8_t *data_at(
size_t offset)
const {
return buf_ + reserved_ - offset; }
1101 void push(
const uint8_t *bytes,
size_t num) {
1102 if (num > 0) { memcpy(make_space(num), bytes, num); }
1106 template<
typename T>
void push_small(
const T &little_endian_t) {
1107 make_space(
sizeof(T));
1108 *
reinterpret_cast<T *
>(cur_) = little_endian_t;
1111 template<
typename T>
void scratch_push_small(
const T &t) {
1112 ensure_space(
sizeof(T));
1113 *
reinterpret_cast<T *
>(scratch_) = t;
1114 scratch_ +=
sizeof(T);
1119 void fill(
size_t zero_pad_bytes) {
1120 make_space(zero_pad_bytes);
1121 for (
size_t i = 0; i < zero_pad_bytes; i++) cur_[i] = 0;
1126 void fill_big(
size_t zero_pad_bytes) {
1127 memset(make_space(zero_pad_bytes), 0, zero_pad_bytes);
1130 void pop(
size_t bytes_to_remove) { cur_ += bytes_to_remove; }
1131 void scratch_pop(
size_t bytes_to_remove) { scratch_ -= bytes_to_remove; }
1135 swap(allocator_, other.allocator_);
1136 swap(own_allocator_, other.own_allocator_);
1137 swap(initial_size_, other.initial_size_);
1138 swap(buffer_minalign_, other.buffer_minalign_);
1139 swap(reserved_, other.reserved_);
1140 swap(buf_, other.buf_);
1141 swap(cur_, other.cur_);
1142 swap(scratch_, other.scratch_);
1147 swap(allocator_, other.allocator_);
1148 swap(own_allocator_, other.own_allocator_);
1157 bool own_allocator_;
1158 size_t initial_size_;
1159 size_t buffer_minalign_;
1165 void reallocate(
size_t len) {
1166 auto old_reserved = reserved_;
1167 auto old_size = size();
1168 auto old_scratch_size = scratch_size();
1170 (std::max)(len, old_reserved ? old_reserved / 2 : initial_size_);
1171 reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1);
1173 buf_ = ReallocateDownward(allocator_, buf_, old_reserved, reserved_,
1174 old_size, old_scratch_size);
1176 buf_ = Allocate(allocator_, reserved_);
1178 cur_ = buf_ + reserved_ - old_size;
1179 scratch_ = buf_ + old_scratch_size;
1184 inline voffset_t FieldIndexToOffset(voffset_t field_id) {
1186 const int fixed_fields = 2;
1187 return static_cast<voffset_t
>((field_id + fixed_fields) *
sizeof(voffset_t));
1190 template<
typename T,
typename Alloc>
1191 const T *data(
const std::vector<T, Alloc> &v) {
1195 return v.empty() ?
reinterpret_cast<const T *
>(&t) : &v.front();
1197 template<
typename T,
typename Alloc> T *data(std::vector<T, Alloc> &v) {
1201 return v.empty() ?
reinterpret_cast<T *
>(&t) : &v.front();
1229 size_t initial_size = 1024,
Allocator *allocator =
nullptr,
1230 bool own_allocator =
false,
1231 size_t buffer_minalign = AlignOf<largest_scalar_t>())
1232 : buf_(initial_size, allocator, own_allocator, buffer_minalign),
1238 force_defaults_(false),
1239 dedup_vtables_(true),
1240 string_pool(nullptr) {
1246 #if !defined(FLATBUFFERS_CPP98_STL)
1251 : buf_(1024,
nullptr,
false, AlignOf<largest_scalar_t>()),
1257 force_defaults_(
false),
1258 dedup_vtables_(
true),
1259 string_pool(
nullptr) {
1268 #if !defined(FLATBUFFERS_CPP98_STL)
1283 buf_.swap(other.buf_);
1284 swap(num_field_loc, other.num_field_loc);
1285 swap(max_voffset_, other.max_voffset_);
1286 swap(nested, other.nested);
1287 swap(finished, other.finished);
1288 swap(minalign_, other.minalign_);
1289 swap(force_defaults_, other.force_defaults_);
1290 swap(dedup_vtables_, other.dedup_vtables_);
1291 swap(string_pool, other.string_pool);
1295 if (string_pool)
delete string_pool;
1311 if (string_pool) string_pool->clear();
1331 return flatbuffers::span<uint8_t>(buf_.data(), buf_.size());
1345 return buf_.release();
1352 return buf_.release();
1366 return buf_.release_raw(size, offset);
1380 void Finished()
const {
1386 FLATBUFFERS_ASSERT(finished);
1402 void Pad(
size_t num_bytes) { buf_.fill(num_bytes); }
1404 void TrackMinAlign(
size_t elem_size) {
1405 if (elem_size > minalign_) minalign_ = elem_size;
1408 void Align(
size_t elem_size) {
1409 TrackMinAlign(elem_size);
1410 buf_.fill(PaddingBytes(buf_.size(), elem_size));
1413 void PushFlatBuffer(
const uint8_t *bytes,
size_t size) {
1414 PushBytes(bytes, size);
1418 void PushBytes(
const uint8_t *bytes,
size_t size) { buf_.push(bytes, size); }
1420 void PopBytes(
size_t amount) { buf_.pop(amount); }
1422 template<
typename T>
void AssertScalarT() {
1424 static_assert(flatbuffers::is_scalar<T>::value,
"T must be a scalar type");
1428 template<
typename T> uoffset_t PushElement(T element) {
1431 buf_.push_small(EndianScalar(element));
1435 template<
typename T> uoffset_t PushElement(Offset<T> off) {
1437 return PushElement(ReferTo(off.o));
1442 void TrackField(voffset_t field, uoffset_t off) {
1443 FieldLoc fl = { off, field };
1444 buf_.scratch_push_small(fl);
1446 max_voffset_ = (std::max)(max_voffset_, field);
1450 template<
typename T>
void AddElement(voffset_t field, T e, T def) {
1452 if (IsTheSameAs(e, def) && !force_defaults_)
return;
1453 auto off = PushElement(e);
1454 TrackField(field, off);
1457 template<
typename T>
void AddElement(voffset_t field, T e) {
1458 auto off = PushElement(e);
1459 TrackField(field, off);
1462 template<
typename T>
void AddOffset(voffset_t field, Offset<T> off) {
1463 if (off.IsNull())
return;
1464 AddElement(field, ReferTo(off.o),
static_cast<uoffset_t
>(0));
1467 template<
typename T>
void AddStruct(voffset_t field,
const T *structptr) {
1468 if (!structptr)
return;
1469 Align(AlignOf<T>());
1470 buf_.push_small(*structptr);
1474 void AddStructOffset(voffset_t field, uoffset_t off) {
1475 TrackField(field, off);
1481 uoffset_t ReferTo(uoffset_t off) {
1483 Align(
sizeof(uoffset_t));
1485 FLATBUFFERS_ASSERT(off && off <=
GetSize());
1486 return GetSize() - off +
static_cast<uoffset_t
>(
sizeof(uoffset_t));
1498 FLATBUFFERS_ASSERT(!nested);
1500 FLATBUFFERS_ASSERT(!num_field_loc);
1505 uoffset_t StartTable() {
1514 uoffset_t EndTable(uoffset_t start) {
1516 FLATBUFFERS_ASSERT(nested);
1519 auto vtableoffsetloc = PushElement<soffset_t>(0);
1526 (std::max)(
static_cast<voffset_t
>(max_voffset_ +
sizeof(voffset_t)),
1527 FieldIndexToOffset(0));
1528 buf_.fill_big(max_voffset_);
1529 auto table_object_size = vtableoffsetloc - start;
1531 FLATBUFFERS_ASSERT(table_object_size < 0x10000);
1532 WriteScalar<voffset_t>(buf_.data() +
sizeof(voffset_t),
1533 static_cast<voffset_t
>(table_object_size));
1534 WriteScalar<voffset_t>(buf_.data(), max_voffset_);
1536 for (
auto it = buf_.scratch_end() - num_field_loc *
sizeof(FieldLoc);
1537 it < buf_.scratch_end(); it +=
sizeof(FieldLoc)) {
1538 auto field_location =
reinterpret_cast<FieldLoc *
>(it);
1539 auto pos =
static_cast<voffset_t
>(vtableoffsetloc - field_location->off);
1542 !ReadScalar<voffset_t>(buf_.data() + field_location->id));
1543 WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
1546 auto vt1 =
reinterpret_cast<voffset_t *
>(buf_.data());
1547 auto vt1_size = ReadScalar<voffset_t>(vt1);
1551 if (dedup_vtables_) {
1552 for (
auto it = buf_.scratch_data(); it < buf_.scratch_end();
1553 it +=
sizeof(uoffset_t)) {
1554 auto vt_offset_ptr =
reinterpret_cast<uoffset_t *
>(it);
1555 auto vt2 =
reinterpret_cast<voffset_t *
>(buf_.data_at(*vt_offset_ptr));
1556 auto vt2_size = ReadScalar<voffset_t>(vt2);
1557 if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size))
continue;
1558 vt_use = *vt_offset_ptr;
1559 buf_.pop(
GetSize() - vtableoffsetloc);
1564 if (vt_use ==
GetSize()) { buf_.scratch_push_small(vt_use); }
1570 WriteScalar(buf_.data_at(vtableoffsetloc),
1571 static_cast<soffset_t
>(vt_use) -
1572 static_cast<soffset_t
>(vtableoffsetloc));
1575 return vtableoffsetloc;
1579 uoffset_t EndTable(uoffset_t start, voffset_t ) {
1580 return EndTable(start);
1585 template<
typename T>
void Required(Offset<T> table, voffset_t field);
1587 uoffset_t StartStruct(
size_t alignment) {
1592 uoffset_t EndStruct() {
return GetSize(); }
1594 void ClearOffsets() {
1595 buf_.scratch_pop(num_field_loc *
sizeof(FieldLoc));
1602 void PreAlign(
size_t len,
size_t alignment) {
1603 TrackMinAlign(alignment);
1604 buf_.fill(PaddingBytes(
GetSize() + len, alignment));
1606 template<
typename T>
void PreAlign(
size_t len) {
1608 PreAlign(len,
sizeof(T));
1618 PreAlign<uoffset_t>(len + 1);
1620 PushBytes(
reinterpret_cast<const uint8_t *
>(str), len);
1621 PushElement(
static_cast<uoffset_t
>(len));
1647 #ifdef FLATBUFFERS_HAS_STRING_VIEW
1661 return str ?
CreateString(str->c_str(), str->size()) : 0;
1680 FLATBUFFERS_ASSERT(FLATBUFFERS_GENERAL_HEAP_ALLOC_OK);
1683 auto size_before_string = buf_.size();
1687 auto it = string_pool->find(off);
1689 if (it != string_pool->end()) {
1691 buf_.pop(buf_.size() - size_before_string);
1695 string_pool->insert(off);
1699 #ifdef FLATBUFFERS_HAS_STRING_VIEW
1742 uoffset_t EndVector(
size_t len) {
1743 FLATBUFFERS_ASSERT(nested);
1745 return PushElement(
static_cast<uoffset_t
>(len));
1748 void StartVector(
size_t len,
size_t elemsize) {
1751 PreAlign<uoffset_t>(len * elemsize);
1752 PreAlign(len * elemsize, elemsize);
1760 void ForceVectorAlignment(
size_t len,
size_t elemsize,
size_t alignment) {
1761 FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment));
1762 PreAlign(len * elemsize, alignment);
1766 void ForceStringAlignment(
size_t len,
size_t alignment) {
1767 FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment));
1768 PreAlign((len + 1) *
sizeof(
char), alignment);
1784 StartVector(len,
sizeof(T));
1787 #if FLATBUFFERS_LITTLEENDIAN
1788 PushBytes(
reinterpret_cast<const uint8_t *
>(v), len *
sizeof(T));
1790 if (
sizeof(T) == 1) {
1791 PushBytes(
reinterpret_cast<const uint8_t *
>(v), len);
1793 for (
auto i = len; i > 0; ) {
1794 PushElement(v[--i]);
1802 template<
typename T>
1805 for (
auto i = len; i > 0;) { PushElement(v[--i]); }
1806 return Offset<Vector<Offset<T>>>(EndVector(len));
1823 StartVector(v.size(),
sizeof(uint8_t));
1824 for (
auto i = v.size(); i > 0;) {
1825 PushElement(
static_cast<uint8_t
>(v[--i]));
1827 return Offset<Vector<uint8_t>>(EndVector(v.size()));
1831 #ifndef FLATBUFFERS_CPP98_STL
1840 const std::function<T (
size_t i)> &f) {
1841 FLATBUFFERS_ASSERT(FLATBUFFERS_GENERAL_HEAP_ALLOC_OK);
1842 std::vector<T> elems(vector_size);
1843 for (
size_t i = 0; i < vector_size; i++) elems[i] = f(i);
1860 template<
typename T,
typename F,
typename S>
1862 FLATBUFFERS_ASSERT(FLATBUFFERS_GENERAL_HEAP_ALLOC_OK);
1863 std::vector<T> elems(vector_size);
1864 for (
size_t i = 0; i < vector_size; i++) elems[i] = f(i, state);
1875 const std::vector<std::string> &v) {
1887 auto size = std::distance(begin, end);
1892 buf_.ensure_space(scratch_buffer_usage);
1893 for (
auto it = begin; it != end; ++it) {
1897 for (
auto i = 1; i <= size; i++) {
1903 buf_.scratch_pop(scratch_buffer_usage);
1914 template<
typename T>
1916 StartVector(len *
sizeof(T) / AlignOf<T>(), AlignOf<T>());
1918 PushBytes(
reinterpret_cast<const uint8_t *
>(v),
sizeof(T) * len);
1933 template<
typename T,
typename S>
1935 const S *v,
size_t len, T (*
const pack_func)(
const S &)) {
1936 FLATBUFFERS_ASSERT(pack_func);
1937 auto structs = StartVectorOfStructs<T>(len);
1938 for (
size_t i = 0; i < len; i++) { structs[i] = pack_func(v[i]); }
1939 return EndVectorOfStructs<T>(len);
1950 template<
typename T,
typename S>
1953 extern T Pack(
const S &);
1958 #ifndef FLATBUFFERS_CPP98_STL
1968 size_t vector_size,
const std::function<
void(
size_t i, T *)> &filler) {
1969 T* structs = StartVectorOfStructs<T>(vector_size);
1970 for (
size_t i = 0; i < vector_size; i++) {
1974 return EndVectorOfStructs<T>(vector_size);
1988 template<
typename T,
typename F,
typename S>
1991 T *structs = StartVectorOfStructs<T>(vector_size);
1992 for (
size_t i = 0; i < vector_size; i++) {
1993 f(i, structs, state);
1996 return EndVectorOfStructs<T>(vector_size);
2005 template<
typename T,
typename Alloc>
2007 const std::vector<T, Alloc> &v) {
2021 template<
typename T,
typename S>
2023 const std::vector<S> &v, T (*
const pack_func)(
const S &)) {
2024 return CreateVectorOfNativeStructs<T, S>(data(v), v.size(), pack_func);
2035 template<
typename T,
typename S>
2037 const std::vector<S> &v) {
2038 return CreateVectorOfNativeStructs<T, S>(data(v), v.size());
2042 template<
typename T>
struct StructKeyComparator {
2043 bool operator()(
const T &a,
const T &b)
const {
2044 return a.KeyCompareLessThan(&b);
2056 template<
typename T>
2069 template<
typename T,
typename S>
2071 std::vector<S> *v) {
2072 return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size());
2083 template<
typename T>
2085 std::sort(v, v + len, StructKeyComparator<T>());
2098 template<
typename T,
typename S>
2101 extern T Pack(
const S &);
2102 auto structs = StartVectorOfStructs<T>(len);
2103 for (
size_t i = 0; i < len; i++) { structs[i] = Pack(v[i]); }
2104 std::sort(structs, structs + len, StructKeyComparator<T>());
2105 return EndVectorOfStructs<T>(len);
2109 template<
typename T>
struct TableKeyComparator {
2111 TableKeyComparator(
const TableKeyComparator &other) : buf_(other.buf_) {}
2112 bool operator()(
const Offset<T> &a,
const Offset<T> &b)
const {
2113 auto table_a =
reinterpret_cast<T *
>(buf_.data_at(a.o));
2114 auto table_b =
reinterpret_cast<T *
>(buf_.data_at(b.o));
2115 return table_a->KeyCompareLessThan(table_b);
2117 vector_downward &buf_;
2120 FLATBUFFERS_DELETE_FUNC(
2121 TableKeyComparator &
operator=(
const TableKeyComparator &other));
2133 template<
typename T>
2136 std::sort(v, v + len, TableKeyComparator<T>(buf_));
2147 template<
typename T>
2163 StartVector(len, elemsize);
2164 buf_.make_space(len * elemsize);
2166 auto vec_end = EndVector(len);
2167 *buf = buf_.data_at(vec_start);
2179 template<
typename T>
2183 reinterpret_cast<uint8_t **
>(buf));
2186 template<
typename T>
2190 reinterpret_cast<uint8_t **
>(buf));
2196 template<
typename T,
typename U>
2197 Offset<Vector<T>> CreateVectorScalarCast(
const U *v,
size_t len) {
2200 StartVector(len,
sizeof(T));
2201 for (
auto i = len; i > 0;) { PushElement(
static_cast<T
>(v[--i])); }
2202 return Offset<Vector<T>>(EndVector(len));
2208 Align(AlignOf<T>());
2209 buf_.push_small(structobj);
2219 template<
typename T>
2221 Finish(root.o, file_identifier,
false);
2231 template<
typename T>
2233 const char *file_identifier =
nullptr) {
2234 Finish(root.o, file_identifier,
true);
2238 buf_.swap_allocator(other.buf_);
2246 void Finish(uoffset_t root,
const char *file_identifier,
bool size_prefix) {
2248 buf_.clear_scratch();
2250 PreAlign((size_prefix ?
sizeof(uoffset_t) : 0) +
sizeof(uoffset_t) +
2253 if (file_identifier) {
2255 PushBytes(
reinterpret_cast<const uint8_t *
>(file_identifier),
2258 PushElement(ReferTo(root));
2259 if (size_prefix) { PushElement(
GetSize()); }
2272 uoffset_t num_field_loc;
2275 voffset_t max_voffset_;
2285 bool force_defaults_;
2287 bool dedup_vtables_;
2292 auto stra =
reinterpret_cast<const String *
>(buf_->data_at(a.o));
2293 auto strb =
reinterpret_cast<const String *
>(buf_->data_at(b.o));
2294 return StringLessThan(stra->data(), stra->size(), strb->data(),
2302 StringOffsetMap *string_pool;
2307 template<
typename T> T *StartVectorOfStructs(
size_t vector_size) {
2308 StartVector(vector_size *
sizeof(T) / AlignOf<T>(), AlignOf<T>());
2309 return reinterpret_cast<T *
>(buf_.make_space(vector_size *
sizeof(T)));
2314 template<
typename T>
2323 template<
typename T> T *GetMutableRoot(
void *buf) {
2325 return reinterpret_cast<T *
>(
2326 reinterpret_cast<uint8_t *
>(buf) +
2327 EndianScalar(*
reinterpret_cast<uoffset_t *
>(buf)));
2330 template<
typename T>
const T *GetRoot(
const void *buf) {
2331 return GetMutableRoot<T>(
const_cast<void *
>(buf));
2334 template<
typename T>
const T *GetSizePrefixedRoot(
const void *buf) {
2335 return GetRoot<T>(
reinterpret_cast<const uint8_t *
>(buf) +
sizeof(uoffset_t));
2341 template<
typename T>
2342 T *GetMutableTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
2343 return reinterpret_cast<T *
>(fbb.GetCurrentBufferPointer() + fbb.GetSize() -
2347 template<
typename T>
2348 const T *GetTemporaryPointer(FlatBufferBuilder &fbb, Offset<T> offset) {
2349 return GetMutableTemporaryPointer<T>(fbb, offset);
2359 inline const char *GetBufferIdentifier(
const void *buf,
2360 bool size_prefixed =
false) {
2361 return reinterpret_cast<const char *
>(buf) +
2362 ((size_prefixed) ? 2 *
sizeof(uoffset_t) :
sizeof(uoffset_t));
2366 inline bool BufferHasIdentifier(
const void *buf,
const char *identifier,
2367 bool size_prefixed =
false) {
2368 return strncmp(GetBufferIdentifier(buf, size_prefixed), identifier,
2373 class Verifier FLATBUFFERS_FINAL_CLASS {
2375 Verifier(
const uint8_t *buf,
size_t buf_len, uoffset_t _max_depth = 64,
2376 uoffset_t _max_tables = 1000000,
bool _check_alignment =
true)
2380 max_depth_(_max_depth),
2382 max_tables_(_max_tables),
2384 check_alignment_(_check_alignment) {
2385 FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
2389 bool Check(
bool ok)
const {
2391 #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
2392 FLATBUFFERS_ASSERT(ok);
2394 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
2403 bool Verify(
size_t elem,
size_t elem_len)
const {
2405 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
2406 auto upper_bound = elem + elem_len;
2407 if (upper_bound_ < upper_bound)
2408 upper_bound_ = upper_bound;
2411 return Check(elem_len < size_ && elem <= size_ - elem_len);
2414 template<
typename T>
bool VerifyAlignment(
size_t elem)
const {
2415 return Check((elem & (
sizeof(T) - 1)) == 0 || !check_alignment_);
2419 template<
typename T>
bool Verify(
size_t elem)
const {
2420 return VerifyAlignment<T>(elem) && Verify(elem,
sizeof(T));
2423 bool VerifyFromPointer(
const uint8_t *p,
size_t len) {
2424 auto o =
static_cast<size_t>(p - buf_);
2425 return Verify(o, len);
2429 bool Verify(
const uint8_t *base, voffset_t elem_off,
size_t elem_len)
const {
2430 return Verify(
static_cast<size_t>(base - buf_) + elem_off, elem_len);
2433 template<
typename T>
2434 bool Verify(
const uint8_t *base, voffset_t elem_off)
const {
2435 return Verify(
static_cast<size_t>(base - buf_) + elem_off,
sizeof(T));
2439 template<
typename T>
bool VerifyTable(
const T *table) {
2440 return !table || table->Verify(*
this);
2444 template<
typename T>
bool VerifyVector(
const Vector<T> *vec)
const {
2445 return !vec || VerifyVectorOrString(
reinterpret_cast<const uint8_t *
>(vec),
2450 template<
typename T>
bool VerifyVector(
const Vector<const T *> *vec)
const {
2451 return VerifyVector(
reinterpret_cast<const Vector<T> *
>(vec));
2455 bool VerifyString(
const String *str)
const {
2457 return !str || (VerifyVectorOrString(
reinterpret_cast<const uint8_t *
>(str),
2460 Check(buf_[end] ==
'\0'));
2464 bool VerifyVectorOrString(
const uint8_t *vec,
size_t elem_size,
2465 size_t *end =
nullptr)
const {
2466 auto veco =
static_cast<size_t>(vec - buf_);
2468 if (!Verify<uoffset_t>(veco))
return false;
2471 auto size = ReadScalar<uoffset_t>(vec);
2472 auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
2473 if (!Check(size < max_elems))
2475 auto byte_size =
sizeof(size) + elem_size * size;
2476 if (end) *end = veco + byte_size;
2477 return Verify(veco, byte_size);
2481 bool VerifyVectorOfStrings(
const Vector<Offset<String>> *vec)
const {
2483 for (uoffset_t i = 0; i < vec->size(); i++) {
2484 if (!VerifyString(vec->Get(i)))
return false;
2491 template<
typename T>
bool VerifyVectorOfTables(
const Vector<Offset<T>> *vec) {
2493 for (uoffset_t i = 0; i < vec->size(); i++) {
2494 if (!vec->Get(i)->Verify(*
this))
return false;
2500 __supress_ubsan__(
"unsigned-integer-overflow") bool VerifyTableStart(
2501 const uint8_t *table) {
2503 auto tableo =
static_cast<size_t>(table - buf_);
2504 if (!Verify<soffset_t>(tableo))
return false;
2507 auto vtableo = tableo -
static_cast<size_t>(ReadScalar<soffset_t>(table));
2509 return VerifyComplexity() && Verify<voffset_t>(vtableo) &&
2510 VerifyAlignment<voffset_t>(ReadScalar<voffset_t>(buf_ + vtableo)) &&
2511 Verify(vtableo, ReadScalar<voffset_t>(buf_ + vtableo));
2514 template<
typename T>
2515 bool VerifyBufferFromStart(
const char *identifier,
size_t start) {
2516 if (identifier && !Check((size_ >= 2 *
sizeof(flatbuffers::uoffset_t) &&
2517 BufferHasIdentifier(buf_ + start, identifier)))) {
2522 auto o = VerifyOffset(start);
2523 return o &&
reinterpret_cast<const T *
>(buf_ + start + o)->Verify(*
this)
2525 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
2526 && GetComputedSize()
2533 template<
typename T>
bool VerifyBuffer() {
return VerifyBuffer<T>(
nullptr); }
2535 template<
typename T>
bool VerifyBuffer(
const char *identifier) {
2536 return VerifyBufferFromStart<T>(identifier, 0);
2539 template<
typename T>
bool VerifySizePrefixedBuffer(
const char *identifier) {
2540 return Verify<uoffset_t>(0U) &&
2541 ReadScalar<uoffset_t>(buf_) == size_ -
sizeof(uoffset_t) &&
2542 VerifyBufferFromStart<T>(identifier,
sizeof(uoffset_t));
2545 uoffset_t VerifyOffset(
size_t start)
const {
2546 if (!Verify<uoffset_t>(start))
return 0;
2547 auto o = ReadScalar<uoffset_t>(buf_ + start);
2549 if (!Check(o != 0))
return 0;
2551 if (!Check(
static_cast<soffset_t
>(o) >= 0))
return 0;
2554 if (!Verify(start + o, 1))
return 0;
2558 uoffset_t VerifyOffset(
const uint8_t *base, voffset_t start)
const {
2559 return VerifyOffset(
static_cast<size_t>(base - buf_) + start);
2566 bool VerifyComplexity() {
2569 return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_);
2579 size_t GetComputedSize()
const {
2581 #ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
2582 uintptr_t size = upper_bound_;
2584 size = (size - 1 +
sizeof(uoffset_t)) & ~(
sizeof(uoffset_t) - 1);
2585 return (size > size_) ? 0 : size;
2589 FLATBUFFERS_ASSERT(
false);
2596 const uint8_t *buf_;
2599 uoffset_t max_depth_;
2600 uoffset_t num_tables_;
2601 uoffset_t max_tables_;
2602 mutable size_t upper_bound_;
2603 bool check_alignment_;
2609 struct BufferRefBase {};
2610 template<
typename T>
struct BufferRef : BufferRefBase {
2611 BufferRef() : buf(nullptr), len(0), must_free(false) {}
2612 BufferRef(uint8_t *_buf, uoffset_t _len)
2613 : buf(_buf), len(_len), must_free(false) {}
2616 if (must_free) free(buf);
2619 const T *GetRoot()
const {
return flatbuffers::GetRoot<T>(buf); }
2622 Verifier verifier(buf, len);
2623 return verifier.VerifyBuffer<T>(
nullptr);
2635 class Struct FLATBUFFERS_FINAL_CLASS {
2637 template<
typename T> T GetField(uoffset_t o)
const {
2638 return ReadScalar<T>(&data_[o]);
2641 template<
typename T> T GetStruct(uoffset_t o)
const {
2642 return reinterpret_cast<T
>(&data_[o]);
2645 const uint8_t *GetAddressOf(uoffset_t o)
const {
return &data_[o]; }
2646 uint8_t *GetAddressOf(uoffset_t o) {
return &data_[o]; }
2652 Struct(
const Struct &);
2653 Struct &operator=(
const Struct &);
2662 const uint8_t *GetVTable()
const {
2663 return data_ - ReadScalar<soffset_t>(data_);
2668 voffset_t GetOptionalFieldOffset(voffset_t field)
const {
2670 auto vtable = GetVTable();
2672 auto vtsize = ReadScalar<voffset_t>(vtable);
2675 return field < vtsize ? ReadScalar<voffset_t>(vtable + field) : 0;
2678 template<
typename T> T GetField(voffset_t field, T defaultval)
const {
2679 auto field_offset = GetOptionalFieldOffset(field);
2680 return field_offset ? ReadScalar<T>(data_ + field_offset) : defaultval;
2683 template<
typename P> P GetPointer(voffset_t field) {
2684 auto field_offset = GetOptionalFieldOffset(field);
2685 auto p = data_ + field_offset;
2686 return field_offset ?
reinterpret_cast<P
>(p + ReadScalar<uoffset_t>(p))
2689 template<
typename P> P GetPointer(voffset_t field)
const {
2690 return const_cast<Table *
>(
this)->GetPointer<P>(field);
2693 template<
typename P> P GetStruct(voffset_t field)
const {
2694 auto field_offset = GetOptionalFieldOffset(field);
2695 auto p =
const_cast<uint8_t *
>(data_ + field_offset);
2696 return field_offset ?
reinterpret_cast<P
>(p) :
nullptr;
2699 template<
typename Raw,
typename Face>
2700 flatbuffers::Optional<Face> GetOptional(voffset_t field)
const {
2701 auto field_offset = GetOptionalFieldOffset(field);
2702 auto p = data_ + field_offset;
2703 return field_offset ? Optional<Face>(
static_cast<Face
>(ReadScalar<Raw>(p)))
2707 template<
typename T>
bool SetField(voffset_t field, T val, T def) {
2708 auto field_offset = GetOptionalFieldOffset(field);
2709 if (!field_offset)
return IsTheSameAs(val, def);
2710 WriteScalar(data_ + field_offset, val);
2713 template<
typename T>
bool SetField(voffset_t field, T val) {
2714 auto field_offset = GetOptionalFieldOffset(field);
2715 if (!field_offset)
return false;
2716 WriteScalar(data_ + field_offset, val);
2720 bool SetPointer(voffset_t field,
const uint8_t *val) {
2721 auto field_offset = GetOptionalFieldOffset(field);
2722 if (!field_offset)
return false;
2723 WriteScalar(data_ + field_offset,
2724 static_cast<uoffset_t
>(val - (data_ + field_offset)));
2728 uint8_t *GetAddressOf(voffset_t field) {
2729 auto field_offset = GetOptionalFieldOffset(field);
2730 return field_offset ? data_ + field_offset :
nullptr;
2732 const uint8_t *GetAddressOf(voffset_t field)
const {
2733 return const_cast<Table *
>(
this)->GetAddressOf(field);
2736 bool CheckField(voffset_t field)
const {
2737 return GetOptionalFieldOffset(field) != 0;
2742 bool VerifyTableStart(Verifier &verifier)
const {
2743 return verifier.VerifyTableStart(data_);
2747 template<
typename T>
2748 bool VerifyField(
const Verifier &verifier, voffset_t field)
const {
2751 auto field_offset = GetOptionalFieldOffset(field);
2753 return !field_offset || verifier.Verify<T>(data_, field_offset);
2757 template<
typename T>
2758 bool VerifyFieldRequired(
const Verifier &verifier, voffset_t field)
const {
2759 auto field_offset = GetOptionalFieldOffset(field);
2760 return verifier.Check(field_offset != 0) &&
2761 verifier.Verify<T>(data_, field_offset);
2765 bool VerifyOffset(
const Verifier &verifier, voffset_t field)
const {
2766 auto field_offset = GetOptionalFieldOffset(field);
2767 return !field_offset || verifier.VerifyOffset(data_, field_offset);
2770 bool VerifyOffsetRequired(
const Verifier &verifier, voffset_t field)
const {
2771 auto field_offset = GetOptionalFieldOffset(field);
2772 return verifier.Check(field_offset != 0) &&
2773 verifier.VerifyOffset(data_, field_offset);
2780 Table(
const Table &other);
2781 Table &operator=(
const Table &);
2789 inline flatbuffers::Optional<bool> Table::GetOptional<uint8_t, bool>(
2790 voffset_t field)
const {
2791 auto field_offset = GetOptionalFieldOffset(field);
2792 auto p = data_ + field_offset;
2793 return field_offset ? Optional<bool>(ReadScalar<uint8_t>(p) != 0)
2797 template<
typename T>
2798 void FlatBufferBuilder::Required(Offset<T> table, voffset_t field) {
2799 auto table_ptr =
reinterpret_cast<const Table *
>(buf_.data_at(table.o));
2800 bool ok = table_ptr->GetOptionalFieldOffset(field) != 0;
2802 FLATBUFFERS_ASSERT(ok);
2810 inline const uint8_t *GetBufferStartFromRootPointer(
const void *root) {
2811 auto table =
reinterpret_cast<const Table *
>(root);
2812 auto vtable = table->GetVTable();
2814 auto start = (std::min)(vtable,
reinterpret_cast<const uint8_t *
>(root));
2816 start =
reinterpret_cast<const uint8_t *
>(
reinterpret_cast<uintptr_t
>(start) &
2817 ~(
sizeof(uoffset_t) - 1));
2828 "file_identifier is assumed to be the same size as uoffset_t");
2829 for (
auto possible_roots = FLATBUFFERS_MAX_ALIGNMENT /
sizeof(uoffset_t) + 1;
2830 possible_roots; possible_roots--) {
2831 start -=
sizeof(uoffset_t);
2832 if (ReadScalar<uoffset_t>(start) + start ==
2833 reinterpret_cast<const uint8_t *
>(root))
2840 FLATBUFFERS_ASSERT(
false);
2845 inline uoffset_t GetPrefixedSize(
const uint8_t *buf) {
2846 return ReadScalar<uoffset_t>(buf);
2852 struct NativeTable {};
2862 typedef uint64_t hash_value_t;
2864 #ifdef FLATBUFFERS_CPP98_STL
2865 typedef void (*resolver_function_t)(
void **pointer_adr, hash_value_t hash);
2866 typedef hash_value_t (*rehasher_function_t)(
void *pointer);
2868 typedef std::function<void (
void **pointer_adr, hash_value_t hash)>
2869 resolver_function_t;
2870 typedef std::function<hash_value_t (
void *pointer)> rehasher_function_t;
2881 template<
typename T>
2882 bool IsFieldPresent(
const T *table,
typename T::FlatBuffersVTableOffset field) {
2884 return reinterpret_cast<const Table *
>(table)->CheckField(
2885 static_cast<voffset_t
>(field));
2891 inline int LookupEnum(
const char **names,
const char *name) {
2892 for (
const char **p = names; *p; p++)
2893 if (!strcmp(*p, name))
return static_cast<int>(p - names);
2908 #if defined(_MSC_VER)
2909 #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
2911 struct __declspec(align(alignment))
2912 #define FLATBUFFERS_STRUCT_END(name, size) \
2914 static_assert(sizeof(name) == size, "compiler breaks packing rules")
2915 #elif defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
2916 #define FLATBUFFERS_MANUALLY_ALIGNED_STRUCT(alignment) \
2917 _Pragma("pack(1)") \
2918 struct __attribute__((aligned(alignment)))
2919 #define FLATBUFFERS_STRUCT_END(name, size) \
2921 static_assert(sizeof(name) == size, "compiler breaks packing rules")
2923 #error Unknown compiler, please define structure alignment macros
2937 enum SequenceType { ST_TABLE, ST_STRUCT, ST_UNION, ST_ENUM };
2941 #define FLATBUFFERS_GEN_ELEMENTARY_TYPES(ET) \
2957 enum ElementaryType {
2958 #define FLATBUFFERS_ET(E) E,
2959 FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
2960 #undef FLATBUFFERS_ET
2963 inline const char *
const *ElementaryTypeNames() {
2964 static const char *
const names[] = {
2965 #define FLATBUFFERS_ET(E) #E,
2966 FLATBUFFERS_GEN_ELEMENTARY_TYPES(FLATBUFFERS_ET)
2967 #undef FLATBUFFERS_ET
2979 unsigned short base_type : 4;
2981 unsigned short is_repeating : 1;
2983 signed short sequence_ref : 11;
2986 static_assert(
sizeof(TypeCode) == 2,
"TypeCode");
2991 typedef const TypeTable *(*TypeFunction)();
2996 const TypeCode *type_codes;
2997 const TypeFunction *type_refs;
2998 const int16_t *array_sizes;
2999 const int64_t *values;
3000 const char *
const *names;
3014 #if !defined(_WIN32) && !defined(__CYGWIN__)
3016 extern volatile __attribute__((weak))
const char *flatbuffer_version_string;
3017 volatile __attribute__((weak))
const char *flatbuffer_version_string =
3019 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR)
"."
3020 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR)
"."
3021 FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
3025 #define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\
3026 inline E operator | (E lhs, E rhs){\
3027 return E(T(lhs) | T(rhs));\
3029 inline E operator & (E lhs, E rhs){\
3030 return E(T(lhs) & T(rhs));\
3032 inline E operator ^ (E lhs, E rhs){\
3033 return E(T(lhs) ^ T(rhs));\
3035 inline E operator ~ (E lhs){\
3038 inline E operator |= (E &lhs, E rhs){\
3042 inline E operator &= (E &lhs, E rhs){\
3046 inline E operator ^= (E &lhs, E rhs){\
3050 inline bool operator !(E rhs) \
3052 return !bool(T(rhs)); \
Definition: flatbuffers.h:738
Definition: flatbuffers.h:477
Definition: flatbuffers.h:779
Definition: flatbuffers.h:818
Helper class to hold data needed in creation of a FlatBuffer.
Definition: flatbuffers.h:1215
uint8_t * GetCurrentBufferPointer() const
Get a pointer to an unfinished buffer.
Definition: flatbuffers.h:1336
void Finish(Offset< T > root, const char *file_identifier=nullptr)
Finish serializing a buffer by writing the root offset.
Definition: flatbuffers.h:2220
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:1839
Offset< String > CreateSharedString(const std::string &str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1726
Offset< Vector< const T * > > CreateVectorOfStructs(const std::vector< T, Alloc > &v)
Serialize a std::vector of structs into a FlatBuffer vector.
Definition: flatbuffers.h:2006
Offset< Vector< const T * > > CreateVectorOfNativeStructs(const std::vector< S > &v)
Serialize a std::vector of native structs into a FlatBuffer vector.
Definition: flatbuffers.h:2036
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:1395
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:2134
Offset< Vector< T > > CreateUninitializedVector(size_t len, T **buf)
Specialized version of CreateVector for non-copying use cases.
Definition: flatbuffers.h:2180
Offset< Vector< const T * > > CreateVectorOfSortedNativeStructs(std::vector< S > *v)
Serialize a std::vector of native structs into a FlatBuffer vector in sorted order.
Definition: flatbuffers.h:2070
Offset< Vector< T > > CreateVector(const T *v, size_t len)
Serialize an array into a FlatBuffer vector.
Definition: flatbuffers.h:1780
Offset< Vector< const T * > > CreateVectorOfNativeStructs(const S *v, size_t len)
Serialize an array of native structs into a FlatBuffer vector.
Definition: flatbuffers.h:1951
Offset< String > CreateSharedString(const char *str)
Store a string in the buffer, which null-terminated.
Definition: flatbuffers.h:1716
size_t GetBufferMinAlignment() const
get the minimum alignment this buffer needs to be accessed properly.
Definition: flatbuffers.h:1374
Offset< const T * > CreateStruct(const T &structobj)
Write a struct by itself, typically to be part of a union.
Definition: flatbuffers.h:2206
Offset< Vector< const T * > > CreateVectorOfNativeStructs(const std::vector< S > &v, T(*const pack_func)(const S &))
Serialize a std::vector of native structs into a FlatBuffer vector.
Definition: flatbuffers.h:2022
Offset< String > CreateSharedString(const flatbuffers::string_view str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1706
Offset< Vector< T > > CreateVector(size_t vector_size, F f, S *state)
Serialize values returned by a function into a FlatBuffer vector.
Definition: flatbuffers.h:1861
Offset< Vector< Offset< String > > > CreateVectorOfStrings(It begin, It end)
Serialize a collection of Strings into a FlatBuffer vector.
Definition: flatbuffers.h:1886
Offset< Vector< Offset< String > > > CreateVectorOfStrings(const std::vector< std::string > &v)
Serialize a std::vector<std::string> into a FlatBuffer vector.
Definition: flatbuffers.h:1874
DetachedBuffer Release()
Get the released DetachedBuffer.
Definition: flatbuffers.h:1350
FLATBUFFERS_ATTRIBUTE(deprecated("use Release() instead")) DetachedBuffer ReleaseBufferPointer()
Get the released pointer to the serialized buffer.
Definition: flatbuffers.h:1342
uoffset_t GetSize() const
The current size of the serialized buffer, counting from the end.
Definition: flatbuffers.h:1316
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:1967
Offset< Vector< const T * > > CreateVectorOfSortedNativeStructs(S *v, size_t len)
Serialize an array of native structs into a FlatBuffer vector in sorted order.
Definition: flatbuffers.h:2099
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:2232
Offset< Vector< const T * > > CreateVectorOfSortedStructs(std::vector< T > *v)
Serialize a std::vector of structs into a FlatBuffer vector in sorted order.
Definition: flatbuffers.h:2057
Offset< String > CreateSharedString(const String *str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1737
Offset< String > CreateString(const std::string &str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1642
Offset< String > CreateString(flatbuffers::string_view str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1651
Offset< Vector< const T * > > CreateVectorOfStructs(size_t vector_size, F f, S *state)
Serialize an array of structs into a FlatBuffer vector.
Definition: flatbuffers.h:1989
uint8_t * ReleaseRaw(size_t &size, size_t &offset)
Get the released pointer to the serialized buffer.
Definition: flatbuffers.h:1364
void DedupVtables(bool dedup)
By default vtables are deduped in order to save space.
Definition: flatbuffers.h:1399
Offset< String > CreateString(const char *str)
Store a string in the buffer, which is null-terminated.
Definition: flatbuffers.h:1628
FlatBufferBuilder(size_t initial_size=1024, Allocator *allocator=nullptr, bool own_allocator=false, size_t buffer_minalign=AlignOf< largest_scalar_t >())
Default constructor for FlatBufferBuilder.
Definition: flatbuffers.h:1228
Offset< Vector< const T * > > CreateVectorOfSortedStructs(T *v, size_t len)
Serialize an array of structs into a FlatBuffer vector in sorted order.
Definition: flatbuffers.h:2084
Offset< String > CreateSharedString(const char *str, size_t len)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1679
Offset< String > CreateString(const T &str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1668
flatbuffers::span< uint8_t > GetBufferSpan() const
Get the serialized buffer (after you call Finish()) as a span.
Definition: flatbuffers.h:1329
uint8_t * GetBufferPointer() const
Get the serialized buffer (after you call Finish()).
Definition: flatbuffers.h:1321
Offset< String > CreateString(const String *str)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1660
uoffset_t CreateUninitializedVector(size_t len, size_t elemsize, uint8_t **buf)
Specialized version of CreateVector for non-copying use cases.
Definition: flatbuffers.h:2160
Offset< String > CreateString(char *str)
Store a string in the buffer, which is null-terminated.
Definition: flatbuffers.h:1635
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:2148
Offset< Vector< const T * > > CreateVectorOfNativeStructs(const S *v, size_t len, T(*const pack_func)(const S &))
Serialize an array of native structs into a FlatBuffer vector.
Definition: flatbuffers.h:1934
FlatBufferBuilder & operator=(FlatBufferBuilder &&other)
Move assignment operator for FlatBufferBuilder.
Definition: flatbuffers.h:1271
FlatBufferBuilder(FlatBufferBuilder &&other) FlatBufferBuilder(FlatBufferBuilder &other)
Move constructor for FlatBufferBuilder.
Definition: flatbuffers.h:1247
void Clear()
Reset all the state in this FlatBufferBuilder so it can be reused to construct another buffer.
Definition: flatbuffers.h:1305
Offset< String > CreateString(const char *str, size_t len)
Store a string in the buffer, which can contain any binary data.
Definition: flatbuffers.h:1616
Offset< Vector< T > > CreateVector(const std::vector< T > &v)
Serialize a std::vector into a FlatBuffer vector.
Definition: flatbuffers.h:1815
static const size_t kFileIdentifierLength
The length of a FlatBuffer file header.
Definition: flatbuffers.h:2214
Offset< Vector< const T * > > CreateVectorOfStructs(const T *v, size_t len)
Serialize an array of structs into a FlatBuffer vector.
Definition: flatbuffers.h:1915
Definition: flatbuffers.h:253
Definition: flatbuffers.h:437
Definition: flatbuffers.h:945
Definition: flatbuffers.h:2263
Definition: flatbuffers.h:2289
Definition: flatbuffers.h:105
Definition: flatbuffers.h:67
Definition: flatbuffers.h:699
Definition: flatbuffers.h:133
Definition: flatbuffers.h:230