Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -15,94 +15,72 @@ namespace Microsoft.Toolkit.HighPerformance.Enumerables
/// </summary>
/// <typeparam name="T">The type of items to enumerate.</typeparam>
[EditorBrowsable(EditorBrowsableState.Never)]
public readonly ref struct ReadOnlySpanEnumerable<T>
public ref struct ReadOnlySpanEnumerable<T>
{
/// <summary>
/// The source <see cref="ReadOnlySpan{T}"/> instance
/// The source <see cref="ReadOnlySpan{T}"/> instance.
/// </summary>
private readonly ReadOnlySpan<T> span;

/// <summary>
/// The current index within <see cref="span"/>.
/// </summary>
private int index;

/// <summary>
/// Initializes a new instance of the <see cref="ReadOnlySpanEnumerable{T}"/> struct.
/// </summary>
/// <param name="span">The source <see cref="ReadOnlySpan{T}"/> to enumerate.</param>
/// <param name="span">The source <see cref="ReadOnlySpan{T}"/> instance.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ReadOnlySpanEnumerable(ReadOnlySpan<T> span)
{
this.span = span;
this.index = -1;
}

/// <summary>
/// Implements the duck-typed <see cref="IEnumerable{T}.GetEnumerator"/> method.
/// </summary>
/// <returns>An <see cref="Enumerator"/> instance targeting the current <see cref="ReadOnlySpan{T}"/> value.</returns>
/// <returns>An <see cref="ReadOnlySpanEnumerable{T}"/> instance targeting the current <see cref="ReadOnlySpan{T}"/> value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator GetEnumerator() => new Enumerator(this.span);
public ReadOnlySpanEnumerable<T> GetEnumerator() => this;

/// <summary>
/// An enumerator for a source <see cref="ReadOnlySpan{T}"/> instance.
/// Implements the duck-typed <see cref="System.Collections.IEnumerator.MoveNext"/> method.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public ref struct Enumerator
/// <returns><see langword="true"/> whether a new element is available, <see langword="false"/> otherwise</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext()
{
/// <summary>
/// The source <see cref="ReadOnlySpan{T}"/> instance.
/// </summary>
private readonly ReadOnlySpan<T> span;

/// <summary>
/// The current index within <see cref="span"/>.
/// </summary>
private int index;

/// <summary>
/// Initializes a new instance of the <see cref="Enumerator"/> struct.
/// </summary>
/// <param name="span">The source <see cref="ReadOnlySpan{T}"/> instance.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator(ReadOnlySpan<T> span)
{
this.span = span;
this.index = -1;
}
int newIndex = this.index + 1;

/// <summary>
/// Implements the duck-typed <see cref="System.Collections.IEnumerator.MoveNext"/> method.
/// </summary>
/// <returns><see langword="true"/> whether a new element is available, <see langword="false"/> otherwise</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext()
if (newIndex < this.span.Length)
{
int newIndex = this.index + 1;
this.index = newIndex;

if (newIndex < this.span.Length)
{
this.index = newIndex;

return true;
}

return false;
return true;
}

/// <summary>
/// Gets the duck-typed <see cref="IEnumerator{T}.Current"/> property.
/// </summary>
public Item Current
return false;
}

/// <summary>
/// Gets the duck-typed <see cref="IEnumerator{T}.Current"/> property.
/// </summary>
public Item Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
#if SPAN_RUNTIME_SUPPORT
ref T r0 = ref MemoryMarshal.GetReference(this.span);
ref T ri = ref Unsafe.Add(ref r0, this.index);
ref T r0 = ref MemoryMarshal.GetReference(this.span);
ref T ri = ref Unsafe.Add(ref r0, this.index);

// See comment in SpanEnumerable<T> about this
return new Item(ref ri, this.index);
// See comment in SpanEnumerable<T> about this
return new Item(ref ri, this.index);
#else
return new Item(this.span, this.index);
return new Item(this.span, this.index);
#endif
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,119 +14,90 @@ namespace Microsoft.Toolkit.HighPerformance.Enumerables
/// </summary>
/// <typeparam name="T">The type of items to enumerate.</typeparam>
[EditorBrowsable(EditorBrowsableState.Never)]
public readonly ref struct ReadOnlySpanTokenizer<T>
public ref struct ReadOnlySpanTokenizer<T>
where T : IEquatable<T>
{
/// <summary>
/// The source <see cref="ReadOnlySpan{T}"/> instance
/// The source <see cref="ReadOnlySpan{T}"/> instance.
/// </summary>
private readonly ReadOnlySpan<T> span;

/// <summary>
/// The separator <typeparamref name="T"/> item to use.
/// The separator item to use.
/// </summary>
private readonly T separator;

/// <summary>
/// The current initial offset.
/// </summary>
private int start;

/// <summary>
/// The current final offset.
/// </summary>
private int end;

/// <summary>
/// Initializes a new instance of the <see cref="ReadOnlySpanTokenizer{T}"/> struct.
/// </summary>
/// <param name="span">The source <see cref="ReadOnlySpan{T}"/> to tokenize.</param>
/// <param name="separator">The separator <typeparamref name="T"/> item to use.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
/// <param name="span">The source <see cref="ReadOnlySpan{T}"/> instance.</param>
/// <param name="separator">The separator item to use.</param>
public ReadOnlySpanTokenizer(ReadOnlySpan<T> span, T separator)
{
this.span = span;
this.separator = separator;
this.start = 0;
this.end = -1;
}

/// <summary>
/// Implements the duck-typed <see cref="IEnumerable{T}.GetEnumerator"/> method.
/// </summary>
/// <returns>An <see cref="Enumerator"/> instance targeting the current <see cref="ReadOnlySpan{T}"/> value.</returns>
/// <returns>An <see cref="ReadOnlySpanTokenizer{T}"/> instance targeting the current <see cref="ReadOnlySpan{T}"/> value.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Enumerator GetEnumerator() => new Enumerator(this.span, this.separator);
public ReadOnlySpanTokenizer<T> GetEnumerator() => this;

/// <summary>
/// An enumerator for a source <see cref="ReadOnlySpan{T}"/> instance.
/// Implements the duck-typed <see cref="System.Collections.IEnumerator.MoveNext"/> method.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
public ref struct Enumerator
/// <returns><see langword="true"/> whether a new element is available, <see langword="false"/> otherwise</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext()
{
/// <summary>
/// The source <see cref="ReadOnlySpan{T}"/> instance.
/// </summary>
private readonly ReadOnlySpan<T> span;

/// <summary>
/// The separator item to use.
/// </summary>
private readonly T separator;

/// <summary>
/// The current initial offset.
/// </summary>
private int start;

/// <summary>
/// The current final offset.
/// </summary>
private int end;

/// <summary>
/// Initializes a new instance of the <see cref="Enumerator"/> struct.
/// </summary>
/// <param name="span">The source <see cref="ReadOnlySpan{T}"/> instance.</param>
/// <param name="separator">The separator item to use.</param>
public Enumerator(ReadOnlySpan<T> span, T separator)
{
this.span = span;
this.separator = separator;
this.start = 0;
this.end = -1;
}
int
newEnd = this.end + 1,
length = this.span.Length;

/// <summary>
/// Implements the duck-typed <see cref="System.Collections.IEnumerator.MoveNext"/> method.
/// </summary>
/// <returns><see langword="true"/> whether a new element is available, <see langword="false"/> otherwise</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext()
// Additional check if the separator is not the last character
if (newEnd <= length)
{
int
newEnd = this.end + 1,
length = this.span.Length;

// Additional check if the separator is not the last character
if (newEnd <= length)
{
this.start = newEnd;
this.start = newEnd;

int index = this.span.Slice(newEnd).IndexOf(this.separator);
int index = this.span.Slice(newEnd).IndexOf(this.separator);

// Extract the current subsequence
if (index >= 0)
{
this.end = newEnd + index;

return true;
}

this.end = length;
// Extract the current subsequence
if (index >= 0)
{
this.end = newEnd + index;

return true;
}

return false;
}
this.end = length;

/// <summary>
/// Gets the duck-typed <see cref="IEnumerator{T}.Current"/> property.
/// </summary>
public ReadOnlySpan<T> Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => this.span.Slice(this.start, this.end - this.start);
return true;
}

return false;
}

/// <summary>
/// Gets the duck-typed <see cref="IEnumerator{T}.Current"/> property.
/// </summary>
public ReadOnlySpan<T> Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => this.span.Slice(this.start, this.end - this.start);
}
}
}
Loading