-
Notifications
You must be signed in to change notification settings - Fork 5.4k
Align ROS.Split handling of zero-length target strings with String.Split #37742
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,15 +15,19 @@ public static void SplitNoMatchSingleResult() | |
| ReadOnlySpan<char> value = "a b"; | ||
|
|
||
| string expected = value.ToString(); | ||
| var enumerator = value.Split(','); | ||
| SpanSplitEnumerator<char> enumerator = value.Split(','); | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(expected, value[enumerator.Current].ToString()); | ||
|
|
||
| enumerator = value.Split(","); | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(expected, value[enumerator.Current].ToString()); | ||
| } | ||
|
|
||
| [Fact] | ||
| public static void DefaultSpanSplitEnumeratorBehavior() | ||
| { | ||
| var charSpanEnumerator = new SpanSplitEnumerator<string>(); | ||
| var charSpanEnumerator = new SpanSplitEnumerator<char>(); | ||
| Assert.Equal(new Range(0, 0), charSpanEnumerator.Current); | ||
| Assert.False(charSpanEnumerator.MoveNext()); | ||
|
|
||
|
|
@@ -41,7 +45,7 @@ public static void ValidateArguments_OverloadWithoutSeparator() | |
| { | ||
| ReadOnlySpan<char> buffer = default; | ||
|
|
||
| SpanSplitEnumerator<char> enumerator = buffer.Split(); | ||
| SpanSplitEnumerator<char> enumerator = buffer.Split(); | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(new Range(0, 0), enumerator.Current); | ||
| Assert.False(enumerator.MoveNext()); | ||
|
|
@@ -67,27 +71,27 @@ public static void ValidateArguments_OverloadWithROSSeparator() | |
| // Default buffer | ||
| ReadOnlySpan<char> buffer = default; | ||
|
|
||
| SpanSplitEnumerator<char> enumerator = buffer.Split(default(char)); | ||
| SpanSplitEnumerator<char> enumerator = buffer.Split(default(char)); | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(enumerator.Current, new Range(0, 0)); | ||
| Assert.Equal(new Range(0, 0), enumerator.Current); | ||
| Assert.False(enumerator.MoveNext()); | ||
|
|
||
| enumerator = buffer.Split(' '); | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(enumerator.Current, new Range(0, 0)); | ||
| Assert.Equal(new Range(0, 0), enumerator.Current); | ||
| Assert.False(enumerator.MoveNext()); | ||
|
|
||
| // Empty buffer | ||
| buffer = ""; | ||
|
|
||
| enumerator = buffer.Split(default(char)); | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(enumerator.Current, new Range(0, 0)); | ||
| Assert.Equal(new Range(0, 0), enumerator.Current); | ||
| Assert.False(enumerator.MoveNext()); | ||
|
|
||
| enumerator = buffer.Split(' '); | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(enumerator.Current, new Range(0, 0)); | ||
| Assert.Equal(new Range(0, 0), enumerator.Current); | ||
| Assert.False(enumerator.MoveNext()); | ||
|
|
||
| // Single whitespace buffer | ||
|
|
@@ -114,60 +118,55 @@ public static void ValidateArguments_OverloadWithStringSeparator() | |
|
|
||
| SpanSplitEnumerator<char> enumerator = buffer.Split(null); // null is treated as empty string | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(enumerator.Current, new Range(0, 0)); | ||
| Assert.Equal(new Range(0, 0), enumerator.Current); | ||
| Assert.False(enumerator.MoveNext()); | ||
|
|
||
| enumerator = buffer.Split(""); | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(enumerator.Current, new Range(0, 0)); | ||
| Assert.Equal(new Range(0, 0), enumerator.Current); | ||
| Assert.False(enumerator.MoveNext()); | ||
|
|
||
| enumerator = buffer.Split(" "); | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(enumerator.Current, new Range(0, 0)); | ||
| Assert.Equal(new Range(0, 0), enumerator.Current); | ||
| Assert.False(enumerator.MoveNext()); | ||
|
|
||
| // Empty buffer | ||
| buffer = ""; | ||
|
|
||
| enumerator = buffer.Split(null); | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(enumerator.Current, new Range(0, 0)); | ||
| Assert.Equal(new Range(0, 0), enumerator.Current); | ||
| Assert.False(enumerator.MoveNext()); | ||
|
|
||
| enumerator = buffer.Split(""); | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(enumerator.Current, new Range(0, 0)); | ||
| Assert.Equal(new Range(0, 0), enumerator.Current); | ||
| Assert.False(enumerator.MoveNext()); | ||
|
|
||
| enumerator = buffer.Split(" "); | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(enumerator.Current, new Range(0, 0)); | ||
| Assert.Equal(new Range(0, 0), enumerator.Current); | ||
| Assert.False(enumerator.MoveNext()); | ||
|
|
||
| // Single whitespace buffer | ||
| buffer = " "; | ||
|
|
||
| enumerator = buffer.Split(null); // null is treated as empty string | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(enumerator.Current, new Range(0, 0)); | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(enumerator.Current, new Range(1, 1)); | ||
| Assert.Equal(new Range(0, 1), enumerator.Current); | ||
| Assert.False(enumerator.MoveNext()); | ||
|
|
||
| enumerator = buffer.Split(""); | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(enumerator.Current, new Range(0, 0)); | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(enumerator.Current, new Range(1, 1)); | ||
| Assert.Equal(new Range(0, 1), enumerator.Current); | ||
| Assert.False(enumerator.MoveNext()); | ||
|
|
||
| enumerator = buffer.Split(" "); | ||
| Assert.Equal(enumerator.Current, new Range(0, 0)); | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(enumerator.Current, new Range(0, 0)); | ||
| Assert.Equal(new Range(0, 0), enumerator.Current); | ||
| Assert.True(enumerator.MoveNext()); | ||
| Assert.Equal(enumerator.Current, new Range(1, 1)); | ||
| Assert.Equal(new Range(1, 1), enumerator.Current); | ||
| Assert.False(enumerator.MoveNext()); | ||
| } | ||
|
|
||
|
|
@@ -231,6 +230,14 @@ public static void SpanSplitDefaultCharSeparator(string valueParam, string[] exp | |
| } | ||
|
|
||
| [Theory] | ||
| [InlineData("a,b,c", null, new[] { "a,b,c" })] | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. empty string (value) ? |
||
| [InlineData("a,b,c", "", new[] { "a,b,c" })] | ||
| [InlineData("a,b,c,", null, new[] { "a,b,c," })] | ||
| [InlineData("a,b,c,", "", new[] { "a,b,c," })] | ||
| [InlineData(" a,b,c,", null, new[] { " a,b,c," })] | ||
| [InlineData(" a,b,c,", "", new[] { " a,b,c," })] | ||
| [InlineData("aaabaaabaaa", "aa", new[] { "", "ab", "ab", "a" })] | ||
| [InlineData("this, is, a, string, with some spaces", ", ", new[] { "this", "is", "a", "string", "with some spaces" })] | ||
| [InlineData(" Foo Bar Baz,", ", ", new[] { " Foo Bar Baz," })] | ||
| [InlineData(" Foo Bar Baz, ", ", ", new[] { " Foo Bar Baz", "" })] | ||
| [InlineData(", Foo Bar Baz, ", ", ", new[] { "", "Foo Bar Baz", "" })] | ||
|
|
@@ -251,7 +258,7 @@ private static void AssertEqual<T>(T[][] items, ReadOnlySpan<T> orig, SpanSplitE | |
| foreach (var item in items) | ||
| { | ||
| Assert.True(source.MoveNext()); | ||
| var slice = orig[source.Current]; | ||
| ReadOnlySpan<T> slice = orig[source.Current]; | ||
| Assert.Equal(item, slice.ToArray()); | ||
| } | ||
| Assert.False(source.MoveNext()); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -43,7 +43,7 @@ internal SpanSplitEnumerator(ReadOnlySpan<T> span, ReadOnlySpan<T> separators) | |
| _separators = separators; | ||
| _separator = default!; | ||
| _splitOnSingleToken = false; | ||
| _separatorLength = _separators.Length != 0 ? _separators.Length : 1; | ||
| _separatorLength = _separators.Length; | ||
| _startCurrent = 0; | ||
| _endCurrent = 0; | ||
| _startNext = 0; | ||
|
|
@@ -76,7 +76,22 @@ public bool MoveNext() | |
| ReadOnlySpan<T> slice = _buffer.Slice(_startNext); | ||
| _startCurrent = _startNext; | ||
|
|
||
| int separatorIndex = _splitOnSingleToken ? slice.IndexOf(_separator) : slice.IndexOf(_separators); | ||
| int separatorIndex; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Oh, nevermind, i did not realize |
||
| if (_splitOnSingleToken) | ||
| { | ||
| separatorIndex = slice.IndexOf(_separator); | ||
| } | ||
| else if (_separators.Length > 0) | ||
| { | ||
| separatorIndex = slice.IndexOf(_separators); | ||
| } | ||
| else | ||
| { | ||
| _endCurrent = _startCurrent + slice.Length; | ||
| _startNext = _endCurrent + 1; | ||
| return true; | ||
| } | ||
|
|
||
| int elementLength = (separatorIndex != -1 ? separatorIndex : slice.Length); | ||
|
|
||
| _endCurrent = _startCurrent + elementLength; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To align with the other changes from
vartoReadOnlySpan<T>.Same below, but for some reason cannot add a suggestion, as it is not part of the diff.