1 // HandlerOutCommon.cpp
5 #include "HandlerOut.h"
6 #include "../../../Windows/PropVariant.h"
7 #include "../../../Common/StringToInt.h"
8 #include "../../ICoder.h"
9 #include "../Common/ParseProperties.h"
12 #include "../../../Windows/System.h"
15 using namespace NWindows;
19 static const wchar_t *kCopyMethod = L"Copy";
20 static const wchar_t *kLZMAMethodName = L"LZMA";
21 static const wchar_t *kLZMA2MethodName = L"LZMA2";
22 static const wchar_t *kBZip2MethodName = L"BZip2";
23 static const wchar_t *kPpmdMethodName = L"PPMd";
24 static const wchar_t *kDeflateMethodName = L"Deflate";
25 static const wchar_t *kDeflate64MethodName = L"Deflate64";
27 static const wchar_t *kLzmaMatchFinderX1 = L"HC4";
28 static const wchar_t *kLzmaMatchFinderX5 = L"BT4";
30 static const UInt32 kLzmaAlgoX1 = 0;
31 static const UInt32 kLzmaAlgoX5 = 1;
33 static const UInt32 kLzmaDicSizeX1 = 1 << 16;
34 static const UInt32 kLzmaDicSizeX3 = 1 << 20;
35 static const UInt32 kLzmaDicSizeX5 = 1 << 24;
36 static const UInt32 kLzmaDicSizeX7 = 1 << 25;
37 static const UInt32 kLzmaDicSizeX9 = 1 << 26;
39 static const UInt32 kLzmaFastBytesX1 = 32;
40 static const UInt32 kLzmaFastBytesX7 = 64;
42 static const UInt32 kPpmdMemSizeX1 = (1 << 22);
43 static const UInt32 kPpmdMemSizeX5 = (1 << 24);
44 static const UInt32 kPpmdMemSizeX7 = (1 << 26);
45 static const UInt32 kPpmdMemSizeX9 = (192 << 20);
47 static const UInt32 kPpmdOrderX1 = 4;
48 static const UInt32 kPpmdOrderX5 = 6;
49 static const UInt32 kPpmdOrderX7 = 16;
50 static const UInt32 kPpmdOrderX9 = 32;
52 static const UInt32 kDeflateAlgoX1 = 0;
53 static const UInt32 kDeflateAlgoX5 = 1;
55 static const UInt32 kDeflateFastBytesX1 = 32;
56 static const UInt32 kDeflateFastBytesX7 = 64;
57 static const UInt32 kDeflateFastBytesX9 = 128;
59 static const UInt32 kDeflatePassesX1 = 1;
60 static const UInt32 kDeflatePassesX7 = 3;
61 static const UInt32 kDeflatePassesX9 = 10;
63 static const UInt32 kBZip2NumPassesX1 = 1;
64 static const UInt32 kBZip2NumPassesX7 = 2;
65 static const UInt32 kBZip2NumPassesX9 = 7;
67 static const UInt32 kBZip2DicSizeX1 = 100000;
68 static const UInt32 kBZip2DicSizeX3 = 500000;
69 static const UInt32 kBZip2DicSizeX5 = 900000;
71 static const wchar_t *kDefaultMethodName = kLZMAMethodName;
73 static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";
74 static const UInt32 kDictionaryForHeaders = 1 << 20;
75 static const UInt32 kNumFastBytesForHeaders = 273;
76 static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5;
78 static bool AreEqual(const UString &methodName, const wchar_t *s)
79 { return (methodName.CompareNoCase(s) == 0); }
81 static inline bool IsLZMAMethod(const UString &methodName)
84 AreEqual(methodName, kLZMAMethodName) ||
85 AreEqual(methodName, kLZMA2MethodName);
88 static inline bool IsBZip2Method(const UString &methodName)
89 { return AreEqual(methodName, kBZip2MethodName); }
91 static inline bool IsPpmdMethod(const UString &methodName)
92 { return AreEqual(methodName, kPpmdMethodName); }
94 static inline bool IsDeflateMethod(const UString &methodName)
97 AreEqual(methodName, kDeflateMethodName) ||
98 AreEqual(methodName, kDeflate64MethodName);
108 CNameToPropID g_NameToPropID[] =
110 { NCoderPropID::kOrder, VT_UI4, L"O" },
111 { NCoderPropID::kPosStateBits, VT_UI4, L"PB" },
112 { NCoderPropID::kLitContextBits, VT_UI4, L"LC" },
113 { NCoderPropID::kLitPosBits, VT_UI4, L"LP" },
114 { NCoderPropID::kEndMarker, VT_BOOL, L"eos" },
116 { NCoderPropID::kNumPasses, VT_UI4, L"Pass" },
117 { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" },
118 { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" },
119 { NCoderPropID::kAlgorithm, VT_UI4, L"a" },
120 { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" },
121 { NCoderPropID::kNumThreads, VT_UI4, L"mt" }
124 static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)
126 if (varType == srcProp.vt)
131 if (varType == VT_UI1)
133 if (srcProp.vt == VT_UI4)
135 UInt32 value = srcProp.ulVal;
138 destProp = (Byte)value;
142 else if (varType == VT_BOOL)
145 if (SetBoolProperty(res, srcProp) != S_OK)
153 static int FindPropIdFromStringName(const UString &name)
155 for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)
156 if (name.CompareNoCase(g_NameToPropID[i].Name) == 0)
161 static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID,
162 const NWindows::NCOM::CPropVariant &value)
164 for (int j = 0; j < oneMethodInfo.Properties.Size(); j++)
165 if (oneMethodInfo.Properties[j].Id == propID)
168 property.Id = propID;
169 property.Value = value;
170 oneMethodInfo.Properties.Add(property);
173 void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
179 UInt32 level = _level;
180 if (oneMethodInfo.MethodName.IsEmpty())
181 oneMethodInfo.MethodName = kDefaultMethodName;
183 if (IsLZMAMethod(oneMethodInfo.MethodName))
186 (level >= 9 ? kLzmaDicSizeX9 :
187 (level >= 7 ? kLzmaDicSizeX7 :
188 (level >= 5 ? kLzmaDicSizeX5 :
189 (level >= 3 ? kLzmaDicSizeX3 :
193 (level >= 5 ? kLzmaAlgoX5 :
197 (level >= 7 ? kLzmaFastBytesX7 :
200 const wchar_t *matchFinder =
201 (level >= 5 ? kLzmaMatchFinderX5 :
204 SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
205 SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
206 SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
207 SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder);
209 SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
212 else if (IsDeflateMethod(oneMethodInfo.MethodName))
215 (level >= 9 ? kDeflateFastBytesX9 :
216 (level >= 7 ? kDeflateFastBytesX7 :
217 kDeflateFastBytesX1));
220 (level >= 9 ? kDeflatePassesX9 :
221 (level >= 7 ? kDeflatePassesX7 :
225 (level >= 5 ? kDeflateAlgoX5 :
228 SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
229 SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
230 SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
232 else if (IsBZip2Method(oneMethodInfo.MethodName))
235 (level >= 9 ? kBZip2NumPassesX9 :
236 (level >= 7 ? kBZip2NumPassesX7 :
240 (level >= 5 ? kBZip2DicSizeX5 :
241 (level >= 3 ? kBZip2DicSizeX3 :
244 SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
245 SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
247 SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
250 else if (IsPpmdMethod(oneMethodInfo.MethodName))
253 (level >= 9 ? kPpmdMemSizeX9 :
254 (level >= 7 ? kPpmdMemSizeX7 :
255 (level >= 5 ? kPpmdMemSizeX5 :
259 (level >= 9 ? kPpmdOrderX9 :
260 (level >= 7 ? kPpmdOrderX7 :
261 (level >= 5 ? kPpmdOrderX5 :
264 SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize);
265 SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order);
269 static void SplitParams(const UString &srcString, UStringVector &subStrings)
273 int len = srcString.Length();
276 for (int i = 0; i < len; i++)
278 wchar_t c = srcString[i];
281 subStrings.Add(name);
287 subStrings.Add(name);
290 static void SplitParam(const UString ¶m, UString &name, UString &value)
292 int eqPos = param.Find(L'=');
295 name = param.Left(eqPos);
296 value = param.Mid(eqPos + 1);
299 for(int i = 0; i < param.Length(); i++)
301 wchar_t c = param[i];
302 if (c >= L'0' && c <= L'9')
304 name = param.Left(i);
305 value = param.Mid(i);
312 HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value)
316 name.CompareNoCase(L"D") == 0 ||
317 name.CompareNoCase(L"MEM") == 0)
320 RINOK(ParsePropDictionaryValue(value, dicSize));
321 if (name.CompareNoCase(L"D") == 0)
322 property.Id = NCoderPropID::kDictionarySize;
324 property.Id = NCoderPropID::kUsedMemorySize;
325 property.Value = dicSize;
326 oneMethodInfo.Properties.Add(property);
330 int index = FindPropIdFromStringName(name);
334 const CNameToPropID &nameToPropID = g_NameToPropID[index];
335 property.Id = nameToPropID.PropID;
337 NCOM::CPropVariant propValue;
339 if (nameToPropID.VarType == VT_BSTR)
341 else if (nameToPropID.VarType == VT_BOOL)
344 if (!StringToBool(value, res))
351 if (ParseStringToUInt32(value, number) == value.Length())
357 if (!ConvertProperty(propValue, nameToPropID.VarType, property.Value))
360 oneMethodInfo.Properties.Add(property);
365 HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString)
367 UStringVector params;
368 SplitParams(srcString, params);
369 if (params.Size() > 0)
370 oneMethodInfo.MethodName = params[0];
371 for (int i = 1; i < params.Size(); i++)
373 const UString ¶m = params[i];
375 SplitParam(param, name, value);
376 RINOK(SetParam(oneMethodInfo, name, value));
381 HRESULT COutHandler::SetSolidSettings(const UString &s)
384 if (StringToBool(s, res))
394 for (int i = 0; i < s2.Length();)
396 const wchar_t *start = ((const wchar_t *)s2) + i;
398 UInt64 v = ConvertStringToUInt64(start, &end);
403 _solidExtension = true;
406 i += (int)(end - start);
407 if (i == s2.Length())
419 _numSolidBytesDefined = true;
422 _numSolidBytes = (v << 10);
423 _numSolidBytesDefined = true;
426 _numSolidBytes = (v << 20);
427 _numSolidBytesDefined = true;
430 _numSolidBytes = (v << 30);
431 _numSolidBytesDefined = true;
440 HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value)
448 return SetSolidSettings(value.bstrVal);
454 void COutHandler::Init()
456 _removeSfxBlock = false;
457 _compressHeaders = true;
458 _encryptHeaders = false;
460 WriteModified = true;
461 WriteCreated = false;
462 WriteAccessed = false;
465 _numThreads = NWindows::NSystem::GetNumberOfProcessors();
475 void COutHandler::BeforeSetProperty()
479 numProcessors = NSystem::GetNumberOfProcessors();
482 mainDicSize = 0xFFFFFFFF;
483 mainDicMethodIndex = 0xFFFFFFFF;
488 HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
490 UString name = nameSpec;
499 return ParsePropValue(name, value, _level);
506 return SetSolidSettings(value);
507 if (value.vt != VT_EMPTY)
509 return SetSolidSettings(name);
516 return ParsePropValue(name, value, _crcSize);
520 int index = ParseStringToUInt32(name, number);
521 UString realName = name.Mid(index);
524 if(name.Left(2).CompareNoCase(L"MT") == 0)
527 RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));
531 if (name.CompareNoCase(L"RSFX") == 0)
532 return SetBoolProperty(_removeSfxBlock, value);
533 if (name.CompareNoCase(L"F") == 0)
534 return SetBoolProperty(_autoFilter, value);
535 if (name.CompareNoCase(L"HC") == 0)
536 return SetBoolProperty(_compressHeaders, value);
537 if (name.CompareNoCase(L"HCF") == 0)
539 bool compressHeadersFull = true;
540 RINOK(SetBoolProperty(compressHeadersFull, value));
541 if (!compressHeadersFull)
545 if (name.CompareNoCase(L"HE") == 0)
546 return SetBoolProperty(_encryptHeaders, value);
547 if (name.CompareNoCase(L"TM") == 0)
548 return SetBoolProperty(WriteModified, value);
549 if (name.CompareNoCase(L"TC") == 0)
550 return SetBoolProperty(WriteCreated, value);
551 if (name.CompareNoCase(L"TA") == 0)
552 return SetBoolProperty(WriteAccessed, value);
553 if (name.CompareNoCase(L"V") == 0)
554 return SetBoolProperty(_volumeMode, value);
559 if (number < minNumber)
562 for(int j = _methods.Size(); j <= (int)number; j++)
564 COneMethodInfo oneMethodInfo;
565 _methods.Add(oneMethodInfo);
568 COneMethodInfo &oneMethodInfo = _methods[number];
570 if (realName.Length() == 0)
572 if (value.vt != VT_BSTR)
575 RINOK(SetParams(oneMethodInfo, value.bstrVal));
580 if (realName.Left(1).CompareNoCase(L"D") == 0)
583 RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize));
584 property.Id = NCoderPropID::kDictionarySize;
585 property.Value = dicSize;
586 oneMethodInfo.Properties.Add(property);
587 if (number <= mainDicMethodIndex)
588 mainDicSize = dicSize;
590 else if (realName.Left(3).CompareNoCase(L"MEM") == 0)
593 RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize));
594 property.Id = NCoderPropID::kUsedMemorySize;
595 property.Value = dicSize;
596 oneMethodInfo.Properties.Add(property);
597 if (number <= mainDicMethodIndex)
598 mainDicSize = dicSize;
602 int index = FindPropIdFromStringName(realName);
606 const CNameToPropID &nameToPropID = g_NameToPropID[index];
607 property.Id = nameToPropID.PropID;
609 if (!ConvertProperty(value, nameToPropID.VarType, property.Value))
612 oneMethodInfo.Properties.Add(property);