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 ¶m, 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 ¶m = 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 + -
显示快捷键?