/* 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 #include #include #include #include #include #ifndef __STD_BITSET_HEADER #define __STD_BITSET_HEADER 1 namespace std{ template class bitset; template bitset operator&(const bitset&, const bitset&); template bitset operator|(const bitset&, const bitset&); template bitset operator^(const bitset&, const bitset&); template basic_istream& operator>>(basic_istream& is, bitset& x); template basic_ostream& operator<<(basic_ostream& os, const bitset& x); //Actual Code template 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 _UCXXEXPORT explicit bitset( const basic_string& str, typename basic_string::size_type pos = 0, typename basic_string::size_type n = basic_string::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& operator&=(const bitset& rhs){ for(size_t i =0; i < num_bytes; ++i){ data[i] &= rhs.data[i]; } return *this; } bitset& operator|=(const bitset& rhs){ for(size_t i =0; i < num_bytes; ++i){ data[i] |= rhs.data[i]; } return *this; } bitset& operator^=(const bitset& rhs){ for(size_t i=0; i < num_bytes; ++i){ data[i] ^= rhs.data[i]; } return *this; } bitset& 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& 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& set(){ size_t i; for(i = 0; i < N ; ++i){ data[byte_num(i)] |= (1<& set(size_t pos, int val = true){ if(val == true){ data[byte_num(pos)] |= (1<& reset(){ for(size_t i = 0; i <= num_bytes; ++i){ data[i] = 0; } return *this; } bitset& reset(size_t pos){ data[byte_num(pos)] &= ~(1< operator~() const{ bitset retval(*this); retval.flip(); return retval; } bitset& flip(){ for(size_t i = 0; i <= num_bytes; ++i){ data[i] = ~data[i]; } return *this; } bitset& 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< 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 basic_string to_string() const { basic_string 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& operator=(const bitset & 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& rhs) const{ for(size_t i =0; i< N; ++i){ if(test(i) != rhs.test(i)){ return false; } } return true; } bool operator!=(const bitset& 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< operator<<(size_t pos) const{ bitset retval(*this); retval<<=pos; return retval; } bitset operator>>(size_t pos) const{ bitset retval(*this); retval>>=pos; return retval; } }; //Non-member functions template _UCXXEXPORT bitset operator&(const bitset& lhs, const bitset& rhs){ bitset retval(lhs); retval &= rhs; return retval; } template _UCXXEXPORT bitset operator|(const bitset& lhs, const bitset& rhs){ bitset retval(lhs); retval |= rhs; return retval; } template _UCXXEXPORT bitset operator^(const bitset& lhs, const bitset& rhs){ bitset retval(lhs); retval ^= rhs; return retval; } template _UCXXEXPORT basic_istream& operator>>(basic_istream& is, bitset& 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 temp(s); x = temp; return is; } template _UCXXEXPORT basic_ostream& operator<<(basic_ostream& os, const bitset& x) { for(size_t i = N ; i > 0; --i){ if(x.test(i-1) == true){ os << "1"; }else{ os << "0"; } } return os; } } #endif