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
11 namespace NArchive {
12
ParseSizeString(const wchar_t * s,const PROPVARIANT & prop,UInt64 percentsBase,UInt64 & res)13 bool 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
SetCommonProperty(const UString & name,const PROPVARIANT & value,HRESULT & hres)85 bool 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
SetMethodProp32(CMethodProps & m,PROPID propID,UInt32 value)117 static void SetMethodProp32(CMethodProps &m, PROPID propID, UInt32 value)
118 {
119 if (m.FindProp(propID) < 0)
120 m.AddProp32(propID, value);
121 }
122
SetGlobalLevelTo(COneMethodInfo & oneMethodInfo) const123 void 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
SetMethodProp32_Replace(CMethodProps & m,PROPID propID,UInt32 value)132 static 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
SetMethodThreadsTo_IfNotFinded(CMethodProps & oneMethodInfo,UInt32 numThreads)144 void CMultiMethodProps::SetMethodThreadsTo_IfNotFinded(CMethodProps &oneMethodInfo, UInt32 numThreads)
145 {
146 SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
147 }
148
SetMethodThreadsTo_Replace(CMethodProps & oneMethodInfo,UInt32 numThreads)149 void CMultiMethodProps::SetMethodThreadsTo_Replace(CMethodProps &oneMethodInfo, UInt32 numThreads)
150 {
151 SetMethodProp32_Replace(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
152 }
153
154 #endif // Z7_ST
155
156
InitMulti()157 void CMultiMethodProps::InitMulti()
158 {
159 _level = (UInt32)(Int32)-1;
160 _analysisLevel = -1;
161 _crcSize = 4;
162 _autoFilter = true;
163 }
164
Init()165 void CMultiMethodProps::Init()
166 {
167 InitCommon();
168 InitMulti();
169 _methods.Clear();
170 _filterMethod.Clear();
171 }
172
173
SetProperty(const wchar_t * nameSpec,const PROPVARIANT & value)174 HRESULT 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
Init()235 void CSingleMethodProps::Init()
236 {
237 InitCommon();
238 InitSingle();
239 Clear();
240 }
241
242
SetProperty(const wchar_t * name2,const PROPVARIANT & value)243 HRESULT 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
SetProperties(const wchar_t * const * names,const PROPVARIANT * values,UInt32 numProps)272 HRESULT 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
PROPVARIANT_to_BoolPair(const PROPVARIANT & prop,CBoolPair & dest)287 static 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
Parse(const UString & name,const PROPVARIANT & prop,bool & processed)294 HRESULT 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