Update ooo320-m1
[ooovba.git] / svtools / source / misc1 / strmadpt.cxx
blob00fcfb9f642affb69a62a070d26cc43349ea9eb7
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: strmadpt.cxx,v $
10 * $Revision: 1.5.136.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_svtools.hxx"
34 #include <functional> // needed under Solaris when including <algorithm>...
36 #include <algorithm>
37 #include <limits>
38 #include <set>
39 #include <rtl/alloc.h>
40 #include <rtl/memory.h>
41 #include <instrm.hxx>
42 #include <outstrm.hxx>
43 #include <strmadpt.hxx>
45 using namespace com::sun::star;
47 //============================================================================
48 class SvDataPipe_Impl
50 public:
51 enum SeekResult { SEEK_BEFORE_MARKED, SEEK_OK, SEEK_PAST_END };
53 private:
54 struct Page
56 Page * m_pPrev;
57 Page * m_pNext;
58 sal_Int8 * m_pStart;
59 sal_Int8 * m_pRead;
60 sal_Int8 * m_pEnd;
61 sal_uInt32 m_nOffset;
62 sal_Int8 m_aBuffer[1];
65 std::multiset< sal_uInt32 > m_aMarks;
66 Page * m_pFirstPage;
67 Page * m_pReadPage;
68 Page * m_pWritePage;
69 sal_Int8 * m_pReadBuffer;
70 sal_uInt32 m_nReadBufferSize;
71 sal_uInt32 m_nReadBufferFilled;
72 sal_uInt32 m_nPageSize;
73 sal_uInt32 m_nMinPages;
74 sal_uInt32 m_nMaxPages;
75 sal_uInt32 m_nPages;
76 bool m_bEOF;
78 bool remove(Page * pPage);
80 public:
81 inline SvDataPipe_Impl(sal_uInt32 nThePageSize = 1000,
82 sal_uInt32 nTheMinPages = 100,
83 sal_uInt32 nTheMaxPages
84 = std::numeric_limits< sal_uInt32 >::max());
86 ~SvDataPipe_Impl();
88 inline void setReadBuffer(sal_Int8 * pBuffer, sal_uInt32 nSize);
90 sal_uInt32 read();
92 void clearReadBuffer() { m_pReadBuffer = 0; }
94 sal_uInt32 write(sal_Int8 const * pBuffer, sal_uInt32 nSize);
96 void setEOF() { m_bEOF = true; }
98 inline bool isEOF() const;
100 bool addMark(sal_uInt32 nPosition);
102 bool removeMark(sal_uInt32 nPosition);
104 inline sal_uInt32 getReadPosition() const;
106 SeekResult setReadPosition(sal_uInt32 nPosition);
109 SvDataPipe_Impl::SvDataPipe_Impl(sal_uInt32 nThePageSize,
110 sal_uInt32 nTheMinPages,
111 sal_uInt32 nTheMaxPages):
112 m_pFirstPage(0),
113 m_pReadPage(0),
114 m_pWritePage(0),
115 m_pReadBuffer(0),
116 m_nPageSize(std::min< sal_uInt32 >(
117 std::max< sal_uInt32 >(nThePageSize, sal_uInt32(1)),
118 sal_uInt32(std::numeric_limits< sal_uInt32 >::max()
119 - sizeof (Page) + 1))),
120 m_nMinPages(std::max< sal_uInt32 >(nTheMinPages, sal_uInt32(1))),
121 m_nMaxPages(std::max< sal_uInt32 >(nTheMaxPages, sal_uInt32(1))),
122 m_nPages(0),
123 m_bEOF(false)
126 inline void SvDataPipe_Impl::setReadBuffer(sal_Int8 * pBuffer,
127 sal_uInt32 nSize)
129 m_pReadBuffer = pBuffer;
130 m_nReadBufferSize = nSize;
131 m_nReadBufferFilled = 0;
134 inline bool SvDataPipe_Impl::isEOF() const
136 return m_bEOF && m_pReadPage == m_pWritePage
137 && (!m_pReadPage || m_pReadPage->m_pRead == m_pReadPage->m_pEnd);
140 inline sal_uInt32 SvDataPipe_Impl::getReadPosition() const
142 return m_pReadPage == 0 ? 0 :
143 m_pReadPage->m_nOffset
144 + (m_pReadPage->m_pRead
145 - m_pReadPage->m_aBuffer);
148 //============================================================================
150 // SvOutputStreamOpenLockBytes
152 //============================================================================
154 TYPEINIT1(SvOutputStreamOpenLockBytes, SvOpenLockBytes)
156 //============================================================================
157 // virtual
158 ErrCode SvOutputStreamOpenLockBytes::ReadAt(ULONG, void *, ULONG, ULONG *)
159 const
161 return ERRCODE_IO_CANTREAD;
164 //============================================================================
165 // virtual
166 ErrCode SvOutputStreamOpenLockBytes::WriteAt(ULONG nPos, void const * pBuffer,
167 ULONG nCount, ULONG * pWritten)
169 if (nPos != m_nPosition)
170 return ERRCODE_IO_CANTWRITE;
171 return FillAppend(pBuffer, nCount, pWritten);
174 //============================================================================
175 // virtual
176 ErrCode SvOutputStreamOpenLockBytes::Flush() const
178 if (!m_xOutputStream.is())
179 return ERRCODE_IO_CANTWRITE;
182 m_xOutputStream->flush();
184 catch (io::IOException)
186 return ERRCODE_IO_CANTWRITE;
188 return ERRCODE_NONE;
191 //============================================================================
192 // virtual
193 ErrCode SvOutputStreamOpenLockBytes::SetSize(ULONG)
195 return ERRCODE_IO_NOTSUPPORTED;
198 //============================================================================
199 // virtual
200 ErrCode SvOutputStreamOpenLockBytes::Stat(SvLockBytesStat * pStat,
201 SvLockBytesStatFlag) const
203 if (pStat)
204 pStat->nSize = m_nPosition;
205 return ERRCODE_NONE;
208 //============================================================================
209 // virtual
210 ErrCode SvOutputStreamOpenLockBytes::FillAppend(void const * pBuffer,
211 ULONG nCount,
212 ULONG * pWritten)
214 if (!m_xOutputStream.is())
215 return ERRCODE_IO_CANTWRITE;
216 if (nCount > 0
217 && nCount > std::numeric_limits< ULONG >::max() - m_nPosition)
219 nCount = std::numeric_limits< ULONG >::max() - m_nPosition;
220 if (nCount == 0)
221 return ERRCODE_IO_CANTWRITE;
225 m_xOutputStream->
226 writeBytes(uno::Sequence< sal_Int8 >(
227 static_cast< sal_Int8 const * >(pBuffer), nCount));
229 catch (io::IOException)
231 return ERRCODE_IO_CANTWRITE;
233 m_nPosition += nCount;
234 if (pWritten)
235 *pWritten = nCount;
236 return ERRCODE_NONE;
239 //============================================================================
240 // virtual
241 ULONG SvOutputStreamOpenLockBytes::Tell() const
243 return m_nPosition;
246 //============================================================================
247 // virtual
248 ULONG SvOutputStreamOpenLockBytes::Seek(ULONG)
250 return m_nPosition;
253 //============================================================================
254 // virtual
255 void SvOutputStreamOpenLockBytes::Terminate()
257 if (m_xOutputStream.is())
260 m_xOutputStream->closeOutput();
262 catch (io::IOException) {}
265 //============================================================================
267 // SvLockBytesInputStream
269 //============================================================================
271 // virtual
272 uno::Any SAL_CALL SvLockBytesInputStream::queryInterface(uno::Type const &
273 rType)
274 throw (uno::RuntimeException)
276 uno::Any
277 aReturn(cppu::queryInterface(rType,
278 static_cast< io::XInputStream * >(this),
279 static_cast< io::XSeekable * >(this)));
280 return aReturn.hasValue() ? aReturn : OWeakObject::queryInterface(rType);
283 //============================================================================
284 // virtual
285 void SAL_CALL SvLockBytesInputStream::acquire() throw ()
287 OWeakObject::acquire();
290 //============================================================================
291 // virtual
292 void SAL_CALL SvLockBytesInputStream::release() throw ()
294 OWeakObject::release();
297 //============================================================================
298 // virtual
299 sal_Int32 SAL_CALL
300 SvLockBytesInputStream::readBytes(uno::Sequence< sal_Int8 > & rData,
301 sal_Int32 nBytesToRead)
302 throw (io::IOException, uno::RuntimeException)
304 OSL_ASSERT(m_nPosition >= 0);
305 if (!m_xLockBytes.Is())
306 throw io::NotConnectedException();
307 if (
308 nBytesToRead < 0 ||
310 static_cast<sal_uInt64>(m_nPosition) > SAL_MAX_SIZE &&
311 nBytesToRead > 0
315 throw io::IOException();
317 rData.realloc(nBytesToRead);
318 sal_Int32 nSize = 0;
319 while (nSize < nBytesToRead)
321 sal_Size nCount;
322 ErrCode nError = m_xLockBytes->ReadAt(static_cast<sal_Size>(
323 m_nPosition),
324 rData.getArray() + nSize,
325 nBytesToRead - nSize, &nCount);
326 if (nError != ERRCODE_NONE && nError != ERRCODE_IO_PENDING)
327 throw io::IOException();
328 m_nPosition += nCount;
329 nSize += nCount;
330 if (nError == ERRCODE_NONE && nCount == 0)
331 break;
333 rData.realloc(nSize);
334 return nSize;
337 //============================================================================
338 // virtual
339 sal_Int32 SAL_CALL
340 SvLockBytesInputStream::readSomeBytes(uno::Sequence< sal_Int8 > & rData,
341 sal_Int32 nMaxBytesToRead)
342 throw (io::IOException, uno::RuntimeException)
344 OSL_ASSERT(m_nPosition >= 0);
345 if (!m_xLockBytes.Is())
346 throw io::NotConnectedException();
347 if (static_cast<sal_uInt64>(m_nPosition) > SAL_MAX_SIZE
348 && nMaxBytesToRead > 0)
349 throw io::IOException();
350 rData.realloc(nMaxBytesToRead);
351 sal_Size nCount = 0;
352 if (nMaxBytesToRead > 0)
354 ErrCode nError;
357 nError = m_xLockBytes->ReadAt(static_cast<sal_Size>(m_nPosition),
358 rData.getArray(),
359 nMaxBytesToRead < 0 ?
360 0 : nMaxBytesToRead,
361 &nCount);
362 if (nError != ERRCODE_NONE && nError != ERRCODE_IO_PENDING)
363 throw io::IOException();
364 m_nPosition += nCount;
366 while (nCount == 0 && nError == ERRCODE_IO_PENDING);
368 rData.realloc(sal_Int32(nCount));
369 return sal_Int32(nCount);
372 //============================================================================
373 // virtual
374 void SAL_CALL SvLockBytesInputStream::skipBytes(sal_Int32 nBytesToSkip)
375 throw (io::IOException, uno::RuntimeException)
377 if (!m_xLockBytes.Is())
378 throw io::NotConnectedException();
379 if (nBytesToSkip < 0)
380 throw io::IOException();
381 if (nBytesToSkip > SAL_MAX_INT64 - m_nPosition)
382 throw io::BufferSizeExceededException();
383 m_nPosition += nBytesToSkip;
386 //============================================================================
387 // virtual
388 sal_Int32 SAL_CALL SvLockBytesInputStream::available()
389 throw (io::IOException, uno::RuntimeException)
391 OSL_ASSERT(m_nPosition >= 0);
392 if (!m_xLockBytes.Is())
393 throw io::NotConnectedException();
394 SvLockBytesStat aStat;
395 if (m_xLockBytes->Stat(&aStat, SVSTATFLAG_DEFAULT) != ERRCODE_NONE)
396 throw io::IOException();
397 return aStat.nSize <= static_cast<sal_uInt64>(m_nPosition) ?
399 static_cast<sal_Size>(aStat.nSize - m_nPosition) <=
400 static_cast<sal_uInt32>(SAL_MAX_INT32) ?
401 static_cast<sal_Int32>(aStat.nSize - m_nPosition) :
402 SAL_MAX_INT32;
405 //============================================================================
406 // virtual
407 void SAL_CALL SvLockBytesInputStream::closeInput()
408 throw (io::IOException, uno::RuntimeException)
410 if (!m_xLockBytes.Is())
411 throw io::NotConnectedException();
412 m_xLockBytes = 0;
415 //============================================================================
416 // virtual
417 void SAL_CALL SvLockBytesInputStream::seek(sal_Int64 nLocation)
418 throw (lang::IllegalArgumentException, io::IOException,
419 uno::RuntimeException)
421 if (nLocation < 0)
422 throw lang::IllegalArgumentException();
423 if (!m_xLockBytes.Is())
424 throw io::NotConnectedException();
425 m_nPosition = nLocation;
428 //============================================================================
429 // virtual
430 sal_Int64 SAL_CALL SvLockBytesInputStream::getPosition()
431 throw (io::IOException, uno::RuntimeException)
433 if (!m_xLockBytes.Is())
434 throw io::NotConnectedException();
435 return m_nPosition;
438 //============================================================================
439 // virtual
440 sal_Int64 SAL_CALL SvLockBytesInputStream::getLength()
441 throw (io::IOException, uno::RuntimeException)
443 if (!m_xLockBytes.Is())
444 throw io::NotConnectedException();
445 SvLockBytesStat aStat;
446 if (m_xLockBytes->Stat(&aStat, SVSTATFLAG_DEFAULT) != ERRCODE_NONE)
447 throw io::IOException();
448 #if SAL_TYPES_SIZEOFPOINTER > 4 // avoid warnings if sal_Size < sal_Int64
449 if (aStat.nSize > static_cast<sal_uInt64>(SAL_MAX_INT64))
450 throw io::IOException();
451 #endif
452 return aStat.nSize;
455 //============================================================================
457 // SvInputStream
459 //============================================================================
461 bool SvInputStream::open()
463 if (GetError() != ERRCODE_NONE)
464 return false;
465 if (!(m_xSeekable.is() || m_pPipe))
467 if (!m_xStream.is())
469 SetError(ERRCODE_IO_INVALIDDEVICE);
470 return false;
472 m_xSeekable
473 = uno::Reference< io::XSeekable >(m_xStream, uno::UNO_QUERY);
474 if (!m_xSeekable.is())
475 m_pPipe = new SvDataPipe_Impl;
477 return true;
480 //============================================================================
481 // virtual
482 ULONG SvInputStream::GetData(void * pData, ULONG nSize)
484 if (!open())
486 SetError(ERRCODE_IO_CANTREAD);
487 return 0;
489 sal_uInt32 nRead = 0;
490 if (m_xSeekable.is())
492 if (m_nSeekedFrom != STREAM_SEEK_TO_END)
496 m_xSeekable->seek(m_nSeekedFrom);
498 catch (io::IOException)
500 SetError(ERRCODE_IO_CANTREAD);
501 return 0;
503 m_nSeekedFrom = STREAM_SEEK_TO_END;
505 for (;;)
507 sal_Int32 nRemain
508 = sal_Int32(
509 std::min(ULONG(nSize - nRead),
510 ULONG(std::numeric_limits< sal_Int32 >::max())));
511 if (nRemain == 0)
512 break;
513 uno::Sequence< sal_Int8 > aBuffer;
514 sal_Int32 nCount;
517 nCount = m_xStream->readBytes(aBuffer, nRemain);
519 catch (io::IOException)
521 SetError(ERRCODE_IO_CANTREAD);
522 return nRead;
524 rtl_copyMemory(static_cast< sal_Int8 * >(pData) + nRead,
525 aBuffer.getConstArray(), sal_uInt32(nCount));
526 nRead += nCount;
527 if (nCount < nRemain)
528 break;
531 else
533 if (m_nSeekedFrom != STREAM_SEEK_TO_END)
535 SetError(ERRCODE_IO_CANTREAD);
536 return 0;
538 m_pPipe->setReadBuffer(static_cast< sal_Int8 * >(pData), nSize);
539 nRead = m_pPipe->read();
540 if (nRead < nSize && !m_pPipe->isEOF())
541 for (;;)
543 sal_Int32 nRemain
544 = sal_Int32(
545 std::min(
546 ULONG(nSize - nRead),
547 ULONG(std::numeric_limits< sal_Int32 >::max())));
548 if (nRemain == 0)
549 break;
550 uno::Sequence< sal_Int8 > aBuffer;
551 sal_Int32 nCount;
554 nCount = m_xStream->readBytes(aBuffer, nRemain);
556 catch (io::IOException)
558 SetError(ERRCODE_IO_CANTREAD);
559 break;
561 m_pPipe->write(aBuffer.getConstArray(), sal_uInt32(nCount));
562 nRead += m_pPipe->read();
563 if (nCount < nRemain)
565 m_xStream->closeInput();
566 m_pPipe->setEOF();
567 break;
570 m_pPipe->clearReadBuffer();
572 return nRead;
575 //============================================================================
576 // virtual
577 ULONG SvInputStream::PutData(void const *, ULONG)
579 SetError(ERRCODE_IO_NOTSUPPORTED);
580 return 0;
583 //============================================================================
584 // virtual
585 void SvInputStream::FlushData()
588 //============================================================================
589 // virtual
590 ULONG SvInputStream::SeekPos(ULONG nPos)
592 if (open())
594 if (nPos == STREAM_SEEK_TO_END)
596 if (m_nSeekedFrom == STREAM_SEEK_TO_END)
598 if (m_xSeekable.is())
601 sal_Int64 nLength = m_xSeekable->getLength();
602 OSL_ASSERT(nLength >= 0);
603 if (static_cast<sal_uInt64>(nLength)
604 < STREAM_SEEK_TO_END)
606 m_nSeekedFrom = Tell();
607 return ULONG(nLength);
610 catch (io::IOException) {}
611 else
612 return Tell(); //@@@
614 else
615 return Tell();
617 else if (nPos == m_nSeekedFrom)
619 m_nSeekedFrom = STREAM_SEEK_TO_END;
620 return nPos;
622 else if (m_xSeekable.is())
625 m_xSeekable->seek(nPos);
626 m_nSeekedFrom = STREAM_SEEK_TO_END;
627 return nPos;
629 catch (io::IOException) {}
630 else if (m_pPipe->setReadPosition(nPos) == SvDataPipe_Impl::SEEK_OK)
632 m_nSeekedFrom = STREAM_SEEK_TO_END;
633 return nPos;
636 SetError(ERRCODE_IO_CANTSEEK);
637 return Tell();
640 //============================================================================
641 // virtual
642 void SvInputStream::SetSize(ULONG)
644 SetError(ERRCODE_IO_NOTSUPPORTED);
647 //============================================================================
648 SvInputStream::SvInputStream(
649 com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
650 const &
651 rTheStream):
652 m_xStream(rTheStream),
653 m_pPipe(0),
654 m_nSeekedFrom(STREAM_SEEK_TO_END)
656 SetBufferSize(0);
659 //============================================================================
660 // virtual
661 SvInputStream::~SvInputStream()
663 if (m_xStream.is())
666 m_xStream->closeInput();
668 catch (io::IOException) {}
669 delete m_pPipe;
672 //============================================================================
673 // virtual
674 USHORT SvInputStream::IsA() const
676 return 0;
679 //============================================================================
680 // virtual
681 void SvInputStream::AddMark(ULONG nPos)
683 if (open() && m_pPipe)
684 m_pPipe->addMark(nPos);
687 //============================================================================
688 // virtual
689 void SvInputStream::RemoveMark(ULONG nPos)
691 if (open() && m_pPipe)
692 m_pPipe->removeMark(nPos);
695 //============================================================================
697 // SvOutputStream
699 //============================================================================
701 // virtual
702 ULONG SvOutputStream::GetData(void *, ULONG)
704 SetError(ERRCODE_IO_NOTSUPPORTED);
705 return 0;
708 //============================================================================
709 // virtual
710 ULONG SvOutputStream::PutData(void const * pData, ULONG nSize)
712 if (!m_xStream.is())
714 SetError(ERRCODE_IO_CANTWRITE);
715 return 0;
717 ULONG nWritten = 0;
718 for (;;)
720 sal_Int32 nRemain
721 = sal_Int32(
722 std::min(ULONG(nSize - nWritten),
723 ULONG(std::numeric_limits< sal_Int32 >::max())));
724 if (nRemain == 0)
725 break;
728 m_xStream->writeBytes(uno::Sequence< sal_Int8 >(
729 static_cast<const sal_Int8 * >(pData)
730 + nWritten,
731 nRemain));
733 catch (io::IOException)
735 SetError(ERRCODE_IO_CANTWRITE);
736 break;
738 nWritten += nRemain;
740 return nWritten;
743 //============================================================================
744 // virtual
745 ULONG SvOutputStream::SeekPos(ULONG)
747 SetError(ERRCODE_IO_NOTSUPPORTED);
748 return 0;
751 //============================================================================
752 // virtual
753 void SvOutputStream::FlushData()
755 if (!m_xStream.is())
757 SetError(ERRCODE_IO_INVALIDDEVICE);
758 return;
762 m_xStream->flush();
764 catch (io::IOException) {}
767 //============================================================================
768 // virtual
769 void SvOutputStream::SetSize(ULONG)
771 SetError(ERRCODE_IO_NOTSUPPORTED);
774 //============================================================================
775 SvOutputStream::SvOutputStream(uno::Reference< io::XOutputStream > const &
776 rTheStream):
777 m_xStream(rTheStream)
779 SetBufferSize(0);
782 //============================================================================
783 // virtual
784 SvOutputStream::~SvOutputStream()
786 if (m_xStream.is())
789 m_xStream->closeOutput();
791 catch (io::IOException) {}
794 //============================================================================
795 // virtual
796 USHORT SvOutputStream::IsA() const
798 return 0;
801 //============================================================================
803 // SvDataPipe_Impl
805 //============================================================================
807 bool SvDataPipe_Impl::remove(Page * pPage)
809 if (
810 pPage != m_pFirstPage ||
811 m_pReadPage == m_pFirstPage ||
813 !m_aMarks.empty() &&
814 *m_aMarks.begin() < m_pFirstPage->m_nOffset + m_nPageSize
818 return false;
821 m_pFirstPage = m_pFirstPage->m_pNext;
823 if (m_nPages <= m_nMinPages)
824 return true;
826 pPage->m_pPrev->m_pNext = pPage->m_pNext;
827 pPage->m_pNext->m_pPrev = pPage->m_pPrev;
828 rtl_freeMemory(pPage);
829 --m_nPages;
831 return true;
834 //============================================================================
835 SvDataPipe_Impl::~SvDataPipe_Impl()
837 if (m_pFirstPage != 0)
838 for (Page * pPage = m_pFirstPage;;)
840 Page * pNext = pPage->m_pNext;
841 rtl_freeMemory(pPage);
842 if (pNext == m_pFirstPage)
843 break;
844 pPage = pNext;
848 //============================================================================
849 sal_uInt32 SvDataPipe_Impl::read()
851 if (m_pReadBuffer == 0 || m_nReadBufferSize == 0 || m_pReadPage == 0)
852 return 0;
854 sal_uInt32 nSize = m_nReadBufferSize;
855 sal_uInt32 nRemain = m_nReadBufferSize - m_nReadBufferFilled;
857 m_pReadBuffer += m_nReadBufferFilled;
858 m_nReadBufferSize -= m_nReadBufferFilled;
859 m_nReadBufferFilled = 0;
861 while (nRemain > 0)
863 sal_uInt32 nBlock = std::min(sal_uInt32(m_pReadPage->m_pEnd
864 - m_pReadPage->m_pRead),
865 nRemain);
866 rtl_copyMemory(m_pReadBuffer, m_pReadPage->m_pRead, nBlock);
867 m_pReadPage->m_pRead += nBlock;
868 m_pReadBuffer += nBlock;
869 m_nReadBufferSize -= nBlock;
870 m_nReadBufferFilled = 0;
871 nRemain -= nBlock;
873 if (m_pReadPage == m_pWritePage)
874 break;
876 if (m_pReadPage->m_pRead == m_pReadPage->m_pEnd)
878 Page * pRemove = m_pReadPage;
879 m_pReadPage = pRemove->m_pNext;
880 remove(pRemove);
884 return nSize - nRemain;
887 //============================================================================
888 sal_uInt32 SvDataPipe_Impl::write(sal_Int8 const * pBuffer, sal_uInt32 nSize)
890 if (nSize == 0)
891 return 0;
893 if (m_pWritePage == 0)
895 m_pFirstPage
896 = static_cast< Page * >(rtl_allocateMemory(sizeof (Page)
897 + m_nPageSize
898 - 1));
899 m_pFirstPage->m_pPrev = m_pFirstPage;
900 m_pFirstPage->m_pNext = m_pFirstPage;
901 m_pFirstPage->m_pStart = m_pFirstPage->m_aBuffer;
902 m_pFirstPage->m_pRead = m_pFirstPage->m_aBuffer;
903 m_pFirstPage->m_pEnd = m_pFirstPage->m_aBuffer;
904 m_pFirstPage->m_nOffset = 0;
905 m_pReadPage = m_pFirstPage;
906 m_pWritePage = m_pFirstPage;
907 ++m_nPages;
910 sal_uInt32 nRemain = nSize;
912 if (m_pReadBuffer != 0 && m_pReadPage == m_pWritePage
913 && m_pReadPage->m_pRead == m_pWritePage->m_pEnd)
915 sal_uInt32 nBlock = std::min(nRemain,
916 sal_uInt32(m_nReadBufferSize
917 - m_nReadBufferFilled));
918 sal_uInt32 nPosition = m_pWritePage->m_nOffset
919 + (m_pWritePage->m_pEnd
920 - m_pWritePage->m_aBuffer);
921 if (!m_aMarks.empty())
922 nBlock = *m_aMarks.begin() > nPosition ?
923 std::min(nBlock, sal_uInt32(*m_aMarks.begin()
924 - nPosition)) :
927 if (nBlock > 0)
929 rtl_copyMemory(m_pReadBuffer + m_nReadBufferFilled, pBuffer,
930 nBlock);
931 m_nReadBufferFilled += nBlock;
932 nRemain -= nBlock;
934 nPosition += nBlock;
935 m_pWritePage->m_nOffset = (nPosition / m_nPageSize) * m_nPageSize;
936 m_pWritePage->m_pStart = m_pWritePage->m_aBuffer
937 + nPosition % m_nPageSize;
938 m_pWritePage->m_pRead = m_pWritePage->m_pStart;
939 m_pWritePage->m_pEnd = m_pWritePage->m_pStart;
943 if (nRemain > 0)
944 for (;;)
946 sal_uInt32 nBlock
947 = std::min(sal_uInt32(m_pWritePage->m_aBuffer + m_nPageSize
948 - m_pWritePage->m_pEnd),
949 nRemain);
950 rtl_copyMemory(m_pWritePage->m_pEnd, pBuffer, nBlock);
951 m_pWritePage->m_pEnd += nBlock;
952 pBuffer += nBlock;
953 nRemain -= nBlock;
955 if (nRemain == 0)
956 break;
958 if (m_pWritePage->m_pNext == m_pFirstPage)
960 if (m_nPages == m_nMaxPages)
961 break;
963 Page * pNew
964 = static_cast< Page * >(rtl_allocateMemory(
965 sizeof (Page) + m_nPageSize
966 - 1));
967 pNew->m_pPrev = m_pWritePage;
968 pNew->m_pNext = m_pWritePage->m_pNext;
970 m_pWritePage->m_pNext->m_pPrev = pNew;
971 m_pWritePage->m_pNext = pNew;
972 ++m_nPages;
975 m_pWritePage->m_pNext->m_nOffset = m_pWritePage->m_nOffset
976 + m_nPageSize;
977 m_pWritePage = m_pWritePage->m_pNext;
978 m_pWritePage->m_pStart = m_pWritePage->m_aBuffer;
979 m_pWritePage->m_pRead = m_pWritePage->m_aBuffer;
980 m_pWritePage->m_pEnd = m_pWritePage->m_aBuffer;
983 return nSize - nRemain;
986 //============================================================================
987 bool SvDataPipe_Impl::addMark(sal_uInt32 nPosition)
989 if (m_pFirstPage != 0 && m_pFirstPage->m_nOffset > nPosition)
990 return false;
991 m_aMarks.insert(nPosition);
992 return true;
995 //============================================================================
996 bool SvDataPipe_Impl::removeMark(sal_uInt32 nPosition)
998 std::multiset< sal_uInt32 >::iterator t = m_aMarks.find(nPosition);
999 if (t == m_aMarks.end())
1000 return false;
1001 m_aMarks.erase(t);
1002 while (remove(m_pFirstPage)) ;
1003 return true;
1006 //============================================================================
1007 SvDataPipe_Impl::SeekResult SvDataPipe_Impl::setReadPosition(sal_uInt32
1008 nPosition)
1010 if (m_pFirstPage == 0)
1011 return nPosition == 0 ? SEEK_OK : SEEK_PAST_END;
1013 if (nPosition
1014 <= m_pReadPage->m_nOffset
1015 + (m_pReadPage->m_pRead - m_pReadPage->m_aBuffer))
1017 if (nPosition
1018 < m_pFirstPage->m_nOffset
1019 + (m_pFirstPage->m_pStart - m_pFirstPage->m_aBuffer))
1020 return SEEK_BEFORE_MARKED;
1022 while (nPosition < m_pReadPage->m_nOffset)
1024 m_pReadPage->m_pRead = m_pReadPage->m_pStart;
1025 m_pReadPage = m_pReadPage->m_pPrev;
1028 else
1030 if (nPosition
1031 > m_pWritePage->m_nOffset
1032 + (m_pWritePage->m_pEnd - m_pWritePage->m_aBuffer))
1033 return SEEK_PAST_END;
1035 while (m_pReadPage != m_pWritePage
1036 && nPosition >= m_pReadPage->m_nOffset + m_nPageSize)
1038 Page * pRemove = m_pReadPage;
1039 m_pReadPage = pRemove->m_pNext;
1040 remove(pRemove);
1044 m_pReadPage->m_pRead = m_pReadPage->m_aBuffer
1045 + (nPosition - m_pReadPage->m_nOffset);
1046 return SEEK_OK;