annotate 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
rev   line source
rlm@1 1 // 7zDecode.cpp
rlm@1 2
rlm@1 3 #include "StdAfx.h"
rlm@1 4
rlm@1 5 #include "../../Common/LimitedStreams.h"
rlm@1 6 #include "../../Common/LockedStream.h"
rlm@1 7 #include "../../Common/ProgressUtils.h"
rlm@1 8 #include "../../Common/StreamObjects.h"
rlm@1 9
rlm@1 10 #include "7zDecode.h"
rlm@1 11
rlm@1 12 namespace NArchive {
rlm@1 13 namespace N7z {
rlm@1 14
rlm@1 15 static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
rlm@1 16 CBindInfoEx &bindInfo)
rlm@1 17 {
rlm@1 18 bindInfo.Clear();
rlm@1 19 int i;
rlm@1 20 for (i = 0; i < folder.BindPairs.Size(); i++)
rlm@1 21 {
rlm@1 22 NCoderMixer::CBindPair bindPair;
rlm@1 23 bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;
rlm@1 24 bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;
rlm@1 25 bindInfo.BindPairs.Add(bindPair);
rlm@1 26 }
rlm@1 27 UInt32 outStreamIndex = 0;
rlm@1 28 for (i = 0; i < folder.Coders.Size(); i++)
rlm@1 29 {
rlm@1 30 NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
rlm@1 31 const CCoderInfo &coderInfo = folder.Coders[i];
rlm@1 32 coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;
rlm@1 33 coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;
rlm@1 34 bindInfo.Coders.Add(coderStreamsInfo);
rlm@1 35 bindInfo.CoderMethodIDs.Add(coderInfo.MethodID);
rlm@1 36 for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
rlm@1 37 if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
rlm@1 38 bindInfo.OutStreams.Add(outStreamIndex);
rlm@1 39 }
rlm@1 40 for (i = 0; i < folder.PackStreams.Size(); i++)
rlm@1 41 bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]);
rlm@1 42 }
rlm@1 43
rlm@1 44 static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,
rlm@1 45 const NCoderMixer::CCoderStreamsInfo &a2)
rlm@1 46 {
rlm@1 47 return (a1.NumInStreams == a2.NumInStreams) &&
rlm@1 48 (a1.NumOutStreams == a2.NumOutStreams);
rlm@1 49 }
rlm@1 50
rlm@1 51 static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2)
rlm@1 52 {
rlm@1 53 return (a1.InIndex == a2.InIndex) &&
rlm@1 54 (a1.OutIndex == a2.OutIndex);
rlm@1 55 }
rlm@1 56
rlm@1 57 static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
rlm@1 58 {
rlm@1 59 if (a1.Coders.Size() != a2.Coders.Size())
rlm@1 60 return false;
rlm@1 61 int i;
rlm@1 62 for (i = 0; i < a1.Coders.Size(); i++)
rlm@1 63 if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
rlm@1 64 return false;
rlm@1 65 if (a1.BindPairs.Size() != a2.BindPairs.Size())
rlm@1 66 return false;
rlm@1 67 for (i = 0; i < a1.BindPairs.Size(); i++)
rlm@1 68 if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))
rlm@1 69 return false;
rlm@1 70 for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
rlm@1 71 if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
rlm@1 72 return false;
rlm@1 73 if (a1.InStreams.Size() != a2.InStreams.Size())
rlm@1 74 return false;
rlm@1 75 if (a1.OutStreams.Size() != a2.OutStreams.Size())
rlm@1 76 return false;
rlm@1 77 return true;
rlm@1 78 }
rlm@1 79
rlm@1 80 CDecoder::CDecoder(bool multiThread)
rlm@1 81 {
rlm@1 82 #ifndef _ST_MODE
rlm@1 83 multiThread = true;
rlm@1 84 #endif
rlm@1 85 _multiThread = multiThread;
rlm@1 86 _bindInfoExPrevIsDefined = false;
rlm@1 87 }
rlm@1 88
rlm@1 89 HRESULT CDecoder::Decode(
rlm@1 90 DECL_EXTERNAL_CODECS_LOC_VARS
rlm@1 91 IInStream *inStream,
rlm@1 92 UInt64 startPos,
rlm@1 93 const UInt64 *packSizes,
rlm@1 94 const CFolder &folderInfo,
rlm@1 95 ISequentialOutStream *outStream,
rlm@1 96 ICompressProgressInfo *compressProgress
rlm@1 97 #ifndef _NO_CRYPTO
rlm@1 98 , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
rlm@1 99 #endif
rlm@1 100 #ifdef COMPRESS_MT
rlm@1 101 , bool mtMode, UInt32 numThreads
rlm@1 102 #endif
rlm@1 103 )
rlm@1 104 {
rlm@1 105 if (!folderInfo.CheckStructure())
rlm@1 106 return E_NOTIMPL;
rlm@1 107 #ifndef _NO_CRYPTO
rlm@1 108 passwordIsDefined = false;
rlm@1 109 #endif
rlm@1 110 CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
rlm@1 111
rlm@1 112 CLockedInStream lockedInStream;
rlm@1 113 lockedInStream.Init(inStream);
rlm@1 114
rlm@1 115 for (int j = 0; j < folderInfo.PackStreams.Size(); j++)
rlm@1 116 {
rlm@1 117 CLockedSequentialInStreamImp *lockedStreamImpSpec = new
rlm@1 118 CLockedSequentialInStreamImp;
rlm@1 119 CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
rlm@1 120 lockedStreamImpSpec->Init(&lockedInStream, startPos);
rlm@1 121 startPos += packSizes[j];
rlm@1 122
rlm@1 123 CLimitedSequentialInStream *streamSpec = new
rlm@1 124 CLimitedSequentialInStream;
rlm@1 125 CMyComPtr<ISequentialInStream> inStream = streamSpec;
rlm@1 126 streamSpec->SetStream(lockedStreamImp);
rlm@1 127 streamSpec->Init(packSizes[j]);
rlm@1 128 inStreams.Add(inStream);
rlm@1 129 }
rlm@1 130
rlm@1 131 int numCoders = folderInfo.Coders.Size();
rlm@1 132
rlm@1 133 CBindInfoEx bindInfo;
rlm@1 134 ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
rlm@1 135 bool createNewCoders;
rlm@1 136 if (!_bindInfoExPrevIsDefined)
rlm@1 137 createNewCoders = true;
rlm@1 138 else
rlm@1 139 createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
rlm@1 140 if (createNewCoders)
rlm@1 141 {
rlm@1 142 int i;
rlm@1 143 _decoders.Clear();
rlm@1 144 // _decoders2.Clear();
rlm@1 145
rlm@1 146 _mixerCoder.Release();
rlm@1 147
rlm@1 148 if (_multiThread)
rlm@1 149 {
rlm@1 150 _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT;
rlm@1 151 _mixerCoder = _mixerCoderMTSpec;
rlm@1 152 _mixerCoderCommon = _mixerCoderMTSpec;
rlm@1 153 }
rlm@1 154 else
rlm@1 155 {
rlm@1 156 #ifdef _ST_MODE
rlm@1 157 _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST;
rlm@1 158 _mixerCoder = _mixerCoderSTSpec;
rlm@1 159 _mixerCoderCommon = _mixerCoderSTSpec;
rlm@1 160 #endif
rlm@1 161 }
rlm@1 162 RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));
rlm@1 163
rlm@1 164 for (i = 0; i < numCoders; i++)
rlm@1 165 {
rlm@1 166 const CCoderInfo &coderInfo = folderInfo.Coders[i];
rlm@1 167
rlm@1 168
rlm@1 169 CMyComPtr<ICompressCoder> decoder;
rlm@1 170 CMyComPtr<ICompressCoder2> decoder2;
rlm@1 171 RINOK(CreateCoder(
rlm@1 172 EXTERNAL_CODECS_LOC_VARS
rlm@1 173 coderInfo.MethodID, decoder, decoder2, false));
rlm@1 174 CMyComPtr<IUnknown> decoderUnknown;
rlm@1 175 if (coderInfo.IsSimpleCoder())
rlm@1 176 {
rlm@1 177 if (decoder == 0)
rlm@1 178 return E_NOTIMPL;
rlm@1 179
rlm@1 180 decoderUnknown = (IUnknown *)decoder;
rlm@1 181
rlm@1 182 if (_multiThread)
rlm@1 183 _mixerCoderMTSpec->AddCoder(decoder);
rlm@1 184 #ifdef _ST_MODE
rlm@1 185 else
rlm@1 186 _mixerCoderSTSpec->AddCoder(decoder, false);
rlm@1 187 #endif
rlm@1 188 }
rlm@1 189 else
rlm@1 190 {
rlm@1 191 if (decoder2 == 0)
rlm@1 192 return E_NOTIMPL;
rlm@1 193 decoderUnknown = (IUnknown *)decoder2;
rlm@1 194 if (_multiThread)
rlm@1 195 _mixerCoderMTSpec->AddCoder2(decoder2);
rlm@1 196 #ifdef _ST_MODE
rlm@1 197 else
rlm@1 198 _mixerCoderSTSpec->AddCoder2(decoder2, false);
rlm@1 199 #endif
rlm@1 200 }
rlm@1 201 _decoders.Add(decoderUnknown);
rlm@1 202 #ifdef EXTERNAL_CODECS
rlm@1 203 CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
rlm@1 204 decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
rlm@1 205 if (setCompressCodecsInfo)
rlm@1 206 {
rlm@1 207 RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));
rlm@1 208 }
rlm@1 209 #endif
rlm@1 210 }
rlm@1 211 _bindInfoExPrev = bindInfo;
rlm@1 212 _bindInfoExPrevIsDefined = true;
rlm@1 213 }
rlm@1 214 int i;
rlm@1 215 _mixerCoderCommon->ReInit();
rlm@1 216
rlm@1 217 UInt32 packStreamIndex = 0, unpackStreamIndex = 0;
rlm@1 218 UInt32 coderIndex = 0;
rlm@1 219 // UInt32 coder2Index = 0;
rlm@1 220
rlm@1 221 for (i = 0; i < numCoders; i++)
rlm@1 222 {
rlm@1 223 const CCoderInfo &coderInfo = folderInfo.Coders[i];
rlm@1 224 CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];
rlm@1 225
rlm@1 226 {
rlm@1 227 CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
rlm@1 228 decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
rlm@1 229 if (setDecoderProperties)
rlm@1 230 {
rlm@1 231 const CByteBuffer &props = coderInfo.Props;
rlm@1 232 size_t size = props.GetCapacity();
rlm@1 233 if (size > 0xFFFFFFFF)
rlm@1 234 return E_NOTIMPL;
rlm@1 235 if (size > 0)
rlm@1 236 {
rlm@1 237 RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size));
rlm@1 238 }
rlm@1 239 }
rlm@1 240 }
rlm@1 241
rlm@1 242 #ifdef COMPRESS_MT
rlm@1 243 if (mtMode)
rlm@1 244 {
rlm@1 245 CMyComPtr<ICompressSetCoderMt> setCoderMt;
rlm@1 246 decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
rlm@1 247 if (setCoderMt)
rlm@1 248 {
rlm@1 249 RINOK(setCoderMt->SetNumberOfThreads(numThreads));
rlm@1 250 }
rlm@1 251 }
rlm@1 252 #endif
rlm@1 253
rlm@1 254 #ifndef _NO_CRYPTO
rlm@1 255 {
rlm@1 256 CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
rlm@1 257 decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
rlm@1 258 if (cryptoSetPassword)
rlm@1 259 {
rlm@1 260 if (getTextPassword == 0)
rlm@1 261 return E_FAIL;
rlm@1 262 CMyComBSTR passwordBSTR;
rlm@1 263 RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));
rlm@1 264 CByteBuffer buffer;
rlm@1 265 passwordIsDefined = true;
rlm@1 266 const UString password(passwordBSTR);
rlm@1 267 const UInt32 sizeInBytes = password.Length() * 2;
rlm@1 268 buffer.SetCapacity(sizeInBytes);
rlm@1 269 for (int i = 0; i < password.Length(); i++)
rlm@1 270 {
rlm@1 271 wchar_t c = password[i];
rlm@1 272 ((Byte *)buffer)[i * 2] = (Byte)c;
rlm@1 273 ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
rlm@1 274 }
rlm@1 275 RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
rlm@1 276 }
rlm@1 277 }
rlm@1 278 #endif
rlm@1 279
rlm@1 280 coderIndex++;
rlm@1 281
rlm@1 282 UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
rlm@1 283 UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
rlm@1 284 CRecordVector<const UInt64 *> packSizesPointers;
rlm@1 285 CRecordVector<const UInt64 *> unpackSizesPointers;
rlm@1 286 packSizesPointers.Reserve(numInStreams);
rlm@1 287 unpackSizesPointers.Reserve(numOutStreams);
rlm@1 288 UInt32 j;
rlm@1 289 for (j = 0; j < numOutStreams; j++, unpackStreamIndex++)
rlm@1 290 unpackSizesPointers.Add(&folderInfo.UnpackSizes[unpackStreamIndex]);
rlm@1 291
rlm@1 292 for (j = 0; j < numInStreams; j++, packStreamIndex++)
rlm@1 293 {
rlm@1 294 int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
rlm@1 295 if (bindPairIndex >= 0)
rlm@1 296 packSizesPointers.Add(
rlm@1 297 &folderInfo.UnpackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]);
rlm@1 298 else
rlm@1 299 {
rlm@1 300 int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
rlm@1 301 if (index < 0)
rlm@1 302 return E_FAIL;
rlm@1 303 packSizesPointers.Add(&packSizes[index]);
rlm@1 304 }
rlm@1 305 }
rlm@1 306
rlm@1 307 _mixerCoderCommon->SetCoderInfo(i,
rlm@1 308 &packSizesPointers.Front(),
rlm@1 309 &unpackSizesPointers.Front());
rlm@1 310 }
rlm@1 311 UInt32 mainCoder, temp;
rlm@1 312 bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
rlm@1 313
rlm@1 314 if (_multiThread)
rlm@1 315 _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);
rlm@1 316 /*
rlm@1 317 else
rlm@1 318 _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
rlm@1 319 */
rlm@1 320
rlm@1 321 if (numCoders == 0)
rlm@1 322 return 0;
rlm@1 323 CRecordVector<ISequentialInStream *> inStreamPointers;
rlm@1 324 inStreamPointers.Reserve(inStreams.Size());
rlm@1 325 for (i = 0; i < inStreams.Size(); i++)
rlm@1 326 inStreamPointers.Add(inStreams[i]);
rlm@1 327 ISequentialOutStream *outStreamPointer = outStream;
rlm@1 328 return _mixerCoder->Code(&inStreamPointers.Front(), NULL,
rlm@1 329 inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress);
rlm@1 330 }
rlm@1 331
rlm@1 332 }}