1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: omark.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_io.hxx"
37 #include <com/sun/star/io/XMarkableStream.hpp>
38 #include <com/sun/star/io/XOutputStream.hpp>
39 #include <com/sun/star/io/XInputStream.hpp>
40 #include <com/sun/star/io/XActiveDataSource.hpp>
41 #include <com/sun/star/io/XActiveDataSink.hpp>
42 #include <com/sun/star/io/XConnectable.hpp>
43 #include <com/sun/star/lang/XServiceInfo.hpp>
45 #include <cppuhelper/factory.hxx>
46 #include <cppuhelper/weak.hxx> // OWeakObject
47 #include <cppuhelper/implbase5.hxx>
49 #include <osl/mutex.hxx>
50 #include <rtl/ustrbuf.hxx>
52 #if OSL_DEBUG_LEVEL == 0
61 using namespace ::std
;
62 using namespace ::rtl
;
63 using namespace ::cppu
;
64 using namespace ::osl
;
65 using namespace ::com::sun::star::io
;
66 using namespace ::com::sun::star::uno
;
67 using namespace ::com::sun::star::lang
;
69 #include "streamhelper.hxx"
70 #include "factreg.hxx"
74 /***********************
76 * OMarkableOutputStream.
78 * This object allows to set marks in an outputstream. It is allowed to jump back to the marks and
79 * rewrite the some bytes.
81 * The object must buffer the data since the last mark set. Flush will not
82 * have any effect. As soon as the last mark has been removed, the object may write the data
83 * through to the chained object.
85 **********************/
86 class OMarkableOutputStream
:
87 public WeakImplHelper5
< XOutputStream
,
95 OMarkableOutputStream( );
96 ~OMarkableOutputStream();
98 public: // XOutputStream
99 virtual void SAL_CALL
writeBytes(const Sequence
< sal_Int8
>& aData
)
100 throw ( NotConnectedException
,
101 BufferSizeExceededException
,
103 virtual void SAL_CALL
flush(void)
104 throw ( NotConnectedException
,
105 BufferSizeExceededException
,
107 virtual void SAL_CALL
closeOutput(void)
108 throw ( NotConnectedException
,
109 BufferSizeExceededException
,
113 virtual sal_Int32 SAL_CALL
createMark(void)
114 throw (IOException
, RuntimeException
);
115 virtual void SAL_CALL
deleteMark(sal_Int32 Mark
)
117 IllegalArgumentException
,
119 virtual void SAL_CALL
jumpToMark(sal_Int32 nMark
)
121 IllegalArgumentException
,
123 virtual void SAL_CALL
jumpToFurthest(void)
124 throw (IOException
, RuntimeException
);
125 virtual sal_Int32 SAL_CALL
offsetToMark(sal_Int32 nMark
)
127 IllegalArgumentException
,
130 public: // XActiveDataSource
131 virtual void SAL_CALL
setOutputStream(const Reference
< XOutputStream
> & aStream
)
132 throw (RuntimeException
);
133 virtual Reference
< XOutputStream
> SAL_CALL
getOutputStream(void)
134 throw (RuntimeException
);
136 public: // XConnectable
137 virtual void SAL_CALL
setPredecessor(const Reference
< XConnectable
> & aPredecessor
)
138 throw (RuntimeException
);
139 virtual Reference
< XConnectable
> SAL_CALL
getPredecessor(void) throw (RuntimeException
);
140 virtual void SAL_CALL
setSuccessor(const Reference
< XConnectable
>& aSuccessor
)
141 throw (RuntimeException
);
142 virtual Reference
< XConnectable
> SAL_CALL
getSuccessor(void) throw (RuntimeException
);
144 public: // XServiceInfo
145 OUString SAL_CALL
getImplementationName() throw ();
146 Sequence
< OUString
> SAL_CALL
getSupportedServiceNames(void) throw ();
147 sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
) throw ();
151 void checkMarksAndFlush() throw( NotConnectedException
, BufferSizeExceededException
);
153 Reference
< XConnectable
> m_succ
;
154 Reference
< XConnectable
> m_pred
;
156 Reference
< XOutputStream
> m_output
;
157 sal_Bool m_bValidStream
;
159 IRingBuffer
*m_pBuffer
;
160 map
<sal_Int32
,sal_Int32
,less
< sal_Int32
> > m_mapMarks
;
161 sal_Int32 m_nCurrentPos
;
162 sal_Int32 m_nCurrentMark
;
167 OMarkableOutputStream::OMarkableOutputStream( )
169 g_moduleCount
.modCnt
.acquire( &g_moduleCount
.modCnt
);
170 m_pBuffer
= new MemRingBuffer
;
175 OMarkableOutputStream::~OMarkableOutputStream()
178 g_moduleCount
.modCnt
.release( &g_moduleCount
.modCnt
);
183 void OMarkableOutputStream::writeBytes(const Sequence
< sal_Int8
>& aData
)
184 throw ( NotConnectedException
,
185 BufferSizeExceededException
,
188 if( m_bValidStream
) {
189 if( m_mapMarks
.empty() && ( m_pBuffer
->getSize() == 0 ) ) {
190 // no mark and buffer active, simple write through
191 m_output
->writeBytes( aData
);
194 MutexGuard
guard( m_mutex
);
195 // new data must be buffered
198 m_pBuffer
->writeAt( m_nCurrentPos
, aData
);
199 m_nCurrentPos
+= aData
.getLength();
201 catch( IRingBuffer_OutOfBoundsException
& )
203 throw BufferSizeExceededException();
205 catch( IRingBuffer_OutOfMemoryException
& )
207 throw BufferSizeExceededException();
209 checkMarksAndFlush();
213 throw NotConnectedException();
217 void OMarkableOutputStream::flush(void)
218 throw ( NotConnectedException
,
219 BufferSizeExceededException
,
222 Reference
< XOutputStream
> output
;
224 MutexGuard
guard( m_mutex
);
228 // Markable cannot flush buffered data, because the data may get rewritten,
229 // however one can forward the flush to the chained stream to give it
230 // a chance to write data buffered in the chained stream.
237 void OMarkableOutputStream::closeOutput(void)
238 throw ( NotConnectedException
,
239 BufferSizeExceededException
,
242 if( m_bValidStream
) {
243 MutexGuard
guard( m_mutex
);
244 // all marks must be cleared and all
246 if( ! m_mapMarks
.empty() )
250 m_nCurrentPos
= m_pBuffer
->getSize();
251 checkMarksAndFlush();
253 m_output
->closeOutput();
255 setOutputStream( Reference
< XOutputStream
> () );
256 setPredecessor( Reference
< XConnectable
>() );
257 setSuccessor( Reference
< XConnectable
> () );
260 throw NotConnectedException();
265 sal_Int32
OMarkableOutputStream::createMark(void)
269 MutexGuard
guard( m_mutex
);
270 sal_Int32 nMark
= m_nCurrentMark
;
272 m_mapMarks
[nMark
] = m_nCurrentPos
;
278 void OMarkableOutputStream::deleteMark(sal_Int32 Mark
)
280 IllegalArgumentException
,
283 MutexGuard
guard( m_mutex
);
284 map
<sal_Int32
,sal_Int32
,less
<sal_Int32
> >::iterator ii
= m_mapMarks
.find( Mark
);
286 if( ii
== m_mapMarks
.end() ) {
287 OUStringBuffer
buf( 128 );
288 buf
.appendAscii( "MarkableOutputStream::deleteMark unknown mark (" );
290 buf
.appendAscii( ")");
291 throw IllegalArgumentException( buf
.makeStringAndClear(), *this, 0);
294 m_mapMarks
.erase( ii
);
295 checkMarksAndFlush();
299 void OMarkableOutputStream::jumpToMark(sal_Int32 nMark
)
301 IllegalArgumentException
,
304 MutexGuard
guard( m_mutex
);
305 map
<sal_Int32
,sal_Int32
,less
<sal_Int32
> >::iterator ii
= m_mapMarks
.find( nMark
);
307 if( ii
== m_mapMarks
.end() ) {
308 OUStringBuffer
buf( 128 );
309 buf
.appendAscii( "MarkableOutputStream::jumpToMark unknown mark (" );
311 buf
.appendAscii( ")");
312 throw IllegalArgumentException( buf
.makeStringAndClear(), *this, 0);
315 m_nCurrentPos
= (*ii
).second
;
319 void OMarkableOutputStream::jumpToFurthest(void)
323 MutexGuard
guard( m_mutex
);
324 m_nCurrentPos
= m_pBuffer
->getSize();
325 checkMarksAndFlush();
328 sal_Int32
OMarkableOutputStream::offsetToMark(sal_Int32 nMark
)
330 IllegalArgumentException
,
334 MutexGuard
guard( m_mutex
);
335 map
<sal_Int32
,sal_Int32
,less
<sal_Int32
> >::const_iterator ii
= m_mapMarks
.find( nMark
);
337 if( ii
== m_mapMarks
.end() )
339 OUStringBuffer
buf( 128 );
340 buf
.appendAscii( "MarkableOutputStream::offsetToMark unknown mark (" );
342 buf
.appendAscii( ")");
343 throw IllegalArgumentException( buf
.makeStringAndClear(), *this, 0);
345 return m_nCurrentPos
- (*ii
).second
;
350 // XActiveDataSource2
351 void OMarkableOutputStream::setOutputStream(const Reference
< XOutputStream
>& aStream
)
352 throw (RuntimeException
)
354 if( m_output
!= aStream
) {
357 Reference
< XConnectable
> succ( m_output
, UNO_QUERY
);
358 setSuccessor( succ
);
360 m_bValidStream
= m_output
.is();
363 Reference
< XOutputStream
> OMarkableOutputStream::getOutputStream(void) throw (RuntimeException
)
370 void OMarkableOutputStream::setSuccessor( const Reference
< XConnectable
> &r
)
371 throw (RuntimeException
)
373 /// if the references match, nothing needs to be done
375 /// store the reference for later use
379 m_succ
->setPredecessor( Reference
< XConnectable
> (
380 SAL_STATIC_CAST( XConnectable
* , this ) ) );
384 Reference
<XConnectable
> OMarkableOutputStream::getSuccessor() throw (RuntimeException
)
391 void OMarkableOutputStream::setPredecessor( const Reference
< XConnectable
> &r
)
392 throw (RuntimeException
)
397 m_pred
->setSuccessor( Reference
< XConnectable
> (
398 SAL_STATIC_CAST ( XConnectable
* , this ) ) );
402 Reference
< XConnectable
> OMarkableOutputStream::getPredecessor() throw (RuntimeException
)
410 void OMarkableOutputStream::checkMarksAndFlush() throw( NotConnectedException
,
411 BufferSizeExceededException
)
413 map
<sal_Int32
,sal_Int32
,less
<sal_Int32
> >::iterator ii
;
415 // find the smallest mark
416 sal_Int32 nNextFound
= m_nCurrentPos
;
417 for( ii
= m_mapMarks
.begin() ; ii
!= m_mapMarks
.end() ; ii
++ ) {
418 if( (*ii
).second
<= nNextFound
) {
419 nNextFound
= (*ii
).second
;
424 // some data must be released !
425 m_nCurrentPos
-= nNextFound
;
426 for( ii
= m_mapMarks
.begin() ; ii
!= m_mapMarks
.end() ; ii
++ ) {
427 (*ii
).second
-= nNextFound
;
430 Sequence
<sal_Int8
> seq(nNextFound
);
431 m_pBuffer
->readAt( 0 , seq
, nNextFound
);
432 m_pBuffer
->forgetFromStart( nNextFound
);
434 // now write data through to streams
435 m_output
->writeBytes( seq
);
438 // nothing to do. There is a mark or the current cursor position, that prevents
445 OUString
OMarkableOutputStream::getImplementationName() throw ()
447 return OMarkableOutputStream_getImplementationName();
451 sal_Bool
OMarkableOutputStream::supportsService(const OUString
& ServiceName
) throw ()
453 Sequence
< OUString
> aSNL
= getSupportedServiceNames();
454 const OUString
* pArray
= aSNL
.getConstArray();
456 for( sal_Int32 i
= 0; i
< aSNL
.getLength(); i
++ )
457 if( pArray
[i
] == ServiceName
)
464 Sequence
< OUString
> OMarkableOutputStream::getSupportedServiceNames(void) throw ()
466 return OMarkableOutputStream_getSupportedServiceNames();
472 /*------------------------
476 *------------------------*/
477 Reference
< XInterface
> SAL_CALL
OMarkableOutputStream_CreateInstance( const Reference
< XComponentContext
> & ) throw(Exception
)
479 OMarkableOutputStream
*p
= new OMarkableOutputStream( );
481 return Reference
< XInterface
> ( ( OWeakObject
* ) p
);
484 OUString
OMarkableOutputStream_getImplementationName()
486 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.io.stm.MarkableOutputStream" ));
489 Sequence
<OUString
> OMarkableOutputStream_getSupportedServiceNames(void)
491 Sequence
<OUString
> aRet(1);
492 aRet
.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.MarkableOutputStream" ) );
502 //------------------------------------------------
504 // XMarkableInputStream
506 //------------------------------------------------
508 class OMarkableInputStream
:
509 public WeakImplHelper5
519 OMarkableInputStream( );
520 ~OMarkableInputStream();
523 public: // XInputStream
524 virtual sal_Int32 SAL_CALL
readBytes(Sequence
< sal_Int8
>& aData
, sal_Int32 nBytesToRead
)
525 throw ( NotConnectedException
,
526 BufferSizeExceededException
,
528 virtual sal_Int32 SAL_CALL
readSomeBytes(Sequence
< sal_Int8
>& aData
, sal_Int32 nMaxBytesToRead
)
529 throw ( NotConnectedException
,
530 BufferSizeExceededException
,
532 virtual void SAL_CALL
skipBytes(sal_Int32 nBytesToSkip
)
533 throw ( NotConnectedException
,
534 BufferSizeExceededException
,
537 virtual sal_Int32 SAL_CALL
available(void)
538 throw ( NotConnectedException
,
540 virtual void SAL_CALL
closeInput(void) throw (NotConnectedException
, RuntimeException
);
543 virtual sal_Int32 SAL_CALL
createMark(void)
544 throw (IOException
, RuntimeException
);
545 virtual void SAL_CALL
deleteMark(sal_Int32 Mark
)
546 throw (IOException
, IllegalArgumentException
, RuntimeException
);
547 virtual void SAL_CALL
jumpToMark(sal_Int32 nMark
)
548 throw (IOException
, IllegalArgumentException
, RuntimeException
);
549 virtual void SAL_CALL
jumpToFurthest(void)
550 throw (IOException
, RuntimeException
);
551 virtual sal_Int32 SAL_CALL
offsetToMark(sal_Int32 nMark
)
552 throw (IOException
, IllegalArgumentException
,RuntimeException
);
554 public: // XActiveDataSink
555 virtual void SAL_CALL
setInputStream(const Reference
< XInputStream
> & aStream
)
556 throw (RuntimeException
);
557 virtual Reference
< XInputStream
> SAL_CALL
getInputStream(void)
558 throw (RuntimeException
);
560 public: // XConnectable
561 virtual void SAL_CALL
setPredecessor(const Reference
< XConnectable
> & aPredecessor
)
562 throw (RuntimeException
);
563 virtual Reference
< XConnectable
> SAL_CALL
getPredecessor(void)
564 throw (RuntimeException
);
565 virtual void SAL_CALL
setSuccessor(const Reference
< XConnectable
> & aSuccessor
)
566 throw (RuntimeException
);
567 virtual Reference
< XConnectable
> SAL_CALL
getSuccessor(void) throw (RuntimeException
);
569 public: // XServiceInfo
570 OUString SAL_CALL
getImplementationName() throw ();
571 Sequence
< OUString
> SAL_CALL
getSupportedServiceNames(void) throw ();
572 sal_Bool SAL_CALL
supportsService(const OUString
& ServiceName
) throw ();
575 void checkMarksAndFlush();
577 Reference
< XConnectable
> m_succ
;
578 Reference
< XConnectable
> m_pred
;
580 Reference
< XInputStream
> m_input
;
581 sal_Bool m_bValidStream
;
583 IRingBuffer
*m_pBuffer
;
584 map
<sal_Int32
,sal_Int32
,less
< sal_Int32
> > m_mapMarks
;
585 sal_Int32 m_nCurrentPos
;
586 sal_Int32 m_nCurrentMark
;
591 OMarkableInputStream::OMarkableInputStream()
593 g_moduleCount
.modCnt
.acquire( &g_moduleCount
.modCnt
);
596 m_pBuffer
= new MemRingBuffer
;
600 OMarkableInputStream::~OMarkableInputStream()
605 g_moduleCount
.modCnt
.release( &g_moduleCount
.modCnt
);
613 sal_Int32
OMarkableInputStream::readBytes(Sequence
< sal_Int8
>& aData
, sal_Int32 nBytesToRead
)
614 throw ( NotConnectedException
,
615 BufferSizeExceededException
,
618 sal_Int32 nBytesRead
;
620 if( m_bValidStream
) {
621 MutexGuard
guard( m_mutex
);
622 if( m_mapMarks
.empty() && ! m_pBuffer
->getSize() ) {
624 nBytesRead
= m_input
->readBytes( aData
, nBytesToRead
);
630 // read enough bytes into buffer
631 if( m_pBuffer
->getSize() - m_nCurrentPos
< nBytesToRead
) {
632 sal_Int32 nToRead
= nBytesToRead
- ( m_pBuffer
->getSize() - m_nCurrentPos
);
633 nRead
= m_input
->readBytes( aData
, nToRead
);
635 assert( aData
.getLength() == nRead
);
639 m_pBuffer
->writeAt( m_pBuffer
->getSize() , aData
);
641 catch( IRingBuffer_OutOfMemoryException
& ) {
642 throw BufferSizeExceededException();
644 catch( IRingBuffer_OutOfBoundsException
& ) {
645 throw BufferSizeExceededException();
648 if( nRead
< nToRead
) {
649 nBytesToRead
= nBytesToRead
- (nToRead
-nRead
);
653 assert( m_pBuffer
->getSize() - m_nCurrentPos
>= nBytesToRead
);
655 m_pBuffer
->readAt( m_nCurrentPos
, aData
, nBytesToRead
);
657 m_nCurrentPos
+= nBytesToRead
;
658 nBytesRead
= nBytesToRead
;
662 throw NotConnectedException(
663 OUString( RTL_CONSTASCII_USTRINGPARAM("MarkableInputStream::readBytes NotConnectedException")) ,
670 sal_Int32
OMarkableInputStream::readSomeBytes(Sequence
< sal_Int8
>& aData
, sal_Int32 nMaxBytesToRead
)
671 throw ( NotConnectedException
,
672 BufferSizeExceededException
,
676 sal_Int32 nBytesRead
;
677 if( m_bValidStream
) {
678 MutexGuard
guard( m_mutex
);
679 if( m_mapMarks
.empty() && ! m_pBuffer
->getSize() ) {
681 nBytesRead
= m_input
->readSomeBytes( aData
, nMaxBytesToRead
);
686 sal_Int32 nInBuffer
= m_pBuffer
->getSize() - m_nCurrentPos
;
687 sal_Int32 nAdditionalBytesToRead
= Min(nMaxBytesToRead
-nInBuffer
,m_input
->available());
688 nAdditionalBytesToRead
= Max(0 , nAdditionalBytesToRead
);
690 // read enough bytes into buffer
691 if( 0 == nInBuffer
) {
692 nRead
= m_input
->readSomeBytes( aData
, nMaxBytesToRead
);
694 else if( nAdditionalBytesToRead
) {
695 nRead
= m_input
->readBytes( aData
, nAdditionalBytesToRead
);
699 aData
.realloc( nRead
);
702 m_pBuffer
->writeAt( m_pBuffer
->getSize() , aData
);
704 catch( IRingBuffer_OutOfMemoryException
& )
706 throw BufferSizeExceededException();
708 catch( IRingBuffer_OutOfBoundsException
& )
710 throw BufferSizeExceededException();
714 nBytesRead
= Min( nMaxBytesToRead
, nInBuffer
+ nRead
);
716 // now take everything from buffer !
717 m_pBuffer
->readAt( m_nCurrentPos
, aData
, nBytesRead
);
719 m_nCurrentPos
+= nBytesRead
;
724 throw NotConnectedException(
725 OUString( RTL_CONSTASCII_USTRINGPARAM("MarkableInputStream::readSomeBytes NotConnectedException")) ,
734 void OMarkableInputStream::skipBytes(sal_Int32 nBytesToSkip
)
735 throw ( NotConnectedException
,
736 BufferSizeExceededException
,
739 if ( nBytesToSkip
< 0 )
740 throw BufferSizeExceededException(
741 ::rtl::OUString::createFromAscii( "precondition not met: XInputStream::skipBytes: non-negative integer required!" ),
745 // this method is blocking
747 Sequence
<sal_Int8
> seqDummy( nBytesToSkip
);
749 nRead
= readBytes( seqDummy
, nBytesToSkip
);
752 sal_Int32
OMarkableInputStream::available(void) throw (NotConnectedException
, RuntimeException
)
755 if( m_bValidStream
) {
756 MutexGuard
guard( m_mutex
);
757 nAvail
= m_input
->available() + ( m_pBuffer
->getSize() - m_nCurrentPos
);
761 throw NotConnectedException(
762 OUString( RTL_CONSTASCII_USTRINGPARAM( "MarkableInputStream::available NotConnectedException" ) ) ,
770 void OMarkableInputStream::closeInput(void) throw (NotConnectedException
, RuntimeException
)
772 if( m_bValidStream
) {
773 MutexGuard
guard( m_mutex
);
775 m_input
->closeInput();
777 setInputStream( Reference
< XInputStream
> () );
778 setPredecessor( Reference
< XConnectable
> () );
779 setSuccessor( Reference
< XConnectable
>() );
787 throw NotConnectedException(
788 OUString( RTL_CONSTASCII_USTRINGPARAM( "MarkableInputStream::closeInput NotConnectedException" ) ) ,
795 sal_Int32
OMarkableInputStream::createMark(void) throw (IOException
, RuntimeException
)
797 MutexGuard
guard( m_mutex
);
798 sal_Int32 nMark
= m_nCurrentMark
;
800 m_mapMarks
[nMark
] = m_nCurrentPos
;
806 void OMarkableInputStream::deleteMark(sal_Int32 Mark
) throw (IOException
, IllegalArgumentException
, RuntimeException
)
808 MutexGuard
guard( m_mutex
);
809 map
<sal_Int32
,sal_Int32
,less
<sal_Int32
> >::iterator ii
= m_mapMarks
.find( Mark
);
811 if( ii
== m_mapMarks
.end() ) {
812 OUStringBuffer
buf( 128 );
813 buf
.appendAscii( "MarkableInputStream::deleteMark unknown mark (" );
815 buf
.appendAscii( ")");
816 throw IllegalArgumentException( buf
.makeStringAndClear(), *this , 0 );
819 m_mapMarks
.erase( ii
);
820 checkMarksAndFlush();
824 void OMarkableInputStream::jumpToMark(sal_Int32 nMark
)
826 IllegalArgumentException
,
829 MutexGuard
guard( m_mutex
);
830 map
<sal_Int32
,sal_Int32
,less
<sal_Int32
> >::iterator ii
= m_mapMarks
.find( nMark
);
832 if( ii
== m_mapMarks
.end() )
834 OUStringBuffer
buf( 128 );
835 buf
.appendAscii( "MarkableInputStream::jumpToMark unknown mark (" );
837 buf
.appendAscii( ")");
838 throw IllegalArgumentException( buf
.makeStringAndClear(), *this , 0 );
842 m_nCurrentPos
= (*ii
).second
;
846 void OMarkableInputStream::jumpToFurthest(void) throw (IOException
, RuntimeException
)
848 MutexGuard
guard( m_mutex
);
849 m_nCurrentPos
= m_pBuffer
->getSize();
850 checkMarksAndFlush();
853 sal_Int32
OMarkableInputStream::offsetToMark(sal_Int32 nMark
)
855 IllegalArgumentException
,
858 MutexGuard
guard( m_mutex
);
859 map
<sal_Int32
,sal_Int32
,less
<sal_Int32
> >::const_iterator ii
= m_mapMarks
.find( nMark
);
861 if( ii
== m_mapMarks
.end() )
863 OUStringBuffer
buf( 128 );
864 buf
.appendAscii( "MarkableInputStream::offsetToMark unknown mark (" );
866 buf
.appendAscii( ")");
867 throw IllegalArgumentException( buf
.makeStringAndClear(), *this , 0 );
869 return m_nCurrentPos
- (*ii
).second
;
879 void OMarkableInputStream::setInputStream(const Reference
< XInputStream
> & aStream
)
880 throw (RuntimeException
)
883 if( m_input
!= aStream
) {
886 Reference
< XConnectable
> pred( m_input
, UNO_QUERY
);
887 setPredecessor( pred
);
890 m_bValidStream
= m_input
.is();
894 Reference
< XInputStream
> OMarkableInputStream::getInputStream(void) throw (RuntimeException
)
902 void OMarkableInputStream::setSuccessor( const Reference
< XConnectable
> &r
)
903 throw (RuntimeException
)
905 /// if the references match, nothing needs to be done
907 /// store the reference for later use
911 /// set this instance as the sink !
912 m_succ
->setPredecessor( Reference
< XConnectable
> (
913 SAL_STATIC_CAST( XConnectable
* , this ) ) );
918 Reference
< XConnectable
> OMarkableInputStream::getSuccessor() throw (RuntimeException
)
925 void OMarkableInputStream::setPredecessor( const Reference
< XConnectable
> &r
)
926 throw (RuntimeException
)
931 m_pred
->setSuccessor( Reference
< XConnectable
> (
932 SAL_STATIC_CAST( XConnectable
* , this ) ) );
936 Reference
< XConnectable
> OMarkableInputStream::getPredecessor() throw (RuntimeException
)
944 void OMarkableInputStream::checkMarksAndFlush()
946 map
<sal_Int32
,sal_Int32
,less
<sal_Int32
> >::iterator ii
;
948 // find the smallest mark
949 sal_Int32 nNextFound
= m_nCurrentPos
;
950 for( ii
= m_mapMarks
.begin() ; ii
!= m_mapMarks
.end() ; ii
++ ) {
951 if( (*ii
).second
<= nNextFound
) {
952 nNextFound
= (*ii
).second
;
957 // some data must be released !
958 m_nCurrentPos
-= nNextFound
;
959 for( ii
= m_mapMarks
.begin() ; ii
!= m_mapMarks
.end() ; ii
++ ) {
960 (*ii
).second
-= nNextFound
;
963 m_pBuffer
->forgetFromStart( nNextFound
);
967 // nothing to do. There is a mark or the current cursor position, that prevents
975 OUString
OMarkableInputStream::getImplementationName() throw ()
977 return OMarkableInputStream_getImplementationName();
981 sal_Bool
OMarkableInputStream::supportsService(const OUString
& ServiceName
) throw ()
983 Sequence
< OUString
> aSNL
= getSupportedServiceNames();
984 const OUString
* pArray
= aSNL
.getConstArray();
986 for( sal_Int32 i
= 0; i
< aSNL
.getLength(); i
++ )
987 if( pArray
[i
] == ServiceName
)
994 Sequence
< OUString
> OMarkableInputStream::getSupportedServiceNames(void) throw ()
996 return OMarkableInputStream_getSupportedServiceNames();
1000 /*------------------------
1004 *------------------------*/
1005 Reference
< XInterface
> SAL_CALL
OMarkableInputStream_CreateInstance(
1006 const Reference
< XComponentContext
> & ) throw(Exception
)
1008 OMarkableInputStream
*p
= new OMarkableInputStream( );
1009 return Reference
< XInterface
> ( (OWeakObject
* ) p
);
1012 OUString
OMarkableInputStream_getImplementationName()
1014 return OUString(RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.io.stm.MarkableInputStream" ));
1017 Sequence
<OUString
> OMarkableInputStream_getSupportedServiceNames(void)
1019 Sequence
<OUString
> aRet(1);
1020 aRet
.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.io.MarkableInputStream" ));