github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/executor/_include/flatbuffers/stl_emulation.h (about) 1 /* 2 * Copyright 2017 Google Inc. All rights reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef FLATBUFFERS_STL_EMULATION_H_ 18 #define FLATBUFFERS_STL_EMULATION_H_ 19 20 // clang-format off 21 #include "flatbuffers/base.h" 22 23 #include <string> 24 #include <type_traits> 25 #include <vector> 26 #include <memory> 27 #include <limits> 28 29 #ifndef FLATBUFFERS_USE_STD_OPTIONAL 30 // Detect C++17 compatible compiler. 31 // __cplusplus >= 201703L - a compiler has support of 'static inline' variables. 32 #if (defined(__cplusplus) && __cplusplus >= 201703L) \ 33 || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) 34 #define FLATBUFFERS_USE_STD_OPTIONAL 1 35 #else 36 #define FLATBUFFERS_USE_STD_OPTIONAL 0 37 #endif // (defined(__cplusplus) && __cplusplus >= 201703L) ... 38 #endif // FLATBUFFERS_USE_STD_OPTIONAL 39 40 #if FLATBUFFERS_USE_STD_OPTIONAL 41 #include <optional> 42 #endif 43 44 #ifndef FLATBUFFERS_USE_STD_SPAN 45 // Testing __cpp_lib_span requires including either <version> or <span>, 46 // both of which were added in C++20. 47 // See: https://en.cppreference.com/w/cpp/utility/feature_test 48 #if defined(__cplusplus) && __cplusplus >= 202002L 49 #define FLATBUFFERS_USE_STD_SPAN 1 50 #endif 51 #endif // FLATBUFFERS_USE_STD_SPAN 52 53 #if defined(FLATBUFFERS_USE_STD_SPAN) 54 #include <array> 55 #include <span> 56 #else 57 // Disable non-trivial ctors if FLATBUFFERS_SPAN_MINIMAL defined. 58 #if !defined(FLATBUFFERS_TEMPLATES_ALIASES) 59 #define FLATBUFFERS_SPAN_MINIMAL 60 #else 61 // Enable implicit construction of a span<T,N> from a std::array<T,N>. 62 #include <array> 63 #endif 64 #endif // defined(FLATBUFFERS_USE_STD_SPAN) 65 66 // This header provides backwards compatibility for older versions of the STL. 67 namespace flatbuffers { 68 69 #if defined(FLATBUFFERS_TEMPLATES_ALIASES) 70 template <typename T> 71 using numeric_limits = std::numeric_limits<T>; 72 #else 73 template <typename T> class numeric_limits : 74 public std::numeric_limits<T> {}; 75 #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES) 76 77 #if defined(FLATBUFFERS_TEMPLATES_ALIASES) 78 template <typename T> using is_scalar = std::is_scalar<T>; 79 template <typename T, typename U> using is_same = std::is_same<T,U>; 80 template <typename T> using is_floating_point = std::is_floating_point<T>; 81 template <typename T> using is_unsigned = std::is_unsigned<T>; 82 template <typename T> using is_enum = std::is_enum<T>; 83 template <typename T> using make_unsigned = std::make_unsigned<T>; 84 template<bool B, class T, class F> 85 using conditional = std::conditional<B, T, F>; 86 template<class T, T v> 87 using integral_constant = std::integral_constant<T, v>; 88 template <bool B> 89 using bool_constant = integral_constant<bool, B>; 90 using true_type = std::true_type; 91 using false_type = std::false_type; 92 #else 93 // MSVC 2010 doesn't support C++11 aliases. 94 template <typename T> struct is_scalar : public std::is_scalar<T> {}; 95 template <typename T, typename U> struct is_same : public std::is_same<T,U> {}; 96 template <typename T> struct is_floating_point : 97 public std::is_floating_point<T> {}; 98 template <typename T> struct is_unsigned : public std::is_unsigned<T> {}; 99 template <typename T> struct is_enum : public std::is_enum<T> {}; 100 template <typename T> struct make_unsigned : public std::make_unsigned<T> {}; 101 template<bool B, class T, class F> 102 struct conditional : public std::conditional<B, T, F> {}; 103 template<class T, T v> 104 struct integral_constant : public std::integral_constant<T, v> {}; 105 template <bool B> 106 struct bool_constant : public integral_constant<bool, B> {}; 107 typedef bool_constant<true> true_type; 108 typedef bool_constant<false> false_type; 109 #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES) 110 111 #if defined(FLATBUFFERS_TEMPLATES_ALIASES) 112 template <class T> using unique_ptr = std::unique_ptr<T>; 113 #else 114 // MSVC 2010 doesn't support C++11 aliases. 115 // We're manually "aliasing" the class here as we want to bring unique_ptr 116 // into the flatbuffers namespace. We have unique_ptr in the flatbuffers 117 // namespace we have a completely independent implementation (see below) 118 // for C++98 STL implementations. 119 template <class T> class unique_ptr : public std::unique_ptr<T> { 120 public: 121 unique_ptr() {} 122 explicit unique_ptr(T* p) : std::unique_ptr<T>(p) {} 123 unique_ptr(std::unique_ptr<T>&& u) { *this = std::move(u); } 124 unique_ptr(unique_ptr&& u) { *this = std::move(u); } 125 unique_ptr& operator=(std::unique_ptr<T>&& u) { 126 std::unique_ptr<T>::reset(u.release()); 127 return *this; 128 } 129 unique_ptr& operator=(unique_ptr&& u) { 130 std::unique_ptr<T>::reset(u.release()); 131 return *this; 132 } 133 unique_ptr& operator=(T* p) { 134 return std::unique_ptr<T>::operator=(p); 135 } 136 }; 137 #endif // defined(FLATBUFFERS_TEMPLATES_ALIASES) 138 139 #if FLATBUFFERS_USE_STD_OPTIONAL 140 template<class T> 141 using Optional = std::optional<T>; 142 using nullopt_t = std::nullopt_t; 143 inline constexpr nullopt_t nullopt = std::nullopt; 144 145 #else 146 // Limited implementation of Optional<T> type for a scalar T. 147 // This implementation limited by trivial types compatible with 148 // std::is_arithmetic<T> or std::is_enum<T> type traits. 149 150 // A tag to indicate an empty flatbuffers::optional<T>. 151 struct nullopt_t { 152 explicit FLATBUFFERS_CONSTEXPR_CPP11 nullopt_t(int) {} 153 }; 154 155 #if defined(FLATBUFFERS_CONSTEXPR_DEFINED) 156 namespace internal { 157 template <class> struct nullopt_holder { 158 static constexpr nullopt_t instance_ = nullopt_t(0); 159 }; 160 template<class Dummy> 161 constexpr nullopt_t nullopt_holder<Dummy>::instance_; 162 } 163 static constexpr const nullopt_t &nullopt = internal::nullopt_holder<void>::instance_; 164 165 #else 166 namespace internal { 167 template <class> struct nullopt_holder { 168 static const nullopt_t instance_; 169 }; 170 template<class Dummy> 171 const nullopt_t nullopt_holder<Dummy>::instance_ = nullopt_t(0); 172 } 173 static const nullopt_t &nullopt = internal::nullopt_holder<void>::instance_; 174 175 #endif 176 177 template<class T> 178 class Optional FLATBUFFERS_FINAL_CLASS { 179 // Non-scalar 'T' would extremely complicated Optional<T>. 180 // Use is_scalar<T> checking because flatbuffers flatbuffers::is_arithmetic<T> 181 // isn't implemented. 182 static_assert(flatbuffers::is_scalar<T>::value, "unexpected type T"); 183 184 public: 185 ~Optional() {} 186 187 FLATBUFFERS_CONSTEXPR_CPP11 Optional() FLATBUFFERS_NOEXCEPT 188 : value_(), has_value_(false) {} 189 190 FLATBUFFERS_CONSTEXPR_CPP11 Optional(nullopt_t) FLATBUFFERS_NOEXCEPT 191 : value_(), has_value_(false) {} 192 193 FLATBUFFERS_CONSTEXPR_CPP11 Optional(T val) FLATBUFFERS_NOEXCEPT 194 : value_(val), has_value_(true) {} 195 196 FLATBUFFERS_CONSTEXPR_CPP11 Optional(const Optional &other) FLATBUFFERS_NOEXCEPT 197 : value_(other.value_), has_value_(other.has_value_) {} 198 199 FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(const Optional &other) FLATBUFFERS_NOEXCEPT { 200 value_ = other.value_; 201 has_value_ = other.has_value_; 202 return *this; 203 } 204 205 FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(nullopt_t) FLATBUFFERS_NOEXCEPT { 206 value_ = T(); 207 has_value_ = false; 208 return *this; 209 } 210 211 FLATBUFFERS_CONSTEXPR_CPP14 Optional &operator=(T val) FLATBUFFERS_NOEXCEPT { 212 value_ = val; 213 has_value_ = true; 214 return *this; 215 } 216 217 void reset() FLATBUFFERS_NOEXCEPT { 218 *this = nullopt; 219 } 220 221 void swap(Optional &other) FLATBUFFERS_NOEXCEPT { 222 std::swap(value_, other.value_); 223 std::swap(has_value_, other.has_value_); 224 } 225 226 FLATBUFFERS_CONSTEXPR_CPP11 FLATBUFFERS_EXPLICIT_CPP11 operator bool() const FLATBUFFERS_NOEXCEPT { 227 return has_value_; 228 } 229 230 FLATBUFFERS_CONSTEXPR_CPP11 bool has_value() const FLATBUFFERS_NOEXCEPT { 231 return has_value_; 232 } 233 234 FLATBUFFERS_CONSTEXPR_CPP11 const T& operator*() const FLATBUFFERS_NOEXCEPT { 235 return value_; 236 } 237 238 const T& value() const { 239 FLATBUFFERS_ASSERT(has_value()); 240 return value_; 241 } 242 243 T value_or(T default_value) const FLATBUFFERS_NOEXCEPT { 244 return has_value() ? value_ : default_value; 245 } 246 247 private: 248 T value_; 249 bool has_value_; 250 }; 251 252 template<class T> 253 FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& opt, nullopt_t) FLATBUFFERS_NOEXCEPT { 254 return !opt; 255 } 256 template<class T> 257 FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(nullopt_t, const Optional<T>& opt) FLATBUFFERS_NOEXCEPT { 258 return !opt; 259 } 260 261 template<class T, class U> 262 FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& lhs, const U& rhs) FLATBUFFERS_NOEXCEPT { 263 return static_cast<bool>(lhs) && (*lhs == rhs); 264 } 265 266 template<class T, class U> 267 FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const T& lhs, const Optional<U>& rhs) FLATBUFFERS_NOEXCEPT { 268 return static_cast<bool>(rhs) && (lhs == *rhs); 269 } 270 271 template<class T, class U> 272 FLATBUFFERS_CONSTEXPR_CPP11 bool operator==(const Optional<T>& lhs, const Optional<U>& rhs) FLATBUFFERS_NOEXCEPT { 273 return static_cast<bool>(lhs) != static_cast<bool>(rhs) 274 ? false 275 : !static_cast<bool>(lhs) ? false : (*lhs == *rhs); 276 } 277 #endif // FLATBUFFERS_USE_STD_OPTIONAL 278 279 280 // Very limited and naive partial implementation of C++20 std::span<T,Extent>. 281 #if defined(FLATBUFFERS_USE_STD_SPAN) 282 inline constexpr std::size_t dynamic_extent = std::dynamic_extent; 283 template<class T, std::size_t Extent = std::dynamic_extent> 284 using span = std::span<T, Extent>; 285 286 #else // !defined(FLATBUFFERS_USE_STD_SPAN) 287 FLATBUFFERS_CONSTEXPR std::size_t dynamic_extent = static_cast<std::size_t>(-1); 288 289 // Exclude this code if MSVC2010 or non-STL Android is active. 290 // The non-STL Android doesn't have `std::is_convertible` required for SFINAE. 291 #if !defined(FLATBUFFERS_SPAN_MINIMAL) 292 namespace internal { 293 // This is SFINAE helper class for checking of a common condition: 294 // > This overload only participates in overload resolution 295 // > Check whether a pointer to an array of From can be converted 296 // > to a pointer to an array of To. 297 // This helper is used for checking of 'From -> const From'. 298 template<class To, std::size_t Extent, class From, std::size_t N> 299 struct is_span_convertible { 300 using type = 301 typename std::conditional<std::is_convertible<From (*)[], To (*)[]>::value 302 && (Extent == dynamic_extent || N == Extent), 303 int, void>::type; 304 }; 305 306 template<typename T> 307 struct SpanIterator { 308 // TODO: upgrade to std::random_access_iterator_tag. 309 using iterator_category = std::forward_iterator_tag; 310 using difference_type = std::ptrdiff_t; 311 using value_type = typename std::remove_cv<T>::type; 312 using reference = T&; 313 using pointer = T*; 314 315 // Convince MSVC compiler that this iterator is trusted (it is verified). 316 #ifdef _MSC_VER 317 using _Unchecked_type = pointer; 318 #endif // _MSC_VER 319 320 SpanIterator(pointer ptr) : ptr_(ptr) {} 321 reference operator*() const { return *ptr_; } 322 pointer operator->() { return ptr_; } 323 SpanIterator& operator++() { ptr_++; return *this; } 324 SpanIterator operator++(int) { auto tmp = *this; ++(*this); return tmp; } 325 326 friend bool operator== (const SpanIterator& lhs, const SpanIterator& rhs) { return lhs.ptr_ == rhs.ptr_; } 327 friend bool operator!= (const SpanIterator& lhs, const SpanIterator& rhs) { return lhs.ptr_ != rhs.ptr_; } 328 329 private: 330 pointer ptr_; 331 }; 332 } // namespace internal 333 #endif // !defined(FLATBUFFERS_SPAN_MINIMAL) 334 335 // T - element type; must be a complete type that is not an abstract 336 // class type. 337 // Extent - the number of elements in the sequence, or dynamic. 338 template<class T, std::size_t Extent = dynamic_extent> 339 class span FLATBUFFERS_FINAL_CLASS { 340 public: 341 typedef T element_type; 342 typedef T& reference; 343 typedef const T& const_reference; 344 typedef T* pointer; 345 typedef const T* const_pointer; 346 typedef std::size_t size_type; 347 348 static FLATBUFFERS_CONSTEXPR size_type extent = Extent; 349 350 // Returns the number of elements in the span. 351 FLATBUFFERS_CONSTEXPR_CPP11 size_type size() const FLATBUFFERS_NOEXCEPT { 352 return count_; 353 } 354 355 // Returns the size of the sequence in bytes. 356 FLATBUFFERS_CONSTEXPR_CPP11 357 size_type size_bytes() const FLATBUFFERS_NOEXCEPT { 358 return size() * sizeof(element_type); 359 } 360 361 // Checks if the span is empty. 362 FLATBUFFERS_CONSTEXPR_CPP11 bool empty() const FLATBUFFERS_NOEXCEPT { 363 return size() == 0; 364 } 365 366 // Returns a pointer to the beginning of the sequence. 367 FLATBUFFERS_CONSTEXPR_CPP11 pointer data() const FLATBUFFERS_NOEXCEPT { 368 return data_; 369 } 370 371 #if !defined(FLATBUFFERS_SPAN_MINIMAL) 372 using Iterator = internal::SpanIterator<T>; 373 374 Iterator begin() const { return Iterator(data()); } 375 Iterator end() const { return Iterator(data() + size()); } 376 #endif 377 378 // Returns a reference to the idx-th element of the sequence. 379 // The behavior is undefined if the idx is greater than or equal to size(). 380 FLATBUFFERS_CONSTEXPR_CPP11 reference operator[](size_type idx) const { 381 return data()[idx]; 382 } 383 384 FLATBUFFERS_CONSTEXPR_CPP11 span(const span &other) FLATBUFFERS_NOEXCEPT 385 : data_(other.data_), count_(other.count_) {} 386 387 FLATBUFFERS_CONSTEXPR_CPP14 span &operator=(const span &other) 388 FLATBUFFERS_NOEXCEPT { 389 data_ = other.data_; 390 count_ = other.count_; 391 } 392 393 // Limited implementation of 394 // `template <class It> constexpr std::span(It first, size_type count);`. 395 // 396 // Constructs a span that is a view over the range [first, first + count); 397 // the resulting span has: data() == first and size() == count. 398 // The behavior is undefined if [first, first + count) is not a valid range, 399 // or if (extent != flatbuffers::dynamic_extent && count != extent). 400 FLATBUFFERS_CONSTEXPR_CPP11 401 explicit span(pointer first, size_type count) FLATBUFFERS_NOEXCEPT 402 : data_ (Extent == dynamic_extent ? first : (Extent == count ? first : nullptr)), 403 count_(Extent == dynamic_extent ? count : (Extent == count ? Extent : 0)) { 404 // Make span empty if the count argument is incompatible with span<T,N>. 405 } 406 407 // Exclude this code if MSVC2010 is active. The MSVC2010 isn't C++11 408 // compliant, it doesn't support default template arguments for functions. 409 #if defined(FLATBUFFERS_SPAN_MINIMAL) 410 FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr), 411 count_(0) { 412 static_assert(extent == 0 || extent == dynamic_extent, "invalid span"); 413 } 414 415 #else 416 // Constructs an empty span whose data() == nullptr and size() == 0. 417 // This overload only participates in overload resolution if 418 // extent == 0 || extent == flatbuffers::dynamic_extent. 419 // A dummy template argument N is need dependency for SFINAE. 420 template<std::size_t N = 0, 421 typename internal::is_span_convertible<element_type, Extent, element_type, (N - N)>::type = 0> 422 FLATBUFFERS_CONSTEXPR_CPP11 span() FLATBUFFERS_NOEXCEPT : data_(nullptr), 423 count_(0) { 424 static_assert(extent == 0 || extent == dynamic_extent, "invalid span"); 425 } 426 427 // Constructs a span that is a view over the array arr; the resulting span 428 // has size() == N and data() == std::data(arr). These overloads only 429 // participate in overload resolution if 430 // extent == std::dynamic_extent || N == extent is true and 431 // std::remove_pointer_t<decltype(std::data(arr))>(*)[] 432 // is convertible to element_type (*)[]. 433 template<std::size_t N, 434 typename internal::is_span_convertible<element_type, Extent, element_type, N>::type = 0> 435 FLATBUFFERS_CONSTEXPR_CPP11 span(element_type (&arr)[N]) FLATBUFFERS_NOEXCEPT 436 : data_(arr), count_(N) {} 437 438 template<class U, std::size_t N, 439 typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0> 440 FLATBUFFERS_CONSTEXPR_CPP11 span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT 441 : data_(arr.data()), count_(N) {} 442 443 //template<class U, std::size_t N, 444 // int = 0> 445 //FLATBUFFERS_CONSTEXPR_CPP11 span(std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT 446 // : data_(arr.data()), count_(N) {} 447 448 template<class U, std::size_t N, 449 typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0> 450 FLATBUFFERS_CONSTEXPR_CPP11 span(const std::array<U, N> &arr) FLATBUFFERS_NOEXCEPT 451 : data_(arr.data()), count_(N) {} 452 453 // Converting constructor from another span s; 454 // the resulting span has size() == s.size() and data() == s.data(). 455 // This overload only participates in overload resolution 456 // if extent == std::dynamic_extent || N == extent is true and U (*)[] 457 // is convertible to element_type (*)[]. 458 template<class U, std::size_t N, 459 typename internal::is_span_convertible<element_type, Extent, U, N>::type = 0> 460 FLATBUFFERS_CONSTEXPR_CPP11 span(const flatbuffers::span<U, N> &s) FLATBUFFERS_NOEXCEPT 461 : span(s.data(), s.size()) { 462 } 463 464 #endif // !defined(FLATBUFFERS_SPAN_MINIMAL) 465 466 private: 467 // This is a naive implementation with 'count_' member even if (Extent != dynamic_extent). 468 pointer const data_; 469 size_type count_; 470 }; 471 #endif // defined(FLATBUFFERS_USE_STD_SPAN) 472 473 #if !defined(FLATBUFFERS_SPAN_MINIMAL) 474 template<class ElementType, std::size_t Extent> 475 FLATBUFFERS_CONSTEXPR_CPP11 476 flatbuffers::span<ElementType, Extent> make_span(ElementType(&arr)[Extent]) FLATBUFFERS_NOEXCEPT { 477 return span<ElementType, Extent>(arr); 478 } 479 480 template<class ElementType, std::size_t Extent> 481 FLATBUFFERS_CONSTEXPR_CPP11 482 flatbuffers::span<const ElementType, Extent> make_span(const ElementType(&arr)[Extent]) FLATBUFFERS_NOEXCEPT { 483 return span<const ElementType, Extent>(arr); 484 } 485 486 template<class ElementType, std::size_t Extent> 487 FLATBUFFERS_CONSTEXPR_CPP11 488 flatbuffers::span<ElementType, Extent> make_span(std::array<ElementType, Extent> &arr) FLATBUFFERS_NOEXCEPT { 489 return span<ElementType, Extent>(arr); 490 } 491 492 template<class ElementType, std::size_t Extent> 493 FLATBUFFERS_CONSTEXPR_CPP11 494 flatbuffers::span<const ElementType, Extent> make_span(const std::array<ElementType, Extent> &arr) FLATBUFFERS_NOEXCEPT { 495 return span<const ElementType, Extent>(arr); 496 } 497 498 template<class ElementType, std::size_t Extent> 499 FLATBUFFERS_CONSTEXPR_CPP11 500 flatbuffers::span<ElementType, dynamic_extent> make_span(ElementType *first, std::size_t count) FLATBUFFERS_NOEXCEPT { 501 return span<ElementType, dynamic_extent>(first, count); 502 } 503 504 template<class ElementType, std::size_t Extent> 505 FLATBUFFERS_CONSTEXPR_CPP11 506 flatbuffers::span<const ElementType, dynamic_extent> make_span(const ElementType *first, std::size_t count) FLATBUFFERS_NOEXCEPT { 507 return span<const ElementType, dynamic_extent>(first, count); 508 } 509 #endif // !defined(FLATBUFFERS_SPAN_MINIMAL) 510 511 } // namespace flatbuffers 512 513 #endif // FLATBUFFERS_STL_EMULATION_H_