sw/inc/IMark.hxx                       |    5 ++++-
 sw/inc/contentindex.hxx                |   32 ++++++++++++++++++++++----------
 sw/inc/pam.hxx                         |    3 +--
 sw/inc/redline.hxx                     |    8 +++++---
 sw/source/core/bastyp/index.cxx        |   18 ++++++------------
 sw/source/core/crsr/bookmark.cxx       |    6 +++---
 sw/source/core/doc/docnew.cxx          |    4 ++--
 sw/source/core/doc/docredln.cxx        |   16 ++++++++--------
 sw/source/core/text/porlay.cxx         |    4 +++-
 sw/source/core/text/porrst.cxx         |    4 +++-
 sw/source/core/txtnode/ndtxt.cxx       |   13 ++++++++-----
 sw/source/core/unocore/unoportenum.cxx |    4 +++-
 12 files changed, 68 insertions(+), 49 deletions(-)

New commits:
commit f0a080babb9ae7bdd9eebc29343017606c5e18bf
Author:     Noel Grandin <noelgran...@gmail.com>
AuthorDate: Wed Aug 7 21:44:17 2024 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Mon Aug 12 13:08:42 2024 +0200

    SwContentIndex owner pointers
    
    we already have two things that "own" a SwContentIndex, for which
    we store a pointer in the SwContentIndex. I want to add more things,
    so rather than add more fields to a very heavily used structure,
    generalise the mechanism so we can store a single field (since
    only thing at a time will ever own a SwContentIndex).
    
    Also add an enum and a GetOwnerType() method so I can avoid
    dynamic_cast, this is a pretty performance-sensitive area.
    
    Change-Id: Ifb03a06b0bb69a325f41a8041e9d23cfc82c3268
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171606
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/sw/inc/IMark.hxx b/sw/inc/IMark.hxx
index 8aea5ea991f0..1a5aed926bfb 100644
--- a/sw/inc/IMark.hxx
+++ b/sw/inc/IMark.hxx
@@ -52,9 +52,12 @@ namespace sw::mark
     };
 
     class SW_DLLPUBLIC MarkBase
-        : virtual public sw::BroadcastingModify // inherited as interface
+        : public ISwContentIndexOwner,
+          virtual public sw::BroadcastingModify // inherited as interface
     {
     public:
+        virtual SwContentIndexOwnerType GetOwnerType() const override final { 
return SwContentIndexOwnerType::Mark; }
+
         //getters
         SwPosition& GetMarkPos() const
             { return const_cast<SwPosition&>(*m_oPos1); }
diff --git a/sw/inc/contentindex.hxx b/sw/inc/contentindex.hxx
index c433782d7e38..6e62d7538401 100644
--- a/sw/inc/contentindex.hxx
+++ b/sw/inc/contentindex.hxx
@@ -32,6 +32,17 @@ class SwRangeRedline;
 
 namespace sw::mark { class MarkBase; }
 
+/// enum to allow us to cast without dynamic_cast (for performance)
+enum class SwContentIndexOwnerType { Redline, Mark };
+
+/// Pure abstract class for a pointer to something that "owns" a SwContentIndex
+class ISwContentIndexOwner
+{
+public:
+    virtual ~ISwContentIndexOwner();
+    virtual SwContentIndexOwnerType GetOwnerType() const = 0;
+};
+
 /// Marks a character position inside a document model content node 
(SwContentNode)
 class SAL_WARN_UNUSED SW_DLLPUBLIC SwContentIndex
 {
@@ -44,11 +55,11 @@ private:
     SwContentIndex * m_pNext;
     SwContentIndex * m_pPrev;
 
-    /// points to the SwRangeRedline (if any) that contains this 
SwContentIndex, via SwPosition and SwPaM
-    SwRangeRedline * m_pRangeRedline = nullptr;
-
-    /// Pointer to a mark that owns this position to allow fast lookup of 
marks of an SwContentIndexReg.
-    const sw::mark::MarkBase* m_pMark;
+    /// This is either
+    /// (*) nullptr
+    /// (*) the SwRangeRedline (if any) that contains this SwContentIndex, via 
SwPosition and SwPaM
+    /// (*) the sw::mark::MarkBase that owns this position to allow fast 
lookup of marks of an SwContentIndexReg.
+    ISwContentIndexOwner * m_pOwner = nullptr;
 
     SwContentIndex& ChgValue( const SwContentIndex& rIdx, sal_Int32 nNewValue 
);
     void Init(sal_Int32 const nIdx);
@@ -103,11 +114,12 @@ public:
     const SwContentNode* GetContentNode() const { return m_pContentNode; }
     const SwContentIndex* GetNext() const { return m_pNext; }
 
-    const sw::mark::MarkBase* GetMark() const { return m_pMark; }
-    void SetMark(const sw::mark::MarkBase* pMark);
-
-    SwRangeRedline* GetRedline() const { return m_pRangeRedline; }
-    void SetRedline(SwRangeRedline* pRangeRedline) { m_pRangeRedline = 
pRangeRedline; }
+    ISwContentIndexOwner* GetOwner() const { return m_pOwner; }
+    void SetOwner(ISwContentIndexOwner* pOwner)
+    {
+        assert(m_pOwner == nullptr && "there can be only one owner");
+        m_pOwner = pOwner;
+    }
 };
 
 SW_DLLPUBLIC std::ostream& operator <<(std::ostream& s, const SwContentIndex& 
index);
diff --git a/sw/inc/pam.hxx b/sw/inc/pam.hxx
index c9bffacb2d65..0fe773aa95b8 100644
--- a/sw/inc/pam.hxx
+++ b/sw/inc/pam.hxx
@@ -83,8 +83,7 @@ struct SAL_WARN_UNUSED SW_DLLPUBLIC SwPosition
 
     const SwContentNode* GetContentNode() const { return 
nContent.GetContentNode(); }
     sal_Int32 GetContentIndex() const { return nContent.GetIndex(); }
-    void SetMark(const sw::mark::MarkBase* pMark) { nContent.SetMark(pMark); }
-    void SetRedline(SwRangeRedline* pRangeRedline) { 
nContent.SetRedline(pRangeRedline); }
+    void SetOwner(ISwContentIndexOwner* pOwner) { nContent.SetOwner(pOwner); }
 
     /// These all set both nNode and nContent
     void Assign( const SwNode& rNd, SwNodeOffset nDelta, sal_Int32 
nContentOffset = 0 );
diff --git a/sw/inc/redline.hxx b/sw/inc/redline.hxx
index ef7c8129ce6a..06ea78c6d37e 100644
--- a/sw/inc/redline.hxx
+++ b/sw/inc/redline.hxx
@@ -161,7 +161,7 @@ public:
     void dumpAsXml(xmlTextWriterPtr pWriter) const;
 };
 
-class SAL_DLLPUBLIC_RTTI SwRangeRedline final : public SwPaM
+class SAL_DLLPUBLIC_RTTI SwRangeRedline final : public SwPaM, public 
ISwContentIndexOwner
 {
     SwRedlineData* m_pRedlineData;
     std::optional<SwNodeIndex> m_oContentSect;
@@ -187,12 +187,14 @@ public:
         SwPaM( rPos ), m_pRedlineData( pData ),
         m_nId( s_nLastId++ ), m_bDelLastPara( bDelLP ), m_bIsVisible( true )
     {
-        GetBound().SetRedline(this);
-        GetBound(false).SetRedline(this);
+        GetBound().SetOwner(this);
+        GetBound(false).SetOwner(this);
     }
     SwRangeRedline( const SwRangeRedline& );
     virtual ~SwRangeRedline() override;
 
+    virtual SwContentIndexOwnerType GetOwnerType() const override final { 
return SwContentIndexOwnerType::Redline; }
+
     sal_uInt32 GetId() const { return m_nId; }
     const SwNodeIndex* GetContentIdx() const { return m_oContentSect ? 
&*m_oContentSect : nullptr; }
     // For Undo.
diff --git a/sw/source/core/bastyp/index.cxx b/sw/source/core/bastyp/index.cxx
index 4deeea8a7eb6..39eebfcd713e 100644
--- a/sw/source/core/bastyp/index.cxx
+++ b/sw/source/core/bastyp/index.cxx
@@ -24,12 +24,13 @@
 
 #include <crossrefbookmark.hxx>
 
+ISwContentIndexOwner::~ISwContentIndexOwner() {}
+
 SwContentIndex::SwContentIndex(const SwContentNode * pContentNode, sal_Int32 
const nIdx)
     : m_nIndex( nIdx )
     , m_pContentNode( const_cast<SwContentNode*>(pContentNode) )
     , m_pNext( nullptr )
     , m_pPrev( nullptr )
-    , m_pMark( nullptr )
 {
     Init(m_nIndex);
 }
@@ -38,7 +39,6 @@ SwContentIndex::SwContentIndex( const SwContentIndex& rIdx, 
short nDiff )
     : m_pContentNode( rIdx.m_pContentNode )
     , m_pNext( nullptr )
     , m_pPrev( nullptr )
-    , m_pMark( nullptr )
 {
     ChgValue( rIdx, rIdx.m_nIndex + nDiff );
 }
@@ -48,7 +48,6 @@ SwContentIndex::SwContentIndex( const SwContentIndex& rIdx )
     , m_pContentNode( rIdx.m_pContentNode )
     , m_pNext( nullptr )
     , m_pPrev( nullptr )
-    , m_pMark( nullptr )
 {
     ChgValue( rIdx, rIdx.m_nIndex );
 }
@@ -219,11 +218,6 @@ SwContentIndex& SwContentIndex::Assign( const 
SwContentNode* pArr, sal_Int32 nId
     return *this;
 }
 
-void SwContentIndex::SetMark(const sw::mark::MarkBase* pMark)
-{
-    m_pMark = pMark;
-}
-
 SwContentIndexReg::SwContentIndexReg()
     : m_pFirst( nullptr ), m_pLast( nullptr )
 {
@@ -270,11 +264,11 @@ void SwContentIndexReg::Update(
         while( pStt )
         {
             // HACK: avoid updating position of cross-ref bookmarks
-            if (!pStt->m_pMark || nullptr == dynamic_cast<
-                    ::sw::mark::CrossRefBookmark const*>(pStt->m_pMark))
-            {
+            if (pStt->m_pOwner && pStt->m_pOwner->GetOwnerType() == 
SwContentIndexOwnerType::Mark
+                && dynamic_cast< ::sw::mark::CrossRefBookmark 
const*>(pStt->m_pOwner))
+                ; // do nothing
+            else
                 pStt->m_nIndex = pStt->m_nIndex + nDiff;
-            }
             pStt = pStt->m_pNext;
         }
     }
diff --git a/sw/source/core/crsr/bookmark.cxx b/sw/source/core/crsr/bookmark.cxx
index 4e91f9ef987b..6f82c913735a 100644
--- a/sw/source/core/crsr/bookmark.cxx
+++ b/sw/source/core/crsr/bookmark.cxx
@@ -275,7 +275,7 @@ namespace sw::mark
         : m_oPos1(*aPaM.GetPoint())
         , m_aName(std::move(aName))
     {
-        m_oPos1->SetMark(this);
+        m_oPos1->SetOwner(this);
         lcl_FixPosition(*m_oPos1);
         if (aPaM.HasMark() && (*aPaM.GetMark() != *aPaM.GetPoint()))
         {
@@ -298,13 +298,13 @@ namespace sw::mark
     void MarkBase::SetMarkPos(const SwPosition& rNewPos)
     {
         m_oPos1.emplace(rNewPos);
-        m_oPos1->SetMark(this);
+        m_oPos1->SetOwner(this);
     }
 
     void MarkBase::SetOtherMarkPos(const SwPosition& rNewPos)
     {
         m_oPos2.emplace(rNewPos);
-        m_oPos2->SetMark(this);
+        m_oPos2->SetOwner(this);
     }
 
     OUString MarkBase::ToString( ) const
diff --git a/sw/source/core/doc/docnew.cxx b/sw/source/core/doc/docnew.cxx
index 51a8a3ddd487..eb3c68a9c148 100644
--- a/sw/source/core/doc/docnew.cxx
+++ b/sw/source/core/doc/docnew.cxx
@@ -1145,9 +1145,9 @@ SwNodeIndex SwDoc::AppendDoc(const SwDoc& rSource, 
sal_uInt16 const nStartPageNu
                 IDocumentMarkAccess* pMarkAccess = getIDocumentMarkAccess();
                 for (const SwContentIndex* pIndex = 
pTextNode->GetFirstIndex(); pIndex; pIndex = pIndex->GetNext())
                 {
-                    sw::mark::MarkBase* pMark = 
const_cast<sw::mark::MarkBase*>(pIndex->GetMark());
-                    if (!pMark)
+                    if (!pIndex->GetOwner() || 
pIndex->GetOwner()->GetOwnerType() != SwContentIndexOwnerType::Mark)
                         continue;
+                    sw::mark::MarkBase* pMark = 
static_cast<sw::mark::MarkBase*>(pIndex->GetOwner());
                     if (!aSeenMarks.insert(pMark).second)
                         continue;
                 }
diff --git a/sw/source/core/doc/docredln.cxx b/sw/source/core/doc/docredln.cxx
index 53c833bf915d..dd1350c0e133 100644
--- a/sw/source/core/doc/docredln.cxx
+++ b/sw/source/core/doc/docredln.cxx
@@ -1408,8 +1408,8 @@ SwRangeRedline::SwRangeRedline(RedlineType eTyp, const 
SwPaM& rPam, sal_uInt32 n
     ,
     m_nId( s_nLastId++ )
 {
-    GetBound().SetRedline(this);
-    GetBound(false).SetRedline(this);
+    GetBound().SetOwner(this);
+    GetBound(false).SetOwner(this);
 
     m_bDelLastPara = false;
     m_bIsVisible = true;
@@ -1432,8 +1432,8 @@ SwRangeRedline::SwRangeRedline( const SwRedlineData& 
rData, const SwPaM& rPam )
     m_pRedlineData( new SwRedlineData( rData )),
     m_nId( s_nLastId++ )
 {
-    GetBound().SetRedline(this);
-    GetBound(false).SetRedline(this);
+    GetBound().SetOwner(this);
+    GetBound(false).SetOwner(this);
 
     m_bDelLastPara = false;
     m_bIsVisible = true;
@@ -1456,8 +1456,8 @@ SwRangeRedline::SwRangeRedline( const SwRedlineData& 
rData, const SwPosition& rP
     m_pRedlineData( new SwRedlineData( rData )),
     m_nId( s_nLastId++ )
 {
-    GetBound().SetRedline(this);
-    GetBound(false).SetRedline(this);
+    GetBound().SetOwner(this);
+    GetBound(false).SetOwner(this);
 
     m_bDelLastPara = false;
     m_bIsVisible = true;
@@ -1468,8 +1468,8 @@ SwRangeRedline::SwRangeRedline( const SwRangeRedline& 
rCpy )
     m_pRedlineData( new SwRedlineData( *rCpy.m_pRedlineData )),
     m_nId( s_nLastId++ )
 {
-    GetBound().SetRedline(this);
-    GetBound(false).SetRedline(this);
+    GetBound().SetOwner(this);
+    GetBound(false).SetOwner(this);
 
     m_bDelLastPara = false;
     m_bIsVisible = true;
diff --git a/sw/source/core/text/porlay.cxx b/sw/source/core/text/porlay.cxx
index 2aec8f3b697f..c74310dda24a 100644
--- a/sw/source/core/text/porlay.cxx
+++ b/sw/source/core/text/porlay.cxx
@@ -2898,7 +2898,9 @@ void SwScriptInfo::selectHiddenTextProperty(const 
SwTextNode& rNode,
 
     for (const SwContentIndex* pIndex = rNode.GetFirstIndex(); pIndex; pIndex 
= pIndex->GetNext())
     {
-        const sw::mark::MarkBase* pMark = pIndex->GetMark();
+        if (!pIndex->GetOwner() || pIndex->GetOwner()->GetOwnerType() != 
SwContentIndexOwnerType::Mark)
+            continue;
+        auto const pMark = static_cast<sw::mark::MarkBase 
const*>(pIndex->GetOwner());
         const sw::mark::Bookmark* pBookmark = dynamic_cast<const 
sw::mark::Bookmark*>(pMark);
         if (pBookmarks && pBookmark)
         {
diff --git a/sw/source/core/text/porrst.cxx b/sw/source/core/text/porrst.cxx
index ba1cafce975d..bec5faf41f9c 100644
--- a/sw/source/core/text/porrst.cxx
+++ b/sw/source/core/text/porrst.cxx
@@ -471,7 +471,9 @@ bool SwTextFrame::FormatEmpty()
     for (SwContentIndex const* pIndex = GetTextNodeFirst()->GetFirstIndex();
          pIndex; pIndex = pIndex->GetNext())
     {
-        sw::mark::MarkBase const*const pMark = pIndex->GetMark();
+        if (!pIndex->GetOwner() || pIndex->GetOwner()->GetOwnerType() != 
SwContentIndexOwnerType::Mark)
+            continue;
+        auto const pMark = static_cast<sw::mark::MarkBase 
const*>(pIndex->GetOwner());
         if (dynamic_cast<const sw::mark::Bookmark*>(pMark) != nullptr)
         {   // need bookmark portions!
             return false;
diff --git a/sw/source/core/txtnode/ndtxt.cxx b/sw/source/core/txtnode/ndtxt.cxx
index e1d16d08114d..8c91d9c8b520 100644
--- a/sw/source/core/txtnode/ndtxt.cxx
+++ b/sw/source/core/txtnode/ndtxt.cxx
@@ -1450,9 +1450,12 @@ void SwTextNode::Update(
         const SwContentIndex* pContentNodeIndex = GetFirstIndex();
         while (pContentNodeIndex)
         {
-            SwRangeRedline* pRedl = pContentNodeIndex->GetRedline();
-            if (pRedl && (pRedl->HasMark() || this == 
&pRedl->GetPoint()->GetNode()))
-                vMyRedlines.insert(pRedl);
+            if (pContentNodeIndex->GetOwner() && 
pContentNodeIndex->GetOwner()->GetOwnerType() == 
SwContentIndexOwnerType::Redline)
+            {
+                auto pRedl = 
static_cast<SwRangeRedline*>(pContentNodeIndex->GetOwner());
+                if (pRedl && (pRedl->HasMark() || this == 
&pRedl->GetPoint()->GetNode()))
+                    vMyRedlines.insert(pRedl);
+            }
             pContentNodeIndex = pContentNodeIndex->GetNext();
         }
         for (SwRangeRedline* pRedl : vMyRedlines)
@@ -1497,9 +1500,9 @@ void SwTextNode::Update(
             for (const SwContentIndex* pIndex = GetFirstIndex(); pIndex; 
pIndex = next )
             {
                 next = pIndex->GetNext();
-                const sw::mark::MarkBase* pMark = pIndex->GetMark();
-                if (!pMark)
+                if (!pIndex->GetOwner() || pIndex->GetOwner()->GetOwnerType() 
!= SwContentIndexOwnerType::Mark)
                     continue;
+                auto const pMark = static_cast<sw::mark::MarkBase 
const*>(pIndex->GetOwner());
                 // filter out ones that cannot match to reduce the max size of 
aSeenMarks
                 const SwPosition* pMarkPos1 = &pMark->GetMarkPos();
                 const SwPosition* pMarkPos2 = pMark->IsExpanded() ? 
&pMark->GetOtherMarkPos() : nullptr;
diff --git a/sw/source/core/unocore/unoportenum.cxx 
b/sw/source/core/unocore/unoportenum.cxx
index 1a9bb475af1c..33a17b85eeb9 100644
--- a/sw/source/core/unocore/unoportenum.cxx
+++ b/sw/source/core/unocore/unoportenum.cxx
@@ -204,8 +204,10 @@ namespace
         o3tl::sorted_vector<const sw::mark::MarkBase*> aSeenMarks;
         for (const SwContentIndex* pIndex = pTextNode->GetFirstIndex(); 
pIndex; pIndex = pIndex->GetNext())
         {
+            if (!pIndex->GetOwner() || pIndex->GetOwner()->GetOwnerType() != 
SwContentIndexOwnerType::Mark)
+                continue;
             // Need a non-cost mark here, as we'll create a UNO wrapper around 
it.
-            sw::mark::MarkBase* pBkmk = 
const_cast<sw::mark::MarkBase*>(pIndex->GetMark());
+            sw::mark::MarkBase* pBkmk = 
static_cast<sw::mark::MarkBase*>(pIndex->GetOwner());
             if (!pBkmk)
                 continue;
             IDocumentMarkAccess::MarkType eType = 
IDocumentMarkAccess::GetType(*pBkmk);

Reply via email to