diff src/win32/7zip/7z/CPP/7zip/Archive/7z/7zDecode.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/win32/7zip/7z/CPP/7zip/Archive/7z/7zDecode.cpp	Sat Mar 03 10:31:27 2012 -0600
     1.3 @@ -0,0 +1,332 @@
     1.4 +// 7zDecode.cpp
     1.5 +
     1.6 +#include "StdAfx.h"
     1.7 +
     1.8 +#include "../../Common/LimitedStreams.h"
     1.9 +#include "../../Common/LockedStream.h"
    1.10 +#include "../../Common/ProgressUtils.h"
    1.11 +#include "../../Common/StreamObjects.h"
    1.12 +
    1.13 +#include "7zDecode.h"
    1.14 +
    1.15 +namespace NArchive {
    1.16 +namespace N7z {
    1.17 +
    1.18 +static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
    1.19 +    CBindInfoEx &bindInfo)
    1.20 +{
    1.21 +  bindInfo.Clear();
    1.22 +  int i;
    1.23 +  for (i = 0; i < folder.BindPairs.Size(); i++)
    1.24 +  {
    1.25 +    NCoderMixer::CBindPair bindPair;
    1.26 +    bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;
    1.27 +    bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;
    1.28 +    bindInfo.BindPairs.Add(bindPair);
    1.29 +  }
    1.30 +  UInt32 outStreamIndex = 0;
    1.31 +  for (i = 0; i < folder.Coders.Size(); i++)
    1.32 +  {
    1.33 +    NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
    1.34 +    const CCoderInfo &coderInfo = folder.Coders[i];
    1.35 +    coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;
    1.36 +    coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;
    1.37 +    bindInfo.Coders.Add(coderStreamsInfo);
    1.38 +    bindInfo.CoderMethodIDs.Add(coderInfo.MethodID);
    1.39 +    for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
    1.40 +      if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
    1.41 +        bindInfo.OutStreams.Add(outStreamIndex);
    1.42 +  }
    1.43 +  for (i = 0; i < folder.PackStreams.Size(); i++)
    1.44 +    bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]);
    1.45 +}
    1.46 +
    1.47 +static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,
    1.48 +    const NCoderMixer::CCoderStreamsInfo &a2)
    1.49 +{
    1.50 +  return (a1.NumInStreams == a2.NumInStreams) &&
    1.51 +    (a1.NumOutStreams == a2.NumOutStreams);
    1.52 +}
    1.53 +
    1.54 +static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2)
    1.55 +{
    1.56 +  return (a1.InIndex == a2.InIndex) &&
    1.57 +    (a1.OutIndex == a2.OutIndex);
    1.58 +}
    1.59 +
    1.60 +static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
    1.61 +{
    1.62 +  if (a1.Coders.Size() != a2.Coders.Size())
    1.63 +    return false;
    1.64 +  int i;
    1.65 +  for (i = 0; i < a1.Coders.Size(); i++)
    1.66 +    if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
    1.67 +      return false;
    1.68 +  if (a1.BindPairs.Size() != a2.BindPairs.Size())
    1.69 +    return false;
    1.70 +  for (i = 0; i < a1.BindPairs.Size(); i++)
    1.71 +    if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))
    1.72 +      return false;
    1.73 +  for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
    1.74 +    if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
    1.75 +      return false;
    1.76 +  if (a1.InStreams.Size() != a2.InStreams.Size())
    1.77 +    return false;
    1.78 +  if (a1.OutStreams.Size() != a2.OutStreams.Size())
    1.79 +    return false;
    1.80 +  return true;
    1.81 +}
    1.82 +
    1.83 +CDecoder::CDecoder(bool multiThread)
    1.84 +{
    1.85 +  #ifndef _ST_MODE
    1.86 +  multiThread = true;
    1.87 +  #endif
    1.88 +  _multiThread = multiThread;
    1.89 +  _bindInfoExPrevIsDefined = false;
    1.90 +}
    1.91 +
    1.92 +HRESULT CDecoder::Decode(
    1.93 +    DECL_EXTERNAL_CODECS_LOC_VARS
    1.94 +    IInStream *inStream,
    1.95 +    UInt64 startPos,
    1.96 +    const UInt64 *packSizes,
    1.97 +    const CFolder &folderInfo,
    1.98 +    ISequentialOutStream *outStream,
    1.99 +    ICompressProgressInfo *compressProgress
   1.100 +    #ifndef _NO_CRYPTO
   1.101 +    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
   1.102 +    #endif
   1.103 +    #ifdef COMPRESS_MT
   1.104 +    , bool mtMode, UInt32 numThreads
   1.105 +    #endif
   1.106 +    )
   1.107 +{
   1.108 +  if (!folderInfo.CheckStructure())
   1.109 +    return E_NOTIMPL;
   1.110 +  #ifndef _NO_CRYPTO
   1.111 +  passwordIsDefined = false;
   1.112 +  #endif
   1.113 +  CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
   1.114 +  
   1.115 +  CLockedInStream lockedInStream;
   1.116 +  lockedInStream.Init(inStream);
   1.117 +  
   1.118 +  for (int j = 0; j < folderInfo.PackStreams.Size(); j++)
   1.119 +  {
   1.120 +    CLockedSequentialInStreamImp *lockedStreamImpSpec = new
   1.121 +        CLockedSequentialInStreamImp;
   1.122 +    CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
   1.123 +    lockedStreamImpSpec->Init(&lockedInStream, startPos);
   1.124 +    startPos += packSizes[j];
   1.125 +    
   1.126 +    CLimitedSequentialInStream *streamSpec = new
   1.127 +        CLimitedSequentialInStream;
   1.128 +    CMyComPtr<ISequentialInStream> inStream = streamSpec;
   1.129 +    streamSpec->SetStream(lockedStreamImp);
   1.130 +    streamSpec->Init(packSizes[j]);
   1.131 +    inStreams.Add(inStream);
   1.132 +  }
   1.133 +  
   1.134 +  int numCoders = folderInfo.Coders.Size();
   1.135 +  
   1.136 +  CBindInfoEx bindInfo;
   1.137 +  ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
   1.138 +  bool createNewCoders;
   1.139 +  if (!_bindInfoExPrevIsDefined)
   1.140 +    createNewCoders = true;
   1.141 +  else
   1.142 +    createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
   1.143 +  if (createNewCoders)
   1.144 +  {
   1.145 +    int i;
   1.146 +    _decoders.Clear();
   1.147 +    // _decoders2.Clear();
   1.148 +    
   1.149 +    _mixerCoder.Release();
   1.150 +
   1.151 +    if (_multiThread)
   1.152 +    {
   1.153 +      _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT;
   1.154 +      _mixerCoder = _mixerCoderMTSpec;
   1.155 +      _mixerCoderCommon = _mixerCoderMTSpec;
   1.156 +    }
   1.157 +    else
   1.158 +    {
   1.159 +      #ifdef _ST_MODE
   1.160 +      _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST;
   1.161 +      _mixerCoder = _mixerCoderSTSpec;
   1.162 +      _mixerCoderCommon = _mixerCoderSTSpec;
   1.163 +      #endif
   1.164 +    }
   1.165 +    RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));
   1.166 +    
   1.167 +    for (i = 0; i < numCoders; i++)
   1.168 +    {
   1.169 +      const CCoderInfo &coderInfo = folderInfo.Coders[i];
   1.170 +
   1.171 +  
   1.172 +      CMyComPtr<ICompressCoder> decoder;
   1.173 +      CMyComPtr<ICompressCoder2> decoder2;
   1.174 +      RINOK(CreateCoder(
   1.175 +          EXTERNAL_CODECS_LOC_VARS
   1.176 +          coderInfo.MethodID, decoder, decoder2, false));
   1.177 +      CMyComPtr<IUnknown> decoderUnknown;
   1.178 +      if (coderInfo.IsSimpleCoder())
   1.179 +      {
   1.180 +        if (decoder == 0)
   1.181 +          return E_NOTIMPL;
   1.182 +
   1.183 +        decoderUnknown = (IUnknown *)decoder;
   1.184 +        
   1.185 +        if (_multiThread)
   1.186 +          _mixerCoderMTSpec->AddCoder(decoder);
   1.187 +        #ifdef _ST_MODE
   1.188 +        else
   1.189 +          _mixerCoderSTSpec->AddCoder(decoder, false);
   1.190 +        #endif
   1.191 +      }
   1.192 +      else
   1.193 +      {
   1.194 +        if (decoder2 == 0)
   1.195 +          return E_NOTIMPL;
   1.196 +        decoderUnknown = (IUnknown *)decoder2;
   1.197 +        if (_multiThread)
   1.198 +          _mixerCoderMTSpec->AddCoder2(decoder2);
   1.199 +        #ifdef _ST_MODE
   1.200 +        else
   1.201 +          _mixerCoderSTSpec->AddCoder2(decoder2, false);
   1.202 +        #endif
   1.203 +      }
   1.204 +      _decoders.Add(decoderUnknown);
   1.205 +      #ifdef EXTERNAL_CODECS
   1.206 +      CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
   1.207 +      decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
   1.208 +      if (setCompressCodecsInfo)
   1.209 +      {
   1.210 +        RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));
   1.211 +      }
   1.212 +      #endif
   1.213 +    }
   1.214 +    _bindInfoExPrev = bindInfo;
   1.215 +    _bindInfoExPrevIsDefined = true;
   1.216 +  }
   1.217 +  int i;
   1.218 +  _mixerCoderCommon->ReInit();
   1.219 +  
   1.220 +  UInt32 packStreamIndex = 0, unpackStreamIndex = 0;
   1.221 +  UInt32 coderIndex = 0;
   1.222 +  // UInt32 coder2Index = 0;
   1.223 +  
   1.224 +  for (i = 0; i < numCoders; i++)
   1.225 +  {
   1.226 +    const CCoderInfo &coderInfo = folderInfo.Coders[i];
   1.227 +    CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];
   1.228 +    
   1.229 +    {
   1.230 +      CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
   1.231 +      decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
   1.232 +      if (setDecoderProperties)
   1.233 +      {
   1.234 +        const CByteBuffer &props = coderInfo.Props;
   1.235 +        size_t size = props.GetCapacity();
   1.236 +        if (size > 0xFFFFFFFF)
   1.237 +          return E_NOTIMPL;
   1.238 +        if (size > 0)
   1.239 +        {
   1.240 +          RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size));
   1.241 +        }
   1.242 +      }
   1.243 +    }
   1.244 +
   1.245 +    #ifdef COMPRESS_MT
   1.246 +    if (mtMode)
   1.247 +    {
   1.248 +      CMyComPtr<ICompressSetCoderMt> setCoderMt;
   1.249 +      decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
   1.250 +      if (setCoderMt)
   1.251 +      {
   1.252 +        RINOK(setCoderMt->SetNumberOfThreads(numThreads));
   1.253 +      }
   1.254 +    }
   1.255 +    #endif
   1.256 +
   1.257 +    #ifndef _NO_CRYPTO
   1.258 +    {
   1.259 +      CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
   1.260 +      decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
   1.261 +      if (cryptoSetPassword)
   1.262 +      {
   1.263 +        if (getTextPassword == 0)
   1.264 +          return E_FAIL;
   1.265 +        CMyComBSTR passwordBSTR;
   1.266 +        RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));
   1.267 +        CByteBuffer buffer;
   1.268 +        passwordIsDefined = true;
   1.269 +        const UString password(passwordBSTR);
   1.270 +        const UInt32 sizeInBytes = password.Length() * 2;
   1.271 +        buffer.SetCapacity(sizeInBytes);
   1.272 +        for (int i = 0; i < password.Length(); i++)
   1.273 +        {
   1.274 +          wchar_t c = password[i];
   1.275 +          ((Byte *)buffer)[i * 2] = (Byte)c;
   1.276 +          ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
   1.277 +        }
   1.278 +        RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
   1.279 +      }
   1.280 +    }
   1.281 +    #endif
   1.282 +
   1.283 +    coderIndex++;
   1.284 +    
   1.285 +    UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
   1.286 +    UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
   1.287 +    CRecordVector<const UInt64 *> packSizesPointers;
   1.288 +    CRecordVector<const UInt64 *> unpackSizesPointers;
   1.289 +    packSizesPointers.Reserve(numInStreams);
   1.290 +    unpackSizesPointers.Reserve(numOutStreams);
   1.291 +    UInt32 j;
   1.292 +    for (j = 0; j < numOutStreams; j++, unpackStreamIndex++)
   1.293 +      unpackSizesPointers.Add(&folderInfo.UnpackSizes[unpackStreamIndex]);
   1.294 +    
   1.295 +    for (j = 0; j < numInStreams; j++, packStreamIndex++)
   1.296 +    {
   1.297 +      int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
   1.298 +      if (bindPairIndex >= 0)
   1.299 +        packSizesPointers.Add(
   1.300 +        &folderInfo.UnpackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]);
   1.301 +      else
   1.302 +      {
   1.303 +        int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
   1.304 +        if (index < 0)
   1.305 +          return E_FAIL;
   1.306 +        packSizesPointers.Add(&packSizes[index]);
   1.307 +      }
   1.308 +    }
   1.309 +    
   1.310 +    _mixerCoderCommon->SetCoderInfo(i,
   1.311 +        &packSizesPointers.Front(),
   1.312 +        &unpackSizesPointers.Front());
   1.313 +  }
   1.314 +  UInt32 mainCoder, temp;
   1.315 +  bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
   1.316 +
   1.317 +  if (_multiThread)
   1.318 +    _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);
   1.319 +  /*
   1.320 +  else
   1.321 +    _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
   1.322 +  */
   1.323 +  
   1.324 +  if (numCoders == 0)
   1.325 +    return 0;
   1.326 +  CRecordVector<ISequentialInStream *> inStreamPointers;
   1.327 +  inStreamPointers.Reserve(inStreams.Size());
   1.328 +  for (i = 0; i < inStreams.Size(); i++)
   1.329 +    inStreamPointers.Add(inStreams[i]);
   1.330 +  ISequentialOutStream *outStreamPointer = outStream;
   1.331 +  return _mixerCoder->Code(&inStreamPointers.Front(), NULL,
   1.332 +    inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress);
   1.333 +}
   1.334 +
   1.335 +}}