summaryrefslogtreecommitdiffstats
path: root/UnknownVersion/include/EABase/eabase.h
diff options
context:
space:
mode:
Diffstat (limited to 'UnknownVersion/include/EABase/eabase.h')
-rw-r--r--UnknownVersion/include/EABase/eabase.h1524
1 files changed, 825 insertions, 699 deletions
diff --git a/UnknownVersion/include/EABase/eabase.h b/UnknownVersion/include/EABase/eabase.h
index 6752124..a378630 100644
--- a/UnknownVersion/include/EABase/eabase.h
+++ b/UnknownVersion/include/EABase/eabase.h
@@ -1,36 +1,7 @@
-/*
-Copyright (C) 2009 Electronic Arts, Inc. All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions
-are met:
-
-1. Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
-3. Neither the name of Electronic Arts, Inc. ("EA") nor the names of
- its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY ELECTRONIC ARTS AND ITS CONTRIBUTORS "AS IS" AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL ELECTRONIC ARTS OR ITS CONTRIBUTORS BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
/*-----------------------------------------------------------------------------
* eabase.h
*
- * Copyright (c) 2002 - 2005 Electronic Arts Inc. All rights reserved.
- * Maintained by Paul Pedriana, Maxis
+ * Copyright (c) Electronic Arts Inc. All rights reserved.
*---------------------------------------------------------------------------*/
@@ -39,52 +10,23 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Identify the compiler and declare the EA_COMPILER_xxxx defines
-#ifndef INCLUDED_eacompiler_H
-# include "EABase/config/eacompiler.h"
-#endif
+#include <EABase/config/eacompiler.h>
// Identify traits which this compiler supports, or does not support
-#ifndef INCLUDED_eacompilertraits_H
-# include "EABase/config/eacompilertraits.h"
-#endif
+#include <EABase/config/eacompilertraits.h>
// Identify the platform and declare the EA_xxxx defines
-#ifndef INCLUDED_eaplatform_H
-# include "EABase/config/eaplatform.h"
-#endif
+#include <EABase/config/eaplatform.h>
-# if defined(_MSC_VER) && (_MSC_VER >= 1600)
-#include <yvals.h>
+#if defined(EA_PRAGMA_ONCE_SUPPORTED)
+#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.
#endif
+// Always include version.h for backwards compatibility.
+#include <EABase/version.h>
-
-///////////////////////////////////////////////////////////////////////////////
-// EABASE_VERSION
-//
-// We more or less follow the conventional EA packaging approach to versioning
-// here. A primary distinction here is that minor versions are defined as two
-// digit entities (e.g. .03") instead of minimal digit entities ".3"). The logic
-// here is that the value is a counter and not a floating point fraction.
-// Note that the major version doesn't have leading zeros.
-//
-// Example version strings:
-// "0.91.00" // Major version 0, minor version 91, patch version 0.
-// "1.00.00" // Major version 1, minor and patch version 0.
-// "3.10.02" // Major version 3, minor version 10, patch version 02.
-// "12.03.01" // Major version 12, minor version 03, patch version
-//
-// Example usage:
-// printf("EABASE version: %s", EABASE_VERSION);
-// printf("EABASE version: %d.%d.%d", EABASE_VERSION_N / 10000 % 100, EABASE_VERSION_N / 100 % 100, EABASE_VERSION_N % 100);
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#ifndef EABASE_VERSION
-# define EABASE_VERSION "2.00.22"
-# define EABASE_VERSION_N 20022
-#endif
-
+// Define common SI unit macros
+#include <EABase/eaunits.h>
// ------------------------------------------------------------------------
@@ -92,30 +34,41 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// not standards-compliant in this respect, so we need an additional include.
// The case is similar with wchar_t under C++.
-#if defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_MSVC) || defined(EA_WCHAR_T_NON_NATIVE)
-# include <stddef.h>
+#if defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_MSVC) || defined(EA_WCHAR_T_NON_NATIVE) || defined(EA_PLATFORM_SONY)
+#if defined(EA_COMPILER_MSVC)
+#pragma warning(push, 0)
+#pragma warning(disable: 4265 4365 4836 4574)
+#endif
+#include <stddef.h>
+#if defined(EA_COMPILER_MSVC)
+#pragma warning(pop)
+#endif
#endif
+// ------------------------------------------------------------------------
+// Include stddef.h on Apple's clang compiler to ensure the ptrdiff_t type
+// is defined.
+#if defined(EA_COMPILER_CLANG) && defined(EA_PLATFORM_APPLE)
+#include <stddef.h>
+#endif
// ------------------------------------------------------------------------
-// Ensure this header file is only processed once (with certain compilers)
-// GCC doesn't need such a pragma because it has special recognition for
-// include guards (such as that above) and effectively implements the same
-// thing without having to resort to non-portable pragmas. It is possible
-// that the decision to use pragma once here is ill-advised, perhaps because
-// some compilers masquerade as MSVC but don't implement all features.
-#if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_METROWERKS)
-# pragma once
+// Include assert.h on C11 supported compilers so we may allow static_assert usage
+// http://en.cppreference.com/w/c/error/static_assert
+// C11 standard(ISO / IEC 9899:2011) :
+// 7.2/3 Diagnostics <assert.h>(p : 186)
+#if !defined(__cplusplus) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201100L
+#include <assert.h>
#endif
// ------------------------------------------------------------------------
-// By default, GCC on certain platforms defines NULL as ((void*)0), which is the
+// By default, GCC defines NULL as ((void*)0), which is the
// C definition. This causes all sort of problems for C++ code, so it is
// worked around by undefining NULL.
#if defined(NULL)
-# undef NULL
+#undef NULL
#endif
@@ -125,9 +78,9 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// is duplicated here.
#if defined(__cplusplus)
-# define NULL 0
+#define NULL 0
#else
-# define NULL ((void*)0)
+#define NULL ((void*)0)
#endif
@@ -137,482 +90,437 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// inttypes.h or stddef.h. Determining if they are predefined can be
// tricky, so we expect some problems on non-standard compilers
+//#if (defined(_INTTYPES_H) || defined(_INTTYPES_H_)) && !defined(PRId64)
+// #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."
+//#endif
+
// ------------------------------------------------------------------------
// We need to test this after we potentially include stddef.h, otherwise we
// would have put this into the compilertraits header.
#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))
-# define EA_COMPILER_HAS_INTTYPES
+#define EA_COMPILER_HAS_INTTYPES
#endif
-
#ifdef EA_COMPILER_HAS_INTTYPES // If the compiler supports inttypes...
- // ------------------------------------------------------------------------
- // Include the stdint header to define and derive the required types.
- // Additionally include inttypes.h as many compilers, including variations
- // of GCC define things in inttypes.h that the C99 standard says goes
- // in stdint.h.
- //
- // The C99 standard specifies that inttypes.h only define printf/scanf
- // format macros if __STDC_FORMAT_MACROS is defined before #including
- // inttypes.h. For consistency, we do that here.
-# ifndef __STDC_FORMAT_MACROS
-# define __STDC_FORMAT_MACROS
-# endif
-# if !defined(__psp__) && defined(__GNUC__) // The GCC compiler defines standard int types (e.g. uint32_t) but not PRId8, etc.
-# include <inttypes.h> // PRId8, SCNd8, etc.
-# endif
-# include <stdint.h> // int32_t, INT64_C, UINT8_MAX, etc.
-# include <math.h> // float_t, double_t, etc.
-# include <float.h> // FLT_EVAL_METHOD.
-
-# 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.
-# ifdef __FLT_EVAL_METHOD__
-# define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
-# else
-# define FLT_EVAL_METHOD _FEVAL
-# endif
-# endif
-
- // MinGW GCC (up to at least v4.3.0-20080502) mistakenly neglects to define float_t and double_t.
- // This appears to be an acknowledged bug as of March 2008 and is scheduled to be fixed.
- // Similarly, Android uses a mix of custom standard library headers which don't define float_t and double_t.
-# if defined(__MINGW32__) || defined(EA_PLATFORM_ANDROID)
-# if defined(__FLT_EVAL_METHOD__)
-# if(__FLT_EVAL_METHOD__== 0)
- typedef float float_t;
- typedef double double_t;
-# elif(__FLT_EVAL_METHOD__ == 1)
- typedef double float_t;
- typedef double double_t;
-# elif(__FLT_EVAL_METHOD__ == 2)
- typedef long double float_t;
- typedef long double double_t;
-# endif
-# else
- typedef float float_t;
- typedef double double_t;
-# endif
-# endif
-
- // Airplay's pretty broken for these types (at least as of 4.1)
-# if defined __S3E__
-
- typedef float float_t;
- typedef double double_t;
-
-# undef INT32_C
-# undef UINT32_C
-# undef INT64_C
-# undef UINT64_C
-# define INT32_C(x) x##L
-# define UINT32_C(x) x##UL
-# define INT64_C(x) x##LL
-# define UINT64_C(x) x##ULL
-
-# define EA_PRI_64_LENGTH_SPECIFIER "ll"
-# define EA_SCN_64_LENGTH_SPECIFIER "ll"
-
-# define SCNd16 "hd"
-# define SCNi16 "hi"
-# define SCNo16 "ho"
-# define SCNu16 "hu"
-# define SCNx16 "hx"
-
-# define SCNd32 "d" // This works for both 32 bit and 64 bit systems, as we assume LP64 conventions.
-# define SCNi32 "i"
-# define SCNo32 "o"
-# define SCNu32 "u"
-# define SCNx32 "x"
-
-# define SCNd64 EA_SCN_64_LENGTH_SPECIFIER "d"
-# define SCNi64 EA_SCN_64_LENGTH_SPECIFIER "i"
-# define SCNo64 EA_SCN_64_LENGTH_SPECIFIER "o"
-# define SCNu64 EA_SCN_64_LENGTH_SPECIFIER "u"
-# define SCNx64 EA_SCN_64_LENGTH_SPECIFIER "x"
-
-# define PRIdPTR PRId32 // Usage of pointer values will generate warnings with
-# define PRIiPTR PRIi32 // some compilers because they are defined in terms of
-# define PRIoPTR PRIo32 // integers. However, you can't simply use "p" because
-# define PRIuPTR PRIu32 // 'p' is interpreted in a specific and often different
-# define PRIxPTR PRIx32 // way by the library.
-# define PRIXPTR PRIX32
-
-# define PRId8 "hhd"
-# define PRIi8 "hhi"
-# define PRIo8 "hho"
-# define PRIu8 "hhu"
-# define PRIx8 "hhx"
-# define PRIX8 "hhX"
-
-# define PRId16 "hd"
-# define PRIi16 "hi"
-# define PRIo16 "ho"
-# define PRIu16 "hu"
-# define PRIx16 "hx"
-# define PRIX16 "hX"
-
-# define PRId32 "d" // This works for both 32 bit and 64 bit systems, as we assume LP64 conventions.
-# define PRIi32 "i"
-# define PRIo32 "o"
-# define PRIu32 "u"
-# define PRIx32 "x"
-# define PRIX32 "X"
-
-# define PRId64 EA_PRI_64_LENGTH_SPECIFIER "d"
-# define PRIi64 EA_PRI_64_LENGTH_SPECIFIER "i"
-# define PRIo64 EA_PRI_64_LENGTH_SPECIFIER "o"
-# define PRIu64 EA_PRI_64_LENGTH_SPECIFIER "u"
-# define PRIx64 EA_PRI_64_LENGTH_SPECIFIER "x"
-# define PRIX64 EA_PRI_64_LENGTH_SPECIFIER "X"
-# endif
-
- // The CodeSourcery definitions of PRIxPTR and SCNxPTR are broken for 32 bit systems.
-# if defined(__SIZEOF_SIZE_T__) && (__SIZEOF_SIZE_T__ == 4) && (defined(__have_long64) || defined(__have_longlong64) || defined(__S3E__))
-# undef PRIdPTR
-# define PRIdPTR "d"
-# undef PRIiPTR
-# define PRIiPTR "i"
-# undef PRIoPTR
-# define PRIoPTR "o"
-# undef PRIuPTR
-# define PRIuPTR "u"
-# undef PRIxPTR
-# define PRIxPTR "x"
-# undef PRIXPTR
-# define PRIXPTR "X"
-
-# undef SCNdPTR
-# define SCNdPTR "d"
-# undef SCNiPTR
-# define SCNiPTR "i"
-# undef SCNoPTR
-# define SCNoPTR "o"
-# undef SCNuPTR
-# define SCNuPTR "u"
-# undef SCNxPTR
-# define SCNxPTR "x"
-# endif
+// ------------------------------------------------------------------------
+// Include the stdint header to define and derive the required types.
+// Additionally include inttypes.h as many compilers, including variations
+// of GCC define things in inttypes.h that the C99 standard says goes
+// in stdint.h.
+//
+// The C99 standard specifies that inttypes.h only define printf/scanf
+// format macros if __STDC_FORMAT_MACROS is defined before #including
+// inttypes.h. For consistency, we do that here.
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+// The GCC PSP compiler defines standard int types (e.g. uint32_t) but not PRId8, etc.
+// MSVC added support for inttypes.h header in VS2013.
+#if !defined(EA_COMPILER_MSVC) || (defined(EA_COMPILER_MSVC) && EA_COMPILER_VERSION >= 1800)
+#include <inttypes.h> // PRId8, SCNd8, etc.
+#endif
+#if defined(_MSC_VER)
+#pragma warning(push, 0)
+#endif
+#include <stdint.h> // int32_t, INT64_C, UINT8_MAX, etc.
+#include <math.h> // float_t, double_t, etc.
+#include <float.h> // FLT_EVAL_METHOD.
+#if defined(_MSC_VER)
+#pragma warning(pop)
+#endif
+
+#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.
+#ifdef __FLT_EVAL_METHOD__
+#define FLT_EVAL_METHOD __FLT_EVAL_METHOD__
+#else
+#define FLT_EVAL_METHOD _FEVAL
+#endif
+#endif
+
+// MinGW GCC (up to at least v4.3.0-20080502) mistakenly neglects to define float_t and double_t.
+// This appears to be an acknowledged bug as of March 2008 and is scheduled to be fixed.
+// Similarly, Android uses a mix of custom standard library headers which prior to SDK API level 21
+// don't define float_t and double_t.
+#if defined(__MINGW32__) || (defined(EA_PLATFORM_ANDROID) && !(defined(EA_ANDROID_SDK_LEVEL) && EA_ANDROID_SDK_LEVEL >= 21))
+#if defined(__FLT_EVAL_METHOD__)
+#if(__FLT_EVAL_METHOD__== 0)
+typedef float float_t;
+typedef double double_t;
+#elif(__FLT_EVAL_METHOD__ == 1)
+typedef double float_t;
+typedef double double_t;
+#elif(__FLT_EVAL_METHOD__ == 2)
+typedef long double float_t;
+typedef long double double_t;
+#endif
+#else
+typedef float float_t;
+typedef double double_t;
+#endif
+#endif
+
+// The CodeSourcery definitions of PRIxPTR and SCNxPTR are broken for 32 bit systems.
+#if defined(__SIZEOF_SIZE_T__) && (__SIZEOF_SIZE_T__ == 4) && (defined(__have_long64) || defined(__have_longlong64))
+#undef PRIdPTR
+#define PRIdPTR "d"
+#undef PRIiPTR
+#define PRIiPTR "i"
+#undef PRIoPTR
+#define PRIoPTR "o"
+#undef PRIuPTR
+#define PRIuPTR "u"
+#undef PRIxPTR
+#define PRIxPTR "x"
+#undef PRIXPTR
+#define PRIXPTR "X"
+
+#undef SCNdPTR
+#define SCNdPTR "d"
+#undef SCNiPTR
+#define SCNiPTR "i"
+#undef SCNoPTR
+#define SCNoPTR "o"
+#undef SCNuPTR
+#define SCNuPTR "u"
+#undef SCNxPTR
+#define SCNxPTR "x"
+#endif
#else // else we must implement types ourselves.
-# if !defined(__S3E__)
-# if !defined(__BIT_TYPES_DEFINED__) && !defined(__int8_t_defined)
- typedef signed char int8_t; //< 8 bit signed integer
-# endif
-# if !defined( __int8_t_defined )
- typedef signed short int16_t; //< 16 bit signed integer
- 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.
-# define __int8_t_defined
-# endif
- typedef unsigned char uint8_t; //< 8 bit unsigned integer
- typedef unsigned short uint16_t; //< 16 bit unsigned integer
-# if !defined( __uint32_t_defined )
- 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.
-# define __uint32_t_defined
-# endif
-# endif
-
- // According to the C98/99 standard, FLT_EVAL_METHOD defines control the
- // width used for floating point _t types.
-# if defined(__MWERKS__) && ((defined(_MSL_C99) && (_MSL_C99 == 1)) || (__MWERKS__ < 0x4000))
- // Metrowerks defines FLT_EVAL_METHOD and
- // float_t/double_t under this condition.
-# elif defined(FLT_EVAL_METHOD)
-# if (FLT_EVAL_METHOD == 0)
- typedef float float_t;
- typedef double double_t;
-# elif (FLT_EVAL_METHOD == 1)
- typedef double float_t;
- typedef double double_t;
-# elif (FLT_EVAL_METHOD == 2)
- typedef long double float_t;
- typedef long double double_t;
-# endif
-# else
-# define FLT_EVAL_METHOD 0
- typedef float float_t;
- typedef double double_t;
-# endif
-
-# if defined(EA_PLATFORM_LINUX) || defined(EA_PLATFORM_PS3) || defined(EA_PLATFORM_PS3_SPU)
- typedef signed long long int64_t;
- typedef unsigned long long uint64_t;
-
-# elif defined(EA_PLATFORM_SUN) || defined(EA_PLATFORM_SGI)
-# if (EA_PLATFORM_PTR_SIZE == 4)
- typedef signed long long int64_t;
- typedef unsigned long long uint64_t;
-# else
- typedef signed long int64_t;
- typedef unsigned long uint64_t;
-# endif
-
-# elif defined(EA_PLATFORM_WINDOWS) || defined(EA_PLATFORM_XBOX) || defined(EA_PLATFORM_XENON) || defined(EA_PLATFORM_MAC)
-# if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_BORLAND) || defined(EA_COMPILER_INTEL)
- typedef signed __int64 int64_t;
- typedef unsigned __int64 uint64_t;
-# else // GCC, Metrowerks, etc.
- typedef long long int64_t;
- typedef unsigned long long uint64_t;
-# endif
-# elif defined(EA_PLATFORM_AIRPLAY)
-# else
- typedef signed long long int64_t;
- typedef unsigned long long uint64_t;
-# endif
-
-
- // ------------------------------------------------------------------------
- // macros for declaring constants in a portable way.
- //
- // e.g. int64_t x = INT64_C(1234567812345678);
- // e.g. int64_t x = INT64_C(0x1111111122222222);
- // e.g. uint64_t x = UINT64_C(0x1111111122222222);
-
-# ifndef INT8_C_DEFINED // If the user hasn't already defined these...
-# define INT8_C_DEFINED
-
- // VC++ 7.0 and earlier don't handle the LL suffix.
-# if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_BORLAND)
-# ifndef INT8_C
-# define INT8_C(x) int8_t(x) // x##i8 doesn't work satisfactorilly because -128i8 generates an out of range warning.
-# endif
-# ifndef UINT8_C
-# define UINT8_C(x) uint8_t(x)
-# endif
-# ifndef INT16_C
-# define INT16_C(x) int16_t(x) // x##i16 doesn't work satisfactorilly because -32768i8 generates an out of range warning.
-# endif
-# ifndef UINT16_C
-# define UINT16_C(x) uint16_t(x)
-# endif
-# ifndef INT32_C
-# define INT32_C(x) x##i32
-# endif
-# ifndef UINT32_C
-# define UINT32_C(x) x##ui32
-# endif
-# ifndef INT64_C
-# define INT64_C(x) x##i64
-# endif
-# ifndef UINT64_C
-# define UINT64_C(x) x##ui64
-# endif
-
-# elif !defined(__STDC_CONSTANT_MACROS) // __STDC_CONSTANT_MACROS is defined by GCC 3 and later when INT8_C(), etc. are defined.
-# define INT8_C(x) int8_t(x) // For the majority of compilers and platforms, long is 32 bits and long long is 64 bits.
-# define UINT8_C(x) uint8_t(x)
-# define INT16_C(x) int16_t(x)
-# 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.
-# if defined(EA_PLATFORM_PS3) // PS3 defines long as 64 bit, so we cannot use any size suffix.
-# define INT32_C(x) int32_t(x)
-# define UINT32_C(x) uint32_t(x)
-# else // Else we are working on a platform whereby sizeof(long) == sizeof(int32_t).
-# define INT32_C(x) x##L
-# define UINT32_C(x) x##UL
-# endif
-# 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.
-# define UINT64_C(x) x##ULL // We need to follow a similar approach for LL.
-# endif
-# endif
-
- // ------------------------------------------------------------------------
- // type sizes
-# ifndef INT8_MAX_DEFINED // If the user hasn't already defined these...
-# define INT8_MAX_DEFINED
-
- // The value must be 2^(n-1)-1
-# ifndef INT8_MAX
-# define INT8_MAX 127
-# endif
-# ifndef INT16_MAX
-# define INT16_MAX 32767
-# endif
-# ifndef INT32_MAX
-# define INT32_MAX 2147483647
-# endif
-# ifndef INT64_MAX
-# define INT64_MAX INT64_C(9223372036854775807)
-# endif
-
- // The value must be either -2^(n-1) or 1-2(n-1).
-# ifndef INT8_MIN
-# define INT8_MIN -128
-# endif
-# ifndef INT16_MIN
-# define INT16_MIN -32768
-# endif
-# ifndef INT32_MIN
-# define INT32_MIN (-INT32_MAX - 1) // -2147483648
-# endif
-# ifndef INT64_MIN
-# define INT64_MIN (-INT64_MAX - 1) // -9223372036854775808
-# endif
-
- // The value must be 2^n-1
-# ifndef UINT8_MAX
-# define UINT8_MAX 0xffU // 255
-# endif
-# ifndef UINT16_MAX
-# define UINT16_MAX 0xffffU // 65535
-# endif
-# ifndef UINT32_MAX
-# define UINT32_MAX UINT32_C(0xffffffff) // 4294967295
-# endif
-# ifndef UINT64_MAX
-# define UINT64_MAX UINT64_C(0xffffffffffffffff) // 18446744073709551615
-# endif
-# endif
-
- // ------------------------------------------------------------------------
- // sized printf and scanf format specifiers
- // See the C99 standard, section 7.8.1 -- Macros for format specifiers.
- //
- // The C99 standard specifies that inttypes.h only define printf/scanf
- // format macros if __STDC_FORMAT_MACROS is defined before #including
- // inttypes.h. For consistency, we define both __STDC_FORMAT_MACROS and
- // the printf format specifiers here. We also skip the "least/most"
- // variations of these specifiers, as we've decided to do so with
- // basic types.
- //
- // For 64 bit systems, we assume the LP64 standard is followed
- // (as opposed to ILP64, etc.) For 32 bit systems, we assume the
- // ILP32 standard is followed. See:
- // http://www.opengroup.org/public/tech/aspen/lp64_wp.htm
- // for information about this. Thus, on both 32 and 64 bit platforms,
- // %l refers to 32 bit data while %ll refers to 64 bit data.
-
-# ifndef __STDC_FORMAT_MACROS
-# define __STDC_FORMAT_MACROS
-# endif
-
-# 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.
-# define EA_PRI_64_LENGTH_SPECIFIER "I64"
-# define EA_SCN_64_LENGTH_SPECIFIER "I64"
-# else
-# define EA_PRI_64_LENGTH_SPECIFIER "ll"
-# define EA_SCN_64_LENGTH_SPECIFIER "ll"
-# 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.
-
- // Printf format specifiers
-# if defined(EA_COMPILER_IS_C99) || defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_METROWERKS) // || defined(EA_COMPILER_INTEL) ?
-# define PRId8 "hhd"
-# define PRIi8 "hhi"
-# define PRIo8 "hho"
-# define PRIu8 "hhu"
-# define PRIx8 "hhx"
-# define PRIX8 "hhX"
-# else // VC++, Borland, etc. which have no way to specify 8 bit values other than %c.
-# define PRId8 "c" // This may not work properly but it at least will not crash. Try using 16 bit versions instead.
-# define PRIi8 "c" // "
-# define PRIo8 "o" // "
-# define PRIu8 "u" // "
-# define PRIx8 "x" // "
-# define PRIX8 "X" // "
-# endif
-
-# define PRId16 "hd"
-# define PRIi16 "hi"
-# define PRIo16 "ho"
-# define PRIu16 "hu"
-# define PRIx16 "hx"
-# define PRIX16 "hX"
-
-# define PRId32 "d" // This works for both 32 bit and 64 bit systems, as we assume LP64 conventions.
-# define PRIi32 "i"
-# define PRIo32 "o"
-# define PRIu32 "u"
-# define PRIx32 "x"
-# define PRIX32 "X"
-
-# define PRId64 EA_PRI_64_LENGTH_SPECIFIER "d"
-# define PRIi64 EA_PRI_64_LENGTH_SPECIFIER "i"
-# define PRIo64 EA_PRI_64_LENGTH_SPECIFIER "o"
-# define PRIu64 EA_PRI_64_LENGTH_SPECIFIER "u"
-# define PRIx64 EA_PRI_64_LENGTH_SPECIFIER "x"
-# define PRIX64 EA_PRI_64_LENGTH_SPECIFIER "X"
-
-# if (EA_PLATFORM_PTR_SIZE == 4)
-# define PRIdPTR PRId32 // Usage of pointer values will generate warnings with
-# define PRIiPTR PRIi32 // some compilers because they are defined in terms of
-# define PRIoPTR PRIo32 // integers. However, you can't simply use "p" because
-# define PRIuPTR PRIu32 // 'p' is interpreted in a specific and often different
-# define PRIxPTR PRIx32 // way by the library.
-# define PRIXPTR PRIX32
-# elif (EA_PLATFORM_PTR_SIZE == 8)
-# define PRIdPTR PRId64
-# define PRIiPTR PRIi64
-# define PRIoPTR PRIo64
-# define PRIuPTR PRIu64
-# define PRIxPTR PRIx64
-# define PRIXPTR PRIX64
-# endif
-
- // Scanf format specifiers
-# if defined(EA_COMPILER_IS_C99) || defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_METROWERKS) // || defined(EA_COMPILER_INTEL) ?
-# define SCNd8 "hhd"
-# define SCNi8 "hhi"
-# define SCNo8 "hho"
-# define SCNu8 "hhu"
-# define SCNx8 "hhx"
-# else // VC++, Borland, etc. which have no way to specify 8 bit values other than %c.
-# define SCNd8 "c" // This will not work properly but it at least will not crash. Try using 16 bit versions instead.
-# define SCNi8 "c" // "
-# define SCNo8 "c" // "
-# define SCNu8 "c" // "
-# define SCNx8 "c" // "
-# endif
-
-# define SCNd16 "hd"
-# define SCNi16 "hi"
-# define SCNo16 "ho"
-# define SCNu16 "hu"
-# define SCNx16 "hx"
-
-# define SCNd32 "d" // This works for both 32 bit and 64 bit systems, as we assume LP64 conventions.
-# define SCNi32 "i"
-# define SCNo32 "o"
-# define SCNu32 "u"
-# define SCNx32 "x"
-
-# define SCNd64 EA_SCN_64_LENGTH_SPECIFIER "d"
-# define SCNi64 EA_SCN_64_LENGTH_SPECIFIER "i"
-# define SCNo64 EA_SCN_64_LENGTH_SPECIFIER "o"
-# define SCNu64 EA_SCN_64_LENGTH_SPECIFIER "u"
-# define SCNx64 EA_SCN_64_LENGTH_SPECIFIER "x"
-
-# if (EA_PLATFORM_PTR_SIZE == 4)
-# define SCNdPTR SCNd32 // Usage of pointer values will generate warnings with
-# define SCNiPTR SCNi32 // some compilers because they are defined in terms of
-# define SCNoPTR SCNo32 // integers. However, you can't simply use "p" because
-# define SCNuPTR SCNu32 // 'p' is interpreted in a specific and often different
-# define SCNxPTR SCNx32 // way by the library.
-# elif (EA_PLATFORM_PTR_SIZE == 8)
-# define SCNdPTR SCNd64
-# define SCNiPTR SCNi64
-# define SCNoPTR SCNo64
-# define SCNuPTR SCNu64
-# define SCNxPTR SCNx64
-# endif
+#if !defined(__BIT_TYPES_DEFINED__) && !defined(__int8_t_defined)
+typedef signed char int8_t; //< 8 bit signed integer
+#endif
+#if !defined( __int8_t_defined )
+typedef signed short int16_t; //< 16 bit signed integer
+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.
+#define __int8_t_defined
+#endif
+typedef unsigned char uint8_t; //< 8 bit unsigned integer
+typedef unsigned short uint16_t; //< 16 bit unsigned integer
+#if !defined( __uint32_t_defined )
+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.
+#define __uint32_t_defined
+#endif
+
+// According to the C98/99 standard, FLT_EVAL_METHOD defines control the
+// width used for floating point _t types.
+#if defined(_MSC_VER) && _MSC_VER >= 1800
+// MSVC's math.h provides float_t, double_t under this condition.
+#elif defined(FLT_EVAL_METHOD)
+#if (FLT_EVAL_METHOD == 0)
+typedef float float_t;
+typedef double double_t;
+#elif (FLT_EVAL_METHOD == 1)
+typedef double float_t;
+typedef double double_t;
+#elif (FLT_EVAL_METHOD == 2)
+typedef long double float_t;
+typedef long double double_t;
+#endif
+#endif
+
+#if defined(EA_COMPILER_MSVC)
+typedef signed __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+
+#else
+typedef signed long long int64_t;
+typedef unsigned long long uint64_t;
+#endif
+#endif
+
+
+// ------------------------------------------------------------------------
+// macros for declaring constants in a portable way.
+//
+// e.g. int64_t x = INT64_C(1234567812345678);
+// e.g. int64_t x = INT64_C(0x1111111122222222);
+// e.g. uint64_t x = UINT64_C(0x1111111122222222);
+//
+// Microsoft VC++'s definitions of INT8_C/UINT8_C/INT16_C/UINT16_C are like so:
+// #define INT8_C(x) (x)
+// #define INT16_C(x) (x)
+// #define UINT8_C(x) (x)
+// #define UINT16_C(x) (x)
+// To consider: undefine Microsoft's and use the casting versions below.
+// ------------------------------------------------------------------------
+
+#ifndef INT8_C_DEFINED // If the user hasn't already defined these...
+#define INT8_C_DEFINED
+
+#ifndef INT8_C
+#define INT8_C(x) int8_t(x) // For the majority of compilers and platforms, long is 32 bits and long long is 64 bits.
+#endif
+#ifndef UINT8_C
+#define UINT8_C(x) uint8_t(x)
+#endif
+#ifndef INT16_C
+#define INT16_C(x) int16_t(x)
+#endif
+#ifndef UINT16_C
+#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.
+#endif
+#ifndef INT32_C
+#define INT32_C(x) x##L
+#endif
+#ifndef UINT32_C
+#define UINT32_C(x) x##UL
+#endif
+#ifndef INT64_C
+#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.
+#endif
+#ifndef UINT64_C
+#define UINT64_C(x) x##ULL // We need to follow a similar approach for LL.
+#endif
+#ifndef UINTMAX_C
+#define UINTMAX_C(x) UINT64_C(x)
+#endif
+#endif
+
+// ------------------------------------------------------------------------
+// type sizes
+#ifndef INT8_MAX_DEFINED // If the user hasn't already defined these...
+#define INT8_MAX_DEFINED
+// The value must be 2^(n-1)-1
+#ifndef INT8_MAX
+#define INT8_MAX 127
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX 32767
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX 2147483647
+#endif
+#ifndef INT64_MAX
+#define INT64_MAX INT64_C(9223372036854775807)
+#endif
+#ifndef INTMAX_MAX
+#define INTMAX_MAX INT64_MAX
+#endif
+#ifndef INTPTR_MAX
+#if EA_PLATFORM_PTR_SIZE == 4
+#define INTPTR_MAX INT32_MAX
+#else
+#define INTPTR_MAX INT64_MAX
+#endif
+#endif
+
+// The value must be either -2^(n-1) or 1-2(n-1).
+#ifndef INT8_MIN
+#define INT8_MIN -128
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN -32768
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-INT32_MAX - 1) // -2147483648
+#endif
+#ifndef INT64_MIN
+#define INT64_MIN (-INT64_MAX - 1) // -9223372036854775808
+#endif
+#ifndef INTMAX_MIN
+#define INTMAX_MIN INT64_MIN
+#endif
+#ifndef INTPTR_MIN
+#if EA_PLATFORM_PTR_SIZE == 4
+#define INTPTR_MIN INT32_MIN
+#else
+#define INTPTR_MIN INT64_MIN
+#endif
+#endif
+
+// The value must be 2^n-1
+#ifndef UINT8_MAX
+#define UINT8_MAX 0xffU // 255
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX 0xffffU // 65535
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX UINT32_C(0xffffffff) // 4294967295
+#endif
+#ifndef UINT64_MAX
+#define UINT64_MAX UINT64_C(0xffffffffffffffff) // 18446744073709551615
+#endif
+#ifndef UINTMAX_MAX
+#define UINTMAX_MAX UINT64_MAX
+#endif
+#ifndef UINTPTR_MAX
+#if EA_PLATFORM_PTR_SIZE == 4
+#define UINTPTR_MAX UINT32_MAX
+#else
+#define UINTPTR_MAX UINT64_MAX
+#endif
+#endif
+#endif
+
+#ifndef FLT_EVAL_METHOD
+#define FLT_EVAL_METHOD 0
+typedef float float_t;
+typedef double double_t;
+#endif
+
+#if defined(EA_COMPILER_HAS_INTTYPES) && (!defined(EA_COMPILER_MSVC) || (defined(EA_COMPILER_MSVC) && EA_COMPILER_VERSION >= 1800))
+#define EA_COMPILER_HAS_C99_FORMAT_MACROS
+#endif
+
+#ifndef EA_COMPILER_HAS_C99_FORMAT_MACROS
+// ------------------------------------------------------------------------
+// sized printf and scanf format specifiers
+// See the C99 standard, section 7.8.1 -- Macros for format specifiers.
+//
+// The C99 standard specifies that inttypes.h only define printf/scanf
+// format macros if __STDC_FORMAT_MACROS is defined before #including
+// inttypes.h. For consistency, we define both __STDC_FORMAT_MACROS and
+// the printf format specifiers here. We also skip the "least/most"
+// variations of these specifiers, as we've decided to do so with
+// basic types.
+//
+// For 64 bit systems, we assume the LP64 standard is followed
+// (as opposed to ILP64, etc.) For 32 bit systems, we assume the
+// ILP32 standard is followed. See:
+// http://www.opengroup.org/public/tech/aspen/lp64_wp.htm
+// for information about this. Thus, on both 32 and 64 bit platforms,
+// %l refers to 32 bit data while %ll refers to 64 bit data.
+
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS
+#endif
+
+#if defined(EA_COMPILER_MSVC) // VC++ 7.1+ understands long long as a data type but doesn't accept %ll as a printf specifier.
+#define EA_PRI_64_LENGTH_SPECIFIER "I64"
+#define EA_SCN_64_LENGTH_SPECIFIER "I64"
+#else
+#define EA_PRI_64_LENGTH_SPECIFIER "ll"
+#define EA_SCN_64_LENGTH_SPECIFIER "ll"
+#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.
+
+// Printf format specifiers
+#if defined(EA_COMPILER_IS_C99) || defined(EA_COMPILER_GNUC)
+#define PRId8 "hhd"
+#define PRIi8 "hhi"
+#define PRIo8 "hho"
+#define PRIu8 "hhu"
+#define PRIx8 "hhx"
+#define PRIX8 "hhX"
+#else // VC++, Borland, etc. which have no way to specify 8 bit values other than %c.
+#define PRId8 "c" // This may not work properly but it at least will not crash. Try using 16 bit versions instead.
+#define PRIi8 "c" // "
+#define PRIo8 "o" // "
+#define PRIu8 "u" // "
+#define PRIx8 "x" // "
+#define PRIX8 "X" // "
+#endif
+
+#define PRId16 "hd"
+#define PRIi16 "hi"
+#define PRIo16 "ho"
+#define PRIu16 "hu"
+#define PRIx16 "hx"
+#define PRIX16 "hX"
+
+#define PRId32 "d" // This works for both 32 bit and 64 bit systems, as we assume LP64 conventions.
+#define PRIi32 "i"
+#define PRIo32 "o"
+#define PRIu32 "u"
+#define PRIx32 "x"
+#define PRIX32 "X"
+
+#define PRId64 EA_PRI_64_LENGTH_SPECIFIER "d"
+#define PRIi64 EA_PRI_64_LENGTH_SPECIFIER "i"
+#define PRIo64 EA_PRI_64_LENGTH_SPECIFIER "o"
+#define PRIu64 EA_PRI_64_LENGTH_SPECIFIER "u"
+#define PRIx64 EA_PRI_64_LENGTH_SPECIFIER "x"
+#define PRIX64 EA_PRI_64_LENGTH_SPECIFIER "X"
+
+#if (EA_PLATFORM_PTR_SIZE == 4)
+#define PRIdPTR PRId32 // Usage of pointer values will generate warnings with
+#define PRIiPTR PRIi32 // some compilers because they are defined in terms of
+#define PRIoPTR PRIo32 // integers. However, you can't simply use "p" because
+#define PRIuPTR PRIu32 // 'p' is interpreted in a specific and often different
+#define PRIxPTR PRIx32 // way by the library.
+#define PRIXPTR PRIX32
+#elif (EA_PLATFORM_PTR_SIZE == 8)
+#define PRIdPTR PRId64
+#define PRIiPTR PRIi64
+#define PRIoPTR PRIo64
+#define PRIuPTR PRIu64
+#define PRIxPTR PRIx64
+#define PRIXPTR PRIX64
+#endif
+
+// Scanf format specifiers
+#if defined(EA_COMPILER_IS_C99) || defined(EA_COMPILER_GNUC)
+#define SCNd8 "hhd"
+#define SCNi8 "hhi"
+#define SCNo8 "hho"
+#define SCNu8 "hhu"
+#define SCNx8 "hhx"
+#else // VC++, Borland, etc. which have no way to specify 8 bit values other than %c.
+#define SCNd8 "c" // This will not work properly but it at least will not crash. Try using 16 bit versions instead.
+#define SCNi8 "c" // "
+#define SCNo8 "c" // "
+#define SCNu8 "c" // "
+#define SCNx8 "c" // "
+#endif
+
+#define SCNd16 "hd"
+#define SCNi16 "hi"
+#define SCNo16 "ho"
+#define SCNu16 "hu"
+#define SCNx16 "hx"
+
+#define SCNd32 "d" // This works for both 32 bit and 64 bit systems, as we assume LP64 conventions.
+#define SCNi32 "i"
+#define SCNo32 "o"
+#define SCNu32 "u"
+#define SCNx32 "x"
+
+#define SCNd64 EA_SCN_64_LENGTH_SPECIFIER "d"
+#define SCNi64 EA_SCN_64_LENGTH_SPECIFIER "i"
+#define SCNo64 EA_SCN_64_LENGTH_SPECIFIER "o"
+#define SCNu64 EA_SCN_64_LENGTH_SPECIFIER "u"
+#define SCNx64 EA_SCN_64_LENGTH_SPECIFIER "x"
+
+#if defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1900)
+#define SCNdPTR PRIdPTR
+#define SCNiPTR PRIiPTR
+#define SCNoPTR PRIoPTR
+#define SCNuPTR PRIuPTR
+#define SCNxPTR PRIxPTR
+#elif (EA_PLATFORM_PTR_SIZE == 4)
+#define SCNdPTR SCNd32 // Usage of pointer values will generate warnings with
+#define SCNiPTR SCNi32 // some compilers because they are defined in terms of
+#define SCNoPTR SCNo32 // integers. However, you can't simply use "p" because
+#define SCNuPTR SCNu32 // 'p' is interpreted in a specific and often different
+#define SCNxPTR SCNx32 // way by the library.
+#elif (EA_PLATFORM_PTR_SIZE == 8)
+#define SCNdPTR SCNd64
+#define SCNiPTR SCNi64
+#define SCNoPTR SCNo64
+#define SCNuPTR SCNu64
+#define SCNxPTR SCNx64
+#endif
#endif
// ------------------------------------------------------------------------
// bool8_t
-// The definition of a bool8_t is controversial with some, as it doesn't
+// The definition of a bool8_t is controversial with some, as it doesn't
// act just like built-in bool. For example, you can assign -100 to it.
-//
+//
#ifndef BOOL8_T_DEFINED // If the user hasn't already defined this...
-# define BOOL8_T_DEFINED
-# if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_METROWERKS) || (defined(EA_COMPILER_INTEL) && defined(EA_PLATFORM_WINDOWS)) || defined(EA_COMPILER_BORLAND)
-# if defined(__cplusplus)
- typedef bool bool8_t;
-# else
- typedef int8_t bool8_t;
-# endif
-# else // EA_COMPILER_GNUC generally uses 4 bytes per bool.
- typedef int8_t bool8_t;
-# endif
+#define BOOL8_T_DEFINED
+#if defined(EA_COMPILER_MSVC) || (defined(EA_COMPILER_INTEL) && defined(EA_PLATFORM_WINDOWS))
+#if defined(__cplusplus)
+typedef bool bool8_t;
+#else
+typedef int8_t bool8_t;
+#endif
+#else // EA_COMPILER_GNUC generally uses 4 bytes per bool.
+typedef int8_t bool8_t;
+#endif
#endif
@@ -622,155 +530,281 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// a native pointer ( intptr_t is defined in STDDEF.H )
//
#if !defined(_INTPTR_T_DEFINED) && !defined(_intptr_t_defined) && !defined(EA_COMPILER_HAS_C99_TYPES)
-# if (EA_PLATFORM_PTR_SIZE == 4)
- typedef int32_t intptr_t;
-# elif (EA_PLATFORM_PTR_SIZE == 8)
- typedef int64_t intptr_t;
-# endif
+#if (EA_PLATFORM_PTR_SIZE == 4)
+typedef int32_t intptr_t;
+#elif (EA_PLATFORM_PTR_SIZE == 8)
+typedef int64_t intptr_t;
+#endif
-# define _intptr_t_defined
-# define _INTPTR_T_DEFINED
+#define _intptr_t_defined
+#define _INTPTR_T_DEFINED
#endif
#if !defined(_UINTPTR_T_DEFINED) && !defined(_uintptr_t_defined) && !defined(EA_COMPILER_HAS_C99_TYPES)
-# if (EA_PLATFORM_PTR_SIZE == 4)
- typedef uint32_t uintptr_t;
-# elif (EA_PLATFORM_PTR_SIZE == 8)
- typedef uint64_t uintptr_t;
-# endif
+#if (EA_PLATFORM_PTR_SIZE == 4)
+typedef uint32_t uintptr_t;
+#elif (EA_PLATFORM_PTR_SIZE == 8)
+typedef uint64_t uintptr_t;
+#endif
-# define _uintptr_t_defined
-# define _UINTPTR_T_DEFINED
+#define _uintptr_t_defined
+#define _UINTPTR_T_DEFINED
#endif
#if !defined(EA_COMPILER_HAS_INTTYPES)
-# ifndef INTMAX_T_DEFINED
-# define INTMAX_T_DEFINED
-
- // At this time, all supported compilers have int64_t as the max
- // integer type. Some compilers support a 128 bit inteter type,
- // but in those cases it is not a true int128_t but rather a
- // crippled data type.
- typedef int64_t intmax_t;
- typedef uint64_t uintmax_t;
-# endif
+#ifndef INTMAX_T_DEFINED
+#define INTMAX_T_DEFINED
+
+// At this time, all supported compilers have int64_t as the max
+// integer type. Some compilers support a 128 bit integer type,
+// but in some cases it is not a true int128_t but rather a
+// crippled data type. Also, it turns out that Unix 64 bit ABIs
+// require that intmax_t be int64_t and nothing larger. So we
+// play it safe here and set intmax_t to int64_t, even though
+// an int128_t type may exist.
+
+typedef int64_t intmax_t;
+typedef uint64_t uintmax_t;
+#endif
#endif
// ------------------------------------------------------------------------
// ssize_t
// signed equivalent to size_t.
-// This is defined by GCC but not by other compilers.
+// This is defined by GCC (except the QNX implementation of GCC) but not by other compilers.
//
-#if !defined(_SIZE_T)
#if !defined(__GNUC__)
- // As of this writing, all non-GCC compilers significant to us implement
- // uintptr_t the same as size_t. However, this isn't guaranteed to be
- // so for all compilers, as size_t may be based on int, long, or long long.
-# if defined(_MSC_VER) && (EA_PLATFORM_PTR_SIZE == 8)
- typedef __int64 ssize_t;
-# elif !defined(__S3E__)
- typedef long ssize_t;
-# endif
-#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.
-# include <sys/types.h>
+// As of this writing, all non-GCC compilers significant to us implement
+// uintptr_t the same as size_t. However, this isn't guaranteed to be
+// so for all compilers, as size_t may be based on int, long, or long long.
+#if !defined(_SSIZE_T_) && !defined(_SSIZE_T_DEFINED)
+#define _SSIZE_T_
+#define _SSIZE_T_DEFINED
+
+#if defined(_MSC_VER) && (EA_PLATFORM_PTR_SIZE == 8)
+typedef __int64 ssize_t;
+#else
+typedef long ssize_t;
#endif
#endif
+#else
+#include <sys/types.h>
+#endif
+
// ------------------------------------------------------------------------
// Character types
-
-#if defined(EA_COMPILER_MSVC) || defined(EA_COMPILER_BORLAND)
-# if defined(EA_WCHAR_T_NON_NATIVE)
- // In this case, wchar_t is not defined unless we include
- // wchar.h or if the compiler makes it built-in.
-# ifdef EA_COMPILER_MSVC
-# pragma warning(push, 3)
-# endif
-# include <wchar.h>
-# ifdef EA_COMPILER_MSVC
-# pragma warning(pop)
-# endif
-# endif
+//
+#if defined(EA_COMPILER_MSVC)
+#if defined(EA_WCHAR_T_NON_NATIVE)
+// In this case, wchar_t is not defined unless we include
+// wchar.h or if the compiler makes it built-in.
+#ifdef EA_COMPILER_MSVC
+#pragma warning(push, 3)
+#endif
+#include <wchar.h>
+#ifdef EA_COMPILER_MSVC
+#pragma warning(pop)
+#endif
+#endif
#endif
// ------------------------------------------------------------------------
// char8_t -- Guaranteed to be equal to the compiler's char data type.
-// Some compilers implement char8_t as unsigned, though char
+// Some compilers implement char8_t as unsigned, though char
// is usually set to be signed.
//
// char16_t -- This is set to be an unsigned 16 bit value. If the compiler
-// has wchar_t as an unsigned 16 bit value, then char16_t is
-// set to be the same thing as wchar_t in order to allow the
+// has wchar_t as an unsigned 16 bit value, then char16_t is
+// set to be the same thing as wchar_t in order to allow the
// user to use char16_t with standard wchar_t functions.
//
// char32_t -- This is set to be an unsigned 32 bit value. If the compiler
-// has wchar_t as an unsigned 32 bit value, then char32_t is
-// set to be the same thing as wchar_t in order to allow the
+// has wchar_t as an unsigned 32 bit value, then char32_t is
+// set to be the same thing as wchar_t in order to allow the
// user to use char32_t with standard wchar_t functions.
//
+// EA_CHAR8_UNIQUE
+// EA_CHAR16_NATIVE
+// EA_CHAR32_NATIVE
+// EA_WCHAR_UNIQUE
+//
// VS2010 unilaterally defines char16_t and char32_t in its yvals.h header
-// unless _HAS_CHAR16_T_LANGUAGE_SUPPORT or _CHAR16T are defined.
-// However, VS2010 does not support the C++0x u"" and U"" string literals,
-// which makes its definition of char16_t and char32_t somewhat useless.
-// Until VC++ supports string literals, the buildystems should define
+// unless _HAS_CHAR16_T_LANGUAGE_SUPPORT or _CHAR16T are defined.
+// However, VS2010 does not support the C++0x u"" and U"" string literals,
+// which makes its definition of char16_t and char32_t somewhat useless.
+// Until VC++ supports string literals, the build system should define
// _CHAR16T and let EABase define char16_t and EA_CHAR16.
//
-// GCC defines char16_t and char32_t in the C compiler in -std=gnu99 mode,
-// as __CHAR16_TYPE__ and __CHAR32_TYPE__, and for the C++ compiler
+// GCC defines char16_t and char32_t in the C compiler in -std=gnu99 mode,
+// as __CHAR16_TYPE__ and __CHAR32_TYPE__, and for the C++ compiler
// in -std=c++0x and -std=gnu++0x modes, as char16_t and char32_t too.
+//
+// The EA_WCHAR_UNIQUE symbol is defined to 1 if wchar_t is distinct from
+// char8_t, char16_t, and char32_t, and defined to 0 if not. In some cases,
+// if the compiler does not support char16_t/char32_t, one of these two types
+// is typically a typedef or define of wchar_t. For compilers that support
+// the C++11 unicode character types often overloads must be provided to
+// support existing code that passes a wide char string to a function that
+// takes a unicode string.
+//
+// The EA_CHAR8_UNIQUE symbol is defined to 1 if char8_t is distinct type
+// from char in the type system, and defined to 0 if otherwise.
#if !defined(EA_CHAR16_NATIVE)
-# if defined(_MSC_VER) && (_MSC_VER >= 1600) && defined(_CHAR16T) || (defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) && _HAS_CHAR16_T_LANGUAGE_SUPPORT) // VS2010+
-# define EA_CHAR16_NATIVE 1
-# elif defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 404) && (defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__STDC_VERSION__) || defined(_CHAR16T)) // g++ (C++ compiler) 4.4+ with -std=c++0x or gcc (C compiler) 4.4+ with -std=gnu99 or QNX660 has defined char16_t and char32_t in its yvals.h header
-# define EA_CHAR16_NATIVE 1
-# else
-# define EA_CHAR16_NATIVE 0
-# endif
+// To do: Change this to be based on EA_COMPILER_NO_NEW_CHARACTER_TYPES.
+#if defined(_MSC_VER) && (_MSC_VER >= 1600) && defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) && _HAS_CHAR16_T_LANGUAGE_SUPPORT // VS2010+
+#define EA_CHAR16_NATIVE 1
+#elif defined(EA_COMPILER_CLANG) && defined(EA_COMPILER_CPP11_ENABLED)
+#if __has_feature(cxx_unicode_literals)
+#define EA_CHAR16_NATIVE 1
+#elif (EA_COMPILER_VERSION >= 300) && !(defined(EA_PLATFORM_IPHONE) || defined(EA_PLATFORM_OSX))
+#define EA_CHAR16_NATIVE 1
+#elif defined(EA_PLATFORM_APPLE)
+#define EA_CHAR16_NATIVE 1
+#else
+#define EA_CHAR16_NATIVE 0
+#endif
+#elif defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 404) && defined(__CHAR16_TYPE__) && defined(EA_COMPILER_CPP11_ENABLED)// EDG 4.4+.
+#define EA_CHAR16_NATIVE 1
+#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
+#define EA_CHAR16_NATIVE 1
+#else
+#define EA_CHAR16_NATIVE 0
+#endif
#endif
-#if !defined(EA_CHAR32_NATIVE)
-# if defined(_MSC_VER) && (_MSC_VER >= 1600) && defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) && _HAS_CHAR16_T_LANGUAGE_SUPPORT // VS2010+
-# define EA_CHAR32_NATIVE 1
-# 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
-# define EA_CHAR32_NATIVE 1
-# else
-# define EA_CHAR32_NATIVE 0
-# endif
+#if !defined(EA_CHAR32_NATIVE) // Microsoft currently ties char32_t language support to char16_t language support. So we use CHAR16_T here.
+// To do: Change this to be based on EA_COMPILER_NO_NEW_CHARACTER_TYPES.
+#if defined(_MSC_VER) && (_MSC_VER >= 1600) && defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) && _HAS_CHAR16_T_LANGUAGE_SUPPORT // VS2010+
+#define EA_CHAR32_NATIVE 1
+#elif defined(EA_COMPILER_CLANG) && defined(EA_COMPILER_CPP11_ENABLED)
+#if __has_feature(cxx_unicode_literals)
+#define EA_CHAR32_NATIVE 1
+#elif (EA_COMPILER_VERSION >= 300) && !(defined(EA_PLATFORM_IPHONE) || defined(EA_PLATFORM_OSX))
+#define EA_CHAR32_NATIVE 1
+#elif defined(EA_PLATFORM_APPLE)
+#define EA_CHAR32_NATIVE 1
+#else
+#define EA_CHAR32_NATIVE 0
+#endif
+#elif defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 404) && defined(__CHAR32_TYPE__) && defined(EA_COMPILER_CPP11_ENABLED)// EDG 4.4+.
+#define EA_CHAR32_NATIVE 1
+#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
+#define EA_CHAR32_NATIVE 1
+#else
+#define EA_CHAR32_NATIVE 0
+#endif
+#endif
+
+
+#if EA_CHAR16_NATIVE || EA_CHAR32_NATIVE
+#define EA_WCHAR_UNIQUE 1
+#else
+#define EA_WCHAR_UNIQUE 0
+#endif
+
+
+// EA_CHAR8_UNIQUE
+//
+// Check for char8_t support in the cpp type system. Moving forward from c++20,
+// the char8_t type allows users to overload function for character encoding.
+//
+// EA_CHAR8_UNIQUE is 1 when the type is a unique in the type system and
+// can there be used as a valid overload. EA_CHAR8_UNIQUE is 0 otherwise.
+//
+// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0482r6.html
+//
+#ifdef __cpp_char8_t
+#define CHAR8_T_DEFINED
+#define EA_CHAR8_UNIQUE 1
+#else
+#define EA_CHAR8_UNIQUE 0
#endif
#ifndef CHAR8_T_DEFINED // If the user hasn't already defined these...
-# define CHAR8_T_DEFINED
-
-# if EA_CHAR16_NATIVE
- typedef char char8_t;
-
- // In C++, char16_t and char32_t are already defined by the compiler.
- // In MS C, char16_t and char32_t are already defined by the compiler/standard library.
- // In GCC C, __CHAR16_TYPE__ and __CHAR32_TYPE__ are defined instead, and we must define char16_t and char32_t from these.
-# if defined(__GNUC__) && !defined(__GXX_EXPERIMENTAL_CXX0X__) && defined(__CHAR16_TYPE__) // If using GCC and compiling in C...
- typedef __CHAR16_TYPE__ char16_t;
- typedef __CHAR32_TYPE__ char32_t;
-# endif
-# elif defined(EA_COMPILER_HAS_CHAR_16_32)
- typedef char char8_t;
-# elif (EA_WCHAR_SIZE == 2)
-# define _CHAR16T
- typedef char char8_t;
- typedef wchar_t char16_t;
- typedef uint32_t char32_t;
-# else
- typedef char char8_t;
- typedef uint16_t char16_t;
- typedef wchar_t char32_t;
-# endif
-#endif
-
-
-// EA_CHAR16 / EA_CHAR32
+#define CHAR8_T_DEFINED
+#if defined(EA_PLATFORM_APPLE)
+#define char8_t char // The Apple debugger is too stupid to realize char8_t is typedef'd to char, so we #define it.
+#else
+typedef char char8_t;
+#endif
+
+#if EA_CHAR16_NATIVE
+// In C++, char16_t and char32_t are already defined by the compiler.
+// In MS C, char16_t and char32_t are already defined by the compiler/standard library.
+// In GCC C, __CHAR16_TYPE__ and __CHAR32_TYPE__ are defined instead, and we must define char16_t and char32_t from these.
+#if defined(__GNUC__) && !defined(__GXX_EXPERIMENTAL_CXX0X__) && defined(__CHAR16_TYPE__) // If using GCC and compiling in C...
+typedef __CHAR16_TYPE__ char16_t;
+typedef __CHAR32_TYPE__ char32_t;
+#endif
+#elif (EA_WCHAR_SIZE == 2)
+#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.
+#if !defined(_CHAR16T)
+#define _CHAR16T
+#endif
+#if !defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) || !_HAS_CHAR16_T_LANGUAGE_SUPPORT
+typedef wchar_t char16_t;
+typedef uint32_t char32_t;
+#endif
+#else
+typedef wchar_t char16_t;
+typedef uint32_t char32_t;
+#endif
+#else
+typedef uint16_t char16_t;
+#if defined(__cplusplus)
+typedef wchar_t char32_t;
+#else
+typedef uint32_t char32_t;
+#endif
+#endif
+#endif
+
+
+// CHAR8_MIN, CHAR8_MAX, etc.
+//
+#define EA_LIMITS_DIGITS_S(T) ((sizeof(T) * 8) - 1)
+#define EA_LIMITS_DIGITS_U(T) ((sizeof(T) * 8))
+#define EA_LIMITS_DIGITS(T) ((EA_LIMITS_IS_SIGNED(T) ? EA_LIMITS_DIGITS_S(T) : EA_LIMITS_DIGITS_U(T)))
+#define EA_LIMITS_IS_SIGNED(T) ((T)(-1) < 0)
+#define EA_LIMITS_MIN_S(T) ((T)((T)1 << EA_LIMITS_DIGITS_S(T)))
+#define EA_LIMITS_MIN_U(T) ((T)0)
+#define EA_LIMITS_MIN(T) ((EA_LIMITS_IS_SIGNED(T) ? EA_LIMITS_MIN_S(T) : EA_LIMITS_MIN_U(T)))
+#define EA_LIMITS_MAX_S(T) ((T)(((((T)1 << (EA_LIMITS_DIGITS(T) - 1)) - 1) << 1) + 1))
+#define EA_LIMITS_MAX_U(T) ((T)~(T)0)
+#define EA_LIMITS_MAX(T) ((EA_LIMITS_IS_SIGNED(T) ? EA_LIMITS_MAX_S(T) : EA_LIMITS_MAX_U(T)))
+
+#if !defined(CHAR8_MIN)
+#define CHAR8_MIN EA_LIMITS_MIN(char8_t)
+#endif
+
+#if !defined(CHAR8_MAX)
+#define CHAR8_MAX EA_LIMITS_MAX(char8_t)
+#endif
+
+#if !defined(CHAR16_MIN)
+#define CHAR16_MIN EA_LIMITS_MIN(char16_t)
+#endif
+
+#if !defined(CHAR16_MAX)
+#define CHAR16_MAX EA_LIMITS_MAX(char16_t)
+#endif
+
+#if !defined(CHAR32_MIN)
+#define CHAR32_MIN EA_LIMITS_MIN(char32_t)
+#endif
+
+#if !defined(CHAR32_MAX)
+#define CHAR32_MAX EA_LIMITS_MAX(char32_t)
+#endif
+
+
+
+// EA_CHAR8 / EA_CHAR16 / EA_CHAR32 / EA_WCHAR
//
// Supports usage of portable string constants.
//
@@ -780,47 +814,104 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// const char16_t c = EA_CHAR16('\x3001');
// const char32_t c = EA_CHAR32('\x3001');
//
+#ifndef EA_CHAR8
+#if EA_CHAR8_UNIQUE
+#define EA_CHAR8(s) u8 ## s
+#else
+#define EA_CHAR8(s) s
+#endif
+#endif
+
+#ifndef EA_WCHAR
+#define EA_WCHAR_(s) L ## s
+#define EA_WCHAR(s) EA_WCHAR_(s)
+#endif
+
#ifndef EA_CHAR16
-# if EA_CHAR16_NATIVE && !defined(_MSC_VER) // Microsoft doesn't support char16_t string literals.
-# define EA_CHAR16(s) u ## s
-# elif (EA_WCHAR_SIZE == 2)
-# define EA_CHAR16(s) L ## s
-# else
- //#define EA_CHAR16(s) // Impossible to implement.
-# endif
+#if EA_CHAR16_NATIVE && !defined(_MSC_VER) // Microsoft doesn't support char16_t string literals.
+#define EA_CHAR16_(s) u ## s
+#define EA_CHAR16(s) EA_CHAR16_(s)
+#elif (EA_WCHAR_SIZE == 2)
+#if defined(_MSC_VER) && (_MSC_VER >= 1900) && defined(__cplusplus) // VS2015 supports u"" string literals.
+#define EA_CHAR16_(s) u ## s
+#define EA_CHAR16(s) EA_CHAR16_(s)
+#else
+#define EA_CHAR16_(s) L ## s
+#define EA_CHAR16(s) EA_CHAR16_(s)
+#endif
+#else
+//#define EA_CHAR16(s) // Impossible to implement efficiently.
+#endif
#endif
#ifndef EA_CHAR32
-# if EA_CHAR32_NATIVE && !defined(_MSC_VER) // Microsoft doesn't support char32_t string literals.
-# define EA_CHAR32(s) U ## s
-# elif (EA_WCHAR_SIZE == 2)
- //#define EA_CHAR32(s) // Impossible to implement.
-# else
-# define EA_CHAR32(s) L ## s
-# endif
+#if EA_CHAR32_NATIVE && !defined(_MSC_VER) // Microsoft doesn't support char32_t string literals.
+#define EA_CHAR32_(s) U ## s
+#define EA_CHAR32(s) EA_CHAR32_(s)
+#elif (EA_WCHAR_SIZE == 2)
+#if defined(_MSC_VER) && (_MSC_VER >= 1900) && defined(__cplusplus) // VS2015 supports u"" string literals.
+#define EA_CHAR32_(s) U ## s
+#define EA_CHAR32(s) EA_CHAR32_(s)
+#else
+//#define EA_CHAR32(s) // Impossible to implement.
+#endif
+#elif (EA_WCHAR_SIZE == 4)
+#define EA_CHAR32_(s) L ## s
+#define EA_CHAR32(s) EA_CHAR32_(s)
+#else
+#error Unexpected size of wchar_t
+#endif
#endif
+// EAText8 / EAText16
+//
+// Provided for backwards compatibility with older code.
+//
+#if defined(EABASE_ENABLE_EATEXT_MACROS)
+#define EAText8(x) x
+#define EAChar8(x) x
+
+#define EAText16(x) EA_CHAR16(x)
+#define EAChar16(x) EA_CHAR16(x)
+#endif
+
+
+
// ------------------------------------------------------------------------
// EAArrayCount
//
// Returns the count of items in a built-in C array. This is a common technique
-// which is often used to help properly calculate the number of items in an
+// which is often used to help properly calculate the number of items in an
// array at runtime in order to prevent overruns, etc.
//
// Example usage:
// int array[75];
// size_t arrayCount = EAArrayCount(array); // arrayCount is 75.
//
+#if defined(EA_COMPILER_NO_CONSTEXPR)
#ifndef EAArrayCount
-# define EAArrayCount(x) (sizeof(x) / sizeof(x[0]))
+#define EAArrayCount(x) (sizeof(x) / sizeof(x[0]))
+#endif
+#else
+// This C++11 version is a little smarter than the macro version above;
+// it can tell the difference between arrays and pointers. Other simpler
+// templated versions have failed in various subtle ways.
+
+template <typename T, size_t N>
+char (&EAArraySizeHelper(T (&x)[N]))[N];
+
+template <typename T, size_t N>
+char (&EAArraySizeHelper(T (&&x)[N]))[N];
+
+#define EAArrayCount(x) (sizeof(EAArraySizeHelper(x)))
#endif
// ------------------------------------------------------------------------
// static_assert
//
-// C++0x static_assert (a.k.a. compile-time assert).
+// C++11 static_assert (a.k.a. compile-time assert).
//
// Specification:
// void static_assert(bool const_expression, const char* description);
@@ -828,57 +919,92 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Example usage:
// static_assert(sizeof(int) == 4, "int must be 32 bits");
//
-#if !defined(EABASE_STATIC_ASSERT_ENABLED)
-# if defined(EA_DEBUG) || defined(_DEBUG)
-# define EABASE_STATIC_ASSERT_ENABLED 1
-# else
-# define EABASE_STATIC_ASSERT_ENABLED 0
-# endif
+#if defined(_MSC_VER) && (_MSC_VER >= 1600) && defined(__cplusplus)
+// static_assert is defined by the compiler for both C and C++.
+#elif !defined(__cplusplus) && defined(EA_PLATFORM_ANDROID) && ((defined(__STDC_VERSION__) && __STDC_VERSION__ < 201100L) || !defined(__STDC_VERSION__))
+// AndroidNDK does not support static_assert despite claiming it's a C11 compiler
+#define NEED_CUSTOM_STATIC_ASSERT
+#elif defined(__clang__) && defined(__cplusplus)
+// We need to separate these checks on a new line, as the pre-processor on other compilers will fail on the _has_feature macros
+#if !(__has_feature(cxx_static_assert) || __has_extension(cxx_static_assert))
+#define NEED_CUSTOM_STATIC_ASSERT
#endif
-
-#ifndef EA_PREPROCESSOR_JOIN
-# define EA_PREPROCESSOR_JOIN(a, b) EA_PREPROCESSOR_JOIN1(a, b)
-# define EA_PREPROCESSOR_JOIN1(a, b) EA_PREPROCESSOR_JOIN2(a, b)
-# define EA_PREPROCESSOR_JOIN2(a, b) a##b
+#elif defined(__GNUC__) && (defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(__cplusplus) && (__cplusplus >= 201103L)))
+// static_assert is defined by the compiler.
+#elif defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401) && defined(EA_COMPILER_CPP11_ENABLED)
+// static_assert is defined by the compiler.
+#elif !defined(__cplusplus) && defined(__GLIBC__) && defined(__USE_ISOC11)
+// static_assert is defined by the compiler.
+#elif !defined(__cplusplus) && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201100L
+// static_assert is defined by the compiler.
+#else
+#define NEED_CUSTOM_STATIC_ASSERT
#endif
-#if defined(_MSC_VER) && (_MSC_VER >= 1600)
- // static_assert is defined by the compiler for both C and C++.
-#elif defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
- // static_assert is defined by the compiler.
-#elif defined(__clang__) && __has_feature(cxx_static_assert)
- // static_assert is defined by the compiler.
-#elif defined(EA_COMPILER_GHS)
- // static_assert is defined by the compiler.
+#ifdef NEED_CUSTOM_STATIC_ASSERT
+#ifdef __GNUC__
+// On GCC the 'unused' attribute can be used to indicate a typedef is not actually used
+// (such as in the static_assert implementation below). New versions of GCC generate
+// warnings for unused typedefs in function/method scopes.
+#define EA_STATIC_ASSERT_UNUSED_ATTRIBUTE __attribute__((unused))
#else
-# if EABASE_STATIC_ASSERT_ENABLED
-# if defined(__COUNTER__) // If this VC++ extension is available...
-# define static_assert(expression, description) enum { EA_PREPROCESSOR_JOIN(static_assert_, __COUNTER__) = 1 / ((!!(expression)) ? 1 : 0) }
-# else
-# define static_assert(expression, description) enum { EA_PREPROCESSOR_JOIN(static_assert_, __LINE__) = 1 / ((!!(expression)) ? 1 : 0) }
-# endif
-# else
-# if defined(EA_COMPILER_METROWERKS)
-# if defined(__cplusplus)
-# define static_assert(expression, description) struct EA_PREPROCESSOR_JOIN(EACTAssertUnused_, __LINE__){ }
-# else
-# define static_assert(expression, description) enum { EA_PREPROCESSOR_JOIN(static_assert_, __LINE__) = 1 / ((!!(expression)) ? 1 : 0) }
-# endif
-# else
-# define static_assert(expression, description)
-# endif
-# endif
+#define EA_STATIC_ASSERT_UNUSED_ATTRIBUTE
#endif
+#define EA_STATIC_ASSERT_TOKEN_PASTE(a,b) a ## b
+#define EA_STATIC_ASSERT_CONCATENATE_HELPER(a,b) EA_STATIC_ASSERT_TOKEN_PASTE(a,b)
-#if defined(__cplusplus)
+#if defined(__COUNTER__) // If this extension is available, which allows multiple statements per line...
+#define static_assert(expression, description) typedef char EA_STATIC_ASSERT_CONCATENATE_HELPER(compileTimeAssert,__COUNTER__) [((expression) != 0) ? 1 : -1] EA_STATIC_ASSERT_UNUSED_ATTRIBUTE
+#else
+#define static_assert(expression, description) typedef char EA_STATIC_ASSERT_CONCATENATE_HELPER(compileTimeAssert,__LINE__) [((expression) != 0) ? 1 : -1] EA_STATIC_ASSERT_UNUSED_ATTRIBUTE
#endif
-#endif // Header include guard
+#undef NEED_CUSTOM_STATIC_ASSERT
+#endif
+// ------------------------------------------------------------------------
+// EA_IS_ENABLED
+//
+// EA_IS_ENABLED is intended to be used for detecting if compile time features are enabled or disabled.
+//
+// It has some advantages over using a standard #if or #ifdef tests:
+// 1) Fails to compile when passes numeric macro values. Valid options are strictly enabled or disabled.
+// 2) Fails to compile when passed undefined macro values rather than disabling by default
+// 3) Fails to compile when the passed macro is defined to but empty
+//
+// To use the macro, the calling code should create a define for the feature to enable or disable. This feature define
+// must be set to either EA_ENABLED or EA_DISABLED. (Do not try to set the feature define directly to some other
+// value.)
+//
+// Note: These macros are analogous to the Frostbite macro FB_USING used in combination with FB_OFF / FB_ON and are
+// designed to be compatible to support gradual migration.
+//
+// Example usage:
+//
+// // The USER_PROVIDED_FEATURE_DEFINE should be defined as either
+// // EA_ENABLED or EA_DISABLED.
+// #define USER_PROVIDED_FEATURE_DEFINE EA_ENABLED
+//
+// #if EA_IS_ENABLED(USER_PROVIDED_FEATURE_DEFINE)
+// // USER_PROVIDED_FEATURE_DEFINE is enabled
+// #else
+// // USER_PROVIDED_FEATURE_DEFINE is disabled
+// #endif
+//
+#define EA_ENABLED 111-
+#define EA_DISABLED 333-
+// 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
+#define EA_IS_ENABLED(x) (333 == 333 * 111 / ((x 0) * (((x 0) == 333 ? 1 : 0) + ((x 0) == 111 ? 1 : 0))))
+// Define int128_t / uint128_t types.
+// NOTE(rparolin): include file at the end because we want all the signed integral types defined.
+#ifdef __cplusplus
+#include <EABase/int128.h>
+#endif
+#endif // Header include guard