basic/CppunitTest_basic_macros.mk | 1 basic/qa/basic_coverage/test_string_replace.vb | 9 ++++- basic/source/runtime/methods.cxx | 44 ++++++++++++++----------- 3 files changed, 34 insertions(+), 20 deletions(-)
New commits: commit 15e4d775f7c2edbafca04ade1d293ce71045e9e7 Author: Andreas Heinisch <andreas.heini...@yahoo.de> AuthorDate: Sun Jul 11 21:06:23 2021 +0200 Commit: Xisco Fauli <xiscofa...@libreoffice.org> CommitDate: Tue Jul 13 12:45:08 2021 +0200 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.heini...@yahoo.de> Signed-off-by: Xisco Fauli <xiscofa...@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/118818 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.vb b/basic/qa/basic_coverage/test_string_replace.vb index 8404aaf4961e..21485daa508a 100644 --- a/basic/qa/basic_coverage/test_string_replace.vb +++ b/basic/qa/basic_coverage/test_string_replace.vb @@ -31,7 +31,14 @@ Function verify_stringReplace() As String ' tdf#143081 - Without the fix in place, this test would have crashed here retStr = Replace("""Straße""", """", """) - TestLog_ASSERT retStr, ""Straße"""", "replace doesn't crash: " & retStr + TestLog_ASSERT retStr, ""Straße"", "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") + TestLog_ASSERT retStr, "Straßen", "special unicode character: " & retStr result = result & Chr$(10) & "Tests passed: " & passCount & Chr$(10) & "Tests failed: " & failCount & Chr$(10) verify_stringReplace = result diff --git a/basic/source/runtime/methods.cxx b/basic/source/runtime/methods.cxx index 7cd9b4716141..ab77fc895b6e 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()); } _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits