Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / sfx2 / source / bastyp / bitset.cxx
blob1b5e750f9513a1d0fd35e23f2c341d90d80a9d80
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #include <tools/debug.hxx>
31 #include "bitset.hxx"
33 #include <string.h> // memset(), memcpy()
34 #include <limits.h> // USHRT_MAX
36 //====================================================================
37 // add nOffset to each bit-value in the set
39 BitSet BitSet::operator<<( sal_uInt16 nOffset ) const
41 // create a work-copy, return it if nothing to shift
42 BitSet aSet(*this);
43 if ( nOffset == 0 )
44 return aSet;
46 // compute the shiftment in long-words and bits
47 sal_uInt16 nBlockDiff = nOffset / 32;
48 sal_uIntPtr nBitValDiff = nOffset % 32;
50 // compute the new number of bits
51 for ( sal_uInt16 nBlock = 0; nBlock < nBlockDiff; ++nBlock )
52 aSet.nCount = aSet.nCount - CountBits( *(aSet.pBitmap+nBlock) );
53 aSet.nCount = aSet.nCount -
54 CountBits( *(aSet.pBitmap+nBlockDiff) >> (32-nBitValDiff) );
56 // shift complete long-words
57 sal_uInt16 nTarget, nSource;
58 for ( nTarget = 0, nSource = nBlockDiff;
59 (nSource+1) < aSet.nBlocks;
60 ++nTarget, ++nSource )
61 *(aSet.pBitmap+nTarget) =
62 ( *(aSet.pBitmap+nSource) << nBitValDiff ) |
63 ( *(aSet.pBitmap+nSource+1) >> (32-nBitValDiff) );
65 // shift the remainder (if in total minor 32 bits, only this)
66 *(aSet.pBitmap+nTarget) = *(aSet.pBitmap+nSource) << nBitValDiff;
68 // determine the last used block
69 while ( *(aSet.pBitmap+nTarget) == 0 )
70 --nTarget;
72 // shorten the block-array
73 if ( nTarget < aSet.nBlocks )
75 sal_uIntPtr* pNewMap = new sal_uIntPtr[nTarget];
76 memcpy( pNewMap, aSet.pBitmap, 4 * nTarget );
77 delete [] aSet.pBitmap;
78 aSet.pBitmap = pNewMap;
79 aSet.nBlocks = nTarget;
82 return aSet;
85 //--------------------------------------------------------------------
87 // substracts nOffset from each bit-value in the set
89 BitSet BitSet::operator>>( sal_uInt16 ) const
91 return BitSet();
94 //--------------------------------------------------------------------
96 // internal code for operator= and copy-ctor
98 void BitSet::CopyFrom( const BitSet& rSet )
100 nCount = rSet.nCount;
101 nBlocks = rSet.nBlocks;
102 if ( rSet.nBlocks )
104 pBitmap = new sal_uIntPtr[nBlocks];
105 memcpy( pBitmap, rSet.pBitmap, 4 * nBlocks );
107 else
108 pBitmap = 0;
111 //--------------------------------------------------------------------
113 // creates an empty bitset
115 BitSet::BitSet()
117 nCount = 0;
118 nBlocks = 0;
119 pBitmap = 0;
122 //--------------------------------------------------------------------
124 // creates a copy of bitset rOrig
126 BitSet::BitSet( const BitSet& rOrig )
128 CopyFrom(rOrig);
131 //--------------------------------------------------------------------
133 // frees the storage
135 BitSet::~BitSet()
137 delete [] pBitmap;
140 //--------------------------------------------------------------------
142 // assignment from another bitset
144 BitSet& BitSet::operator=( const BitSet& rOrig )
146 if ( this != &rOrig )
148 delete [] pBitmap;
149 CopyFrom(rOrig);
151 return *this;
154 //--------------------------------------------------------------------
156 // assignment from a single bit
158 BitSet& BitSet::operator=( sal_uInt16 nBit )
160 delete [] pBitmap;
162 nBlocks = nBit / 32;
163 sal_uIntPtr nBitVal = 1L << (nBit % 32);
164 nCount = 1;
166 pBitmap = new sal_uIntPtr[nBlocks + 1];
167 memset( pBitmap, 0, 4 * (nBlocks + 1) );
169 *(pBitmap+nBlocks) = nBitVal;
171 return *this;
174 //--------------------------------------------------------------------
176 // creates the asymetric difference with another bitset
178 BitSet& BitSet::operator-=(sal_uInt16 nBit)
180 sal_uInt16 nBlock = nBit / 32;
181 sal_uIntPtr nBitVal = 1L << (nBit % 32);
183 if ( nBlock >= nBlocks )
184 return *this;
186 if ( (*(pBitmap+nBlock) & nBitVal) )
188 *(pBitmap+nBlock) &= ~nBitVal;
189 --nCount;
192 return *this;
195 //--------------------------------------------------------------------
197 // unites with the bits of rSet
199 BitSet& BitSet::operator|=( const BitSet& rSet )
201 sal_uInt16 nMax = Min(nBlocks, rSet.nBlocks);
203 // expand the bitmap
204 if ( nBlocks < rSet.nBlocks )
206 sal_uIntPtr *pNewMap = new sal_uIntPtr[rSet.nBlocks];
207 memset( pNewMap + nBlocks, 0, 4 * (rSet.nBlocks - nBlocks) );
209 if ( pBitmap )
211 memcpy( pNewMap, pBitmap, 4 * nBlocks );
212 delete [] pBitmap;
214 pBitmap = pNewMap;
215 nBlocks = rSet.nBlocks;
218 // add the bits blocks by block
219 for ( sal_uInt16 nBlock = 0; nBlock < nMax; ++nBlock )
221 // compute numberof additional bits
222 sal_uIntPtr nDiff = ~*(pBitmap+nBlock) & *(rSet.pBitmap+nBlock);
223 nCount = nCount + CountBits(nDiff);
225 *(pBitmap+nBlock) |= *(rSet.pBitmap+nBlock);
228 return *this;
231 //--------------------------------------------------------------------
233 // unites with a single bit
235 BitSet& BitSet::operator|=( sal_uInt16 nBit )
237 sal_uInt16 nBlock = nBit / 32;
238 sal_uIntPtr nBitVal = 1L << (nBit % 32);
240 if ( nBlock >= nBlocks )
242 sal_uIntPtr *pNewMap = new sal_uIntPtr[nBlock+1];
243 memset( pNewMap + nBlocks, 0, 4 * (nBlock - nBlocks + 1) );
245 if ( pBitmap )
247 memcpy( pNewMap, pBitmap, 4 * nBlocks );
248 delete [] pBitmap;
250 pBitmap = pNewMap;
251 nBlocks = nBlock+1;
254 if ( (*(pBitmap+nBlock) & nBitVal) == 0 )
256 *(pBitmap+nBlock) |= nBitVal;
257 ++nCount;
260 return *this;
263 //--------------------------------------------------------------------
265 // determines if the bit is set (may be the only one)
267 sal_Bool BitSet::Contains( sal_uInt16 nBit ) const
269 sal_uInt16 nBlock = nBit / 32;
270 sal_uIntPtr nBitVal = 1L << (nBit % 32);
272 if ( nBlock >= nBlocks )
273 return sal_False;
274 return ( nBitVal & *(pBitmap+nBlock) ) == nBitVal;
277 //--------------------------------------------------------------------
279 // determines if the bitsets are equal
281 sal_Bool BitSet::operator==( const BitSet& rSet ) const
283 if ( nBlocks != rSet.nBlocks )
284 return sal_False;
286 sal_uInt16 nBlock = nBlocks;
287 while ( nBlock-- > 0 )
288 if ( *(pBitmap+nBlock) != *(rSet.pBitmap+nBlock) )
289 return sal_False;
291 return sal_True;
294 //--------------------------------------------------------------------
296 // counts the number of 1-bits in the parameter
298 sal_uInt16 BitSet::CountBits( sal_uIntPtr nBits )
300 sal_uInt16 nCount = 0;
301 int nBit = 32;
302 while ( nBit-- && nBits )
303 { if ( ( (long)nBits ) < 0 )
304 ++nCount;
305 nBits = nBits << 1;
307 return nCount;
310 //--------------------------------------------------------------------
312 sal_uInt16 IndexBitSet::GetFreeIndex()
314 for(sal_uInt16 i=0;i<USHRT_MAX;i++)
315 if(!Contains(i))
317 *this|=i;
318 return i;
320 DBG_ASSERT(sal_False, "IndexBitSet enthaelt mehr als USHRT_MAX Eintraege");
321 return 0;
325 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */