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