|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
namespace System.Text
{
internal static class SimpleRegex
{
// Based on wildcmp written by Jack Handy - <A href="mailto:jakkhandy@hotmail.com">jakkhandy@hotmail.com</A>
// https://www.codeproject.com/Articles/1088/Wildcard-string-compare-globbing
/// <summary>
/// Perform a match between an input string and a pattern in which the only special character
/// is an asterisk, which can map to zero or more of any character in the input.
/// </summary>
/// <param name="input">The input to match.</param>
/// <param name="pattern">The pattern to match against.</param>
/// <returns>true if the input matches the pattern; otherwise, false.</returns>
public static bool IsMatchWithStarWildcard(ReadOnlySpan<char> input, ReadOnlySpan<char> pattern)
{
int inputPos = 0, inputPosSaved = -1;
int patternPos = 0, patternPosSaved = -1;
// Loop through each character in the input.
while (inputPos < input.Length)
{
if (patternPos < pattern.Length && pattern[patternPos] == '*')
{
// If we're currently positioned on a wildcard in the pattern,
// move past it and remember where we are to backtrack to.
inputPosSaved = inputPos;
patternPosSaved = ++patternPos;
}
else if (patternPos < pattern.Length &&
(pattern[patternPos] == input[inputPos] ||
char.ToUpperInvariant(pattern[patternPos]) == char.ToUpperInvariant(input[inputPos])))
{
// If the characters in the pattern and the input match, advance both.
inputPos++;
patternPos++;
}
else if (patternPosSaved == -1)
{
// If we're not on a wildcard and the current characters don't match and we don't have
// any wildcard to backtrack to, this is not a match.
return false;
}
else
{
// Otherwise, this is not a wildcard, the characters don't match, but we do have a
// wildcard saved, so backtrack to it and use it to consume the next input character.
inputPos = ++inputPosSaved;
patternPos = patternPosSaved;
}
}
// We've reached the end of the input. Eat all wildcards immediately after where we are
// in the pattern, as if they're at the end, they'll all just map to nothing (and if it
// turns out there's something after them, eating them won't matter).
while (patternPos < pattern.Length && pattern[patternPos] == '*')
{
patternPos++;
}
// If we are in fact at the end of the pattern, then we successfully matched.
// If there's anything left, it's not a wildcard, so it doesn't match.
Debug.Assert(patternPos <= pattern.Length);
return patternPos == pattern.Length;
}
}
}
|