#ifndef __JABYENGINE_COMPLEX_BITMAP_HPP__ #define __JABYENGINE_COMPLEX_BITMAP_HPP__ #include "bits.hpp" namespace JabyEngine { struct ClearBitValue { size_t bit; constexpr ClearBitValue(size_t bit) : bit(bit) { } }; template struct Bit { typedef T ValueType; size_t value; constexpr Bit(size_t value) : value(value) { } constexpr operator size_t() const { return this->value; } constexpr ClearBitValue operator!() const { return ClearBitValue(this->value); } }; template struct BitRangeValue { T value; size_t begin; size_t length; constexpr BitRangeValue() = default; constexpr BitRangeValue(T value, size_t begin, size_t length) : value(value), begin(begin), length(length) { } }; template struct BitRange { typedef T ValueType; size_t begin; size_t length; static constexpr BitRange from_to(size_t start, size_t end) { return {start, (end - start + 1)}; } constexpr BitRangeValue with(T value) const { return BitRangeValue(value, this->begin, this->length); } constexpr BitRangeValue max() const { return BitRange::with((1 << this->length) - 1); } }; template static constexpr __always_inline BitRangeValue operator<<(const BitRange& range, T value) { return BitRangeValue{value, range.begin, range.length}; } template class ComplexBitMap { public: typedef T UnderlyingType; T raw; private: template constexpr __always_inline ComplexBitMap& set_va(const S& value) { return this->set(value); } template constexpr __always_inline ComplexBitMap& set_va(const S& value, const ARGS&...args) { return this->set_va(value).set_va(args...); } public: template static constexpr __always_inline ComplexBitMap with(ARGS...args) { return ComplexBitMap().set_va(args...); } //Accesssing bits template constexpr ComplexBitMap& set_bit(S bit) { this->raw = bit::set(this->raw, static_cast(bit)); return *this; } template constexpr void set_bit(S bit) volatile { this->raw = bit::set(this->raw, static_cast(bit)); } template constexpr ComplexBitMap& clear_bit(S bit) { this->raw = bit::clear(this->raw, static_cast(bit)); return *this; } template constexpr void clear_bit(S bit) volatile { this->raw = bit::clear(this->raw, static_cast(bit)); } template constexpr bool is_bit_set(S bit) { return bit::is_set(this->raw, static_cast(bit)); } template constexpr bool is_bit_set(S bit) const volatile { return bit::is_set(this->raw, static_cast(bit)); } //Accessing values template constexpr ComplexBitMap& set_value(S value, const BitRange& range) { this->raw = bit::value::set_normalized(this->raw, static_cast(value), range.begin, range.length); return *this; } template constexpr void set_value(S value, const BitRange& range) volatile { this->raw = bit::value::set_normalized(this->raw, static_cast(value), range.begin, range.length); } template constexpr ComplexBitMap& clear_value(const BitRange& range) { this->raw = bit::value::clear_normalized(this->raw, range.begin, range.length); return *this; } template constexpr void clear_value(const BitRange& range) volatile { this->raw = bit::value::clear_normalized(this->raw, range.begin, range.length); } template constexpr S get_value(const BitRange& range) const { return static_cast(bit::value::get_normalized(this->raw, range.begin, range.length)); } template constexpr S get_value(const BitRange& range) const volatile { return static_cast(bit::value::get_normalized(this->raw, range.begin, range.length)); } //For easier checking constexpr bool is(Bit bit) const { return ComplexBitMap::is_bit_set(bit); } constexpr bool is(Bit bit) const volatile { return ComplexBitMap::is_bit_set(bit); } // For easier constructing template constexpr __always_inline ComplexBitMap& set(const BitRange& range, T value) { this->set_value(value, range); return *this; } template constexpr __always_inline ComplexBitMap& set(const BitRangeValue& value) { this->set_value(value.value, {value.begin, value.length}); return *this; } template constexpr __always_inline ComplexBitMap& set(const Bit& bit) { this->set_bit(bit.value); return *this; } constexpr __always_inline ComplexBitMap& set(const ClearBitValue& value) { this->clear_bit(value.bit); return *this; } constexpr __always_inline ComplexBitMap& operator|(const BitRangeValue& value) { this->set_value(value.value, value.range); return *this; } constexpr __always_inline ComplexBitMap& operator|(const Bit& bit) { this->set_bit(bit.value); return *this; } constexpr __always_inline ComplexBitMap& operator|(const ClearBitValue& value) { this->clear_bit(value.bit); return *this; } constexpr __always_inline operator T() const { return this->raw; } }; } #endif //!__JABYENGINE_COMPLEX_BITMAP_HPP__