mirror of
https://github.com/Xevion/easy7zip.git
synced 2025-12-06 15:14:59 -06:00
247 lines
5.7 KiB
C++
Executable File
247 lines
5.7 KiB
C++
Executable File
// AgentProxy.cpp
|
|
|
|
#include "StdAfx.h"
|
|
|
|
#include "../../../../C/Sort.h"
|
|
|
|
#include "Windows/PropVariant.h"
|
|
#include "Windows/PropVariantConversions.h"
|
|
|
|
#include "../Common/OpenArchive.h"
|
|
|
|
#include "AgentProxy.h"
|
|
|
|
using namespace NWindows;
|
|
|
|
int CProxyFolder::FindDirSubItemIndex(const UString &name, int &insertPos) const
|
|
{
|
|
int left = 0, right = Folders.Size();
|
|
for (;;)
|
|
{
|
|
if (left == right)
|
|
{
|
|
insertPos = left;
|
|
return -1;
|
|
}
|
|
int mid = (left + right) / 2;
|
|
int compare = name.CompareNoCase(Folders[mid].Name);
|
|
if (compare == 0)
|
|
return mid;
|
|
if (compare < 0)
|
|
right = mid;
|
|
else
|
|
left = mid + 1;
|
|
}
|
|
}
|
|
|
|
int CProxyFolder::FindDirSubItemIndex(const UString &name) const
|
|
{
|
|
int insertPos;
|
|
return FindDirSubItemIndex(name, insertPos);
|
|
}
|
|
|
|
void CProxyFolder::AddFileSubItem(UInt32 index, const UString &name)
|
|
{
|
|
Files.Add(CProxyFile());
|
|
Files.Back().Name = name;
|
|
Files.Back().Index = index;
|
|
}
|
|
|
|
CProxyFolder* CProxyFolder::AddDirSubItem(UInt32 index, bool leaf, const UString &name)
|
|
{
|
|
int insertPos;
|
|
int folderIndex = FindDirSubItemIndex(name, insertPos);
|
|
if (folderIndex >= 0)
|
|
{
|
|
CProxyFolder *item = &Folders[folderIndex];
|
|
if (leaf)
|
|
{
|
|
item->Index = index;
|
|
item->IsLeaf = true;
|
|
}
|
|
return item;
|
|
}
|
|
Folders.Insert(insertPos, CProxyFolder());
|
|
CProxyFolder *item = &Folders[insertPos];
|
|
item->Name = name;
|
|
item->Index = index;
|
|
item->Parent = this;
|
|
item->IsLeaf = leaf;
|
|
return item;
|
|
}
|
|
|
|
void CProxyFolder::Clear()
|
|
{
|
|
Folders.Clear();
|
|
Files.Clear();
|
|
}
|
|
|
|
void CProxyFolder::GetPathParts(UStringVector &pathParts) const
|
|
{
|
|
pathParts.Clear();
|
|
UString result;
|
|
const CProxyFolder *current = this;
|
|
while (current->Parent != NULL)
|
|
{
|
|
pathParts.Insert(0, (const wchar_t *)current->Name);
|
|
current = current->Parent;
|
|
}
|
|
}
|
|
|
|
UString CProxyFolder::GetFullPathPrefix() const
|
|
{
|
|
UString result;
|
|
const CProxyFolder *current = this;
|
|
while (current->Parent != NULL)
|
|
{
|
|
result = current->Name + UString(WCHAR_PATH_SEPARATOR) + result;
|
|
current = current->Parent;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
UString CProxyFolder::GetItemName(UInt32 index) const
|
|
{
|
|
if (index < (UInt32)Folders.Size())
|
|
return Folders[index].Name;
|
|
return Files[index - Folders.Size()].Name;
|
|
}
|
|
|
|
void CProxyFolder::AddRealIndices(CUIntVector &realIndices) const
|
|
{
|
|
if (IsLeaf)
|
|
realIndices.Add(Index);
|
|
int i;
|
|
for (i = 0; i < Folders.Size(); i++)
|
|
Folders[i].AddRealIndices(realIndices);
|
|
for (i = 0; i < Files.Size(); i++)
|
|
realIndices.Add(Files[i].Index);
|
|
}
|
|
|
|
void CProxyFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const
|
|
{
|
|
realIndices.Clear();
|
|
for (UInt32 i = 0; i < numItems; i++)
|
|
{
|
|
int index = indices[i];
|
|
int numDirItems = Folders.Size();
|
|
if (index < numDirItems)
|
|
Folders[index].AddRealIndices(realIndices);
|
|
else
|
|
realIndices.Add(Files[index - numDirItems].Index);
|
|
}
|
|
HeapSort(&realIndices.Front(), realIndices.Size());
|
|
}
|
|
|
|
///////////////////////////////////////////////
|
|
// CProxyArchive
|
|
|
|
static UInt64 GetSize(IInArchive *archive, UInt32 index, PROPID propID)
|
|
{
|
|
NCOM::CPropVariant prop;
|
|
if (archive->GetProperty(index, propID, &prop) == S_OK)
|
|
if (prop.vt != VT_EMPTY)
|
|
return ConvertPropVariantToUInt64(prop);
|
|
return 0;
|
|
}
|
|
|
|
void CProxyFolder::CalculateSizes(IInArchive *archive)
|
|
{
|
|
Size = PackSize = 0;
|
|
NumSubFolders = Folders.Size();
|
|
NumSubFiles = Files.Size();
|
|
CrcIsDefined = true;
|
|
Crc = 0;
|
|
int i;
|
|
for (i = 0; i < Files.Size(); i++)
|
|
{
|
|
UInt32 index = Files[i].Index;
|
|
Size += GetSize(archive, index, kpidSize);
|
|
PackSize += GetSize(archive, index, kpidPackSize);
|
|
{
|
|
NCOM::CPropVariant prop;
|
|
if (archive->GetProperty(index, kpidCRC, &prop) == S_OK && prop.vt == VT_UI4)
|
|
Crc += prop.ulVal;
|
|
else
|
|
CrcIsDefined = false;
|
|
}
|
|
}
|
|
for (i = 0; i < Folders.Size(); i++)
|
|
{
|
|
CProxyFolder &f = Folders[i];
|
|
f.CalculateSizes(archive);
|
|
Size += f.Size;
|
|
PackSize += f.PackSize;
|
|
NumSubFiles += f.NumSubFiles;
|
|
NumSubFolders += f.NumSubFolders;
|
|
Crc += f.Crc;
|
|
if (!f.CrcIsDefined)
|
|
CrcIsDefined = false;
|
|
}
|
|
}
|
|
|
|
HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress)
|
|
{
|
|
RootFolder.Clear();
|
|
IInArchive *archive = arc.Archive;
|
|
{
|
|
ThereIsPathProp = false;
|
|
UInt32 numProps;
|
|
archive->GetNumberOfProperties(&numProps);
|
|
for (UInt32 i = 0; i < numProps; i++)
|
|
{
|
|
CMyComBSTR name;
|
|
PROPID propID;
|
|
VARTYPE varType;
|
|
RINOK(archive->GetPropertyInfo(i, &name, &propID, &varType));
|
|
if (propID == kpidPath)
|
|
{
|
|
ThereIsPathProp = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
UInt32 numItems;
|
|
RINOK(archive->GetNumberOfItems(&numItems));
|
|
if (progress != NULL)
|
|
{
|
|
UInt64 totalItems = numItems;
|
|
RINOK(progress->SetTotal(totalItems));
|
|
}
|
|
UString fileName;
|
|
for (UInt32 i = 0; i < numItems; i++)
|
|
{
|
|
if (progress != NULL && (i & 0xFFFFF) == 0)
|
|
{
|
|
UInt64 currentItemIndex = i;
|
|
RINOK(progress->SetCompleted(¤tItemIndex));
|
|
}
|
|
UString filePath;
|
|
RINOK(arc.GetItemPath(i, filePath));
|
|
CProxyFolder *curItem = &RootFolder;
|
|
int len = filePath.Length();
|
|
fileName.Empty();
|
|
for (int j = 0; j < len; j++)
|
|
{
|
|
wchar_t c = filePath[j];
|
|
if (c == WCHAR_PATH_SEPARATOR || c == L'/')
|
|
{
|
|
curItem = curItem->AddDirSubItem((UInt32)(Int32)-1, false, fileName);
|
|
fileName.Empty();
|
|
}
|
|
else
|
|
fileName += c;
|
|
}
|
|
|
|
bool isFolder;
|
|
RINOK(IsArchiveItemFolder(archive, i, isFolder));
|
|
if (isFolder)
|
|
curItem->AddDirSubItem(i, true, fileName);
|
|
else
|
|
curItem->AddFileSubItem(i, fileName);
|
|
}
|
|
RootFolder.CalculateSizes(archive);
|
|
return S_OK;
|
|
}
|