Skip to content

Instantly share code, notes, and snippets.

@Pibben
Created February 11, 2021 10:42
Show Gist options
  • Save Pibben/a7afdf022427fc72db8f2435f75bc149 to your computer and use it in GitHub Desktop.
Save Pibben/a7afdf022427fc72db8f2435f75bc149 to your computer and use it in GitHub Desktop.
#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