bump product version to 6.4.0.3
[LibreOffice.git] / io / source / TextOutputStream / TextOutputStream.cxx
blob22fab1f01bd0545eed875f7c61bf3b8d6735f96e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
22 #include <cppuhelper/implbase.hxx>
23 #include <cppuhelper/supportsservice.hxx>
25 #include <rtl/textenc.h>
26 #include <rtl/tencinfo.h>
28 #include <com/sun/star/io/IOException.hpp>
29 #include <com/sun/star/io/XTextOutputStream2.hpp>
30 #include <com/sun/star/lang/XServiceInfo.hpp>
32 #include <services.hxx>
34 namespace com::sun::star::uno { class XComponentContext; }
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 ::cppu;
41 using namespace ::com::sun::star::uno;
42 using namespace ::com::sun::star::lang;
43 using namespace ::com::sun::star::io;
45 namespace io_TextOutputStream
48 // Implementation XTextOutputStream
50 class OTextOutputStream : public WeakImplHelper< XTextOutputStream2, XServiceInfo >
52 Reference< XOutputStream > mxStream;
54 // Encoding
55 bool mbEncodingInitialized;
56 rtl_UnicodeToTextConverter mConvUnicode2Text;
57 rtl_UnicodeToTextContext mContextUnicode2Text;
59 Sequence<sal_Int8> implConvert( const OUString& rSource );
60 /// @throws IOException
61 void checkOutputStream() const;
63 public:
64 OTextOutputStream();
65 virtual ~OTextOutputStream() override;
67 // Methods XTextOutputStream
68 virtual void SAL_CALL writeString( const OUString& aString ) override;
69 virtual void SAL_CALL setEncoding( const OUString& Encoding ) override;
71 // Methods XOutputStream
72 virtual void SAL_CALL writeBytes( const Sequence< sal_Int8 >& aData ) override;
73 virtual void SAL_CALL flush( ) override;
74 virtual void SAL_CALL closeOutput( ) override;
76 // Methods XActiveDataSource
77 virtual void SAL_CALL setOutputStream( const Reference< XOutputStream >& aStream ) override;
78 virtual Reference< XOutputStream > SAL_CALL getOutputStream( ) override;
80 // Methods XServiceInfo
81 virtual OUString SAL_CALL getImplementationName() override;
82 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
83 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
86 OTextOutputStream::OTextOutputStream()
87 : mbEncodingInitialized(false)
88 , mConvUnicode2Text(nullptr)
89 , mContextUnicode2Text(nullptr)
93 OTextOutputStream::~OTextOutputStream()
95 if( mbEncodingInitialized )
97 rtl_destroyUnicodeToTextContext( mConvUnicode2Text, mContextUnicode2Text );
98 rtl_destroyUnicodeToTextConverter( mConvUnicode2Text );
102 Sequence<sal_Int8> OTextOutputStream::implConvert( const OUString& rSource )
104 const sal_Unicode *puSource = rSource.getStr();
105 sal_Int32 nSourceSize = rSource.getLength();
107 sal_Size nTargetCount = 0;
108 sal_Size nSourceCount = 0;
110 sal_uInt32 uiInfo;
111 sal_Size nSrcCvtChars;
113 // take nSourceSize * 3 as preference
114 // this is an upper boundary for converting to utf8,
115 // which most often used as the target.
116 sal_Int32 nSeqSize = nSourceSize * 3;
118 Sequence<sal_Int8> seqText( nSeqSize );
119 sal_Char *pTarget = reinterpret_cast<char *>(seqText.getArray());
120 while( true )
122 nTargetCount += rtl_convertUnicodeToText(
123 mConvUnicode2Text,
124 mContextUnicode2Text,
125 &( puSource[nSourceCount] ),
126 nSourceSize - nSourceCount ,
127 &( pTarget[nTargetCount] ),
128 nSeqSize - nTargetCount,
129 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT |
130 RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT ,
131 &uiInfo,
132 &nSrcCvtChars);
133 nSourceCount += nSrcCvtChars;
135 if( uiInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL )
137 nSeqSize *= 2;
138 seqText.realloc( nSeqSize ); // double array size
139 pTarget = reinterpret_cast<char*>(seqText.getArray());
140 continue;
142 break;
145 // reduce the size of the buffer (fast, no copy necessary)
146 seqText.realloc( nTargetCount );
147 return seqText;
151 // XTextOutputStream
153 void OTextOutputStream::writeString( const OUString& aString )
155 checkOutputStream();
156 if( !mbEncodingInitialized )
158 setEncoding( "utf8" );
160 if( !mbEncodingInitialized )
161 return;
163 Sequence<sal_Int8> aByteSeq = implConvert( aString );
164 mxStream->writeBytes( aByteSeq );
167 void OTextOutputStream::setEncoding( const OUString& Encoding )
169 OString aOEncodingStr = OUStringToOString( Encoding, RTL_TEXTENCODING_ASCII_US );
170 rtl_TextEncoding encoding = rtl_getTextEncodingFromMimeCharset( aOEncodingStr.getStr() );
171 if( RTL_TEXTENCODING_DONTKNOW == encoding )
172 return;
174 mbEncodingInitialized = true;
175 mConvUnicode2Text = rtl_createUnicodeToTextConverter( encoding );
176 mContextUnicode2Text = rtl_createUnicodeToTextContext( mConvUnicode2Text );
180 // XOutputStream
181 void OTextOutputStream::writeBytes( const Sequence< sal_Int8 >& aData )
183 checkOutputStream();
184 mxStream->writeBytes( aData );
187 void OTextOutputStream::flush( )
189 checkOutputStream();
190 mxStream->flush();
193 void OTextOutputStream::closeOutput( )
195 checkOutputStream();
196 mxStream->closeOutput();
200 void OTextOutputStream::checkOutputStream() const
202 if (! mxStream.is() )
203 throw IOException("output stream is not initialized, you have to use setOutputStream first");
207 // XActiveDataSource
209 void OTextOutputStream::setOutputStream( const Reference< XOutputStream >& aStream )
211 mxStream = aStream;
214 Reference< XOutputStream > OTextOutputStream::getOutputStream()
216 return mxStream;
220 Reference< XInterface > TextOutputStream_CreateInstance(
221 SAL_UNUSED_PARAMETER const Reference< XComponentContext > &)
223 return Reference < XInterface >( static_cast<OWeakObject *>(new OTextOutputStream()) );
226 OUString TextOutputStream_getImplementationName()
228 return IMPLEMENTATION_NAME;
232 Sequence< OUString > TextOutputStream_getSupportedServiceNames()
234 Sequence< OUString > seqNames { SERVICE_NAME };
235 return seqNames;
238 OUString OTextOutputStream::getImplementationName()
240 return TextOutputStream_getImplementationName();
243 sal_Bool OTextOutputStream::supportsService(const OUString& ServiceName)
245 return cppu::supportsService(this, ServiceName);
248 Sequence< OUString > OTextOutputStream::getSupportedServiceNames()
250 return TextOutputStream_getSupportedServiceNames();
256 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */