Mercurial > vba-linux
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 +}}