Coverage Report

Created: 2025-11-16 09:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/oox/helper/binaryinputstream.hxx
Line
Count
Source
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
#ifndef INCLUDED_OOX_HELPER_BINARYINPUTSTREAM_HXX
21
#define INCLUDED_OOX_HELPER_BINARYINPUTSTREAM_HXX
22
23
#include <cstddef>
24
#include <memory>
25
#include <vector>
26
27
#include <com/sun/star/uno/Reference.hxx>
28
#include <oox/dllapi.h>
29
#include <oox/helper/binarystreambase.hxx>
30
#include <oox/helper/helper.hxx>
31
#include <rtl/string.hxx>
32
#include <rtl/textenc.h>
33
#include <rtl/ustring.hxx>
34
#include <sal/types.h>
35
36
namespace com::sun::star {
37
    namespace io { class XInputStream; }
38
}
39
40
namespace oox {
41
42
class BinaryOutputStream;
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 OOX_DLLPUBLIC 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
    [[nodiscard]]
90
    Type                 readValue();
91
92
    [[nodiscard]]
93
0
    sal_Int8             readInt8()   { return readValue<sal_Int8>(); }
94
    [[nodiscard]]
95
120k
    sal_uInt8            readuInt8()  { return readValue<sal_uInt8>(); }
96
    [[nodiscard]]
97
0
    sal_Int16            readInt16()  { return readValue<sal_Int16>(); }
98
    [[nodiscard]]
99
30.7k
    sal_uInt16           readuInt16() { return readValue<sal_uInt16>(); }
100
    [[nodiscard]]
101
283
    sal_Int32            readInt32()  { return readValue<sal_Int32>(); }
102
    [[nodiscard]]
103
33.1k
    sal_uInt32           readuInt32() { return readValue<sal_uInt32>(); }
104
    [[nodiscard]]
105
6
    sal_Int64            readInt64()  { return readValue<sal_Int64>(); }
106
    [[nodiscard]]
107
0
    float                readFloat()  { return readValue<float>(); }
108
    [[nodiscard]]
109
0
    double               readDouble() { return readValue<double>(); }
110
    [[nodiscard]]
111
1.49k
    unsigned char        readuChar()  { return readValue<unsigned char>(); }
112
113
    /** Reads a (preallocated!) C array of values from the stream.
114
115
        Converts all values in the array to platform byte order. All data types
116
        supported by the ByteOrderConverter class can be used.
117
118
        @param nElemCount
119
            Number of array elements to read (NOT byte count).
120
121
        @return
122
            Number of array elements really read (NOT byte count).
123
     */
124
    template< typename Type >
125
    sal_Int32           readArray( Type* opnArray, sal_Int32 nElemCount );
126
127
    /** Reads a vector of values from the stream.
128
129
        The vector will be resized internally. Converts all values in the
130
        vector to platform byte order. All data types supported by the
131
        ByteOrderConverter class can be used.
132
133
        @param nElemCount
134
            Number of elements to put into the vector (NOT byte count).
135
136
        @return
137
            Number of vector elements really read (NOT byte count).
138
     */
139
    template< typename Type >
140
    sal_Int32           readArray( ::std::vector< Type >& orVector, sal_Int32 nElemCount );
141
142
    /** Reads a NUL-terminated Unicode character array and returns the string.
143
     */
144
    OUString     readNulUnicodeArray();
145
146
    /** Reads a byte character array and returns the string.
147
        NUL characters are replaced by question marks.
148
149
        @param nChars
150
            Number of characters (bytes) to read from the stream.
151
     */
152
    OString      readCharArray( sal_Int32 nChars );
153
154
    /** Reads a byte character array and returns a Unicode string.
155
        NUL characters are replaced by question marks.
156
157
        @param nChars
158
            Number of characters (bytes) to read from the stream.
159
160
        @param eTextEnc
161
            The text encoding used to create the Unicode string.
162
     */
163
    OUString     readCharArrayUC( sal_Int32 nChars, rtl_TextEncoding eTextEnc );
164
165
    /** Reads a Unicode character array and returns the string.
166
        NUL characters are replaced by question marks (default).
167
168
        @param nChars
169
            Number of 16-bit characters to read from the stream.
170
     */
171
    OUString     readUnicodeArray( sal_Int32 nChars );
172
173
    /** Reads a Unicode character array (may be compressed) and returns the
174
        string.
175
        NUL characters are replaced by question marks (default).
176
177
        @param nChars
178
            Number of 8-bit or 16-bit characters to read from the stream.
179
180
        @param bCompressed
181
            True = Character array is compressed (stored as 8-bit characters).
182
            False = Character array is not compressed (stored as 16-bit characters).
183
     */
184
    OUString     readCompressedUnicodeArray( sal_Int32 nChars, bool bCompressed );
185
186
    /** Copies bytes from the current position to the passed output stream.
187
     */
188
    void         copyToStream( BinaryOutputStream& rOutStrm );
189
190
protected:
191
231k
    BinaryInputStream() = default;
192
193
private:
194
    BinaryInputStream( BinaryInputStream const& ) = delete;
195
    BinaryInputStream& operator=( BinaryInputStream const& ) = delete;
196
};
197
198
typedef std::shared_ptr< BinaryInputStream > BinaryInputStreamRef;
199
200
201
template< typename Type >
202
Type BinaryInputStream::readValue()
203
186k
{
204
186k
    Type ornValue = Type();
205
186k
    readMemory( &ornValue, static_cast< sal_Int32 >( sizeof( Type ) ), sizeof( Type ) );
206
186k
    ByteOrderConverter::convertLittleEndian( ornValue );
207
186k
    return ornValue;
208
186k
}
int oox::BinaryInputStream::readValue<int>()
Line
Count
Source
203
297
{
204
297
    Type ornValue = Type();
205
297
    readMemory( &ornValue, static_cast< sal_Int32 >( sizeof( Type ) ), sizeof( Type ) );
206
297
    ByteOrderConverter::convertLittleEndian( ornValue );
207
297
    return ornValue;
208
297
}
unsigned short oox::BinaryInputStream::readValue<unsigned short>()
Line
Count
Source
203
30.7k
{
204
30.7k
    Type ornValue = Type();
205
30.7k
    readMemory( &ornValue, static_cast< sal_Int32 >( sizeof( Type ) ), sizeof( Type ) );
206
30.7k
    ByteOrderConverter::convertLittleEndian( ornValue );
207
30.7k
    return ornValue;
208
30.7k
}
Unexecuted instantiation: signed char oox::BinaryInputStream::readValue<signed char>()
unsigned char oox::BinaryInputStream::readValue<unsigned char>()
Line
Count
Source
203
121k
{
204
121k
    Type ornValue = Type();
205
121k
    readMemory( &ornValue, static_cast< sal_Int32 >( sizeof( Type ) ), sizeof( Type ) );
206
121k
    ByteOrderConverter::convertLittleEndian( ornValue );
207
121k
    return ornValue;
208
121k
}
Unexecuted instantiation: short oox::BinaryInputStream::readValue<short>()
unsigned int oox::BinaryInputStream::readValue<unsigned int>()
Line
Count
Source
203
33.2k
{
204
33.2k
    Type ornValue = Type();
205
33.2k
    readMemory( &ornValue, static_cast< sal_Int32 >( sizeof( Type ) ), sizeof( Type ) );
206
33.2k
    ByteOrderConverter::convertLittleEndian( ornValue );
207
33.2k
    return ornValue;
208
33.2k
}
long oox::BinaryInputStream::readValue<long>()
Line
Count
Source
203
6
{
204
6
    Type ornValue = Type();
205
6
    readMemory( &ornValue, static_cast< sal_Int32 >( sizeof( Type ) ), sizeof( Type ) );
206
6
    ByteOrderConverter::convertLittleEndian( ornValue );
207
6
    return ornValue;
208
6
}
Unexecuted instantiation: float oox::BinaryInputStream::readValue<float>()
Unexecuted instantiation: double oox::BinaryInputStream::readValue<double>()
209
210
template< typename Type >
211
sal_Int32 BinaryInputStream::readArray( Type* opnArray, sal_Int32 nElemCount )
212
960
{
213
960
    sal_Int32 nRet = 0;
214
960
    if( !mbEof )
215
685
    {
216
685
        sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int32 >( nElemCount, 0, SAL_MAX_INT32 / sizeof( Type ) ) * sizeof( Type );
217
685
        nRet = readMemory( opnArray, nReadSize, sizeof( Type ) ) / sizeof( Type );
218
685
        ByteOrderConverter::convertLittleEndianArray( opnArray, static_cast< size_t >( nRet ) );
219
685
    }
220
960
    return nRet;
221
960
}
int oox::BinaryInputStream::readArray<unsigned char>(unsigned char*, int)
Line
Count
Source
212
514
{
213
514
    sal_Int32 nRet = 0;
214
514
    if( !mbEof )
215
239
    {
216
239
        sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int32 >( nElemCount, 0, SAL_MAX_INT32 / sizeof( Type ) ) * sizeof( Type );
217
239
        nRet = readMemory( opnArray, nReadSize, sizeof( Type ) ) / sizeof( Type );
218
239
        ByteOrderConverter::convertLittleEndianArray( opnArray, static_cast< size_t >( nRet ) );
219
239
    }
220
514
    return nRet;
221
514
}
int oox::BinaryInputStream::readArray<unsigned short>(unsigned short*, int)
Line
Count
Source
212
446
{
213
446
    sal_Int32 nRet = 0;
214
446
    if( !mbEof )
215
446
    {
216
446
        sal_Int32 nReadSize = getLimitedValue< sal_Int32, sal_Int32 >( nElemCount, 0, SAL_MAX_INT32 / sizeof( Type ) ) * sizeof( Type );
217
446
        nRet = readMemory( opnArray, nReadSize, sizeof( Type ) ) / sizeof( Type );
218
446
        ByteOrderConverter::convertLittleEndianArray( opnArray, static_cast< size_t >( nRet ) );
219
446
    }
220
446
    return nRet;
221
446
}
222
223
template< typename Type >
224
sal_Int32 BinaryInputStream::readArray( ::std::vector< Type >& orVector, sal_Int32 nElemCount )
225
507
{
226
507
    orVector.resize( static_cast< size_t >( nElemCount ) );
227
507
    return orVector.empty() ? 0 : readArray(orVector.data(), nElemCount);
228
507
}
int oox::BinaryInputStream::readArray<unsigned char>(std::__1::vector<unsigned char, std::__1::allocator<unsigned char> >&, int)
Line
Count
Source
225
61
{
226
61
    orVector.resize( static_cast< size_t >( nElemCount ) );
227
61
    return orVector.empty() ? 0 : readArray(orVector.data(), nElemCount);
228
61
}
int oox::BinaryInputStream::readArray<unsigned short>(std::__1::vector<unsigned short, std::__1::allocator<unsigned short> >&, int)
Line
Count
Source
225
446
{
226
446
    orVector.resize( static_cast< size_t >( nElemCount ) );
227
446
    return orVector.empty() ? 0 : readArray(orVector.data(), nElemCount);
228
446
}
229
230
231
/** Wraps a UNO input stream and provides convenient access functions.
232
233
    The binary data in the stream is assumed to be in little-endian format.
234
 */
235
class OOX_DLLPUBLIC BinaryXInputStream final : public BinaryXSeekableStream, public BinaryInputStream
236
{
237
public:
238
    /** Constructs the wrapper object for the passed input stream.
239
240
        @param rxInStream
241
            The com.sun.star.io.XInputStream interface of the UNO input stream
242
            to be wrapped.
243
244
        @param bAutoClose
245
            True = automatically close the wrapped input stream on destruction
246
            of this wrapper or when close() is called.
247
     */
248
    explicit            BinaryXInputStream(
249
                            const css::uno::Reference< css::io::XInputStream >& rxInStrm,
250
                            bool bAutoClose );
251
252
    virtual             ~BinaryXInputStream() override;
253
254
    /** Closes the input stream. Does also close the wrapped UNO input stream
255
        if bAutoClose has been set to true in the constructor. */
256
    virtual void        close() override;
257
258
    /** Reads nBytes bytes to the passed sequence.
259
        @return  Number of bytes really read. */
260
    virtual sal_Int32   readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize = 1 ) override;
261
262
    /** Reads nBytes bytes to the (existing) buffer opMem.
263
        @return  Number of bytes really read. */
264
    virtual sal_Int32   readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize = 1 ) override;
265
266
    /** Seeks the stream forward by the passed number of bytes. This works for
267
        non-seekable streams too. */
268
    virtual void        skip( sal_Int32 nBytes, size_t nAtomSize = 1 ) override;
269
270
private:
271
    StreamDataSequence  maBuffer;       ///< Data buffer used in readMemory() function.
272
    css::uno::Reference< css::io::XInputStream >
273
                        mxInStrm;       ///< Reference to the input stream.
274
    bool                mbAutoClose;    ///< True = automatically close stream on destruction.
275
};
276
277
278
/** Wraps a StreamDataSequence and provides convenient access functions.
279
280
    The binary data in the stream is assumed to be in little-endian format.
281
 */
282
class OOX_DLLPUBLIC SequenceInputStream final : public SequenceSeekableStream, public BinaryInputStream
283
{
284
public:
285
    /** Constructs the wrapper object for the passed data sequence.
286
287
        @attention
288
            The passed data sequence MUST live at least as long as this stream
289
            wrapper. The data sequence MUST NOT be changed from outside as long
290
            as this stream wrapper is used to read from it.
291
     */
292
    explicit            SequenceInputStream( const StreamDataSequence& rData );
293
294
    /** Reads nBytes bytes to the passed sequence.
295
        @return  Number of bytes really read. */
296
    virtual sal_Int32   readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize = 1 ) override;
297
298
    /** Reads nBytes bytes to the (existing) buffer opMem.
299
        @return  Number of bytes really read. */
300
    virtual sal_Int32   readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize = 1 ) override;
301
302
    /** Seeks the stream forward by the passed number of bytes. This works for
303
        non-seekable streams too. */
304
    virtual void        skip( sal_Int32 nBytes, size_t nAtomSize = 1 ) override;
305
306
private:
307
    /** Returns the number of bytes available in the sequence for the passed byte count. */
308
    sal_Int32    getMaxBytes( sal_Int32 nBytes ) const
309
54
                            { return getLimitedValue< sal_Int32, sal_Int32 >( nBytes, 0, mpData->getLength() - mnPos ); }
310
};
311
312
313
/** Wraps a BinaryInputStream and provides access to a specific part of the
314
    stream data.
315
316
    Provides access to the stream data block starting at the current position
317
    of the stream, and with a specific length. If the wrapped stream is
318
    seekable, this wrapper will treat the position of the wrapped stream at
319
    construction time as position "0" (therefore the class name).
320
321
    The passed input stream MUST live at least as long as this stream wrapper.
322
    The stream MUST NOT be changed from outside as long as this stream wrapper
323
    is used to read from it.
324
 */
325
class RelativeInputStream final : public BinaryInputStream
326
{
327
public:
328
    /** Constructs the wrapper object for the passed stream.
329
330
        @param nSize
331
            If specified, restricts the amount of data that can be read from
332
            the passed input stream.
333
     */
334
    explicit            RelativeInputStream(
335
                            BinaryInputStream& rInStrm,
336
                            sal_Int64 nSize );
337
338
    /** Returns the size of the data block in the wrapped stream offered by
339
        this wrapper. */
340
    virtual sal_Int64   size() const override;
341
342
    /** Returns the current relative stream position. */
343
    virtual sal_Int64   tell() const override;
344
345
    /** Seeks the stream to the passed relative position, if the wrapped stream
346
        is seekable. */
347
    virtual void        seek( sal_Int64 nPos ) override;
348
349
    /** Closes the input stream but not the wrapped stream. */
350
    virtual void        close() override;
351
352
    /** Reads nBytes bytes to the passed sequence. Does not read out of the
353
        data block whose size has been specified on construction.
354
        @return  Number of bytes really read. */
355
    virtual sal_Int32   readData( StreamDataSequence& orData, sal_Int32 nBytes, size_t nAtomSize = 1 ) override;
356
357
    /** Reads nBytes bytes to the (existing) buffer opMem. Does not read out of
358
        the data block whose size has been specified on construction.
359
        @return  Number of bytes really read. */
360
    virtual sal_Int32   readMemory( void* opMem, sal_Int32 nBytes, size_t nAtomSize = 1 ) override;
361
362
    /** Seeks the stream forward by the passed number of bytes. This works for
363
        non-seekable streams too. Does not seek out of the data block. */
364
    virtual void        skip( sal_Int32 nBytes, size_t nAtomSize = 1 ) override;
365
366
private:
367
    /** Returns the number of bytes available in the sequence for the passed byte count. */
368
    sal_Int32    getMaxBytes( sal_Int32 nBytes ) const
369
0
                            { return getLimitedValue< sal_Int32, sal_Int64 >( nBytes, 0, mnSize - mnRelPos ); }
370
371
private:
372
    BinaryInputStream*  mpInStrm;
373
    sal_Int64           mnStartPos;
374
    sal_Int64           mnRelPos;
375
    sal_Int64           mnSize;
376
};
377
378
379
} // namespace oox
380
381
#endif
382
383
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */