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

Generated by: LCOV version 1.11