General Purpose library for Freestanding C++ and POSIX systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

86 lines
1.5 KiB

#pragma once
#include "gp/containers/array.hpp"
#include <bit>
#include <stddef.h>
#include <stdint.h>
namespace gp {
using endian = std::endian;
template <typename T>
T swap_endian(T value) noexcept {
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 = 0;
constexpr endian_wrapper() noexcept = default;
endian_wrapper(T v) noexcept
: value{adjust(v)} {}
endian_wrapper& operator=(T v) noexcept {
value = adjust(v);
return *this;
}
operator T() const noexcept {
return adjust(value);
}
auto bytes() const noexcept -> gp::array<uint8_t, sizeof(T)> {
union {
T t;
gp::array<uint8_t, sizeof(T)> bytes;
} tmp {.t = value};
return tmp.bytes;
}
// arithmetic assignment operators
endian_wrapper& operator+=(T rhs) noexcept {
value = adjust(adjust(value) + rhs);
return *this;
}
endian_wrapper& operator+=(endian_wrapper rhs) noexcept {
value = adjust(adjust(value) + adjust(rhs.value));
return *this;
}
endian_wrapper& operator-=(T rhs) noexcept {
value = adjust(adjust(value) - rhs);
return *this;
}
endian_wrapper& operator-=(endian_wrapper rhs) noexcept {
value = adjust(adjust(value) - adjust(rhs.value));
return *this;
}
private:
T adjust(T x) const noexcept {
return (mode == endian::native ? x : swap_endian(x));
}
};
}