From 509d4f530236d940024b429ca3f3d270c097c4db Mon Sep 17 00:00:00 2001 From: Raul Santos Date: Mon, 15 Apr 2024 03:11:49 +0200 Subject: [PATCH] C#: Fix ExprMatch for case sensitive matching We were accidentally stopping the recursion when matching in the case sensitive scenario. Took the opportunity to also rename the private method to follow the Core method naming more closely so it's easier to compare the implementations in the future. Also, the private method now uses `ReadOnlySpan` to avoid allocating strings on each recursion. --- .../GodotSharp/Core/StringExtensions.cs | 41 +++++++++---------- 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs index 9cd5498fa814..37f319b69714 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/StringExtensions.cs @@ -1208,39 +1208,39 @@ namespace Godot /// Do a simple expression match, where '*' matches zero or more /// arbitrary characters and '?' matches any single character except '.'. /// - /// The string to check. - /// Expression to check. + /// The string to check. + /// Expression to check. /// /// If , the check will be case sensitive. /// /// If the expression has any matches. - private static bool ExprMatch(this string instance, string expr, bool caseSensitive) + private static bool WildcardMatch(ReadOnlySpan str, ReadOnlySpan pattern, bool caseSensitive) { // case '\0': - if (expr.Length == 0) - return instance.Length == 0; + if (pattern.IsEmpty) + return str.IsEmpty; - switch (expr[0]) + switch (pattern[0]) { case '*': - return ExprMatch(instance, expr.Substring(1), caseSensitive) || (instance.Length > 0 && - ExprMatch(instance.Substring(1), expr, caseSensitive)); + return WildcardMatch(str, pattern.Slice(1), caseSensitive) + || (!str.IsEmpty && WildcardMatch(str.Slice(1), pattern, caseSensitive)); case '?': - return instance.Length > 0 && instance[0] != '.' && - ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive); + return !str.IsEmpty && str[0] != '.' && + WildcardMatch(str.Slice(1), pattern.Slice(1), caseSensitive); default: - if (instance.Length == 0) + if (str.IsEmpty) return false; - if (caseSensitive) - return instance[0] == expr[0]; - return (char.ToUpperInvariant(instance[0]) == char.ToUpperInvariant(expr[0])) && - ExprMatch(instance.Substring(1), expr.Substring(1), caseSensitive); + bool charMatches = caseSensitive ? + str[0] == pattern[0] : + char.ToUpperInvariant(str[0]) == char.ToUpperInvariant(pattern[0]); + return charMatches && + WildcardMatch(str.Slice(1), pattern.Slice(1), caseSensitive); } } /// - /// Do a simple case sensitive expression match, using ? and * wildcards - /// (see ). + /// Do a simple case sensitive expression match, using ? and * wildcards. /// /// /// The string to check. @@ -1254,12 +1254,11 @@ namespace Godot if (instance.Length == 0 || expr.Length == 0) return false; - return instance.ExprMatch(expr, caseSensitive); + return WildcardMatch(instance, expr, caseSensitive); } /// - /// Do a simple case insensitive expression match, using ? and * wildcards - /// (see ). + /// Do a simple case insensitive expression match, using ? and * wildcards. /// /// /// The string to check. @@ -1270,7 +1269,7 @@ namespace Godot if (instance.Length == 0 || expr.Length == 0) return false; - return instance.ExprMatch(expr, caseSensitive: false); + return WildcardMatch(instance, expr, caseSensitive: false); } ///