[Libreoffice-commits] core.git: Branch 'private/kohei/calc-shared-string' - sc/inc sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Tue Oct 15 17:41:19 PDT 2013


 sc/inc/formulacell.hxx                |    1 
 sc/inc/formularesult.hxx              |   21 ++++++++
 sc/source/core/data/column2.cxx       |   85 +++++++++++++++++++++++-----------
 sc/source/core/data/formulacell.cxx   |   11 ++++
 sc/source/core/tool/formularesult.cxx |   47 ++++++++++++++++++
 5 files changed, 138 insertions(+), 27 deletions(-)

New commits:
commit 87fe06a25dd22a3244f9741a079ce0e734acb6c8
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Tue Oct 15 20:42:00 2013 -0400

    Re-do fetching of vector ref array to support number / string mixture.
    
    For now it only works when the range starts with string cell.  With this,
    the test now passes.
    
    Change-Id: I6f79415ce11233648cdb20c8075f500b8c3d2f76

diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index ea80b15..9d27558 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -253,6 +253,7 @@ public:
     sal_uInt16      GetRawError();  // don't interpret, just return code or result error
     bool GetErrorOrValue( sal_uInt16& rErr, double& rVal );
     bool GetErrorOrString( sal_uInt16& rErr, svl::SharedString& rStr );
+    sc::FormulaResultValue GetResult();
     sal_uInt8       GetMatrixFlag() const;
     ScTokenArray* GetCode();
     const ScTokenArray* GetCode() const;
diff --git a/sc/inc/formularesult.hxx b/sc/inc/formularesult.hxx
index 8a7b365..3708c8a 100644
--- a/sc/inc/formularesult.hxx
+++ b/sc/inc/formularesult.hxx
@@ -23,6 +23,26 @@
 #include "token.hxx"
 #include "scdllapi.h"
 
+namespace sc {
+
+struct FormulaResultValue
+{
+    enum Type { Invalid, Value, String, Error };
+
+    Type meType;
+
+    double mfValue;
+    svl::SharedString maString;
+    sal_uInt16 mnError;
+
+    FormulaResultValue();
+    FormulaResultValue( double fValue );
+    FormulaResultValue(const svl::SharedString& rStr );
+    FormulaResultValue( sal_uInt16 nErr );
+};
+
+}
+
 /** Store a variable formula cell result, balancing between runtime performance
     and memory consumption. */
 class ScFormulaResult
@@ -136,6 +156,7 @@ public:
 
     bool GetErrorOrDouble( sal_uInt16& rErr, double& rVal ) const;
     bool GetErrorOrString( sal_uInt16& rErr, svl::SharedString& rStr ) const;
+    sc::FormulaResultValue GetResult() const;
 
     /** Get error code if set or GetCellResultType() is formula::svError or svUnknown,
         else 0. */
diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx
index a0ee046..8fbfd1b 100644
--- a/sc/source/core/data/column2.cxx
+++ b/sc/source/core/data/column2.cxx
@@ -2178,12 +2178,16 @@ bool appendDouble(
     return false;
 }
 
-bool appendStrings(
-    ScDocument* pDoc, sc::FormulaGroupContext::StrArrayType& rArray,
-    size_t nLen, sc::CellStoreType::iterator it, const sc::CellStoreType::iterator& itEnd)
+formula::VectorRefArray appendBlocks(
+    ScDocument* pDoc, sc::FormulaGroupContext& rCxt, size_t nPos,
+    size_t nLenRequested, sc::CellStoreType::iterator it, const sc::CellStoreType::iterator& itEnd )
 {
-    size_t nLenRemain = nLen;
+    sc::FormulaGroupContext::StrArrayType& rStrArray = rCxt.maStrArrays.back();
+    sc::FormulaGroupContext::NumArrayType* pNumArray = NULL;
     svl::SharedStringPool& rPool = pDoc->GetSharedStringPool();
+    size_t nLenRemain = nLenRequested - nPos;
+    double fNan;
+    rtl::math::setNan(&fNan);
 
     for (; it != itEnd; ++it)
     {
@@ -2194,8 +2198,8 @@ bool appendStrings(
                 sc::string_block::iterator itData, itDataEnd;
                 getBlockIterators<sc::string_block>(it, nLenRemain, itData, itDataEnd);
 
-                for (; itData != itDataEnd; ++itData)
-                    rArray.push_back(itData->getDataIgnoreCase());
+                for (; itData != itDataEnd; ++itData, ++nPos)
+                    rStrArray[nPos] = itData->getDataIgnoreCase();
             }
             break;
             case sc::element_type_edittext:
@@ -2203,10 +2207,10 @@ bool appendStrings(
                 sc::edittext_block::iterator itData, itDataEnd;
                 getBlockIterators<sc::edittext_block>(it, nLenRemain, itData, itDataEnd);
 
-                for (; itData != itDataEnd; ++itData)
+                for (; itData != itDataEnd; ++itData, ++nPos)
                 {
                     OUString aStr = ScEditUtil::GetString(**itData, pDoc);
-                    rArray.push_back(rPool.intern(aStr).getDataIgnoreCase());
+                    rStrArray[nPos] = rPool.intern(aStr).getDataIgnoreCase();
                 }
             }
             break;
@@ -2215,51 +2219,81 @@ bool appendStrings(
                 sc::formula_block::iterator itData, itDataEnd;
                 getBlockIterators<sc::formula_block>(it, nLenRemain, itData, itDataEnd);
 
-                sal_uInt16 nErr;
-                svl::SharedString aStr;
-                for (; itData != itDataEnd; ++itData)
+                for (; itData != itDataEnd; ++itData, ++nPos)
                 {
                     ScFormulaCell& rFC = **itData;
-                    if (!rFC.GetErrorOrString(nErr, aStr) || nErr)
+                    sc::FormulaResultValue aRes = rFC.GetResult();
+                    if (aRes.meType == sc::FormulaResultValue::Invalid || aRes.mnError)
                     {
-                        if (nErr == ScErrorCodes::errCircularReference)
+                        if (aRes.mnError == ScErrorCodes::errCircularReference)
                         {
                             // This cell needs to be recalculated on next visit.
                             rFC.SetErrCode(0);
                             rFC.SetDirtyVar();
                         }
-                        return false;
+                        return formula::VectorRefArray();
                     }
 
-                    rArray.push_back(aStr.getDataIgnoreCase());
+                    if (aRes.meType == sc::FormulaResultValue::String)
+                        rStrArray[nPos] = aRes.maString.getDataIgnoreCase();
+                    else
+                    {
+                        if (!pNumArray)
+                        {
+                            rCxt.maNumArrays.push_back(
+                                new sc::FormulaGroupContext::NumArrayType(nLenRequested, fNan));
+                            pNumArray = &rCxt.maNumArrays.back();
+                        }
+
+                        (*pNumArray)[nPos] = aRes.mfValue;
+                    }
                 }
             }
             break;
             case sc::element_type_empty:
             {
-                // Fill it with NULL pointers.
-                if (nLenRemain >= it->size)
+                if (nLenRemain > it->size)
                 {
-                    rArray.resize(rArray.size() + it->size, NULL);
+                    nPos += it->size;
                     nLenRemain -= it->size;
                 }
                 else
                 {
-                    rArray.resize(rArray.size() + nLenRemain, NULL);
+                    nPos = nLenRequested;
                     nLenRemain = 0;
                 }
             }
             break;
             case sc::element_type_numeric:
+            {
+                sc::numeric_block::iterator itData, itDataEnd;
+                getBlockIterators<sc::numeric_block>(it, nLenRemain, itData, itDataEnd);
+
+                if (!pNumArray)
+                {
+                    rCxt.maNumArrays.push_back(
+                        new sc::FormulaGroupContext::NumArrayType(nLenRequested, fNan));
+                    pNumArray = &rCxt.maNumArrays.back();
+                }
+
+                for (; itData != itDataEnd; ++itData, ++nPos)
+                    (*pNumArray)[nPos] = *itData;
+            }
+            break;
             default:
-                return false;
+                return formula::VectorRefArray();
         }
 
         if (!nLenRemain)
-            return true;
+        {
+            if (pNumArray)
+                return formula::VectorRefArray(&(*pNumArray)[0], &rStrArray[0]);
+            else
+                return formula::VectorRefArray(&rStrArray[0]);
+        }
     }
 
-    return false;
+    return formula::VectorRefArray();
 }
 
 void copyFirstStringBlock(
@@ -2412,14 +2446,11 @@ formula::VectorRefArray ScColumn::FetchVectorRefArray( sc::FormulaGroupContext&
             }
 
             copyFirstStringBlock(*pDocument, rCxt, nLen, aPos);
-            sc::FormulaGroupContext::StrArrayType& rArray = rCxt.maStrArrays.back();
+            rCxt.maStrArrays.back().resize(nLenRequested, NULL); // allocate array to requested length.
 
             // Fill the remaining array with values from the following blocks.
             ++aPos.first;
-            if (!appendStrings(pDocument, rArray, nLenRequested - nLen, aPos.first, maCells.end()))
-                return formula::VectorRefArray();
-
-            return formula::VectorRefArray(&rArray[0]);
+            return appendBlocks(pDocument, rCxt, nLen, nLenRequested, aPos.first, maCells.end());
         }
         break;
         case sc::element_type_empty:
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index 9d32104..4d0284b 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -2094,6 +2094,17 @@ bool ScFormulaCell::GetErrorOrString( sal_uInt16& rErr, svl::SharedString& rStr
     return aResult.GetErrorOrString(rErr, rStr);
 }
 
+sc::FormulaResultValue ScFormulaCell::GetResult()
+{
+    MaybeInterpret();
+
+    sal_uInt16 nErr = pCode->GetCodeError();
+    if (nErr)
+        return sc::FormulaResultValue(nErr);
+
+    return aResult.GetResult();
+}
+
 bool ScFormulaCell::HasOneReference( ScRange& r ) const
 {
     pCode->Reset();
diff --git a/sc/source/core/tool/formularesult.cxx b/sc/source/core/tool/formularesult.cxx
index 5015a85..35d5818 100644
--- a/sc/source/core/tool/formularesult.cxx
+++ b/sc/source/core/tool/formularesult.cxx
@@ -10,6 +10,15 @@
 #include "formularesult.hxx"
 #include "scmatrix.hxx"
 
+namespace sc {
+
+FormulaResultValue::FormulaResultValue() : meType(Invalid), mfValue(0.0), mnError(0) {}
+FormulaResultValue::FormulaResultValue( double fValue ) : meType(Value), mfValue(fValue), mnError(0) {}
+FormulaResultValue::FormulaResultValue( const svl::SharedString& rStr ) : meType(String), mfValue(0.0), maString(rStr), mnError(0) {}
+FormulaResultValue::FormulaResultValue( sal_uInt16 nErr ) : meType(Error), mfValue(0.0), mnError(nErr) {}
+
+}
+
 ScFormulaResult::ScFormulaResult() :
     mpToken(NULL), mnError(0), mbToken(true),
     mbEmpty(false), mbEmptyDisplayedAsString(false),
@@ -372,6 +381,44 @@ bool ScFormulaResult::GetErrorOrString( sal_uInt16& rErr, svl::SharedString& rSt
     return true;
 }
 
+sc::FormulaResultValue ScFormulaResult::GetResult() const
+{
+    if (mnError)
+        return sc::FormulaResultValue(mnError);
+
+    formula::StackVar sv = GetCellResultType();
+    sal_uInt16 nErr = 0;
+    if (sv == formula::svError)
+    {
+        if (GetType() == formula::svMatrixCell)
+        {
+            // don't need to test for mpToken here, GetType() already did it
+            nErr = static_cast<const ScMatrixCellResultToken*>(mpToken)->
+                GetUpperLeftToken()->GetError();
+        }
+        else if (mpToken)
+        {
+            nErr = mpToken->GetError();
+        }
+    }
+
+    if (nErr)
+        return sc::FormulaResultValue(nErr);
+
+    if (isValue(sv))
+        return sc::FormulaResultValue(GetDouble());
+
+    if (!mbToken)
+        // String result type needs token.
+        return sc::FormulaResultValue();
+
+    if (isString(sv))
+        return sc::FormulaResultValue(GetString());
+
+    // Invalid
+    return sc::FormulaResultValue();
+}
+
 sal_uInt16 ScFormulaResult::GetResultError() const
 {
     if (mnError)


More information about the Libreoffice-commits mailing list