1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// 7zEncode.cpp
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "StdAfx.h"
4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../Common/CreateCoder.h"
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../Common/FilterCoder.h"
7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../Common/LimitedStreams.h"
8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../Common/InOutTempBuffer.h"
9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../Common/ProgressUtils.h"
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../Common/StreamObjects.h"
11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "7zEncode.h"
13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "7zSpecStream.h"
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
15baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const UInt64 k_Delta = 0x03;
16baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const UInt64 k_BCJ = 0x03030103;
17baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const UInt64 k_BCJ2 = 0x0303011B;
18baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
19baa3858d3f5d128a5c8466b700098109edcad5f2repo syncnamespace NArchive {
20baa3858d3f5d128a5c8466b700098109edcad5f2repo syncnamespace N7z {
21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
22baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void ConvertBindInfoToFolderItemInfo(const NCoderMixer::CBindInfo &bindInfo,
23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CRecordVector<CMethodId> decompressionMethods,
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CFolder &folder)
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  folder.Coders.Clear();
27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  // bindInfo.CoderMethodIDs.Clear();
28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  // folder.OutStreams.Clear();
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  folder.PackStreams.Clear();
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  folder.BindPairs.Clear();
31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int i;
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < bindInfo.BindPairs.Size(); i++)
33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CBindPair bindPair;
35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bindPair.InIndex = bindInfo.BindPairs[i].InIndex;
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    bindPair.OutIndex = bindInfo.BindPairs[i].OutIndex;
37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    folder.BindPairs.Add(bindPair);
38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < bindInfo.Coders.Size(); i++)
40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CCoderInfo coderInfo;
42baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const NCoderMixer::CCoderStreamsInfo &coderStreamsInfo = bindInfo.Coders[i];
43baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    coderInfo.NumInStreams = coderStreamsInfo.NumInStreams;
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    coderInfo.NumOutStreams = coderStreamsInfo.NumOutStreams;
45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    coderInfo.MethodID = decompressionMethods[i];
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    folder.Coders.Add(coderInfo);
47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
48baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < bindInfo.InStreams.Size(); i++)
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    folder.PackStreams.Add(bindInfo.InStreams[i]);
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
52baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CEncoder::CreateMixerCoder(
53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    DECL_EXTERNAL_CODECS_LOC_VARS
54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UInt64 *inSizeForReduce)
55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _mixerCoderSpec = new NCoderMixer::CCoderMixer2MT;
57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _mixerCoder = _mixerCoderSpec;
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(_mixerCoderSpec->SetBindInfo(_bindInfo));
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (int i = 0; i < _options.Methods.Size(); i++)
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CMethodFull &methodFull = _options.Methods[i];
62baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _codersInfo.Add(CCoderInfo());
63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CCoderInfo &encodingInfo = _codersInfo.Back();
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    encodingInfo.MethodID = methodFull.Id;
65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<ICompressCoder> encoder;
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<ICompressCoder2> encoder2;
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(CreateCoder(
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        EXTERNAL_CODECS_LOC_VARS
71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        methodFull.Id, encoder, encoder2, true));
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!encoder && !encoder2)
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return E_FAIL;
75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<IUnknown> encoderCommon = encoder ? (IUnknown *)encoder : (IUnknown *)encoder2;
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifndef _7ZIP_ST
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CMyComPtr<ICompressSetCoderMt> setCoderMt;
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      encoderCommon.QueryInterface(IID_ICompressSetCoderMt, &setCoderMt);
82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (setCoderMt)
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        RINOK(setCoderMt->SetNumberOfThreads(_options.NumThreads));
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(SetMethodProperties(methodFull, inSizeForReduce, encoderCommon));
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    /*
93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<ICryptoResetSalt> resetSalt;
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    encoderCommon.QueryInterface(IID_ICryptoResetSalt, (void **)&resetSalt);
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (resetSalt != NULL)
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      resetSalt->ResetSalt();
98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    */
100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #ifdef EXTERNAL_CODECS
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<ISetCompressCodecsInfo> setCompressCodecsInfo;
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    encoderCommon.QueryInterface(IID_ISetCompressCodecsInfo, (void **)&setCompressCodecsInfo);
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (setCompressCodecsInfo)
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(setCompressCodecsInfo->SetCompressCodecsInfo(codecsInfo));
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    #endif
109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<ICryptoSetPassword> cryptoSetPassword;
111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    encoderCommon.QueryInterface(IID_ICryptoSetPassword, &cryptoSetPassword);
112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (cryptoSetPassword)
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CByteBuffer buffer;
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      const UInt32 sizeInBytes = _options.Password.Length() * 2;
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      buffer.SetCapacity(sizeInBytes);
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      for (int i = 0; i < _options.Password.Length(); i++)
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        wchar_t c = _options.Password[i];
121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        ((Byte *)buffer)[i * 2] = (Byte)c;
122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        ((Byte *)buffer)[i * 2 + 1] = (Byte)(c >> 8);
123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      RINOK(cryptoSetPassword->CryptoSetPassword((const Byte *)buffer, sizeInBytes));
125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (encoder)
128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _mixerCoderSpec->AddCoder(encoder);
129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _mixerCoderSpec->AddCoder2(encoder2);
131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
135baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CEncoder::Encode(
136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    DECL_EXTERNAL_CODECS_LOC_VARS
137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    ISequentialInStream *inStream,
138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const UInt64 *inStreamSize, const UInt64 *inSizeForReduce,
139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CFolder &folderItem,
140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    ISequentialOutStream *outStream,
141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CRecordVector<UInt64> &packSizes,
142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    ICompressProgressInfo *compressProgress)
143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(EncoderConstr());
145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (_mixerCoderSpec == NULL)
147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(CreateMixerCoder(EXTERNAL_CODECS_LOC_VARS inSizeForReduce));
149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _mixerCoderSpec->ReInit();
151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  // _mixerCoderSpec->SetCoderInfo(0, NULL, NULL, progress);
152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
153baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CObjectVector<CInOutTempBuffer> inOutTempBuffers;
154baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CObjectVector<CSequentialOutTempBufferImp *> tempBufferSpecs;
155baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CObjectVector<CMyComPtr<ISequentialOutStream> > tempBuffers;
156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int numMethods = _bindInfo.Coders.Size();
157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int i;
158baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
159baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
160baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    inOutTempBuffers.Add(CInOutTempBuffer());
161baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    inOutTempBuffers.Back().Create();
162baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    inOutTempBuffers.Back().InitWriting();
163baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
164baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
165baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
166baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CSequentialOutTempBufferImp *tempBufferSpec = new CSequentialOutTempBufferImp;
167baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<ISequentialOutStream> tempBuffer = tempBufferSpec;
168baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    tempBufferSpec->Init(&inOutTempBuffers[i - 1]);
169baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    tempBuffers.Add(tempBuffer);
170baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    tempBufferSpecs.Add(tempBufferSpec);
171baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
172baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
173baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < numMethods; i++)
174baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _mixerCoderSpec->SetCoderInfo(i, NULL, NULL);
175baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
176baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (_bindInfo.InStreams.IsEmpty())
177baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
178baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 mainCoderIndex, mainStreamIndex;
179baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _bindInfo.FindInStream(_bindInfo.InStreams[0], mainCoderIndex, mainStreamIndex);
180baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
181baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (inStreamSize != NULL)
182baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
183baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CRecordVector<const UInt64 *> sizePointers;
184baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (UInt32 i = 0; i < _bindInfo.Coders[mainCoderIndex].NumInStreams; i++)
185baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (i == mainStreamIndex)
186baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        sizePointers.Add(inStreamSize);
187baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      else
188baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        sizePointers.Add(NULL);
189baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _mixerCoderSpec->SetCoderInfo(mainCoderIndex, &sizePointers.Front(), NULL);
190baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
191baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
192baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
193baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  // UInt64 outStreamStartPos;
194baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  // RINOK(stream->Seek(0, STREAM_SEEK_CUR, &outStreamStartPos));
195baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
196baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CSequentialInStreamSizeCount2 *inStreamSizeCountSpec = new CSequentialInStreamSizeCount2;
197baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ISequentialInStream> inStreamSizeCount = inStreamSizeCountSpec;
198baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CSequentialOutStreamSizeCount *outStreamSizeCountSpec = new CSequentialOutStreamSizeCount;
199baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CMyComPtr<ISequentialOutStream> outStreamSizeCount = outStreamSizeCountSpec;
200baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
201baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  inStreamSizeCountSpec->Init(inStream);
202baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  outStreamSizeCountSpec->SetStream(outStream);
203baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  outStreamSizeCountSpec->Init();
204baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
205baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CRecordVector<ISequentialInStream *> inStreamPointers;
206baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CRecordVector<ISequentialOutStream *> outStreamPointers;
207baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  inStreamPointers.Add(inStreamSizeCount);
208baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  outStreamPointers.Add(outStreamSizeCount);
209baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
210baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    outStreamPointers.Add(tempBuffers[i - 1]);
211baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
212baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < _codersInfo.Size(); i++)
213baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
214baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CCoderInfo &encodingInfo = _codersInfo[i];
215baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
216baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<ICryptoResetInitVector> resetInitVector;
217baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _mixerCoderSpec->_coders[i].QueryInterface(IID_ICryptoResetInitVector, (void **)&resetInitVector);
218baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (resetInitVector != NULL)
219baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
220baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      resetInitVector->ResetInitVector();
221baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
222baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
223baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMyComPtr<ICompressWriteCoderProperties> writeCoderProperties;
224baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _mixerCoderSpec->_coders[i].QueryInterface(IID_ICompressWriteCoderProperties, (void **)&writeCoderProperties);
225baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (writeCoderProperties != NULL)
226baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
227baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CDynBufSeqOutStream *outStreamSpec = new CDynBufSeqOutStream;
228baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CMyComPtr<ISequentialOutStream> outStream(outStreamSpec);
229baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      outStreamSpec->Init();
230baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      writeCoderProperties->WriteCoderProperties(outStream);
231baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      outStreamSpec->CopyToBuffer(encodingInfo.Props);
232baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
233baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
234baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
235baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 progressIndex = mainCoderIndex;
236baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
237baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i + 1 < _codersInfo.Size(); i++)
238baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
239baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt64 m = _codersInfo[i].MethodID;
240baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (m == k_Delta || m == k_BCJ || m == k_BCJ2)
241baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      progressIndex = i + 1;
242baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
243baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
244baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _mixerCoderSpec->SetProgressCoderIndex(progressIndex);
245baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
246baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  RINOK(_mixerCoder->Code(&inStreamPointers.Front(), NULL, 1,
247baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    &outStreamPointers.Front(), NULL, outStreamPointers.Size(), compressProgress));
248baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
249baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ConvertBindInfoToFolderItemInfo(_decompressBindInfo, _decompressionMethods, folderItem);
250baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
251baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  packSizes.Add(outStreamSizeCountSpec->GetSize());
252baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
253baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 1; i < _bindInfo.OutStreams.Size(); i++)
254baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
255baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CInOutTempBuffer &inOutTempBuffer = inOutTempBuffers[i - 1];
256baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    RINOK(inOutTempBuffer.WriteToStream(outStream));
257baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    packSizes.Add(inOutTempBuffer.GetDataSize());
258baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
259baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
260baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < (int)_bindReverseConverter->NumSrcInStreams; i++)
261baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
262baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int binder = _bindInfo.FindBinderForInStream(
263baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        _bindReverseConverter->DestOutToSrcInMap[i]);
264baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt64 streamSize;
265baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (binder < 0)
266baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      streamSize = inStreamSizeCountSpec->GetSize();
267baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
268baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      streamSize = _mixerCoderSpec->GetWriteProcessedSize(binder);
269baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    folderItem.UnpackSizes.Add(streamSize);
270baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
271baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = numMethods - 1; i >= 0; i--)
272baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    folderItem.Coders[numMethods - 1 - i].Props = _codersInfo[i].Props;
273baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
274baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
275baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
276baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
277baa3858d3f5d128a5c8466b700098109edcad5f2repo syncCEncoder::CEncoder(const CCompressionMethodMode &options):
278baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _bindReverseConverter(0),
279baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _constructed(false)
280baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
281baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (options.IsEmpty())
282baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    throw 1;
283baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
284baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _options = options;
285baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _mixerCoderSpec = NULL;
286baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
287baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
288baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT CEncoder::EncoderConstr()
289baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
290baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (_constructed)
291baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return S_OK;
292baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (_options.Methods.IsEmpty())
293baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
294baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    // it has only password method;
295baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!_options.PasswordIsDefined)
296baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      throw 1;
297baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (!_options.Binds.IsEmpty())
298baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      throw 1;
299baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
300baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CMethodFull method;
301baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
302baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    method.NumInStreams = 1;
303baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    method.NumOutStreams = 1;
304baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    coderStreamsInfo.NumInStreams = 1;
305baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    coderStreamsInfo.NumOutStreams = 1;
306baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    method.Id = k_AES;
307baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
308baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _options.Methods.Add(method);
309baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _bindInfo.Coders.Add(coderStreamsInfo);
310baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
311baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _bindInfo.InStreams.Add(0);
312baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _bindInfo.OutStreams.Add(0);
313baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
314baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  else
315baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
316baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
317baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 numInStreams = 0, numOutStreams = 0;
318baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int i;
319baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < _options.Methods.Size(); i++)
320baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
321baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CMethodFull &methodFull = _options.Methods[i];
322baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
323baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    coderStreamsInfo.NumInStreams = methodFull.NumOutStreams;
324baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    coderStreamsInfo.NumOutStreams = methodFull.NumInStreams;
325baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (_options.Binds.IsEmpty())
326baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
327baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (i < _options.Methods.Size() - 1)
328baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
329baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        NCoderMixer::CBindPair bindPair;
330baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        bindPair.InIndex = numInStreams + coderStreamsInfo.NumInStreams;
331baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        bindPair.OutIndex = numOutStreams;
332baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        _bindInfo.BindPairs.Add(bindPair);
333baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
334baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      else
335baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        _bindInfo.OutStreams.Insert(0, numOutStreams);
336baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      for (UInt32 j = 1; j < coderStreamsInfo.NumOutStreams; j++)
337baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        _bindInfo.OutStreams.Add(numOutStreams + j);
338baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
339baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
340baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    numInStreams += coderStreamsInfo.NumInStreams;
341baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    numOutStreams += coderStreamsInfo.NumOutStreams;
342baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
343baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _bindInfo.Coders.Add(coderStreamsInfo);
344baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
345baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
346baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!_options.Binds.IsEmpty())
347baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
348baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (i = 0; i < _options.Binds.Size(); i++)
349baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
350baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      NCoderMixer::CBindPair bindPair;
351baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      const CBind &bind = _options.Binds[i];
352baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      bindPair.InIndex = _bindInfo.GetCoderInStreamIndex(bind.InCoder) + bind.InStream;
353baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      bindPair.OutIndex = _bindInfo.GetCoderOutStreamIndex(bind.OutCoder) + bind.OutStream;
354baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _bindInfo.BindPairs.Add(bindPair);
355baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
356baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (i = 0; i < (int)numOutStreams; i++)
357baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (_bindInfo.FindBinderForOutStream(i) == -1)
358baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        _bindInfo.OutStreams.Add(i);
359baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
360baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
361baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (i = 0; i < (int)numInStreams; i++)
362baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (_bindInfo.FindBinderForInStream(i) == -1)
363baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _bindInfo.InStreams.Add(i);
364baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
365baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (_bindInfo.InStreams.IsEmpty())
366baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    throw 1; // this is error
367baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
368baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  // Make main stream first in list
369baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int inIndex = _bindInfo.InStreams[0];
370baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (;;)
371baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
372baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 coderIndex, coderStreamIndex;
373baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _bindInfo.FindInStream(inIndex, coderIndex, coderStreamIndex);
374baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 outIndex = _bindInfo.GetCoderOutStreamIndex(coderIndex);
375baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int binder = _bindInfo.FindBinderForOutStream(outIndex);
376baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (binder >= 0)
377baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
378baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      inIndex = _bindInfo.BindPairs[binder].InIndex;
379baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      continue;
380baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
381baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (i = 0; i < _bindInfo.OutStreams.Size(); i++)
382baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (_bindInfo.OutStreams[i] == outIndex)
383baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
384baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        _bindInfo.OutStreams.Delete(i);
385baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        _bindInfo.OutStreams.Insert(0, outIndex);
386baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        break;
387baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
388baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    break;
389baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
390baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
391baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (_options.PasswordIsDefined)
392baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
393baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int numCryptoStreams = _bindInfo.OutStreams.Size();
394baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
395baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (i = 0; i < numCryptoStreams; i++)
396baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
397baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      NCoderMixer::CBindPair bindPair;
398baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      bindPair.InIndex = numInStreams + i;
399baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      bindPair.OutIndex = _bindInfo.OutStreams[i];
400baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _bindInfo.BindPairs.Add(bindPair);
401baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
402baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _bindInfo.OutStreams.Clear();
403baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
404baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    /*
405baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (numCryptoStreams == 0)
406baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      numCryptoStreams = 1;
407baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    */
408baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
409baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (i = 0; i < numCryptoStreams; i++)
410baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
411baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      NCoderMixer::CCoderStreamsInfo coderStreamsInfo;
412baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      CMethodFull method;
413baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      method.NumInStreams = 1;
414baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      method.NumOutStreams = 1;
415baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      coderStreamsInfo.NumInStreams = method.NumOutStreams;
416baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      coderStreamsInfo.NumOutStreams = method.NumInStreams;
417baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      method.Id = k_AES;
418baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
419baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _options.Methods.Add(method);
420baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _bindInfo.Coders.Add(coderStreamsInfo);
421baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      _bindInfo.OutStreams.Add(numOutStreams + i);
422baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
423baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
424baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
425baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
426baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
427baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (int i = _options.Methods.Size() - 1; i >= 0; i--)
428baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
429baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CMethodFull &methodFull = _options.Methods[i];
430baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    _decompressionMethods.Add(methodFull.Id);
431baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
432baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
433baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _bindReverseConverter = new NCoderMixer::CBindReverseConverter(_bindInfo);
434baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _bindReverseConverter->CreateReverseBindInfo(_decompressBindInfo);
435baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  _constructed = true;
436baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
437baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
438baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
439baa3858d3f5d128a5c8466b700098109edcad5f2repo syncCEncoder::~CEncoder()
440baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
441baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  delete _bindReverseConverter;
442baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
443baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
444baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}}
445