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;