From c8dc2b229960398832ec1721ed2fb7701e89d3ef Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Tue, 12 Oct 2021 22:27:46 -0400 Subject: [PATCH] Experiment with Roslyn optimization for ROS in assembly data section Rolls it out to most static readonly T[] fields initialized to only const values. This will tank perf until Roslyn optimizes these. --- .../src/System/Drawing/KnownColorTable.cs | 14 +- .../Http/aspnetcore/Http2/Hpack/Huffman.cs | 6 +- .../src/System/Security/IdentityHelper.cs | 32 +- .../src/System/ConsolePal.Unix.cs | 4 +- .../src/System/Data/Filter/Operators.cs | 50 ++- .../src/System/Data/SQLTypes/SQLDateTime.cs | 10 +- .../src/System/Data/SQLTypes/SQLDecimal.cs | 62 ++-- .../src/System/Data/SQLTypes/SQLGuid.cs | 14 +- .../Diagnostics/FileVersionInfo.Windows.cs | 24 +- .../DeflateManaged/InflaterManaged.cs | 10 +- .../src/System/IO/Hashing/Crc32.Table.cs | 307 +++++++++++++++-- .../src/System/IO/Hashing/Crc32.cs | 2 +- .../src/System/IO/Hashing/Crc64.Table.cs | 309 ++++++++++++++++-- .../src/System/IO/Hashing/Crc64.cs | 2 +- .../src/System/Net/Http/WinHttpAuthHelper.cs | 6 +- .../AuthenticationHelper.Digest.cs | 30 +- .../Http/SocketsHttpHandler/Http2Stream.cs | 4 +- .../Net/Http/SocketsHttpHandler/MultiProxy.cs | 11 +- .../src/System/Net/HttpListenerResponse.cs | 14 +- .../src/System/Net/Mail/Attachment.cs | 5 +- .../src/System/Net/Cookie.cs | 16 +- .../Utf8Formatter/Utf8Formatter.Date.L.cs | 4 +- .../Utf8Formatter/Utf8Formatter.Date.R.cs | 4 +- .../Text/Utf8Formatter/Utf8Formatter.Date.cs | 8 +- .../Utf8Parser/Utf8Parser.Date.Helpers.cs | 7 +- .../src/System/Collections/HashHelpers.cs | 4 +- .../src/System/Convert.cs | 22 +- .../src/System/DateTime.Windows.cs | 2 +- .../src/System/DateTime.cs | 28 +- .../src/System/Decimal.DecCalc.cs | 54 +-- .../CalendricalCalculationsHelper.cs | 42 +-- .../src/System/Globalization/DateTimeParse.cs | 30 +- .../EastAsianLunisolarCalendar.cs | 11 +- .../System/Globalization/GregorianCalendar.cs | 10 +- .../Globalization/GregorianCalendarHelper.cs | 10 +- .../src/System/Globalization/HijriCalendar.cs | 8 +- .../Globalization/IcuLocaleData.generator.cs | 24 +- .../src/System/Globalization/IdnMapping.cs | 7 +- .../System/Globalization/JulianCalendar.cs | 14 +- .../System/Globalization/PersianCalendar.cs | 12 +- .../FileSystemEnumerableFactory.cs | 13 +- .../System/IO/Enumeration/FileSystemName.cs | 21 +- .../System.Private.CoreLib/src/System/Math.cs | 4 +- .../src/System/MathF.cs | 4 +- .../src/System/Number.BigInteger.cs | 32 +- .../src/System/Number.Grisu3.cs | 30 +- .../Number.NumberToFloatingPointBits.cs | 14 +- .../src/System/Security/SecurityElement.cs | 45 ++- .../Text/EncoderLatin1BestFitFallback.Data.cs | 2 +- .../Text/EncoderLatin1BestFitFallback.cs | 15 +- .../src/System/Text/EncodingData.cs | 66 ++-- .../src/System/Text/EncodingTable.cs | 42 +-- .../Runtime/Serialization/Json/JsonGlobals.cs | 2 +- .../Json/JsonObjectDataContract.cs | 2 +- .../Runtime/Serialization/ObjectToIdCache.cs | 22 +- .../src/System/Xml/UniqueId.cs | 4 +- .../src/System/DomainNameHelper.cs | 5 +- .../System.Private.Uri/src/System/Uri.cs | 13 +- .../src/System/Xml/Linq/XNodeReader.cs | 19 +- .../src/System/Xml/XPath/XNodeNavigator.cs | 4 +- .../src/System/Xml/Schema/XsdBuilder.cs | 6 +- .../src/System/Xml/Schema/XsdDateTime.cs | 24 +- .../src/System/Xml/XPath/XPathNavigator.cs | 10 +- .../System/Xml/Xsl/Runtime/NumberFormatter.cs | 12 +- .../src/System/Xml/Xsl/XPath/XPathParser.cs | 6 +- .../src/System/Xml/Xsl/XPathConvert.cs | 2 +- .../src/System/Xml/Xsl/Xslt/QilGenerator.cs | 10 +- .../System/Reflection/Metadata/BlobReader.cs | 6 +- .../TypeLoading/General/HashHelpers.cs | 6 +- .../Reflection/TypeLoading/General/Helpers.cs | 8 +- .../Resources/Extensions/TypeNameComparer.cs | 17 +- .../src/System/Numerics/BigNumber.cs | 6 +- .../Cryptography/SHAHashProvider.Browser.cs | 6 +- .../Cryptography/Pal.Unix/X500NameEncoder.cs | 18 +- .../src/Data/Tools/EncodingDataGenerator.cs | 50 +-- .../src/System/Text/EncodingTable.Data.cs | 10 +- .../src/System/Text/EncodingTable.cs | 30 +- .../src/System/Text/ISCIIEncoding.cs | 14 +- .../src/System/Text/ISO2022Encoding.cs | 10 +- .../src/System/Text/Json/JsonHelpers.Date.cs | 6 +- .../src/System/Text/Json/Nodes/JsonObject.cs | 2 +- .../Text/Json/Serialization/ReadStack.cs | 4 +- .../Text/Json/Serialization/WriteStack.cs | 2 +- .../Utf8JsonWriter.WriteValues.Comment.cs | 4 +- .../src/System/Web/Util/UriUtil.cs | 5 +- 85 files changed, 1176 insertions(+), 690 deletions(-) diff --git a/src/libraries/Common/src/System/Drawing/KnownColorTable.cs b/src/libraries/Common/src/System/Drawing/KnownColorTable.cs index 281f246d13ade..a8bc80f06ee1e 100644 --- a/src/libraries/Common/src/System/Drawing/KnownColorTable.cs +++ b/src/libraries/Common/src/System/Drawing/KnownColorTable.cs @@ -12,7 +12,7 @@ internal static class KnownColorTable public const byte KnownColorKindUnknown = 2; // All known color values (in order of definition in the KnownColor enum). - public static readonly uint[] s_colorValueTable = new uint[] + public static ReadOnlySpan ColorValueTable => new uint[] { // "not a known color" 0, @@ -466,11 +466,11 @@ internal static class KnownColorTable internal static Color ArgbToKnownColor(uint argb) { Debug.Assert((argb & Color.ARGBAlphaMask) == Color.ARGBAlphaMask); - Debug.Assert(s_colorValueTable.Length == ColorKindTable.Length); + Debug.Assert(ColorValueTable.Length == ColorKindTable.Length); - for (int index = 1; index < s_colorValueTable.Length; ++index) + for (int index = 1; index < ColorValueTable.Length; ++index) { - if (ColorKindTable[index] == KnownColorKindWeb && s_colorValueTable[index] == argb) + if (ColorKindTable[index] == KnownColorKindWeb && ColorValueTable[index] == argb) { return Color.FromKnownColor((KnownColor)index); } @@ -486,7 +486,7 @@ public static uint KnownColorToArgb(KnownColor color) return ColorKindTable[(int)color] == KnownColorKindSystem ? GetSystemColorArgb(color) - : s_colorValueTable[(int)color]; + : ColorValueTable[(int)color]; } #if FEATURE_WINDOWS_SYSTEM_COLORS @@ -494,14 +494,14 @@ public static uint GetSystemColorArgb(KnownColor color) { Debug.Assert(Color.IsKnownColorSystem(color)); - return ColorTranslator.COLORREFToARGB(Interop.User32.GetSysColor((byte)s_colorValueTable[(int)color])); + return ColorTranslator.COLORREFToARGB(Interop.User32.GetSysColor((byte)ColorValueTable[(int)color])); } #else public static uint GetSystemColorArgb(KnownColor color) { Debug.Assert(Color.IsKnownColorSystem(color)); - return s_colorValueTable[(int)color]; + return ColorValueTable[(int)color]; } #endif } diff --git a/src/libraries/Common/src/System/Net/Http/aspnetcore/Http2/Hpack/Huffman.cs b/src/libraries/Common/src/System/Net/Http/aspnetcore/Http2/Hpack/Huffman.cs index ed20c1fb7bba8..d311dabd514f8 100644 --- a/src/libraries/Common/src/System/Net/Http/aspnetcore/Http2/Hpack/Huffman.cs +++ b/src/libraries/Common/src/System/Net/Http/aspnetcore/Http2/Hpack/Huffman.cs @@ -11,7 +11,7 @@ internal static class Huffman { // HPack static huffman code. see: https://httpwg.org/specs/rfc7541.html#huffman.code // Stored into two tables to optimize its initialization and memory consumption. - private static readonly uint[] s_encodingTableCodes = new uint[257] + private static ReadOnlySpan EncodingTableCodes => new uint[257] { 0b11111111_11000000_00000000_00000000, 0b11111111_11111111_10110000_00000000, @@ -537,7 +537,7 @@ internal static class Huffman public static (uint encoded, int bitLength) Encode(int data) { - return (s_encodingTableCodes[data], EncodingTableBitLengths[data]); + return (EncodingTableCodes[data], EncodingTableBitLengths[data]); } private static ushort[] GenerateDecodingLookupTree() @@ -574,7 +574,7 @@ private static ushort[] GenerateDecodingLookupTree() // it is guaranteed that for this huffman code generated decoding lookup tree MUST consist of exactly 15 lookup tables var decodingTree = new ushort[15 * 256]; - uint[] encodingTableCodes = s_encodingTableCodes; + ReadOnlySpan encodingTableCodes = EncodingTableCodes; ReadOnlySpan encodingTableBitLengths = EncodingTableBitLengths; int allocatedLookupTableIndex = 0; diff --git a/src/libraries/Common/src/System/Security/IdentityHelper.cs b/src/libraries/Common/src/System/Security/IdentityHelper.cs index f7bec51d8deb9..f9037e7bf93cf 100644 --- a/src/libraries/Common/src/System/Security/IdentityHelper.cs +++ b/src/libraries/Common/src/System/Security/IdentityHelper.cs @@ -17,14 +17,6 @@ namespace System.Security /// internal static class IdentityHelper { - private static readonly char[] s_base32Char = - { - 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', - 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', - 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', - 'y', 'z', '0', '1', '2', '3', '4', '5' - }; - /// /// Gives a hash equivalent to what Url.Normalize() gives. /// @@ -97,6 +89,14 @@ internal static string ToBase32StringSuitableForDirName(byte[] buff) // Create l chars using the last 5 bits of each byte. // Consume 3 MSB bits 5 bytes at a time. + ReadOnlySpan base32Char = new char[] + { + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', + 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5' + }; + do { byte b0 = (i < l) ? buff[i++] : (byte)0; @@ -106,18 +106,18 @@ internal static string ToBase32StringSuitableForDirName(byte[] buff) byte b4 = (i < l) ? buff[i++] : (byte)0; // Consume the 5 Least significant bits of each byte - sb.Append(s_base32Char[b0 & 0x1F]); - sb.Append(s_base32Char[b1 & 0x1F]); - sb.Append(s_base32Char[b2 & 0x1F]); - sb.Append(s_base32Char[b3 & 0x1F]); - sb.Append(s_base32Char[b4 & 0x1F]); + sb.Append(base32Char[b0 & 0x1F]); + sb.Append(base32Char[b1 & 0x1F]); + sb.Append(base32Char[b2 & 0x1F]); + sb.Append(base32Char[b3 & 0x1F]); + sb.Append(base32Char[b4 & 0x1F]); // Consume 3 MSB of b0, b1, MSB bits 6, 7 of b3, b4 - sb.Append(s_base32Char[( + sb.Append(base32Char[( ((b0 & 0xE0) >> 5) | ((b3 & 0x60) >> 2))]); - sb.Append(s_base32Char[( + sb.Append(base32Char[( ((b1 & 0xE0) >> 5) | ((b4 & 0x60) >> 2))]); @@ -132,7 +132,7 @@ internal static string ToBase32StringSuitableForDirName(byte[] buff) if ((b4 & 0x80) != 0) b2 |= 0x10; - sb.Append(s_base32Char[b2]); + sb.Append(base32Char[b2]); } while (i < l); diff --git a/src/libraries/System.Console/src/System/ConsolePal.Unix.cs b/src/libraries/System.Console/src/System/ConsolePal.Unix.cs index 34d4461345a92..49e2d4cd85f5d 100644 --- a/src/libraries/System.Console/src/System/ConsolePal.Unix.cs +++ b/src/libraries/System.Console/src/System/ConsolePal.Unix.cs @@ -796,7 +796,7 @@ private static void WriteSetColorString(bool foreground, ConsoleColor color) int maxColors = TerminalFormatStrings.Instance.MaxColors; // often 8 or 16; 0 is invalid if (maxColors > 0) { - int ansiCode = _consoleColorToAnsiCode[ccValue] % maxColors; + int ansiCode = ConsoleColorToAnsiCode[ccValue] % maxColors; evaluatedString = TermInfo.ParameterizedStrings.Evaluate(formatString, ansiCode); WriteStdoutAnsiString(evaluatedString); @@ -860,7 +860,7 @@ private static bool EmitAnsiColorCodes /// corresponding ANSI values. We need to do the mapping manually. /// See http://en.wikipedia.org/wiki/ANSI_escape_code#Colors /// - private static readonly int[] _consoleColorToAnsiCode = new int[] + private static ReadOnlySpan ConsoleColorToAnsiCode => new byte[] { // Dark/Normal colors 0, // Black, diff --git a/src/libraries/System.Data.Common/src/System/Data/Filter/Operators.cs b/src/libraries/System.Data.Common/src/System/Data/Filter/Operators.cs index ce93f148fbd47..37ae80b356e06 100644 --- a/src/libraries/System.Data.Common/src/System/Data/Filter/Operators.cs +++ b/src/libraries/System.Data.Common/src/System/Data/Filter/Operators.cs @@ -121,34 +121,32 @@ internal static bool IsRelational(int op) /// Mapping from Operator to priorities /// CONSIDER: fast, but hard to maintain /// - - private static readonly int[] s_priority = new int[] { - priStart, // Noop - priNeg, priNeg, priNot, // Unary -, +, Not - priBetweenAnd, priBetweenInLike, priBetweenInLike, - priRelOp, priRelOp, priRelOp, priRelOp, priRelOp, priRelOp, - priIs, - priBetweenInLike, // Like - - priPlusMinus, priPlusMinus, // +, - - priMulDiv, priMulDiv, priIDiv, priMod, // *, /, \, Mod - priExp, // ** - - priAnd, priOr, priXor, priNot, - priAnd, priOr, - - priParen, priProc, priDot, priDot, // Proc, Iff, Qula, Dot.. - - priMax, priMax, priMax, priMax, priMax, priMax, priMax, - priMax, priMax, priMax, priMax, - priMax, - }; - internal static int Priority(int op) { - if (op > s_priority.Length) - return priMax; - return s_priority[op]; + ReadOnlySpan priority = new int[] + { + priStart, // Noop + priNeg, priNeg, priNot, // Unary -, +, Not + priBetweenAnd, priBetweenInLike, priBetweenInLike, + priRelOp, priRelOp, priRelOp, priRelOp, priRelOp, priRelOp, + priIs, + priBetweenInLike, // Like + + priPlusMinus, priPlusMinus, // +, - + priMulDiv, priMulDiv, priIDiv, priMod, // *, /, \, Mod + priExp, // ** + + priAnd, priOr, priXor, priNot, + priAnd, priOr, + + priParen, priProc, priDot, priDot, // Proc, Iff, Qula, Dot.. + + priMax, priMax, priMax, priMax, priMax, priMax, priMax, + priMax, priMax, priMax, priMax, + priMax, + }; + + return (uint)op < priority.Length ? priority[op] : priMax; } /// diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs index 195ca26628ea4..1d02781a8c355 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDateTime.cs @@ -51,12 +51,6 @@ public struct SqlDateTime : INullable, IComparable, IXmlSerializable private const int s_dayBase = 693595; // Jan 1 1900 is this many days from Jan 1 0001 - - private static readonly int[] s_daysToMonth365 = new int[] { - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; - private static readonly int[] s_daysToMonth366 = new int[] { - 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}; - private static readonly DateTime s_minDateTime = new DateTime(1753, 1, 1); private static readonly DateTime s_maxDateTime = DateTime.MaxValue; private static readonly TimeSpan s_minTimeSpan = s_minDateTime.Subtract(s_SQLBaseDate); @@ -105,7 +99,9 @@ public SqlDateTime(int year, int month, int day, int hour, int minute, int secon { if (year >= s_minYear && year <= s_maxYear && month >= 1 && month <= 12) { - int[] days = IsLeapYear(year) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = IsLeapYear(year) ? + (ReadOnlySpan)new int[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } : + (ReadOnlySpan)new int[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; if (day >= 1 && day <= days[month] - days[month - 1]) { int y = year - 1; diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs index 64e7815e2945c..f07893db3142f 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLDecimal.cs @@ -71,7 +71,7 @@ public struct SqlDecimal : INullable, IComparable, IXmlSerializable private const byte s_cNumeDivScaleMin = 6; // Minimum result scale of numeric division // Array of multipliers for lAdjust and Ceiling/Floor. - private static readonly uint[] s_rgulShiftBase = new uint[9] { + private static ReadOnlySpan RgulShiftBase => new uint[9] { 10, 10 * 10, 10 * 10 * 10, @@ -130,7 +130,7 @@ public static void CreateDecimalHelperTable() #endregion #region DecimalHelperTable - private static readonly uint[] s_decimalHelpersLo = { + private static ReadOnlySpan DecimalHelpersLo => new uint[] { 0x0000000a, // precision:2, value:10 0x00000064, // precision:3, value:100 0x000003e8, // precision:4, value:1000 @@ -171,7 +171,7 @@ public static void CreateDecimalHelperTable() 0x00000000, // precision:38+1, value:99999999999999999999999999999999999999+1 }; - private static readonly uint[] s_decimalHelpersMid = { + private static ReadOnlySpan DecimalHelpersMid => new uint[] { 0x00000000, // precision:2, value:10 0x00000000, // precision:3, value:100 0x00000000, // precision:4, value:1000 @@ -212,7 +212,7 @@ public static void CreateDecimalHelperTable() 0x098a2240, // precision:38+1, value:99999999999999999999999999999999999999+1 }; - private static readonly uint[] s_decimalHelpersHi = { + private static ReadOnlySpan DecimalHelpersHi => new uint[] { 0x00000000, // precision:2, value:10 0x00000000, // precision:3, value:100 0x00000000, // precision:4, value:1000 @@ -253,7 +253,7 @@ public static void CreateDecimalHelperTable() 0x5a86c47a, // precision:38+1, value:99999999999999999999999999999999999999+1 }; - private static readonly uint[] s_decimalHelpersHiHi = { + private static ReadOnlySpan DecimalHelpersHiHi => new uint[] { 0x00000000, // precision:2, value:10 0x00000000, // precision:3, value:100 0x00000000, // precision:4, value:1000 @@ -313,31 +313,31 @@ private byte CalculatePrecision() { int tableIndex; byte precision; - uint[] decimalHelpers; + ReadOnlySpan decimalHelpers; uint decimalPart; if (_data4 != 0) { tableIndex = HelperTableStartIndexHiHi; - decimalHelpers = s_decimalHelpersHiHi; + decimalHelpers = DecimalHelpersHiHi; decimalPart = _data4; } else if (_data3 != 0) { tableIndex = HelperTableStartIndexHi; - decimalHelpers = s_decimalHelpersHi; + decimalHelpers = DecimalHelpersHi; decimalPart = _data3; } else if (_data2 != 0) { tableIndex = HelperTableStartIndexMid; - decimalHelpers = s_decimalHelpersMid; + decimalHelpers = DecimalHelpersMid; decimalPart = _data2; } else { tableIndex = HelperTableStartIndexLo; - decimalHelpers = s_decimalHelpersLo; + decimalHelpers = DecimalHelpersLo; decimalPart = _data1; } @@ -429,25 +429,25 @@ private bool VerifyPrecision(byte precision) Debug.Assert(precision <= MaxPrecision, "Precision > MaxPrecision"); int tableIndex = checked((precision - 1)); - if (_data4 < s_decimalHelpersHiHi[tableIndex]) + if (_data4 < DecimalHelpersHiHi[tableIndex]) { return true; } - else if (_data4 == s_decimalHelpersHiHi[tableIndex]) + else if (_data4 == DecimalHelpersHiHi[tableIndex]) { - if (_data3 < s_decimalHelpersHi[tableIndex]) + if (_data3 < DecimalHelpersHi[tableIndex]) { return true; } - else if (_data3 == s_decimalHelpersHi[tableIndex]) + else if (_data3 == DecimalHelpersHi[tableIndex]) { - if (_data2 < s_decimalHelpersMid[tableIndex]) + if (_data2 < DecimalHelpersMid[tableIndex]) { return true; } - else if (_data2 == s_decimalHelpersMid[tableIndex]) + else if (_data2 == DecimalHelpersMid[tableIndex]) { - if (_data1 < s_decimalHelpersLo[tableIndex]) + if (_data1 < DecimalHelpersLo[tableIndex]) { return true; } @@ -757,9 +757,9 @@ public SqlDecimal(double dVal) : this(false) { ulLenDelta = (ulLen >= 9) ? 9 : ulLen; - dFrac *= s_rgulShiftBase[(int)ulLenDelta - 1]; + dFrac *= RgulShiftBase[(int)ulLenDelta - 1]; ulLen -= ulLenDelta; - MultByULong(s_rgulShiftBase[(int)ulLenDelta - 1]); + MultByULong(RgulShiftBase[(int)ulLenDelta - 1]); AddULong((uint)dFrac); dFrac -= Math.Floor(dFrac); } @@ -1522,12 +1522,12 @@ public static explicit operator decimal(SqlDecimal x) { if (lScaleAdjust <= -9) { - ulShiftBase = s_rgulShiftBase[8]; + ulShiftBase = RgulShiftBase[8]; lScaleAdjust += 9; } else { - ulShiftBase = s_rgulShiftBase[-lScaleAdjust - 1]; + ulShiftBase = RgulShiftBase[-lScaleAdjust - 1]; lScaleAdjust = 0; } MpDiv1(rgulRes, ref culRes, ulShiftBase, out ulRem); @@ -2287,12 +2287,12 @@ internal void AdjustScale(int digits, bool fRound) //if lAdjust>=9, downshift by 10^9 each time, otherwise by the full amount if (lAdjust >= 9) { - ulShiftBase = s_rgulShiftBase[8]; + ulShiftBase = RgulShiftBase[8]; lAdjust -= 9; } else { - ulShiftBase = s_rgulShiftBase[lAdjust - 1]; + ulShiftBase = RgulShiftBase[lAdjust - 1]; lAdjust = 0; } MultByULong(ulShiftBase); @@ -2304,12 +2304,12 @@ internal void AdjustScale(int digits, bool fRound) { if (lAdjust <= -9) { - ulShiftBase = s_rgulShiftBase[8]; + ulShiftBase = RgulShiftBase[8]; lAdjust += 9; } else { - ulShiftBase = s_rgulShiftBase[-lAdjust - 1]; + ulShiftBase = RgulShiftBase[-lAdjust - 1]; lAdjust = 0; } ulRem = DivByULong(ulShiftBase); @@ -3035,12 +3035,12 @@ private void MakeInteger(out bool fFraction) { if (iAdjust >= 9) { - ulRem = DivByULong(s_rgulShiftBase[8]); + ulRem = DivByULong(RgulShiftBase[8]); iAdjust -= 9; } else { - ulRem = DivByULong(s_rgulShiftBase[iAdjust - 1]); + ulRem = DivByULong(RgulShiftBase[iAdjust - 1]); iAdjust = 0; } @@ -3173,14 +3173,14 @@ private static SqlDecimal Round(SqlDecimal n, int lPosition, bool fTruncate) { if (lAdjust >= 9) { - ulRem = n.DivByULong(s_rgulShiftBase[8]); - ulLastDivBase = s_rgulShiftBase[8]; + ulRem = n.DivByULong(RgulShiftBase[8]); + ulLastDivBase = RgulShiftBase[8]; lAdjust -= 9; } else { - ulRem = n.DivByULong(s_rgulShiftBase[lAdjust - 1]); - ulLastDivBase = s_rgulShiftBase[lAdjust - 1]; + ulRem = n.DivByULong(RgulShiftBase[lAdjust - 1]); + ulLastDivBase = RgulShiftBase[lAdjust - 1]; lAdjust = 0; } } diff --git a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLGuid.cs b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLGuid.cs index 8e3c58dff3dad..c6023613c05a3 100644 --- a/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLGuid.cs +++ b/src/libraries/System.Data.Common/src/System/Data/SQLTypes/SQLGuid.cs @@ -20,10 +20,6 @@ public struct SqlGuid : INullable, IComparable, IXmlSerializable { private const int SizeOfGuid = 16; - // Comparison orders. - private static readonly int[] s_rgiGuidOrder = new int[16] - {10, 11, 12, 13, 14, 15, 8, 9, 6, 7, 4, 5, 0, 1, 2, 3}; - // NOTE: If any instance fields change, update SqlTypeWorkarounds type in System.Data.SqlClient. private byte[]? m_value; // the SqlGuid is null if m_value is null @@ -125,16 +121,22 @@ public static SqlGuid Parse(string s) // Comparison operators private static EComparison Compare(SqlGuid x, SqlGuid y) { + // Comparison orders. + ReadOnlySpan rgiGuidOrder = new int[16] { 10, 11, 12, 13, 14, 15, 8, 9, 6, 7, 4, 5, 0, 1, 2, 3 }; + //Swap to the correct order to be compared for (int i = 0; i < SizeOfGuid; i++) { byte b1, b2; - b1 = x.m_value![s_rgiGuidOrder[i]]; - b2 = y.m_value![s_rgiGuidOrder[i]]; + b1 = x.m_value![rgiGuidOrder[i]]; + b2 = y.m_value![rgiGuidOrder[i]]; if (b1 != b2) + { return (b1 < b2) ? EComparison.LT : EComparison.GT; + } } + return EComparison.EQ; } diff --git a/src/libraries/System.Diagnostics.FileVersionInfo/src/System/Diagnostics/FileVersionInfo.Windows.cs b/src/libraries/System.Diagnostics.FileVersionInfo/src/System/Diagnostics/FileVersionInfo.Windows.cs index ce77b52cc6785..3dfc535684840 100644 --- a/src/libraries/System.Diagnostics.FileVersionInfo/src/System/Diagnostics/FileVersionInfo.Windows.cs +++ b/src/libraries/System.Diagnostics.FileVersionInfo/src/System/Diagnostics/FileVersionInfo.Windows.cs @@ -32,11 +32,22 @@ private unsafe FileVersionInfo(string fileName) uint langid = GetVarEntry(memIntPtr); if (!GetVersionInfoForCodePage(memIntPtr, ConvertTo8DigitHex(langid))) { + // Some dlls might not contain correct codepage information, + // in which case the lookup will fail. Explorer will take + // a few shots in dark. We'll simulate similar behavior by + // falling back to the following lang-codepages: + ReadOnlySpan fallbackLanguageCodePages = new uint[] + { + 0x040904B0, // US English + CP_UNICODE + 0x040904E4, // US English + CP_USASCII + 0x04090000 // US English + unknown codepage + }; + // Some DLLs might not contain correct codepage information. In these cases we will fail during lookup. // Explorer will take a few shots in dark by trying several specific lang-codepages // (Explorer also randomly guesses 041D04B0=Swedish+CP_UNICODE and 040704B0=German+CP_UNICODE sometimes). // We will try to simulate similar behavior here. - foreach (uint id in s_fallbackLanguageCodePages) + foreach (uint id in fallbackLanguageCodePages) { if (id != langid) { @@ -52,17 +63,6 @@ private unsafe FileVersionInfo(string fileName) } } - // Some dlls might not contain correct codepage information, - // in which case the lookup will fail. Explorer will take - // a few shots in dark. We'll simulate similar behavior by - // falling back to the following lang-codepages: - private static readonly uint[] s_fallbackLanguageCodePages = new uint[] - { - 0x040904B0, // US English + CP_UNICODE - 0x040904E4, // US English + CP_USASCII - 0x04090000 // US English + unknown codepage - }; - private static string ConvertTo8DigitHex(uint value) { return value.ToString("X8"); diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs index 1031b5128e624..57042d79abc69 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/DeflateManaged/InflaterManaged.cs @@ -18,7 +18,7 @@ internal sealed class InflaterManaged // The base length for length code 257 - 285. // The formula to get the real length for a length code is lengthBase[code - 257] + (value stored in extraBits) - private static readonly int[] s_lengthBase = + private static ReadOnlySpan LengthBase => new int[] { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 3 @@ -26,7 +26,7 @@ internal sealed class InflaterManaged // The base distance for distance code 0 - 31 // The real distance for a distance code is distanceBasePosition[code] + (value stored in extraBits) - private static readonly int[] s_distanceBasePosition = + private static ReadOnlySpan DistanceBasePosition => new int[] { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, 32769, 49153 @@ -410,11 +410,11 @@ private bool DecodeBlock(out bool end_of_block_code_seen) return false; } - if (_length < 0 || _length >= s_lengthBase.Length) + if (_length < 0 || _length >= LengthBase.Length) { throw new InvalidDataException(SR.GenericInvalidData); } - _length = s_lengthBase[_length] + bits; + _length = LengthBase[_length] + bits; } _state = InflaterState.HaveFullLength; goto case InflaterState.HaveFullLength; @@ -456,7 +456,7 @@ private bool DecodeBlock(out bool end_of_block_code_seen) { return false; } - offset = s_distanceBasePosition[_distanceCode] + bits; + offset = DistanceBasePosition[_distanceCode] + bits; } else { diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.Table.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.Table.cs index 6dc3fd7c51844..8756f053d9656 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.Table.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.Table.cs @@ -9,32 +9,293 @@ public sealed partial class Crc32 : NonCryptographicHashAlgorithm // While this implementation is based on the standard CRC-32 polynomial, // x32 + x26 + x23 + x22 + x16 + x12 + x11 + x10 + x8 + x7 + x5 + x4 + x2 + x1 + x0, // this version uses reflected bit ordering, so 0x04C11DB7 becomes 0xEDB88320 - private static readonly uint[] s_crcLookup = GenerateReflectedTable(0xEDB88320u); - - private static uint[] GenerateReflectedTable(uint reflectedPolynomial) + private static ReadOnlySpan CrcLookup => new uint[] { - uint[] table = new uint[256]; - - for (int i = 0; i < 256; i++) - { - uint val = (uint)i; + 0x0u, + 0x77073096u, + 0xEE0E612Cu, + 0x990951BAu, + 0x76DC419u, + 0x706AF48Fu, + 0xE963A535u, + 0x9E6495A3u, + 0xEDB8832u, + 0x79DCB8A4u, + 0xE0D5E91Eu, + 0x97D2D988u, + 0x9B64C2Bu, + 0x7EB17CBDu, + 0xE7B82D07u, + 0x90BF1D91u, + 0x1DB71064u, + 0x6AB020F2u, + 0xF3B97148u, + 0x84BE41DEu, + 0x1ADAD47Du, + 0x6DDDE4EBu, + 0xF4D4B551u, + 0x83D385C7u, + 0x136C9856u, + 0x646BA8C0u, + 0xFD62F97Au, + 0x8A65C9ECu, + 0x14015C4Fu, + 0x63066CD9u, + 0xFA0F3D63u, + 0x8D080DF5u, + 0x3B6E20C8u, + 0x4C69105Eu, + 0xD56041E4u, + 0xA2677172u, + 0x3C03E4D1u, + 0x4B04D447u, + 0xD20D85FDu, + 0xA50AB56Bu, + 0x35B5A8FAu, + 0x42B2986Cu, + 0xDBBBC9D6u, + 0xACBCF940u, + 0x32D86CE3u, + 0x45DF5C75u, + 0xDCD60DCFu, + 0xABD13D59u, + 0x26D930ACu, + 0x51DE003Au, + 0xC8D75180u, + 0xBFD06116u, + 0x21B4F4B5u, + 0x56B3C423u, + 0xCFBA9599u, + 0xB8BDA50Fu, + 0x2802B89Eu, + 0x5F058808u, + 0xC60CD9B2u, + 0xB10BE924u, + 0x2F6F7C87u, + 0x58684C11u, + 0xC1611DABu, + 0xB6662D3Du, + 0x76DC4190u, + 0x1DB7106u, + 0x98D220BCu, + 0xEFD5102Au, + 0x71B18589u, + 0x6B6B51Fu, + 0x9FBFE4A5u, + 0xE8B8D433u, + 0x7807C9A2u, + 0xF00F934u, + 0x9609A88Eu, + 0xE10E9818u, + 0x7F6A0DBBu, + 0x86D3D2Du, + 0x91646C97u, + 0xE6635C01u, + 0x6B6B51F4u, + 0x1C6C6162u, + 0x856530D8u, + 0xF262004Eu, + 0x6C0695EDu, + 0x1B01A57Bu, + 0x8208F4C1u, + 0xF50FC457u, + 0x65B0D9C6u, + 0x12B7E950u, + 0x8BBEB8EAu, + 0xFCB9887Cu, + 0x62DD1DDFu, + 0x15DA2D49u, + 0x8CD37CF3u, + 0xFBD44C65u, + 0x4DB26158u, + 0x3AB551CEu, + 0xA3BC0074u, + 0xD4BB30E2u, + 0x4ADFA541u, + 0x3DD895D7u, + 0xA4D1C46Du, + 0xD3D6F4FBu, + 0x4369E96Au, + 0x346ED9FCu, + 0xAD678846u, + 0xDA60B8D0u, + 0x44042D73u, + 0x33031DE5u, + 0xAA0A4C5Fu, + 0xDD0D7CC9u, + 0x5005713Cu, + 0x270241AAu, + 0xBE0B1010u, + 0xC90C2086u, + 0x5768B525u, + 0x206F85B3u, + 0xB966D409u, + 0xCE61E49Fu, + 0x5EDEF90Eu, + 0x29D9C998u, + 0xB0D09822u, + 0xC7D7A8B4u, + 0x59B33D17u, + 0x2EB40D81u, + 0xB7BD5C3Bu, + 0xC0BA6CADu, + 0xEDB88320u, + 0x9ABFB3B6u, + 0x3B6E20Cu, + 0x74B1D29Au, + 0xEAD54739u, + 0x9DD277AFu, + 0x4DB2615u, + 0x73DC1683u, + 0xE3630B12u, + 0x94643B84u, + 0xD6D6A3Eu, + 0x7A6A5AA8u, + 0xE40ECF0Bu, + 0x9309FF9Du, + 0xA00AE27u, + 0x7D079EB1u, + 0xF00F9344u, + 0x8708A3D2u, + 0x1E01F268u, + 0x6906C2FEu, + 0xF762575Du, + 0x806567CBu, + 0x196C3671u, + 0x6E6B06E7u, + 0xFED41B76u, + 0x89D32BE0u, + 0x10DA7A5Au, + 0x67DD4ACCu, + 0xF9B9DF6Fu, + 0x8EBEEFF9u, + 0x17B7BE43u, + 0x60B08ED5u, + 0xD6D6A3E8u, + 0xA1D1937Eu, + 0x38D8C2C4u, + 0x4FDFF252u, + 0xD1BB67F1u, + 0xA6BC5767u, + 0x3FB506DDu, + 0x48B2364Bu, + 0xD80D2BDAu, + 0xAF0A1B4Cu, + 0x36034AF6u, + 0x41047A60u, + 0xDF60EFC3u, + 0xA867DF55u, + 0x316E8EEFu, + 0x4669BE79u, + 0xCB61B38Cu, + 0xBC66831Au, + 0x256FD2A0u, + 0x5268E236u, + 0xCC0C7795u, + 0xBB0B4703u, + 0x220216B9u, + 0x5505262Fu, + 0xC5BA3BBEu, + 0xB2BD0B28u, + 0x2BB45A92u, + 0x5CB36A04u, + 0xC2D7FFA7u, + 0xB5D0CF31u, + 0x2CD99E8Bu, + 0x5BDEAE1Du, + 0x9B64C2B0u, + 0xEC63F226u, + 0x756AA39Cu, + 0x26D930Au, + 0x9C0906A9u, + 0xEB0E363Fu, + 0x72076785u, + 0x5005713u, + 0x95BF4A82u, + 0xE2B87A14u, + 0x7BB12BAEu, + 0xCB61B38u, + 0x92D28E9Bu, + 0xE5D5BE0Du, + 0x7CDCEFB7u, + 0xBDBDF21u, + 0x86D3D2D4u, + 0xF1D4E242u, + 0x68DDB3F8u, + 0x1FDA836Eu, + 0x81BE16CDu, + 0xF6B9265Bu, + 0x6FB077E1u, + 0x18B74777u, + 0x88085AE6u, + 0xFF0F6A70u, + 0x66063BCAu, + 0x11010B5Cu, + 0x8F659EFFu, + 0xF862AE69u, + 0x616BFFD3u, + 0x166CCF45u, + 0xA00AE278u, + 0xD70DD2EEu, + 0x4E048354u, + 0x3903B3C2u, + 0xA7672661u, + 0xD06016F7u, + 0x4969474Du, + 0x3E6E77DBu, + 0xAED16A4Au, + 0xD9D65ADCu, + 0x40DF0B66u, + 0x37D83BF0u, + 0xA9BCAE53u, + 0xDEBB9EC5u, + 0x47B2CF7Fu, + 0x30B5FFE9u, + 0xBDBDF21Cu, + 0xCABAC28Au, + 0x53B39330u, + 0x24B4A3A6u, + 0xBAD03605u, + 0xCDD70693u, + 0x54DE5729u, + 0x23D967BFu, + 0xB3667A2Eu, + 0xC4614AB8u, + 0x5D681B02u, + 0x2A6F2B94u, + 0xB40BBE37u, + 0xC30C8EA1u, + 0x5A05DF1Bu, + 0x2D02EF8Du, + }; - for (int j = 0; j < 8; j++) - { - if ((val & 0b0000_0001) == 0) - { - val >>= 1; - } - else - { - val = (val >> 1) ^ reflectedPolynomial; - } - } - table[i] = val; - } + // GenerateReflectedTable(0xEDB88320u); - return table; - } + //private static uint[] GenerateReflectedTable(uint reflectedPolynomial) + //{ + // uint[] table = new uint[256]; + // + // for (int i = 0; i < 256; i++) + // { + // uint val = (uint)i; + // + // for (int j = 0; j < 8; j++) + // { + // if ((val & 0b0000_0001) == 0) + // { + // val >>= 1; + // } + // else + // { + // val = (val >> 1) ^ reflectedPolynomial; + // } + // } + // + // table[i] = val; + // } + // + // return table; + //} } } diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.cs index 4f904ebaa64b0..ce5399974b064 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc32.cs @@ -159,7 +159,7 @@ private static uint Update(uint crc, ReadOnlySpan source) { byte idx = (byte)crc; idx ^= source[i]; - crc = s_crcLookup[idx] ^ (crc >> 8); + crc = CrcLookup[idx] ^ (crc >> 8); } return crc; diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.Table.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.Table.cs index 886589e61a36c..37a5106791f76 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.Table.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.Table.cs @@ -6,32 +6,291 @@ namespace System.IO.Hashing public sealed partial class Crc64 : NonCryptographicHashAlgorithm { // Pre-computed CRC-64 transition table. - private static readonly ulong[] s_crcLookup = GenerateTable(0x42F0E1EBA9EA3693); - - private static ulong[] GenerateTable(ulong polynomial) + private static ReadOnlySpan CrcLookup => new ulong[] { - ulong[] table = new ulong[256]; - - for (int i = 0; i < 256; i++) - { - ulong val = (ulong)i << 56; - - for (int j = 0; j < 8; j++) - { - if ((val & 0x8000_0000_0000_0000) == 0) - { - val <<= 1; - } - else - { - val = (val << 1) ^ polynomial; - } - } - - table[i] = val; - } + 0x0ul, + 0xA9EA3693ul, + 0x53D46D26ul, + 0xFA3E5BB5ul, + 0xE42ECDFul, + 0xA7A8DA4Cul, + 0x5D9681F9ul, + 0xF47CB76Aul, + 0x1C85D9BEul, + 0xB56FEF2Dul, + 0x4F51B498ul, + 0xE6BB820Bul, + 0x12C73561ul, + 0xBB2D03F2ul, + 0x41135847ul, + 0xE8F96ED4ul, + 0x90E185EFul, + 0x390BB37Cul, + 0xC335E8C9ul, + 0x6ADFDE5Aul, + 0x9EA36930ul, + 0x37495FA3ul, + 0xCD770416ul, + 0x649D3285ul, + 0x8C645C51ul, + 0x258E6AC2ul, + 0xDFB03177ul, + 0x765A07E4ul, + 0x8226B08Eul, + 0x2BCC861Dul, + 0xD1F2DDA8ul, + 0x7818EB3Bul, + 0x21C30BDEul, + 0x88293D4Dul, + 0x721766F8ul, + 0xDBFD506Bul, + 0x2F81E701ul, + 0x866BD192ul, + 0x7C558A27ul, + 0xD5BFBCB4ul, + 0x3D46D260ul, + 0x94ACE4F3ul, + 0x6E92BF46ul, + 0xC77889D5ul, + 0x33043EBFul, + 0x9AEE082Cul, + 0x60D05399ul, + 0xC93A650Aul, + 0xB1228E31ul, + 0x18C8B8A2ul, + 0xE2F6E317ul, + 0x4B1CD584ul, + 0xBF6062EEul, + 0x168A547Dul, + 0xECB40FC8ul, + 0x455E395Bul, + 0xADA7578Ful, + 0x44D611Cul, + 0xFE733AA9ul, + 0x57990C3Aul, + 0xA3E5BB50ul, + 0xA0F8DC3ul, + 0xF031D676ul, + 0x59DBE0E5ul, + 0xEA6C212Ful, + 0x438617BCul, + 0xB9B84C09ul, + 0x10527A9Aul, + 0xE42ECDF0ul, + 0x4DC4FB63ul, + 0xB7FAA0D6ul, + 0x1E109645ul, + 0xF6E9F891ul, + 0x5F03CE02ul, + 0xA53D95B7ul, + 0xCD7A324ul, + 0xF8AB144Eul, + 0x514122DDul, + 0xAB7F7968ul, + 0x2954FFBul, + 0x7A8DA4C0ul, + 0xD3679253ul, + 0x2959C9E6ul, + 0x80B3FF75ul, + 0x74CF481Ful, + 0xDD257E8Cul, + 0x271B2539ul, + 0x8EF113AAul, + 0x66087D7Eul, + 0xCFE24BEDul, + 0x35DC1058ul, + 0x9C3626CBul, + 0x684A91A1ul, + 0xC1A0A732ul, + 0x3B9EFC87ul, + 0x9274CA14ul, + 0xCBAF2AF1ul, + 0x62451C62ul, + 0x987B47D7ul, + 0x31917144ul, + 0xC5EDC62Eul, + 0x6C07F0BDul, + 0x9639AB08ul, + 0x3FD39D9Bul, + 0xD72AF34Ful, + 0x7EC0C5DCul, + 0x84FE9E69ul, + 0x2D14A8FAul, + 0xD9681F90ul, + 0x70822903ul, + 0x8ABC72B6ul, + 0x23564425ul, + 0x5B4EAF1Eul, + 0xF2A4998Dul, + 0x89AC238ul, + 0xA170F4ABul, + 0x550C43C1ul, + 0xFCE67552ul, + 0x6D82EE7ul, + 0xAF321874ul, + 0x47CB76A0ul, + 0xEE214033ul, + 0x141F1B86ul, + 0xBDF52D15ul, + 0x49899A7Ful, + 0xE063ACECul, + 0x1A5DF759ul, + 0xB3B7C1CAul, + 0x7D3274CDul, + 0xD4D8425Eul, + 0x2EE619EBul, + 0x870C2F78ul, + 0x73709812ul, + 0xDA9AAE81ul, + 0x20A4F534ul, + 0x894EC3A7ul, + 0x61B7AD73ul, + 0xC85D9BE0ul, + 0x3263C055ul, + 0x9B89F6C6ul, + 0x6FF541ACul, + 0xC61F773Ful, + 0x3C212C8Aul, + 0x95CB1A19ul, + 0xEDD3F122ul, + 0x4439C7B1ul, + 0xBE079C04ul, + 0x17EDAA97ul, + 0xE3911DFDul, + 0x4A7B2B6Eul, + 0xB04570DBul, + 0x19AF4648ul, + 0xF156289Cul, + 0x58BC1E0Ful, + 0xA28245BAul, + 0xB687329ul, + 0xFF14C443ul, + 0x56FEF2D0ul, + 0xACC0A965ul, + 0x52A9FF6ul, + 0x5CF17F13ul, + 0xF51B4980ul, + 0xF251235ul, + 0xA6CF24A6ul, + 0x52B393CCul, + 0xFB59A55Ful, + 0x167FEEAul, + 0xA88DC879ul, + 0x4074A6ADul, + 0xE99E903Eul, + 0x13A0CB8Bul, + 0xBA4AFD18ul, + 0x4E364A72ul, + 0xE7DC7CE1ul, + 0x1DE22754ul, + 0xB40811C7ul, + 0xCC10FAFCul, + 0x65FACC6Ful, + 0x9FC497DAul, + 0x362EA149ul, + 0xC2521623ul, + 0x6BB820B0ul, + 0x91867B05ul, + 0x386C4D96ul, + 0xD0952342ul, + 0x797F15D1ul, + 0x83414E64ul, + 0x2AAB78F7ul, + 0xDED7CF9Dul, + 0x773DF90Eul, + 0x8D03A2BBul, + 0x24E99428ul, + 0x975E55E2ul, + 0x3EB46371ul, + 0xC48A38C4ul, + 0x6D600E57ul, + 0x991CB93Dul, + 0x30F68FAEul, + 0xCAC8D41Bul, + 0x6322E288ul, + 0x8BDB8C5Cul, + 0x2231BACFul, + 0xD80FE17Aul, + 0x71E5D7E9ul, + 0x85996083ul, + 0x2C735610ul, + 0xD64D0DA5ul, + 0x7FA73B36ul, + 0x7BFD00Dul, + 0xAE55E69Eul, + 0x546BBD2Bul, + 0xFD818BB8ul, + 0x9FD3CD2ul, + 0xA0170A41ul, + 0x5A2951F4ul, + 0xF3C36767ul, + 0x1B3A09B3ul, + 0xB2D03F20ul, + 0x48EE6495ul, + 0xE1045206ul, + 0x1578E56Cul, + 0xBC92D3FFul, + 0x46AC884Aul, + 0xEF46BED9ul, + 0xB69D5E3Cul, + 0x1F7768AFul, + 0xE549331Aul, + 0x4CA30589ul, + 0xB8DFB2E3ul, + 0x11358470ul, + 0xEB0BDFC5ul, + 0x42E1E956ul, + 0xAA188782ul, + 0x3F2B111ul, + 0xF9CCEAA4ul, + 0x5026DC37ul, + 0xA45A6B5Dul, + 0xDB05DCEul, + 0xF78E067Bul, + 0x5E6430E8ul, + 0x267CDBD3ul, + 0x8F96ED40ul, + 0x75A8B6F5ul, + 0xDC428066ul, + 0x283E370Cul, + 0x81D4019Ful, + 0x7BEA5A2Aul, + 0xD2006CB9ul, + 0x3AF9026Dul, + 0x931334FEul, + 0x692D6F4Bul, + 0xC0C759D8ul, + 0x34BBEEB2ul, + 0x9D51D821ul, + 0x676F8394ul, + 0xCE85B507ul, + }; - return table; - } + //GenerateTable(0x42F0E1EBA9EA3693); + //private static ulong[] GenerateTable(ulong polynomial) + //{ + // ulong[] table = new ulong[256]; + // + // for (int i = 0; i < 256; i++) + // { + // ulong val = (ulong)i << 56; + // + // for (int j = 0; j < 8; j++) + // { + // if ((val & 0x8000_0000_0000_0000) == 0) + // { + // val <<= 1; + // } + // else + // { + // val = (val << 1) ^ polynomial; + // } + // } + // + // table[i] = val; + // } + // + // return table; + //} } } diff --git a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.cs b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.cs index ca41821825979..209cdead8ca24 100644 --- a/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.cs +++ b/src/libraries/System.IO.Hashing/src/System/IO/Hashing/Crc64.cs @@ -157,7 +157,7 @@ private static ulong Update(ulong crc, ReadOnlySpan source) { ulong idx = (crc >> 56); idx ^= source[i]; - crc = s_crcLookup[idx] ^ (crc << 8); + crc = CrcLookup[(int)idx] ^ (crc << 8); } return crc; diff --git a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpAuthHelper.cs b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpAuthHelper.cs index b0b6d86c67541..461e6efeedc5a 100644 --- a/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpAuthHelper.cs +++ b/src/libraries/System.Net.Http.WinHttpHandler/src/System/Net/Http/WinHttpAuthHelper.cs @@ -35,7 +35,7 @@ internal sealed class WinHttpAuthHelper "Negotiate" }; - private static readonly uint[] s_authSchemePriorityOrder = + private static ReadOnlySpan AuthSchemePriorityOrder => new uint[] { Interop.WinHttp.WINHTTP_AUTH_SCHEME_NEGOTIATE, Interop.WinHttp.WINHTTP_AUTH_SCHEME_NTLM, @@ -248,7 +248,7 @@ public bool GetServerCredentialsFromCache( lock (_credentialCacheLock) { - foreach (uint authScheme in s_authSchemePriorityOrder) + foreach (uint authScheme in AuthSchemePriorityOrder) { cred = _credentialCache.GetCredential(uri, s_authSchemeStringMapping[authScheme]!); if (cred != null) @@ -400,7 +400,7 @@ private static uint ChooseAuthScheme(uint supportedSchemes, Uri? uri, ICredentia Debug.Assert(uri != null); - foreach (uint authScheme in s_authSchemePriorityOrder) + foreach (uint authScheme in AuthSchemePriorityOrder) { if ((supportedSchemes & authScheme) != 0 && credentials.GetCredential(uri, s_authSchemeStringMapping[authScheme]!) != null) { diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.Digest.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.Digest.cs index 234ca135aa9bd..1171e7e7e3fbe 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.Digest.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/AuthenticationHelper.Digest.cs @@ -36,10 +36,6 @@ internal static partial class AuthenticationHelper private const string Response = "response"; private const string Stale = "stale"; - // Define alphanumeric characters for cnonce - // 48='0', 65='A', 97='a' - private static readonly int[] s_alphaNumChooser = new int[] { 48, 65, 97 }; - public static async Task GetDigestTokenForCredential(NetworkCredential credential, HttpRequestMessage request, DigestResponse digestResponse) { StringBuilder sb = StringBuilderCache.Acquire(); @@ -219,7 +215,11 @@ private static string GetRandomAlphaNumericString() // Get a random digit 0-9, a random alphabet in a-z, or a random alphabeta in A-Z int rangeIndex = randomNumbers[i++] % 3; int value = randomNumbers[i++] % (rangeIndex == 0 ? 10 : 26); - sb.Append((char)(s_alphaNumChooser[rangeIndex] + value)); + + // Define alphanumeric characters for cnonce + // 48='0', 65='A', 97='a' + ReadOnlySpan alphaNumChooser = new int[] { 48, 65, 97 }; + sb.Append((char)(alphaNumChooser[rangeIndex] + value)); } return StringBuilderCache.GetStringAndRelease(sb); @@ -422,31 +422,27 @@ private void Parse(string challenge) internal static class StringBuilderExtensions { - // Characters that require escaping in quoted string - private static readonly char[] SpecialCharacters = new[] { '"', '\\' }; - - public static void AppendKeyValue(this StringBuilder sb, string key, string value, bool includeQuotes = true, bool includeComma = true) + public static void AppendKeyValue(this StringBuilder sb, string key, ReadOnlySpan value, bool includeQuotes = true, bool includeComma = true) { sb.Append(key); sb.Append('='); if (includeQuotes) { sb.Append('"'); - int lastSpecialIndex = 0; - int specialIndex; + ReadOnlySpan specialCharacters = new char[2] { '"', '\\' }; // characters that require escaping in quoted string while (true) { - specialIndex = value.IndexOfAny(SpecialCharacters, lastSpecialIndex); - if (specialIndex >= 0) + int index = value.IndexOfAny(specialCharacters); + if (index >= 0) { - sb.Append(value, lastSpecialIndex, specialIndex - lastSpecialIndex); + sb.Append(value.Slice(0, index)); sb.Append('\\'); - sb.Append(value[specialIndex]); - lastSpecialIndex = specialIndex + 1; + sb.Append(value[index]); + value = value.Slice(index + 1); } else { - sb.Append(value, lastSpecialIndex, value.Length - lastSpecialIndex); + sb.Append(value); break; } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs index b9afa990d967f..7d308730d2f98 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Stream.cs @@ -466,7 +466,7 @@ public void OnWindowUpdate(int amount) private const int FirstHPackNormalHeaderId = 15; private const int LastHPackNormalHeaderId = 61; - private static readonly int[] s_hpackStaticStatusCodeTable = new int[LastHPackStatusPseudoHeaderId - FirstHPackStatusPseudoHeaderId + 1] { 200, 204, 206, 304, 400, 404, 500 }; + private static ReadOnlySpan HpackStaticStatusCodeTable => new int[LastHPackStatusPseudoHeaderId - FirstHPackStatusPseudoHeaderId + 1] { 200, 204, 206, 304, 400, 404, 500 }; private static readonly (HeaderDescriptor descriptor, byte[] value)[] s_hpackStaticHeaderTable = new (HeaderDescriptor, byte[])[LastHPackNormalHeaderId - FirstHPackNormalHeaderId + 1] { @@ -530,7 +530,7 @@ void IHttpHeadersHandler.OnStaticIndexedHeader(int index) } else if (index <= LastHPackStatusPseudoHeaderId) { - int statusCode = s_hpackStaticStatusCodeTable[index - FirstHPackStatusPseudoHeaderId]; + int statusCode = HpackStaticStatusCodeTable[index - FirstHPackStatusPseudoHeaderId]; OnStatus(statusCode); } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/MultiProxy.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/MultiProxy.cs index 087d104153b10..553f76d5557c6 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/MultiProxy.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/MultiProxy.cs @@ -11,7 +11,6 @@ namespace System.Net.Http /// internal struct MultiProxy { - private static readonly char[] s_proxyDelimiters = { ';', ' ', '\n', '\r', '\t' }; private readonly FailedProxyCache? _failedProxyCache; private readonly Uri[]? _uris; private readonly string? _proxyConfig; @@ -19,8 +18,6 @@ internal struct MultiProxy private int _currentIndex; private Uri? _currentUri; - public static MultiProxy Empty => new MultiProxy(null, Array.Empty()); - private MultiProxy(FailedProxyCache? failedProxyCache, Uri[] uris) { _failedProxyCache = failedProxyCache; @@ -41,6 +38,10 @@ private MultiProxy(FailedProxyCache failedProxyCache, string proxyConfig, bool s _currentUri = null; } + public static MultiProxy Empty => new MultiProxy(null, Array.Empty()); + + private static ReadOnlySpan ProxyDelimiters => new char[] { ';', ' ', '\n', '\r', '\t' }; + /// /// Parses a WinHTTP proxy config into a MultiProxy instance. /// @@ -206,7 +207,7 @@ private static bool TryParseProxyConfigPart(ReadOnlySpan proxyString, bool { // Skip any delimiters. int iter = 0; - while (iter < proxyString.Length && Array.IndexOf(s_proxyDelimiters, proxyString[iter]) >= 0) + while (iter < proxyString.Length && ProxyDelimiters.Contains(proxyString[iter])) { ++iter; } @@ -245,7 +246,7 @@ private static bool TryParseProxyConfigPart(ReadOnlySpan proxyString, bool } // Find the next delimiter, or end of string. - iter = proxyString.IndexOfAny(s_proxyDelimiters); + iter = proxyString.IndexOfAny(ProxyDelimiters); if (iter < 0) { iter = proxyString.Length; diff --git a/src/libraries/System.Net.HttpListener/src/System/Net/HttpListenerResponse.cs b/src/libraries/System.Net.HttpListener/src/System/Net/HttpListenerResponse.cs index 6b7ddc839b303..12609c2d39860 100644 --- a/src/libraries/System.Net.HttpListener/src/System/Net/HttpListenerResponse.cs +++ b/src/libraries/System.Net.HttpListener/src/System/Net/HttpListenerResponse.cs @@ -78,19 +78,13 @@ public bool SendChunked set => EntitySendFormat = value ? EntitySendFormat.Chunked : EntitySendFormat.ContentLength; } - // We MUST NOT send message-body when we send responses with these Status codes - private static readonly int[] s_noResponseBody = { 100, 101, 204, 205, 304 }; + private static bool CanSendResponseBody(int responseCode) { - for (int i = 0; i < s_noResponseBody.Length; i++) - { - if (responseCode == s_noResponseBody[i]) - { - return false; - } - } - return true; + // We MUST NOT send message-body when we send responses with these Status codes + ReadOnlySpan noResponseBody = new int[] { 100, 101, 204, 205, 304 }; + return !noResponseBody.Contains(responseCode); } public long ContentLength64 diff --git a/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs b/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs index 5a275b5e002dd..db4ca08b2c9d3 100644 --- a/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs +++ b/src/libraries/System.Net.Mail/src/System/Net/Mail/Attachment.cs @@ -12,7 +12,6 @@ public abstract class AttachmentBase : IDisposable { internal bool disposed; private readonly MimePart _part = new MimePart(); - private static readonly char[] s_contentCIDInvalidChars = new char[] { '<', '>' }; internal AttachmentBase() { @@ -251,7 +250,9 @@ public string ContentId } else { - if (value.IndexOfAny(s_contentCIDInvalidChars) != -1) + ReadOnlySpan ContentCIDInvalidChars = new char[] { '<', '>' }; + + if (value.AsSpan().IndexOfAny(ContentCIDInvalidChars) != -1) { throw new ArgumentException(SR.MailHeaderInvalidCID, nameof(value)); } diff --git a/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs b/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs index 8ed63ef9f97b3..337bd717c8447 100644 --- a/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs +++ b/src/libraries/System.Net.Primitives/src/System/Net/Cookie.cs @@ -41,8 +41,8 @@ public sealed class Cookie internal static readonly char[] PortSplitDelimiters = new char[] { ' ', ',', '\"' }; // Space (' ') should be reserved as well per RFCs, but major web browsers support it and some web sites use it - so we support it too - internal static readonly char[] ReservedToName = new char[] { '\t', '\r', '\n', '=', ';', ',' }; - internal static readonly char[] ReservedToValue = new char[] { ';', ',' }; + internal static ReadOnlySpan ReservedToName => new char[] { '\t', '\r', '\n', '=', ';', ',' }; + internal static ReadOnlySpan ReservedToValue => new char[] { ';', ',' }; private string m_comment = string.Empty; // Do not rename (binary serialization) private Uri? m_commentUri; // Do not rename (binary serialization) @@ -235,7 +235,7 @@ public string Name } internal bool InternalSetName(string? value) { - if (string.IsNullOrEmpty(value) || value[0] == '$' || value.IndexOfAny(ReservedToName) != -1 || value[0] == ' ' || value[value.Length - 1] == ' ') + if (string.IsNullOrEmpty(value) || value[0] == '$' || value.AsSpan().IndexOfAny(ReservedToName) != -1 || value[0] == ' ' || value[value.Length - 1] == ' ') { m_name = string.Empty; return false; @@ -339,7 +339,7 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma } // Check the name - if (string.IsNullOrEmpty(m_name) || m_name[0] == '$' || m_name.IndexOfAny(ReservedToName) != -1 || m_name[0] == ' ' || m_name[m_name.Length - 1] == ' ') + if (string.IsNullOrEmpty(m_name) || m_name[0] == '$' || m_name.AsSpan().IndexOfAny(ReservedToName) != -1 || m_name[0] == ' ' || m_name[m_name.Length - 1] == ' ') { if (shouldThrow) { @@ -350,7 +350,7 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma // Check the value if (m_value == null || - (!(m_value.Length > 2 && m_value[0] == '\"' && m_value[m_value.Length - 1] == '\"') && m_value.IndexOfAny(ReservedToValue) != -1)) + (!(m_value.Length > 2 && m_value[0] == '\"' && m_value[m_value.Length - 1] == '\"') && m_value.AsSpan().IndexOfAny(ReservedToValue) != -1)) { if (shouldThrow) { @@ -361,7 +361,7 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma // Check Comment syntax if (Comment != null && !(Comment.Length > 2 && Comment[0] == '\"' && Comment[Comment.Length - 1] == '\"') - && (Comment.IndexOfAny(ReservedToValue) != -1)) + && (Comment.AsSpan().IndexOfAny(ReservedToValue) != -1)) { if (shouldThrow) { @@ -372,7 +372,7 @@ internal bool VerifySetDefaults(CookieVariant variant, Uri uri, bool isLocalDoma // Check Path syntax if (Path != null && !(Path.Length > 2 && Path[0] == '\"' && Path[Path.Length - 1] == '\"') - && (Path.IndexOfAny(ReservedToValue) != -1)) + && (Path.AsSpan().IndexOfAny(ReservedToValue) != -1)) { if (shouldThrow) { @@ -591,7 +591,7 @@ public string Port else { // Parse port list - if (value[0] != '\"' || value[value.Length - 1] != '\"') + if (value[0] != '\"' || value[^1] != '\"') { throw new CookieException(SR.Format(SR.net_cookie_attribute, CookieFields.PortAttributeName, value)); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Formatter/Utf8Formatter.Date.L.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Formatter/Utf8Formatter.Date.L.cs index 0f20a2ab55e7b..4f74b5e6d7965 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Formatter/Utf8Formatter.Date.L.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Formatter/Utf8Formatter.Date.L.cs @@ -24,7 +24,7 @@ private static bool TryFormatDateTimeL(DateTime value, Span destination, o value.GetDate(out int year, out int month, out int day); value.GetTime(out int hour, out int minute, out int second); - uint dayAbbrev = s_dayAbbreviationsLowercase[(int)value.DayOfWeek]; + uint dayAbbrev = DayAbbreviationsLowercase[(int)value.DayOfWeek]; destination[0] = (byte)dayAbbrev; dayAbbrev >>= 8; @@ -37,7 +37,7 @@ private static bool TryFormatDateTimeL(DateTime value, Span destination, o FormattingHelpers.WriteTwoDecimalDigits((uint)day, destination, 5); destination[7] = Utf8Constants.Space; - uint monthAbbrev = s_monthAbbreviationsLowercase[month - 1]; + uint monthAbbrev = MonthAbbreviationsLowercase[month - 1]; destination[8] = (byte)monthAbbrev; monthAbbrev >>= 8; destination[9] = (byte)monthAbbrev; diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Formatter/Utf8Formatter.Date.R.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Formatter/Utf8Formatter.Date.R.cs index 9c9738dbb135b..39ebc23ed5818 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Formatter/Utf8Formatter.Date.R.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Formatter/Utf8Formatter.Date.R.cs @@ -24,7 +24,7 @@ private static bool TryFormatDateTimeR(DateTime value, Span destination, o value.GetDate(out int year, out int month, out int day); value.GetTime(out int hour, out int minute, out int second); - uint dayAbbrev = s_dayAbbreviations[(int)value.DayOfWeek]; + uint dayAbbrev = DayAbbreviations[(int)value.DayOfWeek]; destination[0] = (byte)dayAbbrev; dayAbbrev >>= 8; @@ -37,7 +37,7 @@ private static bool TryFormatDateTimeR(DateTime value, Span destination, o FormattingHelpers.WriteTwoDecimalDigits((uint)day, destination, 5); destination[7] = Utf8Constants.Space; - uint monthAbbrev = s_monthAbbreviations[month - 1]; + uint monthAbbrev = MonthAbbreviations[month - 1]; destination[8] = (byte)monthAbbrev; monthAbbrev >>= 8; destination[9] = (byte)monthAbbrev; diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Formatter/Utf8Formatter.Date.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Formatter/Utf8Formatter.Date.cs index f5c877d63fc77..f3db0b459fca8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Formatter/Utf8Formatter.Date.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Formatter/Utf8Formatter.Date.cs @@ -18,7 +18,7 @@ public static partial class Utf8Formatter // The three-letter abbreviation is packed into a 24-bit unsigned integer // where the least significant byte represents the first letter. - private static readonly uint[] s_dayAbbreviations = new uint[] + private static ReadOnlySpan DayAbbreviations => new uint[] { 'S' + ('u' << 8) + ('n' << 16), 'M' + ('o' << 8) + ('n' << 16), @@ -29,7 +29,7 @@ public static partial class Utf8Formatter 'S' + ('a' << 8) + ('t' << 16), }; - private static readonly uint[] s_dayAbbreviationsLowercase = new uint[] + private static ReadOnlySpan DayAbbreviationsLowercase => new uint[] { 's' + ('u' << 8) + ('n' << 16), 'm' + ('o' << 8) + ('n' << 16), @@ -40,7 +40,7 @@ public static partial class Utf8Formatter 's' + ('a' << 8) + ('t' << 16) }; - private static readonly uint[] s_monthAbbreviations = new uint[] + private static ReadOnlySpan MonthAbbreviations => new uint[] { 'J' + ('a' << 8) + ('n' << 16), 'F' + ('e' << 8) + ('b' << 16), @@ -56,7 +56,7 @@ public static partial class Utf8Formatter 'D' + ('e' << 8) + ('c' << 16), }; - private static readonly uint[] s_monthAbbreviationsLowercase = new uint[] + private static ReadOnlySpan MonthAbbreviationsLowercase => new uint[] { 'j' + ('a' << 8) + ('n' << 16), 'f' + ('e' << 8) + ('b' << 16), diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Parser/Utf8Parser.Date.Helpers.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Parser/Utf8Parser.Date.Helpers.cs index 8dcea70dbf14e..93c811a759bae 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Parser/Utf8Parser.Date.Helpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Utf8Parser/Utf8Parser.Date.Helpers.cs @@ -144,7 +144,9 @@ private static bool TryCreateDateTime(int year, int month, int day, int hour, in Debug.Assert(fraction >= 0 && fraction <= Utf8Constants.MaxDateTimeFraction); // All of our callers to date parse the fraction from fixed 7-digit fields so this value is trusted. - int[] days = DateTime.IsLeapYear(year) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = DateTime.IsLeapYear(year) ? + (ReadOnlySpan)new int[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 } : + (ReadOnlySpan)new int[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; int yearMinusOne = year - 1; int totalDays = (yearMinusOne * 365) + (yearMinusOne / 4) - (yearMinusOne / 100) + (yearMinusOne / 400) + days[month - 1] + day - 1; long ticks = totalDays * TimeSpan.TicksPerDay; @@ -154,8 +156,5 @@ private static bool TryCreateDateTime(int year, int month, int day, int hour, in value = new DateTime(ticks: ticks, kind: kind); return true; } - - private static readonly int[] s_daysToMonth365 = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; - private static readonly int[] s_daysToMonth366 = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/HashHelpers.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/HashHelpers.cs index a70b9bf5c0c89..22b7ac20e23f5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/HashHelpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/HashHelpers.cs @@ -28,7 +28,7 @@ internal static partial class HashHelpers // h1(key) + i*h2(key), 0 <= i < size. h2 and the size must be relatively prime. // We prefer the low computation costs of higher prime numbers over the increased // memory allocation of a fixed prime number i.e. when right sizing a HashSet. - private static readonly int[] s_primes = + private static ReadOnlySpan Primes => new int[] { 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919, 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591, @@ -57,7 +57,7 @@ public static int GetPrime(int min) if (min < 0) throw new ArgumentException(SR.Arg_HTCapacityOverflow); - foreach (int prime in s_primes) + foreach (int prime in Primes) { if (prime >= min) return prime; diff --git a/src/libraries/System.Private.CoreLib/src/System/Convert.cs b/src/libraries/System.Private.CoreLib/src/System/Convert.cs index 94b9160f7253a..b819842d31df6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Convert.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Convert.cs @@ -121,13 +121,13 @@ public static partial class Convert // Need to special case Enum because typecode will be underlying type, e.g. Int32 private static readonly Type EnumType = typeof(Enum); - internal static readonly char[] base64Table = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', - 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', - 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', - 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', '+', '/', '=' }; + internal static ReadOnlySpan Base64Table => new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', + 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', + 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', '+', '/', '=' }; - private const int base64LineBreakPosition = 76; + private const int Base64LineBreakPosition = 76; #if DEBUG static Convert() @@ -2472,14 +2472,14 @@ private static unsafe int ConvertToBase64Array(char* outChars, byte* inData, int // Convert three bytes at a time to base64 notation. This will consume 4 chars. int i; - // get a pointer to the base64Table to avoid unnecessary range checking - fixed (char* base64 = &base64Table[0]) + // get a pointer to the Base64Table to avoid unnecessary range checking + fixed (char* base64 = &Base64Table[0]) { for (i = offset; i < calcLength; i += 3) { if (insertLineBreaks) { - if (charcount == base64LineBreakPosition) + if (charcount == Base64LineBreakPosition) { outChars[j++] = '\r'; outChars[j++] = '\n'; @@ -2497,7 +2497,7 @@ private static unsafe int ConvertToBase64Array(char* outChars, byte* inData, int // Where we left off before i = calcLength; - if (insertLineBreaks && (lengthmod3 != 0) && (charcount == base64LineBreakPosition)) + if (insertLineBreaks && (lengthmod3 != 0) && (charcount == Base64LineBreakPosition)) { outChars[j++] = '\r'; outChars[j++] = '\n'; @@ -2535,7 +2535,7 @@ private static int ToBase64_CalculateAndValidateOutputLength(int inputLength, bo if (insertLineBreaks) { - (uint newLines, uint remainder) = Math.DivRem(outlen, base64LineBreakPosition); + (uint newLines, uint remainder) = Math.DivRem(outlen, Base64LineBreakPosition); if (remainder == 0) { --newLines; diff --git a/src/libraries/System.Private.CoreLib/src/System/DateTime.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/DateTime.Windows.cs index f5de9ed1e9388..7306b6f25a6a0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateTime.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateTime.Windows.cs @@ -109,7 +109,7 @@ private static unsafe ulong ToFileTimeLeapSecondsAware(long ticks) private static DateTime CreateDateTimeFromSystemTime(in Interop.Kernel32.SYSTEMTIME time, ulong hundredNanoSecond) { uint year = time.Year; - uint[] days = IsLeapYear((int)year) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = IsLeapYear((int)year) ? DaysToMonth366 : DaysToMonth365; int month = time.Month - 1; uint n = DaysToYear(year) + days[month] + time.Day - 1; ulong ticks = n * (ulong)TicksPerDay; diff --git a/src/libraries/System.Private.CoreLib/src/System/DateTime.cs b/src/libraries/System.Private.CoreLib/src/System/DateTime.cs index cc400c1ab32b1..eeef33d54a1c2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DateTime.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DateTime.cs @@ -108,10 +108,8 @@ namespace System private const int DatePartMonth = 2; private const int DatePartDay = 3; - private static readonly uint[] s_daysToMonth365 = { - 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; - private static readonly uint[] s_daysToMonth366 = { - 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; + private static ReadOnlySpan DaysToMonth365 => new uint[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; + private static ReadOnlySpan DaysToMonth366 => new uint[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; private static ReadOnlySpan DaysInMonth365 => new byte[] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; private static ReadOnlySpan DaysInMonth366 => new byte[] { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; @@ -465,7 +463,7 @@ public DateTime AddMonths(int months) y += q; m -= q * 12; if (y < 1 || y > 9999) ThrowDateArithmetic(2); - uint[] daysTo = IsLeapYear(y) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan daysTo = IsLeapYear(y) ? DaysToMonth366 : DaysToMonth365; uint daysToMonth = daysTo[m - 1]; int days = (int)(daysTo[m] - daysToMonth); if (d > days) d = days; @@ -530,12 +528,12 @@ public DateTime AddYears(int value) int m = month - 1, d = day - 1; if (IsLeapYear(y)) { - n += s_daysToMonth366[m]; + n += DaysToMonth366[m]; } else { if (d == 28 && m == 1) d--; - n += s_daysToMonth365[m]; + n += DaysToMonth365[m]; } n += (uint)d; return new DateTime(n * (ulong)TicksPerDay + UTicks % TicksPerDay | InternalKind); @@ -585,7 +583,7 @@ private static ulong DateToTicks(int year, int month, int day) ThrowHelper.ThrowArgumentOutOfRange_BadYearMonthDay(); } - uint[] days = IsLeapYear(year) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = IsLeapYear(year) ? DaysToMonth366 : DaysToMonth365; if ((uint)day > days[month] - days[month - 1]) { ThrowHelper.ThrowArgumentOutOfRange_BadYearMonthDay(); @@ -882,16 +880,16 @@ private int GetDatePart(int part) if (part == DatePartDayOfYear) return (int)n + 1; // Leap year calculation looks different from IsLeapYear since y1, y4, // and y100 are relative to year 1, not year 0 - uint[] days = y1 == 3 && (y4 != 24 || y100 == 3) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = y1 == 3 && (y4 != 24 || y100 == 3) ? DaysToMonth366 : DaysToMonth365; // All months have less than 32 days, so n >> 5 is a good conservative // estimate for the month uint m = (n >> 5) + 1; // m = 1-based month number - while (n >= days[m]) m++; + while (n >= days[(int)m]) m++; // If month was requested, return it if (part == DatePartMonth) return (int)m; // Return 1-based day-of-month - return (int)(n - days[m - 1] + 1); + return (int)(n - days[(int)(m - 1)] + 1); } // Exactly the same as GetDatePart, except computing all of @@ -926,15 +924,15 @@ internal void GetDate(out int year, out int month, out int day) // dayOfYear = n + 1; // Leap year calculation looks different from IsLeapYear since y1, y4, // and y100 are relative to year 1, not year 0 - uint[] days = y1 == 3 && (y4 != 24 || y100 == 3) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = y1 == 3 && (y4 != 24 || y100 == 3) ? DaysToMonth366 : DaysToMonth365; // All months have less than 32 days, so n >> 5 is a good conservative // estimate for the month uint m = (n >> 5) + 1; // m = 1-based month number - while (n >= days[m]) m++; + while (n >= days[(int)m]) m++; // compute month and day month = (int)m; - day = (int)(n - days[m - 1] + 1); + day = (int)(n - days[(int)(m - 1)] + 1); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -1478,7 +1476,7 @@ internal static bool TryCreate(int year, int month, int day, int hour, int minut return false; } - uint[] days = IsLeapYear(year) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = IsLeapYear(year) ? DaysToMonth366 : DaysToMonth365; if ((uint)day > days[month] - days[month - 1]) { return false; diff --git a/src/libraries/System.Private.CoreLib/src/System/Decimal.DecCalc.cs b/src/libraries/System.Private.CoreLib/src/System/Decimal.DecCalc.cs index a966b35b83c4a..e09d5fba82d74 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Decimal.DecCalc.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Decimal.DecCalc.cs @@ -105,7 +105,7 @@ private ulong Low64 private const int MaxInt64Scale = 19; // Fast access for 10^n where n is 0-9 - private static readonly uint[] s_powers10 = new uint[] { + private static ReadOnlySpan UInt32Powers10 => new uint[] { 1, 10, 100, @@ -119,7 +119,7 @@ private ulong Low64 }; // Fast access for 10^n where n is 1-19 - private static readonly ulong[] s_ulongPowers10 = new ulong[] { + private static ReadOnlySpan UInt64Powers10 => new ulong[] { 10, 100, 1000, @@ -141,7 +141,7 @@ private ulong Low64 10000000000000000000, }; - private static readonly double[] s_doublePowers10 = new double[] { + private static ReadOnlySpan DoublePowers10 => new double[] { 1, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, @@ -935,7 +935,7 @@ internal static unsafe void DecAddSub(ref DecCalc d1, ref DecCalc d2, bool sign) { if (scale <= MaxInt32Scale) { - low64 = UInt32x32To64((uint)low64, s_powers10[scale]); + low64 = UInt32x32To64((uint)low64, UInt32Powers10[scale]); goto AlignedAdd; } scale -= MaxInt32Scale; @@ -947,7 +947,7 @@ internal static unsafe void DecAddSub(ref DecCalc d1, ref DecCalc d2, bool sign) { power = TenToPowerNine; if (scale < MaxInt32Scale) - power = s_powers10[scale]; + power = UInt32Powers10[scale]; tmpLow = UInt32x32To64((uint)low64, power); tmp64 = UInt32x32To64((uint)(low64 >> 32), power) + (tmpLow >> 32); low64 = (uint)tmpLow + (tmp64 << 32); @@ -963,7 +963,7 @@ internal static unsafe void DecAddSub(ref DecCalc d1, ref DecCalc d2, bool sign) // power = TenToPowerNine; if (scale < MaxInt32Scale) - power = s_powers10[scale]; + power = UInt32Powers10[scale]; tmpLow = UInt32x32To64((uint)low64, power); tmp64 = UInt32x32To64((uint)(low64 >> 32), power) + (tmpLow >> 32); low64 = (uint)tmpLow + (tmp64 << 32); @@ -994,7 +994,7 @@ internal static unsafe void DecAddSub(ref DecCalc d1, ref DecCalc d2, bool sign) { power = TenToPowerNine; if (scale < MaxInt32Scale) - power = s_powers10[scale]; + power = UInt32Powers10[scale]; tmp64 = 0; uint* rgulNum = (uint*)&bufNum; for (uint cur = 0; ;) @@ -1202,7 +1202,7 @@ internal static long VarCyFromDec(ref DecCalc pdecIn) { if (pdecIn.High != 0) goto ThrowOverflow; - uint pwr = s_powers10[-scale]; + uint pwr = UInt32Powers10[-scale]; ulong high = UInt32x32To64(pwr, pdecIn.Mid); if (high > uint.MaxValue) goto ThrowOverflow; @@ -1290,7 +1290,7 @@ private static int VarDecCmpSub(in decimal d1, in decimal d2) // Scaling loop, up to 10^9 at a time. do { - uint power = scale >= MaxInt32Scale ? TenToPowerNine : s_powers10[scale]; + uint power = scale >= MaxInt32Scale ? TenToPowerNine : UInt32Powers10[scale]; ulong tmpLow = UInt32x32To64((uint)low64, power); ulong tmp = UInt32x32To64((uint)(low64 >> 32), power) + (tmpLow >> 32); low64 = (uint)tmpLow + (tmp << 32); @@ -1349,7 +1349,7 @@ internal static unsafe void VarDecMul(ref DecCalc d1, ref DecCalc d2) goto ReturnZero; scale -= DEC_SCALE_MAX + 1; - ulong power = s_ulongPowers10[scale]; + ulong power = UInt64Powers10[scale]; // TODO: https://github.com/dotnet/runtime/issues/5213 tmp = low64 / power; @@ -1566,12 +1566,12 @@ internal static void VarDecFromR4(float input, out DecCalc result) if (power > DEC_SCALE_MAX) power = DEC_SCALE_MAX; - dbl *= s_doublePowers10[power]; + dbl *= DoublePowers10[power]; } else { if (power != -1 || dbl >= 1E7) - dbl /= s_doublePowers10[-power]; + dbl /= DoublePowers10[-power]; else power = 0; // didn't scale it } @@ -1608,7 +1608,7 @@ internal static void VarDecFromR4(float input, out DecCalc result) power = -power; if (power < 10) { - result.Low64 = UInt32x32To64(mant, s_powers10[power]); + result.Low64 = UInt32x32To64(mant, UInt32Powers10[power]); } else { @@ -1616,12 +1616,12 @@ internal static void VarDecFromR4(float input, out DecCalc result) // if (power > 18) { - ulong low64 = UInt32x32To64(mant, s_powers10[power - 18]); + ulong low64 = UInt32x32To64(mant, UInt32Powers10[power - 18]); UInt64x64To128(low64, TenToPowerEighteen, ref result); } else { - ulong low64 = UInt32x32To64(mant, s_powers10[power - 9]); + ulong low64 = UInt32x32To64(mant, UInt32Powers10[power - 9]); ulong hi64 = UInt32x32To64(TenToPowerNine, (uint)(low64 >> 32)); low64 = UInt32x32To64(TenToPowerNine, (uint)low64); result.Low = (uint)low64; @@ -1733,12 +1733,12 @@ internal static void VarDecFromR8(double input, out DecCalc result) if (power > DEC_SCALE_MAX) power = DEC_SCALE_MAX; - dbl *= s_doublePowers10[power]; + dbl *= DoublePowers10[power]; } else { if (power != -1 || dbl >= 1E15) - dbl /= s_doublePowers10[-power]; + dbl /= DoublePowers10[-power]; else power = 0; // didn't scale it } @@ -1775,7 +1775,7 @@ internal static void VarDecFromR8(double input, out DecCalc result) power = -power; if (power < 10) { - uint pow10 = s_powers10[power]; + uint pow10 = UInt32Powers10[power]; ulong low64 = UInt32x32To64((uint)mant, pow10); ulong hi64 = UInt32x32To64((uint)(mant >> 32), pow10); result.Low = (uint)low64; @@ -1789,7 +1789,7 @@ internal static void VarDecFromR8(double input, out DecCalc result) // Have a big power of 10. // Debug.Assert(power <= 14); - UInt64x64To128(mant, s_ulongPowers10[power - 1], ref result); + UInt64x64To128(mant, UInt64Powers10[power - 1], ref result); } } else @@ -1877,7 +1877,7 @@ internal static double VarR8FromDec(in decimal value) const double ds2to64 = 1.8446744073709552e+019; double dbl = ((double)value.Low64 + - (double)value.High * ds2to64) / s_doublePowers10[value.Scale]; + (double)value.High * ds2to64) / DoublePowers10[value.Scale]; if (value.IsNegative) dbl = -dbl; @@ -1975,7 +1975,7 @@ internal static unsafe void VarDecDiv(ref DecCalc d1, ref DecCalc d2) } HaveScale: - power = s_powers10[curScale]; + power = UInt32Powers10[curScale]; scale += curScale; if (IncreaseScale(ref bufQuo, power) != 0) @@ -2057,7 +2057,7 @@ internal static unsafe void VarDecDiv(ref DecCalc d1, ref DecCalc d2) } HaveScale64: - power = s_powers10[curScale]; + power = UInt32Powers10[curScale]; scale += curScale; if (IncreaseScale(ref bufQuo, power) != 0) @@ -2128,7 +2128,7 @@ internal static unsafe void VarDecDiv(ref DecCalc d1, ref DecCalc d2) } HaveScale96: - power = s_powers10[curScale]; + power = UInt32Powers10[curScale]; scale += curScale; if (IncreaseScale(ref bufQuo, power) != 0) @@ -2213,7 +2213,7 @@ internal static void VarDecMod(ref DecCalc d1, ref DecCalc d2) // Divisor scale can always be increased to dividend scale for remainder calculation. do { - uint power = scale >= MaxInt32Scale ? TenToPowerNine : s_powers10[scale]; + uint power = scale >= MaxInt32Scale ? TenToPowerNine : UInt32Powers10[scale]; ulong tmp = UInt32x32To64(d2.Low, power); d2.Low = (uint)tmp; tmp >>= 32; @@ -2239,7 +2239,7 @@ internal static void VarDecMod(ref DecCalc d1, ref DecCalc d2) int iCurScale = SearchScale(ref bufQuo, DEC_SCALE_MAX + scale); if (iCurScale == 0) break; - uint power = iCurScale >= MaxInt32Scale ? TenToPowerNine : s_powers10[iCurScale]; + uint power = iCurScale >= MaxInt32Scale ? TenToPowerNine : UInt32Powers10[iCurScale]; scale += iCurScale; ulong tmp = UInt32x32To64(bufQuo.U0, power); bufQuo.U0 = (uint)tmp; @@ -2300,7 +2300,7 @@ private static unsafe void VarDecModFull(ref DecCalc d1, ref DecCalc d2, int sca uint high = 3; while (scale < 0) { - uint power = scale <= -MaxInt32Scale ? TenToPowerNine : s_powers10[-scale]; + uint power = scale <= -MaxInt32Scale ? TenToPowerNine : UInt32Powers10[-scale]; uint* buf = (uint*)&b; ulong tmp64 = UInt32x32To64(b.Buf24.U0, power); b.Buf24.U0 = (uint)tmp64; @@ -2413,7 +2413,7 @@ internal static void InternalRound(ref DecCalc d, uint scale, MidpointRounding m } { - power = s_powers10[scale]; + power = UInt32Powers10[(int)scale]; // TODO: https://github.com/dotnet/runtime/issues/5213 uint n = d.uhi; if (n == 0) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendricalCalculationsHelper.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendricalCalculationsHelper.cs index 99bc6633ce1a6..b60d23633dfe3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendricalCalculationsHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendricalCalculationsHelper.cs @@ -24,16 +24,16 @@ internal static class CalendricalCalculationsHelper private static readonly long s_startOf1810 = GetNumberOfDays(new DateTime(1810, 1, 1)); private static readonly long s_startOf1900Century = GetNumberOfDays(new DateTime(1900, 1, 1)); - private static readonly double[] s_coefficients1900to1987 = new double[] { -0.00002, 0.000297, 0.025184, -0.181133, 0.553040, -0.861938, 0.677066, -0.212591 }; - private static readonly double[] s_coefficients1800to1899 = new double[] { -0.000009, 0.003844, 0.083563, 0.865736, 4.867575, 15.845535, 31.332267, 38.291999, 28.316289, 11.636204, 2.043794 }; - private static readonly double[] s_coefficients1700to1799 = new double[] { 8.118780842, -0.005092142, 0.003336121, -0.0000266484 }; - private static readonly double[] s_coefficients1620to1699 = new double[] { 196.58333, -4.0675, 0.0219167 }; - private static readonly double[] s_lambdaCoefficients = new double[] { 280.46645, 36000.76983, 0.0003032 }; - private static readonly double[] s_anomalyCoefficients = new double[] { 357.52910, 35999.05030, -0.0001559, -0.00000048 }; - private static readonly double[] s_eccentricityCoefficients = new double[] { 0.016708617, -0.000042037, -0.0000001236 }; - private static readonly double[] s_coefficients = new double[] { Angle(23, 26, 21.448), Angle(0, 0, -46.8150), Angle(0, 0, -0.00059), Angle(0, 0, 0.001813) }; - private static readonly double[] s_coefficientsA = new double[] { 124.90, -1934.134, 0.002063 }; - private static readonly double[] s_coefficientsB = new double[] { 201.11, 72001.5377, 0.00057 }; + private static ReadOnlySpan Coefficients1900to1987 => new double[] { -0.00002, 0.000297, 0.025184, -0.181133, 0.553040, -0.861938, 0.677066, -0.212591 }; + private static ReadOnlySpan Coefficients1800to1899 => new double[] { -0.000009, 0.003844, 0.083563, 0.865736, 4.867575, 15.845535, 31.332267, 38.291999, 28.316289, 11.636204, 2.043794 }; + private static ReadOnlySpan Coefficients1700to1799 => new double[] { 8.118780842, -0.005092142, 0.003336121, -0.0000266484 }; + private static ReadOnlySpan Coefficients1620to1699 => new double[] { 196.58333, -4.0675, 0.0219167 }; + private static ReadOnlySpan LambdaCoefficients => new double[] { 280.46645, 36000.76983, 0.0003032 }; + private static ReadOnlySpan AnomalyCoefficients => new double[] { 357.52910, 35999.05030, -0.0001559, -0.00000048 }; + private static ReadOnlySpan EccentricityCoefficients => new double[] { 0.016708617, -0.000042037, -0.0000001236 }; + private static ReadOnlySpan Coefficients => new double[] { Angle(23, 26, 21.448), Angle(0, 0, -46.8150), Angle(0, 0, -0.00059), Angle(0, 0, 0.001813) }; + private static ReadOnlySpan CoefficientsA => new double[] { 124.90, -1934.134, 0.002063 }; + private static ReadOnlySpan CoefficientsB => new double[] { 201.11, 72001.5377, 0.00057 }; private static double RadiansFromDegrees(double degree) { @@ -61,7 +61,7 @@ public static double Angle(int degrees, int minutes, double seconds) private static double Obliquity(double julianCenturies) { - return PolynomialSum(s_coefficients, julianCenturies); + return PolynomialSum(Coefficients, julianCenturies); } internal static long GetNumberOfDays(DateTime date) @@ -129,7 +129,7 @@ public static double AsDayFraction(double longitude) return longitude / FullCircleOfArc; } - private static double PolynomialSum(double[] coefficients, double indeterminate) + private static double PolynomialSum(ReadOnlySpan coefficients, double indeterminate) { double sum = coefficients[0]; double indeterminateRaised = 1; @@ -168,28 +168,28 @@ private static double EphemerisCorrection1900to1987(int gregorianYear) { Debug.Assert(1900 <= gregorianYear && gregorianYear <= 1987); double centuriesFrom1900 = CenturiesFrom1900(gregorianYear); - return PolynomialSum(s_coefficients1900to1987, centuriesFrom1900); + return PolynomialSum(Coefficients1900to1987, centuriesFrom1900); } private static double EphemerisCorrection1800to1899(int gregorianYear) { Debug.Assert(1800 <= gregorianYear && gregorianYear <= 1899); double centuriesFrom1900 = CenturiesFrom1900(gregorianYear); - return PolynomialSum(s_coefficients1800to1899, centuriesFrom1900); + return PolynomialSum(Coefficients1800to1899, centuriesFrom1900); } private static double EphemerisCorrection1700to1799(int gregorianYear) { Debug.Assert(1700 <= gregorianYear && gregorianYear <= 1799); double yearsSince1700 = gregorianYear - 1700; - return PolynomialSum(s_coefficients1700to1799, yearsSince1700) / SecondsPerDay; + return PolynomialSum(Coefficients1700to1799, yearsSince1700) / SecondsPerDay; } private static double EphemerisCorrection1620to1699(int gregorianYear) { Debug.Assert(1620 <= gregorianYear && gregorianYear <= 1699); double yearsSince1600 = gregorianYear - 1600; - return PolynomialSum(s_coefficients1620to1699, yearsSince1600) / SecondsPerDay; + return PolynomialSum(Coefficients1620to1699, yearsSince1600) / SecondsPerDay; } // ephemeris-correction: correction to account for the slowing down of the rotation of the earth @@ -243,9 +243,9 @@ private static double CopySign(double value, double sign) private static double EquationOfTime(double time) { double julianCenturies = JulianCenturies(time); - double lambda = PolynomialSum(s_lambdaCoefficients, julianCenturies); - double anomaly = PolynomialSum(s_anomalyCoefficients, julianCenturies); - double eccentricity = PolynomialSum(s_eccentricityCoefficients, julianCenturies); + double lambda = PolynomialSum(LambdaCoefficients, julianCenturies); + double anomaly = PolynomialSum(AnomalyCoefficients, julianCenturies); + double eccentricity = PolynomialSum(EccentricityCoefficients, julianCenturies); double epsilon = Obliquity(julianCenturies); double tanHalfEpsilon = TanOfDegree(epsilon / 2); @@ -355,8 +355,8 @@ private static double Aberration(double julianCenturies) private static double Nutation(double julianCenturies) { - double a = PolynomialSum(s_coefficientsA, julianCenturies); - double b = PolynomialSum(s_coefficientsB, julianCenturies); + double a = PolynomialSum(CoefficientsA, julianCenturies); + double b = PolynomialSum(CoefficientsB, julianCenturies); return (-0.004778 * SinOfDegree(a)) - (0.0003667 * SinOfDegree(b)); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeParse.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeParse.cs index b4796fd92e63d..40a6df6b21e72 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeParse.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeParse.cs @@ -5446,9 +5446,7 @@ internal bool MatchSpecifiedWord(string target) => Index + target.Length <= Length && m_info.Compare(Value.Slice(Index, target.Length), target, CompareOptions.IgnoreCase) == 0; - private static readonly char[] WhiteSpaceChecks = new char[] { ' ', '\u00A0' }; - - internal bool MatchSpecifiedWords(string target, bool checkWordBoundary, ref int matchLength) + internal bool MatchSpecifiedWords(ReadOnlySpan target, bool checkWordBoundary, ref int matchLength) { int valueRemaining = Value.Length - Index; matchLength = target.Length; @@ -5456,20 +5454,22 @@ internal bool MatchSpecifiedWords(string target, bool checkWordBoundary, ref int if (matchLength > valueRemaining || m_info.Compare(Value.Slice(Index, matchLength), target, CompareOptions.IgnoreCase) != 0) { // Check word by word - int targetPosition = 0; // Where we are in the target string int thisPosition = Index; // Where we are in this string - int wsIndex = target.IndexOfAny(WhiteSpaceChecks, targetPosition); - if (wsIndex == -1) + ReadOnlySpan whiteSpaceChecks = new char[] { ' ', '\u00A0' }; + int segmentLength = target.IndexOfAny(whiteSpaceChecks); + if (segmentLength < 0) { return false; } + do { - int segmentLength = wsIndex - targetPosition; if (thisPosition >= Value.Length - segmentLength) - { // Subtraction to prevent overflow. + { + // Subtraction to prevent overflow. return false; } + if (segmentLength == 0) { // If segmentLength == 0, it means that we have leading space in the target string. @@ -5483,7 +5483,7 @@ internal bool MatchSpecifiedWords(string target, bool checkWordBoundary, ref int { return false; } - if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan(targetPosition, segmentLength)) != 0) + if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.Slice(0, segmentLength)) != 0) { return false; } @@ -5491,7 +5491,7 @@ internal bool MatchSpecifiedWords(string target, bool checkWordBoundary, ref int thisPosition = thisPosition + segmentLength + 1; } // Advance our target string - targetPosition = wsIndex + 1; + target = target.Slice(segmentLength + 1); // Skip past multiple whitespace while (thisPosition < Value.Length && char.IsWhiteSpace(Value[thisPosition])) @@ -5499,16 +5499,16 @@ internal bool MatchSpecifiedWords(string target, bool checkWordBoundary, ref int thisPosition++; matchLength++; } - } while ((wsIndex = target.IndexOfAny(WhiteSpaceChecks, targetPosition)) >= 0); + } while ((segmentLength = target.IndexOfAny(whiteSpaceChecks)) >= 0); + // now check the last segment; - if (targetPosition < target.Length) + if (!target.IsEmpty) { - int segmentLength = target.Length - targetPosition; - if (thisPosition > Value.Length - segmentLength) + if (thisPosition > Value.Length - target.Length) { return false; } - if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target.AsSpan(targetPosition, segmentLength)) != 0) + if (m_info.CompareOptionIgnoreCase(Value.Slice(thisPosition, segmentLength), target) != 0) { return false; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/EastAsianLunisolarCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/EastAsianLunisolarCalendar.cs index 73322a6570a72..35c2d09c3d4dd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/EastAsianLunisolarCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/EastAsianLunisolarCalendar.cs @@ -11,9 +11,8 @@ public abstract class EastAsianLunisolarCalendar : Calendar private const int nDaysPerMonth = 3; // # of days so far in the solar year - private static readonly int[] s_daysToMonth365 = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; - - private static readonly int[] s_daysToMonth366 = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; + private static ReadOnlySpan DaysToMonth365 => new int[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + private static ReadOnlySpan DaysToMonth366 => new int[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; public override CalendarAlgorithmType AlgorithmType => CalendarAlgorithmType.LunisolarCalendar; @@ -273,7 +272,7 @@ private void GregorianToLunar(int solarYear, int solarMonth, int solarDate, out int jan1Date; // Calculate the day number in the solar year. - int solarDay = isLeapYear ? s_daysToMonth366[solarMonth - 1] : s_daysToMonth365[solarMonth - 1]; + int solarDay = isLeapYear ? DaysToMonth366[solarMonth - 1] : DaysToMonth365[solarMonth - 1]; solarDay += solarDate; // Calculate the day number in the lunar year. @@ -314,7 +313,7 @@ private void GregorianToLunar(int solarYear, int solarMonth, int solarDate, out // part of the lunar year. since this part is always in Jan or Feb, // we don't need to handle Leap Year (LY only affects March // and later). - lunarDay -= s_daysToMonth365[jan1Month - 1]; + lunarDay -= DaysToMonth365[jan1Month - 1]; lunarDay -= (jan1Date - 1); // convert the lunar day into a lunar month/date @@ -362,7 +361,7 @@ private bool LunarToGregorian(int lunarYear, int lunarMonth, int lunarDate, out // calc the solar day of year of 1 Lunar day bool isLeapYear = GregorianIsLeapYear(lunarYear); - int[] days = isLeapYear ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = isLeapYear ? DaysToMonth366 : DaysToMonth365; solarDay = jan1Date; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendar.cs index e883c8e3772ad..5a5efffe4ff12 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendar.cs @@ -22,9 +22,9 @@ public class GregorianCalendar : Calendar private GregorianCalendarTypes _type; - private static readonly int[] DaysToMonth365 = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; + private static ReadOnlySpan DaysToMonth365 => new int[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; - private static readonly int[] DaysToMonth366 = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; + private static ReadOnlySpan DaysToMonth366 => new int[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; private static volatile Calendar? s_defaultInstance; @@ -96,7 +96,7 @@ internal static long GetAbsoluteDate(int year, int month, int day) { if (year >= 1 && year <= MaxYear && month >= 1 && month <= 12) { - int[] days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; + ReadOnlySpan days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; if (day >= 1 && (day <= days[month] - days[month - 1])) { int y = year - 1; @@ -157,7 +157,7 @@ public override DateTime AddMonths(DateTime time, int months) y += (i - 11) / 12; } - int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; + ReadOnlySpan daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; int days = (daysArray[m] - daysArray[m - 1]); if (d > days) @@ -278,7 +278,7 @@ internal override bool IsValidDay(int year, int month, int day, int era) return false; } - int[] days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; + ReadOnlySpan days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; return day <= (days[month] - days[month - 1]); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendarHelper.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendarHelper.cs index b22ac88c185a0..c25083b81f4f6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendarHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendarHelper.cs @@ -53,12 +53,12 @@ internal sealed class GregorianCalendarHelper // internal int MaxYear => m_maxYear; - internal static readonly int[] DaysToMonth365 = + internal static ReadOnlySpan DaysToMonth365 => new int[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; - internal static readonly int[] DaysToMonth366 = + internal static ReadOnlySpan DaysToMonth366 => new int[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; @@ -197,7 +197,7 @@ internal static long GetAbsoluteDate(int year, int month, int day) { if (year >= 1 && year <= 9999 && month >= 1 && month <= 12) { - int[] days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; + ReadOnlySpan days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; if (day >= 1 && (day <= days[month] - days[month - 1])) { int y = year - 1; @@ -271,7 +271,7 @@ public DateTime AddMonths(DateTime time, int months) m = 12 + (i + 1) % 12; y += (i - 11) / 12; } - int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; + ReadOnlySpan daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; int days = (daysArray[m] - daysArray[m - 1]); if (d > days) @@ -338,7 +338,7 @@ public int GetDaysInMonth(int year, int month, int era) { ThrowHelper.ThrowArgumentOutOfRange_Month(month); } - int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365); + ReadOnlySpan days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365); return days[month] - days[month - 1]; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/HijriCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/HijriCalendar.cs index fa1f63490195d..316efb150dec5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/HijriCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/HijriCalendar.cs @@ -48,7 +48,7 @@ public partial class HijriCalendar : Calendar private const int MinAdvancedHijri = -2; private const int MaxAdvancedHijri = 2; - private static readonly int[] s_hijriMonthDays = { 0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325, 355 }; + private static ReadOnlySpan HijriMonthDays => new int[] { 0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325, 355 }; private int _hijriAdvance = int.MinValue; @@ -80,7 +80,7 @@ public HijriCalendar() private long GetAbsoluteDateHijri(int y, int m, int d) { - return (long)(DaysUpToHijriYear(y) + s_hijriMonthDays[m - 1] + d - 1 - HijriAdjustment); + return (long)(DaysUpToHijriYear(y) + HijriMonthDays[m - 1] + d - 1 - HijriAdjustment); } private long DaysUpToHijriYear(int HijriYear) @@ -241,7 +241,7 @@ internal virtual int GetDatePart(long ticks, int part) return (int)numDays; } - while ((hijriMonth <= 12) && (numDays > s_hijriMonthDays[hijriMonth - 1])) + while ((hijriMonth <= 12) && (numDays > HijriMonthDays[hijriMonth - 1])) { hijriMonth++; } @@ -253,7 +253,7 @@ internal virtual int GetDatePart(long ticks, int part) } // Calculate the Hijri Day. - int hijriDay = (int)(numDays - s_hijriMonthDays[hijriMonth - 1]); + int hijriDay = (int)(numDays - HijriMonthDays[hijriMonth - 1]); if (part == DatePartDay) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/IcuLocaleData.generator.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/IcuLocaleData.generator.cs index b6327633cd258..6e91bfa4a9b38 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/IcuLocaleData.generator.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/IcuLocaleData.generator.cs @@ -24,10 +24,10 @@ internal static partial class IcuLocaleData internal const int DoubleCommaSep = 4 << 4; private const int CulturesCount = 864; - // s_nameIndexToNumericData is mapping from index in s_localeNamesIndices to locale data. + // NameIndexToNumericData is mapping from index in s_localeNamesIndices to locale data. // each row in the table will have the following data: // Lcid, Ansi codepage, Oem codepage, MAC codepage, EBCDIC codepage, Geo Id, Digit Substitution | ListSeparator, specific locale index, Console locale index - private static readonly int[] s_nameIndexToNumericData = new int[CulturesCount * NUMERIC_LOCALE_DATA_COUNT_PER_ROW] + private static ReadOnlySpan NameIndexToNumericData => new int[CulturesCount * NUMERIC_LOCALE_DATA_COUNT_PER_ROW] { // Lcid, Ansi CP, Oem CP, MAC CP, EBCDIC CP, Geo Id, digit substitution | ListSeparator, Specific culture index, Console locale index // index - locale name 0x1000 , 0x0 , 0x1 , 0x2 , 0x1f4 , 0x49 , 1 | SemicolonSep , 3 , 240 , // 0 - aa @@ -1342,20 +1342,20 @@ static void GenerateData(string[] cultures, (string lcid, string culture)[] lcid Console.WriteLine("private static ReadOnlySpan LcidToCultureNameIndices => new byte[CulturesCount * NumericLocaleDataBytesPerRow]"); Console.WriteLine("{"); - for (int i = 0; i < s_nameIndexToNumericData.Length; i += NUMERIC_LOCALE_DATA_COUNT_PER_ROW) + for (int i = 0; i < NameIndexToNumericData.Length; i += NUMERIC_LOCALE_DATA_COUNT_PER_ROW) { - uint Lcid = (uint)s_nameIndexToNumericData[i]; - uint AnsiCP = (uint)s_nameIndexToNumericData[i + 1]; - uint OemCP = (uint)s_nameIndexToNumericData[i + 2]; - uint MacCP = (uint)s_nameIndexToNumericData[i + 3]; - uint EBCDIC = (uint)s_nameIndexToNumericData[i + 4]; - uint GeoId = (uint)s_nameIndexToNumericData[i + 5]; - uint DigitList = (uint)s_nameIndexToNumericData[i + 6]; + uint Lcid = (uint)NameIndexToNumericData[i]; + uint AnsiCP = (uint)NameIndexToNumericData[i + 1]; + uint OemCP = (uint)NameIndexToNumericData[i + 2]; + uint MacCP = (uint)NameIndexToNumericData[i + 3]; + uint EBCDIC = (uint)NameIndexToNumericData[i + 4]; + uint GeoId = (uint)NameIndexToNumericData[i + 5]; + uint DigitList = (uint)NameIndexToNumericData[i + 6]; - int index = s_nameIndexToNumericData[i + 7]; + int index = NameIndexToNumericData[i + 7]; Debug.Assert(index == -1 || index < 0xfff); uint SpecificCultureIndex = index == -1 ? 0xfff: (uint)index; - index = s_nameIndexToNumericData[i + 8]; + index = NameIndexToNumericData[i + 8]; Debug.Assert(index == -1 || index < 0xfff); uint ConsoleLocaleIndex = index == -1 ? 0xfff : (uint)index; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/IdnMapping.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/IdnMapping.cs index 81b20d53e55a4..8e54629f0747f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/IdnMapping.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/IdnMapping.cs @@ -184,7 +184,7 @@ private static unsafe string GetStringForOutput(string originalString, char* inp private const int c_damp = 700; // Legal "dot" separators (i.e: . in www.microsoft.com) - private static readonly char[] s_dotSeparators = { '.', '\u3002', '\uFF0E', '\uFF61' }; + private static ReadOnlySpan DotSeparators => new char[] { '.', '\u3002', '\uFF0E', '\uFF61' }; private string GetAsciiInvariant(string unicode, int index, int count) { @@ -322,10 +322,9 @@ private static string PunycodeEncode(string unicode) while (iNextDot < unicode.Length) { // Find end of this segment - iNextDot = unicode.IndexOfAny(s_dotSeparators, iAfterLastDot); + iNextDot = unicode.AsSpan(iAfterLastDot).IndexOfAny(DotSeparators); Debug.Assert(iNextDot <= unicode.Length, "[IdnMapping.punycode_encode]IndexOfAny is broken"); - if (iNextDot < 0) - iNextDot = unicode.Length; + iNextDot = iNextDot < 0 ? unicode.Length : iNextDot + iAfterLastDot; // Only allowed to have empty . section at end (www.microsoft.com.) if (iNextDot == iAfterLastDot) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/JulianCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/JulianCalendar.cs index bd213f17fe1f0..dbc741ea92c8f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/JulianCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/JulianCalendar.cs @@ -31,12 +31,12 @@ public class JulianCalendar : Calendar // Number of days in 4 years private const int JulianDaysPer4Years = JulianDaysPerYear * 4 + 1; - private static readonly int[] s_daysToMonth365 = + private static ReadOnlySpan DaysToMonth365 => new int[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; - private static readonly int[] s_daysToMonth366 = + private static ReadOnlySpan DaysToMonth366 => new int[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; @@ -106,7 +106,7 @@ internal static void CheckDayRange(int year, int month, int day) } bool isLeapYear = (year % 4) == 0; - int[] days = isLeapYear ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = isLeapYear ? DaysToMonth366 : DaysToMonth365; int monthDays = days[month] - days[month - 1]; if (day < 1 || day > monthDays) { @@ -153,7 +153,7 @@ internal static int GetDatePart(long ticks, int part) // Leap year calculation looks different from IsLeapYear since y1, y4, // and y100 are relative to year 1, not year 0 bool leapYear = (y1 == 3); - int[] days = leapYear ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = leapYear ? DaysToMonth366 : DaysToMonth365; // All months have less than 32 days, so n >> 5 is a good conservative // estimate for the month int m = (n >> 5) + 1; @@ -178,7 +178,7 @@ internal static int GetDatePart(long ticks, int part) /// internal static long DateToTicks(int year, int month, int day) { - int[] days = (year % 4 == 0) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = (year % 4 == 0) ? DaysToMonth366 : DaysToMonth365; int y = year - 1; int n = y * 365 + y / 4 + days[month - 1] + day - 1; // Gregorian 1/1/0001 is Julian 1/3/0001. n * TicksPerDay is the ticks in JulianCalendar. @@ -212,7 +212,7 @@ public override DateTime AddMonths(DateTime time, int months) y += (i - 11) / 12; } - int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365; int days = daysArray[m] - daysArray[m - 1]; if (d > days) { @@ -245,7 +245,7 @@ public override int GetDaysInMonth(int year, int month, int era) { CheckYearEraRange(year, era); CheckMonthRange(month); - int[] days = (year % 4 == 0) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = (year % 4 == 0) ? DaysToMonth366 : DaysToMonth365; return days[month] - days[month - 1]; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/PersianCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/PersianCalendar.cs index 8bc39dbadb188..3a0ea7b2f9674 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/PersianCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/PersianCalendar.cs @@ -21,7 +21,7 @@ public class PersianCalendar : Calendar { public static readonly int PersianEra = 1; - private static readonly long s_persianEpoch = new DateTime(622, 3, 22).Ticks / GregorianCalendar.TicksPerDay; + private static readonly long s_persianEpoch = new DateTime(622, 3, 22).Ticks / TicksPerDay; private const int ApproximateHalfYear = 180; private const int DatePartYear = 0; @@ -30,7 +30,7 @@ public class PersianCalendar : Calendar private const int DatePartDay = 3; private const int MonthsPerYear = 12; - private static readonly int[] s_daysToMonth = { 0, 31, 62, 93, 124, 155, 186, 216, 246, 276, 306, 336, 366 }; + private static ReadOnlySpan DaysToMonth => new int[] { 0, 31, 62, 93, 124, 155, 186, 216, 246, 276, 306, 336, 366 }; private const int MaxCalendarYear = 9378; private const int MaxCalendarMonth = 10; @@ -125,7 +125,7 @@ private static int MonthFromOrdinalDay(int ordinalDay) { Debug.Assert(ordinalDay <= 366); int index = 0; - while (ordinalDay > s_daysToMonth[index]) + while (ordinalDay > DaysToMonth[index]) { index++; } @@ -138,7 +138,7 @@ private static int DaysInPreviousMonths(int month) Debug.Assert(1 <= month && month <= 12); // months are one based but for calculations use 0 based --month; - return s_daysToMonth[month]; + return DaysToMonth[month]; } internal int GetDatePart(long ticks, int part) @@ -250,7 +250,7 @@ public override int GetDaysInMonth(int year, int month, int era) return MaxCalendarDay; } - int daysInMonth = s_daysToMonth[month] - s_daysToMonth[month - 1]; + int daysInMonth = DaysToMonth[month] - DaysToMonth[month - 1]; if ((month == MonthsPerYear) && !IsLeapYear(year)) { Debug.Assert(daysInMonth == 30); @@ -265,7 +265,7 @@ public override int GetDaysInYear(int year, int era) CheckYearRange(year, era); if (year == MaxCalendarYear) { - return s_daysToMonth[MaxCalendarMonth - 1] + MaxCalendarDay; + return DaysToMonth[MaxCalendarMonth - 1] + MaxCalendarDay; } return IsLeapYear(year, CurrentEra) ? 366 : 365; diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerableFactory.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerableFactory.cs index 378d037bb0fd2..42be1b4efbde1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerableFactory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerableFactory.cs @@ -13,12 +13,6 @@ namespace System.IO.Enumeration { internal static class FileSystemEnumerableFactory { - // These all have special meaning in DOS name matching. '\' is the escaping character (which conveniently - // is the directory separator and cannot be part of any path segment in Windows). The other three are the - // special case wildcards that we'll convert some * and ? into. They're also valid as filenames on Unix, - // which is not true in Windows and as such we'll escape any that occur on the input string. - private static readonly char[] s_unixEscapeChars = { '\\', '"', '<', '>' }; - /// /// Validates the directory and expression strings to check that they have no invalid characters, any special DOS wildcard characters in Win32 in the expression get replaced with their proper escaped representation, and if the expression string begins with a directory name, the directory name is moved and appended at the end of the directory string. /// @@ -80,7 +74,12 @@ internal static bool NormalizeInputs(ref string directory, ref string expression } else { - if (Path.DirectorySeparatorChar != '\\' && expression.IndexOfAny(s_unixEscapeChars) != -1) + // These all have special meaning in DOS name matching. '\' is the escaping character (which conveniently + // is the directory separator and cannot be part of any path segment in Windows). The other three are the + // special case wildcards that we'll convert some * and ? into. They're also valid as filenames on Unix, + // which is not true in Windows and as such we'll escape any that occur on the input string. + ReadOnlySpan unixEscapeChars = new char[] { '\\', '"', '<', '>' }; + if (Path.DirectorySeparatorChar != '\\' && expression.AsSpan().IndexOfAny(unixEscapeChars) >= 0) { // Backslash isn't the default separator, need to escape (e.g. Unix) expression = expression.Replace("\\", "\\\\"); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemName.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemName.cs index fc3c83e4837b2..490f6a04e798a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemName.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemName.cs @@ -13,18 +13,6 @@ namespace System.IO.Enumeration /// Provides methods for matching file system names. public static class FileSystemName { - // [MS - FSA] 2.1.4.4 Algorithm for Determining if a FileName Is in an Expression - // https://msdn.microsoft.com/en-us/library/ff469270.aspx - private static readonly char[] s_wildcardChars = - { - '\"', '<', '>', '*', '?' - }; - - private static readonly char[] s_simpleWildcardChars = - { - '*', '?' - }; - /// Translates the given Win32 expression. Change '*' and '?' to '<', '>' and '"' to match Win32 behavior. /// The expression to translate. /// A string with the translated Win32 expression. @@ -165,7 +153,14 @@ private static bool MatchPattern(ReadOnlySpan expression, ReadOnlySpan expressionEnd = expression.Slice(1); - if (expressionEnd.IndexOfAny(useExtendedWildcards ? s_wildcardChars : s_simpleWildcardChars) == -1) + + // [MS - FSA] 2.1.4.4 Algorithm for Determining if a FileName Is in an Expression + // https://msdn.microsoft.com/en-us/library/ff469270.aspx + ReadOnlySpan wildcardChars = useExtendedWildcards ? + (ReadOnlySpan)new char[] { '\"', '<', '>', '*', '?' } : + (ReadOnlySpan)new char[] { '*', '?' }; + + if (expressionEnd.IndexOfAny(wildcardChars) == -1) { // Handle the special case of a single starting *, which essentially means "ends with" diff --git a/src/libraries/System.Private.CoreLib/src/System/Math.cs b/src/libraries/System.Private.CoreLib/src/System/Math.cs index bb7fa0d4d3c8b..749e2219788bf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Math.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Math.cs @@ -38,7 +38,7 @@ public static partial class Math private const double doubleRoundLimit = 1e16d; // This table is required for the Round function which can specify the number of digits to round to - private static readonly double[] roundPower10Double = new double[] { + private static ReadOnlySpan RoundPower10Double => new double[] { 1E0, 1E1, 1E2, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8, 1E9, 1E10, 1E11, 1E12, 1E13, 1E14, 1E15 }; @@ -1260,7 +1260,7 @@ public static unsafe double Round(double value, int digits, MidpointRounding mod if (Abs(value) < doubleRoundLimit) { - double power10 = roundPower10Double[digits]; + double power10 = RoundPower10Double[digits]; value *= power10; diff --git a/src/libraries/System.Private.CoreLib/src/System/MathF.cs b/src/libraries/System.Private.CoreLib/src/System/MathF.cs index 9d1b75c8b1617..969426aaf0f18 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MathF.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MathF.cs @@ -31,7 +31,7 @@ public static partial class MathF private const int maxRoundingDigits = 6; // This table is required for the Round function which can specify the number of digits to round to - private static readonly float[] roundPower10Single = new float[] { + private static ReadOnlySpan RoundPower10Single => new float[] { 1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f, 1e6f }; @@ -410,7 +410,7 @@ public static unsafe float Round(float x, int digits, MidpointRounding mode) if (Abs(x) < singleRoundLimit) { - float power10 = roundPower10Single[digits]; + float power10 = RoundPower10Single[digits]; x *= power10; diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs b/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs index 48305c4aaa237..4e114b276b475 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs @@ -33,7 +33,7 @@ internal unsafe ref struct BigInteger private const int BitsPerBlock = sizeof(int) * 8; private const int MaxBlockCount = (MaxBits + (BitsPerBlock - 1)) / BitsPerBlock; - private static readonly uint[] s_Pow10UInt32Table = new uint[] + private static ReadOnlySpan Pow10UInt32Table => new uint[] { 1, // 10^0 10, // 10^1 @@ -48,7 +48,7 @@ internal unsafe ref struct BigInteger 1000000000 // 10^9 }; - private static readonly int[] s_Pow10BigNumTableIndices = new int[] + private static ReadOnlySpan Pow10BigNumTableIndices => new int[] { 0, // 10^8 2, // 10^16 @@ -60,7 +60,7 @@ internal unsafe ref struct BigInteger 116, // 10^1024 }; - private static readonly uint[] s_Pow10BigNumTable = new uint[] + private static ReadOnlySpan Pow10BigNumTable => new uint[] { // 10^8 1, // _length @@ -821,37 +821,37 @@ public static void Pow2(uint exponent, out BigInteger result) public static void Pow10(uint exponent, out BigInteger result) { - // We leverage two arrays - s_Pow10UInt32Table and s_Pow10BigNumTable to speed up the Pow10 calculation. + // We leverage two arrays - Pow10UInt32Table and Pow10BigNumTable to speed up the Pow10 calculation. // - // s_Pow10UInt32Table stores the results of 10^0 to 10^7. - // s_Pow10BigNumTable stores the results of 10^8, 10^16, 10^32, 10^64, 10^128, 10^256, and 10^512 + // Pow10UInt32Table stores the results of 10^0 to 10^7. + // Pow10BigNumTable stores the results of 10^8, 10^16, 10^32, 10^64, 10^128, 10^256, and 10^512 // // For example, let's say exp = 0b111111. We can split the exp to two parts, one is small exp, // which 10^smallExp can be represented as uint, another part is 10^bigExp, which must be represented as BigNum. // So the result should be 10^smallExp * 10^bigExp. // - // Calculating 10^smallExp is simple, we just lookup the 10^smallExp from s_Pow10UInt32Table. + // Calculating 10^smallExp is simple, we just lookup the 10^smallExp from Pow10UInt32Table. // But here's a bad news: although uint can represent 10^9, exp 9's binary representation is 1001. // That means 10^(1011), 10^(1101), 10^(1111) all cannot be stored as uint, we cannot easily say something like: - // "Any bits <= 3 is small exp, any bits > 3 is big exp". So instead of involving 10^8, 10^9 to s_Pow10UInt32Table, - // consider 10^8 and 10^9 as a bigNum, so they fall into s_Pow10BigNumTable. Now we can have a simple rule: + // "Any bits <= 3 is small exp, any bits > 3 is big exp". So instead of involving 10^8, 10^9 to Pow10UInt32Table, + // consider 10^8 and 10^9 as a bigNum, so they fall into Pow10BigNumTable. Now we can have a simple rule: // "Any bits <= 3 is small exp, any bits > 3 is big exp". // // For 0b111111, we first calculate 10^(smallExp), which is 10^(7), now we can shift right 3 bits, prepare to calculate the bigExp part, // the exp now becomes 0b000111. // - // Apparently the lowest bit of bigExp should represent 10^8 because we have already shifted 3 bits for smallExp, so s_Pow10BigNumTable[0] = 10^8. + // Apparently the lowest bit of bigExp should represent 10^8 because we have already shifted 3 bits for smallExp, so Pow10BigNumTable[0] = 10^8. // Now let's shift exp right 1 bit, the lowest bit should represent 10^(8 * 2) = 10^16, and so on... // - // That's why we just need the values of s_Pow10BigNumTable be power of 2. + // That's why we just need the values of Pow10BigNumTable be power of 2. // // More details of this implementation can be found at: https://github.com/dotnet/coreclr/pull/12894#discussion_r128890596 - // Validate that `s_Pow10BigNumTable` has exactly enough trailing elements to fill a BigInteger (which contains MaxBlockCount + 1 elements) + // Validate that `Pow10BigNumTable` has exactly enough trailing elements to fill a BigInteger (which contains MaxBlockCount + 1 elements) // We validate here, since this is the only current consumer of the array - Debug.Assert((s_Pow10BigNumTableIndices[^1] + MaxBlockCount + 2) == s_Pow10BigNumTable.Length); + Debug.Assert((Pow10BigNumTableIndices[^1] + MaxBlockCount + 2) == Pow10BigNumTable.Length); - SetUInt32(out BigInteger temp1, s_Pow10UInt32Table[exponent & 0x7]); + SetUInt32(out BigInteger temp1, Pow10UInt32Table[(int)(exponent & 0x7)]); ref BigInteger lhs = ref temp1; SetZero(out BigInteger temp2); @@ -866,7 +866,7 @@ public static void Pow10(uint exponent, out BigInteger result) if ((exponent & 1) != 0) { // Multiply into the next temporary - fixed (uint* pBigNumEntry = &s_Pow10BigNumTable[s_Pow10BigNumTableIndices[index]]) + fixed (uint* pBigNumEntry = &Pow10BigNumTable[Pow10BigNumTableIndices[(int)index]]) { ref BigInteger rhs = ref *(BigInteger*)(pBigNumEntry); Multiply(ref lhs, ref rhs, out product); @@ -1073,7 +1073,7 @@ public void MultiplyPow10(uint exponent) { if (exponent <= 9) { - Multiply(s_Pow10UInt32Table[exponent]); + Multiply(Pow10UInt32Table[(int)exponent]); } else if (!IsZero()) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.Grisu3.cs b/src/libraries/System.Private.CoreLib/src/System/Number.Grisu3.cs index b1217121ef6b5..f18f202837640 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.Grisu3.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.Grisu3.cs @@ -34,7 +34,7 @@ internal static class Grisu3 private const int MaximalTargetExponent = -32; private const int MinimalTargetExponent = -60; - private static readonly short[] s_CachedPowersBinaryExponent = new short[] + private static ReadOnlySpan CachedPowersBinaryExponent => new short[] { -1220, -1193, @@ -125,7 +125,7 @@ internal static class Grisu3 1066, }; - private static readonly short[] s_CachedPowersDecimalExponent = new short[] + private static ReadOnlySpan CachedPowersDecimalExponent => new short[] { CachedPowersMinDecimalExponent, -340, @@ -216,7 +216,7 @@ internal static class Grisu3 CachedPowersPowerMaxDecimalExponent, }; - private static readonly ulong[] s_CachedPowersSignificand = new ulong[] + private static ReadOnlySpan CachedPowersSignificand => new ulong[] { 0xFA8FD5A0081C0288, 0xBAAEE17FA23EBF76, @@ -307,7 +307,7 @@ internal static class Grisu3 0xAF87023B9BF0EE6B, }; - private static readonly uint[] s_SmallPowersOfTen = new uint[] + private static ReadOnlySpan SmallPowersOfTen => new uint[] { 1, // 10^0 10, // 10^1 @@ -540,15 +540,15 @@ private static uint BiggestPowerTen(uint number, int numberBits, out int exponen // 1233/4096 is approximately 1/log2(10) int exponentGuess = ((numberBits + 1) * 1233) >> 12; - Debug.Assert((uint)(exponentGuess) < s_SmallPowersOfTen.Length); + Debug.Assert((uint)(exponentGuess) < SmallPowersOfTen.Length); - uint power = s_SmallPowersOfTen[exponentGuess]; + uint power = SmallPowersOfTen[exponentGuess]; // We don't have any guarantees that 2^numberBits <= number if (number < power) { exponentGuess--; - power = s_SmallPowersOfTen[exponentGuess]; + power = SmallPowersOfTen[exponentGuess]; } exponentPlusOne = exponentGuess + 1; @@ -606,7 +606,7 @@ private static bool TryDigitGenCounted(in DiyFp w, int requestedDigits, Span= 11, integrals is not able to exhaust the count by itself since 10^(11 -1) > uint.MaxValue >= integrals. // If integrals < 10^(requestedDigits - 1), integrals cannot exhaust the count. // Otherwise, integrals might be able to exhaust the count and we need to execute the rest of the code. - if ((fractionals == 0) && ((requestedDigits >= 11) || (integrals < s_SmallPowersOfTen[requestedDigits - 1]))) + if ((fractionals == 0) && ((requestedDigits >= 11) || (integrals < SmallPowersOfTen[requestedDigits - 1]))) { Debug.Assert(buffer[0] == '\0'); length = 0; @@ -884,19 +884,19 @@ private static bool TryDigitGenShortest(in DiyFp low, in DiyFp w, in DiyFp high, // Returns a cached power-of-ten with a binary exponent in the range [minExponent; maxExponent] (boundaries included). private static DiyFp GetCachedPowerForBinaryExponentRange(int minExponent, int maxExponent, out int decimalExponent) { - Debug.Assert(s_CachedPowersSignificand.Length == s_CachedPowersBinaryExponent.Length); - Debug.Assert(s_CachedPowersSignificand.Length == s_CachedPowersDecimalExponent.Length); + Debug.Assert(CachedPowersSignificand.Length == CachedPowersBinaryExponent.Length); + Debug.Assert(CachedPowersSignificand.Length == CachedPowersDecimalExponent.Length); double k = Math.Ceiling((minExponent + DiyFp.SignificandSize - 1) * D1Log210); int index = ((CachedPowersOffset + (int)(k) - 1) / CachedPowersDecimalExponentDistance) + 1; - Debug.Assert((uint)(index) < s_CachedPowersSignificand.Length); + Debug.Assert((uint)(index) < CachedPowersSignificand.Length); - Debug.Assert(minExponent <= s_CachedPowersBinaryExponent[index]); - Debug.Assert(s_CachedPowersBinaryExponent[index] <= maxExponent); + Debug.Assert(minExponent <= CachedPowersBinaryExponent[index]); + Debug.Assert(CachedPowersBinaryExponent[index] <= maxExponent); - decimalExponent = s_CachedPowersDecimalExponent[index]; - return new DiyFp(s_CachedPowersSignificand[index], s_CachedPowersBinaryExponent[index]); + decimalExponent = CachedPowersDecimalExponent[index]; + return new DiyFp(CachedPowersSignificand[index], CachedPowersBinaryExponent[index]); } // Rounds the buffer upwards if the result is closer to v by possibly adding 1 to the buffer. diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs b/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs index e6465da384e25..419e623cee0a7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Number.NumberToFloatingPointBits.cs @@ -71,7 +71,7 @@ public FloatingPointInfo(ushort denormalMantissaBits, ushort exponentBits, int m } } - private static readonly float[] s_Pow10SingleTable = new float[] + private static ReadOnlySpan Pow10SingleTable => new float[] { 1e0f, // 10^0 1e1f, // 10^1 @@ -86,7 +86,7 @@ public FloatingPointInfo(ushort denormalMantissaBits, ushort exponentBits, int m 1e10f, // 10^10 }; - private static readonly double[] s_Pow10DoubleTable = new double[] + private static ReadOnlySpan Pow10DoubleTable => new double[] { 1e0, // 10^0 1e1, // 10^1 @@ -377,7 +377,7 @@ private static ulong NumberToDoubleFloatingPointBits(ref NumberBuffer number, in if ((totalDigits <= 15) && (fastExponent <= 22)) { double result = DigitsToUInt64(src, (int)(totalDigits)); - double scale = s_Pow10DoubleTable[fastExponent]; + double scale = Pow10DoubleTable[(int)fastExponent]; if (fractionalDigitsPresent != 0) { @@ -439,7 +439,7 @@ private static ushort NumberToHalfFloatingPointBits(ref NumberBuffer number, in // wrong value when upcasting to double. float result = DigitsToUInt32(src, (int)(totalDigits)); - float scale = s_Pow10SingleTable[fastExponent]; + float scale = Pow10SingleTable[(int)fastExponent]; if (fractionalDigitsPresent != 0) { @@ -456,7 +456,7 @@ private static ushort NumberToHalfFloatingPointBits(ref NumberBuffer number, in if ((totalDigits <= 15) && (fastExponent <= 22)) { double result = DigitsToUInt64(src, (int)(totalDigits)); - double scale = s_Pow10DoubleTable[fastExponent]; + double scale = Pow10DoubleTable[(int)fastExponent]; if (fractionalDigitsPresent != 0) { @@ -518,7 +518,7 @@ private static uint NumberToSingleFloatingPointBits(ref NumberBuffer number, in // wrong value when upcasting to double. float result = DigitsToUInt32(src, (int)(totalDigits)); - float scale = s_Pow10SingleTable[fastExponent]; + float scale = Pow10SingleTable[(int)fastExponent]; if (fractionalDigitsPresent != 0) { @@ -535,7 +535,7 @@ private static uint NumberToSingleFloatingPointBits(ref NumberBuffer number, in if ((totalDigits <= 15) && (fastExponent <= 22)) { double result = DigitsToUInt64(src, (int)(totalDigits)); - double scale = s_Pow10DoubleTable[fastExponent]; + double scale = Pow10DoubleTable[(int)fastExponent]; if (fractionalDigitsPresent != 0) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs b/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs index b714b64dc26cb..3946243b89a84 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Security/SecurityElement.cs @@ -18,10 +18,10 @@ public sealed class SecurityElement private const int AttributesTypical = 4 * 2; // 4 attributes, times 2 strings per attribute private const int ChildrenTypical = 1; - private static readonly char[] s_tagIllegalCharacters = new char[] { ' ', '<', '>' }; - private static readonly char[] s_textIllegalCharacters = new char[] { '<', '>' }; - private static readonly char[] s_valueIllegalCharacters = new char[] { '<', '>', '\"' }; - private static readonly char[] s_escapeChars = new char[] { '<', '>', '\"', '\'', '&' }; + private static ReadOnlySpan TagIllegalCharacters => new char[] { ' ', '<', '>' }; + private static ReadOnlySpan TextIllegalCharacters => new char[] { '<', '>' }; + private static ReadOnlySpan ValueIllegalCharacters => new char[] { '<', '>', '\"' }; + private static ReadOnlySpan EscapeChars => new char[] { '<', '>', '\"', '\'', '&' }; private static readonly string[] s_escapeStringPairs = new string[] { // these must be all once character escape sequences or a new escaping algorithm is needed @@ -303,7 +303,7 @@ public static bool IsValidTag([NotNullWhen(true)] string? tag) if (tag == null) return false; - return tag.IndexOfAny(s_tagIllegalCharacters) == -1; + return tag.AsSpan().IndexOfAny(TagIllegalCharacters) == -1; } public static bool IsValidText([NotNullWhen(true)] string? text) @@ -311,7 +311,7 @@ public static bool IsValidText([NotNullWhen(true)] string? text) if (text == null) return false; - return text.IndexOfAny(s_textIllegalCharacters) == -1; + return text.AsSpan().IndexOfAny(TextIllegalCharacters) == -1; } public static bool IsValidAttributeName([NotNullWhen(true)] string? name) @@ -324,7 +324,7 @@ public static bool IsValidAttributeValue([NotNullWhen(true)] string? value) if (value == null) return false; - return value.IndexOfAny(s_valueIllegalCharacters) == -1; + return value.AsSpan().IndexOfAny(ValueIllegalCharacters) == -1; } private static string GetEscapeSequence(char c) @@ -349,37 +349,32 @@ private static string GetEscapeSequence(char c) public static string? Escape(string? str) { if (str == null) + { return null; + } StringBuilder? sb = null; - - int strLen = str.Length; - int index; // Pointer into the string that indicates the location of the current '&' character - int newIndex = 0; // Pointer into the string that indicates the start index of the "remaining" string (that still needs to be processed). + ReadOnlySpan span = str; while (true) { - index = str.IndexOfAny(s_escapeChars, newIndex); - - if (index == -1) + int i = span.IndexOfAny(EscapeChars); + if (i < 0) { if (sb == null) - return str; - else { - sb.Append(str, newIndex, strLen - newIndex); - return sb.ToString(); + return str; } + + sb.Append(span); + return sb.ToString(); } - else - { - sb ??= new StringBuilder(); - sb.Append(str, newIndex, index - newIndex); - sb.Append(GetEscapeSequence(str[index])); + sb ??= new StringBuilder(); + sb.Append(span.Slice(0, i)); + sb.Append(GetEscapeSequence(span[i])); - newIndex = (index + 1); - } + span = span.Slice(i + 1); } // no normal exit is possible diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/EncoderLatin1BestFitFallback.Data.cs b/src/libraries/System.Private.CoreLib/src/System/Text/EncoderLatin1BestFitFallback.Data.cs index c110074189c19..fe856d6148225 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/EncoderLatin1BestFitFallback.Data.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/EncoderLatin1BestFitFallback.Data.cs @@ -6,7 +6,7 @@ namespace System.Text internal sealed partial class EncoderLatin1BestFitFallbackBuffer { // Best fit for ASCII, and since it works for ASCII, we use it for latin1 as well. - private static readonly char[] s_arrayCharBestFit = + private static ReadOnlySpan ArrayCharBestFit => new char[] { // The first many are in case you wanted to use this for ASCIIEncoding, which we don't need to do any more. // (char)0x00a0, (char)0x0020, // No-Break Space -> Space diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/EncoderLatin1BestFitFallback.cs b/src/libraries/System.Private.CoreLib/src/System/Text/EncoderLatin1BestFitFallback.cs index 8fb9515001842..d9ceb1178643e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/EncoderLatin1BestFitFallback.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/EncoderLatin1BestFitFallback.cs @@ -123,8 +123,7 @@ private static char TryBestFit(char cUnknown) { // Need to figure out our best fit character, low is beginning of array, high is 1 AFTER end of array int lowBound = 0; - Debug.Assert(s_arrayCharBestFit != null); - int highBound = s_arrayCharBestFit.Length; + int highBound = ArrayCharBestFit.Length; int index; // Binary search the array @@ -136,13 +135,13 @@ private static char TryBestFit(char cUnknown) // Also note that index can never == highBound (because diff is rounded down) index = ((iDiff / 2) + lowBound) & 0xFFFE; - char cTest = s_arrayCharBestFit[index]; + char cTest = ArrayCharBestFit[index]; if (cTest == cUnknown) { // We found it - Debug.Assert(index + 1 < s_arrayCharBestFit.Length, + Debug.Assert(index + 1 < ArrayCharBestFit.Length, "[EncoderLatin1BestFitFallbackBuffer.TryBestFit]Expected replacement character at end of array"); - return s_arrayCharBestFit[index + 1]; + return ArrayCharBestFit[index + 1]; } else if (cTest < cUnknown) { @@ -158,12 +157,12 @@ private static char TryBestFit(char cUnknown) for (index = lowBound; index < highBound; index += 2) { - if (s_arrayCharBestFit[index] == cUnknown) + if (ArrayCharBestFit[index] == cUnknown) { // We found it - Debug.Assert(index + 1 < s_arrayCharBestFit.Length, + Debug.Assert(index + 1 < ArrayCharBestFit.Length, "[EncoderLatin1BestFitFallbackBuffer.TryBestFit]Expected replacement character at end of array"); - return s_arrayCharBestFit[index + 1]; + return ArrayCharBestFit[index + 1]; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/EncodingData.cs b/src/libraries/System.Private.CoreLib/src/System/Text/EncodingData.cs index 992891ff08836..2b621d6bce9fe 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/EncodingData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/EncodingData.cs @@ -9,14 +9,14 @@ namespace System.Text internal static partial class EncodingTable { // - // s_encodingNames is the concatenation of all supported IANA names for each codepage. + // EncodingNames is the concatenation of all supported IANA names for each codepage. // This is done rather than using a large readonly array of strings to avoid // generating a large amount of code in the static constructor. - // Using indices from s_encodingNamesIndices, we binary search this string when mapping + // Using indices from EncodingNamesIndices, we binary search this string when mapping // an encoding name to a codepage. Note that these names are all lowercase and are // sorted alphabetically. // - private const string s_encodingNames = + private const string EncodingNames = "ansi_x3.4-1968" + // 20127 "ansi_x3.4-1986" + // 20127 "ascii" + // 20127 @@ -61,11 +61,11 @@ internal static partial class EncodingTable "x-unicode-2-0-utf-8"; // 65001 // - // s_encodingNameIndices contains the start index of every encoding name in the string - // s_encodingNames. We infer the length of each string by looking at the start index + // EncodingNameIndices contains the start index of every encoding name in the string + // EncodingNames. We infer the length of each string by looking at the start index // of the next string. // - private static readonly int[] s_encodingNameIndices = new int[] + private static ReadOnlySpan EncodingNameIndices => new int[] { 0, // ansi_x3.4-1968 (20127) 14, // ansi_x3.4-1986 (20127) @@ -113,13 +113,13 @@ internal static partial class EncodingTable }; // - // s_codePagesByName contains the list of supported codepages which match the encoding - // names listed in s_encodingNames. The way mapping works is we binary search - // s_encodingNames using s_encodingNamesIndices until we find a match for a given name. - // The index of the entry in s_encodingNamesIndices will be the index of codepage in - // s_codePagesByName. + // CodePagesByName contains the list of supported codepages which match the encoding + // names listed in EncodingNames. The way mapping works is we binary search + // EncodingNames using EncodingNamesIndices until we find a match for a given name. + // The index of the entry in EncodingNamesIndices will be the index of codepage in + // CodePagesByName. // - private static readonly ushort[] s_codePagesByName = new ushort[] + private static ReadOnlySpan CodePagesByName => new ushort[] { 20127, // ansi_x3.4-1968 20127, // ansi_x3.4-1986 @@ -168,14 +168,14 @@ internal static partial class EncodingTable // // When retrieving the value for System.Text.Encoding.WebName or // System.Text.Encoding.EncodingName given System.Text.Encoding.CodePage, - // we perform a linear search on s_mappedCodePages to find the index of the + // we perform a linear search on MappedCodePages to find the index of the // given codepage. This is used to index WebNameIndices to get the start // index of the web name in the string WebNames, and to index - // s_englishNameIndices to get the start of the English name in - // s_englishNames. In addition, this arrays indices correspond to the indices - // into s_uiFamilyCodePages and s_flags. + // EnglishNameIndices to get the start of the English name in + // EnglishNames. In addition, this arrays indices correspond to the indices + // into UiFamilyCodePages and Flags. // - private static readonly ushort[] s_mappedCodePages = new ushort[] + private static ReadOnlySpan MappedCodePages => new ushort[] { 1200, // utf-16 1201, // utf-16be @@ -188,9 +188,9 @@ internal static partial class EncodingTable }; // - // s_uiFamilyCodePages is indexed by the corresponding index in s_mappedCodePages. + // UiFamilyCodePages is indexed by the corresponding index in MappedCodePages. // - private static readonly int[] s_uiFamilyCodePages = new int[] + private static ReadOnlySpan UiFamilyCodePages => new int[] { 1200, 1200, @@ -203,13 +203,13 @@ internal static partial class EncodingTable }; // - // s_webNames is a concatenation of the default encoding names + // WebNames is a concatenation of the default encoding names // for each code page. It is used in retrieving the value for // System.Text.Encoding.WebName given System.Text.Encoding.CodePage. // This is done rather than using a large readonly array of strings to avoid // generating a large amount of code in the static constructor. // - private const string s_webNames = + private const string WebNames = "utf-16" + // 1200 "utf-16BE" + // 1201 "utf-32" + // 12000 @@ -220,11 +220,11 @@ internal static partial class EncodingTable "utf-8"; // 65001 // - // s_webNameIndices contains the start index of each code page's default - // web name in the string s_webNames. It is indexed by an index into - // s_mappedCodePages. + // WebNameIndices contains the start index of each code page's default + // web name in the string WebNames. It is indexed by an index into + // MappedCodePages. // - private static readonly int[] s_webNameIndices = new int[] + private static ReadOnlySpan WebNameIndices => new int[] { 0, // utf-16 (1200) 6, // utf-16be (1201) @@ -238,13 +238,13 @@ internal static partial class EncodingTable }; // - // s_englishNames is the concatenation of the English names for each codepage. + // EnglishNames is the concatenation of the English names for each codepage. // It is used in retrieving the value for System.Text.Encoding.EncodingName // given System.Text.Encoding.CodePage. // This is done rather than using a large readonly array of strings to avoid // generating a large amount of code in the static constructor. // - private const string s_englishNames = + private const string EnglishNames = "Unicode" + // 1200 "Unicode (Big-Endian)" + // 1201 "Unicode (UTF-32)" + // 12000 @@ -255,11 +255,11 @@ internal static partial class EncodingTable "Unicode (UTF-8)"; // 65001 // - // s_englishNameIndices contains the start index of each code page's English - // name in the string s_englishNames. It is indexed by an index into - // s_mappedCodePages. + // EnglishNameIndices contains the start index of each code page's English + // name in the string EnglishNames. It is indexed by an index into + // MappedCodePages. // - private static readonly int[] s_englishNameIndices = new int[] + private static ReadOnlySpan EnglishNameIndices => new int[] { 0, // Unicode (1200) 7, // Unicode (Big-Endian) (1201) @@ -278,8 +278,8 @@ internal static partial class EncodingTable private const uint MIMECONTF_SAVABLE_MAILNEWS = Encoding.MIMECONTF_SAVABLE_MAILNEWS; private const uint MIMECONTF_SAVABLE_BROWSER = Encoding.MIMECONTF_SAVABLE_BROWSER; - // s_flags is indexed by the corresponding index in s_mappedCodePages. - private static readonly uint[] s_flags = new uint[] + // Flags is indexed by the corresponding index in MappedCodePages. + private static ReadOnlySpan Flags => new uint[] { MIMECONTF_SAVABLE_BROWSER, 0, diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/EncodingTable.cs b/src/libraries/System.Private.CoreLib/src/System/Text/EncodingTable.cs index bdf608fc76b6e..15968f3312647 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/EncodingTable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/EncodingTable.cs @@ -51,12 +51,12 @@ internal static int GetCodePageFromName(string name) private static int InternalGetCodePageFromName(string name) { int left = 0; - int right = s_encodingNameIndices.Length - 2; + int right = EncodingNameIndices.Length - 2; int index; int result; - Debug.Assert(s_encodingNameIndices.Length == s_codePagesByName.Length + 1); - Debug.Assert(s_encodingNameIndices[^1] == s_encodingNames.Length); + Debug.Assert(EncodingNameIndices.Length == CodePagesByName.Length + 1); + Debug.Assert(EncodingNameIndices[^1] == EncodingNames.Length); ReadOnlySpan invariantName = name.ToLowerInvariant().AsSpan(); @@ -66,13 +66,13 @@ private static int InternalGetCodePageFromName(string name) { index = ((right - left) / 2) + left; - Debug.Assert(index < s_encodingNameIndices.Length - 1); - result = string.CompareOrdinal(invariantName, s_encodingNames.AsSpan(s_encodingNameIndices[index], s_encodingNameIndices[index + 1] - s_encodingNameIndices[index])); + Debug.Assert(index < EncodingNameIndices.Length - 1); + result = string.CompareOrdinal(invariantName, EncodingNames.AsSpan(EncodingNameIndices[index], EncodingNameIndices[index + 1] - EncodingNameIndices[index])); if (result == 0) { // We found the item, return the associated codePage. - return s_codePagesByName[index]; + return CodePagesByName[index]; } else if (result < 0) { @@ -89,10 +89,10 @@ private static int InternalGetCodePageFromName(string name) // Walk the remaining elements (it'll be 3 or fewer). for (; left <= right; left++) { - Debug.Assert(left < s_encodingNameIndices.Length - 1); - if (string.CompareOrdinal(invariantName, s_encodingNames.AsSpan(s_encodingNameIndices[left], s_encodingNameIndices[left + 1] - s_encodingNameIndices[left])) == 0) + Debug.Assert(left < EncodingNameIndices.Length - 1); + if (string.CompareOrdinal(invariantName, EncodingNames.AsSpan(EncodingNameIndices[left], EncodingNameIndices[left + 1] - EncodingNameIndices[left])) == 0) { - return s_codePagesByName[left]; + return CodePagesByName[left]; } } @@ -108,10 +108,10 @@ internal static EncodingInfo[] GetEncodings() // If UTF-7 encoding is not enabled, we adjust the return array length by -1 // to account for the skipped EncodingInfo element. - ushort[] mappedCodePages = s_mappedCodePages; + ReadOnlySpan mappedCodePages = MappedCodePages; EncodingInfo[] arrayEncodingInfo = new EncodingInfo[(LocalAppContextSwitches.EnableUnsafeUTF7Encoding) ? mappedCodePages.Length : (mappedCodePages.Length - 1)]; - string webNames = s_webNames; - int[] webNameIndices = s_webNameIndices; + string webNames = WebNames; + ReadOnlySpan webNameIndices = WebNameIndices; int arrayEncodingInfoIdx = 0; for (int i = 0; i < mappedCodePages.Length; i++) @@ -136,9 +136,9 @@ internal static EncodingInfo[] GetEncodings() internal static EncodingInfo[] GetEncodings(Dictionary encodingInfoList) { Debug.Assert(encodingInfoList != null); - ushort[] mappedCodePages = s_mappedCodePages; - string webNames = s_webNames; - int[] webNameIndices = s_webNameIndices; + ReadOnlySpan mappedCodePages = MappedCodePages; + string webNames = WebNames; + ReadOnlySpan webNameIndices = WebNameIndices; for (int i = 0; i < mappedCodePages.Length; i++) { @@ -178,10 +178,10 @@ internal static EncodingInfo[] GetEncodings(Dictionary encodi { if (s_codePageToCodePageData == null) { - Interlocked.CompareExchange(ref s_codePageToCodePageData, new CodePageDataItem[s_mappedCodePages.Length], null); + Interlocked.CompareExchange(ref s_codePageToCodePageData, new CodePageDataItem[MappedCodePages.Length], null); } - // Keep in sync with s_mappedCodePages + // Keep in sync with MappedCodePages int index; switch (codePage) { @@ -225,13 +225,13 @@ internal static EncodingInfo[] GetEncodings(Dictionary encodi private static CodePageDataItem InternalGetCodePageDataItem(int codePage, int index) { - int uiFamilyCodePage = s_uiFamilyCodePages[index]; - string webName = s_webNames[s_webNameIndices[index]..s_webNameIndices[index + 1]]; + int uiFamilyCodePage = UiFamilyCodePages[index]; + string webName = WebNames[WebNameIndices[index]..WebNameIndices[index + 1]]; // All supported code pages have identical header names, and body names. string headerName = webName; string bodyName = webName; string displayName = GetDisplayName(codePage, index); - uint flags = s_flags[index]; + uint flags = Flags[index]; return new CodePageDataItem(uiFamilyCodePage, webName, headerName, bodyName, displayName, flags); } @@ -240,7 +240,7 @@ private static string GetDisplayName(int codePage, int englishNameIndex) { string? displayName = SR.GetResourceString("Globalization_cp_" + codePage.ToString()); if (string.IsNullOrEmpty(displayName)) - displayName = s_englishNames[s_englishNameIndices[englishNameIndex]..s_englishNameIndices[englishNameIndex + 1]]; + displayName = EnglishNames[EnglishNameIndices[englishNameIndex]..EnglishNameIndices[englishNameIndex + 1]]; return displayName; } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonGlobals.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonGlobals.cs index b4a99668d1357..68c07237830a7 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonGlobals.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonGlobals.cs @@ -24,7 +24,7 @@ internal static class JsonGlobals public static readonly UTF8Encoding ValidatingUTF8 = new UTF8Encoding(false, true); public const string PositiveInf = "INF"; public const string NegativeInf = "-INF"; - public static readonly char[] FloatingPointCharacters = new char[] { '.', 'e', 'E' }; + public static ReadOnlySpan FloatingPointCharacters => new char[] { '.', 'e', 'E' }; public const string typeString = "type"; public const string nullString = "null"; public const string arrayString = "array"; diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonObjectDataContract.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonObjectDataContract.cs index d7e72a18d01c6..0563b5ece3ab8 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonObjectDataContract.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/Json/JsonObjectDataContract.cs @@ -69,7 +69,7 @@ internal static object ParseJsonNumber(string value, out TypeCode objectTypeCode throw new XmlException(SR.Format(SR.XmlInvalidConversion, value, Globals.TypeOfInt)); } - if (value.IndexOfAny(JsonGlobals.FloatingPointCharacters) == -1) + if (value.AsSpan().IndexOfAny(JsonGlobals.FloatingPointCharacters) < 0) { int intValue; if (int.TryParse(value, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out intValue)) diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ObjectToIdCache.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ObjectToIdCache.cs index 5648bf4734ced..f8e14d4a3e99d 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ObjectToIdCache.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Runtime/Serialization/ObjectToIdCache.cs @@ -161,6 +161,17 @@ private void Rehash() private static int GetPrime(int min) { + ReadOnlySpan primes = new int[] + { + 3, 7, 17, 37, 89, 197, 431, 919, 1931, 4049, 8419, 17519, 36353, + 75431, 156437, 324449, 672827, 1395263, 2893249, 5999471, + 11998949, 23997907, 47995853, 95991737, 191983481, 383966977, 767933981, 1535867969, + 2146435069, 0x7FFFFFC7 + // 0x7FFFFFC7 == Array.MaxLength is not prime, but it is the largest possible array size. + // There's nowhere to go from here. Using a const rather than the MaxLength property + // so that the array contains only const values. + }; + for (int i = 0; i < primes.Length; i++) { int prime = primes[i]; @@ -169,16 +180,5 @@ private static int GetPrime(int min) return min; } - - internal static readonly int[] primes = - { - 3, 7, 17, 37, 89, 197, 431, 919, 1931, 4049, 8419, 17519, 36353, - 75431, 156437, 324449, 672827, 1395263, 2893249, 5999471, - 11998949, 23997907, 47995853, 95991737, 191983481, 383966977, 767933981, 1535867969, - 2146435069, 0x7FFFFFC7 - // 0x7FFFFFC7 == Array.MaxLength is not prime, but it is the largest possible array size. - // There's nowhere to go from here. Using a const rather than the MaxLength property - // so that the array contains only const values. - }; } } diff --git a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/UniqueId.cs b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/UniqueId.cs index 2a922cce9c585..6352a6a00c62f 100644 --- a/src/libraries/System.Private.DataContractSerialization/src/System/Xml/UniqueId.cs +++ b/src/libraries/System.Private.DataContractSerialization/src/System/Xml/UniqueId.cs @@ -13,7 +13,7 @@ public class UniqueId private const int guidLength = 16; private const int uuidLength = 45; - private static readonly short[] s_char2val = new short[256] + private static ReadOnlySpan Char2val => new short[256] { /* 0-15 */ 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, @@ -162,7 +162,7 @@ private unsafe void UnsafeParse(char* chars, int charCount) int i = 0; int j = 0; - fixed (short* ps = &s_char2val[0]) + fixed (short* ps = &Char2val[0]) { short* _char2val = ps; diff --git a/src/libraries/System.Private.Uri/src/System/DomainNameHelper.cs b/src/libraries/System.Private.Uri/src/System/DomainNameHelper.cs index 45f2bdb53c5c4..84c11fcb35e67 100644 --- a/src/libraries/System.Private.Uri/src/System/DomainNameHelper.cs +++ b/src/libraries/System.Private.Uri/src/System/DomainNameHelper.cs @@ -392,11 +392,10 @@ private static bool IsValidDomainLabelCharacter(char character, ref bool notCano // This means that a host containing Unicode characters can be normalized to contain // URI reserved characters, changing the meaning of a URI only when certain properties // such as IdnHost are accessed. To be safe, disallow control characters in normalized hosts. - private static readonly char[] s_UnsafeForNormalizedHost = { '\\', '/', '?', '@', '#', ':', '[', ']' }; - internal static bool ContainsCharactersUnsafeForNormalizedHost(string host) { - return host.IndexOfAny(s_UnsafeForNormalizedHost) != -1; + ReadOnlySpan unsafeForNormalizedHost = new char[] { '\\', '/', '?', '@', '#', ':', '[', ']' }; + return host.AsSpan().IndexOfAny(unsafeForNormalizedHost) != -1; } } } diff --git a/src/libraries/System.Private.Uri/src/System/Uri.cs b/src/libraries/System.Private.Uri/src/System/Uri.cs index b0bda36d92db2..3e2754abd0688 100644 --- a/src/libraries/System.Private.Uri/src/System/Uri.cs +++ b/src/libraries/System.Private.Uri/src/System/Uri.cs @@ -1821,16 +1821,13 @@ public Uri MakeRelativeUri(Uri uri) // // Returns true if a colon is found in the first path segment, false otherwise // - - // Check for anything that may terminate the first regular path segment - // or an illegal colon - private static readonly char[] s_pathDelims = { ':', '\\', '/', '?', '#' }; - private static bool CheckForColonInFirstPathSegment(string uriString) { - int index = uriString.IndexOfAny(s_pathDelims); - - return (index >= 0 && uriString[index] == ':'); + // Check for anything that may terminate the first regular path segment + // or an illegal colon + ReadOnlySpan PathDelims = new char[] { ':', '\\', '/', '?', '#' }; + int index = uriString.AsSpan().IndexOfAny(PathDelims); + return (uint)index < (uint)uriString.Length && uriString[index] == ':'; } internal static string InternalEscapeString(string rawString) => diff --git a/src/libraries/System.Private.Xml.Linq/src/System/Xml/Linq/XNodeReader.cs b/src/libraries/System.Private.Xml.Linq/src/System/Xml/Linq/XNodeReader.cs index 547c8196d58d7..e1b3d8aa4dddb 100644 --- a/src/libraries/System.Private.Xml.Linq/src/System/Xml/Linq/XNodeReader.cs +++ b/src/libraries/System.Private.Xml.Linq/src/System/Xml/Linq/XNodeReader.cs @@ -7,8 +7,6 @@ namespace System.Xml.Linq { internal sealed class XNodeReader : XmlReader, IXmlLineInfo { - private static readonly char[] s_WhitespaceChars = new char[] { ' ', '\t', '\n', '\r' }; - // The reader position is encoded by the tuple (source, parent). // Lazy text uses (instance, parent element). Attribute value // uses (instance, parent attribute). End element uses (instance, @@ -430,14 +428,17 @@ public override XmlSpace XmlSpace XAttribute? a = e.Attribute(name); if (a != null) { - switch (a.Value.Trim(s_WhitespaceChars)) + ReadOnlySpan whitespaceChars = new char[] { ' ', '\t', '\n', '\r' }; + ReadOnlySpan trimmed = a.Value.AsSpan().Trim(whitespaceChars); + + if (trimmed.SequenceEqual("preserve")) + { + return XmlSpace.Preserve; + } + + if (trimmed.SequenceEqual("default")) { - case "preserve": - return XmlSpace.Preserve; - case "default": - return XmlSpace.Default; - default: - break; + return XmlSpace.Default; } } e = e.parent as XElement; diff --git a/src/libraries/System.Private.Xml.Linq/src/System/Xml/XPath/XNodeNavigator.cs b/src/libraries/System.Private.Xml.Linq/src/System/Xml/XPath/XNodeNavigator.cs index 074dd99d4a9db..c866d0ff67715 100644 --- a/src/libraries/System.Private.Xml.Linq/src/System/Xml/XPath/XNodeNavigator.cs +++ b/src/libraries/System.Private.Xml.Linq/src/System/Xml/XPath/XNodeNavigator.cs @@ -16,7 +16,7 @@ internal sealed class XNodeNavigator : XPathNavigator, IXmlLineInfo (1 << (int)XmlNodeType.Element) | (1 << (int)XmlNodeType.ProcessingInstruction) | (1 << (int)XmlNodeType.Comment); - private static readonly int[] s_ElementContentMasks = { + private static ReadOnlySpan ElementContentMasks => new int[] { 0, // Root (1 << (int)XmlNodeType.Element), // Element 0, // Attribute @@ -768,7 +768,7 @@ private static bool IsXmlNamespaceDeclaration(XAttribute a) private static int GetElementContentMask(XPathNodeType type) { - return s_ElementContentMasks[(int)type]; + return ElementContentMasks[(int)type]; } private static XAttribute? GetFirstNamespaceDeclarationGlobal(XElement e) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdBuilder.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdBuilder.cs index 7a72a77d2a39e..b02121bf100e4 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdBuilder.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdBuilder.cs @@ -607,7 +607,7 @@ public BuilderNamespaceManager(XmlNamespaceManager nsMgr, XmlReader reader) // // for 'block' and 'final' attribute values // - private static readonly int[] s_derivationMethodValues = { + private static ReadOnlySpan DerivationMethodValues => new int[] { (int)XmlSchemaDerivationMethod.Substitution, (int)XmlSchemaDerivationMethod.Extension, (int)XmlSchemaDerivationMethod.Restriction, @@ -2533,12 +2533,12 @@ private int ParseBlockFinalEnum(string value, string attributeName) { if (stringValues[i] == s_derivationMethodStrings[j]) { - if ((r & s_derivationMethodValues[j]) != 0 && (r & s_derivationMethodValues[j]) != s_derivationMethodValues[j]) + if ((r & DerivationMethodValues[j]) != 0 && (r & DerivationMethodValues[j]) != DerivationMethodValues[j]) { SendValidationEvent(SR.Sch_InvalidXsdAttributeValue, attributeName, value, null); return 0; } - r |= s_derivationMethodValues[j]; + r |= DerivationMethodValues[j]; matched = true; break; } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDateTime.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDateTime.cs index 71f43082b5e25..febeaba0c5c79 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDateTime.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XsdDateTime.cs @@ -81,8 +81,8 @@ private enum XsdDateTimeKind private const int ZoneHourShift = 8; // Maximum number of fraction digits; - private const short maxFractionDigits = 7; - private const int ticksToFractionDivisor = 10000000; + private const short MaxFractionDigits = 7; + private const int TicksToFractionDivisor = 10000000; private static readonly int s_lzyyyy = "yyyy".Length; private static readonly int s_lzyyyy_ = "yyyy-".Length; @@ -126,9 +126,9 @@ private enum XsdDateTimeKind // Number of days in 400 years private const int DaysPer400Years = DaysPer100Years * 4 + 1; // 146097 - private static readonly int[] DaysToMonth365 = { + private static ReadOnlySpan DaysToMonth365 => new int[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365}; - private static readonly int[] DaysToMonth366 = { + private static ReadOnlySpan DaysToMonth366 => new int[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366}; /// @@ -328,7 +328,7 @@ public int Second /// public int Fraction { - get { return (int)(_dt.Ticks % ticksToFractionDivisor); } + get { return (int)(_dt.Ticks % TicksToFractionDivisor); } } /// @@ -608,7 +608,7 @@ private void GetYearMonthDay(out int year, out int month, out int day) // Leap year calculation looks different from IsLeapYear since y1, y4, // and y100 are relative to year 1, not year 0 bool leapYear = y1 == 3 && (y4 != 24 || y100 == 3); - int[] days = leapYear ? DaysToMonth366 : DaysToMonth365; + ReadOnlySpan days = leapYear ? DaysToMonth366 : DaysToMonth365; // All months have less than 32 days, so n >> 5 is a good conservative // estimate for the month month = (n >> 5) + 1; @@ -632,7 +632,7 @@ private void PrintTime(StringBuilder sb) int fraction = Fraction; if (fraction != 0) { - int fractionDigits = maxFractionDigits; + int fractionDigits = MaxFractionDigits; while (fraction % 10 == 0) { fractionDigits--; @@ -929,7 +929,7 @@ private bool ParseTimeAndWhitespace(int start) return false; } - private static readonly int[] s_power10 = new int[maxFractionDigits] { -1, 10, 100, 1000, 10000, 100000, 1000000 }; + private static ReadOnlySpan Power10 => new int[MaxFractionDigits] { -1, 10, 100, 1000, 10000, 100000, 1000000 }; private bool ParseTime(ref int start) { if ( @@ -955,11 +955,11 @@ private bool ParseTime(ref int start) { // d < 0 || 9 < d break; } - if (fractionDigits < maxFractionDigits) + if (fractionDigits < MaxFractionDigits) { this.fraction = (this.fraction * 10) + d; } - else if (fractionDigits == maxFractionDigits) + else if (fractionDigits == MaxFractionDigits) { if (5 < d) { @@ -976,13 +976,13 @@ private bool ParseTime(ref int start) } fractionDigits++; } - if (fractionDigits < maxFractionDigits) + if (fractionDigits < MaxFractionDigits) { if (fractionDigits == 0) { return false; // cannot end with . } - fraction *= s_power10[maxFractionDigits - fractionDigits]; + fraction *= Power10[MaxFractionDigits - fractionDigits]; } else { diff --git a/src/libraries/System.Private.Xml/src/System/Xml/XPath/XPathNavigator.cs b/src/libraries/System.Private.Xml/src/System/Xml/XPath/XPathNavigator.cs index 6568055ff2d6a..908b9dfeabafd 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/XPath/XPathNavigator.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/XPath/XPathNavigator.cs @@ -1799,7 +1799,7 @@ internal uint IndexInParent } } - internal static readonly char[] NodeTypeLetter = new char[] { + internal static ReadOnlySpan NodeTypeLetter => new char[] { 'R', // Root 'E', // Element 'A', // Attribute @@ -1812,7 +1812,7 @@ internal uint IndexInParent 'X', // All }; - internal static readonly char[] UniqueIdTbl = new char[] { + internal static ReadOnlySpan UniqueIdTbl => new char[] { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', @@ -1845,14 +1845,14 @@ internal virtual string UniqueId } if (idx <= 0x1f) { - sb.Append(UniqueIdTbl[idx]); + sb.Append(UniqueIdTbl[(int)idx]); } else { sb.Append('0'); do { - sb.Append(UniqueIdTbl[idx & 0x1f]); + sb.Append(UniqueIdTbl[(int)(idx & 0x1f)]); idx >>= 5; } while (idx != 0); sb.Append('0'); @@ -1969,7 +1969,7 @@ internal static XmlNamespaceManager GetNamespaces(IXmlNamespaceResolver resolver internal const int AllMask = 0x7FFFFFFF; internal const int NoAttrNmspMask = AllMask & ~(1 << (int)XPathNodeType.Attribute) & ~(1 << (int)XPathNodeType.Namespace); internal const int TextMask = (1 << (int)XPathNodeType.Text) | (1 << (int)XPathNodeType.SignificantWhitespace) | (1 << (int)XPathNodeType.Whitespace); - internal static readonly int[] ContentKindMasks = { + internal static ReadOnlySpan ContentKindMasks => new int[] { (1 << (int) XPathNodeType.Root), // Root (1 << (int) XPathNodeType.Element), // Element 0, // Attribute (not content) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/NumberFormatter.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/NumberFormatter.cs index f2f4c9b2aa7d8..305434a95352f 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/NumberFormatter.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Runtime/NumberFormatter.cs @@ -100,9 +100,6 @@ public static void ConvertToAlphabetic(StringBuilder sb, double val, char firstC private const string RomanDigitsUC = "IIVIXXLXCCDCM"; private const string RomanDigitsLC = "iivixxlxccdcm"; - // RomanDigit = { I IV V IX X XL L XC C CD D CM M } - private static readonly int[] s_romanDigitValue = { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 }; - public static void ConvertToRoman(StringBuilder sb, double val, bool upperCase) { Debug.Assert(1 <= val && val <= MaxRomanValue); @@ -110,11 +107,14 @@ public static void ConvertToRoman(StringBuilder sb, double val, bool upperCase) int number = (int)val; string digits = upperCase ? RomanDigitsUC : RomanDigitsLC; - for (int idx = s_romanDigitValue.Length; idx-- != 0;) + // RomanDigit = { I IV V IX X XL L XC C CD D CM M } + ReadOnlySpan RomanDigitValue = new int[] { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000 }; + + for (int idx = RomanDigitValue.Length; idx-- != 0;) { - while (number >= s_romanDigitValue[idx]) + while (number >= RomanDigitValue[idx]) { - number -= s_romanDigitValue[idx]; + number -= RomanDigitValue[idx]; sb.Append(digits, idx, 1 + (idx & 1)); } } diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPath/XPathParser.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPath/XPathParser.cs index f2226a57863dd..93b1d04f2e1a2 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPath/XPathParser.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPath/XPathParser.cs @@ -360,7 +360,7 @@ private Node ParseSubExpr(int callerPrec) if (_scanner!.Kind == LexKind.Minus) { op = XPathOperator.UnaryMinus; - int opPrec = s_XPathOperatorPrecedence[(int)op]; + int opPrec = XPathOperatorPrecedence[(int)op]; _scanner.NextLex(); opnd = _builder!.Operator(op, ParseSubExpr(opPrec), default(Node)); } @@ -373,7 +373,7 @@ private Node ParseSubExpr(int callerPrec) while (true) { op = (_scanner.Kind <= LexKind.LastOperator) ? (XPathOperator)_scanner.Kind : XPathOperator.Unknown; - int opPrec = s_XPathOperatorPrecedence[(int)op]; + int opPrec = XPathOperatorPrecedence[(int)op]; if (opPrec <= callerPrec) { break; @@ -387,7 +387,7 @@ private Node ParseSubExpr(int callerPrec) return opnd; } - private static readonly int[] s_XPathOperatorPrecedence = { + private static ReadOnlySpan XPathOperatorPrecedence => new int[] { /*Unknown */ 0, /*Or */ 1, /*And */ 2, diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs index db78c6ce2501d..25b42659f9d55 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/XPathConvert.cs @@ -89,7 +89,7 @@ public static double Pred(double x) // Small powers of ten. These are all the powers of ten that have an exact // representation in IEEE double precision format. - public static readonly double[] C10toN = { + public static ReadOnlySpan C10toN => new double[] { 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09, 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22, diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/QilGenerator.cs b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/QilGenerator.cs index 2352c31d00c06..66bb1774e0dd4 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/QilGenerator.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Xsl/Xslt/QilGenerator.cs @@ -1056,7 +1056,7 @@ private QilNode CompileAvt(string source) return result; } - private static readonly char[] s_curlyBraces = { '{', '}' }; + private static ReadOnlySpan CurlyBraces => new char[] { '{', '}' }; [return: NotNullIfNotNull("avt")] private QilNode? CompileStringAvt(string? avt) @@ -1065,20 +1065,24 @@ private QilNode CompileAvt(string source) { return null; } - if (avt.IndexOfAny(s_curlyBraces) == -1) + + if (avt.AsSpan().IndexOfAny(CurlyBraces) < 0) { return _f.String(avt); } + return _f.StrConcat(CompileAvt(avt)); } private QilNode CompileTextAvt(string avt) { Debug.Assert(avt != null); - if (avt.IndexOfAny(s_curlyBraces) == -1) + + if (avt.AsSpan().IndexOfAny(CurlyBraces) == -1) { return _f.TextCtor(_f.String(avt)); } + QilNode avtParts = CompileAvt(avt); if (avtParts.NodeType == QilNodeType.Sequence) { diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobReader.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobReader.cs index ce1299e6f267b..fc0cb882da8f7 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobReader.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobReader.cs @@ -606,7 +606,9 @@ public SignatureTypeCode ReadSignatureTypeCode() public EntityHandle ReadTypeHandle() { uint value = (uint)ReadCompressedIntegerOrInvalid(); - uint tokenType = s_corEncodeTokenArray[value & 0x3]; + + ReadOnlySpan corEncodeTokenArray = new uint[] { TokenTypeIds.TypeDef, TokenTypeIds.TypeRef, TokenTypeIds.TypeSpec, 0 }; + uint tokenType = corEncodeTokenArray[(int)(value & 0x3)]; if (value == InvalidCompressedInteger || tokenType == 0) { @@ -616,8 +618,6 @@ public EntityHandle ReadTypeHandle() return new EntityHandle(tokenType | (value >> 2)); } - private static readonly uint[] s_corEncodeTokenArray = new uint[] { TokenTypeIds.TypeDef, TokenTypeIds.TypeRef, TokenTypeIds.TypeSpec, 0 }; - /// /// Reads a #Blob heap handle encoded as a compressed integer. /// diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/HashHelpers.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/HashHelpers.cs index abbea6c7cbed0..8d72d1c269bc1 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/HashHelpers.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/HashHelpers.cs @@ -20,7 +20,7 @@ internal static partial class HashHelpers // h1(key) + i*h2(key), 0 <= i < size. h2 and the size must be relatively prime. // We prefer the low computation costs of higher prime numbers over the increased // memory allocation of a fixed prime number i.e. when right sizing a HashSet. - public static readonly int[] primes = { + public static ReadOnlySpan Primes => new int[] { 3, 7, 11, 17, 23, 29, 37, 47, 59, 71, 89, 107, 131, 163, 197, 239, 293, 353, 431, 521, 631, 761, 919, 1103, 1327, 1597, 1931, 2333, 2801, 3371, 4049, 4861, 5839, 7013, 8419, 10103, 12143, 14591, 17519, 21023, 25229, 30293, 36353, 43627, 52361, 62851, 75431, 90523, 108631, 130363, 156437, @@ -47,9 +47,9 @@ public static int GetPrime(int min) if (min < 0) throw new ArgumentException(SR.Arg_HTCapacityOverflow); - for (int i = 0; i < primes.Length; i++) + for (int i = 0; i < Primes.Length; i++) { - int prime = primes[i]; + int prime = Primes[i]; if (prime >= min) return prime; } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs index 1cd472bb203f8..0b58643790a22 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs @@ -76,7 +76,7 @@ public static string ComputeArraySuffix(int rank, bool multiDim) public static string EscapeTypeNameIdentifier(this string identifier) { // Some characters in a type name need to be escaped - if (identifier.IndexOfAny(s_charsToEscape) != -1) + if (identifier.AsSpan().IndexOfAny(CharsToEscape) >= 0) { StringBuilder sbEscapedName = new StringBuilder(identifier.Length); foreach (char c in identifier) @@ -93,12 +93,12 @@ public static string EscapeTypeNameIdentifier(this string identifier) public static bool TypeNameContainsTypeParserMetacharacters(this string identifier) { - return identifier.IndexOfAny(s_charsToEscape) != -1; + return identifier.AsSpan().IndexOfAny(CharsToEscape) >= 0; } public static bool NeedsEscapingInTypeName(this char c) { - return Array.IndexOf(s_charsToEscape, c) >= 0; + return CharsToEscape.Contains(c); } public static string UnescapeTypeNameIdentifier(this string identifier) @@ -121,7 +121,7 @@ public static string UnescapeTypeNameIdentifier(this string identifier) return identifier; } - private static readonly char[] s_charsToEscape = new char[] { '\\', '[', ']', '+', '*', '&', ',' }; + private static ReadOnlySpan CharsToEscape => new char[] { '\\', '[', ']', '+', '*', '&', ',' }; /// /// For AssemblyReferences, convert "unspecified" components from the ECMA format (0xffff) to the in-memory System.Version format (0xffffffff). diff --git a/src/libraries/System.Resources.Extensions/src/System/Resources/Extensions/TypeNameComparer.cs b/src/libraries/System.Resources.Extensions/src/System/Resources/Extensions/TypeNameComparer.cs index e0f5acbc8a552..91ffbbcaf0b9a 100644 --- a/src/libraries/System.Resources.Extensions/src/System/Resources/Extensions/TypeNameComparer.cs +++ b/src/libraries/System.Resources.Extensions/src/System/Resources/Extensions/TypeNameComparer.cs @@ -20,10 +20,7 @@ internal sealed class TypeNameComparer : IEqualityComparer public static TypeNameComparer Instance { get; } = new TypeNameComparer(); // these match the set of whitespace characters allowed by the runtime's type parser - private static readonly char[] s_whiteSpaceChars = - { - ' ', '\n', '\r', '\t' - }; + private static ReadOnlySpan WhiteSpaceChars => new char[] { ' ', '\n', '\r', '\t' }; [MethodImpl(MethodImplOptions.AggressiveInlining)] private static ReadOnlySpan ReadTypeName(ReadOnlySpan assemblyQualifiedTypeName) @@ -39,7 +36,7 @@ private static ReadOnlySpan ReadAssemblySimpleName(ReadOnlySpan asse { int comma = assemblyName.IndexOf(','); - return comma == -1 ? assemblyName : assemblyName.Slice(0, comma).TrimEnd(s_whiteSpaceChars); + return comma == -1 ? assemblyName : assemblyName.Slice(0, comma).TrimEnd(WhiteSpaceChars); } private static bool IsMscorlib(ReadOnlySpan assemblyName) @@ -63,8 +60,8 @@ public bool Equals(string assemblyQualifiedTypeName1, string assemblyQualifiedTy if (ReferenceEquals(assemblyQualifiedTypeName1, assemblyQualifiedTypeName2)) return true; - ReadOnlySpan typeSpan1 = assemblyQualifiedTypeName1.AsSpan().TrimStart(s_whiteSpaceChars); - ReadOnlySpan typeSpan2 = assemblyQualifiedTypeName2.AsSpan().TrimStart(s_whiteSpaceChars); + ReadOnlySpan typeSpan1 = assemblyQualifiedTypeName1.AsSpan().TrimStart(WhiteSpaceChars); + ReadOnlySpan typeSpan2 = assemblyQualifiedTypeName2.AsSpan().TrimStart(WhiteSpaceChars); // First, compare type names ReadOnlySpan type1 = ReadTypeName(typeSpan1); @@ -73,8 +70,8 @@ public bool Equals(string assemblyQualifiedTypeName1, string assemblyQualifiedTy return false; // skip separator and whitespace - typeSpan1 = typeSpan1.Length > type1.Length ? typeSpan1.Slice(type1.Length + 1).TrimStart(s_whiteSpaceChars) : ReadOnlySpan.Empty; - typeSpan2 = typeSpan2.Length > type2.Length ? typeSpan2.Slice(type2.Length + 1).TrimStart(s_whiteSpaceChars) : ReadOnlySpan.Empty; + typeSpan1 = typeSpan1.Length > type1.Length ? typeSpan1.Slice(type1.Length + 1).TrimStart(WhiteSpaceChars) : ReadOnlySpan.Empty; + typeSpan2 = typeSpan2.Length > type2.Length ? typeSpan2.Slice(type2.Length + 1).TrimStart(WhiteSpaceChars) : ReadOnlySpan.Empty; // Now, compare assembly simple names ignoring case ReadOnlySpan simpleName1 = ReadAssemblySimpleName(typeSpan1); @@ -116,7 +113,7 @@ public bool Equals(string assemblyQualifiedTypeName1, string assemblyQualifiedTy public int GetHashCode(string assemblyQualifiedTypeName) { // non-allocating GetHashCode that hashes the type name portion of the string - ReadOnlySpan typeSpan = assemblyQualifiedTypeName.AsSpan().TrimStart(s_whiteSpaceChars); + ReadOnlySpan typeSpan = assemblyQualifiedTypeName.AsSpan().TrimStart(WhiteSpaceChars); ReadOnlySpan typeName = ReadTypeName(typeSpan); int hashCode = 0; diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs index 2d7395e2e83dd..22dfc16fa0219 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs @@ -287,7 +287,7 @@ internal static class BigNumber | NumberStyles.AllowThousands | NumberStyles.AllowExponent | NumberStyles.AllowCurrencySymbol | NumberStyles.AllowHexSpecifier); - private static readonly uint[] s_uint32PowersOfTen = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; + private static ReadOnlySpan UInt32PowersOfTen => new uint[] { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; private struct BigNumberBuffer { @@ -522,7 +522,7 @@ private static bool NumberToBigInteger(ref BigNumberBuffer number, out BigIntege if (partialDigitCount > 0) { - MultiplyAdd(ref currentBuffer, s_uint32PowersOfTen[partialDigitCount], partialValue); + MultiplyAdd(ref currentBuffer, UInt32PowersOfTen[partialDigitCount], partialValue); } int trailingZeroCount = numberScale - totalDigitCount; @@ -535,7 +535,7 @@ private static bool NumberToBigInteger(ref BigNumberBuffer number, out BigIntege if (trailingZeroCount > 0) { - MultiplyAdd(ref currentBuffer, s_uint32PowersOfTen[trailingZeroCount], 0); + MultiplyAdd(ref currentBuffer, UInt32PowersOfTen[trailingZeroCount], 0); } int sign; diff --git a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs index fccdff3feb81a..cad3c5cb45b6e 100644 --- a/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs +++ b/src/libraries/System.Security.Cryptography.Algorithms/src/Internal/Cryptography/SHAHashProvider.Browser.cs @@ -247,7 +247,7 @@ public override byte[] HashFinal() return hash; } - private static readonly uint[] _K = { + private static ReadOnlySpan _K => new uint[] { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, @@ -525,7 +525,7 @@ public override byte[] HashFinal() return hash; } - private static readonly ulong[] _K = { + private static ReadOnlySpan _K => new ulong[] { 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, @@ -813,7 +813,7 @@ public override byte[] HashFinal() return hash; } - private static readonly ulong[] _K = { + private static ReadOnlySpan _K => new ulong[] { 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, diff --git a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.cs b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.cs index d68964a48f541..41e22ed5fd35f 100644 --- a/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.cs +++ b/src/libraries/System.Security.Cryptography.X509Certificates/src/Internal/Cryptography/Pal.Unix/X500NameEncoder.cs @@ -15,7 +15,7 @@ internal static partial class X500NameEncoder { private const string OidTagPrefix = "OID."; - private static readonly char[] s_quoteNeedingChars = + private static ReadOnlySpan QuoteNeedingChars => { ',', '+', @@ -134,22 +134,18 @@ internal static byte[] X500DistinguishedNameEncode( return writer.Encode(); } - private static bool NeedsQuoting(string rdnValue) + private static bool NeedsQuoting(ReadOnlySpan rdnValue) { - if (string.IsNullOrEmpty(rdnValue)) + if (rdnValue.IsEmpty || + IsQuotableWhitespace(rdnValue[0]) || + IsQuotableWhitespace(rdnValue[^1])) { return true; } - if (IsQuotableWhitespace(rdnValue[0]) || - IsQuotableWhitespace(rdnValue[rdnValue.Length - 1])) - { - return true; - } - - int index = rdnValue.IndexOfAny(s_quoteNeedingChars); + int index = rdnValue.IndexOfAny(QuoteNeedingChars); - return index != -1; + return index >= 0; } private static bool IsQuotableWhitespace(char c) diff --git a/src/libraries/System.Text.Encoding.CodePages/src/Data/Tools/EncodingDataGenerator.cs b/src/libraries/System.Text.Encoding.CodePages/src/Data/Tools/EncodingDataGenerator.cs index 4bce132659d53..9b55cee929fc4 100644 --- a/src/libraries/System.Text.Encoding.CodePages/src/Data/Tools/EncodingDataGenerator.cs +++ b/src/libraries/System.Text.Encoding.CodePages/src/Data/Tools/EncodingDataGenerator.cs @@ -319,13 +319,13 @@ internal static partial class {3} // Ordered by alphabetized IANA name private const string EncodingNames = @" - // s_encodingNames is the concatenation of all supported IANA names for each codepage. + // EncodingNames is the concatenation of all supported IANA names for each codepage. // This is done rather than using a large readonly array of strings to avoid // generating a large amount of code in the static constructor. - // Using indices from s_encodingNamesIndices, we binary search this string when mapping + // Using indices from EncodingNamesIndices, we binary search this string when mapping // an encoding name to a codepage. Note that these names are all lowercase and are // sorted alphabetically. - private const string s_encodingNames =| + private const string EncodingNames =| ""{0}"" + // {1:D}| """"; "; @@ -338,10 +338,10 @@ internal static partial class {3} // Ordered by alphabetized IANA name private const string EncodingNameIndices = @" - // s_encodingNameIndices contains the start index of every encoding name in the string - // s_encodingNames. We infer the length of each string by looking at the start index + // EncodingNameIndices contains the start index of every encoding name in the string + // EncodingNames. We infer the length of each string by looking at the start index // of the next string. - private static readonly int[] s_encodingNameIndices = new int[] + private static ReadOnlySpan EncodingNameIndices => new int[] { 0|, // {0} ({1:D}) {2:D}| @@ -354,11 +354,11 @@ internal static partial class {3} // Ordered by alphabetized IANA name private const string CodePagesByName = @" - // s_codePagesByName contains the list of supported codepages which match the encoding - // names listed in s_encodingNames. The way mapping works is we binary search - // s_encodingNames using s_encodingNamesIndices until we find a match for a given name. - // The index of the entry in s_encodingNamesIndices will be the index of codepage in s_codePagesByName. - private static readonly ushort[] s_codePagesByName = new ushort[] + // CodePagesByName contains the list of supported codepages which match the encoding + // names listed in EncodingNames. The way mapping works is we binary search + // EncodingNames using EncodingNamesIndices until we find a match for a given name. + // The index of the entry in EncodingNamesIndices will be the index of codepage in CodePagesByName. + private static ReadOnlySpan CodePagesByName => new ushort[] {| {0:D}, // {1}| }; @@ -372,11 +372,11 @@ internal static partial class {3} @" // When retrieving the value for System.Text.Encoding.WebName or // System.Text.Encoding.EncodingName given System.Text.Encoding.CodePage, - // we perform a linear search on s_mappedCodePages to find the index of the + // we perform a linear search on MappedCodePages to find the index of the // given codepage. This is used to index WebNameIndices to get the start // index of the web name in the string WebNames, and to index - // s_englishNameIndices to get the start of the English name in s_englishNames. - private static readonly ushort[] s_mappedCodePages = new ushort[] + // EnglishNameIndices to get the start of the English name in EnglishNames. + private static readonly ReadOnlySpan MappedCodePages => new ushort[] {| {0:D}, // {1}| }; @@ -388,12 +388,12 @@ internal static partial class {3} // Ordered by codepage private const string WebNames = @" - // s_webNames is a concatenation of the default encoding names + // WebNames is a concatenation of the default encoding names // for each code page. It is used in retrieving the value for // System.Text.Encoding.WebName given System.Text.Encoding.CodePage. // This is done rather than using a large readonly array of strings to avoid // generating a large amount of code in the static constructor. - private const string s_webNames =| + private const string WebNames =| ""{0}"" + // {1:D}| """"; "; @@ -406,10 +406,10 @@ internal static partial class {3} // Ordered by codepage private const string WebNameIndices = @" - // s_webNameIndices contains the start index of each code page's default - // web name in the string s_webNames. It is indexed by an index into - // s_mappedCodePages. - private static readonly int[] s_webNameIndices = new int[] + // WebNameIndices contains the start index of each code page's default + // web name in the string WebNames. It is indexed by an index into + // MappedCodePages. + private static ReadOnlySpan WebNameIndices => new int[] { 0|, // {0} ({1:D}) {2:D}| @@ -422,12 +422,12 @@ internal static partial class {3} // Ordered by codepage private const string EnglishNames = @" - // s_englishNames is the concatenation of the English names for each codepage. + // EnglishNames is the concatenation of the English names for each codepage. // It is used in retrieving the value for System.Text.Encoding.EncodingName // given System.Text.Encoding.CodePage. // This is done rather than using a large readonly array of strings to avoid // generating a large amount of code in the static constructor. - private const string s_englishNames =| + private const string EnglishNames =| ""{0}"" + // {1:D}| """"; "; @@ -440,9 +440,9 @@ internal static partial class {3} // Ordered by codepage private const string EnglishNameIndices = @" - // s_englishNameIndices contains the start index of each code page's English - // name in the string s_englishNames. It is indexed by an index into s_mappedCodePages. - private static readonly int[] s_englishNameIndices = new int[] + // EnglishNameIndices contains the start index of each code page's English + // name in the string EnglishNames. It is indexed by an index into MappedCodePages. + private static ReadOnlySpan EnglishNameIndices => new int[] { 0|, // {0} ({1:D}) {2:D}| diff --git a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingTable.Data.cs b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingTable.Data.cs index 9382494e564aa..9bacc395b590f 100644 --- a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingTable.Data.cs +++ b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingTable.Data.cs @@ -388,7 +388,7 @@ internal static partial class EncodingTable // s_encodingNameIndices contains the start index of every encoding name in the string // s_encodingNames. We infer the length of each string by looking at the start index // of the next string. - private static readonly int[] s_encodingNameIndices = new int[] + private static ReadOnlySpan EncodingNameIndices => new int[] { 0, // 437 (437) 3, // arabic (28596) @@ -761,7 +761,7 @@ internal static partial class EncodingTable // names listed in s_encodingNames. The way mapping works is we binary search // s_encodingNames using s_encodingNamesIndices until we find a match for a given name. // The index of the entry in s_encodingNamesIndices will be the index of codepage in s_codePagesByName. - private static readonly ushort[] s_codePagesByName = new ushort[] + private static ReadOnlySpan CodePagesByName => new ushort[] { 437, // 437 28596, // arabic @@ -1135,7 +1135,7 @@ internal static partial class EncodingTable // given codepage. This is used to index WebNameIndices to get the start // index of the web name in the string WebNames, and to index // s_englishNameIndices to get the start of the English name in s_englishNames. - private static readonly ushort[] s_mappedCodePages = new ushort[] + private static ReadOnlySpan MappedCodePages => new ushort[] { 37, // ibm037 437, // ibm437 @@ -1414,7 +1414,7 @@ internal static partial class EncodingTable // s_webNameIndices contains the start index of each code page's default // web name in the string s_webNames. It is indexed by an index into // s_mappedCodePages. - private static readonly int[] s_webNameIndices = new int[] + private static ReadOnlySpan WebNameIndices => new int[] { 0, // ibm037 (37) 6, // ibm437 (437) @@ -1693,7 +1693,7 @@ internal static partial class EncodingTable // s_englishNameIndices contains the start index of each code page's English // name in the string s_englishNames. It is indexed by an index into s_mappedCodePages. - private static readonly int[] s_englishNameIndices = new int[] + private static ReadOnlySpan EnglishNameIndices => new int[] { 0, // IBM EBCDIC (US-Canada) (37) 22, // OEM United States (437) diff --git a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingTable.cs b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingTable.cs index a248a9fc7e733..66840377989be 100644 --- a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingTable.cs +++ b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/EncodingTable.cs @@ -63,12 +63,12 @@ internal static int GetCodePageFromName(string name) private static int InternalGetCodePageFromName(string name) { int left = 0; - int right = s_encodingNameIndices.Length - 2; + int right = EncodingNameIndices.Length - 2; int index; int result; - Debug.Assert(s_encodingNameIndices.Length == s_codePagesByName.Length + 1); - Debug.Assert(s_encodingNameIndices[s_encodingNameIndices.Length - 1] == s_encodingNames.Length); + Debug.Assert(EncodingNameIndices.Length == CodePagesByName.Length + 1); + Debug.Assert(EncodingNameIndices[^1] == s_encodingNames.Length); name = name.ToLowerInvariant(); @@ -78,12 +78,12 @@ private static int InternalGetCodePageFromName(string name) { index = ((right - left) / 2) + left; - Debug.Assert(index < s_encodingNameIndices.Length - 1); - result = CompareOrdinal(name, s_encodingNames, s_encodingNameIndices[index], s_encodingNameIndices[index + 1] - s_encodingNameIndices[index]); + Debug.Assert(index < EncodingNameIndices.Length - 1); + result = CompareOrdinal(name, s_encodingNames, EncodingNameIndices[index], EncodingNameIndices[index + 1] - EncodingNameIndices[index]); if (result == 0) { //We found the item, return the associated codePage. - return (s_codePagesByName[index]); + return (CodePagesByName[index]); } else if (result < 0) { @@ -100,10 +100,10 @@ private static int InternalGetCodePageFromName(string name) //Walk the remaining elements (it'll be 3 or fewer). for (; left <= right; left++) { - Debug.Assert(left < s_encodingNameIndices.Length - 1); - if (CompareOrdinal(name, s_encodingNames, s_encodingNameIndices[left], s_encodingNameIndices[left + 1] - s_encodingNameIndices[left]) == 0) + Debug.Assert(left < EncodingNameIndices.Length - 1); + if (CompareOrdinal(name, s_encodingNames, EncodingNameIndices[left], EncodingNameIndices[left + 1] - EncodingNameIndices[left]) == 0) { - return (s_codePagesByName[left]); + return (CodePagesByName[left]); } } @@ -129,25 +129,25 @@ private static int CompareOrdinal(string s1, string s2, int index, int length) internal static string? GetWebNameFromCodePage(int codePage) { - return GetNameFromCodePage(codePage, s_webNames, s_webNameIndices, s_codePageToWebNameCache); + return GetNameFromCodePage(codePage, s_webNames, WebNameIndices, s_codePageToWebNameCache); } internal static string? GetEnglishNameFromCodePage(int codePage) { - return GetNameFromCodePage(codePage, s_englishNames, s_englishNameIndices, s_codePageToEnglishNameCache); + return GetNameFromCodePage(codePage, s_englishNames, EnglishNameIndices, s_codePageToEnglishNameCache); } - private static string? GetNameFromCodePage(int codePage, string names, int[] indices, Dictionary cache) + private static string? GetNameFromCodePage(int codePage, string names, ReadOnlySpan indices, Dictionary cache) { string? name; - Debug.Assert(s_mappedCodePages.Length + 1 == indices.Length); + Debug.Assert(MappedCodePages.Length + 1 == indices.Length); Debug.Assert(indices[indices.Length - 1] == names.Length); //This is a linear search, but we probably won't be doing it very often. - for (int i = 0; i < s_mappedCodePages.Length; i++) + for (int i = 0; i < MappedCodePages.Length; i++) { - if (s_mappedCodePages[i] == codePage) + if (MappedCodePages[i] == codePage) { Debug.Assert(i < indices.Length - 1); diff --git a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/ISCIIEncoding.cs b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/ISCIIEncoding.cs index 57e3e78079b59..8df7af36f8e93 100644 --- a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/ISCIIEncoding.cs +++ b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/ISCIIEncoding.cs @@ -203,7 +203,7 @@ public override unsafe int GetBytes(char* chars, int charCount, byte* bytes, int } // Its in the Unicode Indic script range - int indicInfo = s_UnicodeToIndicChar[ch - IndicBegin]; + int indicInfo = UnicodeToIndicChar[ch - IndicBegin]; byte byteIndic = (byte)indicInfo; int indicScript = (0x000f & (indicInfo >> 8)); int indicTwoBytes = (0xf000 & indicInfo); @@ -354,7 +354,7 @@ public override unsafe int GetChars(byte* bytes, int byteCount, if (currentCodePage >= CodeDevanagari && currentCodePage <= CodePunjabi) { - currentCodePageIndex = s_IndicMappingIndex[currentCodePage]; + currentCodePageIndex = IndicMappingIndex[currentCodePage]; } // Loop through our input @@ -381,7 +381,7 @@ public override unsafe int GetChars(byte* bytes, int byteCount, { // Remember the code page currentCodePage = b & 0xf; - currentCodePageIndex = s_IndicMappingIndex[currentCodePage]; + currentCodePageIndex = IndicMappingIndex[currentCodePage]; // No longer last ATR bLastATR = false; continue; @@ -395,7 +395,7 @@ public override unsafe int GetChars(byte* bytes, int byteCount, if (currentCodePage >= CodeDevanagari && currentCodePage <= CodePunjabi) { - currentCodePageIndex = s_IndicMappingIndex[currentCodePage]; + currentCodePageIndex = IndicMappingIndex[currentCodePage]; } // No longer last ATR bLastATR = false; @@ -410,7 +410,7 @@ public override unsafe int GetChars(byte* bytes, int byteCount, if (currentCodePage >= CodeDevanagari && currentCodePage <= CodePunjabi) { - currentCodePageIndex = s_IndicMappingIndex[currentCodePage]; + currentCodePageIndex = IndicMappingIndex[currentCodePage]; } // Even though we don't know how to support Roman, windows didn't add a ? so we don't either. @@ -791,7 +791,7 @@ internal override bool HasState // //////////////////////////////////////////////////////////////////////////// - private static readonly int[] s_UnicodeToIndicChar = + private static ReadOnlySpan UnicodeToIndicChar => new int[] { 0x02a1, // U+0901 : Devanagari Sign Candrabindu 0x02a2, // U+0902 : Devanagari Sign Anusvara @@ -1951,7 +1951,7 @@ internal override bool HasState // There are 0x60 characters in each table. The tables are in pairs of 2 // (1st char, 2nd char) and there are 10 tables (1 for each code page "font") //////////////////////////////////////////////////////////////////////////// - private static readonly int[] s_IndicMappingIndex = + private static ReadOnlySpan IndicMappingIndex => new int[] { -1, // 0 DEF 0X40 Default // Not a real code page -1, // 1 RMN 0X41 Roman // Transliteration not supported diff --git a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/ISO2022Encoding.cs b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/ISO2022Encoding.cs index 84e61cb5620c4..05efcdd0f4f16 100644 --- a/src/libraries/System.Text.Encoding.CodePages/src/System/Text/ISO2022Encoding.cs +++ b/src/libraries/System.Text.Encoding.CodePages/src/System/Text/ISO2022Encoding.cs @@ -56,11 +56,11 @@ internal sealed class ISO2022Encoding : DBCSCodePageEncoding // We have to load the 936 code page tables, so impersonate 936 as our base // This pretends to be other code pages as far as memory sections are concerned. - internal ISO2022Encoding(int codePage) : base(codePage, s_tableBaseCodePages[codePage % 10]) + internal ISO2022Encoding(int codePage) : base(codePage, TableBaseCodePages[codePage % 10]) { } - private static readonly int[] s_tableBaseCodePages = + private static ReadOnlySpan TableBaseCodePages => new int[] { 932, // 50220 ISO-2022-JP, No halfwidth Katakana, convert to full width 932, // 50221 ISO-2022-JP, Use escape sequence for half width Katakana @@ -400,14 +400,14 @@ private unsafe int GetBytesCP5022xJP(char* chars, int charCount, { // CodePage 50220 doesn't use halfwidth Katakana, convert to fullwidth // See if its out of range, fallback if so, throws if recursive fallback - if (bTrailByte < 0x21 || bTrailByte >= 0x21 + s_HalfToFullWidthKanaTable.Length) + if (bTrailByte < 0x21 || bTrailByte >= 0x21 + HalfToFullWidthKanaTable.Length) { buffer.Fallback(ch); continue; } // Get the full width katakana char to use. - iBytes = unchecked((ushort)(s_HalfToFullWidthKanaTable[bTrailByte - 0x21] & 0x7F7F)); + iBytes = unchecked((ushort)(HalfToFullWidthKanaTable[bTrailByte - 0x21] & 0x7F7F)); // May have to do all sorts of fun stuff for mode, go back to start convert goto StartConvert; @@ -1854,7 +1854,7 @@ internal override bool HasState } } - private static readonly ushort[] s_HalfToFullWidthKanaTable = + private static ReadOnlySpan HalfToFullWidthKanaTable => new ushort[] { 0xa1a3, // 0x8ea1 : Halfwidth Ideographic Period 0xa1d6, // 0x8ea2 : Halfwidth Opening Corner Bracket diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.Date.cs b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.Date.cs index 80d4bf1a1d3fd..ed094d392637b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.Date.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.Date.cs @@ -601,7 +601,7 @@ private static bool TryCreateDateTime(DateTimeParseData parseData, DateTimeKind Debug.Assert(parseData.Fraction >= 0 && parseData.Fraction <= JsonConstants.MaxDateTimeFraction); // All of our callers to date parse the fraction from fixed 7-digit fields so this value is trusted. - int[] days = DateTime.IsLeapYear(parseData.Year) ? s_daysToMonth366 : s_daysToMonth365; + ReadOnlySpan days = DateTime.IsLeapYear(parseData.Year) ? DaysToMonth366 : DaysToMonth365; int yearMinusOne = parseData.Year - 1; int totalDays = (yearMinusOne * 365) + (yearMinusOne / 4) - (yearMinusOne / 100) + (yearMinusOne / 400) + days[parseData.Month - 1] + parseData.Day - 1; long ticks = totalDays * TimeSpan.TicksPerDay; @@ -612,7 +612,7 @@ private static bool TryCreateDateTime(DateTimeParseData parseData, DateTimeKind return true; } - private static readonly int[] s_daysToMonth365 = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; - private static readonly int[] s_daysToMonth366 = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; + private static ReadOnlySpan DaysToMonth365 => new int[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 }; + private static ReadOnlySpan DaysToMonth366 => new int[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }; } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonObject.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonObject.cs index 2ef7853910f64..c7d38874004d0 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonObject.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonObject.cs @@ -128,7 +128,7 @@ internal override void GetPath(List path, JsonNode? child) InitializeIfRequired(); Debug.Assert(_dictionary != null); string propertyName = _dictionary.FindValue(child)!.Value.Key; - if (propertyName.IndexOfAny(ReadStack.SpecialCharacters) != -1) + if (propertyName.AsSpan().IndexOfAny(ReadStack.SpecialCharacters) != -1) { path.Add($"['{propertyName}']"); } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs index 06c09b9cf07e9..c1add0377684e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs @@ -13,7 +13,7 @@ namespace System.Text.Json [DebuggerDisplay("Path:{JsonPath()} Current: ConverterStrategy.{Current.JsonTypeInfo.PropertyInfoForTypeInfo.ConverterStrategy}, {Current.JsonTypeInfo.Type.Name}")] internal struct ReadStack { - internal static readonly char[] SpecialCharacters = { '.', ' ', '\'', '/', '"', '[', ']', '(', ')', '\t', '\n', '\r', '\f', '\b', '\\', '\u0085', '\u2028', '\u2029' }; + internal static ReadOnlySpan SpecialCharacters => new char[] { '.', ' ', '\'', '/', '"', '[', ']', '(', ')', '\t', '\n', '\r', '\f', '\b', '\\', '\u0085', '\u2028', '\u2029' }; /// /// Exposes the stackframe that is currently active. @@ -289,7 +289,7 @@ static void AppendPropertyName(StringBuilder sb, string? propertyName) { if (propertyName != null) { - if (propertyName.IndexOfAny(SpecialCharacters) != -1) + if (propertyName.AsSpan().IndexOfAny(SpecialCharacters) != -1) { sb.Append(@"['"); sb.Append(propertyName); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs index e5042d9894769..ff2fec1921b7d 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/WriteStack.cs @@ -361,7 +361,7 @@ static void AppendPropertyName(StringBuilder sb, string? propertyName) { if (propertyName != null) { - if (propertyName.IndexOfAny(ReadStack.SpecialCharacters) != -1) + if (propertyName.AsSpan().IndexOfAny(ReadStack.SpecialCharacters) != -1) { sb.Append(@"['"); sb.Append(propertyName); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Comment.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Comment.cs index a1ff7d659d7a5..b091a621c6848 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Comment.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/Utf8JsonWriter.WriteValues.Comment.cs @@ -9,7 +9,7 @@ namespace System.Text.Json { public sealed partial class Utf8JsonWriter { - private static readonly char[] s_singleLineCommentDelimiter = new char[2] { '*', '/' }; + private static ReadOnlySpan SingleLineCommentDelimiter => new char[2] { '*', '/' }; private static ReadOnlySpan SingleLineCommentDelimiterUtf8 => new byte[2] { (byte)'*', (byte)'/' }; /// @@ -42,7 +42,7 @@ public void WriteCommentValue(ReadOnlySpan value) { JsonWriterHelper.ValidateValue(value); - if (value.IndexOf(s_singleLineCommentDelimiter) != -1) + if (value.IndexOf(SingleLineCommentDelimiter) != -1) { ThrowHelper.ThrowArgumentException_InvalidCommentValue(); } diff --git a/src/libraries/System.Web.HttpUtility/src/System/Web/Util/UriUtil.cs b/src/libraries/System.Web.HttpUtility/src/System/Web/Util/UriUtil.cs index 64e88be64f5d0..3bdd66a08023f 100644 --- a/src/libraries/System.Web.HttpUtility/src/System/Web/Util/UriUtil.cs +++ b/src/libraries/System.Web.HttpUtility/src/System/Web/Util/UriUtil.cs @@ -7,14 +7,15 @@ namespace System.Web.Util { internal static class UriUtil { - private static readonly char[] s_queryFragmentSeparators = { '?', '#' }; // Just extracts the query string and fragment from the input path by splitting on the separator characters. // Doesn't perform any validation as to whether the input represents a valid URL. // Concatenating the pieces back together will form the original input string. private static void ExtractQueryAndFragment(string input, out string path, out string? queryAndFragment) { - int queryFragmentSeparatorPos = input.IndexOfAny(s_queryFragmentSeparators); + ReadOnlySpan queryFragmentSeparators = new char[] { '?', '#' }; + + int queryFragmentSeparatorPos = input.AsSpan().IndexOfAny(queryFragmentSeparators); if (queryFragmentSeparatorPos != -1) { path = input.Substring(0, queryFragmentSeparatorPos);