base.h 14 KB

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