Line data Source code
1 : #ifndef FLATBUFFERS_BASE_H_ 2 : #define FLATBUFFERS_BASE_H_ 3 : 4 : // clang-format off 5 : 6 : // If activate should be declared and included first. 7 : #if defined(FLATBUFFERS_MEMORY_LEAK_TRACKING) && \ 8 : defined(_MSC_VER) && defined(_DEBUG) 9 : // The _CRTDBG_MAP_ALLOC inside <crtdbg.h> will replace 10 : // calloc/free (etc) to its debug version using #define directives. 11 : #define _CRTDBG_MAP_ALLOC 12 : #include <stdlib.h> 13 : #include <crtdbg.h> 14 : // Replace operator new by trace-enabled version. 15 : #define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) 16 : #define new DEBUG_NEW 17 : #endif 18 : 19 : #if !defined(FLATBUFFERS_ASSERT) 20 : #include <assert.h> 21 : #define FLATBUFFERS_ASSERT assert 22 : #elif defined(FLATBUFFERS_ASSERT_INCLUDE) 23 : // Include file with forward declaration 24 : #include FLATBUFFERS_ASSERT_INCLUDE 25 : #endif 26 : 27 : #ifndef ARDUINO 28 : #include <cstdint> 29 : #endif 30 : 31 : #include <cstddef> 32 : #include <cstdlib> 33 : #include <cstring> 34 : 35 : #if defined(ARDUINO) && !defined(ARDUINOSTL_M_H) 36 : #include <utility.h> 37 : #else 38 : #include <utility> 39 : #endif 40 : 41 : #include <string> 42 : #include <type_traits> 43 : #include <vector> 44 : #include <set> 45 : #include <algorithm> 46 : #include <iterator> 47 : #include <memory> 48 : 49 : #if defined(__unix__) && !defined(FLATBUFFERS_LOCALE_INDEPENDENT) 50 : #include <unistd.h> 51 : #endif 52 : 53 : #ifdef __ANDROID__ 54 : #include <android/api-level.h> 55 : #endif 56 : 57 : #if defined(__ICCARM__) 58 : #include <intrinsics.h> 59 : #endif 60 : 61 : // Note the __clang__ check is needed, because clang presents itself 62 : // as an older GNUC compiler (4.2). 63 : // Clang 3.3 and later implement all of the ISO C++ 2011 standard. 64 : // Clang 3.4 and later implement all of the ISO C++ 2014 standard. 65 : // http://clang.llvm.org/cxx_status.html 66 : 67 : // Note the MSVC value '__cplusplus' may be incorrect: 68 : // The '__cplusplus' predefined macro in the MSVC stuck at the value 199711L, 69 : // indicating (erroneously!) that the compiler conformed to the C++98 Standard. 70 : // This value should be correct starting from MSVC2017-15.7-Preview-3. 71 : // The '__cplusplus' will be valid only if MSVC2017-15.7-P3 and the `/Zc:__cplusplus` switch is set. 72 : // Workaround (for details see MSDN): 73 : // Use the _MSC_VER and _MSVC_LANG definition instead of the __cplusplus for compatibility. 74 : // The _MSVC_LANG macro reports the Standard version regardless of the '/Zc:__cplusplus' switch. 75 : 76 : #if defined(__GNUC__) && !defined(__clang__) 77 : #define FLATBUFFERS_GCC (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) 78 : #else 79 : #define FLATBUFFERS_GCC 0 80 : #endif 81 : 82 : #if defined(__clang__) 83 : #define FLATBUFFERS_CLANG (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) 84 : #else 85 : #define FLATBUFFERS_CLANG 0 86 : #endif 87 : 88 : /// @cond FLATBUFFERS_INTERNAL 89 : #if __cplusplus <= 199711L && \ 90 : (!defined(_MSC_VER) || _MSC_VER < 1600) && \ 91 : (!defined(__GNUC__) || \ 92 : (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400)) 93 : #error A C++11 compatible compiler with support for the auto typing is \ 94 : required for FlatBuffers. 95 : #error __cplusplus _MSC_VER __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__ 96 : #endif 97 : 98 : #if !defined(__clang__) && \ 99 : defined(__GNUC__) && \ 100 : (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600) 101 : // Backwards compatibility for g++ 4.4, and 4.5 which don't have the nullptr 102 : // and constexpr keywords. Note the __clang__ check is needed, because clang 103 : // presents itself as an older GNUC compiler. 104 : #ifndef nullptr_t 105 : const class nullptr_t { 106 : public: 107 : template<class T> inline operator T*() const { return 0; } 108 : private: 109 : void operator&() const; 110 : } nullptr = {}; 111 : #endif 112 : #ifndef constexpr 113 : #define constexpr const 114 : #endif 115 : #endif 116 : 117 : // The wire format uses a little endian encoding (since that's efficient for 118 : // the common platforms). 119 : #if defined(__s390x__) 120 : #define FLATBUFFERS_LITTLEENDIAN 0 121 : #endif // __s390x__ 122 : #if !defined(FLATBUFFERS_LITTLEENDIAN) 123 : #if defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__) 124 : #if (defined(__BIG_ENDIAN__) || \ 125 : (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) 126 : #define FLATBUFFERS_LITTLEENDIAN 0 127 : #else 128 : #define FLATBUFFERS_LITTLEENDIAN 1 129 : #endif // __BIG_ENDIAN__ 130 : #elif defined(_MSC_VER) 131 : #if defined(_M_PPC) 132 : #define FLATBUFFERS_LITTLEENDIAN 0 133 : #else 134 : #define FLATBUFFERS_LITTLEENDIAN 1 135 : #endif 136 : #else 137 : #error Unable to determine endianness, define FLATBUFFERS_LITTLEENDIAN. 138 : #endif 139 : #endif // !defined(FLATBUFFERS_LITTLEENDIAN) 140 : 141 : #define FLATBUFFERS_VERSION_MAJOR 2 142 : #define FLATBUFFERS_VERSION_MINOR 0 143 : #define FLATBUFFERS_VERSION_REVISION 8 144 : #define FLATBUFFERS_STRING_EXPAND(X) #X 145 : #define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X) 146 : namespace flatbuffers { 147 : // Returns version as string "MAJOR.MINOR.REVISION". 148 : const char* FLATBUFFERS_VERSION(); 149 : } 150 : 151 : #if (!defined(_MSC_VER) || _MSC_VER > 1600) && \ 152 : (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407)) || \ 153 : defined(__clang__) 154 : #define FLATBUFFERS_FINAL_CLASS final 155 : #define FLATBUFFERS_OVERRIDE override 156 : #define FLATBUFFERS_EXPLICIT_CPP11 explicit 157 : #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t 158 : #else 159 : #define FLATBUFFERS_FINAL_CLASS 160 : #define FLATBUFFERS_OVERRIDE 161 : #define FLATBUFFERS_EXPLICIT_CPP11 162 : #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE 163 : #endif 164 : 165 : #if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \ 166 : (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \ 167 : (defined(__cpp_constexpr) && __cpp_constexpr >= 200704) 168 : #define FLATBUFFERS_CONSTEXPR constexpr 169 : #define FLATBUFFERS_CONSTEXPR_CPP11 constexpr 170 : #define FLATBUFFERS_CONSTEXPR_DEFINED 171 : #else 172 : #define FLATBUFFERS_CONSTEXPR const 173 : #define FLATBUFFERS_CONSTEXPR_CPP11 174 : #endif 175 : 176 : #if (defined(__cplusplus) && __cplusplus >= 201402L) || \ 177 : (defined(__cpp_constexpr) && __cpp_constexpr >= 201304) 178 : #define FLATBUFFERS_CONSTEXPR_CPP14 FLATBUFFERS_CONSTEXPR_CPP11 179 : #else 180 : #define FLATBUFFERS_CONSTEXPR_CPP14 181 : #endif 182 : 183 : #if (defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \ 184 : (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023026)) || \ 185 : defined(__clang__) 186 : #define FLATBUFFERS_NOEXCEPT noexcept 187 : #else 188 : #define FLATBUFFERS_NOEXCEPT 189 : #endif 190 : 191 : // NOTE: the FLATBUFFERS_DELETE_FUNC macro may change the access mode to 192 : // private, so be sure to put it at the end or reset access mode explicitly. 193 : #if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \ 194 : (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404)) || \ 195 : defined(__clang__) 196 : #define FLATBUFFERS_DELETE_FUNC(func) func = delete 197 : #else 198 : #define FLATBUFFERS_DELETE_FUNC(func) private: func 199 : #endif 200 : 201 : #if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \ 202 : (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \ 203 : defined(__clang__) 204 : #define FLATBUFFERS_DEFAULT_DECLARATION 205 : #endif 206 : 207 : // Check if we can use template aliases 208 : // Not possible if Microsoft Compiler before 2012 209 : // Possible is the language feature __cpp_alias_templates is defined well 210 : // Or possible if the C++ std is C+11 or newer 211 : #if (defined(_MSC_VER) && _MSC_VER > 1700 /* MSVC2012 */) \ 212 : || (defined(__cpp_alias_templates) && __cpp_alias_templates >= 200704) \ 213 : || (defined(__cplusplus) && __cplusplus >= 201103L) 214 : #define FLATBUFFERS_TEMPLATES_ALIASES 215 : #endif 216 : 217 : #ifndef FLATBUFFERS_HAS_STRING_VIEW 218 : // Only provide flatbuffers::string_view if __has_include can be used 219 : // to detect a header that provides an implementation 220 : #if defined(__has_include) 221 : // Check for std::string_view (in c++17) 222 : #if __has_include(<string_view>) && (__cplusplus >= 201606 || (defined(_HAS_CXX17) && _HAS_CXX17)) 223 : #include <string_view> 224 : namespace flatbuffers { 225 : typedef std::string_view string_view; 226 : } 227 : #define FLATBUFFERS_HAS_STRING_VIEW 1 228 : // Check for std::experimental::string_view (in c++14, compiler-dependent) 229 : #elif __has_include(<experimental/string_view>) && (__cplusplus >= 201411) 230 : #include <experimental/string_view> 231 : namespace flatbuffers { 232 : typedef std::experimental::string_view string_view; 233 : } 234 : #define FLATBUFFERS_HAS_STRING_VIEW 1 235 : // Check for absl::string_view 236 : #elif __has_include("absl/strings/string_view.h") 237 : #include "absl/strings/string_view.h" 238 : namespace flatbuffers { 239 : typedef absl::string_view string_view; 240 : } 241 : #define FLATBUFFERS_HAS_STRING_VIEW 1 242 : #endif 243 : #endif // __has_include 244 : #endif // !FLATBUFFERS_HAS_STRING_VIEW 245 : 246 : #ifndef FLATBUFFERS_GENERAL_HEAP_ALLOC_OK 247 : // Allow heap allocations to be used 248 : #define FLATBUFFERS_GENERAL_HEAP_ALLOC_OK 1 249 : #endif // !FLATBUFFERS_GENERAL_HEAP_ALLOC_OK 250 : 251 : #ifndef FLATBUFFERS_HAS_NEW_STRTOD 252 : // Modern (C++11) strtod and strtof functions are available for use. 253 : // 1) nan/inf strings as argument of strtod; 254 : // 2) hex-float as argument of strtod/strtof. 255 : #if (defined(_MSC_VER) && _MSC_VER >= 1900) || \ 256 : (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \ 257 : (defined(__clang__)) 258 : #define FLATBUFFERS_HAS_NEW_STRTOD 1 259 : #endif 260 : #endif // !FLATBUFFERS_HAS_NEW_STRTOD 261 : 262 : #ifndef FLATBUFFERS_LOCALE_INDEPENDENT 263 : // Enable locale independent functions {strtof_l, strtod_l,strtoll_l, 264 : // strtoull_l}. 265 : #if (defined(_MSC_VER) && _MSC_VER >= 1800) || \ 266 : (defined(__ANDROID_API__) && __ANDROID_API__>= 21) || \ 267 : (defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 700)) && \ 268 : (!defined(__Fuchsia__) && !defined(__ANDROID_API__)) 269 : #define FLATBUFFERS_LOCALE_INDEPENDENT 1 270 : #else 271 : #define FLATBUFFERS_LOCALE_INDEPENDENT 0 272 : #endif 273 : #endif // !FLATBUFFERS_LOCALE_INDEPENDENT 274 : 275 : // Suppress Undefined Behavior Sanitizer (recoverable only). Usage: 276 : // - __suppress_ubsan__("undefined") 277 : // - __suppress_ubsan__("signed-integer-overflow") 278 : #if defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7)) 279 : #define __suppress_ubsan__(type) __attribute__((no_sanitize(type))) 280 : #elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409) 281 : #define __suppress_ubsan__(type) __attribute__((no_sanitize_undefined)) 282 : #else 283 : #define __suppress_ubsan__(type) 284 : #endif 285 : 286 : // This is constexpr function used for checking compile-time constants. 287 : // Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`. 288 : template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) { 289 : return !!t; 290 : } 291 : 292 : // Enable C++ attribute [[]] if std:c++17 or higher. 293 : #if ((__cplusplus >= 201703L) \ 294 : || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L))) 295 : // All attributes unknown to an implementation are ignored without causing an error. 296 : #define FLATBUFFERS_ATTRIBUTE(attr) attr 297 : 298 : #define FLATBUFFERS_FALLTHROUGH() [[fallthrough]] 299 : #else 300 : #define FLATBUFFERS_ATTRIBUTE(attr) 301 : 302 : #if FLATBUFFERS_CLANG >= 30800 303 : #define FLATBUFFERS_FALLTHROUGH() [[clang::fallthrough]] 304 : #elif FLATBUFFERS_GCC >= 70300 305 : #define FLATBUFFERS_FALLTHROUGH() [[gnu::fallthrough]] 306 : #else 307 : #define FLATBUFFERS_FALLTHROUGH() 308 : #endif 309 : #endif 310 : 311 : /// @endcond 312 : 313 : /// @file 314 : namespace flatbuffers { 315 : 316 : /// @cond FLATBUFFERS_INTERNAL 317 : // Our default offset / size type, 32bit on purpose on 64bit systems. 318 : // Also, using a consistent offset type maintains compatibility of serialized 319 : // offset values between 32bit and 64bit systems. 320 : typedef uint32_t uoffset_t; 321 : 322 : // Signed offsets for references that can go in both directions. 323 : typedef int32_t soffset_t; 324 : 325 : // Offset/index used in v-tables, can be changed to uint8_t in 326 : // format forks to save a bit of space if desired. 327 : typedef uint16_t voffset_t; 328 : 329 : typedef uintmax_t largest_scalar_t; 330 : 331 : // In 32bits, this evaluates to 2GB - 1 332 : #define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(::flatbuffers::soffset_t) * 8 - 1)) - 1) 333 : 334 : // The minimum size buffer that can be a valid flatbuffer. 335 : // Includes the offset to the root table (uoffset_t), the offset to the vtable 336 : // of the root table (soffset_t), the size of the vtable (uint16_t), and the 337 : // size of the referring table (uint16_t). 338 : #define FLATBUFFERS_MIN_BUFFER_SIZE sizeof(uoffset_t) + sizeof(soffset_t) + \ 339 : sizeof(uint16_t) + sizeof(uint16_t) 340 : 341 : // We support aligning the contents of buffers up to this size. 342 : #ifndef FLATBUFFERS_MAX_ALIGNMENT 343 : #define FLATBUFFERS_MAX_ALIGNMENT 32 344 : #endif 345 : 346 : /// @brief The length of a FlatBuffer file header. 347 : static const size_t kFileIdentifierLength = 4; 348 : 349 : inline bool VerifyAlignmentRequirements(size_t align, size_t min_align = 1) { 350 : return (min_align <= align) && (align <= (FLATBUFFERS_MAX_ALIGNMENT)) && 351 : (align & (align - 1)) == 0; // must be power of 2 352 : } 353 : 354 : #if defined(_MSC_VER) 355 : #pragma warning(disable: 4351) // C4351: new behavior: elements of array ... will be default initialized 356 : #pragma warning(push) 357 : #pragma warning(disable: 4127) // C4127: conditional expression is constant 358 : #endif 359 : 360 : template<typename T> T EndianSwap(T t) { 361 : #if defined(_MSC_VER) 362 : #define FLATBUFFERS_BYTESWAP16 _byteswap_ushort 363 : #define FLATBUFFERS_BYTESWAP32 _byteswap_ulong 364 : #define FLATBUFFERS_BYTESWAP64 _byteswap_uint64 365 : #elif defined(__ICCARM__) 366 : #define FLATBUFFERS_BYTESWAP16 __REV16 367 : #define FLATBUFFERS_BYTESWAP32 __REV 368 : #define FLATBUFFERS_BYTESWAP64(x) \ 369 : ((__REV(static_cast<uint32_t>(x >> 32U))) | (static_cast<uint64_t>(__REV(static_cast<uint32_t>(x)))) << 32U) 370 : #else 371 : #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__) 372 : // __builtin_bswap16 was missing prior to GCC 4.8. 373 : #define FLATBUFFERS_BYTESWAP16(x) \ 374 : static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16)) 375 : #else 376 : #define FLATBUFFERS_BYTESWAP16 __builtin_bswap16 377 : #endif 378 : #define FLATBUFFERS_BYTESWAP32 __builtin_bswap32 379 : #define FLATBUFFERS_BYTESWAP64 __builtin_bswap64 380 : #endif 381 : if (sizeof(T) == 1) { // Compile-time if-then's. 382 : return t; 383 : } else if (sizeof(T) == 2) { 384 : union { T t; uint16_t i; } u = { t }; 385 : u.i = FLATBUFFERS_BYTESWAP16(u.i); 386 : return u.t; 387 : } else if (sizeof(T) == 4) { 388 : union { T t; uint32_t i; } u = { t }; 389 : u.i = FLATBUFFERS_BYTESWAP32(u.i); 390 : return u.t; 391 : } else if (sizeof(T) == 8) { 392 : union { T t; uint64_t i; } u = { t }; 393 : u.i = FLATBUFFERS_BYTESWAP64(u.i); 394 : return u.t; 395 : } else { 396 : FLATBUFFERS_ASSERT(0); 397 : return t; 398 : } 399 : } 400 : 401 : #if defined(_MSC_VER) 402 : #pragma warning(pop) 403 : #endif 404 : 405 : 406 12562468 : template<typename T> T EndianScalar(T t) { 407 : #if FLATBUFFERS_LITTLEENDIAN 408 12562468 : return t; 409 : #else 410 : return EndianSwap(t); 411 : #endif 412 : } 413 : 414 : template<typename T> 415 : // UBSAN: C++ aliasing type rules, see std::bit_cast<> for details. 416 : __suppress_ubsan__("alignment") 417 10286808 : T ReadScalar(const void *p) { 418 10286808 : return EndianScalar(*reinterpret_cast<const T *>(p)); 419 : } 420 : 421 : // See https://github.com/google/flatbuffers/issues/5950 422 : 423 : #if (FLATBUFFERS_GCC >= 100000) && (FLATBUFFERS_GCC < 110000) 424 : #pragma GCC diagnostic push 425 : #pragma GCC diagnostic ignored "-Wstringop-overflow" 426 : #endif 427 : 428 : template<typename T> 429 : // UBSAN: C++ aliasing type rules, see std::bit_cast<> for details. 430 : __suppress_ubsan__("alignment") 431 794511 : void WriteScalar(void *p, T t) { 432 794511 : *reinterpret_cast<T *>(p) = EndianScalar(t); 433 794511 : } 434 : 435 : template<typename T> struct Offset; 436 : template<typename T> __suppress_ubsan__("alignment") void WriteScalar(void *p, Offset<T> t) { 437 : *reinterpret_cast<uoffset_t *>(p) = EndianScalar(t.o); 438 : } 439 : 440 : #if (FLATBUFFERS_GCC >= 100000) && (FLATBUFFERS_GCC < 110000) 441 : #pragma GCC diagnostic pop 442 : #endif 443 : 444 : // Computes how many bytes you'd have to pad to be able to write an 445 : // "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in 446 : // memory). 447 : __suppress_ubsan__("unsigned-integer-overflow") 448 1195450 : inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) { 449 1195450 : return ((~buf_size) + 1) & (scalar_size - 1); 450 : } 451 : 452 : // Generic 'operator==' with conditional specialisations. 453 : // T e - new value of a scalar field. 454 : // T def - default of scalar (is known at compile-time). 455 1056035 : template<typename T> inline bool IsTheSameAs(T e, T def) { return e == def; } 456 : 457 : #if defined(FLATBUFFERS_NAN_DEFAULTS) && \ 458 : defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0) 459 : // Like `operator==(e, def)` with weak NaN if T=(float|double). 460 : template<typename T> inline bool IsFloatTheSameAs(T e, T def) { 461 : return (e == def) || ((def != def) && (e != e)); 462 : } 463 : template<> inline bool IsTheSameAs<float>(float e, float def) { 464 : return IsFloatTheSameAs(e, def); 465 : } 466 : template<> inline bool IsTheSameAs<double>(double e, double def) { 467 : return IsFloatTheSameAs(e, def); 468 : } 469 : #endif 470 : 471 : // Check 'v' is out of closed range [low; high]. 472 : // Workaround for GCC warning [-Werror=type-limits]: 473 : // comparison is always true due to limited range of data type. 474 : template<typename T> 475 : inline bool IsOutRange(const T &v, const T &low, const T &high) { 476 : return (v < low) || (high < v); 477 : } 478 : 479 : // Check 'v' is in closed range [low; high]. 480 : template<typename T> 481 : inline bool IsInRange(const T &v, const T &low, const T &high) { 482 : return !IsOutRange(v, low, high); 483 : } 484 : 485 : } // namespace flatbuffers 486 : #endif // FLATBUFFERS_BASE_H_