include/svl/nfengine.hxx                   |   28 +++--
 include/svl/numformat.hxx                  |    2 
 sc/inc/interpretercontext.hxx              |    7 +
 sc/source/core/data/document.cxx           |    1 
 sc/source/core/tool/interpretercontext.cxx |   15 ++
 svl/source/numbers/zforlist.cxx            |  162 ++++++++++++++++++-----------
 6 files changed, 148 insertions(+), 67 deletions(-)

New commits:
commit e8e0a3b1d7e706330ca343cf9dd5ba062e9ff0c4
Author:     Caolán McNamara <caolan.mcnam...@collabora.com>
AuthorDate: Thu Mar 28 09:55:06 2024 +0000
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Fri Mar 29 09:51:12 2024 +0100

    crashtesting: fix SvNFEngine::CacheFormatRO assert
    
    since:
    
    commit c6c6126aa3e8de256091b829b98b5943db6a8be6
    Author: Caolán McNamara <caolan.mcnam...@collabora.com>
    Date:   Thu Mar 21 17:25:35 2024 +0000
    
        Related: tdf#160056 refactor SvNumberFormatter
    
        to split it into two constituent parts
    
    Change-Id: I4add9f383789ab03ceab751b07973448a41911ba
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165490
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/include/svl/nfengine.hxx b/include/svl/nfengine.hxx
index a4890e074d1a..c0b463c189f3 100644
--- a/include/svl/nfengine.hxx
+++ b/include/svl/nfengine.hxx
@@ -159,10 +159,12 @@ private:
 
 class SVL_DLLPUBLIC SvNFFormatData
 {
+public:
+    typedef std::map<sal_uInt32, sal_uInt32> DefaultFormatKeysMap;
+
 private:
     typedef std::map<sal_uInt32, std::unique_ptr<SvNumberformat>> 
FormatEntryMap;
     FormatEntryMap aFTable; // Table of format keys to format entries
-    typedef std::map<sal_uInt32, sal_uInt32> DefaultFormatKeysMap;
     DefaultFormatKeysMap aDefaultFormatKeys; // Table of default standard to 
format keys
     sal_uInt32 MaxCLOffset; // Max language/country offset used
     sal_uInt32 nDefaultSystemCurrencyFormat; // NewCurrency matching SYSTEM 
locale
@@ -190,6 +192,8 @@ public:
     bool GetNewCurrencySymbolString(sal_uInt32 nFormat, OUString& rSymbol,
                                     const NfCurrencyEntry** ppEntry, bool* 
pBank = nullptr) const;
 
+    void MergeDefaultFormatKeys(const DefaultFormatKeysMap& 
rDefaultFormatKeys);
+
 private:
     SvNFFormatData(const SvNFFormatData&) = delete;
     SvNFFormatData& operator=(const SvNFFormatData&) = delete;
@@ -262,8 +266,7 @@ private:
     SVL_DLLPRIVATE sal_uInt32 
ImpGetDefaultSystemCurrencyFormat(SvNFLanguageData& rCurrentLanguage,
                                                                 const 
NativeNumberWrapper* pNatNum);
 
-    SVL_DLLPRIVATE std::pair<sal_uInt32, bool>
-    ImpGetDefaultFormat(SvNumFormatType nType, sal_uInt32 nSearch, sal_uInt32 
CLOffset) const;
+    SVL_DLLPRIVATE sal_uInt32 FindCachedDefaultFormat(sal_uInt32 nSearch) 
const;
 
     SVL_DLLPRIVATE static sal_Int32
     ImpGetFormatCodeIndex(const SvNFLanguageData& rCurrentLanguage,
@@ -282,6 +285,7 @@ public:
                                      const NativeNumberWrapper* pNatNum, 
LanguageType eLnge)>
         GetCLOffset;
     typedef std::function<void(sal_uInt32 nSearch, sal_uInt32 nFormat)> 
CacheFormat;
+    typedef std::function<sal_uInt32(sal_uInt32 nSearch)> FindFormat;
 
     typedef std::function<sal_uInt32(SvNFLanguageData& rCurrentLanguage,
                                      const NativeNumberWrapper* pNatNum, 
sal_uInt32 CLOffset,
@@ -292,11 +296,13 @@ public:
     {
         GetCLOffset mGetCLOffset;
         CacheFormat mCacheFormat;
+        FindFormat mFindFormat;
         GetDefaultCurrency mGetDefaultCurrency;
     };
 
     static Accessor GetRWPolicy(SvNFFormatData& rFormatData);
-    static Accessor GetROPolicy(const SvNFFormatData& rFormatData);
+    static Accessor GetROPolicy(const SvNFFormatData& rFormatData,
+                                SvNFFormatData::DefaultFormatKeysMap& 
rFormatCache);
 
     static void ChangeIntl(SvNFLanguageData& rCurrentLanguage, LanguageType 
eLnge);
     static void ChangeNullDate(SvNFLanguageData& rCurrentLanguage, sal_uInt16 
nDay,
@@ -403,9 +409,12 @@ public:
                                    bool IsRed, sal_uInt16 nPrecision, 
sal_uInt16 nLeadingZeros);
 
 private:
-    static sal_uInt32 ImpGetDefaultFormat(const SvNFFormatData& rFormatData,
-                                          const SvNFEngine::CacheFormat& rFunc,
+    static sal_uInt32 ImpGetDefaultFormat(const SvNFFormatData& rFormatData, 
const Accessor& rFuncs,
                                           SvNumFormatType nType, sal_uInt32 
CLOffset);
+
+    static sal_uInt32 ImpGetDefaultFormat(const SvNFFormatData& rFormatData, 
SvNumFormatType nType,
+                                          sal_uInt32 CLOffset);
+
     static sal_uInt32
     ImpGetStandardFormat(SvNFLanguageData& rCurrentLanguage, const 
SvNFFormatData& rFormatData,
                          const NativeNumberWrapper* pNatNum, const 
SvNFEngine::Accessor& rFuncs,
@@ -425,8 +434,13 @@ private:
                                     const NativeNumberWrapper*, LanguageType 
eLnge);
 
     static void CacheFormatRW(SvNFFormatData& rFormatData, sal_uInt32 nSearch, 
sal_uInt32 nFormat);
-    static void CacheFormatRO(const SvNFFormatData& rFormatData, sal_uInt32 
nSearch,
+    static void CacheFormatRO(SvNFFormatData::DefaultFormatKeysMap& rMap, 
sal_uInt32 nSearch,
                               sal_uInt32 nFormat);
+
+    static sal_uInt32 FindFormatRW(const SvNFFormatData& rFormatData, 
sal_uInt32 nSearch);
+    static sal_uInt32 FindFormatRO(const SvNFFormatData& rFormatData,
+                                   const SvNFFormatData::DefaultFormatKeysMap& 
rMap,
+                                   sal_uInt32 nSearch);
 };
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/svl/numformat.hxx b/include/svl/numformat.hxx
index b26e245ca8d5..92f93bb1562a 100644
--- a/include/svl/numformat.hxx
+++ b/include/svl/numformat.hxx
@@ -507,6 +507,8 @@ public:
         language/country, used in XML import */
     OUString GetStandardName(LanguageType eLnge);
 
+    void MergeDefaultFormatKeys(const SvNFFormatData::DefaultFormatKeysMap& 
rDefaultFormatKeys);
+
     /** Check if a specific locale has supported locale data. */
     static bool IsLocaleInstalled(LanguageType eLang);
 
diff --git a/sc/inc/interpretercontext.hxx b/sc/inc/interpretercontext.hxx
index 2f89249a21a6..ead9b04c06c7 100644
--- a/sc/inc/interpretercontext.hxx
+++ b/sc/inc/interpretercontext.hxx
@@ -112,6 +112,8 @@ struct ScInterpreterContext
 
     OUString NFGetCalcCellReturn(sal_uInt32 nFormat) const;
 
+    void MergeDefaultFormatKeys(SvNumberFormatter& rFormatter) const;
+
 private:
     friend class ScInterpreterContextPool;
     void ResetTokens();
@@ -125,6 +127,11 @@ private:
     // the NumberFormat's data and a throw-away object for currently used 
language
     // This is essentially an exploded view of mpFormatter
     std::unique_ptr<SvNFLanguageData> mxLanguageData;
+    // FormatData can be driven read-only, but may want to cache some data,
+    // in RO Mode we can cache per thread to mxAuxFormatKeyMap, and
+    // discard or merge after threaded calculation is over
+    std::unique_ptr<SvNFFormatData::DefaultFormatKeysMap> mxAuxFormatKeyMap;
+
     const SvNFFormatData* mpFormatData;
     SvNFEngine::Accessor maROPolicy;
 
diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx
index 04370b62117f..e87d100b36da 100644
--- a/sc/source/core/data/document.cxx
+++ b/sc/source/core/data/document.cxx
@@ -6929,6 +6929,7 @@ void 
ScDocument::MergeContextBackIntoNonThreadedContext(ScInterpreterContext& th
         
std::make_move_iterator(threadedContext.maDelayedSetNumberFormat.begin()),
         
std::make_move_iterator(threadedContext.maDelayedSetNumberFormat.end()));
     // lookup cache is now only in pooled ScInterpreterContext's
+    threadedContext.MergeDefaultFormatKeys(*GetFormatTable());
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/tool/interpretercontext.cxx 
b/sc/source/core/tool/interpretercontext.cxx
index f4fde3725414..e1fc5fb24252 100644
--- a/sc/source/core/tool/interpretercontext.cxx
+++ b/sc/source/core/tool/interpretercontext.cxx
@@ -46,8 +46,9 @@ ScInterpreterContext::ScInterpreterContext(const ScDocument& 
rDoc, SvNumberForma
     else
     {
         mxLanguageData.reset(new 
SvNFLanguageData(pFormatter->GetROLanguageData()));
+        mxAuxFormatKeyMap.reset(new SvNFFormatData::DefaultFormatKeysMap);
         mpFormatData = &pFormatter->GetROFormatData();
-        maROPolicy = SvNFEngine::GetROPolicy(*mpFormatData);
+        maROPolicy = SvNFEngine::GetROPolicy(*mpFormatData, 
*mxAuxFormatKeyMap);
     }
 }
 
@@ -74,8 +75,9 @@ void ScInterpreterContext::SetDocAndFormatter(const 
ScDocument& rDoc, SvNumberFo
     {
         // formatter has changed
         mxLanguageData.reset(new 
SvNFLanguageData(pFormatter->GetROLanguageData()));
+        mxAuxFormatKeyMap.reset(new SvNFFormatData::DefaultFormatKeysMap);
         mpFormatData = &pFormatter->GetROFormatData();
-        maROPolicy = SvNFEngine::GetROPolicy(*mpFormatData);
+        maROPolicy = SvNFEngine::GetROPolicy(*mpFormatData, 
*mxAuxFormatKeyMap);
         mpFormatter = pFormatter;
 
         // drop cache
@@ -88,8 +90,14 @@ void ScInterpreterContext::initFormatTable()
 {
     mpFormatter = mpDoc->GetFormatTable(); // will assert if not main thread
     mpFormatData = &mpFormatter->GetROFormatData();
-    maROPolicy = SvNFEngine::GetROPolicy(*mpFormatData);
     mxLanguageData.reset(new 
SvNFLanguageData(mpFormatter->GetROLanguageData()));
+    mxAuxFormatKeyMap.reset(new SvNFFormatData::DefaultFormatKeysMap);
+    maROPolicy = SvNFEngine::GetROPolicy(*mpFormatData, *mxAuxFormatKeyMap);
+}
+
+void ScInterpreterContext::MergeDefaultFormatKeys(SvNumberFormatter& 
rFormatter) const
+{
+    rFormatter.MergeDefaultFormatKeys(*mxAuxFormatKeyMap);
 }
 
 void ScInterpreterContext::Cleanup()
@@ -106,6 +114,7 @@ void ScInterpreterContext::ClearLookupCache(const 
ScDocument* pDoc)
     {
         mxScLookupCache.reset();
         mxLanguageData.reset();
+        mxAuxFormatKeyMap.reset();
         mpFormatter = nullptr;
         mpFormatData = nullptr;
     }
diff --git a/svl/source/numbers/zforlist.cxx b/svl/source/numbers/zforlist.cxx
index 9a4490849d11..7b2bcd4352e7 100644
--- a/svl/source/numbers/zforlist.cxx
+++ b/svl/source/numbers/zforlist.cxx
@@ -1537,17 +1537,19 @@ static sal_uInt32 ImpGetSearchOffset(SvNumFormatType 
nType, sal_uInt32 CLOffset)
     return nSearch;
 }
 
+// static
 sal_uInt32 SvNFEngine::ImpGetDefaultFormat(const SvNFFormatData& rFormatData,
-                                           const SvNFEngine::CacheFormat& 
rFunc,
+                                           const SvNFEngine::Accessor& rFuncs,
                                            SvNumFormatType nType, sal_uInt32 
CLOffset)
 {
     sal_uInt32 nSearch = ImpGetSearchOffset(nType, CLOffset);
 
-    std::pair<sal_uInt32, bool> aRes = rFormatData.ImpGetDefaultFormat(nType, 
nSearch, CLOffset);
-    const sal_uInt32 nDefaultFormat = aRes.first;
-    const bool bShouldCache = aRes.second;
-    if (bShouldCache)
-        rFunc(nSearch, nDefaultFormat);
+    sal_uInt32 nDefaultFormat = rFuncs.mFindFormat(nSearch);
+    if (nDefaultFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
+        return nDefaultFormat;
+
+    nDefaultFormat = ImpGetDefaultFormat(rFormatData, nType, CLOffset);
+    rFuncs.mCacheFormat(nSearch, nDefaultFormat);
     return nDefaultFormat;
 }
 
@@ -1602,7 +1604,7 @@ sal_uInt32 
SvNFEngine::ImpGetStandardFormat(SvNFLanguageData& rCurrentLanguage,
     case SvNumFormatType::DATETIME:
     case SvNumFormatType::PERCENT:
     case SvNumFormatType::SCIENTIFIC:
-        return ImpGetDefaultFormat(rFormatData, rFuncs.mCacheFormat, eType, 
CLOffset);
+        return ImpGetDefaultFormat(rFormatData, rFuncs, eType, CLOffset);
     case SvNumFormatType::FRACTION:
         return CLOffset + ZF_STANDARD_FRACTION;
     case SvNumFormatType::LOGICAL:
@@ -1669,59 +1671,70 @@ sal_uInt32 
SvNFEngine::GetStandardFormat(SvNFLanguageData& rCurrentLanguage,
     return ImpGetStandardFormat(rCurrentLanguage, rFormatData, pNatNum, 
rFuncs, eType, nCLOffset, eLnge);
 }
 
-//return a std::pair with the result and true/false if that result should be 
cached in aDefaultFormatKeys
-std::pair<sal_uInt32, bool> 
SvNFFormatData::ImpGetDefaultFormat(SvNumFormatType nType, sal_uInt32 nSearch, 
sal_uInt32 CLOffset) const
+namespace
 {
-    bool bShouldCache = false;
-    DefaultFormatKeysMap::const_iterator it = aDefaultFormatKeys.find(nSearch);
-    sal_uInt32 nDefaultFormat = (it != aDefaultFormatKeys.end() ?
-                                 it->second : NUMBERFORMAT_ENTRY_NOT_FOUND);
-    if ( nDefaultFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
+    sal_uInt32 FindCachedDefaultFormat(const 
SvNFFormatData::DefaultFormatKeysMap& rDefaultFormatKeys, sal_uInt32 nSearch)
     {
-        // look for a defined standard
-        sal_uInt32 nStopKey = CLOffset + SV_COUNTRY_LANGUAGE_OFFSET;
-        sal_uInt32 nKey(0);
-        auto it2 = aFTable.find( CLOffset );
-        while ( it2 != aFTable.end() && (nKey = it2->first ) >= CLOffset && 
nKey < nStopKey )
+        auto it = rDefaultFormatKeys.find(nSearch);
+        sal_uInt32 nDefaultFormat = (it != rDefaultFormatKeys.end() ?
+                                     it->second : 
NUMBERFORMAT_ENTRY_NOT_FOUND);
+        return nDefaultFormat;
+    }
+}
+
+sal_uInt32 SvNFFormatData::FindCachedDefaultFormat(sal_uInt32 nSearch) const
+{
+    return ::FindCachedDefaultFormat(aDefaultFormatKeys, nSearch);
+}
+
+// static
+sal_uInt32 SvNFEngine::ImpGetDefaultFormat(const SvNFFormatData& rFormatData, 
SvNumFormatType nType, sal_uInt32 CLOffset)
+{
+    sal_uInt32 nDefaultFormat = NUMBERFORMAT_ENTRY_NOT_FOUND;
+
+    // look for a defined standard
+    sal_uInt32 nStopKey = CLOffset + SV_COUNTRY_LANGUAGE_OFFSET;
+    sal_uInt32 nKey(0);
+    auto it2 = rFormatData.aFTable.find( CLOffset );
+    while ( it2 != rFormatData.aFTable.end() && (nKey = it2->first ) >= 
CLOffset && nKey < nStopKey )
+    {
+        const SvNumberformat* pEntry = it2->second.get();
+        if ( pEntry->IsStandard() && (pEntry->GetMaskedType() == nType) )
         {
-            const SvNumberformat* pEntry = it2->second.get();
-            if ( pEntry->IsStandard() && (pEntry->GetMaskedType() == nType) )
-            {
-                nDefaultFormat = nKey;
-                break;  // while
-            }
-            ++it2;
+            nDefaultFormat = nKey;
+            break;  // while
         }
+        ++it2;
+    }
 
-        if ( nDefaultFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
-        {   // none found, use old fixed standards
-            switch( nType )
-            {
-            case SvNumFormatType::DATE:
-                nDefaultFormat = CLOffset + ZF_STANDARD_DATE;
-                break;
-            case SvNumFormatType::TIME:
-                nDefaultFormat = CLOffset + ZF_STANDARD_TIME+1;
-                break;
-            case SvNumFormatType::DATETIME:
-                nDefaultFormat = CLOffset + ZF_STANDARD_DATETIME;
-                break;
-            case SvNumFormatType::DURATION:
-                nDefaultFormat = CLOffset + ZF_STANDARD_DURATION;
-                break;
-            case SvNumFormatType::PERCENT:
-                nDefaultFormat = CLOffset + ZF_STANDARD_PERCENT+1;
-                break;
-            case SvNumFormatType::SCIENTIFIC:
-                nDefaultFormat = CLOffset + ZF_STANDARD_SCIENTIFIC;
-                break;
-            default:
-                nDefaultFormat = CLOffset + ZF_STANDARD;
-            }
+    if ( nDefaultFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
+    {   // none found, use old fixed standards
+        switch( nType )
+        {
+        case SvNumFormatType::DATE:
+            nDefaultFormat = CLOffset + ZF_STANDARD_DATE;
+            break;
+        case SvNumFormatType::TIME:
+            nDefaultFormat = CLOffset + ZF_STANDARD_TIME+1;
+            break;
+        case SvNumFormatType::DATETIME:
+            nDefaultFormat = CLOffset + ZF_STANDARD_DATETIME;
+            break;
+        case SvNumFormatType::DURATION:
+            nDefaultFormat = CLOffset + ZF_STANDARD_DURATION;
+            break;
+        case SvNumFormatType::PERCENT:
+            nDefaultFormat = CLOffset + ZF_STANDARD_PERCENT+1;
+            break;
+        case SvNumFormatType::SCIENTIFIC:
+            nDefaultFormat = CLOffset + ZF_STANDARD_SCIENTIFIC;
+            break;
+        default:
+            nDefaultFormat = CLOffset + ZF_STANDARD;
         }
-        bShouldCache = true;
     }
-    return std::make_pair(nDefaultFormat, bShouldCache);
+
+    return nDefaultFormat;
 }
 
 sal_uInt32 SvNumberFormatter::GetStandardFormat( sal_uInt32 nFIndex, 
SvNumFormatType eType,
@@ -3912,9 +3925,19 @@ sal_uInt32 SvNFEngine::GetCLOffsetRO(const 
SvNFFormatData& rFormatData, SvNFLang
     return nCLOffset;
 }
 
-void SvNFEngine::CacheFormatRO(const SvNFFormatData&, sal_uInt32, sal_uInt32)
+// we can't cache to SvNFFormatData in RO mode, so cache to a temp map which 
we can consult pre-thread in FindFormatRO
+// caches can be merged with SvNumberFormatter::MergeDefaultFormatKeys
+void SvNFEngine::CacheFormatRO(SvNFFormatData::DefaultFormatKeysMap& 
rFormatCache, sal_uInt32 nSearch, sal_uInt32 nFormat)
 {
-    assert(false && "not really fatal, just not cached");
+    rFormatCache[nSearch] = nFormat;
+}
+
+sal_uInt32 SvNFEngine::FindFormatRO(const SvNFFormatData& rFormatData, const 
SvNFFormatData::DefaultFormatKeysMap& rFormatCache, sal_uInt32 nSearch)
+{
+    sal_uInt32 nFormat = rFormatData.FindCachedDefaultFormat(nSearch);
+    if (nFormat != NUMBERFORMAT_ENTRY_NOT_FOUND)
+        return nFormat;
+    return ::FindCachedDefaultFormat(rFormatCache, nSearch);
 }
 
 sal_uInt32 SvNFEngine::GetCLOffsetRW(SvNFFormatData& rFormatData, 
SvNFLanguageData& rCurrentLanguage, const NativeNumberWrapper* pNatNum, 
LanguageType eLnge)
@@ -3927,6 +3950,11 @@ void SvNFEngine::CacheFormatRW(SvNFFormatData& 
rFormatData, sal_uInt32 nSearch,
     rFormatData.aDefaultFormatKeys[nSearch] = nFormat;
 }
 
+sal_uInt32 SvNFEngine::FindFormatRW(const SvNFFormatData& rFormatData, 
sal_uInt32 nSearch)
+{
+    return rFormatData.FindCachedDefaultFormat(nSearch);
+}
+
 sal_uInt32 SvNFEngine::DefaultCurrencyRW(SvNFFormatData& rFormatData, 
SvNFLanguageData& rCurrentLanguage, const NativeNumberWrapper* pNatNum, 
sal_uInt32 CLOffset, LanguageType eLnge)
 {
     if (eLnge == LANGUAGE_SYSTEM)
@@ -3953,16 +3981,18 @@ SvNFEngine::Accessor 
SvNFEngine::GetRWPolicy(SvNFFormatData& rFormatData)
     {
         std::bind(SvNFEngine::GetCLOffsetRW, std::ref(rFormatData), 
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3),
         std::bind(SvNFEngine::CacheFormatRW, std::ref(rFormatData), 
std::placeholders::_1, std::placeholders::_2),
+        std::bind(SvNFEngine::FindFormatRW, std::ref(rFormatData), 
std::placeholders::_1),
         std::bind(SvNFEngine::DefaultCurrencyRW, std::ref(rFormatData), 
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, 
std::placeholders::_4)
     };
 }
 
-SvNFEngine::Accessor SvNFEngine::GetROPolicy(const SvNFFormatData& rFormatData)
+SvNFEngine::Accessor SvNFEngine::GetROPolicy(const SvNFFormatData& 
rFormatData, SvNFFormatData::DefaultFormatKeysMap& rFormatCache)
 {
     return
     {
         std::bind(SvNFEngine::GetCLOffsetRO, std::ref(rFormatData), 
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3),
-        std::bind(SvNFEngine::CacheFormatRO, std::ref(rFormatData), 
std::placeholders::_1, std::placeholders::_2),
+        std::bind(SvNFEngine::CacheFormatRO, std::ref(rFormatCache), 
std::placeholders::_1, std::placeholders::_2),
+        std::bind(SvNFEngine::FindFormatRO, std::ref(rFormatData), 
std::ref(rFormatCache), std::placeholders::_1),
         std::bind(SvNFEngine::DefaultCurrencyRO, std::ref(rFormatData), 
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, 
std::placeholders::_4)
     };
 }
@@ -4355,6 +4385,24 @@ bool SvNumberFormatter::ImpLookupCurrencyEntryLoopBody(
     return true;
 }
 
+void SvNFFormatData::MergeDefaultFormatKeys(const DefaultFormatKeysMap& 
rDefaultFormatKeys)
+{
+    for (const auto& r : rDefaultFormatKeys)
+    {
+#ifndef NDEBUG
+        auto iter = aDefaultFormatKeys.find(r.first);
+        assert(iter == aDefaultFormatKeys.end() || iter->second == r.second);
+#endif
+        aDefaultFormatKeys[r.first] = r.second;
+    }
+}
+
+void SvNumberFormatter::MergeDefaultFormatKeys(const 
SvNFFormatData::DefaultFormatKeysMap& rDefaultFormatKeys)
+{
+    ::osl::MutexGuard aGuard( GetInstanceMutex() );
+    m_aFormatData.MergeDefaultFormatKeys(rDefaultFormatKeys);
+}
+
 bool SvNFFormatData::GetNewCurrencySymbolString(sal_uInt32 nFormat, OUString& 
rStr,
                                                 const NfCurrencyEntry** 
ppEntry /* = NULL */,
                                                 bool* pBank /* = NULL */) const

Reply via email to