LibreOffice Module oox (master) 1
binaryinputstream.cxx
Go to the documentation of this file.
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
21
22#include <com/sun/star/io/XInputStream.hpp>
23#include <com/sun/star/io/XSeekable.hpp>
24#include <string.h>
25#include <algorithm>
26#include <vector>
27#include <rtl/ustrbuf.hxx>
28#include <osl/diagnose.h>
30
31namespace oox {
32
33using namespace ::com::sun::star::io;
34using namespace ::com::sun::star::uno;
35
36namespace {
37
38const sal_Int32 INPUTSTREAM_BUFFERSIZE = 0x8000;
39
40} // namespace
41
43{
44 OUStringBuffer aBuffer;
45 for (;;)
46 {
47 sal_uInt16 nChar = readuInt16();
48 if ( mbEof || (nChar == 0) ) break;
49 aBuffer.append( static_cast< sal_Unicode >( nChar ) );
50 }
51 return aBuffer.makeStringAndClear();
52}
53
54OString BinaryInputStream::readCharArray( sal_Int32 nChars )
55{
56 if( nChars <= 0 )
57 return OString();
58
59 ::std::vector< sal_uInt8 > aBuffer;
60 sal_Int32 nCharsRead = readArray( aBuffer, nChars );
61 if( nCharsRead <= 0 )
62 return OString();
63
64 aBuffer.resize( static_cast< size_t >( nCharsRead ) );
65 // NUL characters are replaced by question marks.
66 ::std::replace( aBuffer.begin(), aBuffer.end(), '\0', '?' );
67
68 return OString(reinterpret_cast<char*>(aBuffer.data()), nCharsRead);
69}
70
71OUString BinaryInputStream::readCharArrayUC( sal_Int32 nChars, rtl_TextEncoding eTextEnc )
72{
73 return OStringToOUString( readCharArray( nChars ), eTextEnc );
74}
75
76OUString BinaryInputStream::readUnicodeArray( sal_Int32 nChars )
77{
78 if( nChars <= 0 )
79 return OUString();
80
81 ::std::vector< sal_uInt16 > aBuffer;
82 sal_Int32 nCharsRead = readArray( aBuffer, nChars );
83 if( nCharsRead <= 0 )
84 return OUString();
85
86 aBuffer.resize( static_cast< size_t >( nCharsRead ) );
87 // don't allow nul chars
88 ::std::replace( aBuffer.begin(), aBuffer.begin() + nCharsRead, '\0', '?' );
89
90 OUStringBuffer aStringBuffer;
91 aStringBuffer.ensureCapacity( nCharsRead );
92 for (auto const& elem : aBuffer)
93 aStringBuffer.append( static_cast< sal_Unicode >(elem) );
94 return aStringBuffer.makeStringAndClear();
95}
96
97OUString BinaryInputStream::readCompressedUnicodeArray( sal_Int32 nChars, bool bCompressed )
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 ) :
102 readUnicodeArray( nChars );
103}
104
106{
107 sal_Int64 nBytes = SAL_MAX_INT64;
108 sal_Int32 nBufferSize = INPUTSTREAM_BUFFERSIZE;
109 StreamDataSequence aBuffer( nBufferSize );
110 while( nBytes > 0 )
111 {
112 sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, nBufferSize );
113 sal_Int32 nBytesRead = readData( aBuffer, nReadSize );
114 rOutStrm.writeData( aBuffer );
115 if( nReadSize == nBytesRead )
116 nBytes -= nReadSize;
117 else
118 nBytes = 0;
119 }
120}
121
122BinaryXInputStream::BinaryXInputStream( const Reference< XInputStream >& rxInStrm, bool bAutoClose ) :
123 BinaryStreamBase( Reference< XSeekable >( rxInStrm, UNO_QUERY ).is() ),
124 BinaryXSeekableStream( Reference< XSeekable >( rxInStrm, UNO_QUERY ) ),
125 maBuffer( INPUTSTREAM_BUFFERSIZE ),
126 mxInStrm( rxInStrm ),
127 mbAutoClose( bAutoClose && rxInStrm.is() )
128{
129 mbEof = !mxInStrm.is();
130}
131
133{
134 close();
135}
136
138{
139 OSL_ENSURE( !mbAutoClose || mxInStrm.is(), "BinaryXInputStream::close - invalid call" );
140 if( mxInStrm.is() ) try
141 {
142 mxInStrm->closeInput();
143 }
144 catch( Exception& )
145 {
146 OSL_FAIL( "BinaryXInputStream::close - closing input stream failed" );
147 }
148 mxInStrm.clear();
149 mbAutoClose = false;
151}
152
153sal_Int32 BinaryXInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t /*nAtomSize*/ )
154{
155 sal_Int32 nRet = 0;
156 if( !mbEof && (nBytes > 0) ) try
157 {
158 nRet = mxInStrm->readBytes( orData, nBytes );
159 mbEof = nRet != nBytes;
160 }
161 catch( Exception& )
162 {
163 mbEof = true;
164 }
165 return nRet;
166}
167
168sal_Int32 BinaryXInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize )
169{
170 sal_Int32 nRet = 0;
171 if( !mbEof && (nBytes > 0) )
172 {
173 sal_Int32 nBufferSize = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, INPUTSTREAM_BUFFERSIZE );
174 sal_uInt8* opnMem = static_cast< sal_uInt8* >( opMem );
175 while( !mbEof && (nBytes > 0) )
176 {
177 sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, nBufferSize );
178 sal_Int32 nBytesRead = readData( maBuffer, nReadSize, nAtomSize );
179 if( nBytesRead > 0 )
180 memcpy( opnMem, maBuffer.getConstArray(), static_cast< size_t >( nBytesRead ) );
181 opnMem += nBytesRead;
182 nBytes -= nBytesRead;
183 nRet += nBytesRead;
184 }
185 }
186 return nRet;
187}
188
189void BinaryXInputStream::skip( sal_Int32 nBytes, size_t /*nAtomSize*/ )
190{
191 if( !mbEof ) try
192 {
193 mxInStrm->skipBytes( nBytes );
194 }
195 catch( Exception& )
196 {
197 mbEof = true;
198 }
199}
200
202 BinaryStreamBase( true ),
204{
205}
206
207sal_Int32 SequenceInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t /*nAtomSize*/ )
208{
209 sal_Int32 nReadBytes = 0;
210 if( !mbEof )
211 {
212 nReadBytes = getMaxBytes( nBytes );
213 orData.realloc( nReadBytes );
214 if( nReadBytes > 0 )
215 memcpy( orData.getArray(), mpData->getConstArray() + mnPos, static_cast< size_t >( nReadBytes ) );
216 mnPos += nReadBytes;
217 mbEof = nReadBytes < nBytes;
218 }
219 return nReadBytes;
220}
221
222sal_Int32 SequenceInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t /*nAtomSize*/ )
223{
224 sal_Int32 nReadBytes = 0;
225 if( !mbEof )
226 {
227 nReadBytes = getMaxBytes( nBytes );
228 if( nReadBytes > 0 )
229 memcpy( opMem, mpData->getConstArray() + mnPos, static_cast< size_t >( nReadBytes ) );
230 mnPos += nReadBytes;
231 mbEof = nReadBytes < nBytes;
232 }
233 return nReadBytes;
234}
235
236void SequenceInputStream::skip( sal_Int32 nBytes, size_t /*nAtomSize*/ )
237{
238 if( !mbEof )
239 {
240 sal_Int32 nSkipBytes = getMaxBytes( nBytes );
241 mnPos += nSkipBytes;
242 mbEof = nSkipBytes < nBytes;
243 }
244}
245
247 BinaryStreamBase( rInStrm.isSeekable() ),
248 mpInStrm( &rInStrm ),
249 mnStartPos( rInStrm.tell() ),
250 mnRelPos( 0 )
251{
252 sal_Int64 nRemaining = rInStrm.getRemaining();
253 mnSize = (nRemaining >= 0) ? ::std::min( nSize, nRemaining ) : nSize;
254 mbEof = mbEof || rInStrm.isEof() || (mnSize < 0);
255}
256
258{
259 return mpInStrm ? mnSize : -1;
260}
261
263{
264 return mpInStrm ? mnRelPos : -1;
265}
266
267void RelativeInputStream::seek( sal_Int64 nPos )
268{
269 if( mpInStrm && isSeekable() && (mnStartPos >= 0) )
270 {
271 mnRelPos = getLimitedValue< sal_Int64, sal_Int64 >( nPos, 0, mnSize );
273 mbEof = (mnRelPos != nPos) || mpInStrm->isEof();
274 }
275}
276
278{
279 mpInStrm = nullptr;
280 mbEof = true;
281}
282
283sal_Int32 RelativeInputStream::readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize )
284{
285 sal_Int32 nReadBytes = 0;
286 if( !mbEof )
287 {
288 sal_Int32 nMaxBytes = getMaxBytes( nBytes );
289 nReadBytes = mpInStrm->readData( orData, nMaxBytes, nAtomSize );
290 mnRelPos += nReadBytes;
291 mbEof = (nMaxBytes < nBytes) || mpInStrm->isEof();
292 }
293 return nReadBytes;
294}
295
296sal_Int32 RelativeInputStream::readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize )
297{
298 sal_Int32 nReadBytes = 0;
299 if( !mbEof )
300 {
301 sal_Int32 nMaxBytes = getMaxBytes( nBytes );
302 nReadBytes = mpInStrm->readMemory( opMem, nMaxBytes, nAtomSize );
303 mnRelPos += nReadBytes;
304 mbEof = (nMaxBytes < nBytes) || mpInStrm->isEof();
305 }
306 return nReadBytes;
307}
308
309void RelativeInputStream::skip( sal_Int32 nBytes, size_t nAtomSize )
310{
311 if( !mbEof )
312 {
313 sal_Int32 nSkipBytes = getMaxBytes( nBytes );
314 mpInStrm->skip( nSkipBytes, nAtomSize );
315 mnRelPos += nSkipBytes;
316 mbEof = nSkipBytes < nBytes;
317 }
318}
319
320} // namespace oox
321
322/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Interface for binary input stream classes.
virtual void skip(sal_Int32 nBytes, size_t nAtomSize=1)=0
Derived classes implement seeking the stream forward by the passed number of bytes.
OUString readCharArrayUC(sal_Int32 nChars, rtl_TextEncoding eTextEnc)
Reads a byte character array and returns a Unicode string.
OString readCharArray(sal_Int32 nChars)
Reads a byte character array and returns the string.
sal_Int32 readArray(Type *opnArray, sal_Int32 nElemCount)
Reads a (preallocated!) C array of values from the stream.
OUString readNulUnicodeArray()
Reads a NUL-terminated Unicode character array and returns the string.
virtual sal_Int32 readData(StreamDataSequence &orData, sal_Int32 nBytes, size_t nAtomSize=1)=0
Derived classes implement reading nBytes bytes to the passed sequence.
void copyToStream(BinaryOutputStream &rOutStrm)
Copies bytes from the current position to the passed output stream.
OUString readCompressedUnicodeArray(sal_Int32 nChars, bool bCompressed)
Reads a Unicode character array (may be compressed) and returns the string.
virtual sal_Int32 readMemory(void *opMem, sal_Int32 nBytes, size_t nAtomSize=1)=0
Derived classes implement reading nBytes bytes to the (preallocated!) memory buffer opMem.
OUString readUnicodeArray(sal_Int32 nChars)
Reads a Unicode character array and returns the string.
Interface for binary output stream classes.
virtual void writeData(const StreamDataSequence &rData, size_t nAtomSize=1)=0
Derived classes implement writing the contents of the passed data sequence.
Base class for binary stream classes.
bool isSeekable() const
Returns true, if the implementation supports the seek() operation.
sal_Int64 getRemaining() const
Returns the size of the remaining data available in the stream, if stream supports size() and tell(),...
bool isEof() const
Returns true, if the stream position is invalid (EOF).
virtual void seek(sal_Int64 nPos)=0
Implementations seek the stream to the passed position, if the stream is seekable.
bool mbEof
End of stream flag.
virtual void skip(sal_Int32 nBytes, size_t nAtomSize=1) override
Seeks the stream forward by the passed number of bytes.
bool mbAutoClose
True = automatically close stream on destruction.
BinaryXInputStream(const css::uno::Reference< css::io::XInputStream > &rxInStrm, bool bAutoClose)
Constructs the wrapper object for the passed input stream.
virtual sal_Int32 readMemory(void *opMem, sal_Int32 nBytes, size_t nAtomSize=1) override
Reads nBytes bytes to the (existing) buffer opMem.
virtual void close() override
Closes the input stream.
StreamDataSequence maBuffer
Data buffer used in readMemory() function.
css::uno::Reference< css::io::XInputStream > mxInStrm
Reference to the input stream.
virtual ~BinaryXInputStream() override
virtual sal_Int32 readData(StreamDataSequence &orData, sal_Int32 nBytes, size_t nAtomSize=1) override
Reads nBytes bytes to the passed sequence.
Base class for binary input and output streams wrapping a UNO stream, seekable via the com....
virtual void close() override
Releases the reference to the UNO XSeekable interface.
virtual sal_Int32 readMemory(void *opMem, sal_Int32 nBytes, size_t nAtomSize=1) override
Reads nBytes bytes to the (existing) buffer opMem.
BinaryInputStream * mpInStrm
RelativeInputStream(BinaryInputStream &rInStrm, sal_Int64 nSize)
Constructs the wrapper object for the passed stream.
virtual void seek(sal_Int64 nPos) override
Seeks the stream to the passed relative position, if the wrapped stream is seekable.
virtual sal_Int32 readData(StreamDataSequence &orData, sal_Int32 nBytes, size_t nAtomSize=1) override
Reads nBytes bytes to the passed sequence.
virtual void skip(sal_Int32 nBytes, size_t nAtomSize=1) override
Seeks the stream forward by the passed number of bytes.
virtual void close() override
Closes the input stream but not the wrapped stream.
virtual sal_Int64 size() const override
Returns the size of the data block in the wrapped stream offered by this wrapper.
virtual sal_Int64 tell() const override
Returns the current relative stream position.
sal_Int32 getMaxBytes(sal_Int32 nBytes) const
Returns the number of bytes available in the sequence for the passed byte count.
virtual sal_Int32 readMemory(void *opMem, sal_Int32 nBytes, size_t nAtomSize=1) override
Reads nBytes bytes to the (existing) buffer opMem.
virtual sal_Int32 readData(StreamDataSequence &orData, sal_Int32 nBytes, size_t nAtomSize=1) override
Reads nBytes bytes to the passed sequence.
SequenceInputStream(const StreamDataSequence &rData)
Constructs the wrapper object for the passed data sequence.
virtual void skip(sal_Int32 nBytes, size_t nAtomSize=1) override
Seeks the stream forward by the passed number of bytes.
sal_Int32 getMaxBytes(sal_Int32 nBytes) const
Returns the number of bytes available in the sequence for the passed byte count.
Base class for binary input and output streams wrapping a StreamDataSequence, which is always seekabl...
sal_Int32 mnPos
Current position in the sequence.
const StreamDataSequence * mpData
Wrapped data sequence.
sal_uInt16 nPos
@ Exception
Reference
css::uno::Sequence< sal_Int8 > StreamDataSequence
#define SAL_MAX_INT64
unsigned char sal_uInt8
sal_uInt16 sal_Unicode
std::unique_ptr< char[]> aBuffer