1 // MultiStream.cpp
2 
3 #include "StdAfx.h"
4 
5 #include "MultiStream.h"
6 
Read(void * data,UInt32 size,UInt32 * processedSize)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((Int64)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 
Seek(Int64 offset,UInt32 seekOrigin,UInt64 * newPosition)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 = (UInt64)offset;
64   if (newPosition)
65     *newPosition = (UInt64)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