Update flatbuffers to v22.9.29 (#26)

* update flatbuffers files

How:
- Copied files in from the latest release (v22.9.29) of flatbuffers

Why:
- The files in place blocked compilation within Alpine Linux

Links:
- https://github.com/felt/tippecanoe/issues/24
- https://github.com/google/flatbuffers/releases/tag/v22.9.29

* update flatgeobuf generate files

How
- Created `feature_generated.h` & `header_generated.h` using the `src/fbs` files from the latest release (3.23.1) of flatgeobuf
    - Downloaded the `flatc` binary from the v22.9.29 release of flatbuffers
    - Copied `flatc` into the flatgeobuf repository
    - Created a new directory named `out` to collect the generated files
    - `./flatc --cpp -o out -I include src/fbs/feature.fbs`
    - `./flatc --cpp -o out -I include src/fbs/header.fbs`
    - Moved the generate files from `out` into this repository's `flatgeobuf` directory

Why
- This is a required step in the process of updating flatbuffers files

Links
- https://github.com/flatgeobuf/flatgeobuf/releases/tag/3.23.1
- https://github.com/google/flatbuffers/releases/tag/v22.9.29
- https://github.com/felt/tippecanoe/issues/24#issuecomment-1286476550
This commit is contained in:
James Chevalier 2022-11-03 17:24:02 -04:00 committed by GitHub
parent 5b03b18f31
commit c2214631f2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 436 additions and 291 deletions

View File

@ -138,9 +138,9 @@
#endif
#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
#define FLATBUFFERS_VERSION_MAJOR 2
#define FLATBUFFERS_VERSION_MINOR 0
#define FLATBUFFERS_VERSION_REVISION 5
#define FLATBUFFERS_VERSION_MAJOR 22
#define FLATBUFFERS_VERSION_MINOR 9
#define FLATBUFFERS_VERSION_REVISION 29
#define FLATBUFFERS_STRING_EXPAND(X) #X
#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
namespace flatbuffers {
@ -260,9 +260,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
@ -270,14 +273,14 @@ namespace flatbuffers {
#endif // !FLATBUFFERS_LOCALE_INDEPENDENT
// Suppress Undefined Behavior Sanitizer (recoverable only). Usage:
// - __supress_ubsan__("undefined")
// - __supress_ubsan__("signed-integer-overflow")
// - __suppress_ubsan__("undefined")
// - __suppress_ubsan__("signed-integer-overflow")
#if defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7))
#define __supress_ubsan__(type) __attribute__((no_sanitize(type)))
#define __suppress_ubsan__(type) __attribute__((no_sanitize(type)))
#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
#define __supress_ubsan__(type) __attribute__((no_sanitize_undefined))
#define __suppress_ubsan__(type) __attribute__((no_sanitize_undefined))
#else
#define __supress_ubsan__(type)
#define __suppress_ubsan__(type)
#endif
// This is constexpr function used for checking compile-time constants.
@ -328,8 +331,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;
@ -401,7 +413,7 @@ template<typename T> T EndianScalar(T t) {
template<typename T>
// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
__supress_ubsan__("alignment")
__suppress_ubsan__("alignment")
T ReadScalar(const void *p) {
return EndianScalar(*reinterpret_cast<const T *>(p));
}
@ -415,13 +427,13 @@ T ReadScalar(const void *p) {
template<typename T>
// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
__supress_ubsan__("alignment")
__suppress_ubsan__("alignment")
void WriteScalar(void *p, T t) {
*reinterpret_cast<T *>(p) = EndianScalar(t);
}
template<typename T> struct Offset;
template<typename T> __supress_ubsan__("alignment") void WriteScalar(void *p, Offset<T> t) {
template<typename T> __suppress_ubsan__("alignment") void WriteScalar(void *p, Offset<T> t) {
*reinterpret_cast<uoffset_t *>(p) = EndianScalar(t.o);
}
@ -432,7 +444,7 @@ template<typename T> __supress_ubsan__("alignment") void WriteScalar(void *p, Of
// Computes how many bytes you'd have to pad to be able to write an
// "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in
// memory).
__supress_ubsan__("unsigned-integer-overflow")
__suppress_ubsan__("unsigned-integer-overflow")
inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
return ((~buf_size) + 1) & (scalar_size - 1);
}

View File

@ -95,7 +95,7 @@ template<typename T> struct IndirectHelper<const T *> {
}
};
/// @brief Get a pointer to the the file_identifier section of the buffer.
/// @brief Get a pointer to the file_identifier section of the buffer.
/// @return Returns a const char pointer to the start of the file_identifier
/// characters in the buffer. The returned char * has length
/// 'flatbuffers::FlatBufferBuilder::kFileIdentifierLength'.

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.
@ -358,7 +358,7 @@ class FlatBufferBuilder {
// If you get this assert, a corresponding StartTable wasn't called.
FLATBUFFERS_ASSERT(nested);
// Write the vtable offset, which is the start of any Table.
// We fill it's value later.
// We fill its value later.
auto vtableoffsetloc = PushElement<soffset_t>(0);
// Write a vtable, which consists entirely of voffset_t elements.
// It starts with the number of offsets, followed by a type id, followed
@ -443,12 +443,13 @@ 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));
}
template<typename T> void PreAlign(size_t len) {
AssertScalarT<T>();
PreAlign(len, sizeof(T));
PreAlign(len, AlignOf<T>());
}
/// @endcond
@ -578,7 +579,7 @@ class FlatBufferBuilder {
/// @param[in] str A const pointer to a `String` struct to add to the buffer.
/// @return Returns the offset in the buffer where the string starts
Offset<String> CreateSharedString(const String *str) {
return CreateSharedString(str->c_str(), str->size());
return str ? CreateSharedString(str->c_str(), str->size()) : 0;
}
/// @cond FLATBUFFERS_INTERNAL
@ -588,11 +589,15 @@ class FlatBufferBuilder {
return PushElement(static_cast<uoffset_t>(len));
}
void StartVector(size_t len, size_t elemsize) {
void StartVector(size_t len, size_t elemsize, size_t alignment) {
NotNested();
nested = true;
PreAlign<uoffset_t>(len * elemsize);
PreAlign(len * elemsize, elemsize); // Just in case elemsize > uoffset_t.
PreAlign(len * elemsize, alignment); // Just in case elemsize > uoffset_t.
}
template<typename T> void StartVector(size_t len) {
return StartVector(len, sizeof(T), AlignOf<T>());
}
// Call this right before StartVector/CreateVector if you want to force the
@ -601,12 +606,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);
}
@ -624,7 +631,7 @@ class FlatBufferBuilder {
// If this assert hits, you're specifying a template argument that is
// causing the wrong overload to be selected, remove it.
AssertScalarT<T>();
StartVector(len, sizeof(T));
StartVector<T>(len);
if (len == 0) { return Offset<Vector<T>>(EndVector(len)); }
// clang-format off
#if FLATBUFFERS_LITTLEENDIAN
@ -642,9 +649,30 @@ 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>));
StartVector<Offset<T>>(len);
for (auto i = len; i > 0;) { PushElement(v[--i]); }
return Offset<Vector<Offset<T>>>(EndVector(len));
}
@ -655,7 +683,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());
}
@ -664,7 +692,7 @@ class FlatBufferBuilder {
// an array. Instead, read elements manually.
// Background: https://isocpp.org/blog/2012/11/on-vectorbool
Offset<Vector<uint8_t>> CreateVector(const std::vector<bool> &v) {
StartVector(v.size(), sizeof(uint8_t));
StartVector<uint8_t>(v.size());
for (auto i = v.size(); i > 0;) {
PushElement(static_cast<uint8_t>(v[--i]));
}
@ -706,21 +734,24 @@ 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());
}
/// @brief Serialize a collection of Strings into a FlatBuffer `vector`.
/// This is a convenience function for a common case.
/// @param begin The begining iterator of the collection
/// @param begin The beginning iterator of the collection
/// @param end The ending iterator of the collection
/// @return Returns a typed `Offset` into the serialized data indicating
/// where the vector is stored.
@ -730,12 +761,12 @@ class FlatBufferBuilder {
auto scratch_buffer_usage = size * sizeof(Offset<String>);
// If there is not enough space to store the offsets, there definitely won't
// be enough space to store all the strings. So ensuring space for the
// scratch region is OK, for it it fails, it would have failed later.
// scratch region is OK, for if it fails, it would have failed later.
buf_.ensure_space(scratch_buffer_usage);
for (auto it = begin; it != end; ++it) {
buf_.scratch_push_small(CreateString(*it));
}
StartVector(size, sizeof(Offset<String>));
StartVector<Offset<String>>(size);
for (auto i = 1; i <= size; i++) {
// Note we re-evaluate the buf location each iteration to account for any
// underlying buffer resizing that may occur.
@ -755,7 +786,7 @@ class FlatBufferBuilder {
/// where the vector is stored.
template<typename T>
Offset<Vector<const T *>> CreateVectorOfStructs(const T *v, size_t len) {
StartVector(len * sizeof(T) / AlignOf<T>(), AlignOf<T>());
StartVector(len * sizeof(T) / AlignOf<T>(), sizeof(T), AlignOf<T>());
if (len > 0) {
PushBytes(reinterpret_cast<const uint8_t *>(v), sizeof(T) * len);
}
@ -841,7 +872,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 +888,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 +902,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 +923,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 +937,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 +953,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 +972,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 +1004,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 +1015,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());
@ -998,9 +1029,9 @@ class FlatBufferBuilder {
/// written to at a later time to serialize the data into a `vector`
/// in the buffer.
uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
uint8_t **buf) {
size_t alignment, uint8_t **buf) {
NotNested();
StartVector(len, elemsize);
StartVector(len, elemsize, alignment);
buf_.make_space(len * elemsize);
auto vec_start = GetSize();
auto vec_end = EndVector(len);
@ -1008,6 +1039,12 @@ class FlatBufferBuilder {
return vec_end;
}
FLATBUFFERS_ATTRIBUTE([[deprecated("call the version above instead")]])
uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
uint8_t **buf) {
return CreateUninitializedVector(len, elemsize, elemsize, buf);
}
/// @brief Specialized version of `CreateVector` for non-copying use cases.
/// Write the data any time later to the returned buffer pointer `buf`.
/// @tparam T The data type of the data that will be stored in the buffer
@ -1019,14 +1056,14 @@ class FlatBufferBuilder {
template<typename T>
Offset<Vector<T>> CreateUninitializedVector(size_t len, T **buf) {
AssertScalarT<T>();
return CreateUninitializedVector(len, sizeof(T),
return CreateUninitializedVector(len, sizeof(T), AlignOf<T>(),
reinterpret_cast<uint8_t **>(buf));
}
template<typename T>
Offset<Vector<const T *>> CreateUninitializedVectorOfStructs(size_t len,
T **buf) {
return CreateUninitializedVector(len, sizeof(T),
return CreateUninitializedVector(len, sizeof(T), AlignOf<T>(),
reinterpret_cast<uint8_t **>(buf));
}
@ -1037,7 +1074,7 @@ class FlatBufferBuilder {
Offset<Vector<T>> CreateVectorScalarCast(const U *v, size_t len) {
AssertScalarT<T>();
AssertScalarT<U>();
StartVector(len, sizeof(T));
StartVector<T>(len);
for (auto i = len; i > 0;) { PushElement(static_cast<T>(v[--i])); }
return Offset<Vector<T>>(EndVector(len));
}
@ -1074,7 +1111,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;
@ -1146,7 +1183,7 @@ class FlatBufferBuilder {
// Allocates space for a vector of structures.
// Must be completed with EndVectorOfStructs().
template<typename T> T *StartVectorOfStructs(size_t vector_size) {
StartVector(vector_size * sizeof(T) / AlignOf<T>(), AlignOf<T>());
StartVector(vector_size * sizeof(T) / AlignOf<T>(), sizeof(T), AlignOf<T>());
return reinterpret_cast<T *>(buf_.make_space(vector_size * sizeof(T)));
}

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

@ -26,22 +26,27 @@
#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)
#include <span>
#elif defined(__cpp_lib_span) && defined(__has_include)
#if __has_include(<span>)
#include <array>
#include <span>
#define FLATBUFFERS_USE_STD_SPAN
#endif
@ -128,7 +133,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 +289,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>
struct is_span_convertable {
// > 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_convertible {
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 +367,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.
@ -414,7 +415,7 @@ class span FLATBUFFERS_FINAL_CLASS {
// extent == 0 || extent == flatbuffers::dynamic_extent.
// A dummy template argument N is need dependency for SFINAE.
template<std::size_t N = 0,
typename internal::is_span_convertable<element_type, Extent, element_type, (N - N)>::type = 0>
typename internal::is_span_convertible<element_type, Extent, element_type, (N - N)>::type = 0>
FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr),
count_(0) {
static_assert(extent == 0 || extent == dynamic_extent, "invalid span");
@ -427,12 +428,12 @@ class span FLATBUFFERS_FINAL_CLASS {
// std::remove_pointer_t<decltype(std::data(arr))>(*)[]
// is convertible to element_type (*)[].
template<std::size_t N,
typename internal::is_span_convertable<element_type, Extent, element_type, N>::type = 0>
typename internal::is_span_convertible<element_type, Extent, element_type, N>::type = 0>
FLATBUFFERS_CONSTEXPR_CPP11 span(element_type (&arr)[N]) FLATBUFFERS_NOEXCEPT
: data_(arr), count_(N) {}
template<class U, std::size_t N,
typename internal::is_span_convertable<element_type, Extent, U, N>::type = 0>
typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0>
FLATBUFFERS_CONSTEXPR_CPP11 span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
: data_(arr.data()), count_(N) {}
@ -442,7 +443,7 @@ class span FLATBUFFERS_FINAL_CLASS {
// : data_(arr.data()), count_(N) {}
template<class U, std::size_t N,
typename internal::is_span_convertable<element_type, Extent, U, N>::type = 0>
typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0>
FLATBUFFERS_CONSTEXPR_CPP11 span(const std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT
: data_(arr.data()), count_(N) {}
@ -452,7 +453,7 @@ class span FLATBUFFERS_FINAL_CLASS {
// if extent == std::dynamic_extent || N == extent is true and U (*)[]
// is convertible to element_type (*)[].
template<class U, std::size_t N,
typename internal::is_span_convertable<element_type, Extent, U, N>::type = 0>
typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0>
FLATBUFFERS_CONSTEXPR_CPP11 span(const flatbuffers::span<U, N> &s) FLATBUFFERS_NOEXCEPT
: span(s.data(), s.size()) {
}
@ -462,45 +463,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,19 +17,20 @@
#ifndef FLATBUFFERS_UTIL_H_
#define FLATBUFFERS_UTIL_H_
#include <ctype.h>
#include <errno.h>
#include "flatbuffers/base.h"
#include "flatbuffers/stl_emulation.h"
#ifndef FLATBUFFERS_PREFER_PRINTF
# include <iomanip>
# include <sstream>
#else // FLATBUFFERS_PREFER_PRINTF
# include <float.h>
# include <stdio.h>
#endif // FLATBUFFERS_PREFER_PRINTF
#include <iomanip>
#include <string>
namespace flatbuffers {
@ -94,7 +95,7 @@ template<typename T> size_t IntToDigitCount(T t) {
// Count a single 0 left of the dot for fractional numbers
if (-1 < t && t < 1) digit_count++;
// Count digits until fractional part
T eps = std::numeric_limits<float>::epsilon();
T eps = std::numeric_limits<T>::epsilon();
while (t <= (-1 + eps) || (1 - eps) <= t) {
t /= 10;
digit_count++;
@ -254,7 +255,7 @@ inline void strtoval_impl(double *val, const char *str, char **endptr) {
}
// UBSAN: double to float is safe if numeric_limits<float>::is_iec559 is true.
__supress_ubsan__("float-cast-overflow")
__suppress_ubsan__("float-cast-overflow")
inline void strtoval_impl(float *val, const char *str, char **endptr) {
*val = __strtof_impl(str, endptr);
}
@ -447,6 +448,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,
@ -681,8 +685,31 @@ bool SetGlobalTestLocale(const char *locale_name,
bool ReadEnvironmentVariable(const char *var_name,
std::string *_value = nullptr);
// 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

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

@ -24,7 +24,7 @@
namespace flatbuffers {
// This is a minimal replication of std::vector<uint8_t> functionality,
// except growing from higher to lower addresses. i.e push_back() inserts data
// except growing from higher to lower addresses. i.e. push_back() inserts data
// in the lowest address in the vector.
// Since this vector leaves the lower part unused, we support a "scratch-pad"
// that can be stored there for temporary data, to share the allocated space.

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,21 +25,37 @@ 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)
: 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) {
struct Options {
// The maximum nesting of tables and vectors before we call it invalid.
uoffset_t max_depth = 64;
// The maximum number of tables we will verify before we call it invalid.
uoffset_t max_tables = 1000000;
// If true, verify all data is aligned.
bool check_alignment = true;
// If true, run verifier on nested flatbuffers
bool check_nested_flatbuffers = true;
};
explicit Verifier(const uint8_t *const buf, const size_t buf_len,
const Options &opts)
: buf_(buf), size_(buf_len), opts_(opts) {
FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
}
// Deprecated API, please construct with Verifier::Options.
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)
: Verifier(buf, buf_len, [&] {
Options opts;
opts.max_depth = max_depth;
opts.max_tables = max_tables;
opts.check_alignment = check_alignment;
return opts;
}()) {}
// 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);
@ -54,7 +69,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;
@ -65,48 +80,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 || !opts_.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) &&
@ -115,24 +134,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;
// Check the whole array. If this is a string, the byte past the array must
// be 0.
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;
@ -142,7 +161,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;
@ -151,30 +171,41 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
return true;
}
__supress_ubsan__("unsigned-integer-overflow") bool VerifyTableStart(
const uint8_t *table) {
__suppress_ubsan__("unsigned-integer-overflow") bool VerifyTableStart(
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()
@ -184,9 +215,17 @@ 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) {
// Caller opted out of this.
if (!opts_.check_nested_flatbuffers) return true;
// 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);
}
@ -194,19 +233,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.
@ -217,18 +257,18 @@ 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);
}
// Called at the start of a table to increase counters measuring data
// structure depth and amount, and possibly bails out with false if
// limits set by the constructor have been hit. Needs to be balanced
// with EndTable().
// structure depth and amount, and possibly bails out with false if limits set
// by the constructor have been hit. Needs to be balanced with EndTable().
bool VerifyComplexity() {
depth_++;
num_tables_++;
return Check(depth_ <= max_depth_ && num_tables_ <= max_tables_);
return Check(depth_ <= opts_.max_depth && num_tables_ <= opts_.max_tables);
}
// Called at the end of a table to pop the depth count.
@ -254,15 +294,22 @@ class Verifier FLATBUFFERS_FINAL_CLASS {
// clang-format on
}
std::vector<uint8_t> *GetFlexReuseTracker() { return flex_reuse_tracker_; }
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_;
mutable size_t upper_bound_;
bool check_alignment_;
const size_t size_;
const Options opts_;
mutable size_t upper_bound_ = 0;
uoffset_t depth_ = 0;
uoffset_t num_tables_ = 0;
std::vector<uint8_t> *flex_reuse_tracker_ = nullptr;
};
} // namespace flatbuffers

View File

@ -6,6 +6,13 @@
#include "flatbuffers/flatbuffers.h"
// Ensure the included flatbuffers.h is the same version as when this file was
// generated, otherwise it may not be compatible.
static_assert(FLATBUFFERS_VERSION_MAJOR == 22 &&
FLATBUFFERS_VERSION_MINOR == 9 &&
FLATBUFFERS_VERSION_REVISION == 29,
"Non-compatible flatbuffers version included");
#include "header_generated.h"
namespace FlatGeobuf {
@ -66,7 +73,7 @@ struct Geometry FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
verifier.VerifyVector(t()) &&
VerifyOffset(verifier, VT_TM) &&
verifier.VerifyVector(tm()) &&
VerifyField<uint8_t>(verifier, VT_TYPE) &&
VerifyField<uint8_t>(verifier, VT_TYPE, 1) &&
VerifyOffset(verifier, VT_PARTS) &&
verifier.VerifyVector(parts()) &&
verifier.VerifyVectorOfTables(parts()) &&
@ -121,7 +128,7 @@ inline flatbuffers::Offset<Geometry> CreateGeometry(
flatbuffers::Offset<flatbuffers::Vector<double>> m = 0,
flatbuffers::Offset<flatbuffers::Vector<double>> t = 0,
flatbuffers::Offset<flatbuffers::Vector<uint64_t>> tm = 0,
FlatGeobuf::GeometryType type = FlatGeobuf::GeometryType::Unknown,
FlatGeobuf::GeometryType type = FlatGeobuf::GeometryType_Unknown,
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<FlatGeobuf::Geometry>>> parts = 0) {
GeometryBuilder builder_(_fbb);
builder_.add_parts(parts);
@ -143,7 +150,7 @@ inline flatbuffers::Offset<Geometry> CreateGeometryDirect(
const std::vector<double> *m = nullptr,
const std::vector<double> *t = nullptr,
const std::vector<uint64_t> *tm = nullptr,
FlatGeobuf::GeometryType type = FlatGeobuf::GeometryType::Unknown,
FlatGeobuf::GeometryType type = FlatGeobuf::GeometryType_Unknown,
const std::vector<flatbuffers::Offset<FlatGeobuf::Geometry>> *parts = nullptr) {
auto ends__ = ends ? _fbb.CreateVector<uint32_t>(*ends) : 0;
auto xy__ = xy ? _fbb.CreateVector<double>(*xy) : 0;

View File

@ -6,6 +6,13 @@
#include "flatbuffers/flatbuffers.h"
// Ensure the included flatbuffers.h is the same version as when this file was
// generated, otherwise it may not be compatible.
static_assert(FLATBUFFERS_VERSION_MAJOR == 22 &&
FLATBUFFERS_VERSION_MINOR == 9 &&
FLATBUFFERS_VERSION_REVISION == 29,
"Non-compatible flatbuffers version included");
namespace FlatGeobuf {
struct Column;
@ -17,49 +24,49 @@ struct CrsBuilder;
struct Header;
struct HeaderBuilder;
enum class GeometryType : uint8_t {
Unknown = 0,
Point = 1,
LineString = 2,
Polygon = 3,
MultiPoint = 4,
MultiLineString = 5,
MultiPolygon = 6,
GeometryCollection = 7,
CircularString = 8,
CompoundCurve = 9,
CurvePolygon = 10,
MultiCurve = 11,
MultiSurface = 12,
Curve = 13,
Surface = 14,
PolyhedralSurface = 15,
TIN = 16,
Triangle = 17,
MIN = Unknown,
MAX = Triangle
enum GeometryType : uint8_t {
GeometryType_Unknown = 0,
GeometryType_Point = 1,
GeometryType_LineString = 2,
GeometryType_Polygon = 3,
GeometryType_MultiPoint = 4,
GeometryType_MultiLineString = 5,
GeometryType_MultiPolygon = 6,
GeometryType_GeometryCollection = 7,
GeometryType_CircularString = 8,
GeometryType_CompoundCurve = 9,
GeometryType_CurvePolygon = 10,
GeometryType_MultiCurve = 11,
GeometryType_MultiSurface = 12,
GeometryType_Curve = 13,
GeometryType_Surface = 14,
GeometryType_PolyhedralSurface = 15,
GeometryType_TIN = 16,
GeometryType_Triangle = 17,
GeometryType_MIN = GeometryType_Unknown,
GeometryType_MAX = GeometryType_Triangle
};
inline const GeometryType (&EnumValuesGeometryType())[18] {
static const GeometryType values[] = {
GeometryType::Unknown,
GeometryType::Point,
GeometryType::LineString,
GeometryType::Polygon,
GeometryType::MultiPoint,
GeometryType::MultiLineString,
GeometryType::MultiPolygon,
GeometryType::GeometryCollection,
GeometryType::CircularString,
GeometryType::CompoundCurve,
GeometryType::CurvePolygon,
GeometryType::MultiCurve,
GeometryType::MultiSurface,
GeometryType::Curve,
GeometryType::Surface,
GeometryType::PolyhedralSurface,
GeometryType::TIN,
GeometryType::Triangle
GeometryType_Unknown,
GeometryType_Point,
GeometryType_LineString,
GeometryType_Polygon,
GeometryType_MultiPoint,
GeometryType_MultiLineString,
GeometryType_MultiPolygon,
GeometryType_GeometryCollection,
GeometryType_CircularString,
GeometryType_CompoundCurve,
GeometryType_CurvePolygon,
GeometryType_MultiCurve,
GeometryType_MultiSurface,
GeometryType_Curve,
GeometryType_Surface,
GeometryType_PolyhedralSurface,
GeometryType_TIN,
GeometryType_Triangle
};
return values;
}
@ -90,48 +97,48 @@ inline const char * const *EnumNamesGeometryType() {
}
inline const char *EnumNameGeometryType(GeometryType e) {
if (flatbuffers::IsOutRange(e, GeometryType::Unknown, GeometryType::Triangle)) return "";
if (flatbuffers::IsOutRange(e, GeometryType_Unknown, GeometryType_Triangle)) return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesGeometryType()[index];
}
enum class ColumnType : uint8_t {
Byte = 0,
UByte = 1,
Bool = 2,
Short = 3,
UShort = 4,
Int = 5,
UInt = 6,
Long = 7,
ULong = 8,
Float = 9,
Double = 10,
String = 11,
Json = 12,
DateTime = 13,
Binary = 14,
MIN = Byte,
MAX = Binary
enum ColumnType : uint8_t {
ColumnType_Byte = 0,
ColumnType_UByte = 1,
ColumnType_Bool = 2,
ColumnType_Short = 3,
ColumnType_UShort = 4,
ColumnType_Int = 5,
ColumnType_UInt = 6,
ColumnType_Long = 7,
ColumnType_ULong = 8,
ColumnType_Float = 9,
ColumnType_Double = 10,
ColumnType_String = 11,
ColumnType_Json = 12,
ColumnType_DateTime = 13,
ColumnType_Binary = 14,
ColumnType_MIN = ColumnType_Byte,
ColumnType_MAX = ColumnType_Binary
};
inline const ColumnType (&EnumValuesColumnType())[15] {
static const ColumnType values[] = {
ColumnType::Byte,
ColumnType::UByte,
ColumnType::Bool,
ColumnType::Short,
ColumnType::UShort,
ColumnType::Int,
ColumnType::UInt,
ColumnType::Long,
ColumnType::ULong,
ColumnType::Float,
ColumnType::Double,
ColumnType::String,
ColumnType::Json,
ColumnType::DateTime,
ColumnType::Binary
ColumnType_Byte,
ColumnType_UByte,
ColumnType_Bool,
ColumnType_Short,
ColumnType_UShort,
ColumnType_Int,
ColumnType_UInt,
ColumnType_Long,
ColumnType_ULong,
ColumnType_Float,
ColumnType_Double,
ColumnType_String,
ColumnType_Json,
ColumnType_DateTime,
ColumnType_Binary
};
return values;
}
@ -159,7 +166,7 @@ inline const char * const *EnumNamesColumnType() {
}
inline const char *EnumNameColumnType(ColumnType e) {
if (flatbuffers::IsOutRange(e, ColumnType::Byte, ColumnType::Binary)) return "";
if (flatbuffers::IsOutRange(e, ColumnType_Byte, ColumnType_Binary)) return "";
const size_t index = static_cast<size_t>(e);
return EnumNamesColumnType()[index];
}
@ -216,17 +223,17 @@ struct Column FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
return VerifyTableStart(verifier) &&
VerifyOffsetRequired(verifier, VT_NAME) &&
verifier.VerifyString(name()) &&
VerifyField<uint8_t>(verifier, VT_TYPE) &&
VerifyField<uint8_t>(verifier, VT_TYPE, 1) &&
VerifyOffset(verifier, VT_TITLE) &&
verifier.VerifyString(title()) &&
VerifyOffset(verifier, VT_DESCRIPTION) &&
verifier.VerifyString(description()) &&
VerifyField<int32_t>(verifier, VT_WIDTH) &&
VerifyField<int32_t>(verifier, VT_PRECISION) &&
VerifyField<int32_t>(verifier, VT_SCALE) &&
VerifyField<uint8_t>(verifier, VT_NULLABLE) &&
VerifyField<uint8_t>(verifier, VT_UNIQUE) &&
VerifyField<uint8_t>(verifier, VT_PRIMARY_KEY) &&
VerifyField<int32_t>(verifier, VT_WIDTH, 4) &&
VerifyField<int32_t>(verifier, VT_PRECISION, 4) &&
VerifyField<int32_t>(verifier, VT_SCALE, 4) &&
VerifyField<uint8_t>(verifier, VT_NULLABLE, 1) &&
VerifyField<uint8_t>(verifier, VT_UNIQUE, 1) &&
VerifyField<uint8_t>(verifier, VT_PRIMARY_KEY, 1) &&
VerifyOffset(verifier, VT_METADATA) &&
verifier.VerifyString(metadata()) &&
verifier.EndTable();
@ -285,7 +292,7 @@ struct ColumnBuilder {
inline flatbuffers::Offset<Column> CreateColumn(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::String> name = 0,
FlatGeobuf::ColumnType type = FlatGeobuf::ColumnType::Byte,
FlatGeobuf::ColumnType type = FlatGeobuf::ColumnType_Byte,
flatbuffers::Offset<flatbuffers::String> title = 0,
flatbuffers::Offset<flatbuffers::String> description = 0,
int32_t width = -1,
@ -313,7 +320,7 @@ inline flatbuffers::Offset<Column> CreateColumn(
inline flatbuffers::Offset<Column> CreateColumnDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const char *name = nullptr,
FlatGeobuf::ColumnType type = FlatGeobuf::ColumnType::Byte,
FlatGeobuf::ColumnType type = FlatGeobuf::ColumnType_Byte,
const char *title = nullptr,
const char *description = nullptr,
int32_t width = -1,
@ -374,7 +381,7 @@ struct Crs FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
return VerifyTableStart(verifier) &&
VerifyOffset(verifier, VT_ORG) &&
verifier.VerifyString(org()) &&
VerifyField<int32_t>(verifier, VT_CODE) &&
VerifyField<int32_t>(verifier, VT_CODE, 4) &&
VerifyOffset(verifier, VT_NAME) &&
verifier.VerifyString(name()) &&
VerifyOffset(verifier, VT_DESCRIPTION) &&
@ -527,16 +534,16 @@ struct Header FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
verifier.VerifyString(name()) &&
VerifyOffset(verifier, VT_ENVELOPE) &&
verifier.VerifyVector(envelope()) &&
VerifyField<uint8_t>(verifier, VT_GEOMETRY_TYPE) &&
VerifyField<uint8_t>(verifier, VT_HAS_Z) &&
VerifyField<uint8_t>(verifier, VT_HAS_M) &&
VerifyField<uint8_t>(verifier, VT_HAS_T) &&
VerifyField<uint8_t>(verifier, VT_HAS_TM) &&
VerifyField<uint8_t>(verifier, VT_GEOMETRY_TYPE, 1) &&
VerifyField<uint8_t>(verifier, VT_HAS_Z, 1) &&
VerifyField<uint8_t>(verifier, VT_HAS_M, 1) &&
VerifyField<uint8_t>(verifier, VT_HAS_T, 1) &&
VerifyField<uint8_t>(verifier, VT_HAS_TM, 1) &&
VerifyOffset(verifier, VT_COLUMNS) &&
verifier.VerifyVector(columns()) &&
verifier.VerifyVectorOfTables(columns()) &&
VerifyField<uint64_t>(verifier, VT_FEATURES_COUNT) &&
VerifyField<uint16_t>(verifier, VT_INDEX_NODE_SIZE) &&
VerifyField<uint64_t>(verifier, VT_FEATURES_COUNT, 8) &&
VerifyField<uint16_t>(verifier, VT_INDEX_NODE_SIZE, 2) &&
VerifyOffset(verifier, VT_CRS) &&
verifier.VerifyTable(crs()) &&
VerifyOffset(verifier, VT_TITLE) &&
@ -610,7 +617,7 @@ inline flatbuffers::Offset<Header> CreateHeader(
flatbuffers::FlatBufferBuilder &_fbb,
flatbuffers::Offset<flatbuffers::String> name = 0,
flatbuffers::Offset<flatbuffers::Vector<double>> envelope = 0,
FlatGeobuf::GeometryType geometry_type = FlatGeobuf::GeometryType::Unknown,
FlatGeobuf::GeometryType geometry_type = FlatGeobuf::GeometryType_Unknown,
bool has_z = false,
bool has_m = false,
bool has_t = false,
@ -644,7 +651,7 @@ inline flatbuffers::Offset<Header> CreateHeaderDirect(
flatbuffers::FlatBufferBuilder &_fbb,
const char *name = nullptr,
const std::vector<double> *envelope = nullptr,
FlatGeobuf::GeometryType geometry_type = FlatGeobuf::GeometryType::Unknown,
FlatGeobuf::GeometryType geometry_type = FlatGeobuf::GeometryType_Unknown,
bool has_z = false,
bool has_m = false,
bool has_t = false,