7 #include "../../IPassword.h"
8 #include "../../Common/LockedStream.h"
9 #include "../../Common/StreamObjects.h"
10 #include "../../Common/ProgressUtils.h"
11 #include "../../Common/LimitedStreams.h"
12 #include "../Common/FilterCoder.h"
14 #include "7zMethods.h"
17 #include "../../Compress/LZMA/LZMADecoder.h"
18 static NArchive::N7z::CMethodID k_LZMA
= { { 0x3, 0x1, 0x1 }, 3 };
22 #include "../../Compress/PPMD/PPMDDecoder.h"
23 static NArchive::N7z::CMethodID k_PPMD
= { { 0x3, 0x4, 0x1 }, 3 };
26 #ifdef COMPRESS_BCJ_X86
27 #include "../../Compress/Branch/x86.h"
28 static NArchive::N7z::CMethodID k_BCJ_X86
= { { 0x3, 0x3, 0x1, 0x3 }, 4 };
32 #include "../../Compress/Branch/x86_2.h"
33 static NArchive::N7z::CMethodID k_BCJ2
= { { 0x3, 0x3, 0x1, 0x1B }, 4 };
36 #ifdef COMPRESS_DEFLATE
37 #ifndef COMPRESS_DEFLATE_DECODER
38 #define COMPRESS_DEFLATE_DECODER
42 #ifdef COMPRESS_DEFLATE_DECODER
43 #include "../../Compress/Deflate/DeflateDecoder.h"
44 static NArchive::N7z::CMethodID k_Deflate
= { { 0x4, 0x1, 0x8 }, 3 };
48 #ifndef COMPRESS_BZIP2_DECODER
49 #define COMPRESS_BZIP2_DECODER
53 #ifdef COMPRESS_BZIP2_DECODER
54 #include "../../Compress/BZip2/BZip2Decoder.h"
55 static NArchive::N7z::CMethodID k_BZip2
= { { 0x4, 0x2, 0x2 }, 3 };
59 #include "../../Compress/Copy/CopyCoder.h"
60 static NArchive::N7z::CMethodID k_Copy
= { { 0x0 }, 1 };
64 #include "../../Crypto/7zAES/7zAES.h"
65 static NArchive::N7z::CMethodID k_7zAES
= { { 0x6, 0xF1, 0x07, 0x01 }, 4 };
71 static void ConvertFolderItemInfoToBindInfo(const CFolder
&folder
,
72 CBindInfoEx
&bindInfo
)
76 for (i
= 0; i
< folder
.BindPairs
.Size(); i
++)
78 NCoderMixer2::CBindPair bindPair
;
79 bindPair
.InIndex
= (UInt32
)folder
.BindPairs
[i
].InIndex
;
80 bindPair
.OutIndex
= (UInt32
)folder
.BindPairs
[i
].OutIndex
;
81 bindInfo
.BindPairs
.Add(bindPair
);
83 UInt32 outStreamIndex
= 0;
84 for (i
= 0; i
< folder
.Coders
.Size(); i
++)
86 NCoderMixer2::CCoderStreamsInfo coderStreamsInfo
;
87 const CCoderInfo
&coderInfo
= folder
.Coders
[i
];
88 coderStreamsInfo
.NumInStreams
= (UInt32
)coderInfo
.NumInStreams
;
89 coderStreamsInfo
.NumOutStreams
= (UInt32
)coderInfo
.NumOutStreams
;
90 bindInfo
.Coders
.Add(coderStreamsInfo
);
91 const CAltCoderInfo
&altCoderInfo
= coderInfo
.AltCoders
.Front();
92 bindInfo
.CoderMethodIDs
.Add(altCoderInfo
.MethodID
);
93 for (UInt32 j
= 0; j
< coderStreamsInfo
.NumOutStreams
; j
++, outStreamIndex
++)
94 if (folder
.FindBindPairForOutStream(outStreamIndex
) < 0)
95 bindInfo
.OutStreams
.Add(outStreamIndex
);
97 for (i
= 0; i
< folder
.PackStreams
.Size(); i
++)
98 bindInfo
.InStreams
.Add((UInt32
)folder
.PackStreams
[i
]);
101 static bool AreCodersEqual(const NCoderMixer2::CCoderStreamsInfo
&a1
,
102 const NCoderMixer2::CCoderStreamsInfo
&a2
)
104 return (a1
.NumInStreams
== a2
.NumInStreams
) &&
105 (a1
.NumOutStreams
== a2
.NumOutStreams
);
108 static bool AreBindPairsEqual(const NCoderMixer2::CBindPair
&a1
, const NCoderMixer2::CBindPair
&a2
)
110 return (a1
.InIndex
== a2
.InIndex
) &&
111 (a1
.OutIndex
== a2
.OutIndex
);
114 static bool AreBindInfoExEqual(const CBindInfoEx
&a1
, const CBindInfoEx
&a2
)
116 if (a1
.Coders
.Size() != a2
.Coders
.Size())
119 for (i
= 0; i
< a1
.Coders
.Size(); i
++)
120 if (!AreCodersEqual(a1
.Coders
[i
], a2
.Coders
[i
]))
122 if (a1
.BindPairs
.Size() != a2
.BindPairs
.Size())
124 for (i
= 0; i
< a1
.BindPairs
.Size(); i
++)
125 if (!AreBindPairsEqual(a1
.BindPairs
[i
], a2
.BindPairs
[i
]))
127 for (i
= 0; i
< a1
.CoderMethodIDs
.Size(); i
++)
128 if (a1
.CoderMethodIDs
[i
] != a2
.CoderMethodIDs
[i
])
130 if (a1
.InStreams
.Size() != a2
.InStreams
.Size())
132 if (a1
.OutStreams
.Size() != a2
.OutStreams
.Size())
137 CDecoder::CDecoder(bool multiThread
)
142 _multiThread
= multiThread
;
143 _bindInfoExPrevIsDefinded
= false;
149 HRESULT
CDecoder::Decode(IInStream
*inStream
,
151 const UInt64
*packSizes
,
152 const CFolder
&folderInfo
,
153 ISequentialOutStream
*outStream
,
154 ICompressProgressInfo
*compressProgress
156 , ICryptoGetTextPassword
*getTextPassword
159 , bool mtMode
, UInt32 numThreads
163 CObjectVector
< CMyComPtr
<ISequentialInStream
> > inStreams
;
165 CLockedInStream lockedInStream
;
166 lockedInStream
.Init(inStream
);
168 for (int j
= 0; j
< folderInfo
.PackStreams
.Size(); j
++)
170 CLockedSequentialInStreamImp
*lockedStreamImpSpec
= new
171 CLockedSequentialInStreamImp
;
172 CMyComPtr
<ISequentialInStream
> lockedStreamImp
= lockedStreamImpSpec
;
173 lockedStreamImpSpec
->Init(&lockedInStream
, startPos
);
174 startPos
+= packSizes
[j
];
176 CLimitedSequentialInStream
*streamSpec
= new
177 CLimitedSequentialInStream
;
178 CMyComPtr
<ISequentialInStream
> inStream
= streamSpec
;
179 streamSpec
->Init(lockedStreamImp
, packSizes
[j
]);
180 inStreams
.Add(inStream
);
183 int numCoders
= folderInfo
.Coders
.Size();
185 CBindInfoEx bindInfo
;
186 ConvertFolderItemInfoToBindInfo(folderInfo
, bindInfo
);
187 bool createNewCoders
;
188 if (!_bindInfoExPrevIsDefinded
)
189 createNewCoders
= true;
191 createNewCoders
= !AreBindInfoExEqual(bindInfo
, _bindInfoExPrev
);
196 // _decoders2.Clear();
198 _mixerCoder
.Release();
202 _mixerCoderMTSpec
= new NCoderMixer2::CCoderMixer2MT
;
203 _mixerCoder
= _mixerCoderMTSpec
;
204 _mixerCoderCommon
= _mixerCoderMTSpec
;
209 _mixerCoderSTSpec
= new NCoderMixer2::CCoderMixer2ST
;
210 _mixerCoder
= _mixerCoderSTSpec
;
211 _mixerCoderCommon
= _mixerCoderSTSpec
;
214 _mixerCoderCommon
->SetBindInfo(bindInfo
);
216 for (i
= 0; i
< numCoders
; i
++)
218 const CCoderInfo
&coderInfo
= folderInfo
.Coders
[i
];
219 const CAltCoderInfo
&altCoderInfo
= coderInfo
.AltCoders
.Front();
221 CMethodInfo methodInfo
;
222 if (!GetMethodInfo(altCoderInfo
.MethodID
, methodInfo
))
226 if (coderInfo
.IsSimpleCoder())
228 CMyComPtr
<ICompressCoder
> decoder
;
229 CMyComPtr
<ICompressFilter
> filter
;
232 if (altCoderInfo
.MethodID
== k_LZMA
)
233 decoder
= new NCompress::NLZMA::CDecoder
;
237 if (altCoderInfo
.MethodID
== k_PPMD
)
238 decoder
= new NCompress::NPPMD::CDecoder
;
241 #ifdef COMPRESS_BCJ_X86
242 if (altCoderInfo
.MethodID
== k_BCJ_X86
)
243 filter
= new CBCJ_x86_Decoder
;
246 #ifdef COMPRESS_DEFLATE_DECODER
247 if (altCoderInfo
.MethodID
== k_Deflate
)
248 decoder
= new NCompress::NDeflate::NDecoder::CCOMCoder
;
251 #ifdef COMPRESS_BZIP2_DECODER
252 if (altCoderInfo
.MethodID
== k_BZip2
)
253 decoder
= new NCompress::NBZip2::CDecoder
;
257 if (altCoderInfo
.MethodID
== k_Copy
)
258 decoder
= new NCompress::CCopyCoder
;
262 if (altCoderInfo
.MethodID
== k_7zAES
)
263 filter
= new NCrypto::NSevenZ::CDecoder
;
268 CFilterCoder
*coderSpec
= new CFilterCoder
;
270 coderSpec
->Filter
= filter
;
275 RINOK(_libraries
.CreateCoderSpec(methodInfo
.FilePath
,
276 methodInfo
.Decoder
, &decoder
));
283 _decoders
.Add((IUnknown
*)decoder
);
286 _mixerCoderMTSpec
->AddCoder(decoder
);
289 _mixerCoderSTSpec
->AddCoder(decoder
, false);
294 CMyComPtr
<ICompressCoder2
> decoder
;
297 if (altCoderInfo
.MethodID
== k_BCJ2
)
298 decoder
= new CBCJ2_x86_Decoder
;
304 RINOK(_libraries
.CreateCoder2(methodInfo
.FilePath
,
305 methodInfo
.Decoder
, &decoder
));
312 _decoders
.Add((IUnknown
*)decoder
);
314 _mixerCoderMTSpec
->AddCoder2(decoder
);
317 _mixerCoderSTSpec
->AddCoder2(decoder
, false);
321 _bindInfoExPrev
= bindInfo
;
322 _bindInfoExPrevIsDefinded
= true;
325 _mixerCoderCommon
->ReInit();
327 UInt32 packStreamIndex
= 0, unPackStreamIndex
= 0;
328 UInt32 coderIndex
= 0;
329 // UInt32 coder2Index = 0;
331 for (i
= 0; i
< numCoders
; i
++)
333 const CCoderInfo
&coderInfo
= folderInfo
.Coders
[i
];
334 const CAltCoderInfo
&altCoderInfo
= coderInfo
.AltCoders
.Front();
335 CMyComPtr
<IUnknown
> &decoder
= _decoders
[coderIndex
];
338 CMyComPtr
<ICompressSetDecoderProperties2
> setDecoderProperties
;
339 HRESULT result
= decoder
.QueryInterface(IID_ICompressSetDecoderProperties2
, &setDecoderProperties
);
340 if (setDecoderProperties
)
342 const CByteBuffer
&properties
= altCoderInfo
.Properties
;
343 size_t size
= properties
.GetCapacity();
344 if (size
> 0xFFFFFFFF)
348 RINOK(setDecoderProperties
->SetDecoderProperties2((const Byte
*)properties
, (UInt32
)size
));
356 CMyComPtr
<ICompressSetCoderMt
> setCoderMt
;
357 decoder
.QueryInterface(IID_ICompressSetCoderMt
, &setCoderMt
);
360 RINOK(setCoderMt
->SetNumberOfThreads(numThreads
));
367 CMyComPtr
<ICryptoSetPassword
> cryptoSetPassword
;
368 HRESULT result
= decoder
.QueryInterface(IID_ICryptoSetPassword
, &cryptoSetPassword
);
369 if (cryptoSetPassword
)
371 if (getTextPassword
== 0)
374 RINOK(getTextPassword
->CryptoGetTextPassword(&password
));
376 UString
unicodePassword(password
);
377 const UInt32 sizeInBytes
= unicodePassword
.Length() * 2;
378 buffer
.SetCapacity(sizeInBytes
);
379 for (int i
= 0; i
< unicodePassword
.Length(); i
++)
381 wchar_t c
= unicodePassword
[i
];
382 ((Byte
*)buffer
)[i
* 2] = (Byte
)c
;
383 ((Byte
*)buffer
)[i
* 2 + 1] = (Byte
)(c
>> 8);
385 RINOK(cryptoSetPassword
->CryptoSetPassword(
386 (const Byte
*)buffer
, sizeInBytes
));
393 UInt32 numInStreams
= (UInt32
)coderInfo
.NumInStreams
;
394 UInt32 numOutStreams
= (UInt32
)coderInfo
.NumOutStreams
;
395 CRecordVector
<const UInt64
*> packSizesPointers
;
396 CRecordVector
<const UInt64
*> unPackSizesPointers
;
397 packSizesPointers
.Reserve(numInStreams
);
398 unPackSizesPointers
.Reserve(numOutStreams
);
400 for (j
= 0; j
< numOutStreams
; j
++, unPackStreamIndex
++)
401 unPackSizesPointers
.Add(&folderInfo
.UnPackSizes
[unPackStreamIndex
]);
403 for (j
= 0; j
< numInStreams
; j
++, packStreamIndex
++)
405 int bindPairIndex
= folderInfo
.FindBindPairForInStream(packStreamIndex
);
406 if (bindPairIndex
>= 0)
407 packSizesPointers
.Add(
408 &folderInfo
.UnPackSizes
[(UInt32
)folderInfo
.BindPairs
[bindPairIndex
].OutIndex
]);
411 int index
= folderInfo
.FindPackStreamArrayIndex(packStreamIndex
);
414 packSizesPointers
.Add(&packSizes
[index
]);
418 _mixerCoderCommon
->SetCoderInfo(i
,
419 &packSizesPointers
.Front(),
420 &unPackSizesPointers
.Front());
422 UInt32 mainCoder
, temp
;
423 bindInfo
.FindOutStream(bindInfo
.OutStreams
[0], mainCoder
, temp
);
426 _mixerCoderMTSpec
->SetProgressCoderIndex(mainCoder
);
429 _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
434 CRecordVector
<ISequentialInStream
*> inStreamPointers
;
435 inStreamPointers
.Reserve(inStreams
.Size());
436 for (i
= 0; i
< inStreams
.Size(); i
++)
437 inStreamPointers
.Add(inStreams
[i
]);
438 ISequentialOutStream
*outStreamPointer
= outStream
;
439 return _mixerCoder
->Code(&inStreamPointers
.Front(), NULL
,
440 inStreams
.Size(), &outStreamPointer
, NULL
, 1, compressProgress
);