Non-Alloc String Splitter for .NET / Unity
Runtime/Text/NonAllocStringSplitter.cs
HeaderDoc
(c) 2024 Sator Imaging, Licensed under the MIT License https://github.com/sator-imaging/Unity-Fundamentals
How to Use
var result = new NonAllocStringSplitter("A,,B,C,", ','); // 3 items. empty will be removed
// split by sequence or by any char. using extension method
result = "A, B, C".AsSpan().SplitNonAlloc(" ,"); // 1 item. no ' ,' sequence found
result = "A, B, C".AsSpan().SplitAnyNonAlloc(" ,"); // 3 items. split by ' ' or ','
// enumerate
for (int i = 0; i < result.Count; i++)
{
var span = result[i];
}
foreach (var span in result)
{
Console.WriteLine(span.ToString());
}
// can pass 'stackalloc char[]' directly
result = "A, B, C".AsSpan().SplitNonAlloc(stackalloc char[] { ' ', ',' });
Incremental String Splitter
Allocation-free incremental splitter processes only when consuming enumerator so it supports unlimited length of input text and any number of items can be splitted. (inspired by .NET 9 preview feature)
var span = "ABC DEF".AsSpan();
foreach (var range in span.SplitEnumerator(' '))
{
// use Range struct from enumerator to extract result
Console.WriteLine(span[range].ToString());
}
TrySplit Extensions
Designed to split input text into 2 items.
var span = "https://www.inter.net/path/to/file.html?opt=value&other=data#anchor";
// TrySplitLast searches splitter from end of text
if (!span.TrySplitLast('#', out var urlAndOptions, out var anchorSpan))
{
urlAndOptions = span;
anchorSpan = default;
}
Span<Range> optionNameRanges = default;
Span<Range> optionValueRanges = default;
if (urlAndOptions.TrySplit('?', out var url, out var allOptions)
{
optionNameRanges = stackalloc Range[16];
optionValueRanges = stackalloc Range[16];
int i = -1;
foreach (var range in allOptions.SplitEnumerator('&'))
{
i++;
if (!allOptions[range].TrySplit('=', out var name, out var value)
{
name = allOptions[range];
value = string.Empty;
}
optionNameRanges[i] = new(range.Start, range.Start + name.Length);
optionValueRanges[i] = new(range.End - value.Length, range.End);
}
}