LCOV - code coverage report
Current view: top level - io/source/TextInputStream - TextInputStream.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 120 160 75.0 %
Date: 2015-06-13 12:38:46 Functions: 16 23 69.6 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : #include <string.h>
      21             : #include <osl/diagnose.h>
      22             : 
      23             : #include <uno/mapping.hxx>
      24             : 
      25             : #include <cppuhelper/factory.hxx>
      26             : #include <cppuhelper/implbase2.hxx>
      27             : #include <cppuhelper/implementationentry.hxx>
      28             : #include <cppuhelper/supportsservice.hxx>
      29             : 
      30             : #include <rtl/textenc.h>
      31             : #include <rtl/tencinfo.h>
      32             : 
      33             : #include <com/sun/star/io/XTextInputStream2.hpp>
      34             : #include <com/sun/star/lang/XServiceInfo.hpp>
      35             : 
      36             : #include "services.hxx"
      37             : 
      38             : #define IMPLEMENTATION_NAME "com.sun.star.comp.io.TextInputStream"
      39             : #define SERVICE_NAME "com.sun.star.io.TextInputStream"
      40             : 
      41             : using namespace ::osl;
      42             : using namespace ::cppu;
      43             : using namespace ::com::sun::star::uno;
      44             : using namespace ::com::sun::star::lang;
      45             : using namespace ::com::sun::star::io;
      46             : using namespace ::com::sun::star::registry;
      47             : 
      48             : namespace io_TextInputStream
      49             : {
      50             : 
      51             : // Implementation XTextInputStream
      52             : 
      53             : typedef WeakImplHelper2< XTextInputStream2, XServiceInfo > TextInputStreamHelper;
      54             : 
      55             : #define INITIAL_UNICODE_BUFFER_CAPACITY     0x100
      56             : #define READ_BYTE_COUNT                     0x100
      57             : 
      58             : class OTextInputStream : public TextInputStreamHelper
      59             : {
      60             :     Reference< XInputStream > mxStream;
      61             : 
      62             :     // Encoding
      63             :     OUString mEncoding;
      64             :     bool mbEncodingInitialized;
      65             :     rtl_TextToUnicodeConverter  mConvText2Unicode;
      66             :     rtl_TextToUnicodeContext    mContextText2Unicode;
      67             :     Sequence<sal_Int8>          mSeqSource;
      68             : 
      69             :     // Internal buffer for characters that are already converted successfully
      70             :     sal_Unicode* mpBuffer;
      71             :     sal_Int32 mnBufferSize;
      72             :     sal_Int32 mnCharsInBuffer;
      73             :     bool mbReachedEOF;
      74             : 
      75             :     void implResizeBuffer();
      76             :     OUString implReadString( const Sequence< sal_Unicode >& Delimiters,
      77             :         bool bRemoveDelimiter, bool bFindLineEnd )
      78             :             throw(IOException, RuntimeException);
      79             :     sal_Int32 implReadNext() throw(IOException, RuntimeException);
      80             : 
      81             : public:
      82             :     OTextInputStream();
      83             :     virtual ~OTextInputStream();
      84             : 
      85             :     // Methods XTextInputStream
      86             :     virtual OUString SAL_CALL readLine(  )
      87             :         throw(IOException, RuntimeException, std::exception) SAL_OVERRIDE;
      88             :     virtual OUString SAL_CALL readString( const Sequence< sal_Unicode >& Delimiters, sal_Bool bRemoveDelimiter )
      89             :         throw(IOException, RuntimeException, std::exception) SAL_OVERRIDE;
      90             :     virtual sal_Bool SAL_CALL isEOF(  )
      91             :         throw(IOException, RuntimeException, std::exception) SAL_OVERRIDE;
      92             :     virtual void SAL_CALL setEncoding( const OUString& Encoding ) throw(RuntimeException, std::exception) SAL_OVERRIDE;
      93             : 
      94             :     // Methods XInputStream
      95             :     virtual sal_Int32 SAL_CALL readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
      96             :         throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) SAL_OVERRIDE;
      97             :     virtual sal_Int32 SAL_CALL readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
      98             :         throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) SAL_OVERRIDE;
      99             :     virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
     100             :         throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception) SAL_OVERRIDE;
     101             :     virtual sal_Int32 SAL_CALL available(  )
     102             :         throw(NotConnectedException, IOException, RuntimeException, std::exception) SAL_OVERRIDE;
     103             :     virtual void SAL_CALL closeInput(  )
     104             :         throw(NotConnectedException, IOException, RuntimeException, std::exception) SAL_OVERRIDE;
     105             : 
     106             :     // Methods XActiveDataSink
     107             :     virtual void SAL_CALL setInputStream( const Reference< XInputStream >& aStream )
     108             :         throw(RuntimeException, std::exception) SAL_OVERRIDE;
     109             :     virtual Reference< XInputStream > SAL_CALL getInputStream()
     110             :         throw(RuntimeException, std::exception) SAL_OVERRIDE;
     111             : 
     112             :     // Methods XServiceInfo
     113             :         virtual OUString              SAL_CALL getImplementationName() throw(std::exception) SAL_OVERRIDE;
     114             :         virtual Sequence< OUString >  SAL_CALL getSupportedServiceNames() throw(std::exception) SAL_OVERRIDE;
     115             :         virtual sal_Bool              SAL_CALL supportsService(const OUString& ServiceName) throw(std::exception) SAL_OVERRIDE;
     116             : };
     117             : 
     118         201 : OTextInputStream::OTextInputStream()
     119             :     : mbEncodingInitialized(false)
     120             :     , mConvText2Unicode(NULL)
     121             :     , mContextText2Unicode(NULL)
     122             :     , mSeqSource(READ_BYTE_COUNT)
     123             :     , mpBuffer(NULL)
     124             :     , mnBufferSize(0)
     125             :     , mnCharsInBuffer(0)
     126         201 :     , mbReachedEOF(false)
     127             : {
     128         201 : }
     129             : 
     130         603 : OTextInputStream::~OTextInputStream()
     131             : {
     132         201 :     if( mbEncodingInitialized )
     133             :     {
     134         200 :         rtl_destroyUnicodeToTextContext( mConvText2Unicode, mContextText2Unicode );
     135         200 :         rtl_destroyUnicodeToTextConverter( mConvText2Unicode );
     136             :     }
     137             : 
     138         201 :     delete[] mpBuffer;
     139         402 : }
     140             : 
     141         197 : void OTextInputStream::implResizeBuffer()
     142             : {
     143         197 :     sal_Int32 mnNewBufferSize = mnBufferSize * 2;
     144         197 :     sal_Unicode* pNewBuffer = new sal_Unicode[ mnNewBufferSize ];
     145         197 :     memcpy( pNewBuffer, mpBuffer, mnCharsInBuffer * sizeof( sal_Unicode ) );
     146         197 :     delete[] mpBuffer;
     147         197 :     mpBuffer = pNewBuffer;
     148         197 :     mnBufferSize = mnNewBufferSize;
     149         197 : }
     150             : 
     151             : 
     152             : 
     153             : // XTextInputStream
     154             : 
     155        7536 : OUString OTextInputStream::readLine(  )
     156             :     throw(IOException, RuntimeException, std::exception)
     157             : {
     158        7536 :     static Sequence< sal_Unicode > aDummySeq;
     159        7536 :     return implReadString( aDummySeq, true, true );
     160             : }
     161             : 
     162         291 : OUString OTextInputStream::readString( const Sequence< sal_Unicode >& Delimiters, sal_Bool bRemoveDelimiter )
     163             :         throw(IOException, RuntimeException, std::exception)
     164             : {
     165         291 :     return implReadString( Delimiters, bRemoveDelimiter, false );
     166             : }
     167             : 
     168        8149 : sal_Bool OTextInputStream::isEOF()
     169             :     throw(IOException, RuntimeException, std::exception)
     170             : {
     171        8149 :     bool bRet = false;
     172        8149 :     if( mnCharsInBuffer == 0 && mbReachedEOF )
     173         175 :         bRet = true;
     174        8149 :     return bRet;
     175             : }
     176             : 
     177             : 
     178        7827 : OUString OTextInputStream::implReadString( const Sequence< sal_Unicode >& Delimiters,
     179             :                                            bool bRemoveDelimiter, bool bFindLineEnd )
     180             :         throw(IOException, RuntimeException)
     181             : {
     182        7827 :     OUString aRetStr;
     183        7827 :     if( !mbEncodingInitialized )
     184             :     {
     185           1 :         OUString aUtf8Str("utf8");
     186           1 :         setEncoding( aUtf8Str );
     187             :     }
     188        7827 :     if( !mbEncodingInitialized )
     189           0 :         return aRetStr;
     190             : 
     191        7827 :     if( !mpBuffer )
     192             :     {
     193         200 :         mnBufferSize = INITIAL_UNICODE_BUFFER_CAPACITY;
     194         200 :         mpBuffer = new sal_Unicode[ mnBufferSize ];
     195             :     }
     196             : 
     197             :     // Only for bFindLineEnd
     198        7827 :     sal_Unicode cLineEndChar1 = 0x0D;
     199        7827 :     sal_Unicode cLineEndChar2 = 0x0A;
     200             : 
     201        7827 :     sal_Int32 nBufferReadPos = 0;
     202        7827 :     sal_Int32 nCopyLen = 0;
     203        7827 :     bool bFound = false;
     204        7827 :     bool bFoundFirstLineEndChar = false;
     205        7827 :     sal_Unicode cFirstLineEndChar = 0;
     206        7827 :     const sal_Unicode* pDelims = Delimiters.getConstArray();
     207        7827 :     const sal_Int32 nDelimCount = Delimiters.getLength();
     208      292274 :     while( !bFound )
     209             :     {
     210             :         // Still characters available?
     211      276786 :         if( nBufferReadPos == mnCharsInBuffer )
     212             :         {
     213             :             // Already reached EOF? Then we can't read any more
     214        1385 :             if( mbReachedEOF )
     215           0 :                 break;
     216             : 
     217             :             // No, so read new characters
     218        1385 :             if( !implReadNext() )
     219         166 :                 break;
     220             :         }
     221             : 
     222             :         // Now there should be characters available
     223             :         // (otherwise the loop should have been breaked before)
     224      276620 :         sal_Unicode c = mpBuffer[ nBufferReadPos++ ];
     225             : 
     226      276620 :         if( bFindLineEnd )
     227             :         {
     228      270636 :             if( bFoundFirstLineEndChar )
     229             :             {
     230        7375 :                 bFound = true;
     231        7375 :                 nCopyLen = nBufferReadPos - 2;
     232        7375 :                 if( c == cLineEndChar1 || c == cLineEndChar2 )
     233             :                 {
     234             :                     // Same line end char -> new line break
     235       14750 :                     if( c == cFirstLineEndChar )
     236             :                     {
     237           0 :                         nBufferReadPos--;
     238             :                     }
     239             :                 }
     240             :                 else
     241             :                 {
     242             :                     // No second line end char
     243           0 :                     nBufferReadPos--;
     244             :                 }
     245             :             }
     246      263261 :             else if( c == cLineEndChar1 || c == cLineEndChar2 )
     247             :             {
     248        7375 :                 bFoundFirstLineEndChar = true;
     249        7375 :                 cFirstLineEndChar = c;
     250             :             }
     251             :         }
     252             :         else
     253             :         {
     254       11968 :             for( sal_Int32 i = 0 ; i < nDelimCount ; i++ )
     255             :             {
     256        5984 :                 if( c == pDelims[ i ] )
     257             :                 {
     258         286 :                     bFound = true;
     259         286 :                     nCopyLen = nBufferReadPos;
     260         286 :                     if( bRemoveDelimiter )
     261           0 :                         nCopyLen--;
     262             :                 }
     263             :             }
     264             :         }
     265             :     }
     266             : 
     267             :     // Nothing found? Return all
     268        7827 :     if( !nCopyLen && !bFound && mbReachedEOF )
     269         166 :         nCopyLen = nBufferReadPos;
     270             : 
     271             :     // Create string
     272        7827 :     if( nCopyLen )
     273        7006 :         aRetStr = OUString( mpBuffer, nCopyLen );
     274             : 
     275             :     // Copy rest of buffer
     276             :     memmove( mpBuffer, mpBuffer + nBufferReadPos,
     277        7827 :         (mnCharsInBuffer - nBufferReadPos) * sizeof( sal_Unicode ) );
     278        7827 :     mnCharsInBuffer -= nBufferReadPos;
     279             : 
     280        7827 :     return aRetStr;
     281             : }
     282             : 
     283             : 
     284        1385 : sal_Int32 OTextInputStream::implReadNext()
     285             :         throw(IOException, RuntimeException)
     286             : {
     287        1385 :     sal_Int32 nFreeBufferSize = mnBufferSize - mnCharsInBuffer;
     288        1385 :     if( nFreeBufferSize < READ_BYTE_COUNT )
     289         197 :         implResizeBuffer();
     290        1385 :     nFreeBufferSize = mnBufferSize - mnCharsInBuffer;
     291             : 
     292             :     try
     293             :     {
     294        1385 :         sal_Int32 nBytesToRead = READ_BYTE_COUNT;
     295        1385 :         sal_Int32 nRead = mxStream->readSomeBytes( mSeqSource, nBytesToRead );
     296        1385 :         sal_Int32 nTotalRead = nRead;
     297        1385 :         if( nRead == 0 )
     298         166 :             mbReachedEOF = true;
     299             : 
     300             :         // Try to convert
     301             :         sal_uInt32 uiInfo;
     302        1385 :         sal_Size nSrcCvtBytes = 0;
     303        1385 :         sal_Size nTargetCount = 0;
     304        1385 :         sal_Size nSourceCount = 0;
     305             :         while( true )
     306             :         {
     307        1385 :             const sal_Int8 *pbSource = mSeqSource.getConstArray();
     308             : 
     309             :             // All invalid characters are transformed to the unicode undefined char
     310             :             nTargetCount += rtl_convertTextToUnicode(
     311             :                                 mConvText2Unicode,
     312             :                                 mContextText2Unicode,
     313             :                                 reinterpret_cast<const char*>(&( pbSource[nSourceCount] )),
     314             :                                 nTotalRead - nSourceCount,
     315        1385 :                                 mpBuffer + mnCharsInBuffer + nTargetCount,
     316             :                                 nFreeBufferSize - nTargetCount,
     317             :                                 RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_DEFAULT   |
     318             :                                 RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_DEFAULT |
     319             :                                 RTL_TEXTTOUNICODE_FLAGS_INVALID_DEFAULT,
     320             :                                 &uiInfo,
     321        2770 :                                 &nSrcCvtBytes );
     322        1385 :             nSourceCount += nSrcCvtBytes;
     323             : 
     324        1385 :             bool bCont = false;
     325        1385 :             if( uiInfo & RTL_TEXTTOUNICODE_INFO_DESTBUFFERTOSMALL )
     326             :             {
     327           0 :                 implResizeBuffer();
     328           0 :                 bCont = true;
     329             :             }
     330             : 
     331        1385 :             if( uiInfo & RTL_TEXTTOUNICODE_INFO_SRCBUFFERTOSMALL )
     332             :             {
     333             :                 // read next byte
     334           0 :                 static Sequence< sal_Int8 > aOneByteSeq( 1 );
     335           0 :                 nRead = mxStream->readSomeBytes( aOneByteSeq, 1 );
     336           0 :                 if( nRead == 0 )
     337             :                 {
     338           0 :                     mbReachedEOF = true;
     339           0 :                     break;
     340             :                 }
     341             : 
     342           0 :                 sal_Int32 nOldLen = mSeqSource.getLength();
     343           0 :                 nTotalRead++;
     344           0 :                 if( nTotalRead > nOldLen )
     345             :                 {
     346           0 :                     mSeqSource.realloc( nTotalRead );
     347             :                 }
     348           0 :                 mSeqSource.getArray()[ nOldLen ] = aOneByteSeq.getConstArray()[ 0 ];
     349           0 :                 pbSource = mSeqSource.getConstArray();
     350           0 :                 bCont = true;
     351             :             }
     352             : 
     353        1385 :             if( bCont )
     354           0 :                 continue;
     355        1385 :             break;
     356             :         }
     357             : 
     358        1385 :         mnCharsInBuffer += nTargetCount;
     359        1385 :         return nTargetCount;
     360             :     }
     361           0 :     catch( NotConnectedException& )
     362             :     {
     363           0 :         throw IOException();
     364             :         //throw IOException( L"OTextInputStream::implReadString failed" );
     365             :     }
     366           0 :     catch( BufferSizeExceededException& )
     367             :     {
     368           0 :         throw IOException();
     369             :     }
     370             : }
     371             : 
     372         200 : void OTextInputStream::setEncoding( const OUString& Encoding )
     373             :     throw(RuntimeException, std::exception)
     374             : {
     375         200 :     OString aOEncodingStr = OUStringToOString( Encoding, RTL_TEXTENCODING_ASCII_US );
     376         200 :     rtl_TextEncoding encoding = rtl_getTextEncodingFromMimeCharset( aOEncodingStr.getStr() );
     377         200 :     if( RTL_TEXTENCODING_DONTKNOW == encoding )
     378         200 :         return;
     379             : 
     380         200 :     mbEncodingInitialized = true;
     381         200 :     mConvText2Unicode = rtl_createTextToUnicodeConverter( encoding );
     382         200 :     mContextText2Unicode = rtl_createTextToUnicodeContext( mConvText2Unicode );
     383         200 :     mEncoding = Encoding;
     384             : }
     385             : 
     386             : 
     387             : // XInputStream
     388             : 
     389           0 : sal_Int32 OTextInputStream::readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
     390             :     throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception)
     391             : {
     392           0 :     return mxStream->readBytes( aData, nBytesToRead );
     393             : }
     394             : 
     395           0 : sal_Int32 OTextInputStream::readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
     396             :     throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception)
     397             : {
     398           0 :     return mxStream->readSomeBytes( aData, nMaxBytesToRead );
     399             : }
     400             : 
     401           0 : void OTextInputStream::skipBytes( sal_Int32 nBytesToSkip )
     402             :     throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException, std::exception)
     403             : {
     404           0 :     mxStream->skipBytes( nBytesToSkip );
     405           0 : }
     406             : 
     407           0 : sal_Int32 OTextInputStream::available(  )
     408             :     throw(NotConnectedException, IOException, RuntimeException, std::exception)
     409             : {
     410           0 :     return mxStream->available();
     411             : }
     412             : 
     413           0 : void OTextInputStream::closeInput(  )
     414             :     throw(NotConnectedException, IOException, RuntimeException, std::exception)
     415             : {
     416           0 :     mxStream->closeInput();
     417           0 : }
     418             : 
     419             : 
     420             : 
     421             : // XActiveDataSink
     422             : 
     423         200 : void OTextInputStream::setInputStream( const Reference< XInputStream >& aStream )
     424             :     throw(RuntimeException, std::exception)
     425             : {
     426         200 :     mxStream = aStream;
     427         200 : }
     428             : 
     429           0 : Reference< XInputStream > OTextInputStream::getInputStream()
     430             :     throw(RuntimeException, std::exception)
     431             : {
     432           0 :     return mxStream;
     433             : }
     434             : 
     435             : 
     436         201 : Reference< XInterface > SAL_CALL TextInputStream_CreateInstance(
     437             :     SAL_UNUSED_PARAMETER const Reference< XComponentContext > &)
     438             : {
     439         201 :     return Reference < XInterface >( static_cast<OWeakObject *>(new OTextInputStream()) );
     440             : }
     441             : 
     442         174 : OUString TextInputStream_getImplementationName()
     443             : {
     444         174 :     return OUString ( IMPLEMENTATION_NAME );
     445             : }
     446             : 
     447           8 : Sequence< OUString > TextInputStream_getSupportedServiceNames()
     448             : {
     449           8 :     Sequence< OUString > seqNames(1);
     450           8 :     seqNames.getArray()[0] = SERVICE_NAME;
     451           8 :     return seqNames;
     452             : }
     453             : 
     454           1 : OUString OTextInputStream::getImplementationName() throw(std::exception)
     455             : {
     456           1 :     return TextInputStream_getImplementationName();
     457             : }
     458             : 
     459           0 : sal_Bool OTextInputStream::supportsService(const OUString& ServiceName) throw(std::exception)
     460             : {
     461           0 :     return cppu::supportsService(this, ServiceName);
     462             : }
     463             : 
     464           1 : Sequence< OUString > OTextInputStream::getSupportedServiceNames() throw(std::exception)
     465             : {
     466           1 :     return TextInputStream_getSupportedServiceNames();
     467             : }
     468             : 
     469             : }
     470             : 
     471             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11