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