Mercurial > vba-linux
comparison src/win32/7zip/7z/CPP/7zip/Archive/7z/7zExtract.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 // 7zExtract.cpp | |
2 | |
3 #include "StdAfx.h" | |
4 | |
5 #include "7zHandler.h" | |
6 #include "7zFolderOutStream.h" | |
7 #include "7zDecode.h" | |
8 // #include "7z1Decode.h" | |
9 | |
10 #include "../../../Common/ComTry.h" | |
11 #include "../../Common/StreamObjects.h" | |
12 #include "../../Common/ProgressUtils.h" | |
13 #include "../../Common/LimitedStreams.h" | |
14 | |
15 namespace NArchive { | |
16 namespace N7z { | |
17 | |
18 struct CExtractFolderInfo | |
19 { | |
20 #ifdef _7Z_VOL | |
21 int VolumeIndex; | |
22 #endif | |
23 CNum FileIndex; | |
24 CNum FolderIndex; | |
25 CBoolVector ExtractStatuses; | |
26 UInt64 UnpackSize; | |
27 CExtractFolderInfo( | |
28 #ifdef _7Z_VOL | |
29 int volumeIndex, | |
30 #endif | |
31 CNum fileIndex, CNum folderIndex): | |
32 #ifdef _7Z_VOL | |
33 VolumeIndex(volumeIndex), | |
34 #endif | |
35 FileIndex(fileIndex), | |
36 FolderIndex(folderIndex), | |
37 UnpackSize(0) | |
38 { | |
39 if (fileIndex != kNumNoIndex) | |
40 { | |
41 ExtractStatuses.Reserve(1); | |
42 ExtractStatuses.Add(true); | |
43 } | |
44 }; | |
45 }; | |
46 | |
47 STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, | |
48 Int32 testModeSpec, IArchiveExtractCallback *extractCallbackSpec) | |
49 { | |
50 COM_TRY_BEGIN | |
51 bool testMode = (testModeSpec != 0); | |
52 CMyComPtr<IArchiveExtractCallback> extractCallback = extractCallbackSpec; | |
53 UInt64 importantTotalUnpacked = 0; | |
54 | |
55 bool allFilesMode = (numItems == UInt32(-1)); | |
56 if (allFilesMode) | |
57 numItems = | |
58 #ifdef _7Z_VOL | |
59 _refs.Size(); | |
60 #else | |
61 _db.Files.Size(); | |
62 #endif | |
63 | |
64 if(numItems == 0) | |
65 return S_OK; | |
66 | |
67 /* | |
68 if(_volumes.Size() != 1) | |
69 return E_FAIL; | |
70 const CVolume &volume = _volumes.Front(); | |
71 const CArchiveDatabaseEx &_db = volume.Database; | |
72 IInStream *_inStream = volume.Stream; | |
73 */ | |
74 | |
75 CObjectVector<CExtractFolderInfo> extractFolderInfoVector; | |
76 for(UInt32 ii = 0; ii < numItems; ii++) | |
77 { | |
78 // UInt32 fileIndex = allFilesMode ? indexIndex : indices[indexIndex]; | |
79 UInt32 ref2Index = allFilesMode ? ii : indices[ii]; | |
80 // const CRef2 &ref2 = _refs[ref2Index]; | |
81 | |
82 // for(UInt32 ri = 0; ri < ref2.Refs.Size(); ri++) | |
83 { | |
84 #ifdef _7Z_VOL | |
85 // const CRef &ref = ref2.Refs[ri]; | |
86 const CRef &ref = _refs[ref2Index]; | |
87 | |
88 int volumeIndex = ref.VolumeIndex; | |
89 const CVolume &volume = _volumes[volumeIndex]; | |
90 const CArchiveDatabaseEx &db = volume.Database; | |
91 UInt32 fileIndex = ref.ItemIndex; | |
92 #else | |
93 const CArchiveDatabaseEx &db = _db; | |
94 UInt32 fileIndex = ref2Index; | |
95 #endif | |
96 | |
97 CNum folderIndex = db.FileIndexToFolderIndexMap[fileIndex]; | |
98 if (folderIndex == kNumNoIndex) | |
99 { | |
100 extractFolderInfoVector.Add(CExtractFolderInfo( | |
101 #ifdef _7Z_VOL | |
102 volumeIndex, | |
103 #endif | |
104 fileIndex, kNumNoIndex)); | |
105 continue; | |
106 } | |
107 if (extractFolderInfoVector.IsEmpty() || | |
108 folderIndex != extractFolderInfoVector.Back().FolderIndex | |
109 #ifdef _7Z_VOL | |
110 || volumeIndex != extractFolderInfoVector.Back().VolumeIndex | |
111 #endif | |
112 ) | |
113 { | |
114 extractFolderInfoVector.Add(CExtractFolderInfo( | |
115 #ifdef _7Z_VOL | |
116 volumeIndex, | |
117 #endif | |
118 kNumNoIndex, folderIndex)); | |
119 const CFolder &folderInfo = db.Folders[folderIndex]; | |
120 UInt64 unpackSize = folderInfo.GetUnpackSize(); | |
121 importantTotalUnpacked += unpackSize; | |
122 extractFolderInfoVector.Back().UnpackSize = unpackSize; | |
123 } | |
124 | |
125 CExtractFolderInfo &efi = extractFolderInfoVector.Back(); | |
126 | |
127 // const CFolderInfo &folderInfo = m_dam_Folders[folderIndex]; | |
128 CNum startIndex = db.FolderStartFileIndex[folderIndex]; | |
129 for (CNum index = efi.ExtractStatuses.Size(); | |
130 index <= fileIndex - startIndex; index++) | |
131 { | |
132 // UInt64 unpackSize = _db.Files[startIndex + index].UnpackSize; | |
133 // Count partial_folder_size | |
134 // efi.UnpackSize += unpackSize; | |
135 // importantTotalUnpacked += unpackSize; | |
136 efi.ExtractStatuses.Add(index == fileIndex - startIndex); | |
137 } | |
138 } | |
139 } | |
140 | |
141 extractCallback->SetTotal(importantTotalUnpacked); | |
142 | |
143 CDecoder decoder( | |
144 #ifdef _ST_MODE | |
145 false | |
146 #else | |
147 true | |
148 #endif | |
149 ); | |
150 // CDecoder1 decoder; | |
151 | |
152 UInt64 currentTotalPacked = 0; | |
153 UInt64 currentTotalUnpacked = 0; | |
154 UInt64 totalFolderUnpacked; | |
155 UInt64 totalFolderPacked; | |
156 | |
157 CLocalProgress *lps = new CLocalProgress; | |
158 CMyComPtr<ICompressProgressInfo> progress = lps; | |
159 lps->Init(extractCallback, false); | |
160 | |
161 for(int i = 0; i < extractFolderInfoVector.Size(); i++, | |
162 currentTotalUnpacked += totalFolderUnpacked, | |
163 currentTotalPacked += totalFolderPacked) | |
164 { | |
165 lps->OutSize = currentTotalUnpacked; | |
166 lps->InSize = currentTotalPacked; | |
167 RINOK(lps->SetCur()); | |
168 | |
169 const CExtractFolderInfo &efi = extractFolderInfoVector[i]; | |
170 totalFolderUnpacked = efi.UnpackSize; | |
171 | |
172 totalFolderPacked = 0; | |
173 | |
174 CFolderOutStream *folderOutStream = new CFolderOutStream; | |
175 CMyComPtr<ISequentialOutStream> outStream(folderOutStream); | |
176 | |
177 #ifdef _7Z_VOL | |
178 const CVolume &volume = _volumes[efi.VolumeIndex]; | |
179 const CArchiveDatabaseEx &db = volume.Database; | |
180 #else | |
181 const CArchiveDatabaseEx &db = _db; | |
182 #endif | |
183 | |
184 CNum startIndex; | |
185 if (efi.FileIndex != kNumNoIndex) | |
186 startIndex = efi.FileIndex; | |
187 else | |
188 startIndex = db.FolderStartFileIndex[efi.FolderIndex]; | |
189 | |
190 | |
191 HRESULT result = folderOutStream->Init(&db, | |
192 #ifdef _7Z_VOL | |
193 volume.StartRef2Index, | |
194 #else | |
195 0, | |
196 #endif | |
197 startIndex, | |
198 &efi.ExtractStatuses, extractCallback, testMode, _crcSize != 0); | |
199 | |
200 RINOK(result); | |
201 | |
202 if (efi.FileIndex != kNumNoIndex) | |
203 continue; | |
204 | |
205 CNum folderIndex = efi.FolderIndex; | |
206 const CFolder &folderInfo = db.Folders[folderIndex]; | |
207 | |
208 totalFolderPacked = _db.GetFolderFullPackSize(folderIndex); | |
209 | |
210 CNum packStreamIndex = db.FolderStartPackStreamIndex[folderIndex]; | |
211 UInt64 folderStartPackPos = db.GetFolderStreamPos(folderIndex, 0); | |
212 | |
213 #ifndef _NO_CRYPTO | |
214 CMyComPtr<ICryptoGetTextPassword> getTextPassword; | |
215 if (extractCallback) | |
216 extractCallback.QueryInterface(IID_ICryptoGetTextPassword, &getTextPassword); | |
217 #endif | |
218 | |
219 try | |
220 { | |
221 #ifndef _NO_CRYPTO | |
222 bool passwordIsDefined; | |
223 #endif | |
224 | |
225 HRESULT result = decoder.Decode( | |
226 EXTERNAL_CODECS_VARS | |
227 #ifdef _7Z_VOL | |
228 volume.Stream, | |
229 #else | |
230 _inStream, | |
231 #endif | |
232 folderStartPackPos, | |
233 &db.PackSizes[packStreamIndex], | |
234 folderInfo, | |
235 outStream, | |
236 progress | |
237 #ifndef _NO_CRYPTO | |
238 , getTextPassword, passwordIsDefined | |
239 #endif | |
240 #ifdef COMPRESS_MT | |
241 , true, _numThreads | |
242 #endif | |
243 ); | |
244 | |
245 if (result == S_FALSE) | |
246 { | |
247 RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); | |
248 continue; | |
249 } | |
250 if (result == E_NOTIMPL) | |
251 { | |
252 RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kUnSupportedMethod)); | |
253 continue; | |
254 } | |
255 if (result != S_OK) | |
256 return result; | |
257 if (folderOutStream->WasWritingFinished() != S_OK) | |
258 { | |
259 RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); | |
260 continue; | |
261 } | |
262 } | |
263 catch(...) | |
264 { | |
265 RINOK(folderOutStream->FlushCorrupted(NArchive::NExtract::NOperationResult::kDataError)); | |
266 continue; | |
267 } | |
268 } | |
269 return S_OK; | |
270 COM_TRY_END | |
271 } | |
272 | |
273 }} |