diff --git a/src/mscorlib/shared/System/Text/StringBuilder.cs b/src/mscorlib/shared/System/Text/StringBuilder.cs index 34533a92ca1c..a474f9aaf23a 100644 --- a/src/mscorlib/shared/System/Text/StringBuilder.cs +++ b/src/mscorlib/shared/System/Text/StringBuilder.cs @@ -822,11 +822,6 @@ public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, in throw new ArgumentNullException(nameof(destination)); } - if (count < 0) - { - throw new ArgumentOutOfRangeException(nameof(count), SR.Arg_NegativeArgCount); - } - if (destinationIndex < 0) { throw new ArgumentOutOfRangeException(nameof(destinationIndex), SR.Format(SR.ArgumentOutOfRange_MustBeNonNegNum, nameof(destinationIndex))); @@ -836,6 +831,17 @@ public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, in { throw new ArgumentException(SR.ArgumentOutOfRange_OffsetOut); } + Contract.EndContractBlock(); + + CopyTo(sourceIndex, new Span(destination, destinationIndex), count); + } + + public void CopyTo(int sourceIndex, Span destination, int count) + { + if (count < 0) + { + throw new ArgumentOutOfRangeException(nameof(count), SR.Arg_NegativeArgCount); + } if ((uint)sourceIndex > (uint)Length) { @@ -852,7 +858,7 @@ public void CopyTo(int sourceIndex, char[] destination, int destinationIndex, in StringBuilder chunk = this; int sourceEndIndex = sourceIndex + count; - int curDestIndex = destinationIndex + count; + int curDestIndex = count; while (count > 0) { int chunkEndIndex = sourceEndIndex - chunk.m_ChunkOffset; @@ -1033,6 +1039,21 @@ public StringBuilder Append(char[] value) return this; } + public StringBuilder Append(ReadOnlySpan value) + { + if (value.Length > 0) + { + unsafe + { + fixed (char* valueChars = &value.DangerousGetPinnableReference()) + { + Append(valueChars, value.Length); + } + } + } + return this; + } + #region AppendJoin public unsafe StringBuilder AppendJoin(string separator, params object[] values) @@ -1263,6 +1284,27 @@ public StringBuilder Insert(int index, char[] value, int startIndex, int charCou public StringBuilder Insert(int index, Object value) => (value == null) ? this : Insert(index, value.ToString(), 1); + public StringBuilder Insert(int index, ReadOnlySpan value) + { + Contract.Ensures(Contract.Result() != null); + Contract.EndContractBlock(); + + if ((uint)index > (uint)Length) + { + throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); + } + + if (value.Length > 0) + { + unsafe + { + fixed (char* sourcePtr = &value.DangerousGetPinnableReference()) + Insert(index, sourcePtr, value.Length); + } + } + return this; + } + public StringBuilder AppendFormat(String format, Object arg0) => AppendFormatHelper(null, format, new ParamsArray(arg0)); public StringBuilder AppendFormat(String format, Object arg0, Object arg1) => AppendFormatHelper(null, format, new ParamsArray(arg0, arg1)); @@ -2001,22 +2043,23 @@ private static unsafe void ThreadSafeCopy(char* sourcePtr, char[] destination, i } } - private static void ThreadSafeCopy(char[] source, int sourceIndex, char[] destination, int destinationIndex, int count) + private static unsafe void ThreadSafeCopy(char[] source, int sourceIndex, Span destination, int destinationIndex, int count) { if (count > 0) { - if ((uint)sourceIndex <= (uint)source.Length && (sourceIndex + count) <= source.Length) + if ((uint)sourceIndex > (uint)source.Length || count > source.Length - sourceIndex) { - unsafe - { - fixed (char* sourcePtr = &source[sourceIndex]) - ThreadSafeCopy(sourcePtr, destination, destinationIndex, count); - } + throw new ArgumentOutOfRangeException(nameof(sourceIndex), SR.ArgumentOutOfRange_Index); } - else + + if ((uint)destinationIndex > (uint)destination.Length || count > destination.Length - destinationIndex) { - throw new ArgumentOutOfRangeException(nameof(sourceIndex), SR.ArgumentOutOfRange_Index); + throw new ArgumentOutOfRangeException(nameof(destinationIndex), SR.ArgumentOutOfRange_Index); } + + fixed (char* sourcePtr = &source[sourceIndex]) + fixed (char* destinationPtr = &destination.DangerousGetPinnableReference()) + string.wstrcpy(destinationPtr + destinationIndex, sourcePtr, count); } }