A
Aaron Graham
/**
* Sample usage:
* unsigned long longvar = 0x12345678;
* unsigned long be_longvar = endian::host_to_big(longvar);
* unsigned short shortvar = 0x1234;
* unsigned short le_shortvar = endian::host_to_little(shortvar);
*/
// for std::reverse:
#include <algorithm>
#include <limits>
// for endian information:
#include <endian.h>
// Linux uses __BYTE_ORDER
// FreeBSD and Apple/Darwin use _BYTE_ORDER
// Some other BSD variants use BYTE_ORDER
#if (defined __BYTE_ORDER && __BYTE_ORDER==__BIG_ENDIAN) || \
(defined _BYTE_ORDER && _BYTE_ORDER== _BIG_ENDIAN) || \
(defined BYTE_ORDER && BYTE_ORDER== BIG_ENDIAN)
#define IS_BIG_ENDIAN 1
#else
#define IS_BIG_ENDIAN 0
#endif
namespace endian {
// This function will copy the supplied value and return a byte-swapped
// version of it. This function may/should be optimized for specific
// architectures when necessary. It may also be necessary to create
// partial specializations for certain types, since the current state
// of this function only allows some fundamental types to be swapped.
template <typename _type>
_type byteswap(_type val) {
if (std::numeric_limits<_type>::is_specialized &&
!std::numeric_limits<_type>::is_signed) {
// Found a type that is specialized and is unsigned.
switch (sizeof(_type)) {
case 1:
return val;
case 2:
return ((val & 0x00ff) << 8) | ((val & 0xff00) >> 8);
case 4:
return ((val & 0x000000ff) << 24) | ((val & 0x0000ff00) << 8) |
((val & 0x00ff0000) >> 8) | ((val & 0xff000000) >> 24);
}
}
// Swap this type using a different/fallback/hacky method:
unsigned char* v = reinterpret_cast<unsigned char*>(&val);
std::reverse(v, v + sizeof(_type));
return val;
}
template <typename _type>
_type host_to_big(_type val) {
return IS_BIG_ENDIAN ? val : byteswap(val);
}
template <typename _type>
_type host_to_little(_type val) {
return IS_BIG_ENDIAN ? byteswap(val) : val;
}
template <typename _type>
_type big_to_host(_type val) {
return IS_BIG_ENDIAN ? val : byteswap(val);
}
template <typename _type>
_type little_to_host(_type val) {
return IS_BIG_ENDIAN ? byteswap(val) : val;
}
} // end namespace endian
// Don't need this definition anymore:
#undef IS_BIG_ENDIAN
* Sample usage:
* unsigned long longvar = 0x12345678;
* unsigned long be_longvar = endian::host_to_big(longvar);
* unsigned short shortvar = 0x1234;
* unsigned short le_shortvar = endian::host_to_little(shortvar);
*/
// for std::reverse:
#include <algorithm>
#include <limits>
// for endian information:
#include <endian.h>
// Linux uses __BYTE_ORDER
// FreeBSD and Apple/Darwin use _BYTE_ORDER
// Some other BSD variants use BYTE_ORDER
#if (defined __BYTE_ORDER && __BYTE_ORDER==__BIG_ENDIAN) || \
(defined _BYTE_ORDER && _BYTE_ORDER== _BIG_ENDIAN) || \
(defined BYTE_ORDER && BYTE_ORDER== BIG_ENDIAN)
#define IS_BIG_ENDIAN 1
#else
#define IS_BIG_ENDIAN 0
#endif
namespace endian {
// This function will copy the supplied value and return a byte-swapped
// version of it. This function may/should be optimized for specific
// architectures when necessary. It may also be necessary to create
// partial specializations for certain types, since the current state
// of this function only allows some fundamental types to be swapped.
template <typename _type>
_type byteswap(_type val) {
if (std::numeric_limits<_type>::is_specialized &&
!std::numeric_limits<_type>::is_signed) {
// Found a type that is specialized and is unsigned.
switch (sizeof(_type)) {
case 1:
return val;
case 2:
return ((val & 0x00ff) << 8) | ((val & 0xff00) >> 8);
case 4:
return ((val & 0x000000ff) << 24) | ((val & 0x0000ff00) << 8) |
((val & 0x00ff0000) >> 8) | ((val & 0xff000000) >> 24);
}
}
// Swap this type using a different/fallback/hacky method:
unsigned char* v = reinterpret_cast<unsigned char*>(&val);
std::reverse(v, v + sizeof(_type));
return val;
}
template <typename _type>
_type host_to_big(_type val) {
return IS_BIG_ENDIAN ? val : byteswap(val);
}
template <typename _type>
_type host_to_little(_type val) {
return IS_BIG_ENDIAN ? byteswap(val) : val;
}
template <typename _type>
_type big_to_host(_type val) {
return IS_BIG_ENDIAN ? val : byteswap(val);
}
template <typename _type>
_type little_to_host(_type val) {
return IS_BIG_ENDIAN ? byteswap(val) : val;
}
} // end namespace endian
// Don't need this definition anymore:
#undef IS_BIG_ENDIAN