diff --git a/src/libraries/System.Memory/ref/System.Memory.cs b/src/libraries/System.Memory/ref/System.Memory.cs index 5fef7122c9ea67..9f42d49b21621c 100644 --- a/src/libraries/System.Memory/ref/System.Memory.cs +++ b/src/libraries/System.Memory/ref/System.Memory.cs @@ -518,6 +518,7 @@ public static void Sort(this System.Span keys, Sy private object _dummy; private int _dummyPrimitive; public readonly System.Range Current { get { throw null; } } + public readonly System.ReadOnlySpan Source { get { throw null; } } public System.MemoryExtensions.SpanSplitEnumerator GetEnumerator() { throw null; } public bool MoveNext() { throw null; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs index 7eba0654cf71c1..cae62dc6eb8894 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs @@ -5822,7 +5822,7 @@ private static bool TryWrite(Span destination, IForma public ref struct SpanSplitEnumerator where T : IEquatable { /// The input span being split. - private readonly ReadOnlySpan _span; + private readonly ReadOnlySpan _source; /// A single separator to use when is . private readonly T _separator = default!; @@ -5836,25 +5836,29 @@ private static bool TryWrite(Span destination, IForma /// Mode that dictates how the instance was configured and how its fields should be used in . private SpanSplitEnumeratorMode _splitMode; - /// The inclusive starting index in of the current range. + /// The inclusive starting index in of the current range. private int _startCurrent = 0; - /// The exclusive ending index in of the current range. + /// The exclusive ending index in of the current range. private int _endCurrent = 0; - /// The index in from which the next separator search should start. + /// The index in from which the next separator search should start. private int _startNext = 0; /// Gets an enumerator that allows for iteration over the split span. /// Returns a that can be used to iterate over the split span. public SpanSplitEnumerator GetEnumerator() => this; + /// Gets the source span being enumerated. + /// Returns the that was provided when creating this enumerator. + public readonly ReadOnlySpan Source => _source; + /// Gets the current element of the enumeration. /// Returns a instance that indicates the bounds of the current element withing the source span. public Range Current => new Range(_startCurrent, _endCurrent); /// Initializes the enumerator for . - internal SpanSplitEnumerator(ReadOnlySpan span, SearchValues searchValues) + internal SpanSplitEnumerator(ReadOnlySpan source, SearchValues searchValues) { - _span = span; + _source = source; _splitMode = SpanSplitEnumeratorMode.SearchValues; _searchValues = searchValues; } @@ -5865,9 +5869,9 @@ internal SpanSplitEnumerator(ReadOnlySpan span, SearchValues searchValues) /// it will instead use with a cached /// for all whitespace characters. /// - internal SpanSplitEnumerator(ReadOnlySpan span, ReadOnlySpan separators) + internal SpanSplitEnumerator(ReadOnlySpan source, ReadOnlySpan separators) { - _span = span; + _source = source; if (typeof(T) == typeof(char) && separators.Length == 0) { _searchValues = Unsafe.As>(string.SearchValuesStorage.WhiteSpaceChars); @@ -5882,11 +5886,11 @@ internal SpanSplitEnumerator(ReadOnlySpan span, ReadOnlySpan separators) /// Initializes the enumerator for (or if the separator is empty). /// must be true. - internal SpanSplitEnumerator(ReadOnlySpan span, ReadOnlySpan separator, bool treatAsSingleSeparator) + internal SpanSplitEnumerator(ReadOnlySpan source, ReadOnlySpan separator, bool treatAsSingleSeparator) { Debug.Assert(treatAsSingleSeparator, "Should only ever be called as true; exists to differentiate from separators overload"); - _span = span; + _source = source; _separatorBuffer = separator; _splitMode = separator.Length == 0 ? SpanSplitEnumeratorMode.EmptySequence : @@ -5894,9 +5898,9 @@ internal SpanSplitEnumerator(ReadOnlySpan span, ReadOnlySpan separator, bo } /// Initializes the enumerator for . - internal SpanSplitEnumerator(ReadOnlySpan span, T separator) + internal SpanSplitEnumerator(ReadOnlySpan source, T separator) { - _span = span; + _source = source; _separator = separator; _splitMode = SpanSplitEnumeratorMode.SingleElement; } @@ -5915,17 +5919,17 @@ public bool MoveNext() return false; case SpanSplitEnumeratorMode.SingleElement: - separatorIndex = _span.Slice(_startNext).IndexOf(_separator); + separatorIndex = _source.Slice(_startNext).IndexOf(_separator); separatorLength = 1; break; case SpanSplitEnumeratorMode.Any: - separatorIndex = _span.Slice(_startNext).IndexOfAny(_separatorBuffer); + separatorIndex = _source.Slice(_startNext).IndexOfAny(_separatorBuffer); separatorLength = 1; break; case SpanSplitEnumeratorMode.Sequence: - separatorIndex = _span.Slice(_startNext).IndexOf(_separatorBuffer); + separatorIndex = _source.Slice(_startNext).IndexOf(_separatorBuffer); separatorLength = _separatorBuffer.Length; break; @@ -5936,7 +5940,7 @@ public bool MoveNext() default: Debug.Assert(_splitMode == SpanSplitEnumeratorMode.SearchValues, $"Unknown split mode: {_splitMode}"); - separatorIndex = _span.Slice(_startNext).IndexOfAny(_searchValues); + separatorIndex = _source.Slice(_startNext).IndexOfAny(_searchValues); separatorLength = 1; break; } @@ -5949,7 +5953,7 @@ public bool MoveNext() } else { - _startNext = _endCurrent = _span.Length; + _startNext = _endCurrent = _source.Length; // Set _splitMode to None so that subsequent MoveNext calls will return false. _splitMode = SpanSplitEnumeratorMode.None; diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/String.SplitTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/String.SplitTests.cs index 3ed49c1ef14921..1cda74cfda28d6 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/String.SplitTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/String.SplitTests.cs @@ -730,9 +730,11 @@ private static void AssertEqual(string[] items, ReadOnlySpan source, Memor { Assert.True(enumerator.MoveNext()); Assert.Equal(item, source[enumerator.Current].ToString()); + Assert.Equal(source.ToString(), enumerator.Source.ToString()); } Assert.False(enumerator.MoveNext()); + Assert.Equal(source.ToString(), enumerator.Source.ToString()); } } }