diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /include/svl/itemset.hxx | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'include/svl/itemset.hxx')
-rw-r--r-- | include/svl/itemset.hxx | 357 |
1 files changed, 357 insertions, 0 deletions
diff --git a/include/svl/itemset.hxx b/include/svl/itemset.hxx new file mode 100644 index 0000000000..774fe131c1 --- /dev/null +++ b/include/svl/itemset.hxx @@ -0,0 +1,357 @@ +/* -*- 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 . + */ +#pragma once + +#include <sal/config.h> + +#include <cassert> +#include <memory> +#include <utility> + +#include <svl/svldllapi.h> +#include <svl/poolitem.hxx> +#include <svl/typedwhich.hxx> +#include <svl/whichranges.hxx> + +class SfxItemPool; + +#ifdef DBG_UTIL +SVL_DLLPUBLIC size_t getAllocatedSfxItemSetCount(); +SVL_DLLPUBLIC size_t getUsedSfxItemSetCount(); +SVL_DLLPUBLIC size_t getAllocatedSfxPoolItemHolderCount(); +SVL_DLLPUBLIC size_t getUsedSfxPoolItemHolderCount(); +#endif + +// ItemSet/ItemPool helpers +SfxPoolItem const* implCreateItemEntry(SfxItemPool& rPool, SfxPoolItem const* pSource, sal_uInt16 nWhich, bool bPassingOwnership); +void implCleanupItemEntry(SfxItemPool& rPool, SfxPoolItem const* pSource); + +class SAL_WARN_UNUSED SVL_DLLPUBLIC SfxPoolItemHolder +{ + SfxItemPool* m_pPool; + const SfxPoolItem* m_pItem; +#ifndef NDEBUG + bool m_bDeleted; +#endif +public: + SfxPoolItemHolder(); + SfxPoolItemHolder(SfxItemPool&, const SfxPoolItem*, bool bPassingOwnership = false); + SfxPoolItemHolder(const SfxPoolItemHolder&); + ~SfxPoolItemHolder(); + +#ifndef NDEBUG + bool isDeleted() const { return m_bDeleted; } +#endif + + const SfxPoolItemHolder& operator=(const SfxPoolItemHolder&); + bool operator==(const SfxPoolItemHolder &) const; + SfxItemPool& getPool() const { assert(!isDeleted() && "Destructed instance used (!)"); return *m_pPool; } + const SfxPoolItem* getItem() const { assert(!isDeleted() && "Destructed instance used (!)"); return m_pItem; } + sal_uInt16 Which() const { if(nullptr != m_pItem) return m_pItem->Which(); return 0; } +}; + +class SAL_WARN_UNUSED SVL_DLLPUBLIC SfxItemSet +{ + friend class SfxItemIter; + friend class SfxWhichIter; + + // allow ItemSetTooling to access + friend SfxPoolItem const* implCreateItemEntry(SfxItemPool&, SfxPoolItem const*, sal_uInt16, bool); + friend void implCleanupItemEntry(SfxItemPool&, SfxPoolItem const*); + + SfxItemPool* m_pPool; ///< pool that stores the items + const SfxItemSet* m_pParent; ///< derivation + sal_uInt16 m_nCount; ///< number of items + sal_uInt16 m_nTotalCount; ///< number of WhichIDs, also size of m_ppItems array + + // bitfield (better packaging if a bool needs to be added) + bool m_bItemsFixed : 1; ///< true if this is a SfxItemSetFixed object, so does not *own* m_ppItems + + SfxPoolItem const** m_ppItems; ///< pointer to array of items, we allocate and free this unless m_bItemsFixed==true + WhichRangesContainer m_pWhichRanges; ///< array of Which Ranges + + // Notification-Callback mechanism for SwAttrSet in SW, functionPtr for callback + std::function<void(const SfxPoolItem*, const SfxPoolItem*)> m_aCallback; + +protected: + // Notification-Callback mechanism for SwAttrSet in SW + 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 SfxAllItemSet; + +private: + SVL_DLLPRIVATE void RecreateRanges_Impl(const WhichRangesContainer& pNewRanges); + +public: + SfxPoolItem const** GetItems_Impl() const { return m_ppItems; } + +private: + const SfxItemSet& operator=(const SfxItemSet &) = delete; + +protected: + virtual const SfxPoolItem* PutImpl( const SfxPoolItem&, sal_uInt16 nWhich, bool bPassingOwnership ); + + /** special constructor for SfxAllItemSet */ + enum class SfxAllItemSetFlag { Flag }; + SfxItemSet( SfxItemPool&, SfxAllItemSetFlag ); + /** special constructor for SfxItemSetFixed */ + SfxItemSet( SfxItemPool&, WhichRangesContainer&& ranges, SfxPoolItem const ** ppItems, sal_uInt16 nTotalCount ); + +public: + SfxItemSet( const SfxItemSet& ); + SfxItemSet( SfxItemSet&& ) noexcept; + SfxItemSet( SfxItemPool& ); + SfxItemSet( SfxItemPool&, WhichRangesContainer ranges ); + + SfxItemSet( SfxItemPool& rPool, sal_uInt16 nWhichStart, sal_uInt16 nWhichEnd ) + : SfxItemSet(rPool, WhichRangesContainer(nWhichStart, nWhichEnd)) {} + + template<sal_uInt16... WIDs> + SfxItemSet(SfxItemPool& pool, svl::Items_t<WIDs...> wids) + : SfxItemSet(pool, WhichRangesContainer(wids)) {} + + virtual ~SfxItemSet(); + + virtual std::unique_ptr<SfxItemSet> Clone(bool bItems = true, SfxItemPool *pToPool = nullptr) const; + /** note that this only works if you know for sure that you are dealing with an SfxItemSet + and not one of it's subclasses. */ + SfxItemSet CloneAsValue(bool bItems = true, SfxItemPool *pToPool = nullptr) const; + + // Get number of items + sal_uInt16 Count() const { return m_nCount; } + sal_uInt16 TotalCount() const { return m_nTotalCount; } + + const SfxPoolItem& Get( sal_uInt16 nWhich, bool bSrchInParent = true ) const; + template<class T> + const T& Get( TypedWhichId<T> nWhich, bool bSrchInParent = true ) const + { + return static_cast<const T&>(Get(sal_uInt16(nWhich), bSrchInParent)); + } + + /** This method eases accessing single Items in the SfxItemSet. + + @param nId SlotId or the Item's WhichId + @param bSearchInParent also search in parent ItemSets + @returns 0 if the ItemSet does not contain an Item with the Id 'nWhich' + */ + const SfxPoolItem* GetItem(sal_uInt16 nWhich, bool bSearchInParent = true) const; + + /// Templatized version of GetItem() to directly return the correct type. + template<class T> const T* GetItem(sal_uInt16 nWhich, bool bSearchInParent = true) const + { + const SfxPoolItem* pItem = GetItem(nWhich, bSearchInParent); + const T* pCastedItem = dynamic_cast<const T*>(pItem); + + assert(!pItem || pCastedItem); // if it exists, must have the correct type + return pCastedItem; + } + template<class T> const T* GetItem( TypedWhichId<T> nWhich, bool bSearchInParent = true ) const + { + return GetItem<T>(sal_uInt16(nWhich), bSearchInParent); + } + + + /// Templatized static version of GetItem() to directly return the correct type if the SfxItemSet is available. + template<class T> static const T* GetItem(const SfxItemSet* pItemSet, sal_uInt16 nWhich, bool bSearchInParent) + { + if (pItemSet) + return pItemSet->GetItem<T>(nWhich, bSearchInParent); + + return nullptr; + } + template <class T> + static const T* GetItem(const SfxItemSet* pItemSet, TypedWhichId<T> nWhich, + bool bSearchInParent) + { + return GetItem<T>(pItemSet, static_cast<sal_uInt16>(nWhich), bSearchInParent); + } + + sal_uInt16 GetWhichByOffset(sal_uInt16 nOffset) const; + + SfxItemState GetItemState(sal_uInt16 nWhich, bool bSrchInParent = true, const SfxPoolItem **ppItem = nullptr) const + { + // use local helper, start value for looped-through SfxItemState value is SfxItemState::UNKNOWN + return GetItemState_ForWhichID(SfxItemState::UNKNOWN, nWhich, bSrchInParent, ppItem); + } + + template <class T> SfxItemState GetItemState(TypedWhichId<T> nWhich, bool bSrchInParent = true, const T **ppItem = nullptr ) const + { + // use local helper, start value for looped-through SfxItemState value is SfxItemState::UNKNOWN + return GetItemState_ForWhichID(SfxItemState::UNKNOWN, sal_uInt16(nWhich), bSrchInParent, reinterpret_cast<SfxPoolItem const**>(ppItem)); + } + + /// Templatized version of GetItemState() to directly return the correct type. + template<class T> + const T * GetItemIfSet( TypedWhichId<T> nWhich, + bool bSrchInParent = true ) const + { + const SfxPoolItem * pItem = nullptr; + if (SfxItemState::SET == GetItemState_ForWhichID(SfxItemState::UNKNOWN, sal_uInt16(nWhich), bSrchInParent, &pItem)) + return static_cast<const T*>(pItem); + return nullptr; + } + + bool HasItem(sal_uInt16 nWhich, const SfxPoolItem** ppItem = nullptr) const; + template<class T> + bool HasItem(TypedWhichId<T> nWhich, const T** ppItem = nullptr) const + { return HasItem(sal_uInt16(nWhich), reinterpret_cast<const SfxPoolItem**>(ppItem)); } + + void DisableItem(sal_uInt16 nWhich); + void InvalidateItem(sal_uInt16 nWhich) + { InvalidateItem_ForWhichID(nWhich); } + sal_uInt16 ClearItem( sal_uInt16 nWhich = 0); + void ClearInvalidItems(); + void InvalidateAllItems(); // HACK(via nWhich = 0) ??? + + inline void SetParent( const SfxItemSet* pNew ); + + // add, delete items, work on items +public: + const SfxPoolItem* Put( const SfxPoolItem& rItem, sal_uInt16 nWhich ) + { return PutImpl(rItem, nWhich, /*bPassingOwnership*/false); } + const SfxPoolItem* Put( std::unique_ptr<SfxPoolItem> xItem, sal_uInt16 nWhich ) + { return PutImpl(*xItem.release(), nWhich, /*bPassingOwnership*/true); } + const SfxPoolItem* Put( const SfxPoolItem& rItem ) + { return Put(rItem, rItem.Which()); } + const SfxPoolItem* Put( std::unique_ptr<SfxPoolItem> xItem ) + { auto nWhich = xItem->Which(); return Put(std::move(xItem), nWhich); } + bool Put( const SfxItemSet&, + bool bInvalidAsDefault = true ); + void PutExtended( const SfxItemSet&, + SfxItemState eDontCareAs, + SfxItemState eDefaultAs ); + + bool Set( const SfxItemSet&, bool bDeep = true ); + + void Intersect( const SfxItemSet& rSet ); + void MergeValues( const SfxItemSet& rSet ); + void Differentiate( const SfxItemSet& rSet ); + void MergeValue( const SfxPoolItem& rItem, bool bOverwriteDefaults = false ); + + SfxItemPool* GetPool() const { return m_pPool; } + const WhichRangesContainer & GetRanges() const { return m_pWhichRanges; } + void SetRanges( const WhichRangesContainer& ); + void SetRanges( WhichRangesContainer&& ); + void MergeRange( sal_uInt16 nFrom, sal_uInt16 nTo ); + const SfxItemSet* GetParent() const { return m_pParent; } + + bool operator==(const SfxItemSet &) const; + + /** Compare possibly ignoring SfxItemPool pointer. + + This can be used to compare the content of two SfxItemSet even if they + don't share the same pool. EditTextObject::Equals(...,false) uses this + which is needed in ScGlobal::EETextObjEqual() for + ScPageHFItem::operator==() + + @param bComparePool + if <FALSE/> ignore SfxItemPool pointer, + if <TRUE/> compare also SfxItemPool pointer (identical to operator==()) + */ + bool Equals(const SfxItemSet &, bool bComparePool) const; + + void dumpAsXml(xmlTextWriterPtr pWriter) const; + +private: + // split version(s) of ClearSingleItemImpl for input types WhichID and Offset + sal_uInt16 ClearSingleItem_ForWhichID( sal_uInt16 nWhich ); + sal_uInt16 ClearSingleItem_ForOffset( sal_uInt16 nOffset ); + + // cleanup all Items, but do not reset/change m_ppItems array. That is + // responsibility of the caller & allows specific resets + sal_uInt16 ClearAllItemsImpl(); + + // Merge two given Item(entries) + void MergeItem_Impl(const SfxPoolItem **ppFnd1, const SfxPoolItem *pFnd2, bool bIgnoreDefaults); + + // split version(s) of InvalidateItem for input types WhichID and Offset + void InvalidateItem_ForWhichID(sal_uInt16 nWhich); + void InvalidateItem_ForOffset(sal_uInt16 nOffset); + + // 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; +}; + +inline void SfxItemSet::SetParent( const SfxItemSet* pNew ) +{ + m_pParent = pNew; +} + +class SVL_DLLPUBLIC SfxAllItemSet final : public SfxItemSet + +// Handles all Ranges. Ranges are automatically modified by putting items. + +{ +public: + SfxAllItemSet( SfxItemPool &rPool ); + SfxAllItemSet( const SfxItemSet & ); + SfxAllItemSet( const SfxAllItemSet & ); + + virtual std::unique_ptr<SfxItemSet> Clone( bool bItems = true, SfxItemPool *pToPool = nullptr ) const override; +private: + virtual const SfxPoolItem* PutImpl( const SfxPoolItem&, sal_uInt16 nWhich, bool bPassingOwnership ) override; +}; + + +namespace svl::detail +{ +/** + * Determines the number of sal_uInt16s in a container of pairs of + * sal_uInt16s, each representing a range of sal_uInt16s, and total capacity of the ranges. + */ +template <sal_uInt16 WID1, sal_uInt16 WID2, sal_uInt16... Rest> +static constexpr sal_uInt16 CountRanges1() +{ + sal_uInt16 nCapacity = rangeSize(WID1, WID2); + if constexpr (sizeof...(Rest) > 0) + nCapacity += CountRanges1<Rest...>(); + return nCapacity; +}} + +// Allocate the items array inside the object, to reduce allocation cost. +// +template<sal_uInt16... WIDs> +class SfxItemSetFixed : public SfxItemSet +{ +public: + SfxItemSetFixed( SfxItemPool& rPool) + : SfxItemSet(rPool, WhichRangesContainer(svl::Items_t<WIDs...>{}), m_aItems, NITEMS) {} +private: + static constexpr sal_uInt16 NITEMS = svl::detail::CountRanges1<WIDs...>(); + const SfxPoolItem* m_aItems[NITEMS] = {}; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |