#pragma once namespace nall { template struct BitField; /* static BitField */ template struct BitField { static_assert(Precision >= 1 && Precision <= 64); enum : uint { bits = Precision }; using type = conditional_t>>>; enum : uint { shift = Index < 0 ? Precision + Index : Index }; enum : type { mask = 1ull << shift }; BitField(const BitField&) = delete; inline auto& operator=(const BitField& source) { target = target & ~mask | (bool)source << shift; return *this; } template inline BitField(T* source) : target((type&)*source) { static_assert(sizeof(T) == sizeof(type)); } inline auto bit() const { return shift; } inline operator bool() const { return target & mask; } inline auto& operator=(bool source) { target = target & ~mask | source << shift; return *this; } inline auto& operator&=(bool source) { target = target & (~mask | source << shift); return *this; } inline auto& operator^=(bool source) { target = target ^ source << shift; return *this; } inline auto& operator|=(bool source) { target = target | source << shift; return *this; } private: type& target; }; /* dynamic BitField */ template struct BitField { static_assert(Precision >= 1 && Precision <= 64); enum : uint { bits = Precision }; using type = conditional_t>>>; BitField(const BitField&) = delete; inline auto& operator=(const BitField& source) { target = target & ~mask | (bool)source << shift; return *this; } template inline BitField(T* source, int index) : target((type&)*source) { static_assert(sizeof(T) == sizeof(type)); if(index < 0) index = Precision + index; mask = 1ull << index; shift = index; } inline auto bit() const { return shift; } inline operator bool() const { return target & mask; } inline auto& operator=(bool source) { target = target & ~mask | source << shift; return *this; } inline auto& operator&=(bool source) { target = target & (~mask | source << shift); return *this; } inline auto& operator^=(bool source) { target = target ^ source << shift; return *this; } inline auto& operator|=(bool source) { target = target | source << shift; return *this; } private: type& target; type mask; uint shift; }; }