Mercurial > vba-linux
view 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 source
1 // 7zDecode.cpp3 #include "StdAfx.h"5 #include "../../Common/LimitedStreams.h"6 #include "../../Common/LockedStream.h"7 #include "../../Common/ProgressUtils.h"8 #include "../../Common/StreamObjects.h"10 #include "7zDecode.h"12 namespace NArchive {13 namespace N7z {15 static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,16 CBindInfoEx &bindInfo)17 {18 bindInfo.Clear();19 int i;20 for (i = 0; i < folder.BindPairs.Size(); i++)21 {22 NCoderMixer::CBindPair bindPair;23 bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;24 bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;25 bindInfo.BindPairs.Add(bindPair);26 }27 UInt32 outStreamIndex = 0;28 for (i = 0; i < folder.Coders.Size(); i++)29 {30 NCoderMixer::CCoderStreamsInfo coderStreamsInfo;31 const CCoderInfo &coderInfo = folder.Coders[i];32 coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;33 coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;34 bindInfo.Coders.Add(coderStreamsInfo);35 bindInfo.CoderMethodIDs.Add(coderInfo.MethodID);36 for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)37 if (folder.FindBindPairForOutStream(outStreamIndex) < 0)38 bindInfo.OutStreams.Add(outStreamIndex);39 }40 for (i = 0; i < folder.PackStreams.Size(); i++)41 bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]);42 }44 static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,45 const NCoderMixer::CCoderStreamsInfo &a2)46 {47 return (a1.NumInStreams == a2.NumInStreams) &&48 (a1.NumOutStreams == a2.NumOutStreams);49 }51 static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2)52 {53 return (a1.InIndex == a2.InIndex) &&54 (a1.OutIndex == a2.OutIndex);55 }57 static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)58 {59 if (a1.Coders.Size() != a2.Coders.Size())60 return false;61 int i;62 for (i = 0; i < a1.Coders.Size(); i++)63 if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))64 return false;65 if (a1.BindPairs.Size() != a2.BindPairs.Size())66 return false;67 for (i = 0; i < a1.BindPairs.Size(); i++)68 if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))69 return false;70 for (i = 0; i < a1.CoderMethodIDs.Size(); i++)71 if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])72 return false;73 if (a1.InStreams.Size() != a2.InStreams.Size())74 return false;75 if (a1.OutStreams.Size() != a2.OutStreams.Size())76 return false;77 return true;78 }80 CDecoder::CDecoder(bool multiThread)81 {82 #ifndef _ST_MODE83 multiThread = true;84 #endif85 _multiThread = multiThread;86 _bindInfoExPrevIsDefined = false;87 }89 HRESULT CDecoder::Decode(90 DECL_EXTERNAL_CODECS_LOC_VARS91 IInStream *inStream,92 UInt64 startPos,93 const UInt64 *packSizes,94 const CFolder &folderInfo,95 ISequentialOutStream *outStream,96 ICompressProgressInfo *compressProgress97 #ifndef _NO_CRYPTO98 , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined99 #endif100 #ifdef COMPRESS_MT101 , bool mtMode, UInt32 numThreads102 #endif103 )104 {105 if (!folderInfo.CheckStructure())106 return E_NOTIMPL;107 #ifndef _NO_CRYPTO108 passwordIsDefined = false;109 #endif110 CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;112 CLockedInStream lockedInStream;113 lockedInStream.Init(inStream);115 for (int j = 0; j < folderInfo.PackStreams.Size(); j++)116 {117 CLockedSequentialInStreamImp *lockedStreamImpSpec = new118 CLockedSequentialInStreamImp;119 CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;120 lockedStreamImpSpec->Init(&lockedInStream, startPos);121 startPos += packSizes[j];123 CLimitedSequentialInStream *streamSpec = new124 CLimitedSequentialInStream;125 CMyComPtr<ISequentialInStream> inStream = streamSpec;126 streamSpec->SetStream(lockedStreamImp);127 streamSpec->Init(packSizes[j]);128 inStreams.Add(inStream);129 }131 int numCoders = folderInfo.Coders.Size();133 CBindInfoEx bindInfo;134 ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);135 bool createNewCoders;136 if (!_bindInfoExPrevIsDefined)137 createNewCoders = true;138 else139 createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);140 if (createNewCoders)141 {142 int i;143 _decoders.Clear();144 // _decoders2.Clear();146 _mixerCoder.Release();148 if (_multiThread)149 {150 _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT;151 _mixerCoder = _mixerCoderMTSpec;152 _mixerCoderCommon = _mixerCoderMTSpec;153 }154 else155 {156 #ifdef _ST_MODE157 _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST;158 _mixerCoder = _mixerCoderSTSpec;159 _mixerCoderCommon = _mixerCoderSTSpec;160 #endif161 }162 RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));164 for (i = 0; i < numCoders; i++)165 {166 const CCoderInfo &coderInfo = folderInfo.Coders[i];169 CMyComPtr<ICompressCoder> decoder;170 CMyComPtr<ICompressCoder2> decoder2;171 RINOK(CreateCoder(172 EXTERNAL_CODECS_LOC_VARS173 coderInfo.MethodID, decoder, decoder2, false));174 CMyComPtr<IUnknown> decoderUnknown;175 if (coderInfo.IsSimpleCoder())176 {177 if (decoder == 0)178 return E_NOTIMPL;180 decoderUnknown = (IUnknown *)decoder;182 if (_multiThread)183 _mixerCoderMTSpec->AddCoder(decoder);184 #ifdef _ST_MODE185 else186 _mixerCoderSTSpec->AddCoder(decoder, false);187 #endif188 }189 else190 {191 if (decoder2 == 0)192 return E_NOTIMPL;193 decoderUnknown = (IUnknown *)decoder2;194 if (_multiThread)195 _mixerCoderMTSpec->AddCoder2(decoder2);196 #ifdef _ST_MODE197 else198 _mixerCoderSTSpec->AddCoder2(decoder2, false);199 #endif200 }201 _decoders.Add(decoderUnknown);202 #ifdef EXTERNAL_CODECS203 CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;204 decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);205 if (setCompressCodecsInfo)206 {207 RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));208 }209 #endif210 }211 _bindInfoExPrev = bindInfo;212 _bindInfoExPrevIsDefined = true;213 }214 int i;215 _mixerCoderCommon->ReInit();217 UInt32 packStreamIndex = 0, unpackStreamIndex = 0;218 UInt32 coderIndex = 0;219 // UInt32 coder2Index = 0;221 for (i = 0; i < numCoders; i++)222 {223 const CCoderInfo &coderInfo = folderInfo.Coders[i];224 CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];226 {227 CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;228 decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);229 if (setDecoderProperties)230 {231 const CByteBuffer &props = coderInfo.Props;232 size_t size = props.GetCapacity();233 if (size > 0xFFFFFFFF)234 return E_NOTIMPL;235 if (size > 0)236 {237 RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size));238 }239 }240 }242 #ifdef COMPRESS_MT243 if (mtMode)244 {245 CMyComPtr<ICompressSetCoderMt> setCoderMt;246 decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);247 if (setCoderMt)248 {249 RINOK(setCoderMt->SetNumberOfThreads(numThreads));250 }251 }252 #endif254 #ifndef _NO_CRYPTO255 {256 CMyComPtr<ICryptoSetPassword> cryptoSetPassword;257 decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);258 if (cryptoSetPassword)259 {260 if (getTextPassword == 0)261 return E_FAIL;262 CMyComBSTR passwordBSTR;263 RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));264 CByteBuffer buffer;265 passwordIsDefined = true;266 const UString password(passwordBSTR);267 const UInt32 sizeInBytes = password.Length() * 2;268 buffer.SetCapacity(sizeInBytes);269 for (int i = 0; i < password.Length(); i++)270 {271 wchar_t c = password[i];272 ((Byte *)buffer)[i * 2] = (Byte)c;273 ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);274 }275 RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));276 }277 }278 #endif280 coderIndex++;282 UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;283 UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;284 CRecordVector<const UInt64 *> packSizesPointers;285 CRecordVector<const UInt64 *> unpackSizesPointers;286 packSizesPointers.Reserve(numInStreams);287 unpackSizesPointers.Reserve(numOutStreams);288 UInt32 j;289 for (j = 0; j < numOutStreams; j++, unpackStreamIndex++)290 unpackSizesPointers.Add(&folderInfo.UnpackSizes[unpackStreamIndex]);292 for (j = 0; j < numInStreams; j++, packStreamIndex++)293 {294 int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);295 if (bindPairIndex >= 0)296 packSizesPointers.Add(297 &folderInfo.UnpackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]);298 else299 {300 int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);301 if (index < 0)302 return E_FAIL;303 packSizesPointers.Add(&packSizes[index]);304 }305 }307 _mixerCoderCommon->SetCoderInfo(i,308 &packSizesPointers.Front(),309 &unpackSizesPointers.Front());310 }311 UInt32 mainCoder, temp;312 bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);314 if (_multiThread)315 _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);316 /*317 else318 _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;319 */321 if (numCoders == 0)322 return 0;323 CRecordVector<ISequentialInStream *> inStreamPointers;324 inStreamPointers.Reserve(inStreams.Size());325 for (i = 0; i < inStreams.Size(); i++)326 inStreamPointers.Add(inStreams[i]);327 ISequentialOutStream *outStreamPointer = outStream;328 return _mixerCoder->Code(&inStreamPointers.Front(), NULL,329 inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress);330 }332 }}