Project · Current .NET

Reusable separator tokenizer lab

Use one SearchValues<char> set to split owned nonempty tokens and verify six concrete representation and boundary cases.

All C# source files below are loaded together in the playground. Files written by a run live in its virtual directory.

Program.cs

var checks = TokenizerChecks.Run();
foreach (var check in checks) Console.WriteLine($"{check.Name}:{(check.Passed ? "PASS" : "FAIL")}");
Console.WriteLine($"passed:{checks.Count(check => check.Passed)}/{checks.Count}");
return checks.All(check => check.Passed) ? 0 : 1;

Domain/Tokenizer.cs

using System.Buffers;
public static class Tokenizer
{
    private static readonly SearchValues<char> Separators = SearchValues.Create(",;|");
    public static string[] SplitNonEmpty(string text)
    {
        ArgumentNullException.ThrowIfNull(text);
        ReadOnlySpan<char> remaining = text.AsSpan();
        List<string> tokens = [];
        while (!remaining.IsEmpty)
        {
            int index = remaining.IndexOfAny(Separators);
            ReadOnlySpan<char> token = index < 0 ? remaining : remaining[..index];
            token = token.Trim();
            if (!token.IsEmpty) tokens.Add(token.ToString());
            if (index < 0) break;
            remaining = remaining[(index + 1)..];
        }
        return [.. tokens];
    }
}

Checks/TokenizerChecks.cs

public static class TokenizerChecks
{
    public static List<(string Name, bool Passed)> Run()
    {
        var cases = new (string Name, string Input, string[] Expected)[]
        {
            ("mixed", "a,b;c|d", ["a", "b", "c", "d"]),
            ("empty", "", []),
            ("adjacent", "a,,b", ["a", "b"]),
            ("edge", ";a|", ["a"]),
            ("spaces", " a ;  b  ", ["a", "b"]),
            ("unicode", "rune;🦀", ["rune", "🦀"])
        };
        List<(string Name, bool Passed)> checks = [];
        foreach (var item in cases)
            checks.Add((item.Name, Tokenizer.SplitNonEmpty(item.Input).SequenceEqual(item.Expected)));
        return checks;
    }
}

ConsoleLab.csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net9.0</TargetFramework>
    <LangVersion>13.0</LangVersion>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
</Project>