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

Mike Kaganski (via logerrit) logerrit at kemper.freedesktop.org
Sat Apr 25 06:01:19 UTC 2020


 basic/source/runtime/methods.cxx |  127 +++++++++++++++++++--------------------
 1 file changed, 65 insertions(+), 62 deletions(-)

New commits:
commit dd06a8a2caf93707fbf29c7264cf41f8ec9d4c6d
Author:     Mike Kaganski <mike.kaganski at collabora.com>
AuthorDate: Sat Apr 25 00:49:07 2020 +0300
Commit:     Mike Kaganski <mike.kaganski at collabora.com>
CommitDate: Sat Apr 25 08:00:41 2020 +0200

    tdf#132388: reimplement SbRtl_Replace
    
    It should not convert strings to uppercase each loop; it should use
    OUStringBuffer to avoid extra allocations.
    
    This reduces tick count for the code in the bug from ~6000 to ~30.
    
    Change-Id: I89ea062fc6d012464bb461b6a8ef321f8cc62fe6
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/92884
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kaganski at collabora.com>

diff --git a/basic/source/runtime/methods.cxx b/basic/source/runtime/methods.cxx
index df177d334166..75b7b9177b42 100644
--- a/basic/source/runtime/methods.cxx
+++ b/basic/source/runtime/methods.cxx
@@ -1219,88 +1219,91 @@ void SbRtl_Replace(StarBASIC *, SbxArray & rPar, bool)
     if ( nArgCount < 3 || nArgCount > 6 )
     {
         StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
+        return;
     }
-    else
-    {
-        OUString aExpStr = rPar.Get32(1)->GetOUString();
-        OUString aFindStr = rPar.Get32(2)->GetOUString();
-        OUString aReplaceStr = rPar.Get32(3)->GetOUString();
 
-        sal_Int32 lStartPos = 1;
-        if ( nArgCount >= 4 )
+    sal_Int32 lStartPos = 1;
+    if (nArgCount >= 4)
+    {
+        if (rPar.Get32(4)->GetType() != SbxEMPTY)
         {
-            if( rPar.Get32(4)->GetType() != SbxEMPTY )
-            {
-                lStartPos = rPar.Get32(4)->GetLong();
-            }
-            if( lStartPos < 1)
-            {
-                StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
-                lStartPos = 1;
-            }
+            lStartPos = rPar.Get32(4)->GetLong();
         }
+        if (lStartPos < 1)
+        {
+            StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
+            return;
+        }
+    }
 
-        sal_Int32 lCount = -1;
-        if( nArgCount >=5 )
+    sal_Int32 lCount = -1;
+    if (nArgCount >= 5)
+    {
+        if (rPar.Get32(5)->GetType() != SbxEMPTY)
         {
-            if( rPar.Get32(5)->GetType() != SbxEMPTY )
-            {
-                lCount = rPar.Get32(5)->GetLong();
-            }
-            if( lCount < -1)
-            {
-                StarBASIC::Error( ERRCODE_BASIC_BAD_ARGUMENT );
-                lCount = -1;
-            }
+            lCount = rPar.Get32(5)->GetLong();
         }
+        if (lCount < -1)
+        {
+            StarBASIC::Error(ERRCODE_BASIC_BAD_ARGUMENT);
+            return;
+        }
+    }
 
+    bool bCaseInsensitive;
+    if (nArgCount == 6)
+    {
+        bCaseInsensitive = rPar.Get32(6)->GetInteger();
+    }
+    else
+    {
         SbiInstance* pInst = GetSbData()->pInst;
-        bool bTextMode;
-        bool bCompatibility = ( pInst && pInst->IsCompatibility() );
-        if( bCompatibility )
+        if (pInst && pInst->IsCompatibility())
         {
             SbiRuntime* pRT = pInst->pRun;
-            bTextMode = pRT && pRT->IsImageFlag( SbiImageFlags::COMPARETEXT );
+            bCaseInsensitive = pRT && pRT->IsImageFlag(SbiImageFlags::COMPARETEXT);
         }
         else
         {
-            bTextMode = true;
+            bCaseInsensitive = true;
         }
-        if ( nArgCount == 6 )
+    }
+
+    const OUString aExpStr = rPar.Get32(1)->GetOUString();
+    OUString aFindStr = rPar.Get32(2)->GetOUString();
+    const OUString aReplaceStr = rPar.Get32(3)->GetOUString();
+    const sal_Int32 nExpStrLen = aExpStr.getLength();
+    const sal_Int32 nFindStrLen = aFindStr.getLength();
+
+    OUString aSrcStr(aExpStr);
+    if (bCaseInsensitive)
+    {
+        // FIXME: case insensitivity should not be ASCII-only
+        aSrcStr = aSrcStr.toAsciiUpperCase();
+        aFindStr = aFindStr.toAsciiUpperCase();
+    }
+
+    // Note: the result starts from lStartPos, removing everything to the left. See i#94895.
+    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)
         {
-            bTextMode = rPar.Get32(6)->GetInteger();
+            sResult.append(aExpStr.getStr() + nPrevPos, nPos - nPrevPos);
+            sResult.append(aReplaceStr);
+            nPrevPos = nPos + nFindStrLen;
+            nCounts++;
         }
-        sal_Int32 nExpStrLen = aExpStr.getLength();
-        sal_Int32 nFindStrLen = aFindStr.getLength();
-        sal_Int32 nReplaceStrLen = aReplaceStr.getLength();
-
-        if( lStartPos <= nExpStrLen )
+        else
         {
-            sal_Int32 nPos = lStartPos - 1;
-            sal_Int32 nCounts = 0;
-            while( lCount == -1 || lCount > nCounts )
-            {
-                OUString aSrcStr( aExpStr );
-                if( bTextMode )
-                {
-                    aSrcStr = aSrcStr.toAsciiUpperCase();
-                    aFindStr = aFindStr.toAsciiUpperCase();
-                }
-                nPos = aSrcStr.indexOf( aFindStr, nPos );
-                if( nPos >= 0 )
-                {
-                    aExpStr = aExpStr.replaceAt( nPos, nFindStrLen, aReplaceStr );
-                    nPos = nPos + nReplaceStrLen;
-                    nCounts++;
-                }
-                else
-                {
-                    break;
-                }
-            }
+            break;
         }
-        rPar.Get32(0)->PutString( aExpStr.copy( lStartPos - 1 )  );
     }
+    sResult.append(aExpStr.getStr() + nPrevPos, nExpStrLen - nPrevPos);
+    rPar.Get32(0)->PutString(sResult.makeStringAndClear());
 }
 
 void SbRtl_Right(StarBASIC *, SbxArray & rPar, bool)


More information about the Libreoffice-commits mailing list