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