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