basic/source/classes/sb.cxx   |   16 ++++++++--------
 basic/source/inc/sbunoobj.hxx |    2 +-
 basic/source/sbx/sbxvar.cxx   |    9 +++++++++
 include/basic/sbxdef.hxx      |    1 +
 include/basic/sbxvar.hxx      |    6 +++---
 5 files changed, 22 insertions(+), 12 deletions(-)

New commits:
commit de81c2545aec06a1b269218b7d00656e97d8b66c
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Mon Apr 4 09:58:53 2022 +0300
Commit:     Mike Kaganski <mike.kagan...@collabora.com>
CommitDate: Mon Apr 4 11:06:00 2022 +0200

    Related: tdf#144245 Optimize case-insensitive handling
    
    1. Make BasicCollection::implGetIndexForName take OUString again,
    after commit f7de7de1189ae4e63f73468076da47b37fe61ede made it take
    std::u16string_view. All call sites pass OUStrings, and commit
    ef32c3b4f9b80918d6018e14297fa41245afd381 made it create OUString
    from the argument.
    2. Have SbxVariable cache a case-insensitive variant of the name.
    It is currently only used in the Collection implementation, but
    may be used in other places; Tthe names are case-insensitive in
    Basic, and VBA allows non-ASCII characters in names, so this
    caching might be useful elsewhere.
    3. Skip non-ASCII characters when calculating name hash, to allow
    non-ASCII-containing strings still have some hash variance, when
    at least some of the first 6 characters are ASCII.
    
    Change-Id: If90ccea2c4b44c34967e6b764b6fab45b2976c40
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132493
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>

diff --git a/basic/source/classes/sb.cxx b/basic/source/classes/sb.cxx
index 5c99408847b6..902f7adfd91f 100644
--- a/basic/source/classes/sb.cxx
+++ b/basic/source/classes/sb.cxx
@@ -2065,26 +2065,26 @@ sal_Int32 BasicCollection::implGetIndex( SbxVariable 
const * pIndexVar )
     return nIndex;
 }
 
-sal_Int32 BasicCollection::implGetIndexForName(std::u16string_view rName)
+sal_Int32 BasicCollection::implGetIndexForName(const OUString& rName)
 {
-    sal_Int32 nIndex = -1;
     sal_Int32 nCount = xItemArray->Count();
     sal_Int32 nNameHash = MakeHashCode( rName );
 
     // tdf#144245 - case-insensitive operation for non-ASCII characters
-    utl::TransliterationWrapper& rTransliteration = 
SbGlobal::GetTransliteration();
+    OUString aNameCI; // Only initialize when matching hash found
 
     for( sal_Int32 i = 0 ; i < nCount ; i++ )
     {
         SbxVariable* pVar = xItemArray->Get(i);
-        if (pVar->GetHashCode() == nNameHash
-            && rTransliteration.isEqual(pVar->GetName(), OUString(rName)))
+        if (pVar->GetHashCode() == nNameHash)
         {
-            nIndex = i;
-            break;
+            if (aNameCI.isEmpty() && !rName.isEmpty())
+                aNameCI = SbGlobal::GetTransliteration().transliterate(rName, 
0, rName.getLength());
+            if (aNameCI == pVar->GetName(SbxNameType::CaseInsensitive))
+                return i;
         }
     }
-    return nIndex;
+    return -1;
 }
 
 void BasicCollection::CollAdd( SbxArray* pPar_ )
diff --git a/basic/source/inc/sbunoobj.hxx b/basic/source/inc/sbunoobj.hxx
index 1f3042951e51..1fc8ebe4e6c1 100644
--- a/basic/source/inc/sbunoobj.hxx
+++ b/basic/source/inc/sbunoobj.hxx
@@ -350,7 +350,7 @@ class BasicCollection final : public SbxObject
     virtual ~BasicCollection() override;
     virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override;
     sal_Int32 implGetIndex( SbxVariable const * pIndexVar );
-    sal_Int32 implGetIndexForName(std::u16string_view rName);
+    sal_Int32 implGetIndexForName(const OUString& rName);
     void CollAdd( SbxArray* pPar_ );
     void CollItem( SbxArray* pPar_ );
     void CollRemove( SbxArray* pPar_ );
diff --git a/basic/source/sbx/sbxvar.cxx b/basic/source/sbx/sbxvar.cxx
index 8fb11bf9f2a2..a08122961b66 100644
--- a/basic/source/sbx/sbxvar.cxx
+++ b/basic/source/sbx/sbxvar.cxx
@@ -30,6 +30,8 @@
 #include <sbunoobj.hxx>
 #include <rtl/ustrbuf.hxx>
 #include <sal/log.hxx>
+#include <global.hxx>
+#include <unotools/transliterationwrapper.hxx>
 
 #include <com/sun/star/uno/XInterface.hpp>
 using namespace com::sun::star::uno;
@@ -183,6 +185,7 @@ void SbxVariable::SetName( const OUString& rName )
 {
     maName = rName;
     nHash = MakeHashCode( rName );
+    maNameCI.clear();
 }
 
 const OUString& SbxVariable::GetName( SbxNameType t ) const
@@ -192,6 +195,12 @@ const OUString& SbxVariable::GetName( SbxNameType t ) const
     {
         return maName;
     }
+    if (t == SbxNameType::CaseInsensitive)
+    {
+        if (maNameCI.isEmpty() && !maName.isEmpty())
+            maNameCI = SbGlobal::GetTransliteration().transliterate(maName, 0, 
maName.getLength());
+        return maNameCI;
+    }
     // Request parameter-information (not for objects)
     const_cast<SbxVariable*>(this)->GetInfo();
     // Append nothing, if it is a simple property (no empty brackets)
diff --git a/include/basic/sbxdef.hxx b/include/basic/sbxdef.hxx
index b52b0beb3c7d..e85f1a209664 100644
--- a/include/basic/sbxdef.hxx
+++ b/include/basic/sbxdef.hxx
@@ -122,6 +122,7 @@ enum SbxOperator {
 
 enum class SbxNameType {          // Type of the questioned name of a variable
     NONE,           // plain name
+    CaseInsensitive, // plain name - case insensitive
     ShortTypes,     // Name%(A%,B$)
 };
 
diff --git a/include/basic/sbxvar.hxx b/include/basic/sbxvar.hxx
index 1f1ac8a8c4fc..d302f26637bd 100644
--- a/include/basic/sbxvar.hxx
+++ b/include/basic/sbxvar.hxx
@@ -248,6 +248,7 @@ class BASIC_DLLPUBLIC SbxVariable : public SbxValue
     StarBASIC*       m_pComListenerParentBasic = nullptr;
     std::unique_ptr<SfxBroadcaster>  mpBroadcaster; // Broadcaster, if needed
     OUString         maName;            // Name, if available
+    mutable OUString maNameCI;          // Name, case insentitive - cached for 
fast comparison
     SbxArrayRef      mpPar;             // Parameter-Array, if set
     sal_uInt16       nHash = 0;         // Hash-ID for search
 
@@ -308,9 +309,8 @@ public:
         const auto first6 = aName.substr(0, 6);
         for (const auto& c : first6)
         {
-            // If we have a filthy non-ASCII character, break!!
-            if (c >= 0x80)
-                return 0;
+            if (!rtl::isAscii(c))
+                continue; // Just skip it to let non-ASCII strings have some 
hash variance
             n = static_cast<sal_uInt16>((n << 3) + rtl::toAsciiUpperCase(c));
         }
         return n;

Reply via email to