Skip to content

Commit

Permalink
Remove some calls to wstrcpy (#32342)
Browse files Browse the repository at this point in the history
  • Loading branch information
GrabYourPitchforks authored Feb 21, 2020
1 parent 4c1fca6 commit 70c1e9d
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public partial class String
{
private const int StackallocIntBufferSizeLimit = 128;

private static unsafe void FillStringChecked(string dest, int destPos, string src)
private static void FillStringChecked(string dest, int destPos, string src)
{
Debug.Assert(dest != null);
Debug.Assert(src != null);
Expand All @@ -24,11 +24,10 @@ private static unsafe void FillStringChecked(string dest, int destPos, string sr
throw new IndexOutOfRangeException();
}

fixed (char* pDest = &dest._firstChar)
fixed (char* pSrc = &src._firstChar)
{
wstrcpy(pDest + destPos, pSrc, src.Length);
}
Buffer.Memmove(
destination: ref Unsafe.Add(ref dest._firstChar, destPos),
source: ref src._firstChar,
elementCount: (uint)src.Length);
}

public static string Concat(object? arg0) => arg0?.ToString() ?? string.Empty;
Expand Down Expand Up @@ -1665,18 +1664,17 @@ public string Substring(int startIndex, int length)
return InternalSubString(startIndex, length);
}

private unsafe string InternalSubString(int startIndex, int length)
private string InternalSubString(int startIndex, int length)
{
Debug.Assert(startIndex >= 0 && startIndex <= this.Length, "StartIndex is out of range!");
Debug.Assert(length >= 0 && startIndex <= this.Length - length, "length is out of range!");

string result = FastAllocateString(length);

fixed (char* dest = &result._firstChar)
fixed (char* src = &_firstChar)
{
wstrcpy(dest, src + startIndex, length);
}
Buffer.Memmove(
elementCount: (uint)result.Length, // derefing Length now allows JIT to prove 'result' not null below
destination: ref result._firstChar,
source: ref Unsafe.Add(ref _firstChar, startIndex));

return result;
}
Expand Down
72 changes: 48 additions & 24 deletions src/libraries/System.Private.CoreLib/src/System/String.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,12 @@ private string Ctor(char[]? value)
return Empty;

string result = FastAllocateString(value.Length);
unsafe
{
fixed (char* dest = &result._firstChar, source = value)
wstrcpy(dest, source, value.Length);
}

Buffer.Memmove(
elementCount: (uint)result.Length, // derefing Length now allows JIT to prove 'result' not null below
destination: ref result._firstChar,
source: ref MemoryMarshal.GetArrayDataReference(value));

return result;
}

Expand Down Expand Up @@ -91,11 +92,12 @@ private string Ctor(char[] value, int startIndex, int length)
return Empty;

string result = FastAllocateString(length);
unsafe
{
fixed (char* dest = &result._firstChar, source = value)
wstrcpy(dest, source + startIndex, length);
}

Buffer.Memmove(
elementCount: (uint)result.Length, // derefing Length now allows JIT to prove 'result' not null below
destination: ref result._firstChar,
source: ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(value), startIndex));

return result;
}

Expand All @@ -117,8 +119,12 @@ private unsafe string Ctor(char* ptr)
return Empty;

string result = FastAllocateString(count);
fixed (char* dest = &result._firstChar)
wstrcpy(dest, ptr, count);

Buffer.Memmove(
elementCount: (uint)result.Length, // derefing Length now allows JIT to prove 'result' not null below
destination: ref result._firstChar,
source: ref *ptr);

return result;
}

Expand Down Expand Up @@ -151,8 +157,12 @@ private unsafe string Ctor(char* ptr, int startIndex, int length)
throw new ArgumentOutOfRangeException(nameof(ptr), SR.ArgumentOutOfRange_PartialWCHAR);

string result = FastAllocateString(length);
fixed (char* dest = &result._firstChar)
wstrcpy(dest, pStart, length);

Buffer.Memmove(
elementCount: (uint)result.Length, // derefing Length now allows JIT to prove 'result' not null below
destination: ref result._firstChar,
source: ref *pStart);

return result;
}

Expand Down Expand Up @@ -370,8 +380,12 @@ public static unsafe string Copy(string str)
throw new ArgumentNullException(nameof(str));

string result = FastAllocateString(str.Length);
fixed (char* dest = &result._firstChar, src = &str._firstChar)
wstrcpy(dest, src, str.Length);

Buffer.Memmove(
elementCount: (uint)result.Length, // derefing Length now allows JIT to prove 'result' not null below
destination: ref result._firstChar,
source: ref str._firstChar);

return result;
}

Expand All @@ -393,25 +407,31 @@ public unsafe void CopyTo(int sourceIndex, char[] destination, int destinationIn
if (destinationIndex > destination.Length - count || destinationIndex < 0)
throw new ArgumentOutOfRangeException(nameof(destinationIndex), SR.ArgumentOutOfRange_IndexCount);

fixed (char* src = &_firstChar, dest = destination)
wstrcpy(dest + destinationIndex, src + sourceIndex, count);
Buffer.Memmove(
destination: ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(destination), destinationIndex),
source: ref Unsafe.Add(ref _firstChar, sourceIndex),
elementCount: (uint)count);
}

// Returns the entire string as an array of characters.
public unsafe char[] ToCharArray()
public char[] ToCharArray()
{
if (Length == 0)
return Array.Empty<char>();

char[] chars = new char[Length];
fixed (char* src = &_firstChar, dest = &chars[0])
wstrcpy(dest, src, Length);

Buffer.Memmove(
destination: ref MemoryMarshal.GetArrayDataReference(chars),
source: ref _firstChar,
elementCount: (uint)Length);

return chars;
}

// Returns a substring of this string as an array of characters.
//
public unsafe char[] ToCharArray(int startIndex, int length)
public char[] ToCharArray(int startIndex, int length)
{
// Range check everything.
if (startIndex < 0 || startIndex > Length || startIndex > Length - length)
Expand All @@ -425,8 +445,12 @@ public unsafe char[] ToCharArray(int startIndex, int length)
}

char[] chars = new char[length];
fixed (char* src = &_firstChar, dest = &chars[0])
wstrcpy(dest, src + startIndex, length);

Buffer.Memmove(
destination: ref MemoryMarshal.GetArrayDataReference(chars),
source: ref Unsafe.Add(ref _firstChar, startIndex),
elementCount: (uint)length);

return chars;
}

Expand Down

0 comments on commit 70c1e9d

Please sign in to comment.