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