LCOV - code coverage report
Current view: top level - svl/source/items - nranges.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 87 255 34.1 %
Date: 2012-08-25 Functions: 7 13 53.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 37 150 24.7 %

           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: */

Generated by: LCOV version 1.10