Source code
Revision control
Copy as Markdown
Other Tools
// MethodProps.cpp↩
↩
#include "StdAfx.h"↩
↩
#include "../../Common/StringToInt.h"↩
↩
#include "MethodProps.h"↩
↩
using namespace NWindows;↩
↩
bool StringToBool(const wchar_t *s, bool &res)↩
{↩
if (s[0] == 0 || (s[0] == '+' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "ON"))↩
{↩
res = true;↩
return true;↩
}↩
if ((s[0] == '-' && s[1] == 0) || StringsAreEqualNoCase_Ascii(s, "OFF"))↩
{↩
res = false;↩
return true;↩
}↩
return false;↩
}↩
↩
HRESULT PROPVARIANT_to_bool(const PROPVARIANT &prop, bool &dest)↩
{↩
switch (prop.vt)↩
{↩
case VT_EMPTY: dest = true; return S_OK;↩
case VT_BOOL: dest = (prop.boolVal != VARIANT_FALSE); return S_OK;↩
case VT_BSTR: return StringToBool(prop.bstrVal, dest) ? S_OK : E_INVALIDARG;↩
}↩
return E_INVALIDARG;↩
}↩
↩
unsigned ParseStringToUInt32(const UString &srcString, UInt32 &number)↩
{↩
const wchar_t *start = srcString;↩
const wchar_t *end;↩
number = ConvertStringToUInt32(start, &end);↩
return (unsigned)(end - start);↩
}↩
↩
static unsigned ParseStringToUInt64(const UString &srcString, UInt64 &number)↩
{↩
const wchar_t *start = srcString;↩
const wchar_t *end;↩
number = ConvertStringToUInt64(start, &end);↩
return (unsigned)(end - start);↩
}↩
↩
HRESULT ParsePropToUInt32(const UString &name, const PROPVARIANT &prop, UInt32 &resValue)↩
{↩
// =VT_UI4↩
// =VT_EMPTY↩
// {stringUInt32}=VT_EMPTY↩
↩
if (prop.vt == VT_UI4)↩
{↩
if (!name.IsEmpty())↩
return E_INVALIDARG;↩
resValue = prop.ulVal;↩
return S_OK;↩
}↩
if (prop.vt != VT_EMPTY)↩
return E_INVALIDARG;↩
if (name.IsEmpty())↩
return S_OK;↩
UInt32 v;↩
if (ParseStringToUInt32(name, v) != name.Len())↩
return E_INVALIDARG;↩
resValue = v;↩
return S_OK;↩
}↩
↩
HRESULT ParseMtProp(const UString &name, const PROPVARIANT &prop, UInt32 defaultNumThreads, UInt32 &numThreads)↩
{↩
if (name.IsEmpty())↩
{↩
switch (prop.vt)↩
{↩
case VT_UI4:↩
numThreads = prop.ulVal;↩
break;↩
default:↩
{↩
bool val;↩
RINOK(PROPVARIANT_to_bool(prop, val));↩
numThreads = (val ? defaultNumThreads : 1);↩
break;↩
}↩
}↩
return S_OK;↩
}↩
if (prop.vt != VT_EMPTY)↩
return E_INVALIDARG;↩
return ParsePropToUInt32(name, prop, numThreads);↩
}↩
↩
↩
static HRESULT StringToDictSize(const UString &s, NCOM::CPropVariant &destProp)↩
{↩
const wchar_t *end;↩
UInt32 number = ConvertStringToUInt32(s, &end);↩
unsigned numDigits = (unsigned)(end - s.Ptr());↩
if (numDigits == 0 || s.Len() > numDigits + 1)↩
return E_INVALIDARG;↩
↩
if (s.Len() == numDigits)↩
{↩
if (number >= 64)↩
return E_INVALIDARG;↩
if (number < 32)↩
destProp = (UInt32)((UInt32)1 << (unsigned)number);↩
else↩
destProp = (UInt64)((UInt64)1 << (unsigned)number);↩
return S_OK;↩
}↩
↩
unsigned numBits;↩
↩
switch (MyCharLower_Ascii(s[numDigits]))↩
{↩
case 'b': destProp = number; return S_OK;↩
case 'k': numBits = 10; break;↩
case 'm': numBits = 20; break;↩
case 'g': numBits = 30; break;↩
default: return E_INVALIDARG;↩
}↩
↩
if (number < ((UInt32)1 << (32 - numBits)))↩
destProp = (UInt32)(number << numBits);↩
else↩
destProp = (UInt64)((UInt64)number << numBits);↩
↩
return S_OK;↩
}↩
↩
↩
static HRESULT PROPVARIANT_to_DictSize(const PROPVARIANT &prop, NCOM::CPropVariant &destProp)↩
{↩
if (prop.vt == VT_UI4)↩
{↩
UInt32 v = prop.ulVal;↩
if (v >= 64)↩
return E_INVALIDARG;↩
if (v < 32)↩
destProp = (UInt32)((UInt32)1 << (unsigned)v);↩
else↩
destProp = (UInt64)((UInt64)1 << (unsigned)v);↩
return S_OK;↩
}↩
if (prop.vt == VT_BSTR)↩
{↩
UString s;↩
s = prop.bstrVal;↩
return StringToDictSize(s, destProp);↩
}↩
return E_INVALIDARG;↩
}↩
↩
↩
void CProps::AddProp32(PROPID propid, UInt32 val)↩
{↩
CProp &prop = Props.AddNew();↩
prop.IsOptional = true;↩
prop.Id = propid;↩
prop.Value = (UInt32)val;↩
}↩
↩
void CProps::AddPropBool(PROPID propid, bool val)↩
{↩
CProp &prop = Props.AddNew();↩
prop.IsOptional = true;↩
prop.Id = propid;↩
prop.Value = val;↩
}↩
↩
class CCoderProps↩
{↩
PROPID *_propIDs;↩
NCOM::CPropVariant *_props;↩
unsigned _numProps;↩
unsigned _numPropsMax;↩
public:↩
CCoderProps(unsigned numPropsMax)↩
{↩
_numPropsMax = numPropsMax;↩
_numProps = 0;↩
_propIDs = new PROPID[numPropsMax];↩
_props = new NCOM::CPropVariant[numPropsMax];↩
}↩
~CCoderProps()↩
{↩
delete []_propIDs;↩
delete []_props;↩
}↩
void AddProp(const CProp &prop);↩
HRESULT SetProps(ICompressSetCoderProperties *setCoderProperties)↩
{↩
return setCoderProperties->SetCoderProperties(_propIDs, _props, _numProps);↩
}↩
};↩
↩
void CCoderProps::AddProp(const CProp &prop)↩
{↩
if (_numProps >= _numPropsMax)↩
throw 1;↩
_propIDs[_numProps] = prop.Id;↩
_props[_numProps] = prop.Value;↩
_numProps++;↩
}↩
↩
HRESULT CProps::SetCoderProps(ICompressSetCoderProperties *scp, const UInt64 *dataSizeReduce) const↩
{↩
CCoderProps coderProps(Props.Size() + (dataSizeReduce ? 1 : 0));↩
FOR_VECTOR (i, Props)↩
coderProps.AddProp(Props[i]);↩
if (dataSizeReduce)↩
{↩
CProp prop;↩
prop.Id = NCoderPropID::kReduceSize;↩
prop.Value = *dataSizeReduce;↩
coderProps.AddProp(prop);↩
}↩
return coderProps.SetProps(scp);↩
}↩
↩
↩
int CMethodProps::FindProp(PROPID id) const↩
{↩
for (int i = Props.Size() - 1; i >= 0; i--)↩
if (Props[i].Id == id)↩
return i;↩
return -1;↩
}↩
↩
int CMethodProps::GetLevel() const↩
{↩
int i = FindProp(NCoderPropID::kLevel);↩
if (i < 0)↩
return 5;↩
if (Props[i].Value.vt != VT_UI4)↩
return 9;↩
UInt32 level = Props[i].Value.ulVal;↩
return level > 9 ? 9 : (int)level;↩
}↩
↩
struct CNameToPropID↩
{↩
VARTYPE VarType;↩
const char *Name;↩
};↩
↩
↩
// the following are related to NCoderPropID::EEnum values↩
↩
static const CNameToPropID g_NameToPropID[] =↩
{↩
{ VT_UI4, "" },↩
{ VT_UI4, "d" },↩
{ VT_UI4, "mem" },↩
{ VT_UI4, "o" },↩
{ VT_UI4, "c" },↩
{ VT_UI4, "pb" },↩
{ VT_UI4, "lc" },↩
{ VT_UI4, "lp" },↩
{ VT_UI4, "fb" },↩
{ VT_BSTR, "mf" },↩
{ VT_UI4, "mc" },↩
{ VT_UI4, "pass" },↩
{ VT_UI4, "a" },↩
{ VT_UI4, "mt" },↩
{ VT_BOOL, "eos" },↩
{ VT_UI4, "x" },↩
{ VT_UI8, "reduce" },↩
{ VT_UI8, "expect" },↩
{ VT_UI4, "b" },↩
{ VT_UI4, "check" },↩
{ VT_BSTR, "filter" },↩
{ VT_UI8, "memuse" }↩
};↩
↩
static int FindPropIdExact(const UString &name)↩
{↩
for (unsigned i = 0; i < ARRAY_SIZE(g_NameToPropID); i++)↩
if (StringsAreEqualNoCase_Ascii(name, g_NameToPropID[i].Name))↩
return i;↩
return -1;↩
}↩
↩
static bool ConvertProperty(const PROPVARIANT &srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)↩
{↩
if (varType == srcProp.vt)↩
{↩
destProp = srcProp;↩
return true;↩
}↩
↩
if (varType == VT_UI8 && srcProp.vt == VT_UI4)↩
{↩
destProp = (UInt64)srcProp.ulVal;↩
return true;↩
}↩
↩
if (varType == VT_BOOL)↩
{↩
bool res;↩
if (PROPVARIANT_to_bool(srcProp, res) != S_OK)↩
return false;↩
destProp = res;↩
return true;↩
}↩
if (srcProp.vt == VT_EMPTY)↩
{↩
destProp = srcProp;↩
return true;↩
}↩
return false;↩
}↩
↩
static void SplitParams(const UString &srcString, UStringVector &subStrings)↩
{↩
subStrings.Clear();↩
UString s;↩
unsigned len = srcString.Len();↩
if (len == 0)↩
return;↩
for (unsigned i = 0; i < len; i++)↩
{↩
wchar_t c = srcString[i];↩
if (c == L':')↩
{↩
subStrings.Add(s);↩
s.Empty();↩
}↩
else↩
s += c;↩
}↩
subStrings.Add(s);↩
}↩
↩
static void SplitParam(const UString ¶m, UString &name, UString &value)↩
{↩
int eqPos = param.Find(L'=');↩
if (eqPos >= 0)↩
{↩
name.SetFrom(param, eqPos);↩
value = param.Ptr(eqPos + 1);↩
return;↩
}↩
unsigned i;↩
for (i = 0; i < param.Len(); i++)↩
{↩
wchar_t c = param[i];↩
if (c >= L'0' && c <= L'9')↩
break;↩
}↩
name.SetFrom(param, i);↩
value = param.Ptr(i);↩
}↩
↩
static bool IsLogSizeProp(PROPID propid)↩
{↩
switch (propid)↩
{↩
case NCoderPropID::kDictionarySize:↩
case NCoderPropID::kUsedMemorySize:↩
case NCoderPropID::kBlockSize:↩
case NCoderPropID::kBlockSize2:↩
// case NCoderPropID::kReduceSize:↩
return true;↩
}↩
return false;↩
}↩
↩
HRESULT CMethodProps::SetParam(const UString &name, const UString &value)↩
{↩
int index = FindPropIdExact(name);↩
if (index < 0)↩
return E_INVALIDARG;↩
const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index];↩
CProp prop;↩
prop.Id = index;↩
↩
if (IsLogSizeProp(prop.Id))↩
{↩
RINOK(StringToDictSize(value, prop.Value));↩
}↩
else↩
{↩
NCOM::CPropVariant propValue;↩
if (nameToPropID.VarType == VT_BSTR)↩
propValue = value;↩
else if (nameToPropID.VarType == VT_BOOL)↩
{↩
bool res;↩
if (!StringToBool(value, res))↩
return E_INVALIDARG;↩
propValue = res;↩
}↩
else if (!value.IsEmpty())↩
{↩
if (nameToPropID.VarType == VT_UI4)↩
{↩
UInt32 number;↩
if (ParseStringToUInt32(value, number) == value.Len())↩
propValue = number;↩
else↩
propValue = value;↩
}↩
else if (nameToPropID.VarType == VT_UI8)↩
{↩
UInt64 number;↩
if (ParseStringToUInt64(value, number) == value.Len())↩
propValue = number;↩
else↩
propValue = value;↩
}↩
else↩
propValue = value;↩
}↩
if (!ConvertProperty(propValue, nameToPropID.VarType, prop.Value))↩
return E_INVALIDARG;↩
}↩
Props.Add(prop);↩
return S_OK;↩
}↩
↩
HRESULT CMethodProps::ParseParamsFromString(const UString &srcString)↩
{↩
UStringVector params;↩
SplitParams(srcString, params);↩
FOR_VECTOR (i, params)↩
{↩
const UString ¶m = params[i];↩
UString name, value;↩
SplitParam(param, name, value);↩
RINOK(SetParam(name, value));↩
}↩
return S_OK;↩
}↩
↩
HRESULT CMethodProps::ParseParamsFromPROPVARIANT(const UString &realName, const PROPVARIANT &value)↩
{↩
if (realName.Len() == 0)↩
{↩
// [empty]=method↩
return E_INVALIDARG;↩
}↩
if (value.vt == VT_EMPTY)↩
{↩
// {realName}=[empty]↩
UString name, valueStr;↩
SplitParam(realName, name, valueStr);↩
return SetParam(name, valueStr);↩
}↩
↩
// {realName}=value↩
int index = FindPropIdExact(realName);↩
if (index < 0)↩
return E_INVALIDARG;↩
const CNameToPropID &nameToPropID = g_NameToPropID[(unsigned)index];↩
CProp prop;↩
prop.Id = index;↩
↩
if (IsLogSizeProp(prop.Id))↩
{↩
RINOK(PROPVARIANT_to_DictSize(value, prop.Value));↩
}↩
else↩
{↩
if (!ConvertProperty(value, nameToPropID.VarType, prop.Value))↩
return E_INVALIDARG;↩
}↩
Props.Add(prop);↩
return S_OK;↩
}↩
↩
HRESULT COneMethodInfo::ParseMethodFromString(const UString &s)↩
{↩
MethodName.Empty();↩
int splitPos = s.Find(L':');↩
{↩
UString temp = s;↩
if (splitPos >= 0)↩
temp.DeleteFrom(splitPos);↩
if (!temp.IsAscii())↩
return E_INVALIDARG;↩
MethodName.SetFromWStr_if_Ascii(temp);↩
}↩
if (splitPos < 0)↩
return S_OK;↩
PropsString = s.Ptr(splitPos + 1);↩
return ParseParamsFromString(PropsString);↩
}↩
↩
HRESULT COneMethodInfo::ParseMethodFromPROPVARIANT(const UString &realName, const PROPVARIANT &value)↩
{↩
if (!realName.IsEmpty() && !StringsAreEqualNoCase_Ascii(realName, "m"))↩
return ParseParamsFromPROPVARIANT(realName, value);↩
// -m{N}=method↩
if (value.vt != VT_BSTR)↩
return E_INVALIDARG;↩
UString s;↩
s = value.bstrVal;↩
return ParseMethodFromString(s);↩
}↩