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 throw (uno::RuntimeException)
268 {
269 uno::Any
270 aReturn(cppu::queryInterface(rType,
271 static_cast< io::XInputStream * >(this),
272 static_cast< io::XSeekable * >(this)));
273 return aReturn.hasValue() ? aReturn : OWeakObject::queryInterface(rType);
274 }
275
276 //============================================================================
277 // virtual
acquire()278 void SAL_CALL SvLockBytesInputStream::acquire() throw ()
279 {
280 OWeakObject::acquire();
281 }
282
283 //============================================================================
284 // virtual
release()285 void SAL_CALL SvLockBytesInputStream::release() throw ()
286 {
287 OWeakObject::release();
288 }
289
290 //============================================================================
291 // virtual
292 sal_Int32 SAL_CALL
readBytes(uno::Sequence<sal_Int8> & rData,sal_Int32 nBytesToRead)293 SvLockBytesInputStream::readBytes(uno::Sequence< sal_Int8 > & rData,
294 sal_Int32 nBytesToRead)
295 throw (io::IOException, uno::RuntimeException)
296 {
297 OSL_ASSERT(m_nPosition >= 0);
298 if (!m_xLockBytes.Is())
299 throw io::NotConnectedException();
300 if (
301 nBytesToRead < 0 ||
302 (
303 static_cast<sal_uInt64>(m_nPosition) > SAL_MAX_SIZE &&
304 nBytesToRead > 0
305 )
306 )
307 {
308 throw io::IOException();
309 }
310 rData.realloc(nBytesToRead);
311 sal_Int32 nSize = 0;
312 while (nSize < nBytesToRead)
313 {
314 sal_Size nCount;
315 ErrCode nError = m_xLockBytes->ReadAt(static_cast<sal_Size>(
316 m_nPosition),
317 rData.getArray() + nSize,
318 nBytesToRead - nSize, &nCount);
319 if (nError != ERRCODE_NONE && nError != ERRCODE_IO_PENDING)
320 throw io::IOException();
321 m_nPosition += nCount;
322 nSize += nCount;
323 if (nError == ERRCODE_NONE && nCount == 0)
324 break;
325 }
326 rData.realloc(nSize);
327 return nSize;
328 }
329
330 //============================================================================
331 // virtual
332 sal_Int32 SAL_CALL
readSomeBytes(uno::Sequence<sal_Int8> & rData,sal_Int32 nMaxBytesToRead)333 SvLockBytesInputStream::readSomeBytes(uno::Sequence< sal_Int8 > & rData,
334 sal_Int32 nMaxBytesToRead)
335 throw (io::IOException, uno::RuntimeException)
336 {
337 OSL_ASSERT(m_nPosition >= 0);
338 if (!m_xLockBytes.Is())
339 throw io::NotConnectedException();
340 if (static_cast<sal_uInt64>(m_nPosition) > SAL_MAX_SIZE
341 && nMaxBytesToRead > 0)
342 throw io::IOException();
343 rData.realloc(nMaxBytesToRead);
344 sal_Size nCount = 0;
345 if (nMaxBytesToRead > 0)
346 {
347 ErrCode nError;
348 do
349 {
350 nError = m_xLockBytes->ReadAt(static_cast<sal_Size>(m_nPosition),
351 rData.getArray(),
352 nMaxBytesToRead < 0 ?
353 0 : nMaxBytesToRead,
354 &nCount);
355 if (nError != ERRCODE_NONE && nError != ERRCODE_IO_PENDING)
356 throw io::IOException();
357 m_nPosition += nCount;
358 }
359 while (nCount == 0 && nError == ERRCODE_IO_PENDING);
360 }
361 rData.realloc(sal_Int32(nCount));
362 return sal_Int32(nCount);
363 }
364
365 //============================================================================
366 // virtual
skipBytes(sal_Int32 nBytesToSkip)367 void SAL_CALL SvLockBytesInputStream::skipBytes(sal_Int32 nBytesToSkip)
368 throw (io::IOException, uno::RuntimeException)
369 {
370 if (!m_xLockBytes.Is())
371 throw io::NotConnectedException();
372 if (nBytesToSkip < 0)
373 throw io::IOException();
374 if (nBytesToSkip > SAL_MAX_INT64 - m_nPosition)
375 throw io::BufferSizeExceededException();
376 m_nPosition += nBytesToSkip;
377 }
378
379 //============================================================================
380 // virtual
available()381 sal_Int32 SAL_CALL SvLockBytesInputStream::available()
382 throw (io::IOException, uno::RuntimeException)
383 {
384 OSL_ASSERT(m_nPosition >= 0);
385 if (!m_xLockBytes.Is())
386 throw io::NotConnectedException();
387 SvLockBytesStat aStat;
388 if (m_xLockBytes->Stat(&aStat, SVSTATFLAG_DEFAULT) != ERRCODE_NONE)
389 throw io::IOException();
390 return aStat.nSize <= static_cast<sal_uInt64>(m_nPosition) ?
391 0 :
392 static_cast<sal_Size>(aStat.nSize - m_nPosition) <=
393 static_cast<sal_uInt32>(SAL_MAX_INT32) ?
394 static_cast<sal_Int32>(aStat.nSize - m_nPosition) :
395 SAL_MAX_INT32;
396 }
397
398 //============================================================================
399 // virtual
closeInput()400 void SAL_CALL SvLockBytesInputStream::closeInput()
401 throw (io::IOException, uno::RuntimeException)
402 {
403 if (!m_xLockBytes.Is())
404 throw io::NotConnectedException();
405 m_xLockBytes = 0;
406 }
407
408 //============================================================================
409 // virtual
seek(sal_Int64 nLocation)410 void SAL_CALL SvLockBytesInputStream::seek(sal_Int64 nLocation)
411 throw (lang::IllegalArgumentException, io::IOException,
412 uno::RuntimeException)
413 {
414 if (nLocation < 0)
415 throw lang::IllegalArgumentException();
416 if (!m_xLockBytes.Is())
417 throw io::NotConnectedException();
418 m_nPosition = nLocation;
419 }
420
421 //============================================================================
422 // virtual
getPosition()423 sal_Int64 SAL_CALL SvLockBytesInputStream::getPosition()
424 throw (io::IOException, uno::RuntimeException)
425 {
426 if (!m_xLockBytes.Is())
427 throw io::NotConnectedException();
428 return m_nPosition;
429 }
430
431 //============================================================================
432 // virtual
getLength()433 sal_Int64 SAL_CALL SvLockBytesInputStream::getLength()
434 throw (io::IOException, uno::RuntimeException)
435 {
436 if (!m_xLockBytes.Is())
437 throw io::NotConnectedException();
438 SvLockBytesStat aStat;
439 if (m_xLockBytes->Stat(&aStat, SVSTATFLAG_DEFAULT) != ERRCODE_NONE)
440 throw io::IOException();
441 #if SAL_TYPES_SIZEOFPOINTER > 4 // avoid warnings if sal_Size < sal_Int64
442 if (aStat.nSize > static_cast<sal_uInt64>(SAL_MAX_INT64))
443 throw io::IOException();
444 #endif
445 return aStat.nSize;
446 }
447
448 //============================================================================
449 //
450 // SvInputStream
451 //
452 //============================================================================
453
open()454 bool SvInputStream::open()
455 {
456 if (GetError() != ERRCODE_NONE)
457 return false;
458 if (!(m_xSeekable.is() || m_pPipe))
459 {
460 if (!m_xStream.is())
461 {
462 SetError(ERRCODE_IO_INVALIDDEVICE);
463 return false;
464 }
465 m_xSeekable
466 = uno::Reference< io::XSeekable >(m_xStream, uno::UNO_QUERY);
467 if (!m_xSeekable.is())
468 m_pPipe = new SvDataPipe_Impl;
469 }
470 return true;
471 }
472
473 //============================================================================
474 // virtual
GetData(void * pData,sal_uLong nSize)475 sal_uLong SvInputStream::GetData(void * pData, sal_uLong nSize)
476 {
477 if (!open())
478 {
479 SetError(ERRCODE_IO_CANTREAD);
480 return 0;
481 }
482 sal_uInt32 nRead = 0;
483 if (m_xSeekable.is())
484 {
485 if (m_nSeekedFrom != STREAM_SEEK_TO_END)
486 {
487 try
488 {
489 m_xSeekable->seek(m_nSeekedFrom);
490 }
491 catch (io::IOException)
492 {
493 SetError(ERRCODE_IO_CANTREAD);
494 return 0;
495 }
496 m_nSeekedFrom = STREAM_SEEK_TO_END;
497 }
498 for (;;)
499 {
500 sal_Int32 nRemain
501 = sal_Int32(
502 std::min(sal_uLong(nSize - nRead),
503 sal_uLong(std::numeric_limits< sal_Int32 >::max())));
504 if (nRemain == 0)
505 break;
506 uno::Sequence< sal_Int8 > aBuffer;
507 sal_Int32 nCount;
508 try
509 {
510 nCount = m_xStream->readBytes(aBuffer, nRemain);
511 }
512 catch (io::IOException)
513 {
514 SetError(ERRCODE_IO_CANTREAD);
515 return nRead;
516 }
517 rtl_copyMemory(static_cast< sal_Int8 * >(pData) + nRead,
518 aBuffer.getConstArray(), sal_uInt32(nCount));
519 nRead += nCount;
520 if (nCount < nRemain)
521 break;
522 }
523 }
524 else
525 {
526 if (m_nSeekedFrom != STREAM_SEEK_TO_END)
527 {
528 SetError(ERRCODE_IO_CANTREAD);
529 return 0;
530 }
531 m_pPipe->setReadBuffer(static_cast< sal_Int8 * >(pData), nSize);
532 nRead = m_pPipe->read();
533 if (nRead < nSize && !m_pPipe->isEOF())
534 for (;;)
535 {
536 sal_Int32 nRemain
537 = sal_Int32(
538 std::min(
539 sal_uLong(nSize - nRead),
540 sal_uLong(std::numeric_limits< sal_Int32 >::max())));
541 if (nRemain == 0)
542 break;
543 uno::Sequence< sal_Int8 > aBuffer;
544 sal_Int32 nCount;
545 try
546 {
547 nCount = m_xStream->readBytes(aBuffer, nRemain);
548 }
549 catch (io::IOException)
550 {
551 SetError(ERRCODE_IO_CANTREAD);
552 break;
553 }
554 m_pPipe->write(aBuffer.getConstArray(), sal_uInt32(nCount));
555 nRead += m_pPipe->read();
556 if (nCount < nRemain)
557 {
558 m_xStream->closeInput();
559 m_pPipe->setEOF();
560 break;
561 }
562 }
563 m_pPipe->clearReadBuffer();
564 }
565 return nRead;
566 }
567
568 //============================================================================
569 // virtual
PutData(void const *,sal_uLong)570 sal_uLong SvInputStream::PutData(void const *, sal_uLong)
571 {
572 SetError(ERRCODE_IO_NOTSUPPORTED);
573 return 0;
574 }
575
576 //============================================================================
577 // virtual
FlushData()578 void SvInputStream::FlushData()
579 {}
580
581 //============================================================================
582 // virtual
SeekPos(sal_uLong nPos)583 sal_uLong SvInputStream::SeekPos(sal_uLong nPos)
584 {
585 if (open())
586 {
587 if (nPos == STREAM_SEEK_TO_END)
588 {
589 if (m_nSeekedFrom == STREAM_SEEK_TO_END)
590 {
591 if (m_xSeekable.is())
592 try
593 {
594 sal_Int64 nLength = m_xSeekable->getLength();
595 OSL_ASSERT(nLength >= 0);
596 if (static_cast<sal_uInt64>(nLength)
597 < STREAM_SEEK_TO_END)
598 {
599 m_nSeekedFrom = Tell();
600 return sal_uLong(nLength);
601 }
602 }
603 catch (io::IOException) {}
604 else
605 return Tell(); //@@@
606 }
607 else
608 return Tell();
609 }
610 else if (nPos == m_nSeekedFrom)
611 {
612 m_nSeekedFrom = STREAM_SEEK_TO_END;
613 return nPos;
614 }
615 else if (m_xSeekable.is())
616 try
617 {
618 m_xSeekable->seek(nPos);
619 m_nSeekedFrom = STREAM_SEEK_TO_END;
620 return nPos;
621 }
622 catch (io::IOException) {}
623 else if (m_pPipe->setReadPosition(nPos) == SvDataPipe_Impl::SEEK_OK)
624 {
625 m_nSeekedFrom = STREAM_SEEK_TO_END;
626 return nPos;
627 }
628 }
629 SetError(ERRCODE_IO_CANTSEEK);
630 return Tell();
631 }
632
633 //============================================================================
634 // virtual
SetSize(sal_uLong)635 void SvInputStream::SetSize(sal_uLong)
636 {
637 SetError(ERRCODE_IO_NOTSUPPORTED);
638 }
639
640 //============================================================================
SvInputStream(com::sun::star::uno::Reference<com::sun::star::io::XInputStream> const & rTheStream)641 SvInputStream::SvInputStream(
642 com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
643 const &
644 rTheStream):
645 m_xStream(rTheStream),
646 m_pPipe(0),
647 m_nSeekedFrom(STREAM_SEEK_TO_END)
648 {
649 SetBufferSize(0);
650 }
651
652 //============================================================================
653 // virtual
~SvInputStream()654 SvInputStream::~SvInputStream()
655 {
656 if (m_xStream.is())
657 try
658 {
659 m_xStream->closeInput();
660 }
661 catch (io::IOException) {}
662 delete m_pPipe;
663 }
664
665 //============================================================================
666 // virtual
IsA() const667 sal_uInt16 SvInputStream::IsA() const
668 {
669 return 0;
670 }
671
672 //============================================================================
673 // virtual
AddMark(sal_uLong nPos)674 void SvInputStream::AddMark(sal_uLong nPos)
675 {
676 if (open() && m_pPipe)
677 m_pPipe->addMark(nPos);
678 }
679
680 //============================================================================
681 // virtual
RemoveMark(sal_uLong nPos)682 void SvInputStream::RemoveMark(sal_uLong nPos)
683 {
684 if (open() && m_pPipe)
685 m_pPipe->removeMark(nPos);
686 }
687
688 //============================================================================
689 //
690 // SvOutputStream
691 //
692 //============================================================================
693
694 // virtual
GetData(void *,sal_uLong)695 sal_uLong SvOutputStream::GetData(void *, sal_uLong)
696 {
697 SetError(ERRCODE_IO_NOTSUPPORTED);
698 return 0;
699 }
700
701 //============================================================================
702 // virtual
PutData(void const * pData,sal_uLong nSize)703 sal_uLong SvOutputStream::PutData(void const * pData, sal_uLong nSize)
704 {
705 if (!m_xStream.is())
706 {
707 SetError(ERRCODE_IO_CANTWRITE);
708 return 0;
709 }
710 sal_uLong nWritten = 0;
711 for (;;)
712 {
713 sal_Int32 nRemain
714 = sal_Int32(
715 std::min(sal_uLong(nSize - nWritten),
716 sal_uLong(std::numeric_limits< sal_Int32 >::max())));
717 if (nRemain == 0)
718 break;
719 try
720 {
721 m_xStream->writeBytes(uno::Sequence< sal_Int8 >(
722 static_cast<const sal_Int8 * >(pData)
723 + nWritten,
724 nRemain));
725 }
726 catch (io::IOException)
727 {
728 SetError(ERRCODE_IO_CANTWRITE);
729 break;
730 }
731 nWritten += nRemain;
732 }
733 return nWritten;
734 }
735
736 //============================================================================
737 // virtual
SeekPos(sal_uLong)738 sal_uLong SvOutputStream::SeekPos(sal_uLong)
739 {
740 SetError(ERRCODE_IO_NOTSUPPORTED);
741 return 0;
742 }
743
744 //============================================================================
745 // virtual
FlushData()746 void SvOutputStream::FlushData()
747 {
748 if (!m_xStream.is())
749 {
750 SetError(ERRCODE_IO_INVALIDDEVICE);
751 return;
752 }
753 try
754 {
755 m_xStream->flush();
756 }
757 catch (io::IOException) {}
758 }
759
760 //============================================================================
761 // virtual
SetSize(sal_uLong)762 void SvOutputStream::SetSize(sal_uLong)
763 {
764 SetError(ERRCODE_IO_NOTSUPPORTED);
765 }
766
767 //============================================================================
SvOutputStream(uno::Reference<io::XOutputStream> const & rTheStream)768 SvOutputStream::SvOutputStream(uno::Reference< io::XOutputStream > const &
769 rTheStream):
770 m_xStream(rTheStream)
771 {
772 SetBufferSize(0);
773 }
774
775 //============================================================================
776 // virtual
~SvOutputStream()777 SvOutputStream::~SvOutputStream()
778 {
779 if (m_xStream.is())
780 try
781 {
782 m_xStream->closeOutput();
783 }
784 catch (io::IOException) {}
785 }
786
787 //============================================================================
788 // virtual
IsA() const789 sal_uInt16 SvOutputStream::IsA() const
790 {
791 return 0;
792 }
793
794 //============================================================================
795 //
796 // SvDataPipe_Impl
797 //
798 //============================================================================
799
remove(Page * pPage)800 bool SvDataPipe_Impl::remove(Page * pPage)
801 {
802 if (
803 pPage != m_pFirstPage ||
804 m_pReadPage == m_pFirstPage ||
805 (
806 !m_aMarks.empty() &&
807 *m_aMarks.begin() < m_pFirstPage->m_nOffset + m_nPageSize
808 )
809 )
810 {
811 return false;
812 }
813
814 m_pFirstPage = m_pFirstPage->m_pNext;
815
816 if (m_nPages <= m_nMinPages)
817 return true;
818
819 pPage->m_pPrev->m_pNext = pPage->m_pNext;
820 pPage->m_pNext->m_pPrev = pPage->m_pPrev;
821 rtl_freeMemory(pPage);
822 --m_nPages;
823
824 return true;
825 }
826
827 //============================================================================
~SvDataPipe_Impl()828 SvDataPipe_Impl::~SvDataPipe_Impl()
829 {
830 if (m_pFirstPage != 0)
831 for (Page * pPage = m_pFirstPage;;)
832 {
833 Page * pNext = pPage->m_pNext;
834 rtl_freeMemory(pPage);
835 if (pNext == m_pFirstPage)
836 break;
837 pPage = pNext;
838 }
839 }
840
841 //============================================================================
read()842 sal_uInt32 SvDataPipe_Impl::read()
843 {
844 if (m_pReadBuffer == 0 || m_nReadBufferSize == 0 || m_pReadPage == 0)
845 return 0;
846
847 sal_uInt32 nSize = m_nReadBufferSize;
848 sal_uInt32 nRemain = m_nReadBufferSize - m_nReadBufferFilled;
849
850 m_pReadBuffer += m_nReadBufferFilled;
851 m_nReadBufferSize -= m_nReadBufferFilled;
852 m_nReadBufferFilled = 0;
853
854 while (nRemain > 0)
855 {
856 sal_uInt32 nBlock = std::min(sal_uInt32(m_pReadPage->m_pEnd
857 - m_pReadPage->m_pRead),
858 nRemain);
859 rtl_copyMemory(m_pReadBuffer, m_pReadPage->m_pRead, nBlock);
860 m_pReadPage->m_pRead += nBlock;
861 m_pReadBuffer += nBlock;
862 m_nReadBufferSize -= nBlock;
863 m_nReadBufferFilled = 0;
864 nRemain -= nBlock;
865
866 if (m_pReadPage == m_pWritePage)
867 break;
868
869 if (m_pReadPage->m_pRead == m_pReadPage->m_pEnd)
870 {
871 Page * pRemove = m_pReadPage;
872 m_pReadPage = pRemove->m_pNext;
873 remove(pRemove);
874 }
875 }
876
877 return nSize - nRemain;
878 }
879
880 //============================================================================
write(sal_Int8 const * pBuffer,sal_uInt32 nSize)881 sal_uInt32 SvDataPipe_Impl::write(sal_Int8 const * pBuffer, sal_uInt32 nSize)
882 {
883 if (nSize == 0)
884 return 0;
885
886 if (m_pWritePage == 0)
887 {
888 m_pFirstPage
889 = static_cast< Page * >(rtl_allocateMemory(sizeof (Page)
890 + m_nPageSize
891 - 1));
892 m_pFirstPage->m_pPrev = m_pFirstPage;
893 m_pFirstPage->m_pNext = m_pFirstPage;
894 m_pFirstPage->m_pStart = m_pFirstPage->m_aBuffer;
895 m_pFirstPage->m_pRead = m_pFirstPage->m_aBuffer;
896 m_pFirstPage->m_pEnd = m_pFirstPage->m_aBuffer;
897 m_pFirstPage->m_nOffset = 0;
898 m_pReadPage = m_pFirstPage;
899 m_pWritePage = m_pFirstPage;
900 ++m_nPages;
901 }
902
903 sal_uInt32 nRemain = nSize;
904
905 if (m_pReadBuffer != 0 && m_pReadPage == m_pWritePage
906 && m_pReadPage->m_pRead == m_pWritePage->m_pEnd)
907 {
908 sal_uInt32 nBlock = std::min(nRemain,
909 sal_uInt32(m_nReadBufferSize
910 - m_nReadBufferFilled));
911 sal_uInt32 nPosition = m_pWritePage->m_nOffset
912 + (m_pWritePage->m_pEnd
913 - m_pWritePage->m_aBuffer);
914 if (!m_aMarks.empty())
915 nBlock = *m_aMarks.begin() > nPosition ?
916 std::min(nBlock, sal_uInt32(*m_aMarks.begin()
917 - nPosition)) :
918 0;
919
920 if (nBlock > 0)
921 {
922 rtl_copyMemory(m_pReadBuffer + m_nReadBufferFilled, pBuffer,
923 nBlock);
924 m_nReadBufferFilled += nBlock;
925 nRemain -= nBlock;
926
927 nPosition += nBlock;
928 m_pWritePage->m_nOffset = (nPosition / m_nPageSize) * m_nPageSize;
929 m_pWritePage->m_pStart = m_pWritePage->m_aBuffer
930 + nPosition % m_nPageSize;
931 m_pWritePage->m_pRead = m_pWritePage->m_pStart;
932 m_pWritePage->m_pEnd = m_pWritePage->m_pStart;
933 }
934 }
935
936 if (nRemain > 0)
937 for (;;)
938 {
939 sal_uInt32 nBlock
940 = std::min(sal_uInt32(m_pWritePage->m_aBuffer + m_nPageSize
941 - m_pWritePage->m_pEnd),
942 nRemain);
943 rtl_copyMemory(m_pWritePage->m_pEnd, pBuffer, nBlock);
944 m_pWritePage->m_pEnd += nBlock;
945 pBuffer += nBlock;
946 nRemain -= nBlock;
947
948 if (nRemain == 0)
949 break;
950
951 if (m_pWritePage->m_pNext == m_pFirstPage)
952 {
953 if (m_nPages == m_nMaxPages)
954 break;
955
956 Page * pNew
957 = static_cast< Page * >(rtl_allocateMemory(
958 sizeof (Page) + m_nPageSize
959 - 1));
960 pNew->m_pPrev = m_pWritePage;
961 pNew->m_pNext = m_pWritePage->m_pNext;
962
963 m_pWritePage->m_pNext->m_pPrev = pNew;
964 m_pWritePage->m_pNext = pNew;
965 ++m_nPages;
966 }
967
968 m_pWritePage->m_pNext->m_nOffset = m_pWritePage->m_nOffset
969 + m_nPageSize;
970 m_pWritePage = m_pWritePage->m_pNext;
971 m_pWritePage->m_pStart = m_pWritePage->m_aBuffer;
972 m_pWritePage->m_pRead = m_pWritePage->m_aBuffer;
973 m_pWritePage->m_pEnd = m_pWritePage->m_aBuffer;
974 }
975
976 return nSize - nRemain;
977 }
978
979 //============================================================================
addMark(sal_uInt32 nPosition)980 bool SvDataPipe_Impl::addMark(sal_uInt32 nPosition)
981 {
982 if (m_pFirstPage != 0 && m_pFirstPage->m_nOffset > nPosition)
983 return false;
984 m_aMarks.insert(nPosition);
985 return true;
986 }
987
988 //============================================================================
removeMark(sal_uInt32 nPosition)989 bool SvDataPipe_Impl::removeMark(sal_uInt32 nPosition)
990 {
991 std::multiset< sal_uInt32 >::iterator t = m_aMarks.find(nPosition);
992 if (t == m_aMarks.end())
993 return false;
994 m_aMarks.erase(t);
995 while (remove(m_pFirstPage)) ;
996 return true;
997 }
998
999 //============================================================================
setReadPosition(sal_uInt32 nPosition)1000 SvDataPipe_Impl::SeekResult SvDataPipe_Impl::setReadPosition(sal_uInt32
1001 nPosition)
1002 {
1003 if (m_pFirstPage == 0)
1004 return nPosition == 0 ? SEEK_OK : SEEK_PAST_END;
1005
1006 if (nPosition
1007 <= m_pReadPage->m_nOffset
1008 + (m_pReadPage->m_pRead - m_pReadPage->m_aBuffer))
1009 {
1010 if (nPosition
1011 < m_pFirstPage->m_nOffset
1012 + (m_pFirstPage->m_pStart - m_pFirstPage->m_aBuffer))
1013 return SEEK_BEFORE_MARKED;
1014
1015 while (nPosition < m_pReadPage->m_nOffset)
1016 {
1017 m_pReadPage->m_pRead = m_pReadPage->m_pStart;
1018 m_pReadPage = m_pReadPage->m_pPrev;
1019 }
1020 }
1021 else
1022 {
1023 if (nPosition
1024 > m_pWritePage->m_nOffset
1025 + (m_pWritePage->m_pEnd - m_pWritePage->m_aBuffer))
1026 return SEEK_PAST_END;
1027
1028 while (m_pReadPage != m_pWritePage
1029 && nPosition >= m_pReadPage->m_nOffset + m_nPageSize)
1030 {
1031 Page * pRemove = m_pReadPage;
1032 m_pReadPage = pRemove->m_pNext;
1033 remove(pRemove);
1034 }
1035 }
1036
1037 m_pReadPage->m_pRead = m_pReadPage->m_aBuffer
1038 + (nPosition - m_pReadPage->m_nOffset);
1039 return SEEK_OK;
1040 }
1041
1042