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/UnicodeEncoding.cs')
-rw-r--r--src/System.Private.CoreLib/shared/System/Text/UnicodeEncoding.cs284
1 files changed, 99 insertions, 185 deletions
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)