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