Fall back to naive built-in byte-swap routines

EL5 lacks htobe64 and friends.  Using its byteswap.h requires an endianness
check in our headers, which is fragile and compiler-dependent.  It's a fair
amount of code [1], and is only useful on EL5.

So instead, let's include a fallback implementation of these functions, and use
it whenever we can't find the (now-)standard Linux or OS X routines.  The
fallback is endianness-independent and should work on any platform.

[1] https://github.com/rurban/mosh/commit/da1a5abd1e09f0c1e9295357bb480a643d9dc8e3
This commit is contained in:
Keegan McAllister
2012-04-13 16:44:00 -04:00
committed by Keith Winstein
parent 85d197346a
commit c2a5941f88
2 changed files with 73 additions and 1 deletions
+1 -1
View File
@@ -272,7 +272,7 @@ AC_CHECK_DECL([htobe64],
[AC_CHECK_DECL([OSSwapHostToBigInt64], [AC_CHECK_DECL([OSSwapHostToBigInt64],
[AC_DEFINE([HAVE_OSX_SWAP], [1], [AC_DEFINE([HAVE_OSX_SWAP], [1],
[Define if OSSwapHostToBigInt64 and friends exist.])], [Define if OSSwapHostToBigInt64 and friends exist.])],
[AC_MSG_ERROR([Unable to find byte swapping functions])], [AC_MSG_WARN([Unable to find byte swapping functions; using built-in routines.])],
[[#include <libkern/OSByteOrder.h>]])], [[#include <libkern/OSByteOrder.h>]])],
[[#if defined(HAVE_ENDIAN_H) [[#if defined(HAVE_ENDIAN_H)
#include <endian.h> #include <endian.h>
+72
View File
@@ -27,12 +27,84 @@
# elif defined(HAVE_SYS_ENDIAN_H) # elif defined(HAVE_SYS_ENDIAN_H)
# include <sys/endian.h> # include <sys/endian.h>
# endif # endif
#elif HAVE_OSX_SWAP #elif HAVE_OSX_SWAP
# include <libkern/OSByteOrder.h> # include <libkern/OSByteOrder.h>
# define htobe64 OSSwapHostToBigInt64 # define htobe64 OSSwapHostToBigInt64
# define be64toh OSSwapBigToHostInt64 # define be64toh OSSwapBigToHostInt64
# define htobe16 OSSwapHostToBigInt16 # define htobe16 OSSwapHostToBigInt16
# define be16toh OSSwapBigToHostInt16 # define be16toh OSSwapBigToHostInt16
#else
/* Use our fallback implementation, which is correct for any endianness. */
#include <stdint.h>
/* Make sure they aren't macros */
#undef htobe64
#undef be64toh
#undef htobe16
#undef be16toh
/* Use unions rather than casts, to comply with strict aliasing rules. */
inline uint64_t htobe64( uint64_t x ) {
uint8_t xs[ 8 ] = {
( x >> 56 ) & 0xFF,
( x >> 48 ) & 0xFF,
( x >> 40 ) & 0xFF,
( x >> 32 ) & 0xFF,
( x >> 24 ) & 0xFF,
( x >> 16 ) & 0xFF,
( x >> 8 ) & 0xFF,
x & 0xFF };
union {
const uint8_t *p8;
const uint64_t *p64;
} u;
u.p8 = xs;
return *u.p64;
}
inline uint64_t be64toh( uint64_t x ) {
union {
const uint8_t *p8;
const uint64_t *p64;
} u;
u.p64 = &x;
return ( uint64_t( u.p8[ 0 ] ) << 56 )
| ( uint64_t( u.p8[ 1 ] ) << 48 )
| ( uint64_t( u.p8[ 2 ] ) << 40 )
| ( uint64_t( u.p8[ 3 ] ) << 32 )
| ( uint64_t( u.p8[ 4 ] ) << 24 )
| ( uint64_t( u.p8[ 5 ] ) << 16 )
| ( uint64_t( u.p8[ 6 ] ) << 8 )
| ( uint64_t( u.p8[ 7 ] ) );
}
inline uint16_t htobe16( uint16_t x ) {
uint8_t xs[ 2 ] = {
( x >> 8 ) & 0xFF,
x & 0xFF };
union {
const uint8_t *p8;
const uint16_t *p16;
} u;
u.p8 = xs;
return *u.p16;
}
inline uint16_t be16toh( uint16_t x ) {
union {
const uint8_t *p8;
const uint16_t *p16;
} u;
u.p16 = &x;
return ( uint16_t( u.p8[ 0 ] ) << 8 )
| ( uint16_t( u.p8[ 1 ] ) );
}
#endif #endif
#endif #endif