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

Kohei Yoshida kohei.yoshida at gmail.com
Wed Apr 24 18:44:19 PDT 2013


 sc/inc/formulacell.hxx              |   11 +-
 sc/source/core/data/column3.cxx     |   31 +------
 sc/source/core/data/formulacell.cxx |  150 +++++++++++++-----------------------
 3 files changed, 71 insertions(+), 121 deletions(-)

New commits:
commit eee877bcef42435ee99b2614ba9a0ab151703aa9
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Apr 24 21:43:06 2013 -0400

    We really don't need to use similar data unless I missed something.
    
    Change-Id: Iaab6033120c3d50a54fb151916dc2a7b7ba5a98c

diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 469495a..3e68144 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -34,14 +34,12 @@ struct ScSimilarFormulaDelta;
 struct SC_DLLPUBLIC ScFormulaCellGroup
 {
     sal_Int32              mnRefCount;
-    ScSimilarFormulaDelta *mpDelta;  // difference between items in column
     sal_Int32              mnStart;  // Start offset of that cell
     sal_Int32              mnLength; // How many of these do we have ?
+    bool mbInvariant;
 
     ScFormulaCellGroup();
     ~ScFormulaCellGroup();
-
-    bool IsCompatible( ScSimilarFormulaDelta *pDelta );
 };
 inline void intrusive_ptr_add_ref(ScFormulaCellGroup *p)
 {
@@ -100,6 +98,8 @@ private:
 
 public:
 
+    enum CompareState { NotEqual = 0, EqualInvariant, EqualRelativeRef };
+
 #ifdef USE_MEMPOOL
     DECL_FIXEDMEMPOOL_NEWDEL( ScFormulaCell )
 #endif
@@ -297,8 +297,9 @@ public:
         { return xGroup; }
     void                   SetCellGroup( const ScFormulaCellGroupRef &xRef )
         { xGroup = xRef; }
-    ScSimilarFormulaDelta *BuildDeltaTo( ScFormulaCell *pOther );
-    void                   ReleaseDelta( ScSimilarFormulaDelta *pDelta );
+
+    CompareState CompareByTokenArray( ScFormulaCell *pOther ) const;
+
     bool                   InterpretFormulaGroup();
 
     // nOnlyNames may be one or more of SC_LISTENING_NAMES_*
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 3eb4b17..615fbaf 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -2118,15 +2118,14 @@ void ScColumn::RebuildFormulaGroups()
         if ( rCur.pCell->GetCellType() != CELLTYPE_FORMULA )
             continue;
 
-        // see if these formulae are similar
+        // see if these formula tokens are identical.
         ScFormulaCell *pCur = static_cast< ScFormulaCell *>( rCur.pCell );
         ScFormulaCell *pPrev = static_cast< ScFormulaCell *>( rPrev.pCell );
 
-        ScSimilarFormulaDelta *pDelta = pPrev->BuildDeltaTo( pCur );
-
-        if ( !pDelta )
+        ScFormulaCell::CompareState eCompState = pPrev->CompareByTokenArray(pCur);
+        if (eCompState == ScFormulaCell::NotEqual)
         {
-            // not similar
+            // different formula tokens.
             pCur->SetCellGroup( xNone );
             continue;
         }
@@ -2136,8 +2135,8 @@ void ScColumn::RebuildFormulaGroups()
         {
             // create a new group ...
             xGroup.reset(new ScFormulaCellGroup);
-            xGroup->mpDelta = pDelta;
             xGroup->mnStart = rPrev.nRow;
+            xGroup->mbInvariant = eCompState == ScFormulaCell::EqualInvariant;
             xGroup->mnLength = 2;
 
             maFnGroups.push_back( xGroup );
@@ -2145,27 +2144,11 @@ void ScColumn::RebuildFormulaGroups()
             pCur->SetCellGroup( xGroup );
             pPrev->SetCellGroup( xGroup );
         }
-        else if ( xGroup->IsCompatible( pDelta ) )
+        else
         {
-            // we are a compatible extension - extend the group
+            // existing group. extend its length.
             pCur->SetCellGroup( xGroup );
             xGroup->mnLength++;
-            pCur->ReleaseDelta( pDelta );
-        }
-        else
-        {
-#if OSL_DEBUG_LEVEL > 1
-            OUString aFormula;
-            pCur->GetFormula( aFormula );
-            ScAddress aAddr( nCol, rCur.nRow, nTab );
-            OUString aCellAddr;
-            aAddr.Format( aCellAddr, 0, pDocument );
-
-            fprintf( stderr, "unusual incompatible extension in cell '%s' of formulae '%s'\n" ,
-                     OUStringToOString( aCellAddr, RTL_TEXTENCODING_UTF8 ).getStr(),
-                     OUStringToOString( aFormula, RTL_TEXTENCODING_UTF8 ).getStr() );
-#endif
-            pCur->ReleaseDelta( pDelta );
         }
     }
 
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index ab70344..fe956f5 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -376,7 +376,7 @@ void adjustDBRange(ScToken* pToken, ScDocument& rNewDoc, const ScDocument* pOldD
 }
 
 ScFormulaCellGroup::ScFormulaCellGroup() :
-    mnRefCount(0), mpDelta(NULL), mnStart(0), mnLength(0)
+    mnRefCount(0), mnStart(0), mnLength(0), mbInvariant(false)
 {
 }
 
@@ -2857,123 +2857,89 @@ void ScFormulaCell::CompileColRowNameFormula()
     }
 }
 
-// we really want to be a lot more descriptive than this
-struct ScSimilarFormulaDelta : std::vector< size_t >
-{
-    bool IsCompatible( ScSimilarFormulaDelta *pDelta )
-    {
-        if ( size() != pDelta->size() )
-            return false;
-        for ( size_t i = 0; i < size(); i++ )
-        {
-            if ( (*this)[ i ] != (*pDelta)[ i ] )
-                return false;
-        }
-        return true;
-    }
-
-    void push_delta( const ScSingleRefData& a, const ScSingleRefData& b )
-    {
-        push_back( b.nCol - a.nCol );
-        push_back( b.nRow - a.nRow );
-        push_back( b.nTab - a.nTab );
-    }
-
-    /// if the vector is zero then nothing changes down the column.
-    bool IsInvariant() const
-    {
-        for ( size_t i = 0; i < size(); i++ )
-        {
-            if ( (*this)[ i ] != 0 )
-                return false;
-        }
-        return true;
-    }
-};
-
-bool ScFormulaCellGroup::IsCompatible( ScSimilarFormulaDelta *pDelta )
-{
-    return pDelta && mpDelta && mpDelta->IsCompatible( pDelta );
-}
-
-/// compare formulae tokens and build a series of deltas describing
-/// the difference - ie. the result, when added to this
-/// formulae should produce pOther
-ScSimilarFormulaDelta *ScFormulaCell::BuildDeltaTo( ScFormulaCell *pOtherCell )
+ScFormulaCell::CompareState ScFormulaCell::CompareByTokenArray( ScFormulaCell *pOtherCell ) const
 {
     // no Matrix formulae yet.
     if ( GetMatrixFlag() != MM_NONE )
-        return NULL;
+        return NotEqual;
 
     // are these formule at all similar ?
     if ( GetHash() != pOtherCell->GetHash() )
-        return NULL;
+        return NotEqual;
 
     FormulaToken **pThis = pCode->GetCode();
-    sal_uInt16     pThisLen = pCode->GetCodeLen();
+    sal_uInt16     nThisLen = pCode->GetCodeLen();
     FormulaToken **pOther = pOtherCell->pCode->GetCode();
-    sal_uInt16     pOtherLen = pOtherCell->pCode->GetCodeLen();
+    sal_uInt16     nOtherLen = pOtherCell->pCode->GetCodeLen();
 
     if ( !pThis || !pOther )
     {
-//        fprintf( stderr, "Error: no compiled code for cells !" );
-        return NULL;
+        // Error: no compiled code for cells !"
+        return NotEqual;
     }
 
-    if ( pThisLen != pOtherLen )
-        return NULL;
+    if ( nThisLen != nOtherLen )
+        return NotEqual;
+
+    bool bInvariant = true;
 
     // check we are basically the same function
-    for ( sal_uInt16 i = 0; i < pThisLen; i++ )
+    for ( sal_uInt16 i = 0; i < nThisLen; i++ )
     {
-        if ( pThis[ i ]->GetType() != pOther[ i ]->GetType() ||
-             pThis[ i ]->GetOpCode() != pOther[ i ]->GetOpCode() ||
-             pThis[ i ]->GetParamCount() != pOther[ i ]->GetParamCount() )
+        ScToken *pThisTok = static_cast<ScToken*>( pThis[i] );
+        ScToken *pOtherTok = static_cast<ScToken*>( pOther[i] );
+
+        if ( pThisTok->GetType() != pOtherTok->GetType() ||
+             pThisTok->GetOpCode() != pOtherTok->GetOpCode() ||
+             pThisTok->GetParamCount() != pOtherTok->GetParamCount() )
         {
-//            fprintf( stderr, "Incompatible type, op-code or param counts\n" );
-            return NULL;
+            // Incompatible type, op-code or param counts.
+            return NotEqual;
         }
-        switch( pThis[ i ]->GetType() )
+
+        switch (pThisTok->GetType())
         {
-        case formula::svMatrix:
-        case formula::svExternalSingleRef:
-        case formula::svExternalDoubleRef:
-//            fprintf( stderr, "Ignoring matrix and external references for now\n" );
-            return NULL;
-        default:
+            case formula::svMatrix:
+            case formula::svExternalSingleRef:
+            case formula::svExternalDoubleRef:
+                // Ignoring matrix and external references for now.
+                return NotEqual;
+
+            case formula::svSingleRef:
+            {
+                // Single cell reference.
+                const ScSingleRefData& rRef = pThisTok->GetSingleRef();
+                if (rRef != pOtherTok->GetSingleRef())
+                    return NotEqual;
+
+                if (rRef.IsColRel() || rRef.IsRowRel())
+                    bInvariant = false;
+            }
             break;
-        }
-    }
+            case formula::svDoubleRef:
+            {
+                // Range reference.
+                const ScSingleRefData& rRef1 = pThisTok->GetSingleRef();
+                const ScSingleRefData& rRef2 = pThisTok->GetSingleRef2();
+                if (rRef1 != pOtherTok->GetSingleRef())
+                    return NotEqual;
 
-    ScSimilarFormulaDelta *pDelta = new ScSimilarFormulaDelta();
+                if (rRef2 != pOtherTok->GetSingleRef2())
+                    return NotEqual;
 
-    for ( sal_uInt16 i = 0; i < pThisLen; i++ )
-    {
-        ScToken *pThisTok = static_cast< ScToken * >( pThis[ i ] );
-        ScToken *pOtherTok = static_cast< ScToken * >( pOther[ i ] );
+                if (rRef1.IsColRel() || rRef1.IsRowRel())
+                    bInvariant = false;
 
-        if ( pThis[i]->GetType() == formula::svSingleRef ||
-             pThis[i]->GetType() == formula::svDoubleRef )
-        {
-            const ScSingleRefData& aThisRef = pThisTok->GetSingleRef();
-            const ScSingleRefData& aOtherRef = pOtherTok->GetSingleRef();
-            pDelta->push_delta( aThisRef, aOtherRef );
-        }
-        if ( pThis[i]->GetType() == formula::svDoubleRef )
-        {
-            const ScSingleRefData& aThisRef2 = pThisTok->GetSingleRef2();
-            const ScSingleRefData& aOtherRef2 = pOtherTok->GetSingleRef2();
-            pDelta->push_delta( aThisRef2, aOtherRef2 );
+                if (rRef2.IsColRel() || rRef2.IsRowRel())
+                    bInvariant = false;
+            }
+            break;
+            default:
+                ;
         }
     }
 
-    return pDelta;
-}
-
-/// To avoid exposing impl. details of ScSimilarFormulaDelta publicly
-void ScFormulaCell::ReleaseDelta( ScSimilarFormulaDelta *pDelta )
-{
-    delete pDelta;
+    return bInvariant ? EqualInvariant : EqualRelativeRef;
 }
 
 bool ScFormulaCell::InterpretFormulaGroup()
@@ -2987,7 +2953,7 @@ bool ScFormulaCell::InterpretFormulaGroup()
 
 //    fprintf( stderr, "Interpret cell %d, %d\n", (int)aPos.Col(), (int)aPos.Row() );
 
-    if ( xGroup->mpDelta->IsInvariant() )
+    if (xGroup->mbInvariant)
     {
 //        fprintf( stderr, "struck gold - completely invariant for %d items !\n",
 //                 (int)xGroup->mnLength );


More information about the Libreoffice-commits mailing list