diff options
Diffstat (limited to 'UnknownVersion/include/EABase/eabase.h')
-rw-r--r-- | UnknownVersion/include/EABase/eabase.h | 1524 |
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 |