From be3b47d0d504a3409ce66bd77bb8c0acff87c4f5 Mon Sep 17 00:00:00 2001 From: kh1 Date: Thu, 15 Mar 2012 14:53:47 +0100 Subject: Reorganize the tree, have better ifw.pri. Shadow build support. Change-Id: I01fb12537f863ed0744979973c7e4153889cc5cb Reviewed-by: Tim Jenssen --- .../7zip/win/CPP/7zip/UI/Common/EnumDirItems.cpp | 361 +++++++++++++++++++++ 1 file changed, 361 insertions(+) create mode 100644 src/libs/7zip/win/CPP/7zip/UI/Common/EnumDirItems.cpp (limited to 'src/libs/7zip/win/CPP/7zip/UI/Common/EnumDirItems.cpp') diff --git a/src/libs/7zip/win/CPP/7zip/UI/Common/EnumDirItems.cpp b/src/libs/7zip/win/CPP/7zip/UI/Common/EnumDirItems.cpp new file mode 100644 index 000000000..ba03ea35c --- /dev/null +++ b/src/libs/7zip/win/CPP/7zip/UI/Common/EnumDirItems.cpp @@ -0,0 +1,361 @@ +// EnumDirItems.cpp + +#include "StdAfx.h" + +#include "EnumDirItems.h" + +using namespace NWindows; +using namespace NFile; +using namespace NName; + +void AddDirFileInfo(int phyParent, int logParent, + const NFind::CFileInfoW &fi, CObjectVector &dirItems) +{ + CDirItem di; + di.Size = fi.Size; + di.CTime = fi.CTime; + di.ATime = fi.ATime; + di.MTime = fi.MTime; + di.Attrib = fi.Attrib; + di.PhyParent = phyParent; + di.LogParent = logParent; + di.Name = fi.Name; + dirItems.Add(di); +} + +UString CDirItems::GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const +{ + UString path; + int len = name.Length(); + int i; + for (i = index; i >= 0; i = parents[i]) + len += Prefixes[i].Length(); + int totalLen = len; + wchar_t *p = path.GetBuffer(len); + p[len] = 0; + len -= name.Length(); + memcpy(p + len, (const wchar_t *)name, name.Length() * sizeof(wchar_t)); + for (i = index; i >= 0; i = parents[i]) + { + const UString &s = Prefixes[i]; + len -= s.Length(); + memcpy(p + len, (const wchar_t *)s, s.Length() * sizeof(wchar_t)); + } + path.ReleaseBuffer(totalLen); + return path; +} + +UString CDirItems::GetPhyPath(int index) const +{ + const CDirItem &di = Items[index]; + return GetPrefixesPath(PhyParents, di.PhyParent, di.Name); +} + +UString CDirItems::GetLogPath(int index) const +{ + const CDirItem &di = Items[index]; + return GetPrefixesPath(LogParents, di.LogParent, di.Name); +} + +void CDirItems::ReserveDown() +{ + Prefixes.ReserveDown(); + PhyParents.ReserveDown(); + LogParents.ReserveDown(); + Items.ReserveDown(); +} + +int CDirItems::AddPrefix(int phyParent, int logParent, const UString &prefix) +{ + PhyParents.Add(phyParent); + LogParents.Add(logParent); + return Prefixes.Add(prefix); +} + +void CDirItems::DeleteLastPrefix() +{ + PhyParents.DeleteBack(); + LogParents.DeleteBack(); + Prefixes.DeleteBack(); +} + +void CDirItems::EnumerateDirectory(int phyParent, int logParent, const UString &phyPrefix, + UStringVector &errorPaths, CRecordVector &errorCodes) +{ + NFind::CEnumeratorW enumerator(phyPrefix + (wchar_t)kAnyStringWildcard); + for (;;) + { + NFind::CFileInfoW fi; + bool found; + if (!enumerator.Next(fi, found)) + { + errorCodes.Add(::GetLastError()); + errorPaths.Add(phyPrefix); + return; + } + if (!found) + break; + AddDirFileInfo(phyParent, logParent, fi, Items); + if (fi.IsDir()) + { + const UString name2 = fi.Name + (wchar_t)kDirDelimiter; + int parent = AddPrefix(phyParent, logParent, name2); + EnumerateDirectory(parent, parent, phyPrefix + name2, errorPaths, errorCodes); + } + } +} + +void CDirItems::EnumerateDirItems2(const UString &phyPrefix, const UString &logPrefix, + const UStringVector &filePaths, UStringVector &errorPaths, CRecordVector &errorCodes) +{ + int phyParent = phyPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, phyPrefix); + int logParent = logPrefix.IsEmpty() ? -1 : AddPrefix(-1, -1, logPrefix); + + for (int i = 0; i < filePaths.Size(); i++) + { + const UString &filePath = filePaths[i]; + NFind::CFileInfoW fi; + const UString phyPath = phyPrefix + filePath; + if (!fi.Find(phyPath)) + { + errorCodes.Add(::GetLastError()); + errorPaths.Add(phyPath); + continue; + } + int delimiter = filePath.ReverseFind((wchar_t)kDirDelimiter); + UString phyPrefixCur; + int phyParentCur = phyParent; + if (delimiter >= 0) + { + phyPrefixCur = filePath.Left(delimiter + 1); + phyParentCur = AddPrefix(phyParent, logParent, phyPrefixCur); + } + AddDirFileInfo(phyParentCur, logParent, fi, Items); + if (fi.IsDir()) + { + const UString name2 = fi.Name + (wchar_t)kDirDelimiter; + int parent = AddPrefix(phyParentCur, logParent, name2); + EnumerateDirectory(parent, parent, phyPrefix + phyPrefixCur + name2, errorPaths, errorCodes); + } + } + ReserveDown(); +} + +static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, + int phyParent, int logParent, const UString &phyPrefix, + const UStringVector &addArchivePrefix, + CDirItems &dirItems, + bool enterToSubFolders, + IEnumDirItemCallback *callback, + UStringVector &errorPaths, + CRecordVector &errorCodes); + +static HRESULT EnumerateDirItems_Spec(const NWildcard::CCensorNode &curNode, + int phyParent, int logParent, const UString &curFolderName, + const UString &phyPrefix, + const UStringVector &addArchivePrefix, + CDirItems &dirItems, + bool enterToSubFolders, + IEnumDirItemCallback *callback, + UStringVector &errorPaths, + CRecordVector &errorCodes) + +{ + const UString name2 = curFolderName + (wchar_t)kDirDelimiter; + int parent = dirItems.AddPrefix(phyParent, logParent, name2); + int numItems = dirItems.Items.Size(); + HRESULT res = EnumerateDirItems(curNode, parent, parent, phyPrefix + name2, + addArchivePrefix, dirItems, enterToSubFolders, callback, errorPaths, errorCodes); + if (numItems == dirItems.Items.Size()) + dirItems.DeleteLastPrefix(); + return res; +} + + +static HRESULT EnumerateDirItems(const NWildcard::CCensorNode &curNode, + int phyParent, int logParent, const UString &phyPrefix, + const UStringVector &addArchivePrefix, // prefix from curNode + CDirItems &dirItems, + bool enterToSubFolders, + IEnumDirItemCallback *callback, + UStringVector &errorPaths, + CRecordVector &errorCodes) +{ + if (!enterToSubFolders) + if (curNode.NeedCheckSubDirs()) + enterToSubFolders = true; + if (callback) + RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); + + // try direct_names case at first + if (addArchivePrefix.IsEmpty() && !enterToSubFolders) + { + // check that all names are direct + int i; + for (i = 0; i < curNode.IncludeItems.Size(); i++) + { + const NWildcard::CItem &item = curNode.IncludeItems[i]; + if (item.Recursive || item.PathParts.Size() != 1) + break; + const UString &name = item.PathParts.Front(); + if (name.IsEmpty() || DoesNameContainWildCard(name)) + break; + } + if (i == curNode.IncludeItems.Size()) + { + // all names are direct (no wildcards) + // so we don't need file_system's dir enumerator + CRecordVector needEnterVector; + for (i = 0; i < curNode.IncludeItems.Size(); i++) + { + const NWildcard::CItem &item = curNode.IncludeItems[i]; + const UString &name = item.PathParts.Front(); + const UString fullPath = phyPrefix + name; + NFind::CFileInfoW fi; + if (!fi.Find(fullPath)) + { + errorCodes.Add(::GetLastError()); + errorPaths.Add(fullPath); + continue; + } + bool isDir = fi.IsDir(); + if (isDir && !item.ForDir || !isDir && !item.ForFile) + { + errorCodes.Add((DWORD)E_FAIL); + errorPaths.Add(fullPath); + continue; + } + { + UStringVector pathParts; + pathParts.Add(fi.Name); + if (curNode.CheckPathToRoot(false, pathParts, !isDir)) + continue; + } + AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); + if (!isDir) + continue; + + UStringVector addArchivePrefixNew; + const NWildcard::CCensorNode *nextNode = 0; + int index = curNode.FindSubNode(name); + if (index >= 0) + { + for (int t = needEnterVector.Size(); t <= index; t++) + needEnterVector.Add(true); + needEnterVector[index] = false; + nextNode = &curNode.SubNodes[index]; + } + else + { + nextNode = &curNode; + addArchivePrefixNew.Add(name); // don't change it to fi.Name. It's for shortnames support + } + + RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, fi.Name, phyPrefix, + addArchivePrefixNew, dirItems, true, callback, errorPaths, errorCodes)); + } + for (i = 0; i < curNode.SubNodes.Size(); i++) + { + if (i < needEnterVector.Size()) + if (!needEnterVector[i]) + continue; + const NWildcard::CCensorNode &nextNode = curNode.SubNodes[i]; + const UString fullPath = phyPrefix + nextNode.Name; + NFind::CFileInfoW fi; + if (!fi.Find(fullPath)) + { + if (!nextNode.AreThereIncludeItems()) + continue; + errorCodes.Add(::GetLastError()); + errorPaths.Add(fullPath); + continue; + } + if (!fi.IsDir()) + { + errorCodes.Add((DWORD)E_FAIL); + errorPaths.Add(fullPath); + continue; + } + + RINOK(EnumerateDirItems_Spec(nextNode, phyParent, logParent, fi.Name, phyPrefix, + UStringVector(), dirItems, false, callback, errorPaths, errorCodes)); + } + return S_OK; + } + } + + + NFind::CEnumeratorW enumerator(phyPrefix + wchar_t(kAnyStringWildcard)); + for (int ttt = 0; ; ttt++) + { + NFind::CFileInfoW fi; + bool found; + if (!enumerator.Next(fi, found)) + { + errorCodes.Add(::GetLastError()); + errorPaths.Add(phyPrefix); + break; + } + if (!found) + break; + + if (callback && (ttt & 0xFF) == 0xFF) + RINOK(callback->ScanProgress(dirItems.GetNumFolders(), dirItems.Items.Size(), phyPrefix)); + const UString &name = fi.Name; + bool enterToSubFolders2 = enterToSubFolders; + UStringVector addArchivePrefixNew = addArchivePrefix; + addArchivePrefixNew.Add(name); + { + UStringVector addArchivePrefixNewTemp(addArchivePrefixNew); + if (curNode.CheckPathToRoot(false, addArchivePrefixNewTemp, !fi.IsDir())) + continue; + } + if (curNode.CheckPathToRoot(true, addArchivePrefixNew, !fi.IsDir())) + { + AddDirFileInfo(phyParent, logParent, fi, dirItems.Items); + if (fi.IsDir()) + enterToSubFolders2 = true; + } + if (!fi.IsDir()) + continue; + + const NWildcard::CCensorNode *nextNode = 0; + if (addArchivePrefix.IsEmpty()) + { + int index = curNode.FindSubNode(name); + if (index >= 0) + nextNode = &curNode.SubNodes[index]; + } + if (!enterToSubFolders2 && nextNode == 0) + continue; + + addArchivePrefixNew = addArchivePrefix; + if (nextNode == 0) + { + nextNode = &curNode; + addArchivePrefixNew.Add(name); + } + + RINOK(EnumerateDirItems_Spec(*nextNode, phyParent, logParent, name, phyPrefix, + addArchivePrefixNew, dirItems, enterToSubFolders2, callback, errorPaths, errorCodes)); + } + return S_OK; +} + +HRESULT EnumerateItems( + const NWildcard::CCensor &censor, + CDirItems &dirItems, + IEnumDirItemCallback *callback, + UStringVector &errorPaths, + CRecordVector &errorCodes) +{ + for (int i = 0; i < censor.Pairs.Size(); i++) + { + const NWildcard::CPair &pair = censor.Pairs[i]; + int phyParent = pair.Prefix.IsEmpty() ? -1 : dirItems.AddPrefix(-1, -1, pair.Prefix); + RINOK(EnumerateDirItems(pair.Head, phyParent, -1, pair.Prefix, UStringVector(), dirItems, false, + callback, errorPaths, errorCodes)); + } + dirItems.ReserveDown(); + return S_OK; +} -- cgit v1.2.3