Home | History | Annotate | Download | only in Common
      1 // MultiStream.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include "MultiStream.h"
      6 
      7 STDMETHODIMP CMultiStream::Read(void *data, UInt32 size, UInt32 *processedSize)
      8 {
      9   if (processedSize)
     10     *processedSize = 0;
     11   if (size == 0)
     12     return S_OK;
     13   if (_pos >= _totalLength)
     14     return (_pos == _totalLength) ? S_OK : E_FAIL;
     15 
     16   {
     17     int left = 0, mid = _streamIndex, right = Streams.Size();
     18     for (;;)
     19     {
     20       CSubStreamInfo &m = Streams[mid];
     21       if (_pos < m.GlobalOffset)
     22         right = mid;
     23       else if (_pos >= m.GlobalOffset + m.Size)
     24         left = mid + 1;
     25       else
     26       {
     27         _streamIndex = mid;
     28         break;
     29       }
     30       mid = (left + right) / 2;
     31     }
     32     _streamIndex = mid;
     33   }
     34 
     35   CSubStreamInfo &s = Streams[_streamIndex];
     36   UInt64 localPos = _pos - s.GlobalOffset;
     37   if (localPos != s.LocalPos)
     38   {
     39     RINOK(s.Stream->Seek(localPos, STREAM_SEEK_SET, &s.LocalPos));
     40   }
     41   UInt64 rem = s.Size - localPos;
     42   if (size > rem)
     43     size = (UInt32)rem;
     44   HRESULT result = s.Stream->Read(data, size, &size);
     45   _pos += size;
     46   s.LocalPos += size;
     47   if (processedSize)
     48     *processedSize = size;
     49   return result;
     50 }
     51 
     52 STDMETHODIMP CMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
     53 {
     54   switch(seekOrigin)
     55   {
     56     case STREAM_SEEK_SET: _pos = offset; break;
     57     case STREAM_SEEK_CUR: _pos = _pos + offset; break;
     58     case STREAM_SEEK_END: _pos = _totalLength + offset; break;
     59     default: return STG_E_INVALIDFUNCTION;
     60   }
     61   if (newPosition != 0)
     62     *newPosition = _pos;
     63   return S_OK;
     64 }
     65 
     66 
     67 /*
     68 class COutVolumeStream:
     69   public ISequentialOutStream,
     70   public CMyUnknownImp
     71 {
     72   int _volIndex;
     73   UInt64 _volSize;
     74   UInt64 _curPos;
     75   CMyComPtr<ISequentialOutStream> _volumeStream;
     76   COutArchive _archive;
     77   CCRC _crc;
     78 
     79 public:
     80   MY_UNKNOWN_IMP
     81 
     82   CFileItem _file;
     83   CUpdateOptions _options;
     84   CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
     85   void Init(IArchiveUpdateCallback2 *volumeCallback,
     86       const UString &name)
     87   {
     88     _file.Name = name;
     89     _file.IsStartPosDefined = true;
     90     _file.StartPos = 0;
     91 
     92     VolumeCallback = volumeCallback;
     93     _volIndex = 0;
     94     _volSize = 0;
     95   }
     96 
     97   HRESULT Flush();
     98   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
     99 };
    100 
    101 HRESULT COutVolumeStream::Flush()
    102 {
    103   if (_volumeStream)
    104   {
    105     _file.UnPackSize = _curPos;
    106     _file.FileCRC = _crc.GetDigest();
    107     RINOK(WriteVolumeHeader(_archive, _file, _options));
    108     _archive.Close();
    109     _volumeStream.Release();
    110     _file.StartPos += _file.UnPackSize;
    111   }
    112   return S_OK;
    113 }
    114 */
    115 
    116 /*
    117 STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
    118 {
    119   if(processedSize != NULL)
    120     *processedSize = 0;
    121   while(size > 0)
    122   {
    123     if (_streamIndex >= Streams.Size())
    124     {
    125       CSubStreamInfo subStream;
    126       RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size));
    127       RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream));
    128       subStream.Pos = 0;
    129       Streams.Add(subStream);
    130       continue;
    131     }
    132     CSubStreamInfo &subStream = Streams[_streamIndex];
    133     if (_offsetPos >= subStream.Size)
    134     {
    135       _offsetPos -= subStream.Size;
    136       _streamIndex++;
    137       continue;
    138     }
    139     if (_offsetPos != subStream.Pos)
    140     {
    141       CMyComPtr<IOutStream> outStream;
    142       RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));
    143       RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
    144       subStream.Pos = _offsetPos;
    145     }
    146 
    147     UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos);
    148     UInt32 realProcessed;
    149     RINOK(subStream.Stream->Write(data, curSize, &realProcessed));
    150     data = (void *)((Byte *)data + realProcessed);
    151     size -= realProcessed;
    152     subStream.Pos += realProcessed;
    153     _offsetPos += realProcessed;
    154     _absPos += realProcessed;
    155     if (_absPos > _length)
    156       _length = _absPos;
    157     if(processedSize != NULL)
    158       *processedSize += realProcessed;
    159     if (subStream.Pos == subStream.Size)
    160     {
    161       _streamIndex++;
    162       _offsetPos = 0;
    163     }
    164     if (realProcessed != curSize && realProcessed == 0)
    165       return E_FAIL;
    166   }
    167   return S_OK;
    168 }
    169 
    170 STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
    171 {
    172   if(seekOrigin >= 3)
    173     return STG_E_INVALIDFUNCTION;
    174   switch(seekOrigin)
    175   {
    176     case STREAM_SEEK_SET:
    177       _absPos = offset;
    178       break;
    179     case STREAM_SEEK_CUR:
    180       _absPos += offset;
    181       break;
    182     case STREAM_SEEK_END:
    183       _absPos = _length + offset;
    184       break;
    185   }
    186   _offsetPos = _absPos;
    187   _streamIndex = 0;
    188   return S_OK;
    189 }
    190 */
    191