#ifndef _INC_DSKQUOTA_BITSET_H #define _INC_DSKQUOTA_BITSET_H #ifndef _INC_DSKQUOTA_EXCEPT_H # include "except.h" #endif // Macros & Constants // ELEMENT_TYPE // This macro defines the type of each "element" in the bit buffer. // This type must be an integral type that can be used as an operand // in bitwise expressions. If it is changed, the macros // ELEMENT_BITNUM_MASK and ELEMENT_SHIFT must also be changed as // follows: // ELEMENT_TYPE ELEMENT_BITNUM_MASK ELEMENT_SHIFT // ---------------- ----------------------- ------------------- // BYTE 0x00000007 3 // WORD 0x0000000F 4 // DWORD 0x0000001F 5 // ELEMENT_BITNUM_MASK // This macro defines the mask used to extract the number of the // bit in the array element from the number of the bit being accessed. // ELEMENT_SHIFT // This macro defines the number of bits to right shift the bit number // to obtain the number of the array element. #define ELEMENT_TYPE BYTE const int ELEMENT_BITNUM_MASK = 0x00000007; const int ELEMENT_SHIFT = 3; // Forward declaration. class BitSet; // This is a "helper" class that aids BitSet::operator[]. So that // BitSet::operator[] functions properly for both lvalue and rvalue // conditions, it returns a "Bit" object. The bit object retains the // bit number and a pointer to the "owner" BitSet object. It also // overloads the bool conversion operator and assignment operator. // Knowing the bit number and the owner BitSet, the class can set or // obtain the value of the bit in the BitSet's array. class Bit { public: Bit(int iBit, BitSet *pOwnerSet = NULL) : m_iBit(iBit), m_pOwnerSet(pOwnerSet) { } Bit(Bit& bit) : m_iBit(bit.m_iBit), m_pOwnerSet(bit.m_pOwnerSet) { } // Convert value of bit to a bool. operator bool () const; // Set bit to a bool value. bool operator = (bool bState); private: DWORD m_iBit; // Number of bit in BitSet [0 to n-1] BitSet *m_pOwnerSet; // Ptr to BitSet object. }; class BitSet { public: BitSet(int cBits = 1); ~BitSet(void); BitSet(const BitSet& rhs); BitSet& operator = (const BitSet& rhs); void Initialize(int cBits); int Count(void) const { return m_cBits; } int CountSet(void) const { return m_cSet; } int CountClr(void) const { return m_cBits - m_cSet; } bool IsSet(int iBit) const { return GetBitState(iBit); } bool IsClr(int iBit) const { return !GetBitState(iBit); } void Complement(void); // SetBitState and GetBitState are the fastest // ways to alter or retrieve the state of a bit. void SetBitState(int iBit, bool bSet); bool GetBitState(int iBit) const; // Set and Clr are the next fastest ways to alter // or retrieve the state of a bit. void Set(int iBit) { SetBitState(iBit, TRUE); } void Clr(int iBit) { SetBitState(iBit, FALSE); } // Using the subscript operator is the slowest way // to alter/retrieve the state of a bit. Bit operator [] (int iBit) { return Bit(iBit, this); } void ClrAll(void) { ZeroMemory(m_pBuffer, sizeof(ELEMENT_TYPE) * m_cElements); m_cSet = 0; } void SetAll(void) { FillMemory(m_pBuffer, sizeof(ELEMENT_TYPE) * m_cElements, (BYTE)0xFF); m_cSet = m_cBits; } #if DBG void Dump(void) const; #endif private: ELEMENT_TYPE *m_pBuffer; // Array of elements. int m_cBits; // Bits supported in set. int m_cSet; // Number of bits set to '1'. int m_cElements; // Number of elements in array. // Inline functions for calculating bit/element positions in array. DWORD BitInElement(int iBit) const { return (iBit & ELEMENT_BITNUM_MASK); } DWORD ElementInBuffer(int iBit) const { return (iBit >> ELEMENT_SHIFT); } ELEMENT_TYPE MaskFromBit(int iBit) const { return 1 << BitInElement(iBit); } void ValidateBitNumber(int iBit) const { if (iBit >= m_cBits) throw CMemoryException(CMemoryException::index); } friend class Bit; }; inline Bit::operator bool () const { return m_pOwnerSet->GetBitState(m_iBit); } inline bool Bit::operator = (bool bState) { m_pOwnerSet->SetBitState(m_iBit, bState); return bState; } #endif // _INC_DSKQUOTA_BITSET_H