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