Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

Commit

Permalink
Add StringBuilder Span-based APIs (dotnet/coreclr#13163)
Browse files Browse the repository at this point in the history
* Add StringBuilder Span-based APIs

* Factorized ThreadSafeCopy methods

The char[] based one was called only by CopyTo so it wasn't needed anymore. Replaced by a Span based version

* Fix possible overflow

Signed-off-by: dotnet-bot <[email protected]>
  • Loading branch information
kevingosse authored and jkotas committed Aug 9, 2017
1 parent 9996cbc commit 3390e45
Showing 1 changed file with 58 additions and 15 deletions.
73 changes: 58 additions & 15 deletions src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)));
Expand All @@ -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<char>(destination, destinationIndex), count);
}

public void CopyTo(int sourceIndex, Span<char> destination, int count)
{
if (count < 0)
{
throw new ArgumentOutOfRangeException(nameof(count), SR.Arg_NegativeArgCount);
}

if ((uint)sourceIndex > (uint)Length)
{
Expand All @@ -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;
Expand Down Expand Up @@ -1033,6 +1039,21 @@ public StringBuilder Append(char[] value)
return this;
}

public StringBuilder Append(ReadOnlySpan<char> 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)
Expand Down Expand Up @@ -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<char> value)
{
Contract.Ensures(Contract.Result<StringBuilder>() != 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));
Expand Down Expand Up @@ -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<char> 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);
}
}

Expand Down

0 comments on commit 3390e45

Please sign in to comment.