tdf#81765 slow loading of .ods with >1000 of conditional formats, part 3

This takes the loading time from 14s to 13s

Use a o3tl::sorted_vector to reduce searching time

Change-Id: I947a3e5001fe1058cf9bffc9509d026af4122ef4
Reviewed-on: https://gerrit.libreoffice.org/71035
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
diff --git a/sc/inc/attrib.hxx b/sc/inc/attrib.hxx
index e03d1a2..cecc587 100644
--- a/sc/inc/attrib.hxx
+++ b/sc/inc/attrib.hxx
@@ -25,6 +25,7 @@
#include <svl/poolitem.hxx>
#include <svl/intitem.hxx>
#include <svl/eitem.hxx>
#include <o3tl/sorted_vector.hxx>
#include <o3tl/typed_flags_set.hxx>
#include "scdllapi.h"
#include "global.hxx"
@@ -260,11 +261,15 @@
    sal_uInt16                  mnHeight;
};

typedef o3tl::sorted_vector<sal_uInt32> ScCondFormatIndexes;

class ScCondFormatItem : public SfxPoolItem
{
public:
    explicit ScCondFormatItem();
    explicit ScCondFormatItem(const std::vector<sal_uInt32>& nIndex);
    explicit ScCondFormatItem(sal_uInt32 nIndex);
    explicit ScCondFormatItem(const ScCondFormatIndexes& );
    explicit ScCondFormatItem(ScCondFormatIndexes&& );

    virtual ~ScCondFormatItem() override;

@@ -273,14 +278,12 @@
    virtual bool            IsSortable() const override { return true; }
    virtual ScCondFormatItem*  Clone( SfxItemPool* = nullptr ) const override;

    const std::vector<sal_uInt32>& GetCondFormatData() const { return maIndex;}
    void AddCondFormatData( sal_uInt32 nIndex );
    void SetCondFormatData( const std::vector<sal_uInt32>& aIndex );
    const ScCondFormatIndexes& GetCondFormatData() const { return maIndex;}

    virtual void dumpAsXml(xmlTextWriterPtr pWriter) const override;

private:
    std::vector<sal_uInt32> maIndex;
    ScCondFormatIndexes maIndex;
};

#endif
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 615760e..3d6b87b 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -36,6 +36,7 @@
#include "calcmacros.hxx"
#include "calcconfig.hxx"
#include <o3tl/deleter.hxx>
#include <o3tl/sorted_vector.hxx>
#include <svl/hint.hxx>
#include <svl/typedwhich.hxx>
#include <svl/zforlist.hxx>
@@ -195,6 +196,7 @@
class BitmapEx;
class ScColumnsRange;
struct ScFilterEntries;
typedef o3tl::sorted_vector<sal_uInt32> ScCondFormatIndexes;

namespace sc {

@@ -1693,7 +1695,7 @@
    SC_DLLPUBLIC const SfxItemSet*          GetCondResult( SCCOL nCol, SCROW nRow, SCTAB nTab ) const;
    const SfxItemSet*                       GetCondResult( ScRefCellValue& rCell, const ScAddress& rPos,
                                                           const ScConditionalFormatList& rList,
                                                           const std::vector<sal_uInt32>& rIndex ) const;
                                                           const ScCondFormatIndexes& rIndex ) const;
    const SfxPoolItem*                      GetEffItem( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_uInt16 nWhich ) const;
    template<class T> const T*              GetEffItem( SCCOL nCol, SCROW nRow, SCTAB nTab, TypedWhichId<T> nWhich ) const
    {
diff --git a/sc/qa/unit/ucalc_condformat.cxx b/sc/qa/unit/ucalc_condformat.cxx
index 836f5bc..7392943 100644
--- a/sc/qa/unit/ucalc_condformat.cxx
+++ b/sc/qa/unit/ucalc_condformat.cxx
@@ -305,7 +305,7 @@

    CPPUNIT_ASSERT(pCondFormatItem);
    CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem->GetCondFormatData().size());
    CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex), pCondFormatItem->GetCondFormatData().at(0));
    CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex), pCondFormatItem->GetCondFormatData().front());

    m_pDoc->DeleteTab(0);
}
@@ -344,7 +344,7 @@

    CPPUNIT_ASSERT(pCondFormatItem);
    CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem->GetCondFormatData().size());
    CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex), pCondFormatItem->GetCondFormatData().at(0) );
    CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex), pCondFormatItem->GetCondFormatData().front() );

    m_pDoc->DeleteTab(0);
}
@@ -387,7 +387,7 @@

            CPPUNIT_ASSERT(pCondFormatItem);
            CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem->GetCondFormatData().size());
            CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex), pCondFormatItem->GetCondFormatData().at(0) );
            CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex), pCondFormatItem->GetCondFormatData().front() );
        }
    }

@@ -426,7 +426,7 @@

    CPPUNIT_ASSERT(pCondFormatItem);
    CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem->GetCondFormatData().size());
    CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex), pCondFormatItem->GetCondFormatData().at(0));
    CPPUNIT_ASSERT_EQUAL(sal_uInt32(nIndex), pCondFormatItem->GetCondFormatData().front());

    m_pDoc->DeleteTab(0);
}
@@ -542,7 +542,7 @@

    CPPUNIT_ASSERT(pCondFormatItem);
    CPPUNIT_ASSERT_EQUAL(size_t(1), pCondFormatItem->GetCondFormatData().size());
    CPPUNIT_ASSERT_EQUAL( nKey, pCondFormatItem->GetCondFormatData().at(0) );
    CPPUNIT_ASSERT_EQUAL( nKey, pCondFormatItem->GetCondFormatData().front() );

    m_pDoc->DeleteTab(1);
    m_pDoc->DeleteTab(0);
diff --git a/sc/source/core/data/attarray.cxx b/sc/source/core/data/attarray.cxx
index 282f6ce..7559331 100644
--- a/sc/source/core/data/attarray.cxx
+++ b/sc/source/core/data/attarray.cxx
@@ -299,24 +299,29 @@
            nTempEndRow = std::min<SCROW>( nPatternEndRow, nEndRow );
            const SfxPoolItem* pItem = nullptr;
            pPattern->GetItemSet().GetItemState( ATTR_CONDITIONAL, true, &pItem );
            std::vector< sal_uInt32 > aCondFormatData;
            if(pItem)
                aCondFormatData = static_cast<const ScCondFormatItem*>(pItem)->GetCondFormatData();
            if (std::find(aCondFormatData.begin(), aCondFormatData.end(), nIndex)
                == aCondFormatData.end())
            {
                aCondFormatData.push_back(nIndex);

                ScCondFormatItem aItem;
                aItem.SetCondFormatData( aCondFormatData );
                ScCondFormatIndexes const & rCondFormatData = static_cast<const ScCondFormatItem*>(pItem)->GetCondFormatData();
                if (rCondFormatData.find(nIndex) == rCondFormatData.end())
                {
                    ScCondFormatIndexes aNewCondFormatData;
                    aNewCondFormatData.reserve(rCondFormatData.size()+1);
                    aNewCondFormatData = rCondFormatData;
                    aNewCondFormatData.insert(nIndex);
                    ScCondFormatItem aItem( std::move(aNewCondFormatData) );
                    pNewPattern->GetItemSet().Put( aItem );
                }
            }
            else
            {
                ScCondFormatItem aItem(nIndex);
                pNewPattern->GetItemSet().Put( aItem );
            }
        }
        else
        {
            pNewPattern.reset( new ScPatternAttr( pDocument->GetPool() ) );
            ScCondFormatItem aItem;
            aItem.AddCondFormatData(nIndex);
            ScCondFormatItem aItem(nIndex);
            pNewPattern->GetItemSet().Put( aItem );
            nTempEndRow = nEndRow;
        }
@@ -355,19 +360,25 @@
            if(pItem)
            {
                auto pPatternAttr = std::make_unique<ScPatternAttr>( *pPattern );
                std::vector< sal_uInt32 > aCondFormatData = static_cast<const ScCondFormatItem*>(pItem)->GetCondFormatData();
                std::vector<sal_uInt32>::iterator itr = std::find(aCondFormatData.begin(), aCondFormatData.end(), nIndex);
                if(itr != aCondFormatData.end() || nIndex == 0)
                if (nIndex == 0)
                {
                    ScCondFormatItem aItem;
                    if (nIndex == 0)
                        aCondFormatData.clear();
                    else
                        aCondFormatData.erase(itr);
                    aItem.SetCondFormatData( aCondFormatData );
                    pPatternAttr->GetItemSet().Put( aItem );
                    SetPatternArea( nTempStartRow, nTempEndRow, std::move(pPatternAttr), true );
                }
                else
                {
                    ScCondFormatIndexes const & rCondFormatData = static_cast<const ScCondFormatItem*>(pItem)->GetCondFormatData();
                    auto itr = rCondFormatData.find(nIndex);
                    if(itr != rCondFormatData.end())
                    {
                        ScCondFormatIndexes aNewCondFormatData(rCondFormatData);
                        aNewCondFormatData.erase(nIndex);
                        ScCondFormatItem aItem( std::move(aNewCondFormatData) );
                        pPatternAttr->GetItemSet().Put( aItem );
                        SetPatternArea( nTempStartRow, nTempEndRow, std::move(pPatternAttr), true );
                    }
                }
            }
        }
        else
diff --git a/sc/source/core/data/attrib.cxx b/sc/source/core/data/attrib.cxx
index 37c9c51..cf6a616 100644
--- a/sc/source/core/data/attrib.cxx
+++ b/sc/source/core/data/attrib.cxx
@@ -670,12 +670,24 @@
{
}

ScCondFormatItem::ScCondFormatItem( const std::vector<sal_uInt32>& rIndex ):
ScCondFormatItem::ScCondFormatItem( sal_uInt32 nIndex ):
    SfxPoolItem( ATTR_CONDITIONAL )
{
    maIndex.insert(nIndex);
}

ScCondFormatItem::ScCondFormatItem( const ScCondFormatIndexes& rIndex ):
    SfxPoolItem( ATTR_CONDITIONAL ),
    maIndex( rIndex )
{
}

ScCondFormatItem::ScCondFormatItem( ScCondFormatIndexes&& aIndex ):
    SfxPoolItem( ATTR_CONDITIONAL ),
    maIndex( std::move(aIndex) )
{
}

ScCondFormatItem::~ScCondFormatItem()
{
}
@@ -683,9 +695,11 @@
bool ScCondFormatItem::operator==( const SfxPoolItem& rCmp ) const
{
    auto const & other = static_cast<const ScCondFormatItem&>(rCmp);
    if (maIndex.empty() && other.maIndex.empty())
        return true;
    // memcmp is faster than operator< on std::vector
    return maIndex.size() == other.maIndex.size()
        && memcmp(maIndex.data(), other.maIndex.data(), maIndex.size() * sizeof(sal_uInt32)) == 0;
        && memcmp(&maIndex.front(), &other.maIndex.front(), maIndex.size() * sizeof(sal_uInt32)) == 0;
}

bool ScCondFormatItem::operator<( const SfxPoolItem& rCmp ) const
@@ -695,8 +709,10 @@
        return true;
    if ( maIndex.size() > other.maIndex.size() )
        return false;
    if (maIndex.empty() && other.maIndex.empty())
        return false;
    // memcmp is faster than operator< on std::vector
    return memcmp(maIndex.data(), other.maIndex.data(), maIndex.size() * sizeof(sal_uInt32)) < 0;
    return memcmp(&maIndex.front(), &other.maIndex.front(), maIndex.size() * sizeof(sal_uInt32)) < 0;
}

ScCondFormatItem* ScCondFormatItem::Clone(SfxItemPool*) const
@@ -704,16 +720,6 @@
    return new ScCondFormatItem(maIndex);
}

void ScCondFormatItem::AddCondFormatData( sal_uInt32 nIndex )
{
    maIndex.push_back(nIndex);
}

void ScCondFormatItem::SetCondFormatData( const std::vector<sal_uInt32>& rIndex )
{
    maIndex = rIndex;
}

void ScCondFormatItem::dumpAsXml(xmlTextWriterPtr pWriter) const
{
    xmlTextWriterStartElement(pWriter, BAD_CAST("ScCondFormatItem"));
diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx
index 8e728cb..a760f14 100644
--- a/sc/source/core/data/column3.cxx
+++ b/sc/source/core/data/column3.cxx
@@ -771,7 +771,7 @@
    {
        const ScCondFormatItem& rItem =
            pPattern->GetItem(ATTR_CONDITIONAL);
        const std::vector<sal_uInt32>& rData = rItem.GetCondFormatData();
        const ScCondFormatIndexes& rData = rItem.GetCondFormatData();
        pCondSet = pDocument->GetCondResult(aCell, aPos, *pCFList, rData);
    }

diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index 162537f..d0e5471 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -1009,7 +1009,7 @@
        {
            maPos.SetRow(nRow);
            const ScCondFormatItem& rItem = pPat->GetItem(ATTR_CONDITIONAL);
            const std::vector<sal_uInt32>& rData = rItem.GetCondFormatData();
            const ScCondFormatIndexes& rData = rItem.GetCondFormatData();
            pCondSet = mrCol.GetDoc()->GetCondResult(rCell, maPos, *mpCFList, rData);
        }

diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx
index b89f2f3..a1f5a68 100644
--- a/sc/source/core/data/documen4.cxx
+++ b/sc/source/core/data/documen4.cxx
@@ -752,7 +752,7 @@
        const SfxPoolItem* pItem;
        if ( rSet.GetItemState( ATTR_CONDITIONAL, true, &pItem ) == SfxItemState::SET )
        {
            const std::vector<sal_uInt32>& rIndex = pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData();
            const ScCondFormatIndexes& rIndex = pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData();
            ScConditionalFormatList* pCondFormList = GetCondFormList( nTab );
            if (!rIndex.empty() && pCondFormList)
            {
@@ -791,7 +791,7 @@
    ScAddress aPos(nCol, nRow, nTab);
    ScRefCellValue aCell(const_cast<ScDocument&>(*this), aPos);
    const ScPatternAttr* pPattern = GetPattern( nCol, nRow, nTab );
    const std::vector<sal_uInt32>& rIndex =
    const ScCondFormatIndexes& rIndex =
        pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData();

    return GetCondResult(aCell, aPos, *pFormatList, rIndex);
@@ -799,7 +799,7 @@

const SfxItemSet* ScDocument::GetCondResult(
    ScRefCellValue& rCell, const ScAddress& rPos, const ScConditionalFormatList& rList,
    const std::vector<sal_uInt32>& rIndex ) const
    const ScCondFormatIndexes& rIndex ) const
{
    for (const auto& rItem : rIndex)
    {
@@ -827,7 +827,7 @@
                            SCCOL nCol, SCROW nRow, SCTAB nTab ) const
{
    sal_uInt32 nIndex = 0;
    const std::vector<sal_uInt32>& rCondFormats = GetAttr(nCol, nRow, nTab, ATTR_CONDITIONAL)->GetCondFormatData();
    const ScCondFormatIndexes& rCondFormats = GetAttr(nCol, nRow, nTab, ATTR_CONDITIONAL)->GetCondFormatData();

    if(!rCondFormats.empty())
        nIndex = rCondFormats[0];
diff --git a/sc/source/core/data/fillinfo.cxx b/sc/source/core/data/fillinfo.cxx
index 678709a..aef2e64 100644
--- a/sc/source/core/data/fillinfo.cxx
+++ b/sc/source/core/data/fillinfo.cxx
@@ -272,7 +272,7 @@
    }
}

bool handleConditionalFormat(ScConditionalFormatList& rCondFormList, const std::vector<sal_uInt32>& rCondFormats,
bool handleConditionalFormat(ScConditionalFormatList& rCondFormList, const ScCondFormatIndexes& rCondFormats,
        CellInfo* pInfo, ScStyleSheetPool* pStlPool,
        const ScAddress& rAddr, bool& bHidden, bool& bHideFormula, bool bTabProtect)
{
@@ -522,7 +522,7 @@
                        else
                            bHidden = bHideFormula = false;

                        const std::vector<sal_uInt32>& rCondFormats = pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData();
                        const ScCondFormatIndexes& rCondFormats = pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData();
                        bool bContainsCondFormat = !rCondFormats.empty();

                        do
diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index f465624..2cff749 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -2181,7 +2181,7 @@
                    //  Run through all formats, so that each cell does not have to be
                    //  handled individually

                    const std::vector<sal_uInt32>& rCondFormatData = static_cast<const ScCondFormatItem*>(pCondItem)->GetCondFormatData();
                    const ScCondFormatIndexes& rCondFormatData = static_cast<const ScCondFormatItem*>(pCondItem)->GetCondFormatData();
                    ScStyleSheetPool* pStylePool = pDocument->GetStyleSheetPool();
                    if (mpCondFormatList && pStylePool && !rCondFormatData.empty())
                    {
diff --git a/sc/source/core/data/table4.cxx b/sc/source/core/data/table4.cxx
index 4175459..d0e8bb3 100644
--- a/sc/source/core/data/table4.cxx
+++ b/sc/source/core/data/table4.cxx
@@ -631,7 +631,7 @@
                }

                const ScCondFormatItem& rCondFormatItem = pSrcPattern->GetItem(ATTR_CONDITIONAL);
                const std::vector<sal_uInt32>& rCondFormatIndex = rCondFormatItem.GetCondFormatData();
                const ScCondFormatIndexes& rCondFormatIndex = rCondFormatItem.GetCondFormatData();

                if ( bVertical && nISrcStart == nISrcEnd && !bHasFiltered )
                {
@@ -1648,7 +1648,7 @@
            const ScPatternAttr* pSrcPattern = aCol[nCol].GetPattern(static_cast<SCROW>(nRow));

            const ScCondFormatItem& rCondFormatItem = pSrcPattern->GetItem(ATTR_CONDITIONAL);
            const std::vector<sal_uInt32>& rCondFormatIndex = rCondFormatItem.GetCondFormatData();
            const ScCondFormatIndexes& rCondFormatIndex = rCondFormatItem.GetCondFormatData();

            if (bVertical)
            {
diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
index af0c061..0c726ab 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -2551,7 +2551,7 @@
                            formula::FormulaGrammar::Grammar eGrammar = (bXML ?
                                    rDoc.GetStorageGrammar() :
                                   formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML));
                            const std::vector<sal_uInt32>& rIndex =
                            const ScCondFormatIndexes& rIndex =
                                    pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData();
                            sal_uLong nIndex = 0;
                            if(!rIndex.empty())
diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx
index 2301430..fdeadf5 100644
--- a/sc/source/ui/view/cellsh1.cxx
+++ b/sc/source/ui/view/cellsh1.cxx
@@ -1962,7 +1962,7 @@
                const ScConditionalFormat* pCondFormat = nullptr;
                const ScPatternAttr* pPattern = pDoc->GetPattern(aPos.Col(), aPos.Row(), aPos.Tab());
                ScConditionalFormatList* pList = pDoc->GetCondFormList(aPos.Tab());
                const std::vector<sal_uInt32>& rCondFormats = pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData();
                const ScCondFormatIndexes& rCondFormats = pPattern->GetItem(ATTR_CONDITIONAL).GetCondFormatData();
                bool bContainsCondFormat = !rCondFormats.empty();
                bool bCondFormatDlg = false;
                bool bContainsExistingCondFormat = false;