Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Private.CoreLib/shared/System/Text')
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs124
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/Decoder.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs8
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/Encoder.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs14
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs20
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncoderReplacementFallback.cs22
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/Encoding.cs50
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs70
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs2
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs6
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs37
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs263
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/StringBuilderCache.cs62
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs84
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs92
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs324
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs284
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs60
24 files changed, 945 insertions, 637 deletions
diff --git a/src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs b/src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs
index e89943a19..217d93467 100644
--- a/src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/ASCIIEncoding.cs
@@ -31,7 +31,7 @@ namespace System.Text
{
}
- internal override void SetDefaultFallbacks()
+ internal sealed override void SetDefaultFallbacks()
{
// For ASCIIEncoding we just use default replacement fallback
this.encoderFallback = EncoderFallback.ReplacementFallback;
@@ -59,13 +59,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -81,11 +81,11 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe int GetByteCount(String chars)
+ public override unsafe int GetByteCount(string chars)
{
// Validate input
if (chars==null)
- throw new ArgumentNullException("chars");
+ throw new ArgumentNullException(nameof(chars));
fixed (char* pChars = chars)
return GetByteCount(pChars, chars.Length, null);
@@ -100,34 +100,42 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
}
+ public override unsafe int GetByteCount(ReadOnlySpan<char> chars)
+ {
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ {
+ return GetByteCount(charsPtr, chars.Length, encoder: null);
+ }
+ }
+
// Parent method is safe.
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
- public override unsafe int GetBytes(String chars, int charIndex, int charCount,
+ public override unsafe int GetBytes(string chars, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -154,16 +162,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0
if (charCount == 0)
@@ -186,14 +194,23 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
+ public override unsafe int GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes)
+ {
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ {
+ return GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length, encoder: null);
+ }
+ }
+
// Returns the number of characters produced by decoding a range of bytes
// in a byte array.
//
@@ -206,13 +223,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays
if (count == 0)
@@ -232,14 +249,22 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
+ public override unsafe int GetCharCount(ReadOnlySpan<byte> bytes)
+ {
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ {
+ return GetCharCount(bytesPtr, bytes.Length, decoder: null);
+ }
+ }
+
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
@@ -250,16 +275,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -282,14 +307,23 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
+ public override unsafe int GetChars(ReadOnlySpan<byte> bytes, Span<char> chars)
+ {
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ {
+ return GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length, decoder: null);
+ }
+ }
+
// Returns a string containing the decoded representation of a range of
// bytes in a byte array.
//
@@ -298,24 +332,24 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe String GetString(byte[] bytes, int byteIndex, int byteCount)
+ public override unsafe string GetString(byte[] bytes, int byteIndex, int byteCount)
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (byteCount == 0) return String.Empty;
+ if (byteCount == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + byteIndex, byteCount, this);
}
@@ -326,7 +360,7 @@ namespace System.Text
// GetByteCount
// Note: We start by assuming that the output will be the same as count. Having
// an encoder or fallback may change that assumption
- internal override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS encoder)
+ internal sealed override unsafe int GetByteCount(char* chars, int charCount, EncoderNLS encoder)
{
// Just need to ASSERT, this is called by something else internal that checked parameters already
Debug.Assert(charCount >= 0, "[ASCIIEncoding.GetByteCount]count is negative");
@@ -348,7 +382,7 @@ namespace System.Text
if (encoder != null)
{
charLeftOver = encoder._charLeftOver;
- Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ Debug.Assert(charLeftOver == 0 || char.IsHighSurrogate(charLeftOver),
"[ASCIIEncoding.GetByteCount]leftover character should be high surrogate");
fallback = encoder.Fallback as EncoderReplacementFallback;
@@ -400,7 +434,7 @@ namespace System.Text
// We may have a left over character from last time, try and process it.
if (charLeftOver > 0)
{
- Debug.Assert(Char.IsHighSurrogate(charLeftOver), "[ASCIIEncoding.GetByteCount]leftover character should be high surrogate");
+ Debug.Assert(char.IsHighSurrogate(charLeftOver), "[ASCIIEncoding.GetByteCount]leftover character should be high surrogate");
Debug.Assert(encoder != null, "[ASCIIEncoding.GetByteCount]Expected encoder");
// Since left over char was a surrogate, it'll have to be fallen back.
@@ -460,8 +494,8 @@ namespace System.Text
return byteCount;
}
- internal override unsafe int GetBytes(char* chars, int charCount,
- byte* bytes, int byteCount, EncoderNLS encoder)
+ internal sealed override unsafe int GetBytes(
+ char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder)
{
// Just need to ASSERT, this is called by something else internal that checked parameters already
Debug.Assert(bytes != null, "[ASCIIEncoding.GetBytes]bytes is null");
@@ -502,7 +536,7 @@ namespace System.Text
fallbackBuffer.InternalInitialize(charStart, charEnd, encoder, true);
}
- Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ Debug.Assert(charLeftOver == 0 || char.IsHighSurrogate(charLeftOver),
"[ASCIIEncoding.GetBytes]leftover character should be high surrogate");
// Verify that we have no fallbackbuffer, for ASCII its always empty, so just assert
@@ -676,7 +710,7 @@ namespace System.Text
}
// This is internal and called by something else,
- internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS decoder)
+ internal sealed override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS decoder)
{
// Just assert, we're called internally so these should be safe, checked already
Debug.Assert(bytes != null, "[ASCIIEncoding.GetCharCount]bytes is null");
@@ -748,8 +782,8 @@ namespace System.Text
return charCount;
}
- internal override unsafe int GetChars(byte* bytes, int byteCount,
- char* chars, int charCount, DecoderNLS decoder)
+ internal sealed override unsafe int GetChars(
+ byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS decoder)
{
// Just need to ASSERT, this is called by something else internal that checked parameters already
Debug.Assert(bytes != null, "[ASCIIEncoding.GetChars]bytes is null");
diff --git a/src/System.Private.CoreLib/shared/System/Text/Decoder.cs b/src/System.Private.CoreLib/shared/System/Text/Decoder.cs
index b827648fc..b4a7575ba 100644
--- a/src/System.Private.CoreLib/shared/System/Text/Decoder.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/Decoder.cs
@@ -134,7 +134,7 @@ namespace System.Text
public virtual unsafe int GetCharCount(ReadOnlySpan<byte> bytes, bool flush)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
return GetCharCount(bytesPtr, bytes.Length, flush);
}
@@ -227,8 +227,8 @@ namespace System.Text
public virtual unsafe int GetChars(ReadOnlySpan<byte> bytes, Span<char> chars, bool flush)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
{
return GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length, flush);
}
@@ -341,8 +341,8 @@ namespace System.Text
public virtual unsafe void Convert(ReadOnlySpan<byte> bytes, Span<char> chars, bool flush, out int bytesUsed, out int charsUsed, out bool completed)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
{
Convert(bytesPtr, bytes.Length, charsPtr, chars.Length, flush, out bytesUsed, out charsUsed, out completed);
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs
index 30c817c91..8c62730c2 100644
--- a/src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/DecoderBestFitFallback.cs
@@ -38,7 +38,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
InternalDecoderBestFitFallback that = value as InternalDecoderBestFitFallback;
if (that != null)
@@ -63,15 +63,15 @@ namespace System.Text
private InternalDecoderBestFitFallback _oFallback;
// Private object for locking instead of locking on a public type for SQL reliability work.
- private static Object s_InternalSyncObject;
- private static Object InternalSyncObject
+ private static object s_InternalSyncObject;
+ private static object InternalSyncObject
{
get
{
if (s_InternalSyncObject == null)
{
- Object o = new Object();
- Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ object o = new object();
+ Interlocked.CompareExchange<object>(ref s_InternalSyncObject, o, null);
}
return s_InternalSyncObject;
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs
index 8bfc1f32d..56c004714 100644
--- a/src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/DecoderExceptionFallback.cs
@@ -29,7 +29,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
DecoderExceptionFallback that = value as DecoderExceptionFallback;
if (that != null)
@@ -112,19 +112,19 @@ namespace System.Text
HResult = HResults.COR_E_ARGUMENT;
}
- public DecoderFallbackException(String message)
+ public DecoderFallbackException(string message)
: base(message)
{
HResult = HResults.COR_E_ARGUMENT;
}
- public DecoderFallbackException(String message, Exception innerException)
+ public DecoderFallbackException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_ARGUMENT;
}
- public DecoderFallbackException(String message, byte[] bytesUnknown, int index)
+ public DecoderFallbackException(string message, byte[] bytesUnknown, int index)
: base(message)
{
_bytesUnknown = bytesUnknown;
diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs
index 11b9539b5..fff8ad1d7 100644
--- a/src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/DecoderFallback.cs
@@ -104,9 +104,9 @@ namespace System.Text
while ((ch = GetNextChar()) != 0)
{
// Make sure no mixed up surrogates
- if (Char.IsSurrogate(ch))
+ if (char.IsSurrogate(ch))
{
- if (Char.IsHighSurrogate(ch))
+ if (char.IsHighSurrogate(ch))
{
// High Surrogate
if (bHighSurrogate)
@@ -159,9 +159,9 @@ namespace System.Text
while ((ch = GetNextChar()) != 0)
{
// Make sure no mixed up surrogates
- if (Char.IsSurrogate(ch))
+ if (char.IsSurrogate(ch))
{
- if (Char.IsHighSurrogate(ch))
+ if (char.IsHighSurrogate(ch))
{
// High Surrogate
if (bHighSurrogate)
diff --git a/src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs b/src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs
index 422b80bb2..a97baf05c 100644
--- a/src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/DecoderReplacementFallback.cs
@@ -9,14 +9,14 @@ namespace System.Text
public sealed class DecoderReplacementFallback : DecoderFallback
{
// Our variables
- private String _strDefault;
+ private string _strDefault;
// Construction. Default replacement fallback uses no best fit and ? replacement string
public DecoderReplacementFallback() : this("?")
{
}
- public DecoderReplacementFallback(String replacement)
+ public DecoderReplacementFallback(string replacement)
{
if (replacement == null)
throw new ArgumentNullException(nameof(replacement));
@@ -26,10 +26,10 @@ namespace System.Text
for (int i = 0; i < replacement.Length; i++)
{
// Found a surrogate?
- if (Char.IsSurrogate(replacement, i))
+ if (char.IsSurrogate(replacement, i))
{
// High or Low?
- if (Char.IsHighSurrogate(replacement, i))
+ if (char.IsHighSurrogate(replacement, i))
{
// if already had a high one, stop
if (bFoundHigh)
@@ -60,7 +60,7 @@ namespace System.Text
_strDefault = replacement;
}
- public String DefaultString
+ public string DefaultString
{
get
{
@@ -82,7 +82,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
DecoderReplacementFallback that = value as DecoderReplacementFallback;
if (that != null)
@@ -103,7 +103,7 @@ namespace System.Text
public sealed class DecoderReplacementFallbackBuffer : DecoderFallbackBuffer
{
// Store our default string
- private String _strDefault;
+ private string _strDefault;
private int _fallbackCount = -1;
private int _fallbackIndex = -1;
diff --git a/src/System.Private.CoreLib/shared/System/Text/Encoder.cs b/src/System.Private.CoreLib/shared/System/Text/Encoder.cs
index fb1bdb803..df7d51203 100644
--- a/src/System.Private.CoreLib/shared/System/Text/Encoder.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/Encoder.cs
@@ -132,7 +132,7 @@ namespace System.Text
public virtual unsafe int GetByteCount(ReadOnlySpan<char> chars, bool flush)
{
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
{
return GetByteCount(charsPtr, chars.Length, flush);
}
@@ -221,8 +221,8 @@ namespace System.Text
public virtual unsafe int GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes, bool flush)
{
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
return GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length, flush);
}
@@ -335,8 +335,8 @@ namespace System.Text
public virtual unsafe void Convert(ReadOnlySpan<char> chars, Span<byte> bytes, bool flush, out int charsUsed, out int bytesUsed, out bool completed)
{
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
Convert(charsPtr, chars.Length, bytesPtr, bytes.Length, flush, out charsUsed, out bytesUsed, out completed);
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs b/src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs
index 7f3be2a7a..4aab3f62a 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncoderBestFitFallback.cs
@@ -38,7 +38,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
InternalEncoderBestFitFallback that = value as InternalEncoderBestFitFallback;
if (that != null)
@@ -63,15 +63,15 @@ namespace System.Text
private int _iSize;
// Private object for locking instead of locking on a public type for SQL reliability work.
- private static Object s_InternalSyncObject;
- private static Object InternalSyncObject
+ private static object s_InternalSyncObject;
+ private static object InternalSyncObject
{
get
{
if (s_InternalSyncObject == null)
{
- Object o = new Object();
- Interlocked.CompareExchange<Object>(ref s_InternalSyncObject, o, null);
+ object o = new object();
+ Interlocked.CompareExchange<object>(ref s_InternalSyncObject, o, null);
}
return s_InternalSyncObject;
}
@@ -113,12 +113,12 @@ namespace System.Text
public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index)
{
// Double check input surrogate pair
- if (!Char.IsHighSurrogate(charUnknownHigh))
+ if (!char.IsHighSurrogate(charUnknownHigh))
throw new ArgumentOutOfRangeException(nameof(charUnknownHigh),
SR.Format(SR.ArgumentOutOfRange_Range,
0xD800, 0xDBFF));
- if (!Char.IsLowSurrogate(charUnknownLow))
+ if (!char.IsLowSurrogate(charUnknownLow))
throw new ArgumentOutOfRangeException(nameof(charUnknownLow),
SR.Format(SR.ArgumentOutOfRange_Range,
0xDC00, 0xDFFF));
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs b/src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs
index 66de1940f..92afcf701 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncoderExceptionFallback.cs
@@ -28,7 +28,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
EncoderExceptionFallback that = value as EncoderExceptionFallback;
if (that != null)
@@ -57,18 +57,18 @@ namespace System.Text
public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index)
{
- if (!Char.IsHighSurrogate(charUnknownHigh))
+ if (!char.IsHighSurrogate(charUnknownHigh))
{
throw new ArgumentOutOfRangeException(nameof(charUnknownHigh),
SR.Format(SR.ArgumentOutOfRange_Range, 0xD800, 0xDBFF));
}
- if (!Char.IsLowSurrogate(charUnknownLow))
+ if (!char.IsLowSurrogate(charUnknownLow))
{
throw new ArgumentOutOfRangeException(nameof(charUnknownLow),
SR.Format(SR.ArgumentOutOfRange_Range, 0xDC00, 0xDFFF));
}
- int iTemp = Char.ConvertToUtf32(charUnknownHigh, charUnknownLow);
+ int iTemp = char.ConvertToUtf32(charUnknownHigh, charUnknownLow);
// Fall back our char
throw new EncoderFallbackException(
@@ -111,34 +111,34 @@ namespace System.Text
HResult = HResults.COR_E_ARGUMENT;
}
- public EncoderFallbackException(String message)
+ public EncoderFallbackException(string message)
: base(message)
{
HResult = HResults.COR_E_ARGUMENT;
}
- public EncoderFallbackException(String message, Exception innerException)
+ public EncoderFallbackException(string message, Exception innerException)
: base(message, innerException)
{
HResult = HResults.COR_E_ARGUMENT;
}
internal EncoderFallbackException(
- String message, char charUnknown, int index) : base(message)
+ string message, char charUnknown, int index) : base(message)
{
_charUnknown = charUnknown;
_index = index;
}
internal EncoderFallbackException(
- String message, char charUnknownHigh, char charUnknownLow, int index) : base(message)
+ string message, char charUnknownHigh, char charUnknownLow, int index) : base(message)
{
- if (!Char.IsHighSurrogate(charUnknownHigh))
+ if (!char.IsHighSurrogate(charUnknownHigh))
{
throw new ArgumentOutOfRangeException(nameof(charUnknownHigh),
SR.Format(SR.ArgumentOutOfRange_Range, 0xD800, 0xDBFF));
}
- if (!Char.IsLowSurrogate(charUnknownLow))
+ if (!char.IsLowSurrogate(charUnknownLow))
{
throw new ArgumentOutOfRangeException(nameof(CharUnknownLow),
SR.Format(SR.ArgumentOutOfRange_Range, 0xDC00, 0xDFFF));
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs b/src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs
index d860a02a7..f98b15e07 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncoderFallback.cs
@@ -142,7 +142,7 @@ namespace System.Text
int index = (int)(chars - charStart) - 1;
// See if it was a high surrogate
- if (Char.IsHighSurrogate(ch))
+ if (char.IsHighSurrogate(ch))
{
// See if there's a low surrogate to go with it
if (chars >= this.charEnd)
@@ -165,11 +165,11 @@ namespace System.Text
{
// Might have a low surrogate
char cNext = *chars;
- if (Char.IsLowSurrogate(cNext))
+ if (char.IsLowSurrogate(cNext))
{
// If already falling back then fail
if (bFallingBack && iRecursionCount++ > iMaxRecursion)
- ThrowLastCharRecursive(Char.ConvertToUtf32(ch, cNext));
+ ThrowLastCharRecursive(char.ConvertToUtf32(ch, cNext));
// Next is a surrogate, add it as surrogate pair, and increment chars
chars++;
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncoderReplacementFallback.cs b/src/System.Private.CoreLib/shared/System/Text/EncoderReplacementFallback.cs
index a1d0bbcd9..760c280fd 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncoderReplacementFallback.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncoderReplacementFallback.cs
@@ -11,14 +11,14 @@ namespace System.Text
public sealed class EncoderReplacementFallback : EncoderFallback
{
// Our variables
- private String _strDefault;
+ private string _strDefault;
// Construction. Default replacement fallback uses no best fit and ? replacement string
public EncoderReplacementFallback() : this("?")
{
}
- public EncoderReplacementFallback(String replacement)
+ public EncoderReplacementFallback(string replacement)
{
// Must not be null
if (replacement == null)
@@ -29,10 +29,10 @@ namespace System.Text
for (int i = 0; i < replacement.Length; i++)
{
// Found a surrogate?
- if (Char.IsSurrogate(replacement, i))
+ if (char.IsSurrogate(replacement, i))
{
// High or Low?
- if (Char.IsHighSurrogate(replacement, i))
+ if (char.IsHighSurrogate(replacement, i))
{
// if already had a high one, stop
if (bFoundHigh)
@@ -63,7 +63,7 @@ namespace System.Text
_strDefault = replacement;
}
- public String DefaultString
+ public string DefaultString
{
get
{
@@ -85,7 +85,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
EncoderReplacementFallback that = value as EncoderReplacementFallback;
if (that != null)
@@ -106,7 +106,7 @@ namespace System.Text
public sealed class EncoderReplacementFallbackBuffer : EncoderFallbackBuffer
{
// Store our default string
- private String _strDefault;
+ private string _strDefault;
private int _fallbackCount = -1;
private int _fallbackIndex = -1;
@@ -127,7 +127,7 @@ namespace System.Text
// If we're recursive we may still have something in our buffer that makes this a surrogate
if (char.IsHighSurrogate(charUnknown) && _fallbackCount >= 0 &&
char.IsLowSurrogate(_strDefault[_fallbackIndex + 1]))
- ThrowLastCharRecursive(Char.ConvertToUtf32(charUnknown, _strDefault[_fallbackIndex + 1]));
+ ThrowLastCharRecursive(char.ConvertToUtf32(charUnknown, _strDefault[_fallbackIndex + 1]));
// Nope, just one character
ThrowLastCharRecursive(unchecked((int)charUnknown));
@@ -144,18 +144,18 @@ namespace System.Text
public override bool Fallback(char charUnknownHigh, char charUnknownLow, int index)
{
// Double check input surrogate pair
- if (!Char.IsHighSurrogate(charUnknownHigh))
+ if (!char.IsHighSurrogate(charUnknownHigh))
throw new ArgumentOutOfRangeException(nameof(charUnknownHigh),
SR.Format(SR.ArgumentOutOfRange_Range, 0xD800, 0xDBFF));
- if (!Char.IsLowSurrogate(charUnknownLow))
+ if (!char.IsLowSurrogate(charUnknownLow))
throw new ArgumentOutOfRangeException(nameof(charUnknownLow),
SR.Format(SR.ArgumentOutOfRange_Range, 0xDC00, 0xDFFF));
// If we had a buffer already we're being recursive, throw, it's probably at the suspect
// character in our array.
if (_fallbackCount >= 1)
- ThrowLastCharRecursive(Char.ConvertToUtf32(charUnknownHigh, charUnknownLow));
+ ThrowLastCharRecursive(char.ConvertToUtf32(charUnknownHigh, charUnknownLow));
// Go ahead and get our fallback
_fallbackCount = _strDefault.Length;
diff --git a/src/System.Private.CoreLib/shared/System/Text/Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/Encoding.cs
index e469180ce..005f08afd 100644
--- a/src/System.Private.CoreLib/shared/System/Text/Encoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/Encoding.cs
@@ -325,7 +325,7 @@ namespace System.Text
// Returns an Encoding object for a given name or a given code page value.
//
- public static Encoding GetEncoding(String name)
+ public static Encoding GetEncoding(string name)
{
Encoding baseEncoding = EncodingProvider.GetEncodingFromProvider(name);
if (baseEncoding != null)
@@ -342,7 +342,7 @@ namespace System.Text
// Returns an Encoding object for a given name or a given code page value.
//
- public static Encoding GetEncoding(String name,
+ public static Encoding GetEncoding(string name,
EncoderFallback encoderFallback, DecoderFallback decoderFallback)
{
Encoding baseEncoding = EncodingProvider.GetEncodingFromProvider(name, encoderFallback, decoderFallback);
@@ -386,7 +386,7 @@ namespace System.Text
// Returns the name for this encoding that can be used with mail agent body tags.
// If the encoding may not be used, the string is empty.
- public virtual String BodyName
+ public virtual string BodyName
{
get
{
@@ -443,7 +443,7 @@ namespace System.Text
}
}
#else
- public virtual String EncodingName
+ public virtual string EncodingName
{
get
{
@@ -454,7 +454,7 @@ namespace System.Text
// Returns the name for this encoding that can be used with mail agent header
// tags. If the encoding may not be used, the string is empty.
- public virtual String HeaderName
+ public virtual string HeaderName
{
get
{
@@ -467,7 +467,7 @@ namespace System.Text
}
// Returns the IANA preferred name for this encoding.
- public virtual String WebName
+ public virtual string WebName
{
get
{
@@ -603,7 +603,7 @@ namespace System.Text
}
- public virtual Object Clone()
+ public virtual object Clone()
{
Encoding newEncoding = (Encoding)this.MemberwiseClone();
@@ -646,7 +646,7 @@ namespace System.Text
return GetByteCount(chars, 0, chars.Length);
}
- public virtual int GetByteCount(String s)
+ public virtual int GetByteCount(string s)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
@@ -713,7 +713,7 @@ namespace System.Text
public virtual unsafe int GetByteCount(ReadOnlySpan<char> chars)
{
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
{
return GetByteCount(charsPtr, chars.Length);
}
@@ -767,7 +767,7 @@ namespace System.Text
// Returns a byte array containing the encoded representation of the given
// string.
//
- public virtual byte[] GetBytes(String s)
+ public virtual byte[] GetBytes(string s)
{
if (s == null)
throw new ArgumentNullException(nameof(s),
@@ -817,7 +817,7 @@ namespace System.Text
}
}
- public virtual int GetBytes(String s, int charIndex, int charCount,
+ public virtual int GetBytes(string s, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (s == null)
@@ -895,8 +895,8 @@ namespace System.Text
public virtual unsafe int GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes)
{
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
return GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length);
}
@@ -945,7 +945,7 @@ namespace System.Text
public virtual unsafe int GetCharCount(ReadOnlySpan<byte> bytes)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
return GetCharCount(bytesPtr, bytes.Length);
}
@@ -1057,8 +1057,8 @@ namespace System.Text
public virtual unsafe int GetChars(ReadOnlySpan<byte> bytes, Span<char> chars)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
- fixed (char* charsPtr = &MemoryMarshal.GetReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
{
return GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length);
}
@@ -1082,14 +1082,14 @@ namespace System.Text
if (byteCount < 0)
throw new ArgumentOutOfRangeException(nameof(byteCount), SR.ArgumentOutOfRange_NeedNonNegNum);
- return String.CreateStringFromEncoding(bytes, byteCount, this);
+ return string.CreateStringFromEncoding(bytes, byteCount, this);
}
public unsafe string GetString(ReadOnlySpan<byte> bytes)
{
- fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
{
- return GetString(bytesPtr, bytes.Length);
+ return string.CreateStringFromEncoding(bytesPtr, bytes.Length, this);
}
}
@@ -1184,7 +1184,7 @@ namespace System.Text
// Returns a string containing the decoded representation of a given byte
// array.
//
- public virtual String GetString(byte[] bytes)
+ public virtual string GetString(byte[] bytes)
{
if (bytes == null)
throw new ArgumentNullException(nameof(bytes),
@@ -1198,9 +1198,9 @@ namespace System.Text
//
// Internally we override this for performance
//
- public virtual String GetString(byte[] bytes, int index, int count)
+ public virtual string GetString(byte[] bytes, int index, int count)
{
- return new String(GetChars(bytes, index, count));
+ return new string(GetChars(bytes, index, count));
}
// Returns an encoding for Unicode format. The returned encoding will be
@@ -1241,7 +1241,7 @@ namespace System.Text
private static Encoding BigEndianUTF32 => UTF32Encoding.s_bigEndianDefault;
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
Encoding that = value as Encoding;
if (that != null)
@@ -1325,7 +1325,7 @@ namespace System.Text
_encoding = encoding;
}
- public Object GetRealObject(StreamingContext context)
+ public object GetRealObject(StreamingContext context)
{
throw new PlatformNotSupportedException();
}
@@ -1390,7 +1390,7 @@ namespace System.Text
_encoding = encoding;
}
- public Object GetRealObject(StreamingContext context)
+ public object GetRealObject(StreamingContext context)
{
throw new PlatformNotSupportedException();
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs b/src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs
index 99995f759..8e71e58fa 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncodingInfo.cs
@@ -53,7 +53,7 @@ namespace System.Text
return Encoding.GetEncoding(iCodePage);
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
EncodingInfo that = value as EncodingInfo;
if (that != null)
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs b/src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs
index d5de9e553..e6fa0627d 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncodingNLS.cs
@@ -40,13 +40,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -61,11 +61,11 @@ namespace System.Text
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe int GetByteCount(String s)
+ public override unsafe int GetByteCount(string s)
{
// Validate input
if (s==null)
- throw new ArgumentNullException("s");
+ throw new ArgumentNullException(nameof(s));
fixed (char* pChars = s)
return GetByteCount(pChars, s.Length, null);
@@ -78,10 +78,10 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
@@ -91,20 +91,20 @@ namespace System.Text
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
- public override unsafe int GetBytes(String s, int charIndex, int charCount,
+ public override unsafe int GetBytes(string s, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (s == null || bytes == null)
- throw new ArgumentNullException((s == null ? "s" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((s == null ? nameof(s) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (s.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("s", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -130,16 +130,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0, avoid fixed problem
if (charCount == 0)
@@ -160,10 +160,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
@@ -179,13 +179,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays
if (count == 0)
@@ -203,10 +203,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
@@ -220,16 +220,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -250,10 +250,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
@@ -265,23 +265,23 @@ namespace System.Text
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe String GetString(byte[] bytes, int index, int count)
+ public override unsafe string GetString(byte[] bytes, int index, int count)
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (count == 0) return String.Empty;
+ if (count == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + index, count, this);
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs b/src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs
index ce8c3e020..4d15eea01 100644
--- a/src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/EncodingProvider.cs
@@ -130,7 +130,7 @@ namespace System.Text
return null;
}
- private static Object s_InternalSyncObject = new Object();
+ private static object s_InternalSyncObject = new object();
private static volatile EncodingProvider[] s_providers;
}
}
diff --git a/src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs
index 335eb76e3..736fff5d2 100644
--- a/src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/Latin1Encoding.cs
@@ -11,7 +11,7 @@ namespace System.Text
// Latin1Encoding is a simple override to optimize the GetString version of Latin1Encoding.
// because of the best fit cases we can't do this when encoding the string, only when decoding
//
- internal class Latin1Encoding : EncodingNLS
+ internal sealed class Latin1Encoding : EncodingNLS
{
// Used by Encoding.Latin1 for lazy initialization
// The initialization code will not be run until a static member of the class is referenced
@@ -42,7 +42,7 @@ namespace System.Text
if (encoder != null)
{
charLeftOver = encoder._charLeftOver;
- Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ Debug.Assert(charLeftOver == 0 || char.IsHighSurrogate(charLeftOver),
"[Latin1Encoding.GetByteCount]leftover character should be high surrogate");
fallback = encoder.Fallback as EncoderReplacementFallback;
@@ -164,7 +164,7 @@ namespace System.Text
{
charLeftOver = encoder._charLeftOver;
fallback = encoder.Fallback as EncoderReplacementFallback;
- Debug.Assert(charLeftOver == 0 || Char.IsHighSurrogate(charLeftOver),
+ Debug.Assert(charLeftOver == 0 || char.IsHighSurrogate(charLeftOver),
"[Latin1Encoding.GetBytes]leftover character should be high surrogate");
// Verify that we have no fallbackbuffer, for ASCII its always empty, so just assert
diff --git a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs
new file mode 100644
index 000000000..a62c4777a
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.Debug.cs
@@ -0,0 +1,37 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Diagnostics;
+
+namespace System.Text
+{
+ public sealed partial class StringBuilder
+ {
+ private void ShowChunks(int maxChunksToShow = 10)
+ {
+ int count = 0;
+ StringBuilder head = this, current = this;
+ while (current != null)
+ {
+ if (count < maxChunksToShow)
+ {
+ count++;
+ }
+ else
+ {
+ head = head.m_ChunkPrevious;
+ }
+ current = current.m_ChunkPrevious;
+ }
+ current = head;
+ string[] chunks = new string[count];
+ for (int i = count; i > 0; i--)
+ {
+ chunks[i - 1] = new string(current.m_ChunkChars).Replace('\0', '.');
+ current = current.m_ChunkPrevious;
+ }
+ Debug.WriteLine('|' + string.Join('|', chunks) + '|');
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs
index a7804c399..99021e2dd 100644
--- a/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/StringBuilder.cs
@@ -18,10 +18,10 @@ using System.Collections.Generic;
namespace System.Text
{
// This class represents a mutable string. It is convenient for situations in
- // which it is desirable to modify a string, perhaps by removing, replacing, or
+ // which it is desirable to modify a string, perhaps by removing, replacing, or
// inserting characters, without creating a new String subsequent to
- // each modification.
- //
+ // each modification.
+ //
// The methods contained within this class do not return a new StringBuilder
// object unless specified otherwise. This class may be used in conjunction with the String
// class to carry out modifications upon strings.
@@ -30,8 +30,8 @@ namespace System.Text
public sealed partial class StringBuilder : ISerializable
{
// A StringBuilder is internally represented as a linked list of blocks each of which holds
- // a chunk of the string. It turns out string as a whole can also be represented as just a chunk,
- // so that is what we do.
+ // a chunk of the string. It turns out string as a whole can also be represented as just a chunk,
+ // so that is what we do.
/// <summary>
/// The character buffer for this chunk.
@@ -73,7 +73,7 @@ namespace System.Text
// We want to keep chunk arrays out of large object heap (< 85K bytes ~ 40K chars) to be sure.
// Making the maximum chunk size big means less allocation code called, but also more waste
// in unused characters and slower inserts / replaces (since you do need to slide characters over
- // within a buffer).
+ // within a buffer).
internal const int MaxChunkSize = 8000;
/// <summary>
@@ -201,7 +201,7 @@ namespace System.Text
int persistedCapacity = 0;
string persistedString = null;
- int persistedMaxCapacity = Int32.MaxValue;
+ int persistedMaxCapacity = int.MaxValue;
bool capacityPresent = false;
// Get the data
@@ -353,7 +353,7 @@ namespace System.Text
return Capacity;
}
- public override String ToString()
+ public override string ToString()
{
AssertInvariants();
@@ -377,7 +377,7 @@ namespace System.Text
int chunkOffset = chunk.m_ChunkOffset;
int chunkLength = chunk.m_ChunkLength;
- // Check that we will not overrun our boundaries.
+ // Check that we will not overrun our boundaries.
if ((uint)(chunkLength + chunkOffset) <= (uint)result.Length && (uint)chunkLength <= (uint)sourceArray.Length)
{
fixed (char* sourcePtr = &sourceArray[0])
@@ -462,13 +462,10 @@ namespace System.Text
throw new ArgumentOutOfRangeException(nameof(value), SR.ArgumentOutOfRange_SmallCapacity);
}
- int originalCapacity = Capacity;
-
if (value == 0 && m_ChunkPrevious == null)
{
m_ChunkLength = 0;
m_ChunkOffset = 0;
- Debug.Assert(Capacity >= originalCapacity);
return;
}
@@ -483,22 +480,32 @@ namespace System.Text
StringBuilder chunk = FindChunkForIndex(value);
if (chunk != this)
{
- // We crossed a chunk boundary when reducing the Length. We must replace this middle-chunk with a new larger chunk,
- // to ensure the original capacity is preserved.
- int newLen = originalCapacity - chunk.m_ChunkOffset;
- char[] newArray = new char[newLen];
-
- Debug.Assert(newLen > chunk.m_ChunkChars.Length, "The new chunk should be larger than the one it is replacing.");
- Array.Copy(chunk.m_ChunkChars, 0, newArray, 0, chunk.m_ChunkLength);
+ // Avoid possible infinite capacity growth. See https://github.com/dotnet/coreclr/pull/16926
+ int capacityToPreserve = Math.Min(Capacity, Math.Max(Length * 6 / 5, m_ChunkChars.Length));
+ int newLen = capacityToPreserve - chunk.m_ChunkOffset;
+ if (newLen > chunk.m_ChunkChars.Length)
+ {
+ // We crossed a chunk boundary when reducing the Length. We must replace this middle-chunk with a new larger chunk,
+ // to ensure the capacity we want is preserved.
+ char[] newArray = new char[newLen];
+ Array.Copy(chunk.m_ChunkChars, 0, newArray, 0, chunk.m_ChunkLength);
+ m_ChunkChars = newArray;
+ }
+ else
+ {
+ // Special case where the capacity we want to keep corresponds exactly to the size of the content.
+ // Just take ownership of the array.
+ Debug.Assert(newLen == chunk.m_ChunkChars.Length, "The new chunk should be larger or equal to the one it is replacing.");
+ m_ChunkChars = chunk.m_ChunkChars;
+ }
- m_ChunkChars = newArray;
m_ChunkPrevious = chunk.m_ChunkPrevious;
m_ChunkOffset = chunk.m_ChunkOffset;
}
m_ChunkLength = value - chunk.m_ChunkOffset;
AssertInvariants();
}
- Debug.Assert(Capacity >= originalCapacity);
+ Debug.Assert(Length == value, "Something went wrong setting Length.");
}
}
@@ -551,6 +558,138 @@ namespace System.Text
}
/// <summary>
+ /// GetChunks returns ChunkEnumerator that follows the IEnumerable pattern and
+ /// thus can be used in a C# 'foreach' statements to retreive the data in the StringBuilder
+ /// as chunks (ReadOnlyMemory) of characters. An example use is:
+ ///
+ /// foreach (ReadOnlyMemory<char> chunk in sb.GetChunks())
+ /// foreach(char c in chunk.Span)
+ /// { /* operation on c }
+ ///
+ /// It is undefined what happens if the StringBuilder is modified while the chunk
+ /// enumeration is incomplete. StringBuilder is also not thread-safe, so operating
+ /// on it with concurrent threads is illegal. Finally the ReadOnlyMemory chunks returned
+ /// are NOT guarenteed to remain unchanged if the StringBuilder is modified, so do
+ /// not cache them for later use either. This API's purpose is efficiently extracting
+ /// the data of a CONSTANT StringBuilder.
+ ///
+ /// Creating a ReadOnlySpan from a ReadOnlyMemory (the .Span property) is expensive
+ /// compared to the fetching of the character, so create a local variable for the SPAN
+ /// if you need to use it in a nested for statement. For example
+ ///
+ /// foreach (ReadOnlyMemory<char> chunk in sb.GetChunks())
+ /// {
+ /// var span = chunk.Span;
+ /// for(int i = 0; i < span.Length; i++)
+ /// { /* operation on span[i] */ }
+ /// }
+ /// </summary>
+ public ChunkEnumerator GetChunks() => new ChunkEnumerator(this);
+
+ /// <summary>
+ /// ChunkEnumerator supports both the IEnumerable and IEnumerator pattern so foreach
+ /// works (see GetChunks). It needs to be public (so the compiler can use it
+ /// when building a foreach statement) but users typically don't use it explicitly.
+ /// (which is why it is a nested type).
+ /// </summary>
+ public struct ChunkEnumerator
+ {
+ private readonly StringBuilder _firstChunk; // The first Stringbuilder chunk (which is the end of the logical string)
+ private StringBuilder _currentChunk; // The chunk that this enumerator is currently returning (Current).
+ private readonly ManyChunkInfo _manyChunks; // Only used for long string builders with many chunks (see constructor)
+
+ /// <summary>
+ /// Implement IEnumerable.GetEnumerator() to return 'this' as the IEnumerator
+ /// </summary>
+ [ComponentModel.EditorBrowsable(ComponentModel.EditorBrowsableState.Never)] // Only here to make foreach work
+ public ChunkEnumerator GetEnumerator() { return this; }
+
+ /// <summary>
+ /// Implements the IEnumerator pattern.
+ /// </summary>
+ public bool MoveNext()
+ {
+ if (_currentChunk == _firstChunk)
+ return false;
+
+ if (_manyChunks != null)
+ return _manyChunks.MoveNext(ref _currentChunk);
+
+ StringBuilder next = _firstChunk;
+ while (next.m_ChunkPrevious != _currentChunk)
+ next = next.m_ChunkPrevious;
+ _currentChunk = next;
+ return true;
+ }
+
+ /// <summary>
+ /// Implements the IEnumerator pattern.
+ /// </summary>
+ public ReadOnlyMemory<char> Current => new ReadOnlyMemory<char>(_currentChunk.m_ChunkChars, 0, _currentChunk.m_ChunkLength);
+
+ #region private
+ internal ChunkEnumerator(StringBuilder stringBuilder)
+ {
+ Debug.Assert(stringBuilder != null);
+ _firstChunk = stringBuilder;
+ _currentChunk = null; // MoveNext will find the last chunk if we do this.
+ _manyChunks = null;
+
+ // There is a performance-vs-allocation tradeoff. Because the chunks
+ // are a linked list with each chunk pointing to its PREDECESSOR, walking
+ // the list FORWARD is not efficient. If there are few chunks (< 8) we
+ // simply scan from the start each time, and tolerate the N*N behavior.
+ // However above this size, we allocate an array to hold pointers to all
+ // the chunks and we can be efficient for large N.
+ int chunkCount = ChunkCount(stringBuilder);
+ if (8 < chunkCount)
+ _manyChunks = new ManyChunkInfo(stringBuilder, chunkCount);
+ }
+
+ private static int ChunkCount(StringBuilder stringBuilder)
+ {
+ int ret = 0;
+ while (stringBuilder != null)
+ {
+ ret++;
+ stringBuilder = stringBuilder.m_ChunkPrevious;
+ }
+ return ret;
+ }
+
+ /// <summary>
+ /// Used to hold all the chunks indexes when you have many chunks.
+ /// </summary>
+ private class ManyChunkInfo
+ {
+ private readonly StringBuilder[] _chunks; // These are in normal order (first chunk first)
+ private int _chunkPos;
+
+ public bool MoveNext(ref StringBuilder current)
+ {
+ int pos = ++_chunkPos;
+ if (_chunks.Length <= pos)
+ return false;
+ current = _chunks[pos];
+ return true;
+ }
+
+ public ManyChunkInfo(StringBuilder stringBuilder, int chunkCount)
+ {
+ _chunks = new StringBuilder[chunkCount];
+ while (0 <= --chunkCount)
+ {
+ Debug.Assert(stringBuilder != null);
+ _chunks[chunkCount] = stringBuilder;
+ stringBuilder = stringBuilder.m_ChunkPrevious;
+ }
+ _chunkPos = -1;
+ }
+ }
+#endregion
+ }
+
+ /// <summary>
/// Appends a character 0 or more times to the end of this builder.
/// </summary>
/// <param name="value">The character to append.</param>
@@ -648,7 +787,7 @@ namespace System.Text
/// Appends a string to the end of this builder.
/// </summary>
/// <param name="value">The string to append.</param>
- public StringBuilder Append(String value)
+ public StringBuilder Append(string value)
{
if (value != null)
{
@@ -691,7 +830,7 @@ namespace System.Text
}
// We put this fixed in its own helper to avoid the cost of zero-initing `valueChars` in the
- // case we don't actually use it.
+ // case we don't actually use it.
private void AppendHelper(string value)
{
unsafe
@@ -903,7 +1042,7 @@ namespace System.Text
/// <param name="index">The index to insert in this builder.</param>
/// <param name="value">The string to insert.</param>
/// <param name="count">The number of times to insert the string.</param>
- public StringBuilder Insert(int index, String value, int count)
+ public StringBuilder Insert(int index, string value, int count)
{
if (count < 0)
{
@@ -921,7 +1060,7 @@ namespace System.Text
return this;
}
- // Ensure we don't insert more chars than we can hold, and we don't
+ // Ensure we don't insert more chars than we can hold, and we don't
// have any integer overflow in our new length.
long insertingChars = (long)value.Length * count;
if (insertingChars > MaxCapacity - this.Length)
@@ -1115,7 +1254,7 @@ namespace System.Text
{
return AppendJoinCore(&separator, 1, values);
}
-
+
private unsafe StringBuilder AppendJoinCore<T>(char* separator, int separatorLength, IEnumerable<T> values)
{
Debug.Assert(separator != null);
@@ -1182,7 +1321,7 @@ namespace System.Text
#endregion
- public StringBuilder Insert(int index, String value)
+ public StringBuilder Insert(int index, string value)
{
if ((uint)index > (uint)Length)
{
@@ -1292,7 +1431,7 @@ namespace System.Text
[CLSCompliant(false)]
public StringBuilder Insert(int index, ulong value) => Insert(index, value.ToString(), 1);
- public StringBuilder Insert(int index, Object value) => (value == null) ? this : Insert(index, value.ToString(), 1);
+ public StringBuilder Insert(int index, object value) => (value == null) ? this : Insert(index, value.ToString(), 1);
public StringBuilder Insert(int index, ReadOnlySpan<char> value)
{
@@ -1312,13 +1451,13 @@ namespace System.Text
return this;
}
- public StringBuilder AppendFormat(String format, Object arg0) => AppendFormatHelper(null, format, new ParamsArray(arg0));
+ 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));
+ public StringBuilder AppendFormat(string format, object arg0, object arg1) => AppendFormatHelper(null, format, new ParamsArray(arg0, arg1));
- public StringBuilder AppendFormat(String format, Object arg0, Object arg1, Object arg2) => AppendFormatHelper(null, format, new ParamsArray(arg0, arg1, arg2));
+ public StringBuilder AppendFormat(string format, object arg0, object arg1, object arg2) => AppendFormatHelper(null, format, new ParamsArray(arg0, arg1, arg2));
- public StringBuilder AppendFormat(String format, params Object[] args)
+ public StringBuilder AppendFormat(string format, params object[] args)
{
if (args == null)
{
@@ -1331,13 +1470,13 @@ namespace System.Text
return AppendFormatHelper(null, format, new ParamsArray(args));
}
- public StringBuilder AppendFormat(IFormatProvider provider, String format, Object arg0) => AppendFormatHelper(provider, format, new ParamsArray(arg0));
+ public StringBuilder AppendFormat(IFormatProvider provider, string format, object arg0) => AppendFormatHelper(provider, format, new ParamsArray(arg0));
- public StringBuilder AppendFormat(IFormatProvider provider, String format, Object arg0, Object arg1) => AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1));
+ public StringBuilder AppendFormat(IFormatProvider provider, string format, object arg0, object arg1) => AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1));
- public StringBuilder AppendFormat(IFormatProvider provider, String format, Object arg0, Object arg1, Object arg2) => AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1, arg2));
+ public StringBuilder AppendFormat(IFormatProvider provider, string format, object arg0, object arg1, object arg2) => AppendFormatHelper(provider, format, new ParamsArray(arg0, arg1, arg2));
- public StringBuilder AppendFormat(IFormatProvider provider, String format, params Object[] args)
+ public StringBuilder AppendFormat(IFormatProvider provider, string format, params object[] args)
{
if (args == null)
{
@@ -1359,7 +1498,7 @@ namespace System.Text
private const int IndexLimit = 1000000; // Note: 0 <= ArgIndex < IndexLimit
private const int WidthLimit = 1000000; // Note: -WidthLimit < ArgAlign < WidthLimit
- internal StringBuilder AppendFormatHelper(IFormatProvider provider, String format, ParamsArray args)
+ internal StringBuilder AppendFormatHelper(IFormatProvider provider, string format, ParamsArray args)
{
if (format == null)
{
@@ -1495,8 +1634,8 @@ namespace System.Text
//
// Start of parsing of optional formatting parameter.
//
- Object arg = args[index];
- String itemFormat = null;
+ object arg = args[index];
+ string itemFormat = null;
ReadOnlySpan<char> itemFormatSpan = default; // used if itemFormat is null
// Is current character a colon? which indicates start of formatting parameter.
if (ch == ':')
@@ -1552,7 +1691,7 @@ namespace System.Text
if (startPos != pos)
{
// There was no brace escaping, extract the item format as a single string
- itemFormatSpan = format.AsSpan().Slice(startPos, pos - startPos);
+ itemFormatSpan = format.AsSpan(startPos, pos - startPos);
}
}
else
@@ -1566,7 +1705,7 @@ namespace System.Text
if (ch != '}') FormatError();
// Construct the output for this arg hole.
pos++;
- String s = null;
+ string s = null;
if (cf != null)
{
if (itemFormatSpan.Length != 0 && itemFormat == null)
@@ -1609,7 +1748,7 @@ namespace System.Text
}
}
// Append it to the final output of the Format String.
- if (s == null) s = String.Empty;
+ if (s == null) s = string.Empty;
int pad = width - s.Length;
if (!leftJustify && pad > 0) Append(' ', pad);
Append(s);
@@ -1628,7 +1767,7 @@ namespace System.Text
/// If <paramref name="newValue"/> is <c>null</c>, instances of <paramref name="oldValue"/>
/// are removed from this builder.
/// </remarks>
- public StringBuilder Replace(String oldValue, String newValue) => Replace(oldValue, newValue, 0, Length);
+ public StringBuilder Replace(string oldValue, string newValue) => Replace(oldValue, newValue, 0, Length);
/// <summary>
/// Determines if the contents of this builder are equal to the contents of another builder.
@@ -1680,10 +1819,10 @@ namespace System.Text
/// <summary>
/// Determines if the contents of this builder are equal to the contents of ReadOnlySpan<char>.
/// </summary>
- /// <param name="value">The ReadOnlySpan{char}.</param>
- public bool Equals(ReadOnlySpan<char> value)
+ /// <param name="span">The ReadOnlySpan{char}.</param>
+ public bool Equals(ReadOnlySpan<char> span)
{
- if (value.Length != Length)
+ if (span.Length != Length)
return false;
StringBuilder sbChunk = this;
@@ -1696,7 +1835,7 @@ namespace System.Text
ReadOnlySpan<char> chunk = new ReadOnlySpan<char>(sbChunk.m_ChunkChars, 0, chunk_length);
- if (!chunk.Equals(value.Slice(value.Length - offset, chunk_length)))
+ if (!chunk.EqualsOrdinal(span.Slice(span.Length - offset, chunk_length)))
return false;
sbChunk = sbChunk.m_ChunkPrevious;
@@ -1717,7 +1856,7 @@ namespace System.Text
/// If <paramref name="newValue"/> is <c>null</c>, instances of <paramref name="oldValue"/>
/// are removed from this builder.
/// </remarks>
- public StringBuilder Replace(String oldValue, String newValue, int startIndex, int count)
+ public StringBuilder Replace(string oldValue, string newValue, int startIndex, int count)
{
int currentLength = Length;
if ((uint)startIndex > (uint)currentLength)
@@ -1749,7 +1888,7 @@ namespace System.Text
int indexInChunk = startIndex - chunk.m_ChunkOffset;
while (count > 0)
{
- // Look for a match in the chunk,indexInChunk pointer
+ // Look for a match in the chunk,indexInChunk pointer
if (StartsWith(chunk, indexInChunk, count, oldValue))
{
// Push it on the replacements array (with growth), we will do all replacements in a
@@ -1775,13 +1914,13 @@ namespace System.Text
if (indexInChunk >= chunk.m_ChunkLength || count == 0) // Have we moved out of the current chunk?
{
- // Replacing mutates the blocks, so we need to convert to a logical index and back afterwards.
+ // Replacing mutates the blocks, so we need to convert to a logical index and back afterwards.
int index = indexInChunk + chunk.m_ChunkOffset;
int indexBeforeAdjustment = index;
// See if we accumulated any replacements, if so apply them.
ReplaceAllInChunk(replacements, replacementsCount, chunk, oldValue.Length, newValue);
- // The replacement has affected the logical index. Adjust it.
+ // The replacement has affected the logical index. Adjust it.
index += ((newValue.Length - oldValue.Length) * replacementsCount);
replacementsCount = 0;
@@ -1874,7 +2013,7 @@ namespace System.Text
throw new ArgumentOutOfRangeException(nameof(valueCount), SR.ArgumentOutOfRange_LengthGreaterThanCapacity);
}
- // This case is so common we want to optimize for it heavily.
+ // This case is so common we want to optimize for it heavily.
int newIndex = valueCount + m_ChunkLength;
if (newIndex <= m_ChunkChars.Length)
{
@@ -1891,7 +2030,7 @@ namespace System.Text
m_ChunkLength = m_ChunkChars.Length;
}
- // Expand the builder to add another chunk.
+ // Expand the builder to add another chunk.
int restLength = valueCount - firstLength;
ExpandByABlock(restLength);
Debug.Assert(m_ChunkLength == 0, "A new block was not created.");
@@ -1948,16 +2087,16 @@ namespace System.Text
{
fixed (char* valuePtr = value)
{
- // calculate the total amount of extra space or space needed for all the replacements.
+ // calculate the total amount of extra space or space needed for all the replacements.
int delta = (value.Length - removeCount) * replacementsCount;
StringBuilder targetChunk = sourceChunk; // the target as we copy chars down
int targetIndexInChunk = replacements[0];
- // Make the room needed for all the new characters if needed.
+ // Make the room needed for all the new characters if needed.
if (delta > 0)
MakeRoom(targetChunk.m_ChunkOffset + targetIndexInChunk, delta, out targetChunk, out targetIndexInChunk, true);
- // We made certain that characters after the insertion point are not moved,
+ // We made certain that characters after the insertion point are not moved,
int i = 0;
for (;;)
{
@@ -1974,7 +2113,7 @@ namespace System.Text
Debug.Assert(gapStart < sourceChunk.m_ChunkChars.Length, "gap starts at end of buffer. Should not happen");
Debug.Assert(gapStart <= gapEnd, "negative gap size");
Debug.Assert(gapEnd <= sourceChunk.m_ChunkLength, "gap too big");
- if (delta != 0) // can skip the sliding of gaps if source an target string are the same size.
+ if (delta != 0) // can skip the sliding of gaps if source an target string are the same size.
{
// Copy the gap data between the current replacement and the next replacement
fixed (char* sourcePtr = &sourceChunk.m_ChunkChars[gapStart])
@@ -1987,7 +2126,7 @@ namespace System.Text
}
}
- // Remove extra space if necessary.
+ // Remove extra space if necessary.
if (delta < 0)
Remove(targetChunk.m_ChunkOffset + targetIndexInChunk, -delta, out targetChunk, out targetIndexInChunk);
}
@@ -2044,7 +2183,7 @@ namespace System.Text
/// </param>
/// <param name="value">The pointer to the start of the character buffer.</param>
/// <param name="count">The number of characters in the buffer.</param>
- unsafe private void ReplaceInPlaceAtChunk(ref StringBuilder chunk, ref int indexInChunk, char* value, int count)
+ private unsafe void ReplaceInPlaceAtChunk(ref StringBuilder chunk, ref int indexInChunk, char* value, int count)
{
if (count != 0)
{
@@ -2056,7 +2195,7 @@ namespace System.Text
int lengthToCopy = Math.Min(lengthInChunk, count);
ThreadSafeCopy(value, chunk.m_ChunkChars, indexInChunk, lengthToCopy);
- // Advance the index.
+ // Advance the index.
indexInChunk += lengthToCopy;
if (indexInChunk >= chunk.m_ChunkLength)
{
@@ -2374,7 +2513,7 @@ namespace System.Text
int endIndex = startIndex + count;
- // Find the chunks for the start and end of the block to delete.
+ // Find the chunks for the start and end of the block to delete.
chunk = this;
StringBuilder endChunk = null;
int endIndexInChunk = 0;
@@ -2425,7 +2564,7 @@ namespace System.Text
// SafeCritical: We ensure that `endIndexInChunk + copyCount` is within range of `m_ChunkChars`, and
// also ensure that `copyTargetIndexInChunk + copyCount` is within the chunk.
- // Remove any characters in the end chunk, by sliding the characters down.
+ // Remove any characters in the end chunk, by sliding the characters down.
if (copyTargetIndexInChunk != endIndexInChunk) // Sometimes no move is necessary
{
ThreadSafeCopy(endChunk.m_ChunkChars, endIndexInChunk, endChunk.m_ChunkChars, copyTargetIndexInChunk, copyCount);
diff --git a/src/System.Private.CoreLib/shared/System/Text/StringBuilderCache.cs b/src/System.Private.CoreLib/shared/System/Text/StringBuilderCache.cs
new file mode 100644
index 000000000..e699cc27c
--- /dev/null
+++ b/src/System.Private.CoreLib/shared/System/Text/StringBuilderCache.cs
@@ -0,0 +1,62 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace System.Text
+{
+ /// <summary>Provide a cached reusable instance of stringbuilder per thread.</summary>
+ internal static class StringBuilderCache
+ {
+ // The value 360 was chosen in discussion with performance experts as a compromise between using
+ // as litle memory per thread as possible and still covering a large part of short-lived
+ // StringBuilder creations on the startup path of VS designers.
+ private const int MaxBuilderSize = 360;
+ private const int DefaultCapacity = 16; // == StringBuilder.DefaultCapacity
+
+ // WARNING: We allow diagnostic tools to directly inspect this member (t_cachedInstance).
+ // See https://github.com/dotnet/corert/blob/master/Documentation/design-docs/diagnostics/diagnostics-tools-contract.md for more details.
+ // Please do not change the type, the name, or the semantic usage of this member without understanding the implication for tools.
+ // Get in touch with the diagnostics team if you have questions.
+ [ThreadStatic]
+ private static StringBuilder t_cachedInstance;
+
+ /// <summary>Get a StringBuilder for the specified capacity.</summary>
+ /// <remarks>If a StringBuilder of an appropriate size is cached, it will be returned and the cache emptied.</remarks>
+ public static StringBuilder Acquire(int capacity = DefaultCapacity)
+ {
+ if (capacity <= MaxBuilderSize)
+ {
+ StringBuilder sb = t_cachedInstance;
+ if (sb != null)
+ {
+ // Avoid stringbuilder block fragmentation by getting a new StringBuilder
+ // when the requested size is larger than the current capacity
+ if (capacity <= sb.Capacity)
+ {
+ t_cachedInstance = null;
+ sb.Clear();
+ return sb;
+ }
+ }
+ }
+ return new StringBuilder(capacity);
+ }
+
+ /// <summary>Place the specified builder in the cache if it is not too big.</summary>
+ public static void Release(StringBuilder sb)
+ {
+ if (sb.Capacity <= MaxBuilderSize)
+ {
+ t_cachedInstance = sb;
+ }
+ }
+
+ /// <summary>ToString() the stringbuilder, Release it to the cache, and return the resulting string.</summary>
+ public static string GetStringAndRelease(StringBuilder sb)
+ {
+ string result = sb.ToString();
+ Release(sb);
+ return result;
+ }
+ }
+}
diff --git a/src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs
index 7828775ea..86169e6b1 100644
--- a/src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/UTF32Encoding.cs
@@ -103,13 +103,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -125,11 +125,11 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe int GetByteCount(String s)
+ public override unsafe int GetByteCount(string s)
{
// Validate input
if (s==null)
- throw new ArgumentNullException("s");
+ throw new ArgumentNullException(nameof(s));
fixed (char* pChars = s)
return GetByteCount(pChars, s.Length, null);
@@ -144,10 +144,10 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
@@ -158,20 +158,20 @@ namespace System.Text
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
- public override unsafe int GetBytes(String s, int charIndex, int charCount,
+ public override unsafe int GetBytes(string s, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (s == null || bytes == null)
- throw new ArgumentNullException((s == null ? "s" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((s == null ? nameof(s) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (s.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("s", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -198,16 +198,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0, avoid fixed problem
if (charCount == 0)
@@ -230,10 +230,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
@@ -250,13 +250,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays.
if (count == 0)
@@ -276,10 +276,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
@@ -294,16 +294,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -326,10 +326,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
@@ -342,23 +342,23 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe String GetString(byte[] bytes, int index, int count)
+ public override unsafe string GetString(byte[] bytes, int index, int count)
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (count == 0) return String.Empty;
+ if (count == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + index, count, this);
}
@@ -417,7 +417,7 @@ namespace System.Text
//
// In previous char, we encounter a high surrogate, so we are expecting a low surrogate here.
//
- if (Char.IsLowSurrogate(ch))
+ if (char.IsLowSurrogate(ch))
{
// They're all legal
highSurrogate = '\0';
@@ -447,7 +447,7 @@ namespace System.Text
}
// Do we have another high surrogate?
- if (Char.IsHighSurrogate(ch))
+ if (char.IsHighSurrogate(ch))
{
//
// We'll have a high surrogate to check next time.
@@ -457,7 +457,7 @@ namespace System.Text
}
// Check for illegal characters
- if (Char.IsLowSurrogate(ch))
+ if (char.IsLowSurrogate(ch))
{
// We have a leading low surrogate, do the fallback
charsForFallback = chars;
@@ -552,7 +552,7 @@ namespace System.Text
//
// In previous char, we encountered a high surrogate, so we are expecting a low surrogate here.
//
- if (Char.IsLowSurrogate(ch))
+ if (char.IsLowSurrogate(ch))
{
// Is it a legal one?
uint iTemp = GetSurrogate(highSurrogate, ch);
@@ -616,7 +616,7 @@ namespace System.Text
}
// Do we have another high surrogate?, if so remember it
- if (Char.IsHighSurrogate(ch))
+ if (char.IsHighSurrogate(ch))
{
//
// We'll have a high surrogate to check next time.
@@ -626,7 +626,7 @@ namespace System.Text
}
// Check for illegal characters (low surrogate)
- if (Char.IsLowSurrogate(ch))
+ if (char.IsLowSurrogate(ch))
{
// We have a leading low surrogate, do the fallback
charsForFallback = chars;
@@ -1159,7 +1159,7 @@ namespace System.Text
_emitUTF32ByteOrderMark ? (_bigEndian ? s_bigEndianPreamble : s_littleEndianPreamble) :
Array.Empty<byte>();
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
UTF32Encoding that = value as UTF32Encoding;
if (that != null)
diff --git a/src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs
index 0246c2891..5c51c8107 100644
--- a/src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/UTF7Encoding.cs
@@ -14,17 +14,17 @@ namespace System.Text
{
public class UTF7Encoding : Encoding
{
- private const String base64Chars =
+ private const string base64Chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
// 0123456789111111111122222222223333333333444444444455555555556666
// 012345678901234567890123456789012345678901234567890123
// These are the characters that can be directly encoded in UTF7.
- private const String directChars =
+ private const string directChars =
"\t\n\r '(),-./0123456789:?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
// These are the characters that can be optionally directly encoded in UTF7.
- private const String optionalChars =
+ private const string optionalChars =
"!\"#$%&*;<=>@[]^_`{|}";
// Used by Encoding.UTF7 for lazy initialization
@@ -88,16 +88,16 @@ namespace System.Text
}
// We go ahead and set this because Encoding expects it, however nothing can fall back in UTF7.
- internal override void SetDefaultFallbacks()
+ internal sealed override void SetDefaultFallbacks()
{
// UTF7 had an odd decoderFallback behavior, and the Encoder fallback
// is irrelevant because we encode surrogates individually and never check for unmatched ones
// (so nothing can fallback during encoding)
- this.encoderFallback = new EncoderReplacementFallback(String.Empty);
+ this.encoderFallback = new EncoderReplacementFallback(string.Empty);
this.decoderFallback = new DecoderUTF7Fallback();
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
UTF7Encoding that = value as UTF7Encoding;
if (that != null)
@@ -133,13 +133,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -159,7 +159,7 @@ namespace System.Text
{
// Validate input
if (s==null)
- throw new ArgumentNullException("s");
+ throw new ArgumentNullException(nameof(s));
fixed (char* pChars = s)
return GetByteCount(pChars, s.Length, null);
@@ -174,10 +174,10 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
@@ -192,16 +192,16 @@ namespace System.Text
byte[] bytes, int byteIndex)
{
if (s == null || bytes == null)
- throw new ArgumentNullException((s == null ? "s" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((s == null ? nameof(s) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (s.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("s", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -228,16 +228,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0, avoid fixed problem
if (charCount == 0)
@@ -260,10 +260,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
@@ -280,13 +280,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays.
if (count == 0)
@@ -306,10 +306,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
@@ -324,16 +324,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -356,10 +356,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
@@ -372,23 +372,23 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe String GetString(byte[] bytes, int index, int count)
+ public override unsafe string GetString(byte[] bytes, int index, int count)
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (count == 0) return String.Empty;
+ if (count == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + index, count, this);
}
@@ -396,7 +396,7 @@ namespace System.Text
// End of standard methods copied from EncodingNLS.cs
//
- internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder)
+ internal sealed override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder)
{
Debug.Assert(chars != null, "[UTF7Encoding.GetByteCount]chars!=null");
Debug.Assert(count >= 0, "[UTF7Encoding.GetByteCount]count >=0");
@@ -405,8 +405,8 @@ namespace System.Text
return GetBytes(chars, count, null, 0, baseEncoder);
}
- internal override unsafe int GetBytes(char* chars, int charCount,
- byte* bytes, int byteCount, EncoderNLS baseEncoder)
+ internal sealed override unsafe int GetBytes(
+ char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS baseEncoder)
{
Debug.Assert(byteCount >= 0, "[UTF7Encoding.GetBytes]byteCount >=0");
Debug.Assert(chars != null, "[UTF7Encoding.GetBytes]chars!=null");
@@ -545,7 +545,7 @@ namespace System.Text
return buffer.Count;
}
- internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
{
Debug.Assert(count >= 0, "[UTF7Encoding.GetCharCount]count >=0");
Debug.Assert(bytes != null, "[UTF7Encoding.GetCharCount]bytes!=null");
@@ -554,8 +554,8 @@ namespace System.Text
return GetChars(bytes, count, null, 0, baseDecoder);
}
- internal override unsafe int GetChars(byte* bytes, int byteCount,
- char* chars, int charCount, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetChars(
+ byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder)
{
Debug.Assert(byteCount >= 0, "[UTF7Encoding.GetChars]byteCount >=0");
Debug.Assert(bytes != null, "[UTF7Encoding.GetChars]bytes!=null");
@@ -873,7 +873,7 @@ namespace System.Text
}
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
DecoderUTF7Fallback that = value as DecoderUTF7Fallback;
if (that != null)
diff --git a/src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs b/src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs
index 67f87c9b0..c9e51f661 100644
--- a/src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/UTF8Encoding.cs
@@ -93,7 +93,7 @@ namespace System.Text
SetDefaultFallbacks();
}
- internal override void SetDefaultFallbacks()
+ internal sealed override void SetDefaultFallbacks()
{
// For UTF-X encodings, we use a replacement fallback with an empty string
if (_isThrowException)
@@ -130,13 +130,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -152,7 +152,7 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe int GetByteCount(String chars)
+ public override unsafe int GetByteCount(string chars)
{
// Validate input
if (chars==null)
@@ -171,34 +171,42 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
}
+ public override unsafe int GetByteCount(ReadOnlySpan<char> chars)
+ {
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ {
+ return GetByteCount(charsPtr, chars.Length, baseEncoder: null);
+ }
+ }
+
// Parent method is safe.
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
- public override unsafe int GetBytes(String s, int charIndex, int charCount,
+ public override unsafe int GetBytes(string s, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (s == null || bytes == null)
- throw new ArgumentNullException((s == null ? "s" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((s == null ? nameof(s) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (s.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("s", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -225,16 +233,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0, avoid fixed problem
if (charCount == 0)
@@ -257,14 +265,23 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
+ public override unsafe int GetBytes(ReadOnlySpan<char> chars, Span<byte> bytes)
+ {
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ {
+ return GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length, baseEncoder: null);
+ }
+ }
+
// Returns the number of characters produced by decoding a range of bytes
// in a byte array.
//
@@ -277,13 +294,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays.
if (count == 0)
@@ -303,14 +320,22 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
+ public override unsafe int GetCharCount(ReadOnlySpan<byte> bytes)
+ {
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ {
+ return GetCharCount(bytesPtr, bytes.Length, baseDecoder: null);
+ }
+ }
+
// All of our public Encodings that don't use EncodingNLS must have this (including EncodingNLS)
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
@@ -321,16 +346,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -353,14 +378,23 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
+ public override unsafe int GetChars(ReadOnlySpan<byte> bytes, Span<char> chars)
+ {
+ fixed (byte* bytesPtr = &MemoryMarshal.GetNonNullPinnableReference(bytes))
+ fixed (char* charsPtr = &MemoryMarshal.GetNonNullPinnableReference(chars))
+ {
+ return GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length, baseDecoder: null);
+ }
+ }
+
// Returns a string containing the decoded representation of a range of
// bytes in a byte array.
//
@@ -369,23 +403,23 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe String GetString(byte[] bytes, int index, int count)
+ public override unsafe string GetString(byte[] bytes, int index, int count)
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (count == 0) return String.Empty;
+ if (count == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + index, count, this);
}
@@ -395,7 +429,7 @@ namespace System.Text
// To simplify maintenance, the structure of GetByteCount and GetBytes should be
// kept the same as much as possible
- internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder)
+ internal sealed override unsafe int GetByteCount(char* chars, int count, EncoderNLS baseEncoder)
{
// For fallback we may need a fallback buffer.
// We wait to initialize it though in case we don't have any broken input unicode
@@ -715,12 +749,15 @@ namespace System.Text
break;
LongCodeWithMask:
-#if BIGENDIAN
- // be careful about the sign extension
- ch = (int)(((uint)ch) >> 16);
-#else // BIGENDIAN
- ch = (char)ch;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ ch = (char)ch;
+ }
+ else
+ {
+ // be careful about the sign extension
+ ch = (int)(((uint)ch) >> 16);
+ }
pSrc++;
if (ch <= 0x7F)
@@ -783,13 +820,13 @@ namespace System.Text
// diffs two char pointers using unsigned arithmetic. The unsigned arithmetic
// is good enough for us, and it tends to generate better code than the signed
// arithmetic generated by default
- unsafe private static int PtrDiff(char* a, char* b)
+ private static unsafe int PtrDiff(char* a, char* b)
{
return (int)(((uint)((byte*)a - (byte*)b)) >> 1);
}
// byte* flavor just for parity
- unsafe private static int PtrDiff(byte* a, byte* b)
+ private static unsafe int PtrDiff(byte* a, byte* b)
{
return (int)(a - b);
}
@@ -801,8 +838,8 @@ namespace System.Text
// Our workhorse
// Note: We ignore mismatched surrogates, unless the exception flag is set in which case we throw
- internal override unsafe int GetBytes(char* chars, int charCount,
- byte* bytes, int byteCount, EncoderNLS baseEncoder)
+ internal sealed override unsafe int GetBytes(
+ char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS baseEncoder)
{
Debug.Assert(chars != null, "[UTF8Encoding.GetBytes]chars!=null");
Debug.Assert(byteCount >= 0, "[UTF8Encoding.GetBytes]byteCount >=0");
@@ -1142,31 +1179,37 @@ namespace System.Text
}
// Unfortunately, this is endianess sensitive
-#if BIGENDIAN
- *pTarget = (byte)(ch>>16);
- *(pTarget+1) = (byte)ch;
- pSrc += 4;
- *(pTarget+2) = (byte)(chc>>16);
- *(pTarget+3) = (byte)chc;
- pTarget += 4;
-#else // BIGENDIAN
- *pTarget = (byte)ch;
- *(pTarget + 1) = (byte)(ch >> 16);
- pSrc += 4;
- *(pTarget + 2) = (byte)chc;
- *(pTarget + 3) = (byte)(chc >> 16);
- pTarget += 4;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ *pTarget = (byte)ch;
+ *(pTarget + 1) = (byte)(ch >> 16);
+ pSrc += 4;
+ *(pTarget + 2) = (byte)chc;
+ *(pTarget + 3) = (byte)(chc >> 16);
+ pTarget += 4;
+ }
+ else
+ {
+ *pTarget = (byte)(ch>>16);
+ *(pTarget+1) = (byte)ch;
+ pSrc += 4;
+ *(pTarget+2) = (byte)(chc>>16);
+ *(pTarget+3) = (byte)chc;
+ pTarget += 4;
+ }
}
continue;
LongCodeWithMask:
-#if BIGENDIAN
- // be careful about the sign extension
- ch = (int)(((uint)ch) >> 16);
-#else // BIGENDIAN
- ch = (char)ch;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ ch = (char)ch;
+ }
+ else
+ {
+ // be careful about the sign extension
+ ch = (int)(((uint)ch) >> 16);
+ }
pSrc++;
if (ch > 0x7F)
@@ -1284,7 +1327,7 @@ namespace System.Text
//
// To simplify maintenance, the structure of GetCharCount and GetChars should be
// kept the same as much as possible
- internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
{
Debug.Assert(count >= 0, "[UTF8Encoding.GetCharCount]count >=0");
Debug.Assert(bytes != null, "[UTF8Encoding.GetCharCount]bytes!=null");
@@ -1564,17 +1607,26 @@ namespace System.Text
}
break;
-#if BIGENDIAN
- LongCodeWithMask32:
- // be careful about the sign extension
- ch = (int)(((uint)ch) >> 16);
- LongCodeWithMask16:
- ch = (int)(((uint)ch) >> 8);
-#else // BIGENDIAN
LongCodeWithMask32:
+ if (BitConverter.IsLittleEndian)
+ {
+ ch &= 0xFF;
+ }
+ else
+ {
+ // be careful about the sign extension
+ ch = (int)(((uint)ch) >> 16);
+ }
LongCodeWithMask16:
- ch &= 0xFF;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ ch &= 0xFF;
+ }
+ else
+ {
+ ch = (int)(((uint)ch) >> 8);
+ }
+
pSrc++;
if (ch <= 0x7F)
{
@@ -1713,8 +1765,8 @@ namespace System.Text
//
// To simplify maintenance, the structure of GetCharCount and GetChars should be
// kept the same as much as possible
- internal override unsafe int GetChars(byte* bytes, int byteCount,
- char* chars, int charCount, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetChars(
+ byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder)
{
Debug.Assert(chars != null, "[UTF8Encoding.GetChars]chars!=null");
Debug.Assert(byteCount >= 0, "[UTF8Encoding.GetChars]count >=0");
@@ -2048,17 +2100,20 @@ namespace System.Text
}
// Unfortunately, this is endianess sensitive
-#if BIGENDIAN
- *pTarget = (char)((ch >> 8) & 0x7F);
- pSrc += 2;
- *(pTarget+1) = (char)(ch & 0x7F);
- pTarget += 2;
-#else // BIGENDIAN
- *pTarget = (char)(ch & 0x7F);
- pSrc += 2;
- *(pTarget + 1) = (char)((ch >> 8) & 0x7F);
- pTarget += 2;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ *pTarget = (char)(ch & 0x7F);
+ pSrc += 2;
+ *(pTarget + 1) = (char)((ch >> 8) & 0x7F);
+ pTarget += 2;
+ }
+ else
+ {
+ *pTarget = (char)((ch >> 8) & 0x7F);
+ pSrc += 2;
+ *(pTarget+1) = (char)(ch & 0x7F);
+ pTarget += 2;
+ }
}
// Run 8 characters at a time!
@@ -2072,43 +2127,54 @@ namespace System.Text
}
// Unfortunately, this is endianess sensitive
-#if BIGENDIAN
- *pTarget = (char)((ch >> 24) & 0x7F);
- *(pTarget+1) = (char)((ch >> 16) & 0x7F);
- *(pTarget+2) = (char)((ch >> 8) & 0x7F);
- *(pTarget+3) = (char)(ch & 0x7F);
- pSrc += 8;
- *(pTarget+4) = (char)((chb >> 24) & 0x7F);
- *(pTarget+5) = (char)((chb >> 16) & 0x7F);
- *(pTarget+6) = (char)((chb >> 8) & 0x7F);
- *(pTarget+7) = (char)(chb & 0x7F);
- pTarget += 8;
-#else // BIGENDIAN
- *pTarget = (char)(ch & 0x7F);
- *(pTarget + 1) = (char)((ch >> 8) & 0x7F);
- *(pTarget + 2) = (char)((ch >> 16) & 0x7F);
- *(pTarget + 3) = (char)((ch >> 24) & 0x7F);
- pSrc += 8;
- *(pTarget + 4) = (char)(chb & 0x7F);
- *(pTarget + 5) = (char)((chb >> 8) & 0x7F);
- *(pTarget + 6) = (char)((chb >> 16) & 0x7F);
- *(pTarget + 7) = (char)((chb >> 24) & 0x7F);
- pTarget += 8;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ *pTarget = (char)(ch & 0x7F);
+ *(pTarget + 1) = (char)((ch >> 8) & 0x7F);
+ *(pTarget + 2) = (char)((ch >> 16) & 0x7F);
+ *(pTarget + 3) = (char)((ch >> 24) & 0x7F);
+ pSrc += 8;
+ *(pTarget + 4) = (char)(chb & 0x7F);
+ *(pTarget + 5) = (char)((chb >> 8) & 0x7F);
+ *(pTarget + 6) = (char)((chb >> 16) & 0x7F);
+ *(pTarget + 7) = (char)((chb >> 24) & 0x7F);
+ pTarget += 8;
+ }
+ else
+ {
+ *pTarget = (char)((ch >> 24) & 0x7F);
+ *(pTarget+1) = (char)((ch >> 16) & 0x7F);
+ *(pTarget+2) = (char)((ch >> 8) & 0x7F);
+ *(pTarget+3) = (char)(ch & 0x7F);
+ pSrc += 8;
+ *(pTarget+4) = (char)((chb >> 24) & 0x7F);
+ *(pTarget+5) = (char)((chb >> 16) & 0x7F);
+ *(pTarget+6) = (char)((chb >> 8) & 0x7F);
+ *(pTarget+7) = (char)(chb & 0x7F);
+ pTarget += 8;
+ }
}
break;
-#if BIGENDIAN
- LongCodeWithMask32:
- // be careful about the sign extension
- ch = (int)(((uint)ch) >> 16);
- LongCodeWithMask16:
- ch = (int)(((uint)ch) >> 8);
-#else // BIGENDIAN
LongCodeWithMask32:
+ if (BitConverter.IsLittleEndian)
+ {
+ ch &= 0xFF;
+ }
+ else
+ {
+ // be careful about the sign extension
+ ch = (int)(((uint)ch) >> 16);
+ }
LongCodeWithMask16:
- ch &= 0xFF;
-#endif // BIGENDIAN
+ if (BitConverter.IsLittleEndian)
+ {
+ ch &= 0xFF;
+ }
+ else
+ {
+ ch = (int)(((uint)ch) >> 8);
+ }
pSrc++;
if (ch <= 0x7F)
{
@@ -2173,7 +2239,7 @@ namespace System.Text
// extra byte, we're already planning 2 chars for 2 of these bytes,
// but the big loop is testing the target against pStop, so we need
- // to subtract 2 more or we risk overrunning the input. Subtract
+ // to subtract 2 more or we risk overrunning the input. Subtract
// one here and one below.
pStop--;
}
@@ -2323,11 +2389,17 @@ namespace System.Text
private unsafe int FallbackInvalidByteSequence(
byte* pSrc, int ch, DecoderFallbackBuffer fallback)
{
+ // Calling GetBytesUnknown can adjust the pSrc pointer but we need to pass the pointer before the adjustment
+ // to fallback.InternalFallback. The input pSrc to fallback.InternalFallback will only be used to calculate the
+ // index inside bytesUnknown and if we pass the adjusted pointer we can end up with negative index values.
+ // We store the original pSrc in pOriginalSrc and then pass pOriginalSrc to fallback.InternalFallback.
+ byte* pOriginalSrc = pSrc;
+
// Get our byte[]
byte[] bytesUnknown = GetBytesUnknown(ref pSrc, ch);
// Do the actual fallback
- int count = fallback.InternalFallback(bytesUnknown, pSrc);
+ int count = fallback.InternalFallback(bytesUnknown, pOriginalSrc);
// # of fallback chars expected.
// Note that we only get here for "long" sequences, and have already unreserved
@@ -2336,7 +2408,7 @@ namespace System.Text
}
// Note that some of these bytes may have come from a previous fallback, so we cannot
- // just decrement the pointer and use the values we read. In those cases we have
+ // just decrement the pointer and use the values we read. In those cases we have
// to regenerate the original values.
private unsafe byte[] GetBytesUnknown(ref byte* pSrc, int ch)
{
@@ -2481,7 +2553,7 @@ namespace System.Text
_emitUTF8Identifier ? s_preamble :
Array.Empty<byte>();
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
UTF8Encoding that = value as UTF8Encoding;
if (that != null)
diff --git a/src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs b/src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs
index 342bf53d6..6a27d2c85 100644
--- a/src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs
@@ -6,11 +6,17 @@
// Don't override IsAlwaysNormalized because it is just a Unicode Transformation and could be confused.
//
+// This define can be used to turn off the fast loops. Useful for finding whether
+// the problem is fastloop-specific.
+#define FASTLOOP
+
using System;
using System.Globalization;
using System.Diagnostics;
using System.Runtime.InteropServices;
+using Internal.Runtime.CompilerServices;
+
namespace System.Text
{
public class UnicodeEncoding : Encoding
@@ -23,15 +29,14 @@ namespace System.Text
private static readonly byte[] s_bigEndianPreamble = new byte[2] { 0xfe, 0xff };
private static readonly byte[] s_littleEndianPreamble = new byte[2] { 0xff, 0xfe };
- internal bool isThrowException = false;
+ private bool isThrowException = false;
- internal bool bigEndian = false;
- internal bool byteOrderMark = true;
+ private bool bigEndian = false;
+ private bool byteOrderMark = true;
// Unicode version 2.0 character size in bytes
public const int CharSize = 2;
-
public UnicodeEncoding()
: this(false, true)
{
@@ -56,7 +61,7 @@ namespace System.Text
SetDefaultFallbacks();
}
- internal override void SetDefaultFallbacks()
+ internal sealed override void SetDefaultFallbacks()
{
// For UTF-X encodings, we use a replacement fallback with an empty string
if (this.isThrowException)
@@ -89,13 +94,13 @@ namespace System.Text
{
// Validate input parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - index < count)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input, return 0, avoid fixed empty array problem
if (count == 0)
@@ -111,11 +116,11 @@ namespace System.Text
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
// parent method is safe
- public override unsafe int GetByteCount(String s)
+ public override unsafe int GetByteCount(string s)
{
// Validate input
if (s==null)
- throw new ArgumentNullException("s");
+ throw new ArgumentNullException(nameof(s));
fixed (char* pChars = s)
return GetByteCount(pChars, s.Length, null);
@@ -130,10 +135,10 @@ namespace System.Text
{
// Validate Parameters
if (chars == null)
- throw new ArgumentNullException("chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(chars), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
// Call it with empty encoder
return GetByteCount(chars, count, null);
@@ -144,20 +149,20 @@ namespace System.Text
// So if you fix this, fix the others. Currently those include:
// EncodingNLS, UTF7Encoding, UTF8Encoding, UTF32Encoding, ASCIIEncoding, UnicodeEncoding
- public override unsafe int GetBytes(String s, int charIndex, int charCount,
+ public override unsafe int GetBytes(string s, int charIndex, int charCount,
byte[] bytes, int byteIndex)
{
if (s == null || bytes == null)
- throw new ArgumentNullException((s == null ? "s" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((s == null ? nameof(s) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (s.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("s", SR.ArgumentOutOfRange_IndexCount);
+ throw new ArgumentOutOfRangeException(nameof(s), SR.ArgumentOutOfRange_IndexCount);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
int byteCount = bytes.Length - byteIndex;
@@ -184,16 +189,16 @@ namespace System.Text
{
// Validate parameters
if (chars == null || bytes == null)
- throw new ArgumentNullException((chars == null ? "chars" : "bytes"), SR.ArgumentNull_Array);
+ throw new ArgumentNullException((chars == null ? nameof(chars) : nameof(bytes)), SR.ArgumentNull_Array);
if (charIndex < 0 || charCount < 0)
- throw new ArgumentOutOfRangeException((charIndex < 0 ? "charIndex" : "charCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charIndex < 0 ? nameof(charIndex) : nameof(charCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (chars.Length - charIndex < charCount)
- throw new ArgumentOutOfRangeException("chars", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(chars), SR.ArgumentOutOfRange_IndexCountBuffer);
if (byteIndex < 0 || byteIndex > bytes.Length)
- throw new ArgumentOutOfRangeException("byteIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(byteIndex), SR.ArgumentOutOfRange_Index);
// If nothing to encode return 0, avoid fixed problem
if (charCount == 0)
@@ -216,10 +221,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetBytes(chars, charCount, bytes, byteCount, null);
}
@@ -236,13 +241,13 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// If no input just return 0, fixed doesn't like 0 length arrays
if (count == 0)
@@ -262,10 +267,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (count < 0)
- throw new ArgumentOutOfRangeException("count", SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException(nameof(count), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetCharCount(bytes, count, null);
}
@@ -280,16 +285,16 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (byteIndex < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((byteIndex < 0 ? "byteIndex" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((byteIndex < 0 ? nameof(byteIndex) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
if ( bytes.Length - byteIndex < byteCount)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
if (charIndex < 0 || charIndex > chars.Length)
- throw new ArgumentOutOfRangeException("charIndex", SR.ArgumentOutOfRange_Index);
+ throw new ArgumentOutOfRangeException(nameof(charIndex), SR.ArgumentOutOfRange_Index);
// If no input, return 0 & avoid fixed problem
if (byteCount == 0)
@@ -312,10 +317,10 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null || chars == null)
- throw new ArgumentNullException(bytes == null ? "bytes" : "chars", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(bytes == null ? nameof(bytes) : nameof(chars), SR.ArgumentNull_Array);
if (charCount < 0 || byteCount < 0)
- throw new ArgumentOutOfRangeException((charCount < 0 ? "charCount" : "byteCount"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((charCount < 0 ? nameof(charCount) : nameof(byteCount)), SR.ArgumentOutOfRange_NeedNonNegNum);
return GetChars(bytes, byteCount, chars, charCount, null);
}
@@ -332,19 +337,19 @@ namespace System.Text
{
// Validate Parameters
if (bytes == null)
- throw new ArgumentNullException("bytes", SR.ArgumentNull_Array);
+ throw new ArgumentNullException(nameof(bytes), SR.ArgumentNull_Array);
if (index < 0 || count < 0)
- throw new ArgumentOutOfRangeException((index < 0 ? "index" : "count"), SR.ArgumentOutOfRange_NeedNonNegNum);
+ throw new ArgumentOutOfRangeException((index < 0 ? nameof(index) : nameof(count)), SR.ArgumentOutOfRange_NeedNonNegNum);
if (bytes.Length - index < count)
- throw new ArgumentOutOfRangeException("bytes", SR.ArgumentOutOfRange_IndexCountBuffer);
+ throw new ArgumentOutOfRangeException(nameof(bytes), SR.ArgumentOutOfRange_IndexCountBuffer);
// Avoid problems with empty input buffer
- if (count == 0) return String.Empty;
+ if (count == 0) return string.Empty;
fixed (byte* pBytes = bytes)
- return String.CreateStringFromEncoding(
+ return string.CreateStringFromEncoding(
pBytes + index, count, this);
}
@@ -352,7 +357,7 @@ namespace System.Text
// End of standard methods copied from EncodingNLS.cs
//
- internal override unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder)
+ internal sealed override unsafe int GetByteCount(char* chars, int count, EncoderNLS encoder)
{
Debug.Assert(chars != null, "[UnicodeEncoding.GetByteCount]chars!=null");
Debug.Assert(count >= 0, "[UnicodeEncoding.GetByteCount]count >=0");
@@ -372,11 +377,6 @@ namespace System.Text
bool wasHereBefore = false;
- // Need -1 to check 2 at a time. If we have an even #, longChars will go
- // from longEnd - 1/2 long to longEnd + 1/2 long. If we're odd, longChars
- // will go from longEnd - 1 long to longEnd. (Might not get to use this)
- ulong* longEnd = (ulong*)(charEnd - 3);
-
// For fallback we may need a fallback buffer
EncoderFallbackBuffer fallbackBuffer = null;
char* charsForFallback;
@@ -410,19 +410,21 @@ namespace System.Text
if (ch == 0)
{
// No fallback, maybe we can do it fast
-#if !NO_FAST_UNICODE_LOOP
-#if BIGENDIAN // If endianess is backwards then each pair of bytes would be backwards.
- if ( bigEndian &&
-#else
- if (!bigEndian &&
-#endif // BIGENDIAN
-
-#if BIT64 // 64 bit CPU needs to be long aligned for this to work.
- charLeftOver == 0 && (unchecked((long)chars) & 7) == 0)
+#if FASTLOOP
+ // If endianess is backwards then each pair of bytes would be backwards.
+ if ( (bigEndian ^ BitConverter.IsLittleEndian) &&
+#if BIT64
+ (unchecked((long)chars) & 7) == 0 &&
#else
- charLeftOver == 0 && (unchecked((int)chars) & 3) == 0)
+ (unchecked((int)chars) & 3) == 0 &&
#endif
+ charLeftOver == 0)
{
+ // Need -1 to check 2 at a time. If we have an even #, longChars will go
+ // from longEnd - 1/2 long to longEnd + 1/2 long. If we're odd, longChars
+ // will go from longEnd - 1 long to longEnd. (Might not get to use this)
+ ulong* longEnd = (ulong*)(charEnd - 3);
+
// Need new char* so we can check 4 at a time
ulong* longChars = (ulong*)chars;
@@ -453,11 +455,8 @@ namespace System.Text
// If they happen to be high/low/high/low, we may as well continue. Check the next
// bit to see if its set (low) or not (high) in the right pattern
-#if BIGENDIAN
- if (((0xfc00fc00fc00fc00 & *longChars) ^ 0xd800dc00d800dc00) != 0)
-#else
- if (((0xfc00fc00fc00fc00 & *longChars) ^ 0xdc00d800dc00d800) != 0)
-#endif
+ if ((0xfc00fc00fc00fc00 & *longChars) !=
+ (BitConverter.IsLittleEndian ? (ulong)0xdc00d800dc00d800 : (ulong)0xd800dc00d800dc00))
{
// Either there weren't 4 surrogates, or the 0x0400 bit was set when a high
// was hoped for or the 0x0400 bit wasn't set where a low was hoped for.
@@ -480,7 +479,7 @@ namespace System.Text
if (chars >= charEnd)
break;
}
-#endif // !NO_FAST_UNICODE_LOOP
+#endif // FASTLOOP
// No fallback, just get next char
ch = *chars;
@@ -651,8 +650,8 @@ namespace System.Text
return byteCount;
}
- internal override unsafe int GetBytes(char* chars, int charCount,
- byte* bytes, int byteCount, EncoderNLS encoder)
+ internal sealed override unsafe int GetBytes(
+ char* chars, int charCount, byte* bytes, int byteCount, EncoderNLS encoder)
{
Debug.Assert(chars != null, "[UnicodeEncoding.GetBytes]chars!=null");
Debug.Assert(byteCount >= 0, "[UnicodeEncoding.GetBytes]byteCount >=0");
@@ -700,17 +699,14 @@ namespace System.Text
if (ch == 0)
{
// No fallback, maybe we can do it fast
-#if !NO_FAST_UNICODE_LOOP
-#if BIGENDIAN // If endianess is backwards then each pair of bytes would be backwards.
- if ( bigEndian &&
-#else
- if (!bigEndian &&
-#endif // BIGENDIAN
-#if BIT64 // 64 bit CPU needs to be long aligned for this to work, 32 bit CPU needs to be 32 bit aligned
- (unchecked((long)chars) & 7) == 0 && (unchecked((long)bytes) & 7) == 0 &&
+#if FASTLOOP
+ // If endianess is backwards then each pair of bytes would be backwards.
+ if ( (bigEndian ^ BitConverter.IsLittleEndian) &&
+#if BIT64
+ (unchecked((long)chars) & 7) == 0 &&
#else
- (unchecked((int)chars) & 3) == 0 && (unchecked((int)bytes) & 3) == 0 &&
-#endif // BIT64
+ (unchecked((int)chars) & 3) == 0 &&
+#endif
charLeftOver == 0)
{
// Need -1 to check 2 at a time. If we have an even #, longChars will go
@@ -752,11 +748,8 @@ namespace System.Text
// If they happen to be high/low/high/low, we may as well continue. Check the next
// bit to see if its set (low) or not (high) in the right pattern
-#if BIGENDIAN
- if (((0xfc00fc00fc00fc00 & *longChars) ^ 0xd800dc00d800dc00) != 0)
-#else
- if (((0xfc00fc00fc00fc00 & *longChars) ^ 0xdc00d800dc00d800) != 0)
-#endif
+ if ((0xfc00fc00fc00fc00 & *longChars) !=
+ (BitConverter.IsLittleEndian ? (ulong)0xdc00d800dc00d800 : (ulong)0xd800dc00d800dc00))
{
// Either there weren't 4 surrogates, or the 0x0400 bit was set when a high
// was hoped for or the 0x0400 bit wasn't set where a low was hoped for.
@@ -771,7 +764,7 @@ namespace System.Text
// else all < 0x8000 so we can use them
// We can use these 4 chars.
- *longBytes = *longChars;
+ Unsafe.WriteUnaligned<ulong>(longBytes, *longChars);
longChars++;
longBytes++;
}
@@ -782,66 +775,7 @@ namespace System.Text
if (chars >= charEnd)
break;
}
- // Not aligned, but maybe we can still be somewhat faster
- // Also somehow this optimizes the above loop? It seems to cause something above
- // to get enregistered, but I haven't figured out how to make that happen without this loop.
- else if ((charLeftOver == 0) &&
-#if BIGENDIAN
- bigEndian &&
-#else
- !bigEndian &&
-#endif // BIGENDIAN
-
-#if BIT64
- (unchecked((long)chars) & 7) != (unchecked((long)bytes) & 7) && // Only do this if chars & bytes are out of line, otherwise faster loop will be faster next time
-#else
- (unchecked((int)chars) & 3) != (unchecked((int)bytes) & 3) && // Only do this if chars & bytes are out of line, otherwise faster loop will be faster next time
-#endif // BIT64
- (unchecked((int)(bytes)) & 1) == 0)
- {
- // # to use
- long iCount = ((byteEnd - bytes) >> 1 < charEnd - chars) ?
- (byteEnd - bytes) >> 1 : charEnd - chars;
-
- // Need new char*
- char* charOut = ((char*)bytes); // a char* for our output
- char* tempEnd = chars + iCount - 1; // Our end pointer
-
- while (chars < tempEnd)
- {
- if (*chars >= (char)0xd800 && *chars <= (char)0xdfff)
- {
- // break for fallback for low surrogate
- if (*chars >= 0xdc00)
- break;
-
- // break if next one's not a low surrogate (will do fallback)
- if (*(chars + 1) < 0xdc00 || *(chars + 1) > 0xdfff)
- break;
-
- // They both exist, use them
- }
- // If 2nd char is surrogate & this one isn't then only add one
- else if (*(chars + 1) >= (char)0xd800 && *(chars + 1) <= 0xdfff)
- {
- *charOut = *chars;
- charOut++;
- chars++;
- continue;
- }
-
- *charOut = *chars;
- *(charOut + 1) = *(chars + 1);
- charOut += 2;
- chars += 2;
- }
-
- bytes = (byte*)charOut;
-
- if (chars >= charEnd)
- break;
- }
-#endif // !NO_FAST_UNICODE_LOOP
+#endif // FASTLOOP
// No fallback, just get next char
ch = *chars;
@@ -1070,13 +1004,10 @@ namespace System.Text
encoder == null || !encoder._throwOnOverflow,
"[UnicodeEncoding.GetBytes]Expected empty fallback buffer if not converting");
- // We used to copy it fast, but this doesn't check for surrogates
- // System.IO.__UnmanagedMemoryStream.memcpyimpl(bytes, (byte*)chars, usedByteCount);
-
return (int)(bytes - byteStart);
}
- internal override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetCharCount(byte* bytes, int count, DecoderNLS baseDecoder)
{
Debug.Assert(bytes != null, "[UnicodeEncoding.GetCharCount]bytes!=null");
Debug.Assert(count >= 0, "[UnicodeEncoding.GetCharCount]count >=0");
@@ -1093,11 +1024,6 @@ namespace System.Text
// Start by assuming same # of chars as bytes
int charCount = count >> 1;
- // Need -1 to check 2 at a time. If we have an even #, longBytes will go
- // from longEnd - 1/2 long to longEnd + 1/2 long. If we're odd, longBytes
- // will go from longEnd - 1 long to longEnd. (Might not get to use this)
- ulong* longEnd = (ulong*)(byteEnd - 7);
-
// For fallback we may need a fallback buffer
DecoderFallbackBuffer fallbackBuffer = null;
@@ -1126,19 +1052,20 @@ namespace System.Text
{
// If we're aligned then maybe we can do it fast
// That'll hurt if we're unaligned because we'll always test but never be aligned
-#if !NO_FAST_UNICODE_LOOP
-#if BIGENDIAN
- if (bigEndian &&
-#else // BIGENDIAN
- if (!bigEndian &&
-#endif // BIGENDIAN
-#if BIT64 // win64 has to be long aligned
+#if FASTLOOP
+ if ((bigEndian ^ BitConverter.IsLittleEndian) &&
+#if BIT64
(unchecked((long)bytes) & 7) == 0 &&
#else
(unchecked((int)bytes) & 3) == 0 &&
#endif // BIT64
lastByte == -1 && lastChar == 0)
{
+ // Need -1 to check 2 at a time. If we have an even #, longBytes will go
+ // from longEnd - 1/2 long to longEnd + 1/2 long. If we're odd, longBytes
+ // will go from longEnd - 1 long to longEnd. (Might not get to use this)
+ ulong* longEnd = (ulong*)(byteEnd - 7);
+
// Need new char* so we can check 4 at a time
ulong* longBytes = (ulong*)bytes;
@@ -1169,11 +1096,8 @@ namespace System.Text
// If they happen to be high/low/high/low, we may as well continue. Check the next
// bit to see if its set (low) or not (high) in the right pattern
-#if BIGENDIAN
- if (((0xfc00fc00fc00fc00 & *longBytes) ^ 0xd800dc00d800dc00) != 0)
-#else
- if (((0xfc00fc00fc00fc00 & *longBytes) ^ 0xdc00d800dc00d800) != 0)
-#endif
+ if ((0xfc00fc00fc00fc00 & *longBytes) !=
+ (BitConverter.IsLittleEndian ? (ulong)0xdc00d800dc00d800 : (ulong)0xd800dc00d800dc00))
{
// Either there weren't 4 surrogates, or the 0x0400 bit was set when a high
// was hoped for or the 0x0400 bit wasn't set where a low was hoped for.
@@ -1196,7 +1120,7 @@ namespace System.Text
if (bytes >= byteEnd)
break;
}
-#endif // !NO_FAST_UNICODE_LOOP
+#endif // FASTLOOP
// Get 1st byte
if (lastByte < 0)
@@ -1410,8 +1334,8 @@ namespace System.Text
return charCount;
}
- internal override unsafe int GetChars(byte* bytes, int byteCount,
- char* chars, int charCount, DecoderNLS baseDecoder)
+ internal sealed override unsafe int GetChars(
+ byte* bytes, int byteCount, char* chars, int charCount, DecoderNLS baseDecoder)
{
Debug.Assert(chars != null, "[UnicodeEncoding.GetChars]chars!=null");
Debug.Assert(byteCount >= 0, "[UnicodeEncoding.GetChars]byteCount >=0");
@@ -1449,17 +1373,13 @@ namespace System.Text
{
// If we're aligned then maybe we can do it fast
// That'll hurt if we're unaligned because we'll always test but never be aligned
-#if !NO_FAST_UNICODE_LOOP
-#if BIGENDIAN
- if (bigEndian &&
-#else // BIGENDIAN
- if (!bigEndian &&
-#endif // BIGENDIAN
-#if BIT64 // win64 has to be long aligned
- (unchecked((long)chars) & 7) == 0 && (unchecked((long)bytes) & 7) == 0 &&
+#if FASTLOOP
+ if ((bigEndian ^ BitConverter.IsLittleEndian) &&
+#if BIT64
+ (unchecked((long)chars) & 7) == 0 &&
#else
- (unchecked((int)chars) & 3) == 0 && (unchecked((int)bytes) & 3) == 0 &&
-#endif // BIT64
+ (unchecked((int)chars) & 3) == 0 &&
+#endif
lastByte == -1 && lastChar == 0)
{
// Need -1 to check 2 at a time. If we have an even #, longChars will go
@@ -1501,11 +1421,8 @@ namespace System.Text
// If they happen to be high/low/high/low, we may as well continue. Check the next
// bit to see if its set (low) or not (high) in the right pattern
-#if BIGENDIAN
- if (((0xfc00fc00fc00fc00 & *longBytes) ^ 0xd800dc00d800dc00) != 0)
-#else
- if (((0xfc00fc00fc00fc00 & *longBytes) ^ 0xdc00d800dc00d800) != 0)
-#endif
+ if ((0xfc00fc00fc00fc00 & *longBytes) !=
+ (BitConverter.IsLittleEndian ? (ulong)0xdc00d800dc00d800 : (ulong)0xd800dc00d800dc00))
{
// Either there weren't 4 surrogates, or the 0x0400 bit was set when a high
// was hoped for or the 0x0400 bit wasn't set where a low was hoped for.
@@ -1520,7 +1437,7 @@ namespace System.Text
// else all < 0x8000 so we can use them
// We can use these 4 chars.
- *longChars = *longBytes;
+ Unsafe.WriteUnaligned<ulong>(longChars, *longBytes);
longBytes++;
longChars++;
}
@@ -1531,7 +1448,7 @@ namespace System.Text
if (bytes >= byteEnd)
break;
}
-#endif // !NO_FAST_UNICODE_LOOP
+#endif // FASTLOOP
// Get 1st byte
if (lastByte < 0)
@@ -1840,9 +1757,6 @@ namespace System.Text
decoder.lastByte = lastByte;
}
- // Used to do this the old way
- // System.IO.__UnmanagedMemoryStream.memcpyimpl((byte*)chars, bytes, byteCount);
-
// Shouldn't have anything in fallback buffer for GetChars
// (don't have to check _throwOnOverflow for count or chars)
Debug.Assert(fallbackBuffer == null || fallbackBuffer.Remaining == 0,
@@ -1875,7 +1789,7 @@ namespace System.Text
else
return new byte[2] { 0xff, 0xfe };
}
- return Array.Empty<Byte>();
+ return Array.Empty<byte>();
}
public override ReadOnlySpan<byte> Preamble =>
@@ -1928,7 +1842,7 @@ namespace System.Text
}
- public override bool Equals(Object value)
+ public override bool Equals(object value)
{
UnicodeEncoding that = value as UnicodeEncoding;
if (that != null)
diff --git a/src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs b/src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs
index 18d564867..74b5dacf9 100644
--- a/src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs
+++ b/src/System.Private.CoreLib/shared/System/Text/ValueStringBuilder.cs
@@ -9,7 +9,7 @@ using System.Runtime.InteropServices;
namespace System.Text
{
- internal ref struct ValueStringBuilder
+ internal ref partial struct ValueStringBuilder
{
private char[] _arrayToReturnToPool;
private Span<char> _chars;
@@ -22,11 +22,19 @@ namespace System.Text
_pos = 0;
}
+ public ValueStringBuilder(int initialCapacity)
+ {
+ _arrayToReturnToPool = ArrayPool<char>.Shared.Rent(initialCapacity);
+ _chars = _arrayToReturnToPool;
+ _pos = 0;
+ }
+
public int Length
{
get => _pos;
set
{
+ Debug.Assert(value >= 0);
Debug.Assert(value <= _chars.Length);
_pos = value;
}
@@ -40,7 +48,30 @@ namespace System.Text
Grow(capacity - _chars.Length);
}
- public ref char GetPinnableReference() => ref MemoryMarshal.GetReference(_chars);
+ /// <summary>
+ /// Get a pinnable reference to the builder.
+ /// Does not ensure there is a null char after <see cref="Length"/>
+ /// This overload is pattern matched in the C# 7.3+ compiler so you can omit
+ /// the explicit method call, and write eg "fixed (char* c = builder)"
+ /// </summary>
+ public ref char GetPinnableReference()
+ {
+ return ref MemoryMarshal.GetReference(_chars);
+ }
+
+ /// <summary>
+ /// Get a pinnable reference to the builder.
+ /// </summary>
+ /// <param name="terminate">Ensures that the builder has a null char after <see cref="Length"/></param>
+ public ref char GetPinnableReference(bool terminate)
+ {
+ if (terminate)
+ {
+ EnsureCapacity(Length + 1);
+ _chars[Length] = '\0';
+ }
+ return ref MemoryMarshal.GetReference(_chars);
+ }
public ref char this[int index]
{
@@ -53,12 +84,31 @@ namespace System.Text
public override string ToString()
{
- var s = new string(_chars.Slice(0, _pos));
+ var s = _chars.Slice(0, _pos).ToString();
Dispose();
return s;
}
+ /// <summary>Returns the underlying storage of the builder.</summary>
+ public Span<char> RawChars => _chars;
+
+ /// <summary>
+ /// Returns a span around the contents of the builder.
+ /// </summary>
+ /// <param name="terminate">Ensures that the builder has a null char after <see cref="Length"/></param>
+ public ReadOnlySpan<char> AsSpan(bool terminate)
+ {
+ if (terminate)
+ {
+ EnsureCapacity(Length + 1);
+ _chars[Length] = '\0';
+ }
+ return _chars.Slice(0, _pos);
+ }
+
public ReadOnlySpan<char> AsSpan() => _chars.Slice(0, _pos);
+ public ReadOnlySpan<char> AsSpan(int start) => _chars.Slice(start, _pos - start);
+ public ReadOnlySpan<char> AsSpan(int start, int length) => _chars.Slice(start, length);
public bool TryCopyTo(Span<char> destination, out int charsWritten)
{
@@ -93,7 +143,7 @@ namespace System.Text
public void Append(char c)
{
int pos = _pos;
- if (pos < _chars.Length)
+ if ((uint)pos < (uint)_chars.Length)
{
_chars[pos] = c;
_pos = pos + 1;
@@ -108,7 +158,7 @@ namespace System.Text
public void Append(string s)
{
int pos = _pos;
- if (s.Length == 1 && pos < _chars.Length) // very common case, e.g. appending strings from NumberFormatInfo like separators, percent symbols, etc.
+ if (s.Length == 1 && (uint)pos < (uint)_chars.Length) // very common case, e.g. appending strings from NumberFormatInfo like separators, percent symbols, etc.
{
_chars[pos] = s[0];
_pos = pos + 1;