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