xref: /third_party/lzma/CPP/7zip/Common/MethodProps.h (revision 370b324c)
1// MethodProps.h
2
3#ifndef ZIP7_INC_7Z_METHOD_PROPS_H
4#define ZIP7_INC_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
17inline 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
26UInt64 Calc_From_Val_Percents(UInt64 val, UInt64 percents);
27
28bool StringToBool(const wchar_t *s, bool &res);
29HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest);
30unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number);
31
32/*
33if (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 */
35HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue);
36
37/* input: (numThreads = the_number_of_processors) */
38HRESULT ParseMtProp2(const UString &name, const PROPVARIANT &prop, UInt32 &numThreads, bool &force);
39
40inline 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
48struct CProp
49{
50  PROPID Id;
51  bool IsOptional;
52  NWindows::NCOM::CPropVariant Value;
53  CProp(): IsOptional(false) {}
54};
55
56struct CProps
57{
58  CObjectVector<CProp> Props;
59
60  void Clear() { Props.Clear(); }
61
62  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
74  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
86class CMethodProps: public CProps
87{
88  HRESULT SetParam(const UString &name, const UString &value);
89public:
90  unsigned GetLevel() const;
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
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
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
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
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
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
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
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 */
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
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
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
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
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
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
297  void AddProp_Level(UInt32 level)
298  {
299    AddProp32(NCoderPropID::kLevel, level);
300  }
301
302  void AddProp_NumThreads(UInt32 numThreads)
303  {
304    AddProp32(NCoderPropID::kNumThreads, numThreads);
305  }
306
307  void AddProp_EndMarker_if_NotFound(bool eos)
308  {
309    if (FindProp(NCoderPropID::kEndMarker) < 0)
310      AddPropBool(NCoderPropID::kEndMarker, eos);
311  }
312
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
328class COneMethodInfo: public CMethodProps
329{
330public:
331  AString MethodName;
332  UString PropsString;
333
334  void Clear()
335  {
336    CMethodProps::Clear();
337    MethodName.Empty();
338    PropsString.Empty();
339  }
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