This is an automated email from the ASF dual-hosted git repository.

jimjag pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/openoffice.git


The following commit(s) were added to refs/heads/trunk by this push:
     new b6be11d128 Basic: use a hash map for Collection lookup by key
b6be11d128 is described below

commit b6be11d1285f1f5c601f8ae41773110c184dd1fb
Author: Jim Jagielski <[email protected]>
AuthorDate: Tue Oct 13 11:48:22 2026 -0400

    Basic: use a hash map for Collection lookup by key
---
 main/basic/source/classes/sb.cxx   | 104 +++++++++++++++++++++++++++++++------
 main/basic/source/inc/sbunoobj.hxx |   8 +++
 2 files changed, 97 insertions(+), 15 deletions(-)

diff --git a/main/basic/source/classes/sb.cxx b/main/basic/source/classes/sb.cxx
index beb93b617d..11350c1f88 100644
--- a/main/basic/source/classes/sb.cxx
+++ b/main/basic/source/classes/sb.cxx
@@ -59,6 +59,8 @@
 #include "errobject.hxx"
 #include <map>
 #include <hash_map>
+#include <vector>
+#include <algorithm>
 
 #include <com/sun/star/script/ModuleType.hpp>
 #include <com/sun/star/script/ModuleInfo.hpp>
@@ -2051,8 +2053,21 @@ static sal_uInt16 nCountHash = 0, nAddHash, nItemHash, 
nRemoveHash;
 SbxInfoRef BasicCollection::xAddInfo = NULL;
 SbxInfoRef BasicCollection::xItemInfo = NULL;
 
+// Items may share a name (an item added without a key keeps the name of the
+// variable it was copied from), so each name maps to all of its holders.
+class CollectionNameMap : public
+       std::hash_map< ::rtl::OUString, std::vector< SbxVariable* >,
+               ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > >
+{};
+
+// Matches EqualsIgnoreCaseAscii: only ASCII letters are folded
+static ::rtl::OUString lcl_foldCollectionName( const String& rName )
+{
+       return ::rtl::OUString( rName ).toAsciiUpperCase();
+}
+
 BasicCollection::BasicCollection( const XubString& rClass )
-                        : SbxObject( rClass )
+                        : SbxObject( rClass ), mpNameMap( new 
CollectionNameMap )
 {
        if( !nCountHash )
        {
@@ -2066,7 +2081,9 @@ BasicCollection::BasicCollection( const XubString& rClass 
)
 }
 
 BasicCollection::~BasicCollection()
-{}
+{
+       delete mpNameMap;
+}
 
 void BasicCollection::Clear()
 {
@@ -2077,6 +2094,7 @@ void BasicCollection::Clear()
 void BasicCollection::Initialize()
 {
        xItemArray = new SbxArray();
+       mpNameMap->clear();
        SetType( SbxOBJECT );
        SetFlag( SBX_FIXED );
        ResetFlag( SBX_WRITE );
@@ -2165,22 +2183,69 @@ sal_Int32 BasicCollection::implGetIndex( SbxVariable* 
pIndexVar )
        return nIndex;
 }
 
-sal_Int32 BasicCollection::implGetIndexForName( const String& rName )
+void BasicCollection::implRegisterName( SbxVariable* pVar )
+{
+       // Nameless items are never found by name, see implFindByName
+       if( pVar->GetName().Len() )
+               (*mpNameMap)[ lcl_foldCollectionName( pVar->GetName() ) 
].push_back( pVar );
+}
+
+void BasicCollection::implUnregisterName( SbxVariable* pVar )
+{
+       if( !pVar->GetName().Len() )
+               return;
+       CollectionNameMap::iterator it = mpNameMap->find( 
lcl_foldCollectionName( pVar->GetName() ) );
+       if( it == mpNameMap->end() )
+               return;
+       std::vector< SbxVariable* >& rVars = it->second;
+       rVars.erase( std::remove( rVars.begin(), rVars.end(), pVar ), 
rVars.end() );
+       if( rVars.empty() )
+               mpNameMap->erase( it );
+}
+
+// Returns the item with the lowest index that has the given name
+SbxVariable* BasicCollection::implFindByName( const String& rName )
 {
-       sal_Int32 nIndex = -1;
        sal_Int32 nCount = xItemArray->Count32();
-       sal_Int32 nNameHash = MakeHashCode( rName );
-       for( sal_Int32 i = 0 ; i < nCount ; i++ )
+       if( !rName.Len() )
        {
-               SbxVariable* pVar = xItemArray->Get32( i );
-               if( pVar->GetHashCode() == nNameHash &&
-                       pVar->GetName().EqualsIgnoreCaseAscii( rName ) )
+               // Nameless items are not indexed
+               for( sal_Int32 i = 0 ; i < nCount ; i++ )
                {
-                       nIndex = i;
-                       break;
+                       SbxVariable* pVar = xItemArray->Get32( i );
+                       if( !pVar->GetName().Len() )
+                               return pVar;
                }
+               return NULL;
        }
-       return nIndex;
+
+       CollectionNameMap::iterator it = mpNameMap->find( 
lcl_foldCollectionName( rName ) );
+       if( it == mpNameMap->end() )
+               return NULL;
+       std::vector< SbxVariable* >& rVars = it->second;
+       if( rVars.size() == 1 )
+               return rVars[0];
+       for( sal_Int32 i = 0 ; i < nCount ; i++ )
+       {
+               SbxVariable* pVar = xItemArray->Get32( i );
+               if( std::find( rVars.begin(), rVars.end(), pVar ) != 
rVars.end() )
+                       return pVar;
+       }
+       return NULL;
+}
+
+sal_Int32 BasicCollection::implGetIndexForName( const String& rName )
+{
+       SbxVariable* pFound = implFindByName( rName );
+       if( !pFound )
+               return -1;
+       sal_Int32 nCount = xItemArray->Count32();
+       for( sal_Int32 i = 0 ; i < nCount ; i++ )
+       {
+               if( xItemArray->Get32( i ) == pFound )
+                       return i;
+       }
+       return -1;
 }
 
 void BasicCollection::CollAdd( SbxArray* pPar_ )
@@ -2253,6 +2318,7 @@ void BasicCollection::CollAdd( SbxArray* pPar_ )
                }
                pNewItem->SetFlag( SBX_READWRITE );
                xItemArray->Insert32( pNewItem, nNextIndex );
+               implRegisterName( pNewItem );
        }
        else
        {
@@ -2270,9 +2336,16 @@ void BasicCollection::CollItem( SbxArray* pPar_ )
        }
        SbxVariable* pRes = NULL;
        SbxVariable* p = pPar_->Get( 1 );
-       sal_Int32 nIndex = implGetIndex( p );
-       if( nIndex >= 0 && nIndex < (sal_Int32)xItemArray->Count32() )
-               pRes = xItemArray->Get32( nIndex );
+       if( p->GetType() == SbxSTRING )
+       {
+               pRes = implFindByName( p->GetString() );
+       }
+       else
+       {
+               sal_Int32 nIndex = implGetIndex( p );
+               if( nIndex >= 0 && nIndex < (sal_Int32)xItemArray->Count32() )
+                       pRes = xItemArray->Get32( nIndex );
+       }
        if( !pRes )
                SetError( SbERR_BAD_ARGUMENT );
        else
@@ -2291,6 +2364,7 @@ void BasicCollection::CollRemove( SbxArray* pPar_ )
        sal_Int32 nIndex = implGetIndex( p );
        if( nIndex >= 0 && nIndex < (sal_Int32)xItemArray->Count32() )
        {
+               implUnregisterName( xItemArray->Get32( nIndex ) );
                xItemArray->Remove32( nIndex );
 
                // Correct for stack if necessary
diff --git a/main/basic/source/inc/sbunoobj.hxx 
b/main/basic/source/inc/sbunoobj.hxx
index 8d0e7f280e..ff5659ce64 100644
--- a/main/basic/source/inc/sbunoobj.hxx
+++ b/main/basic/source/inc/sbunoobj.hxx
@@ -305,10 +305,13 @@ void clearNativeObjectWrapperVector( void );
 //========================================================================
 // #118116 Collection object
 
+class CollectionNameMap;
+
 class BasicCollection : public SbxObject
 {
        friend class SbiRuntime;
        SbxArrayRef xItemArray;
+       CollectionNameMap* mpNameMap;
        static SbxInfoRef xAddInfo;
        static SbxInfoRef xItemInfo;
 
@@ -318,6 +321,11 @@ class BasicCollection : public SbxObject
                                                         const SfxHint& rHint, 
const TypeId& rHintType );
        sal_Int32 implGetIndex( SbxVariable* pIndexVar );
        sal_Int32 implGetIndexForName( const String& rName );
+       SbxVariable* implFindByName( const String& rName );
+       void implRegisterName( SbxVariable* pVar );
+       void implUnregisterName( SbxVariable* pVar );
+       BasicCollection( const BasicCollection& );
+       BasicCollection& operator=( const BasicCollection& );
        void CollAdd( SbxArray* pPar_ );
        void CollItem( SbxArray* pPar_ );
        void CollRemove( SbxArray* pPar_ );

Reply via email to