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