summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/lzma/CPP/7zip/Archive/7z/7zDecode.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/lzma/CPP/7zip/Archive/7z/7zDecode.cpp')
-rw-r--r--3rdparty/lzma/CPP/7zip/Archive/7z/7zDecode.cpp569
1 files changed, 390 insertions, 179 deletions
diff --git a/3rdparty/lzma/CPP/7zip/Archive/7z/7zDecode.cpp b/3rdparty/lzma/CPP/7zip/Archive/7z/7zDecode.cpp
index 425a341577d..bfe1b24e923 100644
--- a/3rdparty/lzma/CPP/7zip/Archive/7z/7zDecode.cpp
+++ b/3rdparty/lzma/CPP/7zip/Archive/7z/7zDecode.cpp
@@ -3,7 +3,6 @@
#include "StdAfx.h"
#include "../../Common/LimitedStreams.h"
-#include "../../Common/LockedStream.h"
#include "../../Common/ProgressUtils.h"
#include "../../Common/StreamObjects.h"
@@ -12,230 +11,364 @@
namespace NArchive {
namespace N7z {
-static void ConvertFolderItemInfoToBindInfo(const CFolder &folder,
- CBindInfoEx &bindInfo)
+class CDecProgress:
+ public ICompressProgressInfo,
+ public CMyUnknownImp
{
- bindInfo.Clear();
- int i;
- for (i = 0; i < folder.BindPairs.Size(); i++)
+ CMyComPtr<ICompressProgressInfo> _progress;
+public:
+ CDecProgress(ICompressProgressInfo *progress): _progress(progress) {}
+
+ MY_UNKNOWN_IMP1(ICompressProgressInfo)
+ STDMETHOD(SetRatioInfo)(const UInt64 *inSize, const UInt64 *outSize);
+};
+
+STDMETHODIMP CDecProgress::SetRatioInfo(const UInt64 * /* inSize */, const UInt64 *outSize)
+{
+ return _progress->SetRatioInfo(NULL, outSize);
+}
+
+static void Convert_FolderInfo_to_BindInfo(const CFolderEx &folder, CBindInfoEx &bi)
+{
+ bi.Clear();
+
+ bi.Bonds.ClearAndSetSize(folder.Bonds.Size());
+ unsigned i;
+ for (i = 0; i < folder.Bonds.Size(); i++)
{
- NCoderMixer::CBindPair bindPair;
- bindPair.InIndex = (UInt32)folder.BindPairs[i].InIndex;
- bindPair.OutIndex = (UInt32)folder.BindPairs[i].OutIndex;
- bindInfo.BindPairs.Add(bindPair);
+ NCoderMixer2::CBond &bond = bi.Bonds[i];
+ const N7z::CBond &folderBond = folder.Bonds[i];
+ bond.PackIndex = folderBond.PackIndex;
+ bond.UnpackIndex = folderBond.UnpackIndex;
}
- UInt32 outStreamIndex = 0;
+
+ bi.Coders.ClearAndSetSize(folder.Coders.Size());
+ bi.CoderMethodIDs.ClearAndSetSize(folder.Coders.Size());
for (i = 0; i < folder.Coders.Size(); i++)
{
- NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
const CCoderInfo &coderInfo = folder.Coders[i];
- coderStreamsInfo.NumInStreams = (UInt32)coderInfo.NumInStreams;
- coderStreamsInfo.NumOutStreams = (UInt32)coderInfo.NumOutStreams;
- bindInfo.Coders.Add(coderStreamsInfo);
- bindInfo.CoderMethodIDs.Add(coderInfo.MethodID);
- for (UInt32 j = 0; j < coderStreamsInfo.NumOutStreams; j++, outStreamIndex++)
- if (folder.FindBindPairForOutStream(outStreamIndex) < 0)
- bindInfo.OutStreams.Add(outStreamIndex);
+ bi.Coders[i].NumStreams = coderInfo.NumStreams;
+ bi.CoderMethodIDs[i] = coderInfo.MethodID;
}
+
+ /*
+ if (!bi.SetUnpackCoder())
+ throw 1112;
+ */
+ bi.UnpackCoder = folder.UnpackCoder;
+ bi.PackStreams.ClearAndSetSize(folder.PackStreams.Size());
for (i = 0; i < folder.PackStreams.Size(); i++)
- bindInfo.InStreams.Add((UInt32)folder.PackStreams[i]);
+ bi.PackStreams[i] = folder.PackStreams[i];
}
-static bool AreCodersEqual(const NCoderMixer::CCoderStreamsInfo &a1,
- const NCoderMixer::CCoderStreamsInfo &a2)
+static inline bool AreCodersEqual(
+ const NCoderMixer2::CCoderStreamsInfo &a1,
+ const NCoderMixer2::CCoderStreamsInfo &a2)
{
- return (a1.NumInStreams == a2.NumInStreams) &&
- (a1.NumOutStreams == a2.NumOutStreams);
+ return (a1.NumStreams == a2.NumStreams);
}
-static bool AreBindPairsEqual(const NCoderMixer::CBindPair &a1, const NCoderMixer::CBindPair &a2)
+static inline bool AreBondsEqual(
+ const NCoderMixer2::CBond &a1,
+ const NCoderMixer2::CBond &a2)
{
- return (a1.InIndex == a2.InIndex) &&
- (a1.OutIndex == a2.OutIndex);
+ return
+ (a1.PackIndex == a2.PackIndex) &&
+ (a1.UnpackIndex == a2.UnpackIndex);
}
static bool AreBindInfoExEqual(const CBindInfoEx &a1, const CBindInfoEx &a2)
{
if (a1.Coders.Size() != a2.Coders.Size())
return false;
- int i;
+ unsigned i;
for (i = 0; i < a1.Coders.Size(); i++)
if (!AreCodersEqual(a1.Coders[i], a2.Coders[i]))
return false;
- if (a1.BindPairs.Size() != a2.BindPairs.Size())
+
+ if (a1.Bonds.Size() != a2.Bonds.Size())
return false;
- for (i = 0; i < a1.BindPairs.Size(); i++)
- if (!AreBindPairsEqual(a1.BindPairs[i], a2.BindPairs[i]))
+ for (i = 0; i < a1.Bonds.Size(); i++)
+ if (!AreBondsEqual(a1.Bonds[i], a2.Bonds[i]))
return false;
+
for (i = 0; i < a1.CoderMethodIDs.Size(); i++)
if (a1.CoderMethodIDs[i] != a2.CoderMethodIDs[i])
return false;
- if (a1.InStreams.Size() != a2.InStreams.Size())
+
+ if (a1.PackStreams.Size() != a2.PackStreams.Size())
return false;
- if (a1.OutStreams.Size() != a2.OutStreams.Size())
+ for (i = 0; i < a1.PackStreams.Size(); i++)
+ if (a1.PackStreams[i] != a2.PackStreams[i])
+ return false;
+
+ /*
+ if (a1.UnpackCoder != a2.UnpackCoder)
return false;
+ */
return true;
}
-CDecoder::CDecoder(bool multiThread)
+CDecoder::CDecoder(bool useMixerMT):
+ _bindInfoPrev_Defined(false),
+ _useMixerMT(useMixerMT)
+{}
+
+
+struct CLockedInStream:
+ public IUnknown,
+ public CMyUnknownImp
{
- #ifndef _ST_MODE
- multiThread = true;
+ CMyComPtr<IInStream> Stream;
+ UInt64 Pos;
+
+ MY_UNKNOWN_IMP
+
+ #ifdef USE_MIXER_MT
+ NWindows::NSynchronization::CCriticalSection CriticalSection;
#endif
- _multiThread = multiThread;
- _bindInfoExPrevIsDefined = false;
+};
+
+
+#ifdef USE_MIXER_MT
+
+class CLockedSequentialInStreamMT:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ CLockedInStream *_glob;
+ UInt64 _pos;
+ CMyComPtr<IUnknown> _globRef;
+public:
+ void Init(CLockedInStream *lockedInStream, UInt64 startPos)
+ {
+ _globRef = lockedInStream;
+ _glob = lockedInStream;
+ _pos = startPos;
+ }
+
+ MY_UNKNOWN_IMP1(ISequentialInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CLockedSequentialInStreamMT::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ NWindows::NSynchronization::CCriticalSectionLock lock(_glob->CriticalSection);
+
+ if (_pos != _glob->Pos)
+ {
+ RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));
+ _glob->Pos = _pos;
+ }
+
+ UInt32 realProcessedSize = 0;
+ HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
+ _pos += realProcessedSize;
+ _glob->Pos = _pos;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ return res;
}
+#endif
+
+
+#ifdef USE_MIXER_ST
+
+class CLockedSequentialInStreamST:
+ public ISequentialInStream,
+ public CMyUnknownImp
+{
+ CLockedInStream *_glob;
+ UInt64 _pos;
+ CMyComPtr<IUnknown> _globRef;
+public:
+ void Init(CLockedInStream *lockedInStream, UInt64 startPos)
+ {
+ _globRef = lockedInStream;
+ _glob = lockedInStream;
+ _pos = startPos;
+ }
+
+ MY_UNKNOWN_IMP1(ISequentialInStream)
+
+ STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize);
+};
+
+STDMETHODIMP CLockedSequentialInStreamST::Read(void *data, UInt32 size, UInt32 *processedSize)
+{
+ if (_pos != _glob->Pos)
+ {
+ RINOK(_glob->Stream->Seek(_pos, STREAM_SEEK_SET, NULL));
+ _glob->Pos = _pos;
+ }
+
+ UInt32 realProcessedSize = 0;
+ HRESULT res = _glob->Stream->Read(data, size, &realProcessedSize);
+ _pos += realProcessedSize;
+ _glob->Pos = _pos;
+ if (processedSize)
+ *processedSize = realProcessedSize;
+ return res;
+}
+
+#endif
+
+
+
HRESULT CDecoder::Decode(
DECL_EXTERNAL_CODECS_LOC_VARS
IInStream *inStream,
UInt64 startPos,
- const UInt64 *packSizes,
- const CFolder &folderInfo,
- ISequentialOutStream *outStream,
- ICompressProgressInfo *compressProgress
- #ifndef _NO_CRYPTO
- , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
+ const CFolders &folders, unsigned folderIndex,
+ const UInt64 *unpackSize
+
+ , ISequentialOutStream *outStream
+ , ICompressProgressInfo *compressProgress
+ , ISequentialInStream **
+
+ #ifdef USE_MIXER_ST
+ inStreamMainRes
#endif
+
+ _7Z_DECODER_CRYPRO_VARS_DECL
+
#if !defined(_7ZIP_ST) && !defined(_SFX)
, bool mtMode, UInt32 numThreads
#endif
)
{
- if (!folderInfo.CheckStructure())
+ const UInt64 *packPositions = &folders.PackPositions[folders.FoStartPackStreamIndex[folderIndex]];
+ CFolderEx folderInfo;
+ folders.ParseFolderEx(folderIndex, folderInfo);
+
+ if (!folderInfo.IsDecodingSupported())
+ return E_NOTIMPL;
+
+ CBindInfoEx bindInfo;
+ Convert_FolderInfo_to_BindInfo(folderInfo, bindInfo);
+ if (!bindInfo.CalcMapsAndCheck())
return E_NOTIMPL;
- #ifndef _NO_CRYPTO
- passwordIsDefined = false;
- #endif
- CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
-
- CLockedInStream lockedInStream;
- lockedInStream.Init(inStream);
- for (int j = 0; j < folderInfo.PackStreams.Size(); j++)
+ UInt64 folderUnpackSize = folders.GetFolderUnpackSize(folderIndex);
+ bool fullUnpack = true;
+ if (unpackSize)
{
- CLockedSequentialInStreamImp *lockedStreamImpSpec = new
- CLockedSequentialInStreamImp;
- CMyComPtr<ISequentialInStream> lockedStreamImp = lockedStreamImpSpec;
- lockedStreamImpSpec->Init(&lockedInStream, startPos);
- startPos += packSizes[j];
-
- CLimitedSequentialInStream *streamSpec = new
- CLimitedSequentialInStream;
- CMyComPtr<ISequentialInStream> inStream = streamSpec;
- streamSpec->SetStream(lockedStreamImp);
- streamSpec->Init(packSizes[j]);
- inStreams.Add(inStream);
+ if (*unpackSize > folderUnpackSize)
+ return E_FAIL;
+ fullUnpack = (*unpackSize == folderUnpackSize);
}
+
+ /*
+ We don't need to init isEncrypted and passwordIsDefined
+ We must upgrade them only
- int numCoders = folderInfo.Coders.Size();
+ #ifndef _NO_CRYPTO
+ isEncrypted = false;
+ passwordIsDefined = false;
+ #endif
+ */
- CBindInfoEx bindInfo;
- ConvertFolderItemInfoToBindInfo(folderInfo, bindInfo);
- bool createNewCoders;
- if (!_bindInfoExPrevIsDefined)
- createNewCoders = true;
- else
- createNewCoders = !AreBindInfoExEqual(bindInfo, _bindInfoExPrev);
- if (createNewCoders)
+ if (!_bindInfoPrev_Defined || !AreBindInfoExEqual(bindInfo, _bindInfoPrev))
{
- int i;
- _decoders.Clear();
- // _decoders2.Clear();
-
- _mixerCoder.Release();
+ _mixerRef.Release();
- if (_multiThread)
+ #ifdef USE_MIXER_MT
+ #ifdef USE_MIXER_ST
+ if (_useMixerMT)
+ #endif
{
- _mixerCoderMTSpec = new NCoderMixer::CCoderMixer2MT;
- _mixerCoder = _mixerCoderMTSpec;
- _mixerCoderCommon = _mixerCoderMTSpec;
+ _mixerMT = new NCoderMixer2::CMixerMT(false);
+ _mixerRef = _mixerMT;
+ _mixer = _mixerMT;
}
+ #ifdef USE_MIXER_ST
else
+ #endif
+ #endif
{
- #ifdef _ST_MODE
- _mixerCoderSTSpec = new NCoderMixer::CCoderMixer2ST;
- _mixerCoder = _mixerCoderSTSpec;
- _mixerCoderCommon = _mixerCoderSTSpec;
+ #ifdef USE_MIXER_ST
+ _mixerST = new NCoderMixer2::CMixerST(false);
+ _mixerRef = _mixerST;
+ _mixer = _mixerST;
#endif
}
- RINOK(_mixerCoderCommon->SetBindInfo(bindInfo));
- for (i = 0; i < numCoders; i++)
+ RINOK(_mixer->SetBindInfo(bindInfo));
+
+ FOR_VECTOR(i, folderInfo.Coders)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
+ #ifndef _SFX
+ // we don't support RAR codecs here
+ if ((coderInfo.MethodID >> 8) == 0x403)
+ return E_NOTIMPL;
+ #endif
- CMyComPtr<ICompressCoder> decoder;
- CMyComPtr<ICompressCoder2> decoder2;
+ CCreatedCoder cod;
RINOK(CreateCoder(
EXTERNAL_CODECS_LOC_VARS
- coderInfo.MethodID, decoder, decoder2, false));
- CMyComPtr<IUnknown> decoderUnknown;
+ coderInfo.MethodID, false, cod));
+
if (coderInfo.IsSimpleCoder())
{
- if (decoder == 0)
+ if (!cod.Coder)
return E_NOTIMPL;
-
- decoderUnknown = (IUnknown *)decoder;
-
- if (_multiThread)
- _mixerCoderMTSpec->AddCoder(decoder);
- #ifdef _ST_MODE
- else
- _mixerCoderSTSpec->AddCoder(decoder, false);
- #endif
+ // CMethodId m = coderInfo.MethodID;
+ // isFilter = (IsFilterMethod(m) || m == k_AES);
}
else
{
- if (decoder2 == 0)
+ if (!cod.Coder2 || cod.NumStreams != coderInfo.NumStreams)
return E_NOTIMPL;
- decoderUnknown = (IUnknown *)decoder2;
- if (_multiThread)
- _mixerCoderMTSpec->AddCoder2(decoder2);
- #ifdef _ST_MODE
- else
- _mixerCoderSTSpec->AddCoder2(decoder2, false);
- #endif
}
- _decoders.Add(decoderUnknown);
+ _mixer->AddCoder(cod);
+
+ // now there is no codec that uses another external codec
+ /*
#ifdef EXTERNAL_CODECS
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
decoderUnknown.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
if (setCompressCodecsInfo)
{
- RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));
+ // we must use g_ExternalCodecs also
+ RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));
}
#endif
+ */
}
- _bindInfoExPrev = bindInfo;
- _bindInfoExPrevIsDefined = true;
+
+ _bindInfoPrev = bindInfo;
+ _bindInfoPrev_Defined = true;
}
- int i;
- _mixerCoderCommon->ReInit();
-
- UInt32 packStreamIndex = 0, unpackStreamIndex = 0;
- UInt32 coderIndex = 0;
- // UInt32 coder2Index = 0;
+
+ _mixer->ReInit();
- for (i = 0; i < numCoders; i++)
+ UInt32 packStreamIndex = 0;
+ UInt32 unpackStreamIndexStart = folders.FoToCoderUnpackSizes[folderIndex];
+
+ unsigned i;
+
+ for (i = 0; i < folderInfo.Coders.Size(); i++)
{
const CCoderInfo &coderInfo = folderInfo.Coders[i];
- CMyComPtr<IUnknown> &decoder = _decoders[coderIndex];
-
+ IUnknown *decoder = _mixer->GetCoder(i).GetUnknown();
+
{
CMyComPtr<ICompressSetDecoderProperties2> setDecoderProperties;
- decoder.QueryInterface(IID_ICompressSetDecoderProperties2, &setDecoderProperties);
+ decoder->QueryInterface(IID_ICompressSetDecoderProperties2, (void **)&setDecoderProperties);
if (setDecoderProperties)
{
const CByteBuffer &props = coderInfo.Props;
- size_t size = props.GetCapacity();
+ size_t size = props.Size();
if (size > 0xFFFFFFFF)
return E_NOTIMPL;
- // if (size > 0)
- {
- RINOK(setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size));
- }
+ HRESULT res = setDecoderProperties->SetDecoderProperties2((const Byte *)props, (UInt32)size);
+ if (res == E_INVALIDARG)
+ res = E_NOTIMPL;
+ RINOK(res);
}
}
@@ -243,7 +376,7 @@ HRESULT CDecoder::Decode(
if (mtMode)
{
CMyComPtr<ICompressSetCoderMt> setCoderMt;
- decoder.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
+ decoder->QueryInterface(IID_ICompressSetCoderMt, (void **)&setCoderMt);
if (setCoderMt)
{
RINOK(setCoderMt->SetNumberOfThreads(numThreads));
@@ -254,79 +387,157 @@ HRESULT CDecoder::Decode(
#ifndef _NO_CRYPTO
{
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
- decoder.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
+ decoder->QueryInterface(IID_ICryptoSetPassword, (void **)&cryptoSetPassword);
if (cryptoSetPassword)
{
- if (getTextPassword == 0)
- return E_FAIL;
+ isEncrypted = true;
+ if (!getTextPassword)
+ return E_NOTIMPL;
CMyComBSTR passwordBSTR;
RINOK(getTextPassword->CryptoGetTextPassword(&passwordBSTR));
- CByteBuffer buffer;
passwordIsDefined = true;
- const UString password(passwordBSTR);
- const UInt32 sizeInBytes = password.Length() * 2;
- buffer.SetCapacity(sizeInBytes);
- for (int i = 0; i < password.Length(); i++)
+ password.Empty();
+ size_t len = 0;
+ if (passwordBSTR)
+ {
+ password = passwordBSTR;
+ len = password.Len();
+ }
+ CByteBuffer buffer(len * 2);
+ for (size_t i = 0; i < len; i++)
{
- wchar_t c = password[i];
+ wchar_t c = passwordBSTR[i];
((Byte *)buffer)[i * 2] = (Byte)c;
((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
}
- RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
+ RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)buffer.Size()));
}
}
#endif
- coderIndex++;
+ {
+ CMyComPtr<ICompressSetFinishMode> setFinishMode;
+ decoder->QueryInterface(IID_ICompressSetFinishMode, (void **)&setFinishMode);
+ if (setFinishMode)
+ {
+ RINOK(setFinishMode->SetFinishMode(BoolToInt(fullUnpack)));
+ }
+ }
- UInt32 numInStreams = (UInt32)coderInfo.NumInStreams;
- UInt32 numOutStreams = (UInt32)coderInfo.NumOutStreams;
- CRecordVector<const UInt64 *> packSizesPointers;
- CRecordVector<const UInt64 *> unpackSizesPointers;
- packSizesPointers.Reserve(numInStreams);
- unpackSizesPointers.Reserve(numOutStreams);
- UInt32 j;
- for (j = 0; j < numOutStreams; j++, unpackStreamIndex++)
- unpackSizesPointers.Add(&folderInfo.UnpackSizes[unpackStreamIndex]);
+ UInt32 numStreams = (UInt32)coderInfo.NumStreams;
- for (j = 0; j < numInStreams; j++, packStreamIndex++)
+ CObjArray<UInt64> packSizes(numStreams);
+ CObjArray<const UInt64 *> packSizesPointers(numStreams);
+
+ for (UInt32 j = 0; j < numStreams; j++, packStreamIndex++)
{
- int bindPairIndex = folderInfo.FindBindPairForInStream(packStreamIndex);
- if (bindPairIndex >= 0)
- packSizesPointers.Add(
- &folderInfo.UnpackSizes[(UInt32)folderInfo.BindPairs[bindPairIndex].OutIndex]);
+ int bond = folderInfo.FindBond_for_PackStream(packStreamIndex);
+
+ if (bond >= 0)
+ packSizesPointers[j] = &folders.CoderUnpackSizes[unpackStreamIndexStart + folderInfo.Bonds[(unsigned)bond].UnpackIndex];
else
{
- int index = folderInfo.FindPackStreamArrayIndex(packStreamIndex);
+ int index = folderInfo.Find_in_PackStreams(packStreamIndex);
if (index < 0)
- return E_FAIL;
- packSizesPointers.Add(&packSizes[index]);
+ return E_NOTIMPL;
+ packSizes[j] = packPositions[(unsigned)index + 1] - packPositions[(unsigned)index];
+ packSizesPointers[j] = &packSizes[j];
}
}
+
+ const UInt64 *unpackSizesPointer =
+ (unpackSize && i == bindInfo.UnpackCoder) ?
+ unpackSize :
+ &folders.CoderUnpackSizes[unpackStreamIndexStart + i];
- _mixerCoderCommon->SetCoderInfo(i,
- &packSizesPointers.Front(),
- &unpackSizesPointers.Front());
+ _mixer->SetCoderInfo(i, unpackSizesPointer, packSizesPointers);
}
- UInt32 mainCoder, temp;
- bindInfo.FindOutStream(bindInfo.OutStreams[0], mainCoder, temp);
- if (_multiThread)
- _mixerCoderMTSpec->SetProgressCoderIndex(mainCoder);
- /*
- else
- _mixerCoderSTSpec->SetProgressCoderIndex(mainCoder);;
- */
+ if (outStream)
+ {
+ _mixer->SelectMainCoder(!fullUnpack);
+ }
+
+ CObjectVector< CMyComPtr<ISequentialInStream> > inStreams;
- if (numCoders == 0)
- return 0;
- CRecordVector<ISequentialInStream *> inStreamPointers;
- inStreamPointers.Reserve(inStreams.Size());
- for (i = 0; i < inStreams.Size(); i++)
- inStreamPointers.Add(inStreams[i]);
- ISequentialOutStream *outStreamPointer = outStream;
- return _mixerCoder->Code(&inStreamPointers.Front(), NULL,
- inStreams.Size(), &outStreamPointer, NULL, 1, compressProgress);
+ CLockedInStream *lockedInStreamSpec = new CLockedInStream;
+ CMyComPtr<IUnknown> lockedInStream = lockedInStreamSpec;
+
+ bool needMtLock = false;
+
+ if (folderInfo.PackStreams.Size() > 1)
+ {
+ // lockedInStream.Pos = (UInt64)(Int64)-1;
+ // RINOK(inStream->Seek(0, STREAM_SEEK_CUR, &lockedInStream.Pos));
+ RINOK(inStream->Seek(startPos + packPositions[0], STREAM_SEEK_SET, &lockedInStreamSpec->Pos));
+ lockedInStreamSpec->Stream = inStream;
+
+ #ifdef USE_MIXER_ST
+ if (_mixer->IsThere_ExternalCoder_in_PackTree(_mixer->MainCoderIndex))
+ #endif
+ needMtLock = true;
+ }
+
+ for (unsigned j = 0; j < folderInfo.PackStreams.Size(); j++)
+ {
+ CMyComPtr<ISequentialInStream> packStream;
+ UInt64 packPos = startPos + packPositions[j];
+
+ if (folderInfo.PackStreams.Size() == 1)
+ {
+ RINOK(inStream->Seek(packPos, STREAM_SEEK_SET, NULL));
+ packStream = inStream;
+ }
+ else
+ {
+ #ifdef USE_MIXER_MT
+ #ifdef USE_MIXER_ST
+ if (_useMixerMT || needMtLock)
+ #endif
+ {
+ CLockedSequentialInStreamMT *lockedStreamImpSpec = new CLockedSequentialInStreamMT;
+ packStream = lockedStreamImpSpec;
+ lockedStreamImpSpec->Init(lockedInStreamSpec, packPos);
+ }
+ #ifdef USE_MIXER_ST
+ else
+ #endif
+ #endif
+ {
+ #ifdef USE_MIXER_ST
+ CLockedSequentialInStreamST *lockedStreamImpSpec = new CLockedSequentialInStreamST;
+ packStream = lockedStreamImpSpec;
+ lockedStreamImpSpec->Init(lockedInStreamSpec, packPos);
+ #endif
+ }
+ }
+
+ CLimitedSequentialInStream *streamSpec = new CLimitedSequentialInStream;
+ inStreams.AddNew() = streamSpec;
+ streamSpec->SetStream(packStream);
+ streamSpec->Init(packPositions[j + 1] - packPositions[j]);
+ }
+
+ unsigned num = inStreams.Size();
+ CObjArray<ISequentialInStream *> inStreamPointers(num);
+ for (i = 0; i < num; i++)
+ inStreamPointers[i] = inStreams[i];
+
+ if (outStream)
+ {
+ CMyComPtr<ICompressProgressInfo> progress2;
+ if (compressProgress && !_mixer->Is_PackSize_Correct_for_Coder(_mixer->MainCoderIndex))
+ progress2 = new CDecProgress(compressProgress);
+
+ ISequentialOutStream *outStreamPointer = outStream;
+ return _mixer->Code(inStreamPointers, &outStreamPointer, progress2 ? (ICompressProgressInfo *)progress2 : compressProgress);
+ }
+
+ #ifdef USE_MIXER_ST
+ return _mixerST->GetMainUnpackStream(inStreamPointers, inStreamMainRes);
+ #else
+ return E_FAIL;
+ #endif
}
}}