tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MultiStream.cpp (4819B)


      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 */