1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include "oox/helper/textinputstream.hxx" 29 30 #include <com/sun/star/io/XActiveDataSink.hpp> 31 #include <com/sun/star/io/XTextInputStream.hpp> 32 #include <cppuhelper/implbase1.hxx> 33 #include <rtl/tencinfo.h> 34 #include "oox/helper/binaryinputstream.hxx" 35 36 namespace oox { 37 38 // ============================================================================ 39 40 using namespace ::com::sun::star::io; 41 using namespace ::com::sun::star::lang; 42 using namespace ::com::sun::star::uno; 43 44 using ::rtl::OUString; 45 46 // ============================================================================ 47 48 namespace { 49 50 typedef ::cppu::WeakImplHelper1< XInputStream > UnoBinaryInputStream_BASE; 51 52 /** Implementation of a UNO input stream wrapping a binary input stream. 53 */ 54 class UnoBinaryInputStream : public UnoBinaryInputStream_BASE 55 { 56 public: 57 explicit UnoBinaryInputStream( BinaryInputStream& rInStrm ); 58 59 virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& rData, sal_Int32 nBytesToRead ) 60 throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException); 61 virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead ) 62 throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException); 63 virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) 64 throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException); 65 virtual sal_Int32 SAL_CALL available() 66 throw (NotConnectedException, IOException, RuntimeException); 67 virtual void SAL_CALL closeInput() 68 throw (NotConnectedException, IOException, RuntimeException); 69 70 private: 71 void ensureConnected() const throw (NotConnectedException); 72 73 private: 74 BinaryInputStream* mpInStrm; 75 }; 76 77 // ---------------------------------------------------------------------------- 78 79 UnoBinaryInputStream::UnoBinaryInputStream( BinaryInputStream& rInStrm ) : 80 mpInStrm( &rInStrm ) 81 { 82 } 83 84 sal_Int32 SAL_CALL UnoBinaryInputStream::readBytes( Sequence< sal_Int8 >& rData, sal_Int32 nBytesToRead ) 85 throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) 86 { 87 ensureConnected(); 88 return mpInStrm->readData( rData, nBytesToRead, 1 ); 89 } 90 91 sal_Int32 SAL_CALL UnoBinaryInputStream::readSomeBytes( Sequence< sal_Int8 >& rData, sal_Int32 nMaxBytesToRead ) 92 throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) 93 { 94 ensureConnected(); 95 return mpInStrm->readData( rData, nMaxBytesToRead, 1 ); 96 } 97 98 void SAL_CALL UnoBinaryInputStream::skipBytes( sal_Int32 nBytesToSkip ) 99 throw (NotConnectedException, BufferSizeExceededException, IOException, RuntimeException) 100 { 101 ensureConnected(); 102 mpInStrm->skip( nBytesToSkip, 1 ); 103 } 104 105 sal_Int32 SAL_CALL UnoBinaryInputStream::available() throw (NotConnectedException, IOException, RuntimeException) 106 { 107 ensureConnected(); 108 throw RuntimeException( CREATE_OUSTRING( "Functionality not supported" ), Reference< XInputStream >() ); 109 } 110 111 void SAL_CALL UnoBinaryInputStream::closeInput() throw (NotConnectedException, IOException, RuntimeException) 112 { 113 ensureConnected(); 114 mpInStrm->close(); 115 mpInStrm = 0; 116 } 117 118 void UnoBinaryInputStream::ensureConnected() const throw (NotConnectedException) 119 { 120 if( !mpInStrm ) 121 throw NotConnectedException( CREATE_OUSTRING( "Stream closed" ), Reference< XInterface >() ); 122 } 123 124 } // namespace 125 126 // ============================================================================ 127 128 TextInputStream::TextInputStream( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStrm, rtl_TextEncoding eTextEnc ) 129 { 130 init( rxContext, rxInStrm, eTextEnc ); 131 } 132 133 TextInputStream::TextInputStream( const Reference< XComponentContext >& rxContext, BinaryInputStream& rInStrm, rtl_TextEncoding eTextEnc ) 134 { 135 init( rxContext, new UnoBinaryInputStream( rInStrm ), eTextEnc ); 136 } 137 138 TextInputStream::~TextInputStream() 139 { 140 } 141 142 bool TextInputStream::isEof() const 143 { 144 if( mxTextStrm.is() ) try 145 { 146 return mxTextStrm->isEOF(); 147 } 148 catch( Exception& ) 149 { 150 } 151 return true; 152 } 153 154 OUString TextInputStream::readLine() 155 { 156 if( mxTextStrm.is() ) try 157 { 158 /* The function createFinalString() adds a character that may have 159 been buffered in the previous call of readToChar() (see below). */ 160 return createFinalString( mxTextStrm->readLine() ); 161 } 162 catch( Exception& ) 163 { 164 mxTextStrm.clear(); 165 } 166 return OUString(); 167 } 168 169 OUString TextInputStream::readToChar( sal_Unicode cChar, bool bIncludeChar ) 170 { 171 if( mxTextStrm.is() ) try 172 { 173 Sequence< sal_Unicode > aDelimiters( 1 ); 174 aDelimiters[ 0 ] = cChar; 175 /* Always get the delimiter character from the UNO text input stream. 176 In difference to this implementation, it will not return it in the 177 next call but silently skip it. If caller specifies to exclude the 178 character in this call, it will be returned in the next call of one 179 of the own member functions. The function createFinalString() adds 180 a character that has been buffered in the previous call. */ 181 OUString aString = createFinalString( mxTextStrm->readString( aDelimiters, sal_False ) ); 182 // remove last character from string and remember it for next call 183 if( !bIncludeChar && (aString.getLength() > 0) && (aString[ aString.getLength() - 1 ] == cChar) ) 184 { 185 mcPendingChar = cChar; 186 aString = aString.copy( 0, aString.getLength() - 1 ); 187 } 188 return aString; 189 } 190 catch( Exception& ) 191 { 192 mxTextStrm.clear(); 193 } 194 return OUString(); 195 } 196 197 /*static*/ Reference< XTextInputStream > TextInputStream::createXTextInputStream( 198 const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStrm, rtl_TextEncoding eTextEnc ) 199 { 200 Reference< XTextInputStream > xTextStrm; 201 const char* pcCharset = rtl_getMimeCharsetFromTextEncoding( eTextEnc ); 202 OSL_ENSURE( pcCharset, "TextInputStream::createXTextInputStream - unsupported text encoding" ); 203 if( rxContext.is() && rxInStrm.is() && pcCharset ) try 204 { 205 Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); 206 Reference< XActiveDataSink > xDataSink( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TextInputStream" ) ), UNO_QUERY_THROW ); 207 xDataSink->setInputStream( rxInStrm ); 208 xTextStrm.set( xDataSink, UNO_QUERY_THROW ); 209 xTextStrm->setEncoding( OUString::createFromAscii( pcCharset ) ); 210 } 211 catch( Exception& ) 212 { 213 } 214 return xTextStrm; 215 } 216 217 // private -------------------------------------------------------------------- 218 219 OUString TextInputStream::createFinalString( const OUString& rString ) 220 { 221 if( mcPendingChar == 0 ) 222 return rString; 223 224 OUString aString = OUString( mcPendingChar ) + rString; 225 mcPendingChar = 0; 226 return aString; 227 } 228 229 void TextInputStream::init( const Reference< XComponentContext >& rxContext, const Reference< XInputStream >& rxInStrm, rtl_TextEncoding eTextEnc ) 230 { 231 mcPendingChar = 0; 232 mxTextStrm = createXTextInputStream( rxContext, rxInStrm, eTextEnc ); 233 } 234 235 // ============================================================================ 236 237 } // namespace oox 238