blob: 999c53e0d36dcb791d9126353ff0e9ae05dad314 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sfx2.hxx"
#include <tools/debug.hxx>
#ifndef GCC
#endif
#include "bitset.hxx"
#include <string.h> // memset(), memcpy()
#include <limits.h> // USHRT_MAX
//====================================================================
// add nOffset to each bit-value in the set
BitSet BitSet::operator<<( sal_uInt16 nOffset ) const
{
DBG_MEMTEST();
// create a work-copy, return it if nothing to shift
BitSet aSet(*this);
if ( nOffset == 0 )
return aSet;
// compute the shiftment in long-words and bits
sal_uInt16 nBlockDiff = nOffset / 32;
sal_uIntPtr nBitValDiff = nOffset % 32;
// compute the new number of bits
for ( sal_uInt16 nBlock = 0; nBlock < nBlockDiff; ++nBlock )
aSet.nCount = aSet.nCount - CountBits( *(aSet.pBitmap+nBlock) );
aSet.nCount = aSet.nCount -
CountBits( *(aSet.pBitmap+nBlockDiff) >> (32-nBitValDiff) );
// shift complete long-words
sal_uInt16 nTarget, nSource;
for ( nTarget = 0, nSource = nBlockDiff;
(nSource+1) < aSet.nBlocks;
++nTarget, ++nSource )
*(aSet.pBitmap+nTarget) =
( *(aSet.pBitmap+nSource) << nBitValDiff ) |
( *(aSet.pBitmap+nSource+1) >> (32-nBitValDiff) );
// shift the remainder (if in total minor 32 bits, only this)
*(aSet.pBitmap+nTarget) = *(aSet.pBitmap+nSource) << nBitValDiff;
// determine the last used block
while ( *(aSet.pBitmap+nTarget) == 0 )
--nTarget;
// shorten the block-array
if ( nTarget < aSet.nBlocks )
{
sal_uIntPtr* pNewMap = new sal_uIntPtr[nTarget];
memcpy( pNewMap, aSet.pBitmap, 4 * nTarget );
delete [] aSet.pBitmap;
aSet.pBitmap = pNewMap;
aSet.nBlocks = nTarget;
}
return aSet;
}
//--------------------------------------------------------------------
// substracts nOffset from each bit-value in the set
BitSet BitSet::operator>>( sal_uInt16 ) const
{
DBG_MEMTEST();
return BitSet();
}
//--------------------------------------------------------------------
// internal code for operator= and copy-ctor
void BitSet::CopyFrom( const BitSet& rSet )
{
DBG_MEMTEST();
nCount = rSet.nCount;
nBlocks = rSet.nBlocks;
if ( rSet.nBlocks )
{
DBG_MEMTEST();
pBitmap = new sal_uIntPtr[nBlocks];
memcpy( pBitmap, rSet.pBitmap, 4 * nBlocks );
}
else
pBitmap = 0;
}
//--------------------------------------------------------------------
// creates an empty bitset
BitSet::BitSet()
{
DBG_MEMTEST();
nCount = 0;
nBlocks = 0;
pBitmap = 0;
}
//--------------------------------------------------------------------
// creates a copy of bitset rOrig
BitSet::BitSet( const BitSet& rOrig )
{
DBG_MEMTEST();
CopyFrom(rOrig);
}
//--------------------------------------------------------------------
// creates a bitset from an array
BitSet::BitSet( sal_uInt16* pArray, sal_uInt16 nSize ):
nCount(nSize)
{
DBG_MEMTEST();
// find the highest bit to set
sal_uInt16 nMax = 0;
for ( sal_uInt16 n = 0; n < nCount; ++n )
if ( pArray[n] > nMax )
nMax = pArray[n];
// if there are bits at all
if ( nMax > 0 )
{
// allocate memory for all blocks needed
nBlocks = nMax / 32 + 1;
pBitmap = new sal_uIntPtr[nBlocks];
memset( pBitmap, 0, 4 * nBlocks );
// set all the bits
for ( sal_uInt16 n = 0; n < nCount; ++n )
{
// compute the block no. and bitvalue
sal_uInt16 nBlock = n / 32;
sal_uIntPtr nBitVal = 1L << (n % 32);
// set a single bit
if ( ( *(pBitmap+nBlock) & nBitVal ) == 0 )
{
*(pBitmap+nBlock) |= nBitVal;
++nCount;
}
}
}
else
{
// initalize emtpy set
nBlocks = 0;
pBitmap = 0;
}
}
//--------------------------------------------------------------------
// frees the storage
BitSet::~BitSet()
{
DBG_MEMTEST();
delete [] pBitmap;
}
//--------------------------------------------------------------------
// creates a bitmap with all bits in rRange set
BitSet::BitSet( const Range& )
{
DBG_MEMTEST();
}
//--------------------------------------------------------------------
// assignment from another bitset
BitSet& BitSet::operator=( const BitSet& rOrig )
{
DBG_MEMTEST();
if ( this != &rOrig )
{
delete [] pBitmap;
CopyFrom(rOrig);
}
return *this;
}
//--------------------------------------------------------------------
// assignment from a single bit
BitSet& BitSet::operator=( sal_uInt16 nBit )
{
DBG_MEMTEST();
delete [] pBitmap;
nBlocks = nBit / 32;
sal_uIntPtr nBitVal = 1L << (nBit % 32);
nCount = 1;
pBitmap = new sal_uIntPtr[nBlocks];
memset( pBitmap + nBlocks, 0, 4 * nBlocks );
*(pBitmap+nBlocks) = nBitVal;
return *this;
}
//--------------------------------------------------------------------
// creates the asymetric difference with another bitset
BitSet& BitSet::operator-=(sal_uInt16 nBit)
{
DBG_MEMTEST();
sal_uInt16 nBlock = nBit / 32;
sal_uIntPtr nBitVal = 1L << (nBit % 32);
if ( nBlock >= nBlocks )
return *this;
if ( (*(pBitmap+nBlock) & nBitVal) )
{
*(pBitmap+nBlock) &= ~nBitVal;
--nCount;
}
return *this;
}
//--------------------------------------------------------------------
// unites with the bits of rSet
BitSet& BitSet::operator|=( const BitSet& rSet )
{
DBG_MEMTEST();
sal_uInt16 nMax = Min(nBlocks, rSet.nBlocks);
// expand the bitmap
if ( nBlocks < rSet.nBlocks )
{
sal_uIntPtr *pNewMap = new sal_uIntPtr[rSet.nBlocks];
memset( pNewMap + nBlocks, 0, 4 * (rSet.nBlocks - nBlocks) );
if ( pBitmap )
{
memcpy( pNewMap, pBitmap, 4 * nBlocks );
delete [] pBitmap;
}
pBitmap = pNewMap;
nBlocks = rSet.nBlocks;
}
// add the bits blocks by block
for ( sal_uInt16 nBlock = 0; nBlock < nMax; ++nBlock )
{
// compute numberof additional bits
sal_uIntPtr nDiff = ~*(pBitmap+nBlock) & *(rSet.pBitmap+nBlock);
nCount = nCount + CountBits(nDiff);
*(pBitmap+nBlock) |= *(rSet.pBitmap+nBlock);
}
return *this;
}
//--------------------------------------------------------------------
// unites with a single bit
BitSet& BitSet::operator|=( sal_uInt16 nBit )
{
DBG_MEMTEST();
sal_uInt16 nBlock = nBit / 32;
sal_uIntPtr nBitVal = 1L << (nBit % 32);
if ( nBlock >= nBlocks )
{
sal_uIntPtr *pNewMap = new sal_uIntPtr[nBlock+1];
memset( pNewMap + nBlocks, 0, 4 * (nBlock - nBlocks + 1) );
if ( pBitmap )
{
memcpy( pNewMap, pBitmap, 4 * nBlocks );
delete [] pBitmap;
}
pBitmap = pNewMap;
nBlocks = nBlock+1;
}
if ( (*(pBitmap+nBlock) & nBitVal) == 0 )
{
*(pBitmap+nBlock) |= nBitVal;
++nCount;
}
return *this;
}
//--------------------------------------------------------------------
// determines if the bit is set (may be the only one)
sal_Bool BitSet::Contains( sal_uInt16 nBit ) const
{
DBG_MEMTEST();
sal_uInt16 nBlock = nBit / 32;
sal_uIntPtr nBitVal = 1L << (nBit % 32);
if ( nBlock >= nBlocks )
return sal_False;
return ( nBitVal & *(pBitmap+nBlock) ) == nBitVal;
}
//--------------------------------------------------------------------
// determines if the bitsets are equal
sal_Bool BitSet::operator==( const BitSet& rSet ) const
{
DBG_MEMTEST();
if ( nBlocks != rSet.nBlocks )
return sal_False;
sal_uInt16 nBlock = nBlocks;
while ( nBlock-- > 0 )
if ( *(pBitmap+nBlock) != *(rSet.pBitmap+nBlock) )
return sal_False;
return sal_True;
}
//--------------------------------------------------------------------
// counts the number of 1-bits in the parameter
sal_uInt16 BitSet::CountBits( sal_uIntPtr nBits )
{
sal_uInt16 nCount = 0;
int nBit = 32;
while ( nBit-- && nBits )
{ if ( ( (long)nBits ) < 0 )
++nCount;
nBits = nBits << 1;
}
return nCount;
}
//--------------------------------------------------------------------
sal_uInt16 IndexBitSet::GetFreeIndex()
{
for(sal_uInt16 i=0;i<USHRT_MAX;i++)
if(!Contains(i))
{
*this|=i;
return i;
}
DBG_ASSERT(sal_False, "IndexBitSet enthaelt mehr als USHRT_MAX Eintraege");
return 0;
}