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>
22 :
23 : #include <algorithm>
24 : #include <limits>
25 : #include <set>
26 : #include <string.h>
27 :
28 : #include <com/sun/star/io/XInputStream.hpp>
29 : #include <com/sun/star/io/XSeekable.hpp>
30 :
31 : #include <osl/diagnose.h>
32 : #include <rtl/alloc.h>
33 : #include <cppuhelper/queryinterface.hxx>
34 : #include <svl/instrm.hxx>
35 : #include <svl/outstrm.hxx>
36 :
37 : #include <strmadpt.hxx>
38 :
39 : using namespace com::sun::star;
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 :
85 0 : void clearReadBuffer() { m_pReadBuffer = 0; }
86 :
87 : sal_uInt32 write(sal_Int8 const * pBuffer, sal_uInt32 nSize);
88 :
89 0 : void setEOF() { m_bEOF = true; }
90 :
91 : inline bool isEOF() 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_nReadBufferSize( 0 )
104 : , m_nReadBufferFilled( 0 )
105 : , m_nPageSize(std::min< sal_uInt32 >(
106 0 : std::max< sal_uInt32 >(nThePageSize, sal_uInt32(1)),
107 0 : sal_uInt32(std::numeric_limits< sal_uInt32 >::max()
108 0 : - sizeof (Page) + 1)))
109 0 : , m_nMinPages(std::max< sal_uInt32 >(nTheMinPages, sal_uInt32(1)))
110 0 : , m_nMaxPages(std::max< sal_uInt32 >(nTheMaxPages, sal_uInt32(1)))
111 : , m_nPages( 0 )
112 0 : , m_bEOF( false )
113 0 : {}
114 :
115 0 : inline void SvDataPipe_Impl::setReadBuffer(sal_Int8 * pBuffer,
116 : sal_uInt32 nSize)
117 : {
118 0 : m_pReadBuffer = pBuffer;
119 0 : m_nReadBufferSize = nSize;
120 0 : m_nReadBufferFilled = 0;
121 0 : }
122 :
123 0 : inline bool SvDataPipe_Impl::isEOF() const
124 : {
125 0 : return m_bEOF && m_pReadPage == m_pWritePage
126 0 : && (!m_pReadPage || m_pReadPage->m_pRead == m_pReadPage->m_pEnd);
127 : }
128 :
129 : // SvOutputStreamOpenLockBytes
130 :
131 :
132 0 : TYPEINIT1(SvOutputStreamOpenLockBytes, SvOpenLockBytes)
133 :
134 : // virtual
135 0 : ErrCode SvOutputStreamOpenLockBytes::ReadAt(sal_uInt64, void *, sal_uLong, sal_uLong*)
136 : const
137 : {
138 0 : return ERRCODE_IO_CANTREAD;
139 : }
140 :
141 : // virtual
142 0 : ErrCode SvOutputStreamOpenLockBytes::WriteAt(sal_uInt64 const nPos, void const * pBuffer,
143 : sal_uLong nCount, sal_uLong * pWritten)
144 : {
145 0 : if (nPos != m_nPosition)
146 0 : return ERRCODE_IO_CANTWRITE;
147 0 : return FillAppend(pBuffer, nCount, pWritten);
148 : }
149 :
150 : // virtual
151 0 : ErrCode SvOutputStreamOpenLockBytes::Flush() const
152 : {
153 0 : if (!m_xOutputStream.is())
154 0 : return ERRCODE_IO_CANTWRITE;
155 : try
156 : {
157 0 : m_xOutputStream->flush();
158 : }
159 0 : catch (const io::IOException&)
160 : {
161 0 : return ERRCODE_IO_CANTWRITE;
162 : }
163 0 : return ERRCODE_NONE;
164 : }
165 :
166 : // virtual
167 0 : ErrCode SvOutputStreamOpenLockBytes::SetSize(sal_uInt64)
168 : {
169 0 : return ERRCODE_IO_NOTSUPPORTED;
170 : }
171 :
172 : // virtual
173 0 : ErrCode SvOutputStreamOpenLockBytes::Stat(SvLockBytesStat * pStat,
174 : SvLockBytesStatFlag) const
175 : {
176 0 : if (pStat)
177 0 : pStat->nSize = m_nPosition;
178 0 : return ERRCODE_NONE;
179 : }
180 :
181 : // virtual
182 0 : ErrCode SvOutputStreamOpenLockBytes::FillAppend(void const * pBuffer,
183 : sal_uLong nCount,
184 : sal_uLong * pWritten)
185 : {
186 0 : if (!m_xOutputStream.is())
187 0 : return ERRCODE_IO_CANTWRITE;
188 0 : if (nCount > 0
189 0 : && nCount > std::numeric_limits< sal_uLong >::max() - m_nPosition)
190 : {
191 0 : nCount = std::numeric_limits< sal_uLong >::max() - m_nPosition;
192 0 : if (nCount == 0)
193 0 : return ERRCODE_IO_CANTWRITE;
194 : }
195 : try
196 : {
197 0 : m_xOutputStream->
198 : writeBytes(uno::Sequence< sal_Int8 >(
199 0 : static_cast< sal_Int8 const * >(pBuffer), nCount));
200 : }
201 0 : catch (const io::IOException&)
202 : {
203 0 : return ERRCODE_IO_CANTWRITE;
204 : }
205 0 : m_nPosition += nCount;
206 0 : if (pWritten)
207 0 : *pWritten = nCount;
208 0 : return ERRCODE_NONE;
209 : }
210 :
211 : // virtual
212 0 : sal_uInt64 SvOutputStreamOpenLockBytes::Tell() const
213 : {
214 0 : return m_nPosition;
215 : }
216 :
217 : // virtual
218 0 : sal_uInt64 SvOutputStreamOpenLockBytes::Seek(sal_uInt64)
219 : {
220 0 : return m_nPosition;
221 : }
222 :
223 : // virtual
224 0 : void SvOutputStreamOpenLockBytes::Terminate()
225 : {
226 0 : if (m_xOutputStream.is())
227 : {
228 : try
229 : {
230 0 : m_xOutputStream->closeOutput();
231 : }
232 0 : catch (const io::IOException&)
233 : {
234 : }
235 : }
236 0 : }
237 :
238 :
239 : // SvInputStream
240 :
241 :
242 0 : bool SvInputStream::open()
243 : {
244 0 : if (GetError() != ERRCODE_NONE)
245 0 : return false;
246 0 : if (!(m_xSeekable.is() || m_pPipe))
247 : {
248 0 : if (!m_xStream.is())
249 : {
250 0 : SetError(ERRCODE_IO_INVALIDDEVICE);
251 0 : return false;
252 : }
253 : m_xSeekable
254 0 : = uno::Reference< io::XSeekable >(m_xStream, uno::UNO_QUERY);
255 0 : if (!m_xSeekable.is())
256 0 : m_pPipe = new SvDataPipe_Impl;
257 : }
258 0 : return true;
259 : }
260 :
261 : // virtual
262 0 : sal_uLong SvInputStream::GetData(void * pData, sal_uLong nSize)
263 : {
264 0 : if (!open())
265 : {
266 0 : SetError(ERRCODE_IO_CANTREAD);
267 0 : return 0;
268 : }
269 : // check if a truncated STREAM_SEEK_TO_END was passed
270 : assert(m_nSeekedFrom != SAL_MAX_UINT32);
271 0 : sal_uInt32 nRead = 0;
272 0 : if (m_xSeekable.is())
273 : {
274 0 : if (m_nSeekedFrom != STREAM_SEEK_TO_END)
275 : {
276 : try
277 : {
278 0 : m_xSeekable->seek(m_nSeekedFrom);
279 : }
280 0 : catch (const io::IOException&)
281 : {
282 0 : SetError(ERRCODE_IO_CANTREAD);
283 0 : return 0;
284 : }
285 0 : m_nSeekedFrom = STREAM_SEEK_TO_END;
286 : }
287 : for (;;)
288 : {
289 : sal_Int32 nRemain
290 : = sal_Int32(
291 0 : std::min(sal_uLong(nSize - nRead),
292 0 : sal_uLong(std::numeric_limits< sal_Int32 >::max())));
293 0 : if (nRemain == 0)
294 0 : break;
295 0 : uno::Sequence< sal_Int8 > aBuffer;
296 : sal_Int32 nCount;
297 : try
298 : {
299 0 : nCount = m_xStream->readBytes(aBuffer, nRemain);
300 : }
301 0 : catch (const io::IOException&)
302 : {
303 0 : SetError(ERRCODE_IO_CANTREAD);
304 0 : return nRead;
305 : }
306 0 : memcpy(static_cast< sal_Int8 * >(pData) + nRead,
307 0 : aBuffer.getConstArray(), sal_uInt32(nCount));
308 0 : nRead += nCount;
309 0 : if (nCount < nRemain)
310 0 : break;
311 0 : }
312 : }
313 : else
314 : {
315 0 : if (m_nSeekedFrom != STREAM_SEEK_TO_END)
316 : {
317 0 : SetError(ERRCODE_IO_CANTREAD);
318 0 : return 0;
319 : }
320 0 : m_pPipe->setReadBuffer(static_cast< sal_Int8 * >(pData), nSize);
321 0 : nRead = m_pPipe->read();
322 0 : if (nRead < nSize && !m_pPipe->isEOF())
323 : for (;;)
324 : {
325 : sal_Int32 nRemain
326 : = sal_Int32(
327 : std::min(
328 0 : sal_uLong(nSize - nRead),
329 0 : sal_uLong(std::numeric_limits< sal_Int32 >::max())));
330 0 : if (nRemain == 0)
331 0 : break;
332 0 : uno::Sequence< sal_Int8 > aBuffer;
333 : sal_Int32 nCount;
334 : try
335 : {
336 0 : nCount = m_xStream->readBytes(aBuffer, nRemain);
337 : }
338 0 : catch (const io::IOException&)
339 : {
340 0 : SetError(ERRCODE_IO_CANTREAD);
341 0 : break;
342 : }
343 0 : m_pPipe->write(aBuffer.getConstArray(), sal_uInt32(nCount));
344 0 : nRead += m_pPipe->read();
345 0 : if (nCount < nRemain)
346 : {
347 0 : m_xStream->closeInput();
348 0 : m_pPipe->setEOF();
349 0 : break;
350 : }
351 0 : }
352 0 : m_pPipe->clearReadBuffer();
353 : }
354 0 : return nRead;
355 : }
356 :
357 : // virtual
358 0 : sal_uLong SvInputStream::PutData(void const *, sal_uLong)
359 : {
360 0 : SetError(ERRCODE_IO_NOTSUPPORTED);
361 0 : return 0;
362 : }
363 :
364 : // virtual
365 0 : void SvInputStream::FlushData()
366 0 : {}
367 :
368 : // virtual
369 0 : sal_uInt64 SvInputStream::SeekPos(sal_uInt64 const nPos)
370 : {
371 : // check if a truncated STREAM_SEEK_TO_END was passed
372 : assert(nPos != SAL_MAX_UINT32);
373 0 : if (open())
374 : {
375 0 : if (nPos == STREAM_SEEK_TO_END)
376 : {
377 0 : if (m_nSeekedFrom == STREAM_SEEK_TO_END)
378 : {
379 0 : if (m_xSeekable.is())
380 : try
381 : {
382 0 : sal_Int64 nLength = m_xSeekable->getLength();
383 : OSL_ASSERT(nLength >= 0);
384 0 : if (static_cast<sal_uInt64>(nLength)
385 : < STREAM_SEEK_TO_END)
386 : {
387 0 : m_nSeekedFrom = Tell();
388 0 : return sal_uLong(nLength);
389 : }
390 : }
391 0 : catch (const io::IOException&)
392 : {
393 : }
394 : else
395 0 : return Tell(); //@@@
396 : }
397 : else
398 0 : return Tell();
399 : }
400 0 : else if (nPos == m_nSeekedFrom)
401 : {
402 0 : m_nSeekedFrom = STREAM_SEEK_TO_END;
403 0 : return nPos;
404 : }
405 0 : else if (m_xSeekable.is())
406 : {
407 : try
408 : {
409 0 : m_xSeekable->seek(nPos);
410 0 : m_nSeekedFrom = STREAM_SEEK_TO_END;
411 0 : return nPos;
412 : }
413 0 : catch (const io::IOException&)
414 : {
415 : }
416 : }
417 0 : else if (m_pPipe->setReadPosition(nPos) == SvDataPipe_Impl::SEEK_OK)
418 : {
419 0 : m_nSeekedFrom = STREAM_SEEK_TO_END;
420 0 : return nPos;
421 : }
422 0 : else if ( nPos > Tell() )
423 : {
424 : // Read out the bytes
425 0 : sal_Int32 nRead = nPos - Tell();
426 0 : uno::Sequence< sal_Int8 > aBuffer;
427 0 : m_xStream->readBytes( aBuffer, nRead );
428 0 : return nPos;
429 : }
430 0 : else if ( nPos == Tell() )
431 0 : return nPos;
432 : }
433 0 : SetError(ERRCODE_IO_CANTSEEK);
434 0 : return Tell();
435 : }
436 :
437 : // virtual
438 0 : void SvInputStream::SetSize(sal_uInt64)
439 : {
440 0 : SetError(ERRCODE_IO_NOTSUPPORTED);
441 0 : }
442 :
443 0 : SvInputStream::SvInputStream(
444 : com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
445 : const &
446 : rTheStream):
447 : m_xStream(rTheStream),
448 : m_pPipe(0),
449 0 : m_nSeekedFrom(STREAM_SEEK_TO_END)
450 : {
451 0 : SetBufferSize(0);
452 0 : }
453 :
454 : // virtual
455 0 : SvInputStream::~SvInputStream()
456 : {
457 0 : if (m_xStream.is())
458 : {
459 : try
460 : {
461 0 : m_xStream->closeInput();
462 : }
463 0 : catch (const io::IOException&)
464 : {
465 : }
466 : }
467 0 : delete m_pPipe;
468 0 : }
469 :
470 : // SvOutputStream
471 :
472 : // virtual
473 0 : sal_uLong SvOutputStream::GetData(void *, sal_uLong)
474 : {
475 0 : SetError(ERRCODE_IO_NOTSUPPORTED);
476 0 : return 0;
477 : }
478 :
479 : // virtual
480 1417 : sal_uLong SvOutputStream::PutData(void const * pData, sal_uLong nSize)
481 : {
482 1417 : if (!m_xStream.is())
483 : {
484 0 : SetError(ERRCODE_IO_CANTWRITE);
485 0 : return 0;
486 : }
487 1417 : sal_uLong nWritten = 0;
488 : for (;;)
489 : {
490 : sal_Int32 nRemain
491 : = sal_Int32(
492 2834 : std::min(sal_uLong(nSize - nWritten),
493 5668 : sal_uLong(std::numeric_limits< sal_Int32 >::max())));
494 2834 : if (nRemain == 0)
495 1417 : break;
496 : try
497 : {
498 1417 : m_xStream->writeBytes(uno::Sequence< sal_Int8 >(
499 : static_cast<const sal_Int8 * >(pData)
500 : + nWritten,
501 1417 : nRemain));
502 : }
503 0 : catch (const io::IOException&)
504 : {
505 0 : SetError(ERRCODE_IO_CANTWRITE);
506 0 : break;
507 : }
508 1417 : nWritten += nRemain;
509 1417 : }
510 1417 : return nWritten;
511 : }
512 :
513 : // virtual
514 0 : sal_uInt64 SvOutputStream::SeekPos(sal_uInt64)
515 : {
516 0 : SetError(ERRCODE_IO_NOTSUPPORTED);
517 0 : return 0;
518 : }
519 :
520 : // virtual
521 0 : void SvOutputStream::FlushData()
522 : {
523 0 : if (!m_xStream.is())
524 : {
525 0 : SetError(ERRCODE_IO_INVALIDDEVICE);
526 0 : return;
527 : }
528 : try
529 : {
530 0 : m_xStream->flush();
531 : }
532 0 : catch (const io::IOException&)
533 : {
534 : }
535 : }
536 :
537 : // virtual
538 0 : void SvOutputStream::SetSize(sal_uInt64)
539 : {
540 0 : SetError(ERRCODE_IO_NOTSUPPORTED);
541 0 : }
542 :
543 35 : SvOutputStream::SvOutputStream(uno::Reference< io::XOutputStream > const &
544 : rTheStream):
545 35 : m_xStream(rTheStream)
546 : {
547 35 : SetBufferSize(0);
548 35 : }
549 :
550 : // virtual
551 70 : SvOutputStream::~SvOutputStream()
552 : {
553 35 : if (m_xStream.is())
554 : {
555 : try
556 : {
557 35 : m_xStream->closeOutput();
558 : }
559 0 : catch (const io::IOException&)
560 : {
561 : }
562 : }
563 35 : }
564 :
565 :
566 : // SvDataPipe_Impl
567 :
568 :
569 0 : bool SvDataPipe_Impl::remove(Page * pPage)
570 : {
571 0 : if (
572 0 : pPage != m_pFirstPage ||
573 0 : m_pReadPage == m_pFirstPage ||
574 : (
575 0 : !m_aMarks.empty() &&
576 0 : *m_aMarks.begin() < m_pFirstPage->m_nOffset + m_nPageSize
577 : )
578 : )
579 : {
580 0 : return false;
581 : }
582 :
583 0 : m_pFirstPage = m_pFirstPage->m_pNext;
584 :
585 0 : if (m_nPages <= m_nMinPages)
586 0 : return true;
587 :
588 0 : pPage->m_pPrev->m_pNext = pPage->m_pNext;
589 0 : pPage->m_pNext->m_pPrev = pPage->m_pPrev;
590 0 : rtl_freeMemory(pPage);
591 0 : --m_nPages;
592 :
593 0 : return true;
594 : }
595 :
596 0 : SvDataPipe_Impl::~SvDataPipe_Impl()
597 : {
598 0 : if (m_pFirstPage != 0)
599 0 : for (Page * pPage = m_pFirstPage;;)
600 : {
601 0 : Page * pNext = pPage->m_pNext;
602 0 : rtl_freeMemory(pPage);
603 0 : if (pNext == m_pFirstPage)
604 0 : break;
605 0 : pPage = pNext;
606 0 : }
607 0 : }
608 :
609 0 : sal_uInt32 SvDataPipe_Impl::read()
610 : {
611 0 : if (m_pReadBuffer == 0 || m_nReadBufferSize == 0 || m_pReadPage == 0)
612 0 : return 0;
613 :
614 0 : sal_uInt32 nSize = m_nReadBufferSize;
615 0 : sal_uInt32 nRemain = m_nReadBufferSize - m_nReadBufferFilled;
616 :
617 0 : m_pReadBuffer += m_nReadBufferFilled;
618 0 : m_nReadBufferSize -= m_nReadBufferFilled;
619 0 : m_nReadBufferFilled = 0;
620 :
621 0 : while (nRemain > 0)
622 : {
623 : sal_uInt32 nBlock = std::min(sal_uInt32(m_pReadPage->m_pEnd
624 0 : - m_pReadPage->m_pRead),
625 0 : nRemain);
626 0 : memcpy(m_pReadBuffer, m_pReadPage->m_pRead, nBlock);
627 0 : m_pReadPage->m_pRead += nBlock;
628 0 : m_pReadBuffer += nBlock;
629 0 : m_nReadBufferSize -= nBlock;
630 0 : m_nReadBufferFilled = 0;
631 0 : nRemain -= nBlock;
632 :
633 0 : if (m_pReadPage == m_pWritePage)
634 0 : break;
635 :
636 0 : if (m_pReadPage->m_pRead == m_pReadPage->m_pEnd)
637 : {
638 0 : Page * pRemove = m_pReadPage;
639 0 : m_pReadPage = pRemove->m_pNext;
640 0 : remove(pRemove);
641 : }
642 : }
643 :
644 0 : return nSize - nRemain;
645 : }
646 :
647 0 : sal_uInt32 SvDataPipe_Impl::write(sal_Int8 const * pBuffer, sal_uInt32 nSize)
648 : {
649 0 : if (nSize == 0)
650 0 : return 0;
651 :
652 0 : if (m_pWritePage == 0)
653 : {
654 : m_pFirstPage
655 : = static_cast< Page * >(rtl_allocateMemory(sizeof (Page)
656 0 : + m_nPageSize
657 0 : - 1));
658 0 : m_pFirstPage->m_pPrev = m_pFirstPage;
659 0 : m_pFirstPage->m_pNext = m_pFirstPage;
660 0 : m_pFirstPage->m_pStart = m_pFirstPage->m_aBuffer;
661 0 : m_pFirstPage->m_pRead = m_pFirstPage->m_aBuffer;
662 0 : m_pFirstPage->m_pEnd = m_pFirstPage->m_aBuffer;
663 0 : m_pFirstPage->m_nOffset = 0;
664 0 : m_pReadPage = m_pFirstPage;
665 0 : m_pWritePage = m_pFirstPage;
666 0 : ++m_nPages;
667 : }
668 :
669 0 : sal_uInt32 nRemain = nSize;
670 :
671 0 : if (m_pReadBuffer != 0 && m_pReadPage == m_pWritePage
672 0 : && m_pReadPage->m_pRead == m_pWritePage->m_pEnd)
673 : {
674 : sal_uInt32 nBlock = std::min(nRemain,
675 : sal_uInt32(m_nReadBufferSize
676 0 : - m_nReadBufferFilled));
677 : sal_uInt32 nPosition = m_pWritePage->m_nOffset
678 : + (m_pWritePage->m_pEnd
679 0 : - m_pWritePage->m_aBuffer);
680 0 : if (!m_aMarks.empty())
681 0 : nBlock = *m_aMarks.begin() > nPosition ?
682 0 : std::min(nBlock, sal_uInt32(*m_aMarks.begin()
683 0 : - nPosition)) :
684 0 : 0;
685 :
686 0 : if (nBlock > 0)
687 : {
688 0 : memcpy(m_pReadBuffer + m_nReadBufferFilled, pBuffer,
689 0 : nBlock);
690 0 : m_nReadBufferFilled += nBlock;
691 0 : nRemain -= nBlock;
692 :
693 0 : nPosition += nBlock;
694 0 : m_pWritePage->m_nOffset = (nPosition / m_nPageSize) * m_nPageSize;
695 : m_pWritePage->m_pStart = m_pWritePage->m_aBuffer
696 0 : + nPosition % m_nPageSize;
697 0 : m_pWritePage->m_pRead = m_pWritePage->m_pStart;
698 0 : m_pWritePage->m_pEnd = m_pWritePage->m_pStart;
699 : }
700 : }
701 :
702 0 : if (nRemain > 0)
703 : for (;;)
704 : {
705 : sal_uInt32 nBlock
706 0 : = std::min(sal_uInt32(m_pWritePage->m_aBuffer + m_nPageSize
707 0 : - m_pWritePage->m_pEnd),
708 0 : nRemain);
709 0 : memcpy(m_pWritePage->m_pEnd, pBuffer, nBlock);
710 0 : m_pWritePage->m_pEnd += nBlock;
711 0 : pBuffer += nBlock;
712 0 : nRemain -= nBlock;
713 :
714 0 : if (nRemain == 0)
715 0 : break;
716 :
717 0 : if (m_pWritePage->m_pNext == m_pFirstPage)
718 : {
719 0 : if (m_nPages == m_nMaxPages)
720 0 : break;
721 :
722 : Page * pNew
723 : = static_cast< Page * >(rtl_allocateMemory(
724 0 : sizeof (Page) + m_nPageSize
725 0 : - 1));
726 0 : pNew->m_pPrev = m_pWritePage;
727 0 : pNew->m_pNext = m_pWritePage->m_pNext;
728 :
729 0 : m_pWritePage->m_pNext->m_pPrev = pNew;
730 0 : m_pWritePage->m_pNext = pNew;
731 0 : ++m_nPages;
732 : }
733 :
734 : m_pWritePage->m_pNext->m_nOffset = m_pWritePage->m_nOffset
735 0 : + m_nPageSize;
736 0 : m_pWritePage = m_pWritePage->m_pNext;
737 0 : m_pWritePage->m_pStart = m_pWritePage->m_aBuffer;
738 0 : m_pWritePage->m_pRead = m_pWritePage->m_aBuffer;
739 0 : m_pWritePage->m_pEnd = m_pWritePage->m_aBuffer;
740 0 : }
741 :
742 0 : return nSize - nRemain;
743 : }
744 :
745 0 : SvDataPipe_Impl::SeekResult SvDataPipe_Impl::setReadPosition(sal_uInt32
746 : nPosition)
747 : {
748 0 : if (m_pFirstPage == 0)
749 0 : return nPosition == 0 ? SEEK_OK : SEEK_PAST_END;
750 :
751 0 : if (nPosition
752 0 : <= m_pReadPage->m_nOffset
753 0 : + (m_pReadPage->m_pRead - m_pReadPage->m_aBuffer))
754 : {
755 0 : if (nPosition
756 0 : < m_pFirstPage->m_nOffset
757 0 : + (m_pFirstPage->m_pStart - m_pFirstPage->m_aBuffer))
758 0 : return SEEK_BEFORE_MARKED;
759 :
760 0 : while (nPosition < m_pReadPage->m_nOffset)
761 : {
762 0 : m_pReadPage->m_pRead = m_pReadPage->m_pStart;
763 0 : m_pReadPage = m_pReadPage->m_pPrev;
764 : }
765 : }
766 : else
767 : {
768 0 : if (nPosition
769 0 : > m_pWritePage->m_nOffset
770 0 : + (m_pWritePage->m_pEnd - m_pWritePage->m_aBuffer))
771 0 : return SEEK_PAST_END;
772 :
773 0 : while (m_pReadPage != m_pWritePage
774 0 : && nPosition >= m_pReadPage->m_nOffset + m_nPageSize)
775 : {
776 0 : Page * pRemove = m_pReadPage;
777 0 : m_pReadPage = pRemove->m_pNext;
778 0 : remove(pRemove);
779 : }
780 : }
781 :
782 : m_pReadPage->m_pRead = m_pReadPage->m_aBuffer
783 0 : + (nPosition - m_pReadPage->m_nOffset);
784 0 : return SEEK_OK;
785 : }
786 :
787 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|