// smallest supported by .NET that's not really a problem.
internal partial struct Rc2CbcParameters
{
- private static readonly byte[] s_rc2EkbEncoding =
+ private static ReadOnlySpan<byte> Rc2EkbEncoding => new byte[]
{
0xbd, 0x56, 0xea, 0xf2, 0xa2, 0xf1, 0xac, 0x2a, 0xb0, 0x93, 0xd1, 0x9c, 0x1b, 0x33, 0xfd, 0xd0,
0x30, 0x04, 0xb6, 0xdc, 0x7d, 0xdf, 0x32, 0x4b, 0xf7, 0xcb, 0x45, 0x9b, 0x31, 0xbb, 0x21, 0x5a,
internal Rc2CbcParameters(ReadOnlyMemory<byte> iv, int keySize)
{
- if (keySize > byte.MaxValue)
- {
- Rc2Version = keySize;
- }
- else
- {
- Rc2Version = s_rc2EkbEncoding[keySize];
- }
+ Rc2Version = keySize > byte.MaxValue ?
+ keySize :
+ Rc2EkbEncoding[keySize];
Iv = iv;
}
- internal int GetEffectiveKeyBits()
- {
- if (Rc2Version > byte.MaxValue)
- {
- return Rc2Version;
- }
-
- return Array.IndexOf(s_rc2EkbEncoding, (byte)Rc2Version);
- }
+ internal int GetEffectiveKeyBits() =>
+ Rc2Version > byte.MaxValue ?
+ Rc2Version :
+ Rc2EkbEncoding.IndexOf((byte)Rc2Version);
}
}
/// </summary>
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'
- };
-
/// <summary>
/// Gives a hash equivalent to what Url.Normalize() gives.
/// </summary>
// Create l chars using the last 5 bits of each byte.
// Consume 3 MSB bits 5 bytes at a time.
+ ReadOnlySpan<byte> base32Chars = "abcdefghijklmnopqrstuvwxyz012345"u8;
do
{
byte b0 = (i < l) ? buff[i++] : (byte)0;
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((char)base32Chars[b0 & 0x1F]);
+ sb.Append((char)base32Chars[b1 & 0x1F]);
+ sb.Append((char)base32Chars[b2 & 0x1F]);
+ sb.Append((char)base32Chars[b3 & 0x1F]);
+ sb.Append((char)base32Chars[b4 & 0x1F]);
// Consume 3 MSB of b0, b1, MSB bits 6, 7 of b3, b4
- sb.Append(s_base32Char[(
+ sb.Append((char)base32Chars[(
((b0 & 0xE0) >> 5) |
((b3 & 0x60) >> 2))]);
- sb.Append(s_base32Char[(
+ sb.Append((char)base32Chars[(
((b1 & 0xE0) >> 5) |
((b4 & 0x60) >> 2))]);
if ((b4 & 0x80) != 0)
b2 |= 0x10;
- sb.Append(s_base32Char[b2]);
+ sb.Append((char)base32Chars[b2]);
} while (i < l);
public static readonly int SQLTicksPerHour = SQLTicksPerMinute * 60;
private static readonly int s_SQLTicksPerDay = SQLTicksPerHour * 24;
- private const long s_ticksPerSecond = TimeSpan.TicksPerMillisecond * 1000;
-
private static readonly DateTime s_SQLBaseDate = new DateTime(1900, 1, 1);
private static readonly long s_SQLBaseDateTicks = s_SQLBaseDate.Ticks;
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[] {
+ private static ReadOnlySpan<int> DaysToMonth365 => new int[] {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
- private static readonly int[] s_daysToMonth366 = new int[] {
+ private static ReadOnlySpan<int> 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);
- private static readonly TimeSpan s_maxTimeSpan = s_maxDateTime.Subtract(s_SQLBaseDate);
- private const string s_ISO8601_DateTimeFormat = "yyyy-MM-ddTHH:mm:ss.fff";
+ private static readonly TimeSpan s_minTimeSpan = new DateTime(1753, 1, 1).Subtract(s_SQLBaseDate);
+ private static readonly TimeSpan s_maxTimeSpan = DateTime.MaxValue.Subtract(s_SQLBaseDate);
+ private const string ISO8601_DateTimeFormat = "yyyy-MM-ddTHH:mm:ss.fff";
// These formats are valid styles in SQL Server (style 9, 12, 13, 14)
// but couldn't be recognized by the default parse. Needs to call
{
if (year >= s_minYear && year <= s_maxYear && month >= 1 && month <= 12)
{
- int[] days = IsLeapYear(year) ? s_daysToMonth366 : s_daysToMonth365;
+ ReadOnlySpan<int> days = IsLeapYear(year) ?
+ DaysToMonth366 :
+ DaysToMonth365;
if (day >= 1 && day <= days[month] - days[month - 1])
{
int y = year - 1;
}
else
{
- writer.WriteString(XmlConvert.ToString(Value, s_ISO8601_DateTimeFormat));
+ writer.WriteString(XmlConvert.ToString(Value, ISO8601_DateTimeFormat));
}
}
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<uint> RgulShiftBase => new uint[9] {
10,
10 * 10,
10 * 10 * 10,
#endregion
#region DecimalHelperTable
- private static readonly uint[] s_decimalHelpersLo = {
+ private static ReadOnlySpan<uint> DecimalHelpersLo => new uint[] {
0x0000000a, // precision:2, value:10
0x00000064, // precision:3, value:100
0x000003e8, // precision:4, value:1000
0x00000000, // precision:38+1, value:99999999999999999999999999999999999999+1
};
- private static readonly uint[] s_decimalHelpersMid = {
+ private static ReadOnlySpan<uint> DecimalHelpersMid => new uint[] {
0x00000000, // precision:2, value:10
0x00000000, // precision:3, value:100
0x00000000, // precision:4, value:1000
0x098a2240, // precision:38+1, value:99999999999999999999999999999999999999+1
};
- private static readonly uint[] s_decimalHelpersHi = {
+ private static ReadOnlySpan<uint> DecimalHelpersHi => new uint[] {
0x00000000, // precision:2, value:10
0x00000000, // precision:3, value:100
0x00000000, // precision:4, value:1000
0x5a86c47a, // precision:38+1, value:99999999999999999999999999999999999999+1
};
- private static readonly uint[] s_decimalHelpersHiHi = {
+ private static ReadOnlySpan<uint> DecimalHelpersHiHi => new uint[] {
0x00000000, // precision:2, value:10
0x00000000, // precision:3, value:100
0x00000000, // precision:4, value:1000
{
int tableIndex;
byte precision;
- uint[] decimalHelpers;
+ ReadOnlySpan<uint> 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;
}
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;
}
{
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);
}
{
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);
//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);
{
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);
{
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;
}
{
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;
}
}
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<uint> ColorValueTable => new uint[]
{
// "not a known color"
0,
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)
+ ReadOnlySpan<uint> colorValueTable = ColorValueTable;
+ 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);
}
return ColorKindTable[(int)color] == KnownColorKindSystem
? GetSystemColorArgb(color)
- : s_colorValueTable[(int)color];
+ : ColorValueTable[(int)color];
}
#if FEATURE_WINDOWS_SYSTEM_COLORS
{
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
}
// 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<byte> LengthBase => new byte[]
{
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
// 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<ushort> DistanceBasePosition => new ushort[]
{
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
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;
{
return false;
}
- offset = s_distanceBasePosition[_distanceCode] + bits;
+ offset = DistanceBasePosition[_distanceCode] + bits;
}
else
{
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<int> 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]
{
}
else if (index <= LastHPackStatusPseudoHeaderId)
{
- int statusCode = s_hpackStaticStatusCodeTable[index - FirstHPackStatusPseudoHeaderId];
+ int statusCode = HpackStaticStatusCodeTable[index - FirstHPackStatusPseudoHeaderId];
OnStatus(statusCode);
}
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
+using System.Globalization;
namespace System.Buffers.Text
{
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<int> days = DateTime.IsLeapYear(year) ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.DaysToMonth365;
int yearMinusOne = year - 1;
int totalDays = (yearMinusOne * 365) + (yearMinusOne / 4) - (yearMinusOne / 100) + (yearMinusOne / 400) + days[month - 1] + day - 1;
long ticks = totalDays * TimeSpan.TicksPerDay;
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 };
}
}
// Need to special case Enum because typecode will be underlying type, e.g. Int32
private static readonly Type EnumType = typeof(Enum);
- internal const string Base64Table = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
-
private const int Base64LineBreakPosition = 76;
private const int Base64VectorizationLengthThreshold = 16;
// 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)
+ // get a pointer to the base64 table to avoid unnecessary range checking
+ fixed (byte* base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="u8)
{
for (i = offset; i < calcLength; i += 3)
{
}
charcount += 4;
}
- outChars[j] = base64[(inData[i] & 0xfc) >> 2];
- outChars[j + 1] = base64[((inData[i] & 0x03) << 4) | ((inData[i + 1] & 0xf0) >> 4)];
- outChars[j + 2] = base64[((inData[i + 1] & 0x0f) << 2) | ((inData[i + 2] & 0xc0) >> 6)];
- outChars[j + 3] = base64[inData[i + 2] & 0x3f];
+ outChars[j] = (char)base64[(inData[i] & 0xfc) >> 2];
+ outChars[j + 1] = (char)base64[((inData[i] & 0x03) << 4) | ((inData[i + 1] & 0xf0) >> 4)];
+ outChars[j + 2] = (char)base64[((inData[i + 1] & 0x0f) << 2) | ((inData[i + 2] & 0xc0) >> 6)];
+ outChars[j + 3] = (char)base64[inData[i + 2] & 0x3f];
j += 4;
}
switch (lengthmod3)
{
case 2: // One character padding needed
- outChars[j] = base64[(inData[i] & 0xfc) >> 2];
- outChars[j + 1] = base64[((inData[i] & 0x03) << 4) | ((inData[i + 1] & 0xf0) >> 4)];
- outChars[j + 2] = base64[(inData[i + 1] & 0x0f) << 2];
- outChars[j + 3] = base64[64]; // Pad
+ outChars[j] = (char)base64[(inData[i] & 0xfc) >> 2];
+ outChars[j + 1] = (char)base64[((inData[i] & 0x03) << 4) | ((inData[i + 1] & 0xf0) >> 4)];
+ outChars[j + 2] = (char)base64[(inData[i + 1] & 0x0f) << 2];
+ outChars[j + 3] = (char)base64[64]; // Pad
j += 4;
break;
case 1: // Two character padding needed
- outChars[j] = base64[(inData[i] & 0xfc) >> 2];
- outChars[j + 1] = base64[(inData[i] & 0x03) << 4];
- outChars[j + 2] = base64[64]; // Pad
- outChars[j + 3] = base64[64]; // Pad
+ outChars[j] = (char)base64[(inData[i] & 0xfc) >> 2];
+ outChars[j + 1] = (char)base64[(inData[i] & 0x03) << 4];
+ outChars[j + 2] = (char)base64[64]; // Pad
+ outChars[j + 3] = (char)base64[64]; // Pad
j += 4;
break;
}
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<uint> 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;
private const ulong TicksPer6Hours = TicksPerHour * 6;
private const int March1BasedDayOfNewYear = 306; // Days between March 1 and January 1
- private static readonly uint[] s_daysToMonth365 = {
+ internal static ReadOnlySpan<uint> DaysToMonth365 => new uint[] {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
- private static readonly uint[] s_daysToMonth366 = {
+ internal static ReadOnlySpan<uint> DaysToMonth366 => new uint[] {
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
private static ReadOnlySpan<byte> DaysInMonth365 => new byte[] { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
y += q;
m -= q * 12;
if (y < 1 || y > 9999) ThrowDateArithmetic(2);
- uint[] daysTo = IsLeapYear(y) ? s_daysToMonth366 : s_daysToMonth365;
+ ReadOnlySpan<uint> daysTo = IsLeapYear(y) ? DaysToMonth366 : DaysToMonth365;
uint daysToMonth = daysTo[m - 1];
int days = (int)(daysTo[m] - daysToMonth);
if (d > days) d = days;
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);
ThrowHelper.ThrowArgumentOutOfRange_BadYearMonthDay();
}
- uint[] days = IsLeapYear(year) ? s_daysToMonth366 : s_daysToMonth365;
+ ReadOnlySpan<uint> days = IsLeapYear(year) ? DaysToMonth366 : DaysToMonth365;
if ((uint)day > days[month] - days[month - 1])
{
ThrowHelper.ThrowArgumentOutOfRange_BadYearMonthDay();
return false;
}
- uint[] days = IsLeapYear(year) ? s_daysToMonth366 : s_daysToMonth365;
+ ReadOnlySpan<uint> days = IsLeapYear(year) ? DaysToMonth366 : DaysToMonth365;
if ((uint)day > days[month] - days[month - 1])
{
return false;
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<uint> UInt32Powers10 => new uint[] {
1,
10,
100,
};
// Fast access for 10^n where n is 1-19
- private static readonly ulong[] s_ulongPowers10 = new ulong[] {
+ private static ReadOnlySpan<ulong> UInt64Powers10 => new ulong[] {
10,
100,
1000,
10000000000000000000,
};
- private static readonly double[] s_doublePowers10 = new double[] {
+ private static ReadOnlySpan<double> 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,
{
if (scale <= MaxInt32Scale)
{
- low64 = UInt32x32To64((uint)low64, s_powers10[scale]);
+ low64 = UInt32x32To64((uint)low64, UInt32Powers10[scale]);
goto AlignedAdd;
}
scale -= MaxInt32Scale;
{
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);
//
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);
{
power = TenToPowerNine;
if (scale < MaxInt32Scale)
- power = s_powers10[scale];
+ power = UInt32Powers10[scale];
tmp64 = 0;
uint* rgulNum = (uint*)&bufNum;
for (uint cur = 0; ;)
{
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;
// 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);
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;
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
}
power = -power;
if (power < 10)
{
- result.Low64 = UInt32x32To64(mant, s_powers10[power]);
+ result.Low64 = UInt32x32To64(mant, UInt32Powers10[power]);
}
else
{
//
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;
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
}
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;
// 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
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 (decimal.IsNegative(value))
dbl = -dbl;
}
HaveScale:
- power = s_powers10[curScale];
+ power = UInt32Powers10[curScale];
scale += curScale;
if (IncreaseScale(ref bufQuo, power) != 0)
}
HaveScale64:
- power = s_powers10[curScale];
+ power = UInt32Powers10[curScale];
scale += curScale;
if (IncreaseScale(ref bufQuo, power) != 0)
}
HaveScale96:
- power = s_powers10[curScale];
+ power = UInt32Powers10[curScale];
scale += curScale;
if (IncreaseScale(ref bufQuo, power) != 0)
// 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;
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;
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;
}
{
- power = s_powers10[scale];
+ power = UInt32Powers10[(int)scale];
// TODO: https://github.com/dotnet/runtime/issues/5213
uint n = d.uhi;
if (n == 0)
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 ReadOnlySpan<double> Coefficients1900to1987 => new double[] { -0.00002, 0.000297, 0.025184, -0.181133, 0.553040, -0.861938, 0.677066, -0.212591 };
+ private static ReadOnlySpan<double> 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<double> Coefficients1700to1799 => new double[] { 8.118780842, -0.005092142, 0.003336121, -0.0000266484 };
+ private static ReadOnlySpan<double> Coefficients1620to1699 => new double[] { 196.58333, -4.0675, 0.0219167 };
+ private static ReadOnlySpan<double> LambdaCoefficients => new double[] { 280.46645, 36000.76983, 0.0003032 };
+ private static ReadOnlySpan<double> AnomalyCoefficients => new double[] { 357.52910, 35999.05030, -0.0001559, -0.00000048 };
+ private static ReadOnlySpan<double> EccentricityCoefficients => new double[] { 0.016708617, -0.000042037, -0.0000001236 };
+ private static ReadOnlySpan<double> CoefficientsA => new double[] { 124.90, -1934.134, 0.002063 };
+ private static ReadOnlySpan<double> CoefficientsB => new double[] { 201.11, 72001.5377, 0.00057 };
+
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 double RadiansFromDegrees(double degree)
{
return longitude / FullCircleOfArc;
}
- private static double PolynomialSum(double[] coefficients, double indeterminate)
+ private static double PolynomialSum(ReadOnlySpan<double> coefficients, double indeterminate)
{
double sum = coefficients[0];
double indeterminateRaised = 1;
{
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
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);
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));
}
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<int> DaysToMonth365 => new int[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+ private static ReadOnlySpan<int> DaysToMonth366 => new int[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
public override CalendarAlgorithmType AlgorithmType => CalendarAlgorithmType.LunisolarCalendar;
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.
// 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
// calc the solar day of year of 1 Lunar day
bool isLeapYear = GregorianIsLeapYear(lunarYear);
- int[] days = isLeapYear ? s_daysToMonth366 : s_daysToMonth365;
+ ReadOnlySpan<int> days = isLeapYear ? DaysToMonth366 : DaysToMonth365;
solarDay = jan1Date;
private GregorianCalendarTypes _type;
- private static readonly int[] DaysToMonth365 = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
+ internal static ReadOnlySpan<int> 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 };
+ internal static ReadOnlySpan<int> DaysToMonth366 => new int[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
private static volatile Calendar? s_defaultInstance;
{
if (year >= 1 && year <= MaxYear && month >= 1 && month <= 12)
{
- int[] days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365;
+ ReadOnlySpan<int> 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;
y += (i - 11) / 12;
}
- int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365;
+ ReadOnlySpan<int> daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365;
int days = (daysArray[m] - daysArray[m - 1]);
if (d > days)
return false;
}
- int[] days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365;
+ ReadOnlySpan<int> days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365;
return day <= (days[month] - days[month - 1]);
}
//
internal int MaxYear => m_maxYear;
- internal static readonly int[] DaysToMonth365 =
- {
- 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365
- };
-
- internal static readonly int[] DaysToMonth366 =
- {
- 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366
- };
-
private readonly int m_maxYear;
private readonly int m_minYear;
private readonly Calendar m_Cal;
{
if (year >= 1 && year <= 9999 && month >= 1 && month <= 12)
{
- int[] days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365;
+ ReadOnlySpan<int> days = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.DaysToMonth365;
if (day >= 1 && (day <= days[month] - days[month - 1]))
{
int y = year - 1;
m = 12 + (i + 1) % 12;
y += (i - 11) / 12;
}
- int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? DaysToMonth366 : DaysToMonth365;
+ ReadOnlySpan<int> daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.DaysToMonth365;
int days = (daysArray[m] - daysArray[m - 1]);
if (d > days)
{
ThrowHelper.ThrowArgumentOutOfRange_Month(month);
}
- int[] days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? DaysToMonth366 : DaysToMonth365);
+ ReadOnlySpan<int> days = ((year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.DaysToMonth365);
return days[month] - days[month - 1];
}
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<int> HijriMonthDays => new int[] { 0, 30, 59, 89, 118, 148, 177, 207, 236, 266, 295, 325, 355 };
private int _hijriAdvance = int.MinValue;
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)
return (int)numDays;
}
- while ((hijriMonth <= 12) && (numDays > s_hijriMonthDays[hijriMonth - 1]))
+ while ((hijriMonth <= 12) && (numDays > HijriMonthDays[hijriMonth - 1]))
{
hijriMonth++;
}
}
// Calculate the Hijri Day.
- int hijriDay = (int)(numDays - s_hijriMonthDays[hijriMonth - 1]);
+ int hijriDay = (int)(numDays - HijriMonthDays[hijriMonth - 1]);
if (part == DatePartDay)
{
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<int> 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
Console.WriteLine("private static ReadOnlySpan<byte> 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;
// Number of days in 4 years
private const int JulianDaysPer4Years = JulianDaysPerYear * 4 + 1;
- 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
- };
-
// Gregorian Calendar 9999/12/31 = Julian Calendar 9999/10/19
// keep it as variable field for serialization compat.
internal int MaxYear = 9999;
}
bool isLeapYear = (year % 4) == 0;
- int[] days = isLeapYear ? s_daysToMonth366 : s_daysToMonth365;
+ ReadOnlySpan<int> days = isLeapYear ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.DaysToMonth365;
int monthDays = days[month] - days[month - 1];
if (day < 1 || day > monthDays)
{
// 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<int> days = leapYear ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.DaysToMonth365;
// All months have less than 32 days, so n >> 5 is a good conservative
// estimate for the month
int m = (n >> 5) + 1;
/// </summary>
internal static long DateToTicks(int year, int month, int day)
{
- int[] days = (year % 4 == 0) ? s_daysToMonth366 : s_daysToMonth365;
+ ReadOnlySpan<int> days = (year % 4 == 0) ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.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.
y += (i - 11) / 12;
}
- int[] daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? s_daysToMonth366 : s_daysToMonth365;
+ ReadOnlySpan<int> daysArray = (y % 4 == 0 && (y % 100 != 0 || y % 400 == 0)) ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.DaysToMonth365;
int days = daysArray[m] - daysArray[m - 1];
if (d > days)
{
{
CheckYearEraRange(year, era);
CheckMonthRange(month);
- int[] days = (year % 4 == 0) ? s_daysToMonth366 : s_daysToMonth365;
+ ReadOnlySpan<int> days = (year % 4 == 0) ? GregorianCalendar.DaysToMonth366 : GregorianCalendar.DaysToMonth365;
return days[month] - days[month - 1];
}
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<int> 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;
{
Debug.Assert(ordinalDay <= 366);
int index = 0;
- while (ordinalDay > s_daysToMonth[index])
+ while (ordinalDay > DaysToMonth[index])
{
index++;
}
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)
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);
CheckYearRange(year, era);
if (year == MaxCalendarYear)
{
- return s_daysToMonth[MaxCalendarMonth - 1] + MaxCalendarDay;
+ return DaysToMonth[MaxCalendarMonth - 1] + MaxCalendarDay;
}
return IsLeapYear(year, CurrentEra) ? 366 : 365;
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<double> RoundPower10Double => new double[] {
1E0, 1E1, 1E2, 1E3, 1E4, 1E5, 1E6, 1E7, 1E8,
1E9, 1E10, 1E11, 1E12, 1E13, 1E14, 1E15
};
if (Abs(value) < doubleRoundLimit)
{
- double power10 = roundPower10Double[digits];
+ double power10 = RoundPower10Double[digits];
value *= power10;
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<float> RoundPower10Single => new float[] {
1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f, 1e6f
};
if (Abs(x) < singleRoundLimit)
{
- float power10 = roundPower10Single[digits];
+ float power10 = RoundPower10Single[digits];
x *= power10;
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<uint> Pow10UInt32Table => new uint[]
{
1, // 10^0
10, // 10^1
1000000000 // 10^9
};
- private static readonly int[] s_Pow10BigNumTableIndices = new int[]
+ private static ReadOnlySpan<int> Pow10BigNumTableIndices => new int[]
{
0, // 10^8
2, // 10^16
116, // 10^1024
};
- private static readonly uint[] s_Pow10BigNumTable = new uint[]
+ private static ReadOnlySpan<uint> Pow10BigNumTable => new uint[]
{
// 10^8
1, // _length
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);
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);
{
if (exponent <= 9)
{
- Multiply(s_Pow10UInt32Table[exponent]);
+ Multiply(Pow10UInt32Table[(int)exponent]);
}
else if (!IsZero())
{
private const int MaximalTargetExponent = -32;
private const int MinimalTargetExponent = -60;
- private static readonly short[] s_CachedPowersBinaryExponent = new short[]
+ private static ReadOnlySpan<short> CachedPowersBinaryExponent => new short[]
{
-1220,
-1193,
1066,
};
- private static readonly short[] s_CachedPowersDecimalExponent = new short[]
+ private static ReadOnlySpan<short> CachedPowersDecimalExponent => new short[]
{
CachedPowersMinDecimalExponent,
-340,
CachedPowersPowerMaxDecimalExponent,
};
- private static readonly ulong[] s_CachedPowersSignificand = new ulong[]
+ private static ReadOnlySpan<ulong> CachedPowersSignificand => new ulong[]
{
0xFA8FD5A0081C0288,
0xBAAEE17FA23EBF76,
0xAF87023B9BF0EE6B,
};
- private static readonly uint[] s_SmallPowersOfTen = new uint[]
+ private static ReadOnlySpan<uint> SmallPowersOfTen => new uint[]
{
1, // 10^0
10, // 10^1
// 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;
// If requestedDigits >= 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;
// 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.
/// Normalized 128 bits values for powers of 5^q for q in range [-342, 308]
/// stored as 2 64-bits integers for convenience
/// </summary>
- private static readonly ulong[] s_Pow5128Table = {
+ private static ReadOnlySpan<ulong> Pow5128Table => new ulong[] {
0xeef453d6923bd65a, 0x113faa2906a13b3f,
0x9558b4661b6565f8, 0x4ac7ca59a424c507,
0xbaaee17fa23ebf76, 0x5d79bcf00d2df649,
int index = 2 * (int)(q - -342);
// For small values of q, e.g., q in [0,27], the answer is always exact because
// Math.BigMul gives the exact answer.
- ulong high = Math.BigMul(w, s_Pow5128Table[index], out ulong low);
+ ulong high = Math.BigMul(w, Pow5128Table[index], out ulong low);
ulong precisionMask = (bitPrecision < 64) ? (0xFFFFFFFFFFFFFFFFUL >> bitPrecision) : 0xFFFFFFFFFFFFFFFFUL;
if ((high & precisionMask) == precisionMask)
{
// could further guard with (lower + w < lower)
// regarding the second product, we only need secondproduct.high, but our expectation is that the compiler will optimize this extra work away if needed.
- ulong high2 = Math.BigMul(w, s_Pow5128Table[index + 1], out ulong _);
+ ulong high2 = Math.BigMul(w, Pow5128Table[index + 1], out ulong _);
low += high2;
if (high2 > low)
{
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<char> 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
{
// 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
// 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)
{
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];
}
}
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
"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<int> EncodingNameIndices => new int[]
{
0, // ansi_x3.4-1968 (20127)
14, // ansi_x3.4-1986 (20127)
};
//
- // 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<ushort> CodePagesByName => new ushort[]
{
20127, // ansi_x3.4-1968
20127, // ansi_x3.4-1986
//
// 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<ushort> MappedCodePages => new ushort[]
{
1200, // utf-16
1201, // utf-16be
};
//
- // 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<int> UiFamilyCodePages => new int[]
{
1200,
1200,
};
//
- // 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
"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<int> WebNameIndices => new int[]
{
0, // utf-16 (1200)
6, // utf-16be (1201)
};
//
- // 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
"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<int> EnglishNameIndices => new int[]
{
0, // Unicode (1200)
7, // Unicode (Big-Endian) (1201)
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<uint> Flags => new uint[]
{
MIMECONTF_SAVABLE_BROWSER,
0,
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<char> invariantName = name.ToLowerInvariant().AsSpan();
{
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)
{
// 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];
}
}
// 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<ushort> 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<int> webNameIndices = WebNameIndices;
int arrayEncodingInfoIdx = 0;
for (int i = 0; i < mappedCodePages.Length; i++)
internal static EncodingInfo[] GetEncodings(Dictionary<int, EncodingInfo> encodingInfoList)
{
Debug.Assert(encodingInfoList != null);
- ushort[] mappedCodePages = s_mappedCodePages;
- string webNames = s_webNames;
- int[] webNameIndices = s_webNameIndices;
+ ReadOnlySpan<ushort> mappedCodePages = MappedCodePages;
+ string webNames = WebNames;
+ ReadOnlySpan<int> webNameIndices = WebNameIndices;
for (int i = 0; i < mappedCodePages.Length; i++)
{
{
if (s_codePageToCodePageData == null)
{
- Interlocked.CompareExchange<CodePageDataItem?[]?>(ref s_codePageToCodePageData, new CodePageDataItem[s_mappedCodePages.Length], null);
+ Interlocked.CompareExchange<CodePageDataItem?[]?>(ref s_codePageToCodePageData, new CodePageDataItem[MappedCodePages.Length], null);
}
- // Keep in sync with s_mappedCodePages
+ // Keep in sync with MappedCodePages
int index;
switch (codePage)
{
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);
}
{
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;
}
{
public class UTF7Encoding : Encoding
{
- private const string base64Chars =
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- // 0123456789111111111122222222223333333333444444444455555555556666
- // 012345678901234567890123456789012345678901234567890123
-
- // These are the characters that can be directly encoded in UTF7.
- private const string directChars =
- "\t\n\r '(),-./0123456789:?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
-
- // These are the characters that can be optionally directly encoded in UTF7.
- private const string optionalChars =
- "!\"#$%&*;<=>@[]^_`{|}";
-
#pragma warning disable SYSLIB0001
// Used by Encoding.UTF7 for lazy initialization
// The initialization code will not be run until a static member of the class is referenced
private void MakeTables()
{
// Build our tables
- _base64Bytes = new byte[64];
- for (int i = 0; i < 64; i++) _base64Bytes[i] = (byte)base64Chars[i];
+
+ _base64Bytes = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"u8.ToArray();
+ Debug.Assert(_base64Bytes.Length == 64);
+
_base64Values = new sbyte[128];
for (int i = 0; i < 128; i++) _base64Values[i] = -1;
for (int i = 0; i < 64; i++) _base64Values[_base64Bytes[i]] = (sbyte)i;
+
+ // These are the characters that can be directly encoded in UTF7.
+ ReadOnlySpan<byte> directChars = "\t\n\r '(),-./0123456789:?ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"u8;
_directEncode = new bool[128];
- int count = directChars.Length;
- for (int i = 0; i < count; i++)
+ foreach (byte c in directChars)
{
- _directEncode[directChars[i]] = true;
+ _directEncode[c] = true;
}
if (_allowOptionals)
{
- count = optionalChars.Length;
- for (int i = 0; i < count; i++)
+ // These are the characters that can be optionally directly encoded in UTF7.
+ ReadOnlySpan<byte> optionalChars = "!\"#$%&*;<=>@[]^_`{|}"u8;
+
+ foreach (byte c in optionalChars)
{
- _directEncode[optionalChars[i]] = true;
+ _directEncode[c] = true;
}
}
}
index++;
} while ((uint)index < (uint)date.Length && char.IsAsciiDigit(date[index]));
- int[] days = GregorianCalendarHelper.DaysToMonth365;
+ ReadOnlySpan<int> days = GregorianCalendar.DaysToMonth365;
if (julianDay == 0 || julianDay > days[days.Length - 1])
{
private static int GetPrime(int min)
{
- for (int i = 0; i < primes.Length; i++)
+ ReadOnlySpan<int> primes = new int[]
{
- int prime = primes[i];
- if (prime >= min) return prime;
+ 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.
+ };
+
+ foreach (int prime in primes)
+ {
+ if (prime >= min)
+ {
+ return prime;
+ }
}
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.
- };
}
}
private const int guidLength = 16;
private const int uuidLength = 45;
- private static readonly short[] s_char2val = new short[256]
+ private static ReadOnlySpan<short> Char2val => new short[256]
{
/* 0-15 */
0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100, 0x100,
int i = 0;
int j = 0;
- fixed (short* ps = &s_char2val[0])
+ fixed (short* ps = &Char2val[0])
{
short* _char2val = ps;
(1 << (int)XmlNodeType.Element) |
(1 << (int)XmlNodeType.ProcessingInstruction) |
(1 << (int)XmlNodeType.Comment);
- private static readonly int[] s_ElementContentMasks = {
+ private static ReadOnlySpan<int> ElementContentMasks => new int[] {
0, // Root
(1 << (int)XmlNodeType.Element), // Element
0, // Attribute
private static int GetElementContentMask(XPathNodeType type)
{
- return s_ElementContentMasks[(int)type];
+ return ElementContentMasks[(int)type];
}
private static XAttribute? GetFirstNamespaceDeclarationGlobal(XElement e)
private int _bits;
private int _bitsFilled;
- private const string CharsBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
private static readonly byte[] s_mapBase64 = ConstructMapBase64();
private const int MaxValidChar = (int)'z';
private const byte Invalid = unchecked((byte)-1);
private static byte[] ConstructMapBase64()
{
byte[] mapBase64 = new byte[MaxValidChar + 1];
- for (int i = 0; i < mapBase64.Length; i++)
- {
- mapBase64[i] = Invalid;
- }
- for (int i = 0; i < CharsBase64.Length; i++)
+ Array.Fill(mapBase64, Invalid);
+
+ ReadOnlySpan<byte> charsBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"u8;
+ for (int i = 0; i < charsBase64.Length; i++)
{
- mapBase64[(int)CharsBase64[i]] = (byte)i;
+ mapBase64[charsBase64[i]] = (byte)i;
}
+
return mapBase64;
}
//
// for 'block' and 'final' attribute values
//
- private static readonly int[] s_derivationMethodValues = {
+ private static ReadOnlySpan<int> DerivationMethodValues => new int[] {
(int)XmlSchemaDerivationMethod.Substitution,
(int)XmlSchemaDerivationMethod.Extension,
(int)XmlSchemaDerivationMethod.Restriction,
{
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;
}
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;
// Number of days in 400 years
private const int DaysPer400Years = DaysPer100Years * 4 + 1; // 146097
- private static readonly int[] DaysToMonth365 = {
+ private static ReadOnlySpan<int> DaysToMonth365 => new int[] {
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
- private static readonly int[] DaysToMonth366 = {
+ private static ReadOnlySpan<int> DaysToMonth366 => new int[] {
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
/// <summary>
/// </summary>
public int Fraction
{
- get { return (int)(_dt.Ticks % ticksToFractionDivisor); }
+ get { return (int)(_dt.Ticks % TicksToFractionDivisor); }
}
/// <summary>
// 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<int> 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;
int fraction = Fraction;
if (fraction != 0)
{
- int fractionDigits = maxFractionDigits;
+ int fractionDigits = MaxFractionDigits;
while (fraction % 10 == 0)
{
fractionDigits--;
return false;
}
- private static readonly int[] s_power10 = new int[maxFractionDigits] { -1, 10, 100, 1000, 10000, 100000, 1000000 };
+ private static ReadOnlySpan<int> Power10 => new int[MaxFractionDigits] { -1, 10, 100, 1000, 10000, 100000, 1000000 };
private bool ParseTime(ref int start)
{
if (
{ // 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)
{
}
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
{
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);
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<int> 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));
}
}
// 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<double> 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,
| 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<uint> UInt32PowersOfTen => new uint[] { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
+
internal enum ParsingStatus
{
OK,
if (partialDigitCount > 0)
{
- MultiplyAdd(ref currentBuffer, s_uint32PowersOfTen[partialDigitCount], partialValue);
+ MultiplyAdd(ref currentBuffer, UInt32PowersOfTen[partialDigitCount], partialValue);
}
result = NumberBufferToBigInteger(currentBuffer, number.sign);
if (trailingZeroCount > 0)
{
- MultiplyAdd(ref currentBuffer, s_uint32PowersOfTen[trailingZeroCount], 0);
+ MultiplyAdd(ref currentBuffer, UInt32PowersOfTen[trailingZeroCount], 0);
}
int sign;
return hash;
}
- private static readonly uint[] _K = {
+ private static ReadOnlySpan<uint> _K => new uint[] {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
return hash;
}
- private static readonly ulong[] _K = {
+ private static ReadOnlySpan<ulong> _K => new ulong[] {
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
return hash;
}
- private static readonly ulong[] _K = {
+ private static ReadOnlySpan<ulong> _K => new ulong[] {
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
// 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}|
"""";
";
// 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<int> EncodingNameIndices => new int[]
{
0|, // {0} ({1:D})
{2:D}|
// 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<ushort> CodePagesByName => new ushort[]
{|
{0:D}, // {1}|
};
// we perform a linear search on s_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 ReadOnlySpan<ushort> s_mappedCodePages => new ushort[]
{|
{0:D}, // {1}|
};
// 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}|
"""";
";
// 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
+ // WebNameIndices contains the start index of each code page's default
+ // web name in the string WebNames. It is indexed by an index into
// s_mappedCodePages.
- private static readonly int[] s_webNameIndices = new int[]
+ private static ReadOnlySpan<int> WebNameIndices => new int[]
{
0|, // {0} ({1:D})
{2:D}|
// 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}|
"""";
";
// 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 s_mappedCodePages.
+ private static ReadOnlySpan<int> EnglishNameIndices => new int[]
{
0|, // {0} ({1:D})
{2:D}|
// Using indices from s_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 =
"437" + // 437
"arabic" + // 28596
"asmo-708" + // 708
// 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<int> EncodingNameIndices => new int[]
{
0, // 437 (437)
3, // arabic (28596)
// 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<ushort> CodePagesByName => new ushort[]
{
437, // 437
28596, // arabic
// 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<ushort> MappedCodePages => new ushort[]
{
37, // ibm037
437, // ibm437
// 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 =
"ibm037" + // 37
"ibm437" + // 437
"ibm500" + // 500
// 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<int> WebNameIndices => new int[]
{
0, // ibm037 (37)
6, // ibm437 (437)
// 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 =
"IBM EBCDIC (US-Canada)" + // 37
"OEM United States" + // 437
"IBM EBCDIC (International)" + // 500
// 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<int> EnglishNameIndices => new int[]
{
0, // IBM EBCDIC (US-Canada) (37)
22, // OEM United States (437)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
-using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
private static int InternalGetCodePageFromName(string name)
{
+ ReadOnlySpan<int> encodingNameIndices = EncodingNameIndices;
+
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[encodingNameIndices.Length - 1] == EncodingNames.Length);
name = name.ToLowerInvariant();
{
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, 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)
{
//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, EncodingNames, encodingNameIndices[left], encodingNameIndices[left + 1] - encodingNameIndices[left]) == 0)
{
- return (s_codePagesByName[left]);
+ return CodePagesByName[left];
}
}
internal static string? GetWebNameFromCodePage(int codePage)
{
- return GetNameFromCodePage(codePage, s_webNames, s_webNameIndices, s_codePageToWebNameCache);
+ return GetNameFromCodePage(codePage, WebNames, WebNameIndices, s_codePageToWebNameCache);
}
internal static string? GetEnglishNameFromCodePage(int codePage)
{
- return GetNameFromCodePage(codePage, s_englishNames, s_englishNameIndices, s_codePageToEnglishNameCache);
+ return GetNameFromCodePage(codePage, EnglishNames, EnglishNameIndices, s_codePageToEnglishNameCache);
}
- private static string? GetNameFromCodePage(int codePage, string names, int[] indices, Dictionary<int, string> cache)
+ private static string? GetNameFromCodePage(int codePage, string names, ReadOnlySpan<int> indices, Dictionary<int, string> 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);
if ((uint)codePage > ushort.MaxValue)
}
//This is a linear search, but we probably won't be doing it very often.
- int i = Array.IndexOf(s_mappedCodePages, (ushort)codePage);
+ int i = MappedCodePages.IndexOf((ushort)codePage);
if (i < 0)
{
// Didn't find it.
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<int> 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;
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<int> DaysToMonth365 => new int[] { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
+ private static ReadOnlySpan<int> DaysToMonth366 => new int[] { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
}
}
// PLEASE DON'T MODIFY BY HAND
// IF YOU NEED TO UPDATE UNICODE VERSION FOLLOW THE GUIDE AT src/libraries/System.Private.CoreLib/Tools/GenUnicodeProp/Updating-Unicode-Versions.md
- private static char[] EquivalenceCasingValues { get; } = new char[2336]
+ private static ReadOnlySpan<char> EquivalenceCasingValues => new char[2336]
{
'\u0041', '\u0061', '\u0042', '\u0062', '\u0043', '\u0063', '\u0044', '\u0064', '\u0045', '\u0065', '\u0046', '\u0066', '\u0047', '\u0067', '\u0048', '\u0068',
'\u0049', '\u0069', '\u004A', '\u006A', '\u004B', '\u006B', '\u212A', '\u004C', '\u006C', '\u004D', '\u006D', '\u004E', '\u006E', '\u004F', '\u006F', '\u0050',
'\uFF33', '\uFF53', '\uFF34', '\uFF54', '\uFF35', '\uFF55', '\uFF36', '\uFF56', '\uFF37', '\uFF57', '\uFF38', '\uFF58', '\uFF39', '\uFF59', '\uFF3A', '\uFF5A'
};
- private static ushort[] EquivalenceFirstLevelLookup { get; } = new ushort[64]
+ private static ReadOnlySpan<ushort> EquivalenceFirstLevelLookup => new ushort[64]
{
0x0000, 0x0400, 0xffff, 0xffff, 0x0800, 0xffff, 0xffff, 0x0c00, 0x1000, 0x1400, 0xffff, 0x1800, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x2400
};
- private static ushort[] EquivalenceCasingMap { get; } = new ushort[10240]
+ private static ReadOnlySpan<ushort> EquivalenceCasingMap => new ushort[10240]
{
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
{
public const int CharactersPerRange = 1024;
- private static readonly char[] s_specialCasingSetBehaviors = new char[5]
- {
- 'I', 'i', '\u0130', 'I', '\u0131'
- };
-
/// <summary>
/// Performs a fast lookup which determines if a character is involved in case conversion, as well as
/// returns the characters that should be considered equivalent in case it does participate in case conversion.
equivalences = c switch
{
// Invariant mappings
- 'i' or 'I' when mappingBehavior is RegexCaseBehavior.Invariant => s_specialCasingSetBehaviors.AsSpan(0, 2), // 'I' and 'i'
+ 'i' or 'I' when mappingBehavior is RegexCaseBehavior.Invariant => "Ii".AsSpan(),
// Non-Turkish mappings
- 'i' or 'I' or '\u0130' when mappingBehavior is RegexCaseBehavior.NonTurkish => s_specialCasingSetBehaviors.AsSpan(0, 3), // 'I', 'i', and '\u0130'
+ 'i' or 'I' or '\u0130' when mappingBehavior is RegexCaseBehavior.NonTurkish => "Ii\u0130".AsSpan(),
// Turkish mappings
- 'I' or '\u0131' when mappingBehavior is RegexCaseBehavior.Turkish => s_specialCasingSetBehaviors.AsSpan(3, 2), // 'I' and '\u0131'
- 'i' or '\u0130' when mappingBehavior is RegexCaseBehavior.Turkish => s_specialCasingSetBehaviors.AsSpan(1, 2), // 'i' and '\u0130'
+ 'I' or '\u0131' when mappingBehavior is RegexCaseBehavior.Turkish => "I\u0131".AsSpan(),
+ 'i' or '\u0130' when mappingBehavior is RegexCaseBehavior.Turkish => "i\u0130".AsSpan(),
// Default
_ => default
byte count = (byte)((mappingValue >> 13) & 0b111);
ushort index3 = (ushort)(mappingValue & 0x1FFF);
- equivalences = EquivalenceCasingValues.AsSpan(index3, count);
+ equivalences = EquivalenceCasingValues.Slice(index3, count);
return true;
}
void EmitFirstLevelLookupTable(StreamWriter writer)
{
- var firstLevelLookupTable = FlattenFirstLevelLookupTable();
- writer.Write(" private static ushort[] EquivalenceFirstLevelLookup { get; } = new ushort[" + firstLevelLookupTable.Count + "]\n {\n");
+ List<ushort> firstLevelLookupTable = FlattenFirstLevelLookupTable();
+
+ writer.Write($" private static ReadOnlySpan<ushort> EquivalenceFirstLevelLookup => new ushort[{firstLevelLookupTable.Count}]");
+ writer.Write(" {");
writer.Write(" 0x{0:x4}", firstLevelLookupTable[0]);
for (var i = 1; i < firstLevelLookupTable.Count; i++)
void EmitMapArray(StreamWriter writer)
{
- var flattenedMap = FlattenMapDictionary();
- writer.Write(" private static ushort[] EquivalenceCasingMap { get; } = new ushort[" + flattenedMap.Count + "]\n {\n");
+ List<ushort> flattenedMap = FlattenMapDictionary();
+
+ writer.Write($" private static ReadOnlySpan<ushort> EquivalenceCasingMap => new ushort[{flattenedMap.Count}]");
+ writer.Write(" {");
writer.Write(" 0x{0:x4}", flattenedMap[0]);
for (var i = 1; i < flattenedMap.Count; i++)
void EmitValuesArray(StreamWriter writer)
{
- var flattenedValues = FlattenValuesDictionary();
- writer.Write(" private static char[] EquivalenceCasingValues { get; } = new char[" + flattenedValues.Count + "]\n {\n");
+ List<ushort> flattenedValues = FlattenValuesDictionary();
+
+ writer.Write($" private static ReadOnlySpan<char> EquivalenceCasingValues => new char[{flattenedValues.Count}]");
+ writer.Write(" {");
+
+ writer.Write(" private static ReadOnlySpan<char> EquivalenceCasingValues => new char[" + flattenedValues.Count + "]\n {\n");
writer.Write(" \'\\u{0:X4}\'", flattenedValues[0]);
for (var i = 1; i < flattenedValues.Count; i++)