misc/libphysfs/lzma/CPP/7zip/Archive/Common/HandlerOut.cpp
branchui-scaling
changeset 15283 c4fd2813b127
parent 13390 0135e64c6c66
parent 15279 7ab5cf405686
child 15663 d92eeb468dad
equal deleted inserted replaced
13390:0135e64c6c66 15283:c4fd2813b127
     1 // HandlerOutCommon.cpp
       
     2 
       
     3 #include "StdAfx.h"
       
     4 
       
     5 #include "HandlerOut.h"
       
     6 #include "../../../Windows/PropVariant.h"
       
     7 #include "../../../Common/StringToInt.h"
       
     8 #include "../../ICoder.h"
       
     9 #include "../Common/ParseProperties.h"
       
    10 
       
    11 #ifdef COMPRESS_MT
       
    12 #include "../../../Windows/System.h"
       
    13 #endif
       
    14 
       
    15 using namespace NWindows;
       
    16 
       
    17 namespace NArchive {
       
    18 
       
    19 static const wchar_t *kCopyMethod = L"Copy";
       
    20 static const wchar_t *kLZMAMethodName = L"LZMA";
       
    21 static const wchar_t *kLZMA2MethodName = L"LZMA2";
       
    22 static const wchar_t *kBZip2MethodName = L"BZip2";
       
    23 static const wchar_t *kPpmdMethodName = L"PPMd";
       
    24 static const wchar_t *kDeflateMethodName = L"Deflate";
       
    25 static const wchar_t *kDeflate64MethodName = L"Deflate64";
       
    26 
       
    27 static const wchar_t *kLzmaMatchFinderX1 = L"HC4";
       
    28 static const wchar_t *kLzmaMatchFinderX5 = L"BT4";
       
    29 
       
    30 static const UInt32 kLzmaAlgoX1 = 0;
       
    31 static const UInt32 kLzmaAlgoX5 = 1;
       
    32 
       
    33 static const UInt32 kLzmaDicSizeX1 = 1 << 16;
       
    34 static const UInt32 kLzmaDicSizeX3 = 1 << 20;
       
    35 static const UInt32 kLzmaDicSizeX5 = 1 << 24;
       
    36 static const UInt32 kLzmaDicSizeX7 = 1 << 25;
       
    37 static const UInt32 kLzmaDicSizeX9 = 1 << 26;
       
    38 
       
    39 static const UInt32 kLzmaFastBytesX1 = 32;
       
    40 static const UInt32 kLzmaFastBytesX7 = 64;
       
    41 
       
    42 static const UInt32 kPpmdMemSizeX1 = (1 << 22);
       
    43 static const UInt32 kPpmdMemSizeX5 = (1 << 24);
       
    44 static const UInt32 kPpmdMemSizeX7 = (1 << 26);
       
    45 static const UInt32 kPpmdMemSizeX9 = (192 << 20);
       
    46 
       
    47 static const UInt32 kPpmdOrderX1 = 4;
       
    48 static const UInt32 kPpmdOrderX5 = 6;
       
    49 static const UInt32 kPpmdOrderX7 = 16;
       
    50 static const UInt32 kPpmdOrderX9 = 32;
       
    51 
       
    52 static const UInt32 kDeflateAlgoX1 = 0;
       
    53 static const UInt32 kDeflateAlgoX5 = 1;
       
    54 
       
    55 static const UInt32 kDeflateFastBytesX1 = 32;
       
    56 static const UInt32 kDeflateFastBytesX7 = 64;
       
    57 static const UInt32 kDeflateFastBytesX9 = 128;
       
    58 
       
    59 static const UInt32 kDeflatePassesX1 = 1;
       
    60 static const UInt32 kDeflatePassesX7 = 3;
       
    61 static const UInt32 kDeflatePassesX9 = 10;
       
    62 
       
    63 static const UInt32 kBZip2NumPassesX1 = 1;
       
    64 static const UInt32 kBZip2NumPassesX7 = 2;
       
    65 static const UInt32 kBZip2NumPassesX9 = 7;
       
    66 
       
    67 static const UInt32 kBZip2DicSizeX1 = 100000;
       
    68 static const UInt32 kBZip2DicSizeX3 = 500000;
       
    69 static const UInt32 kBZip2DicSizeX5 = 900000;
       
    70 
       
    71 static const wchar_t *kDefaultMethodName = kLZMAMethodName;
       
    72 
       
    73 static const wchar_t *kLzmaMatchFinderForHeaders = L"BT2";
       
    74 static const UInt32 kDictionaryForHeaders = 1 << 20;
       
    75 static const UInt32 kNumFastBytesForHeaders = 273;
       
    76 static const UInt32 kAlgorithmForHeaders = kLzmaAlgoX5;
       
    77 
       
    78 static bool AreEqual(const UString &methodName, const wchar_t *s)
       
    79   { return (methodName.CompareNoCase(s) == 0); }
       
    80 
       
    81 static inline bool IsLZMAMethod(const UString &methodName)
       
    82 { 
       
    83   return 
       
    84     AreEqual(methodName, kLZMAMethodName) || 
       
    85     AreEqual(methodName, kLZMA2MethodName); 
       
    86 }
       
    87 
       
    88 static inline bool IsBZip2Method(const UString &methodName)
       
    89   { return AreEqual(methodName, kBZip2MethodName); }
       
    90 
       
    91 static inline bool IsPpmdMethod(const UString &methodName)
       
    92   { return AreEqual(methodName, kPpmdMethodName); }
       
    93 
       
    94 static inline bool IsDeflateMethod(const UString &methodName)
       
    95 { 
       
    96   return 
       
    97     AreEqual(methodName, kDeflateMethodName) || 
       
    98     AreEqual(methodName, kDeflate64MethodName); 
       
    99 }
       
   100 
       
   101 struct CNameToPropID
       
   102 {
       
   103   PROPID PropID;
       
   104   VARTYPE VarType;
       
   105   const wchar_t *Name;
       
   106 };
       
   107 
       
   108 CNameToPropID g_NameToPropID[] = 
       
   109 {
       
   110   { NCoderPropID::kOrder, VT_UI4, L"O" },
       
   111   { NCoderPropID::kPosStateBits, VT_UI4, L"PB" },
       
   112   { NCoderPropID::kLitContextBits, VT_UI4, L"LC" },
       
   113   { NCoderPropID::kLitPosBits, VT_UI4, L"LP" },
       
   114   { NCoderPropID::kEndMarker, VT_BOOL, L"eos" },
       
   115 
       
   116   { NCoderPropID::kNumPasses, VT_UI4, L"Pass" },
       
   117   { NCoderPropID::kNumFastBytes, VT_UI4, L"fb" },
       
   118   { NCoderPropID::kMatchFinderCycles, VT_UI4, L"mc" },
       
   119   { NCoderPropID::kAlgorithm, VT_UI4, L"a" },
       
   120   { NCoderPropID::kMatchFinder, VT_BSTR, L"mf" },
       
   121   { NCoderPropID::kNumThreads, VT_UI4, L"mt" }
       
   122 };
       
   123 
       
   124 static bool ConvertProperty(PROPVARIANT srcProp, VARTYPE varType, NCOM::CPropVariant &destProp)
       
   125 {
       
   126   if (varType == srcProp.vt)
       
   127   {
       
   128     destProp = srcProp;
       
   129     return true;
       
   130   }
       
   131   if (varType == VT_UI1)
       
   132   {
       
   133     if (srcProp.vt == VT_UI4)
       
   134     {
       
   135       UInt32 value = srcProp.ulVal;
       
   136       if (value > 0xFF)
       
   137         return false;
       
   138       destProp = (Byte)value;
       
   139       return true;
       
   140     }
       
   141   }
       
   142   else if (varType == VT_BOOL)
       
   143   {
       
   144     bool res;
       
   145     if (SetBoolProperty(res, srcProp) != S_OK)
       
   146       return false;
       
   147     destProp = res;
       
   148     return true;
       
   149   }
       
   150   return false;
       
   151 }
       
   152     
       
   153 static int FindPropIdFromStringName(const UString &name)
       
   154 {
       
   155   for (int i = 0; i < sizeof(g_NameToPropID) / sizeof(g_NameToPropID[0]); i++)
       
   156     if (name.CompareNoCase(g_NameToPropID[i].Name) == 0)
       
   157       return i;
       
   158   return -1;
       
   159 }
       
   160 
       
   161 static void SetOneMethodProp(COneMethodInfo &oneMethodInfo, PROPID propID, 
       
   162     const NWindows::NCOM::CPropVariant &value)
       
   163 {
       
   164   for (int j = 0; j < oneMethodInfo.Properties.Size(); j++)
       
   165     if (oneMethodInfo.Properties[j].Id == propID)
       
   166       return;
       
   167   CProp property;
       
   168   property.Id = propID;
       
   169   property.Value = value;
       
   170   oneMethodInfo.Properties.Add(property);
       
   171 }
       
   172 
       
   173 void COutHandler::SetCompressionMethod2(COneMethodInfo &oneMethodInfo
       
   174     #ifdef COMPRESS_MT
       
   175     , UInt32 numThreads
       
   176     #endif
       
   177     )
       
   178 {
       
   179   UInt32 level = _level;
       
   180   if (oneMethodInfo.MethodName.IsEmpty())
       
   181     oneMethodInfo.MethodName = kDefaultMethodName;
       
   182   
       
   183   if (IsLZMAMethod(oneMethodInfo.MethodName))
       
   184   {
       
   185     UInt32 dicSize = 
       
   186       (level >= 9 ? kLzmaDicSizeX9 : 
       
   187       (level >= 7 ? kLzmaDicSizeX7 : 
       
   188       (level >= 5 ? kLzmaDicSizeX5 : 
       
   189       (level >= 3 ? kLzmaDicSizeX3 : 
       
   190                     kLzmaDicSizeX1)))); 
       
   191     
       
   192     UInt32 algo = 
       
   193       (level >= 5 ? kLzmaAlgoX5 : 
       
   194                     kLzmaAlgoX1); 
       
   195     
       
   196     UInt32 fastBytes = 
       
   197       (level >= 7 ? kLzmaFastBytesX7 : 
       
   198                     kLzmaFastBytesX1); 
       
   199     
       
   200     const wchar_t *matchFinder = 
       
   201       (level >= 5 ? kLzmaMatchFinderX5 : 
       
   202                     kLzmaMatchFinderX1); 
       
   203     
       
   204     SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
       
   205     SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
       
   206     SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
       
   207     SetOneMethodProp(oneMethodInfo, NCoderPropID::kMatchFinder, matchFinder);
       
   208     #ifdef COMPRESS_MT
       
   209     SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
       
   210     #endif
       
   211   }
       
   212   else if (IsDeflateMethod(oneMethodInfo.MethodName))
       
   213   {
       
   214     UInt32 fastBytes = 
       
   215       (level >= 9 ? kDeflateFastBytesX9 : 
       
   216       (level >= 7 ? kDeflateFastBytesX7 : 
       
   217                     kDeflateFastBytesX1));
       
   218     
       
   219     UInt32 numPasses = 
       
   220       (level >= 9 ? kDeflatePassesX9 :  
       
   221       (level >= 7 ? kDeflatePassesX7 : 
       
   222                     kDeflatePassesX1));
       
   223     
       
   224     UInt32 algo = 
       
   225       (level >= 5 ? kDeflateAlgoX5 : 
       
   226                     kDeflateAlgoX1); 
       
   227     
       
   228     SetOneMethodProp(oneMethodInfo, NCoderPropID::kAlgorithm, algo);
       
   229     SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumFastBytes, fastBytes);
       
   230     SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
       
   231   }
       
   232   else if (IsBZip2Method(oneMethodInfo.MethodName))
       
   233   {
       
   234     UInt32 numPasses = 
       
   235       (level >= 9 ? kBZip2NumPassesX9 : 
       
   236       (level >= 7 ? kBZip2NumPassesX7 :  
       
   237                     kBZip2NumPassesX1));
       
   238     
       
   239     UInt32 dicSize = 
       
   240       (level >= 5 ? kBZip2DicSizeX5 : 
       
   241       (level >= 3 ? kBZip2DicSizeX3 : 
       
   242                     kBZip2DicSizeX1));
       
   243     
       
   244     SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumPasses, numPasses);
       
   245     SetOneMethodProp(oneMethodInfo, NCoderPropID::kDictionarySize, dicSize);
       
   246     #ifdef COMPRESS_MT
       
   247     SetOneMethodProp(oneMethodInfo, NCoderPropID::kNumThreads, numThreads);
       
   248     #endif
       
   249   }
       
   250   else if (IsPpmdMethod(oneMethodInfo.MethodName))
       
   251   {
       
   252     UInt32 useMemSize = 
       
   253       (level >= 9 ? kPpmdMemSizeX9 : 
       
   254       (level >= 7 ? kPpmdMemSizeX7 : 
       
   255       (level >= 5 ? kPpmdMemSizeX5 : 
       
   256                     kPpmdMemSizeX1)));
       
   257     
       
   258     UInt32 order = 
       
   259       (level >= 9 ? kPpmdOrderX9 : 
       
   260       (level >= 7 ? kPpmdOrderX7 : 
       
   261       (level >= 5 ? kPpmdOrderX5 : 
       
   262                     kPpmdOrderX1)));
       
   263     
       
   264     SetOneMethodProp(oneMethodInfo, NCoderPropID::kUsedMemorySize, useMemSize);
       
   265     SetOneMethodProp(oneMethodInfo, NCoderPropID::kOrder, order);
       
   266   }
       
   267 }
       
   268 
       
   269 static void SplitParams(const UString &srcString, UStringVector &subStrings)
       
   270 {
       
   271   subStrings.Clear();
       
   272   UString name;
       
   273   int len = srcString.Length();
       
   274   if (len == 0)
       
   275     return;
       
   276   for (int i = 0; i < len; i++)
       
   277   {
       
   278     wchar_t c = srcString[i];
       
   279     if (c == L':')
       
   280     {
       
   281       subStrings.Add(name);
       
   282       name.Empty();
       
   283     }
       
   284     else
       
   285       name += c;
       
   286   }
       
   287   subStrings.Add(name);
       
   288 }
       
   289 
       
   290 static void SplitParam(const UString &param, UString &name, UString &value)
       
   291 {
       
   292   int eqPos = param.Find(L'=');
       
   293   if (eqPos >= 0)
       
   294   {
       
   295     name = param.Left(eqPos);
       
   296     value = param.Mid(eqPos + 1);
       
   297     return;
       
   298   }
       
   299   for(int i = 0; i < param.Length(); i++)
       
   300   {
       
   301     wchar_t c = param[i];
       
   302     if (c >= L'0' && c <= L'9')
       
   303     {
       
   304       name = param.Left(i);
       
   305       value = param.Mid(i);
       
   306       return;
       
   307     }
       
   308   }
       
   309   name = param;
       
   310 }
       
   311 
       
   312 HRESULT COutHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value)
       
   313 {
       
   314   CProp property;
       
   315   if (
       
   316     name.CompareNoCase(L"D") == 0 || 
       
   317     name.CompareNoCase(L"MEM") == 0)
       
   318   {
       
   319     UInt32 dicSize;
       
   320     RINOK(ParsePropDictionaryValue(value, dicSize));
       
   321     if (name.CompareNoCase(L"D") == 0)
       
   322       property.Id = NCoderPropID::kDictionarySize;
       
   323     else
       
   324       property.Id = NCoderPropID::kUsedMemorySize;
       
   325     property.Value = dicSize;
       
   326     oneMethodInfo.Properties.Add(property);
       
   327   }
       
   328   else
       
   329   {
       
   330     int index = FindPropIdFromStringName(name);
       
   331     if (index < 0)
       
   332       return E_INVALIDARG;
       
   333     
       
   334     const CNameToPropID &nameToPropID = g_NameToPropID[index];
       
   335     property.Id = nameToPropID.PropID;
       
   336     
       
   337     NCOM::CPropVariant propValue;
       
   338     
       
   339     if (nameToPropID.VarType == VT_BSTR)
       
   340       propValue = value;
       
   341     else if (nameToPropID.VarType == VT_BOOL)
       
   342     {
       
   343       bool res;
       
   344       if (!StringToBool(value, res))
       
   345         return E_INVALIDARG;
       
   346       propValue = res;
       
   347     }
       
   348     else
       
   349     {
       
   350       UInt32 number;
       
   351       if (ParseStringToUInt32(value, number) == value.Length())
       
   352         propValue = number;
       
   353       else
       
   354         propValue = value;
       
   355     }
       
   356     
       
   357     if (!ConvertProperty(propValue, nameToPropID.VarType, property.Value))
       
   358       return E_INVALIDARG;
       
   359     
       
   360     oneMethodInfo.Properties.Add(property);
       
   361   }
       
   362   return S_OK;
       
   363 }
       
   364 
       
   365 HRESULT COutHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString)
       
   366 {
       
   367   UStringVector params;
       
   368   SplitParams(srcString, params);
       
   369   if (params.Size() > 0)
       
   370     oneMethodInfo.MethodName = params[0];
       
   371   for (int i = 1; i < params.Size(); i++)
       
   372   {
       
   373     const UString &param = params[i];
       
   374     UString name, value;
       
   375     SplitParam(param, name, value);
       
   376     RINOK(SetParam(oneMethodInfo, name, value));
       
   377   }
       
   378   return S_OK;
       
   379 }
       
   380 
       
   381 HRESULT COutHandler::SetSolidSettings(const UString &s)
       
   382 {
       
   383   bool res;
       
   384   if (StringToBool(s, res))
       
   385   {
       
   386     if (res)
       
   387       InitSolid();
       
   388     else
       
   389       _numSolidFiles = 1;
       
   390     return S_OK;
       
   391   }
       
   392   UString s2 = s;
       
   393   s2.MakeUpper();
       
   394   for (int i = 0; i < s2.Length();)
       
   395   {
       
   396     const wchar_t *start = ((const wchar_t *)s2) + i;
       
   397     const wchar_t *end;
       
   398     UInt64 v = ConvertStringToUInt64(start, &end);
       
   399     if (start == end)
       
   400     {
       
   401       if (s2[i++] != 'E')
       
   402         return E_INVALIDARG;
       
   403       _solidExtension = true;
       
   404       continue;
       
   405     }
       
   406     i += (int)(end - start);
       
   407     if (i == s2.Length())
       
   408       return E_INVALIDARG;
       
   409     wchar_t c = s2[i++];
       
   410     switch(c)
       
   411     {
       
   412       case 'F':
       
   413         if (v < 1)
       
   414           v = 1;
       
   415         _numSolidFiles = v;
       
   416         break;
       
   417       case 'B':
       
   418         _numSolidBytes = v;
       
   419         _numSolidBytesDefined = true;
       
   420         break;
       
   421       case 'K':
       
   422         _numSolidBytes = (v << 10);
       
   423         _numSolidBytesDefined = true;
       
   424         break;
       
   425       case 'M':
       
   426         _numSolidBytes = (v << 20);
       
   427         _numSolidBytesDefined = true;
       
   428         break;
       
   429       case 'G':
       
   430         _numSolidBytes = (v << 30);
       
   431         _numSolidBytesDefined = true;
       
   432         break;
       
   433       default:
       
   434         return E_INVALIDARG;
       
   435     }
       
   436   }
       
   437   return S_OK;
       
   438 }
       
   439 
       
   440 HRESULT COutHandler::SetSolidSettings(const PROPVARIANT &value)
       
   441 {
       
   442   switch(value.vt)
       
   443   {
       
   444     case VT_EMPTY:
       
   445       InitSolid();
       
   446       return S_OK;
       
   447     case VT_BSTR:
       
   448       return SetSolidSettings(value.bstrVal);
       
   449     default:
       
   450       return E_INVALIDARG;
       
   451   }
       
   452 }
       
   453 
       
   454 void COutHandler::Init()
       
   455 {
       
   456   _removeSfxBlock = false;
       
   457   _compressHeaders = true;
       
   458   _encryptHeaders = false;
       
   459   
       
   460   WriteModified = true;
       
   461   WriteCreated = false;
       
   462   WriteAccessed = false;
       
   463   
       
   464   #ifdef COMPRESS_MT
       
   465   _numThreads = NWindows::NSystem::GetNumberOfProcessors();
       
   466   #endif
       
   467   
       
   468   _level = 5;
       
   469   _autoFilter = true;
       
   470   _volumeMode = false;
       
   471   _crcSize = 4;
       
   472   InitSolid();
       
   473 }
       
   474 
       
   475 void COutHandler::BeforeSetProperty()
       
   476 {
       
   477   Init();
       
   478   #ifdef COMPRESS_MT
       
   479   numProcessors = NSystem::GetNumberOfProcessors();
       
   480   #endif
       
   481 
       
   482   mainDicSize = 0xFFFFFFFF;
       
   483   mainDicMethodIndex = 0xFFFFFFFF;
       
   484   minNumber = 0;
       
   485   _crcSize = 4;
       
   486 }
       
   487 
       
   488 HRESULT COutHandler::SetProperty(const wchar_t *nameSpec, const PROPVARIANT &value)
       
   489 {
       
   490   UString name = nameSpec;
       
   491   name.MakeUpper();
       
   492   if (name.IsEmpty())
       
   493     return E_INVALIDARG;
       
   494   
       
   495   if (name[0] == 'X')
       
   496   {
       
   497     name.Delete(0);
       
   498     _level = 9;
       
   499     return ParsePropValue(name, value, _level);
       
   500   }
       
   501   
       
   502   if (name[0] == L'S')
       
   503   {
       
   504     name.Delete(0);
       
   505     if (name.IsEmpty())
       
   506       return SetSolidSettings(value);
       
   507     if (value.vt != VT_EMPTY)
       
   508       return E_INVALIDARG;
       
   509     return SetSolidSettings(name);
       
   510   }
       
   511   
       
   512   if (name == L"CRC")
       
   513   {
       
   514     _crcSize = 4;
       
   515     name.Delete(0, 3);
       
   516     return ParsePropValue(name, value, _crcSize);
       
   517   }
       
   518   
       
   519   UInt32 number;
       
   520   int index = ParseStringToUInt32(name, number);
       
   521   UString realName = name.Mid(index);
       
   522   if (index == 0)
       
   523   {
       
   524     if(name.Left(2).CompareNoCase(L"MT") == 0)
       
   525     {
       
   526       #ifdef COMPRESS_MT
       
   527       RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));
       
   528       #endif
       
   529       return S_OK;
       
   530     }
       
   531     if (name.CompareNoCase(L"RSFX") == 0)
       
   532       return SetBoolProperty(_removeSfxBlock, value);
       
   533     if (name.CompareNoCase(L"F") == 0)
       
   534       return SetBoolProperty(_autoFilter, value);
       
   535     if (name.CompareNoCase(L"HC") == 0)
       
   536       return SetBoolProperty(_compressHeaders, value);
       
   537     if (name.CompareNoCase(L"HCF") == 0)
       
   538     {
       
   539       bool compressHeadersFull = true;
       
   540       RINOK(SetBoolProperty(compressHeadersFull, value));
       
   541       if (!compressHeadersFull)
       
   542         return E_INVALIDARG;
       
   543       return S_OK;
       
   544     }
       
   545     if (name.CompareNoCase(L"HE") == 0)
       
   546       return SetBoolProperty(_encryptHeaders, value);
       
   547     if (name.CompareNoCase(L"TM") == 0)
       
   548       return SetBoolProperty(WriteModified, value);
       
   549     if (name.CompareNoCase(L"TC") == 0)
       
   550       return SetBoolProperty(WriteCreated, value);
       
   551     if (name.CompareNoCase(L"TA") == 0)
       
   552       return SetBoolProperty(WriteAccessed, value);
       
   553     if (name.CompareNoCase(L"V") == 0)
       
   554       return SetBoolProperty(_volumeMode, value);
       
   555     number = 0;
       
   556   }
       
   557   if (number > 10000)
       
   558     return E_FAIL;
       
   559   if (number < minNumber)
       
   560     return E_INVALIDARG;
       
   561   number -= minNumber;
       
   562   for(int j = _methods.Size(); j <= (int)number; j++)
       
   563   {
       
   564     COneMethodInfo oneMethodInfo;
       
   565     _methods.Add(oneMethodInfo);
       
   566   }
       
   567   
       
   568   COneMethodInfo &oneMethodInfo = _methods[number];
       
   569   
       
   570   if (realName.Length() == 0)
       
   571   {
       
   572     if (value.vt != VT_BSTR)
       
   573       return E_INVALIDARG;
       
   574     
       
   575     RINOK(SetParams(oneMethodInfo, value.bstrVal));
       
   576   }
       
   577   else
       
   578   {
       
   579     CProp property;
       
   580     if (realName.Left(1).CompareNoCase(L"D") == 0)
       
   581     {
       
   582       UInt32 dicSize;
       
   583       RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize));
       
   584       property.Id = NCoderPropID::kDictionarySize;
       
   585       property.Value = dicSize;
       
   586       oneMethodInfo.Properties.Add(property);
       
   587       if (number <= mainDicMethodIndex)
       
   588         mainDicSize = dicSize;
       
   589     }
       
   590     else if (realName.Left(3).CompareNoCase(L"MEM") == 0)
       
   591     {
       
   592       UInt32 dicSize;
       
   593       RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize));
       
   594       property.Id = NCoderPropID::kUsedMemorySize;
       
   595       property.Value = dicSize;
       
   596       oneMethodInfo.Properties.Add(property);
       
   597       if (number <= mainDicMethodIndex)
       
   598         mainDicSize = dicSize;
       
   599     }
       
   600     else
       
   601     {
       
   602       int index = FindPropIdFromStringName(realName);
       
   603       if (index < 0)
       
   604         return E_INVALIDARG;
       
   605       
       
   606       const CNameToPropID &nameToPropID = g_NameToPropID[index];
       
   607       property.Id = nameToPropID.PropID;
       
   608       
       
   609       if (!ConvertProperty(value, nameToPropID.VarType, property.Value))
       
   610         return E_INVALIDARG;
       
   611       
       
   612       oneMethodInfo.Properties.Add(property);
       
   613     }
       
   614   }
       
   615   return S_OK;
       
   616 }  
       
   617 
       
   618 }