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