xref: /trunk/main/sfx2/source/bastyp/bitset.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sfx2.hxx"
30 #include <tools/debug.hxx>
31 #ifndef GCC
32 #endif
33 
34 #include "bitset.hxx"
35 
36 #include <string.h>     // memset(), memcpy()
37 #include <limits.h>     // USHRT_MAX
38 
39 //====================================================================
40 // add nOffset to each bit-value in the set
41 
42 BitSet BitSet::operator<<( sal_uInt16 nOffset ) const
43 {
44     DBG_MEMTEST();
45     // create a work-copy, return it if nothing to shift
46     BitSet aSet(*this);
47     if ( nOffset == 0 )
48         return aSet;
49 
50     // compute the shiftment in long-words and bits
51     sal_uInt16 nBlockDiff = nOffset / 32;
52     sal_uIntPtr nBitValDiff = nOffset % 32;
53 
54     // compute the new number of bits
55     for ( sal_uInt16 nBlock = 0; nBlock < nBlockDiff; ++nBlock )
56         aSet.nCount = aSet.nCount - CountBits( *(aSet.pBitmap+nBlock) );
57     aSet.nCount = aSet.nCount -
58         CountBits( *(aSet.pBitmap+nBlockDiff) >> (32-nBitValDiff) );
59 
60     // shift complete long-words
61     sal_uInt16 nTarget, nSource;
62     for ( nTarget = 0, nSource = nBlockDiff;
63           (nSource+1) < aSet.nBlocks;
64           ++nTarget, ++nSource )
65         *(aSet.pBitmap+nTarget) =
66             ( *(aSet.pBitmap+nSource) << nBitValDiff ) |
67             ( *(aSet.pBitmap+nSource+1) >> (32-nBitValDiff) );
68 
69     // shift the remainder (if in total minor 32 bits, only this)
70     *(aSet.pBitmap+nTarget) = *(aSet.pBitmap+nSource) << nBitValDiff;
71 
72     // determine the last used block
73     while ( *(aSet.pBitmap+nTarget) == 0 )
74         --nTarget;
75 
76     // shorten the block-array
77     if ( nTarget < aSet.nBlocks )
78     {
79         sal_uIntPtr* pNewMap = new sal_uIntPtr[nTarget];
80         memcpy( pNewMap, aSet.pBitmap, 4 * nTarget );
81         delete [] aSet.pBitmap;
82         aSet.pBitmap = pNewMap;
83         aSet.nBlocks = nTarget;
84     }
85 
86     return aSet;
87 }
88 
89 //--------------------------------------------------------------------
90 
91 // substracts nOffset from each bit-value in the set
92 
93 BitSet BitSet::operator>>( sal_uInt16 ) const
94 {
95     DBG_MEMTEST();
96     return BitSet();
97 }
98 
99 //--------------------------------------------------------------------
100 
101 // internal code for operator= and copy-ctor
102 
103 void BitSet::CopyFrom( const BitSet& rSet )
104 {
105     DBG_MEMTEST();
106     nCount = rSet.nCount;
107     nBlocks = rSet.nBlocks;
108     if ( rSet.nBlocks )
109     {
110         DBG_MEMTEST();
111         pBitmap = new sal_uIntPtr[nBlocks];
112         memcpy( pBitmap, rSet.pBitmap, 4 * nBlocks );
113     }
114     else
115         pBitmap = 0;
116 }
117 
118 //--------------------------------------------------------------------
119 
120 // creates an empty bitset
121 
122 BitSet::BitSet()
123 {
124     DBG_MEMTEST();
125     nCount = 0;
126     nBlocks = 0;
127     pBitmap = 0;
128 }
129 
130 //--------------------------------------------------------------------
131 
132 // creates a copy of bitset rOrig
133 
134 BitSet::BitSet( const BitSet& rOrig )
135 {
136     DBG_MEMTEST();
137     CopyFrom(rOrig);
138 }
139 
140 //--------------------------------------------------------------------
141 
142 // creates a bitset from an array
143 
144 BitSet::BitSet( sal_uInt16* pArray, sal_uInt16 nSize ):
145     nCount(nSize)
146 {
147     DBG_MEMTEST();
148     // find the highest bit to set
149     sal_uInt16 nMax = 0;
150     for ( sal_uInt16 n = 0; n < nCount; ++n )
151         if ( pArray[n] > nMax )
152             nMax = pArray[n];
153 
154     // if there are bits at all
155     if ( nMax > 0 )
156     {
157         // allocate memory for all blocks needed
158         nBlocks = nMax / 32 + 1;
159         pBitmap = new sal_uIntPtr[nBlocks];
160         memset( pBitmap, 0, 4 * nBlocks );
161 
162         // set all the bits
163         for ( sal_uInt16 n = 0; n < nCount; ++n )
164         {
165             // compute the block no. and bitvalue
166             sal_uInt16 nBlock = n / 32;
167             sal_uIntPtr nBitVal = 1L << (n % 32);
168 
169             // set a single bit
170             if ( ( *(pBitmap+nBlock) & nBitVal ) == 0 )
171             {
172                 *(pBitmap+nBlock) |= nBitVal;
173                 ++nCount;
174             }
175         }
176     }
177     else
178     {
179         // initalize emtpy set
180         nBlocks = 0;
181         pBitmap = 0;
182     }
183 }
184 
185 //--------------------------------------------------------------------
186 
187 // frees the storage
188 
189 BitSet::~BitSet()
190 {
191     DBG_MEMTEST();
192     delete [] pBitmap;
193 }
194 
195 //--------------------------------------------------------------------
196 
197 // creates a bitmap with all bits in rRange set
198 
199 BitSet::BitSet( const Range& )
200 {
201     DBG_MEMTEST();
202 }
203 
204 //--------------------------------------------------------------------
205 
206 // assignment from another bitset
207 
208 BitSet& BitSet::operator=( const BitSet& rOrig )
209 {
210     DBG_MEMTEST();
211     if ( this != &rOrig )
212     {
213         delete [] pBitmap;
214         CopyFrom(rOrig);
215     }
216     return *this;
217 }
218 
219 //--------------------------------------------------------------------
220 
221 // assignment from a single bit
222 
223 BitSet& BitSet::operator=( sal_uInt16 nBit )
224 {
225     DBG_MEMTEST();
226     delete [] pBitmap;
227 
228     nBlocks = nBit / 32;
229     sal_uIntPtr nBitVal = 1L << (nBit % 32);
230     nCount = 1;
231 
232     pBitmap = new sal_uIntPtr[nBlocks];
233     memset( pBitmap + nBlocks, 0, 4 * nBlocks );
234 
235     *(pBitmap+nBlocks) = nBitVal;
236 
237     return *this;
238 }
239 
240 //--------------------------------------------------------------------
241 
242 // creates the asymetric difference with another bitset
243 
244 BitSet& BitSet::operator-=(sal_uInt16 nBit)
245 {
246     DBG_MEMTEST();
247     sal_uInt16 nBlock = nBit / 32;
248     sal_uIntPtr nBitVal = 1L << (nBit % 32);
249 
250     if ( nBlock >= nBlocks )
251       return *this;
252 
253     if ( (*(pBitmap+nBlock) & nBitVal) )
254     {
255         *(pBitmap+nBlock) &= ~nBitVal;
256         --nCount;
257     }
258 
259     return *this;
260 }
261 
262 //--------------------------------------------------------------------
263 
264 // unites with the bits of rSet
265 
266 BitSet& BitSet::operator|=( const BitSet& rSet )
267 {
268     DBG_MEMTEST();
269     sal_uInt16 nMax = Min(nBlocks, rSet.nBlocks);
270 
271     // expand the bitmap
272     if ( nBlocks < rSet.nBlocks )
273     {
274         sal_uIntPtr *pNewMap = new sal_uIntPtr[rSet.nBlocks];
275         memset( pNewMap + nBlocks, 0, 4 * (rSet.nBlocks - nBlocks) );
276 
277         if ( pBitmap )
278         {
279             memcpy( pNewMap, pBitmap, 4 * nBlocks );
280             delete [] pBitmap;
281         }
282         pBitmap = pNewMap;
283         nBlocks = rSet.nBlocks;
284     }
285 
286     // add the bits blocks by block
287     for ( sal_uInt16 nBlock = 0; nBlock < nMax; ++nBlock )
288     {
289         // compute numberof additional bits
290         sal_uIntPtr nDiff = ~*(pBitmap+nBlock) & *(rSet.pBitmap+nBlock);
291         nCount = nCount + CountBits(nDiff);
292 
293         *(pBitmap+nBlock) |= *(rSet.pBitmap+nBlock);
294     }
295 
296     return *this;
297 }
298 
299 //--------------------------------------------------------------------
300 
301 // unites with a single bit
302 
303 BitSet& BitSet::operator|=( sal_uInt16 nBit )
304 {
305     DBG_MEMTEST();
306     sal_uInt16 nBlock = nBit / 32;
307     sal_uIntPtr nBitVal = 1L << (nBit % 32);
308 
309     if ( nBlock >= nBlocks )
310     {
311         sal_uIntPtr *pNewMap = new sal_uIntPtr[nBlock+1];
312         memset( pNewMap + nBlocks, 0, 4 * (nBlock - nBlocks + 1) );
313 
314         if ( pBitmap )
315         {
316             memcpy( pNewMap, pBitmap, 4 * nBlocks );
317             delete [] pBitmap;
318         }
319         pBitmap = pNewMap;
320         nBlocks = nBlock+1;
321     }
322 
323     if ( (*(pBitmap+nBlock) & nBitVal) == 0 )
324     {
325         *(pBitmap+nBlock) |= nBitVal;
326         ++nCount;
327     }
328 
329     return *this;
330 }
331 
332 //--------------------------------------------------------------------
333 
334 // determines if the bit is set (may be the only one)
335 
336 sal_Bool BitSet::Contains( sal_uInt16 nBit ) const
337 {
338     DBG_MEMTEST();
339     sal_uInt16 nBlock = nBit / 32;
340     sal_uIntPtr nBitVal = 1L << (nBit % 32);
341 
342     if ( nBlock >= nBlocks )
343         return sal_False;
344     return ( nBitVal & *(pBitmap+nBlock) ) == nBitVal;
345 }
346 
347 //--------------------------------------------------------------------
348 
349 // determines if the bitsets are equal
350 
351 sal_Bool BitSet::operator==( const BitSet& rSet ) const
352 {
353     DBG_MEMTEST();
354     if ( nBlocks != rSet.nBlocks )
355         return sal_False;
356 
357     sal_uInt16 nBlock = nBlocks;
358     while ( nBlock-- > 0 )
359         if ( *(pBitmap+nBlock) != *(rSet.pBitmap+nBlock) )
360             return sal_False;
361 
362     return sal_True;
363 }
364 
365 //--------------------------------------------------------------------
366 
367 // counts the number of 1-bits in the parameter
368 
369 sal_uInt16 BitSet::CountBits( sal_uIntPtr nBits )
370 {
371     sal_uInt16 nCount = 0;
372     int nBit = 32;
373     while ( nBit-- && nBits )
374     {   if ( ( (long)nBits ) < 0 )
375             ++nCount;
376         nBits = nBits << 1;
377     }
378     return nCount;
379 }
380 
381 //--------------------------------------------------------------------
382 
383 sal_uInt16 IndexBitSet::GetFreeIndex()
384 {
385   for(sal_uInt16 i=0;i<USHRT_MAX;i++)
386     if(!Contains(i))
387       {
388         *this|=i;
389         return i;
390       }
391   DBG_ASSERT(sal_False, "IndexBitSet enthaelt mehr als USHRT_MAX Eintraege");
392   return 0;
393 }
394 
395 
396