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(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 = 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 != NULL)
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 != NULL)
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