GPU-Calc: remove Alloc_Host_Ptr for clmem of NAN vector
[LibreOffice.git] / svl / source / items / nranges.cxx
blobc9fc72d51e93c555e2215e8e280dd4fa773714da
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 <cassert>
21 #include <vector>
22 // compiled via include from itemset.cxx only!
25 #ifdef DBG_UTIL
27 #define DBG_CHECK_RANGES(sal_uInt16, pArr) \
28 for ( const sal_uInt16 *pRange = pArr; *pRange; pRange += 2 ) \
29 { \
30 DBG_ASSERT( pRange[0] <= pRange[1], "ranges must be sorted" ); \
31 DBG_ASSERT( !pRange[2] || ( pRange[2] - pRange[1] ) > 1, \
32 "ranges must be sorted and discrete" ); \
35 #else
37 #define DBG_CHECK_RANGES(sal_uInt16,pArr)
39 #endif
41 inline void Swap_Impl(const sal_uInt16 *& rp1, const sal_uInt16 *& rp2)
43 const sal_uInt16 * pTemp = rp1;
44 rp1 = rp2;
45 rp2 = pTemp;
49 sal_uInt16 InitializeRanges_Impl( sal_uInt16 *&rpRanges, va_list pArgs,
50 sal_uInt16 nWh1, sal_uInt16 nWh2, sal_uInt16 nNull )
52 /** <H3>Description</H3>
54 Creates an sal_uInt16-ranges-array in 'rpRanges' using 'nWh1' and 'nWh2' as
55 first range, 'nNull' as terminator or start of 2nd range and 'pArgs' as
56 remaider.
58 It returns the number of sal_uInt16s which are contained in the described
59 set of sal_uInt16s.
63 sal_uInt16 nSize = 0, nIns = 0;
64 std::vector<sal_uInt16> aNumArr;
65 aNumArr.push_back( nWh1 );
66 aNumArr.push_back( nWh2 );
67 DBG_ASSERT( nWh1 <= nWh2, "Ungueltiger Bereich" );
68 nSize += nWh2 - nWh1 + 1;
69 aNumArr.push_back( nNull );
70 bool bEndOfRange = false;
71 while ( 0 !=
72 ( nIns =
73 sal::static_int_cast< sal_uInt16 >(
74 va_arg( pArgs, int ) ) ) )
76 bEndOfRange = !bEndOfRange;
77 if ( bEndOfRange )
79 const sal_uInt16 nPrev(*aNumArr.rbegin());
80 DBG_ASSERT( nPrev <= nIns, "Ungueltiger Bereich" );
81 nSize += nIns - nPrev + 1;
83 aNumArr.push_back( nIns );
86 assert( bEndOfRange ); // odd number of Which-IDs
88 // so, jetzt sind alle Bereiche vorhanden und
89 rpRanges = new sal_uInt16[ aNumArr.size() + 1 ];
90 std::copy( aNumArr.begin(), aNumArr.end(), rpRanges);
91 *(rpRanges + aNumArr.size()) = 0;
93 return nSize;
97 sal_uInt16 Count_Impl( const sal_uInt16 *pRanges )
99 /** <H3>Description</H3>
101 Determines the number of sal_uInt16s in an 0-terminated array of pairs of
102 sal_uInt16s. The terminating 0 is not included in the count.
106 sal_uInt16 nCount = 0;
107 while ( *pRanges )
109 nCount += 2;
110 pRanges += 2;
112 return nCount;
116 sal_uInt16 Capacity_Impl( const sal_uInt16 *pRanges )
118 /** <H3>Description</H3>
120 Determines the total number of sal_uInt16s described in an 0-terminated
121 array of pairs of sal_uInt16s, each representing an range of sal_uInt16s.
125 sal_uInt16 nCount = 0;
127 if ( pRanges )
129 while ( *pRanges )
131 nCount += pRanges[1] - pRanges[0] + 1;
132 pRanges += 2;
135 return nCount;
139 SfxUShortRanges::SfxUShortRanges( const SfxUShortRanges &rOrig )
141 /** <H3>Description</H3>
143 Copy-Ctor.
147 if ( rOrig._pRanges )
149 sal_uInt16 nCount = Count_Impl( rOrig._pRanges ) + 1;
150 _pRanges = new sal_uInt16[nCount];
151 memcpy( _pRanges, rOrig._pRanges, sizeof(sal_uInt16) * nCount );
153 else
154 _pRanges = 0;
158 SfxUShortRanges::SfxUShortRanges( sal_uInt16 nWhich1, sal_uInt16 nWhich2 )
160 /** <H3>Description</H3>
162 Constructs an SfxUShortRanges-instance from one range of sal_uInt16s.
164 precondition:
165 nWhich1 <= nWhich2
168 : _pRanges( new sal_uInt16[3] )
170 _pRanges[0] = nWhich1;
171 _pRanges[1] = nWhich2;
172 _pRanges[2] = 0;
176 SfxUShortRanges::SfxUShortRanges( const sal_uInt16* pArr )
178 /** <H3>Description</H3>
180 Constcurts an SfxUShortRanges-instance from an sorted ranges of sal_uInt16s,
181 terminates with on 0.
183 precondition: for each n >= 0 && n < (sizeof(pArr)-1)
184 pArr[2n] <= pArr[2n+1] && ( pArr[2n+2]-pArr[2n+1] ) > 1
188 DBG_CHECK_RANGES(sal_uInt16, pArr);
189 sal_uInt16 nCount = Count_Impl(pArr) + 1;
190 _pRanges = new sal_uInt16[ nCount ];
191 memcpy( _pRanges, pArr, sizeof(sal_uInt16) * nCount );
195 bool SfxUShortRanges::operator==( const SfxUShortRanges &rOther ) const
197 // Object pointers equal?
198 if ( this == &rOther )
199 return true;
201 // Ranges pointers equal?
202 if ( _pRanges == rOther._pRanges )
203 return true;
205 // Counts equal?
206 sal_uInt16 nCount = Count();
207 if ( nCount != rOther.Count() )
208 return false;
210 // Check arrays.
211 sal_uInt16 n = 0;
212 while( _pRanges[ n ] != 0 )
214 // Elements at current position equal?
215 if ( _pRanges[ n ] != rOther._pRanges[ n ] )
216 return false;
218 ++n;
221 return true;
225 SfxUShortRanges& SfxUShortRanges::operator =
227 const SfxUShortRanges &rRanges
230 /** <H3>Description</H3>
232 Assigns ranges from 'rRanges' to '*this'.
236 // special case: assign itself
237 if ( &rRanges == this )
238 return *this;
240 delete[] _pRanges;
242 // special case: 'rRanges' is empty
243 if ( rRanges.IsEmpty() )
244 _pRanges = 0;
245 else
247 // copy ranges
248 sal_uInt16 nCount = Count_Impl( rRanges._pRanges ) + 1;
249 _pRanges = new sal_uInt16[ nCount ];
250 memcpy( _pRanges, rRanges._pRanges, sizeof(sal_uInt16) * nCount );
252 return *this;
256 SfxUShortRanges& SfxUShortRanges::operator +=
258 const SfxUShortRanges &rRanges
261 /** <H3>Description</H3>
263 Merges *this with 'rRanges'.
265 for each sal_uInt16 n:
266 this->Contains( n ) || rRanges.Contains( n ) => this'->Contains( n )
267 !this->Contains( n ) && !rRanges.Contains( n ) => !this'->Contains( n )
271 // special cases: one is empty
272 if ( rRanges.IsEmpty() )
273 return *this;
274 if ( IsEmpty() )
275 return *this = rRanges;
277 // First, run thru _pRanges and rRanges._pRanges and determine the size of
278 // the new, merged ranges:
279 sal_uInt16 nCount = 0;
280 const sal_uInt16 * pRA = _pRanges;
281 const sal_uInt16 * pRB = rRanges._pRanges;
283 for (;;)
285 // The first pair of pRA has a lower lower bound than the first pair
286 // of pRB:
287 if (pRA[0] > pRB[0])
288 Swap_Impl(pRA, pRB);
290 // We are done with the merging if at least pRA is exhausted:
291 if (!pRA[0])
292 break;
294 for (;;)
296 // Skip those pairs in pRB that completely lie in the first pair
297 // of pRA:
298 while (pRB[1] <= pRA[1])
300 pRB += 2;
302 // Watch out for exhaustion of pRB:
303 if (!pRB[0])
305 Swap_Impl(pRA, pRB);
306 goto count_rest;
310 // If the next pair of pRA does not at least touch the current new
311 // pair, we are done with the current new pair:
312 if (pRB[0] > pRA[1] + 1)
313 break;
315 // The next pair of pRB extends the current new pair; first,
316 // extend the current new pair (we are done if pRB is then
317 // exhausted); second, switch the roles of pRA and pRB in order to
318 // merge in those following pairs of the original pRA that will
319 // lie in the (now larger) current new pair or will even extend it
320 // further:
321 pRA += 2;
322 if (!pRA[0])
323 goto count_rest;
324 Swap_Impl(pRA, pRB);
327 // Done with the current new pair:
328 pRA += 2;
329 nCount += 2;
332 // Only pRB has more pairs available, pRA is already exhausted:
333 count_rest:
334 for (; pRB[0]; pRB += 2)
335 nCount += 2;
337 // Now, create new ranges of the correct size and, on a second run thru
338 // _pRanges and rRanges._pRanges, copy the merged pairs into the new
339 // ranges:
340 sal_uInt16 * pNew = new sal_uInt16[nCount + 1];
341 pRA = _pRanges;
342 pRB = rRanges._pRanges;
343 sal_uInt16 * pRN = pNew;
345 for (;;)
347 // The first pair of pRA has a lower lower bound than the first pair
348 // of pRB:
349 if (pRA[0] > pRB[0])
350 Swap_Impl(pRA, pRB);
352 // We are done with the merging if at least pRA is exhausted:
353 if (!pRA[0])
354 break;
356 // Lower bound of current new pair is already known:
357 *pRN++ = pRA[0];
359 for (;;)
361 // Skip those pairs in pRB that completely lie in the first pair
362 // of pRA:
363 while (pRB[1] <= pRA[1])
365 pRB += 2;
367 // Watch out for exhaustion of pRB:
368 if (!pRB[0])
370 Swap_Impl(pRA, pRB);
371 ++pRB;
372 goto copy_rest;
376 // If the next pair of pRA does not at least touch the current new
377 // pair, we are done with the current new pair:
378 if (pRB[0] > pRA[1] + 1)
379 break;
381 // The next pair of pRB extends the current new pair; first,
382 // extend the current new pair (we are done if pRB is then
383 // exhausted); second, switch the roles of pRA and pRB in order to
384 // merge in those following pairs of the original pRA that will
385 // lie in the (now larger) current new pair or will even extend it
386 // further:
387 pRA += 2;
388 if (!pRA[0])
390 ++pRB;
391 goto copy_rest;
393 Swap_Impl(pRA, pRB);
396 // Done with the current new pair, now upper bound is also known:
397 *pRN++ = pRA[1];
398 pRA += 2;
401 // Only pRB has more pairs available (which are copied to the new ranges
402 // unchanged), pRA is already exhausted:
403 copy_rest:
404 for (; *pRB;)
405 *pRN++ = *pRB++;
406 *pRN = 0;
408 delete[] _pRanges;
409 _pRanges = pNew;
411 return *this;
415 SfxUShortRanges& SfxUShortRanges::operator -=
417 const SfxUShortRanges &rRanges
420 /** <H3>Description</H3>
422 Removes 'rRanges' from '*this'.
424 for each sal_uInt16 n:
425 this->Contains( n ) && rRanges.Contains( n ) => !this'->Contains( n )
426 this->Contains( n ) && !rRanges.Contains( n ) => this'->Contains( n )
427 !this->Contains( n ) => !this'->Contains( n )
431 // special cases: one is empty
432 if ( rRanges.IsEmpty() || IsEmpty() )
433 return *this;
435 // differentiate 'rRanges' in a temporary copy of '*this'
436 // (size is computed for maximal possibly split-count plus terminating 0)
437 sal_uInt16 nThisSize = Count_Impl(_pRanges);
438 sal_uInt16 nTargetSize = 1 + ( nThisSize + Count_Impl(rRanges._pRanges) );
439 sal_uInt16 *pTarget = new sal_uInt16[ nTargetSize ];
440 memset( pTarget, 0, sizeof(sal_uInt16)*nTargetSize );
441 memcpy( pTarget, _pRanges, sizeof(sal_uInt16)*nThisSize );
443 sal_uInt16 nPos1 = 0, nPos2 = 0, nTargetPos = 0;
444 while( _pRanges[ nPos1 ] )
446 sal_uInt16 l1 = _pRanges[ nPos1 ]; // lower bound of interval 1
447 sal_uInt16 u1 = _pRanges[ nPos1+1 ]; // upper bound of interval 1
448 sal_uInt16 l2 = rRanges._pRanges[ nPos2 ]; // lower bound of interval 2
449 sal_uInt16 u2 = rRanges._pRanges[ nPos2+1 ]; // upper bound of interval 2
451 // boundary cases
452 // * subtrahend is empty -> copy the minuend
453 if( !l2 )
455 pTarget[ nTargetPos ] = l1;
456 pTarget[ nTargetPos+1 ] = u1;
457 nTargetPos += 2;
458 nPos1 += 2;
459 continue;
461 // * next subtrahend interval is completely higher -> copy the minuend
462 if( u1 < l2 )
464 pTarget[ nTargetPos ] = l1;
465 pTarget[ nTargetPos+1 ] = u1;
466 nTargetPos += 2;
467 nPos1 += 2;
468 continue;
471 // * next subtrahend interval is completely lower -> try next
472 if( u2 < l1 )
474 nPos2 += 2;
475 continue;
478 // intersecting cases
479 // * subtrahend cuts out from the beginning of the minuend
480 if( l2 <= l1 && u2 <= u1 )
482 // reduce minuend interval, try again (minuend might be affected by other subtrahend intervals)
483 _pRanges[ nPos1 ] = u2 + 1;
484 nPos2 += 2; // this cannot hurt any longer
485 continue;
488 // * subtrahend cuts out from the end of the minuend
489 if( l1 <= l2 && u1 <= u2 )
491 // copy remaining part of minuend (cannot be affected by other intervals)
492 if( l1 < l2 ) // anything left at all?
494 pTarget[ nTargetPos ] = l1;
495 pTarget[ nTargetPos+1 ] = l2 - 1;
496 nTargetPos += 2;
497 // do not increment nPos2, might affect next minuend interval, too
499 nPos1 += 2; // nothing left at all
500 continue;
503 // * subtrahend completely deletes minuend (larger or same at both ends)
504 if( l1 >= l2 && u1 <= u2 )
506 nPos1 += 2; // minuend deleted
507 // do not increment nPos2, might affect next minuend interval, too
508 continue;
511 // * subtrahend divides minuend into two pieces
512 if( l1 <= l2 && u1 >= u2 ) // >= and <= since they may be something left only at one side
514 // left side
515 if( l1 < l2 ) // anything left at all
517 pTarget[ nTargetPos ] = l1;
518 pTarget[ nTargetPos+1 ] = l2 - 1;
519 nTargetPos += 2;
522 // right side
523 if( u1 > u2 ) // anything left at all
525 // reduce minuend interval, try again (minuend might be affected by other subtrahend itnervals )
526 _pRanges[ nPos1 ] = u2 + 1;
529 // subtrahend is completely used
530 nPos2 += 2;
531 continue;
534 // we should never be here
535 OSL_FAIL( "SfxUShortRanges::operator-=: internal error" );
536 } // while
538 pTarget[ nTargetPos ] = 0;
540 // assign the differentiated ranges
541 delete[] _pRanges;
543 sal_uInt16 nUShorts = Count_Impl(pTarget) + 1;
544 if ( 1 != nUShorts )
546 _pRanges = new sal_uInt16[ nUShorts ];
547 memcpy( _pRanges, pTarget, nUShorts * sizeof(sal_uInt16) );
549 else
550 _pRanges = 0;
552 delete [] pTarget;
553 return *this;
557 SfxUShortRanges& SfxUShortRanges::operator /=
559 const SfxUShortRanges &rRanges
562 /** <H3>Description</H3>
564 Determines intersection of '*this' with 'rRanges'.
566 for each sal_uInt16 n:
567 this->Contains( n ) && rRanges.Contains( n ) => this'->Contains( n )
568 !this->Contains( n ) => !this'->Contains( n )
569 !rRanges.Contains( n ) => !this'->Contains( n )
573 // boundary cases
574 // * first set is empty -> nothing to be done
575 // * second set is empty -> delete first set
576 if( rRanges.IsEmpty() )
578 delete[] _pRanges;
580 _pRanges = new sal_uInt16[1];
581 _pRanges[0] = 0;
583 return *this;
586 // intersect 'rRanges' in a temporary copy of '*this'
587 // (size is computed for maximal possibly split-count plus terminating 0)
588 sal_uInt16 nThisSize = Count_Impl(_pRanges);
589 sal_uInt16 nTargetSize = 1 + ( nThisSize + Count_Impl(rRanges._pRanges) );
590 sal_uInt16 *pTarget = new sal_uInt16[ nTargetSize ];
591 memset( pTarget, 0, sizeof(sal_uInt16)*nTargetSize );
592 memcpy( pTarget, _pRanges, sizeof(sal_uInt16)*nThisSize );
594 sal_uInt16 nPos1 = 0, nPos2 = 0, nTargetPos = 0;
595 while( _pRanges[ nPos1 ] != 0 && rRanges._pRanges[ nPos2 ] != 0 )
597 sal_uInt16 l1 = _pRanges[ nPos1 ]; // lower bound of interval 1
598 sal_uInt16 u1 = _pRanges[ nPos1+1 ]; // upper bound of interval 1
599 sal_uInt16 l2 = rRanges._pRanges[ nPos2 ]; // lower bound of interval 2
600 sal_uInt16 u2 = rRanges._pRanges[ nPos2+1 ]; // upper bound of interval 2
602 if( u1 < l2 )
604 // current interval in s1 is completely before ci in s2
605 nPos1 += 2;
606 continue;
608 if( u2 < l1 )
610 // ci in s2 is completely before ci in s1
611 nPos2 += 2;
612 continue;
615 // assert: there exists an intersection between ci1 and ci2
617 if( l1 <= l2 )
619 // c1 "is more to the left" than c2
621 if( u1 <= u2 )
623 pTarget[ nTargetPos ] = l2;
624 pTarget[ nTargetPos+1 ] = u1;
625 nTargetPos += 2;
626 nPos1 += 2;
627 continue;
629 else
631 pTarget[ nTargetPos ] = l2;
632 pTarget[ nTargetPos+1 ] = u2;
633 nTargetPos += 2;
634 nPos2 += 2;
637 else
639 // c2 "is more to the left" than c1"
641 if( u1 > u2 )
643 pTarget[ nTargetPos ] = l1;
644 pTarget[ nTargetPos+1 ] = u2;
645 nTargetPos += 2;
646 nPos2 += 2;
648 else
650 pTarget[ nTargetPos ] = l1;
651 pTarget[ nTargetPos+1 ] = u1;
652 nTargetPos += 2;
653 nPos1 += 2;
656 }; // while
657 pTarget[ nTargetPos ] = 0;
659 // assign the intersected ranges
660 delete[] _pRanges;
662 sal_uInt16 nUShorts = Count_Impl(pTarget) + 1;
663 if ( 1 != nUShorts )
665 _pRanges = new sal_uInt16[ nUShorts ];
666 memcpy( _pRanges, pTarget, nUShorts * sizeof(sal_uInt16) );
668 else
669 _pRanges = 0;
671 delete [] pTarget;
672 return *this;
676 sal_uInt16 SfxUShortRanges::Count() const
678 /** <H3>Description</H3>
680 Determines the number of USHORTs in the set described by the ranges
681 of USHORTs in '*this'.
685 return Capacity_Impl( _pRanges );
688 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */