blob: 95b788e064f2fd30cef296c631bcce59506917b4 [file] [log] [blame]
Austin Schuhe89fa2d2019-08-14 20:24:23 -07001#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
Austin Schuh272c6132020-11-14 16:37:52 -080049#if defined(__unix__) && !defined(FLATBUFFERS_LOCALE_INDEPENDENT)
50 #include <unistd.h>
51#endif
52
Austin Schuhe89fa2d2019-08-14 20:24:23 -070053#ifdef _STLPORT_VERSION
54 #define FLATBUFFERS_CPP98_STL
55#endif
Austin Schuhe89fa2d2019-08-14 20:24:23 -070056
Austin Schuh272c6132020-11-14 16:37:52 -080057#ifdef __ANDROID__
58 #include <android/api-level.h>
59#endif
Austin Schuhe89fa2d2019-08-14 20:24:23 -070060
61#if defined(__ICCARM__)
62#include <intrinsics.h>
63#endif
64
65// Note the __clang__ check is needed, because clang presents itself
66// as an older GNUC compiler (4.2).
67// Clang 3.3 and later implement all of the ISO C++ 2011 standard.
68// Clang 3.4 and later implement all of the ISO C++ 2014 standard.
69// http://clang.llvm.org/cxx_status.html
70
71// Note the MSVC value '__cplusplus' may be incorrect:
72// The '__cplusplus' predefined macro in the MSVC stuck at the value 199711L,
73// indicating (erroneously!) that the compiler conformed to the C++98 Standard.
74// This value should be correct starting from MSVC2017-15.7-Preview-3.
75// The '__cplusplus' will be valid only if MSVC2017-15.7-P3 and the `/Zc:__cplusplus` switch is set.
76// Workaround (for details see MSDN):
77// Use the _MSC_VER and _MSVC_LANG definition instead of the __cplusplus for compatibility.
78// The _MSVC_LANG macro reports the Standard version regardless of the '/Zc:__cplusplus' switch.
79
80#if defined(__GNUC__) && !defined(__clang__)
81 #define FLATBUFFERS_GCC (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
82#else
83 #define FLATBUFFERS_GCC 0
84#endif
85
86#if defined(__clang__)
87 #define FLATBUFFERS_CLANG (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__)
88#else
89 #define FLATBUFFERS_CLANG 0
90#endif
91
92/// @cond FLATBUFFERS_INTERNAL
93#if __cplusplus <= 199711L && \
94 (!defined(_MSC_VER) || _MSC_VER < 1600) && \
95 (!defined(__GNUC__) || \
96 (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40400))
97 #error A C++11 compatible compiler with support for the auto typing is \
98 required for FlatBuffers.
99 #error __cplusplus _MSC_VER __GNUC__ __GNUC_MINOR__ __GNUC_PATCHLEVEL__
100#endif
101
102#if !defined(__clang__) && \
103 defined(__GNUC__) && \
104 (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ < 40600)
Austin Schuh272c6132020-11-14 16:37:52 -0800105 // Backwards compatibility for g++ 4.4, and 4.5 which don't have the nullptr
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700106 // and constexpr keywords. Note the __clang__ check is needed, because clang
107 // presents itself as an older GNUC compiler.
108 #ifndef nullptr_t
109 const class nullptr_t {
110 public:
111 template<class T> inline operator T*() const { return 0; }
112 private:
113 void operator&() const;
114 } nullptr = {};
115 #endif
116 #ifndef constexpr
117 #define constexpr const
118 #endif
119#endif
120
121// The wire format uses a little endian encoding (since that's efficient for
122// the common platforms).
123#if defined(__s390x__)
124 #define FLATBUFFERS_LITTLEENDIAN 0
125#endif // __s390x__
126#if !defined(FLATBUFFERS_LITTLEENDIAN)
127 #if defined(__GNUC__) || defined(__clang__) || defined(__ICCARM__)
128 #if (defined(__BIG_ENDIAN__) || \
129 (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
130 #define FLATBUFFERS_LITTLEENDIAN 0
131 #else
132 #define FLATBUFFERS_LITTLEENDIAN 1
133 #endif // __BIG_ENDIAN__
134 #elif defined(_MSC_VER)
135 #if defined(_M_PPC)
136 #define FLATBUFFERS_LITTLEENDIAN 0
137 #else
138 #define FLATBUFFERS_LITTLEENDIAN 1
139 #endif
140 #else
141 #error Unable to determine endianness, define FLATBUFFERS_LITTLEENDIAN.
142 #endif
143#endif // !defined(FLATBUFFERS_LITTLEENDIAN)
144
145#define FLATBUFFERS_VERSION_MAJOR 1
Austin Schuh272c6132020-11-14 16:37:52 -0800146#define FLATBUFFERS_VERSION_MINOR 12
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700147#define FLATBUFFERS_VERSION_REVISION 0
148#define FLATBUFFERS_STRING_EXPAND(X) #X
149#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
150namespace flatbuffers {
151 // Returns version as string "MAJOR.MINOR.REVISION".
152 const char* FLATBUFFERS_VERSION();
153}
154
155#if (!defined(_MSC_VER) || _MSC_VER > 1600) && \
156 (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 407)) || \
157 defined(__clang__)
158 #define FLATBUFFERS_FINAL_CLASS final
159 #define FLATBUFFERS_OVERRIDE override
Austin Schuh272c6132020-11-14 16:37:52 -0800160 #define FLATBUFFERS_EXPLICIT_CPP11 explicit
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700161 #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t
162#else
163 #define FLATBUFFERS_FINAL_CLASS
164 #define FLATBUFFERS_OVERRIDE
Austin Schuh272c6132020-11-14 16:37:52 -0800165 #define FLATBUFFERS_EXPLICIT_CPP11
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700166 #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE
167#endif
168
169#if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
170 (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \
171 (defined(__cpp_constexpr) && __cpp_constexpr >= 200704)
172 #define FLATBUFFERS_CONSTEXPR constexpr
Austin Schuh272c6132020-11-14 16:37:52 -0800173 #define FLATBUFFERS_CONSTEXPR_CPP11 constexpr
174 #define FLATBUFFERS_CONSTEXPR_DEFINED
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700175#else
176 #define FLATBUFFERS_CONSTEXPR const
Austin Schuh272c6132020-11-14 16:37:52 -0800177 #define FLATBUFFERS_CONSTEXPR_CPP11
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700178#endif
179
180#if (defined(__cplusplus) && __cplusplus >= 201402L) || \
181 (defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
Austin Schuh272c6132020-11-14 16:37:52 -0800182 #define FLATBUFFERS_CONSTEXPR_CPP14 FLATBUFFERS_CONSTEXPR_CPP11
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700183#else
184 #define FLATBUFFERS_CONSTEXPR_CPP14
185#endif
186
187#if (defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \
188 (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023026)) || \
189 defined(__clang__)
190 #define FLATBUFFERS_NOEXCEPT noexcept
191#else
192 #define FLATBUFFERS_NOEXCEPT
193#endif
194
195// NOTE: the FLATBUFFERS_DELETE_FUNC macro may change the access mode to
196// private, so be sure to put it at the end or reset access mode explicitly.
197#if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \
198 (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404)) || \
199 defined(__clang__)
Austin Schuh58b9b472020-11-25 19:12:44 -0800200 #define FLATBUFFERS_DEFAULT_DECLARATION
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700201 #define FLATBUFFERS_DELETE_FUNC(func) func = delete;
202#else
203 #define FLATBUFFERS_DELETE_FUNC(func) private: func;
204#endif
205
Austin Schuh272c6132020-11-14 16:37:52 -0800206// Check if we can use template aliases
207// Not possible if Microsoft Compiler before 2012
208// Possible is the language feature __cpp_alias_templates is defined well
209// Or possible if the C++ std is C+11 or newer
210#if (defined(_MSC_VER) && _MSC_VER > 1700 /* MSVC2012 */) \
211 || (defined(__cpp_alias_templates) && __cpp_alias_templates >= 200704) \
212 || (defined(__cplusplus) && __cplusplus >= 201103L)
213 #define FLATBUFFERS_TEMPLATES_ALIASES
214#endif
215
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700216#ifndef FLATBUFFERS_HAS_STRING_VIEW
217 // Only provide flatbuffers::string_view if __has_include can be used
218 // to detect a header that provides an implementation
219 #if defined(__has_include)
220 // Check for std::string_view (in c++17)
Austin Schuh272c6132020-11-14 16:37:52 -0800221 #if __has_include(<string_view>) && (__cplusplus >= 201606 || (defined(_HAS_CXX17) && _HAS_CXX17))
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700222 #include <string_view>
223 namespace flatbuffers {
224 typedef std::string_view string_view;
225 }
226 #define FLATBUFFERS_HAS_STRING_VIEW 1
227 // Check for std::experimental::string_view (in c++14, compiler-dependent)
228 #elif __has_include(<experimental/string_view>) && (__cplusplus >= 201411)
229 #include <experimental/string_view>
230 namespace flatbuffers {
231 typedef std::experimental::string_view string_view;
232 }
233 #define FLATBUFFERS_HAS_STRING_VIEW 1
Austin Schuh272c6132020-11-14 16:37:52 -0800234 // Check for absl::string_view
235 #elif __has_include("absl/strings/string_view.h")
236 #include "absl/strings/string_view.h"
237 namespace flatbuffers {
238 typedef absl::string_view string_view;
239 }
240 #define FLATBUFFERS_HAS_STRING_VIEW 1
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700241 #endif
242 #endif // __has_include
243#endif // !FLATBUFFERS_HAS_STRING_VIEW
244
245#ifndef FLATBUFFERS_HAS_NEW_STRTOD
246 // Modern (C++11) strtod and strtof functions are available for use.
247 // 1) nan/inf strings as argument of strtod;
248 // 2) hex-float as argument of strtod/strtof.
249 #if (defined(_MSC_VER) && _MSC_VER >= 1900) || \
250 (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \
251 (defined(__clang__))
252 #define FLATBUFFERS_HAS_NEW_STRTOD 1
253 #endif
254#endif // !FLATBUFFERS_HAS_NEW_STRTOD
255
256#ifndef FLATBUFFERS_LOCALE_INDEPENDENT
257 // Enable locale independent functions {strtof_l, strtod_l,strtoll_l, strtoull_l}.
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700258 #if ((defined(_MSC_VER) && _MSC_VER >= 1800) || \
Austin Schuh272c6132020-11-14 16:37:52 -0800259 (defined(_XOPEN_VERSION) && (_XOPEN_VERSION>=700)) && (!defined(__ANDROID_API__) || (defined(__ANDROID_API__) && (__ANDROID_API__>=21))))
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700260 #define FLATBUFFERS_LOCALE_INDEPENDENT 1
261 #else
262 #define FLATBUFFERS_LOCALE_INDEPENDENT 0
263 #endif
264#endif // !FLATBUFFERS_LOCALE_INDEPENDENT
265
266// Suppress Undefined Behavior Sanitizer (recoverable only). Usage:
267// - __supress_ubsan__("undefined")
268// - __supress_ubsan__("signed-integer-overflow")
Austin Schuh272c6132020-11-14 16:37:52 -0800269#if defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7))
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700270 #define __supress_ubsan__(type) __attribute__((no_sanitize(type)))
271#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
272 #define __supress_ubsan__(type) __attribute__((no_sanitize_undefined))
273#else
274 #define __supress_ubsan__(type)
275#endif
276
277// This is constexpr function used for checking compile-time constants.
278// Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`.
279template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) {
280 return !!t;
281}
282
283// Enable C++ attribute [[]] if std:c++17 or higher.
284#if ((__cplusplus >= 201703L) \
285 || (defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L)))
286 // All attributes unknown to an implementation are ignored without causing an error.
287 #define FLATBUFFERS_ATTRIBUTE(attr) [[attr]]
288
289 #define FLATBUFFERS_FALLTHROUGH() [[fallthrough]]
290#else
291 #define FLATBUFFERS_ATTRIBUTE(attr)
292
293 #if FLATBUFFERS_CLANG >= 30800
294 #define FLATBUFFERS_FALLTHROUGH() [[clang::fallthrough]]
295 #elif FLATBUFFERS_GCC >= 70300
296 #define FLATBUFFERS_FALLTHROUGH() [[gnu::fallthrough]]
297 #else
298 #define FLATBUFFERS_FALLTHROUGH()
299 #endif
300#endif
301
302/// @endcond
303
304/// @file
305namespace flatbuffers {
306
307/// @cond FLATBUFFERS_INTERNAL
308// Our default offset / size type, 32bit on purpose on 64bit systems.
309// Also, using a consistent offset type maintains compatibility of serialized
310// offset values between 32bit and 64bit systems.
311typedef uint32_t uoffset_t;
312
313// Signed offsets for references that can go in both directions.
314typedef int32_t soffset_t;
315
316// Offset/index used in v-tables, can be changed to uint8_t in
317// format forks to save a bit of space if desired.
318typedef uint16_t voffset_t;
319
320typedef uintmax_t largest_scalar_t;
321
322// In 32bits, this evaluates to 2GB - 1
Austin Schuh272c6132020-11-14 16:37:52 -0800323#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(::flatbuffers::soffset_t) * 8 - 1)) - 1)
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700324
325// We support aligning the contents of buffers up to this size.
326#define FLATBUFFERS_MAX_ALIGNMENT 16
327
328#if defined(_MSC_VER)
Austin Schuh272c6132020-11-14 16:37:52 -0800329 #pragma warning(disable: 4351) // C4351: new behavior: elements of array ... will be default initialized
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700330 #pragma warning(push)
331 #pragma warning(disable: 4127) // C4127: conditional expression is constant
332#endif
333
334template<typename T> T EndianSwap(T t) {
335 #if defined(_MSC_VER)
336 #define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
337 #define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
338 #define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
339 #elif defined(__ICCARM__)
340 #define FLATBUFFERS_BYTESWAP16 __REV16
341 #define FLATBUFFERS_BYTESWAP32 __REV
342 #define FLATBUFFERS_BYTESWAP64(x) \
343 ((__REV(static_cast<uint32_t>(x >> 32U))) | (static_cast<uint64_t>(__REV(static_cast<uint32_t>(x)))) << 32U)
344 #else
345 #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__)
346 // __builtin_bswap16 was missing prior to GCC 4.8.
347 #define FLATBUFFERS_BYTESWAP16(x) \
348 static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16))
349 #else
350 #define FLATBUFFERS_BYTESWAP16 __builtin_bswap16
351 #endif
352 #define FLATBUFFERS_BYTESWAP32 __builtin_bswap32
353 #define FLATBUFFERS_BYTESWAP64 __builtin_bswap64
354 #endif
355 if (sizeof(T) == 1) { // Compile-time if-then's.
356 return t;
357 } else if (sizeof(T) == 2) {
Austin Schuh272c6132020-11-14 16:37:52 -0800358 union { T t; uint16_t i; } u = { t };
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700359 u.i = FLATBUFFERS_BYTESWAP16(u.i);
360 return u.t;
361 } else if (sizeof(T) == 4) {
Austin Schuh272c6132020-11-14 16:37:52 -0800362 union { T t; uint32_t i; } u = { t };
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700363 u.i = FLATBUFFERS_BYTESWAP32(u.i);
364 return u.t;
365 } else if (sizeof(T) == 8) {
Austin Schuh272c6132020-11-14 16:37:52 -0800366 union { T t; uint64_t i; } u = { t };
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700367 u.i = FLATBUFFERS_BYTESWAP64(u.i);
368 return u.t;
369 } else {
370 FLATBUFFERS_ASSERT(0);
Austin Schuh272c6132020-11-14 16:37:52 -0800371 return t;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700372 }
373}
374
375#if defined(_MSC_VER)
376 #pragma warning(pop)
377#endif
378
379
380template<typename T> T EndianScalar(T t) {
381 #if FLATBUFFERS_LITTLEENDIAN
382 return t;
383 #else
384 return EndianSwap(t);
385 #endif
386}
387
388template<typename T>
389// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
390__supress_ubsan__("alignment")
391T ReadScalar(const void *p) {
392 return EndianScalar(*reinterpret_cast<const T *>(p));
393}
394
Austin Schuh272c6132020-11-14 16:37:52 -0800395// See https://github.com/google/flatbuffers/issues/5950
396
397#if (FLATBUFFERS_GCC >= 100000) && (FLATBUFFERS_GCC < 110000)
398 #pragma GCC diagnostic push
399 #pragma GCC diagnostic ignored "-Wstringop-overflow"
400#endif
401
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700402template<typename T>
403// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
404__supress_ubsan__("alignment")
405void WriteScalar(void *p, T t) {
406 *reinterpret_cast<T *>(p) = EndianScalar(t);
407}
408
409template<typename T> struct Offset;
410template<typename T> __supress_ubsan__("alignment") void WriteScalar(void *p, Offset<T> t) {
411 *reinterpret_cast<uoffset_t *>(p) = EndianScalar(t.o);
412}
413
Austin Schuh272c6132020-11-14 16:37:52 -0800414#if (FLATBUFFERS_GCC >= 100000) && (FLATBUFFERS_GCC < 110000)
415 #pragma GCC diagnostic pop
416#endif
417
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700418// Computes how many bytes you'd have to pad to be able to write an
419// "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in
420// memory).
Austin Schuh272c6132020-11-14 16:37:52 -0800421__supress_ubsan__("unsigned-integer-overflow")
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700422inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
423 return ((~buf_size) + 1) & (scalar_size - 1);
424}
425
426} // namespace flatbuffers
427#endif // FLATBUFFERS_BASE_H_