LCOV - code coverage report
Current view: top level - tools/source/memtools - multisel.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 226 403 56.1 %
Date: 2014-11-03 Functions: 25 31 80.6 %
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 <tools/debug.hxx>
      21             : #include <tools/multisel.hxx>
      22             : 
      23             : #include <rtl/ustrbuf.hxx>
      24             : 
      25         423 : void MultiSelection::ImplClear()
      26             : {
      27             :     // no selected indexes
      28         423 :     nSelCount = 0;
      29             : 
      30         467 :     for ( size_t i = 0, n = aSels.size(); i < n; ++i ) {
      31          44 :         delete aSels[ i ];
      32             :     }
      33         423 :     aSels.clear();
      34         423 : }
      35             : 
      36        4451 : size_t MultiSelection::ImplFindSubSelection( long nIndex ) const
      37             : {
      38             :     // iterate through the sub selections
      39        4451 :     size_t n = 0;
      40        9032 :     for ( ;
      41        4581 :           n < aSels.size() && nIndex > aSels[ n ]->Max();
      42             :           ++n ) {} /* empty loop */
      43        4451 :     return n;
      44             : }
      45             : 
      46           6 : bool MultiSelection::ImplMergeSubSelections( size_t nPos1, size_t nPos2 )
      47             : {
      48             :     // didn't a sub selection at nPos2 exist?
      49           6 :     if ( nPos2 >= aSels.size() )
      50           0 :         return false;
      51             : 
      52             :     // did the sub selections touch each other?
      53           6 :     if ( (aSels[ nPos1 ]->Max() + 1) == aSels[ nPos2 ]->Min() )
      54             :     {
      55             :         // merge them
      56           6 :         aSels[ nPos1 ]->Max() = aSels[ nPos2 ]->Max();
      57           6 :         ImpSelList::iterator it = aSels.begin();
      58           6 :         ::std::advance( it, nPos2 );
      59           6 :         delete *it;
      60           6 :         aSels.erase( it );
      61           6 :         return true;
      62             :     }
      63             : 
      64           0 :     return false;
      65             : }
      66             : 
      67          86 : MultiSelection::MultiSelection():
      68             :     aTotRange( 0, -1 ),
      69             :     nCurSubSel(0),
      70             :     nCurIndex(0),
      71             :     nSelCount(0),
      72             :     bInverseCur(false),
      73             :     bCurValid(false),
      74          86 :     bSelectNew(false)
      75             : {
      76          86 : }
      77             : 
      78           0 : MultiSelection::MultiSelection( const MultiSelection& rOrig ) :
      79             :     aTotRange(rOrig.aTotRange),
      80             :     nSelCount(rOrig.nSelCount),
      81             :     bCurValid(rOrig.bCurValid),
      82           0 :     bSelectNew(false)
      83             : {
      84           0 :     if ( bCurValid )
      85             :     {
      86           0 :         nCurSubSel = rOrig.nCurSubSel;
      87           0 :         nCurIndex = rOrig.nCurIndex;
      88           0 :         bInverseCur = rOrig.bInverseCur;
      89             :     }
      90             :     else
      91             :     {
      92           0 :         nCurSubSel = 0;
      93           0 :         nCurIndex = 0;
      94           0 :         bInverseCur = false;
      95             :     }
      96             : 
      97             :     // copy the sub selections
      98           0 :     for ( size_t n = 0; n < rOrig.aSels.size(); ++n )
      99           0 :         aSels.push_back( new Range( *rOrig.aSels[ n ] ) );
     100           0 : }
     101             : 
     102      151122 : MultiSelection::MultiSelection( const Range& rRange ):
     103             :     aTotRange(rRange),
     104             :     nCurSubSel(0),
     105             :     nCurIndex(0),
     106             :     nSelCount(0),
     107             :     bInverseCur(false),
     108             :     bCurValid(false),
     109      151122 :     bSelectNew(false)
     110             : {
     111      151122 : }
     112             : 
     113      302416 : MultiSelection::~MultiSelection()
     114             : {
     115      152552 :     for ( size_t i = 0, n = aSels.size(); i < n; ++i )
     116        1344 :         delete aSels[ i ];
     117      151208 :     aSels.clear();
     118      151208 : }
     119             : 
     120           4 : MultiSelection& MultiSelection::operator= ( const MultiSelection& rOrig )
     121             : {
     122           4 :     aTotRange = rOrig.aTotRange;
     123           4 :     bCurValid = rOrig.bCurValid;
     124           4 :     if ( bCurValid )
     125             :     {
     126           0 :         nCurSubSel = rOrig.nCurSubSel;
     127           0 :         nCurIndex = rOrig.nCurIndex;
     128             :     }
     129             : 
     130             :     // clear the old and copy the sub selections
     131           4 :     ImplClear();
     132           4 :     for ( size_t n = 0; n < rOrig.aSels.size(); ++n )
     133           0 :         aSels.push_back( new Range( *rOrig.aSels[ n ] ) );
     134           4 :     nSelCount = rOrig.nSelCount;
     135             : 
     136           4 :     return *this;
     137             : }
     138             : 
     139           0 : bool MultiSelection::operator== ( MultiSelection& rWith )
     140             : {
     141           0 :     if ( aTotRange != rWith.aTotRange || nSelCount != rWith.nSelCount ||
     142           0 :          aSels.size() != rWith.aSels.size() )
     143           0 :         return false;
     144             : 
     145             :     // compare the sub seletions
     146           0 :     for ( size_t n = 0; n < aSels.size(); ++n )
     147           0 :         if ( *aSels[ n ] != *rWith.aSels[ n ] )
     148           0 :             return false;
     149           0 :     return true;
     150             : }
     151             : 
     152         375 : void MultiSelection::SelectAll( bool bSelect )
     153             : {
     154         375 :     ImplClear();
     155         375 :     if ( bSelect )
     156             :     {
     157         332 :         aSels.push_back( new Range(aTotRange) );
     158         332 :         nSelCount = aTotRange.Len();
     159             :     }
     160         375 : }
     161             : 
     162          30 : bool MultiSelection::Select( long nIndex, bool bSelect )
     163             : {
     164             :     DBG_ASSERT( aTotRange.IsInside(nIndex), "selected index out of range" );
     165             : 
     166             :     // out of range?
     167          30 :     if ( !aTotRange.IsInside(nIndex) )
     168           0 :         return false;
     169             : 
     170             :     // find the virtual target position
     171          30 :     size_t nSubSelPos = ImplFindSubSelection( nIndex );
     172             : 
     173          30 :     if ( bSelect )
     174             :     {
     175             :         // is it included in the found sub selection?
     176          30 :         if ( nSubSelPos < aSels.size() && aSels[ nSubSelPos ]->IsInside( nIndex ) )
     177             :             // already selected, nothing to do
     178          18 :             return false;
     179             : 
     180             :         // it will become selected
     181          12 :         ++nSelCount;
     182             : 
     183             :         // is it at the end of the previous sub selection
     184          18 :         if ( nSubSelPos > 0 &&
     185           6 :              aSels[ nSubSelPos-1 ]->Max() == (nIndex-1) )
     186             :         {
     187             :             // expand the previous sub selection
     188           6 :             aSels[ nSubSelPos-1 ]->Max() = nIndex;
     189             : 
     190             :             // try to merge the previous sub selection
     191           6 :             ImplMergeSubSelections( nSubSelPos-1, nSubSelPos );
     192             :         }
     193             :         // is is at the beginning of the found sub selection
     194          12 :         else if (  nSubSelPos < aSels.size()
     195           6 :                 && aSels[ nSubSelPos ]->Min() == (nIndex+1)
     196             :         )
     197             :             // expand the found sub selection
     198           0 :             aSels[ nSubSelPos ]->Min() = nIndex;
     199             :         else
     200             :         {
     201             :             // create a new sub selection
     202           6 :             if ( nSubSelPos < aSels.size() ) {
     203           6 :                 ImpSelList::iterator it = aSels.begin();
     204           6 :                 ::std::advance( it, nSubSelPos );
     205           6 :                 aSels.insert( it, new Range( nIndex, nIndex ) );
     206             :             } else {
     207           0 :                 aSels.push_back( new Range( nIndex, nIndex ) );
     208             :             }
     209           6 :             if ( bCurValid && nCurSubSel >= nSubSelPos )
     210           6 :                 ++nCurSubSel;
     211             :         }
     212             :     }
     213             :     else
     214             :     {
     215             :         // is it excluded from the found sub selection?
     216           0 :         if (  nSubSelPos >= aSels.size()
     217           0 :            || !aSels[ nSubSelPos ]->IsInside( nIndex )
     218             :         ) {
     219             :             // not selected, nothing to do
     220           0 :             return false;
     221             :         }
     222             : 
     223             :         // it will become deselected
     224           0 :         --nSelCount;
     225             : 
     226             :         // is it the only index in the found sub selection?
     227           0 :         if ( aSels[ nSubSelPos ]->Len() == 1 )
     228             :         {
     229             :             // remove the complete sub selection
     230           0 :             ImpSelList::iterator it = aSels.begin();
     231           0 :             ::std::advance( it, nSubSelPos );
     232           0 :             delete *it;
     233           0 :             aSels.erase( it );
     234           0 :             return true;
     235             :         }
     236             : 
     237             :         // is it at the beginning of the found sub selection?
     238           0 :         if ( aSels[ nSubSelPos ]->Min() == nIndex )
     239           0 :             ++aSels[ nSubSelPos ]->Min();
     240             :         // is it at the end of the found sub selection?
     241           0 :         else if ( aSels[ nSubSelPos ]->Max() == nIndex )
     242           0 :             --aSels[ nSubSelPos ]->Max();
     243             :         // it is in the middle of the found sub selection?
     244             :         else
     245             :         {
     246             :             // split the sub selection
     247           0 :             if ( nSubSelPos < aSels.size() ) {
     248           0 :                 ImpSelList::iterator it = aSels.begin();
     249           0 :                 ::std::advance( it, nSubSelPos );
     250           0 :                 aSels.insert( it, new Range( aSels[ nSubSelPos ]->Min(), nIndex-1 ) );
     251             :             } else {
     252           0 :                 aSels.push_back( new Range( aSels[ nSubSelPos ]->Min(), nIndex-1 ) );
     253             :             }
     254           0 :             aSels[ nSubSelPos+1 ]->Min() = nIndex + 1;
     255             :         }
     256             :     }
     257             : 
     258          12 :     return true;
     259             : }
     260             : 
     261       10046 : void MultiSelection::Select( const Range& rIndexRange, bool bSelect )
     262             : {
     263             :     Range* pRange;
     264             :     long nOld;
     265             : 
     266       10046 :     sal_uIntPtr nTmpMin = rIndexRange.Min();
     267       10046 :     sal_uIntPtr nTmpMax = rIndexRange.Max();
     268       10046 :     sal_uIntPtr nCurMin = FirstSelected();
     269       10046 :     sal_uIntPtr nCurMax = LastSelected();
     270             :     DBG_ASSERT(aTotRange.IsInside(nTmpMax), "selected index out of range" );
     271             :     DBG_ASSERT(aTotRange.IsInside(nTmpMin), "selected index out of range" );
     272             : 
     273             :     // replace whole selection?
     274       10046 :     if( nTmpMin <= nCurMin && nTmpMax >= nCurMax )
     275             :     {
     276          44 :         ImplClear();
     277          44 :         if ( bSelect )
     278             :         {
     279          44 :             aSels.push_back( new Range(rIndexRange) );
     280          44 :             nSelCount = rIndexRange.Len();
     281             :         }
     282       10084 :         return;
     283             :     }
     284             :     // expand on left side?
     285       10002 :     if( nTmpMax < nCurMin )
     286             :     {
     287        9204 :         if( bSelect )
     288             :         {
     289             :             // extend first range?
     290         846 :             if( nCurMin > (nTmpMax+1)  )
     291             :             {
     292         846 :                 pRange = new Range( rIndexRange );
     293         846 :                 aSels.insert( aSels.begin() , pRange );
     294         846 :                 nSelCount += pRange->Len();
     295             :             }
     296             :             else
     297             :             {
     298           0 :                 pRange = aSels.front();
     299           0 :                 nOld = pRange->Min();
     300           0 :                 pRange->Min() = (long)nTmpMin;
     301           0 :                 nSelCount += ( nOld - nTmpMin );
     302             :             }
     303         846 :             bCurValid = false;
     304             :         }
     305        9204 :         return;
     306             :     }
     307             :     // expand on right side?
     308         798 :     else if( nTmpMin > nCurMax )
     309             :     {
     310         792 :         if( bSelect )
     311             :         {
     312             :             // extend last range?
     313         710 :             if( nTmpMin > (nCurMax+1) )
     314             :             {
     315         166 :                 pRange = new Range( rIndexRange );
     316         166 :                 aSels.push_back( pRange );
     317         166 :                 nSelCount += pRange->Len();
     318             :             }
     319             :             else
     320             :             {
     321         544 :                 pRange = aSels.back();
     322         544 :                 nOld = pRange->Max();
     323         544 :                 pRange->Max() = (long)nTmpMax;
     324         544 :                 nSelCount += ( nTmpMax - nOld );
     325             :             }
     326         710 :             bCurValid = false;
     327             :         }
     328         792 :         return;
     329             :     }
     330             : 
     331             :     // TODO here is potential for optimization
     332          42 :     while( nTmpMin <= nTmpMax )
     333             :     {
     334          30 :         Select( nTmpMin, bSelect );
     335          30 :         nTmpMin++;
     336             :     }
     337             : }
     338             : 
     339        4166 : bool MultiSelection::IsSelected( long nIndex ) const
     340             : {
     341             :     // find the virtual target position
     342        4166 :     size_t nSubSelPos = ImplFindSubSelection( nIndex );
     343             : 
     344        4166 :     return nSubSelPos < aSels.size() && aSels[ nSubSelPos ]->IsInside(nIndex);
     345             : }
     346             : 
     347         210 : void MultiSelection::Insert( long nIndex, long nCount )
     348             : {
     349             :     // find the virtual target position
     350         210 :     size_t nSubSelPos = ImplFindSubSelection( nIndex );
     351             : 
     352             :     // did we need to shift the sub selections?
     353         210 :     if ( nSubSelPos < aSels.size() )
     354             :     {   // did we insert an unselected into an existing sub selection?
     355           0 :         if (  !bSelectNew
     356           0 :            && aSels[ nSubSelPos ]->Min() != nIndex
     357           0 :            && aSels[ nSubSelPos ]->IsInside(nIndex)
     358             :         ) { // split the sub selection
     359           0 :             if ( nSubSelPos < aSels.size() ) {
     360           0 :                 ImpSelList::iterator it = aSels.begin();
     361           0 :                 ::std::advance( it, nSubSelPos );
     362           0 :                 aSels.insert( it, new Range( aSels[ nSubSelPos ]->Min(), nIndex-1 ) );
     363             :             } else {
     364           0 :                 aSels.push_back( new Range( aSels[ nSubSelPos ]->Min(), nIndex-1 ) );
     365             :             }
     366           0 :             ++nSubSelPos;
     367           0 :             aSels[ nSubSelPos ]->Min() = nIndex;
     368             :         }
     369             : 
     370             :         // did we append an selected to an existing sub selection?
     371           0 :         else if (  bSelectNew
     372           0 :                 && nSubSelPos > 0
     373           0 :                 && aSels[ nSubSelPos ]->Max() == nIndex-1
     374             :         )   // expand the previous sub selection
     375           0 :             aSels[ nSubSelPos-1 ]->Max() += nCount;
     376             : 
     377             :         // did we insert an selected into an existing sub selection?
     378           0 :         else if (  bSelectNew
     379           0 :                 && aSels[ nSubSelPos ]->Min() == nIndex
     380             :         ) { // expand the sub selection
     381           0 :             aSels[ nSubSelPos ]->Max() += nCount;
     382           0 :             ++nSubSelPos;
     383             :         }
     384             : 
     385             :         // shift the sub selections behind the inserting position
     386           0 :         for ( size_t nPos = nSubSelPos; nPos < aSels.size(); ++nPos )
     387             :         {
     388           0 :             aSels[ nPos ]->Min() += nCount;
     389           0 :             aSels[ nPos ]->Max() += nCount;
     390             :         }
     391             :     }
     392             : 
     393         210 :     bCurValid = false;
     394         210 :     aTotRange.Max() += nCount;
     395         210 :     if ( bSelectNew )
     396           0 :         nSelCount += nCount;
     397         210 : }
     398             : 
     399          45 : void MultiSelection::Remove( long nIndex )
     400             : {
     401             :     // find the virtual target position
     402          45 :     size_t nSubSelPos = ImplFindSubSelection( nIndex );
     403             : 
     404             :     // did we remove from an existing sub selection?
     405          90 :     if (  nSubSelPos < aSels.size()
     406          45 :        && aSels[ nSubSelPos ]->IsInside(nIndex)
     407             :     ) {
     408             :         // does this sub selection only contain the index to be deleted
     409           0 :         if ( aSels[ nSubSelPos ]->Len() == 1 ) {
     410             :             // completely remove the sub selection
     411           0 :             ImpSelList::iterator it = aSels.begin();
     412           0 :             ::std::advance( it, nSubSelPos );
     413           0 :             delete *it;
     414           0 :             aSels.erase( it );
     415             :         } else {
     416             :             // shorten this sub selection
     417           0 :             --( aSels[ nSubSelPos++ ]->Max() );
     418             :         }
     419             : 
     420             :         // adjust the selected counter
     421           0 :         --nSelCount;
     422             :     }
     423             : 
     424             :     // shift the sub selections behind the removed index
     425          45 :     for ( size_t nPos = nSubSelPos; nPos < aSels.size(); ++nPos )
     426             :     {
     427           0 :         --( aSels[ nPos ]->Min() );
     428           0 :         --( aSels[ nPos ]->Max() );
     429             :     }
     430             : 
     431          45 :     bCurValid = false;
     432          45 :     aTotRange.Max() -= 1;
     433          45 : }
     434             : 
     435           0 : long MultiSelection::ImplFwdUnselected()
     436             : {
     437           0 :     if ( !bCurValid )
     438           0 :         return SFX_ENDOFSELECTION;
     439             : 
     440           0 :     if (  ( nCurSubSel < aSels.size() )
     441           0 :        && ( aSels[ nCurSubSel ]->Min() <= nCurIndex )
     442             :     )
     443           0 :         nCurIndex = aSels[ nCurSubSel++ ]->Max() + 1;
     444             : 
     445           0 :     if ( nCurIndex <= aTotRange.Max() )
     446           0 :         return nCurIndex;
     447             :     else
     448           0 :         return SFX_ENDOFSELECTION;
     449             : }
     450             : 
     451       10129 : long MultiSelection::FirstSelected( bool bInverse )
     452             : {
     453       10129 :     bInverseCur = bInverse;
     454       10129 :     nCurSubSel = 0;
     455             : 
     456       10129 :     if ( bInverseCur )
     457             :     {
     458           0 :         bCurValid = nSelCount < sal_uIntPtr(aTotRange.Len());
     459           0 :         if ( bCurValid )
     460             :         {
     461           0 :             nCurIndex = 0;
     462           0 :             return ImplFwdUnselected();
     463             :         }
     464             :     }
     465             :     else
     466             :     {
     467       10129 :         bCurValid = !aSels.empty();
     468       10129 :         if ( bCurValid )
     469         842 :             return nCurIndex = aSels[ 0 ]->Min();
     470             :     }
     471             : 
     472        9287 :     return SFX_ENDOFSELECTION;
     473             : }
     474             : 
     475       10046 : long MultiSelection::LastSelected()
     476             : {
     477       10046 :     nCurSubSel = aSels.size() - 1;
     478       10046 :     bCurValid = !aSels.empty();
     479             : 
     480       10046 :     if ( bCurValid )
     481         842 :         return nCurIndex = aSels[ nCurSubSel ]->Max();
     482             : 
     483        9204 :     return SFX_ENDOFSELECTION;
     484             : }
     485             : 
     486           0 : long MultiSelection::NextSelected()
     487             : {
     488           0 :     if ( !bCurValid )
     489           0 :         return SFX_ENDOFSELECTION;
     490             : 
     491           0 :     if ( bInverseCur )
     492             :     {
     493           0 :         ++nCurIndex;
     494           0 :         return ImplFwdUnselected();
     495             :     }
     496             :     else
     497             :     {
     498             :         // is the next index in the current sub selection too?
     499           0 :         if ( nCurIndex < aSels[ nCurSubSel ]->Max() )
     500           0 :             return ++nCurIndex;
     501             : 
     502             :         // are there further sub selections?
     503           0 :         if ( ++nCurSubSel < aSels.size() )
     504           0 :             return nCurIndex = aSels[ nCurSubSel ]->Min();
     505             : 
     506             :         // we are at the end!
     507           0 :         return SFX_ENDOFSELECTION;
     508             :     }
     509             : }
     510             : 
     511         338 : void MultiSelection::SetTotalRange( const Range& rTotRange )
     512             : {
     513         338 :     aTotRange = rTotRange;
     514             : 
     515             :     // adjust lower boundary
     516         338 :     Range* pRange = aSels.empty() ? NULL : aSels.front();
     517         676 :     while( pRange )
     518             :     {
     519           0 :         if( pRange->Max() < aTotRange.Min() )
     520             :         {
     521           0 :             delete pRange;
     522           0 :             aSels.erase( aSels.begin() );
     523             :         }
     524           0 :         else if( pRange->Min() < aTotRange.Min() )
     525             :         {
     526           0 :             pRange->Min() = aTotRange.Min();
     527           0 :             break;
     528             :         }
     529             :         else
     530           0 :             break;
     531             : 
     532           0 :         pRange = aSels.empty() ? NULL : aSels.front();
     533             :     }
     534             : 
     535             :     // adjust upper boundary
     536         338 :     size_t nCount = aSels.size();
     537         676 :     while( nCount )
     538             :     {
     539           0 :         pRange = aSels[ nCount - 1 ];
     540           0 :         if( pRange->Min() > aTotRange.Max() )
     541             :         {
     542           0 :             delete pRange;
     543           0 :             aSels.pop_back();
     544             :         }
     545           0 :         else if( pRange->Max() > aTotRange.Max() )
     546             :         {
     547           0 :             pRange->Max() = aTotRange.Max();
     548           0 :             break;
     549             :         }
     550             :         else
     551           0 :             break;
     552             : 
     553           0 :         nCount = aSels.size();
     554             :     }
     555             : 
     556             :     // re-calculate selection count
     557         338 :     nSelCount = 0;
     558         338 :     for ( size_t i = 0, n = aSels.size(); i < n; ++ i )
     559           0 :         nSelCount += aSels[i]->Len();
     560             : 
     561         338 :     bCurValid = false;
     562         338 :     nCurIndex = 0;
     563         338 : }
     564             : 
     565             : // StringRangeEnumerator
     566             : 
     567          98 : StringRangeEnumerator::StringRangeEnumerator( const OUString& i_rInput,
     568             :                                               sal_Int32 i_nMinNumber,
     569             :                                               sal_Int32 i_nMaxNumber,
     570             :                                               sal_Int32 i_nLogicalOffset
     571             :                                               )
     572             :     : mnCount( 0 )
     573             :     , mnMin( i_nMinNumber )
     574             :     , mnMax( i_nMaxNumber )
     575             :     , mnOffset( i_nLogicalOffset )
     576          98 :     , mbValidInput( false )
     577             : {
     578             :     // Parse string only if boundaries are valid.
     579          98 :     if( mnMin >= 0 && mnMax >= 0 && mnMin <= mnMax )
     580          98 :         mbValidInput = setRange( i_rInput );
     581          98 : }
     582             : 
     583         226 : bool StringRangeEnumerator::checkValue( sal_Int32 i_nValue, const std::set< sal_Int32 >* i_pPossibleValues ) const
     584             : {
     585         226 :     if( i_nValue < 0 || i_nValue < mnMin || i_nValue > mnMax )
     586           0 :         return false;
     587         226 :     if( i_pPossibleValues && i_pPossibleValues->find( i_nValue ) == i_pPossibleValues->end() )
     588           0 :         return false;
     589         226 :     return true;
     590             : }
     591             : 
     592          98 : bool StringRangeEnumerator::insertRange( sal_Int32 i_nFirst, sal_Int32 i_nLast, bool bSequence, bool bMayAdjust )
     593             : {
     594          98 :     bool bSuccess = true;
     595          98 :     if( bSequence )
     596             :     {
     597          12 :         if( bMayAdjust )
     598             :         {
     599          12 :             if( i_nFirst < mnMin )
     600           0 :                 i_nFirst = mnMin;
     601          12 :             if( i_nFirst > mnMax )
     602           0 :                 i_nFirst = mnMax;
     603          12 :             if( i_nLast < mnMin )
     604           0 :                 i_nLast = mnMin;
     605          12 :             if( i_nLast > mnMax )
     606           0 :                 i_nLast = mnMax;
     607             :         }
     608          12 :         if( checkValue( i_nFirst ) && checkValue( i_nLast ) )
     609             :         {
     610          12 :             maSequence.push_back( Range( i_nFirst, i_nLast ) );
     611          12 :             sal_Int32 nNumber = i_nLast - i_nFirst;
     612          12 :             nNumber = nNumber < 0 ? -nNumber : nNumber;
     613          12 :             mnCount += nNumber + 1;
     614             :         }
     615             :         else
     616           0 :             bSuccess = false;
     617             :     }
     618             :     else
     619             :     {
     620          86 :         if( checkValue( i_nFirst ) )
     621             :         {
     622          86 :             maSequence.push_back( Range( i_nFirst, i_nFirst ) );
     623          86 :             mnCount++;
     624             :         }
     625           0 :         else if( checkValue( i_nLast ) )
     626             :         {
     627           0 :             maSequence.push_back( Range( i_nLast, i_nLast ) );
     628           0 :             mnCount++;
     629             :         }
     630             :         else
     631           0 :             bSuccess = false;
     632             :     }
     633             : 
     634          98 :     return bSuccess;
     635             : }
     636             : 
     637          98 : bool StringRangeEnumerator::insertJoinedRanges(
     638             :     const std::vector< sal_Int32 >& rNumbers, bool i_bStrict )
     639             : {
     640          98 :     size_t nCount = rNumbers.size();
     641          98 :     if( nCount == 0 )
     642           0 :         return true;
     643             : 
     644          98 :     if( nCount == 1 )
     645           0 :         return insertRange( rNumbers[0], -1, false, ! i_bStrict );
     646             : 
     647         196 :     for( size_t i = 0; i < nCount - 1; i++ )
     648             :     {
     649          98 :         sal_Int32 nFirst = rNumbers[i];
     650          98 :         sal_Int32 nLast  = rNumbers[i + 1];
     651          98 :         if( i > 0 )
     652             :         {
     653           0 :             if     ( nFirst > nLast ) nFirst--;
     654           0 :             else if( nFirst < nLast ) nFirst++;
     655             :         }
     656             : 
     657          98 :         if ( ! insertRange( nFirst, nLast, nFirst != nLast, ! i_bStrict ) && i_bStrict)
     658           0 :             return false;
     659             :     }
     660             : 
     661          98 :     return true;
     662             : }
     663             : 
     664          98 : bool StringRangeEnumerator::setRange( const OUString& i_rNewRange, bool i_bStrict )
     665             : {
     666          98 :     mnCount = 0;
     667          98 :     maSequence.clear();
     668             : 
     669          98 :     const sal_Unicode* pInput = i_rNewRange.getStr();
     670          98 :     OUStringBuffer aNumberBuf( 16 );
     671         196 :     std::vector< sal_Int32 > aNumbers;
     672          98 :     bool bSequence = false;
     673         392 :     while( *pInput )
     674             :     {
     675         588 :         while( *pInput >= '0' && *pInput <= '9' )
     676         196 :             aNumberBuf.append( *pInput++ );
     677         196 :         if( !aNumberBuf.isEmpty() )
     678             :         {
     679         196 :             sal_Int32 nNumber = aNumberBuf.makeStringAndClear().toInt32() + mnOffset;
     680         196 :             aNumbers.push_back( nNumber );
     681         196 :             bSequence = false;
     682             :         }
     683             : 
     684         196 :         if( *pInput == '-' )
     685             :         {
     686          98 :             bSequence = true;
     687          98 :             if( aNumbers.empty() )
     688           0 :                 aNumbers.push_back( mnMin );
     689             :         }
     690          98 :         else if( *pInput == ',' || *pInput == ';' )
     691             :         {
     692           0 :             if( bSequence && !aNumbers.empty() )
     693           0 :                 aNumbers.push_back( mnMax );
     694           0 :             if( ! insertJoinedRanges( aNumbers, i_bStrict ) && i_bStrict )
     695           0 :                 return false;
     696             : 
     697           0 :             aNumbers.clear();
     698           0 :             bSequence = false;
     699             :         }
     700          98 :         else if( *pInput && *pInput != ' ' )
     701           0 :             return false; // parse error
     702             : 
     703         196 :         if( *pInput )
     704          98 :             pInput++;
     705             :     }
     706             :     // insert last entries
     707          98 :     if( bSequence && !aNumbers.empty() )
     708           0 :         aNumbers.push_back( mnMax );
     709          98 :     if( ! insertJoinedRanges( aNumbers, i_bStrict ) && i_bStrict )
     710           0 :         return false;
     711             : 
     712         196 :     return true;
     713             : }
     714             : 
     715           0 : bool StringRangeEnumerator::hasValue( sal_Int32 i_nValue, const std::set< sal_Int32 >* i_pPossibleValues ) const
     716             : {
     717           0 :     if( i_pPossibleValues && i_pPossibleValues->find( i_nValue ) == i_pPossibleValues->end() )
     718           0 :         return false;
     719           0 :     size_t n = maSequence.size();
     720           0 :     for( size_t i= 0; i < n; ++i )
     721             :     {
     722           0 :         const StringRangeEnumerator::Range rRange( maSequence[i] );
     723           0 :         if( rRange.nFirst < rRange.nLast )
     724             :         {
     725           0 :             if( i_nValue >= rRange.nFirst && i_nValue <= rRange.nLast )
     726           0 :                 return true;
     727             :         }
     728             :         else
     729             :         {
     730           0 :             if( i_nValue >= rRange.nLast && i_nValue <= rRange.nFirst )
     731           0 :                 return true;
     732             :         }
     733             :     }
     734           0 :     return false;
     735             : }
     736             : 
     737         116 : StringRangeEnumerator::Iterator& StringRangeEnumerator::Iterator::operator++()
     738             : {
     739         116 :     if( nRangeIndex >= 0 && nCurrent >= 0 && pEnumerator )
     740             :     {
     741         116 :         const StringRangeEnumerator::Range& rRange( pEnumerator->maSequence[nRangeIndex] );
     742         116 :         bool bRangeChange = false;
     743         116 :         if( rRange.nLast < rRange.nFirst )
     744             :         {
     745             :             // backward range
     746           0 :             if( nCurrent > rRange.nLast )
     747           0 :                 nCurrent--;
     748             :             else
     749           0 :                 bRangeChange = true;
     750             :         }
     751             :         else
     752             :         {
     753             :             // forward range
     754         116 :             if( nCurrent < rRange.nLast )
     755          18 :                 nCurrent++;
     756             :             else
     757          98 :                 bRangeChange = true;
     758             :         }
     759         116 :         if( bRangeChange )
     760             :         {
     761          98 :             nRangeIndex++;
     762          98 :             if( size_t(nRangeIndex) == pEnumerator->maSequence.size() )
     763             :             {
     764             :                 // reached the end
     765          98 :                 nRangeIndex = nCurrent = -1;
     766             :             }
     767             :             else
     768           0 :                 nCurrent = pEnumerator->maSequence[nRangeIndex].nFirst;
     769             :         }
     770         116 :         if( nRangeIndex != -1 && nCurrent != -1 )
     771             :         {
     772          18 :             if( ! pEnumerator->checkValue( nCurrent, pPossibleValues ) )
     773           0 :                 return ++(*this);
     774             :         }
     775             :     }
     776         116 :     return *this;
     777             : }
     778             : 
     779             : 
     780         312 : bool StringRangeEnumerator::Iterator::operator==( const Iterator& i_rCompare ) const
     781             : {
     782         312 :     return i_rCompare.pEnumerator == pEnumerator && i_rCompare.nRangeIndex == nRangeIndex && i_rCompare.nCurrent == nCurrent;
     783             : }
     784             : 
     785          98 : StringRangeEnumerator::Iterator StringRangeEnumerator::begin( const std::set< sal_Int32 >* i_pPossibleValues ) const
     786             : {
     787             :     StringRangeEnumerator::Iterator it( this,
     788             :                                         i_pPossibleValues,
     789          98 :                                         maSequence.empty() ? -1 : 0,
     790         196 :                                         maSequence.empty() ? -1 : maSequence[0].nFirst );
     791          98 :     if( ! checkValue(*it, i_pPossibleValues ) )
     792           0 :         ++it;
     793          98 :     return it;
     794             : }
     795             : 
     796          98 : StringRangeEnumerator::Iterator StringRangeEnumerator::end( const std::set< sal_Int32 >* i_pPossibleValues ) const
     797             : {
     798          98 :     return StringRangeEnumerator::Iterator( this, i_pPossibleValues, -1, -1 );
     799             : }
     800             : 
     801           0 : bool StringRangeEnumerator::getRangesFromString( const OUString& i_rPageRange,
     802             :                                                  std::vector< sal_Int32 >& o_rPageVector,
     803             :                                                  sal_Int32 i_nMinNumber,
     804             :                                                  sal_Int32 i_nMaxNumber,
     805             :                                                  sal_Int32 i_nLogicalOffset,
     806             :                                                  std::set< sal_Int32 >* i_pPossibleValues
     807             :                                                )
     808             : {
     809           0 :     o_rPageVector.clear();
     810             : 
     811           0 :     StringRangeEnumerator aEnum( i_rPageRange, i_nMinNumber, i_nMaxNumber, i_nLogicalOffset ) ;
     812             : 
     813             :     //Even if the input range wasn't completely valid, return what ranges could
     814             :     //be extracted from the input.
     815           0 :     o_rPageVector.reserve( static_cast< size_t >( aEnum.size() ) );
     816           0 :     for( StringRangeEnumerator::Iterator it = aEnum.begin( i_pPossibleValues );
     817           0 :          it != aEnum.end( i_pPossibleValues ); ++it )
     818             :     {
     819           0 :         o_rPageVector.push_back( *it );
     820             :     }
     821             : 
     822           0 :     return aEnum.isValidInput();
     823             : }
     824             : 
     825             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10