Example #1
0
/// <summary>
/// Determine if a string matches a pattern containing wildcard characters, case-insensitive.
/// </summary>
/// <param name="pattern">The pattern to compare against.</param>
/// <param name="patternEnd">The end of the pattern to compare against (one past the last character; the
/// address of the '\0' if you're using NUL-terminated strings).</param>
/// <param name="text">The text string to test.</param>
/// <param name="textEnd">The end of the text string to test (one past the last character; the
/// address of the '\0' if you're using NUL-terminated strings).</param>
/// <returns>True if the string matches the pattern, false if it does not.</returns>
static Bool WildcardMatch(const Byte *pattern, const Byte *patternEnd, const Byte *text, const Byte *textEnd)
{
	Byte patternChar, textChar, nextPatternChar;

	while (pattern < patternEnd) {
		switch (patternChar = CaseFold(*pattern++)) {
		case '?':
			// If we ran out of characters, this is a fail.
			if (text == textEnd)
				return False;
			textChar = CaseFold(*text++);
			break;

		case '*':
			// Consume trailing '*' and '?' characters, since they don't mean much (except '?',
			// which adds mandatory filler space).
			while (pattern < patternEnd && ((patternChar = CaseFold(*pattern)) == '?' || patternChar == '*')) {
				if (patternChar == '?' && text == textEnd)
					return False;
				pattern++;
				text++;
			}

			// If we ran out of characters in the pattern, then this is a successful match,
			// since this star can consume everything after it in the text.
			if (pattern == patternEnd)
				return True;

			// Determine the next character in the text that we're searching for.
			nextPatternChar = patternChar;

			// Skim forward in the text looking for that next character, and then recursively
			// perform a pattern-match on the remainders of the pattern and text from there.
			// We use that next character to optimize the recursion, so that we don't recurse
			// if we know there won't be a match.
			while (text < textEnd) {
				textChar = CaseFold(*text);
				if (textChar == nextPatternChar && WildcardMatch(pattern, patternEnd, text, textEnd))
					return True;
				text++;
			}

			// None of the recursive searches matched, so this is a fail.
			return False;

		default:
			if (text == textEnd)
				return False;	// Ran out of characters.
			if (patternChar != CaseFold(*text++))
				return False;	// No match.
			break;
		}
	}

	return text == textEnd;
}
Example #2
0
std::wstring Strings::CaseFold( std::wstring & str )
{
    std::wstring s2 = str;
    Utils::Strings::toUpperCase(s2);
    Utils::Strings::toLowerCase(s2);
    if (s2 != str)
        return CaseFold(s2);
    return s2;
}