LCOV - code coverage report
Current view: top level - svl/source/misc - strmadpt.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 20 458 4.4 %
Date: 2014-11-03 Functions: 3 56 5.4 %
Legend: Lines: hit not hit

          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             :          nBytesToRead < 0 ||
     274             :          (
     275             :           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             :     if (static_cast<sal_uInt64>(m_nPosition) > SAL_MAX_SIZE
     311             :         && nMaxBytesToRead > 0)
     312             :         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           0 :     if (aStat.nSize > static_cast<sal_uInt64>(SAL_MAX_INT64))
     406           0 :         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        2138 : sal_uLong SvOutputStream::PutData(void const * pData, sal_uLong nSize)
     670             : {
     671        2138 :     if (!m_xStream.is())
     672             :     {
     673           0 :         SetError(ERRCODE_IO_CANTWRITE);
     674           0 :         return 0;
     675             :     }
     676        2138 :     sal_uLong nWritten = 0;
     677             :     for (;;)
     678             :     {
     679             :         sal_Int32 nRemain
     680             :             = sal_Int32(
     681        4276 :                 std::min(sal_uLong(nSize - nWritten),
     682        8552 :                          sal_uLong(std::numeric_limits< sal_Int32 >::max())));
     683        4276 :         if (nRemain == 0)
     684        2138 :             break;
     685             :         try
     686             :         {
     687        2138 :             m_xStream->writeBytes(uno::Sequence< sal_Int8 >(
     688             :                                       static_cast<const sal_Int8 * >(pData)
     689             :                                           + nWritten,
     690        2138 :                                       nRemain));
     691             :         }
     692           0 :         catch (const io::IOException&)
     693             :         {
     694           0 :             SetError(ERRCODE_IO_CANTWRITE);
     695           0 :             break;
     696             :         }
     697        2138 :         nWritten += nRemain;
     698        2138 :     }
     699        2138 :     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          54 : SvOutputStream::SvOutputStream(uno::Reference< io::XOutputStream > const &
     733             :                                    rTheStream):
     734          54 :     m_xStream(rTheStream)
     735             : {
     736          54 :     SetBufferSize(0);
     737          54 : }
     738             : 
     739             : // virtual
     740         108 : SvOutputStream::~SvOutputStream()
     741             : {
     742          54 :     if (m_xStream.is())
     743             :     {
     744             :         try
     745             :         {
     746          54 :             m_xStream->closeOutput();
     747             :         }
     748           0 :         catch (const io::IOException&)
     749             :         {
     750             :         }
     751             :     }
     752          54 : }
     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           0 :                                                            + 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             :                                    + (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           0 :                                                 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           0 :             <= m_pReadPage->m_nOffset
     960           0 :                    + (m_pReadPage->m_pRead - m_pReadPage->m_aBuffer))
     961             :     {
     962           0 :         if (nPosition
     963           0 :                 < 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           0 :                 > 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: */

Generated by: LCOV version 1.10