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 6 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 : __has_include("absl/base/config.h") && \ 238 : (__cplusplus >= 201411) 239 : #include "absl/base/config.h" 240 : #if !defined(ABSL_USES_STD_STRING_VIEW) 241 : #include "absl/strings/string_view.h" 242 : namespace flatbuffers { 243 : typedef absl::string_view string_view; 244 : } 245 : #define FLATBUFFERS_HAS_STRING_VIEW 1 246 : #endif 247 : #endif 248 : #endif // __has_include 249 : #endif // !FLATBUFFERS_HAS_STRING_VIEW 250 : 251 : #ifndef FLATBUFFERS_GENERAL_HEAP_ALLOC_OK 252 : // Allow heap allocations to be used 253 : #define FLATBUFFERS_GENERAL_HEAP_ALLOC_OK 1 254 : #endif // !FLATBUFFERS_GENERAL_HEAP_ALLOC_OK 255 : 256 : #ifndef FLATBUFFERS_HAS_NEW_STRTOD 257 : // Modern (C++11) strtod and strtof functions are available for use. 258 : // 1) nan/inf strings as argument of strtod; 259 : // 2) hex-float as argument of strtod/strtof. 260 : #if (defined(_MSC_VER) && _MSC_VER >= 1900) || \ 261 : (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \ 262 : (defined(__clang__)) 263 : #define FLATBUFFERS_HAS_NEW_STRTOD 1 264 : #endif 265 : #endif // !FLATBUFFERS_HAS_NEW_STRTOD 266 : 267 : #ifndef FLATBUFFERS_LOCALE_INDEPENDENT 268 : // Enable locale independent functions {strtof_l, strtod_l,strtoll_l, strtoull_l}. 269 : #if ((defined(_MSC_VER) && _MSC_VER >= 1800) || \ 270 : (defined(_XOPEN_VERSION) && (_XOPEN_VERSION>=700)) && (!defined(__ANDROID_API__) || (defined(__ANDROID_API__) && (__ANDROID_API__>=21)))) 271 : #define FLATBUFFERS_LOCALE_INDEPENDENT 1 272 : #else 273 : #define FLATBUFFERS_LOCALE_INDEPENDENT 0 274 : #endif 275 : #endif // !FLATBUFFERS_LOCALE_INDEPENDENT 276 : 277 : // Suppress Undefined Behavior Sanitizer (recoverable only). Usage: 278 : // - __supress_ubsan__("undefined") 279 : // - __supress_ubsan__("signed-integer-overflow") 280 : #if defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7)) 281 : #define __supress_ubsan__(type) __attribute__((no_sanitize(type))) 282 : #elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409) 283 : #define __supress_ubsan__(type) __attribute__((no_sanitize_undefined)) 284 : #else 285 : #define __supress_ubsan__(type) 286 : #endif 287 : 288 : // This is constexpr function used for checking compile-time constants. 289 : // Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`. 290 : template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) { 291 : return !!t; 292 : } 293 : 294 : // Enable C++ attribute [[]] if std:c++17 or higher. 295 : #if ((__cplusplus >= 201703L) \ 296 : || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L))) 297 : // All attributes unknown to an implementation are ignored without causing an error. 298 : #define FLATBUFFERS_ATTRIBUTE(attr) attr 299 : 300 : #define FLATBUFFERS_FALLTHROUGH() [[fallthrough]] 301 : #else 302 : #define FLATBUFFERS_ATTRIBUTE(attr) 303 : 304 : #if FLATBUFFERS_CLANG >= 30800 305 : #define FLATBUFFERS_FALLTHROUGH() [[clang::fallthrough]] 306 : #elif FLATBUFFERS_GCC >= 70300 307 : #define FLATBUFFERS_FALLTHROUGH() [[gnu::fallthrough]] 308 : #else 309 : #define FLATBUFFERS_FALLTHROUGH() 310 : #endif 311 : #endif 312 : 313 : /// @endcond 314 : 315 : /// @file 316 : namespace flatbuffers { 317 : 318 : /// @cond FLATBUFFERS_INTERNAL 319 : // Our default offset / size type, 32bit on purpose on 64bit systems. 320 : // Also, using a consistent offset type maintains compatibility of serialized 321 : // offset values between 32bit and 64bit systems. 322 : typedef uint32_t uoffset_t; 323 : 324 : // Signed offsets for references that can go in both directions. 325 : typedef int32_t soffset_t; 326 : 327 : // Offset/index used in v-tables, can be changed to uint8_t in 328 : // format forks to save a bit of space if desired. 329 : typedef uint16_t voffset_t; 330 : 331 : typedef uintmax_t largest_scalar_t; 332 : 333 : // In 32bits, this evaluates to 2GB - 1 334 : #define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(::flatbuffers::soffset_t) * 8 - 1)) - 1) 335 : 336 : // We support aligning the contents of buffers up to this size. 337 : #ifndef FLATBUFFERS_MAX_ALIGNMENT 338 : #define FLATBUFFERS_MAX_ALIGNMENT 32 339 : #endif 340 : 341 : /// @brief The length of a FlatBuffer file header. 342 : static const size_t kFileIdentifierLength = 4; 343 : 344 : inline bool VerifyAlignmentRequirements(size_t align, size_t min_align = 1) { 345 : return (min_align <= align) && (align <= (FLATBUFFERS_MAX_ALIGNMENT)) && 346 : (align & (align - 1)) == 0; // must be power of 2 347 : } 348 : 349 : #if defined(_MSC_VER) 350 : #pragma warning(disable: 4351) // C4351: new behavior: elements of array ... will be default initialized 351 : #pragma warning(push) 352 : #pragma warning(disable: 4127) // C4127: conditional expression is constant 353 : #endif 354 : 355 : template<typename T> T EndianSwap(T t) { 356 : #if defined(_MSC_VER) 357 : #define FLATBUFFERS_BYTESWAP16 _byteswap_ushort 358 : #define FLATBUFFERS_BYTESWAP32 _byteswap_ulong 359 : #define FLATBUFFERS_BYTESWAP64 _byteswap_uint64 360 : #elif defined(__ICCARM__) 361 : #define FLATBUFFERS_BYTESWAP16 __REV16 362 : #define FLATBUFFERS_BYTESWAP32 __REV 363 : #define FLATBUFFERS_BYTESWAP64(x) \ 364 : ((__REV(static_cast<uint32_t>(x >> 32U))) | (static_cast<uint64_t>(__REV(static_cast<uint32_t>(x)))) << 32U) 365 : #else 366 : #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__) 367 : // __builtin_bswap16 was missing prior to GCC 4.8. 368 : #define FLATBUFFERS_BYTESWAP16(x) \ 369 : static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16)) 370 : #else 371 : #define FLATBUFFERS_BYTESWAP16 __builtin_bswap16 372 : #endif 373 : #define FLATBUFFERS_BYTESWAP32 __builtin_bswap32 374 : #define FLATBUFFERS_BYTESWAP64 __builtin_bswap64 375 : #endif 376 : if (sizeof(T) == 1) { // Compile-time if-then's. 377 : return t; 378 : } else if (sizeof(T) == 2) { 379 : union { T t; uint16_t i; } u = { t }; 380 : u.i = FLATBUFFERS_BYTESWAP16(u.i); 381 : return u.t; 382 : } else if (sizeof(T) == 4) { 383 : union { T t; uint32_t i; } u = { t }; 384 : u.i = FLATBUFFERS_BYTESWAP32(u.i); 385 : return u.t; 386 : } else if (sizeof(T) == 8) { 387 : union { T t; uint64_t i; } u = { t }; 388 : u.i = FLATBUFFERS_BYTESWAP64(u.i); 389 : return u.t; 390 : } else { 391 : FLATBUFFERS_ASSERT(0); 392 : return t; 393 : } 394 : } 395 : 396 : #if defined(_MSC_VER) 397 : #pragma warning(pop) 398 : #endif 399 : 400 : 401 8729283 : template<typename T> T EndianScalar(T t) { 402 : #if FLATBUFFERS_LITTLEENDIAN 403 8729283 : return t; 404 : #else 405 : return EndianSwap(t); 406 : #endif 407 : } 408 : 409 : template<typename T> 410 : // UBSAN: C++ aliasing type rules, see std::bit_cast<> for details. 411 : __supress_ubsan__("alignment") 412 6738424 : T ReadScalar(const void *p) { 413 6738424 : return EndianScalar(*reinterpret_cast<const T *>(p)); 414 : } 415 : 416 : // See https://github.com/google/flatbuffers/issues/5950 417 : 418 : #if (FLATBUFFERS_GCC >= 100000) && (FLATBUFFERS_GCC < 110000) 419 : #pragma GCC diagnostic push 420 : #pragma GCC diagnostic ignored "-Wstringop-overflow" 421 : #endif 422 : 423 : template<typename T> 424 : // UBSAN: C++ aliasing type rules, see std::bit_cast<> for details. 425 : __supress_ubsan__("alignment") 426 793751 : void WriteScalar(void *p, T t) { 427 793751 : *reinterpret_cast<T *>(p) = EndianScalar(t); 428 793751 : } 429 : 430 : template<typename T> struct Offset; 431 : template<typename T> __supress_ubsan__("alignment") void WriteScalar(void *p, Offset<T> t) { 432 : *reinterpret_cast<uoffset_t *>(p) = EndianScalar(t.o); 433 : } 434 : 435 : #if (FLATBUFFERS_GCC >= 100000) && (FLATBUFFERS_GCC < 110000) 436 : #pragma GCC diagnostic pop 437 : #endif 438 : 439 : // Computes how many bytes you'd have to pad to be able to write an 440 : // "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in 441 : // memory). 442 : __supress_ubsan__("unsigned-integer-overflow") 443 1194030 : inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) { 444 1194030 : return ((~buf_size) + 1) & (scalar_size - 1); 445 : } 446 : 447 : // Generic 'operator==' with conditional specialisations. 448 : // T e - new value of a scalar field. 449 : // T def - default of scalar (is known at compile-time). 450 1055420 : template<typename T> inline bool IsTheSameAs(T e, T def) { return e == def; } 451 : 452 : #if defined(FLATBUFFERS_NAN_DEFAULTS) && \ 453 : defined(FLATBUFFERS_HAS_NEW_STRTOD) && (FLATBUFFERS_HAS_NEW_STRTOD > 0) 454 : // Like `operator==(e, def)` with weak NaN if T=(float|double). 455 : template<typename T> inline bool IsFloatTheSameAs(T e, T def) { 456 : return (e == def) || ((def != def) && (e != e)); 457 : } 458 : template<> inline bool IsTheSameAs<float>(float e, float def) { 459 : return IsFloatTheSameAs(e, def); 460 : } 461 : template<> inline bool IsTheSameAs<double>(double e, double def) { 462 : return IsFloatTheSameAs(e, def); 463 : } 464 : #endif 465 : 466 : // Check 'v' is out of closed range [low; high]. 467 : // Workaround for GCC warning [-Werror=type-limits]: 468 : // comparison is always true due to limited range of data type. 469 : template<typename T> 470 : inline bool IsOutRange(const T &v, const T &low, const T &high) { 471 : return (v < low) || (high < v); 472 : } 473 : 474 : // Check 'v' is in closed range [low; high]. 475 : template<typename T> 476 : inline bool IsInRange(const T &v, const T &low, const T &high) { 477 : return !IsOutRange(v, low, high); 478 : } 479 : 480 : } // namespace flatbuffers 481 : #endif // FLATBUFFERS_BASE_H_