LCOV - code coverage report
Current view: top level - tools/source/memtools - multisel.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 234 403 58.1 %
Date: 2015-06-13 12:38:46 Functions: 26 31 83.9 %
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         225 : void MultiSelection::ImplClear()
      26             : {
      27             :     // no selected indexes
      28         225 :     nSelCount = 0;
      29             : 
      30         254 :     for ( size_t i = 0, n = aSels.size(); i < n; ++i ) {
      31          29 :         delete aSels[ i ];
      32             :     }
      33         225 :     aSels.clear();
      34         225 : }
      35             : 
      36        3377 : size_t MultiSelection::ImplFindSubSelection( long nIndex ) const
      37             : {
      38             :     // iterate through the sub selections
      39        3377 :     size_t n = 0;
      40        6808 :     for ( ;
      41        3431 :           n < aSels.size() && nIndex > aSels[ n ]->Max();
      42             :           ++n ) {} /* empty loop */
      43        3377 :     return n;
      44             : }
      45             : 
      46           3 : bool MultiSelection::ImplMergeSubSelections( size_t nPos1, size_t nPos2 )
      47             : {
      48             :     // didn't a sub selection at nPos2 exist?
      49           3 :     if ( nPos2 >= aSels.size() )
      50           0 :         return false;
      51             : 
      52             :     // did the sub selections touch each other?
      53           3 :     if ( (aSels[ nPos1 ]->Max() + 1) == aSels[ nPos2 ]->Min() )
      54             :     {
      55             :         // merge them
      56           3 :         aSels[ nPos1 ]->Max() = aSels[ nPos2 ]->Max();
      57           3 :         ImpSelList::iterator it = aSels.begin();
      58           3 :         ::std::advance( it, nPos2 );
      59           3 :         delete *it;
      60           3 :         aSels.erase( it );
      61           3 :         return true;
      62             :     }
      63             : 
      64           0 :     return false;
      65             : }
      66             : 
      67          42 : MultiSelection::MultiSelection():
      68             :     aTotRange( 0, -1 ),
      69             :     nCurSubSel(0),
      70             :     nCurIndex(0),
      71             :     nSelCount(0),
      72             :     bInverseCur(false),
      73             :     bCurValid(false),
      74          42 :     bSelectNew(false)
      75             : {
      76          42 : }
      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       91626 : MultiSelection::MultiSelection( const Range& rRange ):
     103             :     aTotRange(rRange),
     104             :     nCurSubSel(0),
     105             :     nCurIndex(0),
     106             :     nSelCount(0),
     107             :     bInverseCur(false),
     108             :     bCurValid(false),
     109       91626 :     bSelectNew(false)
     110             : {
     111       91626 : }
     112             : 
     113      183336 : MultiSelection::~MultiSelection()
     114             : {
     115       92348 :     for ( size_t i = 0, n = aSels.size(); i < n; ++i )
     116         680 :         delete aSels[ i ];
     117       91668 :     aSels.clear();
     118       91668 : }
     119             : 
     120           2 : MultiSelection& MultiSelection::operator= ( const MultiSelection& rOrig )
     121             : {
     122           2 :     aTotRange = rOrig.aTotRange;
     123           2 :     bCurValid = rOrig.bCurValid;
     124           2 :     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           2 :     ImplClear();
     132           2 :     for ( size_t n = 0; n < rOrig.aSels.size(); ++n )
     133           0 :         aSels.push_back( new Range( *rOrig.aSels[ n ] ) );
     134           2 :     nSelCount = rOrig.nSelCount;
     135             : 
     136           2 :     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 selections
     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         194 : void MultiSelection::SelectAll( bool bSelect )
     153             : {
     154         194 :     ImplClear();
     155         194 :     if ( bSelect )
     156             :     {
     157         173 :         aSels.push_back( new Range(aTotRange) );
     158         173 :         nSelCount = aTotRange.Len();
     159             :     }
     160         194 : }
     161             : 
     162          15 : 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          15 :     if ( !aTotRange.IsInside(nIndex) )
     168           0 :         return false;
     169             : 
     170             :     // find the virtual target position
     171          15 :     size_t nSubSelPos = ImplFindSubSelection( nIndex );
     172             : 
     173          15 :     if ( bSelect )
     174             :     {
     175             :         // is it included in the found sub selection?
     176          15 :         if ( nSubSelPos < aSels.size() && aSels[ nSubSelPos ]->IsInside( nIndex ) )
     177             :             // already selected, nothing to do
     178           9 :             return false;
     179             : 
     180             :         // it will become selected
     181           6 :         ++nSelCount;
     182             : 
     183             :         // is it at the end of the previous sub selection
     184           9 :         if ( nSubSelPos > 0 &&
     185           3 :              aSels[ nSubSelPos-1 ]->Max() == (nIndex-1) )
     186             :         {
     187             :             // expand the previous sub selection
     188           3 :             aSels[ nSubSelPos-1 ]->Max() = nIndex;
     189             : 
     190             :             // try to merge the previous sub selection
     191           3 :             ImplMergeSubSelections( nSubSelPos-1, nSubSelPos );
     192             :         }
     193             :         // is it at the beginning of the found sub selection
     194           6 :         else if (  nSubSelPos < aSels.size()
     195           3 :                 && 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           3 :             if ( nSubSelPos < aSels.size() ) {
     203           3 :                 ImpSelList::iterator it = aSels.begin();
     204           3 :                 ::std::advance( it, nSubSelPos );
     205           3 :                 aSels.insert( it, new Range( nIndex, nIndex ) );
     206             :             } else {
     207           0 :                 aSels.push_back( new Range( nIndex, nIndex ) );
     208             :             }
     209           3 :             if ( bCurValid && nCurSubSel >= nSubSelPos )
     210           3 :                 ++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           6 :     return true;
     259             : }
     260             : 
     261        1834 : void MultiSelection::Select( const Range& rIndexRange, bool bSelect )
     262             : {
     263             :     Range* pRange;
     264             :     long nOld;
     265             : 
     266        1834 :     sal_uIntPtr nTmpMin = rIndexRange.Min();
     267        1834 :     sal_uIntPtr nTmpMax = rIndexRange.Max();
     268        1834 :     sal_uIntPtr nCurMin = FirstSelected();
     269        1834 :     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        1834 :     if( nTmpMin <= nCurMin && nTmpMax >= nCurMax )
     275             :     {
     276          29 :         ImplClear();
     277          29 :         if ( bSelect )
     278             :         {
     279          29 :             aSels.push_back( new Range(rIndexRange) );
     280          29 :             nSelCount = rIndexRange.Len();
     281             :         }
     282        1860 :         return;
     283             :     }
     284             :     // expand on left side?
     285        1805 :     if( nTmpMax < nCurMin )
     286             :     {
     287        1407 :         if( bSelect )
     288             :         {
     289             :             // extend first range?
     290         424 :             if( nCurMin > (nTmpMax+1)  )
     291             :             {
     292         424 :                 pRange = new Range( rIndexRange );
     293         424 :                 aSels.insert( aSels.begin() , pRange );
     294         424 :                 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         424 :             bCurValid = false;
     304             :         }
     305        1407 :         return;
     306             :     }
     307             :     // expand on right side?
     308         398 :     else if( nTmpMin > nCurMax )
     309             :     {
     310         395 :         if( bSelect )
     311             :         {
     312             :             // extend last range?
     313         354 :             if( nTmpMin > (nCurMax+1) )
     314             :             {
     315          83 :                 pRange = new Range( rIndexRange );
     316          83 :                 aSels.push_back( pRange );
     317          83 :                 nSelCount += pRange->Len();
     318             :             }
     319             :             else
     320             :             {
     321         271 :                 pRange = aSels.back();
     322         271 :                 nOld = pRange->Max();
     323         271 :                 pRange->Max() = (long)nTmpMax;
     324         271 :                 nSelCount += ( nTmpMax - nOld );
     325             :             }
     326         354 :             bCurValid = false;
     327             :         }
     328         395 :         return;
     329             :     }
     330             : 
     331             :     // TODO here is potential for optimization
     332          21 :     while( nTmpMin <= nTmpMax )
     333             :     {
     334          15 :         Select( nTmpMin, bSelect );
     335          15 :         nTmpMin++;
     336             :     }
     337             : }
     338             : 
     339        3237 : bool MultiSelection::IsSelected( long nIndex ) const
     340             : {
     341             :     // find the virtual target position
     342        3237 :     size_t nSubSelPos = ImplFindSubSelection( nIndex );
     343             : 
     344        3237 :     return nSubSelPos < aSels.size() && aSels[ nSubSelPos ]->IsInside(nIndex);
     345             : }
     346             : 
     347         103 : void MultiSelection::Insert( long nIndex, long nCount )
     348             : {
     349             :     // find the virtual target position
     350         103 :     size_t nSubSelPos = ImplFindSubSelection( nIndex );
     351             : 
     352             :     // did we need to shift the sub selections?
     353         103 :     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         103 :     bCurValid = false;
     394         103 :     aTotRange.Max() += nCount;
     395         103 :     if ( bSelectNew )
     396           0 :         nSelCount += nCount;
     397         103 : }
     398             : 
     399          22 : void MultiSelection::Remove( long nIndex )
     400             : {
     401             :     // find the virtual target position
     402          22 :     size_t nSubSelPos = ImplFindSubSelection( nIndex );
     403             : 
     404             :     // did we remove from an existing sub selection?
     405          44 :     if (  nSubSelPos < aSels.size()
     406          22 :        && 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          22 :     for ( size_t nPos = nSubSelPos; nPos < aSels.size(); ++nPos )
     426             :     {
     427           0 :         --( aSels[ nPos ]->Min() );
     428           0 :         --( aSels[ nPos ]->Max() );
     429             :     }
     430             : 
     431          22 :     bCurValid = false;
     432          22 :     aTotRange.Max() -= 1;
     433          22 : }
     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        1874 : long MultiSelection::FirstSelected( bool bInverse )
     452             : {
     453        1874 :     bInverseCur = bInverse;
     454        1874 :     nCurSubSel = 0;
     455             : 
     456        1874 :     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        1874 :         bCurValid = !aSels.empty();
     468        1874 :         if ( bCurValid )
     469         427 :             return nCurIndex = aSels[ 0 ]->Min();
     470             :     }
     471             : 
     472        1447 :     return SFX_ENDOFSELECTION;
     473             : }
     474             : 
     475        1834 : long MultiSelection::LastSelected()
     476             : {
     477        1834 :     nCurSubSel = aSels.size() - 1;
     478        1834 :     bCurValid = !aSels.empty();
     479             : 
     480        1834 :     if ( bCurValid )
     481         427 :         return nCurIndex = aSels[ nCurSubSel ]->Max();
     482             : 
     483        1407 :     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         159 : void MultiSelection::SetTotalRange( const Range& rTotRange )
     512             : {
     513         159 :     aTotRange = rTotRange;
     514             : 
     515             :     // adjust lower boundary
     516         159 :     Range* pRange = aSels.empty() ? NULL : aSels.front();
     517         318 :     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         159 :     size_t nCount = aSels.size();
     537         318 :     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         159 :     nSelCount = 0;
     558         159 :     for ( size_t i = 0, n = aSels.size(); i < n; ++ i )
     559           0 :         nSelCount += aSels[i]->Len();
     560             : 
     561         159 :     bCurValid = false;
     562         159 :     nCurIndex = 0;
     563         159 : }
     564             : 
     565             : // StringRangeEnumerator
     566             : 
     567          84 : 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          84 :     , mbValidInput( false )
     577             : {
     578             :     // Parse string only if boundaries are valid.
     579          84 :     if( mnMin >= 0 && mnMax >= 0 && mnMin <= mnMax )
     580          84 :         mbValidInput = setRange( i_rInput );
     581          84 : }
     582             : 
     583         187 : bool StringRangeEnumerator::checkValue( sal_Int32 i_nValue, const std::set< sal_Int32 >* i_pPossibleValues ) const
     584             : {
     585         187 :     if( i_nValue < 0 || i_nValue < mnMin || i_nValue > mnMax )
     586           0 :         return false;
     587         187 :     if( i_pPossibleValues && i_pPossibleValues->find( i_nValue ) == i_pPossibleValues->end() )
     588           0 :         return false;
     589         187 :     return true;
     590             : }
     591             : 
     592          84 : bool StringRangeEnumerator::insertRange( sal_Int32 i_nFirst, sal_Int32 i_nLast, bool bSequence, bool bMayAdjust )
     593             : {
     594          84 :     bool bSuccess = true;
     595          84 :     if( bSequence )
     596             :     {
     597           8 :         if( bMayAdjust )
     598             :         {
     599           8 :             if( i_nFirst < mnMin )
     600           0 :                 i_nFirst = mnMin;
     601           8 :             if( i_nFirst > mnMax )
     602           0 :                 i_nFirst = mnMax;
     603           8 :             if( i_nLast < mnMin )
     604           0 :                 i_nLast = mnMin;
     605           8 :             if( i_nLast > mnMax )
     606           0 :                 i_nLast = mnMax;
     607             :         }
     608           8 :         if( checkValue( i_nFirst ) && checkValue( i_nLast ) )
     609             :         {
     610           8 :             maSequence.push_back( Range( i_nFirst, i_nLast ) );
     611           8 :             sal_Int32 nNumber = i_nLast - i_nFirst;
     612           8 :             nNumber = nNumber < 0 ? -nNumber : nNumber;
     613           8 :             mnCount += nNumber + 1;
     614             :         }
     615             :         else
     616           0 :             bSuccess = false;
     617             :     }
     618             :     else
     619             :     {
     620          76 :         if( checkValue( i_nFirst ) )
     621             :         {
     622          76 :             maSequence.push_back( Range( i_nFirst, i_nFirst ) );
     623          76 :             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          84 :     return bSuccess;
     635             : }
     636             : 
     637          84 : bool StringRangeEnumerator::insertJoinedRanges(
     638             :     const std::vector< sal_Int32 >& rNumbers, bool i_bStrict )
     639             : {
     640          84 :     size_t nCount = rNumbers.size();
     641          84 :     if( nCount == 0 )
     642           0 :         return true;
     643             : 
     644          84 :     if( nCount == 1 )
     645           0 :         return insertRange( rNumbers[0], -1, false, ! i_bStrict );
     646             : 
     647         168 :     for( size_t i = 0; i < nCount - 1; i++ )
     648             :     {
     649          84 :         sal_Int32 nFirst = rNumbers[i];
     650          84 :         sal_Int32 nLast  = rNumbers[i + 1];
     651          84 :         if( i > 0 )
     652             :         {
     653           0 :             if     ( nFirst > nLast ) nFirst--;
     654           0 :             else if( nFirst < nLast ) nFirst++;
     655             :         }
     656             : 
     657          84 :         if ( ! insertRange( nFirst, nLast, nFirst != nLast, ! i_bStrict ) && i_bStrict)
     658           0 :             return false;
     659             :     }
     660             : 
     661          84 :     return true;
     662             : }
     663             : 
     664          84 : bool StringRangeEnumerator::setRange( const OUString& i_rNewRange, bool i_bStrict )
     665             : {
     666          84 :     mnCount = 0;
     667          84 :     maSequence.clear();
     668             : 
     669          84 :     const sal_Unicode* pInput = i_rNewRange.getStr();
     670          84 :     OUStringBuffer aNumberBuf( 16 );
     671         168 :     std::vector< sal_Int32 > aNumbers;
     672          84 :     bool bSequence = false;
     673         336 :     while( *pInput )
     674             :     {
     675         504 :         while( *pInput >= '0' && *pInput <= '9' )
     676         168 :             aNumberBuf.append( *pInput++ );
     677         168 :         if( !aNumberBuf.isEmpty() )
     678             :         {
     679         168 :             sal_Int32 nNumber = aNumberBuf.makeStringAndClear().toInt32() + mnOffset;
     680         168 :             aNumbers.push_back( nNumber );
     681         168 :             bSequence = false;
     682             :         }
     683             : 
     684         168 :         if( *pInput == '-' )
     685             :         {
     686          84 :             bSequence = true;
     687          84 :             if( aNumbers.empty() )
     688           0 :                 aNumbers.push_back( mnMin );
     689             :         }
     690          84 :         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          84 :         else if( *pInput && *pInput != ' ' )
     701           0 :             return false; // parse error
     702             : 
     703         168 :         if( *pInput )
     704          84 :             pInput++;
     705             :     }
     706             :     // insert last entries
     707          84 :     if( bSequence && !aNumbers.empty() )
     708           0 :         aNumbers.push_back( mnMax );
     709          84 :     if( ! insertJoinedRanges( aNumbers, i_bStrict ) && i_bStrict )
     710           0 :         return false;
     711             : 
     712         168 :     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          95 : StringRangeEnumerator::Iterator& StringRangeEnumerator::Iterator::operator++()
     738             : {
     739          95 :     if( nRangeIndex >= 0 && nCurrent >= 0 && pEnumerator )
     740             :     {
     741          95 :         const StringRangeEnumerator::Range& rRange( pEnumerator->maSequence[nRangeIndex] );
     742          95 :         bool bRangeChange = false;
     743          95 :         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          95 :             if( nCurrent < rRange.nLast )
     755          11 :                 nCurrent++;
     756             :             else
     757          84 :                 bRangeChange = true;
     758             :         }
     759          95 :         if( bRangeChange )
     760             :         {
     761          84 :             nRangeIndex++;
     762          84 :             if( size_t(nRangeIndex) == pEnumerator->maSequence.size() )
     763             :             {
     764             :                 // reached the end
     765          84 :                 nRangeIndex = nCurrent = -1;
     766             :             }
     767             :             else
     768           0 :                 nCurrent = pEnumerator->maSequence[nRangeIndex].nFirst;
     769             :         }
     770          95 :         if( nRangeIndex != -1 && nCurrent != -1 )
     771             :         {
     772          11 :             if( ! pEnumerator->checkValue( nCurrent, pPossibleValues ) )
     773           0 :                 return ++(*this);
     774             :         }
     775             :     }
     776          95 :     return *this;
     777             : }
     778             : 
     779             : 
     780         262 : bool StringRangeEnumerator::Iterator::operator==( const Iterator& i_rCompare ) const
     781             : {
     782         262 :     return i_rCompare.pEnumerator == pEnumerator && i_rCompare.nRangeIndex == nRangeIndex && i_rCompare.nCurrent == nCurrent;
     783             : }
     784             : 
     785          84 : StringRangeEnumerator::Iterator StringRangeEnumerator::begin( const std::set< sal_Int32 >* i_pPossibleValues ) const
     786             : {
     787             :     StringRangeEnumerator::Iterator it( this,
     788             :                                         i_pPossibleValues,
     789          84 :                                         maSequence.empty() ? -1 : 0,
     790         168 :                                         maSequence.empty() ? -1 : maSequence[0].nFirst );
     791          84 :     if( ! checkValue(*it, i_pPossibleValues ) )
     792           0 :         ++it;
     793          84 :     return it;
     794             : }
     795             : 
     796          85 : StringRangeEnumerator::Iterator StringRangeEnumerator::end( const std::set< sal_Int32 >* i_pPossibleValues ) const
     797             : {
     798          85 :     return StringRangeEnumerator::Iterator( this, i_pPossibleValues, -1, -1 );
     799             : }
     800             : 
     801           1 : 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           1 :     o_rPageVector.clear();
     810             : 
     811           1 :     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           1 :     o_rPageVector.reserve( static_cast< size_t >( aEnum.size() ) );
     816           6 :     for( StringRangeEnumerator::Iterator it = aEnum.begin( i_pPossibleValues );
     817           4 :          it != aEnum.end( i_pPossibleValues ); ++it )
     818             :     {
     819           1 :         o_rPageVector.push_back( *it );
     820             :     }
     821             : 
     822           1 :     return aEnum.isValidInput();
     823             : }
     824             : 
     825             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11