LCOV - code coverage report
Current view: top level - svl/source/filerec - filerec.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 68 166 41.0 %
Date: 2014-11-03 Functions: 12 21 57.1 %
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             : #include <svl/filerec.hxx>
      21             : #include <osl/endian.h>
      22             : 
      23             : 
      24             : /*  The following macros extract parts from a sal_uInt32 value.
      25             :     These sal_uInt32 values are written out instead of the individual
      26             :     values to reduce the number of calls.
      27             : */
      28             : 
      29             : #define SFX_REC_PRE(n) ( ((n) & 0x000000FF) )
      30             : #define SFX_REC_OFS(n) ( ((n) & 0xFFFFFF00) >> 8 )
      31             : #define SFX_REC_TYP(n) ( ((n) & 0x000000FF) )
      32             : #define SFX_REC_VER(n) ( ((n) & 0x0000FF00) >> 8 )
      33             : #define SFX_REC_TAG(n) ( ((n) & 0xFFFF0000) >> 16 )
      34             : 
      35             : #define SFX_REC_CONTENT_VER(n) ( ((n) & 0x000000FF) )
      36             : #define SFX_REC_CONTENT_OFS(n) ( ((n) & 0xFFFFFF00) >> 8 )
      37             : 
      38             : 
      39             : /*  The following macros combine parts to a sal_uInt32 value.
      40             :     This sal_uInt32 value is written instead of the individual values
      41             :     to reduce the number of calls.
      42             : */
      43             : 
      44       71788 : static void lclWriteMiniHeader(SvStream *p, sal_uInt32 nPreTag, sal_uInt32 nStartPos, sal_uInt32 nEndPos)
      45             : {
      46             :    (*p).WriteUInt32(  sal_uInt32(nPreTag) |
      47       71788 :              sal_uInt32(nEndPos-nStartPos-SFX_REC_HEADERSIZE_MINI) << 8  );
      48       71788 : }
      49             : 
      50       50380 : static void lclWriteHeader(SvStream *p, sal_uInt32 nRecType, sal_uInt32 nContentTag, sal_uInt32 nContentVer)
      51             : {
      52       50380 :     (*p).WriteUInt32(  sal_uInt32(nRecType) |
      53       50380 :              ( sal_uInt32(nContentVer) << 8 ) |
      54       50380 :              ( sal_uInt32(nContentTag) << 16 )  );
      55       50380 : }
      56             : 
      57             : #define SFX_REC_CONTENT_HEADER(nContentVer,n1StStartPos,nCurStartPos) \
      58             :                     ( sal_uInt32(nContentVer) | \
      59             :                       sal_uInt32( nCurStartPos - n1StStartPos ) << 8 )
      60             : 
      61             : /** Close the record; write the header
      62             :  *
      63             :  * @param bSeekToEndOfRec
      64             :  * if true (default) the stream is positioned at the end of the record;
      65             :  * if false the stream at the start of the content (so after the header).
      66             :  *
      67             :  * This method closes the record. The main function is to write the header.
      68             :  * If the header was written already this method is a no-op.
      69             :  *
      70             :  * @return sal_uInt32 != 0:  Position im the stream immediately after the record.
      71             :  * If 'bSeekToEndOfRecord==sal_True' this will be equal to the current stream position.
      72             :  * == 0: The header was already written.
      73             :  */
      74       71788 : sal_uInt32 SfxMiniRecordWriter::Close(bool bSeekToEndOfRec)
      75             : {
      76             :     // The header wasn't written yet?
      77       71788 :     if ( !_bHeaderOk )
      78             :     {
      79             :         // Write header at the start of the record
      80       71788 :         sal_uInt32 nEndPos = _pStream->Tell();
      81       71788 :         _pStream->Seek( _nStartPos );
      82       71788 :         lclWriteMiniHeader(_pStream, _nPreTag, _nStartPos, nEndPos );
      83             : 
      84             :         // seek to the end of the record or stay where we are
      85       71788 :         if ( bSeekToEndOfRec )
      86       21408 :             _pStream->Seek( nEndPos );
      87             : 
      88             :         // the header has been written NOW
      89       71788 :         _bHeaderOk = true;
      90       71788 :         return nEndPos;
      91             :     }
      92             : 
      93             :     // Record was closed already
      94           0 :     return 0;
      95             : }
      96             : 
      97             : /**
      98             :     Internal method for belatedly processsing a header read externally.
      99             :     If the header corresponds to an End-Of-Record tag, an error
     100             :     code is set on the stream and sal_False is returned.
     101             :     But the stream will not be reset to the record start in case of an error.
     102             : */
     103           0 : bool SfxMiniRecordReader::SetHeader_Impl( sal_uInt32 nHeader )
     104             : {
     105           0 :     bool bRet = true;
     106             : 
     107             :     // determine reord end and PreTag from the header
     108           0 :     _nEofRec = _pStream->Tell() + SFX_REC_OFS(nHeader);
     109           0 :     _nPreTag = sal::static_int_cast< sal_uInt8 >(SFX_REC_PRE(nHeader));
     110             : 
     111             :     // Errror in cae of End of Record tag
     112           0 :     if ( _nPreTag == SFX_REC_PRETAG_EOR )
     113             :     {
     114           0 :         _pStream->SetError( ERRCODE_IO_WRONGFORMAT );
     115           0 :         bRet = true;
     116             :     }
     117           0 :     return bRet;
     118             : }
     119             : 
     120             : /**
     121             :  *
     122             :  * @param pstream
     123             :  *   an \a SvStream, which has an \a SfxMiniRecord at the current position
     124             :  * @param nTag
     125             :  *   Pre-Tag of the wanted record
     126             :  *
     127             :  * This constructor interprets a 'pStream' from the current position
     128             :  * as a continuous sequence of records that should be parsable by
     129             :  * this group of classes. The first record that is an <SfxMiniRecord>
     130             :  * (possibly an extened-Record> that has the PreTag 'nTag' will be opened
     131             :  * and represented by this instance.
     132             :  *
     133             :  * If the end of stream is reached or a record with tag
     134             :  * SFX_REC_PRETAG_EOR is seen before a record with the wanted 'nTag'
     135             :  * tag is found, the created instance is invalid ('IsValid() ==
     136             :  * sal_False').  The ERRCODE_IO_WRONGFORMAT error code will be set on
     137             :  * the stream,and the current position will be unchanged.
     138             :  *
     139             :  * If (the wanted tag) 'nTag==SFX_FILEREC_PRETAG_EOR' no attempt is
     140             :  * made to read a record, but 'IsValid()' is set to sal_False immediately.
     141             :  * This gives the possibility to include backward compatible SfxMiniRecords
     142             :  * without 'new' or 'delete'. See <SfxItemSet::Load()>.
     143             :  *
     144             :  * Suggested usage:
     145             :  *
     146             :  * This constructor allows for adding new record types in a backward
     147             :  * compatible way by writing out a record with a new tag followed
     148             :  * by one with an old tag. In that case previous versions of the program
     149             :  * that do not recognise the new tag will skip the new record
     150             :  * automatically. This does cause a slight run time inefficiency,
     151             :  * compared just starting reading, but if the first record
     152             :  * is the wanted one the difference is just a comparision of 2 bytes.
     153             :  */
     154             : 
     155           0 : SfxMiniRecordReader::SfxMiniRecordReader(SvStream* pStream, sal_uInt8 nTag)
     156             :     : _pStream(pStream)
     157             :     , _nEofRec(0)
     158           0 :     , _bSkipped(nTag == SFX_REC_PRETAG_EOR)
     159             : {
     160             :     // ignore if we are looking for SFX_REC_PRETAG_EOR
     161           0 :     if ( _bSkipped )
     162             :     {
     163           0 :         _nPreTag = nTag;
     164           0 :         return;
     165             :     }
     166             : 
     167             :     // remember StartPos to be able to seek back in case of error
     168           0 :     sal_uInt32 nStartPos = pStream->Tell();
     169             : 
     170             :     // look for the matching record
     171             :     while(true)
     172             :     {
     173             :         // read header
     174             :         SAL_INFO("svl", "SfxFileRec: searching record at " << pStream->Tell());
     175             :         sal_uInt32 nHeader;
     176           0 :         pStream->ReadUInt32( nHeader );
     177             : 
     178             :         // let the base class extract the header data
     179           0 :         SetHeader_Impl( nHeader );
     180             : 
     181             :         // handle error, if any
     182           0 :         if ( pStream->IsEof() )
     183           0 :             _nPreTag = SFX_REC_PRETAG_EOR;
     184           0 :         else if ( _nPreTag == SFX_REC_PRETAG_EOR )
     185           0 :             pStream->SetError( ERRCODE_IO_WRONGFORMAT );
     186             :         else
     187             :         {
     188             :             // stop the loop if the right tag is found
     189           0 :             if ( _nPreTag == nTag )
     190           0 :                 break;
     191             : 
     192             :             // or else skip the record and continue
     193           0 :             pStream->Seek( _nEofRec );
     194           0 :             continue;
     195             :         }
     196             : 
     197             :         // seek back in case of error
     198           0 :         pStream->Seek( nStartPos );
     199           0 :         break;
     200           0 :     }
     201             : }
     202             : 
     203             : /**
     204             :  *
     205             :  * @param nRecordType  for sub classes
     206             :  * @param pStream      stream to write the record to
     207             :  * @param nContentTag  record type
     208             :  * @param nContentVer  record version
     209             :  *
     210             :  * internal constructor for sub classes
     211             :  */
     212       50380 : SfxSingleRecordWriter::SfxSingleRecordWriter(sal_uInt8  nRecordType,
     213             :                                              SvStream*  pStream,
     214             :                                              sal_uInt16 nContentTag,
     215             :                                              sal_uInt8  nContentVer)
     216       50380 : :   SfxMiniRecordWriter( pStream, SFX_REC_PRETAG_EXT )
     217             : {
     218             :     // write extend header after the SfxMiniRec
     219       50380 :     lclWriteHeader(pStream, nRecordType, nContentTag, nContentVer);
     220       50380 : }
     221             : 
     222             : /**
     223             :  *
     224             :  * Internal method for reading an SfxMultiRecord header, after
     225             :  * the base class has been initialized and its header has been read.
     226             :  * Set an error code on the stream if needed, but don't seek back
     227             :  * in case of error.
     228             :  */
     229             : inline bool SfxSingleRecordReader::ReadHeader_Impl( sal_uInt16 nTypes )
     230             : {
     231             :     bool bRet;
     232             : 
     233             :     // read header of the base class
     234             :     sal_uInt32 nHeader=0;
     235             :     _pStream->ReadUInt32( nHeader );
     236             :     if ( !SetHeader_Impl( nHeader ) )
     237             :         bRet = false;
     238             :     else
     239             :     {
     240             :         // read own header
     241             :         _pStream->ReadUInt32( nHeader );
     242             :         _nRecordVer = sal::static_int_cast< sal_uInt8 >(SFX_REC_VER(nHeader));
     243             :         _nRecordTag = sal::static_int_cast< sal_uInt16 >(SFX_REC_TAG(nHeader));
     244             : 
     245             :         // wrong record type?
     246             :         _nRecordType = sal::static_int_cast< sal_uInt8 >(SFX_REC_TYP(nHeader));
     247             :         bRet = 0 != ( nTypes & _nRecordType);
     248             :     }
     249             :     return bRet;
     250             : }
     251             : 
     252             : 
     253             : /**
     254             :  *
     255             :  * @param nTypes arithmetic OR of allowed record types
     256             :  * @param nTag   record tag to find
     257             :  *
     258             :  * Internal method for reading the header of the first record
     259             :  * that has the tag 'nTag', for which then the type should be
     260             :  * one of the types in 'nTypes'.
     261             :  *
     262             :  * If such a record is not found an error code is set, the stream
     263             :  * position is seek-ed back and sal_False is returned.
     264             :  */
     265           0 : bool SfxSingleRecordReader::FindHeader_Impl(sal_uInt16 nTypes, sal_uInt16 nTag)
     266             : {
     267             :     // remember StartPos to be able to seek back in case of error
     268           0 :     sal_uInt32 nStartPos = _pStream->Tell();
     269             : 
     270             :     // look for the right record
     271           0 :     while ( !_pStream->IsEof() )
     272             :     {
     273             :         // read header
     274             :         sal_uInt32 nHeader;
     275             :         SAL_INFO("svl", "SfxFileRec: searching record at " << _pStream->Tell());
     276           0 :         _pStream->ReadUInt32( nHeader );
     277           0 :         if ( !SetHeader_Impl( nHeader ) )
     278             :             // EOR => abort loop
     279           0 :             break;
     280             : 
     281             :         // found extended record?
     282           0 :         if ( _nPreTag == SFX_REC_PRETAG_EXT )
     283             :         {
     284             :             // read extended header
     285           0 :             _pStream->ReadUInt32( nHeader );
     286           0 :             _nRecordTag = sal::static_int_cast< sal_uInt16 >(SFX_REC_TAG(nHeader));
     287             : 
     288             :             // found right record?
     289           0 :             if ( _nRecordTag == nTag )
     290             :             {
     291             :                 // record type matches as well?
     292             :                 _nRecordType = sal::static_int_cast< sal_uInt8 >(
     293           0 :                     SFX_REC_TYP(nHeader));
     294           0 :                 if ( nTypes & _nRecordType )
     295             :                     // ==> found it
     296           0 :                     return true;
     297             : 
     298             :                 // error => abort loop
     299           0 :                 break;
     300             :             }
     301             :         }
     302             : 
     303             :         // else skip
     304           0 :         if ( !_pStream->IsEof() )
     305           0 :             _pStream->Seek( _nEofRec );
     306             :     }
     307             : 
     308             :     // set error and seek back
     309           0 :     _pStream->SetError( ERRCODE_IO_WRONGFORMAT );
     310           0 :     _pStream->Seek( nStartPos );
     311           0 :     return false;
     312             : }
     313             : 
     314             : /**
     315             :  *
     316             :  * @param nRecordType  sub class record type
     317             :  * @param pStream      Stream to write the record to
     318             :  * @param nContentTag  Content type
     319             :  * @param nContentVer  Content version
     320             :  *
     321             :  * Internal method for sub classes
     322             :  */
     323       50380 : SfxMultiFixRecordWriter::SfxMultiFixRecordWriter(sal_uInt8  nRecordType,
     324             :                                                  SvStream*  pStream,
     325             :                                                  sal_uInt16 nContentTag,
     326             :                                                  sal_uInt8  nContentVer)
     327             :     :  SfxSingleRecordWriter( nRecordType, pStream, nContentTag, nContentVer )
     328             :     , _nContentStartPos(0)
     329             :     , _nContentSize(0)
     330       50380 :     , _nContentCount(0)
     331             : {
     332             :     // space for own header
     333       50380 :     pStream->SeekRel( + SFX_REC_HEADERSIZE_MULTI );
     334       50380 : }
     335             : 
     336             : /**
     337             :  * @see SfxMiniRecordWriter
     338             :  */
     339           0 : sal_uInt32 SfxMultiFixRecordWriter::Close( bool bSeekToEndOfRec )
     340             : {
     341             :     // Header not written yet?
     342           0 :     if ( !_bHeaderOk )
     343             :     {
     344             :         // remember position after header, to be able to seek back to it
     345           0 :         sal_uInt32 nEndPos = SfxSingleRecordWriter::Close( false );
     346             : 
     347             :         // write extended header after SfxSingleRecord
     348           0 :         _pStream->WriteUInt16( _nContentCount );
     349           0 :         _pStream->WriteUInt32( _nContentSize );
     350             : 
     351             :         // seek to end of record or stay after the header
     352           0 :         if ( bSeekToEndOfRec )
     353           0 :             _pStream->Seek(nEndPos);
     354           0 :         return nEndPos;
     355             :     }
     356             : 
     357             :     // Record was closed already
     358           0 :     return 0;
     359             : }
     360             : 
     361             : /**
     362             :  *
     363             :  * @param nRecordType  Record type of the sub class
     364             :  * @param pStream      stream to write the record to
     365             :  * @param nRecordTag   record base type
     366             :  * @param nRecordVer   record base version
     367             :  *
     368             :  * Internal constructor for sub classes
     369             :  */
     370       39676 : SfxMultiVarRecordWriter::SfxMultiVarRecordWriter(sal_uInt8  nRecordType,
     371             :                                                  SvStream*  pStream,
     372             :                                                  sal_uInt16 nRecordTag,
     373             :                                                  sal_uInt8  nRecordVer)
     374             : :   SfxMultiFixRecordWriter( nRecordType, pStream, nRecordTag, nRecordVer ),
     375       39676 :     _nContentVer( 0 )
     376             : {
     377       39676 : }
     378             : 
     379             : /**
     380             :  *
     381             :  * @param pStream,    stream to write the record to
     382             :  * @param nRecordTag  record base type
     383             :  * @param nRecordVer  record base version
     384             :  *
     385             :  * Starts an SfxMultiVarRecord in \a pStream, for which the size
     386             :  * of the content does not have to be known or identical;
     387             :  * after streaming a record its size will be calculated.
     388             :  *
     389             :  * Note:
     390             :  *
     391             :  * This method is not inline since too much code was generated
     392             :  * for initializing the <SvULong> members.
     393             :  */
     394       10704 : SfxMultiVarRecordWriter::SfxMultiVarRecordWriter(SvStream*  pStream,
     395             :                                                  sal_uInt16 nRecordTag,
     396             :                                                  sal_uInt8  nRecordVer)
     397             : :   SfxMultiFixRecordWriter( SFX_REC_TYPE_VARSIZE,
     398             :                              pStream, nRecordTag, nRecordVer ),
     399       10704 :     _nContentVer( 0 )
     400             : {
     401       10704 : }
     402             : 
     403             : 
     404             : /**
     405             :  *
     406             :  *  The destructor of class <SfxMultiVarRecordWriter> closes the
     407             :  *  record automatically, in case <SfxMultiVarRecordWriter::Close()>
     408             :  *  has not been called explicitly yet.
     409             :  */
     410      100760 : SfxMultiVarRecordWriter::~SfxMultiVarRecordWriter()
     411             : {
     412             :     // close if the header has not been written yet
     413       50380 :     if ( !_bHeaderOk )
     414       50380 :         Close();
     415       50380 : }
     416             : 
     417             : /**
     418             :  *
     419             :  * Internal method for finishing individual content
     420             :  */
     421      102576 : void SfxMultiVarRecordWriter::FlushContent_Impl()
     422             : {
     423             :     // record the version and position offset of the current content;
     424             :     // the position offset is relative ot the start position of the
     425             :     // first content.
     426             :     assert(_aContentOfs.size() == static_cast<size_t>(_nContentCount)-1);
     427      102576 :     _aContentOfs.resize(_nContentCount-1);
     428             :     _aContentOfs.push_back(
     429      102576 :             SFX_REC_CONTENT_HEADER(_nContentVer,_nStartPos,_nContentStartPos));
     430      102576 : }
     431             : 
     432             : /**
     433             :  * @see SfxMultiFixRecordWriter
     434             :  */
     435       64224 : void SfxMultiVarRecordWriter::NewContent()
     436             : {
     437             :     // written Content already?
     438       64224 :     if ( _nContentCount )
     439       53520 :         FlushContent_Impl();
     440             : 
     441             :     // start new Content
     442       64224 :     _nContentStartPos = _pStream->Tell();
     443       64224 :     ++_nContentCount;
     444       64224 : }
     445             : 
     446             : /**
     447             :  * @see SfxMiniRecordWriter
     448             :  */
     449       50380 : sal_uInt32 SfxMultiVarRecordWriter::Close( bool bSeekToEndOfRec )
     450             : {
     451             :     // Header not written yet?
     452       50380 :     if ( !_bHeaderOk )
     453             :     {
     454             :         // finish content if needed
     455       50380 :         if ( _nContentCount )
     456       29604 :             FlushContent_Impl();
     457             : 
     458             :         // write out content offset table
     459       50380 :         sal_uInt32 nContentOfsPos = _pStream->Tell();
     460             :         //! (loop without braces)
     461      152956 :         for ( sal_uInt16 n = 0; n < _nContentCount; ++n )
     462      102576 :             _pStream->WriteUInt32( _aContentOfs[n] );
     463             : 
     464             :         // skip SfxMultiFixRecordWriter::Close()!
     465       50380 :         sal_uInt32 nEndPos = SfxSingleRecordWriter::Close( false );
     466             : 
     467             :         // write own header
     468       50380 :         _pStream->WriteUInt16( _nContentCount );
     469      100760 :         if ( SFX_REC_TYPE_VARSIZE_RELOC == _nPreTag ||
     470       50380 :              SFX_REC_TYPE_MIXTAGS_RELOC == _nPreTag )
     471           0 :             _pStream->WriteUInt32( static_cast<sal_uInt32>(nContentOfsPos - ( _pStream->Tell() + sizeof(sal_uInt32) )) );
     472             :         else
     473       50380 :             _pStream->WriteUInt32( nContentOfsPos );
     474             : 
     475             :         // seek to the end of the record or stay where we are
     476       50380 :         if ( bSeekToEndOfRec )
     477       50380 :              _pStream->Seek(nEndPos);
     478       50380 :         return nEndPos;
     479             :     }
     480             : 
     481             :     // Record was closed already
     482           0 :     return 0;
     483             : }
     484             : 
     485             : /**
     486             :  *
     487             :  * @param nContentTag  tag for this content type
     488             :  * @param nContentVer  content version
     489             :  *
     490             :  * With this method new Content is added to a record and
     491             :  * its tag and version are regorded. This method must be called
     492             :  * to start each content, including the first record.
     493             :  */
     494       38352 : void SfxMultiMixRecordWriter::NewContent(sal_uInt16 nContentTag, sal_uInt8 nContentVer)
     495             : {
     496             :     // Finish the previous record if necessary
     497       38352 :     if ( _nContentCount )
     498       19452 :         FlushContent_Impl();
     499             : 
     500             :     // Write the content tag, and record the version and starting position
     501       38352 :     _nContentStartPos = _pStream->Tell();
     502       38352 :     ++_nContentCount;
     503       38352 :     _pStream->WriteUInt16( nContentTag );
     504       38352 :     _nContentVer = nContentVer;
     505       38352 : }
     506             : 
     507             : /**
     508             :  *
     509             :  * Internal method for reading an SfxMultiRecord-Headers, after
     510             :  * the base class has been initialized and its header has been read.
     511             :  * If an error occurs an error code is set on the stream, but
     512             :  * the stream position will not be seek-ed back in that case.
     513             :  */
     514           0 : bool SfxMultiRecordReader::ReadHeader_Impl()
     515             : {
     516             :     // read own header
     517           0 :     _pStream->ReadUInt16( _nContentCount );
     518           0 :     _pStream->ReadUInt32( _nContentSize ); // Fix: each on its own, Var|Mix: table position
     519             : 
     520             :     // do we still need to rade a table with Content offsets?
     521           0 :     if ( _nRecordType != SFX_REC_TYPE_FIXSIZE )
     522             :     {
     523             :         // read table from the stream
     524           0 :         sal_uInt32 nContentPos = _pStream->Tell();
     525           0 :         if ( _nRecordType == SFX_REC_TYPE_VARSIZE_RELOC ||
     526           0 :              _nRecordType == SFX_REC_TYPE_MIXTAGS_RELOC )
     527           0 :             _pStream->SeekRel( + _nContentSize );
     528             :         else
     529           0 :             _pStream->Seek( _nContentSize );
     530           0 :         _pContentOfs = new sal_uInt32[_nContentCount];
     531           0 :         memset(_pContentOfs, 0, _nContentCount*sizeof(sal_uInt32));
     532             :         #if defined(OSL_LITENDIAN)
     533           0 :         _pStream->Read( _pContentOfs, sizeof(sal_uInt32)*_nContentCount );
     534             :         #else
     535             :         // (loop without braces)
     536             :         for ( sal_uInt16 n = 0; n < _nContentCount; ++n )
     537             :             _pStream->ReadUInt32( _pContentOfs[n] );
     538             :         #endif
     539           0 :         _pStream->Seek( nContentPos );
     540             :     }
     541             : 
     542             :     // It was possible to read the error if no error is set on the stream
     543           0 :     return !_pStream->GetError();
     544             : }
     545             : 
     546             : 
     547           0 : SfxMultiRecordReader::SfxMultiRecordReader( SvStream *pStream, sal_uInt16 nTag )
     548             :     : _pContentOfs(0)
     549             :     , _nContentSize(0)
     550             :     , _nContentCount(0)
     551             :     , _nContentNo(0)
     552             :     , _nContentTag( 0 )
     553           0 :     , _nContentVer( 0 )
     554             : {
     555             :     // remember position in the stream to be able seek back in case of error
     556           0 :     _nStartPos = pStream->Tell();
     557             : 
     558             :     // look for matching record and initialize base class
     559           0 :     SfxSingleRecordReader::Construct_Impl( pStream );
     560           0 :     if ( SfxSingleRecordReader::FindHeader_Impl( SFX_REC_TYPE_FIXSIZE |
     561             :             SFX_REC_TYPE_VARSIZE | SFX_REC_TYPE_VARSIZE_RELOC |
     562             :             SFX_REC_TYPE_MIXTAGS | SFX_REC_TYPE_MIXTAGS_RELOC,
     563           0 :             nTag ) )
     564             :     {
     565             :         // also read own header
     566           0 :         if ( !ReadHeader_Impl() )
     567             :             // not readable => mark as invalid and reset stream position
     568           0 :             SetInvalid_Impl( _nStartPos);
     569             :     }
     570           0 : }
     571             : 
     572             : 
     573           0 : SfxMultiRecordReader::~SfxMultiRecordReader()
     574             : {
     575           0 :     delete[] _pContentOfs;
     576           0 : }
     577             : 
     578             : /**
     579             :  *
     580             :  * Positions the stream at the start of the next Content, or
     581             :  * for the first call at the start of the first Content in the record,
     582             :  * and reads its header if necessary.
     583             :  *
     584             :  * @return sal_False if there is no further Content according to
     585             :  * the record header. Even if sal_True is returned an error can
     586             :  * be set on the stream, for instance if the record finished prematurely
     587             :  * in a broken file.
     588             :  */
     589           0 : bool SfxMultiRecordReader::GetContent()
     590             : {
     591             :     // more Content available?
     592           0 :     if ( _nContentNo < _nContentCount )
     593             :     {
     594             :         // position the stream at the start of the Content
     595           0 :         sal_uInt32 nOffset = _nRecordType == SFX_REC_TYPE_FIXSIZE
     596           0 :                     ? _nContentNo * _nContentSize
     597           0 :                     : SFX_REC_CONTENT_OFS(_pContentOfs[_nContentNo]);
     598           0 :         sal_uInt32 nNewPos = _nStartPos + nOffset;
     599             :         DBG_ASSERT( nNewPos >= _pStream->Tell(), "SfxMultiRecordReader::GetContent() - New position before current, to much data red!" );
     600             : 
     601             :         // #99366#: correct stream pos in every case;
     602             :         // the if clause was added by MT  a long time ago,
     603             :         // maybe to 'repair' other corrupt documents; but this
     604             :         // gives errors when writing with 5.1 and reading with current
     605             :         // versions, so we decided to remove the if clause (KA-05/17/2002)
     606             :         // if ( nNewPos > _pStream->Tell() )
     607           0 :         _pStream->Seek( nNewPos );
     608             : 
     609             :         // Read Content Header if available
     610           0 :         if ( _nRecordType == SFX_REC_TYPE_MIXTAGS ||
     611           0 :              _nRecordType == SFX_REC_TYPE_MIXTAGS_RELOC )
     612             :         {
     613             :             _nContentVer = sal::static_int_cast< sal_uInt8 >(
     614           0 :                 SFX_REC_CONTENT_VER(_pContentOfs[_nContentNo]));
     615           0 :             _pStream->ReadUInt16( _nContentTag );
     616             :         }
     617             : 
     618             :         // Increment ContentNo
     619           0 :         ++_nContentNo;
     620           0 :         return true;
     621             :     }
     622             : 
     623           0 :     return false;
     624             : }
     625             : 
     626             : 
     627             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10