diff options
Diffstat (limited to 'other-licenses/7zstub/src/CPP/7zip/Common/MethodProps.cpp')
-rw-r--r-- | other-licenses/7zstub/src/CPP/7zip/Common/MethodProps.cpp | 509 |
1 files changed, 509 insertions, 0 deletions
diff --git a/other-licenses/7zstub/src/CPP/7zip/Common/MethodProps.cpp b/other-licenses/7zstub/src/CPP/7zip/Common/MethodProps.cpp new file mode 100644 index 000000000..2134462c7 --- /dev/null +++ b/other-licenses/7zstub/src/CPP/7zip/Common/MethodProps.cpp @@ -0,0 +1,509 @@ +// 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);
+}
|