Home | History | Annotate | Download | only in flatbuffers
      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