1// ParseProperties.cpp
2
3#include "StdAfx.h"
4
5#include "ParseProperties.h"
6
7#include "Common/StringToInt.h"
8#include "Common/MyCom.h"
9
10HRESULT ParsePropValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
11{
12  if (prop.vt == VT_UI4)
13  {
14    if (!name.IsEmpty())
15      return E_INVALIDARG;
16    resValue = prop.ulVal;
17  }
18  else if (prop.vt == VT_EMPTY)
19  {
20    if(!name.IsEmpty())
21    {
22      const wchar_t *start = name;
23      const wchar_t *end;
24      UInt64 v = ConvertStringToUInt64(start, &end);
25      if (end - start != name.Length())
26        return E_INVALIDARG;
27      resValue = (UInt32)v;
28    }
29  }
30  else
31    return E_INVALIDARG;
32  return S_OK;
33}
34
35static const int kLogarithmicSizeLimit = 32;
36static const wchar_t kByteSymbol = L'B';
37static const wchar_t kKiloByteSymbol = L'K';
38static const wchar_t kMegaByteSymbol = L'M';
39
40HRESULT ParsePropDictionaryValue(const UString &srcStringSpec, UInt32 &dicSize)
41{
42  UString srcString = srcStringSpec;
43  srcString.MakeUpper();
44
45  const wchar_t *start = srcString;
46  const wchar_t *end;
47  UInt64 number = ConvertStringToUInt64(start, &end);
48  int numDigits = (int)(end - start);
49  if (numDigits == 0 || srcString.Length() > numDigits + 1)
50    return E_INVALIDARG;
51  if (srcString.Length() == numDigits)
52  {
53    if (number >= kLogarithmicSizeLimit)
54      return E_INVALIDARG;
55    dicSize = (UInt32)1 << (int)number;
56    return S_OK;
57  }
58  switch (srcString[numDigits])
59  {
60    case kByteSymbol:
61      if (number >= ((UInt64)1 << kLogarithmicSizeLimit))
62        return E_INVALIDARG;
63      dicSize = (UInt32)number;
64      break;
65    case kKiloByteSymbol:
66      if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 10)))
67        return E_INVALIDARG;
68      dicSize = (UInt32)(number << 10);
69      break;
70    case kMegaByteSymbol:
71      if (number >= ((UInt64)1 << (kLogarithmicSizeLimit - 20)))
72        return E_INVALIDARG;
73      dicSize = (UInt32)(number << 20);
74      break;
75    default:
76      return E_INVALIDARG;
77  }
78  return S_OK;
79}
80
81HRESULT ParsePropDictionaryValue(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)
82{
83  if (name.IsEmpty())
84  {
85    if (prop.vt == VT_UI4)
86    {
87      UInt32 logDicSize = prop.ulVal;
88      if (logDicSize >= 32)
89        return E_INVALIDARG;
90      resValue = (UInt32)1 << logDicSize;
91      return S_OK;
92    }
93    if (prop.vt == VT_BSTR)
94      return ParsePropDictionaryValue(prop.bstrVal, resValue);
95    return E_INVALIDARG;
96  }
97  return ParsePropDictionaryValue(name, resValue);
98}
99
100bool StringToBool(const UString &s, bool &res)
101{
102  if (s.IsEmpty() || s.CompareNoCase(L"ON") == 0 || s.Compare(L"+") == 0)
103  {
104    res = true;
105    return true;
106  }
107  if (s.CompareNoCase(L"OFF") == 0 || s.Compare(L"-") == 0)
108  {
109    res = false;
110    return true;
111  }
112  return false;
113}
114
115HRESULT SetBoolProperty(bool &dest, const PROPVARIANT &value)
116{
117  switch(value.vt)
118  {
119    case VT_EMPTY:
120      dest = true;
121      return S_OK;
122    case VT_BOOL:
123      dest = (value.boolVal != VARIANT_FALSE);
124      return S_OK;
125    /*
126    case VT_UI4:
127      dest = (value.ulVal != 0);
128      break;
129    */
130    case VT_BSTR:
131      return StringToBool(value.bstrVal, dest) ?  S_OK : E_INVALIDARG;
132  }
133  return E_INVALIDARG;
134}
135
136int ParseStringToUInt32(const UString &srcString, UInt32 &number)
137{
138  const wchar_t *start = srcString;
139  const wchar_t *end;
140  UInt64 number64 = ConvertStringToUInt64(start, &end);
141  if (number64 > 0xFFFFFFFF)
142  {
143    number = 0;
144    return 0;
145  }
146  number = (UInt32)number64;
147  return (int)(end - start);
148}
149
150HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads)
151{
152  if (name.IsEmpty())
153  {
154    switch(prop.vt)
155    {
156      case VT_UI4:
157        numThreads = prop.ulVal;
158        break;
159      default:
160      {
161        bool val;
162        RINOK(SetBoolProperty(val, prop));
163        numThreads = (val ? defaultNumThreads : 1);
164        break;
165      }
166    }
167  }
168  else
169  {
170    UInt32 number;
171    int index = ParseStringToUInt32(name, number);
172    if (index != name.Length())
173      return E_INVALIDARG;
174    numThreads = number;
175  }
176  return S_OK;
177}
178