diff options
Diffstat (limited to 'io/source/stm/omark.cxx')
-rw-r--r-- | io/source/stm/omark.cxx | 1018 |
1 files changed, 1018 insertions, 0 deletions
diff --git a/io/source/stm/omark.cxx b/io/source/stm/omark.cxx new file mode 100644 index 000000000000..29d326170ff1 --- /dev/null +++ b/io/source/stm/omark.cxx @@ -0,0 +1,1018 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: omark.cxx,v $ + * $Revision: 1.11 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_io.hxx" + +#include <map> +#include <vector> + +#include <com/sun/star/io/XMarkableStream.hpp> +#include <com/sun/star/io/XOutputStream.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/io/XActiveDataSource.hpp> +#include <com/sun/star/io/XActiveDataSink.hpp> +#include <com/sun/star/io/XConnectable.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> + +#include <cppuhelper/factory.hxx> +#include <cppuhelper/weak.hxx> // OWeakObject +#include <cppuhelper/implbase5.hxx> + +#include <osl/mutex.hxx> +#include <rtl/ustrbuf.hxx> + +#include <string.h> + + +using namespace ::std; +using namespace ::rtl; +using namespace ::cppu; +using namespace ::osl; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; + +#include "streamhelper.hxx" +#include "factreg.hxx" + +namespace io_stm { + +/*********************** +* +* OMarkableOutputStream. +* +* This object allows to set marks in an outputstream. It is allowed to jump back to the marks and +* rewrite the some bytes. +* +* The object must buffer the data since the last mark set. Flush will not +* have any effect. As soon as the last mark has been removed, the object may write the data +* through to the chained object. +* +**********************/ +class OMarkableOutputStream : + public WeakImplHelper5< XOutputStream , + XActiveDataSource , + XMarkableStream , + XConnectable, + XServiceInfo + > +{ +public: + OMarkableOutputStream( ); + ~OMarkableOutputStream(); + +public: // XOutputStream + virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData) + throw ( NotConnectedException, + BufferSizeExceededException, + RuntimeException); + virtual void SAL_CALL flush(void) + throw ( NotConnectedException, + BufferSizeExceededException, + RuntimeException); + virtual void SAL_CALL closeOutput(void) + throw ( NotConnectedException, + BufferSizeExceededException, + RuntimeException); + +public: // XMarkable + virtual sal_Int32 SAL_CALL createMark(void) + throw (IOException, RuntimeException); + virtual void SAL_CALL deleteMark(sal_Int32 Mark) + throw (IOException, + IllegalArgumentException, + RuntimeException); + virtual void SAL_CALL jumpToMark(sal_Int32 nMark) + throw (IOException, + IllegalArgumentException, + RuntimeException); + virtual void SAL_CALL jumpToFurthest(void) + throw (IOException, RuntimeException); + virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark) + throw (IOException, + IllegalArgumentException, + RuntimeException); + +public: // XActiveDataSource + virtual void SAL_CALL setOutputStream(const Reference < XOutputStream > & aStream) + throw (RuntimeException); + virtual Reference < XOutputStream > SAL_CALL getOutputStream(void) + throw (RuntimeException); + +public: // XConnectable + virtual void SAL_CALL setPredecessor(const Reference < XConnectable > & aPredecessor) + throw (RuntimeException); + virtual Reference < XConnectable > SAL_CALL getPredecessor(void) throw (RuntimeException); + virtual void SAL_CALL setSuccessor(const Reference < XConnectable >& aSuccessor) + throw (RuntimeException); + virtual Reference< XConnectable > SAL_CALL getSuccessor(void) throw (RuntimeException); + +public: // XServiceInfo + OUString SAL_CALL getImplementationName() throw (); + Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw (); + sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw (); + +private: + // helper methods + void checkMarksAndFlush() throw( NotConnectedException, BufferSizeExceededException); + + Reference< XConnectable > m_succ; + Reference< XConnectable > m_pred; + + Reference< XOutputStream > m_output; + sal_Bool m_bValidStream; + + IRingBuffer *m_pBuffer; + map<sal_Int32,sal_Int32,less< sal_Int32 > > m_mapMarks; + sal_Int32 m_nCurrentPos; + sal_Int32 m_nCurrentMark; + + Mutex m_mutex; +}; + +OMarkableOutputStream::OMarkableOutputStream( ) +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + m_pBuffer = new MemRingBuffer; + m_nCurrentPos = 0; + m_nCurrentMark = 0; +} + +OMarkableOutputStream::~OMarkableOutputStream() +{ + delete m_pBuffer; + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + + +// XOutputStream +void OMarkableOutputStream::writeBytes(const Sequence< sal_Int8 >& aData) + throw ( NotConnectedException, + BufferSizeExceededException, + RuntimeException) +{ + if( m_bValidStream ) { + if( m_mapMarks.empty() && ( m_pBuffer->getSize() == 0 ) ) { + // no mark and buffer active, simple write through + m_output->writeBytes( aData ); + } + else { + MutexGuard guard( m_mutex ); + // new data must be buffered + try + { + m_pBuffer->writeAt( m_nCurrentPos , aData ); + m_nCurrentPos += aData.getLength(); + } + catch( IRingBuffer_OutOfBoundsException & ) + { + throw BufferSizeExceededException(); + } + catch( IRingBuffer_OutOfMemoryException & ) + { + throw BufferSizeExceededException(); + } + checkMarksAndFlush(); + } + } + else { + throw NotConnectedException(); + } +} + +void OMarkableOutputStream::flush(void) + throw ( NotConnectedException, + BufferSizeExceededException, + RuntimeException) +{ + Reference< XOutputStream > output; + { + MutexGuard guard( m_mutex ); + output = m_output; + } + + // Markable cannot flush buffered data, because the data may get rewritten, + // however one can forward the flush to the chained stream to give it + // a chance to write data buffered in the chained stream. + if( output.is() ) + { + output->flush(); + } +} + +void OMarkableOutputStream::closeOutput(void) + throw ( NotConnectedException, + BufferSizeExceededException, + RuntimeException) +{ + if( m_bValidStream ) { + MutexGuard guard( m_mutex ); + // all marks must be cleared and all + + if( ! m_mapMarks.empty() ) + { + m_mapMarks.clear(); + } + m_nCurrentPos = m_pBuffer->getSize(); + checkMarksAndFlush(); + + m_output->closeOutput(); + + setOutputStream( Reference< XOutputStream > () ); + setPredecessor( Reference < XConnectable >() ); + setSuccessor( Reference< XConnectable > () ); + } + else { + throw NotConnectedException(); + } +} + + +sal_Int32 OMarkableOutputStream::createMark(void) + throw ( IOException, + RuntimeException) +{ + MutexGuard guard( m_mutex ); + sal_Int32 nMark = m_nCurrentMark; + + m_mapMarks[nMark] = m_nCurrentPos; + + m_nCurrentMark ++; + return nMark; +} + +void OMarkableOutputStream::deleteMark(sal_Int32 Mark) + throw( IOException, + IllegalArgumentException, + RuntimeException) +{ + MutexGuard guard( m_mutex ); + map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii = m_mapMarks.find( Mark ); + + if( ii == m_mapMarks.end() ) { + OUStringBuffer buf( 128 ); + buf.appendAscii( "MarkableOutputStream::deleteMark unknown mark (" ); + buf.append( Mark ); + buf.appendAscii( ")"); + throw IllegalArgumentException( buf.makeStringAndClear(), *this, 0); + } + else { + m_mapMarks.erase( ii ); + checkMarksAndFlush(); + } +} + +void OMarkableOutputStream::jumpToMark(sal_Int32 nMark) + throw (IOException, + IllegalArgumentException, + RuntimeException) +{ + MutexGuard guard( m_mutex ); + map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii = m_mapMarks.find( nMark ); + + if( ii == m_mapMarks.end() ) { + OUStringBuffer buf( 128 ); + buf.appendAscii( "MarkableOutputStream::jumpToMark unknown mark (" ); + buf.append( nMark ); + buf.appendAscii( ")"); + throw IllegalArgumentException( buf.makeStringAndClear(), *this, 0); + } + else { + m_nCurrentPos = (*ii).second; + } +} + +void OMarkableOutputStream::jumpToFurthest(void) + throw (IOException, + RuntimeException) +{ + MutexGuard guard( m_mutex ); + m_nCurrentPos = m_pBuffer->getSize(); + checkMarksAndFlush(); +} + +sal_Int32 OMarkableOutputStream::offsetToMark(sal_Int32 nMark) + throw (IOException, + IllegalArgumentException, + RuntimeException) +{ + + MutexGuard guard( m_mutex ); + map<sal_Int32,sal_Int32,less<sal_Int32> >::const_iterator ii = m_mapMarks.find( nMark ); + + if( ii == m_mapMarks.end() ) + { + OUStringBuffer buf( 128 ); + buf.appendAscii( "MarkableOutputStream::offsetToMark unknown mark (" ); + buf.append( nMark ); + buf.appendAscii( ")"); + throw IllegalArgumentException( buf.makeStringAndClear(), *this, 0); + } + return m_nCurrentPos - (*ii).second; +} + + + +// XActiveDataSource2 +void OMarkableOutputStream::setOutputStream(const Reference < XOutputStream >& aStream) + throw (RuntimeException) +{ + if( m_output != aStream ) { + m_output = aStream; + + Reference < XConnectable > succ( m_output , UNO_QUERY ); + setSuccessor( succ ); + } + m_bValidStream = m_output.is(); +} + +Reference< XOutputStream > OMarkableOutputStream::getOutputStream(void) throw (RuntimeException) +{ + return m_output; +} + + + +void OMarkableOutputStream::setSuccessor( const Reference< XConnectable > &r ) + throw (RuntimeException) +{ + /// if the references match, nothing needs to be done + if( m_succ != r ) { + /// store the reference for later use + m_succ = r; + + if( m_succ.is() ) { + m_succ->setPredecessor( Reference < XConnectable > ( + SAL_STATIC_CAST( XConnectable * , this ) ) ); + } + } +} +Reference <XConnectable > OMarkableOutputStream::getSuccessor() throw (RuntimeException) +{ + return m_succ; +} + + +// XDataSource +void OMarkableOutputStream::setPredecessor( const Reference< XConnectable > &r ) + throw (RuntimeException) +{ + if( r != m_pred ) { + m_pred = r; + if( m_pred.is() ) { + m_pred->setSuccessor( Reference < XConnectable > ( + SAL_STATIC_CAST ( XConnectable * , this ) ) ); + } + } +} +Reference < XConnectable > OMarkableOutputStream::getPredecessor() throw (RuntimeException) +{ + return m_pred; +} + + +// private methods + +void OMarkableOutputStream::checkMarksAndFlush() throw( NotConnectedException, + BufferSizeExceededException) +{ + map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii; + + // find the smallest mark + sal_Int32 nNextFound = m_nCurrentPos; + for( ii = m_mapMarks.begin() ; ii != m_mapMarks.end() ; ii ++ ) { + if( (*ii).second <= nNextFound ) { + nNextFound = (*ii).second; + } + } + + if( nNextFound ) { + // some data must be released ! + m_nCurrentPos -= nNextFound; + for( ii = m_mapMarks.begin() ; ii != m_mapMarks.end() ; ii ++ ) { + (*ii).second -= nNextFound; + } + + Sequence<sal_Int8> seq(nNextFound); + m_pBuffer->readAt( 0 , seq , nNextFound ); + m_pBuffer->forgetFromStart( nNextFound ); + + // now write data through to streams + m_output->writeBytes( seq ); + } + else { + // nothing to do. There is a mark or the current cursor position, that prevents + // releasing data ! + } +} + + +// XServiceInfo +OUString OMarkableOutputStream::getImplementationName() throw () +{ + return OMarkableOutputStream_getImplementationName(); +} + +// XServiceInfo +sal_Bool OMarkableOutputStream::supportsService(const OUString& ServiceName) throw () +{ + Sequence< OUString > aSNL = getSupportedServiceNames(); + const OUString * pArray = aSNL.getConstArray(); + + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return sal_True; + + return sal_False; +} + +// XServiceInfo +Sequence< OUString > OMarkableOutputStream::getSupportedServiceNames(void) throw () +{ + return OMarkableOutputStream_getSupportedServiceNames(); +} + + + + +/*------------------------ +* +* external binding +* +*------------------------*/ +Reference< XInterface > SAL_CALL OMarkableOutputStream_CreateInstance( const Reference < XComponentContext > & ) throw(Exception) +{ + OMarkableOutputStream *p = new OMarkableOutputStream( ); + + return Reference < XInterface > ( ( OWeakObject * ) p ); +} + +OUString OMarkableOutputStream_getImplementationName() +{ + return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.io.stm.MarkableOutputStream" )); +} + +Sequence<OUString> OMarkableOutputStream_getSupportedServiceNames(void) +{ + Sequence<OUString> aRet(1); + aRet.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.MarkableOutputStream" ) ); + + return aRet; +} + + + + + + +//------------------------------------------------ +// +// XMarkableInputStream +// +//------------------------------------------------ + +class OMarkableInputStream : + public WeakImplHelper5 + < + XInputStream, + XActiveDataSink, + XMarkableStream, + XConnectable, + XServiceInfo + > +{ +public: + OMarkableInputStream( ); + ~OMarkableInputStream(); + + +public: // XInputStream + virtual sal_Int32 SAL_CALL readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) + throw ( NotConnectedException, + BufferSizeExceededException, + RuntimeException) ; + virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) + throw ( NotConnectedException, + BufferSizeExceededException, + RuntimeException); + virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip) + throw ( NotConnectedException, + BufferSizeExceededException, + RuntimeException); + + virtual sal_Int32 SAL_CALL available(void) + throw ( NotConnectedException, + RuntimeException); + virtual void SAL_CALL closeInput(void) throw (NotConnectedException, RuntimeException); + +public: // XMarkable + virtual sal_Int32 SAL_CALL createMark(void) + throw (IOException, RuntimeException); + virtual void SAL_CALL deleteMark(sal_Int32 Mark) + throw (IOException, IllegalArgumentException, RuntimeException); + virtual void SAL_CALL jumpToMark(sal_Int32 nMark) + throw (IOException, IllegalArgumentException, RuntimeException); + virtual void SAL_CALL jumpToFurthest(void) + throw (IOException, RuntimeException); + virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark) + throw (IOException, IllegalArgumentException,RuntimeException); + +public: // XActiveDataSink + virtual void SAL_CALL setInputStream(const Reference < XInputStream > & aStream) + throw (RuntimeException); + virtual Reference < XInputStream > SAL_CALL getInputStream(void) + throw (RuntimeException); + +public: // XConnectable + virtual void SAL_CALL setPredecessor(const Reference < XConnectable > & aPredecessor) + throw (RuntimeException); + virtual Reference < XConnectable > SAL_CALL getPredecessor(void) + throw (RuntimeException); + virtual void SAL_CALL setSuccessor(const Reference < XConnectable > & aSuccessor) + throw (RuntimeException); + virtual Reference < XConnectable > SAL_CALL getSuccessor(void) throw (RuntimeException); + +public: // XServiceInfo + OUString SAL_CALL getImplementationName() throw (); + Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw (); + sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw (); + +private: + void checkMarksAndFlush(); + + Reference < XConnectable > m_succ; + Reference < XConnectable > m_pred; + + Reference< XInputStream > m_input; + sal_Bool m_bValidStream; + + IRingBuffer *m_pBuffer; + map<sal_Int32,sal_Int32,less< sal_Int32 > > m_mapMarks; + sal_Int32 m_nCurrentPos; + sal_Int32 m_nCurrentMark; + + Mutex m_mutex; +}; + +OMarkableInputStream::OMarkableInputStream() +{ + g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt ); + m_nCurrentPos = 0; + m_nCurrentMark = 0; + m_pBuffer = new MemRingBuffer; +} + + +OMarkableInputStream::~OMarkableInputStream() +{ + if( m_pBuffer ) { + delete m_pBuffer; + } + g_moduleCount.modCnt.release( &g_moduleCount.modCnt ); +} + + + + +// XInputStream + +sal_Int32 OMarkableInputStream::readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead) + throw ( NotConnectedException, + BufferSizeExceededException, + RuntimeException) +{ + sal_Int32 nBytesRead; + + if( m_bValidStream ) { + MutexGuard guard( m_mutex ); + if( m_mapMarks.empty() && ! m_pBuffer->getSize() ) { + // normal read ! + nBytesRead = m_input->readBytes( aData, nBytesToRead ); + } + else { + // read from buffer + sal_Int32 nRead; + + // read enough bytes into buffer + if( m_pBuffer->getSize() - m_nCurrentPos < nBytesToRead ) { + sal_Int32 nToRead = nBytesToRead - ( m_pBuffer->getSize() - m_nCurrentPos ); + nRead = m_input->readBytes( aData , nToRead ); + + OSL_ASSERT( aData.getLength() == nRead ); + + try + { + m_pBuffer->writeAt( m_pBuffer->getSize() , aData ); + } + catch( IRingBuffer_OutOfMemoryException & ) { + throw BufferSizeExceededException(); + } + catch( IRingBuffer_OutOfBoundsException & ) { + throw BufferSizeExceededException(); + } + + if( nRead < nToRead ) { + nBytesToRead = nBytesToRead - (nToRead-nRead); + } + } + + OSL_ASSERT( m_pBuffer->getSize() - m_nCurrentPos >= nBytesToRead ); + + m_pBuffer->readAt( m_nCurrentPos , aData , nBytesToRead ); + + m_nCurrentPos += nBytesToRead; + nBytesRead = nBytesToRead; + } + } + else { + throw NotConnectedException( + OUString( RTL_CONSTASCII_USTRINGPARAM("MarkableInputStream::readBytes NotConnectedException")) , + *this ); + } + return nBytesRead; +} + + +sal_Int32 OMarkableInputStream::readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead) + throw ( NotConnectedException, + BufferSizeExceededException, + RuntimeException) +{ + + sal_Int32 nBytesRead; + if( m_bValidStream ) { + MutexGuard guard( m_mutex ); + if( m_mapMarks.empty() && ! m_pBuffer->getSize() ) { + // normal read ! + nBytesRead = m_input->readSomeBytes( aData, nMaxBytesToRead ); + } + else { + // read from buffer + sal_Int32 nRead = 0; + sal_Int32 nInBuffer = m_pBuffer->getSize() - m_nCurrentPos; + sal_Int32 nAdditionalBytesToRead = Min(nMaxBytesToRead-nInBuffer,m_input->available()); + nAdditionalBytesToRead = Max(0 , nAdditionalBytesToRead ); + + // read enough bytes into buffer + if( 0 == nInBuffer ) { + nRead = m_input->readSomeBytes( aData , nMaxBytesToRead ); + } + else if( nAdditionalBytesToRead ) { + nRead = m_input->readBytes( aData , nAdditionalBytesToRead ); + } + + if( nRead ) { + aData.realloc( nRead ); + try + { + m_pBuffer->writeAt( m_pBuffer->getSize() , aData ); + } + catch( IRingBuffer_OutOfMemoryException & ) + { + throw BufferSizeExceededException(); + } + catch( IRingBuffer_OutOfBoundsException & ) + { + throw BufferSizeExceededException(); + } + } + + nBytesRead = Min( nMaxBytesToRead , nInBuffer + nRead ); + + // now take everything from buffer ! + m_pBuffer->readAt( m_nCurrentPos , aData , nBytesRead ); + + m_nCurrentPos += nBytesRead; + } + } + else + { + throw NotConnectedException( + OUString( RTL_CONSTASCII_USTRINGPARAM("MarkableInputStream::readSomeBytes NotConnectedException")) , + *this ); + } + return nBytesRead; + + +} + + +void OMarkableInputStream::skipBytes(sal_Int32 nBytesToSkip) + throw ( NotConnectedException, + BufferSizeExceededException, + RuntimeException) +{ + if ( nBytesToSkip < 0 ) + throw BufferSizeExceededException( + ::rtl::OUString::createFromAscii( "precondition not met: XInputStream::skipBytes: non-negative integer required!" ), + *this + ); + + // this method is blocking + sal_Int32 nRead; + Sequence<sal_Int8> seqDummy( nBytesToSkip ); + + nRead = readBytes( seqDummy , nBytesToSkip ); +} + +sal_Int32 OMarkableInputStream::available(void) throw (NotConnectedException, RuntimeException) +{ + sal_Int32 nAvail; + if( m_bValidStream ) { + MutexGuard guard( m_mutex ); + nAvail = m_input->available() + ( m_pBuffer->getSize() - m_nCurrentPos ); + } + else + { + throw NotConnectedException( + OUString( RTL_CONSTASCII_USTRINGPARAM( "MarkableInputStream::available NotConnectedException" ) ) , + *this ); + } + + return nAvail; +} + + +void OMarkableInputStream::closeInput(void) throw (NotConnectedException, RuntimeException) +{ + if( m_bValidStream ) { + MutexGuard guard( m_mutex ); + + m_input->closeInput(); + + setInputStream( Reference< XInputStream > () ); + setPredecessor( Reference< XConnectable > () ); + setSuccessor( Reference< XConnectable >() ); + + delete m_pBuffer; + m_pBuffer = 0; + m_nCurrentPos = 0; + m_nCurrentMark = 0; + } + else { + throw NotConnectedException( + OUString( RTL_CONSTASCII_USTRINGPARAM( "MarkableInputStream::closeInput NotConnectedException" ) ) , + *this ); + } +} + +// XMarkable + +sal_Int32 OMarkableInputStream::createMark(void) throw (IOException, RuntimeException) +{ + MutexGuard guard( m_mutex ); + sal_Int32 nMark = m_nCurrentMark; + + m_mapMarks[nMark] = m_nCurrentPos; + + m_nCurrentMark ++; + return nMark; +} + +void OMarkableInputStream::deleteMark(sal_Int32 Mark) throw (IOException, IllegalArgumentException, RuntimeException) +{ + MutexGuard guard( m_mutex ); + map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii = m_mapMarks.find( Mark ); + + if( ii == m_mapMarks.end() ) { + OUStringBuffer buf( 128 ); + buf.appendAscii( "MarkableInputStream::deleteMark unknown mark (" ); + buf.append( Mark ); + buf.appendAscii( ")"); + throw IllegalArgumentException( buf.makeStringAndClear(), *this , 0 ); + } + else { + m_mapMarks.erase( ii ); + checkMarksAndFlush(); + } +} + +void OMarkableInputStream::jumpToMark(sal_Int32 nMark) + throw (IOException, + IllegalArgumentException, + RuntimeException) +{ + MutexGuard guard( m_mutex ); + map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii = m_mapMarks.find( nMark ); + + if( ii == m_mapMarks.end() ) + { + OUStringBuffer buf( 128 ); + buf.appendAscii( "MarkableInputStream::jumpToMark unknown mark (" ); + buf.append( nMark ); + buf.appendAscii( ")"); + throw IllegalArgumentException( buf.makeStringAndClear(), *this , 0 ); + } + else + { + m_nCurrentPos = (*ii).second; + } +} + +void OMarkableInputStream::jumpToFurthest(void) throw (IOException, RuntimeException) +{ + MutexGuard guard( m_mutex ); + m_nCurrentPos = m_pBuffer->getSize(); + checkMarksAndFlush(); +} + +sal_Int32 OMarkableInputStream::offsetToMark(sal_Int32 nMark) + throw (IOException, + IllegalArgumentException, + RuntimeException) +{ + MutexGuard guard( m_mutex ); + map<sal_Int32,sal_Int32,less<sal_Int32> >::const_iterator ii = m_mapMarks.find( nMark ); + + if( ii == m_mapMarks.end() ) + { + OUStringBuffer buf( 128 ); + buf.appendAscii( "MarkableInputStream::offsetToMark unknown mark (" ); + buf.append( nMark ); + buf.appendAscii( ")"); + throw IllegalArgumentException( buf.makeStringAndClear(), *this , 0 ); + } + return m_nCurrentPos - (*ii).second; +} + + + + + + + +// XActiveDataSource +void OMarkableInputStream::setInputStream(const Reference< XInputStream > & aStream) + throw (RuntimeException) +{ + + if( m_input != aStream ) { + m_input = aStream; + + Reference < XConnectable > pred( m_input , UNO_QUERY ); + setPredecessor( pred ); + } + + m_bValidStream = m_input.is(); + +} + +Reference< XInputStream > OMarkableInputStream::getInputStream(void) throw (RuntimeException) +{ + return m_input; +} + + + +// XDataSink +void OMarkableInputStream::setSuccessor( const Reference< XConnectable > &r ) + throw (RuntimeException) +{ + /// if the references match, nothing needs to be done + if( m_succ != r ) { + /// store the reference for later use + m_succ = r; + + if( m_succ.is() ) { + /// set this instance as the sink ! + m_succ->setPredecessor( Reference< XConnectable > ( + SAL_STATIC_CAST( XConnectable * , this ) ) ); + } + } +} + +Reference < XConnectable > OMarkableInputStream::getSuccessor() throw (RuntimeException) +{ + return m_succ; +} + + +// XDataSource +void OMarkableInputStream::setPredecessor( const Reference < XConnectable > &r ) + throw (RuntimeException) +{ + if( r != m_pred ) { + m_pred = r; + if( m_pred.is() ) { + m_pred->setSuccessor( Reference< XConnectable > ( + SAL_STATIC_CAST( XConnectable * , this ) ) ); + } + } +} +Reference< XConnectable > OMarkableInputStream::getPredecessor() throw (RuntimeException) +{ + return m_pred; +} + + + + +void OMarkableInputStream::checkMarksAndFlush() +{ + map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii; + + // find the smallest mark + sal_Int32 nNextFound = m_nCurrentPos; + for( ii = m_mapMarks.begin() ; ii != m_mapMarks.end() ; ii ++ ) { + if( (*ii).second <= nNextFound ) { + nNextFound = (*ii).second; + } + } + + if( nNextFound ) { + // some data must be released ! + m_nCurrentPos -= nNextFound; + for( ii = m_mapMarks.begin() ; ii != m_mapMarks.end() ; ii ++ ) { + (*ii).second -= nNextFound; + } + + m_pBuffer->forgetFromStart( nNextFound ); + + } + else { + // nothing to do. There is a mark or the current cursor position, that prevents + // releasing data ! + } +} + + + +// XServiceInfo +OUString OMarkableInputStream::getImplementationName() throw () +{ + return OMarkableInputStream_getImplementationName(); +} + +// XServiceInfo +sal_Bool OMarkableInputStream::supportsService(const OUString& ServiceName) throw () +{ + Sequence< OUString > aSNL = getSupportedServiceNames(); + const OUString * pArray = aSNL.getConstArray(); + + for( sal_Int32 i = 0; i < aSNL.getLength(); i++ ) + if( pArray[i] == ServiceName ) + return sal_True; + + return sal_False; +} + +// XServiceInfo +Sequence< OUString > OMarkableInputStream::getSupportedServiceNames(void) throw () +{ + return OMarkableInputStream_getSupportedServiceNames(); +} + + +/*------------------------ +* +* external binding +* +*------------------------*/ +Reference < XInterface > SAL_CALL OMarkableInputStream_CreateInstance( + const Reference < XComponentContext > & ) throw(Exception) +{ + OMarkableInputStream *p = new OMarkableInputStream( ); + return Reference< XInterface > ( (OWeakObject * ) p ); +} + +OUString OMarkableInputStream_getImplementationName() +{ + return OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.io.stm.MarkableInputStream" )); +} + +Sequence<OUString> OMarkableInputStream_getSupportedServiceNames(void) +{ + Sequence<OUString> aRet(1); + aRet.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.MarkableInputStream" )); + return aRet; +} + +} |