diff --git a/Microsoft.Toolkit.HighPerformance/Enumerables/ReadOnlySpanEnumerable{T}.cs b/Microsoft.Toolkit.HighPerformance/Enumerables/ReadOnlySpanEnumerable{T}.cs index 51b8f675677..29d42924536 100644 --- a/Microsoft.Toolkit.HighPerformance/Enumerables/ReadOnlySpanEnumerable{T}.cs +++ b/Microsoft.Toolkit.HighPerformance/Enumerables/ReadOnlySpanEnumerable{T}.cs @@ -15,94 +15,72 @@ namespace Microsoft.Toolkit.HighPerformance.Enumerables /// /// The type of items to enumerate. [EditorBrowsable(EditorBrowsableState.Never)] - public readonly ref struct ReadOnlySpanEnumerable + public ref struct ReadOnlySpanEnumerable { /// - /// The source instance + /// The source instance. /// private readonly ReadOnlySpan span; + /// + /// The current index within . + /// + private int index; + /// /// Initializes a new instance of the struct. /// - /// The source to enumerate. + /// The source instance. [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlySpanEnumerable(ReadOnlySpan span) { this.span = span; + this.index = -1; } /// /// Implements the duck-typed method. /// - /// An instance targeting the current value. + /// An instance targeting the current value. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Enumerator GetEnumerator() => new Enumerator(this.span); + public ReadOnlySpanEnumerable GetEnumerator() => this; /// - /// An enumerator for a source instance. + /// Implements the duck-typed method. /// - [EditorBrowsable(EditorBrowsableState.Never)] - public ref struct Enumerator + /// whether a new element is available, otherwise + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() { - /// - /// The source instance. - /// - private readonly ReadOnlySpan span; - - /// - /// The current index within . - /// - private int index; - - /// - /// Initializes a new instance of the struct. - /// - /// The source instance. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Enumerator(ReadOnlySpan span) - { - this.span = span; - this.index = -1; - } + int newIndex = this.index + 1; - /// - /// Implements the duck-typed method. - /// - /// whether a new element is available, otherwise - [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; } - /// - /// Gets the duck-typed property. - /// - public Item Current + return false; + } + + /// + /// Gets the duck-typed property. + /// + 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 about this - return new Item(ref ri, this.index); + // See comment in SpanEnumerable 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 - } } } diff --git a/Microsoft.Toolkit.HighPerformance/Enumerables/ReadOnlySpanTokenizer{T}.cs b/Microsoft.Toolkit.HighPerformance/Enumerables/ReadOnlySpanTokenizer{T}.cs index 5a9c7d13823..3977f5829f8 100644 --- a/Microsoft.Toolkit.HighPerformance/Enumerables/ReadOnlySpanTokenizer{T}.cs +++ b/Microsoft.Toolkit.HighPerformance/Enumerables/ReadOnlySpanTokenizer{T}.cs @@ -14,119 +14,90 @@ namespace Microsoft.Toolkit.HighPerformance.Enumerables /// /// The type of items to enumerate. [EditorBrowsable(EditorBrowsableState.Never)] - public readonly ref struct ReadOnlySpanTokenizer + public ref struct ReadOnlySpanTokenizer where T : IEquatable { /// - /// The source instance + /// The source instance. /// private readonly ReadOnlySpan span; /// - /// The separator item to use. + /// The separator item to use. /// private readonly T separator; + /// + /// The current initial offset. + /// + private int start; + + /// + /// The current final offset. + /// + private int end; + /// /// Initializes a new instance of the struct. /// - /// The source to tokenize. - /// The separator item to use. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + /// The source instance. + /// The separator item to use. public ReadOnlySpanTokenizer(ReadOnlySpan span, T separator) { this.span = span; this.separator = separator; + this.start = 0; + this.end = -1; } /// /// Implements the duck-typed method. /// - /// An instance targeting the current value. + /// An instance targeting the current value. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Enumerator GetEnumerator() => new Enumerator(this.span, this.separator); + public ReadOnlySpanTokenizer GetEnumerator() => this; /// - /// An enumerator for a source instance. + /// Implements the duck-typed method. /// - [EditorBrowsable(EditorBrowsableState.Never)] - public ref struct Enumerator + /// whether a new element is available, otherwise + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() { - /// - /// The source instance. - /// - private readonly ReadOnlySpan span; - - /// - /// The separator item to use. - /// - private readonly T separator; - - /// - /// The current initial offset. - /// - private int start; - - /// - /// The current final offset. - /// - private int end; - - /// - /// Initializes a new instance of the struct. - /// - /// The source instance. - /// The separator item to use. - public Enumerator(ReadOnlySpan span, T separator) - { - this.span = span; - this.separator = separator; - this.start = 0; - this.end = -1; - } + int + newEnd = this.end + 1, + length = this.span.Length; - /// - /// Implements the duck-typed method. - /// - /// whether a new element is available, otherwise - [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; - /// - /// Gets the duck-typed property. - /// - public ReadOnlySpan Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => this.span.Slice(this.start, this.end - this.start); + return true; } + + return false; + } + + /// + /// Gets the duck-typed property. + /// + public ReadOnlySpan Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => this.span.Slice(this.start, this.end - this.start); } } } diff --git a/Microsoft.Toolkit.HighPerformance/Enumerables/SpanEnumerable{T}.cs b/Microsoft.Toolkit.HighPerformance/Enumerables/SpanEnumerable{T}.cs index 1db240cc447..791f509339d 100644 --- a/Microsoft.Toolkit.HighPerformance/Enumerables/SpanEnumerable{T}.cs +++ b/Microsoft.Toolkit.HighPerformance/Enumerables/SpanEnumerable{T}.cs @@ -15,99 +15,77 @@ namespace Microsoft.Toolkit.HighPerformance.Enumerables /// /// The type of items to enumerate. [EditorBrowsable(EditorBrowsableState.Never)] - public readonly ref struct SpanEnumerable + public ref struct SpanEnumerable { /// - /// The source instance + /// The source instance. /// private readonly Span span; + /// + /// The current index within . + /// + private int index; + /// /// Initializes a new instance of the struct. /// - /// The source to enumerate. + /// The source instance. [MethodImpl(MethodImplOptions.AggressiveInlining)] public SpanEnumerable(Span span) { this.span = span; + this.index = -1; } /// /// Implements the duck-typed method. /// - /// An instance targeting the current value. + /// An instance targeting the current value. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Enumerator GetEnumerator() => new Enumerator(this.span); + public SpanEnumerable GetEnumerator() => this; /// - /// An enumerator for a source instance. + /// Implements the duck-typed method. /// - [EditorBrowsable(EditorBrowsableState.Never)] - public ref struct Enumerator + /// whether a new element is available, otherwise + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() { - /// - /// The source instance. - /// - private readonly Span span; - - /// - /// The current index within . - /// - private int index; + int newIndex = this.index + 1; - /// - /// Initializes a new instance of the struct. - /// - /// The source instance. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Enumerator(Span span) + if (newIndex < this.span.Length) { - this.span = span; - this.index = -1; - } + this.index = newIndex; - /// - /// Implements the duck-typed method. - /// - /// whether a new element is available, otherwise - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() - { - int newIndex = this.index + 1; - - if (newIndex < this.span.Length) - { - this.index = newIndex; - - return true; - } - - return false; + return true; } - /// - /// Gets the duck-typed property. - /// - public Item Current + return false; + } + + /// + /// Gets the duck-typed property. + /// + 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); - - // On .NET Standard 2.1 we can save 4 bytes by piggybacking - // the current index in the length of the wrapped span. - // We're going to use the first item as the target reference, - // and the length as a host for the current original offset. - // This is not possible on .NET Standard 2.1 as we lack - // the API to create spans from arbitrary references. - return new Item(ref ri, this.index); + ref T r0 = ref MemoryMarshal.GetReference(this.span); + ref T ri = ref Unsafe.Add(ref r0, this.index); + + // On .NET Standard 2.1 we can save 4 bytes by piggybacking + // the current index in the length of the wrapped span. + // We're going to use the first item as the target reference, + // and the length as a host for the current original offset. + // This is not possible on .NET Standard 2.1 as we lack + // the API to create spans from arbitrary references. + return new Item(ref ri, this.index); #else - return new Item(this.span, this.index); + return new Item(this.span, this.index); #endif - } } } diff --git a/Microsoft.Toolkit.HighPerformance/Enumerables/SpanTokenizer{T}.cs b/Microsoft.Toolkit.HighPerformance/Enumerables/SpanTokenizer{T}.cs index a3034d67a0a..953eb535f0b 100644 --- a/Microsoft.Toolkit.HighPerformance/Enumerables/SpanTokenizer{T}.cs +++ b/Microsoft.Toolkit.HighPerformance/Enumerables/SpanTokenizer{T}.cs @@ -14,119 +14,90 @@ namespace Microsoft.Toolkit.HighPerformance.Enumerables /// /// The type of items to enumerate. [EditorBrowsable(EditorBrowsableState.Never)] - public readonly ref struct SpanTokenizer + public ref struct SpanTokenizer where T : IEquatable { /// - /// The source instance + /// The source instance. /// private readonly Span span; /// - /// The separator item to use. + /// The separator item to use. /// private readonly T separator; + /// + /// The current initial offset. + /// + private int start; + + /// + /// The current final offset. + /// + private int end; + /// /// Initializes a new instance of the struct. /// - /// The source to tokenize. - /// The separator item to use. - [MethodImpl(MethodImplOptions.AggressiveInlining)] + /// The source instance. + /// The separator item to use. public SpanTokenizer(Span span, T separator) { this.span = span; this.separator = separator; + this.start = 0; + this.end = -1; } /// /// Implements the duck-typed method. /// - /// An instance targeting the current value. + /// An instance targeting the current value. [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Enumerator GetEnumerator() => new Enumerator(this.span, this.separator); + public SpanTokenizer GetEnumerator() => this; /// - /// An enumerator for a source instance. + /// Implements the duck-typed method. /// - [EditorBrowsable(EditorBrowsableState.Never)] - public ref struct Enumerator + /// whether a new element is available, otherwise + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public bool MoveNext() { - /// - /// The source instance. - /// - private readonly Span span; - - /// - /// The separator item to use. - /// - private readonly T separator; - - /// - /// The current initial offset. - /// - private int start; - - /// - /// The current final offset. - /// - private int end; - - /// - /// Initializes a new instance of the struct. - /// - /// The source instance. - /// The separator item to use. - public Enumerator(Span span, T separator) - { - this.span = span; - this.separator = separator; - this.start = 0; - this.end = -1; - } + int + newEnd = this.end + 1, + length = this.span.Length; - /// - /// Implements the duck-typed method. - /// - /// whether a new element is available, otherwise - [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; - /// - /// Gets the duck-typed property. - /// - public Span Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => this.span.Slice(this.start, this.end - this.start); + return true; } + + return false; + } + + /// + /// Gets the duck-typed property. + /// + public Span Current + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + get => this.span.Slice(this.start, this.end - this.start); } } }