7zhandlerout.cpp

来自「由7-zip提供的压缩、解压缩程序」· C++ 代码 · 共 1,124 行 · 第 1/2 页

CPP
1,124
字号
  {    Int32 newData;    Int32 newProperties;    UInt32 indexInArchive;    if (!updateCallback)      return E_FAIL;    RINOK(updateCallback->GetUpdateItemInfo(i,        &newData, &newProperties, &indexInArchive));    CUpdateItem updateItem;    updateItem.NewProperties = IntToBool(newProperties);    updateItem.NewData = IntToBool(newData);    updateItem.IndexInArchive = indexInArchive;    updateItem.IndexInClient = i;    updateItem.IsAnti = false;    updateItem.Size = 0;    if (updateItem.IndexInArchive != -1)    {      const CFileItem &fileItem = database->Files[updateItem.IndexInArchive];      updateItem.Name = fileItem.Name;      updateItem.IsDirectory = fileItem.IsDirectory;      updateItem.Size = fileItem.UnPackSize;      updateItem.IsAnti = fileItem.IsAnti;      updateItem.LastWriteTime = fileItem.LastWriteTime;      updateItem.LastWriteTimeIsDefined = fileItem.IsLastWriteTimeDefined;    }    if (updateItem.NewProperties)    {      bool nameIsDefined;      bool folderStatusIsDefined;      {        NCOM::CPropVariant propVariant;        RINOK(updateCallback->GetProperty(i, kpidAttributes, &propVariant));        if (propVariant.vt == VT_EMPTY)          updateItem.AttributesAreDefined = false;        else if (propVariant.vt != VT_UI4)          return E_INVALIDARG;        else        {          updateItem.Attributes = propVariant.ulVal;          updateItem.AttributesAreDefined = true;        }      }      {        NCOM::CPropVariant propVariant;        RINOK(updateCallback->GetProperty(i, kpidCreationTime, &propVariant));        if (propVariant.vt == VT_EMPTY)          updateItem.CreationTimeIsDefined = false;        else if (propVariant.vt != VT_FILETIME)          return E_INVALIDARG;        else        {          updateItem.CreationTime = propVariant.filetime;          updateItem.CreationTimeIsDefined = true;        }      }      {        NCOM::CPropVariant propVariant;        RINOK(updateCallback->GetProperty(i, kpidLastWriteTime, &propVariant));        if (propVariant.vt == VT_EMPTY)          updateItem.LastWriteTimeIsDefined = false;        else if (propVariant.vt != VT_FILETIME)          return E_INVALIDARG;        else        {          updateItem.LastWriteTime = propVariant.filetime;          updateItem.LastWriteTimeIsDefined = true;        }      }      {        NCOM::CPropVariant propVariant;        RINOK(updateCallback->GetProperty(i, kpidPath, &propVariant));        if (propVariant.vt == VT_EMPTY)          nameIsDefined = false;        else if (propVariant.vt != VT_BSTR)          return E_INVALIDARG;        else        {          updateItem.Name = NItemName::MakeLegalName(propVariant.bstrVal);          nameIsDefined = true;        }      }      {        NCOM::CPropVariant propVariant;        RINOK(updateCallback->GetProperty(i, kpidIsFolder, &propVariant));        if (propVariant.vt == VT_EMPTY)          folderStatusIsDefined = false;        else if (propVariant.vt != VT_BOOL)          return E_INVALIDARG;        else        {          updateItem.IsDirectory = (propVariant.boolVal != VARIANT_FALSE);          folderStatusIsDefined = true;        }      }      {        NCOM::CPropVariant propVariant;        RINOK(updateCallback->GetProperty(i, kpidIsAnti, &propVariant));        if (propVariant.vt == VT_EMPTY)          updateItem.IsAnti = false;        else if (propVariant.vt != VT_BOOL)          return E_INVALIDARG;        else          updateItem.IsAnti = (propVariant.boolVal != VARIANT_FALSE);      }      if (updateItem.IsAnti)      {        updateItem.AttributesAreDefined = false;        updateItem.CreationTimeIsDefined = false;        updateItem.LastWriteTimeIsDefined = false;        updateItem.Size = 0;      }      if (!folderStatusIsDefined && updateItem.AttributesAreDefined)        updateItem.SetDirectoryStatusFromAttributes();    }    if (updateItem.NewData)    {      NCOM::CPropVariant propVariant;      RINOK(updateCallback->GetProperty(i, kpidSize, &propVariant));      if (propVariant.vt != VT_UI8)        return E_INVALIDARG;      updateItem.Size = (UInt64)propVariant.uhVal.QuadPart;      if (updateItem.Size != 0 && updateItem.IsAnti)        return E_INVALIDARG;    }    updateItems.Add(updateItem);  }  CCompressionMethodMode methodMode, headerMethod;  RINOK(SetCompressionMethod(methodMode, headerMethod));  #ifdef COMPRESS_MT  methodMode.NumThreads = _numThreads;  headerMethod.NumThreads = 1;  #endif  RINOK(SetPassword(methodMode, updateCallback));  bool useAdditionalHeaderStreams = true;  bool compressMainHeader = false;   if (_compressHeadersFull)  {    useAdditionalHeaderStreams = false;    compressMainHeader = true;   }  if (methodMode.PasswordIsDefined)  {    useAdditionalHeaderStreams = false;    compressMainHeader = true;     if(_encryptHeaders)      RINOK(SetPassword(headerMethod, updateCallback));  }  if (numItems < 2)    compressMainHeader = false;  CUpdateOptions options;  options.Method = &methodMode;  options.HeaderMethod = (_compressHeaders ||       (methodMode.PasswordIsDefined && _encryptHeaders)) ?       &headerMethod : 0;  options.UseFilters = _level != 0 && _autoFilter;  options.MaxFilter = _level >= 8;  options.UseAdditionalHeaderStreams = useAdditionalHeaderStreams;  options.CompressMainHeader = compressMainHeader;  options.NumSolidFiles = _numSolidFiles;  options.NumSolidBytes = _numSolidBytes;  options.SolidExtension = _solidExtension;  options.RemoveSfxBlock = _removeSfxBlock;  options.VolumeMode = _volumeMode;  return Update(      #ifdef _7Z_VOL      volume ? volume->Stream: 0,       volume ? database: 0,       #else      _inStream,       database,      #endif      updateItems, outStream, updateCallback, options);  COM_TRY_END}static HRESULT GetBindInfoPart(UString &srcString, UInt32 &coder, UInt32 &stream){  stream = 0;  int index = ParseStringToUInt32(srcString, coder);  if (index == 0)    return E_INVALIDARG;  srcString.Delete(0, index);  if (srcString[0] == 'S')  {    srcString.Delete(0);    int index = ParseStringToUInt32(srcString, stream);    if (index == 0)      return E_INVALIDARG;    srcString.Delete(0, index);  }  return S_OK;}static HRESULT GetBindInfo(UString &srcString, CBind &bind){  RINOK(GetBindInfoPart(srcString, bind.OutCoder, bind.OutStream));  if (srcString[0] != ':')    return E_INVALIDARG;  srcString.Delete(0);  RINOK(GetBindInfoPart(srcString, bind.InCoder, bind.InStream));  if (!srcString.IsEmpty())    return E_INVALIDARG;  return S_OK;}static void SplitParams(const UString &srcString, UStringVector &subStrings){  subStrings.Clear();  UString name;  int len = srcString.Length();  if (len == 0)    return;  for (int i = 0; i < len; i++)  {    wchar_t c = srcString[i];    if (c == L':')    {      subStrings.Add(name);      name.Empty();    }    else      name += c;  }  subStrings.Add(name);}static void SplitParam(const UString &param, UString &name, UString &value){  int eqPos = param.Find(L'=');  if (eqPos >= 0)  {    name = param.Left(eqPos);    value = param.Mid(eqPos + 1);    return;  }  for(int i = 0; i < param.Length(); i++)  {    wchar_t c = param[i];    if (c >= L'0' && c <= L'9')    {      name = param.Left(i);      value = param.Mid(i);      return;    }  }  name = param;}HRESULT CHandler::SetParam(COneMethodInfo &oneMethodInfo, const UString &name, const UString &value){  CProperty property;  if (name.CompareNoCase(L"D") == 0 || name.CompareNoCase(L"MEM") == 0)  {    UInt32 dicSize;    RINOK(ParsePropDictionaryValue(value, dicSize));    if (name.CompareNoCase(L"D") == 0)      property.PropID = NCoderPropID::kDictionarySize;    else      property.PropID = NCoderPropID::kUsedMemorySize;    property.Value = dicSize;    oneMethodInfo.CoderProperties.Add(property);  }  else  {    int index = FindPropIdFromStringName(name);    if (index < 0)      return E_INVALIDARG;        const CNameToPropID &nameToPropID = g_NameToPropID[index];    property.PropID = nameToPropID.PropID;        NCOM::CPropVariant propValue;            if (nameToPropID.VarType == VT_BSTR)      propValue = value;    else    {      UInt32 number;      if (ParseStringToUInt32(value, number) == value.Length())        propValue = number;      else        propValue = value;    }        if (!ConvertProperty(propValue, nameToPropID.VarType, property.Value))      return E_INVALIDARG;        oneMethodInfo.CoderProperties.Add(property);  }  return S_OK;}HRESULT CHandler::SetParams(COneMethodInfo &oneMethodInfo, const UString &srcString){  UStringVector params;  SplitParams(srcString, params);  if (params.Size() > 0)    oneMethodInfo.MethodName = params[0];  for (int i = 1; i < params.Size(); i++)  {    const UString &param = params[i];    UString name, value;    SplitParam(param, name, value);    RINOK(SetParam(oneMethodInfo, name, value));  }  return S_OK;}HRESULT CHandler::SetSolidSettings(const UString &s){  UString s2 = s;  s2.MakeUpper();  if (s2.IsEmpty() || s2.Compare(L"ON") == 0)  {    InitSolid();    return S_OK;  }  if (s2.Compare(L"OFF") == 0)  {    _numSolidFiles = 1;    return S_OK;  }  for (int i = 0; i < s2.Length();)  {    const wchar_t *start = ((const wchar_t *)s2) + i;    const wchar_t *end;    UInt64 v = ConvertStringToUInt64(start, &end);    if (start == end)    {      if (s2[i++] != 'E')        return E_INVALIDARG;      _solidExtension = true;      continue;    }    i += (int)(end - start);    if (i == s2.Length())      return E_INVALIDARG;    wchar_t c = s2[i++];    switch(c)    {      case 'F':        if (v < 1)          v = 1;        _numSolidFiles = v;        break;      case 'B':        _numSolidBytes = v;        _numSolidBytesDefined = true;        break;      case 'K':        _numSolidBytes = (v << 10);        _numSolidBytesDefined = true;        break;      case 'M':        _numSolidBytes = (v << 20);        _numSolidBytesDefined = true;        break;      case 'G':        _numSolidBytes = (v << 30);        _numSolidBytesDefined = true;        break;      default:        return E_INVALIDARG;    }  }  return S_OK;}HRESULT CHandler::SetSolidSettings(const PROPVARIANT &value){  switch(value.vt)  {    case VT_EMPTY:      InitSolid();      return S_OK;    case VT_BSTR:      return SetSolidSettings(value.bstrVal);    default:      return E_INVALIDARG;  }}STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties){  COM_TRY_BEGIN  _methods.Clear();  _binds.Clear();  Init();  #ifdef COMPRESS_MT  const UInt32 numProcessors = NSystem::GetNumberOfProcessors();  #endif  UInt32 mainDicSize = 0xFFFFFFFF;  UInt32 mainDicMethodIndex = 0xFFFFFFFF;  UInt32 minNumber = 0;  for (int i = 0; i < numProperties; i++)  {    UString name = names[i];    name.MakeUpper();    if (name.IsEmpty())      return E_INVALIDARG;    const PROPVARIANT &value = values[i];    if (name[0] == 'X')    {      name.Delete(0);      _level = 9;      RINOK(ParsePropValue(name, value, _level));      continue;    }    if (name[0] == 'B')    {      name.Delete(0);      CBind bind;      RINOK(GetBindInfo(name, bind));      _binds.Add(bind);      continue;    }    if (name[0] == L'S')    {      name.Delete(0);      if (name.IsEmpty())      {        RINOK(SetSolidSettings(value));      }      else      {        RINOK(SetSolidSettings(name));      }      continue;    }              UInt32 number;    int index = ParseStringToUInt32(name, number);    UString realName = name.Mid(index);    if (index == 0)    {      if(name.Left(2).CompareNoCase(L"MT") == 0)      {        #ifdef COMPRESS_MT        RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));        #endif        continue;      }      else if (name.CompareNoCase(L"RSFX") == 0)      {        RINOK(SetBoolProperty(_removeSfxBlock, value));        continue;      }      else if (name.CompareNoCase(L"F") == 0)      {        RINOK(SetBoolProperty(_autoFilter, value));        continue;      }      else if (name.CompareNoCase(L"HC") == 0)      {        RINOK(SetBoolProperty(_compressHeaders, value));        continue;      }      else if (name.CompareNoCase(L"HCF") == 0)      {        RINOK(SetBoolProperty(_compressHeadersFull, value));        continue;      }      else if (name.CompareNoCase(L"HE") == 0)      {        RINOK(SetBoolProperty(_encryptHeaders, value));        continue;      }      else if (name.CompareNoCase(L"V") == 0)      {        RINOK(SetBoolProperty(_volumeMode, value));        continue;      }      number = 0;    }    if (number > 10000)      return E_FAIL;    if (number < minNumber)      return E_INVALIDARG;    number -= minNumber;    for(int j = _methods.Size(); j <= (int)number; j++)    {      COneMethodInfo oneMethodInfo;      _methods.Add(oneMethodInfo);    }    COneMethodInfo &oneMethodInfo = _methods[number];    if (realName.Length() == 0)    {      if (value.vt != VT_BSTR)        return E_INVALIDARG;            // oneMethodInfo.MethodName = UnicodeStringToMultiByte(UString(value.bstrVal));      RINOK(SetParams(oneMethodInfo, value.bstrVal));    }    else    {      CProperty property;      if (realName.Left(1).CompareNoCase(L"D") == 0)      {        UInt32 dicSize;        RINOK(ParsePropDictionaryValue(realName.Mid(1), value, dicSize));        property.PropID = NCoderPropID::kDictionarySize;        property.Value = dicSize;        oneMethodInfo.CoderProperties.Add(property);        if (number <= mainDicMethodIndex)          mainDicSize = dicSize;      }      else if (realName.Left(3).CompareNoCase(L"MEM") == 0)      {        UInt32 dicSize;        RINOK(ParsePropDictionaryValue(realName.Mid(3), value, dicSize));        property.PropID = NCoderPropID::kUsedMemorySize;        property.Value = dicSize;        oneMethodInfo.CoderProperties.Add(property);        if (number <= mainDicMethodIndex)          mainDicSize = dicSize;      }      else      {        int index = FindPropIdFromStringName(realName);        if (index < 0)          return E_INVALIDARG;                const CNameToPropID &nameToPropID = g_NameToPropID[index];        property.PropID = nameToPropID.PropID;                if (!ConvertProperty(value, nameToPropID.VarType, property.Value))          return E_INVALIDARG;                oneMethodInfo.CoderProperties.Add(property);      }    }  }  return S_OK;  COM_TRY_END}  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?