diff options
author | Igor Pavlov <ipavlov@users.sourceforge.net> | 2015-06-15 03:00:00 +0300 |
---|---|---|
committer | Kornel LesiĆski <kornel@geekhood.net> | 2016-05-28 02:16:54 +0300 |
commit | 54490d51d5c6b0d794dcbad2d634d4c95fc25b6c (patch) | |
tree | c3c413656432c0ef87b2841c80e42b55ad17d4e8 /CPP/7zip/Archive/Common | |
parent | 0713a3ab803e57401f18432148b4139e5fe6e5dd (diff) |
15.0515.05
Diffstat (limited to 'CPP/7zip/Archive/Common')
-rw-r--r-- | CPP/7zip/Archive/Common/CoderMixer2.cpp | 1061 | ||||
-rw-r--r-- | CPP/7zip/Archive/Common/CoderMixer2.h | 462 | ||||
-rw-r--r-- | CPP/7zip/Archive/Common/CoderMixer2MT.cpp | 242 | ||||
-rw-r--r-- | CPP/7zip/Archive/Common/CoderMixer2MT.h | 84 | ||||
-rw-r--r-- | CPP/7zip/Archive/Common/CoderMixer2ST.cpp | 595 | ||||
-rw-r--r-- | CPP/7zip/Archive/Common/CoderMixer2ST.h | 165 | ||||
-rw-r--r-- | CPP/7zip/Archive/Common/CoderMixerMT.h | 2 | ||||
-rw-r--r-- | CPP/7zip/Archive/Common/HandlerOut.cpp | 32 | ||||
-rw-r--r-- | CPP/7zip/Archive/Common/HandlerOut.h | 4 | ||||
-rw-r--r-- | CPP/7zip/Archive/Common/OutStreamWithSha1.cpp | 4 | ||||
-rw-r--r-- | CPP/7zip/Archive/Common/OutStreamWithSha1.h | 10 |
11 files changed, 2127 insertions, 534 deletions
diff --git a/CPP/7zip/Archive/Common/CoderMixer2.cpp b/CPP/7zip/Archive/Common/CoderMixer2.cpp index 13019d1f..41b5805c 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2.cpp +++ b/CPP/7zip/Archive/Common/CoderMixer2.cpp @@ -4,116 +4,1041 @@ #include "CoderMixer2.h" -namespace NCoderMixer { +#ifdef USE_MIXER_ST -CBindReverseConverter::CBindReverseConverter(const CBindInfo &srcBindInfo): - _srcBindInfo(srcBindInfo) +STDMETHODIMP CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize) { - srcBindInfo.GetNumStreams(NumSrcInStreams, _numSrcOutStreams); + UInt32 realProcessed = 0; + HRESULT result = S_OK; + if (_stream) + result = _stream->Read(data, size, &realProcessed); + _size += realProcessed; + if (size != 0 && realProcessed == 0) + _wasFinished = true; + if (processedSize) + *processedSize = realProcessed; + return result; +} + - UInt32 j; - _srcInToDestOutMap.ClearAndSetSize(NumSrcInStreams); - DestOutToSrcInMap.ClearAndSetSize(NumSrcInStreams); +STDMETHODIMP COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize) +{ + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, size, &size); + _size += size; + if (processedSize) + *processedSize = size; + return result; +} - for (j = 0; j < NumSrcInStreams; j++) +STDMETHODIMP COutStreamCalcSize::OutStreamFinish() +{ + HRESULT result = S_OK; + if (_stream) { - _srcInToDestOutMap[j] = 0; - DestOutToSrcInMap[j] = 0; + CMyComPtr<IOutStreamFinish> outStreamFinish; + _stream.QueryInterface(IID_IOutStreamFinish, &outStreamFinish); + if (outStreamFinish) + result = outStreamFinish->OutStreamFinish(); } + return result; +} - _srcOutToDestInMap.ClearAndSetSize(_numSrcOutStreams); - _destInToSrcOutMap.ClearAndSetSize(_numSrcOutStreams); +#endif - for (j = 0; j < _numSrcOutStreams; j++) + + + +namespace NCoderMixer2 { + +static void BoolVector_Fill_False(CBoolVector &v, unsigned size) +{ + v.ClearAndSetSize(size); + bool *p = &v[0]; + for (unsigned i = 0; i < size; i++) + p[i] = false; +} + +class CBondsChecks +{ + CBoolVector _coderUsed; + + bool Init(); + bool CheckCoder(unsigned coderIndex); +public: + const CBindInfo *BindInfo; + + bool Check(); +}; + +bool CBondsChecks::CheckCoder(unsigned coderIndex) +{ + const CCoderStreamsInfo &coder = BindInfo->Coders[coderIndex]; + + if (coderIndex >= _coderUsed.Size() || _coderUsed[coderIndex]) + return false; + _coderUsed[coderIndex] = true; + + UInt32 start = BindInfo->Coder_to_Stream[coderIndex]; + + for (unsigned i = 0; i < coder.NumStreams; i++) { - _srcOutToDestInMap[j] = 0; - _destInToSrcOutMap[j] = 0; + UInt32 ind = start + i; + + if (BindInfo->IsStream_in_PackStreams(ind)) + continue; + + int bond = BindInfo->FindBond_for_PackStream(ind); + if (bond < 0) + return false; + if (!CheckCoder(BindInfo->Bonds[bond].UnpackIndex)) + return false; } + + return true; +} + +bool CBondsChecks::Check() +{ + BoolVector_Fill_False(_coderUsed, BindInfo->Coders.Size()); + + if (!CheckCoder(BindInfo->UnpackCoder)) + return false; + + FOR_VECTOR(i, _coderUsed) + if (!_coderUsed[i]) + return false; + + return true; +} + +void CBindInfo::ClearMaps() +{ + Coder_to_Stream.Clear(); + Stream_to_Coder.Clear(); +} - UInt32 destInOffset = 0; - UInt32 destOutOffset = 0; - UInt32 srcInOffset = NumSrcInStreams; - UInt32 srcOutOffset = _numSrcOutStreams; +bool CBindInfo::CalcMapsAndCheck() +{ + ClearMaps(); + + UInt32 numStreams = 0; + + if (Coders.Size() == 0) + return false; + if (Coders.Size() - 1 != Bonds.Size()) + return false; - for (int i = srcBindInfo.Coders.Size() - 1; i >= 0; i--) + FOR_VECTOR(i, Coders) { - const CCoderStreamsInfo &srcCoderInfo = srcBindInfo.Coders[i]; + Coder_to_Stream.Add(numStreams); + + const CCoderStreamsInfo &c = Coders[i]; + + for (unsigned j = 0; j < c.NumStreams; j++) + Stream_to_Coder.Add(i); + + numStreams += c.NumStreams; + } + + if (numStreams != GetNum_Bonds_and_PackStreams()) + return false; + + CBondsChecks bc; + bc.BindInfo = this; + return bc.Check(); +} + + +void CCoder::SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes) +{ + if (unpackSize) + { + UnpackSize = *unpackSize; + UnpackSizePointer = &UnpackSize; + } + else + { + UnpackSize = 0; + UnpackSizePointer = NULL; + } + + PackSizes.ClearAndSetSize((unsigned)NumStreams); + PackSizePointers.ClearAndSetSize((unsigned)NumStreams); + + for (unsigned i = 0; i < NumStreams; i++) + { + if (packSizes && packSizes[i]) + { + PackSizes[i] = *(packSizes[i]); + PackSizePointers[i] = &PackSizes[i]; + } + else + { + PackSizes[i] = 0; + PackSizePointers[i] = NULL; + } + } +} + +bool CMixer::Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex) +{ + if (coderIndex == _bi.UnpackCoder) + return true; + + int bond = _bi.FindBond_for_UnpackStream(coderIndex); + if (bond < 0) + throw 20150213; + + /* + UInt32 coderIndex, coderStreamIndex; + _bi.GetCoder_for_Stream(_bi.Bonds[bond].PackIndex, coderIndex, coderStreamIndex); + */ + UInt32 nextCoder = _bi.Stream_to_Coder[_bi.Bonds[bond].PackIndex]; + + if (!IsFilter_Vector[nextCoder]) + return false; + + return Is_UnpackSize_Correct_for_Coder(nextCoder); +} + +bool CMixer::Is_PackSize_Correct_for_Stream(UInt32 streamIndex) +{ + if (_bi.IsStream_in_PackStreams(streamIndex)) + return true; + + int bond = _bi.FindBond_for_PackStream(streamIndex); + if (bond < 0) + throw 20150213; + + UInt32 nextCoder = _bi.Bonds[bond].UnpackIndex; + + if (!IsFilter_Vector[nextCoder]) + return false; + + return Is_PackSize_Correct_for_Coder(nextCoder); +} + +bool CMixer::Is_PackSize_Correct_for_Coder(UInt32 coderIndex) +{ + UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; + UInt32 numStreams = _bi.Coders[coderIndex].NumStreams; + for (UInt32 i = 0; i < numStreams; i++) + if (!Is_PackSize_Correct_for_Stream(startIndex + i)) + return false; + return true; +} + +bool CMixer::IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex) +{ + if (IsExternal_Vector[coderIndex]) + return true; + UInt32 startIndex = _bi.Coder_to_Stream[coderIndex]; + UInt32 numStreams = _bi.Coders[coderIndex].NumStreams; + for (UInt32 i = 0; i < numStreams; i++) + { + UInt32 si = startIndex + i; + if (_bi.IsStream_in_PackStreams(si)) + continue; + + int bond = _bi.FindBond_for_PackStream(si); + if (bond < 0) + throw 20150213; + + if (IsThere_ExternalCoder_in_PackTree(_bi.Bonds[bond].UnpackIndex)) + return true; + } + return false; +} + + + + +#ifdef USE_MIXER_ST + +CMixerST::CMixerST(bool encodeMode): + CMixer(encodeMode) + {} + +CMixerST::~CMixerST() {} + +void CMixerST::AddCoder(const CCreatedCoder &cod) +{ + IsFilter_Vector.Add(cod.IsFilter); + IsExternal_Vector.Add(cod.IsExternal); + // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()]; + CCoderST &c2 = _coders.AddNew(); + c2.NumStreams = cod.NumStreams; + c2.Coder = cod.Coder; + c2.Coder2 = cod.Coder2; - srcInOffset -= srcCoderInfo.NumInStreams; - srcOutOffset -= srcCoderInfo.NumOutStreams; + /* + if (isFilter) + { + c2.CanRead = true; + c2.CanWrite = true; + } + else + */ + { + IUnknown *unk = (cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2); + { + CMyComPtr<ISequentialInStream> s; + unk->QueryInterface(IID_ISequentialInStream, (void**)&s); + c2.CanRead = (s != NULL); + } + { + CMyComPtr<ISequentialOutStream> s; + unk->QueryInterface(IID_ISequentialOutStream, (void**)&s); + c2.CanWrite = (s != NULL); + } + } +} + +CCoder &CMixerST::GetCoder(unsigned index) +{ + return _coders[index]; +} + +void CMixerST::ReInit() {} + +HRESULT CMixerST::GetInStream2( + ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ + UInt32 outStreamIndex, ISequentialInStream **inStreamRes) +{ + UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0; + + if (EncodeMode) + { + _bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex); + if (coderStreamIndex != 0) + return E_NOTIMPL; + } + + const CCoder &coder = _coders[coderIndex]; + + CMyComPtr<ISequentialInStream> seqInStream; + coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream); + if (!seqInStream) + return E_NOTIMPL; + + UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams; + UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex]; + + bool isSet = false; + + if (numInStreams == 1) + { + CMyComPtr<ICompressSetInStream> setStream; + coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream); + if (setStream) + { + CMyComPtr<ISequentialInStream> seqInStream2; + RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2)); + RINOK(setStream->SetInStream(seqInStream2)); + isSet = true; + } + } + + if (!isSet && numInStreams != 0) + { + CMyComPtr<ICompressSetInStream2> setStream2; + coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2); + if (!setStream2) + return E_NOTIMPL; - UInt32 j; - for (j = 0; j < srcCoderInfo.NumInStreams; j++, destOutOffset++) + for (UInt32 i = 0; i < numInStreams; i++) + { + CMyComPtr<ISequentialInStream> seqInStream2; + RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2)); + RINOK(setStream2->SetInStream2(i, seqInStream2)); + } + } + + *inStreamRes = seqInStream.Detach(); + return S_OK; +} + + +HRESULT CMixerST::GetInStream( + ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ + UInt32 inStreamIndex, ISequentialInStream **inStreamRes) +{ + CMyComPtr<ISequentialInStream> seqInStream; + + { + int index = -1; + if (EncodeMode) + { + if (_bi.UnpackCoder == inStreamIndex) + index = 0; + } + else + index = _bi.FindStream_in_PackStreams(inStreamIndex); + + if (index >= 0) + { + seqInStream = inStreams[(unsigned)index]; + *inStreamRes = seqInStream.Detach(); + return S_OK; + } + } + + int bond = FindBond_for_Stream( + true, // forInputStream + inStreamIndex); + if (bond < 0) + return E_INVALIDARG; + + RINOK(GetInStream2(inStreams, /* inSizes, */ + _bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream)); + + while (_binderStreams.Size() <= (unsigned)bond) + _binderStreams.AddNew(); + CStBinderStream &bs = _binderStreams[bond]; + + if (bs.StreamRef || bs.InStreamSpec) + return E_NOTIMPL; + + CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize; + bs.StreamRef = spec; + bs.InStreamSpec = spec; + + spec->SetStream(seqInStream); + spec->Init(); + + seqInStream = bs.InStreamSpec; + + *inStreamRes = seqInStream.Detach(); + return S_OK; +} + + +HRESULT CMixerST::GetOutStream( + ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */ + UInt32 outStreamIndex, ISequentialOutStream **outStreamRes) +{ + CMyComPtr<ISequentialOutStream> seqOutStream; + + { + int index = -1; + if (!EncodeMode) + { + if (_bi.UnpackCoder == outStreamIndex) + index = 0; + } + else + index = _bi.FindStream_in_PackStreams(outStreamIndex); + + if (index >= 0) + { + seqOutStream = outStreams[(unsigned)index]; + *outStreamRes = seqOutStream.Detach(); + return S_OK; + } + } + + int bond = FindBond_for_Stream( + false, // forInputStream + outStreamIndex); + if (bond < 0) + return E_INVALIDARG; + + UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode); + + UInt32 coderIndex = inStreamIndex; + UInt32 coderStreamIndex = 0; + + if (!EncodeMode) + _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex); + + CCoder &coder = _coders[coderIndex]; + + /* + if (!coder.Coder) + return E_NOTIMPL; + */ + + coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream); + if (!seqOutStream) + return E_NOTIMPL; + + UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1; + UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex; + + bool isSet = false; + + if (numOutStreams == 1) + { + CMyComPtr<ICompressSetOutStream> setOutStream; + coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream); + if (setOutStream) + { + CMyComPtr<ISequentialOutStream> seqOutStream2; + RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2)); + RINOK(setOutStream->SetOutStream(seqOutStream2)); + isSet = true; + } + } + + if (!isSet && numOutStreams != 0) + { + return E_NOTIMPL; + /* + CMyComPtr<ICompressSetOutStream2> setStream2; + coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2); + if (!setStream2) + return E_NOTIMPL; + for (UInt32 i = 0; i < numOutStreams; i++) + { + CMyComPtr<ISequentialOutStream> seqOutStream2; + RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2)); + RINOK(setStream2->SetOutStream2(i, seqOutStream2)); + } + */ + } + + while (_binderStreams.Size() <= (unsigned)bond) + _binderStreams.AddNew(); + CStBinderStream &bs = _binderStreams[bond]; + + if (bs.StreamRef || bs.OutStreamSpec) + return E_NOTIMPL; + + COutStreamCalcSize *spec = new COutStreamCalcSize; + bs.StreamRef = (ISequentialOutStream *)spec; + bs.OutStreamSpec = spec; + + spec->SetStream(seqOutStream); + spec->Init(); + + seqOutStream = bs.OutStreamSpec; + + *outStreamRes = seqOutStream.Detach(); + return S_OK; +} + + +static HRESULT GetError(HRESULT res, HRESULT res2) +{ + if (res == res2) + return res; + if (res == S_OK) + return res2; + if (res == k_My_HRESULT_WritingWasCut) + { + if (res2 != S_OK) + return res2; + } + return res; +} + + +HRESULT CMixerST::FinishStream(UInt32 streamIndex) +{ + { + int index = -1; + if (!EncodeMode) { - UInt32 index = srcInOffset + j; - _srcInToDestOutMap[index] = destOutOffset; - DestOutToSrcInMap[destOutOffset] = index; + if (_bi.UnpackCoder == streamIndex) + index = 0; } - for (j = 0; j < srcCoderInfo.NumOutStreams; j++, destInOffset++) + else + index = _bi.FindStream_in_PackStreams(streamIndex); + + if (index >= 0) + return S_OK; + } + + int bond = FindBond_for_Stream( + false, // forInputStream + streamIndex); + if (bond < 0) + return E_INVALIDARG; + + UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode); + + UInt32 coderIndex = inStreamIndex; + UInt32 coderStreamIndex = 0; + if (!EncodeMode) + _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex); + + CCoder &coder = _coders[coderIndex]; + CMyComPtr<IOutStreamFinish> finish; + coder.QueryInterface(IID_IOutStreamFinish, (void **)&finish); + HRESULT res = S_OK; + if (finish) + { + res = finish->OutStreamFinish(); + } + return GetError(res, FinishCoder(coderIndex)); +} + + +HRESULT CMixerST::FinishCoder(UInt32 coderIndex) +{ + CCoder &coder = _coders[coderIndex]; + + UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1; + UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex; + + HRESULT res = S_OK; + for (unsigned i = 0; i < numOutStreams; i++) + res = GetError(res, FinishStream(startIndex + i)); + return res; +} + + +void CMixerST::SelectMainCoder(bool useFirst) +{ + unsigned ci = _bi.UnpackCoder; + + int firstNonFilter = -1; + int firstAllowed = ci; + + for (;;) + { + const CCoderST &coder = _coders[ci]; + // break; + + if (ci != _bi.UnpackCoder) + if (EncodeMode ? !coder.CanWrite : !coder.CanRead) + { + firstAllowed = ci; + firstNonFilter = -2; + } + + if (coder.NumStreams != 1) + break; + + UInt32 st = _bi.Coder_to_Stream[ci]; + if (_bi.IsStream_in_PackStreams(st)) + break; + int bond = _bi.FindBond_for_PackStream(st); + if (bond < 0) + throw 20150213; + + if (EncodeMode ? !coder.CanRead : !coder.CanWrite) + break; + + if (firstNonFilter == -1 && !IsFilter_Vector[ci]) + firstNonFilter = ci; + + ci = _bi.Bonds[bond].UnpackIndex; + } + + if (useFirst) + ci = firstAllowed; + else if (firstNonFilter >= 0) + ci = firstNonFilter; + + MainCoderIndex = ci; +} + + +HRESULT CMixerST::Code( + ISequentialInStream * const *inStreams, + ISequentialOutStream * const *outStreams, + ICompressProgressInfo *progress) +{ + _binderStreams.Clear(); + unsigned ci = MainCoderIndex; + + const CCoder &mainCoder = _coders[MainCoderIndex]; + + CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams; + CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams; + + UInt32 numInStreams = EncodeMode ? 1 : mainCoder.NumStreams; + UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams; + + UInt32 startInIndex = EncodeMode ? ci : _bi.Coder_to_Stream[ci]; + UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci]; + + UInt32 i; + + for (i = 0; i < numInStreams; i++) + { + CMyComPtr<ISequentialInStream> seqInStream; + RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream)); + seqInStreams.Add(seqInStream); + } + + for (i = 0; i < numOutStreams; i++) + { + CMyComPtr<ISequentialOutStream> seqOutStream; + RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream)); + seqOutStreams.Add(seqOutStream); + } + + CRecordVector< ISequentialInStream * > seqInStreamsSpec; + CRecordVector< ISequentialOutStream * > seqOutStreamsSpec; + + for (i = 0; i < numInStreams; i++) + seqInStreamsSpec.Add(seqInStreams[i]); + for (i = 0; i < numOutStreams; i++) + seqOutStreamsSpec.Add(seqOutStreams[i]); + + for (i = 0; i < _coders.Size(); i++) + { + if (i == ci) + continue; + + CCoder &coder = _coders[i]; + + if (EncodeMode) + { + CMyComPtr<ICompressInitEncoder> initEncoder; + coder.QueryInterface(IID_ICompressInitEncoder, (void **)&initEncoder); + if (initEncoder) + RINOK(initEncoder->InitEncoder()); + } + else + { + CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize; + coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize); + if (setOutStreamSize) + RINOK(setOutStreamSize->SetOutStreamSize( + EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer)); + } + } + + const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : &mainCoder.PackSizePointers.Front(); + const UInt64 * const *outSizes2 = EncodeMode ? &mainCoder.PackSizePointers.Front() : &mainCoder.UnpackSizePointer; + + HRESULT res; + if (mainCoder.Coder) + { + res = mainCoder.Coder->Code( + seqInStreamsSpec[0], seqOutStreamsSpec[0], + isSizes2[0], outSizes2[0], + progress); + } + else + { + res = mainCoder.Coder2->Code( + &seqInStreamsSpec.Front(), isSizes2, numInStreams, + &seqOutStreamsSpec.Front(), outSizes2, numOutStreams, + progress); + } + + if (res == k_My_HRESULT_WritingWasCut) + res = S_OK; + + if (res == S_OK || res == S_FALSE) + { + res = GetError(res, FinishCoder(ci)); + } + + for (i = 0; i < _binderStreams.Size(); i++) + { + const CStBinderStream &bs = _binderStreams[i]; + if (bs.InStreamSpec) + bs.InStreamSpec->ReleaseStream(); + else + bs.OutStreamSpec->ReleaseStream(); + } + + if (res == k_My_HRESULT_WritingWasCut) + res = S_OK; + return res; +} + + +HRESULT CMixerST::GetMainUnpackStream( + ISequentialInStream * const *inStreams, + ISequentialInStream **inStreamRes) +{ + CMyComPtr<ISequentialInStream> seqInStream; + + RINOK(GetInStream2(inStreams, /* inSizes, */ + _bi.UnpackCoder, &seqInStream)) + + FOR_VECTOR (i, _coders) + { + CCoder &coder = _coders[i]; + CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize; + coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize); + if (setOutStreamSize) { - UInt32 index = srcOutOffset + j; - _srcOutToDestInMap[index] = destInOffset; - _destInToSrcOutMap[destInOffset] = index; + RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer)); } } + + *inStreamRes = seqInStream.Detach(); + return S_OK; } -void CBindReverseConverter::CreateReverseBindInfo(CBindInfo &destBindInfo) + +UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const { - destBindInfo.Coders.ClearAndReserve(_srcBindInfo.Coders.Size()); - destBindInfo.BindPairs.ClearAndReserve(_srcBindInfo.BindPairs.Size()); - destBindInfo.InStreams.ClearAndReserve(_srcBindInfo.OutStreams.Size()); - destBindInfo.OutStreams.ClearAndReserve(_srcBindInfo.InStreams.Size()); + const CStBinderStream &bs = _binderStreams[bondIndex]; + if (bs.InStreamSpec) + return bs.InStreamSpec->GetSize(); + return bs.OutStreamSpec->GetSize(); +} + +#endif + + + + + + +#ifdef USE_MIXER_MT + + +void CCoderMT::Execute() +{ + try + { + Code(NULL); + } + catch(...) + { + Result = E_FAIL; + } +} + +void CCoderMT::Code(ICompressProgressInfo *progress) +{ + unsigned numInStreams = EncodeMode ? 1 : NumStreams; + unsigned numOutStreams = EncodeMode ? NumStreams : 1; + + InStreamPointers.ClearAndReserve(numInStreams); + OutStreamPointers.ClearAndReserve(numOutStreams); unsigned i; - for (i = _srcBindInfo.Coders.Size(); i != 0;) + + for (i = 0; i < numInStreams; i++) + InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]); + + for (i = 0; i < numOutStreams; i++) + OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]); + + // we suppose that UnpackSizePointer and PackSizePointers contain correct pointers. + /* + if (UnpackSizePointer) + UnpackSizePointer = &UnpackSize; + for (i = 0; i < NumStreams; i++) + if (PackSizePointers[i]) + PackSizePointers[i] = &PackSizes[i]; + */ + + CReleaser releaser(*this); + + if (Coder) + Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], + EncodeMode ? UnpackSizePointer : PackSizePointers[0], + EncodeMode ? PackSizePointers[0] : UnpackSizePointer, + progress); + else + Result = Coder2->Code( + &InStreamPointers.Front(), EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams, + &OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams, + progress); +} + +HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo) +{ + CMixer::SetBindInfo(bindInfo); + + _streamBinders.Clear(); + FOR_VECTOR (i, _bi.Bonds) { - i--; - const CCoderStreamsInfo &srcCoderInfo = _srcBindInfo.Coders[i]; - CCoderStreamsInfo destCoderInfo; - destCoderInfo.NumInStreams = srcCoderInfo.NumOutStreams; - destCoderInfo.NumOutStreams = srcCoderInfo.NumInStreams; - destBindInfo.Coders.AddInReserved(destCoderInfo); + RINOK(_streamBinders.AddNew().CreateEvents()); } - for (i = _srcBindInfo.BindPairs.Size(); i != 0;) + return S_OK; +} + +void CMixerMT::AddCoder(const CCreatedCoder &cod) +{ + IsFilter_Vector.Add(cod.IsFilter); + IsExternal_Vector.Add(cod.IsExternal); + // const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()]; + CCoderMT &c2 = _coders.AddNew(); + c2.NumStreams = cod.NumStreams; + c2.Coder = cod.Coder; + c2.Coder2 = cod.Coder2; + c2.EncodeMode = EncodeMode; +} + +CCoder &CMixerMT::GetCoder(unsigned index) +{ + return _coders[index]; +} + +void CMixerMT::ReInit() +{ + FOR_VECTOR (i, _streamBinders) + _streamBinders[i].ReInit(); +} + +void CMixerMT::SelectMainCoder(bool useFirst) +{ + unsigned ci = _bi.UnpackCoder; + + if (!useFirst) + for (;;) { - i--; - const CBindPair &srcBindPair = _srcBindInfo.BindPairs[i]; - CBindPair destBindPair; - destBindPair.InIndex = _srcOutToDestInMap[srcBindPair.OutIndex]; - destBindPair.OutIndex = _srcInToDestOutMap[srcBindPair.InIndex]; - destBindInfo.BindPairs.AddInReserved(destBindPair); + if (_coders[ci].NumStreams != 1) + break; + if (!IsFilter_Vector[ci]) + break; + + UInt32 st = _bi.Coder_to_Stream[ci]; + if (_bi.IsStream_in_PackStreams(st)) + break; + int bond = _bi.FindBond_for_PackStream(st); + if (bond < 0) + throw 20150213; + ci = _bi.Bonds[bond].UnpackIndex; } - for (i = 0; i < _srcBindInfo.InStreams.Size(); i++) - destBindInfo.OutStreams.AddInReserved(_srcInToDestOutMap[_srcBindInfo.InStreams[i]]); - for (i = 0; i < _srcBindInfo.OutStreams.Size(); i++) - destBindInfo.InStreams.AddInReserved(_srcOutToDestInMap[_srcBindInfo.OutStreams[i]]); + + MainCoderIndex = ci; } -void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, - CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems) +HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams) { - sizes.ClearAndSetSize(numItems); - sizePointers.ClearAndSetSize(numItems); - for(UInt32 i = 0; i < numItems; i++) + unsigned i; + + for (i = 0; i < _coders.Size(); i++) + { + CCoderMT &coderInfo = _coders[i]; + const CCoderStreamsInfo &csi = _bi.Coders[i]; + + UInt32 j; + + unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams; + unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1; + + coderInfo.InStreams.Clear(); + for (j = 0; j < numInStreams; j++) + coderInfo.InStreams.AddNew(); + + coderInfo.OutStreams.Clear(); + for (j = 0; j < numOutStreams; j++) + coderInfo.OutStreams.AddNew(); + } + + for (i = 0; i < _bi.Bonds.Size(); i++) { - if (!srcSizes || !srcSizes[i]) + const CBond &bond = _bi.Bonds[i]; + + UInt32 inCoderIndex, inCoderStreamIndex; + UInt32 outCoderIndex, outCoderStreamIndex; + + { + UInt32 coderIndex, coderStreamIndex; + _bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex); + + inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex; + outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex; + + inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex; + outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0; + } + + _streamBinders[i].CreateStreams( + &_coders[inCoderIndex].InStreams[inCoderStreamIndex], + &_coders[outCoderIndex].OutStreams[outCoderStreamIndex]); + + CMyComPtr<ICompressSetBufSize> inSetSize, outSetSize; + _coders[inCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&inSetSize); + _coders[outCoderIndex].QueryInterface(IID_ICompressSetBufSize, (void **)&outSetSize); + if (inSetSize && outSetSize) { - sizes[i] = 0; - sizePointers[i] = NULL; + const UInt32 kBufSize = 1 << 19; + inSetSize->SetInBufSize(inCoderStreamIndex, kBufSize); + outSetSize->SetOutBufSize(outCoderStreamIndex, kBufSize); } + } + + { + CCoderMT &cod = _coders[_bi.UnpackCoder]; + if (EncodeMode) + cod.InStreams[0] = inStreams[0]; else + cod.OutStreams[0] = outStreams[0]; + } + + for (i = 0; i < _bi.PackStreams.Size(); i++) + { + UInt32 coderIndex, coderStreamIndex; + _bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex); + CCoderMT &cod = _coders[coderIndex]; + if (EncodeMode) + cod.OutStreams[coderStreamIndex] = outStreams[i]; + else + cod.InStreams[coderStreamIndex] = inStreams[i]; + } + + return S_OK; +} + +HRESULT CMixerMT::ReturnIfError(HRESULT code) +{ + FOR_VECTOR (i, _coders) + if (_coders[i].Result == code) + return code; + return S_OK; +} + +HRESULT CMixerMT::Code( + ISequentialInStream * const *inStreams, + ISequentialOutStream * const *outStreams, + ICompressProgressInfo *progress) +{ + Init(inStreams, outStreams); + + unsigned i; + for (i = 0; i < _coders.Size(); i++) + if (i != MainCoderIndex) { - sizes[i] = *(srcSizes[i]); - sizePointers[i] = &sizes[i]; + RINOK(_coders[i].Create()); } + + for (i = 0; i < _coders.Size(); i++) + if (i != MainCoderIndex) + _coders[i].Start(); + + _coders[MainCoderIndex].Code(progress); + + for (i = 0; i < _coders.Size(); i++) + if (i != MainCoderIndex) + _coders[i].WaitExecuteFinish(); + + RINOK(ReturnIfError(E_ABORT)); + RINOK(ReturnIfError(E_OUTOFMEMORY)); + + for (i = 0; i < _coders.Size(); i++) + { + HRESULT result = _coders[i].Result; + if (result != S_OK + && result != k_My_HRESULT_WritingWasCut + && result != S_FALSE + && result != E_FAIL) + return result; + } + + RINOK(ReturnIfError(S_FALSE)); + + for (i = 0; i < _coders.Size(); i++) + { + HRESULT result = _coders[i].Result; + if (result != S_OK && result != k_My_HRESULT_WritingWasCut) + return result; } + + return S_OK; } -void CCoderInfo2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) +UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const { - SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); - SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); + return _streamBinders[bondIndex].ProcessedSize; } +#endif + } diff --git a/CPP/7zip/Archive/Common/CoderMixer2.h b/CPP/7zip/Archive/Common/CoderMixer2.h index 50e7077a..e63f2ff0 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2.h +++ b/CPP/7zip/Archive/Common/CoderMixer2.h @@ -8,172 +8,430 @@ #include "../../ICoder.h" -namespace NCoderMixer { +#include "../../Common/CreateCoder.h" -struct CBindPair +#ifdef _7ZIP_ST + #define USE_MIXER_ST +#else + #define USE_MIXER_MT + #ifndef _SFX + #define USE_MIXER_ST + #endif +#endif + +#ifdef USE_MIXER_MT +#include "../../Common/StreamBinder.h" +#include "../../Common/VirtThread.h" +#endif + + + +#ifdef USE_MIXER_ST + +class CSequentialInStreamCalcSize: + public ISequentialInStream, + public CMyUnknownImp +{ +public: + MY_UNKNOWN_IMP1(ISequentialInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +private: + CMyComPtr<ISequentialInStream> _stream; + UInt64 _size; + bool _wasFinished; +public: + void SetStream(ISequentialInStream *stream) { _stream = stream; } + void Init() + { + _size = 0; + _wasFinished = false; + } + void ReleaseStream() { _stream.Release(); } + UInt64 GetSize() const { return _size; } + bool WasFinished() const { return _wasFinished; } +}; + + +class COutStreamCalcSize: + public ISequentialOutStream, + public IOutStreamFinish, + public CMyUnknownImp +{ + CMyComPtr<ISequentialOutStream> _stream; + UInt64 _size; +public: + MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFinish) + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(OutStreamFinish)(); + + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void ReleaseStream() { _stream.Release(); } + void Init() { _size = 0; } + UInt64 GetSize() const { return _size; } +}; + +#endif + + + +namespace NCoderMixer2 { + +struct CBond { - UInt32 InIndex; - UInt32 OutIndex; + UInt32 PackIndex; + UInt32 UnpackIndex; + + UInt32 Get_InIndex(bool encodeMode) const { return encodeMode ? UnpackIndex : PackIndex; } + UInt32 Get_OutIndex(bool encodeMode) const { return encodeMode ? PackIndex : UnpackIndex; } }; + struct CCoderStreamsInfo { - UInt32 NumInStreams; - UInt32 NumOutStreams; + UInt32 NumStreams; }; + struct CBindInfo { CRecordVector<CCoderStreamsInfo> Coders; - CRecordVector<CBindPair> BindPairs; - CRecordVector<UInt32> InStreams; - CRecordVector<UInt32> OutStreams; + CRecordVector<CBond> Bonds; + CRecordVector<UInt32> PackStreams; + unsigned UnpackCoder; - void Clear() + unsigned GetNum_Bonds_and_PackStreams() const { return Bonds.Size() + PackStreams.Size(); } + + int FindBond_for_PackStream(UInt32 packStream) const { - Coders.Clear(); - BindPairs.Clear(); - InStreams.Clear(); - OutStreams.Clear(); + FOR_VECTOR (i, Bonds) + if (Bonds[i].PackIndex == packStream) + return i; + return -1; } - /* - UInt32 GetCoderStartOutStream(UInt32 coderIndex) const + int FindBond_for_UnpackStream(UInt32 unpackStream) const { - UInt32 numOutStreams = 0; - for (UInt32 i = 0; i < coderIndex; i++) - numOutStreams += Coders[i].NumOutStreams; - return numOutStreams; + FOR_VECTOR (i, Bonds) + if (Bonds[i].UnpackIndex == unpackStream) + return i; + return -1; } - */ - - void GetNumStreams(UInt32 &numInStreams, UInt32 &numOutStreams) const + bool SetUnpackCoder() { - numInStreams = 0; - numOutStreams = 0; - FOR_VECTOR (i, Coders) + bool isOk = false; + FOR_VECTOR(i, Coders) { - const CCoderStreamsInfo &coderStreamsInfo = Coders[i]; - numInStreams += coderStreamsInfo.NumInStreams; - numOutStreams += coderStreamsInfo.NumOutStreams; + if (FindBond_for_UnpackStream(i) < 0) + { + if (isOk) + return false; + UnpackCoder = i; + isOk = true; + } } + return isOk; } - - int FindBinderForInStream(UInt32 inStream) const + + bool IsStream_in_PackStreams(UInt32 streamIndex) const { - FOR_VECTOR (i, BindPairs) - if (BindPairs[i].InIndex == inStream) - return i; - return -1; + return FindStream_in_PackStreams(streamIndex) >= 0; } - int FindBinderForOutStream(UInt32 outStream) const + + int FindStream_in_PackStreams(UInt32 streamIndex) const { - FOR_VECTOR (i, BindPairs) - if (BindPairs[i].OutIndex == outStream) + FOR_VECTOR(i, PackStreams) + if (PackStreams[i] == streamIndex) return i; return -1; } - UInt32 GetCoderInStreamIndex(UInt32 coderIndex) const + + // that function is used before Maps is calculated + + UInt32 GetStream_for_Coder(UInt32 coderIndex) const { UInt32 streamIndex = 0; for (UInt32 i = 0; i < coderIndex; i++) - streamIndex += Coders[i].NumInStreams; + streamIndex += Coders[i].NumStreams; return streamIndex; } + + // ---------- Maps Section ---------- + + CRecordVector<UInt32> Coder_to_Stream; + CRecordVector<UInt32> Stream_to_Coder; + + void ClearMaps(); + bool CalcMapsAndCheck(); + + // ---------- End of Maps Section ---------- - UInt32 GetCoderOutStreamIndex(UInt32 coderIndex) const + void Clear() { - UInt32 streamIndex = 0; - for (UInt32 i = 0; i < coderIndex; i++) - streamIndex += Coders[i].NumOutStreams; - return streamIndex; + Coders.Clear(); + Bonds.Clear(); + PackStreams.Clear(); + + ClearMaps(); } + + void GetCoder_for_Stream(UInt32 streamIndex, UInt32 &coderIndex, UInt32 &coderStreamIndex) const + { + coderIndex = Stream_to_Coder[streamIndex]; + coderStreamIndex = streamIndex - Coder_to_Stream[coderIndex]; + } +}; - void FindInStream(UInt32 streamIndex, UInt32 &coderIndex, - UInt32 &coderStreamIndex) const + +class CCoder +{ + CLASS_NO_COPY(CCoder); +public: + CMyComPtr<ICompressCoder> Coder; + CMyComPtr<ICompressCoder2> Coder2; + UInt32 NumStreams; + + UInt64 UnpackSize; + const UInt64 *UnpackSizePointer; + + CRecordVector<UInt64> PackSizes; + CRecordVector<const UInt64 *> PackSizePointers; + + CCoder() {} + + void SetCoderInfo(const UInt64 *unpackSize, const UInt64 * const *packSizes); + + IUnknown *GetUnknown() const { - for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) - { - UInt32 curSize = Coders[coderIndex].NumInStreams; - if (streamIndex < curSize) - { - coderStreamIndex = streamIndex; - return; - } - streamIndex -= curSize; - } - throw 1; + return Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; } - void FindOutStream(UInt32 streamIndex, UInt32 &coderIndex, - UInt32 &coderStreamIndex) const + + HRESULT QueryInterface(REFGUID iid, void** pp) const { - for (coderIndex = 0; coderIndex < (UInt32)Coders.Size(); coderIndex++) - { - UInt32 curSize = Coders[coderIndex].NumOutStreams; - if (streamIndex < curSize) + return GetUnknown()->QueryInterface(iid, pp); + } +}; + + + +class CMixer +{ + bool Is_PackSize_Correct_for_Stream(UInt32 streamIndex); + +protected: + CBindInfo _bi; + + int FindBond_for_Stream(bool forInputStream, UInt32 streamIndex) const + { + if (EncodeMode == forInputStream) + return _bi.FindBond_for_UnpackStream(streamIndex); + else + return _bi.FindBond_for_PackStream(streamIndex); + } + + CBoolVector IsFilter_Vector; + CBoolVector IsExternal_Vector; + bool EncodeMode; +public: + unsigned MainCoderIndex; + + CMixer(bool encodeMode): + EncodeMode(encodeMode), + MainCoderIndex(0) + {} + + /* + Sequence of calling: + + SetBindInfo(); + for each coder + AddCoder(); + SelectMainCoder(); + + for each file { - coderStreamIndex = streamIndex; - return; + ReInit() + for each coder + SetCoderInfo(); + Code(); } - streamIndex -= curSize; - } - throw 1; + */ + + virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) + { + _bi = bindInfo; + IsFilter_Vector.Clear(); + MainCoderIndex = 0; + return S_OK; } + + virtual void AddCoder(const CCreatedCoder &cod) = 0; + virtual CCoder &GetCoder(unsigned index) = 0; + virtual void SelectMainCoder(bool useFirst) = 0; + virtual void ReInit() = 0; + virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) = 0; + virtual HRESULT Code( + ISequentialInStream * const *inStreams, + ISequentialOutStream * const *outStreams, + ICompressProgressInfo *progress) = 0; + virtual UInt64 GetBondStreamSize(unsigned bondIndex) const = 0; + + bool Is_UnpackSize_Correct_for_Coder(UInt32 coderIndex); + bool Is_PackSize_Correct_for_Coder(UInt32 coderIndex); + bool IsThere_ExternalCoder_in_PackTree(UInt32 coderIndex); }; -class CBindReverseConverter + + + +#ifdef USE_MIXER_ST + +struct CCoderST: public CCoder { - UInt32 _numSrcOutStreams; - NCoderMixer::CBindInfo _srcBindInfo; - CRecordVector<UInt32> _srcInToDestOutMap; - CRecordVector<UInt32> _srcOutToDestInMap; - CRecordVector<UInt32> _destInToSrcOutMap; -public: - UInt32 NumSrcInStreams; - CRecordVector<UInt32> DestOutToSrcInMap; + bool CanRead; + bool CanWrite; + + CCoderST(): CanRead(false), CanWrite(false) {} +}; - CBindReverseConverter(const NCoderMixer::CBindInfo &srcBindInfo); - void CreateReverseBindInfo(NCoderMixer::CBindInfo &destBindInfo); + +struct CStBinderStream +{ + CSequentialInStreamCalcSize *InStreamSpec; + COutStreamCalcSize *OutStreamSpec; + CMyComPtr<IUnknown> StreamRef; + + CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {} }; -void SetSizes(const UInt64 **srcSizes, CRecordVector<UInt64> &sizes, - CRecordVector<const UInt64 *> &sizePointers, UInt32 numItems); -struct CCoderInfo2 +class CMixerST: + public IUnknown, + public CMixer, + public CMyUnknownImp { - CMyComPtr<ICompressCoder> Coder; - CMyComPtr<ICompressCoder2> Coder2; - UInt32 NumInStreams; - UInt32 NumOutStreams; + HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ + UInt32 outStreamIndex, ISequentialInStream **inStreamRes); + HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ + UInt32 inStreamIndex, ISequentialInStream **inStreamRes); + HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */ + UInt32 outStreamIndex, ISequentialOutStream **outStreamRes); - CRecordVector<UInt64> InSizes; - CRecordVector<UInt64> OutSizes; - CRecordVector<const UInt64 *> InSizePointers; - CRecordVector<const UInt64 *> OutSizePointers; + HRESULT FinishStream(UInt32 streamIndex); + HRESULT FinishCoder(UInt32 coderIndex); - CCoderInfo2(UInt32 numInStreams, UInt32 numOutStreams): - NumInStreams(numInStreams), - NumOutStreams(numOutStreams) {} - void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); +public: + CObjectVector<CCoderST> _coders; + + CObjectVector<CStBinderStream> _binderStreams; - HRESULT QueryInterface(REFGUID iid, void** pp) const + MY_UNKNOWN_IMP + + CMixerST(bool encodeMode); + ~CMixerST(); + + virtual void AddCoder(const CCreatedCoder &cod); + virtual CCoder &GetCoder(unsigned index); + virtual void SelectMainCoder(bool useFirst); + virtual void ReInit(); + virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) + { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); } + virtual HRESULT Code( + ISequentialInStream * const *inStreams, + ISequentialOutStream * const *outStreams, + ICompressProgressInfo *progress); + virtual UInt64 GetBondStreamSize(unsigned bondIndex) const; + + HRESULT GetMainUnpackStream( + ISequentialInStream * const *inStreams, + ISequentialInStream **inStreamRes); +}; + +#endif + + + + +#ifdef USE_MIXER_MT + +class CCoderMT: public CCoder, public CVirtThread +{ + CLASS_NO_COPY(CCoderMT) + CRecordVector<ISequentialInStream*> InStreamPointers; + CRecordVector<ISequentialOutStream*> OutStreamPointers; + +private: + void Execute(); +public: + bool EncodeMode; + HRESULT Result; + CObjectVector< CMyComPtr<ISequentialInStream> > InStreams; + CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams; + + void Release() { - IUnknown *p = Coder ? (IUnknown *)Coder : (IUnknown *)Coder2; - return p->QueryInterface(iid, pp); + InStreamPointers.Clear(); + OutStreamPointers.Clear(); + unsigned i; + for (i = 0; i < InStreams.Size(); i++) + InStreams[i].Release(); + for (i = 0; i < OutStreams.Size(); i++) + OutStreams[i].Release(); } + + class CReleaser + { + CLASS_NO_COPY(CReleaser) + CCoderMT &_c; + public: + CReleaser(CCoderMT &c): _c(c) {} + ~CReleaser() { _c.Release(); } + }; + + CCoderMT(): EncodeMode(false) {} + ~CCoderMT() { CVirtThread::WaitThreadFinish(); } + + void Code(ICompressProgressInfo *progress); }; -class CCoderMixer2 + +class CMixerMT: + public IUnknown, + public CMixer, + public CMyUnknownImp { + CObjectVector<CStreamBinder> _streamBinders; + + HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams); + HRESULT ReturnIfError(HRESULT code); + public: - virtual HRESULT SetBindInfo(const CBindInfo &bindInfo) = 0; - virtual void ReInit() = 0; - virtual void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) = 0; + CObjectVector<CCoderMT> _coders; + + MY_UNKNOWN_IMP + + virtual HRESULT SetBindInfo(const CBindInfo &bindInfo); + virtual void AddCoder(const CCreatedCoder &cod); + virtual CCoder &GetCoder(unsigned index); + virtual void SelectMainCoder(bool useFirst); + virtual void ReInit(); + virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) + { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); } + virtual HRESULT Code( + ISequentialInStream * const *inStreams, + ISequentialOutStream * const *outStreams, + ICompressProgressInfo *progress); + virtual UInt64 GetBondStreamSize(unsigned bondIndex) const; + + CMixerMT(bool encodeMode): CMixer(encodeMode) {} }; +#endif + } #endif diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp index 5288fbc1..c0139862 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2MT.cpp +++ b/CPP/7zip/Archive/Common/CoderMixer2MT.cpp @@ -4,125 +4,153 @@ #include "CoderMixer2MT.h" -namespace NCoderMixer { +namespace NCoderMixer2 { -CCoder2::CCoder2(UInt32 numInStreams, UInt32 numOutStreams): - CCoderInfo2(numInStreams, numOutStreams) +void CCoderMT::Execute() { Code(NULL); } + +void CCoderMT::Code(ICompressProgressInfo *progress) { - InStreams.ClearAndReserve(NumInStreams); - OutStreams.ClearAndReserve(NumOutStreams); -} + unsigned numInStreams = EncodeMode ? 1 : NumStreams; + unsigned numOutStreams = EncodeMode ? NumStreams : 1; -void CCoder2::Execute() { Code(NULL); } + InStreamPointers.ClearAndReserve(numInStreams); + OutStreamPointers.ClearAndReserve(numOutStreams); -void CCoder2::Code(ICompressProgressInfo *progress) -{ - InStreamPointers.ClearAndReserve(NumInStreams); - OutStreamPointers.ClearAndReserve(NumOutStreams); - UInt32 i; - for (i = 0; i < NumInStreams; i++) - { - if (InSizePointers[i]) - InSizePointers[i] = &InSizes[i]; + unsigned i; + + for (i = 0; i < numInStreams; i++) InStreamPointers.AddInReserved((ISequentialInStream *)InStreams[i]); - } - for (i = 0; i < NumOutStreams; i++) - { - if (OutSizePointers[i]) - OutSizePointers[i] = &OutSizes[i]; + + for (i = 0; i < numOutStreams; i++) OutStreamPointers.AddInReserved((ISequentialOutStream *)OutStreams[i]); - } + + // we suppose that UnpackSizePointer and PackSizePointers contain correct pointers. + /* + if (UnpackSizePointer) + UnpackSizePointer = &UnpackSize; + for (i = 0; i < NumStreams; i++) + if (PackSizePointers[i]) + PackSizePointers[i] = &PackSizes[i]; + */ + if (Coder) Result = Coder->Code(InStreamPointers[0], OutStreamPointers[0], - InSizePointers[0], OutSizePointers[0], progress); + EncodeMode ? UnpackSizePointer : PackSizePointers[0], + EncodeMode ? PackSizePointers[0] : UnpackSizePointer, + progress); else - Result = Coder2->Code(&InStreamPointers.Front(), &InSizePointers.Front(), NumInStreams, - &OutStreamPointers.Front(), &OutSizePointers.Front(), NumOutStreams, progress); - { - unsigned i; - for (i = 0; i < InStreams.Size(); i++) - InStreams[i].Release(); - for (i = 0; i < OutStreams.Size(); i++) - OutStreams[i].Release(); - } -} + Result = Coder2->Code( + &InStreamPointers.Front(), EncodeMode ? &UnpackSizePointer : &PackSizePointers.Front(), numInStreams, + &OutStreamPointers.Front(), EncodeMode ? &PackSizePointers.Front(): &UnpackSizePointer, numOutStreams, + progress); + + InStreamPointers.Clear(); + OutStreamPointers.Clear(); -/* -void CCoder2::SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes) -{ - SetSizes(inSizes, InSizes, InSizePointers, NumInStreams); - SetSizes(outSizes, OutSizes, OutSizePointers, NumOutStreams); + for (i = 0; i < InStreams.Size(); i++) + InStreams[i].Release(); + for (i = 0; i < OutStreams.Size(); i++) + OutStreams[i].Release(); } -*/ - -////////////////////////////////////// -// CCoderMixer2MT -HRESULT CCoderMixer2MT::SetBindInfo(const CBindInfo &bindInfo) +HRESULT CMixerMT::SetBindInfo(const CBindInfo &bindInfo) { - _bindInfo = bindInfo; + CMixer::SetBindInfo(bindInfo); + _streamBinders.Clear(); - FOR_VECTOR (i, _bindInfo.BindPairs) + FOR_VECTOR (i, _bi.Bonds) { RINOK(_streamBinders.AddNew().CreateEvents()); } return S_OK; } -void CCoderMixer2MT::AddCoderCommon() -{ - const CCoderStreamsInfo &c = _bindInfo.Coders[_coders.Size()]; - CCoder2 threadCoderInfo(c.NumInStreams, c.NumOutStreams); - _coders.Add(threadCoderInfo); -} - -void CCoderMixer2MT::AddCoder(ICompressCoder *coder) +void CMixerMT::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter) { - AddCoderCommon(); - _coders.Back().Coder = coder; + const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()]; + CCoderMT &c2 = _coders.AddNew(); + c2.NumStreams = c.NumStreams; + c2.EncodeMode = EncodeMode; + c2.Coder = coder; + c2.Coder2 = coder2; + IsFilter_Vector.Add(isFilter); } -void CCoderMixer2MT::AddCoder2(ICompressCoder2 *coder) +CCoder &CMixerMT::GetCoder(unsigned index) { - AddCoderCommon(); - _coders.Back().Coder2 = coder; + return _coders[index]; } - -void CCoderMixer2MT::ReInit() +void CMixerMT::ReInit() { FOR_VECTOR (i, _streamBinders) _streamBinders[i].ReInit(); } +void CMixerMT::SelectMainCoder(bool useFirst) +{ + unsigned ci = _bi.UnpackCoder; + + if (!useFirst) + for (;;) + { + if (_coders[ci].NumStreams != 1) + break; + if (!IsFilter_Vector[ci]) + break; + + UInt32 st = _bi.Coder_to_Stream[ci]; + if (_bi.IsStream_in_PackStreams(st)) + break; + int bond = _bi.FindBond_for_PackStream(st); + if (bond < 0) + throw 20150213; + ci = _bi.Bonds[bond].UnpackIndex; + } + + MainCoderIndex = ci; +} -HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams) +HRESULT CMixerMT::Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams) { - /* - if (_coders.Size() != _bindInfo.Coders.Size()) - throw 0; - */ unsigned i; + for (i = 0; i < _coders.Size(); i++) { - CCoder2 &coderInfo = _coders[i]; - const CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[i]; - coderInfo.InStreams.Clear(); + CCoderMT &coderInfo = _coders[i]; + const CCoderStreamsInfo &csi = _bi.Coders[i]; + UInt32 j; - for (j = 0; j < coderStreamsInfo.NumInStreams; j++) - coderInfo.InStreams.Add(NULL); + + unsigned numInStreams = EncodeMode ? 1 : csi.NumStreams; + unsigned numOutStreams = EncodeMode ? csi.NumStreams : 1; + + coderInfo.InStreams.Clear(); + for (j = 0; j < numInStreams; j++) + coderInfo.InStreams.AddNew(); + coderInfo.OutStreams.Clear(); - for (j = 0; j < coderStreamsInfo.NumOutStreams; j++) - coderInfo.OutStreams.Add(NULL); + for (j = 0; j < numOutStreams; j++) + coderInfo.OutStreams.AddNew(); } - for (i = 0; i < _bindInfo.BindPairs.Size(); i++) + for (i = 0; i < _bi.Bonds.Size(); i++) { - const CBindPair &bindPair = _bindInfo.BindPairs[i]; + const CBond &bond = _bi.Bonds[i]; + UInt32 inCoderIndex, inCoderStreamIndex; UInt32 outCoderIndex, outCoderStreamIndex; - _bindInfo.FindInStream(bindPair.InIndex, inCoderIndex, inCoderStreamIndex); - _bindInfo.FindOutStream(bindPair.OutIndex, outCoderIndex, outCoderStreamIndex); + + { + UInt32 coderIndex, coderStreamIndex; + _bi.GetCoder_for_Stream(bond.PackIndex, coderIndex, coderStreamIndex); + + inCoderIndex = EncodeMode ? bond.UnpackIndex : coderIndex; + outCoderIndex = EncodeMode ? coderIndex : bond.UnpackIndex; + + inCoderStreamIndex = EncodeMode ? 0 : coderStreamIndex; + outCoderStreamIndex = EncodeMode ? coderStreamIndex : 0; + } _streamBinders[i].CreateStreams( &_coders[inCoderIndex].InStreams[inCoderStreamIndex], @@ -139,23 +167,29 @@ HRESULT CCoderMixer2MT::Init(ISequentialInStream **inStreams, ISequentialOutStre } } - for (i = 0; i < _bindInfo.InStreams.Size(); i++) { - UInt32 inCoderIndex, inCoderStreamIndex; - _bindInfo.FindInStream(_bindInfo.InStreams[i], inCoderIndex, inCoderStreamIndex); - _coders[inCoderIndex].InStreams[inCoderStreamIndex] = inStreams[i]; + CCoderMT &cod = _coders[_bi.UnpackCoder]; + if (EncodeMode) + cod.InStreams[0] = inStreams[0]; + else + cod.OutStreams[0] = outStreams[0]; } - - for (i = 0; i < _bindInfo.OutStreams.Size(); i++) + + for (i = 0; i < _bi.PackStreams.Size(); i++) { - UInt32 outCoderIndex, outCoderStreamIndex; - _bindInfo.FindOutStream(_bindInfo.OutStreams[i], outCoderIndex, outCoderStreamIndex); - _coders[outCoderIndex].OutStreams[outCoderStreamIndex] = outStreams[i]; + UInt32 coderIndex, coderStreamIndex; + _bi.GetCoder_for_Stream(_bi.PackStreams[i], coderIndex, coderStreamIndex); + CCoderMT &cod = _coders[coderIndex]; + if (EncodeMode) + cod.OutStreams[coderStreamIndex] = outStreams[i]; + else + cod.InStreams[coderStreamIndex] = inStreams[i]; } + return S_OK; } -HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code) +HRESULT CMixerMT::ReturnIfError(HRESULT code) { FOR_VECTOR (i, _coders) if (_coders[i].Result == code) @@ -163,35 +197,28 @@ HRESULT CCoderMixer2MT::ReturnIfError(HRESULT code) return S_OK; } -STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, - const UInt64 ** /* inSizes */, - UInt32 numInStreams, - ISequentialOutStream **outStreams, - const UInt64 ** /* outSizes */, - UInt32 numOutStreams, - ICompressProgressInfo *progress) +HRESULT CMixerMT::Code( + ISequentialInStream * const *inStreams, + ISequentialOutStream * const *outStreams, + ICompressProgressInfo *progress) { - if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || - numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) - return E_INVALIDARG; - Init(inStreams, outStreams); unsigned i; for (i = 0; i < _coders.Size(); i++) - if (i != _progressCoderIndex) + if (i != MainCoderIndex) { RINOK(_coders[i].Create()); } for (i = 0; i < _coders.Size(); i++) - if (i != _progressCoderIndex) + if (i != MainCoderIndex) _coders[i].Start(); - _coders[_progressCoderIndex].Code(progress); + _coders[MainCoderIndex].Code(progress); for (i = 0; i < _coders.Size(); i++) - if (i != _progressCoderIndex) + if (i != MainCoderIndex) _coders[i].WaitExecuteFinish(); RINOK(ReturnIfError(E_ABORT)); @@ -200,7 +227,10 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; - if (result != S_OK && result != E_FAIL && result != S_FALSE) + if (result != S_OK + && result != k_My_HRESULT_WritingWasCut + && result != S_FALSE + && result != E_FAIL) return result; } @@ -209,10 +239,16 @@ STDMETHODIMP CCoderMixer2MT::Code(ISequentialInStream **inStreams, for (i = 0; i < _coders.Size(); i++) { HRESULT result = _coders[i].Result; - if (result != S_OK) + if (result != S_OK && result != k_My_HRESULT_WritingWasCut) return result; } + return S_OK; } +UInt64 CMixerMT::GetBondStreamSize(unsigned bondIndex) const +{ + return _streamBinders[bondIndex].ProcessedSize; +} + } diff --git a/CPP/7zip/Archive/Common/CoderMixer2MT.h b/CPP/7zip/Archive/Common/CoderMixer2MT.h index ba475cec..41bb3e1c 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2MT.h +++ b/CPP/7zip/Archive/Common/CoderMixer2MT.h @@ -3,81 +3,75 @@ #ifndef __CODER_MIXER2_MT_H #define __CODER_MIXER2_MT_H -#include "CoderMixer2.h" #include "../../../Common/MyCom.h" + #include "../../Common/StreamBinder.h" #include "../../Common/VirtThread.h" -namespace NCoderMixer { +#include "CoderMixer2.h" + +namespace NCoderMixer2 { -struct CCoder2: public CCoderInfo2, public CVirtThread +class CCoderMT: public CCoder, public CVirtThread { + CLASS_NO_COPY(CCoderMT) CRecordVector<ISequentialInStream*> InStreamPointers; CRecordVector<ISequentialOutStream*> OutStreamPointers; +private: + void Execute(); public: + bool EncodeMode; HRESULT Result; CObjectVector< CMyComPtr<ISequentialInStream> > InStreams; CObjectVector< CMyComPtr<ISequentialOutStream> > OutStreams; - CCoder2(UInt32 numInStreams, UInt32 numOutStreams); - ~CCoder2() { CVirtThread::WaitThreadFinish(); } - // void SetCoderInfo(const UInt64 **inSizes, const UInt64 **outSizes); - virtual void Execute(); + CCoderMT(): EncodeMode(false) {} + ~CCoderMT() { CVirtThread::WaitThreadFinish(); } + void Code(ICompressProgressInfo *progress); }; -/* - SetBindInfo() - for each coder - AddCoder[2]() - SetProgressIndex(UInt32 coderIndex); - - for each file - { - ReInit() - for each coder - SetCoderInfo - Code - } -*/ - -class CCoderMixer2MT: - public ICompressCoder2, - public CCoderMixer2, + +class CMixerMT: + public IUnknown, + public CMixer, public CMyUnknownImp { - CBindInfo _bindInfo; CObjectVector<CStreamBinder> _streamBinders; - unsigned _progressCoderIndex; - void AddCoderCommon(); - HRESULT Init(ISequentialInStream **inStreams, ISequentialOutStream **outStreams); + HRESULT Init(ISequentialInStream * const *inStreams, ISequentialOutStream * const *outStreams); HRESULT ReturnIfError(HRESULT code); + public: - CObjectVector<CCoder2> _coders; + CObjectVector<CCoderMT> _coders; + MY_UNKNOWN_IMP - STDMETHOD(Code)(ISequentialInStream **inStreams, - const UInt64 **inSizes, - UInt32 numInStreams, - ISequentialOutStream **outStreams, - const UInt64 **outSizes, - UInt32 numOutStreams, + virtual HRESULT SetBindInfo(const CBindInfo &bindInfo); + + virtual void AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter); + + virtual CCoder &GetCoder(unsigned index); + + virtual void SelectMainCoder(bool useFirst); + + virtual void ReInit(); + + virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) + { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); } + + virtual HRESULT Code( + ISequentialInStream * const *inStreams, + ISequentialOutStream * const *outStreams, ICompressProgressInfo *progress); - HRESULT SetBindInfo(const CBindInfo &bindInfo); - void AddCoder(ICompressCoder *coder); - void AddCoder2(ICompressCoder2 *coder); - void SetProgressCoderIndex(unsigned coderIndex) { _progressCoderIndex = coderIndex; } + virtual UInt64 GetBondStreamSize(unsigned bondIndex) const; - void ReInit(); - void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) - { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); } - UInt64 GetWriteProcessedSize(UInt32 binderIndex) const - { return _streamBinders[binderIndex].ProcessedSize; } + CMixerMT(bool encodeMode): CMixer(encodeMode) {} }; } + #endif diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp index a94ba115..127c1ed4 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2ST.cpp +++ b/CPP/7zip/Archive/Common/CoderMixer2ST.cpp @@ -4,236 +4,559 @@ #include "CoderMixer2ST.h" -namespace NCoderMixer { +STDMETHODIMP CSequentialInStreamCalcSize::Read(void *data, UInt32 size, UInt32 *processedSize) +{ + UInt32 realProcessed = 0; + HRESULT result = S_OK; + if (_stream) + result = _stream->Read(data, size, &realProcessed); + _size += realProcessed; + if (size != 0 && realProcessed == 0) + _wasFinished = true; + if (processedSize) + *processedSize = realProcessed; + return result; +} -CCoderMixer2ST::CCoderMixer2ST() {} -CCoderMixer2ST::~CCoderMixer2ST(){ } -HRESULT CCoderMixer2ST::SetBindInfo(const CBindInfo &bindInfo) +STDMETHODIMP COutStreamCalcSize::Write(const void *data, UInt32 size, UInt32 *processedSize) { - _bindInfo = bindInfo; - return S_OK; + HRESULT result = S_OK; + if (_stream) + result = _stream->Write(data, size, &size); + _size += size; + if (processedSize) + *processedSize = size; + return result; } -void CCoderMixer2ST::AddCoderCommon(bool isMain) +STDMETHODIMP COutStreamCalcSize::Flush() { - const CCoderStreamsInfo &csi = _bindInfo.Coders[_coders.Size()]; - _coders.Add(CSTCoderInfo(csi.NumInStreams, csi.NumOutStreams, isMain)); + HRESULT result = S_OK; + if (_stream) + { + CMyComPtr<IOutStreamFlush> outStreamFlush; + _stream.QueryInterface(IID_IOutStreamFlush, &outStreamFlush); + if (outStreamFlush) + result = outStreamFlush->Flush();; + } + return result; } -void CCoderMixer2ST::AddCoder(ICompressCoder *coder, bool isMain) + + +namespace NCoderMixer2 { + +CMixerST::CMixerST(bool encodeMode): + CMixer(encodeMode) + {} + +CMixerST::~CMixerST() {} + +void CMixerST::AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter) { - AddCoderCommon(isMain); - _coders.Back().Coder = coder; + IsFilter_Vector.Add(isFilter); + const CCoderStreamsInfo &c = _bi.Coders[_coders.Size()]; + CCoderST &c2 = _coders.AddNew(); + c2.NumStreams = c.NumStreams; + c2.Coder = coder; + c2.Coder2 = coder2; + + /* + if (isFilter) + { + c2.CanRead = true; + c2.CanWrite = true; + } + else + */ + { + IUnknown *unk = (coder ? (IUnknown *)coder : (IUnknown *)coder2); + { + CMyComPtr<ISequentialInStream> s; + unk->QueryInterface(IID_ISequentialInStream, (void**)&s); + c2.CanRead = (s != NULL); + } + { + CMyComPtr<ISequentialOutStream> s; + unk->QueryInterface(IID_ISequentialOutStream, (void**)&s); + c2.CanWrite = (s != NULL); + } + } } -void CCoderMixer2ST::AddCoder2(ICompressCoder2 *coder, bool isMain) +CCoder &CMixerST::GetCoder(unsigned index) { - AddCoderCommon(isMain); - _coders.Back().Coder2 = coder; + return _coders[index]; +} + +void CMixerST::ReInit() {} + +HRESULT CMixerST::GetInStream2( + ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ + UInt32 outStreamIndex, ISequentialInStream **inStreamRes) +{ + UInt32 coderIndex = outStreamIndex, coderStreamIndex = 0; + + if (EncodeMode) + { + _bi.GetCoder_for_Stream(outStreamIndex, coderIndex, coderStreamIndex); + if (coderStreamIndex != 0) + return E_NOTIMPL; + } + + const CCoder &coder = _coders[coderIndex]; + + CMyComPtr<ISequentialInStream> seqInStream; + coder.QueryInterface(IID_ISequentialInStream, (void **)&seqInStream); + if (!seqInStream) + return E_NOTIMPL; + + UInt32 numInStreams = EncodeMode ? 1 : coder.NumStreams; + UInt32 startIndex = EncodeMode ? coderIndex : _bi.Coder_to_Stream[coderIndex]; + + bool isSet = false; + + if (numInStreams == 1) + { + CMyComPtr<ICompressSetInStream> setStream; + coder.QueryInterface(IID_ICompressSetInStream, (void **)&setStream); + if (setStream) + { + CMyComPtr<ISequentialInStream> seqInStream2; + RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + 0, &seqInStream2)); + RINOK(setStream->SetInStream(seqInStream2)); + isSet = true; + } + } + + if (!isSet && numInStreams != 0) + { + CMyComPtr<ICompressSetInStream2> setStream2; + coder.QueryInterface(IID_ICompressSetInStream2, (void **)&setStream2); + if (!setStream2) + return E_NOTIMPL; + + for (UInt32 i = 0; i < numInStreams; i++) + { + CMyComPtr<ISequentialInStream> seqInStream2; + RINOK(GetInStream(inStreams, /* inSizes, */ startIndex + i, &seqInStream2)); + RINOK(setStream2->SetInStream2(i, seqInStream2)); + } + } + + *inStreamRes = seqInStream.Detach(); + return S_OK; } -void CCoderMixer2ST::ReInit() { } -HRESULT CCoderMixer2ST::GetInStream( - ISequentialInStream **inStreams, const UInt64 **inSizes, - UInt32 streamIndex, ISequentialInStream **inStreamRes) +HRESULT CMixerST::GetInStream( + ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ + UInt32 inStreamIndex, ISequentialInStream **inStreamRes) { CMyComPtr<ISequentialInStream> seqInStream; - int i; - for (i = 0; i < _bindInfo.InStreams.Size(); i++) - if (_bindInfo.InStreams[i] == streamIndex) + + { + int index = -1; + if (EncodeMode) + { + if (_bi.UnpackCoder == inStreamIndex) + index = 0; + } + else + index = _bi.FindStream_in_PackStreams(inStreamIndex); + + if (index >= 0) { - seqInStream = inStreams[i]; + seqInStream = inStreams[index]; *inStreamRes = seqInStream.Detach(); return S_OK; } - int binderIndex = _bindInfo.FindBinderForInStream(streamIndex); - if (binderIndex < 0) + } + + int bond = FindBond_for_Stream( + true, // forInputStream + inStreamIndex); + if (bond < 0) return E_INVALIDARG; - UInt32 coderIndex, coderStreamIndex; - _bindInfo.FindOutStream(_bindInfo.BindPairs[binderIndex].OutIndex, - coderIndex, coderStreamIndex); - - CCoderInfo2 &coder = _coders[coderIndex]; - if (!coder.Coder) - return E_NOTIMPL; - coder.Coder.QueryInterface(IID_ISequentialInStream, &seqInStream); - if (!seqInStream) - return E_NOTIMPL; + RINOK(GetInStream2(inStreams, /* inSizes, */ + _bi.Bonds[bond].Get_OutIndex(EncodeMode), &seqInStream)); - UInt32 startIndex = _bindInfo.GetCoderInStreamIndex(coderIndex); + while (_binderStreams.Size() <= (unsigned)bond) + _binderStreams.AddNew(); + CStBinderStream &bs = _binderStreams[bond]; - CMyComPtr<ICompressSetInStream> setInStream; - if (!coder.Coder) - return E_NOTIMPL; - coder.Coder.QueryInterface(IID_ICompressSetInStream, &setInStream); - if (!setInStream) + if (bs.StreamRef || bs.InStreamSpec) return E_NOTIMPL; + + CSequentialInStreamCalcSize *spec = new CSequentialInStreamCalcSize; + bs.StreamRef = spec; + bs.InStreamSpec = spec; + + spec->SetStream(seqInStream); + spec->Init(); + + seqInStream = bs.InStreamSpec; - if (coder.NumInStreams > 1) - return E_NOTIMPL; - for (i = 0; i < (int)coder.NumInStreams; i++) - { - CMyComPtr<ISequentialInStream> seqInStream2; - RINOK(GetInStream(inStreams, inSizes, startIndex + i, &seqInStream2)); - RINOK(setInStream->SetInStream(seqInStream2)); - } *inStreamRes = seqInStream.Detach(); return S_OK; } -HRESULT CCoderMixer2ST::GetOutStream( - ISequentialOutStream **outStreams, const UInt64 **outSizes, - UInt32 streamIndex, ISequentialOutStream **outStreamRes) + +HRESULT CMixerST::GetOutStream( + ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */ + UInt32 outStreamIndex, ISequentialOutStream **outStreamRes) { CMyComPtr<ISequentialOutStream> seqOutStream; - int i; - for (i = 0; i < _bindInfo.OutStreams.Size(); i++) - if (_bindInfo.OutStreams[i] == streamIndex) + + { + int index = -1; + if (!EncodeMode) + { + if (_bi.UnpackCoder == outStreamIndex) + index = 0; + } + else + index = _bi.FindStream_in_PackStreams(outStreamIndex); + + if (index >= 0) { - seqOutStream = outStreams[i]; + seqOutStream = outStreams[index]; *outStreamRes = seqOutStream.Detach(); return S_OK; } - int binderIndex = _bindInfo.FindBinderForOutStream(streamIndex); - if (binderIndex < 0) + } + + int bond = FindBond_for_Stream( + false, // forInputStream + outStreamIndex); + if (bond < 0) return E_INVALIDARG; - UInt32 coderIndex, coderStreamIndex; - _bindInfo.FindInStream(_bindInfo.BindPairs[binderIndex].InIndex, - coderIndex, coderStreamIndex); + UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode); + + UInt32 coderIndex = inStreamIndex; + UInt32 coderStreamIndex = 0; + + if (!EncodeMode) + _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex); + + CCoder &coder = _coders[coderIndex]; - CCoderInfo2 &coder = _coders[coderIndex]; + /* if (!coder.Coder) return E_NOTIMPL; - coder.Coder.QueryInterface(IID_ISequentialOutStream, &seqOutStream); + */ + + coder.QueryInterface(IID_ISequentialOutStream, (void **)&seqOutStream); if (!seqOutStream) return E_NOTIMPL; - UInt32 startIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex); + UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1; + UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex; - CMyComPtr<ICompressSetOutStream> setOutStream; - if (!coder.Coder) - return E_NOTIMPL; - coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream); - if (!setOutStream) - return E_NOTIMPL; + bool isSet = false; - if (coder.NumOutStreams > 1) - return E_NOTIMPL; - for (i = 0; i < (int)coder.NumOutStreams; i++) + if (numOutStreams == 1) { - CMyComPtr<ISequentialOutStream> seqOutStream2; - RINOK(GetOutStream(outStreams, outSizes, startIndex + i, &seqOutStream2)); - RINOK(setOutStream->SetOutStream(seqOutStream2)); + CMyComPtr<ICompressSetOutStream> setOutStream; + coder.Coder.QueryInterface(IID_ICompressSetOutStream, &setOutStream); + if (setOutStream) + { + CMyComPtr<ISequentialOutStream> seqOutStream2; + RINOK(GetOutStream(outStreams, /* outSizes, */ startIndex + 0, &seqOutStream2)); + RINOK(setOutStream->SetOutStream(seqOutStream2)); + isSet = true; + } } + + if (!isSet && numOutStreams != 0) + { + // return E_NOTIMPL; + // /* + CMyComPtr<ICompressSetOutStream2> setStream2; + coder.QueryInterface(IID_ICompressSetOutStream2, (void **)&setStream2); + if (!setStream2) + return E_NOTIMPL; + for (UInt32 i = 0; i < numOutStreams; i++) + { + CMyComPtr<ISequentialOutStream> seqOutStream2; + RINOK(GetOutStream(outStreams, startIndex + i, &seqOutStream2)); + RINOK(setStream2->SetOutStream2(i, seqOutStream2)); + } + // */ + } + + while (_binderStreams.Size() <= (unsigned)bond) + _binderStreams.AddNew(); + CStBinderStream &bs = _binderStreams[bond]; + + if (bs.StreamRef || bs.OutStreamSpec) + return E_NOTIMPL; + + COutStreamCalcSize *spec = new COutStreamCalcSize; + bs.StreamRef = (ISequentialOutStream *)spec; + bs.OutStreamSpec = spec; + + spec->SetStream(seqOutStream); + spec->Init(); + + seqOutStream = bs.OutStreamSpec; + *outStreamRes = seqOutStream.Detach(); return S_OK; } - -STDMETHODIMP CCoderMixer2ST::Code(ISequentialInStream **inStreams, - const UInt64 **inSizes, - UInt32 numInStreams, - ISequentialOutStream **outStreams, - const UInt64 **outSizes, - UInt32 numOutStreams, - ICompressProgressInfo *progress) + +static HRESULT GetError(HRESULT res, HRESULT res2) { - if (numInStreams != (UInt32)_bindInfo.InStreams.Size() || - numOutStreams != (UInt32)_bindInfo.OutStreams.Size()) - return E_INVALIDARG; + if (res == res2) + return res; + if (res == S_OK) + return res2; + if (res == k_My_HRESULT_WritingWasCut) + { + if (res2 != S_OK) + return res2; + } + return res; +} - // Find main coder - int _mainCoderIndex = -1; - int i; - for (i = 0; i < _coders.Size(); i++) - if (_coders[i].IsMain) - { - _mainCoderIndex = i; - break; - } - if (_mainCoderIndex < 0) - for (i = 0; i < _coders.Size(); i++) - if (_coders[i].NumInStreams > 1) + +HRESULT CMixerST::FlushStream(UInt32 streamIndex) +{ + { + int index = -1; + if (!EncodeMode) { - if (_mainCoderIndex >= 0) - return E_NOTIMPL; - _mainCoderIndex = i; + if (_bi.UnpackCoder == streamIndex) + index = 0; } - if (_mainCoderIndex < 0) - _mainCoderIndex = 0; + else + index = _bi.FindStream_in_PackStreams(streamIndex); + + if (index >= 0) + return S_OK; + } + + int bond = FindBond_for_Stream( + false, // forInputStream + streamIndex); + if (bond < 0) + return E_INVALIDARG; + + UInt32 inStreamIndex = _bi.Bonds[bond].Get_InIndex(EncodeMode); + + UInt32 coderIndex = inStreamIndex; + UInt32 coderStreamIndex = 0; + if (!EncodeMode) + _bi.GetCoder_for_Stream(inStreamIndex, coderIndex, coderStreamIndex); + + CCoder &coder = _coders[coderIndex]; + CMyComPtr<IOutStreamFlush> flush; + coder.QueryInterface(IID_IOutStreamFlush, (void **)&flush); + HRESULT res = S_OK; + if (flush) + { + res = flush->Flush(); + } + return GetError(res, FlushCoder(coderIndex)); +} + + +HRESULT CMixerST::FlushCoder(UInt32 coderIndex) +{ + CCoder &coder = _coders[coderIndex]; + + UInt32 numOutStreams = EncodeMode ? coder.NumStreams : 1; + UInt32 startIndex = EncodeMode ? _bi.Coder_to_Stream[coderIndex]: coderIndex; + + HRESULT res = S_OK; + for (unsigned i = 0; i < numOutStreams; i++) + res = GetError(res, FlushStream(startIndex + i)); + return res; +} + + +void CMixerST::SelectMainCoder(bool useFirst) +{ + unsigned ci = _bi.UnpackCoder; + + int firstNonFilter = -1; + int firstAllowed = ci; + + for (;;) + { + const CCoderST &coder = _coders[ci]; + // break; + + if (ci != _bi.UnpackCoder) + if (EncodeMode ? !coder.CanWrite : !coder.CanRead) + { + firstAllowed = ci; + firstNonFilter = -2; + } + + if (coder.NumStreams != 1) + break; + + UInt32 st = _bi.Coder_to_Stream[ci]; + if (_bi.IsStream_in_PackStreams(st)) + break; + int bond = _bi.FindBond_for_PackStream(st); + if (bond < 0) + throw 20150213; + + if (EncodeMode ? !coder.CanRead : !coder.CanWrite) + break; + + if (firstNonFilter == -1 && !IsFilter_Vector[ci]) + firstNonFilter = ci; + + ci = _bi.Bonds[bond].UnpackIndex; + } + + ci = firstNonFilter; + if (firstNonFilter < 0 || useFirst) + ci = firstAllowed; + MainCoderIndex = ci; +} + + +HRESULT CMixerST::Code( + ISequentialInStream * const *inStreams, + ISequentialOutStream * const *outStreams, + ICompressProgressInfo *progress) +{ + _binderStreams.Clear(); + unsigned ci = MainCoderIndex; - // _mainCoderIndex = 0; - // _mainCoderIndex = _coders.Size() - 1; - CCoderInfo2 &mainCoder = _coders[_mainCoderIndex]; + const CCoder &mainCoder = _coders[MainCoderIndex]; CObjectVector< CMyComPtr<ISequentialInStream> > seqInStreams; CObjectVector< CMyComPtr<ISequentialOutStream> > seqOutStreams; - UInt32 startInIndex = _bindInfo.GetCoderInStreamIndex(_mainCoderIndex); - UInt32 startOutIndex = _bindInfo.GetCoderOutStreamIndex(_mainCoderIndex); - for (i = 0; i < (int)mainCoder.NumInStreams; i++) + + UInt32 numInStreams = EncodeMode ? 1 : mainCoder.NumStreams; + UInt32 numOutStreams = !EncodeMode ? 1 : mainCoder.NumStreams; + + UInt32 startInIndex = EncodeMode ? ci : _bi.Coder_to_Stream[ci]; + UInt32 startOutIndex = !EncodeMode ? ci : _bi.Coder_to_Stream[ci]; + + UInt32 i; + + for (i = 0; i < numInStreams; i++) { CMyComPtr<ISequentialInStream> seqInStream; - RINOK(GetInStream(inStreams, inSizes, startInIndex + i, &seqInStream)); + RINOK(GetInStream(inStreams, /* inSizes, */ startInIndex + i, &seqInStream)); seqInStreams.Add(seqInStream); } - for (i = 0; i < (int)mainCoder.NumOutStreams; i++) + + for (i = 0; i < numOutStreams; i++) { CMyComPtr<ISequentialOutStream> seqOutStream; - RINOK(GetOutStream(outStreams, outSizes, startOutIndex + i, &seqOutStream)); + RINOK(GetOutStream(outStreams, /* outSizes, */ startOutIndex + i, &seqOutStream)); seqOutStreams.Add(seqOutStream); } + CRecordVector< ISequentialInStream * > seqInStreamsSpec; CRecordVector< ISequentialOutStream * > seqOutStreamsSpec; - for (i = 0; i < (int)mainCoder.NumInStreams; i++) + + for (i = 0; i < numInStreams; i++) seqInStreamsSpec.Add(seqInStreams[i]); - for (i = 0; i < (int)mainCoder.NumOutStreams; i++) + for (i = 0; i < numOutStreams; i++) seqOutStreamsSpec.Add(seqOutStreams[i]); for (i = 0; i < _coders.Size(); i++) { - if (i == _mainCoderIndex) + if (i == ci) continue; - CCoderInfo2 &coder = _coders[i]; + + CCoder &coder = _coders[i]; + CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize; - coder.Coder.QueryInterface(IID_ICompressSetOutStreamSize, &setOutStreamSize); + coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize); if (setOutStreamSize) { - RINOK(setOutStreamSize->SetOutStreamSize(coder.OutSizePointers[0])); + RINOK(setOutStreamSize->SetOutStreamSize( + EncodeMode ? coder.PackSizePointers[0] : coder.UnpackSizePointer)); } } + + const UInt64 * const *isSizes2 = EncodeMode ? &mainCoder.UnpackSizePointer : &mainCoder.PackSizePointers.Front(); + const UInt64 * const *outSizes2 = EncodeMode ? &mainCoder.PackSizePointers.Front() : &mainCoder.UnpackSizePointer; + + HRESULT res; if (mainCoder.Coder) { - RINOK(mainCoder.Coder->Code( + res = mainCoder.Coder->Code( seqInStreamsSpec[0], seqOutStreamsSpec[0], - mainCoder.InSizePointers[0], mainCoder.OutSizePointers[0], - progress)); + isSizes2[0], outSizes2[0], + progress); } else { - RINOK(mainCoder.Coder2->Code( - &seqInStreamsSpec.Front(), - &mainCoder.InSizePointers.Front(), mainCoder.NumInStreams, - &seqOutStreamsSpec.Front(), - &mainCoder.OutSizePointers.Front(), mainCoder.NumOutStreams, - progress)); + res = mainCoder.Coder2->Code( + &seqInStreamsSpec.Front(), isSizes2, numInStreams, + &seqOutStreamsSpec.Front(), outSizes2, numOutStreams, + progress); } - CMyComPtr<IOutStreamFlush> flush; - seqOutStreams.Front().QueryInterface(IID_IOutStreamFlush, &flush); - if (flush) - return flush->Flush(); + + if (res == k_My_HRESULT_WritingWasCut) + res = S_OK; + + if (res == S_OK || res == S_FALSE) + { + res = GetError(res, FlushCoder(ci)); + } + + for (i = 0; i < _binderStreams.Size(); i++) + { + const CStBinderStream &bs = _binderStreams[i]; + if (bs.InStreamSpec) + bs.InStreamSpec->ReleaseStream(); + else + bs.OutStreamSpec->ReleaseStream(); + } + + if (res == k_My_HRESULT_WritingWasCut) + res = S_OK; + return res; +} + + +HRESULT CMixerST::GetMainUnpackStream( + ISequentialInStream * const *inStreams, + ISequentialInStream **inStreamRes) +{ + CMyComPtr<ISequentialInStream> seqInStream; + + RINOK(GetInStream2(inStreams, /* inSizes, */ + _bi.UnpackCoder, &seqInStream)) + + FOR_VECTOR (i, _coders) + { + CCoder &coder = _coders[i]; + CMyComPtr<ICompressSetOutStreamSize> setOutStreamSize; + coder.QueryInterface(IID_ICompressSetOutStreamSize, (void **)&setOutStreamSize); + if (setOutStreamSize) + { + RINOK(setOutStreamSize->SetOutStreamSize(coder.UnpackSizePointer)); + } + } + + *inStreamRes = seqInStream.Detach(); return S_OK; } -/* -UInt64 CCoderMixer2ST::GetWriteProcessedSize(UInt32 binderIndex) const + +UInt64 CMixerST::GetBondStreamSize(unsigned bondIndex) const { - return _streamBinders[binderIndex].ProcessedSize; + const CStBinderStream &bs = _binderStreams[bondIndex]; + if (bs.InStreamSpec) + return bs.InStreamSpec->GetSize(); + return bs.OutStreamSpec->GetSize(); } -*/ } diff --git a/CPP/7zip/Archive/Common/CoderMixer2ST.h b/CPP/7zip/Archive/Common/CoderMixer2ST.h index d35655ba..f2f7c4cb 100644 --- a/CPP/7zip/Archive/Common/CoderMixer2ST.h +++ b/CPP/7zip/Archive/Common/CoderMixer2ST.h @@ -3,84 +3,125 @@ #ifndef __CODER_MIXER2_ST_H #define __CODER_MIXER2_ST_H -#include "CoderMixer2.h" #include "../../../Common/MyCom.h" + #include "../../ICoder.h" -namespace NCoderMixer { - -// SetBindInfo() -// for each coder -// { -// AddCoder[2]() -// } -// -// for each file -// { -// ReInit() -// for each coder -// { -// SetCoderInfo -// } -// SetProgressIndex(UInt32 coderIndex); -// Code -// } - -struct CSTCoderInfo: public CCoderInfo2 +#include "CoderMixer2.h" + +class CSequentialInStreamCalcSize: + public ISequentialInStream, + public CMyUnknownImp { - bool IsMain; - CSTCoderInfo(UInt32 numInStreams, UInt32 numOutStreams, bool isMain): - CCoderInfo2(numInStreams, numOutStreams), IsMain(isMain) {} +public: + MY_UNKNOWN_IMP1(ISequentialInStream) + + STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize); +private: + CMyComPtr<ISequentialInStream> _stream; + UInt64 _size; + bool _wasFinished; +public: + void SetStream(ISequentialInStream *stream) { _stream = stream; } + void Init() + { + _size = 0; + _wasFinished = false; + } + void ReleaseStream() { _stream.Release(); } + UInt64 GetSize() const { return _size; } + bool WasFinished() const { return _wasFinished; } }; -class CCoderMixer2ST: - public ICompressCoder2, - public CCoderMixer2, + +class COutStreamCalcSize: + public ISequentialOutStream, + public IOutStreamFlush, public CMyUnknownImp { - MY_UNKNOWN_IMP - - HRESULT GetInStream( - ISequentialInStream **inStreams, const UInt64 **inSizes, - UInt32 streamIndex, ISequentialInStream **inStreamRes); - HRESULT GetOutStream( - ISequentialOutStream **outStreams, const UInt64 **outSizes, - UInt32 streamIndex, ISequentialOutStream **outStreamRes); + CMyComPtr<ISequentialOutStream> _stream; + UInt64 _size; public: - STDMETHOD(Code)(ISequentialInStream **inStreams, - const UInt64 **inSizes, - UInt32 numInStreams, - ISequentialOutStream **outStreams, - const UInt64 **outSizes, - UInt32 numOutStreams, - ICompressProgressInfo *progress); + MY_UNKNOWN_IMP2(ISequentialOutStream, IOutStreamFlush) + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); + STDMETHOD(Flush)(); + + void SetStream(ISequentialOutStream *stream) { _stream = stream; } + void ReleaseStream() { _stream.Release(); } + void Init() { _size = 0; } + UInt64 GetSize() const { return _size; } +}; - CCoderMixer2ST(); - ~CCoderMixer2ST(); - void AddCoderCommon(bool isMain); - void AddCoder(ICompressCoder *coder, bool isMain); - void AddCoder2(ICompressCoder2 *coder, bool isMain); - void ReInit(); - void SetCoderInfo(UInt32 coderIndex, const UInt64 **inSizes, const UInt64 **outSizes) - { - { _coders[coderIndex].SetCoderInfo(inSizes, outSizes); } - } - void SetProgressCoderIndex(UInt32 /*coderIndex*/) - { - // _progressCoderIndex = coderIndex; - } +namespace NCoderMixer2 { - // UInt64 GetWriteProcessedSize(UInt32 binderIndex) const; +struct CCoderST: public CCoder +{ + bool CanRead; + bool CanWrite; + + CCoderST(): CanRead(false), CanWrite(false) {} +}; + + +struct CStBinderStream +{ + CSequentialInStreamCalcSize *InStreamSpec; + COutStreamCalcSize *OutStreamSpec; + CMyComPtr<IUnknown> StreamRef; + + CStBinderStream(): InStreamSpec(NULL), OutStreamSpec(NULL) {} +}; + + +class CMixerST: + public IUnknown, + public CMixer, + public CMyUnknownImp +{ + HRESULT GetInStream2(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ + UInt32 outStreamIndex, ISequentialInStream **inStreamRes); + HRESULT GetInStream(ISequentialInStream * const *inStreams, /* const UInt64 * const *inSizes, */ + UInt32 inStreamIndex, ISequentialInStream **inStreamRes); + HRESULT GetOutStream(ISequentialOutStream * const *outStreams, /* const UInt64 * const *outSizes, */ + UInt32 outStreamIndex, ISequentialOutStream **outStreamRes); + + HRESULT FlushStream(UInt32 streamIndex); + HRESULT FlushCoder(UInt32 coderIndex); -private: - CBindInfo _bindInfo; - CObjectVector<CSTCoderInfo> _coders; - int _mainCoderIndex; public: - HRESULT SetBindInfo(const CBindInfo &bindInfo); + CObjectVector<CCoderST> _coders; + + CObjectVector<CStBinderStream> _binderStreams; + + MY_UNKNOWN_IMP + + CMixerST(bool encodeMode); + ~CMixerST(); + + virtual void AddCoder(ICompressCoder *coder, ICompressCoder2 *coder2, bool isFilter); + + virtual CCoder &GetCoder(unsigned index); + + virtual void SelectMainCoder(bool useFirst); + + virtual void ReInit(); + + virtual void SetCoderInfo(unsigned coderIndex, const UInt64 *unpackSize, const UInt64 * const *packSizes) + { _coders[coderIndex].SetCoderInfo(unpackSize, packSizes); } + + virtual HRESULT Code( + ISequentialInStream * const *inStreams, + ISequentialOutStream * const *outStreams, + ICompressProgressInfo *progress); + + virtual UInt64 GetBondStreamSize(unsigned bondIndex) const; + HRESULT GetMainUnpackStream( + ISequentialInStream * const *inStreams, + ISequentialInStream **inStreamRes); }; } diff --git a/CPP/7zip/Archive/Common/CoderMixerMT.h b/CPP/7zip/Archive/Common/CoderMixerMT.h index 9491a965..d2891b26 100644 --- a/CPP/7zip/Archive/Common/CoderMixerMT.h +++ b/CPP/7zip/Archive/Common/CoderMixerMT.h @@ -18,7 +18,7 @@ struct CCoder: public CCoderInfo, public CVirtThread virtual void Execute(); void Code(ICompressProgressInfo *progress); - ~CCoder() { CVirtThread::WaitThreadFinish(); } + virtual ~CCoder() { CVirtThread::WaitThreadFinish(); } }; /* diff --git a/CPP/7zip/Archive/Common/HandlerOut.cpp b/CPP/7zip/Archive/Common/HandlerOut.cpp index 18ad5580..9c11b31d 100644 --- a/CPP/7zip/Archive/Common/HandlerOut.cpp +++ b/CPP/7zip/Archive/Common/HandlerOut.cpp @@ -29,6 +29,7 @@ void CMultiMethodProps::SetGlobalLevelAndThreads(COneMethodInfo &oneMethodInfo UInt32 level = _level; if (level != (UInt32)(Int32)-1) SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level); + #ifndef _7ZIP_ST SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads); #endif @@ -41,6 +42,8 @@ void CMultiMethodProps::Init() #endif _level = (UInt32)(Int32)-1; + _analysisLevel = -1; + _autoFilter = true; _crcSize = 4; _filterMethod.Clear(); @@ -60,8 +63,17 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN _level = 9; return ParsePropToUInt32(name, value, _level); } + + if (name.IsPrefixedBy_Ascii_NoCase("yx")) + { + name.Delete(0, 2); + UInt32 v = 9; + RINOK(ParsePropToUInt32(name, value, v)); + _analysisLevel = (int)v; + return S_OK; + } - if (name == L"crc") + if (name.IsEqualTo("crc")) { name.Delete(0, 3); _crcSize = 4; @@ -73,11 +85,12 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN UString realName = name.Ptr(index); if (index == 0) { - if (name.IsPrefixedBy(L"mt")) + if (name.IsPrefixedBy_Ascii_NoCase("mt")) { #ifndef _7ZIP_ST RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads)); #endif + return S_OK; } if (name.IsEqualTo("f")) @@ -87,7 +100,7 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN return res; if (value.vt != VT_BSTR) return E_INVALIDARG; - return _filterMethod.ParseMethodFromPROPVARIANT(L"", value); + return _filterMethod.ParseMethodFromPROPVARIANT(UString(), value); } number = 0; } @@ -101,14 +114,15 @@ HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIAN void CSingleMethodProps::Init() { Clear(); + _level = (UInt32)(Int32)-1; + #ifndef _7ZIP_ST _numProcessors = _numThreads = NWindows::NSystem::GetNumberOfProcessors(); - AddNumThreadsProp(_numThreads); + AddProp_NumThreads(_numThreads); #endif - _level = (UInt32)(Int32)-1; } -HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps) +HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps) { Init(); for (UInt32 i = 0; i < numProps; i++) @@ -123,13 +137,13 @@ HRESULT CSingleMethodProps::SetProperties(const wchar_t **names, const PROPVARIA UInt32 a = 9; RINOK(ParsePropToUInt32(name.Ptr(1), value, a)); _level = a; - AddLevelProp(a); + AddProp_Level(a); } - else if (name.IsPrefixedBy(L"mt")) + else if (name.IsPrefixedBy_Ascii_NoCase("mt")) { #ifndef _7ZIP_ST RINOK(ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads)); - AddNumThreadsProp(_numThreads); + AddProp_NumThreads(_numThreads); #endif } else diff --git a/CPP/7zip/Archive/Common/HandlerOut.h b/CPP/7zip/Archive/Common/HandlerOut.h index 40a4a698..5a18d980 100644 --- a/CPP/7zip/Archive/Common/HandlerOut.h +++ b/CPP/7zip/Archive/Common/HandlerOut.h @@ -10,6 +10,7 @@ namespace NArchive { class CMultiMethodProps { UInt32 _level; + int _analysisLevel; public: #ifndef _7ZIP_ST UInt32 _numThreads; @@ -37,6 +38,7 @@ public: } int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; } + int GetAnalysisLevel() const { return _analysisLevel; } void Init(); @@ -57,7 +59,7 @@ public: void Init(); CSingleMethodProps() { Init(); } int GetLevel() const { return _level == (UInt32)(Int32)-1 ? 5 : (int)_level; } - HRESULT SetProperties(const wchar_t **names, const PROPVARIANT *values, UInt32 numProps); + HRESULT SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps); }; } diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp index 0526c1b1..77252938 100644 --- a/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp +++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.cpp @@ -10,9 +10,9 @@ STDMETHODIMP COutStreamWithSha1::Write(const void *data, UInt32 size, UInt32 *pr if (_stream) result = _stream->Write(data, size, &size); if (_calculate) - _sha.Update((const Byte *)data, size); + Sha1_Update(&_sha, (const Byte *)data, size); _size += size; - if (processedSize != NULL) + if (processedSize) *processedSize = size; return result; } diff --git a/CPP/7zip/Archive/Common/OutStreamWithSha1.h b/CPP/7zip/Archive/Common/OutStreamWithSha1.h index 3bbfbbe1..41a84cd6 100644 --- a/CPP/7zip/Archive/Common/OutStreamWithSha1.h +++ b/CPP/7zip/Archive/Common/OutStreamWithSha1.h @@ -3,7 +3,7 @@ #ifndef __OUT_STREAM_WITH_SHA1_H #define __OUT_STREAM_WITH_SHA1_H -#include "../../Crypto/Sha1.h" +#include "../../../../C/Sha1.h" #include "../../../Common/MyCom.h" @@ -15,7 +15,7 @@ class COutStreamWithSha1: { CMyComPtr<ISequentialOutStream> _stream; UInt64 _size; - NCrypto::NSha1::CContext _sha; + CSha1 _sha; bool _calculate; public: MY_UNKNOWN_IMP @@ -26,11 +26,11 @@ public: { _size = 0; _calculate = calculate; - _sha.Init(); + Sha1_Init(&_sha); } - void InitSha1() { _sha.Init(); } + void InitSha1() { Sha1_Init(&_sha); } UInt64 GetSize() const { return _size; } - void Final(Byte *digest) { _sha.Final(digest); } + void Final(Byte *digest) { Sha1_Final(&_sha, digest); } }; #endif |