1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24 #ifndef OOX_HELPER_BINARYINPUTSTREAM_HXX
25 #define OOX_HELPER_BINARYINPUTSTREAM_HXX
26
27 #include <vector>
28 #include <com/sun/star/io/XInputStream.hpp>
29 #include "oox/helper/binarystreambase.hxx"
30
31 namespace com { namespace sun { namespace star {
32 namespace io { class XInputStream; }
33 } } }
34
35 namespace oox {
36
37 class BinaryOutputStream;
38
39 // ============================================================================
40
41 /** Interface for binary input stream classes.
42
43 The binary data in the stream is assumed to be in little-endian format.
44 */
45 class BinaryInputStream : public virtual BinaryStreamBase
46 {
47 public:
48 /** Derived classes implement reading nBytes bytes to the passed sequence.
49 The sequence will be reallocated internally.
50
51 @param nAtomSize
52 The size of the elements in the memory block, if available. Derived
53 classes may be interested in this information.
54
55 @return
56 Number of bytes really read.
57 */
58 virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize = 1 ) = 0;
59
60 /** Derived classes implement reading nBytes bytes to the (preallocated!)
61 memory buffer opMem.
62
63 @param nAtomSize
64 The size of the elements in the memory block, if available. Derived
65 classes may be interested in this information.
66
67 @return
68 Number of bytes really read.
69 */
70 virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize = 1 ) = 0;
71
72 /** Derived classes implement seeking the stream forward by the passed
73 number of bytes. This should work for non-seekable streams too.
74
75 @param nAtomSize
76 The size of the elements in the memory block, if available. Derived
77 classes may be interested in this information.
78 */
79 virtual void skip( sal_Int32 nBytes, size_t nAtomSize = 1 ) = 0;
80
81 /** Reads a value from the stream and converts it to platform byte order.
82 All data types supported by the ByteOrderConverter class can be used.
83 */
84 template< typename Type >
85 void readValue( Type& ornValue );
86
87 /** Reads a value from the stream and converts it to platform byte order.
88 All data types supported by the ByteOrderConverter class can be used.
89 */
90 template< typename Type >
readValue()91 inline Type readValue() { Type nValue; readValue( nValue ); return nValue; }
92
93 /** Stream operator for all data types supported by the readValue() function. */
94 template< typename Type >
operator >>(Type & ornValue)95 inline BinaryInputStream& operator>>( Type& ornValue ) { readValue( ornValue ); return *this; }
96
readInt8()97 inline sal_Int8 readInt8() { return readValue< sal_Int8 >(); }
readuInt8()98 inline sal_uInt8 readuInt8() { return readValue< sal_uInt8 >(); }
readInt16()99 inline sal_Int16 readInt16() { return readValue< sal_Int16 >(); }
readuInt16()100 inline sal_uInt16 readuInt16() { return readValue< sal_uInt16 >(); }
readInt32()101 inline sal_Int32 readInt32() { return readValue< sal_Int32 >(); }
readuInt32()102 inline sal_uInt32 readuInt32() { return readValue< sal_uInt32 >(); }
readInt64()103 inline sal_Int64 readInt64() { return readValue< sal_Int64 >(); }
readuInt64()104 inline sal_uInt64 readuInt64() { return readValue< sal_uInt64 >(); }
readFloat()105 inline float readFloat() { return readValue< float >(); }
readDouble()106 inline double readDouble() { return readValue< double >(); }
107
108 /** Reads a (preallocated!) C array of values from the stream.
109
110 Converts all values in the array to platform byte order. All data types
111 supported by the ByteOrderConverter class can be used.
112
113 @param nElemCount
114 Number of array elements to read (NOT byte count).
115
116 @return
117 Number of array elements really read (NOT byte count).
118 */
119 template< typename Type >
120 sal_Int32 readArray( Type* opnArray, sal_Int32 nElemCount );
121
122 /** Reads a sequence of values from the stream.
123
124 The sequence will be reallocated internally. Converts all values in the
125 array to platform byte order. All data types supported by the
126 ByteOrderConverter class can be used.
127
128 @param nElemCount
129 Number of elements to put into the sequence (NOT byte count).
130
131 @return
132 Number of sequence elements really read (NOT byte count).
133 */
134 template< typename Type >
135 sal_Int32 readArray( ::com::sun::star::uno::Sequence< Type >& orSequence, sal_Int32 nElemCount );
136
137 /** Reads a vector of values from the stream.
138
139 The vector will be resized internally. Converts all values in the
140 vector to platform byte order. All data types supported by the
141 ByteOrderConverter class can be used.
142
143 @param nElemCount
144 Number of elements to put into the vector (NOT byte count).
145
146 @return
147 Number of vector elements really read (NOT byte count).
148 */
149 template< typename Type >
150 sal_Int32 readArray( ::std::vector< Type >& orVector, sal_Int32 nElemCount );
151
152 /** Skips an array of values of a certain type in the stream.
153
154 All data types supported by the ByteOrderConverter class can be used.
155
156 @param nElemCount
157 Number of array elements to skip (NOT byte count).
158 */
159 template< typename Type >
160 void skipArray( sal_Int32 nElemCount );
161
162 /** Reads a NUL-terminated byte character array and returns the string.
163 */
164 ::rtl::OString readNulCharArray();
165
166 /** Reads a NUL-terminated byte character array and returns a Unicode string.
167
168 @param eTextEnc
169 The text encoding used to create the Unicode string.
170 */
171 ::rtl::OUString readNulCharArrayUC( rtl_TextEncoding eTextEnc );
172
173 /** Reads a NUL-terminated Unicode character array and returns the string.
174 */
175 ::rtl::OUString readNulUnicodeArray();
176
177 /** Reads a byte character array and returns the string.
178
179 @param nChars
180 Number of characters (bytes) to read from the stream.
181
182 @param bAllowNulChars
183 True = NUL characters are inserted into the imported string.
184 False = NUL characters are replaced by question marks (default).
185 */
186 ::rtl::OString readCharArray( sal_Int32 nChars, bool bAllowNulChars = false );
187
188 /** Reads a byte character array and returns a Unicode string.
189
190 @param nChars
191 Number of characters (bytes) to read from the stream.
192
193 @param eTextEnc
194 The text encoding used to create the Unicode string.
195
196 @param bAllowNulChars
197 True = NUL characters are inserted into the imported string.
198 False = NUL characters are replaced by question marks (default).
199 */
200 ::rtl::OUString readCharArrayUC( sal_Int32 nChars, rtl_TextEncoding eTextEnc, bool bAllowNulChars = false );
201
202 /** Reads a Unicode character array and returns the string.
203
204 @param nChars
205 Number of 16-bit characters to read from the stream.
206
207 @param bAllowNulChars
208 True = NUL characters are inserted into the imported string.
209 False = NUL characters are replaced by question marks (default).
210 */
211 ::rtl::OUString readUnicodeArray( sal_Int32 nChars, bool bAllowNulChars = false );
212
213 /** Reads a Unicode character array (may be compressed) and returns the
214 string.
215
216 @param nChars
217 Number of 8-bit or 16-bit characters to read from the stream.
218
219 @param bCompressed
220 True = Character array is compressed (stored as 8-bit characters).
221 False = Character array is not compressed (stored as 16-bit characters).
222
223 @param bAllowNulChars
224 True = NUL characters are inserted into the imported string.
225 False = NUL characters are replaced by question marks (default).
226 */
227 ::rtl::OUString readCompressedUnicodeArray( sal_Int32 nChars, bool bCompressed, bool bAllowNulChars = false );
228
229 /** Copies nBytes bytes from the current position to the passed output stream.
230 */
231 void copyToStream( BinaryOutputStream& rOutStrm, sal_Int64 nBytes = SAL_MAX_INT64, sal_Int32 nAtomSize = 1 );
232
233 protected:
234 /** This dummy default c'tor will never call the c'tor of the virtual base
235 class BinaryStreamBase as this class cannot be instanciated directly. */
BinaryInputStream()236 inline explicit BinaryInputStream() : BinaryStreamBase( false ) {}
237 };
238
239 typedef ::boost::shared_ptr< BinaryInputStream > BinaryInputStreamRef;
240
241 // ----------------------------------------------------------------------------
242
243 template< typename Type >
readValue(Type & ornValue)244 void BinaryInputStream::readValue( Type& ornValue )
245 {
246 readMemory( &ornValue, static_cast< sal_Int32 >( sizeof( Type ) ), sizeof( Type ) );
247 ByteOrderConverter::convertLittleEndian( ornValue );
248 }
249
250 template< typename Type >
readArray(Type * opnArray,sal_Int32 nElemCount)251 sal_Int32 BinaryInputStream::readArray( Type* opnArray, sal_Int32 nElemCount )
252 {
253 sal_Int32 nRet = 0;
254 if( !mbEof )
255 {
256 sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int32 >( nElemCount, 0, SAL_MAX_INT32 / sizeof( Type ) ) * sizeof( Type );
257 nRet = readMemory( opnArray, nReadSize, sizeof( Type ) ) / sizeof( Type );
258 ByteOrderConverter::convertLittleEndianArray( opnArray, static_cast< size_t >( nRet ) );
259 }
260 return nRet;
261 }
262
263 template< typename Type >
readArray(::com::sun::star::uno::Sequence<Type> & orSequence,sal_Int32 nElemCount)264 sal_Int32 BinaryInputStream::readArray( ::com::sun::star::uno::Sequence< Type >& orSequence, sal_Int32 nElemCount )
265 {
266 orSequence.reallocate( nElemCount );
267 return orSequence.hasElements() ? readArray( orSequence.getArray(), nElemCount ) : 0;
268 }
269
270 template< typename Type >
readArray(::std::vector<Type> & orVector,sal_Int32 nElemCount)271 sal_Int32 BinaryInputStream::readArray( ::std::vector< Type >& orVector, sal_Int32 nElemCount )
272 {
273 orVector.resize( static_cast< size_t >( nElemCount ) );
274 return orVector.empty() ? 0 : readArray( &orVector.front(), nElemCount );
275 }
276
277 template< typename Type >
skipArray(sal_Int32 nElemCount)278 void BinaryInputStream::skipArray( sal_Int32 nElemCount )
279 {
280 sal_Int32 nSkipSize = getLimitedValue< sal_Int32, sal_Int32 >( nElemCount, 0, SAL_MAX_INT32 / sizeof( Type ) ) * sizeof( Type );
281 skip( nSkipSize, sizeof( Type ) );
282 }
283
284 // ============================================================================
285
286 /** Wraps a UNO input stream and provides convenient access functions.
287
288 The binary data in the stream is assumed to be in little-endian format.
289 */
290 class BinaryXInputStream : public BinaryXSeekableStream, public BinaryInputStream
291 {
292 public:
293 /** Constructs the wrapper object for the passed input stream.
294
295 @param rxInStream
296 The com.sun.star.io.XInputStream interface of the UNO input stream
297 to be wrapped.
298
299 @param bAutoClose
300 True = automatically close the wrapped input stream on destruction
301 of this wrapper or when close() is called.
302 */
303 explicit BinaryXInputStream(
304 const ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >& rxInStrm,
305 bool bAutoClose );
306
307 virtual ~BinaryXInputStream();
308
309 /** Closes the input stream. Does also close the wrapped UNO input stream
310 if bAutoClose has been set to true in the constructor. */
311 virtual void close();
312
313 /** Reads nBytes bytes to the passed sequence.
314 @return Number of bytes really read. */
315 virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize = 1 );
316
317 /** Reads nBytes bytes to the (existing) buffer opMem.
318 @return Number of bytes really read. */
319 virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize = 1 );
320
321 /** Seeks the stream forward by the passed number of bytes. This works for
322 non-seekable streams too. */
323 virtual void skip( sal_Int32 nBytes, size_t nAtomSize = 1 );
324
325 /** Stream operator for all data types supported by the readValue() function. */
326 template< typename Type >
operator >>(Type & ornValue)327 inline BinaryXInputStream& operator>>( Type& ornValue ) { readValue( ornValue ); return *this; }
328
329 private:
330 StreamDataSequence maBuffer; /// Data buffer used in readMemory() function.
331 ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream >
332 mxInStrm; /// Reference to the input stream.
333 bool mbAutoClose; /// True = automatically close stream on destruction.
334 };
335
336 // ============================================================================
337
338 /** Wraps a StreamDataSequence and provides convenient access functions.
339
340 The binary data in the stream is assumed to be in little-endian format.
341 */
342 class SequenceInputStream : public SequenceSeekableStream, public BinaryInputStream
343 {
344 public:
345 /** Constructs the wrapper object for the passed data sequence.
346
347 @attention
348 The passed data sequence MUST live at least as long as this stream
349 wrapper. The data sequence MUST NOT be changed from outside as long
350 as this stream wrapper is used to read from it.
351 */
352 explicit SequenceInputStream( const StreamDataSequence& rData );
353
354 /** Reads nBytes bytes to the passed sequence.
355 @return Number of bytes really read. */
356 virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize = 1 );
357
358 /** Reads nBytes bytes to the (existing) buffer opMem.
359 @return Number of bytes really read. */
360 virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize = 1 );
361
362 /** Seeks the stream forward by the passed number of bytes. This works for
363 non-seekable streams too. */
364 virtual void skip( sal_Int32 nBytes, size_t nAtomSize = 1 );
365
366 /** Stream operator for all data types supported by the readValue() function. */
367 template< typename Type >
operator >>(Type & ornValue)368 inline SequenceInputStream& operator>>( Type& ornValue ) { readValue( ornValue ); return *this; }
369
370 private:
371 /** Returns the number of bytes available in the sequence for the passed byte count. */
getMaxBytes(sal_Int32 nBytes) const372 inline sal_Int32 getMaxBytes( sal_Int32 nBytes ) const
373 { return getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, mpData->getLength() - mnPos ); }
374 };
375
376 // ============================================================================
377
378 /** Wraps a BinaryInputStream and provides access to a specific part of the
379 stream data.
380
381 Provides access to the stream data block starting at the current position
382 of the stream, and with a specific length. If the wrapped stream is
383 seekable, this wrapper will treat the position of the wrapped stream at
384 construction time as position "0" (therefore the class name).
385
386 The passed input stream MUST live at least as long as this stream wrapper.
387 The stream MUST NOT be changed from outside as long as this stream wrapper
388 is used to read from it.
389 */
390 class RelativeInputStream : public BinaryInputStream
391 {
392 public:
393 /** Constructs the wrapper object for the passed stream.
394
395 @param nSize
396 If specified, restricts the amount of data that can be read from
397 the passed input stream.
398 */
399 explicit RelativeInputStream(
400 BinaryInputStream& rInStrm,
401 sal_Int64 nSize = SAL_MAX_INT64 );
402
403 /** Returns the size of the data block in the wrapped stream offered by
404 this wrapper. */
405 virtual sal_Int64 size() const;
406
407 /** Returns the current relative stream position. */
408 virtual sal_Int64 tell() const;
409
410 /** Seeks the stream to the passed relative position, if the wrapped stream
411 is seekable. */
412 virtual void seek( sal_Int64 nPos );
413
414 /** Closes the input stream but not the wrapped stream. */
415 virtual void close();
416
417 /** Reads nBytes bytes to the passed sequence. Does not read out of the
418 data block whose size has been specified on construction.
419 @return Number of bytes really read. */
420 virtual sal_Int32 readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize = 1 );
421
422 /** Reads nBytes bytes to the (existing) buffer opMem. Does not read out of
423 the data block whose size has been specified on construction.
424 @return Number of bytes really read. */
425 virtual sal_Int32 readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize = 1 );
426
427 /** Seeks the stream forward by the passed number of bytes. This works for
428 non-seekable streams too. Does not seek out of the data block. */
429 virtual void skip( sal_Int32 nBytes, size_t nAtomSize = 1 );
430
431 /** Stream operator for all data types supported by the readValue() function. */
432 template< typename Type >
operator >>(Type & ornValue)433 inline RelativeInputStream& operator>>( Type& ornValue ) { readValue( ornValue ); return *this; }
434
435 private:
436 /** Returns the number of bytes available in the sequence for the passed byte count. */
getMaxBytes(sal_Int32 nBytes) const437 inline sal_Int32 getMaxBytes( sal_Int32 nBytes ) const
438 { return getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, mnSize - mnRelPos ); }
439
440 private:
441 BinaryInputStream* mpInStrm;
442 sal_Int64 mnStartPos;
443 sal_Int64 mnRelPos;
444 sal_Int64 mnSize;
445 };
446
447 // ============================================================================
448
449 } // namespace oox
450
451 #endif
452