1370b324cSopenharmony_ci// MethodProps.cpp
2370b324cSopenharmony_ci
3370b324cSopenharmony_ci#include "StdAfx.h"
4370b324cSopenharmony_ci
5370b324cSopenharmony_ci#include "../../Common/StringToInt.h"
6370b324cSopenharmony_ci
7370b324cSopenharmony_ci#include "MethodProps.h"
8370b324cSopenharmony_ci
9370b324cSopenharmony_ciusing namespace NWindows;
10370b324cSopenharmony_ci
11370b324cSopenharmony_ciUInt64 Calc_From_Val_Percents(UInt64 val, UInt64 percents)
12370b324cSopenharmony_ci{
13370b324cSopenharmony_ci  // if (percents == 0) return 0;
14370b324cSopenharmony_ci  const UInt64 q = percents / 100;
15370b324cSopenharmony_ci  const UInt32 r = (UInt32)(percents % 100);
16370b324cSopenharmony_ci  UInt64 res = 0;
17370b324cSopenharmony_ci
18370b324cSopenharmony_ci  if (q != 0)
19370b324cSopenharmony_ci  {
20370b324cSopenharmony_ci    if (val > (UInt64)(Int64)-1 / q)
21370b324cSopenharmony_ci      return (UInt64)(Int64)-1;
22370b324cSopenharmony_ci    res = val * q;
23370b324cSopenharmony_ci  }
24370b324cSopenharmony_ci
25370b324cSopenharmony_ci  if (r != 0)
26370b324cSopenharmony_ci  {
27370b324cSopenharmony_ci    UInt64 v2;
28370b324cSopenharmony_ci    if (val <= (UInt64)(Int64)-1 / r)
29370b324cSopenharmony_ci      v2 = val * r / 100;
30370b324cSopenharmony_ci    else
31370b324cSopenharmony_ci      v2 = val / 100 * r;
32370b324cSopenharmony_ci    res += v2;
33370b324cSopenharmony_ci    if (res < v2)
34370b324cSopenharmony_ci      return (UInt64)(Int64)-1;
35370b324cSopenharmony_ci  }
36370b324cSopenharmony_ci
37370b324cSopenharmony_ci  return res;
38370b324cSopenharmony_ci}
39370b324cSopenharmony_ci
40370b324cSopenharmony_ci
41370b324cSopenharmony_cibool StringToBool(const wchar_t *s, bool &res)
42370b324cSopenharmony_ci{
43370b324cSopenharmony_ci  if (s[0] == 0 || (s[0] == '+' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "ON"))
44370b324cSopenharmony_ci  {
45370b324cSopenharmony_ci    res = true;
46370b324cSopenharmony_ci    return true;
47370b324cSopenharmony_ci  }
48370b324cSopenharmony_ci  if ((s[0] == '-' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "OFF"))
49370b324cSopenharmony_ci  {
50370b324cSopenharmony_ci    res = false;
51370b324cSopenharmony_ci    return true;
52370b324cSopenharmony_ci  }
53370b324cSopenharmony_ci  return false;
54370b324cSopenharmony_ci}
55370b324cSopenharmony_ci
56370b324cSopenharmony_ciHRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest)
57370b324cSopenharmony_ci{
58370b324cSopenharmony_ci  switch (prop.vt)
59370b324cSopenharmony_ci  {
60370b324cSopenharmony_ci    case VT_EMPTY: dest = true; return S_OK;
61370b324cSopenharmony_ci    case VT_BOOL: dest = (prop.boolVal != VARIANT_FALSE); return S_OK;
62370b324cSopenharmony_ci    case VT_BSTR: return StringToBool(prop.bstrVal, dest) ? S_OK : E_INVALIDARG;
63370b324cSopenharmony_ci  }
64370b324cSopenharmony_ci  return E_INVALIDARG;
65370b324cSopenharmony_ci}
66370b324cSopenharmony_ci
67370b324cSopenharmony_ciunsigned ParseStringToUInt32(const UString &srcString, UInt32 &number)
68370b324cSopenharmony_ci{
69370b324cSopenharmony_ci  const wchar_t *start = srcString;
70370b324cSopenharmony_ci  const wchar_t *end;
71370b324cSopenharmony_ci  number = ConvertStringToUInt32(start, &end);
72370b324cSopenharmony_ci  return (unsigned)(end - start);
73370b324cSopenharmony_ci}
74370b324cSopenharmony_ci
75370b324cSopenharmony_cistatic unsigned ParseStringToUInt64(const UString &srcString, UInt64 &number)
76370b324cSopenharmony_ci{
77370b324cSopenharmony_ci  const wchar_t *start = srcString;
78370b324cSopenharmony_ci  const wchar_t *end;
79370b324cSopenharmony_ci  number = ConvertStringToUInt64(start, &end);
80370b324cSopenharmony_ci  return (unsigned)(end - start);
81370b324cSopenharmony_ci}
82370b324cSopenharmony_ci
83370b324cSopenharmony_ciHRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
84370b324cSopenharmony_ci{
85370b324cSopenharmony_ci  // =VT_UI4
86370b324cSopenharmony_ci  // =VT_EMPTY : it doesn't change (resValue), and returns S_OK
87370b324cSopenharmony_ci  // {stringUInt32}=VT_EMPTY
88370b324cSopenharmony_ci
89370b324cSopenharmony_ci  if (prop.vt == VT_UI4)
90370b324cSopenharmony_ci  {
91370b324cSopenharmony_ci    if (!name.IsEmpty())
92370b324cSopenharmony_ci      return E_INVALIDARG;
93370b324cSopenharmony_ci    resValue = prop.ulVal;
94370b324cSopenharmony_ci    return S_OK;
95370b324cSopenharmony_ci  }
96370b324cSopenharmony_ci  if (prop.vt != VT_EMPTY)
97370b324cSopenharmony_ci    return E_INVALIDARG;
98370b324cSopenharmony_ci  if (name.IsEmpty())
99370b324cSopenharmony_ci    return S_OK;
100370b324cSopenharmony_ci  UInt32 v;
101370b324cSopenharmony_ci  if (ParseStringToUInt32(name, v) != name.Len())
102370b324cSopenharmony_ci    return E_INVALIDARG;
103370b324cSopenharmony_ci  resValue = v;
104370b324cSopenharmony_ci  return S_OK;
105370b324cSopenharmony_ci}
106370b324cSopenharmony_ci
107370b324cSopenharmony_ci
108370b324cSopenharmony_ci
109370b324cSopenharmony_ciHRESULT ParseMtProp2(const UString &name, const PROPVARIANT &prop, UInt32 &numThreads, bool &force)
110370b324cSopenharmony_ci{
111370b324cSopenharmony_ci  force = false;
112370b324cSopenharmony_ci  UString s;
113370b324cSopenharmony_ci  if (name.IsEmpty())
114370b324cSopenharmony_ci  {
115370b324cSopenharmony_ci    if (prop.vt == VT_UI4)
116370b324cSopenharmony_ci    {
117370b324cSopenharmony_ci      numThreads = prop.ulVal;
118370b324cSopenharmony_ci      force = true;
119370b324cSopenharmony_ci      return S_OK;
120370b324cSopenharmony_ci    }
121370b324cSopenharmony_ci    bool val;
122370b324cSopenharmony_ci    HRESULT res = PROPVARIANT_to_bool(prop, val);
123370b324cSopenharmony_ci    if (res == S_OK)
124370b324cSopenharmony_ci    {
125370b324cSopenharmony_ci      if (!val)
126370b324cSopenharmony_ci      {
127370b324cSopenharmony_ci        numThreads = 1;
128370b324cSopenharmony_ci        force = true;
129370b324cSopenharmony_ci      }
130370b324cSopenharmony_ci      // force = true; for debug
131370b324cSopenharmony_ci      // "(VT_BOOL = VARIANT_TRUE)" set "force = false" and doesn't change numThreads
132370b324cSopenharmony_ci      return S_OK;
133370b324cSopenharmony_ci    }
134370b324cSopenharmony_ci    if (prop.vt != VT_BSTR)
135370b324cSopenharmony_ci      return res;
136370b324cSopenharmony_ci    s.SetFromBstr(prop.bstrVal);
137370b324cSopenharmony_ci    if (s.IsEmpty())
138370b324cSopenharmony_ci      return E_INVALIDARG;
139370b324cSopenharmony_ci  }
140370b324cSopenharmony_ci  else
141370b324cSopenharmony_ci  {
142370b324cSopenharmony_ci    if (prop.vt != VT_EMPTY)
143370b324cSopenharmony_ci      return E_INVALIDARG;
144370b324cSopenharmony_ci    s = name;
145370b324cSopenharmony_ci  }
146370b324cSopenharmony_ci
147370b324cSopenharmony_ci  s.MakeLower_Ascii();
148370b324cSopenharmony_ci  const wchar_t *start = s;
149370b324cSopenharmony_ci  UInt32 v = numThreads;
150370b324cSopenharmony_ci
151370b324cSopenharmony_ci  /* we force up, if threads number specified
152370b324cSopenharmony_ci     only `d` will force it down */
153370b324cSopenharmony_ci  bool force_loc = true;
154370b324cSopenharmony_ci  for (;;)
155370b324cSopenharmony_ci  {
156370b324cSopenharmony_ci    const wchar_t c = *start;
157370b324cSopenharmony_ci    if (!c)
158370b324cSopenharmony_ci      break;
159370b324cSopenharmony_ci    if (c == 'd')
160370b324cSopenharmony_ci    {
161370b324cSopenharmony_ci      force_loc = false;  // force down
162370b324cSopenharmony_ci      start++;
163370b324cSopenharmony_ci      continue;
164370b324cSopenharmony_ci    }
165370b324cSopenharmony_ci    if (c == 'u')
166370b324cSopenharmony_ci    {
167370b324cSopenharmony_ci      force_loc = true;   // force up
168370b324cSopenharmony_ci      start++;
169370b324cSopenharmony_ci      continue;
170370b324cSopenharmony_ci    }
171370b324cSopenharmony_ci    bool isPercent = false;
172370b324cSopenharmony_ci    if (c == 'p')
173370b324cSopenharmony_ci    {
174370b324cSopenharmony_ci      isPercent = true;
175370b324cSopenharmony_ci      start++;
176370b324cSopenharmony_ci    }
177370b324cSopenharmony_ci    const wchar_t *end;
178370b324cSopenharmony_ci    v = ConvertStringToUInt32(start, &end);
179370b324cSopenharmony_ci    if (end == start)
180370b324cSopenharmony_ci      return E_INVALIDARG;
181370b324cSopenharmony_ci    if (isPercent)
182370b324cSopenharmony_ci      v = numThreads * v / 100;
183370b324cSopenharmony_ci    start = end;
184370b324cSopenharmony_ci  }
185370b324cSopenharmony_ci
186370b324cSopenharmony_ci  numThreads = v;
187370b324cSopenharmony_ci  force = force_loc;
188370b324cSopenharmony_ci  return S_OK;
189370b324cSopenharmony_ci}
190370b324cSopenharmony_ci
191370b324cSopenharmony_ci
192370b324cSopenharmony_ci
193370b324cSopenharmony_cistatic HRESULT SetLogSizeProp(UInt64 number, NCOM::CPropVariant &destProp)
194370b324cSopenharmony_ci{
195370b324cSopenharmony_ci  if (number >= 64)
196370b324cSopenharmony_ci    return E_INVALIDARG;
197370b324cSopenharmony_ci  UInt32 val32;
198370b324cSopenharmony_ci  if (number < 32)
199370b324cSopenharmony_ci    val32 = (UInt32)1 << (unsigned)number;
200370b324cSopenharmony_ci  /*
201370b324cSopenharmony_ci  else if (number == 32 && reduce_4GB_to_32bits)
202370b324cSopenharmony_ci    val32 = (UInt32)(Int32)-1;
203370b324cSopenharmony_ci  */
204370b324cSopenharmony_ci  else
205370b324cSopenharmony_ci  {
206370b324cSopenharmony_ci    destProp = (UInt64)((UInt64)1 << (unsigned)number);
207370b324cSopenharmony_ci    return S_OK;
208370b324cSopenharmony_ci  }
209370b324cSopenharmony_ci  destProp = (UInt32)val32;
210370b324cSopenharmony_ci  return S_OK;
211370b324cSopenharmony_ci}
212370b324cSopenharmony_ci
213370b324cSopenharmony_ci
214370b324cSopenharmony_cistatic HRESULT StringToDictSize(const UString &s, NCOM::CPropVariant &destProp)
215370b324cSopenharmony_ci{
216370b324cSopenharmony_ci  /* if (reduce_4GB_to_32bits) we can reduce (4 GiB) property to (4 GiB - 1).
217370b324cSopenharmony_ci     to fit the value to UInt32 for clients that do not support 64-bit values */
218370b324cSopenharmony_ci
219370b324cSopenharmony_ci  const wchar_t *end;
220370b324cSopenharmony_ci  const UInt64 number = ConvertStringToUInt64(s, &end);
221370b324cSopenharmony_ci  const unsigned numDigits = (unsigned)(end - s.Ptr());
222370b324cSopenharmony_ci  if (numDigits == 0 || s.Len() > numDigits + 1)
223370b324cSopenharmony_ci    return E_INVALIDARG;
224370b324cSopenharmony_ci
225370b324cSopenharmony_ci  if (s.Len() == numDigits)
226370b324cSopenharmony_ci    return SetLogSizeProp(number, destProp);
227370b324cSopenharmony_ci
228370b324cSopenharmony_ci  unsigned numBits;
229370b324cSopenharmony_ci
230370b324cSopenharmony_ci  switch (MyCharLower_Ascii(s[numDigits]))
231370b324cSopenharmony_ci  {
232370b324cSopenharmony_ci    case 'b': numBits =  0; break;
233370b324cSopenharmony_ci    case 'k': numBits = 10; break;
234370b324cSopenharmony_ci    case 'm': numBits = 20; break;
235370b324cSopenharmony_ci    case 'g': numBits = 30; break;
236370b324cSopenharmony_ci    default: return E_INVALIDARG;
237370b324cSopenharmony_ci  }
238370b324cSopenharmony_ci
239370b324cSopenharmony_ci  const UInt64 range4g = ((UInt64)1 << (32 - numBits));
240370b324cSopenharmony_ci  if (number < range4g)
241370b324cSopenharmony_ci    destProp = (UInt32)((UInt32)number << numBits);
242370b324cSopenharmony_ci  /*
243370b324cSopenharmony_ci  else if (number == range4g && reduce_4GB_to_32bits)
244370b324cSopenharmony_ci    destProp = (UInt32)(Int32)-1;
245370b324cSopenharmony_ci  */
246370b324cSopenharmony_ci  else if (numBits == 0)
247370b324cSopenharmony_ci    destProp = (UInt64)number;
248370b324cSopenharmony_ci  else if (number >= ((UInt64)1 << (64 - numBits)))
249370b324cSopenharmony_ci    return E_INVALIDARG;
250370b324cSopenharmony_ci  else
251370b324cSopenharmony_ci    destProp = (UInt64)((UInt64)number << numBits);
252370b324cSopenharmony_ci  return S_OK;
253370b324cSopenharmony_ci}
254370b324cSopenharmony_ci
255370b324cSopenharmony_ci
256370b324cSopenharmony_cistatic HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, NCOM::CPropVariant &destProp)
257370b324cSopenharmony_ci{
258370b324cSopenharmony_ci  if (prop.vt == VT_UI4)
259370b324cSopenharmony_ci    return SetLogSizeProp(prop.ulVal, destProp);
260370b324cSopenharmony_ci
261370b324cSopenharmony_ci  if (prop.vt == VT_BSTR)
262370b324cSopenharmony_ci  {
263370b324cSopenharmony_ci    UString s;
264370b324cSopenharmony_ci    s = prop.bstrVal;
265370b324cSopenharmony_ci    return StringToDictSize(s, destProp);
266370b324cSopenharmony_ci  }
267370b324cSopenharmony_ci  return E_INVALIDARG;
268370b324cSopenharmony_ci}
269370b324cSopenharmony_ci
270370b324cSopenharmony_ci
271370b324cSopenharmony_civoid CProps::AddProp32(PROPID propid, UInt32 val)
272370b324cSopenharmony_ci{
273370b324cSopenharmony_ci  CProp &prop = Props.AddNew();
274370b324cSopenharmony_ci  prop.IsOptional = true;
275370b324cSopenharmony_ci  prop.Id = propid;
276370b324cSopenharmony_ci  prop.Value = (UInt32)val;
277370b324cSopenharmony_ci}
278370b324cSopenharmony_ci
279370b324cSopenharmony_civoid CProps::AddPropBool(PROPID propid, bool val)
280370b324cSopenharmony_ci{
281370b324cSopenharmony_ci  CProp &prop = Props.AddNew();
282370b324cSopenharmony_ci  prop.IsOptional = true;
283370b324cSopenharmony_ci  prop.Id = propid;
284370b324cSopenharmony_ci  prop.Value = val;
285370b324cSopenharmony_ci}
286370b324cSopenharmony_ci
287370b324cSopenharmony_ciclass CCoderProps
288370b324cSopenharmony_ci{
289370b324cSopenharmony_ci  PROPID *_propIDs;
290370b324cSopenharmony_ci  NCOM::CPropVariant *_props;
291370b324cSopenharmony_ci  unsigned _numProps;
292370b324cSopenharmony_ci  unsigned _numPropsMax;
293370b324cSopenharmony_cipublic:
294370b324cSopenharmony_ci  CCoderProps(unsigned numPropsMax):
295370b324cSopenharmony_ci      _propIDs(NULL),
296370b324cSopenharmony_ci      _props(NULL),
297370b324cSopenharmony_ci      _numProps(0),
298370b324cSopenharmony_ci      _numPropsMax(numPropsMax)
299370b324cSopenharmony_ci  {
300370b324cSopenharmony_ci    _propIDs = new PROPID[numPropsMax];
301370b324cSopenharmony_ci    _props = new NCOM::CPropVariant[numPropsMax];
302370b324cSopenharmony_ci  }
303370b324cSopenharmony_ci  ~CCoderProps()
304370b324cSopenharmony_ci  {
305370b324cSopenharmony_ci    delete []_propIDs;
306370b324cSopenharmony_ci    delete []_props;
307370b324cSopenharmony_ci  }
308370b324cSopenharmony_ci  void AddProp(const CProp &prop);
309370b324cSopenharmony_ci  HRESULT SetProps(ICompressSetCoderProperties *setCoderProperties)
310370b324cSopenharmony_ci  {
311370b324cSopenharmony_ci    return setCoderProperties->SetCoderProperties(_propIDs, _props, _numProps);
312370b324cSopenharmony_ci  }
313370b324cSopenharmony_ci};
314370b324cSopenharmony_ci
315370b324cSopenharmony_civoid CCoderProps::AddProp(const CProp &prop)
316370b324cSopenharmony_ci{
317370b324cSopenharmony_ci  if (_numProps >= _numPropsMax)
318370b324cSopenharmony_ci    throw 1;
319370b324cSopenharmony_ci  _propIDs[_numProps] = prop.Id;
320370b324cSopenharmony_ci  _props[_numProps] = prop.Value;
321370b324cSopenharmony_ci  _numProps++;
322370b324cSopenharmony_ci}
323370b324cSopenharmony_ci
324370b324cSopenharmony_ciHRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const
325370b324cSopenharmony_ci{
326370b324cSopenharmony_ci  return SetCoderProps_DSReduce_Aff(scp, dataSizeReduce, NULL);
327370b324cSopenharmony_ci}
328370b324cSopenharmony_ci
329370b324cSopenharmony_ciHRESULT CProps::SetCoderProps_DSReduce_Aff(
330370b324cSopenharmony_ci    ICompressSetCoderProperties *scp,
331370b324cSopenharmony_ci    const UInt64 *dataSizeReduce,
332370b324cSopenharmony_ci    const UInt64 *affinity) const
333370b324cSopenharmony_ci{
334370b324cSopenharmony_ci  CCoderProps coderProps(Props.Size() + (dataSizeReduce ? 1 : 0) + (affinity ? 1 : 0) );
335370b324cSopenharmony_ci  FOR_VECTOR (i, Props)
336370b324cSopenharmony_ci    coderProps.AddProp(Props[i]);
337370b324cSopenharmony_ci  if (dataSizeReduce)
338370b324cSopenharmony_ci  {
339370b324cSopenharmony_ci    CProp prop;
340370b324cSopenharmony_ci    prop.Id = NCoderPropID::kReduceSize;
341370b324cSopenharmony_ci    prop.Value = *dataSizeReduce;
342370b324cSopenharmony_ci    coderProps.AddProp(prop);
343370b324cSopenharmony_ci  }
344370b324cSopenharmony_ci  if (affinity)
345370b324cSopenharmony_ci  {
346370b324cSopenharmony_ci    CProp prop;
347370b324cSopenharmony_ci    prop.Id = NCoderPropID::kAffinity;
348370b324cSopenharmony_ci    prop.Value = *affinity;
349370b324cSopenharmony_ci    coderProps.AddProp(prop);
350370b324cSopenharmony_ci  }
351370b324cSopenharmony_ci  return coderProps.SetProps(scp);
352370b324cSopenharmony_ci}
353370b324cSopenharmony_ci
354370b324cSopenharmony_ci
355370b324cSopenharmony_ciint CMethodProps::FindProp(PROPID id) const
356370b324cSopenharmony_ci{
357370b324cSopenharmony_ci  for (unsigned i = Props.Size(); i != 0;)
358370b324cSopenharmony_ci    if (Props[--i].Id == id)
359370b324cSopenharmony_ci      return (int)i;
360370b324cSopenharmony_ci  return -1;
361370b324cSopenharmony_ci}
362370b324cSopenharmony_ci
363370b324cSopenharmony_ciunsigned CMethodProps::GetLevel() const
364370b324cSopenharmony_ci{
365370b324cSopenharmony_ci  int i = FindProp(NCoderPropID::kLevel);
366370b324cSopenharmony_ci  if (i < 0)
367370b324cSopenharmony_ci    return 5;
368370b324cSopenharmony_ci  if (Props[(unsigned)i].Value.vt != VT_UI4)
369370b324cSopenharmony_ci    return 9;
370370b324cSopenharmony_ci  UInt32 level = Props[(unsigned)i].Value.ulVal;
371370b324cSopenharmony_ci  return level > 9 ? 9 : (unsigned)level;
372370b324cSopenharmony_ci}
373370b324cSopenharmony_ci
374370b324cSopenharmony_cistruct CNameToPropID
375370b324cSopenharmony_ci{
376370b324cSopenharmony_ci  VARTYPE VarType;
377370b324cSopenharmony_ci  const char *Name;
378370b324cSopenharmony_ci};
379370b324cSopenharmony_ci
380370b324cSopenharmony_ci
381370b324cSopenharmony_ci// the following are related to NCoderPropID::EEnum values
382370b324cSopenharmony_ci// NCoderPropID::k_NUM_DEFINED
383370b324cSopenharmony_cistatic const CNameToPropID g_NameToPropID[] =
384370b324cSopenharmony_ci{
385370b324cSopenharmony_ci  { VT_UI4, "" },
386370b324cSopenharmony_ci  { VT_UI4, "d" },
387370b324cSopenharmony_ci  { VT_UI4, "mem" },
388370b324cSopenharmony_ci  { VT_UI4, "o" },
389370b324cSopenharmony_ci  { VT_UI8, "c" },
390370b324cSopenharmony_ci  { VT_UI4, "pb" },
391370b324cSopenharmony_ci  { VT_UI4, "lc" },
392370b324cSopenharmony_ci  { VT_UI4, "lp" },
393370b324cSopenharmony_ci  { VT_UI4, "fb" },
394370b324cSopenharmony_ci  { VT_BSTR, "mf" },
395370b324cSopenharmony_ci  { VT_UI4, "mc" },
396370b324cSopenharmony_ci  { VT_UI4, "pass" },
397370b324cSopenharmony_ci  { VT_UI4, "a" },
398370b324cSopenharmony_ci  { VT_UI4, "mt" },
399370b324cSopenharmony_ci  { VT_BOOL, "eos" },
400370b324cSopenharmony_ci  { VT_UI4, "x" },
401370b324cSopenharmony_ci  { VT_UI8, "reduce" },
402370b324cSopenharmony_ci  { VT_UI8, "expect" },
403370b324cSopenharmony_ci  { VT_UI8, "cc" }, // "cc" in v23,  "b" in v22.01
404370b324cSopenharmony_ci  { VT_UI4, "check" },
405370b324cSopenharmony_ci  { VT_BSTR, "filter" },
406370b324cSopenharmony_ci  { VT_UI8, "memuse" },
407370b324cSopenharmony_ci  { VT_UI8, "aff" },
408370b324cSopenharmony_ci  { VT_UI4, "offset" },
409370b324cSopenharmony_ci  { VT_UI4, "zhb" }
410370b324cSopenharmony_ci  /*
411370b324cSopenharmony_ci  ,
412370b324cSopenharmony_ci  // { VT_UI4, "zhc" },
413370b324cSopenharmony_ci  // { VT_UI4, "zhd" },
414370b324cSopenharmony_ci  // { VT_UI4, "zcb" },
415370b324cSopenharmony_ci  { VT_UI4, "dc" },
416370b324cSopenharmony_ci  { VT_UI4, "zx" },
417370b324cSopenharmony_ci  { VT_UI4, "zf" },
418370b324cSopenharmony_ci  { VT_UI4, "zmml" },
419370b324cSopenharmony_ci  { VT_UI4, "zov" },
420370b324cSopenharmony_ci  { VT_BOOL, "zmfr" },
421370b324cSopenharmony_ci  { VT_BOOL, "zle" }, // long enable
422370b324cSopenharmony_ci  // { VT_UI4, "zldb" },
423370b324cSopenharmony_ci  { VT_UI4, "zld" },
424370b324cSopenharmony_ci  { VT_UI4, "zlhb" },
425370b324cSopenharmony_ci  { VT_UI4, "zlmml" },
426370b324cSopenharmony_ci  { VT_UI4, "zlbb" },
427370b324cSopenharmony_ci  { VT_UI4, "zlhrb" },
428370b324cSopenharmony_ci  { VT_BOOL, "zwus" },
429370b324cSopenharmony_ci  { VT_BOOL, "zshp" },
430370b324cSopenharmony_ci  { VT_BOOL, "zshs" },
431370b324cSopenharmony_ci  { VT_BOOL, "zshe" },
432370b324cSopenharmony_ci  { VT_BOOL, "zshg" },
433370b324cSopenharmony_ci  { VT_UI4, "zpsm" }
434370b324cSopenharmony_ci  */
435370b324cSopenharmony_ci  // { VT_UI4, "mcb" }, // mc log version
436370b324cSopenharmony_ci  // { VT_UI4, "ztlen" },  // fb ?
437370b324cSopenharmony_ci};
438370b324cSopenharmony_ci
439370b324cSopenharmony_ci/*
440370b324cSopenharmony_ci#if defined(static_assert) || (defined(__cplusplus) && __cplusplus >= 200410L) || (defined(_MSC_VER) && _MSC_VER >= 1600)
441370b324cSopenharmony_ci
442370b324cSopenharmony_ci#if (defined(__cplusplus) && __cplusplus < 201103L) \
443370b324cSopenharmony_ci    && defined(__clang__) && __clang_major__ >= 4
444370b324cSopenharmony_ci#pragma GCC diagnostic ignored "-Wc11-extensions"
445370b324cSopenharmony_ci#endif
446370b324cSopenharmony_ci  static_assert(Z7_ARRAY_SIZE(g_NameToPropID) == NCoderPropID::k_NUM_DEFINED,
447370b324cSopenharmony_ci    "g_NameToPropID doesn't match NCoderPropID enum");
448370b324cSopenharmony_ci#endif
449370b324cSopenharmony_ci*/
450370b324cSopenharmony_ci
451370b324cSopenharmony_cistatic int FindPropIdExact(const UString &name)
452370b324cSopenharmony_ci{
453370b324cSopenharmony_ci  for (unsigned i = 0; i < Z7_ARRAY_SIZE(g_NameToPropID); i++)
454370b324cSopenharmony_ci    if (StringsAreEqualNoCase_Ascii(name, g_NameToPropID[i].Name))
455370b324cSopenharmony_ci      return (int)i;
456370b324cSopenharmony_ci  return -1;
457370b324cSopenharmony_ci}
458370b324cSopenharmony_ci
459370b324cSopenharmony_cistatic bool ConvertProperty(const PROPVARIANT &srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)
460370b324cSopenharmony_ci{
461370b324cSopenharmony_ci  if (varType == srcProp.vt)
462370b324cSopenharmony_ci  {
463370b324cSopenharmony_ci    destProp = srcProp;
464370b324cSopenharmony_ci    return true;
465370b324cSopenharmony_ci  }
466370b324cSopenharmony_ci
467370b324cSopenharmony_ci  if (varType == VT_UI8 && srcProp.vt == VT_UI4)
468370b324cSopenharmony_ci  {
469370b324cSopenharmony_ci    destProp = (UInt64)srcProp.ulVal;
470370b324cSopenharmony_ci    return true;
471370b324cSopenharmony_ci  }
472370b324cSopenharmony_ci
473370b324cSopenharmony_ci  if (varType == VT_BOOL)
474370b324cSopenharmony_ci  {
475370b324cSopenharmony_ci    bool res;
476370b324cSopenharmony_ci    if (PROPVARIANT_to_bool(srcProp, res) != S_OK)
477370b324cSopenharmony_ci      return false;
478370b324cSopenharmony_ci    destProp = res;
479370b324cSopenharmony_ci    return true;
480370b324cSopenharmony_ci  }
481370b324cSopenharmony_ci  if (srcProp.vt == VT_EMPTY)
482370b324cSopenharmony_ci  {
483370b324cSopenharmony_ci    destProp = srcProp;
484370b324cSopenharmony_ci    return true;
485370b324cSopenharmony_ci  }
486370b324cSopenharmony_ci  return false;
487370b324cSopenharmony_ci}
488370b324cSopenharmony_ci
489370b324cSopenharmony_cistatic void SplitParams(const UString &srcString, UStringVector &subStrings)
490370b324cSopenharmony_ci{
491370b324cSopenharmony_ci  subStrings.Clear();
492370b324cSopenharmony_ci  UString s;
493370b324cSopenharmony_ci  unsigned len = srcString.Len();
494370b324cSopenharmony_ci  if (len == 0)
495370b324cSopenharmony_ci    return;
496370b324cSopenharmony_ci  for (unsigned i = 0; i < len; i++)
497370b324cSopenharmony_ci  {
498370b324cSopenharmony_ci    wchar_t c = srcString[i];
499370b324cSopenharmony_ci    if (c == L':')
500370b324cSopenharmony_ci    {
501370b324cSopenharmony_ci      subStrings.Add(s);
502370b324cSopenharmony_ci      s.Empty();
503370b324cSopenharmony_ci    }
504370b324cSopenharmony_ci    else
505370b324cSopenharmony_ci      s += c;
506370b324cSopenharmony_ci  }
507370b324cSopenharmony_ci  subStrings.Add(s);
508370b324cSopenharmony_ci}
509370b324cSopenharmony_ci
510370b324cSopenharmony_cistatic void SplitParam(const UString &param, UString &name, UString &value)
511370b324cSopenharmony_ci{
512370b324cSopenharmony_ci  int eqPos = param.Find(L'=');
513370b324cSopenharmony_ci  if (eqPos >= 0)
514370b324cSopenharmony_ci  {
515370b324cSopenharmony_ci    name.SetFrom(param, (unsigned)eqPos);
516370b324cSopenharmony_ci    value = param.Ptr((unsigned)(eqPos + 1));
517370b324cSopenharmony_ci    return;
518370b324cSopenharmony_ci  }
519370b324cSopenharmony_ci  unsigned i;
520370b324cSopenharmony_ci  for (i = 0; i < param.Len(); i++)
521370b324cSopenharmony_ci  {
522370b324cSopenharmony_ci    wchar_t c = param[i];
523370b324cSopenharmony_ci    if (c >= L'0' && c <= L'9')
524370b324cSopenharmony_ci      break;
525370b324cSopenharmony_ci  }
526370b324cSopenharmony_ci  name.SetFrom(param, i);
527370b324cSopenharmony_ci  value = param.Ptr(i);
528370b324cSopenharmony_ci}
529370b324cSopenharmony_ci
530370b324cSopenharmony_cistatic bool IsLogSizeProp(PROPID propid)
531370b324cSopenharmony_ci{
532370b324cSopenharmony_ci  switch (propid)
533370b324cSopenharmony_ci  {
534370b324cSopenharmony_ci    case NCoderPropID::kDictionarySize:
535370b324cSopenharmony_ci    case NCoderPropID::kUsedMemorySize:
536370b324cSopenharmony_ci    case NCoderPropID::kBlockSize:
537370b324cSopenharmony_ci    case NCoderPropID::kBlockSize2:
538370b324cSopenharmony_ci    /*
539370b324cSopenharmony_ci    case NCoderPropID::kChainSize:
540370b324cSopenharmony_ci    case NCoderPropID::kLdmWindowSize:
541370b324cSopenharmony_ci    */
542370b324cSopenharmony_ci    // case NCoderPropID::kReduceSize:
543370b324cSopenharmony_ci      return true;
544370b324cSopenharmony_ci  }
545370b324cSopenharmony_ci  return false;
546370b324cSopenharmony_ci}
547370b324cSopenharmony_ci
548370b324cSopenharmony_ciHRESULT CMethodProps::SetParam(const UString &name, const UString &value)
549370b324cSopenharmony_ci{
550370b324cSopenharmony_ci  int index = FindPropIdExact(name);
551370b324cSopenharmony_ci  if (index < 0)
552370b324cSopenharmony_ci  {
553370b324cSopenharmony_ci    // 'b' was used as NCoderPropID::kBlockSize2 before v23
554370b324cSopenharmony_ci    if (!name.IsEqualTo_Ascii_NoCase("b") || value.Find(L':') >= 0)
555370b324cSopenharmony_ci      return E_INVALIDARG;
556370b324cSopenharmony_ci    index = NCoderPropID::kBlockSize2;
557370b324cSopenharmony_ci  }
558370b324cSopenharmony_ci  const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index];
559370b324cSopenharmony_ci  CProp prop;
560370b324cSopenharmony_ci  prop.Id = (unsigned)index;
561370b324cSopenharmony_ci
562370b324cSopenharmony_ci  if (IsLogSizeProp(prop.Id))
563370b324cSopenharmony_ci  {
564370b324cSopenharmony_ci    RINOK(StringToDictSize(value, prop.Value))
565370b324cSopenharmony_ci  }
566370b324cSopenharmony_ci  else
567370b324cSopenharmony_ci  {
568370b324cSopenharmony_ci    NCOM::CPropVariant propValue;
569370b324cSopenharmony_ci    if (nameToPropID.VarType == VT_BSTR)
570370b324cSopenharmony_ci      propValue = value;
571370b324cSopenharmony_ci    else if (nameToPropID.VarType == VT_BOOL)
572370b324cSopenharmony_ci    {
573370b324cSopenharmony_ci      bool res;
574370b324cSopenharmony_ci      if (!StringToBool(value, res))
575370b324cSopenharmony_ci        return E_INVALIDARG;
576370b324cSopenharmony_ci      propValue = res;
577370b324cSopenharmony_ci    }
578370b324cSopenharmony_ci    else if (!value.IsEmpty())
579370b324cSopenharmony_ci    {
580370b324cSopenharmony_ci      if (nameToPropID.VarType == VT_UI4)
581370b324cSopenharmony_ci      {
582370b324cSopenharmony_ci        UInt32 number;
583370b324cSopenharmony_ci        if (ParseStringToUInt32(value, number) == value.Len())
584370b324cSopenharmony_ci          propValue = number;
585370b324cSopenharmony_ci        else
586370b324cSopenharmony_ci          propValue = value;
587370b324cSopenharmony_ci      }
588370b324cSopenharmony_ci      else if (nameToPropID.VarType == VT_UI8)
589370b324cSopenharmony_ci      {
590370b324cSopenharmony_ci        UInt64 number;
591370b324cSopenharmony_ci        if (ParseStringToUInt64(value, number) == value.Len())
592370b324cSopenharmony_ci          propValue = number;
593370b324cSopenharmony_ci        else
594370b324cSopenharmony_ci          propValue = value;
595370b324cSopenharmony_ci      }
596370b324cSopenharmony_ci      else
597370b324cSopenharmony_ci        propValue = value;
598370b324cSopenharmony_ci    }
599370b324cSopenharmony_ci    if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value))
600370b324cSopenharmony_ci      return E_INVALIDARG;
601370b324cSopenharmony_ci  }
602370b324cSopenharmony_ci  Props.Add(prop);
603370b324cSopenharmony_ci  return S_OK;
604370b324cSopenharmony_ci}
605370b324cSopenharmony_ci
606370b324cSopenharmony_ciHRESULT CMethodProps::ParseParamsFromString(const UString &srcString)
607370b324cSopenharmony_ci{
608370b324cSopenharmony_ci  UStringVector params;
609370b324cSopenharmony_ci  SplitParams(srcString, params);
610370b324cSopenharmony_ci  FOR_VECTOR (i, params)
611370b324cSopenharmony_ci  {
612370b324cSopenharmony_ci    const UString &param = params[i];
613370b324cSopenharmony_ci    UString name, value;
614370b324cSopenharmony_ci    SplitParam(param, name, value);
615370b324cSopenharmony_ci    RINOK(SetParam(name, value))
616370b324cSopenharmony_ci  }
617370b324cSopenharmony_ci  return S_OK;
618370b324cSopenharmony_ci}
619370b324cSopenharmony_ci
620370b324cSopenharmony_ciHRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value)
621370b324cSopenharmony_ci{
622370b324cSopenharmony_ci  if (realName.Len() == 0)
623370b324cSopenharmony_ci  {
624370b324cSopenharmony_ci    // [empty]=method
625370b324cSopenharmony_ci    return E_INVALIDARG;
626370b324cSopenharmony_ci  }
627370b324cSopenharmony_ci  if (value.vt == VT_EMPTY)
628370b324cSopenharmony_ci  {
629370b324cSopenharmony_ci    // {realName}=[empty]
630370b324cSopenharmony_ci    UString name, valueStr;
631370b324cSopenharmony_ci    SplitParam(realName, name, valueStr);
632370b324cSopenharmony_ci    return SetParam(name, valueStr);
633370b324cSopenharmony_ci  }
634370b324cSopenharmony_ci
635370b324cSopenharmony_ci  // {realName}=value
636370b324cSopenharmony_ci  const int index = FindPropIdExact(realName);
637370b324cSopenharmony_ci  if (index < 0)
638370b324cSopenharmony_ci    return E_INVALIDARG;
639370b324cSopenharmony_ci  const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index];
640370b324cSopenharmony_ci  CProp prop;
641370b324cSopenharmony_ci  prop.Id = (unsigned)index;
642370b324cSopenharmony_ci
643370b324cSopenharmony_ci  if (IsLogSizeProp(prop.Id))
644370b324cSopenharmony_ci  {
645370b324cSopenharmony_ci    RINOK(PROPVARIANT_to_DictSize(value, prop.Value))
646370b324cSopenharmony_ci  }
647370b324cSopenharmony_ci  else
648370b324cSopenharmony_ci  {
649370b324cSopenharmony_ci    if (!ConvertProperty(value, nameToPropID.VarType, prop.Value))
650370b324cSopenharmony_ci      return E_INVALIDARG;
651370b324cSopenharmony_ci  }
652370b324cSopenharmony_ci  Props.Add(prop);
653370b324cSopenharmony_ci  return S_OK;
654370b324cSopenharmony_ci}
655370b324cSopenharmony_ci
656370b324cSopenharmony_ci
657370b324cSopenharmony_cistatic UInt64 GetMemoryUsage_LZMA(UInt32 dict, bool isBt, UInt32 numThreads)
658370b324cSopenharmony_ci{
659370b324cSopenharmony_ci  UInt32 hs = dict - 1;
660370b324cSopenharmony_ci  hs |= (hs >> 1);
661370b324cSopenharmony_ci  hs |= (hs >> 2);
662370b324cSopenharmony_ci  hs |= (hs >> 4);
663370b324cSopenharmony_ci  hs |= (hs >> 8);
664370b324cSopenharmony_ci  hs >>= 1;
665370b324cSopenharmony_ci  if (hs >= (1 << 24))
666370b324cSopenharmony_ci    hs >>= 1;
667370b324cSopenharmony_ci  hs |= (1 << 16) - 1;
668370b324cSopenharmony_ci  // if (numHashBytes >= 5)
669370b324cSopenharmony_ci  if (!isBt)
670370b324cSopenharmony_ci    hs |= (256 << 10) - 1;
671370b324cSopenharmony_ci  hs++;
672370b324cSopenharmony_ci  UInt64 size1 = (UInt64)hs * 4;
673370b324cSopenharmony_ci  size1 += (UInt64)dict * 4;
674370b324cSopenharmony_ci  if (isBt)
675370b324cSopenharmony_ci    size1 += (UInt64)dict * 4;
676370b324cSopenharmony_ci  size1 += (2 << 20);
677370b324cSopenharmony_ci
678370b324cSopenharmony_ci  if (numThreads > 1 && isBt)
679370b324cSopenharmony_ci    size1 += (2 << 20) + (4 << 20);
680370b324cSopenharmony_ci  return size1;
681370b324cSopenharmony_ci}
682370b324cSopenharmony_ci
683370b324cSopenharmony_cistatic const UInt32 kLzmaMaxDictSize = (UInt32)15 << 28;
684370b324cSopenharmony_ci
685370b324cSopenharmony_ciUInt64 CMethodProps::Get_Lzma_MemUsage(bool addSlidingWindowSize) const
686370b324cSopenharmony_ci{
687370b324cSopenharmony_ci  const UInt64 dicSize = Get_Lzma_DicSize();
688370b324cSopenharmony_ci  const bool isBt = Get_Lzma_MatchFinder_IsBt();
689370b324cSopenharmony_ci  const UInt32 dict32 = (dicSize >= kLzmaMaxDictSize ? kLzmaMaxDictSize : (UInt32)dicSize);
690370b324cSopenharmony_ci  const UInt32 numThreads = Get_Lzma_NumThreads();
691370b324cSopenharmony_ci  UInt64 size = GetMemoryUsage_LZMA(dict32, isBt, numThreads);
692370b324cSopenharmony_ci
693370b324cSopenharmony_ci  if (addSlidingWindowSize)
694370b324cSopenharmony_ci  {
695370b324cSopenharmony_ci    const UInt32 kBlockSizeMax = (UInt32)0 - (UInt32)(1 << 16);
696370b324cSopenharmony_ci    UInt64 blockSize = (UInt64)dict32 + (1 << 16)
697370b324cSopenharmony_ci        + (numThreads > 1 ? (1 << 20) : 0);
698370b324cSopenharmony_ci    blockSize += (blockSize >> (blockSize < ((UInt32)1 << 30) ? 1 : 2));
699370b324cSopenharmony_ci    if (blockSize >= kBlockSizeMax)
700370b324cSopenharmony_ci      blockSize = kBlockSizeMax;
701370b324cSopenharmony_ci    size += blockSize;
702370b324cSopenharmony_ci  }
703370b324cSopenharmony_ci  return size;
704370b324cSopenharmony_ci}
705370b324cSopenharmony_ci
706370b324cSopenharmony_ci
707370b324cSopenharmony_ci
708370b324cSopenharmony_ci
709370b324cSopenharmony_ciHRESULT COneMethodInfo::ParseMethodFromString(const UString &s)
710370b324cSopenharmony_ci{
711370b324cSopenharmony_ci  MethodName.Empty();
712370b324cSopenharmony_ci  int splitPos = s.Find(L':');
713370b324cSopenharmony_ci  {
714370b324cSopenharmony_ci    UString temp = s;
715370b324cSopenharmony_ci    if (splitPos >= 0)
716370b324cSopenharmony_ci      temp.DeleteFrom((unsigned)splitPos);
717370b324cSopenharmony_ci    if (!temp.IsAscii())
718370b324cSopenharmony_ci      return E_INVALIDARG;
719370b324cSopenharmony_ci    MethodName.SetFromWStr_if_Ascii(temp);
720370b324cSopenharmony_ci  }
721370b324cSopenharmony_ci  if (splitPos < 0)
722370b324cSopenharmony_ci    return S_OK;
723370b324cSopenharmony_ci  PropsString = s.Ptr((unsigned)(splitPos + 1));
724370b324cSopenharmony_ci  return ParseParamsFromString(PropsString);
725370b324cSopenharmony_ci}
726370b324cSopenharmony_ci
727370b324cSopenharmony_ciHRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value)
728370b324cSopenharmony_ci{
729370b324cSopenharmony_ci  if (!realName.IsEmpty() && !StringsAreEqualNoCase_Ascii(realName, "m"))
730370b324cSopenharmony_ci    return ParseParamsFromPROPVARIANT(realName, value);
731370b324cSopenharmony_ci  // -m{N}=method
732370b324cSopenharmony_ci  if (value.vt != VT_BSTR)
733370b324cSopenharmony_ci    return E_INVALIDARG;
734370b324cSopenharmony_ci  UString s;
735370b324cSopenharmony_ci  s = value.bstrVal;
736370b324cSopenharmony_ci  return ParseMethodFromString(s);
737370b324cSopenharmony_ci}
738