Mercurial > vba-linux
comparison src/win32/7zip/7z/CPP/7zip/Archive/Lzma/LzmaHandler.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 // LzmaHandler.cpp | |
2 | |
3 #include "StdAfx.h" | |
4 | |
5 #include "LzmaHandler.h" | |
6 | |
7 #include "Common/Defs.h" | |
8 #include "Common/StringConvert.h" | |
9 #include "Common/ComTry.h" | |
10 #include "Common/IntToString.h" | |
11 | |
12 #include "Windows/PropVariant.h" | |
13 | |
14 #include "../../Common/ProgressUtils.h" | |
15 #include "../../Common/StreamUtils.h" | |
16 #include "../Common/DummyOutStream.h" | |
17 | |
18 #include "LzmaFiltersDecode.h" | |
19 | |
20 namespace NArchive { | |
21 namespace NLzma { | |
22 | |
23 STATPROPSTG kProps[] = | |
24 { | |
25 { NULL, kpidSize, VT_UI8}, | |
26 { NULL, kpidPackSize, VT_UI8}, | |
27 { NULL, kpidMethod, VT_UI1} | |
28 }; | |
29 | |
30 IMP_IInArchive_Props | |
31 IMP_IInArchive_ArcProps_NO | |
32 | |
33 STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) | |
34 { | |
35 *numItems = 1; | |
36 return S_OK; | |
37 } | |
38 | |
39 static void ConvertUInt32ToString(UInt32 value, wchar_t *s) | |
40 { | |
41 ConvertUInt64ToString(value, s + MyStringLen(s)); | |
42 } | |
43 | |
44 static void DictSizeToString(UInt32 value, wchar_t *s) | |
45 { | |
46 for (int i = 0; i <= 31; i++) | |
47 if ((UInt32(1) << i) == value) | |
48 { | |
49 ConvertUInt32ToString(i, s); | |
50 return; | |
51 } | |
52 wchar_t c = L'b'; | |
53 if ((value & ((1 << 20) - 1)) == 0) | |
54 { | |
55 value >>= 20; | |
56 c = L'm'; | |
57 } | |
58 else if ((value & ((1 << 10) - 1)) == 0) | |
59 { | |
60 value >>= 10; | |
61 c = L'k'; | |
62 } | |
63 ConvertUInt32ToString(value, s); | |
64 int p = MyStringLen(s); | |
65 s[p++] = c; | |
66 s[p++] = L'\0'; | |
67 } | |
68 | |
69 static void MyStrCat(wchar_t *d, const wchar_t *s) | |
70 { | |
71 MyStringCopy(d + MyStringLen(d), s); | |
72 } | |
73 | |
74 STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) | |
75 { | |
76 if (index != 0) | |
77 return E_INVALIDARG; | |
78 NWindows::NCOM::CPropVariant propVariant; | |
79 switch(propID) | |
80 { | |
81 case kpidSize: | |
82 if (m_StreamInfo.HasUnpackSize()) | |
83 propVariant = (UInt64)m_StreamInfo.UnpackSize; | |
84 break; | |
85 case kpidPackSize: | |
86 propVariant = (UInt64)m_PackSize; | |
87 break; | |
88 case kpidMethod: | |
89 { | |
90 wchar_t s[64]; | |
91 s[0] = '\0'; | |
92 if (m_StreamInfo.IsThereFilter) | |
93 { | |
94 const wchar_t *f; | |
95 if (m_StreamInfo.FilterMethod == 0) | |
96 f = L"Copy"; | |
97 else if (m_StreamInfo.FilterMethod == 1) | |
98 f = L"BCJ"; | |
99 else | |
100 f = L"Unknown"; | |
101 MyStrCat(s, f); | |
102 MyStrCat(s, L" "); | |
103 } | |
104 MyStrCat(s, L"LZMA:"); | |
105 DictSizeToString(m_StreamInfo.GetDicSize(), s); | |
106 propVariant = s; | |
107 break; | |
108 } | |
109 } | |
110 propVariant.Detach(value); | |
111 return S_OK; | |
112 } | |
113 | |
114 STDMETHODIMP CHandler::Open(IInStream *inStream, | |
115 const UInt64 * /* maxCheckStartPosition */, | |
116 IArchiveOpenCallback * /* openArchiveCallback */) | |
117 { | |
118 { | |
119 RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); | |
120 | |
121 HRESULT res = ReadStreamHeader(inStream, m_StreamInfo); | |
122 if (res != S_OK) | |
123 return S_FALSE; | |
124 | |
125 Byte b; | |
126 RINOK(ReadStream_FALSE(inStream, &b, 1)); | |
127 if (b != 0) | |
128 return S_FALSE; | |
129 | |
130 UInt64 endPos; | |
131 RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); | |
132 m_PackSize = endPos - m_StreamStartPosition - m_StreamInfo.GetHeaderSize(); | |
133 | |
134 m_Stream = inStream; | |
135 } | |
136 return S_OK; | |
137 } | |
138 | |
139 STDMETHODIMP CHandler::Close() | |
140 { | |
141 m_Stream.Release(); | |
142 return S_OK; | |
143 } | |
144 | |
145 | |
146 STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, | |
147 Int32 _aTestMode, IArchiveExtractCallback *extractCallback) | |
148 { | |
149 COM_TRY_BEGIN | |
150 bool allFilesMode = (numItems == UInt32(-1)); | |
151 if (!allFilesMode) | |
152 { | |
153 if (numItems == 0) | |
154 return S_OK; | |
155 if (numItems != 1) | |
156 return E_INVALIDARG; | |
157 if (indices[0] != 0) | |
158 return E_INVALIDARG; | |
159 } | |
160 | |
161 bool testMode = (_aTestMode != 0); | |
162 | |
163 RINOK(extractCallback->SetTotal(m_PackSize)); | |
164 | |
165 UInt64 currentTotalPacked = 0; | |
166 | |
167 CDummyOutStream *outStreamSpec = new CDummyOutStream; | |
168 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); | |
169 | |
170 { | |
171 CMyComPtr<ISequentialOutStream> realOutStream; | |
172 Int32 askMode = testMode ? | |
173 NArchive::NExtract::NAskMode::kTest : | |
174 NArchive::NExtract::NAskMode::kExtract; | |
175 | |
176 RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); | |
177 | |
178 outStreamSpec->SetStream(realOutStream); | |
179 outStreamSpec->Init(); | |
180 if(!testMode && !realOutStream) | |
181 return S_OK; | |
182 extractCallback->PrepareOperation(askMode); | |
183 } | |
184 | |
185 CLocalProgress *lps = new CLocalProgress; | |
186 CMyComPtr<ICompressProgressInfo> progress = lps; | |
187 lps->Init(extractCallback, true); | |
188 | |
189 CDecoder decoder; | |
190 RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL)); | |
191 UInt64 streamPos = m_StreamStartPosition; | |
192 Int32 opRes = NArchive::NExtract::NOperationResult::kOK; | |
193 bool firstItem = true; | |
194 for (;;) | |
195 { | |
196 CHeader st; | |
197 HRESULT result = ReadStreamHeader(m_Stream, st); | |
198 if (result != S_OK) | |
199 { | |
200 if (firstItem) | |
201 return E_FAIL; | |
202 break; | |
203 } | |
204 firstItem = false; | |
205 | |
206 lps->OutSize = outStreamSpec->GetSize(); | |
207 lps->InSize = currentTotalPacked; | |
208 RINOK(lps->SetCur()); | |
209 | |
210 streamPos += st.GetHeaderSize(); | |
211 UInt64 packProcessed; | |
212 | |
213 { | |
214 result = decoder.Code( | |
215 EXTERNAL_CODECS_VARS | |
216 st, m_Stream, outStream, &packProcessed, progress); | |
217 if (result == E_NOTIMPL) | |
218 { | |
219 opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; | |
220 break; | |
221 } | |
222 if (result == S_FALSE) | |
223 { | |
224 opRes = NArchive::NExtract::NOperationResult::kDataError; | |
225 break; | |
226 } | |
227 RINOK(result); | |
228 } | |
229 | |
230 if (packProcessed == (UInt64)(Int64)-1) | |
231 break; | |
232 RINOK(m_Stream->Seek(streamPos + packProcessed, STREAM_SEEK_SET, NULL)); | |
233 currentTotalPacked += packProcessed; | |
234 streamPos += packProcessed; | |
235 } | |
236 outStream.Release(); | |
237 return extractCallback->SetOperationResult(opRes); | |
238 COM_TRY_END | |
239 } | |
240 | |
241 IMPL_ISetCompressCodecsInfo | |
242 | |
243 }} |