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