diff options
-rw-r--r-- | include/svl/itemiter.hxx | 32 | ||||
-rw-r--r-- | include/svl/itemset.hxx | 10 | ||||
-rw-r--r-- | sc/source/core/data/patattr.cxx | 6 | ||||
-rw-r--r-- | solenv/gdb/libreoffice/svl.py | 44 | ||||
-rw-r--r-- | svl/qa/unit/items/test_itempool.cxx | 55 | ||||
-rw-r--r-- | svl/source/items/itemiter.cxx | 62 | ||||
-rw-r--r-- | svl/source/items/itemset.cxx | 1000 | ||||
-rw-r--r-- | svx/source/dialog/srchdlg.cxx | 2 | ||||
-rw-r--r-- | sw/source/core/crsr/findattr.cxx | 8 | ||||
-rw-r--r-- | sw/source/core/undo/undobj1.cxx | 3 | ||||
-rw-r--r-- | sw/source/uibase/app/docstyle.cxx | 3 |
11 files changed, 740 insertions, 485 deletions
diff --git a/include/svl/itemiter.hxx b/include/svl/itemiter.hxx index b68730f245d6..30b6bd13d00d 100644 --- a/include/svl/itemiter.hxx +++ b/include/svl/itemiter.hxx @@ -21,7 +21,6 @@ #include <svl/svldllapi.h> #include <svl/itemset.hxx> -#include <vector> class SfxPoolItem; class SfxItemSet; @@ -29,23 +28,32 @@ class SfxItemPool; class SVL_DLLPUBLIC SfxItemIter { - const SfxItemSet& m_rSet; - std::vector<sal_uInt16> m_keys; - std::vector<sal_uInt16>::const_iterator m_iter; + const SfxItemSet& m_rSet; + sal_uInt16 m_nStart; + sal_uInt16 m_nEnd; + sal_uInt16 m_nCurrent; public: SfxItemIter( const SfxItemSet& rSet ); ~SfxItemIter(); /// get item, or null if no items - SfxPoolItem const * FirstItem(); - SfxPoolItem const * GetCurItem(); - SfxPoolItem const * NextItem(); - - bool IsAtEnd() const; - sal_uInt16 GetCurWhich() const { return *m_iter; } - sal_uInt16 GetFirstWhich() const { return *m_keys.begin(); } - sal_uInt16 GetLastWhich() const { return *m_keys.rbegin(); } + const SfxPoolItem* FirstItem() + { + m_nCurrent = m_nStart; + return m_rSet.m_nCount ? *(m_rSet.m_pItems + m_nCurrent) : nullptr; + } + const SfxPoolItem* GetCurItem() + { + return m_rSet.m_nCount ? *(m_rSet.m_pItems + m_nCurrent) : nullptr; + } + const SfxPoolItem* NextItem(); + + bool IsAtEnd() const { return m_nCurrent == m_nEnd; } + + sal_uInt16 GetCurPos() const { return m_nCurrent; } + sal_uInt16 GetFirstPos() const { return m_nStart; } + sal_uInt16 GetLastPos() const { return m_nEnd; } }; #endif diff --git a/include/svl/itemset.hxx b/include/svl/itemset.hxx index 8c1ebd5b8109..dccebd2b23b3 100644 --- a/include/svl/itemset.hxx +++ b/include/svl/itemset.hxx @@ -23,13 +23,12 @@ #include <cstdarg> #include <svl/poolitem.hxx> -#include <map> class SfxItemPool; class SfxPoolItem; class SvStream; -typedef std::map<sal_uInt16, SfxPoolItem const *> SfxItemMap; +typedef SfxPoolItem const** SfxItemArray; class SAL_WARN_UNUSED SVL_DLLPUBLIC SfxItemSet { @@ -37,8 +36,9 @@ class SAL_WARN_UNUSED SVL_DLLPUBLIC SfxItemSet SfxItemPool* m_pPool; ///< pool that stores the items const SfxItemSet* m_pParent; ///< derivation - SfxItemMap m_aItems; ///< array of items + SfxItemArray m_pItems; ///< array of items sal_uInt16* m_pWhichRanges; ///< array of Which Ranges + sal_uInt16 m_nCount; ///< number of items friend class SfxItemPoolCache; friend class SfxAllItemSet; @@ -50,7 +50,7 @@ private: SVL_DLLPRIVATE void InitRanges_Impl(sal_uInt16 nWh1, sal_uInt16 nWh2); public: - SfxItemMap const & GetItems_Impl() const { return m_aItems; } + SfxItemArray GetItems_Impl() const { return m_pItems; } private: const SfxItemSet& operator=(const SfxItemSet &) = delete; @@ -73,7 +73,7 @@ public: virtual SfxItemSet * Clone(bool bItems = true, SfxItemPool *pToPool = nullptr) const; // Get number of items - sal_uInt16 Count() const { return m_aItems.size(); } + sal_uInt16 Count() const { return m_nCount; } sal_uInt16 TotalCount() const; const SfxPoolItem& Get( sal_uInt16 nWhich, bool bSrchInParent = true ) const; diff --git a/sc/source/core/data/patattr.cxx b/sc/source/core/data/patattr.cxx index fd8c8f7f1dd4..133b9809eb33 100644 --- a/sc/source/core/data/patattr.cxx +++ b/sc/source/core/data/patattr.cxx @@ -126,10 +126,10 @@ inline bool EqualPatternSets( const SfxItemSet& rSet1, const SfxItemSet& rSet2 ) if ( rSet1.Count() != rSet2.Count() ) return false; - SfxItemMap const & rItems1 = rSet1.GetItems_Impl(); // inline method of SfxItemSet - SfxItemMap const & rItems2 = rSet2.GetItems_Impl(); + SfxItemArray pItems1 = rSet1.GetItems_Impl(); // inline method of SfxItemSet + SfxItemArray pItems2 = rSet2.GetItems_Impl(); - return rItems1 == rItems2; + return ( 0 == memcmp( pItems1, pItems2, (ATTR_PATTERN_END - ATTR_PATTERN_START + 1) * sizeof(pItems1[0]) ) ); } bool ScPatternAttr::operator==( const SfxPoolItem& rCmp ) const diff --git a/solenv/gdb/libreoffice/svl.py b/solenv/gdb/libreoffice/svl.py index f7d5dbcc5e90..05049652c434 100644 --- a/solenv/gdb/libreoffice/svl.py +++ b/solenv/gdb/libreoffice/svl.py @@ -34,8 +34,48 @@ class ItemSetPrinter(object): return whiches def children(self): - children = [ ( 'items', self.value['m_aItems'] ) ] - return children.__iter__() + whichranges = self.which_ranges() + size = 0 + whichids = [] + for (whichfrom, whichto) in whichranges: + size += whichto - whichfrom + 1 + whichids += [which for which in range(whichfrom, whichto+1)] + return self._iterator(self.value['m_pItems'], size, whichids) + + class _iterator(six.Iterator): + + def __init__(self, data, count, whichids): + self.data = data + self.whichids = whichids + self.count = count + self.pos = 0 + self._check_invariant() + + def __iter__(self): + return self + + def __next__(self): + if self.pos == self.count: + raise StopIteration() + + which = self.whichids[self.pos] + elem = self.data[self.pos] + self.pos = self.pos + 1 + + self._check_invariant() + if (elem == -1): + elem = "(Invalid)" + elif (elem != 0): + # let's try how well that works... + elem = elem.cast(elem.dynamic_type).dereference() + return (str(which), elem) + + def _check_invariant(self): + assert self.count >= 0 + assert self.data + assert self.pos >= 0 + assert self.pos <= self.count + assert len(self.whichids) == self.count printer = None diff --git a/svl/qa/unit/items/test_itempool.cxx b/svl/qa/unit/items/test_itempool.cxx index 0987a6bc548a..00c2c2ee6eda 100644 --- a/svl/qa/unit/items/test_itempool.cxx +++ b/svl/qa/unit/items/test_itempool.cxx @@ -8,8 +8,6 @@ */ #include <svl/itempool.hxx> -#include <svl/itemset.hxx> -#include <svl/itemiter.hxx> #include <poolio.hxx> #include <cppunit/TestAssert.h> @@ -23,11 +21,13 @@ class PoolItemTest : public CppUnit::TestFixture PoolItemTest() {} void testPool(); - void testItemSet(); + // Adds code needed to register the test suite CPPUNIT_TEST_SUITE(PoolItemTest); + CPPUNIT_TEST(testPool); - CPPUNIT_TEST(testItemSet); + + // End of test suite definition CPPUNIT_TEST_SUITE_END(); }; @@ -99,53 +99,6 @@ void PoolItemTest::testPool() CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), pImpl->maPoolItems[3]->maFree.size()); } -void PoolItemTest::testItemSet() -{ - SfxItemInfo aItems[] = - { { 1, false }, - { 2, false }, - { 3, false }, - { 4, false }, - { 5, false }, - { 6, false }, - { 7, false } - }; - - SfxItemPool *pPool = new SfxItemPool("testpool", 1, 7, aItems); - std::vector<SfxPoolItem*> aDefaults { - new SfxVoidItem(1), - new SfxVoidItem(2), - new SfxVoidItem(3), - new SfxVoidItem(4), - new SfxVoidItem(5), - new SfxVoidItem(6), - new SfxVoidItem(7) - }; - pPool->SetDefaults(&aDefaults); - - SfxItemSet aItemSet(*pPool, 1, 3, 5, 7, 0); - aItemSet.Put(SfxVoidItem(1)); - aItemSet.Put(SfxVoidItem(2)); - aItemSet.Put(SfxVoidItem(3)); - aItemSet.Put(SfxVoidItem(5)); - aItemSet.Put(SfxVoidItem(6)); - aItemSet.Put(SfxVoidItem(7)); - - SfxItemIter aIter(aItemSet); - - CPPUNIT_ASSERT_EQUAL((sal_uInt16)1, aIter.GetFirstWhich()); - CPPUNIT_ASSERT_EQUAL((sal_uInt16)7, aIter.GetLastWhich()); - const SfxPoolItem *pFirstItem = aIter.FirstItem(); - CPPUNIT_ASSERT(pFirstItem); - CPPUNIT_ASSERT_EQUAL((sal_uInt16)1, pFirstItem->Which()); - CPPUNIT_ASSERT_EQUAL((sal_uInt16)2, aIter.NextItem()->Which()); - CPPUNIT_ASSERT_EQUAL((sal_uInt16)3, aIter.NextItem()->Which()); - CPPUNIT_ASSERT_EQUAL((sal_uInt16)5, aIter.NextItem()->Which()); - CPPUNIT_ASSERT_EQUAL((sal_uInt16)6, aIter.NextItem()->Which()); - CPPUNIT_ASSERT_EQUAL((sal_uInt16)7, aIter.NextItem()->Which()); - CPPUNIT_ASSERT_EQUAL(static_cast<const SfxPoolItem*>(nullptr), aIter.NextItem()); - CPPUNIT_ASSERT_EQUAL(true, aIter.IsAtEnd()); -} CPPUNIT_TEST_SUITE_REGISTRATION(PoolItemTest); diff --git a/svl/source/items/itemiter.cxx b/svl/source/items/itemiter.cxx index e1e8baade8be..a42a90bc2358 100644 --- a/svl/source/items/itemiter.cxx +++ b/svl/source/items/itemiter.cxx @@ -25,50 +25,44 @@ SfxItemIter::SfxItemIter( const SfxItemSet& rItemSet ) : m_rSet( rItemSet ) { - // store the set of keys because client code likes modifying the map - // while iterating over it - m_keys.resize(rItemSet.m_aItems.size()); - size_t idx = 0; - for (auto const & rPair : rItemSet.m_aItems) { - m_keys[idx++] = rPair.first; + if (!m_rSet.m_nCount) + { + m_nStart = 1; + m_nEnd = 0; } - m_iter = m_keys.begin(); -} + else + { + SfxItemArray ppFnd = m_rSet.m_pItems; -SfxItemIter::~SfxItemIter() -{ -} + // Find the first Item that is set + for (m_nStart = 0; !*(ppFnd + m_nStart ); ++m_nStart) + ; // empty loop + if (1 < m_rSet.Count()) + for (m_nEnd = m_rSet.TotalCount(); !*(ppFnd + --m_nEnd); ) + ; // empty loop + else + m_nEnd = m_nStart; + } -SfxPoolItem const * SfxItemIter::FirstItem() -{ - m_iter = m_keys.begin(); - return GetCurItem(); + m_nCurrent = m_nStart; } -SfxPoolItem const * SfxItemIter::GetCurItem() +SfxItemIter::~SfxItemIter() { - if (m_keys.empty()) - return nullptr; - auto it = m_rSet.m_aItems.find(*m_iter); - if (it == m_rSet.m_aItems.end()) - return nullptr; - return it->second; } -SfxPoolItem const * SfxItemIter::NextItem() +const SfxPoolItem* SfxItemIter::NextItem() { - if (m_iter == m_keys.end()) - return nullptr; - ++m_iter; - if (m_iter == m_keys.end()) - return nullptr; - return GetCurItem(); -} + SfxItemArray ppFnd = m_rSet.m_pItems; -bool SfxItemIter::IsAtEnd() const -{ - return m_iter == m_keys.end() || std::next(m_iter) == m_keys.end(); + if (m_nCurrent < m_nEnd) + { + do { + m_nCurrent++; + } while (m_nCurrent < m_nEnd && !*(ppFnd + m_nCurrent )); + return *(ppFnd+m_nCurrent); + } + return nullptr; } - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/svl/source/items/itemset.cxx b/svl/source/items/itemset.cxx index 468ecb75f06d..9e44a8ba1889 100644 --- a/svl/source/items/itemset.cxx +++ b/svl/source/items/itemset.cxx @@ -101,6 +101,25 @@ sal_uInt16 Count_Impl( const sal_uInt16 *pRanges ) return nCount; } +/** + * Determines the total number of sal_uInt16s described in a 0-terminated + * array of pairs of sal_uInt16s, each representing an range of sal_uInt16s. + */ +sal_uInt16 Capacity_Impl( const sal_uInt16 *pRanges ) +{ + sal_uInt16 nCount = 0; + + if ( pRanges ) + { + while ( *pRanges ) + { + nCount += pRanges[1] - pRanges[0] + 1; + pRanges += 2; + } + } + return nCount; +} + } /** @@ -113,16 +132,21 @@ sal_uInt16 Count_Impl( const sal_uInt16 *pRanges ) SfxItemSet::SfxItemSet(SfxItemPool& rPool) : m_pPool( &rPool ) , m_pParent(nullptr) + , m_nCount(0) { m_pWhichRanges = const_cast<sal_uInt16*>(m_pPool->GetFrozenIdRanges()); assert( m_pWhichRanges && "don't create ItemSets with full range before FreezeIdRanges()" ); if (!m_pWhichRanges) m_pPool->FillItemIdRanges_Impl( m_pWhichRanges ); + + const sal_uInt16 nSize = TotalCount(); + m_pItems = new const SfxPoolItem*[nSize]{}; } SfxItemSet::SfxItemSet(SfxItemPool& rPool, sal_uInt16 nWhich1, sal_uInt16 nWhich2) : m_pPool( &rPool ) , m_pParent(nullptr) + , m_nCount(0) { assert(nWhich1 <= nWhich2); @@ -132,17 +156,21 @@ SfxItemSet::SfxItemSet(SfxItemPool& rPool, sal_uInt16 nWhich1, sal_uInt16 nWhich void SfxItemSet::InitRanges_Impl(sal_uInt16 nWh1, sal_uInt16 nWh2) { m_pWhichRanges = new sal_uInt16[3]{nWh1, nWh2, 0}; + const sal_uInt16 nRg = nWh2 - nWh1 + 1; + m_pItems = new const SfxPoolItem*[nRg]{}; } void SfxItemSet::InitRanges_Impl(va_list pArgs, sal_uInt16 nWh1, sal_uInt16 nWh2, sal_uInt16 nNull) { - InitializeRanges_Impl(m_pWhichRanges, pArgs, nWh1, nWh2, nNull); + sal_uInt16 nSize = InitializeRanges_Impl(m_pWhichRanges, pArgs, nWh1, nWh2, nNull); + m_pItems = new const SfxPoolItem*[nSize]{}; } SfxItemSet::SfxItemSet(SfxItemPool& rPool, int nWh1, int nWh2, int nNull, ...) : m_pPool( &rPool ) , m_pParent(nullptr) , m_pWhichRanges(nullptr) + , m_nCount(0) { assert(nWh1 <= nWh2); @@ -171,6 +199,8 @@ void SfxItemSet::InitRanges_Impl(const sal_uInt16 *pWhichPairTable) pPtr += 2; } + m_pItems = new const SfxPoolItem*[nCnt]{}; + std::ptrdiff_t cnt = pPtr - pWhichPairTable +1; m_pWhichRanges = new sal_uInt16[ cnt ]; memcpy( m_pWhichRanges, pWhichPairTable, sizeof( sal_uInt16 ) * cnt ); @@ -179,7 +209,9 @@ void SfxItemSet::InitRanges_Impl(const sal_uInt16 *pWhichPairTable) SfxItemSet::SfxItemSet( SfxItemPool& rPool, const sal_uInt16* pWhichPairTable ) : m_pPool(&rPool) , m_pParent(nullptr) + , m_pItems(nullptr) , m_pWhichRanges(nullptr) + , m_nCount(0) { // pWhichPairTable == 0 is for the SfxAllEnumItemSet if ( pWhichPairTable ) @@ -189,6 +221,7 @@ SfxItemSet::SfxItemSet( SfxItemPool& rPool, const sal_uInt16* pWhichPairTable ) SfxItemSet::SfxItemSet( const SfxItemSet& rASet ) : m_pPool( rASet.m_pPool ) , m_pParent( rASet.m_pParent ) + , m_nCount( rASet.m_nCount ) { // Calculate the attribute count sal_uInt16 nCnt = 0; @@ -199,51 +232,58 @@ SfxItemSet::SfxItemSet( const SfxItemSet& rASet ) pPtr += 2; } + m_pItems = new const SfxPoolItem* [ nCnt ]; + // Copy attributes - SfxItemMap ppDst = m_aItems, ppSrc = rASet.m_aItems; - for (auto & rSrcPair : rASet.m_aItems) - { - if ( IsInvalidItem(rSrcPair.second) || // DontCare? - IsStaticDefaultItem(rSrcPair.second) ) // Defaults that are not to be pooled? + SfxItemArray ppDst = m_pItems, ppSrc = rASet.m_pItems; + for( sal_uInt16 n = nCnt; 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 - m_aItems.insert(rSrcPair); - else if (m_pPool->IsItemPoolable( *rSrcPair.second )) + *ppDst = *ppSrc; + else if (m_pPool->IsItemPoolable( **ppSrc )) { // Just copy the pointer and increase RefCount - m_aItems.insert(rSrcPair); - rSrcPair.second->AddRef(); + *ppDst = *ppSrc; + (*ppDst)->AddRef(); } - else if ( !rSrcPair.second->Which() ) - m_aItems[rSrcPair.first] = rSrcPair.second->Clone(); + else if ( !(*ppSrc)->Which() ) + *ppDst = (*ppSrc)->Clone(); else // !IsPoolable() => assign via Pool - m_aItems[rSrcPair.first] = &m_pPool->Put( *rSrcPair.second ); - } + *ppDst = &m_pPool->Put( **ppSrc ); // Copy the WhichRanges - std::ptrdiff_t cnt = pPtr - rASet.m_pWhichRanges + 1; + std::ptrdiff_t cnt = pPtr - rASet.m_pWhichRanges+1; m_pWhichRanges = new sal_uInt16[ cnt ]; memcpy( m_pWhichRanges, rASet.m_pWhichRanges, sizeof( sal_uInt16 ) * cnt); } SfxItemSet::~SfxItemSet() { - for (auto & rPair : m_aItems) - if( !IsInvalidItem(rPair.second) ) - { - if( !rPair.second->Which() ) - delete rPair.second; - else { - // Still multiple references present, so just alter the RefCount - if ( 1 < rPair.second->GetRefCount() && !IsDefaultItem(rPair.second) ) - rPair.second->ReleaseRef(); - else - if ( !IsDefaultItem(rPair.second) ) - // Delete from Pool - m_pPool->Remove( *rPair.second ); + sal_uInt16 nCount = TotalCount(); + if( Count() ) + { + SfxItemArray ppFnd = m_pItems; + for( sal_uInt16 nCnt = nCount; 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 ); + } } - } + } + delete[] m_pItems; if (m_pWhichRanges != m_pPool->GetFrozenIdRanges()) delete[] m_pWhichRanges; m_pWhichRanges = nullptr; // for invariant-testing @@ -258,67 +298,89 @@ sal_uInt16 SfxItemSet::ClearItem( sal_uInt16 nWhich ) return 0; sal_uInt16 nDel = 0; + SfxItemArray ppFnd = m_pItems; if( nWhich ) { - auto it = m_aItems.find(nWhich); - if (it != m_aItems.end()) + const sal_uInt16* pPtr = m_pWhichRanges; + while( *pPtr ) { - const SfxPoolItem *pItemToClear = it->second; - m_aItems.erase(it); - // Due to the assertions in the sub calls, we need to do the following - - if ( !IsInvalidItem(pItemToClear) ) + // Within this range? + if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) { - if (SfxItemPool::IsWhich(nWhich)) + // Actually set? + ppFnd += nWhich - *pPtr; + if( *ppFnd ) { - const SfxPoolItem& rNew = m_pParent - ? m_pParent->Get( nWhich ) - : m_pPool->GetDefaultItem( nWhich ); + // Due to the assertions in the sub calls, we need to do the following + --m_nCount; + const SfxPoolItem *pItemToClear = *ppFnd; + *ppFnd = nullptr; - Changed( *pItemToClear, rNew ); + if ( !IsInvalidItem(pItemToClear) ) + { + if (SfxItemPool::IsWhich(nWhich)) + { + const SfxPoolItem& rNew = m_pParent + ? m_pParent->Get( nWhich ) + : m_pPool->GetDefaultItem( nWhich ); + + Changed( *pItemToClear, rNew ); + } + if ( pItemToClear->Which() ) + m_pPool->Remove( *pItemToClear ); + } + ++nDel; } - if ( pItemToClear->Which() ) - m_pPool->Remove( *pItemToClear ); + + // found => break + break; } - ++nDel; + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; } } else { - nDel = m_aItems.size(); + nDel = m_nCount; - SfxItemMap aTmp; - aTmp.swap(m_aItems); - for (auto & rPair : aTmp) + sal_uInt16* pPtr = m_pWhichRanges; + while( *pPtr ) { - const SfxPoolItem *pItemToClear = rPair.second; - nWhich = rPair.first; - - if ( !IsInvalidItem(pItemToClear) ) - { - if (SfxItemPool::IsWhich(nWhich)) + for( nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd ) + if( *ppFnd ) { - const SfxPoolItem& rNew = m_pParent - ? m_pParent->Get( nWhich ) - : m_pPool->GetDefaultItem( nWhich ); - - Changed( *pItemToClear, rNew ); - } - - // #i32448# - // Take care of disabled items, too. - if (!pItemToClear->m_nWhich) - { - // item is disabled, delete it - delete pItemToClear; - } - else - { - // remove item from pool - m_pPool->Remove( *pItemToClear ); - } - } + // Due to the assertions in the sub calls, we need to do this + --m_nCount; + const SfxPoolItem *pItemToClear = *ppFnd; + *ppFnd = nullptr; + + if ( !IsInvalidItem(pItemToClear) ) + { + if (SfxItemPool::IsWhich(nWhich)) + { + const SfxPoolItem& rNew = m_pParent + ? m_pParent->Get( nWhich ) + : m_pPool->GetDefaultItem( nWhich ); + + Changed( *pItemToClear, rNew ); + } + + // #i32448# + // Take care of disabled items, too. + if (!pItemToClear->m_nWhich) + { + // item is disabled, delete it + delete pItemToClear; + } + else + { + // remove item from pool + m_pPool->Remove( *pItemToClear ); + } + } + } + pPtr += 2; } } return nDel; @@ -326,30 +388,25 @@ sal_uInt16 SfxItemSet::ClearItem( sal_uInt16 nWhich ) void SfxItemSet::ClearInvalidItems() { - for (auto it = m_aItems.begin(); it != m_aItems.end(); ) + sal_uInt16* pPtr = m_pWhichRanges; + SfxItemArray ppFnd = m_pItems; + while( *pPtr ) { - if( IsInvalidItem(it->second) ) - { - it = m_aItems.erase(it); - } - else - ++it; + for( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd ) + if( IsInvalidItem(*ppFnd) ) + { + *ppFnd = nullptr; + --m_nCount; + } + pPtr += 2; } } void SfxItemSet::InvalidateAllItems() { - assert( m_aItems.empty() && "There are still Items set" ); - m_aItems.clear(); - const sal_uInt16* pPtr = m_pWhichRanges; - while ( *pPtr ) - { - for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich ) - { - m_aItems[nWhich] = reinterpret_cast<const SfxPoolItem *>(-1); - } - pPtr += 2; - } + assert( !m_nCount && "There are still Items set" ); + m_nCount = TotalCount(); + memset(static_cast<void*>(m_pItems), -1, m_nCount * sizeof(SfxPoolItem*)); } SfxItemState SfxItemSet::GetItemState( sal_uInt16 nWhich, @@ -361,44 +418,39 @@ SfxItemState SfxItemSet::GetItemState( sal_uInt16 nWhich, SfxItemState eRet = SfxItemState::UNKNOWN; do { + SfxItemArray ppFnd = pAktSet->m_pItems; const sal_uInt16* pPtr = pAktSet->m_pWhichRanges; - bool bFound = false; if (pPtr) { while ( *pPtr ) { if ( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) { - bFound = true; - break; - } - pPtr += 2; - } - } - if (bFound) - { - auto it = pAktSet->m_aItems.find(nWhich); - if ( it == pAktSet->m_aItems.end()) - { - eRet = SfxItemState::DEFAULT; - if( !bSrchInParent ) - return eRet; // Not present - // Keep searching in the parents! - } - else - { - if ( reinterpret_cast<SfxPoolItem*>(-1) == it->second ) - // Different ones are present - return SfxItemState::DONTCARE; + // Within this range + ppFnd += nWhich - *pPtr; + if ( !*ppFnd ) + { + eRet = SfxItemState::DEFAULT; + if( !bSrchInParent ) + return eRet; // Not present + break; // Keep searching in the parents! + } - if ( dynamic_cast<const SfxVoidItem *>(it->second) != nullptr ) - return SfxItemState::DISABLED; + if ( reinterpret_cast<SfxPoolItem*>(-1) == *ppFnd ) + // Different ones are present + return SfxItemState::DONTCARE; - if (ppItem) - { - *ppItem = it->second; + if ( dynamic_cast<const SfxVoidItem *>(*ppFnd) != nullptr ) + return SfxItemState::DISABLED; + + if (ppItem) + { + *ppItem = *ppFnd; + } + return SfxItemState::SET; } - return SfxItemState::SET; + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; } } } while (bSrchInParent && nullptr != (pAktSet = pAktSet->m_pParent)); @@ -418,83 +470,82 @@ const SfxPoolItem* SfxItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich if ( !nWhich ) return nullptr; //FIXME: Only because of Outliner bug - bool bFound = false; + SfxItemArray ppFnd = m_pItems; const sal_uInt16* pPtr = m_pWhichRanges; while( *pPtr ) { if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) { - bFound = true; - break; - } - pPtr += 2; - } - if (!bFound) - return nullptr; - - auto it = m_aItems.find(nWhich); - if (it != m_aItems.end()) // Already one present - { - // Same Item already present? - if ( it->second == &rItem ) - return nullptr; + // Within this range + ppFnd += nWhich - *pPtr; + if( *ppFnd ) // Already one present + { + // Same Item already present? + if ( *ppFnd == &rItem ) + return nullptr; - // Will 'dontcare' or 'disabled' be overwritten with some real value? - if ( rItem.Which() && ( IsInvalidItem(it->second) || !it->second->Which() ) ) - { - auto const old = it->second; - it->second = &m_pPool->Put( rItem, nWhich ); - if (!IsInvalidItem(old)) { - assert(old->Which() == 0); - delete old; - } - return it->second; - } + // Will 'dontcare' or 'disabled' be overwritten with some real value? + if ( rItem.Which() && ( IsInvalidItem(*ppFnd) || !(*ppFnd)->Which() ) ) + { + auto const old = *ppFnd; + *ppFnd = &m_pPool->Put( rItem, nWhich ); + if (!IsInvalidItem(old)) { + assert(old->Which() == 0); + delete old; + } + return *ppFnd; + } - // Turns into disabled? - if( !rItem.Which() ) - { - if (IsInvalidItem(it->second) || it->second->Which() != 0) { - it->second = rItem.Clone(m_pPool); + // Turns into disabled? + if( !rItem.Which() ) + { + if (IsInvalidItem(*ppFnd) || (*ppFnd)->Which() != 0) { + *ppFnd = rItem.Clone(m_pPool); + } + return nullptr; + } + else + { + // Same value already present? + if ( rItem == **ppFnd ) + return nullptr; + + // Add the new one, remove the old one + const SfxPoolItem& rNew = m_pPool->Put( rItem, nWhich ); + const SfxPoolItem* pOld = *ppFnd; + *ppFnd = &rNew; + if (SfxItemPool::IsWhich(nWhich)) + Changed( *pOld, rNew ); + m_pPool->Remove( *pOld ); + } } - return nullptr; - } - else - { - // Same value already present? - if ( rItem == *it->second ) - return nullptr; - - // Add the new one, remove the old one - const SfxPoolItem& rNew = m_pPool->Put( rItem, nWhich ); - const SfxPoolItem* pOld = it->second; - it->second = &rNew; - if (SfxItemPool::IsWhich(nWhich)) - Changed( *pOld, rNew ); - m_pPool->Remove( *pOld ); - } - } - else - { - if( !rItem.Which() ) - it = m_aItems.insert({ nWhich, rItem.Clone(m_pPool)}).first; - else { - const SfxPoolItem& rNew = m_pPool->Put( rItem, nWhich ); - it = m_aItems.insert({nWhich, &rNew}).first; - if (SfxItemPool::IsWhich(nWhich)) + else { - const SfxPoolItem& rOld = m_pParent - ? m_pParent->Get( nWhich ) - : m_pPool->GetDefaultItem( nWhich ); - Changed( rOld, rNew ); + ++m_nCount; + if( !rItem.Which() ) + *ppFnd = rItem.Clone(m_pPool); + else { + const SfxPoolItem& rNew = m_pPool->Put( rItem, nWhich ); + *ppFnd = &rNew; + if (SfxItemPool::IsWhich(nWhich)) + { + const SfxPoolItem& rOld = m_pParent + ? m_pParent->Get( nWhich ) + : m_pPool->GetDefaultItem( nWhich ); + Changed( rOld, rNew ); + } + } } + SAL_WARN_IF(m_pPool->IsItemPoolable(nWhich) && + dynamic_cast<const SfxSetItem*>( &rItem ) == nullptr && + **ppFnd != rItem, + "svl.items", "putted Item unequal, with ID/pos " << nWhich ); + return *ppFnd; } + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; } - SAL_WARN_IF(m_pPool->IsItemPoolable(nWhich) && - dynamic_cast<const SfxSetItem*>( &rItem ) == nullptr && - *it->second != rItem, - "svl.items", "putted Item unequal, with ID/pos " << nWhich ); - return it->second; + return nullptr; } bool SfxItemSet::Put( const SfxItemSet& rSet, bool bInvalidAsDefault ) @@ -502,19 +553,26 @@ bool SfxItemSet::Put( const SfxItemSet& rSet, bool bInvalidAsDefault ) bool bRet = false; if( rSet.Count() ) { - for (auto const & rPair : rSet.m_aItems) + SfxItemArray ppFnd = rSet.m_pItems; + const sal_uInt16* pPtr = rSet.m_pWhichRanges; + while ( *pPtr ) { - if ( IsInvalidItem( rPair.second ) ) - { - if ( bInvalidAsDefault ) - bRet |= 0 != ClearItem( rPair.first ); - // FIXME: Caused a SEGFAULT on non Windows-platforms: - // bRet |= 0 != Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich ); - else - InvalidateItem( rPair.first ); - } - else - bRet |= nullptr != Put( *rPair.second, rPair.first ); + for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd ) + if( *ppFnd ) + { + if ( IsInvalidItem( *ppFnd ) ) + { + if ( bInvalidAsDefault ) + bRet |= 0 != ClearItem( nWhich ); + // FIXME: Caused a SEGFAULT on non Windows-platforms: + // bRet |= 0 != Put( rSet.GetPool()->GetDefaultItem(nWhich), nWhich ); + else + InvalidateItem( nWhich ); + } + else + bRet |= nullptr != Put( **ppFnd, nWhich ); + } + pPtr += 2; } } return bRet; @@ -543,15 +601,14 @@ void SfxItemSet::PutExtended ) { // don't "optimize" with "if( rSet.Count()" because of dont-care + defaults + SfxItemArray ppFnd = rSet.m_pItems; const sal_uInt16* pPtr = rSet.m_pWhichRanges; while ( *pPtr ) { - for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich ) - { - auto it = rSet.m_aItems.find(nWhich); - if( it != rSet.m_aItems.end() ) + for ( sal_uInt16 nWhich = *pPtr; nWhich <= *(pPtr+1); ++nWhich, ++ppFnd ) + if( *ppFnd ) { - if ( IsInvalidItem( it->second ) ) + if ( IsInvalidItem( *ppFnd ) ) { // Item ist DontCare: switch ( eDontCareAs ) @@ -574,7 +631,7 @@ void SfxItemSet::PutExtended } else // Item is set: - Put( *it->second, nWhich ); + Put( **ppFnd, nWhich ); } else { @@ -597,7 +654,6 @@ void SfxItemSet::PutExtended assert(!"invalid Argument for eDefaultAs"); } } - } pPtr += 2; } } @@ -693,8 +749,12 @@ void SfxItemSet::SetRanges( const sal_uInt16 *pNewRanges ) } // create new item-array (by iterating through all new ranges) - SfxItemMap aNewItems; - if (!m_aItems.empty()) + sal_uLong nSize = Capacity_Impl(pNewRanges); + SfxItemArray aNewItems = new const SfxPoolItem* [ nSize ]; + sal_uInt16 nNewCount = 0; + if (m_nCount == 0) + memset( aNewItems, 0, nSize * sizeof( SfxPoolItem* ) ); + else { sal_uInt16 n = 0; for ( const sal_uInt16 *pRange = pNewRanges; *pRange; pRange += 2 ) @@ -703,40 +763,45 @@ void SfxItemSet::SetRanges( const sal_uInt16 *pNewRanges ) for ( sal_uInt16 nWID = *pRange; nWID <= pRange[1]; ++nWID, ++n ) { // direct move of pointer (not via pool) - auto it = m_aItems.find(nWID); - if ( it == m_aItems.end()) + SfxItemState eState = GetItemState( nWID, false, aNewItems+n ); + if ( SfxItemState::SET == eState ) { - // default + // increment new item count and possibly increment ref count + ++nNewCount; + aNewItems[n]->AddRef(); } - else if ( reinterpret_cast<SfxPoolItem*>(-1) == it->second ) + else if ( SfxItemState::DISABLED == eState ) { - // don't care - aNewItems[nWID] = reinterpret_cast<SfxPoolItem*>(-1); + // put "disabled" item + ++nNewCount; + aNewItems[n] = new SfxVoidItem(0); } - else if ( dynamic_cast<const SfxVoidItem *>(it->second) != nullptr ) + else if ( SfxItemState::DONTCARE == eState ) { - // put "disabled" item - aNewItems[nWID] = new SfxVoidItem(0); + ++nNewCount; + aNewItems[n] = reinterpret_cast<SfxPoolItem*>(-1); } else { - aNewItems[nWID] = it->second; - // increment new item count and possibly increment ref count - aNewItems[nWID]->AddRef(); + // default + aNewItems[n] = nullptr; } } } // free old items - for ( auto & rPair : m_aItems ) + sal_uInt16 nOldTotalCount = TotalCount(); + for ( sal_uInt16 nItem = 0; nItem < nOldTotalCount; ++nItem ) { - const SfxPoolItem *pItem = rPair.second; - if ( !IsInvalidItem(pItem) && pItem->Which() ) + const SfxPoolItem *pItem = m_pItems[nItem]; + if ( pItem && !IsInvalidItem(pItem) && pItem->Which() ) m_pPool->Remove(*pItem); } } // replace old items-array and ranges - m_aItems.swap(aNewItems); + delete[] m_pItems; + m_pItems = aNewItems; + m_nCount = nNewCount; if( pNewRanges == GetPool()->GetFrozenIdRanges() ) { @@ -789,7 +854,7 @@ bool SfxItemSet::Set ) { bool bRet = false; - if (!m_aItems.empty()) + if (m_nCount) ClearItem(); if ( bDeep ) { @@ -833,24 +898,39 @@ const SfxPoolItem& SfxItemSet::Get( sal_uInt16 nWhich, bool bSrchInParent) const { if( pAktSet->Count() ) { - auto it = pAktSet->m_aItems.find(nWhich); - if( it != pAktSet->m_aItems.end() ) + SfxItemArray ppFnd = pAktSet->m_pItems; + const sal_uInt16* pPtr = pAktSet->m_pWhichRanges; + while( *pPtr ) { - if( reinterpret_cast<SfxPoolItem*>(-1) == it->second ) { - //FIXME: The following code is duplicated further down - SAL_WARN_IF(!m_pPool, "svl.items", "no Pool, but status is ambiguous, with ID/pos " << nWhich); - //!((SfxAllItemSet *)this)->aDefault.SetWhich(nWhich); - //!return aDefault; - return m_pPool->GetDefaultItem( nWhich ); - } + if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + // In this Range + ppFnd += nWhich - *pPtr; + if( *ppFnd ) + { + if( reinterpret_cast<SfxPoolItem*>(-1) == *ppFnd ) { + //FIXME: The following code is duplicated further down + SAL_WARN_IF(!m_pPool, "svl.items", "no Pool, but status is ambiguous, with ID/pos " << nWhich); + //!((SfxAllItemSet *)this)->aDefault.SetWhich(nWhich); + //!return aDefault; + return m_pPool->GetDefaultItem( nWhich ); + } #ifdef DBG_UTIL - const SfxPoolItem *pItem = it->second; - if ( dynamic_cast<const SfxVoidItem *>(pItem) != nullptr || !pItem->Which() ) - SAL_INFO("svl.items", "SFX_WARNING: Getting disabled Item"); + const SfxPoolItem *pItem = *ppFnd; + if ( dynamic_cast<const SfxVoidItem *>(pItem) != nullptr || !pItem->Which() ) + SAL_INFO("svl.items", "SFX_WARNING: Getting disabled Item"); #endif - return *it->second; + return **ppFnd; + } + break; // Continue with Parent + } + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; } } +//TODO: Search until end of Range: What are we supposed to do now? To the Parent or Default?? +// if( !*pPtr ) // Until the end of the search Range? +// break; } while (bSrchInParent && nullptr != (pAktSet = pAktSet->m_pParent)); // Get the Default from the Pool and return @@ -872,7 +952,7 @@ sal_uInt16 SfxItemSet::TotalCount() const sal_uInt16* pPtr = m_pWhichRanges; while( *pPtr ) { - nRet += *(pPtr+1) - *pPtr + 1; + nRet += ( *(pPtr+1) - *pPtr ) + 1; pPtr += 2; } return nRet; @@ -880,7 +960,7 @@ sal_uInt16 SfxItemSet::TotalCount() const /** * Only retain the Items that are also present in rSet - * (never mind their value). + * (nevermind their value). */ void SfxItemSet::Intersect( const SfxItemSet& rSet ) { @@ -895,17 +975,64 @@ void SfxItemSet::Intersect( const SfxItemSet& rSet ) return; } - // get the set of keys since we are going to be modifying - // the map while we iterate over it - std::vector<sal_uInt16> keys(m_aItems.size()); - size_t idx = 0; - for (auto const & rPair : m_aItems) { - keys[idx++] = rPair.first; + // Test whether the Which Ranges are different + sal_uInt16* pWh1 = m_pWhichRanges; + sal_uInt16* pWh2 = rSet.m_pWhichRanges; + sal_uInt16 nSize = 0; + + for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n ) + { + if( *pWh1 != *pWh2 ) + { + break; + } + if( n & 1 ) + nSize += ( *(pWh1) - *(pWh1-1) ) + 1; + } + bool bEqual = *pWh1 == *pWh2; // Also check for 0 + + // If the Ranges are identical, we can easily process it + if( bEqual ) + { + SfxItemArray ppFnd1 = m_pItems; + SfxItemArray ppFnd2 = rSet.m_pItems; + + for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 ) + if( *ppFnd1 && !*ppFnd2 ) + { + // Delete from Pool + if( !IsInvalidItem( *ppFnd1 ) ) + { + sal_uInt16 nWhich = (*ppFnd1)->Which(); + if (SfxItemPool::IsWhich(nWhich)) + { + const SfxPoolItem& rNew = m_pParent + ? m_pParent->Get( nWhich ) + : m_pPool->GetDefaultItem( nWhich ); + + Changed( **ppFnd1, rNew ); + } + m_pPool->Remove( **ppFnd1 ); + } + *ppFnd1 = nullptr; + --m_nCount; + } } - for (sal_uInt16 nWhich : keys) + else { - if( SfxItemState::UNKNOWN == rSet.GetItemState( nWhich, false ) ) - ClearItem( nWhich ); // Delete + SfxItemIter aIter( *this ); + const SfxPoolItem* pItem = aIter.GetCurItem(); + while( true ) + { + sal_uInt16 nWhich = IsInvalidItem( pItem ) + ? GetWhichByPos( aIter.GetCurPos() ) + : pItem->Which(); + if( SfxItemState::UNKNOWN == rSet.GetItemState( nWhich, false ) ) + ClearItem( nWhich ); // Delete + if( aIter.IsAtEnd() ) + break; + pItem = aIter.NextItem(); + } } } @@ -914,17 +1041,65 @@ void SfxItemSet::Differentiate( const SfxItemSet& rSet ) if( !Count() || !rSet.Count() )// None set? return; - // get the set of keys since we are going to be modifying - // the map while we iterate over it - std::vector<sal_uInt16> keys(m_aItems.size()); - size_t idx = 0; - for (auto const & rPair : m_aItems) { - keys[idx++] = rPair.first; + // Test whether the Which Ranges are different + sal_uInt16* pWh1 = m_pWhichRanges; + sal_uInt16* pWh2 = rSet.m_pWhichRanges; + sal_uInt16 nSize = 0; + + for( sal_uInt16 n = 0; *pWh1 && *pWh2; ++pWh1, ++pWh2, ++n ) + { + if( *pWh1 != *pWh2 ) + { + break; + } + if( n & 1 ) + nSize += ( *(pWh1) - *(pWh1-1) ) + 1; + } + bool bEqual = *pWh1 == *pWh2; // Also test for 0 + + // If the Ranges are identical, we can easily process it + if( bEqual ) + { + SfxItemArray ppFnd1 = m_pItems; + SfxItemArray ppFnd2 = rSet.m_pItems; + + for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 ) + if( *ppFnd1 && *ppFnd2 ) + { + // Delete from Pool + if( !IsInvalidItem( *ppFnd1 ) ) + { + sal_uInt16 nWhich = (*ppFnd1)->Which(); + if (SfxItemPool::IsWhich(nWhich)) + { + const SfxPoolItem& rNew = m_pParent + ? m_pParent->Get( nWhich ) + : m_pPool->GetDefaultItem( nWhich ); + + Changed( **ppFnd1, rNew ); + } + m_pPool->Remove( **ppFnd1 ); + } + *ppFnd1 = nullptr; + --m_nCount; + } } - for (sal_uInt16 nWhich : keys) + else { - if( SfxItemState::SET == rSet.GetItemState( nWhich, false ) ) - ClearItem( nWhich ); // Delete + SfxItemIter aIter( *this ); + const SfxPoolItem* pItem = aIter.GetCurItem(); + while( true ) + { + sal_uInt16 nWhich = IsInvalidItem( pItem ) + ? GetWhichByPos( aIter.GetCurPos() ) + : pItem->Which(); + if( SfxItemState::SET == rSet.GetItemState( nWhich, false ) ) + ClearItem( nWhich ); // Delete + if( aIter.IsAtEnd() ) + break; + pItem = aIter.NextItem(); + } + } } @@ -1006,63 +1181,66 @@ void SfxItemSet::Differentiate( const SfxItemSet& rSet ) * dontcare unknown != sal_True - - - * unknown unknown != sal_True - - - */ -static void MergeItem_Impl( SfxItemPool *_pPool, - SfxItemMap& rItems, sal_uInt16 nWhich, const SfxPoolItem *pFnd2, +static void MergeItem_Impl( SfxItemPool *_pPool, sal_uInt16 &rCount, + const SfxPoolItem **ppFnd1, const SfxPoolItem *pFnd2, bool bIgnoreDefaults ) { - auto ppFnd1 = rItems.find(nWhich); + assert(ppFnd1 != nullptr && "Merging to 0-Item"); // 1st Item is Default? - if ( ppFnd1 == rItems.end() ) + if ( !*ppFnd1 ) { if ( IsInvalidItem(pFnd2) ) // Decision table: default, dontcare, doesn't matter, doesn't matter - rItems[nWhich] = reinterpret_cast<SfxPoolItem*>(-1); + *ppFnd1 = reinterpret_cast<SfxPoolItem*>(-1); else if ( pFnd2 && !bIgnoreDefaults && _pPool->GetDefaultItem(pFnd2->Which()) != *pFnd2 ) // Decision table: default, set, !=, sal_False - rItems[nWhich] = reinterpret_cast<SfxPoolItem*>(-1); + *ppFnd1 = reinterpret_cast<SfxPoolItem*>(-1); else if ( pFnd2 && bIgnoreDefaults ) // Decision table: default, set, doesn't matter, sal_True - rItems[nWhich] = &_pPool->Put( *pFnd2 ); + *ppFnd1 = &_pPool->Put( *pFnd2 ); + + if ( *ppFnd1 ) + ++rCount; } // 1st Item set? - else if ( !IsInvalidItem(ppFnd1->second) ) + else if ( !IsInvalidItem(*ppFnd1) ) { if ( !pFnd2 ) { // 2nd Item is Default if ( !bIgnoreDefaults && - *ppFnd1->second != _pPool->GetDefaultItem(ppFnd1->second->Which()) ) + **ppFnd1 != _pPool->GetDefaultItem((*ppFnd1)->Which()) ) { // Decision table: set, default, !=, sal_False - _pPool->Remove( *ppFnd1->second ); - ppFnd1->second = reinterpret_cast<SfxPoolItem*>(-1); + _pPool->Remove( **ppFnd1 ); + *ppFnd1 = reinterpret_cast<SfxPoolItem*>(-1); } } else if ( IsInvalidItem(pFnd2) ) { // 2nd Item is dontcare if ( !bIgnoreDefaults || - *ppFnd1->second != _pPool->GetDefaultItem( ppFnd1->second->Which()) ) + **ppFnd1 != _pPool->GetDefaultItem( (*ppFnd1)->Which()) ) { // Decision table: set, dontcare, doesn't matter, sal_False // or: set, dontcare, !=, sal_True - _pPool->Remove( *ppFnd1->second ); - ppFnd1->second = reinterpret_cast<SfxPoolItem*>(-1); + _pPool->Remove( **ppFnd1 ); + *ppFnd1 = reinterpret_cast<SfxPoolItem*>(-1); } } else { // 2nd Item is set - if ( *ppFnd1->second != *pFnd2 ) + if ( **ppFnd1 != *pFnd2 ) { // Decision table: set, set, !=, doesn't matter - _pPool->Remove( *ppFnd1->second ); - ppFnd1->second = reinterpret_cast<SfxPoolItem*>(-1); + _pPool->Remove( **ppFnd1 ); + *ppFnd1 = reinterpret_cast<SfxPoolItem*>(-1); } } } @@ -1087,82 +1265,96 @@ void SfxItemSet::MergeValues( const SfxItemSet& rSet ) if( n & 1 ) nSize += ( *(pWh1) - *(pWh1-1) ) + 1; } + bool bEqual = *pWh1 == *pWh2; // Also check for 0 - SfxWhichIter aIter( rSet ); - sal_uInt16 nWhich; - while( 0 != ( nWhich = aIter.NextWhich() ) ) + // If the Ranges match, they are easier to process! + if( bEqual ) { - const SfxPoolItem* pItem = nullptr; - (void)rSet.GetItemState( nWhich, true, &pItem ); - if( !pItem ) + SfxItemArray ppFnd1 = m_pItems; + SfxItemArray ppFnd2 = rSet.m_pItems; + + for( ; nSize; --nSize, ++ppFnd1, ++ppFnd2 ) + MergeItem_Impl(m_pPool, m_nCount, ppFnd1, *ppFnd2, false/*bIgnoreDefaults*/); + } + else + { + SfxWhichIter aIter( rSet ); + sal_uInt16 nWhich; + while( 0 != ( nWhich = aIter.NextWhich() ) ) { - // Not set, so default - MergeValue( rSet.GetPool()->GetDefaultItem( nWhich ) ); + const SfxPoolItem* pItem = nullptr; + (void)rSet.GetItemState( nWhich, true, &pItem ); + if( !pItem ) + { + // Not set, so default + MergeValue( rSet.GetPool()->GetDefaultItem( nWhich ) ); + } + else if( IsInvalidItem( pItem ) ) + // don't care + InvalidateItem( nWhich ); + else + MergeValue( *pItem ); } - else if( IsInvalidItem( pItem ) ) - // don't care - InvalidateItem( nWhich ); - else - MergeValue( *pItem ); } } void SfxItemSet::MergeValue( const SfxPoolItem& rAttr, bool bIgnoreDefaults ) { + SfxItemArray ppFnd = m_pItems; const sal_uInt16* pPtr = m_pWhichRanges; const sal_uInt16 nWhich = rAttr.Which(); - bool bFound = false; while( *pPtr ) { // In this Range?? if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) { - bFound = true; + ppFnd += nWhich - *pPtr; + MergeItem_Impl(m_pPool, m_nCount, ppFnd, &rAttr, bIgnoreDefaults); break; } + ppFnd += *(pPtr+1) - *pPtr + 1; pPtr += 2; } - if (bFound) - MergeItem_Impl(m_pPool, m_aItems, nWhich, &rAttr, bIgnoreDefaults); } void SfxItemSet::InvalidateItem( sal_uInt16 nWhich ) { - bool bFound = false; + SfxItemArray ppFnd = m_pItems; const sal_uInt16* pPtr = m_pWhichRanges; while( *pPtr ) { if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) { - bFound = true; + // In this Range? + ppFnd += nWhich - *pPtr; + + if( *ppFnd ) // Set for me + { + if( reinterpret_cast<SfxPoolItem*>(-1) != *ppFnd ) // Not yet dontcare! + { + m_pPool->Remove( **ppFnd ); + *ppFnd = reinterpret_cast<SfxPoolItem*>(-1); + } + } + else + { + *ppFnd = reinterpret_cast<SfxPoolItem*>(-1); + ++m_nCount; + } break; } + ppFnd += *(pPtr+1) - *pPtr + 1; pPtr += 2; } - if (!bFound) - return; - - auto it = m_aItems.find(nWhich); - if (it != m_aItems.end()) - { - if( reinterpret_cast<SfxPoolItem*>(-1) != it->second ) // Not yet dontcare! - { - m_pPool->Remove( *it->second ); - it->second = reinterpret_cast<SfxPoolItem*>(-1); - } - } - else - { - m_aItems[nWhich] = reinterpret_cast<SfxPoolItem*>(-1); - } } sal_uInt16 SfxItemSet::GetWhichByPos( sal_uInt16 nPos ) const { + sal_uInt16 n = 0; sal_uInt16* pPtr = m_pWhichRanges; while( *pPtr ) { - sal_uInt16 n = *(pPtr+1) - *pPtr + 1; + n = ( *(pPtr+1) - *pPtr ) + 1; if( nPos < n ) return *(pPtr)+nPos; nPos = nPos - n; @@ -1194,10 +1386,10 @@ void SfxItemSet::Store // Remember position of the count (to be able to correct it, if need be) sal_uLong nCountPos = rStream.Tell(); - rStream.WriteUInt16( m_aItems.size() ); + rStream.WriteUInt16( m_nCount ); // If there's nothing to save, don't construct an ItemIter - if (!m_aItems.empty()) + if (m_nCount) { // Keep record of how many Items are really saved sal_uInt16 nWrittenCount = 0; // Count of Items streamed in 'rStream' @@ -1217,7 +1409,7 @@ void SfxItemSet::Store } // Fewer written than read (e.g. old format) - if (nWrittenCount != m_aItems.size()) + if (nWrittenCount != m_nCount) { // Store real count in the stream sal_uLong nPos = rStream.Tell(); @@ -1270,23 +1462,25 @@ void SfxItemSet::Load { // Find position for Item pointer in the set sal_uInt16 nWhich = pItem->Which(); + SfxItemArray ppFnd = m_pItems; const sal_uInt16* pPtr = m_pWhichRanges; - bool bFound = false; while ( *pPtr ) { // In this Range?? if ( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) { - bFound = true; + // Remember Item pointer in the set + ppFnd += nWhich - *pPtr; + SAL_WARN_IF( *ppFnd, "svl.items", "Item is present twice, with ID/pos " << nWhich); + *ppFnd = pItem; + ++m_nCount; break; } + + // In the range array and Item array to the next Which range + ppFnd += *(pPtr+1) - *pPtr + 1; pPtr += 2; } - if (bFound) - { - SAL_WARN_IF( m_aItems.find(nWhich) != m_aItems.end(), "svl.items", "Item is present twice, with ID/pos " << nWhich); - m_aItems[nWhich] = pItem; - } } } } @@ -1333,29 +1527,27 @@ bool SfxItemSet::operator==(const SfxItemSet &rCmp) const } // Are all pointers the same? - if ( m_aItems == rCmp.m_aItems ) + if (0 == memcmp( m_pItems, rCmp.m_pItems, nCount1 * sizeof(m_pItems[0]) )) return true; // We need to compare each one separately then - auto it1 = m_aItems.begin(); - auto it2 = rCmp.m_aItems.begin(); - for (;; ++it1, ++it2) + const SfxPoolItem **ppItem1 = m_pItems; + const SfxPoolItem **ppItem2 = rCmp.m_pItems; + for ( sal_uInt16 nPos = 0; nPos < nCount1; ++nPos ) { - if (it1 == m_aItems.end() && it2 == rCmp.m_aItems.end()) - break; - if (it1 == m_aItems.end() || it2 == rCmp.m_aItems.end()) - return false; - if (it1->first != it2->first) - return false; - if (it1->second == it2->second) - continue; - if (IsInvalidItem(it1->second) || IsInvalidItem(it2->second)) - return false; - if (m_pPool->IsItemPoolable(*it1->second)) - return false; - if (*it1->second != *it2->second) + // If the pointers of the poolable Items are not the same, the Items + // must match + if ( *ppItem1 != *ppItem2 && + ( ( !*ppItem1 || !*ppItem2 ) || + ( IsInvalidItem(*ppItem1) || IsInvalidItem(*ppItem2) ) || + (m_pPool->IsItemPoolable(**ppItem1)) || + **ppItem1 != **ppItem2 ) ) return false; + + ++ppItem1; + ++ppItem2; } + return true; } @@ -1386,42 +1578,43 @@ SfxItemSet *SfxItemSet::Clone(bool bItems, SfxItemPool *pToPool ) const void SfxItemSet::PutDirect(const SfxPoolItem &rItem) { + SfxItemArray ppFnd = m_pItems; const sal_uInt16* pPtr = m_pWhichRanges; const sal_uInt16 nWhich = rItem.Which(); #ifdef DBG_UTIL IsPoolDefaultItem(&rItem) || m_pPool->GetSurrogate(&rItem); // Only cause assertion in the callees #endif - - bool bFound = false; while( *pPtr ) { if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) { - bFound = true; - break; - } - pPtr += 2; - } - if (!bFound) - return; + // In this Range? + ppFnd += nWhich - *pPtr; + const SfxPoolItem* pOld = *ppFnd; + if( pOld ) // One already present + { + if( rItem == **ppFnd ) + return; // Already present! + m_pPool->Remove( *pOld ); + } + else + ++m_nCount; - auto it = m_aItems.find(nWhich); - if (it != m_aItems.end()) // One already present - { - if( rItem == *it->second ) - return; // Already present! - m_pPool->Remove( *it->second ); - } + // Add the new one + if( IsPoolDefaultItem(&rItem) ) + *ppFnd = &m_pPool->Put( rItem ); + else + { + *ppFnd = &rItem; + if( !IsStaticDefaultItem( &rItem ) ) + rItem.AddRef(); + } - // Add the new one - if( IsPoolDefaultItem(&rItem) ) - m_aItems[nWhich] = &m_pPool->Put( rItem ); - else - { - m_aItems[nWhich] = &rItem; - if( !IsStaticDefaultItem( &rItem ) ) - rItem.AddRef(); + return; + } + ppFnd += *(pPtr+1) - *pPtr + 1; + pPtr += 2; } } @@ -1455,6 +1648,9 @@ SfxAllItemSet::SfxAllItemSet( SfxItemPool &rPool ) : SfxItemSet(rPool, nullptr), nFree(nInitCount) { + // Initially no Items + m_pItems = nullptr; + // Allocate nInitCount pairs at USHORTs for Ranges m_pWhichRanges = new sal_uInt16[nInitCount + 1]{}; } @@ -1503,17 +1699,61 @@ static sal_uInt16 *AddRanges_Impl( } /** + * This internal function creates a new ItemArray, which is copied from 'pItems', + * but has room for a new ItemPointer at 'nPos'. + * + * @returns the new ItemArray (the old 'pItems' is freed) + */ +static SfxItemArray AddItem_Impl(SfxItemArray pItems, sal_uInt16 nOldSize, sal_uInt16 nPos) +{ + // Create new ItemArray + SfxItemArray pNew = new const SfxPoolItem*[nOldSize+1]; + + // Was there one before? + if ( pItems ) + { + // Copy all Items before nPos + if ( nPos ) + memcpy( static_cast<void*>(pNew), pItems, nPos * sizeof(SfxPoolItem *) ); + + // Copy all Items after nPos + if ( nPos < nOldSize ) + memcpy( static_cast<void*>(pNew + nPos + 1), pItems + nPos, + (nOldSize-nPos) * sizeof(SfxPoolItem *) ); + } + + // Initialize new Item + *(pNew + nPos) = nullptr; + + // Free old ItemArray + delete[] pItems; + + return pNew; +} + +/** * Putting with automatic extension of the WhichId with the ID of the Item. */ const SfxPoolItem* SfxAllItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhich ) { + sal_uInt16 nPos = 0; // Position for 'rItem' in 'm_pItems' + const sal_uInt16 nItemCount = TotalCount(); + // Let's see first whether there's a suitable Range already sal_uInt16 *pPtr = m_pWhichRanges; while ( *pPtr ) { // WhichId is within this Range? if( *pPtr <= nWhich && nWhich <= *(pPtr+1) ) + { + // Insert + nPos += nWhich - *pPtr; break; + } + + // Carry over the position of the Item in m_pItems + nPos += *(pPtr+1) - *pPtr + 1; + // To the next Range pPtr += 2; } @@ -1523,24 +1763,35 @@ const SfxPoolItem* SfxAllItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhi { // Let's see if we can attach it somewhere pPtr = m_pWhichRanges; + nPos = 0; while ( *pPtr ) { // WhichId is right before this Range? if ( (nWhich+1) == *pPtr ) { - // Grow range downwards + // Range grows downwards (*pPtr)--; + + // Make room before first Item of this Range + m_pItems = AddItem_Impl(m_pItems, nItemCount, nPos); break; } // WhichId is right after this Range? else if ( (nWhich-1) == *(pPtr+1) ) { - // Grow range upwards + // Range grows upwards? (*(pPtr+1))++; + + // Make room after last Item of this Range + nPos += nWhich - *pPtr; + m_pItems = AddItem_Impl(m_pItems, nItemCount, nPos); break; } + // Carry over position of the Item in m_pItems + nPos += *(pPtr+1) - *pPtr + 1; + // To the next Range pPtr += 2; } @@ -1562,28 +1813,32 @@ const SfxPoolItem* SfxAllItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhi *pPtr++ = nWhich; *pPtr = nWhich; nFree -= 2; + + // Expand ItemArray + nPos = nItemCount; + m_pItems = AddItem_Impl(m_pItems, nItemCount, nPos); } // Add new Item to Pool const SfxPoolItem& rNew = m_pPool->Put( rItem, nWhich ); // Remember old Item - auto it = m_aItems.find(nWhich); - const SfxPoolItem* pOld = nullptr; - if (it != m_aItems.end()) - pOld = it->second; + bool bIncrementCount = false; + const SfxPoolItem* pOld = *( m_pItems + nPos ); if ( reinterpret_cast< SfxPoolItem* >( -1 ) == pOld ) // state "dontcare" pOld = nullptr; if ( !pOld ) { - if (m_pParent) - pOld = &m_pParent->Get( nWhich ); - else if (SfxItemPool::IsWhich(nWhich)) - pOld = &m_pPool->GetDefaultItem(nWhich); + bIncrementCount = true; + pOld = (m_pParent) + ? &m_pParent->Get( nWhich ) + : (SfxItemPool::IsWhich(nWhich) + ? &m_pPool->GetDefaultItem(nWhich) + : nullptr); } // Add new Item to ItemSet - m_aItems[nWhich] = &rNew; + *(m_pItems + nPos) = &rNew; // Send Changed Notification if ( pOld ) @@ -1593,6 +1848,9 @@ const SfxPoolItem* SfxAllItemSet::Put( const SfxPoolItem& rItem, sal_uInt16 nWhi m_pPool->Remove( *pOld ); } + if ( bIncrementCount ) + ++m_nCount; + return &rNew; } diff --git a/svx/source/dialog/srchdlg.cxx b/svx/source/dialog/srchdlg.cxx index 630b111edf02..a7f025d1c11d 100644 --- a/svx/source/dialog/srchdlg.cxx +++ b/svx/source/dialog/srchdlg.cxx @@ -194,7 +194,7 @@ void SearchAttrItemList::Put( const SfxItemSet& rSet ) // only test that it is available? if( IsInvalidItem( pItem ) ) { - nWhich = aIter.GetCurWhich(); + nWhich = rSet.GetWhichByPos( aIter.GetCurPos() ); aItem.pItem = const_cast<SfxPoolItem*>(pItem); } else diff --git a/sw/source/core/crsr/findattr.cxx b/sw/source/core/crsr/findattr.cxx index 5e347f9fbac7..73b577712c86 100644 --- a/sw/source/core/crsr/findattr.cxx +++ b/sw/source/core/crsr/findattr.cxx @@ -235,8 +235,8 @@ SwAttrCheckArr::SwAttrCheckArr( const SfxItemSet& rSet, bool bFwd, // determine area of Fnd/Stack array (Min/Max) SfxItemIter aIter( aCmpSet ); - nArrStart = aIter.GetFirstWhich(); - nArrLen = aIter.GetLastWhich() - nArrStart + 1; + nArrStart = aCmpSet.GetWhichByPos( aIter.GetFirstPos() ); + nArrLen = aCmpSet.GetWhichByPos( aIter.GetLastPos() ) - nArrStart+1; char* pFndChar = new char[ nArrLen * sizeof(SwSrchChrAttr) ]; char* pStackChar = new char[ nArrLen * sizeof(SwSrchChrAttr) ]; @@ -287,7 +287,7 @@ void SwAttrCheckArr::SetNewSet( const SwTextNode& rTextNd, const SwPaM& rPam ) { if( IsInvalidItem( pItem ) ) { - nWhich = aIter.GetCurWhich(); + nWhich = aCmpSet.GetWhichByPos( aIter.GetCurPos() ); if( RES_TXTATR_END <= nWhich ) break; // end of text attributes @@ -861,7 +861,7 @@ static bool lcl_Search( const SwContentNode& rCNd, const SfxItemSet& rCmpSet, bo { if( IsInvalidItem( pItem )) { - nWhich = aIter.GetCurWhich(); + nWhich = rCmpSet.GetWhichByPos( aIter.GetCurPos() ); if( SfxItemState::SET != rNdSet.GetItemState( nWhich, !bNoColls, &pNdItem ) || CmpAttr( *pNdItem, rNdSet.GetPool()->GetDefaultItem( nWhich ) )) return false; diff --git a/sw/source/core/undo/undobj1.cxx b/sw/source/core/undo/undobj1.cxx index 331470225d06..0b0b21f33e69 100644 --- a/sw/source/core/undo/undobj1.cxx +++ b/sw/source/core/undo/undobj1.cxx @@ -531,7 +531,8 @@ void SwUndoSetFlyFormat::UndoImpl(::sw::UndoRedoContext & rContext) while( pItem ) { if( IsInvalidItem( pItem )) - pFrameFormat->ResetFormatAttr( aIter.GetCurWhich() ); + pFrameFormat->ResetFormatAttr( pItemSet->GetWhichByPos( + aIter.GetCurPos() )); else pFrameFormat->SetFormatAttr( *pItem ); diff --git a/sw/source/uibase/app/docstyle.cxx b/sw/source/uibase/app/docstyle.cxx index 7a8a5f848822..a4257fa71fb3 100644 --- a/sw/source/uibase/app/docstyle.cxx +++ b/sw/source/uibase/app/docstyle.cxx @@ -1677,7 +1677,8 @@ void SwDocStyleSheet::SetItemSet( const SfxItemSet& rSet, { // use method <SwDoc::ResetAttrAtFormat(..)> in order to // create an Undo object for the attribute reset. - rDoc.ResetAttrAtFormat( aIter.GetCurWhich(), *pFormat ); + rDoc.ResetAttrAtFormat( rSet.GetWhichByPos(aIter.GetCurPos()), + *pFormat ); } if( aIter.IsAtEnd() ) |