/** This file is a part of rexy's general purpose library Copyright (C) 2020 rexy712 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef REXY_BOOL_SPECIALIZE_BASE_HPP #define REXY_BOOL_SPECIALIZE_BASE_HPP #include //size_t #include //move, forward, pair #include //CHAR_BIT #include "../../utility.hpp" //swap namespace rexy::cx::detail{ class bool_specialize_base { protected: using size_type = size_t; using difference_type = ptrdiff_t; static constexpr size_type bits_per_byte = CHAR_BIT; static constexpr std::pair convert_to_byte_bit_pair(size_type s){ return {s / bits_per_byte, s % bits_per_byte}; } static constexpr std::pair convert_to_position(size_type s){ size_type bits = s % bits_per_byte; size_type bytes = s / bits_per_byte; if(bits == 0){ bits = bits_per_byte-1; bytes -= 1; } return {bytes, bits}; } public: struct boolean { private: using uchar = unsigned char; uchar* m_value; size_type m_offset; public: constexpr boolean(uchar& val, size_type offset)noexcept: m_value(&val), m_offset(offset){} constexpr boolean(const boolean&)noexcept = default; constexpr boolean(boolean&&)noexcept = default; ~boolean(void)noexcept = default; constexpr boolean& operator=(const boolean& b)noexcept{ return *this = static_cast(b); } constexpr boolean& operator=(boolean&& b)noexcept{ return *this = static_cast(b); } constexpr boolean& operator=(bool b)noexcept{ (*m_value) = ((*m_value) & ~static_cast(uchar{1} << m_offset)) | static_cast(uchar{b} << m_offset); return *this; } constexpr operator bool(void)const noexcept{ return (*m_value) & static_cast(uchar{1} << m_offset); } }; protected: struct booleans { private: using uchar = unsigned char; uchar m_value = 0; public: constexpr booleans(void)noexcept = default; constexpr booleans(const booleans&)noexcept = default; constexpr booleans(booleans&&)noexcept = default; ~booleans(void)noexcept = default; constexpr booleans& operator=(const booleans&)noexcept = default; constexpr booleans& operator=(booleans&&)noexcept = default; constexpr boolean operator[](size_t i){ return boolean{m_value, i}; } constexpr boolean operator[](size_t i)const{ return boolean{const_cast(m_value), i}; } constexpr uchar& data(void){ return m_value; } constexpr const uchar& data(void)const{ return m_value; } }; public: struct const_bool_iter; struct bool_iter { friend class const_bool_iter; private: using uchar = unsigned char; booleans* m_value; size_type m_offset; public: constexpr bool_iter(booleans& val, size_type offset)noexcept: m_value(&val), m_offset(offset){} constexpr bool_iter(const bool_iter&)noexcept = default; constexpr bool_iter(bool_iter&&)noexcept = default; ~bool_iter(void)noexcept = default; constexpr bool_iter& operator=(const bool_iter&)noexcept = default; constexpr bool_iter& operator=(bool_iter&&)noexcept = default; constexpr boolean operator*(void)const noexcept{ return boolean(m_value->data(), m_offset); } constexpr bool_iter& operator++(void)noexcept{ if(m_offset < (bits_per_byte-1)){ ++m_offset; }else{ m_offset = 0; ++m_value; } return *this; } constexpr bool_iter& operator--(void)noexcept{ if(m_offset > 0){ --m_offset; }else{ m_offset = (bits_per_byte-1); --m_value; } return *this; } constexpr difference_type operator-(const bool_iter& other)const noexcept{ return (m_value - other.m_value) * bits_per_byte + (m_offset - other.m_offset); } constexpr bool_iter operator-(difference_type d)const noexcept{ bool_iter ret = *this; return ret -= d; } constexpr bool_iter operator+(difference_type d)const noexcept{ bool_iter ret = *this; return ret += d; } constexpr bool_iter& operator+=(difference_type d)noexcept{ if(d >= 0){ while(d--){ ++(*this); } }else{ while(d++){ --(*this); } } return *this; } constexpr bool_iter& operator-=(difference_type d)noexcept{ return (*this) += -d; } constexpr bool operator<(const bool_iter& other)const noexcept{ return (m_value < other.m_value) || (m_offset < other.m_offset); } constexpr bool operator>(const bool_iter& other)const noexcept{ return (m_value > other.m_value) || (m_offset > other.m_offset); } constexpr bool operator<=(const bool_iter& other)const noexcept{ return (m_value <= other.m_value) || (m_offset <= other.m_offset); } constexpr bool operator>=(const bool_iter& other)const noexcept{ return (m_value >= other.m_value) || (m_offset >= other.m_offset); } constexpr bool operator==(const bool_iter& other)const noexcept{ return m_value == other.m_value && m_offset == other.m_offset; } constexpr bool operator!=(const bool_iter& other)const noexcept{ return !(*this == other); } }; struct const_bool_iter { friend class bool_iter; private: using uchar = unsigned char; const booleans* m_value; size_type m_offset; public: constexpr const_bool_iter(const booleans& val, size_type offset)noexcept: m_value(&val), m_offset(offset){} constexpr const_bool_iter(const bool_iter& b)noexcept: m_value(b.m_value), m_offset(b.m_offset){} constexpr const_bool_iter(const const_bool_iter&)noexcept = default; constexpr const_bool_iter(const_bool_iter&&)noexcept = default; ~const_bool_iter(void)noexcept = default; constexpr const_bool_iter& operator=(const const_bool_iter&)noexcept = default; constexpr const_bool_iter& operator=(const_bool_iter&&)noexcept = default; constexpr boolean operator*(void)const noexcept{ return boolean(const_cast(m_value->data()), m_offset); } constexpr const_bool_iter& operator++(void)noexcept{ if(m_offset < (bits_per_byte-1)){ ++m_offset; }else{ m_offset = 0; ++m_value; } return *this; } constexpr const_bool_iter& operator--(void)noexcept{ if(m_offset > 0){ --m_offset; }else{ m_offset = (bits_per_byte-1); --m_value; } return *this; } constexpr difference_type operator-(const const_bool_iter& other)const noexcept{ return (m_value - other.m_value) * bits_per_byte + (m_offset - other.m_offset); } constexpr const_bool_iter operator-(difference_type d)const noexcept{ const_bool_iter ret = *this; return ret -= d; } constexpr const_bool_iter operator+(difference_type d)const noexcept{ const_bool_iter ret = *this; return ret += d; } constexpr const_bool_iter& operator+=(difference_type d)noexcept{ if(d >= 0){ while(d--){ ++(*this); } }else{ while(d++){ --(*this); } } return *this; } constexpr const_bool_iter& operator-=(difference_type d)noexcept{ return (*this) += -d; } constexpr bool operator<(const const_bool_iter& other)const noexcept{ return (m_value < other.m_value) || (m_offset < other.m_offset); } constexpr bool operator>(const const_bool_iter& other)const noexcept{ return (m_value > other.m_value) || (m_offset > other.m_offset); } constexpr bool operator<=(const const_bool_iter& other)const noexcept{ return (m_value <= other.m_value) || (m_offset <= other.m_offset); } constexpr bool operator>=(const const_bool_iter& other)const noexcept{ return (m_value >= other.m_value) || (m_offset >= other.m_offset); } constexpr bool operator==(const const_bool_iter& other)const noexcept{ return m_value == other.m_value && m_offset == other.m_offset; } constexpr bool operator!=(const const_bool_iter& other)const noexcept{ return !(*this == other); } }; }; } #endif