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