Sierra Toolkit  Version of the Day
eabase_eastl.h
1 /*
2 Copyright (C) 2009 Electronic Arts, Inc. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without
5 modification, are permitted provided that the following conditions
6 are met:
7 
8 1. Redistributions of source code must retain the above copyright
9  notice, this list of conditions and the following disclaimer.
10 2. Redistributions in binary form must reproduce the above copyright
11  notice, this list of conditions and the following disclaimer in the
12  documentation and/or other materials provided with the distribution.
13 3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
14  its contributors may be used to endorse or promote products derived
15  from this software without specific prior written permission.
16 
17 THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
18 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 
29 /*-----------------------------------------------------------------------------
30  * eabase.h
31  *
32  * Copyright (c) 2002 - 2005 Electronic Arts Inc. All rights reserved.
33  * Maintained by Paul Pedriana, Maxis
34  *---------------------------------------------------------------------------*/
35 
36 
37 #ifndef INCLUDED_eabase_H
38 #define INCLUDED_eabase_H
39 
40 
41 // Identify the compiler and declare the EA_COMPILER_xxxx defines
42 #ifndef INCLUDED_eacompiler_H
43  #include <stk_util/util/eacompiler_eastl.h>
44 #endif
45 
46 // Identify traits which this compiler supports, or does not support
47 #ifndef INCLUDED_eacompilertraits_H
48  #include <stk_util/util/eacompilertraits_eastl.h>
49 #endif
50 
51 // Identify the platform and declare the EA_xxxx defines
52 #ifndef INCLUDED_eaplatform_H
53  #include <stk_util/util/eaplatform_eastl.h>
54 #endif
55 
56 
57 
59 // EABASE_VERSION
60 //
61 // We more or less follow the conventional EA packaging approach to versioning
62 // here. A primary distinction here is that minor versions are defined as two
63 // digit entities (e.g. .03") instead of minimal digit entities ".3"). The logic
64 // here is that the value is a counter and not a floating point fraction.
65 // Note that the major version doesn't have leading zeros.
66 //
67 // Example version strings:
68 // "0.91.00" // Major version 0, minor version 91, patch version 0.
69 // "1.00.00" // Major version 1, minor and patch version 0.
70 // "3.10.02" // Major version 3, minor version 10, patch version 02.
71 // "12.03.01" // Major version 12, minor version 03, patch version
72 //
73 // Example usage:
74 // printf("EABASE version: %s", EABASE_VERSION);
75 // printf("EABASE version: %d.%d.%d", EABASE_VERSION_N / 10000 % 100, EABASE_VERSION_N / 100 % 100, EABASE_VERSION_N % 100);
76 //
78 
79 #ifndef EABASE_VERSION
80  #define EABASE_VERSION "2.00.22"
81  #define EABASE_VERSION_N 20022
82 #endif
83 
84 
85 
86 // ------------------------------------------------------------------------
87 // The C++ standard defines size_t as a built-in type. Some compilers are
88 // not standards-compliant in this respect, so we need an additional include.
89 // The case is similar with wchar_t under C++.
90 
91 #if defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_MSVC) || defined(EA_WCHAR_T_NON_NATIVE)
92  #include <stddef.h>
93 #endif
94 
95 
96 // ------------------------------------------------------------------------
97 // Ensure this header file is only processed once (with certain compilers)
98 // GCC doesn't need such a pragma because it has special recognition for
99 // include guards (such as that above) and effectively implements the same
100 // thing without having to resort to non-portable pragmas. It is possible
101 // that the decision to use pragma once here is ill-advised, perhaps because
102 // some compilers masquerade as MSVC but don't implement all features.
103 #if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_METROWERKS)
104  #pragma once
105 #endif
106 
107 
108 // ------------------------------------------------------------------------
109 // By default, GCC on certain platforms defines NULL as ((void*)0), which is the
110 // C definition. This causes all sort of problems for C++ code, so it is
111 // worked around by undefining NULL.
112 
113 #if defined(NULL)
114  #undef NULL
115 #endif
116 
117 
118 // ------------------------------------------------------------------------
119 // Define the NULL pointer. This is normally defined in <stddef.h>, but we
120 // don't want to force a global dependency on that header, so the definition
121 // is duplicated here.
122 
123 #if defined(__cplusplus)
124  #define NULL 0
125 #else
126  #define NULL ((void*)0)
127 #endif
128 
129 
130 // ------------------------------------------------------------------------
131 // C98/99 Standard typedefs. From the ANSI ISO/IEC 9899 standards document
132 // Most recent versions of the gcc-compiler come with these defined in
133 // inttypes.h or stddef.h. Determining if they are predefined can be
134 // tricky, so we expect some problems on non-standard compilers
135 
136 // ------------------------------------------------------------------------
137 // We need to test this after we potentially include stddef.h, otherwise we
138 // would have put this into the compilertraits header.
139 #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))
140  #define EA_COMPILER_HAS_INTTYPES
141 #endif
142 
143 
144 #ifdef EA_COMPILER_HAS_INTTYPES // If the compiler supports inttypes...
145  // ------------------------------------------------------------------------
146  // Include the stdint header to define and derive the required types.
147  // Additionally include inttypes.h as many compilers, including variations
148  // of GCC define things in inttypes.h that the C99 standard says goes
149  // in stdint.h.
150  //
151  // The C99 standard specifies that inttypes.h only define printf/scanf
152  // format macros if __STDC_FORMAT_MACROS is defined before #including
153  // inttypes.h. For consistency, we do that here.
154  #ifndef __STDC_FORMAT_MACROS
155  #define __STDC_FORMAT_MACROS
156  #endif
157  #if !defined(__psp__) // The GCC compiler defines standard int types (e.g. uint32_t) but not PRId8, etc.
158  #include <inttypes.h> // PRId8, SCNd8, etc.
159  #endif
160  #include <stdint.h> // int32_t, INT64_C, UINT8_MAX, etc.
161  #include <math.h> // float_t, double_t, etc.
162  #include <float.h> // FLT_EVAL_METHOD.
163 
164  #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.
165  #ifdef __FLT_EVAL_METHOD__
166  #define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
167  #else
168  #define FLT_EVAL_METHOD _FEVAL
169  #endif
170  #endif
171 
172  // MinGW GCC (up to at least v4.3.0-20080502) mistakenly neglects to define float_t and double_t.
173  // This appears to be an acknowledged bug as of March 2008 and is scheduled to be fixed.
174  // Similarly, Android uses a mix of custom standard library headers which don't define float_t and double_t.
175  #if defined(__MINGW32__) || defined(EA_PLATFORM_ANDROID)
176  #if defined(__FLT_EVAL_METHOD__)
177  #if(__FLT_EVAL_METHOD__== 0)
178  typedef float float_t;
179  typedef double double_t;
180  #elif(__FLT_EVAL_METHOD__ == 1)
181  typedef double float_t;
182  typedef double double_t;
183  #elif(__FLT_EVAL_METHOD__ == 2)
184  typedef long double float_t;
185  typedef long double double_t;
186  #endif
187  #else
188  typedef float float_t;
189  typedef double double_t;
190  #endif
191  #endif
192 
193  // Airplay's pretty broken for these types (at least as of 4.1)
194  #if defined __S3E__
195 
196  typedef float float_t;
197  typedef double double_t;
198 
199  #undef INT32_C
200  #undef UINT32_C
201  #undef INT64_C
202  #undef UINT64_C
203  #define INT32_C(x) x##L
204  #define UINT32_C(x) x##UL
205  #define INT64_C(x) x##LL
206  #define UINT64_C(x) x##ULL
207 
208  #define EA_PRI_64_LENGTH_SPECIFIER "ll"
209  #define EA_SCN_64_LENGTH_SPECIFIER "ll"
210 
211  #define SCNd16 "hd"
212  #define SCNi16 "hi"
213  #define SCNo16 "ho"
214  #define SCNu16 "hu"
215  #define SCNx16 "hx"
216 
217  #define SCNd32 "d" // This works for both 32 bit and 64 bit systems, as we assume LP64 conventions.
218  #define SCNi32 "i"
219  #define SCNo32 "o"
220  #define SCNu32 "u"
221  #define SCNx32 "x"
222 
223  #define SCNd64 EA_SCN_64_LENGTH_SPECIFIER "d"
224  #define SCNi64 EA_SCN_64_LENGTH_SPECIFIER "i"
225  #define SCNo64 EA_SCN_64_LENGTH_SPECIFIER "o"
226  #define SCNu64 EA_SCN_64_LENGTH_SPECIFIER "u"
227  #define SCNx64 EA_SCN_64_LENGTH_SPECIFIER "x"
228 
229  #define PRIdPTR PRId32 // Usage of pointer values will generate warnings with
230  #define PRIiPTR PRIi32 // some compilers because they are defined in terms of
231  #define PRIoPTR PRIo32 // integers. However, you can't simply use "p" because
232  #define PRIuPTR PRIu32 // 'p' is interpreted in a specific and often different
233  #define PRIxPTR PRIx32 // way by the library.
234  #define PRIXPTR PRIX32
235 
236  #define PRId8 "hhd"
237  #define PRIi8 "hhi"
238  #define PRIo8 "hho"
239  #define PRIu8 "hhu"
240  #define PRIx8 "hhx"
241  #define PRIX8 "hhX"
242 
243  #define PRId16 "hd"
244  #define PRIi16 "hi"
245  #define PRIo16 "ho"
246  #define PRIu16 "hu"
247  #define PRIx16 "hx"
248  #define PRIX16 "hX"
249 
250  #define PRId32 "d" // This works for both 32 bit and 64 bit systems, as we assume LP64 conventions.
251  #define PRIi32 "i"
252  #define PRIo32 "o"
253  #define PRIu32 "u"
254  #define PRIx32 "x"
255  #define PRIX32 "X"
256 
257  #define PRId64 EA_PRI_64_LENGTH_SPECIFIER "d"
258  #define PRIi64 EA_PRI_64_LENGTH_SPECIFIER "i"
259  #define PRIo64 EA_PRI_64_LENGTH_SPECIFIER "o"
260  #define PRIu64 EA_PRI_64_LENGTH_SPECIFIER "u"
261  #define PRIx64 EA_PRI_64_LENGTH_SPECIFIER "x"
262  #define PRIX64 EA_PRI_64_LENGTH_SPECIFIER "X"
263  #endif
264 
265  // The CodeSourcery definitions of PRIxPTR and SCNxPTR are broken for 32 bit systems.
266  #if defined(__SIZEOF_SIZE_T__) && (__SIZEOF_SIZE_T__ == 4) && (defined(__have_long64) || defined(__have_longlong64) || defined(__S3E__))
267  #undef PRIdPTR
268  #define PRIdPTR "d"
269  #undef PRIiPTR
270  #define PRIiPTR "i"
271  #undef PRIoPTR
272  #define PRIoPTR "o"
273  #undef PRIuPTR
274  #define PRIuPTR "u"
275  #undef PRIxPTR
276  #define PRIxPTR "x"
277  #undef PRIXPTR
278  #define PRIXPTR "X"
279 
280  #undef SCNdPTR
281  #define SCNdPTR "d"
282  #undef SCNiPTR
283  #define SCNiPTR "i"
284  #undef SCNoPTR
285  #define SCNoPTR "o"
286  #undef SCNuPTR
287  #define SCNuPTR "u"
288  #undef SCNxPTR
289  #define SCNxPTR "x"
290  #endif
291 #else // else we must implement types ourselves.
292 
293  #if !defined(__S3E__)
294  #if !defined(__BIT_TYPES_DEFINED__) && !defined(__int8_t_defined)
295  typedef signed char int8_t; //< 8 bit signed integer
296  #endif
297  #if !defined( __int8_t_defined )
298  typedef signed short int16_t; //< 16 bit signed integer
299  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.
300  #define __int8_t_defined
301  #endif
302  typedef unsigned char uint8_t; //< 8 bit unsigned integer
303  typedef unsigned short uint16_t; //< 16 bit unsigned integer
304  #if !defined( __uint32_t_defined )
305  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.
306  #define __uint32_t_defined
307  #endif
308  #endif
309 
310  // According to the C98/99 standard, FLT_EVAL_METHOD defines control the
311  // width used for floating point _t types.
312  #if defined(__MWERKS__) && ((defined(_MSL_C99) && (_MSL_C99 == 1)) || (__MWERKS__ < 0x4000))
313  // Metrowerks defines FLT_EVAL_METHOD and
314  // float_t/double_t under this condition.
315  #elif defined(FLT_EVAL_METHOD)
316  #if (FLT_EVAL_METHOD == 0)
317  typedef float float_t;
318  typedef double double_t;
319  #elif (FLT_EVAL_METHOD == 1)
320  typedef double float_t;
321  typedef double double_t;
322  #elif (FLT_EVAL_METHOD == 2)
323  typedef long double float_t;
324  typedef long double double_t;
325  #endif
326  #else
327  #define FLT_EVAL_METHOD 0
328  typedef float float_t;
329  typedef double double_t;
330  #endif
331 
332  #if defined(EA_PLATFORM_LINUX) || defined(EA_PLATFORM_PS3) || defined(EA_PLATFORM_PS3_SPU)
333  typedef signed long long int64_t;
334  typedef unsigned long long uint64_t;
335 
336  #elif defined(EA_PLATFORM_SUN) || defined(EA_PLATFORM_SGI)
337  #if (EA_PLATFORM_PTR_SIZE == 4)
338  typedef signed long long int64_t;
339  typedef unsigned long long uint64_t;
340  #else
341  typedef signed long int64_t;
342  typedef unsigned long uint64_t;
343  #endif
344 
345  #elif defined(EA_PLATFORM_WINDOWS) || defined(EA_PLATFORM_XBOX) || defined(EA_PLATFORM_XENON) || defined(EA_PLATFORM_MAC)
346  #if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_BORLAND) || defined(EA_COMPILER_INTEL)
347  typedef signed __int64 int64_t;
348  typedef unsigned __int64 uint64_t;
349  #else // GCC, Metrowerks, etc.
350  typedef long long int64_t;
351  typedef unsigned long long uint64_t;
352  #endif
353  #elif defined(EA_PLATFORM_AIRPLAY)
354  #else
355  typedef signed long long int64_t;
356  typedef unsigned long long uint64_t;
357  #endif
358 
359 
360  // ------------------------------------------------------------------------
361  // macros for declaring constants in a portable way.
362  //
363  // e.g. int64_t x = INT64_C(1234567812345678);
364  // e.g. int64_t x = INT64_C(0x1111111122222222);
365  // e.g. uint64_t x = UINT64_C(0x1111111122222222);
366 
367  #ifndef INT8_C_DEFINED // If the user hasn't already defined these...
368  #define INT8_C_DEFINED
369 
370  // VC++ 7.0 and earlier don't handle the LL suffix.
371  #if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_BORLAND)
372  #ifndef INT8_C
373  #define INT8_C(x) int8_t(x) // x##i8 doesn't work satisfactorilly because -128i8 generates an out of range warning.
374  #endif
375  #ifndef UINT8_C
376  #define UINT8_C(x) uint8_t(x)
377  #endif
378  #ifndef INT16_C
379  #define INT16_C(x) int16_t(x) // x##i16 doesn't work satisfactorilly because -32768i8 generates an out of range warning.
380  #endif
381  #ifndef UINT16_C
382  #define UINT16_C(x) uint16_t(x)
383  #endif
384  #ifndef INT32_C
385  #define INT32_C(x) x##i32
386  #endif
387  #ifndef UINT32_C
388  #define UINT32_C(x) x##ui32
389  #endif
390  #ifndef INT64_C
391  #define INT64_C(x) x##i64
392  #endif
393  #ifndef UINT64_C
394  #define UINT64_C(x) x##ui64
395  #endif
396 
397  #elif !defined(__STDC_CONSTANT_MACROS) // __STDC_CONSTANT_MACROS is defined by GCC 3 and later when INT8_C(), etc. are defined.
398  #define INT8_C(x) int8_t(x) // For the majority of compilers and platforms, long is 32 bits and long long is 64 bits.
399  #define UINT8_C(x) uint8_t(x)
400  #define INT16_C(x) int16_t(x)
401  #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.
402  #if defined(EA_PLATFORM_PS3) // PS3 defines long as 64 bit, so we cannot use any size suffix.
403  #define INT32_C(x) int32_t(x)
404  #define UINT32_C(x) uint32_t(x)
405  #else // Else we are working on a platform whereby sizeof(long) == sizeof(int32_t).
406  #define INT32_C(x) x##L
407  #define UINT32_C(x) x##UL
408  #endif
409  #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.
410  #define UINT64_C(x) x##ULL // We need to follow a similar approach for LL.
411  #endif
412  #endif
413 
414  // ------------------------------------------------------------------------
415  // type sizes
416  #ifndef INT8_MAX_DEFINED // If the user hasn't already defined these...
417  #define INT8_MAX_DEFINED
418 
419  // The value must be 2^(n-1)-1
420  #ifndef INT8_MAX
421  #define INT8_MAX 127
422  #endif
423  #ifndef INT16_MAX
424  #define INT16_MAX 32767
425  #endif
426  #ifndef INT32_MAX
427  #define INT32_MAX 2147483647
428  #endif
429  #ifndef INT64_MAX
430  #define INT64_MAX INT64_C(9223372036854775807)
431  #endif
432 
433  // The value must be either -2^(n-1) or 1-2(n-1).
434  #ifndef INT8_MIN
435  #define INT8_MIN -128
436  #endif
437  #ifndef INT16_MIN
438  #define INT16_MIN -32768
439  #endif
440  #ifndef INT32_MIN
441  #define INT32_MIN (-INT32_MAX - 1) // -2147483648
442  #endif
443  #ifndef INT64_MIN
444  #define INT64_MIN (-INT64_MAX - 1) // -9223372036854775808
445  #endif
446 
447  // The value must be 2^n-1
448  #ifndef UINT8_MAX
449  #define UINT8_MAX 0xffU // 255
450  #endif
451  #ifndef UINT16_MAX
452  #define UINT16_MAX 0xffffU // 65535
453  #endif
454  #ifndef UINT32_MAX
455  #define UINT32_MAX UINT32_C(0xffffffff) // 4294967295
456  #endif
457  #ifndef UINT64_MAX
458  #define UINT64_MAX UINT64_C(0xffffffffffffffff) // 18446744073709551615
459  #endif
460  #endif
461 
462  // ------------------------------------------------------------------------
463  // sized printf and scanf format specifiers
464  // See the C99 standard, section 7.8.1 -- Macros for format specifiers.
465  //
466  // The C99 standard specifies that inttypes.h only define printf/scanf
467  // format macros if __STDC_FORMAT_MACROS is defined before #including
468  // inttypes.h. For consistency, we define both __STDC_FORMAT_MACROS and
469  // the printf format specifiers here. We also skip the "least/most"
470  // variations of these specifiers, as we've decided to do so with
471  // basic types.
472  //
473  // For 64 bit systems, we assume the LP64 standard is followed
474  // (as opposed to ILP64, etc.) For 32 bit systems, we assume the
475  // ILP32 standard is followed. See:
476  // http://www.opengroup.org/public/tech/aspen/lp64_wp.htm
477  // for information about this. Thus, on both 32 and 64 bit platforms,
478  // %l refers to 32 bit data while %ll refers to 64 bit data.
479 
480  #ifndef __STDC_FORMAT_MACROS
481  #define __STDC_FORMAT_MACROS
482  #endif
483 
484  #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.
485  #define EA_PRI_64_LENGTH_SPECIFIER "I64"
486  #define EA_SCN_64_LENGTH_SPECIFIER "I64"
487  #else
488  #define EA_PRI_64_LENGTH_SPECIFIER "ll"
489  #define EA_SCN_64_LENGTH_SPECIFIER "ll"
490  #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.
491 
492  // Printf format specifiers
493  #if defined(EA_COMPILER_IS_C99) || defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_METROWERKS) // || defined(EA_COMPILER_INTEL) ?
494  #define PRId8 "hhd"
495  #define PRIi8 "hhi"
496  #define PRIo8 "hho"
497  #define PRIu8 "hhu"
498  #define PRIx8 "hhx"
499  #define PRIX8 "hhX"
500  #else // VC++, Borland, etc. which have no way to specify 8 bit values other than %c.
501  #define PRId8 "c" // This may not work properly but it at least will not crash. Try using 16 bit versions instead.
502  #define PRIi8 "c" // "
503  #define PRIo8 "o" // "
504  #define PRIu8 "u" // "
505  #define PRIx8 "x" // "
506  #define PRIX8 "X" // "
507  #endif
508 
509  #define PRId16 "hd"
510  #define PRIi16 "hi"
511  #define PRIo16 "ho"
512  #define PRIu16 "hu"
513  #define PRIx16 "hx"
514  #define PRIX16 "hX"
515 
516  #define PRId32 "d" // This works for both 32 bit and 64 bit systems, as we assume LP64 conventions.
517  #define PRIi32 "i"
518  #define PRIo32 "o"
519  #define PRIu32 "u"
520  #define PRIx32 "x"
521  #define PRIX32 "X"
522 
523  #define PRId64 EA_PRI_64_LENGTH_SPECIFIER "d"
524  #define PRIi64 EA_PRI_64_LENGTH_SPECIFIER "i"
525  #define PRIo64 EA_PRI_64_LENGTH_SPECIFIER "o"
526  #define PRIu64 EA_PRI_64_LENGTH_SPECIFIER "u"
527  #define PRIx64 EA_PRI_64_LENGTH_SPECIFIER "x"
528  #define PRIX64 EA_PRI_64_LENGTH_SPECIFIER "X"
529 
530  #if (EA_PLATFORM_PTR_SIZE == 4)
531  #define PRIdPTR PRId32 // Usage of pointer values will generate warnings with
532  #define PRIiPTR PRIi32 // some compilers because they are defined in terms of
533  #define PRIoPTR PRIo32 // integers. However, you can't simply use "p" because
534  #define PRIuPTR PRIu32 // 'p' is interpreted in a specific and often different
535  #define PRIxPTR PRIx32 // way by the library.
536  #define PRIXPTR PRIX32
537  #elif (EA_PLATFORM_PTR_SIZE == 8)
538  #define PRIdPTR PRId64
539  #define PRIiPTR PRIi64
540  #define PRIoPTR PRIo64
541  #define PRIuPTR PRIu64
542  #define PRIxPTR PRIx64
543  #define PRIXPTR PRIX64
544  #endif
545 
546  // Scanf format specifiers
547  #if defined(EA_COMPILER_IS_C99) || defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_METROWERKS) // || defined(EA_COMPILER_INTEL) ?
548  #define SCNd8 "hhd"
549  #define SCNi8 "hhi"
550  #define SCNo8 "hho"
551  #define SCNu8 "hhu"
552  #define SCNx8 "hhx"
553  #else // VC++, Borland, etc. which have no way to specify 8 bit values other than %c.
554  #define SCNd8 "c" // This will not work properly but it at least will not crash. Try using 16 bit versions instead.
555  #define SCNi8 "c" // "
556  #define SCNo8 "c" // "
557  #define SCNu8 "c" // "
558  #define SCNx8 "c" // "
559  #endif
560 
561  #define SCNd16 "hd"
562  #define SCNi16 "hi"
563  #define SCNo16 "ho"
564  #define SCNu16 "hu"
565  #define SCNx16 "hx"
566 
567  #define SCNd32 "d" // This works for both 32 bit and 64 bit systems, as we assume LP64 conventions.
568  #define SCNi32 "i"
569  #define SCNo32 "o"
570  #define SCNu32 "u"
571  #define SCNx32 "x"
572 
573  #define SCNd64 EA_SCN_64_LENGTH_SPECIFIER "d"
574  #define SCNi64 EA_SCN_64_LENGTH_SPECIFIER "i"
575  #define SCNo64 EA_SCN_64_LENGTH_SPECIFIER "o"
576  #define SCNu64 EA_SCN_64_LENGTH_SPECIFIER "u"
577  #define SCNx64 EA_SCN_64_LENGTH_SPECIFIER "x"
578 
579  #if (EA_PLATFORM_PTR_SIZE == 4)
580  #define SCNdPTR SCNd32 // Usage of pointer values will generate warnings with
581  #define SCNiPTR SCNi32 // some compilers because they are defined in terms of
582  #define SCNoPTR SCNo32 // integers. However, you can't simply use "p" because
583  #define SCNuPTR SCNu32 // 'p' is interpreted in a specific and often different
584  #define SCNxPTR SCNx32 // way by the library.
585  #elif (EA_PLATFORM_PTR_SIZE == 8)
586  #define SCNdPTR SCNd64
587  #define SCNiPTR SCNi64
588  #define SCNoPTR SCNo64
589  #define SCNuPTR SCNu64
590  #define SCNxPTR SCNx64
591  #endif
592 
593 #endif
594 
595 
596 // ------------------------------------------------------------------------
597 // bool8_t
598 // The definition of a bool8_t is controversial with some, as it doesn't
599 // act just like built-in bool. For example, you can assign -100 to it.
600 //
601 #ifndef BOOL8_T_DEFINED // If the user hasn't already defined this...
602  #define BOOL8_T_DEFINED
603  #if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_METROWERKS) || (defined(EA_COMPILER_INTEL) && defined(EA_PLATFORM_WINDOWS)) || defined(EA_COMPILER_BORLAND)
604  #if defined(__cplusplus)
605  typedef bool bool8_t;
606  #else
607  typedef int8_t bool8_t;
608  #endif
609  #else // EA_COMPILER_GNUC generally uses 4 bytes per bool.
610  typedef int8_t bool8_t;
611  #endif
612 #endif
613 
614 
615 // ------------------------------------------------------------------------
616 // intptr_t / uintptr_t
617 // Integer type guaranteed to be big enough to hold
618 // a native pointer ( intptr_t is defined in STDDEF.H )
619 //
620 #if !defined(_INTPTR_T_DEFINED) && !defined(_intptr_t_defined) && !defined(EA_COMPILER_HAS_C99_TYPES)
621  #if (EA_PLATFORM_PTR_SIZE == 4)
622  typedef int32_t intptr_t;
623  #elif (EA_PLATFORM_PTR_SIZE == 8)
624  typedef int64_t intptr_t;
625  #endif
626 
627  #define _intptr_t_defined
628  #define _INTPTR_T_DEFINED
629 #endif
630 
631 #if !defined(_UINTPTR_T_DEFINED) && !defined(_uintptr_t_defined) && !defined(EA_COMPILER_HAS_C99_TYPES)
632  #if (EA_PLATFORM_PTR_SIZE == 4)
633  typedef uint32_t uintptr_t;
634  #elif (EA_PLATFORM_PTR_SIZE == 8)
635  typedef uint64_t uintptr_t;
636  #endif
637 
638  #define _uintptr_t_defined
639  #define _UINTPTR_T_DEFINED
640 #endif
641 
642 #if !defined(EA_COMPILER_HAS_INTTYPES)
643  #ifndef INTMAX_T_DEFINED
644  #define INTMAX_T_DEFINED
645 
646  // At this time, all supported compilers have int64_t as the max
647  // integer type. Some compilers support a 128 bit inteter type,
648  // but in those cases it is not a true int128_t but rather a
649  // crippled data type.
650  typedef int64_t intmax_t;
651  typedef uint64_t uintmax_t;
652  #endif
653 #endif
654 
655 
656 // ------------------------------------------------------------------------
657 // ssize_t
658 // signed equivalent to size_t.
659 // This is defined by GCC but not by other compilers.
660 //
661 #if !defined(__GNUC__)
662  // As of this writing, all non-GCC compilers significant to us implement
663  // uintptr_t the same as size_t. However, this isn't guaranteed to be
664  // so for all compilers, as size_t may be based on int, long, or long long.
665  #if defined(_MSC_VER) && (EA_PLATFORM_PTR_SIZE == 8)
666  typedef __int64 ssize_t;
667  #elif !defined(__S3E__)
668  typedef long ssize_t;
669  #endif
670 #elif defined(EA_PLATFORM_UNIX) || defined(EA_PLATFORM_MINGW) || defined(__APPLE__) || defined(_BSD_SIZE_T_) // _BSD_SIZE_T_ indicates that Unix-like headers are present, even though it may not be a true Unix platform.
671  #include <sys/types.h>
672 #endif
673 
674 
675 // ------------------------------------------------------------------------
676 // Character types
677 
678 #if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_BORLAND)
679  #if defined(EA_WCHAR_T_NON_NATIVE)
680  // In this case, wchar_t is not defined unless we include
681  // wchar.h or if the compiler makes it built-in.
682  #ifdef EA_COMPILER_MSVC
683  #pragma warning(push, 3)
684  #endif
685  #include <wchar.h>
686  #ifdef EA_COMPILER_MSVC
687  #pragma warning(pop)
688  #endif
689  #endif
690 #endif
691 
692 
693 // ------------------------------------------------------------------------
694 // char8_t -- Guaranteed to be equal to the compiler's char data type.
695 // Some compilers implement char8_t as unsigned, though char
696 // is usually set to be signed.
697 //
698 // char16_t -- This is set to be an unsigned 16 bit value. If the compiler
699 // has wchar_t as an unsigned 16 bit value, then char16_t is
700 // set to be the same thing as wchar_t in order to allow the
701 // user to use char16_t with standard wchar_t functions.
702 //
703 // char32_t -- This is set to be an unsigned 32 bit value. If the compiler
704 // has wchar_t as an unsigned 32 bit value, then char32_t is
705 // set to be the same thing as wchar_t in order to allow the
706 // user to use char32_t with standard wchar_t functions.
707 //
708 // VS2010 unilaterally defines char16_t and char32_t in its yvals.h header
709 // unless _HAS_CHAR16_T_LANGUAGE_SUPPORT or _CHAR16T are defined.
710 // However, VS2010 does not support the C++0x u"" and U"" string literals,
711 // which makes its definition of char16_t and char32_t somewhat useless.
712 // Until VC++ supports string literals, the buildystems should define
713 // _CHAR16T and let EABase define char16_t and EA_CHAR16.
714 //
715 // GCC defines char16_t and char32_t in the C compiler in -std=gnu99 mode,
716 // as __CHAR16_TYPE__ and __CHAR32_TYPE__, and for the C++ compiler
717 // in -std=c++0x and -std=gnu++0x modes, as char16_t and char32_t too.
718 
719 #if !defined(EA_CHAR16_NATIVE)
720  #if defined(_MSC_VER) && (_MSC_VER >= 1600) && defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) && _HAS_CHAR16_T_LANGUAGE_SUPPORT // VS2010+
721  #define EA_CHAR16_NATIVE 1
722  #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 404) && (defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__STDC_VERSION__)) // g++ (C++ compiler) 4.4+ with -std=c++0x or gcc (C compiler) 4.4+ with -std=gnu99
723  #define EA_CHAR16_NATIVE 1
724  #else
725  #define EA_CHAR16_NATIVE 0
726  #endif
727 #endif
728 
729 #if !defined(EA_CHAR32_NATIVE)
730  #if defined(_MSC_VER) && (_MSC_VER >= 1600) && defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) && _HAS_CHAR16_T_LANGUAGE_SUPPORT // VS2010+
731  #define EA_CHAR32_NATIVE 1
732  #elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 404) && (defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__STDC_VERSION__)) // g++ (C++ compiler) 4.4+ with -std=c++0x or gcc (C compiler) 4.4+ with -std=gnu99
733  #define EA_CHAR32_NATIVE 1
734  #else
735  #define EA_CHAR32_NATIVE 0
736  #endif
737 #endif
738 
739 
740 #ifndef CHAR8_T_DEFINED // If the user hasn't already defined these...
741  #define CHAR8_T_DEFINED
742 
743  #if EA_CHAR16_NATIVE
744  typedef char char8_t;
745 
746  // In C++, char16_t and char32_t are already defined by the compiler.
747  // In MS C, char16_t and char32_t are already defined by the compiler/standard library.
748  // In GCC C, __CHAR16_TYPE__ and __CHAR32_TYPE__ are defined instead, and we must define char16_t and char32_t from these.
749  #if defined(__GNUC__) && !defined(__GXX_EXPERIMENTAL_CXX0X__) && defined(__CHAR16_TYPE__) // If using GCC and compiling in C...
750  typedef __CHAR16_TYPE__ char16_t;
751  typedef __CHAR32_TYPE__ char32_t;
752  #endif
753  #elif (EA_WCHAR_SIZE == 2)
754  typedef char char8_t;
755  typedef wchar_t char16_t;
756  typedef uint32_t char32_t;
757  #else
758  typedef char char8_t;
759  typedef uint16_t char16_t;
760  typedef wchar_t char32_t;
761  #endif
762 #endif
763 
764 
765 // EA_CHAR16 / EA_CHAR32
766 //
767 // Supports usage of portable string constants.
768 //
769 // Example usage:
770 // const char16_t* str = EA_CHAR16("Hello world");
771 // const char32_t* str = EA_CHAR32("Hello world");
772 // const char16_t c = EA_CHAR16('\x3001');
773 // const char32_t c = EA_CHAR32('\x3001');
774 //
775 #ifndef EA_CHAR16
776  #if EA_CHAR16_NATIVE && !defined(_MSC_VER) // Microsoft doesn't support char16_t string literals.
777  #define EA_CHAR16(s) u ## s
778  #elif (EA_WCHAR_SIZE == 2)
779  #define EA_CHAR16(s) L ## s
780  #else
781  //#define EA_CHAR16(s) // Impossible to implement.
782  #endif
783 #endif
784 
785 #ifndef EA_CHAR32
786  #if EA_CHAR32_NATIVE && !defined(_MSC_VER) // Microsoft doesn't support char32_t string literals.
787  #define EA_CHAR32(s) U ## s
788  #elif (EA_WCHAR_SIZE == 2)
789  //#define EA_CHAR32(s) // Impossible to implement.
790  #else
791  #define EA_CHAR32(s) L ## s
792  #endif
793 #endif
794 
795 
796 // ------------------------------------------------------------------------
797 // EAArrayCount
798 //
799 // Returns the count of items in a built-in C array. This is a common technique
800 // which is often used to help properly calculate the number of items in an
801 // array at runtime in order to prevent overruns, etc.
802 //
803 // Example usage:
804 // int array[75];
805 // size_t arrayCount = EAArrayCount(array); // arrayCount is 75.
806 //
807 #ifndef EAArrayCount
808  #define EAArrayCount(x) (sizeof(x) / sizeof(x[0]))
809 #endif
810 
811 
812 // ------------------------------------------------------------------------
813 // static_assert
814 //
815 // C++0x static_assert (a.k.a. compile-time assert).
816 //
817 // Specification:
818 // void static_assert(bool const_expression, const char* description);
819 //
820 // Example usage:
821 // static_assert(sizeof(int) == 4, "int must be 32 bits");
822 //
823 #if !defined(EABASE_STATIC_ASSERT_ENABLED)
824  #if defined(EA_DEBUG) || defined(_DEBUG)
825  #define EABASE_STATIC_ASSERT_ENABLED 1
826  #else
827  #define EABASE_STATIC_ASSERT_ENABLED 0
828  #endif
829 #endif
830 
831 #ifndef EA_PREPROCESSOR_JOIN
832  #define EA_PREPROCESSOR_JOIN(a, b) EA_PREPROCESSOR_JOIN1(a, b)
833  #define EA_PREPROCESSOR_JOIN1(a, b) EA_PREPROCESSOR_JOIN2(a, b)
834  #define EA_PREPROCESSOR_JOIN2(a, b) a##b
835 #endif
836 
837 #if defined(_MSC_VER) && (_MSC_VER >= 1600)
838  // static_assert is defined by the compiler for both C and C++.
839 #elif defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
840  // static_assert is defined by the compiler.
841 #else
842  #if EABASE_STATIC_ASSERT_ENABLED
843  #if defined(__COUNTER__) // If this VC++ extension is available...
844  #define static_assert(expression, description) enum { EA_PREPROCESSOR_JOIN(static_assert_, __COUNTER__) = 1 / ((!!(expression)) ? 1 : 0) }
845  #else
846  #define static_assert(expression, description) enum { EA_PREPROCESSOR_JOIN(static_assert_, __LINE__) = 1 / ((!!(expression)) ? 1 : 0) }
847  #endif
848  #else
849  #if defined(EA_COMPILER_METROWERKS)
850  #if defined(__cplusplus)
851  #define static_assert(expression, description) struct EA_PREPROCESSOR_JOIN(EACTAssertUnused_, __LINE__){ }
852  #else
853  #define static_assert(expression, description) enum { EA_PREPROCESSOR_JOIN(static_assert_, __LINE__) = 1 / ((!!(expression)) ? 1 : 0) }
854  #endif
855  #else
856  #define static_assert(expression, description)
857  #endif
858  #endif
859 #endif
860 
861 
862 #endif // Header include guard