Coverage Report

Created: 2026-11-06 11:29

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/oox/source/helper/textinputstream.cxx
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
#include <oox/helper/textinputstream.hxx>
21
22
#include <com/sun/star/io/NotConnectedException.hpp>
23
#include <com/sun/star/io/TextInputStream.hpp>
24
#include <cppuhelper/implbase.hxx>
25
#include <osl/diagnose.h>
26
#include <rtl/tencinfo.h>
27
#include <oox/helper/binaryinputstream.hxx>
28
29
namespace oox {
30
31
using namespace ::com::sun::star::io;
32
using namespace ::com::sun::star::lang;
33
using namespace ::com::sun::star::uno;
34
35
namespace {
36
37
/** Implementation of a UNO input stream wrapping a binary input stream.
38
 */
39
class UnoBinaryInputStream : public ::cppu::WeakImplHelper< XInputStream >
40
{
41
public:
42
    explicit            UnoBinaryInputStream( BinaryInputStream& rInStrm );
43
44
    virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& rData, sal_Int32 nBytesToRead ) override;
45
    virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead ) override;
46
    virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) override;
47
    virtual sal_Int32 SAL_CALL available() override;
48
    virtual void SAL_CALL closeInput() override;
49
50
private:
51
    /// @throws NotConnectedException
52
    void                ensureConnected() const;
53
54
private:
55
    BinaryInputStream*  mpInStrm;
56
};
57
58
UnoBinaryInputStream::UnoBinaryInputStream( BinaryInputStream& rInStrm ) :
59
13
    mpInStrm( &rInStrm )
60
13
{
61
13
}
62
63
sal_Int32 SAL_CALL UnoBinaryInputStream::readBytes( Sequence< sal_Int8 >& rData, sal_Int32 nBytesToRead )
64
0
{
65
0
    ensureConnected();
66
0
    return mpInStrm->readData( rData, nBytesToRead );
67
0
}
68
69
sal_Int32 SAL_CALL UnoBinaryInputStream::readSomeBytes( Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead )
70
32
{
71
32
    ensureConnected();
72
32
    return mpInStrm->readData( rData, nMaxBytesToRead );
73
32
}
74
75
void SAL_CALL UnoBinaryInputStream::skipBytes( sal_Int32 nBytesToSkip )
76
0
{
77
0
    ensureConnected();
78
0
    mpInStrm->skip( nBytesToSkip );
79
0
}
80
81
sal_Int32 SAL_CALL UnoBinaryInputStream::available()
82
0
{
83
0
    ensureConnected();
84
0
    throw RuntimeException( u"Functionality not supported"_ustr, Reference< XInputStream >() );
85
0
}
86
87
void SAL_CALL UnoBinaryInputStream::closeInput()
88
0
{
89
0
    ensureConnected();
90
0
    mpInStrm->close();
91
0
    mpInStrm = nullptr;
92
0
}
93
94
void UnoBinaryInputStream::ensureConnected() const
95
32
{
96
32
    if( !mpInStrm )
97
0
        throw NotConnectedException( u"Stream closed"_ustr );
98
32
}
99
100
} // namespace
101
102
TextInputStream::TextInputStream( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStrm, rtl_TextEncoding eTextEnc )
103
0
{
104
0
    init( rxContext, rxInStrm, eTextEnc );
105
0
}
106
107
TextInputStream::TextInputStream( const Reference< XComponentContext >& rxContext, BinaryInputStream& rInStrm, rtl_TextEncoding eTextEnc )
108
13
{
109
13
    init( rxContext, new UnoBinaryInputStream( rInStrm ), eTextEnc );
110
13
}
111
112
TextInputStream::~TextInputStream()
113
13
{
114
13
}
115
116
bool TextInputStream::isEof() const
117
151
{
118
151
    if( mxTextStrm.is() ) try
119
151
    {
120
151
        return mxTextStrm->isEOF();
121
151
    }
122
151
    catch (const Exception&)
123
151
    {
124
0
    }
125
0
    return true;
126
151
}
127
128
OUString TextInputStream::readLine()
129
148
{
130
148
    if( mxTextStrm.is() ) try
131
148
    {
132
        /*  The function createFinalString() adds a character that may have
133
            been buffered in the previous call of readToChar() (see below). */
134
148
        return createFinalString( mxTextStrm->readLine() );
135
148
    }
136
148
    catch (const Exception&)
137
148
    {
138
0
        mxTextStrm.clear();
139
0
    }
140
0
    return OUString();
141
148
}
142
143
OUString TextInputStream::readToChar( sal_Unicode cChar, bool bIncludeChar )
144
0
{
145
0
    if( mxTextStrm.is() ) try
146
0
    {
147
0
        Sequence< sal_Unicode > aDelimiters{ cChar };
148
        /*  Always get the delimiter character from the UNO text input stream.
149
            In difference to this implementation, it will not return it in the
150
            next call but silently skip it. If caller specifies to exclude the
151
            character in this call, it will be returned in the next call of one
152
            of the own member functions. The function createFinalString() adds
153
            a character that has been buffered in the previous call. */
154
0
        OUString aString = createFinalString( mxTextStrm->readString( aDelimiters, false ) );
155
        // remove last character from string and remember it for next call
156
0
        if( !bIncludeChar && !aString.isEmpty() && (aString[ aString.getLength() - 1 ] == cChar) )
157
0
        {
158
0
            mcPendingChar = cChar;
159
0
            aString = aString.copy( 0, aString.getLength() - 1 );
160
0
        }
161
0
        return aString;
162
0
    }
163
0
    catch (const Exception&)
164
0
    {
165
0
        mxTextStrm.clear();
166
0
    }
167
0
    return OUString();
168
0
}
169
170
Reference< XTextInputStream2 > TextInputStream::createXTextInputStream(
171
        const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStrm, rtl_TextEncoding eTextEnc )
172
448
{
173
448
    Reference< XTextInputStream2 > xTextStrm;
174
448
    const char* pcCharset = rtl_getBestMimeCharsetFromTextEncoding( eTextEnc );
175
448
    OSL_ENSURE( pcCharset, "TextInputStream::createXTextInputStream - unsupported text encoding" );
176
448
    if( rxContext.is() && rxInStrm.is() && pcCharset ) try
177
329
    {
178
329
        xTextStrm = css::io::TextInputStream::create( rxContext );
179
329
        xTextStrm->setInputStream( rxInStrm );
180
329
        xTextStrm->setEncoding( OUString::createFromAscii( pcCharset ) );
181
329
    }
182
329
    catch (const Exception&)
183
329
    {
184
0
    }
185
448
    return xTextStrm;
186
448
}
187
188
// private --------------------------------------------------------------------
189
190
OUString TextInputStream::createFinalString( const OUString& rString )
191
148
{
192
148
    if( mcPendingChar == 0 )
193
148
        return rString;
194
195
0
    OUString aString = OUStringChar( mcPendingChar ) + rString;
196
0
    mcPendingChar = 0;
197
0
    return aString;
198
148
}
199
200
void TextInputStream::init( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStrm, rtl_TextEncoding eTextEnc )
201
13
{
202
13
    mcPendingChar = 0;
203
13
    mxTextStrm = createXTextInputStream( rxContext, rxInStrm, eTextEnc );
204
13
}
205
206
} // namespace oox
207
208
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */