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