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 <type_traits>
42 #include <vector>
43 #include <algorithm>
44 #include <iterator>
45 
46 #ifndef FLATBUFFERS_CHRE
47 #include <memory>
48 #include <set>
49 #include <string>
50 #endif
51 
52 #ifdef _STLPORT_VERSION
53   #define FLATBUFFERS_CPP98_STL
54 #endif
55 #if !defined(FLATBUFFERS_CPP98_STL) && !defined(FLATBUFFERS_CHRE)
56   #include <functional>
57 #endif
58 
59 #include "flatbuffers/stl_emulation.h"
60 
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)
105   // Backwards compatibility for g++ 4.4, and 4.5 which don't have the nullptr
106   // 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
146 #define FLATBUFFERS_VERSION_MINOR 12
147 #define FLATBUFFERS_VERSION_REVISION 0
148 #define FLATBUFFERS_STRING_EXPAND(X) #X
149 #define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
150 namespace 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
160   #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t
161 #else
162   #define FLATBUFFERS_FINAL_CLASS
163   #define FLATBUFFERS_OVERRIDE
164   #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE
165 #endif
166 
167 #if (!defined(_MSC_VER) || _MSC_VER >= 1900) && \
168     (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \
169     (defined(__cpp_constexpr) && __cpp_constexpr >= 200704)
170   #define FLATBUFFERS_CONSTEXPR constexpr
171 #else
172   #define FLATBUFFERS_CONSTEXPR const
173 #endif
174 
175 #if (defined(__cplusplus) && __cplusplus >= 201402L) || \
176     (defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
177   #define FLATBUFFERS_CONSTEXPR_CPP14 FLATBUFFERS_CONSTEXPR
178 #else
179   #define FLATBUFFERS_CONSTEXPR_CPP14
180 #endif
181 
182 #if (defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406)) || \
183     (defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 190023026)) || \
184     defined(__clang__)
185   #define FLATBUFFERS_NOEXCEPT noexcept
186 #else
187   #define FLATBUFFERS_NOEXCEPT
188 #endif
189 
190 // NOTE: the FLATBUFFERS_DELETE_FUNC macro may change the access mode to
191 // private, so be sure to put it at the end or reset access mode explicitly.
192 #if (!defined(_MSC_VER) || _MSC_FULL_VER >= 180020827) && \
193     (!defined(__GNUC__) || (__GNUC__ * 100 + __GNUC_MINOR__ >= 404)) || \
194     defined(__clang__)
195   #define FLATBUFFERS_DELETE_FUNC(func) func = delete;
196 #else
197   #define FLATBUFFERS_DELETE_FUNC(func) private: func;
198 #endif
199 
200 #ifndef FLATBUFFERS_HAS_STRING_VIEW
201   // Only provide flatbuffers::string_view if __has_include can be used
202   // to detect a header that provides an implementation
203   #if defined(__has_include)
204     // Check for std::string_view (in c++17)
205     #if __has_include(<string_view>) && (__cplusplus >= 201606 || (defined(_HAS_CXX17) && _HAS_CXX17))
206       #include <string_view>
207       namespace flatbuffers {
208         typedef std::string_view string_view;
209       }
210       #define FLATBUFFERS_HAS_STRING_VIEW 1
211     // Check for std::experimental::string_view (in c++14, compiler-dependent)
212     #elif __has_include(<experimental/string_view>) && (__cplusplus >= 201411)
213       #include <experimental/string_view>
214       namespace flatbuffers {
215         typedef std::experimental::string_view string_view;
216       }
217       #define FLATBUFFERS_HAS_STRING_VIEW 1
218     // Check for absl::string_view
219     #elif __has_include("absl/strings/string_view.h")
220       #include "absl/strings/string_view.h"
221       namespace flatbuffers {
222         typedef absl::string_view string_view;
223       }
224       #define FLATBUFFERS_HAS_STRING_VIEW 1
225     #endif
226   #endif // __has_include
227 #endif // !FLATBUFFERS_HAS_STRING_VIEW
228 
229 #ifndef FLATBUFFERS_HAS_NEW_STRTOD
230   // Modern (C++11) strtod and strtof functions are available for use.
231   // 1) nan/inf strings as argument of strtod;
232   // 2) hex-float  as argument of  strtod/strtof.
233   #if (defined(_MSC_VER) && _MSC_VER >= 1900) || \
234       (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)) || \
235       (defined(__clang__))
236     #define FLATBUFFERS_HAS_NEW_STRTOD 1
237   #endif
238 #endif // !FLATBUFFERS_HAS_NEW_STRTOD
239 
240 #ifndef FLATBUFFERS_LOCALE_INDEPENDENT
241   // Enable locale independent functions {strtof_l, strtod_l,strtoll_l, strtoull_l}.
242   // They are part of the POSIX-2008 but not part of the C/C++ standard.
243   // GCC/Clang have definition (_XOPEN_SOURCE>=700) if POSIX-2008.
244   #if ((defined(_MSC_VER) && _MSC_VER >= 1800)            || \
245        (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE>=700)))
246     #define FLATBUFFERS_LOCALE_INDEPENDENT 1
247   #else
248     #define FLATBUFFERS_LOCALE_INDEPENDENT 0
249   #endif
250 #endif  // !FLATBUFFERS_LOCALE_INDEPENDENT
251 
252 // Suppress Undefined Behavior Sanitizer (recoverable only). Usage:
253 // - __supress_ubsan__("undefined")
254 // - __supress_ubsan__("signed-integer-overflow")
255 #if defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7))
256   #define __supress_ubsan__(type) __attribute__((no_sanitize(type)))
257 #elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
258   #define __supress_ubsan__(type) __attribute__((no_sanitize_undefined))
259 #else
260   #define __supress_ubsan__(type)
261 #endif
262 
263 // This is constexpr function used for checking compile-time constants.
264 // Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`.
IsConstTrue(T t)265 template<typename T> FLATBUFFERS_CONSTEXPR inline bool IsConstTrue(T t) {
266   return !!t;
267 }
268 
269 // Enable C++ attribute [[]] if std:c++17 or higher.
270 #if ((__cplusplus >= 201703L) \
271     || (defined(_MSVC_LANG) &&  (_MSVC_LANG >= 201703L)))
272   // All attributes unknown to an implementation are ignored without causing an error.
273   #define FLATBUFFERS_ATTRIBUTE(attr) [[attr]]
274 
275   #define FLATBUFFERS_FALLTHROUGH() [[fallthrough]]
276 #else
277   #define FLATBUFFERS_ATTRIBUTE(attr)
278 
279   #if FLATBUFFERS_CLANG >= 30800
280     #define FLATBUFFERS_FALLTHROUGH() [[clang::fallthrough]]
281   #elif FLATBUFFERS_GCC >= 70300
282     #define FLATBUFFERS_FALLTHROUGH() [[gnu::fallthrough]]
283   #else
284     #define FLATBUFFERS_FALLTHROUGH()
285   #endif
286 #endif
287 
288 /// @endcond
289 
290 /// @file
291 namespace flatbuffers {
292 
293 /// @cond FLATBUFFERS_INTERNAL
294 // Our default offset / size type, 32bit on purpose on 64bit systems.
295 // Also, using a consistent offset type maintains compatibility of serialized
296 // offset values between 32bit and 64bit systems.
297 typedef uint32_t uoffset_t;
298 
299 // Signed offsets for references that can go in both directions.
300 typedef int32_t soffset_t;
301 
302 // Offset/index used in v-tables, can be changed to uint8_t in
303 // format forks to save a bit of space if desired.
304 typedef uint16_t voffset_t;
305 
306 typedef uintmax_t largest_scalar_t;
307 
308 // In 32bits, this evaluates to 2GB - 1
309 #define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(::flatbuffers::soffset_t) * 8 - 1)) - 1)
310 
311 // We support aligning the contents of buffers up to this size.
312 #define FLATBUFFERS_MAX_ALIGNMENT 16
313 
314 #if defined(_MSC_VER)
315   #pragma warning(push)
316   #pragma warning(disable: 4127) // C4127: conditional expression is constant
317 #endif
318 
EndianSwap(T t)319 template<typename T> T EndianSwap(T t) {
320   #if defined(_MSC_VER)
321     #define FLATBUFFERS_BYTESWAP16 _byteswap_ushort
322     #define FLATBUFFERS_BYTESWAP32 _byteswap_ulong
323     #define FLATBUFFERS_BYTESWAP64 _byteswap_uint64
324   #elif defined(__ICCARM__)
325     #define FLATBUFFERS_BYTESWAP16 __REV16
326     #define FLATBUFFERS_BYTESWAP32 __REV
327     #define FLATBUFFERS_BYTESWAP64(x) \
328        ((__REV(static_cast<uint32_t>(x >> 32U))) | (static_cast<uint64_t>(__REV(static_cast<uint32_t>(x)))) << 32U)
329   #else
330     #if defined(__GNUC__) && __GNUC__ * 100 + __GNUC_MINOR__ < 408 && !defined(__clang__)
331       // __builtin_bswap16 was missing prior to GCC 4.8.
332       #define FLATBUFFERS_BYTESWAP16(x) \
333         static_cast<uint16_t>(__builtin_bswap32(static_cast<uint32_t>(x) << 16))
334     #else
335       #define FLATBUFFERS_BYTESWAP16 __builtin_bswap16
336     #endif
337     #define FLATBUFFERS_BYTESWAP32 __builtin_bswap32
338     #define FLATBUFFERS_BYTESWAP64 __builtin_bswap64
339   #endif
340   if (sizeof(T) == 1) {   // Compile-time if-then's.
341     return t;
342   } else if (sizeof(T) == 2) {
343     union { T t; uint16_t i; } u = { t };
344     u.i = FLATBUFFERS_BYTESWAP16(u.i);
345     return u.t;
346   } else if (sizeof(T) == 4) {
347     union { T t; uint32_t i; } u = { t };
348     u.i = FLATBUFFERS_BYTESWAP32(u.i);
349     return u.t;
350   } else if (sizeof(T) == 8) {
351     union { T t; uint64_t i; } u = { t };
352     u.i = FLATBUFFERS_BYTESWAP64(u.i);
353     return u.t;
354   } else {
355     FLATBUFFERS_ASSERT(0);
356     return t;
357   }
358 }
359 
360 #if defined(_MSC_VER)
361   #pragma warning(pop)
362 #endif
363 
364 
EndianScalar(T t)365 template<typename T> T EndianScalar(T t) {
366   #if FLATBUFFERS_LITTLEENDIAN
367     return t;
368   #else
369     return EndianSwap(t);
370   #endif
371 }
372 
373 template<typename T>
374 // UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
375 __supress_ubsan__("alignment")
ReadScalar(const void * p)376 T ReadScalar(const void *p) {
377   return EndianScalar(*reinterpret_cast<const T *>(p));
378 }
379 
380 template<typename T>
381 // UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
382 __supress_ubsan__("alignment")
WriteScalar(void * p,T t)383 void WriteScalar(void *p, T t) {
384   *reinterpret_cast<T *>(p) = EndianScalar(t);
385 }
386 
387 template<typename T> struct Offset;
WriteScalar(void * p,Offset<T> t)388 template<typename T> __supress_ubsan__("alignment") void WriteScalar(void *p, Offset<T> t) {
389   *reinterpret_cast<uoffset_t *>(p) = EndianScalar(t.o);
390 }
391 
392 // Computes how many bytes you'd have to pad to be able to write an
393 // "scalar_size" scalar if the buffer had grown to "buf_size" (downwards in
394 // memory).
395 __supress_ubsan__("unsigned-integer-overflow")
PaddingBytes(size_t buf_size,size_t scalar_size)396 inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
397   return ((~buf_size) + 1) & (scalar_size - 1);
398 }
399 
400 }  // namespace flatbuffers
401 #endif  // FLATBUFFERS_BASE_H_
402