diff -r ea891871f481 -r bb5522e88ab2 misc/libphysfs/lzma/CPP/Common/Wildcard.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/misc/libphysfs/lzma/CPP/Common/Wildcard.cpp Mon Apr 10 12:06:43 2017 -0400 @@ -0,0 +1,458 @@ +// Common/Wildcard.cpp + +#include "StdAfx.h" + +#include "Wildcard.h" + +bool g_CaseSensitive = + #ifdef _WIN32 + false; + #else + 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"\"/:<>\\|"; + + +static inline bool IsCharDirLimiter(wchar_t c) +{ + return ( + #ifdef _WIN32 + c == kDirDelimiter1 || + #endif + c == kDirDelimiter2); +} + +int CompareFileNames(const UString &s1, const UString &s2) +{ + if (g_CaseSensitive) + return s1.Compare(s2); + return s1.CompareNoCase(s2); +} + +// ----------------------------------------- +// this function compares name with mask +// ? - any char +// * - any char or empty + +static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) +{ + for (;;) + { + wchar_t m = *mask; + wchar_t c = *name; + if (m == 0) + return (c == 0); + if (m == kAnyCharsChar) + { + if (EnhancedMaskTest(mask + 1, name)) + return true; + if (c == 0) + return false; + } + else + { + if (m == kAnyCharChar) + { + if (c == 0) + return false; + } + else if (m != c) + if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c)) + return false; + mask++; + } + name++; + } +} + +// -------------------------------------------------- +// Splits path to strings + +void SplitPathToParts(const UString &path, UStringVector &pathParts) +{ + pathParts.Clear(); + UString name; + int len = path.Length(); + if (len == 0) + return; + for (int i = 0; i < len; i++) + { + wchar_t c = path[i]; + if (IsCharDirLimiter(c)) + { + pathParts.Add(name); + name.Empty(); + } + else + name += c; + } + pathParts.Add(name); +} + +void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name) +{ + int i; + for(i = path.Length() - 1; i >= 0; i--) + if(IsCharDirLimiter(path[i])) + break; + dirPrefix = path.Left(i + 1); + name = path.Mid(i + 1); +} + +UString ExtractDirPrefixFromPath(const UString &path) +{ + int i; + for(i = path.Length() - 1; i >= 0; i--) + if(IsCharDirLimiter(path[i])) + break; + return path.Left(i + 1); +} + +UString ExtractFileNameFromPath(const UString &path) +{ + int i; + for(i = path.Length() - 1; i >= 0; i--) + if(IsCharDirLimiter(path[i])) + break; + return path.Mid(i + 1); +} + + +bool CompareWildCardWithName(const UString &mask, const UString &name) +{ + return EnhancedMaskTest(mask, name); +} + +bool DoesNameContainWildCard(const UString &path) +{ + return (path.FindOneOf(kWildCardCharSet) >= 0); +} + + +// ----------------------------------------------------------' +// NWildcard + +namespace NWildcard { + + +/* +M = MaskParts.Size(); +N = TestNameParts.Size(); + + File Dir +ForFile req M<=N [N-M, N) - + nonreq M=N [0, M) - + +ForDir req M 1) + return true; + } + return false; +} + +bool CCensorNode::AreThereIncludeItems() const +{ + if (IncludeItems.Size() > 0) + return true; + for (int i = 0; i < SubNodes.Size(); i++) + if (SubNodes[i].AreThereIncludeItems()) + return true; + return false; +} + +bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const +{ + const CObjectVector &items = include ? IncludeItems : ExcludeItems; + for (int i = 0; i < items.Size(); i++) + if (items[i].CheckPath(pathParts, isFile)) + return true; + return false; +} + +bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const +{ + if (CheckPathCurrent(false, pathParts, isFile)) + { + include = false; + return true; + } + include = true; + bool finded = CheckPathCurrent(true, pathParts, isFile); + 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)) + return true; + } + return finded; +} + +bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const +{ + UStringVector pathParts; + SplitPathToParts(path, pathParts); + return CheckPath(pathParts, isFile, include); +} + +bool CCensorNode::CheckPath(const UString &path, bool isFile) const +{ + bool include; + if(CheckPath(path, isFile, include)) + return include; + return false; +} + +bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const +{ + if (CheckPathCurrent(include, pathParts, isFile)) + return true; + if (Parent == 0) + return false; + pathParts.Insert(0, Name); + return Parent->CheckPathToRoot(include, pathParts, isFile); +} + +/* +bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const +{ + UStringVector pathParts; + SplitPathToParts(path, pathParts); + return CheckPathToRoot(include, pathParts, isFile); +} +*/ + +void CCensorNode::AddItem2(bool include, const UString &path, bool recursive) +{ + if (path.IsEmpty()) + return; + bool forFile = true; + bool forFolder = true; + UString path2 = path; + if (IsCharDirLimiter(path[path.Length() - 1])) + { + path2.Delete(path.Length() - 1); + forFile = false; + } + AddItem(include, path2, recursive, forFile, forFolder); +} + +void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) +{ + ExcludeItems += fromNodes.ExcludeItems; + for (int i = 0; i < fromNodes.SubNodes.Size(); i++) + { + const CCensorNode &node = fromNodes.SubNodes[i]; + int subNodeIndex = FindSubNode(node.Name); + if (subNodeIndex < 0) + subNodeIndex = SubNodes.Add(CCensorNode(node.Name, this)); + SubNodes[subNodeIndex].ExtendExclude(node); + } +} + +int CCensor::FindPrefix(const UString &prefix) const +{ + for (int i = 0; i < Pairs.Size(); i++) + if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) + return i; + return -1; +} + +void CCensor::AddItem(bool include, const UString &path, bool recursive) +{ + 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 + { + for (int i = 0; i < pathParts.Size(); i++) + { + const UString &part = pathParts[i]; + if (part == L".." || part == L".") + { + isAbs = true; + break; + } + } + } + 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)); + + CItem item; + item.PathParts = pathParts; + item.ForDir = true; + item.ForFile = forFile; + item.Recursive = recursive; + Pairs[index].Head.AddItem(include, item); +} + +bool CCensor::CheckPath(const UString &path, bool isFile) const +{ + bool finded = false; + for (int i = 0; i < Pairs.Size(); i++) + { + bool include; + if (Pairs[i].Head.CheckPath(path, isFile, include)) + { + if (!include) + return false; + finded = true; + } + } + return finded; +} + +void CCensor::ExtendExclude() +{ + int i; + for (i = 0; i < Pairs.Size(); i++) + if (Pairs[i].Prefix.IsEmpty()) + break; + if (i == Pairs.Size()) + return; + int index = i; + for (i = 0; i < Pairs.Size(); i++) + if (index != i) + Pairs[i].Head.ExtendExclude(Pairs[index].Head); +} + +}