diff options
37 files changed, 341 insertions, 157 deletions
diff --git a/cui/source/dialogs/srchxtra.cxx b/cui/source/dialogs/srchxtra.cxx index 9ed00b46377d..4c672b9839f2 100644 --- a/cui/source/dialogs/srchxtra.cxx +++ b/cui/source/dialogs/srchxtra.cxx @@ -135,7 +135,7 @@ SvxSearchAttributeDialog::SvxSearchAttributeDialog(weld::Window* pParent, if ( nSlot == rList[i].nSlot ) { bFound = true; - if ( IsInvalidItem( rList[i].pItem ) ) + if ( IsInvalidItem( rList[i].pItemPtr ) ) bChecked = true; } } @@ -167,8 +167,8 @@ SvxSearchAttributeDialog::~SvxSearchAttributeDialog() IMPL_LINK_NOARG(SvxSearchAttributeDialog, OKHdl, weld::Button&, void) { - SearchAttrItem aInvalidItem; - aInvalidItem.pItem = INVALID_POOL_ITEM; + SearchAttrInfo aInvalidItem; + aInvalidItem.pItemPtr = INVALID_POOL_ITEM; for (int i = 0, nCount = m_xAttrLB->n_children(); i < nCount; ++i) { @@ -178,17 +178,17 @@ IMPL_LINK_NOARG(SvxSearchAttributeDialog, OKHdl, weld::Button&, void) sal_uInt16 j; for ( j = rList.Count(); j; ) { - SearchAttrItem& rItem = rList[ --j ]; + SearchAttrInfo& rItem = rList[ --j ]; if( rItem.nSlot == nSlot ) { if( bChecked ) { - if( !IsInvalidItem( rItem.pItem ) ) - delete rItem.pItem; - rItem.pItem = INVALID_POOL_ITEM; + if( !IsInvalidItem( rItem.pItemPtr ) ) + delete rItem.pItemPtr; + rItem.pItemPtr = INVALID_POOL_ITEM; } - else if( IsInvalidItem( rItem.pItem ) ) - rItem.pItem = nullptr; + else if( IsInvalidItem( rItem.pItemPtr ) ) + rItem.pItemPtr = nullptr; j = 1; break; } @@ -203,7 +203,7 @@ IMPL_LINK_NOARG(SvxSearchAttributeDialog, OKHdl, weld::Button&, void) // remove invalid items (pItem == NULL) for ( sal_uInt16 n = rList.Count(); n; ) - if ( !rList[ --n ].pItem ) + if ( !rList[ --n ].pItemPtr ) rList.Remove( n ); m_xDialog->response(RET_OK); diff --git a/cui/source/options/optgdlg.cxx b/cui/source/options/optgdlg.cxx index 64d11a62451b..3223637b8d47 100644 --- a/cui/source/options/optgdlg.cxx +++ b/cui/source/options/optgdlg.cxx @@ -48,6 +48,7 @@ #include <editeng/editids.hrc> #include <svx/svxids.hrc> #include <svl/intitem.hxx> +#include <svl/voiditem.hxx> #include <GraphicsTestsDialog.hxx> #include <unotools/searchopt.hxx> #include <sal/log.hxx> diff --git a/editeng/qa/unit/core-test.cxx b/editeng/qa/unit/core-test.cxx index 075703266c18..d3f92ce60c2c 100644 --- a/editeng/qa/unit/core-test.cxx +++ b/editeng/qa/unit/core-test.cxx @@ -29,6 +29,7 @@ #include <editeng/flditem.hxx> #include <editeng/udlnitem.hxx> #include <svl/srchitem.hxx> +#include <svl/voiditem.hxx> #include <editeng/fontitem.hxx> #include <editeng/fhgtitem.hxx> diff --git a/editeng/source/editeng/editattr.cxx b/editeng/source/editeng/editattr.cxx index a045f16ade81..d1d79fd0263e 100644 --- a/editeng/source/editeng/editattr.cxx +++ b/editeng/source/editeng/editattr.cxx @@ -20,6 +20,7 @@ #include <vcl/outdev.hxx> #include <svl/grabbagitem.hxx> +#include <svl/voiditem.hxx> #include <libxml/xmlwriter.h> #include <editeng/svxfont.hxx> #include <editeng/flditem.hxx> diff --git a/editeng/source/editeng/editdoc.cxx b/editeng/source/editeng/editdoc.cxx index d4dc4ee16e37..9b0d3948bc13 100644 --- a/editeng/source/editeng/editdoc.cxx +++ b/editeng/source/editeng/editdoc.cxx @@ -54,6 +54,7 @@ #include <osl/diagnose.h> #include <svl/grabbagitem.hxx> +#include <svl/voiditem.hxx> #include <tools/debug.hxx> #include <com/sun/star/i18n/ScriptType.hpp> #include <libxml/xmlwriter.h> diff --git a/editeng/source/editeng/eerdll.cxx b/editeng/source/editeng/eerdll.cxx index f6a1cbc049c2..9e3e8c4cf8c5 100644 --- a/editeng/source/editeng/eerdll.cxx +++ b/editeng/source/editeng/eerdll.cxx @@ -36,6 +36,7 @@ #include <editeng/hngpnctitem.hxx> #include <editeng/forbiddenruleitem.hxx> #include <svl/grabbagitem.hxx> +#include <svl/voiditem.hxx> #include <vcl/svapp.hxx> #include <vcl/virdev.hxx> diff --git a/editeng/source/editeng/impedit2.cxx b/editeng/source/editeng/impedit2.cxx index 8d4960069cc8..61b3d0062748 100644 --- a/editeng/source/editeng/impedit2.cxx +++ b/editeng/source/editeng/impedit2.cxx @@ -59,6 +59,7 @@ #include <sot/exchange.hxx> #include <sot/formats.hxx> #include <svl/asiancfg.hxx> +#include <svl/voiditem.hxx> #include <i18nutil/unicode.hxx> #include <comphelper/diagnose_ex.hxx> #include <comphelper/flagguard.hxx> diff --git a/include/svl/itemset.hxx b/include/svl/itemset.hxx index a3736427b002..37141a0a79b3 100644 --- a/include/svl/itemset.hxx +++ b/include/svl/itemset.hxx @@ -57,6 +57,21 @@ protected: void setCallback(const std::function<void(const SfxPoolItem*, const SfxPoolItem*)> &func) { m_aCallback = func; } void clearCallback() { m_aCallback = nullptr; } + // container library interface support + // only for internal use (for now), thus protected + using const_iterator = SfxPoolItem const**; + + const_iterator begin() const noexcept { return m_ppItems; } + const_iterator end() const noexcept { return begin() + m_nTotalCount; } + + bool empty() const noexcept { return 0 == m_nTotalCount; } + sal_Int32 size() const noexcept { return m_nTotalCount; } + SfxPoolItem const* operator[](sal_Int32 idx) const noexcept + { + assert(idx >= 0 && idx < m_nTotalCount && "index out of range"); + return m_ppItems[idx]; + } + friend class SfxItemPoolCache; friend class SfxAllItemSet; @@ -242,6 +257,9 @@ private: // split version(s) of GetItemStateImpl for input types WhichID and Offset SfxItemState GetItemState_ForWhichID( SfxItemState eState, sal_uInt16 nWhich, bool bSrchInParent, const SfxPoolItem **ppItem) const; SfxItemState GetItemState_ForOffset( sal_uInt16 nOffset, const SfxPoolItem **ppItem) const; + + void implCreateItemEntry(SfxPoolItem const*& rpTarget, SfxPoolItem const* pSource); + void implCleanupItemEntry(SfxPoolItem const* pSource); }; inline void SfxItemSet::SetParent( const SfxItemSet* pNew ) diff --git a/include/svl/poolitem.hxx b/include/svl/poolitem.hxx index 10a7901b4e70..46dd8b0a76f5 100644 --- a/include/svl/poolitem.hxx +++ b/include/svl/poolitem.hxx @@ -106,7 +106,10 @@ enum class SfxItemState { SET = 0x0040 }; -#define INVALID_POOL_ITEM reinterpret_cast<SfxPoolItem*>(-1) +#ifdef DBG_UTIL +SVL_DLLPUBLIC size_t getAllocatedSfxPoolItemCount(); +SVL_DLLPUBLIC size_t getUsedSfxPoolItemCount(); +#endif class SfxItemPool; class SfxItemSet; @@ -118,7 +121,6 @@ friend class SfxItemPool; friend class SfxItemDisruptor_Impl; friend class SfxItemPoolCache; friend class SfxItemSet; -friend class SfxVoidItem; mutable sal_uInt32 m_nRefCount; sal_uInt16 m_nWhich; @@ -286,40 +288,13 @@ inline bool IsPooledItem( const SfxPoolItem *pItem ) return pItem && pItem->GetRefCount() > 0 && pItem->GetRefCount() <= SFX_ITEMS_MAXREF; } +SVL_DLLPUBLIC extern SfxPoolItem const * const INVALID_POOL_ITEM; + inline bool IsInvalidItem(const SfxPoolItem *pItem) { return pItem == INVALID_POOL_ITEM; } -class SVL_DLLPUBLIC SfxVoidItem final: public SfxPoolItem -{ -public: - static SfxPoolItem* CreateDefault(); - explicit SfxVoidItem( sal_uInt16 nWhich ); - virtual ~SfxVoidItem() override; - - SfxVoidItem(SfxVoidItem const &) = default; - SfxVoidItem(SfxVoidItem &&) = default; - SfxVoidItem & operator =(SfxVoidItem const &) = delete; // due to SfxPoolItem - SfxVoidItem & operator =(SfxVoidItem &&) = delete; // due to SfxPoolItem - - virtual bool operator==( const SfxPoolItem& ) const override; - - virtual bool GetPresentation( SfxItemPresentation ePres, - MapUnit eCoreMetric, - MapUnit ePresMetric, - OUString &rText, - const IntlWrapper& ) const override; - virtual void dumpAsXml(xmlTextWriterPtr pWriter) const override; - - // create a copy of itself - virtual SfxVoidItem* Clone( SfxItemPool *pPool = nullptr ) const override; - - /** Always returns true as this is an SfxVoidItem. */ - virtual bool IsVoidItem() const override; -}; - - class SVL_DLLPUBLIC SfxPoolItemHint final : public SfxHint { SfxPoolItem* pObj; diff --git a/include/svl/voiditem.hxx b/include/svl/voiditem.hxx new file mode 100644 index 000000000000..b06f28e84b2e --- /dev/null +++ b/include/svl/voiditem.hxx @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_SVL_VOIDITEM_HXX +#define INCLUDED_SVL_VOIDITEM_HXX + +#include <svl/poolitem.hxx> + +class SVL_DLLPUBLIC SfxVoidItem final : public SfxPoolItem +{ +public: + static SfxPoolItem* CreateDefault(); + explicit SfxVoidItem(sal_uInt16 nWhich); + virtual ~SfxVoidItem() override; + + SfxVoidItem(SfxVoidItem const&) = default; + SfxVoidItem(SfxVoidItem&&) = default; + SfxVoidItem& operator=(SfxVoidItem const&) = delete; // due to SfxPoolItem + SfxVoidItem& operator=(SfxVoidItem&&) = delete; // due to SfxPoolItem + + virtual bool operator==(const SfxPoolItem&) const override; + + virtual bool GetPresentation(SfxItemPresentation ePres, MapUnit eCoreMetric, + MapUnit ePresMetric, OUString& rText, + const IntlWrapper&) const override; + virtual void dumpAsXml(xmlTextWriterPtr pWriter) const override; + + // create a copy of itself + virtual SfxVoidItem* Clone(SfxItemPool* pPool = nullptr) const override; + + /** Always returns true as this is an SfxVoidItem. */ + virtual bool IsVoidItem() const override; +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/srchdlg.hxx b/include/svx/srchdlg.hxx index 2b975e435083..9a75199ad818 100644 --- a/include/svx/srchdlg.hxx +++ b/include/svx/srchdlg.hxx @@ -38,15 +38,15 @@ struct SearchDlg_Impl; enum class ModifyFlags; enum class TransliterationFlags; -struct SearchAttrItem +struct SearchAttrInfo { sal_uInt16 nSlot; - SfxPoolItem* pItem; + const SfxPoolItem* pItemPtr; }; -typedef std::vector<SearchAttrItem> SrchAttrItemList; +typedef std::vector<SearchAttrInfo> SrchAttrInfoList; -class SVX_DLLPUBLIC SearchAttrItemList : private SrchAttrItemList +class SVX_DLLPUBLIC SearchAttrItemList : private SrchAttrInfoList { public: SearchAttrItemList() {} @@ -57,15 +57,15 @@ public: void Put( const SfxItemSet& rSet ); SfxItemSet& Get( SfxItemSet& rSet ); void Clear(); - sal_uInt16 Count() const { return SrchAttrItemList::size(); } - SearchAttrItem& operator[](sal_uInt16 nPos) - { return SrchAttrItemList::operator[]( nPos ); } - SearchAttrItem& GetObject( sal_uInt16 nPos ) - { return SrchAttrItemList::operator[]( nPos ); } + sal_uInt16 Count() const { return SrchAttrInfoList::size(); } + SearchAttrInfo& operator[](sal_uInt16 nPos) + { return SrchAttrInfoList::operator[]( nPos ); } + SearchAttrInfo& GetObject( sal_uInt16 nPos ) + { return SrchAttrInfoList::operator[]( nPos ); } // the pointer to the item is not being copied, so don't delete - void Insert( const SearchAttrItem& rItem ) - { SrchAttrItemList::push_back( rItem ); } + void Insert( const SearchAttrInfo& rItem ) + { SrchAttrInfoList::push_back( rItem ); } // deletes the pointer to the items void Remove(size_t nPos); }; diff --git a/sfx2/source/appl/appbas.cxx b/sfx2/source/appl/appbas.cxx index 482b93692200..1cedcd978540 100644 --- a/sfx2/source/appl/appbas.cxx +++ b/sfx2/source/appl/appbas.cxx @@ -28,6 +28,7 @@ #include <svl/intitem.hxx> #include <svl/eitem.hxx> #include <svl/whiter.hxx> +#include <svl/voiditem.hxx> #include <basic/sbstar.hxx> #include <sfx2/frame.hxx> diff --git a/sfx2/source/control/bindings.cxx b/sfx2/source/control/bindings.cxx index 629ad3aa41df..dcba259627ab 100644 --- a/sfx2/source/control/bindings.cxx +++ b/sfx2/source/control/bindings.cxx @@ -29,6 +29,7 @@ #include <svl/eitem.hxx> #include <svl/intitem.hxx> #include <svl/stritem.hxx> +#include <svl/voiditem.hxx> #include <vcl/svapp.hxx> #include <vcl/timer.hxx> #include <com/sun/star/frame/XDispatch.hpp> diff --git a/sfx2/source/control/sfxstatuslistener.cxx b/sfx2/source/control/sfxstatuslistener.cxx index 7cc4e8dd688b..b7e76cdff7c3 100644 --- a/sfx2/source/control/sfxstatuslistener.cxx +++ b/sfx2/source/control/sfxstatuslistener.cxx @@ -23,6 +23,7 @@ #include <svl/stritem.hxx> #include <svl/intitem.hxx> #include <svl/visitem.hxx> +#include <svl/voiditem.hxx> #include <comphelper/processfactory.hxx> #include <comphelper/servicehelper.hxx> #include <vcl/svapp.hxx> diff --git a/sfx2/source/control/shell.cxx b/sfx2/source/control/shell.cxx index aeba636a491f..5cba99c231d5 100644 --- a/sfx2/source/control/shell.cxx +++ b/sfx2/source/control/shell.cxx @@ -25,6 +25,7 @@ #include <osl/diagnose.h> #include <svl/itempool.hxx> #include <svl/setitem.hxx> +#include <svl/voiditem.hxx> #include <svl/undo.hxx> #include <itemdel.hxx> #include <svtools/asynclink.hxx> diff --git a/sfx2/source/control/statcach.cxx b/sfx2/source/control/statcach.cxx index 03f1daa5a370..cf059affbed1 100644 --- a/sfx2/source/control/statcach.cxx +++ b/sfx2/source/control/statcach.cxx @@ -31,6 +31,7 @@ #include <svl/intitem.hxx> #include <svl/stritem.hxx> #include <svl/visitem.hxx> +#include <svl/voiditem.hxx> #include <sfx2/app.hxx> #include <statcach.hxx> diff --git a/sfx2/source/statbar/stbitem.cxx b/sfx2/source/statbar/stbitem.cxx index e9d8512fa832..2387557d6ba9 100644 --- a/sfx2/source/statbar/stbitem.cxx +++ b/sfx2/source/statbar/stbitem.cxx @@ -18,6 +18,7 @@ */ #include <svl/stritem.hxx> +#include <svl/voiditem.hxx> #include <com/sun/star/util/URL.hpp> #include <com/sun/star/util/URLTransformer.hpp> #include <com/sun/star/util/XURLTransformer.hpp> diff --git a/sfx2/source/toolbox/tbxitem.cxx b/sfx2/source/toolbox/tbxitem.cxx index 70bd2b2762de..f355806aaa00 100644 --- a/sfx2/source/toolbox/tbxitem.cxx +++ b/sfx2/source/toolbox/tbxitem.cxx @@ -39,6 +39,7 @@ #include <svl/stritem.hxx> #include <svl/intitem.hxx> #include <svl/visitem.hxx> +#include <svl/voiditem.hxx> #include <vcl/svapp.hxx> #include <vcl/toolbox.hxx> diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx index 524bf7f7efda..a6d9ef825e35 100644 --- a/sfx2/source/view/lokhelper.cxx +++ b/sfx2/source/view/lokhelper.cxx @@ -558,7 +558,7 @@ namespace { void SfxLokHelper::sendUnoStatus(const SfxViewShell* pShell, const SfxPoolItem* pItem) { - if (!pShell || !pItem || pItem == INVALID_POOL_ITEM || DisableCallbacks::disabled()) + if (!pShell || !pItem || IsInvalidItem(pItem) || DisableCallbacks::disabled()) return; boost::property_tree::ptree aItem = pItem->dumpAsJSON(); diff --git a/starmath/source/view.cxx b/starmath/source/view.cxx index e495039326f9..1a1a236deca5 100644 --- a/starmath/source/view.cxx +++ b/starmath/source/view.cxx @@ -55,6 +55,7 @@ #include <svl/itemset.hxx> #include <svl/poolitem.hxx> #include <svl/stritem.hxx> +#include <svl/voiditem.hxx> #include <vcl/transfer.hxx> #include <svtools/colorcfg.hxx> #include <svl/whiter.hxx> diff --git a/svl/Library_svl.mk b/svl/Library_svl.mk index 87024bbf499e..aee540d56514 100644 --- a/svl/Library_svl.mk +++ b/svl/Library_svl.mk @@ -143,6 +143,7 @@ $(eval $(call gb_Library_add_exception_objects,svl,\ svl/source/items/style \ svl/source/items/stylepool \ svl/source/items/visitem \ + svl/source/items/voiditem \ svl/source/items/whiter \ svl/source/misc/PasswordHelper \ svl/source/misc/adrparse \ diff --git a/svl/qa/unit/items/test_itempool.cxx b/svl/qa/unit/items/test_itempool.cxx index 6868999f0f76..339da002bfc1 100644 --- a/svl/qa/unit/items/test_itempool.cxx +++ b/svl/qa/unit/items/test_itempool.cxx @@ -8,6 +8,7 @@ */ #include <svl/itempool.hxx> +#include <svl/voiditem.hxx> #include <poolio.hxx> #include <cppunit/TestAssert.h> diff --git a/svl/source/items/itemset.cxx b/svl/source/items/itemset.cxx index 289a69adf4da..401044e8ba09 100644 --- a/svl/source/items/itemset.cxx +++ b/svl/source/items/itemset.cxx @@ -32,6 +32,7 @@ #include <svl/itemiter.hxx> #include <svl/setitem.hxx> #include <svl/whiter.hxx> +#include <svl/voiditem.hxx> #include <items_helper.hxx> @@ -99,6 +100,68 @@ SfxItemSet::SfxItemSet(SfxItemPool& pool, WhichRangesContainer wids) assert(svl::detail::validRanges2(m_pWhichRanges)); } +void SfxItemSet::implCreateItemEntry(SfxPoolItem const*& rpTarget, SfxPoolItem const* pSource) +{ + if (nullptr == pSource + || IsInvalidItem(pSource) + || IsStaticDefaultItem(pSource)) + { + // copy the pointer if + // - SfxItemState::UNKNOWN aka current default (nullptr) + // - SfxItemState::DONTCARE aka invalid item + // - StaticDefaultItem aka static pool default (however this finds + // it's way to the ItemSet? It *should* be default, too) + rpTarget = pSource; + return; + } + + if (0 == pSource->Which()) + { + // these *should* be SfxVoidItem(0) the only Items with 0 == WhichID + rpTarget = pSource->Clone(); + return; + } + + if (m_pPool->IsItemPoolable(*pSource)) + { + // copy the pointer and increase RefCount + rpTarget = pSource; + rpTarget->AddRef(); + return; + } + + // !IsPoolable() => assign via Pool + rpTarget = &m_pPool->Put(*pSource); +} + +void SfxItemSet::implCleanupItemEntry(SfxPoolItem const* pSource) +{ + if (nullptr == pSource // no entry, done + || IsInvalidItem(pSource) // nothing to do for invalid item entries + || IsDefaultItem(pSource)) // default items are owned by the pool, nothing to do + { + return; + } + + if (0 == pSource->Which()) + { + // these *should* be SfxVoidItem(0) the only Items with 0 == WhichID + // and need to be deleted + delete pSource; + return; + } + + if (1 < pSource->GetRefCount()) + { + // Still multiple references present, so just alter the RefCount + pSource->ReleaseRef(); + return; + } + + // Delete from Pool + m_pPool->Remove(*pSource); +} + SfxItemSet::SfxItemSet( const SfxItemSet& rASet ) : m_pPool( rASet.m_pPool ) , m_pParent( rASet.m_pParent ) @@ -114,28 +177,17 @@ SfxItemSet::SfxItemSet( const SfxItemSet& rASet ) return; } - m_ppItems = new const SfxPoolItem* [TotalCount()] {}; + // allocate new array (no need to initialize, will be done below) + m_ppItems = new const SfxPoolItem* [TotalCount()]; // Copy attributes - SfxPoolItem const** ppDst = m_ppItems; - SfxPoolItem const** ppSrc = rASet.m_ppItems; - for( sal_uInt16 n = TotalCount(); n; --n, ++ppDst, ++ppSrc ) - if ( nullptr == *ppSrc || // Current Default? - IsInvalidItem(*ppSrc) || // DontCare? - IsStaticDefaultItem(*ppSrc) ) // Defaults that are not to be pooled? - // Just copy the pointer - *ppDst = *ppSrc; - else if (m_pPool->IsItemPoolable( **ppSrc )) - { - // Just copy the pointer and increase RefCount - *ppDst = *ppSrc; - (*ppDst)->AddRef(); - } - else if ( !(*ppSrc)->Which() ) - *ppDst = (*ppSrc)->Clone(); - else - // !IsPoolable() => assign via Pool - *ppDst = &m_pPool->Put( **ppSrc ); + SfxPoolItem const** ppDst(m_ppItems); + + for (const auto& rSource : rASet) + { + implCreateItemEntry(*ppDst, rSource); + ppDst++; + } assert(svl::detail::validRanges2(m_pWhichRanges)); } @@ -170,32 +222,24 @@ SfxItemSet::SfxItemSet(SfxItemSet&& rASet) noexcept SfxItemSet::~SfxItemSet() { - if (!m_pWhichRanges.empty()) // might be nullptr if we have been moved-from + // might be nullptr if we have been moved-from, also only needed + // when we have ::SET items + if (!m_pWhichRanges.empty() && Count()) { - if( Count() ) + for (auto& rCandidate : *this) { - SfxPoolItem const** ppFnd = m_ppItems; - for( sal_uInt16 nCnt = TotalCount(); nCnt; --nCnt, ++ppFnd ) - if( *ppFnd && !IsInvalidItem(*ppFnd) ) - { - if( !(*ppFnd)->Which() ) - delete *ppFnd; - else { - // Still multiple references present, so just alter the RefCount - if ( 1 < (*ppFnd)->GetRefCount() && !IsDefaultItem(*ppFnd) ) - (*ppFnd)->ReleaseRef(); - else - if ( !IsDefaultItem(*ppFnd) ) - // Delete from Pool - m_pPool->Remove( **ppFnd ); - } - } + implCleanupItemEntry(rCandidate); } } if (!m_bItemsFixed) + { + // free SfxPoolItem array delete[] m_ppItems; - m_pWhichRanges.reset(); // for invariant-testing + } + + // for invariant-testing + m_pWhichRanges.reset(); } /** @@ -316,7 +360,7 @@ void SfxItemSet::ClearInvalidItems() void SfxItemSet::InvalidateAllItems() { assert( !m_nCount && "There are still Items set" ); - memset(static_cast<void*>(m_ppItems), -1, TotalCount() * sizeof(SfxPoolItem*)); + std::fill(m_ppItems, m_ppItems + TotalCount(), INVALID_POOL_ITEM); } SfxItemState SfxItemSet::GetItemState( sal_uInt16 nWhich, diff --git a/svl/source/items/poolitem.cxx b/svl/source/items/poolitem.cxx index cb1bec15159c..9a45e8803448 100644 --- a/svl/source/items/poolitem.cxx +++ b/svl/source/items/poolitem.cxx @@ -461,16 +461,30 @@ // class SwPaMItem : public SfxPoolItem ////////////////////////////////////////////////////////////////////////////// +#ifdef DBG_UTIL +static size_t nAllocatedSfxPoolItemCount(0); +static size_t nUsedSfxPoolItemCount(0); +size_t getAllocatedSfxPoolItemCount() { return nAllocatedSfxPoolItemCount; } +size_t getUsedSfxPoolItemCount() { return nUsedSfxPoolItemCount; } +#endif + SfxPoolItem::SfxPoolItem(sal_uInt16 const nWhich) : m_nRefCount(0) , m_nWhich(nWhich) , m_nKind(SfxItemKind::NONE) { +#ifdef DBG_UTIL + nAllocatedSfxPoolItemCount++; + nUsedSfxPoolItemCount++; +#endif assert(nWhich <= SHRT_MAX); } SfxPoolItem::~SfxPoolItem() { +#ifdef DBG_UTIL + nAllocatedSfxPoolItemCount--; +#endif assert((m_nRefCount == 0 || m_nRefCount > SFX_ITEMS_MAXREF) && "destroying item in use"); } @@ -562,40 +576,6 @@ std::unique_ptr<SfxPoolItem> SfxPoolItem::CloneSetWhich(sal_uInt16 nNewWhich) co bool SfxPoolItem::IsVoidItem() const { return false; } -SfxPoolItem* SfxVoidItem::CreateDefault() { return new SfxVoidItem(0); } - -SfxVoidItem::SfxVoidItem(sal_uInt16 which) - : SfxPoolItem(which) -{ -} - -bool SfxVoidItem::operator==(const SfxPoolItem& rCmp) const -{ - assert(SfxPoolItem::operator==(rCmp)); - (void)rCmp; - return true; -} - -bool SfxVoidItem::GetPresentation(SfxItemPresentation /*ePresentation*/, MapUnit /*eCoreMetric*/, - MapUnit /*ePresentationMetric*/, OUString& rText, - const IntlWrapper&) const -{ - rText = "Void"; - return true; -} - -void SfxVoidItem::dumpAsXml(xmlTextWriterPtr pWriter) const -{ - (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SfxVoidItem")); - (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), - BAD_CAST(OString::number(Which()).getStr())); - (void)xmlTextWriterEndElement(pWriter); -} - -SfxVoidItem* SfxVoidItem::Clone(SfxItemPool*) const { return new SfxVoidItem(*this); } - -bool SfxVoidItem::IsVoidItem() const { return true; } - void SfxPoolItem::ScaleMetrics(tools::Long /*lMult*/, tools::Long /*lDiv*/) {} bool SfxPoolItem::HasMetrics() const { return false; } @@ -612,6 +592,16 @@ bool SfxPoolItem::PutValue(const css::uno::Any&, sal_uInt8) return false; } -SfxVoidItem::~SfxVoidItem() {} +namespace +{ +class InvalidItem final : public SfxPoolItem +{ + virtual bool operator==(const SfxPoolItem&) const override { return true; } + virtual SfxPoolItem* Clone(SfxItemPool*) const override { return nullptr; } +}; +InvalidItem aInvalidItem; +} + +SfxPoolItem const* const INVALID_POOL_ITEM = &aInvalidItem; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svl/source/items/voiditem.cxx b/svl/source/items/voiditem.cxx new file mode 100644 index 000000000000..3afa64de5332 --- /dev/null +++ b/svl/source/items/voiditem.cxx @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <svl/voiditem.hxx> +#include <libxml/xmlwriter.h> + +SfxPoolItem* SfxVoidItem::CreateDefault() { return new SfxVoidItem(0); } + +SfxVoidItem::SfxVoidItem(sal_uInt16 which) + : SfxPoolItem(which) +{ +} + +bool SfxVoidItem::operator==(const SfxPoolItem& rCmp) const +{ + assert(SfxPoolItem::operator==(rCmp)); + (void)rCmp; + return true; +} + +bool SfxVoidItem::GetPresentation(SfxItemPresentation /*ePresentation*/, MapUnit /*eCoreMetric*/, + MapUnit /*ePresentationMetric*/, OUString& rText, + const IntlWrapper&) const +{ + rText = "Void"; + return true; +} + +void SfxVoidItem::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("SfxVoidItem")); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("whichId"), + BAD_CAST(OString::number(Which()).getStr())); + (void)xmlTextWriterEndElement(pWriter); +} + +SfxVoidItem* SfxVoidItem::Clone(SfxItemPool*) const { return new SfxVoidItem(*this); } + +bool SfxVoidItem::IsVoidItem() const { return true; } + +SfxVoidItem::~SfxVoidItem() {} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svx/source/dialog/srchdlg.cxx b/svx/source/dialog/srchdlg.cxx index 7f496535e2b7..dcb467b5475f 100644 --- a/svx/source/dialog/srchdlg.cxx +++ b/svx/source/dialog/srchdlg.cxx @@ -175,19 +175,19 @@ static void StrArrToList_Impl( TypedWhichId<SfxStringListItem> nId, const std::v } SearchAttrItemList::SearchAttrItemList( SearchAttrItemList&& rList ) : - SrchAttrItemList(std::move(rList)) + SrchAttrInfoList(std::move(rList)) { for ( size_t i = 0; i < size(); ++i ) - if ( !IsInvalidItem( (*this)[i].pItem ) ) - (*this)[i].pItem = (*this)[i].pItem->Clone(); + if ( !IsInvalidItem( (*this)[i].pItemPtr ) ) + (*this)[i].pItemPtr = (*this)[i].pItemPtr->Clone(); } SearchAttrItemList::SearchAttrItemList( const SearchAttrItemList& rList ) : - SrchAttrItemList(rList) + SrchAttrInfoList(rList) { for ( size_t i = 0; i < size(); ++i ) - if ( !IsInvalidItem( (*this)[i].pItem ) ) - (*this)[i].pItem = (*this)[i].pItem->Clone(); + if ( !IsInvalidItem( (*this)[i].pItemPtr ) ) + (*this)[i].pItemPtr = (*this)[i].pItemPtr->Clone(); } SearchAttrItemList::~SearchAttrItemList() @@ -202,7 +202,7 @@ void SearchAttrItemList::Put( const SfxItemSet& rSet ) SfxItemPool* pPool = rSet.GetPool(); SfxItemIter aIter( rSet ); - SearchAttrItem aItem; + SearchAttrInfo aItem; const SfxPoolItem* pItem = aIter.GetCurItem(); sal_uInt16 nWhich; @@ -212,12 +212,12 @@ void SearchAttrItemList::Put( const SfxItemSet& rSet ) if( IsInvalidItem( pItem ) ) { nWhich = rSet.GetWhichByOffset( aIter.GetCurPos() ); - aItem.pItem = const_cast<SfxPoolItem*>(pItem); + aItem.pItemPtr = pItem; } else { nWhich = pItem->Which(); - aItem.pItem = pItem->Clone(); + aItem.pItemPtr = pItem->Clone(); } aItem.nSlot = pPool->GetSlotId( nWhich ); @@ -233,10 +233,10 @@ SfxItemSet& SearchAttrItemList::Get( SfxItemSet& rSet ) SfxItemPool* pPool = rSet.GetPool(); for ( size_t i = 0; i < size(); ++i ) - if ( IsInvalidItem( (*this)[i].pItem ) ) + if ( IsInvalidItem( (*this)[i].pItemPtr ) ) rSet.InvalidateItem( pPool->GetWhich( (*this)[i].nSlot ) ); else - rSet.Put( *(*this)[i].pItem ); + rSet.Put( *(*this)[i].pItemPtr ); return rSet; } @@ -244,9 +244,9 @@ SfxItemSet& SearchAttrItemList::Get( SfxItemSet& rSet ) void SearchAttrItemList::Clear() { for ( size_t i = 0; i < size(); ++i ) - if ( !IsInvalidItem( (*this)[i].pItem ) ) - delete (*this)[i].pItem; - SrchAttrItemList::clear(); + if ( !IsInvalidItem( (*this)[i].pItemPtr ) ) + delete (*this)[i].pItemPtr; + SrchAttrInfoList::clear(); } @@ -258,10 +258,10 @@ void SearchAttrItemList::Remove(size_t nPos) nLen = size() - nPos; for ( size_t i = nPos; i < nPos + nLen; ++i ) - if ( !IsInvalidItem( (*this)[i].pItem ) ) - delete (*this)[i].pItem; + if ( !IsInvalidItem( (*this)[i].pItemPtr ) ) + delete (*this)[i].pItemPtr; - SrchAttrItemList::erase( begin() + nPos, begin() + nPos + nLen ); + SrchAttrInfoList::erase( begin() + nPos, begin() + nPos + nLen ); } SvxSearchDialog::SvxSearchDialog(weld::Window* pParent, SfxChildWindow* pChildWin, SfxBindings& rBind) @@ -1996,14 +1996,14 @@ IMPL_LINK_NOARG(SvxSearchDialog, FormatHdl_Impl, weld::Button&, void) const SfxPoolItem* pItem; for( sal_uInt16 n = 0; n < pList->Count(); ++n ) { - SearchAttrItem* pAItem = &pList->GetObject(n); - if( !IsInvalidItem( pAItem->pItem ) && + SearchAttrInfo* pAItem = &pList->GetObject(n); + if( !IsInvalidItem( pAItem->pItemPtr ) && SfxItemState::SET == aOutSet.GetItemState( - pAItem->pItem->Which(), false, &pItem ) ) + pAItem->pItemPtr->Which(), false, &pItem ) ) { - delete pAItem->pItem; - pAItem->pItem = pItem->Clone(); - aOutSet.ClearItem( pAItem->pItem->Which() ); + delete pAItem->pItemPtr; + pAItem->pItemPtr = pItem->Clone(); + aOutSet.ClearItem( pAItem->pItemPtr->Which() ); } } @@ -2135,15 +2135,15 @@ OUString& SvxSearchDialog::BuildAttrText_Impl( OUString& rStr, IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag()); for ( sal_uInt16 i = 0; i < pList->Count(); ++i ) { - const SearchAttrItem& rItem = pList->GetObject(i); + const SearchAttrInfo& rItem = pList->GetObject(i); if ( !rStr.isEmpty() ) rStr += ", "; - if ( !IsInvalidItem( rItem.pItem ) ) + if ( !IsInvalidItem( rItem.pItemPtr ) ) { OUString aStr; - rPool.GetPresentation(*rItem.pItem, eMapUnit, aStr, aIntlWrapper); + rPool.GetPresentation(*rItem.pItemPtr, eMapUnit, aStr, aIntlWrapper); if (aStr.isEmpty()) { if (rStr.endsWith(", ")) diff --git a/svx/source/mnuctrls/clipboardctl.cxx b/svx/source/mnuctrls/clipboardctl.cxx index 70b2620565bf..b5b55535f13a 100644 --- a/svx/source/mnuctrls/clipboardctl.cxx +++ b/svx/source/mnuctrls/clipboardctl.cxx @@ -22,6 +22,7 @@ #include <comphelper/propertyvalue.hxx> #include <sfx2/tbxctrl.hxx> #include <svl/intitem.hxx> +#include <svl/voiditem.hxx> #include <vcl/svapp.hxx> #include <vcl/toolbox.hxx> #include <vcl/weldutils.hxx> diff --git a/svx/source/stbctrls/zoomctrl.cxx b/svx/source/stbctrls/zoomctrl.cxx index 77bb47fce38f..9a86cc8ffb73 100644 --- a/svx/source/stbctrls/zoomctrl.cxx +++ b/svx/source/stbctrls/zoomctrl.cxx @@ -21,6 +21,7 @@ #include <comphelper/propertyvalue.hxx> #include <i18nutil/unicode.hxx> +#include <svl/voiditem.hxx> #include <vcl/commandevent.hxx> #include <vcl/event.hxx> #include <vcl/svapp.hxx> diff --git a/svx/source/svdraw/svdattr.cxx b/svx/source/svdraw/svdattr.cxx index 9ed199d34586..0a4ce01cab2c 100644 --- a/svx/source/svdraw/svdattr.cxx +++ b/svx/source/svdraw/svdattr.cxx @@ -46,6 +46,7 @@ #include <vcl/settings.hxx> #include <svl/grabbagitem.hxx> +#include <svl/voiditem.hxx> #include <svx/strings.hrc> #include <svx/dialmgr.hxx> diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx index a5450d29b673..2e43441958f8 100644 --- a/sw/qa/extras/tiledrendering/tiledrendering.cxx +++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx @@ -38,6 +38,7 @@ #include <svl/srchitem.hxx> #include <svl/slstitm.hxx> #include <svl/stritem.hxx> +#include <svl/voiditem.hxx> #include <sfx2/viewsh.hxx> #include <sfx2/bindings.hxx> #include <sfx2/dispatch.hxx> diff --git a/sw/source/core/bastyp/init.cxx b/sw/source/core/bastyp/init.cxx index f2a4d974cfa1..3e286b31e80a 100644 --- a/sw/source/core/bastyp/init.cxx +++ b/sw/source/core/bastyp/init.cxx @@ -63,6 +63,7 @@ #include <editeng/postitem.hxx> #include <editeng/rsiditem.hxx> #include <svl/grabbagitem.hxx> +#include <svl/voiditem.hxx> #include <editeng/scriptspaceitem.hxx> #include <editeng/shaditem.hxx> #include <editeng/shdditem.hxx> diff --git a/sw/source/core/doc/DocumentContentOperationsManager.cxx b/sw/source/core/doc/DocumentContentOperationsManager.cxx index 4ad364ea6afc..091da2714e02 100644 --- a/sw/source/core/doc/DocumentContentOperationsManager.cxx +++ b/sw/source/core/doc/DocumentContentOperationsManager.cxx @@ -1293,9 +1293,10 @@ namespace //local functions originally from docfmt.cxx aSet.ClearItem( RES_TXTATR_META ); aSet.ClearItem( RES_TXTATR_METAFIELD ); - // After GetParaAttr aSet can contain INVALID_POOL_ITEM items, e.g. RES_TXTATR_CHARFMT - // and (a copy of) this SfxItemSet can be passed to MSWordExportBase::OutputItemSet - // which doesn't handle INVALID_POOL_ITEM items so clear InvalidItems here + // After GetParaAttr aSet can contain invalid/dontcare items (true == IsInvalidItem, + // DONTCARE == SfxItemState), e.g. RES_TXTATR_CHARFMT and (a copy of) this + // SfxItemSet can be passed to MSWordExportBase::OutputItemSet + // which doesn't handle invalid/dontcare items so clear them here aSet.ClearInvalidItems(); xExtra.reset(new SwRedlineExtraData_FormatColl("", USHRT_MAX, &aSet)); diff --git a/sw/source/uibase/app/apphdl.cxx b/sw/source/uibase/app/apphdl.cxx index 9d8dfadbdef6..fd687268eebd 100644 --- a/sw/source/uibase/app/apphdl.cxx +++ b/sw/source/uibase/app/apphdl.cxx @@ -30,6 +30,7 @@ #include <svl/eitem.hxx> #include <svl/whiter.hxx> #include <svl/stritem.hxx> +#include <svl/voiditem.hxx> #include <sfx2/request.hxx> #include <sfx2/fcontnr.hxx> #include <svl/ctloptions.hxx> diff --git a/sw/source/uibase/app/applab.cxx b/sw/source/uibase/app/applab.cxx index c39ec665da71..78436664c3cb 100644 --- a/sw/source/uibase/app/applab.cxx +++ b/sw/source/uibase/app/applab.cxx @@ -23,6 +23,7 @@ #include <hintids.hxx> #include <comphelper/string.hxx> +#include <svl/voiditem.hxx> #include <sfx2/dispatch.hxx> #include <sfx2/printer.hxx> #include <sfx2/request.hxx> diff --git a/sw/source/uibase/lingu/olmenu.cxx b/sw/source/uibase/lingu/olmenu.cxx index 80e32a4cdb30..acf06f2e41a7 100644 --- a/sw/source/uibase/lingu/olmenu.cxx +++ b/sw/source/uibase/lingu/olmenu.cxx @@ -54,6 +54,7 @@ #include <svl/itemset.hxx> #include <svl/languageoptions.hxx> #include <svl/stritem.hxx> +#include <svl/voiditem.hxx> #include <svtools/langtab.hxx> #include <unotools/lingucfg.hxx> #include <unotools/linguprops.hxx> diff --git a/sw/source/uibase/ribbar/workctrl.cxx b/sw/source/uibase/ribbar/workctrl.cxx index eed488a72c46..03c883dc0155 100644 --- a/sw/source/uibase/ribbar/workctrl.cxx +++ b/sw/source/uibase/ribbar/workctrl.cxx @@ -36,6 +36,7 @@ #include <wrtsh.hxx> #include <cppuhelper/queryinterface.hxx> #include <cppuhelper/supportsservice.hxx> +#include <svl/voiditem.hxx> #include <vcl/event.hxx> #include <vcl/menu.hxx> #include <vcl/settings.hxx> diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index 6fed89a5fdd7..4b7fc313bbb1 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -74,6 +74,10 @@ #include <comphelper/solarmutex.hxx> #include <osl/process.h> +#ifdef DBG_UTIL +#include <svl/poolitem.hxx> +#endif + #include <cassert> #include <limits> #include <string_view> @@ -174,6 +178,21 @@ Application::~Application() { ImplDeInitSVData(); ImplGetSVData()->mpApp = nullptr; +#ifdef DBG_UTIL + // Due to + // svx/source/dialog/framelinkarray.cxx + // class Cell final : public SfxPoolItem + // const Cell OBJ_CELL_NONE; + // being a static held SfxPoolItem which is not yet de-initialized here + // number often is (1), even higher with other modules loaded (like 5). + // These get de-allocated reliaby in module-deinitializations, so this + // is no memory loss. These counters are more to be able to have an eye + // on amounts of SfxPoolItems used during office usage and to be able to + // detect if an error in future changes may lead to memory losses - these + // would show in dramaitically higher numbers then imediately + SAL_WARN("vcl", "ITEM: " << getAllocatedSfxPoolItemCount() << " SfxPoolItems still allocated at shutdown"); + SAL_WARN("vcl", "ITEM: " << getUsedSfxPoolItemCount() << " SfxPoolItems were incarnated during office usage"); +#endif } int Application::Main() |