// MethodProps.h #ifndef ZIP7_INC_7Z_METHOD_PROPS_H #define ZIP7_INC_7Z_METHOD_PROPS_H #include "../../Common/MyString.h" #include "../../Common/Defs.h" #include "../../Windows/Defs.h" #include "../../Windows/PropVariant.h" #include "../ICoder.h" // UInt64 GetMemoryUsage_LZMA(UInt32 dict, bool isBt, UInt32 numThreads); inline UInt64 Calc_From_Val_Percents_Less100(UInt64 val, UInt64 percents) { if (percents == 0) return 0; if (val <= (UInt64)(Int64)-1 / percents) return val * percents / 100; return val / 100 * percents; } UInt64 Calc_From_Val_Percents(UInt64 val, UInt64 percents); bool StringToBool(const wchar_t *s, bool &res); HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest); unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number); /* if (name.IsEmpty() && prop.vt == VT_EMPTY), it doesn't change (resValue) and returns S_OK. So you must set (resValue) for default value before calling */ HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue); /* input: (numThreads = the_number_of_processors) */ HRESULT ParseMtProp2(const UString &name, const PROPVARIANT &prop, UInt32 &numThreads, bool &force); inline HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 numCPUs, UInt32 &numThreads) { bool forced = false; numThreads = numCPUs; return ParseMtProp2(name, prop, numThreads, forced); } struct CProp { PROPID Id; bool IsOptional; NWindows::NCOM::CPropVariant Value; CProp(): IsOptional(false) {} }; struct CProps { CObjectVector Props; void Clear() { Props.Clear(); } bool AreThereNonOptionalProps() const { FOR_VECTOR (i, Props) if (!Props[i].IsOptional) return true; return false; } void AddProp32(PROPID propid, UInt32 val); void AddPropBool(PROPID propid, bool val); void AddProp_Ascii(PROPID propid, const char *s) { CProp &prop = Props.AddNew(); prop.IsOptional = true; prop.Id = propid; prop.Value = s; } HRESULT SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce = NULL) const; HRESULT SetCoderProps_DSReduce_Aff(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce, const UInt64 *affinity) const; }; class CMethodProps: public CProps { HRESULT SetParam(const UString &name, const UString &value); public: unsigned GetLevel() const; int Get_NumThreads() const { const int i = FindProp(NCoderPropID::kNumThreads); if (i >= 0) { const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_UI4) return (int)val.ulVal; } return -1; } bool Get_DicSize(UInt64 &res) const { res = 0; const int i = FindProp(NCoderPropID::kDictionarySize); if (i >= 0) { const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_UI4) { res = val.ulVal; return true; } if (val.vt == VT_UI8) { res = val.uhVal.QuadPart; return true; } } return false; } int FindProp(PROPID id) const; UInt32 Get_Lzma_Algo() const { int i = FindProp(NCoderPropID::kAlgorithm); if (i >= 0) { const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_UI4) return val.ulVal; } return GetLevel() >= 5 ? 1 : 0; } UInt64 Get_Lzma_DicSize() const { UInt64 v; if (Get_DicSize(v)) return v; const unsigned level = GetLevel(); const UInt32 dictSize = ( level <= 3 ? ((UInt32)1 << (level * 2 + 16)) : ( level <= 6 ? ((UInt32)1 << (level + 19)) : ( level <= 7 ? ((UInt32)1 << 25) : ((UInt32)1 << 26) ))); return dictSize; } bool Get_Lzma_MatchFinder_IsBt() const { const int i = FindProp(NCoderPropID::kMatchFinder); if (i >= 0) { const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_BSTR) return ((val.bstrVal[0] | 0x20) != 'h'); // check for "hc" } return GetLevel() >= 5; } bool Get_Lzma_Eos() const { const int i = FindProp(NCoderPropID::kEndMarker); if (i >= 0) { const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_BOOL) return VARIANT_BOOLToBool(val.boolVal); } return false; } bool Are_Lzma_Model_Props_Defined() const { if (FindProp(NCoderPropID::kPosStateBits) >= 0) return true; if (FindProp(NCoderPropID::kLitContextBits) >= 0) return true; if (FindProp(NCoderPropID::kLitPosBits) >= 0) return true; return false; } UInt32 Get_Lzma_NumThreads() const { if (Get_Lzma_Algo() == 0) return 1; int numThreads = Get_NumThreads(); if (numThreads >= 0) return numThreads < 2 ? 1 : 2; return 2; } UInt64 Get_Lzma_MemUsage(bool addSlidingWindowSize) const; /* returns -1, if numThreads is unknown */ int Get_Xz_NumThreads(UInt32 &lzmaThreads) const { lzmaThreads = 1; int numThreads = Get_NumThreads(); if (numThreads >= 0 && numThreads <= 1) return 1; if (Get_Lzma_Algo() != 0) lzmaThreads = 2; return numThreads; } UInt64 GetProp_BlockSize(PROPID id) const { const int i = FindProp(id); if (i >= 0) { const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_UI4) { return val.ulVal; } if (val.vt == VT_UI8) { return val.uhVal.QuadPart; } } return 0; } UInt64 Get_Xz_BlockSize() const { { UInt64 blockSize1 = GetProp_BlockSize(NCoderPropID::kBlockSize); UInt64 blockSize2 = GetProp_BlockSize(NCoderPropID::kBlockSize2); UInt64 minSize = MyMin(blockSize1, blockSize2); if (minSize != 0) return minSize; UInt64 maxSize = MyMax(blockSize1, blockSize2); if (maxSize != 0) return maxSize; } const UInt32 kMinSize = (UInt32)1 << 20; const UInt32 kMaxSize = (UInt32)1 << 28; const UInt64 dictSize = Get_Lzma_DicSize(); /* lzma2 code uses fake 4 GiB to calculate ChunkSize. So we do same */ UInt64 blockSize = (UInt64)dictSize << 2; if (blockSize < kMinSize) blockSize = kMinSize; if (blockSize > kMaxSize) blockSize = kMaxSize; if (blockSize < dictSize) blockSize = dictSize; blockSize += (kMinSize - 1); blockSize &= ~(UInt64)(kMinSize - 1); return blockSize; } UInt32 Get_BZip2_NumThreads(bool &fixedNumber) const { fixedNumber = false; int numThreads = Get_NumThreads(); if (numThreads >= 0) { fixedNumber = true; if (numThreads < 1) return 1; const unsigned kNumBZip2ThreadsMax = 64; if ((unsigned)numThreads > kNumBZip2ThreadsMax) return kNumBZip2ThreadsMax; return (unsigned)numThreads; } return 1; } UInt32 Get_BZip2_BlockSize() const { const int i = FindProp(NCoderPropID::kDictionarySize); if (i >= 0) { const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_UI4) { UInt32 blockSize = val.ulVal; const UInt32 kDicSizeMin = 100000; const UInt32 kDicSizeMax = 900000; if (blockSize < kDicSizeMin) blockSize = kDicSizeMin; if (blockSize > kDicSizeMax) blockSize = kDicSizeMax; return blockSize; } } const unsigned level = GetLevel(); return 100000 * (level >= 5 ? 9 : (level >= 1 ? level * 2 - 1: 1)); } UInt64 Get_Ppmd_MemSize() const { const int i = FindProp(NCoderPropID::kUsedMemorySize); if (i >= 0) { const NWindows::NCOM::CPropVariant &val = Props[(unsigned)i].Value; if (val.vt == VT_UI4) return val.ulVal; if (val.vt == VT_UI8) return val.uhVal.QuadPart; } const unsigned level = GetLevel(); const UInt32 mem = (UInt32)1 << (level + 19); return mem; } void AddProp_Level(UInt32 level) { AddProp32(NCoderPropID::kLevel, level); } void AddProp_NumThreads(UInt32 numThreads) { AddProp32(NCoderPropID::kNumThreads, numThreads); } void AddProp_EndMarker_if_NotFound(bool eos) { if (FindProp(NCoderPropID::kEndMarker) < 0) AddPropBool(NCoderPropID::kEndMarker, eos); } void AddProp_BlockSize2(UInt64 blockSize2) { if (FindProp(NCoderPropID::kBlockSize2) < 0) { CProp &prop = Props.AddNew(); prop.IsOptional = true; prop.Id = NCoderPropID::kBlockSize2; prop.Value = blockSize2; } } HRESULT ParseParamsFromString(const UString &srcString); HRESULT ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value); }; class COneMethodInfo: public CMethodProps { public: AString MethodName; UString PropsString; void Clear() { CMethodProps::Clear(); MethodName.Empty(); PropsString.Empty(); } bool IsEmpty() const { return MethodName.IsEmpty() && Props.IsEmpty(); } HRESULT ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value); HRESULT ParseMethodFromString(const UString &s); }; #endif