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