{"id":19080415,"url":"https://github.com/seeminglyscience/psvaluewildcard","last_synced_at":"2026-05-12T23:32:35.962Z","repository":{"id":87373559,"uuid":"234797760","full_name":"SeeminglyScience/PSValueWildcard","owner":"SeeminglyScience","description":null,"archived":false,"fork":false,"pushed_at":"2020-02-01T23:09:55.000Z","size":51,"stargazers_count":3,"open_issues_count":1,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-01-02T19:42:00.538Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SeeminglyScience.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-01-18T21:06:09.000Z","updated_at":"2024-02-22T17:18:37.000Z","dependencies_parsed_at":"2023-03-27T13:04:50.135Z","dependency_job_id":null,"html_url":"https://github.com/SeeminglyScience/PSValueWildcard","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SeeminglyScience%2FPSValueWildcard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SeeminglyScience%2FPSValueWildcard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SeeminglyScience%2FPSValueWildcard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SeeminglyScience%2FPSValueWildcard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SeeminglyScience","download_url":"https://codeload.github.com/SeeminglyScience/PSValueWildcard/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240131737,"owners_count":19752727,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-09T02:23:32.318Z","updated_at":"2026-05-12T23:32:35.918Z","avatar_url":"https://github.com/SeeminglyScience.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PSValueWildcard\n\nA span based wildcard pattern evaluator compatible with PowerShell's [WildcardPattern] implementation.\n\n- **Testers needed**: Ideally this project will be as reliable as PowerShell's implementation, but a\n  whole lot of testing is needed before this project could be considered production ready. If this project\n  interests you, try to break it! Especially folks who use culture settings other than `en-US`!\n\n## Features\n\n- Accepts [ReadOnlySpan\u0026lt;char\u0026gt;] for both input and pattern\n- Often heap allocation free (see [About heap allocations](#about-heap-allocations))\n- Focus on performance\n- Completely standalone, PowerShell is not required\n\n## Installation\n\n```powershell\ndotnet add package PSValueWildcard --version 1.0.0-alpha1\n```\n\n## Usage\n\n### On demand\n\n```csharp\nusing PSValueWildcard;\n\npublic void Match()\n{\n    ValueWildcardPattern.IsMatch(input: \"test\", pattern: \"T*t\");\n    // true\n\n    ValueWildcardPattern.IsMatch(input: \"test\", pattern: \"T*t\", options: ValueWildcardOptions.Ordinal);\n    // false\n}\n```\n\n**NOTE**: Unlike the regex based [WildcardPattern], the parsed result will not be cached when utilizing\n`ValueWildcardPattern`. For the majority of pattern lengths and complexities it should still be performant.\n\n### Heap cached\n\n```csharp\nusing PSValueWildcard;\n\npublic void Match(string pattern)\n{\n    using var wildcard = ValueWildcardPattern.Parse(pattern);\n\n    foreach (string input in GetNames())\n    {\n        // Options are optional. Default is InvariantCultureIgnoreCase.\n        if (!wildcard.IsMatch(input, ValueWildcardOptions.CurrentCultureIgnoreCase))\n        {\n            throw new Exception();\n        }\n    }\n}\n```\n\n### Cmdlet example (requires PowerShell)\n\n```csharp\nusing System.Management.Automation;\n\nusing PSValueWildcard;\n\n[Cmdlet(VerbsDiagnostic.Test, \"Pattern\")]\npublic sealed class TestPatternCommand : PSCmdlet, IDisposable\n{\n    private ParsedWildcardPattern _pattern;\n\n    [Parameter(Mandatory = true, ValueFromPipeline = true)]\n    public string InputObject { get; set; }\n\n    [Parameter(Mandatory = true, Position = 0)]\n    public string Pattern { get; set; }\n\n    protected override void BeginProcessing()\n    {\n        _pattern = ValueWildcardPattern.Parse(Pattern);\n    }\n\n    protected override void ProcessRecord()\n    {\n        WriteObject(_pattern.IsMatch(InputObject));\n    }\n\n    public void Dispose() =\u003e _pattern.Dispose();\n}\n```\n\n## Why\n\nI made this because I really like using the [Span\u0026lt;T\u0026gt;] API these days. If I'm making something, then\nit's often for PowerShell.  And if it's for PowerShell, I often want to support wildcard matching. In\norder to do that, I end up allocating *a whole bunch* of strings that I wouldn't have to otherwise\njust trying to find an item.\n\nThat's why I built it, but here's a few scenarios where you might consider this library:\n\n1. You're already using [Span\u0026lt;T\u0026gt;]\n2. You're building an application where you want to support PowerShell style wildcard patterns,\n   but do not want to reference all of [System.Management.Automation]\n3. You feel that [WildcardPattern] is too slow or allocates too much\n\n## About heap allocations\n\nThis library attempts to achieve zero heap allocations, however there are a few circumstances\nwhere they may be required. These circumstances include (but may not be limited to):\n\n- Heuristics are used to guess how many \"instructions\" (e.g. `[ad]`, `?` and `whole string` are\n  one instruction each) are in a pattern. If the estimation is too low and the stack allocated\n  buffer is too small, some heap allocations will be made\n\n- When an \"any of\" pattern (e.g. `[qwerty]`) contains an escape character (\u003ckbd\u003e`\u003c/kbd\u003e) they\n  are parsed as separate \"partial\" instructions. During evaluation they are combined into a\n  single instruction.  When this happens, if the combined text is too long to be allocated\n  on the stack, a heap allocation will be made\n\n- When saving the parsed pattern as a `ParsedWildcardPattern`, the entire object is allocated\n  to the heap along with a [GCHandle] for the pinned string\n\n[Span\u0026lt;T\u0026gt;]: https://docs.microsoft.com/en-us/dotnet/api/system.span-1\n[ReadOnlySpan\u0026lt;char\u0026gt;]:https://docs.microsoft.com/en-us/dotnet/api/system.readonlyspan-1\n[WildcardPattern]: https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.wildcardpattern\n[System.Management.Automation]: https://www.nuget.org/packages/System.Management.Automation\n[GCHandle]: https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.gchandle\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseeminglyscience%2Fpsvaluewildcard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fseeminglyscience%2Fpsvaluewildcard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fseeminglyscience%2Fpsvaluewildcard/lists"}