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