00001
00002
00003
00004
00005
00006
00007
00008 #ifndef _BASE_BITARRAY_
00009 #define _BASE_BITARRAY_
00010
00011 #include <memory>
00012
00013 namespace base {
00014
00015 class BitArray
00016 {
00017 public:
00018
00019
00020
00021
00022
00023 explicit BitArray(unsigned size)
00024 {
00025 Init(size);
00026
00027
00028 Trim();
00029 }
00030
00031 BitArray(const BitArray &that)
00032 {
00033 mpStore = 0;
00034 *this = that;
00035 }
00036
00037 virtual ~BitArray()
00038 {
00039 if (mLength > 1)
00040 delete[] mpStore;
00041 }
00042
00043
00044
00045
00046
00047 class BitProxy;
00048
00049 BitArray &operator=(const BitArray &that)
00050 {
00051 if (this != &that)
00052 {
00053 if (mLength > 1)
00054 delete[] mpStore;
00055
00056 Init(that.mNumBits);
00057
00058 memcpy(mpStore, that.mpStore, mLength * sizeof(store_type));
00059 }
00060 return *this;
00061 }
00062
00063 BitProxy operator[](unsigned pos)
00064 {
00065 Assert(pos < mNumBits);
00066 return BitProxy(*this, pos);
00067 }
00068
00069 const BitProxy operator[](unsigned pos) const
00070 {
00071 Assert(pos < mNumBits);
00072 return BitProxy(const_cast<BitArray &>(*this), pos);
00073 }
00074
00075 bool operator==(const BitArray &that) const
00076 {
00077 if (mNumBits != that.mNumBits)
00078 return false;
00079
00080 for (unsigned i = 0; i < mLength; i++)
00081 if (mpStore[i] != that.mpStore[i])
00082 return false;
00083 return true;
00084 }
00085
00086 bool operator!=(const BitArray &that) const
00087 {
00088 return !(*this == that);
00089 }
00090
00091 BitArray &operator&=(const BitArray &that)
00092 {
00093 Assert(mNumBits == that.mNumBits);
00094 for (unsigned i = 0; i < mLength; i++)
00095 mpStore[i] &= that.mpStore[i];
00096 return *this;
00097 }
00098
00099 BitArray operator|=(const BitArray &that)
00100 {
00101 Assert(mNumBits == that.mNumBits);
00102 for (unsigned i = 0; i < mLength; i++)
00103 mpStore[i] |= that.mpStore[i];
00104 return *this;
00105 }
00106
00107 BitArray operator^=(const BitArray &that)
00108 {
00109 Assert(mNumBits == that.mNumBits);
00110 for (unsigned i = 0; i < mLength; i++)
00111 mpStore[i] ^= that.mpStore[i];
00112 return *this;
00113 }
00114
00115 BitArray operator~() const
00116 {
00117 return BitArray(*this).FlipAllBits();
00118 }
00119
00120 friend BitArray operator&(const BitArray &a1, const BitArray &a2)
00121 {
00122 return BitArray(a1) &= a2;
00123 }
00124
00125 friend BitArray operator|(const BitArray &a1, const BitArray &a2)
00126 {
00127 return BitArray(a1) |= a2;
00128 }
00129
00130 friend BitArray operator^(const BitArray &a1, const BitArray &a2)
00131 {
00132 return BitArray(a1) ^= a2;
00133 }
00134
00135
00136
00137
00138
00139
00140 void Clear()
00141 {
00142 memset(mpStore, 0, mLength * sizeof(store_type));
00143 }
00144
00145
00146 void SetBit(unsigned pos)
00147 {
00148 Assert(pos < mNumBits);
00149 mpStore[GetIndex(pos)] |= 1 << GetOffset(pos);
00150 }
00151
00152
00153 void ClearBit(unsigned pos)
00154 {
00155 Assert(pos < mNumBits);
00156 mpStore[GetIndex(pos)] &= ~(1 << GetOffset(pos));
00157 }
00158
00159
00160 void FlipBit(unsigned pos)
00161 {
00162 Assert(pos < mNumBits);
00163 mpStore[GetIndex(pos)] ^= 1 << GetOffset(pos);
00164 }
00165
00166
00167 void Set(unsigned pos, bool val)
00168 {
00169 val ? SetBit(pos) : ClearBit(pos);
00170 }
00171
00172
00173 bool IsBitSet(unsigned pos) const
00174 {
00175 Assert(pos < mNumBits);
00176 return (mpStore[GetIndex(pos)] & (1 << GetOffset(pos))) != 0;
00177 }
00178
00179
00180 bool AllBitsFalse() const
00181 {
00182 for (unsigned i=0; i < mLength; i++)
00183 if (mpStore[i] != 0)
00184 return false;
00185 return true;
00186 }
00187
00188
00189 BitArray &FlipAllBits()
00190 {
00191 for (unsigned i=0; i < mLength; i++)
00192 mpStore[i] = ~mpStore[i];
00193
00194 Trim();
00195 return *this;
00196 }
00197
00198
00199
00200
00201
00202 friend class BitProxy;
00203
00204 class BitProxy
00205 {
00206 public:
00207 BitProxy(BitArray &array, unsigned pos):
00208 mArray(array), mPos(pos)
00209 {}
00210
00211 BitProxy &operator=(bool value)
00212 {
00213 mArray.Set(mPos, value);
00214 return *this;
00215 }
00216
00217 BitProxy &operator=(const BitProxy &that)
00218 {
00219 mArray.Set(mPos, that.mArray.IsBitSet(that.mPos));
00220 return *this;
00221 }
00222
00223 operator bool() const
00224 {
00225 return mArray.IsBitSet(mPos);
00226 }
00227
00228 bool Flip()
00229 {
00230 mArray.FlipBit(mPos);
00231 return mArray.IsBitSet(mPos);
00232 }
00233
00234 private:
00235 BitArray &mArray;
00236 unsigned mPos;
00237 };
00238
00239 private:
00240
00241 typedef unsigned long store_type;
00242 enum
00243 {
00244 bits_per_byte = 8,
00245 cell_size = sizeof(store_type) * bits_per_byte
00246 };
00247
00248 store_type *mpStore;
00249 store_type mSingleWord;
00250 unsigned mLength;
00251 unsigned mNumBits;
00252
00253
00254 static unsigned GetIndex(unsigned bit_num)
00255 {
00256 return bit_num / cell_size;
00257 }
00258
00259 static unsigned GetOffset(unsigned bit_num)
00260 {
00261 return bit_num % cell_size;
00262 }
00263
00264 void Init(unsigned size)
00265 {
00266 mNumBits = size;
00267
00268 if (size == 0)
00269 mLength = 0;
00270 else
00271 mLength = 1 + GetIndex(size - 1);
00272
00273
00274 if (mLength <= 1)
00275 mpStore = &mSingleWord;
00276 else
00277 mpStore = new store_type[mLength];
00278 }
00279
00280
00281 inline void Trim()
00282 {
00283 unsigned extra_bits = mNumBits % cell_size;
00284 if (mLength > 0 && extra_bits != 0)
00285 mpStore[mLength - 1] &= ~((~(store_type) 0) << extra_bits);
00286 }
00287 };
00288
00289 }
00290
00291 #endif