summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2015-06-08 15:33:51 +0200
committerEike Rathke <erack@redhat.com>2015-06-08 15:58:49 +0200
commit81a4cd506929416de278a94279c4774ad5a7ac95 (patch)
tree6c73cd8ddabbe6ecba299a45787728cb8d03c01f
parent4d2bbb45df5882386eaa01447e48022f8ec68079 (diff)
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)
-rw-r--r--sc/source/core/tool/token.cxx273
1 files changed, 159 insertions, 114 deletions
diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx
index 53fc62b9f391..3df3717377d5 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:
- ;
}
}
}