Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

base/BitArray

Go to the documentation of this file.
00001 // A one-dimensional array of bits, similar to STL bitset.
00002 //
00003 // Copyright 2000 Andrew Kirmse.  All rights reserved.
00004 //
00005 // Permission is granted to use this code for any purpose, as long as this
00006 // copyright message remains intact.
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    // Constructors and destructor
00021    //
00022    
00023    explicit BitArray(unsigned size)
00024    {
00025       Init(size);
00026 
00027       // Clear last bits
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    // Operators
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    // Plain English interface
00137    //
00138    
00139    // Set all bits to false.
00140    void Clear()
00141    {
00142       memset(mpStore, 0, mLength * sizeof(store_type));
00143    }
00144    
00145    // Set the bit at position pos to true.
00146    void SetBit(unsigned pos)
00147    {
00148       Assert(pos < mNumBits);
00149       mpStore[GetIndex(pos)] |= 1 << GetOffset(pos); 
00150    }
00151 
00152    // Set the bit at position pos to false.
00153    void ClearBit(unsigned pos)
00154    { 
00155       Assert(pos < mNumBits);
00156       mpStore[GetIndex(pos)] &= ~(1 << GetOffset(pos)); 
00157    }
00158 
00159    // Toggle the bit at position pos.
00160    void FlipBit(unsigned pos) 
00161    { 
00162       Assert(pos < mNumBits);
00163       mpStore[GetIndex(pos)] ^= 1 << GetOffset(pos); 
00164    }
00165 
00166    // Set the bit at position pos to the given value.
00167    void Set(unsigned pos, bool val)
00168    { 
00169       val ? SetBit(pos) : ClearBit(pos);
00170    }
00171 
00172    // Returns true iff the bit at position pos is true.
00173    bool IsBitSet(unsigned pos) const
00174    {
00175       Assert(pos < mNumBits);
00176       return (mpStore[GetIndex(pos)] & (1 << GetOffset(pos))) != 0;
00177    }
00178 
00179    // Returns true iff all bits are false.
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    // Change value of all bits
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    // Bit proxy (for operator[])
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; // Use this buffer when mLength is 1
00250    unsigned           mLength;     // Length of mpStore in units of store_type
00251    unsigned           mNumBits;
00252 
00253    // Get the index and bit offset for a given bit number.
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       // Avoid allocation if length is 1 (common case)
00274       if (mLength <= 1)
00275          mpStore = &mSingleWord;      
00276       else
00277          mpStore = new store_type[mLength];
00278    }
00279    
00280    // Force overhang bits at the end to 0
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 } // base
00290 
00291 #endif

Generated on Thu Jul 29 15:56:04 2004 for OpenSim by doxygen 1.3.6