Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
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/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
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 .
18 : : */
19 : :
20 : :
21 : : // streams
22 : : #include <com/sun/star/io/XInputStream.hpp>
23 : : #include <com/sun/star/io/XOutputStream.hpp>
24 : : #include <com/sun/star/io/XConnectable.hpp>
25 : :
26 : : #include <com/sun/star/lang/XServiceInfo.hpp>
27 : :
28 : : #include <cppuhelper/factory.hxx>
29 : :
30 : : #include <cppuhelper/implbase4.hxx> // OWeakObject
31 : :
32 : : #include <osl/conditn.hxx>
33 : : #include <osl/mutex.hxx>
34 : :
35 : : #include <limits>
36 : : #include <string.h>
37 : :
38 : : using namespace ::rtl;
39 : : using namespace ::osl;
40 : : using namespace ::cppu;
41 : : using namespace ::com::sun::star::uno;
42 : : using namespace ::com::sun::star::io;
43 : : using namespace ::com::sun::star::lang;
44 : :
45 : : #include "factreg.hxx"
46 : : #include "streamhelper.hxx"
47 : :
48 : : // Implementation and service names
49 : : #define IMPLEMENTATION_NAME "com.sun.star.comp.io.stm.Pipe"
50 : : #define SERVICE_NAME "com.sun.star.io.Pipe"
51 : :
52 : : namespace io_stm{
53 : :
54 : : class OPipeImpl :
55 : : public WeakImplHelper4< XInputStream , XOutputStream , XConnectable , XServiceInfo >
56 : : {
57 : : public:
58 : : OPipeImpl( );
59 : : ~OPipeImpl();
60 : :
61 : : public: // XInputStream
62 : : virtual sal_Int32 SAL_CALL readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
63 : : throw( NotConnectedException,
64 : : BufferSizeExceededException,
65 : : RuntimeException );
66 : : virtual sal_Int32 SAL_CALL readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
67 : : throw( NotConnectedException,
68 : : BufferSizeExceededException,
69 : : RuntimeException );
70 : : virtual void SAL_CALL skipBytes(sal_Int32 nBytesToSkip)
71 : : throw( NotConnectedException,
72 : : BufferSizeExceededException,
73 : : RuntimeException );
74 : : virtual sal_Int32 SAL_CALL available(void)
75 : : throw( NotConnectedException,
76 : : RuntimeException );
77 : : virtual void SAL_CALL closeInput(void)
78 : : throw( NotConnectedException,
79 : : RuntimeException );
80 : :
81 : : public: // XOutputStream
82 : :
83 : : virtual void SAL_CALL writeBytes(const Sequence< sal_Int8 >& aData)
84 : : throw( NotConnectedException,
85 : : BufferSizeExceededException,
86 : : RuntimeException );
87 : : virtual void SAL_CALL flush(void)
88 : : throw( NotConnectedException,
89 : : BufferSizeExceededException,
90 : : RuntimeException );
91 : : virtual void SAL_CALL closeOutput(void)
92 : : throw( NotConnectedException,
93 : : BufferSizeExceededException,
94 : : RuntimeException );
95 : :
96 : : public: // XConnectable
97 : : virtual void SAL_CALL setPredecessor(const Reference< XConnectable >& aPredecessor)
98 : : throw( RuntimeException );
99 : : virtual Reference< XConnectable > SAL_CALL getPredecessor(void) throw( RuntimeException );
100 : : virtual void SAL_CALL setSuccessor(const Reference < XConnectable > & aSuccessor)
101 : : throw( RuntimeException );
102 : : virtual Reference < XConnectable > SAL_CALL getSuccessor(void) throw( RuntimeException ) ;
103 : :
104 : :
105 : : public: // XServiceInfo
106 : : OUString SAL_CALL getImplementationName() throw( );
107 : : Sequence< OUString > SAL_CALL getSupportedServiceNames(void) throw( );
108 : : sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw( );
109 : :
110 : : private:
111 : :
112 : : Reference < XConnectable > m_succ;
113 : : Reference < XConnectable > m_pred;
114 : :
115 : : sal_Int32 m_nBytesToSkip;
116 : :
117 : : sal_Bool m_bOutputStreamClosed;
118 : : sal_Bool m_bInputStreamClosed;
119 : :
120 : : oslCondition m_conditionBytesAvail;
121 : : Mutex m_mutexAccess;
122 : : I_FIFO *m_pFIFO;
123 : : };
124 : :
125 : :
126 : :
127 [ + - ]: 82 : OPipeImpl::OPipeImpl()
128 : : {
129 [ + - ]: 82 : g_moduleCount.modCnt.acquire( &g_moduleCount.modCnt );
130 : 82 : m_nBytesToSkip = 0;
131 : :
132 : 82 : m_bOutputStreamClosed = sal_False;
133 : 82 : m_bInputStreamClosed = sal_False;
134 : :
135 [ + - ][ + - ]: 82 : m_pFIFO = new MemFIFO;
136 [ + - ]: 82 : m_conditionBytesAvail = osl_createCondition();
137 : 82 : }
138 : :
139 [ # # ]: 0 : OPipeImpl::~OPipeImpl()
140 : : {
141 [ # # ]: 0 : osl_destroyCondition( m_conditionBytesAvail );
142 [ # # ][ # # ]: 0 : delete m_pFIFO;
143 [ # # ]: 0 : g_moduleCount.modCnt.release( &g_moduleCount.modCnt );
144 [ # # ]: 0 : }
145 : :
146 : :
147 : 3614 : sal_Int32 OPipeImpl::readBytes(Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead)
148 : : throw( NotConnectedException, BufferSizeExceededException,RuntimeException )
149 : : {
150 : 3614 : while( sal_True )
151 : : {
152 : : { // start guarded section
153 [ + - ]: 3614 : MutexGuard guard( m_mutexAccess );
154 [ - + ]: 3614 : if( m_bInputStreamClosed )
155 : : {
156 : : throw NotConnectedException(
157 : : OUString( RTL_CONSTASCII_USTRINGPARAM( "Pipe::readBytes NotConnectedException" )),
158 [ # # ][ # # ]: 0 : *this );
[ # # ]
159 : : }
160 : 3614 : sal_Int32 nOccupiedBufferLen = m_pFIFO->getSize();
161 : :
162 [ # # ][ - + ]: 3614 : if( m_bOutputStreamClosed && nBytesToRead > nOccupiedBufferLen )
163 : : {
164 : 0 : nBytesToRead = nOccupiedBufferLen;
165 : : }
166 : :
167 [ - + ]: 3614 : if( nOccupiedBufferLen < nBytesToRead )
168 : : {
169 : : // wait outside guarded section
170 [ # # ]: 0 : osl_resetCondition( m_conditionBytesAvail );
171 : : }
172 : : else {
173 : : // necessary bytes are available
174 [ + - ]: 3614 : m_pFIFO->read( aData , nBytesToRead );
175 : 7228 : return nBytesToRead;
176 [ + - ][ - + ]: 3614 : }
177 : : } // end guarded section
178 : :
179 : : // wait for new data outside guarded section!
180 : 0 : osl_waitCondition( m_conditionBytesAvail , 0 );
181 : : }
182 : : }
183 : :
184 : :
185 : 0 : sal_Int32 OPipeImpl::readSomeBytes(Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead)
186 : : throw( NotConnectedException,
187 : : BufferSizeExceededException,
188 : : RuntimeException )
189 : : {
190 : 0 : while( sal_True ) {
191 : : {
192 [ # # ]: 0 : MutexGuard guard( m_mutexAccess );
193 [ # # ]: 0 : if( m_bInputStreamClosed )
194 : : {
195 : : throw NotConnectedException(
196 : : OUString( RTL_CONSTASCII_USTRINGPARAM( "Pipe::readSomeBytes NotConnectedException" )),
197 [ # # ][ # # ]: 0 : *this );
[ # # ]
198 : : }
199 [ # # ]: 0 : if( m_pFIFO->getSize() )
200 : : {
201 [ # # ]: 0 : sal_Int32 nSize = Min( nMaxBytesToRead , m_pFIFO->getSize() );
202 [ # # ]: 0 : aData.realloc( nSize );
203 [ # # ]: 0 : m_pFIFO->read( aData , nSize );
204 : 0 : return nSize;
205 : : }
206 : :
207 [ # # ]: 0 : if( m_bOutputStreamClosed )
208 : : {
209 : : // no bytes in buffer anymore
210 : 0 : return 0;
211 [ # # ][ # # ]: 0 : }
212 : : }
213 : :
214 : 0 : osl_waitCondition( m_conditionBytesAvail , 0 );
215 : : }
216 : : }
217 : :
218 : :
219 : 0 : void OPipeImpl::skipBytes(sal_Int32 nBytesToSkip)
220 : : throw( NotConnectedException,
221 : : BufferSizeExceededException,
222 : : RuntimeException )
223 : : {
224 [ # # ]: 0 : MutexGuard guard( m_mutexAccess );
225 [ # # ]: 0 : if( m_bInputStreamClosed )
226 : : {
227 : : throw NotConnectedException(
228 : : OUString( RTL_CONSTASCII_USTRINGPARAM( "Pipe::skipBytes NotConnectedException" ) ),
229 [ # # ][ # # ]: 0 : *this );
[ # # ]
230 : : }
231 : :
232 [ # # # # ]: 0 : if( nBytesToSkip < 0
[ # # ]
233 : : || (nBytesToSkip
234 : 0 : > std::numeric_limits< sal_Int32 >::max() - m_nBytesToSkip) )
235 : : {
236 : : throw BufferSizeExceededException(
237 : : OUString( RTL_CONSTASCII_USTRINGPARAM( "Pipe::skipBytes BufferSizeExceededException" )),
238 [ # # ][ # # ]: 0 : *this );
[ # # ]
239 : : }
240 : 0 : m_nBytesToSkip += nBytesToSkip;
241 : :
242 [ # # ]: 0 : nBytesToSkip = Min( m_pFIFO->getSize() , m_nBytesToSkip );
243 [ # # ]: 0 : m_pFIFO->skip( nBytesToSkip );
244 [ # # ]: 0 : m_nBytesToSkip -= nBytesToSkip;
245 : 0 : }
246 : :
247 : :
248 : 0 : sal_Int32 OPipeImpl::available(void)
249 : : throw( NotConnectedException,
250 : : RuntimeException )
251 : : {
252 [ # # ]: 0 : MutexGuard guard( m_mutexAccess );
253 [ # # ]: 0 : if( m_bInputStreamClosed )
254 : : {
255 : : throw NotConnectedException(
256 : : OUString( RTL_CONSTASCII_USTRINGPARAM( "Pipe::available NotConnectedException" ) ),
257 [ # # ][ # # ]: 0 : *this );
[ # # ]
258 : : }
259 [ # # ]: 0 : return m_pFIFO->getSize();
260 : : }
261 : :
262 : 0 : void OPipeImpl::closeInput(void)
263 : : throw( NotConnectedException,
264 : : RuntimeException)
265 : : {
266 [ # # ]: 0 : MutexGuard guard( m_mutexAccess );
267 : :
268 : 0 : m_bInputStreamClosed = sal_True;
269 : :
270 [ # # ][ # # ]: 0 : delete m_pFIFO;
271 : 0 : m_pFIFO = 0;
272 : :
273 : : // readBytes may throw an exception
274 [ # # ]: 0 : osl_setCondition( m_conditionBytesAvail );
275 : :
276 [ # # ]: 0 : setSuccessor( Reference< XConnectable > () );
277 [ # # ]: 0 : return;
278 : : }
279 : :
280 : :
281 : 1506 : void OPipeImpl::writeBytes(const Sequence< sal_Int8 >& aData)
282 : : throw( NotConnectedException,
283 : : BufferSizeExceededException,
284 : : RuntimeException)
285 : : {
286 [ + - ]: 1506 : MutexGuard guard( m_mutexAccess );
287 : :
288 [ - + ]: 1506 : if( m_bOutputStreamClosed )
289 : : {
290 : : throw NotConnectedException(
291 : : OUString( RTL_CONSTASCII_USTRINGPARAM( "Pipe::writeBytes NotConnectedException (outputstream)" )),
292 [ # # ][ # # ]: 0 : *this );
[ # # ]
293 : : }
294 : :
295 [ - + ]: 1506 : if( m_bInputStreamClosed )
296 : : {
297 : : throw NotConnectedException(
298 : : OUString( RTL_CONSTASCII_USTRINGPARAM( "Pipe::writeBytes NotConnectedException (inputstream)" )),
299 [ # # ][ # # ]: 0 : *this );
[ # # ]
300 : : }
301 : :
302 : : // check skipping
303 : 1506 : sal_Int32 nLen = aData.getLength();
304 [ # # ][ - + ]: 1506 : if( m_nBytesToSkip && m_nBytesToSkip >= nLen ) {
305 : : // all must be skipped - forget whole call
306 : 0 : m_nBytesToSkip -= nLen;
307 : 1506 : return;
308 : : }
309 : :
310 : : // adjust buffersize if necessary
311 : :
312 : : try
313 : : {
314 [ - + ]: 1506 : if( m_nBytesToSkip )
315 : : {
316 [ # # ]: 0 : Sequence< sal_Int8 > seqCopy( nLen - m_nBytesToSkip );
317 [ # # ]: 0 : memcpy( seqCopy.getArray() , &( aData.getConstArray()[m_nBytesToSkip] ) , nLen-m_nBytesToSkip );
318 [ # # ][ # # ]: 0 : m_pFIFO->write( seqCopy );
319 : : }
320 : : else
321 : : {
322 [ + - ]: 1506 : m_pFIFO->write( aData );
323 : : }
324 : 1506 : m_nBytesToSkip = 0;
325 : : }
326 : 0 : catch ( I_FIFO_OutOfBoundsException & )
327 : : {
328 : : throw BufferSizeExceededException(
329 : : OUString( RTL_CONSTASCII_USTRINGPARAM( "Pipe::writeBytes BufferSizeExceededException" )),
330 [ # # # # : 0 : *this );
# # ]
331 : : }
332 [ # # # ]: 0 : catch ( I_FIFO_OutOfMemoryException & )
333 : : {
334 : : throw BufferSizeExceededException(
335 : : OUString( RTL_CONSTASCII_USTRINGPARAM( "Pipe::writeBytes BufferSizeExceededException" )),
336 [ # # # # : 0 : *this );
# # ]
337 : : }
338 : :
339 : : // readBytes may check again if enough bytes are available
340 [ + - ][ + - ]: 1506 : osl_setCondition( m_conditionBytesAvail );
[ + - ]
341 : : }
342 : :
343 : :
344 : 0 : void OPipeImpl::flush(void)
345 : : throw( NotConnectedException,
346 : : BufferSizeExceededException,
347 : : RuntimeException)
348 : : {
349 : : // nothing to do for a pipe
350 : 0 : return;
351 : : }
352 : :
353 : 0 : void OPipeImpl::closeOutput(void)
354 : : throw( NotConnectedException,
355 : : BufferSizeExceededException,
356 : : RuntimeException)
357 : : {
358 [ # # ]: 0 : MutexGuard guard( m_mutexAccess );
359 : :
360 : 0 : m_bOutputStreamClosed = sal_True;
361 [ # # ]: 0 : osl_setCondition( m_conditionBytesAvail );
362 [ # # ]: 0 : setPredecessor( Reference < XConnectable > () );
363 [ # # ]: 0 : return;
364 : : }
365 : :
366 : :
367 : 82 : void OPipeImpl::setSuccessor( const Reference < XConnectable > &r )
368 : : throw( RuntimeException )
369 : : {
370 : : /// if the references match, nothing needs to be done
371 [ + - ]: 82 : if( m_succ != r ) {
372 : : /// store the reference for later use
373 : 82 : m_succ = r;
374 : :
375 [ + - ]: 82 : if( m_succ.is() )
376 : : {
377 : 82 : m_succ->setPredecessor(
378 [ + - ]: 82 : Reference< XConnectable > ( (static_cast< XConnectable * >(this)) ) );
379 : : }
380 : : }
381 : 82 : }
382 : :
383 : 0 : Reference < XConnectable > OPipeImpl::getSuccessor() throw( RuntimeException )
384 : : {
385 : 0 : return m_succ;
386 : : }
387 : :
388 : :
389 : : // XDataSource
390 : 82 : void OPipeImpl::setPredecessor( const Reference < XConnectable > &r )
391 : : throw( RuntimeException )
392 : : {
393 [ + - ]: 82 : if( r != m_pred ) {
394 : 82 : m_pred = r;
395 [ + - ]: 82 : if( m_pred.is() ) {
396 : 82 : m_pred->setSuccessor(
397 [ + - ]: 82 : Reference < XConnectable > ( (static_cast< XConnectable * >(this)) ) );
398 : : }
399 : : }
400 : 82 : }
401 : :
402 : 0 : Reference < XConnectable > OPipeImpl::getPredecessor() throw( RuntimeException )
403 : : {
404 : 0 : return m_pred;
405 : : }
406 : :
407 : :
408 : :
409 : :
410 : : // XServiceInfo
411 : 0 : OUString OPipeImpl::getImplementationName() throw( )
412 : : {
413 : 0 : return OPipeImpl_getImplementationName();
414 : : }
415 : :
416 : : // XServiceInfo
417 : 0 : sal_Bool OPipeImpl::supportsService(const OUString& ServiceName) throw( )
418 : : {
419 : 0 : Sequence< OUString > aSNL = getSupportedServiceNames();
420 : 0 : const OUString * pArray = aSNL.getConstArray();
421 : :
422 [ # # ]: 0 : for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
423 [ # # ]: 0 : if( pArray[i] == ServiceName )
424 : 0 : return sal_True;
425 : :
426 [ # # ]: 0 : return sal_False;
427 : : }
428 : :
429 : : // XServiceInfo
430 : 0 : Sequence< OUString > OPipeImpl::getSupportedServiceNames(void) throw( )
431 : : {
432 : 0 : return OPipeImpl_getSupportedServiceNames();
433 : : }
434 : :
435 : :
436 : :
437 : :
438 : :
439 : : /* implementation functions
440 : : *
441 : : *
442 : : */
443 : :
444 : :
445 : 82 : Reference < XInterface > SAL_CALL OPipeImpl_CreateInstance(
446 : : SAL_UNUSED_PARAMETER const Reference < XComponentContext > & )
447 : : throw(Exception)
448 : : {
449 [ + - ]: 82 : OPipeImpl *p = new OPipeImpl;
450 : :
451 : 82 : return Reference < XInterface > ( (static_cast< OWeakObject * >(p)) );
452 : : }
453 : :
454 : :
455 : 20 : OUString OPipeImpl_getImplementationName()
456 : : {
457 : 20 : return OUString( RTL_CONSTASCII_USTRINGPARAM ( IMPLEMENTATION_NAME ) );
458 : : }
459 : :
460 : 4 : Sequence<OUString> OPipeImpl_getSupportedServiceNames(void)
461 : : {
462 : 4 : Sequence<OUString> aRet(1);
463 [ + - ][ + - ]: 4 : aRet.getArray()[0] = OUString( RTL_CONSTASCII_USTRINGPARAM( SERVICE_NAME ));
464 : 4 : return aRet;
465 : : }
466 : : }
467 : :
468 : :
469 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|