2016-06-08 22:26:35 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
namespace nall {
|
|
|
|
|
2016-07-01 11:58:12 +00:00
|
|
|
template<typename Type, uint Bit> struct BooleanBitField {
|
|
|
|
enum : uint { bit = Bit };
|
|
|
|
enum : uint { mask = 1ull << bit };
|
|
|
|
using type = Type;
|
|
|
|
using utype = typename std::make_unsigned<type>::type;
|
|
|
|
static_assert(bit < sizeof(type) * 8, "");
|
|
|
|
|
|
|
|
inline BooleanBitField() = default;
|
|
|
|
inline BooleanBitField(const BooleanBitField& value) { set(value.get()); }
|
|
|
|
template<typename T> inline BooleanBitField(const bool value) { set(value); }
|
|
|
|
|
|
|
|
inline operator bool() const { return get(); }
|
|
|
|
|
|
|
|
inline auto& operator=(const BooleanBitField& value) { return set(value.get()); }
|
|
|
|
inline auto& operator=(const bool value) { return set(value); }
|
|
|
|
|
|
|
|
inline auto& operator&=(const bool value) { return set(get() & value); }
|
|
|
|
inline auto& operator|=(const bool value) { return set(get() | value); }
|
|
|
|
inline auto& operator^=(const bool value) { return set(get() ^ value); }
|
|
|
|
|
|
|
|
inline auto raise() { return get() == 0 ? set(1), true : false; }
|
|
|
|
inline auto lower() { return get() == 1 ? set(0), true : false; }
|
|
|
|
inline auto& invert() { return set(get() ^ 1); }
|
|
|
|
|
|
|
|
private:
|
|
|
|
utype data;
|
|
|
|
|
|
|
|
inline auto get() const -> bool {
|
|
|
|
return data & mask;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline auto set(bool value) -> BooleanBitField& {
|
|
|
|
return data = (data & ~mask) | (value << bit), *this;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename Type, uint Lo, uint Hi> struct NaturalBitField {
|
2016-06-08 22:26:35 +00:00
|
|
|
enum : uint { lo = Lo <= Hi ? Lo : Hi };
|
|
|
|
enum : uint { hi = Hi >= Lo ? Hi : Lo };
|
|
|
|
enum : uint { bits = hi - lo + 1 };
|
|
|
|
enum : uint { mask = (~0ull >> (64 - bits)) << lo };
|
2016-07-01 11:58:12 +00:00
|
|
|
using type = Type;
|
|
|
|
using utype = typename std::make_unsigned<type>::type;
|
2016-06-08 22:26:35 +00:00
|
|
|
static_assert(hi < sizeof(type) * 8, "");
|
|
|
|
|
2016-06-28 10:43:47 +00:00
|
|
|
inline NaturalBitField() = default;
|
|
|
|
inline NaturalBitField(const NaturalBitField& value) { set(value.data); }
|
|
|
|
template<typename T> inline NaturalBitField(const T& value) { set(value << lo); }
|
2016-06-08 22:26:35 +00:00
|
|
|
|
|
|
|
inline explicit operator bool() const { return data & mask; }
|
2016-07-01 11:58:12 +00:00
|
|
|
inline operator utype() const { return get(); }
|
2016-06-08 22:26:35 +00:00
|
|
|
|
2016-06-28 10:43:47 +00:00
|
|
|
inline auto& operator=(const NaturalBitField& value) { return set(value.data); }
|
2016-06-08 22:26:35 +00:00
|
|
|
template<typename T> inline auto& operator=(const T& value) { return set(value << lo); }
|
|
|
|
|
2016-07-01 11:58:12 +00:00
|
|
|
inline auto operator++(int) { utype value = get(); set(data + (1 << lo)); return value; }
|
|
|
|
inline auto operator--(int) { utype value = get(); set(data - (1 << lo)); return value; }
|
2016-06-08 22:26:35 +00:00
|
|
|
|
|
|
|
inline auto& operator++() { return set(data + (1 << lo)); }
|
|
|
|
inline auto& operator--() { return set(data - (1 << lo)); }
|
|
|
|
|
2016-07-01 11:58:12 +00:00
|
|
|
inline auto& operator &=(const utype value) { return set(data & (value << lo)); }
|
|
|
|
inline auto& operator |=(const utype value) { return set(data | (value << lo)); }
|
|
|
|
inline auto& operator ^=(const utype value) { return set(data ^ (value << lo)); }
|
|
|
|
inline auto& operator<<=(const utype value) { return set((data & mask) << value); }
|
|
|
|
inline auto& operator>>=(const utype value) { return set((data & mask) >> value); }
|
|
|
|
inline auto& operator +=(const utype value) { return set(data + (value << lo)); }
|
|
|
|
inline auto& operator -=(const utype value) { return set(data - (value << lo)); }
|
|
|
|
inline auto& operator *=(const utype value) { return set((get() * value) << lo); }
|
|
|
|
inline auto& operator /=(const utype value) { return set((get() / value) << lo); }
|
|
|
|
inline auto& operator %=(const utype value) { return set((get() % value) << lo); }
|
2016-06-08 22:26:35 +00:00
|
|
|
|
|
|
|
private:
|
2016-07-01 11:58:12 +00:00
|
|
|
utype data;
|
2016-06-08 22:26:35 +00:00
|
|
|
|
2016-07-01 11:58:12 +00:00
|
|
|
inline auto get() const -> utype {
|
2016-06-08 22:26:35 +00:00
|
|
|
return (data & mask) >> lo;
|
|
|
|
}
|
|
|
|
|
2016-07-01 11:58:12 +00:00
|
|
|
inline auto set(utype value) -> NaturalBitField& {
|
2016-06-08 22:26:35 +00:00
|
|
|
return data = (data & ~mask) | (value & mask), *this;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2016-07-01 11:58:12 +00:00
|
|
|
template<typename Type, uint Lo, uint Hi> struct IntegerBitField {
|
|
|
|
enum : uint { lo = Lo <= Hi ? Lo : Hi };
|
|
|
|
enum : uint { hi = Hi >= Lo ? Hi : Lo };
|
|
|
|
enum : uint { bits = hi - lo + 1 };
|
|
|
|
enum : uint { mask = (~0ull >> (64 - bits)) << lo };
|
|
|
|
using type = Type;
|
|
|
|
using stype = typename std::make_signed<type>::type;
|
|
|
|
using utype = typename std::make_unsigned<type>::type;
|
|
|
|
static_assert(hi < sizeof(type) * 8, "");
|
2016-06-08 22:26:35 +00:00
|
|
|
|
2016-07-01 11:58:12 +00:00
|
|
|
inline IntegerBitField() = default;
|
|
|
|
inline IntegerBitField(const IntegerBitField& value) { set(value.get()); }
|
|
|
|
template<typename T> inline IntegerBitField(const T& value) { set(value); }
|
2016-06-08 22:26:35 +00:00
|
|
|
|
2016-07-01 11:58:12 +00:00
|
|
|
inline explicit operator bool() const { return data & mask; }
|
|
|
|
inline operator stype() const { return get(); }
|
2016-06-08 22:26:35 +00:00
|
|
|
|
2016-07-01 11:58:12 +00:00
|
|
|
inline auto& operator=(const IntegerBitField& value) { return set(value.get()); }
|
|
|
|
template<typename T> inline auto& operator=(const T& value) { return set(value); }
|
2016-06-08 22:26:35 +00:00
|
|
|
|
2016-07-01 11:58:12 +00:00
|
|
|
inline auto operator++(int) { stype value = get(); set(value + 1); return value; }
|
|
|
|
inline auto operator--(int) { stype value = get(); set(value - 1); return value; }
|
2016-06-08 22:26:35 +00:00
|
|
|
|
2016-07-01 11:58:12 +00:00
|
|
|
inline auto& operator++() { return set(get() + 1); }
|
|
|
|
inline auto& operator--() { return set(get() - 1); }
|
|
|
|
|
|
|
|
inline auto& operator &=(const stype value) { return set(get() & value); }
|
|
|
|
inline auto& operator |=(const stype value) { return set(get() | value); }
|
|
|
|
inline auto& operator ^=(const stype value) { return set(get() ^ value); }
|
|
|
|
inline auto& operator<<=(const stype value) { return set(get() << value); }
|
|
|
|
inline auto& operator>>=(const stype value) { return set(get() >> value); }
|
|
|
|
inline auto& operator +=(const stype value) { return set(get() + value); }
|
|
|
|
inline auto& operator -=(const stype value) { return set(get() - value); }
|
|
|
|
inline auto& operator *=(const stype value) { return set(get() * value); }
|
|
|
|
inline auto& operator /=(const stype value) { return set(get() / value); }
|
|
|
|
inline auto& operator %=(const stype value) { return set(get() % value); }
|
2016-06-27 13:07:57 +00:00
|
|
|
|
2016-06-08 22:26:35 +00:00
|
|
|
private:
|
2016-07-01 11:58:12 +00:00
|
|
|
utype data;
|
2016-06-08 22:26:35 +00:00
|
|
|
|
2016-07-01 11:58:12 +00:00
|
|
|
inline auto get() const -> stype {
|
|
|
|
enum : utype { b = 1ull << (bits - 1) };
|
|
|
|
enum : utype { m = b * 2 - 1 };
|
|
|
|
return ((((data & mask) >> lo) & m) ^ b) - b;
|
2016-06-08 22:26:35 +00:00
|
|
|
}
|
|
|
|
|
2016-07-01 11:58:12 +00:00
|
|
|
inline auto set(utype value) -> IntegerBitField& {
|
|
|
|
return data = (data & ~mask) | ((value << lo) & mask), *this;
|
2016-06-08 22:26:35 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}
|