tdf#158556 speed up SwNodes::RemoveNode
Change-Id: I49daf93793c67da6261081fce92e1fed1a71248b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165139
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
diff --git a/sw/inc/bparr.hxx b/sw/inc/bparr.hxx
index 9f3e17f..4f831c8 100644
--- a/sw/inc/bparr.hxx
+++ b/sw/inc/bparr.hxx
@@ -91,6 +91,11 @@ public:
void Move( sal_Int32 from, sal_Int32 to );
void Replace( sal_Int32 pos, BigPtrEntry* p);
/** Speed up the complicated removal logic in SwNodes::RemoveNode.
Returns the entry before pNotTheOne.
*/
BigPtrEntry* ReplaceTheOneAfter( BigPtrEntry* pNotTheOne, BigPtrEntry* pNewEntry);
SW_DLLPUBLIC BigPtrEntry* operator[]( sal_Int32 ) const;
};
diff --git a/sw/source/core/bastyp/bparr.cxx b/sw/source/core/bastyp/bparr.cxx
index b99385b..03e035c 100644
--- a/sw/source/core/bastyp/bparr.cxx
+++ b/sw/source/core/bastyp/bparr.cxx
@@ -397,6 +397,47 @@ void BigPtrArray::Replace( sal_Int32 idx, BigPtrEntry* pElem)
p->mvData[ idx - p->nStart ] = pElem;
}
/** Speed up the complicated removal logic in SwNodes::RemoveNode.
Replaces the node AFTER pNotTheOne.
Returns the entry BEFORE pNotTheOne.
*/
BigPtrEntry* BigPtrArray::ReplaceTheOneAfter( BigPtrEntry* pNotTheOne, BigPtrEntry* pNewEntry)
{
assert(pNotTheOne->m_pBlock->pBigArr == this);
BlockInfo* p = pNotTheOne->m_pBlock;
sal_uInt16 nOffset = pNotTheOne->m_nOffset;
// if the next node is inside the current block
if (nOffset < p->nElem - 1)
{
++nOffset;
p->mvData[nOffset] = pNewEntry;
pNewEntry->m_nOffset = nOffset;
pNewEntry->m_pBlock = p;
--nOffset;
}
else
{
// slow path
BigPtrArray::Replace( pNotTheOne->GetPos()+1, pNewEntry );
}
// if the previous node is inside the current block
if (nOffset != 0)
{
--nOffset;
return p->mvData[nOffset];
}
else
{
// slow path
sal_Int32 nPrevPos = pNotTheOne->GetPos();
if (nPrevPos == 0)
return nullptr;
return BigPtrArray::operator[]( nPrevPos - 1 );
}
}
/** Compress the array */
sal_uInt16 BigPtrArray::Compress()
{
diff --git a/sw/source/core/docnode/nodes.cxx b/sw/source/core/docnode/nodes.cxx
index 0e2a0bc..5f059f9 100644
--- a/sw/source/core/docnode/nodes.cxx
+++ b/sw/source/core/docnode/nodes.cxx
@@ -2413,14 +2413,8 @@ void SwNodes::RemoveNode( SwNodeOffset nDelPos, SwNodeOffset nSz, bool bDel )
delete pDel;
// coverity[use_after_free : FALSE] - pPrev will be reassigned if there will be another iteration to the loop
pDel = pPrev;
sal_uLong nPrevNdIdx = pPrev->GetPos();
BigPtrEntry* pTempEntry = &aTempEntries[sal_Int32(nCnt)];
BigPtrArray::Replace( nPrevNdIdx+1, pTempEntry );
if( nCnt )
pPrev = BigPtrArray::operator []( nPrevNdIdx - 1 );
// the accessed element can be a naked BigPtrEntry from
// aTempEntries, so the downcast to SwNode* in
// SwNodes::operator[] would be illegal (and unnecessary)
pPrev = ReplaceTheOneAfter(pPrev, pTempEntry);
}
nDelPos = SwNodeOffset(pDel->GetPos() + 1);
}