summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Kaganski <mike.kaganski@collabora.com>2022-02-01 07:48:48 +0100
committerXisco Fauli <xiscofauli@libreoffice.org>2022-02-10 16:36:13 +0100
commit7cddf9609df427c0a87d759cfeab2a6a34ef211b (patch)
treebd8c3a8df5a43d19e359310d2ad00505a05726be
parentea02ca06de604370061a59dd3084f7cfacccbe39 (diff)
tdf#147109: Optimize ScInterpreter::ScSubstitute
Avoid multiple reallocations, making it freeze for e.g. =SUBSTITUTE(REPT(" ";1000000);" ";"") Change-Id: I269c0b06a0b3cbf9369cc47f33c2eea026b12903 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/129252 Tested-by: Mike Kaganski <mike.kaganski@collabora.com> Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com> (cherry picked from commit 0b397d8ef0a2615e8e6202804ca2f6cb58436fa5) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/129262 Tested-by: Jenkins Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
-rw-r--r--sc/source/core/tool/interpr1.cxx39
1 files changed, 17 insertions, 22 deletions
diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx
index 44672395903f..131f76cca889 100644
--- a/sc/source/core/tool/interpr1.cxx
+++ b/sc/source/core/tool/interpr1.cxx
@@ -9696,32 +9696,27 @@ void ScInterpreter::ScSubstitute()
OUString sStr = GetString().getString();
sal_Int32 nPos = 0;
sal_Int32 nCount = 0;
- sal_Int32 nNewLen = sNewStr.getLength();
- sal_Int32 nOldLen = sOldStr.getLength();
- while( true )
+ std::optional<OUStringBuffer> oResult;
+ for (sal_Int32 nEnd = sStr.indexOf(sOldStr); nEnd >= 0; nEnd = sStr.indexOf(sOldStr, nEnd))
{
- nPos = sStr.indexOf( sOldStr, nPos );
- if (nPos != -1)
+ if (nCnt == 0 || ++nCount == nCnt) // Found a replacement cite
{
- nCount++;
- if( !nCnt || nCount == nCnt )
- {
- sStr = sStr.replaceAt(nPos,nOldLen, u"");
- if ( CheckStringResultLen( sStr, sNewStr ) )
- {
- sStr = sStr.replaceAt(nPos, 0, sNewStr);
- nPos = sal::static_int_cast<sal_Int32>( nPos + nNewLen );
- }
- else
- break;
- }
- else
- nPos++;
+ if (!oResult) // Only allocate buffer when needed
+ oResult.emplace(sStr.getLength() + sNewStr.getLength() - sOldStr.getLength());
+
+ oResult->append(sStr.subView(nPos, nEnd - nPos)); // Copy leading unchanged text
+ if (!CheckStringResultLen(*oResult, sNewStr))
+ return PushError(GetError());
+ oResult->append(sNewStr); // Copy the replacement
+ nPos = nEnd + sOldStr.getLength();
+ if (nCnt > 0) // Found the single replacement site - end the loop
+ break;
}
- else
- break;
+ nEnd += sOldStr.getLength();
}
- PushString( sStr );
+ if (oResult) // If there were prior replacements, copy the rest, otherwise use original
+ oResult->append(sStr.subView(nPos, sStr.getLength() - nPos));
+ PushString(oResult ? oResult->makeStringAndClear() : sStr);
}
void ScInterpreter::ScRept()