diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2021-04-08 16:45:12 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2021-04-08 16:45:12 +0200 |
commit | 3c534012646b0a68566a494d76fde274e29bfb9e (patch) | |
tree | 36126ee7113361e9a26c42b7fa2ee5570770081d /include/Common |
Squashed 'EASTL/test/packages/EABase/' content from commit 9816bb9
git-subtree-dir: EASTL/test/packages/EABase
git-subtree-split: 9816bb911b17f9ee593ad0913a036a175aeaece7
Diffstat (limited to 'include/Common')
-rw-r--r-- | include/Common/EABase/config/eacompiler.h | 1778 | ||||
-rw-r--r-- | include/Common/EABase/config/eacompilertraits.h | 2561 | ||||
-rw-r--r-- | include/Common/EABase/config/eaplatform.h | 738 | ||||
-rw-r--r-- | include/Common/EABase/eabase.h | 1011 | ||||
-rw-r--r-- | include/Common/EABase/eahave.h | 877 | ||||
-rw-r--r-- | include/Common/EABase/earesult.h | 62 | ||||
-rw-r--r-- | include/Common/EABase/eastdarg.h | 99 | ||||
-rw-r--r-- | include/Common/EABase/eaunits.h | 54 | ||||
-rw-r--r-- | include/Common/EABase/int128.h | 1268 | ||||
-rw-r--r-- | include/Common/EABase/nullptr.h | 102 | ||||
-rw-r--r-- | include/Common/EABase/version.h | 36 |
11 files changed, 8586 insertions, 0 deletions
diff --git a/include/Common/EABase/config/eacompiler.h b/include/Common/EABase/config/eacompiler.h new file mode 100644 index 0000000..bd656ed --- /dev/null +++ b/include/Common/EABase/config/eacompiler.h @@ -0,0 +1,1778 @@ +/*----------------------------------------------------------------------------- + * config/eacompiler.h + * + * Copyright (c) Electronic Arts Inc. All rights reserved. + *----------------------------------------------------------------------------- + * Currently supported defines include: + * EA_COMPILER_GNUC + * EA_COMPILER_ARM + * EA_COMPILER_EDG + * EA_COMPILER_SN + * EA_COMPILER_MSVC + * EA_COMPILER_METROWERKS + * EA_COMPILER_INTEL + * EA_COMPILER_BORLANDC + * EA_COMPILER_IBM + * EA_COMPILER_QNX + * EA_COMPILER_GREEN_HILLS + * EA_COMPILER_CLANG + * EA_COMPILER_CLANG_CL + * + * EA_COMPILER_VERSION = <integer> + * EA_COMPILER_NAME = <string> + * EA_COMPILER_STRING = <string> + * + * EA_COMPILER_VA_COPY_REQUIRED + * + * C++98/03 functionality + * EA_COMPILER_NO_STATIC_CONSTANTS + * EA_COMPILER_NO_TEMPLATE_SPECIALIZATION + * EA_COMPILER_NO_TEMPLATE_PARTIAL_SPECIALIZATION + * EA_COMPILER_NO_MEMBER_TEMPLATES + * EA_COMPILER_NO_MEMBER_TEMPLATE_SPECIALIZATION + * EA_COMPILER_NO_TEMPLATE_TEMPLATES + * EA_COMPILER_NO_MEMBER_TEMPLATE_FRIENDS + * EA_COMPILER_NO_VOID_RETURNS + * EA_COMPILER_NO_COVARIANT_RETURN_TYPE + * EA_COMPILER_NO_DEDUCED_TYPENAME + * EA_COMPILER_NO_ARGUMENT_DEPENDENT_LOOKUP + * EA_COMPILER_NO_EXCEPTION_STD_NAMESPACE + * EA_COMPILER_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS + * EA_COMPILER_NO_RTTI + * EA_COMPILER_NO_EXCEPTIONS + * EA_COMPILER_NO_NEW_THROW_SPEC + * EA_THROW_SPEC_NEW / EA_THROW_SPEC_DELETE + * EA_COMPILER_NO_UNWIND + * EA_COMPILER_NO_STANDARD_CPP_LIBRARY + * EA_COMPILER_NO_STATIC_VARIABLE_INIT + * EA_COMPILER_NO_STATIC_FUNCTION_INIT + * EA_COMPILER_NO_VARIADIC_MACROS + * + * C++11 functionality + * EA_COMPILER_NO_RVALUE_REFERENCES + * EA_COMPILER_NO_EXTERN_TEMPLATE + * EA_COMPILER_NO_RANGE_BASED_FOR_LOOP + * EA_COMPILER_NO_CONSTEXPR + * EA_COMPILER_NO_OVERRIDE + * EA_COMPILER_NO_INHERITANCE_FINAL + * EA_COMPILER_NO_NULLPTR + * EA_COMPILER_NO_AUTO + * EA_COMPILER_NO_DECLTYPE + * EA_COMPILER_NO_DEFAULTED_FUNCTIONS + * EA_COMPILER_NO_DELETED_FUNCTIONS + * EA_COMPILER_NO_LAMBDA_EXPRESSIONS + * EA_COMPILER_NO_TRAILING_RETURN_TYPES + * EA_COMPILER_NO_STRONGLY_TYPED_ENUMS + * EA_COMPILER_NO_FORWARD_DECLARED_ENUMS + * EA_COMPILER_NO_VARIADIC_TEMPLATES + * EA_COMPILER_NO_TEMPLATE_ALIASES + * EA_COMPILER_NO_INITIALIZER_LISTS + * EA_COMPILER_NO_NORETURN + * EA_COMPILER_NO_CARRIES_DEPENDENCY + * EA_COMPILER_NO_FALLTHROUGH + * EA_COMPILER_NO_NODISCARD + * EA_COMPILER_NO_MAYBE_UNUSED + * EA_COMPILER_NO_NONSTATIC_MEMBER_INITIALIZERS + * EA_COMPILER_NO_RIGHT_ANGLE_BRACKETS + * EA_COMPILER_NO_ALIGNOF + * EA_COMPILER_NO_ALIGNAS + * EA_COMPILER_NO_DELEGATING_CONSTRUCTORS + * EA_COMPILER_NO_INHERITING_CONSTRUCTORS + * EA_COMPILER_NO_USER_DEFINED_LITERALS + * EA_COMPILER_NO_STANDARD_LAYOUT_TYPES + * EA_COMPILER_NO_EXTENDED_SIZEOF + * EA_COMPILER_NO_INLINE_NAMESPACES + * EA_COMPILER_NO_UNRESTRICTED_UNIONS + * EA_COMPILER_NO_EXPLICIT_CONVERSION_OPERATORS + * EA_COMPILER_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS + * EA_COMPILER_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS + * EA_COMPILER_NO_NOEXCEPT + * EA_COMPILER_NO_RAW_LITERALS + * EA_COMPILER_NO_UNICODE_STRING_LITERALS + * EA_COMPILER_NO_NEW_CHARACTER_TYPES + * EA_COMPILER_NO_UNICODE_CHAR_NAME_LITERALS + * EA_COMPILER_NO_UNIFIED_INITIALIZATION_SYNTAX + * EA_COMPILER_NO_EXTENDED_FRIEND_DECLARATIONS + * + * C++14 functionality + * EA_COMPILER_NO_VARIABLE_TEMPLATES + * + * C++17 functionality + * EA_COMPILER_NO_INLINE_VARIABLES + * EA_COMPILER_NO_ALIGNED_NEW + * + * C++20 functionality + * EA_COMPILER_NO_DESIGNATED_INITIALIZERS + * + *----------------------------------------------------------------------------- + * + * Supplemental documentation + * EA_COMPILER_NO_STATIC_CONSTANTS + * Code such as this is legal, but some compilers fail to compile it: + * struct A{ static const a = 1; }; + * + * EA_COMPILER_NO_TEMPLATE_SPECIALIZATION + * Some compilers fail to allow template specialization, such as with this: + * template<class U> void DoSomething(U u); + * void DoSomething(int x); + * + * EA_COMPILER_NO_TEMPLATE_PARTIAL_SPECIALIZATION + * Some compilers fail to allow partial template specialization, such as with this: + * template <class T, class Allocator> class vector{ }; // Primary templated class. + * template <class Allocator> class vector<bool, Allocator>{ }; // Partially specialized version. + * + * EA_COMPILER_NO_MEMBER_TEMPLATES + * Some compilers fail to allow member template functions such as this: + * struct A{ template<class U> void DoSomething(U u); }; + * + * EA_COMPILER_NO_MEMBER_TEMPLATE_SPECIALIZATION + * Some compilers fail to allow member template specialization, such as with this: + * struct A{ + * template<class U> void DoSomething(U u); + * void DoSomething(int x); + * }; + * + * EA_COMPILER_NO_TEMPLATE_TEMPLATES + * Code such as this is legal: + * template<typename T, template<typename> class U> + * U<T> SomeFunction(const U<T> x) { return x.DoSomething(); } + * + * EA_COMPILER_NO_MEMBER_TEMPLATE_FRIENDS + * Some compilers fail to compile templated friends, as with this: + * struct A{ template<class U> friend class SomeFriend; }; + * This is described in the C++ Standard at 14.5.3. + * + * EA_COMPILER_NO_VOID_RETURNS + * This is legal C++: + * void DoNothing1(){ }; + * void DoNothing2(){ return DoNothing1(); } + * + * EA_COMPILER_NO_COVARIANT_RETURN_TYPE + * See the C++ standard sec 10.3,p5. + * + * EA_COMPILER_NO_DEDUCED_TYPENAME + * Some compilers don't support the use of 'typename' for + * dependent types in deduced contexts, as with this: + * template <class T> void Function(T, typename T::type); + * + * EA_COMPILER_NO_ARGUMENT_DEPENDENT_LOOKUP + * Also known as Koenig lookup. Basically, if you have a function + * that is a namespace and you call that function without prefixing + * it with the namespace the compiler should look at any arguments + * you pass to that function call and search their namespace *first* + * to see if the given function exists there. + * + * EA_COMPILER_NO_EXCEPTION_STD_NAMESPACE + * <exception> is in namespace std. Some std libraries fail to + * put the contents of <exception> in namespace std. The following + * code should normally be legal: + * void Function(){ std::terminate(); } + * + * EA_COMPILER_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS + * Some compilers fail to execute DoSomething() properly, though they + * succeed in compiling it, as with this: + * template <int i> + * bool DoSomething(int j){ return i == j; }; + * DoSomething<1>(2); + * + * EA_COMPILER_NO_EXCEPTIONS + * The compiler is configured to disallow the use of try/throw/catch + * syntax (often to improve performance). Use of such syntax in this + * case will cause a compilation error. + * + * EA_COMPILER_NO_UNWIND + * The compiler is configured to allow the use of try/throw/catch + * syntax and behaviour but disables the generation of stack unwinding + * code for responding to exceptions (often to improve performance). + * + *---------------------------------------------------------------------------*/ + +#ifndef INCLUDED_eacompiler_H +#define INCLUDED_eacompiler_H + + #include <EABase/config/eaplatform.h> + + // Note: This is used to generate the EA_COMPILER_STRING macros + #ifndef INTERNAL_STRINGIZE + #define INTERNAL_STRINGIZE(x) INTERNAL_PRIMITIVE_STRINGIZE(x) + #endif + #ifndef INTERNAL_PRIMITIVE_STRINGIZE + #define INTERNAL_PRIMITIVE_STRINGIZE(x) #x + #endif + + // EA_COMPILER_HAS_FEATURE + #ifndef EA_COMPILER_HAS_FEATURE + #if defined(__clang__) + #define EA_COMPILER_HAS_FEATURE(x) __has_feature(x) + #else + #define EA_COMPILER_HAS_FEATURE(x) 0 + #endif + #endif + + + // EA_COMPILER_HAS_BUILTIN + #ifndef EA_COMPILER_HAS_BUILTIN + #if defined(__clang__) + #define EA_COMPILER_HAS_BUILTIN(x) __has_builtin(x) + #else + #define EA_COMPILER_HAS_BUILTIN(x) 0 + #endif + #endif + + + // EDG (EDG compiler front-end, used by other compilers such as SN) + #if defined(__EDG_VERSION__) + #define EA_COMPILER_EDG 1 + + #if defined(_MSC_VER) + #define EA_COMPILER_EDG_VC_MODE 1 + #endif + #if defined(__GNUC__) + #define EA_COMPILER_EDG_GCC_MODE 1 + #endif + #endif + + // EA_COMPILER_WINRTCX_ENABLED + // + // Defined as 1 if the compiler has its available C++/CX support enabled, else undefined. + // This specifically means the corresponding compilation unit has been built with Windows Runtime + // Components enabled, usually via the '-ZW' compiler flags being used. This option allows for using + // ref counted hat-type '^' objects and other C++/CX specific keywords like "ref new" + #if !defined(EA_COMPILER_WINRTCX_ENABLED) && defined(__cplusplus_winrt) + #define EA_COMPILER_WINRTCX_ENABLED 1 + #endif + + + // EA_COMPILER_CPP11_ENABLED + // + // Defined as 1 if the compiler has its available C++11 support enabled, else undefined. + // This does not mean that all of C++11 or any particular feature of C++11 is supported + // by the compiler. It means that whatever C++11 support the compiler has is enabled. + // This also includes existing and older compilers that still identify C++11 as C++0x. + // + // We cannot use (__cplusplus >= 201103L) alone because some compiler vendors have + // decided to not define __cplusplus like thus until they have fully completed their + // C++11 support. + // + #if !defined(EA_COMPILER_CPP11_ENABLED) && defined(__cplusplus) + #if (__cplusplus >= 201103L) // Clang and GCC defines this like so in C++11 mode. + #define EA_COMPILER_CPP11_ENABLED 1 + #elif defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__) + #define EA_COMPILER_CPP11_ENABLED 1 + #elif defined(_MSC_VER) && _MSC_VER >= 1600 // Microsoft unilaterally enables its C++11 support; there is no way to disable it. + #define EA_COMPILER_CPP11_ENABLED 1 + #elif defined(__EDG_VERSION__) // && ??? + // To do: Is there a generic way to determine this? + #endif + #endif + + + // EA_COMPILER_CPP14_ENABLED + // + // Defined as 1 if the compiler has its available C++14 support enabled, else undefined. + // This does not mean that all of C++14 or any particular feature of C++14 is supported + // by the compiler. It means that whatever C++14 support the compiler has is enabled. + // + // We cannot use (__cplusplus >= 201402L) alone because some compiler vendors have + // decided to not define __cplusplus like thus until they have fully completed their + // C++14 support. + #if !defined(EA_COMPILER_CPP14_ENABLED) && defined(__cplusplus) + #if (__cplusplus >= 201402L) // Clang and GCC defines this like so in C++14 mode. + #define EA_COMPILER_CPP14_ENABLED 1 + #elif defined(_MSC_VER) && (_MSC_VER >= 1900) // VS2015+ + #define EA_COMPILER_CPP14_ENABLED 1 + #endif + #endif + + + // EA_COMPILER_CPP17_ENABLED + // + // Defined as 1 if the compiler has its available C++17 support enabled, else undefined. + // This does not mean that all of C++17 or any particular feature of C++17 is supported + // by the compiler. It means that whatever C++17 support the compiler has is enabled. + // + // We cannot use (__cplusplus >= 201703L) alone because some compiler vendors have + // decided to not define __cplusplus like thus until they have fully completed their + // C++17 support. + #if !defined(EA_COMPILER_CPP17_ENABLED) && defined(__cplusplus) + #if (__cplusplus >= 201703L) + #define EA_COMPILER_CPP17_ENABLED 1 + #elif defined(_MSVC_LANG) && (_MSVC_LANG >= 201703L) // C++17+ + #define EA_COMPILER_CPP17_ENABLED 1 + #endif + #endif + + + // EA_COMPILER_CPP20_ENABLED + // + // Defined as 1 if the compiler has its available C++20 support enabled, else undefined. + // This does not mean that all of C++20 or any particular feature of C++20 is supported + // by the compiler. It means that whatever C++20 support the compiler has is enabled. + // + // We cannot use (__cplusplus >= 202003L) alone because some compiler vendors have + // decided to not define __cplusplus like thus until they have fully completed their + // C++20 support. + #if !defined(EA_COMPILER_CPP20_ENABLED) && defined(__cplusplus) + // TODO(rparoin): enable once a C++20 value for the __cplusplus macro has been published + // #if (__cplusplus >= 202003L) + // #define EA_COMPILER_CPP20_ENABLED 1 + // #elif defined(_MSVC_LANG) && (_MSVC_LANG >= 202003L) // C++20+ + // #define EA_COMPILER_CPP20_ENABLED 1 + // #endif + #endif + + + + #if defined(__ARMCC_VERSION) + // Note that this refers to the ARM RVCT compiler (armcc or armcpp), but there + // are other compilers that target ARM processors, such as GCC and Microsoft VC++. + // If you want to detect compiling for the ARM processor, check for EA_PROCESSOR_ARM + // being defined. + // This compiler is also identified by defined(__CC_ARM) || defined(__ARMCC__). + #define EA_COMPILER_RVCT 1 + #define EA_COMPILER_ARM 1 + #define EA_COMPILER_VERSION __ARMCC_VERSION + #define EA_COMPILER_NAME "RVCT" + //#define EA_COMPILER_STRING (defined below) + + // Clang's GCC-compatible driver. + #elif defined(__clang__) && !defined(_MSC_VER) + #define EA_COMPILER_CLANG 1 + #define EA_COMPILER_VERSION (__clang_major__ * 100 + __clang_minor__) + #define EA_COMPILER_NAME "clang" + #define EA_COMPILER_STRING EA_COMPILER_NAME __clang_version__ + + // GCC (a.k.a. GNUC) + #elif defined(__GNUC__) // GCC compilers exist for many platforms. + #define EA_COMPILER_GNUC 1 + #define EA_COMPILER_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) + #define EA_COMPILER_NAME "GCC" + #define EA_COMPILER_STRING EA_COMPILER_NAME " compiler, version " INTERNAL_STRINGIZE( __GNUC__ ) "." INTERNAL_STRINGIZE( __GNUC_MINOR__ ) + + #if (__GNUC__ == 2) && (__GNUC_MINOR__ < 95) // If GCC < 2.95... + #define EA_COMPILER_NO_MEMBER_TEMPLATES 1 + #endif + #if (__GNUC__ == 2) && (__GNUC_MINOR__ <= 97) // If GCC <= 2.97... + #define EA_COMPILER_NO_MEMBER_TEMPLATE_FRIENDS 1 + #endif + #if (__GNUC__ == 3) && ((__GNUC_MINOR__ == 1) || (__GNUC_MINOR__ == 2)) // If GCC 3.1 or 3.2 (but not pre 3.1 or post 3.2)... + #define EA_COMPILER_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS 1 + #endif + + // Borland C++ + #elif defined(__BORLANDC__) + #define EA_COMPILER_BORLANDC 1 + #define EA_COMPILER_VERSION __BORLANDC__ + #define EA_COMPILER_NAME "Borland C" + //#define EA_COMPILER_STRING (defined below) + + #if (__BORLANDC__ <= 0x0550) // If Borland C++ Builder 4 and 5... + #define EA_COMPILER_NO_MEMBER_TEMPLATE_FRIENDS 1 + #endif + #if (__BORLANDC__ >= 0x561) && (__BORLANDC__ < 0x600) + #define EA_COMPILER_NO_MEMBER_FUNCTION_SPECIALIZATION 1 + #endif + + + // Intel C++ + // The Intel Windows compiler masquerades as VC++ and defines _MSC_VER. + // The Intel compiler is based on the EDG compiler front-end. + #elif defined(__ICL) || defined(__ICC) + #define EA_COMPILER_INTEL 1 + + // Should we enable the following? We probably should do so since enabling it does a lot more good than harm + // for users. The Intel Windows compiler does a pretty good job of emulating VC++ and so the user would likely + // have to handle few special cases where the Intel compiler doesn't emulate VC++ correctly. + #if defined(_MSC_VER) + #define EA_COMPILER_MSVC 1 + #define EA_COMPILER_MICROSOFT 1 + #endif + + // Should we enable the following? This isn't as clear because as of this writing we don't know if the Intel + // compiler truly emulates GCC well enough that enabling this does more good than harm. + #if defined(__GNUC__) + #define EA_COMPILER_GNUC 1 + #endif + + #if defined(__ICL) + #define EA_COMPILER_VERSION __ICL + #elif defined(__ICC) + #define EA_COMPILER_VERSION __ICC + #endif + #define EA_COMPILER_NAME "Intel C++" + #if defined(_MSC_VER) + #define EA_COMPILER_STRING EA_COMPILER_NAME " compiler, version " INTERNAL_STRINGIZE( EA_COMPILER_VERSION ) ", EDG version " INTERNAL_STRINGIZE( __EDG_VERSION__ ) ", VC++ version " INTERNAL_STRINGIZE( _MSC_VER ) + #elif defined(__GNUC__) + #define EA_COMPILER_STRING EA_COMPILER_NAME " compiler, version " INTERNAL_STRINGIZE( EA_COMPILER_VERSION ) ", EDG version " INTERNAL_STRINGIZE( __EDG_VERSION__ ) ", GCC version " INTERNAL_STRINGIZE( __GNUC__ ) + #else + #define EA_COMPILER_STRING EA_COMPILER_NAME " compiler, version " INTERNAL_STRINGIZE( EA_COMPILER_VERSION ) ", EDG version " INTERNAL_STRINGIZE( __EDG_VERSION__ ) + #endif + + + #elif defined(_MSC_VER) + #define EA_COMPILER_MSVC 1 + #define EA_COMPILER_MICROSOFT 1 + #define EA_COMPILER_VERSION _MSC_VER + #define EA_COMPILER_NAME "Microsoft Visual C++" + //#define EA_COMPILER_STRING (defined below) + + #if defined(__clang__) + // Clang's MSVC-compatible driver. + #define EA_COMPILER_CLANG_CL 1 + #endif + + #define EA_STANDARD_LIBRARY_MSVC 1 + #define EA_STANDARD_LIBRARY_MICROSOFT 1 + + #if (_MSC_VER <= 1200) // If VC6.x and earlier... + #if (_MSC_VER < 1200) + #define EA_COMPILER_MSVCOLD 1 + #else + #define EA_COMPILER_MSVC6 1 + #endif + + #if (_MSC_VER < 1200) // If VC5.x or earlier... + #define EA_COMPILER_NO_TEMPLATE_SPECIALIZATION 1 + #endif + #define EA_COMPILER_NO_EXPLICIT_FUNCTION_TEMPLATE_ARGUMENTS 1 // The compiler compiles this OK, but executes it wrong. Fixed in VC7.0 + #define EA_COMPILER_NO_VOID_RETURNS 1 // The compiler fails to compile such cases. Fixed in VC7.0 + #define EA_COMPILER_NO_EXCEPTION_STD_NAMESPACE 1 // The compiler fails to compile such cases. Fixed in VC7.0 + #define EA_COMPILER_NO_DEDUCED_TYPENAME 1 // The compiler fails to compile such cases. Fixed in VC7.0 + #define EA_COMPILER_NO_STATIC_CONSTANTS 1 // The compiler fails to compile such cases. Fixed in VC7.0 + #define EA_COMPILER_NO_COVARIANT_RETURN_TYPE 1 // The compiler fails to compile such cases. Fixed in VC7.1 + #define EA_COMPILER_NO_ARGUMENT_DEPENDENT_LOOKUP 1 // The compiler compiles this OK, but executes it wrong. Fixed in VC7.1 + #define EA_COMPILER_NO_TEMPLATE_TEMPLATES 1 // The compiler fails to compile such cases. Fixed in VC7.1 + #define EA_COMPILER_NO_TEMPLATE_PARTIAL_SPECIALIZATION 1 // The compiler fails to compile such cases. Fixed in VC7.1 + #define EA_COMPILER_NO_MEMBER_TEMPLATE_FRIENDS 1 // The compiler fails to compile such cases. Fixed in VC7.1 + //#define EA_COMPILER_NO_MEMBER_TEMPLATES 1 // VC6.x supports member templates properly 95% of the time. So do we flag the remaining 5%? + //#define EA_COMPILER_NO_MEMBER_TEMPLATE_SPECIALIZATION 1 // VC6.x supports member templates properly 95% of the time. So do we flag the remaining 5%? + + #elif (_MSC_VER <= 1300) // If VC7.0 and earlier... + #define EA_COMPILER_MSVC7 1 + + #define EA_COMPILER_NO_COVARIANT_RETURN_TYPE 1 // The compiler fails to compile such cases. Fixed in VC7.1 + #define EA_COMPILER_NO_ARGUMENT_DEPENDENT_LOOKUP 1 // The compiler compiles this OK, but executes it wrong. Fixed in VC7.1 + #define EA_COMPILER_NO_TEMPLATE_TEMPLATES 1 // The compiler fails to compile such cases. Fixed in VC7.1 + #define EA_COMPILER_NO_TEMPLATE_PARTIAL_SPECIALIZATION 1 // The compiler fails to compile such cases. Fixed in VC7.1 + #define EA_COMPILER_NO_MEMBER_TEMPLATE_FRIENDS 1 // The compiler fails to compile such cases. Fixed in VC7.1 + #define EA_COMPILER_NO_MEMBER_FUNCTION_SPECIALIZATION 1 // This is the case only for VC7.0 and not VC6 or VC7.1+. Fixed in VC7.1 + //#define EA_COMPILER_NO_MEMBER_TEMPLATES 1 // VC7.0 supports member templates properly 95% of the time. So do we flag the remaining 5%? + + #elif (_MSC_VER < 1400) // VS2003 _MSC_VER of 1300 means VC7 (VS2003) + // The VC7.1 and later compiler is fairly close to the C++ standard + // and thus has no compiler limitations that we are concerned about. + #define EA_COMPILER_MSVC7_2003 1 + #define EA_COMPILER_MSVC7_1 1 + + #elif (_MSC_VER < 1500) // VS2005 _MSC_VER of 1400 means VC8 (VS2005) + #define EA_COMPILER_MSVC8_2005 1 + #define EA_COMPILER_MSVC8_0 1 + + #elif (_MSC_VER < 1600) // VS2008. _MSC_VER of 1500 means VC9 (VS2008) + #define EA_COMPILER_MSVC9_2008 1 + #define EA_COMPILER_MSVC9_0 1 + + #elif (_MSC_VER < 1700) // VS2010 _MSC_VER of 1600 means VC10 (VS2010) + #define EA_COMPILER_MSVC_2010 1 + #define EA_COMPILER_MSVC10_0 1 + + #elif (_MSC_VER < 1800) // VS2012 _MSC_VER of 1700 means VS2011/VS2012 + #define EA_COMPILER_MSVC_2011 1 // Microsoft changed the name to VS2012 before shipping, despite referring to it as VS2011 up to just a few weeks before shipping. + #define EA_COMPILER_MSVC11_0 1 + #define EA_COMPILER_MSVC_2012 1 + #define EA_COMPILER_MSVC12_0 1 + + #elif (_MSC_VER < 1900) // VS2013 _MSC_VER of 1800 means VS2013 + #define EA_COMPILER_MSVC_2013 1 + #define EA_COMPILER_MSVC13_0 1 + + #elif (_MSC_VER < 1910) // VS2015 _MSC_VER of 1900 means VS2015 + #define EA_COMPILER_MSVC_2015 1 + #define EA_COMPILER_MSVC14_0 1 + + #elif (_MSC_VER < 1911) // VS2017 _MSC_VER of 1910 means VS2017 + #define EA_COMPILER_MSVC_2017 1 + #define EA_COMPILER_MSVC15_0 1 + + #endif + + + // IBM + #elif defined(__xlC__) + #define EA_COMPILER_IBM 1 + #define EA_COMPILER_NAME "IBM XL C" + #define EA_COMPILER_VERSION __xlC__ + #define EA_COMPILER_STRING "IBM XL C compiler, version " INTERNAL_STRINGIZE( __xlC__ ) + + // Unknown + #else // Else the compiler is unknown + + #define EA_COMPILER_VERSION 0 + #define EA_COMPILER_NAME "Unknown" + + #endif + + #ifndef EA_COMPILER_STRING + #define EA_COMPILER_STRING EA_COMPILER_NAME " compiler, version " INTERNAL_STRINGIZE(EA_COMPILER_VERSION) + #endif + + + // Deprecated definitions + // For backwards compatibility, should be supported for at least the life of EABase v2.0.x. + #ifndef EA_COMPILER_NO_TEMPLATE_PARTIAL_SPECIALIZATION + #define EA_COMPILER_PARTIAL_TEMPLATE_SPECIALIZATION 1 + #endif + #ifndef EA_COMPILER_NO_TEMPLATE_SPECIALIZATION + #define EA_COMPILER_TEMPLATE_SPECIALIZATION 1 + #endif + #ifndef EA_COMPILER_NO_MEMBER_TEMPLATES + #define EA_COMPILER_MEMBER_TEMPLATES 1 + #endif + #ifndef EA_COMPILER_NO_MEMBER_TEMPLATE_SPECIALIZATION + #define EA_COMPILER_MEMBER_TEMPLATE_SPECIALIZATION 1 + #endif + + + + /////////////////////////////////////////////////////////////////////////////// + // EA_COMPILER_VA_COPY_REQUIRED + // + // Defines whether va_copy must be used to copy or save va_list objects between uses. + // Some compilers on some platforms implement va_list whereby its contents + // are destroyed upon usage, even if passed by value to another function. + // With these compilers you can use va_copy to save and restore a va_list. + // Known compiler/platforms that destroy va_list contents upon usage include: + // CodeWarrior on PowerPC + // GCC on x86-64 + // However, va_copy is part of the C99 standard and not part of earlier C and + // C++ standards. So not all compilers support it. VC++ doesn't support va_copy, + // but it turns out that VC++ doesn't usually need it on the platforms it supports, + // and va_copy can usually be implemented via memcpy(va_list, va_list) with VC++. + /////////////////////////////////////////////////////////////////////////////// + + #ifndef EA_COMPILER_VA_COPY_REQUIRED + #if ((defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__clang__)) && (!defined(__i386__) || defined(__x86_64__)) && !defined(__ppc__) && !defined(__PPC__) && !defined(__PPC64__) + #define EA_COMPILER_VA_COPY_REQUIRED 1 + #endif + #endif + + + // EA_COMPILER_NO_RTTI + // + // If EA_COMPILER_NO_RTTI is defined, then RTTI (run-time type information) + // is not available (possibly due to being disabled by the user). + // + #if defined(__EDG_VERSION__) && !defined(__RTTI) + #define EA_COMPILER_NO_RTTI 1 + #elif defined(__clang__) && !EA_COMPILER_HAS_FEATURE(cxx_rtti) + #define EA_COMPILER_NO_RTTI 1 + #elif defined(__IBMCPP__) && !defined(__RTTI_ALL__) + #define EA_COMPILER_NO_RTTI 1 + #elif defined(__GXX_ABI_VERSION) && !defined(__GXX_RTTI) + #define EA_COMPILER_NO_RTTI 1 + #elif defined(_MSC_VER) && !defined(_CPPRTTI) + #define EA_COMPILER_NO_RTTI 1 + #elif defined(__ARMCC_VERSION) && defined(__TARGET_CPU_MPCORE) && !defined(__RTTI) + #define EA_COMPILER_NO_RTTI 1 + #endif + + + + // EA_COMPILER_NO_EXCEPTIONS / EA_COMPILER_NO_UNWIND + // + // If EA_COMPILER_NO_EXCEPTIONS is defined, then the compiler is + // configured to not recognize C++ exception-handling statements + // such as try/catch/throw. Thus, when EA_COMPILER_NO_EXCEPTIONS is + // defined, code that attempts to use exception handling statements + // will usually cause a compilation error. If is often desirable + // for projects to disable exception handling because exception + // handling causes extra code and/or data generation which might + // not be needed, especially if it is known that exceptions won't + // be happening. When writing code that is to be portable between + // systems of which some enable exception handling while others + // don't, check for EA_COMPILER_NO_EXCEPTIONS being defined. + // + #if !defined(EA_COMPILER_NO_EXCEPTIONS) && !defined(EA_COMPILER_NO_UNWIND) + #if defined(EA_COMPILER_GNUC) && defined(_NO_EX) // GCC on some platforms defines _NO_EX when exceptions are disabled. + #define EA_COMPILER_NO_EXCEPTIONS 1 + + #elif (defined(EA_COMPILER_CLANG) || defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_INTEL) || defined(EA_COMPILER_RVCT)) && !defined(__EXCEPTIONS) // GCC and most EDG-based compilers define __EXCEPTIONS when exception handling is enabled. + #define EA_COMPILER_NO_EXCEPTIONS 1 + + #elif (defined(EA_COMPILER_MSVC)) && !defined(_CPPUNWIND) + #define EA_COMPILER_NO_UNWIND 1 + + #endif // EA_COMPILER_NO_EXCEPTIONS / EA_COMPILER_NO_UNWIND + #endif // !defined(EA_COMPILER_NO_EXCEPTIONS) && !defined(EA_COMPILER_NO_UNWIND) + + + // ------------------------------------------------------------------------ + // EA_DISABLE_ALL_VC_WARNINGS / EA_RESTORE_ALL_VC_WARNINGS + // + // Disable and re-enable all warning(s) within code. + // + // Example usage: + // EA_DISABLE_ALL_VC_WARNINGS() + // <code> + // EA_RESTORE_ALL_VC_WARNINGS() + // + //This is duplicated from EABase's eacompilertraits.h + #ifndef EA_DISABLE_ALL_VC_WARNINGS + #if defined(_MSC_VER) + #define EA_DISABLE_ALL_VC_WARNINGS() \ + __pragma(warning(push, 0)) \ + __pragma(warning(disable: 4244 4265 4267 4350 4472 4509 4548 4623 4710 4985 6320 4755 4625 4626 4702)) // Some warnings need to be explicitly called out. + #else + #define EA_DISABLE_ALL_VC_WARNINGS() + #endif + #endif + + //This is duplicated from EABase's eacompilertraits.h + #ifndef EA_RESTORE_ALL_VC_WARNINGS + #if defined(_MSC_VER) + #define EA_RESTORE_ALL_VC_WARNINGS() \ + __pragma(warning(pop)) + #else + #define EA_RESTORE_ALL_VC_WARNINGS() + #endif + #endif + + // Dinkumware + //This is duplicated from EABase's eahave.h + #if !defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && !defined(EA_NO_HAVE_DINKUMWARE_CPP_LIBRARY) + #if defined(__cplusplus) + EA_DISABLE_ALL_VC_WARNINGS() + #include <cstddef> // Need to trigger the compilation of yvals.h without directly using <yvals.h> because it might not exist. + EA_RESTORE_ALL_VC_WARNINGS() + #endif + + #if defined(__cplusplus) && defined(_CPPLIB_VER) /* If using the Dinkumware Standard library... */ + #define EA_HAVE_DINKUMWARE_CPP_LIBRARY 1 + #else + #define EA_NO_HAVE_DINKUMWARE_CPP_LIBRARY 1 + #endif + #endif + + + // EA_COMPILER_NO_ALIGNED_NEW + // + // + #if !defined(EA_COMPILER_NO_ALIGNED_NEW) + #if defined(_HAS_ALIGNED_NEW) && _HAS_ALIGNED_NEW // VS2017 15.5 Preview + // supported. + #elif defined(EA_COMPILER_CPP17_ENABLED) + // supported. + #else + #define EA_COMPILER_NO_ALIGNED_NEW 1 + #endif + #endif + + // EA_COMPILER_NO_NEW_THROW_SPEC / EA_THROW_SPEC_NEW / EA_THROW_SPEC_DELETE + // + // If defined then the compiler's version of operator new is not decorated + // with a throw specification. This is useful for us to know because we + // often want to write our own overloaded operator new implementations. + // We need such operator new overrides to be declared identically to the + // way the compiler is defining operator new itself. + // + // Example usage: + // void* operator new(std::size_t) EA_THROW_SPEC_NEW(std::bad_alloc); + // void* operator new[](std::size_t) EA_THROW_SPEC_NEW(std::bad_alloc); + // void* operator new(std::size_t, const std::nothrow_t&) EA_THROW_SPEC_NEW_NONE(); + // void* operator new[](std::size_t, const std::nothrow_t&) EA_THROW_SPEC_NEW_NONE(); + // void operator delete(void*) EA_THROW_SPEC_DELETE_NONE(); + // void operator delete[](void*) EA_THROW_SPEC_DELETE_NONE(); + // void operator delete(void*, const std::nothrow_t&) EA_THROW_SPEC_DELETE_NONE(); + // void operator delete[](void*, const std::nothrow_t&) EA_THROW_SPEC_DELETE_NONE(); + // + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) + #if defined(_MSC_VER) && (_MSC_VER >= 1912) // VS2017 15.3+ + #define EA_THROW_SPEC_NEW(x) noexcept(false) + #define EA_THROW_SPEC_NEW_NONE() noexcept + #define EA_THROW_SPEC_DELETE_NONE() noexcept + + #elif defined(_MSC_VER) && (_MSC_VER >= 1910) // VS2017+ + #define EA_THROW_SPEC_NEW(x) throw(x) + #define EA_THROW_SPEC_NEW_NONE() throw() + #define EA_THROW_SPEC_DELETE_NONE() throw() + + #else + #if defined(EA_PLATFORM_SONY) + #define EA_THROW_SPEC_NEW(X) _THROWS(X) + #elif defined(_MSC_VER) + // Disabled warning "nonstandard extension used: 'throw (...)'" as this warning is a W4 warning which is usually off by default + // and doesn't convey any important information but will still complain when building with /Wall (which most teams do) + #define EA_THROW_SPEC_NEW(X) __pragma(warning(push)) __pragma(warning(disable: 4987)) _THROWS(X) __pragma(warning(pop)) + #else + #define EA_THROW_SPEC_NEW(X) _THROW1(X) + #endif + #define EA_THROW_SPEC_NEW_NONE() _THROW0() + #define EA_THROW_SPEC_DELETE_NONE() _THROW0() + + #endif + #elif defined(EA_COMPILER_NO_EXCEPTIONS) && !defined(EA_COMPILER_RVCT) && !defined(EA_PLATFORM_LINUX) && !defined(EA_PLATFORM_APPLE) && !defined(CS_UNDEFINED_STRING) + #define EA_COMPILER_NO_NEW_THROW_SPEC 1 + + #define EA_THROW_SPEC_NEW(x) + #define EA_THROW_SPEC_NEW_NONE() + #define EA_THROW_SPEC_DELETE_NONE() + #else + #define EA_THROW_SPEC_NEW(x) throw(x) + #define EA_THROW_SPEC_NEW_NONE() throw() + #define EA_THROW_SPEC_DELETE_NONE() throw() + #endif + + + // EA_COMPILER_NO_STANDARD_CPP_LIBRARY + // + // If defined, then the compiler doesn't provide a Standard C++ library. + // + #if defined(EA_PLATFORM_ANDROID) + // Disabled because EA's eaconfig/android_config/android_sdk packages currently + // don't support linking STL libraries. Perhaps we can figure out what linker arguments + // are needed for an app so we can manually specify them and then re-enable this code. + //#include <android/api-level.h> + // + //#if (__ANDROID_API__ < 9) // Earlier versions of Android provide no std C++ STL implementation. + #define EA_COMPILER_NO_STANDARD_CPP_LIBRARY 1 + //#endif + #endif + + + // EA_COMPILER_NO_STATIC_VARIABLE_INIT + // + // If defined, it means that global or static C++ variables will be + // constructed. Not all compiler/platorm combinations support this. + // User code that needs to be portable must avoid having C++ variables + // that construct before main. + // + //#if defined(EA_PLATFORM_MOBILE) + // #define EA_COMPILER_NO_STATIC_VARIABLE_INIT 1 + //#endif + + + // EA_COMPILER_NO_STATIC_FUNCTION_INIT + // + // If defined, it means that functions marked as startup functions + // (e.g. __attribute__((constructor)) in GCC) are supported. It may + // be that some compiler/platform combinations don't support this. + // + //#if defined(XXX) // So far, all compiler/platforms we use support this. + // #define EA_COMPILER_NO_STATIC_VARIABLE_INIT 1 + //#endif + + // EA_COMPILER_NO_VARIADIC_MACROS + // + // If defined, the compiler doesn't support C99/C++11 variadic macros. + // With a variadic macro, you can do this: + // #define MY_PRINTF(format, ...) printf(format, __VA_ARGS__) + // + #if !defined(EA_COMPILER_NO_VARIADIC_MACROS) + #if defined(_MSC_VER) && (_MSC_VER < 1500) // If earlier than VS2008.. + #define EA_COMPILER_NO_VARIADIC_MACROS 1 + #elif defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__)) < 401 // If earlier than GCC 4.1.. + #define EA_COMPILER_NO_VARIADIC_MACROS 1 + #elif defined(EA_COMPILER_EDG) // Includes other compilers + // variadic macros are supported + #endif + #endif + + + // EA_COMPILER_NO_RVALUE_REFERENCES + // + // If defined, the compiler doesn't fully support C++11 rvalue reference semantics. + // This applies to the compiler only and not the Standard Library in use with the compiler, + // which is required by the Standard to have some support itself. + // + #if !defined(EA_COMPILER_NO_RVALUE_REFERENCES) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (_MSC_VER >= 1600) // VS2010+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403) // EDG 4.3+. + // supported. Earlier EDG supported a subset of rvalue references. Implicit move constructors and assignment operators aren't supported until EDG 4.5. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && EA_COMPILER_HAS_FEATURE(cxx_rvalue_references) + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4005) // GCC 4.5+ + // supported. + #else + #define EA_COMPILER_NO_RVALUE_REFERENCES 1 + #endif + #endif + + + // EA_COMPILER_NO_EXTERN_TEMPLATE + // + // If defined, the compiler doesn't support C++11 extern template. + // With extern templates, you can do this: + // extern template void DoSomething(KnownType u); + // + #if !defined(EA_COMPILER_NO_EXTERN_TEMPLATE) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (_MSC_VER >= 1700) // VS2012+... + // Extern template is supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401) // EDG 4.1+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && defined(__apple_build_version__) && (EA_COMPILER_VERSION >= 401) + // Extern template is supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && !defined(__apple_build_version__) // Clang other than Apple's Clang + // Extern template is supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4006) // GCC 4.6+ + // Extern template is supported. + #else + #define EA_COMPILER_NO_EXTERN_TEMPLATE 1 + #endif + #endif + + + // EA_COMPILER_NO_RANGE_BASED_FOR_LOOP + // + // If defined, the compiler doesn't support C++11 range-based for loops. + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2930.html + // You must #include <iterator> for range-based for loops to work. + // Example usage: + // #include <iterator> + // #include <vector> + // std::vector<float> floatVector; + // for(float& f : floatVector) + // f += 1.0; + // + #if !defined(EA_COMPILER_NO_RANGE_BASED_FOR_LOOP) + #if defined(EA_COMPILER_CPP11_ENABLED) && (defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1700)) // VS2012+... + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405) // EDG 4.5+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && (defined(__clang__) && (EA_COMPILER_VERSION >= 300)) // Clang 3.x+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && (defined(__GNUC__) && (EA_COMPILER_VERSION >= 4006)) // GCC 4.6+ + // supported. + #else + #define EA_COMPILER_NO_RANGE_BASED_FOR_LOOP 1 + #endif + #endif + + + // EA_COMPILER_NO_CONSTEXPR + // + // Refers to C++11 = constexpr (const expression) declarations. + // + #if !defined(EA_COMPILER_NO_CONSTEXPR) + #if defined(EA_COMPILER_CPP11_ENABLED) && (defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1900)) // VS2015+... Not present in VC++ up to and including VS2013. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 406) // EDG 4.6+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && EA_COMPILER_HAS_FEATURE(cxx_constexpr) + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4006) // GCC 4.6+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1900) // VS 2015+ + // supported. + #else + #define EA_COMPILER_NO_CONSTEXPR 1 + #endif + #endif + + + // EA_COMPILER_NO_CONSTEXPR_IF + // + // Refers to C++17 = constexpr if(const expression) conditionals. + // + #if !defined(EA_COMPILER_NO_CONSTEXPR_IF) + #if defined(EA_COMPILER_CPP17_ENABLED) && (defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1911)) // VS2017 15.3+ + // supported. + #elif defined(EA_COMPILER_CPP17_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 309) // Clang 3.9+ + // supported. + #elif defined(EA_COMPILER_CPP17_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 7000) // GCC 7+ + // supported. + #else + #define EA_COMPILER_NO_CONSTEXPR_IF 1 + #endif + #endif + + + // EA_COMPILER_NO_OVERRIDE + // + // Refers to the C++11 override specifier. + // + #ifndef EA_COMPILER_NO_OVERRIDE + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION > 1600) // VC++ > VS2010, even without C++11 support. VS2010 does support override, however will generate warnings due to the keyword being 'non-standard' + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 209) // Clang 2.9+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4007) // GCC 4.7+ + // supported. + #else + #define EA_COMPILER_NO_OVERRIDE 1 + #endif + #endif + + + // EA_COMPILER_NO_INHERITANCE_FINAL + // + // Refers to the C++11 final specifier. + // + #ifndef EA_COMPILER_NO_INHERITANCE_FINAL + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1500) // VS2008+, even without C++11 support. + // supported, though you need to use EA_INHERITANCE_FINAL for it to work with VS versions prior to 2012. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 209) // Clang 2.9+ + // supported + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4007) // GCC 4.7+ + // supported + #else + #define EA_COMPILER_NO_INHERITANCE_FINAL 1 + #endif + #endif + + + // EA_COMPILER_NO_AUTO + // + // Refers to C++11 auto. + // + #if !defined(EA_COMPILER_NO_AUTO) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1600) // VS2010+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401) // EDG 4.1+. + // supported with the exception of the usage of braced initializer lists as of EDG 4.3. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 209) // Clang 2.9+, including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4004) // GCC 4.4+ + // supported. + #else + #define EA_COMPILER_NO_AUTO 1 + #endif + #endif + + + // EA_COMPILER_NO_NULLPTR + // + // Refers to C++11 nullptr (which is a built in type). std::nullptr_t is defined in C++11 <cstddef>. + // Note that <EABase/nullptr.h> implements a portable nullptr implementation. + // + #if !defined(EA_COMPILER_NO_NULLPTR) + #if (defined(_MSC_VER) && (_MSC_VER >= 1600)) && defined(EA_COMPILER_CPP11_ENABLED) + // supported + #elif defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4006) && defined(EA_COMPILER_CPP11_ENABLED) + // supported + #elif defined(__clang__) && defined(EA_COMPILER_CPP11_ENABLED) + // supported + #elif defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403) && defined(EA_COMPILER_CPP11_ENABLED) + // supported + #else + #define EA_COMPILER_NO_NULLPTR 1 + #endif + #endif + + + // EA_COMPILER_NO_DECLTYPE + // + // Refers to C++11 decltype. + // + #if !defined(EA_COMPILER_NO_DECLTYPE) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1600) // VS2010+ + // supported, though VS2010 doesn't support the spec completely as specified in the final standard. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401) // EDG 4.1+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 209) // Clang 2.9+, including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4003) // GCC 4.3+ + // supported. + #else + #define EA_COMPILER_NO_DECLTYPE 1 + #endif + #endif + + + + // EA_COMPILER_NO_DEFAULTED_FUNCTIONS + // EA_COMPILER_NO_DELETED_FUNCTIONS + // + // Refers to C++11 = default and = delete function declarations. + // + #if !defined(EA_COMPILER_NO_DEFAULTED_FUNCTIONS) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1800) // VS2013+ + // supported, but as of VS2013 it isn't supported for defaulted move constructors and move assignment operators. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401) // EDG 4.1+. + // supported, but as of EDG 4.3 it isn't supported for defaulted move constructors and move assignment operators until EDG 4.5. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 300) // Clang 3.0+, including Apple's Clang + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4004) // GCC 4.4+ + // supported. + #else + // VC++ doesn't support it as of VS2012. + #define EA_COMPILER_NO_DEFAULTED_FUNCTIONS 1 + #endif + #endif + + #if !defined(EA_COMPILER_NO_DELETED_FUNCTIONS) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1800) // VS2013+ + // supported, but as of VS2013 it isn't supported for defaulted move constructors and move assignment operators. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401) // EDG 4.1+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 209) // Clang 2.9+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4004) // GCC 4.4+ + // supported. + #else + // VC++ doesn't support it as of VS2012. + #define EA_COMPILER_NO_DELETED_FUNCTIONS 1 + #endif + #endif + + + // EA_COMPILER_NO_LAMBDA_EXPRESSIONS + // + // Refers to C++11 lambda expressions. + // + #if !defined(EA_COMPILER_NO_LAMBDA_EXPRESSIONS) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1600) // VS2010+ + // supported, though VS2010 doesn't support the spec completely as specified in the final standard. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401) // EDG 4.1+. + // supported. However, converting lambdas to function pointers is not supported until EDG 4.5. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 301) && !defined(__apple_build_version__) // Clang 3.1+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4004) // GCC 4.4+ + // supported. + #else + #define EA_COMPILER_NO_LAMBDA_EXPRESSIONS 1 + #endif + #endif + + + // EA_COMPILER_NO_TRAILING_RETURN_TYPES + // + // Refers to C++11 trailing-return-type. Also sometimes referred to as "incomplete return type". + // + #if !defined(EA_COMPILER_NO_TRAILING_RETURN_TYPES) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1600) // VS2010+ + // supported, though VS2010 doesn't support the spec completely as specified in the final standard. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 402) // EDG 4.2+. + // supported. However, use of "this" in trailing return types is not supported untiil EDG 4.4 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 301) && !defined(__apple_build_version__) // Clang 3.1+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4004) // GCC 4.4+ + // supported. + #else + #define EA_COMPILER_NO_TRAILING_RETURN_TYPES 1 + #endif + #endif + + + // EA_COMPILER_NO_STRONGLY_TYPED_ENUMS + // + // Refers to C++11 strongly typed enums, which includes enum classes and sized enums. Doesn't include forward-declared enums. + // + #if !defined(EA_COMPILER_NO_STRONGLY_TYPED_ENUMS) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1700) // VS2012+ + // supported. A subset of this is actually supported by VS2010. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 400) // EDG 4.0+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 209) // Clang 2.9+, including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4004) // GCC 4.4+ + // supported. + #else + #define EA_COMPILER_NO_STRONGLY_TYPED_ENUMS 1 + #endif + #endif + + + // EA_COMPILER_NO_FORWARD_DECLARED_ENUMS + // + // Refers to C++11 forward declared enums. + // + #if !defined(EA_COMPILER_NO_FORWARD_DECLARED_ENUMS) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1700) // VS2012+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405) // EDG 4.5+. + // supported. EDG 4.3 supports basic forward-declared enums, but not forward-declared strongly typed enums. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 301) && !defined(__apple_build_version__) // Clang 3.1+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4006) // GCC 4.6+ + // supported. + #else + #define EA_COMPILER_NO_FORWARD_DECLARED_ENUMS 1 + #endif + #endif + + + // EA_COMPILER_NO_VARIADIC_TEMPLATES + // + // Refers to C++11 variadic templates. + // + #if !defined(EA_COMPILER_NO_VARIADIC_TEMPLATES) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1800) // VS2013+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (_MSC_FULL_VER == 170051025) // VS2012 November Preview for Windows only. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403) // EDG 4.3+. + // supported, though 4.1 has partial support for variadic templates. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 209) // Clang 2.9+, including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4004) // GCC 4.4+ + // supported, though GCC 4.3 has partial support for variadic templates. + #else + #define EA_COMPILER_NO_VARIADIC_TEMPLATES 1 + #endif + #endif + + + // EA_COMPILER_NO_TEMPLATE_ALIASES + // + // Refers to C++11 alias templates. + // Example alias template usage: + // template <typename T> + // using Dictionary = eastl::map<eastl::string, T>; + // + // Dictionary<int> StringIntDictionary; + // + #if !defined(EA_COMPILER_NO_TEMPLATE_ALIASES) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1800) // VS2013+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 402) // EDG 4.2+. + // supported, though 4.1 has partial support for variadic templates. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 300) && !defined(__apple_build_version__) // Clang 3.0+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4007) // GCC 4.7+ + // supported, though GCC 4.3 has partial support for variadic templates. + #else + #define EA_COMPILER_NO_TEMPLATE_ALIASES 1 + #endif + #endif + + + // EA_COMPILER_NO_VARIABLE_TEMPLATES + // + // Refers to C++14 variable templates. + // Example variable template usage: + // template<class T> + // constexpr T pi = T(3.1415926535897932385); + // + #if !defined(EA_COMPILER_NO_VARIABLE_TEMPLATES) + #if defined(_MSC_VER) && (_MSC_FULL_VER >= 190023918) // VS2015 Update 2 and above. + // supported. + #elif defined(EA_COMPILER_CPP14_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 304) && !defined(__apple_build_version__) // Clang 3.4+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP14_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 5000) // GCC 5+ + // supported. + #elif !defined(EA_COMPILER_CPP14_ENABLED) + #define EA_COMPILER_NO_VARIABLE_TEMPLATES 1 + #endif + #endif + + + // EA_COMPILER_NO_INLINE_VARIABLES + // + // Refers to C++17 inline variables that allows the definition of variables in header files + // + // Example usage: + // struct Foo + // { + // static inline constexpr int kConstant = 42; // no out of class definition + // }; + // + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4424.pdf + // http://en.cppreference.com/w/cpp/language/inline + // + #if !defined(EA_COMPILER_NO_INLINE_VARIABLES) + #define EA_COMPILER_NO_INLINE_VARIABLES 1 + #endif + + + // EA_COMPILER_NO_INITIALIZER_LISTS + // + // Refers to C++11 initializer lists. + // This refers to the compiler support for this and not the Standard Library support (std::initializer_list). + // + #if !defined(EA_COMPILER_NO_INITIALIZER_LISTS) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1800) // VS2013+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (_MSC_FULL_VER == 170051025) // VS2012 November Preview for Windows only. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405) // EDG 4.5+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 301) && !defined(__apple_build_version__) // Clang 3.1+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4004) // GCC 4.4+ + // supported, though GCC 4.3 has partial support for it. + #else + #define EA_COMPILER_NO_INITIALIZER_LISTS 1 + #endif + #endif + + + // EA_COMPILER_NO_NORETURN + // + // Refers to C++11 declaration attribute: noreturn. + // http://en.cppreference.com/w/cpp/language/attributes + // http://blog.aaronballman.com/2011/09/understanding-attributes/ + // + #if !defined(EA_COMPILER_NO_NORETURN) + #if defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1300) // VS2003+ + // supported via __declspec(noreturn). You need to use that or EA_NORETURN. VC++ up to VS2013 doesn't support any C++11 attribute types. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 402) // EDG 4.2+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 300) && !defined(__apple_build_version__) // Clang 3.0+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4008) // GCC 4.8+ + // supported. + #else + #define EA_COMPILER_NO_NORETURN 1 + #endif + #endif + + + // EA_COMPILER_NO_CARRIES_DEPENDENCY + // + // Refers to C++11 declaration attribute: carries_dependency. + // http://en.cppreference.com/w/cpp/language/attributes + // http://blog.aaronballman.com/2011/09/understanding-attributes/ + // + #if !defined(EA_COMPILER_NO_CARRIES_DEPENDENCY) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) // Apple clang 4.1+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 402) // EDG 4.2+. + // supported; stricter than other compilers in its usage. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 300) && !defined(__apple_build_version__) // Clang 3.0+, not including Apple's Clang. + // supported. + // Currently GNUC doesn't appear to support this attribute. + //#elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4008) // GCC 4.8+ + // // supported. + #else + #define EA_COMPILER_NO_CARRIES_DEPENDENCY 1 + #endif + #endif + + + // EA_COMPILER_NO_FALLTHROUGH + // + // Refers to C++17 declaration attribute: fallthrough. + // http://en.cppreference.com/w/cpp/language/attributes + // + #if !defined(EA_COMPILER_NO_FALLTHROUGH) + #if defined(EA_COMPILER_CPP17_ENABLED) + // supported. + #else + #define EA_COMPILER_NO_FALLTHROUGH 1 + #endif + #endif + + + // EA_COMPILER_NO_NODISCARD + // + // Refers to C++17 declaration attribute: nodiscard. + // http://en.cppreference.com/w/cpp/language/attributes + // + #if !defined(EA_COMPILER_NO_NODISCARD) + #if defined(EA_COMPILER_CPP17_ENABLED) + // supported. + #else + #define EA_COMPILER_NO_NODISCARD 1 + #endif + #endif + + + // EA_COMPILER_NO_MAYBE_UNUSED + // + // Refers to C++17 declaration attribute: maybe_unused. + // http://en.cppreference.com/w/cpp/language/attributes + // + #if !defined(EA_COMPILER_NO_MAYBE_UNUSED) + #if defined(EA_COMPILER_CPP17_ENABLED) + // supported. + #elif defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1912) // VS2017 15.3+ + // supported. + #else + #define EA_COMPILER_NO_MAYBE_UNUSED 1 + #endif + #endif + + + // EA_COMPILER_NO_STRUCTURED_BINDING + // + // Indicates if target compiler supports the C++17 "structured binding" language feature. + // https://en.cppreference.com/w/cpp/language/structured_binding + // + // + #if !defined(EA_COMPILER_NO_STRUCTURED_BINDING) + #if defined(EA_COMPILER_CPP17_ENABLED) + // supported. + #elif defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1912) // VS2017 15.3+ + // supported. + #else + #define EA_COMPILER_NO_STRUCTURED_BINDING 1 + #endif + #endif + + + // EA_COMPILER_NO_DESIGNATED_INITIALIZERS + // + // Indicates the target compiler supports the C++20 "designated initializer" language feature. + // https://en.cppreference.com/w/cpp/language/aggregate_initialization + // + // Example: + // struct A { int x; int y; }; + // A a = { .y = 42, .x = 1 }; + // + #if !defined(EA_COMPILER_NO_DESIGNATED_INITIALIZERS) + #if defined(EA_COMPILER_CPP20_ENABLED) + // supported. + #else + #define EA_COMPILER_NO_DESIGNATED_INITIALIZERS 1 + #endif + #endif + + + // EA_COMPILER_NO_NONSTATIC_MEMBER_INITIALIZERS + // + // Refers to C++11 declaration attribute: carries_dependency. + // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2008/n2756.htm + // + #if !defined(EA_COMPILER_NO_NONSTATIC_MEMBER_INITIALIZERS) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1800) // VS2013+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) // Apple clang 4.1+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 300) && !defined(__apple_build_version__) // Clang 3.0+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4007) // GCC 4.7+ + // supported. + #else + #define EA_COMPILER_NO_NONSTATIC_MEMBER_INITIALIZERS 1 + #endif + #endif + + + // EA_COMPILER_NO_RIGHT_ANGLE_BRACKETS + // + // Defines if the compiler supports >> (as opposed to > >) in template + // declarations such as typedef eastl::list<eastl::list<int>> ListList; + // + #if !defined(EA_COMPILER_NO_RIGHT_ANGLE_BRACKETS) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1600) // VS2010+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401) // EDG 4.1+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 209) // Clang 2.9+, including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4003) // GCC 4.3+ + // supported. + #else + #define EA_COMPILER_NO_RIGHT_ANGLE_BRACKETS 1 + #endif + #endif + + + // EA_COMPILER_NO_ALIGNOF + // + // Refers specifically to C++11 alignof and not old compiler extensions such as __alignof__(). + // However, EABase provides a portable EA_ALIGN_OF which works for all compilers. + // + #if !defined(EA_COMPILER_NO_ALIGNOF) + // Not supported by VC++ as of VS2013, though EA_ALIGN_OF is supported on all coompilers as an alternative. + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 209) // Clang 2.9+, including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4005) // GCC 4.5+ + // supported. + #else + #define EA_COMPILER_NO_ALIGNOF 1 + #endif + #endif + + + // EA_COMPILER_NO_ALIGNAS + // + // Refers to C++11 alignas. + // + #if !defined(EA_COMPILER_NO_ALIGNAS) + // Not supported by VC++ as of VS2013. + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) // Apple clang 4.1+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 300) && !defined(__apple_build_version__) // Clang 3.0+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4008) // GCC 4.8+ + // supported. + #else + #define EA_COMPILER_NO_ALIGNAS 1 + #endif + #endif + + + // EA_COMPILER_NO_DELEGATING_CONSTRUCTORS + // + // Refers to C++11 constructor delegation. + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1986.pdf + // https://www.ibm.com/developerworks/mydeveloperworks/blogs/5894415f-be62-4bc0-81c5-3956e82276f3/entry/c_0x_delegating_constructors + // + #if !defined(EA_COMPILER_NO_DELEGATING_CONSTRUCTORS) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1800) // VS2013+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 407) // EDG 4.7+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) // Apple clang 4.1+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 300) && !defined(__apple_build_version__) // Clang 3.0+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4007) // GCC 4.7+ + // supported. + #else + #define EA_COMPILER_NO_DELEGATING_CONSTRUCTORS 1 + #endif + #endif + + + // EA_COMPILER_NO_INHERITING_CONSTRUCTORS + // + // Refers to C++11 constructor inheritance via 'using'. + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2540.htm + // + #if !defined(EA_COMPILER_NO_INHERITING_CONSTRUCTORS) + // Not supported by VC++ as of VS2013. + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && EA_COMPILER_HAS_FEATURE(cxx_inheriting_constructors) // Clang + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4008) // GCC 4.8+ + // supported. + #else + #define EA_COMPILER_NO_INHERITING_CONSTRUCTORS 1 + #endif + #endif + + + // EA_COMPILER_NO_USER_DEFINED_LITERALS + // + // http://en.cppreference.com/w/cpp/language/user_literal + // http://stackoverflow.com/questions/237804/what-new-capabilities-do-user-defined-literals-add-to-c + // + #if !defined(EA_COMPILER_NO_USER_DEFINED_LITERALS) + // Not supported by VC++ as of VS2013. + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) // Apple clang 4.1+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 301) && !defined(__apple_build_version__) // Clang 3.1+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4007) // GCC 4.7+ + // supported. + #else + #define EA_COMPILER_NO_USER_DEFINED_LITERALS 1 + #endif + #endif + + + // EA_COMPILER_NO_STANDARD_LAYOUT_TYPES + // a.k.a. POD relaxation + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm + // + #if !defined(EA_COMPILER_NO_STANDARD_LAYOUT_TYPES) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1700) // VS2012+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) // Apple clang 4.1+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 300) && !defined(__apple_build_version__) // Clang 3.0+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4005) // GCC 4.5+ + // supported. + #else + #define EA_COMPILER_NO_STANDARD_LAYOUT_TYPES 1 + #endif + #endif + + + // EA_COMPILER_NO_EXTENDED_SIZEOF + // + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2253.html + // Allows you to do this: sizeof(SomeClass::mSomeMember) + // + #if !defined(EA_COMPILER_NO_EXTENDED_SIZEOF) + // Not supported by VC++ as of VS2013. + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) // Apple clang 4.1+ + // supported. + // Versions of EDG prior to 4.5 only support extended sizeof in non-member functions. Full support was added in 4.5 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405) // EDG 4.5+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 301) && !defined(__apple_build_version__) // Clang 3.1+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4005) // GCC 4.5+ + // supported. + #else + #define EA_COMPILER_NO_EXTENDED_SIZEOF 1 + #endif + #endif + + + // EA_COMPILER_NO_INLINE_NAMESPACES + // + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2535.htm + // http://blog.aaronballman.com/2011/07/inline-namespaces/ + // + #if !defined(EA_COMPILER_NO_INLINE_NAMESPACES) + // Not supported by VC++ as of VS2013. + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405) // EDG 4.5+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 209) // Clang 2.9+, including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4004) // GCC 4.4+ + // supported. + #else + #define EA_COMPILER_NO_INLINE_NAMESPACES 1 + #endif + #endif + + + // EA_COMPILER_NO_UNRESTRICTED_UNIONS + // + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2544.pdf + // + #if !defined(EA_COMPILER_NO_UNRESTRICTED_UNIONS) + // Not supported by VC++ as of VS2013. + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 406) // EDG 4.6+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) // Apple clang 4.1+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 301) && !defined(__apple_build_version__) // Clang 3.1+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4006) // GCC 4.6+ + // supported. + #else + #define EA_COMPILER_NO_UNRESTRICTED_UNIONS 1 + #endif + #endif + + + // EA_COMPILER_NO_EXPLICIT_CONVERSION_OPERATORS + // + // http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_conversion_operators + // + #if !defined(EA_COMPILER_NO_EXPLICIT_CONVERSION_OPERATORS) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1800) // VS2013+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (_MSC_FULL_VER == 170051025) // VS2012 November Preview for Windows only. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 404) // EDG 4.4+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) // Apple clang 4.1+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 300) && !defined(__apple_build_version__) // Clang 3.0+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4005) // GCC 4.5+ + // supported. + #else + #define EA_COMPILER_NO_EXPLICIT_CONVERSION_OPERATORS 1 + #endif + #endif + + + // EA_COMPILER_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS + // + // The compiler does not support default template arguments for function templates. + // http://stackoverflow.com/questions/2447458/default-template-arguments-for-function-templates + // + #if !defined(EA_COMPILER_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1800) // VS2013+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403) // EDG 4.4+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 209) // Clang 2.9+, including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4003) // GCC 4.3+ + // supported. + #else + #define EA_COMPILER_NO_FUNCTION_TEMPLATE_DEFAULT_ARGS 1 + #endif + #endif + + + // EA_COMPILER_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS + // + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2657.htm + // http://stackoverflow.com/questions/5751977/local-type-as-template-arguments-in-c + // + #if !defined(EA_COMPILER_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1600) // VS2010+ + // supported. + #if (EA_COMPILER_VERSION < 1700) // VS2010 generates a warning, but the C++ language now allows it. + #pragma warning(disable: 4836) // nonstandard extension used: local types or unnamed types cannot be used as template arguments. + #endif + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 402) // EDG 4.2+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 209) // Clang 2.9+, including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4005) // GCC 4.5+ + // supported. + #else + #define EA_COMPILER_NO_LOCAL_CLASS_TEMPLATE_PARAMETERS 1 + #endif + #endif + + + // EA_COMPILER_NO_NOEXCEPT + // + // C++11 noexcept + // http://en.cppreference.com/w/cpp/language/attributes + // http://en.cppreference.com/w/cpp/language/noexcept + // + #if !defined(EA_COMPILER_NO_NOEXCEPT) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1900) // VS2014+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) // Apple clang 4.1+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 405) // EDG 4.5+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 300) && !defined(__apple_build_version__) // Clang 3.0+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4006) // GCC 4.6+ + // supported. + #else + #define EA_COMPILER_NO_NOEXCEPT 1 + #endif + #endif + + + // EA_COMPILER_NO_RAW_LITERALS + // + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2442.htm + // http://en.wikipedia.org/wiki/C%2B%2B11#New_string_literals + // + #if !defined(EA_COMPILER_NO_RAW_LITERALS) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1800) // VS2013+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 407) // EDG 4.7+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) // Apple clang 4.1+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 300) && !defined(__apple_build_version__) // Clang 3.0+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4005) // GCC 4.5+ + // supported. + #else + #define EA_COMPILER_NO_RAW_LITERALS 1 + #endif + #endif + + + // EA_COMPILER_NO_UNICODE_STRING_LITERALS + // + // http://en.wikipedia.org/wiki/C%2B%2B11#New_string_literals + // + #if !defined(EA_COMPILER_NO_UNICODE_STRING_LITERALS) + // Not supported by VC++ as of VS2013. + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 407) // EDG 4.7+. + // supported. It's not clear if it's v4.4 or v4.7 that adds this support. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) // Apple clang 4.1+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 300) && !defined(__apple_build_version__) // Clang 3.0+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4004) // GCC 4.4+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 407) // EDG 4.7+. + // supported. It's not clear if it's v4.4 or v4.7 that adds this support. + #else + #define EA_COMPILER_NO_UNICODE_STRING_LITERALS 1 + #endif + #endif + + + // EA_COMPILER_NO_NEW_CHARACTER_TYPES + // + // Refers to char16_t and char32_t as true native types (and not something simply typedef'd from uint16_t and uint32_t). + // http://en.cppreference.com/w/cpp/language/types + // + #if !defined(EA_COMPILER_NO_NEW_CHARACTER_TYPES) + #if defined(EA_COMPILER_NO_UNICODE_STRING_LITERALS) // Some compilers have had support for char16_t prior to support for u"", but it's not useful to have the former without the latter. + #define EA_COMPILER_NO_NEW_CHARACTER_TYPES 1 + #endif + #endif + + + // EA_COMPILER_NO_UNICODE_CHAR_NAME_LITERALS + // + // C++ 11 relaxed \u\U sequences in strings. + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2170.html + // + #if !defined(EA_COMPILER_NO_UNICODE_CHAR_NAME_LITERALS) + // VC++ up till at least VS2013 supports \u and \U but supports them wrong with respect to the C++11 Standard. + + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) // Apple clang 4.1+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 301) && !defined(__apple_build_version__) // Clang 3.1+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4005) // GCC 4.5+ + // supported. + #else + #define EA_COMPILER_NO_UNICODE_CHAR_NAME_LITERALS 1 + #endif + #endif + + + // EA_COMPILER_NO_UNIFIED_INITIALIZATION_SYNTAX + // + // http://en.wikipedia.org/wiki/C%2B%2B11#Uniform_initialization + // + #if !defined(EA_COMPILER_NO_UNIFIED_INITIALIZATION_SYNTAX) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1800) // VS2013+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 401) && defined(__apple_build_version__) // Apple clang 4.1+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 301) && !defined(__apple_build_version__) // Clang 3.1+, not including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4004) // GCC 4.4+ + // supported. + #else + #define EA_COMPILER_NO_UNIFIED_INITIALIZATION_SYNTAX 1 + #endif + #endif + + + // EA_COMPILER_NO_EXTENDED_FRIEND_DECLARATIONS + // + // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1791.pdf + // + #if !defined(EA_COMPILER_NO_EXTENDED_FRIEND_DECLARATIONS) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1600) // VS2010+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 401) // EDG 4.1+. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && (EA_COMPILER_VERSION >= 209) // Clang 2.9+, including Apple's Clang. + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4007) // GCC 4.7+ + // supported. + #else + #define EA_COMPILER_NO_EXTENDED_FRIEND_DECLARATIONS 1 + #endif + #endif + + + // EA_COMPILER_NO_THREAD_LOCAL + // + // Refers specifically to C++ thread_local, which is like compiler __thread implementations except + // that it also supports non-trivial classes (e.g. with ctors). EA_COMPILER_NO_THREAD_LOCAL refers + // specifically to full C++11 thread_local support. The EAThread package provides a wrapper for + // __thread via EA_THREAD_LOCAL (which unfortunately sounds like C++ thread_local). + // + // https://en.cppreference.com/w/cpp/keyword/thread_local + // + #if !defined(EA_COMPILER_NO_THREAD_LOCAL) + #if defined(EA_COMPILER_CPP11_ENABLED) && defined(__clang__) && EA_COMPILER_HAS_FEATURE(cxx_thread_local) + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(_MSC_VER) && (EA_COMPILER_VERSION >= 1900) // VS2015+ + // supported. + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(__GNUC__) && (EA_COMPILER_VERSION >= 4008) // GCC 4.8+ + // supported. + #else + #define EA_COMPILER_NO_THREAD_LOCAL 1 + #endif + #endif + + +#endif // INCLUDED_eacompiler_H + + + + + diff --git a/include/Common/EABase/config/eacompilertraits.h b/include/Common/EABase/config/eacompilertraits.h new file mode 100644 index 0000000..1d8bcb4 --- /dev/null +++ b/include/Common/EABase/config/eacompilertraits.h @@ -0,0 +1,2561 @@ +/*----------------------------------------------------------------------------- + * config/eacompilertraits.h + * + * Copyright (c) Electronic Arts Inc. All rights reserved. + *----------------------------------------------------------------------------- + * Currently supported defines include: + * EA_PREPROCESSOR_JOIN + * + * EA_COMPILER_IS_ANSIC + * EA_COMPILER_IS_C99 + * EA_COMPILER_IS_C11 + * EA_COMPILER_HAS_C99_TYPES + * EA_COMPILER_IS_CPLUSPLUS + * EA_COMPILER_MANAGED_CPP + * EA_COMPILER_INTMAX_SIZE + * EA_OFFSETOF + * EA_SIZEOF_MEMBER + * + * EA_ALIGN_OF() + * EA_ALIGN_MAX_STATIC / EA_ALIGN_MAX_AUTOMATIC + * EA_ALIGN() / EA_PREFIX_ALIGN() / EA_POSTFIX_ALIGN() + * EA_ALIGNED() + * EA_PACKED() + * + * EA_LIKELY() + * EA_UNLIKELY() + * EA_INIT_PRIORITY() + * EA_MAY_ALIAS() + * EA_ASSUME() + * EA_ANALYSIS_ASSUME() + * EA_PURE + * EA_WEAK + * EA_UNUSED() + * EA_EMPTY() + * + * EA_WCHAR_T_NON_NATIVE + * EA_WCHAR_SIZE = <n bytes> + * + * EA_RESTRICT + * EA_DEPRECATED / EA_PREFIX_DEPRECATED / EA_POSTFIX_DEPRECATED + * EA_FORCE_INLINE / EA_PREFIX_FORCE_INLINE / EA_POSTFIX_FORCE_INLINE + * EA_NO_INLINE / EA_PREFIX_NO_INLINE / EA_POSTFIX_NO_INLINE + * EA_NO_VTABLE / EA_CLASS_NO_VTABLE / EA_STRUCT_NO_VTABLE + * EA_PASCAL + * EA_PASCAL_FUNC() + * EA_SSE = [0 | 1] + * EA_IMPORT + * EA_EXPORT + * EA_PRAGMA_ONCE_SUPPORTED + * EA_ONCE + * EA_OVERRIDE + * EA_INHERITANCE_FINAL + * EA_SEALED + * EA_ABSTRACT + * EA_CONSTEXPR / EA_CONSTEXPR_OR_CONST + * EA_CONSTEXPR_IF + * EA_EXTERN_TEMPLATE + * EA_NOEXCEPT + * EA_NORETURN + * EA_CARRIES_DEPENDENCY + * EA_NON_COPYABLE / struct EANonCopyable + * EA_OPTIMIZE_OFF / EA_OPTIMIZE_ON + * EA_SIGNED_RIGHT_SHIFT_IS_UNSIGNED + * + * EA_DISABLE_VC_WARNING / EA_RESTORE_VC_WARNING / EA_DISABLE_ALL_VC_WARNINGS / EA_RESTORE_ALL_VC_WARNINGS + * EA_DISABLE_GCC_WARNING / EA_RESTORE_GCC_WARNING + * EA_DISABLE_CLANG_WARNING / EA_RESTORE_CLANG_WARNING + * EA_DISABLE_SN_WARNING / EA_RESTORE_SN_WARNING / EA_DISABLE_ALL_SN_WARNINGS / EA_RESTORE_ALL_SN_WARNINGS + * EA_DISABLE_GHS_WARNING / EA_RESTORE_GHS_WARNING + * EA_DISABLE_EDG_WARNING / EA_RESTORE_EDG_WARNING + * EA_DISABLE_CW_WARNING / EA_RESTORE_CW_WARNING + * + * EA_DISABLE_DEFAULT_CTOR + * EA_DISABLE_COPY_CTOR + * EA_DISABLE_MOVE_CTOR + * EA_DISABLE_ASSIGNMENT_OPERATOR + * EA_DISABLE_MOVE_OPERATOR + * + * Todo: + * Find a way to reliably detect wchar_t size at preprocessor time and + * implement it below for EA_WCHAR_SIZE. + * + * Todo: + * Find out how to support EA_PASCAL and EA_PASCAL_FUNC for systems in + * which it hasn't yet been found out for. + *---------------------------------------------------------------------------*/ + + +#ifndef INCLUDED_eacompilertraits_H +#define INCLUDED_eacompilertraits_H + + #include <EABase/config/eaplatform.h> + #include <EABase/config/eacompiler.h> + + + // Metrowerks uses #defines in its core C header files to define + // the kind of information we need below (e.g. C99 compatibility) + + + + // Determine if this compiler is ANSI C compliant and if it is C99 compliant. + #if defined(__STDC__) + #define EA_COMPILER_IS_ANSIC 1 // The compiler claims to be ANSI C + + // Is the compiler a C99 compiler or equivalent? + // From ISO/IEC 9899:1999: + // 6.10.8 Predefined macro names + // __STDC_VERSION__ The integer constant 199901L. (150) + // + // 150) This macro was not specified in ISO/IEC 9899:1990 and was + // specified as 199409L in ISO/IEC 9899/AMD1:1995. The intention + // is that this will remain an integer constant of type long int + // that is increased with each revision of this International Standard. + // + #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) + #define EA_COMPILER_IS_C99 1 + #endif + + // Is the compiler a C11 compiler? + // From ISO/IEC 9899:2011: + // Page 176, 6.10.8.1 (Predefined macro names) : + // __STDC_VERSION__ The integer constant 201112L. (178) + // + #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) + #define EA_COMPILER_IS_C11 1 + #endif + #endif + + // Some compilers (e.g. GCC) define __USE_ISOC99 if they are not + // strictly C99 compilers (or are simply C++ compilers) but are set + // to use C99 functionality. Metrowerks defines _MSL_C99 as 1 in + // this case, but 0 otherwise. + #if (defined(__USE_ISOC99) || (defined(_MSL_C99) && (_MSL_C99 == 1))) && !defined(EA_COMPILER_IS_C99) + #define EA_COMPILER_IS_C99 1 + #endif + + // Metrowerks defines C99 types (e.g. intptr_t) instrinsically when in C99 mode (-lang C99 on the command line). + #if (defined(_MSL_C99) && (_MSL_C99 == 1)) + #define EA_COMPILER_HAS_C99_TYPES 1 + #endif + + #if defined(__GNUC__) + #if (((__GNUC__ * 100) + __GNUC_MINOR__) >= 302) // Also, GCC defines _HAS_C9X. + #define EA_COMPILER_HAS_C99_TYPES 1 // The compiler is not necessarily a C99 compiler, but it defines C99 types. + + #ifndef __STDC_LIMIT_MACROS + #define __STDC_LIMIT_MACROS 1 + #endif + + #ifndef __STDC_CONSTANT_MACROS + #define __STDC_CONSTANT_MACROS 1 // This tells the GCC compiler that we want it to use its native C99 types. + #endif + #endif + #endif + + #if defined(_MSC_VER) && (_MSC_VER >= 1600) + #define EA_COMPILER_HAS_C99_TYPES 1 + #endif + + #ifdef __cplusplus + #define EA_COMPILER_IS_CPLUSPLUS 1 + #endif + + + // ------------------------------------------------------------------------ + // EA_PREPROCESSOR_JOIN + // + // This macro joins the two arguments together, even when one of + // the arguments is itself a macro (see 16.3.1 in C++98 standard). + // This is often used to create a unique name with __LINE__. + // + // For example, this declaration: + // char EA_PREPROCESSOR_JOIN(unique_, __LINE__); + // expands to this: + // char unique_73; + // + // Note that all versions of MSVC++ up to at least version 7.1 + // fail to properly compile macros that use __LINE__ in them + // when the "program database for edit and continue" option + // is enabled. The result is that __LINE__ gets converted to + // something like __LINE__(Var+37). + // + #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 + #endif + + + // ------------------------------------------------------------------------ + // EA_STRINGIFY + // + // Example usage: + // printf("Line: %s", EA_STRINGIFY(__LINE__)); + // + #ifndef EA_STRINGIFY + #define EA_STRINGIFY(x) EA_STRINGIFYIMPL(x) + #define EA_STRINGIFYIMPL(x) #x + #endif + + + // ------------------------------------------------------------------------ + // EA_IDENTITY + // + #ifndef EA_IDENTITY + #define EA_IDENTITY(x) x + #endif + + + // ------------------------------------------------------------------------ + // EA_COMPILER_MANAGED_CPP + // Defined if this is being compiled with Managed C++ extensions + #ifdef EA_COMPILER_MSVC + #if EA_COMPILER_VERSION >= 1300 + #ifdef _MANAGED + #define EA_COMPILER_MANAGED_CPP 1 + #endif + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_COMPILER_INTMAX_SIZE + // + // This is related to the concept of intmax_t uintmax_t, but is available + // in preprocessor form as opposed to compile-time form. At compile-time + // you can use intmax_t and uintmax_t to use the actual types. + // + #if defined(__GNUC__) && defined(__x86_64__) + #define EA_COMPILER_INTMAX_SIZE 16 // intmax_t is __int128_t (GCC extension) and is 16 bytes. + #else + #define EA_COMPILER_INTMAX_SIZE 8 // intmax_t is int64_t and is 8 bytes. + #endif + + + + // ------------------------------------------------------------------------ + // EA_LPAREN / EA_RPAREN / EA_COMMA / EA_SEMI + // + // These are used for using special characters in macro-using expressions. + // Note that this macro intentionally uses (), as in some cases it can't + // work unless it does. + // + // Example usage: + // int x = SOME_MACRO(SomeTemplate<int EA_COMMA() int EACOMMA() char>); + // + #ifndef EA_LPAREN + #define EA_LPAREN() ( + #endif + #ifndef EA_RPAREN + #define EA_RPAREN() ) + #endif + #ifndef EA_COMMA + #define EA_COMMA() , + #endif + #ifndef EA_SEMI + #define EA_SEMI() ; + #endif + + + + + // ------------------------------------------------------------------------ + // EA_OFFSETOF + // Implements a portable version of the non-standard offsetof macro. + // + // The offsetof macro is guaranteed to only work with POD types. However, we wish to use + // it for non-POD types but where we know that offsetof will still work for the cases + // in which we use it. GCC unilaterally gives a warning when using offsetof with a non-POD, + // even if the given usage happens to work. So we make a workaround version of offsetof + // here for GCC which has the same effect but tricks the compiler into not issuing the warning. + // The 65536 does the compiler fooling; the reinterpret_cast prevents the possibility of + // an overloaded operator& for the class getting in the way. + // + // Example usage: + // struct A{ int x; int y; }; + // size_t n = EA_OFFSETOF(A, y); + // + #if defined(__GNUC__) // We can't use GCC 4's __builtin_offsetof because it mistakenly complains about non-PODs that are really PODs. + #define EA_OFFSETOF(struct_, member_) ((size_t)(((uintptr_t)&reinterpret_cast<const volatile char&>((((struct_*)65536)->member_))) - 65536)) + #else + #define EA_OFFSETOF(struct_, member_) offsetof(struct_, member_) + #endif + + // ------------------------------------------------------------------------ + // EA_SIZEOF_MEMBER + // Implements a portable way to determine the size of a member. + // + // The EA_SIZEOF_MEMBER simply returns the size of a member within a class or struct; member + // access rules still apply. We offer two approaches depending on the compiler's support for non-static member + // initializers although most C++11 compilers support this. + // + // Example usage: + // struct A{ int x; int y; }; + // size_t n = EA_SIZEOF_MEMBER(A, y); + // + #ifndef EA_COMPILER_NO_EXTENDED_SIZEOF + #define EA_SIZEOF_MEMBER(struct_, member_) (sizeof(struct_::member_)) + #else + #define EA_SIZEOF_MEMBER(struct_, member_) (sizeof(((struct_*)0)->member_)) + #endif + + // ------------------------------------------------------------------------ + // alignment expressions + // + // Here we define + // EA_ALIGN_OF(type) // Returns size_t. + // EA_ALIGN_MAX_STATIC // The max align value that the compiler will respect for EA_ALIGN for static data (global and static variables). Some compilers allow high values, some allow no more than 8. EA_ALIGN_MIN is assumed to be 1. + // EA_ALIGN_MAX_AUTOMATIC // The max align value for automatic variables (variables declared as local to a function). + // EA_ALIGN(n) // Used as a prefix. n is byte alignment, with being a power of two. Most of the time you can use this and avoid using EA_PREFIX_ALIGN/EA_POSTFIX_ALIGN. + // EA_ALIGNED(t, v, n) // Type, variable, alignment. Used to align an instance. You should need this only for unusual compilers. + // EA_PACKED // Specifies that the given structure be packed (and not have its members aligned). + // + // Also we define the following for rare cases that it's needed. + // EA_PREFIX_ALIGN(n) // n is byte alignment, with being a power of two. You should need this only for unusual compilers. + // EA_POSTFIX_ALIGN(n) // Valid values for n are 1, 2, 4, 8, etc. You should need this only for unusual compilers. + // + // Example usage: + // size_t x = EA_ALIGN_OF(int); Non-aligned equivalents. Meaning + // EA_PREFIX_ALIGN(8) int x = 5; int x = 5; Align x on 8 for compilers that require prefix attributes. Can just use EA_ALIGN instead. + // EA_ALIGN(8) int x; int x; Align x on 8 for compilers that allow prefix attributes. + // int x EA_POSTFIX_ALIGN(8); int x; Align x on 8 for compilers that require postfix attributes. + // int x EA_POSTFIX_ALIGN(8) = 5; int x = 5; Align x on 8 for compilers that require postfix attributes. + // int x EA_POSTFIX_ALIGN(8)(5); int x(5); Align x on 8 for compilers that require postfix attributes. + // struct EA_PREFIX_ALIGN(8) X { int x; } EA_POSTFIX_ALIGN(8); struct X { int x; }; Define X as a struct which is aligned on 8 when used. + // EA_ALIGNED(int, x, 8) = 5; int x = 5; Align x on 8. + // EA_ALIGNED(int, x, 16)(5); int x(5); Align x on 16. + // EA_ALIGNED(int, x[3], 16); int x[3]; Align x array on 16. + // EA_ALIGNED(int, x[3], 16) = { 1, 2, 3 }; int x[3] = { 1, 2, 3 }; Align x array on 16. + // int x[3] EA_PACKED; int x[3]; Pack the 3 ints of the x array. GCC doesn't seem to support packing of int arrays. + // struct EA_ALIGN(32) X { int x; int y; }; struct X { int x; }; Define A as a struct which is aligned on 32 when used. + // EA_ALIGN(32) struct X { int x; int y; } Z; struct X { int x; } Z; Define A as a struct, and align the instance Z on 32. + // struct X { int x EA_PACKED; int y EA_PACKED; }; struct X { int x; int y; }; Pack the x and y members of struct X. + // struct X { int x; int y; } EA_PACKED; struct X { int x; int y; }; Pack the members of struct X. + // typedef EA_ALIGNED(int, int16, 16); int16 n16; typedef int int16; int16 n16; Define int16 as an int which is aligned on 16. + // typedef EA_ALIGNED(X, X16, 16); X16 x16; typedef X X16; X16 x16; Define X16 as an X which is aligned on 16. + + #if !defined(EA_ALIGN_MAX) // If the user hasn't globally set an alternative value... + #if defined(EA_PROCESSOR_ARM) // ARM compilers in general tend to limit automatic variables to 8 or less. + #define EA_ALIGN_MAX_STATIC 1048576 + #define EA_ALIGN_MAX_AUTOMATIC 1 // Typically they support only built-in natural aligment types (both arm-eabi and apple-abi). + #elif defined(EA_PLATFORM_APPLE) + #define EA_ALIGN_MAX_STATIC 1048576 + #define EA_ALIGN_MAX_AUTOMATIC 16 + #else + #define EA_ALIGN_MAX_STATIC 1048576 // Arbitrarily high value. What is the actual max? + #define EA_ALIGN_MAX_AUTOMATIC 1048576 + #endif + #endif + + // EDG intends to be compatible with GCC but has a bug whereby it + // fails to support calling a constructor in an aligned declaration when + // using postfix alignment attributes. Prefix works for alignment, but does not align + // the size like postfix does. Prefix also fails on templates. So gcc style post fix + // is still used, but the user will need to use EA_POSTFIX_ALIGN before the constructor parameters. + #if defined(__GNUC__) && (__GNUC__ < 3) + #define EA_ALIGN_OF(type) ((size_t)__alignof__(type)) + #define EA_ALIGN(n) + #define EA_PREFIX_ALIGN(n) + #define EA_POSTFIX_ALIGN(n) __attribute__((aligned(n))) + #define EA_ALIGNED(variable_type, variable, n) variable_type variable __attribute__((aligned(n))) + #define EA_PACKED __attribute__((packed)) + + // GCC 3.x+, IBM, and clang support prefix attributes. + #elif (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__xlC__) || defined(__clang__) + #define EA_ALIGN_OF(type) ((size_t)__alignof__(type)) + #define EA_ALIGN(n) __attribute__((aligned(n))) + #define EA_PREFIX_ALIGN(n) + #define EA_POSTFIX_ALIGN(n) __attribute__((aligned(n))) + #define EA_ALIGNED(variable_type, variable, n) variable_type variable __attribute__((aligned(n))) + #define EA_PACKED __attribute__((packed)) + + // Metrowerks supports prefix attributes. + // Metrowerks does not support packed alignment attributes. + #elif defined(EA_COMPILER_INTEL) || defined(CS_UNDEFINED_STRING) || (defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1300)) + #define EA_ALIGN_OF(type) ((size_t)__alignof(type)) + #define EA_ALIGN(n) __declspec(align(n)) + #define EA_PREFIX_ALIGN(n) EA_ALIGN(n) + #define EA_POSTFIX_ALIGN(n) + #define EA_ALIGNED(variable_type, variable, n) EA_ALIGN(n) variable_type variable + #define EA_PACKED // See EA_PRAGMA_PACK_VC for an alternative. + + // Arm brand compiler + #elif defined(EA_COMPILER_ARM) + #define EA_ALIGN_OF(type) ((size_t)__ALIGNOF__(type)) + #define EA_ALIGN(n) __align(n) + #define EA_PREFIX_ALIGN(n) __align(n) + #define EA_POSTFIX_ALIGN(n) + #define EA_ALIGNED(variable_type, variable, n) __align(n) variable_type variable + #define EA_PACKED __packed + + #else // Unusual compilers + // There is nothing we can do about some of these. This is not as bad a problem as it seems. + // If the given platform/compiler doesn't support alignment specifications, then it's somewhat + // likely that alignment doesn't matter for that platform. Otherwise they would have defined + // functionality to manipulate alignment. + #define EA_ALIGN(n) + #define EA_PREFIX_ALIGN(n) + #define EA_POSTFIX_ALIGN(n) + #define EA_ALIGNED(variable_type, variable, n) variable_type variable + #define EA_PACKED + + #ifdef __cplusplus + template <typename T> struct EAAlignOf1 { enum { s = sizeof (T), value = s ^ (s & (s - 1)) }; }; + template <typename T> struct EAAlignOf2; + template <int size_diff> struct helper { template <typename T> struct Val { enum { value = size_diff }; }; }; + template <> struct helper<0> { template <typename T> struct Val { enum { value = EAAlignOf2<T>::value }; }; }; + template <typename T> struct EAAlignOf2 { struct Big { T x; char c; }; + enum { diff = sizeof (Big) - sizeof (T), value = helper<diff>::template Val<Big>::value }; }; + template <typename T> struct EAAlignof3 { enum { x = EAAlignOf2<T>::value, y = EAAlignOf1<T>::value, value = x < y ? x : y }; }; + #define EA_ALIGN_OF(type) ((size_t)EAAlignof3<type>::value) + + #else + // C implementation of EA_ALIGN_OF + // This implementation works for most cases, but doesn't directly work + // for types such as function pointer declarations. To work with those + // types you need to typedef the type and then use the typedef in EA_ALIGN_OF. + #define EA_ALIGN_OF(type) ((size_t)offsetof(struct { char c; type m; }, m)) + #endif + #endif + + // EA_PRAGMA_PACK_VC + // + // Wraps #pragma pack in a way that allows for cleaner code. + // + // Example usage: + // EA_PRAGMA_PACK_VC(push, 1) + // struct X{ char c; int i; }; + // EA_PRAGMA_PACK_VC(pop) + // + #if !defined(EA_PRAGMA_PACK_VC) + #if defined(EA_COMPILER_MSVC) + #define EA_PRAGMA_PACK_VC(...) __pragma(pack(__VA_ARGS__)) + #elif !defined(EA_COMPILER_NO_VARIADIC_MACROS) + #define EA_PRAGMA_PACK_VC(...) + #else + // No support. However, all compilers of significance to us support variadic macros. + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_LIKELY / EA_UNLIKELY + // + // Defined as a macro which gives a hint to the compiler for branch + // prediction. GCC gives you the ability to manually give a hint to + // the compiler about the result of a comparison, though it's often + // best to compile shipping code with profiling feedback under both + // GCC (-fprofile-arcs) and VC++ (/LTCG:PGO, etc.). However, there + // are times when you feel very sure that a boolean expression will + // usually evaluate to either true or false and can help the compiler + // by using an explicity directive... + // + // Example usage: + // if(EA_LIKELY(a == 0)) // Tell the compiler that a will usually equal 0. + // { ... } + // + // Example usage: + // if(EA_UNLIKELY(a == 0)) // Tell the compiler that a will usually not equal 0. + // { ... } + // + #ifndef EA_LIKELY + #if (defined(__GNUC__) && (__GNUC__ >= 3)) || defined(__clang__) + #if defined(__cplusplus) + #define EA_LIKELY(x) __builtin_expect(!!(x), true) + #define EA_UNLIKELY(x) __builtin_expect(!!(x), false) + #else + #define EA_LIKELY(x) __builtin_expect(!!(x), 1) + #define EA_UNLIKELY(x) __builtin_expect(!!(x), 0) + #endif + #else + #define EA_LIKELY(x) (x) + #define EA_UNLIKELY(x) (x) + #endif + #endif + + // ------------------------------------------------------------------------ + // EA_HAS_INCLUDE_AVAILABLE + // + // Used to guard against the EA_HAS_INCLUDE() macro on compilers that do not + // support said feature. + // + // Example usage: + // + // #if EA_HAS_INCLUDE_AVAILABLE + // #if EA_HAS_INCLUDE("myinclude.h") + // #include "myinclude.h" + // #endif + // #endif + #if !defined(EA_HAS_INCLUDE_AVAILABLE) + #if EA_COMPILER_CPP17_ENABLED || EA_COMPILER_CLANG || EA_COMPILER_GNUC + #define EA_HAS_INCLUDE_AVAILABLE 1 + #else + #define EA_HAS_INCLUDE_AVAILABLE 0 + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_HAS_INCLUDE + // + // May be used in #if and #elif expressions to test for the existence + // of the header referenced in the operand. If possible it evaluates to a + // non-zero value and zero otherwise. The operand is the same form as the file + // in a #include directive. + // + // Example usage: + // + // #if EA_HAS_INCLUDE("myinclude.h") + // #include "myinclude.h" + // #endif + // + // #if EA_HAS_INCLUDE(<myinclude.h>) + // #include <myinclude.h> + // #endif + + #if !defined(EA_HAS_INCLUDE) + #if EA_COMPILER_CPP17_ENABLED + #define EA_HAS_INCLUDE(x) __has_include(x) + #elif EA_COMPILER_CLANG + #define EA_HAS_INCLUDE(x) __has_include(x) + #elif EA_COMPILER_GNUC + #define EA_HAS_INCLUDE(x) __has_include(x) + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_INIT_PRIORITY_AVAILABLE + // + // This value is either not defined, or defined to 1. + // Defines if the GCC attribute init_priority is supported by the compiler. + // + #if !defined(EA_INIT_PRIORITY_AVAILABLE) + #if defined(__GNUC__) && !defined(__EDG__) // EDG typically #defines __GNUC__ but doesn't implement init_priority. + #define EA_INIT_PRIORITY_AVAILABLE 1 + #elif defined(__clang__) + #define EA_INIT_PRIORITY_AVAILABLE 1 // Clang implements init_priority + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_INIT_PRIORITY + // + // This is simply a wrapper for the GCC init_priority attribute that allows + // multiplatform code to be easier to read. This attribute doesn't apply + // to VC++ because VC++ uses file-level pragmas to control init ordering. + // + // Example usage: + // SomeClass gSomeClass EA_INIT_PRIORITY(2000); + // + #if !defined(EA_INIT_PRIORITY) + #if defined(EA_INIT_PRIORITY_AVAILABLE) + #define EA_INIT_PRIORITY(x) __attribute__ ((init_priority (x))) + #else + #define EA_INIT_PRIORITY(x) + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_INIT_SEG_AVAILABLE + // + // + #if !defined(EA_INIT_SEG_AVAILABLE) + #if defined(_MSC_VER) + #define EA_INIT_SEG_AVAILABLE 1 + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_INIT_SEG + // + // Specifies a keyword or code section that affects the order in which startup code is executed. + // + // https://docs.microsoft.com/en-us/cpp/preprocessor/init-seg?view=vs-2019 + // + // Example: + // EA_INIT_SEG(compiler) MyType gMyTypeGlobal; + // EA_INIT_SEG("my_section") MyOtherType gMyOtherTypeGlobal; + // + #if !defined(EA_INIT_SEG) + #if defined(EA_INIT_SEG_AVAILABLE) + #define EA_INIT_SEG(x) \ + __pragma(warning(push)) __pragma(warning(disable : 4074)) __pragma(warning(disable : 4075)) __pragma(init_seg(x)) \ + __pragma(warning(pop)) + #else + #define EA_INIT_SEG(x) + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_MAY_ALIAS_AVAILABLE + // + // Defined as 0, 1, or 2. + // Defines if the GCC attribute may_alias is supported by the compiler. + // Consists of a value 0 (unsupported, shouldn't be used), 1 (some support), + // or 2 (full proper support). + // + #ifndef EA_MAY_ALIAS_AVAILABLE + #if defined(__GNUC__) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 303) + #if !defined(__EDG__) // define it as 1 while defining GCC's support as 2. + #define EA_MAY_ALIAS_AVAILABLE 2 + #else + #define EA_MAY_ALIAS_AVAILABLE 0 + #endif + #else + #define EA_MAY_ALIAS_AVAILABLE 0 + #endif + #endif + + + // EA_MAY_ALIAS + // + // Defined as a macro that wraps the GCC may_alias attribute. This attribute + // has no significance for VC++ because VC++ doesn't support the concept of + // strict aliasing. Users should avoid writing code that breaks strict + // aliasing rules; EA_MAY_ALIAS is for cases with no alternative. + // + // Example usage: + // void* EA_MAY_ALIAS gPtr = NULL; + // + // Example usage: + // typedef void* EA_MAY_ALIAS pvoid_may_alias; + // pvoid_may_alias gPtr = NULL; + // + #if EA_MAY_ALIAS_AVAILABLE + #define EA_MAY_ALIAS __attribute__((__may_alias__)) + #else + #define EA_MAY_ALIAS + #endif + + + // ------------------------------------------------------------------------ + // EA_ASSUME + // + // This acts the same as the VC++ __assume directive and is implemented + // simply as a wrapper around it to allow portable usage of it and to take + // advantage of it if and when it appears in other compilers. + // + // Example usage: + // void Function(int a) { + // switch(a) { + // case 1: + // DoSomething(1); + // break; + // case 2: + // DoSomething(-1); + // break; + // default: + // EA_ASSUME(0); // This tells the optimizer that the default cannot be reached. + // } + // } + // + #ifndef EA_ASSUME + #if defined(_MSC_VER) && (_MSC_VER >= 1300) // If VC7.0 and later + #define EA_ASSUME(x) __assume(x) + #else + #define EA_ASSUME(x) + #endif + #endif + + + + // ------------------------------------------------------------------------ + // EA_ANALYSIS_ASSUME + // + // This acts the same as the VC++ __analysis_assume directive and is implemented + // simply as a wrapper around it to allow portable usage of it and to take + // advantage of it if and when it appears in other compilers. + // + // Example usage: + // char Function(char* p) { + // EA_ANALYSIS_ASSUME(p != NULL); + // return *p; + // } + // + #ifndef EA_ANALYSIS_ASSUME + #if defined(_MSC_VER) && (_MSC_VER >= 1300) // If VC7.0 and later + #define EA_ANALYSIS_ASSUME(x) __analysis_assume(!!(x)) // !! because that allows for convertible-to-bool in addition to bool. + #else + #define EA_ANALYSIS_ASSUME(x) + #endif + #endif + + + + // ------------------------------------------------------------------------ + // EA_DISABLE_VC_WARNING / EA_RESTORE_VC_WARNING + // + // Disable and re-enable warning(s) within code. + // This is simply a wrapper for VC++ #pragma warning(disable: nnnn) for the + // purpose of making code easier to read due to avoiding nested compiler ifdefs + // directly in code. + // + // Example usage: + // EA_DISABLE_VC_WARNING(4127 3244) + // <code> + // EA_RESTORE_VC_WARNING() + // + #ifndef EA_DISABLE_VC_WARNING + #if defined(_MSC_VER) + #define EA_DISABLE_VC_WARNING(w) \ + __pragma(warning(push)) \ + __pragma(warning(disable:w)) + #else + #define EA_DISABLE_VC_WARNING(w) + #endif + #endif + + #ifndef EA_RESTORE_VC_WARNING + #if defined(_MSC_VER) + #define EA_RESTORE_VC_WARNING() \ + __pragma(warning(pop)) + #else + #define EA_RESTORE_VC_WARNING() + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_ENABLE_VC_WARNING_AS_ERROR / EA_DISABLE_VC_WARNING_AS_ERROR + // + // Disable and re-enable treating a warning as error within code. + // This is simply a wrapper for VC++ #pragma warning(error: nnnn) for the + // purpose of making code easier to read due to avoiding nested compiler ifdefs + // directly in code. + // + // Example usage: + // EA_ENABLE_VC_WARNING_AS_ERROR(4996) + // <code> + // EA_DISABLE_VC_WARNING_AS_ERROR() + // + #ifndef EA_ENABLE_VC_WARNING_AS_ERROR + #if defined(_MSC_VER) + #define EA_ENABLE_VC_WARNING_AS_ERROR(w) \ + __pragma(warning(push)) \ + __pragma(warning(error:w)) + #else + #define EA_ENABLE_VC_WARNING_AS_ERROR(w) + #endif + #endif + + #ifndef EA_DISABLE_VC_WARNING_AS_ERROR + #if defined(_MSC_VER) + #define EA_DISABLE_VC_WARNING_AS_ERROR() \ + __pragma(warning(pop)) + #else + #define EA_DISABLE_VC_WARNING_AS_ERROR() + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_DISABLE_GCC_WARNING / EA_RESTORE_GCC_WARNING + // + // Example usage: + // // Only one warning can be ignored per statement, due to how GCC works. + // EA_DISABLE_GCC_WARNING(-Wuninitialized) + // EA_DISABLE_GCC_WARNING(-Wunused) + // <code> + // EA_RESTORE_GCC_WARNING() + // EA_RESTORE_GCC_WARNING() + // + #ifndef EA_DISABLE_GCC_WARNING + #if defined(EA_COMPILER_GNUC) + #define EAGCCWHELP0(x) #x + #define EAGCCWHELP1(x) EAGCCWHELP0(GCC diagnostic ignored x) + #define EAGCCWHELP2(x) EAGCCWHELP1(#x) + #endif + + #if defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4006) // Can't test directly for __GNUC__ because some compilers lie. + #define EA_DISABLE_GCC_WARNING(w) \ + _Pragma("GCC diagnostic push") \ + _Pragma(EAGCCWHELP2(w)) + #elif defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4004) + #define EA_DISABLE_GCC_WARNING(w) \ + _Pragma(EAGCCWHELP2(w)) + #else + #define EA_DISABLE_GCC_WARNING(w) + #endif + #endif + + #ifndef EA_RESTORE_GCC_WARNING + #if defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4006) + #define EA_RESTORE_GCC_WARNING() \ + _Pragma("GCC diagnostic pop") + #else + #define EA_RESTORE_GCC_WARNING() + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_DISABLE_ALL_GCC_WARNINGS / EA_RESTORE_ALL_GCC_WARNINGS + // + // This isn't possible except via using _Pragma("GCC system_header"), though + // that has some limitations in how it works. Another means is to manually + // disable individual warnings within a GCC diagnostic push statement. + // GCC doesn't have as many warnings as VC++ and EDG and so this may be feasible. + // ------------------------------------------------------------------------ + + + // ------------------------------------------------------------------------ + // EA_ENABLE_GCC_WARNING_AS_ERROR / EA_DISABLE_GCC_WARNING_AS_ERROR + // + // Example usage: + // // Only one warning can be treated as an error per statement, due to how GCC works. + // EA_ENABLE_GCC_WARNING_AS_ERROR(-Wuninitialized) + // EA_ENABLE_GCC_WARNING_AS_ERROR(-Wunused) + // <code> + // EA_DISABLE_GCC_WARNING_AS_ERROR() + // EA_DISABLE_GCC_WARNING_AS_ERROR() + // + #ifndef EA_ENABLE_GCC_WARNING_AS_ERROR + #if defined(EA_COMPILER_GNUC) + #define EAGCCWERRORHELP0(x) #x + #define EAGCCWERRORHELP1(x) EAGCCWERRORHELP0(GCC diagnostic error x) + #define EAGCCWERRORHELP2(x) EAGCCWERRORHELP1(#x) + #endif + + #if defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4006) // Can't test directly for __GNUC__ because some compilers lie. + #define EA_ENABLE_GCC_WARNING_AS_ERROR(w) \ + _Pragma("GCC diagnostic push") \ + _Pragma(EAGCCWERRORHELP2(w)) + #elif defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4004) + #define EA_DISABLE_GCC_WARNING(w) \ + _Pragma(EAGCCWERRORHELP2(w)) + #else + #define EA_DISABLE_GCC_WARNING(w) + #endif + #endif + + #ifndef EA_DISABLE_GCC_WARNING_AS_ERROR + #if defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4006) + #define EA_DISABLE_GCC_WARNING_AS_ERROR() \ + _Pragma("GCC diagnostic pop") + #else + #define EA_DISABLE_GCC_WARNING_AS_ERROR() + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_DISABLE_CLANG_WARNING / EA_RESTORE_CLANG_WARNING + // + // Example usage: + // // Only one warning can be ignored per statement, due to how clang works. + // EA_DISABLE_CLANG_WARNING(-Wuninitialized) + // EA_DISABLE_CLANG_WARNING(-Wunused) + // <code> + // EA_RESTORE_CLANG_WARNING() + // EA_RESTORE_CLANG_WARNING() + // + #ifndef EA_DISABLE_CLANG_WARNING + #if defined(EA_COMPILER_CLANG) || defined(EA_COMPILER_CLANG_CL) + #define EACLANGWHELP0(x) #x + #define EACLANGWHELP1(x) EACLANGWHELP0(clang diagnostic ignored x) + #define EACLANGWHELP2(x) EACLANGWHELP1(#x) + + #define EA_DISABLE_CLANG_WARNING(w) \ + _Pragma("clang diagnostic push") \ + _Pragma(EACLANGWHELP2(-Wunknown-warning-option))\ + _Pragma(EACLANGWHELP2(w)) + #else + #define EA_DISABLE_CLANG_WARNING(w) + #endif + #endif + + #ifndef EA_RESTORE_CLANG_WARNING + #if defined(EA_COMPILER_CLANG) || defined(EA_COMPILER_CLANG_CL) + #define EA_RESTORE_CLANG_WARNING() \ + _Pragma("clang diagnostic pop") + #else + #define EA_RESTORE_CLANG_WARNING() + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_DISABLE_ALL_CLANG_WARNINGS / EA_RESTORE_ALL_CLANG_WARNINGS + // + // The situation for clang is the same as for GCC. See above. + // ------------------------------------------------------------------------ + + + // ------------------------------------------------------------------------ + // EA_ENABLE_CLANG_WARNING_AS_ERROR / EA_DISABLE_CLANG_WARNING_AS_ERROR + // + // Example usage: + // // Only one warning can be treated as an error per statement, due to how clang works. + // EA_ENABLE_CLANG_WARNING_AS_ERROR(-Wuninitialized) + // EA_ENABLE_CLANG_WARNING_AS_ERROR(-Wunused) + // <code> + // EA_DISABLE_CLANG_WARNING_AS_ERROR() + // EA_DISABLE_CLANG_WARNING_AS_ERROR() + // + #ifndef EA_ENABLE_CLANG_WARNING_AS_ERROR + #if defined(EA_COMPILER_CLANG) || defined(EA_COMPILER_CLANG_CL) + #define EACLANGWERRORHELP0(x) #x + #define EACLANGWERRORHELP1(x) EACLANGWERRORHELP0(clang diagnostic error x) + #define EACLANGWERRORHELP2(x) EACLANGWERRORHELP1(#x) + + #define EA_ENABLE_CLANG_WARNING_AS_ERROR(w) \ + _Pragma("clang diagnostic push") \ + _Pragma(EACLANGWERRORHELP2(w)) + #else + #define EA_DISABLE_CLANG_WARNING(w) + #endif + #endif + + #ifndef EA_DISABLE_CLANG_WARNING_AS_ERROR + #if defined(EA_COMPILER_CLANG) || defined(EA_COMPILER_CLANG_CL) + #define EA_DISABLE_CLANG_WARNING_AS_ERROR() \ + _Pragma("clang diagnostic pop") + #else + #define EA_DISABLE_CLANG_WARNING_AS_ERROR() + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_DISABLE_SN_WARNING / EA_RESTORE_SN_WARNING + // + // Note that we define this macro specifically for the SN compiler instead of + // having a generic one for EDG-based compilers. The reason for this is that + // while SN is indeed based on EDG, SN has different warning value mappings + // and thus warning 1234 for SN is not the same as 1234 for all other EDG compilers. + // + // Example usage: + // // Currently we are limited to one warning per line. + // EA_DISABLE_SN_WARNING(1787) + // EA_DISABLE_SN_WARNING(552) + // <code> + // EA_RESTORE_SN_WARNING() + // EA_RESTORE_SN_WARNING() + // + #ifndef EA_DISABLE_SN_WARNING + #define EA_DISABLE_SN_WARNING(w) + #endif + + #ifndef EA_RESTORE_SN_WARNING + #define EA_RESTORE_SN_WARNING() + #endif + + + // ------------------------------------------------------------------------ + // EA_DISABLE_ALL_SN_WARNINGS / EA_RESTORE_ALL_SN_WARNINGS + // + // Example usage: + // EA_DISABLE_ALL_SN_WARNINGS() + // <code> + // EA_RESTORE_ALL_SN_WARNINGS() + // + #ifndef EA_DISABLE_ALL_SN_WARNINGS + #define EA_DISABLE_ALL_SN_WARNINGS() + #endif + + #ifndef EA_RESTORE_ALL_SN_WARNINGS + #define EA_RESTORE_ALL_SN_WARNINGS() + #endif + + + + // ------------------------------------------------------------------------ + // EA_DISABLE_GHS_WARNING / EA_RESTORE_GHS_WARNING + // + // Disable warnings from the Green Hills compiler. + // + // Example usage: + // EA_DISABLE_GHS_WARNING(193) + // EA_DISABLE_GHS_WARNING(236, 5323) + // <code> + // EA_RESTORE_GHS_WARNING() + // EA_RESTORE_GHS_WARNING() + // + #ifndef EA_DISABLE_GHS_WARNING + #define EA_DISABLE_GHS_WARNING(w) + #endif + + #ifndef EA_RESTORE_GHS_WARNING + #define EA_RESTORE_GHS_WARNING() + #endif + + + // ------------------------------------------------------------------------ + // EA_DISABLE_ALL_GHS_WARNINGS / EA_RESTORE_ALL_GHS_WARNINGS + // + // #ifndef EA_DISABLE_ALL_GHS_WARNINGS + // #if defined(EA_COMPILER_GREEN_HILLS) + // #define EA_DISABLE_ALL_GHS_WARNINGS(w) \_ + // _Pragma("_________") + // #else + // #define EA_DISABLE_ALL_GHS_WARNINGS(w) + // #endif + // #endif + // + // #ifndef EA_RESTORE_ALL_GHS_WARNINGS + // #if defined(EA_COMPILER_GREEN_HILLS) + // #define EA_RESTORE_ALL_GHS_WARNINGS() \_ + // _Pragma("_________") + // #else + // #define EA_RESTORE_ALL_GHS_WARNINGS() + // #endif + // #endif + + + + // ------------------------------------------------------------------------ + // EA_DISABLE_EDG_WARNING / EA_RESTORE_EDG_WARNING + // + // Example usage: + // // Currently we are limited to one warning per line. + // EA_DISABLE_EDG_WARNING(193) + // EA_DISABLE_EDG_WARNING(236) + // <code> + // EA_RESTORE_EDG_WARNING() + // EA_RESTORE_EDG_WARNING() + // + #ifndef EA_DISABLE_EDG_WARNING + // EDG-based compilers are inconsistent in how the implement warning pragmas. + #if defined(EA_COMPILER_EDG) && !defined(EA_COMPILER_INTEL) && !defined(EA_COMPILER_RVCT) + #define EAEDGWHELP0(x) #x + #define EAEDGWHELP1(x) EAEDGWHELP0(diag_suppress x) + + #define EA_DISABLE_EDG_WARNING(w) \ + _Pragma("control %push diag") \ + _Pragma(EAEDGWHELP1(w)) + #else + #define EA_DISABLE_EDG_WARNING(w) + #endif + #endif + + #ifndef EA_RESTORE_EDG_WARNING + #if defined(EA_COMPILER_EDG) && !defined(EA_COMPILER_INTEL) && !defined(EA_COMPILER_RVCT) + #define EA_RESTORE_EDG_WARNING() \ + _Pragma("control %pop diag") + #else + #define EA_RESTORE_EDG_WARNING() + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_DISABLE_ALL_EDG_WARNINGS / EA_RESTORE_ALL_EDG_WARNINGS + // + //#ifndef EA_DISABLE_ALL_EDG_WARNINGS + // #if defined(EA_COMPILER_EDG) && !defined(EA_COMPILER_SN) + // #define EA_DISABLE_ALL_EDG_WARNINGS(w) \_ + // _Pragma("_________") + // #else + // #define EA_DISABLE_ALL_EDG_WARNINGS(w) + // #endif + //#endif + // + //#ifndef EA_RESTORE_ALL_EDG_WARNINGS + // #if defined(EA_COMPILER_EDG) && !defined(EA_COMPILER_SN) + // #define EA_RESTORE_ALL_EDG_WARNINGS() \_ + // _Pragma("_________") + // #else + // #define EA_RESTORE_ALL_EDG_WARNINGS() + // #endif + //#endif + + + + // ------------------------------------------------------------------------ + // EA_DISABLE_CW_WARNING / EA_RESTORE_CW_WARNING + // + // Note that this macro can only control warnings via numbers and not by + // names. The reason for this is that the compiler's syntax for such + // warnings is not the same as for numbers. + // + // Example usage: + // // Currently we are limited to one warning per line and must also specify the warning in the restore macro. + // EA_DISABLE_CW_WARNING(10317) + // EA_DISABLE_CW_WARNING(10324) + // <code> + // EA_RESTORE_CW_WARNING(10317) + // EA_RESTORE_CW_WARNING(10324) + // + #ifndef EA_DISABLE_CW_WARNING + #define EA_DISABLE_CW_WARNING(w) + #endif + + #ifndef EA_RESTORE_CW_WARNING + + #define EA_RESTORE_CW_WARNING(w) + + #endif + + + // ------------------------------------------------------------------------ + // EA_DISABLE_ALL_CW_WARNINGS / EA_RESTORE_ALL_CW_WARNINGS + // + #ifndef EA_DISABLE_ALL_CW_WARNINGS + #define EA_DISABLE_ALL_CW_WARNINGS() + + #endif + + #ifndef EA_RESTORE_ALL_CW_WARNINGS + #define EA_RESTORE_ALL_CW_WARNINGS() + #endif + + + + // ------------------------------------------------------------------------ + // EA_PURE + // + // This acts the same as the GCC __attribute__ ((pure)) directive and is + // implemented simply as a wrapper around it to allow portable usage of + // it and to take advantage of it if and when it appears in other compilers. + // + // A "pure" function is one that has no effects except its return value and + // its return value is a function of only the function's parameters or + // non-volatile global variables. Any parameter or global variable access + // must be read-only. Loop optimization and subexpression elimination can be + // applied to such functions. A common example is strlen(): Given identical + // inputs, the function's return value (its only effect) is invariant across + // multiple invocations and thus can be pulled out of a loop and called but once. + // + // Example usage: + // EA_PURE void Function(); + // + #ifndef EA_PURE + #if defined(EA_COMPILER_GNUC) + #define EA_PURE __attribute__((pure)) + #elif defined(EA_COMPILER_ARM) // Arm brand compiler for ARM CPU + #define EA_PURE __pure + #else + #define EA_PURE + #endif + #endif + + + + // ------------------------------------------------------------------------ + // EA_WEAK + // EA_WEAK_SUPPORTED -- defined as 0 or 1. + // + // GCC + // The weak attribute causes the declaration to be emitted as a weak + // symbol rather than a global. This is primarily useful in defining + // library functions which can be overridden in user code, though it + // can also be used with non-function declarations. + // + // VC++ + // At link time, if multiple definitions of a COMDAT are seen, the linker + // picks one and discards the rest. If the linker option /OPT:REF + // is selected, then COMDAT elimination will occur to remove all the + // unreferenced data items in the linker output. + // + // Example usage: + // EA_WEAK void Function(); + // + #ifndef EA_WEAK + #if defined(_MSC_VER) && (_MSC_VER >= 1300) // If VC7.0 and later + #define EA_WEAK __declspec(selectany) + #define EA_WEAK_SUPPORTED 1 + #elif defined(_MSC_VER) || (defined(__GNUC__) && defined(__CYGWIN__)) + #define EA_WEAK + #define EA_WEAK_SUPPORTED 0 + #elif defined(EA_COMPILER_ARM) // Arm brand compiler for ARM CPU + #define EA_WEAK __weak + #define EA_WEAK_SUPPORTED 1 + #else // GCC and IBM compilers, others. + #define EA_WEAK __attribute__((weak)) + #define EA_WEAK_SUPPORTED 1 + #endif + #endif + + + + // ------------------------------------------------------------------------ + // EA_UNUSED + // + // Makes compiler warnings about unused variables go away. + // + // Example usage: + // void Function(int x) + // { + // int y; + // EA_UNUSED(x); + // EA_UNUSED(y); + // } + // + #ifndef EA_UNUSED + // The EDG solution below is pretty weak and needs to be augmented or replaced. + // It can't handle the C language, is limited to places where template declarations + // can be used, and requires the type x to be usable as a functions reference argument. + #if defined(__cplusplus) && defined(__EDG__) + template <typename T> + inline void EABaseUnused(T const volatile & x) { (void)x; } + #define EA_UNUSED(x) EABaseUnused(x) + #else + #define EA_UNUSED(x) (void)x + #endif + #endif + + + + // ------------------------------------------------------------------------ + // EA_EMPTY + // + // Allows for a null statement, usually for the purpose of avoiding compiler warnings. + // + // Example usage: + // #ifdef EA_DEBUG + // #define MyDebugPrintf(x, y) printf(x, y) + // #else + // #define MyDebugPrintf(x, y) EA_EMPTY + // #endif + // + #ifndef EA_EMPTY + #define EA_EMPTY (void)0 + #endif + + + // ------------------------------------------------------------------------ + // EA_CURRENT_FUNCTION + // + // Provides a consistent way to get the current function name as a macro + // like the __FILE__ and __LINE__ macros work. The C99 standard specifies + // that __func__ be provided by the compiler, but most compilers don't yet + // follow that convention. However, many compilers have an alternative. + // + // We also define EA_CURRENT_FUNCTION_SUPPORTED for when it is not possible + // to have EA_CURRENT_FUNCTION work as expected. + // + // Defined inside a function because otherwise the macro might not be + // defined and code below might not compile. This happens with some + // compilers. + // + #ifndef EA_CURRENT_FUNCTION + #if defined __GNUC__ || (defined __ICC && __ICC >= 600) + #define EA_CURRENT_FUNCTION __PRETTY_FUNCTION__ + #elif defined(__FUNCSIG__) + #define EA_CURRENT_FUNCTION __FUNCSIG__ + #elif (defined __INTEL_COMPILER && __INTEL_COMPILER >= 600) || (defined __IBMCPP__ && __IBMCPP__ >= 500) || (defined CS_UNDEFINED_STRING && CS_UNDEFINED_STRING >= 0x4200) + #define EA_CURRENT_FUNCTION __FUNCTION__ + #elif defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901 + #define EA_CURRENT_FUNCTION __func__ + #else + #define EA_CURRENT_FUNCTION "(unknown function)" + #endif + #endif + + + // ------------------------------------------------------------------------ + // wchar_t + // Here we define: + // EA_WCHAR_T_NON_NATIVE + // EA_WCHAR_SIZE = <sizeof(wchar_t)> + // + #ifndef EA_WCHAR_T_NON_NATIVE + // Compilers that always implement wchar_t as native include: + // COMEAU, new SN, and other EDG-based compilers. + // GCC + // Borland + // SunPro + // IBM Visual Age + #if defined(EA_COMPILER_INTEL) + #if (EA_COMPILER_VERSION < 700) + #define EA_WCHAR_T_NON_NATIVE 1 + #else + #if (!defined(_WCHAR_T_DEFINED) && !defined(_WCHAR_T)) + #define EA_WCHAR_T_NON_NATIVE 1 + #endif + #endif + #elif defined(EA_COMPILER_MSVC) || (defined(EA_COMPILER_CLANG) && defined(EA_PLATFORM_WINDOWS)) + #ifndef _NATIVE_WCHAR_T_DEFINED + #define EA_WCHAR_T_NON_NATIVE 1 + #endif + #elif defined(__EDG_VERSION__) && (!defined(_WCHAR_T) && (__EDG_VERSION__ < 400)) // EDG prior to v4 uses _WCHAR_T to indicate if wchar_t is native. v4+ may define something else, but we're not currently aware of it. + #define EA_WCHAR_T_NON_NATIVE 1 + #endif + #endif + + #ifndef EA_WCHAR_SIZE // If the user hasn't specified that it is a given size... + #if defined(__WCHAR_MAX__) // GCC defines this for most platforms. + #if (__WCHAR_MAX__ == 2147483647) || (__WCHAR_MAX__ == 4294967295) + #define EA_WCHAR_SIZE 4 + #elif (__WCHAR_MAX__ == 32767) || (__WCHAR_MAX__ == 65535) + #define EA_WCHAR_SIZE 2 + #elif (__WCHAR_MAX__ == 127) || (__WCHAR_MAX__ == 255) + #define EA_WCHAR_SIZE 1 + #else + #define EA_WCHAR_SIZE 4 + #endif + #elif defined(WCHAR_MAX) // The SN and Arm compilers define this. + #if (WCHAR_MAX == 2147483647) || (WCHAR_MAX == 4294967295) + #define EA_WCHAR_SIZE 4 + #elif (WCHAR_MAX == 32767) || (WCHAR_MAX == 65535) + #define EA_WCHAR_SIZE 2 + #elif (WCHAR_MAX == 127) || (WCHAR_MAX == 255) + #define EA_WCHAR_SIZE 1 + #else + #define EA_WCHAR_SIZE 4 + #endif + #elif defined(__WCHAR_BIT) // Green Hills (and other versions of EDG?) uses this. + #if (__WCHAR_BIT == 16) + #define EA_WCHAR_SIZE 2 + #elif (__WCHAR_BIT == 32) + #define EA_WCHAR_SIZE 4 + #elif (__WCHAR_BIT == 8) + #define EA_WCHAR_SIZE 1 + #else + #define EA_WCHAR_SIZE 4 + #endif + #elif defined(_WCMAX) // The SN and Arm compilers define this. + #if (_WCMAX == 2147483647) || (_WCMAX == 4294967295) + #define EA_WCHAR_SIZE 4 + #elif (_WCMAX == 32767) || (_WCMAX == 65535) + #define EA_WCHAR_SIZE 2 + #elif (_WCMAX == 127) || (_WCMAX == 255) + #define EA_WCHAR_SIZE 1 + #else + #define EA_WCHAR_SIZE 4 + #endif + #elif defined(EA_PLATFORM_UNIX) + // It is standard on Unix to have wchar_t be int32_t or uint32_t. + // All versions of GNUC default to a 32 bit wchar_t, but EA has used + // the -fshort-wchar GCC command line option to force it to 16 bit. + // If you know that the compiler is set to use a wchar_t of other than + // the default, you need to manually define EA_WCHAR_SIZE for the build. + #define EA_WCHAR_SIZE 4 + #else + // It is standard on Windows to have wchar_t be uint16_t. GCC + // defines wchar_t as int by default. Electronic Arts has + // standardized on wchar_t being an unsigned 16 bit value on all + // console platforms. Given that there is currently no known way to + // tell at preprocessor time what the size of wchar_t is, we declare + // it to be 2, as this is the Electronic Arts standard. If you have + // EA_WCHAR_SIZE != sizeof(wchar_t), then your code might not be + // broken, but it also won't work with wchar libraries and data from + // other parts of EA. Under GCC, you can force wchar_t to two bytes + // with the -fshort-wchar compiler argument. + #define EA_WCHAR_SIZE 2 + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_RESTRICT + // + // The C99 standard defines a new keyword, restrict, which allows for the + // improvement of code generation regarding memory usage. Compilers can + // generate significantly faster code when you are able to use restrict. + // + // Example usage: + // void DoSomething(char* EA_RESTRICT p1, char* EA_RESTRICT p2); + // + #ifndef EA_RESTRICT + #if defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1400) // If VC8 (VS2005) or later... + #define EA_RESTRICT __restrict + #elif defined(EA_COMPILER_CLANG) + #define EA_RESTRICT __restrict + #elif defined(EA_COMPILER_GNUC) // Includes GCC and other compilers emulating GCC. + #define EA_RESTRICT __restrict // GCC defines 'restrict' (as opposed to __restrict) in C99 mode only. + #elif defined(EA_COMPILER_ARM) + #define EA_RESTRICT __restrict + #elif defined(EA_COMPILER_IS_C99) + #define EA_RESTRICT restrict + #else + // If the compiler didn't support restricted pointers, defining EA_RESTRICT + // away would result in compiling and running fine but you just wouldn't + // the same level of optimization. On the other hand, all the major compilers + // support restricted pointers. + #define EA_RESTRICT + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_DEPRECATED // Used as a prefix. + // EA_PREFIX_DEPRECATED // You should need this only for unusual compilers. + // EA_POSTFIX_DEPRECATED // You should need this only for unusual compilers. + // EA_DEPRECATED_MESSAGE // Used as a prefix and provides a deprecation message. + // + // Example usage: + // EA_DEPRECATED void Function(); + // EA_DEPRECATED_MESSAGE("Use 1.0v API instead") void Function(); + // + // or for maximum portability: + // EA_PREFIX_DEPRECATED void Function() EA_POSTFIX_DEPRECATED; + // + + #ifndef EA_DEPRECATED + #if defined(EA_COMPILER_CPP14_ENABLED) + #define EA_DEPRECATED [[deprecated]] + #elif defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION > 1300) // If VC7 (VS2003) or later... + #define EA_DEPRECATED __declspec(deprecated) + #elif defined(EA_COMPILER_MSVC) + #define EA_DEPRECATED + #else + #define EA_DEPRECATED __attribute__((deprecated)) + #endif + #endif + + #ifndef EA_PREFIX_DEPRECATED + #if defined(EA_COMPILER_CPP14_ENABLED) + #define EA_PREFIX_DEPRECATED [[deprecated]] + #define EA_POSTFIX_DEPRECATED + #elif defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION > 1300) // If VC7 (VS2003) or later... + #define EA_PREFIX_DEPRECATED __declspec(deprecated) + #define EA_POSTFIX_DEPRECATED + #elif defined(EA_COMPILER_MSVC) + #define EA_PREFIX_DEPRECATED + #define EA_POSTFIX_DEPRECATED + #else + #define EA_PREFIX_DEPRECATED + #define EA_POSTFIX_DEPRECATED __attribute__((deprecated)) + #endif + #endif + + #ifndef EA_DEPRECATED_MESSAGE + #if defined(EA_COMPILER_CPP14_ENABLED) + #define EA_DEPRECATED_MESSAGE(msg) [[deprecated(#msg)]] + #else + // Compiler does not support depreaction messages, explicitly drop the msg but still mark the function as deprecated + #define EA_DEPRECATED_MESSAGE(msg) EA_DEPRECATED + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_FORCE_INLINE // Used as a prefix. + // EA_PREFIX_FORCE_INLINE // You should need this only for unusual compilers. + // EA_POSTFIX_FORCE_INLINE // You should need this only for unusual compilers. + // + // Example usage: + // EA_FORCE_INLINE void Foo(); // Implementation elsewhere. + // EA_PREFIX_FORCE_INLINE void Foo() EA_POSTFIX_FORCE_INLINE; // Implementation elsewhere. + // + // Note that when the prefix version of this function is used, it replaces + // the regular C++ 'inline' statement. Thus you should not use both the + // C++ inline statement and this macro with the same function declaration. + // + // To force inline usage under GCC 3.1+, you use this: + // inline void Foo() __attribute__((always_inline)); + // or + // inline __attribute__((always_inline)) void Foo(); + // + // The CodeWarrior compiler doesn't have the concept of forcing inlining per function. + // + #ifndef EA_FORCE_INLINE + #if defined(EA_COMPILER_MSVC) + #define EA_FORCE_INLINE __forceinline + #elif defined(EA_COMPILER_GNUC) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 301) || defined(EA_COMPILER_CLANG) + #if defined(__cplusplus) + #define EA_FORCE_INLINE inline __attribute__((always_inline)) + #else + #define EA_FORCE_INLINE __inline__ __attribute__((always_inline)) + #endif + #else + #if defined(__cplusplus) + #define EA_FORCE_INLINE inline + #else + #define EA_FORCE_INLINE __inline + #endif + #endif + #endif + + #if defined(EA_COMPILER_GNUC) && (((__GNUC__ * 100) + __GNUC_MINOR__) >= 301) || defined(EA_COMPILER_CLANG) + #define EA_PREFIX_FORCE_INLINE inline + #define EA_POSTFIX_FORCE_INLINE __attribute__((always_inline)) + #else + #define EA_PREFIX_FORCE_INLINE inline + #define EA_POSTFIX_FORCE_INLINE + #endif + + + // ------------------------------------------------------------------------ + // EA_FORCE_INLINE_LAMBDA + // + // EA_FORCE_INLINE_LAMBDA is used to force inline a call to a lambda when possible. + // Force inlining a lambda can be useful to reduce overhead in situations where a lambda may + // may only be called once, or inlining allows the compiler to apply other optimizations that wouldn't + // otherwise be possible. + // + // The ability to force inline a lambda is currently only available on a subset of compilers. + // + // Example usage: + // + // auto lambdaFunction = []() EA_FORCE_INLINE_LAMBDA + // { + // }; + // + #ifndef EA_FORCE_INLINE_LAMBDA + #if defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG) + #define EA_FORCE_INLINE_LAMBDA __attribute__((always_inline)) + #else + #define EA_FORCE_INLINE_LAMBDA + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_NO_INLINE // Used as a prefix. + // EA_PREFIX_NO_INLINE // You should need this only for unusual compilers. + // EA_POSTFIX_NO_INLINE // You should need this only for unusual compilers. + // + // Example usage: + // EA_NO_INLINE void Foo(); // Implementation elsewhere. + // EA_PREFIX_NO_INLINE void Foo() EA_POSTFIX_NO_INLINE; // Implementation elsewhere. + // + // That this declaration is incompatbile with C++ 'inline' and any + // variant of EA_FORCE_INLINE. + // + // To disable inline usage under VC++ priof to VS2005, you need to use this: + // #pragma inline_depth(0) // Disable inlining. + // void Foo() { ... } + // #pragma inline_depth() // Restore to default. + // + // Since there is no easy way to disable inlining on a function-by-function + // basis in VC++ prior to VS2005, the best strategy is to write platform-specific + // #ifdefs in the code or to disable inlining for a given module and enable + // functions individually with EA_FORCE_INLINE. + // + #ifndef EA_NO_INLINE + #if defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1400) // If VC8 (VS2005) or later... + #define EA_NO_INLINE __declspec(noinline) + #elif defined(EA_COMPILER_MSVC) + #define EA_NO_INLINE + #else + #define EA_NO_INLINE __attribute__((noinline)) + #endif + #endif + + #if defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1400) // If VC8 (VS2005) or later... + #define EA_PREFIX_NO_INLINE __declspec(noinline) + #define EA_POSTFIX_NO_INLINE + #elif defined(EA_COMPILER_MSVC) + #define EA_PREFIX_NO_INLINE + #define EA_POSTFIX_NO_INLINE + #else + #define EA_PREFIX_NO_INLINE + #define EA_POSTFIX_NO_INLINE __attribute__((noinline)) + #endif + + + // ------------------------------------------------------------------------ + // EA_NO_VTABLE + // + // Example usage: + // class EA_NO_VTABLE X { + // virtual void InterfaceFunction(); + // }; + // + // EA_CLASS_NO_VTABLE(X) { + // virtual void InterfaceFunction(); + // }; + // + #ifdef EA_COMPILER_MSVC + #define EA_NO_VTABLE __declspec(novtable) + #define EA_CLASS_NO_VTABLE(x) class __declspec(novtable) x + #define EA_STRUCT_NO_VTABLE(x) struct __declspec(novtable) x + #else + #define EA_NO_VTABLE + #define EA_CLASS_NO_VTABLE(x) class x + #define EA_STRUCT_NO_VTABLE(x) struct x + #endif + + + // ------------------------------------------------------------------------ + // EA_PASCAL + // + // Also known on PC platforms as stdcall. + // This convention causes the compiler to assume that the called function + // will pop off the stack space used to pass arguments, unless it takes a + // variable number of arguments. + // + // Example usage: + // this: + // void DoNothing(int x); + // void DoNothing(int x){} + // would be written as this: + // void EA_PASCAL_FUNC(DoNothing(int x)); + // void EA_PASCAL_FUNC(DoNothing(int x)){} + // + #ifndef EA_PASCAL + #if defined(EA_COMPILER_MSVC) + #define EA_PASCAL __stdcall + #elif defined(EA_COMPILER_GNUC) && defined(EA_PROCESSOR_X86) + #define EA_PASCAL __attribute__((stdcall)) + #else + // Some compilers simply don't support pascal calling convention. + // As a result, there isn't an issue here, since the specification of + // pascal calling convention is for the purpose of disambiguating the + // calling convention that is applied. + #define EA_PASCAL + #endif + #endif + + #ifndef EA_PASCAL_FUNC + #if defined(EA_COMPILER_MSVC) + #define EA_PASCAL_FUNC(funcname_and_paramlist) __stdcall funcname_and_paramlist + #elif defined(EA_COMPILER_GNUC) && defined(EA_PROCESSOR_X86) + #define EA_PASCAL_FUNC(funcname_and_paramlist) __attribute__((stdcall)) funcname_and_paramlist + #else + #define EA_PASCAL_FUNC(funcname_and_paramlist) funcname_and_paramlist + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_SSE + // Visual C Processor Packs define _MSC_FULL_VER and are needed for SSE + // Intel C also has SSE support. + // EA_SSE is used to select FPU or SSE versions in hw_select.inl + // + // EA_SSE defines the level of SSE support: + // 0 indicates no SSE support + // 1 indicates SSE1 is supported + // 2 indicates SSE2 is supported + // 3 indicates SSE3 (or greater) is supported + // + // Note: SSE support beyond SSE3 can't be properly represented as a single + // version number. Instead users should use specific SSE defines (e.g. + // EA_SSE4_2) to detect what specific support is available. EA_SSE being + // equal to 3 really only indicates that SSE3 or greater is supported. + #ifndef EA_SSE + #if defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG) + #if defined(__SSE3__) + #define EA_SSE 3 + #elif defined(__SSE2__) + #define EA_SSE 2 + #elif defined(__SSE__) && __SSE__ + #define EA_SSE 1 + #else + #define EA_SSE 0 + #endif + #elif (defined(EA_SSE3) && EA_SSE3) || defined EA_PLATFORM_XBOXONE || defined CS_UNDEFINED_STRING + #define EA_SSE 3 + #elif defined(EA_SSE2) && EA_SSE2 + #define EA_SSE 2 + #elif defined(EA_PROCESSOR_X86) && defined(_MSC_FULL_VER) && !defined(__NOSSE__) && defined(_M_IX86_FP) + #define EA_SSE _M_IX86_FP + #elif defined(EA_PROCESSOR_X86) && defined(EA_COMPILER_INTEL) && !defined(__NOSSE__) + #define EA_SSE 1 + #elif defined(EA_PROCESSOR_X86_64) + // All x64 processors support SSE2 or higher + #define EA_SSE 2 + #else + #define EA_SSE 0 + #endif + #endif + + // ------------------------------------------------------------------------ + // We define separate defines for SSE support beyond SSE1. These defines + // are particularly useful for detecting SSE4.x features since there isn't + // a single concept of SSE4. + // + // The following SSE defines are always defined. 0 indicates the + // feature/level of SSE is not supported, and 1 indicates support is + // available. + #ifndef EA_SSE2 + #if EA_SSE >= 2 + #define EA_SSE2 1 + #else + #define EA_SSE2 0 + #endif + #endif + #ifndef EA_SSE3 + #if EA_SSE >= 3 + #define EA_SSE3 1 + #else + #define EA_SSE3 0 + #endif + #endif + #ifndef EA_SSSE3 + #if defined __SSSE3__ || defined EA_PLATFORM_XBOXONE || defined CS_UNDEFINED_STRING + #define EA_SSSE3 1 + #else + #define EA_SSSE3 0 + #endif + #endif + #ifndef EA_SSE4_1 + #if defined __SSE4_1__ || defined EA_PLATFORM_XBOXONE || defined CS_UNDEFINED_STRING + #define EA_SSE4_1 1 + #else + #define EA_SSE4_1 0 + #endif + #endif + #ifndef EA_SSE4_2 + #if defined __SSE4_2__ || defined EA_PLATFORM_XBOXONE || defined CS_UNDEFINED_STRING + #define EA_SSE4_2 1 + #else + #define EA_SSE4_2 0 + #endif + #endif + #ifndef EA_SSE4A + #if defined __SSE4A__ || defined EA_PLATFORM_XBOXONE || defined CS_UNDEFINED_STRING + #define EA_SSE4A 1 + #else + #define EA_SSE4A 0 + #endif + #endif + + // ------------------------------------------------------------------------ + // EA_AVX + // EA_AVX may be used to determine if Advanced Vector Extensions are available for the target architecture + // + // EA_AVX defines the level of AVX support: + // 0 indicates no AVX support + // 1 indicates AVX1 is supported + // 2 indicates AVX2 is supported + #ifndef EA_AVX + #if defined __AVX2__ + #define EA_AVX 2 + #elif defined __AVX__ || defined EA_PLATFORM_XBOXONE || defined CS_UNDEFINED_STRING + #define EA_AVX 1 + #else + #define EA_AVX 0 + #endif + #endif + #ifndef EA_AVX2 + #if EA_AVX >= 2 + #define EA_AVX2 1 + #else + #define EA_AVX2 0 + #endif + #endif + + // EA_FP16C may be used to determine the existence of float <-> half conversion operations on an x86 CPU. + // (For example to determine if _mm_cvtph_ps or _mm_cvtps_ph could be used.) + #ifndef EA_FP16C + #if defined __F16C__ || defined EA_PLATFORM_XBOXONE || defined CS_UNDEFINED_STRING + #define EA_FP16C 1 + #else + #define EA_FP16C 0 + #endif + #endif + + // EA_FP128 may be used to determine if __float128 is a supported type for use. This type is enabled by a GCC extension (_GLIBCXX_USE_FLOAT128) + // but has support by some implementations of clang (__FLOAT128__) + // PS4 does not support __float128 as of SDK 5.500 https://ps4.siedev.net/resources/documents/SDK/5.500/CPU_Compiler_ABI-Overview/0003.html + #ifndef EA_FP128 + #if (defined __FLOAT128__ || defined _GLIBCXX_USE_FLOAT128) && !defined(EA_PLATFORM_SONY) + #define EA_FP128 1 + #else + #define EA_FP128 0 + #endif + #endif + + // ------------------------------------------------------------------------ + // EA_ABM + // EA_ABM may be used to determine if Advanced Bit Manipulation sets are available for the target architecture (POPCNT, LZCNT) + // + #ifndef EA_ABM + #if defined(__ABM__) || defined(EA_PLATFORM_XBOXONE) || defined(EA_PLATFORM_SONY) || defined(CS_UNDEFINED_STRING) + #define EA_ABM 1 + #else + #define EA_ABM 0 + #endif + #endif + + // ------------------------------------------------------------------------ + // EA_NEON + // EA_NEON may be used to determine if NEON is supported. + #ifndef EA_NEON + #if defined(__ARM_NEON__) || defined(__ARM_NEON) + #define EA_NEON 1 + #else + #define EA_NEON 0 + #endif + #endif + + // ------------------------------------------------------------------------ + // EA_BMI + // EA_BMI may be used to determine if Bit Manipulation Instruction sets are available for the target architecture + // + // EA_BMI defines the level of BMI support: + // 0 indicates no BMI support + // 1 indicates BMI1 is supported + // 2 indicates BMI2 is supported + #ifndef EA_BMI + #if defined(__BMI2__) + #define EA_BMI 2 + #elif defined(__BMI__) || defined(EA_PLATFORM_XBOXONE) || defined(CS_UNDEFINED_STRING) + #define EA_BMI 1 + #else + #define EA_BMI 0 + #endif + #endif + #ifndef EA_BMI2 + #if EA_BMI >= 2 + #define EA_BMI2 1 + #else + #define EA_BMI2 0 + #endif + #endif + + // ------------------------------------------------------------------------ + // EA_FMA3 + // EA_FMA3 may be used to determine if Fused Multiply Add operations are available for the target architecture + // __FMA__ is defined only by GCC, Clang, and ICC; MSVC only defines __AVX__ and __AVX2__ + // FMA3 was introduced alongside AVX2 on Intel Haswell + // All AMD processors support FMA3 if AVX2 is also supported + // + // EA_FMA3 defines the level of FMA3 support: + // 0 indicates no FMA3 support + // 1 indicates FMA3 is supported + #ifndef EA_FMA3 + #if defined(__FMA__) || EA_AVX2 >= 1 + #define EA_FMA3 1 + #else + #define EA_FMA3 0 + #endif + #endif + + // ------------------------------------------------------------------------ + // EA_TBM + // EA_TBM may be used to determine if Trailing Bit Manipulation instructions are available for the target architecture + #ifndef EA_TBM + #if defined(__TBM__) + #define EA_TBM 1 + #else + #define EA_TBM 0 + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_IMPORT + // import declaration specification + // specifies that the declared symbol is imported from another dynamic library. + #ifndef EA_IMPORT + #if defined(EA_COMPILER_MSVC) + #define EA_IMPORT __declspec(dllimport) + #else + #define EA_IMPORT + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_EXPORT + // export declaration specification + // specifies that the declared symbol is exported from the current dynamic library. + // this is not the same as the C++ export keyword. The C++ export keyword has been + // removed from the language as of C++11. + #ifndef EA_EXPORT + #if defined(EA_COMPILER_MSVC) + #define EA_EXPORT __declspec(dllexport) + #else + #define EA_EXPORT + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_PRAGMA_ONCE_SUPPORTED + // + // This is a wrapper for the #pragma once preprocessor directive. + // It allows for some compilers (in particular VC++) to implement signifcantly + // faster include file preprocessing. #pragma once can be used to replace + // header include guards or to augment them. However, #pragma once isn't + // necessarily supported by all compilers and isn't guaranteed to be so in + // the future, so using #pragma once to replace traditional include guards + // is not strictly portable. Note that a direct #define for #pragma once is + // impossible with VC++, due to limitations, but can be done with other + // compilers/preprocessors via _Pragma("once"). + // + // Example usage (which includes traditional header guards for portability): + // #ifndef SOMEPACKAGE_SOMEHEADER_H + // #define SOMEPACKAGE_SOMEHEADER_H + // + // #if defined(EA_PRAGMA_ONCE_SUPPORTED) + // #pragma once + // #endif + // + // <user code> + // + // #endif + // + #if defined(_MSC_VER) || defined(__GNUC__) || defined(__EDG__) || defined(__APPLE__) + #define EA_PRAGMA_ONCE_SUPPORTED 1 + #endif + + + + // ------------------------------------------------------------------------ + // EA_ONCE + // + // Example usage (which includes traditional header guards for portability): + // #ifndef SOMEPACKAGE_SOMEHEADER_H + // #define SOMEPACKAGE_SOMEHEADER_H + // + // EA_ONCE() + // + // <user code> + // + // #endif + // + #if defined(EA_PRAGMA_ONCE_SUPPORTED) + #if defined(_MSC_VER) + #define EA_ONCE() __pragma(once) + #else + #define EA_ONCE() // _Pragma("once") It turns out that _Pragma("once") isn't supported by many compilers. + #endif + #endif + + + + // ------------------------------------------------------------------------ + // EA_OVERRIDE + // + // C++11 override + // See http://msdn.microsoft.com/en-us/library/jj678987.aspx for more information. + // You can use EA_FINAL_OVERRIDE to combine usage of EA_OVERRIDE and EA_INHERITANCE_FINAL in a single statement. + // + // Example usage: + // struct B { virtual void f(int); }; + // struct D : B { void f(int) EA_OVERRIDE; }; + // + #ifndef EA_OVERRIDE + #if defined(EA_COMPILER_NO_OVERRIDE) + #define EA_OVERRIDE + #else + #define EA_OVERRIDE override + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_INHERITANCE_FINAL + // + // Portably wraps the C++11 final specifier. + // See http://msdn.microsoft.com/en-us/library/jj678985.aspx for more information. + // You can use EA_FINAL_OVERRIDE to combine usage of EA_OVERRIDE and EA_INHERITANCE_FINAL in a single statement. + // This is not called EA_FINAL because that term is used within EA to denote debug/release/final builds. + // + // Example usage: + // struct B { virtual void f() EA_INHERITANCE_FINAL; }; + // + #ifndef EA_INHERITANCE_FINAL + #if defined(EA_COMPILER_NO_INHERITANCE_FINAL) + #define EA_INHERITANCE_FINAL + #elif (defined(_MSC_VER) && (EA_COMPILER_VERSION < 1700)) // Pre-VS2012 + #define EA_INHERITANCE_FINAL sealed + #else + #define EA_INHERITANCE_FINAL final + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_FINAL_OVERRIDE + // + // Portably wraps the C++11 override final specifiers combined. + // + // Example usage: + // struct A { virtual void f(); }; + // struct B : public A { virtual void f() EA_FINAL_OVERRIDE; }; + // + #ifndef EA_FINAL_OVERRIDE + #define EA_FINAL_OVERRIDE EA_OVERRIDE EA_INHERITANCE_FINAL + #endif + + + // ------------------------------------------------------------------------ + // EA_SEALED + // + // This is deprecated, as the C++11 Standard has final (EA_INHERITANCE_FINAL) instead. + // See http://msdn.microsoft.com/en-us/library/0w2w91tf.aspx for more information. + // Example usage: + // struct B { virtual void f() EA_SEALED; }; + // + #ifndef EA_SEALED + #if defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1400) // VS2005 (VC8) and later + #define EA_SEALED sealed + #else + #define EA_SEALED + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_ABSTRACT + // + // This is a Microsoft language extension. + // See http://msdn.microsoft.com/en-us/library/b0z6b513.aspx for more information. + // Example usage: + // struct X EA_ABSTRACT { virtual void f(){} }; + // + #ifndef EA_ABSTRACT + #if defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1400) // VS2005 (VC8) and later + #define EA_ABSTRACT abstract + #else + #define EA_ABSTRACT + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_CONSTEXPR + // EA_CONSTEXPR_OR_CONST + // + // Portable wrapper for C++11's 'constexpr' support. + // + // See http://www.cprogramming.com/c++11/c++11-compile-time-processing-with-constexpr.html for more information. + // Example usage: + // EA_CONSTEXPR int GetValue() { return 37; } + // EA_CONSTEXPR_OR_CONST double gValue = std::sin(kTwoPi); + // + #if !defined(EA_CONSTEXPR) + #if defined(EA_COMPILER_NO_CONSTEXPR) + #define EA_CONSTEXPR + #else + #define EA_CONSTEXPR constexpr + #endif + #endif + + #if !defined(EA_CONSTEXPR_OR_CONST) + #if defined(EA_COMPILER_NO_CONSTEXPR) + #define EA_CONSTEXPR_OR_CONST const + #else + #define EA_CONSTEXPR_OR_CONST constexpr + #endif + #endif + + // ------------------------------------------------------------------------ + // EA_CONSTEXPR_IF + // + // Portable wrapper for C++17's 'constexpr if' support. + // + // https://en.cppreference.com/w/cpp/language/if + // + // Example usage: + // + // EA_CONSTEXPR_IF(eastl::is_copy_constructible_v<T>) + // { ... } + // + #if !defined(EA_CONSTEXPR_IF) + #if defined(EA_COMPILER_NO_CONSTEXPR_IF) + #define EA_CONSTEXPR_IF(predicate) if ((predicate)) + #else + #define EA_CONSTEXPR_IF(predicate) if constexpr ((predicate)) + #endif + #endif + + + + // ------------------------------------------------------------------------ + // EA_EXTERN_TEMPLATE + // + // Portable wrapper for C++11's 'extern template' support. + // + // Example usage: + // EA_EXTERN_TEMPLATE(class basic_string<char>); + // + #if !defined(EA_EXTERN_TEMPLATE) + #if defined(EA_COMPILER_NO_EXTERN_TEMPLATE) + #define EA_EXTERN_TEMPLATE(declaration) + #else + #define EA_EXTERN_TEMPLATE(declaration) extern template declaration + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_NOEXCEPT + // EA_NOEXCEPT_IF(predicate) + // EA_NOEXCEPT_EXPR(expression) + // + // Portable wrapper for C++11 noexcept + // http://en.cppreference.com/w/cpp/language/noexcept + // http://en.cppreference.com/w/cpp/language/noexcept_spec + // + // Example usage: + // EA_NOEXCEPT + // EA_NOEXCEPT_IF(predicate) + // EA_NOEXCEPT_EXPR(expression) + // + // This function never throws an exception. + // void DoNothing() EA_NOEXCEPT + // { } + // + // This function throws an exception of T::T() throws an exception. + // template <class T> + // void DoNothing() EA_NOEXCEPT_IF(EA_NOEXCEPT_EXPR(T())) + // { T t; } + // + #if !defined(EA_NOEXCEPT) + #if defined(EA_COMPILER_NO_NOEXCEPT) + #define EA_NOEXCEPT + #define EA_NOEXCEPT_IF(predicate) + #define EA_NOEXCEPT_EXPR(expression) false + #else + #define EA_NOEXCEPT noexcept + #define EA_NOEXCEPT_IF(predicate) noexcept((predicate)) + #define EA_NOEXCEPT_EXPR(expression) noexcept((expression)) + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_NORETURN + // + // Wraps the C++11 noreturn attribute. See EA_COMPILER_NO_NORETURN + // http://en.cppreference.com/w/cpp/language/attributes + // http://msdn.microsoft.com/en-us/library/k6ktzx3s%28v=vs.80%29.aspx + // http://blog.aaronballman.com/2011/09/understanding-attributes/ + // + // Example usage: + // EA_NORETURN void SomeFunction() + // { throw "error"; } + // + #if !defined(EA_NORETURN) + #if defined(EA_COMPILER_MSVC) && (EA_COMPILER_VERSION >= 1300) // VS2003 (VC7) and later + #define EA_NORETURN __declspec(noreturn) + #elif defined(EA_COMPILER_NO_NORETURN) + #define EA_NORETURN + #else + #define EA_NORETURN [[noreturn]] + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_CARRIES_DEPENDENCY + // + // Wraps the C++11 carries_dependency attribute + // http://en.cppreference.com/w/cpp/language/attributes + // http://blog.aaronballman.com/2011/09/understanding-attributes/ + // + // Example usage: + // EA_CARRIES_DEPENDENCY int* SomeFunction() + // { return &mX; } + // + // + #if !defined(EA_CARRIES_DEPENDENCY) + #if defined(EA_COMPILER_NO_CARRIES_DEPENDENCY) + #define EA_CARRIES_DEPENDENCY + #else + #define EA_CARRIES_DEPENDENCY [[carries_dependency]] + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_FALLTHROUGH + // + // [[fallthrough] is a C++17 standard attribute that appears in switch + // statements to indicate that the fallthrough from the previous case in the + // switch statement is intentially and not a bug. + // + // http://en.cppreference.com/w/cpp/language/attributes + // + // Example usage: + // void f(int n) + // { + // switch(n) + // { + // case 1: + // DoCase1(); + // // Compiler may generate a warning for fallthrough behaviour + // + // case 2: + // DoCase2(); + // + // EA_FALLTHROUGH; + // case 3: + // DoCase3(); + // } + // } + // + #if !defined(EA_FALLTHROUGH) + #if defined(EA_COMPILER_NO_FALLTHROUGH) + #define EA_FALLTHROUGH + #else + #define EA_FALLTHROUGH [[fallthrough]] + #endif + #endif + + + + // ------------------------------------------------------------------------ + // EA_NODISCARD + // + // [[nodiscard]] is a C++17 standard attribute that can be applied to a + // function declaration, enum, or class declaration. If a any of the list + // previously are returned from a function (without the user explicitly + // casting to void) the addition of the [[nodiscard]] attribute encourages + // the compiler to generate a warning about the user discarding the return + // value. This is a useful practice to encourage client code to check API + // error codes. + // + // http://en.cppreference.com/w/cpp/language/attributes + // + // Example usage: + // + // EA_NODISCARD int baz() { return 42; } + // + // void foo() + // { + // baz(); // warning: ignoring return value of function declared with 'nodiscard' attribute + // } + // + #if !defined(EA_NODISCARD) + #if defined(EA_COMPILER_NO_NODISCARD) + #define EA_NODISCARD + #else + #define EA_NODISCARD [[nodiscard]] + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_MAYBE_UNUSED + // + // [[maybe_unused]] is a C++17 standard attribute that suppresses warnings + // on unused entities that are declared as maybe_unused. + // + // http://en.cppreference.com/w/cpp/language/attributes + // + // Example usage: + // void foo(EA_MAYBE_UNUSED int i) + // { + // assert(i == 42); // warning suppressed when asserts disabled. + // } + // + #if !defined(EA_MAYBE_UNUSED) + #if defined(EA_COMPILER_NO_MAYBE_UNUSED) + #define EA_MAYBE_UNUSED + #else + #define EA_MAYBE_UNUSED [[maybe_unused]] + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_NO_UBSAN + // + // The LLVM/Clang undefined behaviour sanitizer will not analyse a function tagged with the following attribute. + // + // https://clang.llvm.org/docs/UndefinedBehaviorSanitizer.html#disabling-instrumentation-with-attribute-no-sanitize-undefined + // + // Example usage: + // EA_NO_UBSAN int SomeFunction() { ... } + // + #ifndef EA_NO_UBSAN + #if defined(EA_COMPILER_CLANG) + #define EA_NO_UBSAN __attribute__((no_sanitize("undefined"))) + #else + #define EA_NO_UBSAN + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_NO_ASAN + // + // The LLVM/Clang address sanitizer will not analyse a function tagged with the following attribute. + // + // https://clang.llvm.org/docs/AddressSanitizer.html#disabling-instrumentation-with-attribute-no-sanitize-address + // + // Example usage: + // EA_NO_ASAN int SomeFunction() { ... } + // + #ifndef EA_NO_ASAN + #if defined(EA_COMPILER_CLANG) + #define EA_NO_ASAN __attribute__((no_sanitize("address"))) + #else + #define EA_NO_ASAN + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_ASAN_ENABLED + // + // Defined as 0 or 1. It's value depends on the compile environment. + // Specifies whether the code is being built with Clang's Address Sanitizer. + // + #if defined(__has_feature) + #if __has_feature(address_sanitizer) + #define EA_ASAN_ENABLED 1 + #else + #define EA_ASAN_ENABLED 0 + #endif + #else + #define EA_ASAN_ENABLED 0 + #endif + + + // ------------------------------------------------------------------------ + // EA_NON_COPYABLE + // + // This macro defines as a class as not being copy-constructable + // or assignable. This is useful for preventing class instances + // from being passed to functions by value, is useful for preventing + // compiler warnings by some compilers about the inability to + // auto-generate a copy constructor and assignment, and is useful + // for simply declaring in the interface that copy semantics are + // not supported by the class. Your class needs to have at least a + // default constructor when using this macro. + // + // Beware that this class works by declaring a private: section of + // the class in the case of compilers that don't support C++11 deleted + // functions. + // + // Note: With some pre-C++11 compilers (e.g. Green Hills), you may need + // to manually define an instances of the hidden functions, even + // though they are not used. + // + // Example usage: + // class Widget { + // Widget(); + // . . . + // EA_NON_COPYABLE(Widget) + // }; + // + #if !defined(EA_NON_COPYABLE) + #if defined(EA_COMPILER_NO_DELETED_FUNCTIONS) + #define EA_NON_COPYABLE(EAClass_) \ + private: \ + EA_DISABLE_VC_WARNING(4822); /* local class member function does not have a body */ \ + EAClass_(const EAClass_&); \ + void operator=(const EAClass_&); \ + EA_RESTORE_VC_WARNING(); + #else + #define EA_NON_COPYABLE(EAClass_) \ + EA_DISABLE_VC_WARNING(4822); /* local class member function does not have a body */ \ + EAClass_(const EAClass_&) = delete; \ + void operator=(const EAClass_&) = delete; \ + EA_RESTORE_VC_WARNING(); + #endif + #endif + + + // ------------------------------------------------------------------------ + // EA_FUNCTION_DELETE + // + // Semi-portable way of specifying a deleted function which allows for + // cleaner code in class declarations. + // + // Example usage: + // + // class Example + // { + // private: // For portability with pre-C++11 compilers, make the function private. + // void foo() EA_FUNCTION_DELETE; + // }; + // + // Note: EA_FUNCTION_DELETE'd functions should be private to prevent the + // functions from being called even when the compiler does not support + // deleted functions. Some compilers (e.g. Green Hills) that don't support + // C++11 deleted functions can require that you define the function, + // which you can do in the associated source file for the class. + // + #if defined(EA_COMPILER_NO_DELETED_FUNCTIONS) + #define EA_FUNCTION_DELETE + #else + #define EA_FUNCTION_DELETE = delete + #endif + + // ------------------------------------------------------------------------ + // EA_DISABLE_DEFAULT_CTOR + // + // Disables the compiler generated default constructor. This macro is + // provided to improve portability and clarify intent of code. + // + // Example usage: + // + // class Example + // { + // private: + // EA_DISABLE_DEFAULT_CTOR(Example); + // }; + // + #define EA_DISABLE_DEFAULT_CTOR(ClassName) ClassName() EA_FUNCTION_DELETE + + // ------------------------------------------------------------------------ + // EA_DISABLE_COPY_CTOR + // + // Disables the compiler generated copy constructor. This macro is + // provided to improve portability and clarify intent of code. + // + // Example usage: + // + // class Example + // { + // private: + // EA_DISABLE_COPY_CTOR(Example); + // }; + // + #define EA_DISABLE_COPY_CTOR(ClassName) ClassName(const ClassName &) EA_FUNCTION_DELETE + + // ------------------------------------------------------------------------ + // EA_DISABLE_MOVE_CTOR + // + // Disables the compiler generated move constructor. This macro is + // provided to improve portability and clarify intent of code. + // + // Example usage: + // + // class Example + // { + // private: + // EA_DISABLE_MOVE_CTOR(Example); + // }; + // + #define EA_DISABLE_MOVE_CTOR(ClassName) ClassName(ClassName&&) EA_FUNCTION_DELETE + + // ------------------------------------------------------------------------ + // EA_DISABLE_ASSIGNMENT_OPERATOR + // + // Disables the compiler generated assignment operator. This macro is + // provided to improve portability and clarify intent of code. + // + // Example usage: + // + // class Example + // { + // private: + // EA_DISABLE_ASSIGNMENT_OPERATOR(Example); + // }; + // + #define EA_DISABLE_ASSIGNMENT_OPERATOR(ClassName) ClassName & operator=(const ClassName &) EA_FUNCTION_DELETE + + // ------------------------------------------------------------------------ + // EA_DISABLE_MOVE_OPERATOR + // + // Disables the compiler generated move operator. This macro is + // provided to improve portability and clarify intent of code. + // + // Example usage: + // + // class Example + // { + // private: + // EA_DISABLE_MOVE_OPERATOR(Example); + // }; + // + #define EA_DISABLE_MOVE_OPERATOR(ClassName) ClassName & operator=(ClassName&&) EA_FUNCTION_DELETE + + // ------------------------------------------------------------------------ + // EANonCopyable + // + // Declares a class as not supporting copy construction or assignment. + // May be more reliable with some situations that EA_NON_COPYABLE alone, + // though it may result in more code generation. + // + // Note that VC++ will generate warning C4625 and C4626 if you use EANonCopyable + // and you are compiling with /W4 and /Wall. There is no resolution but + // to redelare EA_NON_COPYABLE in your subclass or disable the warnings with + // code like this: + // EA_DISABLE_VC_WARNING(4625 4626) + // ... + // EA_RESTORE_VC_WARNING() + // + // Example usage: + // struct Widget : EANonCopyable { + // . . . + // }; + // + #ifdef __cplusplus + struct EANonCopyable + { + #if defined(EA_COMPILER_NO_DEFAULTED_FUNCTIONS) || defined(__EDG__) + // EDG doesn't appear to behave properly for the case of defaulted constructors; + // it generates a mistaken warning about missing default constructors. + EANonCopyable() {} // Putting {} here has the downside that it allows a class to create itself, + ~EANonCopyable() {} // but avoids linker errors that can occur with some compilers (e.g. Green Hills). + #else + EANonCopyable() = default; + ~EANonCopyable() = default; + #endif + + EA_NON_COPYABLE(EANonCopyable) + }; + #endif + + + // ------------------------------------------------------------------------ + // EA_OPTIMIZE_OFF / EA_OPTIMIZE_ON + // + // Implements portable inline optimization enabling/disabling. + // Usage of these macros must be in order OFF then ON. This is + // because the OFF macro pushes a set of settings and the ON + // macro pops them. The nesting of OFF/ON sets (e.g. OFF, OFF, ON, ON) + // is not guaranteed to work on all platforms. + // + // This is often used to allow debugging of some code that's + // otherwise compiled with undebuggable optimizations. It's also + // useful for working around compiler code generation problems + // that occur in optimized builds. + // + // Some compilers (e.g. VC++) don't allow doing this within a function and + // so the usage must be outside a function, as with the example below. + // GCC on x86 appears to have some problem with argument passing when + // using EA_OPTIMIZE_OFF in optimized builds. + // + // Example usage: + // // Disable optimizations for SomeFunction. + // EA_OPTIMIZE_OFF() + // void SomeFunction() + // { + // ... + // } + // EA_OPTIMIZE_ON() + // + #if !defined(EA_OPTIMIZE_OFF) + #if defined(EA_COMPILER_MSVC) + #define EA_OPTIMIZE_OFF() __pragma(optimize("", off)) + #elif defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION > 4004) && (defined(__i386__) || defined(__x86_64__)) // GCC 4.4+ - Seems to work only on x86/Linux so far. However, GCC 4.4 itself appears broken and screws up parameter passing conventions. + #define EA_OPTIMIZE_OFF() \ + _Pragma("GCC push_options") \ + _Pragma("GCC optimize 0") + #elif defined(EA_COMPILER_CLANG) && (!defined(EA_PLATFORM_ANDROID) || (EA_COMPILER_VERSION >= 380)) + #define EA_OPTIMIZE_OFF() \ + EA_DISABLE_CLANG_WARNING(-Wunknown-pragmas) \ + _Pragma("clang optimize off") \ + EA_RESTORE_CLANG_WARNING() + #else + #define EA_OPTIMIZE_OFF() + #endif + #endif + + #if !defined(EA_OPTIMIZE_ON) + #if defined(EA_COMPILER_MSVC) + #define EA_OPTIMIZE_ON() __pragma(optimize("", on)) + #elif defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION > 4004) && (defined(__i386__) || defined(__x86_64__)) // GCC 4.4+ - Seems to work only on x86/Linux so far. However, GCC 4.4 itself appears broken and screws up parameter passing conventions. + #define EA_OPTIMIZE_ON() _Pragma("GCC pop_options") + #elif defined(EA_COMPILER_CLANG) && (!defined(EA_PLATFORM_ANDROID) || (EA_COMPILER_VERSION >= 380)) + #define EA_OPTIMIZE_ON() \ + EA_DISABLE_CLANG_WARNING(-Wunknown-pragmas) \ + _Pragma("clang optimize on") \ + EA_RESTORE_CLANG_WARNING() + #else + #define EA_OPTIMIZE_ON() + #endif + #endif + + + + // ------------------------------------------------------------------------ + // EA_SIGNED_RIGHT_SHIFT_IS_UNSIGNED + // + // Defined if right shifts of signed integers (i.e. arithmetic shifts) fail + // to propogate the high bit downward, and thus preserve sign. Most hardware + // and their corresponding compilers do this. + // + // <No current platform fails to propogate sign bits on right signed shifts> + +#endif // Header include guard + + + + + + + + + + diff --git a/include/Common/EABase/config/eaplatform.h b/include/Common/EABase/config/eaplatform.h new file mode 100644 index 0000000..37c1350 --- /dev/null +++ b/include/Common/EABase/config/eaplatform.h @@ -0,0 +1,738 @@ +/*----------------------------------------------------------------------------- + * config/eaplatform.h + * + * Copyright (c) Electronic Arts Inc. All rights reserved. + *----------------------------------------------------------------------------- + * Currently supported platform indentification defines include: + */ +#ifdef EA_PLATFORM_PS4 // ifdef for code stripping purposes +// EA_PLATFORM_PS4 (EA_PLATFORM_KETTLE) +#endif +#ifdef EA_PLATFORM_XBOXONE // ifdef for code stripping purposes + // EA_PLATFORM_XBOXONE (EA_PLATFORM_CAPILANO) + // EA_PLATFORM_XBOXONE_XDK (EA_PLATFORM_CAPILANO_XDK), set by capilano_config package + // EA_PLATFORM_XBOXONE_ADK (EA_PLATFORM_CAPILANO_ADK), set by capilano_config package +#endif +// EA_PLATFORM_ANDROID +// EA_PLATFORM_APPLE +// EA_PLATFORM_IPHONE +// EA_PLATFORM_IPHONE_SIMULATOR +// EA_PLATFORM_OSX +// EA_PLATFORM_LINUX +// EA_PLATFORM_SAMSUNG_TV +// EA_PLATFORM_WINDOWS +// EA_PLATFORM_WIN32 +// EA_PLATFORM_WIN64 +// EA_PLATFORM_WINDOWS_PHONE +// EA_PLATFORM_WINRT +// EA_PLATFORM_SUN +// EA_PLATFORM_LRB (Larrabee) +// EA_PLATFORM_POSIX (pseudo-platform; may be defined along with another platform like EA_PLATFORM_LINUX, EA_PLATFORM_UNIX, EA_PLATFORM_QNX) +// EA_PLATFORM_UNIX (pseudo-platform; may be defined along with another platform like EA_PLATFORM_LINUX) +// EA_PLATFORM_CYGWIN (pseudo-platform; may be defined along with another platform like EA_PLATFORM_LINUX) +// EA_PLATFORM_MINGW (pseudo-platform; may be defined along with another platform like EA_PLATFORM_WINDOWS) +// EA_PLATFORM_MICROSOFT (pseudo-platform; may be defined along with another platform like EA_PLATFORM_WINDOWS) +// +// EA_ABI_ARM_LINUX (a.k.a. "eabi". for all platforms that use the CodeSourcery GNU/Linux toolchain, like Android) +// EA_ABI_ARM_APPLE (similar to eabi but not identical) +// EA_ABI_ARM64_APPLE (similar to eabi but not identical) https://developer.apple.com/library/ios/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html +// EA_ABI_ARM_WINCE (similar to eabi but not identical) +// +// Other definitions emanated from this file inclue: +// EA_PLATFORM_NAME = <string> +// EA_PLATFORM_DESCRIPTION = <string> +// EA_PROCESSOR_XXX +// EA_MISALIGNED_SUPPORT_LEVEL=0|1|2 +// EA_SYSTEM_LITTLE_ENDIAN | EA_SYSTEM_BIG_ENDIAN +// EA_ASM_STYLE_ATT | EA_ASM_STYLE_INTEL | EA_ASM_STYLE_MOTOROLA +// EA_PLATFORM_PTR_SIZE = <integer size in bytes> +// EA_PLATFORM_WORD_SIZE = <integer size in bytes> +// EA_CACHE_LINE_SIZE = <integer size in bytes> +//--------------------------------------------------------------------------- + +/* + EA_PLATFORM_MOBILE + EA_PLATFORM_MOBILE is a peer to EA_PLATORM_DESKTOP and EA_PLATFORM_CONSOLE. Their definition is qualitative rather + than quantitative, and refers to the general (usually weaker) capabilities of the machine. Mobile devices have a + similar set of weaknesses that are useful to generally categorize. The primary motivation is to avoid code that + tests for multiple mobile platforms on a line and needs to be updated every time we get a new one. + For example, mobile platforms tend to have weaker ARM processors, don't have full multiple processor support, + are hand-held, don't have mice (though may have touch screens or basic cursor controls), have writable solid + state permanent storage. Production user code shouldn't have too many expectations about the meaning of this define. + + EA_PLATFORM_DESKTOP + This is similar to EA_PLATFORM_MOBILE in its qualitative nature and refers to platforms that are powerful. + For example, they nearly always have virtual memory, mapped memory, hundreds of GB of writable disk storage, + TCP/IP network connections, mice, keyboards, 512+ MB of RAM, multiprocessing, multiple display support. + Production user code shouldn't have too many expectations about the meaning of this define. + + EA_PLATFORM_CONSOLE + This is similar to EA_PLATFORM_MOBILE in its qualitative nature and refers to platforms that are consoles. + This means platforms that are connected to TVs, are fairly powerful (especially graphics-wise), are tightly + controlled by vendors, tend not to have mapped memory, tend to have TCP/IP, don't have multiple process support + though they might have multiple CPUs, support TV output only. Production user code shouldn't have too many + expectations about the meaning of this define. + +*/ + + +#ifndef INCLUDED_eaplatform_H +#define INCLUDED_eaplatform_H + + +// Cygwin +// This is a pseudo-platform which will be defined along with EA_PLATFORM_LINUX when +// using the Cygwin build environment. +#if defined(__CYGWIN__) + #define EA_PLATFORM_CYGWIN 1 + #define EA_PLATFORM_DESKTOP 1 +#endif + +// MinGW +// This is a pseudo-platform which will be defined along with EA_PLATFORM_WINDOWS when +// using the MinGW Windows build environment. +#if defined(__MINGW32__) || defined(__MINGW64__) + #define EA_PLATFORM_MINGW 1 + #define EA_PLATFORM_DESKTOP 1 +#endif + +#if defined(EA_PLATFORM_PS4) || defined(__ORBIS__) || defined(EA_PLATFORM_KETTLE) + // PlayStation 4 + // Orbis was Sony's code-name for the platform, which is now obsolete. + // Kettle was an EA-specific code-name for the platform, which is now obsolete. + #if defined(EA_PLATFORM_PS4) + #undef EA_PLATFORM_PS4 + #endif + #define EA_PLATFORM_PS4 1 + + // Backward compatibility: + #if defined(EA_PLATFORM_KETTLE) + #undef EA_PLATFORM_KETTLE + #endif + // End backward compatbility + + #define EA_PLATFORM_KETTLE 1 + #define EA_PLATFORM_NAME "PS4" + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "PS4 on x64" + #define EA_PLATFORM_CONSOLE 1 + #define EA_PLATFORM_SONY 1 + #define EA_PLATFORM_POSIX 1 + // #define EA_POSIX_THREADS_AVAILABLE 1 // POSIX threading API is available but discouraged. Sony indicated use of the scePthreads* API is preferred. + #define EA_PROCESSOR_X86_64 1 + #if defined(__GNUC__) || defined(__clang__) + #define EA_ASM_STYLE_ATT 1 + #endif + +#elif defined(EA_PLATFORM_XBOXONE) || defined(_DURANGO) || defined(_XBOX_ONE) || defined(EA_PLATFORM_CAPILANO) || defined(_GAMING_XBOX) + // XBox One + // Durango was Microsoft's code-name for the platform, which is now obsolete. + // Microsoft uses _DURANGO instead of some variation of _XBOX, though it's not natively defined by the compiler. + // Capilano was an EA-specific code-name for the platform, which is now obsolete. + #if defined(EA_PLATFORM_XBOXONE) + #undef EA_PLATFORM_XBOXONE + #endif + #define EA_PLATFORM_XBOXONE 1 + + // Backward compatibility: + #if defined(EA_PLATFORM_CAPILANO) + #undef EA_PLATFORM_CAPILANO + #endif + #define EA_PLATFORM_CAPILANO 1 + #if defined(EA_PLATFORM_CAPILANO_XDK) && !defined(EA_PLATFORM_XBOXONE_XDK) + #define EA_PLATFORM_XBOXONE_XDK 1 + #endif + #if defined(EA_PLATFORM_CAPILANO_ADK) && !defined(EA_PLATFORM_XBOXONE_ADK) + #define EA_PLATFORM_XBOXONE_ADK 1 + #endif + // End backward compatibility + + #if !defined(_DURANGO) + #define _DURANGO + #endif + #define EA_PLATFORM_NAME "XBox One" + //#define EA_PROCESSOR_X86 Currently our policy is that we don't define this, even though x64 is something of a superset of x86. + #define EA_PROCESSOR_X86_64 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "XBox One on x64" + #define EA_ASM_STYLE_INTEL 1 + #define EA_PLATFORM_CONSOLE 1 + #define EA_PLATFORM_MICROSOFT 1 + + // WINAPI_FAMILY defines - mirrored from winapifamily.h + #define EA_WINAPI_FAMILY_APP 1000 + #define EA_WINAPI_FAMILY_DESKTOP_APP 1001 + #define EA_WINAPI_FAMILY_PHONE_APP 1002 + #define EA_WINAPI_FAMILY_TV_APP 1003 + #define EA_WINAPI_FAMILY_TV_TITLE 1004 + #define EA_WINAPI_FAMILY_GAMES 1006 + + #if defined(WINAPI_FAMILY) + #include <winapifamily.h> + #if defined(WINAPI_FAMILY_TV_TITLE) && WINAPI_FAMILY == WINAPI_FAMILY_TV_TITLE + #define EA_WINAPI_FAMILY EA_WINAPI_FAMILY_TV_TITLE + #elif defined(WINAPI_FAMILY_DESKTOP_APP) && WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP + #define EA_WINAPI_FAMILY EA_WINAPI_FAMILY_DESKTOP_APP + #elif defined(WINAPI_FAMILY_GAMES) && WINAPI_FAMILY == WINAPI_FAMILY_GAMES + #define EA_WINAPI_FAMILY EA_WINAPI_FAMILY_GAMES + #else + #error Unsupported WINAPI_FAMILY + #endif + #else + #error WINAPI_FAMILY should always be defined on Capilano. + #endif + + // Macro to determine if a partition is enabled. + #define EA_WINAPI_FAMILY_PARTITION(Partition) (Partition) + + #if EA_WINAPI_FAMILY == EA_WINAPI_FAMILY_DESKTOP_APP + #define EA_WINAPI_PARTITION_CORE 1 + #define EA_WINAPI_PARTITION_DESKTOP 1 + #define EA_WINAPI_PARTITION_APP 1 + #define EA_WINAPI_PARTITION_PC_APP 0 + #define EA_WIANPI_PARTITION_PHONE 0 + #define EA_WINAPI_PARTITION_TV_APP 0 + #define EA_WINAPI_PARTITION_TV_TITLE 0 + #define EA_WINAPI_PARTITION_GAMES 0 + #elif EA_WINAPI_FAMILY == EA_WINAPI_FAMILY_TV_TITLE + #define EA_WINAPI_PARTITION_CORE 1 + #define EA_WINAPI_PARTITION_DESKTOP 0 + #define EA_WINAPI_PARTITION_APP 0 + #define EA_WINAPI_PARTITION_PC_APP 0 + #define EA_WIANPI_PARTITION_PHONE 0 + #define EA_WINAPI_PARTITION_TV_APP 0 + #define EA_WINAPI_PARTITION_TV_TITLE 1 + #define EA_WINAPI_PARTITION_GAMES 0 + #elif EA_WINAPI_FAMILY == EA_WINAPI_FAMILY_GAMES + #define EA_WINAPI_PARTITION_CORE 1 + #define EA_WINAPI_PARTITION_DESKTOP 0 + #define EA_WINAPI_PARTITION_APP 0 + #define EA_WINAPI_PARTITION_PC_APP 0 + #define EA_WIANPI_PARTITION_PHONE 0 + #define EA_WINAPI_PARTITION_TV_APP 0 + #define EA_WINAPI_PARTITION_TV_TITLE 0 + #define EA_WINAPI_PARTITION_GAMES 1 + #else + #error Unsupported WINAPI_FAMILY + #endif + + #if EA_WINAPI_FAMILY_PARTITION(EA_WINAPI_PARTITION_GAMES) + #define CS_UNDEFINED_STRING 1 + #define CS_UNDEFINED_STRING 1 + #endif + + #if EA_WINAPI_FAMILY_PARTITION(EA_WINAPI_PARTITION_TV_TITLE) + #define EA_PLATFORM_XBOXONE_XDK 1 + #endif +#elif defined(EA_PLATFORM_LRB) || defined(__LRB__) || (defined(__EDG__) && defined(__ICC) && defined(__x86_64__)) + #undef EA_PLATFORM_LRB + #define EA_PLATFORM_LRB 1 + #define EA_PLATFORM_NAME "Larrabee" + #define EA_PLATFORM_DESCRIPTION "Larrabee on LRB1" + #define EA_PROCESSOR_X86_64 1 + #if defined(BYTE_ORDER) && (BYTE_ORDER == 4321) + #define EA_SYSTEM_BIG_ENDIAN 1 + #else + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #endif + #define EA_PROCESSOR_LRB 1 + #define EA_PROCESSOR_LRB1 1 // Larrabee version 1 + #define EA_ASM_STYLE_ATT 1 // Both types of asm style + #define EA_ASM_STYLE_INTEL 1 // are supported. + #define EA_PLATFORM_DESKTOP 1 + +// Android (Google phone OS) +#elif defined(EA_PLATFORM_ANDROID) || defined(__ANDROID__) + #undef EA_PLATFORM_ANDROID + #define EA_PLATFORM_ANDROID 1 + #define EA_PLATFORM_LINUX 1 + #define EA_PLATFORM_UNIX 1 + #define EA_PLATFORM_POSIX 1 + #define EA_PLATFORM_NAME "Android" + #define EA_ASM_STYLE_ATT 1 + #if defined(__arm__) + #define EA_ABI_ARM_LINUX 1 // a.k.a. "ARM eabi" + #define EA_PROCESSOR_ARM32 1 + #define EA_PLATFORM_DESCRIPTION "Android on ARM" + #elif defined(__aarch64__) + #define EA_PROCESSOR_ARM64 1 + #define EA_PLATFORM_DESCRIPTION "Android on ARM64" + #elif defined(__i386__) + #define EA_PROCESSOR_X86 1 + #define EA_PLATFORM_DESCRIPTION "Android on x86" + #elif defined(__x86_64) + #define EA_PROCESSOR_X86_64 1 + #define EA_PLATFORM_DESCRIPTION "Android on x64" + #else + #error Unknown processor + #endif + #if !defined(EA_SYSTEM_BIG_ENDIAN) && !defined(EA_SYSTEM_LITTLE_ENDIAN) + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #endif + #define EA_PLATFORM_MOBILE 1 + +// Samsung SMART TV - a Linux-based smart TV +#elif defined(EA_PLATFORM_SAMSUNG_TV) + #undef EA_PLATFORM_SAMSUNG_TV + #define EA_PLATFORM_SAMSUNG_TV 1 + #define EA_PLATFORM_LINUX 1 + #define EA_PLATFORM_UNIX 1 + #define EA_PLATFORM_POSIX 1 + #define EA_PLATFORM_NAME "SamsungTV" + #define EA_PLATFORM_DESCRIPTION "Samsung SMART TV on ARM" + #define EA_ASM_STYLE_ATT 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PROCESSOR_ARM32 1 + #define EA_ABI_ARM_LINUX 1 // a.k.a. "ARM eabi" + #define EA_PROCESSOR_ARM7 1 + +#elif defined(__APPLE__) && __APPLE__ + #include <TargetConditionals.h> + + // Apple family of operating systems. + #define EA_PLATFORM_APPLE + #define EA_PLATFORM_POSIX 1 + + // iPhone + // TARGET_OS_IPHONE will be undefined on an unknown compiler, and will be defined on gcc. + #if defined(EA_PLATFORM_IPHONE) || defined(__IPHONE__) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || (defined(TARGET_IPHONE_SIMULATOR) && TARGET_IPHONE_SIMULATOR) + #undef EA_PLATFORM_IPHONE + #define EA_PLATFORM_IPHONE 1 + #define EA_PLATFORM_NAME "iPhone" + #define EA_ASM_STYLE_ATT 1 + #define EA_POSIX_THREADS_AVAILABLE 1 + #if defined(__arm__) + #define EA_ABI_ARM_APPLE 1 + #define EA_PROCESSOR_ARM32 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "iPhone on ARM" + #elif defined(__aarch64__) || defined(__AARCH64) + #define EA_ABI_ARM64_APPLE 1 + #define EA_PROCESSOR_ARM64 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "iPhone on ARM64" + #elif defined(__i386__) + #define EA_PLATFORM_IPHONE_SIMULATOR 1 + #define EA_PROCESSOR_X86 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "iPhone simulator on x86" + #elif defined(__x86_64) || defined(__amd64) + #define EA_PROCESSOR_X86_64 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "iPhone simulator on x64" + #else + #error Unknown processor + #endif + #define EA_PLATFORM_MOBILE 1 + + // Macintosh OSX + // TARGET_OS_MAC is defined by the Metrowerks and older AppleC compilers. + // Howerver, TARGET_OS_MAC is defined to be 1 in all cases. + // __i386__ and __intel__ are defined by the GCC compiler. + // __dest_os is defined by the Metrowerks compiler. + // __MACH__ is defined by the Metrowerks and GCC compilers. + // powerc and __powerc are defined by the Metrowerks and GCC compilers. + #elif defined(EA_PLATFORM_OSX) || defined(__MACH__) || (defined(__MSL__) && (__dest_os == __mac_os_x)) + #undef EA_PLATFORM_OSX + #define EA_PLATFORM_OSX 1 + #define EA_PLATFORM_UNIX 1 + #define EA_PLATFORM_POSIX 1 + //#define EA_PLATFORM_BSD 1 We don't currently define this. OSX has some BSD history but a lot of the API is different. + #define EA_PLATFORM_NAME "OSX" + #if defined(__i386__) || defined(__intel__) + #define EA_PROCESSOR_X86 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "OSX on x86" + #elif defined(__x86_64) || defined(__amd64) + #define EA_PROCESSOR_X86_64 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "OSX on x64" + #elif defined(__arm__) + #define EA_ABI_ARM_APPLE 1 + #define EA_PROCESSOR_ARM32 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "OSX on ARM" + #elif defined(__aarch64__) || defined(__AARCH64) + #define EA_ABI_ARM64_APPLE 1 + #define EA_PROCESSOR_ARM64 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "OSX on ARM64" + #elif defined(__POWERPC64__) || defined(__powerpc64__) + #define EA_PROCESSOR_POWERPC 1 + #define EA_PROCESSOR_POWERPC_64 1 + #define EA_SYSTEM_BIG_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "OSX on PowerPC 64" + #elif defined(__POWERPC__) || defined(__powerpc__) + #define EA_PROCESSOR_POWERPC 1 + #define EA_PROCESSOR_POWERPC_32 1 + #define EA_SYSTEM_BIG_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "OSX on PowerPC" + #else + #error Unknown processor + #endif + #if defined(__GNUC__) + #define EA_ASM_STYLE_ATT 1 + #else + #define EA_ASM_STYLE_MOTOROLA 1 + #endif + #define EA_PLATFORM_DESKTOP 1 + #else + #error Unknown Apple Platform + #endif + +// Linux +// __linux and __linux__ are defined by the GCC and Borland compiler. +// __i386__ and __intel__ are defined by the GCC compiler. +// __i386__ is defined by the Metrowerks compiler. +// _M_IX86 is defined by the Borland compiler. +// __sparc__ is defined by the GCC compiler. +// __powerpc__ is defined by the GCC compiler. +// __ARM_EABI__ is defined by GCC on an ARM v6l (Raspberry Pi 1) +// __ARM_ARCH_7A__ is defined by GCC on an ARM v7l (Raspberry Pi 2) +#elif defined(EA_PLATFORM_LINUX) || (defined(__linux) || defined(__linux__)) + #undef EA_PLATFORM_LINUX + #define EA_PLATFORM_LINUX 1 + #define EA_PLATFORM_UNIX 1 + #define EA_PLATFORM_POSIX 1 + #define EA_PLATFORM_NAME "Linux" + #if defined(__i386__) || defined(__intel__) || defined(_M_IX86) + #define EA_PROCESSOR_X86 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "Linux on x86" + #elif defined(__ARM_ARCH_7A__) || defined(__ARM_EABI__) + #define EA_ABI_ARM_LINUX 1 + #define EA_PROCESSOR_ARM32 1 + #define EA_PLATFORM_DESCRIPTION "Linux on ARM 6/7 32-bits" + #elif defined(__aarch64__) || defined(__AARCH64) + #define EA_PROCESSOR_ARM64 1 + #define EA_PLATFORM_DESCRIPTION "Linux on ARM64" + #elif defined(__x86_64__) + #define EA_PROCESSOR_X86_64 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "Linux on x64" + #elif defined(__powerpc64__) + #define EA_PROCESSOR_POWERPC 1 + #define EA_PROCESSOR_POWERPC_64 1 + #define EA_SYSTEM_BIG_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "Linux on PowerPC 64" + #elif defined(__powerpc__) + #define EA_PROCESSOR_POWERPC 1 + #define EA_PROCESSOR_POWERPC_32 1 + #define EA_SYSTEM_BIG_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "Linux on PowerPC" + #else + #error Unknown processor + #error Unknown endianness + #endif + #if defined(__GNUC__) + #define EA_ASM_STYLE_ATT 1 + #endif + #define EA_PLATFORM_DESKTOP 1 + + +#elif defined(EA_PLATFORM_BSD) || (defined(__BSD__) || defined(__FreeBSD__)) + #undef EA_PLATFORM_BSD + #define EA_PLATFORM_BSD 1 + #define EA_PLATFORM_UNIX 1 + #define EA_PLATFORM_POSIX 1 // BSD's posix complaince is not identical to Linux's + #define EA_PLATFORM_NAME "BSD Unix" + #if defined(__i386__) || defined(__intel__) + #define EA_PROCESSOR_X86 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "BSD on x86" + #elif defined(__x86_64__) + #define EA_PROCESSOR_X86_64 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "BSD on x64" + #elif defined(__powerpc64__) + #define EA_PROCESSOR_POWERPC 1 + #define EA_PROCESSOR_POWERPC_64 1 + #define EA_SYSTEM_BIG_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "BSD on PowerPC 64" + #elif defined(__powerpc__) + #define EA_PROCESSOR_POWERPC 1 + #define EA_PROCESSOR_POWERPC_32 1 + #define EA_SYSTEM_BIG_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "BSD on PowerPC" + #else + #error Unknown processor + #error Unknown endianness + #endif + #if !defined(EA_PLATFORM_FREEBSD) && defined(__FreeBSD__) + #define EA_PLATFORM_FREEBSD 1 // This is a variation of BSD. + #endif + #if defined(__GNUC__) + #define EA_ASM_STYLE_ATT 1 + #endif + #define EA_PLATFORM_DESKTOP 1 + + +#elif defined(EA_PLATFORM_WINDOWS_PHONE) + #undef EA_PLATFORM_WINDOWS_PHONE + #define EA_PLATFORM_WINDOWS_PHONE 1 + #define EA_PLATFORM_NAME "Windows Phone" + #if defined(_M_AMD64) || defined(_AMD64_) || defined(__x86_64__) + #define EA_PROCESSOR_X86_64 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "Windows Phone on x64" + #elif defined(_M_IX86) || defined(_X86_) + #define EA_PROCESSOR_X86 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "Windows Phone on X86" + #elif defined(_M_ARM) + #define EA_ABI_ARM_WINCE 1 + #define EA_PROCESSOR_ARM32 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "Windows Phone on ARM" + #else //Possibly other Windows Phone variants + #error Unknown processor + #error Unknown endianness + #endif + #define EA_PLATFORM_MICROSOFT 1 + + // WINAPI_FAMILY defines - mirrored from winapifamily.h + #define EA_WINAPI_FAMILY_APP 1 + #define EA_WINAPI_FAMILY_DESKTOP_APP 2 + #define EA_WINAPI_FAMILY_PHONE_APP 3 + + #if defined(WINAPI_FAMILY) + #include <winapifamily.h> + #if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP + #define EA_WINAPI_FAMILY EA_WINAPI_FAMILY_PHONE_APP + #else + #error Unsupported WINAPI_FAMILY for Windows Phone + #endif + #else + #error WINAPI_FAMILY should always be defined on Windows Phone. + #endif + + // Macro to determine if a partition is enabled. + #define EA_WINAPI_FAMILY_PARTITION(Partition) (Partition) + + // Enable the appropriate partitions for the current family + #if EA_WINAPI_FAMILY == EA_WINAPI_FAMILY_PHONE_APP + # define EA_WINAPI_PARTITION_CORE 1 + # define EA_WINAPI_PARTITION_PHONE 1 + # define EA_WINAPI_PARTITION_APP 1 + #else + # error Unsupported WINAPI_FAMILY for Windows Phone + #endif + + +// Windows +// _WIN32 is defined by the VC++, Intel and GCC compilers. +// _WIN64 is defined by the VC++, Intel and GCC compilers. +// __WIN32__ is defined by the Borland compiler. +// __INTEL__ is defined by the Metrowerks compiler. +// _M_IX86, _M_AMD64 and _M_IA64 are defined by the VC++, Intel, and Borland compilers. +// _X86_, _AMD64_, and _IA64_ are defined by the Metrowerks compiler. +// _M_ARM is defined by the VC++ compiler. +#elif (defined(EA_PLATFORM_WINDOWS) || (defined(_WIN32) || defined(__WIN32__) || defined(_WIN64))) && !defined(CS_UNDEFINED_STRING) + #undef EA_PLATFORM_WINDOWS + #define EA_PLATFORM_WINDOWS 1 + #define EA_PLATFORM_NAME "Windows" + #ifdef _WIN64 // VC++ defines both _WIN32 and _WIN64 when compiling for Win64. + #define EA_PLATFORM_WIN64 1 + #else + #define EA_PLATFORM_WIN32 1 + #endif + #if defined(_M_AMD64) || defined(_AMD64_) || defined(__x86_64__) + #define EA_PROCESSOR_X86_64 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "Windows on x64" + #elif defined(_M_IX86) || defined(_X86_) + #define EA_PROCESSOR_X86 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "Windows on X86" + #elif defined(_M_IA64) || defined(_IA64_) + #define EA_PROCESSOR_IA64 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "Windows on IA-64" + #elif defined(_M_ARM) + #define EA_ABI_ARM_WINCE 1 + #define EA_PROCESSOR_ARM32 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "Windows on ARM" + #elif defined(_M_ARM64) + #define EA_PROCESSOR_ARM64 1 + #define EA_SYSTEM_LITTLE_ENDIAN 1 + #define EA_PLATFORM_DESCRIPTION "Windows on ARM64" + #else //Possibly other Windows CE variants + #error Unknown processor + #error Unknown endianness + #endif + #if defined(__GNUC__) + #define EA_ASM_STYLE_ATT 1 + #elif defined(_MSC_VER) || defined(__BORLANDC__) || defined(__ICL) + #define EA_ASM_STYLE_INTEL 1 + #endif + #define EA_PLATFORM_DESKTOP 1 + #define EA_PLATFORM_MICROSOFT 1 + + // WINAPI_FAMILY defines to support Windows 8 Metro Apps - mirroring winapifamily.h in the Windows 8 SDK + #define EA_WINAPI_FAMILY_APP 1000 + #define EA_WINAPI_FAMILY_DESKTOP_APP 1001 + #define EA_WINAPI_FAMILY_GAMES 1006 + + #if defined(WINAPI_FAMILY) + #if defined(_MSC_VER) + #pragma warning(push, 0) + #endif + #include <winapifamily.h> + #if defined(_MSC_VER) + #pragma warning(pop) + #endif + #if defined(WINAPI_FAMILY_DESKTOP_APP) && WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP + #define EA_WINAPI_FAMILY EA_WINAPI_FAMILY_DESKTOP_APP + #elif defined(WINAPI_FAMILY_APP) && WINAPI_FAMILY == WINAPI_FAMILY_APP + #define EA_WINAPI_FAMILY EA_WINAPI_FAMILY_APP + #elif defined(WINAPI_FAMILY_GAMES) && WINAPI_FAMILY == WINAPI_FAMILY_GAMES + #define EA_WINAPI_FAMILY EA_WINAPI_FAMILY_GAMES + #else + #error Unsupported WINAPI_FAMILY + #endif + #else + #define EA_WINAPI_FAMILY EA_WINAPI_FAMILY_DESKTOP_APP + #endif + + #define EA_WINAPI_PARTITION_DESKTOP 1 + #define EA_WINAPI_PARTITION_APP 1 + #define EA_WINAPI_PARTITION_GAMES (EA_WINAPI_FAMILY == EA_WINAPI_FAMILY_GAMES) + + #define EA_WINAPI_FAMILY_PARTITION(Partition) (Partition) + + // EA_PLATFORM_WINRT + // This is a subset of Windows which is used for tablets and the "Metro" (restricted) Windows user interface. + // WinRT doesn't doesn't have access to the Windows "desktop" API, but WinRT can nevertheless run on + // desktop computers in addition to tablets. The Windows Phone API is a subset of WinRT and is not included + // in it due to it being only a part of the API. + #if defined(__cplusplus_winrt) + #define EA_PLATFORM_WINRT 1 + #endif + +// Sun (Solaris) +// __SUNPRO_CC is defined by the Sun compiler. +// __sun is defined by the GCC compiler. +// __i386 is defined by the Sun and GCC compilers. +// __sparc is defined by the Sun and GCC compilers. +#else + #error Unknown platform + #error Unknown processor + #error Unknown endianness +#endif + +#ifndef EA_PROCESSOR_ARM + #if defined(EA_PROCESSOR_ARM32) || defined(EA_PROCESSOR_ARM64) || defined(EA_PROCESSOR_ARM7) + #define EA_PROCESSOR_ARM + #endif +#endif + +// EA_PLATFORM_PTR_SIZE +// Platform pointer size; same as sizeof(void*). +// This is not the same as sizeof(int), as int is usually 32 bits on +// even 64 bit platforms. +// +// _WIN64 is defined by Win64 compilers, such as VC++. +// _M_IA64 is defined by VC++ and Intel compilers for IA64 processors. +// __LP64__ is defined by HP compilers for the LP64 standard. +// _LP64 is defined by the GCC and Sun compilers for the LP64 standard. +// __ia64__ is defined by the GCC compiler for IA64 processors. +// __arch64__ is defined by the Sparc compiler for 64 bit processors. +// __mips64__ is defined by the GCC compiler for MIPS processors. +// __powerpc64__ is defined by the GCC compiler for PowerPC processors. +// __64BIT__ is defined by the AIX compiler for 64 bit processors. +// __sizeof_ptr is defined by the ARM compiler (armcc, armcpp). +// +#ifndef EA_PLATFORM_PTR_SIZE + #if defined(__WORDSIZE) // Defined by some variations of GCC. + #define EA_PLATFORM_PTR_SIZE ((__WORDSIZE) / 8) + #elif defined(_WIN64) || defined(__LP64__) || defined(_LP64) || defined(_M_IA64) || defined(__ia64__) || defined(__arch64__) || defined(__aarch64__) || defined(__mips64__) || defined(__64BIT__) || defined(__Ptr_Is_64) + #define EA_PLATFORM_PTR_SIZE 8 + #elif defined(__CC_ARM) && (__sizeof_ptr == 8) + #define EA_PLATFORM_PTR_SIZE 8 + #else + #define EA_PLATFORM_PTR_SIZE 4 + #endif +#endif + + + +// EA_PLATFORM_WORD_SIZE +// This defines the size of a machine word. This will be the same as +// the size of registers on the machine but not necessarily the same +// as the size of pointers on the machine. A number of 64 bit platforms +// have 64 bit registers but 32 bit pointers. +// +#ifndef EA_PLATFORM_WORD_SIZE + #define EA_PLATFORM_WORD_SIZE EA_PLATFORM_PTR_SIZE +#endif + +// EA_PLATFORM_MIN_MALLOC_ALIGNMENT +// This defines the minimal alignment that the platform's malloc +// implementation will return. This should be used when writing custom +// allocators to ensure that the alignment matches that of malloc +#ifndef EA_PLATFORM_MIN_MALLOC_ALIGNMENT + #if defined(EA_PLATFORM_APPLE) + #define EA_PLATFORM_MIN_MALLOC_ALIGNMENT 16 + #elif defined(EA_PLATFORM_ANDROID) && defined(EA_PROCESSOR_ARM) + #define EA_PLATFORM_MIN_MALLOC_ALIGNMENT 8 + #elif defined(EA_PLATFORM_ANDROID) && defined(EA_PROCESSOR_X86_64) + #define EA_PLATFORM_MIN_MALLOC_ALIGNMENT 8 + #else + #define EA_PLATFORM_MIN_MALLOC_ALIGNMENT (EA_PLATFORM_PTR_SIZE * 2) + #endif +#endif + + +// EA_MISALIGNED_SUPPORT_LEVEL +// Specifies if the processor can read and write built-in types that aren't +// naturally aligned. +// 0 - not supported. Likely causes an exception. +// 1 - supported but slow. +// 2 - supported and fast. +// +#ifndef EA_MISALIGNED_SUPPORT_LEVEL + #if defined(EA_PROCESSOR_X86_64) + #define EA_MISALIGNED_SUPPORT_LEVEL 2 + #else + #define EA_MISALIGNED_SUPPORT_LEVEL 0 + #endif +#endif + +// Macro to determine if a Windows API partition is enabled. Always false on non Microsoft platforms. +#if !defined(EA_WINAPI_FAMILY_PARTITION) + #define EA_WINAPI_FAMILY_PARTITION(Partition) (0) +#endif + + +// EA_CACHE_LINE_SIZE +// Specifies the cache line size broken down by compile target. +// This the expected best guess values for the targets that we can make at compilation time. + +#ifndef EA_CACHE_LINE_SIZE + #if defined(EA_PROCESSOR_X86) + #define EA_CACHE_LINE_SIZE 32 // This is the minimum possible value. + #elif defined(EA_PROCESSOR_X86_64) + #define EA_CACHE_LINE_SIZE 64 // This is the minimum possible value + #elif defined(EA_PROCESSOR_ARM32) + #define EA_CACHE_LINE_SIZE 32 // This varies between implementations and is usually 32 or 64. + #elif defined(EA_PROCESSOR_ARM64) + #define EA_CACHE_LINE_SIZE 64 // Cache line Cortex-A8 (64 bytes) http://shervinemami.info/armAssembly.html however this remains to be mostly an assumption at this stage + #elif (EA_PLATFORM_WORD_SIZE == 4) + #define EA_CACHE_LINE_SIZE 32 // This is the minimum possible value + #else + #define EA_CACHE_LINE_SIZE 64 // This is the minimum possible value + #endif +#endif + + +#endif // INCLUDED_eaplatform_H + + + + + + + + + diff --git a/include/Common/EABase/eabase.h b/include/Common/EABase/eabase.h new file mode 100644 index 0000000..dab9e46 --- /dev/null +++ b/include/Common/EABase/eabase.h @@ -0,0 +1,1011 @@ +/*----------------------------------------------------------------------------- + * eabase.h + * + * Copyright (c) Electronic Arts Inc. All rights reserved. + *---------------------------------------------------------------------------*/ + + +#ifndef INCLUDED_eabase_H +#define INCLUDED_eabase_H + + +// Identify the compiler and declare the EA_COMPILER_xxxx defines +#include <EABase/config/eacompiler.h> + +// Identify traits which this compiler supports, or does not support +#include <EABase/config/eacompilertraits.h> + +// Identify the platform and declare the EA_xxxx defines +#include <EABase/config/eaplatform.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> + +// Define common SI unit macros +#include <EABase/eaunits.h> + + +// ------------------------------------------------------------------------ +// The C++ standard defines size_t as a built-in type. Some compilers are +// 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) || 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 + +// ------------------------------------------------------------------------ +// 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 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 +#endif + + +// ------------------------------------------------------------------------ +// Define the NULL pointer. This is normally defined in <stddef.h>, but we +// don't want to force a global dependency on that header, so the definition +// is duplicated here. + +#if defined(__cplusplus) + #define NULL 0 +#else + #define NULL ((void*)0) +#endif + + +// ------------------------------------------------------------------------ +// C98/99 Standard typedefs. From the ANSI ISO/IEC 9899 standards document +// Most recent versions of the gcc-compiler come with these defined in +// 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 +#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 + // 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(__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 +// 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_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 + + +// ------------------------------------------------------------------------ +// intptr_t / uintptr_t +// Integer type guaranteed to be big enough to hold +// 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 + + #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 + + #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 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 (except the QNX implementation of GCC) but not by other compilers. +// +#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(_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) + #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 +// 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 +// 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 +// 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 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 +// 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) + // 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) // 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 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. +// +// Example usage: +// const char16_t* str = EA_CHAR16("Hello world"); +// const char32_t* str = EA_CHAR32("Hello world"); +// 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 + #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 + #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 +// 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])) + #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++11 static_assert (a.k.a. compile-time assert). +// +// Specification: +// void static_assert(bool const_expression, const char* description); +// +// Example usage: +// static_assert(sizeof(int) == 4, "int must be 32 bits"); +// +#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 +#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 + +#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 + #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(__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 + + #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 + + + + diff --git a/include/Common/EABase/eahave.h b/include/Common/EABase/eahave.h new file mode 100644 index 0000000..b0987be --- /dev/null +++ b/include/Common/EABase/eahave.h @@ -0,0 +1,877 @@ +/*----------------------------------------------------------------------------- + * eahave.h + * + * Copyright (c) Electronic Arts Inc. All rights reserved. + *---------------------------------------------------------------------------*/ + + +/*----------------------------------------------------------------------------- + This file's functionality is preliminary and won't be considered stable until + a future EABase version. + *---------------------------------------------------------------------------*/ + + +/*----------------------------------------------------------------------------- + This header identifies if the given facilities are available in the + standard build environment the current compiler/linker/standard library/ + operating system combination. This file may in some cases #include standard + headers in order to make availability determinations, such as to check + compiler or SDK version numbers. However, it cannot be perfect. + This header does not identify compiler features, as those are defined in + eacompiler.h and eacompilertraits.h. Rather this header is about library support. + This header does not identify platform or library conventions either, such + as whether the file paths use \ or / for directory separators. + + We provide three types of HAVE features here: + + - EA_HAVE_XXX_FEATURE - Have compiler feature. + Identifies if the compiler has or lacks some feature in the + current build. Sometimes you need to check to see if the + compiler is running in some mode in able to write portable code + against it. For example, some compilers (e.g. VC++) have a + mode in which all language extensions are disabled. If you want + to write code that works with that but still uses the extensions + when available then you can check #if defined(EA_HAVE_EXTENSIONS_FEATURE). + Features can be forcibly cancelled via EA_NO_HAVE_XXX_FEATURE. + EA_NO_HAVE is useful for a build system or user to override the + defaults because it happens to know better. + + - EA_HAVE_XXX_H - Have header file information. + Identifies if a given header file is available to the current + compile configuration. For example, some compilers provide a + malloc.h header, while others don't. For the former we define + EA_HAVE_MALLOC_H, while for the latter it remains undefined. + If a header is missing then it may still be that the functions + the header usually declares are declared in some other header. + EA_HAVE_XXX does not include the possibility that our own code + provides versions of these headers, and in fact a purpose of + EA_HAVE_XXX is to decide if we should be using our own because + the system doesn't provide one. + Header availability can be forcibly cancelled via EA_NO_HAVE_XXX_H. + EA_NO_HAVE is useful for a build system or user to override the + defaults because it happens to know better. + + - EA_HAVE_XXX_DECL - Have function declaration information. + Identifies if a given function declaration is provided by + the current compile configuration. For example, some compiler + standard libraries declare a wcslen function, while others + don't. For the former we define EA_HAVE_WCSLEN_DECL, while for + the latter it remains undefined. If a declaration of a function + is missing then we assume the implementation is missing as well. + EA_HAVE_XXX_DECL does not include the possibility that our + own code provides versions of these declarations, and in fact a + purpose of EA_HAVE_XXX_DECL is to decide if we should be using + our own because the system doesn't provide one. + Declaration availability can be forcibly cancelled via EA_NO_HAVE_XXX_DECL. + EA_NO_HAVE is useful for a build system or user to override the + defaults because it happens to know better. + + - EA_HAVE_XXX_IMPL - Have function implementation information. + Identifies if a given function implementation is provided by + the current compile and link configuration. For example, it's + commonly the case that console platforms declare a getenv function + but don't provide a linkable implementation. + In this case the user needs to provide such a function manually + as part of the link. If the implementation is available then + we define EA_HAVE_GETENV_IMPL, otherwise it remains undefined. + Beware that sometimes a function may not seem to be present in + the Standard Library but in reality you need to link some auxiliary + provided library for it. An example of this is the Unix real-time + functions such as clock_gettime. + EA_HAVE_XXX_IMPL does not include the possibility that our + own code provides versions of these implementations, and in fact a + purpose of EA_HAVE_XXX_IMPL is to decide if we should be using + our own because the system doesn't provide one. + Implementation availability can be forcibly cancelled via EA_NO_HAVE_XXX_IMPL. + EA_NO_HAVE is useful for a build system or user to override the + defaults because it happens to know better. + + It's not practical to define EA_HAVE macros for every possible header, + declaration, and implementation, and so the user must simply know that + some headers, declarations, and implementations tend to require EA_HAVE + checking. Nearly every C Standard Library we've seen has a <string.h> + header, a strlen declaration, and a linkable strlen implementation, + so there's no need to provide EA_HAVE support for this. On the other hand + it's commonly the case that the C Standard Library doesn't have a malloc.h + header or an inet_ntop declaration. + +---------------------------------------------------------------------------*/ + + +#ifndef INCLUDED_eahave_H +#define INCLUDED_eahave_H + + +#include <EABase/eabase.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 + +/* EA_HAVE_XXX_FEATURE */ + +#if !defined(EA_HAVE_EXTENSIONS_FEATURE) && !defined(EA_NO_HAVE_EXTENSIONS_FEATURE) + #define EA_HAVE_EXTENSIONS_FEATURE 1 +#endif + + +/* EA_HAVE_XXX_LIBRARY */ + +// Dinkumware +#if !defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && !defined(EA_NO_HAVE_DINKUMWARE_CPP_LIBRARY) + #if defined(__cplusplus) + EA_DISABLE_ALL_VC_WARNINGS() + #include <cstddef> // Need to trigger the compilation of yvals.h without directly using <yvals.h> because it might not exist. + EA_RESTORE_ALL_VC_WARNINGS() + #endif + + #if defined(__cplusplus) && defined(_CPPLIB_VER) /* If using the Dinkumware Standard library... */ + #define EA_HAVE_DINKUMWARE_CPP_LIBRARY 1 + #else + #define EA_NO_HAVE_DINKUMWARE_CPP_LIBRARY 1 + #endif +#endif + +// GCC libstdc++ +#if !defined(EA_HAVE_LIBSTDCPP_LIBRARY) && !defined(EA_NO_HAVE_LIBSTDCPP_LIBRARY) + #if defined(__GLIBCXX__) /* If using libstdc++ ... */ + #define EA_HAVE_LIBSTDCPP_LIBRARY 1 + #else + #define EA_NO_HAVE_LIBSTDCPP_LIBRARY 1 + #endif +#endif + +// Clang libc++ +#if !defined(EA_HAVE_LIBCPP_LIBRARY) && !defined(EA_NO_HAVE_LIBCPP_LIBRARY) + #if EA_HAS_INCLUDE_AVAILABLE + #if EA_HAS_INCLUDE(<__config>) + #define EA_HAVE_LIBCPP_LIBRARY 1 // We could also #include <ciso646> and check if defined(_LIBCPP_VERSION). + #endif + #endif + + #if !defined(EA_HAVE_LIBCPP_LIBRARY) + #define EA_NO_HAVE_LIBCPP_LIBRARY 1 + #endif +#endif + + +/* EA_HAVE_XXX_H */ + +// #include <sys/types.h> +#if !defined(EA_HAVE_SYS_TYPES_H) && !defined(EA_NO_HAVE_SYS_TYPES_H) + #define EA_HAVE_SYS_TYPES_H 1 +#endif + +// #include <io.h> (and not sys/io.h or asm/io.h) +#if !defined(EA_HAVE_IO_H) && !defined(EA_NO_HAVE_IO_H) + // Unix doesn't have Microsoft's <io.h> but has the same functionality in <fcntl.h> and <sys/stat.h>. + #if defined(EA_PLATFORM_MICROSOFT) + #define EA_HAVE_IO_H 1 + #else + #define EA_NO_HAVE_IO_H 1 + #endif +#endif + +// #include <inttypes.h> +#if !defined(EA_HAVE_INTTYPES_H) && !defined(EA_NO_HAVE_INTTYPES_H) + #if !defined(EA_PLATFORM_MICROSOFT) + #define EA_HAVE_INTTYPES_H 1 + #else + #define EA_NO_HAVE_INTTYPES_H 1 + #endif +#endif + +// #include <unistd.h> +#if !defined(EA_HAVE_UNISTD_H) && !defined(EA_NO_HAVE_UNISTD_H) + #if defined(EA_PLATFORM_UNIX) + #define EA_HAVE_UNISTD_H 1 + #else + #define EA_NO_HAVE_UNISTD_H 1 + #endif +#endif + +// #include <sys/time.h> +#if !defined(EA_HAVE_SYS_TIME_H) && !defined(EA_NO_HAVE_SYS_TIME_H) + #if !defined(EA_PLATFORM_MICROSOFT) && !defined(_CPPLIB_VER) /* _CPPLIB_VER indicates Dinkumware. */ + #define EA_HAVE_SYS_TIME_H 1 /* defines struct timeval */ + #else + #define EA_NO_HAVE_SYS_TIME_H 1 + #endif +#endif + +// #include <ptrace.h> +#if !defined(EA_HAVE_SYS_PTRACE_H) && !defined(EA_NO_HAVE_SYS_PTRACE_H) + #if defined(EA_PLATFORM_UNIX) && !defined(__CYGWIN__) && (defined(EA_PLATFORM_DESKTOP) || defined(EA_PLATFORM_SERVER)) + #define EA_HAVE_SYS_PTRACE_H 1 /* declares the ptrace function */ + #else + #define EA_NO_HAVE_SYS_PTRACE_H 1 + #endif +#endif + +// #include <sys/stat.h> +#if !defined(EA_HAVE_SYS_STAT_H) && !defined(EA_NO_HAVE_SYS_STAT_H) + #if (defined(EA_PLATFORM_UNIX) && !(defined(EA_PLATFORM_SONY) && defined(EA_PLATFORM_CONSOLE))) || defined(__APPLE__) || defined(EA_PLATFORM_ANDROID) + #define EA_HAVE_SYS_STAT_H 1 /* declares the stat struct and function */ + #else + #define EA_NO_HAVE_SYS_STAT_H 1 + #endif +#endif + +// #include <locale.h> +#if !defined(EA_HAVE_LOCALE_H) && !defined(EA_NO_HAVE_LOCALE_H) + #define EA_HAVE_LOCALE_H 1 +#endif + +// #include <signal.h> +#if !defined(EA_HAVE_SIGNAL_H) && !defined(EA_NO_HAVE_SIGNAL_H) + #if !defined(EA_PLATFORM_BSD) && !defined(EA_PLATFORM_SONY) && !defined(CS_UNDEFINED_STRING) + #define EA_HAVE_SIGNAL_H 1 + #else + #define EA_NO_HAVE_SIGNAL_H 1 + #endif +#endif + +// #include <sys/signal.h> +#if !defined(EA_HAVE_SYS_SIGNAL_H) && !defined(EA_NO_HAVE_SYS_SIGNAL_H) + #if defined(EA_PLATFORM_BSD) || defined(EA_PLATFORM_SONY) + #define EA_HAVE_SYS_SIGNAL_H 1 + #else + #define EA_NO_HAVE_SYS_SIGNAL_H 1 + #endif +#endif + +// #include <pthread.h> +#if !defined(EA_HAVE_PTHREAD_H) && !defined(EA_NO_HAVE_PTHREAD_H) + #if defined(EA_PLATFORM_UNIX) || defined(EA_PLATFORM_APPLE) || defined(EA_PLATFORM_POSIX) + #define EA_HAVE_PTHREAD_H 1 /* It can be had under Microsoft/Windows with the http://sourceware.org/pthreads-win32/ library */ + #else + #define EA_NO_HAVE_PTHREAD_H 1 + #endif +#endif + +// #include <wchar.h> +#if !defined(EA_HAVE_WCHAR_H) && !defined(EA_NO_HAVE_WCHAR_H) + #if defined(EA_PLATFORM_DESKTOP) && defined(EA_PLATFORM_UNIX) && defined(EA_PLATFORM_SONY) && defined(EA_PLATFORM_APPLE) + #define EA_HAVE_WCHAR_H 1 + #else + #define EA_NO_HAVE_WCHAR_H 1 + #endif +#endif + +// #include <malloc.h> +#if !defined(EA_HAVE_MALLOC_H) && !defined(EA_NO_HAVE_MALLOC_H) + #if defined(_MSC_VER) || defined(__MINGW32__) + #define EA_HAVE_MALLOC_H 1 + #else + #define EA_NO_HAVE_MALLOC_H 1 + #endif +#endif + +// #include <alloca.h> +#if !defined(EA_HAVE_ALLOCA_H) && !defined(EA_NO_HAVE_ALLOCA_H) + #if !defined(EA_HAVE_MALLOC_H) && !defined(EA_PLATFORM_SONY) + #define EA_HAVE_ALLOCA_H 1 + #else + #define EA_NO_HAVE_ALLOCA_H 1 + #endif +#endif + +// #include <execinfo.h> +#if !defined(EA_HAVE_EXECINFO_H) && !defined(EA_NO_HAVE_EXECINFO_H) + #if (defined(EA_PLATFORM_LINUX) || defined(EA_PLATFORM_OSX)) && !defined(EA_PLATFORM_ANDROID) + #define EA_HAVE_EXECINFO_H 1 + #else + #define EA_NO_HAVE_EXECINFO_H 1 + #endif +#endif + +// #include <semaphore.h> (Unix semaphore support) +#if !defined(EA_HAVE_SEMAPHORE_H) && !defined(EA_NO_HAVE_SEMAPHORE_H) + #if defined(EA_PLATFORM_UNIX) + #define EA_HAVE_SEMAPHORE_H 1 + #else + #define EA_NO_HAVE_SEMAPHORE_H 1 + #endif +#endif + +// #include <dirent.h> (Unix semaphore support) +#if !defined(EA_HAVE_DIRENT_H) && !defined(EA_NO_HAVE_DIRENT_H) + #if defined(EA_PLATFORM_UNIX) && !defined(EA_PLATFORM_CONSOLE) + #define EA_HAVE_DIRENT_H 1 + #else + #define EA_NO_HAVE_DIRENT_H 1 + #endif +#endif + +// #include <array>, <forward_list>, <ununordered_set>, <unordered_map> +#if !defined(EA_HAVE_CPP11_CONTAINERS) && !defined(EA_NO_HAVE_CPP11_CONTAINERS) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 520) // Dinkumware. VS2010+ + #define EA_HAVE_CPP11_CONTAINERS 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4004) // Actually GCC 4.3 supports array and unordered_ + #define EA_HAVE_CPP11_CONTAINERS 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_CONTAINERS 1 + #else + #define EA_NO_HAVE_CPP11_CONTAINERS 1 + #endif +#endif + +// #include <atomic> +#if !defined(EA_HAVE_CPP11_ATOMIC) && !defined(EA_NO_HAVE_CPP11_ATOMIC) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 540) // Dinkumware. VS2012+ + #define EA_HAVE_CPP11_ATOMIC 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4007) + #define EA_HAVE_CPP11_ATOMIC 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_ATOMIC 1 + #else + #define EA_NO_HAVE_CPP11_ATOMIC 1 + #endif +#endif + +// #include <condition_variable> +#if !defined(EA_HAVE_CPP11_CONDITION_VARIABLE) && !defined(EA_NO_HAVE_CPP11_CONDITION_VARIABLE) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 540) // Dinkumware. VS2012+ + #define EA_HAVE_CPP11_CONDITION_VARIABLE 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4007) + #define EA_HAVE_CPP11_CONDITION_VARIABLE 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_CONDITION_VARIABLE 1 + #else + #define EA_NO_HAVE_CPP11_CONDITION_VARIABLE 1 + #endif +#endif + +// #include <mutex> +#if !defined(EA_HAVE_CPP11_MUTEX) && !defined(EA_NO_HAVE_CPP11_MUTEX) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 540) // Dinkumware. VS2012+ + #define EA_HAVE_CPP11_MUTEX 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4007) + #define EA_HAVE_CPP11_MUTEX 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_MUTEX 1 + #else + #define EA_NO_HAVE_CPP11_MUTEX 1 + #endif +#endif + +// #include <thread> +#if !defined(EA_HAVE_CPP11_THREAD) && !defined(EA_NO_HAVE_CPP11_THREAD) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 540) // Dinkumware. VS2012+ + #define EA_HAVE_CPP11_THREAD 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4007) + #define EA_HAVE_CPP11_THREAD 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_THREAD 1 + #else + #define EA_NO_HAVE_CPP11_THREAD 1 + #endif +#endif + +// #include <future> +#if !defined(EA_HAVE_CPP11_FUTURE) && !defined(EA_NO_HAVE_CPP11_FUTURE) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 540) // Dinkumware. VS2012+ + #define EA_HAVE_CPP11_FUTURE 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4005) + #define EA_HAVE_CPP11_FUTURE 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_FUTURE 1 + #else + #define EA_NO_HAVE_CPP11_FUTURE 1 + #endif +#endif + + +// #include <type_traits> +#if !defined(EA_HAVE_CPP11_TYPE_TRAITS) && !defined(EA_NO_HAVE_CPP11_TYPE_TRAITS) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 540) // Dinkumware. VS2012+ + #define EA_HAVE_CPP11_TYPE_TRAITS 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4007) // Prior versions of libstdc++ have incomplete support for C++11 type traits. + #define EA_HAVE_CPP11_TYPE_TRAITS 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_TYPE_TRAITS 1 + #else + #define EA_NO_HAVE_CPP11_TYPE_TRAITS 1 + #endif +#endif + +// #include <tuple> +#if !defined(EA_HAVE_CPP11_TUPLES) && !defined(EA_NO_HAVE_CPP11_TUPLES) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 520) // Dinkumware. VS2010+ + #define EA_HAVE_CPP11_TUPLES 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4003) + #define EA_HAVE_CPP11_TUPLES 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_TUPLES 1 + #else + #define EA_NO_HAVE_CPP11_TUPLES 1 + #endif +#endif + +// #include <regex> +#if !defined(EA_HAVE_CPP11_REGEX) && !defined(EA_NO_HAVE_CPP11_REGEX) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 540) && (defined(_HAS_EXCEPTIONS) && _HAS_EXCEPTIONS) // Dinkumware. VS2012+ + #define EA_HAVE_CPP11_REGEX 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4003) + #define EA_HAVE_CPP11_REGEX 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_REGEX 1 + #else + #define EA_NO_HAVE_CPP11_REGEX 1 + #endif +#endif + +// #include <random> +#if !defined(EA_HAVE_CPP11_RANDOM) && !defined(EA_NO_HAVE_CPP11_RANDOM) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 520) // Dinkumware. VS2010+ + #define EA_HAVE_CPP11_RANDOM 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4005) + #define EA_HAVE_CPP11_RANDOM 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_RANDOM 1 + #else + #define EA_NO_HAVE_CPP11_RANDOM 1 + #endif +#endif + +// #include <chrono> +#if !defined(EA_HAVE_CPP11_CHRONO) && !defined(EA_NO_HAVE_CPP11_CHRONO) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 540) // Dinkumware. VS2012+ + #define EA_HAVE_CPP11_CHRONO 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4007) // chrono was broken in glibc prior to 4.7. + #define EA_HAVE_CPP11_CHRONO 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_CHRONO 1 + #else + #define EA_NO_HAVE_CPP11_CHRONO 1 + #endif +#endif + +// #include <scoped_allocator> +#if !defined(EA_HAVE_CPP11_SCOPED_ALLOCATOR) && !defined(EA_NO_HAVE_CPP11_SCOPED_ALLOCATOR) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 540) // Dinkumware. VS2012+ + #define EA_HAVE_CPP11_SCOPED_ALLOCATOR 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4007) + #define EA_HAVE_CPP11_SCOPED_ALLOCATOR 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_SCOPED_ALLOCATOR 1 + #else + #define EA_NO_HAVE_CPP11_SCOPED_ALLOCATOR 1 + #endif +#endif + +// #include <initializer_list> +#if !defined(EA_HAVE_CPP11_INITIALIZER_LIST) && !defined(EA_NO_HAVE_CPP11_INITIALIZER_LIST) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 520) && !defined(EA_COMPILER_NO_INITIALIZER_LISTS) // Dinkumware. VS2010+ + #define EA_HAVE_CPP11_INITIALIZER_LIST 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_CLANG) && (EA_COMPILER_VERSION >= 301) && !defined(EA_COMPILER_NO_INITIALIZER_LISTS) && !defined(EA_PLATFORM_APPLE) + #define EA_HAVE_CPP11_INITIALIZER_LIST 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBCPP_LIBRARY) && defined(EA_COMPILER_CLANG) && (EA_COMPILER_VERSION >= 301) && !defined(EA_COMPILER_NO_INITIALIZER_LISTS) && !defined(EA_PLATFORM_APPLE) + #define EA_HAVE_CPP11_INITIALIZER_LIST 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4004) && !defined(EA_COMPILER_NO_INITIALIZER_LISTS) && !defined(EA_PLATFORM_APPLE) + #define EA_HAVE_CPP11_INITIALIZER_LIST 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) && !defined(EA_COMPILER_NO_INITIALIZER_LISTS) + #define EA_HAVE_CPP11_INITIALIZER_LIST 1 + #else + #define EA_NO_HAVE_CPP11_INITIALIZER_LIST 1 + #endif +#endif + +// #include <system_error> +#if !defined(EA_HAVE_CPP11_SYSTEM_ERROR) && !defined(EA_NO_HAVE_CPP11_SYSTEM_ERROR) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 520) && !(defined(_HAS_CPP0X) && _HAS_CPP0X) // Dinkumware. VS2010+ + #define EA_HAVE_CPP11_SYSTEM_ERROR 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_CLANG) && (EA_COMPILER_VERSION >= 301) && !defined(EA_PLATFORM_APPLE) + #define EA_HAVE_CPP11_SYSTEM_ERROR 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4004) && !defined(EA_PLATFORM_APPLE) + #define EA_HAVE_CPP11_SYSTEM_ERROR 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_SYSTEM_ERROR 1 + #else + #define EA_NO_HAVE_CPP11_SYSTEM_ERROR 1 + #endif +#endif + +// #include <codecvt> +#if !defined(EA_HAVE_CPP11_CODECVT) && !defined(EA_NO_HAVE_CPP11_CODECVT) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 520) // Dinkumware. VS2010+ + #define EA_HAVE_CPP11_CODECVT 1 + // Future versions of libc++ may support this header. However, at the moment there isn't + // a reliable way of detecting if this header is available. + //#elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4008) + // #define EA_HAVE_CPP11_CODECVT 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_CODECVT 1 + #else + #define EA_NO_HAVE_CPP11_CODECVT 1 + #endif +#endif + +// #include <typeindex> +#if !defined(EA_HAVE_CPP11_TYPEINDEX) && !defined(EA_NO_HAVE_CPP11_TYPEINDEX) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 520) // Dinkumware. VS2010+ + #define EA_HAVE_CPP11_TYPEINDEX 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4006) + #define EA_HAVE_CPP11_TYPEINDEX 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_TYPEINDEX 1 + #else + #define EA_NO_HAVE_CPP11_TYPEINDEX 1 + #endif +#endif + + + + +/* EA_HAVE_XXX_DECL */ + +#if !defined(EA_HAVE_mkstemps_DECL) && !defined(EA_NO_HAVE_mkstemps_DECL) + #if defined(EA_PLATFORM_APPLE) || defined(CS_UNDEFINED_STRING) + #define EA_HAVE_mkstemps_DECL 1 + #else + #define EA_NO_HAVE_mkstemps_DECL 1 + #endif +#endif + +#if !defined(EA_HAVE_gettimeofday_DECL) && !defined(EA_NO_HAVE_gettimeofday_DECL) + #if defined(EA_PLATFORM_POSIX) /* Posix means Linux, Unix, and Macintosh OSX, among others (including Linux-based mobile platforms). */ + #define EA_HAVE_gettimeofday_DECL 1 + #else + #define EA_NO_HAVE_gettimeofday_DECL 1 + #endif +#endif + +#if !defined(EA_HAVE_strcasecmp_DECL) && !defined(EA_NO_HAVE_strcasecmp_DECL) + #if !defined(EA_PLATFORM_MICROSOFT) + #define EA_HAVE_strcasecmp_DECL 1 /* This is found as stricmp when not found as strcasecmp */ + #define EA_HAVE_strncasecmp_DECL 1 + #else + #define EA_HAVE_stricmp_DECL 1 + #define EA_HAVE_strnicmp_DECL 1 + #endif +#endif + +#if !defined(EA_HAVE_mmap_DECL) && !defined(EA_NO_HAVE_mmap_DECL) + #if defined(EA_PLATFORM_POSIX) + #define EA_HAVE_mmap_DECL 1 /* mmap functionality varies significantly between systems. */ + #else + #define EA_NO_HAVE_mmap_DECL 1 + #endif +#endif + +#if !defined(EA_HAVE_fopen_DECL) && !defined(EA_NO_HAVE_fopen_DECL) + #define EA_HAVE_fopen_DECL 1 /* C FILE functionality such as fopen */ +#endif + +#if !defined(EA_HAVE_ISNAN) && !defined(EA_NO_HAVE_ISNAN) + #if defined(EA_PLATFORM_MICROSOFT) && !defined(EA_PLATFORM_MINGW) + #define EA_HAVE_ISNAN(x) _isnan(x) /* declared in <math.h> */ + #define EA_HAVE_ISINF(x) !_finite(x) + #elif defined(EA_PLATFORM_APPLE) + #define EA_HAVE_ISNAN(x) std::isnan(x) /* declared in <cmath> */ + #define EA_HAVE_ISINF(x) std::isinf(x) + #elif defined(EA_PLATFORM_ANDROID) + #define EA_HAVE_ISNAN(x) __builtin_isnan(x) /* There are a number of standard libraries for Android and it's hard to tell them apart, so just go with builtins */ + #define EA_HAVE_ISINF(x) __builtin_isinf(x) + #elif defined(__GNUC__) && defined(__CYGWIN__) + #define EA_HAVE_ISNAN(x) __isnand(x) /* declared nowhere, it seems. */ + #define EA_HAVE_ISINF(x) __isinfd(x) + #else + #define EA_HAVE_ISNAN(x) std::isnan(x) /* declared in <cmath> */ + #define EA_HAVE_ISINF(x) std::isinf(x) + #endif +#endif + +#if !defined(EA_HAVE_itoa_DECL) && !defined(EA_NO_HAVE_itoa_DECL) + #if defined(EA_COMPILER_MSVC) + #define EA_HAVE_itoa_DECL 1 + #else + #define EA_NO_HAVE_itoa_DECL 1 + #endif +#endif + +#if !defined(EA_HAVE_nanosleep_DECL) && !defined(EA_NO_HAVE_nanosleep_DECL) + #if (defined(EA_PLATFORM_UNIX) && !defined(EA_PLATFORM_SONY)) || defined(EA_PLATFORM_IPHONE) || defined(EA_PLATFORM_OSX) || defined(EA_PLATFORM_SONY) || defined(CS_UNDEFINED_STRING) + #define EA_HAVE_nanosleep_DECL 1 + #else + #define EA_NO_HAVE_nanosleep_DECL 1 + #endif +#endif + +#if !defined(EA_HAVE_utime_DECL) && !defined(EA_NO_HAVE_utime_DECL) + #if defined(EA_PLATFORM_MICROSOFT) + #define EA_HAVE_utime_DECL _utime + #elif EA_PLATFORM_UNIX + #define EA_HAVE_utime_DECL utime + #else + #define EA_NO_HAVE_utime_DECL 1 + #endif +#endif + +#if !defined(EA_HAVE_ftruncate_DECL) && !defined(EA_NO_HAVE_ftruncate_DECL) + #if !defined(__MINGW32__) + #define EA_HAVE_ftruncate_DECL 1 + #else + #define EA_NO_HAVE_ftruncate_DECL 1 + #endif +#endif + +#if !defined(EA_HAVE_localtime_DECL) && !defined(EA_NO_HAVE_localtime_DECL) + #define EA_HAVE_localtime_DECL 1 +#endif + +#if !defined(EA_HAVE_pthread_getattr_np_DECL) && !defined(EA_NO_HAVE_pthread_getattr_np_DECL) + #if defined(EA_PLATFORM_LINUX) + #define EA_HAVE_pthread_getattr_np_DECL 1 + #else + #define EA_NO_HAVE_pthread_getattr_np_DECL 1 + #endif +#endif + + + +/* EA_HAVE_XXX_IMPL*/ + +#if !defined(EA_HAVE_WCHAR_IMPL) && !defined(EA_NO_HAVE_WCHAR_IMPL) + #if defined(EA_PLATFORM_DESKTOP) + #define EA_HAVE_WCHAR_IMPL 1 /* Specifies if wchar_t string functions are provided, such as wcslen, wprintf, etc. Implies EA_HAVE_WCHAR_H */ + #else + #define EA_NO_HAVE_WCHAR_IMPL 1 + #endif +#endif + +#if !defined(EA_HAVE_getenv_IMPL) && !defined(EA_NO_HAVE_getenv_IMPL) + #if (defined(EA_PLATFORM_DESKTOP) || defined(EA_PLATFORM_UNIX)) && !defined(EA_PLATFORM_WINRT) + #define EA_HAVE_getenv_IMPL 1 + #else + #define EA_NO_HAVE_getenv_IMPL 1 + #endif +#endif + +#if !defined(EA_HAVE_setenv_IMPL) && !defined(EA_NO_HAVE_setenv_IMPL) + #if defined(EA_PLATFORM_UNIX) && defined(EA_PLATFORM_POSIX) + #define EA_HAVE_setenv_IMPL 1 + #else + #define EA_NO_HAVE_setenv_IMPL 1 + #endif +#endif + +#if !defined(EA_HAVE_unsetenv_IMPL) && !defined(EA_NO_HAVE_unsetenv_IMPL) + #if defined(EA_PLATFORM_UNIX) && defined(EA_PLATFORM_POSIX) + #define EA_HAVE_unsetenv_IMPL 1 + #else + #define EA_NO_HAVE_unsetenv_IMPL 1 + #endif +#endif + +#if !defined(EA_HAVE_putenv_IMPL) && !defined(EA_NO_HAVE_putenv_IMPL) + #if (defined(EA_PLATFORM_DESKTOP) || defined(EA_PLATFORM_UNIX)) && !defined(EA_PLATFORM_WINRT) + #define EA_HAVE_putenv_IMPL 1 /* With Microsoft compilers you may need to use _putenv, as they have deprecated putenv. */ + #else + #define EA_NO_HAVE_putenv_IMPL 1 + #endif +#endif + +#if !defined(EA_HAVE_time_IMPL) && !defined(EA_NO_HAVE_time_IMPL) + #define EA_HAVE_time_IMPL 1 + #define EA_HAVE_clock_IMPL 1 +#endif + +// <cstdio> fopen() +#if !defined(EA_HAVE_fopen_IMPL) && !defined(EA_NO_HAVE_fopen_IMPL) + #define EA_HAVE_fopen_IMPL 1 /* C FILE functionality such as fopen */ +#endif + +// <arpa/inet.h> inet_ntop() +#if !defined(EA_HAVE_inet_ntop_IMPL) && !defined(EA_NO_HAVE_inet_ntop_IMPL) + #if (defined(EA_PLATFORM_UNIX) || defined(EA_PLATFORM_POSIX)) && !defined(EA_PLATFORM_SONY) && !defined(CS_UNDEFINED_STRING) + #define EA_HAVE_inet_ntop_IMPL 1 /* This doesn't identify if the platform SDK has some alternative function that does the same thing; */ + #define EA_HAVE_inet_pton_IMPL 1 /* it identifies strictly the <arpa/inet.h> inet_ntop and inet_pton functions. For example, Microsoft has InetNtop in <Ws2tcpip.h> */ + #else + #define EA_NO_HAVE_inet_ntop_IMPL 1 + #define EA_NO_HAVE_inet_pton_IMPL 1 + #endif +#endif + +// <time.h> clock_gettime() +#if !defined(EA_HAVE_clock_gettime_IMPL) && !defined(EA_NO_HAVE_clock_gettime_IMPL) + #if defined(EA_PLATFORM_LINUX) || defined(__CYGWIN__) || (defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)) || (defined(EA_PLATFORM_POSIX) && defined(_CPPLIB_VER) /*Dinkumware*/) + #define EA_HAVE_clock_gettime_IMPL 1 /* You need to link the 'rt' library to get this */ + #else + #define EA_NO_HAVE_clock_gettime_IMPL 1 + #endif +#endif + +#if !defined(EA_HAVE_getcwd_IMPL) && !defined(EA_NO_HAVE_getcwd_IMPL) + #if (defined(EA_PLATFORM_DESKTOP) || defined(EA_PLATFORM_UNIX)) && !defined(EA_PLATFORM_ANDROID) && !defined(EA_PLATFORM_WINRT) + #define EA_HAVE_getcwd_IMPL 1 /* With Microsoft compilers you may need to use _getcwd, as they have deprecated getcwd. And in any case it's present at <direct.h> */ + #else + #define EA_NO_HAVE_getcwd_IMPL 1 + #endif +#endif + +#if !defined(EA_HAVE_tmpnam_IMPL) && !defined(EA_NO_HAVE_tmpnam_IMPL) + #if (defined(EA_PLATFORM_DESKTOP) || defined(EA_PLATFORM_UNIX)) && !defined(EA_PLATFORM_ANDROID) + #define EA_HAVE_tmpnam_IMPL 1 + #else + #define EA_NO_HAVE_tmpnam_IMPL 1 + #endif +#endif + +// nullptr, the built-in C++11 type. +// This EA_HAVE is deprecated, as EA_COMPILER_NO_NULLPTR is more appropriate, given that nullptr is a compiler-level feature and not a library feature. +#if !defined(EA_HAVE_nullptr_IMPL) && !defined(EA_NO_HAVE_nullptr_IMPL) + #if defined(EA_COMPILER_NO_NULLPTR) + #define EA_NO_HAVE_nullptr_IMPL 1 + #else + #define EA_HAVE_nullptr_IMPL 1 + #endif +#endif + +// <cstddef> std::nullptr_t +// Note that <EABase/nullptr.h> implements a portable nullptr implementation, but this +// EA_HAVE specifically refers to std::nullptr_t from the standard libraries. +#if !defined(EA_HAVE_nullptr_t_IMPL) && !defined(EA_NO_HAVE_nullptr_t_IMPL) + #if defined(EA_COMPILER_CPP11_ENABLED) + // VS2010+ with its default Dinkumware standard library. + #if defined(_MSC_VER) && (_MSC_VER >= 1600) && defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) + #define EA_HAVE_nullptr_t_IMPL 1 + + #elif defined(EA_HAVE_LIBCPP_LIBRARY) // clang/llvm libc++ + #define EA_HAVE_nullptr_t_IMPL 1 + + #elif defined(EA_HAVE_LIBSTDCPP_LIBRARY) // GNU libstdc++ + // Unfortunately __GLIBCXX__ date values don't go strictly in version ordering. + #if (__GLIBCXX__ >= 20110325) && (__GLIBCXX__ != 20120702) && (__GLIBCXX__ != 20110428) + #define EA_HAVE_nullptr_t_IMPL 1 + #else + #define EA_NO_HAVE_nullptr_t_IMPL 1 + #endif + + // We simply assume that the standard library (e.g. Dinkumware) provides std::nullptr_t. + #elif defined(__clang__) + #define EA_HAVE_nullptr_t_IMPL 1 + + // With GCC compiler >= 4.6, std::nullptr_t is always defined in <cstddef>, in practice. + #elif defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4006) + #define EA_HAVE_nullptr_t_IMPL 1 + + // The EDG compiler provides nullptr, but uses an older standard library that doesn't support std::nullptr_t. + #elif defined(__EDG_VERSION__) && (__EDG_VERSION__ >= 403) + #define EA_HAVE_nullptr_t_IMPL 1 + + #else + #define EA_NO_HAVE_nullptr_t_IMPL 1 + #endif + #else + #define EA_NO_HAVE_nullptr_t_IMPL 1 + #endif +#endif + +// <exception> std::terminate +#if !defined(EA_HAVE_std_terminate_IMPL) && !defined(EA_NO_HAVE_std_terminate_IMPL) + #if !defined(EA_PLATFORM_IPHONE) && !defined(EA_PLATFORM_ANDROID) + #define EA_HAVE_std_terminate_IMPL 1 /* iOS doesn't appear to provide an implementation for std::terminate under the armv6 target. */ + #else + #define EA_NO_HAVE_std_terminate_IMPL 1 + #endif +#endif + +// <iterator>: std::begin, std::end, std::prev, std::next, std::move_iterator. +#if !defined(EA_HAVE_CPP11_ITERATOR_IMPL) && !defined(EA_NO_HAVE_CPP11_ITERATOR_IMPL) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 520) && !(defined(_HAS_CPP0X) && _HAS_CPP0X) // Dinkumware. VS2010+ + #define EA_HAVE_CPP11_ITERATOR_IMPL 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4006) + #define EA_HAVE_CPP11_ITERATOR_IMPL 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_ITERATOR_IMPL 1 + #else + #define EA_NO_HAVE_CPP11_ITERATOR_IMPL 1 + #endif +#endif + +// <memory>: std::weak_ptr, std::shared_ptr, std::unique_ptr, std::bad_weak_ptr, std::owner_less +#if !defined(EA_HAVE_CPP11_SMART_POINTER_IMPL) && !defined(EA_NO_HAVE_CPP11_SMART_POINTER_IMPL) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 520) && !(defined(_HAS_CPP0X) && _HAS_CPP0X) // Dinkumware. VS2010+ + #define EA_HAVE_CPP11_SMART_POINTER_IMPL 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4004) + #define EA_HAVE_CPP11_SMART_POINTER_IMPL 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_SMART_POINTER_IMPL 1 + #else + #define EA_NO_HAVE_CPP11_SMART_POINTER_IMPL 1 + #endif +#endif + +// <functional>: std::function, std::mem_fn, std::bad_function_call, std::is_bind_expression, std::is_placeholder, std::reference_wrapper, std::hash, std::bind, std::ref, std::cref. +#if !defined(EA_HAVE_CPP11_FUNCTIONAL_IMPL) && !defined(EA_NO_HAVE_CPP11_FUNCTIONAL_IMPL) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 520) && !(defined(_HAS_CPP0X) && _HAS_CPP0X) // Dinkumware. VS2010+ + #define EA_HAVE_CPP11_FUNCTIONAL_IMPL 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4004) + #define EA_HAVE_CPP11_FUNCTIONAL_IMPL 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_FUNCTIONAL_IMPL 1 + #else + #define EA_NO_HAVE_CPP11_FUNCTIONAL_IMPL 1 + #endif +#endif + +// <exception> std::current_exception, std::rethrow_exception, std::exception_ptr, std::make_exception_ptr +#if !defined(EA_HAVE_CPP11_EXCEPTION_IMPL) && !defined(EA_NO_HAVE_CPP11_EXCEPTION_IMPL) + #if defined(EA_HAVE_DINKUMWARE_CPP_LIBRARY) && (_CPPLIB_VER >= 520) && !(defined(_HAS_CPP0X) && _HAS_CPP0X) // Dinkumware. VS2010+ + #define EA_HAVE_CPP11_EXCEPTION_IMPL 1 + #elif defined(EA_COMPILER_CPP11_ENABLED) && defined(EA_HAVE_LIBSTDCPP_LIBRARY) && defined(EA_COMPILER_GNUC) && (EA_COMPILER_VERSION >= 4004) + #define EA_HAVE_CPP11_EXCEPTION_IMPL 1 + #elif defined(EA_HAVE_LIBCPP_LIBRARY) && (_LIBCPP_VERSION >= 1) + #define EA_HAVE_CPP11_EXCEPTION_IMPL 1 + #else + #define EA_NO_HAVE_CPP11_EXCEPTION_IMPL 1 + #endif +#endif + + + + +/* Implementations that all platforms seem to have: */ +/* + alloca + malloc + calloc + strtoll + strtoull + vsprintf + vsnprintf +*/ + +/* Implementations that we don't care about: */ +/* + bcopy -- Just use memmove or some customized equivalent. bcopy offers no practical benefit. + strlcpy -- So few platforms have this built-in that we get no benefit from using it. Use EA::StdC::Strlcpy instead. + strlcat -- " +*/ + + + +/*----------------------------------------------------------------------------- + EABASE_USER_HAVE_HEADER + + This allows the user to define a header file to be #included after the + eahave.h's contents are compiled. A primary use of this is to override + the contents of this header file. You can define the overhead header + file name in-code or define it globally as part of your build file. + + Example usage: + #define EABASE_USER_HAVE_HEADER "MyHaveOverrides.h" + #include <EABase/eahave.h> +---------------------------------------------------------------------------*/ + +#ifdef EABASE_USER_HAVE_HEADER + #include EABASE_USER_HAVE_HEADER +#endif + + +#endif /* Header include guard */ + + + diff --git a/include/Common/EABase/earesult.h b/include/Common/EABase/earesult.h new file mode 100644 index 0000000..d08b346 --- /dev/null +++ b/include/Common/EABase/earesult.h @@ -0,0 +1,62 @@ +/*----------------------------------------------------------------------------- + * earesult.h + * + * Copyright (c) Electronic Arts Inc. All rights reserved. + *---------------------------------------------------------------------------*/ + + +#ifndef INCLUDED_earesult_H +#define INCLUDED_earesult_H + + +#include <EABase/eabase.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 + + + +/* This result type is width-compatible with most systems. */ +typedef int32_t ea_result_type; + + +namespace EA +{ + typedef int32_t result_type; + + enum + { +#ifndef SUCCESS + // Deprecated + // Note: a public MS header has created a define of this name which causes a build error. Fortunately they + // define it to 0 which is compatible. + // see: WindowsSDK\8.1.51641-fb\installed\Include\um\RasError.h + SUCCESS = 0, +#endif + // Deprecated + FAILURE = -1, + + // These values are now the preferred constants + EA_SUCCESS = 0, + EA_FAILURE = -1, + }; +} + + +/* Macro to simplify testing for success. */ +#ifndef EA_SUCCEEDED + #define EA_SUCCEEDED(result) ((result) >= 0) +#endif + +/* Macro to simplfify testing for general failure. */ +#ifndef EA_FAILED + #define EA_FAILED(result) ((result) < 0) +#endif + + +#endif + + + + diff --git a/include/Common/EABase/eastdarg.h b/include/Common/EABase/eastdarg.h new file mode 100644 index 0000000..2c613eb --- /dev/null +++ b/include/Common/EABase/eastdarg.h @@ -0,0 +1,99 @@ +/*----------------------------------------------------------------------------- + * eastdarg.h + * + * Copyright (c) Electronic Arts Inc. All rights reserved. + *---------------------------------------------------------------------------*/ + + +#ifndef INCLUDED_eastdarg_H +#define INCLUDED_eastdarg_H + + +#include <EABase/eabase.h> +#include <stdarg.h> + + +// VA_ARG_COUNT +// +// Returns the number of arguments passed to a macro's ... argument. +// This applies to macros only and not functions. +// +// Example usage: +// assert(VA_ARG_COUNT() == 0); +// assert(VA_ARG_COUNT(a) == 1); +// assert(VA_ARG_COUNT(a, b) == 2); +// assert(VA_ARG_COUNT(a, b, c) == 3); +// +#if !defined(VA_ARG_COUNT) + #define VA_ARG_COUNT(...) VA_ARG_COUNT_II((VA_ARG_COUNT_PREFIX_ ## __VA_ARGS__ ## _VA_ARG_COUNT_POSTFIX,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)) + #define VA_ARG_COUNT_II(__args) VA_ARG_COUNT_I __args + #define VA_ARG_COUNT_PREFIX__VA_ARG_COUNT_POSTFIX ,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0 + #define VA_ARG_COUNT_I(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,N,...) N +#endif + + +// va_copy +// +// va_copy is required by C++11 +// C++11 and C99 require va_copy to be #defined and implemented. +// http://en.cppreference.com/w/cpp/utility/variadic/va_copy +// +// Example usage: +// void Func(char* p, ...){ +// va_list args, argsCopy; +// va_start(args, p); +// va_copy(argsCopy, args); +// (use args) +// (use argsCopy, which acts the same as args) +// va_end(args); +// va_end(argsCopy); +// } +// +#ifndef va_copy + #if defined(__va_copy) // GCC and others define this for non-C99 compatibility. + #define va_copy(dest, src) __va_copy((dest), (src)) + #else + // This may not work for some platforms, depending on their ABI. + // It works for Microsoft x86,x64, and PowerPC-based platforms. + #define va_copy(dest, src) memcpy(&(dest), &(src), sizeof(va_list)) + #endif +#endif + + + +// va_list_reference +// +// va_list_reference is not part of the C or C++ standards. +// It allows you to pass a va_list by reference to another +// function instead of by value. You cannot simply use va_list& +// as that won't work with many va_list implementations because +// they are implemented as arrays (which can't be passed by +// reference to a function without decaying to a pointer). +// +// Example usage: +// void Test(va_list_reference args){ +// printf("%d", va_arg(args, int)); +// } +// void Func(char* p, ...){ +// va_list args; +// va_start(args, p); +// Test(args); // Upon return args will be modified. +// va_end(args); +// } +#ifndef va_list_reference + #if defined(EA_PLATFORM_MICROSOFT) || (EA_PLATFORM_PTR_SIZE == 4) || (defined(EA_PLATFORM_APPLE) && defined(EA_PROCESSOR_ARM64)) || defined(CS_UNDEFINED_STRING) || (defined(EA_PLATFORM_ANDROID) && defined(EA_PROCESSOR_ARM64)) + // This is required for platform ABIs in which va_list is a struct or pointer. + #define va_list_reference va_list& + #else + // This is required for platform ABIs in which va_list is defined to be an array. + #define va_list_reference va_list + #endif +#endif + + + + +#endif /* Header include guard */ + + + diff --git a/include/Common/EABase/eaunits.h b/include/Common/EABase/eaunits.h new file mode 100644 index 0000000..2235723 --- /dev/null +++ b/include/Common/EABase/eaunits.h @@ -0,0 +1,54 @@ +/*----------------------------------------------------------------------------- + * eaunits.h + * + * Copyright (c) Electronic Arts Inc. All rights reserved. + *---------------------------------------------------------------------------*/ + + +#ifndef INCLUDED_eaunits_h +#define INCLUDED_eaunits_h + +#include <EABase/eabase.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 + +// Defining common SI unit macros. +// +// The mebibyte is a multiple of the unit byte for digital information. Technically a +// megabyte (MB) is a power of ten, while a mebibyte (MiB) is a power of two, +// appropriate for binary machines. Many Linux distributions use the unit, but it is +// not widely acknowledged within the industry or media. +// Reference: https://en.wikipedia.org/wiki/Mebibyte +// +// Examples: +// auto size1 = EA_KILOBYTE(16); +// auto size2 = EA_MEGABYTE(128); +// auto size3 = EA_MEBIBYTE(8); +// auto size4 = EA_GIBIBYTE(8); + +// define byte for completeness +#define EA_BYTE(x) (x) + +// Decimal SI units +#define EA_KILOBYTE(x) (size_t(x) * 1000) +#define EA_MEGABYTE(x) (size_t(x) * 1000 * 1000) +#define EA_GIGABYTE(x) (size_t(x) * 1000 * 1000 * 1000) +#define EA_TERABYTE(x) (size_t(x) * 1000 * 1000 * 1000 * 1000) +#define EA_PETABYTE(x) (size_t(x) * 1000 * 1000 * 1000 * 1000 * 1000) +#define EA_EXABYTE(x) (size_t(x) * 1000 * 1000 * 1000 * 1000 * 1000 * 1000) + +// Binary SI units +#define EA_KIBIBYTE(x) (size_t(x) * 1024) +#define EA_MEBIBYTE(x) (size_t(x) * 1024 * 1024) +#define EA_GIBIBYTE(x) (size_t(x) * 1024 * 1024 * 1024) +#define EA_TEBIBYTE(x) (size_t(x) * 1024 * 1024 * 1024 * 1024) +#define EA_PEBIBYTE(x) (size_t(x) * 1024 * 1024 * 1024 * 1024 * 1024) +#define EA_EXBIBYTE(x) (size_t(x) * 1024 * 1024 * 1024 * 1024 * 1024 * 1024) + +#endif // INCLUDED_earesult_H + + + + diff --git a/include/Common/EABase/int128.h b/include/Common/EABase/int128.h new file mode 100644 index 0000000..068d557 --- /dev/null +++ b/include/Common/EABase/int128.h @@ -0,0 +1,1268 @@ +/*----------------------------------------------------------------------------- + * eaint128_t.h + * + * Copyright (c) Electronic Arts Inc. All rights reserved. + *---------------------------------------------------------------------------*/ + + +#ifndef INCLUDED_int128_h +#define INCLUDED_int128_h + + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// EA_INT128_INTRINSIC_AVAILABLE +// +#if (EA_COMPILER_INTMAX_SIZE >= 16) && (defined(EA_COMPILER_GNUC) || defined(EA_COMPILER_CLANG)) + // __int128_t/__uint128_t is supported + #define EA_INT128_INTRINSIC_AVAILABLE 1 +#else + #define EA_INT128_INTRINSIC_AVAILABLE 0 +#endif + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// EA_INT128_ALIGNAS +// +#if EA_INT128_INTRINSIC_AVAILABLE && !defined(EA_COMPILER_NO_ALIGNAS) + #define EA_INT128_ALIGNAS alignas(unsigned __int128) +#else + #define EA_INT128_ALIGNAS +#endif + + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// EA_HAVE_INT128 +// +// Indicates that EABase implements 128-bit integer types +// +#define EA_HAVE_INT128 1 + + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// uint128_t_base +// +struct EA_INT128_ALIGNAS int128_t_base +{ + // Constructors / destructors + int128_t_base() = default; + int128_t_base(uint32_t nPart0, uint32_t nPart1, uint32_t nPart2, uint32_t nPart3); + int128_t_base(uint64_t nPart0, uint64_t nPart1); + int128_t_base(uint8_t value); + int128_t_base(uint16_t value); + int128_t_base(uint32_t value); + int128_t_base(uint64_t value); + int128_t_base(const int128_t_base& value) = default; + + // Assignment operator + int128_t_base& operator=(const int128_t_base& value) = default; + + // Explicit operators to convert back to basic types + EA_CONSTEXPR explicit operator bool() const; + EA_CONSTEXPR explicit operator char() const; + EA_CONSTEXPR explicit operator int() const; + EA_CONSTEXPR explicit operator long() const; + EA_CONSTEXPR explicit operator long long() const; + EA_CONSTEXPR explicit operator short() const; + EA_CONSTEXPR explicit operator signed char() const; + EA_CONSTEXPR explicit operator unsigned char() const; + EA_CONSTEXPR explicit operator unsigned int() const; + EA_CONSTEXPR explicit operator unsigned long long() const; + EA_CONSTEXPR explicit operator unsigned long() const; + EA_CONSTEXPR explicit operator unsigned short() const; +#if EA_WCHAR_UNIQUE + // EA_CONSTEXPR explicit operator char16_t() const; + // EA_CONSTEXPR explicit operator char32_t() const; + // EA_CONSTEXPR explicit operator wchar_t() const; +#endif + EA_CONSTEXPR explicit operator float() const; + EA_CONSTEXPR explicit operator double() const; + EA_CONSTEXPR explicit operator long double() const; +#if EA_INT128_INTRINSIC_AVAILABLE + EA_CONSTEXPR explicit operator __int128() const; + EA_CONSTEXPR explicit operator unsigned __int128() const; +#endif + + // Math operators + static void OperatorPlus (const int128_t_base& value1, const int128_t_base& value2, int128_t_base& result); + static void OperatorMinus(const int128_t_base& value1, const int128_t_base& value2, int128_t_base& result); + static void OperatorMul (const int128_t_base& value1, const int128_t_base& value2, int128_t_base& result); + + // Shift operators + static void OperatorShiftRight(const int128_t_base& value, int nShift, int128_t_base& result); + static void OperatorShiftLeft (const int128_t_base& value, int nShift, int128_t_base& result); + + // Unary arithmetic/logic operators + bool operator!() const; + + // Logical operators + static void OperatorXOR(const int128_t_base& value1, const int128_t_base& value2, int128_t_base& result); + static void OperatorOR (const int128_t_base& value1, const int128_t_base& value2, int128_t_base& result); + static void OperatorAND(const int128_t_base& value1, const int128_t_base& value2, int128_t_base& result); + + bool IsZero() const; + void SetZero(); + void TwosComplement(); + void InverseTwosComplement(); + + int GetBit(int nIndex) const; + void SetBit(int nIndex, int value); + +protected: + void DoubleToUint128(double value); + + EA_CONSTEXPR uint64_t Low() const + { + return mPart0; + } + + EA_CONSTEXPR uint64_t High() const + { + return mPart1; + } + +protected: + #ifdef EA_SYSTEM_BIG_ENDIAN + uint64_t mPart1; // Most significant byte. + uint64_t mPart0; // Least significant byte. + #else + uint64_t mPart0; // Most significant byte. + uint64_t mPart1; // Least significant byte. + #endif +}; + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// int128_t +// +// Implements signed 128 bit integer. +// +struct int128_t : public int128_t_base +{ + // Constructors / destructors + using int128_t_base::int128_t_base; + + // Assignment operator + using int128_t_base::operator=; + + // Unary arithmetic/logic operators + int128_t operator-() const; + int128_t& operator++(); + int128_t& operator--(); + int128_t operator++(int); + int128_t operator--(int); + int128_t operator~() const; + int128_t operator+() const; + + // Math operators + int128_t operator+ (const int128_t& other); + int128_t operator- (const int128_t& other); + int128_t operator* (const int128_t& other); + int128_t operator/ (const int128_t& other); + int128_t operator% (const int128_t& other); + int128_t& operator+=(const int128_t& other); + int128_t& operator-=(const int128_t& other); + int128_t& operator*=(const int128_t& other); + int128_t& operator/=(const int128_t& other); + int128_t& operator%=(const int128_t& other); + + // Shift operators + int128_t operator>> (int nShift) const; + int128_t operator<< (int nShift) const; + int128_t& operator>>=(int nShift); + int128_t& operator<<=(int nShift); + + // Logical operators + int128_t operator^ (const int128_t& other) const; + int128_t operator| (const int128_t& other) const; + int128_t operator& (const int128_t& other) const; + int128_t& operator^=(const int128_t& other); + int128_t& operator|=(const int128_t& other); + int128_t& operator&=(const int128_t& other); + + // Equality operators + bool operator==(const int128_t& other) const; + bool operator!=(const int128_t& other) const; + bool operator> (const int128_t& other) const; + bool operator>=(const int128_t& other) const; + bool operator< (const int128_t& other) const; + bool operator<=(const int128_t& other) const; + +protected: + int compare(const int128_t& other) const; + void Negate(); + void Modulus(const int128_t& divisor, int128_t& quotient, int128_t& remainder) const; + bool IsNegative() const; // Returns true for value < 0 + bool IsPositive() const; // Returns true for value >= 0 +}; + + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// uint128_t +// +// Implements unsigned 128 bit integer. +// +struct uint128_t : public int128_t_base +{ + // Constructors / destructors + using int128_t_base::int128_t_base; + + // Assignment operator + using int128_t_base::operator=; + + // Unary arithmetic/logic operators + uint128_t operator-() const; + uint128_t& operator++(); + uint128_t& operator--(); + uint128_t operator++(int); + uint128_t operator--(int); + uint128_t operator~() const; + uint128_t operator+() const; + + // Math operators + uint128_t operator+ (const uint128_t& other); + uint128_t operator- (const uint128_t& other); + uint128_t operator* (const uint128_t& other); + uint128_t operator/ (const uint128_t& other); + uint128_t operator% (const uint128_t& other); + uint128_t& operator+=(const uint128_t& other); + uint128_t& operator-=(const uint128_t& other); + uint128_t& operator*=(const uint128_t& other); + uint128_t& operator/=(const uint128_t& other); + uint128_t& operator%=(const uint128_t& other); + + // Shift operators + uint128_t operator>> (int nShift) const; + uint128_t operator<< (int nShift) const; + uint128_t& operator>>=(int nShift); + uint128_t& operator<<=(int nShift); + + // Logical operators + uint128_t operator^ (const uint128_t& other) const; + uint128_t operator| (const uint128_t& other) const; + uint128_t operator& (const uint128_t& other) const; + uint128_t& operator^=(const uint128_t& other); + uint128_t& operator|=(const uint128_t& other); + uint128_t& operator&=(const uint128_t& other); + + // Equality operators + bool operator==(const uint128_t& other) const; + bool operator!=(const uint128_t& other) const; + bool operator> (const uint128_t& other) const; + bool operator>=(const uint128_t& other) const; + bool operator< (const uint128_t& other) const; + bool operator<=(const uint128_t& other) const; + +protected: + int compare(const uint128_t& other) const; + void Negate(); + void Modulus(const uint128_t& divisor, uint128_t& quotient, uint128_t& remainder) const; + bool IsNegative() const; // Returns true for value < 0 + bool IsPositive() const; // Returns true for value >= 0 +}; + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// uint128_t_base implementation +/////////////////////////////////////////////////////////////////////////////////////////////////////// +EA_CONSTEXPR inline int128_t_base::operator bool() const { return mPart0 || mPart1; } +EA_CONSTEXPR inline int128_t_base::operator char() const { return static_cast<char>(Low()); } +#if EA_WCHAR_UNIQUE +// EA_CONSTEXPR inline int128_t_base::operator char16_t() const { return static_cast<char16_t>(Low()); } +// EA_CONSTEXPR inline int128_t_base::operator char32_t() const { return static_cast<char32_t>(Low()); } +// EA_CONSTEXPR inline int128_t_base::operator wchar_t() const { return static_cast<wchar_t>(Low()); } +#endif +EA_CONSTEXPR inline int128_t_base::operator int() const { return static_cast<int>(Low()); } +EA_CONSTEXPR inline int128_t_base::operator long() const { return static_cast<long>(Low()); } +EA_CONSTEXPR inline int128_t_base::operator long long() const { return static_cast<long long>(Low()); } +EA_CONSTEXPR inline int128_t_base::operator short() const { return static_cast<short>(Low()); } +EA_CONSTEXPR inline int128_t_base::operator signed char() const { return static_cast<signed char>(Low()); } +EA_CONSTEXPR inline int128_t_base::operator unsigned char() const { return static_cast<unsigned char>(Low()); } +EA_CONSTEXPR inline int128_t_base::operator unsigned int() const { return static_cast<unsigned int>(Low()); } +EA_CONSTEXPR inline int128_t_base::operator unsigned long long() const { return static_cast<unsigned long long>(Low()); } +EA_CONSTEXPR inline int128_t_base::operator unsigned long() const { return static_cast<unsigned long>(Low()); } +EA_CONSTEXPR inline int128_t_base::operator unsigned short() const { return static_cast<unsigned short>(Low()); } +EA_CONSTEXPR inline int128_t_base::operator float() const { return static_cast<float>(Low()); } +EA_CONSTEXPR inline int128_t_base::operator double() const { return static_cast<double>(Low()); } +EA_CONSTEXPR inline int128_t_base::operator long double() const { return static_cast<long double>(Low()); } +#if EA_INT128_INTRINSIC_AVAILABLE +EA_CONSTEXPR inline int128_t_base::operator __int128() const { return static_cast<__int128>(Low()); } +EA_CONSTEXPR inline int128_t_base::operator unsigned __int128() const { return static_cast<unsigned __int128>(Low()); } +#endif + +inline void int128_t_base::SetBit(int nIndex, int value) +{ + // EA_ASSERT((nIndex >= 0) && (nIndex < 128)); + + const uint64_t nBitMask = ((uint64_t)1 << (nIndex % 64)); + + if(nIndex < 64) + { + if(value) + mPart0 = mPart0 | nBitMask; + else + mPart0 = mPart0 & ~nBitMask; + } + else if(nIndex < 128) + { + if(value) + mPart1 = mPart1 | nBitMask; + else + mPart1 = mPart1 & ~nBitMask; + } +} + +inline int int128_t_base::GetBit(int nIndex) const +{ + // EA_ASSERT((nIndex >= 0) && (nIndex < 128)); + + const uint64_t nBitMask = ((uint64_t)1 << (nIndex % 64)); + + if(nIndex < 64) + return ((mPart0 & nBitMask) ? 1 : 0); + else if(nIndex < 128) + return ((mPart1 & nBitMask) ? 1 : 0); + return 0; +} + +inline int128_t_base::int128_t_base(uint32_t nPart0, uint32_t nPart1, uint32_t nPart2, uint32_t nPart3) +{ + mPart1 = ((uint64_t)nPart3 << 32) + nPart2; + mPart0 = ((uint64_t)nPart1 << 32) + nPart0; +} + +inline int128_t_base::int128_t_base(uint64_t nPart0, uint64_t nPart1) +{ + mPart1 = nPart1; + mPart0 = nPart0; +} + +inline int128_t_base::int128_t_base(uint8_t value) +{ + mPart1 = 0; + mPart0 = value; +} + +inline int128_t_base::int128_t_base(uint16_t value) +{ + mPart1 = 0; + mPart0 = value; +} + +inline int128_t_base::int128_t_base(uint32_t value) +{ + mPart1 = 0; + mPart0 = value; +} + +inline int128_t_base::int128_t_base(uint64_t value) +{ + mPart1 = 0; + mPart0 = value; +} + +/////////////////////////////////////////////////////////////////////////////// +// OperatorPlus +// +// Returns: (value1 + value2) into result. +// The output 'result' *is* allowed to point to the same memory as one of the inputs. +// To consider: Fix 'defect' of this function whereby it doesn't implement overflow wraparound. +// +inline void int128_t_base::OperatorPlus(const int128_t_base& value1, const int128_t_base& value2, int128_t_base& result) +{ + uint64_t t = value1.mPart0 + value2.mPart0; + uint64_t nCarry = (t < value1.mPart0) && (t < value2.mPart0); + result.mPart0 = t; + result.mPart1 = value1.mPart1 + value2.mPart1 + nCarry; +} + +/////////////////////////////////////////////////////////////////////////////// +// OperatorMinus +// +// Returns: (value1 - value2) into result. +// The output 'result' *is* allowed to point to the same memory as one of the inputs. +// To consider: Fix 'defect' of this function whereby it doesn't implement overflow wraparound. +// +inline void int128_t_base::OperatorMinus(const int128_t_base& value1, const int128_t_base& value2, int128_t_base& result) +{ + uint64_t t = (value1.mPart0 - value2.mPart0); + uint64_t nCarry = (value1.mPart0 < value2.mPart0) ? 1u : 0u; + result.mPart0 = t; + result.mPart1 = (value1.mPart1 - value2.mPart1) - nCarry; +} + +/////////////////////////////////////////////////////////////////////////////// +// OperatorMul +// +// 64 bit systems: +// This is how it would be able to work if we could get a 128 bit result from +// two 64 bit values. None of the 64 bit systems that we are currently working +// with have C language support for multiplying two 64 bit numbers and retrieving +// the 128 bit result. However, many 64 bit platforms have support at the asm +// level for doing such a thing. +// Part 1 Part 0 +// 0000000000000002 0000000000000001 +// x 0000000000000002 0000000000000001 +// ------------------------------------------- +// | 0000000000000002 0000000000000001 +// + 0000000000000004 | 0000000000000002 (0000000000000000) +// ------------------------------------------------------------------------- +// +inline void int128_t_base::OperatorMul(const int128_t_base& a, const int128_t_base& b, int128_t_base& result) +{ + // To consider: Use compiler or OS-provided custom functionality here, such as + // Windows UnsignedMultiply128 and GCC's built-in int128_t. + + #if defined(DISABLED_PLATFORM_WIN64) + // To do: Implement x86-64 asm here. + + #else + // Else we are stuck doing something less efficient. In this case we + // fall back to doing 32 bit multiplies as with 32 bit platforms. + result = (a.mPart0 & 0xffffffff) * (b.mPart0 & 0xffffffff); + int128_t v01 = (a.mPart0 & 0xffffffff) * ((b.mPart0 >> 32) & 0xffffffff); + int128_t v02 = (a.mPart0 & 0xffffffff) * (b.mPart1 & 0xffffffff); + int128_t v03 = (a.mPart0 & 0xffffffff) * ((b.mPart1 >> 32) & 0xffffffff); + + int128_t v10 = ((a.mPart0 >> 32) & 0xffffffff) * (b.mPart0 & 0xffffffff); + int128_t v11 = ((a.mPart0 >> 32) & 0xffffffff) * ((b.mPart0 >> 32) & 0xffffffff); + int128_t v12 = ((a.mPart0 >> 32) & 0xffffffff) * (b.mPart1 & 0xffffffff); + + int128_t v20 = (a.mPart1 & 0xffffffff) * (b.mPart0 & 0xffffffff); + int128_t v21 = (a.mPart1 & 0xffffffff) * ((b.mPart0 >> 32) & 0xffffffff); + + int128_t v30 = ((a.mPart1 >> 32) & 0xffffffff) * (b.mPart0 & 0xffffffff); + + // Do row addition, shifting as needed. + OperatorPlus(result, v01 << 32, result); + OperatorPlus(result, v02 << 64, result); + OperatorPlus(result, v03 << 96, result); + + OperatorPlus(result, v10 << 32, result); + OperatorPlus(result, v11 << 64, result); + OperatorPlus(result, v12 << 96, result); + + OperatorPlus(result, v20 << 64, result); + OperatorPlus(result, v21 << 96, result); + + OperatorPlus(result, v30 << 96, result); + #endif +} + +/////////////////////////////////////////////////////////////////////////////// +// OperatorShiftRight +// +// Returns: value >> nShift into result +// The output 'result' may *not* be the same as one the input. +// With rightward shifts of negative numbers, shift in zero from the left side. +// +inline void int128_t_base::OperatorShiftRight(const int128_t_base& value, int nShift, int128_t_base& result) +{ + if(nShift >= 0) + { + if(nShift < 64) + { // 0 - 63 + result.mPart1 = (value.mPart1 >> nShift); + + if(nShift == 0) + result.mPart0 = (value.mPart0 >> nShift); + else + result.mPart0 = (value.mPart0 >> nShift) | (value.mPart1 << (64 - nShift)); + } + else + { // 64+ + result.mPart1 = 0; + result.mPart0 = (value.mPart1 >> (nShift - 64)); + } + } + else // (nShift < 0) + OperatorShiftLeft(value, -nShift, result); +} + + +/////////////////////////////////////////////////////////////////////////////// +// OperatorShiftRight +// +// Returns: value << nShift into result +// The output 'result' may *not* be the same as one the input. +// With rightward shifts of negative numbers, shift in zero from the left side. +// +inline void int128_t_base::OperatorShiftLeft(const int128_t_base& value, int nShift, int128_t_base& result) +{ + if(nShift >= 0) + { + if(nShift < 64) + { + if(nShift) // We need to have a special case because CPUs convert a shift by 64 to a no-op. + { + // 1 - 63 + result.mPart0 = (value.mPart0 << nShift); + result.mPart1 = (value.mPart1 << nShift) | (value.mPart0 >> (64 - nShift)); + } + else + { + result.mPart0 = value.mPart0; + result.mPart1 = value.mPart1; + } + } + else + { // 64+ + result.mPart0 = 0; + result.mPart1 = (value.mPart0 << (nShift - 64)); + } + } + else // (nShift < 0) + OperatorShiftRight(value, -nShift, result); +} + + +inline bool int128_t_base::operator!() const +{ + return (mPart0 == 0) && (mPart1 == 0); +} + + +/////////////////////////////////////////////////////////////////////////////// +// OperatorXOR +// +// Returns: value1 ^ value2 into result +// The output 'result' may be the same as one the input. +// +inline void int128_t_base::OperatorXOR(const int128_t_base& value1, const int128_t_base& value2, int128_t_base& result) +{ + result.mPart0 = (value1.mPart0 ^ value2.mPart0); + result.mPart1 = (value1.mPart1 ^ value2.mPart1); +} + + +/////////////////////////////////////////////////////////////////////////////// +// OperatorOR +// +// Returns: value1 | value2 into result +// The output 'result' may be the same as one the input. +// +inline void int128_t_base::OperatorOR(const int128_t_base& value1, const int128_t_base& value2, int128_t_base& result) +{ + result.mPart0 = (value1.mPart0 | value2.mPart0); + result.mPart1 = (value1.mPart1 | value2.mPart1); +} + + +/////////////////////////////////////////////////////////////////////////////// +// OperatorAND +// +// Returns: value1 & value2 into result +// The output 'result' may be the same as one the input. +// +inline void int128_t_base::OperatorAND(const int128_t_base& value1, const int128_t_base& value2, int128_t_base& result) +{ + result.mPart0 = (value1.mPart0 & value2.mPart0); + result.mPart1 = (value1.mPart1 & value2.mPart1); +} + + +inline bool int128_t_base::IsZero() const +{ + return (mPart0 == 0) && // Check mPart0 first as this will likely yield faster execution. + (mPart1 == 0); +} + + +inline void int128_t_base::SetZero() +{ + mPart1 = 0; + mPart0 = 0; +} + + +inline void int128_t_base::TwosComplement() +{ + mPart1 = ~mPart1; + mPart0 = ~mPart0; + + // What we want to do, but isn't available at this level: + // operator++(); + // Alternative: + int128_t_base one((uint32_t)1); + OperatorPlus(*this, one, *this); +} + + +inline void int128_t_base::InverseTwosComplement() +{ + // What we want to do, but isn't available at this level: + // operator--(); + // Alternative: + int128_t_base one((uint32_t)1); + OperatorMinus(*this, one, *this); + + mPart1 = ~mPart1; + mPart0 = ~mPart0; +} + + +inline void int128_t_base::DoubleToUint128(double value) +{ + // Currently this function is limited to 64 bits of integer input. + // We need to make a better version of this function. Perhaps we should implement + // it via dissecting the IEEE floating point format (sign, exponent, matissa). + // EA_ASSERT(fabs(value) < 18446744073709551616.0); // Assert that the input is <= 64 bits of integer. + + mPart1 = 0; + mPart0 = (value >= 0 ? (uint64_t)value : (uint64_t)-value); +} + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// uint128_t implementation +/////////////////////////////////////////////////////////////////////////////////////////////////////// + +inline uint128_t uint128_t::operator^(const uint128_t& other) const +{ + uint128_t temp; + uint128_t::OperatorXOR(*this, other, temp); + return temp; +} + +inline uint128_t uint128_t::operator|(const uint128_t& other) const +{ + uint128_t temp; + uint128_t::OperatorOR(*this, other, temp); + return temp; +} + +inline uint128_t uint128_t::operator&(const uint128_t& other) const +{ + uint128_t temp; + uint128_t::OperatorAND(*this, other, temp); + return temp; +} + +inline uint128_t& uint128_t::operator^=(const uint128_t& value) +{ + OperatorXOR(*this, value, *this); + return *this; +} + +inline uint128_t& uint128_t::operator|=(const uint128_t& value) +{ + OperatorOR(*this, value, *this); + return *this; +} + +inline uint128_t& uint128_t::operator&=(const uint128_t& value) +{ + OperatorAND(*this, value, *this); + return *this; +} + +// With rightward shifts of negative numbers, shift in zero from the left side. +inline uint128_t uint128_t::operator>>(int nShift) const +{ + uint128_t temp; + OperatorShiftRight(*this, nShift, temp); + return temp; +} + +// With rightward shifts of negative numbers, shift in zero from the left side. +inline uint128_t uint128_t::operator<<(int nShift) const +{ + uint128_t temp; + OperatorShiftLeft(*this, nShift, temp); + return temp; +} + +inline uint128_t& uint128_t::operator>>=(int nShift) +{ + uint128_t temp; + OperatorShiftRight(*this, nShift, temp); + *this = temp; + return *this; +} + +inline uint128_t& uint128_t::operator<<=(int nShift) +{ + uint128_t temp; + OperatorShiftLeft(*this, nShift, temp); + *this = temp; + return *this; +} + +inline uint128_t& uint128_t::operator+=(const uint128_t& value) +{ + OperatorPlus(*this, value, *this); + return *this; +} + +inline uint128_t& uint128_t::operator-=(const uint128_t& value) +{ + OperatorMinus(*this, value, *this); + return *this; +} + +inline uint128_t& uint128_t::operator*=(const uint128_t& value) +{ + *this = *this * value; + return *this; +} + +inline uint128_t& uint128_t::operator/=(const uint128_t& value) +{ + *this = *this / value; + return *this; +} + +inline uint128_t& uint128_t::operator%=(const uint128_t& value) +{ + *this = *this % value; + return *this; +} + +inline uint128_t uint128_t::operator+(const uint128_t& other) +{ + uint128_t temp; + uint128_t::OperatorPlus(*this, other, temp); + return temp; +} + +inline uint128_t uint128_t::operator-(const uint128_t& other) +{ + uint128_t temp; + uint128_t::OperatorMinus(*this, other, temp); + return temp; +} + +inline uint128_t uint128_t::operator*(const uint128_t& other) +{ + uint128_t returnValue; + int128_t_base::OperatorMul(*this, other, returnValue); + return returnValue; +} + +inline uint128_t uint128_t::operator/(const uint128_t& other) +{ + uint128_t remainder; + uint128_t quotient; + this->Modulus(other, quotient, remainder); + return quotient; +} + +inline uint128_t uint128_t::operator%(const uint128_t& other) +{ + uint128_t remainder; + uint128_t quotient; + this->Modulus(other, quotient, remainder); + return remainder; +} + +inline uint128_t uint128_t::operator+() const +{ + return *this; +} + +inline uint128_t uint128_t::operator~() const +{ + return uint128_t(~mPart0, ~mPart1); +} + +inline uint128_t& uint128_t::operator--() +{ + int128_t_base one((uint32_t)1); + OperatorMinus(*this, one, *this); + return *this; +} + +inline uint128_t uint128_t::operator--(int) +{ + uint128_t temp((uint32_t)1); + OperatorMinus(*this, temp, temp); + return temp; +} + +inline uint128_t uint128_t::operator++(int) +{ + uint128_t prev = *this; + uint128_t temp((uint32_t)1); + OperatorPlus(*this, temp, *this); + return prev; +} + +inline uint128_t& uint128_t::operator++() +{ + int128_t_base one((uint32_t)1); + OperatorPlus(*this, one, *this); + return *this; +} + +inline void uint128_t::Negate() +{ + TwosComplement(); +} + +inline uint128_t uint128_t::operator-() const +{ + uint128_t returnValue(*this); + returnValue.Negate(); + return returnValue; +} + +// This function forms the basis of all logical comparison functions. +// If value1 < value2, the return value is -1. +// If value1 == value2, the return value is 0. +// If value1 > value2, the return value is 1. +inline int uint128_t::compare(const uint128_t& other) const +{ + // Compare individual parts. At this point, the two numbers have the same sign. + if(mPart1 == other.mPart1) + { + if(mPart0 == other.mPart0) + return 0; + else if(mPart0 > other.mPart0) + return 1; + // return -1; //Just fall through to the end. + } + else if(mPart1 > other.mPart1) + return 1; + return -1; +} + +EA_DISABLE_VC_WARNING(4723) // warning C4723: potential divide by 0 +inline void uint128_t::Modulus(const uint128_t& divisor, uint128_t& quotient, uint128_t& remainder) const +{ + uint128_t tempDividend(*this); + uint128_t tempDivisor(divisor); + + if(tempDivisor.IsZero()) + { + // Force a divide by zero exception. + // We know that tempDivisor.mPart0 is zero. + quotient.mPart0 /= tempDivisor.mPart0; + } + else if(tempDividend.IsZero()) + { + quotient = uint128_t((uint32_t)0); + remainder = uint128_t((uint32_t)0); + } + else + { + remainder.SetZero(); + + for(int i(0); i < 128; i++) + { + remainder += (uint32_t)tempDividend.GetBit(127 - i); + const bool bBit(remainder >= tempDivisor); + quotient.SetBit(127 - i, bBit); + + if(bBit) + remainder -= tempDivisor; + + if((i != 127) && !remainder.IsZero()) + remainder <<= 1; + } + } +} +EA_RESTORE_VC_WARNING() + +inline bool uint128_t::operator==(const uint128_t& other) const +{ + return (mPart0 == other.mPart0) && // Check mPart0 first as this will likely yield faster execution. + (mPart1 == other.mPart1); +} + +inline bool uint128_t::operator< (const uint128_t& other) const { return (compare(other) < 0); } +inline bool uint128_t::operator!=(const uint128_t& other) const { return !(*this == other); } +inline bool uint128_t::operator> (const uint128_t& other) const { return other < *this; } +inline bool uint128_t::operator>=(const uint128_t& other) const { return !(*this < other); } +inline bool uint128_t::operator<=(const uint128_t& other) const { return !(other < *this); } + +inline bool uint128_t::IsNegative() const +{ // True if value < 0 + return false; +} + +inline bool uint128_t::IsPositive() const +{ + // True of value >= 0 + return true; +} + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// int128_t implementation +/////////////////////////////////////////////////////////////////////////////////////////////////////// + +inline void int128_t::Negate() +{ + if (IsPositive()) + TwosComplement(); + else + InverseTwosComplement(); +} + +inline int128_t int128_t::operator-() const +{ + int128_t returnValue(*this); + returnValue.Negate(); + return returnValue; +} + +inline int128_t& int128_t::operator++() +{ + int128_t_base one((uint32_t)1); + OperatorPlus(*this, one, *this); + return *this; +} + +inline int128_t& int128_t::operator--() +{ + int128_t_base one((uint32_t)1); + OperatorMinus(*this, one, *this); + return *this; +} + +inline int128_t int128_t::operator++(int) +{ + int128_t prev = *this; + int128_t temp((uint32_t)1); + OperatorPlus(*this, temp, *this); + return prev; +} + +inline int128_t int128_t::operator--(int) +{ + int128_t temp((uint32_t)1); + OperatorMinus(*this, temp, temp); + return temp; +} + +inline int128_t int128_t::operator+() const +{ + return *this; +} + +inline int128_t int128_t::operator~() const +{ + return int128_t(~mPart0, ~mPart1); +} + +inline int128_t int128_t::operator+(const int128_t& other) +{ + int128_t temp; + int128_t::OperatorPlus(*this, other, temp); + return temp; +} + +inline int128_t int128_t::operator-(const int128_t& other) +{ + int128_t temp; + int128_t::OperatorMinus(*this, other, temp); + return temp; +} + +// This function forms the basis of all logical comparison functions. +// If value1 < value2, the return value is -1. +// If value1 == value2, the return value is 0. +// If value1 > value2, the return value is 1. +inline int int128_t::compare(const int128_t& other) const +{ + // Cache some values. Positive means >= 0. Negative means < 0 and thus means '!positive'. + const bool bValue1IsPositive( IsPositive()); + const bool bValue2IsPositive(other.IsPositive()); + + // Do positive/negative tests. + if(bValue1IsPositive != bValue2IsPositive) + return bValue1IsPositive ? 1 : -1; + + // Compare individual parts. At this point, the two numbers have the same sign. + if(mPart1 == other.mPart1) + { + if(mPart0 == other.mPart0) + return 0; + else if(mPart0 > other.mPart0) + return 1; + // return -1; //Just fall through to the end. + } + else if(mPart1 > other.mPart1) + return 1; + return -1; +} + +inline bool int128_t::operator==(const int128_t& other) const +{ + return (mPart0 == other.mPart0) && // Check mPart0 first as this will likely yield faster execution. + (mPart1 == other.mPart1); +} + +inline bool int128_t::operator!=(const int128_t& other) const +{ + return (mPart0 != other.mPart0) || // Check mPart0 first as this will likely yield faster execution. + (mPart1 != other.mPart1); +} + +inline bool int128_t::operator>(const int128_t& other) const +{ + return (compare(other) > 0); +} + +inline bool int128_t::operator>=(const int128_t& other) const +{ + return (compare(other) >= 0); +} + +inline bool int128_t::operator<(const int128_t& other) const +{ + return (compare(other) < 0); +} + +inline bool int128_t::operator<=(const int128_t& other) const +{ + return (compare(other) <= 0); +} + +inline bool int128_t::IsNegative() const +{ // True if value < 0 + return ((mPart1 & UINT64_C(0x8000000000000000)) != 0); +} + +inline bool int128_t::IsPositive() const +{ // True of value >= 0 + return ((mPart1 & UINT64_C(0x8000000000000000)) == 0); +} + +inline int128_t int128_t::operator*(const int128_t& other) +{ + int128_t a(*this); + int128_t b(other); + int128_t returnValue; + + // Correctly handle negative values + bool bANegative(false); + bool bBNegative(false); + + if(a.IsNegative()) + { + bANegative = true; + a.Negate(); + } + + if(b.IsNegative()) + { + bBNegative = true; + b.Negate(); + } + + int128_t_base::OperatorMul(a, b, returnValue); + + // Do negation as needed. + if(bANegative != bBNegative) + returnValue.Negate(); + + return returnValue; +} + +inline int128_t int128_t::operator/(const int128_t& other) +{ + int128_t remainder; + int128_t quotient; + this->Modulus(other, quotient, remainder); + return quotient; +} + +inline int128_t int128_t::operator<<(int nShift) const +{ + int128_t temp; + OperatorShiftLeft(*this, nShift, temp); + return temp; +} + +inline int128_t& int128_t::operator+=(const int128_t& value) +{ + OperatorPlus(*this, value, *this); + return *this; +} + +inline int128_t& int128_t::operator-=(const int128_t& value) +{ + OperatorMinus(*this, value, *this); + return *this; +} + +inline int128_t& int128_t::operator<<=(int nShift) +{ + int128_t temp; + OperatorShiftLeft(*this, nShift, temp); + *this = temp; + return *this; +} + +inline int128_t& int128_t::operator*=(const int128_t& value) +{ + *this = *this * value; + return *this; +} + +inline int128_t& int128_t::operator%=(const int128_t& value) +{ + *this = *this % value; + return *this; +} + +inline int128_t int128_t::operator%(const int128_t& other) +{ + int128_t remainder; + int128_t quotient; + this->Modulus(other, quotient, remainder); + return remainder; +} + +inline int128_t& int128_t::operator/=(const int128_t& value) +{ + *this = *this / value; + return *this; +} + +// With rightward shifts of negative numbers, shift in zero from the left side. +inline int128_t int128_t::operator>>(int nShift) const +{ + int128_t temp; + OperatorShiftRight(*this, nShift, temp); + return temp; +} + +inline int128_t& int128_t::operator>>=(int nShift) +{ + int128_t temp; + OperatorShiftRight(*this, nShift, temp); + *this = temp; + return *this; +} + +inline int128_t int128_t::operator^(const int128_t& other) const +{ + int128_t temp; + int128_t::OperatorXOR(*this, other, temp); + return temp; +} + +inline int128_t int128_t::operator|(const int128_t& other) const +{ + int128_t temp; + int128_t::OperatorOR(*this, other, temp); + return temp; +} + + +inline int128_t int128_t::operator&(const int128_t& other) const +{ + int128_t temp; + int128_t::OperatorAND(*this, other, temp); + return temp; +} + +inline int128_t& int128_t::operator^=(const int128_t& value) +{ + OperatorXOR(*this, value, *this); + return *this; +} + +inline int128_t& int128_t::operator|=(const int128_t& value) +{ + OperatorOR(*this, value, *this); + return *this; +} + +inline int128_t& int128_t::operator&=(const int128_t& value) +{ + OperatorAND(*this, value, *this); + return *this; +} + +EA_DISABLE_VC_WARNING(4723) // warning C4723: potential divide by 0 +inline void int128_t::Modulus(const int128_t& divisor, int128_t& quotient, int128_t& remainder) const +{ + int128_t tempDividend(*this); + int128_t tempDivisor(divisor); + + bool bDividendNegative = false; + bool bDivisorNegative = false; + + if(tempDividend.IsNegative()) + { + bDividendNegative = true; + tempDividend.Negate(); + } + if(tempDivisor.IsNegative()) + { + bDivisorNegative = true; + tempDivisor.Negate(); + } + + // Handle the special cases + if(tempDivisor.IsZero()) + { + // Force a divide by zero exception. + // We know that tempDivisor.mPart0 is zero. + quotient.mPart0 /= tempDivisor.mPart0; + } + else if(tempDividend.IsZero()) + { + quotient = int128_t((uint32_t)0); + remainder = int128_t((uint32_t)0); + } + else + { + remainder.SetZero(); + + for(int i(0); i < 128; i++) + { + remainder += (uint32_t)tempDividend.GetBit(127 - i); + const bool bBit(remainder >= tempDivisor); + quotient.SetBit(127 - i, bBit); + + if(bBit) + remainder -= tempDivisor; + + if((i != 127) && !remainder.IsZero()) + remainder <<= 1; + } + } + + if((bDividendNegative && !bDivisorNegative) || (!bDividendNegative && bDivisorNegative)) + { + // Ensure the following formula applies for negative dividends + // dividend = divisor * quotient + remainder + quotient.Negate(); + } +} +EA_RESTORE_VC_WARNING() + + + + + + +/////////////////////////////////////////////////////////////////////////////////////////////////////// +// INT128_C / UINT128_C +// +// The C99 language defines macros for portably defining constants of +// sized numeric types. For example, there might be: +// #define UINT64_C(x) x##ULL +// Since our int128 data type is not a built-in type, we can't define a +// UINT128_C macro as something that pastes ULLL at the end of the digits. +// Instead we define it to create a temporary that is constructed from a +// string of the digits. This will work in most cases that suffix pasting +// would work. +// +/* EA_CONSTEXPR */ inline uint128_t UINT128_C(uint64_t nPart1, uint64_t nPart0) { return uint128_t(nPart0, nPart1); } +/* EA_CONSTEXPR */ inline int128_t INT128_C(int64_t nPart1, int64_t nPart0) { return int128_t(static_cast<uint64_t>(nPart0), static_cast<uint64_t>(nPart1)); } + + + + +#endif // INCLUDED_int128_h + diff --git a/include/Common/EABase/nullptr.h b/include/Common/EABase/nullptr.h new file mode 100644 index 0000000..d6629d5 --- /dev/null +++ b/include/Common/EABase/nullptr.h @@ -0,0 +1,102 @@ +/*----------------------------------------------------------------------------- + * nullptr.h + * + * Copyright (c) Electronic Arts Inc. All rights reserved. + *---------------------------------------------------------------------------*/ + + +#include <EABase/eabase.h> +#include <EABase/eahave.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 + + +#if defined(EA_COMPILER_CPP11_ENABLED) && !defined(EA_COMPILER_NO_NULLPTR) && !defined(EA_HAVE_nullptr_t_IMPL) + // The compiler supports nullptr, but the standard library doesn't implement a declaration for std::nullptr_t. So we provide one. + namespace std { typedef decltype(nullptr) nullptr_t; } +#endif + + + +#if defined(EA_COMPILER_NO_NULLPTR) // If the compiler lacks a native version... + + namespace std + { + class nullptr_t + { + public: + template<class T> // When tested a pointer, acts as 0. + operator T*() const + { return 0; } + + template<class C, class T> // When tested as a member pointer, acts as 0. + operator T C::*() const + { return 0; } + + typedef void* (nullptr_t::*bool_)() const; + operator bool_() const // An rvalue of type std::nullptr_t can be converted to an rvalue of type bool; the resulting value is false. + { return false; } // We can't use operator bool(){ return false; } because bool is convertable to int which breaks other required functionality. + + // We can't enable this without generating warnings about nullptr being uninitialized after being used when created without "= {}". + //void* mSizeofVoidPtr; // sizeof(nullptr_t) == sizeof(void*). Needs to be public if nullptr_t is to be a POD. + + private: + void operator&() const; // Address cannot be taken. + }; + + inline nullptr_t nullptr_get() + { + nullptr_t n = { }; // std::nullptr exists. + return n; + } + + #if !defined(nullptr) // If somebody hasn't already defined nullptr in a custom way... + #define nullptr nullptr_get() + #endif + + } // namespace std + + + template<class T> + inline bool operator==(T* p, const std::nullptr_t) + { return p == 0; } + + template<class T> + inline bool operator==(const std::nullptr_t, T* p) + { return p == 0; } + + template<class T, class U> + inline bool operator==(T U::* p, const std::nullptr_t) + { return p == 0; } + + template<class T, class U> + inline bool operator==(const std::nullptr_t, T U::* p) + { return p == 0; } + + inline bool operator==(const std::nullptr_t, const std::nullptr_t) + { return true; } + + inline bool operator!=(const std::nullptr_t, const std::nullptr_t) + { return false; } + + inline bool operator<(const std::nullptr_t, const std::nullptr_t) + { return false; } + + inline bool operator>(const std::nullptr_t, const std::nullptr_t) + { return false; } + + inline bool operator<=(const std::nullptr_t, const std::nullptr_t) + { return true; } + + inline bool operator>=(const std::nullptr_t, const std::nullptr_t) + { return true; } + + + using std::nullptr_t; // exported to global namespace. + using std::nullptr_get; // exported to global namespace. + +#endif // EA_COMPILER_NO_NULLPTR + diff --git a/include/Common/EABase/version.h b/include/Common/EABase/version.h new file mode 100644 index 0000000..b6e1b66 --- /dev/null +++ b/include/Common/EABase/version.h @@ -0,0 +1,36 @@ +/*----------------------------------------------------------------------------- + * version.h + * + * Copyright (c) Electronic Arts Inc. All rights reserved. + *---------------------------------------------------------------------------*/ + +#ifndef INCLUDED_EABASE_VERSION_H +#define INCLUDED_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.09.12" + #define EABASE_VERSION_N 20912 +#endif + +#endif |