diff options
author | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-06-25 00:03:11 -0400 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-06-27 15:47:53 -0400 |
commit | a8d277d0d90116d6f8788beb64d9bb563f159464 (patch) | |
tree | c6a9af33b96ac442a16f66a58b9ec4c030aff052 /sc | |
parent | 884528f06abcec239a67e064092003f343c966c2 (diff) |
Use double and string arrays directly when creating matrix from cells.
Change-Id: Ib251075418baeb7d884696c54504b8851bc9f65e
Diffstat (limited to 'sc')
-rw-r--r-- | sc/inc/column.hxx | 1 | ||||
-rw-r--r-- | sc/inc/document.hxx | 2 | ||||
-rw-r--r-- | sc/inc/table.hxx | 2 | ||||
-rw-r--r-- | sc/source/core/data/column2.cxx | 156 | ||||
-rw-r--r-- | sc/source/core/data/documen8.cxx | 19 | ||||
-rw-r--r-- | sc/source/core/data/table1.cxx | 7 | ||||
-rw-r--r-- | sc/source/core/tool/interpr5.cxx | 125 |
7 files changed, 188 insertions, 124 deletions
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 23e3a1608c5f..858aef4aef35 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -449,6 +449,7 @@ public: ScFormulaVectorState GetFormulaVectorState( SCROW nRow ) const; formula::FormulaTokenRef ResolveStaticReference( SCROW nRow ); bool ResolveStaticReference( ScMatrix& rMat, SCCOL nMatCol, SCROW nRow1, SCROW nRow2 ); + void FillMatrix( ScMatrix& rMat, size_t nMatCol, SCROW nRow1, SCROW nRow2 ) const; const double* FetchDoubleArray( sc::FormulaGroupContext& rCxt, SCROW nRow1, SCROW nRow2 ) const; void SetNumberFormat( SCROW nRow, sal_uInt32 nNumberFormat ); diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 377c80eacba4..25483df15bbe 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -1708,6 +1708,8 @@ public: */ bool IsEmptyData( SCTAB nTab, SCCOL nCol ) const; + void FillMatrix( ScMatrix& rMat, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) const; + private: ScDocument(const ScDocument& r); // disabled with no definition diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 15f04e50c848..64bd829d8ab0 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -851,6 +851,8 @@ public: void DeleteBroadcasters( sc::ColumnBlockPosition& rBlockPos, SCCOL nCol, SCROW nRow1, SCROW nRow2 ); bool HasBroadcaster( SCCOL nCol ) const; + void FillMatrix( ScMatrix& rMat, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) const; + /** Replace behaves differently to the Search; adjust the rCol and rRow accordingly. 'Replace' replaces at the 'current' position, but in order to achieve diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 5a0badf71c27..a946e9334afc 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -1899,6 +1899,162 @@ bool ScColumn::ResolveStaticReference( ScMatrix& rMat, SCCOL nMatCol, SCROW nRow return aFunc.isSuccess(); } +namespace { + +struct CellBucket +{ + SCSIZE mnNumValStart; + SCSIZE mnStrValStart; + std::vector<double> maNumVals; + std::vector<OUString> maStrVals; + + CellBucket() : mnNumValStart(0), mnStrValStart(0) {} + + void flush(ScMatrix& rMat, SCSIZE nCol) + { + if (!maNumVals.empty()) + { + const double* p = &maNumVals[0]; + rMat.PutDouble(p, maNumVals.size(), nCol, mnNumValStart); + reset(); + } + else if (!maStrVals.empty()) + { + const OUString* p = &maStrVals[0]; + rMat.PutString(p, maStrVals.size(), nCol, mnStrValStart); + reset(); + } + } + + void reset() + { + mnNumValStart = mnStrValStart = 0; + maNumVals.clear(); + maStrVals.clear(); + } +}; + +class FillMatrixHandler +{ + ScMatrix& mrMat; + size_t mnMatCol; + size_t mnTopRow; + + SCCOL mnCol; + SCTAB mnTab; + +public: + FillMatrixHandler(ScMatrix& rMat, size_t nMatCol, size_t nTopRow, SCCOL nCol, SCTAB nTab) : + mrMat(rMat), mnMatCol(nMatCol), mnTopRow(nTopRow), mnCol(nCol), mnTab(nTab) {} + + void operator() (const sc::CellStoreType::value_type& node, size_t nOffset, size_t nDataSize) + { + size_t nMatRow = node.position + nOffset - mnTopRow; + + switch (node.type) + { + case sc::element_type_numeric: + { + const double* p = &sc::numeric_block::at(*node.data, nOffset); + mrMat.PutDouble(p, nDataSize, mnMatCol, nMatRow); + } + break; + case sc::element_type_string: + { + const OUString* p = &sc::string_block::at(*node.data, nOffset); + mrMat.PutString(p, nDataSize, mnMatCol, nMatRow); + } + break; + case sc::element_type_edittext: + { + std::vector<OUString> aStrs; + aStrs.reserve(nDataSize); + sc::edittext_block::const_iterator it = sc::edittext_block::begin(*node.data); + std::advance(it, nOffset); + sc::edittext_block::const_iterator itEnd = it; + std::advance(itEnd, nDataSize); + for (; it != itEnd; ++it) + aStrs.push_back(ScEditUtil::GetString(**it)); + + const OUString* p = &aStrs[0]; + mrMat.PutString(p, nDataSize, mnMatCol, nMatRow); + } + break; + case sc::element_type_formula: + { + CellBucket aBucket; + sc::formula_block::const_iterator it = sc::formula_block::begin(*node.data); + std::advance(it, nOffset); + sc::formula_block::const_iterator itEnd = it; + std::advance(itEnd, nDataSize); + + size_t nPrevRow, nThisRow = node.position + nOffset; + for (; it != itEnd; ++it, nPrevRow = nThisRow, ++nThisRow) + { + ScFormulaCell& rCell = const_cast<ScFormulaCell&>(**it); + + if (rCell.IsEmpty()) + { + aBucket.flush(mrMat, mnMatCol); + continue; + } + + sal_uInt16 nErr; + double fVal; + if (rCell.GetErrorOrValue(nErr, fVal)) + { + ScAddress aAdr(mnCol, nThisRow, mnTab); + + if (nErr) + fVal = CreateDoubleError(nErr); + + if (!aBucket.maNumVals.empty() && nThisRow == nPrevRow + 1) + { + // Secondary numbers. + aBucket.maNumVals.push_back(fVal); + } + else + { + // First number. + aBucket.flush(mrMat, mnMatCol); + aBucket.mnNumValStart = nThisRow - mnTopRow; + aBucket.maNumVals.push_back(fVal); + } + continue; + } + + OUString aStr = rCell.GetString(); + if (!aBucket.maStrVals.empty() && nThisRow == nPrevRow + 1) + { + // Secondary strings. + aBucket.maStrVals.push_back(aStr); + } + else + { + // First string. + aBucket.flush(mrMat, mnMatCol); + aBucket.mnStrValStart = nThisRow - mnTopRow; + aBucket.maStrVals.push_back(aStr); + } + } + + aBucket.flush(mrMat, mnMatCol); + } + break; + default: + ; + } + } +}; + +} + +void ScColumn::FillMatrix( ScMatrix& rMat, size_t nMatCol, SCROW nRow1, SCROW nRow2 ) const +{ + FillMatrixHandler aFunc(rMat, nMatCol, nRow1, nCol, nTab); + sc::ParseBlock(maCells.begin(), maCells, aFunc, nRow1, nRow2); +} + const double* ScColumn::FetchDoubleArray( sc::FormulaGroupContext& /*rCxt*/, SCROW nRow1, SCROW nRow2 ) const { // TODO: I'll use the context object later. diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx index 4cbaf8d1be51..694b3985405a 100644 --- a/sc/source/core/data/documen8.cxx +++ b/sc/source/core/data/documen8.cxx @@ -431,6 +431,25 @@ bool ScDocument::IsEmptyData( SCTAB nTab, SCCOL nCol ) const return pTab->IsEmptyData(nCol); } +void ScDocument::FillMatrix( + ScMatrix& rMat, SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) const +{ + const ScTable* pTab = FetchTable(nTab); + if (!pTab) + return; + + if (nCol1 > nCol2 || nRow1 > nRow2) + return; + + SCSIZE nC, nR; + rMat.GetDimensions(nC, nR); + if (static_cast<SCROW>(nR) != nRow2 - nRow1 + 1 || static_cast<SCCOL>(nC) != nCol2 - nCol1 + 1) + return; + + pTab->FillMatrix(rMat, nCol1, nRow1, nCol2, nRow2); +} + + //------------------------------------------------------------------------ void ScDocument::InvalidateTextWidth( const ScAddress* pAdrFrom, const ScAddress* pAdrTo, diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx index d26a42c2ba64..d3d26a8396f0 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -2202,6 +2202,13 @@ bool ScTable::HasBroadcaster( SCCOL nCol ) const return aCol[nCol].HasBroadcaster(); } +void ScTable::FillMatrix( ScMatrix& rMat, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 ) const +{ + size_t nMatCol = 0; + for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol, ++nMatCol) + aCol[nCol].FillMatrix(rMat, nMatCol, nRow1, nRow2); +} + const SvtBroadcaster* ScTable::GetBroadcaster( SCCOL nCol, SCROW nRow ) const { if (!ValidColRow(nCol, nRow)) diff --git a/sc/source/core/tool/interpr5.cxx b/sc/source/core/tool/interpr5.cxx index df47cf0d7a31..c6fc44a3509e 100644 --- a/sc/source/core/tool/interpr5.cxx +++ b/sc/source/core/tool/interpr5.cxx @@ -344,43 +344,6 @@ ScInterpreter::VolatileType ScInterpreter::GetVolatileType() const return meVolatileType; } -namespace { - -struct CellBucket -{ - SCSIZE mnNumValStart; - SCSIZE mnStrValStart; - std::vector<double> maNumVals; - std::vector<OUString> maStrVals; - - CellBucket() : mnNumValStart(0), mnStrValStart(0) {} - - void flush(ScMatrix& rMat, SCSIZE nCol) - { - if (!maNumVals.empty()) - { - const double* p = &maNumVals[0]; - rMat.PutDouble(p, maNumVals.size(), nCol, mnNumValStart); - reset(); - } - else if (!maStrVals.empty()) - { - const OUString* p = &maStrVals[0]; - rMat.PutString(p, maStrVals.size(), nCol, mnStrValStart); - reset(); - } - } - - void reset() - { - mnNumValStart = mnStrValStart = 0; - maNumVals.clear(); - maStrVals.clear(); - } -}; - -} - ScMatrixRef ScInterpreter::CreateMatrixFromDoubleRef( const FormulaToken* pToken, SCCOL nCol1, SCROW nRow1, SCTAB nTab1, SCCOL nCol2, SCROW nRow2, SCTAB nTab2 ) @@ -412,93 +375,7 @@ ScMatrixRef ScInterpreter::CreateMatrixFromDoubleRef( const FormulaToken* pToken if (!pMat || nGlobalError) return NULL; - CellBucket aBucket; - - for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) - { - // Scan one column at a time, to pass a sequence of values to matrix in one call. - ScCellIterator aCellIter( - pDok, ScRange(nCol, nRow1, nTab1, nCol, nRow2, nTab2)); - - SCROW nPrevRow = -2, nThisRow = -2; - - // Neighboring cell values of identical type are stored and passed as - // an array to the matrix object, for performance reasons. - for (bool bHas = aCellIter.first(); bHas; bHas = aCellIter.next(), nPrevRow = nThisRow) - { - nThisRow = aCellIter.GetPos().Row(); - - if (aCellIter.hasEmptyData()) - { - aBucket.flush(*pMat, static_cast<SCSIZE>(nCol-nCol1)); - continue; - } - - if (aCellIter.hasNumeric()) - { - ScAddress aAdr(nCol, nThisRow, nTab1); - ScRefCellValue aCell = aCellIter.getRefCellValue(); - double fVal = GetCellValue(aCellIter.GetPos(), aCell); - - if ( nGlobalError ) - { - fVal = CreateDoubleError( nGlobalError); - nGlobalError = 0; - } - - if (!aBucket.maNumVals.empty() && nThisRow == nPrevRow + 1) - { - // Secondary numbers. - aBucket.maNumVals.push_back(fVal); - } - else - { - // First number. - aBucket.flush(*pMat, static_cast<SCSIZE>(nCol-nCol1)); - aBucket.mnNumValStart = nThisRow - nRow1; - aBucket.maNumVals.push_back(fVal); - } - continue; - } - - String aStr = aCellIter.getString(); - if ( nGlobalError ) - { - double fVal = CreateDoubleError( nGlobalError); - nGlobalError = 0; - - if (!aBucket.maNumVals.empty() && nThisRow == nPrevRow + 1) - { - // Secondary numbers. - aBucket.maNumVals.push_back(fVal); - } - else - { - // First number. - aBucket.flush(*pMat, static_cast<SCSIZE>(nCol-nCol1)); - aBucket.mnNumValStart = nThisRow - nRow1; - aBucket.maNumVals.push_back(fVal); - } - } - else - { - if (!aBucket.maStrVals.empty() && nThisRow == nPrevRow + 1) - { - // Secondary numbers. - aBucket.maStrVals.push_back(aStr); - } - else - { - // First number. - aBucket.flush(*pMat, static_cast<SCSIZE>(nCol-nCol1)); - aBucket.mnStrValStart = nThisRow - nRow1; - aBucket.maStrVals.push_back(aStr); - } - } - } - - aBucket.flush(*pMat, static_cast<SCSIZE>(nCol-nCol1)); - } + pDok->FillMatrix(*pMat, nTab1, nCol1, nRow1, nCol2, nRow2); if (pTokenMatrixMap) pTokenMatrixMap->insert( ScTokenMatrixMap::value_type( |