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 S_OK;
     15 
     16   {
     17     unsigned 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: break;
     57     case STREAM_SEEK_CUR: offset += _pos; break;
     58     case STREAM_SEEK_END: offset += _totalLength; break;
     59     default: return STG_E_INVALIDFUNCTION;
     60   }
     61   if (offset < 0)
     62     return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
     63   _pos = offset;
     64   if (newPosition)
     65     *newPosition = offset;
     66   return S_OK;
     67 }
     68 
     69 
     70 /*
     71 class COutVolumeStream:
     72   public ISequentialOutStream,
     73   public CMyUnknownImp
     74 {
     75   unsigned _volIndex;
     76   UInt64 _volSize;
     77   UInt64 _curPos;
     78   CMyComPtr<ISequentialOutStream> _volumeStream;
     79   COutArchive _archive;
     80   CCRC _crc;
     81 
     82 public:
     83   MY_UNKNOWN_IMP
     84 
     85   CFileItem _file;
     86   CUpdateOptions _options;
     87   CMyComPtr<IArchiveUpdateCallback2> VolumeCallback;
     88   void Init(IArchiveUpdateCallback2 *volumeCallback,
     89       const UString &name)
     90   {
     91     _file.Name = name;
     92     _file.IsStartPosDefined = true;
     93     _file.StartPos = 0;
     94 
     95     VolumeCallback = volumeCallback;
     96     _volIndex = 0;
     97     _volSize = 0;
     98   }
     99 
    100   HRESULT Flush();
    101   STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize);
    102 };
    103 
    104 HRESULT COutVolumeStream::Flush()
    105 {
    106   if (_volumeStream)
    107   {
    108     _file.UnPackSize = _curPos;
    109     _file.FileCRC = _crc.GetDigest();
    110     RINOK(WriteVolumeHeader(_archive, _file, _options));
    111     _archive.Close();
    112     _volumeStream.Release();
    113     _file.StartPos += _file.UnPackSize;
    114   }
    115   return S_OK;
    116 }
    117 */
    118 
    119 /*
    120 STDMETHODIMP COutMultiStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
    121 {
    122   if (processedSize)
    123     *processedSize = 0;
    124   while (size > 0)
    125   {
    126     if (_streamIndex >= Streams.Size())
    127     {
    128       CSubStreamInfo subStream;
    129       RINOK(VolumeCallback->GetVolumeSize(Streams.Size(), &subStream.Size));
    130       RINOK(VolumeCallback->GetVolumeStream(Streams.Size(), &subStream.Stream));
    131       subStream.Pos = 0;
    132       Streams.Add(subStream);
    133       continue;
    134     }
    135     CSubStreamInfo &subStream = Streams[_streamIndex];
    136     if (_offsetPos >= subStream.Size)
    137     {
    138       _offsetPos -= subStream.Size;
    139       _streamIndex++;
    140       continue;
    141     }
    142     if (_offsetPos != subStream.Pos)
    143     {
    144       CMyComPtr<IOutStream> outStream;
    145       RINOK(subStream.Stream.QueryInterface(IID_IOutStream, &outStream));
    146       RINOK(outStream->Seek(_offsetPos, STREAM_SEEK_SET, NULL));
    147       subStream.Pos = _offsetPos;
    148     }
    149 
    150     UInt32 curSize = (UInt32)MyMin((UInt64)size, subStream.Size - subStream.Pos);
    151     UInt32 realProcessed;
    152     RINOK(subStream.Stream->Write(data, curSize, &realProcessed));
    153     data = (void *)((Byte *)data + realProcessed);
    154     size -= realProcessed;
    155     subStream.Pos += realProcessed;
    156     _offsetPos += realProcessed;
    157     _absPos += realProcessed;
    158     if (_absPos > _length)
    159       _length = _absPos;
    160     if (processedSize)
    161       *processedSize += realProcessed;
    162     if (subStream.Pos == subStream.Size)
    163     {
    164       _streamIndex++;
    165       _offsetPos = 0;
    166     }
    167     if (realProcessed != curSize && realProcessed == 0)
    168       return E_FAIL;
    169   }
    170   return S_OK;
    171 }
    172 
    173 STDMETHODIMP COutMultiStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
    174 {
    175   switch (seekOrigin)
    176   {
    177     case STREAM_SEEK_SET: break;
    178     case STREAM_SEEK_CUR: offset += _absPos; break;
    179     case STREAM_SEEK_END: offset += _length; break;
    180     default: return STG_E_INVALIDFUNCTION;
    181   }
    182   if (offset < 0)
    183     return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
    184   _absPos = offset;
    185   _offsetPos = _absPos;
    186   _streamIndex = 0;
    187   if (newPosition)
    188     *newPosition = offset;
    189   return S_OK;
    190 }
    191 */
    192