#pragma once
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
|
|
namespace gp{
|
|
namespace _impl{
|
|
constexpr uint32_t uint32_ = 0x01020304;
|
|
constexpr uint8_t magic_ = (const uint8_t&)uint32_;
|
|
}
|
|
|
|
enum class endian : uint16_t
|
|
{
|
|
#ifdef _WIN32
|
|
little = 0,
|
|
big = 1,
|
|
native = little
|
|
#elseif defined(__BYTE_ORDER__)
|
|
little = __ORDER_LITTLE_ENDIAN__,
|
|
big = __ORDER_BIG_ENDIAN__,
|
|
native = __BYTE_ORDER__
|
|
#else
|
|
little = true,
|
|
big = false,
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wfour-char-constants"
|
|
#pragma gcc diagnostic push
|
|
#pragma gcc diagnostic ignored "-Wfour-char-constants"
|
|
native = ('ABCD'==0x41424344UL)
|
|
#pragma gcc diagnostic pop
|
|
#pragma clang diagnostic pop
|
|
#endif
|
|
};
|
|
|
|
|
|
template <typename T>
|
|
T swap_endian(T value)
|
|
{
|
|
union
|
|
{
|
|
T v;
|
|
uint8_t u8[sizeof(T)];
|
|
} src, dest;
|
|
|
|
src.v = value;
|
|
|
|
for (size_t idx = 0;idx<sizeof(T);idx++)
|
|
{
|
|
dest.u8[idx] = src.u8[sizeof(T)-idx-1];
|
|
}
|
|
|
|
return dest.v;
|
|
}
|
|
|
|
template<typename T, endian mode = endian::big>
|
|
struct endian_wrapper {
|
|
T value;
|
|
endian_wrapper(){};
|
|
endian_wrapper(T v) : value{
|
|
mode == endian::native ? v : swap_endian(v)
|
|
}{}
|
|
endian_wrapper(endian_wrapper& v) : value{
|
|
v.value
|
|
}{}
|
|
|
|
endian_wrapper& operator=(T p) {
|
|
value = mode == endian::native ? p : swap_endian(p);
|
|
return *this;
|
|
}
|
|
|
|
operator T(){
|
|
return mode == endian::native ? value : swap_endian(value);
|
|
}
|
|
};
|
|
}
|