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

📄 openarchive.cpp

📁 7z一个高压缩比的压缩程序源代码,重要的是里面的算法值得学习
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    }
    #endif

    HRESULT result = archive->Open(inStream, &kMaxCheckStartPosition, openArchiveCallback);
    if (result == S_FALSE)
      continue;
    RINOK(result);
    *archiveResult = archive.Detach();
    const CArcInfoEx &format = codecs->Formats[formatIndex];
    if (format.Exts.Size() == 0)
    {
      defaultItemName = GetDefaultName2(fileName, L"", L"");
    }
    else
    {
      int subExtIndex = format.FindExtension(extension);
      if (subExtIndex < 0)
        subExtIndex = 0;
      defaultItemName = GetDefaultName2(fileName,
          format.Exts[subExtIndex].Ext,
          format.Exts[subExtIndex].AddExt);
    }
    return S_OK;
  }
  return S_FALSE;
}

HRESULT OpenArchive(
    CCodecs *codecs,
    int arcTypeIndex,
    const UString &filePath,
    IInArchive **archiveResult,
    int &formatIndex,
    UString &defaultItemName,
    IArchiveOpenCallback *openArchiveCallback)
{
  CInFileStream *inStreamSpec = new CInFileStream;
  CMyComPtr<IInStream> inStream(inStreamSpec);
  if (!inStreamSpec->Open(filePath))
    return GetLastError();
  return OpenArchive(codecs, arcTypeIndex, inStream, ExtractFileNameFromPath(filePath),
    archiveResult, formatIndex,
    defaultItemName, openArchiveCallback);
}

static void MakeDefaultName(UString &name)
{
  int dotPos = name.ReverseFind(L'.');
  if (dotPos < 0)
    return;
  UString ext = name.Mid(dotPos + 1);
  if (ext.IsEmpty())
    return;
  for (int pos = 0; pos < ext.Length(); pos++)
    if (ext[pos] < L'0' || ext[pos] > L'9')
      return;
  name = name.Left(dotPos);
}

HRESULT OpenArchive(
    CCodecs *codecs,
    const CIntVector &formatIndices,
    const UString &fileName,
    IInArchive **archive0,
    IInArchive **archive1,
    int &formatIndex0,
    int &formatIndex1,
    UString &defaultItemName0,
    UString &defaultItemName1,
    IArchiveOpenCallback *openArchiveCallback)
{
  if (formatIndices.Size() >= 3)
    return E_NOTIMPL;
  
  int arcTypeIndex = -1;
  if (formatIndices.Size() >= 1)
    arcTypeIndex = formatIndices[formatIndices.Size() - 1];
  
  HRESULT result = OpenArchive(codecs, arcTypeIndex, fileName,
    archive0, formatIndex0, defaultItemName0, openArchiveCallback);
  RINOK(result);

  if (formatIndices.Size() == 1)
    return S_OK;
  arcTypeIndex = -1;
  if (formatIndices.Size() >= 2)
    arcTypeIndex = formatIndices[formatIndices.Size() - 2];

  HRESULT resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL);

  CMyComPtr<IInArchiveGetStream> getStream;
  result = (*archive0)->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream);
  if (result != S_OK || !getStream)
    return resSpec;

  CMyComPtr<ISequentialInStream> subSeqStream;
  result = getStream->GetStream(0, &subSeqStream);
  if (result != S_OK || !subSeqStream)
    return resSpec;

  CMyComPtr<IInStream> subStream;
  result = subSeqStream.QueryInterface(IID_IInStream, &subStream);
  if (result != S_OK || !subStream)
    return resSpec;

  UInt32 numItems;
  RINOK((*archive0)->GetNumberOfItems(&numItems));
  if (numItems < 1)
    return resSpec;

  UString subPath;
  RINOK(GetArchiveItemPath(*archive0, 0, subPath))
  if (subPath.IsEmpty())
  {
    MakeDefaultName(defaultItemName0);
    subPath = defaultItemName0;
    const CArcInfoEx &format = codecs->Formats[formatIndex0];
    if (format.Name.CompareNoCase(L"7z") == 0)
    {
      if (subPath.Right(3).CompareNoCase(L".7z") != 0)
        subPath += L".7z";
    }
  }
  else
    subPath = ExtractFileNameFromPath(subPath);

  CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName;
  openArchiveCallback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);
  if (setSubArchiveName)
    setSubArchiveName->SetSubArchiveName(subPath);

  result = OpenArchive(codecs, arcTypeIndex, subStream, subPath,
      archive1, formatIndex1, defaultItemName1, openArchiveCallback);
  resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE);
  if (result != S_OK)
    return resSpec;
  return S_OK;
}

static void SetCallback(const UString &archiveName,
    IOpenCallbackUI *openCallbackUI,
    IArchiveOpenCallback *reOpenCallback,
    CMyComPtr<IArchiveOpenCallback> &openCallback)
{
  COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
  openCallback = openCallbackSpec;
  openCallbackSpec->Callback = openCallbackUI;
  openCallbackSpec->ReOpenCallback = reOpenCallback;

  UString fullName;
  int fileNamePartStartIndex;
  NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex);
  openCallbackSpec->Init(
      fullName.Left(fileNamePartStartIndex),
      fullName.Mid(fileNamePartStartIndex));
}

HRESULT MyOpenArchive(
    CCodecs *codecs,
    int arcTypeIndex,
    const UString &archiveName,
    IInArchive **archive, UString &defaultItemName, IOpenCallbackUI *openCallbackUI)
{
  CMyComPtr<IArchiveOpenCallback> openCallback;
  SetCallback(archiveName, openCallbackUI, NULL, openCallback);
  int formatInfo;
  return OpenArchive(codecs, arcTypeIndex, archiveName, archive, formatInfo, defaultItemName, openCallback);
}

HRESULT MyOpenArchive(
    CCodecs *codecs,
    const CIntVector &formatIndices,
    const UString &archiveName,
    IInArchive **archive0,
    IInArchive **archive1,
    UString &defaultItemName0,
    UString &defaultItemName1,
    UStringVector &volumePaths,
    UInt64 &volumesSize,
    IOpenCallbackUI *openCallbackUI)
{
  volumesSize = 0;
  COpenCallbackImp *openCallbackSpec = new COpenCallbackImp;
  CMyComPtr<IArchiveOpenCallback> openCallback = openCallbackSpec;
  openCallbackSpec->Callback = openCallbackUI;

  UString fullName;
  int fileNamePartStartIndex;
  NFile::NDirectory::MyGetFullPathName(archiveName, fullName, fileNamePartStartIndex);
  UString prefix = fullName.Left(fileNamePartStartIndex);
  UString name = fullName.Mid(fileNamePartStartIndex);
  openCallbackSpec->Init(prefix, name);

  int formatIndex0, formatIndex1;
  RINOK(OpenArchive(codecs, formatIndices, archiveName,
      archive0,
      archive1,
      formatIndex0,
      formatIndex1,
      defaultItemName0,
      defaultItemName1,
      openCallback));
  volumePaths.Add(prefix + name);
  for (int i = 0; i < openCallbackSpec->FileNames.Size(); i++)
    volumePaths.Add(prefix + openCallbackSpec->FileNames[i]);
  volumesSize = openCallbackSpec->TotalSize;
  return S_OK;
}

HRESULT CArchiveLink::Close()
{
  if (Archive1 != 0)
    RINOK(Archive1->Close());
  if (Archive0 != 0)
    RINOK(Archive0->Close());
  IsOpen = false;
  return S_OK;
}

void CArchiveLink::Release()
{
  IsOpen = false;
  Archive1.Release();
  Archive0.Release();
}

HRESULT OpenArchive(
    CCodecs *codecs,
    const CIntVector &formatIndices,
    const UString &archiveName,
    CArchiveLink &archiveLink,
    IArchiveOpenCallback *openCallback)
{
  HRESULT res = OpenArchive(codecs, formatIndices, archiveName,
    &archiveLink.Archive0, &archiveLink.Archive1,
    archiveLink.FormatIndex0, archiveLink.FormatIndex1,
    archiveLink.DefaultItemName0, archiveLink.DefaultItemName1,
    openCallback);
  archiveLink.IsOpen = (res == S_OK);
  return res;
}

HRESULT MyOpenArchive(CCodecs *codecs,
    const CIntVector &formatIndices,
    const UString &archiveName,
    CArchiveLink &archiveLink,
    IOpenCallbackUI *openCallbackUI)
{
  HRESULT res = MyOpenArchive(codecs, formatIndices, archiveName,
    &archiveLink.Archive0, &archiveLink.Archive1,
    archiveLink.DefaultItemName0, archiveLink.DefaultItemName1,
    archiveLink.VolumePaths,
    archiveLink.VolumesSize,
    openCallbackUI);
  archiveLink.IsOpen = (res == S_OK);
  return res;
}

HRESULT ReOpenArchive(CCodecs *codecs, CArchiveLink &archiveLink, const UString &fileName,
    IArchiveOpenCallback *openCallback)
{
  if (archiveLink.GetNumLevels() > 1)
    return E_NOTIMPL;

  if (archiveLink.GetNumLevels() == 0)
    return MyOpenArchive(codecs, CIntVector(), fileName, archiveLink, 0);

  CMyComPtr<IArchiveOpenCallback> openCallbackNew;
  SetCallback(fileName, NULL, openCallback, openCallbackNew);

  HRESULT res = ReOpenArchive(archiveLink.GetArchive(), fileName, openCallbackNew);
  archiveLink.IsOpen = (res == S_OK);
  return res;
}

⌨️ 快捷键说明

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