7zencode.cpp

来自「由7-zip提供的压缩、解压缩程序」· C++ 代码 · 共 613 行 · 第 1/2 页

CPP
613
字号
// Encode.cpp#include "StdAfx.h"#include "7zEncode.h"#include "7zSpecStream.h"#include "7zMethods.h"#include "../../IPassword.h"#include "../../Common/ProgressUtils.h"#include "../../Common/LimitedStreams.h"#include "../../Common/InOutTempBuffer.h"#include "../../Common/StreamObjects.h"#include "../Common/FilterCoder.h"#ifdef COMPRESS_COPYstatic NArchive::N7z::CMethodID k_Copy = { { 0x0 }, 1 };#include "../../Compress/Copy/CopyCoder.h"#endifstatic NArchive::N7z::CMethodID k_LZMA = { { 0x3, 0x1, 0x1 }, 3 };#ifdef COMPRESS_LZMA#include "../../Compress/LZMA/LZMAEncoder.h"#endif#ifdef COMPRESS_PPMD#include "../../Compress/PPMD/PPMDEncoder.h"static NArchive::N7z::CMethodID k_PPMD = { { 0x3, 0x4, 0x1 }, 3 };#endif#ifdef COMPRESS_BCJ_X86static NArchive::N7z::CMethodID k_BCJ_X86 = { { 0x3, 0x3, 0x1, 0x3 }, 4 };#include "../../Compress/Branch/x86.h"#endif#ifdef COMPRESS_BCJ2static NArchive::N7z::CMethodID k_BCJ2 = { { 0x3, 0x3, 0x1, 0x1B }, 4 };#include "../../Compress/Branch/x86_2.h"#endif#ifdef COMPRESS_DEFLATE#ifndef COMPRESS_DEFLATE_ENCODER#define COMPRESS_DEFLATE_ENCODER#endif#endif#ifdef COMPRESS_DEFLATE_ENCODER#include "../../Compress/Deflate/DeflateEncoder.h"static NArchive::N7z::CMethodID k_Deflate = { { 0x4, 0x1, 0x8 }, 3 };#endif#ifdef COMPRESS_BZIP2#ifndef COMPRESS_BZIP2_ENCODER#define COMPRESS_BZIP2_ENCODER#endif#endif#ifdef COMPRESS_BZIP2_ENCODER#include "../../Compress/BZip2/BZip2Encoder.h"static NArchive::N7z::CMethodID k_BZip2 = { { 0x4, 0x2, 0x2 }, 3 };#endifstatic NArchive::N7z::CMethodID k_AES = { { 0x6, 0xF1, 0x7, 0x1}, 4 };#ifndef EXCLUDE_COMstatic const wchar_t *kCryproMethod = L"7zAES";/*// {23170F69-40C1-278B-06F1-070100000100}DEFINE_GUID(CLSID_CCrypto7zAESEncoder, 0x23170F69, 0x40C1, 0x278B, 0x06, 0xF1, 0x07, 0x01, 0x00, 0x00, 0x01, 0x00);*/#endif#ifdef CRYPTO_7ZAES#include "../../Crypto/7zAES/7zAES.h"#endifnamespace NArchive {namespace N7z {static void ConvertBindInfoToFolderItemInfo(const NCoderMixer2::CBindInfo &bindInfo,    const CRecordVector<CMethodID> decompressionMethods,    CFolder &folder){  folder.Coders.Clear();  // bindInfo.CoderMethodIDs.Clear();  // folder.OutStreams.Clear();  folder.PackStreams.Clear();  folder.BindPairs.Clear();  int i;  for (i = 0; i < bindInfo.BindPairs.Size(); i++)  {    CBindPair bindPair;    bindPair.InIndex = bindInfo.BindPairs[i].InIndex;    bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex;    folder.BindPairs.Add(bindPair);  }  for (i = 0; i < bindInfo.Coders.Size(); i++)  {    CCoderInfo coderInfo;    const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];    coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;    coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;        // coderInfo.MethodID = decompressionMethods[i];    // if (coderInfo.AltCoders.Size() == 0)    coderInfo.AltCoders.Add(CAltCoderInfo());    CAltCoderInfo &altCoderInfo = coderInfo.AltCoders.Front();    altCoderInfo.MethodID = decompressionMethods[i];    folder.Coders.Add(coderInfo);  }  for (i = 0; i < bindInfo.InStreams.Size(); i++)    folder.PackStreams.Add(bindInfo.InStreams[i]);}HRESULT CEncoder::CreateMixerCoder(const UInt64 *inSizeForReduce){  _mixerCoderSpec = new NCoderMixer2::CCoderMixer2MT;  _mixerCoder = _mixerCoderSpec;  _mixerCoderSpec->SetBindInfo(_bindInfo);  for (int i = 0; i < _options.Methods.Size(); i++)  {    const CMethodFull &methodFull = _options.Methods[i];    _codersInfo.Add(CCoderInfo());    CCoderInfo &encodingInfo = _codersInfo.Back();    CMyComPtr<ICompressCoder> encoder;    CMyComPtr<ICompressFilter> filter;    CMyComPtr<ICompressCoder2> encoder2;        if (methodFull.IsSimpleCoder())    {      #ifdef COMPRESS_LZMA      if (methodFull.MethodID == k_LZMA)        encoder = new NCompress::NLZMA::CEncoder;      #endif            #ifdef COMPRESS_PPMD      if (methodFull.MethodID == k_PPMD)        encoder = new NCompress::NPPMD::CEncoder;      #endif            #ifdef COMPRESS_BCJ_X86      if (methodFull.MethodID == k_BCJ_X86)        filter = new CBCJ_x86_Encoder;      #endif            #ifdef COMPRESS_COPY      if (methodFull.MethodID == k_Copy)        encoder = new NCompress::CCopyCoder;      #endif            #ifdef COMPRESS_BZIP2_ENCODER      if (methodFull.MethodID == k_BZip2)        encoder = new NCompress::NBZip2::CEncoder;      #endif            #ifdef COMPRESS_DEFLATE_ENCODER      if (methodFull.MethodID == k_Deflate)        encoder = new NCompress::NDeflate::NEncoder::CCOMCoder;      #endif            #ifdef CRYPTO_7ZAES      if (methodFull.MethodID == k_AES)        filter = new NCrypto::NSevenZ::CEncoder;      #endif      if (filter)      {        CFilterCoder *coderSpec = new CFilterCoder;        encoder = coderSpec;        coderSpec->Filter = filter;      }      #ifndef EXCLUDE_COM      if (encoder == 0)      {        RINOK(_libraries.CreateCoderSpec(methodFull.FilePath,               methodFull.EncoderClassID, &encoder));      }      #endif            if (encoder == 0)        return E_FAIL;          }    else    {      #ifdef COMPRESS_BCJ2      if (methodFull.MethodID == k_BCJ2)        encoder2 = new CBCJ2_x86_Encoder;      #endif            #ifndef EXCLUDE_COM      if (encoder2 == 0)      {        RINOK(_libraries.CreateCoder2(methodFull.FilePath,               methodFull.EncoderClassID, &encoder2));      }      #else            if (encoder2 == 0)        return E_FAIL;      #endif    }    bool tryReduce = false;    UInt32 reducedDictionarySize = 1 << 10;    if (inSizeForReduce != 0 && methodFull.MethodID == k_LZMA)    {      while (true)      {        const UInt32 step = (reducedDictionarySize >> 1);        if (reducedDictionarySize >= *inSizeForReduce)        {          tryReduce = true;          break;        }        reducedDictionarySize += step;        if (reducedDictionarySize >= *inSizeForReduce)        {          tryReduce = true;          break;        }        if (reducedDictionarySize >= ((UInt32)11 << 30))          break;        reducedDictionarySize += step;      }    }    CMyComPtr<IUnknown> encoderCommon = methodFull.IsSimpleCoder() ? (IUnknown *)encoder : (IUnknown *)encoder2;       #ifdef COMPRESS_MT    {      CMyComPtr<ICompressSetCoderMt> setCoderMt;      encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);      if (setCoderMt)      {        RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads));      }    }    #endif            if (methodFull.CoderProperties.Size() > 0)    {      CRecordVector<PROPID> propIDs;      int numProperties = methodFull.CoderProperties.Size();      NWindows::NCOM::CPropVariant *values = new NWindows::NCOM::CPropVariant[numProperties];      try      {        for (int i = 0; i < numProperties; i++)        {          const CProperty &property = methodFull.CoderProperties[i];          propIDs.Add(property.PropID);          NWindows::NCOM::CPropVariant value = property.Value;          if (tryReduce && property.PropID == NCoderPropID::kDictionarySize && value.vt == VT_UI4 && reducedDictionarySize < value.ulVal)            value.ulVal = reducedDictionarySize;          values[i] = value;        }        CMyComPtr<ICompressSetCoderProperties> setCoderProperties;        RINOK(encoderCommon.QueryInterface(IID_ICompressSetCoderProperties, &setCoderProperties));        RINOK(setCoderProperties->SetCoderProperties(&propIDs.Front(), values, numProperties));      }      catch(...)      {        delete []values;        throw;      }      delete []values;    }        CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;        encoderCommon.QueryInterface(IID_ICompressWriteCoderProperties, &writeCoderProperties);        if (writeCoderProperties != NULL)    {      CSequentialOutStreamImp *outStreamSpec = new CSequentialOutStreamImp;      CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);      outStreamSpec->Init();      writeCoderProperties->WriteCoderProperties(outStream);            size_t size = outStreamSpec->GetSize();            // encodingInfo.Properties.SetCapacity(size);      if (encodingInfo.AltCoders.Size() == 0)        encodingInfo.AltCoders.Add(CAltCoderInfo());      CAltCoderInfo &altCoderInfo = encodingInfo.AltCoders.Front();      altCoderInfo.Properties.SetCapacity(size);            memmove(altCoderInfo.Properties, outStreamSpec->GetBuffer(), size);    }        CMyComPtr<ICryptoSetPassword> cryptoSetPassword;    encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);    if (cryptoSetPassword)    {      CByteBuffer buffer;      const UInt32 sizeInBytes = _options.Password.Length() * 2;      buffer.SetCapacity(sizeInBytes);      for (int i = 0; i < _options.Password.Length(); i++)      {        wchar_t c = _options.Password[i];        ((Byte *)buffer)[i * 2] = (Byte)c;        ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);

⌨️ 快捷键说明

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