LibreOffice Module io (master) 1
TextOutputStream.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20
21
24
25#include <rtl/textenc.h>
26#include <rtl/tencinfo.h>
27
28#include <com/sun/star/io/IOException.hpp>
29#include <com/sun/star/io/XTextOutputStream2.hpp>
30#include <com/sun/star/lang/XServiceInfo.hpp>
31
32namespace com::sun::star::uno { class XComponentContext; }
33
34using namespace ::osl;
35using namespace ::cppu;
36using namespace ::com::sun::star::uno;
37using namespace ::com::sun::star::lang;
38using namespace ::com::sun::star::io;
39
40// Implementation XTextOutputStream
41
42namespace {
43
44class OTextOutputStream : public WeakImplHelper< XTextOutputStream2, XServiceInfo >
45{
46 Reference< XOutputStream > mxStream;
47
48 // Encoding
49 bool mbEncodingInitialized;
50 rtl_UnicodeToTextConverter mConvUnicode2Text;
51 rtl_UnicodeToTextContext mContextUnicode2Text;
52
53 Sequence<sal_Int8> implConvert( const OUString& rSource );
55 void checkOutputStream() const;
56
57public:
58 OTextOutputStream();
59 virtual ~OTextOutputStream() override;
60
61 // Methods XTextOutputStream
62 virtual void SAL_CALL writeString( const OUString& aString ) override;
63 virtual void SAL_CALL setEncoding( const OUString& Encoding ) override;
64
65 // Methods XOutputStream
66 virtual void SAL_CALL writeBytes( const Sequence< sal_Int8 >& aData ) override;
67 virtual void SAL_CALL flush( ) override;
68 virtual void SAL_CALL closeOutput( ) override;
69
70 // Methods XActiveDataSource
71 virtual void SAL_CALL setOutputStream( const Reference< XOutputStream >& aStream ) override;
72 virtual Reference< XOutputStream > SAL_CALL getOutputStream( ) override;
73
74 // Methods XServiceInfo
75 virtual OUString SAL_CALL getImplementationName() override;
76 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
77 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
78};
79
80}
81
82OTextOutputStream::OTextOutputStream()
83 : mbEncodingInitialized(false)
84 , mConvUnicode2Text(nullptr)
85 , mContextUnicode2Text(nullptr)
86{
87}
88
89OTextOutputStream::~OTextOutputStream()
90{
91 if( mbEncodingInitialized )
92 {
93 rtl_destroyUnicodeToTextContext( mConvUnicode2Text, mContextUnicode2Text );
94 rtl_destroyUnicodeToTextConverter( mConvUnicode2Text );
95 }
96}
97
98Sequence<sal_Int8> OTextOutputStream::implConvert( const OUString& rSource )
99{
100 const sal_Unicode *puSource = rSource.getStr();
101 sal_Int32 nSourceSize = rSource.getLength();
102
103 sal_Size nTargetCount = 0;
104 sal_Size nSourceCount = 0;
105
106 sal_uInt32 uiInfo;
107 sal_Size nSrcCvtChars;
108
109 // take nSourceSize * 3 as preference
110 // this is an upper boundary for converting to utf8,
111 // which most often used as the target.
112 sal_Int32 nSeqSize = nSourceSize * 3;
113
114 Sequence<sal_Int8> seqText( nSeqSize );
115 char *pTarget = reinterpret_cast<char *>(seqText.getArray());
116 while( true )
117 {
118 nTargetCount += rtl_convertUnicodeToText(
119 mConvUnicode2Text,
120 mContextUnicode2Text,
121 &( puSource[nSourceCount] ),
122 nSourceSize - nSourceCount ,
123 &( pTarget[nTargetCount] ),
124 nSeqSize - nTargetCount,
125 RTL_UNICODETOTEXT_FLAGS_UNDEFINED_DEFAULT |
126 RTL_UNICODETOTEXT_FLAGS_INVALID_DEFAULT ,
127 &uiInfo,
128 &nSrcCvtChars);
129 nSourceCount += nSrcCvtChars;
130
131 if( uiInfo & RTL_UNICODETOTEXT_INFO_DESTBUFFERTOSMALL )
132 {
133 nSeqSize *= 2;
134 seqText.realloc( nSeqSize ); // double array size
135 pTarget = reinterpret_cast<char*>(seqText.getArray());
136 continue;
137 }
138 break;
139 }
140
141 // reduce the size of the buffer (fast, no copy necessary)
142 seqText.realloc( nTargetCount );
143 return seqText;
144}
145
146
147// XTextOutputStream
148
149void OTextOutputStream::writeString( const OUString& aString )
150{
151 checkOutputStream();
152 if( !mbEncodingInitialized )
153 {
154 setEncoding( "utf8" );
155 }
156 if( !mbEncodingInitialized )
157 return;
158
159 Sequence<sal_Int8> aByteSeq = implConvert( aString );
160 mxStream->writeBytes( aByteSeq );
161}
162
163void OTextOutputStream::setEncoding( const OUString& Encoding )
164{
165 OString aOEncodingStr = OUStringToOString( Encoding, RTL_TEXTENCODING_ASCII_US );
166 rtl_TextEncoding encoding = rtl_getTextEncodingFromMimeCharset( aOEncodingStr.getStr() );
167 if( RTL_TEXTENCODING_DONTKNOW == encoding )
168 return;
169
170 mbEncodingInitialized = true;
171 mConvUnicode2Text = rtl_createUnicodeToTextConverter( encoding );
172 mContextUnicode2Text = rtl_createUnicodeToTextContext( mConvUnicode2Text );
173}
174
175
176// XOutputStream
177void OTextOutputStream::writeBytes( const Sequence< sal_Int8 >& aData )
178{
179 checkOutputStream();
180 mxStream->writeBytes( aData );
181}
182
183void OTextOutputStream::flush( )
184{
185 checkOutputStream();
186 mxStream->flush();
187}
188
189void OTextOutputStream::closeOutput( )
190{
191 checkOutputStream();
192 mxStream->closeOutput();
193}
194
195
196void OTextOutputStream::checkOutputStream() const
197{
198 if (! mxStream.is() )
199 throw IOException("output stream is not initialized, you have to use setOutputStream first");
200}
201
202
203// XActiveDataSource
204
205void OTextOutputStream::setOutputStream( const Reference< XOutputStream >& aStream )
206{
207 mxStream = aStream;
208}
209
210Reference< XOutputStream > OTextOutputStream::getOutputStream()
211{
212 return mxStream;
213}
214
215OUString OTextOutputStream::getImplementationName()
216{
217 return "com.sun.star.comp.io.TextOutputStream";
218}
219
220sal_Bool OTextOutputStream::supportsService(const OUString& ServiceName)
221{
222 return cppu::supportsService(this, ServiceName);
223}
224
225Sequence< OUString > OTextOutputStream::getSupportedServiceNames()
226{
227 return { "com.sun.star.io.TextOutputStream" };
228}
229
230
231
232extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
234 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
235{
236 return cppu::acquire(new OTextOutputStream());
237}
238
239/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * io_OTextOutputStream_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
bool getOutputStream(ProgramOptions const &options, OString const &extension, std::ostream **ppOutputStream, OString &targetSourceFileName, OString &tmpSourceFileName)
sal_uInt32 writeString(sal_uInt8 *buffer, const sal_Unicode *v)
unsigned char sal_Bool
sal_uInt16 sal_Unicode