Created
February 19, 2025 19:54
-
-
Save vborovikov/4c6ebc960e4a763faafc72f25a793cb7 to your computer and use it in GitHub Desktop.
File name globbing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| namespace SimpleGlobbing; | |
| using System; | |
| using System.Buffers; | |
| using System.Diagnostics.CodeAnalysis; | |
| using System.Runtime.CompilerServices; | |
| using System.Runtime.InteropServices; | |
| static class Globbing | |
| { | |
| private static readonly SearchValues<char> Wildcards = SearchValues.Create("*?"); | |
| public static bool HasWildcard([NotNullWhen(true)] this string? name) => name.AsSpan().HasWildcard(); | |
| public static bool HasWildcard(this ReadOnlySpan<char> name) => name.Length > 0 && name.IndexOfAny(Wildcards) >= 0; | |
| public static bool Matches(this string pattern, ReadOnlySpan<char> name) => pattern.AsSpan().Matches(name); | |
| public static bool Matches(this ReadOnlySpan<char> pattern, ReadOnlySpan<char> name) | |
| { | |
| var nameLen = name.Length; | |
| var patternLen = pattern.Length; | |
| ref var nameRef = ref MemoryMarshal.GetReference(name); | |
| ref var patternRef = ref MemoryMarshal.GetReference(pattern); | |
| var starLen = 0; | |
| while (patternLen > 0) | |
| { | |
| if (patternRef == '*') | |
| { | |
| while (patternLen > 0) | |
| { | |
| if (patternRef != '*') | |
| { | |
| break; | |
| } | |
| else | |
| { | |
| patternRef = ref Unsafe.Add(ref patternRef, 1); | |
| patternLen--; | |
| } | |
| } | |
| if (patternLen == 0) | |
| return true; | |
| starLen = patternLen; | |
| if (patternRef == '?') | |
| continue; | |
| while (nameLen > 0) | |
| { | |
| if (patternLen > 0 && char.ToUpperInvariant(nameRef) == char.ToUpperInvariant(patternRef)) | |
| { | |
| break; | |
| } | |
| else | |
| { | |
| nameRef = ref Unsafe.Add(ref nameRef, 1); | |
| nameLen--; | |
| } | |
| } | |
| } | |
| else | |
| { | |
| if (nameLen == 0) | |
| return false; | |
| if (patternRef != '?' && char.ToUpperInvariant(nameRef) != char.ToUpperInvariant(patternRef)) | |
| { | |
| if (starLen > 0) | |
| { | |
| patternRef = ref Unsafe.Add(ref patternRef, patternLen - starLen); | |
| patternLen = starLen; | |
| nameRef = ref Unsafe.Add(ref nameRef, 1); | |
| nameLen--; | |
| continue; | |
| } | |
| return false; | |
| } | |
| nameRef = ref Unsafe.Add(ref nameRef, 1); | |
| nameLen--; | |
| patternRef = ref Unsafe.Add(ref patternRef, 1); | |
| patternLen--; | |
| } | |
| } | |
| return patternLen == 0 && (nameLen == 0 || pattern[^1] == '*'); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment