1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <osl/diagnose.h>
23 #include <uno/mapping.hxx>
25 #include <cppuhelper/factory.hxx>
26 #include <cppuhelper/implbase2.hxx>
27 #include <cppuhelper/implementationentry.hxx>
29 #include <rtl/textenc.h>
30 #include <rtl/tencinfo.h>
32 #include <com/sun/star/io/XTextOutputStream2.hpp>
33 #include <com/sun/star/lang/XServiceInfo.hpp>
36 #define IMPLEMENTATION_NAME "com.sun.star.comp.io.TextOutputStream"
37 #define SERVICE_NAME "com.sun.star.io.TextOutputStream"
39 using namespace ::osl
;
40 using namespace ::rtl
;
41 using namespace ::cppu
;
42 using namespace ::com::sun::star::uno
;
43 using namespace ::com::sun::star::lang
;
44 using namespace ::com::sun::star::io
;
45 using namespace ::com::sun::star::registry
;
47 namespace io_TextOutputStream
49 //===========================================================================
50 // Implementation XTextOutputStream
52 typedef WeakImplHelper2
< XTextOutputStream2
, XServiceInfo
> TextOutputStreamHelper
;
54 class OTextOutputStream
: public TextOutputStreamHelper
56 Reference
< XOutputStream
> mxStream
;
60 sal_Bool mbEncodingInitialized
;
61 rtl_UnicodeToTextConverter mConvUnicode2Text
;
62 rtl_UnicodeToTextContext mContextUnicode2Text
;
64 Sequence
<sal_Int8
> implConvert( const OUString
& rSource
);
70 // Methods XTextOutputStream
71 virtual void SAL_CALL
writeString( const OUString
& aString
)
72 throw(IOException
, RuntimeException
);
73 virtual void SAL_CALL
setEncoding( const OUString
& Encoding
)
74 throw(RuntimeException
);
76 // Methods XOutputStream
77 virtual void SAL_CALL
writeBytes( const Sequence
< sal_Int8
>& aData
)
78 throw(NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
);
79 virtual void SAL_CALL
flush( )
80 throw(NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
);
81 virtual void SAL_CALL
closeOutput( )
82 throw(NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
);
84 // Methods XActiveDataSource
85 virtual void SAL_CALL
setOutputStream( const Reference
< XOutputStream
>& aStream
)
86 throw(RuntimeException
);
87 virtual Reference
< XOutputStream
> SAL_CALL
getOutputStream( )
88 throw(RuntimeException
);
90 // Methods XServiceInfo
91 virtual OUString SAL_CALL
getImplementationName() throw();
92 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames(void) throw();
93 virtual sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
) throw();
96 OTextOutputStream::OTextOutputStream()
98 mbEncodingInitialized
= false;
101 OTextOutputStream::~OTextOutputStream()
103 if( mbEncodingInitialized
)
105 rtl_destroyUnicodeToTextContext( mConvUnicode2Text
, mContextUnicode2Text
);
106 rtl_destroyUnicodeToTextConverter( mConvUnicode2Text
);
110 Sequence
<sal_Int8
> OTextOutputStream::implConvert( const OUString
& rSource
)
112 const sal_Unicode
*puSource
= rSource
.getStr();
113 sal_Int32 nSourceSize
= rSource
.getLength();
115 sal_Size nTargetCount
= 0;
116 sal_Size nSourceCount
= 0;
119 sal_Size nSrcCvtChars
;
121 // take nSourceSize * 3 as preference
122 // this is an upper boundary for converting to utf8,
123 // which most often used as the target.
124 sal_Int32 nSeqSize
= nSourceSize
* 3;
126 Sequence
<sal_Int8
> seqText( nSeqSize
);
127 sal_Char
*pTarget
= (sal_Char
*) seqText
.getArray();
130 nTargetCount
+= rtl_convertUnicodeToText(
132 mContextUnicode2Text
,
133 &( puSource
[nSourceCount
] ),
134 nSourceSize
- nSourceCount
,
135 &( pTarget
[nTargetCount
] ),
136 nSeqSize
- nTargetCount
,
137 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT
|
138 RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT
,
141 nSourceCount
+= nSrcCvtChars
;
143 if( uiInfo
& RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL
)
146 seqText
.realloc( nSeqSize
); // double array size
147 pTarget
= (sal_Char
*) seqText
.getArray();
153 // reduce the size of the buffer (fast, no copy necessary)
154 seqText
.realloc( nTargetCount
);
159 //===========================================================================
162 void OTextOutputStream::writeString( const OUString
& aString
)
163 throw(IOException
, RuntimeException
)
165 if( !mbEncodingInitialized
)
167 OUString
aUtf8Str("utf8");
168 setEncoding( aUtf8Str
);
170 if( !mbEncodingInitialized
)
173 Sequence
<sal_Int8
> aByteSeq
= implConvert( aString
);
174 mxStream
->writeBytes( aByteSeq
);
177 void OTextOutputStream::setEncoding( const OUString
& Encoding
)
178 throw(RuntimeException
)
180 OString aOEncodingStr
= OUStringToOString( Encoding
, RTL_TEXTENCODING_ASCII_US
);
181 rtl_TextEncoding encoding
= rtl_getTextEncodingFromMimeCharset( aOEncodingStr
.getStr() );
182 if( RTL_TEXTENCODING_DONTKNOW
== encoding
)
185 mbEncodingInitialized
= true;
186 mConvUnicode2Text
= rtl_createUnicodeToTextConverter( encoding
);
187 mContextUnicode2Text
= rtl_createUnicodeToTextContext( mConvUnicode2Text
);
188 mEncoding
= Encoding
;
191 //===========================================================================
193 void OTextOutputStream::writeBytes( const Sequence
< sal_Int8
>& aData
)
194 throw(NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
196 mxStream
->writeBytes( aData
);
199 void OTextOutputStream::flush( )
200 throw(NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
205 void OTextOutputStream::closeOutput( )
206 throw(NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
208 mxStream
->closeOutput();
212 //===========================================================================
215 void OTextOutputStream::setOutputStream( const Reference
< XOutputStream
>& aStream
)
216 throw(RuntimeException
)
221 Reference
< XOutputStream
> OTextOutputStream::getOutputStream()
222 throw(RuntimeException
)
228 Reference
< XInterface
> SAL_CALL
TextOutputStream_CreateInstance(
229 SAL_UNUSED_PARAMETER
const Reference
< XComponentContext
> &)
231 return Reference
< XInterface
>( ( OWeakObject
* ) new OTextOutputStream() );
234 OUString
TextOutputStream_getImplementationName() SAL_THROW( () )
236 return OUString( IMPLEMENTATION_NAME
);
240 Sequence
< OUString
> TextOutputStream_getSupportedServiceNames()
242 Sequence
< OUString
> seqNames(1);
243 seqNames
.getArray()[0] = SERVICE_NAME
;
247 OUString
OTextOutputStream::getImplementationName() throw()
249 return TextOutputStream_getImplementationName();
252 sal_Bool
OTextOutputStream::supportsService(const OUString
& ServiceName
) throw()
254 Sequence
< OUString
> aSNL
= getSupportedServiceNames();
255 const OUString
* pArray
= aSNL
.getConstArray();
257 for( sal_Int32 i
= 0; i
< aSNL
.getLength(); i
++ )
258 if( pArray
[i
] == ServiceName
)
264 Sequence
< OUString
> OTextOutputStream::getSupportedServiceNames(void) throw()
266 return TextOutputStream_getSupportedServiceNames();
272 using namespace io_TextOutputStream
;
274 static struct ImplementationEntry g_entries
[] =
277 TextOutputStream_CreateInstance
, TextOutputStream_getImplementationName
,
278 TextOutputStream_getSupportedServiceNames
, createSingleComponentFactory
,
284 extern "C" SAL_DLLPUBLIC_EXPORT
void * SAL_CALL
textoutstream_component_getFactory(
285 const sal_Char
* pImplName
, void * pServiceManager
, void * pRegistryKey
)
287 return component_getFactoryHelper( pImplName
, pServiceManager
, pRegistryKey
, g_entries
);
290 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */