LCOV - code coverage report
Current view: top level - sc/source/core/data - markarr.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 188 199 94.5 %
Date: 2015-06-13 12:38:46 Functions: 17 17 100.0 %
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 "markarr.hxx"
      21             : #include "global.hxx"
      22             : #include "address.hxx"
      23             : 
      24             : #include <osl/diagnose.h>
      25             : 
      26             : // STATIC DATA -----------------------------------------------------------
      27             : 
      28     1164288 : ScMarkArray::ScMarkArray() :
      29             :     nCount( 0 ),
      30             :     nLimit( 0 ),
      31     1164288 :     pData( NULL )
      32             : {
      33             :     // special case "no marks" with pData = NULL
      34     1164288 : }
      35             : 
      36     1164288 : ScMarkArray::~ScMarkArray()
      37             : {
      38     1164288 :     delete[] pData;
      39     1164288 : }
      40             : 
      41       43207 : void ScMarkArray::Reset( bool bMarked )
      42             : {
      43             :     // always create pData here
      44             :     // (or have separate method to ensure pData)
      45             : 
      46       43207 :     delete[] pData;
      47             : 
      48       43207 :     nCount = nLimit = 1;
      49       43207 :     pData = new ScMarkEntry[1];
      50       43207 :     pData[0].nRow = MAXROW;
      51       43207 :     pData[0].bMarked = bMarked;
      52       43207 : }
      53             : 
      54      167571 : bool ScMarkArray::Search( SCROW nRow, SCSIZE& nIndex ) const
      55             : {
      56      167571 :     long    nHi         = static_cast<long>(nCount) - 1;
      57      167571 :     long    i           = 0;
      58      167571 :     bool    bFound      = (nCount == 1);
      59      167571 :     if (pData)
      60             :     {
      61      167127 :         long    nLo         = 0;
      62      167127 :         long    nStartRow   = 0;
      63      632118 :         while ( !bFound && nLo <= nHi )
      64             :         {
      65      297864 :             i = (nLo + nHi) / 2;
      66      297864 :             if (i > 0)
      67      163191 :                 nStartRow = (long) pData[i - 1].nRow;
      68             :             else
      69      134673 :                 nStartRow = -1;
      70      297864 :             long nEndRow = (long) pData[i].nRow;
      71      297864 :             if (nEndRow < (long) nRow)
      72      150276 :                 nLo = ++i;
      73             :             else
      74      147588 :                 if (nStartRow >= (long) nRow)
      75         451 :                     nHi = --i;
      76             :                 else
      77      147137 :                     bFound = true;
      78             :         }
      79             :     }
      80             :     else
      81         444 :         bFound = false;
      82             : 
      83      167571 :     if (bFound)
      84      167127 :         nIndex=(SCSIZE)i;
      85             :     else
      86         444 :         nIndex=0;
      87      167571 :     return bFound;
      88             : }
      89             : 
      90        2710 : bool ScMarkArray::GetMark( SCROW nRow ) const
      91             : {
      92             :     SCSIZE i;
      93        2710 :     if (Search( nRow, i ))
      94        2495 :         return pData[i].bMarked;
      95             :     else
      96         215 :         return false;
      97             : 
      98             : }
      99             : 
     100      187972 : void ScMarkArray::SetMarkArea( SCROW nStartRow, SCROW nEndRow, bool bMarked )
     101             : {
     102      187972 :     if (ValidRow(nStartRow) && ValidRow(nEndRow))
     103             :     {
     104      187972 :         if ((nStartRow == 0) && (nEndRow == MAXROW))
     105             :         {
     106       17636 :             Reset(bMarked);
     107             :         }
     108             :         else
     109             :         {
     110      170336 :             if (!pData)
     111       23337 :                 Reset(false);   // create pData for further processing - could use special case handling!
     112             : 
     113      170336 :             SCSIZE nNeeded = nCount + 2;
     114      170336 :             if ( nLimit < nNeeded )
     115             :             {
     116       24476 :                 nLimit += SC_MARKARRAY_DELTA;
     117       24476 :                 if ( nLimit < nNeeded )
     118           0 :                     nLimit = nNeeded;
     119       24476 :                 ScMarkEntry* pNewData = new ScMarkEntry[nLimit];
     120       24476 :                 memcpy( pNewData, pData, nCount*sizeof(ScMarkEntry) );
     121       24476 :                 delete[] pData;
     122       24476 :                 pData = pNewData;
     123             :             }
     124             : 
     125             :             SCSIZE ni;          // number of entries in beginning
     126             :             SCSIZE nInsert;     // insert position (MAXROW+1 := no insert)
     127      170336 :             bool bCombined = false;
     128      170336 :             bool bSplit = false;
     129      170336 :             if ( nStartRow > 0 )
     130             :             {
     131             :                 // skip beginning
     132             :                 SCSIZE nIndex;
     133      162141 :                 Search( nStartRow, nIndex );
     134      162141 :                 ni = nIndex;
     135             : 
     136      162141 :                 nInsert = MAXROWCOUNT;
     137      162141 :                 if ( pData[ni].bMarked != bMarked )
     138             :                 {
     139      147302 :                     if ( ni == 0 || (pData[ni-1].nRow < nStartRow - 1) )
     140             :                     {   // may be a split or a simple insert or just a shrink,
     141             :                         // row adjustment is done further down
     142        5030 :                         if ( pData[ni].nRow > nEndRow )
     143        4887 :                             bSplit = true;
     144        5030 :                         ni++;
     145        5030 :                         nInsert = ni;
     146             :                     }
     147      142272 :                     else if ( ni > 0 && pData[ni-1].nRow == nStartRow - 1 )
     148      142272 :                         nInsert = ni;
     149             :                 }
     150      162141 :                 if ( ni > 0 && pData[ni-1].bMarked == bMarked )
     151             :                 {   // combine
     152      142272 :                     pData[ni-1].nRow = nEndRow;
     153      142272 :                     nInsert = MAXROWCOUNT;
     154      142272 :                     bCombined = true;
     155             :                 }
     156             :             }
     157             :             else
     158             :         {
     159        8195 :                 nInsert = 0;
     160        8195 :                 ni = 0;
     161             :         }
     162             : 
     163      170336 :             SCSIZE nj = ni;     // stop position of range to replace
     164      347766 :             while ( nj < nCount && pData[nj].nRow <= nEndRow )
     165        7094 :                 nj++;
     166      170336 :             if ( !bSplit )
     167             :             {
     168      165449 :                 if ( nj < nCount && pData[nj].bMarked == bMarked )
     169             :                 {   // combine
     170       15393 :                     if ( ni > 0 )
     171             :                     {
     172          82 :                         if ( pData[ni-1].bMarked == bMarked )
     173             :                         {   // adjacent entries
     174          40 :                             pData[ni-1].nRow = pData[nj].nRow;
     175          40 :                             nj++;
     176             :                         }
     177          42 :                         else if ( ni == nInsert )
     178           8 :                             pData[ni-1].nRow = nStartRow - 1;   // shrink
     179             :                     }
     180       15393 :                     nInsert = MAXROWCOUNT;
     181       15393 :                     bCombined = true;
     182             :                 }
     183      150056 :                 else if ( ni > 0 && ni == nInsert )
     184         135 :                     pData[ni-1].nRow = nStartRow - 1;   // shrink
     185             :             }
     186      170336 :             if ( ni < nj )
     187             :             {   // remove middle entries
     188        7094 :                 if ( !bCombined )
     189             :                 {   // replace one entry
     190         820 :                     pData[ni].nRow = nEndRow;
     191         820 :                     pData[ni].bMarked = bMarked;
     192         820 :                     ni++;
     193         820 :                     nInsert = MAXROWCOUNT;
     194             :                 }
     195        7094 :                 if ( ni < nj )
     196             :                 {   // remove entries
     197        6274 :                     memmove( pData + ni, pData + nj, (nCount - nj) * sizeof(ScMarkEntry) );
     198        6274 :                     nCount -= nj - ni;
     199             :                 }
     200             :             }
     201             : 
     202      170336 :             if ( nInsert < sal::static_int_cast<SCSIZE>(MAXROWCOUNT) )
     203             :             {   // insert or append new entry
     204       11891 :                 if ( nInsert <= nCount )
     205             :                 {
     206       11891 :                     if ( !bSplit )
     207        7004 :                         memmove( pData + nInsert + 1, pData + nInsert,
     208       14008 :                             (nCount - nInsert) * sizeof(ScMarkEntry) );
     209             :                     else
     210             :                     {
     211        4887 :                         memmove( pData + nInsert + 2, pData + nInsert,
     212        9774 :                             (nCount - nInsert) * sizeof(ScMarkEntry) );
     213        4887 :                         pData[nInsert+1] = pData[nInsert-1];
     214        4887 :                         nCount++;
     215             :                     }
     216             :                 }
     217       11891 :                 if ( nInsert )
     218        5022 :                     pData[nInsert-1].nRow = nStartRow - 1;
     219       11891 :                 pData[nInsert].nRow = nEndRow;
     220       11891 :                 pData[nInsert].bMarked = bMarked;
     221       11891 :                 nCount++;
     222             :             }
     223             :         }
     224             :     }
     225      187972 : }
     226             : 
     227          36 : bool ScMarkArray::IsAllMarked( SCROW nStartRow, SCROW nEndRow ) const
     228             : {
     229             :     SCSIZE nStartIndex;
     230             :     SCSIZE nEndIndex;
     231             : 
     232          36 :     if (Search( nStartRow, nStartIndex ))
     233          36 :         if (pData[nStartIndex].bMarked)
     234          36 :             if (Search( nEndRow, nEndIndex ))
     235          36 :                 if (nEndIndex==nStartIndex)
     236          36 :                     return true;
     237             : 
     238           0 :     return false;
     239             : }
     240             : 
     241         131 : bool ScMarkArray::HasOneMark( SCROW& rStartRow, SCROW& rEndRow ) const
     242             : {
     243         131 :     bool bRet = false;
     244         131 :     if ( nCount == 1 )
     245             :     {
     246          26 :         if ( pData[0].bMarked )
     247             :         {
     248          26 :             rStartRow = 0;
     249          26 :             rEndRow = MAXROW;
     250          26 :             bRet = true;
     251             :         }
     252             :     }
     253         105 :     else if ( nCount == 2 )
     254             :     {
     255          13 :         if ( pData[0].bMarked )
     256             :         {
     257          13 :             rStartRow = 0;
     258          13 :             rEndRow = pData[0].nRow;
     259             :         }
     260             :         else
     261             :         {
     262           0 :             rStartRow = pData[0].nRow + 1;
     263           0 :             rEndRow = MAXROW;
     264             :         }
     265          13 :         bRet = true;
     266             :     }
     267          92 :     else if ( nCount == 3 )
     268             :     {
     269          79 :         if ( pData[1].bMarked )
     270             :         {
     271          79 :             rStartRow = pData[0].nRow + 1;
     272          79 :             rEndRow = pData[1].nRow;
     273          79 :             bRet = true;
     274             :         }
     275             :     }
     276         131 :     return bRet;
     277             : }
     278             : 
     279        4712 : bool ScMarkArray::HasEqualRowsMarked( const ScMarkArray& rOther ) const
     280             : {
     281        4712 :     if (nCount != rOther.nCount)
     282         403 :         return false;
     283             : 
     284       13158 :     for (size_t i=0; i < nCount; ++i)
     285             :     {
     286       19460 :         if (pData[i].bMarked != rOther.pData[i].bMarked ||
     287        9730 :                 pData[i].nRow != rOther.pData[i].nRow)
     288         881 :             return false;
     289             :     }
     290             : 
     291        3428 :     return true;
     292             : }
     293             : 
     294      234496 : void ScMarkArray::CopyMarksTo( ScMarkArray& rDestMarkArray ) const
     295             : {
     296      234496 :     delete[] rDestMarkArray.pData;
     297             : 
     298      234496 :     if (pData)
     299             :     {
     300        1138 :         rDestMarkArray.pData = new ScMarkEntry[nCount];
     301        1138 :         memcpy( rDestMarkArray.pData, pData, nCount * sizeof(ScMarkEntry) );
     302             :     }
     303             :     else
     304      233358 :         rDestMarkArray.pData = NULL;
     305             : 
     306      234496 :     rDestMarkArray.nCount = rDestMarkArray.nLimit = nCount;
     307      234496 : }
     308             : 
     309        2265 : SCsROW ScMarkArray::GetNextMarked( SCsROW nRow, bool bUp ) const
     310             : {
     311        2265 :     if (!pData)
     312        2234 :         const_cast<ScMarkArray*>(this)->Reset(false);   // create pData for further processing
     313             : 
     314        2265 :     SCsROW nRet = nRow;
     315        2265 :     if (ValidRow(nRow))
     316             :     {
     317             :         SCSIZE nIndex;
     318        2265 :         Search(nRow, nIndex);
     319        2265 :         if (!pData[nIndex].bMarked)
     320             :         {
     321        2258 :             if (bUp)
     322             :             {
     323           0 :                 if (nIndex>0)
     324           0 :                     nRet = pData[nIndex-1].nRow;
     325             :                 else
     326           0 :                     nRet = -1;
     327             :             }
     328             :             else
     329        2258 :                 nRet = pData[nIndex].nRow + 1;
     330             :         }
     331             :     }
     332        2265 :     return nRet;
     333             : }
     334             : 
     335          29 : SCROW ScMarkArray::GetMarkEnd( SCROW nRow, bool bUp ) const
     336             : {
     337          29 :     if (!pData)
     338           0 :         const_cast<ScMarkArray*>(this)->Reset(false);   // create pData for further processing
     339             : 
     340             :     SCROW nRet;
     341             :     SCSIZE nIndex;
     342          29 :     Search(nRow, nIndex);
     343             :     OSL_ENSURE( pData[nIndex].bMarked, "GetMarkEnd without bMarked" );
     344          29 :     if (bUp)
     345             :     {
     346           0 :         if (nIndex>0)
     347           0 :             nRet = pData[nIndex-1].nRow + 1;
     348             :         else
     349           0 :             nRet = 0;
     350             :     }
     351             :     else
     352          29 :         nRet = pData[nIndex].nRow;
     353             : 
     354          29 :     return nRet;
     355             : }
     356             : 
     357             : //  -------------- Iterator ----------------------------------------------
     358             : 
     359      661370 : ScMarkArrayIter::ScMarkArrayIter( const ScMarkArray* pNewArray ) :
     360             :     pArray( pNewArray ),
     361      661370 :     nPos( 0 )
     362             : {
     363      661370 : }
     364             : 
     365      661370 : ScMarkArrayIter::~ScMarkArrayIter()
     366             : {
     367      661370 : }
     368             : 
     369      736981 : bool ScMarkArrayIter::Next( SCROW& rTop, SCROW& rBottom )
     370             : {
     371      736981 :     if ( nPos >= pArray->nCount )
     372      648324 :         return false;
     373      187024 :     while (!pArray->pData[nPos].bMarked)
     374             :     {
     375       22756 :         ++nPos;
     376       22756 :         if ( nPos >= pArray->nCount )
     377       13046 :             return false;
     378             :     }
     379       75611 :     rBottom = pArray->pData[nPos].nRow;
     380       75611 :     if (nPos==0)
     381       65901 :         rTop = 0;
     382             :     else
     383        9710 :         rTop = pArray->pData[nPos-1].nRow + 1;
     384       75611 :     ++nPos;
     385       75611 :     return true;
     386         156 : }
     387             : 
     388             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11