1// HandlerOut.cpp
2
3#include "StdAfx.h"
4
5#include "../../../Common/StringToInt.h"
6
7#include "../Common/ParseProperties.h"
8
9#include "HandlerOut.h"
10
11namespace NArchive {
12
13bool ParseSizeString(const wchar_t *s, const PROPVARIANT &prop, UInt64 percentsBase, UInt64 &res)
14{
15  if (*s == 0)
16  {
17    switch (prop.vt)
18    {
19      case VT_UI4: res = prop.ulVal; return true;
20      case VT_UI8: res = prop.uhVal.QuadPart; return true;
21      case VT_BSTR:
22        s = prop.bstrVal;
23        break;
24      default: return false;
25    }
26  }
27  else if (prop.vt != VT_EMPTY)
28    return false;
29
30  bool percentMode = false;
31  {
32    const wchar_t c = *s;
33    if (MyCharLower_Ascii(c) == 'p')
34    {
35      percentMode = true;
36      s++;
37    }
38  }
39
40  const wchar_t *end;
41  const UInt64 v = ConvertStringToUInt64(s, &end);
42  if (s == end)
43    return false;
44  const wchar_t c = *end;
45
46  if (percentMode)
47  {
48    if (c != 0)
49      return false;
50    res = Calc_From_Val_Percents(percentsBase, v);
51    return true;
52  }
53
54  if (c == 0)
55  {
56    res = v;
57    return true;
58  }
59  if (end[1] != 0)
60    return false;
61
62  if (c == '%')
63  {
64    res = Calc_From_Val_Percents(percentsBase, v);
65    return true;
66  }
67
68  unsigned numBits;
69  switch (MyCharLower_Ascii(c))
70  {
71    case 'b': numBits =  0; break;
72    case 'k': numBits = 10; break;
73    case 'm': numBits = 20; break;
74    case 'g': numBits = 30; break;
75    case 't': numBits = 40; break;
76    default: return false;
77  }
78  const UInt64 val2 = v << numBits;
79  if ((val2 >> numBits) != v)
80    return false;
81  res = val2;
82  return true;
83}
84
85bool CCommonMethodProps::SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres)
86{
87  hres = S_OK;
88
89  if (name.IsPrefixedBy_Ascii_NoCase("mt"))
90  {
91    #ifndef Z7_ST
92    _numThreads = _numProcessors;
93    _numThreads_WasForced = false;
94    hres = ParseMtProp2(name.Ptr(2), value, _numThreads, _numThreads_WasForced);
95    // "mt" means "_numThreads_WasForced = false" here
96    #endif
97    return true;
98  }
99
100  if (name.IsPrefixedBy_Ascii_NoCase("memuse"))
101  {
102    UInt64 v;
103    if (!ParseSizeString(name.Ptr(6), value, _memAvail, v))
104      hres = E_INVALIDARG;
105    _memUsage_Decompress = v;
106    _memUsage_Compress = v;
107    _memUsage_WasSet = true;
108    return true;
109  }
110
111  return false;
112}
113
114
115#ifndef Z7_EXTRACT_ONLY
116
117static void SetMethodProp32(CMethodProps &m, PROPID propID, UInt32 value)
118{
119  if (m.FindProp(propID) < 0)
120    m.AddProp32(propID, value);
121}
122
123void CMultiMethodProps::SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const
124{
125  UInt32 level = _level;
126  if (level != (UInt32)(Int32)-1)
127    SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level);
128}
129
130#ifndef Z7_ST
131
132static void SetMethodProp32_Replace(CMethodProps &m, PROPID propID, UInt32 value)
133{
134  const int i = m.FindProp(propID);
135  if (i >= 0)
136  {
137    NWindows::NCOM::CPropVariant &val = m.Props[(unsigned)i].Value;
138    val = (UInt32)value;
139    return;
140  }
141  m.AddProp32(propID, value);
142}
143
144void CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(CMethodProps &oneMethodInfo, UInt32 numThreads)
145{
146  SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
147}
148
149void CMultiMethodProps::SetMethodThreadsTo_Replace(CMethodProps &oneMethodInfo, UInt32 numThreads)
150{
151  SetMethodProp32_Replace(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
152}
153
154#endif // Z7_ST
155
156
157void CMultiMethodProps::InitMulti()
158{
159  _level = (UInt32)(Int32)-1;
160  _analysisLevel = -1;
161  _crcSize = 4;
162  _autoFilter = true;
163}
164
165void CMultiMethodProps::Init()
166{
167  InitCommon();
168  InitMulti();
169  _methods.Clear();
170  _filterMethod.Clear();
171}
172
173
174HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
175{
176  UString name = nameSpec;
177  name.MakeLower_Ascii();
178  if (name.IsEmpty())
179    return E_INVALIDARG;
180
181  if (name[0] == 'x')
182  {
183    name.Delete(0);
184    _level = 9;
185    return ParsePropToUInt32(name, value, _level);
186  }
187
188  if (name.IsPrefixedBy_Ascii_NoCase("yx"))
189  {
190    name.Delete(0, 2);
191    UInt32 v = 9;
192    RINOK(ParsePropToUInt32(name, value, v))
193    _analysisLevel = (int)v;
194    return S_OK;
195  }
196
197  if (name.IsPrefixedBy_Ascii_NoCase("crc"))
198  {
199    name.Delete(0, 3);
200    _crcSize = 4;
201    return ParsePropToUInt32(name, value, _crcSize);
202  }
203
204  {
205    HRESULT hres;
206    if (SetCommonProperty(name, value, hres))
207      return hres;
208  }
209
210  UInt32 number;
211  const unsigned index = ParseStringToUInt32(name, number);
212  const UString realName = name.Ptr(index);
213  if (index == 0)
214  {
215    if (name.IsEqualTo("f"))
216    {
217      const HRESULT res = PROPVARIANT_to_bool(value, _autoFilter);
218      if (res == S_OK)
219        return res;
220      if (value.vt != VT_BSTR)
221        return E_INVALIDARG;
222      return _filterMethod.ParseMethodFromPROPVARIANT(UString(), value);
223    }
224    number = 0;
225  }
226  if (number > 64)
227    return E_INVALIDARG;
228  for (unsigned j = _methods.Size(); j <= number; j++)
229    _methods.AddNew();
230  return _methods[number].ParseMethodFromPROPVARIANT(realName, value);
231}
232
233
234
235void CSingleMethodProps::Init()
236{
237  InitCommon();
238  InitSingle();
239  Clear();
240}
241
242
243HRESULT CSingleMethodProps::SetProperty(const wchar_t *name2, const PROPVARIANT &value)
244{
245  // processed = false;
246  UString name = name2;
247  name.MakeLower_Ascii();
248  if (name.IsEmpty())
249    return E_INVALIDARG;
250  if (name.IsPrefixedBy_Ascii_NoCase("x"))
251  {
252    UInt32 a = 9;
253    RINOK(ParsePropToUInt32(name.Ptr(1), value, a))
254    _level = a;
255    AddProp_Level(a);
256    // processed = true;
257    return S_OK;
258  }
259  {
260    HRESULT hres;
261    if (SetCommonProperty(name, value, hres))
262    {
263      // processed = true;
264      return S_OK;
265    }
266  }
267  RINOK(ParseMethodFromPROPVARIANT(name, value))
268  return S_OK;
269}
270
271
272HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
273{
274  Init();
275
276  for (UInt32 i = 0; i < numProps; i++)
277  {
278    RINOK(SetProperty(names[i], values[i]))
279  }
280
281  return S_OK;
282}
283
284#endif
285
286
287static HRESULT PROPVARIANT_to_BoolPair(const PROPVARIANT &prop, CBoolPair &dest)
288{
289  RINOK(PROPVARIANT_to_bool(prop, dest.Val))
290  dest.Def = true;
291  return S_OK;
292}
293
294HRESULT CHandlerTimeOptions::Parse(const UString &name, const PROPVARIANT &prop, bool &processed)
295{
296  processed = true;
297  if (name.IsEqualTo_Ascii_NoCase("tm")) { return PROPVARIANT_to_BoolPair(prop, Write_MTime); }
298  if (name.IsEqualTo_Ascii_NoCase("ta")) { return PROPVARIANT_to_BoolPair(prop, Write_ATime); }
299  if (name.IsEqualTo_Ascii_NoCase("tc")) { return PROPVARIANT_to_BoolPair(prop, Write_CTime); }
300  if (name.IsPrefixedBy_Ascii_NoCase("tp"))
301  {
302    UInt32 v = 0;
303    RINOK(ParsePropToUInt32(name.Ptr(2), prop, v))
304    Prec = v;
305    return S_OK;
306  }
307  processed = false;
308  return S_OK;
309}
310
311}
312