/**
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