[Libreoffice-commits] core.git: Branch 'feature/formula-core-rework' - formula/source include/formula sc/inc sc/source

Kohei Yoshida kohei.yoshida at gmail.com
Mon Apr 29 11:12:39 PDT 2013


 formula/source/core/api/vectortoken.cxx |    4 -
 include/formula/vectortoken.hxx         |    4 -
 sc/inc/column.hxx                       |    9 +++
 sc/inc/document.hxx                     |    2 
 sc/inc/table.hxx                        |    1 
 sc/source/core/data/column.cxx          |   21 +++++++
 sc/source/core/data/column2.cxx         |   56 ++++++++++++++++---
 sc/source/core/data/document.cxx        |    9 +++
 sc/source/core/data/formulacell.cxx     |   90 ++++++++++++++++++++++++++++----
 sc/source/core/data/table1.cxx          |   11 +++
 10 files changed, 183 insertions(+), 24 deletions(-)

New commits:
commit fdc968dfd2423da3a349c2d6a6e9153745c511c2
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Mon Apr 29 14:14:43 2013 -0400

    Add method to allow fetching of double array, and store it in token.
    
    Change-Id: If094dbf139e18ad23c73d6cf5a78ac4844132b14

diff --git a/formula/source/core/api/vectortoken.cxx b/formula/source/core/api/vectortoken.cxx
index b7cab77..0c2e455 100644
--- a/formula/source/core/api/vectortoken.cxx
+++ b/formula/source/core/api/vectortoken.cxx
@@ -23,9 +23,9 @@ const VectorArray& SingleVectorRefToken::GetArray() const
 }
 
 DoubleVectorRefToken::DoubleVectorRefToken(
-    const std::vector<VectorArray>& rArrays, size_t nColSize, size_t nRowSize, bool bAbsStart, bool bAbsEnd ) :
+    const std::vector<VectorArray>& rArrays, size_t nRowSize, bool bAbsStart, bool bAbsEnd ) :
     FormulaToken(svDoubleVectorRef, ocPush),
-    maArrays(rArrays), mnColSize(nColSize), mnRowSize(nRowSize), mbAbsStart(bAbsStart), mbAbsEnd(bAbsEnd) {}
+    maArrays(rArrays), mnRowSize(nRowSize), mbAbsStart(bAbsStart), mbAbsEnd(bAbsEnd) {}
 
 const std::vector<VectorArray>& DoubleVectorRefToken::GetArrays() const
 {
diff --git a/include/formula/vectortoken.hxx b/include/formula/vectortoken.hxx
index 5af2690..90e28d8 100644
--- a/include/formula/vectortoken.hxx
+++ b/include/formula/vectortoken.hxx
@@ -39,7 +39,6 @@ class FORMULA_DLLPUBLIC DoubleVectorRefToken : public FormulaToken
 {
     std::vector<VectorArray> maArrays;
 
-    size_t mnColSize;
     size_t mnRowSize;
 
     bool mbAbsStart:1; /// whether or not the start row position is absolute.
@@ -47,8 +46,7 @@ class FORMULA_DLLPUBLIC DoubleVectorRefToken : public FormulaToken
 
 public:
     DoubleVectorRefToken(
-        const std::vector<VectorArray>& rArrays, size_t nColSize, size_t nRowSize,
-        bool bAbsStart, bool bAbsEnd );
+        const std::vector<VectorArray>& rArrays, size_t nRowSize, bool bAbsStart, bool bAbsEnd );
 
     const std::vector<VectorArray>& GetArrays() const;
 };
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 157bc17..6b3202a 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -106,6 +106,11 @@ struct ColDoubleEntry
 {
     SCROW               mnStart;
     std::vector<double> maData;
+
+    struct LessByPtr : std::binary_function<ColDoubleEntry*, ColDoubleEntry*, bool>
+    {
+        bool operator() (const ColDoubleEntry* p1, const ColDoubleEntry* p2) const;
+    };
 };
 
 class ScColumn
@@ -155,6 +160,9 @@ friend class ScDocumentImport;
 
     static void SwapScriptTypes( ScriptType& rSrc, SCROW nSrcRow, ScriptType& rDest, SCROW nDestRow );
 
+    std::vector<ColEntry>::iterator Search( SCROW nRow );
+    std::vector<ColEntry>::const_iterator Search( SCROW nRow ) const;
+
 public:
                 ScColumn();
                 ~ScColumn();
@@ -452,6 +460,7 @@ public:
     ScFormulaVectorState GetFormulaVectorState( SCROW nRow ) const;
     formula::FormulaTokenRef ResolveStaticReference( SCROW nRow );
     bool ResolveStaticReference( ScMatrix& rMat, SCCOL nMatCol, SCROW nRow1, SCROW nRow2 );
+    const double* FetchDoubleArray( SCROW nRow1, SCROW nRow2 ) const;
 
     ScRefCellValue GetRefCellValue( SCROW );
 
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index cdb80e0..876c9d7 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -1944,6 +1944,8 @@ public:
     formula::FormulaTokenRef ResolveStaticReference( const ScAddress& rPos );
     formula::FormulaTokenRef ResolveStaticReference( const ScRange& rRange );
 
+    const double* FetchDoubleArray( const ScAddress& rPos, SCROW nLength ) const;
+
 private: // CLOOK-Impl-methods
 
     /**
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index c04b902..7c45a57 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -822,6 +822,7 @@ public:
     ScFormulaVectorState GetFormulaVectorState( SCCOL nCol, SCROW nRow ) const;
     formula::FormulaTokenRef ResolveStaticReference( SCCOL nCol, SCROW nRow );
     formula::FormulaTokenRef ResolveStaticReference( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
+    const double* FetchDoubleArray( SCCOL nCol, SCROW nRow1, SCROW nRow2 ) const;
 
     ScRefCellValue GetRefCellValue( SCCOL nCol, SCROW nRow );
 
diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx
index 0c3e630..17bbe68 100644
--- a/sc/source/core/data/column.cxx
+++ b/sc/source/core/data/column.cxx
@@ -50,6 +50,11 @@ bool ColEntry::Less::operator() (const ColEntry& r1, const ColEntry& r2) const
     return r1.nRow < r2.nRow;
 }
 
+bool ColDoubleEntry::LessByPtr::operator() (const ColDoubleEntry* p1, const ColDoubleEntry* p2) const
+{
+    return p1->mnStart < p2->mnStart;
+}
+
 namespace {
 
 inline bool IsAmbiguousScriptNonZero( sal_uInt8 nScript )
@@ -89,6 +94,22 @@ void ScColumn::SwapScriptTypes( ScriptType& rSrc, SCROW nSrcRow, ScriptType& rDe
         rDest.set_empty(nDestRow, nDestRow);
 }
 
+std::vector<ColEntry>::iterator ScColumn::Search( SCROW nRow )
+{
+    // Find first cell whose position is equal or greater than nRow.
+    ColEntry aBound;
+    aBound.nRow = nRow;
+    return std::lower_bound(maItems.begin(), maItems.end(), aBound, ColEntry::Less());
+}
+
+std::vector<ColEntry>::const_iterator ScColumn::Search( SCROW nRow ) const
+{
+    // Find first cell whose position is equal or greater than nRow.
+    ColEntry aBound;
+    aBound.nRow = nRow;
+    return std::lower_bound(maItems.begin(), maItems.end(), aBound, ColEntry::Less());
+}
+
 ScColumn::ScColumn() :
     maTextWidths(MAXROWCOUNT),
     maScriptTypes(MAXROWCOUNT),
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index 6bcf282..25725ae 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -1591,12 +1591,8 @@ ScFormulaVectorState ScColumn::GetFormulaVectorState( SCROW nRow ) const
 
 formula::FormulaTokenRef ScColumn::ResolveStaticReference( SCROW nRow )
 {
+    std::vector<ColEntry>::iterator it = Search(nRow);
     std::vector<ColEntry>::iterator itEnd = maItems.end();
-    // Find first cell whose position is equal or greater than nRow1.
-    ColEntry aBound;
-    aBound.nRow = nRow;
-    std::vector<ColEntry>::iterator it =
-        std::lower_bound(maItems.begin(), itEnd, aBound, ColEntry::Less());
 
     if (it == itEnd || it->nRow != nRow)
     {
@@ -1633,12 +1629,8 @@ bool ScColumn::ResolveStaticReference( ScMatrix& rMat, SCCOL nMatCol, SCROW nRow
     if (nRow1 > nRow2)
         return false;
 
+    std::vector<ColEntry>::iterator it = Search(nRow1);
     std::vector<ColEntry>::iterator itEnd = maItems.end();
-    // Find first cell whose position is equal or greater than nRow1.
-    ColEntry aBound;
-    aBound.nRow = nRow1;
-    std::vector<ColEntry>::iterator it =
-        std::lower_bound(maItems.begin(), itEnd, aBound, ColEntry::Less());
 
     for (; it != itEnd && it->nRow <= nRow2; ++it)
     {
@@ -1668,6 +1660,50 @@ bool ScColumn::ResolveStaticReference( ScMatrix& rMat, SCCOL nMatCol, SCROW nRow
     return true;
 }
 
+const double* ScColumn::FetchDoubleArray( SCROW nRow1, SCROW nRow2 ) const
+{
+    if (nRow1 > nRow2)
+        return NULL;
+
+    ColDoubleEntry aBound;
+    aBound.mnStart = nRow1;
+    std::vector<ColDoubleEntry*>::const_iterator it =
+        std::lower_bound(maDoubles.begin(), maDoubles.end(), &aBound, ColDoubleEntry::LessByPtr());
+
+    if (it == maDoubles.end())
+        return NULL;
+
+    // There should never be an entry with empty double array. So we don't
+    // even bother checking for emptiness here.
+
+    const ColDoubleEntry& rEntry = **it;
+
+    if (rEntry.mnStart == nRow1)
+    {
+        SCROW nLastRow = rEntry.mnStart + rEntry.maData.size() - 1;
+        if (nLastRow < nRow2)
+            // Array is shorter than requested length.
+            return NULL;
+
+        return &rEntry.maData[0];
+    }
+
+    OSL_ASSERT(nRow1 < rEntry.mnStart);
+
+    if (it == maDoubles.begin())
+        // This is the very first array entry.
+        return NULL;
+
+    --it; // Go to previous array so that rEntry.mnStart < nRow1.
+    OSL_ASSERT((**it).mnStart < nRow1);
+    SCROW nLastRow = rEntry.mnStart + rEntry.maData.size() - 1;
+    if (nLastRow < nRow2)
+        // Array is shorter than requested length.
+        return NULL;
+
+    return &rEntry.maData[nRow1 - rEntry.mnStart];
+}
+
 ScRefCellValue ScColumn::GetRefCellValue( SCROW nRow )
 {
     ScRefCellValue aCell; // start empty
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 9a3dcf7..c4f93c6 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -1593,6 +1593,15 @@ formula::FormulaTokenRef ScDocument::ResolveStaticReference( const ScRange& rRan
         rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
 }
 
+const double* ScDocument::FetchDoubleArray( const ScAddress& rPos, SCROW nLength ) const
+{
+    SCTAB nTab = rPos.Tab();
+    if (!TableExists(nTab))
+        return NULL;
+
+    return maTabs[nTab]->FetchDoubleArray(rPos.Col(), rPos.Row(), rPos.Row()+nLength-1);
+}
+
 bool ScDocument::CanFitBlock( const ScRange& rOld, const ScRange& rNew )
 {
     if ( rOld == rNew )
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 3bfd458..20ec752 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -40,6 +40,7 @@
 #include "tokenarray.hxx"
 
 #include "formula/errorcodes.hxx"
+#include "formula/vectortoken.hxx"
 #include "svl/intitem.hxx"
 #include "rtl/strbuf.hxx"
 
@@ -2912,7 +2913,7 @@ ScFormulaCell::CompareState ScFormulaCell::CompareByTokenArray( ScFormulaCell *p
                 if (rRef != pOtherTok->GetSingleRef())
                     return NotEqual;
 
-                if (rRef.IsColRel() || rRef.IsRowRel())
+                if (rRef.IsRowRel())
                     bInvariant = false;
             }
             break;
@@ -2927,10 +2928,10 @@ ScFormulaCell::CompareState ScFormulaCell::CompareByTokenArray( ScFormulaCell *p
                 if (rRef2 != pOtherTok->GetSingleRef2())
                     return NotEqual;
 
-                if (rRef1.IsColRel() || rRef1.IsRowRel())
+                if (rRef1.IsRowRel())
                     bInvariant = false;
 
-                if (rRef2.IsColRel() || rRef2.IsRowRel())
+                if (rRef2.IsRowRel())
                     bInvariant = false;
             }
             break;
@@ -2967,6 +2968,75 @@ bool ScFormulaCell::InterpretFormulaGroup()
     if (xGroup->mbInvariant)
         return InterpretInvariantFormulaGroup();
 
+    ScTokenArray aCode;
+    pCode->Reset();
+    for (const formula::FormulaToken* p = pCode->First(); p; p = pCode->Next())
+    {
+        // A reference can be either absolute or relative.  If it's absolute,
+        // convert it to a static value token.  If relative, convert it to a
+        // vector reference token.  Note: we only care about relative vs
+        // absolute reference state for row directions.
+
+        const ScToken* pToken = static_cast<const ScToken*>(p);
+        switch (pToken->GetType())
+        {
+            case svSingleRef:
+            {
+                ScSingleRefData aRef = pToken->GetSingleRef();
+                aRef.CalcAbsIfRel(aPos);
+                ScAddress aRefPos(aRef.nCol, aRef.nRow, aRef.nTab);
+                if (aRef.IsRowRel())
+                {
+                    // Fetch double array guarantees that the length of the
+                    // returned array equals or greater than the requested
+                    // length.
+                    const double* pArray = pDocument->FetchDoubleArray(aRefPos, xGroup->mnLength);
+                    if (!pArray)
+                        return false;
+
+                    formula::SingleVectorRefToken aTok(pArray, xGroup->mnLength);
+                    aCode.AddToken(aTok);
+                }
+                else
+                {
+                    // Absolute row reference.
+                    formula::FormulaTokenRef pNewToken = pDocument->ResolveStaticReference(aRefPos);
+                    if (!pNewToken)
+                        return false;
+
+                    aCode.AddToken(*pNewToken);
+                }
+            }
+            break;
+            case svDoubleRef:
+            {
+                ScComplexRefData aRef = pToken->GetDoubleRef();
+                aRef.CalcAbsIfRel(aPos);
+                if (aRef.Ref1.IsRowRel() || aRef.Ref2.IsRowRel())
+                {
+                    // TODO: Implement this.
+                    return false;
+                }
+                else
+                {
+                    // Absolute row reference.
+                    ScRange aRefRange(
+                        aRef.Ref1.nCol, aRef.Ref1.nRow, aRef.Ref1.nTab,
+                        aRef.Ref2.nCol, aRef.Ref2.nRow, aRef.Ref2.nTab);
+
+                    formula::FormulaTokenRef pNewToken = pDocument->ResolveStaticReference(aRefRange);
+                    if (!pNewToken)
+                        return false;
+
+                    aCode.AddToken(*pNewToken);
+                }
+            }
+            break;
+            default:
+                aCode.AddToken(*pToken);
+        }
+    }
+
     // scan the formula ...
     // have a document method: "Get2DRangeAsDoublesArray" that does the
     // column-based heavy lifting call it for each absolute range from the
@@ -3001,7 +3071,7 @@ bool ScFormulaCell::InterpretInvariantFormulaGroup()
 {
     if (pCode->GetVectorState() == FormulaVectorCheckReference)
     {
-        // An invariant group should only have absolute references, and no
+        // An invariant group should only have absolute row references, and no
         // external references are allowed.
 
         ScTokenArray aCode;
@@ -3013,8 +3083,9 @@ bool ScFormulaCell::InterpretInvariantFormulaGroup()
             {
                 case svSingleRef:
                 {
-                    const ScSingleRefData& rRef = pToken->GetSingleRef();
-                    ScAddress aRefPos(rRef.nCol, rRef.nRow, rRef.nTab);
+                    ScSingleRefData aRef = pToken->GetSingleRef();
+                    aRef.CalcAbsIfRel(aPos); // column may be relative.
+                    ScAddress aRefPos(aRef.nCol, aRef.nRow, aRef.nTab);
                     formula::FormulaTokenRef pNewToken = pDocument->ResolveStaticReference(aRefPos);
                     if (!pNewToken)
                         return false;
@@ -3024,10 +3095,11 @@ bool ScFormulaCell::InterpretInvariantFormulaGroup()
                 break;
                 case svDoubleRef:
                 {
-                    const ScComplexRefData& rRef = pToken->GetDoubleRef();
+                    ScComplexRefData aRef = pToken->GetDoubleRef();
+                    aRef.CalcAbsIfRel(aPos); // column may be relative.
                     ScRange aRefRange(
-                        rRef.Ref1.nCol, rRef.Ref1.nRow, rRef.Ref1.nTab,
-                        rRef.Ref2.nCol, rRef.Ref2.nRow, rRef.Ref2.nTab);
+                        aRef.Ref1.nCol, aRef.Ref1.nRow, aRef.Ref1.nTab,
+                        aRef.Ref2.nCol, aRef.Ref2.nRow, aRef.Ref2.nTab);
 
                     formula::FormulaTokenRef pNewToken = pDocument->ResolveStaticReference(aRefRange);
                     if (!pNewToken)
diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx
index 52e0bb9..a6c60425 100644
--- a/sc/source/core/data/table1.cxx
+++ b/sc/source/core/data/table1.cxx
@@ -2140,6 +2140,17 @@ formula::FormulaTokenRef ScTable::ResolveStaticReference( SCCOL nCol1, SCROW nRo
     return formula::FormulaTokenRef(new ScMatrixToken(pMat));
 }
 
+const double* ScTable::FetchDoubleArray( SCCOL nCol, SCROW nRow1, SCROW nRow2 ) const
+{
+    if (nRow2 < nRow1)
+        return NULL;
+
+    if (!ValidCol(nCol) || !ValidRow(nRow1) || !ValidRow(nRow2))
+        return NULL;
+
+    return aCol[nCol].FetchDoubleArray(nRow1, nRow1);
+}
+
 ScRefCellValue ScTable::GetRefCellValue( SCCOL nCol, SCROW nRow )
 {
     if (!ValidColRow(nCol, nRow))


More information about the Libreoffice-commits mailing list