blob: 1a5ae76772dd7f3c40564e19748400166b9d9d22 [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
James Kuszmaul3b15b0c2022-11-08 14:03:16 -080035#if defined(ARDUINO) && !defined(ARDUINOSTL_M_H) && defined(__AVR__)
Austin Schuhe89fa2d2019-08-14 20:24:23 -070036 #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 Schuh272c6132020-11-14 16:37:52 -080053#ifdef __ANDROID__
54 #include <android/api-level.h>
55#endif
Austin Schuhe89fa2d2019-08-14 20:24:23 -070056
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)
Austin Schuh272c6132020-11-14 16:37:52 -0800101 // Backwards compatibility for g++ 4.4, and 4.5 which don't have the nullptr
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700102 // 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
James Kuszmaul3b15b0c2022-11-08 14:03:16 -0800141#define FLATBUFFERS_VERSION_MAJOR 22
142#define FLATBUFFERS_VERSION_MINOR 10
143#define FLATBUFFERS_VERSION_REVISION 26
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700144#define FLATBUFFERS_STRING_EXPAND(X) #X
145#define FLATBUFFERS_STRING(X) FLATBUFFERS_STRING_EXPAND(X)
146namespace 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
Austin Schuh272c6132020-11-14 16:37:52 -0800156 #define FLATBUFFERS_EXPLICIT_CPP11 explicit
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700157 #define FLATBUFFERS_VTABLE_UNDERLYING_TYPE : flatbuffers::voffset_t
158#else
159 #define FLATBUFFERS_FINAL_CLASS
160 #define FLATBUFFERS_OVERRIDE
Austin Schuh272c6132020-11-14 16:37:52 -0800161 #define FLATBUFFERS_EXPLICIT_CPP11
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700162 #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
Austin Schuh272c6132020-11-14 16:37:52 -0800169 #define FLATBUFFERS_CONSTEXPR_CPP11 constexpr
170 #define FLATBUFFERS_CONSTEXPR_DEFINED
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700171#else
172 #define FLATBUFFERS_CONSTEXPR const
Austin Schuh272c6132020-11-14 16:37:52 -0800173 #define FLATBUFFERS_CONSTEXPR_CPP11
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700174#endif
175
176#if (defined(__cplusplus) && __cplusplus >= 201402L) || \
177 (defined(__cpp_constexpr) && __cpp_constexpr >= 201304)
Austin Schuh272c6132020-11-14 16:37:52 -0800178 #define FLATBUFFERS_CONSTEXPR_CPP14 FLATBUFFERS_CONSTEXPR_CPP11
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700179#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__)
James Kuszmaul8e62b022022-03-22 09:33:25 -0700196 #define FLATBUFFERS_DELETE_FUNC(func) func = delete
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700197#else
James Kuszmaul8e62b022022-03-22 09:33:25 -0700198 #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
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700205#endif
206
Austin Schuh272c6132020-11-14 16:37:52 -0800207// 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
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700217#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)
Austin Schuh272c6132020-11-14 16:37:52 -0800222 #if __has_include(<string_view>) && (__cplusplus >= 201606 || (defined(_HAS_CXX17) && _HAS_CXX17))
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700223 #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
Austin Schuh272c6132020-11-14 16:37:52 -0800235 // 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
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700242 #endif
243 #endif // __has_include
244#endif // !FLATBUFFERS_HAS_STRING_VIEW
245
James Kuszmaul8e62b022022-03-22 09:33:25 -0700246#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
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700251#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
Austin Schuh2dd86a92022-09-14 21:19:23 -0700263 // 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__))
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700269 #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:
Austin Schuh2dd86a92022-09-14 21:19:23 -0700276// - __suppress_ubsan__("undefined")
277// - __suppress_ubsan__("signed-integer-overflow")
Austin Schuh272c6132020-11-14 16:37:52 -0800278#if defined(__clang__) && (__clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >=7))
Austin Schuh2dd86a92022-09-14 21:19:23 -0700279 #define __suppress_ubsan__(type) __attribute__((no_sanitize(type)))
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700280#elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 409)
Austin Schuh2dd86a92022-09-14 21:19:23 -0700281 #define __suppress_ubsan__(type) __attribute__((no_sanitize_undefined))
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700282#else
Austin Schuh2dd86a92022-09-14 21:19:23 -0700283 #define __suppress_ubsan__(type)
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700284#endif
285
286// This is constexpr function used for checking compile-time constants.
287// Avoid `#pragma warning(disable: 4127) // C4127: expression is constant`.
288template<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.
James Kuszmaul8e62b022022-03-22 09:33:25 -0700296 #define FLATBUFFERS_ATTRIBUTE(attr) attr
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700297
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
314namespace 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.
320typedef uint32_t uoffset_t;
321
322// Signed offsets for references that can go in both directions.
323typedef 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.
327typedef uint16_t voffset_t;
328
329typedef uintmax_t largest_scalar_t;
330
331// In 32bits, this evaluates to 2GB - 1
Austin Schuh272c6132020-11-14 16:37:52 -0800332#define FLATBUFFERS_MAX_BUFFER_SIZE ((1ULL << (sizeof(::flatbuffers::soffset_t) * 8 - 1)) - 1)
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700333
Austin Schuh2dd86a92022-09-14 21:19:23 -0700334// 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
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700341// We support aligning the contents of buffers up to this size.
Austin Schuh2dd86a92022-09-14 21:19:23 -0700342#ifndef FLATBUFFERS_MAX_ALIGNMENT
343 #define FLATBUFFERS_MAX_ALIGNMENT 32
344#endif
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700345
James Kuszmaul8e62b022022-03-22 09:33:25 -0700346/// @brief The length of a FlatBuffer file header.
347static const size_t kFileIdentifierLength = 4;
348
349inline 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
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700354#if defined(_MSC_VER)
Austin Schuh272c6132020-11-14 16:37:52 -0800355 #pragma warning(disable: 4351) // C4351: new behavior: elements of array ... will be default initialized
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700356 #pragma warning(push)
357 #pragma warning(disable: 4127) // C4127: conditional expression is constant
358#endif
359
360template<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) {
Austin Schuh272c6132020-11-14 16:37:52 -0800384 union { T t; uint16_t i; } u = { t };
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700385 u.i = FLATBUFFERS_BYTESWAP16(u.i);
386 return u.t;
387 } else if (sizeof(T) == 4) {
Austin Schuh272c6132020-11-14 16:37:52 -0800388 union { T t; uint32_t i; } u = { t };
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700389 u.i = FLATBUFFERS_BYTESWAP32(u.i);
390 return u.t;
391 } else if (sizeof(T) == 8) {
Austin Schuh272c6132020-11-14 16:37:52 -0800392 union { T t; uint64_t i; } u = { t };
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700393 u.i = FLATBUFFERS_BYTESWAP64(u.i);
394 return u.t;
395 } else {
396 FLATBUFFERS_ASSERT(0);
Austin Schuh272c6132020-11-14 16:37:52 -0800397 return t;
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700398 }
399}
400
401#if defined(_MSC_VER)
402 #pragma warning(pop)
403#endif
404
405
406template<typename T> T EndianScalar(T t) {
407 #if FLATBUFFERS_LITTLEENDIAN
408 return t;
409 #else
410 return EndianSwap(t);
411 #endif
412}
413
414template<typename T>
415// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
Austin Schuh2dd86a92022-09-14 21:19:23 -0700416__suppress_ubsan__("alignment")
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700417T ReadScalar(const void *p) {
418 return EndianScalar(*reinterpret_cast<const T *>(p));
419}
420
Austin Schuh272c6132020-11-14 16:37:52 -0800421// 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
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700428template<typename T>
429// UBSAN: C++ aliasing type rules, see std::bit_cast<> for details.
Austin Schuh2dd86a92022-09-14 21:19:23 -0700430__suppress_ubsan__("alignment")
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700431void WriteScalar(void *p, T t) {
432 *reinterpret_cast<T *>(p) = EndianScalar(t);
433}
434
435template<typename T> struct Offset;
Austin Schuh2dd86a92022-09-14 21:19:23 -0700436template<typename T> __suppress_ubsan__("alignment") void WriteScalar(void *p, Offset<T> t) {
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700437 *reinterpret_cast<uoffset_t *>(p) = EndianScalar(t.o);
438}
439
Austin Schuh272c6132020-11-14 16:37:52 -0800440#if (FLATBUFFERS_GCC >= 100000) && (FLATBUFFERS_GCC < 110000)
441 #pragma GCC diagnostic pop
442#endif
443
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700444// 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).
Austin Schuh2dd86a92022-09-14 21:19:23 -0700447__suppress_ubsan__("unsigned-integer-overflow")
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700448inline size_t PaddingBytes(size_t buf_size, size_t scalar_size) {
449 return ((~buf_size) + 1) & (scalar_size - 1);
450}
451
James Kuszmaul8e62b022022-03-22 09:33:25 -0700452// 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).
455template<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).
460template<typename T> inline bool IsFloatTheSameAs(T e, T def) {
461 return (e == def) || ((def != def) && (e != e));
462}
463template<> inline bool IsTheSameAs<float>(float e, float def) {
464 return IsFloatTheSameAs(e, def);
465}
466template<> 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.
474template<typename T>
475inline 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].
480template<typename T>
481inline bool IsInRange(const T &v, const T &low, const T &high) {
482 return !IsOutRange(v, low, high);
483}
484
Austin Schuhe89fa2d2019-08-14 20:24:23 -0700485} // namespace flatbuffers
486#endif // FLATBUFFERS_BASE_H_