1// MethodProps.h 2 3#ifndef ZIP7_INC_7Z_METHOD_PROPS_H 4#define ZIP7_INC_7Z_METHOD_PROPS_H 5 6#include "../../Common/MyString.h" 7#include "../../Common/Defs.h" 8 9#include "../../Windows/Defs.h" 10 11#include "../../Windows/PropVariant.h" 12 13#include "../ICoder.h" 14 15// UInt64 GetMemoryUsage_LZMA(UInt32 dict, bool isBt, UInt32 numThreads); 16 17inline UInt64 Calc_From_Val_Percents_Less100(UInt64 val, UInt64 percents) 18{ 19 if (percents == 0) 20 return 0; 21 if (val <= (UInt64)(Int64)-1 / percents) 22 return val * percents / 100; 23 return val / 100 * percents; 24} 25 26UInt64 Calc_From_Val_Percents(UInt64 val, UInt64 percents); 27 28bool StringToBool(const wchar_t *s, bool &res); 29HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest); 30unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number); 31 32/* 33if (name.IsEmpty() && prop.vt == VT_EMPTY), it doesn't change (resValue) and returns S_OK. 34 So you must set (resValue) for default value before calling */ 35HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); 36 37/* input: (numThreads = the_number_of_processors) */ 38HRESULT ParseMtProp2(const UString &name, const PROPVARIANT &prop, UInt32 &numThreads, bool &force); 39 40inline HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 numCPUs, UInt32 &numThreads) 41{ 42 bool forced = false; 43 numThreads = numCPUs; 44 return ParseMtProp2(name, prop, numThreads, forced); 45} 46 47 48struct CProp 49{ 50 PROPID Id; 51 bool IsOptional; 52 NWindows::NCOM::CPropVariant Value; 53 CProp(): IsOptional(false) {} 54}; 55 56struct CProps 57{ 58 CObjectVector<CProp> Props; 59 60 void Clear() { Props.Clear(); } 61 62 bool AreThereNonOptionalProps() const 63 { 64 FOR_VECTOR (i, Props) 65 if (!Props[i].IsOptional) 66 return true; 67 return false; 68 } 69 70 void AddProp32(PROPID propid, UInt32 val); 71 72 void AddPropBool(PROPID propid, bool val); 73 74 void AddProp_Ascii(PROPID propid, const char *s) 75 { 76 CProp &prop = Props.AddNew(); 77 prop.IsOptional = true; 78 prop.Id = propid; 79 prop.Value = s; 80 } 81 82 HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce = NULL) const; 83 HRESULT SetCoderProps_DSReduce_Aff(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce, const UInt64 *affinity) const; 84}; 85 86class CMethodProps: public CProps 87{ 88 HRESULT SetParam(const UString &name, const UString &value); 89public: 90 unsigned GetLevel() const; 91 int Get_NumThreads() const 92 { 93 const int i = FindProp(NCoderPropID::kNumThreads); 94 if (i >= 0) 95 { 96 const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; 97 if (val.vt == VT_UI4) 98 return (int)val.ulVal; 99 } 100 return -1; 101 } 102 103 bool Get_DicSize(UInt64 &res) const 104 { 105 res = 0; 106 const int i = FindProp(NCoderPropID::kDictionarySize); 107 if (i >= 0) 108 { 109 const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; 110 if (val.vt == VT_UI4) 111 { 112 res = val.ulVal; 113 return true; 114 } 115 if (val.vt == VT_UI8) 116 { 117 res = val.uhVal.QuadPart; 118 return true; 119 } 120 } 121 return false; 122 } 123 124 int FindProp(PROPID id) const; 125 126 UInt32 Get_Lzma_Algo() const 127 { 128 int i = FindProp(NCoderPropID::kAlgorithm); 129 if (i >= 0) 130 { 131 const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; 132 if (val.vt == VT_UI4) 133 return val.ulVal; 134 } 135 return GetLevel() >= 5 ? 1 : 0; 136 } 137 138 UInt64 Get_Lzma_DicSize() const 139 { 140 UInt64 v; 141 if (Get_DicSize(v)) 142 return v; 143 const unsigned level = GetLevel(); 144 const UInt32 dictSize = 145 ( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) : 146 ( level <= 6 ? ((UInt32)1 << (level + 19)) : 147 ( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26) 148 ))); 149 return dictSize; 150 } 151 152 bool Get_Lzma_MatchFinder_IsBt() const 153 { 154 const int i = FindProp(NCoderPropID::kMatchFinder); 155 if (i >= 0) 156 { 157 const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; 158 if (val.vt == VT_BSTR) 159 return ((val.bstrVal[0] | 0x20) != 'h'); // check for "hc" 160 } 161 return GetLevel() >= 5; 162 } 163 164 bool Get_Lzma_Eos() const 165 { 166 const int i = FindProp(NCoderPropID::kEndMarker); 167 if (i >= 0) 168 { 169 const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; 170 if (val.vt == VT_BOOL) 171 return VARIANT_BOOLToBool(val.boolVal); 172 } 173 return false; 174 } 175 176 bool Are_Lzma_Model_Props_Defined() const 177 { 178 if (FindProp(NCoderPropID::kPosStateBits) >= 0) return true; 179 if (FindProp(NCoderPropID::kLitContextBits) >= 0) return true; 180 if (FindProp(NCoderPropID::kLitPosBits) >= 0) return true; 181 return false; 182 } 183 184 UInt32 Get_Lzma_NumThreads() const 185 { 186 if (Get_Lzma_Algo() == 0) 187 return 1; 188 int numThreads = Get_NumThreads(); 189 if (numThreads >= 0) 190 return numThreads < 2 ? 1 : 2; 191 return 2; 192 } 193 194 UInt64 Get_Lzma_MemUsage(bool addSlidingWindowSize) const; 195 196 /* returns -1, if numThreads is unknown */ 197 int Get_Xz_NumThreads(UInt32 &lzmaThreads) const 198 { 199 lzmaThreads = 1; 200 int numThreads = Get_NumThreads(); 201 if (numThreads >= 0 && numThreads <= 1) 202 return 1; 203 if (Get_Lzma_Algo() != 0) 204 lzmaThreads = 2; 205 return numThreads; 206 } 207 208 UInt64 GetProp_BlockSize(PROPID id) const 209 { 210 const int i = FindProp(id); 211 if (i >= 0) 212 { 213 const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; 214 if (val.vt == VT_UI4) { return val.ulVal; } 215 if (val.vt == VT_UI8) { return val.uhVal.QuadPart; } 216 } 217 return 0; 218 } 219 220 UInt64 Get_Xz_BlockSize() const 221 { 222 { 223 UInt64 blockSize1 = GetProp_BlockSize(NCoderPropID::kBlockSize); 224 UInt64 blockSize2 = GetProp_BlockSize(NCoderPropID::kBlockSize2); 225 UInt64 minSize = MyMin(blockSize1, blockSize2); 226 if (minSize != 0) 227 return minSize; 228 UInt64 maxSize = MyMax(blockSize1, blockSize2); 229 if (maxSize != 0) 230 return maxSize; 231 } 232 const UInt32 kMinSize = (UInt32)1 << 20; 233 const UInt32 kMaxSize = (UInt32)1 << 28; 234 const UInt64 dictSize = Get_Lzma_DicSize(); 235 /* lzma2 code uses fake 4 GiB to calculate ChunkSize. So we do same */ 236 UInt64 blockSize = (UInt64)dictSize << 2; 237 if (blockSize < kMinSize) blockSize = kMinSize; 238 if (blockSize > kMaxSize) blockSize = kMaxSize; 239 if (blockSize < dictSize) blockSize = dictSize; 240 blockSize += (kMinSize - 1); 241 blockSize &= ~(UInt64)(kMinSize - 1); 242 return blockSize; 243 } 244 245 246 UInt32 Get_BZip2_NumThreads(bool &fixedNumber) const 247 { 248 fixedNumber = false; 249 int numThreads = Get_NumThreads(); 250 if (numThreads >= 0) 251 { 252 fixedNumber = true; 253 if (numThreads < 1) return 1; 254 const unsigned kNumBZip2ThreadsMax = 64; 255 if ((unsigned)numThreads > kNumBZip2ThreadsMax) return kNumBZip2ThreadsMax; 256 return (unsigned)numThreads; 257 } 258 return 1; 259 } 260 261 UInt32 Get_BZip2_BlockSize() const 262 { 263 const int i = FindProp(NCoderPropID::kDictionarySize); 264 if (i >= 0) 265 { 266 const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; 267 if (val.vt == VT_UI4) 268 { 269 UInt32 blockSize = val.ulVal; 270 const UInt32 kDicSizeMin = 100000; 271 const UInt32 kDicSizeMax = 900000; 272 if (blockSize < kDicSizeMin) blockSize = kDicSizeMin; 273 if (blockSize > kDicSizeMax) blockSize = kDicSizeMax; 274 return blockSize; 275 } 276 } 277 const unsigned level = GetLevel(); 278 return 100000 * (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1)); 279 } 280 281 UInt64 Get_Ppmd_MemSize() const 282 { 283 const int i = FindProp(NCoderPropID::kUsedMemorySize); 284 if (i >= 0) 285 { 286 const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; 287 if (val.vt == VT_UI4) 288 return val.ulVal; 289 if (val.vt == VT_UI8) 290 return val.uhVal.QuadPart; 291 } 292 const unsigned level = GetLevel(); 293 const UInt32 mem = (UInt32)1 << (level + 19); 294 return mem; 295 } 296 297 void AddProp_Level(UInt32 level) 298 { 299 AddProp32(NCoderPropID::kLevel, level); 300 } 301 302 void AddProp_NumThreads(UInt32 numThreads) 303 { 304 AddProp32(NCoderPropID::kNumThreads, numThreads); 305 } 306 307 void AddProp_EndMarker_if_NotFound(bool eos) 308 { 309 if (FindProp(NCoderPropID::kEndMarker) < 0) 310 AddPropBool(NCoderPropID::kEndMarker, eos); 311 } 312 313 void AddProp_BlockSize2(UInt64 blockSize2) 314 { 315 if (FindProp(NCoderPropID::kBlockSize2) < 0) 316 { 317 CProp &prop = Props.AddNew(); 318 prop.IsOptional = true; 319 prop.Id = NCoderPropID::kBlockSize2; 320 prop.Value = blockSize2; 321 } 322 } 323 324 HRESULT ParseParamsFromString(const UString &srcString); 325 HRESULT ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value); 326}; 327 328class COneMethodInfo: public CMethodProps 329{ 330public: 331 AString MethodName; 332 UString PropsString; 333 334 void Clear() 335 { 336 CMethodProps::Clear(); 337 MethodName.Empty(); 338 PropsString.Empty(); 339 } 340 bool IsEmpty() const { return MethodName.IsEmpty() && Props.IsEmpty(); } 341 HRESULT ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value); 342 HRESULT ParseMethodFromString(const UString &s); 343}; 344 345#endif 346