sc/source/filter/excel/xestyle.cxx |   79 +++++++++++++++++++++++++++----------
 sc/source/filter/inc/xestyle.hxx   |   27 ++++++++++++
 2 files changed, 85 insertions(+), 21 deletions(-)

New commits:
commit cb15e56dfd4e3443467c0b54522023bbe03505e9
Author:     Noel Grandin <noel.gran...@collabora.co.uk>
AuthorDate: Fri Oct 25 08:55:51 2019 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Fri Oct 25 12:01:50 2019 +0200

    tdf#126021 speed up saving xls with lots of styles
    
    extend the find-map so we can do partial-match searching.
    Makes it 10x faster for me.
    
    Change-Id: I1952a221a919707af078fac9fd1eb63781d9188d
    Reviewed-on: https://gerrit.libreoffice.org/81488
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>
    (cherry picked from commit c0b8be4d7eb9fa1a0d8abfb1d27c71ac34bffd1b)
    Reviewed-on: https://gerrit.libreoffice.org/81489

diff --git a/sc/source/filter/excel/xestyle.cxx 
b/sc/source/filter/excel/xestyle.cxx
index 3ab025d0cb60..e4109a908468 100644
--- a/sc/source/filter/excel/xestyle.cxx
+++ b/sc/source/filter/excel/xestyle.cxx
@@ -2666,24 +2666,58 @@ void XclExpXFBuffer::SaveXFXml( XclExpXmlStream& rStrm, 
XclExpXF& rXF )
 sal_uInt32 XclExpXFBuffer::FindXF( const ScPatternAttr& rPattern,
         sal_uInt32 nForceScNumFmt, sal_uInt16 nForceXclFont, bool 
bForceLineBreak ) const
 {
-    auto it = maXFFindMap.find(&rPattern.GetItemSet());
-    if (it == maXFFindMap.end())
-        return EXC_XFID_NOTFOUND;
-    for (auto const & nPos : it->second)
-        if( maXFList.GetRecord( nPos )->Equals( rPattern, nForceScNumFmt, 
nForceXclFont, bForceLineBreak ) )
-            return nPos;
+    if (nForceScNumFmt != NUMBERFORMAT_ENTRY_NOT_FOUND && nForceXclFont == 
EXC_FONT_NOTFOUND)
+    {
+        FindKey key1 { /*mbCellXF*/true, &rPattern.GetItemSet(), 
nForceScNumFmt, 0 };
+        FindKey key2 { /*mbCellXF*/true, &rPattern.GetItemSet(), 
nForceScNumFmt, EXC_FONT_NOTFOUND };
+        auto it1 = maXFFindMap.lower_bound(key1);
+        if (it1 != maXFFindMap.end())
+        {
+            auto it2 = maXFFindMap.upper_bound(key2);
+            for (auto it = it1; it != it2; ++it)
+                for (auto const & nPos : it->second)
+                    if( maXFList.GetRecord( nPos )->Equals( rPattern, 
nForceScNumFmt, nForceXclFont, bForceLineBreak ) )
+                        return nPos;
+        }
+    }
+    else if (nForceScNumFmt == NUMBERFORMAT_ENTRY_NOT_FOUND || nForceXclFont 
== EXC_FONT_NOTFOUND)
+    {
+        FindKey key1 { /*mbCellXF*/true, &rPattern.GetItemSet(), 0, 0 };
+        FindKey key2 { /*mbCellXF*/true, &rPattern.GetItemSet(), 
NUMBERFORMAT_ENTRY_NOT_FOUND, EXC_FONT_NOTFOUND };
+        auto it1 = maXFFindMap.lower_bound(key1);
+        if (it1 != maXFFindMap.end())
+        {
+            auto it2 = maXFFindMap.upper_bound(key2);
+            for (auto it = it1; it != it2; ++it)
+                for (auto const & nPos : it->second)
+                    if( maXFList.GetRecord( nPos )->Equals( rPattern, 
nForceScNumFmt, nForceXclFont, bForceLineBreak ) )
+                        return nPos;
+        }
+    }
+    else
+    {
+        FindKey key { /*mbCellXF*/true, &rPattern.GetItemSet(), 
nForceScNumFmt, nForceXclFont };
+        auto it = maXFFindMap.find(key);
+        if (it == maXFFindMap.end())
+            return EXC_XFID_NOTFOUND;
+        for (auto const & nPos : it->second)
+            if( maXFList.GetRecord( nPos )->Equals( rPattern, nForceScNumFmt, 
nForceXclFont, bForceLineBreak ) )
+                return nPos;
+    }
     return EXC_XFID_NOTFOUND;
 }
 
 sal_uInt32 XclExpXFBuffer::FindXF( const SfxStyleSheetBase& rStyleSheet ) const
 {
     const SfxItemSet* pItemSet = &const_cast< SfxStyleSheetBase& >( 
rStyleSheet ).GetItemSet();
-    auto it = maXFFindMap.find(pItemSet);
-    if (it == maXFFindMap.end())
-        return EXC_XFID_NOTFOUND;
-    for (auto const & nPos : it->second)
-        if( maXFList.GetRecord( nPos )->Equals( rStyleSheet ) )
-            return nPos;
+    FindKey key1 { /*mbCellXF*/false, pItemSet, 0, 0 };
+    FindKey key2 { /*mbCellXF*/false, pItemSet, NUMBERFORMAT_ENTRY_NOT_FOUND, 
EXC_FONT_NOTFOUND };
+    auto it1 = maXFFindMap.lower_bound(key1);
+    auto it2 = maXFFindMap.upper_bound(key2);
+    for (auto it = it1; it != it2; ++it)
+        for (auto const & nPos : it->second)
+            if( maXFList.GetRecord( nPos )->Equals( rStyleSheet ) )
+                return nPos;
     return EXC_XFID_NOTFOUND;
 }
 
@@ -2698,6 +2732,11 @@ sal_uInt32 XclExpXFBuffer::FindBuiltInXF( sal_uInt8 
nStyleId, sal_uInt8 nLevel )
     return EXC_XFID_NOTFOUND;
 }
 
+XclExpXFBuffer::FindKey XclExpXFBuffer::ToFindKey(XclExpXF const & rRec)
+{
+    return { rRec.IsCellXF(), rRec.GetItemSet(), rRec.GetScNumFmt(), 
rRec.GetXclFont() };
+}
+
 sal_uInt32 XclExpXFBuffer::InsertCellXF( const ScPatternAttr* pPattern, 
sal_Int16 nScript,
         sal_uInt32 nForceScNumFmt, sal_uInt16 nForceXclFont, bool 
bForceLineBreak )
 {
@@ -2715,14 +2754,14 @@ sal_uInt32 XclExpXFBuffer::InsertCellXF( const 
ScPatternAttr* pPattern, sal_Int1
         if( rbPredefined )
         {
             // remove old entry in find-map
-            auto & rPositions = 
maXFFindMap[maXFList.GetRecord(EXC_XF_DEFAULTCELL)->GetItemSet()];
+            auto & rPositions = 
maXFFindMap[ToFindKey(*maXFList.GetRecord(EXC_XF_DEFAULTCELL))];
             auto it = std::find(rPositions.begin(), rPositions.end(), 
EXC_XF_DEFAULTCELL);
             rPositions.erase(it);
             // replace default cell pattern
             XclExpXFRef xNewXF( new XclExpXF( GetRoot(), *pPattern, nScript ) 
);
             maXFList.ReplaceRecord( xNewXF, EXC_XF_DEFAULTCELL );
             // and add new entry in find-map
-            maXFFindMap[xNewXF->GetItemSet()].push_back(EXC_XF_DEFAULTCELL);
+            maXFFindMap[ToFindKey(*xNewXF)].push_back(EXC_XF_DEFAULTCELL);
             rbPredefined = false;
         }
         return GetDefCellXFId();
@@ -2739,7 +2778,7 @@ sal_uInt32 XclExpXFBuffer::InsertCellXF( const 
ScPatternAttr* pPattern, sal_Int1
             maXFList.AppendNewRecord( pNewExp );
             // do not set nXFId before the AppendNewRecord() call - it may 
insert 2 XFs (style+cell)
             nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() - 1 );
-            maXFFindMap[pNewExp->GetItemSet()].push_back(nXFId);
+            maXFFindMap[ToFindKey(*pNewExp)].push_back(nXFId);
         }
         else
         {
@@ -2775,14 +2814,14 @@ sal_uInt32 XclExpXFBuffer::InsertStyleXF( const 
SfxStyleSheetBase& rStyleSheet )
             if( rbPredefined )
             {
                 // remove old entry in find-map
-                auto & rPositions = 
maXFFindMap[maXFList.GetRecord(nXFId)->GetItemSet()];
+                auto & rPositions = 
maXFFindMap[ToFindKey(*maXFList.GetRecord(nXFId))];
                 auto it = std::find(rPositions.begin(), rPositions.end(), 
nXFId);
                 rPositions.erase(it);
                 // replace predefined built-in style (ReplaceRecord() deletes 
old record)
                 auto pNewExp = std::make_shared<XclExpXF>( GetRoot(), 
rStyleSheet );
                 maXFList.ReplaceRecord( pNewExp, nXFId );
                 // and add new entry in find-map
-                maXFFindMap[pNewExp->GetItemSet()].push_back(nXFId);
+                maXFFindMap[ToFindKey(*pNewExp)].push_back(nXFId);
                 rbPredefined = false;
             }
         }
@@ -2812,7 +2851,7 @@ sal_uInt32 XclExpXFBuffer::InsertStyleXF( const 
SfxStyleSheetBase& rStyleSheet )
             // create the STYLE record
             if( !rStyleSheet.GetName().isEmpty() )
                 maStyleList.AppendNewRecord( new XclExpStyle( nXFId, 
rStyleSheet.GetName() ) );
-            maXFFindMap[pNewExp->GetItemSet()].push_back(nXFId);
+            maXFFindMap[ToFindKey(*pNewExp)].push_back(nXFId);
         }
         else
             // list full - fall back to default style XF
@@ -2833,7 +2872,7 @@ sal_uInt32 XclExpXFBuffer::AppendBuiltInXF( XclExpXFRef 
const & xXF, sal_uInt8 n
 {
     sal_uInt32 nXFId = static_cast< sal_uInt32 >( maXFList.GetSize() );
     maXFList.AppendRecord( xXF );
-    maXFFindMap[xXF->GetItemSet()].push_back(nXFId);
+    maXFFindMap[ToFindKey(*xXF)].push_back(nXFId);
     XclExpBuiltInInfo& rInfo = maBuiltInMap[ nXFId ];
     rInfo.mnStyleId = nStyleId;
     rInfo.mnLevel = nLevel;
@@ -2906,7 +2945,7 @@ void XclExpXFBuffer::InsertDefaultRecords()
 
     // index 15: default hard cell format, placeholder to be able to add more 
built-in styles
     maXFList.AppendNewRecord( new XclExpDefaultXF( GetRoot(), true ) );
-    
maXFFindMap[maXFList.GetRecord(maXFList.GetSize()-1)->GetItemSet()].push_back(maXFList.GetSize()-1);
+    
maXFFindMap[ToFindKey(*maXFList.GetRecord(maXFList.GetSize()-1))].push_back(maXFList.GetSize()-1);
     maBuiltInMap[ EXC_XF_DEFAULTCELL ].mbPredefined = true;
 
     // index 16-20: other built-in styles
diff --git a/sc/source/filter/inc/xestyle.hxx b/sc/source/filter/inc/xestyle.hxx
index 48b1e53f4fa2..ae960530e80c 100644
--- a/sc/source/filter/inc/xestyle.hxx
+++ b/sc/source/filter/inc/xestyle.hxx
@@ -30,6 +30,7 @@
 #include <fonthelper.hxx>
 #include <memory>
 #include <vector>
+#include <o3tl/sorted_vector.hxx>
 
 /* ============================================================================
 - Buffers for style records (PALETTE, FONT, FORMAT, XF, STYLE).
@@ -470,6 +471,9 @@ public:
 
     const SfxItemSet*   GetItemSet() const { return mpItemSet; }
 
+    sal_uInt32          GetScNumFmt() const { return mnScNumFmt; }
+    sal_uInt16          GetXclFont() const { return mnXclFont; }
+
 protected:
     explicit            XclExpXF( const XclExpRoot& rRoot, bool bCellXF );
 
@@ -681,8 +685,29 @@ private:
     typedef ::std::vector< XclExpCellBorder >           XclExpBorderList;
     typedef ::std::vector< XclExpCellArea >             XclExpFillList;
 
+    /** composite key for the find-map, so we can do partial key searching */
+    struct FindKey
+    {
+        bool mbCellXF; // is this a hard cell format, or a cell style
+        const SfxItemSet* mpItemSet;
+        sal_uInt32 mnScNumFmt;
+        sal_uInt16 mnXclFont;
+
+        bool operator<(const FindKey& other) const
+        {
+            if (mbCellXF != other.mbCellXF)
+                return mbCellXF < other.mbCellXF;
+            if (mpItemSet != other.mpItemSet)
+                return mpItemSet < other.mpItemSet;
+            if (mnScNumFmt != other.mnScNumFmt)
+                return mnScNumFmt < other.mnScNumFmt;
+            return mnXclFont < other.mnXclFont;
+        }
+    };
+    static FindKey ToFindKey(XclExpXF const &);
+
     XclExpXFList        maXFList;           /// List of all XF records.
-    std::unordered_map<const SfxItemSet*, std::vector<sal_uInt32>>
+    std::map<FindKey, std::vector<sal_uInt32>>
                         maXFFindMap;        /// map of itemset to vector of 
positions, to speed up find
     XclExpStyleList     maStyleList;        /// List of all STYLE records.
     XclExpBuiltInMap    maBuiltInMap;       /// Contained elements describe 
built-in XFs.
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to