LCOV - code coverage report
Current view: top level - sc/source/filter/oox - biffinputstream.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 1 252 0.4 %
Date: 2014-11-03 Functions: 2 46 4.3 %
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 "biffinputstream.hxx"
      21             : 
      22             : #include <algorithm>
      23             : #include <rtl/ustrbuf.hxx>
      24             : 
      25             : namespace oox {
      26             : namespace xls {
      27             : 
      28             : namespace prv {
      29             : 
      30           0 : BiffInputRecordBuffer::BiffInputRecordBuffer( BinaryInputStream& rInStrm ) :
      31             :     mrInStrm( rInStrm ),
      32             :     mpCurrentData( 0 ),
      33             :     mnHeaderPos( -1 ),
      34             :     mnBodyPos( 0 ),
      35             :     mnBufferBodyPos( 0 ),
      36             :     mnNextHeaderPos( 0 ),
      37             :     mnRecId( BIFF_ID_UNKNOWN ),
      38             :     mnRecSize( 0 ),
      39             :     mnRecPos( 0 ),
      40           0 :     mbValidHeader( false )
      41             : {
      42             :     OSL_ENSURE( mrInStrm.isSeekable(), "BiffInputRecordBuffer::BiffInputRecordBuffer - stream must be seekable" );
      43           0 :     mrInStrm.seekToStart();
      44           0 :     maOriginalData.reserve( SAL_MAX_UINT16 );
      45           0 :     maDecodedData.reserve( SAL_MAX_UINT16 );
      46           0 :     enableDecoder( false );     // updates mpCurrentData
      47           0 : }
      48             : 
      49           0 : void BiffInputRecordBuffer::restartAt( sal_Int64 nPos )
      50             : {
      51           0 :     mnHeaderPos = -1;
      52           0 :     mnBodyPos = mnBufferBodyPos = 0;
      53           0 :     mnNextHeaderPos = nPos;
      54           0 :     mnRecId = BIFF_ID_UNKNOWN;
      55           0 :     mnRecSize = mnRecPos = 0;
      56           0 :     mbValidHeader = false;
      57           0 : }
      58             : 
      59           0 : void BiffInputRecordBuffer::setDecoder( const BiffDecoderRef& rxDecoder )
      60             : {
      61           0 :     mxDecoder = rxDecoder;
      62           0 :     enableDecoder( true );
      63           0 :     updateDecoded();
      64           0 : }
      65             : 
      66           0 : void BiffInputRecordBuffer::enableDecoder( bool bEnable )
      67             : {
      68           0 :     mpCurrentData = (bEnable && mxDecoder.get() && mxDecoder->isValid()) ? &maDecodedData : &maOriginalData;
      69           0 : }
      70             : 
      71           0 : bool BiffInputRecordBuffer::startRecord( sal_Int64 nHeaderPos )
      72             : {
      73           0 :     mbValidHeader = (0 <= nHeaderPos) && (nHeaderPos + 4 <= mrInStrm.size());
      74           0 :     if( mbValidHeader )
      75             :     {
      76           0 :         mnHeaderPos = nHeaderPos;
      77           0 :         mrInStrm.seek( nHeaderPos );
      78           0 :         mrInStrm >> mnRecId >> mnRecSize;
      79           0 :         mnBodyPos = mrInStrm.tell();
      80           0 :         mnNextHeaderPos = mnBodyPos + mnRecSize;
      81           0 :         mbValidHeader = !mrInStrm.isEof() && (mnNextHeaderPos <= mrInStrm.size());
      82             :     }
      83           0 :     if( !mbValidHeader )
      84             :     {
      85           0 :         mnHeaderPos = mnBodyPos = -1;
      86           0 :         mnNextHeaderPos = 0;
      87           0 :         mnRecId = BIFF_ID_UNKNOWN;
      88           0 :         mnRecSize = 0;
      89             :     }
      90           0 :     mnRecPos = 0;
      91           0 :     return mbValidHeader;
      92             : }
      93             : 
      94           0 : bool BiffInputRecordBuffer::startNextRecord()
      95             : {
      96           0 :     return startRecord( mnNextHeaderPos );
      97             : }
      98             : 
      99           0 : sal_uInt16 BiffInputRecordBuffer::getNextRecId()
     100             : {
     101           0 :     sal_uInt16 nRecId = BIFF_ID_UNKNOWN;
     102           0 :     if( mbValidHeader && (mnNextHeaderPos + 4 <= mrInStrm.size()) )
     103             :     {
     104           0 :         mrInStrm.seek( mnNextHeaderPos );
     105           0 :         mrInStrm >> nRecId;
     106             :     }
     107           0 :     return nRecId;
     108             : }
     109             : 
     110           0 : void BiffInputRecordBuffer::read( void* opData, sal_uInt16 nBytes )
     111             : {
     112           0 :     updateBuffer();
     113             :     OSL_ENSURE( nBytes > 0, "BiffInputRecordBuffer::read - nothing to read" );
     114             :     OSL_ENSURE( nBytes <= getRecLeft(), "BiffInputRecordBuffer::read - buffer overflow" );
     115           0 :     memcpy( opData, &(*mpCurrentData)[ mnRecPos ], nBytes );
     116           0 :     mnRecPos = mnRecPos + nBytes;
     117           0 : }
     118             : 
     119           0 : void BiffInputRecordBuffer::skip( sal_uInt16 nBytes )
     120             : {
     121             :     OSL_ENSURE( nBytes > 0, "BiffInputRecordBuffer::skip - nothing to skip" );
     122             :     OSL_ENSURE( nBytes <= getRecLeft(), "BiffInputRecordBuffer::skip - buffer overflow" );
     123           0 :     mnRecPos = mnRecPos + nBytes;
     124           0 : }
     125             : 
     126           0 : void BiffInputRecordBuffer::updateBuffer()
     127             : {
     128             :     OSL_ENSURE( mbValidHeader, "BiffInputRecordBuffer::updateBuffer - invalid access" );
     129           0 :     if( mnBodyPos != mnBufferBodyPos )
     130             :     {
     131           0 :         mrInStrm.seek( mnBodyPos );
     132           0 :         maOriginalData.resize( mnRecSize );
     133           0 :         if( mnRecSize > 0 )
     134           0 :             mrInStrm.readMemory( &maOriginalData.front(), static_cast< sal_Int32 >( mnRecSize ) );
     135           0 :         mnBufferBodyPos = mnBodyPos;
     136           0 :         updateDecoded();
     137             :     }
     138           0 : }
     139             : 
     140           0 : void BiffInputRecordBuffer::updateDecoded()
     141             : {
     142           0 :     if( mxDecoder.get() && mxDecoder->isValid() )
     143             :     {
     144           0 :         maDecodedData.resize( mnRecSize );
     145           0 :         if( mnRecSize > 0 )
     146           0 :             mxDecoder->decode( &maDecodedData.front(), &maOriginalData.front(), mnBodyPos, mnRecSize );
     147             :     }
     148           0 : }
     149             : 
     150             : } // namespace prv
     151             : 
     152           0 : BiffInputStream::BiffInputStream( BinaryInputStream& rInStream, bool bContLookup ) :
     153             :     BinaryStreamBase( true ),
     154             :     maRecBuffer( rInStream ),
     155             :     mnRecHandle( -1 ),
     156             :     mnRecId( BIFF_ID_UNKNOWN ),
     157             :     mnAltContId( BIFF_ID_UNKNOWN ),
     158             :     mnCurrRecSize( 0 ),
     159             :     mnComplRecSize( 0 ),
     160             :     mbHasComplRec( false ),
     161           0 :     mbCont( bContLookup )
     162             : {
     163           0 :     mbEof = true;   // EOF will be true if stream is not inside a record
     164           0 : }
     165             : 
     166             : // record control -------------------------------------------------------------
     167             : 
     168           0 : bool BiffInputStream::startNextRecord()
     169             : {
     170           0 :     bool bValidRec = false;
     171             :     /*  #i4266# ignore zero records (id==len==0) (e.g. the application
     172             :         "Crystal Report" writes zero records between other records) */
     173           0 :     bool bIsZeroRec = false;
     174           0 :     do
     175             :     {
     176             :         // record header is never encrypted
     177           0 :         maRecBuffer.enableDecoder( false );
     178             :         // read header of next raw record, returns false at end of stream
     179           0 :         bValidRec = maRecBuffer.startNextRecord();
     180             :         // ignore record, if identifier and size are zero
     181           0 :         bIsZeroRec = (maRecBuffer.getRecId() == 0) && (maRecBuffer.getRecSize() == 0);
     182             :     }
     183           0 :     while( bValidRec && ((mbCont && isContinueId( maRecBuffer.getRecId() )) || bIsZeroRec) );
     184             : 
     185             :     // setup other class members
     186           0 :     setupRecord();
     187           0 :     return isInRecord();
     188             : }
     189             : 
     190           0 : bool BiffInputStream::startRecordByHandle( sal_Int64 nRecHandle )
     191             : {
     192           0 :     rewindToRecord( nRecHandle );
     193           0 :     return startNextRecord();
     194             : }
     195             : 
     196           0 : void BiffInputStream::rewindRecord()
     197             : {
     198           0 :     rewindToRecord( mnRecHandle );
     199           0 : }
     200             : 
     201             : // decoder --------------------------------------------------------------------
     202             : 
     203           0 : void BiffInputStream::setDecoder( const BiffDecoderRef& rxDecoder )
     204             : {
     205           0 :     maRecBuffer.setDecoder( rxDecoder );
     206           0 : }
     207             : 
     208           0 : void BiffInputStream::enableDecoder( bool bEnable )
     209             : {
     210           0 :     maRecBuffer.enableDecoder( bEnable );
     211           0 : }
     212             : 
     213             : // stream/record state and info -----------------------------------------------
     214             : 
     215           0 : sal_uInt16 BiffInputStream::getNextRecId()
     216             : {
     217           0 :     sal_uInt16 nRecId = BIFF_ID_UNKNOWN;
     218           0 :     if( isInRecord() )
     219             :     {
     220           0 :         sal_Int64 nCurrPos = tell();            // save current position in record
     221           0 :         while( jumpToNextContinue() ) {}        // skip following CONTINUE records
     222           0 :         if( maRecBuffer.startNextRecord() )     // read header of next record
     223           0 :             nRecId = maRecBuffer.getRecId();
     224           0 :         seek( nCurrPos );                       // restore position, seek() resets old mbValid state
     225             :     }
     226           0 :     return nRecId;
     227             : }
     228             : 
     229             : // BinaryStreamBase interface (seeking) ---------------------------------------
     230             : 
     231           0 : sal_Int64 BiffInputStream::size() const
     232             : {
     233           0 :     if( !mbHasComplRec )
     234           0 :         const_cast< BiffInputStream* >( this )->calcRecordLength();
     235           0 :     return mnComplRecSize;
     236             : }
     237             : 
     238           0 : sal_Int64 BiffInputStream::tell() const
     239             : {
     240           0 :     return mbEof ? -1 : (mnCurrRecSize - maRecBuffer.getRecLeft());
     241             : }
     242             : 
     243           0 : void BiffInputStream::seek( sal_Int64 nRecPos )
     244             : {
     245           0 :     if( isInRecord() )
     246             :     {
     247           0 :         if( mbEof || (nRecPos < tell()) )
     248           0 :             restartRecord( false );
     249           0 :         if( !mbEof && (nRecPos > tell()) )
     250           0 :             skip( static_cast< sal_Int32 >( nRecPos - tell() ) );
     251             :     }
     252           0 : }
     253             : 
     254           0 : void BiffInputStream::close()
     255             : {
     256           0 : }
     257             : 
     258             : // BinaryInputStream interface (stream read access) ---------------------------
     259             : 
     260           0 : sal_Int32 BiffInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize )
     261             : {
     262           0 :     sal_Int32 nRet = 0;
     263           0 :     if( !mbEof )
     264             :     {
     265           0 :         orData.realloc( ::std::max< sal_Int32 >( nBytes, 0 ) );
     266           0 :         if( nBytes > 0 )
     267           0 :             nRet = readMemory( orData.getArray(), nBytes, nAtomSize );
     268             :     }
     269           0 :     return nRet;
     270             : }
     271             : 
     272           0 : sal_Int32 BiffInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize )
     273             : {
     274           0 :     sal_Int32 nRet = 0;
     275           0 :     if( !mbEof && opMem && (nBytes > 0) )
     276             :     {
     277           0 :         sal_uInt8* pnBuffer = reinterpret_cast< sal_uInt8* >( opMem );
     278           0 :         sal_Int32 nBytesLeft = nBytes;
     279             : 
     280           0 :         while( !mbEof && (nBytesLeft > 0) )
     281             :         {
     282           0 :             sal_uInt16 nReadSize = getMaxRawReadSize( nBytesLeft, nAtomSize );
     283             :             // check nReadSize, stream may already be located at end of a raw record
     284           0 :             if( nReadSize > 0 )
     285             :             {
     286           0 :                 maRecBuffer.read( pnBuffer, nReadSize );
     287           0 :                 nRet += nReadSize;
     288           0 :                 pnBuffer += nReadSize;
     289           0 :                 nBytesLeft -= nReadSize;
     290             :             }
     291           0 :             if( nBytesLeft > 0 )
     292           0 :                 jumpToNextContinue();
     293             :             OSL_ENSURE( !mbEof, "BiffInputStream::readMemory - record overread" );
     294             :         }
     295             :     }
     296           0 :     return nRet;
     297             : }
     298             : 
     299           0 : void BiffInputStream::skip( sal_Int32 nBytes, size_t nAtomSize )
     300             : {
     301           0 :     sal_Int32 nBytesLeft = nBytes;
     302           0 :     while( !mbEof && (nBytesLeft > 0) )
     303             :     {
     304           0 :         sal_uInt16 nSkipSize = getMaxRawReadSize( nBytesLeft, nAtomSize );
     305             :         // check nSkipSize, stream may already be located at end of a raw record
     306           0 :         if( nSkipSize > 0 )
     307             :         {
     308           0 :             maRecBuffer.skip( nSkipSize );
     309           0 :             nBytesLeft -= nSkipSize;
     310             :         }
     311           0 :         if( nBytesLeft > 0 )
     312           0 :             jumpToNextContinue();
     313             :         OSL_ENSURE( !mbEof, "BiffInputStream::skip - record overread" );
     314             :     }
     315           0 : }
     316             : 
     317             : // byte strings ---------------------------------------------------------------
     318             : 
     319           0 : OString BiffInputStream::readByteString( bool b16BitLen, bool bAllowNulChars )
     320             : {
     321           0 :     sal_Int32 nStrLen = b16BitLen ? readuInt16() : readuInt8();
     322           0 :     return readCharArray( nStrLen, bAllowNulChars );
     323             : }
     324             : 
     325           0 : OUString BiffInputStream::readByteStringUC( bool b16BitLen, rtl_TextEncoding eTextEnc, bool bAllowNulChars )
     326             : {
     327           0 :     return OStringToOUString( readByteString( b16BitLen, bAllowNulChars ), eTextEnc );
     328             : }
     329             : 
     330             : // Unicode strings ------------------------------------------------------------
     331             : 
     332           0 : OUString BiffInputStream::readUniStringChars( sal_uInt16 nChars, bool b16BitChars, bool bAllowNulChars )
     333             : {
     334           0 :     OUStringBuffer aBuffer;
     335           0 :     aBuffer.ensureCapacity( nChars );
     336             : 
     337             :     /*  This function has to react on CONTINUE records which repeat the flags
     338             :         field in their first byte and may change the 8bit/16bit character mode,
     339             :         thus a plain call to readCompressedUnicodeArray() cannot be used here. */
     340           0 :     sal_Int32 nCharsLeft = nChars;
     341           0 :     while( !mbEof && (nCharsLeft > 0) )
     342             :     {
     343             :         /*  Read the character array from the remaining part of the current raw
     344             :             record. First, calculate the maximum number of characters that can
     345             :             be read without triggering to start a following CONTINUE record. */
     346           0 :         sal_Int32 nRawChars = b16BitChars ? (getMaxRawReadSize( nCharsLeft * 2, 2 ) / 2) : getMaxRawReadSize( nCharsLeft, 1 );
     347           0 :         aBuffer.append( readCompressedUnicodeArray( nRawChars, !b16BitChars, bAllowNulChars ) );
     348             : 
     349             :         /*  Prepare for next CONTINUE record. Calling jumpToNextStringContinue()
     350             :             reads the leading byte in the following CONTINUE record and updates
     351             :             the b16BitChars flag. */
     352           0 :         nCharsLeft -= nRawChars;
     353           0 :         if( nCharsLeft > 0 )
     354           0 :             jumpToNextStringContinue( b16BitChars );
     355             :     }
     356             : 
     357           0 :     return aBuffer.makeStringAndClear();
     358             : }
     359             : 
     360           0 : OUString BiffInputStream::readUniStringBody( sal_uInt16 nChars, bool bAllowNulChars )
     361             : {
     362             :     bool b16BitChars;
     363             :     sal_Int32 nAddSize;
     364           0 :     readUniStringHeader( b16BitChars, nAddSize );
     365           0 :     OUString aString = readUniStringChars( nChars, b16BitChars, bAllowNulChars );
     366           0 :     skip( nAddSize );
     367           0 :     return aString;
     368             : }
     369             : 
     370           0 : OUString BiffInputStream::readUniString( bool bAllowNulChars )
     371             : {
     372           0 :     return readUniStringBody( readuInt16(), bAllowNulChars );
     373             : }
     374             : 
     375             : // private --------------------------------------------------------------------
     376             : 
     377           0 : void BiffInputStream::setupRecord()
     378             : {
     379             :     // initialize class members
     380           0 :     mnRecHandle = maRecBuffer.getRecHeaderPos();
     381           0 :     mnRecId = maRecBuffer.getRecId();
     382           0 :     mnAltContId = BIFF_ID_UNKNOWN;
     383           0 :     mnCurrRecSize = mnComplRecSize = maRecBuffer.getRecSize();
     384           0 :     mbHasComplRec = !mbCont;
     385           0 :     mbEof = !isInRecord();
     386             :     // enable decoder in new record
     387           0 :     enableDecoder( true );
     388           0 : }
     389             : 
     390           0 : void BiffInputStream::restartRecord( bool bInvalidateRecSize )
     391             : {
     392           0 :     if( isInRecord() )
     393             :     {
     394           0 :         maRecBuffer.startRecord( getRecHandle() );
     395           0 :         mnCurrRecSize = maRecBuffer.getRecSize();
     396           0 :         if( bInvalidateRecSize )
     397             :         {
     398           0 :             mnComplRecSize = mnCurrRecSize;
     399           0 :             mbHasComplRec = !mbCont;
     400             :         }
     401           0 :         mbEof = false;
     402             :     }
     403           0 : }
     404             : 
     405           0 : void BiffInputStream::rewindToRecord( sal_Int64 nRecHandle )
     406             : {
     407           0 :     if( nRecHandle >= 0 )
     408             :     {
     409           0 :         maRecBuffer.restartAt( nRecHandle );
     410           0 :         mnRecHandle = -1;
     411           0 :         mbEof = true;   // as long as the record is not started
     412             :     }
     413           0 : }
     414             : 
     415           0 : bool BiffInputStream::isContinueId( sal_uInt16 nRecId ) const
     416             : {
     417           0 :     return (nRecId == BIFF_ID_CONT) || (nRecId == mnAltContId);
     418             : }
     419             : 
     420           0 : bool BiffInputStream::jumpToNextContinue()
     421             : {
     422           0 :     mbEof = mbEof || !mbCont || !isContinueId( maRecBuffer.getNextRecId() ) || !maRecBuffer.startNextRecord();
     423           0 :     if( !mbEof )
     424           0 :         mnCurrRecSize += maRecBuffer.getRecSize();
     425           0 :     return !mbEof;
     426             : }
     427             : 
     428           0 : bool BiffInputStream::jumpToNextStringContinue( bool& rb16BitChars )
     429             : {
     430             :     OSL_ENSURE( maRecBuffer.getRecLeft() == 0, "BiffInputStream::jumpToNextStringContinue - alignment error" );
     431             : 
     432           0 :     if( mbCont && (getRemaining() > 0) )
     433             :     {
     434           0 :         jumpToNextContinue();
     435             :     }
     436           0 :     else if( mnRecId == BIFF_ID_CONT )
     437             :     {
     438             :         /*  CONTINUE handling is off, but we have started reading in a CONTINUE
     439             :             record -> start next CONTINUE for TXO import. We really start a new
     440             :             record here - no chance to return to string origin. */
     441           0 :         mbEof = mbEof || (maRecBuffer.getNextRecId() != BIFF_ID_CONT) || !maRecBuffer.startNextRecord();
     442           0 :         if( !mbEof )
     443           0 :             setupRecord();
     444             :     }
     445             : 
     446             :     // trying to read the flags invalidates stream, if no CONTINUE record has been found
     447             :     sal_uInt8 nFlags;
     448           0 :     readValue( nFlags );
     449           0 :     rb16BitChars = getFlag( nFlags, BIFF_STRF_16BIT );
     450           0 :     return !mbEof;
     451             : }
     452             : 
     453           0 : void BiffInputStream::calcRecordLength()
     454             : {
     455           0 :     sal_Int64 nCurrPos = tell();            // save current position in record
     456           0 :     while( jumpToNextContinue() ) {}        // jumpToNextContinue() adds up mnCurrRecSize
     457           0 :     mnComplRecSize = mnCurrRecSize;
     458           0 :     mbHasComplRec = true;
     459           0 :     seek( nCurrPos );                       // restore position, seek() resets old mbValid state
     460           0 : }
     461             : 
     462           0 : sal_uInt16 BiffInputStream::getMaxRawReadSize( sal_Int32 nBytes, size_t nAtomSize ) const
     463             : {
     464           0 :     sal_uInt16 nMaxSize = getLimitedValue< sal_uInt16, sal_Int32 >( nBytes, 0, maRecBuffer.getRecLeft() );
     465           0 :     if( (0 < nMaxSize) && (nMaxSize < nBytes) && (nAtomSize > 1) )
     466             :     {
     467             :         // check that remaining data in record buffer is a multiple of the passed atom size
     468           0 :         sal_uInt16 nPadding = static_cast< sal_uInt16 >( nMaxSize % nAtomSize );
     469             :         OSL_ENSURE( nPadding == 0, "BiffInputStream::getMaxRawReadSize - alignment error" );
     470           0 :         nMaxSize = nMaxSize - nPadding;
     471             :     }
     472           0 :     return nMaxSize;
     473             : }
     474             : 
     475           0 : void BiffInputStream::readUniStringHeader( bool& orb16BitChars, sal_Int32& ornAddSize )
     476             : {
     477           0 :     sal_uInt8 nFlags = readuInt8();
     478             :     OSL_ENSURE( !getFlag( nFlags, BIFF_STRF_UNKNOWN ), "BiffInputStream::readUniStringHeader - unknown flags" );
     479           0 :     orb16BitChars = getFlag( nFlags, BIFF_STRF_16BIT );
     480           0 :     sal_uInt16 nFontCount = getFlag( nFlags, BIFF_STRF_RICH ) ? readuInt16() : 0;
     481           0 :     sal_Int32 nPhoneticSize = getFlag( nFlags, BIFF_STRF_PHONETIC ) ? readInt32() : 0;
     482           0 :     ornAddSize = 4 * nFontCount + ::std::max< sal_Int32 >( 0, nPhoneticSize );
     483           0 : }
     484             : 
     485           0 : BiffInputStreamPos::BiffInputStreamPos( BiffInputStream& rStrm ) :
     486             :     mrStrm( rStrm ),
     487           0 :     mnRecHandle( rStrm.getRecHandle() ),
     488           0 :     mnRecPos( rStrm.tell() )
     489             : {
     490           0 : }
     491             : 
     492           0 : bool BiffInputStreamPos::restorePosition()
     493             : {
     494           0 :     bool bValidRec = mrStrm.startRecordByHandle( mnRecHandle );
     495           0 :     if( bValidRec )
     496           0 :         mrStrm.seek( mnRecPos );
     497           0 :     return bValidRec && !mrStrm.isEof();
     498             : }
     499             : 
     500           0 : BiffInputStreamPosGuard::BiffInputStreamPosGuard( BiffInputStream& rStrm ) :
     501           0 :     BiffInputStreamPos( rStrm )
     502             : {
     503           0 : }
     504             : 
     505           0 : BiffInputStreamPosGuard::~BiffInputStreamPosGuard()
     506             : {
     507           0 :     restorePosition();
     508           0 : }
     509             : 
     510             : } // namespace xls
     511          48 : } // namespace oox
     512             : 
     513             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10