Branch data 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 "oox/helper/binaryinputstream.hxx"
21 : :
22 : : #include <com/sun/star/io/XInputStream.hpp>
23 : : #include <com/sun/star/io/XSeekable.hpp>
24 : : #include <string.h>
25 : : #include <vector>
26 : : #include <rtl/strbuf.hxx>
27 : : #include <rtl/ustrbuf.hxx>
28 : : #include "oox/helper/binaryoutputstream.hxx"
29 : :
30 : : namespace oox {
31 : :
32 : : // ============================================================================
33 : :
34 : : using namespace ::com::sun::star::io;
35 : : using namespace ::com::sun::star::uno;
36 : :
37 : : using ::rtl::OString;
38 : : using ::rtl::OStringBuffer;
39 : : using ::rtl::OStringToOUString;
40 : : using ::rtl::OUString;
41 : : using ::rtl::OUStringBuffer;
42 : :
43 : : namespace {
44 : :
45 : : const sal_Int32 INPUTSTREAM_BUFFERSIZE = 0x8000;
46 : :
47 : : } // namespace
48 : :
49 : : // ============================================================================
50 : :
51 : 5 : OUString BinaryInputStream::readNulUnicodeArray()
52 : : {
53 : 5 : OUStringBuffer aBuffer;
54 [ + - ][ + - ]: 55 : for( sal_uInt16 nChar = readuInt16(); !mbEof && (nChar > 0); readValue( nChar ) )
[ + + ][ + + ]
[ + - ]
55 [ + - ]: 50 : aBuffer.append( static_cast< sal_Unicode >( nChar ) );
56 [ + - ]: 5 : return aBuffer.makeStringAndClear();
57 : : }
58 : :
59 : 343 : OString BinaryInputStream::readCharArray( sal_Int32 nChars, bool bAllowNulChars )
60 : : {
61 [ + + ]: 343 : if( nChars <= 0 )
62 : 105 : return OString();
63 : :
64 [ + - ]: 238 : ::std::vector< sal_uInt8 > aBuffer;
65 [ + - ]: 238 : sal_Int32 nCharsRead = readArray( aBuffer, nChars );
66 [ - + ]: 238 : if( nCharsRead <= 0 )
67 : 0 : return OString();
68 : :
69 [ + - ]: 238 : aBuffer.resize( static_cast< size_t >( nCharsRead ) );
70 [ + - ]: 238 : if( !bAllowNulChars )
71 [ + - ]: 238 : ::std::replace( aBuffer.begin(), aBuffer.end(), '\0', '?' );
72 : :
73 [ + - ]: 343 : return OString( reinterpret_cast< sal_Char* >( &aBuffer.front() ), nCharsRead );
74 : : }
75 : :
76 : 343 : OUString BinaryInputStream::readCharArrayUC( sal_Int32 nChars, rtl_TextEncoding eTextEnc, bool bAllowNulChars )
77 : : {
78 [ + - ]: 343 : return OStringToOUString( readCharArray( nChars, bAllowNulChars ), eTextEnc );
79 : : }
80 : :
81 : 0 : OUString BinaryInputStream::readUnicodeArray( sal_Int32 nChars, bool bAllowNulChars )
82 : : {
83 [ # # ]: 0 : if( nChars <= 0 )
84 : 0 : return OUString();
85 : :
86 [ # # ]: 0 : ::std::vector< sal_uInt16 > aBuffer;
87 [ # # ]: 0 : sal_Int32 nCharsRead = readArray( aBuffer, nChars );
88 [ # # ]: 0 : if( nCharsRead <= 0 )
89 : 0 : return OUString();
90 : :
91 [ # # ]: 0 : aBuffer.resize( static_cast< size_t >( nCharsRead ) );
92 [ # # ]: 0 : if( !bAllowNulChars )
93 [ # # ][ # # ]: 0 : ::std::replace( aBuffer.begin(), aBuffer.begin() + nCharsRead, '\0', '?' );
94 : :
95 : 0 : OUStringBuffer aStringBuffer;
96 [ # # ]: 0 : aStringBuffer.ensureCapacity( nCharsRead );
97 [ # # ][ # # ]: 0 : for( ::std::vector< sal_uInt16 >::iterator aIt = aBuffer.begin(), aEnd = aBuffer.end(); aIt != aEnd; ++aIt )
[ # # ]
98 [ # # ][ # # ]: 0 : aStringBuffer.append( static_cast< sal_Unicode >( *aIt ) );
99 [ # # ]: 0 : return aStringBuffer.makeStringAndClear();
100 : : }
101 : :
102 : 39 : OUString BinaryInputStream::readCompressedUnicodeArray( sal_Int32 nChars, bool bCompressed, bool bAllowNulChars )
103 : : {
104 : : return bCompressed ?
105 : : // ISO-8859-1 maps all byte values 0xHH to the same Unicode code point U+00HH
106 : : readCharArrayUC( nChars, RTL_TEXTENCODING_ISO_8859_1, bAllowNulChars ) :
107 [ + - ]: 39 : readUnicodeArray( nChars, bAllowNulChars );
108 : : }
109 : :
110 : 574 : void BinaryInputStream::copyToStream( BinaryOutputStream& rOutStrm, sal_Int64 nBytes, sal_Int32 nAtomSize )
111 : : {
112 [ + - ]: 574 : if( nBytes > 0 )
113 : : {
114 : : // make buffer size a multiple of the passed atom size
115 [ + - ]: 574 : sal_Int32 nBufferSize = getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, (INPUTSTREAM_BUFFERSIZE / nAtomSize) * nAtomSize );
116 [ + - ]: 574 : StreamDataSequence aBuffer( nBufferSize );
117 [ + + ]: 1148 : while( nBytes > 0 )
118 : : {
119 [ + - ]: 574 : sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, nBufferSize );
120 [ + - ]: 574 : sal_Int32 nBytesRead = readData( aBuffer, nReadSize, nAtomSize );
121 [ + - ]: 574 : rOutStrm.writeData( aBuffer );
122 [ - + ]: 574 : if( nReadSize == nBytesRead )
123 : 0 : nBytes -= nReadSize;
124 : : else
125 : 574 : nBytes = 0;
126 [ + - ]: 574 : }
127 : : }
128 : 574 : }
129 : :
130 : : // ============================================================================
131 : :
132 : 739 : BinaryXInputStream::BinaryXInputStream( const Reference< XInputStream >& rxInStrm, bool bAutoClose ) :
133 : 1478 : BinaryStreamBase( Reference< XSeekable >( rxInStrm, UNO_QUERY ).is() ),
134 : : BinaryXSeekableStream( Reference< XSeekable >( rxInStrm, UNO_QUERY ) ),
135 : : maBuffer( INPUTSTREAM_BUFFERSIZE ),
136 : : mxInStrm( rxInStrm ),
137 [ + - ][ + - ]: 1478 : mbAutoClose( bAutoClose && rxInStrm.is() )
[ + - ][ + + ]
[ + - ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ + - ]
138 : : {
139 : 739 : mbEof = !mxInStrm.is();
140 : 739 : }
141 : :
142 [ + - ][ + - ]: 1478 : BinaryXInputStream::~BinaryXInputStream()
[ + - ][ # # ]
[ # # ][ # # ]
143 : : {
144 [ + - ][ # # ]: 739 : close();
145 [ + - ][ - + ]: 1478 : }
[ # # ][ # # ]
[ # # ][ # # ]
146 : :
147 : 739 : void BinaryXInputStream::close()
148 : : {
149 : : OSL_ENSURE( !mbAutoClose || mxInStrm.is(), "BinaryXInputStream::close - invalid call" );
150 [ + + ]: 739 : if( mxInStrm.is() ) try
151 : : {
152 [ + - ][ + - ]: 484 : mxInStrm->closeInput();
153 : : }
154 : 0 : catch( Exception& )
155 : : {
156 : : OSL_FAIL( "BinaryXInputStream::close - closing input stream failed" );
157 : : }
158 : 739 : mxInStrm.clear();
159 : 739 : mbAutoClose = false;
160 : 739 : BinaryXSeekableStream::close();
161 [ # # ]: 739 : }
162 : :
163 : 50988 : sal_Int32 BinaryXInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t /*nAtomSize*/ )
164 : : {
165 : 50988 : sal_Int32 nRet = 0;
166 [ + + ][ + - ]: 50988 : if( !mbEof && (nBytes > 0) ) try
167 : : {
168 [ + - ][ + - ]: 50733 : nRet = mxInStrm->readBytes( orData, nBytes );
169 : 50733 : mbEof = nRet != nBytes;
170 : : }
171 : 0 : catch( Exception& )
172 : : {
173 : 0 : mbEof = true;
174 : : }
175 [ # # ]: 50988 : return nRet;
176 : : }
177 : :
178 : 50376 : sal_Int32 BinaryXInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize )
179 : : {
180 : 50376 : sal_Int32 nRet = 0;
181 [ + - ][ + - ]: 50376 : if( !mbEof && (nBytes > 0) )
182 : : {
183 : 50376 : sal_Int32 nBufferSize = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, INPUTSTREAM_BUFFERSIZE );
184 : 50376 : sal_uInt8* opnMem = reinterpret_cast< sal_uInt8* >( opMem );
185 [ + + ][ + + ]: 100752 : while( !mbEof && (nBytes > 0) )
[ + + ]
186 : : {
187 : 50376 : sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, nBufferSize );
188 : 50376 : sal_Int32 nBytesRead = readData( maBuffer, nReadSize, nAtomSize );
189 [ + + ]: 50376 : if( nBytesRead > 0 )
190 : 50281 : memcpy( opnMem, maBuffer.getConstArray(), static_cast< size_t >( nBytesRead ) );
191 : 50376 : opnMem += nBytesRead;
192 : 50376 : nBytes -= nBytesRead;
193 : 50376 : nRet += nBytesRead;
194 : : }
195 : : }
196 : 50376 : return nRet;
197 : : }
198 : :
199 : 466 : void BinaryXInputStream::skip( sal_Int32 nBytes, size_t /*nAtomSize*/ )
200 : : {
201 [ + - ]: 466 : if( !mbEof ) try
202 : : {
203 [ + - ][ + - ]: 466 : mxInStrm->skipBytes( nBytes );
204 : : }
205 : 0 : catch( Exception& )
206 : : {
207 : 0 : mbEof = true;
208 : : }
209 [ # # ]: 466 : }
210 : :
211 : : // ============================================================================
212 : :
213 : 1397 : SequenceInputStream::SequenceInputStream( const StreamDataSequence& rData ) :
214 : : BinaryStreamBase( true ),
215 [ + - ][ + - ]: 1397 : SequenceSeekableStream( rData )
[ # # ][ # # ]
216 : : {
217 : 1397 : }
218 : :
219 : 0 : sal_Int32 SequenceInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t /*nAtomSize*/ )
220 : : {
221 : 0 : sal_Int32 nReadBytes = 0;
222 [ # # ]: 0 : if( !mbEof )
223 : : {
224 : 0 : nReadBytes = getMaxBytes( nBytes );
225 : 0 : orData.realloc( nReadBytes );
226 [ # # ]: 0 : if( nReadBytes > 0 )
227 : 0 : memcpy( orData.getArray(), mpData->getConstArray() + mnPos, static_cast< size_t >( nReadBytes ) );
228 : 0 : mnPos += nReadBytes;
229 : 0 : mbEof = nReadBytes < nBytes;
230 : : }
231 : 0 : return nReadBytes;
232 : : }
233 : :
234 : 342 : sal_Int32 SequenceInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t /*nAtomSize*/ )
235 : : {
236 : 342 : sal_Int32 nReadBytes = 0;
237 [ + - ]: 342 : if( !mbEof )
238 : : {
239 : 342 : nReadBytes = getMaxBytes( nBytes );
240 [ + - ]: 342 : if( nReadBytes > 0 )
241 : 342 : memcpy( opMem, mpData->getConstArray() + mnPos, static_cast< size_t >( nReadBytes ) );
242 : 342 : mnPos += nReadBytes;
243 : 342 : mbEof = nReadBytes < nBytes;
244 : : }
245 : 342 : return nReadBytes;
246 : : }
247 : :
248 : 0 : void SequenceInputStream::skip( sal_Int32 nBytes, size_t /*nAtomSize*/ )
249 : : {
250 [ # # ]: 0 : if( !mbEof )
251 : : {
252 : 0 : sal_Int32 nSkipBytes = getMaxBytes( nBytes );
253 : 0 : mnPos += nSkipBytes;
254 : 0 : mbEof = nSkipBytes < nBytes;
255 : : }
256 : 0 : }
257 : :
258 : : // ============================================================================
259 : :
260 : 0 : RelativeInputStream::RelativeInputStream( BinaryInputStream& rInStrm, sal_Int64 nSize ) :
261 : 0 : BinaryStreamBase( rInStrm.isSeekable() ),
262 : : mpInStrm( &rInStrm ),
263 [ # # ][ # # ]: 0 : mnStartPos( rInStrm.tell() ),
264 [ # # ][ # # ]: 0 : mnRelPos( 0 )
265 : : {
266 [ # # ][ # # ]: 0 : sal_Int64 nRemaining = rInStrm.getRemaining();
267 [ # # ][ # # ]: 0 : mnSize = (nRemaining >= 0) ? ::std::min( nSize, nRemaining ) : nSize;
[ # # ][ # # ]
268 [ # # ][ # # ]: 0 : mbEof = mbEof || rInStrm.isEof() || (mnSize < 0);
[ # # ][ # # ]
[ # # ][ # # ]
269 : 0 : }
270 : :
271 : 0 : sal_Int64 RelativeInputStream::size() const
272 : : {
273 [ # # ]: 0 : return mpInStrm ? mnSize : -1;
274 : : }
275 : :
276 : 0 : sal_Int64 RelativeInputStream::tell() const
277 : : {
278 [ # # ]: 0 : return mpInStrm ? mnRelPos : -1;
279 : : }
280 : :
281 : 0 : void RelativeInputStream::seek( sal_Int64 nPos )
282 : : {
283 [ # # ][ # # ]: 0 : if( mpInStrm && isSeekable() && (mnStartPos >= 0) )
[ # # ][ # # ]
284 : : {
285 : 0 : mnRelPos = getLimitedValue< sal_Int64, sal_Int64 >( nPos, 0, mnSize );
286 : 0 : mpInStrm->seek( mnStartPos + mnRelPos );
287 [ # # ][ # # ]: 0 : mbEof = (mnRelPos != nPos) || mpInStrm->isEof();
288 : : }
289 : 0 : }
290 : :
291 : 0 : void RelativeInputStream::close()
292 : : {
293 : 0 : mpInStrm = 0;
294 : 0 : mbEof = true;
295 : 0 : }
296 : :
297 : 0 : sal_Int32 RelativeInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize )
298 : : {
299 : 0 : sal_Int32 nReadBytes = 0;
300 [ # # ]: 0 : if( !mbEof )
301 : : {
302 : 0 : sal_Int32 nMaxBytes = getMaxBytes( nBytes );
303 : 0 : nReadBytes = mpInStrm->readData( orData, nMaxBytes, nAtomSize );
304 : 0 : mnRelPos += nReadBytes;
305 [ # # ][ # # ]: 0 : mbEof = (nMaxBytes < nBytes) || mpInStrm->isEof();
306 : : }
307 : 0 : return nReadBytes;
308 : : }
309 : :
310 : 0 : sal_Int32 RelativeInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize )
311 : : {
312 : 0 : sal_Int32 nReadBytes = 0;
313 [ # # ]: 0 : if( !mbEof )
314 : : {
315 : 0 : sal_Int32 nMaxBytes = getMaxBytes( nBytes );
316 : 0 : nReadBytes = mpInStrm->readMemory( opMem, nMaxBytes, nAtomSize );
317 : 0 : mnRelPos += nReadBytes;
318 [ # # ][ # # ]: 0 : mbEof = (nMaxBytes < nBytes) || mpInStrm->isEof();
319 : : }
320 : 0 : return nReadBytes;
321 : : }
322 : :
323 : 0 : void RelativeInputStream::skip( sal_Int32 nBytes, size_t nAtomSize )
324 : : {
325 [ # # ]: 0 : if( !mbEof )
326 : : {
327 : 0 : sal_Int32 nSkipBytes = getMaxBytes( nBytes );
328 : 0 : mpInStrm->skip( nSkipBytes, nAtomSize );
329 : 0 : mnRelPos += nSkipBytes;
330 : 0 : mbEof = nSkipBytes < nBytes;
331 : : }
332 : 0 : }
333 : :
334 : : // ============================================================================
335 : :
336 : : } // namespace oox
337 : :
338 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|