• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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