/* Copyright (C) 2004 Garrett A. Kajmowicz
This file is part of the uClibc++ Library.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <basic_definitions>
#include <cstddef>
#include <climits>
#include <func_exception>
#include <string>
#include <iosfwd>
#ifndef __STD_BITSET_HEADER
#define __STD_BITSET_HEADER 1
#pragma GCC visibility push(default)
namespace std{
template <size_t N> class bitset;
template <size_t N> bitset<N> operator&(const bitset<N>&, const bitset<N>&);
template <size_t N> bitset<N> operator|(const bitset<N>&, const bitset<N>&);
template <size_t N> bitset<N> operator^(const bitset<N>&, const bitset<N>&);
template <class charT, class traits, size_t N> basic_istream<charT, traits>&
operator>>(basic_istream<charT, traits>& is, bitset<N>& x);
template <class charT, class traits, size_t N> basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& os, const bitset<N>& x);
//Actual Code
template<size_t N> class _UCXXEXPORT bitset {
private:
//Number of characters allocated to hold the bits
static const size_t WORD_SIZE = CHAR_BIT; //Use int maybe?
static const size_t num_bytes = (N + WORD_SIZE - 1) / WORD_SIZE;
//From the bit number, figure out which byte we are working with
size_t byte_num(size_t bit_num) const{
if(WORD_SIZE == 8){
return (bit_num >> 3);
}
if(WORD_SIZE == 16){
return (bit_num >> 4);
}
if(WORD_SIZE == 32){
return (bit_num >> 5);
}
if(WORD_SIZE == 64){
return (bit_num >> 6);
}
return bit_num / WORD_SIZE;
}
//From the bit number, figure out which bit inside the byte we need
size_t bit_num(const size_t bit_num) const{
return bit_num % WORD_SIZE;
}
//Point to the actual data
char data[num_bytes];
public:
class _UCXXEXPORT reference {
friend class bitset;
reference() : bit_num(0), parent(0) { }
size_t bit_num;
bitset * parent;
public:
~reference() { }
reference& operator=(bool x){ // for b[i] = x;
parent->set(bit_num, x);
return *this;
}
reference& operator=(const reference& x){ // for b[i] = b[j];
parent->set(bit_num, x);
return *this;
}
bool operator~() const{ // flips the bit
return !parent->test(bit_num);
}
operator bool() const{ // for x = b[i];
return parent->test(bit_num);
}
reference& flip(){ // for b[i].flip();
parent->flip(bit_num);
return *this;
}
};
bitset(){
reset();
}
bitset(unsigned long val){
reset();
size_t count = sizeof(val) * CHAR_BIT;
if(count > N){
count = N;
}
for(size_t i = 0; i < count; ++i){
set(i, ((val >> i) & 1));
}
}
bitset(const bitset & val){
for(size_t i = 0; i < num_bytes; ++i){
data[i] = val.data[i];
}
}
template<class charT, class traits, class Allocator> _UCXXEXPORT
explicit bitset(
const basic_string<charT,traits,Allocator>& str,
typename basic_string<charT,traits,Allocator>::size_type pos = 0,
typename basic_string<charT,traits,Allocator>::size_type n =
basic_string<charT>::npos
){
reset();
if(n > str.length()){
n = str.length();
}
size_t width = n;
if (width + pos > str.length()){
width = str.length() - pos;
}
for(size_t i = 0; i < width; ++i){
switch(str[pos + width - i - 1]){
case '0':
break;
case '1':
set(i);
break;
default:
__throw_invalid_argument();
}
}
}
bitset<N>& operator&=(const bitset<N>& rhs){
for(size_t i =0; i < num_bytes; ++i){
data[i] &= rhs.data[i];
}
return *this;
}
bitset<N>& operator|=(const bitset<N>& rhs){
for(size_t i =0; i < num_bytes; ++i){
data[i] |= rhs.data[i];
}
return *this;
}
bitset<N>& operator^=(const bitset<N>& rhs){
for(size_t i=0; i < num_bytes; ++i){
data[i] ^= rhs.data[i];
}
return *this;
}
bitset<N>& operator<<=(size_t pos){
for(size_t i = N-1; i >=pos; --i){
set(i, test(i - pos));
}
for(size_t i = 0; i < pos; ++i){
reset(i);
}
return *this;
}
bitset<N>& operator>>=(size_t pos){
for(size_t i = 0; i < (N - pos); ++i){
set(i, test(i + pos));
}
for(size_t i = pos; i > 0; --i){
reset(N - i);
}
return *this;
}
bitset<N>& set(){
size_t i;
for(i = 0; i < N ; ++i){
data[byte_num(i)] |= (1<<bit_num(i));
}
return *this;
}
bitset<N>& set(size_t pos, int val = true){
if(val == true){
data[byte_num(pos)] |= (1<<bit_num(pos));
}else{
data[byte_num(pos)] &= ~(1<<bit_num(pos));
}
return *this;
}
bitset<N>& reset(){
for(size_t i = 0; i < num_bytes; ++i){
data[i] = 0;
}
return *this;
}
bitset<N>& reset(size_t pos){
data[byte_num(pos)] &= ~(1<<bit_num(pos));
return *this;
}
bitset<N> operator~() const{
bitset<N> retval(*this);
retval.flip();
return retval;
}
bitset<N>& flip(){
for(size_t i = 0; i < num_bytes; ++i){
data[i] = ~data[i];
}
return *this;
}
bitset<N>& flip(size_t pos){
char temp = data[byte_num(pos)] & (1 << bit_num(pos));
if(temp == 0){ //Bit was 0
data[byte_num(pos)] |= (1 << bit_num(pos));
}else{ //Bit was 1
data[byte_num(pos)] &= ~(1<<bit_num(pos));
}
return *this;
}
reference operator[](size_t pos){ // for b[i];
reference retval;
retval.parent = this;
retval.bit_num = pos;
return retval;
}
unsigned long to_ulong() const{
if(N > sizeof(unsigned long) * CHAR_BIT){
__throw_overflow_error();
}
unsigned long retval = 0;
size_t count = N;
for(size_t i = count; i > 0; --i){
if(test(i)){
retval +=1;
}
retval<<=1;
}
if(test(0)){
retval +=1;
}
return retval;
}
template <class charT, class traits, class Allocator>
basic_string<charT, traits, Allocator> to_string() const
{
basic_string<charT, traits, Allocator> retval;
retval.reserve(N);
for(size_t i = N ; i > 0; --i){
if(test(i-1) == true){
retval.append("1");
}else{
retval.append("0");
}
}
return retval;
}
size_t count() const{
size_t retval = 0;
for(size_t i =0; i < N; ++i){
if(test(i)){
++retval;
}
}
return retval;
}
size_t size() const{
return N;
}
bitset<N>& operator=(const bitset<N> & rhs){
if(&rhs == this){
return *this;
}
for(size_t i = 0; i <= byte_num(N); ++i){
data[i] = rhs.data[i];
}
return *this;
}
bool operator==(const bitset<N>& rhs) const{
for(size_t i =0; i< N; ++i){
if(test(i) != rhs.test(i)){
return false;
}
}
return true;
}
bool operator!=(const bitset<N>& rhs) const{
for(size_t i =0; i< N; ++i){
if(test(i) != rhs.test(i)){
return true;
}
}
return false;
}
bool test(size_t pos) const{
return (data[byte_num(pos)] & (1<<bit_num(pos)) ) != 0;
}
bool any() const{
for(size_t i = 0; i< N; ++i){
if(test(i)==true){
return true;
}
}
return false;
}
bool none() const{
if(any() == true){
return false;
}
return true;
}
bitset<N> operator<<(size_t pos) const{
bitset retval(*this);
retval<<=pos;
return retval;
}
bitset<N> operator>>(size_t pos) const{
bitset retval(*this);
retval>>=pos;
return retval;
}
};
//Non-member functions
template <size_t N> _UCXXEXPORT bitset<N> operator&(const bitset<N>& lhs, const bitset<N>& rhs){
bitset<N> retval(lhs);
retval &= rhs;
return retval;
}
template <size_t N> _UCXXEXPORT bitset<N> operator|(const bitset<N>& lhs, const bitset<N>& rhs){
bitset<N> retval(lhs);
retval |= rhs;
return retval;
}
template <size_t N> _UCXXEXPORT bitset<N> operator^(const bitset<N>& lhs, const bitset<N>& rhs){
bitset<N> retval(lhs);
retval ^= rhs;
return retval;
}
template <class charT, class traits, size_t N> _UCXXEXPORT basic_istream<charT, traits>&
operator>>(basic_istream<charT, traits>& is, bitset<N>& x)
{
string s;
charT c;
for(size_t i = 0; i < N; ++i){
is.get(c);
if(!is.good()){
break;
}
if(c != '1' && c !='0'){
is.putback(c);
break;
}
s+=c;
}
bitset<N> temp(s);
x = temp;
return is;
}
template <class charT, class traits, size_t N> _UCXXEXPORT basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>& os, const bitset<N>& x)
{
for(size_t i = N ; i > 0; --i){
if(x.test(i-1) == true){
os << "1";
}else{
os << "0";
}
}
return os;
}
}
#pragma GCC visibility pop
#endif