Skip to content

Commit 6c4f45c

Browse files
authored
Make String.{Try}CopyTo public (#53246)
1 parent 293d472 commit 6c4f45c

File tree

12 files changed

+61
-24
lines changed

12 files changed

+61
-24
lines changed

src/libraries/Common/src/System/Net/SocketAddress.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ public override string ToString()
251251
stackalloc char[256] :
252252
new char[maxLength];
253253

254-
familyString.AsSpan().CopyTo(result);
254+
familyString.CopyTo(result);
255255
int length = familyString.Length;
256256

257257
result[length++] = ':';

src/libraries/Common/src/System/Text/ValueStringBuilder.cs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,10 +158,9 @@ public void Insert(int index, string? s)
158158

159159
int remaining = _pos - index;
160160
_chars.Slice(index, remaining).CopyTo(_chars.Slice(index + count));
161-
#if SYSTEM_PRIVATE_CORELIB
162161
s
163-
#else
164-
s.AsSpan()
162+
#if !NET6_0_OR_GREATER
163+
.AsSpan()
165164
#endif
166165
.CopyTo(_chars.Slice(index));
167166
_pos += count;
@@ -210,10 +209,9 @@ private void AppendSlow(string s)
210209
Grow(s.Length);
211210
}
212211

213-
#if SYSTEM_PRIVATE_CORELIB
214212
s
215-
#else
216-
s.AsSpan()
213+
#if !NET6_0_OR_GREATER
214+
.AsSpan()
217215
#endif
218216
.CopyTo(_chars.Slice(pos));
219217
_pos += s.Length;

src/libraries/Common/tests/Tests/System/StringTests.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,42 @@ public static void CopyTo_Invalid()
482482
AssertExtensions.Throws<ArgumentOutOfRangeException>("sourceIndex", () => s.CopyTo(0, dst, 0, 6));
483483
}
484484

485+
[Theory]
486+
[InlineData("", 0)]
487+
[InlineData("", 1)]
488+
[InlineData("a", 1)]
489+
[InlineData("a", 0)]
490+
[InlineData("a", 2)]
491+
[InlineData("abc", 2)]
492+
[InlineData("abc", 3)]
493+
[InlineData("abc", 4)]
494+
[InlineData("Hello world", 20)]
495+
public static void CopyTo_Span(string s, int destinationLength)
496+
{
497+
char[] destination = new char[destinationLength];
498+
499+
if (s.Length > destinationLength)
500+
{
501+
AssertExtensions.Throws<ArgumentException>("destination", () => s.CopyTo(destination));
502+
Assert.All(destination, c => Assert.Equal(0, c));
503+
504+
Assert.False(s.TryCopyTo(destination));
505+
Assert.All(destination, c => Assert.Equal(0, c));
506+
}
507+
else
508+
{
509+
s.CopyTo(destination);
510+
Assert.Equal(s, new Span<char>(destination, 0, s.Length).ToString());
511+
Assert.All(destination.AsSpan(s.Length).ToArray(), c => Assert.Equal(0, c));
512+
513+
Array.Clear(destination, 0, destination.Length);
514+
515+
Assert.True(s.TryCopyTo(destination));
516+
Assert.Equal(s, new Span<char>(destination, 0, s.Length).ToString());
517+
Assert.All(destination.AsSpan(s.Length).ToArray(), c => Assert.Equal(0, c));
518+
}
519+
}
520+
485521
public static IEnumerable<object[]> Compare_TestData()
486522
{
487523
// CurrentCulture

src/libraries/System.Diagnostics.TextWriterTraceListener/src/System/Diagnostics/XmlWriterTraceListener.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,14 @@ public override void Fail(string? message, string? detailMessage)
7171
TraceEvent(null, SR.TraceAsTraceSource, TraceEventType.Error, 0, string.Create(length, (message, detailMessage),
7272
(dst, v) =>
7373
{
74-
ReadOnlySpan<char> prefix = v.message;
74+
string prefix = v.message;
7575
prefix.CopyTo(dst);
7676

7777
if (v.detailMessage != null)
7878
{
7979
dst[prefix.Length] = ' ';
8080

81-
ReadOnlySpan<char> detail = v.detailMessage;
81+
string detail = v.detailMessage;
8282
detail.CopyTo(dst.Slice(prefix.Length + 1, detail.Length));
8383
}
8484
}));

src/libraries/System.Private.CoreLib/src/System/String.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -461,14 +461,11 @@ public unsafe void CopyTo(int sourceIndex, char[] destination, int destinationIn
461461
elementCount: (uint)count);
462462
}
463463

464-
// TODO: https://github.com/dotnet/runtime/issues/51061
465-
// Make these {Try}CopyTo methods public and use throughout dotnet/runtime.
466-
467464
/// <summary>Copies the contents of this string into the destination span.</summary>
468465
/// <param name="destination">The span into which to copy this string's contents.</param>
469466
/// <exception cref="System.ArgumentException">The destination span is shorter than the source string.</exception>
470467
[MethodImpl(MethodImplOptions.AggressiveInlining)]
471-
internal void CopyTo(Span<char> destination)
468+
public void CopyTo(Span<char> destination)
472469
{
473470
if ((uint)Length <= (uint)destination.Length)
474471
{
@@ -484,7 +481,7 @@ internal void CopyTo(Span<char> destination)
484481
/// <param name="destination">The span into which to copy this string's contents.</param>
485482
/// <returns>true if the data was copied; false if the destination was too short to fit the contents of the string.</returns>
486483
[MethodImpl(MethodImplOptions.AggressiveInlining)]
487-
internal bool TryCopyTo(Span<char> destination)
484+
public bool TryCopyTo(Span<char> destination)
488485
{
489486
bool retVal = false;
490487
if ((uint)Length <= (uint)destination.Length)

src/libraries/System.Private.Xml/src/System/Xml/Serialization/CodeIdentifier.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public static string MakePascal(string identifier)
3535
{
3636
return string.Create(identifier.Length, identifier, static (buffer, identifier) =>
3737
{
38-
identifier.AsSpan().CopyTo(buffer);
38+
identifier.CopyTo(buffer);
3939
buffer[0] = char.ToUpperInvariant(buffer[0]); // convert only first char to uppercase; leave all else as-is
4040
});
4141
}
@@ -59,7 +59,7 @@ public static string MakeCamel(string identifier)
5959
{
6060
return string.Create(identifier.Length, identifier, static (buffer, identifier) =>
6161
{
62-
identifier.AsSpan().CopyTo(buffer);
62+
identifier.CopyTo(buffer);
6363
buffer[0] = char.ToLowerInvariant(buffer[0]); // convert only first char to lowercase; leave all else as-is
6464
});
6565
}

src/libraries/System.Runtime/ref/System.Runtime.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3632,6 +3632,7 @@ public unsafe String(sbyte* value, int startIndex, int length, System.Text.Encod
36323632
[System.ObsoleteAttribute("This API should not be used to create mutable strings. See https://go.microsoft.com/fwlink/?linkid=2084035 for alternatives.")]
36333633
public static System.String Copy(System.String str) { throw null; }
36343634
public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, int count) { }
3635+
public void CopyTo(System.Span<char> destination) { }
36353636
public static System.String Create<TState>(int length, TState state, System.Buffers.SpanAction<char, TState> action) { throw null; }
36363637
public bool EndsWith(char value) { throw null; }
36373638
public bool EndsWith(System.String value) { throw null; }
@@ -3767,6 +3768,7 @@ public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, in
37673768
public System.String TrimStart() { throw null; }
37683769
public System.String TrimStart(char trimChar) { throw null; }
37693770
public System.String TrimStart(params char[]? trimChars) { throw null; }
3771+
public bool TryCopyTo(System.Span<char> destination) { throw null; }
37703772
}
37713773
public abstract partial class StringComparer : System.Collections.Generic.IComparer<string?>, System.Collections.Generic.IEqualityComparer<string?>, System.Collections.IComparer, System.Collections.IEqualityComparer
37723774
{

src/libraries/System.Security.Cryptography.Encoding/src/System/Security/Cryptography/PemEncoding.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,9 @@ static ReadOnlySpan<char> WritePostEB(ReadOnlySpan<char> label, Span<char> desti
168168
{
169169
int size = PostEBPrefix.Length + label.Length + Ending.Length;
170170
Debug.Assert(destination.Length >= size);
171-
PostEBPrefix.AsSpan().CopyTo(destination);
171+
PostEBPrefix.CopyTo(destination);
172172
label.CopyTo(destination.Slice(PostEBPrefix.Length));
173-
Ending.AsSpan().CopyTo(destination.Slice(PostEBPrefix.Length + label.Length));
173+
Ending.CopyTo(destination.Slice(PostEBPrefix.Length + label.Length));
174174
return destination.Slice(0, size);
175175
}
176176
}

src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/OpenSslX509ChainProcessor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -740,7 +740,7 @@ private static string UrlPathAppend(string baseUri, ReadOnlyMemory<char> resourc
740740
(baseUri, resource),
741741
(buf, st) =>
742742
{
743-
st.baseUri.AsSpan().CopyTo(buf);
743+
st.baseUri.CopyTo(buf);
744744
st.resource.Span.CopyTo(buf.Slice(st.baseUri.Length));
745745
});
746746
}
@@ -750,7 +750,7 @@ private static string UrlPathAppend(string baseUri, ReadOnlyMemory<char> resourc
750750
(baseUri, resource),
751751
(buf, st) =>
752752
{
753-
st.baseUri.AsSpan().CopyTo(buf);
753+
st.baseUri.CopyTo(buf);
754754
buf[st.baseUri.Length] = '/';
755755
st.resource.Span.CopyTo(buf.Slice(st.baseUri.Length + 1));
756756
});

src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonCamelCaseNamingPolicy.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ public override string ConvertName(string name)
1515
#if BUILDING_INBOX_LIBRARY
1616
return string.Create(name.Length, name, (chars, name) =>
1717
{
18-
name.AsSpan().CopyTo(chars);
18+
name
19+
#if !NET6_0_OR_GREATER
20+
.AsSpan()
21+
#endif
22+
.CopyTo(chars);
1923
FixCasing(chars);
2024
});
2125
#else

src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCharClass.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,11 +576,11 @@ public static string ConvertOldStringsToClass(string set, string category)
576576
span[FlagsIndex] = '\0';
577577
span[SetLengthIndex] = (char)state.set.Length;
578578
span[CategoryLengthIndex] = (char)state.category.Length;
579-
state.set.AsSpan().CopyTo(span.Slice(SetStartIndex));
579+
state.set.CopyTo(span.Slice(SetStartIndex));
580580
index = SetStartIndex + state.set.Length;
581581
}
582582

583-
state.category.AsSpan().CopyTo(span.Slice(index));
583+
state.category.CopyTo(span.Slice(index));
584584
});
585585
}
586586

src/libraries/System.Web.HttpUtility/src/System/Web/Util/Utf16StringValidator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ internal static string ValidateString(string input)
3434
// slow case: surrogates exist, so we need to validate them
3535
return string.Create(input.Length, (input, idxOfFirstSurrogate), (chars, state) =>
3636
{
37-
state.input.AsSpan().CopyTo(chars);
37+
state.input.CopyTo(chars);
3838
for (int i = state.idxOfFirstSurrogate; i < chars.Length; i++)
3939
{
4040
char thisChar = chars[i];

0 commit comments

Comments
 (0)