summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Heinisch <andreas.heinisch@yahoo.de>2021-07-11 21:06:23 +0200
committerAndreas Heinisch <andreas.heinisch@yahoo.de>2021-07-12 20:30:19 +0200
commit7e5c9220ef5d51ac23e618c5c9eeda9cf4339c88 (patch)
treee6ed4ef122e536e25d60f77c947842c2334308dd
parentcffd97193f7468f770368559d5a5c58bd0bb2327 (diff)
tdf#142487 - use utl::TextSearch in order to implement the replace algorithm
In the old algorithm, some special unicode characters lead to a malfunction of basic's replace function. For instance, replacing a German ß to uppercase in the insensitive case will lead to SS, breaking the replace positions. Change-Id: I4e6f6e5fba3d560b8cfd0786fa2439ed5174a928 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118760 Tested-by: Jenkins Reviewed-by: Andreas Heinisch <andreas.heinisch@yahoo.de>
-rw-r--r--basic/CppunitTest_basic_macros.mk1
-rw-r--r--basic/qa/basic_coverage/test_string_replace.bas9
-rw-r--r--basic/source/runtime/methods.cxx44
3 files changed, 34 insertions, 20 deletions
diff --git a/basic/CppunitTest_basic_macros.mk b/basic/CppunitTest_basic_macros.mk
index c2c1eb5b7a04..c70bfff42c68 100644
--- a/basic/CppunitTest_basic_macros.mk
+++ b/basic/CppunitTest_basic_macros.mk
@@ -61,6 +61,7 @@ $(eval $(call gb_CppunitTest_use_vcl,basic_macros))
$(eval $(call gb_CppunitTest_use_components,basic_macros,\
configmgr/source/configmgr \
+ i18npool/source/search/i18nsearch \
i18npool/util/i18npool \
ucb/source/core/ucb1 \
ucb/source/ucp/file/ucpfile1 \
diff --git a/basic/qa/basic_coverage/test_string_replace.bas b/basic/qa/basic_coverage/test_string_replace.bas
index 4dfac668109d..d68f36fbb662 100644
--- a/basic/qa/basic_coverage/test_string_replace.bas
+++ b/basic/qa/basic_coverage/test_string_replace.bas
@@ -24,7 +24,14 @@ Sub verify_stringReplace()
' tdf#143081 - Without the fix in place, this test would have crashed here
retStr = Replace("""Straße""", """", "&quot;")
- TestUtil.AssertEqual(retStr, "&quot;Straße""&quot;", "replace doesn't crash: " & retStr)
+ TestUtil.AssertEqual(retStr, "&quot;Straße&quot;", "replace doesn't crash: " & retStr)
+
+ ' tdf#142487 - replace of special unicode characters.
+ ' Without the fix in place, this test would have failed with:
+ ' - Expected: Straßen
+ ' - Actual : Straßeen
+ retStr = Replace("Straße", "e", "en")
+ TestUtil.AssertEqual(retStr, "Straßen", "special unicode character: " & retStr)
Exit Sub
errorHandler:
diff --git a/basic/source/runtime/methods.cxx b/basic/source/runtime/methods.cxx
index 41f0d38ec1b0..e745fa2fd1c6 100644
--- a/basic/source/runtime/methods.cxx
+++ b/basic/source/runtime/methods.cxx
@@ -67,6 +67,14 @@
#include <string_view>
#include <o3tl/char16_t2wchar_t.hxx>
+// include search util
+#include <com/sun/star/util/SearchFlags.hpp>
+#include <com/sun/star/util/SearchAlgorithms2.hpp>
+#include <i18nutil/searchopt.hxx>
+#include <unotools/textsearch.hxx>
+
+
+
using namespace comphelper;
using namespace osl;
using namespace com::sun::star;
@@ -1283,34 +1291,32 @@ void SbRtl_Replace(StarBASIC *, SbxArray & rPar, bool)
}
const OUString aExpStr = rPar.Get(1)->GetOUString();
- OUString aFindStr = rPar.Get(2)->GetOUString();
+ const OUString aFindStr = rPar.Get(2)->GetOUString();
const OUString aReplaceStr = rPar.Get(3)->GetOUString();
+ const sal_Int32 nExpStrLen = aExpStr.getLength();
+ const sal_Int32 nFindStrLen = aFindStr.getLength();
- OUString aSrcStr(aExpStr);
+ // tdf#142487 - use utl::TextSearch in order to implement the replace algorithm
+ i18nutil::SearchOptions2 aSearchOptions;
+ aSearchOptions.searchString = aFindStr;
+ aSearchOptions.AlgorithmType2 = util::SearchAlgorithms2::ABSOLUTE;
if (bCaseInsensitive)
- {
- // tdf#132389 - case-insensitive operation for non-ASCII characters
- const css::lang::Locale& rLocale = Application::GetSettings().GetLanguageTag().getLocale();
- css::uno::Reference<i18n::XCharacterClassification> xCharClass
- = vcl::unohelper::CreateCharacterClassification();
- aSrcStr = xCharClass->toUpper(aSrcStr, 0, aSrcStr.getLength(), rLocale);
- aFindStr = xCharClass->toUpper(aFindStr, 0, aFindStr.getLength(), rLocale);
- }
- const sal_Int32 nSrcStrLen = aSrcStr.getLength();
- const sal_Int32 nFindStrLen = aFindStr.getLength();
+ aSearchOptions.transliterateFlags |= TransliterationFlags::IGNORE_CASE;
+ utl::TextSearch textSearch(aSearchOptions);
// Note: the result starts from lStartPos, removing everything to the left. See i#94895.
- sal_Int32 nPrevPos = std::min(lStartPos - 1, nSrcStrLen);
- OUStringBuffer sResult(nSrcStrLen - nPrevPos);
+ sal_Int32 nPrevPos = std::min(lStartPos - 1, nExpStrLen);
+ OUStringBuffer sResult(nExpStrLen - nPrevPos);
sal_Int32 nCounts = 0;
while (lCount == -1 || lCount > nCounts)
{
- sal_Int32 nPos = aSrcStr.indexOf(aFindStr, nPrevPos);
- if (nPos >= 0)
+ sal_Int32 nStartPos = nPrevPos;
+ sal_Int32 aEndPos = aExpStr.getLength();
+ if (textSearch.SearchForward(aExpStr, &nStartPos, &aEndPos))
{
- sResult.append(aExpStr.getStr() + nPrevPos, nPos - nPrevPos);
+ sResult.append(aExpStr.getStr() + nPrevPos, nStartPos - nPrevPos);
sResult.append(aReplaceStr);
- nPrevPos = nPos + nFindStrLen;
+ nPrevPos = nStartPos + nFindStrLen;
nCounts++;
}
else
@@ -1318,7 +1324,7 @@ void SbRtl_Replace(StarBASIC *, SbxArray & rPar, bool)
break;
}
}
- sResult.append(aExpStr.getStr() + nPrevPos, nSrcStrLen - nPrevPos);
+ sResult.append(aExpStr.getStr() + nPrevPos, nExpStrLen - nPrevPos);
rPar.Get(0)->PutString(sResult.makeStringAndClear());
}