Mercurial > vba-clojure
diff src/win32/7zip/7z/CPP/Common/Wildcard.cpp @ 1:f9f4f1b99eed
importing src directory
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:27 -0600 |
parents | |
children |
line wrap: on
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/win32/7zip/7z/CPP/Common/Wildcard.cpp Sat Mar 03 10:31:27 2012 -0600 1.3 @@ -0,0 +1,458 @@ 1.4 +// Common/Wildcard.cpp 1.5 + 1.6 +#include "StdAfx.h" 1.7 + 1.8 +#include "Wildcard.h" 1.9 + 1.10 +bool g_CaseSensitive = 1.11 + #ifdef _WIN32 1.12 + false; 1.13 + #else 1.14 + true; 1.15 + #endif 1.16 + 1.17 +static const wchar_t kAnyCharsChar = L'*'; 1.18 +static const wchar_t kAnyCharChar = L'?'; 1.19 + 1.20 +#ifdef _WIN32 1.21 +static const wchar_t kDirDelimiter1 = L'\\'; 1.22 +#endif 1.23 +static const wchar_t kDirDelimiter2 = L'/'; 1.24 + 1.25 +static const UString kWildCardCharSet = L"?*"; 1.26 + 1.27 +static const UString kIllegalWildCardFileNameChars= 1.28 + L"\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF" 1.29 + L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F" 1.30 + L"\"/:<>\\|"; 1.31 + 1.32 + 1.33 +static inline bool IsCharDirLimiter(wchar_t c) 1.34 +{ 1.35 + return ( 1.36 + #ifdef _WIN32 1.37 + c == kDirDelimiter1 || 1.38 + #endif 1.39 + c == kDirDelimiter2); 1.40 +} 1.41 + 1.42 +int CompareFileNames(const UString &s1, const UString &s2) 1.43 +{ 1.44 + if (g_CaseSensitive) 1.45 + return s1.Compare(s2); 1.46 + return s1.CompareNoCase(s2); 1.47 +} 1.48 + 1.49 +// ----------------------------------------- 1.50 +// this function compares name with mask 1.51 +// ? - any char 1.52 +// * - any char or empty 1.53 + 1.54 +static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name) 1.55 +{ 1.56 + for (;;) 1.57 + { 1.58 + wchar_t m = *mask; 1.59 + wchar_t c = *name; 1.60 + if (m == 0) 1.61 + return (c == 0); 1.62 + if (m == kAnyCharsChar) 1.63 + { 1.64 + if (EnhancedMaskTest(mask + 1, name)) 1.65 + return true; 1.66 + if (c == 0) 1.67 + return false; 1.68 + } 1.69 + else 1.70 + { 1.71 + if (m == kAnyCharChar) 1.72 + { 1.73 + if (c == 0) 1.74 + return false; 1.75 + } 1.76 + else if (m != c) 1.77 + if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c)) 1.78 + return false; 1.79 + mask++; 1.80 + } 1.81 + name++; 1.82 + } 1.83 +} 1.84 + 1.85 +// -------------------------------------------------- 1.86 +// Splits path to strings 1.87 + 1.88 +void SplitPathToParts(const UString &path, UStringVector &pathParts) 1.89 +{ 1.90 + pathParts.Clear(); 1.91 + UString name; 1.92 + int len = path.Length(); 1.93 + if (len == 0) 1.94 + return; 1.95 + for (int i = 0; i < len; i++) 1.96 + { 1.97 + wchar_t c = path[i]; 1.98 + if (IsCharDirLimiter(c)) 1.99 + { 1.100 + pathParts.Add(name); 1.101 + name.Empty(); 1.102 + } 1.103 + else 1.104 + name += c; 1.105 + } 1.106 + pathParts.Add(name); 1.107 +} 1.108 + 1.109 +void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name) 1.110 +{ 1.111 + int i; 1.112 + for (i = path.Length() - 1; i >= 0; i--) 1.113 + if (IsCharDirLimiter(path[i])) 1.114 + break; 1.115 + dirPrefix = path.Left(i + 1); 1.116 + name = path.Mid(i + 1); 1.117 +} 1.118 + 1.119 +UString ExtractDirPrefixFromPath(const UString &path) 1.120 +{ 1.121 + int i; 1.122 + for (i = path.Length() - 1; i >= 0; i--) 1.123 + if (IsCharDirLimiter(path[i])) 1.124 + break; 1.125 + return path.Left(i + 1); 1.126 +} 1.127 + 1.128 +UString ExtractFileNameFromPath(const UString &path) 1.129 +{ 1.130 + int i; 1.131 + for (i = path.Length() - 1; i >= 0; i--) 1.132 + if (IsCharDirLimiter(path[i])) 1.133 + break; 1.134 + return path.Mid(i + 1); 1.135 +} 1.136 + 1.137 + 1.138 +bool CompareWildCardWithName(const UString &mask, const UString &name) 1.139 +{ 1.140 + return EnhancedMaskTest(mask, name); 1.141 +} 1.142 + 1.143 +bool DoesNameContainWildCard(const UString &path) 1.144 +{ 1.145 + return (path.FindOneOf(kWildCardCharSet) >= 0); 1.146 +} 1.147 + 1.148 + 1.149 +// ----------------------------------------------------------' 1.150 +// NWildcard 1.151 + 1.152 +namespace NWildcard { 1.153 + 1.154 + 1.155 +/* 1.156 +M = MaskParts.Size(); 1.157 +N = TestNameParts.Size(); 1.158 + 1.159 + File Dir 1.160 +ForFile req M<=N [N-M, N) - 1.161 + nonreq M=N [0, M) - 1.162 + 1.163 +ForDir req M<N [0, M) ... [N-M-1, N-1) same as ForBoth-File 1.164 + nonreq [0, M) same as ForBoth-File 1.165 + 1.166 +ForBoth req m<=N [0, M) ... [N-M, N) same as ForBoth-File 1.167 + nonreq [0, M) same as ForBoth-File 1.168 + 1.169 +*/ 1.170 + 1.171 +bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const 1.172 +{ 1.173 + if (!isFile && !ForDir) 1.174 + return false; 1.175 + int delta = (int)pathParts.Size() - (int)PathParts.Size(); 1.176 + if (delta < 0) 1.177 + return false; 1.178 + int start = 0; 1.179 + int finish = 0; 1.180 + if (isFile) 1.181 + { 1.182 + if (!ForDir && !Recursive && delta !=0) 1.183 + return false; 1.184 + if (!ForFile && delta == 0) 1.185 + return false; 1.186 + if (!ForDir && Recursive) 1.187 + start = delta; 1.188 + } 1.189 + if (Recursive) 1.190 + { 1.191 + finish = delta; 1.192 + if (isFile && !ForFile) 1.193 + finish = delta - 1; 1.194 + } 1.195 + for (int d = start; d <= finish; d++) 1.196 + { 1.197 + int i; 1.198 + for (i = 0; i < PathParts.Size(); i++) 1.199 + if (!CompareWildCardWithName(PathParts[i], pathParts[i + d])) 1.200 + break; 1.201 + if (i == PathParts.Size()) 1.202 + return true; 1.203 + } 1.204 + return false; 1.205 +} 1.206 + 1.207 +int CCensorNode::FindSubNode(const UString &name) const 1.208 +{ 1.209 + for (int i = 0; i < SubNodes.Size(); i++) 1.210 + if (CompareFileNames(SubNodes[i].Name, name) == 0) 1.211 + return i; 1.212 + return -1; 1.213 +} 1.214 + 1.215 +void CCensorNode::AddItemSimple(bool include, CItem &item) 1.216 +{ 1.217 + if (include) 1.218 + IncludeItems.Add(item); 1.219 + else 1.220 + ExcludeItems.Add(item); 1.221 +} 1.222 + 1.223 +void CCensorNode::AddItem(bool include, CItem &item) 1.224 +{ 1.225 + if (item.PathParts.Size() <= 1) 1.226 + { 1.227 + AddItemSimple(include, item); 1.228 + return; 1.229 + } 1.230 + const UString &front = item.PathParts.Front(); 1.231 + if (DoesNameContainWildCard(front)) 1.232 + { 1.233 + AddItemSimple(include, item); 1.234 + return; 1.235 + } 1.236 + int index = FindSubNode(front); 1.237 + if (index < 0) 1.238 + index = SubNodes.Add(CCensorNode(front, this)); 1.239 + item.PathParts.Delete(0); 1.240 + SubNodes[index].AddItem(include, item); 1.241 +} 1.242 + 1.243 +void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir) 1.244 +{ 1.245 + CItem item; 1.246 + SplitPathToParts(path, item.PathParts); 1.247 + item.Recursive = recursive; 1.248 + item.ForFile = forFile; 1.249 + item.ForDir = forDir; 1.250 + AddItem(include, item); 1.251 +} 1.252 + 1.253 +bool CCensorNode::NeedCheckSubDirs() const 1.254 +{ 1.255 + for (int i = 0; i < IncludeItems.Size(); i++) 1.256 + { 1.257 + const CItem &item = IncludeItems[i]; 1.258 + if (item.Recursive || item.PathParts.Size() > 1) 1.259 + return true; 1.260 + } 1.261 + return false; 1.262 +} 1.263 + 1.264 +bool CCensorNode::AreThereIncludeItems() const 1.265 +{ 1.266 + if (IncludeItems.Size() > 0) 1.267 + return true; 1.268 + for (int i = 0; i < SubNodes.Size(); i++) 1.269 + if (SubNodes[i].AreThereIncludeItems()) 1.270 + return true; 1.271 + return false; 1.272 +} 1.273 + 1.274 +bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const 1.275 +{ 1.276 + const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems; 1.277 + for (int i = 0; i < items.Size(); i++) 1.278 + if (items[i].CheckPath(pathParts, isFile)) 1.279 + return true; 1.280 + return false; 1.281 +} 1.282 + 1.283 +bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const 1.284 +{ 1.285 + if (CheckPathCurrent(false, pathParts, isFile)) 1.286 + { 1.287 + include = false; 1.288 + return true; 1.289 + } 1.290 + include = true; 1.291 + bool finded = CheckPathCurrent(true, pathParts, isFile); 1.292 + if (pathParts.Size() == 1) 1.293 + return finded; 1.294 + int index = FindSubNode(pathParts.Front()); 1.295 + if (index >= 0) 1.296 + { 1.297 + UStringVector pathParts2 = pathParts; 1.298 + pathParts2.Delete(0); 1.299 + if (SubNodes[index].CheckPath(pathParts2, isFile, include)) 1.300 + return true; 1.301 + } 1.302 + return finded; 1.303 +} 1.304 + 1.305 +bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const 1.306 +{ 1.307 + UStringVector pathParts; 1.308 + SplitPathToParts(path, pathParts); 1.309 + return CheckPath(pathParts, isFile, include); 1.310 +} 1.311 + 1.312 +bool CCensorNode::CheckPath(const UString &path, bool isFile) const 1.313 +{ 1.314 + bool include; 1.315 + if (CheckPath(path, isFile, include)) 1.316 + return include; 1.317 + return false; 1.318 +} 1.319 + 1.320 +bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const 1.321 +{ 1.322 + if (CheckPathCurrent(include, pathParts, isFile)) 1.323 + return true; 1.324 + if (Parent == 0) 1.325 + return false; 1.326 + pathParts.Insert(0, Name); 1.327 + return Parent->CheckPathToRoot(include, pathParts, isFile); 1.328 +} 1.329 + 1.330 +/* 1.331 +bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const 1.332 +{ 1.333 + UStringVector pathParts; 1.334 + SplitPathToParts(path, pathParts); 1.335 + return CheckPathToRoot(include, pathParts, isFile); 1.336 +} 1.337 +*/ 1.338 + 1.339 +void CCensorNode::AddItem2(bool include, const UString &path, bool recursive) 1.340 +{ 1.341 + if (path.IsEmpty()) 1.342 + return; 1.343 + bool forFile = true; 1.344 + bool forFolder = true; 1.345 + UString path2 = path; 1.346 + if (IsCharDirLimiter(path[path.Length() - 1])) 1.347 + { 1.348 + path2.Delete(path.Length() - 1); 1.349 + forFile = false; 1.350 + } 1.351 + AddItem(include, path2, recursive, forFile, forFolder); 1.352 +} 1.353 + 1.354 +void CCensorNode::ExtendExclude(const CCensorNode &fromNodes) 1.355 +{ 1.356 + ExcludeItems += fromNodes.ExcludeItems; 1.357 + for (int i = 0; i < fromNodes.SubNodes.Size(); i++) 1.358 + { 1.359 + const CCensorNode &node = fromNodes.SubNodes[i]; 1.360 + int subNodeIndex = FindSubNode(node.Name); 1.361 + if (subNodeIndex < 0) 1.362 + subNodeIndex = SubNodes.Add(CCensorNode(node.Name, this)); 1.363 + SubNodes[subNodeIndex].ExtendExclude(node); 1.364 + } 1.365 +} 1.366 + 1.367 +int CCensor::FindPrefix(const UString &prefix) const 1.368 +{ 1.369 + for (int i = 0; i < Pairs.Size(); i++) 1.370 + if (CompareFileNames(Pairs[i].Prefix, prefix) == 0) 1.371 + return i; 1.372 + return -1; 1.373 +} 1.374 + 1.375 +void CCensor::AddItem(bool include, const UString &path, bool recursive) 1.376 +{ 1.377 + UStringVector pathParts; 1.378 + SplitPathToParts(path, pathParts); 1.379 + bool forFile = true; 1.380 + if (pathParts.Back().IsEmpty()) 1.381 + { 1.382 + forFile = false; 1.383 + pathParts.DeleteBack(); 1.384 + } 1.385 + const UString &front = pathParts.Front(); 1.386 + bool isAbs = false; 1.387 + if (front.IsEmpty()) 1.388 + isAbs = true; 1.389 + else if (front.Length() == 2 && front[1] == L':') 1.390 + isAbs = true; 1.391 + else 1.392 + { 1.393 + for (int i = 0; i < pathParts.Size(); i++) 1.394 + { 1.395 + const UString &part = pathParts[i]; 1.396 + if (part == L".." || part == L".") 1.397 + { 1.398 + isAbs = true; 1.399 + break; 1.400 + } 1.401 + } 1.402 + } 1.403 + int numAbsParts = 0; 1.404 + if (isAbs) 1.405 + if (pathParts.Size() > 1) 1.406 + numAbsParts = pathParts.Size() - 1; 1.407 + else 1.408 + numAbsParts = 1; 1.409 + UString prefix; 1.410 + for (int i = 0; i < numAbsParts; i++) 1.411 + { 1.412 + const UString &front = pathParts.Front(); 1.413 + if (DoesNameContainWildCard(front)) 1.414 + break; 1.415 + prefix += front; 1.416 + prefix += WCHAR_PATH_SEPARATOR; 1.417 + pathParts.Delete(0); 1.418 + } 1.419 + int index = FindPrefix(prefix); 1.420 + if (index < 0) 1.421 + index = Pairs.Add(CPair(prefix)); 1.422 + 1.423 + CItem item; 1.424 + item.PathParts = pathParts; 1.425 + item.ForDir = true; 1.426 + item.ForFile = forFile; 1.427 + item.Recursive = recursive; 1.428 + Pairs[index].Head.AddItem(include, item); 1.429 +} 1.430 + 1.431 +bool CCensor::CheckPath(const UString &path, bool isFile) const 1.432 +{ 1.433 + bool finded = false; 1.434 + for (int i = 0; i < Pairs.Size(); i++) 1.435 + { 1.436 + bool include; 1.437 + if (Pairs[i].Head.CheckPath(path, isFile, include)) 1.438 + { 1.439 + if (!include) 1.440 + return false; 1.441 + finded = true; 1.442 + } 1.443 + } 1.444 + return finded; 1.445 +} 1.446 + 1.447 +void CCensor::ExtendExclude() 1.448 +{ 1.449 + int i; 1.450 + for (i = 0; i < Pairs.Size(); i++) 1.451 + if (Pairs[i].Prefix.IsEmpty()) 1.452 + break; 1.453 + if (i == Pairs.Size()) 1.454 + return; 1.455 + int index = i; 1.456 + for (i = 0; i < Pairs.Size(); i++) 1.457 + if (index != i) 1.458 + Pairs[i].Head.ExtendExclude(Pairs[index].Head); 1.459 +} 1.460 + 1.461 +}