From: Dale Weiler Date: Thu, 20 Dec 2012 23:07:06 +0000 (+0000) Subject: Implemented roboust compile-time endianess check. X-Git-Tag: 0.2~34 X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=commitdiff_plain;h=e1f0e40341c3d82264c42626813b9e5142faf53c Implemented roboust compile-time endianess check. --- diff --git a/gmqcc.h b/gmqcc.h index 1adcd52..65a1fad 100644 --- a/gmqcc.h +++ b/gmqcc.h @@ -139,6 +139,88 @@ # include #endif +/* + * Very roboust way at determining endianess at compile time: this handles + * almost every possible situation. Otherwise a runtime check has to be + * performed. + */ +#define GMQCC_BYTE_ORDER_LITTLE 1234 +#define GMQCC_BYTE_ORDER_BIG 4321 + +#if defined (__GNUC__) || defined (__GNU_LIBRARY__) +# if defined (__FreeBSD__) || defined (__OpenBSD__) +# include +# elif defined (BSD) && (BSD >= 199103) || defined (__DJGPP__) || defined (__CYGWIN32__) +# include +# elif defined (__APPLE__) +# if defined (__BIG_ENDIAN__) && !defined(BIG_ENDIAN) +# define BIG_ENDIAN +# elif defined (__LITTLE_ENDIAN__) && !defined (LITTLE_ENDIAN) +# define LITTLE_ENDIAN +# endif +# elif !defined (__MINGW32__) +# include +# if !defined (__BEOS__) +# include +# endif +# endif +#endif +#if !defined(PLATFORM_BYTE_ORDER) +# if defined (LITTLE_ENDIAN) || defined (BIG_ENDIAN) +# if defined (LITTLE_ENDIAN) && !defined(BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE +# elif !defined (LITTLE_ENDIAN) && defined (BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_BIG +# elif defined (BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN) +# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE +# elif defined (BYTE_ORDER) && (BYTE_ORDER == BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_BIG +# endif +# elif defined (_LITTLE_ENDIAN) || defined (_BIG_ENDIAN) +# if defined (_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE +# elif !defined (_LITTLE_ENDIAN) && defined (_BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_BIG +# elif defined (_BYTE_ORDER) && (_BYTE_ORDER == _LITTLE_ENDIAN) +# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE +# elif defined (_BYTE_ORDER) && (_BYTE_ORDER == _BIG_ENDIAN) +# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_BIG +# endif +# elif defined (__LITTLE_ENDIAN__) || defined (__BIG_ENDIAN__) +# if defined (__LITTLE_ENDIAN__) && !defined (__BIG_ENDIAN__) +# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE +# elif !defined (__LITTLE_ENDIAN__) && defined (__BIG_ENDIAN__) +# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_BIG +# elif defined (__BYTE_ORDER__) && (__BYTE_ORDER__ == __LITTLE_ENDIAN__) +# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE +# elif defined (__BYTE_ORDER__) && (__BYTE_ORDER__ == __BIG_ENDIAN__) +# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_BIG +# endif +# endif +#endif +#if !defined (PLATFORM_BYTE_ORDER) +# if defined (__aplha__) || defined (__aplha) || defined (i386) || \ + defined (__i386__) || defined (_M_I86) || defined (_M_IX86) || \ + defined (__OS2__) || defined (sun386) || defined (__TURBOC__) || \ + defined (vax) || defined (vms) || defined (VMS) || \ + defined (__VMS) || defined (__x86_64__) || defined (_M_IA64) || \ + defined (_M_X64) || defined (__i386) || defined (__x86_64) +# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_LITTLE +# elif defined (AMIGA) || defined (applec) || defined (__AS400__) || \ + defined (_CRAY) || defined (__hppa) || defined (__hp9000) || \ + defined (ibm370) || defined (mc68000) || defined (m68k) || \ + defined (__MRC__) || defined (__MVS__) || defined (__MWERKS__) || \ + defined (sparc) || defined (__sparc) || defined (SYMANTEC_C) || \ + defined (__TANDEM) || defined (THINK_C) || defined (__VMCMS__) || \ + defined (__PPC__) || defined (__PPC) || defined (PPC) +# define PLATFORM_BYTE_ORDER GMQCC_BYTE_ORDER_BIG +# else +# define PLATFORM_BYTE_ORDER -1 +# endif +#endif + + + /*===================================================================*/ /*=========================== util.c ================================*/ /*===================================================================*/ diff --git a/util.c b/util.c index 03cf40e..d277ae4 100644 --- a/util.c +++ b/util.c @@ -283,61 +283,76 @@ void util_endianswap(void *m, int s, int l) { } #endif -static void util_swap16(uint16_t *d, size_t l) { - while (l--) { - d[l] = (d[l] << 8) | (d[l] >> 8); +/* + * only required if big endian .. otherwise no need to swap + * data. + */ +#if PLATFORM_BYTE_ORDER == GMQCC_BYTE_ORDER_BIG + static void util_swap16(uint16_t *d, size_t l) { + while (l--) { + d[l] = (d[l] << 8) | (d[l] >> 8); + } } -} -static void util_swap32(uint32_t *d, size_t l) { - while (l--) { - uint32_t v; - v = ((d[l] << 8) & 0xFF00FF00) | ((d[l] >> 8) & 0x00FF00FF); - d[l] = (v << 16) | (v >> 16); + static void util_swap32(uint32_t *d, size_t l) { + while (l--) { + uint32_t v; + v = ((d[l] << 8) & 0xFF00FF00) | ((d[l] >> 8) & 0x00FF00FF); + d[l] = (v << 16) | (v >> 16); + } } -} -/* Some strange system doesn't like constants that big, AND doesn't recognize an ULL suffix - * so let's go the safe way - */ -static void util_swap64(uint32_t *d, size_t l) { - /* - while (l--) { - uint64_t v; - v = ((d[l] << 8) & 0xFF00FF00FF00FF00) | ((d[l] >> 8) & 0x00FF00FF00FF00FF); - v = ((v << 16) & 0xFFFF0000FFFF0000) | ((v >> 16) & 0x0000FFFF0000FFFF); - d[l] = (v << 32) | (v >> 32); - } - */ - size_t i; - for (i = 0; i < l; i += 2) { - uint32_t v1 = d[i]; - d[i] = d[i+1]; - d[i+1] = v1; - util_swap32(d+i, 2); + /* Some strange system doesn't like constants that big, AND doesn't recognize an ULL suffix + * so let's go the safe way + */ + static void util_swap64(uint32_t *d, size_t l) { + /* + while (l--) { + uint64_t v; + v = ((d[l] << 8) & 0xFF00FF00FF00FF00) | ((d[l] >> 8) & 0x00FF00FF00FF00FF); + v = ((v << 16) & 0xFFFF0000FFFF0000) | ((v >> 16) & 0x0000FFFF0000FFFF); + d[l] = (v << 32) | (v >> 32); + } + */ + size_t i; + for (i = 0; i < l; i += 2) { + uint32_t v1 = d[i]; + d[i] = d[i+1]; + d[i+1] = v1; + util_swap32(d+i, 2); + } } -} +#endif void util_endianswap(void *_data, size_t length, unsigned int typesize) { - /* I'm guessing there's no GOOD way to do this at compile time: - * FIXME: - */ +# if PLATFORM_BYTE_ORDER == -1 /* runtime check */ if (*((char*)&typesize)) return; - if (typesize == 1) - return; - if (typesize == 2) { - util_swap16((uint16_t*)_data, length>>1); - return; - } - if (typesize == 4) { - util_swap32((uint32_t*)_data, length>>2); - return; - } - if (typesize == 4) { - util_swap64((uint32_t*)_data, length>>3); +#else + /* prevent unused warnings */ + (void) _data; + (void) length; + (void) typesize; + +# if PLATFORM_BYTE_ORDER == GMQCC_BYTE_ORDER_LITTLE return; - } +# else + switch (typesize) { + case 1: return; + case 2: + util_swap16((uint16_t*)_data, length>>1); + return; + case 4: + util_swap32((uint32_t*)_data, length>>2); + return; + case 8: + util_swap64((uint32_t*)_data, length>>3); + return; + + default: abort(); /* please blow the fuck up! */ + } +# endif +#endif } /*