diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2008-05-05 04:00:00 +0400 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:15:55 +0300 |
commit | 3901bf0ab88106a5b031cba7bc18d60cdebf7eef (patch) | |
tree | 808a2489abed822223b118b64e0553db80af6087 /CPP/7zip/Archive/Lzma | |
parent | bd1fa36322ac27f5715433b388742893d6524516 (diff) |
4.58 beta
Diffstat (limited to 'CPP/7zip/Archive/Lzma')
-rwxr-xr-x | CPP/7zip/Archive/Lzma/LzmaArcRegister.cpp | 14 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Lzma/LzmaFiltersDecode.cpp | 86 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Lzma/LzmaFiltersDecode.h | 26 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Lzma/LzmaHandler.cpp | 243 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Lzma/LzmaHandler.h | 69 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Lzma/LzmaIn.cpp | 56 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Lzma/LzmaIn.h | 16 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Lzma/LzmaItem.h | 27 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Lzma/StdAfx.h | 8 | ||||
-rwxr-xr-x | CPP/7zip/Archive/Lzma/lzma.ico | bin | 0 -> 3638 bytes |
10 files changed, 545 insertions, 0 deletions
diff --git a/CPP/7zip/Archive/Lzma/LzmaArcRegister.cpp b/CPP/7zip/Archive/Lzma/LzmaArcRegister.cpp new file mode 100755 index 00000000..bbeb177b --- /dev/null +++ b/CPP/7zip/Archive/Lzma/LzmaArcRegister.cpp @@ -0,0 +1,14 @@ +// LzmaArcRegister.cpp + +#include "StdAfx.h" + +#include "../../Common/RegisterArc.h" + +#include "LzmaHandler.h" + +static IInArchive *CreateArc() { return new NArchive::NLzma::CHandler; } + +static CArcInfo g_ArcInfo = + { L"Lzma", L"lzma lzma86", 0, 0xA, {0 }, 0, true, CreateArc, NULL }; + +REGISTER_ARC(Lzma) diff --git a/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.cpp b/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.cpp new file mode 100755 index 00000000..d3450616 --- /dev/null +++ b/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.cpp @@ -0,0 +1,86 @@ +// LzmaFiltersDecode.cpp + +#include "StdAfx.h" + +#include "LzmaFiltersDecode.h" + +namespace NArchive { +namespace NLzma { + +static const UInt64 k_LZMA = 0x030101; +static const UInt64 k_BCJ = 0x03030103; + +HRESULT CDecoder::Code( + DECL_EXTERNAL_CODECS_LOC_VARS + const CHeader &block, + ISequentialInStream *inStream, ISequentialOutStream *outStream, + UInt64 *inProcessedSize, ICompressProgressInfo *progress) +{ + *inProcessedSize = (UInt64)(Int64)-1; + + if (block.FilterMethod > 1) + return E_NOTIMPL; + + if (!_lzmaDecoder) + { + RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_LZMA, _lzmaDecoder, false)); + if (_lzmaDecoder == 0) + return E_NOTIMPL; + } + + { + CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties; + _lzmaDecoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties); + if (!setDecoderProperties) + return E_NOTIMPL; + RINOK(setDecoderProperties->SetDecoderProperties2(block.LzmaProps, 5)); + } + + bool filteredMode = (block.FilterMethod == 1); + + CMyComPtr<ICompressSetOutStream> setOutStream; + + if (filteredMode) + { + if (!_bcjStream) + { + CMyComPtr<ICompressCoder> coder; + RINOK(CreateCoder(EXTERNAL_CODECS_LOC_VARS k_BCJ, coder, false)); + if (!coder) + return E_NOTIMPL; + coder.QueryInterface(IID_ISequentialOutStream, &_bcjStream); + if (!_bcjStream) + return E_NOTIMPL; + } + + _bcjStream.QueryInterface(IID_ICompressSetOutStream, &setOutStream); + if (!setOutStream) + return E_NOTIMPL; + RINOK(setOutStream->SetOutStream(outStream)); + outStream = _bcjStream; + } + + const UInt64 *unpackSize = block.HasUnpackSize() ? &block.UnpackSize : NULL; + RINOK(_lzmaDecoder->Code(inStream, outStream, NULL, unpackSize, progress)); + + if (filteredMode) + { + CMyComPtr<IOutStreamFlush> flush; + _bcjStream.QueryInterface(IID_IOutStreamFlush, &flush); + if (flush) + { + RINOK(flush->Flush()); + } + RINOK(setOutStream->ReleaseOutStream()); + } + + CMyComPtr<ICompressGetInStreamProcessedSize> getInStreamProcessedSize; + _lzmaDecoder.QueryInterface(IID_ICompressGetInStreamProcessedSize, &getInStreamProcessedSize); + if (getInStreamProcessedSize) + { + RINOK(getInStreamProcessedSize->GetInStreamProcessedSize(inProcessedSize)); + } + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.h b/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.h new file mode 100755 index 00000000..a9f4927b --- /dev/null +++ b/CPP/7zip/Archive/Lzma/LzmaFiltersDecode.h @@ -0,0 +1,26 @@ +// LzmaFiltersDecode.h + +#ifndef __LZMA_FILTERS_DECODE_H +#define __LZMA_FILTERS_DECODE_H + +#include "../../Common/CreateCoder.h" + +#include "LzmaItem.h" + +namespace NArchive { +namespace NLzma { + +class CDecoder +{ + CMyComPtr<ICompressCoder> _lzmaDecoder; + CMyComPtr<ISequentialOutStream> _bcjStream; +public: + HRESULT Code(DECL_EXTERNAL_CODECS_LOC_VARS + const CHeader &block, + ISequentialInStream *inStream, ISequentialOutStream *outStream, + UInt64 *inProcessedSize, ICompressProgressInfo *progress); +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Lzma/LzmaHandler.cpp b/CPP/7zip/Archive/Lzma/LzmaHandler.cpp new file mode 100755 index 00000000..70126aa4 --- /dev/null +++ b/CPP/7zip/Archive/Lzma/LzmaHandler.cpp @@ -0,0 +1,243 @@ +// LzmaHandler.cpp + +#include "StdAfx.h" + +#include "LzmaHandler.h" + +#include "Common/Defs.h" +#include "Common/StringConvert.h" +#include "Common/ComTry.h" +#include "Common/IntToString.h" + +#include "Windows/PropVariant.h" + +#include "../../Common/ProgressUtils.h" +#include "../../Common/StreamUtils.h" +#include "../Common/DummyOutStream.h" + +#include "LzmaFiltersDecode.h" + +namespace NArchive { +namespace NLzma { + +STATPROPSTG kProps[] = +{ + { NULL, kpidSize, VT_UI8}, + { NULL, kpidPackedSize, VT_UI8}, + { NULL, kpidMethod, VT_UI1} +}; + +IMP_IInArchive_Props +IMP_IInArchive_ArcProps_NO + +STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems) +{ + *numItems = 1; + return S_OK; +} + +static void ConvertUInt32ToString(UInt32 value, wchar_t *s) +{ + ConvertUInt64ToString(value, s + MyStringLen(s)); +} + +static void DictSizeToString(UInt32 value, wchar_t *s) +{ + for (int i = 0; i <= 31; i++) + if ((UInt32(1) << i) == value) + { + ConvertUInt32ToString(i, s); + return; + } + wchar_t c = L'b'; + if ((value & ((1 << 20) - 1)) == 0) + { + value >>= 20; + c = L'm'; + } + else if ((value & ((1 << 10) - 1)) == 0) + { + value >>= 10; + c = L'k'; + } + ConvertUInt32ToString(value, s); + int p = MyStringLen(s); + s[p++] = c; + s[p++] = L'\0'; +} + +static void MyStrCat(wchar_t *d, const wchar_t *s) +{ + MyStringCopy(d + MyStringLen(d), s); +} + +STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID, PROPVARIANT *value) +{ + if (index != 0) + return E_INVALIDARG; + NWindows::NCOM::CPropVariant propVariant; + switch(propID) + { + case kpidSize: + if (m_StreamInfo.HasUnpackSize()) + propVariant = (UInt64)m_StreamInfo.UnpackSize; + break; + case kpidPackedSize: + propVariant = (UInt64)m_PackSize; + break; + case kpidMethod: + { + wchar_t s[64]; + s[0] = '\0'; + if (m_StreamInfo.IsThereFilter) + { + const wchar_t *f; + if (m_StreamInfo.FilterMethod == 0) + f = L"Copy"; + else if (m_StreamInfo.FilterMethod == 1) + f = L"BCJ"; + else + f = L"Unknown"; + MyStrCat(s, f); + MyStrCat(s, L" "); + } + MyStrCat(s, L"LZMA:"); + DictSizeToString(m_StreamInfo.GetDicSize(), s); + propVariant = s; + break; + } + } + propVariant.Detach(value); + return S_OK; +} + +STDMETHODIMP CHandler::Open(IInStream *inStream, + const UInt64 * /* maxCheckStartPosition */, + IArchiveOpenCallback * /* openArchiveCallback */) +{ + { + RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &m_StreamStartPosition)); + + HRESULT res = ReadStreamHeader(inStream, m_StreamInfo); + if (res != S_OK) + return S_FALSE; + + Byte b; + RINOK(ReadStream_FALSE(inStream, &b, 1)); + if (b != 0) + return S_FALSE; + + UInt64 endPos; + RINOK(inStream->Seek(0, STREAM_SEEK_END, &endPos)); + m_PackSize = endPos - m_StreamStartPosition - m_StreamInfo.GetHeaderSize(); + + m_Stream = inStream; + } + return S_OK; +} + +STDMETHODIMP CHandler::Close() +{ + m_Stream.Release(); + return S_OK; +} + + +STDMETHODIMP CHandler::Extract(const UInt32* indices, UInt32 numItems, + Int32 _aTestMode, IArchiveExtractCallback *extractCallback) +{ + COM_TRY_BEGIN + bool allFilesMode = (numItems == UInt32(-1)); + if (!allFilesMode) + { + if (numItems == 0) + return S_OK; + if (numItems != 1) + return E_INVALIDARG; + if (indices[0] != 0) + return E_INVALIDARG; + } + + bool testMode = (_aTestMode != 0); + + RINOK(extractCallback->SetTotal(m_PackSize)); + + UInt64 currentTotalPacked = 0; + + CDummyOutStream *outStreamSpec = new CDummyOutStream; + CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); + + { + CMyComPtr<ISequentialOutStream> realOutStream; + Int32 askMode = testMode ? + NArchive::NExtract::NAskMode::kTest : + NArchive::NExtract::NAskMode::kExtract; + + RINOK(extractCallback->GetStream(0, &realOutStream, askMode)); + + outStreamSpec->SetStream(realOutStream); + outStreamSpec->Init(); + if(!testMode && !realOutStream) + return S_OK; + extractCallback->PrepareOperation(askMode); + } + + CLocalProgress *lps = new CLocalProgress; + CMyComPtr<ICompressProgressInfo> progress = lps; + lps->Init(extractCallback, true); + + CDecoder decoder; + RINOK(m_Stream->Seek(m_StreamStartPosition, STREAM_SEEK_SET, NULL)); + UInt64 streamPos = m_StreamStartPosition; + Int32 opRes = NArchive::NExtract::NOperationResult::kOK; + bool firstItem = true; + for (;;) + { + CHeader st; + HRESULT result = ReadStreamHeader(m_Stream, st); + if (result != S_OK) + { + if (firstItem) + return E_FAIL; + break; + } + firstItem = false; + + lps->OutSize = outStreamSpec->GetSize(); + lps->InSize = currentTotalPacked; + RINOK(lps->SetCur()); + + streamPos += st.GetHeaderSize(); + UInt64 packProcessed; + + { + result = decoder.Code( + EXTERNAL_CODECS_VARS + st, m_Stream, outStream, &packProcessed, progress); + if (result == E_NOTIMPL) + { + opRes = NArchive::NExtract::NOperationResult::kUnSupportedMethod; + break; + } + if (result == S_FALSE) + { + opRes = NArchive::NExtract::NOperationResult::kDataError; + break; + } + RINOK(result); + } + + if (packProcessed == (UInt64)(Int64)-1) + break; + RINOK(m_Stream->Seek(streamPos + packProcessed, STREAM_SEEK_SET, NULL)); + currentTotalPacked += packProcessed; + streamPos += packProcessed; + } + outStream.Release(); + return extractCallback->SetOperationResult(opRes); + COM_TRY_END +} + +IMPL_ISetCompressCodecsInfo + +}} diff --git a/CPP/7zip/Archive/Lzma/LzmaHandler.h b/CPP/7zip/Archive/Lzma/LzmaHandler.h new file mode 100755 index 00000000..e4078309 --- /dev/null +++ b/CPP/7zip/Archive/Lzma/LzmaHandler.h @@ -0,0 +1,69 @@ +// Lzma/Handler.h + +#ifndef __GZIP_HANDLER_H +#define __GZIP_HANDLER_H + +#include "Common/MyCom.h" + +#include "../IArchive.h" +#include "../../Common/CreateCoder.h" + +#include "LzmaIn.h" + +namespace NArchive { +namespace NLzma { + +// const UInt64 k_LZMA = 0x030101; + +class CHandler: + public IInArchive, + PUBLIC_ISetCompressCodecsInfo + public CMyUnknownImp +{ +public: + MY_QUERYINTERFACE_BEGIN + MY_QUERYINTERFACE_ENTRY(IInArchive) + QUERY_ENTRY_ISetCompressCodecsInfo + MY_QUERYINTERFACE_END + MY_ADDREF_RELEASE + + STDMETHOD(Open)(IInStream *inStream, + const UInt64 *maxCheckStartPosition, + IArchiveOpenCallback *openArchiveCallback); + STDMETHOD(Close)(); + + STDMETHOD(GetNumberOfItems)(UInt32 *numItems); + STDMETHOD(GetProperty)(UInt32 index, PROPID propID, PROPVARIANT *value); + STDMETHOD(Extract)(const UInt32* indices, UInt32 numItems, + Int32 testMode, IArchiveExtractCallback *extractCallback); + + STDMETHOD(GetArchiveProperty)(PROPID propID, PROPVARIANT *value); + + STDMETHOD(GetNumberOfProperties)(UInt32 *numProperties); + STDMETHOD(GetPropertyInfo)(UInt32 index, + BSTR *name, PROPID *propID, VARTYPE *varType); + + STDMETHOD(GetNumberOfArchiveProperties)(UInt32 *numProperties); + STDMETHOD(GetArchivePropertyInfo)(UInt32 index, + BSTR *name, PROPID *propID, VARTYPE *varType); + + UString GetMethodString(); +public: + CHandler() { } + +private: + CHeader m_StreamInfo; + UInt64 m_StreamStartPosition; + UInt64 m_PackSize; + + CMyComPtr<IInStream> m_Stream; + + DECL_EXTERNAL_CODECS_VARS + + DECL_ISetCompressCodecsInfo + +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Lzma/LzmaIn.cpp b/CPP/7zip/Archive/Lzma/LzmaIn.cpp new file mode 100755 index 00000000..342b01e1 --- /dev/null +++ b/CPP/7zip/Archive/Lzma/LzmaIn.cpp @@ -0,0 +1,56 @@ +// Archive/LzmaIn.cpp + +#include "StdAfx.h" + +#include "LzmaIn.h" + +#include "../../Common/StreamUtils.h" + +namespace NArchive { +namespace NLzma { + +static bool CheckDictSize(const Byte *p) +{ + UInt32 dicSize = GetUi32(p); + int i; + for (i = 1; i <= 30; i++) + if (dicSize == ((UInt32)2 << i) || dicSize == ((UInt32)3 << i)) + return true; + return false; +} + +HRESULT ReadStreamHeader(ISequentialInStream *inStream, CHeader &block) +{ + Byte sig[5 + 9]; + RINOK(ReadStream_FALSE(inStream, sig, 5 + 8)); + + const Byte kMaxProp0Val = 5 * 5 * 9 - 1; + if (sig[0] > kMaxProp0Val) + return S_FALSE; + + for (int i = 0; i < 5; i++) + block.LzmaProps[i] = sig[i]; + + block.IsThereFilter = false; + block.FilterMethod = 0; + + if (!CheckDictSize(sig + 1)) + { + if (sig[0] > 1 || sig[1] > kMaxProp0Val) + return S_FALSE; + block.IsThereFilter = true; + block.FilterMethod = sig[0]; + for (int i = 0; i < 5; i++) + block.LzmaProps[i] = sig[i + 1]; + if (!CheckDictSize(block.LzmaProps + 1)) + return S_FALSE; + RINOK(ReadStream_FALSE(inStream, sig + 5 + 8, 1)); + } + UInt32 unpOffset = 5 + (block.IsThereFilter ? 1 : 0); + block.UnpackSize = GetUi64(sig + unpOffset); + if (block.HasUnpackSize() && block.UnpackSize >= ((UInt64)1 << 56)) + return S_FALSE; + return S_OK; +} + +}} diff --git a/CPP/7zip/Archive/Lzma/LzmaIn.h b/CPP/7zip/Archive/Lzma/LzmaIn.h new file mode 100755 index 00000000..6f237f2d --- /dev/null +++ b/CPP/7zip/Archive/Lzma/LzmaIn.h @@ -0,0 +1,16 @@ +// Archive/LzmaIn.h + +#ifndef __ARCHIVE_LZMA_IN_H +#define __ARCHIVE_LZMA_IN_H + +#include "LzmaItem.h" +#include "../../IStream.h" + +namespace NArchive { +namespace NLzma { + +HRESULT ReadStreamHeader(ISequentialInStream *inStream, CHeader &st); + +}} + +#endif diff --git a/CPP/7zip/Archive/Lzma/LzmaItem.h b/CPP/7zip/Archive/Lzma/LzmaItem.h new file mode 100755 index 00000000..8fcae210 --- /dev/null +++ b/CPP/7zip/Archive/Lzma/LzmaItem.h @@ -0,0 +1,27 @@ +// Archive/LzmaItem.h + +#ifndef __ARCHIVE_LZMA_ITEM_H +#define __ARCHIVE_LZMA_ITEM_H + +#include "Common/Types.h" + +#include "../../../../C/CpuArch.h" + +namespace NArchive { +namespace NLzma { + +struct CHeader +{ + UInt64 UnpackSize; + bool IsThereFilter; + Byte FilterMethod; + Byte LzmaProps[5]; + + UInt32 GetDicSize() const { return GetUi32(LzmaProps + 1); } + bool HasUnpackSize() const { return (UnpackSize != (UInt64)(Int64)-1); } + unsigned GetHeaderSize() const { return 5 + 8 + (IsThereFilter ? 1 : 0); } +}; + +}} + +#endif diff --git a/CPP/7zip/Archive/Lzma/StdAfx.h b/CPP/7zip/Archive/Lzma/StdAfx.h new file mode 100755 index 00000000..e7fb6986 --- /dev/null +++ b/CPP/7zip/Archive/Lzma/StdAfx.h @@ -0,0 +1,8 @@ +// StdAfx.h + +#ifndef __STDAFX_H +#define __STDAFX_H + +#include "../../../Common/MyWindows.h" + +#endif diff --git a/CPP/7zip/Archive/Lzma/lzma.ico b/CPP/7zip/Archive/Lzma/lzma.ico Binary files differnew file mode 100755 index 00000000..1f4f754c --- /dev/null +++ b/CPP/7zip/Archive/Lzma/lzma.ico |