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