Mercurial > vba-clojure
view 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 source
1 // Common/Wildcard.cpp3 #include "StdAfx.h"5 #include "Wildcard.h"7 bool g_CaseSensitive =8 #ifdef _WIN329 false;10 #else11 true;12 #endif14 static const wchar_t kAnyCharsChar = L'*';15 static const wchar_t kAnyCharChar = L'?';17 #ifdef _WIN3218 static const wchar_t kDirDelimiter1 = L'\\';19 #endif20 static const wchar_t kDirDelimiter2 = L'/';22 static const UString kWildCardCharSet = L"?*";24 static const UString kIllegalWildCardFileNameChars=25 L"\x1\x2\x3\x4\x5\x6\x7\x8\x9\xA\xB\xC\xD\xE\xF"26 L"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"27 L"\"/:<>\\|";30 static inline bool IsCharDirLimiter(wchar_t c)31 {32 return (33 #ifdef _WIN3234 c == kDirDelimiter1 ||35 #endif36 c == kDirDelimiter2);37 }39 int CompareFileNames(const UString &s1, const UString &s2)40 {41 if (g_CaseSensitive)42 return s1.Compare(s2);43 return s1.CompareNoCase(s2);44 }46 // -----------------------------------------47 // this function compares name with mask48 // ? - any char49 // * - any char or empty51 static bool EnhancedMaskTest(const wchar_t *mask, const wchar_t *name)52 {53 for (;;)54 {55 wchar_t m = *mask;56 wchar_t c = *name;57 if (m == 0)58 return (c == 0);59 if (m == kAnyCharsChar)60 {61 if (EnhancedMaskTest(mask + 1, name))62 return true;63 if (c == 0)64 return false;65 }66 else67 {68 if (m == kAnyCharChar)69 {70 if (c == 0)71 return false;72 }73 else if (m != c)74 if (g_CaseSensitive || MyCharUpper(m) != MyCharUpper(c))75 return false;76 mask++;77 }78 name++;79 }80 }82 // --------------------------------------------------83 // Splits path to strings85 void SplitPathToParts(const UString &path, UStringVector &pathParts)86 {87 pathParts.Clear();88 UString name;89 int len = path.Length();90 if (len == 0)91 return;92 for (int i = 0; i < len; i++)93 {94 wchar_t c = path[i];95 if (IsCharDirLimiter(c))96 {97 pathParts.Add(name);98 name.Empty();99 }100 else101 name += c;102 }103 pathParts.Add(name);104 }106 void SplitPathToParts(const UString &path, UString &dirPrefix, UString &name)107 {108 int i;109 for (i = path.Length() - 1; i >= 0; i--)110 if (IsCharDirLimiter(path[i]))111 break;112 dirPrefix = path.Left(i + 1);113 name = path.Mid(i + 1);114 }116 UString ExtractDirPrefixFromPath(const UString &path)117 {118 int i;119 for (i = path.Length() - 1; i >= 0; i--)120 if (IsCharDirLimiter(path[i]))121 break;122 return path.Left(i + 1);123 }125 UString ExtractFileNameFromPath(const UString &path)126 {127 int i;128 for (i = path.Length() - 1; i >= 0; i--)129 if (IsCharDirLimiter(path[i]))130 break;131 return path.Mid(i + 1);132 }135 bool CompareWildCardWithName(const UString &mask, const UString &name)136 {137 return EnhancedMaskTest(mask, name);138 }140 bool DoesNameContainWildCard(const UString &path)141 {142 return (path.FindOneOf(kWildCardCharSet) >= 0);143 }146 // ----------------------------------------------------------'147 // NWildcard149 namespace NWildcard {152 /*153 M = MaskParts.Size();154 N = TestNameParts.Size();156 File Dir157 ForFile req M<=N [N-M, N) -158 nonreq M=N [0, M) -160 ForDir req M<N [0, M) ... [N-M-1, N-1) same as ForBoth-File161 nonreq [0, M) same as ForBoth-File163 ForBoth req m<=N [0, M) ... [N-M, N) same as ForBoth-File164 nonreq [0, M) same as ForBoth-File166 */168 bool CItem::CheckPath(const UStringVector &pathParts, bool isFile) const169 {170 if (!isFile && !ForDir)171 return false;172 int delta = (int)pathParts.Size() - (int)PathParts.Size();173 if (delta < 0)174 return false;175 int start = 0;176 int finish = 0;177 if (isFile)178 {179 if (!ForDir && !Recursive && delta !=0)180 return false;181 if (!ForFile && delta == 0)182 return false;183 if (!ForDir && Recursive)184 start = delta;185 }186 if (Recursive)187 {188 finish = delta;189 if (isFile && !ForFile)190 finish = delta - 1;191 }192 for (int d = start; d <= finish; d++)193 {194 int i;195 for (i = 0; i < PathParts.Size(); i++)196 if (!CompareWildCardWithName(PathParts[i], pathParts[i + d]))197 break;198 if (i == PathParts.Size())199 return true;200 }201 return false;202 }204 int CCensorNode::FindSubNode(const UString &name) const205 {206 for (int i = 0; i < SubNodes.Size(); i++)207 if (CompareFileNames(SubNodes[i].Name, name) == 0)208 return i;209 return -1;210 }212 void CCensorNode::AddItemSimple(bool include, CItem &item)213 {214 if (include)215 IncludeItems.Add(item);216 else217 ExcludeItems.Add(item);218 }220 void CCensorNode::AddItem(bool include, CItem &item)221 {222 if (item.PathParts.Size() <= 1)223 {224 AddItemSimple(include, item);225 return;226 }227 const UString &front = item.PathParts.Front();228 if (DoesNameContainWildCard(front))229 {230 AddItemSimple(include, item);231 return;232 }233 int index = FindSubNode(front);234 if (index < 0)235 index = SubNodes.Add(CCensorNode(front, this));236 item.PathParts.Delete(0);237 SubNodes[index].AddItem(include, item);238 }240 void CCensorNode::AddItem(bool include, const UString &path, bool recursive, bool forFile, bool forDir)241 {242 CItem item;243 SplitPathToParts(path, item.PathParts);244 item.Recursive = recursive;245 item.ForFile = forFile;246 item.ForDir = forDir;247 AddItem(include, item);248 }250 bool CCensorNode::NeedCheckSubDirs() const251 {252 for (int i = 0; i < IncludeItems.Size(); i++)253 {254 const CItem &item = IncludeItems[i];255 if (item.Recursive || item.PathParts.Size() > 1)256 return true;257 }258 return false;259 }261 bool CCensorNode::AreThereIncludeItems() const262 {263 if (IncludeItems.Size() > 0)264 return true;265 for (int i = 0; i < SubNodes.Size(); i++)266 if (SubNodes[i].AreThereIncludeItems())267 return true;268 return false;269 }271 bool CCensorNode::CheckPathCurrent(bool include, const UStringVector &pathParts, bool isFile) const272 {273 const CObjectVector<CItem> &items = include ? IncludeItems : ExcludeItems;274 for (int i = 0; i < items.Size(); i++)275 if (items[i].CheckPath(pathParts, isFile))276 return true;277 return false;278 }280 bool CCensorNode::CheckPath(UStringVector &pathParts, bool isFile, bool &include) const281 {282 if (CheckPathCurrent(false, pathParts, isFile))283 {284 include = false;285 return true;286 }287 include = true;288 bool finded = CheckPathCurrent(true, pathParts, isFile);289 if (pathParts.Size() == 1)290 return finded;291 int index = FindSubNode(pathParts.Front());292 if (index >= 0)293 {294 UStringVector pathParts2 = pathParts;295 pathParts2.Delete(0);296 if (SubNodes[index].CheckPath(pathParts2, isFile, include))297 return true;298 }299 return finded;300 }302 bool CCensorNode::CheckPath(const UString &path, bool isFile, bool &include) const303 {304 UStringVector pathParts;305 SplitPathToParts(path, pathParts);306 return CheckPath(pathParts, isFile, include);307 }309 bool CCensorNode::CheckPath(const UString &path, bool isFile) const310 {311 bool include;312 if (CheckPath(path, isFile, include))313 return include;314 return false;315 }317 bool CCensorNode::CheckPathToRoot(bool include, UStringVector &pathParts, bool isFile) const318 {319 if (CheckPathCurrent(include, pathParts, isFile))320 return true;321 if (Parent == 0)322 return false;323 pathParts.Insert(0, Name);324 return Parent->CheckPathToRoot(include, pathParts, isFile);325 }327 /*328 bool CCensorNode::CheckPathToRoot(bool include, const UString &path, bool isFile) const329 {330 UStringVector pathParts;331 SplitPathToParts(path, pathParts);332 return CheckPathToRoot(include, pathParts, isFile);333 }334 */336 void CCensorNode::AddItem2(bool include, const UString &path, bool recursive)337 {338 if (path.IsEmpty())339 return;340 bool forFile = true;341 bool forFolder = true;342 UString path2 = path;343 if (IsCharDirLimiter(path[path.Length() - 1]))344 {345 path2.Delete(path.Length() - 1);346 forFile = false;347 }348 AddItem(include, path2, recursive, forFile, forFolder);349 }351 void CCensorNode::ExtendExclude(const CCensorNode &fromNodes)352 {353 ExcludeItems += fromNodes.ExcludeItems;354 for (int i = 0; i < fromNodes.SubNodes.Size(); i++)355 {356 const CCensorNode &node = fromNodes.SubNodes[i];357 int subNodeIndex = FindSubNode(node.Name);358 if (subNodeIndex < 0)359 subNodeIndex = SubNodes.Add(CCensorNode(node.Name, this));360 SubNodes[subNodeIndex].ExtendExclude(node);361 }362 }364 int CCensor::FindPrefix(const UString &prefix) const365 {366 for (int i = 0; i < Pairs.Size(); i++)367 if (CompareFileNames(Pairs[i].Prefix, prefix) == 0)368 return i;369 return -1;370 }372 void CCensor::AddItem(bool include, const UString &path, bool recursive)373 {374 UStringVector pathParts;375 SplitPathToParts(path, pathParts);376 bool forFile = true;377 if (pathParts.Back().IsEmpty())378 {379 forFile = false;380 pathParts.DeleteBack();381 }382 const UString &front = pathParts.Front();383 bool isAbs = false;384 if (front.IsEmpty())385 isAbs = true;386 else if (front.Length() == 2 && front[1] == L':')387 isAbs = true;388 else389 {390 for (int i = 0; i < pathParts.Size(); i++)391 {392 const UString &part = pathParts[i];393 if (part == L".." || part == L".")394 {395 isAbs = true;396 break;397 }398 }399 }400 int numAbsParts = 0;401 if (isAbs)402 if (pathParts.Size() > 1)403 numAbsParts = pathParts.Size() - 1;404 else405 numAbsParts = 1;406 UString prefix;407 for (int i = 0; i < numAbsParts; i++)408 {409 const UString &front = pathParts.Front();410 if (DoesNameContainWildCard(front))411 break;412 prefix += front;413 prefix += WCHAR_PATH_SEPARATOR;414 pathParts.Delete(0);415 }416 int index = FindPrefix(prefix);417 if (index < 0)418 index = Pairs.Add(CPair(prefix));420 CItem item;421 item.PathParts = pathParts;422 item.ForDir = true;423 item.ForFile = forFile;424 item.Recursive = recursive;425 Pairs[index].Head.AddItem(include, item);426 }428 bool CCensor::CheckPath(const UString &path, bool isFile) const429 {430 bool finded = false;431 for (int i = 0; i < Pairs.Size(); i++)432 {433 bool include;434 if (Pairs[i].Head.CheckPath(path, isFile, include))435 {436 if (!include)437 return false;438 finded = true;439 }440 }441 return finded;442 }444 void CCensor::ExtendExclude()445 {446 int i;447 for (i = 0; i < Pairs.Size(); i++)448 if (Pairs[i].Prefix.IsEmpty())449 break;450 if (i == Pairs.Size())451 return;452 int index = i;453 for (i = 0; i < Pairs.Size(); i++)454 if (index != i)455 Pairs[i].Head.ExtendExclude(Pairs[index].Head);456 }458 }