windows-nt/Source/XPSP1/NT/printscan/print/spooler/spllib/bitarray.cxx
2020-09-26 16:20:57 +08:00

478 lines
7.9 KiB
C++

/*++
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;
}