Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
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/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
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 .
18 : : */
19 : :
20 : :
21 : : #include <vector>
22 : : // compiled via include from itemset.cxx only!
23 : :
24 : : //========================================================================
25 : :
26 : : #ifdef DBG_UTIL
27 : :
28 : : #define DBG_CHECK_RANGES(NUMTYPE, pArr) \
29 : : for ( const NUMTYPE *pRange = pArr; *pRange; pRange += 2 ) \
30 : : { \
31 : : DBG_ASSERT( pRange[0] <= pRange[1], "ranges must be sorted" ); \
32 : : DBG_ASSERT( !pRange[2] || ( pRange[2] - pRange[1] ) > 1, \
33 : : "ranges must be sorted and discrete" ); \
34 : : }
35 : :
36 : : #else
37 : :
38 : : #define DBG_CHECK_RANGES(NUMTYPE,pArr)
39 : :
40 : : #endif
41 : :
42 : : //============================================================================
43 : 60102 : inline void Swap_Impl(const NUMTYPE *& rp1, const NUMTYPE *& rp2)
44 : : {
45 : 60102 : const NUMTYPE * pTemp = rp1;
46 : 60102 : rp1 = rp2;
47 : 60102 : rp2 = pTemp;
48 : 60102 : }
49 : :
50 : : //========================================================================
51 : :
52 : 105615 : NUMTYPE InitializeRanges_Impl( NUMTYPE *&rpRanges, va_list pArgs,
53 : : NUMTYPE nWh1, NUMTYPE nWh2, NUMTYPE nNull )
54 : :
55 : : /** <H3>Description</H3>
56 : :
57 : : Creates an sal_uInt16-ranges-array in 'rpRanges' using 'nWh1' and 'nWh2' as
58 : : first range, 'nNull' as terminator or start of 2nd range and 'pArgs' as
59 : : remaider.
60 : :
61 : : It returns the number of NUMTYPEs which are contained in the described
62 : : set of NUMTYPEs.
63 : : */
64 : :
65 : : {
66 : 105615 : NUMTYPE nSize = 0, nIns = 0;
67 [ + - ]: 105615 : std::vector<NUMTYPE> aNumArr;
68 [ + - ]: 105615 : aNumArr.push_back( nWh1 );
69 [ + - ]: 105615 : aNumArr.push_back( nWh2 );
70 : : DBG_ASSERT( nWh1 <= nWh2, "Ungueltiger Bereich" );
71 : 105615 : nSize += nWh2 - nWh1 + 1;
72 [ + - ]: 105615 : aNumArr.push_back( nNull );
73 : 105615 : bool bEndOfRange = false;
74 [ + + ]: 962423 : while ( 0 !=
75 : : ( nIns =
76 : : sal::static_int_cast< NUMTYPE >(
77 : 856808 : va_arg( pArgs, NUMTYPE_ARG ) ) ) )
78 : : {
79 : 751193 : bEndOfRange = !bEndOfRange;
80 [ + + ]: 751193 : if ( bEndOfRange )
81 : : {
82 [ + - ]: 428404 : const NUMTYPE nPrev(*aNumArr.rbegin());
83 : : DBG_ASSERT( nPrev <= nIns, "Ungueltiger Bereich" );
84 : 428404 : nSize += nIns - nPrev + 1;
85 : : }
86 [ + - ]: 751193 : aNumArr.push_back( nIns );
87 : : }
88 : :
89 : : DBG_ASSERT( bEndOfRange, "ungerade Anzahl von Which-Paaren!" );
90 : :
91 : : // so, jetzt sind alle Bereiche vorhanden und
92 [ + - ]: 105615 : rpRanges = new NUMTYPE[ aNumArr.size() + 1 ];
93 [ + - ]: 105615 : std::copy( aNumArr.begin(), aNumArr.end(), rpRanges);
94 : 105615 : *(rpRanges + aNumArr.size()) = 0;
95 : :
96 : 105615 : return nSize;
97 : : }
98 : :
99 : : //------------------------------------------------------------------------
100 : :
101 : 80136 : NUMTYPE Count_Impl( const NUMTYPE *pRanges )
102 : :
103 : : /** <H3>Description</H3>
104 : :
105 : : Determines the number of NUMTYPEs in an 0-terminated array of pairs of
106 : : NUMTYPEs. The terminating 0 is not included in the count.
107 : : */
108 : :
109 : : {
110 : 80136 : NUMTYPE nCount = 0;
111 [ + + ]: 320544 : while ( *pRanges )
112 : : {
113 : 240408 : nCount += 2;
114 : 240408 : pRanges += 2;
115 : : }
116 : 80136 : return nCount;
117 : : }
118 : :
119 : : //------------------------------------------------------------------------
120 : :
121 : 40068 : NUMTYPE Capacity_Impl( const NUMTYPE *pRanges )
122 : :
123 : : /** <H3>Description</H3>
124 : :
125 : : Determines the total number of NUMTYPEs described in an 0-terminated
126 : : array of pairs of NUMTYPEs, each representing an range of NUMTYPEs.
127 : : */
128 : :
129 : : {
130 : 40068 : NUMTYPE nCount = 0;
131 : :
132 [ + - ]: 40068 : if ( pRanges )
133 : : {
134 [ + + ]: 180306 : while ( *pRanges )
135 : : {
136 : 140238 : nCount += pRanges[1] - pRanges[0] + 1;
137 : 140238 : pRanges += 2;
138 : : }
139 : : }
140 : 40068 : return nCount;
141 : : }
142 : :
143 : : //------------------------------------------------------------------------
144 : :
145 : 0 : SfxNumRanges::SfxNumRanges( const SfxNumRanges &rOrig )
146 : :
147 : : /** <H3>Description</H3>
148 : :
149 : : Copy-Ctor.
150 : : */
151 : :
152 : : {
153 [ # # ]: 0 : if ( rOrig._pRanges )
154 : : {
155 : 0 : NUMTYPE nCount = Count_Impl( rOrig._pRanges ) + 1;
156 : 0 : _pRanges = new NUMTYPE[nCount];
157 : 0 : memcpy( _pRanges, rOrig._pRanges, sizeof(NUMTYPE) * nCount );
158 : : }
159 : : else
160 : 0 : _pRanges = 0;
161 : 0 : }
162 : :
163 : : //------------------------------------------------------------------------
164 : :
165 : 40068 : SfxNumRanges::SfxNumRanges( NUMTYPE nWhich1, NUMTYPE nWhich2 )
166 : :
167 : : /** <H3>Description</H3>
168 : :
169 : : Constructs an SfxNumRanges-instance from one range of NUMTYPEs.
170 : :
171 : : precondition:
172 : : nWhich1 <= nWhich2
173 : : */
174 : :
175 : 40068 : : _pRanges( new NUMTYPE[3] )
176 : : {
177 : 40068 : _pRanges[0] = nWhich1;
178 : 40068 : _pRanges[1] = nWhich2;
179 : 40068 : _pRanges[2] = 0;
180 : 40068 : }
181 : :
182 : : //------------------------------------------------------------------------
183 : :
184 : 40068 : SfxNumRanges::SfxNumRanges( const NUMTYPE* pArr )
185 : :
186 : : /** <H3>Description</H3>
187 : :
188 : : Constcurts an SfxNumRanges-instance from an sorted ranges of NUMTYPEs,
189 : : terminates with on 0.
190 : :
191 : : precondition: for each n >= 0 && n < (sizeof(pArr)-1)
192 : : pArr[2n] <= pArr[2n+1] && ( pArr[2n+2]-pArr[2n+1] ) > 1
193 : : */
194 : :
195 : : {
196 : : DBG_CHECK_RANGES(NUMTYPE, pArr);
197 : 40068 : NUMTYPE nCount = Count_Impl(pArr) + 1;
198 : 40068 : _pRanges = new NUMTYPE[ nCount ];
199 : 40068 : memcpy( _pRanges, pArr, sizeof(NUMTYPE) * nCount );
200 : 40068 : }
201 : :
202 : : //------------------------------------------------------------------------
203 : :
204 : 0 : sal_Bool SfxNumRanges::operator==( const SfxNumRanges &rOther ) const
205 : : {
206 : : // Object pointers equal?
207 [ # # ]: 0 : if ( this == &rOther )
208 : 0 : return sal_True;
209 : :
210 : : // Ranges pointers equal?
211 [ # # ]: 0 : if ( _pRanges == rOther._pRanges )
212 : 0 : return sal_True;
213 : :
214 : : // Counts equal?
215 : 0 : NUMTYPE nCount = Count();
216 [ # # ]: 0 : if ( nCount != rOther.Count() )
217 : 0 : return sal_False;
218 : :
219 : : // Check arrays.
220 : 0 : NUMTYPE n = 0;
221 [ # # ]: 0 : while( _pRanges[ n ] != 0 )
222 : : {
223 : : // Elements at current position equal?
224 [ # # ]: 0 : if ( _pRanges[ n ] != rOther._pRanges[ n ] )
225 : 0 : return sal_False;
226 : :
227 : 0 : ++n;
228 : : }
229 : :
230 : 0 : return sal_True;
231 : : }
232 : :
233 : : //------------------------------------------------------------------------
234 : :
235 : 0 : SfxNumRanges& SfxNumRanges::operator =
236 : : (
237 : : const SfxNumRanges &rRanges
238 : : )
239 : :
240 : : /** <H3>Description</H3>
241 : :
242 : : Assigns ranges from 'rRanges' to '*this'.
243 : : */
244 : :
245 : : {
246 : : // special case: assign itself
247 [ # # ]: 0 : if ( &rRanges == this )
248 : 0 : return *this;
249 : :
250 [ # # ]: 0 : delete[] _pRanges;
251 : :
252 : : // special case: 'rRanges' is empty
253 [ # # ]: 0 : if ( rRanges.IsEmpty() )
254 : 0 : _pRanges = 0;
255 : : else
256 : : {
257 : : // copy ranges
258 : 0 : NUMTYPE nCount = Count_Impl( rRanges._pRanges ) + 1;
259 : 0 : _pRanges = new NUMTYPE[ nCount ];
260 : 0 : memcpy( _pRanges, rRanges._pRanges, sizeof(NUMTYPE) * nCount );
261 : : }
262 : 0 : return *this;
263 : : }
264 : :
265 : : //------------------------------------------------------------------------
266 : :
267 : 40068 : SfxNumRanges& SfxNumRanges::operator +=
268 : : (
269 : : const SfxNumRanges &rRanges
270 : : )
271 : :
272 : : /** <H3>Description</H3>
273 : :
274 : : Merges *this with 'rRanges'.
275 : :
276 : : for each NUMTYPE n:
277 : : this->Contains( n ) || rRanges.Contains( n ) => this'->Contains( n )
278 : : !this->Contains( n ) && !rRanges.Contains( n ) => !this'->Contains( n )
279 : : */
280 : :
281 : : {
282 : : // special cases: one is empty
283 [ - + ]: 40068 : if ( rRanges.IsEmpty() )
284 : 0 : return *this;
285 [ - + ]: 40068 : if ( IsEmpty() )
286 [ # # ]: 0 : return *this = rRanges;
287 : :
288 : : // First, run thru _pRanges and rRanges._pRanges and determine the size of
289 : : // the new, merged ranges:
290 : 40068 : NUMTYPE nCount = 0;
291 : 40068 : const NUMTYPE * pRA = _pRanges;
292 : 40068 : const NUMTYPE * pRB = rRanges._pRanges;
293 : :
294 : 100170 : for (;;)
295 : : {
296 : : // The first pair of pRA has a lower lower bound than the first pair
297 : : // of pRB:
298 [ + + ]: 140238 : if (pRA[0] > pRB[0])
299 : 30051 : Swap_Impl(pRA, pRB);
300 : :
301 : : // We are done with the merging if at least pRA is exhausted:
302 [ + + ]: 140238 : if (!pRA[0])
303 : 40068 : break;
304 : :
305 : 0 : for (;;)
306 : : {
307 : : // Skip those pairs in pRB that completely lie in the first pair
308 : : // of pRA:
309 [ - + ]: 100170 : while (pRB[1] <= pRA[1])
310 : : {
311 : 0 : pRB += 2;
312 : :
313 : : // Watch out for exhaustion of pRB:
314 [ # # ]: 0 : if (!pRB[0])
315 : : {
316 : 0 : Swap_Impl(pRA, pRB);
317 : 0 : goto count_rest;
318 : : }
319 : : }
320 : :
321 : : // If the next pair of pRA does not at least touch the current new
322 : : // pair, we are done with the current new pair:
323 [ + - ]: 100170 : if (pRB[0] > pRA[1] + 1)
324 : 100170 : break;
325 : :
326 : : // The next pair of pRB extends the current new pair; first,
327 : : // extend the current new pair (we are done if pRB is then
328 : : // exhausted); second, switch the roles of pRA and pRB in order to
329 : : // merge in those following pairs of the original pRA that will
330 : : // lie in the (now larger) current new pair or will even extend it
331 : : // further:
332 : 0 : pRA += 2;
333 [ # # ]: 0 : if (!pRA[0])
334 : 0 : goto count_rest;
335 : 0 : Swap_Impl(pRA, pRB);
336 : : }
337 : :
338 : : // Done with the current new pair:
339 : 100170 : pRA += 2;
340 : 100170 : nCount += 2;
341 : : }
342 : :
343 : : // Only pRB has more pairs available, pRA is already exhausted:
344 : : count_rest:
345 [ + + ]: 80136 : for (; pRB[0]; pRB += 2)
346 : 40068 : nCount += 2;
347 : :
348 : : // Now, create new ranges of the correct size and, on a second run thru
349 : : // _pRanges and rRanges._pRanges, copy the merged pairs into the new
350 : : // ranges:
351 [ + - ]: 40068 : NUMTYPE * pNew = new NUMTYPE[nCount + 1];
352 : 40068 : pRA = _pRanges;
353 : 40068 : pRB = rRanges._pRanges;
354 : 40068 : NUMTYPE * pRN = pNew;
355 : :
356 : 100170 : for (;;)
357 : : {
358 : : // The first pair of pRA has a lower lower bound than the first pair
359 : : // of pRB:
360 [ + + ]: 140238 : if (pRA[0] > pRB[0])
361 : 30051 : Swap_Impl(pRA, pRB);
362 : :
363 : : // We are done with the merging if at least pRA is exhausted:
364 [ + + ]: 140238 : if (!pRA[0])
365 : 40068 : break;
366 : :
367 : : // Lower bound of current new pair is already known:
368 : 100170 : *pRN++ = pRA[0];
369 : :
370 : 0 : for (;;)
371 : : {
372 : : // Skip those pairs in pRB that completely lie in the first pair
373 : : // of pRA:
374 [ - + ]: 100170 : while (pRB[1] <= pRA[1])
375 : : {
376 : 0 : pRB += 2;
377 : :
378 : : // Watch out for exhaustion of pRB:
379 [ # # ]: 0 : if (!pRB[0])
380 : : {
381 : 0 : Swap_Impl(pRA, pRB);
382 : 0 : ++pRB;
383 : 0 : goto copy_rest;
384 : : }
385 : : }
386 : :
387 : : // If the next pair of pRA does not at least touch the current new
388 : : // pair, we are done with the current new pair:
389 [ + - ]: 100170 : if (pRB[0] > pRA[1] + 1)
390 : 100170 : break;
391 : :
392 : : // The next pair of pRB extends the current new pair; first,
393 : : // extend the current new pair (we are done if pRB is then
394 : : // exhausted); second, switch the roles of pRA and pRB in order to
395 : : // merge in those following pairs of the original pRA that will
396 : : // lie in the (now larger) current new pair or will even extend it
397 : : // further:
398 : 0 : pRA += 2;
399 [ # # ]: 0 : if (!pRA[0])
400 : : {
401 : 0 : ++pRB;
402 : 0 : goto copy_rest;
403 : : }
404 : 0 : Swap_Impl(pRA, pRB);
405 : : }
406 : :
407 : : // Done with the current new pair, now upper bound is also known:
408 : 100170 : *pRN++ = pRA[1];
409 : 100170 : pRA += 2;
410 : : }
411 : :
412 : : // Only pRB has more pairs available (which are copied to the new ranges
413 : : // unchanged), pRA is already exhausted:
414 : : copy_rest:
415 [ + + ]: 120204 : for (; *pRB;)
416 : 80136 : *pRN++ = *pRB++;
417 : 40068 : *pRN = 0;
418 : :
419 [ + - ]: 40068 : delete[] _pRanges;
420 : 40068 : _pRanges = pNew;
421 : :
422 : 40068 : return *this;
423 : : }
424 : :
425 : : //------------------------------------------------------------------------
426 : :
427 : 0 : SfxNumRanges& SfxNumRanges::operator -=
428 : : (
429 : : const SfxNumRanges &rRanges
430 : : )
431 : :
432 : : /** <H3>Description</H3>
433 : :
434 : : Removes 'rRanges' from '*this'.
435 : :
436 : : for each NUMTYPE n:
437 : : this->Contains( n ) && rRanges.Contains( n ) => !this'->Contains( n )
438 : : this->Contains( n ) && !rRanges.Contains( n ) => this'->Contains( n )
439 : : !this->Contains( n ) => !this'->Contains( n )
440 : : */
441 : :
442 : : {
443 : : // special cases: one is empty
444 [ # # ][ # # ]: 0 : if ( rRanges.IsEmpty() || IsEmpty() )
[ # # ]
445 : 0 : return *this;
446 : :
447 : : // differentiate 'rRanges' in a temporary copy of '*this'
448 : : // (size is computed for maximal possibly split-count plus terminating 0)
449 : 0 : NUMTYPE nThisSize = Count_Impl(_pRanges);
450 : 0 : NUMTYPE nTargetSize = 1 + ( nThisSize + Count_Impl(rRanges._pRanges) );
451 : 0 : NUMTYPE *pTarget = new NUMTYPE[ nTargetSize ];
452 : 0 : memset( pTarget, 0, sizeof(NUMTYPE)*nTargetSize );
453 : 0 : memcpy( pTarget, _pRanges, sizeof(NUMTYPE)*nThisSize );
454 : :
455 : 0 : NUMTYPE nPos1 = 0, nPos2 = 0, nTargetPos = 0;
456 [ # # ]: 0 : while( _pRanges[ nPos1 ] )
457 : : {
458 : 0 : NUMTYPE l1 = _pRanges[ nPos1 ]; // lower bound of interval 1
459 : 0 : NUMTYPE u1 = _pRanges[ nPos1+1 ]; // upper bound of interval 1
460 : 0 : NUMTYPE l2 = rRanges._pRanges[ nPos2 ]; // lower bound of interval 2
461 : 0 : NUMTYPE u2 = rRanges._pRanges[ nPos2+1 ]; // upper bound of interval 2
462 : :
463 : : // boundary cases
464 : : // * subtrahend is empty -> copy the minuend
465 [ # # ]: 0 : if( !l2 )
466 : : {
467 : 0 : pTarget[ nTargetPos ] = l1;
468 : 0 : pTarget[ nTargetPos+1 ] = u1;
469 : 0 : nTargetPos += 2;
470 : 0 : nPos1 += 2;
471 : 0 : continue;
472 : : }
473 : : // * next subtrahend interval is completely higher -> copy the minuend
474 [ # # ]: 0 : if( u1 < l2 )
475 : : {
476 : 0 : pTarget[ nTargetPos ] = l1;
477 : 0 : pTarget[ nTargetPos+1 ] = u1;
478 : 0 : nTargetPos += 2;
479 : 0 : nPos1 += 2;
480 : 0 : continue;
481 : : }
482 : :
483 : : // * next subtrahend interval is completely lower -> try next
484 [ # # ]: 0 : if( u2 < l1 )
485 : : {
486 : 0 : nPos2 += 2;
487 : 0 : continue;
488 : : }
489 : :
490 : : // intersecting cases
491 : : // * subtrahend cuts out from the beginning of the minuend
492 [ # # ][ # # ]: 0 : if( l2 <= l1 && u2 <= u1 )
493 : : {
494 : : // reduce minuend interval, try again (minuend might be affected by other subtrahend intervals)
495 : 0 : _pRanges[ nPos1 ] = u2 + 1;
496 : 0 : nPos2 += 2; // this cannot hurt any longer
497 : 0 : continue;
498 : : }
499 : :
500 : : // * subtrahend cuts out from the end of the minuend
501 [ # # ][ # # ]: 0 : if( l1 <= l2 && u1 <= u2 )
502 : : {
503 : : // copy remaining part of minuend (cannot be affected by other intervals)
504 [ # # ]: 0 : if( l1 < l2 ) // anything left at all?
505 : : {
506 : 0 : pTarget[ nTargetPos ] = l1;
507 : 0 : pTarget[ nTargetPos+1 ] = l2 - 1;
508 : 0 : nTargetPos += 2;
509 : : // do not increment nPos2, might affect next minuend interval, too
510 : : }
511 : 0 : nPos1 += 2; // nothing left at all
512 : 0 : continue;
513 : : }
514 : :
515 : : // * subtrahend completely deletes minuend (larger or same at both ends)
516 [ # # ][ # # ]: 0 : if( l1 >= l2 && u1 <= u2 )
517 : : {
518 : 0 : nPos1 += 2; // minuend deleted
519 : : // do not increment nPos2, might affect next minuend interval, too
520 : 0 : continue;
521 : : }
522 : :
523 : : // * subtrahend divides minuend into two pieces
524 [ # # ][ # # ]: 0 : if( l1 <= l2 && u1 >= u2 ) // >= and <= since they may be something left only at one side
525 : : {
526 : : // left side
527 [ # # ]: 0 : if( l1 < l2 ) // anything left at all
528 : : {
529 : 0 : pTarget[ nTargetPos ] = l1;
530 : 0 : pTarget[ nTargetPos+1 ] = l2 - 1;
531 : 0 : nTargetPos += 2;
532 : : }
533 : :
534 : : // right side
535 [ # # ]: 0 : if( u1 > u2 ) // anything left at all
536 : : {
537 : : // reduce minuend interval, try again (minuend might be affected by other subtrahend itnervals )
538 : 0 : _pRanges[ nPos1 ] = u2 + 1;
539 : : }
540 : :
541 : : // subtrahend is completely used
542 : 0 : nPos2 += 2;
543 : 0 : continue;
544 : : }
545 : :
546 : : // we should never be here
547 : : OSL_FAIL( "SfxNumRanges::operator-=: internal error" );
548 : : } // while
549 : :
550 : 0 : pTarget[ nTargetPos ] = 0;
551 : :
552 : : // assign the differentiated ranges
553 [ # # ]: 0 : delete[] _pRanges;
554 : :
555 : 0 : NUMTYPE nUShorts = Count_Impl(pTarget) + 1;
556 [ # # ]: 0 : if ( 1 != nUShorts )
557 : : {
558 : 0 : _pRanges = new NUMTYPE[ nUShorts ];
559 : 0 : memcpy( _pRanges, pTarget, nUShorts * sizeof(NUMTYPE) );
560 : : }
561 : : else
562 : 0 : _pRanges = 0;
563 : :
564 [ # # ]: 0 : delete [] pTarget;
565 : 0 : return *this;
566 : : }
567 : :
568 : : //------------------------------------------------------------------------
569 : :
570 : 0 : SfxNumRanges& SfxNumRanges::operator /=
571 : : (
572 : : const SfxNumRanges &rRanges
573 : : )
574 : :
575 : : /** <H3>Description</H3>
576 : :
577 : : Determines intersection of '*this' with 'rRanges'.
578 : :
579 : : for each NUMTYPE n:
580 : : this->Contains( n ) && rRanges.Contains( n ) => this'->Contains( n )
581 : : !this->Contains( n ) => !this'->Contains( n )
582 : : !rRanges.Contains( n ) => !this'->Contains( n )
583 : : */
584 : :
585 : : {
586 : : // boundary cases
587 : : // * first set is empty -> nothing to be done
588 : : // * second set is empty -> delete first set
589 [ # # ]: 0 : if( rRanges.IsEmpty() )
590 : : {
591 [ # # ]: 0 : delete[] _pRanges;
592 : :
593 : 0 : _pRanges = new NUMTYPE[1];
594 : 0 : _pRanges[0] = 0;
595 : :
596 : 0 : return *this;
597 : : }
598 : :
599 : : // intersect 'rRanges' in a temporary copy of '*this'
600 : : // (size is computed for maximal possibly split-count plus terminating 0)
601 : 0 : NUMTYPE nThisSize = Count_Impl(_pRanges);
602 : 0 : NUMTYPE nTargetSize = 1 + ( nThisSize + Count_Impl(rRanges._pRanges) );
603 : 0 : NUMTYPE *pTarget = new NUMTYPE[ nTargetSize ];
604 : 0 : memset( pTarget, 0, sizeof(NUMTYPE)*nTargetSize );
605 : 0 : memcpy( pTarget, _pRanges, sizeof(NUMTYPE)*nThisSize );
606 : :
607 : 0 : NUMTYPE nPos1 = 0, nPos2 = 0, nTargetPos = 0;
608 [ # # ][ # # ]: 0 : while( _pRanges[ nPos1 ] != 0 && rRanges._pRanges[ nPos2 ] != 0 )
[ # # ]
609 : : {
610 : 0 : NUMTYPE l1 = _pRanges[ nPos1 ]; // lower bound of interval 1
611 : 0 : NUMTYPE u1 = _pRanges[ nPos1+1 ]; // upper bound of interval 1
612 : 0 : NUMTYPE l2 = rRanges._pRanges[ nPos2 ]; // lower bound of interval 2
613 : 0 : NUMTYPE u2 = rRanges._pRanges[ nPos2+1 ]; // upper bound of interval 2
614 : :
615 [ # # ]: 0 : if( u1 < l2 )
616 : : {
617 : : // current interval in s1 is completely before ci in s2
618 : 0 : nPos1 += 2;
619 : 0 : continue;
620 : : }
621 [ # # ]: 0 : if( u2 < l1 )
622 : : {
623 : : // ci in s2 is completely before ci in s1
624 : 0 : nPos2 += 2;
625 : 0 : continue;
626 : : }
627 : :
628 : : // assert: there exists an intersection between ci1 and ci2
629 : :
630 [ # # ]: 0 : if( l1 <= l2 )
631 : : {
632 : : // c1 "is more to the left" than c2
633 : :
634 [ # # ]: 0 : if( u1 <= u2 )
635 : : {
636 : 0 : pTarget[ nTargetPos ] = l2;
637 : 0 : pTarget[ nTargetPos+1 ] = u1;
638 : 0 : nTargetPos += 2;
639 : 0 : nPos1 += 2;
640 : 0 : continue;
641 : : }
642 : : else
643 : : {
644 : 0 : pTarget[ nTargetPos ] = l2;
645 : 0 : pTarget[ nTargetPos+1 ] = u2;
646 : 0 : nTargetPos += 2;
647 : 0 : nPos2 += 2;
648 : : }
649 : : }
650 : : else
651 : : {
652 : : // c2 "is more to the left" than c1"
653 : :
654 [ # # ]: 0 : if( u1 > u2 )
655 : : {
656 : 0 : pTarget[ nTargetPos ] = l1;
657 : 0 : pTarget[ nTargetPos+1 ] = u2;
658 : 0 : nTargetPos += 2;
659 : 0 : nPos2 += 2;
660 : : }
661 : : else
662 : : {
663 : 0 : pTarget[ nTargetPos ] = l1;
664 : 0 : pTarget[ nTargetPos+1 ] = u1;
665 : 0 : nTargetPos += 2;
666 : 0 : nPos1 += 2;
667 : : }
668 : : }
669 : : }; // while
670 : 0 : pTarget[ nTargetPos ] = 0;
671 : :
672 : : // assign the intersected ranges
673 [ # # ]: 0 : delete[] _pRanges;
674 : :
675 : 0 : NUMTYPE nUShorts = Count_Impl(pTarget) + 1;
676 [ # # ]: 0 : if ( 1 != nUShorts )
677 : : {
678 : 0 : _pRanges = new NUMTYPE[ nUShorts ];
679 : 0 : memcpy( _pRanges, pTarget, nUShorts * sizeof(NUMTYPE) );
680 : : }
681 : : else
682 : 0 : _pRanges = 0;
683 : :
684 [ # # ]: 0 : delete [] pTarget;
685 : 0 : return *this;
686 : : }
687 : :
688 : : //------------------------------------------------------------------------
689 : :
690 : 0 : NUMTYPE SfxNumRanges::Count() const
691 : :
692 : : /** <H3>Description</H3>
693 : :
694 : : Determines the number of USHORTs in the set described by the ranges
695 : : of USHORTs in '*this'.
696 : : */
697 : :
698 : : {
699 : 0 : return Capacity_Impl( _pRanges );
700 : : }
701 : :
702 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|