diff --git a/thirdparty/README.md b/thirdparty/README.md index 87802db10d..0f5822a1a9 100644 --- a/thirdparty/README.md +++ b/thirdparty/README.md @@ -56,7 +56,7 @@ ## flatbuffers - Upstream: https://github.com/google/flatbuffers -- Version: 1.12.0 +- Version: 2.0.0 - License: Apache-2.0 ## FreeType diff --git a/thirdparty/flatbuffers/base.h b/thirdparty/flatbuffers/base.h index 9557380672..cc9e22dccc 100644 --- a/thirdparty/flatbuffers/base.h +++ b/thirdparty/flatbuffers/base.h @@ -46,14 +46,17 @@ #include #include +#if defined(__unix__) && !defined(FLATBUFFERS_LOCALE_INDEPENDENT) + #include +#endif + #ifdef _STLPORT_VERSION #define FLATBUFFERS_CPP98_STL #endif -#ifndef FLATBUFFERS_CPP98_STL - #include -#endif -#include "flatbuffers/stl_emulation.h" +#ifdef __ANDROID__ + #include +#endif #if defined(__ICCARM__) #include @@ -139,8 +142,8 @@ #endif #endif // !defined(FLATBUFFERS_LITTLEENDIAN) -#define FLATBUFFERS_VERSION_MAJOR 1 -#define FLATBUFFERS_VERSION_MINOR 12 +#define FLATBUFFERS_VERSION_MAJOR 2 +#define FLATBUFFERS_VERSION_MINOR 0 #define FLATBUFFERS_VERSION_REVISION 0 #define FLATBUFFERS_STRING_EXPAND(X) #X #define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X) @@ -154,10 +157,12 @@ namespace flatbuffers { defined(__clang__) #define FLATBUFFERS_FINAL_CLASS final #define FLATBUFFERS_OVERRIDE override + #define FLATBUFFERS_EXPLICIT_CPP11 explicit #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t #else #define FLATBUFFERS_FINAL_CLASS #define FLATBUFFERS_OVERRIDE + #define FLATBUFFERS_EXPLICIT_CPP11 #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE #endif @@ -165,13 +170,16 @@ namespace flatbuffers { (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \ (defined(__cpp_constexpr) && __cpp_constexpr >= 200704) #define FLATBUFFERS_CONSTEXPR constexpr + #define FLATBUFFERS_CONSTEXPR_CPP11 constexpr + #define FLATBUFFERS_CONSTEXPR_DEFINED #else #define FLATBUFFERS_CONSTEXPR const + #define FLATBUFFERS_CONSTEXPR_CPP11 #endif #if (defined(__cplusplus) && __cplusplus >= 201402L) || \ (defined(__cpp_constexpr) && __cpp_constexpr >= 201304) - #define FLATBUFFERS_CONSTEXPR_CPP14 FLATBUFFERS_CONSTEXPR + #define FLATBUFFERS_CONSTEXPR_CPP14 FLATBUFFERS_CONSTEXPR_CPP11 #else #define FLATBUFFERS_CONSTEXPR_CPP14 #endif @@ -189,9 +197,25 @@ namespace flatbuffers { #if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \ (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404)) || \ defined(__clang__) - #define FLATBUFFERS_DELETE_FUNC(func) func = delete; + #define FLATBUFFERS_DELETE_FUNC(func) func = delete #else - #define FLATBUFFERS_DELETE_FUNC(func) private: func; + #define FLATBUFFERS_DELETE_FUNC(func) private: func +#endif + +#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \ + (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \ + defined(__clang__) + #define FLATBUFFERS_DEFAULT_DECLARATION +#endif + +// Check if we can use template aliases +// Not possible if Microsoft Compiler before 2012 +// Possible is the language feature __cpp_alias_templates is defined well +// Or possible if the C++ std is C+11 or newer +#if (defined(_MSC_VER) && _MSC_VER > 1700 /* MSVC2012 */) \ + || (defined(__cpp_alias_templates) && __cpp_alias_templates >= 200704) \ + || (defined(__cplusplus) && __cplusplus >= 201103L) + #define FLATBUFFERS_TEMPLATES_ALIASES #endif #ifndef FLATBUFFERS_HAS_STRING_VIEW @@ -236,10 +260,8 @@ namespace flatbuffers { #ifndef FLATBUFFERS_LOCALE_INDEPENDENT // Enable locale independent functions {strtof_l, strtod_l,strtoll_l, strtoull_l}. - // They are part of the POSIX-2008 but not part of the C/C++ standard. - // GCC/Clang have definition (_XOPEN_SOURCE>=700) if POSIX-2008. #if ((defined(_MSC_VER) && _MSC_VER >= 1800) || \ - (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE>=700))) + (defined(_XOPEN_VERSION) && (_XOPEN_VERSION>=700)) && (!defined(__ANDROID_API__) || (defined(__ANDROID_API__) && (__ANDROID_API__>=21)))) #define FLATBUFFERS_LOCALE_INDEPENDENT 1 #else #define FLATBUFFERS_LOCALE_INDEPENDENT 0 @@ -308,7 +330,13 @@ typedef uintmax_t largest_scalar_t; // We support aligning the contents of buffers up to this size. #define FLATBUFFERS_MAX_ALIGNMENT 16 +inline bool VerifyAlignmentRequirements(size_t align, size_t min_align = 1) { + return (min_align <= align) && (align <= (FLATBUFFERS_MAX_ALIGNMENT)) && + (align & (align - 1)) == 0; // must be power of 2 +} + #if defined(_MSC_VER) + #pragma warning(disable: 4351) // C4351: new behavior: elements of array ... will be default initialized #pragma warning(push) #pragma warning(disable: 4127) // C4127: conditional expression is constant #endif @@ -374,6 +402,13 @@ T ReadScalar(const void *p) { return EndianScalar(*reinterpret_cast(p)); } +// See https://github.com/google/flatbuffers/issues/5950 + +#if (FLATBUFFERS_GCC >= 100000) && (FLATBUFFERS_GCC < 110000) + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif + template // UBSAN: C++ aliasing type rules, see std::bit_cast<> for details. __supress_ubsan__("alignment") @@ -386,6 +421,10 @@ template __supress_ubsan__("alignment") void WriteScalar(void *p, Of *reinterpret_cast(p) = EndianScalar(t.o); } +#if (FLATBUFFERS_GCC >= 100000) && (FLATBUFFERS_GCC < 110000) + #pragma GCC diagnostic pop +#endif + // 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). diff --git a/thirdparty/flatbuffers/flatbuffers.h b/thirdparty/flatbuffers/flatbuffers.h index c4dc5bcd03..ee34d54ed4 100644 --- a/thirdparty/flatbuffers/flatbuffers.h +++ b/thirdparty/flatbuffers/flatbuffers.h @@ -18,6 +18,11 @@ #define FLATBUFFERS_H_ #include "flatbuffers/base.h" +#include "flatbuffers/stl_emulation.h" + +#ifndef FLATBUFFERS_CPP98_STL +# include +#endif #if defined(FLATBUFFERS_NAN_DEFAULTS) # include @@ -167,8 +172,12 @@ template struct VectorIterator { return (data_ - other.data_) / IndirectHelper::element_stride; } + // Note: return type is incompatible with the standard + // `reference operator*()`. IT operator*() const { return IndirectHelper::Read(data_, 0); } + // Note: return type is incompatible with the standard + // `pointer operator->()`. IT operator->() const { return IndirectHelper::Read(data_, 0); } VectorIterator &operator++() { @@ -222,12 +231,18 @@ struct VectorReverseIterator : public std::reverse_iterator { explicit VectorReverseIterator(Iterator iter) : std::reverse_iterator(iter) {} + // Note: return type is incompatible with the standard + // `reference operator*()`. typename Iterator::value_type operator*() const { - return *(std::reverse_iterator::current); + auto tmp = std::reverse_iterator::current; + return *--tmp; } + // Note: return type is incompatible with the standard + // `pointer operator->()`. typename Iterator::value_type operator->() const { - return *(std::reverse_iterator::current); + auto tmp = std::reverse_iterator::current; + return *--tmp; } }; @@ -252,6 +267,7 @@ template class Vector { typedef typename IndirectHelper::return_type return_type; typedef typename IndirectHelper::mutable_return_type mutable_return_type; + typedef return_type value_type; return_type Get(uoffset_t i) const { FLATBUFFERS_ASSERT(i < size()); @@ -289,14 +305,14 @@ template class Vector { iterator end() { return iterator(Data(), size()); } const_iterator end() const { return const_iterator(Data(), size()); } - reverse_iterator rbegin() { return reverse_iterator(end() - 1); } + reverse_iterator rbegin() { return reverse_iterator(end()); } const_reverse_iterator rbegin() const { - return const_reverse_iterator(end() - 1); + return const_reverse_iterator(end()); } - reverse_iterator rend() { return reverse_iterator(begin() - 1); } + reverse_iterator rend() { return reverse_iterator(begin()); } const_reverse_iterator rend() const { - return const_reverse_iterator(begin() - 1); + return const_reverse_iterator(begin()); } const_iterator cbegin() const { return begin(); } @@ -430,6 +446,7 @@ template class Array { IndirectHelperType; public: + typedef uint16_t size_type; typedef typename IndirectHelper::return_type return_type; typedef VectorIterator const_iterator; typedef VectorReverseIterator const_reverse_iterator; @@ -456,7 +473,9 @@ template class Array { const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } - const_reverse_iterator rend() const { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const { + return const_reverse_iterator(begin()); + } const_iterator cbegin() const { return begin(); } const_iterator cend() const { return end(); } @@ -487,6 +506,22 @@ template class Array { const T *data() const { return reinterpret_cast(Data()); } T *data() { return reinterpret_cast(Data()); } + // Copy data from a span with endian conversion. + // If this Array and the span overlap, the behavior is undefined. + void CopyFromSpan(flatbuffers::span src) { + const auto p1 = reinterpret_cast(src.data()); + const auto p2 = Data(); + FLATBUFFERS_ASSERT(!(p1 >= p2 && p1 < (p2 + length)) && + !(p2 >= p1 && p2 < (p1 + length))); + (void)p1; + (void)p2; + + CopyFromSpanImpl( + flatbuffers::integral_constant < bool, + !scalar_tag::value || sizeof(T) == 1 || FLATBUFFERS_LITTLEENDIAN > (), + src); + } + protected: void MutateImpl(flatbuffers::integral_constant, uoffset_t i, const T &val) { @@ -499,6 +534,20 @@ template class Array { *(GetMutablePointer(i)) = val; } + void CopyFromSpanImpl(flatbuffers::integral_constant, + flatbuffers::span src) { + // Use std::memcpy() instead of std::copy() to avoid preformance degradation + // due to aliasing if T is char or unsigned char. + // The size is known at compile time, so memcpy would be inlined. + std::memcpy(data(), src.data(), length * sizeof(T)); + } + + // Copy data from flatbuffers::span with endian conversion. + void CopyFromSpanImpl(flatbuffers::integral_constant, + flatbuffers::span src) { + for (size_type k = 0; k < length; k++) { Mutate(k, src[k]); } + } + // This class is only used to access pre-existing data. Don't ever // try to construct these manually. // 'constexpr' allows us to use 'size()' at compile time. @@ -544,6 +593,30 @@ template class Array, length> { uint8_t data_[1]; }; +// Cast a raw T[length] to a raw flatbuffers::Array +// without endian conversion. Use with care. +template +Array &CastToArray(T (&arr)[length]) { + return *reinterpret_cast *>(arr); +} + +template +const Array &CastToArray(const T (&arr)[length]) { + return *reinterpret_cast *>(arr); +} + +template +Array &CastToArrayOfEnum(T (&arr)[length]) { + static_assert(sizeof(E) == sizeof(T), "invalid enum type E"); + return *reinterpret_cast *>(arr); +} + +template +const Array &CastToArrayOfEnum(const T (&arr)[length]) { + static_assert(sizeof(E) == sizeof(T), "invalid enum type E"); + return *reinterpret_cast *>(arr); +} + // Lexicographically compare two strings (possibly containing nulls), and // return true if the first is less than the second. static inline bool StringLessThan(const char *a_data, uoffset_t a_size, @@ -581,6 +654,14 @@ static inline const char *GetCstring(const String *str) { return str ? str->c_str() : ""; } +#ifdef FLATBUFFERS_HAS_STRING_VIEW +// Convenience function to get string_view from a String returning an empty +// string_view on null pointer. +static inline flatbuffers::string_view GetStringView(const String *str) { + return str ? str->string_view() : flatbuffers::string_view(); +} +#endif // FLATBUFFERS_HAS_STRING_VIEW + // Allocator interface. This is flatbuffers-specific and meant only for // `vector_downward` usage. class Allocator { @@ -753,9 +834,9 @@ class DetachedBuffer { #if !defined(FLATBUFFERS_CPP98_STL) // clang-format on // These may change access mode, leave these at end of public section - FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other)) + FLATBUFFERS_DELETE_FUNC(DetachedBuffer(const DetachedBuffer &other)); FLATBUFFERS_DELETE_FUNC( - DetachedBuffer &operator=(const DetachedBuffer &other)) + DetachedBuffer &operator=(const DetachedBuffer &other)); // clang-format off #endif // !defined(FLATBUFFERS_CPP98_STL) // clang-format on @@ -920,7 +1001,7 @@ class vector_downward { Allocator *get_custom_allocator() { return allocator_; } uoffset_t size() const { - return static_cast(reserved_ - (cur_ - buf_)); + return static_cast(reserved_ - static_cast(cur_ - buf_)); } uoffset_t scratch_size() const { @@ -998,8 +1079,8 @@ class vector_downward { private: // You shouldn't really be copying instances of this class. - FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward &)) - FLATBUFFERS_DELETE_FUNC(vector_downward &operator=(const vector_downward &)) + FLATBUFFERS_DELETE_FUNC(vector_downward(const vector_downward &)); + FLATBUFFERS_DELETE_FUNC(vector_downward &operator=(const vector_downward &)); Allocator *allocator_; bool own_allocator_; @@ -1171,6 +1252,14 @@ class FlatBufferBuilder { return buf_.data(); } + /// @brief Get the serialized buffer (after you call `Finish()`) as a span. + /// @return Returns a constructed flatbuffers::span that is a view over the + /// FlatBuffer data inside the buffer. + flatbuffers::span GetBufferSpan() const { + Finished(); + return flatbuffers::span(buf_.data(), buf_.size()); + } + /// @brief Get a pointer to an unfinished buffer. /// @return Returns a `uint8_t` pointer to the unfinished buffer. uint8_t *GetCurrentBufferPointer() const { return buf_.data(); } @@ -1211,7 +1300,7 @@ class FlatBufferBuilder { /// you call Finish()). You can use this information if you need to embed /// a FlatBuffer in some other buffer, such that you can later read it /// without first having to copy it into its own buffer. - size_t GetBufferMinAlignment() { + size_t GetBufferMinAlignment() const { Finished(); return minalign_; } @@ -1295,6 +1384,11 @@ class FlatBufferBuilder { TrackField(field, off); } + template void AddElement(voffset_t field, T e) { + auto off = PushElement(e); + TrackField(field, off); + } + template void AddOffset(voffset_t field, Offset off) { if (off.IsNull()) return; // Don't store. AddElement(field, ReferTo(off.o), static_cast(0)); @@ -1530,6 +1624,16 @@ class FlatBufferBuilder { return off; } +#ifdef FLATBUFFERS_HAS_STRING_VIEW + /// @brief Store a string in the buffer, which can contain any binary data. + /// If a string with this exact contents has already been serialized before, + /// instead simply returns the offset of the existing string. + /// @param[in] str A const std::string_view to store in the buffer. + /// @return Returns the offset in the buffer where the string starts + Offset CreateSharedString(const flatbuffers::string_view str) { + return CreateSharedString(str.data(), str.size()); + } +#else /// @brief Store a string in the buffer, which null-terminated. /// If a string with this exact contents has already been serialized before, /// instead simply returns the offset of the existing string. @@ -1547,6 +1651,7 @@ class FlatBufferBuilder { Offset CreateSharedString(const std::string &str) { return CreateSharedString(str.c_str(), str.length()); } +#endif /// @brief Store a string in the buffer, which can contain any binary data. /// If a string with this exact contents has already been serialized before, @@ -1577,11 +1682,13 @@ 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) { + FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment)); PreAlign(len * elemsize, alignment); } // Similar to ForceVectorAlignment but for String fields. void ForceStringAlignment(size_t len, size_t alignment) { + FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment)); PreAlign((len + 1) * sizeof(char), alignment); } @@ -1599,6 +1706,7 @@ class FlatBufferBuilder { // causing the wrong overload to be selected, remove it. AssertScalarT(); StartVector(len, sizeof(T)); + if (len == 0) { return Offset>(EndVector(len)); } // clang-format off #if FLATBUFFERS_LITTLEENDIAN PushBytes(reinterpret_cast(v), len * sizeof(T)); @@ -1704,6 +1812,25 @@ class FlatBufferBuilder { return Offset>(EndVector(len)); } + /// @brief Serialize an array of native structs into a FlatBuffer `vector`. + /// @tparam T The data type of the struct array elements. + /// @tparam S The data type of the native struct array elements. + /// @param[in] v A pointer to the array of type `S` to serialize into the + /// buffer as a `vector`. + /// @param[in] len The number of elements to serialize. + /// @param[in] pack_func Pointer to a function to convert the native struct + /// to the FlatBuffer struct. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template + Offset> CreateVectorOfNativeStructs( + const S *v, size_t len, T((*const pack_func)(const S &))) { + FLATBUFFERS_ASSERT(pack_func); + std::vector vv(len); + std::transform(v, v + len, vv.begin(), pack_func); + return CreateVectorOfStructs(data(vv), vv.size()); + } + /// @brief Serialize an array of native structs into a FlatBuffer `vector`. /// @tparam T The data type of the struct array elements. /// @tparam S The data type of the native struct array elements. @@ -1716,9 +1843,7 @@ class FlatBufferBuilder { Offset> CreateVectorOfNativeStructs(const S *v, size_t len) { extern T Pack(const S &); - std::vector vv(len); - std::transform(v, v + len, vv.begin(), Pack); - return CreateVectorOfStructs(data(vv), vv.size()); + return CreateVectorOfNativeStructs(v, len, Pack); } // clang-format off @@ -1775,6 +1900,22 @@ class FlatBufferBuilder { return CreateVectorOfStructs(data(v), v.size()); } + /// @brief Serialize a `std::vector` of native structs into a FlatBuffer + /// `vector`. + /// @tparam T The data type of the `std::vector` struct elements. + /// @tparam S The data type of the `std::vector` native struct elements. + /// @param[in] v A const reference to the `std::vector` of structs to + /// serialize into the buffer as a `vector`. + /// @param[in] pack_func Pointer to a function to convert the native struct + /// to the FlatBuffer struct. + /// @return Returns a typed `Offset` into the serialized data indicating + /// where the vector is stored. + template + Offset> CreateVectorOfNativeStructs( + const std::vector &v, T((*const pack_func)(const S &))) { + return CreateVectorOfNativeStructs(data(v), v.size(), pack_func); + } + /// @brief Serialize a `std::vector` of native structs into a FlatBuffer /// `vector`. /// @tparam T The data type of the `std::vector` struct elements. @@ -1795,8 +1936,8 @@ class FlatBufferBuilder { return a.KeyCompareLessThan(&b); } - private: - StructKeyComparator &operator=(const StructKeyComparator &); + FLATBUFFERS_DELETE_FUNC( + StructKeyComparator &operator=(const StructKeyComparator &)); }; /// @endcond @@ -1871,10 +2012,8 @@ class FlatBufferBuilder { vector_downward &buf_; private: - TableKeyComparator &operator=(const TableKeyComparator &other) { - buf_ = other.buf_; - return *this; - } + FLATBUFFERS_DELETE_FUNC( + TableKeyComparator &operator=(const TableKeyComparator &other)); }; /// @endcond @@ -2269,8 +2408,8 @@ class Verifier FLATBUFFERS_FINAL_CLASS { template bool VerifyBufferFromStart(const char *identifier, size_t start) { - if (identifier && (size_ < 2 * sizeof(flatbuffers::uoffset_t) || - !BufferHasIdentifier(buf_ + start, identifier))) { + if (identifier && !Check((size_ >= 2 * sizeof(flatbuffers::uoffset_t) && + BufferHasIdentifier(buf_ + start, identifier)))) { return false; } @@ -2452,12 +2591,26 @@ class Table { return field_offset ? reinterpret_cast

(p) : nullptr; } + template + flatbuffers::Optional GetOptional(voffset_t field) const { + auto field_offset = GetOptionalFieldOffset(field); + auto p = data_ + field_offset; + return field_offset ? Optional(static_cast(ReadScalar(p))) + : Optional(); + } + template bool SetField(voffset_t field, T val, T def) { auto field_offset = GetOptionalFieldOffset(field); if (!field_offset) return IsTheSameAs(val, def); WriteScalar(data_ + field_offset, val); return true; } + template bool SetField(voffset_t field, T val) { + auto field_offset = GetOptionalFieldOffset(field); + if (!field_offset) return false; + WriteScalar(data_ + field_offset, val); + return true; + } bool SetPointer(voffset_t field, const uint8_t *val) { auto field_offset = GetOptionalFieldOffset(field); @@ -2525,6 +2678,17 @@ class Table { uint8_t data_[1]; }; +// This specialization allows avoiding warnings like: +// MSVC C4800: type: forcing value to bool 'true' or 'false'. +template<> +inline flatbuffers::Optional Table::GetOptional( + voffset_t field) const { + auto field_offset = GetOptionalFieldOffset(field); + auto p = data_ + field_offset; + return field_offset ? Optional(ReadScalar(p) != 0) + : Optional(); +} + template void FlatBufferBuilder::Required(Offset table, voffset_t field) { auto table_ptr = reinterpret_cast(buf_.data_at(table.o)); @@ -2702,10 +2866,16 @@ inline const char * const *ElementaryTypeNames() { // clang-format on // Basic type info cost just 16bits per field! +// We're explicitly defining the signedness since the signedness of integer +// bitfields is otherwise implementation-defined and causes warnings on older +// GCC compilers. struct TypeCode { - uint16_t base_type : 4; // ElementaryType - uint16_t is_vector : 1; - int16_t sequence_ref : 11; // Index into type_refs below, or -1 for none. + // ElementaryType + unsigned short base_type : 4; + // Either vector (in table) or array (in struct) + unsigned short is_repeating : 1; + // Index into type_refs below, or -1 for none. + signed short sequence_ref : 11; }; static_assert(sizeof(TypeCode) == 2, "TypeCode"); @@ -2720,6 +2890,7 @@ struct TypeTable { size_t num_elems; // of type_codes, values, names (but not type_refs). const TypeCode *type_codes; // num_elems count const TypeFunction *type_refs; // less than num_elems entries (see TypeCode). + const int16_t *array_sizes; // less than num_elems entries (see TypeCode). const int64_t *values; // Only set for non-consecutive enum/union or structs. const char *const *names; // Only set if compiled with --reflect-names. }; diff --git a/thirdparty/flatbuffers/stl_emulation.h b/thirdparty/flatbuffers/stl_emulation.h index 8bae61bfd6..70e5dc944e 100644 --- a/thirdparty/flatbuffers/stl_emulation.h +++ b/thirdparty/flatbuffers/stl_emulation.h @@ -18,6 +18,7 @@ #define FLATBUFFERS_STL_EMULATION_H_ // clang-format off +#include "flatbuffers/base.h" #include #include @@ -33,15 +34,34 @@ #include #endif // defined(FLATBUFFERS_CPP98_STL) -// Check if we can use template aliases -// Not possible if Microsoft Compiler before 2012 -// Possible is the language feature __cpp_alias_templates is defined well -// Or possible if the C++ std is C+11 or newer -#if (defined(_MSC_VER) && _MSC_VER > 1700 /* MSVC2012 */) \ - || (defined(__cpp_alias_templates) && __cpp_alias_templates >= 200704) \ - || (defined(__cplusplus) && __cplusplus >= 201103L) - #define FLATBUFFERS_TEMPLATES_ALIASES -#endif +// 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)) + #include + #ifndef FLATBUFFERS_USE_STD_OPTIONAL + #define FLATBUFFERS_USE_STD_OPTIONAL + #endif +#endif // defined(FLATBUFFERS_USE_STD_OPTIONAL) ... + +// 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 + #define FLATBUFFERS_USE_STD_SPAN + #endif +#else + // Disable non-trivial ctors if FLATBUFFERS_SPAN_MINIMAL defined. + #if !defined(FLATBUFFERS_TEMPLATES_ALIASES) || defined(FLATBUFFERS_CPP98_STL) + #define FLATBUFFERS_SPAN_MINIMAL + #else + // Enable implicit construction of a span from a std::array. + #include + #endif +#endif // defined(FLATBUFFERS_USE_STD_SPAN) // This header provides backwards compatibility for C++98 STLs like stlport. namespace flatbuffers { @@ -144,6 +164,8 @@ inline void vector_emplace_back(std::vector *vector, V &&data) { using conditional = std::conditional; template using integral_constant = std::integral_constant; + template + using bool_constant = integral_constant; #else // Map C++ TR1 templates defined by stlport. template using is_scalar = std::tr1::is_scalar; @@ -167,6 +189,8 @@ inline void vector_emplace_back(std::vector *vector, V &&data) { using conditional = std::tr1::conditional; template using integral_constant = std::tr1::integral_constant; + template + using bool_constant = integral_constant; #endif // !FLATBUFFERS_CPP98_STL #else // MSVC 2010 doesn't support C++11 aliases. @@ -181,6 +205,8 @@ inline void vector_emplace_back(std::vector *vector, V &&data) { struct conditional : public std::conditional {}; template struct integral_constant : public std::integral_constant {}; + template + struct bool_constant : public integral_constant {}; #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES) #ifndef FLATBUFFERS_CPP98_STL @@ -190,7 +216,7 @@ inline void vector_emplace_back(std::vector *vector, V &&data) { // MSVC 2010 doesn't support C++11 aliases. // We're manually "aliasing" the class here as we want to bring unique_ptr // into the flatbuffers namespace. We have unique_ptr in the flatbuffers - // namespace we have a completely independent implemenation (see below) + // namespace we have a completely independent implementation (see below) // for C++98 STL implementations. template class unique_ptr : public std::unique_ptr { public: @@ -302,6 +328,346 @@ inline void vector_emplace_back(std::vector *vector, V &&data) { #endif // !FLATBUFFERS_CPP98_STL +#ifdef FLATBUFFERS_USE_STD_OPTIONAL +template +using Optional = std::optional; +using nullopt_t = std::nullopt_t; +inline constexpr nullopt_t nullopt = std::nullopt; + +#else +// Limited implementation of Optional type for a scalar T. +// This implementation limited by trivial types compatible with +// std::is_arithmetic or std::is_enum type traits. + +// A tag to indicate an empty flatbuffers::optional. +struct nullopt_t { + explicit FLATBUFFERS_CONSTEXPR_CPP11 nullopt_t(int) {} +}; + +#if defined(FLATBUFFERS_CONSTEXPR_DEFINED) + namespace internal { + template struct nullopt_holder { + static constexpr nullopt_t instance_ = nullopt_t(0); + }; + template + constexpr nullopt_t nullopt_holder::instance_; + } + static constexpr const nullopt_t &nullopt = internal::nullopt_holder::instance_; + +#else + namespace internal { + template struct nullopt_holder { + static const nullopt_t instance_; + }; + template + const nullopt_t nullopt_holder::instance_ = nullopt_t(0); + } + static const nullopt_t &nullopt = internal::nullopt_holder::instance_; + +#endif + +template +class Optional FLATBUFFERS_FINAL_CLASS { + // Non-scalar 'T' would extremely complicated Optional. + // Use is_scalar checking because flatbuffers flatbuffers::is_arithmetic + // isn't implemented. + static_assert(flatbuffers::is_scalar::value, "unexpected type T"); + + public: + ~Optional() {} + + FLATBUFFERS_CONSTEXPR_CPP11 Optional() FLATBUFFERS_NOEXCEPT + : value_(), has_value_(false) {} + + FLATBUFFERS_CONSTEXPR_CPP11 Optional(nullopt_t) FLATBUFFERS_NOEXCEPT + : value_(), has_value_(false) {} + + FLATBUFFERS_CONSTEXPR_CPP11 Optional(T val) FLATBUFFERS_NOEXCEPT + : value_(val), has_value_(true) {} + + FLATBUFFERS_CONSTEXPR_CPP11 Optional(const Optional &other) FLATBUFFERS_NOEXCEPT + : value_(other.value_), has_value_(other.has_value_) {} + + FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(const Optional &other) FLATBUFFERS_NOEXCEPT { + value_ = other.value_; + has_value_ = other.has_value_; + return *this; + } + + FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(nullopt_t) FLATBUFFERS_NOEXCEPT { + value_ = T(); + has_value_ = false; + return *this; + } + + FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(T val) FLATBUFFERS_NOEXCEPT { + value_ = val; + has_value_ = true; + return *this; + } + + void reset() FLATBUFFERS_NOEXCEPT { + *this = nullopt; + } + + void swap(Optional &other) FLATBUFFERS_NOEXCEPT { + std::swap(value_, other.value_); + std::swap(has_value_, other.has_value_); + } + + FLATBUFFERS_CONSTEXPR_CPP11 FLATBUFFERS_EXPLICIT_CPP11 operator bool() const FLATBUFFERS_NOEXCEPT { + return has_value_; + } + + FLATBUFFERS_CONSTEXPR_CPP11 bool has_value() const FLATBUFFERS_NOEXCEPT { + return has_value_; + } + + FLATBUFFERS_CONSTEXPR_CPP11 const T& operator*() const FLATBUFFERS_NOEXCEPT { + return value_; + } + + const T& value() const { + FLATBUFFERS_ASSERT(has_value()); + return value_; + } + + T value_or(T default_value) const FLATBUFFERS_NOEXCEPT { + return has_value() ? value_ : default_value; + } + + private: + T value_; + bool has_value_; +}; + +template +FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional& opt, nullopt_t) FLATBUFFERS_NOEXCEPT { + return !opt; +} +template +FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(nullopt_t, const Optional& opt) FLATBUFFERS_NOEXCEPT { + return !opt; +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional& lhs, const U& rhs) FLATBUFFERS_NOEXCEPT { + return static_cast(lhs) && (*lhs == rhs); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const T& lhs, const Optional& rhs) FLATBUFFERS_NOEXCEPT { + return static_cast(rhs) && (lhs == *rhs); +} + +template +FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional& lhs, const Optional& rhs) FLATBUFFERS_NOEXCEPT { + return static_cast(lhs) != static_cast(rhs) + ? false + : !static_cast(lhs) ? false : (*lhs == *rhs); +} +#endif // FLATBUFFERS_USE_STD_OPTIONAL + + +// Very limited and naive partial implementation of C++20 std::span. +#if defined(FLATBUFFERS_USE_STD_SPAN) + inline constexpr std::size_t dynamic_extent = std::dynamic_extent; + template + using span = std::span; + +#else // !defined(FLATBUFFERS_USE_STD_SPAN) +FLATBUFFERS_CONSTEXPR std::size_t dynamic_extent = static_cast(-1); + +// Exclude this code if MSVC2010 or non-STL Android is active. +// The non-STL Android doesn't have `std::is_convertible` required for SFINAE. +#if !defined(FLATBUFFERS_SPAN_MINIMAL) +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 { + using type = + typename std::conditional::value + && (Extent == dynamic_extent || N == Extent), + int, void>::type; + }; + +} // namespace internal +#endif // !defined(FLATBUFFERS_SPAN_MINIMAL) + +// T - element type; must be a complete type that is not an abstract +// class type. +// Extent - the number of elements in the sequence, or dynamic. +template +class span FLATBUFFERS_FINAL_CLASS { + public: + typedef T element_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + typedef std::size_t size_type; + + static FLATBUFFERS_CONSTEXPR size_type extent = Extent; + + // Returns the number of elements in the span. + FLATBUFFERS_CONSTEXPR_CPP11 size_type size() const FLATBUFFERS_NOEXCEPT { + return count_; + } + + // Returns the size of the sequence in bytes. + FLATBUFFERS_CONSTEXPR_CPP11 + size_type size_bytes() const FLATBUFFERS_NOEXCEPT { + return size() * sizeof(element_type); + } + + // Checks if the span is empty. + FLATBUFFERS_CONSTEXPR_CPP11 bool empty() const FLATBUFFERS_NOEXCEPT { + return size() == 0; + } + + // Returns a pointer to the beginning of the sequence. + FLATBUFFERS_CONSTEXPR_CPP11 pointer data() const FLATBUFFERS_NOEXCEPT { + return data_; + } + + // Returns a reference to the idx-th element of the sequence. + // The behavior is undefined if the idx is greater than or equal to size(). + FLATBUFFERS_CONSTEXPR_CPP11 reference operator[](size_type idx) const { + return data()[idx]; + } + + FLATBUFFERS_CONSTEXPR_CPP11 span(const span &other) FLATBUFFERS_NOEXCEPT + : data_(other.data_), count_(other.count_) {} + + FLATBUFFERS_CONSTEXPR_CPP14 span &operator=(const span &other) + FLATBUFFERS_NOEXCEPT { + data_ = other.data_; + count_ = other.count_; + } + + // Limited implementation of + // `template constexpr std::span(It first, size_type count);`. + // + // Constructs a span that is a view over the range [first, first + count); + // the resulting span has: data() == first and size() == count. + // The behavior is undefined if [first, first + count) is not a valid range, + // or if (extent != flatbuffers::dynamic_extent && count != extent). + FLATBUFFERS_CONSTEXPR_CPP11 + explicit span(pointer first, size_type count) FLATBUFFERS_NOEXCEPT + : data_ (Extent == dynamic_extent ? first : (Extent == count ? first : nullptr)), + count_(Extent == dynamic_extent ? count : (Extent == count ? Extent : 0)) { + // Make span empty if the count argument is incompatible with span. + } + + // Exclude this code if MSVC2010 is active. The MSVC2010 isn't C++11 + // compliant, it doesn't support default template arguments for functions. + #if defined(FLATBUFFERS_SPAN_MINIMAL) + FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr), + count_(0) { + static_assert(extent == 0 || extent == dynamic_extent, "invalid span"); + } + + #else + // Constructs an empty span whose data() == nullptr and size() == 0. + // This overload only participates in overload resolution if + // extent == 0 || extent == flatbuffers::dynamic_extent. + // A dummy template argument N is need dependency for SFINAE. + template::type = 0> + FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr), + count_(0) { + static_assert(extent == 0 || extent == dynamic_extent, "invalid span"); + } + + // Constructs a span that is a view over the array arr; the resulting span + // has size() == N and data() == std::data(arr). These overloads only + // participate in overload resolution if + // extent == std::dynamic_extent || N == extent is true and + // std::remove_pointer_t(*)[] + // is convertible to element_type (*)[]. + template::type = 0> + FLATBUFFERS_CONSTEXPR_CPP11 span(element_type (&arr)[N]) FLATBUFFERS_NOEXCEPT + : data_(arr), count_(N) {} + + template::type = 0> + FLATBUFFERS_CONSTEXPR_CPP11 span(std::array &arr) FLATBUFFERS_NOEXCEPT + : data_(arr.data()), count_(N) {} + + //template + //FLATBUFFERS_CONSTEXPR_CPP11 span(std::array &arr) FLATBUFFERS_NOEXCEPT + // : data_(arr.data()), count_(N) {} + + template::type = 0> + FLATBUFFERS_CONSTEXPR_CPP11 span(const std::array &arr) FLATBUFFERS_NOEXCEPT + : data_(arr.data()), count_(N) {} + + // Converting constructor from another span s; + // the resulting span has size() == s.size() and data() == s.data(). + // This overload only participates in overload resolution + // if extent == std::dynamic_extent || N == extent is true and U (*)[] + // is convertible to element_type (*)[]. + template::type = 0> + FLATBUFFERS_CONSTEXPR_CPP11 span(const flatbuffers::span &s) FLATBUFFERS_NOEXCEPT + : span(s.data(), s.size()) { + } + + #endif // !defined(FLATBUFFERS_SPAN_MINIMAL) + + private: + // This is a naive implementation with 'count_' member even if (Extent != dynamic_extent). + pointer const data_; + const size_type count_; +}; + + #if !defined(FLATBUFFERS_SPAN_MINIMAL) + template + FLATBUFFERS_CONSTEXPR_CPP11 + flatbuffers::span make_span(U(&arr)[N]) FLATBUFFERS_NOEXCEPT { + return span(arr); + } + + template + FLATBUFFERS_CONSTEXPR_CPP11 + flatbuffers::span make_span(const U(&arr)[N]) FLATBUFFERS_NOEXCEPT { + return span(arr); + } + + template + FLATBUFFERS_CONSTEXPR_CPP11 + flatbuffers::span make_span(std::array &arr) FLATBUFFERS_NOEXCEPT { + return span(arr); + } + + template + FLATBUFFERS_CONSTEXPR_CPP11 + flatbuffers::span make_span(const std::array &arr) FLATBUFFERS_NOEXCEPT { + return span(arr); + } + + template + FLATBUFFERS_CONSTEXPR_CPP11 + flatbuffers::span make_span(U *first, std::size_t count) FLATBUFFERS_NOEXCEPT { + return span(first, count); + } + + template + FLATBUFFERS_CONSTEXPR_CPP11 + flatbuffers::span make_span(const U *first, std::size_t count) FLATBUFFERS_NOEXCEPT { + return span(first, count); + } +#endif + +#endif // defined(FLATBUFFERS_USE_STD_SPAN) + } // namespace flatbuffers #endif // FLATBUFFERS_STL_EMULATION_H_