LCOV - code coverage report
Current view: top level - svl/source/items - poolio.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 125 482 25.9 %
Date: 2015-06-13 12:38:46 Functions: 13 28 46.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include <string.h>
      22             : 
      23             : #include <sal/log.hxx>
      24             : #include <tools/solar.h>
      25             : #include <svl/itempool.hxx>
      26             : #include "whassert.hxx"
      27             : #include <svl/SfxBroadcaster.hxx>
      28             : #include <svl/filerec.hxx>
      29             : #include "poolio.hxx"
      30             : #include <boost/scoped_ptr.hpp>
      31             : #include <boost/scoped_array.hpp>
      32             : 
      33             : /**
      34             :  * Returns the <SfxItemPool> that is being saved.
      35             :  * This should only be used in very exceptional cases e.g.
      36             :  * when guaranteeing file format compatibility:
      37             :  * When overriding a <SfxPoolItem::Store()> getting additional data from the Pool
      38             :  */
      39           0 : const SfxItemPool* SfxItemPool::GetStoringPool()
      40             : {
      41           0 :     return pStoringPool_;
      42             : }
      43             : 
      44           0 : static sal_uInt16 convertSfxItemKindToUInt16(SfxItemKind x)
      45             : {
      46           0 :     if ( x == SFX_ITEMS_NONE )
      47           0 :         return 0;
      48           0 :     if ( x == SFX_ITEMS_DELETEONIDLE )
      49           0 :         return 0xfffd;
      50           0 :     if ( x == SFX_ITEMS_STATICDEFAULT )
      51           0 :         return 0xfffe;
      52           0 :     if ( x == SFX_ITEMS_POOLDEFAULT )
      53           0 :         return 0xffff;
      54             :     assert(false);
      55           0 :     abort();
      56             : }
      57             : 
      58           0 : static SfxItemKind convertUInt16ToSfxItemKind(sal_uInt16 x)
      59             : {
      60           0 :     if ( x == 0 )
      61           0 :         return SFX_ITEMS_NONE;
      62           0 :     if ( x == 0xfffd )
      63           0 :         return SFX_ITEMS_DELETEONIDLE;
      64           0 :     if ( x == 0xfffe )
      65           0 :         return SFX_ITEMS_STATICDEFAULT;
      66           0 :     if ( x == 0xffff )
      67           0 :         return SFX_ITEMS_POOLDEFAULT;
      68             :     assert(false);
      69           0 :     abort();
      70             : }
      71             : 
      72             : 
      73             : 
      74             : /**
      75             :  * The SfxItemPool is saved to the specified Stream (together with all its
      76             :  * secondary Pools) using its Pool Defaults and pooled Items.
      77             :  * The static defaults are not saved.
      78             :  * [Fileformat]
      79             :  *
      80             :  *  ;First, a compatibility header section
      81             :  *    Start:      0x1111  SFX_ITEMPOOL_TAG_STARTPOOLS(_4/_5)
      82             :  *                sal_uInt8   MAJOR_VER                   ;SfxItemPool version
      83             :  *               sal_uInt8   MINOR_VER                   ;"
      84             :  *               0xFFFF  SFX_ITEMPOOL_TAG_TRICK4OLD      ;ex. GetVersion()
      85             :  *               sal_uInt16  0x0000                      ;Pseudo StyleSheetPool
      86             :  *               sal_uInt16  0x0000                      ;Pseudo StyleSheetPool
      87             :  *
      88             :  *   ;The whole Pool into a record
      89             :  *              record  SfxMiniRecod(SFX_ITEMPOOL_REC)
      90             :  *
      91             :  *   ;Start with a Header for each
      92             :  *   Header:     record      SfxMiniRecord(SFX_ITEMPOOL_REC_HEADER)
      93             :  *               sal_uInt16          GetVersion()        ;Which-Ranges etc.
      94             :  *               String          GetName()               ;Pool name
      95             :  *
      96             :  *  ;The version map: in order to be able to map WhichIds of new file version
      97             :  *    Versions:   record      SfxMultiRecord(SFX_ITEMPOOL_REC_VERSIONS, 0)
      98             :  *               sal_uInt16          OldVersion
      99             :  *               sal_uInt16          OldStartWhich
     100             :  *               sal_uInt16          OldEndWhich
     101             :  *               sal_uInt16[]        NewWhich (OldEndWhich-OldStartWhich+1)
     102             :  *
     103             :  *   ;Now the pooled Items (first the non-SfxSetItems)
     104             :  *   Items:      record      SfxMultiRecord(SFX_ITEMPOOL_REC_WHICHIDS, 0)
     105             :  *                content         SlotId, 0
     106             :  *               sal_uInt16          WhichId
     107             :  *               sal_uInt16          pItem->GetVersion()
     108             :  *               sal_uInt16          Array-Size
     109             :  *               record          SfxMultiRecord(SFX_, 0)
     110             :  *               content             Surrogate
     111             :  *               sal_uInt16              RefCount
     112             :  *               unknown             pItem->Store()
     113             :  *
     114             :  *   ;Now the set Pool defaults
     115             :  *   Defaults:   record      SfxMultiRecord(SFX_ITEMPOOL_REC_DEFAULTS, 0)
     116             :  *               content         SlotId, 0
     117             :  *               sal_uInt16          WhichId
     118             :  *               sal_uInt16          pPoolDef->GetVersion()
     119             :  *               unknown         pPoolDef->Store();
     120             :  *
     121             :  *   ;Hereafter the secondary follows (if present) without compatibility header section
     122             :  */
     123        6366 : SvStream &SfxItemPool::Store(SvStream &rStream) const
     124             : {
     125             :     // Find StoreMaster
     126        6366 :     SfxItemPool *pStoreMaster = pImp->mpMaster != this ? pImp->mpMaster : 0;
     127       12732 :     while ( pStoreMaster && !pStoreMaster->pImp->bStreaming )
     128           0 :         pStoreMaster = pStoreMaster->pImp->mpSecondary;
     129             : 
     130             :     // Old header (version of the Pool and content version is 0xffff by default)
     131        6366 :     pImp->bStreaming = true;
     132        6366 :     if ( !pStoreMaster )
     133             :     {
     134        6366 :         rStream.WriteUInt16( rStream.GetVersion() >= SOFFICE_FILEFORMAT_50
     135             :                 ? SFX_ITEMPOOL_TAG_STARTPOOL_5
     136        6366 :                 : SFX_ITEMPOOL_TAG_STARTPOOL_4  );
     137        6366 :         rStream.WriteUInt8( SFX_ITEMPOOL_VER_MAJOR ).WriteUInt8( SFX_ITEMPOOL_VER_MINOR );
     138        6366 :         rStream.WriteUInt16( SFX_ITEMPOOL_TAG_TRICK4OLD );
     139             : 
     140             :         // Work around SfxStyleSheet bug
     141        6366 :         rStream.WriteUInt16( 0 ); // Version
     142        6366 :         rStream.WriteUInt16( 0 ); // Count (or else 2nd loop breaks)
     143             :     }
     144             : 
     145             :     // Every Pool as a whole is a record
     146        6366 :     SfxMiniRecordWriter aPoolRec( &rStream, SFX_ITEMPOOL_REC );
     147        6366 :     pStoringPool_ = this;
     148             : 
     149             :     // Single header (content version and name)
     150             :     {
     151        6366 :         SfxMiniRecordWriter aPoolHeaderRec( &rStream, SFX_ITEMPOOL_REC_HEADER);
     152        6366 :         rStream.WriteUInt16( pImp->nVersion );
     153        6366 :         writeByteString(rStream, pImp->aName);
     154             :     }
     155             : 
     156             :     // VersionMaps
     157             :     {
     158        6366 :         SfxMultiVarRecordWriter aVerRec( &rStream, SFX_ITEMPOOL_REC_VERSIONMAP, 0 );
     159       44562 :         for ( size_t nVerNo = 0; nVerNo < pImp->aVersions.size(); ++nVerNo )
     160             :         {
     161       38196 :             aVerRec.NewContent();
     162       38196 :             SfxPoolVersion_ImplPtr pVer = pImp->aVersions[nVerNo];
     163       38196 :             rStream.WriteUInt16( pVer->_nVer ).WriteUInt16( pVer->_nStart ).WriteUInt16( pVer->_nEnd );
     164       38196 :             sal_uInt16 nCount = pVer->_nEnd - pVer->_nStart + 1;
     165       38196 :             sal_uInt16 nNewWhich = 0;
     166     1184076 :             for ( sal_uInt16 n = 0; n < nCount; ++n )
     167             :             {
     168     1145880 :                 nNewWhich = pVer->_pMap[n];
     169     1145880 :                 rStream.WriteUInt16( nNewWhich );
     170             :             }
     171             : 
     172             :             // Workaround for bug in SetVersionMap 312
     173       38196 :             if ( SOFFICE_FILEFORMAT_31 == pImp->mnFileFormatVersion )
     174           0 :                 rStream.WriteUInt16( nNewWhich+1 );
     175       44562 :         }
     176             :     }
     177             : 
     178             :     // Pooled Items
     179             :     {
     180        6366 :         SfxMultiMixRecordWriter aWhichIdsRec( &rStream, SFX_ITEMPOOL_REC_WHICHIDS, 0 );
     181             : 
     182             :         // First write the atomic Items and then write the Sets (important when loading)
     183       19098 :         for (int ft = 0 ; ft < 2 && !rStream.GetError(); ft++)
     184             :         {
     185       12732 :             pImp->bInSetItem = ft != 0;
     186             : 
     187       12732 :             std::vector<SfxPoolItemArray_Impl*>::iterator itrArr = pImp->maPoolItems.begin();
     188       12732 :             SfxPoolItem **ppDefItem = pImp->ppStaticDefaults;
     189       12732 :             const sal_uInt16 nSize = GetSize_Impl();
     190      712992 :             for ( size_t i = 0; i < nSize && !rStream.GetError(); ++i, ++itrArr, ++ppDefItem )
     191             :             {
     192             :                 // Get version of the Item
     193      700260 :                 sal_uInt16 nItemVersion = (*ppDefItem)->GetVersion( pImp->mnFileFormatVersion );
     194      700260 :                 if ( USHRT_MAX == nItemVersion )
     195             :                     // => Was not present in the version that was supposed to be exported
     196       25464 :                     continue;
     197             : 
     198             :                 // ! Poolable is not even saved in the Pool
     199             :                 // And itemsets/plain-items depending on the round
     200      696204 :                 if ( *itrArr && IsItemFlag(**ppDefItem, SfxItemPoolFlags::POOLABLE) &&
     201       21408 :                      pImp->bInSetItem == (bool) (*ppDefItem)->ISA(SfxSetItem) )
     202             :                 {
     203             :                     // Own signature, global WhichId and ItemVersion
     204       10704 :                     sal_uInt16 nSlotId = GetSlotId( (*ppDefItem)->Which(), false );
     205       10704 :                     aWhichIdsRec.NewContent(nSlotId, 0);
     206       10704 :                     rStream.WriteUInt16( (*ppDefItem)->Which() );
     207       10704 :                     rStream.WriteUInt16( nItemVersion );
     208       10704 :                     const sal_uInt32 nCount = ::std::min<size_t>( (*itrArr)->size(), SAL_MAX_UINT32 );
     209             :                     DBG_ASSERT(nCount, "ItemArr is empty");
     210       10704 :                     rStream.WriteUInt32( nCount );
     211             : 
     212             :                     // Write Items
     213       10704 :                     SfxMultiMixRecordWriter aItemsRec( &rStream, SFX_ITEMPOOL_REC_ITEMS, 0 );
     214       22418 :                     for ( size_t j = 0; j < nCount; ++j )
     215             :                     {
     216             :                         // Get Item
     217       11714 :                         const SfxPoolItem *pItem = (*itrArr)->operator[](j);
     218       11714 :                         if ( pItem && pItem->GetRefCount() ) //! See other MI-REF
     219             :                         {
     220       11714 :                             aItemsRec.NewContent((sal_uInt16)j, 'X' );
     221             : 
     222       11714 :                             if ( pItem->GetRefCount() == SFX_ITEMS_SPECIAL )
     223           0 :                                 rStream.WriteUInt16( convertSfxItemKindToUInt16(pItem->GetKind()) );
     224             :                             else
     225             :                             {
     226       11714 :                                 rStream.WriteUInt16( pItem->GetRefCount() );
     227       11714 :                                 if( pItem->GetRefCount() > SFX_ITEMS_OLD_MAXREF )
     228           0 :                                     rStream.SetError( ERRCODE_IO_NOTSTORABLEINBINARYFORMAT );
     229             :                             }
     230             : 
     231       11714 :                             if ( !rStream.GetError() )
     232       11714 :                                 pItem->Store(rStream, nItemVersion);
     233             :                             else
     234           0 :                                 break;
     235             : #ifdef DBG_UTIL_MI
     236             :                             if ( !pItem->ISA(SfxSetItem) )
     237             :                             {
     238             :                                 sal_uLong nMark = rStream.Tell();
     239             :                                 rStream.Seek( nItemStartPos + sizeof(sal_uInt16) );
     240             :                                 boost::scoped_ptr<SfxPoolItem> pClone(pItem->Create(rStream, nItemVersion ));
     241             :                                 sal_uInt16 nWh = pItem->Which();
     242             :                                 SFX_ASSERT( rStream.Tell() == nMark, nWh,"asymmetric store/create" );
     243             :                                 SFX_ASSERT( *pClone == *pItem, nWh, "unequal after store/create" );
     244             :                             }
     245             : #endif
     246             :                         }
     247       10704 :                     }
     248             :                 }
     249             :             }
     250             :         }
     251             : 
     252        6366 :         pImp->bInSetItem = false;
     253             :     }
     254             : 
     255             :     // Save the set Defaults (PoolDefaults)
     256        6366 :     if ( !rStream.GetError() )
     257             :     {
     258        6366 :         SfxMultiMixRecordWriter aDefsRec( &rStream, SFX_ITEMPOOL_REC_DEFAULTS, 0 );
     259        6366 :         sal_uInt16 nCount = GetSize_Impl();
     260      356496 :         for ( sal_uInt16 n = 0; n < nCount; ++n )
     261             :         {
     262      350130 :             const SfxPoolItem* pDefaultItem = pImp->ppPoolDefaults[n];
     263      350130 :             if ( pDefaultItem )
     264             :             {
     265             :                 // Get version
     266           0 :                 sal_uInt16 nItemVersion = pDefaultItem->GetVersion( pImp->mnFileFormatVersion );
     267           0 :                 if ( USHRT_MAX == nItemVersion )
     268             :                     // => Was not present in the version yet
     269           0 :                     continue;
     270             : 
     271             :                 // Own signature, global signature, version
     272           0 :                 sal_uInt16 nSlotId = GetSlotId( pDefaultItem->Which(), false );
     273           0 :                 aDefsRec.NewContent( nSlotId, 0 );
     274           0 :                 rStream.WriteUInt16( pDefaultItem->Which() );
     275           0 :                 rStream.WriteUInt16( nItemVersion );
     276             : 
     277             :                 // Item
     278           0 :                 pDefaultItem->Store( rStream, nItemVersion );
     279             :             }
     280        6366 :         }
     281             :     }
     282             : 
     283             :     // Write out additional Pools
     284        6366 :     pStoringPool_ = 0;
     285        6366 :     aPoolRec.Close();
     286        6366 :     if ( !rStream.GetError() && pImp->mpSecondary )
     287           0 :         pImp->mpSecondary->Store( rStream );
     288             : 
     289        6366 :     pImp->bStreaming = false;
     290        6366 :     return rStream;
     291             : }
     292             : 
     293           0 : bool SfxItemPool::HasPersistentRefCounts() const
     294             : {
     295           0 :     return pImp->mbPersistentRefCounts;
     296             : }
     297             : 
     298             : /**
     299             :  * If the SfxItemPool was loaded with 'bRefCounts' == sal_False, we need
     300             :  * to finish the loading of the document contents with a call of this method.
     301             :  * In any other case calling this function has no meaning.
     302             :  *
     303             :  * When loading without RefCounts, they are actually set to 1 so that
     304             :  * SfxPoolItems that are needed during and after loading are not deleted.
     305             :  * This method resets the RefCount and also removes all items that are not
     306             :  * needed anymore.
     307             :  *
     308             :  * @see SfxItemPool::Load()
     309             : */
     310           0 : void SfxItemPool::LoadCompleted()
     311             : {
     312             :     // Did we load without RefCounts?
     313           0 :     if ( pImp->nInitRefCount > 1 )
     314             :     {
     315             :         // Iterate over all Which values
     316           0 :         std::vector<SfxPoolItemArray_Impl*>::iterator itrItemArr = pImp->maPoolItems.begin();
     317           0 :         for( sal_uInt16 nArrCnt = GetSize_Impl(); nArrCnt; --nArrCnt, ++itrItemArr )
     318             :         {
     319             :             // Is there an item with the Which value present at all?
     320           0 :             if ( *itrItemArr )
     321             :             {
     322             :                 // Iterate over all items with this WhichId
     323           0 :                 SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*itrItemArr)->begin();
     324           0 :                 for( size_t n = (*itrItemArr)->size(); n; --n, ++ppHtArr )
     325             :                 {
     326           0 :                     if (*ppHtArr)
     327             :                     {
     328           0 :                         if ( !ReleaseRef( **ppHtArr, 1 ) )
     329           0 :                             DELETEZ( *ppHtArr );
     330             :                     }
     331             :                 }
     332           0 :                 (*itrItemArr)->ReHash();
     333             :             }
     334             :         }
     335             : 
     336             :         // from now on normal initial ref count
     337           0 :         pImp->nInitRefCount = 1;
     338             :     }
     339             : 
     340             :     // notify secondary pool
     341           0 :     if ( pImp->mpSecondary )
     342           0 :         pImp->mpSecondary->LoadCompleted();
     343           0 : }
     344             : 
     345       23939 : sal_uInt16 SfxItemPool::GetFirstWhich() const
     346             : {
     347       23939 :     return pImp->mnStart;
     348             : }
     349             : 
     350     1160043 : sal_uInt16 SfxItemPool::GetLastWhich() const
     351             : {
     352     1160043 :     return pImp->mnEnd;
     353             : }
     354             : 
     355   381252180 : bool SfxItemPool::IsInRange( sal_uInt16 nWhich ) const
     356             : {
     357   381252180 :     return nWhich >= pImp->mnStart && nWhich <= pImp->mnEnd;
     358             : }
     359             : 
     360             : // This had to be moved to a method of its own to keep Solaris GCC happy:
     361           0 : void SfxItemPool_Impl::readTheItems (
     362             :     SvStream & rStream, sal_uInt32 nItemCount, sal_uInt16 nVer,
     363             :     SfxPoolItem * pDefItem, SfxPoolItemArray_Impl ** ppArr)
     364             : {
     365           0 :     SfxMultiRecordReader aItemsRec( &rStream, SFX_ITEMPOOL_REC_ITEMS );
     366             : 
     367           0 :     SfxPoolItemArray_Impl *pNewArr = new SfxPoolItemArray_Impl();
     368           0 :     SfxPoolItem *pItem = 0;
     369             : 
     370           0 :     sal_uLong n, nLastSurrogate = sal_uLong(-1);
     371           0 :     while (aItemsRec.GetContent())
     372             :     {
     373             :         // Get next surrogate
     374           0 :         sal_uInt16 nSurrogate = aItemsRec.GetContentTag();
     375             :         DBG_ASSERT( aItemsRec.GetContentVersion() == 'X',
     376             :                     "not an item content" );
     377             : 
     378             :         // Fill up missing ones
     379             :         // coverity[tainted_data] - ignore this, though we should finally kill off this format
     380           0 :         for ( pItem = 0, n = nLastSurrogate+1; n < nSurrogate; ++n )
     381           0 :             pNewArr->push_back( pItem );
     382           0 :         nLastSurrogate = nSurrogate;
     383             : 
     384             :         // Load RefCount and Item
     385           0 :         sal_uInt16 nRef(0);
     386           0 :         rStream.ReadUInt16( nRef );
     387             : 
     388           0 :         pItem = pDefItem->Create(rStream, nVer);
     389           0 :         pNewArr->push_back( pItem );
     390             : 
     391           0 :         if ( !mbPersistentRefCounts )
     392             :             // Hold onto it until SfxItemPool::LoadCompleted()
     393           0 :             SfxItemPool::AddRef(*pItem, 1);
     394             :         else
     395             :         {
     396           0 :             if ( nRef > SFX_ITEMS_OLD_MAXREF )
     397           0 :                 SfxItemPool::SetKind(*pItem, convertUInt16ToSfxItemKind(nRef));
     398             :             else
     399           0 :                 SfxItemPool::AddRef(*pItem, nRef);
     400             :         }
     401             :     }
     402             : 
     403             :     // Fill up missing ones
     404           0 :     for ( pItem = 0, n = nLastSurrogate+1; n < nItemCount; ++n )
     405           0 :         pNewArr->push_back( pItem );
     406             : 
     407           0 :     SfxPoolItemArray_Impl *pOldArr = *ppArr;
     408           0 :     *ppArr = pNewArr;
     409             : 
     410             :     // Remember items that are already in the pool
     411           0 :     bool bEmpty = true;
     412           0 :     if ( 0 != pOldArr )
     413           0 :         for ( n = 0; bEmpty && n < pOldArr->size(); ++n )
     414           0 :             bEmpty = pOldArr->operator[](n) == 0;
     415             :     DBG_ASSERTWARNING( bEmpty, "loading non-empty pool" );
     416           0 :     if ( !bEmpty )
     417             :     {
     418             :         // See if there's a new one for all old ones
     419           0 :         for ( size_t nOld = 0; nOld < pOldArr->size(); ++nOld )
     420             :         {
     421           0 :             SfxPoolItem *pOldItem = (*pOldArr)[nOld];
     422           0 :             if ( pOldItem )
     423             :             {
     424           0 :                 sal_uInt32 nFree = SAL_MAX_UINT32;
     425           0 :                 bool bFound = false;
     426           0 :                 for ( size_t nNew = (*ppArr)->size(); nNew--; )
     427             :                 {
     428             :                     // Loaded Item
     429             :                     SfxPoolItem *&rpNewItem =
     430           0 :                         (*ppArr)->operator[](nNew);
     431             : 
     432             :                     // Unused surrogate?
     433           0 :                     if ( !rpNewItem )
     434           0 :                         nFree = nNew;
     435             : 
     436             :                     // Found it?
     437           0 :                     else if ( *rpNewItem == *pOldItem )
     438             :                     {
     439             :                         // Reuse
     440           0 :                         SfxItemPool::AddRef( *pOldItem, rpNewItem->GetRefCount() );
     441           0 :                         SfxItemPool::SetRefCount( *rpNewItem, 0 );
     442           0 :                         delete rpNewItem;
     443           0 :                         rpNewItem = pOldItem;
     444           0 :                         bFound = true;
     445           0 :                         break;
     446             :                     }
     447             :                 }
     448             : 
     449             :                 // Take over the ones that were previously present, but had not been loaded
     450           0 :                 if ( !bFound )
     451             :                 {
     452           0 :                     if ( nFree != SAL_MAX_UINT32 )
     453           0 :                         (*ppArr)->operator[](nFree) = pOldItem;
     454             :                     else
     455           0 :                         (*ppArr)->push_back( pOldItem );
     456             :                 }
     457             :             }
     458             :         }
     459             :     }
     460           0 :     delete pOldArr;
     461             : 
     462           0 :     (*ppArr)->ReHash(); // paranoid
     463           0 : }
     464             : 
     465           0 : SvStream &SfxItemPool::Load(SvStream &rStream)
     466             : {
     467             :     DBG_ASSERT(pImp->ppStaticDefaults, "No DefaultArray");
     468             : 
     469             :     // Protect items by increasing ref count
     470           0 :     if ( !pImp->mbPersistentRefCounts )
     471             :     {
     472             : 
     473             :         // Iterate over all Which values
     474           0 :         std::vector<SfxPoolItemArray_Impl*>::iterator itrItemArr = pImp->maPoolItems.begin();
     475           0 :         for( size_t nArrCnt = GetSize_Impl(); nArrCnt; --nArrCnt, ++itrItemArr )
     476             :         {
     477             :             // Is there an Item with that Which value present at all?
     478           0 :             if ( *itrItemArr )
     479             :             {
     480           0 :                 SfxPoolItemArrayBase_Impl::iterator ppHtArr = (*itrItemArr)->begin();
     481           0 :                 for( size_t n = (*itrItemArr)->size(); n; --n, ++ppHtArr )
     482           0 :                     if (*ppHtArr)
     483             :                     {
     484             :                         DBG_WARNING( "loading non-empty ItemPool" );
     485             : 
     486           0 :                         AddRef( **ppHtArr, 1 );
     487             :                     }
     488             :             }
     489             :         }
     490             : 
     491             :         // During loading (until LoadCompleted()) protect all items
     492           0 :         pImp->nInitRefCount = 2;
     493             :     }
     494             : 
     495             :     // Find LoadMaster
     496           0 :     SfxItemPool *pLoadMaster = pImp->mpMaster != this ? pImp->mpMaster : 0;
     497           0 :     while ( pLoadMaster && !pLoadMaster->pImp->bStreaming )
     498           0 :         pLoadMaster = pLoadMaster->pImp->mpSecondary;
     499             : 
     500             :     // Read whole Header
     501           0 :     pImp->bStreaming = true;
     502           0 :     if ( !pLoadMaster )
     503             :     {
     504             :         // Load format version
     505           0 :         CHECK_FILEFORMAT2( rStream,
     506             :                 SFX_ITEMPOOL_TAG_STARTPOOL_5, SFX_ITEMPOOL_TAG_STARTPOOL_4 );
     507           0 :         rStream.ReadUChar( pImp->nMajorVer ).ReadUChar( pImp->nMinorVer );
     508             : 
     509             :         // Take over format version to MasterPool
     510           0 :         pImp->mpMaster->pImp->nMajorVer = pImp->nMajorVer;
     511           0 :         pImp->mpMaster->pImp->nMinorVer = pImp->nMinorVer;
     512             : 
     513             :         // Unknown Format
     514           0 :         if (pImp->nMajorVer < 2 || pImp->nMajorVer > SFX_ITEMPOOL_VER_MAJOR)
     515             :         {
     516           0 :             rStream.SetError(SVSTREAM_FILEFORMAT_ERROR);
     517           0 :             pImp->bStreaming = false;
     518           0 :             return rStream;
     519             :         }
     520             : 
     521             :         // Trick for version 1.2: skip data
     522           0 :         CHECK_FILEFORMAT( rStream, SFX_ITEMPOOL_TAG_TRICK4OLD );
     523           0 :         rStream.SeekRel( 4 ); // Hack: Skip data due to SfxStyleSheetPool bug
     524             :     }
     525             : 
     526             :     // New record-oriented format
     527           0 :     SfxMiniRecordReader aPoolRec( &rStream, SFX_ITEMPOOL_REC );
     528           0 :     if ( rStream.GetError() )
     529             :     {
     530           0 :         pImp->bStreaming = false;
     531           0 :         return rStream;
     532             :     }
     533             : 
     534             :     // Single header
     535           0 :     OUString aExternName;
     536             :     {
     537             :         // Find HeaderRecord
     538           0 :         SfxMiniRecordReader aPoolHeaderRec( &rStream, SFX_ITEMPOOL_REC_HEADER );
     539           0 :         if ( rStream.GetError() )
     540             :         {
     541           0 :             pImp->bStreaming = false;
     542           0 :             return rStream;
     543             :         }
     544             : 
     545             :         // Read Header
     546           0 :         rStream.ReadUInt16( pImp->nLoadingVersion );
     547           0 :         aExternName = readByteString(rStream);
     548           0 :         bool bOwnPool = aExternName == pImp->aName;
     549             : 
     550             :         //! As long as we cannot read foreign Pools
     551           0 :         if ( !bOwnPool )
     552             :         {
     553           0 :             rStream.SetError(SVSTREAM_FILEFORMAT_ERROR);
     554           0 :             aPoolRec.Skip();
     555           0 :             pImp->bStreaming = false;
     556           0 :             return rStream;
     557           0 :         }
     558             :     }
     559             : 
     560             :     // Version maps
     561             :     {
     562           0 :         SfxMultiRecordReader aVerRec( &rStream, SFX_ITEMPOOL_REC_VERSIONMAP );
     563           0 :         if ( rStream.GetError() )
     564             :         {
     565           0 :             pImp->bStreaming = false;
     566           0 :             return rStream;
     567             :         }
     568             : 
     569             :         // Version maps einlesen
     570           0 :         sal_uInt16 nOwnVersion = pImp->nVersion;
     571           0 :         for ( sal_uInt16 nVerNo = 0; aVerRec.GetContent(); ++nVerNo )
     572             :         {
     573             :             // Read header for single versions
     574           0 :             sal_uInt16 nVersion(0), nHStart(0), nHEnd(0);
     575           0 :             rStream.ReadUInt16( nVersion ).ReadUInt16( nHStart ).ReadUInt16( nHEnd );
     576           0 :             sal_uInt16 nCount = nHEnd - nHStart + 1;
     577             : 
     578             :             // Is new version is known?
     579           0 :             if ( nVerNo >= pImp->aVersions.size() )
     580             :             {
     581             :                 // Add new Version
     582           0 :                 const size_t nMaxRecords = rStream.remainingSize() / sizeof(sal_uInt16);
     583           0 :                 if (nCount > nMaxRecords)
     584             :                 {
     585             :                     SAL_WARN("svl", "Parsing error: " << nMaxRecords <<
     586             :                              " max possible entries, but " << nCount << " claimed, truncating");
     587           0 :                     nCount = nMaxRecords;
     588             :                 }
     589           0 :                 sal_uInt16 *pMap = new sal_uInt16[nCount];
     590           0 :                 memset(pMap, 0, nCount * sizeof(sal_uInt16));
     591           0 :                 for ( sal_uInt16 n = 0; n < nCount; ++n )
     592           0 :                     rStream.ReadUInt16( pMap[n] );
     593           0 :                 SetVersionMap( nVersion, nHStart, nHEnd, pMap );
     594             :             }
     595             :         }
     596           0 :         pImp->nVersion = nOwnVersion;
     597             :     }
     598             : 
     599             :     // Load Items
     600           0 :     bool bSecondaryLoaded = false;
     601           0 :     long nSecondaryEnd = 0;
     602             :     {
     603           0 :         SfxMultiRecordReader aWhichIdsRec( &rStream, SFX_ITEMPOOL_REC_WHICHIDS);
     604           0 :         while ( aWhichIdsRec.GetContent() )
     605             :         {
     606             :             // Get SlotId, WhichId and Item version
     607           0 :             sal_uInt32 nCount(0);
     608           0 :             sal_uInt16 nVersion(0), nWhich(0);
     609             :             //!sal_uInt16 nSlotId = aWhichIdsRec.GetContentTag();
     610           0 :             rStream.ReadUInt16( nWhich );
     611           0 :             if ( pImp->nLoadingVersion != pImp->nVersion )
     612             :                 // Move WhichId from file version to Pool version
     613           0 :                 nWhich = GetNewWhich( nWhich );
     614             : 
     615             :             // Unknown Item from newer version
     616           0 :             if ( !IsInRange(nWhich) )
     617           0 :                 continue;
     618             : 
     619           0 :             rStream.ReadUInt16( nVersion );
     620           0 :             rStream.ReadUInt32( nCount );
     621             :             //!SFX_ASSERTWARNING( !nSlotId || !HasMap() ||
     622             :             //!         ( nSlotId == GetSlotId( nWhich, sal_False ) ) ||
     623             :             //!         !GetSlotId( nWhich, sal_False ),
     624             :             //!         nWhich, "Slot/Which mismatch" );
     625             : 
     626           0 :             sal_uInt16 nIndex = GetIndex_Impl(nWhich);
     627           0 :             SfxPoolItemArray_Impl **ppArr = &pImp->maPoolItems[0] + nIndex;
     628             : 
     629             :             // SfxSetItems could contain Items from secondary Pools
     630           0 :             SfxPoolItem *pDefItem = *(pImp->ppStaticDefaults + nIndex);
     631           0 :             pImp->bInSetItem = pDefItem->ISA(SfxSetItem);
     632           0 :             if ( !bSecondaryLoaded && pImp->mpSecondary && pImp->bInSetItem )
     633             :             {
     634             :                 // Seek to end of own Pool
     635           0 :                 sal_uLong nLastPos = rStream.Tell();
     636           0 :                 aPoolRec.Skip();
     637             : 
     638             :                 // Read secondary Pool
     639           0 :                 pImp->mpSecondary->Load( rStream );
     640           0 :                 bSecondaryLoaded = true;
     641           0 :                 nSecondaryEnd = rStream.Tell();
     642             : 
     643             :                 // Back to our own Items
     644           0 :                 rStream.Seek(nLastPos);
     645             :             }
     646             : 
     647             :             // Read Items
     648           0 :             pImp->readTheItems(rStream, nCount, nVersion, pDefItem, ppArr);
     649             : 
     650           0 :             pImp->bInSetItem = false;
     651           0 :         }
     652             :     }
     653             : 
     654             :     // Read Pool defaults
     655             :     {
     656           0 :         SfxMultiRecordReader aDefsRec( &rStream, SFX_ITEMPOOL_REC_DEFAULTS );
     657             : 
     658           0 :         while ( aDefsRec.GetContent() )
     659             :         {
     660             :             // Get SlotId, WhichId and Item versions
     661           0 :             sal_uInt16 nVersion(0), nWhich(0);
     662             :             //!sal_uInt16 nSlotId = aDefsRec.GetContentTag();
     663           0 :             rStream.ReadUInt16( nWhich );
     664           0 :             if ( pImp->nLoadingVersion != pImp->nVersion )
     665             :                 // Move WhichId from file version to Pool version
     666           0 :                 nWhich = GetNewWhich( nWhich );
     667             : 
     668             :             // Unknown Item from newer version
     669           0 :             if ( !IsInRange(nWhich) )
     670           0 :                 continue;
     671             : 
     672           0 :             rStream.ReadUInt16( nVersion );
     673             :             //!SFX_ASSERTWARNING( !HasMap() || ( nSlotId == GetSlotId( nWhich, sal_False ) ),
     674             :             //!         nWhich, "Slot/Which mismatch" );
     675             : 
     676             :             // Load PoolDefaultItem
     677             :             SfxPoolItem *pItem =
     678           0 :                     ( *( pImp->ppStaticDefaults + GetIndex_Impl(nWhich) ) )
     679           0 :                     ->Create( rStream, nVersion );
     680           0 :             pItem->SetKind( SFX_ITEMS_POOLDEFAULT );
     681           0 :             *( pImp->ppPoolDefaults + GetIndex_Impl(nWhich) ) = pItem;
     682           0 :         }
     683             :     }
     684             : 
     685             :     // Load secondary Pool if needed
     686           0 :     aPoolRec.Skip();
     687           0 :     if ( pImp->mpSecondary )
     688             :     {
     689           0 :         if ( !bSecondaryLoaded )
     690           0 :             pImp->mpSecondary->Load( rStream );
     691             :         else
     692           0 :             rStream.Seek( nSecondaryEnd );
     693             :     }
     694             : 
     695             :     // If not own Pool, then no name
     696           0 :     if ( aExternName != pImp->aName )
     697           0 :         (pImp->aName).clear();
     698             : 
     699           0 :     pImp->bStreaming = false;
     700           0 :     return rStream;
     701             : };
     702             : 
     703   333475855 : sal_uInt16 SfxItemPool::GetIndex_Impl(sal_uInt16 nWhich) const
     704             : {
     705   333475855 :     if (nWhich < pImp->mnStart || nWhich > pImp->mnEnd)
     706             :     {
     707             :         assert(false && "missing bounds check before use");
     708           0 :         return 0;
     709             :     }
     710   333475855 :     return nWhich - pImp->mnStart;
     711             : }
     712             : 
     713      133152 : sal_uInt16 SfxItemPool::GetSize_Impl() const
     714             : {
     715      133152 :     return pImp->mnEnd - pImp->mnStart + 1;
     716             : }
     717             : 
     718             : /**
     719             :  * Loads surrogate from 'rStream' and returns the corresponding SfxPoolItem
     720             :  * from the rRefPool.
     721             :  * If the surrogate contained within the stream == SFX_ITEMS_DIRECT
     722             :  * (!SfxItemPoolFlags::POOLABLE), we return 0 and the Item is to be loaded directly
     723             :  * from the stream.
     724             :  * We also return 0 for 0xfffffff0 (SFX_ITEMS_NULL) and rWhich is set to 0,
     725             :  * making the Items unavailable.
     726             :  *
     727             :  * Apart from that we also take into account whether the Pool is loaded without
     728             :  * RefCounts, if we reload from a new Pool (&rRefPool != this) or if we're
     729             :  * building from a differently constructed Pool.
     730             :  *
     731             :  * If we load from a differently constructed Pool and the 'nSlotId' cannot be
     732             :  * mapped to a WhichId of this Pool, we also return 0.
     733             :  *
     734             :  * Preconditions:   - Pool must be loaded
     735             :  *                  - LoadCompleted must not have been called yet
     736             :  *                  - 'rStream' is at the position at which a surrogate
     737             :  *                    for an Item with the SlotId 'nSlotId', the WhichId
     738             :  *                    'rWhichId' was saved with StoreSurrogate
     739             :  *
     740             :  * Postconditions:  - 'rStream' is at the same position as after StoreSurrogate
     741             :  *                    had finished saving
     742             :  *                  - If we were able to load an Item, it's now in this
     743             :  *                    SfxItemPool
     744             :  *                  - 'rWhichId' now contains the mapped WhichId
     745             :  *
     746             :  * Runtime: Depth of the traget secondary Pool * 10 + 10
     747             :  *
     748             :  * @see SfxItemPool::StoreSurrogate(SvStream&,const SfxPoolItem &)const
     749             : */
     750           0 : const SfxPoolItem* SfxItemPool::LoadSurrogate
     751             : (
     752             :     SvStream&           rStream,    // Stream before a surrogate
     753             :     sal_uInt16&         rWhich,     // WhichId of the SfxPoolItem that is to be loaded
     754             :     sal_uInt16          nSlotId,    // SlotId of the SfxPoolItem that is to be loaded
     755             :     const SfxItemPool*  pRefPool    // SfxItemPool in which the surrogate is valid
     756             : )
     757             : {
     758             :     // Read the first surrogate
     759           0 :     sal_uInt32 nSurrogat(0);
     760           0 :     rStream.ReadUInt32( nSurrogat );
     761             : 
     762             :     // Is item stored directly?
     763           0 :     if ( SFX_ITEMS_DIRECT == nSurrogat )
     764           0 :         return 0;
     765             : 
     766             :     // Item does not exist?
     767           0 :     if ( SFX_ITEMS_NULL == nSurrogat )
     768             :     {
     769           0 :         rWhich = 0;
     770           0 :         return 0;
     771             :     }
     772             : 
     773             :     // If the Pool in the stream has the same structure, the surrogate
     774             :     // can be resolved in any case
     775           0 :     if ( !pRefPool )
     776           0 :         pRefPool = this;
     777             : 
     778           0 :     bool bResolvable = !pRefPool->GetName().isEmpty();
     779           0 :     if ( !bResolvable )
     780             :     {
     781             :         // If the pool in the stream has a different structure, the SlotId
     782             :         // from the stream must be mapable to a WhichId
     783           0 :         sal_uInt16 nMappedWhich = nSlotId ? GetWhich(nSlotId, true) : 0;
     784           0 :         if ( IsWhich(nMappedWhich) )
     785             :         {
     786             :             // Mapped SlotId can be taken over
     787           0 :             rWhich = nMappedWhich;
     788           0 :             bResolvable = true;
     789             :         }
     790             :     }
     791             : 
     792             :     // Can the surrogate be resolved?
     793           0 :     if ( bResolvable )
     794             :     {
     795           0 :         const SfxPoolItem *pItem = 0;
     796           0 :         for ( SfxItemPool *pTarget = this; pTarget; pTarget = pTarget->pImp->mpSecondary )
     797             :         {
     798             :             // Found the right (Range-)Pool?
     799           0 :             if ( pTarget->IsInRange(rWhich) )
     800             :             {
     801             :                 // Default attribute?
     802           0 :                 if ( SFX_ITEMS_DEFAULT == nSurrogat )
     803           0 :                     return *(pTarget->pImp->ppStaticDefaults +
     804           0 :                             pTarget->GetIndex_Impl(rWhich));
     805             : 
     806             :                 SfxPoolItemArray_Impl* pItemArr =
     807           0 :                     pTarget->pImp->maPoolItems[pTarget->GetIndex_Impl(rWhich)];
     808           0 :                 pItem = pItemArr && nSurrogat < pItemArr->size()
     809           0 :                             ? (*pItemArr)[nSurrogat]
     810           0 :                             : 0;
     811           0 :                 if ( !pItem )
     812             :                 {
     813             :                     OSL_FAIL( "can't resolve surrogate" );
     814           0 :                     rWhich = 0; // Just to be sure; for the right StreamPos
     815           0 :                     return 0;
     816             :                 }
     817             : 
     818             :                 // Reload from RefPool?
     819           0 :                 if ( pRefPool != pImp->mpMaster )
     820           0 :                     return &pTarget->Put( *pItem );
     821             : 
     822             :                 // References have NOT been loaded together with the pool?
     823           0 :                 if ( !pTarget->HasPersistentRefCounts() )
     824           0 :                     AddRef( *pItem, 1 );
     825             :                 else
     826           0 :                     return pItem;
     827             : 
     828           0 :                 return pItem;
     829             :             }
     830             :         }
     831             : 
     832             :         SFX_ASSERT( false, rWhich, "can't resolve Which-Id in LoadSurrogate" );
     833             :     }
     834             : 
     835           0 :     return 0;
     836             : }
     837             : 
     838             : 
     839             : /**
     840             :  * Saves a surrogate for '*pItem' in 'rStream'
     841             :  *
     842             :  * @returns sal_True: a real surrogates has been saved
     843             :  *                    SFX_ITEMS_NULL for 'pItem==0', SFX_ITEMS_STATICDEFAULT
     844             :  *                    and SFX_ITEMS_POOLDEFAULT are 'real' surrogates
     845             :  *
     846             :  * @returns sal_False: a dummy surrogate (SFX_ITEMS_DIRECT) has been saved;
     847             :  *                     the actual Item needs to be saved right after it on
     848             :  *                     its own
     849             : */
     850       16149 : bool SfxItemPool::StoreSurrogate ( SvStream& rStream, const SfxPoolItem*  pItem) const
     851             : {
     852       16149 :     if ( pItem )
     853             :     {
     854       16149 :         bool bRealSurrogate = IsItemFlag(*pItem, SfxItemPoolFlags::POOLABLE);
     855             :         rStream.WriteUInt32( bRealSurrogate
     856             :                         ? GetSurrogate( pItem )
     857       16149 :                         : SFX_ITEMS_DIRECT  );
     858       16149 :         return bRealSurrogate;
     859             :     }
     860             : 
     861           0 :     rStream.WriteUInt32( SFX_ITEMS_NULL );
     862           0 :     return true;
     863             : }
     864             : 
     865             : 
     866             : 
     867       16149 : sal_uInt32 SfxItemPool::GetSurrogate(const SfxPoolItem *pItem) const
     868             : {
     869             :     DBG_ASSERT( pItem, "no 0-Pointer Surrogate" );
     870             :     DBG_ASSERT( !IsInvalidItem(pItem), "no Invalid-Item Surrogate" );
     871             :     DBG_ASSERT( !IsPoolDefaultItem(pItem), "no Pool-Default-Item Surrogate" );
     872             : 
     873       16149 :     if ( !IsInRange(pItem->Which()) )
     874             :     {
     875           0 :         if ( pImp->mpSecondary )
     876           0 :             return pImp->mpSecondary->GetSurrogate( pItem );
     877             :         SFX_ASSERT( false, pItem->Which(), "unknown Which-Id - dont ask me for surrogates" );
     878             :     }
     879             : 
     880             :     // Pointer on static or pool-default attribute?
     881       16149 :     if( IsStaticDefaultItem(pItem) || IsPoolDefaultItem(pItem) )
     882           0 :         return SFX_ITEMS_DEFAULT;
     883             : 
     884       16149 :     SfxPoolItemArray_Impl* pItemArr = pImp->maPoolItems[GetIndex_Impl(pItem->Which())];
     885             :     DBG_ASSERT(pItemArr, "ItemArr is not available");
     886             : 
     887       17327 :     for ( size_t i = 0; i < pItemArr->size(); ++i )
     888             :     {
     889       17327 :         const SfxPoolItem *p = (*pItemArr)[i];
     890       17327 :         if ( p == pItem )
     891       16149 :             return i;
     892             :     }
     893             :     SFX_ASSERT( false, pItem->Which(), "Item not in the pool");
     894           0 :     return SFX_ITEMS_NULL;
     895             : }
     896             : 
     897             : 
     898        9964 : bool SfxItemPool::IsInStoringRange( sal_uInt16 nWhich ) const
     899             : {
     900       19928 :     return nWhich >= pImp->nStoringStart &&
     901       19928 :            nWhich <= pImp->nStoringEnd;
     902             : }
     903             : 
     904             : /**
     905             :  * This method allows for restricting the WhichRange, which is saved
     906             :  * by ItemSets of this Pool (and the Pool itself).
     907             :  * The method must be called before SfxItemPool::Store() and the values
     908             :  * must also be still set when the actual document (the ItemSets) is
     909             :  * being saved.
     910             :  *
     911             :  * Resetting it is not necessary, if this range is set correctly before
     912             :  * _every_ save, because its only accounted for when saving.
     913             :  *
     914             :  * We need to do this for the 3.1 format, because there's a bug in the
     915             :  * Pool loading method.
     916             : */
     917        6366 : void SfxItemPool::SetStoringRange( sal_uInt16 nFrom, sal_uInt16 nTo )
     918             : {
     919        6366 :     pImp->nStoringStart = nFrom;
     920        6366 :     pImp->nStoringEnd = nTo;
     921        6366 : }
     922             : 
     923             : 
     924             : /**
     925             :  * This method allows for the creation of new and incompatible WhichId
     926             :  * Ranges or distributions. Pools that were saved with old versions
     927             :  * are mapped using the provided conversion table until the current
     928             :  * version has been reached. Newer pools can be loaded, but will lose
     929             :  * newer attributes, because the map is saved in conjunction with the pool.
     930             :  *
     931             :  *  Precondition:   Pool must not be loaded yet
     932             :  *  Postcondition:  WhichIds from older versions can be mapped to version 'nVer'
     933             :  *  Runtime:        1.5 * new + 10
     934             :  *
     935             :  *  For newer WhichRanges (nStart,nEnd) it must hold that older WhichRanges
     936             :  *  (nOldStart,nOldEnd) are completely contained in the newer WhichRange.
     937             :  *  It is valid to extend the WhichRange to both sides; also by inserting
     938             :  *  WhichIds. Moving WhichIds is not permitted.
     939             :  *  This method should only be called in or right after the ctor.
     940             :  *
     941             :  *  The array must be static, because its not copied and resued in the
     942             :  *  copy-ctor of the SfxItemPool
     943             :  *
     944             :  *  Example usage:
     945             :  *  Originally (version 0) the pool had the following WhichIds:
     946             :  *
     947             :  *     1:A, 2:B, 3:C, 4:D
     948             :  *
     949             :  *  A newer version (version 1) is now supposed to contain two new Ids
     950             :  *  X and Y between B and C, looking like this:
     951             :  *
     952             :  *      1:A, 2:B, 3:X, 4:Y, 5:C, 6:D
     953             :  *
     954             :  *  We see that the Ids 3 and 4 have changed. For the new version, we
     955             :  *  would need to set the following in the new Pool:
     956             :  *
     957             :  *      static sal_uInt16 nVersion1Map = { 1, 2, 5, 6 };
     958             :  *      pPool->SetVersionMap( 1, 1, 4, &nVersion1Map );
     959             :  *
     960             :  *  @see SfxItemPool::IsLoadingVersionCurrent() const
     961             :  *  @see SfxItemPool::GetNewWhich(sal_uInt16)
     962             :  *  @see SfxItemPool::GetVersion() const
     963             :  */
     964      374459 : void SfxItemPool::SetVersionMap
     965             : (
     966             :     sal_uInt16  nVer,               // New version number
     967             :     sal_uInt16  nOldStart,          // Old first WhichId
     968             :     sal_uInt16  nOldEnd,            // Old last WhichId
     969             :     const sal_uInt16* pOldWhichIdTab /* Array containing the structure of the WhichIds
     970             :                                         of the previous version, in which the new
     971             :                                         corresponding new WhichId is located */
     972             : )
     973             : {
     974             :     // Create new map entry to insert
     975             :     const SfxPoolVersion_ImplPtr pVerMap = SfxPoolVersion_ImplPtr( new SfxPoolVersion_Impl(
     976      374459 :                 nVer, nOldStart, nOldEnd, pOldWhichIdTab ) );
     977      374459 :     pImp->aVersions.push_back( pVerMap );
     978             : 
     979             :     DBG_ASSERT( nVer > pImp->nVersion, "Versions not sorted" );
     980      374459 :     pImp->nVersion = nVer;
     981             : 
     982             :     // Adapt version range
     983    13973783 :     for ( sal_uInt16 n = 0; n < nOldEnd-nOldStart+1; ++n )
     984             :     {
     985    13599324 :         sal_uInt16 nWhich = pOldWhichIdTab[n];
     986    13599324 :         if ( nWhich < pImp->nVerStart )
     987             :         {
     988           0 :             if ( !nWhich )
     989           0 :                 nWhich = 0;
     990           0 :             pImp->nVerStart = nWhich;
     991             :         }
     992    13599324 :         else if ( nWhich > pImp->nVerEnd )
     993        1378 :             pImp->nVerEnd = nWhich;
     994      374459 :     }
     995      374459 : }
     996             : 
     997             : 
     998             : /**
     999             :  * This method converts WhichIds from a file format to the version of the
    1000             :  * current pool.
    1001             :  * If the file format is older, the conversion tables (set by the pool developer
    1002             :  * using SetVersion()) are used. If the file format is newer the conversion tables
    1003             :  * loaded from the file format are used. In this case, not every WhichId can be
    1004             :  * mapped in which case we return 0.
    1005             :  *
    1006             :  * The calculation is only defined for WhichIds supported by the corresponding
    1007             :  * file version, which is guarded by an assertion.
    1008             :  *
    1009             :  * Precondition:   Pool must be loaded
    1010             :  * Postcondition:  Unchanged
    1011             :  * Runtime:        linear(Count of the secondary pools) +
    1012             :  *                 linear(Difference of the old and newer version)
    1013             :  *
    1014             :  * @see SfxItemPool::IsLoadingVersionCurrent() const
    1015             :  * @see SfxItemPool::SetVersionMap(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16*)
    1016             :  * @see SfxItemPool::GetVersion() const
    1017             :  */
    1018           0 : sal_uInt16 SfxItemPool::GetNewWhich
    1019             : (
    1020             :     sal_uInt16  nFileWhich // The WhichId loaded from the stream
    1021             : )   const
    1022             : {
    1023             :     // Determine (secondary) Pool
    1024           0 :     if ( !IsInVersionsRange(nFileWhich) )
    1025             :     {
    1026           0 :         if ( pImp->mpSecondary )
    1027           0 :             return pImp->mpSecondary->GetNewWhich( nFileWhich );
    1028             :         SFX_ASSERT( false, nFileWhich, "unknown which in GetNewWhich()" );
    1029             :     }
    1030             : 
    1031             :     // Newer/the same/older version?
    1032           0 :     short nDiff = (short)pImp->nLoadingVersion - (short)pImp->nVersion;
    1033             : 
    1034             :     // WhichId of a newer version?
    1035           0 :     if ( nDiff > 0 )
    1036             :     {
    1037             :         // Map step by step from the top version down to the file version
    1038           0 :         for ( size_t nMap = pImp->aVersions.size(); nMap > 0; --nMap )
    1039             :         {
    1040           0 :             SfxPoolVersion_ImplPtr pVerInfo = pImp->aVersions[nMap-1];
    1041           0 :             if ( pVerInfo->_nVer > pImp->nVersion )
    1042             :             {   sal_uInt16 nOfs;
    1043           0 :                 sal_uInt16 nCount = pVerInfo->_nEnd - pVerInfo->_nStart + 1;
    1044           0 :                 for ( nOfs = 0;
    1045           0 :                       nOfs <= nCount &&
    1046           0 :                         pVerInfo->_pMap[nOfs] != nFileWhich;
    1047             :                       ++nOfs )
    1048           0 :                     continue;
    1049             : 
    1050           0 :                 if ( pVerInfo->_pMap[nOfs] == nFileWhich )
    1051           0 :                     nFileWhich = pVerInfo->_nStart + nOfs;
    1052             :                 else
    1053           0 :                     return 0;
    1054             :             }
    1055             :             else
    1056           0 :                 break;
    1057           0 :         }
    1058             :     }
    1059             : 
    1060             :     // WhichId of a newer version?
    1061           0 :     else if ( nDiff < 0 )
    1062             :     {
    1063             :         // Map step by step from the top version down to the file version
    1064           0 :         for ( size_t nMap = 0; nMap < pImp->aVersions.size(); ++nMap )
    1065             :         {
    1066           0 :             SfxPoolVersion_ImplPtr pVerInfo = pImp->aVersions[nMap];
    1067           0 :             if ( pVerInfo->_nVer > pImp->nLoadingVersion )
    1068             :             {
    1069           0 :                 if (nFileWhich >= pVerInfo->_nStart &&
    1070           0 :                             nFileWhich <= pVerInfo->_nEnd)
    1071             :                 {
    1072           0 :                     nFileWhich = pVerInfo->_pMap[nFileWhich - pVerInfo->_nStart];
    1073             :                 }
    1074             :                 else
    1075             :                 {
    1076             :                     SAL_WARN("svl.items", "which-id unknown in version");
    1077             :                 }
    1078             :             }
    1079           0 :         }
    1080             :     }
    1081             : 
    1082             :     // Return original (nDiff==0) or mapped (nDiff!=0) Id
    1083           0 :     return nFileWhich;
    1084             : }
    1085             : 
    1086             : 
    1087             : 
    1088             : 
    1089           0 : bool SfxItemPool::IsInVersionsRange( sal_uInt16 nWhich ) const
    1090             : {
    1091           0 :     return nWhich >= pImp->nVerStart && nWhich <= pImp->nVerEnd;
    1092             : }
    1093             : 
    1094             : 
    1095             : /**
    1096             :  * This method determines whether the loaded Pool version corresponds to the
    1097             :  * currently loaded Pool structure.
    1098             :  *
    1099             :  * Precondition:   Pool is loaded
    1100             :  * Postcondition:  Unchanged
    1101             :  * Runtime:        linear(Count of secondary pools)
    1102             :  *
    1103             :  * @see SfxItemPool::SetVersionMap(sal_uInt16,sal_uInt16,sal_uInt16,sal_uInt16*)
    1104             :  * @see SfxItemPool::GetNewWhich(sal_uInt16) const
    1105             :  * @see SfxItemPool::GetVersion() const
    1106             :  */
    1107           0 : bool SfxItemPool::IsCurrentVersionLoading() const
    1108             : {
    1109           0 :     return ( pImp->nVersion == pImp->nLoadingVersion ) &&
    1110           0 :            ( !pImp->mpSecondary || pImp->mpSecondary->IsCurrentVersionLoading() );
    1111             : }
    1112             : 
    1113             : 
    1114             : /**
    1115             :  * Saves the SfxPoolItem 'rItem' to the SvStream 'rStream':
    1116             :  * either as a surrogate ('bDirect == sal_False') or directly with
    1117             :  * 'rItem.Store()'.
    1118             :  * Non-poolable Items are always saved directly. Items without WhichId and
    1119             :  * SID-Items as well as Items that were not yet present in the file format
    1120             :  * version (return sal_False) are not saved.
    1121             :  *
    1122             :  * The Item is saved to the Stream in the following manner:
    1123             :  *   sal_uInt16  rItem.Which()
    1124             :  *   sal_uInt16  GetSlotId( rItem.Which() ) or 0 if not available
    1125             :  *   sal_uInt16  GetSurrogate( &rItem ) or SFX_ITEM_DIRECT fo '!SFX_ITEM_POOLBLE'
    1126             :  *
    1127             :  * Optionally (if 'bDirect == sal_True' or '!rItem.IsPoolable()':
    1128             :  *   sal_uInt16  rItem.GetVersion()
    1129             :  *   sal_uLong   Size
    1130             :  *   Size        rItem.Store()
    1131             :  *
    1132             :  *  @see SfxItemPool::LoadItem(SvStream&,bool) const
    1133             :  */
    1134        9964 : bool SfxItemPool::StoreItem( SvStream &rStream, const SfxPoolItem &rItem,
    1135             :                                  bool bDirect ) const
    1136             : {
    1137             :     DBG_ASSERT( !IsInvalidItem(&rItem), "cannot store invalid items" );
    1138             : 
    1139        9964 :     if ( IsSlot( rItem.Which() ) )
    1140           0 :         return false;
    1141             : 
    1142        9964 :     const SfxItemPool *pPool = this;
    1143       19928 :     while ( !pPool->IsInStoringRange(rItem.Which()) )
    1144           0 :         if ( 0 == ( pPool = pPool->pImp->mpSecondary ) )
    1145           0 :             return false;
    1146             : 
    1147             :     DBG_ASSERT( !pImp->bInSetItem || !rItem.ISA(SfxSetItem),
    1148             :                 "SetItem contains ItemSet with SetItem" );
    1149             : 
    1150        9964 :     sal_uInt16 nSlotId = pPool->GetSlotId( rItem.Which(), true );
    1151        9964 :     sal_uInt16 nItemVersion = rItem.GetVersion(pImp->mnFileFormatVersion);
    1152        9964 :     if ( USHRT_MAX == nItemVersion )
    1153           0 :         return false;
    1154             : 
    1155        9964 :     rStream.WriteUInt16( rItem.Which() ).WriteUInt16( nSlotId );
    1156        9964 :     if ( bDirect || !pPool->StoreSurrogate( rStream, &rItem ) )
    1157             :     {
    1158           0 :         rStream.WriteUInt16( nItemVersion );
    1159           0 :         rStream.WriteUInt32( 0L ); // Room for length in bytes
    1160           0 :         sal_uLong nIStart = rStream.Tell();
    1161           0 :         rItem.Store(rStream, nItemVersion);
    1162           0 :         sal_uLong nIEnd = rStream.Tell();
    1163           0 :         rStream.Seek( nIStart-4 );
    1164           0 :         rStream.WriteInt32( nIEnd-nIStart );
    1165           0 :         rStream.Seek( nIEnd );
    1166             :     }
    1167             : 
    1168        9964 :     return true;
    1169             : }
    1170             : 
    1171             : 
    1172             : /**
    1173             :  * If pRefPool==-1 => do not put!
    1174             :  */
    1175           0 : const SfxPoolItem* SfxItemPool::LoadItem( SvStream &rStream, bool bDirect,
    1176             :                                           const SfxItemPool *pRefPool )
    1177             : {
    1178           0 :     sal_uInt16 nWhich(0), nSlot(0); // nSurrogate;
    1179           0 :     rStream.ReadUInt16( nWhich ).ReadUInt16( nSlot );
    1180             : 
    1181           0 :     bool bDontPut = reinterpret_cast<SfxItemPool*>(-1) == pRefPool;
    1182           0 :     if ( bDontPut || !pRefPool )
    1183           0 :         pRefPool = this;
    1184             : 
    1185             :     // Find right secondary Pool
    1186           0 :     while ( !pRefPool->IsInVersionsRange(nWhich) )
    1187             :     {
    1188           0 :         if ( pRefPool->pImp->mpSecondary )
    1189           0 :             pRefPool = pRefPool->pImp->mpSecondary;
    1190             :         else
    1191             :         {
    1192             :             // WID not present in this version => skip
    1193           0 :             sal_uInt32 nSurro(0);
    1194           0 :             sal_uInt16 nVersion(0), nLen(0);
    1195           0 :             rStream.ReadUInt32( nSurro );
    1196           0 :             if ( SFX_ITEMS_DIRECT == nSurro )
    1197             :             {
    1198           0 :                 rStream.ReadUInt16( nVersion ).ReadUInt16( nLen );
    1199           0 :                 rStream.SeekRel( nLen );
    1200             :             }
    1201           0 :             return 0;
    1202             :         }
    1203             :     }
    1204             : 
    1205             :     // Are we loading a different version?
    1206           0 :     bool bCurVersion = pRefPool->IsCurrentVersionLoading();
    1207           0 :     if ( !bCurVersion )
    1208           0 :         nWhich = pRefPool->GetNewWhich( nWhich ); // Map WhichId to new version
    1209             : 
    1210             :     DBG_ASSERT( !nWhich || !pImp->bInSetItem ||
    1211             :                 !pRefPool->pImp->ppStaticDefaults[pRefPool->GetIndex_Impl(nWhich)]->ISA(SfxSetItem),
    1212             :                 "loading SetItem in ItemSet of SetItem" );
    1213             : 
    1214             :     // Are we loading via surrogate?
    1215           0 :     const SfxPoolItem *pItem = 0;
    1216           0 :     if ( !bDirect )
    1217             :     {
    1218             :         // WhichId known in this version?
    1219           0 :         if ( nWhich )
    1220             :             // Load surrogate and react if none present
    1221           0 :             pItem = LoadSurrogate( rStream, nWhich, nSlot, pRefPool );
    1222             :         else
    1223             :             // Else skip it
    1224           0 :             rStream.SeekRel( sizeof(sal_uInt16) );
    1225             :     }
    1226             : 
    1227             :     // Is loaded directly (not via surrogate)?
    1228           0 :     if ( bDirect || ( nWhich && !pItem ) )
    1229             :     {
    1230             :         // bDirekt or not IsPoolable() => Load Item directly
    1231           0 :         sal_uInt16 nVersion(0);
    1232           0 :         sal_uInt32 nLen(0);
    1233           0 :         rStream.ReadUInt16( nVersion ).ReadUInt32( nLen );
    1234           0 :         sal_uLong nIStart = rStream.Tell();
    1235             : 
    1236             :         // WhichId known in this version?
    1237           0 :         if ( nWhich )
    1238             :         {
    1239             :             // Load Item directly
    1240             :             SfxPoolItem *pNewItem =
    1241           0 :                     pRefPool->GetDefaultItem(nWhich).Create(rStream, nVersion);
    1242           0 :             if ( bDontPut )
    1243           0 :                 pItem = pNewItem;
    1244             :             else
    1245           0 :                 if ( pNewItem )
    1246             :                 {
    1247           0 :                     pItem = &Put(*pNewItem);
    1248           0 :                     delete pNewItem;
    1249             :                 }
    1250             :                 else
    1251           0 :                     pItem = 0;
    1252           0 :             sal_uLong nIEnd = rStream.Tell();
    1253             :             DBG_ASSERT( nIEnd <= (nIStart+nLen), "read past end of item" );
    1254           0 :             if ( (nIStart+nLen) != nIEnd )
    1255           0 :                 rStream.Seek( nIStart+nLen );
    1256             :         }
    1257             :         else
    1258             :             // SKip Item
    1259           0 :             rStream.Seek( nIStart+nLen );
    1260             :     }
    1261             : 
    1262           0 :     return pItem;
    1263             : }
    1264             : 
    1265             : 
    1266           0 : OUString readByteString(SvStream& rStream)
    1267             : {
    1268           0 :     return rStream.ReadUniOrByteString(rStream.GetStreamCharSet());
    1269             : }
    1270             : 
    1271        6366 : void writeByteString(SvStream & rStream, const OUString& rString)
    1272             : {
    1273        6366 :     rStream.WriteUniOrByteString(rString, rStream.GetStreamCharSet());
    1274        6366 : }
    1275             : 
    1276           0 : OUString readUnicodeString(SvStream & rStream, bool bUnicode)
    1277             : {
    1278             :     return rStream.ReadUniOrByteString(bUnicode ? RTL_TEXTENCODING_UCS2 :
    1279           0 :                                       rStream.GetStreamCharSet());
    1280             : }
    1281             : 
    1282           0 : void writeUnicodeString(SvStream & rStream, const OUString& rString)
    1283             : {
    1284           0 :     rStream.WriteUniOrByteString(rString, RTL_TEXTENCODING_UCS2);
    1285           0 : }
    1286             : 
    1287             : 
    1288             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11