#pragma once
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <array>
|
|
#include <algorithm>
|
|
|
|
#if __cplusplus <= 201703L
|
|
namespace _hidden{
|
|
enum class endian
|
|
{
|
|
#ifdef _WIN32
|
|
little = 0,
|
|
big = 1,
|
|
native = little
|
|
#else
|
|
little = __ORDER_LITTLE_ENDIAN__,
|
|
big = __ORDER_BIG_ENDIAN__,
|
|
native = __BYTE_ORDER__
|
|
#endif
|
|
};
|
|
}
|
|
namespace bitops{
|
|
using endian = _hidden::endian;
|
|
}
|
|
#else
|
|
#include <type_traits>
|
|
namespace bitops{
|
|
using endian = std::endian;
|
|
}
|
|
#endif
|
|
|
|
namespace bitops{
|
|
|
|
template<typename T, size_t sz = sizeof(T)>
|
|
constexpr std::array<uint8_t,sizeof(T)> swap_if_little_raw(T xsz)
|
|
{
|
|
std::array<uint8_t,sizeof(T)> ret = {0};
|
|
|
|
auto abstract = (std::array<uint8_t,sizeof(T)>*)&xsz;
|
|
if constexpr (endian::native == endian::little)
|
|
{
|
|
std::copy(abstract->rbegin(), abstract->rend(), ret.begin());
|
|
}
|
|
else
|
|
{
|
|
std::copy(abstract->begin(), abstract->end(), ret.begin());
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
template<typename T, size_t sz = sizeof(T)>
|
|
constexpr T swap_if_little(T xsz)
|
|
{
|
|
auto tmp = swap_if_little_raw(xsz);
|
|
return *(T*)&tmp;
|
|
}
|
|
|
|
template<typename T>
|
|
struct [[gnu::packed]] regulated{
|
|
T internal = 0;
|
|
|
|
constexpr regulated(T value)
|
|
: internal{swap_if_little(value)}
|
|
{ }
|
|
|
|
constexpr void operator=(T value)
|
|
{
|
|
internal = swap_if_little(value);
|
|
}
|
|
|
|
template<typename Ta>
|
|
constexpr void operator+=(const Ta& v)
|
|
{
|
|
internal = swap_if_little(T(*this)+(T)v);
|
|
}
|
|
|
|
constexpr operator T() const {
|
|
return swap_if_little(internal);
|
|
}
|
|
};
|
|
}
|