diff --git a/Pilz/Text/LikeOperator.cs b/Pilz/Text/LikeOperator.cs new file mode 100644 index 0000000..8288cb4 --- /dev/null +++ b/Pilz/Text/LikeOperator.cs @@ -0,0 +1,96 @@ +using System.Text.RegularExpressions; + +namespace Pilz.Text; + +public static class LikeOperator +{ + public static bool IsLike(this string? input, string pattern) + { + return IsLike(input, pattern, true); + } + + public static bool IsLike(this string? input, string pattern, bool ignoreCase) + { + return IsLike(input, pattern, GetDefaultOptions(ignoreCase)); + } + + public static bool IsLike(this string? input, string pattern, RegexOptions options) + { + var resultPattern = new System.Text.StringBuilder(); + var insideList = false; + var prevInsideList = false; + + for (var i = 0; i < pattern.Length; i++) + { + var c = pattern[i]; + var tempInsideList = insideList; + + // Manage pattern start + if (i == 0 && c != '*') + resultPattern.Append('^'); + + // Manage characterlists + if (c == '[' && !insideList) + { + insideList = true; + resultPattern.Append(c); + } + else if (c == ']' && insideList) + { + insideList = false; + resultPattern.Append(c); + } + else if (c == '!' && insideList && !prevInsideList) + { + // Special chars for Like that need to be converted + resultPattern.Append('^'); + } + else if (c == '?' && !insideList) + { + resultPattern.Append('.'); + } + else if (c == '#' && !insideList) + { + resultPattern.Append(@"\d"); + } + else if (c == '*' && i == 0) + { + // Nothing to append + } + else if (c == '*' && i == pattern.Length - 1) + { + // Nothing to append + } + else if (c == '*' && !insideList) + { + resultPattern.Append(".*"); + } + else if (c == '.' || c == '\\' || c == '(' || c == ')') + { + // Special chars for Regex that need to be escaped + resultPattern.Append('\\'); + resultPattern.Append(c); + } + else + resultPattern.Append(c); + + // Manage pattern end + if (i == pattern.Length - 1 && c != '*') + resultPattern.Append('$'); + + prevInsideList = tempInsideList; + } + + return Regex.IsMatch(input, resultPattern.ToString(), options); + } + + public static RegexOptions GetDefaultOptions(bool ignoreCase) + { + var options = RegexOptions.Singleline | RegexOptions.CultureInvariant; + + if (ignoreCase) + options |= RegexOptions.IgnoreCase; + + return options; + } +}