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 (_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
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: _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