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 75 UnoBinaryInputStream::UnoBinaryInputStream( BinaryInputStream& rInStrm ) : 76 mpInStrm( &rInStrm ) 77 { 78 } 79 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 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 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 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 107 void SAL_CALL UnoBinaryInputStream::closeInput() throw (NotConnectedException, IOException, RuntimeException) 108 { 109 ensureConnected(); 110 mpInStrm->close(); 111 mpInStrm = 0; 112 } 113 114 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 124 TextInputStream::TextInputStream( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStrm, rtl_TextEncoding eTextEnc ) 125 { 126 init( rxContext, rxInStrm, eTextEnc ); 127 } 128 129 TextInputStream::TextInputStream( const Reference< XComponentContext >& rxContext, BinaryInputStream& rInStrm, rtl_TextEncoding eTextEnc ) 130 { 131 init( rxContext, new UnoBinaryInputStream( rInStrm ), eTextEnc ); 132 } 133 134 TextInputStream::~TextInputStream() 135 { 136 } 137 138 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 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 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 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_getMimeCharsetFromTextEncoding( 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 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 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