sw/inc/IDocumentFieldsAccess.hxx             |    5 
 sw/inc/calc.hxx                              |   61 -------
 sw/source/core/bastyp/calc.cxx               |  226 +++++++--------------------
 sw/source/core/doc/DocumentFieldsManager.cxx |   73 ++------
 sw/source/core/doc/docfld.cxx                |   48 +----
 sw/source/core/edit/editsh.cxx               |    2 
 sw/source/core/fields/expfld.cxx             |    2 
 sw/source/core/inc/DocumentFieldsManager.hxx |    2 
 sw/source/core/inc/docfld.hxx                |   29 +--
 9 files changed, 114 insertions(+), 334 deletions(-)

New commits:
commit 947b23c20780ede6b4d588fb9b944f572e9f8bc8
Author:     Noel Grandin <noelgran...@gmail.com>
AuthorDate: Sat Nov 25 00:53:37 2023 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Sat Nov 25 11:25:25 2023 +0100

    Convert SwHashTable to std::unordered_map
    
    Change-Id: I88b082dc61c05761fd162ea4cf1d30940c2dfccd
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159941
    Tested-by: Noel Grandin <noel.gran...@collabora.co.uk>
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/sw/inc/IDocumentFieldsAccess.hxx b/sw/inc/IDocumentFieldsAccess.hxx
index 4664ae3bc846..4ffe7779833f 100644
--- a/sw/inc/IDocumentFieldsAccess.hxx
+++ b/sw/inc/IDocumentFieldsAccess.hxx
@@ -25,6 +25,7 @@
 #include <sal/types.h>
 #include "swtypes.hxx"
 #include "nodeoffset.hxx"
+#include <unordered_map>
 
 class SwFieldTypes;
 class SwFieldType;
@@ -40,8 +41,6 @@ class SetGetExpField;
 class SwNode;
 class SwTable;
 enum class SwFieldIds : sal_uInt16;
-template <class T> class SwHashTable;
-struct HashStr;
 class SwRootFrame;
 class IDocumentRedlineAccess;
 
@@ -128,7 +127,7 @@ namespace com::sun::star::uno { class Any; }
 
     virtual void FieldsToCalc(SwCalc& rCalc, const SetGetExpField& 
rToThisField, SwRootFrame const* pLayout) = 0;
 
-    virtual void FieldsToExpand(SwHashTable<HashStr> & rTable, const 
SetGetExpField& rToThisField, SwRootFrame const& rLayout) = 0;
+    virtual void FieldsToExpand(std::unordered_map<OUString,OUString> & 
rTable, const SetGetExpField& rToThisField, SwRootFrame const& rLayout) = 0;
 
     virtual bool IsNewFieldLst() const = 0;
 
diff --git a/sw/inc/calc.hxx b/sw/inc/calc.hxx
index 87583f752ff4..0e066bae145f 100644
--- a/sw/inc/calc.hxx
+++ b/sw/inc/calc.hxx
@@ -22,6 +22,7 @@
 
 #include <memory>
 #include <vector>
+#include <unordered_map>
 #include <i18nlangtag/lang.h>
 #include <basic/sbxvar.hxx>
 #include <unotools/syslocale.hxx>
@@ -37,8 +38,6 @@ class SwFieldType;
 class SwDoc;
 class SwUserFieldType;
 
-#define TBLSZ 47                // should be a prime, because of hash table
-
 const sal_Unicode cListDelim    = '|';
 
 enum SwCalcOper
@@ -131,62 +130,12 @@ public:
     void SetDBvalue(bool bSet) {m_bDBvalue = bSet;}
 };
 
-// Calculate HashTables for VarTable and Operations
-struct SwHash
-{
-    SwHash( OUString aStr );
-    virtual ~SwHash();
-    OUString aStr;
-    std::unique_ptr<SwHash> pNext;
-};
-
-struct SwCalcExp final : public SwHash
+struct SwCalcExp
 {
     SwSbxValue  nValue;
     const SwFieldType* pFieldType;
 
-    SwCalcExp( const OUString& rStr, SwSbxValue aVal,
-                const SwFieldType* pFieldType );
-};
-
-/// T should be a subclass of SwHash
-template<class T>
-class SwHashTable
-{
-    std::vector<std::unique_ptr<T>> m_aData;
-public:
-    SwHashTable(size_t nSize) : m_aData(nSize)
-    {
-        assert(nSize < SAL_MAX_UINT32);
-    }
-    std::unique_ptr<T> & operator[](size_t idx) { return m_aData[idx]; }
-    std::unique_ptr<T> const & operator[](size_t idx) const { return 
m_aData[idx]; }
-    void resize(size_t nSize) { m_aData.resize(nSize); }
-
-    T* Find( std::u16string_view aStr, sal_uInt32* pPos = nullptr ) const
-    {
-        size_t nTableSize = m_aData.size();
-        assert(nTableSize < SAL_MAX_UINT32);
-        sal_uInt32 ii = 0;
-        for( size_t n = 0; n < aStr.size(); ++n )
-        {
-            ii = ii << 1 ^ aStr[n];
-        }
-        ii %= nTableSize;
-
-        if( pPos )
-            *pPos = ii;
-
-        for( T* pEntry = m_aData[ii].get(); pEntry; pEntry = 
static_cast<T*>(pEntry->pNext.get()) )
-        {
-            if( aStr == pEntry->aStr )
-            {
-                return pEntry;
-            }
-        }
-        return nullptr;
-    }
-
+    SwCalcExp( SwSbxValue aVal, const SwFieldType* pFieldType );
 };
 
 
@@ -198,7 +147,7 @@ extern "C" typedef double (*pfCalc)(double);
 
 class SwCalc
 {
-    SwHashTable<SwCalcExp> m_aVarTable;
+    std::unordered_map<OUString, SwCalcExp> m_aVarTable;
     OUStringBuffer m_aVarName;
     OUString    m_sCurrSym;
     OUString    m_sCommand;
@@ -245,7 +194,7 @@ public:
     SwCalcExp*  VarLook( const OUString &rStr, bool bIns = false );
     void        VarChange( const OUString& rStr, const SwSbxValue& rValue );
     void        VarChange( const OUString& rStr, double );
-    SwHashTable<SwCalcExp> & GetVarTable() { return m_aVarTable; }
+    std::unordered_map<OUString, SwCalcExp> & GetVarTable() { return 
m_aVarTable; }
 
     bool        Push(const SwUserFieldType* pUserFieldType);
     void        Pop();
diff --git a/sw/source/core/bastyp/calc.cxx b/sw/source/core/bastyp/calc.cxx
index 62d300f60ba7..0c9643317a4e 100644
--- a/sw/source/core/bastyp/calc.cxx
+++ b/sw/source/core/bastyp/calc.cxx
@@ -218,8 +218,7 @@ static double lcl_ConvertToDateValue( SwDoc& rDoc, 
sal_Int32 nDate )
 }
 
 SwCalc::SwCalc( SwDoc& rD )
-    : m_aVarTable(TBLSZ)
-    , m_aErrExpr( OUString(), SwSbxValue(), nullptr )
+    : m_aErrExpr( SwSbxValue(), nullptr )
     , m_nCommandPos(0)
     , m_rDoc( rD )
     , m_pCharClass( &GetAppCharClass() )
@@ -229,7 +228,6 @@ SwCalc::SwCalc( SwDoc& rD )
     , m_eCurrListOper( CALC_NAME )
     , m_eError( SwCalcError::NONE )
 {
-    m_aErrExpr.aStr = "~C_ERR~";
     LanguageType eLang = GetDocAppScriptLang( m_rDoc );
     LanguageTag aLanguageTag( eLang );
 
@@ -242,53 +240,36 @@ SwCalc::SwCalc( SwDoc& rD )
     m_sCurrSym = 
comphelper::string::strip(m_xLocaleDataWrapper->getCurrSymbol(), ' ');
     m_sCurrSym  = m_pCharClass->lowercase( m_sCurrSym );
 
-    static char const
-        sNType0[] = "false",
-        sNType1[] = "true",
-        sNType2[] = "pi",
-        sNType3[] = "e",
-        sNType4[] = "tables",
-        sNType5[] = "graf",
-        sNType6[] = "ole",
-        sNType7[] = "page",
-        sNType8[] = "para",
-        sNType9[] = "word",
-        sNType10[]= "char",
-
-        sNType11[] = "user_firstname" ,
-        sNType12[] = "user_lastname" ,
-        sNType13[] = "user_initials" ,
-        sNType14[] = "user_company" ,
-        sNType15[] = "user_street" ,
-        sNType16[] = "user_country" ,
-        sNType17[] = "user_zipcode" ,
-        sNType18[] = "user_city" ,
-        sNType19[] = "user_title" ,
-        sNType20[] = "user_position" ,
-        sNType21[] = "user_tel_work" ,
-        sNType22[] = "user_tel_home" ,
-        sNType23[] = "user_fax" ,
-        sNType24[] = "user_email" ,
-        sNType25[] = "user_state" ,
-        sNType26[] = "graph"
-        ;
-    static const char* const sNTypeTab[ 27 ] =
+    static constexpr OUString sNTypeTab[]
     {
-        sNType0, sNType1, sNType2, sNType3, sNType4, sNType5,
-        sNType6, sNType7, sNType8, sNType9, sNType10, sNType11,
-        sNType12, sNType13, sNType14, sNType15, sNType16, sNType17,
-        sNType18, sNType19, sNType20, sNType21, sNType22, sNType23,
-        sNType24,
-
-        // those have two HashIds
-        sNType25, sNType26
-    };
-    static sal_uInt16 const aHashValue[ 27 ] =
-    {
-        34, 38, 43,  7, 18, 32, 22, 29, 30, 33,  3,
-        28, 24, 40,  9, 11, 26, 45,  4, 23, 36, 44, 19,  5,  1,
-        // those have two HashIds
-        11, 38
+        u"false"_ustr,
+        u"true"_ustr,
+        u"pi"_ustr,
+        u"e"_ustr,
+        u"tables"_ustr,
+        u"graf"_ustr,
+        u"ole"_ustr,
+        u"page"_ustr,
+        u"para"_ustr,
+        u"word"_ustr,
+        u"char"_ustr,
+
+        u"user_firstname"_ustr,
+        u"user_lastname"_ustr,
+        u"user_initials"_ustr,
+        u"user_company"_ustr,
+        u"user_street"_ustr,
+        u"user_country"_ustr,
+        u"user_zipcode"_ustr,
+        u"user_city"_ustr,
+        u"user_title"_ustr,
+        u"user_position"_ustr,
+        u"user_tel_work"_ustr,
+        u"user_tel_home"_ustr,
+        u"user_fax"_ustr,
+        u"user_email"_ustr,
+        u"user_state"_ustr,
+        u"graph"_ustr
     };
     static UserOptToken const aAdrToken[ 12 ] =
     {
@@ -307,45 +288,36 @@ SwCalc::SwCalc( SwDoc& rD )
         &SwDocStat::nWord, &SwDocStat::nChar
     };
 
-#if TBLSZ != 47
-#error Did you adjust all hash values?
-#endif
-
     const SwDocStat& rDocStat = m_rDoc.getIDocumentStatistics().GetDocStat();
 
     SwSbxValue nVal;
-    OUString sTmpStr;
     sal_uInt16 n;
 
     for( n = 0; n < 25; ++n )
-    {
-        sTmpStr = OUString::createFromAscii(sNTypeTab[n]);
-        m_aVarTable[ aHashValue[ n ] ].reset( new SwCalcExp( sTmpStr, nVal, 
nullptr ) );
-    }
+        m_aVarTable.insert( { sNTypeTab[n], SwCalcExp( nVal, nullptr ) } );
 
-    m_aVarTable[ aHashValue[ 0 ] ]->nValue.PutBool( false );
-    m_aVarTable[ aHashValue[ 1 ] ]->nValue.PutBool( true );
-    m_aVarTable[ aHashValue[ 2 ] ]->nValue.PutDouble( M_PI );
-    m_aVarTable[ aHashValue[ 3 ] ]->nValue.PutDouble( M_E );
+    m_aVarTable.find( sNTypeTab[ 0 ] )->second.nValue.PutBool( false );
+    m_aVarTable.find( sNTypeTab[ 1 ] )->second.nValue.PutBool( true );
+    m_aVarTable.find( sNTypeTab[ 2 ] )->second.nValue.PutDouble( M_PI );
+    m_aVarTable.find( sNTypeTab[ 3 ] )->second.nValue.PutDouble( M_E );
 
     for( n = 0; n < 3; ++n )
-        m_aVarTable[ aHashValue[ n + 4 ] ]->nValue.PutLong( 
rDocStat.*aDocStat1[ n ]  );
+        m_aVarTable.find( sNTypeTab[ n + 4 ] )->second.nValue.PutLong( 
rDocStat.*aDocStat1[ n ]  );
     for( n = 0; n < 4; ++n )
-        m_aVarTable[ aHashValue[ n + 7 ] ]->nValue.PutLong( 
rDocStat.*aDocStat2[ n ]  );
+        m_aVarTable.find( sNTypeTab[ n + 7 ] )->second.nValue.PutLong( 
rDocStat.*aDocStat2[ n ]  );
 
     SvtUserOptions& rUserOptions = SW_MOD()->GetUserOptions();
 
-    m_aVarTable[ aHashValue[ 11 ] ]->nValue.PutString( 
rUserOptions.GetFirstName() );
-    m_aVarTable[ aHashValue[ 12 ] ]->nValue.PutString( 
rUserOptions.GetLastName() );
-    m_aVarTable[ aHashValue[ 13 ] ]->nValue.PutString( rUserOptions.GetID() );
+    m_aVarTable.find( sNTypeTab[ 11 ] )->second.nValue.PutString( 
rUserOptions.GetFirstName() );
+    m_aVarTable.find( sNTypeTab[ 12 ] )->second.nValue.PutString( 
rUserOptions.GetLastName() );
+    m_aVarTable.find( sNTypeTab[ 13 ] )->second.nValue.PutString( 
rUserOptions.GetID() );
 
     for( n = 0; n < 11; ++n )
-        m_aVarTable[ aHashValue[ n + 14 ] ]->nValue.PutString(
+        m_aVarTable.find( sNTypeTab[ n + 14 ] )->second.nValue.PutString(
                                         rUserOptions.GetToken( aAdrToken[ n ] 
));
 
     nVal.PutString( rUserOptions.GetToken( aAdrToken[ 11 ] ));
-    sTmpStr = OUString::createFromAscii(sNTypeTab[25]);
-    m_aVarTable[ aHashValue[ 25 ] ]->pNext.reset( new SwCalcExp( sTmpStr, 
nVal, nullptr ) );
+    m_aVarTable.insert( { sNTypeTab[ 25 ], SwCalcExp( nVal, nullptr ) } );
 
 } // SwCalc::SwCalc
 
@@ -430,26 +402,23 @@ SwCalcExp* SwCalc::VarLook( const OUString& rStr, bool 
bIns )
 {
     m_aErrExpr.nValue.SetVoidValue(false);
 
-    sal_uInt32 ii = 0;
     OUString aStr = m_pCharClass->lowercase( rStr );
-
-    SwCalcExp* pFnd = m_aVarTable.Find(aStr, &ii);
+    SwCalcExp* pFnd = nullptr;
+    auto it = m_aVarTable.find(aStr);
+    if (it != m_aVarTable.end())
+        pFnd = &it->second;
 
     if( !pFnd )
     {
         // then check doc
-        SwHashTable<SwCalcFieldType> const & rDocTable = 
m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().GetFieldTypeTable();
-        for( SwHash* pEntry = rDocTable[ii].get(); pEntry; pEntry = 
pEntry->pNext.get() )
+        std::unordered_multimap<OUString, const SwFieldType*> & rDocTable
+            = 
m_rDoc.getIDocumentFieldsAccess().GetUpdateFields().GetFieldTypeTable();
+        auto docIt = rDocTable.find(aStr);
+        if (docIt != rDocTable.end())
         {
-            if( aStr == pEntry->aStr )
-            {
-                // then insert here
-                pFnd = new SwCalcExp( aStr, SwSbxValue(),
-                                    
static_cast<SwCalcFieldType*>(pEntry)->pFieldType );
-                pFnd->pNext = std::move( m_aVarTable[ii] );
-                m_aVarTable[ii].reset(pFnd);
-                break;
-            }
+            const SwFieldType* pFieldType = docIt->second;
+            it = m_aVarTable.insert( { aStr, SwCalcExp( SwSbxValue(), 
pFieldType ) } ).first;
+            pFnd = &it->second;
         }
     }
 
@@ -558,9 +527,7 @@ SwCalcExp* SwCalc::VarLook( const OUString& rStr, bool bIns 
)
         return &m_aErrExpr;
     }
 
-    SwCalcExp* pNewExp = new SwCalcExp( aStr, SwSbxValue(), nullptr );
-    pNewExp->pNext = std::move( m_aVarTable[ ii ] );
-    m_aVarTable[ ii ].reset( pNewExp );
+    SwCalcExp* pNewExp = &m_aVarTable.insert( { aStr, SwCalcExp( SwSbxValue(), 
nullptr ) } ).first->second;
 
     OUString sColumnName( GetColumnName( sTmpName ));
     OSL_ENSURE( !sColumnName.isEmpty(), "Missing DB column name" );
@@ -598,19 +565,11 @@ void SwCalc::VarChange( const OUString& rStr, const 
SwSbxValue& rValue )
 {
     OUString aStr = m_pCharClass->lowercase( rStr );
 
-    sal_uInt32 nPos = 0;
-    SwCalcExp* pFnd = m_aVarTable.Find( aStr, &nPos );
-
-    if( !pFnd )
-    {
-        pFnd = new SwCalcExp( aStr, rValue, nullptr );
-        pFnd->pNext = std::move( m_aVarTable[ nPos ] );
-        m_aVarTable[ nPos ].reset( pFnd );
-    }
+    auto it = m_aVarTable.find( aStr );
+    if (it != m_aVarTable.end())
+        it->second.nValue = rValue;
     else
-    {
-        pFnd->nValue = rValue;
-    }
+        m_aVarTable.insert( { aStr, SwCalcExp( rValue, nullptr ) } );
 }
 
 bool SwCalc::Push( const SwUserFieldType* pUserFieldType )
@@ -1442,19 +1401,8 @@ bool SwCalc::IsValidVarName( const OUString& rStr, 
OUString* pValidName )
     return bRet;
 }
 
-SwHash::SwHash(OUString _aStr)
-    : aStr(std::move(_aStr))
-{
-}
-
-SwHash::~SwHash()
-{
-}
-
-SwCalcExp::SwCalcExp(const OUString& rStr, SwSbxValue aVal,
-                      const SwFieldType* pType)
-    : SwHash(rStr)
-    , nValue(std::move(aVal))
+SwCalcExp::SwCalcExp(SwSbxValue aVal, const SwFieldType* pType)
+    : nValue(std::move(aVal))
     , pFieldType(pType)
 {
 }
@@ -1491,58 +1439,4 @@ SwSbxValue& SwSbxValue::MakeDouble()
     return *this;
 }
 
-#ifdef STANDALONE_HASHCALC
-
-// this is example code how to create hash values in the CTOR:
-
-#include <stdio.h>
-void main()
-{
-    static char
-        sNType0[] = "false",    sNType1[] = "true",     sNType2[] = "pi",
-        sNType3[] = "e",        sNType4[] = "tables",   sNType5[] = "graf",
-        sNType6[] = "ole",      sNType7[] = "page",     sNType8[] = "para",
-        sNType9[] = "word",     sNType10[]= "char",
-        sNType11[] = "user_company" ,       sNType12[] = "user_firstname" ,
-        sNType13[] = "user_lastname" ,      sNType14[] = "user_initials",
-        sNType15[] = "user_street" ,        sNType16[] = "user_country" ,
-        sNType17[] = "user_zipcode" ,       sNType18[] = "user_city" ,
-        sNType19[] = "user_title" ,         sNType20[] = "user_position" ,
-        sNType21[] = "user_tel_home",       sNType22[] = "user_tel_work",
-        sNType23[] = "user_fax" ,           sNType24[] = "user_email" ,
-        sNType25[] = "user_state",          sNType26[] = "graph"
-        ;
-
-    static const char* sNTypeTab[ 27 ] =
-    {
-        sNType0, sNType1, sNType2, sNType3, sNType4, sNType5,
-        sNType6, sNType7, sNType8, sNType9, sNType10, sNType11,
-        sNType12, sNType13, sNType14, sNType15, sNType16, sNType17,
-        sNType18, sNType19, sNType20, sNType21, sNType22, sNType23,
-        sNType24, sNType25, sNType26
-    };
-
-    const unsigned short nTableSize = 47;
-    int aArr[ nTableSize ] = { 0 };
-    char ch;
-
-    for( int n = 0; n < 27; ++n )
-    {
-        unsigned int ii = 0;
-        const char* pp = sNTypeTab[ n ];
-
-        while( *pp )
-        {
-            ii = ii << 1 ^ *pp++;
-        }
-        ii %= nTableSize;
-
-        ch = aArr[ ii ] ? 'X' : ' ';
-        aArr[ ii ] = 1;
-        printf( "%-20s -> %3u [%c]\n", sNTypeTab[ n ], ii, ch );
-    }
-}
-
-#endif
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/doc/DocumentFieldsManager.cxx 
b/sw/source/core/doc/DocumentFieldsManager.cxx
index a7be3bb96394..66f65438c095 100644
--- a/sw/source/core/doc/DocumentFieldsManager.cxx
+++ b/sw/source/core/doc/DocumentFieldsManager.cxx
@@ -852,11 +852,7 @@ void DocumentFieldsManager::UpdateExpFieldsImpl(
     SwFieldIds nWhich;
 
     // Hash table for all string replacements is filled on-the-fly.
-    // Try to fabricate an uneven number.
-    const SwFieldTypes::size_type nHashSize {(( mpFieldTypes->size() / 7 ) + 1 
) * 7};
-    const sal_uInt16 nStrFormatCnt = o3tl::narrowing<sal_uInt16>(nHashSize);
-    OSL_ENSURE( nStrFormatCnt == nHashSize, "Downcasting to sal_uInt16 lost 
information!" );
-    SwHashTable<HashStr> aHashStrTable(nStrFormatCnt);
+    std::unordered_map<OUString, OUString> aHashStrTable;
 
     {
         const SwFieldType* pFieldType;
@@ -869,17 +865,15 @@ void DocumentFieldsManager::UpdateExpFieldsImpl(
             case SwFieldIds::User:
                 {
                     // Entry present?
-                    sal_uInt32 nPos;
                     const OUString& rNm = pFieldType->GetName();
                     OUString 
sExpand(const_cast<SwUserFieldType*>(static_cast<const 
SwUserFieldType*>(pFieldType))->Expand(nsSwGetSetExpType::GSE_STRING, 0, 
LANGUAGE_SYSTEM));
-                    SwHash* pFnd = aHashStrTable.Find( rNm, &nPos );
-                    if( pFnd )
+                    auto pFnd = aHashStrTable.find( rNm );
+                    if( pFnd != aHashStrTable.end() )
                         // modify entry in the hash table
-                        static_cast<HashStr*>(pFnd)->aSetStr = sExpand;
+                        pFnd->second = sExpand;
                     else
                         // insert the new entry
-                        aHashStrTable[nPos].reset( new HashStr( rNm, sExpand,
-                                                                
aHashStrTable[nPos].release() ) );
+                        aHashStrTable.insert( { rNm, sExpand } );
                 }
                 break;
             default: break;
@@ -1051,19 +1045,17 @@ void DocumentFieldsManager::UpdateExpFieldsImpl(
 
             // Add entry to hash table
             // Entry present?
-            sal_uInt32 nPos;
-            HashStr* pFnd = aHashStrTable.Find( rName, &nPos );
+            auto pFnd = aHashStrTable.find( rName );
             OUString const value(pField->ExpandField(m_rDoc.IsClipBoard(), 
nullptr));
-            if( pFnd )
+            if( pFnd != aHashStrTable.end() )
             {
                 // Modify entry in the hash table
-                pFnd->aSetStr = value;
+                pFnd->second = value;
             }
             else
             {
                 // insert new entry
-               aHashStrTable[nPos].reset( new HashStr( rName,
-                    value, aHashStrTable[nPos].release()) );
+               aHashStrTable.insert( { rName, value } );
             }
 #endif
         }
@@ -1100,23 +1092,17 @@ void DocumentFieldsManager::UpdateExpFieldsImpl(
                     // lookup the field's name
                     aNew = 
static_cast<SwSetExpFieldType*>(pSField->GetTyp())->GetSetRefName();
                     // Entry present?
-                    sal_uInt32 nPos;
-                    HashStr* pFnd = aHashStrTable.Find( aNew, &nPos );
-                    if( pFnd )
+                    auto pFnd = aHashStrTable.find( aNew );
+                    if( pFnd != aHashStrTable.end() )
                         // Modify entry in the hash table
-                        pFnd->aSetStr = pSField->GetExpStr(pLayout);
+                        pFnd->second = pSField->GetExpStr(pLayout);
                     else
-                    {
                         // insert new entry
-                        aHashStrTable[nPos].reset( new HashStr( aNew,
-                                        pSField->GetExpStr(pLayout),
-                                        aHashStrTable[nPos].release() ) );
-                        pFnd = aHashStrTable[nPos].get();
-                    }
+                        pFnd = aHashStrTable.insert( { aNew, 
pSField->GetExpStr(pLayout) } ).first;
 
                     // Extension for calculation with Strings
                     SwSbxValue aValue;
-                    aValue.PutString( pFnd->aSetStr );
+                    aValue.PutString( pFnd->second );
                     aCalc.VarChange( aNew, aValue );
                 }
             }
@@ -1555,7 +1541,7 @@ void DocumentFieldsManager::FieldsToCalc(SwCalc& rCalc,
 #endif
 }
 
-void DocumentFieldsManager::FieldsToExpand( SwHashTable<HashStr> & rHashTable,
+void DocumentFieldsManager::FieldsToExpand( std::unordered_map<OUString, 
OUString> & rHashTable,
         const SetGetExpField& rToThisField, SwRootFrame const& rLayout)
 {
     // create the sorted list of all SetFields
@@ -1564,11 +1550,6 @@ void DocumentFieldsManager::FieldsToExpand( 
SwHashTable<HashStr> & rHashTable,
 
     IDocumentRedlineAccess const& rIDRA(m_rDoc.getIDocumentRedlineAccess());
 
-    // Hash table for all string replacements is filled on-the-fly.
-    // Try to fabricate an uneven number.
-    sal_uInt16 nTableSize = ((mpUpdateFields->GetSortList()->size() / 7) + 1) 
* 7;
-    rHashTable.resize(nTableSize);
-
     SetGetExpFields::const_iterator const itLast =
         mpUpdateFields->GetSortList()->upper_bound(&rToThisField);
 
@@ -1605,15 +1586,13 @@ void DocumentFieldsManager::FieldsToExpand( 
SwHashTable<HashStr> & rHashTable,
                 // look up the field's name
                 aNew = 
static_cast<SwSetExpFieldType*>(pSField->GetTyp())->GetSetRefName();
                 // Entry present?
-                sal_uInt32 nPos;
-                SwHash* pFnd = rHashTable.Find( aNew, &nPos );
-                if( pFnd )
+                auto pFnd = rHashTable.find( aNew );
+                if( pFnd != rHashTable.end() )
                     // modify entry in the hash table
-                    static_cast<HashStr*>(pFnd)->aSetStr = 
pSField->GetExpStr(&rLayout);
+                    pFnd->second = pSField->GetExpStr(&rLayout);
                 else
                     // insert the new entry
-                    rHashTable[nPos].reset( new HashStr( aNew,
-                            pSField->GetExpStr(&rLayout), 
rHashTable[nPos].release()));
+                    rHashTable.insert( { aNew, pSField->GetExpStr(&rLayout) } 
);
             }
             break;
         case SwFieldIds::Database:
@@ -1622,20 +1601,14 @@ void DocumentFieldsManager::FieldsToExpand( 
SwHashTable<HashStr> & rHashTable,
 
                 // Insert entry in the hash table
                 // Entry present?
-                sal_uInt32 nPos;
-                HashStr* pFnd = rHashTable.Find( rName, &nPos );
+                auto pFnd = rHashTable.find( rName );
                 OUString const value(pField->ExpandField(m_rDoc.IsClipBoard(), 
nullptr));
-                if( pFnd )
-                {
+                if( pFnd != rHashTable.end() )
                     // modify entry in the hash table
-                    pFnd->aSetStr = value;
-                }
+                    pFnd->second = value;
                 else
-                {
                     // insert the new entry
-                    rHashTable[nPos].reset( new HashStr( rName,
-                        value, rHashTable[nPos].release()) );
-                }
+                    rHashTable.insert( { rName, value } );
             }
             break;
         default: break;
diff --git a/sw/source/core/doc/docfld.cxx b/sw/source/core/doc/docfld.cxx
index c5b2dbe86b82..c723ee162e3a 100644
--- a/sw/source/core/doc/docfld.cxx
+++ b/sw/source/core/doc/docfld.cxx
@@ -367,19 +367,12 @@ sal_Int32 SetGetExpField::GetCntPosFromContent() const
     return nRet;
 }
 
-HashStr::HashStr( const OUString& rName, OUString aText,
-                    HashStr* pNxt )
-    : SwHash( rName ), aSetStr(std::move( aText ))
-{
-    pNext.reset( pNxt );
-}
-
 /// Look up the Name, if it is present, return its String, otherwise return an 
empty String
-OUString LookString( SwHashTable<HashStr> const & rTable, const OUString& 
rName )
+OUString LookString( std::unordered_map<OUString, OUString> const & rTable, 
const OUString& rName )
 {
-    HashStr* pFnd = rTable.Find( comphelper::string::strip(rName, ' ') );
-    if( pFnd )
-        return pFnd->aSetStr;
+    auto it = rTable.find( comphelper::string::strip(rName, ' ') );
+    if( it != rTable.end() )
+        return it->second;
 
     return OUString();
 }
@@ -1191,16 +1184,10 @@ void SwDocUpdateField::InsertFieldType( const 
SwFieldType& rType )
     SetFieldsDirty( true );
     // look up and remove from the hash table
     sFieldName = GetAppCharClass().lowercase( sFieldName );
-    sal_uInt32 n;
-
-    SwCalcFieldType* pFnd = GetFieldTypeTable().Find( sFieldName, &n );
 
-    if( !pFnd )
-    {
-        SwCalcFieldType* pNew = new SwCalcFieldType( sFieldName, &rType );
-        pNew->pNext.reset( m_FieldTypeTable[n].release() );
-        m_FieldTypeTable[n].reset(pNew);
-    }
+    auto it = m_FieldTypeTable.find( sFieldName );
+    if( it == m_FieldTypeTable.end() )
+        m_FieldTypeTable.insert( { sFieldName, &rType } );
 }
 
 void SwDocUpdateField::RemoveFieldType( const SwFieldType& rType )
@@ -1223,29 +1210,12 @@ void SwDocUpdateField::RemoveFieldType( const 
SwFieldType& rType )
     SetFieldsDirty( true );
     // look up and remove from the hash table
     sFieldName = GetAppCharClass().lowercase( sFieldName );
-    sal_uInt32 n;
 
-    SwCalcFieldType* pFnd = GetFieldTypeTable().Find( sFieldName, &n );
-    if( !pFnd )
-        return;
-
-    if (m_FieldTypeTable[n].get() == pFnd)
-    {
-        
m_FieldTypeTable[n].reset(static_cast<SwCalcFieldType*>(pFnd->pNext.release()));
-    }
-    else
-    {
-        SwHash* pPrev = m_FieldTypeTable[n].get();
-        while( pPrev->pNext.get() != pFnd )
-            pPrev = pPrev->pNext.get();
-        pPrev->pNext = std::move(pFnd->pNext);
-        // no need to explicitly delete here, the embedded linked list uses 
unique_ptr
-    }
+    GetFieldTypeTable().erase( sFieldName );
 }
 
 SwDocUpdateField::SwDocUpdateField(SwDoc& rDoc)
-    : m_FieldTypeTable(TBLSZ)
-    , m_nNodes(0)
+    : m_nNodes(0)
     , m_nFieldListGetMode(0)
     , m_rDoc(rDoc)
     , m_bInUpdateFields(false)
diff --git a/sw/source/core/edit/editsh.cxx b/sw/source/core/edit/editsh.cxx
index 0dcec2742c66..333eecd35262 100644
--- a/sw/source/core/edit/editsh.cxx
+++ b/sw/source/core/edit/editsh.cxx
@@ -565,7 +565,7 @@ OUString SwEditShell::Calculate()
 
                     OUString sVar = aStr.copy( nTmpStt, nPos - nTmpStt );
                     if( !::FindOperator( sVar ) &&
-                        (aCalc.GetVarTable().Find(sVar) ||
+                        (aCalc.GetVarTable().find(sVar) != 
aCalc.GetVarTable().end() ||
                          aCalc.VarLook( sVar )) )
                     {
                         if( !bValidFields )
diff --git a/sw/source/core/fields/expfld.cxx b/sw/source/core/fields/expfld.cxx
index 39467d9b7a61..434f67672903 100644
--- a/sw/source/core/fields/expfld.cxx
+++ b/sw/source/core/fields/expfld.cxx
@@ -371,7 +371,7 @@ void SwGetExpField::ChangeExpansion( const SwFrame& rFrame, 
const SwTextField& r
     SetGetExpField aEndField(aPos.GetNode(), &rField, aPos.GetContentIndex(), 
rFrame.GetPhyPageNum());
     if(GetSubType() & nsSwGetSetExpType::GSE_STRING)
     {
-        SwHashTable<HashStr> aHashTable(0);
+        std::unordered_map<OUString, OUString> aHashTable;
         rDoc.getIDocumentFieldsAccess().FieldsToExpand(aHashTable, aEndField, 
rLayout);
         rExpand = LookString( aHashTable, GetFormula() );
     }
diff --git a/sw/source/core/inc/DocumentFieldsManager.hxx 
b/sw/source/core/inc/DocumentFieldsManager.hxx
index 75f2926474c8..accf7a53e83c 100644
--- a/sw/source/core/inc/DocumentFieldsManager.hxx
+++ b/sw/source/core/inc/DocumentFieldsManager.hxx
@@ -57,7 +57,7 @@ public:
     virtual void SetFixFields(const DateTime* pNewDateTime) override;
     virtual void FieldsToCalc(SwCalc& rCalc, SwNodeOffset nLastNd, sal_Int32 
nLastCnt) override;
     virtual void FieldsToCalc(SwCalc& rCalc, const SetGetExpField& 
rToThisField, SwRootFrame const* pLayout) override;
-    virtual void FieldsToExpand(SwHashTable<HashStr>& rTable, const 
SetGetExpField& rToThisField, SwRootFrame const& rLayout) override;
+    virtual void FieldsToExpand(std::unordered_map<OUString, OUString>& 
rTable, const SetGetExpField& rToThisField, SwRootFrame const& rLayout) 
override;
     virtual bool IsNewFieldLst() const override;
     virtual void SetNewFieldLst( bool bFlag) override;
     virtual void InsDelFieldInFieldLst(bool bIns, const SwTextField& rField) 
override;
diff --git a/sw/source/core/inc/docfld.hxx b/sw/source/core/inc/docfld.hxx
index a96dccabdc1b..f09116978fb5 100644
--- a/sw/source/core/inc/docfld.hxx
+++ b/sw/source/core/inc/docfld.hxx
@@ -118,24 +118,18 @@ class SetGetExpFields : public 
o3tl::sorted_vector<std::unique_ptr<SetGetExpFiel
 {
 };
 
-// struct for saving strings from the SetExp's string fields
-struct HashStr final : public SwHash
-{
-    OUString aSetStr;
-    HashStr( const OUString& rName, OUString aText, HashStr* );
-};
 
-struct SwCalcFieldType final : public SwHash
-{
-    const SwFieldType* pFieldType;
-
-    SwCalcFieldType( const OUString& rStr, const SwFieldType* pFieldTyp )
-        : SwHash( rStr ), pFieldType( pFieldTyp )
-    {}
-};
+//struct SwCalcFieldType final : public SwHash
+//{
+//    const SwFieldType* pFieldType;
+//
+//    SwCalcFieldType( const OUString& rStr, const SwFieldType* pFieldTyp )
+//        : SwHash( rStr ), pFieldType( pFieldTyp )
+//    {}
+//};
 
 // search for the string that was saved under rName in the hash table
-OUString LookString( SwHashTable<HashStr> const & rTable, const OUString& 
rName );
+OUString LookString( std::unordered_map<OUString,OUString> const & rTable, 
const OUString& rName );
 
 const int GETFLD_ALL        = 3;        // combine flags via OR
 const int GETFLD_CALC       = 1;
@@ -144,7 +138,7 @@ const int GETFLD_EXPAND     = 2;
 class SwDocUpdateField
 {
     std::unique_ptr<SetGetExpFields> m_pFieldSortList; ///< current field list 
for calculation
-    SwHashTable<SwCalcFieldType> m_FieldTypeTable;
+    std::unordered_multimap<OUString, const SwFieldType*> m_FieldTypeTable;
 
     SwNodeOffset m_nNodes; ///< to check if the node count changed
     int m_nFieldListGetMode;
@@ -185,7 +179,8 @@ public:
         }
     }
 
-    SwHashTable<SwCalcFieldType> const& GetFieldTypeTable() const { return 
m_FieldTypeTable; }
+    std::unordered_multimap<OUString, const SwFieldType*> const& 
GetFieldTypeTable() const { return m_FieldTypeTable; }
+    std::unordered_multimap<OUString, const SwFieldType*> & 
GetFieldTypeTable() { return m_FieldTypeTable; }
 };
 
 #endif

Reply via email to