1 // MethodProps.h
2
3 #ifndef __7Z_METHOD_PROPS_H
4 #define __7Z_METHOD_PROPS_H
5
6 #include "../../Common/MyString.h"
7 #include "../../Common/Defs.h"
8
9 #include "../../Windows/Defs.h"
10
11 #include "../../Windows/PropVariant.h"
12
13 #include "../ICoder.h"
14
15 // UInt64 GetMemoryUsage_LZMA(UInt32 dict, bool isBt, UInt32 numThreads);
16
Calc_From_Val_Percents_Less100(UInt64 val,UInt64 percents)17 inline UInt64 Calc_From_Val_Percents_Less100(UInt64 val, UInt64 percents)
18 {
19 if (percents == 0)
20 return 0;
21 if (val <= (UInt64)(Int64)-1 / percents)
22 return val * percents / 100;
23 return val / 100 * percents;
24 }
25
26 UInt64 Calc_From_Val_Percents(UInt64 val, UInt64 percents);
27
28 bool StringToBool(const wchar_t *s, bool &res);
29 HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest);
30 unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number);
31
32 /*
33 if (name.IsEmpty() && prop.vt == VT_EMPTY), it doesn't change (resValue) and returns S_OK.
34 So you must set (resValue) for default value before calling */
35 HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
36
37 /* input: (numThreads = the_number_of_processors) */
38 HRESULT ParseMtProp2(const UString &name, const PROPVARIANT &prop, UInt32 &numThreads, bool &force);
39
ParseMtProp(const UString & name,const PROPVARIANT & prop,UInt32 numCPUs,UInt32 & numThreads)40 inline HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 numCPUs, UInt32 &numThreads)
41 {
42 bool forced = false;
43 numThreads = numCPUs;
44 return ParseMtProp2(name, prop, numThreads, forced);
45 }
46
47
48 struct CProp
49 {
50 PROPID Id;
51 bool IsOptional;
52 NWindows::NCOM::CPropVariant Value;
CPropCProp53 CProp(): IsOptional(false) {}
54 };
55
56 struct CProps
57 {
58 CObjectVector<CProp> Props;
59
ClearCProps60 void Clear() { Props.Clear(); }
61
AreThereNonOptionalPropsCProps62 bool AreThereNonOptionalProps() const
63 {
64 FOR_VECTOR (i, Props)
65 if (!Props[i].IsOptional)
66 return true;
67 return false;
68 }
69
70 void AddProp32(PROPID propid, UInt32 val);
71
72 void AddPropBool(PROPID propid, bool val);
73
AddProp_AsciiCProps74 void AddProp_Ascii(PROPID propid, const char *s)
75 {
76 CProp &prop = Props.AddNew();
77 prop.IsOptional = true;
78 prop.Id = propid;
79 prop.Value = s;
80 }
81
82 HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce = NULL) const;
83 HRESULT SetCoderProps_DSReduce_Aff(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce, const UInt64 *affinity) const;
84 };
85
86 class CMethodProps: public CProps
87 {
88 HRESULT SetParam(const UString &name, const UString &value);
89 public:
90 unsigned GetLevel() const;
Get_NumThreads()91 int Get_NumThreads() const
92 {
93 const int i = FindProp(NCoderPropID::kNumThreads);
94 if (i >= 0)
95 {
96 const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;
97 if (val.vt == VT_UI4)
98 return (int)val.ulVal;
99 }
100 return -1;
101 }
102
Get_DicSize(UInt64 & res)103 bool Get_DicSize(UInt64 &res) const
104 {
105 res = 0;
106 const int i = FindProp(NCoderPropID::kDictionarySize);
107 if (i >= 0)
108 {
109 const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;
110 if (val.vt == VT_UI4)
111 {
112 res = val.ulVal;
113 return true;
114 }
115 if (val.vt == VT_UI8)
116 {
117 res = val.uhVal.QuadPart;
118 return true;
119 }
120 }
121 return false;
122 }
123
124 int FindProp(PROPID id) const;
125
Get_Lzma_Algo()126 UInt32 Get_Lzma_Algo() const
127 {
128 int i = FindProp(NCoderPropID::kAlgorithm);
129 if (i >= 0)
130 {
131 const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;
132 if (val.vt == VT_UI4)
133 return val.ulVal;
134 }
135 return GetLevel() >= 5 ? 1 : 0;
136 }
137
Get_Lzma_DicSize()138 UInt64 Get_Lzma_DicSize() const
139 {
140 UInt64 v;
141 if (Get_DicSize(v))
142 return v;
143 const unsigned level = GetLevel();
144 const UInt32 dictSize =
145 ( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) :
146 ( level <= 6 ? ((UInt32)1 << (level + 19)) :
147 ( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26)
148 )));
149 return dictSize;
150 }
151
Get_Lzma_MatchFinder_IsBt()152 bool Get_Lzma_MatchFinder_IsBt() const
153 {
154 const int i = FindProp(NCoderPropID::kMatchFinder);
155 if (i >= 0)
156 {
157 const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;
158 if (val.vt == VT_BSTR)
159 return ((val.bstrVal[0] | 0x20) != 'h'); // check for "hc"
160 }
161 return GetLevel() >= 5;
162 }
163
Get_Lzma_Eos()164 bool Get_Lzma_Eos() const
165 {
166 const int i = FindProp(NCoderPropID::kEndMarker);
167 if (i >= 0)
168 {
169 const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;
170 if (val.vt == VT_BOOL)
171 return VARIANT_BOOLToBool(val.boolVal);
172 }
173 return false;
174 }
175
Are_Lzma_Model_Props_Defined()176 bool Are_Lzma_Model_Props_Defined() const
177 {
178 if (FindProp(NCoderPropID::kPosStateBits) >= 0) return true;
179 if (FindProp(NCoderPropID::kLitContextBits) >= 0) return true;
180 if (FindProp(NCoderPropID::kLitPosBits) >= 0) return true;
181 return false;
182 }
183
Get_Lzma_NumThreads()184 UInt32 Get_Lzma_NumThreads() const
185 {
186 if (Get_Lzma_Algo() == 0)
187 return 1;
188 int numThreads = Get_NumThreads();
189 if (numThreads >= 0)
190 return numThreads < 2 ? 1 : 2;
191 return 2;
192 }
193
194 UInt64 Get_Lzma_MemUsage(bool addSlidingWindowSize) const;
195
196 /* returns -1, if numThreads is unknown */
Get_Xz_NumThreads(UInt32 & lzmaThreads)197 int Get_Xz_NumThreads(UInt32 &lzmaThreads) const
198 {
199 lzmaThreads = 1;
200 int numThreads = Get_NumThreads();
201 if (numThreads >= 0 && numThreads <= 1)
202 return 1;
203 if (Get_Lzma_Algo() != 0)
204 lzmaThreads = 2;
205 return numThreads;
206 }
207
GetProp_BlockSize(PROPID id)208 UInt64 GetProp_BlockSize(PROPID id) const
209 {
210 const int i = FindProp(id);
211 if (i >= 0)
212 {
213 const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;
214 if (val.vt == VT_UI4) { return val.ulVal; }
215 if (val.vt == VT_UI8) { return val.uhVal.QuadPart; }
216 }
217 return 0;
218 }
219
Get_Xz_BlockSize()220 UInt64 Get_Xz_BlockSize() const
221 {
222 {
223 UInt64 blockSize1 = GetProp_BlockSize(NCoderPropID::kBlockSize);
224 UInt64 blockSize2 = GetProp_BlockSize(NCoderPropID::kBlockSize2);
225 UInt64 minSize = MyMin(blockSize1, blockSize2);
226 if (minSize != 0)
227 return minSize;
228 UInt64 maxSize = MyMax(blockSize1, blockSize2);
229 if (maxSize != 0)
230 return maxSize;
231 }
232 const UInt32 kMinSize = (UInt32)1 << 20;
233 const UInt32 kMaxSize = (UInt32)1 << 28;
234 const UInt64 dictSize = Get_Lzma_DicSize();
235 /* lzma2 code uses fake 4 GiB to calculate ChunkSize. So we do same */
236 UInt64 blockSize = (UInt64)dictSize << 2;
237 if (blockSize < kMinSize) blockSize = kMinSize;
238 if (blockSize > kMaxSize) blockSize = kMaxSize;
239 if (blockSize < dictSize) blockSize = dictSize;
240 blockSize += (kMinSize - 1);
241 blockSize &= ~(UInt64)(kMinSize - 1);
242 return blockSize;
243 }
244
245
Get_BZip2_NumThreads(bool & fixedNumber)246 UInt32 Get_BZip2_NumThreads(bool &fixedNumber) const
247 {
248 fixedNumber = false;
249 int numThreads = Get_NumThreads();
250 if (numThreads >= 0)
251 {
252 fixedNumber = true;
253 if (numThreads < 1) return 1;
254 const unsigned kNumBZip2ThreadsMax = 64;
255 if ((unsigned)numThreads > kNumBZip2ThreadsMax) return kNumBZip2ThreadsMax;
256 return (unsigned)numThreads;
257 }
258 return 1;
259 }
260
Get_BZip2_BlockSize()261 UInt32 Get_BZip2_BlockSize() const
262 {
263 const int i = FindProp(NCoderPropID::kDictionarySize);
264 if (i >= 0)
265 {
266 const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;
267 if (val.vt == VT_UI4)
268 {
269 UInt32 blockSize = val.ulVal;
270 const UInt32 kDicSizeMin = 100000;
271 const UInt32 kDicSizeMax = 900000;
272 if (blockSize < kDicSizeMin) blockSize = kDicSizeMin;
273 if (blockSize > kDicSizeMax) blockSize = kDicSizeMax;
274 return blockSize;
275 }
276 }
277 const unsigned level = GetLevel();
278 return 100000 * (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1));
279 }
280
Get_Ppmd_MemSize()281 UInt64 Get_Ppmd_MemSize() const
282 {
283 const int i = FindProp(NCoderPropID::kUsedMemorySize);
284 if (i >= 0)
285 {
286 const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value;
287 if (val.vt == VT_UI4)
288 return val.ulVal;
289 if (val.vt == VT_UI8)
290 return val.uhVal.QuadPart;
291 }
292 const unsigned level = GetLevel();
293 const UInt32 mem = (UInt32)1 << (level + 19);
294 return mem;
295 }
296
AddProp_Level(UInt32 level)297 void AddProp_Level(UInt32 level)
298 {
299 AddProp32(NCoderPropID::kLevel, level);
300 }
301
AddProp_NumThreads(UInt32 numThreads)302 void AddProp_NumThreads(UInt32 numThreads)
303 {
304 AddProp32(NCoderPropID::kNumThreads, numThreads);
305 }
306
AddProp_EndMarker_if_NotFound(bool eos)307 void AddProp_EndMarker_if_NotFound(bool eos)
308 {
309 if (FindProp(NCoderPropID::kEndMarker) < 0)
310 AddPropBool(NCoderPropID::kEndMarker, eos);
311 }
312
AddProp_BlockSize2(UInt64 blockSize2)313 void AddProp_BlockSize2(UInt64 blockSize2)
314 {
315 if (FindProp(NCoderPropID::kBlockSize2) < 0)
316 {
317 CProp &prop = Props.AddNew();
318 prop.IsOptional = true;
319 prop.Id = NCoderPropID::kBlockSize2;
320 prop.Value = blockSize2;
321 }
322 }
323
324 HRESULT ParseParamsFromString(const UString &srcString);
325 HRESULT ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value);
326 };
327
328 class COneMethodInfo: public CMethodProps
329 {
330 public:
331 AString MethodName;
332 UString PropsString;
333
Clear()334 void Clear()
335 {
336 CMethodProps::Clear();
337 MethodName.Empty();
338 PropsString.Empty();
339 }
IsEmpty()340 bool IsEmpty() const { return MethodName.IsEmpty() && Props.IsEmpty(); }
341 HRESULT ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value);
342 HRESULT ParseMethodFromString(const UString &s);
343 };
344
345 #endif
346