This is much simpler: fewer new strings created, no recursion. And it allows the caller to specify how to do a string comparison.
public static bool
WildcardMatch
(
this string Subject
,
string Pattern
,
System.StringComparison StringComparison
)
{
bool result = true ;
if ( Subject == null )
{
throw ( new System.ArgumentNullException ( "Subject" , "Subject must not be null" ) ) ;
}
if ( Pattern == null )
{
throw ( new System.ArgumentNullException ( "Pattern" , "Pattern must not be null" ) ) ;
}
int soff = 0 ; /* Where we are in the Subject */
int poff = 0 ; /* Where we are in the Pattern */
int star = 0 ; /* The number of asterisks */
int ques = 0 ; /* The number of question marks */
/* Traverse the Pattern */
while ( result && ( poff < Pattern.Length ) )
{
switch ( Pattern [ poff ] )
{
/* Count any asterisks */
case '*' :
{
star++ ;
poff++ ;
break ;
}
/* Count any question marks */
case '?' :
{
ques++ ;
poff++ ;
break ;
}
/* Upon finding a non-wildcard */
default :
{
/* Count the number of contiguous non-wildcards */
int plen = poff ;
while
(
( plen < Pattern.Length )
&&
( Pattern [ plen ] != '*' )
&&
( Pattern [ plen ] != '?' )
)
{
plen++ ;
}
plen -= poff ;
/* Search the Subject for a matching sequence of characters */
int slen = Subject.IndexOf
(
Pattern.Substring ( poff , plen )
,
soff
,
StringComparison
) - soff ;
/* The sequence must be present and must be offset by at least the number of */
/* question marks and may be offet by more if there was at least one asterisk */
result = ( star == 0 ) ? ( slen == ques ) : ( slen >= ques ) ;
/* Prepare to find more wildcards */
soff += slen + plen ;
poff += plen ;
star = 0 ;
ques = 0 ;
break ;
}
}
}
/* Handle any trailing wildcards */
if ( result )
{
int slen = Subject.Length - soff ;
result = ( star == 0 ) ? ( slen == ques ) : ( slen >= ques ) ;
}
return ( result ) ;
}