262 lines
7.0 KiB
C++
262 lines
7.0 KiB
C++
#pragma once
|
|
|
|
namespace nall {
|
|
|
|
/* static BitRange */
|
|
|
|
template<s32 Precision, s32 Lo, s32 Hi> struct BitRange {
|
|
static_assert(Precision >= 1 && Precision <= 64);
|
|
static_assert(Lo < Precision && Hi < Precision);
|
|
static_assert(Lo <= Hi);
|
|
using type =
|
|
conditional_t<Precision <= 8, u8,
|
|
conditional_t<Precision <= 16, u16,
|
|
conditional_t<Precision <= 32, u32,
|
|
conditional_t<Precision <= 64, u64,
|
|
void>>>>;
|
|
enum : u32 { lo = Lo < 0 ? Precision + Lo : Lo };
|
|
enum : u32 { hi = Hi < 0 ? Precision + Hi : Hi };
|
|
enum : type { mask = ~0ull >> 64 - (hi - lo + 1) << lo };
|
|
enum : u32 { shift = lo };
|
|
|
|
BitRange(const BitRange& source) = delete;
|
|
BitRange(BitRange&& source) = default;
|
|
|
|
auto& operator=(const BitRange& source) {
|
|
target = target & ~mask | ((source.target & source.mask) >> source.shift) << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> BitRange(T* source) : target((type&)*source) {
|
|
static_assert(sizeof(T) == sizeof(type));
|
|
}
|
|
|
|
operator type() const {
|
|
return (target & mask) >> shift;
|
|
}
|
|
|
|
auto operator++(s32) {
|
|
auto value = (target & mask) >> shift;
|
|
target = target & ~mask | target + (1 << shift) & mask;
|
|
return value;
|
|
}
|
|
|
|
auto operator--(s32) {
|
|
auto value = (target & mask) >> shift;
|
|
target = target & ~mask | target - (1 << shift) & mask;
|
|
return value;
|
|
}
|
|
|
|
auto& operator++() {
|
|
target = target & ~mask | target + (1 << shift) & mask;
|
|
return *this;
|
|
}
|
|
|
|
auto& operator--() {
|
|
target = target & ~mask | target - (1 << shift) & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator=(const T& source) {
|
|
type value = source;
|
|
target = target & ~mask | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator*=(const T& source) {
|
|
auto value = ((target & mask) >> shift) * source;
|
|
target = target & ~mask | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator/=(const T& source) {
|
|
auto value = ((target & mask) >> shift) / source;
|
|
target = target & ~mask | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator%=(const T& source) {
|
|
auto value = ((target & mask) >> shift) % source;
|
|
target = target & ~mask | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator+=(const T& source) {
|
|
auto value = ((target & mask) >> shift) + source;
|
|
target = target & ~mask | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator-=(const T& source) {
|
|
auto value = ((target & mask) >> shift) - source;
|
|
target = target & ~mask | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator<<=(const T& source) {
|
|
auto value = ((target & mask) >> shift) << source;
|
|
target = target & ~mask | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator>>=(const T& source) {
|
|
auto value = ((target & mask) >> shift) >> source;
|
|
target = target & ~mask | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator&=(const T& source) {
|
|
type value = source;
|
|
target = target & (~mask | value << shift & mask);
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator^=(const T& source) {
|
|
type value = source;
|
|
target = target ^ value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator|=(const T& source) {
|
|
type value = source;
|
|
target = target | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
type& target;
|
|
};
|
|
|
|
/* dynamic BitRange */
|
|
|
|
template<typename Type, s32 Precision = Type::bits()> struct DynamicBitRange {
|
|
static_assert(Precision >= 1 && Precision <= 64);
|
|
using type =
|
|
conditional_t<Precision <= 8, u8,
|
|
conditional_t<Precision <= 16, u16,
|
|
conditional_t<Precision <= 32, u32,
|
|
conditional_t<Precision <= 64, u64,
|
|
void>>>>;
|
|
|
|
DynamicBitRange(const DynamicBitRange& source) = delete;
|
|
DynamicBitRange(DynamicBitRange&& source) = default;
|
|
|
|
auto& operator=(const DynamicBitRange& source) {
|
|
target = target & ~mask | ((source.target & source.mask) >> source.shift) << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
DynamicBitRange(Type& source, s32 index) : target(source) {
|
|
if(index < 0) index = Precision + index;
|
|
mask = 1ull << index;
|
|
shift = index;
|
|
}
|
|
|
|
DynamicBitRange(Type& source, s32 lo, s32 hi) : target(source) {
|
|
if(lo < 0) lo = Precision + lo;
|
|
if(hi < 0) hi = Precision + hi;
|
|
if(lo > hi) swap(lo, hi);
|
|
mask = ~0ull >> 64 - (hi - lo + 1) << lo;
|
|
shift = lo;
|
|
}
|
|
|
|
operator type() const {
|
|
return (target & mask) >> shift;
|
|
}
|
|
|
|
auto operator++(s32) {
|
|
auto value = (target & mask) >> shift;
|
|
target = target & ~mask | target + (1 << shift) & mask;
|
|
return value;
|
|
}
|
|
|
|
auto operator--(s32) {
|
|
auto value = (target & mask) >> shift;
|
|
target = target & ~mask | target - (1 << shift) & mask;
|
|
return value;
|
|
}
|
|
|
|
auto& operator++() {
|
|
target = target & ~mask | target + (1 << shift) & mask;
|
|
return *this;
|
|
}
|
|
|
|
auto& operator--() {
|
|
target = target & ~mask | target - (1 << shift) & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator=(const T& source) {
|
|
type value = source;
|
|
target = target & ~mask | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator*=(const T& source) {
|
|
auto value = ((target & mask) >> shift) * source;
|
|
target = target & ~mask | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator/=(const T& source) {
|
|
auto value = ((target & mask) >> shift) / source;
|
|
target = target & ~mask | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator%=(const T& source) {
|
|
auto value = ((target & mask) >> shift) % source;
|
|
target = target & ~mask | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator+=(const T& source) {
|
|
auto value = ((target & mask) >> shift) + source;
|
|
target = target & ~mask | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator-=(const T& source) {
|
|
auto value = ((target & mask) >> shift) - source;
|
|
target = target & ~mask | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator<<=(const T& source) {
|
|
auto value = ((target & mask) >> shift) << source;
|
|
target = target & ~mask | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator>>=(const T& source) {
|
|
auto value = ((target & mask) >> shift) >> source;
|
|
target = target & ~mask | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator&=(const T& source) {
|
|
type value = source;
|
|
target = target & (~mask | value << shift & mask);
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator^=(const T& source) {
|
|
type value = source;
|
|
target = target ^ value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
template<typename T> auto& operator|=(const T& source) {
|
|
type value = source;
|
|
target = target | value << shift & mask;
|
|
return *this;
|
|
}
|
|
|
|
private:
|
|
Type& target;
|
|
type mask;
|
|
u32 shift;
|
|
};
|
|
|
|
}
|