[Libreoffice-commits] core.git: Branch 'libreoffice-4-4-4' - sc/source

Eike Rathke erack at redhat.com
Wed Jun 10 10:00:09 PDT 2015


 sc/source/core/tool/token.cxx |  277 ++++++++++++++++++++++++------------------
 1 file changed, 163 insertions(+), 114 deletions(-)

New commits:
commit 17c9cfef1a1bf48489fc856d59c6776a47ef0f77
Author: Eike Rathke <erack at redhat.com>
Date:   Mon Jun 8 15:33:51 2015 +0200

    check bounds in RPN tokens, tdf#90694 related and others
    
    Listeners are set up from references in RPN, so check those for bounds
    to catch also references resulting from named expressions, database
    ranges, tables, ... and references in the token code array that are not
    referenced in RPN.
    
    (cherry picked from commit 4baf76ddb39580678cf14019900be78bb9071d7b)
    
    Windows MSVC: cannot specify explicit initializer for arrays
    
    (cherry picked from commit 883ebe0283dc6bdf62f08191dede2a249f777f63)
    
    c42897ba6bb520c931f63e56d0f453ed14cfaa3d
    
    Change-Id: I54770b45818f4c0541a39815278d3271a77b345d
    Reviewed-on: https://gerrit.libreoffice.org/16155
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Reviewed-by: Christian Lohmaier <lohmaier+LibreOffice at googlemail.com>
    Tested-by: Christian Lohmaier <lohmaier+LibreOffice at googlemail.com>

diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 9500a28..1462a8b 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -113,6 +113,34 @@ namespace
         rRef.SetAbsTab(0);
     }
 
+    struct TokenPointerRange
+    {
+        FormulaToken**  mpStart;
+        FormulaToken**  mpStop;
+
+        TokenPointerRange() : mpStart(NULL), mpStop(NULL) {}
+        TokenPointerRange( FormulaToken** p, sal_uInt16 n ) :
+            mpStart(p), mpStop( p + static_cast<size_t>(n)) {}
+    };
+    struct TokenPointers
+    {
+        TokenPointerRange maPointerRange[2];
+
+        TokenPointers( FormulaToken** pCode, sal_uInt16 nLen, FormulaToken** pRPN, sal_uInt16 nRPN )
+        {
+            maPointerRange[0] = TokenPointerRange( pCode, nLen);
+            maPointerRange[1] = TokenPointerRange( pRPN, nRPN);
+        }
+
+        static bool skipToken( size_t i, const FormulaToken* const * pp )
+        {
+            // Handle all tokens in RPN, and code tokens only if they have a
+            // reference count of 1, which means they are not referenced in
+            // RPN.
+            return i == 0 && (*pp)->GetRef() > 1;
+        }
+    };
+
 } // namespace
 
 // Align MemPools on 4k boundaries - 64 bytes (4k is a MUST for OS/2)
@@ -3670,28 +3698,35 @@ void checkBounds(
 void ScTokenArray::CheckRelativeReferenceBounds(
     const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen, std::vector<SCROW>& rBounds ) const
 {
-    FormulaToken** p = pCode;
-    FormulaToken** pEnd = p + static_cast<size_t>(nLen);
-    for (; p != pEnd; ++p)
+    TokenPointers aPtrs( pCode, nLen, pRPN, nRPN);
+    for (size_t j=0; j<2; ++j)
     {
-        switch ((*p)->GetType())
+        FormulaToken** p = aPtrs.maPointerRange[j].mpStart;
+        FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
+        for (; p != pEnd; ++p)
         {
-            case svSingleRef:
-            {
-                formula::FormulaToken* pToken = *p;
-                checkBounds(rCxt, rPos, nGroupLen, *pToken->GetSingleRef(), rBounds);
-            }
-            break;
-            case svDoubleRef:
+            if (TokenPointers::skipToken(j,p))
+                continue;
+
+            switch ((*p)->GetType())
             {
-                formula::FormulaToken* pToken = *p;
-                const ScComplexRefData& rRef = *pToken->GetDoubleRef();
-                checkBounds(rCxt, rPos, nGroupLen, rRef.Ref1, rBounds);
-                checkBounds(rCxt, rPos, nGroupLen, rRef.Ref2, rBounds);
+                case svSingleRef:
+                    {
+                        formula::FormulaToken* pToken = *p;
+                        checkBounds(rCxt, rPos, nGroupLen, *pToken->GetSingleRef(), rBounds);
+                    }
+                    break;
+                case svDoubleRef:
+                    {
+                        formula::FormulaToken* pToken = *p;
+                        const ScComplexRefData& rRef = *pToken->GetDoubleRef();
+                        checkBounds(rCxt, rPos, nGroupLen, rRef.Ref1, rBounds);
+                        checkBounds(rCxt, rPos, nGroupLen, rRef.Ref2, rBounds);
+                    }
+                    break;
+                default:
+                    ;
             }
-            break;
-            default:
-                ;
         }
     }
 }
@@ -3699,29 +3734,36 @@ void ScTokenArray::CheckRelativeReferenceBounds(
 void ScTokenArray::CheckRelativeReferenceBounds(
     const ScAddress& rPos, SCROW nGroupLen, const ScRange& rRange, std::vector<SCROW>& rBounds ) const
 {
-    FormulaToken** p = pCode;
-    FormulaToken** pEnd = p + static_cast<size_t>(nLen);
-    for (; p != pEnd; ++p)
+    TokenPointers aPtrs( pCode, nLen, pRPN, nRPN);
+    for (size_t j=0; j<2; ++j)
     {
-        switch ((*p)->GetType())
+        FormulaToken** p = aPtrs.maPointerRange[j].mpStart;
+        FormulaToken** pEnd = aPtrs.maPointerRange[j].mpStop;
+        for (; p != pEnd; ++p)
         {
-            case svSingleRef:
-            {
-                formula::FormulaToken* pToken = *p;
-                const ScSingleRefData& rRef = *pToken->GetSingleRef();
-                checkBounds(rPos, nGroupLen, rRange, rRef, rBounds);
-            }
-            break;
-            case svDoubleRef:
+            if (TokenPointers::skipToken(j,p))
+                continue;
+
+            switch ((*p)->GetType())
             {
-                formula::FormulaToken* pToken = *p;
-                const ScComplexRefData& rRef = *pToken->GetDoubleRef();
-                checkBounds(rPos, nGroupLen, rRange, rRef.Ref1, rBounds);
-                checkBounds(rPos, nGroupLen, rRange, rRef.Ref2, rBounds);
+                case svSingleRef:
+                    {
+                        formula::FormulaToken* pToken = *p;
+                        const ScSingleRefData& rRef = *pToken->GetSingleRef();
+                        checkBounds(rPos, nGroupLen, rRange, rRef, rBounds);
+                    }
+                    break;
+                case svDoubleRef:
+                    {
+                        formula::FormulaToken* pToken = *p;
+                        const ScComplexRefData& rRef = *pToken->GetDoubleRef();
+                        checkBounds(rPos, nGroupLen, rRange, rRef.Ref1, rBounds);
+                        checkBounds(rPos, nGroupLen, rRange, rRef.Ref2, rBounds);
+                    }
+                    break;
+                default:
+                    ;
             }
-            break;
-            default:
-                ;
         }
     }
 }
@@ -3730,91 +3772,98 @@ void ScTokenArray::CheckExpandReferenceBounds(
     const sc::RefUpdateContext& rCxt, const ScAddress& rPos, SCROW nGroupLen, std::vector<SCROW>& rBounds ) const
 {
     const SCROW nInsRow = rCxt.maRange.aStart.Row();
-    const FormulaToken* const * p = pCode;
-    const FormulaToken* const * pEnd = p + static_cast<size_t>(nLen);
-    for (; p != pEnd; ++p)
+    TokenPointers aPtrs( pCode, nLen, pRPN, nRPN);
+    for (size_t j=0; j<2; ++j)
     {
-        switch ((*p)->GetType())
+        const FormulaToken* const * p = aPtrs.maPointerRange[j].mpStart;
+        const FormulaToken* const * pEnd = aPtrs.maPointerRange[j].mpStop;
+        for (; p != pEnd; ++p)
         {
-            case svDoubleRef:
-            {
-                const formula::FormulaToken* pToken = *p;
-                const ScComplexRefData& rRef = *pToken->GetDoubleRef();
-                bool bStartRowRelative = rRef.Ref1.IsRowRel();
-                bool bEndRowRelative = rRef.Ref2.IsRowRel();
-
-                // For absolute references nothing needs to be done, they stay
-                // the same for all and if to be expanded the group will be
-                // adjusted later.
-                if (!bStartRowRelative && !bEndRowRelative)
-                    break;  // switch
-
-                ScRange aAbsStart(rRef.toAbs(rPos));
-                ScAddress aPos(rPos);
-                aPos.IncRow(nGroupLen);
-                ScRange aAbsEnd(rRef.toAbs(aPos));
-                // References must be at least two rows to be expandable.
-                if ((aAbsStart.aEnd.Row() - aAbsStart.aStart.Row() < 1) &&
-                        (aAbsEnd.aEnd.Row() - aAbsEnd.aStart.Row() < 1))
-                    break;  // switch
-
-                // Only need to process if an edge may be touching the
-                // insertion row anywhere within the run of the group.
-                if (!((aAbsStart.aStart.Row() <= nInsRow && nInsRow <= aAbsEnd.aStart.Row()) ||
-                            (aAbsStart.aEnd.Row() <= nInsRow && nInsRow <= aAbsEnd.aEnd.Row())))
-                    break;  // switch
-
-                SCROW nStartRow = aAbsStart.aStart.Row();
-                SCROW nEndRow = aAbsStart.aEnd.Row();
-                // Position on first relevant range.
-                SCROW nOffset = 0;
-                if (nEndRow + 1 < nInsRow)
-                {
-                    if (bEndRowRelative)
-                    {
-                        nOffset = nInsRow - nEndRow - 1;
-                        nEndRow += nOffset;
-                        if (bStartRowRelative)
-                            nStartRow += nOffset;
-                    }
-                    else    // bStartRowRelative==true
-                    {
-                        nOffset = nInsRow - nStartRow;
-                        nStartRow += nOffset;
-                        // Start is overtaking End, swap.
-                        bStartRowRelative = false;
-                        bEndRowRelative = true;
-                    }
-                }
-                for (SCROW i = nOffset; i < nGroupLen; ++i)
-                {
-                    bool bSplit = (nStartRow == nInsRow || nEndRow + 1 == nInsRow);
-                    if (bSplit)
-                        rBounds.push_back( rPos.Row() + i);
+            if (TokenPointers::skipToken(j,p))
+                continue;
 
-                    if (bEndRowRelative)
-                        ++nEndRow;
-                    if (bStartRowRelative)
+            switch ((*p)->GetType())
+            {
+                case svDoubleRef:
                     {
-                        ++nStartRow;
-                        if (!bEndRowRelative && nStartRow == nEndRow)
+                        const formula::FormulaToken* pToken = *p;
+                        const ScComplexRefData& rRef = *pToken->GetDoubleRef();
+                        bool bStartRowRelative = rRef.Ref1.IsRowRel();
+                        bool bEndRowRelative = rRef.Ref2.IsRowRel();
+
+                        // For absolute references nothing needs to be done, they stay
+                        // the same for all and if to be expanded the group will be
+                        // adjusted later.
+                        if (!bStartRowRelative && !bEndRowRelative)
+                            break;  // switch
+
+                        ScRange aAbsStart(rRef.toAbs(rPos));
+                        ScAddress aPos(rPos);
+                        aPos.IncRow(nGroupLen);
+                        ScRange aAbsEnd(rRef.toAbs(aPos));
+                        // References must be at least two rows to be expandable.
+                        if ((aAbsStart.aEnd.Row() - aAbsStart.aStart.Row() < 1) &&
+                                (aAbsEnd.aEnd.Row() - aAbsEnd.aStart.Row() < 1))
+                            break;  // switch
+
+                        // Only need to process if an edge may be touching the
+                        // insertion row anywhere within the run of the group.
+                        if (!((aAbsStart.aStart.Row() <= nInsRow && nInsRow <= aAbsEnd.aStart.Row()) ||
+                                    (aAbsStart.aEnd.Row() <= nInsRow && nInsRow <= aAbsEnd.aEnd.Row())))
+                            break;  // switch
+
+                        SCROW nStartRow = aAbsStart.aStart.Row();
+                        SCROW nEndRow = aAbsStart.aEnd.Row();
+                        // Position on first relevant range.
+                        SCROW nOffset = 0;
+                        if (nEndRow + 1 < nInsRow)
                         {
-                            // Start is overtaking End, swap.
-                            bStartRowRelative = false;
-                            bEndRowRelative = true;
+                            if (bEndRowRelative)
+                            {
+                                nOffset = nInsRow - nEndRow - 1;
+                                nEndRow += nOffset;
+                                if (bStartRowRelative)
+                                    nStartRow += nOffset;
+                            }
+                            else    // bStartRowRelative==true
+                            {
+                                nOffset = nInsRow - nStartRow;
+                                nStartRow += nOffset;
+                                // Start is overtaking End, swap.
+                                bStartRowRelative = false;
+                                bEndRowRelative = true;
+                            }
+                        }
+                        for (SCROW i = nOffset; i < nGroupLen; ++i)
+                        {
+                            bool bSplit = (nStartRow == nInsRow || nEndRow + 1 == nInsRow);
+                            if (bSplit)
+                                rBounds.push_back( rPos.Row() + i);
+
+                            if (bEndRowRelative)
+                                ++nEndRow;
+                            if (bStartRowRelative)
+                            {
+                                ++nStartRow;
+                                if (!bEndRowRelative && nStartRow == nEndRow)
+                                {
+                                    // Start is overtaking End, swap.
+                                    bStartRowRelative = false;
+                                    bEndRowRelative = true;
+                                }
+                            }
+                            if (nInsRow < nStartRow || (!bStartRowRelative && nInsRow <= nEndRow))
+                            {
+                                if (bSplit && (++i < nGroupLen))
+                                    rBounds.push_back( rPos.Row() + i);
+                                break;  // for, out of range now
+                            }
                         }
                     }
-                    if (nInsRow < nStartRow || (!bStartRowRelative && nInsRow <= nEndRow))
-                    {
-                        if (bSplit && (++i < nGroupLen))
-                            rBounds.push_back( rPos.Row() + i);
-                        break;  // for, out of range now
-                    }
-                }
+                    break;
+                default:
+                    ;
             }
-            break;
-            default:
-                ;
         }
     }
 }


More information about the Libreoffice-commits mailing list