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

Kohei Yoshida kohei.yoshida at gmail.com
Tue Mar 26 08:58:56 PDT 2013


 sc/inc/cell.hxx                   |    1 
 sc/inc/cellvalue.hxx              |   56 ++++++
 sc/inc/column.hxx                 |    1 
 sc/inc/document.hxx               |   11 +
 sc/inc/table.hxx                  |    1 
 sc/source/core/data/cellvalue.cxx |  309 ++++++++++++++++++++++++++++----------
 sc/source/core/data/column3.cxx   |   12 +
 sc/source/core/data/document.cxx  |    8 
 sc/source/core/data/table2.cxx    |    7 
 9 files changed, 326 insertions(+), 80 deletions(-)

New commits:
commit 0aa3d9c489effcc9ab01946ab9cea846bbab1c39
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Tue Mar 26 12:00:43 2013 -0400

    Add ScRefCellValue, which is ScCellValue without copied value.
    
    It directly points to the original cell value instance.
    
    Change-Id: I638ec8b931873d237871b6d8fa9f0e1277520d0f

diff --git a/sc/inc/cell.hxx b/sc/inc/cell.hxx
index 236ad43..0b78f98 100644
--- a/sc/inc/cell.hxx
+++ b/sc/inc/cell.hxx
@@ -175,6 +175,7 @@ public:
 
     inline void     SetString( const rtl::OUString& rString ) { maString = rString; }
     inline const    rtl::OUString& GetString() const { return maString; }
+    const OUString* GetStringPtr() const { return &maString; }
 
 private:
     rtl::OUString   maString;
diff --git a/sc/inc/cellvalue.hxx b/sc/inc/cellvalue.hxx
index 9dd3a9a..7998898 100644
--- a/sc/inc/cellvalue.hxx
+++ b/sc/inc/cellvalue.hxx
@@ -19,7 +19,8 @@ class ScBaseCell;
 
 /**
  * Store arbitrary cell value of any kind.  It only stores cell value and
- * nothing else.
+ * nothing else.  It creates a copy of the original cell value, and manages
+ * the life cycle of the copied value.
  */
 struct SC_DLLPUBLIC ScCellValue
 {
@@ -78,6 +79,59 @@ struct SC_DLLPUBLIC ScCellValue
     void swap( ScCellValue& r );
 };
 
+/**
+ * This is very similar to ScCellValue, except that it points to the
+ * original value instead of copying it.  As such, don't hold an instance of
+ * this class any longer than necessary.
+ */
+struct SC_DLLPUBLIC ScRefCellValue
+{
+    CellType meType;
+    union {
+        double mfValue;
+        const OUString* mpString;
+        const EditTextObject* mpEditText;
+        ScFormulaCell* mpFormula;
+    };
+
+    ScRefCellValue();
+    ScRefCellValue( double fValue );
+    ScRefCellValue( const OUString* pString );
+    ScRefCellValue( const EditTextObject* pEditText );
+    ScRefCellValue( ScFormulaCell* pFormula );
+    ScRefCellValue( const ScRefCellValue& r );
+    ~ScRefCellValue();
+
+    void clear();
+
+    /**
+     * Take cell value from specified position in specified document.
+     */
+    void assign( ScDocument& rDoc, const ScAddress& rPos );
+
+    /**
+     * TODO: Remove this later.
+     */
+    void assign( ScBaseCell& rCell );
+
+    /**
+     * Set cell value at specified position in specified document.
+     */
+    void commit( ScDocument& rDoc, const ScAddress& rPos ) const;
+
+    bool hasString() const;
+
+    bool hasNumeric() const;
+
+    bool isEmpty() const;
+
+    bool equalsWithoutFormat( const ScRefCellValue& r ) const;
+
+    ScRefCellValue& operator= ( const ScRefCellValue& r );
+
+    void swap( ScRefCellValue& r );
+};
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index f25dc78..ac329b2 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -272,6 +272,7 @@ public:
     void        SetError( SCROW nRow, const sal_uInt16 nError);
 
     void        GetString( SCROW nRow, rtl::OUString& rString ) const;
+    const OUString* GetStringCell( SCROW nRow ) const;
     void        GetInputString( SCROW nRow, rtl::OUString& rString ) const;
     double      GetValue( SCROW nRow ) const;
     const EditTextObject* GetEditText( SCROW nRow ) const;
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 70c5620..892d18f 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -802,6 +802,17 @@ public:
 
     SC_DLLPUBLIC OUString GetString( SCCOL nCol, SCROW nRow, SCTAB nTab ) const;
     OUString GetString( const ScAddress& rPos ) const;
+
+    /**
+     * Return a pointer to the string object stored in string cell.
+     *
+     * @param rPos cell position.
+     *
+     * @return pointer to the string object stored in string cell, or NULL if
+     *         the cell at specified position is not a string cell. Note that
+     *         it returns NULL even for a edit cell.
+     */
+    const OUString* GetStringCell( const ScAddress& rPos ) const;
     SC_DLLPUBLIC void           GetInputString( SCCOL nCol, SCROW nRow, SCTAB nTab, String& rString );
     SC_DLLPUBLIC void           GetInputString( SCCOL nCol, SCROW nRow, SCTAB nTab, rtl::OUString& rString );
     sal_uInt16                  GetStringForFormula( const ScAddress& rPos, rtl::OUString& rString );
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 461da522..0a12ead 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -318,6 +318,7 @@ public:
     void        SetError( SCCOL nCol, SCROW nRow, sal_uInt16 nError);
 
     void        GetString( SCCOL nCol, SCROW nRow, rtl::OUString& rString ) const;
+    const OUString* GetStringCell( SCCOL nCol, SCROW nRow ) const;
     void        GetInputString( SCCOL nCol, SCROW nRow, rtl::OUString& rString ) const;
     double      GetValue( const ScAddress& rPos ) const
                     {
diff --git a/sc/source/core/data/cellvalue.cxx b/sc/source/core/data/cellvalue.cxx
index 8b0baa4..5b853a3 100644
--- a/sc/source/core/data/cellvalue.cxx
+++ b/sc/source/core/data/cellvalue.cxx
@@ -16,6 +16,121 @@
 #include "editutil.hxx"
 #include "formula/token.hxx"
 
+namespace {
+
+CellType adjustCellType( CellType eOrig )
+{
+    switch (eOrig)
+    {
+        case CELLTYPE_NOTE:
+            return CELLTYPE_NONE;
+        case CELLTYPE_EDIT:
+            return CELLTYPE_STRING;
+        default:
+            ;
+    }
+    return eOrig;
+}
+
+template<typename _T>
+OUString getString( const _T& rVal )
+{
+    if (rVal.meType == CELLTYPE_STRING)
+        return *rVal.mpString;
+
+    if (rVal.meType == CELLTYPE_EDIT)
+    {
+        OUStringBuffer aRet;
+        size_t n = rVal.mpEditText->GetParagraphCount();
+        for (size_t i = 0; i < n; ++i)
+        {
+            if (i > 0)
+                aRet.append('\n');
+            aRet.append(rVal.mpEditText->GetText(i));
+        }
+        return aRet.makeStringAndClear();
+    }
+
+    return EMPTY_OUSTRING;
+}
+
+bool equalsFormulaCells( const ScFormulaCell* p1, const ScFormulaCell* p2 )
+{
+    const ScTokenArray* pCode1 = p1->GetCode();
+    const ScTokenArray* pCode2 = p2->GetCode();
+
+    if (pCode1->GetLen() != pCode2->GetLen())
+        return false;
+
+    sal_uInt16 n = pCode1->GetLen();
+    formula::FormulaToken** ppToken1 = pCode1->GetArray();
+    formula::FormulaToken** ppToken2 = pCode2->GetArray();
+    for (sal_uInt16 i = 0; i < n; ++i)
+    {
+        if (!ppToken1[i]->TextEqual(*(ppToken2[i])))
+            return false;
+    }
+
+    return true;
+}
+
+template<typename _T>
+bool equalsWithoutFormatImpl( const _T& left, const _T& right )
+{
+    CellType eType1 = adjustCellType(left.meType);
+    CellType eType2 = adjustCellType(right.meType);
+    if (eType1 != eType2)
+        return false;
+
+    switch (eType1)
+    {
+        case CELLTYPE_NONE:
+            return true;
+        case CELLTYPE_VALUE:
+            return left.mfValue == right.mfValue;
+        case CELLTYPE_STRING:
+        {
+            OUString aStr1 = getString(left);
+            OUString aStr2 = getString(right);
+            return aStr1 == aStr2;
+        }
+        case CELLTYPE_FORMULA:
+            return equalsFormulaCells(left.mpFormula, right.mpFormula);
+        default:
+            ;
+    }
+    return false;
+}
+
+bool hasStringImpl( CellType eType, ScFormulaCell* pFormula )
+{
+    switch (eType)
+    {
+        case CELLTYPE_STRING:
+        case CELLTYPE_EDIT:
+            return true;
+        case CELLTYPE_FORMULA:
+            return !pFormula->IsValue();
+        default:
+            return false;
+    }
+}
+
+bool hasNumericImpl( CellType eType, ScFormulaCell* pFormula )
+{
+    switch (eType)
+    {
+        case CELLTYPE_VALUE:
+            return true;
+        case CELLTYPE_FORMULA:
+            return pFormula->IsValue();
+        default:
+            return false;
+    }
+}
+
+}
+
 ScCellValue::ScCellValue() : meType(CELLTYPE_NONE), mfValue(0.0) {}
 ScCellValue::ScCellValue( double fValue ) : meType(CELLTYPE_VALUE), mfValue(fValue) {}
 ScCellValue::ScCellValue( const OUString& rString ) : meType(CELLTYPE_STRING), mpString(new OUString(rString)) {}
@@ -223,29 +338,12 @@ void ScCellValue::release( ScDocument& rDoc, const ScAddress& rPos )
 
 bool ScCellValue::hasString() const
 {
-    switch (meType)
-    {
-        case CELLTYPE_STRING:
-        case CELLTYPE_EDIT:
-            return true;
-        case CELLTYPE_FORMULA:
-            return !mpFormula->IsValue();
-        default:
-            return false;
-    }
+    return hasStringImpl(meType, mpFormula);
 }
 
 bool ScCellValue::hasNumeric() const
 {
-    switch (meType)
-    {
-        case CELLTYPE_VALUE:
-            return true;
-        case CELLTYPE_FORMULA:
-            return mpFormula->IsValue();
-        default:
-            return false;
-    }
+    return hasNumericImpl(meType, mpFormula);
 }
 
 bool ScCellValue::isEmpty() const
@@ -253,97 +351,150 @@ bool ScCellValue::isEmpty() const
     return meType == CELLTYPE_NOTE || meType == CELLTYPE_NONE;
 }
 
-namespace {
+bool ScCellValue::equalsWithoutFormat( const ScCellValue& r ) const
+{
+    return equalsWithoutFormatImpl(*this, r);
+}
 
-CellType adjustCellType( CellType eOrig )
+ScCellValue& ScCellValue::operator= ( const ScCellValue& r )
 {
-    switch (eOrig)
+    ScCellValue aTmp(r);
+    swap(aTmp);
+    return *this;
+}
+
+void ScCellValue::swap( ScCellValue& r )
+{
+    std::swap(meType, r.meType);
+
+    // double is 8 bytes, whereas a pointer may be 4 or 8 bytes depending on
+    // the platform. Swap by double values.
+    std::swap(mfValue, r.mfValue);
+}
+
+ScRefCellValue::ScRefCellValue() : meType(CELLTYPE_NONE), mfValue(0.0) {}
+ScRefCellValue::ScRefCellValue( double fValue ) : meType(CELLTYPE_VALUE), mfValue(fValue) {}
+ScRefCellValue::ScRefCellValue( const OUString* pString ) : meType(CELLTYPE_STRING), mpString(pString) {}
+ScRefCellValue::ScRefCellValue( const EditTextObject* pEditText ) : meType(CELLTYPE_EDIT), mpEditText(pEditText) {}
+ScRefCellValue::ScRefCellValue( ScFormulaCell* pFormula ) : meType(CELLTYPE_FORMULA), mpFormula(pFormula) {}
+
+// It should be enough to copy the double value, which is at least as large
+// as the pointer values.
+ScRefCellValue::ScRefCellValue( const ScRefCellValue& r ) : meType(r.meType), mfValue(r.mfValue) {}
+
+ScRefCellValue::~ScRefCellValue()
+{
+    clear();
+}
+
+void ScRefCellValue::clear()
+{
+    // Reset to empty value.
+    meType = CELLTYPE_NONE;
+    mfValue = 0.0;
+}
+
+void ScRefCellValue::assign( ScDocument& rDoc, const ScAddress& rPos )
+{
+    clear();
+
+    meType = rDoc.GetCellType(rPos);
+    switch (meType)
     {
-        case CELLTYPE_NOTE:
-            return CELLTYPE_NONE;
+        case CELLTYPE_STRING:
+            mpString = rDoc.GetStringCell(rPos);
+        break;
         case CELLTYPE_EDIT:
-            return CELLTYPE_STRING;
+            mpEditText = rDoc.GetEditText(rPos);
+        break;
+        case CELLTYPE_VALUE:
+            mfValue = rDoc.GetValue(rPos);
+        break;
+        case CELLTYPE_FORMULA:
+            mpFormula = rDoc.GetFormulaCell(rPos);
+        break;
         default:
-            ;
+            meType = CELLTYPE_NONE; // reset to empty.
     }
-    return eOrig;
 }
 
-OUString getString( const ScCellValue& rVal )
+void ScRefCellValue::assign( ScBaseCell& rCell )
 {
-    if (rVal.meType == CELLTYPE_STRING)
-        return *rVal.mpString;
+    clear();
 
-    if (rVal.meType == CELLTYPE_EDIT)
+    meType = rCell.GetCellType();
+    switch (meType)
     {
-        OUStringBuffer aRet;
-        size_t n = rVal.mpEditText->GetParagraphCount();
-        for (size_t i = 0; i < n; ++i)
-        {
-            if (i > 0)
-                aRet.append('\n');
-            aRet.append(rVal.mpEditText->GetText(i));
-        }
-        return aRet.makeStringAndClear();
+        case CELLTYPE_STRING:
+            mpString = static_cast<const ScStringCell&>(rCell).GetStringPtr();
+        break;
+        case CELLTYPE_EDIT:
+            mpEditText = static_cast<const ScEditCell&>(rCell).GetData();
+        break;
+        case CELLTYPE_VALUE:
+            mfValue = static_cast<const ScValueCell&>(rCell).GetValue();
+        break;
+        case CELLTYPE_FORMULA:
+            mpFormula = static_cast<ScFormulaCell*>(&rCell);
+        break;
+        default:
+            meType = CELLTYPE_NONE; // reset to empty.
     }
-
-    return EMPTY_OUSTRING;
 }
 
-}
-
-bool ScCellValue::equalsWithoutFormat( const ScCellValue& r ) const
+void ScRefCellValue::commit( ScDocument& rDoc, const ScAddress& rPos ) const
 {
-    CellType eType1 = adjustCellType(meType);
-    CellType eType2 = adjustCellType(r.meType);
-    if (eType1 != eType2)
-        return false;
-
     switch (meType)
     {
-        case CELLTYPE_NONE:
-            return true;
-        case CELLTYPE_VALUE:
-            return mfValue == r.mfValue;
         case CELLTYPE_STRING:
         {
-            OUString aStr1 = getString(*this);
-            OUString aStr2 = getString(r);
-            return aStr1 == aStr2;
+            ScSetStringParam aParam;
+            aParam.setTextInput();
+            rDoc.SetString(rPos, *mpString, &aParam);
         }
+        break;
+        case CELLTYPE_EDIT:
+            rDoc.SetEditText(rPos, mpEditText->Clone());
+        break;
+        case CELLTYPE_VALUE:
+            rDoc.SetValue(rPos, mfValue);
+        break;
         case CELLTYPE_FORMULA:
-        {
-            ScTokenArray* pCode1 = mpFormula->GetCode();
-            ScTokenArray* pCode2 = r.mpFormula->GetCode();
+            rDoc.SetFormulaCell(rPos, mpFormula->Clone());
+        break;
+        default:
+            rDoc.SetEmptyCell(rPos);
+    }
+}
 
-            if (pCode1->GetLen() != pCode2->GetLen())
-                return false;
+bool ScRefCellValue::hasString() const
+{
+    return hasStringImpl(meType, mpFormula);
+}
 
-            sal_uInt16 n = pCode1->GetLen();
-            formula::FormulaToken** ppToken1 = pCode1->GetArray();
-            formula::FormulaToken** ppToken2 = pCode2->GetArray();
-            for (sal_uInt16 i = 0; i < n; ++i)
-            {
-                if (!ppToken1[i]->TextEqual(*(ppToken2[i])))
-                    return false;
-            }
+bool ScRefCellValue::hasNumeric() const
+{
+    return hasNumericImpl(meType, mpFormula);
+}
 
-            return true;
-        }
-        default:
-            ;
-    }
-    return false;
+bool ScRefCellValue::isEmpty() const
+{
+    return meType == CELLTYPE_NOTE || meType == CELLTYPE_NONE;
 }
 
-ScCellValue& ScCellValue::operator= ( const ScCellValue& r )
+bool ScRefCellValue::equalsWithoutFormat( const ScRefCellValue& r ) const
 {
-    ScCellValue aTmp(r);
+    return equalsWithoutFormatImpl(*this, r);
+}
+
+ScRefCellValue& ScRefCellValue::operator= ( const ScRefCellValue& r )
+{
+    ScRefCellValue aTmp(r);
     swap(aTmp);
     return *this;
 }
 
-void ScCellValue::swap( ScCellValue& r )
+void ScRefCellValue::swap( ScRefCellValue& r )
 {
     std::swap(meType, r.meType);
 
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 3297b88..3a591cd 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -1758,6 +1758,18 @@ void ScColumn::GetString( SCROW nRow, rtl::OUString& rString ) const
         rString = rtl::OUString();
 }
 
+const OUString* ScColumn::GetStringCell( SCROW nRow ) const
+{
+    SCSIZE  nIndex;
+    if (!Search(nRow, nIndex))
+        return NULL;
+
+    const ScBaseCell* pCell = maItems[nIndex].pCell;
+    if (pCell->GetCellType() != CELLTYPE_STRING)
+        return NULL;
+
+    return static_cast<const ScStringCell*>(pCell)->GetStringPtr();
+}
 
 void ScColumn::GetInputString( SCROW nRow, rtl::OUString& rString ) const
 {
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 6ebbf39..1603d23 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -3053,6 +3053,14 @@ OUString ScDocument::GetString( const ScAddress& rPos ) const
     return aStr;
 }
 
+const OUString* ScDocument::GetStringCell( const ScAddress& rPos ) const
+{
+    if (!TableExists(rPos.Tab()))
+        return NULL;
+
+    return maTabs[rPos.Tab()]->GetStringCell(rPos.Col(), rPos.Row());
+}
+
 void ScDocument::GetInputString( SCCOL nCol, SCROW nRow, SCTAB nTab, OUString& rString )
 {
     if ( ValidTab(nTab) && nTab < static_cast<SCTAB>(maTabs.size()) && maTabs[nTab] )
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index f6d34c2..319226f 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1404,6 +1404,13 @@ void ScTable::GetString( SCCOL nCol, SCROW nRow, rtl::OUString& rString ) const
         rString = rtl::OUString();
 }
 
+const OUString* ScTable::GetStringCell( SCCOL nCol, SCROW nRow ) const
+{
+    if (!ValidColRow(nCol,nRow))
+        return NULL;
+
+    return aCol[nCol].GetStringCell(nRow);
+}
 
 void ScTable::GetInputString( SCCOL nCol, SCROW nRow, rtl::OUString& rString ) const
 {


More information about the Libreoffice-commits mailing list