Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/kornelski/7z.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIgor Pavlov <ipavlov@users.sourceforge.net>2015-06-15 03:00:00 +0300
committerKornel LesiƄski <kornel@geekhood.net>2016-05-28 02:16:54 +0300
commit54490d51d5c6b0d794dcbad2d634d4c95fc25b6c (patch)
treec3c413656432c0ef87b2841c80e42b55ad17d4e8 /CPP/7zip/Archive/7z/7zEncode.cpp
parent0713a3ab803e57401f18432148b4139e5fe6e5dd (diff)
15.0515.05
Diffstat (limited to 'CPP/7zip/Archive/7z/7zEncode.cpp')
-rw-r--r--CPP/7zip/Archive/7z/7zEncode.cpp580
1 files changed, 386 insertions, 194 deletions
diff --git a/CPP/7zip/Archive/7z/7zEncode.cpp b/CPP/7zip/Archive/7z/7zEncode.cpp
index 36ff5177..ab251711 100644
--- a/CPP/7zip/Archive/7z/7zEncode.cpp
+++ b/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()
+{
+ 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)
{
- // bindInfo.CoderMethodIDs.Clear();
- // folder.OutStreams.Clear();
- folder.BindPairs.SetSize(bindInfo.BindPairs.Size());
+ folder.Bonds.SetSize(_bindInfo.Bonds.Size());
+
unsigned i;
- for (i = 0; i < bindInfo.BindPairs.Size(); i++)
+
+ for (i = 0; i < _bindInfo.Bonds.Size(); i++)
{
- CBindPair &bp = folder.BindPairs[i];
- const NCoderMixer::CBindPair &mixerBp = bindInfo.BindPairs[i];
- bp.InIndex = mixerBp.InIndex;
- bp.OutIndex = mixerBp.OutIndex;
+ 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];
}
- folder.Coders.SetSize(bindInfo.Coders.Size());
- for (i = 0; i < bindInfo.Coders.Size(); i++)
+
+ folder.Coders.SetSize(_bindInfo.Coders.Size());
+
+ for (i = 0; i < _bindInfo.Coders.Size(); i++)
{
CCoderInfo &coderInfo = folder.Coders[i];
- const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
- coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;
- coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;
- coderInfo.MethodID = decompressionMethods[i];
- // coderInfo.Props can be nonFree;
+ 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.
}
- folder.PackStreams.SetSize(bindInfo.InStreams.Size());
- for (i = 0; i < bindInfo.InStreams.Size(); i++)
- folder.PackStreams[i] = 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,30 +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));
+ #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];
- CCoderInfo &encodingInfo = _codersInfo.AddNew();
- 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
{
@@ -105,21 +187,25 @@ HRESULT CEncoder::CreateMixerCoder(
}
*/
+ // now there is no codec that uses another external codec
+ /*
#ifdef EXTERNAL_CODECS
CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
if (setCompressCodecsInfo)
{
+ // we must use g_ExternalCodecs also
RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(__externalCodecs->GetCodecs));
}
#endif
+ */
CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
if (cryptoSetPassword)
{
- const UInt32 sizeInBytes = _options.Password.Len() * 2;
+ const unsigned sizeInBytes = _options.Password.Len() * 2;
CByteBuffer buffer(sizeInBytes);
for (unsigned i = 0; i < _options.Password.Len(); i++)
{
@@ -127,21 +213,79 @@ HRESULT CEncoder::CreateMixerCoder(
((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,
@@ -151,27 +295,37 @@ HRESULT CEncoder::Encode(
{
RINOK(EncoderConstr());
- if (!_mixerCoderSpec)
+ 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;
+
unsigned numMethods = _bindInfo.Coders.Size();
+
unsigned i;
- for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
+
+ for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
{
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,94 +333,111 @@ 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);
-
+
+ /* 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)
- {
- 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);
- }
+ _mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL);
+ */
- // UInt64 outStreamStartPos;
- // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));
-
CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;
CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
+
CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL;
CMyComPtr<ISequentialOutStream> outStreamSizeCount;
inStreamSizeCountSpec->Init(inStream);
- CRecordVector<ISequentialInStream *> inStreamPointers;
+ ISequentialInStream *inStreamPointer = inStreamSizeCount;
CRecordVector<ISequentialOutStream *> outStreamPointers;
- inStreamPointers.Add(inStreamSizeCount);
- if (_bindInfo.OutStreams.Size() != 0)
- {
- outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
- outStreamSizeCount = outStreamSizeCountSpec;
- outStreamSizeCountSpec->SetStream(outStream);
- outStreamSizeCountSpec->Init();
- outStreamPointers.Add(outStreamSizeCount);
- }
+ SetFolder(folderItem);
- for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
- outStreamPointers.Add(tempBuffers[i - 1]);
-
- 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);
+ coder->QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
if (resetInitVector)
{
resetInitVector->ResetInitVector();
}
CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
- _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
+ 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));
- if (_bindInfo.OutStreams.Size() != 0)
+ 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));
@@ -274,37 +445,45 @@ HRESULT CEncoder::Encode(
}
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);
+ streamSize = _mixer->GetBondStreamSize(bond);
coderUnpackSizes.Add(streamSize);
}
- for (i = 0; i < numMethods; 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)
@@ -314,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;
+ 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 if (coderStreamsInfo.NumOutStreams != 0)
- _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)
{
- unsigned 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)
@@ -428,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() {}
}}