diff options
Diffstat (limited to '3rdparty/lzma/CPP/Common/Wildcard.cpp')
-rw-r--r-- | 3rdparty/lzma/CPP/Common/Wildcard.cpp | 468 |
1 files changed, 344 insertions, 124 deletions
diff --git a/3rdparty/lzma/CPP/Common/Wildcard.cpp b/3rdparty/lzma/CPP/Common/Wildcard.cpp index 87d449714bc..a83f9f104c0 100644 --- a/3rdparty/lzma/CPP/Common/Wildcard.cpp +++ b/3rdparty/lzma/CPP/Common/Wildcard.cpp @@ -2,8 +2,6 @@ #include "StdAfx.h" -#include "../../C/Types.h" - #include "Wildcard.h" bool g_CaseSensitive = @@ -13,37 +11,29 @@ bool g_CaseSensitive = true; #endif -static const wchar_t kAnyCharsChar = L'*'; -static const wchar_t kAnyCharChar = L'?'; - -#ifdef _WIN32 -static const wchar_t kDirDelimiter1 = L'\\'; -#endif -static const wchar_t kDirDelimiter2 = L'/'; - -static const UString kWildCardCharSet = L"?*"; - -static const UString kIllegalWildCardFileNameChars= - L"\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF" - L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" - L"\"/:<>\\|"; +bool IsPath1PrefixedByPath2(const wchar_t *s1, const wchar_t *s2) +{ + if (g_CaseSensitive) + return IsString1PrefixedByString2(s1, s2); + return IsString1PrefixedByString2_NoCase(s1, s2); +} -static inline bool IsCharDirLimiter(wchar_t c) +int CompareFileNames(const wchar_t *s1, const wchar_t *s2) STRING_UNICODE_THROW { - return ( - #ifdef _WIN32 - c == kDirDelimiter1 || - #endif - c == kDirDelimiter2); + if (g_CaseSensitive) + return wcscmp(s1, s2); + return MyStringCompareNoCase(s1, s2); } -int CompareFileNames(const UString &s1, const UString &s2) +#ifndef USE_UNICODE_FSTRING +int CompareFileNames(const char *s1, const char *s2) { if (g_CaseSensitive) - return s1.Compare(s2); - return s1.CompareNoCase(s2); + return wcscmp(fs2us(s1), fs2us(s2)); + return MyStringCompareNoCase(fs2us(s1), fs2us(s2)); } +#endif // ----------------------------------------- // this function compares name with mask @@ -58,7 +48,7 @@ static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) wchar_t c = *name; if (m == 0) return (c == 0); - if (m == kAnyCharsChar) + if (m == '*') { if (EnhancedMaskTest(mask + 1, name)) return true; @@ -67,7 +57,7 @@ static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) } else { - if (m == kAnyCharChar) + if (m == '?') { if (c == 0) return false; @@ -87,61 +77,84 @@ static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) void SplitPathToParts(const UString &path, UStringVector &pathParts) { pathParts.Clear(); - UString name; - int len = path.Length(); + unsigned len = path.Len(); if (len == 0) return; - for (int i = 0; i < len; i++) - { - wchar_t c = path[i]; - if (IsCharDirLimiter(c)) + UString name; + unsigned prev = 0; + for (unsigned i = 0; i < len; i++) + if (IsPathSepar(path[i])) { + name.SetFrom(path.Ptr(prev), i - prev); pathParts.Add(name); - name.Empty(); + prev = i + 1; } - else - name += c; - } + name.SetFrom(path.Ptr(prev), len - prev); pathParts.Add(name); } -void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name) +void SplitPathToParts_2(const UString &path, UString &dirPrefix, UString &name) { - int i; - for (i = path.Length() - 1; i >= 0; i--) - if (IsCharDirLimiter(path[i])) + const wchar_t *start = path; + const wchar_t *p = start + path.Len(); + for (; p != start; p--) + if (IsPathSepar(*(p - 1))) break; - dirPrefix = path.Left(i + 1); - name = path.Mid(i + 1); + dirPrefix.SetFrom(path, (unsigned)(p - start)); + name = p; +} + +void SplitPathToParts_Smart(const UString &path, UString &dirPrefix, UString &name) +{ + const wchar_t *start = path; + const wchar_t *p = start + path.Len(); + if (p != start) + { + if (IsPathSepar(*(p - 1))) + p--; + for (; p != start; p--) + if (IsPathSepar(*(p - 1))) + break; + } + dirPrefix.SetFrom(path, (unsigned)(p - start)); + name = p; } UString ExtractDirPrefixFromPath(const UString &path) { - int i; - for (i = path.Length() - 1; i >= 0; i--) - if (IsCharDirLimiter(path[i])) + const wchar_t *start = path; + const wchar_t *p = start + path.Len(); + for (; p != start; p--) + if (IsPathSepar(*(p - 1))) break; - return path.Left(i + 1); + return path.Left((unsigned)(p - start)); } UString ExtractFileNameFromPath(const UString &path) { - int i; - for (i = path.Length() - 1; i >= 0; i--) - if (IsCharDirLimiter(path[i])) + const wchar_t *start = path; + const wchar_t *p = start + path.Len(); + for (; p != start; p--) + if (IsPathSepar(*(p - 1))) break; - return path.Mid(i + 1); + return p; } -bool CompareWildCardWithName(const UString &mask, const UString &name) +bool DoesWildcardMatchName(const UString &mask, const UString &name) { return EnhancedMaskTest(mask, name); } -bool DoesNameContainWildCard(const UString &path) +bool DoesNameContainWildcard(const UString &path) { - return (path.FindOneOf(kWildCardCharSet) >= 0); + for (unsigned i = 0; i < path.Len(); i++) + { + wchar_t c = path[i]; + if (c == '*' || c == '?') + return true; + } + return false; } @@ -150,62 +163,106 @@ bool DoesNameContainWildCard(const UString &path) namespace NWildcard { - /* + M = MaskParts.Size(); N = TestNameParts.Size(); File Dir -ForFile req M<=N [N-M, N) - - nonreq M=N [0, M) - +ForFile rec M<=N [N-M, N) - +!ForDir nonrec M=N [0, M) - -ForDir req M<N [0, M) ... [N-M-1, N-1) same as ForBoth-File - nonreq [0, M) same as ForBoth-File +ForDir rec M<N [0, M) ... [N-M-1, N-1) same as ForBoth-File +!ForFile nonrec [0, M) same as ForBoth-File -ForBoth req m<=N [0, M) ... [N-M, N) same as ForBoth-File - nonreq [0, M) same as ForBoth-File +ForFile rec m<=N [0, M) ... [N-M, N) same as ForBoth-File +ForDir nonrec [0, M) same as ForBoth-File */ +bool CItem::AreAllAllowed() const +{ + return ForFile && ForDir && WildcardMatching && PathParts.Size() == 1 && PathParts.Front() == L"*"; +} + 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; int start = 0; int finish = 0; + if (isFile) { - if (!ForDir && !Recursive && delta !=0) - return false; + if (!ForDir) + { + if (Recursive) + start = delta; + else if (delta !=0) + return false; + } if (!ForFile && delta == 0) return false; - if (!ForDir && Recursive) - start = delta; } + if (Recursive) { finish = delta; if (isFile && !ForFile) finish = delta - 1; } + for (int d = start; d <= finish; d++) { - int i; + unsigned i; for (i = 0; i < PathParts.Size(); i++) - if (!CompareWildCardWithName(PathParts[i], pathParts[i + d])) - break; + { + if (WildcardMatching) + { + if (!DoesWildcardMatchName(PathParts[i], pathParts[i + d])) + break; + } + else + { + if (CompareFileNames(PathParts[i], pathParts[i + d]) != 0) + break; + } + } if (i == PathParts.Size()) return true; } return false; } +bool CCensorNode::AreAllAllowed() const +{ + if (!Name.IsEmpty() || + !SubNodes.IsEmpty() || + !ExcludeItems.IsEmpty() || + IncludeItems.Size() != 1) + return false; + return IncludeItems.Front().AreAllAllowed(); +} + int CCensorNode::FindSubNode(const UString &name) const { - for (int i = 0; i < SubNodes.Size(); i++) + FOR_VECTOR (i, SubNodes) if (CompareFileNames(SubNodes[i].Name, name) == 0) return i; return -1; @@ -219,15 +276,24 @@ 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) { + if (item.PathParts.Size() != 0 && item.WildcardMatching) + { + if (!DoesNameContainWildcard(item.PathParts.Front())) + item.WildcardMatching = false; + } AddItemSimple(include, item); return; } const UString &front = item.PathParts.Front(); - if (DoesNameContainWildCard(front)) + + // WIN32 doesn't support wildcards in file names + if (item.WildcardMatching + && ignoreWildcardIndex != 0 + && DoesNameContainWildcard(front)) { AddItemSimple(include, item); return; @@ -236,22 +302,23 @@ 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) +void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir, bool wildcardMatching) { CItem item; SplitPathToParts(path, item.PathParts); item.Recursive = recursive; item.ForFile = forFile; item.ForDir = forDir; + item.WildcardMatching = wildcardMatching; AddItem(include, item); } bool CCensorNode::NeedCheckSubDirs() const { - for (int i = 0; i < IncludeItems.Size(); i++) + FOR_VECTOR (i, IncludeItems) { const CItem &item = IncludeItems[i]; if (item.Recursive || item.PathParts.Size() > 1) @@ -264,7 +331,7 @@ bool CCensorNode::AreThereIncludeItems() const { if (IncludeItems.Size() > 0) return true; - for (int i = 0; i < SubNodes.Size(); i++) + FOR_VECTOR (i, SubNodes) if (SubNodes[i].AreThereIncludeItems()) return true; return false; @@ -273,13 +340,13 @@ bool CCensorNode::AreThereIncludeItems() const bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const { const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems; - for (int i = 0; i < items.Size(); i++) + FOR_VECTOR (i, items) if (items[i].CheckPath(pathParts, isFile)) return true; return false; } -bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const +bool CCensorNode::CheckPathVect(const UStringVector &pathParts, bool isFile, bool &include) const { if (CheckPathCurrent(false, pathParts, isFile)) { @@ -288,33 +355,50 @@ bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include } include = true; bool finded = CheckPathCurrent(true, pathParts, isFile); - if (pathParts.Size() == 1) + if (pathParts.Size() <= 1) return finded; int index = FindSubNode(pathParts.Front()); if (index >= 0) { UStringVector pathParts2 = pathParts; pathParts2.Delete(0); - if (SubNodes[index].CheckPath(pathParts2, isFile, include)) + if (SubNodes[index].CheckPathVect(pathParts2, isFile, include)) return true; } return finded; } -bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const +/* +bool CCensorNode::CheckPath2(bool isAltStream, const UString &path, bool isFile, bool &include) const { UStringVector pathParts; SplitPathToParts(path, pathParts); - return CheckPath(pathParts, isFile, include); + if (CheckPathVect(pathParts, isFile, include)) + { + if (!include || !isAltStream) + return true; + } + if (isAltStream && !pathParts.IsEmpty()) + { + UString &back = pathParts.Back(); + int pos = back.Find(L':'); + if (pos > 0) + { + back.DeleteFrom(pos); + return CheckPathVect(pathParts, isFile, include); + } + } + return false; } -bool CCensorNode::CheckPath(const UString &path, bool isFile) const +bool CCensorNode::CheckPath(bool isAltStream, const UString &path, bool isFile) const { bool include; - if (CheckPath(path, isFile, include)) + if (CheckPath2(isAltStream, path, isFile, include)) return include; return false; } +*/ bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const { @@ -335,25 +419,25 @@ bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile } */ -void CCensorNode::AddItem2(bool include, const UString &path, bool recursive) +void CCensorNode::AddItem2(bool include, const UString &path, bool recursive, bool wildcardMatching) { if (path.IsEmpty()) return; bool forFile = true; bool forFolder = true; UString path2 = path; - if (IsCharDirLimiter(path.Back())) + if (IsPathSepar(path.Back())) { path2.DeleteBack(); forFile = false; } - AddItem(include, path2, recursive, forFile, forFolder); + AddItem(include, path2, recursive, forFile, forFolder, wildcardMatching); } void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) { ExcludeItems += fromNodes.ExcludeItems; - for (int i = 0; i < fromNodes.SubNodes.Size(); i++) + FOR_VECTOR (i, fromNodes.SubNodes) { const CCensorNode &node = fromNodes.SubNodes[i]; int subNodeIndex = FindSubNode(node.Name); @@ -365,77 +449,193 @@ void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) int CCensor::FindPrefix(const UString &prefix) const { - for (int i = 0; i < Pairs.Size(); i++) + FOR_VECTOR (i, Pairs) if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) return i; return -1; } -void CCensor::AddItem(bool include, const UString &path, bool recursive) +#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()) { forFile = false; pathParts.DeleteBack(); } - const UString &front = pathParts.Front(); - bool isAbs = false; - if (front.IsEmpty()) - isAbs = true; - else if (front.Length() == 2 && front[1] == L':') - isAbs = true; - else + + 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) { - for (int i = 0; i < pathParts.Size(); i++) + ignoreWildcardIndex = -1; + + const unsigned numPrefixParts = GetNumPrefixParts(pathParts); + unsigned numSkipParts = numPrefixParts; + + if (pathMode != k_FullPath) + { + if (numPrefixParts != 0 && pathParts.Size() > numPrefixParts) + numSkipParts = pathParts.Size() - 1; + } { - const UString &part = pathParts[i]; - if (part == L".." || part == L".") + int dotsIndex = -1; + for (unsigned i = numPrefixParts; i < pathParts.Size(); i++) { - isAbs = true; - break; + 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; + } + + for (unsigned i = 0; i < numSkipParts; i++) + { + { + const UString &front = pathParts.Front(); + // WIN32 doesn't support wildcards in file names + if (wildcardMatching) + if (i >= numPrefixParts && DoesNameContainWildcard(front)) + break; + prefix += front; + prefix.Add_PathSepar(); + } + pathParts.Delete(0); } } - int numAbsParts = 0; - if (isAbs) - if (pathParts.Size() > 1) - numAbsParts = pathParts.Size() - 1; - else - numAbsParts = 1; - UString prefix; - for (int i = 0; i < numAbsParts; i++) - { - const UString &front = pathParts.Front(); - if (DoesNameContainWildCard(front)) - break; - prefix += front; - prefix += WCHAR_PATH_SEPARATOR; - pathParts.Delete(0); - } + int index = FindPrefix(prefix); 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; - Pairs[index].Head.AddItem(include, item); + item.WildcardMatching = wildcardMatching; + Pairs[index].Head.AddItem(include, item, ignoreWildcardIndex); } -bool CCensor::CheckPath(const UString &path, bool isFile) const +/* +bool CCensor::CheckPath(bool isAltStream, const UString &path, bool isFile) const { bool finded = false; - for (int i = 0; i < Pairs.Size(); i++) + FOR_VECTOR (i, Pairs) { bool include; - if (Pairs[i].Head.CheckPath(path, isFile, include)) + if (Pairs[i].Head.CheckPath2(isAltStream, path, isFile, include)) { if (!include) return false; @@ -444,19 +644,39 @@ bool CCensor::CheckPath(const UString &path, bool isFile) const } return finded; } +*/ void CCensor::ExtendExclude() { - int i; + unsigned i; for (i = 0; i < Pairs.Size(); i++) if (Pairs[i].Prefix.IsEmpty()) break; if (i == Pairs.Size()) return; - int index = i; + unsigned index = i; for (i = 0; i < Pairs.Size(); i++) if (index != i) Pairs[i].Head.ExtendExclude(Pairs[index].Head); } +void CCensor::AddPathsToCensor(ECensorPathMode censorPathMode) +{ + FOR_VECTOR(i, CensorPaths) + { + const CCensorPath &cp = CensorPaths[i]; + AddItem(censorPathMode, cp.Include, cp.Path, cp.Recursive, cp.WildcardMatching); + } + CensorPaths.Clear(); +} + +void CCensor::AddPreItem(bool include, const UString &path, bool recursive, bool wildcardMatching) +{ + CCensorPath &cp = CensorPaths.AddNew(); + cp.Path = path; + cp.Include = include; + cp.Recursive = recursive; + cp.WildcardMatching = wildcardMatching; +} + } |