diff options
Diffstat (limited to '3rdparty/lzma/CPP/7zip/Archive/7z/7zEncode.cpp')
-rw-r--r-- | 3rdparty/lzma/CPP/7zip/Archive/7z/7zEncode.cpp | 622 |
1 files changed, 413 insertions, 209 deletions
diff --git a/3rdparty/lzma/CPP/7zip/Archive/7z/7zEncode.cpp b/3rdparty/lzma/CPP/7zip/Archive/7z/7zEncode.cpp index 614f9913d15..ab251711fd2 100644 --- a/3rdparty/lzma/CPP/7zip/Archive/7z/7zEncode.cpp +++ b/3rdparty/lzma/CPP/7zip/Archive/7z/7zEncode.cpp @@ -12,43 +12,80 @@ #include "7zEncode.h" #include "7zSpecStream.h" -static const UInt64 k_Delta = 0x03; -static const UInt64 k_BCJ = 0x03030103; -static const UInt64 k_BCJ2 = 0x0303011B; - namespace NArchive { namespace N7z { -static void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo, - const CRecordVector<CMethodId> decompressionMethods, - CFolder &folder) +void CEncoder::InitBindConv() { - folder.Coders.Clear(); - // bindInfo.CoderMethodIDs.Clear(); - // folder.OutStreams.Clear(); - folder.PackStreams.Clear(); - folder.BindPairs.Clear(); - int i; - for (i = 0; i < bindInfo.BindPairs.Size(); i++) + unsigned numIn = _bindInfo.Coders.Size(); + + _SrcIn_to_DestOut.ClearAndSetSize(numIn); + _DestOut_to_SrcIn.ClearAndSetSize(numIn); + + unsigned numOut = _bindInfo.GetNum_Bonds_and_PackStreams(); + _SrcOut_to_DestIn.ClearAndSetSize(numOut); + // _DestIn_to_SrcOut.ClearAndSetSize(numOut); + + UInt32 destIn = 0; + UInt32 destOut = 0; + + for (unsigned i = _bindInfo.Coders.Size(); i != 0;) + { + i--; + + const NCoderMixer2::CCoderStreamsInfo &coder = _bindInfo.Coders[i]; + + numIn--; + numOut -= coder.NumStreams; + + _SrcIn_to_DestOut[numIn] = destOut; + _DestOut_to_SrcIn[destOut] = numIn; + + destOut++; + + for (UInt32 j = 0; j < coder.NumStreams; j++, destIn++) + { + UInt32 index = numOut + j; + _SrcOut_to_DestIn[index] = destIn; + // _DestIn_to_SrcOut[destIn] = index; + } + } +} + +void CEncoder::SetFolder(CFolder &folder) +{ + folder.Bonds.SetSize(_bindInfo.Bonds.Size()); + + unsigned i; + + for (i = 0; i < _bindInfo.Bonds.Size(); i++) { - CBindPair bindPair; - bindPair.InIndex = bindInfo.BindPairs[i].InIndex; - bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex; - folder.BindPairs.Add(bindPair); + CBond &fb = folder.Bonds[i]; + const NCoderMixer2::CBond &mixerBond = _bindInfo.Bonds[_bindInfo.Bonds.Size() - 1 - i]; + fb.PackIndex = _SrcOut_to_DestIn[mixerBond.PackIndex]; + fb.UnpackIndex = _SrcIn_to_DestOut[mixerBond.UnpackIndex]; } - for (i = 0; i < bindInfo.Coders.Size(); i++) + + folder.Coders.SetSize(_bindInfo.Coders.Size()); + + for (i = 0; i < _bindInfo.Coders.Size(); i++) { - CCoderInfo coderInfo; - const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i]; - coderInfo.NumInStreams = coderStreamsInfo.NumInStreams; - coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams; - coderInfo.MethodID = decompressionMethods[i]; - folder.Coders.Add(coderInfo); + CCoderInfo &coderInfo = folder.Coders[i]; + const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[_bindInfo.Coders.Size() - 1 - i]; + + coderInfo.NumStreams = coderStreamsInfo.NumStreams; + coderInfo.MethodID = _decompressionMethods[i]; + // we don't free coderInfo.Props here. So coderInfo.Props can be non-empty. } - for (i = 0; i < bindInfo.InStreams.Size(); i++) - folder.PackStreams.Add(bindInfo.InStreams[i]); + + folder.PackStreams.SetSize(_bindInfo.PackStreams.Size()); + + for (i = 0; i < _bindInfo.PackStreams.Size(); i++) + folder.PackStreams[i] = _SrcOut_to_DestIn[_bindInfo.PackStreams[i]]; } + + static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder) { CMyComPtr<ICompressSetCoderProperties> setCoderProperties; @@ -58,31 +95,75 @@ static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK; } + + +void CMtEncMultiProgress::Init(ICompressProgressInfo *progress) +{ + _progress = progress; + OutSize = 0; +} + +STDMETHODIMP CMtEncMultiProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */) +{ + UInt64 outSize2; + { + #ifndef _7ZIP_ST + NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection); + #endif + outSize2 = OutSize; + } + + if (_progress) + return _progress->SetRatioInfo(inSize, &outSize2); + + return S_OK; +} + + + HRESULT CEncoder::CreateMixerCoder( DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce) { - _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT; - _mixerCoder = _mixerCoderSpec; - RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo)); - for (int i = 0; i < _options.Methods.Size(); i++) + #ifdef USE_MIXER_MT + #ifdef USE_MIXER_ST + if (_options.MultiThreadMixer) + #endif + { + _mixerMT = new NCoderMixer2::CMixerMT(true); + _mixerRef = _mixerMT; + _mixer = _mixerMT; + } + #ifdef USE_MIXER_ST + else + #endif + #endif + { + #ifdef USE_MIXER_ST + _mixerST = new NCoderMixer2::CMixerST(true); + _mixerRef = _mixerST; + _mixer = _mixerST; + #endif + } + + RINOK(_mixer->SetBindInfo(_bindInfo)); + + FOR_VECTOR (i, _options.Methods) { const CMethodFull &methodFull = _options.Methods[i]; - _codersInfo.Add(CCoderInfo()); - CCoderInfo &encodingInfo = _codersInfo.Back(); - encodingInfo.MethodID = methodFull.Id; - CMyComPtr<ICompressCoder> encoder; - CMyComPtr<ICompressCoder2> encoder2; - + CCreatedCoder cod; + RINOK(CreateCoder( EXTERNAL_CODECS_LOC_VARS - methodFull.Id, encoder, encoder2, true)); + methodFull.Id, true, cod)); - if (!encoder && !encoder2) + if (cod.NumStreams != methodFull.NumStreams) + return E_FAIL; + if (!cod.Coder && !cod.Coder2) return E_FAIL; - CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2; + CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2; #ifndef _7ZIP_ST { @@ -100,78 +181,151 @@ HRESULT CEncoder::CreateMixerCoder( /* CMyComPtr<ICryptoResetSalt> resetSalt; encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt); - if (resetSalt != NULL) + if (resetSalt) { resetSalt->ResetSalt(); } */ + // now there is no codec that uses another external codec + /* #ifdef EXTERNAL_CODECS CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo; encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo); if (setCompressCodecsInfo) { - RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo)); + // we must use g_ExternalCodecs also + RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs)); } #endif + */ CMyComPtr<ICryptoSetPassword> cryptoSetPassword; encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword); if (cryptoSetPassword) { - CByteBuffer buffer; - const UInt32 sizeInBytes = _options.Password.Length() * 2; - buffer.SetCapacity(sizeInBytes); - for (int i = 0; i < _options.Password.Length(); i++) + const unsigned sizeInBytes = _options.Password.Len() * 2; + CByteBuffer buffer(sizeInBytes); + for (unsigned i = 0; i < _options.Password.Len(); i++) { wchar_t c = _options.Password[i]; ((Byte *)buffer)[i * 2] = (Byte)c; ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8); } - RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes)); + RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)sizeInBytes)); } - if (encoder) - _mixerCoderSpec->AddCoder(encoder); - else - _mixerCoderSpec->AddCoder2(encoder2); + _mixer->AddCoder(cod); } return S_OK; } + + +class CSequentialOutTempBufferImp2: + public ISequentialOutStream, + public CMyUnknownImp +{ + CInOutTempBuffer *_buf; +public: + CMtEncMultiProgress *_mtProgresSpec; + + CSequentialOutTempBufferImp2(): _buf(0), _mtProgresSpec(NULL) {} + void Init(CInOutTempBuffer *buffer) { _buf = buffer; } + MY_UNKNOWN_IMP1(ISequentialOutStream) + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed) +{ + if (!_buf->Write(data, size)) + { + if (processed) + *processed = 0; + return E_FAIL; + } + if (processed) + *processed = size; + if (_mtProgresSpec) + _mtProgresSpec->AddOutSize(size); + return S_OK; +} + + +class CSequentialOutMtNotify: + public ISequentialOutStream, + public CMyUnknownImp +{ +public: + CMyComPtr<ISequentialOutStream> _stream; + CMtEncMultiProgress *_mtProgresSpec; + + CSequentialOutMtNotify(): _mtProgresSpec(NULL) {} + MY_UNKNOWN_IMP1(ISequentialOutStream) + + STDMETHOD(Write)(const void *data, UInt32 size, UInt32 *processedSize); +}; + +STDMETHODIMP CSequentialOutMtNotify::Write(const void *data, UInt32 size, UInt32 *processed) +{ + UInt32 realProcessed = 0; + HRESULT res = _stream->Write(data, size, &realProcessed); + if (processed) + *processed = realProcessed; + if (_mtProgresSpec) + _mtProgresSpec->AddOutSize(size); + return res; +} + + + HRESULT CEncoder::Encode( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, - const UInt64 *inStreamSize, const UInt64 *inSizeForReduce, + // const UInt64 *inStreamSize, + const UInt64 *inSizeForReduce, CFolder &folderItem, + CRecordVector<UInt64> &coderUnpackSizes, + UInt64 &unpackSize, ISequentialOutStream *outStream, CRecordVector<UInt64> &packSizes, ICompressProgressInfo *compressProgress) { RINOK(EncoderConstr()); - if (_mixerCoderSpec == NULL) + if (!_mixerRef) { RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce)); } - _mixerCoderSpec->ReInit(); - // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress); + + _mixer->ReInit(); + + CMtEncMultiProgress *mtProgressSpec = NULL; + CMyComPtr<ICompressProgressInfo> mtProgress; + + CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL; + CMyComPtr<ISequentialOutStream> mtOutStreamNotify; CObjectVector<CInOutTempBuffer> inOutTempBuffers; - CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs; + CObjectVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs; CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers; - int numMethods = _bindInfo.Coders.Size(); - int i; - for (i = 1; i < _bindInfo.OutStreams.Size(); i++) + + unsigned numMethods = _bindInfo.Coders.Size(); + + unsigned i; + + for (i = 1; i < _bindInfo.PackStreams.Size(); i++) { - inOutTempBuffers.Add(CInOutTempBuffer()); - inOutTempBuffers.Back().Create(); - inOutTempBuffers.Back().InitWriting(); + CInOutTempBuffer &iotb = inOutTempBuffers.AddNew(); + iotb.Create(); + iotb.InitWriting(); } - for (i = 1; i < _bindInfo.OutStreams.Size(); i++) + + for (i = 1; i < _bindInfo.PackStreams.Size(); i++) { - CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp; + CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2; CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec; tempBufferSpec->Init(&inOutTempBuffers[i - 1]); tempBuffers.Add(tempBuffer); @@ -179,120 +333,157 @@ HRESULT CEncoder::Encode( } for (i = 0; i < numMethods; i++) - _mixerCoderSpec->SetCoderInfo(i, NULL, NULL); + _mixer->SetCoderInfo(i, NULL, NULL); - if (_bindInfo.InStreams.IsEmpty()) - return E_FAIL; - UInt32 mainCoderIndex, mainStreamIndex; - _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex); - - if (inStreamSize != NULL) - { - CRecordVector<const UInt64 *> sizePointers; - for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++) - if (i == mainStreamIndex) - sizePointers.Add(inStreamSize); - else - sizePointers.Add(NULL); - _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL); - } - - // UInt64 outStreamStartPos; - // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos)); + /* inStreamSize can be used by BCJ2 to set optimal range of conversion. + But current BCJ2 encoder uses also another way to check exact size of current file. + So inStreamSize is not required. */ + + /* + if (inStreamSize) + _mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL); + */ + CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2; CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec; - CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; - CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec; + + CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL; + CMyComPtr<ISequentialOutStream> outStreamSizeCount; inStreamSizeCountSpec->Init(inStream); - outStreamSizeCountSpec->SetStream(outStream); - outStreamSizeCountSpec->Init(); - CRecordVector<ISequentialInStream *> inStreamPointers; + ISequentialInStream *inStreamPointer = inStreamSizeCount; CRecordVector<ISequentialOutStream *> outStreamPointers; - inStreamPointers.Add(inStreamSizeCount); - outStreamPointers.Add(outStreamSizeCount); - for (i = 1; i < _bindInfo.OutStreams.Size(); i++) - outStreamPointers.Add(tempBuffers[i - 1]); + + SetFolder(folderItem); - for (i = 0; i < _codersInfo.Size(); i++) + for (i = 0; i < numMethods; i++) { - CCoderInfo &encodingInfo = _codersInfo[i]; - + IUnknown *coder = _mixer->GetCoder(i).GetUnknown(); + CMyComPtr<ICryptoResetInitVector> resetInitVector; - _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); - if (resetInitVector != NULL) + coder->QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector); + if (resetInitVector) { resetInitVector->ResetInitVector(); } CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties; - _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); - if (writeCoderProperties != NULL) + coder->QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties); + + CByteBuffer &props = folderItem.Coders[numMethods - 1 - i].Props; + + if (writeCoderProperties) { CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream; - CMyComPtr<ISequentialOutStream> outStream(outStreamSpec); + CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec); outStreamSpec->Init(); - writeCoderProperties->WriteCoderProperties(outStream); - outStreamSpec->CopyToBuffer(encodingInfo.Props); + writeCoderProperties->WriteCoderProperties(dynOutStream); + outStreamSpec->CopyToBuffer(props); } + else + props.Free(); } - UInt32 progressIndex = mainCoderIndex; + _mixer->SelectMainCoder(false); + UInt32 mainCoder = _mixer->MainCoderIndex; - for (i = 0; i + 1 < _codersInfo.Size(); i++) + bool useMtProgress = false; + if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder)) { - UInt64 m = _codersInfo[i].MethodID; - if (m == k_Delta || m == k_BCJ || m == k_BCJ2) - progressIndex = i + 1; + #ifdef _7ZIP_ST + if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder)) + #endif + useMtProgress = true; } - _mixerCoderSpec->SetProgressCoderIndex(progressIndex); + if (useMtProgress) + { + mtProgressSpec = new CMtEncMultiProgress; + mtProgress = mtProgressSpec; + mtProgressSpec->Init(compressProgress); + + mtOutStreamNotifySpec = new CSequentialOutMtNotify; + mtOutStreamNotify = mtOutStreamNotifySpec; + mtOutStreamNotifySpec->_stream = outStream; + mtOutStreamNotifySpec->_mtProgresSpec = mtProgressSpec; + + FOR_VECTOR(i, tempBufferSpecs) + { + tempBufferSpecs[i]->_mtProgresSpec = mtProgressSpec; + } + } - RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1, - &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress)); - ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem); + if (_bindInfo.PackStreams.Size() != 0) + { + outStreamSizeCountSpec = new CSequentialOutStreamSizeCount; + outStreamSizeCount = outStreamSizeCountSpec; + outStreamSizeCountSpec->SetStream(mtOutStreamNotify ? (ISequentialOutStream *)mtOutStreamNotify : outStream); + outStreamSizeCountSpec->Init(); + outStreamPointers.Add(outStreamSizeCount); + } + + for (i = 1; i < _bindInfo.PackStreams.Size(); i++) + outStreamPointers.Add(tempBuffers[i - 1]); + + RINOK(_mixer->Code( + &inStreamPointer, + &outStreamPointers.Front(), + mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress)); - packSizes.Add(outStreamSizeCountSpec->GetSize()); + if (_bindInfo.PackStreams.Size() != 0) + packSizes.Add(outStreamSizeCountSpec->GetSize()); - for (i = 1; i < _bindInfo.OutStreams.Size(); i++) + for (i = 1; i < _bindInfo.PackStreams.Size(); i++) { CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1]; RINOK(inOutTempBuffer.WriteToStream(outStream)); packSizes.Add(inOutTempBuffer.GetDataSize()); } + + unpackSize = 0; - for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++) + for (i = 0; i < _bindInfo.Coders.Size(); i++) { - int binder = _bindInfo.FindBinderForInStream( - _bindReverseConverter->DestOutToSrcInMap[i]); + int bond = _bindInfo.FindBond_for_UnpackStream(_DestOut_to_SrcIn[i]); UInt64 streamSize; - if (binder < 0) + if (bond < 0) + { streamSize = inStreamSizeCountSpec->GetSize(); + unpackSize = streamSize; + } else - streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder); - folderItem.UnpackSizes.Add(streamSize); + streamSize = _mixer->GetBondStreamSize(bond); + coderUnpackSizes.Add(streamSize); } - for (i = numMethods - 1; i >= 0; i--) - folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props; + return S_OK; } CEncoder::CEncoder(const CCompressionMethodMode &options): - _bindReverseConverter(0), - _constructed(false) + _constructed(false) { if (options.IsEmpty()) throw 1; _options = options; - _mixerCoderSpec = NULL; + + #ifdef USE_MIXER_ST + _mixerST = NULL; + #endif + + #ifdef USE_MIXER_MT + _mixerMT = NULL; + #endif + + _mixer = NULL; } + HRESULT CEncoder::EncoderConstr() { if (_constructed) @@ -302,112 +493,125 @@ HRESULT CEncoder::EncoderConstr() // it has only password method; if (!_options.PasswordIsDefined) throw 1; - if (!_options.Binds.IsEmpty()) + if (!_options.Bonds.IsEmpty()) throw 1; - NCoderMixer::CCoderStreamsInfo coderStreamsInfo; + CMethodFull method; - - method.NumInStreams = 1; - method.NumOutStreams = 1; - coderStreamsInfo.NumInStreams = 1; - coderStreamsInfo.NumOutStreams = 1; method.Id = k_AES; - + method.NumStreams = 1; _options.Methods.Add(method); + + NCoderMixer2::CCoderStreamsInfo coderStreamsInfo; + coderStreamsInfo.NumStreams = 1; _bindInfo.Coders.Add(coderStreamsInfo); - _bindInfo.InStreams.Add(0); - _bindInfo.OutStreams.Add(0); + _bindInfo.PackStreams.Add(0); + _bindInfo.UnpackCoder = 0; } else { - UInt32 numInStreams = 0, numOutStreams = 0; - int i; + UInt32 numOutStreams = 0; + unsigned i; + for (i = 0; i < _options.Methods.Size(); i++) { const CMethodFull &methodFull = _options.Methods[i]; - NCoderMixer::CCoderStreamsInfo coderStreamsInfo; - coderStreamsInfo.NumInStreams = methodFull.NumOutStreams; - coderStreamsInfo.NumOutStreams = methodFull.NumInStreams; - if (_options.Binds.IsEmpty()) + NCoderMixer2::CCoderStreamsInfo cod; + + cod.NumStreams = methodFull.NumStreams; + + if (_options.Bonds.IsEmpty()) { - if (i < _options.Methods.Size() - 1) + // if there are no bonds in options, we create bonds via first streams of coders + if (i != _options.Methods.Size() - 1) { - NCoderMixer::CBindPair bindPair; - bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams; - bindPair.OutIndex = numOutStreams; - _bindInfo.BindPairs.Add(bindPair); + NCoderMixer2::CBond bond; + bond.PackIndex = numOutStreams; + bond.UnpackIndex = i + 1; // it's next coder + _bindInfo.Bonds.Add(bond); } - else - _bindInfo.OutStreams.Insert(0, numOutStreams); - for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++) - _bindInfo.OutStreams.Add(numOutStreams + j); + else if (cod.NumStreams != 0) + _bindInfo.PackStreams.Insert(0, numOutStreams); + + for (UInt32 j = 1; j < cod.NumStreams; j++) + _bindInfo.PackStreams.Add(numOutStreams + j); } - numInStreams += coderStreamsInfo.NumInStreams; - numOutStreams += coderStreamsInfo.NumOutStreams; + numOutStreams += cod.NumStreams; - _bindInfo.Coders.Add(coderStreamsInfo); + _bindInfo.Coders.Add(cod); } - if (!_options.Binds.IsEmpty()) + if (!_options.Bonds.IsEmpty()) { - for (i = 0; i < _options.Binds.Size(); i++) + for (i = 0; i < _options.Bonds.Size(); i++) { - NCoderMixer::CBindPair bindPair; - const CBind &bind = _options.Binds[i]; - bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream; - bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream; - _bindInfo.BindPairs.Add(bindPair); + NCoderMixer2::CBond mixerBond; + const CBond2 &bond = _options.Bonds[i]; + if (bond.InCoder >= _bindInfo.Coders.Size() + || bond.OutCoder >= _bindInfo.Coders.Size() + || bond.OutStream >= _bindInfo.Coders[bond.OutCoder].NumStreams) + return E_INVALIDARG; + mixerBond.PackIndex = _bindInfo.GetStream_for_Coder(bond.OutCoder) + bond.OutStream; + mixerBond.UnpackIndex = bond.InCoder; + _bindInfo.Bonds.Add(mixerBond); } - for (i = 0; i < (int)numOutStreams; i++) - if (_bindInfo.FindBinderForOutStream(i) == -1) - _bindInfo.OutStreams.Add(i); + + for (i = 0; i < numOutStreams; i++) + if (_bindInfo.FindBond_for_PackStream(i) == -1) + _bindInfo.PackStreams.Add(i); } - for (i = 0; i < (int)numInStreams; i++) - if (_bindInfo.FindBinderForInStream(i) == -1) - _bindInfo.InStreams.Add(i); + if (!_bindInfo.SetUnpackCoder()) + return E_INVALIDARG; - if (_bindInfo.InStreams.IsEmpty()) - throw 1; // this is error + if (!_bindInfo.CalcMapsAndCheck()) + return E_INVALIDARG; - // Make main stream first in list - int inIndex = _bindInfo.InStreams[0]; - for (;;) + if (_bindInfo.PackStreams.Size() != 1) { - UInt32 coderIndex, coderStreamIndex; - _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex); - UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex); - int binder = _bindInfo.FindBinderForOutStream(outIndex); - if (binder >= 0) + /* main_PackStream is pack stream of main path of coders tree. + We find main_PackStream, and place to start of list of out streams. + It allows to use more optimal memory usage for temp buffers, + if main_PackStream is largest stream. */ + + UInt32 ci = _bindInfo.UnpackCoder; + + for (;;) { - inIndex = _bindInfo.BindPairs[binder].InIndex; - continue; - } - for (i = 0; i < _bindInfo.OutStreams.Size(); i++) - if (_bindInfo.OutStreams[i] == outIndex) - { - _bindInfo.OutStreams.Delete(i); - _bindInfo.OutStreams.Insert(0, outIndex); + if (_bindInfo.Coders[ci].NumStreams == 0) break; + + UInt32 outIndex = _bindInfo.Coder_to_Stream[ci]; + int bond = _bindInfo.FindBond_for_PackStream(outIndex); + if (bond >= 0) + { + ci = _bindInfo.Bonds[bond].UnpackIndex; + continue; } - break; + + int i = _bindInfo.FindStream_in_PackStreams(outIndex); + if (i >= 0) + _bindInfo.PackStreams.MoveToFront(i); + break; + } } if (_options.PasswordIsDefined) { - int numCryptoStreams = _bindInfo.OutStreams.Size(); + unsigned numCryptoStreams = _bindInfo.PackStreams.Size(); + unsigned numInStreams = _bindInfo.Coders.Size(); + for (i = 0; i < numCryptoStreams; i++) { - NCoderMixer::CBindPair bindPair; - bindPair.InIndex = numInStreams + i; - bindPair.OutIndex = _bindInfo.OutStreams[i]; - _bindInfo.BindPairs.Add(bindPair); + NCoderMixer2::CBond bond; + bond.UnpackIndex = numInStreams + i; + bond.PackIndex = _bindInfo.PackStreams[i]; + _bindInfo.Bonds.Add(bond); } - _bindInfo.OutStreams.Clear(); + _bindInfo.PackStreams.Clear(); /* if (numCryptoStreams == 0) @@ -416,37 +620,37 @@ HRESULT CEncoder::EncoderConstr() for (i = 0; i < numCryptoStreams; i++) { - NCoderMixer::CCoderStreamsInfo coderStreamsInfo; CMethodFull method; - method.NumInStreams = 1; - method.NumOutStreams = 1; - coderStreamsInfo.NumInStreams = method.NumOutStreams; - coderStreamsInfo.NumOutStreams = method.NumInStreams; + method.NumStreams = 1; method.Id = k_AES; - _options.Methods.Add(method); - _bindInfo.Coders.Add(coderStreamsInfo); - _bindInfo.OutStreams.Add(numOutStreams + i); + + NCoderMixer2::CCoderStreamsInfo cod; + cod.NumStreams = 1; + _bindInfo.Coders.Add(cod); + + _bindInfo.PackStreams.Add(numOutStreams++); } } } - for (int i = _options.Methods.Size() - 1; i >= 0; i--) - { - const CMethodFull &methodFull = _options.Methods[i]; - _decompressionMethods.Add(methodFull.Id); - } + for (unsigned i = _options.Methods.Size(); i != 0;) + _decompressionMethods.Add(_options.Methods[--i].Id); - _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo); - _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo); + if (_bindInfo.Coders.Size() > 16) + return E_INVALIDARG; + if (_bindInfo.GetNum_Bonds_and_PackStreams() > 16) + return E_INVALIDARG; + + if (!_bindInfo.CalcMapsAndCheck()) + return E_INVALIDARG; + + InitBindConv(); _constructed = true; return S_OK; } -CEncoder::~CEncoder() -{ - delete _bindReverseConverter; -} +CEncoder::~CEncoder() {} }} |