LCOV - code coverage report
Current view: top level - libreoffice/io/source/stm - omark.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 341 0.0 %
Date: 2012-12-27 Functions: 0 50 0.0 %
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             : 
      21             : #include <map>
      22             : #include <vector>
      23             : 
      24             : #include <com/sun/star/io/XMarkableStream.hpp>
      25             : #include <com/sun/star/io/XOutputStream.hpp>
      26             : #include <com/sun/star/io/XInputStream.hpp>
      27             : #include <com/sun/star/io/XActiveDataSource.hpp>
      28             : #include <com/sun/star/io/XActiveDataSink.hpp>
      29             : #include <com/sun/star/io/XConnectable.hpp>
      30             : #include <com/sun/star/lang/XServiceInfo.hpp>
      31             : 
      32             : #include <cppuhelper/factory.hxx>
      33             : #include <cppuhelper/weak.hxx>      // OWeakObject
      34             : #include <cppuhelper/implbase5.hxx>
      35             : 
      36             : #include <osl/mutex.hxx>
      37             : #include <rtl/ustrbuf.hxx>
      38             : 
      39             : #include <string.h>
      40             : 
      41             : 
      42             : using namespace ::std;
      43             : using namespace ::rtl;
      44             : using namespace ::cppu;
      45             : using namespace ::osl;
      46             : using namespace ::com::sun::star::io;
      47             : using namespace ::com::sun::star::uno;
      48             : using namespace ::com::sun::star::lang;
      49             : 
      50             : #include "streamhelper.hxx"
      51             : #include "factreg.hxx"
      52             : 
      53             : namespace io_stm {
      54             : 
      55             : /***********************
      56             : *
      57             : * OMarkableOutputStream.
      58             : *
      59             : * This object allows to set marks in an outputstream. It is allowed to jump back to the marks and
      60             : * rewrite the some bytes.
      61             : *
      62             : *         The object must buffer the data since the last mark set. Flush will not
      63             : *         have any effect. As soon as the last mark has been removed, the object may write the data
      64             : *         through to the chained object.
      65             : *
      66             : **********************/
      67             : class OMarkableOutputStream :
      68             :     public WeakImplHelper5< XOutputStream ,
      69             :                             XActiveDataSource ,
      70             :                             XMarkableStream ,
      71             :                             XConnectable,
      72             :                             XServiceInfo
      73             :                           >
      74             : {
      75             : public:
      76             :     OMarkableOutputStream(  );
      77             :     ~OMarkableOutputStream();
      78             : 
      79             : public: // XOutputStream
      80             :     virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData)
      81             :         throw ( NotConnectedException,
      82             :                 BufferSizeExceededException,
      83             :                 RuntimeException);
      84             :     virtual void SAL_CALL flush(void)
      85             :         throw ( NotConnectedException,
      86             :                 BufferSizeExceededException,
      87             :                 RuntimeException);
      88             :     virtual void SAL_CALL closeOutput(void)
      89             :         throw ( NotConnectedException,
      90             :                 BufferSizeExceededException,
      91             :                 RuntimeException);
      92             : 
      93             : public: // XMarkable
      94             :     virtual sal_Int32 SAL_CALL createMark(void)
      95             :         throw (IOException, RuntimeException);
      96             :     virtual void SAL_CALL deleteMark(sal_Int32 Mark)
      97             :         throw (IOException,
      98             :                IllegalArgumentException,
      99             :                RuntimeException);
     100             :     virtual void SAL_CALL jumpToMark(sal_Int32 nMark)
     101             :         throw (IOException,
     102             :                IllegalArgumentException,
     103             :                RuntimeException);
     104             :     virtual void SAL_CALL jumpToFurthest(void)
     105             :         throw (IOException, RuntimeException);
     106             :     virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark)
     107             :         throw (IOException,
     108             :                IllegalArgumentException,
     109             :                RuntimeException);
     110             : 
     111             : public: // XActiveDataSource
     112             :     virtual void SAL_CALL setOutputStream(const Reference < XOutputStream > & aStream)
     113             :         throw (RuntimeException);
     114             :     virtual Reference < XOutputStream > SAL_CALL getOutputStream(void)
     115             :         throw (RuntimeException);
     116             : 
     117             : public: // XConnectable
     118             :     virtual void SAL_CALL setPredecessor(const Reference < XConnectable > & aPredecessor)
     119             :         throw (RuntimeException);
     120             :     virtual Reference < XConnectable > SAL_CALL getPredecessor(void) throw (RuntimeException);
     121             :     virtual void SAL_CALL setSuccessor(const Reference < XConnectable >& aSuccessor)
     122             :         throw (RuntimeException);
     123             :     virtual Reference<  XConnectable >  SAL_CALL getSuccessor(void) throw (RuntimeException);
     124             : 
     125             : public: // XServiceInfo
     126             :     OUString                     SAL_CALL getImplementationName() throw ();
     127             :     Sequence< OUString >         SAL_CALL getSupportedServiceNames(void) throw ();
     128             :     sal_Bool                        SAL_CALL supportsService(const OUString& ServiceName) throw ();
     129             : 
     130             : private:
     131             :     // helper methods
     132             :     void checkMarksAndFlush() throw( NotConnectedException, BufferSizeExceededException);
     133             : 
     134             :     Reference< XConnectable > m_succ;
     135             :     Reference< XConnectable > m_pred;
     136             : 
     137             :     Reference< XOutputStream >  m_output;
     138             :     sal_Bool m_bValidStream;
     139             : 
     140             :     IRingBuffer *m_pBuffer;
     141             :     map<sal_Int32,sal_Int32,less< sal_Int32 > > m_mapMarks;
     142             :     sal_Int32 m_nCurrentPos;
     143             :     sal_Int32 m_nCurrentMark;
     144             : 
     145             :     Mutex m_mutex;
     146             : };
     147             : 
     148           0 : OMarkableOutputStream::OMarkableOutputStream( )
     149             : {
     150           0 :     g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
     151           0 :     m_pBuffer = new MemRingBuffer;
     152           0 :     m_nCurrentPos = 0;
     153           0 :     m_nCurrentMark = 0;
     154           0 : }
     155             : 
     156           0 : OMarkableOutputStream::~OMarkableOutputStream()
     157             : {
     158           0 :     delete m_pBuffer;
     159           0 :     g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
     160           0 : }
     161             : 
     162             : 
     163             : // XOutputStream
     164           0 : void OMarkableOutputStream::writeBytes(const Sequence< sal_Int8 >& aData)
     165             :     throw ( NotConnectedException,
     166             :             BufferSizeExceededException,
     167             :             RuntimeException)
     168             : {
     169           0 :     if( m_bValidStream ) {
     170           0 :         if( m_mapMarks.empty() && ( m_pBuffer->getSize() == 0 ) ) {
     171             :             // no mark and  buffer active, simple write through
     172           0 :             m_output->writeBytes( aData );
     173             :         }
     174             :         else {
     175           0 :             MutexGuard guard( m_mutex );
     176             :             // new data must be buffered
     177             :             try
     178             :             {
     179           0 :                 m_pBuffer->writeAt( m_nCurrentPos , aData );
     180           0 :                 m_nCurrentPos += aData.getLength();
     181             :             }
     182           0 :             catch( IRingBuffer_OutOfBoundsException & )
     183             :             {
     184           0 :                 throw BufferSizeExceededException();
     185             :             }
     186           0 :             catch( IRingBuffer_OutOfMemoryException & )
     187             :             {
     188           0 :                 throw BufferSizeExceededException();
     189             :             }
     190           0 :             checkMarksAndFlush();
     191             :         }
     192             :     }
     193             :     else {
     194           0 :         throw NotConnectedException();
     195             :     }
     196           0 : }
     197             : 
     198           0 : void OMarkableOutputStream::flush(void)
     199             :     throw ( NotConnectedException,
     200             :             BufferSizeExceededException,
     201             :             RuntimeException)
     202             : {
     203           0 :     Reference< XOutputStream > output;
     204             :     {
     205           0 :         MutexGuard guard( m_mutex );
     206           0 :         output = m_output;
     207             :     }
     208             : 
     209             :     // Markable cannot flush buffered data, because the data may get rewritten,
     210             :     // however one can forward the flush to the chained stream to give it
     211             :     // a chance to write data buffered in the chained stream.
     212           0 :     if( output.is() )
     213             :     {
     214           0 :         output->flush();
     215           0 :     }
     216           0 : }
     217             : 
     218           0 : void OMarkableOutputStream::closeOutput(void)
     219             :     throw ( NotConnectedException,
     220             :             BufferSizeExceededException,
     221             :             RuntimeException)
     222             : {
     223           0 :     if( m_bValidStream ) {
     224           0 :         MutexGuard guard( m_mutex );
     225             :         // all marks must be cleared and all
     226             : 
     227           0 :         if( ! m_mapMarks.empty() )
     228             :         {
     229           0 :             m_mapMarks.clear();
     230             :          }
     231           0 :         m_nCurrentPos = m_pBuffer->getSize();
     232           0 :           checkMarksAndFlush();
     233             : 
     234           0 :         m_output->closeOutput();
     235             : 
     236           0 :         setOutputStream( Reference< XOutputStream > () );
     237           0 :         setPredecessor( Reference < XConnectable >() );
     238           0 :         setSuccessor( Reference< XConnectable > () );
     239             :     }
     240             :     else {
     241           0 :         throw NotConnectedException();
     242             :     }
     243           0 : }
     244             : 
     245             : 
     246           0 : sal_Int32 OMarkableOutputStream::createMark(void)
     247             :     throw ( IOException,
     248             :             RuntimeException)
     249             : {
     250           0 :     MutexGuard guard( m_mutex );
     251           0 :     sal_Int32 nMark = m_nCurrentMark;
     252             : 
     253           0 :     m_mapMarks[nMark] = m_nCurrentPos;
     254             : 
     255           0 :     m_nCurrentMark ++;
     256           0 :     return nMark;
     257             : }
     258             : 
     259           0 : void OMarkableOutputStream::deleteMark(sal_Int32 Mark)
     260             :     throw( IOException,
     261             :            IllegalArgumentException,
     262             :            RuntimeException)
     263             : {
     264           0 :     MutexGuard guard( m_mutex );
     265           0 :     map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii = m_mapMarks.find( Mark );
     266             : 
     267           0 :     if( ii == m_mapMarks.end() ) {
     268           0 :         OUStringBuffer buf( 128 );
     269           0 :         buf.appendAscii( "MarkableOutputStream::deleteMark unknown mark (" );
     270           0 :         buf.append( Mark );
     271           0 :         buf.appendAscii( ")");
     272           0 :         throw IllegalArgumentException( buf.makeStringAndClear(), *this, 0);
     273             :     }
     274             :     else {
     275           0 :         m_mapMarks.erase( ii );
     276           0 :         checkMarksAndFlush();
     277           0 :     }
     278           0 : }
     279             : 
     280           0 : void OMarkableOutputStream::jumpToMark(sal_Int32 nMark)
     281             :     throw (IOException,
     282             :            IllegalArgumentException,
     283             :            RuntimeException)
     284             : {
     285           0 :     MutexGuard guard( m_mutex );
     286           0 :     map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii = m_mapMarks.find( nMark );
     287             : 
     288           0 :     if( ii == m_mapMarks.end() ) {
     289           0 :         OUStringBuffer buf( 128 );
     290           0 :         buf.appendAscii( "MarkableOutputStream::jumpToMark unknown mark (" );
     291           0 :         buf.append( nMark );
     292           0 :         buf.appendAscii( ")");
     293           0 :         throw IllegalArgumentException( buf.makeStringAndClear(), *this, 0);
     294             :     }
     295             :     else {
     296           0 :         m_nCurrentPos = (*ii).second;
     297           0 :     }
     298           0 : }
     299             : 
     300           0 : void OMarkableOutputStream::jumpToFurthest(void)
     301             :     throw (IOException,
     302             :            RuntimeException)
     303             : {
     304           0 :     MutexGuard guard( m_mutex );
     305           0 :     m_nCurrentPos = m_pBuffer->getSize();
     306           0 :     checkMarksAndFlush();
     307           0 : }
     308             : 
     309           0 : sal_Int32 OMarkableOutputStream::offsetToMark(sal_Int32 nMark)
     310             :     throw (IOException,
     311             :            IllegalArgumentException,
     312             :            RuntimeException)
     313             : {
     314             : 
     315           0 :     MutexGuard guard( m_mutex );
     316           0 :     map<sal_Int32,sal_Int32,less<sal_Int32> >::const_iterator ii = m_mapMarks.find( nMark );
     317             : 
     318           0 :     if( ii == m_mapMarks.end() )
     319             :     {
     320           0 :         OUStringBuffer buf( 128 );
     321           0 :         buf.appendAscii( "MarkableOutputStream::offsetToMark unknown mark (" );
     322           0 :         buf.append( nMark );
     323           0 :         buf.appendAscii( ")");
     324           0 :         throw IllegalArgumentException( buf.makeStringAndClear(), *this, 0);
     325             :     }
     326           0 :     return m_nCurrentPos - (*ii).second;
     327             : }
     328             : 
     329             : 
     330             : 
     331             : // XActiveDataSource2
     332           0 : void OMarkableOutputStream::setOutputStream(const Reference < XOutputStream >& aStream)
     333             :     throw (RuntimeException)
     334             : {
     335           0 :     if( m_output != aStream ) {
     336           0 :         m_output = aStream;
     337             : 
     338           0 :         Reference < XConnectable > succ( m_output , UNO_QUERY );
     339           0 :         setSuccessor( succ );
     340             :     }
     341           0 :     m_bValidStream = m_output.is();
     342           0 : }
     343             : 
     344           0 : Reference< XOutputStream > OMarkableOutputStream::getOutputStream(void) throw (RuntimeException)
     345             : {
     346           0 :     return m_output;
     347             : }
     348             : 
     349             : 
     350             : 
     351           0 : void OMarkableOutputStream::setSuccessor( const Reference< XConnectable > &r )
     352             :     throw (RuntimeException)
     353             : {
     354             :      /// if the references match, nothing needs to be done
     355           0 :      if( m_succ != r ) {
     356             :          /// store the reference for later use
     357           0 :          m_succ = r;
     358             : 
     359           0 :          if( m_succ.is() ) {
     360           0 :               m_succ->setPredecessor( Reference < XConnectable > (
     361           0 :                   (static_cast< XConnectable *  >(this)) ) );
     362             :          }
     363             :      }
     364           0 : }
     365           0 : Reference <XConnectable > OMarkableOutputStream::getSuccessor()     throw (RuntimeException)
     366             : {
     367           0 :     return m_succ;
     368             : }
     369             : 
     370             : 
     371             : // XDataSource
     372           0 : void OMarkableOutputStream::setPredecessor( const Reference< XConnectable > &r )
     373             :     throw (RuntimeException)
     374             : {
     375           0 :     if( r != m_pred ) {
     376           0 :         m_pred = r;
     377           0 :         if( m_pred.is() ) {
     378           0 :             m_pred->setSuccessor( Reference < XConnectable > (
     379           0 :                 (static_cast< XConnectable *  >(this )) ) );
     380             :         }
     381             :     }
     382           0 : }
     383           0 : Reference < XConnectable > OMarkableOutputStream::getPredecessor() throw (RuntimeException)
     384             : {
     385           0 :     return m_pred;
     386             : }
     387             : 
     388             : 
     389             : // private methods
     390             : 
     391           0 : void OMarkableOutputStream::checkMarksAndFlush() throw(     NotConnectedException,
     392             :                                                             BufferSizeExceededException)
     393             : {
     394           0 :     map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii;
     395             : 
     396             :     // find the smallest mark
     397           0 :     sal_Int32 nNextFound = m_nCurrentPos;
     398           0 :     for( ii = m_mapMarks.begin() ; ii != m_mapMarks.end() ; ++ii ) {
     399           0 :         if( (*ii).second <= nNextFound )  {
     400           0 :             nNextFound = (*ii).second;
     401             :         }
     402             :     }
     403             : 
     404           0 :     if( nNextFound ) {
     405             :         // some data must be released !
     406           0 :         m_nCurrentPos -= nNextFound;
     407           0 :         for( ii = m_mapMarks.begin() ; ii != m_mapMarks.end() ; ++ii ) {
     408           0 :             (*ii).second -= nNextFound;
     409             :         }
     410             : 
     411           0 :         Sequence<sal_Int8> seq(nNextFound);
     412           0 :         m_pBuffer->readAt( 0 , seq , nNextFound );
     413           0 :         m_pBuffer->forgetFromStart( nNextFound );
     414             : 
     415             :         // now write data through to streams
     416           0 :         m_output->writeBytes( seq );
     417             :     }
     418             :     else {
     419             :         // nothing to do. There is a mark or the current cursor position, that prevents
     420             :         // releasing data !
     421             :     }
     422           0 : }
     423             : 
     424             : 
     425             : // XServiceInfo
     426           0 : OUString OMarkableOutputStream::getImplementationName() throw ()
     427             : {
     428           0 :     return OMarkableOutputStream_getImplementationName();
     429             : }
     430             : 
     431             : // XServiceInfo
     432           0 : sal_Bool OMarkableOutputStream::supportsService(const OUString& ServiceName) throw ()
     433             : {
     434           0 :     Sequence< OUString > aSNL = getSupportedServiceNames();
     435           0 :     const OUString * pArray = aSNL.getConstArray();
     436             : 
     437           0 :     for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
     438           0 :         if( pArray[i] == ServiceName )
     439           0 :             return sal_True;
     440             : 
     441           0 :     return sal_False;
     442             : }
     443             : 
     444             : // XServiceInfo
     445           0 : Sequence< OUString > OMarkableOutputStream::getSupportedServiceNames(void) throw ()
     446             : {
     447           0 :     return OMarkableOutputStream_getSupportedServiceNames();
     448             : }
     449             : 
     450             : 
     451             : 
     452             : 
     453             : /*------------------------
     454             : *
     455             : * external binding
     456             : *
     457             : *------------------------*/
     458           0 : Reference< XInterface > SAL_CALL OMarkableOutputStream_CreateInstance(
     459             :     SAL_UNUSED_PARAMETER const Reference < XComponentContext > & )
     460             :     throw(Exception)
     461             : {
     462           0 :     OMarkableOutputStream *p = new OMarkableOutputStream( );
     463             : 
     464           0 :     return Reference < XInterface > ( ( OWeakObject * ) p );
     465             : }
     466             : 
     467           0 : OUString    OMarkableOutputStream_getImplementationName()
     468             : {
     469           0 :     return OUString("com.sun.star.comp.io.stm.MarkableOutputStream");
     470             : }
     471             : 
     472           0 : Sequence<OUString> OMarkableOutputStream_getSupportedServiceNames(void)
     473             : {
     474           0 :     Sequence<OUString> aRet(1);
     475           0 :     aRet.getArray()[0] = "com.sun.star.io.MarkableOutputStream";
     476             : 
     477           0 :     return aRet;
     478             : }
     479             : 
     480             : 
     481             : 
     482             : 
     483             : 
     484             : 
     485             : //------------------------------------------------
     486             : //
     487             : // XMarkableInputStream
     488             : //
     489             : //------------------------------------------------
     490             : 
     491             : class OMarkableInputStream :
     492             :     public WeakImplHelper5
     493             :     <
     494             :              XInputStream,
     495             :              XActiveDataSink,
     496             :              XMarkableStream,
     497             :              XConnectable,
     498             :              XServiceInfo
     499             :     >
     500             : {
     501             : public:
     502             :     OMarkableInputStream(  );
     503             :     ~OMarkableInputStream();
     504             : 
     505             : 
     506             : public: // XInputStream
     507             :     virtual sal_Int32 SAL_CALL readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
     508             :         throw ( NotConnectedException,
     509             :                 BufferSizeExceededException,
     510             :                 RuntimeException) ;
     511             :     virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
     512             :         throw ( NotConnectedException,
     513             :                 BufferSizeExceededException,
     514             :                 RuntimeException);
     515             :     virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip)
     516             :         throw ( NotConnectedException,
     517             :                 BufferSizeExceededException,
     518             :                 RuntimeException);
     519             : 
     520             :     virtual sal_Int32 SAL_CALL available(void)
     521             :         throw ( NotConnectedException,
     522             :                 RuntimeException);
     523             :     virtual void SAL_CALL closeInput(void) throw (NotConnectedException, RuntimeException);
     524             : 
     525             : public: // XMarkable
     526             :     virtual sal_Int32 SAL_CALL createMark(void)
     527             :         throw (IOException, RuntimeException);
     528             :     virtual void SAL_CALL deleteMark(sal_Int32 Mark)
     529             :         throw (IOException, IllegalArgumentException, RuntimeException);
     530             :     virtual void SAL_CALL jumpToMark(sal_Int32 nMark)
     531             :         throw (IOException, IllegalArgumentException, RuntimeException);
     532             :     virtual void SAL_CALL jumpToFurthest(void)
     533             :         throw (IOException, RuntimeException);
     534             :     virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark)
     535             :         throw (IOException, IllegalArgumentException,RuntimeException);
     536             : 
     537             : public: // XActiveDataSink
     538             :     virtual void SAL_CALL setInputStream(const Reference < XInputStream > & aStream)
     539             :         throw (RuntimeException);
     540             :     virtual Reference < XInputStream > SAL_CALL getInputStream(void)
     541             :         throw (RuntimeException);
     542             : 
     543             : public: // XConnectable
     544             :     virtual void SAL_CALL setPredecessor(const Reference < XConnectable > & aPredecessor)
     545             :         throw (RuntimeException);
     546             :     virtual Reference < XConnectable > SAL_CALL getPredecessor(void)
     547             :         throw (RuntimeException);
     548             :     virtual void SAL_CALL setSuccessor(const Reference < XConnectable > & aSuccessor)
     549             :         throw (RuntimeException);
     550             :     virtual Reference < XConnectable > SAL_CALL getSuccessor(void) throw (RuntimeException);
     551             : 
     552             : public: // XServiceInfo
     553             :     OUString                     SAL_CALL getImplementationName() throw ();
     554             :     Sequence< OUString >         SAL_CALL getSupportedServiceNames(void) throw ();
     555             :     sal_Bool                         SAL_CALL  supportsService(const OUString& ServiceName) throw ();
     556             : 
     557             : private:
     558             :     void checkMarksAndFlush();
     559             : 
     560             :     Reference < XConnectable >  m_succ;
     561             :     Reference < XConnectable >  m_pred;
     562             : 
     563             :     Reference< XInputStream > m_input;
     564             :     sal_Bool m_bValidStream;
     565             : 
     566             :     IRingBuffer *m_pBuffer;
     567             :     map<sal_Int32,sal_Int32,less< sal_Int32 > > m_mapMarks;
     568             :     sal_Int32 m_nCurrentPos;
     569             :     sal_Int32 m_nCurrentMark;
     570             : 
     571             :     Mutex m_mutex;
     572             : };
     573             : 
     574           0 : OMarkableInputStream::OMarkableInputStream()
     575             : {
     576           0 :     g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
     577           0 :     m_nCurrentPos = 0;
     578           0 :     m_nCurrentMark = 0;
     579           0 :     m_pBuffer = new MemRingBuffer;
     580           0 : }
     581             : 
     582             : 
     583           0 : OMarkableInputStream::~OMarkableInputStream()
     584             : {
     585           0 :     if( m_pBuffer ) {
     586           0 :         delete m_pBuffer;
     587             :     }
     588           0 :     g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
     589           0 : }
     590             : 
     591             : 
     592             : 
     593             : 
     594             : // XInputStream
     595             : 
     596           0 : sal_Int32 OMarkableInputStream::readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
     597             :     throw ( NotConnectedException,
     598             :             BufferSizeExceededException,
     599             :             RuntimeException)
     600             : {
     601             :     sal_Int32 nBytesRead;
     602             : 
     603           0 :     if( m_bValidStream ) {
     604           0 :         MutexGuard guard( m_mutex );
     605           0 :         if( m_mapMarks.empty() && ! m_pBuffer->getSize() ) {
     606             :             // normal read !
     607           0 :             nBytesRead = m_input->readBytes( aData, nBytesToRead );
     608             :         }
     609             :         else {
     610             :             // read from buffer
     611             :             sal_Int32 nRead;
     612             : 
     613             :             // read enough bytes into buffer
     614           0 :             if( m_pBuffer->getSize() - m_nCurrentPos < nBytesToRead  ) {
     615           0 :                 sal_Int32 nToRead = nBytesToRead - ( m_pBuffer->getSize() - m_nCurrentPos );
     616           0 :                 nRead = m_input->readBytes( aData , nToRead );
     617             : 
     618             :                 OSL_ASSERT( aData.getLength() == nRead );
     619             : 
     620             :                 try
     621             :                 {
     622           0 :                     m_pBuffer->writeAt( m_pBuffer->getSize() , aData );
     623             :                 }
     624           0 :                 catch( IRingBuffer_OutOfMemoryException & ) {
     625           0 :                     throw BufferSizeExceededException();
     626             :                 }
     627           0 :                 catch( IRingBuffer_OutOfBoundsException & ) {
     628           0 :                     throw BufferSizeExceededException();
     629             :                 }
     630             : 
     631           0 :                 if( nRead < nToRead ) {
     632           0 :                     nBytesToRead = nBytesToRead - (nToRead-nRead);
     633             :                 }
     634             :             }
     635             : 
     636             :             OSL_ASSERT( m_pBuffer->getSize() - m_nCurrentPos >= nBytesToRead  );
     637             : 
     638           0 :             m_pBuffer->readAt( m_nCurrentPos , aData , nBytesToRead );
     639             : 
     640           0 :             m_nCurrentPos += nBytesToRead;
     641           0 :             nBytesRead = nBytesToRead;
     642           0 :         }
     643             :     }
     644             :     else {
     645             :         throw NotConnectedException(
     646             :             OUString("MarkableInputStream::readBytes NotConnectedException") ,
     647           0 :             *this );
     648             :     }
     649           0 :     return nBytesRead;
     650             : }
     651             : 
     652             : 
     653           0 : sal_Int32 OMarkableInputStream::readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
     654             :     throw ( NotConnectedException,
     655             :             BufferSizeExceededException,
     656             :             RuntimeException)
     657             : {
     658             : 
     659             :     sal_Int32 nBytesRead;
     660           0 :     if( m_bValidStream ) {
     661           0 :         MutexGuard guard( m_mutex );
     662           0 :         if( m_mapMarks.empty() && ! m_pBuffer->getSize() ) {
     663             :             // normal read !
     664           0 :             nBytesRead = m_input->readSomeBytes( aData, nMaxBytesToRead );
     665             :         }
     666             :         else {
     667             :             // read from buffer
     668           0 :             sal_Int32 nRead = 0;
     669           0 :             sal_Int32 nInBuffer = m_pBuffer->getSize() - m_nCurrentPos;
     670           0 :             sal_Int32 nAdditionalBytesToRead = Min(nMaxBytesToRead-nInBuffer,m_input->available());
     671           0 :             nAdditionalBytesToRead = Max(0 , nAdditionalBytesToRead );
     672             : 
     673             :             // read enough bytes into buffer
     674           0 :             if( 0 == nInBuffer ) {
     675           0 :                 nRead = m_input->readSomeBytes( aData , nMaxBytesToRead );
     676             :             }
     677           0 :             else if( nAdditionalBytesToRead ) {
     678           0 :                 nRead = m_input->readBytes( aData , nAdditionalBytesToRead );
     679             :             }
     680             : 
     681           0 :             if( nRead ) {
     682           0 :                 aData.realloc( nRead );
     683             :                 try
     684             :                 {
     685           0 :                     m_pBuffer->writeAt( m_pBuffer->getSize() , aData );
     686             :                 }
     687           0 :                 catch( IRingBuffer_OutOfMemoryException & )
     688             :                 {
     689           0 :                     throw BufferSizeExceededException();
     690             :                 }
     691           0 :                 catch( IRingBuffer_OutOfBoundsException &  )
     692             :                 {
     693           0 :                     throw BufferSizeExceededException();
     694             :                 }
     695             :             }
     696             : 
     697           0 :             nBytesRead = Min( nMaxBytesToRead , nInBuffer + nRead );
     698             : 
     699             :             // now take everything from buffer !
     700           0 :             m_pBuffer->readAt( m_nCurrentPos , aData , nBytesRead );
     701             : 
     702           0 :             m_nCurrentPos += nBytesRead;
     703           0 :         }
     704             :     }
     705             :     else
     706             :     {
     707             :         throw NotConnectedException(
     708             :             OUString("MarkableInputStream::readSomeBytes NotConnectedException") ,
     709           0 :             *this );
     710             :     }
     711           0 :     return nBytesRead;
     712             : 
     713             : 
     714             : }
     715             : 
     716             : 
     717           0 : void OMarkableInputStream::skipBytes(sal_Int32 nBytesToSkip)
     718             :     throw ( NotConnectedException,
     719             :             BufferSizeExceededException,
     720             :             RuntimeException)
     721             : {
     722           0 :     if ( nBytesToSkip < 0 )
     723             :         throw BufferSizeExceededException(
     724             :             OUString("precondition not met: XInputStream::skipBytes: non-negative integer required!"),
     725             :             *this
     726           0 :         );
     727             : 
     728             :     // this method is blocking
     729           0 :     Sequence<sal_Int8> seqDummy( nBytesToSkip );
     730           0 :     readBytes( seqDummy , nBytesToSkip );
     731           0 : }
     732             : 
     733           0 : sal_Int32 OMarkableInputStream::available(void) throw (NotConnectedException, RuntimeException)
     734             : {
     735             :     sal_Int32 nAvail;
     736           0 :     if( m_bValidStream ) {
     737           0 :         MutexGuard guard( m_mutex );
     738           0 :         nAvail = m_input->available() + ( m_pBuffer->getSize() - m_nCurrentPos );
     739             :     }
     740             :     else
     741             :     {
     742             :         throw NotConnectedException(
     743             :             OUString("MarkableInputStream::available NotConnectedException") ,
     744           0 :             *this );
     745             :     }
     746             : 
     747           0 :     return nAvail;
     748             : }
     749             : 
     750             : 
     751           0 : void OMarkableInputStream::closeInput(void) throw (NotConnectedException, RuntimeException)
     752             : {
     753           0 :     if( m_bValidStream ) {
     754           0 :         MutexGuard guard( m_mutex );
     755             : 
     756           0 :         m_input->closeInput();
     757             : 
     758           0 :         setInputStream( Reference< XInputStream > () );
     759           0 :         setPredecessor( Reference< XConnectable > () );
     760           0 :         setSuccessor( Reference< XConnectable >() );
     761             : 
     762           0 :         delete m_pBuffer;
     763           0 :         m_pBuffer = 0;
     764           0 :         m_nCurrentPos = 0;
     765           0 :         m_nCurrentMark = 0;
     766             :     }
     767             :     else {
     768             :         throw NotConnectedException(
     769             :             OUString("MarkableInputStream::closeInput NotConnectedException") ,
     770           0 :             *this );
     771             :     }
     772           0 : }
     773             : 
     774             : // XMarkable
     775             : 
     776           0 : sal_Int32 OMarkableInputStream::createMark(void)            throw (IOException, RuntimeException)
     777             : {
     778           0 :     MutexGuard guard( m_mutex );
     779           0 :     sal_Int32 nMark = m_nCurrentMark;
     780             : 
     781           0 :     m_mapMarks[nMark] = m_nCurrentPos;
     782             : 
     783           0 :     m_nCurrentMark ++;
     784           0 :     return nMark;
     785             : }
     786             : 
     787           0 : void OMarkableInputStream::deleteMark(sal_Int32 Mark)       throw (IOException, IllegalArgumentException, RuntimeException)
     788             : {
     789           0 :     MutexGuard guard( m_mutex );
     790           0 :     map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii = m_mapMarks.find( Mark );
     791             : 
     792           0 :     if( ii == m_mapMarks.end() ) {
     793           0 :         OUStringBuffer buf( 128 );
     794           0 :         buf.appendAscii( "MarkableInputStream::deleteMark unknown mark (" );
     795           0 :         buf.append( Mark );
     796           0 :         buf.appendAscii( ")");
     797           0 :         throw IllegalArgumentException( buf.makeStringAndClear(), *this , 0 );
     798             :     }
     799             :     else {
     800           0 :         m_mapMarks.erase( ii );
     801           0 :         checkMarksAndFlush();
     802           0 :     }
     803           0 : }
     804             : 
     805           0 : void OMarkableInputStream::jumpToMark(sal_Int32 nMark)
     806             :     throw (IOException,
     807             :            IllegalArgumentException,
     808             :            RuntimeException)
     809             : {
     810           0 :     MutexGuard guard( m_mutex );
     811           0 :     map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii = m_mapMarks.find( nMark );
     812             : 
     813           0 :     if( ii == m_mapMarks.end() )
     814             :     {
     815           0 :         OUStringBuffer buf( 128 );
     816           0 :         buf.appendAscii( "MarkableInputStream::jumpToMark unknown mark (" );
     817           0 :         buf.append( nMark );
     818           0 :         buf.appendAscii( ")");
     819           0 :         throw IllegalArgumentException( buf.makeStringAndClear(), *this , 0 );
     820             :     }
     821             :     else
     822             :     {
     823           0 :         m_nCurrentPos = (*ii).second;
     824           0 :     }
     825           0 : }
     826             : 
     827           0 : void OMarkableInputStream::jumpToFurthest(void)         throw (IOException, RuntimeException)
     828             : {
     829           0 :     MutexGuard guard( m_mutex );
     830           0 :     m_nCurrentPos = m_pBuffer->getSize();
     831           0 :     checkMarksAndFlush();
     832           0 : }
     833             : 
     834           0 : sal_Int32 OMarkableInputStream::offsetToMark(sal_Int32 nMark)
     835             :      throw (IOException,
     836             :            IllegalArgumentException,
     837             :            RuntimeException)
     838             : {
     839           0 :     MutexGuard guard( m_mutex );
     840           0 :     map<sal_Int32,sal_Int32,less<sal_Int32> >::const_iterator ii = m_mapMarks.find( nMark );
     841             : 
     842           0 :     if( ii == m_mapMarks.end() )
     843             :     {
     844           0 :         OUStringBuffer buf( 128 );
     845           0 :         buf.appendAscii( "MarkableInputStream::offsetToMark unknown mark (" );
     846           0 :         buf.append( nMark );
     847           0 :         buf.appendAscii( ")");
     848           0 :         throw IllegalArgumentException( buf.makeStringAndClear(), *this , 0 );
     849             :     }
     850           0 :     return m_nCurrentPos - (*ii).second;
     851             : }
     852             : 
     853             : 
     854             : 
     855             : 
     856             : 
     857             : 
     858             : 
     859             : // XActiveDataSource
     860           0 : void OMarkableInputStream::setInputStream(const Reference< XInputStream > & aStream)
     861             :     throw (RuntimeException)
     862             : {
     863             : 
     864           0 :     if( m_input != aStream ) {
     865           0 :         m_input = aStream;
     866             : 
     867           0 :         Reference < XConnectable >  pred( m_input , UNO_QUERY );
     868           0 :         setPredecessor( pred );
     869             :     }
     870             : 
     871           0 :     m_bValidStream = m_input.is();
     872             : 
     873           0 : }
     874             : 
     875           0 : Reference< XInputStream > OMarkableInputStream::getInputStream(void) throw (RuntimeException)
     876             : {
     877           0 :     return m_input;
     878             : }
     879             : 
     880             : 
     881             : 
     882             : // XDataSink
     883           0 : void OMarkableInputStream::setSuccessor( const Reference< XConnectable > &r )
     884             :     throw (RuntimeException)
     885             : {
     886             :      /// if the references match, nothing needs to be done
     887           0 :      if( m_succ != r ) {
     888             :          /// store the reference for later use
     889           0 :          m_succ = r;
     890             : 
     891           0 :          if( m_succ.is() ) {
     892             :               /// set this instance as the sink !
     893           0 :               m_succ->setPredecessor( Reference< XConnectable > (
     894           0 :                   (static_cast< XConnectable *  >(this)) ) );
     895             :          }
     896             :      }
     897           0 : }
     898             : 
     899           0 : Reference < XConnectable >  OMarkableInputStream::getSuccessor() throw (RuntimeException)
     900             : {
     901           0 :     return m_succ;
     902             : }
     903             : 
     904             : 
     905             : // XDataSource
     906           0 : void OMarkableInputStream::setPredecessor( const Reference < XConnectable >  &r )
     907             :     throw (RuntimeException)
     908             : {
     909           0 :     if( r != m_pred ) {
     910           0 :         m_pred = r;
     911           0 :         if( m_pred.is() ) {
     912           0 :             m_pred->setSuccessor( Reference< XConnectable > (
     913           0 :                 (static_cast< XConnectable *  >(this)) ) );
     914             :         }
     915             :     }
     916           0 : }
     917           0 : Reference< XConnectable >  OMarkableInputStream::getPredecessor() throw (RuntimeException)
     918             : {
     919           0 :     return m_pred;
     920             : }
     921             : 
     922             : 
     923             : 
     924             : 
     925           0 : void OMarkableInputStream::checkMarksAndFlush()
     926             : {
     927           0 :     map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii;
     928             : 
     929             :     // find the smallest mark
     930           0 :     sal_Int32 nNextFound = m_nCurrentPos;
     931           0 :     for( ii = m_mapMarks.begin() ; ii != m_mapMarks.end() ; ++ii ) {
     932           0 :         if( (*ii).second <= nNextFound )  {
     933           0 :             nNextFound = (*ii).second;
     934             :         }
     935             :     }
     936             : 
     937           0 :     if( nNextFound ) {
     938             :         // some data must be released !
     939           0 :         m_nCurrentPos -= nNextFound;
     940           0 :         for( ii = m_mapMarks.begin() ; ii != m_mapMarks.end() ; ++ii ) {
     941           0 :             (*ii).second -= nNextFound;
     942             :         }
     943             : 
     944           0 :         m_pBuffer->forgetFromStart( nNextFound );
     945             : 
     946             :     }
     947             :     else {
     948             :         // nothing to do. There is a mark or the current cursor position, that prevents
     949             :         // releasing data !
     950             :     }
     951           0 : }
     952             : 
     953             : 
     954             : 
     955             : // XServiceInfo
     956           0 : OUString OMarkableInputStream::getImplementationName() throw ()
     957             : {
     958           0 :     return OMarkableInputStream_getImplementationName();
     959             : }
     960             : 
     961             : // XServiceInfo
     962           0 : sal_Bool OMarkableInputStream::supportsService(const OUString& ServiceName) throw ()
     963             : {
     964           0 :     Sequence< OUString > aSNL = getSupportedServiceNames();
     965           0 :     const OUString * pArray = aSNL.getConstArray();
     966             : 
     967           0 :     for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
     968           0 :         if( pArray[i] == ServiceName )
     969           0 :             return sal_True;
     970             : 
     971           0 :     return sal_False;
     972             : }
     973             : 
     974             : // XServiceInfo
     975           0 : Sequence< OUString > OMarkableInputStream::getSupportedServiceNames(void) throw ()
     976             : {
     977           0 :     return OMarkableInputStream_getSupportedServiceNames();
     978             : }
     979             : 
     980             : 
     981             : /*------------------------
     982             : *
     983             : * external binding
     984             : *
     985             : *------------------------*/
     986           0 : Reference < XInterface > SAL_CALL OMarkableInputStream_CreateInstance(
     987             :     SAL_UNUSED_PARAMETER const Reference < XComponentContext > & )
     988             :     throw(Exception)
     989             : {
     990           0 :     OMarkableInputStream *p = new OMarkableInputStream( );
     991           0 :     return Reference< XInterface > ( (OWeakObject * ) p );
     992             : }
     993             : 
     994           0 : OUString    OMarkableInputStream_getImplementationName()
     995             : {
     996           0 :     return OUString("com.sun.star.comp.io.stm.MarkableInputStream");
     997             : }
     998             : 
     999           0 : Sequence<OUString> OMarkableInputStream_getSupportedServiceNames(void)
    1000             : {
    1001           0 :     Sequence<OUString> aRet(1);
    1002           0 :     aRet.getArray()[0] = "com.sun.star.io.MarkableInputStream";
    1003           0 :     return aRet;
    1004             : }
    1005             : 
    1006             : }
    1007             : 
    1008             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10