-
-
Save Pibben/a7afdf022427fc72db8f2435f75bc149 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifdef _MSC_VER | |
#include <Windows.h> | |
#endif | |
#ifdef __BYTE_ORDER__ | |
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ | |
#define IS_BIG_ENDIAN 0 | |
#else | |
#define IS_BIG_ENDIAN 1 | |
#endif | |
#elif defined(_MSC_VER) | |
#define IS_BIG_ENDIAN 0 | |
#else | |
#error "Could not determine endianness" | |
#endif | |
uint16_t swapEndian16(uint16_t value) { | |
#ifdef __GNUC__ | |
return __builtin_bswap16(value); | |
#elif defined(_MSC_VER) | |
return _byteswap_ushort(value); | |
#else | |
return (value >> 8) | (value << 8); | |
#endif | |
} | |
uint32_t swapEndian32(uint32_t value) { | |
#ifdef __GNUC__ | |
return __builtin_bswap32(value); | |
#elif defined(_MSC_VER) | |
return _byteswap_ulong(value); | |
#else | |
value = ((value << 8) & 0xFF00FF00) | ((value >> 8) & 0xFF00FF); | |
return (tmp << 16) | (tmp >> 16); | |
#endif | |
} | |
uint64_t swapEndian64(uint64_t value) { | |
#ifdef __GNUC__ | |
return __builtin_bswap64(value); | |
#elif defined(_MSC_VER) | |
return _byteswap_uint64(value); | |
#else | |
value = ((value & 0x00000000FFFFFFFFull) << 32) | ((value & 0xFFFFFFFF00000000ull) >> 32); | |
value = ((value & 0x0000FFFF0000FFFFull) << 16) | ((value & 0xFFFF0000FFFF0000ull) >> 16); | |
value = ((value & 0x00FF00FF00FF00FFull) << 8) | ((value & 0xFF00FF00FF00FF00ull) >> 8); | |
return value; | |
#endif | |
} | |
struct StringSource { | |
std::string mStr = {(char)0xff, 32, 1, 19}; | |
size_t pos{}; | |
std::optional<size_t> read(size_t n, uint8_t* dst) { | |
std::copy(mStr.data() + pos, mStr.data() + pos + n, dst); | |
pos += n; | |
return n; | |
} | |
}; | |
struct NativeEndianConverter { | |
static uint16_t convert(uint16_t val) { | |
return val; | |
} | |
static uint32_t convert(uint32_t val) { | |
return val; | |
} | |
}; | |
struct OppositeEndianConverter { | |
template <class T> | |
static T convert(T) { | |
assert(0); | |
return 0; | |
} | |
static uint16_t convert(uint16_t val) { | |
return swapEndian16(val); | |
} | |
static uint32_t convert(uint32_t val) { | |
return swapEndian32(val); | |
} | |
}; | |
#if IS_BIG_ENDIAN == 1 | |
using BigEndianConverter = NativeEndianConverter; | |
#else | |
using BigEndianConverter = OppositeEndianConverter; | |
#endif | |
#undef IS_BIG_ENDIAN | |
template <class Src, class EndianConverter = NativeEndianConverter> | |
struct InputStream { | |
InputStream(const Src& src) : mSrc(src) {} | |
Src mSrc; | |
std::pair<uint8_t, bool> readUint8() { | |
uint8_t retval; | |
const auto res = mSrc.read(1, &retval); | |
return {retval, res && *res == 1}; | |
} | |
std::pair<int8_t, bool> readInt8() { | |
return readUint8(); | |
} | |
std::pair<uint16_t, bool> readUint16() { | |
uint16_t retval; | |
const auto res = mSrc.read(sizeof(uint16_t), reinterpret_cast<uint8_t*>(&retval)); | |
retval = EndianConverter::convert(retval); | |
return {retval, res && *res == sizeof(uint16_t)}; | |
} | |
std::pair<int16_t, bool> readInt16() { | |
return readUint16(); | |
} | |
std::pair<uint32_t, bool> readUint32() { | |
uint32_t retval; | |
const auto res = mSrc.read(sizeof(uint32_t), reinterpret_cast<uint8_t*>(&retval)); | |
retval = EndianConverter::convert(retval); | |
return {retval, res && *res == sizeof(uint32_t)}; | |
} | |
std::pair<int32_t, bool> readInt32() { | |
return readUint32(); | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment