public static bool Match(string target, string pattern, bool caseSensitive)
{
// an empty pattern always matches.
if (pattern == null || pattern.Length == 0)
{
return true;
}
// an empty string never matches.
if (target == null || target.Length == 0)
{
return false;
}
// check for exact match
if (caseSensitive)
{
if (target == pattern)
{
return true;
}
}
else
{
if (target.ToLower() == pattern.ToLower())
{
return true;
}
}
char c;
char p;
char l;
int pIndex = 0;
int tIndex = 0;
while (tIndex < target.Length && pIndex < pattern.Length)
{
p = ConvertCase(pattern[pIndex++], caseSensitive);
if (pIndex > pattern.Length)
{
return (tIndex >= target.Length); // if end of string true
}
switch (p)
{
// match zero or more char.
case '*':
{
while (pIndex < pattern.Length && pattern[pIndex] == '*')
{
pIndex++;
}
while (tIndex < target.Length)
{
if (Match(target.Substring(tIndex++), pattern.Substring(pIndex), caseSensitive))
{
return true;
}
}
return Match(target, pattern.Substring(pIndex), caseSensitive);
}
// match any one char.
case '?':
{
// check if end of string when looking for a single character.
if (tIndex >= target.Length)
{
return false;
}
// check if end of pattern and still string data left.
if (pIndex >= pattern.Length && tIndex < target.Length-1)
{
return false;
}
tIndex++;
break;
}
// match char set
case '[':
{
c = ConvertCase(target[tIndex++], caseSensitive);
if (tIndex > target.Length)
{
return false; // syntax
}
l = '\0';
// match a char if NOT in set []
if (pattern[pIndex] == '!')
{
++pIndex;
p = ConvertCase(pattern[pIndex++], caseSensitive);
while (pIndex < pattern.Length)
{
if (p == ']') // if end of char set, then
{
break; // no match found
}
if (p == '-')
{
// check a range of chars?
p = ConvertCase(pattern[pIndex], caseSensitive);
// get high limit of range
if (pIndex > pattern.Length || p == ']')
{
return false; // syntax
}
if (c >= l && c <= p)
{
return false; // if in range, return false
}
}
l = p;
if (c == p) // if char matches this element
{
return false; // return false
}
p = ConvertCase(pattern[pIndex++], caseSensitive);
}
}
// match if char is in set []
else
{
p = ConvertCase(pattern[pIndex++], caseSensitive);
while (pIndex < pattern.Length)
{
if (p == ']') // if end of char set, then no match found
{
return false;
}
if (p == '-')
{
// check a range of chars?
p = ConvertCase(pattern[pIndex], caseSensitive);
// get high limit of range
if (pIndex > pattern.Length || p == ']')
{
return false; // syntax
}
if (c >= l && c <= p)
{
break; // if in range, move on
}
}
l = p;
if (c == p) // if char matches this element move on
{
break;
}
p = ConvertCase(pattern[pIndex++], caseSensitive);
}
while (pIndex < pattern.Length && p != ']') // got a match in char set skip to end of set
{
p = pattern[pIndex++];
}
}
break;
}
// match digit.
case '#':
{
c = target[tIndex++];
if (!Char.IsDigit(c))
{
return false; // not a digit
}
break;
}
// match exact char.
default:
{
c = ConvertCase(target[tIndex++], caseSensitive);
if (c != p) // check for exact char
{
return false; // not a match
}
// check if end of pattern and still string data left.
if (pIndex >= pattern.Length && tIndex < target.Length-1)
{
return false;
}
break;
}
}
}
return true;
}