1 // 7zEncode.cpp
2
3 #include "StdAfx.h"
4
5 #include "../../../Common/ComTry.h"
6
7 #include "../../Common/CreateCoder.h"
8 #include "../../Common/FilterCoder.h"
9 #include "../../Common/LimitedStreams.h"
10 #include "../../Common/InOutTempBuffer.h"
11 #include "../../Common/ProgressUtils.h"
12 #include "../../Common/StreamObjects.h"
13
14 #include "7zEncode.h"
15 #include "7zSpecStream.h"
16
17 namespace NArchive {
18 namespace N7z {
19
InitBindConv()20 void CEncoder::InitBindConv()
21 {
22 unsigned numIn = _bindInfo.Coders.Size();
23
24 SrcIn_to_DestOut.ClearAndSetSize(numIn);
25 DestOut_to_SrcIn.ClearAndSetSize(numIn);
26
27 unsigned numOut = _bindInfo.GetNum_Bonds_and_PackStreams();
28 SrcOut_to_DestIn.ClearAndSetSize(numOut);
29 // _DestIn_to_SrcOut.ClearAndSetSize(numOut);
30
31 UInt32 destIn = 0;
32 UInt32 destOut = 0;
33
34 for (unsigned i = _bindInfo.Coders.Size(); i != 0;)
35 {
36 i--;
37
38 const NCoderMixer2::CCoderStreamsInfo &coder = _bindInfo.Coders[i];
39
40 numIn--;
41 numOut -= coder.NumStreams;
42
43 SrcIn_to_DestOut[numIn] = destOut;
44 DestOut_to_SrcIn[destOut] = numIn;
45
46 destOut++;
47
48 for (UInt32 j = 0; j < coder.NumStreams; j++, destIn++)
49 {
50 UInt32 index = numOut + j;
51 SrcOut_to_DestIn[index] = destIn;
52 // _DestIn_to_SrcOut[destIn] = index;
53 }
54 }
55 }
56
SetFolder(CFolder &folder)57 void CEncoder::SetFolder(CFolder &folder)
58 {
59 folder.Bonds.SetSize(_bindInfo.Bonds.Size());
60
61 unsigned i;
62
63 for (i = 0; i < _bindInfo.Bonds.Size(); i++)
64 {
65 CBond &fb = folder.Bonds[i];
66 const NCoderMixer2::CBond &mixerBond = _bindInfo.Bonds[_bindInfo.Bonds.Size() - 1 - i];
67 fb.PackIndex = SrcOut_to_DestIn[mixerBond.PackIndex];
68 fb.UnpackIndex = SrcIn_to_DestOut[mixerBond.UnpackIndex];
69 }
70
71 folder.Coders.SetSize(_bindInfo.Coders.Size());
72
73 for (i = 0; i < _bindInfo.Coders.Size(); i++)
74 {
75 CCoderInfo &coderInfo = folder.Coders[i];
76 const NCoderMixer2::CCoderStreamsInfo &coderStreamsInfo = _bindInfo.Coders[_bindInfo.Coders.Size() - 1 - i];
77
78 coderInfo.NumStreams = coderStreamsInfo.NumStreams;
79 coderInfo.MethodID = _decompressionMethods[i];
80 // we don't free coderInfo.Props here. So coderInfo.Props can be non-empty.
81 }
82
83 folder.PackStreams.SetSize(_bindInfo.PackStreams.Size());
84
85 for (i = 0; i < _bindInfo.PackStreams.Size(); i++)
86 folder.PackStreams[i] = SrcOut_to_DestIn[_bindInfo.PackStreams[i]];
87 }
88
89
90
SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder)91 static HRESULT SetCoderProps2(const CProps &props, const UInt64 *dataSizeReduce, IUnknown *coder)
92 {
93 Z7_DECL_CMyComPtr_QI_FROM(
94 ICompressSetCoderProperties,
95 setCoderProperties, coder)
96 if (setCoderProperties)
97 return props.SetCoderProps(setCoderProperties, dataSizeReduce);
98 return props.AreThereNonOptionalProps() ? E_INVALIDARG : S_OK;
99 }
100
101
102
Init(ICompressProgressInfo *progress)103 void CMtEncMultiProgress::Init(ICompressProgressInfo *progress)
104 {
105 _progress = progress;
106 OutSize = 0;
107 }
108
SetRatioInfo(const UInt64 *inSize, const UInt64 * )109 Z7_COM7F_IMF(CMtEncMultiProgress::SetRatioInfo(const UInt64 *inSize, const UInt64 * /* outSize */))
110 {
111 UInt64 outSize2;
112 {
113 #ifndef Z7_ST
114 NWindows::NSynchronization::CCriticalSectionLock lock(CriticalSection);
115 #endif
116 outSize2 = OutSize;
117 }
118
119 if (_progress)
120 return _progress->SetRatioInfo(inSize, &outSize2);
121
122 return S_OK;
123 }
124
125
126
CreateMixerCoder( DECL_EXTERNAL_CODECS_LOC_VARS const UInt64 *inSizeForReduce)127 HRESULT CEncoder::CreateMixerCoder(
128 DECL_EXTERNAL_CODECS_LOC_VARS
129 const UInt64 *inSizeForReduce)
130 {
131 #ifdef USE_MIXER_MT
132 #ifdef USE_MIXER_ST
133 if (_options.MultiThreadMixer)
134 #endif
135 {
136 _mixerMT = new NCoderMixer2::CMixerMT(true);
137 _mixerRef = _mixerMT;
138 _mixer = _mixerMT;
139 }
140 #ifdef USE_MIXER_ST
141 else
142 #endif
143 #endif
144 {
145 #ifdef USE_MIXER_ST
146 _mixerST = new NCoderMixer2::CMixerST(true);
147 _mixerRef = _mixerST;
148 _mixer = _mixerST;
149 #endif
150 }
151
152 RINOK(_mixer->SetBindInfo(_bindInfo))
153
154 FOR_VECTOR (m, _options.Methods)
155 {
156 const CMethodFull &methodFull = _options.Methods[m];
157
158 CCreatedCoder cod;
159
160 if (methodFull.CodecIndex >= 0)
161 {
162 RINOK(CreateCoder_Index(
163 EXTERNAL_CODECS_LOC_VARS
164 (unsigned)methodFull.CodecIndex, true, cod))
165 }
166 else
167 {
168 RINOK(CreateCoder_Id(
169 EXTERNAL_CODECS_LOC_VARS
170 methodFull.Id, true, cod))
171 }
172
173 if (!cod.Coder && !cod.Coder2)
174 {
175 return E_NOTIMPL; // unsupported method, if encoder
176 // return E_FAIL;
177 }
178
179 if (cod.NumStreams != methodFull.NumStreams)
180 return E_FAIL;
181
182 CMyComPtr<IUnknown> encoderCommon = cod.Coder ? (IUnknown *)cod.Coder : (IUnknown *)cod.Coder2;
183
184 #ifndef Z7_ST
185 if (methodFull.Set_NumThreads)
186 {
187 CMyComPtr<ICompressSetCoderMt> setCoderMt;
188 encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
189 if (setCoderMt)
190 {
191 RINOK(setCoderMt->SetNumberOfThreads(
192 /* _options.NumThreads */
193 methodFull.NumThreads
194 ))
195 }
196 }
197 #endif
198
199 RINOK(SetCoderProps2(methodFull, inSizeForReduce, encoderCommon))
200
201 /*
202 CMyComPtr<ICryptoResetSalt> resetSalt;
203 encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt);
204 if (resetSalt)
205 {
206 resetSalt->ResetSalt();
207 }
208 */
209
210 // now there is no codec that uses another external codec
211 /*
212 #ifdef Z7_EXTERNAL_CODECS
213 CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
214 encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
215 if (setCompressCodecsInfo)
216 {
217 // we must use g_ExternalCodecs also
218 RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs));
219 }
220 #endif
221 */
222
223 CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
224 encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
225
226 if (cryptoSetPassword)
227 {
228 const unsigned sizeInBytes = _options.Password.Len() * 2;
229 CByteBuffer_Wipe buffer(sizeInBytes);
230 for (unsigned i = 0; i < _options.Password.Len(); i++)
231 {
232 wchar_t c = _options.Password[i];
233 ((Byte *)buffer)[i * 2] = (Byte)c;
234 ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
235 }
236 RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, (UInt32)sizeInBytes))
237 }
238
239 _mixer->AddCoder(cod);
240 }
241 return S_OK;
242 }
243
244
245
246 Z7_CLASS_IMP_COM_1(
247 CSequentialOutTempBufferImp2
248 , ISequentialOutStream
249 )
250 public:
251 CInOutTempBuffer TempBuffer;
252 CMtEncMultiProgress *_mtProgressSpec;
253
CSequentialOutTempBufferImp2()254 CSequentialOutTempBufferImp2(): _mtProgressSpec(NULL) {}
255 };
256
Write(const void *data, UInt32 size, UInt32 *processed)257 Z7_COM7F_IMF(CSequentialOutTempBufferImp2::Write(const void *data, UInt32 size, UInt32 *processed))
258 {
259 COM_TRY_BEGIN
260 if (processed)
261 *processed = 0;
262 RINOK(TempBuffer.Write_HRESULT(data, size))
263 if (processed)
264 *processed = size;
265 if (_mtProgressSpec)
266 _mtProgressSpec->AddOutSize(size);
267 return S_OK;
268 COM_TRY_END
269 }
270
271
272 Z7_CLASS_IMP_COM_1(
273 CSequentialOutMtNotify
274 , ISequentialOutStream
275 )
276 public:
277 CMyComPtr<ISequentialOutStream> _stream;
278 CMtEncMultiProgress *_mtProgressSpec;
279
CSequentialOutMtNotify()280 CSequentialOutMtNotify(): _mtProgressSpec(NULL) {}
281 };
282
Write(const void *data, UInt32 size, UInt32 *processed)283 Z7_COM7F_IMF(CSequentialOutMtNotify::Write(const void *data, UInt32 size, UInt32 *processed))
284 {
285 UInt32 realProcessed = 0;
286 HRESULT res = _stream->Write(data, size, &realProcessed);
287 if (processed)
288 *processed = realProcessed;
289 if (_mtProgressSpec)
290 _mtProgressSpec->AddOutSize(size);
291 return res;
292 }
293
294
FillProps_from_Coder(IUnknown *coder, CByteBuffer &props)295 static HRESULT FillProps_from_Coder(IUnknown *coder, CByteBuffer &props)
296 {
297 Z7_DECL_CMyComPtr_QI_FROM(
298 ICompressWriteCoderProperties,
299 writeCoderProperties, coder)
300 if (writeCoderProperties)
301 {
302 CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;
303 CMyComPtr<ISequentialOutStream> dynOutStream(outStreamSpec);
304 outStreamSpec->Init();
305 RINOK(writeCoderProperties->WriteCoderProperties(dynOutStream))
306 outStreamSpec->CopyToBuffer(props);
307 }
308 else
309 props.Free();
310 return S_OK;
311 }
312
Encode1( DECL_EXTERNAL_CODECS_LOC_VARS ISequentialInStream *inStream, const UInt64 *inSizeForReduce, UInt64 expectedDataSize, CFolder &folderItem, ISequentialOutStream *outStream, CRecordVector<UInt64> &packSizes, ICompressProgressInfo *compressProgress)313 HRESULT CEncoder::Encode1(
314 DECL_EXTERNAL_CODECS_LOC_VARS
315 ISequentialInStream *inStream,
316 // const UInt64 *inStreamSize,
317 const UInt64 *inSizeForReduce,
318 UInt64 expectedDataSize,
319 CFolder &folderItem,
320 // CRecordVector<UInt64> &coderUnpackSizes,
321 // UInt64 &unpackSize,
322 ISequentialOutStream *outStream,
323 CRecordVector<UInt64> &packSizes,
324 ICompressProgressInfo *compressProgress)
325 {
326 RINOK(EncoderConstr())
327
328 if (!_mixerRef)
329 {
330 RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce))
331 }
332
333 RINOK(_mixer->ReInit2())
334
335 CMtEncMultiProgress *mtProgressSpec = NULL;
336 CMyComPtr<ICompressProgressInfo> mtProgress;
337
338 CSequentialOutMtNotify *mtOutStreamNotifySpec = NULL;
339 CMyComPtr<ISequentialOutStream> mtOutStreamNotify;
340
341 CRecordVector<CSequentialOutTempBufferImp2 *> tempBufferSpecs;
342 CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
343
344 unsigned i;
345
346 for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
347 {
348 CSequentialOutTempBufferImp2 *tempBufferSpec = new CSequentialOutTempBufferImp2();
349 CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
350 tempBufferSpecs.Add(tempBufferSpec);
351 tempBuffers.Add(tempBuffer);
352 }
353
354 const unsigned numMethods = _bindInfo.Coders.Size();
355
356 for (i = 0; i < numMethods; i++)
357 _mixer->SetCoderInfo(i, NULL, NULL, false);
358
359
360 /* inStreamSize can be used by BCJ2 to set optimal range of conversion.
361 But current BCJ2 encoder uses also another way to check exact size of current file.
362 So inStreamSize is not required. */
363
364 /*
365 if (inStreamSize)
366 _mixer->SetCoderInfo(_bindInfo.UnpackCoder, inStreamSize, NULL);
367 */
368
369
370 /*
371 CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;
372 CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
373 */
374
375 CSequentialOutStreamSizeCount *outStreamSizeCountSpec = NULL;
376 CMyComPtr<ISequentialOutStream> outStreamSizeCount;
377
378 // inStreamSizeCountSpec->Init(inStream);
379
380 // ISequentialInStream *inStreamPointer = inStreamSizeCount;
381 ISequentialInStream *inStreamPointer = inStream;
382
383 CRecordVector<ISequentialOutStream *> outStreamPointers;
384
385 SetFolder(folderItem);
386
387 for (i = 0; i < numMethods; i++)
388 {
389 IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
390 /*
391 {
392 CEncoder *sfEncoder = NULL;
393 Z7_DECL_CMyComPtr_QI_FROM(
394 IGetSfEncoderInternal,
395 sf, coder)
396 if (sf)
397 {
398 RINOK(sf->GetSfEncoder(&sfEncoder));
399 if (!sfEncoder)
400 return E_FAIL;
401
402 }
403 }
404 */
405 /*
406 #ifdef Z7_EXTERNAL_CODECS
407 {
408 Z7_DECL_CMyComPtr_QI_FROM(
409 ISetCompressCodecsInfo,
410 setCompressCodecsInfo, coder)
411 if (setCompressCodecsInfo)
412 {
413 // we must use g_ExternalCodecs also
414 RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(_externalCodecs->GetCodecs))
415 }
416 }
417 #endif
418 */
419 {
420 Z7_DECL_CMyComPtr_QI_FROM(
421 ICryptoResetInitVector,
422 resetInitVector, coder)
423 if (resetInitVector)
424 {
425 RINOK(resetInitVector->ResetInitVector())
426 }
427 }
428 {
429 Z7_DECL_CMyComPtr_QI_FROM(
430 ICompressSetCoderPropertiesOpt,
431 optProps, coder)
432 if (optProps)
433 {
434 const PROPID propID = NCoderPropID::kExpectedDataSize;
435 NWindows::NCOM::CPropVariant prop = (UInt64)expectedDataSize;
436 RINOK(optProps->SetCoderPropertiesOpt(&propID, &prop, 1))
437 }
438 }
439 // we must write properties from coder after ResetInitVector()
440 RINOK(FillProps_from_Coder(coder, folderItem.Coders[numMethods - 1 - i].Props))
441 }
442
443 _mixer->SelectMainCoder(false);
444 const UInt32 mainCoder = _mixer->MainCoderIndex;
445
446 bool useMtProgress = false;
447 if (!_mixer->Is_PackSize_Correct_for_Coder(mainCoder))
448 {
449 #ifdef Z7_ST
450 if (!_mixer->IsThere_ExternalCoder_in_PackTree(mainCoder))
451 #endif
452 useMtProgress = true;
453 }
454
455 if (useMtProgress)
456 {
457 mtProgressSpec = new CMtEncMultiProgress;
458 mtProgress = mtProgressSpec;
459 mtProgressSpec->Init(compressProgress);
460
461 mtOutStreamNotifySpec = new CSequentialOutMtNotify;
462 mtOutStreamNotify = mtOutStreamNotifySpec;
463 mtOutStreamNotifySpec->_stream = outStream;
464 mtOutStreamNotifySpec->_mtProgressSpec = mtProgressSpec;
465
466 FOR_VECTOR (t, tempBufferSpecs)
467 {
468 tempBufferSpecs[t]->_mtProgressSpec = mtProgressSpec;
469 }
470 }
471
472
473 if (_bindInfo.PackStreams.Size() != 0)
474 {
475 outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
476 outStreamSizeCount = outStreamSizeCountSpec;
477 outStreamSizeCountSpec->SetStream(mtOutStreamNotify ? (ISequentialOutStream *)mtOutStreamNotify : outStream);
478 outStreamSizeCountSpec->Init();
479 outStreamPointers.Add(outStreamSizeCount);
480 }
481
482 for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
483 outStreamPointers.Add(tempBuffers[i - 1]);
484
485 bool dataAfterEnd_Error;
486
487 RINOK(_mixer->Code(
488 &inStreamPointer,
489 &outStreamPointers.Front(),
490 mtProgress ? (ICompressProgressInfo *)mtProgress : compressProgress, dataAfterEnd_Error))
491
492 if (_bindInfo.PackStreams.Size() != 0)
493 packSizes.Add(outStreamSizeCountSpec->GetSize());
494
495 for (i = 1; i < _bindInfo.PackStreams.Size(); i++)
496 {
497 CInOutTempBuffer &iotb = tempBufferSpecs[i - 1]->TempBuffer;
498 RINOK(iotb.WriteToStream(outStream))
499 packSizes.Add(iotb.GetDataSize());
500 }
501
502 /* Code() in some future codec can change properties.
503 v23: so we fill properties again after Code() */
504 for (i = 0; i < numMethods; i++)
505 {
506 IUnknown *coder = _mixer->GetCoder(i).GetUnknown();
507 RINOK(FillProps_from_Coder(coder, folderItem.Coders[numMethods - 1 - i].Props))
508 }
509
510 return S_OK;
511 }
512
513
Encode_Post( UInt64 unpackSize, CRecordVector<UInt64> &coderUnpackSizes)514 void CEncoder::Encode_Post(
515 UInt64 unpackSize,
516 CRecordVector<UInt64> &coderUnpackSizes)
517 {
518 // unpackSize = 0;
519 for (unsigned i = 0; i < _bindInfo.Coders.Size(); i++)
520 {
521 const int bond = _bindInfo.FindBond_for_UnpackStream(DestOut_to_SrcIn[i]);
522 UInt64 streamSize;
523 if (bond < 0)
524 {
525 // streamSize = inStreamSizeCountSpec->GetSize();
526 // unpackSize = streamSize;
527 streamSize = unpackSize;
528 }
529 else
530 streamSize = _mixer->GetBondStreamSize((unsigned)bond);
531 coderUnpackSizes.Add(streamSize);
532 }
533 }
534
535
CEncoder(const CCompressionMethodMode &options)536 CEncoder::CEncoder(const CCompressionMethodMode &options):
537 _constructed(false)
538 {
539 if (options.IsEmpty())
540 throw 1;
541
542 _options = options;
543
544 #ifdef USE_MIXER_ST
545 _mixerST = NULL;
546 #endif
547
548 #ifdef USE_MIXER_MT
549 _mixerMT = NULL;
550 #endif
551
552 _mixer = NULL;
553 }
554
555
EncoderConstr()556 HRESULT CEncoder::EncoderConstr()
557 {
558 if (_constructed)
559 return S_OK;
560 if (_options.Methods.IsEmpty())
561 {
562 // it has only password method;
563 if (!_options.PasswordIsDefined)
564 throw 1;
565 if (!_options.Bonds.IsEmpty())
566 throw 1;
567
568 CMethodFull method;
569 method.Id = k_AES;
570 method.NumStreams = 1;
571 _options.Methods.Add(method);
572
573 NCoderMixer2::CCoderStreamsInfo coderStreamsInfo;
574 coderStreamsInfo.NumStreams = 1;
575 _bindInfo.Coders.Add(coderStreamsInfo);
576
577 _bindInfo.PackStreams.Add(0);
578 _bindInfo.UnpackCoder = 0;
579 }
580 else
581 {
582
583 UInt32 numOutStreams = 0;
584 unsigned i;
585
586 for (i = 0; i < _options.Methods.Size(); i++)
587 {
588 const CMethodFull &methodFull = _options.Methods[i];
589 NCoderMixer2::CCoderStreamsInfo cod;
590
591 cod.NumStreams = methodFull.NumStreams;
592
593 if (_options.Bonds.IsEmpty())
594 {
595 // if there are no bonds in options, we create bonds via first streams of coders
596 if (i != _options.Methods.Size() - 1)
597 {
598 NCoderMixer2::CBond bond;
599 bond.PackIndex = numOutStreams;
600 bond.UnpackIndex = i + 1; // it's next coder
601 _bindInfo.Bonds.Add(bond);
602 }
603 else if (cod.NumStreams != 0)
604 _bindInfo.PackStreams.Insert(0, numOutStreams);
605
606 for (UInt32 j = 1; j < cod.NumStreams; j++)
607 _bindInfo.PackStreams.Add(numOutStreams + j);
608 }
609
610 numOutStreams += cod.NumStreams;
611
612 _bindInfo.Coders.Add(cod);
613 }
614
615 if (!_options.Bonds.IsEmpty())
616 {
617 for (i = 0; i < _options.Bonds.Size(); i++)
618 {
619 NCoderMixer2::CBond mixerBond;
620 const CBond2 &bond = _options.Bonds[i];
621 if (bond.InCoder >= _bindInfo.Coders.Size()
622 || bond.OutCoder >= _bindInfo.Coders.Size()
623 || bond.OutStream >= _bindInfo.Coders[bond.OutCoder].NumStreams)
624 return E_INVALIDARG;
625 mixerBond.PackIndex = _bindInfo.GetStream_for_Coder(bond.OutCoder) + bond.OutStream;
626 mixerBond.UnpackIndex = bond.InCoder;
627 _bindInfo.Bonds.Add(mixerBond);
628 }
629
630 for (i = 0; i < numOutStreams; i++)
631 if (_bindInfo.FindBond_for_PackStream(i) == -1)
632 _bindInfo.PackStreams.Add(i);
633 }
634
635 if (!_bindInfo.SetUnpackCoder())
636 return E_INVALIDARG;
637
638 if (!_bindInfo.CalcMapsAndCheck())
639 return E_INVALIDARG;
640
641 if (_bindInfo.PackStreams.Size() != 1)
642 {
643 /* main_PackStream is pack stream of main path of coders tree.
644 We find main_PackStream, and place to start of list of out streams.
645 It allows to use more optimal memory usage for temp buffers,
646 if main_PackStream is largest stream. */
647
648 UInt32 ci = _bindInfo.UnpackCoder;
649
650 for (;;)
651 {
652 if (_bindInfo.Coders[ci].NumStreams == 0)
653 break;
654
655 const UInt32 outIndex = _bindInfo.Coder_to_Stream[ci];
656 const int bond = _bindInfo.FindBond_for_PackStream(outIndex);
657 if (bond >= 0)
658 {
659 ci = _bindInfo.Bonds[(unsigned)bond].UnpackIndex;
660 continue;
661 }
662
663 const int si = _bindInfo.FindStream_in_PackStreams(outIndex);
664 if (si >= 0)
665 _bindInfo.PackStreams.MoveToFront((unsigned)si);
666 break;
667 }
668 }
669
670 if (_options.PasswordIsDefined)
671 {
672 unsigned numCryptoStreams = _bindInfo.PackStreams.Size();
673
674 unsigned numInStreams = _bindInfo.Coders.Size();
675
676 for (i = 0; i < numCryptoStreams; i++)
677 {
678 NCoderMixer2::CBond bond;
679 bond.UnpackIndex = numInStreams + i;
680 bond.PackIndex = _bindInfo.PackStreams[i];
681 _bindInfo.Bonds.Add(bond);
682 }
683 _bindInfo.PackStreams.Clear();
684
685 /*
686 if (numCryptoStreams == 0)
687 numCryptoStreams = 1;
688 */
689
690 for (i = 0; i < numCryptoStreams; i++)
691 {
692 CMethodFull method;
693 method.NumStreams = 1;
694 method.Id = k_AES;
695 _options.Methods.Add(method);
696
697 NCoderMixer2::CCoderStreamsInfo cod;
698 cod.NumStreams = 1;
699 _bindInfo.Coders.Add(cod);
700
701 _bindInfo.PackStreams.Add(numOutStreams++);
702 }
703 }
704
705 }
706
707 for (unsigned i = _options.Methods.Size(); i != 0;)
708 _decompressionMethods.Add(_options.Methods[--i].Id);
709
710 if (_bindInfo.Coders.Size() > 16)
711 return E_INVALIDARG;
712 if (_bindInfo.GetNum_Bonds_and_PackStreams() > 16)
713 return E_INVALIDARG;
714
715 if (!_bindInfo.CalcMapsAndCheck())
716 return E_INVALIDARG;
717
718 InitBindConv();
719 _constructed = true;
720 return S_OK;
721 }
722
~CEncoder()723 CEncoder::~CEncoder() {}
724
725 }}
726