Skip to content

Instantly share code, notes, and snippets.

@AntonC9018
Created August 30, 2023 19:11
Show Gist options
  • Save AntonC9018/35a5a2cad4b3fedeb6e95bf5b2462eaa to your computer and use it in GitHub Desktop.
Save AntonC9018/35a5a2cad4b3fedeb6e95bf5b2462eaa to your computer and use it in GitHub Desktop.
Split that can be used on ReadOnlySpan<char> without allocations
public static class SpanExtensions
{
public static Splitter<T> Splitter<T>(
this ReadOnlySpan<T> span,
ReadOnlySpan<T> delimiter)
where T : IEquatable<T>
{
return new(span, delimiter);
}
}
public readonly ref struct Splitter<T>
where T : IEquatable<T>
{
public Splitter(ReadOnlySpan<T> span, ReadOnlySpan<T> delimiter)
{
Span = span;
Delimiter = delimiter;
}
public ReadOnlySpan<T> Span { get; }
public ReadOnlySpan<T> Delimiter { get; }
public Enumerator GetEnumerator() => new(this);
public ref struct Enumerator
{
private readonly Splitter<T> _splitter;
private int _currentIndex;
private int _currentLength;
public Enumerator(Splitter<T> splitter)
{
_splitter = splitter;
_currentIndex = 0;
_currentLength = -1;
}
public ReadOnlySpan<T> Current => _splitter.Span.Slice(_currentIndex, _currentLength);
public bool MoveNext()
{
_currentIndex += _currentLength + 1;
if (_currentIndex >= _splitter.Span.Length)
return false;
var spanLeft = _splitter.Span[_currentIndex ..];
_currentLength = spanLeft.IndexOf(_splitter.Delimiter);
if (_currentLength == -1)
_currentLength = spanLeft.Length;
return true;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment