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 85 void clearReadBuffer() { m_pReadBuffer = 0; } 86 87 sal_uInt32 write(sal_Int8 const * pBuffer, sal_uInt32 nSize); 88 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 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 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 127 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 133 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 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 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 169 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 186 ErrCode SvOutputStreamOpenLockBytes::SetSize(sal_uLong) 187 { 188 return ERRCODE_IO_NOTSUPPORTED; 189 } 190 191 //============================================================================ 192 // virtual 193 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 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 234 sal_uLong SvOutputStreamOpenLockBytes::Tell() const 235 { 236 return m_nPosition; 237 } 238 239 //============================================================================ 240 // virtual 241 sal_uLong SvOutputStreamOpenLockBytes::Seek(sal_uLong) 242 { 243 return m_nPosition; 244 } 245 246 //============================================================================ 247 // virtual 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 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 278 void SAL_CALL SvLockBytesInputStream::acquire() throw () 279 { 280 OWeakObject::acquire(); 281 } 282 283 //============================================================================ 284 // virtual 285 void SAL_CALL SvLockBytesInputStream::release() throw () 286 { 287 OWeakObject::release(); 288 } 289 290 //============================================================================ 291 // virtual 292 sal_Int32 SAL_CALL 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 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 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 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 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 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 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 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 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 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 570 sal_uLong SvInputStream::PutData(void const *, sal_uLong) 571 { 572 SetError(ERRCODE_IO_NOTSUPPORTED); 573 return 0; 574 } 575 576 //============================================================================ 577 // virtual 578 void SvInputStream::FlushData() 579 {} 580 581 //============================================================================ 582 // virtual 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 635 void SvInputStream::SetSize(sal_uLong) 636 { 637 SetError(ERRCODE_IO_NOTSUPPORTED); 638 } 639 640 //============================================================================ 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 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 667 sal_uInt16 SvInputStream::IsA() const 668 { 669 return 0; 670 } 671 672 //============================================================================ 673 // virtual 674 void SvInputStream::AddMark(sal_uLong nPos) 675 { 676 if (open() && m_pPipe) 677 m_pPipe->addMark(nPos); 678 } 679 680 //============================================================================ 681 // virtual 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 695 sal_uLong SvOutputStream::GetData(void *, sal_uLong) 696 { 697 SetError(ERRCODE_IO_NOTSUPPORTED); 698 return 0; 699 } 700 701 //============================================================================ 702 // virtual 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 738 sal_uLong SvOutputStream::SeekPos(sal_uLong) 739 { 740 SetError(ERRCODE_IO_NOTSUPPORTED); 741 return 0; 742 } 743 744 //============================================================================ 745 // virtual 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 762 void SvOutputStream::SetSize(sal_uLong) 763 { 764 SetError(ERRCODE_IO_NOTSUPPORTED); 765 } 766 767 //============================================================================ 768 SvOutputStream::SvOutputStream(uno::Reference< io::XOutputStream > const & 769 rTheStream): 770 m_xStream(rTheStream) 771 { 772 SetBufferSize(0); 773 } 774 775 //============================================================================ 776 // virtual 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 789 sal_uInt16 SvOutputStream::IsA() const 790 { 791 return 0; 792 } 793 794 //============================================================================ 795 // 796 // SvDataPipe_Impl 797 // 798 //============================================================================ 799 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 //============================================================================ 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 //============================================================================ 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 //============================================================================ 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 //============================================================================ 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 //============================================================================ 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 //============================================================================ 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