Rolling 20220924

This commit is contained in:
jomjol
2022-09-24 21:24:50 +02:00
parent a1691a77cf
commit 68e57d5ec4
133 changed files with 5485 additions and 1810 deletions

View File

@@ -150,7 +150,7 @@
#define FLATBUFFERS_VERSION_MAJOR 2
#define FLATBUFFERS_VERSION_MINOR 0
#define FLATBUFFERS_VERSION_REVISION 5
#define FLATBUFFERS_VERSION_REVISION 6
#define FLATBUFFERS_STRING_EXPAND(X) #X
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
namespace flatbuffers {
@@ -270,9 +270,12 @@ namespace flatbuffers {
#endif // !FLATBUFFERS_HAS_NEW_STRTOD
#ifndef FLATBUFFERS_LOCALE_INDEPENDENT
// Enable locale independent functions {strtof_l, strtod_l,strtoll_l, strtoull_l}.
#if ((defined(_MSC_VER) && _MSC_VER >= 1800) || \
(defined(_XOPEN_VERSION) && (_XOPEN_VERSION>=700)) && (!defined(__ANDROID_API__) || (defined(__ANDROID_API__) && (__ANDROID_API__>=21))))
// Enable locale independent functions {strtof_l, strtod_l,strtoll_l,
// strtoull_l}.
#if (defined(_MSC_VER) && _MSC_VER >= 1800) || \
(defined(__ANDROID_API__) && __ANDROID_API__>= 21) || \
(defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 700)) && \
(!defined(__Fuchsia__) && !defined(__ANDROID_API__))
#define FLATBUFFERS_LOCALE_INDEPENDENT 1
#else
#define FLATBUFFERS_LOCALE_INDEPENDENT 0
@@ -338,8 +341,17 @@ typedef uintmax_t largest_scalar_t;
// In 32bits, this evaluates to 2GB - 1
#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(::flatbuffers::soffset_t) * 8 - 1)) - 1)
// The minimum size buffer that can be a valid flatbuffer.
// Includes the offset to the root table (uoffset_t), the offset to the vtable
// of the root table (soffset_t), the size of the vtable (uint16_t), and the
// size of the referring table (uint16_t).
#define FLATBUFFERS_MIN_BUFFER_SIZE sizeof(uoffset_t) + sizeof(soffset_t) + \
sizeof(uint16_t) + sizeof(uint16_t)
// We support aligning the contents of buffers up to this size.
#define FLATBUFFERS_MAX_ALIGNMENT 16
#ifndef FLATBUFFERS_MAX_ALIGNMENT
#define FLATBUFFERS_MAX_ALIGNMENT 32
#endif
/// @brief The length of a FlatBuffer file header.
static const size_t kFileIdentifierLength = 4;

View File

@@ -18,6 +18,7 @@
#define FLATBUFFERS_FLATBUFFER_BUILDER_H_
#include <functional>
#include <initializer_list>
#include "flatbuffers/allocator.h"
#include "flatbuffers/array.h"
@@ -42,14 +43,15 @@ inline voffset_t FieldIndexToOffset(voffset_t field_id) {
return static_cast<voffset_t>((field_id + fixed_fields) * sizeof(voffset_t));
}
template<typename T, typename Alloc>
template<typename T, typename Alloc = std::allocator<T>>
const T *data(const std::vector<T, Alloc> &v) {
// Eventually the returned pointer gets passed down to memcpy, so
// we need it to be non-null to avoid undefined behavior.
static uint8_t t;
return v.empty() ? reinterpret_cast<const T *>(&t) : &v.front();
}
template<typename T, typename Alloc> T *data(std::vector<T, Alloc> &v) {
template<typename T, typename Alloc = std::allocator<T>>
T *data(std::vector<T, Alloc> &v) {
// Eventually the returned pointer gets passed down to memcpy, so
// we need it to be non-null to avoid undefined behavior.
static uint8_t t;
@@ -285,9 +287,7 @@ class FlatBufferBuilder {
FieldLoc fl = { off, field };
buf_.scratch_push_small(fl);
num_field_loc++;
if (field > max_voffset_) {
max_voffset_ = field;
}
if (field > max_voffset_) { max_voffset_ = field; }
}
// Like PushElement, but additionally tracks the field this represents.
@@ -443,6 +443,7 @@ class FlatBufferBuilder {
// Aligns such that when "len" bytes are written, an object can be written
// after it with "alignment" without padding.
void PreAlign(size_t len, size_t alignment) {
if (len == 0) return;
TrackMinAlign(alignment);
buf_.fill(PaddingBytes(GetSize() + len, alignment));
}
@@ -601,12 +602,14 @@ class FlatBufferBuilder {
// This is useful when storing a nested_flatbuffer in a vector of bytes,
// or when storing SIMD floats, etc.
void ForceVectorAlignment(size_t len, size_t elemsize, size_t alignment) {
if (len == 0) return;
FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment));
PreAlign(len * elemsize, alignment);
}
// Similar to ForceVectorAlignment but for String fields.
void ForceStringAlignment(size_t len, size_t alignment) {
if (len == 0) return;
FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment));
PreAlign((len + 1) * sizeof(char), alignment);
}
@@ -642,6 +645,27 @@ class FlatBufferBuilder {
return Offset<Vector<T>>(EndVector(len));
}
/// @brief Serialize an array like object into a FlatBuffer `vector`.
/// @tparam T The data type of the array elements.
/// @tparam C The type of the array.
/// @param[in] array A reference to an array like object of type `T` to
/// serialize into the buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T, class C> Offset<Vector<T>> CreateVector(const C &array) {
return CreateVector(array.data(), array.size());
}
/// @brief Serialize an initializer list into a FlatBuffer `vector`.
/// @tparam T The data type of the initializer list elements.
/// @param[in] v The value of the initializer list.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T>
Offset<Vector<T>> CreateVector(std::initializer_list<T> v) {
return CreateVector(v.begin(), v.size());
}
template<typename T>
Offset<Vector<Offset<T>>> CreateVector(const Offset<T> *v, size_t len) {
StartVector(len, sizeof(Offset<T>));
@@ -655,7 +679,7 @@ class FlatBufferBuilder {
/// buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T, typename Alloc>
template<typename T, typename Alloc = std::allocator<T>>
Offset<Vector<T>> CreateVector(const std::vector<T, Alloc> &v) {
return CreateVector(data(v), v.size());
}
@@ -706,15 +730,18 @@ class FlatBufferBuilder {
return CreateVector(elems);
}
/// @brief Serialize a `std::vector<std::string>` into a FlatBuffer `vector`.
/// @brief Serialize a `std::vector<StringType>` into a FlatBuffer `vector`.
/// whereas StringType is any type that is accepted by the CreateString()
/// overloads.
/// This is a convenience function for a common case.
/// @param v A const reference to the `std::vector` to serialize into the
/// buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename Alloc>
template<typename StringType = std::string,
typename Alloc = std::allocator<StringType>>
Offset<Vector<Offset<String>>> CreateVectorOfStrings(
const std::vector<std::string, Alloc> &v) {
const std::vector<StringType, Alloc> &v) {
return CreateVectorOfStrings(v.cbegin(), v.cend());
}
@@ -841,7 +868,7 @@ class FlatBufferBuilder {
/// serialize into the buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T, typename Alloc>
template<typename T, typename Alloc = std::allocator<T>>
Offset<Vector<const T *>> CreateVectorOfStructs(
const std::vector<T, Alloc> &v) {
return CreateVectorOfStructs(data(v), v.size());
@@ -857,7 +884,7 @@ class FlatBufferBuilder {
/// to the FlatBuffer struct.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T, typename S, typename Alloc>
template<typename T, typename S, typename Alloc = std::allocator<T>>
Offset<Vector<const T *>> CreateVectorOfNativeStructs(
const std::vector<S, Alloc> &v, T (*const pack_func)(const S &)) {
return CreateVectorOfNativeStructs<T, S>(data(v), v.size(), pack_func);
@@ -871,7 +898,7 @@ class FlatBufferBuilder {
/// serialize into the buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T, typename S, typename Alloc>
template<typename T, typename S, typename Alloc = std::allocator<S>>
Offset<Vector<const T *>> CreateVectorOfNativeStructs(
const std::vector<S, Alloc> &v) {
return CreateVectorOfNativeStructs<T, S>(data(v), v.size());
@@ -892,7 +919,7 @@ class FlatBufferBuilder {
/// serialize into the buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T, typename Alloc>
template<typename T, typename Alloc = std::allocator<T>>
Offset<Vector<const T *>> CreateVectorOfSortedStructs(
std::vector<T, Alloc> *v) {
return CreateVectorOfSortedStructs(data(*v), v->size());
@@ -906,7 +933,7 @@ class FlatBufferBuilder {
/// serialize into the buffer as a `vector`.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T, typename S, typename Alloc>
template<typename T, typename S, typename Alloc = std::allocator<T>>
Offset<Vector<const T *>> CreateVectorOfSortedNativeStructs(
std::vector<S, Alloc> *v) {
return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size());
@@ -922,7 +949,7 @@ class FlatBufferBuilder {
/// where the vector is stored.
template<typename T>
Offset<Vector<const T *>> CreateVectorOfSortedStructs(T *v, size_t len) {
std::sort(v, v + len, StructKeyComparator<T>());
std::stable_sort(v, v + len, StructKeyComparator<T>());
return CreateVectorOfStructs(v, len);
}
@@ -941,7 +968,7 @@ class FlatBufferBuilder {
extern T Pack(const S &);
auto structs = StartVectorOfStructs<T>(len);
for (size_t i = 0; i < len; i++) { structs[i] = Pack(v[i]); }
std::sort(structs, structs + len, StructKeyComparator<T>());
std::stable_sort(structs, structs + len, StructKeyComparator<T>());
return EndVectorOfStructs<T>(len);
}
@@ -973,7 +1000,7 @@ class FlatBufferBuilder {
template<typename T>
Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(Offset<T> *v,
size_t len) {
std::sort(v, v + len, TableKeyComparator<T>(buf_));
std::stable_sort(v, v + len, TableKeyComparator<T>(buf_));
return CreateVector(v, len);
}
@@ -984,7 +1011,7 @@ class FlatBufferBuilder {
/// offsets to store in the buffer in sorted order.
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
template<typename T, typename Alloc>
template<typename T, typename Alloc = std::allocator<T>>
Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
std::vector<Offset<T>, Alloc> *v) {
return CreateVectorOfSortedTables(data(*v), v->size());
@@ -1074,7 +1101,7 @@ class FlatBufferBuilder {
void SwapBufAllocator(FlatBufferBuilder &other) {
buf_.swap_allocator(other.buf_);
}
/// @brief The length of a FlatBuffer file header.
static const size_t kFileIdentifierLength =
::flatbuffers::kFileIdentifierLength;

View File

@@ -226,27 +226,13 @@ struct TypeTable {
};
// String which identifies the current version of FlatBuffers.
// flatbuffer_version_string is used by Google developers to identify which
// applications uploaded to Google Play are using this library. This allows
// the development team at Google to determine the popularity of the library.
// How it works: Applications that are uploaded to the Google Play Store are
// scanned for this version string. We track which applications are using it
// to measure popularity. You are free to remove it (of course) but we would
// appreciate if you left it in.
inline const char *flatbuffers_version_string() {
return "FlatBuffers " FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
}
// Weak linkage is culled by VS & doesn't work on cygwin.
// clang-format off
#if !defined(_WIN32) && !defined(__CYGWIN__)
extern volatile __attribute__((weak)) const char *flatbuffer_version_string;
volatile __attribute__((weak)) const char *flatbuffer_version_string =
"FlatBuffers "
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MAJOR) "."
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_MINOR) "."
FLATBUFFERS_STRING(FLATBUFFERS_VERSION_REVISION);
#endif // !defined(_WIN32) && !defined(__CYGWIN__)
#define FLATBUFFERS_DEFINE_BITMASK_OPERATORS(E, T)\
inline E operator | (E lhs, E rhs){\
return E(T(lhs) | T(rhs));\

View File

@@ -156,6 +156,7 @@ inline uint64_t ReadUInt64(const uint8_t *data, uint8_t byte_width) {
// TODO: GCC apparently replaces memcpy by a rep movsb, but only if count is a
// constant, which here it isn't. Test if memcpy is still faster than
// the conditionals in ReadSizedScalar. Can also use inline asm.
// clang-format off
#if defined(_MSC_VER) && defined(_M_X64) && !defined(_M_ARM64EC)
// This is 64-bit Windows only, __movsb does not work on 32-bit Windows.
@@ -371,10 +372,7 @@ void AppendToString(std::string &s, T &&v, bool keys_quoted) {
class Reference {
public:
Reference()
: data_(nullptr),
parent_width_(0),
byte_width_(0),
type_(FBT_NULL) {}
: data_(nullptr), parent_width_(0), byte_width_(0), type_(FBT_NULL) {}
Reference(const uint8_t *data, uint8_t parent_width, uint8_t byte_width,
Type type)
@@ -590,7 +588,23 @@ class Reference {
auto keys = m.Keys();
auto vals = m.Values();
for (size_t i = 0; i < keys.size(); i++) {
keys[i].ToString(true, keys_quoted, s);
bool kq = keys_quoted;
if (!kq) {
// FlexBuffers keys may contain arbitrary characters, only allow
// unquoted if it looks like an "identifier":
const char *p = keys[i].AsKey();
if (!flatbuffers::is_alpha(*p) && *p != '_') {
kq = true;
} else {
while (*++p) {
if (!flatbuffers::is_alnum(*p) && *p != '_') {
kq = true;
break;
}
}
}
}
keys[i].ToString(true, kq, s);
s += ": ";
vals[i].ToString(true, keys_quoted, s);
if (i < keys.size() - 1) s += ", ";
@@ -1424,10 +1438,12 @@ class Builder FLATBUFFERS_FINAL_CLASS {
template<typename T> static Type GetScalarType() {
static_assert(flatbuffers::is_scalar<T>::value, "Unrelated types");
return flatbuffers::is_floating_point<T>::value ? FBT_FLOAT
: flatbuffers::is_same<T, bool>::value
? FBT_BOOL
: (flatbuffers::is_unsigned<T>::value ? FBT_UINT : FBT_INT);
return flatbuffers::is_floating_point<T>::value
? FBT_FLOAT
: flatbuffers::is_same<T, bool>::value
? FBT_BOOL
: (flatbuffers::is_unsigned<T>::value ? FBT_UINT
: FBT_INT);
}
public:
@@ -1660,8 +1676,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
// comes at the cost of using additional memory the same size of
// the buffer being verified, so it is by default off.
std::vector<uint8_t> *reuse_tracker = nullptr,
bool _check_alignment = true,
size_t max_depth = 64)
bool _check_alignment = true, size_t max_depth = 64)
: buf_(buf),
size_(buf_len),
depth_(0),
@@ -1704,18 +1719,16 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
auto o = static_cast<size_t>(p - buf_);
return VerifyBefore(o, len);
}
bool VerifyByteWidth(size_t width) {
return Check(width == 1 || width == 2 || width == 4 || width == 8);
}
bool VerifyType(int type) {
return Check(type >= 0 && type < FBT_MAX_TYPE);
}
bool VerifyType(int type) { return Check(type >= 0 && type < FBT_MAX_TYPE); }
bool VerifyOffset(uint64_t off, const uint8_t *p) {
return Check(off <= static_cast<uint64_t>(size_)) &&
off <= static_cast<uint64_t>(p - buf_);
off <= static_cast<uint64_t>(p - buf_);
}
bool VerifyAlignment(const uint8_t *p, size_t size) const {
@@ -1723,16 +1736,16 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
return Check((o & (size - 1)) == 0 || !check_alignment_);
}
// Macro, since we want to escape from parent function & use lazy args.
#define FLEX_CHECK_VERIFIED(P, PACKED_TYPE) \
if (reuse_tracker_) { \
auto packed_type = PACKED_TYPE; \
auto existing = (*reuse_tracker_)[P - buf_]; \
if (existing == packed_type) return true; \
/* Fail verification if already set with different type! */ \
if (!Check(existing == 0)) return false; \
(*reuse_tracker_)[P - buf_] = packed_type; \
}
// Macro, since we want to escape from parent function & use lazy args.
#define FLEX_CHECK_VERIFIED(P, PACKED_TYPE) \
if (reuse_tracker_) { \
auto packed_type = PACKED_TYPE; \
auto existing = (*reuse_tracker_)[P - buf_]; \
if (existing == packed_type) return true; \
/* Fail verification if already set with different type! */ \
if (!Check(existing == 0)) return false; \
(*reuse_tracker_)[P - buf_] = packed_type; \
}
bool VerifyVector(Reference r, const uint8_t *p, Type elem_type) {
// Any kind of nesting goes thru this function, so guard against that
@@ -1742,19 +1755,19 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
if (!Check(depth_ <= max_depth_ && num_vectors_ <= max_vectors_))
return false;
auto size_byte_width = r.byte_width_;
FLEX_CHECK_VERIFIED(p, PackedType(Builder::WidthB(size_byte_width), r.type_));
if (!VerifyBeforePointer(p, size_byte_width))
return false;
if (!VerifyBeforePointer(p, size_byte_width)) return false;
FLEX_CHECK_VERIFIED(p - size_byte_width,
PackedType(Builder::WidthB(size_byte_width), r.type_));
auto sized = Sized(p, size_byte_width);
auto num_elems = sized.size();
auto elem_byte_width =
r.type_ == FBT_STRING || r.type_ == FBT_BLOB ? uint8_t(1) : r.byte_width_;
auto elem_byte_width = r.type_ == FBT_STRING || r.type_ == FBT_BLOB
? uint8_t(1)
: r.byte_width_;
auto max_elems = SIZE_MAX / elem_byte_width;
if (!Check(num_elems < max_elems))
return false; // Protect against byte_size overflowing.
auto byte_size = num_elems * elem_byte_width;
if (!VerifyFromPointer(p, byte_size))
return false;
if (!VerifyFromPointer(p, byte_size)) return false;
if (elem_type == FBT_NULL) {
// Verify type bytes after the vector.
if (!VerifyFromPointer(p + byte_size, num_elems)) return false;
@@ -1775,28 +1788,25 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
bool VerifyKeys(const uint8_t *p, uint8_t byte_width) {
// The vector part of the map has already been verified.
const size_t num_prefixed_fields = 3;
if (!VerifyBeforePointer(p, byte_width * num_prefixed_fields))
return false;
if (!VerifyBeforePointer(p, byte_width * num_prefixed_fields)) return false;
p -= byte_width * num_prefixed_fields;
auto off = ReadUInt64(p, byte_width);
if (!VerifyOffset(off, p))
return false;
if (!VerifyOffset(off, p)) return false;
auto key_byte_with =
static_cast<uint8_t>(ReadUInt64(p + byte_width, byte_width));
if (!VerifyByteWidth(key_byte_with))
return false;
static_cast<uint8_t>(ReadUInt64(p + byte_width, byte_width));
if (!VerifyByteWidth(key_byte_with)) return false;
return VerifyVector(Reference(p, byte_width, key_byte_with, FBT_VECTOR_KEY),
p - off, FBT_KEY);
}
bool VerifyKey(const uint8_t* p) {
bool VerifyKey(const uint8_t *p) {
FLEX_CHECK_VERIFIED(p, PackedType(BIT_WIDTH_8, FBT_KEY));
while (p < buf_ + size_)
if (*p++) return true;
return false;
}
#undef FLEX_CHECK_VERIFIED
#undef FLEX_CHECK_VERIFIED
bool VerifyTerminator(const String &s) {
return VerifyFromPointer(reinterpret_cast<const uint8_t *>(s.c_str()),
@@ -1814,37 +1824,26 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
}
// All remaining types are an offset.
auto off = ReadUInt64(r.data_, r.parent_width_);
if (!VerifyOffset(off, r.data_))
return false;
if (!VerifyOffset(off, r.data_)) return false;
auto p = r.Indirect();
if (!VerifyAlignment(p, r.byte_width_))
return false;
if (!VerifyAlignment(p, r.byte_width_)) return false;
switch (r.type_) {
case FBT_INDIRECT_INT:
case FBT_INDIRECT_UINT:
case FBT_INDIRECT_FLOAT:
return VerifyFromPointer(p, r.byte_width_);
case FBT_KEY:
return VerifyKey(p);
case FBT_INDIRECT_FLOAT: return VerifyFromPointer(p, r.byte_width_);
case FBT_KEY: return VerifyKey(p);
case FBT_MAP:
return VerifyVector(r, p, FBT_NULL) &&
VerifyKeys(p, r.byte_width_);
case FBT_VECTOR:
return VerifyVector(r, p, FBT_NULL);
case FBT_VECTOR_INT:
return VerifyVector(r, p, FBT_INT);
return VerifyVector(r, p, FBT_NULL) && VerifyKeys(p, r.byte_width_);
case FBT_VECTOR: return VerifyVector(r, p, FBT_NULL);
case FBT_VECTOR_INT: return VerifyVector(r, p, FBT_INT);
case FBT_VECTOR_BOOL:
case FBT_VECTOR_UINT:
return VerifyVector(r, p, FBT_UINT);
case FBT_VECTOR_FLOAT:
return VerifyVector(r, p, FBT_FLOAT);
case FBT_VECTOR_KEY:
return VerifyVector(r, p, FBT_KEY);
case FBT_VECTOR_UINT: return VerifyVector(r, p, FBT_UINT);
case FBT_VECTOR_FLOAT: return VerifyVector(r, p, FBT_FLOAT);
case FBT_VECTOR_KEY: return VerifyVector(r, p, FBT_KEY);
case FBT_VECTOR_STRING_DEPRECATED:
// Use of FBT_KEY here intentional, see elsewhere.
return VerifyVector(r, p, FBT_KEY);
case FBT_BLOB:
return VerifyVector(r, p, FBT_UINT);
case FBT_BLOB: return VerifyVector(r, p, FBT_UINT);
case FBT_STRING:
return VerifyVector(r, p, FBT_UINT) &&
VerifyTerminator(String(p, r.byte_width_));
@@ -1859,12 +1858,10 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
case FBT_VECTOR_FLOAT4: {
uint8_t len = 0;
auto vtype = ToFixedTypedVectorElementType(r.type_, &len);
if (!VerifyType(vtype))
return false;
if (!VerifyType(vtype)) return false;
return VerifyFromPointer(p, r.byte_width_ * len);
}
default:
return false;
default: return false;
}
}
@@ -1874,8 +1871,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
auto end = buf_ + size_;
auto byte_width = *--end;
auto packed_type = *--end;
return VerifyByteWidth(byte_width) &&
Check(end - buf_ >= byte_width) &&
return VerifyByteWidth(byte_width) && Check(end - buf_ >= byte_width) &&
VerifyRef(Reference(end - byte_width, byte_width, packed_type));
}
@@ -1890,27 +1886,14 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
std::vector<uint8_t> *reuse_tracker_;
};
// Utility function that contructs the Verifier for you, see above for parameters.
// Utility function that contructs the Verifier for you, see above for
// parameters.
inline bool VerifyBuffer(const uint8_t *buf, size_t buf_len,
std::vector<uint8_t> *reuse_tracker = nullptr) {
Verifier verifier(buf, buf_len, reuse_tracker);
return verifier.VerifyBuffer();
}
#ifdef FLATBUFFERS_H_
// This is a verifier utility function that works together with the
// FlatBuffers verifier, which should only be present if flatbuffer.h
// has been included (which it typically is in generated code).
inline bool VerifyNestedFlexBuffer(const flatbuffers::Vector<uint8_t> *nv,
flatbuffers::Verifier &verifier) {
if (!nv) return true;
return verifier.Check(
flexbuffers::VerifyBuffer(nv->data(), nv->size(),
verifier.GetFlexReuseTracker()));
}
#endif
} // namespace flexbuffers
#if defined(_MSC_VER)

View File

@@ -26,16 +26,20 @@
#include <memory>
#include <limits>
// Detect C++17 compatible compiler.
// __cplusplus >= 201703L - a compiler has support of 'static inline' variables.
#if defined(FLATBUFFERS_USE_STD_OPTIONAL) \
|| (defined(__cplusplus) && __cplusplus >= 201703L) \
|| (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L))
#ifndef FLATBUFFERS_USE_STD_OPTIONAL
// Detect C++17 compatible compiler.
// __cplusplus >= 201703L - a compiler has support of 'static inline' variables.
#if (defined(__cplusplus) && __cplusplus >= 201703L) \
|| (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
#define FLATBUFFERS_USE_STD_OPTIONAL 1
#else
#define FLATBUFFERS_USE_STD_OPTIONAL 0
#endif // (defined(__cplusplus) && __cplusplus >= 201703L) ...
#endif // FLATBUFFERS_USE_STD_OPTIONAL
#if FLATBUFFERS_USE_STD_OPTIONAL
#include <optional>
#ifndef FLATBUFFERS_USE_STD_OPTIONAL
#define FLATBUFFERS_USE_STD_OPTIONAL
#endif
#endif // defined(FLATBUFFERS_USE_STD_OPTIONAL) ...
#endif
// The __cpp_lib_span is the predefined feature macro.
#if defined(FLATBUFFERS_USE_STD_SPAN)
@@ -128,7 +132,7 @@ namespace flatbuffers {
};
#endif // defined(FLATBUFFERS_TEMPLATES_ALIASES)
#ifdef FLATBUFFERS_USE_STD_OPTIONAL
#if FLATBUFFERS_USE_STD_OPTIONAL
template<class T>
using Optional = std::optional<T>;
using nullopt_t = std::nullopt_t;
@@ -284,13 +288,13 @@ FLATBUFFERS_CONSTEXPR std::size_t dynamic_extent = static_cast<std::size_t>(-1);
namespace internal {
// This is SFINAE helper class for checking of a common condition:
// > This overload only participates in overload resolution
// > Check whether a pointer to an array of U can be converted
// > to a pointer to an array of E.
// This helper is used for checking of 'U -> const U'.
template<class E, std::size_t Extent, class U, std::size_t N>
// > Check whether a pointer to an array of From can be converted
// > to a pointer to an array of To.
// This helper is used for checking of 'From -> const From'.
template<class To, std::size_t Extent, class From, std::size_t N>
struct is_span_convertable {
using type =
typename std::conditional<std::is_convertible<U (*)[], E (*)[]>::value
typename std::conditional<std::is_convertible<From (*)[], To (*)[]>::value
&& (Extent == dynamic_extent || N == Extent),
int, void>::type;
};
@@ -362,13 +366,9 @@ class span FLATBUFFERS_FINAL_CLASS {
#if !defined(FLATBUFFERS_SPAN_MINIMAL)
using Iterator = internal::SpanIterator<T>;
using ConstIterator = internal::SpanIterator<const T>;
Iterator begin() const { return Iterator(data()); }
Iterator end() const { return Iterator(data() + size()); }
ConstIterator cbegin() const { return ConstIterator(data()); }
ConstIterator cend() const { return ConstIterator(data() + size()); }
#endif
// Returns a reference to the idx-th element of the sequence.
@@ -462,45 +462,45 @@ class span FLATBUFFERS_FINAL_CLASS {
private:
// This is a naive implementation with 'count_' member even if (Extent != dynamic_extent).
pointer const data_;
const size_type count_;
size_type count_;
};
#endif // defined(FLATBUFFERS_USE_STD_SPAN)
#if !defined(FLATBUFFERS_SPAN_MINIMAL)
template<class U, std::size_t N>
template<class ElementType, std::size_t Extent>
FLATBUFFERS_CONSTEXPR_CPP11
flatbuffers::span<U, N> make_span(U(&arr)[N]) FLATBUFFERS_NOEXCEPT {
return span<U, N>(arr);
flatbuffers::span<ElementType, Extent> make_span(ElementType(&arr)[Extent]) FLATBUFFERS_NOEXCEPT {
return span<ElementType, Extent>(arr);
}
template<class U, std::size_t N>
template<class ElementType, std::size_t Extent>
FLATBUFFERS_CONSTEXPR_CPP11
flatbuffers::span<const U, N> make_span(const U(&arr)[N]) FLATBUFFERS_NOEXCEPT {
return span<const U, N>(arr);
flatbuffers::span<const ElementType, Extent> make_span(const ElementType(&arr)[Extent]) FLATBUFFERS_NOEXCEPT {
return span<const ElementType, Extent>(arr);
}
template<class U, std::size_t N>
template<class ElementType, std::size_t Extent>
FLATBUFFERS_CONSTEXPR_CPP11
flatbuffers::span<U, N> make_span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
return span<U, N>(arr);
flatbuffers::span<ElementType, Extent> make_span(std::array<ElementType, Extent> &arr) FLATBUFFERS_NOEXCEPT {
return span<ElementType, Extent>(arr);
}
template<class U, std::size_t N>
template<class ElementType, std::size_t Extent>
FLATBUFFERS_CONSTEXPR_CPP11
flatbuffers::span<const U, N> make_span(const std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT {
return span<const U, N>(arr);
flatbuffers::span<const ElementType, Extent> make_span(const std::array<ElementType, Extent> &arr) FLATBUFFERS_NOEXCEPT {
return span<const ElementType, Extent>(arr);
}
template<class U, std::size_t N>
template<class ElementType, std::size_t Extent>
FLATBUFFERS_CONSTEXPR_CPP11
flatbuffers::span<U, dynamic_extent> make_span(U *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
return span<U, dynamic_extent>(first, count);
flatbuffers::span<ElementType, dynamic_extent> make_span(ElementType *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
return span<ElementType, dynamic_extent>(first, count);
}
template<class U, std::size_t N>
template<class ElementType, std::size_t Extent>
FLATBUFFERS_CONSTEXPR_CPP11
flatbuffers::span<const U, dynamic_extent> make_span(const U *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
return span<const U, dynamic_extent>(first, count);
flatbuffers::span<const ElementType, dynamic_extent> make_span(const ElementType *first, std::size_t count) FLATBUFFERS_NOEXCEPT {
return span<const ElementType, dynamic_extent>(first, count);
}
#endif // !defined(FLATBUFFERS_SPAN_MINIMAL)

View File

@@ -112,20 +112,22 @@ class Table {
// Verify a particular field.
template<typename T>
bool VerifyField(const Verifier &verifier, voffset_t field) const {
bool VerifyField(const Verifier &verifier, voffset_t field,
size_t align) const {
// Calling GetOptionalFieldOffset should be safe now thanks to
// VerifyTable().
auto field_offset = GetOptionalFieldOffset(field);
// Check the actual field.
return !field_offset || verifier.Verify<T>(data_, field_offset);
return !field_offset || verifier.VerifyField<T>(data_, field_offset, align);
}
// VerifyField for required fields.
template<typename T>
bool VerifyFieldRequired(const Verifier &verifier, voffset_t field) const {
bool VerifyFieldRequired(const Verifier &verifier, voffset_t field,
size_t align) const {
auto field_offset = GetOptionalFieldOffset(field);
return verifier.Check(field_offset != 0) &&
verifier.Verify<T>(data_, field_offset);
verifier.VerifyField<T>(data_, field_offset, align);
}
// Versions for offsets.
@@ -163,4 +165,4 @@ inline flatbuffers::Optional<bool> Table::GetOptional<uint8_t, bool>(
} // namespace flatbuffers
#endif // FLATBUFFERS_TABLE_H_
#endif // FLATBUFFERS_TABLE_H_

View File

@@ -17,8 +17,8 @@
#ifndef FLATBUFFERS_UTIL_H_
#define FLATBUFFERS_UTIL_H_
#include <errno.h>
#include <ctype.h>
#include <errno.h>
#include "flatbuffers/base.h"
#include "flatbuffers/stl_emulation.h"
@@ -30,8 +30,8 @@
#endif
#ifndef FLATBUFFERS_PREFER_PRINTF
# include <sstream>
# include <iomanip>
# include <sstream>
#else // FLATBUFFERS_PREFER_PRINTF
# include <float.h>
# include <stdio.h>
@@ -454,6 +454,9 @@ std::string StripPath(const std::string &filepath);
// Strip the last component of the path + separator.
std::string StripFileName(const std::string &filepath);
std::string StripPrefix(const std::string &filepath,
const std::string &prefix_to_remove);
// Concatenates a path with a filename, regardless of whether the path
// ends in a separator or not.
std::string ConCatPathFileName(const std::string &path,
@@ -691,6 +694,32 @@ bool ReadEnvironmentVariable(const char *var_name,
// MSVC specific: Send all assert reports to STDOUT to prevent CI hangs.
void SetupDefaultCRTReportMode();
enum class Case {
kUnknown = 0,
// TheQuickBrownFox
kUpperCamel = 1,
// theQuickBrownFox
kLowerCamel = 2,
// the_quick_brown_fox
kSnake = 3,
// THE_QUICK_BROWN_FOX
kScreamingSnake = 4,
// THEQUICKBROWNFOX
kAllUpper = 5,
// thequickbrownfox
kAllLower = 6,
// the-quick-brown-fox
kDasher = 7,
// THEQuiCKBr_ownFox (or whatever you want, we won't change it)
kKeep = 8,
// the_quick_brown_fox123 (as opposed to the_quick_brown_fox_123)
kSnake2 = 9,
};
// Convert the `input` string of case `input_case` to the specified `output_case`.
std::string ConvertCase(const std::string &input, Case output_case,
Case input_case = Case::kSnake);
} // namespace flatbuffers
#endif // FLATBUFFERS_UTIL_H_

View File

@@ -19,6 +19,7 @@
#include "flatbuffers/base.h"
#include "flatbuffers/buffer.h"
#include "flatbuffers/stl_emulation.h"
namespace flatbuffers {
@@ -326,6 +327,24 @@ FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const uint8_t> make_bytes_span(
return span<const uint8_t>(vec.Data(), vec.size() * sizeof(U));
}
// Convenient helper functions to get a span of any vector, regardless
// of whether it is null or not (the field is not set).
template<class U>
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<U> make_span(Vector<U> *ptr)
FLATBUFFERS_NOEXCEPT {
static_assert(Vector<U>::is_span_observable,
"wrong type U, only LE-scalar, or byte types are allowed");
return ptr ? make_span(*ptr) : span<U>();
}
template<class U>
FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span<const U> make_span(
const Vector<U> *ptr) FLATBUFFERS_NOEXCEPT {
static_assert(Vector<U>::is_span_observable,
"wrong type U, only LE-scalar, or byte types are allowed");
return ptr ? make_span(*ptr) : span<const U>();
}
// Represent a vector much like the template above, but in this case we
// don't know what the element types are (used with reflection.h).
class VectorOfAny {

View File

@@ -18,7 +18,6 @@
#define FLATBUFFERS_VERIFIER_H_
#include "flatbuffers/base.h"
#include "flatbuffers/util.h"
#include "flatbuffers/vector.h"
namespace flatbuffers {
@@ -26,22 +25,24 @@ namespace flatbuffers {
// Helper class to verify the integrity of a FlatBuffer
class Verifier FLATBUFFERS_FINAL_CLASS {
public:
Verifier(const uint8_t *buf, size_t buf_len, uoffset_t _max_depth = 64,
uoffset_t _max_tables = 1000000, bool _check_alignment = true)
Verifier(const uint8_t *const buf, const size_t buf_len,
const uoffset_t _max_depth = 64,
const uoffset_t _max_tables = 1000000,
const bool _check_alignment = true)
: buf_(buf),
size_(buf_len),
depth_(0),
max_depth_(_max_depth),
num_tables_(0),
max_tables_(_max_tables),
upper_bound_(0),
check_alignment_(_check_alignment),
upper_bound_(0),
depth_(0),
num_tables_(0),
flex_reuse_tracker_(nullptr) {
FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
}
// Central location where any verification failures register.
bool Check(bool ok) const {
bool Check(const bool ok) const {
// clang-format off
#ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
FLATBUFFERS_ASSERT(ok);
@@ -55,7 +56,7 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
}
// Verify any range within the buffer.
bool Verify(size_t elem, size_t elem_len) const {
bool Verify(const size_t elem, const size_t elem_len) const {
// clang-format off
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
auto upper_bound = elem + elem_len;
@@ -66,48 +67,52 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
return Check(elem_len < size_ && elem <= size_ - elem_len);
}
template<typename T> bool VerifyAlignment(size_t elem) const {
return Check((elem & (sizeof(T) - 1)) == 0 || !check_alignment_);
bool VerifyAlignment(const size_t elem, const size_t align) const {
return Check((elem & (align - 1)) == 0 || !check_alignment_);
}
// Verify a range indicated by sizeof(T).
template<typename T> bool Verify(size_t elem) const {
return VerifyAlignment<T>(elem) && Verify(elem, sizeof(T));
template<typename T> bool Verify(const size_t elem) const {
return VerifyAlignment(elem, sizeof(T)) && Verify(elem, sizeof(T));
}
bool VerifyFromPointer(const uint8_t *p, size_t len) {
auto o = static_cast<size_t>(p - buf_);
return Verify(o, len);
bool VerifyFromPointer(const uint8_t *const p, const size_t len) {
return Verify(static_cast<size_t>(p - buf_), len);
}
// Verify relative to a known-good base pointer.
bool Verify(const uint8_t *base, voffset_t elem_off, size_t elem_len) const {
return Verify(static_cast<size_t>(base - buf_) + elem_off, elem_len);
bool VerifyFieldStruct(const uint8_t *const base, const voffset_t elem_off,
const size_t elem_len, const size_t align) const {
const auto f = static_cast<size_t>(base - buf_) + elem_off;
return VerifyAlignment(f, align) && Verify(f, elem_len);
}
template<typename T>
bool Verify(const uint8_t *base, voffset_t elem_off) const {
return Verify(static_cast<size_t>(base - buf_) + elem_off, sizeof(T));
bool VerifyField(const uint8_t *const base, const voffset_t elem_off,
const size_t align) const {
const auto f = static_cast<size_t>(base - buf_) + elem_off;
return VerifyAlignment(f, align) && Verify(f, sizeof(T));
}
// Verify a pointer (may be NULL) of a table type.
template<typename T> bool VerifyTable(const T *table) {
template<typename T> bool VerifyTable(const T *const table) {
return !table || table->Verify(*this);
}
// Verify a pointer (may be NULL) of any vector type.
template<typename T> bool VerifyVector(const Vector<T> *vec) const {
template<typename T> bool VerifyVector(const Vector<T> *const vec) const {
return !vec || VerifyVectorOrString(reinterpret_cast<const uint8_t *>(vec),
sizeof(T));
}
// Verify a pointer (may be NULL) of a vector to struct.
template<typename T> bool VerifyVector(const Vector<const T *> *vec) const {
template<typename T>
bool VerifyVector(const Vector<const T *> *const vec) const {
return VerifyVector(reinterpret_cast<const Vector<T> *>(vec));
}
// Verify a pointer (may be NULL) to string.
bool VerifyString(const String *str) const {
bool VerifyString(const String *const str) const {
size_t end;
return !str || (VerifyVectorOrString(reinterpret_cast<const uint8_t *>(str),
1, &end) &&
@@ -116,24 +121,24 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
}
// Common code between vectors and strings.
bool VerifyVectorOrString(const uint8_t *vec, size_t elem_size,
size_t *end = nullptr) const {
auto veco = static_cast<size_t>(vec - buf_);
bool VerifyVectorOrString(const uint8_t *const vec, const size_t elem_size,
size_t *const end = nullptr) const {
const auto veco = static_cast<size_t>(vec - buf_);
// Check we can read the size field.
if (!Verify<uoffset_t>(veco)) return false;
// Check the whole array. If this is a string, the byte past the array
// must be 0.
auto size = ReadScalar<uoffset_t>(vec);
auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
const auto size = ReadScalar<uoffset_t>(vec);
const auto max_elems = FLATBUFFERS_MAX_BUFFER_SIZE / elem_size;
if (!Check(size < max_elems))
return false; // Protect against byte_size overflowing.
auto byte_size = sizeof(size) + elem_size * size;
const auto byte_size = sizeof(size) + elem_size * size;
if (end) *end = veco + byte_size;
return Verify(veco, byte_size);
}
// Special case for string contents, after the above has been called.
bool VerifyVectorOfStrings(const Vector<Offset<String>> *vec) const {
bool VerifyVectorOfStrings(const Vector<Offset<String>> *const vec) const {
if (vec) {
for (uoffset_t i = 0; i < vec->size(); i++) {
if (!VerifyString(vec->Get(i))) return false;
@@ -143,7 +148,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
}
// Special case for table contents, after the above has been called.
template<typename T> bool VerifyVectorOfTables(const Vector<Offset<T>> *vec) {
template<typename T>
bool VerifyVectorOfTables(const Vector<Offset<T>> *const vec) {
if (vec) {
for (uoffset_t i = 0; i < vec->size(); i++) {
if (!vec->Get(i)->Verify(*this)) return false;
@@ -153,29 +159,40 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
}
__supress_ubsan__("unsigned-integer-overflow") bool VerifyTableStart(
const uint8_t *table) {
const uint8_t *const table) {
// Check the vtable offset.
auto tableo = static_cast<size_t>(table - buf_);
const auto tableo = static_cast<size_t>(table - buf_);
if (!Verify<soffset_t>(tableo)) return false;
// This offset may be signed, but doing the subtraction unsigned always
// gives the result we want.
auto vtableo = tableo - static_cast<size_t>(ReadScalar<soffset_t>(table));
const auto vtableo =
tableo - static_cast<size_t>(ReadScalar<soffset_t>(table));
// Check the vtable size field, then check vtable fits in its entirety.
return VerifyComplexity() && Verify<voffset_t>(vtableo) &&
VerifyAlignment<voffset_t>(ReadScalar<voffset_t>(buf_ + vtableo)) &&
Verify(vtableo, ReadScalar<voffset_t>(buf_ + vtableo));
if (!(VerifyComplexity() && Verify<voffset_t>(vtableo) &&
VerifyAlignment(ReadScalar<voffset_t>(buf_ + vtableo),
sizeof(voffset_t))))
return false;
const auto vsize = ReadScalar<voffset_t>(buf_ + vtableo);
return Check((vsize & 1) == 0) && Verify(vtableo, vsize);
}
template<typename T>
bool VerifyBufferFromStart(const char *identifier, size_t start) {
bool VerifyBufferFromStart(const char *const identifier, const size_t start) {
// Buffers have to be of some size to be valid. The reason it is a runtime
// check instead of static_assert, is that nested flatbuffers go through
// this call and their size is determined at runtime.
if (!Check(size_ >= FLATBUFFERS_MIN_BUFFER_SIZE)) return false;
// If an identifier is provided, check that we have a buffer
if (identifier && !Check((size_ >= 2 * sizeof(flatbuffers::uoffset_t) &&
BufferHasIdentifier(buf_ + start, identifier)))) {
return false;
}
// Call T::Verify, which must be in the generated code for this type.
auto o = VerifyOffset(start);
return o && reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this)
const auto o = VerifyOffset(start);
return Check(o != 0) &&
reinterpret_cast<const T *>(buf_ + start + o)->Verify(*this)
// clang-format off
#ifdef FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE
&& GetComputedSize()
@@ -185,9 +202,14 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
}
template<typename T>
bool VerifyNestedFlatBuffer(const Vector<uint8_t> *buf,
const char *identifier) {
bool VerifyNestedFlatBuffer(const Vector<uint8_t> *const buf,
const char *const identifier) {
// An empty buffer is OK as it indicates not present.
if (!buf) return true;
// If there is a nested buffer, it must be greater than the min size.
if(!Check(buf->size() >= FLATBUFFERS_MIN_BUFFER_SIZE)) return false;
Verifier nested_verifier(buf->data(), buf->size());
return nested_verifier.VerifyBuffer<T>(identifier);
}
@@ -195,19 +217,20 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
// Verify this whole buffer, starting with root type T.
template<typename T> bool VerifyBuffer() { return VerifyBuffer<T>(nullptr); }
template<typename T> bool VerifyBuffer(const char *identifier) {
template<typename T> bool VerifyBuffer(const char *const identifier) {
return VerifyBufferFromStart<T>(identifier, 0);
}
template<typename T> bool VerifySizePrefixedBuffer(const char *identifier) {
template<typename T>
bool VerifySizePrefixedBuffer(const char *const identifier) {
return Verify<uoffset_t>(0U) &&
ReadScalar<uoffset_t>(buf_) == size_ - sizeof(uoffset_t) &&
Check(ReadScalar<uoffset_t>(buf_) == size_ - sizeof(uoffset_t)) &&
VerifyBufferFromStart<T>(identifier, sizeof(uoffset_t));
}
uoffset_t VerifyOffset(size_t start) const {
uoffset_t VerifyOffset(const size_t start) const {
if (!Verify<uoffset_t>(start)) return 0;
auto o = ReadScalar<uoffset_t>(buf_ + start);
const auto o = ReadScalar<uoffset_t>(buf_ + start);
// May not point to itself.
if (!Check(o != 0)) return 0;
// Can't wrap around / buffers are max 2GB.
@@ -218,7 +241,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
return o;
}
uoffset_t VerifyOffset(const uint8_t *base, voffset_t start) const {
uoffset_t VerifyOffset(const uint8_t *const base,
const voffset_t start) const {
return VerifyOffset(static_cast<size_t>(base - buf_) + start);
}
@@ -255,23 +279,23 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
// clang-format on
}
std::vector<uint8_t> *GetFlexReuseTracker() {
return flex_reuse_tracker_;
}
std::vector<uint8_t> *GetFlexReuseTracker() { return flex_reuse_tracker_; }
void SetFlexReuseTracker(std::vector<uint8_t> *rt) {
void SetFlexReuseTracker(std::vector<uint8_t> *const rt) {
flex_reuse_tracker_ = rt;
}
private:
const uint8_t *buf_;
size_t size_;
uoffset_t depth_;
uoffset_t max_depth_;
uoffset_t num_tables_;
uoffset_t max_tables_;
const size_t size_;
const uoffset_t max_depth_;
const uoffset_t max_tables_;
const bool check_alignment_;
mutable size_t upper_bound_;
bool check_alignment_;
uoffset_t depth_;
uoffset_t num_tables_;
std::vector<uint8_t> *flex_reuse_tracker_;
};