xref: /trunk/main/svl/source/misc/strmadpt.cxx (revision 40df464e)
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