[Libreoffice-commits] core.git: Branch 'libreoffice-5-1' - 3 commits - formula/source include/formula sc/qa

Eike Rathke erack at redhat.com
Tue Jan 5 05:50:29 PST 2016


 formula/source/core/api/FormulaCompiler.cxx        |   26 +++++++++
 formula/source/core/api/token.cxx                  |   58 +++++++++++++++++++++
 include/formula/tokenarray.hxx                     |   16 +++++
 sc/qa/unit/data/contentCSV/date-time-functions.csv |    2 
 4 files changed, 100 insertions(+), 2 deletions(-)

New commits:
commit 63931f25785e25368ee808f4e0e269f91c99d0e6
Author: Eike Rathke <erack at redhat.com>
Date:   Tue Jan 5 14:16:27 2016 +0100

    tdf#96198 adapt unit test to reality, tdf#50950 follow-up
    
    * old WEEKNUM(date,1) (saved as ISOWEEKNUM(date,1)) now results in
      Err:504 because there is no match to convert to.
    
    * old WEEKNUM(date,2) (saved as ISOWEEKNUM(date,2)) is now converted to
      ISOWEEKNUM(date) and for the sample date 1995-01-01 week 52 is the
      correct result, the test case erroneously tested against week 1
      because the implementation of the now current WEEKNUM(date,2) was
      wrong and even if now right doesn't match the calculation of the ISO
      week.
    
    Change-Id: Ia6940fce1f97639ea9b04f05172a64eb46b65635
    (cherry picked from commit 1efc41a87e2b9491b2a7471b1154a4d586a21c37)

diff --git a/sc/qa/unit/data/contentCSV/date-time-functions.csv b/sc/qa/unit/data/contentCSV/date-time-functions.csv
index 33aa540..a9e3ddd 100644
--- a/sc/qa/unit/data/contentCSV/date-time-functions.csv
+++ b/sc/qa/unit/data/contentCSV/date-time-functions.csv
@@ -21,7 +21,7 @@
 4,3,4
 52
 1,1,52
-1,1
+Err:504,52
 52
 10,11
 52,52
commit a7c0dcf6cf7c25420c0ea804e878861f1ba39206
Author: Michael Meeks <michael.meeks at collabora.com>
Date:   Tue Jan 5 12:44:41 2016 +0000

    formula: add missing algorithm include for std::min.
    
    Change-Id: Ica344a8f1351826e53c109ef49f80e4b022a0364
    (cherry picked from commit 15494f0f99d1cf6f75e8c2996377b242af247bbf)

diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 65211f3..53bc620 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -20,6 +20,7 @@
 
 #include <cstddef>
 #include <cstdio>
+#include <algorithm>
 
 #include <string.h>
 #include <limits.h>
commit 3e5deb8ccfaf0b73fb6cf394822e560dc036a686
Author: Eike Rathke <erack at redhat.com>
Date:   Tue Jan 5 11:54:32 2016 +0100

    tdf#96198 detect old ISO/WEEKNUM usage with two arguments, tdf#50950 follow-up
    
    5.0 and earlier implemented WEEKNUM(date,mode) with mode!=1 such that
    effectively an ISO 8601 week number was calculated. WEEKNUM was wrongly
    saved as ISOWEEKNUM (even with two parameters though it is defined to
    have only one) so that when reading it we can try to detect a literal
    double argument for mode and if it is not 1 remove it to keep
    ISOWEEKNUM(date) instead of calling WEEKNUM(date,mode) which wouldn't
    match.
    
    A further change to 5.0 to accept also only one parameter in
    WEEKNUM(date) and for this default the mode to not 1 for ISO week will
    yield forward compatibility.
    
    Change-Id: I88de7dd809d69b6826a190505d2a1dd3fe79c90b
    (cherry picked from commit 2f79244cb3fcc4cbfd2b818380ea9d62b49aaade)

diff --git a/formula/source/core/api/FormulaCompiler.cxx b/formula/source/core/api/FormulaCompiler.cxx
index c4ca443..457beee 100644
--- a/formula/source/core/api/FormulaCompiler.cxx
+++ b/formula/source/core/api/FormulaCompiler.cxx
@@ -1271,6 +1271,7 @@ void FormulaCompiler::Factor()
                 else
                     SetError( errPairExpected);
                 sal_uInt8 nSepCount = 0;
+                const sal_uInt16 nSepPos = pArr->nIndex - 1;    // separator position, if any
                 if( !bNoParam )
                 {
                     nSepCount++;
@@ -1289,7 +1290,30 @@ void FormulaCompiler::Factor()
                 pFacToken->SetByte( nSepCount );
                 if (nSepCount == 2)
                 {
-                    pFacToken->NewOpCode( ocWeek, FormulaToken::PrivateAccess());
+                    // An old mode!=1 indicates ISO week, remove argument if
+                    // literal double value and keep function. Anything else
+                    // can not be resolved, there exists no "like ISO but week
+                    // starts on Sunday" mode in WEEKNUM and for an expression
+                    // we can't determine, so let ISOWEEKNUM generate an error
+                    // for two arguments in these cases.
+                    if (pc >= 2 && pArr->nIndex == nSepPos + 3 &&
+                            pArr->pCode[nSepPos+1]->GetType() == svDouble &&
+                            pArr->pCode[nSepPos+1]->GetDouble() != 1.0 &&
+                            pArr->RemoveToken( nSepPos, 2) == 2)
+                    {
+                        // Remove the ocPush/svDouble just removed also from
+                        // the compiler local RPN array.
+                        --pCode, --pc;
+                        (*pCode)->DecRef(); // may be dead now
+                        pFacToken->SetByte( nSepCount - 1 );
+                    }
+                    else
+                    {
+                        /* FIXME: introduce (hidden?) compatibility function? */
+#if 0
+                        pFacToken->NewOpCode( ocWeeknumCompat, FormulaToken::PrivateAccess());
+#endif
+                    }
                 }
                 PutCode( pFacToken );
             }
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 339e927..65211f3 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -900,6 +900,63 @@ FormulaToken* FormulaTokenArray::ReplaceToken( sal_uInt16 nOffset, FormulaToken*
     }
 }
 
+sal_uInt16 FormulaTokenArray::RemoveToken( sal_uInt16 nOffset, sal_uInt16 nCount )
+{
+    if (nOffset < nLen)
+    {
+        SAL_WARN_IF( nOffset + nCount > nLen, "formula.core",
+                "FormulaTokenArray::RemoveToken - nOffset " << nOffset << " + nCount " << nCount << " > nLen " << nLen);
+        const sal_uInt16 nStop = ::std::min( static_cast<sal_uInt16>(nOffset + nCount), nLen);
+        nCount = nStop - nOffset;
+        for (sal_uInt16 j = nOffset; j < nStop; ++j)
+        {
+            FormulaToken* p = pCode[j];
+            if (p->GetRef() > 1)
+            {
+                for (sal_uInt16 i=0; i < nRPN; ++i)
+                {
+                    if (pRPN[i] == p)
+                    {
+                        // Shift remaining tokens in pRPN down.
+                        for (sal_uInt16 x=i+1; x < nRPN; ++x)
+                        {
+                            pRPN[x-1] = pRPN[x];
+                        }
+                        --nRPN;
+
+                        p->DecRef();
+                        if (p->GetRef() == 1)
+                            break;  // for
+                    }
+                }
+            }
+            p->DecRef();    // may be dead now
+        }
+
+        // Shift remaining tokens in pCode down.
+        for (sal_uInt16 x = nStop; x < nLen; ++x)
+        {
+            pCode[x-nCount] = pCode[x];
+        }
+        nLen -= nCount;
+
+        if (nIndex >= nOffset)
+        {
+            if (nIndex < nStop)
+                nIndex = nOffset + 1;
+            else
+                nIndex -= nStop - nOffset;
+        }
+
+        return nCount;
+    }
+    else
+    {
+        SAL_WARN("formula.core","FormulaTokenArray::RemoveToken - nOffset " << nOffset << " >= nLen " << nLen);
+        return 0;
+    }
+}
+
 FormulaToken* FormulaTokenArray::Add( FormulaToken* t )
 {
     if( !pCode )
diff --git a/include/formula/tokenarray.hxx b/include/formula/tokenarray.hxx
index 6dcbcfc..292b318 100644
--- a/include/formula/tokenarray.hxx
+++ b/include/formula/tokenarray.hxx
@@ -148,6 +148,22 @@ protected:
      */
     FormulaToken*           ReplaceToken( sal_uInt16 nOffset, FormulaToken*, ReplaceMode eMode );
 
+    /** Remove a sequence of tokens from pCode array, and pRPN array if the
+        tokens are referenced there.
+
+        This' nLen and nRPN are adapted, as is nIndex if it points behind
+        nOffset. If nIndex points into the to be removed range
+        (nOffset < nIndex < nOffset+nCount) it is set to nOffset+1.
+
+        @param  nOffset
+                Start offset into pCode.
+        @param  nCount
+                Count of tokens to remove.
+
+        @return The actual number of tokens removed from pCode array.
+     */
+    sal_uInt16              RemoveToken( sal_uInt16 nOffset, sal_uInt16 nCount );
+
     inline  void            SetCombinedBitsRecalcMode( ScRecalcMode nBits )
                                 { nMode |= (nBits & ~RECALCMODE_EMASK); }
     inline  ScRecalcMode    GetCombinedBitsRecalcMode() const


More information about the Libreoffice-commits mailing list