tdf#158773 add a set to sd::ShapeList

because the std::list is atrociously bad at checking if the element
already exists when the number of shapes gets large.

Shaves 5% off the load time

Change-Id: I6b8f972f8ff9559c363c084d91adea88b1267d3f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/164597
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
diff --git a/sd/inc/shapelist.hxx b/sd/inc/shapelist.hxx
index 6528cc0..c933448 100644
--- a/sd/inc/shapelist.hxx
+++ b/sd/inc/shapelist.hxx
@@ -23,6 +23,7 @@
#include <svx/sdrobjectuser.hxx>

#include <list>
#include <unordered_set>

namespace sd
{
@@ -65,6 +66,7 @@ namespace sd
        typedef std::list< SdrObject* > ListImpl;
        ListImpl maShapeList;
        ListImpl::iterator maIter;
        std::unordered_set<const SdrObject*> maShapeSet;
    };
}

diff --git a/sd/source/core/shapelist.cxx b/sd/source/core/shapelist.cxx
index 613286c..a73044b 100644
--- a/sd/source/core/shapelist.cxx
+++ b/sd/source/core/shapelist.cxx
@@ -38,8 +38,7 @@ ShapeList::~ShapeList()
/** adds the given shape to this list */
void ShapeList::addShape( SdrObject& rObject )
{
    ListImpl::iterator aIter( std::find( maShapeList.begin(), maShapeList.end(), &rObject ) );
    if( aIter == maShapeList.end() )
    if( maShapeSet.insert(&rObject).second )
    {
        maShapeList.push_back(&rObject);
        rObject.AddObjectUser( *this );
@@ -53,9 +52,9 @@ void ShapeList::addShape( SdrObject& rObject )
/** removes the given shape from this list */
void ShapeList::removeShape( SdrObject& rObject )
{
    ListImpl::iterator aIter( std::find( maShapeList.begin(), maShapeList.end(), &rObject ) );
    if( aIter != maShapeList.end() )
    if( maShapeSet.erase(&rObject) )
    {
        ListImpl::iterator aIter( std::find( maShapeList.begin(), maShapeList.end(), &rObject ) );
        bool bIterErased = aIter == maIter;

        (*aIter)->RemoveObjectUser(*this);
@@ -76,6 +75,7 @@ void ShapeList::clear()
{
    ListImpl aShapeList;
    aShapeList.swap( maShapeList );
    maShapeSet.clear();

    for( auto& rpShape : aShapeList )
        rpShape->RemoveObjectUser(*this);
@@ -92,14 +92,14 @@ bool ShapeList::isEmpty() const
/** returns true if given shape is part of this list */
bool ShapeList::hasShape( SdrObject& rObject ) const
{
    return std::find( maShapeList.begin(), maShapeList.end(), &rObject )  != maShapeList.end();
    return maShapeSet.contains( &rObject );
}

void ShapeList::ObjectInDestruction(const SdrObject& rObject)
{
    ListImpl::iterator aIter( std::find( maShapeList.begin(), maShapeList.end(), &rObject ) );
    if( aIter != maShapeList.end() )
    if( maShapeSet.erase(&rObject) )
    {
        ListImpl::iterator aIter( std::find( maShapeList.begin(), maShapeList.end(), &rObject ) );
        bool bIterErased = aIter == maIter;

        aIter = maShapeList.erase( aIter );