|
|
- #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);
- }
- };
- }
|