diff options
Diffstat (limited to 'CPP/7zip/Archive/Common/CoderMixer2ST.cpp')
-rw-r--r-- | CPP/7zip/Archive/Common/CoderMixer2ST.cpp | 595 |
1 files changed, 459 insertions, 136 deletions
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(); } -*/ } |