1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: biffinputstream.cxx,v $
10 * $Revision: 1.4.20.2 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "oox/xls/biffinputstream.hxx"
33 #include <rtl/ustrbuf.hxx>
36 using ::rtl::OStringToOUString
;
37 using ::rtl::OUString
;
38 using ::rtl::OUStringBuffer
;
43 // ============================================================================
47 BiffInputRecordBuffer::BiffInputRecordBuffer( BinaryInputStream
& rInStrm
) :
54 mnRecId( BIFF_ID_UNKNOWN
),
57 mbValidHeader( false )
59 OSL_ENSURE( mrInStrm
.isSeekable(), "BiffInputRecordBuffer::BiffInputRecordBuffer - stream must be seekable" );
60 mrInStrm
.seekToStart();
61 maOriginalData
.reserve( SAL_MAX_UINT16
);
62 maDecodedData
.reserve( SAL_MAX_UINT16
);
63 enableDecoder( false ); // updates mpCurrentData
66 void BiffInputRecordBuffer::restartAt( sal_Int64 nPos
)
69 mnBodyPos
= mnBufferBodyPos
= 0;
70 mnNextHeaderPos
= nPos
;
71 mnRecId
= BIFF_ID_UNKNOWN
;
72 mnRecSize
= mnRecPos
= 0;
73 mbValidHeader
= false;
76 void BiffInputRecordBuffer::setDecoder( const BiffDecoderRef
& rxDecoder
)
78 mxDecoder
= rxDecoder
;
79 enableDecoder( true );
83 void BiffInputRecordBuffer::enableDecoder( bool bEnable
)
85 mpCurrentData
= (bEnable
&& mxDecoder
.get() && mxDecoder
->isValid()) ? &maDecodedData
: &maOriginalData
;
88 bool BiffInputRecordBuffer::startRecord( sal_Int64 nHeaderPos
)
90 mbValidHeader
= (0 <= nHeaderPos
) && (nHeaderPos
+ 4 <= mrInStrm
.getLength());
93 mnHeaderPos
= nHeaderPos
;
94 mrInStrm
.seek( nHeaderPos
);
95 mrInStrm
>> mnRecId
>> mnRecSize
;
96 mnBodyPos
= mrInStrm
.tell();
97 mnNextHeaderPos
= mnBodyPos
+ mnRecSize
;
98 mbValidHeader
= !mrInStrm
.isEof() && (mnNextHeaderPos
<= mrInStrm
.getLength());
102 mnHeaderPos
= mnBodyPos
= -1;
104 mnRecId
= BIFF_ID_UNKNOWN
;
108 return mbValidHeader
;
111 bool BiffInputRecordBuffer::startNextRecord()
113 return startRecord( mnNextHeaderPos
);
116 sal_uInt16
BiffInputRecordBuffer::getNextRecId()
118 sal_uInt16 nRecId
= BIFF_ID_UNKNOWN
;
119 if( mbValidHeader
&& (mnNextHeaderPos
+ 4 <= mrInStrm
.getLength()) )
121 mrInStrm
.seek( mnNextHeaderPos
);
127 void BiffInputRecordBuffer::read( void* opData
, sal_uInt16 nBytes
)
130 OSL_ENSURE( nBytes
> 0, "BiffInputRecordBuffer::read - nothing to read" );
131 OSL_ENSURE( nBytes
<= getRecLeft(), "BiffInputRecordBuffer::read - buffer overflow" );
132 memcpy( opData
, &(*mpCurrentData
)[ mnRecPos
], nBytes
);
133 mnRecPos
= mnRecPos
+ nBytes
;
136 void BiffInputRecordBuffer::skip( sal_uInt16 nBytes
)
138 OSL_ENSURE( nBytes
> 0, "BiffInputRecordBuffer::skip - nothing to skip" );
139 OSL_ENSURE( nBytes
<= getRecLeft(), "BiffInputRecordBuffer::skip - buffer overflow" );
140 mnRecPos
= mnRecPos
+ nBytes
;
143 void BiffInputRecordBuffer::updateBuffer()
145 OSL_ENSURE( mbValidHeader
, "BiffInputRecordBuffer::updateBuffer - invalid access" );
146 if( mnBodyPos
!= mnBufferBodyPos
)
148 mrInStrm
.seek( mnBodyPos
);
149 maOriginalData
.resize( mnRecSize
);
151 mrInStrm
.readMemory( &maOriginalData
.front(), static_cast< sal_Int32
>( mnRecSize
) );
152 mnBufferBodyPos
= mnBodyPos
;
157 void BiffInputRecordBuffer::updateDecoded()
159 if( mxDecoder
.get() && mxDecoder
->isValid() )
161 maDecodedData
.resize( mnRecSize
);
163 mxDecoder
->decode( &maDecodedData
.front(), &maOriginalData
.front(), mnBodyPos
, mnRecSize
);
169 // ============================================================================
171 BiffInputStream::BiffInputStream( BinaryInputStream
& rInStream
, bool bContLookup
) :
172 maRecBuffer( rInStream
),
174 mnRecId( BIFF_ID_UNKNOWN
),
175 mnAltContId( BIFF_ID_UNKNOWN
),
178 mbHasComplRec( false ),
179 mbCont( bContLookup
)
181 mbEof
= true; // EOF will be true if stream is not inside a record
184 // record control -------------------------------------------------------------
186 bool BiffInputStream::startNextRecord()
188 bool bValidRec
= false;
189 /* #i4266# ignore zero records (id==len==0) (e.g. the application
190 "Crystal Report" writes zero records between other records) */
191 bool bIsZeroRec
= false;
194 // record header is never encrypted
195 maRecBuffer
.enableDecoder( false );
196 // read header of next raw record, returns false at end of stream
197 bValidRec
= maRecBuffer
.startNextRecord();
198 // ignore record, if identifier and size are zero
199 bIsZeroRec
= (maRecBuffer
.getRecId() == 0) && (maRecBuffer
.getRecSize() == 0);
201 while( bValidRec
&& ((mbCont
&& isContinueId( maRecBuffer
.getRecId() )) || bIsZeroRec
) );
203 // setup other class members
208 bool BiffInputStream::startRecordByHandle( sal_Int64 nRecHandle
)
210 rewindToRecord( nRecHandle
);
211 return startNextRecord();
214 void BiffInputStream::resetRecord( bool bContLookup
, sal_uInt16 nAltContId
)
218 mbCont
= bContLookup
;
219 mnAltContId
= nAltContId
;
220 restartRecord( true );
221 maRecBuffer
.enableDecoder( true );
225 void BiffInputStream::rewindRecord()
227 rewindToRecord( mnRecHandle
);
230 // decoder --------------------------------------------------------------------
232 void BiffInputStream::setDecoder( const BiffDecoderRef
& rxDecoder
)
234 maRecBuffer
.setDecoder( rxDecoder
);
237 void BiffInputStream::enableDecoder( bool bEnable
)
239 maRecBuffer
.enableDecoder( bEnable
);
242 // stream/record state and info -----------------------------------------------
244 sal_uInt16
BiffInputStream::getNextRecId()
246 sal_uInt16 nRecId
= BIFF_ID_UNKNOWN
;
249 sal_Int64 nCurrPos
= tell(); // save current position in record
250 while( jumpToNextContinue() ) {} // skip following CONTINUE records
251 if( maRecBuffer
.startNextRecord() ) // read header of next record
252 nRecId
= maRecBuffer
.getRecId();
253 seek( nCurrPos
); // restore position, seek() resets old mbValid state
258 // BinaryStreamBase interface (seeking) ---------------------------------------
260 bool BiffInputStream::isSeekable() const
265 sal_Int64
BiffInputStream::tell() const
267 return mbEof
? -1 : (mnCurrRecSize
- maRecBuffer
.getRecLeft());
270 sal_Int64
BiffInputStream::getLength() const
273 const_cast< BiffInputStream
* >( this )->calcRecordLength();
274 return mnComplRecSize
;
277 void BiffInputStream::seek( sal_Int64 nRecPos
)
281 if( mbEof
|| (nRecPos
< tell()) )
282 restartRecord( false );
283 if( !mbEof
&& (nRecPos
> tell()) )
284 skip( static_cast< sal_Int32
>( nRecPos
- tell() ) );
288 sal_Int64
BiffInputStream::tellBase() const
290 return maRecBuffer
.getBaseStream().tell();
293 sal_Int64
BiffInputStream::getBaseLength() const
295 return maRecBuffer
.getBaseStream().getLength();
298 // BinaryInputStream interface (stream read access) ---------------------------
300 sal_Int32
BiffInputStream::readData( StreamDataSequence
& orData
, sal_Int32 nBytes
)
305 orData
.realloc( ::std::max
< sal_Int32
>( nBytes
, 0 ) );
308 nRet
= readMemory( orData
.getArray(), nBytes
);
310 orData
.realloc( nRet
);
316 sal_Int32
BiffInputStream::readMemory( void* opMem
, sal_Int32 nBytes
)
319 if( !mbEof
&& opMem
&& (nBytes
> 0) )
321 sal_uInt8
* pnBuffer
= reinterpret_cast< sal_uInt8
* >( opMem
);
322 sal_Int32 nBytesLeft
= nBytes
;
324 while( !mbEof
&& (nBytesLeft
> 0) )
326 sal_uInt16 nReadSize
= getMaxRawReadSize( nBytesLeft
);
327 // check nReadSize, stream may already be located at end of a raw record
330 maRecBuffer
.read( pnBuffer
, nReadSize
);
332 pnBuffer
+= nReadSize
;
333 nBytesLeft
-= nReadSize
;
336 jumpToNextContinue();
337 OSL_ENSURE( !mbEof
, "BiffInputStream::readMemory - record overread" );
343 void BiffInputStream::skip( sal_Int32 nBytes
)
345 sal_Int32 nBytesLeft
= nBytes
;
346 while( !mbEof
&& (nBytesLeft
> 0) )
348 sal_uInt16 nSkipSize
= getMaxRawReadSize( nBytesLeft
);
349 // check nSkipSize, stream may already be located at end of a raw record
352 maRecBuffer
.skip( nSkipSize
);
353 nBytesLeft
-= nSkipSize
;
356 jumpToNextContinue();
357 OSL_ENSURE( !mbEof
, "BiffInputStream::skip - record overread" );
361 // byte strings ---------------------------------------------------------------
363 OString
BiffInputStream::readByteString( bool b16BitLen
, bool bAllowNulChars
)
365 sal_Int32 nStrLen
= b16BitLen
? readuInt16() : readuInt8();
366 return readCharArray( nStrLen
, bAllowNulChars
);
369 OUString
BiffInputStream::readByteStringUC( bool b16BitLen
, rtl_TextEncoding eTextEnc
, bool bAllowNulChars
)
371 return OStringToOUString( readByteString( b16BitLen
, bAllowNulChars
), eTextEnc
);
374 void BiffInputStream::skipByteString( bool b16BitLen
)
376 skip( b16BitLen
? readuInt16() : readuInt8() );
379 // Unicode strings ------------------------------------------------------------
381 OUString
BiffInputStream::readUniStringChars( sal_uInt16 nChars
, bool b16BitChars
, bool bAllowNulChars
)
383 OUStringBuffer aBuffer
;
384 aBuffer
.ensureCapacity( nChars
);
386 /* This function has to react on CONTINUE records to read the repeated
387 flags field, so readUnicodeArray() cannot be used here. */
388 sal_uInt16 nCharsLeft
= nChars
;
389 while( !mbEof
&& (nCharsLeft
> 0) )
391 sal_uInt16 nPortionCount
= 0;
394 nPortionCount
= ::std::min
< sal_uInt16
>( nCharsLeft
, maRecBuffer
.getRecLeft() / 2 );
395 OSL_ENSURE( (nPortionCount
<= nCharsLeft
) || ((maRecBuffer
.getRecLeft() & 1) == 0),
396 "BiffInputStream::readUniStringChars - missing a byte" );
400 nPortionCount
= getMaxRawReadSize( nCharsLeft
);
403 // read the character array
404 appendUnicodeArray( aBuffer
, nPortionCount
, b16BitChars
, bAllowNulChars
);
406 // prepare for next CONTINUE record
407 nCharsLeft
= nCharsLeft
- nPortionCount
;
409 jumpToNextStringContinue( b16BitChars
);
412 return aBuffer
.makeStringAndClear();
415 OUString
BiffInputStream::readUniStringBody( sal_uInt16 nChars
, bool bAllowNulChars
)
419 readUniStringHeader( b16BitChars
, nAddSize
);
420 OUString aString
= readUniStringChars( nChars
, b16BitChars
, bAllowNulChars
);
425 OUString
BiffInputStream::readUniString( bool bAllowNulChars
)
427 return readUniStringBody( readuInt16(), bAllowNulChars
);
430 void BiffInputStream::skipUniStringChars( sal_uInt16 nChars
, bool b16BitChars
)
432 sal_uInt16 nCharsLeft
= nChars
;
433 while( !mbEof
&& (nCharsLeft
> 0) )
435 sal_uInt16 nPortionCount
;
438 nPortionCount
= ::std::min
< sal_uInt16
>( nCharsLeft
, maRecBuffer
.getRecLeft() / 2 );
439 OSL_ENSURE( (nPortionCount
<= nCharsLeft
) || ((maRecBuffer
.getRecLeft() & 1) == 0),
440 "BiffInputStream::skipUniStringChars - missing a byte" );
441 skip( 2 * nPortionCount
);
445 nPortionCount
= getMaxRawReadSize( nCharsLeft
);
446 skip( nPortionCount
);
449 // prepare for next CONTINUE record
450 nCharsLeft
= nCharsLeft
- nPortionCount
;
452 jumpToNextStringContinue( b16BitChars
);
456 void BiffInputStream::skipUniStringBody( sal_uInt16 nChars
)
460 readUniStringHeader( b16BitChars
, nAddSize
);
461 skipUniStringChars( nChars
, b16BitChars
);
465 void BiffInputStream::skipUniString()
467 skipUniStringBody( readuInt16() );
470 // private --------------------------------------------------------------------
472 void BiffInputStream::readAtom( void* opMem
, sal_uInt8 nSize
)
474 // byte swapping is done in calling BinaryInputStream::readValue() template function
475 if( ensureRawReadSize( nSize
) )
476 maRecBuffer
.read( opMem
, nSize
);
479 void BiffInputStream::setupRecord()
481 // initialize class members
482 mnRecHandle
= maRecBuffer
.getRecHeaderPos();
483 mnRecId
= maRecBuffer
.getRecId();
484 mnAltContId
= BIFF_ID_UNKNOWN
;
485 mnCurrRecSize
= mnComplRecSize
= maRecBuffer
.getRecSize();
486 mbHasComplRec
= !mbCont
;
487 mbEof
= !isInRecord();
488 // enable decoder in new record
489 enableDecoder( true );
492 void BiffInputStream::restartRecord( bool bInvalidateRecSize
)
496 maRecBuffer
.startRecord( getRecHandle() );
497 mnCurrRecSize
= maRecBuffer
.getRecSize();
498 if( bInvalidateRecSize
)
500 mnComplRecSize
= mnCurrRecSize
;
501 mbHasComplRec
= !mbCont
;
507 void BiffInputStream::rewindToRecord( sal_Int64 nRecHandle
)
509 if( nRecHandle
>= 0 )
511 maRecBuffer
.restartAt( nRecHandle
);
513 mbEof
= true; // as long as the record is not started
517 bool BiffInputStream::isContinueId( sal_uInt16 nRecId
) const
519 return (nRecId
== BIFF_ID_CONT
) || (nRecId
== mnAltContId
);
522 bool BiffInputStream::jumpToNextContinue()
524 mbEof
= mbEof
|| !mbCont
|| !isContinueId( maRecBuffer
.getNextRecId() ) || !maRecBuffer
.startNextRecord();
526 mnCurrRecSize
+= maRecBuffer
.getRecSize();
530 bool BiffInputStream::jumpToNextStringContinue( bool& rb16BitChars
)
532 OSL_ENSURE( maRecBuffer
.getRecLeft() == 0, "BiffInputStream::jumpToNextStringContinue - unexpected garbage" );
534 if( mbCont
&& (getRemaining() > 0) )
536 jumpToNextContinue();
538 else if( mnRecId
== BIFF_ID_CONT
)
540 /* CONTINUE handling is off, but we have started reading in a CONTINUE
541 record -> start next CONTINUE for TXO import. We really start a new
542 record here - no chance to return to string origin. */
543 mbEof
= mbEof
|| (maRecBuffer
.getNextRecId() != BIFF_ID_CONT
) || !maRecBuffer
.startNextRecord();
548 // trying to read the flags invalidates stream, if no CONTINUE record has been found
551 rb16BitChars
= getFlag( nFlags
, BIFF_STRF_16BIT
);
555 void BiffInputStream::calcRecordLength()
557 sal_Int64 nCurrPos
= tell(); // save current position in record
558 while( jumpToNextContinue() ) {} // jumpToNextContinue() adds up mnCurrRecSize
559 mnComplRecSize
= mnCurrRecSize
;
560 mbHasComplRec
= true;
561 seek( nCurrPos
); // restore position, seek() resets old mbValid state
564 bool BiffInputStream::ensureRawReadSize( sal_uInt16 nBytes
)
566 if( !mbEof
&& (nBytes
> 0) )
568 while( !mbEof
&& (maRecBuffer
.getRecLeft() == 0) ) jumpToNextContinue();
569 mbEof
= mbEof
|| (nBytes
> maRecBuffer
.getRecLeft());
570 OSL_ENSURE( !mbEof
, "BiffInputStream::ensureRawReadSize - record overread" );
575 sal_uInt16
BiffInputStream::getMaxRawReadSize( sal_Int32 nBytes
) const
577 return getLimitedValue
< sal_uInt16
, sal_Int32
>( nBytes
, 0, maRecBuffer
.getRecLeft() );
580 void BiffInputStream::appendUnicodeArray( OUStringBuffer
& orBuffer
, sal_uInt16 nChars
, bool b16BitChars
, bool bAllowNulChars
)
582 orBuffer
.ensureCapacity( orBuffer
.getLength() + nChars
);
584 for( sal_uInt16 nCharIdx
= 0; !mbEof
&& (nCharIdx
< nChars
); ++nCharIdx
)
586 if( b16BitChars
) readValue( nChar
); else nChar
= readuInt8();
587 orBuffer
.append( static_cast< sal_Unicode
>( (!bAllowNulChars
&& (nChar
== 0)) ? '?' : nChar
) );
591 void BiffInputStream::readUniStringHeader( bool& orb16BitChars
, sal_Int32
& ornAddSize
)
593 sal_uInt8 nFlags
= readuInt8();
594 OSL_ENSURE( !getFlag( nFlags
, BIFF_STRF_UNKNOWN
), "BiffInputStream::readUniStringHeader - unknown flags" );
595 orb16BitChars
= getFlag( nFlags
, BIFF_STRF_16BIT
);
596 sal_uInt16 nFontCount
= getFlag( nFlags
, BIFF_STRF_RICH
) ? readuInt16() : 0;
597 sal_Int32 nPhoneticSize
= getFlag( nFlags
, BIFF_STRF_PHONETIC
) ? readInt32() : 0;
598 ornAddSize
= 4 * nFontCount
+ ::std::max
< sal_Int32
>( 0, nPhoneticSize
);
601 // ============================================================================
603 BiffInputStreamPos::BiffInputStreamPos( BiffInputStream
& rStrm
) :
605 mnRecHandle( rStrm
.getRecHandle() ),
606 mnRecPos( rStrm
.tell() )
610 bool BiffInputStreamPos::restorePosition()
612 bool bValidRec
= mrStrm
.startRecordByHandle( mnRecHandle
);
614 mrStrm
.seek( mnRecPos
);
615 return bValidRec
&& !mrStrm
.isEof();
618 // ============================================================================
620 BiffInputStreamPosGuard::BiffInputStreamPosGuard( BiffInputStream
& rStrm
) :
621 BiffInputStreamPos( rStrm
)
625 BiffInputStreamPosGuard::~BiffInputStreamPosGuard()
630 // ============================================================================