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;