123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- #pragma once
- namespace nall {
- template<int...> struct BitRange;
- /* static BitRange */
- template<int Precision, int Lo, int Hi> struct BitRange<Precision, Lo, Hi> {
- static_assert(Precision >= 1 && Precision <= 64);
- enum : uint { bits = Precision };
- using type =
- conditional_t<bits <= 8, uint8_t,
- conditional_t<bits <= 16, uint16_t,
- conditional_t<bits <= 32, uint32_t,
- conditional_t<bits <= 64, uint64_t,
- void>>>>;
- enum : uint { lo = Lo < 0 ? Precision + Lo : Lo };
- enum : uint { hi = Hi < 0 ? Precision + Hi : Hi };
- enum : type { mask = ~0ull >> 64 - (hi - lo + 1) << lo };
- enum : uint { shift = lo };
- BitRange(const BitRange& source) = delete;
- inline auto& operator=(const BitRange& source) {
- target = target & ~mask | ((source.target & source.mask) >> source.shift) << shift & mask;
- return *this;
- }
- template<typename T> inline BitRange(T* source) : target((type&)*source) {
- static_assert(sizeof(T) == sizeof(type));
- }
- inline operator type() const {
- return (target & mask) >> shift;
- }
- inline auto operator++(int) {
- auto value = (target & mask) >> shift;
- target = target & ~mask | target + (1 << shift) & mask;
- return value;
- }
- inline auto operator--(int) {
- auto value = (target & mask) >> shift;
- target = target & ~mask | target - (1 << shift) & mask;
- return value;
- }
- inline auto& operator++() {
- target = target & ~mask | target + (1 << shift) & mask;
- return *this;
- }
- inline auto& operator--() {
- target = target & ~mask | target - (1 << shift) & mask;
- return *this;
- }
- template<typename T> inline auto& operator=(const T& source) {
- type value = source;
- target = target & ~mask | value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator*=(const T& source) {
- auto value = ((target & mask) >> shift) * source;
- target = target & ~mask | value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator/=(const T& source) {
- auto value = ((target & mask) >> shift) / source;
- target = target & ~mask | value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator%=(const T& source) {
- auto value = ((target & mask) >> shift) % source;
- target = target & ~mask | value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator+=(const T& source) {
- auto value = ((target & mask) >> shift) + source;
- target = target & ~mask | value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator-=(const T& source) {
- auto value = ((target & mask) >> shift) - source;
- target = target & ~mask | value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator<<=(const T& source) {
- auto value = ((target & mask) >> shift) << source;
- target = target & ~mask | value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator>>=(const T& source) {
- auto value = ((target & mask) >> shift) >> source;
- target = target & ~mask | value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator&=(const T& source) {
- type value = source;
- target = target & (~mask | value << shift & mask);
- return *this;
- }
- template<typename T> inline auto& operator^=(const T& source) {
- type value = source;
- target = target ^ value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator|=(const T& source) {
- type value = source;
- target = target | value << shift & mask;
- return *this;
- }
- private:
- type& target;
- };
- /* dynamic BitRange */
- template<int Precision> struct BitRange<Precision> {
- static_assert(Precision >= 1 && Precision <= 64);
- enum : uint { bits = Precision };
- using type =
- conditional_t<bits <= 8, uint8_t,
- conditional_t<bits <= 16, uint16_t,
- conditional_t<bits <= 32, uint32_t,
- conditional_t<bits <= 64, uint64_t,
- void>>>>;
- BitRange(const BitRange& source) = delete;
- inline auto& operator=(const BitRange& source) {
- target = target & ~mask | ((source.target & source.mask) >> source.shift) << shift & mask;
- return *this;
- }
- template<typename T> inline BitRange(T* source, int index) : target((type&)*source) {
- static_assert(sizeof(T) == sizeof(type));
- if(index < 0) index = Precision + index;
- mask = 1ull << index;
- shift = index;
- }
- template<typename T> inline BitRange(T* source, int lo, int hi) : target((type&)*source) {
- static_assert(sizeof(T) == sizeof(type));
- 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;
- }
- inline operator type() const {
- return (target & mask) >> shift;
- }
- inline auto operator++(int) {
- auto value = (target & mask) >> shift;
- target = target & ~mask | target + (1 << shift) & mask;
- return value;
- }
- inline auto operator--(int) {
- auto value = (target & mask) >> shift;
- target = target & ~mask | target - (1 << shift) & mask;
- return value;
- }
- inline auto& operator++() {
- target = target & ~mask | target + (1 << shift) & mask;
- return *this;
- }
- inline auto& operator--() {
- target = target & ~mask | target - (1 << shift) & mask;
- return *this;
- }
- template<typename T> inline auto& operator=(const T& source) {
- type value = source;
- target = target & ~mask | value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator*=(const T& source) {
- auto value = ((target & mask) >> shift) * source;
- target = target & ~mask | value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator/=(const T& source) {
- auto value = ((target & mask) >> shift) / source;
- target = target & ~mask | value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator%=(const T& source) {
- auto value = ((target & mask) >> shift) % source;
- target = target & ~mask | value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator+=(const T& source) {
- auto value = ((target & mask) >> shift) + source;
- target = target & ~mask | value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator-=(const T& source) {
- auto value = ((target & mask) >> shift) - source;
- target = target & ~mask | value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator<<=(const T& source) {
- auto value = ((target & mask) >> shift) << source;
- target = target & ~mask | value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator>>=(const T& source) {
- auto value = ((target & mask) >> shift) >> source;
- target = target & ~mask | value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator&=(const T& source) {
- type value = source;
- target = target & (~mask | value << shift & mask);
- return *this;
- }
- template<typename T> inline auto& operator^=(const T& source) {
- type value = source;
- target = target ^ value << shift & mask;
- return *this;
- }
- template<typename T> inline auto& operator|=(const T& source) {
- type value = source;
- target = target | value << shift & mask;
- return *this;
- }
- private:
- type& target;
- type mask;
- uint shift;
- };
- }
|