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