LCOV - code coverage report
Current view: top level - libreoffice/svl/source/items - nranges.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 19 255 7.5 %
Date: 2012-12-27 Functions: 1 13 7.7 %
Legend: Lines: hit not hit

          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             : #include <cassert>
      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           0 : inline void Swap_Impl(const NUMTYPE *& rp1, const NUMTYPE *& rp2)
      44             : {
      45           0 :     const NUMTYPE * pTemp = rp1;
      46           0 :     rp1 = rp2;
      47           0 :     rp2 = pTemp;
      48           0 : }
      49             : 
      50             : //========================================================================
      51             : 
      52       12306 : 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       12306 :     NUMTYPE nSize = 0, nIns = 0;
      67       12306 :     std::vector<NUMTYPE> aNumArr;
      68       12306 :     aNumArr.push_back( nWh1 );
      69       12306 :     aNumArr.push_back( nWh2 );
      70             :     DBG_ASSERT( nWh1 <= nWh2, "Ungueltiger Bereich" );
      71       12306 :     nSize += nWh2 - nWh1 + 1;
      72       12306 :     aNumArr.push_back( nNull );
      73       12306 :     bool bEndOfRange = false;
      74      108710 :     while ( 0 !=
      75             :             ( nIns =
      76             :               sal::static_int_cast< NUMTYPE >(
      77       96404 :                   va_arg( pArgs, NUMTYPE_ARG ) ) ) )
      78             :     {
      79       84098 :         bEndOfRange = !bEndOfRange;
      80       84098 :         if ( bEndOfRange )
      81             :         {
      82       48202 :             const NUMTYPE nPrev(*aNumArr.rbegin());
      83             :             DBG_ASSERT( nPrev <= nIns, "Ungueltiger Bereich" );
      84       48202 :             nSize += nIns - nPrev + 1;
      85             :         }
      86       84098 :         aNumArr.push_back( nIns );
      87             :     }
      88             : 
      89             :     assert( bEndOfRange ); // odd number of Which-IDs
      90             : 
      91             :     // so, jetzt sind alle Bereiche vorhanden und
      92       12306 :     rpRanges = new NUMTYPE[ aNumArr.size() + 1 ];
      93       12306 :     std::copy( aNumArr.begin(), aNumArr.end(), rpRanges);
      94       12306 :     *(rpRanges + aNumArr.size()) = 0;
      95             : 
      96       12306 :     return nSize;
      97             : }
      98             : 
      99             : //------------------------------------------------------------------------
     100             : 
     101           0 : 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           0 :     NUMTYPE nCount = 0;
     111           0 :     while ( *pRanges )
     112             :     {
     113           0 :         nCount += 2;
     114           0 :         pRanges += 2;
     115             :     }
     116           0 :     return nCount;
     117             : }
     118             : 
     119             : //------------------------------------------------------------------------
     120             : 
     121           0 : 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           0 :     NUMTYPE nCount = 0;
     131             : 
     132           0 :     if ( pRanges )
     133             :     {
     134           0 :         while ( *pRanges )
     135             :         {
     136           0 :             nCount += pRanges[1] - pRanges[0] + 1;
     137           0 :             pRanges += 2;
     138             :         }
     139             :     }
     140           0 :     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           0 : 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           0 : :   _pRanges( new NUMTYPE[3] )
     176             : {
     177           0 :     _pRanges[0] = nWhich1;
     178           0 :     _pRanges[1] = nWhich2;
     179           0 :     _pRanges[2] = 0;
     180           0 : }
     181             : 
     182             : //------------------------------------------------------------------------
     183             : 
     184           0 : 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           0 :     NUMTYPE nCount = Count_Impl(pArr) + 1;
     198           0 :     _pRanges = new NUMTYPE[ nCount ];
     199           0 :     memcpy( _pRanges, pArr, sizeof(NUMTYPE) * nCount );
     200           0 : }
     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           0 : 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           0 :     if ( rRanges.IsEmpty() )
     284           0 :         return *this;
     285           0 :     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           0 :     NUMTYPE nCount = 0;
     291           0 :     const NUMTYPE * pRA = _pRanges;
     292           0 :     const NUMTYPE * pRB = rRanges._pRanges;
     293             : 
     294           0 :     for (;;)
     295             :     {
     296             :         // The first pair of pRA has a lower lower bound than the first pair
     297             :         // of pRB:
     298           0 :         if (pRA[0] > pRB[0])
     299           0 :             Swap_Impl(pRA, pRB);
     300             : 
     301             :         // We are done with the merging if at least pRA is exhausted:
     302           0 :         if (!pRA[0])
     303           0 :             break;
     304             : 
     305           0 :         for (;;)
     306             :         {
     307             :             // Skip those pairs in pRB that completely lie in the first pair
     308             :             // of pRA:
     309           0 :             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           0 :             if (pRB[0] > pRA[1] + 1)
     324           0 :                 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           0 :         pRA += 2;
     340           0 :         nCount += 2;
     341             :     }
     342             : 
     343             :     // Only pRB has more pairs available, pRA is already exhausted:
     344             : count_rest:
     345           0 :     for (; pRB[0]; pRB += 2)
     346           0 :         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           0 :     NUMTYPE * pNew = new NUMTYPE[nCount + 1];
     352           0 :     pRA = _pRanges;
     353           0 :     pRB = rRanges._pRanges;
     354           0 :     NUMTYPE * pRN = pNew;
     355             : 
     356           0 :     for (;;)
     357             :     {
     358             :         // The first pair of pRA has a lower lower bound than the first pair
     359             :         // of pRB:
     360           0 :         if (pRA[0] > pRB[0])
     361           0 :             Swap_Impl(pRA, pRB);
     362             : 
     363             :         // We are done with the merging if at least pRA is exhausted:
     364           0 :         if (!pRA[0])
     365           0 :             break;
     366             : 
     367             :         // Lower bound of current new pair is already known:
     368           0 :         *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           0 :             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           0 :             if (pRB[0] > pRA[1] + 1)
     390           0 :                 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           0 :         *pRN++ = pRA[1];
     409           0 :         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           0 :     for (; *pRB;)
     416           0 :         *pRN++ = *pRB++;
     417           0 :     *pRN = 0;
     418             : 
     419           0 :     delete[] _pRanges;
     420           0 :     _pRanges = pNew;
     421             : 
     422           0 :     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: */

Generated by: LCOV version 1.10