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 2 : OUString BinaryInputStream::readNulUnicodeArray()
52 : {
53 2 : OUStringBuffer aBuffer;
54 22 : for( sal_uInt16 nChar = readuInt16(); !mbEof && (nChar > 0); readValue( nChar ) )
55 20 : aBuffer.append( static_cast< sal_Unicode >( nChar ) );
56 2 : return aBuffer.makeStringAndClear();
57 : }
58 :
59 178 : OString BinaryInputStream::readCharArray( sal_Int32 nChars, bool bAllowNulChars )
60 : {
61 178 : if( nChars <= 0 )
62 54 : return OString();
63 :
64 124 : ::std::vector< sal_uInt8 > aBuffer;
65 124 : sal_Int32 nCharsRead = readArray( aBuffer, nChars );
66 124 : if( nCharsRead <= 0 )
67 0 : return OString();
68 :
69 124 : aBuffer.resize( static_cast< size_t >( nCharsRead ) );
70 124 : if( !bAllowNulChars )
71 124 : ::std::replace( aBuffer.begin(), aBuffer.end(), '\0', '?' );
72 :
73 124 : return OString( reinterpret_cast< sal_Char* >( &aBuffer.front() ), nCharsRead );
74 : }
75 :
76 178 : OUString BinaryInputStream::readCharArrayUC( sal_Int32 nChars, rtl_TextEncoding eTextEnc, bool bAllowNulChars )
77 : {
78 178 : 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 18 : 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 18 : readUnicodeArray( nChars, bAllowNulChars );
108 : }
109 :
110 340 : void BinaryInputStream::copyToStream( BinaryOutputStream& rOutStrm, sal_Int64 nBytes, sal_Int32 nAtomSize )
111 : {
112 340 : if( nBytes > 0 )
113 : {
114 : // make buffer size a multiple of the passed atom size
115 340 : sal_Int32 nBufferSize = getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, (INPUTSTREAM_BUFFERSIZE / nAtomSize) * nAtomSize );
116 340 : StreamDataSequence aBuffer( nBufferSize );
117 1020 : while( nBytes > 0 )
118 : {
119 340 : sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, nBufferSize );
120 340 : sal_Int32 nBytesRead = readData( aBuffer, nReadSize, nAtomSize );
121 340 : rOutStrm.writeData( aBuffer );
122 340 : if( nReadSize == nBytesRead )
123 0 : nBytes -= nReadSize;
124 : else
125 340 : nBytes = 0;
126 340 : }
127 : }
128 340 : }
129 :
130 : // ============================================================================
131 :
132 448 : BinaryXInputStream::BinaryXInputStream( const Reference< XInputStream >& rxInStrm, bool bAutoClose ) :
133 896 : BinaryStreamBase( Reference< XSeekable >( rxInStrm, UNO_QUERY ).is() ),
134 : BinaryXSeekableStream( Reference< XSeekable >( rxInStrm, UNO_QUERY ) ),
135 : maBuffer( INPUTSTREAM_BUFFERSIZE ),
136 : mxInStrm( rxInStrm ),
137 896 : mbAutoClose( bAutoClose && rxInStrm.is() )
138 : {
139 448 : mbEof = !mxInStrm.is();
140 448 : }
141 :
142 1344 : BinaryXInputStream::~BinaryXInputStream()
143 : {
144 448 : close();
145 896 : }
146 :
147 448 : void BinaryXInputStream::close()
148 : {
149 : OSL_ENSURE( !mbAutoClose || mxInStrm.is(), "BinaryXInputStream::close - invalid call" );
150 448 : if( mxInStrm.is() ) try
151 : {
152 262 : mxInStrm->closeInput();
153 : }
154 0 : catch( Exception& )
155 : {
156 : OSL_FAIL( "BinaryXInputStream::close - closing input stream failed" );
157 : }
158 448 : mxInStrm.clear();
159 448 : mbAutoClose = false;
160 448 : BinaryXSeekableStream::close();
161 448 : }
162 :
163 26482 : sal_Int32 BinaryXInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t /*nAtomSize*/ )
164 : {
165 26482 : sal_Int32 nRet = 0;
166 26482 : if( !mbEof && (nBytes > 0) ) try
167 : {
168 26296 : nRet = mxInStrm->readBytes( orData, nBytes );
169 26296 : mbEof = nRet != nBytes;
170 : }
171 0 : catch( Exception& )
172 : {
173 0 : mbEof = true;
174 : }
175 26482 : return nRet;
176 : }
177 :
178 26122 : sal_Int32 BinaryXInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize )
179 : {
180 26122 : sal_Int32 nRet = 0;
181 26122 : if( !mbEof && (nBytes > 0) )
182 : {
183 26122 : sal_Int32 nBufferSize = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, INPUTSTREAM_BUFFERSIZE );
184 26122 : sal_uInt8* opnMem = reinterpret_cast< sal_uInt8* >( opMem );
185 78366 : while( !mbEof && (nBytes > 0) )
186 : {
187 26122 : sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, nBufferSize );
188 26122 : sal_Int32 nBytesRead = readData( maBuffer, nReadSize, nAtomSize );
189 26122 : if( nBytesRead > 0 )
190 26072 : memcpy( opnMem, maBuffer.getConstArray(), static_cast< size_t >( nBytesRead ) );
191 26122 : opnMem += nBytesRead;
192 26122 : nBytes -= nBytesRead;
193 26122 : nRet += nBytesRead;
194 : }
195 : }
196 26122 : return nRet;
197 : }
198 :
199 216 : void BinaryXInputStream::skip( sal_Int32 nBytes, size_t /*nAtomSize*/ )
200 : {
201 216 : if( !mbEof ) try
202 : {
203 216 : mxInStrm->skipBytes( nBytes );
204 : }
205 0 : catch( Exception& )
206 : {
207 0 : mbEof = true;
208 : }
209 216 : }
210 :
211 : // ============================================================================
212 :
213 740 : SequenceInputStream::SequenceInputStream( const StreamDataSequence& rData ) :
214 : BinaryStreamBase( true ),
215 740 : SequenceSeekableStream( rData )
216 : {
217 740 : }
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 180 : sal_Int32 SequenceInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t /*nAtomSize*/ )
235 : {
236 180 : sal_Int32 nReadBytes = 0;
237 180 : if( !mbEof )
238 : {
239 180 : nReadBytes = getMaxBytes( nBytes );
240 180 : if( nReadBytes > 0 )
241 180 : memcpy( opMem, mpData->getConstArray() + mnPos, static_cast< size_t >( nReadBytes ) );
242 180 : mnPos += nReadBytes;
243 180 : mbEof = nReadBytes < nBytes;
244 : }
245 180 : 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: */
|