mirror of
https://github.com/DarkPlacesEngine/gmqcc.git
synced 2025-01-19 06:40:49 +00:00
Implemented roboust compile-time endianess check.
This commit is contained in:
parent
5375400e85
commit
e1f0e40341
2 changed files with 142 additions and 45 deletions
82
gmqcc.h
82
gmqcc.h
|
@ -139,6 +139,88 @@
|
|||
# include <stdint.h>
|
||||
#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 <sys/endian.h>
|
||||
# elif defined (BSD) && (BSD >= 199103) || defined (__DJGPP__) || defined (__CYGWIN32__)
|
||||
# include <machine/endiane.h>
|
||||
# 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 <endian.h>
|
||||
# if !defined (__BEOS__)
|
||||
# include <byteswap.h>
|
||||
# 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 ================================*/
|
||||
/*===================================================================*/
|
||||
|
|
105
util.c
105
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);
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
*/
|
||||
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)
|
||||
#else
|
||||
/* prevent unused warnings */
|
||||
(void) _data;
|
||||
(void) length;
|
||||
(void) typesize;
|
||||
|
||||
# if PLATFORM_BYTE_ORDER == GMQCC_BYTE_ORDER_LITTLE
|
||||
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);
|
||||
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
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue