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