merge the formfield patch from ooo-build
[ooovba.git] / io / source / TextInputStream / TextInputStream.cxx
blobbde9eb2f7d639aeebf77da60adc8877f2077f439
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: TextInputStream.cxx,v $
10 * $Revision: 1.15 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_io.hxx"
35 #include <string.h>
36 #include <osl/mutex.hxx>
37 #include <osl/diagnose.h>
39 #include <rtl/unload.h>
41 #include <uno/mapping.hxx>
43 #include <cppuhelper/factory.hxx>
44 #include <cppuhelper/implbase3.hxx>
45 #include <cppuhelper/implementationentry.hxx>
47 #include <rtl/textenc.h>
48 #include <rtl/tencinfo.h>
50 #include <com/sun/star/io/XTextInputStream.hpp>
51 #include <com/sun/star/io/XActiveDataSink.hpp>
52 #include <com/sun/star/lang/XServiceInfo.hpp>
55 #define IMPLEMENTATION_NAME "com.sun.star.comp.io.TextInputStream"
56 #define SERVICE_NAME "com.sun.star.io.TextInputStream"
58 using namespace ::osl;
59 using namespace ::rtl;
60 using namespace ::cppu;
61 using namespace ::com::sun::star::uno;
62 using namespace ::com::sun::star::lang;
63 using namespace ::com::sun::star::io;
64 using namespace ::com::sun::star::registry;
66 namespace io_TextInputStream
68 rtl_StandardModuleCount g_moduleCount = MODULE_COUNT_INIT;
70 //===========================================================================
71 // Implementation XTextInputStream
73 typedef WeakImplHelper3< XTextInputStream, XActiveDataSink, XServiceInfo > TextInputStreamHelper;
74 class OCommandEnvironment;
76 #define INITIAL_UNICODE_BUFFER_CAPACITY 0x100
77 #define READ_BYTE_COUNT 0x100
79 class OTextInputStream : public TextInputStreamHelper
81 Reference< XInputStream > mxStream;
83 // Encoding
84 OUString mEncoding;
85 sal_Bool mbEncodingInitialized;
86 rtl_TextToUnicodeConverter mConvText2Unicode;
87 rtl_TextToUnicodeContext mContextText2Unicode;
88 Sequence<sal_Int8> mSeqSource;
90 // Internal buffer for characters that are already converted successfully
91 sal_Unicode* mpBuffer;
92 sal_Int32 mnBufferSize;
93 sal_Int32 mnCharsInBuffer;
94 sal_Bool mbReachedEOF;
96 void implResizeBuffer( void );
97 OUString implReadString( const Sequence< sal_Unicode >& Delimiters,
98 sal_Bool bRemoveDelimiter, sal_Bool bFindLineEnd )
99 throw(IOException, RuntimeException);
100 sal_Int32 implReadNext() throw(IOException, RuntimeException);
102 public:
103 OTextInputStream();
104 virtual ~OTextInputStream();
106 // Methods XTextInputStream
107 virtual OUString SAL_CALL readLine( )
108 throw(IOException, RuntimeException);
109 virtual OUString SAL_CALL readString( const Sequence< sal_Unicode >& Delimiters, sal_Bool bRemoveDelimiter )
110 throw(IOException, RuntimeException);
111 virtual sal_Bool SAL_CALL isEOF( )
112 throw(IOException, RuntimeException);
113 virtual void SAL_CALL setEncoding( const OUString& Encoding ) throw(RuntimeException);
115 // Methods XInputStream
116 virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
117 throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException);
118 virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
119 throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException);
120 virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
121 throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException);
122 virtual sal_Int32 SAL_CALL available( )
123 throw(NotConnectedException, IOException, RuntimeException);
124 virtual void SAL_CALL closeInput( )
125 throw(NotConnectedException, IOException, RuntimeException);
127 // Methods XActiveDataSink
128 virtual void SAL_CALL setInputStream( const Reference< XInputStream >& aStream )
129 throw(RuntimeException);
130 virtual Reference< XInputStream > SAL_CALL getInputStream()
131 throw(RuntimeException);
133 // Methods XServiceInfo
134 virtual OUString SAL_CALL getImplementationName() throw();
135 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw();
136 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw();
139 OTextInputStream::OTextInputStream()
140 : mSeqSource( READ_BYTE_COUNT ), mpBuffer( NULL ), mnBufferSize( 0 )
141 , mnCharsInBuffer( 0 ), mbReachedEOF( sal_False )
143 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
144 mbEncodingInitialized = false;
147 OTextInputStream::~OTextInputStream()
149 if( mbEncodingInitialized )
151 rtl_destroyUnicodeToTextContext( mConvText2Unicode, mContextText2Unicode );
152 rtl_destroyUnicodeToTextConverter( mConvText2Unicode );
154 g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
157 void OTextInputStream::implResizeBuffer( void )
159 sal_Int32 mnNewBufferSize = mnBufferSize * 2;
160 sal_Unicode* pNewBuffer = new sal_Unicode[ mnNewBufferSize ];
161 memcpy( pNewBuffer, mpBuffer, mnCharsInBuffer * sizeof( sal_Unicode ) );
162 mpBuffer = pNewBuffer;
163 mnBufferSize = mnNewBufferSize;
167 //===========================================================================
168 // XTextInputStream
170 OUString OTextInputStream::readLine( )
171 throw(IOException, RuntimeException)
173 static Sequence< sal_Unicode > aDummySeq;
174 return implReadString( aDummySeq, sal_True, sal_True );
177 OUString OTextInputStream::readString( const Sequence< sal_Unicode >& Delimiters, sal_Bool )
178 throw(IOException, RuntimeException)
180 return implReadString( Delimiters, sal_True, sal_False );
183 sal_Bool OTextInputStream::isEOF()
184 throw(IOException, RuntimeException)
186 sal_Bool bRet = sal_False;
187 if( mnCharsInBuffer == 0 && mbReachedEOF )
188 bRet = sal_True;
189 return bRet;
193 OUString OTextInputStream::implReadString( const Sequence< sal_Unicode >& Delimiters,
194 sal_Bool bRemoveDelimiter, sal_Bool bFindLineEnd )
195 throw(IOException, RuntimeException)
197 OUString aRetStr;
198 if( !mbEncodingInitialized )
200 OUString aUtf8Str( RTL_CONSTASCII_USTRINGPARAM("utf8") );
201 setEncoding( aUtf8Str );
203 if( !mbEncodingInitialized )
204 return aRetStr;
206 if( !mpBuffer )
208 mnBufferSize = INITIAL_UNICODE_BUFFER_CAPACITY;
209 mpBuffer = new sal_Unicode[ mnBufferSize ];
212 // Only for bFindLineEnd
213 sal_Unicode cLineEndChar1 = 0x0D;
214 sal_Unicode cLineEndChar2 = 0x0A;
216 sal_Int32 nBufferReadPos = 0;
217 sal_Int32 nCopyLen = 0;
218 sal_Bool bFound = sal_False;
219 sal_Bool bFoundFirstLineEndChar = sal_False;
220 sal_Unicode cFirstLineEndChar = 0;
221 const sal_Unicode* pDelims = Delimiters.getConstArray();
222 const sal_Int32 nDelimCount = Delimiters.getLength();
223 while( !bFound )
225 // Still characters available?
226 if( nBufferReadPos == mnCharsInBuffer )
228 // Already reached EOF? Then we can't read any more
229 if( mbReachedEOF )
230 break;
232 // No, so read new characters
233 if( !implReadNext() )
234 break;
237 // Now there should be characters available
238 // (otherwise the loop should have been breaked before)
239 sal_Unicode c = mpBuffer[ nBufferReadPos++ ];
241 if( bFindLineEnd )
243 if( bFoundFirstLineEndChar )
245 bFound = sal_True;
246 nCopyLen = nBufferReadPos - 2;
247 if( c == cLineEndChar1 || c == cLineEndChar2 )
249 // Same line end char -> new line break
250 if( c == cFirstLineEndChar )
252 nBufferReadPos--;
255 else
257 // No second line end char
258 nBufferReadPos--;
261 else if( c == cLineEndChar1 || c == cLineEndChar2 )
263 bFoundFirstLineEndChar = sal_True;
264 cFirstLineEndChar = c;
267 else
269 for( sal_Int32 i = 0 ; i < nDelimCount ; i++ )
271 if( c == pDelims[ i ] )
273 bFound = sal_True;
274 nCopyLen = nBufferReadPos;
275 if( bRemoveDelimiter )
276 nCopyLen--;
282 // Nothing found? Return all
283 if( !nCopyLen && !bFound && mbReachedEOF )
284 nCopyLen = nBufferReadPos;
286 // Create string
287 if( nCopyLen )
288 aRetStr = OUString( mpBuffer, nCopyLen );
290 // Copy rest of buffer
291 memmove( mpBuffer, mpBuffer + nBufferReadPos,
292 (mnCharsInBuffer - nBufferReadPos) * sizeof( sal_Unicode ) );
293 mnCharsInBuffer -= nBufferReadPos;
295 return aRetStr;
299 sal_Int32 OTextInputStream::implReadNext()
300 throw(IOException, RuntimeException)
302 sal_Int32 nFreeBufferSize = mnBufferSize - mnCharsInBuffer;
303 if( nFreeBufferSize < READ_BYTE_COUNT )
304 implResizeBuffer();
305 nFreeBufferSize = mnBufferSize - mnCharsInBuffer;
309 sal_Int32 nBytesToRead = READ_BYTE_COUNT;
310 sal_Int32 nRead = mxStream->readSomeBytes( mSeqSource, nBytesToRead );
311 sal_Int32 nTotalRead = nRead;
312 if( nRead < nBytesToRead )
313 mbReachedEOF = sal_True;
315 // Try to convert
316 sal_uInt32 uiInfo;
317 sal_Size nSrcCvtBytes = 0;
318 sal_Size nTargetCount = 0;
319 sal_Size nSourceCount = 0;
320 while( sal_True )
322 const sal_Int8 *pbSource = mSeqSource.getConstArray();
324 // All invalid characters are transformed to the unicode undefined char
325 nTargetCount += rtl_convertTextToUnicode(
326 mConvText2Unicode,
327 mContextText2Unicode,
328 (const sal_Char*) &( pbSource[nSourceCount] ),
329 nTotalRead - nSourceCount,
330 mpBuffer + mnCharsInBuffer + nTargetCount,
331 nFreeBufferSize - nTargetCount,
332 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT |
333 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
334 RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT,
335 &uiInfo,
336 &nSrcCvtBytes );
337 nSourceCount += nSrcCvtBytes;
339 sal_Bool bCont = sal_False;
340 if( uiInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL )
342 implResizeBuffer();
343 bCont = sal_True;
346 if( uiInfo & RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL )
348 // read next byte
349 static Sequence< sal_Int8 > aOneByteSeq( 1 );
350 nRead = mxStream->readSomeBytes( aOneByteSeq, 1 );
351 if( nRead == 0 )
353 mbReachedEOF = sal_True;
354 break;
357 sal_Int32 nOldLen = mSeqSource.getLength();
358 nTotalRead++;
359 if( nTotalRead > nOldLen )
361 mSeqSource.realloc( nTotalRead );
363 mSeqSource.getArray()[ nOldLen ] = aOneByteSeq.getConstArray()[ 0 ];
364 pbSource = mSeqSource.getConstArray();
365 bCont = sal_True;
368 if( bCont )
369 continue;
370 break;
373 mnCharsInBuffer += nTargetCount;
374 return nTargetCount;
376 catch( NotConnectedException& )
378 throw IOException();
379 //throw IOException( L"OTextInputStream::implReadString failed" );
381 catch( BufferSizeExceededException& )
383 throw IOException();
387 void OTextInputStream::setEncoding( const OUString& Encoding )
388 throw(RuntimeException)
390 OString aOEncodingStr = OUStringToOString( Encoding, RTL_TEXTENCODING_ASCII_US );
391 rtl_TextEncoding encoding = rtl_getTextEncodingFromMimeCharset( aOEncodingStr.getStr() );
392 if( RTL_TEXTENCODING_DONTKNOW == encoding )
393 return;
395 mbEncodingInitialized = true;
396 mConvText2Unicode = rtl_createTextToUnicodeConverter( encoding );
397 mContextText2Unicode = rtl_createTextToUnicodeContext( mConvText2Unicode );
398 mEncoding = Encoding;
401 //===========================================================================
402 // XInputStream
404 sal_Int32 OTextInputStream::readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
405 throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
407 return mxStream->readBytes( aData, nBytesToRead );
410 sal_Int32 OTextInputStream::readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
411 throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
413 return mxStream->readSomeBytes( aData, nMaxBytesToRead );
416 void OTextInputStream::skipBytes( sal_Int32 nBytesToSkip )
417 throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
419 mxStream->skipBytes( nBytesToSkip );
422 sal_Int32 OTextInputStream::available( )
423 throw(NotConnectedException, IOException, RuntimeException)
425 return mxStream->available();
428 void OTextInputStream::closeInput( )
429 throw(NotConnectedException, IOException, RuntimeException)
431 mxStream->closeInput();
435 //===========================================================================
436 // XActiveDataSink
438 void OTextInputStream::setInputStream( const Reference< XInputStream >& aStream )
439 throw(RuntimeException)
441 mxStream = aStream;
444 Reference< XInputStream > OTextInputStream::getInputStream()
445 throw(RuntimeException)
447 return mxStream;
451 Reference< XInterface > SAL_CALL TextInputStream_CreateInstance( const Reference< XComponentContext > &)
453 return Reference < XInterface >( ( OWeakObject * ) new OTextInputStream() );
456 OUString TextInputStream_getImplementationName()
458 return OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME ) );
461 Sequence< OUString > TextInputStream_getSupportedServiceNames()
463 static Sequence < OUString > *pNames = 0;
464 if( ! pNames )
466 MutexGuard guard( Mutex::getGlobalMutex() );
467 if( !pNames )
469 static Sequence< OUString > seqNames(1);
470 seqNames.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICE_NAME ) );
471 pNames = &seqNames;
474 return *pNames;
477 OUString OTextInputStream::getImplementationName() throw()
479 return TextInputStream_getImplementationName();
482 sal_Bool OTextInputStream::supportsService(const OUString& ServiceName) throw()
484 Sequence< OUString > aSNL = getSupportedServiceNames();
485 const OUString * pArray = aSNL.getConstArray();
487 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
488 if( pArray[i] == ServiceName )
489 return sal_True;
491 return sal_False;
494 Sequence< OUString > OTextInputStream::getSupportedServiceNames(void) throw()
496 return TextInputStream_getSupportedServiceNames();
501 using namespace io_TextInputStream;
503 static struct ImplementationEntry g_entries[] =
506 TextInputStream_CreateInstance, TextInputStream_getImplementationName ,
507 TextInputStream_getSupportedServiceNames, createSingleComponentFactory ,
508 &g_moduleCount.modCnt , 0
510 { 0, 0, 0, 0, 0, 0 }
513 extern "C"
515 sal_Bool SAL_CALL component_canUnload( TimeValue *pTime )
517 return g_moduleCount.canUnload( &g_moduleCount , pTime );
520 //==================================================================================================
521 void SAL_CALL component_getImplementationEnvironment(
522 const sal_Char ** ppEnvTypeName, uno_Environment ** )
524 *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
526 //==================================================================================================
527 sal_Bool SAL_CALL component_writeInfo(
528 void * pServiceManager, void * pRegistryKey )
530 return component_writeInfoHelper( pServiceManager, pRegistryKey, g_entries );
532 //==================================================================================================
533 void * SAL_CALL component_getFactory(
534 const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
536 return component_getFactoryHelper( pImplName, pServiceManager, pRegistryKey , g_entries );