[Libreoffice-commits] core.git: basic/CppunitTest_basic_macros.mk basic/qa basic/source

Andreas Heinisch (via logerrit) logerrit at kemper.freedesktop.org
Mon Jul 12 18:30:53 UTC 2021


 basic/CppunitTest_basic_macros.mk               |    1 
 basic/qa/basic_coverage/test_string_replace.bas |    9 ++++
 basic/source/runtime/methods.cxx                |   44 +++++++++++++-----------
 3 files changed, 34 insertions(+), 20 deletions(-)

New commits:
commit 7e5c9220ef5d51ac23e618c5c9eeda9cf4339c88
Author:     Andreas Heinisch <andreas.heinisch at yahoo.de>
AuthorDate: Sun Jul 11 21:06:23 2021 +0200
Commit:     Andreas Heinisch <andreas.heinisch at yahoo.de>
CommitDate: Mon Jul 12 20:30:19 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.heinisch at yahoo.de>

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""", """", """)
-    TestUtil.AssertEqual(retStr, ""Straße"""", "replace doesn't crash: " & retStr)
+    TestUtil.AssertEqual(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")
+    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());
 }
 


More information about the Libreoffice-commits mailing list