1*cdf0e10cSrcweir /************************************************************************* 2*cdf0e10cSrcweir * 3*cdf0e10cSrcweir * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4*cdf0e10cSrcweir * 5*cdf0e10cSrcweir * Copyright 2000, 2010 Oracle and/or its affiliates. 6*cdf0e10cSrcweir * 7*cdf0e10cSrcweir * OpenOffice.org - a multi-platform office productivity suite 8*cdf0e10cSrcweir * 9*cdf0e10cSrcweir * This file is part of OpenOffice.org. 10*cdf0e10cSrcweir * 11*cdf0e10cSrcweir * OpenOffice.org is free software: you can redistribute it and/or modify 12*cdf0e10cSrcweir * it under the terms of the GNU Lesser General Public License version 3 13*cdf0e10cSrcweir * only, as published by the Free Software Foundation. 14*cdf0e10cSrcweir * 15*cdf0e10cSrcweir * OpenOffice.org is distributed in the hope that it will be useful, 16*cdf0e10cSrcweir * but WITHOUT ANY WARRANTY; without even the implied warranty of 17*cdf0e10cSrcweir * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18*cdf0e10cSrcweir * GNU Lesser General Public License version 3 for more details 19*cdf0e10cSrcweir * (a copy is included in the LICENSE file that accompanied this code). 20*cdf0e10cSrcweir * 21*cdf0e10cSrcweir * You should have received a copy of the GNU Lesser General Public License 22*cdf0e10cSrcweir * version 3 along with OpenOffice.org. If not, see 23*cdf0e10cSrcweir * <http://www.openoffice.org/license.html> 24*cdf0e10cSrcweir * for a copy of the LGPLv3 License. 25*cdf0e10cSrcweir * 26*cdf0e10cSrcweir ************************************************************************/ 27*cdf0e10cSrcweir 28*cdf0e10cSrcweir #include "oox/xls/biffoutputstream.hxx" 29*cdf0e10cSrcweir 30*cdf0e10cSrcweir namespace oox { 31*cdf0e10cSrcweir namespace xls { 32*cdf0e10cSrcweir 33*cdf0e10cSrcweir // ============================================================================ 34*cdf0e10cSrcweir 35*cdf0e10cSrcweir namespace prv { 36*cdf0e10cSrcweir 37*cdf0e10cSrcweir BiffOutputRecordBuffer::BiffOutputRecordBuffer( BinaryOutputStream& rOutStrm, sal_uInt16 nMaxRecSize ) : 38*cdf0e10cSrcweir mrOutStrm( rOutStrm ), 39*cdf0e10cSrcweir mnMaxRecSize( nMaxRecSize ), 40*cdf0e10cSrcweir mnRecId( BIFF_ID_UNKNOWN ), 41*cdf0e10cSrcweir mbInRec( false ) 42*cdf0e10cSrcweir { 43*cdf0e10cSrcweir OSL_ENSURE( mrOutStrm.isSeekable(), "BiffOutputRecordBuffer::BiffOutputRecordBuffer - stream must be seekable" ); 44*cdf0e10cSrcweir maData.reserve( SAL_MAX_UINT16 ); 45*cdf0e10cSrcweir } 46*cdf0e10cSrcweir 47*cdf0e10cSrcweir void BiffOutputRecordBuffer::startRecord( sal_uInt16 nRecId ) 48*cdf0e10cSrcweir { 49*cdf0e10cSrcweir OSL_ENSURE( !mbInRec, "BiffOutputRecordBuffer::startRecord - another record still open" ); 50*cdf0e10cSrcweir mnRecId = nRecId; 51*cdf0e10cSrcweir maData.clear(); 52*cdf0e10cSrcweir mbInRec = true; 53*cdf0e10cSrcweir } 54*cdf0e10cSrcweir 55*cdf0e10cSrcweir void BiffOutputRecordBuffer::endRecord() 56*cdf0e10cSrcweir { 57*cdf0e10cSrcweir OSL_ENSURE( mbInRec, "BiffOutputRecordBuffer::endRecord - no record open" ); 58*cdf0e10cSrcweir sal_uInt16 nRecSize = getLimitedValue< sal_uInt16, size_t >( maData.size(), 0, SAL_MAX_UINT16 ); 59*cdf0e10cSrcweir mrOutStrm.seekToEnd(); 60*cdf0e10cSrcweir mrOutStrm << mnRecId << nRecSize; 61*cdf0e10cSrcweir if( nRecSize > 0 ) 62*cdf0e10cSrcweir mrOutStrm.writeMemory( &maData.front(), nRecSize ); 63*cdf0e10cSrcweir mbInRec = false; 64*cdf0e10cSrcweir } 65*cdf0e10cSrcweir 66*cdf0e10cSrcweir void BiffOutputRecordBuffer::write( const void* pData, sal_uInt16 nBytes ) 67*cdf0e10cSrcweir { 68*cdf0e10cSrcweir OSL_ENSURE( mbInRec, "BiffOutputRecordBuffer::write - no record open" ); 69*cdf0e10cSrcweir OSL_ENSURE( nBytes > 0, "BiffOutputRecordBuffer::write - nothing to write" ); 70*cdf0e10cSrcweir OSL_ENSURE( nBytes <= getRecLeft(), "BiffOutputRecordBuffer::write - buffer overflow" ); 71*cdf0e10cSrcweir maData.resize( maData.size() + nBytes ); 72*cdf0e10cSrcweir memcpy( &*(maData.end() - nBytes), pData, nBytes ); 73*cdf0e10cSrcweir } 74*cdf0e10cSrcweir 75*cdf0e10cSrcweir void BiffOutputRecordBuffer::fill( sal_uInt8 nValue, sal_uInt16 nBytes ) 76*cdf0e10cSrcweir { 77*cdf0e10cSrcweir OSL_ENSURE( mbInRec, "BiffOutputRecordBuffer::write - no record open" ); 78*cdf0e10cSrcweir OSL_ENSURE( nBytes > 0, "BiffOutputRecordBuffer::write - nothing to write" ); 79*cdf0e10cSrcweir OSL_ENSURE( nBytes <= getRecLeft(), "BiffOutputRecordBuffer::write - buffer overflow" ); 80*cdf0e10cSrcweir maData.resize( maData.size() + nBytes, nValue ); 81*cdf0e10cSrcweir } 82*cdf0e10cSrcweir 83*cdf0e10cSrcweir } // namespace prv 84*cdf0e10cSrcweir 85*cdf0e10cSrcweir // ============================================================================ 86*cdf0e10cSrcweir 87*cdf0e10cSrcweir BiffOutputStream::BiffOutputStream( BinaryOutputStream& rOutStream, sal_uInt16 nMaxRecSize ) : 88*cdf0e10cSrcweir BinaryStreamBase( true ), 89*cdf0e10cSrcweir maRecBuffer( rOutStream, nMaxRecSize ), 90*cdf0e10cSrcweir mnPortionSize( 0 ), 91*cdf0e10cSrcweir mnPortionPos( 0 ) 92*cdf0e10cSrcweir { 93*cdf0e10cSrcweir } 94*cdf0e10cSrcweir 95*cdf0e10cSrcweir // record control ------------------------------------------------------------- 96*cdf0e10cSrcweir 97*cdf0e10cSrcweir void BiffOutputStream::startRecord( sal_uInt16 nRecId ) 98*cdf0e10cSrcweir { 99*cdf0e10cSrcweir maRecBuffer.startRecord( nRecId ); 100*cdf0e10cSrcweir setPortionSize( 1 ); 101*cdf0e10cSrcweir } 102*cdf0e10cSrcweir 103*cdf0e10cSrcweir void BiffOutputStream::endRecord() 104*cdf0e10cSrcweir { 105*cdf0e10cSrcweir setPortionSize( 1 ); 106*cdf0e10cSrcweir maRecBuffer.endRecord(); 107*cdf0e10cSrcweir } 108*cdf0e10cSrcweir 109*cdf0e10cSrcweir void BiffOutputStream::setPortionSize( sal_uInt8 nSize ) 110*cdf0e10cSrcweir { 111*cdf0e10cSrcweir OSL_ENSURE( mnPortionPos == 0, "BiffOutputStream::setPortionSize - block operation inside portion" ); 112*cdf0e10cSrcweir mnPortionSize = ::std::max< sal_uInt8 >( nSize, 1 ); 113*cdf0e10cSrcweir mnPortionPos = 0; 114*cdf0e10cSrcweir } 115*cdf0e10cSrcweir 116*cdf0e10cSrcweir // BinaryStreamBase interface (seeking) --------------------------------------- 117*cdf0e10cSrcweir 118*cdf0e10cSrcweir sal_Int64 BiffOutputStream::tellBase() const 119*cdf0e10cSrcweir { 120*cdf0e10cSrcweir return maRecBuffer.getBaseStream().tell(); 121*cdf0e10cSrcweir } 122*cdf0e10cSrcweir 123*cdf0e10cSrcweir sal_Int64 BiffOutputStream::sizeBase() const 124*cdf0e10cSrcweir { 125*cdf0e10cSrcweir return maRecBuffer.getBaseStream().size(); 126*cdf0e10cSrcweir } 127*cdf0e10cSrcweir 128*cdf0e10cSrcweir // BinaryOutputStream interface (stream write access) ------------------------- 129*cdf0e10cSrcweir 130*cdf0e10cSrcweir void BiffOutputStream::writeData( const StreamDataSequence& rData, size_t nAtomSize ) 131*cdf0e10cSrcweir { 132*cdf0e10cSrcweir if( rData.hasElements() ) 133*cdf0e10cSrcweir writeMemory( rData.getConstArray(), rData.getLength(), nAtomSize ); 134*cdf0e10cSrcweir } 135*cdf0e10cSrcweir 136*cdf0e10cSrcweir void BiffOutputStream::writeMemory( const void* pMem, sal_Int32 nBytes, size_t nAtomSize ) 137*cdf0e10cSrcweir { 138*cdf0e10cSrcweir if( pMem && (nBytes > 0) ) 139*cdf0e10cSrcweir { 140*cdf0e10cSrcweir const sal_uInt8* pnBuffer = reinterpret_cast< const sal_uInt8* >( pMem ); 141*cdf0e10cSrcweir sal_Int32 nBytesLeft = nBytes; 142*cdf0e10cSrcweir while( nBytesLeft > 0 ) 143*cdf0e10cSrcweir { 144*cdf0e10cSrcweir sal_uInt16 nBlockSize = prepareWriteBlock( nBytesLeft, nAtomSize ); 145*cdf0e10cSrcweir maRecBuffer.write( pnBuffer, nBlockSize ); 146*cdf0e10cSrcweir pnBuffer += nBlockSize; 147*cdf0e10cSrcweir nBytesLeft -= nBlockSize; 148*cdf0e10cSrcweir } 149*cdf0e10cSrcweir } 150*cdf0e10cSrcweir } 151*cdf0e10cSrcweir 152*cdf0e10cSrcweir void BiffOutputStream::fill( sal_uInt8 nValue, sal_Int32 nBytes, size_t nAtomSize ) 153*cdf0e10cSrcweir { 154*cdf0e10cSrcweir sal_Int32 nBytesLeft = nBytes; 155*cdf0e10cSrcweir while( nBytesLeft > 0 ) 156*cdf0e10cSrcweir { 157*cdf0e10cSrcweir sal_uInt16 nBlockSize = prepareWriteBlock( nBytesLeft, nAtomSize ); 158*cdf0e10cSrcweir maRecBuffer.fill( nValue, nBlockSize ); 159*cdf0e10cSrcweir nBytesLeft -= nBlockSize; 160*cdf0e10cSrcweir } 161*cdf0e10cSrcweir } 162*cdf0e10cSrcweir 163*cdf0e10cSrcweir // private -------------------------------------------------------------------- 164*cdf0e10cSrcweir 165*cdf0e10cSrcweir sal_uInt16 BiffOutputStream::prepareWriteBlock( sal_Int32 nTotalSize, size_t nAtomSize ) 166*cdf0e10cSrcweir { 167*cdf0e10cSrcweir sal_uInt16 nRecLeft = maRecBuffer.getRecLeft(); 168*cdf0e10cSrcweir if( mnPortionSize <= 1 ) 169*cdf0e10cSrcweir { 170*cdf0e10cSrcweir // no portions: restrict remaining record size to entire atoms 171*cdf0e10cSrcweir nRecLeft = static_cast< sal_uInt16 >( (nRecLeft / nAtomSize) * nAtomSize ); 172*cdf0e10cSrcweir } 173*cdf0e10cSrcweir else 174*cdf0e10cSrcweir { 175*cdf0e10cSrcweir sal_Int32 nPortionLeft = mnPortionSize - mnPortionPos; 176*cdf0e10cSrcweir if( nTotalSize <= nPortionLeft ) 177*cdf0e10cSrcweir { 178*cdf0e10cSrcweir // block fits into the current portion 179*cdf0e10cSrcweir OSL_ENSURE( nPortionLeft <= nRecLeft, "BiffOutputStream::prepareWriteBlock - portion exceeds record" ); 180*cdf0e10cSrcweir mnPortionPos = static_cast< sal_uInt8 >( (mnPortionPos + nTotalSize) % mnPortionSize ); 181*cdf0e10cSrcweir } 182*cdf0e10cSrcweir else 183*cdf0e10cSrcweir { 184*cdf0e10cSrcweir // restrict remaining record size to entire portions 185*cdf0e10cSrcweir OSL_ENSURE( mnPortionPos == 0, "BiffOutputStream::prepareWriteBlock - writing over multiple portions starts inside portion" ); 186*cdf0e10cSrcweir mnPortionPos = 0; 187*cdf0e10cSrcweir // check that atom size matches portion size 188*cdf0e10cSrcweir OSL_ENSURE( mnPortionSize % nAtomSize == 0, "BiffOutputStream::prepareWriteBlock - atom size does not match portion size" ); 189*cdf0e10cSrcweir sal_uInt8 nPortionSize = static_cast< sal_uInt8 >( (mnPortionSize / nAtomSize) * nAtomSize ); 190*cdf0e10cSrcweir // restrict remaining record size to entire portions 191*cdf0e10cSrcweir nRecLeft = (nRecLeft / nPortionSize) * nPortionSize; 192*cdf0e10cSrcweir } 193*cdf0e10cSrcweir } 194*cdf0e10cSrcweir 195*cdf0e10cSrcweir // current record has space for some data: return size of available space 196*cdf0e10cSrcweir if( nRecLeft > 0 ) 197*cdf0e10cSrcweir return getLimitedValue< sal_uInt16, sal_Int32 >( nTotalSize, 0, nRecLeft ); 198*cdf0e10cSrcweir 199*cdf0e10cSrcweir // finish current record and start a new CONTINUE record 200*cdf0e10cSrcweir maRecBuffer.endRecord(); 201*cdf0e10cSrcweir maRecBuffer.startRecord( BIFF_ID_CONT ); 202*cdf0e10cSrcweir mnPortionPos = 0; 203*cdf0e10cSrcweir return prepareWriteBlock( nTotalSize, nAtomSize ); 204*cdf0e10cSrcweir } 205*cdf0e10cSrcweir 206*cdf0e10cSrcweir // ============================================================================ 207*cdf0e10cSrcweir 208*cdf0e10cSrcweir } // namespace xls 209*cdf0e10cSrcweir } // namespace oox 210