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 #ifdef _STLPORT_VERSION 50 #define FLATBUFFERS_CPP98_STL 51 #endif 52 #ifndef FLATBUFFERS_CPP98_STL 53 #include <functional> 54 #endif 55 56 #include "flatbuffers/stl_emulation.h" 57 58 // Note the __clang__ check is needed, because clang presents itself 59 // as an older GNUC compiler (4.2). 60 // Clang 3.3 and later implement all of the ISO C++ 2011 standard. 61 // Clang 3.4 and later implement all of the ISO C++ 2014 standard. 62 // http://clang.llvm.org/cxx_status.html 63 64 // Note the MSVC value '__cplusplus' may be incorrect: 65 // The '__cplusplus' predefined macro in the MSVC stuck at the value 199711L, 66 // indicating (erroneously!) that the compiler conformed to the C++98 Standard. 67 // This value should be correct starting from MSVC2017-15.7-Preview-3. 68 // The '__cplusplus' will be valid only if MSVC2017-15.7-P3 and the `/Zc:__cplusplus` switch is set. 69 // Workaround (for details see MSDN): 70 // Use the _MSC_VER and _MSVC_LANG definition instead of the __cplusplus for compatibility. 71 // The _MSVC_LANG macro reports the Standard version regardless of the '/Zc:__cplusplus' switch. 72 73 #if defined(__GNUC__) && !defined(__clang__) 74 #define FLATBUFFERS_GCC (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) 75 #else 76 #define FLATBUFFERS_GCC 0 77 #endif 78 79 #if defined(__clang__) 80 #define FLATBUFFERS_CLANG (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) 81 #else 82 #define FLATBUFFERS_CLANG 0 83 #endif 84 85 /// @cond FLATBUFFERS_INTERNAL 86 #if __cplusplus <= 199711L && \ 87 (!defined(_MSC_VER) || _MSC_VER < 1600) && \ 88 (!defined(__GNUC__) || \ 89 (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400)) 90 #error A C++11 compatible compiler with support for the auto typing is \ 91 required for FlatBuffers. 92 #error __cplusplus _MSC_VER __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__ 93 #endif 94 95 #if !defined(__clang__) && \ 96 defined(__GNUC__) && \ 97 (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600) 98 // Backwards compatability for g++ 4.4, and 4.5 which don't have the nullptr 99 // and constexpr keywords. Note the __clang__ check is needed, because clang 100 // presents itself as an older GNUC compiler. 101 #ifndef nullptr_t 102 const class nullptr_t { 103 public: 104 template<class T> inline operator T*() const { return 0; } 105 private: 106 void operator&() const; 107 } nullptr = {}; 108 #endif 109 #ifndef constexpr 110 #define constexpr const 111 #endif 112 #endif 113 114 // The wire format uses a little endian encoding (since that's efficient for 115 // the common platforms). 116 #if defined(__s390x__) 117 #define FLATBUFFERS_LITTLEENDIAN 0 118 #endif // __s390x__ 119 #if !defined(FLATBUFFERS_LITTLEENDIAN) 120 #if defined(__GNUC__) || defined(__clang__) 121 #if (defined(__BIG_ENDIAN__) || \ 122 (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) 123 #define FLATBUFFERS_LITTLEENDIAN 0 124 #else 125 #define FLATBUFFERS_LITTLEENDIAN 1 126 #endif // __BIG_ENDIAN__ 127 #elif defined(_MSC_VER) 128 #if defined(_M_PPC) 129 #define FLATBUFFERS_LITTLEENDIAN 0 130 #else 131 #define FLATBUFFERS_LITTLEENDIAN 1 132 #endif 133 #else 134 #error Unable to determine endianness, define FLATBUFFERS_LITTLEENDIAN. 135 #endif 136 #endif // !defined(FLATBUFFERS_LITTLEENDIAN) 137 138 #define FLATBUFFERS_VERSION_MAJOR 1 139 #define FLATBUFFERS_VERSION_MINOR 10 140 #define FLATBUFFERS_VERSION_REVISION 0 141 #define FLATBUFFERS_STRING_EXPAND(X) #X 142 #define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X) 143 144 #if (!defined(_MSC_VER) || _MSC_VER > 1600) && \ 145 (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407)) || \ 146 defined(__clang__) 147 #define FLATBUFFERS_FINAL_CLASS final 148 #define FLATBUFFERS_OVERRIDE override 149 #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t 150 #else 151 #define FLATBUFFERS_FINAL_CLASS 152 #define FLATBUFFERS_OVERRIDE 153 #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE 154 #endif 155 156 #if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \ 157 (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \ 158 (defined(__cpp_constexpr) && __cpp_constexpr >= 200704) 159 #define FLATBUFFERS_CONSTEXPR constexpr 160 #else 161 #define FLATBUFFERS_CONSTEXPR const 162 #endif 163 164 #if (defined(__cplusplus) && __cplusplus >= 201402L) || \ 165 (defined(__cpp_constexpr) && __cpp_constexpr >= 201304) 166 #define FLATBUFFERS_CONSTEXPR_CPP14 FLATBUFFERS_CONSTEXPR 167 #else 168 #define FLATBUFFERS_CONSTEXPR_CPP14 169 #endif 170 171 #if (defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \ 172 (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023026)) || \ 173 defined(__clang__) 174 #define FLATBUFFERS_NOEXCEPT noexcept 175 #else 176 #define FLATBUFFERS_NOEXCEPT 177 #endif 178 179 // NOTE: the FLATBUFFERS_DELETE_FUNC macro may change the access mode to 180 // private, so be sure to put it at the end or reset access mode explicitly. 181 #if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \ 182 (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404)) || \ 183 defined(__clang__) 184 #define FLATBUFFERS_DELETE_FUNC(func) func = delete; 185 #else 186 #define FLATBUFFERS_DELETE_FUNC(func) private: func; 187 #endif 188 189 #ifndef FLATBUFFERS_HAS_STRING_VIEW 190 // Only provide flatbuffers::string_view if __has_include can be used 191 // to detect a header that provides an implementation 192 #if defined(__has_include) 193 // Check for std::string_view (in c++17) 194 #if __has_include(<string_view>) && (__cplusplus >= 201606 || _HAS_CXX17) 195 #include <string_view> 196 namespace flatbuffers { 197 typedef std::string_view string_view; 198 } 199 #define FLATBUFFERS_HAS_STRING_VIEW 1 200 // Check for std::experimental::string_view (in c++14, compiler-dependent) 201 #elif __has_include(<experimental/string_view>) && (__cplusplus >= 201411) 202 #include <experimental/string_view> 203 namespace flatbuffers { 204 typedef std::experimental::string_view string_view; 205 } 206 #define FLATBUFFERS_HAS_STRING_VIEW 1 207 #endif 208 #endif // __has_include 209 #endif // !FLATBUFFERS_HAS_STRING_VIEW 210 211 #ifndef FLATBUFFERS_HAS_NEW_STRTOD 212 // Modern (C++11) strtod and strtof functions are available for use. 213 // 1) nan/inf strings as argument of strtod; 214 // 2) hex-float as argument of strtod/strtof. 215 #if (defined(_MSC_VER) && _MSC_VER >= 1900) || \ 216 (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \ 217 (defined(__clang__)) 218 #define FLATBUFFERS_HAS_NEW_STRTOD 1 219 #endif 220 #endif // !FLATBUFFERS_HAS_NEW_STRTOD 221 222 #ifndef FLATBUFFERS_LOCALE_INDEPENDENT 223 // Enable locale independent functions {strtof_l, strtod_l,strtoll_l, strtoull_l}. 224 // They are part of the POSIX-2008 but not part of the C/C++ standard. 225 // GCC/Clang have definition (_XOPEN_SOURCE>=700) if POSIX-2008. 226 #if ((defined(_MSC_VER) && _MSC_VER >= 1800) || \ 227 (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE>=700))) 228 #define FLATBUFFERS_LOCALE_INDEPENDENT 1 229 #else 230 #define FLATBUFFERS_LOCALE_INDEPENDENT 0 231 #endif 232 #endif // !FLATBUFFERS_LOCALE_INDEPENDENT 233 234 // Suppress Undefined Behavior Sanitizer (recoverable only). Usage: 235 // - __supress_ubsan__("undefined") 236 // - __supress_ubsan__("signed-integer-overflow") 237 #if defined(__clang__) 238 #define __supress_ubsan__(type) __attribute__((no_sanitize(type))) 239 #elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409) 240 #define __supress_ubsan__(type) __attribute__((no_sanitize_undefined)) 241 #else 242 #define __supress_ubsan__(type) 243 #endif 244 245 // This is constexpr function used for checking compile-time constants. 246 // Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`. 247 template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) { 248 return !!t; 249 } 250 251 // Enable C++ attribute [[]] if std:c++17 or higher. 252 #if ((__cplusplus >= 201703L) \ 253 || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L))) 254 // All attributes unknown to an implementation are ignored without causing an error. 255 #define FLATBUFFERS_ATTRIBUTE(attr) [[attr]] 256 257 #define FLATBUFFERS_FALLTHROUGH() [[fallthrough]] 258 #else 259 #define FLATBUFFERS_ATTRIBUTE(attr) 260 261 #if FLATBUFFERS_CLANG >= 30800 262 #define FLATBUFFERS_FALLTHROUGH() [[clang::fallthrough]] 263 #elif FLATBUFFERS_GCC >= 70300 264 #define FLATBUFFERS_FALLTHROUGH() [[gnu::fallthrough]] 265 #else 266 #define FLATBUFFERS_FALLTHROUGH() 267 #endif 268 #endif 269 270 /// @endcond 271 272 /// @file 273 namespace flatbuffers { 274 275 /// @cond FLATBUFFERS_INTERNAL 276 // Our default offset / size type, 32bit on purpose on 64bit systems. 277 // Also, using a consistent offset type maintains compatibility of serialized 278 // offset values between 32bit and 64bit systems. 279 typedef uint32_t uoffset_t; 280 281 // Signed offsets for references that can go in both directions. 282 typedef int32_t soffset_t; 283 284 // Offset/index used in v-tables, can be changed to uint8_t in 285 // format forks to save a bit of space if desired. 286 typedef uint16_t voffset_t; 287 288 typedef uintmax_t largest_scalar_t; 289 290 // In 32bits, this evaluates to 2GB - 1 291 #define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(soffset_t) * 8 - 1)) - 1) 292 293 // We support aligning the contents of buffers up to this size. 294 #define FLATBUFFERS_MAX_ALIGNMENT 16 295 296 #if defined(_MSC_VER) 297 #pragma warning(push) 298 #pragma warning(disable: 4127) // C4127: conditional expression is constant 299 #endif 300 301 template<typename T> T EndianSwap(T t) { 302 #if defined(_MSC_VER) 303 #define FLATBUFFERS_BYTESWAP16 _byteswap_ushort 304 #define FLATBUFFERS_BYTESWAP32 _byteswap_ulong 305 #define FLATBUFFERS_BYTESWAP64 _byteswap_uint64 306 #else 307 #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__) 308 // __builtin_bswap16 was missing prior to GCC 4.8. 309 #define FLATBUFFERS_BYTESWAP16(x) \ 310 static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16)) 311 #else 312 #define FLATBUFFERS_BYTESWAP16 __builtin_bswap16 313 #endif 314 #define FLATBUFFERS_BYTESWAP32 __builtin_bswap32 315 #define FLATBUFFERS_BYTESWAP64 __builtin_bswap64 316 #endif 317 if (sizeof(T) == 1) { // Compile-time if-then's. 318 return t; 319 } else if (sizeof(T) == 2) { 320 union { T t; uint16_t i; } u; 321 u.t = t; 322 u.i = FLATBUFFERS_BYTESWAP16(u.i); 323 return u.t; 324 } else if (sizeof(T) == 4) { 325 union { T t; uint32_t i; } u; 326 u.t = t; 327 u.i = FLATBUFFERS_BYTESWAP32(u.i); 328 return u.t; 329 } else if (sizeof(T) == 8) { 330 union { T t; uint64_t i; } u; 331 u.t = t; 332 u.i = FLATBUFFERS_BYTESWAP64(u.i); 333 return u.t; 334 } else { 335 FLATBUFFERS_ASSERT(0); 336 } 337 } 338 339 #if defined(_MSC_VER) 340 #pragma warning(pop) 341 #endif 342 343 344 template<typename T> T EndianScalar(T t) { 345 #if FLATBUFFERS_LITTLEENDIAN 346 return t; 347 #else 348 return EndianSwap(t); 349 #endif 350 } 351 352 template<typename T> 353 // UBSAN: C++ aliasing type rules, see std::bit_cast<> for details. 354 __supress_ubsan__("alignment") 355 T ReadScalar(const void *p) { 356 return EndianScalar(*reinterpret_cast<const T *>(p)); 357 } 358 359 template<typename T> 360 // UBSAN: C++ aliasing type rules, see std::bit_cast<> for details. 361 __supress_ubsan__("alignment") 362 void WriteScalar(void *p, T t) { 363 *reinterpret_cast<T *>(p) = EndianScalar(t); 364 } 365 366 template<typename T> struct Offset; 367 template<typename T> __supress_ubsan__("alignment") void WriteScalar(void *p, Offset<T> t) { 368 *reinterpret_cast<uoffset_t *>(p) = EndianScalar(t.o); 369 } 370 371 // Computes how many bytes you'd have to pad to be able to write an 372 // "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in 373 // memory). 374 inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) { 375 return ((~buf_size) + 1) & (scalar_size - 1); 376 } 377 378 } // namespace flatbuffers 379 #endif // FLATBUFFERS_BASE_H_ 380