merge the formfield patch from ooo-build
[ooovba.git] / oox / source / ole / vbainputstream.cxx
blob6dc8aad88f4f2fb0d1158912f9adf7ec7dcee3fe
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: vbainputstream.cxx,v $
10 * $Revision: 1.1.2.1 $
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/ole/vbainputstream.hxx"
32 #include <osl/diagnose.h>
34 namespace oox {
35 namespace ole {
37 namespace {
39 const sal_uInt8 VBASTREAM_SIGNATURE = 1;
41 const sal_uInt16 VBACHUNK_SIGMASK = 0x7000;
42 const sal_uInt16 VBACHUNK_SIG = 0x3000;
43 const sal_uInt16 VBACHUNK_COMPRESSED = 0x8000;
44 const sal_uInt16 VBACHUNK_LENMASK = 0x0FFF;
46 } // namespace
48 // ============================================================================
50 VbaInputStream::VbaInputStream( BinaryInputStream& rInStrm ) :
51 mrInStrm( rInStrm ),
52 mnChunkPos( 0 )
54 maChunk.reserve( 4096 );
56 sal_uInt8 nSig = mrInStrm.readuInt8();
57 OSL_ENSURE( nSig == VBASTREAM_SIGNATURE, "VbaInputStream::VbaInputStream - wrong signature" );
58 mbEof = nSig != VBASTREAM_SIGNATURE;
61 sal_Int32 VbaInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes )
63 sal_Int32 nRet = 0;
64 if( !mbEof )
66 orData.realloc( ::std::max< sal_Int32 >( nBytes, 0 ) );
67 if( nBytes > 0 )
69 nRet = readMemory( orData.getArray(), nBytes );
70 if( nRet < nBytes )
71 orData.realloc( nRet );
74 return nRet;
77 sal_Int32 VbaInputStream::readMemory( void* opMem, sal_Int32 nBytes )
79 sal_Int32 nRet = 0;
80 sal_uInt8* opnMem = reinterpret_cast< sal_uInt8* >( opMem );
81 while( (nBytes > 0) && updateChunk() )
83 sal_Int32 nChunkLeft = static_cast< sal_Int32 >( maChunk.size() - mnChunkPos );
84 sal_Int32 nReadBytes = ::std::min( nBytes, nChunkLeft );
85 memcpy( opnMem, &*(maChunk.begin() + mnChunkPos), nReadBytes );
86 opnMem += nReadBytes;
87 mnChunkPos += static_cast< size_t >( nReadBytes );
88 nBytes -= nReadBytes;
89 nRet += nReadBytes;
91 return nRet;
94 void VbaInputStream::skip( sal_Int32 nBytes )
96 while( (nBytes > 0) && updateChunk() )
98 sal_Int32 nChunkLeft = static_cast< sal_Int32 >( maChunk.size() - mnChunkPos );
99 sal_Int32 nSkipBytes = ::std::min( nBytes, nChunkLeft );
100 mnChunkPos += static_cast< size_t >( nSkipBytes );
101 nBytes -= nSkipBytes;
105 // private --------------------------------------------------------------------
107 bool VbaInputStream::updateChunk()
109 if( mbEof || (mnChunkPos < maChunk.size()) ) return !mbEof;
111 // try to read next chunk header, this may trigger EOF
112 sal_uInt16 nHeader = mrInStrm.readuInt16();
113 mbEof = mrInStrm.isEof();
114 if( mbEof ) return false;
116 // check header signature
117 OSL_ENSURE( (nHeader & VBACHUNK_SIGMASK) == VBACHUNK_SIG, "VbaInputStream::updateChunk - invalid chunk signature" );
118 mbEof = (nHeader & VBACHUNK_SIGMASK) != VBACHUNK_SIG;
119 if( mbEof ) return false;
121 // decode length of chunk data and compression flag
122 bool bCompressed = getFlag( nHeader, VBACHUNK_COMPRESSED );
123 sal_uInt16 nChunkLen = (nHeader & VBACHUNK_LENMASK) + 1;
124 OSL_ENSURE( bCompressed || (nChunkLen == 4096), "VbaInputStream::updateChunk - invalid uncompressed chunk size" );
125 if( bCompressed )
127 maChunk.clear();
128 sal_uInt8 nBitCount = 4;
129 sal_uInt16 nChunkPos = 0;
130 while( !mbEof && !mrInStrm.isEof() && (nChunkPos < nChunkLen) )
132 sal_uInt8 nTokenFlags = mrInStrm.readuInt8();
133 ++nChunkPos;
134 for( int nBit = 0; !mbEof && !mrInStrm.isEof() && (nBit < 8) && (nChunkPos < nChunkLen); ++nBit, nTokenFlags >>= 1 )
136 if( nTokenFlags & 1 )
138 sal_uInt16 nCopyToken = mrInStrm.readuInt16();
139 nChunkPos = nChunkPos + 2;
140 // update bit count used for offset/length in the token
141 while( static_cast< size_t >( 1 << nBitCount ) < maChunk.size() ) ++nBitCount;
142 // extract length from lower (16-nBitCount) bits, plus 3
143 sal_uInt16 nLength = extractValue< sal_uInt16 >( nCopyToken, 0, 16 - nBitCount ) + 3;
144 // extract offset from high nBitCount bits, plus 1
145 sal_uInt16 nOffset = extractValue< sal_uInt16 >( nCopyToken, 16 - nBitCount, nBitCount ) + 1;
146 mbEof = (nOffset > maChunk.size()) || (maChunk.size() + nLength > 4096);
147 OSL_ENSURE( !mbEof, "VbaInputStream::updateChunk - invalid offset or size in copy token" );
148 if( !mbEof )
150 // append data to buffer
151 maChunk.resize( maChunk.size() + nLength );
152 sal_uInt8* pnTo = &*(maChunk.end() - nLength);
153 const sal_uInt8* pnEnd = pnTo + nLength;
154 const sal_uInt8* pnFrom = pnTo - nOffset;
155 // offset may be less than length, effectively duplicating source data several times
156 size_t nRunLen = ::std::min< size_t >( nLength, nOffset );
157 while( pnTo < pnEnd )
159 size_t nStepLen = ::std::min< size_t >( nRunLen, pnEnd - pnTo );
160 memcpy( pnTo, pnFrom, nStepLen );
161 pnTo += nStepLen;
165 else
167 maChunk.resize( maChunk.size() + 1 );
168 mrInStrm >> maChunk.back();
169 ++nChunkPos;
174 else
176 maChunk.resize( nChunkLen );
177 mrInStrm.readMemory( &maChunk.front(), nChunkLen );
180 mnChunkPos = 0;
181 return !mbEof;
184 // ============================================================================
186 } // namespace ole
187 } // namespace oox