/*++ Copyright (c) 1997 Microsoft Corporation All rights reserved. Module Name: bitarray.cxx Abstract: Common utils. Author: Steve Kiraly (SteveKi) 01-12-97 Revision History: --*/ #include "spllibp.hxx" #pragma hdrstop /******************************************************************** Bit Array class ********************************************************************/ TBitArray:: TBitArray( IN UINT nBits, IN UINT uGrowSize ) : _nBits( nBits ), _pBits( NULL ), _uGrowSize( uGrowSize ) { DBGMSG( DBG_TRACE, ( "TBitArray::ctor\n" ) ); // // If the initial number of bits is not specified then // create a default bit array size. // if( !_nBits ) { _nBits = kBitsInType; } // // This could fail, thus leaving the bit array // in an invalid state, Note _pBits being true is // the bValid check. // _pBits = new Type [ nBitsToType( _nBits ) ]; if( _pBits ) { // // The grow size should be at least the // number of bits in the type. // if( _uGrowSize < kBitsInType ) { _uGrowSize = kBitsInType; } // // Clear all the bits. // memset( _pBits, 0, nBitsToType( _nBits ) * sizeof( Type ) ); } } TBitArray:: TBitArray( const TBitArray &rhs ) : _nBits( kBitsInType ), _pBits( NULL ) { DBGMSG( DBG_TRACE, ( "TBitArray::copy_ctor\n" ) ); bClone( rhs ); } const TBitArray & TBitArray:: operator =( const TBitArray &rhs ) { DBGMSG( DBG_TRACE, ( "TBitArray::operator =\n" ) ); bClone( rhs ); return *this; } TBitArray:: ~TBitArray( VOID ) { DBGMSG( DBG_TRACE, ( "TBitArray::dtor\n" ) ); delete [] _pBits; } BOOL TBitArray:: bValid( VOID ) const { return _pBits != NULL; } BOOL TBitArray:: bToString( IN TString &strBits ) const { BOOL bStatus = bValid(); if( bStatus ) { TString strString; strBits.bUpdate( NULL ); // // Get the upper bound bit. // UINT uIndex = _nBits - 1; // // Print the array in reverse order to make the bit array // appear as one large binary number. // for( UINT i = 0; i < _nBits; i++, uIndex-- ) { strString.bFormat( TEXT( "%d" ), bRead( uIndex ) ); strBits.bCat( strString ); } bStatus = strBits.bValid(); } return bStatus; } BOOL TBitArray:: bRead( IN UINT Bit ) const { BOOL bStatus = bIsValidBit( Bit ); if( bStatus ) { bStatus = _pBits[BitToIndex( Bit )] & BitToMask( Bit ) ? TRUE : FALSE; } return bStatus; } BOOL TBitArray:: bSet( IN UINT Bit ) { BOOL bStatus = bIsValidBit( Bit ); if( bStatus ) { _pBits[BitToIndex( Bit )] |= BitToMask( Bit ); } return bStatus; } BOOL TBitArray:: bReset( IN UINT Bit ) { BOOL bStatus = bIsValidBit( Bit ); if( bStatus ) { _pBits[BitToIndex( Bit )] &= ~BitToMask( Bit ); } return bStatus; } BOOL TBitArray:: bToggle( IN UINT Bit ) { BOOL bStatus = bIsValidBit( Bit ); if( bStatus ) { _pBits[BitToIndex( Bit )] ^= BitToMask( Bit ); } return bStatus; } // // Add one new bit to the end of the bit array. // If multiple bits need to be added the user of the // class should call this routine repeatedly. // BOOL TBitArray:: bAdd( VOID ) { BOOL bStatus = FALSE; UINT Bit = _nBits + 1; // // Check if there is room in the array for one more bit. // if( Bit <= nBitsToType( _nBits ) * kBitsInType ) { // // Update the current bit count and return true. // _nBits = Bit; bStatus = TRUE; } else { // // Grow the bit array. // bStatus = bGrow( Bit ); } return bStatus; } VOID TBitArray:: vSetAll( VOID ) { for( UINT i = 0; i < _nBits; i++ ) { bSet( i ); } } VOID TBitArray:: vResetAll( VOID ) { for( UINT i = 0; i < _nBits; i++ ) { bReset( i ); } } UINT TBitArray:: uNumBits( VOID ) const { return _nBits; } BOOL TBitArray:: bFindNextResetBit( IN UINT *puNextFreeBit ) { BOOL bStatus = bValid(); if( bStatus ) { BOOL bFound = FALSE; // // Locate the first type that contains at least one cleared bit. // for( UINT i = 0; i < nBitsToType( _nBits ); i++ ) { if( _pBits[i] != kBitsInTypeMask ) { // // Search for the bit that is cleared. // for( UINT j = 0; j < kBitsInType; j++ ) { if( !( _pBits[i] & BitToMask( j ) ) ) { *puNextFreeBit = i * kBitsInType + j; bFound = TRUE; break; } } } // // Free bit found terminate the search. // if( bFound ) { break; } } // // Free bit was not found then grow the bit array // if( !bFound ) { // // Assume a new bit will be added. // *puNextFreeBit = uNumBits(); // // Add a new bit. // bStatus = bAdd(); } } return bStatus; } /******************************************************************** Bit Array - private member functions. ********************************************************************/ BOOL TBitArray:: bClone( const TBitArray &rhs ) { BOOL bStatus = FALSE; if( this == &rhs ) { bStatus = TRUE; } else { Type *pTempBits = new Type [ nBitsToType( _nBits ) ]; if( pTempBits ) { memcpy( pTempBits, rhs._pBits, nBitsToType( _nBits ) * sizeof( Type ) ); delete [] _pBits; _pBits = pTempBits; _nBits = rhs._nBits; bStatus = TRUE; } } return bStatus; } BOOL TBitArray:: bGrow( IN UINT uBits ) { DBGMSG( DBG_TRACE, ( "TBitArray::bGrow\n" ) ); BOOL bStatus = FALSE; UINT uNewBits = uBits + _uGrowSize; DBGMSG( DBG_TRACE, ( "Grow to size %d Original size %d Buffer pointer %x\n", uNewBits, _nBits, _pBits ) ); // // We do support reducing the size of the bit array. // SPLASSERT( uNewBits > _nBits ); // // Allocate the enlarged bit array. // Type *pNewBits = new Type [ nBitsToType( uNewBits ) ]; if( pNewBits ) { // // Clear the new bits. // memset( pNewBits, 0, nBitsToType( uNewBits ) * sizeof( Type ) ); // // Copy the old bits to the new bit array. // memcpy( pNewBits, _pBits, nBitsToType( _nBits ) * sizeof( Type ) ); // // Release the old bit array and save the new pointer and size. // delete [] _pBits; _pBits = pNewBits; _nBits = uBits; // // Success. // bStatus = TRUE; } DBGMSG( DBG_TRACE, ( "New size %d Buffer pointer %x\n", _nBits, _pBits ) ); return bStatus; } UINT TBitArray:: nBitsToType( IN UINT uBits ) const { return ( uBits + kBitsInType - 1 ) / kBitsInType; } TBitArray::Type TBitArray:: BitToMask( IN UINT uBit ) const { return 1 << ( uBit % kBitsInType ); } UINT TBitArray:: BitToIndex( IN UINT uBit ) const { return uBit / kBitsInType; } BOOL TBitArray:: bIsValidBit( IN UINT uBit ) const { BOOL bStatus = ( uBit < _nBits ) && bValid(); if( !bStatus ) { DBGMSG( DBG_TRACE, ( "Invalid bit value %d\n", uBit ) ); } return bStatus; }