diff options
Diffstat (limited to 'CPP/7zip/UI/Agent/AgentProxy.cpp')
-rw-r--r--[-rwxr-xr-x] | CPP/7zip/UI/Agent/AgentProxy.cpp | 565 |
1 files changed, 453 insertions, 112 deletions
diff --git a/CPP/7zip/UI/Agent/AgentProxy.cpp b/CPP/7zip/UI/Agent/AgentProxy.cpp index ce9b3bfb..a31a904b 100755..100644 --- a/CPP/7zip/UI/Agent/AgentProxy.cpp +++ b/CPP/7zip/UI/Agent/AgentProxy.cpp @@ -3,17 +3,21 @@ #include "StdAfx.h" #include "../../../../C/Sort.h" +#include "../../../../C/CpuArch.h" -#include "Windows/PropVariant.h" -#include "Windows/PropVariantConversions.h" +#include "../../../Common/Wildcard.h" + +#include "../../../Windows/PropVariant.h" +#include "../../../Windows/PropVariantConv.h" #include "AgentProxy.h" using namespace NWindows; -int CProxyFolder::FindDirSubItemIndex(const UString &name, int &insertPos) const +int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name, unsigned &insertPos) const { - int left = 0, right = Folders.Size(); + const CRecordVector<unsigned> &subFolders = Folders[folderIndex].Folders; + unsigned left = 0, right = subFolders.Size(); for (;;) { if (left == right) @@ -21,10 +25,11 @@ int CProxyFolder::FindDirSubItemIndex(const UString &name, int &insertPos) const insertPos = left; return -1; } - int mid = (left + right) / 2; - int compare = name.CompareNoCase(Folders[mid].Name); + unsigned mid = (left + right) / 2; + unsigned folderIndex = subFolders[mid]; + int compare = CompareFileNames(name, Folders[folderIndex].Name); if (compare == 0) - return mid; + return folderIndex; if (compare < 0) right = mid; else @@ -32,40 +37,41 @@ int CProxyFolder::FindDirSubItemIndex(const UString &name, int &insertPos) const } } -int CProxyFolder::FindDirSubItemIndex(const UString &name) const +int CProxyArchive::FindDirSubItemIndex(unsigned folderIndex, const UString &name) const { - int insertPos; - return FindDirSubItemIndex(name, insertPos); + unsigned insertPos; + return FindDirSubItemIndex(folderIndex, name, insertPos); } void CProxyFolder::AddFileSubItem(UInt32 index, const UString &name) { - Files.Add(CProxyFile()); - Files.Back().Name = name; - Files.Back().Index = index; + CProxyFile &f = Files.AddNew(); + f.Index = index; + f.Name = name; } -CProxyFolder* CProxyFolder::AddDirSubItem(UInt32 index, bool leaf, const UString &name) +unsigned CProxyArchive::AddDirSubItem(unsigned folderIndex, UInt32 index, bool leaf, const UString &name) { - int insertPos; - int folderIndex = FindDirSubItemIndex(name, insertPos); - if (folderIndex >= 0) + unsigned insertPos; + int subFolderIndex = FindDirSubItemIndex(folderIndex, name, insertPos); + if (subFolderIndex >= 0) { - CProxyFolder *item = &Folders[folderIndex]; + CProxyFolder &item = Folders[subFolderIndex]; if (leaf) { - item->Index = index; - item->IsLeaf = true; + item.Index = index; + item.IsLeaf = true; } - return item; + return subFolderIndex; } - Folders.Insert(insertPos, CProxyFolder()); - CProxyFolder *item = &Folders[insertPos]; - item->Name = name; - item->Index = index; - item->Parent = this; - item->IsLeaf = leaf; - return item; + subFolderIndex = Folders.Size(); + Folders[folderIndex].Folders.Insert(insertPos, subFolderIndex); + CProxyFolder &item = Folders.AddNew(); + item.Name = name; + item.Index = index; + item.Parent = folderIndex; + item.IsLeaf = leaf; + return subFolderIndex; } void CProxyFolder::Clear() @@ -74,51 +80,71 @@ void CProxyFolder::Clear() Files.Clear(); } -void CProxyFolder::GetPathParts(UStringVector &pathParts) const +void CProxyArchive::GetPathParts(int folderIndex, UStringVector &pathParts) const { pathParts.Clear(); - const CProxyFolder *current = this; - while (current->Parent != NULL) + while (folderIndex >= 0) { - pathParts.Insert(0, current->Name); - current = current->Parent; + const CProxyFolder &folder = Folders[folderIndex]; + folderIndex = folder.Parent; + if (folderIndex < 0) + break; + pathParts.Insert(0, folder.Name); } } -UString CProxyFolder::GetFullPathPrefix() const +UString CProxyArchive::GetFullPathPrefix(int folderIndex) const { UString result; - const CProxyFolder *current = this; - while (current->Parent != NULL) + while (folderIndex >= 0) { - result = current->Name + UString(WCHAR_PATH_SEPARATOR) + result; - current = current->Parent; + const CProxyFolder &folder = Folders[folderIndex]; + folderIndex = folder.Parent; + if (folderIndex < 0) + break; + result = folder.Name + UString(WCHAR_PATH_SEPARATOR) + result; } return result; } -void CProxyFolder::AddRealIndices(CUIntVector &realIndices) const +void CProxyArchive::AddRealIndices(unsigned folderIndex, 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); + const CProxyFolder &folder = Folders[folderIndex]; + if (folder.IsLeaf) + realIndices.Add(folder.Index); + unsigned i; + for (i = 0; i < folder.Folders.Size(); i++) + AddRealIndices(folder.Folders[i], realIndices); + for (i = 0; i < folder.Files.Size(); i++) + realIndices.Add(folder.Files[i].Index); +} + +int CProxyArchive::GetRealIndex(unsigned folderIndex, unsigned index) const +{ + const CProxyFolder &folder = Folders[folderIndex]; + unsigned numDirItems = folder.Folders.Size(); + if (index < numDirItems) + { + const CProxyFolder &f = Folders[folder.Folders[index]]; + if (f.IsLeaf) + return f.Index; + return -1; + } + return folder.Files[index - numDirItems].Index; } -void CProxyFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const +void CProxyArchive::GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, CUIntVector &realIndices) const { + const CProxyFolder &folder = Folders[folderIndex]; realIndices.Clear(); for (UInt32 i = 0; i < numItems; i++) { - int index = indices[i]; - int numDirItems = Folders.Size(); + UInt32 index = indices[i]; + unsigned numDirItems = folder.Folders.Size(); if (index < numDirItems) - Folders[index].AddRealIndices(realIndices); + AddRealIndices(folder.Folders[index], realIndices); else - realIndices.Add(Files[index - numDirItems].Index); + realIndices.Add(folder.Files[index - numDirItems].Index); } HeapSort(&realIndices.Front(), realIndices.Size()); } @@ -126,111 +152,426 @@ void CProxyFolder::GetRealIndices(const UInt32 *indices, UInt32 numItems, CUIntV /////////////////////////////////////////////// // CProxyArchive -static UInt64 GetSize(IInArchive *archive, UInt32 index, PROPID propID) +static bool GetSize(IInArchive *archive, UInt32 index, PROPID propID, UInt64 &size) { + size = 0; NCOM::CPropVariant prop; - if (archive->GetProperty(index, propID, &prop) == S_OK) - if (prop.vt != VT_EMPTY) - return ConvertPropVariantToUInt64(prop); - return 0; + if (archive->GetProperty(index, propID, &prop) != S_OK) + throw 20120228; + return ConvertPropVariantToUInt64(prop, size); } -void CProxyFolder::CalculateSizes(IInArchive *archive) +void CProxyArchive::CalculateSizes(unsigned folderIndex, IInArchive *archive) { - Size = PackSize = 0; - NumSubFolders = Folders.Size(); - NumSubFiles = Files.Size(); - CrcIsDefined = true; - Crc = 0; - int i; - for (i = 0; i < Files.Size(); i++) + CProxyFolder &folder = Folders[folderIndex]; + folder.Size = folder.PackSize = 0; + folder.NumSubFolders = folder.Folders.Size(); + folder.NumSubFiles = folder.Files.Size(); + folder.CrcIsDefined = true; + folder.Crc = 0; + unsigned i; + for (i = 0; i < folder.Files.Size(); i++) { - UInt32 index = Files[i].Index; - Size += GetSize(archive, index, kpidSize); - PackSize += GetSize(archive, index, kpidPackSize); + UInt32 index = folder.Files[i].Index; + UInt64 size, packSize; + bool sizeDefined = GetSize(archive, index, kpidSize, size); + folder.Size += size; + GetSize(archive, index, kpidPackSize, packSize); + folder.PackSize += packSize; { NCOM::CPropVariant prop; - if (archive->GetProperty(index, kpidCRC, &prop) == S_OK && prop.vt == VT_UI4) - Crc += prop.ulVal; + if (archive->GetProperty(index, kpidCRC, &prop) == S_OK) + { + if (prop.vt == VT_UI4) + folder.Crc += prop.ulVal; + else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined) + folder.CrcIsDefined = false; + } else - CrcIsDefined = false; + folder.CrcIsDefined = false; } } - for (i = 0; i < Folders.Size(); i++) + for (i = 0; i < folder.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; + unsigned subFolderIndex = folder.Folders[i]; + CProxyFolder &f = Folders[subFolderIndex]; + CalculateSizes(subFolderIndex, archive); + folder.Size += f.Size; + folder.PackSize += f.PackSize; + folder.NumSubFiles += f.NumSubFiles; + folder.NumSubFolders += f.NumSubFolders; + folder.Crc += f.Crc; if (!f.CrcIsDefined) - CrcIsDefined = false; + folder.CrcIsDefined = false; } } HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress) { - RootFolder.Clear(); + /* + DWORD tickCount = GetTickCount(); + for (int ttt = 0; ttt < 1000; ttt++) { + */ + + Folders.Clear(); + Folders.AddNew(); 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)); - } + if (progress) + RINOK(progress->SetTotal(numItems)); + UString filePath; UString fileName; for (UInt32 i = 0; i < numItems; i++) { - if (progress != NULL && (i & 0xFFFFF) == 0) + if (progress && (i & 0xFFFFF) == 0) { UInt64 currentItemIndex = i; RINOK(progress->SetCompleted(¤tItemIndex)); } - UString filePath; RINOK(arc.GetItemPath(i, filePath)); - CProxyFolder *curItem = &RootFolder; - int len = filePath.Length(); + unsigned curItem = 0; + unsigned len = filePath.Len(); fileName.Empty(); - for (int j = 0; j < len; j++) + + /* + if (arc.Ask_Deleted) + { + bool isDeleted = false; + RINOK(Archive_IsItem_Deleted(archive, i, isDeleted)); + if (isDeleted) + curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, L"[DELETED]"); + } + */ + + for (unsigned 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); + curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, fileName); fileName.Empty(); } else fileName += c; } + /* + that code must be implemeted to hide alt streams in list. + if (arc.Ask_AltStreams) + { + bool isAltStream; + RINOK(Archive_IsItem_AltStream(archive, i, isAltStream)); + if (isAltStream) + { + + } + } + */ + bool isFolder; - RINOK(IsArchiveItemFolder(archive, i, isFolder)); + RINOK(Archive_IsItem_Folder(archive, i, isFolder)); if (isFolder) - curItem->AddDirSubItem(i, true, fileName); + AddDirSubItem(curItem, i, true, fileName); else - curItem->AddFileSubItem(i, fileName); + Folders[curItem].AddFileSubItem(i, fileName); + } + CalculateSizes(0, archive); + + /* + } + char s[128]; + sprintf(s, "load archive %7d ms", GetTickCount() - tickCount); + OutputDebugStringA(s); + */ + + return S_OK; +} + + + +// ---------- for Tree-mode archive ---------- + +void CProxyArchive2::GetPathParts(int folderIndex, UStringVector &pathParts) const +{ + pathParts.Clear(); + while (folderIndex > 0) + { + const CProxyFolder2 &folder = Folders[folderIndex]; + const CProxyFile2 &file = Files[folder.ArcIndex]; + pathParts.Insert(0, file.Name); + int par = file.Parent; + if (par < 0) + break; + folderIndex = Files[par].FolderIndex; + } +} + +UString CProxyArchive2::GetFullPathPrefix(unsigned folderIndex) const +{ + return Folders[folderIndex].PathPrefix; + /* + UString result; + while (folderIndex > 0) + { + const CProxyFile2 &file = Files[Folders[folderIndex].ArcIndex]; + result = (UString)(file.Name) + (UString)WCHAR_PATH_SEPARATOR + result; + if (file.Parent < 0) + break; + folderIndex = Files[file.Parent].FolderIndex; + } + return result; + */ +} + +void CProxyArchive2::AddRealIndices_of_ArcItem(unsigned arcIndex, bool includeAltStreams, CUIntVector &realIndices) const +{ + realIndices.Add(arcIndex); + const CProxyFile2 &file = Files[arcIndex]; + if (file.FolderIndex >= 0) + AddRealIndices_of_Folder(file.FolderIndex, includeAltStreams, realIndices); + if (includeAltStreams && file.AltStreamsFolderIndex >= 0) + AddRealIndices_of_Folder(file.AltStreamsFolderIndex, includeAltStreams, realIndices); +} + +void CProxyArchive2::AddRealIndices_of_Folder(unsigned folderIndex, bool includeAltStreams, CUIntVector &realIndices) const +{ + const CRecordVector<unsigned> &subFiles = Folders[folderIndex].SubFiles; + FOR_VECTOR (i, subFiles) + { + AddRealIndices_of_ArcItem(subFiles[i], includeAltStreams, realIndices); } - RootFolder.CalculateSizes(archive); +} + +unsigned CProxyArchive2::GetRealIndex(unsigned folderIndex, unsigned index) const +{ + return Folders[folderIndex].SubFiles[index]; +} + +void CProxyArchive2::GetRealIndices(unsigned folderIndex, const UInt32 *indices, UInt32 numItems, bool includeAltStreams, CUIntVector &realIndices) const +{ + const CProxyFolder2 &folder = Folders[folderIndex]; + realIndices.Clear(); + for (UInt32 i = 0; i < numItems; i++) + { + AddRealIndices_of_ArcItem(folder.SubFiles[indices[i]], includeAltStreams, realIndices); + } + HeapSort(&realIndices.Front(), realIndices.Size()); +} + +void CProxyArchive2::CalculateSizes(unsigned folderIndex, IInArchive *archive) +{ + CProxyFolder2 &folder = Folders[folderIndex]; + folder.Size = folder.PackSize = 0; + folder.NumSubFolders = 0; // folder.Folders.Size(); + folder.NumSubFiles = 0; // folder.Files.Size(); + folder.CrcIsDefined = true; + folder.Crc = 0; + FOR_VECTOR (i, folder.SubFiles) + { + UInt32 index = folder.SubFiles[i]; + UInt64 size, packSize; + bool sizeDefined = GetSize(archive, index, kpidSize, size); + folder.Size += size; + GetSize(archive, index, kpidPackSize, packSize); + folder.PackSize += packSize; + { + NCOM::CPropVariant prop; + if (archive->GetProperty(index, kpidCRC, &prop) == S_OK) + { + if (prop.vt == VT_UI4) + folder.Crc += prop.ulVal; + else if (prop.vt != VT_EMPTY || size != 0 || !sizeDefined) + folder.CrcIsDefined = false; + } + else + folder.CrcIsDefined = false; + } + + const CProxyFile2 &subFile = Files[index]; + if (subFile.FolderIndex < 0) + { + folder.NumSubFiles++; + } + else + { + folder.NumSubFolders++; + CProxyFolder2 &f = Folders[subFile.FolderIndex]; + f.PathPrefix = folder.PathPrefix + subFile.Name + WCHAR_PATH_SEPARATOR; + CalculateSizes(subFile.FolderIndex, archive); + folder.Size += f.Size; + folder.PackSize += f.PackSize; + folder.NumSubFiles += f.NumSubFiles; + folder.NumSubFolders += f.NumSubFolders; + folder.Crc += f.Crc; + if (!f.CrcIsDefined) + folder.CrcIsDefined = false; + } + + if (subFile.AltStreamsFolderIndex < 0) + { + // folder.NumSubFiles++; + } + else + { + // folder.NumSubFolders++; + CProxyFolder2 &f = Folders[subFile.AltStreamsFolderIndex]; + f.PathPrefix = folder.PathPrefix + subFile.Name + L":"; + CalculateSizes(subFile.AltStreamsFolderIndex, archive); + /* + folder.Size += f.Size; + folder.PackSize += f.PackSize; + folder.NumSubFiles += f.NumSubFiles; + folder.NumSubFolders += f.NumSubFolders; + folder.Crc += f.Crc; + if (!f.CrcIsDefined) + folder.CrcIsDefined = false; + */ + } + + + } +} + + +bool CProxyArchive2::IsThere_SubDir(unsigned folderIndex, const UString &name) const +{ + const CRecordVector<unsigned> &subFiles = Folders[folderIndex].SubFiles; + FOR_VECTOR (i, subFiles) + { + const CProxyFile2 &file = Files[subFiles[i]]; + if (file.IsDir()) + if (CompareFileNames(name, file.Name) == 0) + return true; + } + return false; +} + +HRESULT CProxyArchive2::Load(const CArc &arc, IProgress *progress) +{ + if (!arc.GetRawProps) + return E_FAIL; + + // DWORD tickCount = GetTickCount(); + + Folders.Clear(); + + IInArchive *archive = arc.Archive; + + UInt32 numItems; + RINOK(archive->GetNumberOfItems(&numItems)); + if (progress) + RINOK(progress->SetTotal(numItems)); + UString fileName; + { + CProxyFolder2 &folder = Folders.AddNew(); + folder.ArcIndex = -1; + } + + Files.Alloc(numItems); + + UInt32 i; + for (i = 0; i < numItems; i++) + { + if (progress && (i & 0xFFFFF) == 0) + { + UInt64 currentItemIndex = i; + RINOK(progress->SetCompleted(¤tItemIndex)); + } + + CProxyFile2 &file = Files[i]; + + #ifdef MY_CPU_LE + const void *p; + UInt32 size; + UInt32 propType; + RINOK(arc.GetRawProps->GetRawProp(i, kpidName, &p, &size, &propType)); + + if (p && propType == PROP_DATA_TYPE_wchar_t_PTR_Z_LE) + { + file.Name = (const wchar_t *)p; + file.NameSize = 0; + if (size >= 2) + file.NameSize = size / 2 - 1; + } + else + #endif + { + NCOM::CPropVariant prop; + RINOK(arc.Archive->GetProperty(i, kpidName, &prop)); + const wchar_t *s; + if (prop.vt == VT_BSTR) + s = prop.bstrVal; + else if (prop.vt == VT_EMPTY) + s = L"[Content]"; + else + return E_FAIL; + file.NameSize = MyStringLen(s); + file.Name = new wchar_t[file.NameSize + 1]; + file.NeedDeleteName = true; + MyStringCopy((wchar_t *)file.Name, s); + } + UInt32 parent = (UInt32)(Int32)-1; + UInt32 parentType = 0; + RINOK(arc.GetRawProps->GetParent(i, &parent, &parentType)); + file.Parent = (Int32)parent; + + if (arc.Ask_Deleted) + { + bool isDeleted = false; + RINOK(Archive_IsItem_Deleted(archive, i, isDeleted)); + if (isDeleted) + { + // continue; + // curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, L"[DELETED]"); + } + } + + bool isFolder; + RINOK(Archive_IsItem_Folder(archive, i, isFolder)); + + if (isFolder) + { + file.FolderIndex = Folders.Size(); + CProxyFolder2 &folder = Folders.AddNew(); + folder.ArcIndex = i; + } + if (arc.Ask_AltStream) + RINOK(Archive_IsItem_AltStream(archive, i, file.IsAltStream)); + } + + for (i = 0; i < numItems; i++) + { + CProxyFile2 &file = Files[i]; + if (file.IsAltStream) + { + if (file.Parent >= 0) + { + int &folderIndex = Files[file.Parent].AltStreamsFolderIndex; + if (folderIndex < 0) + { + folderIndex = Folders.Size(); + CProxyFolder2 &folder = Folders.AddNew(); + folder.ArcIndex = file.Parent; // do we need it ??? + } + Folders[folderIndex].SubFiles.Add(i); + } + } + else + { + int folderIndex = GetParentFolderOfFile(i); + if (folderIndex < 0) + return E_FAIL; + Folders[folderIndex].SubFiles.Add(i); + } + } + CalculateSizes(0, archive); + + /* + char s[128]; + sprintf(s, "load archive %7d ms", GetTickCount() - tickCount); + OutputDebugStringA(s); + */ return S_OK; } |