289 lines
8.4 KiB
C++
289 lines
8.4 KiB
C++
/**
|
|
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 Affero 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 Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef REXY_BOOL_SPECIALIZE_BASE_HPP
|
|
#define REXY_BOOL_SPECIALIZE_BASE_HPP
|
|
|
|
#include <cstddef> //size_t
|
|
#include <utility> //move, forward, pair
|
|
#include <climits> //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<size_type,size_type> convert_to_byte_bit_pair(size_type s){
|
|
return {s / bits_per_byte, s % bits_per_byte};
|
|
}
|
|
static constexpr std::pair<size_type,size_type> 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<bool>(b);
|
|
}
|
|
constexpr boolean& operator=(boolean&& b)noexcept{
|
|
return *this = static_cast<bool>(b);
|
|
}
|
|
constexpr boolean& operator=(bool b)noexcept{
|
|
(*m_value) = ((*m_value) & ~static_cast<uchar>(uchar{1} << m_offset)) | static_cast<uchar>(uchar{b} << m_offset);
|
|
return *this;
|
|
}
|
|
constexpr operator bool(void)const noexcept{
|
|
return (*m_value) & static_cast<uchar>(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<uchar&>(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<uchar&>(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
|