7zhandlerout.cpp
来自「由7-zip提供的压缩、解压缩程序」· C++ 代码 · 共 1,124 行 · 第 1/2 页
CPP
1,124 行
// 7z/OutHandler.cpp#include "StdAfx.h"#include "7zHandler.h"#include "7zOut.h"#include "7zUpdate.h"#include "7zMethods.h"#include "../../../Windows/PropVariant.h"#include "../../../Common/ComTry.h"#include "../../../Common/StringToInt.h"#include "../../IPassword.h"#include "../../ICoder.h"#include "../Common/ItemNameUtils.h"#include "../Common/ParseProperties.h"using namespace NWindows;namespace NArchive {namespace N7z {#ifdef COMPRESS_LZMAstatic CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };#endif#ifdef COMPRESS_PPMDstatic CMethodID k_PPMD = { { 0x3, 0x4, 0x1 }, 3 };#endif#ifdef COMPRESS_BCJ_X86static CMethodID k_BCJ_X86 = { { 0x3, 0x3, 0x1, 0x3 }, 4 };#endif#ifdef COMPRESS_BCJ2static CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 };#endif#ifdef COMPRESS_COPYstatic CMethodID k_Copy = { { 0x0 }, 1 };#endif#ifdef COMPRESS_DEFLATE#ifndef COMPRESS_DEFLATE_ENCODER#define COMPRESS_DEFLATE_ENCODER#endif#endif#ifdef COMPRESS_DEFLATE_ENCODERstatic CMethodID k_Deflate = { { 0x4, 0x1, 0x8 }, 3 };#endif#ifdef COMPRESS_BZIP2#ifndef COMPRESS_BZIP2_ENCODER#define COMPRESS_BZIP2_ENCODER#endif#endif#ifdef COMPRESS_BZIP2_ENCODERstatic CMethodID k_BZip2 = { { 0x4, 0x2, 0x2 }, 3 };#endifconst wchar_t *kCopyMethod = L"Copy";const wchar_t *kLZMAMethodName = L"LZMA";const wchar_t *kBZip2MethodName = L"BZip2";const wchar_t *kPpmdMethodName = L"PPMd";const wchar_t *kDeflateMethodName = L"Deflate";const wchar_t *kDeflate64MethodName = L"Deflate64";static const wchar_t *kLzmaMatchFinderX1 = L"HC4";static const wchar_t *kLzmaMatchFinderX5 = L"BT4";static const UInt32 kLzmaAlgorithmX1 = 0;static const UInt32 kLzmaAlgorithmX5 = 1;static const UInt32 kLzmaDicSizeX1 = 1 << 16;static const UInt32 kLzmaDicSizeX3 = 1 << 20;static const UInt32 kLzmaDicSizeX5 = 1 << 22;static const UInt32 kLzmaDicSizeX7 = 1 << 24;static const UInt32 kLzmaDicSizeX9 = 1 << 26;static const UInt32 kLzmaFastBytesX1 = 32;static const UInt32 kLzmaFastBytesX7 = 64;static const UInt32 kPpmdMemSizeX1 = (1 << 22);static const UInt32 kPpmdMemSizeX5 = (1 << 24);static const UInt32 kPpmdMemSizeX7 = (1 << 26);static const UInt32 kPpmdMemSizeX9 = (192 << 20);static const UInt32 kPpmdOrderX1 = 4;static const UInt32 kPpmdOrderX5 = 6;static const UInt32 kPpmdOrderX7 = 16;static const UInt32 kPpmdOrderX9 = 32;static const UInt32 kDeflateFastBytesX1 = 32;static const UInt32 kDeflateFastBytesX7 = 64;static const UInt32 kDeflateFastBytesX9 = 128;static const UInt32 kDeflatePassesX1 = 1;static const UInt32 kDeflatePassesX7 = 3;static const UInt32 kDeflatePassesX9 = 10;static const UInt32 kBZip2NumPassesX1 = 1;static const UInt32 kBZip2NumPassesX7 = 2;static const UInt32 kBZip2NumPassesX9 = 7;static const UInt32 kBZip2DicSizeX1 = 100000;static const UInt32 kBZip2DicSizeX3 = 500000;static const UInt32 kBZip2DicSizeX5 = 900000;const wchar_t *kDefaultMethodName = kLZMAMethodName;static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";static const UInt32 kDictionaryForHeaders = 1 << 20;static const UInt32 kNumFastBytesForHeaders = 273;static const UInt32 kAlgorithmForHeaders = kLzmaAlgorithmX5;static bool IsCopyMethod(const UString &methodName) { return (methodName.CompareNoCase(kCopyMethod) == 0); }static bool IsLZMAMethod(const UString &methodName) { return (methodName.CompareNoCase(kLZMAMethodName) == 0); }static bool IsLZMethod(const UString &methodName) { return IsLZMAMethod(methodName); }static bool IsBZip2Method(const UString &methodName) { return (methodName.CompareNoCase(kBZip2MethodName) == 0); }static bool IsPpmdMethod(const UString &methodName) { return (methodName.CompareNoCase(kPpmdMethodName) == 0); }static bool IsDeflateMethod(const UString &methodName) { return (methodName.CompareNoCase(kDeflateMethodName) == 0) || (methodName.CompareNoCase(kDeflate64MethodName) == 0); }STDMETHODIMP CHandler::GetFileTimeType(UInt32 *type){ *type = NFileTimeType::kWindows; return S_OK;}HRESULT CHandler::SetPassword(CCompressionMethodMode &methodMode, IArchiveUpdateCallback *updateCallback){ CMyComPtr<ICryptoGetTextPassword2> getTextPassword; if (!getTextPassword) { CMyComPtr<IArchiveUpdateCallback> udateCallback2(updateCallback); udateCallback2.QueryInterface(IID_ICryptoGetTextPassword2, &getTextPassword); } if (getTextPassword) { CMyComBSTR password; Int32 passwordIsDefined; RINOK(getTextPassword->CryptoGetTextPassword2( &passwordIsDefined, &password)); if (methodMode.PasswordIsDefined = IntToBool(passwordIsDefined)) methodMode.Password = password; } else methodMode.PasswordIsDefined = false; return S_OK;}struct CNameToPropID{ PROPID PropID; VARTYPE VarType; const wchar_t *Name;};CNameToPropID g_NameToPropID[] = { { NCoderPropID::kOrder, VT_UI4, L"O" }, { NCoderPropID::kPosStateBits, VT_UI4, L"PB" }, { NCoderPropID::kLitContextBits, VT_UI4, L"LC" }, { NCoderPropID::kLitPosBits, VT_UI4, L"LP" }, { NCoderPropID::kNumPasses, VT_UI4, L"Pass" }, { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" }, { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" }, { NCoderPropID::kAlgorithm, VT_UI4, L"a" }, { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" }, { NCoderPropID::kNumThreads, VT_UI4, L"mt" }};bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp){ if (varType == srcProp.vt) { destProp = srcProp; return true; } if (varType == VT_UI1) { if(srcProp.vt == VT_UI4) { UInt32 value = srcProp.ulVal; if (value > 0xFF) return false; destProp = Byte(value); return true; } } return false;} const int kNumNameToPropIDItems = sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]);int FindPropIdFromStringName(const UString &name){ for (int i = 0; i < kNumNameToPropIDItems; i++) if (name.CompareNoCase(g_NameToPropID[i].Name) == 0) return i; return -1;}HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CCompressionMethodMode &headerMethod){ HRESULT res = SetCompressionMethod(methodMode, _methods #ifdef COMPRESS_MT , _numThreads #endif ); RINOK(res); methodMode.Binds = _binds; if (_compressHeadersFull) _compressHeaders = true; if (_compressHeaders) { // headerMethod.Methods.Add(methodMode.Methods.Back()); CObjectVector<COneMethodInfo> headerMethodInfoVector; COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = kLZMAMethodName; { CProperty property; property.PropID = NCoderPropID::kMatchFinder; property.Value = kLzmaMatchFinderForHeaders; oneMethodInfo.CoderProperties.Add(property); } { CProperty property; property.PropID = NCoderPropID::kAlgorithm; property.Value = kAlgorithmForHeaders; oneMethodInfo.CoderProperties.Add(property); } { CProperty property; property.PropID = NCoderPropID::kNumFastBytes; property.Value = UInt32(kNumFastBytesForHeaders); oneMethodInfo.CoderProperties.Add(property); } { CProperty property; property.PropID = NCoderPropID::kDictionarySize; property.Value = UInt32(kDictionaryForHeaders); oneMethodInfo.CoderProperties.Add(property); } headerMethodInfoVector.Add(oneMethodInfo); HRESULT res = SetCompressionMethod(headerMethod, headerMethodInfoVector #ifdef COMPRESS_MT ,1 #endif ); RINOK(res); } return S_OK;}static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID, const NWindows::NCOM::CPropVariant &value){ int j; for (j = 0; j < oneMethodInfo.CoderProperties.Size(); j++) if (oneMethodInfo.CoderProperties[j].PropID == propID) break; if (j != oneMethodInfo.CoderProperties.Size()) return; CProperty property; property.PropID = propID; property.Value = value; oneMethodInfo.CoderProperties.Add(property);}HRESULT CHandler::SetCompressionMethod( CCompressionMethodMode &methodMode, CObjectVector<COneMethodInfo> &methodsInfo #ifdef COMPRESS_MT , UInt32 numThreads #endif ){ #ifndef EXCLUDE_COM /* CObjectVector<CMethodInfo2> methodInfoVector; if (!NRegistryInfo::EnumerateAllMethods(methodInfoVector)) return E_FAIL; */ #endif UInt32 level = _level; if (methodsInfo.IsEmpty()) { COneMethodInfo oneMethodInfo; oneMethodInfo.MethodName = ((level == 0) ? kCopyMethod : kDefaultMethodName); methodsInfo.Add(oneMethodInfo); } bool needSolid = false; for(int i = 0; i < methodsInfo.Size(); i++) { COneMethodInfo &oneMethodInfo = methodsInfo[i]; if (oneMethodInfo.MethodName.IsEmpty()) oneMethodInfo.MethodName = kDefaultMethodName; if (!IsCopyMethod(oneMethodInfo.MethodName)) needSolid = true; if (IsLZMAMethod(oneMethodInfo.MethodName)) { UInt32 dicSize = (level >= 9 ? kLzmaDicSizeX9 : (level >= 7 ? kLzmaDicSizeX7 : (level >= 5 ? kLzmaDicSizeX5 : (level >= 3 ? kLzmaDicSizeX3 : kLzmaDicSizeX1)))); UInt32 algorithm = (level >= 5 ? kLzmaAlgorithmX5 : kLzmaAlgorithmX1); UInt32 fastBytes = (level >= 7 ? kLzmaFastBytesX7 : kLzmaFastBytesX1); const wchar_t *matchFinder = (level >= 5 ? kLzmaMatchFinderX5 : kLzmaMatchFinderX1); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algorithm); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsDeflateMethod(oneMethodInfo.MethodName)) { UInt32 fastBytes = (level >= 9 ? kDeflateFastBytesX9 : (level >= 7 ? kDeflateFastBytesX7 : kDeflateFastBytesX1)); UInt32 numPasses = (level >= 9 ? kDeflatePassesX9 : (level >= 7 ? kDeflatePassesX7 : kDeflatePassesX1)); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); } else if (IsBZip2Method(oneMethodInfo.MethodName)) { UInt32 numPasses = (level >= 9 ? kBZip2NumPassesX9 : (level >= 7 ? kBZip2NumPassesX7 : kBZip2NumPassesX1)); UInt32 dicSize = (level >= 5 ? kBZip2DicSizeX5 : (level >= 3 ? kBZip2DicSizeX3 : kBZip2DicSizeX1)); SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses); SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize); #ifdef COMPRESS_MT SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif } else if (IsPpmdMethod(oneMethodInfo.MethodName)) { UInt32 useMemSize = (level >= 9 ? kPpmdMemSizeX9 : (level >= 7 ? kPpmdMemSizeX7 : (level >= 5 ? kPpmdMemSizeX5 : kPpmdMemSizeX1))); UInt32 order = (level >= 9 ? kPpmdOrderX9 : (level >= 7 ? kPpmdOrderX7 : (level >= 5 ? kPpmdOrderX5 : kPpmdOrderX1))); SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize); SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order); } CMethodFull methodFull; methodFull.NumInStreams = 1; methodFull.NumOutStreams = 1; bool defined = false; #ifdef COMPRESS_LZMA if (oneMethodInfo.MethodName.CompareNoCase(L"LZMA") == 0) { defined = true; methodFull.MethodID = k_LZMA; } #endif #ifdef COMPRESS_PPMD if (oneMethodInfo.MethodName.CompareNoCase(L"PPMD") == 0) { defined = true; methodFull.MethodID = k_PPMD; } #endif #ifdef COMPRESS_BCJ_X86 if (oneMethodInfo.MethodName.CompareNoCase(L"BCJ") == 0) { defined = true; methodFull.MethodID = k_BCJ_X86; } #endif #ifdef COMPRESS_BCJ2 if (oneMethodInfo.MethodName.CompareNoCase(L"BCJ2") == 0) { defined = true; methodFull.MethodID = k_BCJ2; methodFull.NumInStreams = 4; methodFull.NumOutStreams = 1; } #endif #ifdef COMPRESS_DEFLATE_ENCODER if (oneMethodInfo.MethodName.CompareNoCase(L"Deflate") == 0) { defined = true; methodFull.MethodID = k_Deflate; } #endif #ifdef COMPRESS_BZIP2_ENCODER if (oneMethodInfo.MethodName.CompareNoCase(L"BZip2") == 0) { defined = true; methodFull.MethodID = k_BZip2; } #endif #ifdef COMPRESS_COPY if (oneMethodInfo.MethodName.CompareNoCase(L"Copy") == 0) { defined = true; methodFull.MethodID = k_Copy; } #endif #ifdef EXCLUDE_COM if (defined) { methodFull.CoderProperties = oneMethodInfo.CoderProperties; methodMode.Methods.Add(methodFull); continue; } #else CMethodInfo2 methodInfo; if (!GetMethodInfo(oneMethodInfo.MethodName, methodInfo)) return E_FAIL; if (!methodInfo.EncoderIsAssigned) return E_FAIL; methodFull.MethodID = methodInfo.MethodID; methodFull.NumInStreams = methodInfo.NumInStreams; methodFull.NumOutStreams = methodInfo.NumOutStreams; methodFull.EncoderClassID = methodInfo.Encoder; methodFull.FilePath = methodInfo.FilePath; methodFull.CoderProperties = oneMethodInfo.CoderProperties; defined = true; #endif if (!defined) return E_FAIL; methodMode.Methods.Add(methodFull); if (!_numSolidBytesDefined) { for (int j = 0; j < methodFull.CoderProperties.Size(); j++) { const CProperty &prop = methodFull.CoderProperties[j]; if ((prop.PropID == NCoderPropID::kDictionarySize || prop.PropID == NCoderPropID::kUsedMemorySize) && prop.Value.vt == VT_UI4) { _numSolidBytes = ((UInt64)prop.Value.ulVal) << 7; const UInt64 kMinSize = (1 << 24); if (_numSolidBytes < kMinSize) _numSolidBytes = kMinSize; _numSolidBytesDefined = true; break; } } } } if (!needSolid && !_numSolidBytesDefined) { _numSolidBytesDefined = true; _numSolidBytes = 0; } return S_OK;}STDMETHODIMP CHandler::UpdateItems(ISequentialOutStream *outStream, UInt32 numItems, IArchiveUpdateCallback *updateCallback){ COM_TRY_BEGIN const CArchiveDatabaseEx *database = 0; #ifdef _7Z_VOL if(_volumes.Size() > 1) return E_FAIL; const CVolume *volume = 0; if (_volumes.Size() == 1) { volume = &_volumes.Front(); database = &volume->Database; } #else if (_inStream != 0) database = &_database; #endif // CRecordVector<bool> compressStatuses; CObjectVector<CUpdateItem> updateItems; // CRecordVector<UInt32> copyIndices; // CMyComPtr<IUpdateCallback2> updateCallback2; // updateCallback->QueryInterface(&updateCallback2); for(UInt32 i = 0; i < numItems; i++)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?