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

Eike Rathke erack at redhat.com
Mon Jun 8 07:01:06 PDT 2015


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

New commits:
commit 81a4cd506929416de278a94279c4774ad5a7ac95
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.
    
    Change-Id: I54770b45818f4c0541a39815278d3271a77b345d
    (cherry picked from commit 4baf76ddb39580678cf14019900be78bb9071d7b)

diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 53fc62b..3df3717 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -114,6 +114,30 @@ namespace
         rRef.SetAbsTab(0);
     }
 
+    struct TokenPointerRange
+    {
+        FormulaToken**  mpStart;
+        FormulaToken**  mpStop;
+
+        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{ TokenPointerRange( pCode, nLen), 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)
@@ -3850,28 +3874,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:
-                ;
         }
     }
 }
@@ -3879,29 +3910,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:
-                ;
         }
     }
 }
@@ -3910,91 +3948,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