[Libreoffice-commits] core.git: Branch 'feature/formula-core-rework' - sc/inc sc/source
Kohei Yoshida
kohei.yoshida at gmail.com
Mon Jun 24 21:01:05 PDT 2013
sc/inc/column.hxx | 1
sc/inc/document.hxx | 2
sc/inc/table.hxx | 2
sc/source/core/data/column2.cxx | 156 +++++++++++++++++++++++++++++++++++++++
sc/source/core/data/documen8.cxx | 19 ++++
sc/source/core/data/table1.cxx | 7 +
sc/source/core/tool/interpr5.cxx | 125 -------------------------------
7 files changed, 188 insertions(+), 124 deletions(-)
New commits:
commit 792aa859ca22aa151dd2e3bfc9dd570cd2717731
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date: Tue Jun 25 00:03:11 2013 -0400
Use double and string arrays directly when creating matrix from cells.
Change-Id: Ib251075418baeb7d884696c54504b8851bc9f65e
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index e7c58c1..79c37fc 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -442,6 +442,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 08c4ab6..5069ccc 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1701,6 +1701,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 65cb180..fe88f09 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -845,6 +845,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 5a0badf..a946e93 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 4cbaf8d..694b398 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 d26a42c..d3d26a8 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 df47cf0..c6fc44a 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(
More information about the Libreoffice-commits
mailing list