[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