1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: TextOutputStream.cxx,v $
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 <osl/mutex.hxx>
36 #include <osl/diagnose.h>
38 #include <uno/mapping.hxx>
40 #include <cppuhelper/factory.hxx>
41 #include <cppuhelper/implbase3.hxx>
42 #include <cppuhelper/implementationentry.hxx>
44 #include <rtl/textenc.h>
45 #include <rtl/tencinfo.h>
46 #include <rtl/unload.h>
48 #include <com/sun/star/io/XTextOutputStream.hpp>
49 #include <com/sun/star/io/XActiveDataSource.hpp>
50 #include <com/sun/star/lang/XServiceInfo.hpp>
53 #define IMPLEMENTATION_NAME "com.sun.star.comp.io.TextOutputStream"
54 #define SERVICE_NAME "com.sun.star.io.TextOutputStream"
56 using namespace ::osl
;
57 using namespace ::rtl
;
58 using namespace ::cppu
;
59 using namespace ::com::sun::star::uno
;
60 using namespace ::com::sun::star::lang
;
61 using namespace ::com::sun::star::io
;
62 using namespace ::com::sun::star::registry
;
64 namespace io_TextOutputStream
66 rtl_StandardModuleCount g_moduleCount
= MODULE_COUNT_INIT
;
67 //===========================================================================
68 // Implementation XTextOutputStream
70 typedef WeakImplHelper3
< XTextOutputStream
, XActiveDataSource
, XServiceInfo
> TextOutputStreamHelper
;
71 class OCommandEnvironment
;
73 class OTextOutputStream
: public TextOutputStreamHelper
75 Reference
< XOutputStream
> mxStream
;
79 sal_Bool mbEncodingInitialized
;
80 rtl_UnicodeToTextConverter mConvUnicode2Text
;
81 rtl_UnicodeToTextContext mContextUnicode2Text
;
83 Sequence
<sal_Int8
> implConvert( const OUString
& rSource
);
89 // Methods XTextOutputStream
90 virtual void SAL_CALL
writeString( const OUString
& aString
)
91 throw(IOException
, RuntimeException
);
92 virtual void SAL_CALL
setEncoding( const OUString
& Encoding
)
93 throw(RuntimeException
);
95 // Methods XOutputStream
96 virtual void SAL_CALL
writeBytes( const Sequence
< sal_Int8
>& aData
)
97 throw(NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
);
98 virtual void SAL_CALL
flush( )
99 throw(NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
);
100 virtual void SAL_CALL
closeOutput( )
101 throw(NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
);
103 // Methods XActiveDataSource
104 virtual void SAL_CALL
setOutputStream( const Reference
< XOutputStream
>& aStream
)
105 throw(RuntimeException
);
106 virtual Reference
< XOutputStream
> SAL_CALL
getOutputStream( )
107 throw(RuntimeException
);
109 // Methods XServiceInfo
110 virtual OUString SAL_CALL
getImplementationName() throw();
111 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames(void) throw();
112 virtual sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
) throw();
115 OTextOutputStream::OTextOutputStream()
117 mbEncodingInitialized
= false;
120 OTextOutputStream::~OTextOutputStream()
122 if( mbEncodingInitialized
)
124 rtl_destroyUnicodeToTextContext( mConvUnicode2Text
, mContextUnicode2Text
);
125 rtl_destroyUnicodeToTextConverter( mConvUnicode2Text
);
129 Sequence
<sal_Int8
> OTextOutputStream::implConvert( const OUString
& rSource
)
131 const sal_Unicode
*puSource
= rSource
.getStr();
132 sal_Int32 nSourceSize
= rSource
.getLength();
134 sal_Size nTargetCount
= 0;
135 sal_Size nSourceCount
= 0;
138 sal_Size nSrcCvtChars
;
140 // take nSourceSize * 3 as preference
141 // this is an upper boundary for converting to utf8,
142 // which most often used as the target.
143 sal_Int32 nSeqSize
= nSourceSize
* 3;
145 Sequence
<sal_Int8
> seqText( nSeqSize
);
146 sal_Char
*pTarget
= (sal_Char
*) seqText
.getArray();
149 nTargetCount
+= rtl_convertUnicodeToText(
151 mContextUnicode2Text
,
152 &( puSource
[nSourceCount
] ),
153 nSourceSize
- nSourceCount
,
154 &( pTarget
[nTargetCount
] ),
155 nSeqSize
- nTargetCount
,
156 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT
|
157 RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT
,
160 nSourceCount
+= nSrcCvtChars
;
162 if( uiInfo
& RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL
)
165 seqText
.realloc( nSeqSize
); // double array size
166 pTarget
= (sal_Char
*) seqText
.getArray();
172 // reduce the size of the buffer (fast, no copy necessary)
173 seqText
.realloc( nTargetCount
);
178 //===========================================================================
181 void OTextOutputStream::writeString( const OUString
& aString
)
182 throw(IOException
, RuntimeException
)
184 if( !mbEncodingInitialized
)
186 OUString
aUtf8Str( RTL_CONSTASCII_USTRINGPARAM("utf8") );
187 setEncoding( aUtf8Str
);
189 if( !mbEncodingInitialized
)
192 Sequence
<sal_Int8
> aByteSeq
= implConvert( aString
);
193 mxStream
->writeBytes( aByteSeq
);
196 void OTextOutputStream::setEncoding( const OUString
& Encoding
)
197 throw(RuntimeException
)
199 OString aOEncodingStr
= OUStringToOString( Encoding
, RTL_TEXTENCODING_ASCII_US
);
200 rtl_TextEncoding encoding
= rtl_getTextEncodingFromMimeCharset( aOEncodingStr
.getStr() );
201 if( RTL_TEXTENCODING_DONTKNOW
== encoding
)
204 mbEncodingInitialized
= true;
205 mConvUnicode2Text
= rtl_createUnicodeToTextConverter( encoding
);
206 mContextUnicode2Text
= rtl_createUnicodeToTextContext( mConvUnicode2Text
);
207 mEncoding
= Encoding
;
210 //===========================================================================
212 void OTextOutputStream::writeBytes( const Sequence
< sal_Int8
>& aData
)
213 throw(NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
215 mxStream
->writeBytes( aData
);
218 void OTextOutputStream::flush( )
219 throw(NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
224 void OTextOutputStream::closeOutput( )
225 throw(NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
227 mxStream
->closeOutput();
231 //===========================================================================
234 void OTextOutputStream::setOutputStream( const Reference
< XOutputStream
>& aStream
)
235 throw(RuntimeException
)
240 Reference
< XOutputStream
> OTextOutputStream::getOutputStream()
241 throw(RuntimeException
)
247 Reference
< XInterface
> SAL_CALL
TextOutputStream_CreateInstance( const Reference
< XComponentContext
> &)
249 return Reference
< XInterface
>( ( OWeakObject
* ) new OTextOutputStream() );
252 OUString
TextOutputStream_getImplementationName() SAL_THROW( () )
254 return OUString( RTL_CONSTASCII_USTRINGPARAM( IMPLEMENTATION_NAME
) );
258 Sequence
< OUString
> TextOutputStream_getSupportedServiceNames()
260 static Sequence
< OUString
> *pNames
= 0;
263 MutexGuard
guard( Mutex::getGlobalMutex() );
266 static Sequence
< OUString
> seqNames(1);
267 seqNames
.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICE_NAME
) );
274 OUString
OTextOutputStream::getImplementationName() throw()
276 return TextOutputStream_getImplementationName();
279 sal_Bool
OTextOutputStream::supportsService(const OUString
& ServiceName
) throw()
281 Sequence
< OUString
> aSNL
= getSupportedServiceNames();
282 const OUString
* pArray
= aSNL
.getConstArray();
284 for( sal_Int32 i
= 0; i
< aSNL
.getLength(); i
++ )
285 if( pArray
[i
] == ServiceName
)
291 Sequence
< OUString
> OTextOutputStream::getSupportedServiceNames(void) throw()
293 return TextOutputStream_getSupportedServiceNames();
299 using namespace io_TextOutputStream
;
301 static struct ImplementationEntry g_entries
[] =
304 TextOutputStream_CreateInstance
, TextOutputStream_getImplementationName
,
305 TextOutputStream_getSupportedServiceNames
, createSingleComponentFactory
,
306 &g_moduleCount
.modCnt
, 0
313 sal_Bool SAL_CALL
component_canUnload( TimeValue
*pTime
)
315 return g_moduleCount
.canUnload( &g_moduleCount
, pTime
);
318 //==================================================================================================
319 void SAL_CALL
component_getImplementationEnvironment(
320 const sal_Char
** ppEnvTypeName
, uno_Environment
** )
322 *ppEnvTypeName
= CPPU_CURRENT_LANGUAGE_BINDING_NAME
;
324 //==================================================================================================
325 sal_Bool SAL_CALL
component_writeInfo(
326 void * pServiceManager
, void * pRegistryKey
)
328 return component_writeInfoHelper( pServiceManager
, pRegistryKey
, g_entries
);
330 //==================================================================================================
331 void * SAL_CALL
component_getFactory(
332 const sal_Char
* pImplName
, void * pServiceManager
, void * pRegistryKey
)
334 return component_getFactoryHelper( pImplName
, pServiceManager
, pRegistryKey
, g_entries
);