using System.Collections.Concurrent; using System.Text; using System.Text.RegularExpressions; namespace MxGateway.Server.Galaxy; public static class GalaxyGlobMatcher { /// /// Compiled-regex cache keyed by glob pattern. IsMatch is called once per /// object per DiscoverHierarchy/WatchDeployEvents evaluation, so the /// same handful of glob patterns are translated repeatedly; caching avoids /// rebuilding and recompiling the regex on every call. /// private static readonly ConcurrentDictionary RegexCache = new(StringComparer.Ordinal); public static bool IsMatch(string value, string glob) { if (string.IsNullOrWhiteSpace(glob)) { return true; } return GetOrCreateRegex(glob).IsMatch(value ?? string.Empty); } private static Regex GetOrCreateRegex(string glob) { return RegexCache.GetOrAdd(glob, static pattern => new Regex( BuildRegex(pattern), RegexOptions.CultureInvariant | RegexOptions.IgnoreCase | RegexOptions.Compiled, TimeSpan.FromMilliseconds(100))); } private static string BuildRegex(string glob) { StringBuilder builder = new("^", glob.Length + 2); foreach (char character in glob) { switch (character) { case '*': builder.Append(".*"); break; case '?': builder.Append('.'); break; default: builder.Append(Regex.Escape(character.ToString())); break; } } builder.Append('$'); return builder.ToString(); } }