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 + -
显示快捷键?