Nugget
eabase.h
1 /*-----------------------------------------------------------------------------
2  * eabase.h
3  *
4  * Copyright (c) Electronic Arts Inc. All rights reserved.
5  *---------------------------------------------------------------------------*/
6 
7 
8 #ifndef INCLUDED_eabase_H
9 #define INCLUDED_eabase_H
10 
11 #include <stdint.h>
12 
13 
14 // Identify the compiler and declare the EA_COMPILER_xxxx defines
15 #include <EABase/config/eacompiler.h>
16 
17 // Identify traits which this compiler supports, or does not support
18 #include <EABase/config/eacompilertraits.h>
19 
20 // Identify the platform and declare the EA_xxxx defines
21 #include <EABase/config/eaplatform.h>
22 
23 #if defined(EA_PRAGMA_ONCE_SUPPORTED)
24  #pragma once // Some compilers (e.g. VC++) benefit significantly from using this. We've measured 3-4% build speed improvements in apps as a result.
25 #endif
26 
27 // Always include version.h for backwards compatibility.
28 #include <EABase/version.h>
29 
30 // Define common SI unit macros
31 #include <EABase/eaunits.h>
32 
33 
34 // ------------------------------------------------------------------------
35 // The C++ standard defines size_t as a built-in type. Some compilers are
36 // not standards-compliant in this respect, so we need an additional include.
37 // The case is similar with wchar_t under C++.
38 
39 #if defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_MSVC) || defined(EA_WCHAR_T_NON_NATIVE) || defined(EA_PLATFORM_SONY)
40  #if defined(EA_COMPILER_MSVC)
41  #pragma warning(push, 0)
42  #pragma warning(disable: 4265 4365 4836 4574)
43  #endif
44  #include <stddef.h>
45  #if defined(EA_COMPILER_MSVC)
46  #pragma warning(pop)
47  #endif
48 #endif
49 
50 // ------------------------------------------------------------------------
51 // Include stddef.h on Apple's clang compiler to ensure the ptrdiff_t type
52 // is defined.
53 #if defined(EA_COMPILER_CLANG) && defined(EA_PLATFORM_APPLE)
54  #include <stddef.h>
55 #endif
56 
57 // ------------------------------------------------------------------------
58 // Include assert.h on C11 supported compilers so we may allow static_assert usage
59 // http://en.cppreference.com/w/c/error/static_assert
60 // C11 standard(ISO / IEC 9899:2011) :
61 // 7.2/3 Diagnostics <assert.h>(p : 186)
62 #if !defined(__cplusplus) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201100L
63  #include <assert.h>
64 #endif
65 
66 
67 // ------------------------------------------------------------------------
68 // By default, GCC defines NULL as ((void*)0), which is the
69 // C definition. This causes all sort of problems for C++ code, so it is
70 // worked around by undefining NULL.
71 
72 #if defined(NULL)
73  #undef NULL
74 #endif
75 
76 
77 // ------------------------------------------------------------------------
78 // Define the NULL pointer. This is normally defined in <stddef.h>, but we
79 // don't want to force a global dependency on that header, so the definition
80 // is duplicated here.
81 
82 #if defined(__cplusplus)
83  #define NULL 0
84 #else
85  #define NULL ((void*)0)
86 #endif
87 
88 
89 // ------------------------------------------------------------------------
90 // C98/99 Standard typedefs. From the ANSI ISO/IEC 9899 standards document
91 // Most recent versions of the gcc-compiler come with these defined in
92 // inttypes.h or stddef.h. Determining if they are predefined can be
93 // tricky, so we expect some problems on non-standard compilers
94 
95 //#if (defined(_INTTYPES_H) || defined(_INTTYPES_H_)) && !defined(PRId64)
96 // #error "<inttypes.h> was #included before eabase.h, but without __STDC_FORMAT_MACROS #defined. You must #include eabase.h or an equivalent before #including C99 headers, or you must define __STDC_FORMAT_MACRO before #including system headrs."
97 //#endif
98 
99 // ------------------------------------------------------------------------
100 // We need to test this after we potentially include stddef.h, otherwise we
101 // would have put this into the compilertraits header.
102 //#if !defined(EA_COMPILER_HAS_INTTYPES) && (!defined(_MSC_VER) || (_MSC_VER > 1500)) && (defined(EA_COMPILER_IS_C99) || defined(INT8_MIN) || defined(EA_COMPILER_HAS_C99_TYPES) || defined(_SN_STDINT_H))
103 // #define EA_COMPILER_HAS_INTTYPES
104 //#endif
105 
106 #ifdef EA_COMPILER_HAS_INTTYPES // If the compiler supports inttypes...
107  // ------------------------------------------------------------------------
108  // Include the stdint header to define and derive the required types.
109  // Additionally include inttypes.h as many compilers, including variations
110  // of GCC define things in inttypes.h that the C99 standard says goes
111  // in stdint.h.
112  //
113  // The C99 standard specifies that inttypes.h only define printf/scanf
114  // format macros if __STDC_FORMAT_MACROS is defined before #including
115  // inttypes.h. For consistency, we do that here.
116  #ifndef __STDC_FORMAT_MACROS
117  #define __STDC_FORMAT_MACROS
118  #endif
119  // The GCC PSP compiler defines standard int types (e.g. uint32_t) but not PRId8, etc.
120  // MSVC added support for inttypes.h header in VS2013.
121  #if !defined(EA_COMPILER_MSVC) || (defined(EA_COMPILER_MSVC) && EA_COMPILER_VERSION >= 1800)
122  #include <inttypes.h> // PRId8, SCNd8, etc.
123  #endif
124  #if defined(_MSC_VER)
125  #pragma warning(push, 0)
126  #endif
127  #include <stdint.h> // int32_t, INT64_C, UINT8_MAX, etc.
128  #include <math.h> // float_t, double_t, etc.
129  #include <float.h> // FLT_EVAL_METHOD.
130  #if defined(_MSC_VER)
131  #pragma warning(pop)
132  #endif
133 
134  #if !defined(FLT_EVAL_METHOD) && (defined(__FLT_EVAL_METHOD__) || defined(_FEVAL)) // GCC 3.x defines __FLT_EVAL_METHOD__ instead of the C99 standard FLT_EVAL_METHOD.
135  #ifdef __FLT_EVAL_METHOD__
136  #define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
137  #else
138  #define FLT_EVAL_METHOD _FEVAL
139  #endif
140  #endif
141 
142  // MinGW GCC (up to at least v4.3.0-20080502) mistakenly neglects to define float_t and double_t.
143  // This appears to be an acknowledged bug as of March 2008 and is scheduled to be fixed.
144  // Similarly, Android uses a mix of custom standard library headers which prior to SDK API level 21
145  // don't define float_t and double_t.
146  #if defined(__MINGW32__) || (defined(EA_PLATFORM_ANDROID) && !(defined(EA_ANDROID_SDK_LEVEL) && EA_ANDROID_SDK_LEVEL >= 21))
147  #if defined(__FLT_EVAL_METHOD__)
148  #if(__FLT_EVAL_METHOD__== 0)
149  typedef float float_t;
150  typedef double double_t;
151  #elif(__FLT_EVAL_METHOD__ == 1)
152  typedef double float_t;
153  typedef double double_t;
154  #elif(__FLT_EVAL_METHOD__ == 2)
155  typedef long double float_t;
156  typedef long double double_t;
157  #endif
158  #else
159  typedef float float_t;
160  typedef double double_t;
161  #endif
162  #endif
163 
164  // The CodeSourcery definitions of PRIxPTR and SCNxPTR are broken for 32 bit systems.
165  #if defined(__SIZEOF_SIZE_T__) && (__SIZEOF_SIZE_T__ == 4) && (defined(__have_long64) || defined(__have_longlong64))
166  #undef PRIdPTR
167  #define PRIdPTR "d"
168  #undef PRIiPTR
169  #define PRIiPTR "i"
170  #undef PRIoPTR
171  #define PRIoPTR "o"
172  #undef PRIuPTR
173  #define PRIuPTR "u"
174  #undef PRIxPTR
175  #define PRIxPTR "x"
176  #undef PRIXPTR
177  #define PRIXPTR "X"
178 
179  #undef SCNdPTR
180  #define SCNdPTR "d"
181  #undef SCNiPTR
182  #define SCNiPTR "i"
183  #undef SCNoPTR
184  #define SCNoPTR "o"
185  #undef SCNuPTR
186  #define SCNuPTR "u"
187  #undef SCNxPTR
188  #define SCNxPTR "x"
189  #endif
190 #else // else we must implement types ourselves.
191 
192 #if 0
193  #if !defined(__BIT_TYPES_DEFINED__) && !defined(__int8_t_defined)
194  typedef signed char int8_t; //< 8 bit signed integer
195  #endif
196  #if !defined( __int8_t_defined )
197  typedef signed short int16_t; //< 16 bit signed integer
198  typedef signed int int32_t; //< 32 bit signed integer. This works for both 32 bit and 64 bit platforms, as we assume the LP64 is followed.
199  #define __int8_t_defined
200  #endif
201  typedef unsigned char uint8_t; //< 8 bit unsigned integer
202  typedef unsigned short uint16_t; //< 16 bit unsigned integer
203  #if !defined( __uint32_t_defined )
204  typedef unsigned int uint32_t; //< 32 bit unsigned integer. This works for both 32 bit and 64 bit platforms, as we assume the LP64 is followed.
205  #define __uint32_t_defined
206  #endif
207 #endif
208 
209  // According to the C98/99 standard, FLT_EVAL_METHOD defines control the
210  // width used for floating point _t types.
211  #if defined(_MSC_VER) && _MSC_VER >= 1800
212  // MSVC's math.h provides float_t, double_t under this condition.
213  #elif defined(FLT_EVAL_METHOD)
214  #if (FLT_EVAL_METHOD == 0)
215  typedef float float_t;
216  typedef double double_t;
217  #elif (FLT_EVAL_METHOD == 1)
218  typedef double float_t;
219  typedef double double_t;
220  #elif (FLT_EVAL_METHOD == 2)
221  typedef long double float_t;
222  typedef long double double_t;
223  #endif
224  #endif
225 
226  #if defined(EA_COMPILER_MSVC)
227  typedef signed __int64 int64_t;
228  typedef unsigned __int64 uint64_t;
229 
230  #else
231  typedef signed long long int64_t;
232  typedef unsigned long long uint64_t;
233  #endif
234 #endif
235 
236 
237 // ------------------------------------------------------------------------
238 // macros for declaring constants in a portable way.
239 //
240 // e.g. int64_t x = INT64_C(1234567812345678);
241 // e.g. int64_t x = INT64_C(0x1111111122222222);
242 // e.g. uint64_t x = UINT64_C(0x1111111122222222);
243 //
244 // Microsoft VC++'s definitions of INT8_C/UINT8_C/INT16_C/UINT16_C are like so:
245 // #define INT8_C(x) (x)
246 // #define INT16_C(x) (x)
247 // #define UINT8_C(x) (x)
248 // #define UINT16_C(x) (x)
249 // To consider: undefine Microsoft's and use the casting versions below.
250 // ------------------------------------------------------------------------
251 
252 #ifndef INT8_C_DEFINED // If the user hasn't already defined these...
253  #define INT8_C_DEFINED
254 
255  #ifndef INT8_C
256  #define INT8_C(x) int8_t(x) // For the majority of compilers and platforms, long is 32 bits and long long is 64 bits.
257  #endif
258  #ifndef UINT8_C
259  #define UINT8_C(x) uint8_t(x)
260  #endif
261  #ifndef INT16_C
262  #define INT16_C(x) int16_t(x)
263  #endif
264  #ifndef UINT16_C
265  #define UINT16_C(x) uint16_t(x) // Possibly we should make this be uint16_t(x##u). Let's see how compilers react before changing this.
266  #endif
267  #ifndef INT32_C
268  #define INT32_C(x) x##L
269  #endif
270  #ifndef UINT32_C
271  #define UINT32_C(x) x##UL
272  #endif
273  #ifndef INT64_C
274  #define INT64_C(x) x##LL // The way to deal with this is to compare ULONG_MAX to 0xffffffff and if not equal, then remove the L.
275  #endif
276  #ifndef UINT64_C
277  #define UINT64_C(x) x##ULL // We need to follow a similar approach for LL.
278  #endif
279  #ifndef UINTMAX_C
280  #define UINTMAX_C(x) UINT64_C(x)
281  #endif
282 #endif
283 
284 // ------------------------------------------------------------------------
285 // type sizes
286 #ifndef INT8_MAX_DEFINED // If the user hasn't already defined these...
287  #define INT8_MAX_DEFINED
288 
289  // The value must be 2^(n-1)-1
290  #ifndef INT8_MAX
291  #define INT8_MAX 127
292  #endif
293  #ifndef INT16_MAX
294  #define INT16_MAX 32767
295  #endif
296  #ifndef INT32_MAX
297  #define INT32_MAX 2147483647
298  #endif
299  #ifndef INT64_MAX
300  #define INT64_MAX INT64_C(9223372036854775807)
301  #endif
302  #ifndef INTMAX_MAX
303  #define INTMAX_MAX INT64_MAX
304  #endif
305  #ifndef INTPTR_MAX
306  #if EA_PLATFORM_PTR_SIZE == 4
307  #define INTPTR_MAX INT32_MAX
308  #else
309  #define INTPTR_MAX INT64_MAX
310  #endif
311  #endif
312 
313  // The value must be either -2^(n-1) or 1-2(n-1).
314  #ifndef INT8_MIN
315  #define INT8_MIN -128
316  #endif
317  #ifndef INT16_MIN
318  #define INT16_MIN -32768
319  #endif
320  #ifndef INT32_MIN
321  #define INT32_MIN (-INT32_MAX - 1) // -2147483648
322  #endif
323  #ifndef INT64_MIN
324  #define INT64_MIN (-INT64_MAX - 1) // -9223372036854775808
325  #endif
326  #ifndef INTMAX_MIN
327  #define INTMAX_MIN INT64_MIN
328  #endif
329  #ifndef INTPTR_MIN
330  #if EA_PLATFORM_PTR_SIZE == 4
331  #define INTPTR_MIN INT32_MIN
332  #else
333  #define INTPTR_MIN INT64_MIN
334  #endif
335  #endif
336 
337  // The value must be 2^n-1
338  #ifndef UINT8_MAX
339  #define UINT8_MAX 0xffU // 255
340  #endif
341  #ifndef UINT16_MAX
342  #define UINT16_MAX 0xffffU // 65535
343  #endif
344  #ifndef UINT32_MAX
345  #define UINT32_MAX UINT32_C(0xffffffff) // 4294967295
346  #endif
347  #ifndef UINT64_MAX
348  #define UINT64_MAX UINT64_C(0xffffffffffffffff) // 18446744073709551615
349  #endif
350  #ifndef UINTMAX_MAX
351  #define UINTMAX_MAX UINT64_MAX
352  #endif
353  #ifndef UINTPTR_MAX
354  #if EA_PLATFORM_PTR_SIZE == 4
355  #define UINTPTR_MAX UINT32_MAX
356  #else
357  #define UINTPTR_MAX UINT64_MAX
358  #endif
359  #endif
360 #endif
361 
362 #ifndef FLT_EVAL_METHOD
363  #define FLT_EVAL_METHOD 0
364  typedef float float_t;
365  typedef double double_t;
366 #endif
367 
368 #if defined(EA_COMPILER_HAS_INTTYPES) && (!defined(EA_COMPILER_MSVC) || (defined(EA_COMPILER_MSVC) && EA_COMPILER_VERSION >= 1800))
369  #define EA_COMPILER_HAS_C99_FORMAT_MACROS
370 #endif
371 
372 #ifndef EA_COMPILER_HAS_C99_FORMAT_MACROS
373  // ------------------------------------------------------------------------
374  // sized printf and scanf format specifiers
375  // See the C99 standard, section 7.8.1 -- Macros for format specifiers.
376  //
377  // The C99 standard specifies that inttypes.h only define printf/scanf
378  // format macros if __STDC_FORMAT_MACROS is defined before #including
379  // inttypes.h. For consistency, we define both __STDC_FORMAT_MACROS and
380  // the printf format specifiers here. We also skip the "least/most"
381  // variations of these specifiers, as we've decided to do so with
382  // basic types.
383  //
384  // For 64 bit systems, we assume the LP64 standard is followed
385  // (as opposed to ILP64, etc.) For 32 bit systems, we assume the
386  // ILP32 standard is followed. See:
387  // http://www.opengroup.org/public/tech/aspen/lp64_wp.htm
388  // for information about this. Thus, on both 32 and 64 bit platforms,
389  // %l refers to 32 bit data while %ll refers to 64 bit data.
390 
391  #ifndef __STDC_FORMAT_MACROS
392  #define __STDC_FORMAT_MACROS
393  #endif
394 
395  #if defined(EA_COMPILER_MSVC) // VC++ 7.1+ understands long long as a data type but doesn't accept %ll as a printf specifier.
396  #define EA_PRI_64_LENGTH_SPECIFIER "I64"
397  #define EA_SCN_64_LENGTH_SPECIFIER "I64"
398  #else
399  #define EA_PRI_64_LENGTH_SPECIFIER "ll"
400  #define EA_SCN_64_LENGTH_SPECIFIER "ll"
401  #endif // It turns out that some platforms use %q to represent a 64 bit value, but these are not relevant to us at this time.
402 
403  // Printf format specifiers
404  #if defined(EA_COMPILER_IS_C99) || defined(EA_COMPILER_GNUC)
405  #define PRId8 "hhd"
406  #define PRIi8 "hhi"
407  #define PRIo8 "hho"
408  #define PRIu8 "hhu"
409  #define PRIx8 "hhx"
410  #define PRIX8 "hhX"
411  #else // VC++, Borland, etc. which have no way to specify 8 bit values other than %c.
412  #define PRId8 "c" // This may not work properly but it at least will not crash. Try using 16 bit versions instead.
413  #define PRIi8 "c" // "
414  #define PRIo8 "o" // "
415  #define PRIu8 "u" // "
416  #define PRIx8 "x" // "
417  #define PRIX8 "X" // "
418  #endif
419 
420  #define PRId16 "hd"
421  #define PRIi16 "hi"
422  #define PRIo16 "ho"
423  #define PRIu16 "hu"
424  #define PRIx16 "hx"
425  #define PRIX16 "hX"
426 
427  #define PRId32 "d" // This works for both 32 bit and 64 bit systems, as we assume LP64 conventions.
428  #define PRIi32 "i"
429  #define PRIo32 "o"
430  #define PRIu32 "u"
431  #define PRIx32 "x"
432  #define PRIX32 "X"
433 
434  #define PRId64 EA_PRI_64_LENGTH_SPECIFIER "d"
435  #define PRIi64 EA_PRI_64_LENGTH_SPECIFIER "i"
436  #define PRIo64 EA_PRI_64_LENGTH_SPECIFIER "o"
437  #define PRIu64 EA_PRI_64_LENGTH_SPECIFIER "u"
438  #define PRIx64 EA_PRI_64_LENGTH_SPECIFIER "x"
439  #define PRIX64 EA_PRI_64_LENGTH_SPECIFIER "X"
440 
441  #if (EA_PLATFORM_PTR_SIZE == 4)
442  #define PRIdPTR PRId32 // Usage of pointer values will generate warnings with
443  #define PRIiPTR PRIi32 // some compilers because they are defined in terms of
444  #define PRIoPTR PRIo32 // integers. However, you can't simply use "p" because
445  #define PRIuPTR PRIu32 // 'p' is interpreted in a specific and often different
446  #define PRIxPTR PRIx32 // way by the library.
447  #define PRIXPTR PRIX32
448  #elif (EA_PLATFORM_PTR_SIZE == 8)
449  #define PRIdPTR PRId64
450  #define PRIiPTR PRIi64
451  #define PRIoPTR PRIo64
452  #define PRIuPTR PRIu64
453  #define PRIxPTR PRIx64
454  #define PRIXPTR PRIX64
455  #endif
456 
457  // Scanf format specifiers
458  #if defined(EA_COMPILER_IS_C99) || defined(EA_COMPILER_GNUC)
459  #define SCNd8 "hhd"
460  #define SCNi8 "hhi"
461  #define SCNo8 "hho"
462  #define SCNu8 "hhu"
463  #define SCNx8 "hhx"
464  #else // VC++, Borland, etc. which have no way to specify 8 bit values other than %c.
465  #define SCNd8 "c" // This will not work properly but it at least will not crash. Try using 16 bit versions instead.
466  #define SCNi8 "c" // "
467  #define SCNo8 "c" // "
468  #define SCNu8 "c" // "
469  #define SCNx8 "c" // "
470  #endif
471 
472  #define SCNd16 "hd"
473  #define SCNi16 "hi"
474  #define SCNo16 "ho"
475  #define SCNu16 "hu"
476  #define SCNx16 "hx"
477 
478  #define SCNd32 "d" // This works for both 32 bit and 64 bit systems, as we assume LP64 conventions.
479  #define SCNi32 "i"
480  #define SCNo32 "o"
481  #define SCNu32 "u"
482  #define SCNx32 "x"
483 
484  #define SCNd64 EA_SCN_64_LENGTH_SPECIFIER "d"
485  #define SCNi64 EA_SCN_64_LENGTH_SPECIFIER "i"
486  #define SCNo64 EA_SCN_64_LENGTH_SPECIFIER "o"
487  #define SCNu64 EA_SCN_64_LENGTH_SPECIFIER "u"
488  #define SCNx64 EA_SCN_64_LENGTH_SPECIFIER "x"
489 
490  #if defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1900)
491  #define SCNdPTR PRIdPTR
492  #define SCNiPTR PRIiPTR
493  #define SCNoPTR PRIoPTR
494  #define SCNuPTR PRIuPTR
495  #define SCNxPTR PRIxPTR
496  #elif (EA_PLATFORM_PTR_SIZE == 4)
497  #define SCNdPTR SCNd32 // Usage of pointer values will generate warnings with
498  #define SCNiPTR SCNi32 // some compilers because they are defined in terms of
499  #define SCNoPTR SCNo32 // integers. However, you can't simply use "p" because
500  #define SCNuPTR SCNu32 // 'p' is interpreted in a specific and often different
501  #define SCNxPTR SCNx32 // way by the library.
502  #elif (EA_PLATFORM_PTR_SIZE == 8)
503  #define SCNdPTR SCNd64
504  #define SCNiPTR SCNi64
505  #define SCNoPTR SCNo64
506  #define SCNuPTR SCNu64
507  #define SCNxPTR SCNx64
508  #endif
509 #endif
510 
511 
512 // ------------------------------------------------------------------------
513 // bool8_t
514 // The definition of a bool8_t is controversial with some, as it doesn't
515 // act just like built-in bool. For example, you can assign -100 to it.
516 //
517 #ifndef BOOL8_T_DEFINED // If the user hasn't already defined this...
518  #define BOOL8_T_DEFINED
519  #if defined(EA_COMPILER_MSVC) || (defined(EA_COMPILER_INTEL) && defined(EA_PLATFORM_WINDOWS))
520  #if defined(__cplusplus)
521  typedef bool bool8_t;
522  #else
523  typedef int8_t bool8_t;
524  #endif
525  #else // EA_COMPILER_GNUC generally uses 4 bytes per bool.
526  typedef int8_t bool8_t;
527  #endif
528 #endif
529 
530 
531 // ------------------------------------------------------------------------
532 // intptr_t / uintptr_t
533 // Integer type guaranteed to be big enough to hold
534 // a native pointer ( intptr_t is defined in STDDEF.H )
535 //
536 #if !defined(_INTPTR_T_DEFINED) && !defined(_intptr_t_defined) && !defined(EA_COMPILER_HAS_C99_TYPES)
537  #if (EA_PLATFORM_PTR_SIZE == 4)
538  typedef int32_t intptr_t;
539  #elif (EA_PLATFORM_PTR_SIZE == 8)
540  typedef int64_t intptr_t;
541  #endif
542 
543  #define _intptr_t_defined
544  #define _INTPTR_T_DEFINED
545 #endif
546 
547 #if !defined(_UINTPTR_T_DEFINED) && !defined(_uintptr_t_defined) && !defined(EA_COMPILER_HAS_C99_TYPES)
548  #if (EA_PLATFORM_PTR_SIZE == 4)
549  typedef uint32_t uintptr_t;
550  #elif (EA_PLATFORM_PTR_SIZE == 8)
551  typedef uint64_t uintptr_t;
552  #endif
553 
554  #define _uintptr_t_defined
555  #define _UINTPTR_T_DEFINED
556 #endif
557 
558 #if !defined(EA_COMPILER_HAS_INTTYPES)
559  #ifndef INTMAX_T_DEFINED
560  #define INTMAX_T_DEFINED
561 
562  // At this time, all supported compilers have int64_t as the max
563  // integer type. Some compilers support a 128 bit integer type,
564  // but in some cases it is not a true int128_t but rather a
565  // crippled data type. Also, it turns out that Unix 64 bit ABIs
566  // require that intmax_t be int64_t and nothing larger. So we
567  // play it safe here and set intmax_t to int64_t, even though
568  // an int128_t type may exist.
569 
570  typedef int64_t intmax_t;
571  typedef uint64_t uintmax_t;
572  #endif
573 #endif
574 
575 
576 // ------------------------------------------------------------------------
577 // ssize_t
578 // signed equivalent to size_t.
579 // This is defined by GCC (except the QNX implementation of GCC) but not by other compilers.
580 //
581 #if 0
582 #if !defined(__GNUC__)
583  // As of this writing, all non-GCC compilers significant to us implement
584  // uintptr_t the same as size_t. However, this isn't guaranteed to be
585  // so for all compilers, as size_t may be based on int, long, or long long.
586  #if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED)
587  #define _SSIZE_T_
588  #define _SSIZE_T_DEFINED
589 
590  #if defined(_MSC_VER) && (EA_PLATFORM_PTR_SIZE == 8)
591  typedef __int64 ssize_t;
592  #else
593  typedef long ssize_t;
594  #endif
595  #endif
596 #else
597  #include <sys/types.h>
598 #endif
599 #endif
600 
601 // ------------------------------------------------------------------------
602 // Character types
603 //
604 #if defined(EA_COMPILER_MSVC)
605  #if defined(EA_WCHAR_T_NON_NATIVE)
606  // In this case, wchar_t is not defined unless we include
607  // wchar.h or if the compiler makes it built-in.
608  #ifdef EA_COMPILER_MSVC
609  #pragma warning(push, 3)
610  #endif
611  #include <wchar.h>
612  #ifdef EA_COMPILER_MSVC
613  #pragma warning(pop)
614  #endif
615  #endif
616 #endif
617 
618 
619 // ------------------------------------------------------------------------
620 // char8_t -- Guaranteed to be equal to the compiler's char data type.
621 // Some compilers implement char8_t as unsigned, though char
622 // is usually set to be signed.
623 //
624 // char16_t -- This is set to be an unsigned 16 bit value. If the compiler
625 // has wchar_t as an unsigned 16 bit value, then char16_t is
626 // set to be the same thing as wchar_t in order to allow the
627 // user to use char16_t with standard wchar_t functions.
628 //
629 // char32_t -- This is set to be an unsigned 32 bit value. If the compiler
630 // has wchar_t as an unsigned 32 bit value, then char32_t is
631 // set to be the same thing as wchar_t in order to allow the
632 // user to use char32_t with standard wchar_t functions.
633 //
634 // EA_CHAR8_UNIQUE
635 // EA_CHAR16_NATIVE
636 // EA_CHAR32_NATIVE
637 // EA_WCHAR_UNIQUE
638 //
639 // VS2010 unilaterally defines char16_t and char32_t in its yvals.h header
640 // unless _HAS_CHAR16_T_LANGUAGE_SUPPORT or _CHAR16T are defined.
641 // However, VS2010 does not support the C++0x u"" and U"" string literals,
642 // which makes its definition of char16_t and char32_t somewhat useless.
643 // Until VC++ supports string literals, the build system should define
644 // _CHAR16T and let EABase define char16_t and EA_CHAR16.
645 //
646 // GCC defines char16_t and char32_t in the C compiler in -std=gnu99 mode,
647 // as __CHAR16_TYPE__ and __CHAR32_TYPE__, and for the C++ compiler
648 // in -std=c++0x and -std=gnu++0x modes, as char16_t and char32_t too.
649 //
650 // The EA_WCHAR_UNIQUE symbol is defined to 1 if wchar_t is distinct from
651 // char8_t, char16_t, and char32_t, and defined to 0 if not. In some cases,
652 // if the compiler does not support char16_t/char32_t, one of these two types
653 // is typically a typedef or define of wchar_t. For compilers that support
654 // the C++11 unicode character types often overloads must be provided to
655 // support existing code that passes a wide char string to a function that
656 // takes a unicode string.
657 //
658 // The EA_CHAR8_UNIQUE symbol is defined to 1 if char8_t is distinct type
659 // from char in the type system, and defined to 0 if otherwise.
660 
661 #if !defined(EA_CHAR16_NATIVE)
662  // To do: Change this to be based on EA_COMPILER_NO_NEW_CHARACTER_TYPES.
663  #if defined(_MSC_VER) && (_MSC_VER >= 1600) && defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) && _HAS_CHAR16_T_LANGUAGE_SUPPORT // VS2010+
664  #define EA_CHAR16_NATIVE 1
665  #elif defined(EA_COMPILER_CLANG) && defined(EA_COMPILER_CPP11_ENABLED)
666  #if __has_feature(cxx_unicode_literals)
667  #define EA_CHAR16_NATIVE 1
668  #elif (EA_COMPILER_VERSION >= 300) && !(defined(EA_PLATFORM_IPHONE) || defined(EA_PLATFORM_OSX))
669  #define EA_CHAR16_NATIVE 1
670  #elif defined(EA_PLATFORM_APPLE)
671  #define EA_CHAR16_NATIVE 1
672  #else
673  #define EA_CHAR16_NATIVE 0
674  #endif
675  #elif defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 404) && defined(__CHAR16_TYPE__) && defined(EA_COMPILER_CPP11_ENABLED)// EDG 4.4+.
676  #define EA_CHAR16_NATIVE 1
677  #elif defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4004) && !defined(EA_COMPILER_EDG) && (defined(EA_COMPILER_CPP11_ENABLED) || defined(__STDC_VERSION__)) // g++ (C++ compiler) 4.4+ with -std=c++0x or gcc (C compiler) 4.4+ with -std=gnu99
678  #define EA_CHAR16_NATIVE 1
679  #else
680  #define EA_CHAR16_NATIVE 0
681  #endif
682 #endif
683 
684 #if !defined(EA_CHAR32_NATIVE) // Microsoft currently ties char32_t language support to char16_t language support. So we use CHAR16_T here.
685  // To do: Change this to be based on EA_COMPILER_NO_NEW_CHARACTER_TYPES.
686  #if defined(_MSC_VER) && (_MSC_VER >= 1600) && defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) && _HAS_CHAR16_T_LANGUAGE_SUPPORT // VS2010+
687  #define EA_CHAR32_NATIVE 1
688  #elif defined(EA_COMPILER_CLANG) && defined(EA_COMPILER_CPP11_ENABLED)
689  #if __has_feature(cxx_unicode_literals)
690  #define EA_CHAR32_NATIVE 1
691  #elif (EA_COMPILER_VERSION >= 300) && !(defined(EA_PLATFORM_IPHONE) || defined(EA_PLATFORM_OSX))
692  #define EA_CHAR32_NATIVE 1
693  #elif defined(EA_PLATFORM_APPLE)
694  #define EA_CHAR32_NATIVE 1
695  #else
696  #define EA_CHAR32_NATIVE 0
697  #endif
698  #elif defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 404) && defined(__CHAR32_TYPE__) && defined(EA_COMPILER_CPP11_ENABLED)// EDG 4.4+.
699  #define EA_CHAR32_NATIVE 1
700  #elif defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4004) && !defined(EA_COMPILER_EDG) && (defined(EA_COMPILER_CPP11_ENABLED) || defined(__STDC_VERSION__)) // g++ (C++ compiler) 4.4+ with -std=c++0x or gcc (C compiler) 4.4+ with -std=gnu99
701  #define EA_CHAR32_NATIVE 1
702  #else
703  #define EA_CHAR32_NATIVE 0
704  #endif
705 #endif
706 
707 
708 #if EA_CHAR16_NATIVE || EA_CHAR32_NATIVE
709  #define EA_WCHAR_UNIQUE 1
710 #else
711  #define EA_WCHAR_UNIQUE 0
712 #endif
713 
714 
715 // EA_CHAR8_UNIQUE
716 //
717 // Check for char8_t support in the cpp type system. Moving forward from c++20,
718 // the char8_t type allows users to overload function for character encoding.
719 //
720 // EA_CHAR8_UNIQUE is 1 when the type is a unique in the type system and
721 // can there be used as a valid overload. EA_CHAR8_UNIQUE is 0 otherwise.
722 //
723 // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0482r6.html
724 //
725 #ifdef __cpp_char8_t
726  #define CHAR8_T_DEFINED
727  #define EA_CHAR8_UNIQUE 1
728 #else
729  #define EA_CHAR8_UNIQUE 0
730 #endif
731 
732 
733 #ifndef CHAR8_T_DEFINED // If the user hasn't already defined these...
734  #define CHAR8_T_DEFINED
735  #if defined(EA_PLATFORM_APPLE)
736  #define char8_t char // The Apple debugger is too stupid to realize char8_t is typedef'd to char, so we #define it.
737  #else
738  typedef char char8_t;
739  #endif
740 
741  #if EA_CHAR16_NATIVE
742  // In C++, char16_t and char32_t are already defined by the compiler.
743  // In MS C, char16_t and char32_t are already defined by the compiler/standard library.
744  // In GCC C, __CHAR16_TYPE__ and __CHAR32_TYPE__ are defined instead, and we must define char16_t and char32_t from these.
745  #if defined(__GNUC__) && !defined(__GXX_EXPERIMENTAL_CXX0X__) && defined(__CHAR16_TYPE__) // If using GCC and compiling in C...
746  typedef __CHAR16_TYPE__ char16_t;
747  typedef __CHAR32_TYPE__ char32_t;
748  #endif
749  #elif (EA_WCHAR_SIZE == 2)
750  #if (defined(_MSC_VER) && (_MSC_VER >= 1600)) // if VS2010+ or using platforms that use Dinkumware under a compiler that doesn't natively support C++11 char16_t.
751  #if !defined(_CHAR16T)
752  #define _CHAR16T
753  #endif
754  #if !defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) || !_HAS_CHAR16_T_LANGUAGE_SUPPORT
755  typedef wchar_t char16_t;
756  typedef uint32_t char32_t;
757  #endif
758  #else
759  typedef wchar_t char16_t;
760  typedef uint32_t char32_t;
761  #endif
762  #else
763  typedef uint16_t char16_t;
764  #if defined(__cplusplus)
765  typedef wchar_t char32_t;
766  #else
767  typedef uint32_t char32_t;
768  #endif
769  #endif
770 #endif
771 
772 
773 // CHAR8_MIN, CHAR8_MAX, etc.
774 //
775 #define EA_LIMITS_DIGITS_S(T) ((sizeof(T) * 8) - 1)
776 #define EA_LIMITS_DIGITS_U(T) ((sizeof(T) * 8))
777 #define EA_LIMITS_DIGITS(T) ((EA_LIMITS_IS_SIGNED(T) ? EA_LIMITS_DIGITS_S(T) : EA_LIMITS_DIGITS_U(T)))
778 #define EA_LIMITS_IS_SIGNED(T) ((T)(-1) < 0)
779 #define EA_LIMITS_MIN_S(T) ((T)((T)1 << EA_LIMITS_DIGITS_S(T)))
780 #define EA_LIMITS_MIN_U(T) ((T)0)
781 #define EA_LIMITS_MIN(T) ((EA_LIMITS_IS_SIGNED(T) ? EA_LIMITS_MIN_S(T) : EA_LIMITS_MIN_U(T)))
782 #define EA_LIMITS_MAX_S(T) ((T)(((((T)1 << (EA_LIMITS_DIGITS(T) - 1)) - 1) << 1) + 1))
783 #define EA_LIMITS_MAX_U(T) ((T)~(T)0)
784 #define EA_LIMITS_MAX(T) ((EA_LIMITS_IS_SIGNED(T) ? EA_LIMITS_MAX_S(T) : EA_LIMITS_MAX_U(T)))
785 
786 #if !defined(CHAR8_MIN)
787  #define CHAR8_MIN EA_LIMITS_MIN(char8_t)
788 #endif
789 
790 #if !defined(CHAR8_MAX)
791  #define CHAR8_MAX EA_LIMITS_MAX(char8_t)
792 #endif
793 
794 #if !defined(CHAR16_MIN)
795  #define CHAR16_MIN EA_LIMITS_MIN(char16_t)
796 #endif
797 
798 #if !defined(CHAR16_MAX)
799  #define CHAR16_MAX EA_LIMITS_MAX(char16_t)
800 #endif
801 
802 #if !defined(CHAR32_MIN)
803  #define CHAR32_MIN EA_LIMITS_MIN(char32_t)
804 #endif
805 
806 #if !defined(CHAR32_MAX)
807  #define CHAR32_MAX EA_LIMITS_MAX(char32_t)
808 #endif
809 
810 
811 
812 // EA_CHAR8 / EA_CHAR16 / EA_CHAR32 / EA_WCHAR
813 //
814 // Supports usage of portable string constants.
815 //
816 // Example usage:
817 // const char16_t* str = EA_CHAR16("Hello world");
818 // const char32_t* str = EA_CHAR32("Hello world");
819 // const char16_t c = EA_CHAR16('\x3001');
820 // const char32_t c = EA_CHAR32('\x3001');
821 //
822 #ifndef EA_CHAR8
823  #if EA_CHAR8_UNIQUE
824  #define EA_CHAR8(s) u8 ## s
825  #else
826  #define EA_CHAR8(s) s
827  #endif
828 #endif
829 
830 #ifndef EA_WCHAR
831  #define EA_WCHAR_(s) L ## s
832  #define EA_WCHAR(s) EA_WCHAR_(s)
833 #endif
834 
835 #ifndef EA_CHAR16
836  #if EA_CHAR16_NATIVE && !defined(_MSC_VER) // Microsoft doesn't support char16_t string literals.
837  #define EA_CHAR16_(s) u ## s
838  #define EA_CHAR16(s) EA_CHAR16_(s)
839  #elif (EA_WCHAR_SIZE == 2)
840  #if defined(_MSC_VER) && (_MSC_VER >= 1900) && defined(__cplusplus) // VS2015 supports u"" string literals.
841  #define EA_CHAR16_(s) u ## s
842  #define EA_CHAR16(s) EA_CHAR16_(s)
843  #else
844  #define EA_CHAR16_(s) L ## s
845  #define EA_CHAR16(s) EA_CHAR16_(s)
846  #endif
847  #else
848  //#define EA_CHAR16(s) // Impossible to implement efficiently.
849  #endif
850 #endif
851 
852 #ifndef EA_CHAR32
853  #if EA_CHAR32_NATIVE && !defined(_MSC_VER) // Microsoft doesn't support char32_t string literals.
854  #define EA_CHAR32_(s) U ## s
855  #define EA_CHAR32(s) EA_CHAR32_(s)
856  #elif (EA_WCHAR_SIZE == 2)
857  #if defined(_MSC_VER) && (_MSC_VER >= 1900) && defined(__cplusplus) // VS2015 supports u"" string literals.
858  #define EA_CHAR32_(s) U ## s
859  #define EA_CHAR32(s) EA_CHAR32_(s)
860  #else
861  //#define EA_CHAR32(s) // Impossible to implement.
862  #endif
863  #elif (EA_WCHAR_SIZE == 4)
864  #define EA_CHAR32_(s) L ## s
865  #define EA_CHAR32(s) EA_CHAR32_(s)
866  #else
867  #error Unexpected size of wchar_t
868  #endif
869 #endif
870 
871 // EAText8 / EAText16
872 //
873 // Provided for backwards compatibility with older code.
874 //
875 #if defined(EABASE_ENABLE_EATEXT_MACROS)
876  #define EAText8(x) x
877  #define EAChar8(x) x
878 
879  #define EAText16(x) EA_CHAR16(x)
880  #define EAChar16(x) EA_CHAR16(x)
881 #endif
882 
883 
884 
885 
886 // ------------------------------------------------------------------------
887 // EAArrayCount
888 //
889 // Returns the count of items in a built-in C array. This is a common technique
890 // which is often used to help properly calculate the number of items in an
891 // array at runtime in order to prevent overruns, etc.
892 //
893 // Example usage:
894 // int array[75];
895 // size_t arrayCount = EAArrayCount(array); // arrayCount is 75.
896 //
897 #if defined(EA_COMPILER_NO_CONSTEXPR)
898  #ifndef EAArrayCount
899  #define EAArrayCount(x) (sizeof(x) / sizeof(x[0]))
900  #endif
901 #else
902  // This C++11 version is a little smarter than the macro version above;
903  // it can tell the difference between arrays and pointers. Other simpler
904  // templated versions have failed in various subtle ways.
905 
906  template <typename T, size_t N>
907  char (&EAArraySizeHelper(T (&x)[N]))[N];
908 
909  template <typename T, size_t N>
910  char (&EAArraySizeHelper(T (&&x)[N]))[N];
911 
912  #define EAArrayCount(x) (sizeof(EAArraySizeHelper(x)))
913 #endif
914 
915 
916 // ------------------------------------------------------------------------
917 // static_assert
918 //
919 // C++11 static_assert (a.k.a. compile-time assert).
920 //
921 // Specification:
922 // void static_assert(bool const_expression, const char* description);
923 //
924 // Example usage:
925 // static_assert(sizeof(int) == 4, "int must be 32 bits");
926 //
927 #if defined(_MSC_VER) && (_MSC_VER >= 1600) && defined(__cplusplus)
928  // static_assert is defined by the compiler for both C and C++.
929 #elif !defined(__cplusplus) && defined(EA_PLATFORM_ANDROID) && ((defined(__STDC_VERSION__) && __STDC_VERSION__ < 201100L) || !defined(__STDC_VERSION__))
930  // AndroidNDK does not support static_assert despite claiming it's a C11 compiler
931  #define NEED_CUSTOM_STATIC_ASSERT
932 #elif defined(__clang__) && defined(__cplusplus)
933  // We need to separate these checks on a new line, as the pre-processor on other compilers will fail on the _has_feature macros
934  #if !(__has_feature(cxx_static_assert) || __has_extension(cxx_static_assert))
935  #define NEED_CUSTOM_STATIC_ASSERT
936  #endif
937 #elif defined(__GNUC__) && (defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(__cplusplus) && (__cplusplus >= 201103L)))
938  // static_assert is defined by the compiler.
939 #elif defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401) && defined(EA_COMPILER_CPP11_ENABLED)
940  // static_assert is defined by the compiler.
941 #elif !defined(__cplusplus) && defined(__GLIBC__) && defined(__USE_ISOC11)
942  // static_assert is defined by the compiler.
943 #elif !defined(__cplusplus) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201100L
944  // static_assert is defined by the compiler.
945 #else
946  #define NEED_CUSTOM_STATIC_ASSERT
947 #endif
948 
949 #ifdef NEED_CUSTOM_STATIC_ASSERT
950  #ifdef __GNUC__
951  // On GCC the 'unused' attribute can be used to indicate a typedef is not actually used
952  // (such as in the static_assert implementation below). New versions of GCC generate
953  // warnings for unused typedefs in function/method scopes.
954  #define EA_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
955  #else
956  #define EA_STATIC_ASSERT_UNUSED_ATTRIBUTE
957  #endif
958  #define EA_STATIC_ASSERT_TOKEN_PASTE(a,b) a ## b
959  #define EA_STATIC_ASSERT_CONCATENATE_HELPER(a,b) EA_STATIC_ASSERT_TOKEN_PASTE(a,b)
960 
961  #if defined(__COUNTER__) // If this extension is available, which allows multiple statements per line...
962  #define static_assert(expression, description) typedef char EA_STATIC_ASSERT_CONCATENATE_HELPER(compileTimeAssert,__COUNTER__) [((expression) != 0) ? 1 : -1] EA_STATIC_ASSERT_UNUSED_ATTRIBUTE
963  #else
964  #define static_assert(expression, description) typedef char EA_STATIC_ASSERT_CONCATENATE_HELPER(compileTimeAssert,__LINE__) [((expression) != 0) ? 1 : -1] EA_STATIC_ASSERT_UNUSED_ATTRIBUTE
965  #endif
966 
967  #undef NEED_CUSTOM_STATIC_ASSERT
968 #endif
969 
970 // ------------------------------------------------------------------------
971 // EA_IS_ENABLED
972 //
973 // EA_IS_ENABLED is intended to be used for detecting if compile time features are enabled or disabled.
974 //
975 // It has some advantages over using a standard #if or #ifdef tests:
976 // 1) Fails to compile when passes numeric macro values. Valid options are strictly enabled or disabled.
977 // 2) Fails to compile when passed undefined macro values rather than disabling by default
978 // 3) Fails to compile when the passed macro is defined to but empty
979 //
980 // To use the macro, the calling code should create a define for the feature to enable or disable. This feature define
981 // must be set to either EA_ENABLED or EA_DISABLED. (Do not try to set the feature define directly to some other
982 // value.)
983 //
984 // Note: These macros are analogous to the Frostbite macro FB_USING used in combination with FB_OFF / FB_ON and are
985 // designed to be compatible to support gradual migration.
986 //
987 // Example usage:
988 //
989 // // The USER_PROVIDED_FEATURE_DEFINE should be defined as either
990 // // EA_ENABLED or EA_DISABLED.
991 // #define USER_PROVIDED_FEATURE_DEFINE EA_ENABLED
992 //
993 // #if EA_IS_ENABLED(USER_PROVIDED_FEATURE_DEFINE)
994 // // USER_PROVIDED_FEATURE_DEFINE is enabled
995 // #else
996 // // USER_PROVIDED_FEATURE_DEFINE is disabled
997 // #endif
998 //
999 #define EA_ENABLED 111-
1000 #define EA_DISABLED 333-
1001 // NOTE: Numeric values for x will produce a parse error while empty values produce a divide by zero, and the test is a bool for proper negation behavior
1002 #define EA_IS_ENABLED(x) (333 == 333 * 111 / ((x 0) * (((x 0) == 333 ? 1 : 0) + ((x 0) == 111 ? 1 : 0))))
1003 
1004 
1005 
1006 // Define int128_t / uint128_t types.
1007 // NOTE(rparolin): include file at the end because we want all the signed integral types defined.
1008 #ifdef __cplusplus
1009  #include <EABase/int128.h>
1010 #endif
1011 
1012 #endif // Header include guard
1013 
1014 
1015 
1016