⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 handlerout.cpp

📁 一个7ZIP的解压源码。比较详细。里面含有四种语言的实现代码。
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// HandlerOutCommon.cpp

#include "StdAfx.h"

#include "HandlerOut.h"
#include "../../../Windows/PropVariant.h"
#include "../../../Common/StringToInt.h"
#include "../../ICoder.h"
#include "../Common/ParseProperties.h"

#ifdef COMPRESS_MT
#include "../../../Windows/System.h"
#endif

using namespace NWindows;

namespace NArchive {

static const wchar_t *kCopyMethod = L"Copy";
static const wchar_t *kLZMAMethodName = L"LZMA";
static const wchar_t *kLZMA2MethodName = L"LZMA2";
static const wchar_t *kBZip2MethodName = L"BZip2";
static const wchar_t *kPpmdMethodName = L"PPMd";
static const wchar_t *kDeflateMethodName = L"Deflate";
static const wchar_t *kDeflate64MethodName = L"Deflate64";

static const wchar_t *kLzmaMatchFinderX1 = L"HC4";
static const wchar_t *kLzmaMatchFinderX5 = L"BT4";

static const UInt32 kLzmaAlgoX1 = 0;
static const UInt32 kLzmaAlgoX5 = 1;

static const UInt32 kLzmaDicSizeX1 = 1 << 16;
static const UInt32 kLzmaDicSizeX3 = 1 << 20;
static const UInt32 kLzmaDicSizeX5 = 1 << 24;
static const UInt32 kLzmaDicSizeX7 = 1 << 25;
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 kDeflateAlgoX1 = 0;
static const UInt32 kDeflateAlgoX5 = 1;

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;

static 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 = kLzmaAlgoX5;

static bool AreEqual(const UString &methodName, const wchar_t *s)
  { return (methodName.CompareNoCase(s) == 0); }

static inline bool IsLZMAMethod(const UString &methodName)
{ 
  return 
    AreEqual(methodName, kLZMAMethodName) || 
    AreEqual(methodName, kLZMA2MethodName); 
}

static inline bool IsBZip2Method(const UString &methodName)
  { return AreEqual(methodName, kBZip2MethodName); }

static inline bool IsPpmdMethod(const UString &methodName)
  { return AreEqual(methodName, kPpmdMethodName); }

static inline bool IsDeflateMethod(const UString &methodName)
{ 
  return 
    AreEqual(methodName, kDeflateMethodName) || 
    AreEqual(methodName, kDeflate64MethodName); 
}

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::kEndMarker, VT_BOOL, L"eos" },

  { 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" }
};

static 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;
    }
  }
  else if (varType == VT_BOOL)
  {
    bool res;
    if (SetBoolProperty(res, srcProp) != S_OK)
      return false;
    destProp = res;
    return true;
  }
  return false;
}
    
static int FindPropIdFromStringName(const UString &name)
{
  for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)
    if (name.CompareNoCase(g_NameToPropID[i].Name) == 0)
      return i;
  return -1;
}

static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID, 
    const NWindows::NCOM::CPropVariant &value)
{
  for (int j = 0; j < oneMethodInfo.Properties.Size(); j++)
    if (oneMethodInfo.Properties[j].Id == propID)
      return;
  CProp property;
  property.Id = propID;
  property.Value = value;
  oneMethodInfo.Properties.Add(property);
}

void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
    #ifdef COMPRESS_MT
    , UInt32 numThreads
    #endif
    )
{
  UInt32 level = _level;
  if (oneMethodInfo.MethodName.IsEmpty())
    oneMethodInfo.MethodName = kDefaultMethodName;
  
  if (IsLZMAMethod(oneMethodInfo.MethodName))
  {
    UInt32 dicSize = 
      (level >= 9 ? kLzmaDicSizeX9 : 
      (level >= 7 ? kLzmaDicSizeX7 : 
      (level >= 5 ? kLzmaDicSizeX5 : 
      (level >= 3 ? kLzmaDicSizeX3 : 
                    kLzmaDicSizeX1)))); 
    
    UInt32 algo = 
      (level >= 5 ? kLzmaAlgoX5 : 
                    kLzmaAlgoX1); 
    
    UInt32 fastBytes = 
      (level >= 7 ? kLzmaFastBytesX7 : 
                    kLzmaFastBytesX1); 
    
    const wchar_t *matchFinder = 
      (level >= 5 ? kLzmaMatchFinderX5 : 
                    kLzmaMatchFinderX1); 
    
    SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
    SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
    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));
    
    UInt32 algo = 
      (level >= 5 ? kDeflateAlgoX5 : 
                    kDeflateAlgoX1); 
    
    SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
    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);
  }
}

static void SplitParams(const UString &srcString, UStringVector &subStrings)
{
  subStrings.Clear();
  UString name;
  int len = srcString.Length();
  if (len == 0)
    return;
  for (int i = 0; i < len; i++)
  {
    wchar_t c = srcString[i];
    if (c == L':')
    {
      subStrings.Add(name);
      name.Empty();
    }
    else
      name += c;
  }
  subStrings.Add(name);
}

static void SplitParam(const UString &param, UString &name, UString &value)
{
  int eqPos = param.Find(L'=');
  if (eqPos >= 0)
  {
    name = param.Left(eqPos);
    value = param.Mid(eqPos + 1);
    return;
  }
  for(int i = 0; i < param.Length(); i++)
  {
    wchar_t c = param[i];
    if (c >= L'0' && c <= L'9')
    {
      name = param.Left(i);
      value = param.Mid(i);
      return;
    }
  }
  name = param;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -