tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / io / source / TextInputStream / TextInputStream.cxx
blob94710fe6c8d543719bbbb7ff93a68027f29e87f8
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 .
20 #include <string.h>
22 #include <comphelper/sequence.hxx>
23 #include <cppuhelper/implbase.hxx>
24 #include <cppuhelper/supportsservice.hxx>
26 #include <rtl/textenc.h>
27 #include <rtl/tencinfo.h>
29 #include <com/sun/star/io/BufferSizeExceededException.hpp>
30 #include <com/sun/star/io/IOException.hpp>
31 #include <com/sun/star/io/NotConnectedException.hpp>
32 #include <com/sun/star/io/XTextInputStream2.hpp>
33 #include <com/sun/star/lang/XServiceInfo.hpp>
35 #include <vector>
37 namespace com::sun::star::uno { class XComponentContext; }
39 using namespace ::cppu;
40 using namespace ::com::sun::star::uno;
41 using namespace ::com::sun::star::lang;
42 using namespace ::com::sun::star::io;
45 // Implementation XTextInputStream
47 #define INITIAL_UNICODE_BUFFER_CAPACITY 0x100
48 #define READ_BYTE_COUNT 0x100
50 namespace {
52 class OTextInputStream : public WeakImplHelper< XTextInputStream2, XServiceInfo >
54 Reference< XInputStream > mxStream;
56 // Encoding
57 bool mbEncodingInitialized;
58 rtl_TextToUnicodeConverter mConvText2Unicode;
59 rtl_TextToUnicodeContext mContextText2Unicode;
60 Sequence<sal_Int8> mSeqSource;
62 // Internal buffer for characters that are already converted successfully
63 std::vector<sal_Unicode> mvBuffer;
64 sal_Int32 mnCharsInBuffer;
65 bool mbReachedEOF;
67 /// @throws IOException
68 /// @throws RuntimeException
69 OUString implReadString( const Sequence< sal_Unicode >& Delimiters,
70 bool bRemoveDelimiter, bool bFindLineEnd );
71 /// @throws IOException
72 /// @throws RuntimeException
73 sal_Int32 implReadNext();
74 /// @throws RuntimeException
75 void checkNull();
77 public:
78 OTextInputStream();
79 virtual ~OTextInputStream() override;
81 // Methods XTextInputStream
82 virtual OUString SAL_CALL readLine( ) override;
83 virtual OUString SAL_CALL readString( const Sequence< sal_Unicode >& Delimiters, sal_Bool bRemoveDelimiter ) override;
84 virtual sal_Bool SAL_CALL isEOF( ) override;
85 virtual void SAL_CALL setEncoding( const OUString& Encoding ) override;
87 // Methods XInputStream
88 virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) override;
89 virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) override;
90 virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip ) override;
91 virtual sal_Int32 SAL_CALL available( ) override;
92 virtual void SAL_CALL closeInput( ) override;
94 // Methods XActiveDataSink
95 virtual void SAL_CALL setInputStream( const Reference< XInputStream >& aStream ) override;
96 virtual Reference< XInputStream > SAL_CALL getInputStream() override;
98 // Methods XServiceInfo
99 virtual OUString SAL_CALL getImplementationName() override;
100 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
101 virtual sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
106 OTextInputStream::OTextInputStream()
107 : mbEncodingInitialized(false)
108 , mConvText2Unicode(nullptr)
109 , mContextText2Unicode(nullptr)
110 , mSeqSource(READ_BYTE_COUNT)
111 , mvBuffer(INITIAL_UNICODE_BUFFER_CAPACITY, 0)
112 , mnCharsInBuffer(0)
113 , mbReachedEOF(false)
117 OTextInputStream::~OTextInputStream()
119 if( mbEncodingInitialized )
121 rtl_destroyTextToUnicodeContext( mConvText2Unicode, mContextText2Unicode );
122 rtl_destroyTextToUnicodeConverter( mConvText2Unicode );
126 // Check uninitialized object
128 void OTextInputStream::checkNull()
130 if (mxStream==nullptr){
131 throw RuntimeException(u"Uninitialized object"_ustr);
135 // XTextInputStream
137 OUString OTextInputStream::readLine( )
139 checkNull();
140 static Sequence< sal_Unicode > aDummySeq;
141 return implReadString( aDummySeq, true, true );
144 OUString OTextInputStream::readString( const Sequence< sal_Unicode >& Delimiters, sal_Bool bRemoveDelimiter )
146 checkNull();
147 return implReadString( Delimiters, bRemoveDelimiter, false );
150 sal_Bool OTextInputStream::isEOF()
152 checkNull();
153 bool bRet = false;
154 if( mnCharsInBuffer == 0 && mbReachedEOF )
155 bRet = true;
156 return bRet;
160 OUString OTextInputStream::implReadString( const Sequence< sal_Unicode >& Delimiters,
161 bool bRemoveDelimiter, bool bFindLineEnd )
163 OUString aRetStr;
164 if( !mbEncodingInitialized )
166 setEncoding( u"utf8"_ustr );
168 if( !mbEncodingInitialized )
169 return aRetStr;
171 // Only for bFindLineEnd
172 constexpr sal_Unicode cLineEndChar1 = '\r';
173 constexpr sal_Unicode cLineEndChar2 = '\n';
175 sal_Int32 nBufferReadPos = 0;
176 sal_Int32 nCopyLen = -1;
177 sal_Unicode cFirstLineEndChar = 0;
178 while (true)
180 // Still characters available?
181 if( nBufferReadPos == mnCharsInBuffer )
183 // Already reached EOF? Then we can't read any more
184 // Or no, so read new characters
185 if( !implReadNext() )
186 break;
189 // Now there should be characters available
190 // (otherwise the loop should have been broken before)
191 sal_Unicode c = mvBuffer[ nBufferReadPos++ ];
193 if( bFindLineEnd )
195 if (cFirstLineEndChar != 0)
197 assert(nCopyLen >= 0);
198 // This is a check if the next character after a line end char is its second half
199 // Same line end char -> new line break; non-line-end char -> new line start
200 if ((c == cFirstLineEndChar) || (c != cLineEndChar1 && c != cLineEndChar2))
202 // Not a two-char line end
203 nBufferReadPos--;
205 break;
207 else if( c == cLineEndChar1 || c == cLineEndChar2 )
209 nCopyLen = nBufferReadPos - 1; // we know what to copy
210 cFirstLineEndChar = c; // take one more loop, to check if it's a two-char line end
213 else if( comphelper::findValue(Delimiters, c) != -1 )
215 nCopyLen = nBufferReadPos;
216 if( bRemoveDelimiter )
217 nCopyLen--;
218 break;
222 // Nothing found? Return all
223 if (nCopyLen < 0)
224 nCopyLen = nBufferReadPos;
226 // Create string
227 if( nCopyLen )
228 aRetStr = OUString( mvBuffer.data(), nCopyLen );
230 // Copy rest of buffer
231 memmove( mvBuffer.data(), mvBuffer.data() + nBufferReadPos,
232 (mnCharsInBuffer - nBufferReadPos) * sizeof( sal_Unicode ) );
233 mnCharsInBuffer -= nBufferReadPos;
235 return aRetStr;
239 sal_Int32 OTextInputStream::implReadNext()
241 // Already reached EOF? Then we can't read any more
242 if (mbReachedEOF)
243 return 0;
247 if (mxStream->readSomeBytes(mSeqSource, READ_BYTE_COUNT) == 0)
249 mbReachedEOF = true;
250 return 0;
253 // Try to convert
254 sal_uInt32 uiInfo = mvBuffer.size() - mnCharsInBuffer < o3tl::make_unsigned(mSeqSource.getLength())
255 ? RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOOSMALL
256 : 0;
257 const sal_Int32 nOldCharsInBuffer = mnCharsInBuffer;
258 sal_Size nSourceCount = 0;
259 while( true )
261 if (uiInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOOSMALL)
263 mvBuffer.resize(mvBuffer.size() * 2);
266 // All invalid characters are transformed to the unicode undefined char
267 sal_Size nSrcCvtBytes = 0;
268 mnCharsInBuffer += rtl_convertTextToUnicode(
269 mConvText2Unicode,
270 mContextText2Unicode,
271 reinterpret_cast<const char*>(mSeqSource.getConstArray() + nSourceCount),
272 mSeqSource.getLength() - nSourceCount,
273 mvBuffer.data() + mnCharsInBuffer,
274 mvBuffer.size() - mnCharsInBuffer,
275 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT |
276 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
277 RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT,
278 &uiInfo,
279 &nSrcCvtBytes );
280 nSourceCount += nSrcCvtBytes;
282 if( uiInfo & RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOOSMALL )
284 // read next byte
285 Sequence<sal_Int8> aOneByteSeq(1);
286 if (mxStream->readSomeBytes(aOneByteSeq, 1) == 0)
288 mbReachedEOF = true;
289 return mnCharsInBuffer - nOldCharsInBuffer;
292 mSeqSource = comphelper::concatSequences(mSeqSource, aOneByteSeq);
294 else if (!(uiInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOOSMALL))
295 return mnCharsInBuffer - nOldCharsInBuffer; // finished
298 catch( NotConnectedException& )
300 throw IOException(u"Not connected"_ustr);
301 //throw IOException( L"OTextInputStream::implReadString failed" );
303 catch( BufferSizeExceededException& )
305 throw IOException(u"Buffer size exceeded"_ustr);
309 void OTextInputStream::setEncoding( const OUString& Encoding )
311 OString aOEncodingStr = OUStringToOString( Encoding, RTL_TEXTENCODING_ASCII_US );
312 rtl_TextEncoding encoding = rtl_getTextEncodingFromMimeCharset( aOEncodingStr.getStr() );
313 if( RTL_TEXTENCODING_DONTKNOW == encoding )
314 return;
316 mbEncodingInitialized = true;
317 mConvText2Unicode = rtl_createTextToUnicodeConverter( encoding );
318 mContextText2Unicode = rtl_createTextToUnicodeContext( mConvText2Unicode );
322 // XInputStream
324 sal_Int32 OTextInputStream::readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
326 checkNull();
327 return mxStream->readBytes( aData, nBytesToRead );
330 sal_Int32 OTextInputStream::readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
332 checkNull();
333 return mxStream->readSomeBytes( aData, nMaxBytesToRead );
336 void OTextInputStream::skipBytes( sal_Int32 nBytesToSkip )
338 checkNull();
339 mxStream->skipBytes( nBytesToSkip );
342 sal_Int32 OTextInputStream::available( )
344 checkNull();
345 return mxStream->available();
348 void OTextInputStream::closeInput( )
350 checkNull();
351 mxStream->closeInput();
355 // XActiveDataSink
357 void OTextInputStream::setInputStream( const Reference< XInputStream >& aStream )
359 mxStream = aStream;
362 Reference< XInputStream > OTextInputStream::getInputStream()
364 return mxStream;
367 OUString OTextInputStream::getImplementationName()
369 return u"com.sun.star.comp.io.TextInputStream"_ustr;
372 sal_Bool OTextInputStream::supportsService(const OUString& ServiceName)
374 return cppu::supportsService(this, ServiceName);
377 Sequence< OUString > OTextInputStream::getSupportedServiceNames()
379 return { u"com.sun.star.io.TextInputStream"_ustr };
382 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
383 io_OTextInputStream_get_implementation(
384 css::uno::XComponentContext* , css::uno::Sequence<css::uno::Any> const&)
386 return cppu::acquire(new OTextInputStream());
390 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */