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 : #include <functional> // needed under Solaris when including <algorithm>...
22 :
23 : #include <algorithm>
24 : #include <limits>
25 : #include <set>
26 : #include <string.h>
27 :
28 : #include <rtl/alloc.h>
29 : #include <svl/instrm.hxx>
30 : #include <svl/outstrm.hxx>
31 : #include <svl/strmadpt.hxx>
32 :
33 : using namespace com::sun::star;
34 :
35 : //============================================================================
36 : class SvDataPipe_Impl
37 : {
38 : public:
39 : enum SeekResult { SEEK_BEFORE_MARKED, SEEK_OK, SEEK_PAST_END };
40 :
41 : private:
42 : struct Page
43 : {
44 : Page * m_pPrev;
45 : Page * m_pNext;
46 : sal_Int8 * m_pStart;
47 : sal_Int8 * m_pRead;
48 : sal_Int8 * m_pEnd;
49 : sal_uInt32 m_nOffset;
50 : sal_Int8 m_aBuffer[1];
51 : };
52 :
53 : std::multiset< sal_uInt32 > m_aMarks;
54 : Page * m_pFirstPage;
55 : Page * m_pReadPage;
56 : Page * m_pWritePage;
57 : sal_Int8 * m_pReadBuffer;
58 : sal_uInt32 m_nReadBufferSize;
59 : sal_uInt32 m_nReadBufferFilled;
60 : sal_uInt32 m_nPageSize;
61 : sal_uInt32 m_nMinPages;
62 : sal_uInt32 m_nMaxPages;
63 : sal_uInt32 m_nPages;
64 : bool m_bEOF;
65 :
66 : bool remove(Page * pPage);
67 :
68 : public:
69 : inline SvDataPipe_Impl(sal_uInt32 nThePageSize = 1000,
70 : sal_uInt32 nTheMinPages = 100,
71 : sal_uInt32 nTheMaxPages
72 : = std::numeric_limits< sal_uInt32 >::max());
73 :
74 : ~SvDataPipe_Impl();
75 :
76 : inline void setReadBuffer(sal_Int8 * pBuffer, sal_uInt32 nSize);
77 :
78 : sal_uInt32 read();
79 :
80 0 : void clearReadBuffer() { m_pReadBuffer = 0; }
81 :
82 : sal_uInt32 write(sal_Int8 const * pBuffer, sal_uInt32 nSize);
83 :
84 0 : void setEOF() { m_bEOF = true; }
85 :
86 : inline bool isEOF() const;
87 :
88 : bool addMark(sal_uInt32 nPosition);
89 : bool removeMark(sal_uInt32 nPosition);
90 :
91 : inline sal_uInt32 getReadPosition() const;
92 :
93 : SeekResult setReadPosition(sal_uInt32 nPosition);
94 : };
95 :
96 0 : SvDataPipe_Impl::SvDataPipe_Impl(sal_uInt32 nThePageSize,
97 : sal_uInt32 nTheMinPages,
98 : sal_uInt32 nTheMaxPages):
99 : m_pFirstPage(0),
100 : m_pReadPage(0),
101 : m_pWritePage(0),
102 : m_pReadBuffer(0),
103 : m_nPageSize(std::min< sal_uInt32 >(
104 0 : std::max< sal_uInt32 >(nThePageSize, sal_uInt32(1)),
105 0 : sal_uInt32(std::numeric_limits< sal_uInt32 >::max()
106 0 : - sizeof (Page) + 1))),
107 0 : m_nMinPages(std::max< sal_uInt32 >(nTheMinPages, sal_uInt32(1))),
108 0 : m_nMaxPages(std::max< sal_uInt32 >(nTheMaxPages, sal_uInt32(1))),
109 : m_nPages(0),
110 0 : m_bEOF(false)
111 0 : {}
112 :
113 0 : inline void SvDataPipe_Impl::setReadBuffer(sal_Int8 * pBuffer,
114 : sal_uInt32 nSize)
115 : {
116 0 : m_pReadBuffer = pBuffer;
117 0 : m_nReadBufferSize = nSize;
118 0 : m_nReadBufferFilled = 0;
119 0 : }
120 :
121 0 : inline bool SvDataPipe_Impl::isEOF() const
122 : {
123 : return m_bEOF && m_pReadPage == m_pWritePage
124 0 : && (!m_pReadPage || m_pReadPage->m_pRead == m_pReadPage->m_pEnd);
125 : }
126 :
127 : inline sal_uInt32 SvDataPipe_Impl::getReadPosition() const
128 : {
129 : return m_pReadPage == 0 ? 0 :
130 : m_pReadPage->m_nOffset
131 : + (m_pReadPage->m_pRead
132 : - m_pReadPage->m_aBuffer);
133 : }
134 :
135 : //============================================================================
136 : //
137 : // SvOutputStreamOpenLockBytes
138 : //
139 : //============================================================================
140 :
141 0 : TYPEINIT1(SvOutputStreamOpenLockBytes, SvOpenLockBytes)
142 :
143 : //============================================================================
144 : // virtual
145 0 : ErrCode SvOutputStreamOpenLockBytes::ReadAt(sal_uLong, void *, sal_uLong, sal_uLong *)
146 : const
147 : {
148 0 : return ERRCODE_IO_CANTREAD;
149 : }
150 :
151 : //============================================================================
152 : // virtual
153 0 : ErrCode SvOutputStreamOpenLockBytes::WriteAt(sal_uLong nPos, void const * pBuffer,
154 : sal_uLong nCount, sal_uLong * pWritten)
155 : {
156 0 : if (nPos != m_nPosition)
157 0 : return ERRCODE_IO_CANTWRITE;
158 0 : return FillAppend(pBuffer, nCount, pWritten);
159 : }
160 :
161 : //============================================================================
162 : // virtual
163 0 : ErrCode SvOutputStreamOpenLockBytes::Flush() const
164 : {
165 0 : if (!m_xOutputStream.is())
166 0 : return ERRCODE_IO_CANTWRITE;
167 : try
168 : {
169 0 : m_xOutputStream->flush();
170 : }
171 0 : catch (const io::IOException&)
172 : {
173 0 : return ERRCODE_IO_CANTWRITE;
174 : }
175 0 : return ERRCODE_NONE;
176 : }
177 :
178 : //============================================================================
179 : // virtual
180 0 : ErrCode SvOutputStreamOpenLockBytes::SetSize(sal_uLong)
181 : {
182 0 : return ERRCODE_IO_NOTSUPPORTED;
183 : }
184 :
185 : //============================================================================
186 : // virtual
187 0 : ErrCode SvOutputStreamOpenLockBytes::Stat(SvLockBytesStat * pStat,
188 : SvLockBytesStatFlag) const
189 : {
190 0 : if (pStat)
191 0 : pStat->nSize = m_nPosition;
192 0 : return ERRCODE_NONE;
193 : }
194 :
195 : //============================================================================
196 : // virtual
197 0 : ErrCode SvOutputStreamOpenLockBytes::FillAppend(void const * pBuffer,
198 : sal_uLong nCount,
199 : sal_uLong * pWritten)
200 : {
201 0 : if (!m_xOutputStream.is())
202 0 : return ERRCODE_IO_CANTWRITE;
203 0 : if (nCount > 0
204 0 : && nCount > std::numeric_limits< sal_uLong >::max() - m_nPosition)
205 : {
206 0 : nCount = std::numeric_limits< sal_uLong >::max() - m_nPosition;
207 0 : if (nCount == 0)
208 0 : return ERRCODE_IO_CANTWRITE;
209 : }
210 : try
211 : {
212 0 : m_xOutputStream->
213 : writeBytes(uno::Sequence< sal_Int8 >(
214 0 : static_cast< sal_Int8 const * >(pBuffer), nCount));
215 : }
216 0 : catch (const io::IOException&)
217 : {
218 0 : return ERRCODE_IO_CANTWRITE;
219 : }
220 0 : m_nPosition += nCount;
221 0 : if (pWritten)
222 0 : *pWritten = nCount;
223 0 : return ERRCODE_NONE;
224 : }
225 :
226 : //============================================================================
227 : // virtual
228 0 : sal_uLong SvOutputStreamOpenLockBytes::Tell() const
229 : {
230 0 : return m_nPosition;
231 : }
232 :
233 : //============================================================================
234 : // virtual
235 0 : sal_uLong SvOutputStreamOpenLockBytes::Seek(sal_uLong)
236 : {
237 0 : return m_nPosition;
238 : }
239 :
240 : //============================================================================
241 : // virtual
242 0 : void SvOutputStreamOpenLockBytes::Terminate()
243 : {
244 0 : if (m_xOutputStream.is())
245 : {
246 : try
247 : {
248 0 : m_xOutputStream->closeOutput();
249 : }
250 0 : catch (const io::IOException&)
251 : {
252 : }
253 : }
254 0 : }
255 :
256 : //============================================================================
257 : //
258 : // SvLockBytesInputStream
259 : //
260 : //============================================================================
261 :
262 : // virtual
263 0 : uno::Any SAL_CALL SvLockBytesInputStream::queryInterface(uno::Type const &
264 : rType)
265 : throw (uno::RuntimeException)
266 : {
267 : uno::Any
268 : aReturn(cppu::queryInterface(rType,
269 : static_cast< io::XInputStream * >(this),
270 0 : static_cast< io::XSeekable * >(this)));
271 0 : return aReturn.hasValue() ? aReturn : OWeakObject::queryInterface(rType);
272 : }
273 :
274 : //============================================================================
275 : // virtual
276 0 : void SAL_CALL SvLockBytesInputStream::acquire() throw ()
277 : {
278 0 : OWeakObject::acquire();
279 0 : }
280 :
281 : //============================================================================
282 : // virtual
283 0 : void SAL_CALL SvLockBytesInputStream::release() throw ()
284 : {
285 0 : OWeakObject::release();
286 0 : }
287 :
288 : //============================================================================
289 : // virtual
290 : sal_Int32 SAL_CALL
291 0 : SvLockBytesInputStream::readBytes(uno::Sequence< sal_Int8 > & rData,
292 : sal_Int32 nBytesToRead)
293 : throw (io::IOException, uno::RuntimeException)
294 : {
295 : OSL_ASSERT(m_nPosition >= 0);
296 0 : if (!m_xLockBytes.Is())
297 0 : throw io::NotConnectedException();
298 0 : if (
299 : nBytesToRead < 0 ||
300 : (
301 : static_cast<sal_uInt64>(m_nPosition) > SAL_MAX_SIZE &&
302 : nBytesToRead > 0
303 : )
304 : )
305 : {
306 0 : throw io::IOException();
307 : }
308 0 : rData.realloc(nBytesToRead);
309 0 : sal_Int32 nSize = 0;
310 0 : while (nSize < nBytesToRead)
311 : {
312 : sal_Size nCount;
313 0 : ErrCode nError = m_xLockBytes->ReadAt(static_cast<sal_Size>(
314 : m_nPosition),
315 0 : rData.getArray() + nSize,
316 0 : nBytesToRead - nSize, &nCount);
317 0 : if (nError != ERRCODE_NONE && nError != ERRCODE_IO_PENDING)
318 0 : throw io::IOException();
319 0 : m_nPosition += nCount;
320 0 : nSize += nCount;
321 0 : if (nError == ERRCODE_NONE && nCount == 0)
322 : break;
323 : }
324 0 : rData.realloc(nSize);
325 0 : return nSize;
326 : }
327 :
328 : //============================================================================
329 : // virtual
330 : sal_Int32 SAL_CALL
331 0 : SvLockBytesInputStream::readSomeBytes(uno::Sequence< sal_Int8 > & rData,
332 : sal_Int32 nMaxBytesToRead)
333 : throw (io::IOException, uno::RuntimeException)
334 : {
335 : OSL_ASSERT(m_nPosition >= 0);
336 0 : if (!m_xLockBytes.Is())
337 0 : throw io::NotConnectedException();
338 0 : if (static_cast<sal_uInt64>(m_nPosition) > SAL_MAX_SIZE
339 : && nMaxBytesToRead > 0)
340 0 : throw io::IOException();
341 0 : rData.realloc(nMaxBytesToRead);
342 0 : sal_Size nCount = 0;
343 0 : if (nMaxBytesToRead > 0)
344 : {
345 : ErrCode nError;
346 0 : do
347 : {
348 0 : nError = m_xLockBytes->ReadAt(static_cast<sal_Size>(m_nPosition),
349 0 : rData.getArray(),
350 : nMaxBytesToRead < 0 ?
351 : 0 : nMaxBytesToRead,
352 0 : &nCount);
353 0 : if (nError != ERRCODE_NONE && nError != ERRCODE_IO_PENDING)
354 0 : throw io::IOException();
355 0 : m_nPosition += nCount;
356 : }
357 : while (nCount == 0 && nError == ERRCODE_IO_PENDING);
358 : }
359 0 : rData.realloc(sal_Int32(nCount));
360 0 : return sal_Int32(nCount);
361 : }
362 :
363 : //============================================================================
364 : // virtual
365 0 : void SAL_CALL SvLockBytesInputStream::skipBytes(sal_Int32 nBytesToSkip)
366 : throw (io::IOException, uno::RuntimeException)
367 : {
368 0 : if (!m_xLockBytes.Is())
369 0 : throw io::NotConnectedException();
370 0 : if (nBytesToSkip < 0)
371 0 : throw io::IOException();
372 0 : if (nBytesToSkip > SAL_MAX_INT64 - m_nPosition)
373 0 : throw io::BufferSizeExceededException();
374 0 : m_nPosition += nBytesToSkip;
375 0 : }
376 :
377 : //============================================================================
378 : // virtual
379 0 : sal_Int32 SAL_CALL SvLockBytesInputStream::available()
380 : throw (io::IOException, uno::RuntimeException)
381 : {
382 : OSL_ASSERT(m_nPosition >= 0);
383 0 : if (!m_xLockBytes.Is())
384 0 : throw io::NotConnectedException();
385 0 : SvLockBytesStat aStat;
386 0 : if (m_xLockBytes->Stat(&aStat, SVSTATFLAG_DEFAULT) != ERRCODE_NONE)
387 0 : throw io::IOException();
388 : return aStat.nSize <= static_cast<sal_uInt64>(m_nPosition) ?
389 : 0 :
390 : static_cast<sal_Size>(aStat.nSize - m_nPosition) <=
391 : static_cast<sal_uInt32>(SAL_MAX_INT32) ?
392 : static_cast<sal_Int32>(aStat.nSize - m_nPosition) :
393 0 : SAL_MAX_INT32;
394 : }
395 :
396 : //============================================================================
397 : // virtual
398 0 : void SAL_CALL SvLockBytesInputStream::closeInput()
399 : throw (io::IOException, uno::RuntimeException)
400 : {
401 0 : if (!m_xLockBytes.Is())
402 0 : throw io::NotConnectedException();
403 0 : m_xLockBytes = 0;
404 0 : }
405 :
406 : //============================================================================
407 : // virtual
408 0 : void SAL_CALL SvLockBytesInputStream::seek(sal_Int64 nLocation)
409 : throw (lang::IllegalArgumentException, io::IOException,
410 : uno::RuntimeException)
411 : {
412 0 : if (nLocation < 0)
413 0 : throw lang::IllegalArgumentException();
414 0 : if (!m_xLockBytes.Is())
415 0 : throw io::NotConnectedException();
416 0 : m_nPosition = nLocation;
417 0 : }
418 :
419 : //============================================================================
420 : // virtual
421 0 : sal_Int64 SAL_CALL SvLockBytesInputStream::getPosition()
422 : throw (io::IOException, uno::RuntimeException)
423 : {
424 0 : if (!m_xLockBytes.Is())
425 0 : throw io::NotConnectedException();
426 0 : return m_nPosition;
427 : }
428 :
429 : //============================================================================
430 : // virtual
431 0 : sal_Int64 SAL_CALL SvLockBytesInputStream::getLength()
432 : throw (io::IOException, uno::RuntimeException)
433 : {
434 0 : if (!m_xLockBytes.Is())
435 0 : throw io::NotConnectedException();
436 0 : SvLockBytesStat aStat;
437 0 : if (m_xLockBytes->Stat(&aStat, SVSTATFLAG_DEFAULT) != ERRCODE_NONE)
438 0 : throw io::IOException();
439 : #if SAL_TYPES_SIZEOFPOINTER > 4 // avoid warnings if sal_Size < sal_Int64
440 : if (aStat.nSize > static_cast<sal_uInt64>(SAL_MAX_INT64))
441 : throw io::IOException();
442 : #endif
443 0 : return aStat.nSize;
444 : }
445 :
446 : //============================================================================
447 : //
448 : // SvInputStream
449 : //
450 : //============================================================================
451 :
452 0 : bool SvInputStream::open()
453 : {
454 0 : if (GetError() != ERRCODE_NONE)
455 0 : return false;
456 0 : if (!(m_xSeekable.is() || m_pPipe))
457 : {
458 0 : if (!m_xStream.is())
459 : {
460 0 : SetError(ERRCODE_IO_INVALIDDEVICE);
461 0 : return false;
462 : }
463 : m_xSeekable
464 0 : = uno::Reference< io::XSeekable >(m_xStream, uno::UNO_QUERY);
465 0 : if (!m_xSeekable.is())
466 0 : m_pPipe = new SvDataPipe_Impl;
467 : }
468 0 : return true;
469 : }
470 :
471 : //============================================================================
472 : // virtual
473 0 : sal_uLong SvInputStream::GetData(void * pData, sal_uLong nSize)
474 : {
475 0 : if (!open())
476 : {
477 0 : SetError(ERRCODE_IO_CANTREAD);
478 0 : return 0;
479 : }
480 0 : sal_uInt32 nRead = 0;
481 0 : if (m_xSeekable.is())
482 : {
483 0 : if (m_nSeekedFrom != STREAM_SEEK_TO_END)
484 : {
485 : try
486 : {
487 0 : m_xSeekable->seek(m_nSeekedFrom);
488 : }
489 0 : catch (const io::IOException&)
490 : {
491 0 : SetError(ERRCODE_IO_CANTREAD);
492 0 : return 0;
493 : }
494 0 : m_nSeekedFrom = STREAM_SEEK_TO_END;
495 : }
496 0 : for (;;)
497 : {
498 : sal_Int32 nRemain
499 : = sal_Int32(
500 : std::min(sal_uLong(nSize - nRead),
501 0 : sal_uLong(std::numeric_limits< sal_Int32 >::max())));
502 0 : if (nRemain == 0)
503 : break;
504 0 : uno::Sequence< sal_Int8 > aBuffer;
505 : sal_Int32 nCount;
506 : try
507 : {
508 0 : nCount = m_xStream->readBytes(aBuffer, nRemain);
509 : }
510 0 : catch (const io::IOException&)
511 : {
512 0 : SetError(ERRCODE_IO_CANTREAD);
513 0 : return nRead;
514 : }
515 0 : memcpy(static_cast< sal_Int8 * >(pData) + nRead,
516 0 : aBuffer.getConstArray(), sal_uInt32(nCount));
517 0 : nRead += nCount;
518 0 : if (nCount < nRemain)
519 : break;
520 0 : }
521 : }
522 : else
523 : {
524 0 : if (m_nSeekedFrom != STREAM_SEEK_TO_END)
525 : {
526 0 : SetError(ERRCODE_IO_CANTREAD);
527 0 : return 0;
528 : }
529 0 : m_pPipe->setReadBuffer(static_cast< sal_Int8 * >(pData), nSize);
530 0 : nRead = m_pPipe->read();
531 0 : if (nRead < nSize && !m_pPipe->isEOF())
532 0 : for (;;)
533 : {
534 : sal_Int32 nRemain
535 : = sal_Int32(
536 : std::min(
537 : sal_uLong(nSize - nRead),
538 0 : sal_uLong(std::numeric_limits< sal_Int32 >::max())));
539 0 : if (nRemain == 0)
540 : break;
541 0 : uno::Sequence< sal_Int8 > aBuffer;
542 : sal_Int32 nCount;
543 : try
544 : {
545 0 : nCount = m_xStream->readBytes(aBuffer, nRemain);
546 : }
547 0 : catch (const io::IOException&)
548 : {
549 0 : SetError(ERRCODE_IO_CANTREAD);
550 : break;
551 : }
552 0 : m_pPipe->write(aBuffer.getConstArray(), sal_uInt32(nCount));
553 0 : nRead += m_pPipe->read();
554 0 : if (nCount < nRemain)
555 : {
556 0 : m_xStream->closeInput();
557 0 : m_pPipe->setEOF();
558 : break;
559 : }
560 0 : }
561 0 : m_pPipe->clearReadBuffer();
562 : }
563 0 : return nRead;
564 : }
565 :
566 : //============================================================================
567 : // virtual
568 0 : sal_uLong SvInputStream::PutData(void const *, sal_uLong)
569 : {
570 0 : SetError(ERRCODE_IO_NOTSUPPORTED);
571 0 : return 0;
572 : }
573 :
574 : //============================================================================
575 : // virtual
576 0 : void SvInputStream::FlushData()
577 0 : {}
578 :
579 : //============================================================================
580 : // virtual
581 0 : sal_uLong SvInputStream::SeekPos(sal_uLong nPos)
582 : {
583 0 : if (open())
584 : {
585 0 : if (nPos == STREAM_SEEK_TO_END)
586 : {
587 0 : if (m_nSeekedFrom == STREAM_SEEK_TO_END)
588 : {
589 0 : if (m_xSeekable.is())
590 : try
591 : {
592 0 : sal_Int64 nLength = m_xSeekable->getLength();
593 : OSL_ASSERT(nLength >= 0);
594 0 : if (static_cast<sal_uInt64>(nLength)
595 : < STREAM_SEEK_TO_END)
596 : {
597 0 : m_nSeekedFrom = Tell();
598 0 : return sal_uLong(nLength);
599 : }
600 : }
601 0 : catch (const io::IOException&)
602 : {
603 : }
604 : else
605 0 : return Tell(); //@@@
606 : }
607 : else
608 0 : return Tell();
609 : }
610 0 : else if (nPos == m_nSeekedFrom)
611 : {
612 0 : m_nSeekedFrom = STREAM_SEEK_TO_END;
613 0 : return nPos;
614 : }
615 0 : else if (m_xSeekable.is())
616 : {
617 : try
618 : {
619 0 : m_xSeekable->seek(nPos);
620 0 : m_nSeekedFrom = STREAM_SEEK_TO_END;
621 0 : return nPos;
622 : }
623 0 : catch (const io::IOException&)
624 : {
625 : }
626 : }
627 0 : else if (m_pPipe->setReadPosition(nPos) == SvDataPipe_Impl::SEEK_OK)
628 : {
629 0 : m_nSeekedFrom = STREAM_SEEK_TO_END;
630 0 : return nPos;
631 : }
632 0 : else if ( nPos > Tell() )
633 : {
634 : // Read out the bytes
635 0 : sal_Int32 nRead = nPos - Tell();
636 0 : uno::Sequence< sal_Int8 > aBuffer;
637 0 : m_xStream->readBytes( aBuffer, nRead );
638 0 : return nPos;
639 : }
640 0 : else if ( nPos == Tell() )
641 0 : return nPos;
642 : }
643 0 : SetError(ERRCODE_IO_CANTSEEK);
644 0 : return Tell();
645 : }
646 :
647 : //============================================================================
648 : // virtual
649 0 : void SvInputStream::SetSize(sal_uLong)
650 : {
651 0 : SetError(ERRCODE_IO_NOTSUPPORTED);
652 0 : }
653 :
654 : //============================================================================
655 0 : SvInputStream::SvInputStream(
656 : com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
657 : const &
658 : rTheStream):
659 : m_xStream(rTheStream),
660 : m_pPipe(0),
661 0 : m_nSeekedFrom(STREAM_SEEK_TO_END)
662 : {
663 0 : SetBufferSize(0);
664 0 : }
665 :
666 : //============================================================================
667 : // virtual
668 0 : SvInputStream::~SvInputStream()
669 : {
670 0 : if (m_xStream.is())
671 : {
672 : try
673 : {
674 0 : m_xStream->closeInput();
675 : }
676 0 : catch (const io::IOException&)
677 : {
678 : }
679 : }
680 0 : delete m_pPipe;
681 0 : }
682 :
683 : //============================================================================
684 : // virtual
685 0 : sal_uInt16 SvInputStream::IsA() const
686 : {
687 0 : return 0;
688 : }
689 :
690 : //============================================================================
691 : // virtual
692 0 : void SvInputStream::AddMark(sal_uLong nPos)
693 : {
694 0 : if (open() && m_pPipe)
695 0 : m_pPipe->addMark(nPos);
696 0 : }
697 :
698 : //============================================================================
699 : // virtual
700 0 : void SvInputStream::RemoveMark(sal_uLong nPos)
701 : {
702 0 : if (open() && m_pPipe)
703 0 : m_pPipe->removeMark(nPos);
704 0 : }
705 :
706 : //============================================================================
707 : //
708 : // SvOutputStream
709 : //
710 : //============================================================================
711 :
712 : // virtual
713 0 : sal_uLong SvOutputStream::GetData(void *, sal_uLong)
714 : {
715 0 : SetError(ERRCODE_IO_NOTSUPPORTED);
716 0 : return 0;
717 : }
718 :
719 : //============================================================================
720 : // virtual
721 0 : sal_uLong SvOutputStream::PutData(void const * pData, sal_uLong nSize)
722 : {
723 0 : if (!m_xStream.is())
724 : {
725 0 : SetError(ERRCODE_IO_CANTWRITE);
726 0 : return 0;
727 : }
728 0 : sal_uLong nWritten = 0;
729 0 : for (;;)
730 : {
731 : sal_Int32 nRemain
732 : = sal_Int32(
733 : std::min(sal_uLong(nSize - nWritten),
734 0 : sal_uLong(std::numeric_limits< sal_Int32 >::max())));
735 0 : if (nRemain == 0)
736 0 : break;
737 : try
738 : {
739 0 : m_xStream->writeBytes(uno::Sequence< sal_Int8 >(
740 : static_cast<const sal_Int8 * >(pData)
741 : + nWritten,
742 0 : nRemain));
743 : }
744 0 : catch (const io::IOException&)
745 : {
746 0 : SetError(ERRCODE_IO_CANTWRITE);
747 : break;
748 : }
749 0 : nWritten += nRemain;
750 : }
751 0 : return nWritten;
752 : }
753 :
754 : //============================================================================
755 : // virtual
756 0 : sal_uLong SvOutputStream::SeekPos(sal_uLong)
757 : {
758 0 : SetError(ERRCODE_IO_NOTSUPPORTED);
759 0 : return 0;
760 : }
761 :
762 : //============================================================================
763 : // virtual
764 0 : void SvOutputStream::FlushData()
765 : {
766 0 : if (!m_xStream.is())
767 : {
768 0 : SetError(ERRCODE_IO_INVALIDDEVICE);
769 0 : return;
770 : }
771 : try
772 : {
773 0 : m_xStream->flush();
774 : }
775 0 : catch (const io::IOException&)
776 : {
777 : }
778 : }
779 :
780 : //============================================================================
781 : // virtual
782 0 : void SvOutputStream::SetSize(sal_uLong)
783 : {
784 0 : SetError(ERRCODE_IO_NOTSUPPORTED);
785 0 : }
786 :
787 : //============================================================================
788 0 : SvOutputStream::SvOutputStream(uno::Reference< io::XOutputStream > const &
789 : rTheStream):
790 0 : m_xStream(rTheStream)
791 : {
792 0 : SetBufferSize(0);
793 0 : }
794 :
795 : //============================================================================
796 : // virtual
797 0 : SvOutputStream::~SvOutputStream()
798 : {
799 0 : if (m_xStream.is())
800 : {
801 : try
802 : {
803 0 : m_xStream->closeOutput();
804 : }
805 0 : catch (const io::IOException&)
806 : {
807 : }
808 : }
809 0 : }
810 :
811 : //============================================================================
812 : // virtual
813 0 : sal_uInt16 SvOutputStream::IsA() const
814 : {
815 0 : return 0;
816 : }
817 :
818 : //============================================================================
819 : //
820 : // SvDataPipe_Impl
821 : //
822 : //============================================================================
823 :
824 0 : bool SvDataPipe_Impl::remove(Page * pPage)
825 : {
826 0 : if (
827 : pPage != m_pFirstPage ||
828 : m_pReadPage == m_pFirstPage ||
829 : (
830 0 : !m_aMarks.empty() &&
831 0 : *m_aMarks.begin() < m_pFirstPage->m_nOffset + m_nPageSize
832 : )
833 : )
834 : {
835 0 : return false;
836 : }
837 :
838 0 : m_pFirstPage = m_pFirstPage->m_pNext;
839 :
840 0 : if (m_nPages <= m_nMinPages)
841 0 : return true;
842 :
843 0 : pPage->m_pPrev->m_pNext = pPage->m_pNext;
844 0 : pPage->m_pNext->m_pPrev = pPage->m_pPrev;
845 0 : rtl_freeMemory(pPage);
846 0 : --m_nPages;
847 :
848 0 : return true;
849 : }
850 :
851 : //============================================================================
852 0 : SvDataPipe_Impl::~SvDataPipe_Impl()
853 : {
854 0 : if (m_pFirstPage != 0)
855 0 : for (Page * pPage = m_pFirstPage;;)
856 : {
857 0 : Page * pNext = pPage->m_pNext;
858 0 : rtl_freeMemory(pPage);
859 0 : if (pNext == m_pFirstPage)
860 0 : break;
861 0 : pPage = pNext;
862 : }
863 0 : }
864 :
865 : //============================================================================
866 0 : sal_uInt32 SvDataPipe_Impl::read()
867 : {
868 0 : if (m_pReadBuffer == 0 || m_nReadBufferSize == 0 || m_pReadPage == 0)
869 0 : return 0;
870 :
871 0 : sal_uInt32 nSize = m_nReadBufferSize;
872 0 : sal_uInt32 nRemain = m_nReadBufferSize - m_nReadBufferFilled;
873 :
874 0 : m_pReadBuffer += m_nReadBufferFilled;
875 0 : m_nReadBufferSize -= m_nReadBufferFilled;
876 0 : m_nReadBufferFilled = 0;
877 :
878 0 : while (nRemain > 0)
879 : {
880 : sal_uInt32 nBlock = std::min(sal_uInt32(m_pReadPage->m_pEnd
881 : - m_pReadPage->m_pRead),
882 0 : nRemain);
883 0 : memcpy(m_pReadBuffer, m_pReadPage->m_pRead, nBlock);
884 0 : m_pReadPage->m_pRead += nBlock;
885 0 : m_pReadBuffer += nBlock;
886 0 : m_nReadBufferSize -= nBlock;
887 0 : m_nReadBufferFilled = 0;
888 0 : nRemain -= nBlock;
889 :
890 0 : if (m_pReadPage == m_pWritePage)
891 0 : break;
892 :
893 0 : if (m_pReadPage->m_pRead == m_pReadPage->m_pEnd)
894 : {
895 0 : Page * pRemove = m_pReadPage;
896 0 : m_pReadPage = pRemove->m_pNext;
897 0 : remove(pRemove);
898 : }
899 : }
900 :
901 0 : return nSize - nRemain;
902 : }
903 :
904 : //============================================================================
905 0 : sal_uInt32 SvDataPipe_Impl::write(sal_Int8 const * pBuffer, sal_uInt32 nSize)
906 : {
907 0 : if (nSize == 0)
908 0 : return 0;
909 :
910 0 : if (m_pWritePage == 0)
911 : {
912 : m_pFirstPage
913 : = static_cast< Page * >(rtl_allocateMemory(sizeof (Page)
914 : + m_nPageSize
915 0 : - 1));
916 0 : m_pFirstPage->m_pPrev = m_pFirstPage;
917 0 : m_pFirstPage->m_pNext = m_pFirstPage;
918 0 : m_pFirstPage->m_pStart = m_pFirstPage->m_aBuffer;
919 0 : m_pFirstPage->m_pRead = m_pFirstPage->m_aBuffer;
920 0 : m_pFirstPage->m_pEnd = m_pFirstPage->m_aBuffer;
921 0 : m_pFirstPage->m_nOffset = 0;
922 0 : m_pReadPage = m_pFirstPage;
923 0 : m_pWritePage = m_pFirstPage;
924 0 : ++m_nPages;
925 : }
926 :
927 0 : sal_uInt32 nRemain = nSize;
928 :
929 0 : if (m_pReadBuffer != 0 && m_pReadPage == m_pWritePage
930 : && m_pReadPage->m_pRead == m_pWritePage->m_pEnd)
931 : {
932 : sal_uInt32 nBlock = std::min(nRemain,
933 : sal_uInt32(m_nReadBufferSize
934 0 : - m_nReadBufferFilled));
935 : sal_uInt32 nPosition = m_pWritePage->m_nOffset
936 : + (m_pWritePage->m_pEnd
937 0 : - m_pWritePage->m_aBuffer);
938 0 : if (!m_aMarks.empty())
939 0 : nBlock = *m_aMarks.begin() > nPosition ?
940 0 : std::min(nBlock, sal_uInt32(*m_aMarks.begin()
941 0 : - nPosition)) :
942 0 : 0;
943 :
944 0 : if (nBlock > 0)
945 : {
946 0 : memcpy(m_pReadBuffer + m_nReadBufferFilled, pBuffer,
947 0 : nBlock);
948 0 : m_nReadBufferFilled += nBlock;
949 0 : nRemain -= nBlock;
950 :
951 0 : nPosition += nBlock;
952 0 : m_pWritePage->m_nOffset = (nPosition / m_nPageSize) * m_nPageSize;
953 : m_pWritePage->m_pStart = m_pWritePage->m_aBuffer
954 0 : + nPosition % m_nPageSize;
955 0 : m_pWritePage->m_pRead = m_pWritePage->m_pStart;
956 0 : m_pWritePage->m_pEnd = m_pWritePage->m_pStart;
957 : }
958 : }
959 :
960 0 : if (nRemain > 0)
961 0 : for (;;)
962 : {
963 : sal_uInt32 nBlock
964 0 : = std::min(sal_uInt32(m_pWritePage->m_aBuffer + m_nPageSize
965 : - m_pWritePage->m_pEnd),
966 0 : nRemain);
967 0 : memcpy(m_pWritePage->m_pEnd, pBuffer, nBlock);
968 0 : m_pWritePage->m_pEnd += nBlock;
969 0 : pBuffer += nBlock;
970 0 : nRemain -= nBlock;
971 :
972 0 : if (nRemain == 0)
973 0 : break;
974 :
975 0 : if (m_pWritePage->m_pNext == m_pFirstPage)
976 : {
977 0 : if (m_nPages == m_nMaxPages)
978 0 : break;
979 :
980 : Page * pNew
981 : = static_cast< Page * >(rtl_allocateMemory(
982 : sizeof (Page) + m_nPageSize
983 0 : - 1));
984 0 : pNew->m_pPrev = m_pWritePage;
985 0 : pNew->m_pNext = m_pWritePage->m_pNext;
986 :
987 0 : m_pWritePage->m_pNext->m_pPrev = pNew;
988 0 : m_pWritePage->m_pNext = pNew;
989 0 : ++m_nPages;
990 : }
991 :
992 : m_pWritePage->m_pNext->m_nOffset = m_pWritePage->m_nOffset
993 0 : + m_nPageSize;
994 0 : m_pWritePage = m_pWritePage->m_pNext;
995 0 : m_pWritePage->m_pStart = m_pWritePage->m_aBuffer;
996 0 : m_pWritePage->m_pRead = m_pWritePage->m_aBuffer;
997 0 : m_pWritePage->m_pEnd = m_pWritePage->m_aBuffer;
998 : }
999 :
1000 0 : return nSize - nRemain;
1001 : }
1002 :
1003 : //============================================================================
1004 0 : bool SvDataPipe_Impl::addMark(sal_uInt32 nPosition)
1005 : {
1006 0 : if (m_pFirstPage != 0 && m_pFirstPage->m_nOffset > nPosition)
1007 0 : return false;
1008 0 : m_aMarks.insert(nPosition);
1009 0 : return true;
1010 : }
1011 :
1012 : //============================================================================
1013 0 : bool SvDataPipe_Impl::removeMark(sal_uInt32 nPosition)
1014 : {
1015 0 : std::multiset< sal_uInt32 >::iterator t = m_aMarks.find(nPosition);
1016 0 : if (t == m_aMarks.end())
1017 0 : return false;
1018 0 : m_aMarks.erase(t);
1019 0 : while (remove(m_pFirstPage)) ;
1020 0 : return true;
1021 : }
1022 :
1023 : //============================================================================
1024 0 : SvDataPipe_Impl::SeekResult SvDataPipe_Impl::setReadPosition(sal_uInt32
1025 : nPosition)
1026 : {
1027 0 : if (m_pFirstPage == 0)
1028 0 : return nPosition == 0 ? SEEK_OK : SEEK_PAST_END;
1029 :
1030 0 : if (nPosition
1031 : <= m_pReadPage->m_nOffset
1032 : + (m_pReadPage->m_pRead - m_pReadPage->m_aBuffer))
1033 : {
1034 0 : if (nPosition
1035 : < m_pFirstPage->m_nOffset
1036 : + (m_pFirstPage->m_pStart - m_pFirstPage->m_aBuffer))
1037 0 : return SEEK_BEFORE_MARKED;
1038 :
1039 0 : while (nPosition < m_pReadPage->m_nOffset)
1040 : {
1041 0 : m_pReadPage->m_pRead = m_pReadPage->m_pStart;
1042 0 : m_pReadPage = m_pReadPage->m_pPrev;
1043 : }
1044 : }
1045 : else
1046 : {
1047 0 : if (nPosition
1048 : > m_pWritePage->m_nOffset
1049 : + (m_pWritePage->m_pEnd - m_pWritePage->m_aBuffer))
1050 0 : return SEEK_PAST_END;
1051 :
1052 0 : while (m_pReadPage != m_pWritePage
1053 : && nPosition >= m_pReadPage->m_nOffset + m_nPageSize)
1054 : {
1055 0 : Page * pRemove = m_pReadPage;
1056 0 : m_pReadPage = pRemove->m_pNext;
1057 0 : remove(pRemove);
1058 : }
1059 : }
1060 :
1061 : m_pReadPage->m_pRead = m_pReadPage->m_aBuffer
1062 0 : + (nPosition - m_pReadPage->m_nOffset);
1063 0 : return SEEK_OK;
1064 : }
1065 :
1066 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|