diff options
Diffstat (limited to 'CPP/Common/Wildcard.cpp')
-rw-r--r-- | CPP/Common/Wildcard.cpp | 257 |
1 files changed, 162 insertions, 95 deletions
diff --git a/CPP/Common/Wildcard.cpp b/CPP/Common/Wildcard.cpp index 9614f63d..a83f9f10 100644 --- a/CPP/Common/Wildcard.cpp +++ b/CPP/Common/Wildcard.cpp @@ -15,22 +15,8 @@ bool g_CaseSensitive = bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2) { if (g_CaseSensitive) - { - for (;;) - { - wchar_t c2 = *s2++; if (c2 == 0) return true; - wchar_t c1 = *s1++; - if (MyCharUpper(c1) != - MyCharUpper(c2)) - return false; - } - } - - for (;;) - { - wchar_t c2 = *s2++; if (c2 == 0) return true; - wchar_t c1 = *s1++; if (c1 != c2) return false; - } + return IsString1PrefixedByString2(s1, s2); + return IsString1PrefixedByString2_NoCase(s1, s2); } int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW @@ -97,7 +83,7 @@ void SplitPathToParts(const UString &path, UStringVector &pathParts) UString name; unsigned prev = 0; for (unsigned i = 0; i < len; i++) - if (IsCharDirLimiter(path[i])) + if (IsPathSepar(path[i])) { name.SetFrom(path.Ptr(prev), i - prev); pathParts.Add(name); @@ -112,7 +98,7 @@ void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name) const wchar_t *start = path; const wchar_t *p = start + path.Len(); for (; p != start; p--) - if (IsCharDirLimiter(*(p - 1))) + if (IsPathSepar(*(p - 1))) break; dirPrefix.SetFrom(path, (unsigned)(p - start)); name = p; @@ -124,10 +110,10 @@ void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &na const wchar_t *p = start + path.Len(); if (p != start) { - if (IsCharDirLimiter(*(p - 1))) + if (IsPathSepar(*(p - 1))) p--; for (; p != start; p--) - if (IsCharDirLimiter(*(p - 1))) + if (IsPathSepar(*(p - 1))) break; } dirPrefix.SetFrom(path, (unsigned)(p - start)); @@ -139,7 +125,7 @@ UString ExtractDirPrefixFromPath(const UString &path) const wchar_t *start = path; const wchar_t *p = start + path.Len(); for (; p != start; p--) - if (IsCharDirLimiter(*(p - 1))) + if (IsPathSepar(*(p - 1))) break; return path.Left((unsigned)(p - start)); } @@ -149,7 +135,7 @@ UString ExtractFileNameFromPath(const UString &path) const wchar_t *start = path; const wchar_t *p = start + path.Len(); for (; p != start; p--) - if (IsCharDirLimiter(*(p - 1))) + if (IsPathSepar(*(p - 1))) break; return p; } @@ -177,15 +163,6 @@ bool DoesNameContainWildcard(const UString &path) namespace NWildcard { - -#ifdef _WIN32 -bool IsDriveColonName(const wchar_t *s) -{ - wchar_t c = s[0]; - return c != 0 && s[1] == ':' && s[2] == 0 && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'); -} -#endif - /* M = MaskParts.Size(); @@ -212,6 +189,19 @@ bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const { if (!isFile && !ForDir) return false; + + /* + if (PathParts.IsEmpty()) + { + // PathParts.IsEmpty() means all items (universal wildcard) + if (!isFile) + return true; + if (pathParts.Size() <= 1) + return ForFile; + return (ForDir || Recursive && ForFile); + } + */ + int delta = (int)pathParts.Size() - (int)PathParts.Size(); if (delta < 0) return false; @@ -286,7 +276,7 @@ void CCensorNode::AddItemSimple(bool include, CItem &item) ExcludeItems.Add(item); } -void CCensorNode::AddItem(bool include, CItem &item) +void CCensorNode::AddItem(bool include, CItem &item, int ignoreWildcardIndex) { if (item.PathParts.Size() <= 1) { @@ -300,9 +290,10 @@ void CCensorNode::AddItem(bool include, CItem &item) } const UString &front = item.PathParts.Front(); - // We can't ignore wildcard, since we don't allow wildcard in SubNodes[].Name - // if (item.Wildcard) - if (DoesNameContainWildcard(front)) + // WIN32 doesn't support wildcards in file names + if (item.WildcardMatching + && ignoreWildcardIndex != 0 + && DoesNameContainWildcard(front)) { AddItemSimple(include, item); return; @@ -311,7 +302,7 @@ void CCensorNode::AddItem(bool include, CItem &item) if (index < 0) index = SubNodes.Add(CCensorNode(front, this)); item.PathParts.Delete(0); - SubNodes[index].AddItem(include, item); + SubNodes[index].AddItem(include, item, ignoreWildcardIndex - 1); } void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir, bool wildcardMatching) @@ -377,6 +368,7 @@ bool CCensorNode::CheckPathVect(const UStringVector &pathParts, bool isFile, boo return finded; } +/* bool CCensorNode::CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const { UStringVector pathParts; @@ -406,6 +398,7 @@ bool CCensorNode::CheckPath(bool isAltStream, const UString &path, bool isFile) return include; return false; } +*/ bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const { @@ -433,7 +426,7 @@ void CCensorNode::AddItem2(bool include, const UString &path, bool recursive, bo bool forFile = true; bool forFolder = true; UString path2 = path; - if (IsCharDirLimiter(path.Back())) + if (IsPathSepar(path.Back())) { path2.DeleteBack(); forFile = false; @@ -462,12 +455,90 @@ int CCensor::FindPrefix(const UString &prefix) const return -1; } +#ifdef _WIN32 + +bool IsDriveColonName(const wchar_t *s) +{ + wchar_t c = s[0]; + return c != 0 && s[1] == ':' && s[2] == 0 && (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z'); +} + +unsigned GetNumPrefixParts_if_DrivePath(UStringVector &pathParts) +{ + if (pathParts.IsEmpty()) + return 0; + + unsigned testIndex = 0; + if (pathParts[0].IsEmpty()) + { + if (pathParts.Size() < 4 + || !pathParts[1].IsEmpty() + || pathParts[2] != L"?") + return 0; + testIndex = 3; + } + if (NWildcard::IsDriveColonName(pathParts[testIndex])) + return testIndex + 1; + return 0; +} + +#endif + +static unsigned GetNumPrefixParts(const UStringVector pathParts) +{ + if (pathParts.IsEmpty()) + return 0; + + #ifdef _WIN32 + + if (IsDriveColonName(pathParts[0])) + return 1; + if (!pathParts[0].IsEmpty()) + return 0; + + if (pathParts.Size() == 1) + return 1; + if (!pathParts[1].IsEmpty()) + return 1; + if (pathParts.Size() == 2) + return 2; + if (pathParts[2] == L".") + return 3; + + unsigned networkParts = 2; + if (pathParts[2] == L"?") + { + if (pathParts.Size() == 3) + return 3; + if (IsDriveColonName(pathParts[3])) + return 4; + if (!pathParts[3].IsEqualTo_Ascii_NoCase("UNC")) + return 3; + networkParts = 4; + } + + networkParts += + // 2; // server/share + 1; // server + if (pathParts.Size() <= networkParts) + return pathParts.Size(); + return networkParts; + + #else + + return pathParts[0].IsEmpty() ? 1 : 0; + + #endif +} + void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &path, bool recursive, bool wildcardMatching) { - UStringVector pathParts; if (path.IsEmpty()) throw "Empty file path"; + + UStringVector pathParts; SplitPathToParts(path, pathParts); + bool forFile = true; if (pathParts.Back().IsEmpty()) { @@ -477,74 +548,55 @@ void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &pat UString prefix; + int ignoreWildcardIndex = -1; + + // #ifdef _WIN32 + // we ignore "?" wildcard in "\\?\" prefix. + if (pathParts.Size() >= 3 + && pathParts[0].IsEmpty() + && pathParts[1].IsEmpty() + && pathParts[2] == L"?") + ignoreWildcardIndex = 2; + // #endif + if (pathMode != k_AbsPath) { - const UString &front = pathParts.Front(); - bool isAbs = false; - - if (front.IsEmpty()) - isAbs = true; - else + ignoreWildcardIndex = -1; + + const unsigned numPrefixParts = GetNumPrefixParts(pathParts); + unsigned numSkipParts = numPrefixParts; + + if (pathMode != k_FullPath) { - #ifdef _WIN32 - - if (IsDriveColonName(front)) - isAbs = true; - else - - #endif - - FOR_VECTOR (i, pathParts) - { - const UString &part = pathParts[i]; - if (part == L".." || part == L".") - { - isAbs = true; - break; - } - } + if (numPrefixParts != 0 && pathParts.Size() > numPrefixParts) + numSkipParts = pathParts.Size() - 1; } - - unsigned numAbsParts = 0; - if (isAbs) - if (pathParts.Size() > 1) - numAbsParts = pathParts.Size() - 1; - else - numAbsParts = 1; - - #ifdef _WIN32 - - // \\?\ case - if (numAbsParts >= 3) { - if (pathParts[0].IsEmpty() && - pathParts[1].IsEmpty() && - pathParts[2] == L"?") + int dotsIndex = -1; + for (unsigned i = numPrefixParts; i < pathParts.Size(); i++) { - prefix = - WSTRING_PATH_SEPARATOR - WSTRING_PATH_SEPARATOR L"?" - WSTRING_PATH_SEPARATOR; - numAbsParts -= 3; - pathParts.DeleteFrontal(3); + const UString &part = pathParts[i]; + if (part == L".." || part == L".") + dotsIndex = i; } + + if (dotsIndex >= 0) + if (dotsIndex == (int)pathParts.Size() - 1) + numSkipParts = pathParts.Size(); + else + numSkipParts = pathParts.Size() - 1; } - - #endif - - if (numAbsParts > 1 && pathMode == k_FullPath) - numAbsParts = 1; - - // We can't ignore wildcard, since we don't allow wildcard in SubNodes[].Name - // if (wildcardMatching) - for (unsigned i = 0; i < numAbsParts; i++) + + for (unsigned i = 0; i < numSkipParts; i++) { { const UString &front = pathParts.Front(); - if (DoesNameContainWildcard(front)) - break; + // WIN32 doesn't support wildcards in file names + if (wildcardMatching) + if (i >= numPrefixParts && DoesNameContainWildcard(front)) + break; prefix += front; - prefix += WCHAR_PATH_SEPARATOR; + prefix.Add_PathSepar(); } pathParts.Delete(0); } @@ -554,15 +606,29 @@ void CCensor::AddItem(ECensorPathMode pathMode, bool include, const UString &pat if (index < 0) index = Pairs.Add(CPair(prefix)); + if (pathMode != k_AbsPath) + { + if (pathParts.IsEmpty() || pathParts.Size() == 1 && pathParts[0].IsEmpty()) + { + // we create universal item, if we skip all parts as prefix (like \ or L:\ ) + pathParts.Clear(); + pathParts.Add(L"*"); + forFile = true; + wildcardMatching = true; + recursive = false; + } + } + CItem item; item.PathParts = pathParts; item.ForDir = true; item.ForFile = forFile; item.Recursive = recursive; item.WildcardMatching = wildcardMatching; - Pairs[index].Head.AddItem(include, item); + Pairs[index].Head.AddItem(include, item, ignoreWildcardIndex); } +/* bool CCensor::CheckPath(bool isAltStream, const UString &path, bool isFile) const { bool finded = false; @@ -578,6 +644,7 @@ bool CCensor::CheckPath(bool isAltStream, const UString &path, bool isFile) cons } return finded; } +*/ void CCensor::ExtendExclude() { |