Stop leaking all ScPostIt instances.
[LibreOffice.git] / io / source / stm / omark.cxx
blob44baddc36d9bc86c003d683c14504da425222133
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include <map>
22 #include <vector>
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>
32 #include <cppuhelper/factory.hxx>
33 #include <cppuhelper/weak.hxx>
34 #include <cppuhelper/implbase5.hxx>
36 #include <osl/mutex.hxx>
37 #include <rtl/ustrbuf.hxx>
39 #include <string.h>
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;
50 #include "services.hxx"
51 #include "streamhelper.hxx"
53 namespace io_stm {
55 /***********************
57 * OMarkableOutputStream.
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.
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.
66 **********************/
67 class OMarkableOutputStream :
68 public WeakImplHelper5< XOutputStream ,
69 XActiveDataSource ,
70 XMarkableStream ,
71 XConnectable,
72 XServiceInfo
75 public:
76 OMarkableOutputStream( );
77 ~OMarkableOutputStream();
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);
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);
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);
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);
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 ();
130 private:
131 // helper methods
132 void checkMarksAndFlush() throw( NotConnectedException, BufferSizeExceededException);
134 Reference< XConnectable > m_succ;
135 Reference< XConnectable > m_pred;
137 Reference< XOutputStream > m_output;
138 sal_Bool m_bValidStream;
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;
145 Mutex m_mutex;
148 OMarkableOutputStream::OMarkableOutputStream( )
150 m_pBuffer = new MemRingBuffer;
151 m_nCurrentPos = 0;
152 m_nCurrentMark = 0;
155 OMarkableOutputStream::~OMarkableOutputStream()
157 delete m_pBuffer;
161 // XOutputStream
162 void OMarkableOutputStream::writeBytes(const Sequence< sal_Int8 >& aData)
163 throw ( NotConnectedException,
164 BufferSizeExceededException,
165 RuntimeException)
167 if( m_bValidStream ) {
168 if( m_mapMarks.empty() && ( m_pBuffer->getSize() == 0 ) ) {
169 // no mark and buffer active, simple write through
170 m_output->writeBytes( aData );
172 else {
173 MutexGuard guard( m_mutex );
174 // new data must be buffered
177 m_pBuffer->writeAt( m_nCurrentPos , aData );
178 m_nCurrentPos += aData.getLength();
180 catch( IRingBuffer_OutOfBoundsException & )
182 throw BufferSizeExceededException();
184 catch( IRingBuffer_OutOfMemoryException & )
186 throw BufferSizeExceededException();
188 checkMarksAndFlush();
191 else {
192 throw NotConnectedException();
196 void OMarkableOutputStream::flush(void)
197 throw ( NotConnectedException,
198 BufferSizeExceededException,
199 RuntimeException)
201 Reference< XOutputStream > output;
203 MutexGuard guard( m_mutex );
204 output = m_output;
207 // Markable cannot flush buffered data, because the data may get rewritten,
208 // however one can forward the flush to the chained stream to give it
209 // a chance to write data buffered in the chained stream.
210 if( output.is() )
212 output->flush();
216 void OMarkableOutputStream::closeOutput(void)
217 throw ( NotConnectedException,
218 BufferSizeExceededException,
219 RuntimeException)
221 if( m_bValidStream ) {
222 MutexGuard guard( m_mutex );
223 // all marks must be cleared and all
225 if( ! m_mapMarks.empty() )
227 m_mapMarks.clear();
229 m_nCurrentPos = m_pBuffer->getSize();
230 checkMarksAndFlush();
232 m_output->closeOutput();
234 setOutputStream( Reference< XOutputStream > () );
235 setPredecessor( Reference < XConnectable >() );
236 setSuccessor( Reference< XConnectable > () );
238 else {
239 throw NotConnectedException();
244 sal_Int32 OMarkableOutputStream::createMark(void)
245 throw ( IOException,
246 RuntimeException)
248 MutexGuard guard( m_mutex );
249 sal_Int32 nMark = m_nCurrentMark;
251 m_mapMarks[nMark] = m_nCurrentPos;
253 m_nCurrentMark ++;
254 return nMark;
257 void OMarkableOutputStream::deleteMark(sal_Int32 Mark)
258 throw( IOException,
259 IllegalArgumentException,
260 RuntimeException)
262 MutexGuard guard( m_mutex );
263 map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii = m_mapMarks.find( Mark );
265 if( ii == m_mapMarks.end() ) {
266 OUStringBuffer buf( 128 );
267 buf.appendAscii( "MarkableOutputStream::deleteMark unknown mark (" );
268 buf.append( Mark );
269 buf.appendAscii( ")");
270 throw IllegalArgumentException( buf.makeStringAndClear(), *this, 0);
272 else {
273 m_mapMarks.erase( ii );
274 checkMarksAndFlush();
278 void OMarkableOutputStream::jumpToMark(sal_Int32 nMark)
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( nMark );
286 if( ii == m_mapMarks.end() ) {
287 OUStringBuffer buf( 128 );
288 buf.appendAscii( "MarkableOutputStream::jumpToMark unknown mark (" );
289 buf.append( nMark );
290 buf.appendAscii( ")");
291 throw IllegalArgumentException( buf.makeStringAndClear(), *this, 0);
293 else {
294 m_nCurrentPos = (*ii).second;
298 void OMarkableOutputStream::jumpToFurthest(void)
299 throw (IOException,
300 RuntimeException)
302 MutexGuard guard( m_mutex );
303 m_nCurrentPos = m_pBuffer->getSize();
304 checkMarksAndFlush();
307 sal_Int32 OMarkableOutputStream::offsetToMark(sal_Int32 nMark)
308 throw (IOException,
309 IllegalArgumentException,
310 RuntimeException)
313 MutexGuard guard( m_mutex );
314 map<sal_Int32,sal_Int32,less<sal_Int32> >::const_iterator ii = m_mapMarks.find( nMark );
316 if( ii == m_mapMarks.end() )
318 OUStringBuffer buf( 128 );
319 buf.appendAscii( "MarkableOutputStream::offsetToMark unknown mark (" );
320 buf.append( nMark );
321 buf.appendAscii( ")");
322 throw IllegalArgumentException( buf.makeStringAndClear(), *this, 0);
324 return m_nCurrentPos - (*ii).second;
329 // XActiveDataSource2
330 void OMarkableOutputStream::setOutputStream(const Reference < XOutputStream >& aStream)
331 throw (RuntimeException)
333 if( m_output != aStream ) {
334 m_output = aStream;
336 Reference < XConnectable > succ( m_output , UNO_QUERY );
337 setSuccessor( succ );
339 m_bValidStream = m_output.is();
342 Reference< XOutputStream > OMarkableOutputStream::getOutputStream(void) throw (RuntimeException)
344 return m_output;
349 void OMarkableOutputStream::setSuccessor( const Reference< XConnectable > &r )
350 throw (RuntimeException)
352 /// if the references match, nothing needs to be done
353 if( m_succ != r ) {
354 /// store the reference for later use
355 m_succ = r;
357 if( m_succ.is() ) {
358 m_succ->setPredecessor( Reference < XConnectable > (
359 (static_cast< XConnectable * >(this)) ) );
363 Reference <XConnectable > OMarkableOutputStream::getSuccessor() throw (RuntimeException)
365 return m_succ;
369 // XDataSource
370 void OMarkableOutputStream::setPredecessor( const Reference< XConnectable > &r )
371 throw (RuntimeException)
373 if( r != m_pred ) {
374 m_pred = r;
375 if( m_pred.is() ) {
376 m_pred->setSuccessor( Reference < XConnectable > (
377 (static_cast< XConnectable * >(this )) ) );
381 Reference < XConnectable > OMarkableOutputStream::getPredecessor() throw (RuntimeException)
383 return m_pred;
387 // private methods
389 void OMarkableOutputStream::checkMarksAndFlush() throw( NotConnectedException,
390 BufferSizeExceededException)
392 map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii;
394 // find the smallest mark
395 sal_Int32 nNextFound = m_nCurrentPos;
396 for( ii = m_mapMarks.begin() ; ii != m_mapMarks.end() ; ++ii ) {
397 if( (*ii).second <= nNextFound ) {
398 nNextFound = (*ii).second;
402 if( nNextFound ) {
403 // some data must be released !
404 m_nCurrentPos -= nNextFound;
405 for( ii = m_mapMarks.begin() ; ii != m_mapMarks.end() ; ++ii ) {
406 (*ii).second -= nNextFound;
409 Sequence<sal_Int8> seq(nNextFound);
410 m_pBuffer->readAt( 0 , seq , nNextFound );
411 m_pBuffer->forgetFromStart( nNextFound );
413 // now write data through to streams
414 m_output->writeBytes( seq );
416 else {
417 // nothing to do. There is a mark or the current cursor position, that prevents
418 // releasing data !
423 // XServiceInfo
424 OUString OMarkableOutputStream::getImplementationName() throw ()
426 return OMarkableOutputStream_getImplementationName();
429 // XServiceInfo
430 sal_Bool OMarkableOutputStream::supportsService(const OUString& ServiceName) throw ()
432 Sequence< OUString > aSNL = getSupportedServiceNames();
433 const OUString * pArray = aSNL.getConstArray();
435 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
436 if( pArray[i] == ServiceName )
437 return sal_True;
439 return sal_False;
442 // XServiceInfo
443 Sequence< OUString > OMarkableOutputStream::getSupportedServiceNames(void) throw ()
445 return OMarkableOutputStream_getSupportedServiceNames();
451 /*------------------------
453 * external binding
455 *------------------------*/
456 Reference< XInterface > SAL_CALL OMarkableOutputStream_CreateInstance(
457 SAL_UNUSED_PARAMETER const Reference < XComponentContext > & )
458 throw(Exception)
460 OMarkableOutputStream *p = new OMarkableOutputStream( );
462 return Reference < XInterface > ( ( OWeakObject * ) p );
465 OUString OMarkableOutputStream_getImplementationName()
467 return OUString("com.sun.star.comp.io.stm.MarkableOutputStream");
470 Sequence<OUString> OMarkableOutputStream_getSupportedServiceNames(void)
472 Sequence<OUString> aRet(1);
473 aRet.getArray()[0] = "com.sun.star.io.MarkableOutputStream";
475 return aRet;
483 //------------------------------------------------
485 // XMarkableInputStream
487 //------------------------------------------------
489 class OMarkableInputStream :
490 public WeakImplHelper5
492 XInputStream,
493 XActiveDataSink,
494 XMarkableStream,
495 XConnectable,
496 XServiceInfo
499 public:
500 OMarkableInputStream( );
501 ~OMarkableInputStream();
504 public: // XInputStream
505 virtual sal_Int32 SAL_CALL readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
506 throw ( NotConnectedException,
507 BufferSizeExceededException,
508 RuntimeException) ;
509 virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
510 throw ( NotConnectedException,
511 BufferSizeExceededException,
512 RuntimeException);
513 virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip)
514 throw ( NotConnectedException,
515 BufferSizeExceededException,
516 RuntimeException);
518 virtual sal_Int32 SAL_CALL available(void)
519 throw ( NotConnectedException,
520 RuntimeException);
521 virtual void SAL_CALL closeInput(void) throw (NotConnectedException, RuntimeException);
523 public: // XMarkable
524 virtual sal_Int32 SAL_CALL createMark(void)
525 throw (IOException, RuntimeException);
526 virtual void SAL_CALL deleteMark(sal_Int32 Mark)
527 throw (IOException, IllegalArgumentException, RuntimeException);
528 virtual void SAL_CALL jumpToMark(sal_Int32 nMark)
529 throw (IOException, IllegalArgumentException, RuntimeException);
530 virtual void SAL_CALL jumpToFurthest(void)
531 throw (IOException, RuntimeException);
532 virtual sal_Int32 SAL_CALL offsetToMark(sal_Int32 nMark)
533 throw (IOException, IllegalArgumentException,RuntimeException);
535 public: // XActiveDataSink
536 virtual void SAL_CALL setInputStream(const Reference < XInputStream > & aStream)
537 throw (RuntimeException);
538 virtual Reference < XInputStream > SAL_CALL getInputStream(void)
539 throw (RuntimeException);
541 public: // XConnectable
542 virtual void SAL_CALL setPredecessor(const Reference < XConnectable > & aPredecessor)
543 throw (RuntimeException);
544 virtual Reference < XConnectable > SAL_CALL getPredecessor(void)
545 throw (RuntimeException);
546 virtual void SAL_CALL setSuccessor(const Reference < XConnectable > & aSuccessor)
547 throw (RuntimeException);
548 virtual Reference < XConnectable > SAL_CALL getSuccessor(void) throw (RuntimeException);
550 public: // XServiceInfo
551 OUString SAL_CALL getImplementationName() throw ();
552 Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw ();
553 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw ();
555 private:
556 void checkMarksAndFlush();
558 Reference < XConnectable > m_succ;
559 Reference < XConnectable > m_pred;
561 Reference< XInputStream > m_input;
562 sal_Bool m_bValidStream;
564 IRingBuffer *m_pBuffer;
565 map<sal_Int32,sal_Int32,less< sal_Int32 > > m_mapMarks;
566 sal_Int32 m_nCurrentPos;
567 sal_Int32 m_nCurrentMark;
569 Mutex m_mutex;
572 OMarkableInputStream::OMarkableInputStream()
574 m_nCurrentPos = 0;
575 m_nCurrentMark = 0;
576 m_pBuffer = new MemRingBuffer;
580 OMarkableInputStream::~OMarkableInputStream()
582 if( m_pBuffer ) {
583 delete m_pBuffer;
590 // XInputStream
592 sal_Int32 OMarkableInputStream::readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
593 throw ( NotConnectedException,
594 BufferSizeExceededException,
595 RuntimeException)
597 sal_Int32 nBytesRead;
599 if( m_bValidStream ) {
600 MutexGuard guard( m_mutex );
601 if( m_mapMarks.empty() && ! m_pBuffer->getSize() ) {
602 // normal read !
603 nBytesRead = m_input->readBytes( aData, nBytesToRead );
605 else {
606 // read from buffer
607 sal_Int32 nRead;
609 // read enough bytes into buffer
610 if( m_pBuffer->getSize() - m_nCurrentPos < nBytesToRead ) {
611 sal_Int32 nToRead = nBytesToRead - ( m_pBuffer->getSize() - m_nCurrentPos );
612 nRead = m_input->readBytes( aData , nToRead );
614 OSL_ASSERT( aData.getLength() == nRead );
618 m_pBuffer->writeAt( m_pBuffer->getSize() , aData );
620 catch( IRingBuffer_OutOfMemoryException & ) {
621 throw BufferSizeExceededException();
623 catch( IRingBuffer_OutOfBoundsException & ) {
624 throw BufferSizeExceededException();
627 if( nRead < nToRead ) {
628 nBytesToRead = nBytesToRead - (nToRead-nRead);
632 OSL_ASSERT( m_pBuffer->getSize() - m_nCurrentPos >= nBytesToRead );
634 m_pBuffer->readAt( m_nCurrentPos , aData , nBytesToRead );
636 m_nCurrentPos += nBytesToRead;
637 nBytesRead = nBytesToRead;
640 else {
641 throw NotConnectedException(
642 OUString("MarkableInputStream::readBytes NotConnectedException") ,
643 *this );
645 return nBytesRead;
649 sal_Int32 OMarkableInputStream::readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
650 throw ( NotConnectedException,
651 BufferSizeExceededException,
652 RuntimeException)
655 sal_Int32 nBytesRead;
656 if( m_bValidStream ) {
657 MutexGuard guard( m_mutex );
658 if( m_mapMarks.empty() && ! m_pBuffer->getSize() ) {
659 // normal read !
660 nBytesRead = m_input->readSomeBytes( aData, nMaxBytesToRead );
662 else {
663 // read from buffer
664 sal_Int32 nRead = 0;
665 sal_Int32 nInBuffer = m_pBuffer->getSize() - m_nCurrentPos;
666 sal_Int32 nAdditionalBytesToRead = Min(nMaxBytesToRead-nInBuffer,m_input->available());
667 nAdditionalBytesToRead = Max(0 , nAdditionalBytesToRead );
669 // read enough bytes into buffer
670 if( 0 == nInBuffer ) {
671 nRead = m_input->readSomeBytes( aData , nMaxBytesToRead );
673 else if( nAdditionalBytesToRead ) {
674 nRead = m_input->readBytes( aData , nAdditionalBytesToRead );
677 if( nRead ) {
678 aData.realloc( nRead );
681 m_pBuffer->writeAt( m_pBuffer->getSize() , aData );
683 catch( IRingBuffer_OutOfMemoryException & )
685 throw BufferSizeExceededException();
687 catch( IRingBuffer_OutOfBoundsException & )
689 throw BufferSizeExceededException();
693 nBytesRead = Min( nMaxBytesToRead , nInBuffer + nRead );
695 // now take everything from buffer !
696 m_pBuffer->readAt( m_nCurrentPos , aData , nBytesRead );
698 m_nCurrentPos += nBytesRead;
701 else
703 throw NotConnectedException(
704 OUString("MarkableInputStream::readSomeBytes NotConnectedException") ,
705 *this );
707 return nBytesRead;
713 void OMarkableInputStream::skipBytes(sal_Int32 nBytesToSkip)
714 throw ( NotConnectedException,
715 BufferSizeExceededException,
716 RuntimeException)
718 if ( nBytesToSkip < 0 )
719 throw BufferSizeExceededException(
720 OUString("precondition not met: XInputStream::skipBytes: non-negative integer required!"),
721 *this
724 // this method is blocking
725 Sequence<sal_Int8> seqDummy( nBytesToSkip );
726 readBytes( seqDummy , nBytesToSkip );
729 sal_Int32 OMarkableInputStream::available(void) throw (NotConnectedException, RuntimeException)
731 sal_Int32 nAvail;
732 if( m_bValidStream ) {
733 MutexGuard guard( m_mutex );
734 nAvail = m_input->available() + ( m_pBuffer->getSize() - m_nCurrentPos );
736 else
738 throw NotConnectedException(
739 OUString("MarkableInputStream::available NotConnectedException") ,
740 *this );
743 return nAvail;
747 void OMarkableInputStream::closeInput(void) throw (NotConnectedException, RuntimeException)
749 if( m_bValidStream ) {
750 MutexGuard guard( m_mutex );
752 m_input->closeInput();
754 setInputStream( Reference< XInputStream > () );
755 setPredecessor( Reference< XConnectable > () );
756 setSuccessor( Reference< XConnectable >() );
758 delete m_pBuffer;
759 m_pBuffer = 0;
760 m_nCurrentPos = 0;
761 m_nCurrentMark = 0;
763 else {
764 throw NotConnectedException(
765 OUString("MarkableInputStream::closeInput NotConnectedException") ,
766 *this );
770 // XMarkable
772 sal_Int32 OMarkableInputStream::createMark(void) throw (IOException, RuntimeException)
774 MutexGuard guard( m_mutex );
775 sal_Int32 nMark = m_nCurrentMark;
777 m_mapMarks[nMark] = m_nCurrentPos;
779 m_nCurrentMark ++;
780 return nMark;
783 void OMarkableInputStream::deleteMark(sal_Int32 Mark) throw (IOException, IllegalArgumentException, RuntimeException)
785 MutexGuard guard( m_mutex );
786 map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii = m_mapMarks.find( Mark );
788 if( ii == m_mapMarks.end() ) {
789 OUStringBuffer buf( 128 );
790 buf.appendAscii( "MarkableInputStream::deleteMark unknown mark (" );
791 buf.append( Mark );
792 buf.appendAscii( ")");
793 throw IllegalArgumentException( buf.makeStringAndClear(), *this , 0 );
795 else {
796 m_mapMarks.erase( ii );
797 checkMarksAndFlush();
801 void OMarkableInputStream::jumpToMark(sal_Int32 nMark)
802 throw (IOException,
803 IllegalArgumentException,
804 RuntimeException)
806 MutexGuard guard( m_mutex );
807 map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii = m_mapMarks.find( nMark );
809 if( ii == m_mapMarks.end() )
811 OUStringBuffer buf( 128 );
812 buf.appendAscii( "MarkableInputStream::jumpToMark unknown mark (" );
813 buf.append( nMark );
814 buf.appendAscii( ")");
815 throw IllegalArgumentException( buf.makeStringAndClear(), *this , 0 );
817 else
819 m_nCurrentPos = (*ii).second;
823 void OMarkableInputStream::jumpToFurthest(void) throw (IOException, RuntimeException)
825 MutexGuard guard( m_mutex );
826 m_nCurrentPos = m_pBuffer->getSize();
827 checkMarksAndFlush();
830 sal_Int32 OMarkableInputStream::offsetToMark(sal_Int32 nMark)
831 throw (IOException,
832 IllegalArgumentException,
833 RuntimeException)
835 MutexGuard guard( m_mutex );
836 map<sal_Int32,sal_Int32,less<sal_Int32> >::const_iterator ii = m_mapMarks.find( nMark );
838 if( ii == m_mapMarks.end() )
840 OUStringBuffer buf( 128 );
841 buf.appendAscii( "MarkableInputStream::offsetToMark unknown mark (" );
842 buf.append( nMark );
843 buf.appendAscii( ")");
844 throw IllegalArgumentException( buf.makeStringAndClear(), *this , 0 );
846 return m_nCurrentPos - (*ii).second;
855 // XActiveDataSource
856 void OMarkableInputStream::setInputStream(const Reference< XInputStream > & aStream)
857 throw (RuntimeException)
860 if( m_input != aStream ) {
861 m_input = aStream;
863 Reference < XConnectable > pred( m_input , UNO_QUERY );
864 setPredecessor( pred );
867 m_bValidStream = m_input.is();
871 Reference< XInputStream > OMarkableInputStream::getInputStream(void) throw (RuntimeException)
873 return m_input;
878 // XDataSink
879 void OMarkableInputStream::setSuccessor( const Reference< XConnectable > &r )
880 throw (RuntimeException)
882 /// if the references match, nothing needs to be done
883 if( m_succ != r ) {
884 /// store the reference for later use
885 m_succ = r;
887 if( m_succ.is() ) {
888 /// set this instance as the sink !
889 m_succ->setPredecessor( Reference< XConnectable > (
890 (static_cast< XConnectable * >(this)) ) );
895 Reference < XConnectable > OMarkableInputStream::getSuccessor() throw (RuntimeException)
897 return m_succ;
901 // XDataSource
902 void OMarkableInputStream::setPredecessor( const Reference < XConnectable > &r )
903 throw (RuntimeException)
905 if( r != m_pred ) {
906 m_pred = r;
907 if( m_pred.is() ) {
908 m_pred->setSuccessor( Reference< XConnectable > (
909 (static_cast< XConnectable * >(this)) ) );
913 Reference< XConnectable > OMarkableInputStream::getPredecessor() throw (RuntimeException)
915 return m_pred;
921 void OMarkableInputStream::checkMarksAndFlush()
923 map<sal_Int32,sal_Int32,less<sal_Int32> >::iterator ii;
925 // find the smallest mark
926 sal_Int32 nNextFound = m_nCurrentPos;
927 for( ii = m_mapMarks.begin() ; ii != m_mapMarks.end() ; ++ii ) {
928 if( (*ii).second <= nNextFound ) {
929 nNextFound = (*ii).second;
933 if( nNextFound ) {
934 // some data must be released !
935 m_nCurrentPos -= nNextFound;
936 for( ii = m_mapMarks.begin() ; ii != m_mapMarks.end() ; ++ii ) {
937 (*ii).second -= nNextFound;
940 m_pBuffer->forgetFromStart( nNextFound );
943 else {
944 // nothing to do. There is a mark or the current cursor position, that prevents
945 // releasing data !
951 // XServiceInfo
952 OUString OMarkableInputStream::getImplementationName() throw ()
954 return OMarkableInputStream_getImplementationName();
957 // XServiceInfo
958 sal_Bool OMarkableInputStream::supportsService(const OUString& ServiceName) throw ()
960 Sequence< OUString > aSNL = getSupportedServiceNames();
961 const OUString * pArray = aSNL.getConstArray();
963 for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
964 if( pArray[i] == ServiceName )
965 return sal_True;
967 return sal_False;
970 // XServiceInfo
971 Sequence< OUString > OMarkableInputStream::getSupportedServiceNames(void) throw ()
973 return OMarkableInputStream_getSupportedServiceNames();
977 /*------------------------
979 * external binding
981 *------------------------*/
982 Reference < XInterface > SAL_CALL OMarkableInputStream_CreateInstance(
983 SAL_UNUSED_PARAMETER const Reference < XComponentContext > & )
984 throw(Exception)
986 OMarkableInputStream *p = new OMarkableInputStream( );
987 return Reference< XInterface > ( (OWeakObject * ) p );
990 OUString OMarkableInputStream_getImplementationName()
992 return OUString("com.sun.star.comp.io.stm.MarkableInputStream");
995 Sequence<OUString> OMarkableInputStream_getSupportedServiceNames(void)
997 Sequence<OUString> aRet(1);
998 aRet.getArray()[0] = "com.sun.star.io.MarkableInputStream";
999 return aRet;
1004 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */