(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / corlib / System.IO / SearchPattern.cs
blobb6579e6dba0b0f09ab7bc6c53b29bbe5e2ecc66d
1 //
2 // System.IO.SearchPattern.cs: Filename glob support.
3 //
4 // Author:
5 // Dan Lewis (dihlewis@yahoo.co.uk)
6 //
7 // (C) 2002
8 //
11 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
20 //
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System;
35 namespace System.IO {
37 // FIXME: there's a complication with this algorithm under windows.
38 // the pattern '*.*' matches all files (i think . matches the extension),
39 // whereas under UNIX it should only match files containing the '.' character.
41 class SearchPattern {
42 public SearchPattern (string pattern) : this (pattern, false) { }
44 public SearchPattern (string pattern, bool ignore)
46 this.ignore = ignore;
47 Compile (pattern);
50 public bool IsMatch (string text)
52 return Match (ops, text, 0);
55 // private
57 private Op ops; // the compiled pattern
58 private bool ignore; // ignore case
60 private void Compile (string pattern)
62 if (pattern == null || pattern.IndexOfAny (InvalidChars) >= 0)
63 throw new ArgumentException ("Invalid search pattern.");
65 if (pattern == "*") { // common case
66 ops = new Op (OpCode.True);
67 return;
70 ops = null;
72 int ptr = 0;
73 Op last_op = null;
74 while (ptr < pattern.Length) {
75 Op op;
77 switch (pattern [ptr]) {
78 case '?':
79 op = new Op (OpCode.AnyChar);
80 ++ ptr;
81 break;
83 case '*':
84 op = new Op (OpCode.AnyString);
85 ++ ptr;
86 break;
88 default:
89 op = new Op (OpCode.ExactString);
90 int end = pattern.IndexOfAny (WildcardChars, ptr);
91 if (end < 0)
92 end = pattern.Length;
94 op.Argument = pattern.Substring (ptr, end - ptr);
95 if (ignore)
96 op.Argument = op.Argument.ToLowerInvariant ();
98 ptr = end;
99 break;
102 if (last_op == null)
103 ops = op;
104 else
105 last_op.Next = op;
107 last_op = op;
110 if (last_op == null)
111 ops = new Op (OpCode.End);
112 else
113 last_op.Next = new Op (OpCode.End);
116 private bool Match (Op op, string text, int ptr)
118 while (op != null) {
119 switch (op.Code) {
120 case OpCode.True:
121 return true;
123 case OpCode.End:
124 if (ptr == text.Length)
125 return true;
127 return false;
129 case OpCode.ExactString:
130 int length = op.Argument.Length;
131 if (ptr + length > text.Length)
132 return false;
134 string str = text.Substring (ptr, length);
135 if (ignore)
136 str = str.ToLowerInvariant ();
138 if (str != op.Argument)
139 return false;
141 ptr += length;
142 break;
144 case OpCode.AnyChar:
145 if (++ ptr > text.Length)
146 return false;
147 break;
149 case OpCode.AnyString:
150 while (ptr <= text.Length) {
151 if (Match (op.Next, text, ptr))
152 return true;
154 ++ ptr;
157 return false;
160 op = op.Next;
163 return true;
166 // private static
168 internal static readonly char [] WildcardChars = { '*', '?' };
169 internal static readonly char [] InvalidChars = { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };
171 private class Op {
172 public Op (OpCode code)
174 this.Code = code;
175 this.Argument = null;
176 this.Next = null;
179 public OpCode Code;
180 public string Argument;
181 public Op Next;
184 private enum OpCode {
185 ExactString, // literal
186 AnyChar, // ?
187 AnyString, // *
188 End, // end of pattern
189 True // always succeeds