From c2214631f244807a7ec3ab62f5841582f5d767e8 Mon Sep 17 00:00:00 2001 From: James Chevalier Date: Thu, 3 Nov 2022 17:24:02 -0400 Subject: [PATCH] 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 --- flatbuffers/base.h | 44 ++++--- flatbuffers/buffer.h | 2 +- flatbuffers/flatbuffer_builder.h | 111 ++++++++++++------ flatbuffers/flatbuffers.h | 24 +--- flatbuffers/stl_emulation.h | 89 +++++++------- flatbuffers/table.h | 12 +- flatbuffers/util.h | 37 +++++- flatbuffers/vector.h | 19 +++ flatbuffers/vector_downward.h | 2 +- flatbuffers/verifier.h | 181 ++++++++++++++++++----------- flatgeobuf/feature_generated.h | 13 ++- flatgeobuf/header_generated.h | 193 ++++++++++++++++--------------- 12 files changed, 436 insertions(+), 291 deletions(-) diff --git a/flatbuffers/base.h b/flatbuffers/base.h index a5ac10d..607d3b2 100644 --- a/flatbuffers/base.h +++ b/flatbuffers/base.h @@ -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 T EndianScalar(T t) { template // 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(p)); } @@ -415,13 +427,13 @@ T ReadScalar(const void *p) { template // 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(p) = EndianScalar(t); } template struct Offset; -template __supress_ubsan__("alignment") void WriteScalar(void *p, Offset t) { +template __suppress_ubsan__("alignment") void WriteScalar(void *p, Offset t) { *reinterpret_cast(p) = EndianScalar(t.o); } @@ -432,7 +444,7 @@ template __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); } diff --git a/flatbuffers/buffer.h b/flatbuffers/buffer.h index e8d2ce9..ca005f7 100644 --- a/flatbuffers/buffer.h +++ b/flatbuffers/buffer.h @@ -95,7 +95,7 @@ template struct IndirectHelper { } }; -/// @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'. diff --git a/flatbuffers/flatbuffer_builder.h b/flatbuffers/flatbuffer_builder.h index 8be4efb..66c33ff 100644 --- a/flatbuffers/flatbuffer_builder.h +++ b/flatbuffers/flatbuffer_builder.h @@ -18,6 +18,7 @@ #define FLATBUFFERS_FLATBUFFER_BUILDER_H_ #include +#include #include "flatbuffers/allocator.h" #include "flatbuffers/array.h" @@ -42,14 +43,15 @@ inline voffset_t FieldIndexToOffset(voffset_t field_id) { return static_cast((field_id + fixed_fields) * sizeof(voffset_t)); } -template +template> const T *data(const std::vector &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(&t) : &v.front(); } -template T *data(std::vector &v) { +template> +T *data(std::vector &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(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 void PreAlign(size_t len) { AssertScalarT(); - PreAlign(len, sizeof(T)); + PreAlign(len, AlignOf()); } /// @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 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(len)); } - void StartVector(size_t len, size_t elemsize) { + void StartVector(size_t len, size_t elemsize, size_t alignment) { NotNested(); nested = true; PreAlign(len * elemsize); - PreAlign(len * elemsize, elemsize); // Just in case elemsize > uoffset_t. + PreAlign(len * elemsize, alignment); // Just in case elemsize > uoffset_t. + } + + template void StartVector(size_t len) { + return StartVector(len, sizeof(T), AlignOf()); } // 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(); - StartVector(len, sizeof(T)); + StartVector(len); if (len == 0) { return Offset>(EndVector(len)); } // clang-format off #if FLATBUFFERS_LITTLEENDIAN @@ -642,9 +649,30 @@ class FlatBufferBuilder { return Offset>(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 Offset> 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 + Offset> CreateVector(std::initializer_list v) { + return CreateVector(v.begin(), v.size()); + } + template Offset>> CreateVector(const Offset *v, size_t len) { - StartVector(len, sizeof(Offset)); + StartVector>(len); for (auto i = len; i > 0;) { PushElement(v[--i]); } return Offset>>(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 + template> Offset> CreateVector(const std::vector &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> CreateVector(const std::vector &v) { - StartVector(v.size(), sizeof(uint8_t)); + StartVector(v.size()); for (auto i = v.size(); i > 0;) { PushElement(static_cast(v[--i])); } @@ -706,21 +734,24 @@ class FlatBufferBuilder { return CreateVector(elems); } - /// @brief Serialize a `std::vector` into a FlatBuffer `vector`. + /// @brief Serialize a `std::vector` 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 + template> Offset>> CreateVectorOfStrings( - const std::vector &v) { + const std::vector &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); // 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)); + StartVector>(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 Offset> CreateVectorOfStructs(const T *v, size_t len) { - StartVector(len * sizeof(T) / AlignOf(), AlignOf()); + StartVector(len * sizeof(T) / AlignOf(), sizeof(T), AlignOf()); if (len > 0) { PushBytes(reinterpret_cast(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 + template> Offset> CreateVectorOfStructs( const std::vector &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 + template> Offset> CreateVectorOfNativeStructs( const std::vector &v, T (*const pack_func)(const S &)) { return CreateVectorOfNativeStructs(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 + template> Offset> CreateVectorOfNativeStructs( const std::vector &v) { return CreateVectorOfNativeStructs(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 + template> Offset> CreateVectorOfSortedStructs( std::vector *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 + template> Offset> CreateVectorOfSortedNativeStructs( std::vector *v) { return CreateVectorOfSortedNativeStructs(data(*v), v->size()); @@ -922,7 +953,7 @@ class FlatBufferBuilder { /// where the vector is stored. template Offset> CreateVectorOfSortedStructs(T *v, size_t len) { - std::sort(v, v + len, StructKeyComparator()); + std::stable_sort(v, v + len, StructKeyComparator()); return CreateVectorOfStructs(v, len); } @@ -941,7 +972,7 @@ class FlatBufferBuilder { extern T Pack(const S &); auto structs = StartVectorOfStructs(len); for (size_t i = 0; i < len; i++) { structs[i] = Pack(v[i]); } - std::sort(structs, structs + len, StructKeyComparator()); + std::stable_sort(structs, structs + len, StructKeyComparator()); return EndVectorOfStructs(len); } @@ -973,7 +1004,7 @@ class FlatBufferBuilder { template Offset>> CreateVectorOfSortedTables(Offset *v, size_t len) { - std::sort(v, v + len, TableKeyComparator(buf_)); + std::stable_sort(v, v + len, TableKeyComparator(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 + template> Offset>> CreateVectorOfSortedTables( std::vector, 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 Offset> CreateUninitializedVector(size_t len, T **buf) { AssertScalarT(); - return CreateUninitializedVector(len, sizeof(T), + return CreateUninitializedVector(len, sizeof(T), AlignOf(), reinterpret_cast(buf)); } template Offset> CreateUninitializedVectorOfStructs(size_t len, T **buf) { - return CreateUninitializedVector(len, sizeof(T), + return CreateUninitializedVector(len, sizeof(T), AlignOf(), reinterpret_cast(buf)); } @@ -1037,7 +1074,7 @@ class FlatBufferBuilder { Offset> CreateVectorScalarCast(const U *v, size_t len) { AssertScalarT(); AssertScalarT(); - StartVector(len, sizeof(T)); + StartVector(len); for (auto i = len; i > 0;) { PushElement(static_cast(v[--i])); } return Offset>(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 T *StartVectorOfStructs(size_t vector_size) { - StartVector(vector_size * sizeof(T) / AlignOf(), AlignOf()); + StartVector(vector_size * sizeof(T) / AlignOf(), sizeof(T), AlignOf()); return reinterpret_cast(buf_.make_space(vector_size * sizeof(T))); } diff --git a/flatbuffers/flatbuffers.h b/flatbuffers/flatbuffers.h index c903d64..6421788 100644 --- a/flatbuffers/flatbuffers.h +++ b/flatbuffers/flatbuffers.h @@ -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));\ diff --git a/flatbuffers/stl_emulation.h b/flatbuffers/stl_emulation.h index 75d13b2..452ddb8 100644 --- a/flatbuffers/stl_emulation.h +++ b/flatbuffers/stl_emulation.h @@ -26,22 +26,27 @@ #include #include -// 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 - #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 #elif defined(__cpp_lib_span) && defined(__has_include) #if __has_include() + #include #include #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 using Optional = std::optional; using nullopt_t = std::nullopt_t; @@ -284,13 +289,13 @@ FLATBUFFERS_CONSTEXPR std::size_t dynamic_extent = static_cast(-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 - 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 + struct is_span_convertible { using type = - typename std::conditional::value + typename std::conditional::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; - using ConstIterator = internal::SpanIterator; 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::type = 0> + typename internal::is_span_convertible::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(*)[] // is convertible to element_type (*)[]. template::type = 0> + typename internal::is_span_convertible::type = 0> FLATBUFFERS_CONSTEXPR_CPP11 span(element_type (&arr)[N]) FLATBUFFERS_NOEXCEPT : data_(arr), count_(N) {} template::type = 0> + typename internal::is_span_convertible::type = 0> FLATBUFFERS_CONSTEXPR_CPP11 span(std::array &arr) FLATBUFFERS_NOEXCEPT : data_(arr.data()), count_(N) {} @@ -442,7 +443,7 @@ class span FLATBUFFERS_FINAL_CLASS { // : data_(arr.data()), count_(N) {} template::type = 0> + typename internal::is_span_convertible::type = 0> FLATBUFFERS_CONSTEXPR_CPP11 span(const std::array &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::type = 0> + typename internal::is_span_convertible::type = 0> FLATBUFFERS_CONSTEXPR_CPP11 span(const flatbuffers::span &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 +template FLATBUFFERS_CONSTEXPR_CPP11 -flatbuffers::span make_span(U(&arr)[N]) FLATBUFFERS_NOEXCEPT { - return span(arr); +flatbuffers::span make_span(ElementType(&arr)[Extent]) FLATBUFFERS_NOEXCEPT { + return span(arr); } -template +template FLATBUFFERS_CONSTEXPR_CPP11 -flatbuffers::span make_span(const U(&arr)[N]) FLATBUFFERS_NOEXCEPT { - return span(arr); +flatbuffers::span make_span(const ElementType(&arr)[Extent]) FLATBUFFERS_NOEXCEPT { + return span(arr); } -template +template FLATBUFFERS_CONSTEXPR_CPP11 -flatbuffers::span make_span(std::array &arr) FLATBUFFERS_NOEXCEPT { - return span(arr); +flatbuffers::span make_span(std::array &arr) FLATBUFFERS_NOEXCEPT { + return span(arr); } -template +template FLATBUFFERS_CONSTEXPR_CPP11 -flatbuffers::span make_span(const std::array &arr) FLATBUFFERS_NOEXCEPT { - return span(arr); +flatbuffers::span make_span(const std::array &arr) FLATBUFFERS_NOEXCEPT { + return span(arr); } -template +template FLATBUFFERS_CONSTEXPR_CPP11 -flatbuffers::span make_span(U *first, std::size_t count) FLATBUFFERS_NOEXCEPT { - return span(first, count); +flatbuffers::span make_span(ElementType *first, std::size_t count) FLATBUFFERS_NOEXCEPT { + return span(first, count); } -template +template FLATBUFFERS_CONSTEXPR_CPP11 -flatbuffers::span make_span(const U *first, std::size_t count) FLATBUFFERS_NOEXCEPT { - return span(first, count); +flatbuffers::span make_span(const ElementType *first, std::size_t count) FLATBUFFERS_NOEXCEPT { + return span(first, count); } #endif // !defined(FLATBUFFERS_SPAN_MINIMAL) diff --git a/flatbuffers/table.h b/flatbuffers/table.h index 4247069..11b2924 100644 --- a/flatbuffers/table.h +++ b/flatbuffers/table.h @@ -112,20 +112,22 @@ class Table { // Verify a particular field. template - 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(data_, field_offset); + return !field_offset || verifier.VerifyField(data_, field_offset, align); } // VerifyField for required fields. template - 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(data_, field_offset); + verifier.VerifyField(data_, field_offset, align); } // Versions for offsets. @@ -163,4 +165,4 @@ inline flatbuffers::Optional Table::GetOptional( } // namespace flatbuffers -#endif // FLATBUFFERS_TABLE_H_ \ No newline at end of file +#endif // FLATBUFFERS_TABLE_H_ diff --git a/flatbuffers/util.h b/flatbuffers/util.h index 020a060..73a3ab7 100644 --- a/flatbuffers/util.h +++ b/flatbuffers/util.h @@ -17,19 +17,20 @@ #ifndef FLATBUFFERS_UTIL_H_ #define FLATBUFFERS_UTIL_H_ +#include #include #include "flatbuffers/base.h" #include "flatbuffers/stl_emulation.h" #ifndef FLATBUFFERS_PREFER_PRINTF +# include # include #else // FLATBUFFERS_PREFER_PRINTF # include # include #endif // FLATBUFFERS_PREFER_PRINTF -#include #include namespace flatbuffers { @@ -94,7 +95,7 @@ template 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::epsilon(); + T eps = std::numeric_limits::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::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 diff --git a/flatbuffers/vector.h b/flatbuffers/vector.h index f8a5d88..6bcdfe2 100644 --- a/flatbuffers/vector.h +++ b/flatbuffers/vector.h @@ -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 make_bytes_span( return span(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 +FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_span(Vector *ptr) + FLATBUFFERS_NOEXCEPT { + static_assert(Vector::is_span_observable, + "wrong type U, only LE-scalar, or byte types are allowed"); + return ptr ? make_span(*ptr) : span(); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 flatbuffers::span make_span( + const Vector *ptr) FLATBUFFERS_NOEXCEPT { + static_assert(Vector::is_span_observable, + "wrong type U, only LE-scalar, or byte types are allowed"); + return ptr ? make_span(*ptr) : span(); +} + // 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 { diff --git a/flatbuffers/vector_downward.h b/flatbuffers/vector_downward.h index 3391391..d25e544 100644 --- a/flatbuffers/vector_downward.h +++ b/flatbuffers/vector_downward.h @@ -24,7 +24,7 @@ namespace flatbuffers { // This is a minimal replication of std::vector 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. diff --git a/flatbuffers/verifier.h b/flatbuffers/verifier.h index b6971c1..87d3f54 100644 --- a/flatbuffers/verifier.h +++ b/flatbuffers/verifier.h @@ -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 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 bool Verify(size_t elem) const { - return VerifyAlignment(elem) && Verify(elem, sizeof(T)); + template 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(p - buf_); - return Verify(o, len); + bool VerifyFromPointer(const uint8_t *const p, const size_t len) { + return Verify(static_cast(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(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(base - buf_) + elem_off; + return VerifyAlignment(f, align) && Verify(f, elem_len); } template - bool Verify(const uint8_t *base, voffset_t elem_off) const { - return Verify(static_cast(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(base - buf_) + elem_off; + return VerifyAlignment(f, align) && Verify(f, sizeof(T)); } // Verify a pointer (may be NULL) of a table type. - template bool VerifyTable(const T *table) { + template bool VerifyTable(const T *const table) { return !table || table->Verify(*this); } // Verify a pointer (may be NULL) of any vector type. - template bool VerifyVector(const Vector *vec) const { + template bool VerifyVector(const Vector *const vec) const { return !vec || VerifyVectorOrString(reinterpret_cast(vec), sizeof(T)); } // Verify a pointer (may be NULL) of a vector to struct. - template bool VerifyVector(const Vector *vec) const { + template + bool VerifyVector(const Vector *const vec) const { return VerifyVector(reinterpret_cast *>(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(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(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(vec - buf_); // Check we can read the size field. if (!Verify(veco)) return false; - // Check the whole array. If this is a string, the byte past the array - // must be 0. - auto size = ReadScalar(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(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> *vec) const { + bool VerifyVectorOfStrings(const Vector> *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 bool VerifyVectorOfTables(const Vector> *vec) { + template + bool VerifyVectorOfTables(const Vector> *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(table - buf_); + const auto tableo = static_cast(table - buf_); if (!Verify(tableo)) return false; // This offset may be signed, but doing the subtraction unsigned always // gives the result we want. - auto vtableo = tableo - static_cast(ReadScalar(table)); + const auto vtableo = + tableo - static_cast(ReadScalar(table)); // Check the vtable size field, then check vtable fits in its entirety. - return VerifyComplexity() && Verify(vtableo) && - VerifyAlignment(ReadScalar(buf_ + vtableo)) && - Verify(vtableo, ReadScalar(buf_ + vtableo)); + if (!(VerifyComplexity() && Verify(vtableo) && + VerifyAlignment(ReadScalar(buf_ + vtableo), + sizeof(voffset_t)))) + return false; + const auto vsize = ReadScalar(buf_ + vtableo); + return Check((vsize & 1) == 0) && Verify(vtableo, vsize); } template - 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(buf_ + start + o)->Verify(*this) + const auto o = VerifyOffset(start); + return Check(o != 0) && + reinterpret_cast(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 - bool VerifyNestedFlatBuffer(const Vector *buf, - const char *identifier) { + bool VerifyNestedFlatBuffer(const Vector *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(identifier); } @@ -194,19 +233,20 @@ class Verifier FLATBUFFERS_FINAL_CLASS { // Verify this whole buffer, starting with root type T. template bool VerifyBuffer() { return VerifyBuffer(nullptr); } - template bool VerifyBuffer(const char *identifier) { + template bool VerifyBuffer(const char *const identifier) { return VerifyBufferFromStart(identifier, 0); } - template bool VerifySizePrefixedBuffer(const char *identifier) { + template + bool VerifySizePrefixedBuffer(const char *const identifier) { return Verify(0U) && - ReadScalar(buf_) == size_ - sizeof(uoffset_t) && + Check(ReadScalar(buf_) == size_ - sizeof(uoffset_t)) && VerifyBufferFromStart(identifier, sizeof(uoffset_t)); } - uoffset_t VerifyOffset(size_t start) const { + uoffset_t VerifyOffset(const size_t start) const { if (!Verify(start)) return 0; - auto o = ReadScalar(buf_ + start); + const auto o = ReadScalar(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(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 *GetFlexReuseTracker() { return flex_reuse_tracker_; } + + void SetFlexReuseTracker(std::vector *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 *flex_reuse_tracker_ = nullptr; }; } // namespace flatbuffers diff --git a/flatgeobuf/feature_generated.h b/flatgeobuf/feature_generated.h index 2a3dbcd..daa9712 100644 --- a/flatgeobuf/feature_generated.h +++ b/flatgeobuf/feature_generated.h @@ -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(verifier, VT_TYPE) && + VerifyField(verifier, VT_TYPE, 1) && VerifyOffset(verifier, VT_PARTS) && verifier.VerifyVector(parts()) && verifier.VerifyVectorOfTables(parts()) && @@ -121,7 +128,7 @@ inline flatbuffers::Offset CreateGeometry( flatbuffers::Offset> m = 0, flatbuffers::Offset> t = 0, flatbuffers::Offset> tm = 0, - FlatGeobuf::GeometryType type = FlatGeobuf::GeometryType::Unknown, + FlatGeobuf::GeometryType type = FlatGeobuf::GeometryType_Unknown, flatbuffers::Offset>> parts = 0) { GeometryBuilder builder_(_fbb); builder_.add_parts(parts); @@ -143,7 +150,7 @@ inline flatbuffers::Offset CreateGeometryDirect( const std::vector *m = nullptr, const std::vector *t = nullptr, const std::vector *tm = nullptr, - FlatGeobuf::GeometryType type = FlatGeobuf::GeometryType::Unknown, + FlatGeobuf::GeometryType type = FlatGeobuf::GeometryType_Unknown, const std::vector> *parts = nullptr) { auto ends__ = ends ? _fbb.CreateVector(*ends) : 0; auto xy__ = xy ? _fbb.CreateVector(*xy) : 0; diff --git a/flatgeobuf/header_generated.h b/flatgeobuf/header_generated.h index 8fc9717..8a682a5 100644 --- a/flatgeobuf/header_generated.h +++ b/flatgeobuf/header_generated.h @@ -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(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(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(verifier, VT_TYPE) && + VerifyField(verifier, VT_TYPE, 1) && VerifyOffset(verifier, VT_TITLE) && verifier.VerifyString(title()) && VerifyOffset(verifier, VT_DESCRIPTION) && verifier.VerifyString(description()) && - VerifyField(verifier, VT_WIDTH) && - VerifyField(verifier, VT_PRECISION) && - VerifyField(verifier, VT_SCALE) && - VerifyField(verifier, VT_NULLABLE) && - VerifyField(verifier, VT_UNIQUE) && - VerifyField(verifier, VT_PRIMARY_KEY) && + VerifyField(verifier, VT_WIDTH, 4) && + VerifyField(verifier, VT_PRECISION, 4) && + VerifyField(verifier, VT_SCALE, 4) && + VerifyField(verifier, VT_NULLABLE, 1) && + VerifyField(verifier, VT_UNIQUE, 1) && + VerifyField(verifier, VT_PRIMARY_KEY, 1) && VerifyOffset(verifier, VT_METADATA) && verifier.VerifyString(metadata()) && verifier.EndTable(); @@ -285,7 +292,7 @@ struct ColumnBuilder { inline flatbuffers::Offset CreateColumn( flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset name = 0, - FlatGeobuf::ColumnType type = FlatGeobuf::ColumnType::Byte, + FlatGeobuf::ColumnType type = FlatGeobuf::ColumnType_Byte, flatbuffers::Offset title = 0, flatbuffers::Offset description = 0, int32_t width = -1, @@ -313,7 +320,7 @@ inline flatbuffers::Offset CreateColumn( inline flatbuffers::Offset 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(verifier, VT_CODE) && + VerifyField(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(verifier, VT_GEOMETRY_TYPE) && - VerifyField(verifier, VT_HAS_Z) && - VerifyField(verifier, VT_HAS_M) && - VerifyField(verifier, VT_HAS_T) && - VerifyField(verifier, VT_HAS_TM) && + VerifyField(verifier, VT_GEOMETRY_TYPE, 1) && + VerifyField(verifier, VT_HAS_Z, 1) && + VerifyField(verifier, VT_HAS_M, 1) && + VerifyField(verifier, VT_HAS_T, 1) && + VerifyField(verifier, VT_HAS_TM, 1) && VerifyOffset(verifier, VT_COLUMNS) && verifier.VerifyVector(columns()) && verifier.VerifyVectorOfTables(columns()) && - VerifyField(verifier, VT_FEATURES_COUNT) && - VerifyField(verifier, VT_INDEX_NODE_SIZE) && + VerifyField(verifier, VT_FEATURES_COUNT, 8) && + VerifyField(verifier, VT_INDEX_NODE_SIZE, 2) && VerifyOffset(verifier, VT_CRS) && verifier.VerifyTable(crs()) && VerifyOffset(verifier, VT_TITLE) && @@ -610,7 +617,7 @@ inline flatbuffers::Offset
CreateHeader( flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset name = 0, flatbuffers::Offset> 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
CreateHeaderDirect( flatbuffers::FlatBufferBuilder &_fbb, const char *name = nullptr, const std::vector *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,