merge the formfield patch from ooo-build
[ooovba.git] / io / source / stm / omark.cxx
blob251b0ed262d6b608814d63c9b5c28b6c6563c403
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: omark.cxx,v $
10 * $Revision: 1.11 $
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"
34 #include <map>
35 #include <vector>
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
53 # ifndef NDEBUG
54 # define NDEBUG
55 # endif
56 #endif
57 #include <assert.h>
58 #include <string.h>
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"
72 namespace io_stm {
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 ,
88 XActiveDataSource ,
89 XMarkableStream ,
90 XConnectable,
91 XServiceInfo
94 public:
95 OMarkableOutputStream( );
96 ~OMarkableOutputStream();
98 public: // XOutputStream
99 virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData)
100 throw ( NotConnectedException,
101 BufferSizeExceededException,
102 RuntimeException);
103 virtual void SAL_CALL flush(void)
104 throw ( NotConnectedException,
105 BufferSizeExceededException,
106 RuntimeException);
107 virtual void SAL_CALL closeOutput(void)
108 throw ( NotConnectedException,
109 BufferSizeExceededException,
110 RuntimeException);
112 public: // XMarkable
113 virtual sal_Int32 SAL_CALL createMark(void)
114 throw (IOException, RuntimeException);
115 virtual void SAL_CALL deleteMark(sal_Int32 Mark)
116 throw (IOException,
117 IllegalArgumentException,
118 RuntimeException);
119 virtual void SAL_CALL jumpToMark(sal_Int32 nMark)
120 throw (IOException,
121 IllegalArgumentException,
122 RuntimeException);
123 virtual void SAL_CALL jumpToFurthest(void)
124 throw (IOException, RuntimeException);
125 virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark)
126 throw (IOException,
127 IllegalArgumentException,
128 RuntimeException);
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 ();
149 private:
150 // helper methods
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;
164 Mutex m_mutex;
167 OMarkableOutputStream::OMarkableOutputStream( )
169 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
170 m_pBuffer = new MemRingBuffer;
171 m_nCurrentPos = 0;
172 m_nCurrentMark = 0;
175 OMarkableOutputStream::~OMarkableOutputStream()
177 delete m_pBuffer;
178 g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
182 // XOutputStream
183 void OMarkableOutputStream::writeBytes(const Sequence< sal_Int8 >& aData)
184 throw ( NotConnectedException,
185 BufferSizeExceededException,
186 RuntimeException)
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 );
193 else {
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();
212 else {
213 throw NotConnectedException();
217 void OMarkableOutputStream::flush(void)
218 throw ( NotConnectedException,
219 BufferSizeExceededException,
220 RuntimeException)
222 Reference< XOutputStream > output;
224 MutexGuard guard( m_mutex );
225 output = m_output;
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.
231 if( output.is() )
233 output->flush();
237 void OMarkableOutputStream::closeOutput(void)
238 throw ( NotConnectedException,
239 BufferSizeExceededException,
240 RuntimeException)
242 if( m_bValidStream ) {
243 MutexGuard guard( m_mutex );
244 // all marks must be cleared and all
246 if( ! m_mapMarks.empty() )
248 m_mapMarks.clear();
250 m_nCurrentPos = m_pBuffer->getSize();
251 checkMarksAndFlush();
253 m_output->closeOutput();
255 setOutputStream( Reference< XOutputStream > () );
256 setPredecessor( Reference < XConnectable >() );
257 setSuccessor( Reference< XConnectable > () );
259 else {
260 throw NotConnectedException();
265 sal_Int32 OMarkableOutputStream::createMark(void)
266 throw ( IOException,
267 RuntimeException)
269 MutexGuard guard( m_mutex );
270 sal_Int32 nMark = m_nCurrentMark;
272 m_mapMarks[nMark] = m_nCurrentPos;
274 m_nCurrentMark ++;
275 return nMark;
278 void OMarkableOutputStream::deleteMark(sal_Int32 Mark)
279 throw( IOException,
280 IllegalArgumentException,
281 RuntimeException)
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 (" );
289 buf.append( Mark );
290 buf.appendAscii( ")");
291 throw IllegalArgumentException( buf.makeStringAndClear(), *this, 0);
293 else {
294 m_mapMarks.erase( ii );
295 checkMarksAndFlush();
299 void OMarkableOutputStream::jumpToMark(sal_Int32 nMark)
300 throw (IOException,
301 IllegalArgumentException,
302 RuntimeException)
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 (" );
310 buf.append( nMark );
311 buf.appendAscii( ")");
312 throw IllegalArgumentException( buf.makeStringAndClear(), *this, 0);
314 else {
315 m_nCurrentPos = (*ii).second;
319 void OMarkableOutputStream::jumpToFurthest(void)
320 throw (IOException,
321 RuntimeException)
323 MutexGuard guard( m_mutex );
324 m_nCurrentPos = m_pBuffer->getSize();
325 checkMarksAndFlush();
328 sal_Int32 OMarkableOutputStream::offsetToMark(sal_Int32 nMark)
329 throw (IOException,
330 IllegalArgumentException,
331 RuntimeException)
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 (" );
341 buf.append( nMark );
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 ) {
355 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)
365 return m_output;
370 void OMarkableOutputStream::setSuccessor( const Reference< XConnectable > &r )
371 throw (RuntimeException)
373 /// if the references match, nothing needs to be done
374 if( m_succ != r ) {
375 /// store the reference for later use
376 m_succ = r;
378 if( m_succ.is() ) {
379 m_succ->setPredecessor( Reference < XConnectable > (
380 SAL_STATIC_CAST( XConnectable * , this ) ) );
384 Reference <XConnectable > OMarkableOutputStream::getSuccessor() throw (RuntimeException)
386 return m_succ;
390 // XDataSource
391 void OMarkableOutputStream::setPredecessor( const Reference< XConnectable > &r )
392 throw (RuntimeException)
394 if( r != m_pred ) {
395 m_pred = r;
396 if( m_pred.is() ) {
397 m_pred->setSuccessor( Reference < XConnectable > (
398 SAL_STATIC_CAST ( XConnectable * , this ) ) );
402 Reference < XConnectable > OMarkableOutputStream::getPredecessor() throw (RuntimeException)
404 return m_pred;
408 // private methods
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;
423 if( nNextFound ) {
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 );
437 else {
438 // nothing to do. There is a mark or the current cursor position, that prevents
439 // releasing data !
444 // XServiceInfo
445 OUString OMarkableOutputStream::getImplementationName() throw ()
447 return OMarkableOutputStream_getImplementationName();
450 // XServiceInfo
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 )
458 return sal_True;
460 return sal_False;
463 // XServiceInfo
464 Sequence< OUString > OMarkableOutputStream::getSupportedServiceNames(void) throw ()
466 return OMarkableOutputStream_getSupportedServiceNames();
472 /*------------------------
474 * external binding
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" ) );
494 return aRet;
502 //------------------------------------------------
504 // XMarkableInputStream
506 //------------------------------------------------
508 class OMarkableInputStream :
509 public WeakImplHelper5
511 XInputStream,
512 XActiveDataSink,
513 XMarkableStream,
514 XConnectable,
515 XServiceInfo
518 public:
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,
527 RuntimeException) ;
528 virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
529 throw ( NotConnectedException,
530 BufferSizeExceededException,
531 RuntimeException);
532 virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip)
533 throw ( NotConnectedException,
534 BufferSizeExceededException,
535 RuntimeException);
537 virtual sal_Int32 SAL_CALL available(void)
538 throw ( NotConnectedException,
539 RuntimeException);
540 virtual void SAL_CALL closeInput(void) throw (NotConnectedException, RuntimeException);
542 public: // XMarkable
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 ();
574 private:
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;
588 Mutex m_mutex;
591 OMarkableInputStream::OMarkableInputStream()
593 g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
594 m_nCurrentPos = 0;
595 m_nCurrentMark = 0;
596 m_pBuffer = new MemRingBuffer;
600 OMarkableInputStream::~OMarkableInputStream()
602 if( m_pBuffer ) {
603 delete m_pBuffer;
605 g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
611 // XInputStream
613 sal_Int32 OMarkableInputStream::readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
614 throw ( NotConnectedException,
615 BufferSizeExceededException,
616 RuntimeException)
618 sal_Int32 nBytesRead;
620 if( m_bValidStream ) {
621 MutexGuard guard( m_mutex );
622 if( m_mapMarks.empty() && ! m_pBuffer->getSize() ) {
623 // normal read !
624 nBytesRead = m_input->readBytes( aData, nBytesToRead );
626 else {
627 // read from buffer
628 sal_Int32 nRead;
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;
661 else {
662 throw NotConnectedException(
663 OUString( RTL_CONSTASCII_USTRINGPARAM("MarkableInputStream::readBytes NotConnectedException")) ,
664 *this );
666 return nBytesRead;
670 sal_Int32 OMarkableInputStream::readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
671 throw ( NotConnectedException,
672 BufferSizeExceededException,
673 RuntimeException)
676 sal_Int32 nBytesRead;
677 if( m_bValidStream ) {
678 MutexGuard guard( m_mutex );
679 if( m_mapMarks.empty() && ! m_pBuffer->getSize() ) {
680 // normal read !
681 nBytesRead = m_input->readSomeBytes( aData, nMaxBytesToRead );
683 else {
684 // read from buffer
685 sal_Int32 nRead = 0;
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 );
698 if( nRead ) {
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;
722 else
724 throw NotConnectedException(
725 OUString( RTL_CONSTASCII_USTRINGPARAM("MarkableInputStream::readSomeBytes NotConnectedException")) ,
726 *this );
728 return nBytesRead;
734 void OMarkableInputStream::skipBytes(sal_Int32 nBytesToSkip)
735 throw ( NotConnectedException,
736 BufferSizeExceededException,
737 RuntimeException)
739 if ( nBytesToSkip < 0 )
740 throw BufferSizeExceededException(
741 ::rtl::OUString::createFromAscii( "precondition not met: XInputStream::skipBytes: non-negative integer required!" ),
742 *this
745 // this method is blocking
746 sal_Int32 nRead;
747 Sequence<sal_Int8> seqDummy( nBytesToSkip );
749 nRead = readBytes( seqDummy , nBytesToSkip );
752 sal_Int32 OMarkableInputStream::available(void) throw (NotConnectedException, RuntimeException)
754 sal_Int32 nAvail;
755 if( m_bValidStream ) {
756 MutexGuard guard( m_mutex );
757 nAvail = m_input->available() + ( m_pBuffer->getSize() - m_nCurrentPos );
759 else
761 throw NotConnectedException(
762 OUString( RTL_CONSTASCII_USTRINGPARAM( "MarkableInputStream::available NotConnectedException" ) ) ,
763 *this );
766 return nAvail;
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 >() );
781 delete m_pBuffer;
782 m_pBuffer = 0;
783 m_nCurrentPos = 0;
784 m_nCurrentMark = 0;
786 else {
787 throw NotConnectedException(
788 OUString( RTL_CONSTASCII_USTRINGPARAM( "MarkableInputStream::closeInput NotConnectedException" ) ) ,
789 *this );
793 // XMarkable
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;
802 m_nCurrentMark ++;
803 return nMark;
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 (" );
814 buf.append( Mark );
815 buf.appendAscii( ")");
816 throw IllegalArgumentException( buf.makeStringAndClear(), *this , 0 );
818 else {
819 m_mapMarks.erase( ii );
820 checkMarksAndFlush();
824 void OMarkableInputStream::jumpToMark(sal_Int32 nMark)
825 throw (IOException,
826 IllegalArgumentException,
827 RuntimeException)
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 (" );
836 buf.append( nMark );
837 buf.appendAscii( ")");
838 throw IllegalArgumentException( buf.makeStringAndClear(), *this , 0 );
840 else
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)
854 throw (IOException,
855 IllegalArgumentException,
856 RuntimeException)
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 (" );
865 buf.append( nMark );
866 buf.appendAscii( ")");
867 throw IllegalArgumentException( buf.makeStringAndClear(), *this , 0 );
869 return m_nCurrentPos - (*ii).second;
878 // XActiveDataSource
879 void OMarkableInputStream::setInputStream(const Reference< XInputStream > & aStream)
880 throw (RuntimeException)
883 if( m_input != aStream ) {
884 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)
896 return m_input;
901 // XDataSink
902 void OMarkableInputStream::setSuccessor( const Reference< XConnectable > &r )
903 throw (RuntimeException)
905 /// if the references match, nothing needs to be done
906 if( m_succ != r ) {
907 /// store the reference for later use
908 m_succ = r;
910 if( m_succ.is() ) {
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)
920 return m_succ;
924 // XDataSource
925 void OMarkableInputStream::setPredecessor( const Reference < XConnectable > &r )
926 throw (RuntimeException)
928 if( r != m_pred ) {
929 m_pred = r;
930 if( m_pred.is() ) {
931 m_pred->setSuccessor( Reference< XConnectable > (
932 SAL_STATIC_CAST( XConnectable * , this ) ) );
936 Reference< XConnectable > OMarkableInputStream::getPredecessor() throw (RuntimeException)
938 return m_pred;
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;
956 if( nNextFound ) {
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 );
966 else {
967 // nothing to do. There is a mark or the current cursor position, that prevents
968 // releasing data !
974 // XServiceInfo
975 OUString OMarkableInputStream::getImplementationName() throw ()
977 return OMarkableInputStream_getImplementationName();
980 // XServiceInfo
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 )
988 return sal_True;
990 return sal_False;
993 // XServiceInfo
994 Sequence< OUString > OMarkableInputStream::getSupportedServiceNames(void) throw ()
996 return OMarkableInputStream_getSupportedServiceNames();
1000 /*------------------------
1002 * external binding
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" ));
1021 return aRet;