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

Generated by: LCOV version 1.10