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