Bump version to 4.1-6
[LibreOffice.git] / sfx2 / source / bastyp / bitset.cxx
blobf1798f515d812ca58b255cd03592c2bf1c14acc1
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <tools/debug.hxx>
22 #include "bitset.hxx"
24 #include <string.h> // memset(), memcpy()
25 #include <limits.h> // USHRT_MAX
26 #include <algorithm>
28 //====================================================================
29 // add nOffset to each bit-value in the set
31 BitSet BitSet::operator<<( sal_uInt16 nOffset ) const
33 // create a work-copy, return it if nothing to shift
34 BitSet aSet(*this);
35 if ( nOffset == 0 )
36 return aSet;
38 // compute the shiftment in long-words and bits
39 sal_uInt16 nBlockDiff = nOffset / 32;
40 sal_uIntPtr nBitValDiff = nOffset % 32;
42 // compute the new number of bits
43 for ( sal_uInt16 nBlock = 0; nBlock < nBlockDiff; ++nBlock )
44 aSet.nCount = aSet.nCount - CountBits( *(aSet.pBitmap+nBlock) );
45 aSet.nCount = aSet.nCount -
46 CountBits( *(aSet.pBitmap+nBlockDiff) >> (32-nBitValDiff) );
48 // shift complete long-words
49 sal_uInt16 nTarget, nSource;
50 for ( nTarget = 0, nSource = nBlockDiff;
51 (nSource+1) < aSet.nBlocks;
52 ++nTarget, ++nSource )
53 *(aSet.pBitmap+nTarget) =
54 ( *(aSet.pBitmap+nSource) << nBitValDiff ) |
55 ( *(aSet.pBitmap+nSource+1) >> (32-nBitValDiff) );
57 // shift the remainder (if in total minor 32 bits, only this)
58 *(aSet.pBitmap+nTarget) = *(aSet.pBitmap+nSource) << nBitValDiff;
60 // determine the last used block
61 while ( *(aSet.pBitmap+nTarget) == 0 )
62 --nTarget;
64 // shorten the block-array
65 if ( nTarget < aSet.nBlocks )
67 sal_uIntPtr* pNewMap = new sal_uIntPtr[nTarget];
68 memcpy( pNewMap, aSet.pBitmap, 4 * nTarget );
69 delete [] aSet.pBitmap;
70 aSet.pBitmap = pNewMap;
71 aSet.nBlocks = nTarget;
74 return aSet;
77 //--------------------------------------------------------------------
79 // substracts nOffset from each bit-value in the set
81 BitSet BitSet::operator>>( sal_uInt16 ) const
83 return BitSet();
86 //--------------------------------------------------------------------
88 // internal code for operator= and copy-ctor
90 void BitSet::CopyFrom( const BitSet& rSet )
92 nCount = rSet.nCount;
93 nBlocks = rSet.nBlocks;
94 if ( rSet.nBlocks )
96 pBitmap = new sal_uIntPtr[nBlocks];
97 memcpy( pBitmap, rSet.pBitmap, 4 * nBlocks );
99 else
100 pBitmap = 0;
103 //--------------------------------------------------------------------
105 // creates an empty bitset
107 BitSet::BitSet()
109 nCount = 0;
110 nBlocks = 0;
111 pBitmap = 0;
114 //--------------------------------------------------------------------
116 // creates a copy of bitset rOrig
118 BitSet::BitSet( const BitSet& rOrig )
120 CopyFrom(rOrig);
123 //--------------------------------------------------------------------
125 // frees the storage
127 BitSet::~BitSet()
129 delete [] pBitmap;
132 //--------------------------------------------------------------------
134 // assignment from another bitset
136 BitSet& BitSet::operator=( const BitSet& rOrig )
138 if ( this != &rOrig )
140 delete [] pBitmap;
141 CopyFrom(rOrig);
143 return *this;
146 //--------------------------------------------------------------------
148 // assignment from a single bit
150 BitSet& BitSet::operator=( sal_uInt16 nBit )
152 delete [] pBitmap;
154 nBlocks = nBit / 32;
155 sal_uIntPtr nBitVal = 1L << (nBit % 32);
156 nCount = 1;
158 pBitmap = new sal_uIntPtr[nBlocks + 1];
159 memset( pBitmap, 0, 4 * (nBlocks + 1) );
161 *(pBitmap+nBlocks) = nBitVal;
163 return *this;
166 //--------------------------------------------------------------------
168 // creates the asymetric difference with another bitset
170 BitSet& BitSet::operator-=(sal_uInt16 nBit)
172 sal_uInt16 nBlock = nBit / 32;
173 sal_uIntPtr nBitVal = 1L << (nBit % 32);
175 if ( nBlock >= nBlocks )
176 return *this;
178 if ( (*(pBitmap+nBlock) & nBitVal) )
180 *(pBitmap+nBlock) &= ~nBitVal;
181 --nCount;
184 return *this;
187 //--------------------------------------------------------------------
189 // unites with the bits of rSet
191 BitSet& BitSet::operator|=( const BitSet& rSet )
193 sal_uInt16 nMax = std::min(nBlocks, rSet.nBlocks);
195 // expand the bitmap
196 if ( nBlocks < rSet.nBlocks )
198 sal_uIntPtr *pNewMap = new sal_uIntPtr[rSet.nBlocks];
199 memset( pNewMap + nBlocks, 0, 4 * (rSet.nBlocks - nBlocks) );
201 if ( pBitmap )
203 memcpy( pNewMap, pBitmap, 4 * nBlocks );
204 delete [] pBitmap;
206 pBitmap = pNewMap;
207 nBlocks = rSet.nBlocks;
210 // add the bits blocks by block
211 for ( sal_uInt16 nBlock = 0; nBlock < nMax; ++nBlock )
213 // compute numberof additional bits
214 sal_uIntPtr nDiff = ~*(pBitmap+nBlock) & *(rSet.pBitmap+nBlock);
215 nCount = nCount + CountBits(nDiff);
217 *(pBitmap+nBlock) |= *(rSet.pBitmap+nBlock);
220 return *this;
223 //--------------------------------------------------------------------
225 // unites with a single bit
227 BitSet& BitSet::operator|=( sal_uInt16 nBit )
229 sal_uInt16 nBlock = nBit / 32;
230 sal_uIntPtr nBitVal = 1L << (nBit % 32);
232 if ( nBlock >= nBlocks )
234 sal_uIntPtr *pNewMap = new sal_uIntPtr[nBlock+1];
235 memset( pNewMap + nBlocks, 0, 4 * (nBlock - nBlocks + 1) );
237 if ( pBitmap )
239 memcpy( pNewMap, pBitmap, 4 * nBlocks );
240 delete [] pBitmap;
242 pBitmap = pNewMap;
243 nBlocks = nBlock+1;
246 if ( (*(pBitmap+nBlock) & nBitVal) == 0 )
248 *(pBitmap+nBlock) |= nBitVal;
249 ++nCount;
252 return *this;
255 //--------------------------------------------------------------------
257 // determines if the bit is set (may be the only one)
259 sal_Bool BitSet::Contains( sal_uInt16 nBit ) const
261 sal_uInt16 nBlock = nBit / 32;
262 sal_uIntPtr nBitVal = 1L << (nBit % 32);
264 if ( nBlock >= nBlocks )
265 return sal_False;
266 return ( nBitVal & *(pBitmap+nBlock) ) == nBitVal;
269 //--------------------------------------------------------------------
271 // determines if the bitsets are equal
273 sal_Bool BitSet::operator==( const BitSet& rSet ) const
275 if ( nBlocks != rSet.nBlocks )
276 return sal_False;
278 sal_uInt16 nBlock = nBlocks;
279 while ( nBlock-- > 0 )
280 if ( *(pBitmap+nBlock) != *(rSet.pBitmap+nBlock) )
281 return sal_False;
283 return sal_True;
286 //--------------------------------------------------------------------
288 // counts the number of 1-bits in the parameter
290 sal_uInt16 BitSet::CountBits( sal_uIntPtr nBits )
292 sal_uInt16 nCount = 0;
293 int nBit = 32;
294 while ( nBit-- && nBits )
295 { if ( ( (long)nBits ) < 0 )
296 ++nCount;
297 nBits = nBits << 1;
299 return nCount;
302 //--------------------------------------------------------------------
304 sal_uInt16 IndexBitSet::GetFreeIndex()
306 for(sal_uInt16 i=0;i<USHRT_MAX;i++)
307 if(!Contains(i))
309 *this|=i;
310 return i;
312 DBG_ASSERT(sal_False, "IndexBitSet enthaelt mehr als USHRT_MAX Eintraege");
313 return 0;
317 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */