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 const wchar_t *end;
31 UInt64 v = ConvertStringToUInt64(s, &end);
32 if (s == end)
33 return false;
34 wchar_t c = *end;
35 if (c == 0)
36 {
37 res = v;
38 return true;
39 }
40 if (end[1] != 0)
41 return false;
42
43 if (c == '%')
44 {
45 res = percentsBase / 100 * v;
46 return true;
47 }
48
49 unsigned numBits;
50 switch (MyCharLower_Ascii(c))
51 {
52 case 'b': numBits = 0; break;
53 case 'k': numBits = 10; break;
54 case 'm': numBits = 20; break;
55 case 'g': numBits = 30; break;
56 case 't': numBits = 40; break;
57 default: return false;
58 }
59 UInt64 val2 = v << numBits;
60 if ((val2 >> numBits) != v)
61 return false;
62 res = val2;
63 return true;
64 }
65
SetCommonProperty(const UString & name,const PROPVARIANT & value,HRESULT & hres)66 bool CCommonMethodProps::SetCommonProperty(const UString &name, const PROPVARIANT &value, HRESULT &hres)
67 {
68 hres = S_OK;
69
70 if (name.IsPrefixedBy_Ascii_NoCase("mt"))
71 {
72 #ifndef _7ZIP_ST
73 hres = ParseMtProp(name.Ptr(2), value, _numProcessors, _numThreads);
74 #endif
75 return true;
76 }
77
78 if (name.IsPrefixedBy_Ascii_NoCase("memuse"))
79 {
80 if (!ParseSizeString(name.Ptr(6), value, _memAvail, _memUsage))
81 hres = E_INVALIDARG;
82 return true;
83 }
84
85 return false;
86 }
87
88
89 #ifndef EXTRACT_ONLY
90
SetMethodProp32(COneMethodInfo & m,PROPID propID,UInt32 value)91 static void SetMethodProp32(COneMethodInfo &m, PROPID propID, UInt32 value)
92 {
93 if (m.FindProp(propID) < 0)
94 m.AddProp32(propID, value);
95 }
96
SetGlobalLevelTo(COneMethodInfo & oneMethodInfo) const97 void CMultiMethodProps::SetGlobalLevelTo(COneMethodInfo &oneMethodInfo) const
98 {
99 UInt32 level = _level;
100 if (level != (UInt32)(Int32)-1)
101 SetMethodProp32(oneMethodInfo, NCoderPropID::kLevel, (UInt32)level);
102 }
103
104 #ifndef _7ZIP_ST
SetMethodThreadsTo(COneMethodInfo & oneMethodInfo,UInt32 numThreads)105 void CMultiMethodProps::SetMethodThreadsTo(COneMethodInfo &oneMethodInfo, UInt32 numThreads)
106 {
107 SetMethodProp32(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
108 }
109 #endif
110
InitMulti()111 void CMultiMethodProps::InitMulti()
112 {
113 _level = (UInt32)(Int32)-1;
114 _analysisLevel = -1;
115 _crcSize = 4;
116 _autoFilter = true;
117 }
118
Init()119 void CMultiMethodProps::Init()
120 {
121 InitCommon();
122 InitMulti();
123 _methods.Clear();
124 _filterMethod.Clear();
125 }
126
127
SetProperty(const wchar_t * nameSpec,const PROPVARIANT & value)128 HRESULT CMultiMethodProps::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
129 {
130 UString name = nameSpec;
131 name.MakeLower_Ascii();
132 if (name.IsEmpty())
133 return E_INVALIDARG;
134
135 if (name[0] == 'x')
136 {
137 name.Delete(0);
138 _level = 9;
139 return ParsePropToUInt32(name, value, _level);
140 }
141
142 if (name.IsPrefixedBy_Ascii_NoCase("yx"))
143 {
144 name.Delete(0, 2);
145 UInt32 v = 9;
146 RINOK(ParsePropToUInt32(name, value, v));
147 _analysisLevel = (int)v;
148 return S_OK;
149 }
150
151 if (name.IsPrefixedBy_Ascii_NoCase("crc"))
152 {
153 name.Delete(0, 3);
154 _crcSize = 4;
155 return ParsePropToUInt32(name, value, _crcSize);
156 }
157
158 {
159 HRESULT hres;
160 if (SetCommonProperty(name, value, hres))
161 return hres;
162 }
163
164 UInt32 number;
165 unsigned index = ParseStringToUInt32(name, number);
166 UString realName = name.Ptr(index);
167 if (index == 0)
168 {
169 if (name.IsEqualTo("f"))
170 {
171 HRESULT res = PROPVARIANT_to_bool(value, _autoFilter);
172 if (res == S_OK)
173 return res;
174 if (value.vt != VT_BSTR)
175 return E_INVALIDARG;
176 return _filterMethod.ParseMethodFromPROPVARIANT(UString(), value);
177 }
178 number = 0;
179 }
180 if (number > 64)
181 return E_FAIL;
182 for (int j = _methods.Size(); j <= (int)number; j++)
183 _methods.Add(COneMethodInfo());
184 return _methods[number].ParseMethodFromPROPVARIANT(realName, value);
185 }
186
187
188
Init()189 void CSingleMethodProps::Init()
190 {
191 InitCommon();
192 InitSingle();
193 Clear();
194 }
195
196
SetProperties(const wchar_t * const * names,const PROPVARIANT * values,UInt32 numProps)197 HRESULT CSingleMethodProps::SetProperties(const wchar_t * const *names, const PROPVARIANT *values, UInt32 numProps)
198 {
199 Init();
200
201 for (UInt32 i = 0; i < numProps; i++)
202 {
203 UString name = names[i];
204 name.MakeLower_Ascii();
205 if (name.IsEmpty())
206 return E_INVALIDARG;
207 const PROPVARIANT &value = values[i];
208 if (name[0] == L'x')
209 {
210 UInt32 a = 9;
211 RINOK(ParsePropToUInt32(name.Ptr(1), value, a));
212 _level = a;
213 AddProp_Level(a);
214 continue;
215 }
216 {
217 HRESULT hres;
218 if (SetCommonProperty(name, value, hres))
219 {
220 RINOK(hres)
221 continue;
222 }
223 }
224 RINOK(ParseMethodFromPROPVARIANT(names[i], value));
225 }
226
227 return S_OK;
228 }
229
230 #endif
231
232 }
233