Thanks to visit codestin.com
Credit goes to github.com

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
1 change: 1 addition & 0 deletions src/libraries/System.Memory/ref/System.Memory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ public static void CopyTo<T>(this T[]? source, System.Span<T> destination) { }
public static bool Overlaps<T>(this System.Span<T> span, System.ReadOnlySpan<T> other) { throw null; }
public static bool Overlaps<T>(this System.Span<T> span, System.ReadOnlySpan<T> other, out int elementOffset) { throw null; }
public static void Replace<T>(this System.Span<T> span, T oldValue, T newValue) where T : System.IEquatable<T>? { }
public static void Replace<T>(this System.ReadOnlySpan<T> source, System.Span<T> destination, T oldValue, T newValue) where T : System.IEquatable<T>? { }
public static void Reverse<T>(this System.Span<T> span) { }
public static int SequenceCompareTo<T>(this System.ReadOnlySpan<T> span, System.ReadOnlySpan<T> other) where T : System.IComparable<T>? { throw null; }
public static int SequenceCompareTo<T>(this System.Span<T> span, System.ReadOnlySpan<T> other) where T : System.IComparable<T>? { throw null; }
Expand Down
165 changes: 146 additions & 19 deletions src/libraries/System.Memory/tests/Span/Replace.T.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,38 @@ public class ReplaceTests_Double : ReplaceTests<double> { protected override dou
public class ReplaceTests_Record : ReplaceTests<SimpleRecord> { protected override SimpleRecord Create(int value) => new SimpleRecord(value); }
public class ReplaceTests_CustomEquatable : ReplaceTests<CustomEquatable> { protected override CustomEquatable Create(int value) => new CustomEquatable((byte)value); }

public class ReplaceTests_String : ReplaceTests<string>
{
protected override string Create(int value) => value.ToString();

[Fact]
public void NullOld_NonNullOriginal_CopiedCorrectly()
{
string[] orig = new string[] { "a", "b", "c" };
string[] actual = new string[orig.Length];
((ReadOnlySpan<string>)orig).Replace(actual, null, "d");
Assert.Equal(orig, actual);
}

[Fact]
public void NullOld_NullOriginal_CopiedCorrectly()
{
string[] orig = new string[] { "a", null, "c" };
string[] actual = new string[orig.Length];
((ReadOnlySpan<string>)orig).Replace(actual, null, "b");
Assert.Equal(new string[] { "a", "b", "c" }, actual);
}

[Fact]
public void NonNullOld_NullOriginal_CopiedCorrectly()
{
string[] orig = new string[] { "a", null, "c" };
string[] actual = new string[orig.Length];
((ReadOnlySpan<string>)orig).Replace(actual, "d", "b");
Assert.Equal(orig, actual);
}
}

public readonly struct CustomEquatable : IEquatable<CustomEquatable>
{
public byte Value { get; }
Expand All @@ -36,57 +68,113 @@ protected ReplaceTests()
}

[Fact]
public void ZeroLengthSpan()
public void ZeroLengthSpan_InPlace()
{
Exception actual = Record.Exception(() => Span<T>.Empty.Replace(_oldValue, _newValue));
Span<T>.Empty.Replace(_oldValue, _newValue);
}

Assert.Null(actual);
[Fact]
public void ZeroLengthSpan_Copy()
{
ReadOnlySpan<T>.Empty.Replace(Span<T>.Empty, _oldValue, _newValue);
}

[Fact]
public void ArgumentValidation_Copy()
{
AssertExtensions.Throws<ArgumentException>("destination", () => ((ReadOnlySpan<T>)new T[] { _oldValue }).Replace(Span<T>.Empty, _oldValue, _newValue));

T[] values = new T[] { _oldValue, _oldValue, _oldValue };
AssertExtensions.Throws<ArgumentException>(null, () => new ReadOnlySpan<T>(values, 0, 2).Replace(new Span<T>(values, 1, 2), _oldValue, _newValue));
}

[Theory]
[MemberData(nameof(Length_MemberData))]
public void AllElementsNeedToBeReplaced(int length)
public void AllElementsNeedToBeReplaced_InPlace(int length)
{
Span<T> span = CreateArray(length, _oldValue);
T[] expected = CreateArray(length, _newValue);

span.Replace(_oldValue, _newValue);
T[] actual = span.ToArray();

Assert.Equal(expected, actual);
Assert.Equal(CreateArray(length, _newValue), span.ToArray());
}

[Theory]
[MemberData(nameof(Length_MemberData))]
public void AllElementsNeedToBeReplaced_Copy(int length)
{
ReadOnlySpan<T> span = CreateArray(length, _oldValue);
T[] original = span.ToArray();

T[] destination = new T[span.Length];
span.Replace(destination, _oldValue, _newValue);
Assert.Equal(CreateArray(length, _newValue), destination);
Assert.Equal(original, span.ToArray());

destination = new T[span.Length + 1];
span.Replace(destination, _oldValue, _newValue);
Assert.Equal(CreateArray(length, _newValue), destination[0..^1]);
Assert.Equal(default, destination[^1]);
Assert.Equal(original, span.ToArray());
}

[Theory]
[MemberData(nameof(Length_MemberData))]
public void DefaultToBeReplaced(int length)
public void DefaultToBeReplaced_InPlace(int length)
{
Span<T> span = CreateArray(length);
T[] expected = CreateArray(length, _newValue);

span.Replace(default, _newValue);
T[] actual = span.ToArray();

Assert.Equal(expected, actual);
Assert.Equal(CreateArray(length, _newValue), span.ToArray());
}

[Theory]
[MemberData(nameof(Length_MemberData))]
public void DefaultToBeReplaced_Copy(int length)
{
ReadOnlySpan<T> span = CreateArray(length);
T[] original = span.ToArray();

T[] destination = new T[span.Length];
span.Replace(destination, default, _newValue);

Assert.Equal(original, span.ToArray());
Assert.Equal(CreateArray(length, _newValue), destination);
}

[Theory]
[MemberData(nameof(Length_MemberData))]
public void NoElementsNeedToBeReplaced(int length)
public void NoElementsNeedToBeReplaced_InPlace(int length)
{
T[] values = { Create('0'), Create('1') };

Span<T> span = CreateArray(length, values);
T[] expected = span.ToArray();
T[] original = span.ToArray();

span.Replace(_oldValue, _newValue);
T[] actual = span.ToArray();

Assert.Equal(expected, actual);
Assert.Equal(original, span.ToArray());
}

[Theory]
[MemberData(nameof(Length_MemberData))]
public void SomeElementsNeedToBeReplaced(int length)
public void NoElementsNeedToBeReplaced_Copy(int length)
{
T[] values = { Create('0'), Create('1') };

ReadOnlySpan<T> span = CreateArray(length, values);
T[] original = span.ToArray();

T[] destination = span.ToArray();
span.Replace(destination, _oldValue, _newValue);

Assert.Equal(original, destination);
}

[Theory]
[MemberData(nameof(Length_MemberData))]
public void SomeElementsNeedToBeReplaced_InPlace(int length)
{
T[] values = { Create('0'), Create('1') };

Expand All @@ -106,7 +194,29 @@ public void SomeElementsNeedToBeReplaced(int length)

[Theory]
[MemberData(nameof(Length_MemberData))]
public void OldAndNewValueAreSame(int length)
public void SomeElementsNeedToBeReplaced_Copy(int length)
{
T[] values = { Create('0'), Create('1') };

Span<T> span = CreateArray(length, values);
span[0] = _oldValue;
span[^1] = _oldValue;
T[] original = span.ToArray();

T[] expected = CreateArray(length, values);
expected[0] = _newValue;
expected[^1] = _newValue;

T[] destination = new T[expected.Length];
((ReadOnlySpan<T>)span).Replace(destination, _oldValue, _newValue);

Assert.Equal(original, span.ToArray());
Assert.Equal(expected, destination);
}

[Theory]
[MemberData(nameof(Length_MemberData))]
public void OldAndNewValueAreSame_InPlace(int length)
{
T[] values = { Create('0'), Create('1') };

Expand All @@ -116,9 +226,26 @@ public void OldAndNewValueAreSame(int length)
T[] expected = span.ToArray();

span.Replace(_oldValue, _oldValue);
T[] actual = span.ToArray();

Assert.Equal(expected, actual);
Assert.Equal(expected, span.ToArray());
}

[Theory]
[MemberData(nameof(Length_MemberData))]
public void OldAndNewValueAreSame_Copy(int length)
{
T[] values = { Create('0'), Create('1') };

Span<T> span = CreateArray(length, values);
span[0] = _oldValue;
span[^1] = _oldValue;
T[] expected = span.ToArray();

T[] destination = new T[expected.Length];
((ReadOnlySpan<T>)span).Replace(destination, _oldValue, _oldValue);

Assert.Equal(expected, span.ToArray());
Assert.Equal(expected, destination);
}

public static IEnumerable<object[]> Length_MemberData()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ internal static int LastIndexOfOrdinalIgnoreCase(ReadOnlySpan<char> source, Read
internal static int ToUpperOrdinal(ReadOnlySpan<char> source, Span<char> destination)
{
if (source.Overlaps(destination))
throw new InvalidOperationException(SR.InvalidOperation_SpanOverlappedOperation);
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_SpanOverlappedOperation);

// Assuming that changing case does not affect length
if (destination.Length < source.Length)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ ref MemoryMarshal.GetReference(value),
public static int ToLower(this ReadOnlySpan<char> source, Span<char> destination, CultureInfo? culture)
{
if (source.Overlaps(destination))
throw new InvalidOperationException(SR.InvalidOperation_SpanOverlappedOperation);
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_SpanOverlappedOperation);

culture ??= CultureInfo.CurrentCulture;

Expand All @@ -223,7 +223,7 @@ public static int ToLower(this ReadOnlySpan<char> source, Span<char> destination
public static int ToLowerInvariant(this ReadOnlySpan<char> source, Span<char> destination)
{
if (source.Overlaps(destination))
throw new InvalidOperationException(SR.InvalidOperation_SpanOverlappedOperation);
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_SpanOverlappedOperation);

// Assuming that changing case does not affect length
if (destination.Length < source.Length)
Expand All @@ -249,7 +249,7 @@ public static int ToLowerInvariant(this ReadOnlySpan<char> source, Span<char> de
public static int ToUpper(this ReadOnlySpan<char> source, Span<char> destination, CultureInfo? culture)
{
if (source.Overlaps(destination))
throw new InvalidOperationException(SR.InvalidOperation_SpanOverlappedOperation);
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_SpanOverlappedOperation);

culture ??= CultureInfo.CurrentCulture;

Expand All @@ -275,7 +275,7 @@ public static int ToUpper(this ReadOnlySpan<char> source, Span<char> destination
public static int ToUpperInvariant(this ReadOnlySpan<char> source, Span<char> destination)
{
if (source.Overlaps(destination))
throw new InvalidOperationException(SR.InvalidOperation_SpanOverlappedOperation);
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_SpanOverlappedOperation);

// Assuming that changing case does not affect length
if (destination.Length < source.Length)
Expand Down
Loading