LCOV - code coverage report
Current view: top level - svl/source/misc - strmadpt.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 20 351 5.7 %
Date: 2015-06-13 12:38:46 Functions: 3 41 7.3 %
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 <com/sun/star/io/XInputStream.hpp>
      29             : #include <com/sun/star/io/XSeekable.hpp>
      30             : 
      31             : #include <osl/diagnose.h>
      32             : #include <rtl/alloc.h>
      33             : #include <cppuhelper/queryinterface.hxx>
      34             : #include <svl/instrm.hxx>
      35             : #include <svl/outstrm.hxx>
      36             : 
      37             : #include <strmadpt.hxx>
      38             : 
      39             : using namespace com::sun::star;
      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           0 :     void clearReadBuffer() { m_pReadBuffer = 0; }
      86             : 
      87             :     sal_uInt32 write(sal_Int8 const * pBuffer, sal_uInt32 nSize);
      88             : 
      89           0 :     void setEOF() { m_bEOF = true; }
      90             : 
      91             :     inline bool isEOF() const;
      92             : 
      93             :     SeekResult setReadPosition(sal_uInt32 nPosition);
      94             : };
      95             : 
      96           0 : SvDataPipe_Impl::SvDataPipe_Impl(sal_uInt32 nThePageSize,
      97             :                                  sal_uInt32 nTheMinPages,
      98             :                                  sal_uInt32 nTheMaxPages)
      99             :     : m_pFirstPage( 0 )
     100             :     , m_pReadPage( 0 )
     101             :     , m_pWritePage( 0 )
     102             :     , m_pReadBuffer( 0 )
     103             :     , m_nReadBufferSize( 0 )
     104             :     , m_nReadBufferFilled( 0 )
     105             :     , m_nPageSize(std::min< sal_uInt32 >(
     106           0 :                           std::max< sal_uInt32 >(nThePageSize, sal_uInt32(1)),
     107           0 :                           sal_uInt32(std::numeric_limits< sal_uInt32 >::max()
     108           0 :                                      - sizeof (Page) + 1)))
     109           0 :     , m_nMinPages(std::max< sal_uInt32 >(nTheMinPages, sal_uInt32(1)))
     110           0 :     , m_nMaxPages(std::max< sal_uInt32 >(nTheMaxPages, sal_uInt32(1)))
     111             :     , m_nPages( 0 )
     112           0 :     , m_bEOF( false )
     113           0 : {}
     114             : 
     115           0 : inline void SvDataPipe_Impl::setReadBuffer(sal_Int8 * pBuffer,
     116             :                                            sal_uInt32 nSize)
     117             : {
     118           0 :     m_pReadBuffer = pBuffer;
     119           0 :     m_nReadBufferSize = nSize;
     120           0 :     m_nReadBufferFilled = 0;
     121           0 : }
     122             : 
     123           0 : inline bool SvDataPipe_Impl::isEOF() const
     124             : {
     125           0 :     return m_bEOF && m_pReadPage == m_pWritePage
     126           0 :            && (!m_pReadPage || m_pReadPage->m_pRead == m_pReadPage->m_pEnd);
     127             : }
     128             : 
     129             : //  SvOutputStreamOpenLockBytes
     130             : 
     131             : 
     132           0 : TYPEINIT1(SvOutputStreamOpenLockBytes, SvOpenLockBytes)
     133             : 
     134             : // virtual
     135           0 : ErrCode SvOutputStreamOpenLockBytes::ReadAt(sal_uInt64, void *, sal_uLong, sal_uLong*)
     136             :     const
     137             : {
     138           0 :     return ERRCODE_IO_CANTREAD;
     139             : }
     140             : 
     141             : // virtual
     142           0 : ErrCode SvOutputStreamOpenLockBytes::WriteAt(sal_uInt64 const nPos, void const * pBuffer,
     143             :                                              sal_uLong nCount, sal_uLong * pWritten)
     144             : {
     145           0 :     if (nPos != m_nPosition)
     146           0 :         return ERRCODE_IO_CANTWRITE;
     147           0 :     return FillAppend(pBuffer, nCount, pWritten);
     148             : }
     149             : 
     150             : // virtual
     151           0 : ErrCode SvOutputStreamOpenLockBytes::Flush() const
     152             : {
     153           0 :     if (!m_xOutputStream.is())
     154           0 :         return ERRCODE_IO_CANTWRITE;
     155             :     try
     156             :     {
     157           0 :         m_xOutputStream->flush();
     158             :     }
     159           0 :     catch (const io::IOException&)
     160             :     {
     161           0 :         return ERRCODE_IO_CANTWRITE;
     162             :     }
     163           0 :     return ERRCODE_NONE;
     164             : }
     165             : 
     166             : // virtual
     167           0 : ErrCode SvOutputStreamOpenLockBytes::SetSize(sal_uInt64)
     168             : {
     169           0 :     return ERRCODE_IO_NOTSUPPORTED;
     170             : }
     171             : 
     172             : // virtual
     173           0 : ErrCode SvOutputStreamOpenLockBytes::Stat(SvLockBytesStat * pStat,
     174             :                                           SvLockBytesStatFlag) const
     175             : {
     176           0 :     if (pStat)
     177           0 :         pStat->nSize = m_nPosition;
     178           0 :     return ERRCODE_NONE;
     179             : }
     180             : 
     181             : // virtual
     182           0 : ErrCode SvOutputStreamOpenLockBytes::FillAppend(void const * pBuffer,
     183             :                                                 sal_uLong nCount,
     184             :                                                 sal_uLong * pWritten)
     185             : {
     186           0 :     if (!m_xOutputStream.is())
     187           0 :         return ERRCODE_IO_CANTWRITE;
     188           0 :     if (nCount > 0
     189           0 :         && nCount > std::numeric_limits< sal_uLong >::max() - m_nPosition)
     190             :     {
     191           0 :         nCount = std::numeric_limits< sal_uLong >::max() - m_nPosition;
     192           0 :         if (nCount == 0)
     193           0 :             return ERRCODE_IO_CANTWRITE;
     194             :     }
     195             :     try
     196             :     {
     197           0 :         m_xOutputStream->
     198             :             writeBytes(uno::Sequence< sal_Int8 >(
     199           0 :                            static_cast< sal_Int8 const * >(pBuffer), nCount));
     200             :     }
     201           0 :     catch (const io::IOException&)
     202             :     {
     203           0 :         return ERRCODE_IO_CANTWRITE;
     204             :     }
     205           0 :     m_nPosition += nCount;
     206           0 :     if (pWritten)
     207           0 :         *pWritten = nCount;
     208           0 :     return ERRCODE_NONE;
     209             : }
     210             : 
     211             : // virtual
     212           0 : sal_uInt64 SvOutputStreamOpenLockBytes::Tell() const
     213             : {
     214           0 :     return m_nPosition;
     215             : }
     216             : 
     217             : // virtual
     218           0 : sal_uInt64 SvOutputStreamOpenLockBytes::Seek(sal_uInt64)
     219             : {
     220           0 :     return m_nPosition;
     221             : }
     222             : 
     223             : // virtual
     224           0 : void SvOutputStreamOpenLockBytes::Terminate()
     225             : {
     226           0 :     if (m_xOutputStream.is())
     227             :     {
     228             :         try
     229             :         {
     230           0 :             m_xOutputStream->closeOutput();
     231             :         }
     232           0 :         catch (const io::IOException&)
     233             :         {
     234             :         }
     235             :     }
     236           0 : }
     237             : 
     238             : 
     239             : //  SvInputStream
     240             : 
     241             : 
     242           0 : bool SvInputStream::open()
     243             : {
     244           0 :     if (GetError() != ERRCODE_NONE)
     245           0 :         return false;
     246           0 :     if (!(m_xSeekable.is() || m_pPipe))
     247             :     {
     248           0 :         if (!m_xStream.is())
     249             :         {
     250           0 :             SetError(ERRCODE_IO_INVALIDDEVICE);
     251           0 :             return false;
     252             :         }
     253             :         m_xSeekable
     254           0 :             = uno::Reference< io::XSeekable >(m_xStream, uno::UNO_QUERY);
     255           0 :         if (!m_xSeekable.is())
     256           0 :             m_pPipe = new SvDataPipe_Impl;
     257             :     }
     258           0 :     return true;
     259             : }
     260             : 
     261             : // virtual
     262           0 : sal_uLong SvInputStream::GetData(void * pData, sal_uLong nSize)
     263             : {
     264           0 :     if (!open())
     265             :     {
     266           0 :         SetError(ERRCODE_IO_CANTREAD);
     267           0 :         return 0;
     268             :     }
     269             :     // check if a truncated STREAM_SEEK_TO_END was passed
     270             :     assert(m_nSeekedFrom != SAL_MAX_UINT32);
     271           0 :     sal_uInt32 nRead = 0;
     272           0 :     if (m_xSeekable.is())
     273             :     {
     274           0 :         if (m_nSeekedFrom != STREAM_SEEK_TO_END)
     275             :         {
     276             :             try
     277             :             {
     278           0 :                 m_xSeekable->seek(m_nSeekedFrom);
     279             :             }
     280           0 :             catch (const io::IOException&)
     281             :             {
     282           0 :                 SetError(ERRCODE_IO_CANTREAD);
     283           0 :                 return 0;
     284             :             }
     285           0 :             m_nSeekedFrom = STREAM_SEEK_TO_END;
     286             :         }
     287             :         for (;;)
     288             :         {
     289             :             sal_Int32 nRemain
     290             :                 = sal_Int32(
     291           0 :                     std::min(sal_uLong(nSize - nRead),
     292           0 :                              sal_uLong(std::numeric_limits< sal_Int32 >::max())));
     293           0 :             if (nRemain == 0)
     294           0 :                 break;
     295           0 :             uno::Sequence< sal_Int8 > aBuffer;
     296             :             sal_Int32 nCount;
     297             :             try
     298             :             {
     299           0 :                 nCount = m_xStream->readBytes(aBuffer, nRemain);
     300             :             }
     301           0 :             catch (const io::IOException&)
     302             :             {
     303           0 :                 SetError(ERRCODE_IO_CANTREAD);
     304           0 :                 return nRead;
     305             :             }
     306           0 :             memcpy(static_cast< sal_Int8 * >(pData) + nRead,
     307           0 :                            aBuffer.getConstArray(), sal_uInt32(nCount));
     308           0 :             nRead += nCount;
     309           0 :             if (nCount < nRemain)
     310           0 :                 break;
     311           0 :         }
     312             :     }
     313             :     else
     314             :     {
     315           0 :         if (m_nSeekedFrom != STREAM_SEEK_TO_END)
     316             :         {
     317           0 :             SetError(ERRCODE_IO_CANTREAD);
     318           0 :             return 0;
     319             :         }
     320           0 :         m_pPipe->setReadBuffer(static_cast< sal_Int8 * >(pData), nSize);
     321           0 :         nRead = m_pPipe->read();
     322           0 :         if (nRead < nSize && !m_pPipe->isEOF())
     323             :             for (;;)
     324             :             {
     325             :                 sal_Int32 nRemain
     326             :                     = sal_Int32(
     327             :                         std::min(
     328           0 :                             sal_uLong(nSize - nRead),
     329           0 :                             sal_uLong(std::numeric_limits< sal_Int32 >::max())));
     330           0 :                 if (nRemain == 0)
     331           0 :                     break;
     332           0 :                 uno::Sequence< sal_Int8 > aBuffer;
     333             :                 sal_Int32 nCount;
     334             :                 try
     335             :                 {
     336           0 :                     nCount = m_xStream->readBytes(aBuffer, nRemain);
     337             :                 }
     338           0 :                 catch (const io::IOException&)
     339             :                 {
     340           0 :                     SetError(ERRCODE_IO_CANTREAD);
     341           0 :                     break;
     342             :                 }
     343           0 :                 m_pPipe->write(aBuffer.getConstArray(), sal_uInt32(nCount));
     344           0 :                 nRead += m_pPipe->read();
     345           0 :                 if (nCount < nRemain)
     346             :                 {
     347           0 :                     m_xStream->closeInput();
     348           0 :                     m_pPipe->setEOF();
     349           0 :                     break;
     350             :                 }
     351           0 :             }
     352           0 :         m_pPipe->clearReadBuffer();
     353             :     }
     354           0 :     return nRead;
     355             : }
     356             : 
     357             : // virtual
     358           0 : sal_uLong SvInputStream::PutData(void const *, sal_uLong)
     359             : {
     360           0 :     SetError(ERRCODE_IO_NOTSUPPORTED);
     361           0 :     return 0;
     362             : }
     363             : 
     364             : // virtual
     365           0 : void SvInputStream::FlushData()
     366           0 : {}
     367             : 
     368             : // virtual
     369           0 : sal_uInt64 SvInputStream::SeekPos(sal_uInt64 const nPos)
     370             : {
     371             :     // check if a truncated STREAM_SEEK_TO_END was passed
     372             :     assert(nPos != SAL_MAX_UINT32);
     373           0 :     if (open())
     374             :     {
     375           0 :         if (nPos == STREAM_SEEK_TO_END)
     376             :         {
     377           0 :             if (m_nSeekedFrom == STREAM_SEEK_TO_END)
     378             :             {
     379           0 :                 if (m_xSeekable.is())
     380             :                     try
     381             :                     {
     382           0 :                         sal_Int64 nLength = m_xSeekable->getLength();
     383             :                         OSL_ASSERT(nLength >= 0);
     384           0 :                         if (static_cast<sal_uInt64>(nLength)
     385             :                             < STREAM_SEEK_TO_END)
     386             :                         {
     387           0 :                             m_nSeekedFrom = Tell();
     388           0 :                             return sal_uLong(nLength);
     389             :                         }
     390             :                     }
     391           0 :                     catch (const io::IOException&)
     392             :                     {
     393             :                     }
     394             :                 else
     395           0 :                     return Tell(); //@@@
     396             :             }
     397             :             else
     398           0 :                 return Tell();
     399             :         }
     400           0 :         else if (nPos == m_nSeekedFrom)
     401             :         {
     402           0 :             m_nSeekedFrom = STREAM_SEEK_TO_END;
     403           0 :             return nPos;
     404             :         }
     405           0 :         else if (m_xSeekable.is())
     406             :         {
     407             :             try
     408             :             {
     409           0 :                 m_xSeekable->seek(nPos);
     410           0 :                 m_nSeekedFrom = STREAM_SEEK_TO_END;
     411           0 :                 return nPos;
     412             :             }
     413           0 :             catch (const io::IOException&)
     414             :             {
     415             :             }
     416             :         }
     417           0 :         else if (m_pPipe->setReadPosition(nPos) == SvDataPipe_Impl::SEEK_OK)
     418             :         {
     419           0 :             m_nSeekedFrom = STREAM_SEEK_TO_END;
     420           0 :             return nPos;
     421             :         }
     422           0 :         else if ( nPos > Tell() )
     423             :         {
     424             :             // Read out the bytes
     425           0 :             sal_Int32 nRead = nPos - Tell();
     426           0 :             uno::Sequence< sal_Int8 > aBuffer;
     427           0 :             m_xStream->readBytes( aBuffer, nRead );
     428           0 :             return nPos;
     429             :         }
     430           0 :         else if ( nPos == Tell() )
     431           0 :             return nPos;
     432             :     }
     433           0 :     SetError(ERRCODE_IO_CANTSEEK);
     434           0 :     return Tell();
     435             : }
     436             : 
     437             : // virtual
     438           0 : void SvInputStream::SetSize(sal_uInt64)
     439             : {
     440           0 :     SetError(ERRCODE_IO_NOTSUPPORTED);
     441           0 : }
     442             : 
     443           0 : SvInputStream::SvInputStream(
     444             :         com::sun::star::uno::Reference< com::sun::star::io::XInputStream >
     445             :                 const &
     446             :             rTheStream):
     447             :     m_xStream(rTheStream),
     448             :     m_pPipe(0),
     449           0 :     m_nSeekedFrom(STREAM_SEEK_TO_END)
     450             : {
     451           0 :     SetBufferSize(0);
     452           0 : }
     453             : 
     454             : // virtual
     455           0 : SvInputStream::~SvInputStream()
     456             : {
     457           0 :     if (m_xStream.is())
     458             :     {
     459             :         try
     460             :         {
     461           0 :             m_xStream->closeInput();
     462             :         }
     463           0 :         catch (const io::IOException&)
     464             :         {
     465             :         }
     466             :     }
     467           0 :     delete m_pPipe;
     468           0 : }
     469             : 
     470             : //  SvOutputStream
     471             : 
     472             : // virtual
     473           0 : sal_uLong SvOutputStream::GetData(void *, sal_uLong)
     474             : {
     475           0 :     SetError(ERRCODE_IO_NOTSUPPORTED);
     476           0 :     return 0;
     477             : }
     478             : 
     479             : // virtual
     480        1417 : sal_uLong SvOutputStream::PutData(void const * pData, sal_uLong nSize)
     481             : {
     482        1417 :     if (!m_xStream.is())
     483             :     {
     484           0 :         SetError(ERRCODE_IO_CANTWRITE);
     485           0 :         return 0;
     486             :     }
     487        1417 :     sal_uLong nWritten = 0;
     488             :     for (;;)
     489             :     {
     490             :         sal_Int32 nRemain
     491             :             = sal_Int32(
     492        2834 :                 std::min(sal_uLong(nSize - nWritten),
     493        5668 :                          sal_uLong(std::numeric_limits< sal_Int32 >::max())));
     494        2834 :         if (nRemain == 0)
     495        1417 :             break;
     496             :         try
     497             :         {
     498        1417 :             m_xStream->writeBytes(uno::Sequence< sal_Int8 >(
     499             :                                       static_cast<const sal_Int8 * >(pData)
     500             :                                           + nWritten,
     501        1417 :                                       nRemain));
     502             :         }
     503           0 :         catch (const io::IOException&)
     504             :         {
     505           0 :             SetError(ERRCODE_IO_CANTWRITE);
     506           0 :             break;
     507             :         }
     508        1417 :         nWritten += nRemain;
     509        1417 :     }
     510        1417 :     return nWritten;
     511             : }
     512             : 
     513             : // virtual
     514           0 : sal_uInt64 SvOutputStream::SeekPos(sal_uInt64)
     515             : {
     516           0 :     SetError(ERRCODE_IO_NOTSUPPORTED);
     517           0 :     return 0;
     518             : }
     519             : 
     520             : // virtual
     521           0 : void SvOutputStream::FlushData()
     522             : {
     523           0 :     if (!m_xStream.is())
     524             :     {
     525           0 :         SetError(ERRCODE_IO_INVALIDDEVICE);
     526           0 :         return;
     527             :     }
     528             :     try
     529             :     {
     530           0 :         m_xStream->flush();
     531             :     }
     532           0 :     catch (const io::IOException&)
     533             :     {
     534             :     }
     535             : }
     536             : 
     537             : // virtual
     538           0 : void SvOutputStream::SetSize(sal_uInt64)
     539             : {
     540           0 :     SetError(ERRCODE_IO_NOTSUPPORTED);
     541           0 : }
     542             : 
     543          35 : SvOutputStream::SvOutputStream(uno::Reference< io::XOutputStream > const &
     544             :                                    rTheStream):
     545          35 :     m_xStream(rTheStream)
     546             : {
     547          35 :     SetBufferSize(0);
     548          35 : }
     549             : 
     550             : // virtual
     551          70 : SvOutputStream::~SvOutputStream()
     552             : {
     553          35 :     if (m_xStream.is())
     554             :     {
     555             :         try
     556             :         {
     557          35 :             m_xStream->closeOutput();
     558             :         }
     559           0 :         catch (const io::IOException&)
     560             :         {
     561             :         }
     562             :     }
     563          35 : }
     564             : 
     565             : 
     566             : //  SvDataPipe_Impl
     567             : 
     568             : 
     569           0 : bool SvDataPipe_Impl::remove(Page * pPage)
     570             : {
     571           0 :     if (
     572           0 :         pPage != m_pFirstPage ||
     573           0 :         m_pReadPage == m_pFirstPage ||
     574             :         (
     575           0 :          !m_aMarks.empty() &&
     576           0 :          *m_aMarks.begin() < m_pFirstPage->m_nOffset + m_nPageSize
     577             :         )
     578             :        )
     579             :     {
     580           0 :         return false;
     581             :     }
     582             : 
     583           0 :     m_pFirstPage = m_pFirstPage->m_pNext;
     584             : 
     585           0 :     if (m_nPages <= m_nMinPages)
     586           0 :         return true;
     587             : 
     588           0 :     pPage->m_pPrev->m_pNext = pPage->m_pNext;
     589           0 :     pPage->m_pNext->m_pPrev = pPage->m_pPrev;
     590           0 :     rtl_freeMemory(pPage);
     591           0 :     --m_nPages;
     592             : 
     593           0 :     return true;
     594             : }
     595             : 
     596           0 : SvDataPipe_Impl::~SvDataPipe_Impl()
     597             : {
     598           0 :     if (m_pFirstPage != 0)
     599           0 :         for (Page * pPage = m_pFirstPage;;)
     600             :         {
     601           0 :             Page * pNext = pPage->m_pNext;
     602           0 :             rtl_freeMemory(pPage);
     603           0 :             if (pNext == m_pFirstPage)
     604           0 :                 break;
     605           0 :             pPage = pNext;
     606           0 :         }
     607           0 : }
     608             : 
     609           0 : sal_uInt32 SvDataPipe_Impl::read()
     610             : {
     611           0 :     if (m_pReadBuffer == 0 || m_nReadBufferSize == 0 || m_pReadPage == 0)
     612           0 :         return 0;
     613             : 
     614           0 :     sal_uInt32 nSize = m_nReadBufferSize;
     615           0 :     sal_uInt32 nRemain = m_nReadBufferSize - m_nReadBufferFilled;
     616             : 
     617           0 :     m_pReadBuffer += m_nReadBufferFilled;
     618           0 :     m_nReadBufferSize -= m_nReadBufferFilled;
     619           0 :     m_nReadBufferFilled = 0;
     620             : 
     621           0 :     while (nRemain > 0)
     622             :     {
     623             :         sal_uInt32 nBlock = std::min(sal_uInt32(m_pReadPage->m_pEnd
     624           0 :                                                     - m_pReadPage->m_pRead),
     625           0 :                                      nRemain);
     626           0 :         memcpy(m_pReadBuffer, m_pReadPage->m_pRead, nBlock);
     627           0 :         m_pReadPage->m_pRead += nBlock;
     628           0 :         m_pReadBuffer += nBlock;
     629           0 :         m_nReadBufferSize -= nBlock;
     630           0 :         m_nReadBufferFilled = 0;
     631           0 :         nRemain -= nBlock;
     632             : 
     633           0 :         if (m_pReadPage == m_pWritePage)
     634           0 :             break;
     635             : 
     636           0 :         if (m_pReadPage->m_pRead == m_pReadPage->m_pEnd)
     637             :         {
     638           0 :             Page * pRemove = m_pReadPage;
     639           0 :             m_pReadPage = pRemove->m_pNext;
     640           0 :             remove(pRemove);
     641             :         }
     642             :     }
     643             : 
     644           0 :     return nSize - nRemain;
     645             : }
     646             : 
     647           0 : sal_uInt32 SvDataPipe_Impl::write(sal_Int8 const * pBuffer, sal_uInt32 nSize)
     648             : {
     649           0 :     if (nSize == 0)
     650           0 :         return 0;
     651             : 
     652           0 :     if (m_pWritePage == 0)
     653             :     {
     654             :         m_pFirstPage
     655             :             = static_cast< Page * >(rtl_allocateMemory(sizeof (Page)
     656           0 :                                                            + m_nPageSize
     657           0 :                                                            - 1));
     658           0 :         m_pFirstPage->m_pPrev = m_pFirstPage;
     659           0 :         m_pFirstPage->m_pNext = m_pFirstPage;
     660           0 :         m_pFirstPage->m_pStart = m_pFirstPage->m_aBuffer;
     661           0 :         m_pFirstPage->m_pRead = m_pFirstPage->m_aBuffer;
     662           0 :         m_pFirstPage->m_pEnd = m_pFirstPage->m_aBuffer;
     663           0 :         m_pFirstPage->m_nOffset = 0;
     664           0 :         m_pReadPage = m_pFirstPage;
     665           0 :         m_pWritePage = m_pFirstPage;
     666           0 :         ++m_nPages;
     667             :     }
     668             : 
     669           0 :     sal_uInt32 nRemain = nSize;
     670             : 
     671           0 :     if (m_pReadBuffer != 0 && m_pReadPage == m_pWritePage
     672           0 :         && m_pReadPage->m_pRead == m_pWritePage->m_pEnd)
     673             :     {
     674             :         sal_uInt32 nBlock = std::min(nRemain,
     675             :                                      sal_uInt32(m_nReadBufferSize
     676           0 :                                                     - m_nReadBufferFilled));
     677             :         sal_uInt32 nPosition = m_pWritePage->m_nOffset
     678             :                                    + (m_pWritePage->m_pEnd
     679           0 :                                           - m_pWritePage->m_aBuffer);
     680           0 :         if (!m_aMarks.empty())
     681           0 :             nBlock = *m_aMarks.begin() > nPosition ?
     682           0 :                          std::min(nBlock, sal_uInt32(*m_aMarks.begin()
     683           0 :                                                          - nPosition)) :
     684           0 :                          0;
     685             : 
     686           0 :         if (nBlock > 0)
     687             :         {
     688           0 :             memcpy(m_pReadBuffer + m_nReadBufferFilled, pBuffer,
     689           0 :                            nBlock);
     690           0 :             m_nReadBufferFilled += nBlock;
     691           0 :             nRemain -= nBlock;
     692             : 
     693           0 :             nPosition += nBlock;
     694           0 :             m_pWritePage->m_nOffset = (nPosition / m_nPageSize) * m_nPageSize;
     695             :             m_pWritePage->m_pStart = m_pWritePage->m_aBuffer
     696           0 :                                          + nPosition % m_nPageSize;
     697           0 :             m_pWritePage->m_pRead = m_pWritePage->m_pStart;
     698           0 :             m_pWritePage->m_pEnd = m_pWritePage->m_pStart;
     699             :         }
     700             :     }
     701             : 
     702           0 :     if (nRemain > 0)
     703             :         for (;;)
     704             :         {
     705             :             sal_uInt32 nBlock
     706           0 :                 = std::min(sal_uInt32(m_pWritePage->m_aBuffer + m_nPageSize
     707           0 :                                           - m_pWritePage->m_pEnd),
     708           0 :                            nRemain);
     709           0 :             memcpy(m_pWritePage->m_pEnd, pBuffer, nBlock);
     710           0 :             m_pWritePage->m_pEnd += nBlock;
     711           0 :             pBuffer += nBlock;
     712           0 :             nRemain -= nBlock;
     713             : 
     714           0 :             if (nRemain == 0)
     715           0 :                 break;
     716             : 
     717           0 :             if (m_pWritePage->m_pNext == m_pFirstPage)
     718             :             {
     719           0 :                 if (m_nPages == m_nMaxPages)
     720           0 :                     break;
     721             : 
     722             :                 Page * pNew
     723             :                     = static_cast< Page * >(rtl_allocateMemory(
     724           0 :                                                 sizeof (Page) + m_nPageSize
     725           0 :                                                     - 1));
     726           0 :                 pNew->m_pPrev = m_pWritePage;
     727           0 :                 pNew->m_pNext = m_pWritePage->m_pNext;
     728             : 
     729           0 :                 m_pWritePage->m_pNext->m_pPrev = pNew;
     730           0 :                 m_pWritePage->m_pNext = pNew;
     731           0 :                 ++m_nPages;
     732             :             }
     733             : 
     734             :             m_pWritePage->m_pNext->m_nOffset = m_pWritePage->m_nOffset
     735           0 :                                                    + m_nPageSize;
     736           0 :             m_pWritePage = m_pWritePage->m_pNext;
     737           0 :             m_pWritePage->m_pStart = m_pWritePage->m_aBuffer;
     738           0 :             m_pWritePage->m_pRead = m_pWritePage->m_aBuffer;
     739           0 :             m_pWritePage->m_pEnd = m_pWritePage->m_aBuffer;
     740           0 :         }
     741             : 
     742           0 :     return nSize - nRemain;
     743             : }
     744             : 
     745           0 : SvDataPipe_Impl::SeekResult SvDataPipe_Impl::setReadPosition(sal_uInt32
     746             :                                                                  nPosition)
     747             : {
     748           0 :     if (m_pFirstPage == 0)
     749           0 :         return nPosition == 0 ? SEEK_OK : SEEK_PAST_END;
     750             : 
     751           0 :     if (nPosition
     752           0 :             <= m_pReadPage->m_nOffset
     753           0 :                    + (m_pReadPage->m_pRead - m_pReadPage->m_aBuffer))
     754             :     {
     755           0 :         if (nPosition
     756           0 :                 < m_pFirstPage->m_nOffset
     757           0 :                       + (m_pFirstPage->m_pStart - m_pFirstPage->m_aBuffer))
     758           0 :             return SEEK_BEFORE_MARKED;
     759             : 
     760           0 :         while (nPosition < m_pReadPage->m_nOffset)
     761             :         {
     762           0 :             m_pReadPage->m_pRead = m_pReadPage->m_pStart;
     763           0 :             m_pReadPage = m_pReadPage->m_pPrev;
     764             :         }
     765             :     }
     766             :     else
     767             :     {
     768           0 :         if (nPosition
     769           0 :                 > m_pWritePage->m_nOffset
     770           0 :                       + (m_pWritePage->m_pEnd - m_pWritePage->m_aBuffer))
     771           0 :             return SEEK_PAST_END;
     772             : 
     773           0 :         while (m_pReadPage != m_pWritePage
     774           0 :                && nPosition >= m_pReadPage->m_nOffset + m_nPageSize)
     775             :         {
     776           0 :             Page * pRemove = m_pReadPage;
     777           0 :             m_pReadPage = pRemove->m_pNext;
     778           0 :             remove(pRemove);
     779             :         }
     780             :     }
     781             : 
     782             :     m_pReadPage->m_pRead = m_pReadPage->m_aBuffer
     783           0 :                                + (nPosition - m_pReadPage->m_nOffset);
     784           0 :     return SEEK_OK;
     785             : }
     786             : 
     787             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11