Skip to content

Instantly share code, notes, and snippets.

@antekone
Created March 17, 2017 14:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save antekone/147f7042b6cba7f77f8c7853178a2f5a to your computer and use it in GitHub Desktop.
Save antekone/147f7042b6cba7f77f8c7853178a2f5a to your computer and use it in GitHub Desktop.
#pragma once
#define NAMESPACE_ENDIANCONVERSION_BEGIN namespace EndianConversion {
#define NAMESPACE_ENDIANCONVERSION_END }
#include <stdint.h>
// __BYTE_ORDER__ is a gcc macro
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define __LESWAP(n, x) x
#define __BESWAP(n, x) doBSwap ## n(x)
#else
#define __LESWAP(n, x) doBSwap ## n(x)
#define __BESWAP(n, x) x
#endif
NAMESPACE_ENDIANCONVERSION_BEGIN
constexpr uint64_t inC64(uint64_t c) {
return ((c >> 32) & 0x00000000FFFFFFFF) |
((c << 32) & 0xFFFFFFFF00000000);
}
constexpr uint64_t inB64(uint64_t b) {
return ((b >> 16) & 0x0000FFFF0000FFFF) |
((b << 16) & 0xFFFF0000FFFF0000);
}
constexpr uint64_t inA64(uint64_t a) {
return ((a >> 8) & 0x00FF00FF00FF00FF) |
((a << 8) & 0xFF00FF00FF00FF00);
}
constexpr uint32_t inB32(uint32_t b) {
return ((b >> 16) & 0x0000FFFF) |
((b << 16) & 0xFFFF0000);
}
constexpr uint32_t inA32(uint32_t a) {
return ((a >> 8) & 0x00FF00FF) |
((a << 8) & 0xFF00FF00);
}
constexpr uint16_t inA16(uint16_t a) {
return ((a >> 8) & 0x00FF) |
((a << 8) & 0xFF00);
}
// This gets compiled to 1 instruction on g++ -O2 and clang++ -O1, placed
// inline in the caller code.
//
// 31 b: 48 0f c8 bswap %rax
constexpr uint64_t doBSwap64(uint64_t in) { return inA64(inB64(inC64(in))); }
// 31 b: 48 0f c8 bswap %eax
constexpr uint32_t doBSwap32(uint32_t in) { return inA32(inB32(in)); }
// 12 b: 66 c1 c0 08 rol $0x8,%ax
constexpr uint32_t doBSwap16(uint16_t in) { return inA16(in); }
inline uint64_t systemToLittle64(uint64_t in) { return __LESWAP(64, in); }
inline uint32_t systemToLittle32(uint32_t in) { return __LESWAP(32, in); }
inline uint16_t systemToLittle16(uint16_t in) { return __LESWAP(16, in); }
inline uint64_t systemToBig64(uint64_t in) { return __BESWAP(64, in); }
inline uint32_t systemToBig32(uint32_t in) { return __BESWAP(32, in); }
inline uint16_t systemToBig16(uint16_t in) { return __BESWAP(16, in); }
inline uint64_t littleToSystem64(uint64_t in) { return __LESWAP(64, in); }
inline uint32_t littleToSystem32(uint32_t in) { return __LESWAP(32, in); }
inline uint16_t littleToSystem16(uint16_t in) { return __LESWAP(16, in); }
inline uint64_t bigToSystem64(uint64_t in) { return __BESWAP(64, in); }
inline uint32_t bigToSystem32(uint32_t in) { return __BESWAP(32, in); }
inline uint16_t bigToSystem16(uint16_t in) { return __BESWAP(16, in); }
#undef __LIB_LE
// If these static_asserts fail, you have a problem with your compiler.
static_assert(0x3412 == doBSwap16(0x1234));
static_assert(0x2193 == doBSwap16(0x9321));
static_assert(0x78563412 == doBSwap32(0x12345678));
static_assert(0x21436587 == doBSwap32(0x87654321));
static_assert(0x7856341278563412 == doBSwap64(0x1234567812345678));
static_assert(0x2143658721436587 == doBSwap64(0x8765432187654321));
NAMESPACE_ENDIANCONVERSION_END
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment