Mercurial > vba-linux
comparison src/win32/7zip/7z/CPP/7zip/Archive/BZip2/BZip2Handler.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 // BZip2Handler.cpp | |
2 | |
3 #include "StdAfx.h" | |
4 | |
5 #include "Common/ComTry.h" | |
6 | |
7 #include "Windows/PropVariant.h" | |
8 | |
9 #include "../../Common/CreateCoder.h" | |
10 #include "../../Common/ProgressUtils.h" | |
11 #include "../../Common/StreamUtils.h" | |
12 | |
13 #include "../Common/DummyOutStream.h" | |
14 | |
15 #include "BZip2Handler.h" | |
16 | |
17 using namespace NWindows; | |
18 | |
19 namespace NArchive { | |
20 namespace NBZip2 { | |
21 | |
22 static const CMethodId kMethodId_BZip2 = 0x040202; | |
23 | |
24 STATPROPSTG kProps[] = | |
25 { | |
26 { NULL, kpidPackSize, VT_UI8} | |
27 }; | |
28 | |
29 IMP_IInArchive_Props | |
30 IMP_IInArchive_ArcProps_NO | |
31 | |
32 STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) | |
33 { | |
34 *numItems = 1; | |
35 return S_OK; | |
36 } | |
37 | |
38 STDMETHODIMP CHandler::GetProperty(UInt32 /* index */, PROPID propID, PROPVARIANT *value) | |
39 { | |
40 NWindows::NCOM::CPropVariant prop; | |
41 switch(propID) | |
42 { | |
43 case kpidPackSize: prop = _item.PackSize; break; | |
44 } | |
45 prop.Detach(value); | |
46 return S_OK; | |
47 } | |
48 | |
49 STDMETHODIMP CHandler::Open(IInStream *stream, | |
50 const UInt64 * /* maxCheckStartPosition */, | |
51 IArchiveOpenCallback * /* openArchiveCallback */) | |
52 { | |
53 COM_TRY_BEGIN | |
54 try | |
55 { | |
56 RINOK(stream->Seek(0, STREAM_SEEK_CUR, &_streamStartPosition)); | |
57 const int kSignatureSize = 3; | |
58 Byte buffer[kSignatureSize]; | |
59 RINOK(ReadStream_FALSE(stream, buffer, kSignatureSize)); | |
60 if (buffer[0] != 'B' || buffer[1] != 'Z' || buffer[2] != 'h') | |
61 return S_FALSE; | |
62 | |
63 UInt64 endPosition; | |
64 RINOK(stream->Seek(0, STREAM_SEEK_END, &endPosition)); | |
65 _item.PackSize = endPosition - _streamStartPosition; | |
66 | |
67 _stream = stream; | |
68 } | |
69 catch(...) | |
70 { | |
71 return S_FALSE; | |
72 } | |
73 return S_OK; | |
74 COM_TRY_END | |
75 } | |
76 | |
77 STDMETHODIMP CHandler::Close() | |
78 { | |
79 _stream.Release(); | |
80 return S_OK; | |
81 } | |
82 | |
83 | |
84 STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, | |
85 Int32 testModeSpec, IArchiveExtractCallback *extractCallback) | |
86 { | |
87 COM_TRY_BEGIN | |
88 bool allFilesMode = (numItems == UInt32(-1)); | |
89 if (!allFilesMode) | |
90 { | |
91 if (numItems == 0) | |
92 return S_OK; | |
93 if (numItems != 1) | |
94 return E_INVALIDARG; | |
95 if (indices[0] != 0) | |
96 return E_INVALIDARG; | |
97 } | |
98 | |
99 bool testMode = (testModeSpec != 0); | |
100 | |
101 extractCallback->SetTotal(_item.PackSize); | |
102 | |
103 UInt64 currentTotalPacked = 0; | |
104 | |
105 RINOK(extractCallback->SetCompleted(¤tTotalPacked)); | |
106 | |
107 CMyComPtr<ISequentialOutStream> realOutStream; | |
108 Int32 askMode; | |
109 askMode = testMode ? NExtract::NAskMode::kTest : | |
110 NExtract::NAskMode::kExtract; | |
111 | |
112 RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); | |
113 | |
114 if(!testMode && !realOutStream) | |
115 return S_OK; | |
116 | |
117 | |
118 extractCallback->PrepareOperation(askMode); | |
119 | |
120 CMyComPtr<ICompressCoder> decoder; | |
121 HRESULT loadResult = CreateCoder( | |
122 EXTERNAL_CODECS_VARS | |
123 kMethodId_BZip2, decoder, false); | |
124 if (loadResult != S_OK || !decoder) | |
125 { | |
126 RINOK(extractCallback->SetOperationResult(NExtract::NOperationResult::kUnSupportedMethod)); | |
127 return S_OK; | |
128 } | |
129 | |
130 #ifdef COMPRESS_MT | |
131 { | |
132 CMyComPtr<ICompressSetCoderMt> setCoderMt; | |
133 decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt); | |
134 if (setCoderMt) | |
135 { | |
136 RINOK(setCoderMt->SetNumberOfThreads(_numThreads)); | |
137 } | |
138 } | |
139 #endif | |
140 | |
141 CDummyOutStream *outStreamSpec = new CDummyOutStream; | |
142 CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); | |
143 outStreamSpec->SetStream(realOutStream); | |
144 outStreamSpec->Init(); | |
145 | |
146 realOutStream.Release(); | |
147 | |
148 CLocalProgress *lps = new CLocalProgress; | |
149 CMyComPtr<ICompressProgressInfo> progress = lps; | |
150 lps->Init(extractCallback, true); | |
151 | |
152 RINOK(_stream->Seek(_streamStartPosition, STREAM_SEEK_SET, NULL)); | |
153 | |
154 HRESULT result = S_OK; | |
155 | |
156 bool firstItem = true; | |
157 for (;;) | |
158 { | |
159 lps->InSize = currentTotalPacked; | |
160 lps->OutSize = outStreamSpec->GetSize(); | |
161 | |
162 RINOK(lps->SetCur()); | |
163 | |
164 const int kSignatureSize = 3; | |
165 Byte buffer[kSignatureSize]; | |
166 size_t processedSize = kSignatureSize; | |
167 RINOK(ReadStream(_stream, buffer, &processedSize)); | |
168 if (processedSize != kSignatureSize) | |
169 { | |
170 if (firstItem) | |
171 return E_FAIL; | |
172 break; | |
173 } | |
174 if (buffer[0] != 'B' || buffer[1] != 'Z' || buffer[2] != 'h') | |
175 { | |
176 if (firstItem) | |
177 return E_FAIL; | |
178 break; | |
179 } | |
180 firstItem = false; | |
181 | |
182 UInt64 dataStartPos; | |
183 RINOK(_stream->Seek((UInt64)(Int64)(-3), STREAM_SEEK_CUR, &dataStartPos)); | |
184 | |
185 result = decoder->Code(_stream, outStream, NULL, NULL, progress); | |
186 | |
187 if (result != S_OK) | |
188 break; | |
189 | |
190 CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; | |
191 decoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, &getInStreamProcessedSize); | |
192 if (!getInStreamProcessedSize) | |
193 break; | |
194 UInt64 packSize; | |
195 RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(&packSize)); | |
196 UInt64 pos; | |
197 RINOK(_stream->Seek(dataStartPos + packSize, STREAM_SEEK_SET, &pos)); | |
198 currentTotalPacked = pos - _streamStartPosition; | |
199 } | |
200 outStream.Release(); | |
201 | |
202 Int32 retResult; | |
203 if (result == S_OK) | |
204 retResult = NExtract::NOperationResult::kOK; | |
205 else if (result == S_FALSE) | |
206 retResult = NExtract::NOperationResult::kDataError; | |
207 else | |
208 return result; | |
209 return extractCallback->SetOperationResult(retResult); | |
210 | |
211 COM_TRY_END | |
212 } | |
213 | |
214 IMPL_ISetCompressCodecsInfo | |
215 | |
216 }} |