summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLászló Németh <laszlo.nemeth@collabora.com>2015-02-28 01:40:13 +0100
committerLászló Németh <laszlo.nemeth@collabora.com>2015-02-28 01:49:39 +0100
commit3d586d61d6a2b314783203d92fb0c1b62ea0e95e (patch)
tree015355f46ca0b559d944d4b0a418deee592ad0ca
parentf5b00ec964a9b4320543028e77fb6acb25f70e74 (diff)
tdf#89436 ScHorizontalAttrIterator cleanup
+ optimization (removing cycle on cells with default attributes) Change-Id: I4441fab13cb8ba6251d8524db4045e22514436fa
-rw-r--r--sc/inc/dociter.hxx5
-rw-r--r--sc/source/core/data/dociter.cxx187
2 files changed, 88 insertions, 104 deletions
diff --git a/sc/inc/dociter.hxx b/sc/inc/dociter.hxx
index 65023b0434dd..838c100ce643 100644
--- a/sc/inc/dociter.hxx
+++ b/sc/inc/dociter.hxx
@@ -487,7 +487,7 @@ private:
SCROW nEndRow;
SCROW* pNextEnd;
- SCCOL* pPrevColEnd;
+ SCCOL* pHorizEnd;
SCSIZE* pIndices;
const ScPatternAttr** ppPatterns;
SCCOL nCol;
@@ -496,6 +496,9 @@ private:
bool bRepeatedRow;
SCROW nMinNextEnd;
+ void InitForNextRow(bool bInitialization);
+ bool InitForNextAttr();
+
public:
ScHorizontalAttrIterator( ScDocument* pDocument, SCTAB nTable,
SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
diff --git a/sc/source/core/data/dociter.cxx b/sc/source/core/data/dociter.cxx
index 77cf69379ea9..6ab77bc304be 100644
--- a/sc/source/core/data/dociter.cxx
+++ b/sc/source/core/data/dociter.cxx
@@ -2230,8 +2230,6 @@ ScHorizontalAttrIterator::ScHorizontalAttrIterator( ScDocument* pDocument, SCTAB
OSL_FAIL("try to access index out of bounds, FIX IT");
OSL_ENSURE( pDoc->maTabs[nTab], "Table does not exist" );
- SCCOL i;
-
nRow = nStartRow;
nCol = nStartCol;
bRowEmpty = false;
@@ -2239,49 +2237,97 @@ ScHorizontalAttrIterator::ScHorizontalAttrIterator( ScDocument* pDocument, SCTAB
pIndices = new SCSIZE[nEndCol-nStartCol+1];
pNextEnd = new SCROW[nEndCol-nStartCol+1];
- pPrevColEnd = new SCCOL[nEndCol-nStartCol+1];
+ pHorizEnd = new SCCOL[nEndCol-nStartCol+1];
ppPatterns = new const ScPatternAttr*[nEndCol-nStartCol+1];
- nMinNextEnd = MAXROW;
+ InitForNextRow(true);
+}
+
+ScHorizontalAttrIterator::~ScHorizontalAttrIterator()
+{
+ delete[] ppPatterns;
+ delete[] pHorizEnd;
+ delete[] pNextEnd;
+ delete[] pIndices;
+}
+
+void ScHorizontalAttrIterator::InitForNextRow(bool bInitialization)
+{
bool bEmpty = true;
- for (i=nStartCol; i<=nEndCol; i++)
+ nMinNextEnd = MAXROW;
+ SCCOL nThisHead = 0;
+
+ for (SCCOL i=nStartCol; i<=nEndCol; i++)
{
SCCOL nPos = i - nStartCol;
- const ScAttrArray* pArray = pDoc->maTabs[nTab]->aCol[i].pAttrArray;
- OSL_ENSURE( pArray, "pArray == 0" );
+ if ( bInitialization || pNextEnd[nPos] < nRow )
+ {
+ const ScAttrArray* pArray = pDoc->maTabs[nTab]->aCol[i].pAttrArray;
+ OSL_ENSURE( pArray, "pArray == 0" );
+
+ SCSIZE nIndex;
+ if (bInitialization)
+ {
+ pArray->Search( nStartRow, nIndex );
+ pIndices[nPos] = nIndex;
+ pHorizEnd[nPos] = MAXCOL+1; // only for OSL_ENSURE
+ }
+ else
+ nIndex = ++pIndices[nPos];
- SCSIZE nIndex;
- pArray->Search( nStartRow, nIndex );
+ if ( nIndex < pArray->nCount )
+ {
+ const ScPatternAttr* pPattern = pArray->pData[nIndex].pPattern;
+ SCROW nThisEnd = pArray->pData[nIndex].nRow;
- const ScPatternAttr* pPattern = pArray->pData[nIndex].pPattern;
- SCROW nThisEnd = pArray->pData[nIndex].nRow;
+ if ( IsDefaultItem( pPattern ) )
+ pPattern = NULL;
+ else
+ bEmpty = false; // Found attributes
- if ( nThisEnd < nMinNextEnd )
- nMinNextEnd = nThisEnd; // nMinNextEnd can be set here already
+ pNextEnd[nPos] = nThisEnd;
+ OSL_ENSURE( pNextEnd[nPos] >= nRow, "Sequence out of order" );
+ ppPatterns[nPos] = pPattern;
+ }
+ else
+ {
+ OSL_FAIL("AttrArray does not range to MAXROW");
+ pNextEnd[nPos] = MAXROW;
+ ppPatterns[nPos] = NULL;
+ }
+ }
+ else if ( ppPatterns[nPos] )
+ bEmpty = false; // Area not at the end yet
- if ( IsDefaultItem( pPattern ) )
- pPattern = NULL;
- else
- bEmpty = false; // Found attributes
+ if ( nMinNextEnd > pNextEnd[nPos] )
+ nMinNextEnd = pNextEnd[nPos];
- pIndices[nPos] = nIndex;
- pNextEnd[nPos] = nThisEnd;
- pPrevColEnd[nPos] = MAXCOL+1; // only for OSL_ENSURE
- ppPatterns[nPos] = pPattern;
+ // store positions of ScHorizontalAttrIterator elements (minimizing expensive ScPatternAttr comparisons)
+ if (i > nStartCol && ppPatterns[nThisHead] != ppPatterns[nPos])
+ {
+ pHorizEnd[nThisHead] = i - 1;
+ nThisHead = nPos; // start position of the next horizontal group
+ }
}
if (bEmpty)
nRow = nMinNextEnd; // Skip until end of next section
-
+ else
+ pHorizEnd[nThisHead] = nEndCol; // set the end position of the last horizontal group, too
bRowEmpty = bEmpty;
}
-ScHorizontalAttrIterator::~ScHorizontalAttrIterator()
+bool ScHorizontalAttrIterator::InitForNextAttr()
{
- delete[] ppPatterns;
- delete[] pNextEnd;
- delete[] pPrevColEnd;
- delete[] pIndices;
+ if ( !ppPatterns[nCol-nStartCol] ) // Skip default items
+ {
+ OSL_ENSURE( pHorizEnd[nCol-nStartCol] < MAXCOL+1, "missing stored data" );
+ nCol = pHorizEnd[nCol-nStartCol] + 1;
+ if ( nCol > nEndCol )
+ return false;
+ }
+
+ return true;
}
const ScPatternAttr* ScHorizontalAttrIterator::GetNext( SCCOL& rCol1, SCCOL& rCol2, SCROW& rRow )
@@ -2290,35 +2336,16 @@ const ScPatternAttr* ScHorizontalAttrIterator::GetNext( SCCOL& rCol1, SCCOL& rCo
OSL_FAIL("try to access index out of bounds, FIX IT");
for (;;)
{
- if (!bRowEmpty)
+ if ( !bRowEmpty && nCol <= nEndCol && InitForNextAttr() )
{
- // Search in this row
- while ( nCol <= nEndCol && !ppPatterns[nCol-nStartCol] )
- ++nCol;
-
- if ( nCol <= nEndCol )
- {
- const ScPatternAttr* pPat = ppPatterns[nCol-nStartCol];
- rRow = nRow;
- rCol1 = nCol;
- if ( bRepeatedRow )
- {
- OSL_ENSURE( pPrevColEnd[nCol-nStartCol] < MAXCOL+1, "missing stored data" );
- nCol = pPrevColEnd[nCol-nStartCol]; // use the result stored before
- }
- else
- {
- while ( nCol < nEndCol && ( ppPatterns[nCol+1-nStartCol] == pPat) )
- ++nCol;
- // store the result to avoid the previous very expensive comparisons
- pPrevColEnd[rCol1-nStartCol] = nCol;
- }
- rCol2 = nCol;
- ++nCol; // Count up for next call
- return pPat; // Found it!
- }
-
- bRepeatedRow = true; // we can use the stored row data next time
+ const ScPatternAttr* pPat = ppPatterns[nCol-nStartCol];
+ rRow = nRow;
+ rCol1 = nCol;
+ OSL_ENSURE( pHorizEnd[nCol-nStartCol] < MAXCOL+1, "missing stored data" );
+ nCol = pHorizEnd[nCol-nStartCol];
+ rCol2 = nCol;
+ ++nCol; // Count up for next call
+ return pPat; // Found it!
}
// Next row
@@ -2327,54 +2354,8 @@ const ScPatternAttr* ScHorizontalAttrIterator::GetNext( SCCOL& rCol1, SCCOL& rCo
return NULL; // Found nothing
nCol = nStartCol; // Start at the left again
- if ( bRepeatedRow && nRow <= nMinNextEnd ) // use only the stored data of the previous row
- continue;
-
- bRepeatedRow = false;
- nMinNextEnd = MAXROW;
- bool bEmpty = true;
- SCCOL i;
-
- for ( i = nStartCol; i <= nEndCol; i++)
- {
- SCCOL nPos = i-nStartCol;
- if ( pNextEnd[nPos] < nRow )
- {
- const ScAttrArray* pArray = pDoc->maTabs[nTab]->aCol[i].pAttrArray;
-
- SCSIZE nIndex = ++pIndices[nPos];
- if ( nIndex < pArray->nCount )
- {
- const ScPatternAttr* pPattern = pArray->pData[nIndex].pPattern;
- SCROW nThisEnd = pArray->pData[nIndex].nRow;
- if ( IsDefaultItem( pPattern ) )
- pPattern = NULL;
- else
- bEmpty = false; // Found attributes
-
- pNextEnd[nPos] = nThisEnd;
- ppPatterns[nPos] = pPattern;
-
- OSL_ENSURE( pNextEnd[nPos] >= nRow, "Sequence out of order" );
- }
- else
- {
- OSL_FAIL("AttrArray does not range to MAXROW");
- pNextEnd[nPos] = MAXROW;
- ppPatterns[nPos] = NULL;
- }
- }
- else if ( ppPatterns[nPos] )
- bEmpty = false; // Area not at the end yet
-
- if ( nMinNextEnd > pNextEnd[nPos] )
- nMinNextEnd = pNextEnd[nPos];
-
- }
-
- if (bEmpty)
- nRow = nMinNextEnd; // Skip empty rows
- bRowEmpty = bEmpty;
+ if ( bRowEmpty || nRow > nMinNextEnd )
+ InitForNextRow(false);
}
}