1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_svl.hxx"
26
27 // compiled via include from itemset.cxx only!
28
29 //========================================================================
30
31 #ifdef DBG_UTIL
32
33 #define DBG_CHECK_RANGES(NUMTYPE, pArr) \
34 for ( const NUMTYPE *pRange = pArr; *pRange; pRange += 2 ) \
35 { \
36 DBG_ASSERT( pRange[0] <= pRange[1], "ranges must be sorted" ); \
37 DBG_ASSERT( !pRange[2] || ( pRange[2] - pRange[1] ) > 1, \
38 "ranges must be sorted and discrete" ); \
39 }
40
41 #else
42
43 #define DBG_CHECK_RANGES(NUMTYPE,pArr)
44
45 #endif
46
47 //============================================================================
Swap_Impl(const NUMTYPE * & rp1,const NUMTYPE * & rp2)48 inline void Swap_Impl(const NUMTYPE *& rp1, const NUMTYPE *& rp2)
49 {
50 const NUMTYPE * pTemp = rp1;
51 rp1 = rp2;
52 rp2 = pTemp;
53 }
54
55 //========================================================================
56
InitializeRanges_Impl(NUMTYPE * & rpRanges,va_list pArgs,NUMTYPE nWh1,NUMTYPE nWh2,NUMTYPE nNull)57 NUMTYPE InitializeRanges_Impl( NUMTYPE *&rpRanges, va_list pArgs,
58 NUMTYPE nWh1, NUMTYPE nWh2, NUMTYPE nNull )
59
60 /** <H3>Description</H3>
61
62 Creates an sal_uInt16-ranges-array in 'rpRanges' using 'nWh1' and 'nWh2' as
63 first range, 'nNull' as terminator or start of 2nd range and 'pArgs' as
64 remaider.
65
66 It returns the number of NUMTYPEs which are contained in the described
67 set of NUMTYPEs.
68 */
69
70 {
71 NUMTYPE nSize = 0, nIns = 0;
72 sal_uInt16 nCnt = 0;
73 SvNums aNumArr( 11, 8 );
74 aNumArr.Insert( nWh1, nCnt++ );
75 aNumArr.Insert( nWh2, nCnt++ );
76 DBG_ASSERT( nWh1 <= nWh2, "Ungueltiger Bereich" );
77 nSize += nWh2 - nWh1 + 1;
78 aNumArr.Insert( nNull, nCnt++ );
79 while ( 0 !=
80 ( nIns =
81 sal::static_int_cast< NUMTYPE >(
82 va_arg( pArgs, NUMTYPE_ARG ) ) ) )
83 {
84 aNumArr.Insert( nIns, nCnt++ );
85 if ( 0 == (nCnt & 1) ) // 4,6,8, usw.
86 {
87 DBG_ASSERT( aNumArr[ nCnt-2 ] <= nIns, "Ungueltiger Bereich" );
88 nSize += nIns - aNumArr[ nCnt-2 ] + 1;
89 }
90 }
91 va_end( pArgs );
92
93 DBG_ASSERT( 0 == (nCnt & 1), "ungerade Anzahl von Which-Paaren!" );
94
95 // so, jetzt sind alle Bereiche vorhanden und
96 rpRanges = new NUMTYPE[ nCnt+1 ];
97 memcpy( rpRanges, aNumArr.GetData(), sizeof(NUMTYPE) * nCnt );
98 *(rpRanges+nCnt) = 0;
99
100 return nSize;
101 }
102
103 //------------------------------------------------------------------------
104
Count_Impl(const NUMTYPE * pRanges)105 NUMTYPE Count_Impl( const NUMTYPE *pRanges )
106
107 /** <H3>Description</H3>
108
109 Determines the number of NUMTYPEs in an 0-terminated array of pairs of
110 NUMTYPEs. The terminating 0 is not included in the count.
111 */
112
113 {
114 NUMTYPE nCount = 0;
115 while ( *pRanges )
116 {
117 nCount += 2;
118 pRanges += 2;
119 }
120 return nCount;
121 }
122
123 //------------------------------------------------------------------------
124
Capacity_Impl(const NUMTYPE * pRanges)125 NUMTYPE Capacity_Impl( const NUMTYPE *pRanges )
126
127 /** <H3>Description</H3>
128
129 Determines the total number of NUMTYPEs described in an 0-terminated
130 array of pairs of NUMTYPEs, each representing an range of NUMTYPEs.
131 */
132
133 {
134 NUMTYPE nCount = 0;
135
136 if ( pRanges )
137 {
138 while ( *pRanges )
139 {
140 nCount += pRanges[1] - pRanges[0] + 1;
141 pRanges += 2;
142 }
143 }
144 return nCount;
145 }
146
147 //------------------------------------------------------------------------
148
SfxNumRanges(const SfxNumRanges & rOrig)149 SfxNumRanges::SfxNumRanges( const SfxNumRanges &rOrig )
150
151 /** <H3>Description</H3>
152
153 Copy-Ctor.
154 */
155
156 {
157 if ( rOrig._pRanges )
158 {
159 NUMTYPE nCount = Count_Impl( rOrig._pRanges ) + 1;
160 _pRanges = new NUMTYPE[nCount];
161 memcpy( _pRanges, rOrig._pRanges, sizeof(NUMTYPE) * nCount );
162 }
163 else
164 _pRanges = 0;
165 }
166
167 //------------------------------------------------------------------------
168
SfxNumRanges(NUMTYPE nWhich1,NUMTYPE nWhich2)169 SfxNumRanges::SfxNumRanges( NUMTYPE nWhich1, NUMTYPE nWhich2 )
170
171 /** <H3>Description</H3>
172
173 Constructs an SfxNumRanges-instance from one range of NUMTYPEs.
174
175 precondition:
176 nWhich1 <= nWhich2
177 */
178
179 : _pRanges( new NUMTYPE[3] )
180 {
181 _pRanges[0] = nWhich1;
182 _pRanges[1] = nWhich2;
183 _pRanges[2] = 0;
184 }
185
186 //------------------------------------------------------------------------
187
SfxNumRanges(NUMTYPE_ARG nWh0,NUMTYPE_ARG nWh1,NUMTYPE_ARG nNull,...)188 SfxNumRanges::SfxNumRanges( NUMTYPE_ARG nWh0, NUMTYPE_ARG nWh1, NUMTYPE_ARG nNull, ... )
189
190 /** <H3>Description</H3>
191
192 Constructs an SfxNumRanges-instance from more than one sorted ranges of
193 NUMTYPEs terminated with one 0.
194
195 precondition: for each n >= 0 && n < nArgs
196 nWh(2n) <= nWh(2n+1) && ( nWh(2n+2)-nWh(2n+1) ) > 1
197 */
198
199 {
200 va_list pArgs;
201 va_start( pArgs, nNull );
202 InitializeRanges_Impl(
203 _pRanges, pArgs, sal::static_int_cast< NUMTYPE >(nWh0),
204 sal::static_int_cast< NUMTYPE >(nWh1),
205 sal::static_int_cast< NUMTYPE >(nNull));
206 DBG_CHECK_RANGES(NUMTYPE, _pRanges);
207 }
208
209 //------------------------------------------------------------------------
210
SfxNumRanges(const NUMTYPE * pArr)211 SfxNumRanges::SfxNumRanges( const NUMTYPE* pArr )
212
213 /** <H3>Description</H3>
214
215 Constcurts an SfxNumRanges-instance from an sorted ranges of NUMTYPEs,
216 terminates with on 0.
217
218 precondition: for each n >= 0 && n < (sizeof(pArr)-1)
219 pArr[2n] <= pArr[2n+1] && ( pArr[2n+2]-pArr[2n+1] ) > 1
220 */
221
222 {
223 DBG_CHECK_RANGES(NUMTYPE, pArr);
224 NUMTYPE nCount = Count_Impl(pArr) + 1;
225 _pRanges = new NUMTYPE[ nCount ];
226 memcpy( _pRanges, pArr, sizeof(NUMTYPE) * nCount );
227 }
228
229 //------------------------------------------------------------------------
230
operator ==(const SfxNumRanges & rOther) const231 sal_Bool SfxNumRanges::operator==( const SfxNumRanges &rOther ) const
232 {
233 // Object pointers equal?
234 if ( this == &rOther )
235 return sal_True;
236
237 // Ranges pointers equal?
238 if ( _pRanges == rOther._pRanges )
239 return sal_True;
240
241 // Counts equal?
242 NUMTYPE nCount = Count();
243 if ( nCount != rOther.Count() )
244 return sal_False;
245
246 // Check arrays.
247 NUMTYPE n = 0;
248 while( _pRanges[ n ] != 0 )
249 {
250 // Elements at current position equal?
251 if ( _pRanges[ n ] != rOther._pRanges[ n ] )
252 return sal_False;
253
254 ++n;
255 }
256
257 return sal_True;
258 }
259
260 //------------------------------------------------------------------------
261
operator =(const SfxNumRanges & rRanges)262 SfxNumRanges& SfxNumRanges::operator =
263 (
264 const SfxNumRanges &rRanges
265 )
266
267 /** <H3>Description</H3>
268
269 Assigns ranges from 'rRanges' to '*this'.
270 */
271
272 {
273 // special case: assign itself
274 if ( &rRanges == this )
275 return *this;
276
277 delete[] _pRanges;
278
279 // special case: 'rRanges' is empty
280 if ( rRanges.IsEmpty() )
281 _pRanges = 0;
282 else
283 {
284 // copy ranges
285 NUMTYPE nCount = Count_Impl( rRanges._pRanges ) + 1;
286 _pRanges = new NUMTYPE[ nCount ];
287 memcpy( _pRanges, rRanges._pRanges, sizeof(NUMTYPE) * nCount );
288 }
289 return *this;
290 }
291
292 //------------------------------------------------------------------------
293
operator +=(const SfxNumRanges & rRanges)294 SfxNumRanges& SfxNumRanges::operator +=
295 (
296 const SfxNumRanges &rRanges
297 )
298
299 /** <H3>Description</H3>
300
301 Merges *this with 'rRanges'.
302
303 for each NUMTYPE n:
304 this->Contains( n ) || rRanges.Contains( n ) => this'->Contains( n )
305 !this->Contains( n ) && !rRanges.Contains( n ) => !this'->Contains( n )
306 */
307
308 {
309 // special cases: one is empty
310 if ( rRanges.IsEmpty() )
311 return *this;
312 if ( IsEmpty() )
313 return *this = rRanges;
314
315 // First, run thru _pRanges and rRanges._pRanges and determine the size of
316 // the new, merged ranges:
317 NUMTYPE nCount = 0;
318 const NUMTYPE * pRA = _pRanges;
319 const NUMTYPE * pRB = rRanges._pRanges;
320
321 for (;;)
322 {
323 // The first pair of pRA has a lower lower bound than the first pair
324 // of pRB:
325 if (pRA[0] > pRB[0])
326 Swap_Impl(pRA, pRB);
327
328 // We are done with the merging if at least pRA is exhausted:
329 if (!pRA[0])
330 break;
331
332 for (;;)
333 {
334 // Skip those pairs in pRB that completely lie in the first pair
335 // of pRA:
336 while (pRB[1] <= pRA[1])
337 {
338 pRB += 2;
339
340 // Watch out for exhaustion of pRB:
341 if (!pRB[0])
342 {
343 Swap_Impl(pRA, pRB);
344 goto count_rest;
345 }
346 }
347
348 // If the next pair of pRA does not at least touch the current new
349 // pair, we are done with the current new pair:
350 if (pRB[0] > pRA[1] + 1)
351 break;
352
353 // The next pair of pRB extends the current new pair; first,
354 // extend the current new pair (we are done if pRB is then
355 // exhausted); second, switch the roles of pRA and pRB in order to
356 // merge in those following pairs of the original pRA that will
357 // lie in the (now larger) current new pair or will even extend it
358 // further:
359 pRA += 2;
360 if (!pRA[0])
361 goto count_rest;
362 Swap_Impl(pRA, pRB);
363 }
364
365 // Done with the current new pair:
366 pRA += 2;
367 nCount += 2;
368 }
369
370 // Only pRB has more pairs available, pRA is already exhausted:
371 count_rest:
372 for (; pRB[0]; pRB += 2)
373 nCount += 2;
374
375 // Now, create new ranges of the correct size and, on a second run thru
376 // _pRanges and rRanges._pRanges, copy the merged pairs into the new
377 // ranges:
378 NUMTYPE * pNew = new NUMTYPE[nCount + 1];
379 pRA = _pRanges;
380 pRB = rRanges._pRanges;
381 NUMTYPE * pRN = pNew;
382
383 for (;;)
384 {
385 // The first pair of pRA has a lower lower bound than the first pair
386 // of pRB:
387 if (pRA[0] > pRB[0])
388 Swap_Impl(pRA, pRB);
389
390 // We are done with the merging if at least pRA is exhausted:
391 if (!pRA[0])
392 break;
393
394 // Lower bound of current new pair is already known:
395 *pRN++ = pRA[0];
396
397 for (;;)
398 {
399 // Skip those pairs in pRB that completely lie in the first pair
400 // of pRA:
401 while (pRB[1] <= pRA[1])
402 {
403 pRB += 2;
404
405 // Watch out for exhaustion of pRB:
406 if (!pRB[0])
407 {
408 Swap_Impl(pRA, pRB);
409 ++pRB;
410 goto copy_rest;
411 }
412 }
413
414 // If the next pair of pRA does not at least touch the current new
415 // pair, we are done with the current new pair:
416 if (pRB[0] > pRA[1] + 1)
417 break;
418
419 // The next pair of pRB extends the current new pair; first,
420 // extend the current new pair (we are done if pRB is then
421 // exhausted); second, switch the roles of pRA and pRB in order to
422 // merge in those following pairs of the original pRA that will
423 // lie in the (now larger) current new pair or will even extend it
424 // further:
425 pRA += 2;
426 if (!pRA[0])
427 {
428 ++pRB;
429 goto copy_rest;
430 }
431 Swap_Impl(pRA, pRB);
432 }
433
434 // Done with the current new pair, now upper bound is also known:
435 *pRN++ = pRA[1];
436 pRA += 2;
437 }
438
439 // Only pRB has more pairs available (which are copied to the new ranges
440 // unchanged), pRA is already exhausted:
441 copy_rest:
442 for (; *pRB;)
443 *pRN++ = *pRB++;
444 *pRN = 0;
445
446 delete[] _pRanges;
447 _pRanges = pNew;
448
449 return *this;
450 }
451
452 //------------------------------------------------------------------------
453
operator -=(const SfxNumRanges & rRanges)454 SfxNumRanges& SfxNumRanges::operator -=
455 (
456 const SfxNumRanges &rRanges
457 )
458
459 /** <H3>Description</H3>
460
461 Removes 'rRanges' from '*this'.
462
463 for each NUMTYPE n:
464 this->Contains( n ) && rRanges.Contains( n ) => !this'->Contains( n )
465 this->Contains( n ) && !rRanges.Contains( n ) => this'->Contains( n )
466 !this->Contains( n ) => !this'->Contains( n )
467 */
468
469 {
470 // special cases: one is empty
471 if ( rRanges.IsEmpty() || IsEmpty() )
472 return *this;
473
474 // differentiate 'rRanges' in a temporary copy of '*this'
475 // (size is computed for maximal possibly split-count plus terminating 0)
476 NUMTYPE nThisSize = Count_Impl(_pRanges);
477 NUMTYPE nTargetSize = 1 + ( nThisSize + Count_Impl(rRanges._pRanges) );
478 NUMTYPE *pTarget = new NUMTYPE[ nTargetSize ];
479 memset( pTarget, 0, sizeof(NUMTYPE)*nTargetSize );
480 memcpy( pTarget, _pRanges, sizeof(NUMTYPE)*nThisSize );
481
482 NUMTYPE nPos1 = 0, nPos2 = 0, nTargetPos = 0;
483 while( _pRanges[ nPos1 ] )
484 {
485 NUMTYPE l1 = _pRanges[ nPos1 ]; // lower bound of interval 1
486 NUMTYPE u1 = _pRanges[ nPos1+1 ]; // upper bound of interval 1
487 NUMTYPE l2 = rRanges._pRanges[ nPos2 ]; // lower bound of interval 2
488 NUMTYPE u2 = rRanges._pRanges[ nPos2+1 ]; // upper bound of interval 2
489
490 // boundary cases
491 // * subtrahend is empty -> copy the minuend
492 if( !l2 )
493 {
494 pTarget[ nTargetPos ] = l1;
495 pTarget[ nTargetPos+1 ] = u1;
496 nTargetPos += 2;
497 nPos1 += 2;
498 continue;
499 }
500 // * next subtrahend interval is completely higher -> copy the minuend
501 if( u1 < l2 )
502 {
503 pTarget[ nTargetPos ] = l1;
504 pTarget[ nTargetPos+1 ] = u1;
505 nTargetPos += 2;
506 nPos1 += 2;
507 continue;
508 }
509
510 // * next subtrahend interval is completely lower -> try next
511 if( u2 < l1 )
512 {
513 nPos2 += 2;
514 continue;
515 }
516
517 // intersecting cases
518 // * subtrahend cuts out from the beginning of the minuend
519 if( l2 <= l1 && u2 <= u1 )
520 {
521 // reduce minuend interval, try again (minuend might be affected by other subtrahend intervals)
522 _pRanges[ nPos1 ] = u2 + 1;
523 nPos2 += 2; // this cannot hurt any longer
524 continue;
525 }
526
527 // * subtrahend cuts out from the end of the minuend
528 if( l1 <= l2 && u1 <= u2 )
529 {
530 // copy remaining part of minuend (cannot be affected by other intervals)
531 if( l1 < l2 ) // anything left at all?
532 {
533 pTarget[ nTargetPos ] = l1;
534 pTarget[ nTargetPos+1 ] = l2 - 1;
535 nTargetPos += 2;
536 // do not increment nPos2, might affect next minuend interval, too
537 }
538 nPos1 += 2; // nothing left at all
539 continue;
540 }
541
542 // * subtrahend completely deletes minuend (larger or same at both ends)
543 if( l1 >= l2 && u1 <= u2 )
544 {
545 nPos1 += 2; // minuend deleted
546 // do not increment nPos2, might affect next minuend interval, too
547 continue;
548 }
549
550 // * subtrahend divides minuend into two pieces
551 if( l1 <= l2 && u1 >= u2 ) // >= and <= since they may be something left only at one side
552 {
553 // left side
554 if( l1 < l2 ) // anything left at all
555 {
556 pTarget[ nTargetPos ] = l1;
557 pTarget[ nTargetPos+1 ] = l2 - 1;
558 nTargetPos += 2;
559 }
560
561 // right side
562 if( u1 > u2 ) // anything left at all
563 {
564 // reduce minuend interval, try again (minuend might be affected by other subtrahend itnervals )
565 _pRanges[ nPos1 ] = u2 + 1;
566 }
567
568 // subtrahend is completely used
569 nPos2 += 2;
570 continue;
571 }
572
573 // we should never be here
574 DBG_ERROR( "SfxNumRanges::operator-=: internal error" );
575 } // while
576
577 pTarget[ nTargetPos ] = 0;
578
579 // assign the differentiated ranges
580 delete[] _pRanges;
581
582 NUMTYPE nUShorts = Count_Impl(pTarget) + 1;
583 if ( 1 != nUShorts )
584 {
585 _pRanges = new NUMTYPE[ nUShorts ];
586 memcpy( _pRanges, pTarget, nUShorts * sizeof(NUMTYPE) );
587 }
588 else
589 _pRanges = 0;
590
591 delete [] pTarget;
592 return *this;
593
594 /* untested code from MI commented out (MDA, 28.01.97)
595 do
596 {
597 // 1st range is smaller than 2nd range?
598 if ( pRange1[1] < pRange2[0] )
599 // => keep 1st range
600 pRange1 += 2;
601
602 // 2nd range is smaller than 1st range?
603 else if ( pRange2[1] < pRange1[0] )
604 // => skip 2nd range
605 pRange2 += 2;
606
607 // 2nd range totally overlaps the 1st range?
608 else if ( pRange2[0] <= pRange1[0] && pRange2[1] >= pRange1[1] )
609 // => remove 1st range
610 memmove( pRange1, pRange1+2, sizeof(NUMTYPE) * (pEndOfTarget-pRange1+2) );
611
612 // 2nd range overlaps only the beginning of 1st range?
613 else if ( pRange2[0] <= pRange1[0] && pRange2[1] < pRange1[1] )
614 {
615 // => cut the beginning of 1st range and goto next 2nd range
616 pRange1[0] = pRange2[1] + 1;
617 pRange2 += 2;
618 }
619
620 // 2nd range overlaps only the end of 1st range?
621 else if ( pRange2[0] > pRange1[0] && pRange2[1] >= pRange1[0] )
622 // => cut the beginning of 1st range
623 pRange1[0] = pRange2[1]+1;
624
625 // 2nd range is a real subset of 1st range
626 else
627 {
628 // => split 1st range and goto next 2nd range
629 memmove( pRange1+3, pRange1+1, sizeof(NUMTYPE) * (pEndOfTarget-pRange1-1) );
630 pRange1[1] = pRange2[0] - 1;
631 pRange1[2] = pRange2[1] + 1;
632 pRange1 += 2;
633 pRange2 += 2;
634 }
635 }
636 while ( *pRange1 && *pRange2 );
637
638 // assign the differentiated ranges
639 delete[] _pRanges;
640 NUMTYPE nUShorts = Count_Impl(pTarget) + 1;
641 if ( 1 != nUShorts )
642 {
643 _pRanges = new NUMTYPE[ nUShorts ];
644 memcpy( _pRanges, pTarget, nUShorts * sizeof(NUMTYPE) );
645 _pRanges[ nUShorts-1 ] = 0;
646 }
647 else
648 _pRanges = 0;
649 return *this;
650 */
651 }
652
653 //------------------------------------------------------------------------
654
operator /=(const SfxNumRanges & rRanges)655 SfxNumRanges& SfxNumRanges::operator /=
656 (
657 const SfxNumRanges &rRanges
658 )
659
660 /** <H3>Description</H3>
661
662 Determines intersection of '*this' with 'rRanges'.
663
664 for each NUMTYPE n:
665 this->Contains( n ) && rRanges.Contains( n ) => this'->Contains( n )
666 !this->Contains( n ) => !this'->Contains( n )
667 !rRanges.Contains( n ) => !this'->Contains( n )
668 */
669
670 {
671 // boundary cases
672 // * first set is empty -> nothing to be done
673 // * second set is empty -> delete first set
674 if( rRanges.IsEmpty() )
675 {
676 delete[] _pRanges;
677
678 _pRanges = new NUMTYPE[1];
679 _pRanges[0] = 0;
680
681 return *this;
682 }
683
684 // intersect 'rRanges' in a temporary copy of '*this'
685 // (size is computed for maximal possibly split-count plus terminating 0)
686 NUMTYPE nThisSize = Count_Impl(_pRanges);
687 NUMTYPE nTargetSize = 1 + ( nThisSize + Count_Impl(rRanges._pRanges) );
688 NUMTYPE *pTarget = new NUMTYPE[ nTargetSize ];
689 memset( pTarget, 0, sizeof(NUMTYPE)*nTargetSize );
690 memcpy( pTarget, _pRanges, sizeof(NUMTYPE)*nThisSize );
691
692 NUMTYPE nPos1 = 0, nPos2 = 0, nTargetPos = 0;
693 while( _pRanges[ nPos1 ] != 0 && rRanges._pRanges[ nPos2 ] != 0 )
694 {
695 NUMTYPE l1 = _pRanges[ nPos1 ]; // lower bound of interval 1
696 NUMTYPE u1 = _pRanges[ nPos1+1 ]; // upper bound of interval 1
697 NUMTYPE l2 = rRanges._pRanges[ nPos2 ]; // lower bound of interval 2
698 NUMTYPE u2 = rRanges._pRanges[ nPos2+1 ]; // upper bound of interval 2
699
700 if( u1 < l2 )
701 {
702 // current interval in s1 is completely before ci in s2
703 nPos1 += 2;
704 continue;
705 }
706 if( u2 < l1 )
707 {
708 // ci in s2 is completely before ci in s1
709 nPos2 += 2;
710 continue;
711 }
712
713 // assert: there exists an intersection between ci1 and ci2
714
715 if( l1 <= l2 )
716 {
717 // c1 "is more to the left" than c2
718
719 if( u1 <= u2 )
720 {
721 pTarget[ nTargetPos ] = l2;
722 pTarget[ nTargetPos+1 ] = u1;
723 nTargetPos += 2;
724 nPos1 += 2;
725 continue;
726 }
727 else
728 {
729 pTarget[ nTargetPos ] = l2;
730 pTarget[ nTargetPos+1 ] = u2;
731 nTargetPos += 2;
732 nPos2 += 2;
733 }
734 }
735 else
736 {
737 // c2 "is more to the left" than c1"
738
739 if( u1 > u2 )
740 {
741 pTarget[ nTargetPos ] = l1;
742 pTarget[ nTargetPos+1 ] = u2;
743 nTargetPos += 2;
744 nPos2 += 2;
745 }
746 else
747 {
748 pTarget[ nTargetPos ] = l1;
749 pTarget[ nTargetPos+1 ] = u1;
750 nTargetPos += 2;
751 nPos1 += 2;
752 }
753 }
754 }; // while
755 pTarget[ nTargetPos ] = 0;
756
757 // assign the intersected ranges
758 delete[] _pRanges;
759
760 NUMTYPE nUShorts = Count_Impl(pTarget) + 1;
761 if ( 1 != nUShorts )
762 {
763 _pRanges = new NUMTYPE[ nUShorts ];
764 memcpy( _pRanges, pTarget, nUShorts * sizeof(NUMTYPE) );
765 }
766 else
767 _pRanges = 0;
768
769 delete [] pTarget;
770 return *this;
771 }
772
773 //------------------------------------------------------------------------
774
Intersects(const SfxNumRanges & rRanges) const775 sal_Bool SfxNumRanges::Intersects( const SfxNumRanges &rRanges ) const
776
777 /** <H3>Description</H3>
778
779 Determines if at least one range in 'rRanges' intersects with one
780 range in '*this'.
781
782 sal_True, if there is at least one with:
783 this->Contains( n ) && rRanges.Contains( n )
784 */
785
786 {
787 // special cases: one is empty
788 if ( rRanges.IsEmpty() || IsEmpty() )
789 return sal_False;
790
791 // find at least one intersecting range
792 const NUMTYPE *pRange1 = _pRanges;
793 const NUMTYPE *pRange2 = rRanges._pRanges;
794
795 do
796 {
797 // 1st range is smaller than 2nd range?
798 if ( pRange1[1] < pRange2[0] )
799 // => keep 1st range
800 pRange1 += 2;
801
802 // 2nd range is smaller than 1st range?
803 else if ( pRange2[1] < pRange1[0] )
804 // => skip 2nd range
805 pRange2 += 2;
806
807 // the ranges are overlappung
808 else
809 return sal_True;
810 }
811 while ( *pRange2 );
812
813 // no intersection found
814 return sal_False;
815 }
816
817 //------------------------------------------------------------------------
818
Count() const819 NUMTYPE SfxNumRanges::Count() const
820
821 /** <H3>Description</H3>
822
823 Determines the number of USHORTs in the set described by the ranges
824 of USHORTs in '*this'.
825 */
826
827 {
828 return Capacity_Impl( _pRanges );
829 }
830
831 //------------------------------------------------------------------------
832
Contains(NUMTYPE n) const833 sal_Bool SfxNumRanges::Contains( NUMTYPE n ) const
834
835 /** <H3>Description</H3>
836
837 Determines if '*this' contains 'n'.
838 */
839
840 {
841 for ( NUMTYPE *pRange = _pRanges; *pRange && *pRange <= n; pRange += 2 )
842 if ( pRange[0] <= n && n <= pRange[1] )
843 return sal_True;
844 return sal_False;
845
846 }
847