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