⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 archivecommandline.cpp

📁 一个7ZIP的解压源码。比较详细。里面含有四种语言的实现代码。
💻 CPP
📖 第 1 页 / 共 3 页
字号:
        property.Name = postString.Left(index);
        property.Value = postString.Mid(index + 1);
      }
      properties.Add(property);
    }
  }
}

CArchiveCommandLineParser::CArchiveCommandLineParser(): 
  parser(sizeof(kSwitchForms) / sizeof(kSwitchForms[0])) {}

void CArchiveCommandLineParser::Parse1(const UStringVector &commandStrings,
    CArchiveCommandLineOptions &options)
{
  try
  {
    parser.ParseStrings(kSwitchForms, commandStrings);
  }
  catch(...) 
  {
    ThrowUserErrorException();
  }

  options.IsInTerminal = MY_IS_TERMINAL(stdin);
  options.IsStdOutTerminal = MY_IS_TERMINAL(stdout);
  options.IsStdErrTerminal = MY_IS_TERMINAL(stderr);
  options.StdOutMode = parser[NKey::kStdOut].ThereIs;
  options.EnableHeaders = !parser[NKey::kDisableHeaders].ThereIs;
  options.HelpMode = parser[NKey::kHelp1].ThereIs || parser[NKey::kHelp2].ThereIs  || parser[NKey::kHelp3].ThereIs;

  #ifdef _WIN32
  options.LargePages = false;
  if (parser[NKey::kLargePages].ThereIs)
  {
    const UString &postString = parser[NKey::kLargePages].PostStrings.Front();
    if (postString.IsEmpty())
      options.LargePages = true;
  }
  #endif
}

struct CCodePagePair
{
  const wchar_t *Name;
  UINT CodePage;
};

static CCodePagePair g_CodePagePairs[] = 
{
  { L"UTF-8", CP_UTF8 },
  { L"WIN",   CP_ACP },
  { L"DOS",   CP_OEMCP }
};

static const int kNumCodePages = sizeof(g_CodePagePairs) / sizeof(g_CodePagePairs[0]);

static bool ConvertStringToUInt32(const wchar_t *s, UInt32 &v)
{
  const wchar_t *end;
  UInt64 number = ConvertStringToUInt64(s, &end);
  if (*end != 0)
    return false;
  if (number > (UInt32)0xFFFFFFFF)
    return false;
  v = (UInt32)number;
  return true;
}

void CArchiveCommandLineParser::Parse2(CArchiveCommandLineOptions &options)
{
  const UStringVector &nonSwitchStrings = parser.NonSwitchStrings;
  int numNonSwitchStrings = nonSwitchStrings.Size();
  if(numNonSwitchStrings < kMinNonSwitchWords)  
    ThrowUserErrorException();

  if (!ParseArchiveCommand(nonSwitchStrings[kCommandIndex], options.Command))
    ThrowUserErrorException();

  options.TechMode = parser[NKey::kTechMode].ThereIs;

  if (parser[NKey::kCaseSensitive].ThereIs)
    g_CaseSensitive = (parser[NKey::kCaseSensitive].PostCharIndex < 0);

  NRecursedType::EEnum recursedType;
  if (parser[NKey::kRecursed].ThereIs)
    recursedType = GetRecursedTypeFromIndex(parser[NKey::kRecursed].PostCharIndex);
  else
    recursedType = NRecursedType::kNonRecursed;

  UINT codePage = CP_UTF8;
  if (parser[NKey::kCharSet].ThereIs)
  {
    UString name = parser[NKey::kCharSet].PostStrings.Front();
    name.MakeUpper();
    int i;
    for (i = 0; i < kNumCodePages; i++)
    {
      const CCodePagePair &pair = g_CodePagePairs[i];
      if (name.Compare(pair.Name) == 0)
      {
        codePage = pair.CodePage;
        break;
      }
    }
    if (i >= kNumCodePages)
      ThrowUserErrorException();
  }

  bool thereAreSwitchIncludes = false;
  if (parser[NKey::kInclude].ThereIs)
  {
    thereAreSwitchIncludes = true;
    AddSwitchWildCardsToCensor(options.WildcardCensor, 
        parser[NKey::kInclude].PostStrings, true, recursedType, codePage);
  }
  if (parser[NKey::kExclude].ThereIs)
    AddSwitchWildCardsToCensor(options.WildcardCensor, 
        parser[NKey::kExclude].PostStrings, false, recursedType, codePage);
 
  int curCommandIndex = kCommandIndex + 1;
  bool thereIsArchiveName = !parser[NKey::kNoArName].ThereIs && 
      options.Command.CommandType != NCommandType::kBenchmark && 
      options.Command.CommandType != NCommandType::kInfo;
  if (thereIsArchiveName)
  {
    if(curCommandIndex >= numNonSwitchStrings)  
      ThrowUserErrorException();
    options.ArchiveName = nonSwitchStrings[curCommandIndex++];
  }

  AddToCensorFromNonSwitchesStrings(
      curCommandIndex, options.WildcardCensor, 
      nonSwitchStrings, recursedType, thereAreSwitchIncludes, codePage);

  options.YesToAll = parser[NKey::kYes].ThereIs;

  bool isExtractGroupCommand = options.Command.IsFromExtractGroup();

  options.PasswordEnabled = parser[NKey::kPassword].ThereIs;

  if(options.PasswordEnabled)
    options.Password = parser[NKey::kPassword].PostStrings[0];

  options.StdInMode = parser[NKey::kStdIn].ThereIs;
  options.ShowDialog = parser[NKey::kShowDialog].ThereIs;

  if(isExtractGroupCommand || options.Command.CommandType == NCommandType::kList)
  {
    if (options.StdInMode)
      ThrowException("Reading archives from stdin is not implemented");
    if (!options.WildcardCensor.AllAreRelative())
      ThrowException("Cannot use absolute pathnames for this command");

    NWildcard::CCensor archiveWildcardCensor;

    if (parser[NKey::kArInclude].ThereIs)
    {
      AddSwitchWildCardsToCensor(archiveWildcardCensor, 
        parser[NKey::kArInclude].PostStrings, true, NRecursedType::kNonRecursed, codePage);
    }
    if (parser[NKey::kArExclude].ThereIs)
      AddSwitchWildCardsToCensor(archiveWildcardCensor, 
      parser[NKey::kArExclude].PostStrings, false, NRecursedType::kNonRecursed, codePage);

    if (thereIsArchiveName)
      AddCommandLineWildCardToCensr(archiveWildcardCensor, options.ArchiveName, true, NRecursedType::kNonRecursed);

    #ifdef _WIN32
    ConvertToLongNames(archiveWildcardCensor);
    #endif

    archiveWildcardCensor.ExtendExclude();

    CObjectVector<CDirItem> dirItems;
    {
      UStringVector errorPaths;
      CRecordVector<DWORD> errorCodes;
      HRESULT res = EnumerateItems(archiveWildcardCensor, dirItems, NULL, errorPaths, errorCodes);
      if (res != S_OK || errorPaths.Size() > 0)
        throw "cannot find archive";
    }
    UStringVector archivePaths;
    int i;
    for (i = 0; i < dirItems.Size(); i++)
    {
      const CDirItem &dirItem = dirItems[i];
      if (!dirItem.IsDirectory())
        archivePaths.Add(dirItem.FullPath);
    }

    if (archivePaths.Size() == 0)
      throw "there is no such archive";

    UStringVector archivePathsFull;

    for (i = 0; i < archivePaths.Size(); i++)
    {
      UString fullPath;
      NFile::NDirectory::MyGetFullPathName(archivePaths[i], fullPath);
      archivePathsFull.Add(fullPath);
    }
    CIntVector indices;
    SortFileNames(archivePathsFull, indices);
    options.ArchivePathsSorted.Reserve(indices.Size());
    options.ArchivePathsFullSorted.Reserve(indices.Size());
    for (i = 0; i < indices.Size(); i++)
    {
      options.ArchivePathsSorted.Add(archivePaths[indices[i]]);
      options.ArchivePathsFullSorted.Add(archivePathsFull[indices[i]]);
    }

    if (isExtractGroupCommand)
    {
      SetMethodOptions(parser, options.ExtractProperties); 
      if (options.StdOutMode && options.IsStdOutTerminal && options.IsStdErrTerminal)
        throw kSameTerminalError;
      if(parser[NKey::kOutputDir].ThereIs)
      {
        options.OutputDir = parser[NKey::kOutputDir].PostStrings[0];
        NFile::NName::NormalizeDirPathPrefix(options.OutputDir);
      }

      options.OverwriteMode = NExtract::NOverwriteMode::kAskBefore;
      if(parser[NKey::kOverwrite].ThereIs)
        options.OverwriteMode = 
            k_OverwriteModes[parser[NKey::kOverwrite].PostCharIndex];
      else if (options.YesToAll)
        options.OverwriteMode = NExtract::NOverwriteMode::kWithoutPrompt;
    }
  }
  else if(options.Command.IsFromUpdateGroup())
  {
    CUpdateOptions &updateOptions = options.UpdateOptions;

    if(parser[NKey::kArchiveType].ThereIs)
      options.ArcType = parser[NKey::kArchiveType].PostStrings[0];

    SetAddCommandOptions(options.Command.CommandType, parser, updateOptions); 
    
    SetMethodOptions(parser, updateOptions.MethodMode.Properties); 

    if (parser[NKey::kShareForWrite].ThereIs)
      updateOptions.OpenShareForWrite = true;

    options.EnablePercents = !parser[NKey::kDisablePercents].ThereIs;

    if (options.EnablePercents)
    {
      if ((options.StdOutMode && !options.IsStdErrTerminal) || 
         (!options.StdOutMode && !options.IsStdOutTerminal))  
        options.EnablePercents = false;
    }

    updateOptions.EMailMode = parser[NKey::kEmail].ThereIs;
    if (updateOptions.EMailMode)
    {
      updateOptions.EMailAddress = parser[NKey::kEmail].PostStrings.Front();
      if (updateOptions.EMailAddress.Length() > 0)
        if (updateOptions.EMailAddress[0] == L'.')
        {
          updateOptions.EMailRemoveAfter = true;
          updateOptions.EMailAddress.Delete(0);
        }
    }

    updateOptions.StdOutMode = options.StdOutMode;
    updateOptions.StdInMode = options.StdInMode;

    if (updateOptions.StdOutMode && updateOptions.EMailMode)
      throw "stdout mode and email mode cannot be combined";
    if (updateOptions.StdOutMode && options.IsStdOutTerminal)
      throw kTerminalOutError;
    if(updateOptions.StdInMode)
      updateOptions.StdInFileName = parser[NKey::kStdIn].PostStrings.Front();

    #ifdef _WIN32
    ConvertToLongNames(options.WildcardCensor);
    #endif
  }
  else if(options.Command.CommandType == NCommandType::kBenchmark)
  {
    options.NumThreads = (UInt32)-1;
    options.DictionarySize = (UInt32)-1;
    options.NumIterations = 1;
    if (curCommandIndex < numNonSwitchStrings)  
    {
      if (!ConvertStringToUInt32(nonSwitchStrings[curCommandIndex++], options.NumIterations))
        ThrowUserErrorException();
    }
    for (int i = 0; i < parser[NKey::kProperty].PostStrings.Size(); i++)
    {
      UString postString = parser[NKey::kProperty].PostStrings[i];
      postString.MakeUpper();
      if (postString.Length() < 2)
        ThrowUserErrorException();
      if (postString[0] == 'D')
      {
        int pos = 1;
        if (postString[pos] == '=')
          pos++;
        UInt32 logSize;
        if (!ConvertStringToUInt32((const wchar_t *)postString + pos, logSize))
          ThrowUserErrorException();
        if (logSize > 31)
          ThrowUserErrorException();
        options.DictionarySize = 1 << logSize;
      }
      else if (postString[0] == 'M' && postString[1] == 'T' )
      {
        int pos = 2;
        if (postString[pos] == '=')
          pos++;
        if (postString[pos] != 0)
          if (!ConvertStringToUInt32((const wchar_t *)postString + pos, options.NumThreads))
            ThrowUserErrorException();
      }
      else if (postString[0] == 'M' && postString[1] == '=' )
      {
        int pos = 2;
        if (postString[pos] != 0)
          options.Method = postString.Mid(2);
      }
      else
        ThrowUserErrorException();
    }
  }
  else if(options.Command.CommandType == NCommandType::kInfo)
  {
  }
  else 
    ThrowUserErrorException();
  options.WildcardCensor.ExtendExclude();
}

⌨️ 快捷键说明

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