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