Mercurial > vba-linux
comparison src/win32/7zip/7z/CPP/7zip/Archive/Split/SplitHandler.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:8ced16adf2e1 | 1:f9f4f1b99eed |
---|---|
1 // SplitHandler.cpp | |
2 | |
3 #include "StdAfx.h" | |
4 | |
5 #include "Common/ComTry.h" | |
6 #include "Common/Defs.h" | |
7 #include "Common/NewHandler.h" | |
8 #include "Common/StringConvert.h" | |
9 | |
10 #include "Windows/PropVariant.h" | |
11 #include "Windows/Time.h" | |
12 | |
13 #include "../../Common/ProgressUtils.h" | |
14 | |
15 #include "../../Compress/CopyCoder.h" | |
16 | |
17 #include "../Common/ItemNameUtils.h" | |
18 #include "../Common/MultiStream.h" | |
19 | |
20 #include "SplitHandler.h" | |
21 | |
22 using namespace NWindows; | |
23 using namespace NTime; | |
24 | |
25 namespace NArchive { | |
26 namespace NSplit { | |
27 | |
28 STATPROPSTG kProps[] = | |
29 { | |
30 { NULL, kpidPath, VT_BSTR}, | |
31 { NULL, kpidSize, VT_UI8}, | |
32 { NULL, kpidPackSize, VT_UI8}, | |
33 }; | |
34 | |
35 IMP_IInArchive_Props | |
36 IMP_IInArchive_ArcProps_NO | |
37 | |
38 class CSeqName | |
39 { | |
40 public: | |
41 UString _unchangedPart; | |
42 UString _changedPart; | |
43 bool _splitStyle; | |
44 UString GetNextName() | |
45 { | |
46 UString newName; | |
47 if (_splitStyle) | |
48 { | |
49 int i; | |
50 int numLetters = _changedPart.Length(); | |
51 for (i = numLetters - 1; i >= 0; i--) | |
52 { | |
53 wchar_t c = _changedPart[i]; | |
54 if (c == 'z') | |
55 { | |
56 c = 'a'; | |
57 newName = c + newName; | |
58 continue; | |
59 } | |
60 else if (c == 'Z') | |
61 { | |
62 c = 'A'; | |
63 newName = c + newName; | |
64 continue; | |
65 } | |
66 c++; | |
67 if ((c == 'z' || c == 'Z') && i == 0) | |
68 { | |
69 _unchangedPart += c; | |
70 wchar_t newChar = (c == 'z') ? L'a' : L'A'; | |
71 newName.Empty(); | |
72 numLetters++; | |
73 for (int k = 0; k < numLetters; k++) | |
74 newName += newChar; | |
75 break; | |
76 } | |
77 newName = c + newName; | |
78 i--; | |
79 for (; i >= 0; i--) | |
80 newName = _changedPart[i] + newName; | |
81 break; | |
82 } | |
83 } | |
84 else | |
85 { | |
86 int i; | |
87 int numLetters = _changedPart.Length(); | |
88 for (i = numLetters - 1; i >= 0; i--) | |
89 { | |
90 wchar_t c = _changedPart[i]; | |
91 if (c == L'9') | |
92 { | |
93 c = L'0'; | |
94 newName = c + newName; | |
95 if (i == 0) | |
96 newName = UString(L'1') + newName; | |
97 continue; | |
98 } | |
99 c++; | |
100 newName = c + newName; | |
101 i--; | |
102 for (; i >= 0; i--) | |
103 newName = _changedPart[i] + newName; | |
104 break; | |
105 } | |
106 } | |
107 _changedPart = newName; | |
108 return _unchangedPart + _changedPart; | |
109 } | |
110 }; | |
111 | |
112 STDMETHODIMP CHandler::Open(IInStream *stream, | |
113 const UInt64 * /* maxCheckStartPosition */, | |
114 IArchiveOpenCallback *openArchiveCallback) | |
115 { | |
116 COM_TRY_BEGIN | |
117 Close(); | |
118 if (openArchiveCallback == 0) | |
119 return S_FALSE; | |
120 // try | |
121 { | |
122 CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback; | |
123 CMyComPtr<IArchiveOpenCallback> openArchiveCallbackWrap = openArchiveCallback; | |
124 if (openArchiveCallbackWrap.QueryInterface(IID_IArchiveOpenVolumeCallback, | |
125 &openVolumeCallback) != S_OK) | |
126 return S_FALSE; | |
127 | |
128 { | |
129 NCOM::CPropVariant prop; | |
130 RINOK(openVolumeCallback->GetProperty(kpidName, &prop)); | |
131 if (prop.vt != VT_BSTR) | |
132 return S_FALSE; | |
133 _name = prop.bstrVal; | |
134 } | |
135 | |
136 int dotPos = _name.ReverseFind('.'); | |
137 UString prefix, ext; | |
138 if (dotPos >= 0) | |
139 { | |
140 prefix = _name.Left(dotPos + 1); | |
141 ext = _name.Mid(dotPos + 1); | |
142 } | |
143 else | |
144 ext = _name; | |
145 UString extBig = ext; | |
146 extBig.MakeUpper(); | |
147 | |
148 CSeqName seqName; | |
149 | |
150 int numLetters = 2; | |
151 bool splitStyle = false; | |
152 if (extBig.Right(2) == L"AA") | |
153 { | |
154 splitStyle = true; | |
155 while (numLetters < extBig.Length()) | |
156 { | |
157 if (extBig[extBig.Length() - numLetters - 1] != 'A') | |
158 break; | |
159 numLetters++; | |
160 } | |
161 } | |
162 else if (ext.Right(2) == L"01") | |
163 { | |
164 while (numLetters < extBig.Length()) | |
165 { | |
166 if (extBig[extBig.Length() - numLetters - 1] != '0') | |
167 break; | |
168 numLetters++; | |
169 } | |
170 if (numLetters != ext.Length()) | |
171 return S_FALSE; | |
172 } | |
173 else | |
174 return S_FALSE; | |
175 | |
176 _streams.Add(stream); | |
177 | |
178 seqName._unchangedPart = prefix + ext.Left(extBig.Length() - numLetters); | |
179 seqName._changedPart = ext.Right(numLetters); | |
180 seqName._splitStyle = splitStyle; | |
181 | |
182 if (prefix.Length() < 1) | |
183 _subName = L"file"; | |
184 else | |
185 _subName = prefix.Left(prefix.Length() - 1); | |
186 | |
187 _totalSize = 0; | |
188 UInt64 size; | |
189 { | |
190 NCOM::CPropVariant prop; | |
191 RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); | |
192 if (prop.vt != VT_UI8) | |
193 return E_INVALIDARG; | |
194 size = prop.uhVal.QuadPart; | |
195 } | |
196 _totalSize += size; | |
197 _sizes.Add(size); | |
198 | |
199 if (openArchiveCallback != NULL) | |
200 { | |
201 UInt64 numFiles = _streams.Size(); | |
202 RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); | |
203 } | |
204 | |
205 for (;;) | |
206 { | |
207 UString fullName = seqName.GetNextName(); | |
208 CMyComPtr<IInStream> nextStream; | |
209 HRESULT result = openVolumeCallback->GetStream(fullName, &nextStream); | |
210 if (result == S_FALSE) | |
211 break; | |
212 if (result != S_OK) | |
213 return result; | |
214 if (!stream) | |
215 break; | |
216 { | |
217 NCOM::CPropVariant prop; | |
218 RINOK(openVolumeCallback->GetProperty(kpidSize, &prop)); | |
219 if (prop.vt != VT_UI8) | |
220 return E_INVALIDARG; | |
221 size = prop.uhVal.QuadPart; | |
222 } | |
223 _totalSize += size; | |
224 _sizes.Add(size); | |
225 _streams.Add(nextStream); | |
226 if (openArchiveCallback != NULL) | |
227 { | |
228 UInt64 numFiles = _streams.Size(); | |
229 RINOK(openArchiveCallback->SetCompleted(&numFiles, NULL)); | |
230 } | |
231 } | |
232 } | |
233 /* | |
234 catch(...) | |
235 { | |
236 return S_FALSE; | |
237 } | |
238 */ | |
239 return S_OK; | |
240 COM_TRY_END | |
241 } | |
242 | |
243 STDMETHODIMP CHandler::Close() | |
244 { | |
245 _sizes.Clear(); | |
246 _streams.Clear(); | |
247 return S_OK; | |
248 } | |
249 | |
250 STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) | |
251 { | |
252 *numItems = _streams.IsEmpty() ? 0 : 1; | |
253 return S_OK; | |
254 } | |
255 | |
256 STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) | |
257 { | |
258 NWindows::NCOM::CPropVariant prop; | |
259 switch(propID) | |
260 { | |
261 case kpidPath: | |
262 prop = _subName; | |
263 break; | |
264 case kpidSize: | |
265 case kpidPackSize: | |
266 prop = _totalSize; | |
267 break; | |
268 } | |
269 prop.Detach(value); | |
270 return S_OK; | |
271 } | |
272 | |
273 STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, | |
274 Int32 _aTestMode, IArchiveExtractCallback *_anExtractCallback) | |
275 { | |
276 COM_TRY_BEGIN | |
277 | |
278 if (numItems != UInt32(-1)) | |
279 { | |
280 if (numItems != 1) | |
281 return E_INVALIDARG; | |
282 if (indices[0] != 0) | |
283 return E_INVALIDARG; | |
284 } | |
285 bool testMode = (_aTestMode != 0); | |
286 CMyComPtr<IArchiveExtractCallback> extractCallback = _anExtractCallback; | |
287 extractCallback->SetTotal(_totalSize); | |
288 | |
289 /* | |
290 CMyComPtr<IArchiveVolumeExtractCallback> volumeExtractCallback; | |
291 if (extractCallback.QueryInterface(&volumeExtractCallback) != S_OK) | |
292 return E_FAIL; | |
293 */ | |
294 | |
295 UInt64 currentTotalSize = 0; | |
296 UInt64 currentItemSize; | |
297 | |
298 RINOK(extractCallback->SetCompleted(¤tTotalSize)); | |
299 CMyComPtr<ISequentialOutStream> realOutStream; | |
300 Int32 askMode; | |
301 askMode = testMode ? NArchive::NExtract::NAskMode::kTest : | |
302 NArchive::NExtract::NAskMode::kExtract; | |
303 Int32 index = 0; | |
304 RINOK(extractCallback->GetStream(index, &realOutStream, askMode)); | |
305 | |
306 RINOK(extractCallback->PrepareOperation(askMode)); | |
307 if (testMode) | |
308 { | |
309 RINOK(extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK)); | |
310 return S_OK; | |
311 } | |
312 | |
313 if (!testMode && (!realOutStream)) | |
314 return S_OK; | |
315 | |
316 NCompress::CCopyCoder *copyCoderSpec = new NCompress::CCopyCoder; | |
317 CMyComPtr<ICompressCoder> copyCoder = copyCoderSpec; | |
318 | |
319 CLocalProgress *lps = new CLocalProgress; | |
320 CMyComPtr<ICompressProgressInfo> progress = lps; | |
321 lps->Init(extractCallback, false); | |
322 | |
323 for (int i = 0; i < _streams.Size(); i++, currentTotalSize += currentItemSize) | |
324 { | |
325 lps->InSize = lps->OutSize = currentTotalSize; | |
326 RINOK(lps->SetCur()); | |
327 IInStream *inStream = _streams[i]; | |
328 RINOK(inStream->Seek(0, STREAM_SEEK_SET, NULL)); | |
329 RINOK(copyCoder->Code(inStream, realOutStream, NULL, NULL, progress)); | |
330 currentItemSize = copyCoderSpec->TotalSize; | |
331 } | |
332 realOutStream.Release(); | |
333 return extractCallback->SetOperationResult(NArchive::NExtract::NOperationResult::kOK); | |
334 COM_TRY_END | |
335 } | |
336 | |
337 STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream) | |
338 { | |
339 if (index != 0) | |
340 return E_INVALIDARG; | |
341 *stream = 0; | |
342 CMultiStream *streamSpec = new CMultiStream; | |
343 CMyComPtr<ISequentialInStream> streamTemp = streamSpec; | |
344 for (int i = 0; i < _streams.Size(); i++) | |
345 { | |
346 CMultiStream::CSubStreamInfo subStreamInfo; | |
347 subStreamInfo.Stream = _streams[i]; | |
348 subStreamInfo.Pos = 0; | |
349 subStreamInfo.Size = _sizes[i]; | |
350 streamSpec->Streams.Add(subStreamInfo); | |
351 } | |
352 streamSpec->Init(); | |
353 *stream = streamTemp.Detach(); | |
354 return S_OK; | |
355 } | |
356 | |
357 }} |